VMware: improve instance names on VC
Up until now the instance name of the VM on the VC was the UUID of the instance. This is very confusing for administrators and they would like some context for the VM. This will now be: <display-name> (<instance-uuid>) Once the the instance is created we will perform a rename. The reason for this is that the disks are all stored under a folder on the datastore that has the name of the instance UUID. NOTE: this is only for the display on the VC. The search for the VM's is done via the instanceUUID configured on the VM. If that fails then the nvp.uuid extra spec is used for the search. This completed the blueprint vmware-better-display-names Closes-bug: #1330873 Change-Id: Ibeb000f4c1d88fa296390143b0cf98e05e735086
This commit is contained in:
parent
23907ba774
commit
47e3a4e961
|
@ -1325,6 +1325,13 @@ class FakeVim(object):
|
|||
task_mdo = create_task(method, "success")
|
||||
return task_mdo.obj
|
||||
|
||||
def _rename(self, method, *args, **kwargs):
|
||||
vm_ref = args[0]
|
||||
vm_mdo = _get_vm_mdo(vm_ref)
|
||||
vm_mdo.set('name', kwargs['newName'])
|
||||
task_mdo = create_task(method, "success")
|
||||
return task_mdo.obj
|
||||
|
||||
def _create_copy_disk(self, method, vmdk_file_path):
|
||||
"""Creates/copies a vmdk file object in the datastore."""
|
||||
# We need to add/create both .vmdk and .-flat.vmdk files
|
||||
|
@ -1589,6 +1596,9 @@ class FakeVim(object):
|
|||
elif attr_name == "ReconfigVM_Task":
|
||||
return lambda *args, **kwargs: self._reconfig_vm(attr_name,
|
||||
*args, **kwargs)
|
||||
elif attr_name == "Rename_Task":
|
||||
return lambda *args, **kwargs: self._rename(attr_name,
|
||||
*args, **kwargs)
|
||||
elif attr_name == "CreateVirtualDisk_Task":
|
||||
return lambda *args, **kwargs: self._create_copy_disk(attr_name,
|
||||
kwargs.get("name"))
|
||||
|
|
|
@ -177,6 +177,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
|
|||
self._set_exception_vars()
|
||||
self.node_name = self.conn._nodename
|
||||
self.ds = 'ds1'
|
||||
self._display_name = 'fake-display-name'
|
||||
|
||||
self.vim = vmwareapi_fake.FakeVim()
|
||||
|
||||
|
@ -301,6 +302,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
|
|||
if ephemeral is not None:
|
||||
self.type_data['ephemeral_gb'] = ephemeral
|
||||
values = {'name': 'fake_name',
|
||||
'display_name': self._display_name,
|
||||
'id': 1,
|
||||
'uuid': uuid,
|
||||
'project_id': self.project_id,
|
||||
|
@ -348,7 +350,8 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
|
|||
# Get record for VM
|
||||
vms = vmwareapi_fake._get_objects("VirtualMachine")
|
||||
for vm in vms.objects:
|
||||
if vm.get('name') == self.uuid:
|
||||
if vm.get('name') == vm_util._get_vm_name(self._display_name,
|
||||
self.uuid):
|
||||
return vm
|
||||
self.fail('Unable to find VM backing!')
|
||||
|
||||
|
@ -439,11 +442,6 @@ class VMwareAPIVMTestCase(test.NoDBTestCase):
|
|||
uuids = self.conn.list_instance_uuids()
|
||||
self.assertEqual(1, len(uuids))
|
||||
|
||||
def test_list_instance_uuids_invalid_uuid(self):
|
||||
self._create_vm(uuid='fake_id')
|
||||
uuids = self.conn.list_instance_uuids()
|
||||
self.assertEqual(0, len(uuids))
|
||||
|
||||
def _cached_files_exist(self, exists=True):
|
||||
cache = ds_obj.DatastorePath(self.ds, 'vmware_base',
|
||||
self.fake_image_uuid,
|
||||
|
|
|
@ -49,6 +49,7 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
|
|||
self._instance = fake_instance.fake_instance_obj(
|
||||
None,
|
||||
**{'id': 7, 'name': 'fake!',
|
||||
'display_name': 'fake-display-name',
|
||||
'uuid': uuidutils.generate_uuid(),
|
||||
'vcpus': 2, 'memory_mb': 2048})
|
||||
|
||||
|
@ -1732,6 +1733,39 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
|
|||
vm_util.folder_ref_cache_update(path, 'fake-ref')
|
||||
self.assertEqual('fake-ref', vm_util.folder_ref_cache_get(path))
|
||||
|
||||
def test_get_vm_name(self):
|
||||
uuid = uuidutils.generate_uuid()
|
||||
expected = uuid
|
||||
name = vm_util._get_vm_name(None, uuid)
|
||||
self.assertEqual(expected, name)
|
||||
|
||||
display_name = 'fira'
|
||||
expected = 'fira (%s)' % uuid
|
||||
name = vm_util._get_vm_name(display_name, uuid)
|
||||
self.assertEqual(expected, name)
|
||||
|
||||
display_name = 'X' * 255
|
||||
expected = '%s (%s)' % ('X' * 41, uuid)
|
||||
name = vm_util._get_vm_name(display_name, uuid)
|
||||
self.assertEqual(expected, name)
|
||||
self.assertEqual(len(name), 80)
|
||||
|
||||
@mock.patch.object(vm_util, '_get_vm_name', return_value='fake-name')
|
||||
def test_rename_vm(self, mock_get_name):
|
||||
session = fake.FakeSession()
|
||||
with test.nested(
|
||||
mock.patch.object(session, '_call_method',
|
||||
return_value='fake_rename_task'),
|
||||
mock.patch.object(session, '_wait_for_task')
|
||||
) as (_call_method, _wait_for_task):
|
||||
vm_util.rename_vm(session, 'fake-ref', self._instance)
|
||||
_call_method.assert_called_once_with(mock.ANY,
|
||||
'Rename_Task', 'fake-ref', newName='fake-name')
|
||||
_wait_for_task.assert_called_once_with(
|
||||
'fake_rename_task')
|
||||
mock_get_name.assert_called_once_with(self._instance.display_name,
|
||||
self._instance.uuid)
|
||||
|
||||
|
||||
@mock.patch.object(driver.VMwareAPISession, 'vim', stubs.fake_vim_prop)
|
||||
class VMwareVMUtilGetHostRefTestCase(test.NoDBTestCase):
|
||||
|
|
|
@ -81,6 +81,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
self._instance_values = {
|
||||
'display_name': 'fake_display_name',
|
||||
'name': 'fake_name',
|
||||
'display_name': 'fake_display_name',
|
||||
'uuid': 'fake_uuid',
|
||||
'vcpus': 1,
|
||||
'memory_mb': 512,
|
||||
|
@ -203,12 +204,12 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
def test_get_valid_vms_from_retrieve_result(self, _mock_cont):
|
||||
ops = vmops.VMwareVMOps(self._session, mock.Mock(), mock.Mock())
|
||||
fake_objects = vmwareapi_fake.FakeRetrieveResult()
|
||||
fake_objects.add_object(vmwareapi_fake.VirtualMachine(
|
||||
name=uuidutils.generate_uuid()))
|
||||
fake_objects.add_object(vmwareapi_fake.VirtualMachine(
|
||||
name=uuidutils.generate_uuid()))
|
||||
fake_objects.add_object(vmwareapi_fake.VirtualMachine(
|
||||
name=uuidutils.generate_uuid()))
|
||||
for x in range(0, 3):
|
||||
vm = vmwareapi_fake.VirtualMachine()
|
||||
vm.set('config.extraConfig["nvp.vm-uuid"]',
|
||||
vmwareapi_fake.OptionValue(
|
||||
value=uuidutils.generate_uuid()))
|
||||
fake_objects.add_object(vm)
|
||||
vms = ops._get_valid_vms_from_retrieve_result(fake_objects)
|
||||
self.assertEqual(3, len(vms))
|
||||
|
||||
|
@ -217,14 +218,21 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
_mock_cont):
|
||||
ops = vmops.VMwareVMOps(self._session, mock.Mock(), mock.Mock())
|
||||
fake_objects = vmwareapi_fake.FakeRetrieveResult()
|
||||
fake_objects.add_object(vmwareapi_fake.VirtualMachine(
|
||||
name=uuidutils.generate_uuid()))
|
||||
invalid_vm1 = vmwareapi_fake.VirtualMachine(
|
||||
name=uuidutils.generate_uuid())
|
||||
valid_vm = vmwareapi_fake.VirtualMachine()
|
||||
valid_vm.set('config.extraConfig["nvp.vm-uuid"]',
|
||||
vmwareapi_fake.OptionValue(
|
||||
value=uuidutils.generate_uuid()))
|
||||
fake_objects.add_object(valid_vm)
|
||||
invalid_vm1 = vmwareapi_fake.VirtualMachine()
|
||||
invalid_vm1.set('runtime.connectionState', 'orphaned')
|
||||
invalid_vm2 = vmwareapi_fake.VirtualMachine(
|
||||
name=uuidutils.generate_uuid())
|
||||
invalid_vm1.set('config.extraConfig["nvp.vm-uuid"]',
|
||||
vmwareapi_fake.OptionValue(
|
||||
value=uuidutils.generate_uuid()))
|
||||
invalid_vm2 = vmwareapi_fake.VirtualMachine()
|
||||
invalid_vm2.set('runtime.connectionState', 'inaccessible')
|
||||
invalid_vm2.set('config.extraConfig["nvp.vm-uuid"]',
|
||||
vmwareapi_fake.OptionValue(
|
||||
value=uuidutils.generate_uuid()))
|
||||
fake_objects.add_object(invalid_vm1)
|
||||
fake_objects.add_object(invalid_vm2)
|
||||
vms = ops._get_valid_vms_from_retrieve_result(fake_objects)
|
||||
|
@ -944,6 +952,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
'image_id': image_id,
|
||||
'version': version.version_string_with_package()})
|
||||
|
||||
@mock.patch.object(vm_util, 'rename_vm')
|
||||
@mock.patch.object(vmops.VMwareVMOps, '_create_folders',
|
||||
return_value='fake_vm_folder')
|
||||
@mock.patch('nova.virt.vmwareapi.vm_util.power_on_instance')
|
||||
|
@ -963,7 +972,8 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
enlist_image, fetch_image,
|
||||
use_disk_image,
|
||||
power_on_instance,
|
||||
create_folders):
|
||||
create_folders,
|
||||
rename_vm):
|
||||
self._instance.flavor = self._flavor
|
||||
extra_specs = get_extra_specs.return_value
|
||||
connection_info1 = {'data': 'fake-data1', 'serial': 'volume-fake-id1'}
|
||||
|
@ -1007,6 +1017,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
connection_info2, self._instance,
|
||||
constants.DEFAULT_ADAPTER_TYPE)
|
||||
|
||||
@mock.patch.object(vm_util, 'rename_vm')
|
||||
@mock.patch.object(vmops.VMwareVMOps, '_create_folders',
|
||||
return_value='fake_vm_folder')
|
||||
@mock.patch('nova.virt.vmwareapi.vm_util.power_on_instance')
|
||||
|
@ -1020,7 +1031,8 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
get_vm_config_info,
|
||||
build_virtual_machine,
|
||||
power_on_instance,
|
||||
create_folders):
|
||||
create_folders,
|
||||
rename_vm):
|
||||
self._instance.image_ref = None
|
||||
self._instance.flavor = self._flavor
|
||||
extra_specs = get_extra_specs.return_value
|
||||
|
@ -1294,6 +1306,8 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
if extras:
|
||||
expected_methods.extend(extras)
|
||||
|
||||
# Last call should be renaming the instance
|
||||
expected_methods.append('Rename_Task')
|
||||
recorded_methods = [c[1][1] for c in mock_call_method.mock_calls]
|
||||
self.assertEqual(expected_methods, recorded_methods)
|
||||
|
||||
|
@ -1570,6 +1584,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
'device_name': '/dev/sdb'}}
|
||||
self._test_spawn(block_device_info=block_device_info)
|
||||
|
||||
@mock.patch.object(vm_util, 'rename_vm')
|
||||
@mock.patch('nova.virt.vmwareapi.vm_util.power_on_instance')
|
||||
@mock.patch.object(vmops.VMwareVMOps, '_create_and_attach_thin_disk')
|
||||
@mock.patch.object(vmops.VMwareVMOps, '_use_disk_image_as_linked_clone')
|
||||
|
@ -1589,7 +1604,8 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
fetch_image,
|
||||
use_disk_image,
|
||||
create_and_attach_thin_disk,
|
||||
power_on_instance):
|
||||
power_on_instance,
|
||||
rename_vm):
|
||||
self._instance.flavor = objects.Flavor(vcpus=1, memory_mb=512,
|
||||
name="m1.tiny", root_gb=1,
|
||||
ephemeral_gb=1, swap=512,
|
||||
|
|
|
@ -1608,3 +1608,17 @@ def folder_ref_cache_update(path, folder_ref):
|
|||
|
||||
def folder_ref_cache_get(path):
|
||||
return _FOLDER_PATH_REF_MAPPING.get(path)
|
||||
|
||||
|
||||
def _get_vm_name(display_name, id):
|
||||
if display_name:
|
||||
return '%s (%s)' % (display_name[:41], id[:36])
|
||||
else:
|
||||
return id[:36]
|
||||
|
||||
|
||||
def rename_vm(session, vm_ref, instance):
|
||||
vm_name = _get_vm_name(instance.display_name, instance.uuid)
|
||||
rename_task = session._call_method(session.vim, "Rename_Task", vm_ref,
|
||||
newName=vm_name)
|
||||
session._wait_for_task(rename_task)
|
||||
|
|
|
@ -785,6 +785,11 @@ class VMwareVMOps(object):
|
|||
instance, vm_ref, vi.dc_info, vi.datastore,
|
||||
injected_files, admin_password, network_info)
|
||||
|
||||
# Rename the VM. This is done after the spec is created to ensure
|
||||
# that all of the files for the instance are under the directory
|
||||
# 'uuid' of the instance
|
||||
vm_util.rename_vm(self._session, vm_ref, instance)
|
||||
|
||||
vm_util.power_on_instance(self._session, instance, vm_ref=vm_ref)
|
||||
|
||||
def _is_bdm_valid(self, block_device_mapping):
|
||||
|
@ -1674,17 +1679,19 @@ class VMwareVMOps(object):
|
|||
|
||||
while retrieve_result:
|
||||
for vm in retrieve_result.objects:
|
||||
vm_name = None
|
||||
vm_uuid = None
|
||||
conn_state = None
|
||||
for prop in vm.propSet:
|
||||
if prop.name == "name":
|
||||
vm_name = prop.val
|
||||
elif prop.name == "runtime.connectionState":
|
||||
if prop.name == "runtime.connectionState":
|
||||
conn_state = prop.val
|
||||
elif prop.name == 'config.extraConfig["nvp.vm-uuid"]':
|
||||
vm_uuid = prop.val.value
|
||||
# Ignore VM's that do not have nvp.vm-uuid defined
|
||||
if not vm_uuid:
|
||||
continue
|
||||
# Ignoring the orphaned or inaccessible VMs
|
||||
if (conn_state not in ["orphaned", "inaccessible"] and
|
||||
uuidutils.is_uuid_like(vm_name)):
|
||||
lst_vm_names.append(vm_name)
|
||||
if conn_state not in ["orphaned", "inaccessible"]:
|
||||
lst_vm_names.append(vm_uuid)
|
||||
retrieve_result = self._session._call_method(vutil,
|
||||
'continue_retrieval',
|
||||
retrieve_result)
|
||||
|
@ -1911,7 +1918,8 @@ class VMwareVMOps(object):
|
|||
|
||||
def list_instances(self):
|
||||
"""Lists the VM instances that are registered with vCenter cluster."""
|
||||
properties = ['name', 'runtime.connectionState']
|
||||
properties = ['runtime.connectionState',
|
||||
'config.extraConfig["nvp.vm-uuid"]']
|
||||
LOG.debug("Getting list of instances from cluster %s",
|
||||
self._cluster)
|
||||
vms = []
|
||||
|
|
Loading…
Reference in New Issue