Hugo Brito b3d206781b Improve DC VIM strategy create/apply error handling
This commit updates subcloud's error_description with the error
returned by the software API during VIM strategy create and apply.

- Created two custom exceptions for handling these errors.
- Clean up error_description in strategy creation.

Note: This also updated the timeout values of software API.

Test Plan:
PASS - Apply a sw-deploy-strategy and force an error in the
deploy precheck command.
  - Apply should fail in the `create VIM strategy` state
  - dcmanager subcloud errors should be updated
PASS - Apply a sw-deploy-strategy and force an error in the
deploy start command.
  - Apply should fail in `apply VIM strategy` state
  - dcmanager subcloud errors should be updated
PASS - Create a dcmanager sw-deploy-strategy with subcloud errors.
  - Strategy created and subcloud errors should be `No errors present`.

Story: 2010676
Task: 50644

Change-Id: Ib0b0b586d90093088a6af96e5d630e3fe04fd3f7
Signed-off-by: Hugo Brito <hugo.brito@windriver.com>
2024-07-30 13:59:53 -03:00

150 lines
5.2 KiB
Python

#
# Copyright (c) 2023-2024 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
from dccommon.drivers.openstack import software_v1
from dcmanager.common import consts
from dcmanager.common import exceptions
from dcmanager.orchestrator.states.base import BaseState
from dcmanager.orchestrator.states.software.cache.cache_specifications import (
REGION_ONE_RELEASE_USM_CACHE_TYPE,
)
class FinishStrategyState(BaseState):
"""Finish Software Strategy software orchestration state"""
def __init__(self, region_name):
super().__init__(
next_state=consts.STRATEGY_STATE_COMPLETE,
region_name=region_name,
)
def perform_state_action(self, strategy_step):
"""Finish Software Strategy"""
self.info_log(strategy_step, "Finishing software strategy")
regionone_deployed_releases = self._read_from_cache(
REGION_ONE_RELEASE_USM_CACHE_TYPE, state=software_v1.DEPLOYED
)
self.debug_log(
strategy_step,
f"regionone_deployed_releases: {regionone_deployed_releases}",
)
try:
software_client = self.get_software_client(self.region_name)
subcloud_releases = software_client.list()
except Exception:
message = "Cannot retrieve subcloud releases. Please see logs for details."
self.exception_log(strategy_step, message)
raise exceptions.SoftwareListFailedException(
subcloud=strategy_step.subcloud.name,
details=message,
)
self.debug_log(strategy_step, f"Releases for subcloud: {subcloud_releases}")
# For this subcloud, determine which releases should be committed,
# which should be deleted and which should finish the deploy.
releases_to_delete = [
release["release_id"]
for release in subcloud_releases
if release["state"] in (software_v1.AVAILABLE, software_v1.UNAVAILABLE)
]
# TODO(nicodemos): Update releases_to_commit and handle it after
# `software commit` is implemented
releases_to_commit = []
releases_to_deploy_delete = [
release["release_id"]
for release in subcloud_releases
if release["state"] == software_v1.DEPLOYING
]
if releases_to_delete:
self._handle_release_delete(
strategy_step, software_client, releases_to_delete
)
if self.stopped():
raise exceptions.StrategyStoppedException()
if releases_to_commit:
self._handle_deploy_commit(
strategy_step, software_client, releases_to_commit
)
if releases_to_deploy_delete:
self._handle_deploy_delete(
strategy_step,
software_client,
releases_to_deploy_delete,
regionone_deployed_releases,
)
return self.next_state
def _handle_release_delete(
self, strategy_step, software_client, releases_to_delete
):
self.info_log(strategy_step, f"Deleting releases {releases_to_delete}")
try:
software_client.delete(releases_to_delete)
except Exception:
message = (
"Cannot delete releases from subcloud. Please see logs for details."
)
self.exception_log(strategy_step, message)
raise exceptions.SoftwareDeleteFailedException(
subcloud=strategy_step.subcloud.name,
details=message,
)
def _handle_deploy_commit(self, strategy_step, software_client, releases_to_commit):
raise NotImplementedError()
# If there are releases in deploying state and it's deployed in the regionone,
# they should be finished executing the deploy delete operation.
def _handle_deploy_delete(
self,
strategy_step,
software_client,
releases_to_deploy_delete,
regionone_deployed_releases,
):
if not any(
release_id == release_regionone["release_id"]
for release_id in releases_to_deploy_delete
for release_regionone in regionone_deployed_releases
):
message = (
f"Deploying release found on subcloud {strategy_step.subcloud.name} "
"and is not deployed in System Controller. Aborting."
)
self.error_log(strategy_step, message)
raise exceptions.SoftwareDeployDeleteFailedException(
subcloud=strategy_step.subcloud.name,
details=message,
)
self.info_log(
strategy_step,
f"Finishing releases {releases_to_deploy_delete} to subcloud",
)
try:
software_client.deploy_delete()
except Exception:
message = (
"Cannot finish deploy delete on subcloud. Please see logs for details."
)
self.exception_log(strategy_step, message)
raise exceptions.SoftwareDeployDeleteFailedException(
subcloud=strategy_step.subcloud.name,
details=message,
)