VMware: mark virtual machines as 'belonging' to OpenStack
This patch registers an extension in vCenter that indicates that the VM's that are run from OpenStack will belong to OpenStack. If an administrator tries to update the VM via vCenter then they will get the following message: "Solution OpenStack manages the selected virtual machine. You should not modify the virtual machine directly. Use the management console of the solution to make changes. Do you want to proceed?" The extension will be called 'org.openstack.compute'. This will make use of a type called 'instance'. Closes-bug: #1366506 Change-Id: I1046576c448704841ae8e1800b8390e947b0d457
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -33,6 +33,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))
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -34,6 +34,7 @@ from nova.openstack.common import jsonutils
|
||||
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."""
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user