distcloud/distributedcloud/dcmanager/orchestrator/states/prestage/states.py

175 lines
6.7 KiB
Python

#
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import abc
from oslo_log import log as logging
from dcmanager.common import consts
from dcmanager.common import exceptions
from dcmanager.common import prestage
from dcmanager.common import utils
from dcmanager.db import api as db_api
from dcmanager.orchestrator.states.base import BaseState
LOG = logging.getLogger(__name__)
class PrestageState(BaseState):
"""Perform prepare operation"""
def __init__(self, next_state, region_name):
super(PrestageState, self).__init__(
next_state=next_state, region_name=region_name)
@abc.abstractmethod
def _do_state_action(self, strategy_step):
pass
def perform_state_action(self, strategy_step):
"""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
# state machine can proceed to the next state
return self.next_state
class PrestagePreCheckState(PrestageState):
"""Perform pre check operations"""
def __init__(self, region_name):
super(PrestagePreCheckState, self).__init__(
next_state=consts.STRATEGY_STATE_PRESTAGE_PREPARE,
region_name=region_name)
@utils.synchronized('prestage-update-extra-args', external=True)
def _update_oam_floating_ip(self, strategy_step, oam_floating_ip):
# refresh the extra_args
extra_args = utils.get_sw_update_strategy_extra_args(self.context)
if 'oam_floating_ip_dict' in extra_args:
LOG.debug("Updating oam_floating_ip_dict: %s: %s",
strategy_step.subcloud.name, oam_floating_ip)
oam_floating_ip_dict = extra_args['oam_floating_ip_dict']
oam_floating_ip_dict[strategy_step.subcloud.name] \
= oam_floating_ip
else:
LOG.debug("Creating oam_floating_ip_dict: %s: %s",
strategy_step.subcloud.name, oam_floating_ip)
oam_floating_ip_dict = {
strategy_step.subcloud.name: oam_floating_ip
}
db_api.sw_update_strategy_update(
self.context, state=None, update_type=None,
additional_args={'oam_floating_ip_dict': oam_floating_ip_dict})
def _do_state_action(self, strategy_step):
extra_args = utils.get_sw_update_strategy_extra_args(self.context)
if extra_args is None:
message = "Prestage pre-check: missing all mandatory arguments"
self.error_log(strategy_step, message)
raise Exception(message)
payload = {
'sysadmin_password': extra_args['sysadmin_password'],
'force': extra_args['force']
}
try:
oam_floating_ip = prestage.validate_prestage(
strategy_step.subcloud, payload)
self._update_oam_floating_ip(strategy_step, oam_floating_ip)
if strategy_step.stage == 1:
# Note: this cleanup happens for every subcloud, but they are all
# processed before moving on to the next strategy step
# TODO(kmacleod) although this is a quick check, it is
# synchronized, so we may want to figure out a better
# way to only run this once
prestage.cleanup_failed_preparation()
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:
raise exceptions.StrategySkippedException(details=str(ex))
self.error_log(strategy_step, "Pre-check failed: %s" % ex)
raise
else:
self.info_log(strategy_step, "Pre-check pass")
class PrestagePrepareState(PrestageState):
"""Perform prepare operation"""
def __init__(self, region_name):
super(PrestagePrepareState, self).__init__(
next_state=consts.STRATEGY_STATE_PRESTAGE_PACKAGES,
region_name=region_name)
def _do_state_action(self, strategy_step):
extra_args = utils.get_sw_update_strategy_extra_args(self.context)
payload = {
'sysadmin_password': extra_args['sysadmin_password'],
'oam_floating_ip':
extra_args['oam_floating_ip_dict'][strategy_step.subcloud.name],
'force': extra_args['force']
}
prestage.prestage_prepare(self.context, strategy_step.subcloud, payload)
self.info_log(strategy_step, "Prepare finished")
class PrestagePackagesState(PrestageState):
"""Perform prestage packages operation"""
def __init__(self, region_name):
super(PrestagePackagesState, self).__init__(
next_state=consts.STRATEGY_STATE_PRESTAGE_IMAGES,
region_name=region_name)
def _do_state_action(self, strategy_step):
extra_args = utils.get_sw_update_strategy_extra_args(self.context)
payload = {
'sysadmin_password': extra_args['sysadmin_password'],
'oam_floating_ip':
extra_args['oam_floating_ip_dict'][strategy_step.subcloud.name],
'force': extra_args['force']
}
prestage.prestage_packages(self.context,
strategy_step.subcloud, payload)
self.info_log(strategy_step, "Packages finished")
class PrestageImagesState(PrestageState):
"""Perform prestage images operation"""
def __init__(self, region_name):
super(PrestageImagesState, self).__init__(
next_state=consts.STRATEGY_STATE_COMPLETE,
region_name=region_name)
def _do_state_action(self, strategy_step):
extra_args = utils.get_sw_update_strategy_extra_args(self.context)
payload = {
'sysadmin_password': extra_args['sysadmin_password'],
'oam_floating_ip':
extra_args['oam_floating_ip_dict'][strategy_step.subcloud.name],
'force': extra_args['force']
}
prestage.prestage_images(self.context, strategy_step.subcloud, payload)
self.info_log(strategy_step, "Images finished")
prestage.prestage_complete(self.context, strategy_step.subcloud.id)