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

167 lines
6.5 KiB
Python

#
# Copyright (c) 2022-2024 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 prestage_status back to None (nothing has changed)
db_api.subcloud_update(
self.context, strategy_step.subcloud.id,
prestage_status=None)
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_PACKAGES,
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']
}
if extra_args.get(consts.PRESTAGE_SOFTWARE_VERSION):
payload.update({consts.PRESTAGE_REQUEST_RELEASE:
extra_args.get(consts.PRESTAGE_SOFTWARE_VERSION)})
try:
oam_floating_ip = prestage.validate_prestage(
strategy_step.subcloud, payload)
self._update_oam_floating_ip(strategy_step, oam_floating_ip)
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 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']
}
if extra_args.get(consts.PRESTAGE_SOFTWARE_VERSION):
payload.update({consts.PRESTAGE_REQUEST_RELEASE:
extra_args.get(consts.PRESTAGE_SOFTWARE_VERSION)})
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):
log_file = utils.get_subcloud_ansible_log_file(
strategy_step.subcloud.name)
# Get the prestage versions from the ansible playbook logs
# generated by the previous step - prestage packages.
prestage_versions = utils.get_msg_output_info(
log_file,
prestage.PRINT_PRESTAGE_VERSIONS_TASK,
prestage.PRESTAGE_VERSIONS_KEY_STR)
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']
}
if extra_args.get(consts.PRESTAGE_SOFTWARE_VERSION):
payload.update({consts.PRESTAGE_REQUEST_RELEASE:
extra_args.get(consts.PRESTAGE_SOFTWARE_VERSION)})
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, prestage_versions)