From bda8202f6d91cc46f082f5c54128c5eb2b40f6ec Mon Sep 17 00:00:00 2001 From: jiaopengju Date: Wed, 9 Jan 2019 21:36:27 +0800 Subject: [PATCH] Add support to rewrite the flavor id in restore When using karbor to restore server to another openstack cluster(cross keystone), and if the another cluster do not have the same flavor id, the restore will fail. We should add support for adding flavor id as a parameter to rewrite the flavor id in checkpoint metadata. Change-Id: Ie5c7a1adf07b7f9b1225ee4a5e16000a3453a7cc Closes-Bug: #1811090 --- .../server/nova_protection_plugin.py | 4 ++ .../server/server_plugin_schemas.py | 5 ++ .../protection/test_nova_protection_plugin.py | 62 ++++++++++++++++++- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/karbor/services/protection/protection_plugins/server/nova_protection_plugin.py b/karbor/services/protection/protection_plugins/server/nova_protection_plugin.py index 8c388976..723623aa 100644 --- a/karbor/services/protection/protection_plugins/server/nova_protection_plugin.py +++ b/karbor/services/protection/protection_plugins/server/nova_protection_plugin.py @@ -230,6 +230,10 @@ class RestoreOperation(protection_plugin.Operation): # restore server instance restore_net_id = parameters.get("restore_net_id", None) + restore_flavor_id = parameters.get("restore_flavor_id", None) + if restore_flavor_id: + resource_definition["server_metadata"]['flavor'] = ( + restore_flavor_id) new_server_id = self._restore_server_instance( nova_client, new_resources, original_server_id, parameters.get("restore_name", "karbor-restore-server"), diff --git a/karbor/services/protection/protection_plugins/server/server_plugin_schemas.py b/karbor/services/protection/protection_plugins/server/server_plugin_schemas.py index bf2b054a..39b682c0 100644 --- a/karbor/services/protection/protection_plugins/server/server_plugin_schemas.py +++ b/karbor/services/protection/protection_plugins/server/server_plugin_schemas.py @@ -30,6 +30,11 @@ RESTORE_SCHEMA = { "type": "string", "title": "Restore Server Net Id", "description": "The net id of the restore server" + }, + "restore_flavor_id": { + "type": "string", + "title": "Restore Server Flavor Id", + "description": "The flavor id of the restore server" } }, "required": ["restore_name"] diff --git a/karbor/tests/unit/protection/test_nova_protection_plugin.py b/karbor/tests/unit/protection/test_nova_protection_plugin.py index fc22e921..7437eaba 100644 --- a/karbor/tests/unit/protection/test_nova_protection_plugin.py +++ b/karbor/tests/unit/protection/test_nova_protection_plugin.py @@ -29,7 +29,7 @@ from karbor.tests import base class Server(object): def __init__(self, id, addresses, availability_zone, - flavor, key_name, security_groups): + flavor, key_name, security_groups, status): super(Server, self).__init__() self.id = id self.addresses = addresses @@ -37,6 +37,7 @@ class Server(object): self.flavor = flavor self.key_name = key_name self.security_groups = security_groups + self.status = status class Volume(object): @@ -94,7 +95,8 @@ FakeServers = { 'rel': 'bookmark'} ]}, key_name=None, - security_groups="default"), + security_groups="default", + status="ACTIVE"), "vm_id_2": Server(id="vm_id_2", addresses={'fake_net': [ {'OS-EXT-IPS-MAC:mac_addr': 'mac_address_2', @@ -109,7 +111,8 @@ FakeServers = { 'rel': 'bookmark'} ]}, key_name=None, - security_groups="default") + security_groups="default", + status="ACTIVE") } FakeVolumes = { @@ -454,6 +457,59 @@ class NovaProtectionPluginTest(base.TestCase): call_hooks(delete_operation, self.checkpoint, resource, self.cntxt, {}) + @mock.patch('karbor.services.protection.protection_plugins.utils.' + 'update_resource_restore_result') + @mock.patch('karbor.services.protection.clients.neutron.create') + @mock.patch('karbor.services.protection.clients.glance.create') + @mock.patch('karbor.services.protection.clients.nova.create') + @mock.patch('karbor.services.protection.clients.cinder.create') + def test_restore_backup_with_parameters(self, mock_cinder_client, + mock_nova_client, + mock_glance_client, + mock_neutron_client, + mock_update_result): + resource = Resource(id='vm_id_1', + type=constants.SERVER_RESOURCE_TYPE, + name='fake_vm') + fake_bank._plugin._objects[ + "/resource_data/checkpoint_id/vm_id_1/metadata"] = { + "server_metadata": { + "availability_zone": "nova", + "key_name": None, + "floating_ips": [], + "flavor": "fake_flavor_id_1", + "networks": ["fake_net_id_1"], + "security_groups": [{"name": "default"}]}, + "boot_metadata": { + "boot_image_id": "fake_image_id", + "boot_device_type": "image"}, + "attach_metadata": {}, + "resource_id": "vm_id_1"} + restore_operation = self.plugin.get_restore_operation(resource) + mock_cinder_client.return_value = self.cinder_client + mock_nova_client.return_value = self.nova_client + mock_glance_client.return_value = self.glance_client + mock_neutron_client.return_value = self.neutron_client + parameters = {'restore_net_id': 'fake_net_id_2', + 'restore_flavor_id': 'fake_flavor_id_2'} + checkpoint = Checkpoint() + new_resources = {"new_resources": {"fake_image_id": "fake_image_id"}} + self.nova_client.servers.create = mock.MagicMock() + self.nova_client.servers.create.return_value = FakeServers['vm_id_2'] + call_hooks(restore_operation, checkpoint, resource, self.cntxt, + parameters, **new_resources) + properties = { + "availability_zone": "nova", + "flavor": "fake_flavor_id_2", + "name": "karbor-restore-server", + "image": "fake_image_id", + "key_name": None, + "security_groups": ['default'], + "nics": [{'net-id': 'fake_net_id_2'}], + "userdata": None + } + self.nova_client.servers.create.assert_called_with(**properties) + @mock.patch('karbor.services.protection.protection_plugins.utils.' 'update_resource_verify_result') def test_verify_backup(self, mock_update_verify):