From 3c90e3b949c5533feee25efedda114376f43a0ff Mon Sep 17 00:00:00 2001 From: jgauld Date: Mon, 19 Apr 2021 17:21:09 +0000 Subject: [PATCH] Add lifecycle hook to allow to_app application-update semantic checking This adds new lifecycle update operation so that a semantic check lifecycle step is run against the "to" application during application-update. The application specific lifecycle code requires a custom semantic check using the new hook (e.g., similar to the following): if hook_info.lifecycle_type == constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK: if hook_info.operation == constants.APP_UPDATE_OP: if hook_info[LifecycleConstants.EXTRA].get(LifecycleConstants.TO_APP, False): return self.update_check(app_op._dbapi, app) Testing: * VirtualBox: AIO-SX * Created example application changes for platform-integ-apps using semantic check shown above, and prototype update_check() routine. * Tested the following for both pass and fail semantic check cases: system application-update platform-integ-apps-1.0-29.tgz * Tested that apps on the application-update are okay on an upgrade, as invoked in upgrade-scripts/65-k8s-app-upgrade.sh. i.e., system upgrade-activate Semantic check passes, update proceeds to 1.0-29 "to" version, the 1.0-27 "from" version is cleaned up. Semantic check fails, application recovery proceeds to "from" version, the 1.0-29 "to" version is cleaned up. Example when semantic check fails, system application-list | platform-integ-apps | 1.0-27 | platform-integration-manifest | manifest.yaml \ | applied | Application update from version 1.0-27 to version 1.0-29 aborted. \ Application recover to version 1.0-27 completed. Please check logs for details sysinv.log sysinv 2021-04-19 09:32:53.422 3810926 INFO sysinv.conductor.kube_app [-] \ Starting recover Application platform-integ-apps from version: 1.0-29 to version: 1.0-27 Story: 2008829 Task: 42311 Signed-off-by: jgauld Change-Id: If0787e3e3806bdf5dc175fde64ac63e1f38fd852 --- .../sysinv/api/controllers/v1/kube_app.py | 2 ++ .../sysinv/sysinv/conductor/kube_app.py | 20 +++++++++++++++++++ .../sysinv/sysinv/helm/lifecycle_constants.py | 2 ++ 3 files changed, 24 insertions(+) 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 bd8eec1da9..14e220c1a3 100644 --- a/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/kube_app.py +++ b/sysinv/sysinv/sysinv/sysinv/api/controllers/v1/kube_app.py @@ -23,6 +23,7 @@ from sysinv.common import constants from sysinv.common import exception from sysinv.common import utils as cutils from sysinv.common import kubernetes +from sysinv.helm.lifecycle_constants import LifecycleConstants from sysinv.helm.lifecycle_hook import LifecycleHookInfo from sysinv.openstack.common.rpc import common as rpc_common import cgcs_patch.constants as patch_constants @@ -415,6 +416,7 @@ class KubeAppController(rest.RestController): constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK, constants.APP_LIFECYCLE_TIMING_PRE, constants.APP_UPDATE_OP) + lifecycle_hook_info[LifecycleConstants.EXTRA][LifecycleConstants.FROM_APP] = True self._app_lifecycle_actions(applied_app, lifecycle_hook_info) except Exception as e: diff --git a/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py b/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py index 7acded1843..cfb51e1f37 100644 --- a/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py +++ b/sysinv/sysinv/sysinv/sysinv/conductor/kube_app.py @@ -2457,6 +2457,26 @@ class AppOperator(object): lifecycle_hook_info_app_upload=lifecycle_hook_info_app_update) lifecycle_hook_info_app_update.operation = constants.APP_UPDATE_OP + # Semantic checking for N+1 app + try: + lifecycle_hook_info = copy.deepcopy(lifecycle_hook_info_app_update) + lifecycle_hook_info.lifecycle_type = constants.APP_LIFECYCLE_TYPE_SEMANTIC_CHECK + lifecycle_hook_info[LifecycleConstants.EXTRA][LifecycleConstants.TO_APP] = True + + self.app_lifecycle_actions(None, None, to_rpc_app, lifecycle_hook_info) + except exception.LifecycleSemanticCheckException as e: + LOG.info("App {} rejected operation {} for reason: {}" + "".format(to_app.name, constants.APP_UPDATE_OP, str(e))) + # lifecycle hooks not used in perform_app_recover + return self._perform_app_recover(from_app, to_app, + armada_process_required=False) + except Exception as e: + LOG.error("App {} operation {} semantic check error: {}" + "".format(to_app.name, constants.APP_UPDATE_OP, str(e))) + # lifecycle hooks not used in perform_app_recover + return self._perform_app_recover(from_app, to_app, + armada_process_required=False) + self.load_application_metadata_from_file(to_rpc_app) # Check whether the new application is compatible with the current k8s version diff --git a/sysinv/sysinv/sysinv/sysinv/helm/lifecycle_constants.py b/sysinv/sysinv/sysinv/sysinv/helm/lifecycle_constants.py index c1f9c4c1b9..960c9f6724 100644 --- a/sysinv/sysinv/sysinv/sysinv/helm/lifecycle_constants.py +++ b/sysinv/sysinv/sysinv/sysinv/helm/lifecycle_constants.py @@ -25,3 +25,5 @@ class LifecycleConstants(object): TRIGGER_DELTA_FIELDS = 'delta_fields' ACTION = 'action' APP_STATUS = 'app_status' + FROM_APP = 'from_app' + TO_APP = 'to_app'