Delete deployment
This commit adds the function to delete a deployment. There's some validations in order to be able to delete it some of them is: The deploy host state should be one of: [pending, failed] The deploy state should be one of: [start-done, start-failed, abort-done] All nodes are running from release software. In case of delete a major release the data generated during the deploy should also be deleted which include /sysroot/upgrade/ostree_repo, /sysroot/upgrade/sysroot and the folders [config, fluxcd, helm, nfv/vim, sysinv, puppet, deploy] under /opt/platform/<folders>/<sw_version>. Also delete the /var/lib/postgres/<sw_version>. Note: The function is not called by any endpoint at this point as the New USM REST API is in development to avoid conflicts and rework. Test Plan: PASS: Folders deleted on /opt/platform/<folders>/<sw_version> with start-done and start-failed deploy state. PASS: Cleanup of staging data. PASS: Failed to attempt deletion with a deployed host N+1 release Story: 2010676 Task: 49979 Change-Id: I1789172edc730e6c94fa6bec7f5881c0bdfd7eab Signed-off-by: Luis Eduardo Bonatti <LuizEduardo.Bonatti@windriver.com>
This commit is contained in:
parent
f99f8377d0
commit
46a49a09fa
|
@ -34,6 +34,7 @@ RC_UNHEALTHY = 3
|
||||||
|
|
||||||
DEPLOY_PRECHECK_SCRIPT = "deploy-precheck"
|
DEPLOY_PRECHECK_SCRIPT = "deploy-precheck"
|
||||||
DEPLOY_START_SCRIPT = "software-deploy-start"
|
DEPLOY_START_SCRIPT = "software-deploy-start"
|
||||||
|
DEPLOY_CLEANUP_SCRIPT = "deploy-cleanup"
|
||||||
|
|
||||||
SEMANTICS_DIR = "%s/semantics" % SOFTWARE_STORAGE_DIR
|
SEMANTICS_DIR = "%s/semantics" % SOFTWARE_STORAGE_DIR
|
||||||
|
|
||||||
|
@ -56,6 +57,18 @@ DEBIAN_RELEASE = "bullseye"
|
||||||
STARLINGX_RELEASE = SW_VERSION
|
STARLINGX_RELEASE = SW_VERSION
|
||||||
PATCH_SCRIPTS_STAGING_DIR = "/var/www/pages/updates/software-scripts"
|
PATCH_SCRIPTS_STAGING_DIR = "/var/www/pages/updates/software-scripts"
|
||||||
SYSROOT_OSTREE = "/sysroot/ostree/repo"
|
SYSROOT_OSTREE = "/sysroot/ostree/repo"
|
||||||
|
STAGING_DIR = "/sysroot/upgrade"
|
||||||
|
ROOT_DIR = "%s/sysroot" % STAGING_DIR
|
||||||
|
POSTGRES_PATH = "/var/lib/postgresql"
|
||||||
|
PLATFORM_PATH = "/opt/platform"
|
||||||
|
CONFIG = "config"
|
||||||
|
FLUXCD = "fluxcd"
|
||||||
|
HELM = "helm"
|
||||||
|
VIM = "nfv/vim"
|
||||||
|
SYSINV = "sysinv"
|
||||||
|
PUPPET = "puppet"
|
||||||
|
DEPLOY = "deploy"
|
||||||
|
CLEANUP_FOLDERS_NAME = [CONFIG, FLUXCD, HELM, VIM, SYSINV, PUPPET, DEPLOY]
|
||||||
|
|
||||||
LOOPBACK_INTERFACE_NAME = "lo"
|
LOOPBACK_INTERFACE_NAME = "lo"
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,13 @@ class SoftwareAPI:
|
||||||
finally:
|
finally:
|
||||||
self.end_update()
|
self.end_update()
|
||||||
|
|
||||||
|
def get_all_current_hosts_states(self):
|
||||||
|
self.begin_update()
|
||||||
|
try:
|
||||||
|
return self.deploy_host_handler.query_all_current_states()
|
||||||
|
finally:
|
||||||
|
self.end_update()
|
||||||
|
|
||||||
def update_deploy_host(self, hostname, state):
|
def update_deploy_host(self, hostname, state):
|
||||||
self.begin_update()
|
self.begin_update()
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -27,7 +27,6 @@ from wsgiref import simple_server
|
||||||
from fm_api import fm_api
|
from fm_api import fm_api
|
||||||
from fm_api import constants as fm_constants
|
from fm_api import constants as fm_constants
|
||||||
|
|
||||||
|
|
||||||
from oslo_config import cfg as oslo_cfg
|
from oslo_config import cfg as oslo_cfg
|
||||||
|
|
||||||
import software.apt_utils as apt_utils
|
import software.apt_utils as apt_utils
|
||||||
|
@ -79,6 +78,7 @@ from software.deploy_state import DeployState
|
||||||
from software.release_verify import verify_files
|
from software.release_verify import verify_files
|
||||||
import software.config as cfg
|
import software.config as cfg
|
||||||
import software.utils as utils
|
import software.utils as utils
|
||||||
|
from software.sysinv_utils import get_ihost_list
|
||||||
from software.sysinv_utils import get_k8s_ver
|
from software.sysinv_utils import get_k8s_ver
|
||||||
from software.sysinv_utils import is_system_controller
|
from software.sysinv_utils import is_system_controller
|
||||||
|
|
||||||
|
@ -2651,6 +2651,56 @@ class PatchController(PatchService):
|
||||||
# a deployment)
|
# a deployment)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@require_deploy_state([DEPLOY_STATES.START_DONE, DEPLOY_STATES.START_FAILED, DEPLOY_STATES.ABORT_DONE],
|
||||||
|
"Deploy must be in the following states to be able to delete: %s, %s, %s" % (
|
||||||
|
DEPLOY_STATES.START_DONE.value, DEPLOY_STATES.START_FAILED.value,
|
||||||
|
DEPLOY_STATES.ABORT_DONE.value))
|
||||||
|
def software_deploy_delete_api(self) -> dict:
|
||||||
|
"""
|
||||||
|
Delete deployment and the data generated during the deploy.
|
||||||
|
|
||||||
|
:return: dict of info, warning and error messages
|
||||||
|
"""
|
||||||
|
msg_info = ""
|
||||||
|
msg_warning = ""
|
||||||
|
msg_error = ""
|
||||||
|
deploy = self.db_api_instance.get_deploy_all()[0]
|
||||||
|
to_release = deploy.get("to_release")
|
||||||
|
from_release = deploy.get("from_release")
|
||||||
|
major_from_release = utils.get_major_release_version(from_release)
|
||||||
|
for host in get_ihost_list():
|
||||||
|
# TODO(lbonatti) change it to sw_version once load is deprecated
|
||||||
|
if host.software_load != major_from_release:
|
||||||
|
raise SoftwareServiceError(f"Delete not allow because {host.hostname} is not running from release"
|
||||||
|
f" {major_from_release}")
|
||||||
|
|
||||||
|
hosts_states = self.db_api_instance.get_all_current_hosts_states()
|
||||||
|
if states.DEPLOY_HOST_STATES.DEPLOYED in hosts_states or states.DEPLOY_HOST_STATES.DEPLOYING in hosts_states:
|
||||||
|
raise SoftwareServiceError(f"There's host already {states.DEPLOY_HOST_STATES.DEPLOYED.value} "
|
||||||
|
f"or in {states.DEPLOY_HOST_STATES.DEPLOYING.value} process")
|
||||||
|
major_release = utils.get_major_release_version(to_release)
|
||||||
|
major_to_release = constants.MAJOR_RELEASE % major_release
|
||||||
|
if to_release == major_to_release:
|
||||||
|
try:
|
||||||
|
cmd_path = utils.get_software_deploy_script(to_release, constants.DEPLOY_CLEANUP_SCRIPT)
|
||||||
|
if (os.path.exists(f"{constants.STAGING_DIR}/{constants.OSTREE_REPO}") and
|
||||||
|
os.path.exists(constants.ROOT_DIR)):
|
||||||
|
subprocess.check_output([cmd_path, f"{constants.STAGING_DIR}/{constants.OSTREE_REPO}",
|
||||||
|
constants.ROOT_DIR, "all"], stderr=subprocess.STDOUT)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
msg_error = "Failed to delete deploy."
|
||||||
|
LOG.error("%s: %s" % (msg_error, e))
|
||||||
|
return dict(info=msg_info, warning=msg_warning, error=msg_error)
|
||||||
|
|
||||||
|
for folder in constants.CLEANUP_FOLDERS_NAME:
|
||||||
|
path = os.path.join(constants.PLATFORM_PATH, folder, major_release, "")
|
||||||
|
shutil.rmtree(path, ignore_errors=True)
|
||||||
|
shutil.rmtree(f"{constants.POSTGRES_PATH}/{major_release}")
|
||||||
|
msg_info += "Deploy deleted with success"
|
||||||
|
self.db_api_instance.delete_deploy_host_all()
|
||||||
|
self.db_api_instance.delete_deploy()
|
||||||
|
return dict(info=msg_info, warning=msg_warning, error=msg_error)
|
||||||
|
|
||||||
@require_deploy_state([DEPLOY_STATES.ACTIVATE_DONE],
|
@require_deploy_state([DEPLOY_STATES.ACTIVATE_DONE],
|
||||||
"Must complete deploy activate before completing the deployment")
|
"Must complete deploy activate before completing the deployment")
|
||||||
def software_deploy_complete_api(self) -> dict:
|
def software_deploy_complete_api(self) -> dict:
|
||||||
|
|
|
@ -367,6 +367,13 @@ class DeployHostHandler(DeployHosts):
|
||||||
data = get_software_filesystem_data()
|
data = get_software_filesystem_data()
|
||||||
return data.get("deploy_host", [])
|
return data.get("deploy_host", [])
|
||||||
|
|
||||||
|
def query_all_current_states(self):
|
||||||
|
data = get_software_filesystem_data()
|
||||||
|
states = []
|
||||||
|
for host in data.get("deploy_host", []):
|
||||||
|
states.append(host.get("state"))
|
||||||
|
return states
|
||||||
|
|
||||||
def update(self, hostname, state: DEPLOY_HOST_STATES):
|
def update(self, hostname, state: DEPLOY_HOST_STATES):
|
||||||
super().update(hostname, state)
|
super().update(hostname, state)
|
||||||
deploy = self.query(hostname)
|
deploy = self.query(hostname)
|
||||||
|
|
Loading…
Reference in New Issue