distcloud/distributedcloud/dcmanager/tests/unit/manager/states/upgrade/test_installing_license.py
albailey 5e5c416a9b Implement import-load and starting-upgrade strategy states
This commit allows the state machine to be defined through an
ordered list of states. The states are mapped to by a dictionary
to state handler classes.

This greatly simplifies the software upgrade orch thread so that it
can be refactored in the future to share functionality with other orch
thread strategy types.

The following states have been implemented:
 - 'importing load'
 - 'starting upgrade'
 - 'activating upgrade'
 - 'completing upgrade'

The 'installing license' state now uses this design pattern.
Its functionality and unit tests are now in their own files.

The 'unlocking' state requires additional changes for the
'activating' and 'completing' states to pass.

Change-Id: Iedc40bdea406461dd4c2ce3887a37be6ec3c999f
Story: 2007403
Task: 40001
Signed-off-by: albailey <Al.Bailey@windriver.com>
2020-06-09 15:34:27 -05:00

159 lines
6.1 KiB
Python

#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import mock
from dcmanager.common import consts
from dcmanager.tests.unit.manager.states.upgrade.test_base \
import TestSwUpgradeState
MISSING_LICENSE_RESPONSE = {
u'content': u'',
u'error': u'License file not found. A license may not have been installed.'
}
LICENSE_VALID_RESPONSE = {
u'content': u'A valid license',
u'error': u''
}
ALTERNATE_LICENSE_RESPONSE = {
u'content': u'A different valid license',
u'error': u''
}
class TestSwUpgradeInstallingLicenseStage(TestSwUpgradeState):
def setUp(self):
super(TestSwUpgradeInstallingLicenseStage, self).setUp()
# next state after installing a license is 'importing load'
self.on_success_state = consts.STRATEGY_STATE_IMPORTING_LOAD
# Add the strategy_step state being processed by this unit test
self.strategy_step = \
self.setup_strategy_step(consts.STRATEGY_STATE_INSTALLING_LICENSE)
# Add mock API endpoints for sysinv client calls invcked by this state
self.sysinv_client.get_license = mock.MagicMock()
self.sysinv_client.install_license = mock.MagicMock()
def test_upgrade_subcloud_license_install_failure(self):
"""Test the installing license step where the install fails.
The system controller has a license, but the API call to install on the
subcloud fails.
"""
# Order of get_license calls:
# first license query is to system controller
# second license query is to subcloud (should be missing)
self.sysinv_client.get_license.side_effect = [LICENSE_VALID_RESPONSE,
MISSING_LICENSE_RESPONSE]
# Simulate a license install failure on the subcloud
self.sysinv_client.install_license.return_value = \
MISSING_LICENSE_RESPONSE
# invoke the strategy state operation on the orch thread
self.worker.perform_state_action(self.strategy_step)
# verify the license install was invoked
self.sysinv_client.install_license.assert_called()
# Verify a install_license failure leads to a state failure
self.assert_step_updated(self.strategy_step.subcloud_id,
consts.STRATEGY_STATE_FAILED)
def test_upgrade_subcloud_license_install_success(self):
"""Test the install license step succeeds.
The license will be installed on the subcloud when system controller
has a license, the subcloud does not have a license, and the API call
succeeds.
"""
# Order of get_license calls:
# first license query is to system controller
# second license query is to subcloud (should be missing)
self.sysinv_client.get_license.side_effect = [LICENSE_VALID_RESPONSE,
MISSING_LICENSE_RESPONSE]
# A license install should return a success
self.sysinv_client.install_license.return_value = \
LICENSE_VALID_RESPONSE
# invoke the strategy state operation on the orch thread
self.worker.perform_state_action(self.strategy_step)
# verify the license install was invoked
self.sysinv_client.install_license.assert_called()
# On success, the next state after installing license is importing load
self.assert_step_updated(self.strategy_step.subcloud_id,
self.on_success_state)
def test_upgrade_subcloud_license_skip_existing(self):
"""Test the install license step skipped due to license up to date"""
# Order of get_license calls:
# first license query is to system controller
# second license query is to subcloud
self.sysinv_client.get_license.side_effect = [LICENSE_VALID_RESPONSE,
LICENSE_VALID_RESPONSE]
# invoke the strategy state operation on the orch thread
self.worker.perform_state_action(self.strategy_step)
# A license install should not have been attempted due to the license
# already being up to date
self.sysinv_client.install_license.assert_not_called()
# On success, the next state after installing license is importing load
self.assert_step_updated(self.strategy_step.subcloud_id,
self.on_success_state)
def test_upgrade_subcloud_license_overrides_mismatched_license(self):
"""Test the install license overrides a mismatched license"""
# Order of get_license calls:
# first license query is to system controller
# second license query is to subcloud (should be valid but different)
self.sysinv_client.get_license.side_effect = \
[LICENSE_VALID_RESPONSE,
ALTERNATE_LICENSE_RESPONSE]
# A license install should return a success
self.sysinv_client.install_license.return_value = \
LICENSE_VALID_RESPONSE
# invoke the strategy state operation on the orch thread
self.worker.perform_state_action(self.strategy_step)
# verify the license install was invoked
self.sysinv_client.install_license.assert_called()
# Verify it successfully moves to the next step
self.assert_step_updated(self.strategy_step.subcloud_id,
self.on_success_state)
def test_upgrade_subcloud_license_skip_when_no_sys_controller_lic(self):
"""Test license install skipped when no license on system controller."""
# Only makes one query: to system controller
self.sysinv_client.get_license.return_value = MISSING_LICENSE_RESPONSE
# invoke the strategy state operation on the orch thread
self.worker.perform_state_action(self.strategy_step)
# Should skip install_license API call
self.sysinv_client.install_license.assert_not_called()
# Verify it successfully moves to the next step
self.assert_step_updated(self.strategy_step.subcloud_id,
self.on_success_state)