Initial Commit
This commit is contained in:
165
api/.dockerignore
Normal file
165
api/.dockerignore
Normal file
@@ -0,0 +1,165 @@
|
||||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
# Database
|
||||
*.db
|
||||
dashboard_database.db
|
||||
|
||||
# Ignore files
|
||||
.dockerignore
|
||||
.gitignore
|
||||
|
||||
# Docker
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
157
api/.gitignore
vendored
Normal file
157
api/.gitignore
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
# Database
|
||||
*.db
|
||||
dashboard_database.db
|
||||
31
api/Dockerfile
Normal file
31
api/Dockerfile
Normal file
@@ -0,0 +1,31 @@
|
||||
# syntax = docker/dockerfile:1
|
||||
|
||||
FROM python:3.11.5-slim as builder
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y libpq-dev gcc
|
||||
|
||||
RUN python -m venv /opt/venv
|
||||
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip3 install -r requirements.txt
|
||||
|
||||
FROM python:3.11.5-slim
|
||||
|
||||
# Set working dir
|
||||
COPY --from=builder /opt/venv /opt/venv
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE 1
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
COPY . /usr/src/virt.dashboard
|
||||
|
||||
WORKDIR /usr/src/virt.dashboard/app
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
CMD [ "waitress-serve", "--port=5000", "wsgi:app" ]
|
||||
0
api/app/__init__.py
Normal file
0
api/app/__init__.py
Normal file
9
api/app/custom_swagger.json
Normal file
9
api/app/custom_swagger.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "Virt.Dashboard API",
|
||||
"description": "Backend API for Virt.Dashboard",
|
||||
"termsOfService": "",
|
||||
"version": "1.1.2"
|
||||
}
|
||||
}
|
||||
BIN
api/app/favicon.ico
Normal file
BIN
api/app/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
0
api/app/helpers/__init__.py
Normal file
0
api/app/helpers/__init__.py
Normal file
23
api/app/helpers/authentication.py
Normal file
23
api/app/helpers/authentication.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from flask_httpauth import HTTPBasicAuth
|
||||
|
||||
auth = HTTPBasicAuth()
|
||||
|
||||
|
||||
@auth.verify_password
|
||||
def verify_password(username_or_token, password):
|
||||
|
||||
if username_or_token == "user" and password == "passwd":
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def post_login_required(func):
|
||||
def post_decorator(*args, **kwargs):
|
||||
print("post_decorator ", func, *args, **kwargs)
|
||||
return auth.login_required(func)(*args, **kwargs)
|
||||
|
||||
if func.__name__ in ("post", "patch", "delete"):
|
||||
return post_decorator
|
||||
|
||||
return func
|
||||
3
api/app/helpers/database.py
Normal file
3
api/app/helpers/database.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
|
||||
db = SQLAlchemy()
|
||||
2
api/app/helpers/math.py
Normal file
2
api/app/helpers/math.py
Normal file
@@ -0,0 +1,2 @@
|
||||
def safe_division(n: int, d: int, r: int = 2):
|
||||
return round((n / d), r) if d else 0
|
||||
35
api/app/main.py
Normal file
35
api/app/main.py
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/bin/python
|
||||
import logging
|
||||
|
||||
from flask import Flask
|
||||
from flask_cors import CORS
|
||||
|
||||
from helpers.database import db
|
||||
from swagger import create_api
|
||||
from settings import config
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.DEBUG,
|
||||
format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s",
|
||||
datefmt="%m-%d %H:%M",
|
||||
handlers=[logging.FileHandler(config.DASHBOARD_LOG), logging.StreamHandler()], # noqa
|
||||
)
|
||||
|
||||
app = Flask(__name__)
|
||||
cors = CORS(app, resources={r"/api/*": {"origins": "*"}}) # noqa
|
||||
|
||||
app.config.update(
|
||||
SQLALCHEMY_DATABASE_URI=config.SQLALCHEMY_DATABASE_URI,
|
||||
DEBUG=config.DEBUG
|
||||
)
|
||||
db.init_app(app)
|
||||
|
||||
with app.app_context():
|
||||
db.create_all()
|
||||
create_api(
|
||||
app=app,
|
||||
port="5000",
|
||||
host="localhost",
|
||||
api_prefix=config.API_PREFIX_STRING,
|
||||
custom_swagger=config.CUSTOM_SWAGGER
|
||||
)
|
||||
0
api/app/models/common/__init__.py
Normal file
0
api/app/models/common/__init__.py
Normal file
9
api/app/models/common/base.py
Normal file
9
api/app/models/common/base.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from helpers.database import db
|
||||
|
||||
from safrs import SAFRSBase
|
||||
from safrs.api_methods import search
|
||||
|
||||
|
||||
class BaseModel(SAFRSBase, db.Model):
|
||||
__abstract__ = True
|
||||
SAFRSBase.search = search
|
||||
0
api/app/models/common/core/__init__.py
Normal file
0
api/app/models/common/core/__init__.py
Normal file
21
api/app/models/common/core/contour.py
Normal file
21
api/app/models/common/core/contour.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from sqlalchemy import Column, String, Integer
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class contour(BaseModel):
|
||||
"""
|
||||
description: Technological infrastructure contours.
|
||||
"""
|
||||
__tablename__ = "tcc_contours"
|
||||
_s_collection_name = "contours"
|
||||
_s_class_name = "contours"
|
||||
exclude_rels = ["vcenter", "pcentral"]
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
name = Column(String(64), unique=True, index=True, nullable=False)
|
||||
description = Column(String(255))
|
||||
|
||||
vcenter = relationship("vcenter", back_populates="contour")
|
||||
pcentral = relationship("pcentral", back_populates="contour")
|
||||
27
api/app/models/common/core/environment.py
Normal file
27
api/app/models/common/core/environment.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from sqlalchemy import Column, String, Integer
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class environment(BaseModel):
|
||||
"""
|
||||
description: Technological infrastructure environments.
|
||||
"""
|
||||
__tablename__ = "tcc_environments"
|
||||
_s_collection_name = "environments"
|
||||
_s_class_name = "environment"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
name = Column(String(32), unique=True, index=True, nullable=False)
|
||||
color = Column(String(7), index=False, nullable=True)
|
||||
|
||||
cluster = relationship("cluster", back_populates="environment")
|
||||
pelement = relationship("pelement", back_populates="environment")
|
||||
|
||||
def to_dict(self):
|
||||
result = BaseModel.to_dict(self)
|
||||
|
||||
result['name'] = result['name'].upper()
|
||||
|
||||
return result
|
||||
21
api/app/models/common/core/timestamps.py
Normal file
21
api/app/models/common/core/timestamps.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from datetime import datetime
|
||||
from sqlalchemy import Column, String, Integer, DateTime
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class timestamp(BaseModel):
|
||||
"""
|
||||
description: Timestamps.
|
||||
"""
|
||||
__tablename__ = "tcc_timestamps"
|
||||
_s_collection_name = "timestamps"
|
||||
_s_class_name = "timestamps"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
name = Column(String(64), unique=True, nullable=False)
|
||||
timestamp = Column(
|
||||
DateTime,
|
||||
default=datetime.utcnow,
|
||||
onupdate=datetime.utcnow
|
||||
)
|
||||
0
api/app/models/nutanix/__init__.py
Normal file
0
api/app/models/nutanix/__init__.py
Normal file
0
api/app/models/nutanix/core/__init__.py
Normal file
0
api/app/models/nutanix/core/__init__.py
Normal file
40
api/app/models/nutanix/core/pcentral.py
Normal file
40
api/app/models/nutanix/core/pcentral.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
String,
|
||||
Integer,
|
||||
ForeignKey
|
||||
)
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class pcentral(BaseModel):
|
||||
"""
|
||||
description: Nutanix prism central model
|
||||
"""
|
||||
__tablename__ = "tnc_pcentrals"
|
||||
_s_collection_name = "pcentrals"
|
||||
_s_class_name = "pcentral"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
name = Column(String(32), unique=True, index=True, nullable=False)
|
||||
hostname = Column(String(64), unique=True, index=True, nullable=True)
|
||||
ncc_version = Column(String(16), index=True, nullable=False)
|
||||
aos_version = Column(String(16), index=True, nullable=False)
|
||||
|
||||
contour_id = Column(Integer, ForeignKey("tcc_contours.id"))
|
||||
contour = relationship("contour", back_populates="pcentral")
|
||||
|
||||
npcreport = relationship(
|
||||
"npcreport",
|
||||
backref="pcentral",
|
||||
cascade="save-update, delete",
|
||||
lazy="dynamic"
|
||||
)
|
||||
pelement = relationship(
|
||||
"pelement",
|
||||
backref="pcentral",
|
||||
cascade="save-update, delete",
|
||||
lazy="dynamic"
|
||||
)
|
||||
52
api/app/models/nutanix/core/pelement.py
Normal file
52
api/app/models/nutanix/core/pelement.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
String,
|
||||
Integer,
|
||||
ForeignKey
|
||||
)
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class pelement(BaseModel):
|
||||
"""
|
||||
description: Nutanix prism element model
|
||||
"""
|
||||
__tablename__ = "tnc_pelement"
|
||||
_s_collection_name = "pelements"
|
||||
_s_class_name = "pelement"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
ip = Column(String(15), unique=True, nullable=False)
|
||||
name = Column(String(32), unique=True, nullable=False)
|
||||
hostname = Column(String(64), unique=True, nullable=True)
|
||||
description = Column(String(64), unique=False, nullable=False)
|
||||
ncc_version = Column(String(16), index=True, nullable=False)
|
||||
aos_version = Column(String(16), index=True, nullable=False)
|
||||
cpu_decomiss = Column(Integer, nullable=True)
|
||||
|
||||
pcentral_id = Column(Integer, ForeignKey("tnc_pcentrals.id"))
|
||||
environment_id = Column(Integer, ForeignKey("tcc_environments.id"))
|
||||
|
||||
environment = relationship("environment", back_populates="pelement")
|
||||
pelement = relationship(
|
||||
"npereport",
|
||||
backref="pelement",
|
||||
cascade="save-update, delete",
|
||||
lazy="dynamic"
|
||||
)
|
||||
maintenance = relationship(
|
||||
"nmreport",
|
||||
backref="pelement",
|
||||
cascade="save-update, delete",
|
||||
lazy="dynamic"
|
||||
)
|
||||
|
||||
def to_dict(self):
|
||||
result = BaseModel.to_dict(self)
|
||||
|
||||
if (result['hostname'] is None):
|
||||
result['hostname'] = result['hostname']
|
||||
|
||||
return result
|
||||
0
api/app/models/nutanix/reports/__init__.py
Normal file
0
api/app/models/nutanix/reports/__init__.py
Normal file
0
api/app/models/nutanix/reports/mmhosts/__init__.py
Normal file
0
api/app/models/nutanix/reports/mmhosts/__init__.py
Normal file
37
api/app/models/nutanix/reports/mmhosts/report.py
Normal file
37
api/app/models/nutanix/reports/mmhosts/report.py
Normal file
@@ -0,0 +1,37 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
String,
|
||||
Integer,
|
||||
DateTime,
|
||||
ForeignKey
|
||||
)
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class nmreport(BaseModel):
|
||||
"""
|
||||
description: Nutanix hosts in maintenance mode report
|
||||
"""
|
||||
__tablename__ = "tnrm_report"
|
||||
_s_collection_name = "nmreport"
|
||||
_s_class_name = "nmreport"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
ip = Column(String(15), unique=True, nullable=False)
|
||||
ipmi = Column(String(15), unique=True, nullable=False)
|
||||
hypervisor_name = Column(String(64), unique=True, nullable=False)
|
||||
hypervisor_type = Column(String(32), index=True)
|
||||
hypervisor_state = Column(String(64), index=True)
|
||||
serial = Column(String(32), unique=True, nullable=False)
|
||||
reason = Column(String(255), nullable=True)
|
||||
date = Column(DateTime, default=datetime.utcnow)
|
||||
|
||||
pelement_id = Column(
|
||||
Integer,
|
||||
ForeignKey("tnc_pelement.id"),
|
||||
nullable=False,
|
||||
index=True
|
||||
)
|
||||
34
api/app/models/nutanix/reports/prismCentral/report.py
Normal file
34
api/app/models/nutanix/reports/prismCentral/report.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
Integer,
|
||||
ForeignKey
|
||||
)
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class npcreport(BaseModel):
|
||||
"""
|
||||
description: Nutanix prism central report model
|
||||
"""
|
||||
__tablename__ = "tnrpc_report"
|
||||
_s_collection_name = "npcreport"
|
||||
_s_class_name = "prismCentral"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
vms_total = Column(Integer, nullable=False)
|
||||
cert_status = Column(Integer, nullable=False)
|
||||
aos_status = Column(Integer, nullable=False)
|
||||
projects_total = Column(Integer, nullable=False)
|
||||
|
||||
alerts_crit_ack = Column(Integer, nullable=False)
|
||||
alerts_crit_nack = Column(Integer, nullable=False)
|
||||
alerts_warn_ack = Column(Integer, nullable=False)
|
||||
alerts_warn_nack = Column(Integer, nullable=False)
|
||||
|
||||
pcentral_id = Column(
|
||||
Integer,
|
||||
ForeignKey("tnc_pcentrals.id"),
|
||||
nullable=False,
|
||||
index=True
|
||||
)
|
||||
49
api/app/models/nutanix/reports/prismElement/report.py
Normal file
49
api/app/models/nutanix/reports/prismElement/report.py
Normal file
@@ -0,0 +1,49 @@
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
String,
|
||||
Integer,
|
||||
ForeignKey
|
||||
)
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class npereport(BaseModel):
|
||||
"""
|
||||
description: Nutanix prism element report model
|
||||
"""
|
||||
__tablename__ = "tnrpe_report"
|
||||
_s_collection_name = "npereport"
|
||||
_s_class_name = "prismElement"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
vms_total = Column(Integer, nullable=False)
|
||||
cert_status = Column(Integer, nullable=False)
|
||||
aos_status = Column(Integer, nullable=False)
|
||||
storage_dedup = Column(Integer, nullable=False)
|
||||
hosts_total = Column(Integer, nullable=False)
|
||||
hosts_in_maintenance = Column(Integer, nullable=False)
|
||||
storage_usage = Column(Integer, nullable=False)
|
||||
cpu_usage = Column(Integer, nullable=False)
|
||||
mem_usage = Column(Integer, nullable=False)
|
||||
hypervisor = Column(String(32), nullable=True)
|
||||
hypervisor_version = Column(String(32), nullable=True)
|
||||
alerts_crit_ack = Column(Integer, nullable=False)
|
||||
alerts_crit_nack = Column(Integer, nullable=False)
|
||||
alerts_warn_ack = Column(Integer, nullable=False)
|
||||
alerts_warn_nack = Column(Integer, nullable=False)
|
||||
redundancy_factor = Column(Integer, nullable=False)
|
||||
|
||||
pelement_id = Column(
|
||||
Integer,
|
||||
ForeignKey("tnc_pelement.id"),
|
||||
nullable=False,
|
||||
index=True
|
||||
)
|
||||
decomission = relationship(
|
||||
"nureport",
|
||||
backref="npereport",
|
||||
cascade="save-update, delete",
|
||||
lazy="dynamic"
|
||||
)
|
||||
31
api/app/models/nutanix/reports/utilization/report.py
Normal file
31
api/app/models/nutanix/reports/utilization/report.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
Integer,
|
||||
Float,
|
||||
ForeignKey
|
||||
)
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class nureport(BaseModel):
|
||||
"""
|
||||
description: Nutanix utilization report
|
||||
"""
|
||||
__tablename__ = "tnru_report"
|
||||
_s_collection_name = "nureport"
|
||||
_s_class_name = "utilization"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
cpu_avg = Column(Float, nullable=False)
|
||||
cpu_peak = Column(Float, nullable=False)
|
||||
mem_avg = Column(Float, nullable=False)
|
||||
mem_peak = Column(Float, nullable=False)
|
||||
storage = Column(Float, nullable=False)
|
||||
|
||||
pelement_id = Column(
|
||||
Integer,
|
||||
ForeignKey("tnrpe_report.id"),
|
||||
nullable=False,
|
||||
index=True
|
||||
)
|
||||
0
api/app/models/vmware/__init__.py
Normal file
0
api/app/models/vmware/__init__.py
Normal file
0
api/app/models/vmware/core/__init__.py
Normal file
0
api/app/models/vmware/core/__init__.py
Normal file
54
api/app/models/vmware/core/cluster.py
Normal file
54
api/app/models/vmware/core/cluster.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
String,
|
||||
Integer,
|
||||
ForeignKey
|
||||
)
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class cluster(BaseModel):
|
||||
"""
|
||||
description: VMware cluster model
|
||||
"""
|
||||
__tablename__ = "tvc_clusters"
|
||||
_s_collection_name = "clusters"
|
||||
exclude_rels = ["capacity", "datastores", "sharedNetwork"]
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
name = Column(String(64), unique=True, index=True, nullable=False)
|
||||
vcenter_id = Column(Integer, ForeignKey("tvc_vcenters.id"), nullable=False)
|
||||
environment_id = Column(
|
||||
Integer,
|
||||
ForeignKey("tcc_environments.id"),
|
||||
nullable=True
|
||||
)
|
||||
|
||||
vcenter = relationship("vcenter", back_populates="cluster")
|
||||
environment = relationship("environment", back_populates="cluster")
|
||||
capacity = relationship(
|
||||
"capacity",
|
||||
backref="cluster",
|
||||
cascade="save-update, delete",
|
||||
lazy="dynamic"
|
||||
)
|
||||
maintenance = relationship(
|
||||
"maintenance",
|
||||
backref="cluster",
|
||||
cascade="save-update, delete",
|
||||
lazy="dynamic"
|
||||
)
|
||||
datastores = relationship(
|
||||
"datastore",
|
||||
backref="cluster",
|
||||
cascade="save-update, delete",
|
||||
lazy="dynamic"
|
||||
)
|
||||
sharedNetwork = relationship(
|
||||
"sharedNetwork",
|
||||
backref="cluster",
|
||||
cascade="save-update, delete",
|
||||
lazy="dynamic"
|
||||
)
|
||||
36
api/app/models/vmware/core/vcenter.py
Normal file
36
api/app/models/vmware/core/vcenter.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
String,
|
||||
Integer,
|
||||
ForeignKey
|
||||
)
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class vcenter(BaseModel):
|
||||
"""
|
||||
description: VMware vcenter model
|
||||
"""
|
||||
__tablename__ = "tvc_vcenters"
|
||||
_s_collection_name = "vcenters"
|
||||
|
||||
exclude_rels = ["rvm_vcenter"]
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
hostname = Column(String(64), unique=True, index=True, nullable=False)
|
||||
contour_id = Column(Integer, ForeignKey("tcc_contours.id"))
|
||||
|
||||
cluster = relationship(
|
||||
"cluster",
|
||||
back_populates="vcenter",
|
||||
cascade="save-update, delete"
|
||||
)
|
||||
contour = relationship("contour", back_populates="vcenter")
|
||||
|
||||
vcenter = relationship(
|
||||
"maintenance",
|
||||
backref="vcenter",
|
||||
cascade="save-update, delete"
|
||||
)
|
||||
0
api/app/models/vmware/reports/__init__.py
Normal file
0
api/app/models/vmware/reports/__init__.py
Normal file
0
api/app/models/vmware/reports/capacity/__init__.py
Normal file
0
api/app/models/vmware/reports/capacity/__init__.py
Normal file
25
api/app/models/vmware/reports/capacity/frame.py
Normal file
25
api/app/models/vmware/reports/capacity/frame.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Column, Integer, DateTime
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class frame(BaseModel):
|
||||
__tablename__ = "tvrc_frames"
|
||||
_s_collection_name = "frames"
|
||||
http_methods = {"get", "post", "delete"}
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
timestamp = Column(
|
||||
DateTime,
|
||||
default=datetime.utcnow,
|
||||
onupdate=datetime.utcnow
|
||||
)
|
||||
|
||||
capacity = relationship(
|
||||
"capacity",
|
||||
backref="frame",
|
||||
cascade="save-update, delete"
|
||||
)
|
||||
131
api/app/models/vmware/reports/capacity/report.py
Normal file
131
api/app/models/vmware/reports/capacity/report.py
Normal file
@@ -0,0 +1,131 @@
|
||||
from safrs import jsonapi_rpc, SAFRSFormattedResponse
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
Integer,
|
||||
Float,
|
||||
ForeignKey
|
||||
)
|
||||
|
||||
from helpers.database import db
|
||||
from helpers.math import safe_division
|
||||
from models.common.base import BaseModel
|
||||
from models.vmware.reports.capacity.frame import frame
|
||||
|
||||
|
||||
class capacity(BaseModel):
|
||||
"""
|
||||
description: Capacity report model
|
||||
"""
|
||||
__tablename__ = "tvrc_report"
|
||||
_s_collection_name = "capacity"
|
||||
|
||||
http_methods = {"get", "post"}
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
hosts_on_duty = Column(Integer, nullable=False)
|
||||
hosts_in_maintenance = Column(Integer, nullable=False)
|
||||
hosts_reserved = Column(Integer, nullable=False)
|
||||
hosts_staged_dcm = Column(Integer, nullable=False)
|
||||
vms_total = Column(Integer, nullable=False)
|
||||
sockets_total = Column(Integer, nullable=False)
|
||||
pcpu_total = Column(Integer, nullable=False)
|
||||
pcpu_host_max = Column(Integer, nullable=False)
|
||||
vcpu_provisioned = Column(Integer, nullable=False)
|
||||
pmemory_total = Column(Float, nullable=False)
|
||||
vmemory_provisioned = Column(Float, nullable=False)
|
||||
pstorage_total = Column(Float, nullable=False)
|
||||
vstorage_used = Column(Float, nullable=False)
|
||||
vstorage_provisioned = Column(Float, nullable=False)
|
||||
rdm_total = Column(Float, nullable=False)
|
||||
pcpu_ovp_target = Column(Float, nullable=False)
|
||||
pmemory_ovp_target = Column(Float, nullable=False)
|
||||
pstorage_ovp_target = Column(Float, nullable=False)
|
||||
pcpu_retire_target = Column(Float, nullable=False)
|
||||
|
||||
frame_id = Column(
|
||||
Integer, ForeignKey("tvrc_frames.id"),
|
||||
nullable=False,
|
||||
index=True
|
||||
)
|
||||
cluster_id = Column(
|
||||
Integer,
|
||||
ForeignKey("tvc_clusters.id"),
|
||||
nullable=False,
|
||||
index=True
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@jsonapi_rpc(http_methods=["GET"])
|
||||
def get_last(self, *args, **kwargs):
|
||||
"""
|
||||
description : Get capacity report by last frameid
|
||||
summary : Get last capacity report
|
||||
tags:
|
||||
- capacity
|
||||
produces:
|
||||
- application/xml
|
||||
- application/json
|
||||
"""
|
||||
|
||||
frame_obj = db.session.query(frame).order_by(frame.id.desc()).first()
|
||||
|
||||
reports = db.session.query(capacity).\
|
||||
filter(capacity.frame_id == frame_obj.id).all()
|
||||
|
||||
data = [reports]
|
||||
response = SAFRSFormattedResponse(
|
||||
data,
|
||||
self._s_meta(),
|
||||
{},
|
||||
{},
|
||||
len(reports)
|
||||
)
|
||||
return response
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
pcpu_ovp_current = kwargs.pop("pcpu_ovp_current", None) # noqa
|
||||
pmemory_ovp_current = kwargs.pop("pmemory_ovp_current", None) # noqa
|
||||
pstorage_ovp_current = kwargs.pop("pstorage_ovp_current", None) # noqa
|
||||
|
||||
cpu_cap_used = kwargs.pop("cpu_cap_used", None) # noqa
|
||||
mem_cap_used = kwargs.pop("mem_cap_used", None) # noqa
|
||||
str_cap_used = kwargs.pop("str_cap_used", None) # noqa
|
||||
|
||||
hosts_total = kwargs.pop("hosts_total", None) # noqa
|
||||
|
||||
BaseModel.__init__(self, **kwargs)
|
||||
|
||||
def to_dict(self):
|
||||
result = BaseModel.to_dict(self)
|
||||
|
||||
result['pcpu_ovp_current'] = safe_division(
|
||||
result['vcpu_provisioned'],
|
||||
result['pcpu_total']
|
||||
)
|
||||
result['pmemory_ovp_current'] = safe_division(
|
||||
result['vmemory_provisioned'],
|
||||
result['pmemory_total']
|
||||
)
|
||||
result['pstorage_ovp_current'] = safe_division(
|
||||
result['vstorage_provisioned'],
|
||||
result['pstorage_total']
|
||||
)
|
||||
|
||||
result['cpu_cap_used'] = round(safe_division(
|
||||
result['pcpu_ovp_current'],
|
||||
result['pcpu_ovp_target']
|
||||
)*100)
|
||||
result['mem_cap_used'] = round(safe_division(
|
||||
result['pmemory_ovp_current'],
|
||||
result['pmemory_ovp_target']
|
||||
)*100)
|
||||
result['str_cap_used'] = round(safe_division(
|
||||
result['pstorage_ovp_current'],
|
||||
result['pstorage_ovp_target']
|
||||
)*100)
|
||||
|
||||
result['hosts_total'] = result['hosts_on_duty'] +\
|
||||
result['hosts_reserved'] +\
|
||||
result['hosts_in_maintenance']
|
||||
|
||||
return result
|
||||
56
api/app/models/vmware/reports/datastores/report.py
Normal file
56
api/app/models/vmware/reports/datastores/report.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
String,
|
||||
Integer,
|
||||
ForeignKey
|
||||
)
|
||||
|
||||
from helpers.math import safe_division
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class datastore(BaseModel):
|
||||
"""
|
||||
description: Datastores report model
|
||||
"""
|
||||
__tablename__ = "tvrd_report"
|
||||
_s_collection_name = "datastores"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
name = Column(String(64), index=True, nullable=False)
|
||||
space_used = Column(Integer, nullable=False)
|
||||
space_total = Column(Integer, nullable=False)
|
||||
space_provisioned = Column(Integer, nullable=False)
|
||||
|
||||
cluster_id = Column(
|
||||
Integer,
|
||||
ForeignKey("tvc_clusters.id"),
|
||||
nullable=False,
|
||||
index=True
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
ovp_current = kwargs.pop("ovp_current", None) # noqa
|
||||
space_free_percent = kwargs.pop("space_free_percent", None) # noqa
|
||||
cap_used = kwargs.pop("cap_used", None) # noqa
|
||||
|
||||
BaseModel.__init__(self, **kwargs)
|
||||
|
||||
def to_dict(self):
|
||||
result = BaseModel.to_dict(self)
|
||||
|
||||
result["ovp_current"] = safe_division(
|
||||
result["space_provisioned"],
|
||||
result["space_total"]
|
||||
)
|
||||
result["space_free_percent"] = round((1 - safe_division(
|
||||
result["space_used"],
|
||||
result["space_total"]
|
||||
))*100, 0)
|
||||
|
||||
result['cap_used'] = round(safe_division(
|
||||
result['ovp_current'],
|
||||
2
|
||||
)*100)
|
||||
|
||||
return result
|
||||
0
api/app/models/vmware/reports/mmhosts/__init__.py
Normal file
0
api/app/models/vmware/reports/mmhosts/__init__.py
Normal file
38
api/app/models/vmware/reports/mmhosts/report.py
Normal file
38
api/app/models/vmware/reports/mmhosts/report.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
String,
|
||||
Integer,
|
||||
DateTime,
|
||||
ForeignKey
|
||||
)
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class maintenance(BaseModel):
|
||||
__tablename__ = "tvrm_report"
|
||||
_s_collection_name = "maintenance"
|
||||
|
||||
http_methods = {"get", "post", "delete"}
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
folder = Column(String(255), nullable=False)
|
||||
hostname = Column(String(64), unique=True, nullable=False)
|
||||
state = Column(String(64), index=True)
|
||||
reason = Column(String(255))
|
||||
placedby = Column(String(64))
|
||||
placedbyFN = Column(String(64))
|
||||
date = Column(DateTime)
|
||||
|
||||
vcenter_id = Column(
|
||||
Integer,
|
||||
ForeignKey("tvc_vcenters.id"),
|
||||
nullable=False,
|
||||
index=True
|
||||
)
|
||||
cluster_id = Column(
|
||||
Integer,
|
||||
ForeignKey("tvc_clusters.id"),
|
||||
nullable=True,
|
||||
index=True
|
||||
)
|
||||
49
api/app/models/vmware/reports/sharedNetworks/report.py
Normal file
49
api/app/models/vmware/reports/sharedNetworks/report.py
Normal file
@@ -0,0 +1,49 @@
|
||||
from sqlalchemy import (
|
||||
Column,
|
||||
String,
|
||||
Integer,
|
||||
Float,
|
||||
ForeignKey
|
||||
)
|
||||
|
||||
from models.common.base import BaseModel
|
||||
|
||||
|
||||
class sharedNetwork(BaseModel):
|
||||
"""
|
||||
description: Shared Networks report model
|
||||
"""
|
||||
__tablename__ = "tvrsn_report"
|
||||
_s_collection_name = "sharedNetworks"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
vrf = Column(String(64), nullable=False)
|
||||
vrfId = Column(Integer, nullable=False, index=True)
|
||||
subnet = Column(String(15), nullable=False)
|
||||
subnetId = Column(Integer, nullable=False, unique=True, index=True)
|
||||
subnetMask = Column(Integer, nullable=False)
|
||||
requestsID = Column(String(32))
|
||||
bussinessLine = Column(String(32))
|
||||
subnetManager = Column(String(32), index=True)
|
||||
virtSubnetName = Column(String(32))
|
||||
virtSubnetUUID = Column(String(32))
|
||||
freeIPPercent = Column(Float, nullable=False)
|
||||
|
||||
cluster_id = Column(
|
||||
Integer,
|
||||
ForeignKey("tvc_clusters.id"),
|
||||
nullable=True,
|
||||
index=True
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
platform = kwargs.pop("platform", None) # noqa
|
||||
|
||||
BaseModel.__init__(self, **kwargs)
|
||||
|
||||
def to_dict(self):
|
||||
result = BaseModel.to_dict(self)
|
||||
|
||||
result["platform"] = "vmware"
|
||||
|
||||
return result
|
||||
46
api/app/settings.py
Normal file
46
api/app/settings.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import json
|
||||
from functools import lru_cache
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
ENVIRONMENT: str = "dev"
|
||||
|
||||
SWAGGER_HOST: str = "localhost:5000"
|
||||
|
||||
API_PREFIX_STRING: str = "/api"
|
||||
API_DESCRIPTION: str = "vtb_dashboard_api"
|
||||
|
||||
DASHBOARD_LOG: str = "vtb_dashboard_api.log"
|
||||
|
||||
POSTGRES_SERVER: str = "localhost"
|
||||
POSTGRES_PORT: int = 5432
|
||||
POSTGRES_USER: str
|
||||
POSTGRES_PASSWORD: str
|
||||
POSTGRES_DB: str = "virt.dashboard"
|
||||
|
||||
DEBUG: bool = False
|
||||
|
||||
@property
|
||||
def SQLALCHEMY_DATABASE_URI(self):
|
||||
return f"postgresql://{self.POSTGRES_USER}:{self.POSTGRES_PASSWORD}@{self.POSTGRES_SERVER}:{self.POSTGRES_PORT}/{self.POSTGRES_DB}" # noqa
|
||||
|
||||
@property
|
||||
def CUSTOM_SWAGGER(self):
|
||||
with open("custom_swagger.json") as j_fp:
|
||||
custom_swagger = json.load(j_fp)
|
||||
custom_swagger["host"] = self.SWAGGER_HOST
|
||||
return custom_swagger
|
||||
|
||||
model_config = SettingsConfigDict(extra='allow', env_file=".env")
|
||||
|
||||
|
||||
@lru_cache
|
||||
def get_config():
|
||||
load_dotenv()
|
||||
return Settings()
|
||||
|
||||
|
||||
config = get_config()
|
||||
59
api/app/swagger.py
Normal file
59
api/app/swagger.py
Normal file
@@ -0,0 +1,59 @@
|
||||
import logging
|
||||
|
||||
from flask import Flask
|
||||
from safrs import SAFRSAPI
|
||||
|
||||
from models.common.core.contour import contour as mcc_Contour
|
||||
from models.common.core.environment import environment as mcc_Environment
|
||||
from models.common.core.timestamps import timestamp as mcc_Timestamp
|
||||
|
||||
from models.vmware.core.vcenter import vcenter as mvc_vCenter
|
||||
from models.vmware.core.cluster import cluster as mvc_Cluster
|
||||
from models.vmware.reports.capacity.frame import frame as mvrc_Frame
|
||||
from models.vmware.reports.capacity.report import capacity as mvrc_Report
|
||||
from models.vmware.reports.mmhosts.report import maintenance as mvrm_Report
|
||||
from models.vmware.reports.datastores.report import datastore as mvrd_Report # noqa
|
||||
from models.vmware.reports.sharedNetworks.report import sharedNetwork as mvrsn_Report # noqa
|
||||
|
||||
from models.nutanix.core.pelement import pelement as mnc_Cluster
|
||||
from models.nutanix.core.pcentral import pcentral as mnc_Central
|
||||
from models.nutanix.reports.prismElement.report import npereport as mnrpe_Report # noqa
|
||||
from models.nutanix.reports.prismCentral.report import npcreport as mnrpc_Report # noqa
|
||||
from models.nutanix.reports.mmhosts.report import nmreport as mnrm_Report
|
||||
from models.nutanix.reports.utilization.report import nureport as mnru_Report # noqa
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def create_api(
|
||||
app: Flask,
|
||||
host: str,
|
||||
port: str,
|
||||
api_prefix: str,
|
||||
custom_swagger: dict = {}
|
||||
) -> None:
|
||||
api = SAFRSAPI(
|
||||
app,
|
||||
host=host,
|
||||
schemes=["http", "https"],
|
||||
port=port,
|
||||
prefix=api_prefix,
|
||||
custom_swagger=custom_swagger
|
||||
)
|
||||
|
||||
for model in [mcc_Contour, mcc_Environment, mcc_Timestamp]:
|
||||
api.expose_object(model, url_prefix="/common")
|
||||
|
||||
for model in [mvc_vCenter, mvc_Cluster]:
|
||||
api.expose_object(model, url_prefix="/vmware")
|
||||
|
||||
for model in [mvrc_Report, mvrm_Report, mvrd_Report, mvrsn_Report]:
|
||||
api.expose_object(model, url_prefix="/vmware/report")
|
||||
|
||||
api.expose_object(mvrc_Frame, url_prefix="/vmware/report/capacity")
|
||||
|
||||
for model in [mnc_Cluster, mnc_Central]:
|
||||
api.expose_object(model, url_prefix="/nutanix")
|
||||
|
||||
for model in [mnrpe_Report, mnrpc_Report, mnrm_Report, mnru_Report]:
|
||||
api.expose_object(model, url_prefix="/nutanix/report")
|
||||
5
api/app/wsgi.py
Normal file
5
api/app/wsgi.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from main import app
|
||||
from settings import config
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=config.DEBUG, host="0.0.0.0", port=5000)
|
||||
31
api/requirements.txt
Normal file
31
api/requirements.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
aniso8601>=9.0.1
|
||||
build>=0.10.0
|
||||
click>=8.1.3
|
||||
Flask>=2.2.5
|
||||
Flask-Cors>=3.0.10
|
||||
Flask-RESTful>=0.3.9
|
||||
flask-restful-swagger-2>=0.35
|
||||
Flask-SQLAlchemy>=3.0.3
|
||||
flask-swagger-ui>=4.11.1
|
||||
Flask-HTTPAuth>=4.8.0
|
||||
greenlet>=2.0.2
|
||||
importlib-metadata>=6.0.0
|
||||
itsdangerous>=2.1.2
|
||||
Jinja2>=3.1.2
|
||||
MarkupSafe>=2.1.2
|
||||
packaging>=23.0
|
||||
pyproject-hooks>=1.0.0
|
||||
pytz>=2022.7.1
|
||||
PyYAML>=6.0
|
||||
six>=1.16.0
|
||||
SQLAlchemy>=2.0.3
|
||||
tomli>=2.0.1
|
||||
typing-extensions>=4.4.0
|
||||
Werkzeug>=2.2.2
|
||||
zipp>=3.13.0
|
||||
safrs>=3.0.4
|
||||
psycopg2-binary>=2.9.7
|
||||
pydantic>=2.3.0
|
||||
pydantic-settings>=2.0.3
|
||||
python-dotenv>=1.0.0
|
||||
waitress>=2.1.2
|
||||
Reference in New Issue
Block a user