diff --git a/sysinv/cgts-client/cgts-client/cgtsclient/v1/app_shell.py b/sysinv/cgts-client/cgts-client/cgtsclient/v1/app_shell.py index 586905d2de..45440c69d1 100644 --- a/sysinv/cgts-client/cgts-client/cgtsclient/v1/app_shell.py +++ b/sysinv/cgts-client/cgts-client/cgtsclient/v1/app_shell.py @@ -103,9 +103,19 @@ def do_application_show(cc, args): @utils.arg('-v', '--app-version', metavar='', help='Version of the application') +@utils.arg('-i', '--images', + action='store_true', + default=False, + help='Save application images in the registry as part of app' + ' upload. This option is normally used in the System' + ' Controller of a Distributed Cloud system to also upload' + ' the application images to the central registry when the' + ' app is registered within the system') def do_application_upload(cc, args): """Upload application Helm chart(s) and manifest""" data = _application_check(args) + if args.images: + data.update({'images': True}) if not _is_url(data["tarfile"]): try: diff --git a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/kube_app.py b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/kube_app.py index 2d0ca2538b..cb58bf49d7 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/kube_app.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/kube_app.py @@ -207,6 +207,7 @@ class KubeAppController(rest.RestController): tarfile_binary = body.get('binary_data', '') name = body.get('name', '') version = body.get('app_version', '') + images = body.get('images', False) if not cutils.is_url(tarfile_path) and not os.path.exists(tarfile_path): path_tarballs = '/tmp/tarball_uploads' @@ -255,7 +256,8 @@ class KubeAppController(rest.RestController): pecan.request.rpcapi.perform_app_upload(pecan.request.context, new_app, tarfile_path, - lifecycle_hook_info=lifecycle_hook_info) + lifecycle_hook_info=lifecycle_hook_info, + images=images) return KubeApp.convert_with_links(new_app) @cutils.synchronized(LOCK_NAME) diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py b/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py index 52deb5e90c..345580f6ed 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py @@ -1721,7 +1721,7 @@ class AppOperator(object): LOG.error("Application rollback aborted!") return False - def perform_app_upload(self, rpc_app, tarfile, lifecycle_hook_info_app_upload): + def perform_app_upload(self, rpc_app, tarfile, lifecycle_hook_info_app_upload, images=False): """Process application upload request This method validates the application manifest. If Helm charts are @@ -1732,6 +1732,7 @@ class AppOperator(object): :param rpc_app: application object in the RPC request :param tarfile: location of application tarfile :param lifecycle_hook_info_app_upload: LifecycleHookInfo object + :param images: save application images in the registry as part of app upload """ @@ -1808,6 +1809,17 @@ class AppOperator(object): # prior to scraping chart/system/armada overrides for images self._save_images_list(app) + if images: + # We need to download the images at upload_app so that subclouds + # may use the distributed cloud registry + self._update_app_status( + app, new_progress=constants.APP_PROGRESS_DOWNLOAD_IMAGES) + + if AppOperator.is_app_aborted(app.name): + raise exception.KubeAppAbort() + + self.download_images(app) + if app.patch_dependencies: self._utils._patch_report_app_dependencies( app.name + '-' + app.version, app.patch_dependencies) diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py index aaa6e3700f..74c7cefe9f 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/manager.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/manager.py @@ -12739,18 +12739,20 @@ class ConductorManager(service.PeriodicService): LOG.exception(ex) return (False, None) - def perform_app_upload(self, context, rpc_app, tarfile, lifecycle_hook_info_app_upload): + def perform_app_upload(self, context, rpc_app, tarfile, + lifecycle_hook_info_app_upload, images=False): """Handling of application upload request (via AppOperator) :param context: request context. :param rpc_app: data object provided in the rpc request :param tarfile: location of the application tarfile to be exracted :param lifecycle_hook_info_app_upload: LifecycleHookInfo object + :param images: save application images in the registry as part of app upload """ lifecycle_hook_info_app_upload.operation = constants.APP_UPLOAD_OP - self._app.perform_app_upload(rpc_app, tarfile, lifecycle_hook_info_app_upload) + self._app.perform_app_upload(rpc_app, tarfile, lifecycle_hook_info_app_upload, images) self._app.load_application_metadata_from_file(rpc_app) # Perform post upload operation actions diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py b/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py index a3412185f2..79830719dc 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/rpcapi.py @@ -1892,20 +1892,22 @@ class ConductorAPI(sysinv.openstack.common.rpc.proxy.RpcProxy): return self.call(context, self.make_msg('backup_restore_lifecycle_actions', operation=operation, success=success)) - def perform_app_upload(self, context, rpc_app, tarfile, lifecycle_hook_info): + def perform_app_upload(self, context, rpc_app, tarfile, lifecycle_hook_info, images=False): """Handle application upload request :param context: request context. :param rpc_app: data object provided in the rpc request :param tarfile: location of application tarfile to be extracted :param lifecycle_hook_info: LifecycleHookInfo object + :param images: save application images in the registry as part of app upload """ return self.cast(context, self.make_msg('perform_app_upload', rpc_app=rpc_app, tarfile=tarfile, - lifecycle_hook_info_app_upload=lifecycle_hook_info)) + lifecycle_hook_info_app_upload=lifecycle_hook_info, + images=images)) def perform_app_apply(self, context, rpc_app, mode, lifecycle_hook_info): """Handle application apply request