1706 lines
64 KiB
Python
1706 lines
64 KiB
Python
# Copyright (c) 2017-2024 Wind River Systems, Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
#
|
|
|
|
import base64
|
|
import copy
|
|
import mock
|
|
|
|
from oslo_config import cfg
|
|
from oslo_utils import uuidutils
|
|
|
|
from dccommon import consts as dccommon_consts
|
|
from dcmanager.common import consts
|
|
from dcmanager.common import context
|
|
from dcmanager.common import exceptions
|
|
from dcmanager.common import prestage
|
|
from dcmanager.common import utils as cutils
|
|
from dcmanager.db.sqlalchemy import api as db_api
|
|
from dcmanager.orchestrator import sw_update_manager
|
|
|
|
from dcmanager.tests import base
|
|
from dcmanager.tests import utils
|
|
|
|
|
|
OAM_FLOATING_IP = "10.10.10.12"
|
|
CONF = cfg.CONF
|
|
FAKE_ID = "1"
|
|
FAKE_SW_UPDATE_DATA = {
|
|
"type": consts.SW_UPDATE_TYPE_PATCH,
|
|
"subcloud-apply-type": consts.SUBCLOUD_APPLY_TYPE_PARALLEL,
|
|
"max-parallel-subclouds": "2",
|
|
"stop-on-failure": "true",
|
|
"force": "false",
|
|
"state": consts.SW_UPDATE_STATE_INITIAL,
|
|
}
|
|
|
|
FAKE_SW_PRESTAGE_DATA = {
|
|
"type": consts.SW_UPDATE_TYPE_PRESTAGE,
|
|
"subcloud-apply-type": consts.SUBCLOUD_APPLY_TYPE_PARALLEL,
|
|
"max-parallel-subclouds": "2",
|
|
"stop-on-failure": "true",
|
|
"force": "false",
|
|
"state": consts.SW_UPDATE_STATE_INITIAL,
|
|
}
|
|
|
|
FAKE_SW_PATCH_DATA = {
|
|
"type": consts.SW_UPDATE_TYPE_PATCH,
|
|
"subcloud-apply-type": consts.SUBCLOUD_APPLY_TYPE_PARALLEL,
|
|
"max-parallel-subclouds": "2",
|
|
"stop-on-failure": "true",
|
|
"force": "false",
|
|
"state": consts.SW_UPDATE_STATE_INITIAL,
|
|
}
|
|
|
|
health_report_no_mgmt_alarm = "System Health:\n \
|
|
All hosts are provisioned: [Fail]\n \
|
|
1 Unprovisioned hosts\n \
|
|
All hosts are unlocked/enabled: [OK]\n \
|
|
All hosts have current configurations: [OK]\n \
|
|
All hosts are patch current: [OK]\n \
|
|
No alarms: [OK]\n \
|
|
All kubernetes nodes are ready: [OK]\n \
|
|
All kubernetes control plane pods are ready: [OK]"
|
|
|
|
|
|
class Subcloud(object):
|
|
def __init__(self, id, name, group_id, is_managed, is_online):
|
|
self.id = id
|
|
self.name = name
|
|
self.software_version = "12.04"
|
|
self.group_id = group_id
|
|
if is_managed:
|
|
self.management_state = dccommon_consts.MANAGEMENT_MANAGED
|
|
else:
|
|
self.management_state = dccommon_consts.MANAGEMENT_UNMANAGED
|
|
if is_online:
|
|
self.availability_status = dccommon_consts.AVAILABILITY_ONLINE
|
|
else:
|
|
self.availability_status = dccommon_consts.AVAILABILITY_OFFLINE
|
|
|
|
|
|
# All orch_threads can be mocked the same way
|
|
class FakeOrchThread(object):
|
|
def __init__(self):
|
|
# Mock methods that are called in normal execution of this thread
|
|
self.start = mock.MagicMock()
|
|
|
|
|
|
class FakeDCManagerAuditAPI(object):
|
|
def __init__(self):
|
|
self.trigger_patch_audit = mock.MagicMock()
|
|
|
|
|
|
class TestSwUpdateManager(base.DCManagerTestCase):
|
|
@staticmethod
|
|
def create_subcloud(ctxt, name, group_id, is_managed, is_online):
|
|
values = {
|
|
"name": name,
|
|
"description": "subcloud1 description",
|
|
"location": "subcloud1 location",
|
|
"software_version": "18.03",
|
|
"management_subnet": "192.168.101.0/24",
|
|
"management_gateway_ip": "192.168.101.1",
|
|
"management_start_ip": "192.168.101.3",
|
|
"management_end_ip": "192.168.101.4",
|
|
"systemcontroller_gateway_ip": "192.168.204.101",
|
|
'deploy_status': "not-deployed",
|
|
'error_description': 'No errors present',
|
|
'region_name': uuidutils.generate_uuid().replace("-", ""),
|
|
'openstack_installed': False,
|
|
'group_id': group_id,
|
|
'data_install': 'data from install',
|
|
}
|
|
subcloud = db_api.subcloud_create(ctxt, **values)
|
|
if is_managed:
|
|
state = dccommon_consts.MANAGEMENT_MANAGED
|
|
subcloud = db_api.subcloud_update(
|
|
ctxt, subcloud.id, management_state=state
|
|
)
|
|
if is_online:
|
|
status = dccommon_consts.AVAILABILITY_ONLINE
|
|
subcloud = db_api.subcloud_update(
|
|
ctxt, subcloud.id, availability_status=status
|
|
)
|
|
return subcloud
|
|
|
|
@staticmethod
|
|
def create_subcloud_group(ctxt, name, update_apply_type, max_parallel_subclouds):
|
|
values = {
|
|
"name": name,
|
|
"description": "subcloud1 description",
|
|
"update_apply_type": update_apply_type,
|
|
"max_parallel_subclouds": max_parallel_subclouds,
|
|
}
|
|
return db_api.subcloud_group_create(ctxt, **values)
|
|
|
|
@staticmethod
|
|
def update_subcloud_status(ctxt, subcloud_id, endpoint=None, status=None):
|
|
if endpoint:
|
|
endpoint_type = endpoint
|
|
else:
|
|
endpoint_type = dccommon_consts.ENDPOINT_TYPE_PATCHING
|
|
if status:
|
|
sync_status = status
|
|
else:
|
|
sync_status = dccommon_consts.SYNC_STATUS_OUT_OF_SYNC
|
|
|
|
subcloud_status = db_api.subcloud_status_update(
|
|
ctxt, subcloud_id, endpoint_type, sync_status
|
|
)
|
|
return subcloud_status
|
|
|
|
@staticmethod
|
|
def create_strategy(ctxt, strategy_type, state):
|
|
values = {
|
|
"type": strategy_type,
|
|
"subcloud_apply_type": consts.SUBCLOUD_APPLY_TYPE_PARALLEL,
|
|
"max_parallel_subclouds": 2,
|
|
"stop_on_failure": True,
|
|
"state": state,
|
|
}
|
|
return db_api.sw_update_strategy_create(ctxt, **values)
|
|
|
|
@staticmethod
|
|
def create_strategy_step(ctxt, state):
|
|
values = {
|
|
"subcloud_id": 1,
|
|
"stage": 1,
|
|
"state": state,
|
|
"details": "Dummy details",
|
|
}
|
|
return db_api.strategy_step_create(ctxt, **values)
|
|
|
|
def setUp(self):
|
|
super(TestSwUpdateManager, self).setUp()
|
|
# Mock the context
|
|
self.ctxt = utils.dummy_context()
|
|
p = mock.patch.object(context, "get_admin_context")
|
|
self.mock_get_admin_context = p.start()
|
|
self.mock_get_admin_context.return_value = self.ctx
|
|
self.addCleanup(p.stop)
|
|
|
|
# Note: mock where an item is used, not where it comes from
|
|
self.fake_sw_upgrade_orch_thread = FakeOrchThread()
|
|
p = mock.patch.object(sw_update_manager, "SwUpgradeOrchThread")
|
|
self.mock_sw_upgrade_orch_thread = p.start()
|
|
self.mock_sw_upgrade_orch_thread.return_value = (
|
|
self.fake_sw_upgrade_orch_thread
|
|
)
|
|
self.addCleanup(p.stop)
|
|
|
|
self.fake_software_orch_thread = FakeOrchThread()
|
|
p = mock.patch.object(sw_update_manager, "SoftwareOrchThread")
|
|
self.fake_software_orch_thread = p.start()
|
|
self.fake_software_orch_thread.return_value = (
|
|
self.fake_software_orch_thread
|
|
)
|
|
self.addCleanup(p.stop)
|
|
|
|
self.fake_fw_update_orch_thread = FakeOrchThread()
|
|
p = mock.patch.object(sw_update_manager, "FwUpdateOrchThread")
|
|
self.mock_fw_update_orch_thread = p.start()
|
|
self.mock_fw_update_orch_thread.return_value = (
|
|
self.fake_fw_update_orch_thread
|
|
)
|
|
self.addCleanup(p.stop)
|
|
|
|
self.fake_kube_upgrade_orch_thread = FakeOrchThread()
|
|
p = mock.patch.object(sw_update_manager, "KubeUpgradeOrchThread")
|
|
self.mock_kube_upgrade_orch_thread = p.start()
|
|
self.mock_kube_upgrade_orch_thread.return_value = (
|
|
self.fake_kube_upgrade_orch_thread
|
|
)
|
|
self.addCleanup(p.stop)
|
|
|
|
self.fake_kube_rootca_update_orch_thread = FakeOrchThread()
|
|
p = mock.patch.object(sw_update_manager, "KubeRootcaUpdateOrchThread")
|
|
self.mock_kube_rootca_update_orch_thread = p.start()
|
|
self.mock_kube_rootca_update_orch_thread.return_value = (
|
|
self.fake_kube_rootca_update_orch_thread
|
|
)
|
|
self.addCleanup(p.stop)
|
|
|
|
self.fake_prestage_orch_thread = FakeOrchThread()
|
|
p = mock.patch.object(sw_update_manager, "PrestageOrchThread")
|
|
self.mock_prestage_orch_thread = p.start()
|
|
self.mock_prestage_orch_thread.return_value = self.fake_prestage_orch_thread
|
|
self.addCleanup(p.stop)
|
|
|
|
# Mock the dcmanager audit API
|
|
self.fake_dcmanager_audit_api = FakeDCManagerAuditAPI()
|
|
p = mock.patch("dcmanager.audit.rpcapi.ManagerAuditClient")
|
|
self.mock_dcmanager_audit_api = p.start()
|
|
self.mock_dcmanager_audit_api.return_value = self.fake_dcmanager_audit_api
|
|
self.addCleanup(p.stop)
|
|
|
|
# Fake subcloud groups
|
|
# Group 1 exists by default in database with max_parallel 2 and
|
|
# apply_type parallel
|
|
self.fake_group2 = self.create_subcloud_group(
|
|
self.ctxt, "Group2", consts.SUBCLOUD_APPLY_TYPE_SERIAL, 2
|
|
)
|
|
self.fake_group3 = self.create_subcloud_group(
|
|
self.ctxt, "Group3", consts.SUBCLOUD_APPLY_TYPE_PARALLEL, 2
|
|
)
|
|
self.fake_group4 = self.create_subcloud_group(
|
|
self.ctxt, "Group4", consts.SUBCLOUD_APPLY_TYPE_SERIAL, 2
|
|
)
|
|
self.fake_group5 = self.create_subcloud_group(
|
|
self.ctxt, "Group5", consts.SUBCLOUD_APPLY_TYPE_PARALLEL, 2
|
|
)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_init(self, mock_patch_orch_thread):
|
|
um = sw_update_manager.SwUpdateManager()
|
|
self.assertIsNotNone(um)
|
|
self.assertEqual("sw_update_manager", um.service_name)
|
|
self.assertEqual("localhost", um.host)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_no_subclouds(self, mock_patch_orch_thread):
|
|
um = sw_update_manager.SwUpdateManager()
|
|
# No strategy will be created, so it should raise:
|
|
# 'Bad strategy request: Strategy has no steps to apply'
|
|
self.assertRaises(
|
|
exceptions.BadRequest,
|
|
um.create_sw_update_strategy,
|
|
self.ctxt,
|
|
payload=FAKE_SW_UPDATE_DATA,
|
|
)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_for_a_single_group(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# Create fake subclouds and respective status
|
|
# Subcloud1 will be patched
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud1",
|
|
self.fake_group2.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud1.id)
|
|
|
|
# Subcloud2 will not be patched because not managed
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud2",
|
|
self.fake_group2.id,
|
|
is_managed=False,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud2.id)
|
|
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
data["subcloud_group"] = str(self.fake_group2.id)
|
|
um = sw_update_manager.SwUpdateManager()
|
|
response = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Verify strategy was created as expected using group values
|
|
self.assertEqual(response["max-parallel-subclouds"], 1)
|
|
self.assertEqual(
|
|
response["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_SERIAL
|
|
)
|
|
self.assertEqual(response["type"], FAKE_SW_UPDATE_DATA["type"])
|
|
|
|
# Verify strategy step was created as expected
|
|
strategy_steps = db_api.strategy_step_get_all(self.ctx)
|
|
self.assertEqual(strategy_steps[0]["state"], consts.STRATEGY_STATE_INITIAL)
|
|
self.assertEqual(strategy_steps[0]["details"], "")
|
|
self.assertEqual(strategy_steps[0]["subcloud_id"], 1)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_parallel_for_a_single_group(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# Create fake subclouds and respective status
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud1",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud1.id, endpoint=dccommon_consts.ENDPOINT_TYPE_LOAD
|
|
)
|
|
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud2",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud2.id, endpoint=dccommon_consts.ENDPOINT_TYPE_LOAD
|
|
)
|
|
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
data["type"] = consts.SW_UPDATE_TYPE_UPGRADE
|
|
data["subcloud_group"] = str(self.fake_group3.id)
|
|
um = sw_update_manager.SwUpdateManager()
|
|
response = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Verify strategy was created as expected using group values
|
|
self.assertEqual(response["max-parallel-subclouds"], 2)
|
|
self.assertEqual(
|
|
response["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_PARALLEL
|
|
)
|
|
self.assertEqual(response["type"], consts.SW_UPDATE_TYPE_UPGRADE)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [1, 2]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(prestage, "initial_subcloud_validate")
|
|
@mock.patch.object(prestage, "global_prestage_validate")
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_prestage_strategy_parallel_for_a_single_group(
|
|
self,
|
|
mock_patch_orch_thread,
|
|
mock_global_prestage_validate,
|
|
mock_initial_subcloud_validate,
|
|
):
|
|
# Create fake subclouds and respective status
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud1",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud1.id, endpoint=dccommon_consts.ENDPOINT_TYPE_LOAD
|
|
)
|
|
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud2",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud2.id, endpoint=dccommon_consts.ENDPOINT_TYPE_LOAD
|
|
)
|
|
|
|
mock_global_prestage_validate.return_value = None
|
|
mock_initial_subcloud_validate.return_value = None
|
|
|
|
data = copy.copy(FAKE_SW_PRESTAGE_DATA)
|
|
fake_password = (base64.b64encode("testpass".encode("utf-8"))).decode(
|
|
"ascii"
|
|
)
|
|
data["sysadmin_password"] = fake_password
|
|
|
|
data["subcloud_group"] = str(self.fake_group3.id)
|
|
um = sw_update_manager.SwUpdateManager()
|
|
response = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Verify strategy was created as expected using group values
|
|
self.assertEqual(response["max-parallel-subclouds"], 2)
|
|
self.assertEqual(
|
|
response["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_PARALLEL
|
|
)
|
|
self.assertEqual(response["type"], consts.SW_UPDATE_TYPE_PRESTAGE)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [1, 2]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(prestage, "initial_subcloud_validate")
|
|
@mock.patch.object(prestage, "global_prestage_validate")
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_prestage_strategy_load_insync_out_of_sync_unknown_and_no_load(
|
|
self,
|
|
mock_patch_orch_thread,
|
|
mock_global_prestage_validate,
|
|
mock_initial_subcloud_validate,
|
|
):
|
|
# Create fake subclouds and respective status
|
|
# Subcloud1 will be prestaged load in sync
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud1.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_IN_SYNC,
|
|
)
|
|
|
|
# Subcloud2 will be prestaged load is None
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt, "subcloud2", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud2.id, dccommon_consts.ENDPOINT_TYPE_LOAD, None
|
|
)
|
|
|
|
# Subcloud3 will be prestaged load out of sync
|
|
fake_subcloud3 = self.create_subcloud(
|
|
self.ctxt, "subcloud3", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud3.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
|
|
)
|
|
|
|
# Subcloud4 will be prestaged sync unknown
|
|
fake_subcloud4 = self.create_subcloud(
|
|
self.ctxt, "subcloud4", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud4.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_UNKNOWN,
|
|
)
|
|
|
|
mock_global_prestage_validate.return_value = None
|
|
mock_initial_subcloud_validate.return_value = None
|
|
|
|
data = copy.copy(FAKE_SW_PRESTAGE_DATA)
|
|
fake_password = (base64.b64encode("testpass".encode("utf-8"))).decode(
|
|
"ascii"
|
|
)
|
|
data["sysadmin_password"] = fake_password
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
response = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Verify strategy was created as expected using group values
|
|
self.assertEqual(response["max-parallel-subclouds"], 2)
|
|
self.assertEqual(
|
|
response["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_PARALLEL
|
|
)
|
|
self.assertEqual(response["type"], consts.SW_UPDATE_TYPE_PRESTAGE)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [1, 2, 3, 4]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(prestage, "initial_subcloud_validate")
|
|
@mock.patch.object(prestage, "_get_system_controller_upgrades")
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_prestage_strategy_no_password(
|
|
self,
|
|
mock_patch_orch_thread,
|
|
mock_controller_upgrade,
|
|
mock_initial_subcloud_validate,
|
|
):
|
|
# Create fake subclouds and respective status
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud1",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud1.id, endpoint=dccommon_consts.ENDPOINT_TYPE_LOAD
|
|
)
|
|
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud2",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud2.id, endpoint=dccommon_consts.ENDPOINT_TYPE_LOAD
|
|
)
|
|
|
|
mock_initial_subcloud_validate.return_value = None
|
|
mock_controller_upgrade.return_value = list()
|
|
|
|
data = copy.copy(FAKE_SW_PRESTAGE_DATA)
|
|
data["sysadmin_password"] = ""
|
|
data["subcloud_group"] = str(self.fake_group3.id)
|
|
um = sw_update_manager.SwUpdateManager()
|
|
|
|
self.assertRaises(
|
|
exceptions.BadRequest,
|
|
um.create_sw_update_strategy,
|
|
self.ctxt,
|
|
payload=data,
|
|
)
|
|
|
|
@mock.patch.object(prestage, "_get_system_controller_upgrades")
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_prestage_strategy_backup_in_progress(
|
|
self, mock_patch_orch_thread, mock_controller_upgrade
|
|
):
|
|
mock_controller_upgrade.return_value = list()
|
|
|
|
# Create fake subcloud and respective status (managed & online)
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud1",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud1.id)
|
|
db_api.subcloud_update(
|
|
self.ctx,
|
|
fake_subcloud1.id,
|
|
backup_status=consts.BACKUP_STATE_IN_PROGRESS,
|
|
)
|
|
|
|
data = copy.copy(FAKE_SW_PRESTAGE_DATA)
|
|
fake_password = (base64.b64encode("testpass".encode("utf-8"))).decode(
|
|
"ascii"
|
|
)
|
|
data["sysadmin_password"] = fake_password
|
|
data["cloud_name"] = "subcloud1"
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
|
|
self.assertRaises(
|
|
exceptions.BadRequest,
|
|
um.create_sw_update_strategy,
|
|
self.ctxt,
|
|
payload=data,
|
|
)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_cloud_name_not_exists(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# Create fake subclouds and respective status
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud1",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud1.id)
|
|
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
|
|
# Create a strategy with a cloud_name that doesn't exist
|
|
data["cloud_name"] = "subcloud2"
|
|
um = sw_update_manager.SwUpdateManager()
|
|
self.assertRaises(
|
|
exceptions.BadRequest,
|
|
um.create_sw_update_strategy,
|
|
self.ctxt,
|
|
payload=data,
|
|
)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_parallel(self, mock_patch_orch_thread):
|
|
# Create fake subclouds and respective status
|
|
# Subcloud1 will be patched
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud1.id)
|
|
|
|
# Subcloud2 will not be patched because not managed
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt, "subcloud2", 1, is_managed=False, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud2.id)
|
|
|
|
# Subcloud3 will be patched
|
|
fake_subcloud3 = self.create_subcloud(
|
|
self.ctxt, "subcloud3", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud3.id)
|
|
|
|
# Subcloud4 will not be patched because patching is in sync
|
|
fake_subcloud4 = self.create_subcloud(
|
|
self.ctxt, "subcloud4", 2, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud4.id, None, dccommon_consts.SYNC_STATUS_IN_SYNC
|
|
)
|
|
# Subcloud5 will be patched
|
|
fake_subcloud5 = self.create_subcloud(
|
|
self.ctxt, "subcloud5", 2, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud5.id)
|
|
|
|
# Subcloud6 will be patched
|
|
fake_subcloud6 = self.create_subcloud(
|
|
self.ctxt, "subcloud6", 3, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud6.id)
|
|
|
|
# Subcloud7 will be patched
|
|
fake_subcloud7 = self.create_subcloud(
|
|
self.ctxt, "subcloud7", 3, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud7.id)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
strategy_dict = um.create_sw_update_strategy(
|
|
self.ctxt, payload=FAKE_SW_UPDATE_DATA
|
|
)
|
|
|
|
# Assert that values passed through CLI are used instead of group values
|
|
self.assertEqual(strategy_dict["max-parallel-subclouds"], 2)
|
|
self.assertEqual(
|
|
strategy_dict["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_PARALLEL
|
|
)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [1, 3, 5, 6, 7]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_patching_subcloud_in_sync_out_of_sync(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# Subcloud 1 will be patched
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud1",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud1.id,
|
|
dccommon_consts.ENDPOINT_TYPE_PATCHING,
|
|
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
|
|
)
|
|
|
|
# Subcloud 2 will not be patched because it is offline
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud2",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=False,
|
|
)
|
|
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud2.id,
|
|
dccommon_consts.ENDPOINT_TYPE_PATCHING,
|
|
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
|
|
)
|
|
|
|
# Subcloud 3 will be patched
|
|
fake_subcloud3 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud3",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud3.id,
|
|
dccommon_consts.ENDPOINT_TYPE_PATCHING,
|
|
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
|
|
)
|
|
|
|
# Subcloud 4 will not be patched because it is in sync
|
|
fake_subcloud4 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud4",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud4.id,
|
|
dccommon_consts.ENDPOINT_TYPE_PATCHING,
|
|
dccommon_consts.SYNC_STATUS_IN_SYNC,
|
|
)
|
|
|
|
data = copy.copy(FAKE_SW_PATCH_DATA)
|
|
data["type"] = consts.SW_UPDATE_TYPE_PATCH
|
|
data["subcloud_group"] = str(self.fake_group3.id)
|
|
um = sw_update_manager.SwUpdateManager()
|
|
response = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Verify strategy was created as expected using group values
|
|
self.assertEqual(response["max-parallel-subclouds"], 2)
|
|
self.assertEqual(
|
|
response["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_PARALLEL
|
|
)
|
|
self.assertEqual(response["type"], consts.SW_UPDATE_TYPE_PATCH)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [1, 3]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
subcloud_id_processed = []
|
|
for strategy_step in strategy_step_list:
|
|
subcloud_id_processed.append(strategy_step.subcloud_id)
|
|
self.assertEqual(subcloud_ids, subcloud_id_processed)
|
|
|
|
@mock.patch.object(cutils, "get_systemcontroller_installed_loads")
|
|
@mock.patch.object(prestage, "initial_subcloud_validate")
|
|
@mock.patch.object(prestage, "_get_system_controller_upgrades")
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_prestage_strategy_parallel(
|
|
self,
|
|
mock_patch_orch_thread,
|
|
mock_controller_upgrade,
|
|
mock_initial_subcloud_validate,
|
|
mock_installed_loads,
|
|
):
|
|
# Create fake subclouds and respective status
|
|
# Subcloud1 will be prestaged
|
|
self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=True
|
|
)
|
|
|
|
# Subcloud2 will not be prestaged because not managed
|
|
self.create_subcloud(
|
|
self.ctxt, "subcloud2", 1, is_managed=False, is_online=True
|
|
)
|
|
|
|
# Subcloud3 will be prestaged
|
|
self.create_subcloud(
|
|
self.ctxt, "subcloud3", 1, is_managed=True, is_online=True
|
|
)
|
|
|
|
# Subcloud4 will not be prestaged because offline
|
|
self.create_subcloud(
|
|
self.ctxt, "subcloud4", 2, is_managed=True, is_online=False
|
|
)
|
|
|
|
# Subcloud5 will be prestaged
|
|
self.create_subcloud(
|
|
self.ctxt, "subcloud5", 2, is_managed=True, is_online=True
|
|
)
|
|
|
|
# Subcloud6 will be prestaged
|
|
self.create_subcloud(
|
|
self.ctxt, "subcloud6", 3, is_managed=True, is_online=True
|
|
)
|
|
|
|
# Subcloud7 will be prestaged
|
|
self.create_subcloud(
|
|
self.ctxt, "subcloud7", 3, is_managed=True, is_online=True
|
|
)
|
|
|
|
data = copy.copy(FAKE_SW_PRESTAGE_DATA)
|
|
fake_password = (base64.b64encode("testpass".encode("utf-8"))).decode(
|
|
"ascii"
|
|
)
|
|
data["sysadmin_password"] = fake_password
|
|
fake_release = "21.12"
|
|
data[consts.PRESTAGE_REQUEST_RELEASE] = fake_release
|
|
mock_installed_loads.return_value = [fake_release]
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
strategy_dict = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
mock_initial_subcloud_validate.return_value = None
|
|
mock_controller_upgrade.return_value = list()
|
|
|
|
# Assert that values passed through CLI are used instead of group values
|
|
self.assertEqual(strategy_dict["max-parallel-subclouds"], 2)
|
|
self.assertEqual(
|
|
strategy_dict["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_PARALLEL
|
|
)
|
|
self.assertEqual(
|
|
fake_release,
|
|
strategy_dict["extra-args"].get(consts.PRESTAGE_SOFTWARE_VERSION),
|
|
)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [1, 3, 5, 6, 7]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
subcloud_id_processed = []
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
subcloud_id_processed.append(strategy_step.subcloud_id)
|
|
self.assertEqual(subcloud_ids, subcloud_id_processed)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_serial(self, mock_patch_orch_thread):
|
|
# Create fake subclouds and respective status
|
|
# Subcloud1 will be patched
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud1.id)
|
|
|
|
# Subcloud2 will not be patched because not managed
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt, "subcloud2", 1, is_managed=False, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud2.id)
|
|
|
|
# Subcloud3 will be patched
|
|
fake_subcloud3 = self.create_subcloud(
|
|
self.ctxt, "subcloud3", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud3.id)
|
|
|
|
# Subcloud4 will not be patched because patching is in sync
|
|
fake_subcloud4 = self.create_subcloud(
|
|
self.ctxt, "subcloud4", 2, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud4.id, None, dccommon_consts.SYNC_STATUS_IN_SYNC
|
|
)
|
|
# Subcloud5 will be patched
|
|
fake_subcloud5 = self.create_subcloud(
|
|
self.ctxt, "subcloud5", 2, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud5.id)
|
|
|
|
# Subcloud6 will be patched
|
|
fake_subcloud6 = self.create_subcloud(
|
|
self.ctxt, "subcloud6", 3, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud6.id)
|
|
|
|
# Subcloud7 will be patched
|
|
fake_subcloud7 = self.create_subcloud(
|
|
self.ctxt, "subcloud7", 3, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud7.id)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
data["subcloud-apply-type"] = consts.SUBCLOUD_APPLY_TYPE_SERIAL
|
|
strategy_dict = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Assert that values passed through CLI are used instead of group values
|
|
self.assertEqual(strategy_dict["max-parallel-subclouds"], 1)
|
|
self.assertEqual(
|
|
strategy_dict["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_SERIAL
|
|
)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [1, 3, 5, 6, 7]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_using_group_apply_type(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# Create fake subclouds and respective status
|
|
# Subcloud1 will be patched
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud1.id)
|
|
|
|
# Subcloud2 will not be patched because not managed
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt, "subcloud2", 1, is_managed=False, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud2.id)
|
|
|
|
# Subcloud3 will be patched
|
|
fake_subcloud3 = self.create_subcloud(
|
|
self.ctxt, "subcloud3", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud3.id)
|
|
|
|
# Subcloud4 will not be patched because patching is in sync
|
|
fake_subcloud4 = self.create_subcloud(
|
|
self.ctxt, "subcloud4", 2, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud4.id, None, dccommon_consts.SYNC_STATUS_IN_SYNC
|
|
)
|
|
# Subcloud5 will be patched
|
|
fake_subcloud5 = self.create_subcloud(
|
|
self.ctxt, "subcloud5", 2, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud5.id)
|
|
|
|
# Subcloud6 will be patched
|
|
fake_subcloud6 = self.create_subcloud(
|
|
self.ctxt, "subcloud6", 3, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud6.id)
|
|
|
|
# Subcloud7 will be patched
|
|
fake_subcloud7 = self.create_subcloud(
|
|
self.ctxt, "subcloud7", 3, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud7.id)
|
|
|
|
# Subcloud8 will be patched
|
|
fake_subcloud8 = self.create_subcloud(
|
|
self.ctxt, "subcloud8", 4, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud8.id)
|
|
|
|
# Subcloud9 will be patched
|
|
fake_subcloud9 = self.create_subcloud(
|
|
self.ctxt, "subcloud9", 4, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud9.id)
|
|
|
|
# Subcloud10 will be patched
|
|
fake_subcloud10 = self.create_subcloud(
|
|
self.ctxt, "subcloud10", 4, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud10.id)
|
|
|
|
# Subcloud11 will be patched
|
|
fake_subcloud11 = self.create_subcloud(
|
|
self.ctxt, "subcloud11", 5, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud11.id)
|
|
|
|
# Subcloud12 will be patched
|
|
fake_subcloud12 = self.create_subcloud(
|
|
self.ctxt, "subcloud12", 5, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud12.id)
|
|
|
|
# Subcloud13 will be patched
|
|
fake_subcloud13 = self.create_subcloud(
|
|
self.ctxt, "subcloud13", 5, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud13.id)
|
|
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
del data["subcloud-apply-type"]
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
strategy_dict = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Assert that group values are being used for subcloud_apply_type
|
|
self.assertEqual(strategy_dict["subcloud-apply-type"], None)
|
|
|
|
# Assert that values passed through CLI are used instead of
|
|
# group values for max_parallel_subclouds
|
|
self.assertEqual(strategy_dict["max-parallel-subclouds"], 2)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_using_group_max_parallel(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# Create fake subclouds and respective status
|
|
# Subcloud1 will be patched
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud1.id)
|
|
|
|
# Subcloud2 will not be patched because not managed
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt, "subcloud2", 1, is_managed=False, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud2.id)
|
|
|
|
# Subcloud3 will be patched
|
|
fake_subcloud3 = self.create_subcloud(
|
|
self.ctxt, "subcloud3", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud3.id)
|
|
|
|
# Subcloud4 will not be patched because patching is in sync
|
|
fake_subcloud4 = self.create_subcloud(
|
|
self.ctxt, "subcloud4", 2, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud4.id, None, dccommon_consts.SYNC_STATUS_IN_SYNC
|
|
)
|
|
# Subcloud5 will be patched
|
|
fake_subcloud5 = self.create_subcloud(
|
|
self.ctxt, "subcloud5", 2, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud5.id)
|
|
|
|
# Subcloud6 will be patched
|
|
fake_subcloud6 = self.create_subcloud(
|
|
self.ctxt, "subcloud6", 3, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud6.id)
|
|
|
|
# Subcloud7 will be patched
|
|
fake_subcloud7 = self.create_subcloud(
|
|
self.ctxt, "subcloud7", 3, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud7.id)
|
|
|
|
# Subcloud8 will be patched
|
|
fake_subcloud8 = self.create_subcloud(
|
|
self.ctxt, "subcloud8", 4, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud8.id)
|
|
|
|
# Subcloud9 will be patched
|
|
fake_subcloud9 = self.create_subcloud(
|
|
self.ctxt, "subcloud9", 4, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud9.id)
|
|
|
|
# Subcloud10 will be patched
|
|
fake_subcloud10 = self.create_subcloud(
|
|
self.ctxt, "subcloud10", 4, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud10.id)
|
|
|
|
# Subcloud11 will be patched
|
|
fake_subcloud11 = self.create_subcloud(
|
|
self.ctxt, "subcloud11", 5, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud11.id)
|
|
|
|
# Subcloud12 will be patched
|
|
fake_subcloud12 = self.create_subcloud(
|
|
self.ctxt, "subcloud12", 5, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud12.id)
|
|
|
|
# Subcloud13 will be patched
|
|
fake_subcloud13 = self.create_subcloud(
|
|
self.ctxt, "subcloud13", 5, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud13.id)
|
|
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
del data["max-parallel-subclouds"]
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
strategy_dict = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Assert that values passed through CLI are used instead of
|
|
# group values for max_parallel_subclouds
|
|
self.assertEqual(
|
|
strategy_dict["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_PARALLEL
|
|
)
|
|
|
|
# Assert that group values are being used for subcloud_apply_type
|
|
self.assertEqual(
|
|
strategy_dict["max-parallel-subclouds"],
|
|
consts.DEFAULT_SUBCLOUD_GROUP_MAX_PARALLEL_SUBCLOUDS,
|
|
)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_using_all_group_values(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# Create fake subclouds and respective status
|
|
# Subcloud1 will be patched
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud1.id)
|
|
|
|
# Subcloud2 will not be patched because not managed
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt, "subcloud2", 1, is_managed=False, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud2.id)
|
|
|
|
# Subcloud3 will be patched
|
|
fake_subcloud3 = self.create_subcloud(
|
|
self.ctxt, "subcloud3", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud3.id)
|
|
|
|
# Subcloud4 will not be patched because patching is in sync
|
|
fake_subcloud4 = self.create_subcloud(
|
|
self.ctxt, "subcloud4", 2, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud4.id, None, dccommon_consts.SYNC_STATUS_IN_SYNC
|
|
)
|
|
# Subcloud5 will be patched
|
|
fake_subcloud5 = self.create_subcloud(
|
|
self.ctxt, "subcloud5", 2, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud5.id)
|
|
|
|
# Subcloud6 will be patched
|
|
fake_subcloud6 = self.create_subcloud(
|
|
self.ctxt, "subcloud6", 3, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud6.id)
|
|
|
|
# Subcloud7 will be patched
|
|
fake_subcloud7 = self.create_subcloud(
|
|
self.ctxt, "subcloud7", 3, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud7.id)
|
|
|
|
# Subcloud8 will be patched
|
|
fake_subcloud8 = self.create_subcloud(
|
|
self.ctxt, "subcloud8", 4, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud8.id)
|
|
|
|
# Subcloud9 will be patched
|
|
fake_subcloud9 = self.create_subcloud(
|
|
self.ctxt, "subcloud9", 4, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud9.id)
|
|
|
|
# Subcloud10 will be patched
|
|
fake_subcloud10 = self.create_subcloud(
|
|
self.ctxt, "subcloud10", 4, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud10.id)
|
|
|
|
# Subcloud11 will be patched
|
|
fake_subcloud11 = self.create_subcloud(
|
|
self.ctxt, "subcloud11", 5, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud11.id)
|
|
|
|
# Subcloud12 will be patched
|
|
fake_subcloud12 = self.create_subcloud(
|
|
self.ctxt, "subcloud12", 5, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud12.id)
|
|
|
|
# Subcloud13 will be patched
|
|
fake_subcloud13 = self.create_subcloud(
|
|
self.ctxt, "subcloud13", 5, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud13.id)
|
|
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
del data["subcloud-apply-type"]
|
|
del data["max-parallel-subclouds"]
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
strategy_dict = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Assert that group values are being used
|
|
self.assertEqual(
|
|
strategy_dict["max-parallel-subclouds"],
|
|
consts.DEFAULT_SUBCLOUD_GROUP_MAX_PARALLEL_SUBCLOUDS,
|
|
)
|
|
self.assertEqual(strategy_dict["subcloud-apply-type"], None)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [1, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_unknown_sync_status(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# Create fake subclouds and respective status
|
|
# Subcloud1 will be patched
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud1.id)
|
|
|
|
# Subcloud2 will not be patched because not managed
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt, "subcloud2", 1, is_managed=False, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud2.id)
|
|
|
|
# Subcloud3 will be patched
|
|
fake_subcloud3 = self.create_subcloud(
|
|
self.ctxt, "subcloud3", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud3.id)
|
|
|
|
# Subcloud4 will not be patched because patching is not in sync
|
|
fake_subcloud4 = self.create_subcloud(
|
|
self.ctxt, "subcloud4", 2, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt, fake_subcloud4.id, None, dccommon_consts.SYNC_STATUS_UNKNOWN
|
|
)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
self.assertRaises(
|
|
exceptions.BadRequest,
|
|
um.create_sw_update_strategy,
|
|
self.ctxt,
|
|
payload=FAKE_SW_UPDATE_DATA,
|
|
)
|
|
|
|
@mock.patch.object(prestage, "_get_prestage_subcloud_info")
|
|
@mock.patch.object(prestage, "_get_system_controller_upgrades")
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_prestage_strategy_duplex(
|
|
self,
|
|
mock_patch_orch_thread,
|
|
mock_controller_upgrade,
|
|
mock_prestage_subcloud_info,
|
|
):
|
|
# Create fake subclouds and respective status
|
|
|
|
# A note on subcloud system mode = duplex checking: For this test case
|
|
# it will be *included* in the strategy_step_list. It is not until the
|
|
# strategy is applied that the subcloud is skipped. During
|
|
# orchestration, we will see a raised PrestagePreCheckFailedException
|
|
# from prestage.validate_prestage() during the PrestagePreCheckState
|
|
# from the orchestration. That state is the first state executed by
|
|
# the orchestrator.
|
|
#
|
|
# Therefore, subcloud1 will be included in the strategy but not be
|
|
# prestaged because during the apply we find out it is a duplex
|
|
self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=True
|
|
)
|
|
|
|
data = copy.copy(FAKE_SW_PRESTAGE_DATA)
|
|
fake_password = (base64.b64encode("testpass".encode("utf-8"))).decode(
|
|
"ascii"
|
|
)
|
|
data["sysadmin_password"] = fake_password
|
|
|
|
mock_controller_upgrade.return_value = list()
|
|
mock_prestage_subcloud_info.return_value = (
|
|
consts.SYSTEM_MODE_DUPLEX,
|
|
health_report_no_mgmt_alarm,
|
|
OAM_FLOATING_IP,
|
|
)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
self.assertEqual(1, len(strategy_step_list))
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_offline_subcloud_no_force(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# Create fake subclouds and respective status
|
|
# Subcloud1 will not be included in the strategy as it's offline
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=False
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud1.id)
|
|
|
|
# Subcloud2 will be included in the strategy as it's online
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt, "subcloud2", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud2.id)
|
|
|
|
# Subcloud3 will be included in the strategy as it's online
|
|
fake_subcloud3 = self.create_subcloud(
|
|
self.ctxt, "subcloud3", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud3.id)
|
|
|
|
# Subcloud4 will be included in the strategy as it's online
|
|
fake_subcloud4 = self.create_subcloud(
|
|
self.ctxt, "subcloud4", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud4.id)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
data["max-parallel-subclouds"] = 10
|
|
strategy_dict = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Assert that values passed through CLI are used instead of group values
|
|
self.assertEqual(strategy_dict["max-parallel-subclouds"], 10)
|
|
self.assertEqual(
|
|
strategy_dict["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_PARALLEL
|
|
)
|
|
self.assertEqual(strategy_dict["type"], consts.SW_UPDATE_TYPE_PATCH)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [2, 3, 4]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_with_force_option(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# Subcloud 1 will be upgraded because force is true
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud1",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=False,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud1.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
|
|
)
|
|
|
|
# Subcloud 2 will be upgraded
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud2",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud2.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
|
|
)
|
|
|
|
# Subcloud 3 will not be upgraded because it is already load in-sync
|
|
fake_subcloud3 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud3",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud3.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_IN_SYNC,
|
|
)
|
|
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
data["type"] = consts.SW_UPDATE_TYPE_UPGRADE
|
|
data["force"] = "true"
|
|
data["subcloud_group"] = str(self.fake_group3.id)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
strategy_dict = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Assert that values passed through CLI are used instead of group values
|
|
self.assertEqual(
|
|
strategy_dict["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_PARALLEL
|
|
)
|
|
self.assertEqual(strategy_dict["type"], consts.SW_UPDATE_TYPE_UPGRADE)
|
|
|
|
subcloud_ids = [1, 2]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_without_force_option(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# Subcloud 1 will not be upgraded
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud1",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=False,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud1.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
|
|
)
|
|
|
|
# Subcloud 2 will be upgraded
|
|
fake_subcloud2 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud2",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud2.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_OUT_OF_SYNC,
|
|
)
|
|
|
|
# Subcloud 3 will not be upgraded because it is already load in-sync
|
|
fake_subcloud3 = self.create_subcloud(
|
|
self.ctxt,
|
|
"subcloud3",
|
|
self.fake_group3.id,
|
|
is_managed=True,
|
|
is_online=True,
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud3.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_IN_SYNC,
|
|
)
|
|
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
data["type"] = consts.SW_UPDATE_TYPE_UPGRADE
|
|
data["force"] = "false"
|
|
data["subcloud_group"] = str(self.fake_group3.id)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
strategy_dict = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Assert that values passed through CLI are used instead of group values
|
|
self.assertEqual(
|
|
strategy_dict["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_PARALLEL
|
|
)
|
|
self.assertEqual(strategy_dict["type"], consts.SW_UPDATE_TYPE_UPGRADE)
|
|
|
|
subcloud_ids = [2]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_not_insync_offline_sc_with_force_upgrade(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# This test verifies the offline subcloud is added to the strategy
|
|
# because force option is specified in the upgrade request.
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=False
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud1.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_UNKNOWN,
|
|
)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
data["type"] = consts.SW_UPDATE_TYPE_UPGRADE
|
|
data["force"] = "true"
|
|
data["cloud_name"] = "subcloud1"
|
|
|
|
strategy_dict = um.create_sw_update_strategy(self.ctxt, payload=data)
|
|
|
|
# Assert that values passed through CLI are used instead of group values
|
|
self.assertEqual(
|
|
strategy_dict["subcloud-apply-type"], consts.SUBCLOUD_APPLY_TYPE_PARALLEL
|
|
)
|
|
self.assertEqual(strategy_dict["type"], consts.SW_UPDATE_TYPE_UPGRADE)
|
|
|
|
# Verify the strategy step list
|
|
subcloud_ids = [1]
|
|
strategy_step_list = db_api.strategy_step_get_all(self.ctxt)
|
|
for index, strategy_step in enumerate(strategy_step_list):
|
|
self.assertEqual(subcloud_ids[index], strategy_step.subcloud_id)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_in_sync_offline_subcloud_with_force_upgrade(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# This test verifies that a bad request exception is raised even
|
|
# though force option is specified in the request because the load sync
|
|
# status of the offline subcloud is in-sync.
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=False
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud1.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_IN_SYNC,
|
|
)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
data["type"] = consts.SW_UPDATE_TYPE_UPGRADE
|
|
data["force"] = True
|
|
data["cloud_name"] = "subcloud1"
|
|
|
|
self.assertRaises(
|
|
exceptions.BadRequest,
|
|
um.create_sw_update_strategy,
|
|
self.ctxt,
|
|
payload=data,
|
|
)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_online_subcloud_with_force_upgrade(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# This test verifies that the force option has no effect in
|
|
# upgrade creation strategy if the subcloud is online. A bad request
|
|
# exception will be raised if the subcloud load sync status is
|
|
# unknown.
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=True
|
|
)
|
|
self.update_subcloud_status(
|
|
self.ctxt,
|
|
fake_subcloud1.id,
|
|
dccommon_consts.ENDPOINT_TYPE_LOAD,
|
|
dccommon_consts.SYNC_STATUS_UNKNOWN,
|
|
)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
data["type"] = consts.SW_UPDATE_TYPE_UPGRADE
|
|
data["force"] = True
|
|
data["cloud_name"] = "subcloud1"
|
|
|
|
self.assertRaises(
|
|
exceptions.BadRequest,
|
|
um.create_sw_update_strategy,
|
|
self.ctxt,
|
|
payload=data,
|
|
)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_create_sw_update_strategy_offline_subcloud_with_force_patching(
|
|
self, mock_patch_orch_thread
|
|
):
|
|
# This test verifies that the force option has no effect in
|
|
# patching creation strategy even though the subcloud is offline
|
|
fake_subcloud1 = self.create_subcloud(
|
|
self.ctxt, "subcloud1", 1, is_managed=True, is_online=False
|
|
)
|
|
self.update_subcloud_status(self.ctxt, fake_subcloud1.id)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
data = copy.copy(FAKE_SW_UPDATE_DATA)
|
|
data["force"] = True
|
|
data["cloud_name"] = "subcloud1"
|
|
|
|
# No strategy step is created when all subclouds are offline,
|
|
# should raise 'Bad strategy request: Strategy has no steps to apply'
|
|
self.assertRaises(
|
|
exceptions.BadRequest,
|
|
um.create_sw_update_strategy,
|
|
self.ctxt,
|
|
payload=data,
|
|
)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_delete_sw_update_strategy(self, mock_patch_orch_thread):
|
|
self.create_strategy(
|
|
self.ctxt, consts.SW_UPDATE_TYPE_PATCH, consts.SW_UPDATE_STATE_INITIAL
|
|
)
|
|
um = sw_update_manager.SwUpdateManager()
|
|
deleted_strategy = um.delete_sw_update_strategy(self.ctxt)
|
|
self.assertEqual(deleted_strategy["state"], consts.SW_UPDATE_STATE_DELETING)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_delete_sw_update_strategy_scoped(self, mock_patch_orch_thread):
|
|
self.create_strategy(
|
|
self.ctxt, consts.SW_UPDATE_TYPE_PATCH, consts.SW_UPDATE_STATE_INITIAL
|
|
)
|
|
um = sw_update_manager.SwUpdateManager()
|
|
deleted_strategy = um.delete_sw_update_strategy(
|
|
self.ctxt, update_type=consts.SW_UPDATE_TYPE_PATCH
|
|
)
|
|
self.assertEqual(deleted_strategy["state"], consts.SW_UPDATE_STATE_DELETING)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_delete_sw_update_strategy_bad_scope(self, mock_patch_orch_thread):
|
|
self.create_strategy(
|
|
self.ctxt, consts.SW_UPDATE_TYPE_PATCH, consts.SW_UPDATE_STATE_INITIAL
|
|
)
|
|
um = sw_update_manager.SwUpdateManager()
|
|
# the strategy is PATCH. The delete for UPGRADE should fail
|
|
self.assertRaises(
|
|
exceptions.NotFound,
|
|
um.delete_sw_update_strategy,
|
|
self.ctx,
|
|
update_type=consts.SW_UPDATE_TYPE_UPGRADE,
|
|
)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_delete_sw_update_strategy_invalid_state(self, mock_patch_orch_thread):
|
|
# Create fake strategy
|
|
self.create_strategy(
|
|
self.ctxt, consts.SW_UPDATE_TYPE_PATCH, consts.SW_UPDATE_STATE_APPLYING
|
|
)
|
|
um = sw_update_manager.SwUpdateManager()
|
|
self.assertRaises(
|
|
exceptions.BadRequest, um.delete_sw_update_strategy, self.ctxt
|
|
)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_apply_sw_update_strategy(self, mock_patch_orch_thread):
|
|
# Create fake strategy
|
|
self.create_strategy(
|
|
self.ctxt, consts.SW_UPDATE_TYPE_PATCH, consts.SW_UPDATE_STATE_INITIAL
|
|
)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
updated_strategy = um.apply_sw_update_strategy(self.ctxt)
|
|
self.assertEqual(updated_strategy["state"], consts.SW_UPDATE_STATE_APPLYING)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_apply_sw_update_strategy_invalid_state(self, mock_patch_orch_thread):
|
|
# Create fake strategy
|
|
self.create_strategy(
|
|
self.ctxt, consts.SW_UPDATE_TYPE_PATCH, consts.SW_UPDATE_STATE_APPLYING
|
|
)
|
|
um = sw_update_manager.SwUpdateManager()
|
|
self.assertRaises(
|
|
exceptions.BadRequest, um.apply_sw_update_strategy, self.ctxt
|
|
)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_abort_sw_update_strategy(self, mock_patch_orch_thread):
|
|
# Create fake strategy
|
|
self.create_strategy(
|
|
self.ctxt, consts.SW_UPDATE_TYPE_PATCH, consts.SW_UPDATE_STATE_APPLYING
|
|
)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
aborted_strategy = um.abort_sw_update_strategy(self.ctxt)
|
|
self.assertEqual(
|
|
aborted_strategy["state"], consts.SW_UPDATE_STATE_ABORT_REQUESTED
|
|
)
|
|
|
|
@mock.patch.object(sw_update_manager, "PatchOrchThread")
|
|
def test_abort_sw_update_strategy_invalid_state(self, mock_patch_orch_thread):
|
|
# Create fake strategy
|
|
self.create_strategy(
|
|
self.ctxt, consts.SW_UPDATE_TYPE_PATCH, consts.SW_UPDATE_STATE_COMPLETE
|
|
)
|
|
|
|
um = sw_update_manager.SwUpdateManager()
|
|
self.assertRaises(
|
|
exceptions.BadRequest, um.apply_sw_update_strategy, self.ctxt
|
|
)
|