diff --git a/software/software/software_client.py b/software/software/software_client.py index a5fb52b9..edb6e65a 100644 --- a/software/software/software_client.py +++ b/software/software/software_client.py @@ -1209,94 +1209,6 @@ def register_deploy_commands(commands): cmd.set_defaults(restricted=False) # can run non root -def register_release_commands(commands): - """release commands - - delete - - list - - show - - upload - - upload-dir - non root/sudo users can run: - - show - - list - """ - cmd_area = 'release' - cmd_parser = commands.add_parser( - cmd_area, - help='Software Release', - epilog="StarlingX Unified Software Deployment" - ) - cmd_parser.set_defaults(cmd_area=cmd_area) - sub_cmds = cmd_parser.add_subparsers( - title='Software Release Commands', - metavar='' - ) - sub_cmds.required = True - - # -- software release delete --------------- - cmd = sub_cmds.add_parser( - 'delete', - help='Delete the software release' - ) - cmd.set_defaults(cmd='delete') - cmd.set_defaults(func=release_delete_req) - cmd.add_argument('release', - nargs="+", # accepts a list - help='Release ID to delete') - - # --- software release list --------------------------- - cmd = sub_cmds.add_parser( - 'list', - help='List the software releases' - ) - cmd.set_defaults(cmd='list') - cmd.set_defaults(func=release_list_req) - cmd.set_defaults(restricted=False) # can run non root - # --release is an optional argument - cmd.add_argument('--release', - required=False, - help='filter against a release ID') - # --state is an optional argument. default: "all" - cmd.add_argument('--state', - default="all", - required=False, - help='filter against a release state') - - # --- software release show ----------------- - cmd = sub_cmds.add_parser( - 'show', - help='Show the software release' - ) - cmd.set_defaults(cmd='show') - cmd.set_defaults(func=release_show_req) - cmd.set_defaults(restricted=False) # can run non root - cmd.add_argument('release', - nargs="+", # accepts a list - help='Release ID to show') - - # --- software release upload --------------- - cmd = sub_cmds.add_parser( - 'upload', - help='Upload a software release' - ) - cmd.set_defaults(cmd='upload') - cmd.set_defaults(func=release_upload_req) - cmd.add_argument('release', - nargs="+", # accepts a list - help='software releases to upload') - - # --- software release upload-dir ------ - cmd = sub_cmds.add_parser( - 'upload-dir', - help='Upload a software release dir' - ) - cmd.set_defaults(cmd='upload-dir') - cmd.set_defaults(func=release_upload_dir_req) - cmd.add_argument('release', - nargs="+", # accepts a list - help='directory containing software releases to upload') - - def setup_argparse(): parser = argparse.ArgumentParser(prog="software", description="Unified Software Management", @@ -1323,8 +1235,70 @@ def setup_argparse(): commands = parser.add_subparsers(title='Commands', metavar='') commands.required = True + # -- software delete --------------- + cmd = commands.add_parser( + 'delete', + help='Delete the software release' + ) + cmd.set_defaults(cmd='delete') + cmd.set_defaults(func=release_delete_req) + cmd.add_argument('release', + nargs="+", # accepts a list + help='Release ID to delete') + + # --- software list --------------------------- + cmd = commands.add_parser( + 'list', + help='List the software releases' + ) + cmd.set_defaults(cmd='list') + cmd.set_defaults(func=release_list_req) + cmd.set_defaults(restricted=False) # can run non root + # --release is an optional argument + cmd.add_argument('--release', + required=False, + help='filter against a release ID') + # --state is an optional argument. default: "all" + cmd.add_argument('--state', + default="all", + required=False, + help='filter against a release state') + + # --- software show ----------------- + cmd = commands.add_parser( + 'show', + help='Show the software release' + ) + cmd.set_defaults(cmd='show') + cmd.set_defaults(func=release_show_req) + cmd.set_defaults(restricted=False) # can run non root + cmd.add_argument('release', + nargs="+", # accepts a list + help='Release ID to show') + + # --- software upload --------------- + cmd = commands.add_parser( + 'upload', + help='Upload a software release' + ) + cmd.set_defaults(cmd='upload') + cmd.set_defaults(func=release_upload_req) + cmd.add_argument('release', + nargs="+", # accepts a list + help='software releases to upload') + + # --- software upload-dir ------ + cmd = commands.add_parser( + 'upload-dir', + help='Upload a software release dir' + ) + cmd.set_defaults(cmd='upload-dir') + cmd.set_defaults(func=release_upload_dir_req) + cmd.add_argument('release', + nargs="+", # accepts a list + help='directory containing software releases to upload') + register_deploy_commands(commands) - register_release_commands(commands) return parser diff --git a/software/software/software_controller.py b/software/software/software_controller.py index e3f2f55f..67c39891 100644 --- a/software/software/software_controller.py +++ b/software/software/software_controller.py @@ -1107,7 +1107,8 @@ class PatchController(PatchService): # Handle operation for release_id in release_list: - release_sw_version = self.release_data.metadata[release_id]["sw_version"] + release_sw_version = utils.get_major_release_version( + self.release_data.metadata[release_id]["sw_version"]) # Need to support delete of older centos patches (metadata) from upgrades. # todo(abailey): do we need to be concerned about this since this component is new. @@ -1775,6 +1776,7 @@ class PatchController(PatchService): self.interim_state[release] = list(self.hosts) elif operation == "remove": + removed = False deployment_list = self.release_apply_remove_order(deployment, running_sw_version) msg = "Deploy start order for remove operation: %s" % ",".join(deployment_list) LOG.info(msg) @@ -1829,6 +1831,7 @@ class PatchController(PatchService): self.run_semantic_check(constants.SEMANTIC_PREREMOVE, deployment_list) for release in deployment_list: + removed = True msg = "Removing release: %s" % release LOG.info(msg) audit_log_info(msg) @@ -1865,10 +1868,6 @@ class PatchController(PatchService): metadata_dir = DEPLOY_STATE_METADATA_DIR_DICT[deploystate] shutil.move("%s/%s-metadata.xml" % (metadata_dir, release), "%s/%s-metadata.xml" % (removing_dir, release)) - deploystate = self.release_data.metadata[deployment]["state"] - metadata_dir = DEPLOY_STATE_METADATA_DIR_DICT[deploystate] - shutil.move("%s/%s-metadata.xml" % (metadata_dir, deployment), - "%s/%s-metadata.xml" % (deploying_start_dir, deployment)) msg_info += "%s has been removed from the repo\n" % release except shutil.Error: msg = "Failed to move the metadata for %s" % release @@ -1878,10 +1877,8 @@ class PatchController(PatchService): # update state if len(self.hosts) > 0: self.release_data.metadata[release]["state"] = constants.REMOVING - self.release_data.metadata[deployment]["state"] = constants.DEPLOYING_START else: self.release_data.metadata[release]["state"] = constants.UNKNOWN - self.release_data.metadata[deployment]["state"] = constants.UNKNOWN # only update lastest_feed_commit if it is an ostree patch if self.release_data.contents[release].get("base") is not None: @@ -1892,6 +1889,23 @@ class PatchController(PatchService): with self.hosts_lock: self.interim_state[release] = list(self.hosts) + if removed: + try: + metadata_dir = DEPLOY_STATE_METADATA_DIR_DICT[deploystate] + shutil.move("%s/%s-metadata.xml" % (metadata_dir, deployment), + "%s/%s-metadata.xml" % (deploying_start_dir, deployment)) + msg_info += "Deployment started for %s\n" % deployment + except shutil.Error: + msg = "Failed to move the metadata for %s" % deployment + LOG.exception(msg) + raise MetadataFail(msg) + + # update state + if len(self.hosts) > 0: + self.release_data.metadata[deployment]["state"] = constants.DEPLOYING_START + else: + self.release_data.metadata[deployment]["state"] = constants.UNKNOWN + return dict(info=msg_info, warning=msg_warning, error=msg_error) def software_deploy_complete_api(self, release: str) -> dict: diff --git a/software/software/software_functions.py b/software/software/software_functions.py index 92396410..af2b1109 100644 --- a/software/software/software_functions.py +++ b/software/software/software_functions.py @@ -29,6 +29,7 @@ from software.exceptions import ReleaseMismatchFailure from software.exceptions import SoftwareFail import software.constants as constants +import software.utils as utils try: # The tsconfig module is only available at runtime @@ -347,7 +348,8 @@ class ReleaseData(object): else: self.metadata[release_id]["reboot_required"] = "N" - release_sw_version = self.metadata[release_id]["sw_version"] + release_sw_version = utils.get_major_release_version( + self.metadata[release_id]["sw_version"]) global package_dir if release_sw_version not in package_dir: package_dir[release_sw_version] = "%s/%s" % (root_package_dir, release_sw_version) @@ -835,9 +837,10 @@ class PatchFile(object): if not metadata_only and base_pkgdata is not None: # Run version validation tests first - patch_sw_version = thispatch.metadata[patch_id]["sw_version"] + patch_sw_version = utils.get_major_release_version( + thispatch.metadata[patch_id]["sw_version"]) if not base_pkgdata.check_release(patch_sw_version): - msg = "Patch %s software release (%s) is not installed" % (patch_id, patch_sw_version) + msg = "Software version %s for release %s is not installed" % (patch_sw_version, patch_id) LOG.exception(msg) raise ReleaseValidationFailure(msg) @@ -849,7 +852,8 @@ class PatchFile(object): LOG.exception(msg) raise ReleaseMismatchFailure(msg) - patch_sw_version = thispatch.metadata[patch_id]["sw_version"] + patch_sw_version = utils.get_major_release_version( + thispatch.metadata[patch_id]["sw_version"]) abs_ostree_tar_dir = package_dir[patch_sw_version] if not os.path.exists(abs_ostree_tar_dir): os.makedirs(abs_ostree_tar_dir)