Add unit tests for subcloud restore

Update API and manager unit tests to include subcloud restore
tests.

Story: 2008573
Task: 42028
Change-Id: I0e16f9914fb5a4d0b73ea9837a75931e2a4432d6
Signed-off-by: Tee Ngo <tee.ngo@windriver.com>
This commit is contained in:
Tee Ngo 2021-03-10 09:05:19 -05:00
parent 7289578bf0
commit 36497a9bf5
2 changed files with 255 additions and 1 deletions

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
# Copyright (c) 2017-2020 Wind River Systems, Inc.
# Copyright (c) 2017-2021 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
@ -736,6 +736,15 @@ class TestSubcloudPost(testroot.DCManagerApiTest,
class TestSubcloudAPIOther(testroot.DCManagerApiTest):
FAKE_RESTORE_PAYLOAD = {
'sysadmin_password':
(base64.b64encode('testpass'.encode("utf-8"))).decode('ascii'),
'with_install': 'true',
'restore_values': {'on_box_data': 'false',
'backup_filename': 'some_fake_tarfile'}
}
"""Test GET, delete and patch API calls"""
def setUp(self):
super(TestSubcloudAPIOther, self).setUp()
@ -1209,3 +1218,141 @@ class TestSubcloudAPIOther(testroot.DCManagerApiTest):
subcloud.id,
mock.ANY)
self.assertEqual(response.status_int, 200)
@mock.patch.object(rpc_client, 'ManagerClient')
@mock.patch.object(subclouds.SubcloudsController, '_get_restore_payload')
def test_restore_subcloud_no_body(self, mock_get_restore_payload,
mock_rpc_client):
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
restore_payload = {}
mock_rpc_client().restore_subcloud.return_value = True
mock_get_restore_payload.return_value = restore_payload
six.assertRaisesRegex(self, webtest.app.AppError, "400 *",
self.app.patch_json, FAKE_URL + '/' +
str(subcloud.id) + '/restore',
headers=FAKE_HEADERS, params=restore_payload)
@mock.patch.object(rpc_client, 'ManagerClient')
def test_restore_subcloud_missing_restore_values(self, mock_rpc_client):
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
restore_payload = copy.copy(self.FAKE_RESTORE_PAYLOAD)
del restore_payload['restore_values']
mock_rpc_client().restore_subcloud.return_value = True
six.assertRaisesRegex(self, webtest.app.AppError, "400 *",
self.app.patch_json, FAKE_URL + '/' +
str(subcloud.id) + '/restore',
headers=FAKE_HEADERS, params=restore_payload)
@mock.patch.object(rpc_client, 'ManagerClient')
@mock.patch.object(subclouds.SubcloudsController, '_get_restore_payload')
def test_restore_subcloud_in_managed_state(self, mock_get_restore_payload,
mock_rpc_client):
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
db_api.subcloud_update(self.ctx,
subcloud.id,
management_state=consts.MANAGEMENT_MANAGED)
restore_payload = copy.copy(self.FAKE_RESTORE_PAYLOAD)
mock_rpc_client().restore_subcloud.return_value = True
mock_get_restore_payload.return_value = restore_payload
six.assertRaisesRegex(self, webtest.app.AppError, "400 *",
self.app.patch_json, FAKE_URL + '/' +
str(subcloud.id) + '/restore',
headers=FAKE_HEADERS, params=restore_payload)
@mock.patch.object(rpc_client, 'ManagerClient')
@mock.patch.object(subclouds.SubcloudsController, '_get_restore_payload')
def test_restore_subcloud_undergoing_bootstrap(self, mock_get_restore_payload,
mock_rpc_client):
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
db_api.subcloud_update(self.ctx,
subcloud.id,
deploy_status=consts.DEPLOY_STATE_BOOTSTRAPPING)
restore_payload = copy.copy(self.FAKE_RESTORE_PAYLOAD)
mock_rpc_client().restore_subcloud.return_value = True
mock_get_restore_payload.return_value = restore_payload
six.assertRaisesRegex(self, webtest.app.AppError, "400 *",
self.app.patch_json, FAKE_URL + '/' +
str(subcloud.id) + '/restore',
headers=FAKE_HEADERS, params=restore_payload)
@mock.patch.object(rpc_client, 'ManagerClient')
@mock.patch.object(subclouds.SubcloudsController, '_get_restore_payload')
def test_restore_subcloud_bad_sysadmin_password(self, mock_get_restore_payload,
mock_rpc_client):
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
restore_payload = copy.copy(self.FAKE_RESTORE_PAYLOAD)
restore_payload['sysadmin_password'] = 'not_base64_encoded'
mock_rpc_client().restore_subcloud.return_value = True
mock_get_restore_payload.return_value = restore_payload
six.assertRaisesRegex(self, webtest.app.AppError, "400 *",
self.app.patch_json, FAKE_URL + '/' +
str(subcloud.id) + '/restore',
headers=FAKE_HEADERS, params=restore_payload)
@mock.patch.object(rpc_client, 'ManagerClient')
@mock.patch.object(subclouds.SubcloudsController, '_get_restore_payload')
def test_restore_subcloud_without_remote_install(self, mock_get_restore_payload,
mock_rpc_client):
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
restore_payload = copy.copy(self.FAKE_RESTORE_PAYLOAD)
del restore_payload['with_install']
mock_rpc_client().restore_subcloud.return_value = True
mock_get_restore_payload.return_value = restore_payload
six.assertRaisesRegex(self, webtest.app.AppError, "400 *",
self.app.patch_json, FAKE_URL + '/' +
str(subcloud.id) + '/restore',
headers=FAKE_HEADERS, params=restore_payload)
@mock.patch.object(rpc_client, 'ManagerClient')
@mock.patch.object(subclouds.SubcloudsController, '_get_restore_payload')
def test_restore_subcloud_missing_mandatory_restore_parameter(
self, mock_get_restore_payload, mock_rpc_client):
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
restore_payload = copy.copy(self.FAKE_RESTORE_PAYLOAD)
restore_payload['restore_values'] = {'on_box_data': 'false'}
mock_rpc_client().restore_subcloud.return_value = True
mock_get_restore_payload.return_value = restore_payload
six.assertRaisesRegex(self, webtest.app.AppError, "400 *",
self.app.patch_json, FAKE_URL + '/' +
str(subcloud.id) + '/restore',
headers=FAKE_HEADERS, params=restore_payload)
@mock.patch.object(cutils, 'get_vault_load_files')
@mock.patch.object(rpc_client, 'ManagerClient')
@mock.patch.object(subclouds.SubcloudsController, '_get_subcloud_db_install_values')
@mock.patch.object(subclouds.SubcloudsController, '_get_restore_payload')
def test_restore_subcloud(self, mock_get_restore_payload,
mock_get_subcloud_db_install_values,
mock_rpc_client, mock_get_vault_load_files):
subcloud = fake_subcloud.create_fake_subcloud(self.ctx)
install_data = copy.copy(FAKE_SUBCLOUD_INSTALL_VALUES)
restore_payload = copy.copy(self.FAKE_RESTORE_PAYLOAD)
mock_get_subcloud_db_install_values.return_value = install_data
mock_rpc_client().restore_subcloud.return_value = True
mock_get_restore_payload.return_value = restore_payload
mock_get_vault_load_files.return_value = ('iso_file_path', 'sig_file_path')
response = self.app.patch_json(FAKE_URL + '/' + str(subcloud.id) +
'/restore',
headers=FAKE_HEADERS,
params=restore_payload)
mock_rpc_client().restore_subcloud.assert_called_once_with(
mock.ANY,
subcloud.id,
mock.ANY)
self.assertEqual(response.status_int, 200)

View File

@ -176,6 +176,24 @@ class FakeException(Exception):
pass
FAKE_RESTORE_VALUES = {
"backup_filename": "subcloud_platform_backup.tgz",
"on_box_data": "false",
"initial_backup_dir": "/home/sysadmin",
"skip_patches_restore": "true"
}
FAKE_SUBCLOUD_RESTORE_PAYLOAD = {
"install_values": fake_subcloud.FAKE_SUBCLOUD_INSTALL_VALUES,
"with_install": True,
"bootstrap-address": "bootstrap_ip",
"software_version": "20.12",
"sysadmin_password": "testpasswd",
"restore_values": FAKE_RESTORE_VALUES
}
class Subcloud(object):
def __init__(self, data, is_online):
self.id = data['id']
@ -1325,3 +1343,92 @@ class TestSubcloudManager(base.DCManagerTestCase):
subcloud = db_api.subcloud_get_by_name(self.ctx, subcloud11.name)
self.assertEqual(consts.DEPLOY_STATE_DONE,
subcloud.deploy_status)
def test_compose_check_target_command(self):
sm = subcloud_manager.SubcloudManager()
check_target_command = sm.compose_check_target_command(
'subcloud1', '/opt/dc/ansible/subcloud1_inventory.yml',
FAKE_SUBCLOUD_RESTORE_PAYLOAD)
self.assertEqual(
check_target_command,
[
'ansible-playbook', subcloud_manager.ANSIBLE_HOST_VALIDATION_PLAYBOOK,
'-i', '/opt/dc/ansible/subcloud1_inventory.yml', '--limit', 'subcloud1',
'-e', '@/opt/dc/ansible/subcloud1_check_target_values.yml'
]
)
def test_compose_restore_command(self):
sm = subcloud_manager.SubcloudManager()
restore_command = sm.compose_restore_command(
'subcloud1', '/opt/dc/ansible/subcloud1_inventory.yml',
FAKE_SUBCLOUD_RESTORE_PAYLOAD)
self.assertEqual(
restore_command,
[
'ansible-playbook', subcloud_manager.ANSIBLE_SUBCLOUD_RESTORE_PLAYBOOK,
'-i', '/opt/dc/ansible/subcloud1_inventory.yml', '--limit', 'subcloud1',
'-e', '@/opt/dc/ansible/subcloud1_restore_values.yml'
]
)
def test_restore_managed_subcloud(self):
subcloud = self.create_subcloud_static(
self.ctx,
name='subcloud1',
deploy_status=consts.DEPLOY_STATE_DONE)
db_api.subcloud_update(self.ctx,
subcloud.id,
management_state=consts.MANAGEMENT_MANAGED)
fake_dcmanager_cermon_api = FakeDCManagerNotifications()
p = mock.patch('dcmanager.rpc.client.DCManagerNotifications')
mock_dcmanager_api = p.start()
mock_dcmanager_api.return_value = fake_dcmanager_cermon_api
sm = subcloud_manager.SubcloudManager()
self.assertRaises(exceptions.SubcloudNotUnmanaged,
sm.restore_subcloud, self.ctx,
subcloud.id, FAKE_SUBCLOUD_RESTORE_PAYLOAD)
@mock.patch.object(cutils, 'get_vault_load_files')
@mock.patch.object(cutils, 'create_subcloud_inventory')
@mock.patch.object(
subcloud_manager.SubcloudManager, 'compose_install_command')
@mock.patch.object(subcloud_manager.SubcloudManager,
'_prepare_for_restore')
@mock.patch.object(
subcloud_manager.SubcloudManager, 'compose_check_target_command')
@mock.patch.object(
subcloud_manager.SubcloudManager, 'compose_restore_command')
@mock.patch.object(threading.Thread, 'start')
def test_restore_subcloud(
self, mock_thread_start,
mock_compose_restore_command, mock_compose_check_target_command,
mock_prepare_for_restore, mock_compose_install_command,
mock_create_subcloud_inventory, mock_get_vault_load_files):
subcloud = self.create_subcloud_static(
self.ctx,
name='subcloud1',
deploy_status=consts.DEPLOY_STATE_PRE_RESTORE)
sm = subcloud_manager.SubcloudManager()
mock_get_vault_load_files.return_value = ("iso file path", "sig file path")
sm.restore_subcloud(self.ctx, subcloud.id, FAKE_SUBCLOUD_RESTORE_PAYLOAD)
mock_get_vault_load_files.assert_called_once_with(SW_VERSION)
mock_create_subcloud_inventory.assert_called_once_with(
FAKE_SUBCLOUD_RESTORE_PAYLOAD, mock.ANY)
mock_compose_install_command.assert_called_once_with(subcloud.name, mock.ANY)
mock_compose_check_target_command.assert_called_once_with(
subcloud.name, mock.ANY, FAKE_SUBCLOUD_RESTORE_PAYLOAD)
mock_compose_restore_command.assert_called_once_with(
subcloud.name, mock.ANY, FAKE_SUBCLOUD_RESTORE_PAYLOAD)
mock_thread_start.assert_called_once()
# Verify that subcloud has the correct deploy status
updated_subcloud = db_api.subcloud_get_by_name(self.ctx, subcloud.name)
self.assertEqual(consts.DEPLOY_STATE_PRE_RESTORE,
updated_subcloud.deploy_status)