create data-api to access current deploy state

Change-Id: I25c542e9cac07c781790652ed01921181ad1916c
Signed-off-by: Luis Eduardo Bonatti <LuizEduardo.Bonatti@windriver.com>
This commit is contained in:
Luis Eduardo Bonatti
2023-10-27 13:22:43 -03:00
parent e222c1b9dc
commit b870c3a2bb
5 changed files with 386 additions and 4 deletions

View File

@@ -108,6 +108,90 @@ class SoftwareAPIController(object):
return result return result
@expose('json')
@expose('query.xml', content_type='application/xml')
def create_deploy_host(self, *args):
sc.software_create_deploy_host(list(args)[0])
return dict(succes="Deploy host created.")
@expose('json')
@expose('query.xml', content_type='application/xml')
def get_deploy_host(self, *args):
try:
deploy = sc.software_get_deploy_host(list(args)[0])
except Exception as e:
LOG.exception("Failed to get deploy %s. Error: %s", list(args)[0], e)
return dict(error="Failed to get the deploy.")
except DeployDoNotExist:
return dict(error=f"Deploy host %s do not exist." % list(args)[0])
return dict(data=deploy)
@expose('json')
@expose('query.xml', content_type='application/xml')
def update_deploy_host(self, *args):
try:
deploy = sc.software_update_deploy_host(list(args)[0])
except Exception as e:
LOG.exception("Failed to update deploy %s. Error: %s", list(args)[0], e)
return dict(error="Failed to get the deploy.")
except DeployDoNotExist:
return dict(error=f"Deploy host %s do not exist." % list(args)[0])
return dict(succes=deploy)
@expose('json')
@expose('query.xml', content_type='application/xml')
def delete_all_deploy_host(self, *args):
try:
deploy = sc.software_delete_all_deploy_host(list(args)[0])
except Exception as e:
LOG.exception("Failed to delete deploy host %s. Error: %s", list(args)[0], e)
return dict(error="Failed to delete the deploy host.")
except DeployDoNotExist:
return dict(error=f"Deploy host %s do not exist." % list(args)[0])
return dict(succes=deploy)
@expose('json')
@expose('query.xml', content_type='application/xml')
def create_deploy(self, *args):
sc.software_create_deploy(list(args)[0])
return dict(succes="Deploy created.")
@expose('json')
@expose('query.xml', content_type='application/xml')
def get_deploy(self, *args):
try:
deploy = sc.software_get_deploy(list(args)[0])
except Exception as e:
LOG.exception("Failed to get deploy %s. Error: %s", list(args)[0], e)
return dict(error="Failed to get the deploy.")
except DeployDoNotExist:
return dict(error=f"Deploy %s do not exist." % list(args)[0])
return dict(data=deploy)
@expose('json')
@expose('query.xml', content_type='application/xml')
def update_deploy(self, *args):
try:
deploy = sc.software_update_deploy(list(args)[0])
except Exception as e:
LOG.exception("Failed to update deploy %s. Error: %s", list(args)[0], e)
return dict(error="Failed to get the deploy.")
except DeployDoNotExist:
return dict(error=f"Deploy %s do not exist." % list(args)[0])
return dict(succes=deploy)
@expose('json')
@expose('query.xml', content_type='application/xml')
def delete_deploy(self, *args):
try:
deploy = sc.software_delete_deploy(list(args)[0])
except Exception as e:
LOG.exception("Failed to delete deploy %s. Error: %s", list(args)[0], e)
return dict(error="Failed to get the deploy.")
except DeployDoNotExist:
return dict(error=f"Deploy %s do not exist." % list(args)[0])
return dict(succes=deploy)
@expose('json') @expose('json')
@expose('query.xml', content_type='application/xml') @expose('query.xml', content_type='application/xml')
def deploy_start(self, *args, **kwargs): def deploy_start(self, *args, **kwargs):

View File

@@ -95,3 +95,7 @@ class SysinvClientNotInitialized(SoftwareError):
class StateValidationFailure(SoftwareError): class StateValidationFailure(SoftwareError):
"""State Validation Failure""" """State Validation Failure"""
pass pass
class DeployDoNotExist(SoftwareError):
"""Deploy Do Not Exist"""
pass

View File

@@ -27,6 +27,8 @@ from wsgiref import simple_server
from oslo_config import cfg as oslo_cfg from oslo_config import cfg as oslo_cfg
import software.ostree_utils as ostree_utils import software.ostree_utils as ostree_utils
from software.software_entities import DeployHandler
from software.software_entities import DeployHostHandler
from software.api import app from software.api import app
from software.authapi import app as auth_app from software.authapi import app as auth_app
from software.base import PatchService from software.base import PatchService
@@ -1787,6 +1789,179 @@ class PatchController(PatchService):
msg = "Failed to delete the restart script for %s" % patch_id msg = "Failed to delete the restart script for %s" % patch_id
LOG.exception(msg) LOG.exception(msg)
def software_create_deploy_host(self, deployment: str) -> dict:
"""
Verify if system is capable to upgrade to a specified deployment
return: dict of info, warning and error messages
"""
msg_info = ""
msg_warning = ""
msg_error = ""
# We need to verify that the software release exists
release = self.release_data.metadata.get(deployment, None)
if not release:
msg = "Software release version corresponding to the specified deployment " \
"%s does not exist." % deployment
LOG.error(msg)
msg_error += msg + "\n"
return dict(info=msg_info, warning=msg_warning, error=msg_error)
# Check if software release directory location exists
release_version = utils.get_major_release_version(release["sw_version"])
return DeployHostHandler().create(from_release=SW_VERSION, to_release=release_version)
def software_get_deploy_host(self, hostname) -> dict:
"""
Verify if system is capable to upgrade to a specified deployment
return: dict of info, warning and error messages
"""
return DeployHostHandler().get(hostname=hostname)
def software_update_deploy_host(self, deployment: str, hostname: str, state: str) -> dict:
"""
Verify if system is capable to upgrade to a specified deployment
return: dict of info, warning and error messages
"""
msg_info = ""
msg_warning = ""
msg_error = ""
# We need to verify that the software release exists
release = self.release_data.metadata.get(deployment, None)
if not release:
msg = "Software release version corresponding to the specified deployment " \
"%s does not exist." % deployment
LOG.error(msg)
msg_error += msg + "\n"
return dict(info=msg_info, warning=msg_warning, error=msg_error)
# Check if software release directory location exists
release_version = utils.get_major_release_version(release["sw_version"])
return DeployHostHandler().update(hostname=hostname, from_release=SW_VERSION,
to_release=release_version, state=state)
def software_delete_all_deploy_host(self, deployment: str) -> dict:
"""
Verify if system is capable to upgrade to a specified deployment
return: dict of info, warning and error messages
"""
msg_info = ""
msg_warning = ""
msg_error = ""
# We need to verify that the software release exists
release = self.release_data.metadata.get(deployment, None)
if not release:
msg = "Software release version corresponding to the specified deployment " \
"%s does not exist." % deployment
LOG.error(msg)
msg_error += msg + "\n"
return dict(info=msg_info, warning=msg_warning, error=msg_error)
# Check if software release directory location exists
release_version = utils.get_major_release_version(release["sw_version"])
return DeployHostHandler().delete_all(from_release=SW_VERSION, to_release=release_version)
def software_create_deploy(self, deployment: str) -> dict:
"""
Verify if system is capable to upgrade to a specified deployment
return: dict of info, warning and error messages
"""
msg_info = ""
msg_warning = ""
msg_error = ""
# We need to verify that the software release exists
release = self.release_data.metadata.get(deployment, None)
if not release:
msg = "Software release version corresponding to the specified deployment " \
"%s does not exist." % deployment
LOG.error(msg)
msg_error += msg + "\n"
return dict(info=msg_info, warning=msg_warning, error=msg_error)
# Check if software release directory location exists
release_version = utils.get_major_release_version(release["sw_version"])
return DeployHandler().create(from_release=SW_VERSION, to_release=release_version)
# return dict(info=msg_info, warning=msg_warning, error=msg_error)
def software_get_deploy(self, deployment: str) -> dict:
"""
Verify if system is capable to upgrade to a specified deployment
return: dict of info, warning and error messages
"""
msg_info = ""
msg_warning = ""
msg_error = ""
# We need to verify that the software release exists
release = self.release_data.metadata.get(deployment, None)
if not release:
msg = "Software release version corresponding to the specified deployment " \
"%s does not exist." % deployment
LOG.error(msg)
msg_error += msg + "\n"
return dict(info=msg_info, warning=msg_warning, error=msg_error)
# Check if software release directory location exists
release_version = utils.get_major_release_version(release["sw_version"])
return DeployHandler().get(from_release=SW_VERSION, to_release=release_version)
# return dict(info=msg_info, warning=msg_warning, error=msg_error)
def software_update_deploy(self, deployment: str) -> dict:
"""
Verify if system is capable to upgrade to a specified deployment
return: dict of info, warning and error messages
"""
msg_info = ""
msg_warning = ""
msg_error = ""
# We need to verify that the software release exists
release = self.release_data.metadata.get(deployment, None)
if not release:
msg = "Software release version corresponding to the specified deployment " \
"%s does not exist." % deployment
LOG.error(msg)
msg_error += msg + "\n"
return dict(info=msg_info, warning=msg_warning, error=msg_error)
# Check if software release directory location exists
release_version = utils.get_major_release_version(release["sw_version"])
DeployHandler().update(from_release=SW_VERSION, to_release=release_version)
return dict(info=msg_info, warning=msg_warning, error=msg_error)
def software_delete_deploy(self, deployment: str) -> dict:
"""
Verify if system is capable to upgrade to a specified deployment
return: dict of info, warning and error messages
"""
msg_info = ""
msg_warning = ""
msg_error = ""
# We need to verify that the software release exists
release = self.release_data.metadata.get(deployment, None)
if not release:
msg = "Software release version corresponding to the specified deployment " \
"%s does not exist." % deployment
LOG.error(msg)
msg_error += msg + "\n"
return dict(info=msg_info, warning=msg_warning, error=msg_error)
# Check if software release directory location exists
release_version = utils.get_major_release_version(release["sw_version"])
DeployHandler().delete(from_release=SW_VERSION, to_release=release_version)
return dict(info=msg_info, warning=msg_warning, error=msg_error)
def software_deploy_precheck_api(self, deployment: str, **kwargs) -> dict: def software_deploy_precheck_api(self, deployment: str, **kwargs) -> dict:
""" """
Verify if system is capable to upgrade to a specified deployment Verify if system is capable to upgrade to a specified deployment

View File

@@ -6,11 +6,15 @@ SPDX-License-Identifier: Apache-2.0
""" """
import logging import logging
import os
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from enum import Enum from enum import Enum
from typing import List from typing import List
from software.utils import check_instances, check_state from software.utils import check_instances, check_state, load_from_json_file, save_to_json_file, get_software_filesystem_data
from software import constants
from software.exceptions import DeployDoNotExist
LOG = logging.getLogger('main_logger') LOG = logging.getLogger('main_logger')
@@ -140,11 +144,12 @@ class Deploy(ABC):
""" """
check_instances([from_release, to_release, state], str) check_instances([from_release, to_release, state], str)
if state:
check_state(state, self.states) check_state(state, self.states)
pass pass
@abstractmethod @abstractmethod
def query(self, from_release: str, to_release: str): def get(self, from_release: str, to_release: str):
""" """
Get deployments based on source and target release versions. Get deployments based on source and target release versions.
@@ -227,11 +232,114 @@ class DeployHosts(ABC):
pass pass
@abstractmethod @abstractmethod
def delete(self, host_name: str): def delete(self, host_name: str, software_release: str, target_release: str):
""" """
Delete deploy-host entries for a given host. Delete deploy-host entries for a given host.
:param host_name: The name of the host. :param host_name: The name of the host.
:param software_release: The software release version.
:param target_release: The target release version.
""" """
check_instances([host_name], str) check_instances([host_name], str)
pass pass
class DeployHandler(Deploy):
def __init__(self):
self.data = get_software_filesystem_data()
def create(self, from_release, to_release, state=None):
deploy = self.get(from_release, to_release)
if deploy:
raise DeployAlreadyExist("Error to create. Deploy already exist.")
deploy_data = {
"deploy": []
}
deploy_data["deploy"].append({
"from_release": from_release,
"to_release": to_release,
"state": state
})
self.data.update(deploy_data)
save_to_json_file(constants.SOFTWARE_JSON_FILE, self.data)
def get(self, from_release, to_release):
for deploy in self.data.get("deploys", []):
if deploy.get("from_release") == from_release and deploy.get("to_release") == to_release:
return deploy
def update(self, from_release, to_release, state):
deploy = self.get(from_release, to_release)
if not deploy:
raise DeployDoNotExist("Error to update. Deploy do not exist.")
deploy_data = {
"deploy": []
}
deploy_data["deploy"].append({
"from_release": from_release,
"to_release": to_release,
"state": state
})
self.data.update(deploy_data)
save_to_json_file(constants.SOFTWARE_JSON_FILE, self.data)
def delete(self, from_release, to_release):
deploy = self.get(from_release, to_release)
if not deploy:
raise DeployDoNotExist("Error to delete. Deploy do not exist.")
else:
self.data.get("deploy").remove(deploy)
self.data.update(data)
save_to_json_file(constants.SOFTWARE_JSON_FILE, self.data)
class DeployHostHandler(DeployHosts):
def __init__(self):
self.data = get_software_filesystem_data()
def create(self, hostname, from_release, to_release, state=None):
deploy = self.get(hostname, from_release, to_release)
if deploy:
raise DeployAlreadyExist("Error to create. Deploy host already exist.")
deploy_data = self.data.get("deploy_host", [])
if not deploy_data:
deploy_data = {
"deploy_host": []
}
deploy_data["deploy_host"].append({
"hostname": hostname,
"from_release": from_release,
"to_release": to_release,
"state": state
})
self.data.update(deploy_data)
else:
deploy_data.append({
"hostname": hostname,
"from_release": from_release,
"to_release": to_release,
"state": state
})
save_to_json_file(constants.SOFTWARE_JSON_FILE, self.data)
def get(self, hostname, from_release, to_release):
for deploy in self.data.get("deploys", []):
if (deploy.get("hostname") == hostname and deploy.get("from_release") == from_release
and deploy.get("to_release") == to_release):
return deploy
def get_by_hostname(self, hostname):
for deploy in self.data.get("deploys", []):
if deploy.get("hostname") == hostname:
return deploy
def update(self, hostname, from_release, to_release, state):
deploy = self.get(hostname, from_release, to_release)
if not deploy:
raise Exception("Error to update. Deploy host do not exist.")
index = self.data.get("deploy_host", []).index(deploy)
self.data["deploy_host"][index].update({
"hostname": hostname,
"from_release": from_release,
"to_release": to_release,
"state": state
})
save_to_json_file(constants.SOFTWARE_JSON_FILE, self.data)
def delete_all(self):
self.data.get("deploy_host").clear()
save_to_json_file(constants.SOFTWARE_JSON_FILE, self.data)

View File

@@ -269,6 +269,10 @@ def load_from_json_file(file):
except FileNotFoundError: except FileNotFoundError:
LOG.error("File %s not found", file) LOG.error("File %s not found", file)
return None return None
except ValueError:
return {}
except Exception as e: except Exception as e:
LOG.error("Problem reading from %s: %s", file, e) LOG.error("Problem reading from %s: %s", file, e)
return None return None
@@ -292,3 +296,10 @@ def check_instances(params: list, instance):
msg = "Param %s must be type: %s" % (p, instance) msg = "Param %s must be type: %s" % (p, instance)
LOG.exception(msg) LOG.exception(msg)
raise ValueError(msg) raise ValueError(msg)
def get_software_filesystem_data():
if os.path.exists(constants.SOFTWARE_JSON_FILE):
data = load_from_json_file(constants.SOFTWARE_JSON_FILE)
else:
data = {}
return data