diff --git a/api-ref/source/parameters.yaml b/api-ref/source/parameters.yaml index 94963b6d8..92d370284 100644 --- a/api-ref/source/parameters.yaml +++ b/api-ref/source/parameters.yaml @@ -22,7 +22,8 @@ subcloud_uri: sw_update_strategy_type: description: | Filter to query a particular type of update strategy if it exists. - One of: `firmware`, `kube-rootca-update`, `kubernetes`, `patch`, `upgrade` + One of: `firmware`, `kube-rootca-update`, `kubernetes`, `patch`, + `prestage`, or `upgrade`. in: path required: false type: string diff --git a/distributedcloud/dcmanager/common/exceptions.py b/distributedcloud/dcmanager/common/exceptions.py index f570a239e..8f5a503c6 100644 --- a/distributedcloud/dcmanager/common/exceptions.py +++ b/distributedcloud/dcmanager/common/exceptions.py @@ -229,5 +229,12 @@ class StrategyStepNameNotFound(NotFound): message = _("StrategyStep with name %(name)s doesn't exist.") +class StrategySkippedException(DCManagerException): + def __init__(self, details): + self.details = details + self.message = _(details) + super(StrategySkippedException, self).__init__() + + class StrategyStoppedException(DCManagerException): message = _("Strategy has been stopped") diff --git a/distributedcloud/dcmanager/orchestrator/orch_thread.py b/distributedcloud/dcmanager/orchestrator/orch_thread.py index e4dc1592a..480247147 100644 --- a/distributedcloud/dcmanager/orchestrator/orch_thread.py +++ b/distributedcloud/dcmanager/orchestrator/orch_thread.py @@ -122,8 +122,12 @@ class OrchThread(threading.Thread): @staticmethod def format_update_details(last_state, info): - # include the last state, since the current state is likely 'failed' - details = "%s: %s" % (last_state, info) + # Optionally include the last state, since the current state + # is likely 'failed' + if last_state: + details = "%s: %s" % (last_state, info) + else: + details = str(info) # details cannot exceed 255 chars. truncate and add '..' if len(details) > 255: details = details[:253] + '..' @@ -535,14 +539,26 @@ class OrchThread(threading.Thread): self.strategy_step_update(strategy_step.subcloud_id, state=next_state, details="") - except Exception as e: + except exceptions.StrategySkippedException as ex: + LOG.info("(%s) Skipping subcloud, Stage: %s, State: %s, Subcloud: %s" + % (self.update_type, + strategy_step.stage, + strategy_step.state, + self.get_region_name(strategy_step))) + # Transition immediately to complete. Update the details to show + # that this subcloud has been skipped + details = self.format_update_details(None, str(ex)) + self.strategy_step_update(strategy_step.subcloud_id, + state=consts.STRATEGY_STATE_COMPLETE, + details=details) + except Exception as ex: # Catch ALL exceptions and set the strategy to failed LOG.exception("(%s) Failed! Stage: %s, State: %s, Subcloud: %s" % (self.update_type, strategy_step.stage, strategy_step.state, self.get_region_name(strategy_step))) - details = self.format_update_details(strategy_step.state, str(e)) + details = self.format_update_details(strategy_step.state, str(ex)) self.strategy_step_update(strategy_step.subcloud_id, state=consts.STRATEGY_STATE_FAILED, details=details) diff --git a/distributedcloud/dcmanager/orchestrator/states/prestage/states.py b/distributedcloud/dcmanager/orchestrator/states/prestage/states.py index 6468b4fcd..c3ee8ed2f 100644 --- a/distributedcloud/dcmanager/orchestrator/states/prestage/states.py +++ b/distributedcloud/dcmanager/orchestrator/states/prestage/states.py @@ -32,7 +32,12 @@ class PrestageState(BaseState): """Wrapper to ensure proper error handling""" try: self._do_state_action(strategy_step) - + except exceptions.StrategySkippedException: + # Move deploy_status back to complete (nothing has changed) + db_api.subcloud_update( + self.context, strategy_step.subcloud.id, + deploy_status=consts.DEPLOY_STATE_DONE) + raise except Exception: prestage.prestage_fail(self.context, strategy_step.subcloud.id) raise @@ -95,19 +100,14 @@ class PrestagePreCheckState(PrestageState): prestage.prestage_start(self.context, strategy_step.subcloud.id) except exceptions.PrestagePreCheckFailedException as ex: + # We've either failed precheck or we want to skip this subcloud. + # Either way, we'll re-raise up to the base class for status + # update, and then let OrchThread take it from here if ex.orch_skip: - self.info_log(strategy_step, - "Pre-check: skipping subcloud: %s" % ex) + raise exceptions.StrategySkippedException(details=str(ex)) - # Update the details to show that this subcloud has been skipped - db_api.strategy_step_update(self.context, - strategy_step.subcloud.id, - details=str(ex)) - - self.override_next_state(consts.STRATEGY_STATE_COMPLETE) - else: - self.info_log(strategy_step, "Pre-check failed: %s" % ex) - raise + self.error_log(strategy_step, "Pre-check failed: %s" % ex) + raise else: self.info_log(strategy_step, "Pre-check pass")