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:
parent
7289578bf0
commit
36497a9bf5
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue