diff --git a/nova/tests/virt/vmwareapi/fake.py b/nova/tests/virt/vmwareapi/fake.py index 12741941cf29..7026cbb5fa28 100644 --- a/nova/tests/virt/vmwareapi/fake.py +++ b/nova/tests/virt/vmwareapi/fake.py @@ -1045,6 +1045,9 @@ class FakeService(DataObject): def Logout(self, session_manager): pass + def FindExtension(self, extension_manager, key): + return [] + class FakeClient(DataObject): """Fake client class.""" @@ -1116,6 +1119,7 @@ class FakeVim(object): service_content.fileManager = "FileManager" service_content.rootFolder = "RootFolder" service_content.sessionManager = "SessionManager" + service_content.extensionManager = "ExtensionManager" service_content.searchIndex = "SearchIndex" about_info = DataObject() diff --git a/nova/tests/virt/vmwareapi/test_configdrive.py b/nova/tests/virt/vmwareapi/test_configdrive.py index 0136ad662680..0b408e537511 100644 --- a/nova/tests/virt/vmwareapi/test_configdrive.py +++ b/nova/tests/virt/vmwareapi/test_configdrive.py @@ -14,6 +14,7 @@ # under the License. import fixtures +import mock import mox from nova import context @@ -32,7 +33,8 @@ from nova.virt.vmwareapi import vmware_images class ConfigDriveTestCase(test.NoDBTestCase): - def setUp(self): + @mock.patch.object(driver.VMwareVCDriver, '_register_openstack_extension') + def setUp(self, mock_register): super(ConfigDriveTestCase, self).setUp() vm_util.vm_refs_cache_reset() self.context = context.RequestContext('fake', 'fake', is_admin=False) diff --git a/nova/tests/virt/vmwareapi/test_driver_api.py b/nova/tests/virt/vmwareapi/test_driver_api.py index 31020d4d9caf..64139c73376e 100644 --- a/nova/tests/virt/vmwareapi/test_driver_api.py +++ b/nova/tests/virt/vmwareapi/test_driver_api.py @@ -34,6 +34,7 @@ from oslo.utils import units from oslo.vmware import exceptions as vexc from oslo.vmware import pbm from oslo.vmware import vim +from oslo.vmware import vim_util as oslo_vim_util import suds from nova import block_device @@ -192,7 +193,8 @@ class VMwareSessionTestCase(test.NoDBTestCase): class VMwareAPIVMTestCase(test.NoDBTestCase): """Unit tests for Vmware API connection calls.""" - def setUp(self, create_connection=True): + @mock.patch.object(driver.VMwareVCDriver, '_register_openstack_extension') + def setUp(self, mock_register, create_connection=True): super(VMwareAPIVMTestCase, self).setUp() vm_util.vm_refs_cache_reset() self.context = context.RequestContext('fake', 'fake', is_admin=False) @@ -2036,8 +2038,8 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): class VMwareAPIVCDriverTestCase(VMwareAPIVMTestCase): - def setUp(self): - + @mock.patch.object(driver.VMwareVCDriver, '_register_openstack_extension') + def setUp(self, mock_register): super(VMwareAPIVCDriverTestCase, self).setUp(create_connection=False) cluster_name = 'test_cluster' cluster_name2 = 'test_cluster2' @@ -2064,6 +2066,25 @@ class VMwareAPIVCDriverTestCase(VMwareAPIVMTestCase): def test_public_api_signatures(self): self.assertPublicAPISignatures(v_driver.ComputeDriver(None), self.conn) + def test_register_extension(self): + with mock.patch.object(self.conn._session, '_call_method', + return_value=None) as mock_call_method: + self.conn._register_openstack_extension() + mock_call_method.assert_has_calls( + [mock.call(oslo_vim_util, 'find_extension', + constants.EXTENSION_KEY), + mock.call(oslo_vim_util, 'register_extension', + constants.EXTENSION_KEY, + constants.EXTENSION_TYPE_INSTANCE)]) + + def test_register_extension_already_exists(self): + with mock.patch.object(self.conn._session, '_call_method', + return_value='fake-extension') as mock_find_ext: + self.conn._register_openstack_extension() + mock_find_ext.assert_called_once_with(oslo_vim_util, + 'find_extension', + constants.EXTENSION_KEY) + def test_list_instances(self): instances = self.conn.list_instances() self.assertEqual(0, len(instances)) diff --git a/nova/tests/virt/vmwareapi/test_vm_util.py b/nova/tests/virt/vmwareapi/test_vm_util.py index 74d2f603bd38..4a1bcdb6400d 100644 --- a/nova/tests/virt/vmwareapi/test_vm_util.py +++ b/nova/tests/virt/vmwareapi/test_vm_util.py @@ -555,6 +555,9 @@ class VMwareVMUtilTestCase(test.NoDBTestCase): 'key': 'nvp.vm-uuid', 'obj_name': 'ns0:OptionValue'}], 'memoryMB': 2048, + 'managedBy': {'extensionKey': 'org.openstack.compute', + 'type': 'instance', + 'obj_name': 'ns0:ManagedByInfo'}, 'obj_name': 'ns0:VirtualMachineConfigSpec', 'guestId': 'otherGuest', 'tools': {'beforeGuestStandby': True, @@ -587,6 +590,9 @@ class VMwareVMUtilTestCase(test.NoDBTestCase): 'key': 'nvp.vm-uuid', 'obj_name': 'ns0:OptionValue'}], 'memoryMB': 2048, + 'managedBy': {'extensionKey': 'org.openstack.compute', + 'type': 'instance', + 'obj_name': 'ns0:ManagedByInfo'}, 'obj_name': 'ns0:VirtualMachineConfigSpec', 'guestId': 'otherGuest', 'tools': {'beforeGuestStandby': True, @@ -621,6 +627,9 @@ class VMwareVMUtilTestCase(test.NoDBTestCase): 'key': 'nvp.vm-uuid', 'obj_name': 'ns0:OptionValue'}], 'memoryMB': 2048, + 'managedBy': {'extensionKey': 'org.openstack.compute', + 'type': 'instance', + 'obj_name': 'ns0:ManagedByInfo'}, 'obj_name': 'ns0:VirtualMachineConfigSpec', 'guestId': 'otherGuest', 'tools': {'beforeGuestStandby': True, @@ -655,6 +664,9 @@ class VMwareVMUtilTestCase(test.NoDBTestCase): 'key': 'nvp.vm-uuid', 'obj_name': 'ns0:OptionValue'}], 'memoryMB': 2048, + 'managedBy': {'extensionKey': 'org.openstack.compute', + 'type': 'instance', + 'obj_name': 'ns0:ManagedByInfo'}, 'obj_name': 'ns0:VirtualMachineConfigSpec', 'guestId': 'otherGuest', 'tools': {'beforeGuestStandby': True, @@ -692,6 +704,9 @@ class VMwareVMUtilTestCase(test.NoDBTestCase): 'key': 'nvp.vm-uuid', 'obj_name': 'ns0:OptionValue'}], 'memoryMB': 2048, + 'managedBy': {'extensionKey': 'org.openstack.compute', + 'type': 'instance', + 'obj_name': 'ns0:ManagedByInfo'}, 'obj_name': 'ns0:VirtualMachineConfigSpec', 'guestId': 'otherGuest', 'tools': {'beforeGuestStandby': True, diff --git a/nova/virt/vmwareapi/constants.py b/nova/virt/vmwareapi/constants.py index 0e1c3064132d..ddb0b3034484 100644 --- a/nova/virt/vmwareapi/constants.py +++ b/nova/virt/vmwareapi/constants.py @@ -37,3 +37,6 @@ ADAPTER_TYPE_LSILOGICSAS = "lsiLogicsas" ADAPTER_TYPE_PARAVIRTUAL = "paraVirtual" SUPPORTED_FLAT_VARIANTS = ["thin", "preallocated", "thick", "eagerZeroedThick"] + +EXTENSION_KEY = 'org.openstack.compute' +EXTENSION_TYPE_INSTANCE = 'instance' diff --git a/nova/virt/vmwareapi/driver.py b/nova/virt/vmwareapi/driver.py index f56eb44aa41a..43e4ea2120b7 100644 --- a/nova/virt/vmwareapi/driver.py +++ b/nova/virt/vmwareapi/driver.py @@ -34,6 +34,7 @@ from nova.i18n import _, _LW from nova.openstack.common import log as logging from nova.openstack.common import uuidutils from nova.virt import driver +from nova.virt.vmwareapi import constants from nova.virt.vmwareapi import error_util from nova.virt.vmwareapi import host from nova.virt.vmwareapi import vm_util @@ -191,6 +192,9 @@ class VMwareVCDriver(driver.ComputeDriver): self._volumeops = self._resources.get(first_cluster).get('volumeops') self._vc_state = self._resources.get(first_cluster).get('vcstate') + # Register the OpenStack extension + self._register_openstack_extension() + def _update_pbm_location(self): if CONF.vmware.pbm_wsdl_location: pbm_wsdl_loc = CONF.vmware.pbm_wsdl_location @@ -234,6 +238,19 @@ class VMwareVCDriver(driver.ComputeDriver): except suds.WebFault: LOG.debug("No vSphere session was open during cleanup_host.") + def _register_openstack_extension(self): + # Register an 'OpenStack' extension in vCenter + LOG.debug('Registering extension %s with vCenter', + constants.EXTENSION_KEY) + os_extension = self._session._call_method(vim_util, 'find_extension', + constants.EXTENSION_KEY) + if os_extension is None: + LOG.debug('Extension does not exist. Registering type %s.', + constants.EXTENSION_TYPE_INSTANCE) + self._session._call_method(vim_util, 'register_extension', + constants.EXTENSION_KEY, + constants.EXTENSION_TYPE_INSTANCE) + def cleanup(self, context, instance, network_info, block_device_info=None, destroy_disks=True, migrate_data=None, destroy_vifs=True): """Cleanup after instance being destroyed by Hypervisor.""" diff --git a/nova/virt/vmwareapi/vm_util.py b/nova/virt/vmwareapi/vm_util.py index 206f09e60267..658f23a69e7a 100644 --- a/nova/virt/vmwareapi/vm_util.py +++ b/nova/virt/vmwareapi/vm_util.py @@ -176,6 +176,12 @@ def get_vm_create_spec(client_factory, instance, name, data_store_name, config_spec.extraConfig = extra_config + # Set the VM to be 'managed' by 'OpenStack' + managed_by = client_factory.create('ns0:ManagedByInfo') + managed_by.extensionKey = constants.EXTENSION_KEY + managed_by.type = constants.EXTENSION_TYPE_INSTANCE + config_spec.managedBy = managed_by + return config_spec