Merge "VMware: StableMoRefProxy for moref recovery"
This commit is contained in:
commit
3ac9948f98
|
@ -23,11 +23,11 @@ import collections
|
|||
import sys
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import units
|
||||
from oslo_utils import uuidutils
|
||||
from oslo_vmware import exceptions as vexc
|
||||
from oslo_vmware.objects import datastore as ds_obj
|
||||
from oslo_vmware import vim_util
|
||||
|
||||
from nova import exception
|
||||
from nova.virt.vmwareapi import constants
|
||||
|
@ -76,23 +76,34 @@ def cleanup():
|
|||
_db_content[c] = {}
|
||||
|
||||
|
||||
def _create_object(table, table_obj):
|
||||
def _create_object(table_obj):
|
||||
"""Create an object in the db."""
|
||||
_db_content.setdefault(table, {})
|
||||
_db_content[table][table_obj.obj] = table_obj
|
||||
_db_content.setdefault(table_obj.obj._type, {})
|
||||
update_object(table_obj)
|
||||
|
||||
|
||||
def _get_object(obj_ref):
|
||||
def get_object(obj_ref):
|
||||
"""Get object for the give reference."""
|
||||
return _db_content[obj_ref.type][obj_ref]
|
||||
return _db_content[obj_ref.type][obj_ref.value]
|
||||
|
||||
|
||||
def _get_objects(obj_type):
|
||||
def get_objects(obj_type):
|
||||
"""Get objects of the type."""
|
||||
lst_objs = FakeRetrieveResult()
|
||||
for key in _db_content[obj_type]:
|
||||
lst_objs.add_object(_db_content[obj_type][key])
|
||||
return lst_objs
|
||||
return _db_content[obj_type].values()
|
||||
|
||||
|
||||
def get_first_object(obj_type):
|
||||
"""Get the first object of an object type"""
|
||||
return next(iter(_db_content[obj_type].values()))
|
||||
|
||||
|
||||
def get_first_object_ref(obj_type):
|
||||
"""Get the first reference of an object type"""
|
||||
return get_first_object(obj_type).obj
|
||||
|
||||
|
||||
def _no_objects_of_type(obj_type):
|
||||
return not _db_content.get(obj_type)
|
||||
|
||||
|
||||
def _convert_to_array_of_mor(mors):
|
||||
|
@ -135,21 +146,19 @@ class FakeRetrieveResult(object):
|
|||
if token is not None:
|
||||
self.token = token
|
||||
|
||||
def add_object(self, object):
|
||||
self.objects.append(object)
|
||||
def add_object(self, obj):
|
||||
self.objects.append(obj)
|
||||
|
||||
|
||||
def _get_object_refs(obj_type):
|
||||
"""Get object References of the type."""
|
||||
lst_objs = []
|
||||
for key in _db_content[obj_type]:
|
||||
lst_objs.append(key)
|
||||
return lst_objs
|
||||
def get_object_refs(obj_type):
|
||||
"""Get iterator over object References of the type."""
|
||||
for obj in _db_content[obj_type].values():
|
||||
yield obj.obj
|
||||
|
||||
|
||||
def _update_object(table, table_obj):
|
||||
def update_object(table_obj):
|
||||
"""Update objects of the type."""
|
||||
_db_content[table][table_obj.obj] = table_obj
|
||||
_db_content[table_obj.obj._type][table_obj.obj.value] = table_obj
|
||||
|
||||
|
||||
class Prop(object):
|
||||
|
@ -177,6 +186,14 @@ class ManagedObjectReference(object):
|
|||
self.type = name
|
||||
self._type = name
|
||||
|
||||
def __repr__(self):
|
||||
return f'{self._type}:{self.value}'
|
||||
|
||||
def __eq__(self, other):
|
||||
return (other is not None and
|
||||
vim_util.get_moref_value(other) == self.value and
|
||||
vim_util.get_moref_type(other) == self.type)
|
||||
|
||||
|
||||
class ObjectContent(object):
|
||||
"""ObjectContent array holds dynamic properties."""
|
||||
|
@ -262,8 +279,11 @@ class ManagedObject(object):
|
|||
return prefix + "-" + str(self.__class__._counter)
|
||||
|
||||
def __repr__(self):
|
||||
return jsonutils.dumps({elem.name: elem.val
|
||||
for elem in self.propSet})
|
||||
# We can't just dump the managed-object, because it may be circular
|
||||
return "{}:{}({})".format(self.obj._type, self.obj.value,
|
||||
", ".join(
|
||||
"{}={}".format(p.name, p.val if p.name == "name" else "<>")
|
||||
for p in self.propSet))
|
||||
|
||||
|
||||
class DataObject(object):
|
||||
|
@ -593,8 +613,7 @@ class ResourcePool(ManagedObject):
|
|||
class DatastoreHostMount(DataObject):
|
||||
def __init__(self, value='host-100'):
|
||||
super(DatastoreHostMount, self).__init__()
|
||||
host_ref = (_db_content["HostSystem"]
|
||||
[list(_db_content["HostSystem"].keys())[0]].obj)
|
||||
host_ref = get_first_object_ref("HostSystem")
|
||||
host_system = DataObject()
|
||||
host_system.ManagedObjectReference = [host_ref]
|
||||
host_system.value = value
|
||||
|
@ -621,9 +640,15 @@ class ClusterComputeResource(ManagedObject):
|
|||
summary.effectiveCpu = 10000
|
||||
self.set("summary", summary)
|
||||
|
||||
vm_list = DataObject()
|
||||
vm_list.ManagedObjectReference = []
|
||||
self.set("vm", vm_list)
|
||||
|
||||
def _add_root_resource_pool(self, r_pool):
|
||||
if r_pool:
|
||||
self.set("resourcePool", r_pool)
|
||||
pool = get_object(r_pool)
|
||||
self.set("vm", pool.get("vm"))
|
||||
|
||||
def _add_host(self, host_sys):
|
||||
if host_sys:
|
||||
|
@ -659,7 +684,7 @@ class ClusterComputeResource(ManagedObject):
|
|||
# Compute the aggregate stats
|
||||
summary.numHosts = len(hosts.ManagedObjectReference)
|
||||
for host_ref in hosts.ManagedObjectReference:
|
||||
host_sys = _get_object(host_ref)
|
||||
host_sys = get_object(host_ref)
|
||||
connected = host_sys.get("connected")
|
||||
host_summary = host_sys.get("summary")
|
||||
summary.numCpuCores += host_summary.hardware.numCpuCores
|
||||
|
@ -717,14 +742,17 @@ class HostSystem(ManagedObject):
|
|||
maintenance_mode=False):
|
||||
super(HostSystem, self).__init__("host")
|
||||
self.set("name", name)
|
||||
if _db_content.get("HostNetworkSystem", None) is None:
|
||||
if _no_objects_of_type("HostNetworkSystem"):
|
||||
create_host_network_system()
|
||||
if not _get_object_refs('HostStorageSystem'):
|
||||
|
||||
if _no_objects_of_type("HostStorageSystem"):
|
||||
create_host_storage_system()
|
||||
host_net_key = list(_db_content["HostNetworkSystem"].keys())[0]
|
||||
host_net_sys = _db_content["HostNetworkSystem"][host_net_key].obj
|
||||
self.set("configManager.networkSystem", host_net_sys)
|
||||
host_storage_sys_key = _get_object_refs('HostStorageSystem')[0]
|
||||
|
||||
host_net_obj = get_first_object("HostNetworkSystem")
|
||||
host_net_ref = host_net_obj.obj
|
||||
self.set("configManager.networkSystem", host_net_ref)
|
||||
|
||||
host_storage_sys_key = get_first_object_ref('HostStorageSystem')
|
||||
self.set("configManager.storageSystem", host_storage_sys_key)
|
||||
|
||||
if not ds_ref:
|
||||
|
@ -779,10 +807,9 @@ class HostSystem(ManagedObject):
|
|||
self.set("config.network.pnic", net_info_pnic)
|
||||
self.set("connected", connected)
|
||||
|
||||
if _db_content.get("Network", None) is None:
|
||||
if _no_objects_of_type("Network"):
|
||||
create_network()
|
||||
net_ref = _db_content["Network"][
|
||||
list(_db_content["Network"].keys())[0]].obj
|
||||
net_ref = get_first_object_ref("Network")
|
||||
network_do = DataObject()
|
||||
network_do.ManagedObjectReference = [net_ref]
|
||||
self.set("network", network_do)
|
||||
|
@ -821,7 +848,7 @@ class HostSystem(ManagedObject):
|
|||
self.set("config.storageDevice.hostBusAdapter", host_bus_adapter_array)
|
||||
|
||||
# Set the same on the storage system managed object
|
||||
host_storage_sys = _get_object(host_storage_sys_key)
|
||||
host_storage_sys = get_object(host_storage_sys_key)
|
||||
host_storage_sys.set('storageDeviceInfo.hostBusAdapter',
|
||||
host_bus_adapter_array)
|
||||
|
||||
|
@ -882,17 +909,15 @@ class Datacenter(ManagedObject):
|
|||
def __init__(self, name="ha-datacenter", ds_ref=None):
|
||||
super(Datacenter, self).__init__("dc")
|
||||
self.set("name", name)
|
||||
if _db_content.get("Folder", None) is None:
|
||||
if _no_objects_of_type("Folder"):
|
||||
create_folder()
|
||||
folder_ref = _db_content["Folder"][
|
||||
list(_db_content["Folder"].keys())[0]].obj
|
||||
folder_ref = get_first_object_ref("Folder")
|
||||
folder_do = DataObject()
|
||||
folder_do.ManagedObjectReference = [folder_ref]
|
||||
self.set("vmFolder", folder_ref)
|
||||
if _db_content.get("Network", None) is None:
|
||||
if _no_objects_of_type("Network"):
|
||||
create_network()
|
||||
net_ref = _db_content["Network"][
|
||||
list(_db_content["Network"].keys())[0]].obj
|
||||
net_ref = get_first_object_ref("Network")
|
||||
network_do = DataObject()
|
||||
network_do.ManagedObjectReference = [net_ref]
|
||||
self.set("network", network_do)
|
||||
|
@ -927,54 +952,56 @@ class Task(ManagedObject):
|
|||
|
||||
def create_host_network_system():
|
||||
host_net_system = HostNetworkSystem()
|
||||
_create_object("HostNetworkSystem", host_net_system)
|
||||
_create_object(host_net_system)
|
||||
|
||||
|
||||
def create_host_storage_system():
|
||||
host_storage_system = HostStorageSystem()
|
||||
_create_object("HostStorageSystem", host_storage_system)
|
||||
_create_object(host_storage_system)
|
||||
|
||||
|
||||
def create_host(ds_ref=None):
|
||||
host_system = HostSystem(ds_ref=ds_ref)
|
||||
_create_object('HostSystem', host_system)
|
||||
_create_object(host_system)
|
||||
|
||||
|
||||
def create_datacenter(name, ds_ref=None):
|
||||
data_center = Datacenter(name, ds_ref)
|
||||
_create_object('Datacenter', data_center)
|
||||
_create_object(data_center)
|
||||
|
||||
|
||||
def create_datastore(name, capacity, free):
|
||||
data_store = Datastore(name, capacity, free)
|
||||
_create_object('Datastore', data_store)
|
||||
_create_object(data_store)
|
||||
return data_store.obj
|
||||
|
||||
|
||||
def create_res_pool():
|
||||
res_pool = ResourcePool()
|
||||
_create_object('ResourcePool', res_pool)
|
||||
_create_object(res_pool)
|
||||
return res_pool.obj
|
||||
|
||||
|
||||
def create_folder():
|
||||
folder = Folder()
|
||||
_create_object('Folder', folder)
|
||||
_create_object(folder)
|
||||
return folder.obj
|
||||
|
||||
|
||||
def create_network():
|
||||
network = Network()
|
||||
_create_object('Network', network)
|
||||
_create_object(network)
|
||||
|
||||
|
||||
def create_cluster(name, ds_ref):
|
||||
cluster = ClusterComputeResource(name=name)
|
||||
cluster._add_host(_get_object_refs("HostSystem")[0])
|
||||
cluster._add_host(_get_object_refs("HostSystem")[1])
|
||||
for i, host in enumerate(get_object_refs("HostSystem")):
|
||||
cluster._add_host(host)
|
||||
if i >= 1:
|
||||
break
|
||||
cluster._add_datastore(ds_ref)
|
||||
cluster._add_root_resource_pool(create_res_pool())
|
||||
_create_object('ClusterComputeResource', cluster)
|
||||
_create_object(cluster)
|
||||
return cluster
|
||||
|
||||
|
||||
|
@ -993,16 +1020,15 @@ def create_vm(uuid=None, name=None,
|
|||
devices = []
|
||||
|
||||
if vmPathName is None:
|
||||
vm_path = ds_obj.DatastorePath(
|
||||
list(_db_content['Datastore'].values())[0])
|
||||
vm_path = ds_obj.DatastorePath(get_first_object("Datastore"))
|
||||
else:
|
||||
vm_path = ds_obj.DatastorePath.parse(vmPathName)
|
||||
|
||||
if res_pool_ref is None:
|
||||
res_pool_ref = list(_db_content['ResourcePool'].keys())[0]
|
||||
res_pool_ref = get_first_object_ref("ResourcePool")
|
||||
|
||||
if host_ref is None:
|
||||
host_ref = list(_db_content["HostSystem"].keys())[0]
|
||||
host_ref = get_first_object_ref("HostSystem")
|
||||
|
||||
# Fill in the default path to the vmx file if we were only given a
|
||||
# datastore. Note that if you create a VM with vmPathName '[foo]', when you
|
||||
|
@ -1011,9 +1037,9 @@ def create_vm(uuid=None, name=None,
|
|||
if vm_path.rel_path == '':
|
||||
vm_path = vm_path.join(name, name + '.vmx')
|
||||
|
||||
for key, value in _db_content["Datastore"].items():
|
||||
for value in get_objects("Datastore"):
|
||||
if value.get('summary.name') == vm_path.datastore:
|
||||
ds = key
|
||||
ds = value.obj
|
||||
break
|
||||
else:
|
||||
ds = create_datastore(vm_path.datastore, 1024, 500)
|
||||
|
@ -1030,9 +1056,9 @@ def create_vm(uuid=None, name=None,
|
|||
"instanceUuid": uuid,
|
||||
"version": version}
|
||||
vm = VirtualMachine(**vm_dict)
|
||||
_create_object("VirtualMachine", vm)
|
||||
_create_object(vm)
|
||||
|
||||
res_pool = _get_object(res_pool_ref)
|
||||
res_pool = get_object(res_pool_ref)
|
||||
res_pool.vm.ManagedObjectReference.append(vm.obj)
|
||||
|
||||
return vm.obj
|
||||
|
@ -1040,7 +1066,7 @@ def create_vm(uuid=None, name=None,
|
|||
|
||||
def create_task(task_name, state="running", result=None, error_fault=None):
|
||||
task = Task(task_name, state, result, error_fault)
|
||||
_create_object("Task", task)
|
||||
_create_object(task)
|
||||
return task
|
||||
|
||||
|
||||
|
@ -1103,12 +1129,14 @@ def fake_fetch_image(context, instance, host, port, dc_name, ds_name,
|
|||
|
||||
def _get_vm_mdo(vm_ref):
|
||||
"""Gets the Virtual Machine with the ref from the db."""
|
||||
if _db_content.get("VirtualMachine", None) is None:
|
||||
vms = _db_content.get("VirtualMachine")
|
||||
if not vms:
|
||||
raise exception.NotFound("There is no VM registered")
|
||||
if vm_ref not in _db_content.get("VirtualMachine"):
|
||||
try:
|
||||
return vms[vm_ref.value]
|
||||
except KeyError:
|
||||
raise exception.NotFound("Virtual Machine with ref %s is not "
|
||||
"there" % vm_ref)
|
||||
return _db_content.get("VirtualMachine")[vm_ref]
|
||||
"there" % vm_ref.value)
|
||||
|
||||
|
||||
def _merge_extraconfig(existing, changes):
|
||||
|
@ -1354,11 +1382,10 @@ class FakeVim(object):
|
|||
def _find_all_by_uuid(self, *args, **kwargs):
|
||||
uuid = kwargs.get('uuid')
|
||||
vm_refs = []
|
||||
for vm_ref in _db_content.get("VirtualMachine"):
|
||||
vm = _get_object(vm_ref)
|
||||
for vm in get_objects("VirtualMachine"):
|
||||
vm_uuid = vm.get("summary.config.instanceUuid")
|
||||
if vm_uuid == uuid:
|
||||
vm_refs.append(vm_ref)
|
||||
vm_refs.append(vm.obj)
|
||||
return vm_refs
|
||||
|
||||
def _delete_snapshot(self, method, *args, **kwargs):
|
||||
|
@ -1412,7 +1439,7 @@ class FakeVim(object):
|
|||
vm_dict["extra_config"] = extraConfigs
|
||||
|
||||
virtual_machine = VirtualMachine(**vm_dict)
|
||||
_create_object("VirtualMachine", virtual_machine)
|
||||
_create_object(virtual_machine)
|
||||
task_mdo = create_task(method, "success")
|
||||
return task_mdo.obj
|
||||
|
||||
|
@ -1420,7 +1447,7 @@ class FakeVim(object):
|
|||
"""Unregisters a VM from the Host System."""
|
||||
vm_ref = args[0]
|
||||
_get_vm_mdo(vm_ref)
|
||||
del _db_content["VirtualMachine"][vm_ref]
|
||||
del _db_content["VirtualMachine"][vm_ref.value]
|
||||
task_mdo = create_task(method, "success")
|
||||
return task_mdo.obj
|
||||
|
||||
|
@ -1491,13 +1518,7 @@ class FakeVim(object):
|
|||
|
||||
def _set_power_state(self, method, vm_ref, pwr_state="poweredOn"):
|
||||
"""Sets power state for the VM."""
|
||||
if _db_content.get("VirtualMachine", None) is None:
|
||||
raise exception.NotFound("No Virtual Machine has been "
|
||||
"registered yet")
|
||||
if vm_ref not in _db_content.get("VirtualMachine"):
|
||||
raise exception.NotFound("Virtual Machine with ref %s is not "
|
||||
"there" % vm_ref)
|
||||
vm_mdo = _db_content.get("VirtualMachine").get(vm_ref)
|
||||
vm_mdo = _get_vm_mdo(vm_ref)
|
||||
vm_mdo.set("runtime.powerState", pwr_state)
|
||||
task_mdo = create_task(method, "success")
|
||||
return task_mdo.obj
|
||||
|
@ -1526,7 +1547,7 @@ class FakeVim(object):
|
|||
# This means that we are retrieving props for all managed
|
||||
# data objects of the specified 'type' in the entire
|
||||
# inventory. This gets invoked by vim_util.get_objects.
|
||||
mdo_refs = _db_content[spec_type]
|
||||
mdo_refs = list(get_object_refs(spec_type))
|
||||
elif obj_ref.type != spec_type:
|
||||
# This means that we are retrieving props for the managed
|
||||
# data objects in the parent object's 'path' property.
|
||||
|
@ -1536,7 +1557,7 @@ class FakeVim(object):
|
|||
# path = 'datastore'
|
||||
# the above will retrieve all datastores in the given
|
||||
# cluster.
|
||||
parent_mdo = _db_content[obj_ref.type][obj_ref]
|
||||
parent_mdo = get_object(obj_ref)
|
||||
path = obj.selectSet[0].path
|
||||
mdo_refs = parent_mdo.get(path).ManagedObjectReference
|
||||
else:
|
||||
|
@ -1545,12 +1566,13 @@ class FakeVim(object):
|
|||
# vim_util.get_properties_for_a_collection_of_objects.
|
||||
mdo_refs = [obj_ref]
|
||||
|
||||
mdo_list = _db_content[spec_type]
|
||||
for mdo_ref in mdo_refs:
|
||||
mdo = _db_content[spec_type][mdo_ref]
|
||||
prop_list = []
|
||||
for prop_name in properties:
|
||||
prop = Prop(prop_name, mdo.get(prop_name))
|
||||
prop_list.append(prop)
|
||||
mdo = mdo_list[mdo_ref.value]
|
||||
prop_list = [
|
||||
Prop(prop_name, mdo.get(prop_name))
|
||||
for prop_name in properties
|
||||
]
|
||||
obj_content = ObjectContent(mdo.obj, prop_list)
|
||||
lst_ret_objs.add_object(obj_content)
|
||||
except Exception:
|
||||
|
@ -1560,14 +1582,13 @@ class FakeVim(object):
|
|||
|
||||
def _add_port_group(self, method, *args, **kwargs):
|
||||
"""Adds a port group to the host system."""
|
||||
_host_sk = list(_db_content["HostSystem"].keys())[0]
|
||||
host_mdo = _db_content["HostSystem"][_host_sk]
|
||||
host_mdo = get_first_object("HostSystem")
|
||||
host_mdo._add_port_group(kwargs.get("portgrp"))
|
||||
|
||||
def _add_iscsi_send_tgt(self, method, *args, **kwargs):
|
||||
"""Adds a iscsi send target to the hba."""
|
||||
send_targets = kwargs.get('targets')
|
||||
host_storage_sys = _get_objects('HostStorageSystem').objects[0]
|
||||
host_storage_sys = get_first_object('HostStorageSystem')
|
||||
iscsi_hba_array = host_storage_sys.get('storageDeviceInfo'
|
||||
'.hostBusAdapter')
|
||||
iscsi_hba = iscsi_hba_array.HostHostBusAdapter[0]
|
||||
|
|
|
@ -373,8 +373,8 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
|
|||
|
||||
def _get_vm_record(self):
|
||||
# Get record for VM
|
||||
vms = vmwareapi_fake._get_objects("VirtualMachine")
|
||||
for vm in vms.objects:
|
||||
vms = vmwareapi_fake.get_objects("VirtualMachine")
|
||||
for vm in vms:
|
||||
if vm.get('name') == vm_util._get_vm_name(self._display_name,
|
||||
self.uuid):
|
||||
return vm
|
||||
|
@ -1269,7 +1269,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
|
|||
|
||||
def _snapshot_delete_vm_snapshot_exception(self, exception, call_count=1):
|
||||
self._create_vm()
|
||||
fake_vm = vmwareapi_fake._get_objects("VirtualMachine").objects[0].obj
|
||||
fake_vm = vmwareapi_fake.get_first_object_ref("VirtualMachine")
|
||||
snapshot_ref = vmwareapi_fake.ManagedObjectReference(
|
||||
value="Snapshot-123",
|
||||
name="VirtualMachineSnapshot")
|
||||
|
@ -1763,8 +1763,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
|
|||
|
||||
get_vm_ref.assert_called_once_with(self.conn._session,
|
||||
self.instance)
|
||||
get_volume_ref.assert_called_once_with(
|
||||
connection_info['data']['volume'])
|
||||
get_volume_ref.assert_called_once_with(connection_info['data'])
|
||||
self.assertTrue(get_vmdk_info.called)
|
||||
attach_disk_to_vm.assert_called_once_with(mock.sentinel.vm_ref,
|
||||
self.instance, adapter_type, disk_type, vmdk_path='fake-path')
|
||||
|
@ -1840,8 +1839,8 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
|
|||
|
||||
def test_iscsi_rescan_hba(self):
|
||||
fake_target_portal = 'fake_target_host:port'
|
||||
host_storage_sys = vmwareapi_fake._get_objects(
|
||||
"HostStorageSystem").objects[0]
|
||||
host_storage_sys = vmwareapi_fake.get_first_object(
|
||||
"HostStorageSystem")
|
||||
iscsi_hba_array = host_storage_sys.get('storageDeviceInfo'
|
||||
'.hostBusAdapter')
|
||||
iscsi_hba = iscsi_hba_array.HostHostBusAdapter[0]
|
||||
|
@ -1861,7 +1860,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
|
|||
def test_iscsi_get_target(self):
|
||||
data = {'target_portal': 'fake_target_host:port',
|
||||
'target_iqn': 'fake_target_iqn'}
|
||||
host = vmwareapi_fake._get_objects('HostSystem').objects[0]
|
||||
host = vmwareapi_fake.get_first_object('HostSystem')
|
||||
host._add_iscsi_target(data)
|
||||
vops = volumeops.VMwareVolumeOps(self.conn._session)
|
||||
result = vops._iscsi_get_target(data)
|
||||
|
|
|
@ -22,6 +22,9 @@ Test suite for VMwareAPI Session
|
|||
"""
|
||||
|
||||
import mock
|
||||
|
||||
from oslo_vmware import exceptions as vexec
|
||||
|
||||
from nova import test
|
||||
from nova.tests.unit.virt.vmwareapi import fake as vmwareapi_fake
|
||||
from nova.virt.vmwareapi import session
|
||||
|
@ -36,17 +39,47 @@ def _fake_create_session(inst):
|
|||
inst._session = _session
|
||||
|
||||
|
||||
def _fake_fetch_moref_impl(inst, _):
|
||||
inst.moref = vmwareapi_fake.ManagedObjectReference(
|
||||
value=mock.sentinel.moref2)
|
||||
|
||||
|
||||
class FakeStableMoRefProxy(session.StableMoRefProxy):
|
||||
def __init__(self, ref=None):
|
||||
super(FakeStableMoRefProxy, self).__init__(
|
||||
ref or vmwareapi_fake.ManagedObjectReference(
|
||||
value=mock.sentinel.moref))
|
||||
|
||||
def fetch_moref(self, session):
|
||||
pass
|
||||
|
||||
def __repr__(self):
|
||||
return "FakeStableMoRefProxy({!r})".format(self.moref)
|
||||
|
||||
|
||||
class StableMoRefProxyTestCase(test.NoDBTestCase):
|
||||
def test_proxy(self):
|
||||
ref = FakeStableMoRefProxy()
|
||||
self.assertEqual(mock.sentinel.moref, ref.value)
|
||||
self.assertEqual("ManagedObject", ref._type)
|
||||
|
||||
def test_proxy_classes(self):
|
||||
# Necessary for suds serialisation
|
||||
ref = FakeStableMoRefProxy()
|
||||
self.assertEqual("ManagedObjectReference", ref.__class__.__name__)
|
||||
|
||||
|
||||
class VMwareSessionTestCase(test.NoDBTestCase):
|
||||
|
||||
@mock.patch.object(session.VMwareAPISession, '_is_vim_object',
|
||||
return_value=False)
|
||||
def test_call_method(self, mock_is_vim):
|
||||
with test.nested(
|
||||
mock.patch.object(session.VMwareAPISession,
|
||||
'_create_session',
|
||||
_fake_create_session),
|
||||
mock.patch.object(session.VMwareAPISession,
|
||||
'invoke_api'),
|
||||
mock.patch.object(session.VMwareAPISession,
|
||||
'_create_session',
|
||||
_fake_create_session),
|
||||
mock.patch.object(session.VMwareAPISession,
|
||||
'invoke_api'),
|
||||
) as (fake_create, fake_invoke):
|
||||
_session = session.VMwareAPISession()
|
||||
_session._vim = mock.Mock()
|
||||
|
@ -58,13 +91,118 @@ class VMwareSessionTestCase(test.NoDBTestCase):
|
|||
return_value=True)
|
||||
def test_call_method_vim(self, mock_is_vim):
|
||||
with test.nested(
|
||||
mock.patch.object(session.VMwareAPISession,
|
||||
'_create_session',
|
||||
_fake_create_session),
|
||||
mock.patch.object(session.VMwareAPISession,
|
||||
'invoke_api'),
|
||||
mock.patch.object(session.VMwareAPISession,
|
||||
'_create_session',
|
||||
_fake_create_session),
|
||||
mock.patch.object(session.VMwareAPISession,
|
||||
'invoke_api'),
|
||||
) as (fake_create, fake_invoke):
|
||||
_session = session.VMwareAPISession()
|
||||
module = mock.Mock()
|
||||
_session._call_method(module, 'fira')
|
||||
fake_invoke.assert_called_once_with(module, 'fira')
|
||||
|
||||
@mock.patch.object(session.VMwareAPISession, '_is_vim_object',
|
||||
return_value=True)
|
||||
def test_call_method_no_recovery(self, mock_is_vim):
|
||||
with test.nested(
|
||||
mock.patch.object(session.VMwareAPISession, '_create_session',
|
||||
_fake_create_session),
|
||||
mock.patch.object(session.VMwareAPISession, 'invoke_api'),
|
||||
mock.patch.object(FakeStableMoRefProxy, 'fetch_moref'),
|
||||
) as (fake_create, fake_invoke, fake_fetch_moref):
|
||||
_session = session.VMwareAPISession()
|
||||
module = mock.Mock()
|
||||
ref = FakeStableMoRefProxy()
|
||||
|
||||
_session._call_method(
|
||||
module, mock.sentinel.method_arg, ref, ref=ref)
|
||||
|
||||
fake_invoke.assert_called_once_with(
|
||||
module, mock.sentinel.method_arg, ref, ref=ref)
|
||||
fake_fetch_moref.assert_not_called()
|
||||
|
||||
@mock.patch.object(session.VMwareAPISession, '_is_vim_object',
|
||||
return_value=True)
|
||||
def test_call_method_recovery_arg_failed(self, mock_is_vim):
|
||||
with test.nested(
|
||||
mock.patch.object(session.VMwareAPISession, '_create_session',
|
||||
_fake_create_session),
|
||||
mock.patch.object(session.VMwareAPISession, 'invoke_api'),
|
||||
mock.patch.object(FakeStableMoRefProxy, 'fetch_moref'),
|
||||
) as (fake_create, fake_invoke, fake_fetch_moref):
|
||||
_session = session.VMwareAPISession()
|
||||
module = mock.Mock()
|
||||
ref = FakeStableMoRefProxy()
|
||||
fake_invoke.side_effect = [vexec.ManagedObjectNotFoundException]
|
||||
|
||||
self.assertRaises(vexec.ManagedObjectNotFoundException,
|
||||
_session._call_method, module, mock.sentinel.method_arg, ref)
|
||||
|
||||
fake_invoke.assert_called_once_with(
|
||||
module, mock.sentinel.method_arg, ref)
|
||||
fake_fetch_moref.assert_not_called()
|
||||
|
||||
@mock.patch.object(session.VMwareAPISession, '_is_vim_object',
|
||||
return_value=True)
|
||||
def test_call_method_recovery_kwarg_failed(self, mock_is_vim):
|
||||
with test.nested(
|
||||
mock.patch.object(session.VMwareAPISession, '_create_session',
|
||||
_fake_create_session),
|
||||
mock.patch.object(session.VMwareAPISession, 'invoke_api'),
|
||||
mock.patch.object(FakeStableMoRefProxy, 'fetch_moref'),
|
||||
) as (fake_create, fake_invoke, fake_fetch_moref):
|
||||
_session = session.VMwareAPISession()
|
||||
module = mock.Mock()
|
||||
ref = FakeStableMoRefProxy()
|
||||
fake_invoke.side_effect = [vexec.ManagedObjectNotFoundException]
|
||||
|
||||
self.assertRaises(vexec.ManagedObjectNotFoundException,
|
||||
_session._call_method, module,
|
||||
mock.sentinel.method_arg, ref=ref)
|
||||
|
||||
fake_invoke.assert_called_once_with(
|
||||
module, mock.sentinel.method_arg, ref=ref)
|
||||
fake_fetch_moref.assert_not_called()
|
||||
|
||||
@mock.patch.object(session.VMwareAPISession, '_is_vim_object',
|
||||
return_value=True)
|
||||
def test_call_method_recovery_arg_success(self, mock_is_vim):
|
||||
with test.nested(
|
||||
mock.patch.object(session.VMwareAPISession, '_create_session',
|
||||
_fake_create_session),
|
||||
mock.patch.object(session.VMwareAPISession, 'invoke_api'),
|
||||
mock.patch.object(FakeStableMoRefProxy,
|
||||
'fetch_moref', _fake_fetch_moref_impl),
|
||||
) as (fake_create, fake_invoke, fake_fetch_moref):
|
||||
_session = session.VMwareAPISession()
|
||||
module = mock.Mock()
|
||||
ref = FakeStableMoRefProxy()
|
||||
|
||||
fake_invoke.side_effect = [vexec.ManagedObjectNotFoundException(
|
||||
details=dict(obj=mock.sentinel.moref),
|
||||
), None]
|
||||
_session._call_method(module, mock.sentinel.method_arg, ref)
|
||||
fake_invoke.assert_called_with(
|
||||
module, mock.sentinel.method_arg, ref)
|
||||
|
||||
@mock.patch.object(session.VMwareAPISession, '_is_vim_object',
|
||||
return_value=True)
|
||||
def test_call_method_recovery_kwarg_success(self, mock_is_vim):
|
||||
with test.nested(
|
||||
mock.patch.object(session.VMwareAPISession, '_create_session',
|
||||
_fake_create_session),
|
||||
mock.patch.object(session.VMwareAPISession, 'invoke_api'),
|
||||
mock.patch.object(FakeStableMoRefProxy,
|
||||
'fetch_moref', _fake_fetch_moref_impl),
|
||||
) as (fake_create, fake_invoke, fake_fetch_moref):
|
||||
_session = session.VMwareAPISession()
|
||||
module = mock.Mock()
|
||||
ref = FakeStableMoRefProxy()
|
||||
|
||||
fake_invoke.side_effect = [vexec.ManagedObjectNotFoundException(
|
||||
details=dict(obj=mock.sentinel.moref),
|
||||
), None]
|
||||
_session._call_method(module, mock.sentinel.method_arg, ref=ref)
|
||||
fake_invoke.assert_called_with(
|
||||
module, mock.sentinel.method_arg, ref=ref)
|
||||
|
|
|
@ -28,11 +28,11 @@ class VMwareVIMUtilTestCase(test.NoDBTestCase):
|
|||
def test_get_inner_objects(self):
|
||||
property = ['summary.name']
|
||||
# Get the fake datastores directly from the cluster
|
||||
cluster_refs = fake._get_object_refs('ClusterComputeResource')
|
||||
cluster = fake._get_object(cluster_refs[0])
|
||||
cluster = fake.get_first_object('ClusterComputeResource')
|
||||
cluster_ref = cluster.obj
|
||||
expected_ds = cluster.datastore.ManagedObjectReference
|
||||
# Get the fake datastores using inner objects utility method
|
||||
result = vim_util.get_inner_objects(
|
||||
self.vim, cluster_refs[0], 'datastore', 'Datastore', property)
|
||||
self.vim, cluster_ref, 'datastore', 'Datastore', property)
|
||||
datastores = [oc.obj for oc in result.objects]
|
||||
self.assertEqual(expected_ds, datastores)
|
||||
|
|
|
@ -376,7 +376,7 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
|
|||
ide_controller = fake.VirtualIDEController()
|
||||
devices.append(scsi_controller)
|
||||
devices.append(ide_controller)
|
||||
fake._update_object("VirtualMachine", vm)
|
||||
fake.update_object(vm)
|
||||
# return the scsi type, not ide
|
||||
self.assertEqual(constants.DEFAULT_ADAPTER_TYPE,
|
||||
vm_util.get_scsi_adapter_type(devices))
|
||||
|
@ -388,7 +388,7 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
|
|||
ide_controller = fake.VirtualIDEController()
|
||||
devices.append(scsi_controller)
|
||||
devices.append(ide_controller)
|
||||
fake._update_object("VirtualMachine", vm)
|
||||
fake.update_object(vm)
|
||||
# the controller is not suitable since the device under this controller
|
||||
# has exceeded SCSI_MAX_CONNECT_NUMBER
|
||||
for i in range(0, constants.SCSI_MAX_CONNECT_NUMBER):
|
||||
|
@ -2066,7 +2066,7 @@ class VMwareVMUtilGetHostRefTestCase(test.NoDBTestCase):
|
|||
self.session = vmware_session.VMwareAPISession()
|
||||
|
||||
# Create a fake VirtualMachine running on a known host
|
||||
self.host_ref = list(fake._db_content['HostSystem'].keys())[0]
|
||||
self.host_ref = fake.get_first_object_ref("HostSystem")
|
||||
self.vm_ref = fake.create_vm(host_ref=self.host_ref)
|
||||
|
||||
@mock.patch.object(vm_util, 'get_vm_ref')
|
||||
|
@ -2082,7 +2082,7 @@ class VMwareVMUtilGetHostRefTestCase(test.NoDBTestCase):
|
|||
def test_get_host_name_for_vm(self, mock_get_vm_ref):
|
||||
mock_get_vm_ref.return_value = self.vm_ref
|
||||
|
||||
host = fake._get_object(self.host_ref)
|
||||
host = fake.get_object(self.host_ref)
|
||||
|
||||
ret = vm_util.get_host_name_for_vm(self.session, 'fake-instance')
|
||||
|
||||
|
|
|
@ -69,14 +69,16 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
|
||||
self._virtapi = mock.Mock()
|
||||
self._image_id = uuids.image
|
||||
fake_ds_ref = vmwareapi_fake.ManagedObjectReference(value='fake-ds')
|
||||
fake_ds_ref = vmwareapi_fake.ManagedObjectReference(
|
||||
name='Datastore', value='fake-ds')
|
||||
self._ds = ds_obj.Datastore(
|
||||
ref=fake_ds_ref, name='fake_ds',
|
||||
capacity=10 * units.Gi,
|
||||
freespace=10 * units.Gi)
|
||||
self._dc_info = ds_util.DcInfo(
|
||||
ref='fake_dc_ref', name='fake_dc',
|
||||
vmFolder='fake_vm_folder')
|
||||
vmFolder=vmwareapi_fake.ManagedObjectReference(
|
||||
name='Folder', value='fake_vm_folder'))
|
||||
cluster = vmwareapi_fake.create_cluster('fake_cluster', fake_ds_ref)
|
||||
self._uuid = uuids.foo
|
||||
fake_info_cache = {
|
||||
|
@ -297,7 +299,8 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
mock_save.assert_called_once_with()
|
||||
self.assertEqual(50, self._instance.progress)
|
||||
|
||||
@mock.patch.object(vm_util, 'get_vm_ref', return_value='fake_ref')
|
||||
@mock.patch.object(vm_util, 'get_vm_ref',
|
||||
return_value=vmwareapi_fake.ManagedObjectReference())
|
||||
def test_get_info(self, mock_get_vm_ref):
|
||||
result = {
|
||||
'summary.config.numCpu': 4,
|
||||
|
@ -2059,7 +2062,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
extra_specs,
|
||||
self._metadata)
|
||||
|
||||
vm = vmwareapi_fake._get_object(vm_ref)
|
||||
vm = vmwareapi_fake.get_object(vm_ref)
|
||||
|
||||
# Test basic VM parameters
|
||||
self.assertEqual(self._instance.uuid, vm.name)
|
||||
|
@ -2082,7 +2085,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
|||
datastores = vm.datastore.ManagedObjectReference
|
||||
self.assertEqual(1, len(datastores))
|
||||
|
||||
datastore = vmwareapi_fake._get_object(datastores[0])
|
||||
datastore = vmwareapi_fake.get_object(datastores[0])
|
||||
self.assertEqual(self._ds.name, datastore.get('summary.name'))
|
||||
|
||||
# Test that the VM's network is configured as specified
|
||||
|
|
|
@ -143,8 +143,7 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
|
|||
|
||||
get_vm_ref.assert_called_once_with(self._volumeops._session,
|
||||
instance)
|
||||
get_volume_ref.assert_called_once_with(
|
||||
connection_info['data']['volume'])
|
||||
get_volume_ref.assert_called_once_with(connection_info['data'])
|
||||
self.assertTrue(get_vmdk_info.called)
|
||||
get_vm_state.assert_called_once_with(self._volumeops._session,
|
||||
instance)
|
||||
|
@ -267,8 +266,7 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
|
|||
|
||||
get_vm_ref.assert_called_once_with(self._volumeops._session,
|
||||
instance)
|
||||
get_volume_ref.assert_called_once_with(
|
||||
connection_info['data']['volume'])
|
||||
get_volume_ref.assert_called_once_with(connection_info['data'])
|
||||
get_vmdk_backed_disk_device.assert_called_once_with(
|
||||
mock.sentinel.vm_ref, connection_info['data'])
|
||||
adapter_type = vm_util.CONTROLLER_TO_ADAPTER_TYPE.get(
|
||||
|
@ -317,8 +315,7 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
|
|||
|
||||
get_vm_ref.assert_called_once_with(self._volumeops._session,
|
||||
instance)
|
||||
get_volume_ref.assert_called_once_with(
|
||||
connection_info['data']['volume'])
|
||||
get_volume_ref.assert_called_once_with(connection_info['data'])
|
||||
get_vmdk_backed_disk_device.assert_called_once_with(
|
||||
mock.sentinel.vm_ref, connection_info['data'])
|
||||
get_vm_state.assert_called_once_with(self._volumeops._session,
|
||||
|
@ -497,8 +494,7 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
|
|||
|
||||
get_vm_ref.assert_called_once_with(self._volumeops._session,
|
||||
self._instance)
|
||||
get_volume_ref.assert_called_once_with(
|
||||
connection_info['data']['volume'])
|
||||
get_volume_ref.assert_called_once_with(connection_info['data'])
|
||||
self.assertTrue(get_vmdk_info.called)
|
||||
attach_disk_to_vm.assert_called_once_with(
|
||||
vm_ref, self._instance, adapter_type,
|
||||
|
|
|
@ -15,12 +15,71 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import abc
|
||||
import itertools
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
from oslo_vmware import api
|
||||
from oslo_vmware import exceptions as vexc
|
||||
from oslo_vmware import vim
|
||||
from oslo_vmware.vim_util import get_moref_value
|
||||
|
||||
import nova.conf
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StableMoRefProxy(metaclass=abc.ABCMeta):
|
||||
"""Abstract base class which acts as a proxy
|
||||
for Managed-Object-References (MoRef).
|
||||
Those references are usually "stable", meaning
|
||||
they don't change over the life-time of the object.
|
||||
But usually doesn't mean always. In that case, we
|
||||
need to fetch the reference again via some search method,
|
||||
which uses a guaranteed stable identifier (names, uuids, ...)
|
||||
"""
|
||||
|
||||
def __init__(self, ref):
|
||||
self.moref = ref
|
||||
|
||||
@property
|
||||
def __class__(self):
|
||||
# Suds accesses the __class__.__name__ attribute
|
||||
# of the object to determine the xml-tag of the object
|
||||
# so we have to fake it
|
||||
return self.moref.__class__
|
||||
|
||||
@abc.abstractmethod
|
||||
def fetch_moref(self, session):
|
||||
"""Updates the moref field or raises
|
||||
same exception the initial search would have
|
||||
"""
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.moref, name)
|
||||
|
||||
def __repr__(self):
|
||||
return "StableMoRefProxy({!r})".format(self.moref)
|
||||
|
||||
|
||||
class MoRef(StableMoRefProxy):
|
||||
"""MoRef takes a closure to resolve the reference of a managed object
|
||||
That closure is called again, in case we get a ManagedObjectNotFound
|
||||
exception on said reference.
|
||||
"""
|
||||
|
||||
def __init__(self, closure, ref=None):
|
||||
self._closure = closure
|
||||
ref = ref or self._closure()
|
||||
super().__init__(ref)
|
||||
|
||||
def fetch_moref(self, _):
|
||||
self.moref = self._closure()
|
||||
|
||||
def __repr__(self):
|
||||
return "MoRef({!r})".format(self.moref)
|
||||
|
||||
|
||||
class VMwareAPISession(api.VMwareAPISession):
|
||||
|
@ -59,10 +118,37 @@ class VMwareAPISession(api.VMwareAPISession):
|
|||
"""Calls a method within the module specified with
|
||||
args provided.
|
||||
"""
|
||||
if not self._is_vim_object(module):
|
||||
return self.invoke_api(module, method, self.vim, *args, **kwargs)
|
||||
else:
|
||||
try:
|
||||
if not self._is_vim_object(module):
|
||||
return self.invoke_api(module, method, self.vim, *args,
|
||||
**kwargs)
|
||||
return self.invoke_api(module, method, *args, **kwargs)
|
||||
except vexc.ManagedObjectNotFoundException as monfe:
|
||||
with excutils.save_and_reraise_exception() as ctxt:
|
||||
moref = monfe.details.get("obj") if monfe.details else None
|
||||
for arg in itertools.chain(args, kwargs.values()):
|
||||
if not isinstance(arg, StableMoRefProxy):
|
||||
continue
|
||||
moref_arg = get_moref_value(arg.moref)
|
||||
if moref != moref_arg:
|
||||
continue
|
||||
# We have found the argument with the moref
|
||||
# causing the exception and we can try to recover it
|
||||
arg.fetch_moref(self)
|
||||
if not arg.moref:
|
||||
# We didn't recover the reference
|
||||
ctxt.reraise = True
|
||||
break
|
||||
moref_arg = get_moref_value(arg.moref)
|
||||
if moref != moref_arg:
|
||||
# We actually recovered, so do not raise `monfe`
|
||||
LOG.info("Replaced moref %s with %s",
|
||||
moref, moref_arg)
|
||||
ctxt.reraise = False
|
||||
# We only end up here when we have recovered a moref by changing
|
||||
# the stored value of an argument to a different value,
|
||||
# so let's try again (and recover again if it happens more than once)
|
||||
return self._call_method(module, method, *args, **kwargs)
|
||||
|
||||
def _wait_for_task(self, task_ref):
|
||||
"""Return a Deferred that will give the result of the given task.
|
||||
|
|
|
@ -20,7 +20,6 @@ The VMware API VM utility module to build SOAP object specs.
|
|||
|
||||
import collections
|
||||
import copy
|
||||
import functools
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_service import loopingcall
|
||||
|
@ -37,6 +36,7 @@ from nova import exception
|
|||
from nova.i18n import _
|
||||
from nova.network import model as network_model
|
||||
from nova.virt.vmwareapi import constants
|
||||
from nova.virt.vmwareapi import session
|
||||
from nova.virt.vmwareapi import vim_util
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -131,22 +131,6 @@ def vm_ref_cache_get(id_):
|
|||
return _VM_REFS_CACHE.get(id_)
|
||||
|
||||
|
||||
def _vm_ref_cache(id_, func, session, data):
|
||||
vm_ref = vm_ref_cache_get(id_)
|
||||
if not vm_ref:
|
||||
vm_ref = func(session, data)
|
||||
vm_ref_cache_update(id_, vm_ref)
|
||||
return vm_ref
|
||||
|
||||
|
||||
def vm_ref_cache_from_instance(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(session, instance):
|
||||
id_ = instance.uuid
|
||||
return _vm_ref_cache(id_, func, session, instance)
|
||||
return wrapper
|
||||
|
||||
|
||||
# the config key which stores the VNC port
|
||||
VNC_CONFIG_KEY = 'config.extraConfig["RemoteDisplay.vnc.port"]'
|
||||
|
||||
|
@ -1131,15 +1115,25 @@ def _get_vm_ref_from_extraconfig(session, instance_uuid):
|
|||
_get_object_for_optionvalue)
|
||||
|
||||
|
||||
@vm_ref_cache_from_instance
|
||||
class VmMoRefProxy(session.StableMoRefProxy):
|
||||
def __init__(self, ref, uuid):
|
||||
super(VmMoRefProxy, self).__init__(ref)
|
||||
self._uuid = uuid
|
||||
|
||||
def fetch_moref(self, session):
|
||||
self.moref = search_vm_ref_by_identifier(session, self._uuid)
|
||||
if not self.moref:
|
||||
raise exception.InstanceNotFound(instance_id=self._uuid)
|
||||
vm_ref_cache_update(self._uuid, self.moref)
|
||||
|
||||
|
||||
def get_vm_ref(session, instance):
|
||||
"""Get reference to the VM through uuid or vm name."""
|
||||
uuid = instance.uuid
|
||||
vm_ref = (search_vm_ref_by_identifier(session, uuid) or
|
||||
_get_vm_ref_from_name(session, instance.name))
|
||||
if vm_ref is None:
|
||||
raise exception.InstanceNotFound(instance_id=uuid)
|
||||
return vm_ref
|
||||
"""Get reference to the VM through uuid."""
|
||||
moref = vm_ref_cache_get(instance.uuid)
|
||||
stable_ref = VmMoRefProxy(moref, instance.uuid)
|
||||
if not moref:
|
||||
stable_ref.fetch_moref(session)
|
||||
return stable_ref
|
||||
|
||||
|
||||
def search_vm_ref_by_identifier(session, identifier):
|
||||
|
@ -1151,8 +1145,7 @@ def search_vm_ref_by_identifier(session, identifier):
|
|||
use get_vm_ref instead.
|
||||
"""
|
||||
vm_ref = (_get_vm_ref_from_vm_uuid(session, identifier) or
|
||||
_get_vm_ref_from_extraconfig(session, identifier) or
|
||||
_get_vm_ref_from_name(session, identifier))
|
||||
_get_vm_ref_from_extraconfig(session, identifier))
|
||||
return vm_ref
|
||||
|
||||
|
||||
|
|
|
@ -26,12 +26,30 @@ import nova.conf
|
|||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova.virt.vmwareapi import constants
|
||||
from nova.virt.vmwareapi import session
|
||||
from nova.virt.vmwareapi import vm_util
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class VolumeMoRefProxy(session.StableMoRefProxy):
|
||||
def __init__(self, connection_info_data):
|
||||
volume_ref_value = connection_info_data.get('volume')
|
||||
ref = None
|
||||
if volume_ref_value:
|
||||
ref = vutil.get_moref(volume_ref_value, 'VirtualMachine')
|
||||
super(VolumeMoRefProxy, self).__init__(ref)
|
||||
self._connection_info_data = connection_info_data
|
||||
|
||||
def fetch_moref(self, session):
|
||||
volume_id = self._connection_info_data.get('volume_id')
|
||||
if not volume_id:
|
||||
volume_id = self._connection_info_data.get('name')
|
||||
if volume_id:
|
||||
self.moref = vm_util._get_vm_ref_from_vm_uuid(session, volume_id)
|
||||
|
||||
|
||||
class VMwareVolumeOps(object):
|
||||
"""Management class for Volume-related tasks."""
|
||||
|
||||
|
@ -300,9 +318,10 @@ class VMwareVolumeOps(object):
|
|||
connector['instance'] = vutil.get_moref_value(vm_ref)
|
||||
return connector
|
||||
|
||||
def _get_volume_ref(self, volume_ref_name):
|
||||
"""Get the volume moref from the ref name."""
|
||||
return vutil.get_moref(volume_ref_name, 'VirtualMachine')
|
||||
@staticmethod
|
||||
def _get_volume_ref(connection_info_data):
|
||||
"""Get the volume moref from the "data" field in connection_info ."""
|
||||
return VolumeMoRefProxy(connection_info_data)
|
||||
|
||||
def _get_vmdk_base_volume_device(self, volume_ref):
|
||||
# Get the vmdk file name that the VM is pointing to
|
||||
|
@ -317,7 +336,7 @@ class VMwareVolumeOps(object):
|
|||
LOG.debug("_attach_volume_vmdk: %s", connection_info,
|
||||
instance=instance)
|
||||
data = connection_info['data']
|
||||
volume_ref = self._get_volume_ref(data['volume'])
|
||||
volume_ref = self._get_volume_ref(data)
|
||||
|
||||
# Get details required for adding disk device such as
|
||||
# adapter_type, disk_type
|
||||
|
@ -552,7 +571,7 @@ class VMwareVolumeOps(object):
|
|||
LOG.debug("_detach_volume_vmdk: %s", connection_info,
|
||||
instance=instance)
|
||||
data = connection_info['data']
|
||||
volume_ref = self._get_volume_ref(data['volume'])
|
||||
volume_ref = self._get_volume_ref(data)
|
||||
|
||||
device = self._get_vmdk_backed_disk_device(vm_ref, data)
|
||||
|
||||
|
@ -645,7 +664,7 @@ class VMwareVolumeOps(object):
|
|||
vm_ref = vm_util.get_vm_ref(self._session, instance)
|
||||
data = connection_info['data']
|
||||
# Get the volume ref
|
||||
volume_ref = self._get_volume_ref(data['volume'])
|
||||
volume_ref = self._get_volume_ref(data)
|
||||
# Pick the resource pool on which the instance resides. Move the
|
||||
# volume to the datastore of the instance.
|
||||
res_pool = self._get_res_pool_of_vm(vm_ref)
|
||||
|
|
Loading…
Reference in New Issue