Merge "Delete deployment"

This commit is contained in:
Zuul
2024-05-29 14:10:53 +00:00
committed by Gerrit Code Review
7 changed files with 161 additions and 1 deletions

View File

@@ -82,6 +82,15 @@ class DeployManager(base.Manager):
return self._create(path, body={})
def delete(self, args):
# Ignore interrupts during this function
signal.signal(signal.SIGINT, signal.SIG_IGN)
# Issue deploy delete request
path = "/v1/deploy"
return self._delete(path)
def host_list(self):
path = '/v1/deploy_host'
return self._list(path, "")

View File

@@ -19,6 +19,7 @@ DEPLOY_COMMAND_MODULES = [
# - host
# - activate
# - complete
# - delete
# non root/sudo users can run:
# - host-list
# - show

View File

@@ -152,3 +152,15 @@ def do_complete(cc, args):
utils.display_info(resp)
return utils.check_rc(resp, data)
def do_delete(cc, args):
"""Delete the software deployment"""
resp, data = cc.deploy.delete(args)
if args.debug:
utils.print_result_debug(resp, data)
utils.display_info(resp)
return utils.check_rc(resp, data)

View File

@@ -23,6 +23,7 @@ class DeployController(RestController):
'precheck': ['POST'],
'start': ['POST'],
'complete': ['POST'],
'delete': ['DELETE'],
'software_upgrade': ['GET'],
}
@@ -42,6 +43,14 @@ class DeployController(RestController):
sc.software_sync()
return result
@expose(method='DELETE', template='json')
def delete(self):
reload_release_data()
result = sc.software_deploy_delete_api()
sc.software_sync()
return result
@expose(method='POST', template='json')
def precheck(self, release, force=None, region_name=None):
_force = force is not None

View File

@@ -36,6 +36,7 @@ RC_UNHEALTHY = 3
DEPLOY_PRECHECK_SCRIPT = "deploy-precheck"
UPGRADE_UTILS_SCRIPT = "upgrade_utils.py"
DEPLOY_START_SCRIPT = "software-deploy-start"
DEPLOY_CLEANUP_SCRIPT = "deploy-cleanup"
SEMANTICS_DIR = "%s/semantics" % SOFTWARE_STORAGE_DIR
@@ -59,6 +60,24 @@ DEBIAN_RELEASE = "bullseye"
STARLINGX_RELEASE = SW_VERSION
PATCH_SCRIPTS_STAGING_DIR = "/var/www/pages/updates/software-scripts"
SYSROOT_OSTREE = "/sysroot/ostree/repo"
STAGING_DIR = "/sysroot/upgrade"
ROOT_DIR = "%s/sysroot" % STAGING_DIR
POSTGRES_PATH = "/var/lib/postgresql"
PLATFORM_PATH = "/opt/platform"
RABBIT_PATH = '/var/lib/rabbitmq'
ETCD_PATH = "/opt/etcd"
ARMADA = "armada"
CONFIG = "config"
DEPLOY = "deploy"
FLUXCD = "fluxcd"
HELM = "helm"
KEYRING = ".keyring"
PUPPET = "puppet"
SYSINV = "sysinv"
UPGRADE = "upgrade"
VIM = "nfv/vim"
DEPLOY_CLEANUP_FOLDERS_NAME = [ARMADA, CONFIG, DEPLOY, FLUXCD, HELM, KEYRING, PUPPET, SYSINV, VIM]
LOOPBACK_INTERFACE_NAME = "lo"

View File

@@ -27,7 +27,6 @@ from wsgiref import simple_server
from fm_api import fm_api
from fm_api import constants as fm_constants
from oslo_config import cfg as oslo_cfg
import software.apt_utils as apt_utils
@@ -76,6 +75,8 @@ from software.software_functions import repo_root_dir
from software.software_functions import is_deploy_state_in_sync
from software.software_functions import is_deployment_in_progress
from software.software_functions import get_release_from_patch
from software.software_functions import clean_up_deployment_data
from software.software_functions import run_deploy_clean_up_script
from software.release_state import ReleaseState
from software.deploy_host_state import DeployHostState
from software.deploy_state import DeployState
@@ -2689,6 +2690,76 @@ class PatchController(PatchService):
return dict(info=msg_info, warning=msg_warning, error=msg_error)
@require_deploy_state([DEPLOY_STATES.ABORT_DONE, DEPLOY_STATES.COMPLETED, DEPLOY_STATES.START_DONE,
DEPLOY_STATES.START_FAILED],
"Deploy must be in the following states to be able to delete: %s, %s, %s, %s" % (
DEPLOY_STATES.ABORT_DONE.value, DEPLOY_STATES.COMPLETED.value,
DEPLOY_STATES.START_DONE.value, DEPLOY_STATES.START_FAILED.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_current_deploy()
to_release = deploy.get("to_release")
from_release = deploy.get("from_release")
to_release_deployment = constants.RELEASE_GA_NAME % to_release
from_release_deployment = constants.RELEASE_GA_NAME % from_release
deploy_state_instance = DeployState.get_instance()
is_major_release = False
if DEPLOY_STATES.COMPLETED == deploy_state_instance.get_deploy_state():
major_release = utils.get_major_release_version(from_release)
# Try except in case there is no deploy in the class i.e. after unlock in RR deployment.
try:
is_major_release = ReleaseState().is_major_release_deployment()
except AttributeError:
release = self.release_collection.get_release_by_id(from_release_deployment)
is_major_release = ReleaseState(release_ids=[release.id]).is_major_release_deployment()
elif DEPLOY_STATES.ABORT_DONE == deploy_state_instance.get_deploy_state():
major_release = utils.get_major_release_version(to_release)
try:
is_major_release = ReleaseState().is_major_release_deployment()
except AttributeError:
release = self.release_collection.get_release_by_id(to_release_deployment)
is_major_release = ReleaseState(release_ids=[release.id]).is_major_release_deployment()
elif deploy_state_instance.get_deploy_state() in [DEPLOY_STATES.START_DONE, DEPLOY_STATES.START_FAILED]:
hosts_states = []
for host in self.db_api_instance.get_deploy_host():
hosts_states.append(host.get("state"))
if (DEPLOY_HOST_STATES.DEPLOYED.value in hosts_states or
DEPLOY_HOST_STATES.DEPLOYING.value in hosts_states):
raise SoftwareServiceError(f"There are hosts already {DEPLOY_HOST_STATES.DEPLOYED.value} "
f"or in {DEPLOY_HOST_STATES.DEPLOYING.value} process")
major_release = utils.get_major_release_version(to_release)
try:
is_major_release = ReleaseState().is_major_release_deployment()
except AttributeError:
release = self.release_collection.get_release_by_id(to_release_deployment)
is_major_release = ReleaseState(release_ids=[release.id]).is_major_release_deployment()
if is_major_release:
try:
run_deploy_clean_up_script(to_release)
except subprocess.CalledProcessError as e:
msg_error = "Failed to delete deploy"
LOG.error("%s: %s" % (msg_error, e))
raise SoftwareServiceError(msg_error)
if is_major_release:
clean_up_deployment_data(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)
def _deploy_complete(self):
is_all_hosts_in_deployed_state = all(host_state.get("state") == DEPLOY_HOST_STATES.DEPLOYED.value
for host_state in self.db_api_instance.get_deploy_host())

View File

@@ -1435,3 +1435,42 @@ def mount_remote_directory(remote_dir, local_dir):
subprocess.check_call(["/bin/umount", local_dir])
except subprocess.CalledProcessError as e:
LOG.error("Error unmounting %s: %s" % (local_dir, str(e)))
def clean_up_deployment_data(major_release):
"""
Clean up all data generated during deployment.
:param major_release: Major release to be deleted.
"""
# Delete the data inside /opt/platform/<folder>/<major_release>
for folder in constants.DEPLOY_CLEANUP_FOLDERS_NAME:
path = os.path.join(constants.PLATFORM_PATH, folder, major_release, "")
shutil.rmtree(path, ignore_errors=True)
# TODO(lbonatti): These folders should be revisited on software deploy abort/rollback
# to check additional folders that might be needed to delete.
upgrade_folders = [
os.path.join(constants.POSTGRES_PATH, constants.UPGRADE),
os.path.join(constants.POSTGRES_PATH, major_release),
os.path.join(constants.RABBIT_PATH, major_release),
os.path.join(constants.ETCD_PATH, major_release),
]
for folder in upgrade_folders:
shutil.rmtree(folder, ignore_errors=True)
def run_deploy_clean_up_script(release):
"""
Runs the deploy-cleanup script for the given release.
:param release: Release to be cleaned.
"""
cmd_path = utils.get_software_deploy_script(release, constants.DEPLOY_CLEANUP_SCRIPT)
if (os.path.exists(f"{constants.STAGING_DIR}/{constants.OSTREE_REPO}") and
os.path.exists(constants.ROOT_DIR)):
try:
subprocess.check_output([cmd_path, f"{constants.STAGING_DIR}/{constants.OSTREE_REPO}",
constants.ROOT_DIR, "all"], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
LOG.exception("Error running deploy-cleanup script: %s" % str(e))
raise