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:
Gary Kotton
2014-06-17 05:05:06 -07:00
parent 1ada993c32
commit f4fec08e98
7 changed files with 72 additions and 4 deletions

View File

@@ -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()

View File

@@ -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)

View File

@@ -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))

View File

@@ -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,

View File

@@ -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'

View File

@@ -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."""

View File

@@ -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