diff --git a/nova/compute/api.py b/nova/compute/api.py index 8b763ff22fd..89add8fdbd1 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -2454,7 +2454,8 @@ def get(self, context, instance_id, expected_attrs=None): except exception.InvalidID: LOG.debug("Invalid instance id %s", instance_id) raise exception.InstanceNotFound(instance_id=instance_id) - + context.resource_id = instance.uuid + context.update_store() return instance def get_all(self, context, search_opts=None, limit=None, marker=None, diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 9fda5459d14..170c925c897 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1952,6 +1952,9 @@ def build_and_run_instance(self, context, instance, image, request_spec, @utils.synchronized(instance.uuid) def _locked_do_build_and_run_instance(*args, **kwargs): + # NOTE(fwiesel): Spawned in a different thread, store the context + context.update_store() + # NOTE(danms): We grab the semaphore with the instance uuid # locked because we could wait in line to build this instance # for a while and we want to make sure that nothing else tries @@ -7929,6 +7932,9 @@ def _sync_power_states(self, context): 'num_vm_instances': num_vm_instances}) def _sync(db_instance): + context.resource_uuid = db_instance.uuid + context.update_store() + # NOTE(melwitt): This must be synchronized as we query state from # two separate sources, the driver and the database. # They are set (in stop_instance) and read, in sync. diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index 9d4f6ef7fde..a3f161fb643 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -669,6 +669,8 @@ def build_instances(self, context, instances, image, filter_properties, elevated = context.elevated() for (instance, host_list) in six.moves.zip(instances, host_lists): + context.resource_uuid = instance.uuid + context.update_store() host = host_list.pop(0) if is_reschedule: # If this runs in the superconductor, the first instance will @@ -774,7 +776,7 @@ def build_instances(self, context, instances, image, filter_properties, alts = [(alt.service_host, alt.nodename) for alt in host_list] LOG.debug("Selected host: %s; Selected node: %s; Alternates: %s", - host.service_host, host.nodename, alts, instance=instance) + host.service_host, host.nodename, alts) self.compute_rpcapi.build_and_run_instance(context, instance=instance, host=host.service_host, image=image, @@ -1374,13 +1376,15 @@ def schedule_and_build_instances(self, context, build_requests, # Skip placeholders that were buried in cell0 or had their # build requests deleted by the user before instance create. continue + context.resource_uuid = instance.uuid + context.update_store() cell = cell_mapping_cache[instance.uuid] # host_list is a list of one or more Selection objects, the first # of which has been selected and its resources claimed. host = host_list.pop(0) alts = [(alt.service_host, alt.nodename) for alt in host_list] LOG.debug("Selected host: %s; Selected node: %s; Alternates: %s", - host.service_host, host.nodename, alts, instance=instance) + host.service_host, host.nodename, alts) filter_props = request_spec.to_legacy_filter_properties_dict() scheduler_utils.populate_retry(filter_props, instance.uuid) scheduler_utils.populate_filter_properties(filter_props, diff --git a/nova/tests/unit/virt/vmwareapi/fake.py b/nova/tests/unit/virt/vmwareapi/fake.py index fe7e0c7871c..c827839c0e9 100644 --- a/nova/tests/unit/virt/vmwareapi/fake.py +++ b/nova/tests/unit/virt/vmwareapi/fake.py @@ -22,8 +22,9 @@ import collections import sys +import six + 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 @@ -79,20 +80,27 @@ def cleanup(): def _create_object(table, table_obj): """Create an object in the db.""" _db_content.setdefault(table, {}) - _db_content[table][table_obj.obj] = table_obj + _db_content[table][table_obj.obj.value] = 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 six.itervalues(_db_content[obj_type]) + + +def get_first_object(obj_type): + """Get the first object of an object type""" + return next(six.itervalues(_db_content[obj_type])) + + +def get_first_object_ref(obj_type): + """Get the first reference of an object type""" + return get_first_object(obj_type).obj def _convert_to_array_of_mor(mors): @@ -140,16 +148,14 @@ def add_object(self, object): 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 + """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): """Update objects of the type.""" - _db_content[table][table_obj.obj] = table_obj + _db_content[table][table_obj.obj.value] = table_obj class Prop(object): @@ -176,6 +182,9 @@ def __init__(self, name="ManagedObject", value=None): self.type = name self._type = name + def __repr__(self): + return "{}:{}".format(self._type, self.value) + class ObjectContent(object): """ObjectContent array holds dynamic properties.""" @@ -261,8 +270,11 @@ def _generate_moid(self, prefix): 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): @@ -592,8 +604,7 @@ def __init__(self, name="test_ResPool", value="resgroup-test"): 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 @@ -609,6 +620,7 @@ def __init__(self, name="test_cluster"): self.set("host", None) self.set("datastore", None) self.set("resourcePool", None) + self.set("vm", []) summary = DataObject() summary.numHosts = 0 @@ -630,9 +642,15 @@ def __init__(self, name="test_cluster"): configuration.dasConfig.admissionControlPolicy = policy self.set("configuration.dasConfig.admissionControlPolicy", policy) + 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: @@ -668,7 +686,7 @@ def _update_summary(self): # 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 @@ -726,14 +744,18 @@ def __init__(self, name="ha-host", connected=True, ds_ref=None, maintenance_mode=False): super(HostSystem, self).__init__("host") self.set("name", name) - if _db_content.get("HostNetworkSystem", None) is None: + + if not _db_content.get("HostNetworkSystem", None): create_host_network_system() - if not _get_object_refs('HostStorageSystem'): + + if not _db_content.get("HostStorageSystem", None): 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: @@ -813,10 +835,9 @@ def __init__(self, name="ha-host", connected=True, ds_ref=None, self.set("config.network.pnic", net_info_pnic) self.set("connected", connected) - if _db_content.get("Network", None) is None: + if not _db_content.get("Network", None): 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) @@ -855,7 +876,7 @@ def __init__(self, name="ha-host", connected=True, ds_ref=None, 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) @@ -918,15 +939,13 @@ def __init__(self, name="ha-datacenter", ds_ref=None): self.set("name", name) if _db_content.get("Folder", None) is None: 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: 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) @@ -1004,8 +1023,10 @@ def create_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) @@ -1027,16 +1048,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 @@ -1047,7 +1067,7 @@ def create_vm(uuid=None, name=None, for key, value in _db_content["Datastore"].items(): if value.get('summary.name') == vm_path.datastore: - ds = key + ds = value.obj break else: ds = create_datastore(vm_path.datastore, 1024, 500) @@ -1067,7 +1087,7 @@ def create_vm(uuid=None, name=None, vm = VirtualMachine(**vm_dict) _create_object("VirtualMachine", 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 @@ -1140,10 +1160,10 @@ def _get_vm_mdo(vm_ref): """Gets the Virtual Machine with the ref from the db.""" if _db_content.get("VirtualMachine", None) is None: raise exception.NotFound("There is no VM registered") - if vm_ref not in _db_content.get("VirtualMachine"): + if vm_ref.value not in _db_content.get("VirtualMachine"): raise exception.NotFound("Virtual Machine with ref %s is not " - "there" % vm_ref) - return _db_content.get("VirtualMachine")[vm_ref] + "there" % vm_ref.value) + return _db_content.get("VirtualMachine")[vm_ref.value] def _merge_extraconfig(existing, changes): @@ -1216,17 +1236,17 @@ class FakeSession(object): def __init__(self): self.vim = FakeVim() - def _call_method(self, module, method, *args, **kwargs): + def call_method(self, module, method, *args, **kwargs): raise NotImplementedError() - def _wait_for_task(self, task_ref): + def wait_for_task(self, task_ref): raise NotImplementedError() class FakeObjectRetrievalSession(FakeSession): """A session for faking object retrieval tasks. - _call_method() returns a given set of objects + call_method() returns a given set of objects sequentially, regardless of the method called. """ @@ -1235,7 +1255,7 @@ def __init__(self, *ret): self.ret = ret self.ind = 0 - def _call_method(self, module, method, *args, **kwargs): + def call_method(self, module, method, *args, **kwargs): if (method == 'continue_retrieval' or method == 'cancel_retrieval'): return @@ -1394,11 +1414,10 @@ def _snapshot_vm(self, method): 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 _db_content.get("VirtualMachine").values(): 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): @@ -1460,7 +1479,7 @@ def _unregister_vm(self, method, *args, **kwargs): """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 @@ -1534,10 +1553,10 @@ def _set_power_state(self, method, vm_ref, pwr_state="poweredOn"): 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"): + vm_mdo = _db_content.get("VirtualMachine").get(vm_ref.value) + if not vm_mdo: raise exception.NotFound("Virtual Machine with ref %s is not " - "there" % vm_ref) - vm_mdo = _db_content.get("VirtualMachine").get(vm_ref) + "there" % vm_ref.value) vm_mdo.set("runtime.powerState", pwr_state) task_mdo = create_task(method, "success") return task_mdo.obj @@ -1566,7 +1585,8 @@ def _retrieve_properties(self, method, *args, **kwargs): # 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 = [obj.obj + for obj in _db_content[spec_type].values()] 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. @@ -1576,7 +1596,7 @@ def _retrieve_properties(self, method, *args, **kwargs): # path = 'datastore' # the above will retrieve all datastores in the given # cluster. - parent_mdo = _db_content[obj_ref.type][obj_ref] + parent_mdo = _db_content[obj_ref.type][obj_ref.value] path = obj.selectSet[0].path mdo_refs = parent_mdo.get(path).ManagedObjectReference else: @@ -1586,7 +1606,7 @@ def _retrieve_properties(self, method, *args, **kwargs): mdo_refs = [obj_ref] for mdo_ref in mdo_refs: - mdo = _db_content[spec_type][mdo_ref] + mdo = _db_content[spec_type][mdo_ref.value] prop_list = [] for prop_name in properties: prop = Prop(prop_name, mdo.get(prop_name)) @@ -1600,14 +1620,13 @@ def _retrieve_properties(self, method, *args, **kwargs): 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] diff --git a/nova/tests/unit/virt/vmwareapi/stubs.py b/nova/tests/unit/virt/vmwareapi/stubs.py index 41d5e38794e..e1b4a7957cf 100644 --- a/nova/tests/unit/virt/vmwareapi/stubs.py +++ b/nova/tests/unit/virt/vmwareapi/stubs.py @@ -36,7 +36,7 @@ def fake_vim_prop(arg): return fake.get_fake_vim_object(arg) -def fake_is_vim_object(arg, module): +def fake_is_vim_object(module): """Stubs out the VMwareAPISession's is_vim_object method.""" return isinstance(module, fake.FakeVim) @@ -74,9 +74,10 @@ def set_stubs(test): fake.fake_upload_image) test.stub_out('nova.virt.vmwareapi.images.fetch_image', fake.fake_fetch_image) - test.stub_out('nova.virt.vmwareapi.driver.VMwareAPISession.vim', + test.stub_out('nova.virt.vmwareapi.session.VMwareAPISession.vim', fake_vim_prop) - test.stub_out('nova.virt.vmwareapi.driver.VMwareAPISession._is_vim_object', + test.stub_out('nova.virt.vmwareapi.session.VMwareAPISession.' + '_is_vim_object', fake_is_vim_object) if CONF.use_neutron: test.stub_out( diff --git a/nova/tests/unit/virt/vmwareapi/test_configdrive.py b/nova/tests/unit/virt/vmwareapi/test_configdrive.py index 6ad72801a87..4bddfeb511b 100644 --- a/nova/tests/unit/virt/vmwareapi/test_configdrive.py +++ b/nova/tests/unit/virt/vmwareapi/test_configdrive.py @@ -147,23 +147,23 @@ def _spawn_vm(self, mock_find_image_template_vm, block_device_info=block_device_info) @mock.patch.object(vmops.VMwareVMOps, '_create_config_drive', - return_value=('[ds1] fake.iso')) + return_value='fake-path/fake.iso') @mock.patch.object(vmops.VMwareVMOps, '_attach_cdrom_to_vm') def test_create_vm_with_config_drive_verify_method_invocation(self, mock_attach_cdrom, mock_create_config_drive): self.test_instance.config_drive = 'True' self._spawn_vm() - mock_create_config_drive.assert_called_once_with(mock.ANY, + mock_create_config_drive.assert_called_once_with(self.context, self.test_instance, mock.ANY, mock.ANY, mock.ANY, + 'ds1', mock.ANY, mock.ANY, - mock.ANY, - mock.ANY) + 'Fake-CookieJar') mock_attach_cdrom.assert_called_once_with(mock.ANY, mock.ANY, - mock.ANY, mock.ANY) + mock.ANY) @mock.patch.object(vmops.VMwareVMOps, '_create_config_drive', return_value=('[ds1] fake.iso')) diff --git a/nova/tests/unit/virt/vmwareapi/test_driver_api.py b/nova/tests/unit/virt/vmwareapi/test_driver_api.py index 358f41f1e29..c1ecc9316c7 100644 --- a/nova/tests/unit/virt/vmwareapi/test_driver_api.py +++ b/nova/tests/unit/virt/vmwareapi/test_driver_api.py @@ -65,6 +65,7 @@ from nova.virt.vmwareapi import error_util from nova.virt.vmwareapi import imagecache from nova.virt.vmwareapi import images +from nova.virt.vmwareapi.session import VMwareAPISession from nova.virt.vmwareapi import vif from nova.virt.vmwareapi import vim_util from nova.virt.vmwareapi import vm_util @@ -125,7 +126,7 @@ class VMwareDriverStartupTestCase(test.NoDBTestCase): def _start_driver_with_flags(self, expected_exception_type, startup_flags): self.flags(**startup_flags) with mock.patch( - 'nova.virt.vmwareapi.driver.VMwareAPISession.__init__'): + 'nova.virt.vmwareapi.session.VMwareAPISession.__init__'): e = self.assertRaises( Exception, driver.VMwareVCDriver, None) # noqa self.assertIs(type(e), expected_exception_type) @@ -160,31 +161,31 @@ def test_start_driver_with_user_host_password(self): class VMwareSessionTestCase(test.NoDBTestCase): - @mock.patch.object(driver.VMwareAPISession, '_is_vim_object', + @mock.patch.object(VMwareAPISession, '_is_vim_object', return_value=False) def test_call_method(self, mock_is_vim): with test.nested( - mock.patch.object(driver.VMwareAPISession, '_create_session', + mock.patch.object(VMwareAPISession, '_create_session', _fake_create_session), - mock.patch.object(driver.VMwareAPISession, 'invoke_api'), + mock.patch.object(VMwareAPISession, 'invoke_api'), ) as (fake_create, fake_invoke): - session = driver.VMwareAPISession() + session = VMwareAPISession() session._vim = mock.Mock() module = mock.Mock() - session._call_method(module, 'fira') + session.call_method(module, 'fira') fake_invoke.assert_called_once_with(module, 'fira', session._vim) - @mock.patch.object(driver.VMwareAPISession, '_is_vim_object', + @mock.patch.object(VMwareAPISession, '_is_vim_object', return_value=True) def test_call_method_vim(self, mock_is_vim): with test.nested( - mock.patch.object(driver.VMwareAPISession, '_create_session', + mock.patch.object(VMwareAPISession, '_create_session', _fake_create_session), - mock.patch.object(driver.VMwareAPISession, 'invoke_api'), + mock.patch.object(VMwareAPISession, 'invoke_api'), ) as (fake_create, fake_invoke): - session = driver.VMwareAPISession() + session = VMwareAPISession() module = mock.Mock() - session._call_method(module, 'fira') + session.call_method(module, 'fira') fake_invoke.assert_called_once_with(module, 'fira') @@ -294,8 +295,8 @@ def test_init_host(self): self.fail("init_host raised: %s" % ex) def _set_exception_vars(self): - self.wait_task = self.conn._session._wait_for_task - self.call_method = self.conn._session._call_method + self.wait_task = self.conn._session.wait_for_task + self.call_method = self.conn._session.call_method self.task_ref = None self.exception = False @@ -349,7 +350,7 @@ def _fake_check_session(_self): _fake_check_session) with mock.patch.object(greenthread, 'sleep'): - self.conn = driver.VMwareAPISession() + self.conn = VMwareAPISession() self.assertEqual(2, self.attempts) def _get_instance_type_by_name(self, type): @@ -430,8 +431,8 @@ def _create_vm(self, node=None, num_instances=1, uuid=None, 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 @@ -595,7 +596,7 @@ def test_iso_disk_cdrom_attach(self, self.fake_image_uuid, '%s.iso' % self.fake_image_uuid) - def fake_attach_cdrom(vm_ref, instance, data_store_ref, + def fake_attach_cdrom(vm_ref, data_store_ref, iso_uploaded_path): self.assertEqual(iso_uploaded_path, str(iso_path)) @@ -626,7 +627,7 @@ def test_iso_disk_cdrom_attach_with_config_drive(self, ds_obj.DatastorePath(self.ds, 'fake-config-drive')] self.iso_index = 0 - def fake_attach_cdrom(vm_ref, instance, data_store_ref, + def fake_attach_cdrom(vm_ref, data_store_ref, iso_uploaded_path): self.assertEqual(iso_uploaded_path, str(iso_path[self.iso_index])) self.iso_index += 1 @@ -680,7 +681,7 @@ def test_cdrom_attach_with_config_drive(self): iso_path = ds_obj.DatastorePath(self.ds, 'fake-config-drive') self.cd_attach_called = False - def fake_attach_cdrom(vm_ref, instance, data_store_ref, + def fake_attach_cdrom(vm_ref, data_store_ref, iso_uploaded_path): self.assertEqual(iso_uploaded_path, str(iso_path)) self.cd_attach_called = True @@ -816,7 +817,7 @@ def fake_call_method(module, method, *args, **kwargs): return task_ref with ( - mock.patch.object(self.conn._session, '_call_method', + mock.patch.object(self.conn._session, 'call_method', fake_call_method) ): if fault: @@ -860,7 +861,7 @@ def test_spawn_disk_extend(self, mock_extend, self._create_vm() info = self._get_info() self._check_vm_info(info, power_state.RUNNING) - mock_extend.assert_called_once_with(mock.ANY, requested_size, + mock_extend.assert_called_once_with(requested_size, mock.ANY, mock.ANY) @mock.patch.object(vmops.VMwareVMOps, 'update_cached_instances') @@ -869,7 +870,7 @@ def test_spawn_disk_extend_exists(self, mock_update_cached_instances): self.fake_image_uuid, '%s.80.vmdk' % self.fake_image_uuid) - def _fake_extend(instance, requested_size, name, dc_ref): + def _fake_extend(requested_size, name, dc_ref): vmwareapi_fake._add_file(str(root)) with test.nested( @@ -919,7 +920,7 @@ def test_spawn_disk_extend_sparse(self, mock_from_image, cached_image = ds_obj.DatastorePath(self.ds, 'vmware_base', iid, '%s.80.vmdk' % iid) mock_extend.assert_called_once_with( - self.instance, self.instance.flavor.root_gb * units.Mi, + self.instance.flavor.root_gb * units.Mi, str(cached_image), "fake_dc_ref") def test_spawn_disk_extend_failed_copy(self): @@ -943,9 +944,9 @@ def fake_call_method(module, method, *args, **kwargs): return self.call_method(module, method, *args, **kwargs) with test.nested( - mock.patch.object(self.conn._session, '_call_method', + mock.patch.object(self.conn._session, 'call_method', new=fake_call_method), - mock.patch.object(self.conn._session, '_wait_for_task', + mock.patch.object(self.conn._session, 'wait_for_task', new=fake_wait_for_task)): self.assertRaises(CopyError, self._create_vm) @@ -979,9 +980,9 @@ def fake_call_method(module, method, *args, **kwargs): return task_ref with test.nested( - mock.patch.object(self.conn._session, '_call_method', + mock.patch.object(self.conn._session, 'call_method', new=fake_call_method), - mock.patch.object(self.conn._session, '_wait_for_task', + mock.patch.object(self.conn._session, 'wait_for_task', new=fake_wait_for_task)): self.assertRaises(CopyError, self._create_vm) vmwareapi_fake.assertPathNotExists(self, cached_image) @@ -1023,9 +1024,9 @@ def fake_call_method(module, method, *args, **kwargs): return task_ref with test.nested( - mock.patch.object(self.conn._session, '_wait_for_task', + mock.patch.object(self.conn._session, 'wait_for_task', new=fake_wait_for_task), - mock.patch.object(self.conn._session, '_call_method', + mock.patch.object(self.conn._session, 'call_method', new=fake_call_method)): self.assertRaises(DeleteError, self._create_vm) vmwareapi_fake.assertPathExists(self, cached_image) @@ -1079,9 +1080,9 @@ def fake_call_method(module, method, *args, **kwargs): return task_ref with test.nested( - mock.patch.object(self.conn._session, '_wait_for_task', + mock.patch.object(self.conn._session, 'wait_for_task', fake_wait_for_task), - mock.patch.object(self.conn._session, '_call_method', + mock.patch.object(self.conn._session, 'call_method', fake_call_method) ) as (mock_wait_for_task, mock_call_method): self.assertRaises(NoDiskSpace, self._create_vm) @@ -1111,9 +1112,9 @@ def fake_call_method(module, method, *args, **kwargs): return task_ref with test.nested( - mock.patch.object(self.conn._session, '_wait_for_task', + mock.patch.object(self.conn._session, 'wait_for_task', fake_wait_for_task), - mock.patch.object(self.conn._session, '_call_method', + mock.patch.object(self.conn._session, 'call_method', fake_call_method) ) as (_wait_for_task, _call_method): self._create_vm() @@ -1142,9 +1143,9 @@ def fake_call_method(module, method, *args, **kwargs): return task_ref with test.nested( - mock.patch.object(self.conn._session, '_wait_for_task', + mock.patch.object(self.conn._session, 'wait_for_task', fake_wait_for_task), - mock.patch.object(self.conn._session, '_call_method', + mock.patch.object(self.conn._session, 'call_method', fake_call_method) ) as (_wait_for_task, _call_method): self.assertRaises(vexc.VMwareDriverException, @@ -1152,7 +1153,7 @@ def fake_call_method(module, method, *args, **kwargs): self.assertTrue(self.exception) def test_spawn_with_move_poll_exception(self): - self.call_method = self.conn._session._call_method + self.call_method = self.conn._session.call_method def fake_call_method(module, method, *args, **kwargs): task_ref = self.call_method(module, method, *args, **kwargs) @@ -1162,7 +1163,7 @@ def fake_call_method(module, method, *args, **kwargs): return task_ref with ( - mock.patch.object(self.conn._session, '_call_method', + mock.patch.object(self.conn._session, 'call_method', fake_call_method) ): self.assertRaises(vexc.VMwareDriverException, @@ -1187,7 +1188,7 @@ def fake_call_method(module, method, *args, **kwargs): return task_ref with ( - mock.patch.object(self.conn._session, '_call_method', + mock.patch.object(self.conn._session, 'call_method', fake_call_method) ): self._create_vm() @@ -1281,7 +1282,8 @@ def mock_upload_image(self, context, image, instance, session, **kwargs): def test_get_vm_ref_using_extra_config(self): self._create_vm() vm_ref = vm_util._get_vm_ref_from_extraconfig(self.conn._session, - self.instance['uuid']) + self.conn._cluster_ref, + self.instance['uuid']) self.assertIsNotNone(vm_ref, 'VM Reference cannot be none') # Disrupt the fake Virtual Machine object so that extraConfig # cannot be matched. @@ -1289,32 +1291,39 @@ def test_get_vm_ref_using_extra_config(self): fake_vm.get('config.extraConfig["nvp.vm-uuid"]').value = "" # We should not get a Virtual Machine through extraConfig. vm_ref = vm_util._get_vm_ref_from_extraconfig(self.conn._session, - self.instance['uuid']) + self.conn._cluster_ref, + self.instance['uuid']) self.assertIsNone(vm_ref, 'VM Reference should be none') # Check if we can find the Virtual Machine using the name. - vm_ref = vm_util.get_vm_ref(self.conn._session, self.instance) + vm_ref = vm_util.get_vm_ref(self.conn._session, self.conn._cluster_ref, + self.instance) self.assertIsNotNone(vm_ref, 'VM Reference cannot be none') @mock.patch.object(vmops.VMwareVMOps, 'update_cached_instances') def test_search_vm_ref_by_identifier(self, mock_update_cached_instances): self._create_vm() vm_ref = vm_util.search_vm_ref_by_identifier(self.conn._session, - self.instance['uuid']) + self.conn._cluster_ref, + self.instance['uuid']) self.assertIsNotNone(vm_ref, 'VM Reference cannot be none') fake_vm = self._get_vm_record() fake_vm.set("summary.config.instanceUuid", "foo") fake_vm.set("name", "foo") fake_vm.get('config.extraConfig["nvp.vm-uuid"]').value = "foo" self.assertIsNone(vm_util.search_vm_ref_by_identifier( - self.conn._session, self.instance['uuid']), + self.conn._session, + self.conn._cluster_ref, + self.instance['uuid']), "VM Reference should be none") self.assertIsNotNone( - vm_util.search_vm_ref_by_identifier(self.conn._session, "foo"), + vm_util.search_vm_ref_by_identifier(self.conn._session, + self.conn._cluster_ref, + "foo"), "VM Reference should not be none") def test_get_object_for_optionvalue(self): self._create_vm() - vms = self.conn._session._call_method(vim_util, "get_objects", + vms = self.conn._session.call_method(vim_util, "get_objects", "VirtualMachine", ['config.extraConfig["nvp.vm-uuid"]']) vm_ref = vm_util._get_object_for_optionvalue(vms.objects, self.instance["uuid"]) @@ -1378,7 +1387,6 @@ def test_snapshot_delete_vm_snapshot(self, mock_attach_volume, mock_get_vmdk.return_value = self.get_fake_vmdk() self._create_vm() - fake_vm = self._get_vm_record() snapshot_ref = vmwareapi_fake.ManagedObjectReference( value="Snapshot-123", name="VirtualMachineSnapshot") @@ -1388,9 +1396,7 @@ def test_snapshot_delete_vm_snapshot(self, mock_attach_volume, self._test_snapshot() - mock_delete_vm_snapshot.assert_called_once_with(self.instance, - fake_vm.obj, - snapshot_ref) + mock_delete_vm_snapshot.assert_called_once_with(snapshot_ref) def get_fake_vmdk(self): ds_ref = vmwareapi_fake.ManagedObjectReference(value='fake-ref') @@ -1410,24 +1416,22 @@ def get_fake_vmdk(self): def _snapshot_delete_vm_snapshot_exception(self, exception, call_count=1): self._create_vm() - fake_vm = vmwareapi_fake._get_objects("VirtualMachine").objects[0].obj snapshot_ref = vmwareapi_fake.ManagedObjectReference( value="Snapshot-123", name="VirtualMachineSnapshot") with test.nested( - mock.patch.object(self.conn._session, '_wait_for_task', + mock.patch.object(self.conn._session, 'wait_for_task', side_effect=exception), mock.patch.object(vmops, '_time_sleep_wrapper') ) as (_fake_wait, _fake_sleep): if exception != vexc.TaskInProgress: self.assertRaises(exception, self.conn._vmops._delete_vm_snapshot, - self.instance, fake_vm, snapshot_ref) + snapshot_ref) self.assertEqual(0, _fake_sleep.call_count) else: - self.conn._vmops._delete_vm_snapshot(self.instance, fake_vm, - snapshot_ref) + self.conn._vmops._delete_vm_snapshot(snapshot_ref) self.assertEqual(call_count - 1, _fake_sleep.call_count) self.assertEqual(call_count, _fake_wait.call_count) @@ -1602,13 +1606,19 @@ def test_power_off_non_existent(self): @mock.patch.object(driver.VMwareVCDriver, 'reboot') @mock.patch.object(vm_util, 'get_vm_state', return_value=power_state.SHUTDOWN) - def test_resume_state_on_host_boot(self, mock_get_vm_state, + @mock.patch.object(vm_util, 'get_vm_ref', + return_value=mock.sentinel.vm_ref) + def test_resume_state_on_host_boot(self, mock_get_vm_ref, + mock_get_vm_state, mock_reboot): self._create_instance() self.conn.resume_state_on_host_boot(self.context, self.instance, 'network_info') + mock_get_vm_ref.assert_called_once_with(self.conn._session, + self.conn._cluster_ref, + self.instance) mock_get_vm_state.assert_called_once_with(self.conn._session, - self.instance) + mock.sentinel.vm_ref) mock_reboot.assert_called_once_with(self.context, self.instance, 'network_info', 'hard', None) @@ -1616,15 +1626,20 @@ def test_resume_state_on_host_boot_no_reboot(self): self._create_instance() for state in [power_state.RUNNING, power_state.SUSPENDED]: with test.nested( + mock.patch.object(vm_util, 'get_vm_ref', + return_value=mock.sentinel.vm_ref), mock.patch.object(driver.VMwareVCDriver, 'reboot'), mock.patch.object(vm_util, 'get_vm_state', return_value=state) - ) as (mock_reboot, mock_get_vm_state): + ) as (mock_get_vm_ref, mock_reboot, mock_get_vm_state): self.conn.resume_state_on_host_boot(self.context, self.instance, 'network_info') + mock_get_vm_ref.assert_called_once_with(self.conn._session, + self.conn._cluster_ref, + self.instance) mock_get_vm_state.assert_called_once_with(self.conn._session, - self.instance) + mock.sentinel.vm_ref) self.assertFalse(mock_reboot.called) @mock.patch('nova.virt.driver.block_device_info_get_mapping') @@ -1715,7 +1730,7 @@ def fake_vm_ref_from_name(session, vm_name): mock.patch.object(vm_util, 'get_vm_ref_from_name', fake_vm_ref_from_name), mock.patch.object(self.conn._session, - '_call_method'), + 'call_method'), mock.patch.object(self.conn._vmops, '_destroy_instance') ) as (mock_get, mock_call, mock_destroy): @@ -1775,9 +1790,9 @@ def fake_create_config_drive(instance, injected_files, password, self._create_vm() - def fake_power_on_instance(session, instance, vm_ref=None): + def fake_power_on_instance(session, vm_ref): self._power_on_called += 1 - return self._power_on(session, instance, vm_ref=vm_ref) + return self._power_on(session, vm_ref) info = self._get_info() self._check_vm_info(info, power_state.RUNNING) @@ -1959,12 +1974,13 @@ def test_attach_vmdk_disk_to_vm(self): '/dev/vdc') get_vm_ref.assert_called_once_with(self.conn._session, + self.conn._cluster_ref, self.instance) get_volume_ref.assert_called_once_with( connection_info['data']['volume']) 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', + adapter_type, disk_type, vmdk_path='fake-path', volume_uuid=connection_info['data']['volume_id'], backing_uuid=disk_uuid) @@ -2033,15 +2049,15 @@ def test_attach_iscsi_disk_to_vm(self): self.conn.attach_volume(None, connection_info, self.instance, mount_point) - mock_attach_disk.assert_called_once_with(mock.ANY, self.instance, + mock_attach_disk.assert_called_once_with(mock.ANY, mock.ANY, 'rdmp', device_name=mock.ANY) mock_iscsi_get_target.assert_called_once_with( connection_info['data']) 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] @@ -2049,7 +2065,8 @@ def test_iscsi_rescan_hba(self): self.assertRaises(AttributeError, getattr, iscsi_hba, 'configuredSendTarget') # Rescan HBA with the target portal - vops = volumeops.VMwareVolumeOps(self.conn._session) + vops = volumeops.VMwareVolumeOps(self.conn._session, + self.conn._cluster_ref) vops._iscsi_rescan_hba(fake_target_portal) # Check if HBA has the target portal configured self.assertEqual('fake_target_host', @@ -2061,9 +2078,10 @@ def test_iscsi_rescan_hba(self): 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) + vops = volumeops.VMwareVolumeOps(self.conn._session, + self.conn._cluster_ref) result = vops._iscsi_get_target(data) self.assertEqual(('fake-device', 'fake-uuid'), result) @@ -2093,7 +2111,7 @@ def test_detach_iscsi_disk_from_vm(self, mock_iscsi_get_target, mock_iscsi_get_target.assert_called_once_with(connection_info['data']) mock_get_rdm_disk.assert_called_once() mock_detach_disk_from_vm.assert_called_once_with(mock.ANY, - self.instance, device, destroy_disk=True) + device, destroy_disk=True) def test_connection_info_get(self): self._create_vm() @@ -2228,7 +2246,7 @@ 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', + 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( @@ -2239,7 +2257,7 @@ def test_register_extension(self): constants.EXTENSION_TYPE_INSTANCE)]) def test_register_extension_already_exists(self): - with mock.patch.object(self.conn._session, '_call_method', + 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, @@ -2255,7 +2273,7 @@ def fake_call_method(module, method, *args, **kwargs): else: raise Exception() with (mock.patch.object( - self.conn._session, '_call_method', fake_call_method)): + self.conn._session, 'call_method', fake_call_method)): self.conn._register_openstack_extension() @mock.patch.object(vmops.VMwareVMOps, 'update_cached_instances') @@ -2525,7 +2543,7 @@ def test_attach_interface_with_exception(self): self._create_vm() vif = self._create_vif() - with mock.patch.object(self.conn._session, '_wait_for_task', + with mock.patch.object(self.conn._session, 'wait_for_task', side_effect=Exception): self.assertRaises(exception.InterfaceAttachFailed, self.conn.attach_interface, @@ -2572,7 +2590,7 @@ def test_detach_interface_with_exception(self, mock_get_device): vif = self._create_vif() self._attach_interface(vif) - with mock.patch.object(self.conn._session, '_wait_for_task', + with mock.patch.object(self.conn._session, 'wait_for_task', side_effect=Exception): self.assertRaises(exception.InterfaceDetachFailed, self.conn.detach_interface, diff --git a/nova/tests/unit/virt/vmwareapi/test_ds_util.py b/nova/tests/unit/virt/vmwareapi/test_ds_util.py index 77cfc41201f..860625003bd 100644 --- a/nova/tests/unit/virt/vmwareapi/test_ds_util.py +++ b/nova/tests/unit/virt/vmwareapi/test_ds_util.py @@ -38,7 +38,7 @@ def tearDown(self): fake.reset() def test_get_datacenter_ref(self): - with mock.patch.object(self.session, '_call_method') as call_method: + with mock.patch.object(self.session, 'call_method') as call_method: ds_util.get_datacenter_ref(self.session, "datacenter") call_method.assert_called_once_with( self.session.vim, @@ -56,8 +56,8 @@ def fake_call_method(module, method, *args, **kwargs): return 'fake_delete_task' with test.nested( - mock.patch.object(self.session, '_wait_for_task'), - mock.patch.object(self.session, '_call_method', + mock.patch.object(self.session, 'wait_for_task'), + mock.patch.object(self.session, 'call_method', fake_call_method) ) as (_wait_for_task, _call_method): ds_path = ds_obj.DatastorePath('ds', 'fake/path') @@ -80,8 +80,8 @@ def fake_call_method(module, method, *args, **kwargs): return 'fake_copy_task' with test.nested( - mock.patch.object(self.session, '_wait_for_task'), - mock.patch.object(self.session, '_call_method', + mock.patch.object(self.session, 'wait_for_task'), + mock.patch.object(self.session, 'call_method', fake_call_method) ) as (_wait_for_task, _call_method): src_ds_path = ds_obj.DatastorePath('ds', 'fake/path', 'src_file') @@ -106,8 +106,8 @@ def fake_call_method(module, method, *args, **kwargs): return 'fake_move_task' with test.nested( - mock.patch.object(self.session, '_wait_for_task'), - mock.patch.object(self.session, '_call_method', + mock.patch.object(self.session, 'wait_for_task'), + mock.patch.object(self.session, 'call_method', fake_call_method) ) as (_wait_for_task, _call_method): src_ds_path = ds_obj.DatastorePath('ds', 'tmp/src') @@ -131,8 +131,8 @@ def fake_call_method(module, method, *args, **kwargs): return 'fake_move_task' with test.nested( - mock.patch.object(self.session, '_wait_for_task'), - mock.patch.object(self.session, '_call_method', + mock.patch.object(self.session, 'wait_for_task'), + mock.patch.object(self.session, 'call_method', fake_call_method) ) as (_wait_for_task, _call_method): ds_util.disk_move(self.session, @@ -142,8 +142,8 @@ def fake_call_method(module, method, *args, **kwargs): def test_disk_copy(self): with test.nested( - mock.patch.object(self.session, '_wait_for_task'), - mock.patch.object(self.session, '_call_method', + mock.patch.object(self.session, 'wait_for_task'), + mock.patch.object(self.session, 'call_method', return_value=mock.sentinel.cm) ) as (_wait_for_task, _call_method): ds_util.disk_copy(self.session, mock.sentinel.dc_ref, @@ -158,8 +158,8 @@ def test_disk_copy(self): def test_disk_delete(self): with test.nested( - mock.patch.object(self.session, '_wait_for_task'), - mock.patch.object(self.session, '_call_method', + mock.patch.object(self.session, 'wait_for_task'), + mock.patch.object(self.session, 'call_method', return_value=mock.sentinel.cm) ) as (_wait_for_task, _call_method): ds_util.disk_delete(self.session, @@ -179,7 +179,7 @@ def fake_call_method(module, method, *args, **kwargs): createParentDirectories = kwargs.get('createParentDirectories') self.assertTrue(createParentDirectories) - with mock.patch.object(self.session, '_call_method', + with mock.patch.object(self.session, 'call_method', fake_call_method): ds_path = ds_obj.DatastorePath('ds', 'fake/path') ds_util.mkdir(self.session, ds_path, 'fake-dc-ref') @@ -214,9 +214,9 @@ def fake_wait_for_task(task_ref): self.fail() with test.nested( - mock.patch.object(self.session, '_call_method', + mock.patch.object(self.session, 'call_method', fake_call_method), - mock.patch.object(self.session, '_wait_for_task', + mock.patch.object(self.session, 'wait_for_task', fake_wait_for_task)): ds_path = ds_obj.DatastorePath('ds', 'fake/path') file_exists = ds_util.file_exists(self.session, @@ -239,9 +239,9 @@ def fake_wait_for_task(task_ref): self.fail() with test.nested( - mock.patch.object(self.session, '_call_method', + mock.patch.object(self.session, 'call_method', fake_call_method), - mock.patch.object(self.session, '_wait_for_task', + mock.patch.object(self.session, 'wait_for_task', fake_wait_for_task)): ds_path = ds_obj.DatastorePath('ds', 'fake/path') file_exists = ds_util.file_exists(self.session, @@ -285,7 +285,7 @@ def fake_call_method(module, method, *args, **kwargs): def next_datastore(*args, **kwargs): return next(datastores_i[0]) - with mock.patch.object(self.session, '_call_method', + with mock.patch.object(self.session, 'call_method', side_effect=fake_call_method), \ mock.patch('oslo_vmware.vim_util.continue_retrieval', side_effect=next_datastore), \ @@ -400,7 +400,7 @@ def test_get_datastore_no_host_in_cluster(self): def fake_call_method(module, method, *args, **kwargs): return '' - with mock.patch.object(self.session, '_call_method', + with mock.patch.object(self.session, 'call_method', fake_call_method): self.assertRaises(exception.DatastoreNotFound, ds_util.get_datastore, @@ -456,7 +456,7 @@ def test_is_datastore_valid_matching_regex(self): def test_get_connected_hosts_none(self): with mock.patch.object(self.session, - '_call_method') as _call_method: + 'call_method') as _call_method: hosts = ds_util.get_connected_hosts(self.session, 'fake_datastore') self.assertEqual([], hosts) @@ -472,7 +472,7 @@ def test_get_connected_hosts(self): host_mounts = mock.Mock(spec=object) host_mounts.DatastoreHostMount = [host_mount] - with mock.patch.object(self.session, '_call_method', + with mock.patch.object(self.session, 'call_method', return_value=host_mounts) as _call_method: hosts = ds_util.get_connected_hosts(self.session, 'fake_datastore') diff --git a/nova/tests/unit/virt/vmwareapi/test_images.py b/nova/tests/unit/virt/vmwareapi/test_images.py index 5e2aff019f2..d5945e1ded9 100644 --- a/nova/tests/unit/virt/vmwareapi/test_images.py +++ b/nova/tests/unit/virt/vmwareapi/test_images.py @@ -20,12 +20,14 @@ import mock from oslo_utils import units +from oslo_vmware.objects import datastore as ds_obj from oslo_vmware import rw_handles from nova import exception from nova import objects from nova import test import nova.tests.unit.image.fake +from nova.tests.unit.virt.vmwareapi import fake as vmwareapi_fake from nova.tests import uuidsentinel from nova.virt.vmwareapi import constants from nova.virt.vmwareapi import images @@ -34,6 +36,13 @@ class VMwareImagesTestCase(test.NoDBTestCase): """Unit tests for Vmware API connection calls.""" + def setUp(self): + super(test.NoDBTestCase, self).setUp() + fake_ds_ref = vmwareapi_fake.ManagedObjectReference(value='fake-ds') + self._ds = ds_obj.Datastore( + ref=fake_ds_ref, name='fake_ds', + capacity=10 * units.Gi, + freespace=10 * units.Gi) def test_fetch_image(self): """Test fetching images.""" @@ -118,7 +127,7 @@ def test_fetch_image_ova(self, mock_tar_open, mock_write_class, mock.patch.object(images.IMAGE_API, 'download'), mock.patch.object(images, 'image_transfer'), mock.patch.object(images, '_build_shadow_vm_config_spec'), - mock.patch.object(session, '_call_method'), + mock.patch.object(session, 'call_method'), mock.patch.object(vm_util, 'get_vmdk_info') ) as (mock_image_api_get, mock_image_api_download, @@ -164,7 +173,7 @@ def fake_extract(name): mock_tar_open.return_value.__enter__.return_value = mock_tar images.fetch_image_ova( - context, instance, session, 'fake-vm', 'fake-datastore', + context, instance, session, 'fake-vm', self._ds, vm_folder_ref, res_pool_ref) mock_tar_open.assert_called_once_with(mode='r|', @@ -189,7 +198,7 @@ def test_fetch_image_stream_optimized(self, mock.patch.object(images.IMAGE_API, 'download'), mock.patch.object(images, 'image_transfer'), mock.patch.object(images, '_build_shadow_vm_config_spec'), - mock.patch.object(session, '_call_method'), + mock.patch.object(session, 'call_method'), mock.patch.object(vm_util, 'get_vmdk_info') ) as (mock_image_api_get, mock_image_api_download, @@ -216,7 +225,7 @@ def test_fetch_image_stream_optimized(self, mock.sentinel.vm_ref images.fetch_image_stream_optimized( - context, instance, session, 'fake-vm', 'fake-datastore', + context, instance, session, 'fake-vm', self._ds, vm_folder_ref, res_pool_ref) mock_image_transfer.assert_called_once_with(mock_read_handle, diff --git a/nova/tests/unit/virt/vmwareapi/test_network_util.py b/nova/tests/unit/virt/vmwareapi/test_network_util.py index 9d6533ebfb0..6be301b0bd1 100644 --- a/nova/tests/unit/virt/vmwareapi/test_network_util.py +++ b/nova/tests/unit/virt/vmwareapi/test_network_util.py @@ -23,8 +23,8 @@ from nova import test from nova.tests.unit.virt.vmwareapi import fake from nova.tests.unit.virt.vmwareapi import stubs -from nova.virt.vmwareapi import driver from nova.virt.vmwareapi import network_util +from nova.virt.vmwareapi.session import VMwareAPISession from nova.virt.vmwareapi import vm_util @@ -38,12 +38,12 @@ class GetNetworkWithTheNameTestCase(test.NoDBTestCase): def setUp(self): super(GetNetworkWithTheNameTestCase, self).setUp() fake.reset() - self.stub_out('nova.virt.vmwareapi.driver.VMwareAPISession.vim', + self.stub_out('nova.virt.vmwareapi.session.VMwareAPISession.vim', stubs.fake_vim_prop) - self.stub_out('nova.virt.vmwareapi.driver.' + self.stub_out('nova.virt.vmwareapi.session.' 'VMwareAPISession.is_vim_object', stubs.fake_is_vim_object) - self._session = driver.VMwareAPISession() + self._session = VMwareAPISession() def _build_cluster_networks(self, networks): """Returns a set of results for a cluster network lookup. @@ -104,7 +104,7 @@ def mock_call_method(module, method, *args, **kwargs): result.name = 'no-match' return result - with mock.patch.object(self._session, '_call_method', + with mock.patch.object(self._session, 'call_method', mock_call_method): res = network_util.get_network_with_the_name(self._session, 'fake_net', @@ -126,7 +126,7 @@ def mock_call_method(module, method, *args, **kwargs): result.distributedVirtualSwitch = 'fake_dvs' return result - with mock.patch.object(self._session, '_call_method', + with mock.patch.object(self._session, 'call_method', mock_call_method): res = network_util.get_network_with_the_name(self._session, 'fake_net', @@ -149,7 +149,7 @@ def mock_call_method(module, method, *args, **kwargs): if method == 'get_object_property': return 'fake_net' - with mock.patch.object(self._session, '_call_method', + with mock.patch.object(self._session, 'call_method', mock_call_method): res = network_util.get_network_with_the_name(self._session, 'fake_net', @@ -162,7 +162,7 @@ class GetVlanIdAndVswitchForPortgroupTestCase(test.NoDBTestCase): @mock.patch.object(vm_util, 'get_host_ref') def test_no_port_groups(self, mock_get_host_ref): session = mock.Mock() - session._call_method.return_value = None + session.call_method.return_value = None self.assertRaises( exception.NovaException, network_util.get_vlanid_and_vswitch_for_portgroup, @@ -174,7 +174,7 @@ def test_no_port_groups(self, mock_get_host_ref): @mock.patch.object(vm_util, 'get_host_ref') def test_valid_port_group(self, mock_get_host_ref): session = mock.Mock() - session._call_method.return_value = self._fake_port_groups() + session.call_method.return_value = self._fake_port_groups() vlanid, vswitch = network_util.get_vlanid_and_vswitch_for_portgroup( session, 'port_group_name', @@ -186,7 +186,7 @@ def test_valid_port_group(self, mock_get_host_ref): @mock.patch.object(vm_util, 'get_host_ref') def test_unknown_port_group(self, mock_get_host_ref): session = mock.Mock() - session._call_method.return_value = self._fake_port_groups() + session.call_method.return_value = self._fake_port_groups() vlanid, vswitch = network_util.get_vlanid_and_vswitch_for_portgroup( session, 'unknown_port_group', diff --git a/nova/tests/unit/virt/vmwareapi/test_vif.py b/nova/tests/unit/virt/vmwareapi/test_vif.py index 59b2937866e..d0c9a244aa2 100644 --- a/nova/tests/unit/virt/vmwareapi/test_vif.py +++ b/nova/tests/unit/virt/vmwareapi/test_vif.py @@ -188,7 +188,7 @@ def fake_call_method(module, method, *args, **kwargs): with test.nested( mock.patch.object(vm_util, 'get_add_vswitch_port_group_spec'), mock.patch.object(vm_util, 'get_host_ref'), - mock.patch.object(self.session, '_call_method', + mock.patch.object(self.session, 'call_method', fake_call_method) ) as (_add_vswitch, _get_host, _call_method): network_util.create_port_group(self.session, 'pg_name', @@ -203,7 +203,7 @@ def fake_call_method(module, method, *args, **kwargs): with test.nested( mock.patch.object(vm_util, 'get_add_vswitch_port_group_spec'), mock.patch.object(vm_util, 'get_host_ref'), - mock.patch.object(self.session, '_call_method', + mock.patch.object(self.session, 'call_method', fake_call_method) ) as (_add_vswitch, _get_host, _call_method): self.assertRaises(vexc.VMwareDriverException, diff --git a/nova/tests/unit/virt/vmwareapi/test_vim_util.py b/nova/tests/unit/virt/vmwareapi/test_vim_util.py index bdd9cf569d3..42b56fe2169 100644 --- a/nova/tests/unit/virt/vmwareapi/test_vim_util.py +++ b/nova/tests/unit/virt/vmwareapi/test_vim_util.py @@ -28,12 +28,12 @@ def setUp(self): 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) diff --git a/nova/tests/unit/virt/vmwareapi/test_vm_util.py b/nova/tests/unit/virt/vmwareapi/test_vm_util.py index 25dfa98076a..906189f9728 100644 --- a/nova/tests/unit/virt/vmwareapi/test_vm_util.py +++ b/nova/tests/unit/virt/vmwareapi/test_vm_util.py @@ -33,7 +33,7 @@ from nova.tests.unit.virt.vmwareapi import fake from nova.tests.unit.virt.vmwareapi import stubs from nova.virt.vmwareapi import constants -from nova.virt.vmwareapi import driver +from nova.virt.vmwareapi.session import VMwareAPISession from nova.virt.vmwareapi import vim_util from nova.virt.vmwareapi import vm_util @@ -127,7 +127,7 @@ def fake_call_method(*args): raise Exception('unexpected method call') session = fake.FakeSession() - with mock.patch.object(session, '_call_method', fake_call_method): + with mock.patch.object(session, 'call_method', fake_call_method): result = vm_util.get_stats_from_cluster(session, "cluster1") if connection_state == "connected" and not maintenance_mode: num_hosts = 2 @@ -482,7 +482,7 @@ def test_get_vmdk_path_and_adapter_type(self): filename = '[test_datastore] uuid/uuid.vmdk' devices = self._vmdk_path_and_adapter_type_devices(filename) session = fake.FakeSession() - with mock.patch.object(session, '_call_method', return_value=devices): + with mock.patch.object(session, 'call_method', return_value=devices): vmdk = vm_util.get_vmdk_info(session, None) self.assertEqual(constants.ADAPTER_TYPE_LSILOGICSAS, vmdk.adapter_type) @@ -495,7 +495,7 @@ def test_get_vmdk_path_and_adapter_type_with_match(self): n_filename = '[test_datastore] uuid/uuid.vmdk' devices = self._vmdk_path_and_adapter_type_devices(n_filename) session = fake.FakeSession() - with mock.patch.object(session, '_call_method', return_value=devices): + with mock.patch.object(session, 'call_method', return_value=devices): vmdk = vm_util.get_vmdk_info(session, None, uuid='uuid') self.assertEqual(constants.ADAPTER_TYPE_LSILOGICSAS, vmdk.adapter_type) @@ -507,7 +507,7 @@ def test_get_vmdk_path_and_adapter_type_with_nomatch(self): n_filename = '[test_datastore] diuu/diuu.vmdk' session = fake.FakeSession() devices = self._vmdk_path_and_adapter_type_devices_nomatch(n_filename) - with mock.patch.object(session, '_call_method', return_value=devices): + with mock.patch.object(session, 'call_method', return_value=devices): vmdk = vm_util.get_vmdk_info(session, None, uuid='uuid') self.assertIsNone(vmdk.adapter_type) self.assertIsNone(vmdk.path) @@ -1194,14 +1194,13 @@ def fake_wait_for_task(self, *args): fake_call_mock = mock.Mock(side_effect=fake_call_method) fake_wait_mock = mock.Mock(side_effect=fake_wait_for_task) with test.nested( - mock.patch.object(session, '_wait_for_task', + mock.patch.object(session, 'wait_for_task', fake_wait_mock), - mock.patch.object(session, '_call_method', + mock.patch.object(session, 'call_method', fake_call_mock) ) as (wait_for_task, call_method): vm_ref = vm_util.create_vm( session, - self._instance, 'fake_vm_folder', 'fake_config_spec', 'fake_res_pool_ref') @@ -1227,7 +1226,7 @@ def fake_log_warn(msg, values): found[0] = True mock_log_warn.side_effect = fake_log_warn - session = driver.VMwareAPISession() + session = VMwareAPISession() config_spec = vm_util.get_vm_create_spec( session.vim.client.factory, @@ -1236,7 +1235,7 @@ def fake_log_warn(msg, values): os_type='invalid_os_type') self.assertRaises(vexc.VMwareDriverException, - vm_util.create_vm, session, self._instance, + vm_util.create_vm, session, 'folder', config_spec, 'res-pool') self.assertTrue(found[0]) @@ -1259,28 +1258,11 @@ def test_convert_vif_model(self): def test_power_on_instance_with_vm_ref(self): session = fake.FakeSession() with test.nested( - mock.patch.object(session, "_call_method", + mock.patch.object(session, "call_method", return_value='fake-task'), - mock.patch.object(session, "_wait_for_task"), + mock.patch.object(session, "wait_for_task"), ) as (fake_call_method, fake_wait_for_task): - vm_util.power_on_instance(session, self._instance, - vm_ref='fake-vm-ref') - fake_call_method.assert_called_once_with(session.vim, - "PowerOnVM_Task", - 'fake-vm-ref') - fake_wait_for_task.assert_called_once_with('fake-task') - - def test_power_on_instance_without_vm_ref(self): - session = fake.FakeSession() - with test.nested( - mock.patch.object(vm_util, "get_vm_ref", - return_value='fake-vm-ref'), - mock.patch.object(session, "_call_method", - return_value='fake-task'), - mock.patch.object(session, "_wait_for_task"), - ) as (fake_get_vm_ref, fake_call_method, fake_wait_for_task): - vm_util.power_on_instance(session, self._instance) - fake_get_vm_ref.assert_called_once_with(session, self._instance) + vm_util.power_on_instance(session, 'fake-vm-ref') fake_call_method.assert_called_once_with(session.vim, "PowerOnVM_Task", 'fake-vm-ref') @@ -1289,15 +1271,14 @@ def test_power_on_instance_without_vm_ref(self): def test_power_on_instance_with_exception(self): session = fake.FakeSession() with test.nested( - mock.patch.object(session, "_call_method", + mock.patch.object(session, "call_method", return_value='fake-task'), - mock.patch.object(session, "_wait_for_task", + mock.patch.object(session, "wait_for_task", side_effect=exception.NovaException('fake')), ) as (fake_call_method, fake_wait_for_task): self.assertRaises(exception.NovaException, vm_util.power_on_instance, - session, self._instance, - vm_ref='fake-vm-ref') + session, 'fake-vm-ref') fake_call_method.assert_called_once_with(session.vim, "PowerOnVM_Task", 'fake-vm-ref') @@ -1306,14 +1287,13 @@ def test_power_on_instance_with_exception(self): def test_power_on_instance_with_power_state_exception(self): session = fake.FakeSession() with test.nested( - mock.patch.object(session, "_call_method", + mock.patch.object(session, "call_method", return_value='fake-task'), mock.patch.object( - session, "_wait_for_task", + session, "wait_for_task", side_effect=vexc.InvalidPowerStateException), ) as (fake_call_method, fake_wait_for_task): - vm_util.power_on_instance(session, self._instance, - vm_ref='fake-vm-ref') + vm_util.power_on_instance(session, 'fake-vm-ref') fake_call_method.assert_called_once_with(session.vim, "PowerOnVM_Task", 'fake-vm-ref') @@ -1325,9 +1305,9 @@ def test_create_virtual_disk(self): with test.nested( mock.patch.object(vm_util, "get_vmdk_create_spec", return_value='fake-spec'), - mock.patch.object(session, "_call_method", + mock.patch.object(session, "call_method", return_value='fake-task'), - mock.patch.object(session, "_wait_for_task"), + mock.patch.object(session, "wait_for_task"), ) as (fake_get_spec, fake_call_method, fake_wait_for_task): vm_util.create_virtual_disk(session, 'fake-dc-ref', 'fake-adapter-type', 'fake-disk-type', @@ -1349,9 +1329,9 @@ def test_copy_virtual_disk(self): session = fake.FakeSession() dm = session.vim.service_content.virtualDiskManager with test.nested( - mock.patch.object(session, "_call_method", + mock.patch.object(session, "call_method", return_value='fake-task'), - mock.patch.object(session, "_wait_for_task"), + mock.patch.object(session, "wait_for_task"), ) as (fake_call_method, fake_wait_for_task): vm_util.copy_virtual_disk(session, 'fake-dc-ref', 'fake-source', 'fake-dest') @@ -1372,9 +1352,9 @@ def _create_fake_vm_objects(self): def test_reconfigure_vm(self): session = fake.FakeSession() with test.nested( - mock.patch.object(session, '_call_method', + mock.patch.object(session, 'call_method', return_value='fake_reconfigure_task'), - mock.patch.object(session, '_wait_for_task') + mock.patch.object(session, 'wait_for_task') ) as (_call_method, _wait_for_task): vm_util.reconfigure_vm(session, 'fake-ref', 'fake-spec') _call_method.assert_called_once_with(mock.ANY, @@ -1667,70 +1647,49 @@ def test_get_network_detach_config_spec(self): self.assertEqual(expected, result) - @mock.patch.object(vm_util, "get_vm_ref") - def test_power_off_instance(self, fake_get_ref): - session = fake.FakeSession() - with test.nested( - mock.patch.object(session, '_call_method', - return_value='fake-task'), - mock.patch.object(session, '_wait_for_task') - ) as (fake_call_method, fake_wait_for_task): - vm_util.power_off_instance(session, self._instance, 'fake-vm-ref') - fake_call_method.assert_called_once_with(session.vim, - "PowerOffVM_Task", - 'fake-vm-ref') - fake_wait_for_task.assert_called_once_with('fake-task') - self.assertFalse(fake_get_ref.called) - - @mock.patch.object(vm_util, "get_vm_ref", return_value="fake-vm-ref") - def test_power_off_instance_no_vm_ref(self, fake_get_ref): + def test_power_off_instance(self): session = fake.FakeSession() with test.nested( - mock.patch.object(session, '_call_method', + mock.patch.object(session, 'call_method', return_value='fake-task'), - mock.patch.object(session, '_wait_for_task') + mock.patch.object(session, 'wait_for_task') ) as (fake_call_method, fake_wait_for_task): - vm_util.power_off_instance(session, self._instance) - fake_get_ref.assert_called_once_with(session, self._instance) + vm_util.power_off_instance(session, 'fake-vm-ref') fake_call_method.assert_called_once_with(session.vim, "PowerOffVM_Task", 'fake-vm-ref') fake_wait_for_task.assert_called_once_with('fake-task') - @mock.patch.object(vm_util, "get_vm_ref") - def test_power_off_instance_with_exception(self, fake_get_ref): + def test_power_off_instance_with_exception(self): session = fake.FakeSession() with test.nested( - mock.patch.object(session, '_call_method', + mock.patch.object(session, 'call_method', return_value='fake-task'), - mock.patch.object(session, '_wait_for_task', + mock.patch.object(session, 'wait_for_task', side_effect=exception.NovaException('fake')) ) as (fake_call_method, fake_wait_for_task): self.assertRaises(exception.NovaException, vm_util.power_off_instance, - session, self._instance, 'fake-vm-ref') + session, 'fake-vm-ref') fake_call_method.assert_called_once_with(session.vim, "PowerOffVM_Task", 'fake-vm-ref') fake_wait_for_task.assert_called_once_with('fake-task') - self.assertFalse(fake_get_ref.called) - @mock.patch.object(vm_util, "get_vm_ref") - def test_power_off_instance_power_state_exception(self, fake_get_ref): + def test_power_off_instance_power_state_exception(self): session = fake.FakeSession() with test.nested( - mock.patch.object(session, '_call_method', + mock.patch.object(session, 'call_method', return_value='fake-task'), mock.patch.object( - session, '_wait_for_task', + session, 'wait_for_task', side_effect=vexc.InvalidPowerStateException) ) as (fake_call_method, fake_wait_for_task): - vm_util.power_off_instance(session, self._instance, 'fake-vm-ref') + vm_util.power_off_instance(session, 'fake-vm-ref') fake_call_method.assert_called_once_with(session.vim, "PowerOffVM_Task", 'fake-vm-ref') fake_wait_for_task.assert_called_once_with('fake-task') - self.assertFalse(fake_get_ref.called) def test_get_vm_create_spec_updated_hw_version(self): extra_specs = vm_util.ExtraSpecs(hw_version='vmx-08') @@ -2010,7 +1969,7 @@ def test_get_swap(self): devices = [root_disk, swap_disk] session = fake.FakeSession() - with mock.patch.object(session, '_call_method', + with mock.patch.object(session, 'call_method', return_value=devices) as mock_call: device = vm_util.get_swap(session, vm_ref) @@ -2022,7 +1981,7 @@ def test_create_folder(self): """Test create_folder when the folder doesn't exist""" child_folder = mock.sentinel.child_folder session = fake.FakeSession() - with mock.patch.object(session, '_call_method', + with mock.patch.object(session, 'call_method', side_effect=[child_folder]): parent_folder = mock.sentinel.parent_folder parent_folder.value = 'parent-ref' @@ -2030,7 +1989,7 @@ def test_create_folder(self): ret = vm_util.create_folder(session, parent_folder, child_name) self.assertEqual(child_folder, ret) - session._call_method.assert_called_once_with(session.vim, + session.call_method.assert_called_once_with(session.vim, 'CreateFolder', parent_folder, name=child_name) @@ -2040,7 +1999,7 @@ def test_create_folder_duplicate_name(self): session = fake.FakeSession() details = {'object': 'folder-1'} duplicate_exception = vexc.DuplicateName(details=details) - with mock.patch.object(session, '_call_method', + with mock.patch.object(session, 'call_method', side_effect=[duplicate_exception]): parent_folder = mock.sentinel.parent_folder parent_folder.value = 'parent-ref' @@ -2049,7 +2008,7 @@ def test_create_folder_duplicate_name(self): self.assertEqual('Folder', ret._type) self.assertEqual('folder-1', ret.value) - session._call_method.assert_called_once_with(session.vim, + session.call_method.assert_called_once_with(session.vim, 'CreateFolder', parent_folder, name=child_name) @@ -2081,9 +2040,9 @@ def test_get_vm_name(self): def test_rename_vm(self, mock_get_name): session = fake.FakeSession() with test.nested( - mock.patch.object(session, '_call_method', + mock.patch.object(session, 'call_method', return_value='fake_rename_task'), - mock.patch.object(session, '_wait_for_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, @@ -2094,40 +2053,29 @@ def test_rename_vm(self, mock_get_name): self._instance.uuid) -@mock.patch.object(driver.VMwareAPISession, 'vim', stubs.fake_vim_prop) +@mock.patch.object(VMwareAPISession, 'vim', stubs.fake_vim_prop) class VMwareVMUtilGetHostRefTestCase(test.NoDBTestCase): # N.B. Mocking on the class only mocks test_*(), but we need # VMwareAPISession.vim to be mocked in both setUp and tests. Not mocking in # setUp causes object initialisation to fail. Not mocking in tests results # in vim calls not using FakeVim. - @mock.patch.object(driver.VMwareAPISession, 'vim', stubs.fake_vim_prop) + @mock.patch.object(VMwareAPISession, 'vim', stubs.fake_vim_prop) def setUp(self): super(VMwareVMUtilGetHostRefTestCase, self).setUp() fake.reset() vm_util.vm_refs_cache_reset() - self.session = driver.VMwareAPISession() + self.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') - def test_get_host_ref_for_vm(self, mock_get_vm_ref): - mock_get_vm_ref.return_value = self.vm_ref - - ret = vm_util.get_host_ref_for_vm(self.session, 'fake-instance') - - mock_get_vm_ref.assert_called_once_with(self.session, 'fake-instance') + def test_get_host_ref_for_vm(self): + ret = vm_util.get_host_ref_for_vm(self.session, self.vm_ref) self.assertEqual(self.host_ref, ret) - @mock.patch.object(vm_util, 'get_vm_ref') - 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) - - ret = vm_util.get_host_name_for_vm(self.session, 'fake-instance') - - mock_get_vm_ref.assert_called_once_with(self.session, 'fake-instance') + def test_get_host_name_for_vm(self): + host = fake.get_object(self.host_ref) + ret = vm_util.get_host_name_for_vm(self.session, self.vm_ref) self.assertEqual(host.name, ret) diff --git a/nova/tests/unit/virt/vmwareapi/test_vmops.py b/nova/tests/unit/virt/vmwareapi/test_vmops.py index 4418496ddeb..01646f05065 100644 --- a/nova/tests/unit/virt/vmwareapi/test_vmops.py +++ b/nova/tests/unit/virt/vmwareapi/test_vmops.py @@ -44,9 +44,9 @@ from nova.virt import hardware from nova.virt.vmwareapi import cluster_util from nova.virt.vmwareapi import constants -from nova.virt.vmwareapi import driver from nova.virt.vmwareapi import ds_util from nova.virt.vmwareapi import images +from nova.virt.vmwareapi.session import VMwareAPISession from nova.virt.vmwareapi import vif from nova.virt.vmwareapi import vim_util from nova.virt.vmwareapi import vm_util @@ -75,11 +75,12 @@ def setUp(self): my_ip='', flat_injected=True) self._context = context.RequestContext('fake_user', 'fake_project') - self._session = driver.VMwareAPISession() + self._session = VMwareAPISession() self._virtapi = mock.Mock() self._image_id = nova.tests.unit.image.fake.get_valid_image_id() - fake_ds_ref = vmwareapi_fake.ManagedObjectReference(value='fake-ds') + fake_ds_ref = vmwareapi_fake.ManagedObjectReference(name='fake-ds', + value='Datastore') self._ds = ds_obj.Datastore( ref=fake_ds_ref, name='fake_ds', capacity=10 * units.Gi, @@ -87,9 +88,9 @@ def setUp(self): self._dc_info = ds_util.DcInfo( ref='fake_dc_ref', name='fake_dc', - vmFolder=vmwareapi_fake.ManagedObjectReference - (name='fake_vm_folder', - value='Folder')) + vmFolder=vmwareapi_fake.ManagedObjectReference( + name='fake_vm_folder', + value='Folder')) cluster = vmwareapi_fake.create_cluster('fake_cluster', fake_ds_ref) self._uuid = uuidsentinel.foo self._instance_values = { @@ -109,7 +110,7 @@ def setUp(self): root_gb=10, ephemeral_gb=0, swap=0, extra_specs={}) self._instance.flavor = self._flavor - self._volumeops = volumeops.VMwareVolumeOps(self._session) + self._volumeops = volumeops.VMwareVolumeOps(self._session, cluster.obj) self._vmops = vmops.VMwareVMOps(self._session, self._virtapi, self._volumeops, cluster=cluster.obj) @@ -268,11 +269,10 @@ def fake_call_method(module, method, *args, **kwargs): return 'fake_remove_snapshot_task' with test.nested( - mock.patch.object(self._session, '_wait_for_task'), - mock.patch.object(self._session, '_call_method', fake_call_method) + mock.patch.object(self._session, 'wait_for_task'), + mock.patch.object(self._session, 'call_method', fake_call_method) ) as (_wait_for_task, _call_method): - self._vmops._delete_vm_snapshot(self._instance, - "fake_vm_ref", "fake_vm_snapshot") + self._vmops._delete_vm_snapshot("fake_vm_snapshot") _wait_for_task.assert_has_calls([ mock.call('fake_remove_snapshot_task')]) @@ -295,8 +295,8 @@ def fake_call_method(module, method, *args, **kwargs): return task_info with test.nested( - mock.patch.object(self._session, '_wait_for_task'), - mock.patch.object(self._session, '_call_method', fake_call_method) + mock.patch.object(self._session, 'wait_for_task'), + mock.patch.object(self._session, 'call_method', fake_call_method) ) as (_wait_for_task, _call_method): snap = self._vmops._create_vm_snapshot(self._instance, "fake_vm_ref") @@ -306,8 +306,7 @@ def fake_call_method(module, method, *args, **kwargs): def test_update_instance_progress(self): with mock.patch.object(self._instance, 'save') as mock_save: - self._vmops._update_instance_progress(self._instance._context, - self._instance, 5, 10) + self._vmops._update_instance_progress(self._instance, 5, 10) mock_save.assert_called_once_with() self.assertEqual(50, self._instance.progress) @@ -326,11 +325,12 @@ def test_get_info(self, mock_value_cache, mock_update_cached_instances, mock_get_vm_ref.return_value = vmwareapi_fake.ManagedObjectReference( value='test_id') - with mock.patch.object(self._session, '_call_method', + with mock.patch.object(self._session, 'call_method', return_value=result): info = self._vmops.get_info(self._instance) mock_get_vm_ref.assert_called_once_with(self._session, - self._instance) + self._cluster.obj, + self._instance) expected = hardware.InstanceInfo(state=power_state.RUNNING) self.assertEqual(expected, info) @@ -341,21 +341,23 @@ def test_get_info_when_ds_unavailable(self, mock_get_vm_ref): } mock_get_vm_ref.return_value = vmwareapi_fake.ManagedObjectReference( value='fake_powered_off') - with mock.patch.object(self._session, '_call_method', + with mock.patch.object(self._session, 'call_method', return_value=result): info = self._vmops.get_info(self._instance) mock_get_vm_ref.assert_called_once_with(self._session, - self._instance) + self._cluster.obj, + self._instance) self.assertEqual(hardware.InstanceInfo(state=power_state.SHUTDOWN), info) - @mock.patch.object(vm_util, 'get_vm_ref') + @mock.patch.object(vm_util, 'search_vm_ref_by_identifier') @mock.patch.object(vmops.VMwareVMOps, 'update_cached_instances') @mock.patch.object(vm_util, '_VM_VALUE_CACHE') def test_get_info_instance_deleted(self, mock_value_cache, mock_update_cached_instances, - mock_get_vm_ref): + mock_search_vm_ref): vm_util.vm_value_cache_reset() + vm_ref_value = mock.sentinel.missing_ref props = ['summary.config.numCpu', 'summary.config.memorySizeMB', 'runtime.powerState'] prop_cpu = vmwareapi_fake.Prop(props[0], 4) @@ -365,19 +367,25 @@ def test_get_info_instance_deleted(self, mock_value_cache, obj_content = vmwareapi_fake.ObjectContent(None, prop_list=prop_list) result = vmwareapi_fake.FakeRetrieveResult() result.add_object(obj_content) - mock_get_vm_ref.return_value = vmwareapi_fake.ManagedObjectReference( - value='fake_powered_off') + mock_search_vm_ref.side_effect = [ + vmwareapi_fake.ManagedObjectReference(value=vm_ref_value), + None + ] def mock_call_method(module, method, *args, **kwargs): - raise vexc.ManagedObjectNotFoundException() + raise vexc.ManagedObjectNotFoundException( + details={'obj': vm_ref_value} + ) - with mock.patch.object(self._session, '_call_method', + with mock.patch.object(vutil, 'get_object_properties_dict', mock_call_method): self.assertRaises(exception.InstanceNotFound, self._vmops.get_info, self._instance) - mock_get_vm_ref.assert_called_once_with(self._session, - self._instance) + mock_search_vm_ref.assert_has_calls(2 * [ + mock.call(self._session, + self._cluster.obj, + self._instance.uuid)]) def _test_get_datacenter_ref_and_name(self, ds_ref_exists=False): instance_ds_ref = mock.Mock() @@ -393,7 +401,7 @@ def _test_get_datacenter_ref_and_name(self, ds_ref_exists=False): result.add_object(vmwareapi_fake.Datacenter(ds_ref=None)) result.add_object(vmwareapi_fake.Datacenter()) - with mock.patch.object(self._session, '_call_method', + with mock.patch.object(self._session, 'call_method', return_value=result) as fake_call: dc_info = _vcvmops.get_datacenter_ref_and_name(instance_ds_ref) @@ -462,7 +470,6 @@ def test_rescue(self, self._vmops.rescue( self._context, self._instance, None, self._image_meta) mock_power_off.assert_called_once_with(self._session, - self._instance, vm_ref) uuid = self._instance.image_ref @@ -473,15 +480,14 @@ def test_rescue(self, mock_disk_copy.assert_called_once_with(self._session, dc_info.ref, cache_path, rescue_path) _volumeops.attach_disk_to_vm.assert_called_once_with(vm_ref, - self._instance, mock.ANY, mock.ANY, rescue_path) + mock.ANY, mock.ANY, rescue_path) mock_get_boot_spec.assert_called_once_with(mock.ANY, 'fake-rescue-device') mock_reconfigure.assert_called_once_with(self._session, vm_ref, 'fake-boot-spec') mock_power_on.assert_called_once_with(self._session, - self._instance, - vm_ref=vm_ref) + vm_ref) def test_unrescue_power_on(self): self._test_unrescue(True) @@ -503,7 +509,7 @@ def fake_call_method(module, method, *args, **kwargs): mock.patch.object(vm_util, 'power_on_instance'), mock.patch.object(vm_util, 'find_rescue_device'), mock.patch.object(vm_util, 'get_vm_ref', return_value=vm_ref), - mock.patch.object(self._session, '_call_method', + mock.patch.object(self._session, 'call_method', fake_call_method), mock.patch.object(vm_util, 'power_off_instance') ) as (_power_on_instance, _find_rescue, _get_vm_ref, @@ -512,15 +518,16 @@ def fake_call_method(module, method, *args, **kwargs): if power_on: _power_on_instance.assert_called_once_with(self._session, - self._instance, vm_ref=vm_ref) + vm_ref) else: self.assertFalse(_power_on_instance.called) + _get_vm_ref.assert_called_once_with(self._session, + self._cluster.obj, self._instance) - _power_off.assert_called_once_with(self._session, self._instance, - vm_ref) + _power_off.assert_called_once_with(self._session, vm_ref) _volumeops.detach_disk_from_vm.assert_called_once_with( - vm_ref, self._instance, mock.ANY, destroy_disk=True) + vm_ref, mock.ANY, destroy_disk=True) @mock.patch.object(time, 'sleep') @mock.patch.object(vmops.VMwareVMOps, 'update_cached_instances') @@ -576,7 +583,7 @@ def fake_call_method(module, method, *args, **kwargs): with test.nested( mock.patch.object(vm_util, 'get_vm_ref', return_value=vm_ref), - mock.patch.object(self._session, '_call_method', + mock.patch.object(self._session, 'call_method', side_effect=fake_call_method) ) as (mock_get_vm_ref, mock_call_method): result = self._vmops._clean_shutdown(instance, timeout, @@ -584,6 +591,7 @@ def fake_call_method(module, method, *args, **kwargs): self.assertEqual(succeeds, result) mock_get_vm_ref.assert_called_once_with(self._session, + self._cluster.obj, self._instance) def test_clean_shutdown_first_time(self): @@ -662,7 +670,8 @@ def _test_finish_migration(self, power_on=True, self._instance.flavor.root_gb * units.Gi, 'fake-device') fake_get_vmdk_info.return_value = vmdk - vm_ref_calls = [mock.call(self._session, self._instance)] + vm_ref_calls = [mock.call(self._session, + self._cluster.obj, self._instance)] try: self._vmops.finish_migration(context=self._context, migration=migration, @@ -699,8 +708,7 @@ def _test_finish_migration(self, power_on=True, 'fake-ref') if power_on: fake_power_on.assert_called_once_with(self._session, - self._instance, - vm_ref='fake-ref') + 'fake-ref') else: self.assertFalse(fake_power_on.called) @@ -716,7 +724,7 @@ def _test_finish_migration(self, power_on=True, vmdk, self._instance.flavor) - calls = [mock.call(self._context, self._instance, step=i, + calls = [mock.call(self._instance, step=i, total_steps=vmops.RESIZE_TOTAL_STEPS) for i in range(2, 7)] fake_update_instance_progress.assert_has_calls(calls) @@ -872,9 +880,10 @@ def _test_finish_revert_migration(self, fake_list_instances, except test.TestingException: pass - vm_ref_calls = [mock.call(self._session, self._instance)] + vm_ref_calls = [mock.call(self._session, + self._cluster.obj, + self._instance)] fake_power_off.assert_called_once_with(self._session, - self._instance, 'fake-ref') # Validate VM reconfiguration metadata = ('name:fake_display_name\n' @@ -909,7 +918,6 @@ def _test_finish_revert_migration(self, fake_list_instances, 'original.vmdk') mock_detach_disk.assert_called_once_with('fake-ref', - self._instance, device) fake_disk_delete.assert_called_once_with( self._session, dc_info.ref, '[fake] uuid/root.vmdk') @@ -918,7 +926,7 @@ def _test_finish_revert_migration(self, fake_list_instances, '[fake] uuid/original.vmdk', '[fake] uuid/root.vmdk') mock_attach_disk.assert_called_once_with( - 'fake-ref', self._instance, vmdk.adapter_type, 'fake-disk', + 'fake-ref', vmdk.adapter_type, 'fake-disk', '[fake] uuid/root.vmdk') fake_remove_ephemerals_and_swap.assert_called_once_with('fake-ref') fake_resize_create_ephemerals_and_swap.assert_called_once_with( @@ -940,7 +948,7 @@ def _test_finish_revert_migration(self, fake_list_instances, fake_get_vm_ref.assert_has_calls(vm_ref_calls) if power_on and not relocate_fails: fake_power_on.assert_called_once_with(self._session, - self._instance) + 'fake-ref') else: self.assertFalse(fake_power_on.called) @@ -1134,10 +1142,9 @@ def test_resize_disk(self, fake_disk_copy, fake_disk_move, self._session, dc_info.ref, '[fake] uuid/root.vmdk', '[fake] uuid/resized.vmdk') mock_detach_disk.assert_called_once_with('fake-ref', - instance, device) fake_extend.assert_called_once_with( - instance, flavor['root_gb'] * units.Mi, + flavor['root_gb'] * units.Mi, '[fake] uuid/resized.vmdk', dc_info.ref) calls = [ mock.call(self._session, dc_info.ref, @@ -1149,7 +1156,7 @@ def test_resize_disk(self, fake_disk_copy, fake_disk_move, fake_disk_move.assert_has_calls(calls) mock_attach_disk.assert_called_once_with( - 'fake-ref', instance, 'fake-adapter', 'fake-disk', + 'fake-ref', 'fake-adapter', 'fake-disk', '[fake] uuid/root.vmdk') @mock.patch.object(vm_util, 'detach_devices_from_vm') @@ -1199,6 +1206,7 @@ def test_confirm_migration(self, fake_get_vm_ref, fake_get_browser, self._instance, None) fake_get_vm_ref.assert_called_once_with(self._session, + self._cluster.obj, self._instance) fake_get_vmdk_info.assert_called_once_with( self._session, 'fake-ref', uuid=self._instance.uuid) @@ -1244,12 +1252,12 @@ def _test_migrate_disk_and_power_off(self, fake_get_vm_ref, fake_progress, flavor) fake_get_vm_ref.assert_called_once_with(self._session, + self._cluster.obj, self._instance) fake_power_off.assert_called_once_with(self._session, - self._instance, 'fake-ref') - calls = [mock.call(self._context, self._instance, step=i, + calls = [mock.call(self._instance, step=i, total_steps=vmops.RESIZE_TOTAL_STEPS) for i in range(2)] fake_progress.assert_has_calls(calls) @@ -1326,19 +1334,19 @@ def test_finish_migration_root_block_device(self, fake_get_vm_ref, image_meta=self._image_meta, power_on=True) fake_get_vm_ref.assert_called_once_with(self._session, + self._cluster.obj, self._instance) fake_resize_create_eph_swap.assert_called_once_with( 'fake-ref', self._instance, None) fake_remove_eph_and_swap.assert_called_once_with('fake-ref') - fake_power_on.assert_called_once_with(self._session, self._instance, - vm_ref='fake-ref') + fake_power_on.assert_called_once_with(self._session, 'fake-ref') fake_resize_vm.assert_called_once_with(self._context, self._instance, 'fake-ref', self._instance.flavor, self._image_meta) fake_get_vmdk_info.assert_not_called() fake_resize_disk.assert_not_called() - calls = [mock.call(self._context, self._instance, step=i, + calls = [mock.call(self._instance, step=i, total_steps=vmops.RESIZE_TOTAL_STEPS) for i in range(2, 7)] fake_progress.assert_has_calls(calls) @@ -1441,11 +1449,10 @@ def test_manage_image_cache_templates(self, mock_get_avlbl_ds, mock.patch.object(self._vmops, '_get_image_template_vms', return_value=[(expired_templ_vm_ref, 'n1'), (used_templ_vm_ref, 'n2')]), - mock.patch.object(self._session, '_call_method'), - mock.patch.object(self._session, '_wait_for_task')): + mock.patch.object(self._session, 'call_method'), + mock.patch.object(self._session, 'wait_for_task')): self._vmops.manage_image_cache(self._context, fake_instances) mock_destroy_vm.assert_called_once_with(self._session, - None, expired_templ_vm_ref) @mock.patch.object(vutil, 'WithRetrieval') @@ -1519,7 +1526,7 @@ def test_configure_config_drive(self, network_info, self._ds.name, 'fake_path', self._instance.uuid, "Fake-CookieJar") mock_attach_cdrom_to_vm.assert_called_once_with( - vm_ref, self._instance, self._ds.ref, str(upload_iso_path)) + vm_ref, self._ds.ref, str(upload_iso_path)) @mock.patch('nova.image.api.API.get') @mock.patch.object(vmops.LOG, 'debug') @@ -1667,7 +1674,7 @@ def test_spawn_non_root_block_device(self, from_image, get_vm_config_info.assert_called_once_with(self._instance, image_info, extra_specs) build_virtual_machine.assert_called_once_with( - self._instance, self._context, image_info, vi.datastore, [], + self._instance, image_info, vi.datastore, [], extra_specs, self._get_metadata(), 'fake_vm_folder') enlist_image.assert_called_once_with(image_info.image_id, vi.datastore, vi.dc_info.ref) @@ -1733,7 +1740,7 @@ def test_spawn_with_no_image_and_block_devices(self, from_image, get_vm_config_info.assert_called_once_with(self._instance, image_info, extra_specs) build_virtual_machine.assert_called_once_with( - self._instance, self._context, image_info, vi.datastore, [], + self._instance, image_info, vi.datastore, [], extra_specs, self._get_metadata(is_image_used=False), 'fake_vm_folder') volumeops.attach_root_volume.assert_called_once_with( @@ -1790,7 +1797,7 @@ def test_spawn_unsupported_hardware(self, from_image, get_vm_config_info.assert_called_once_with( self._instance, image_info, extra_specs) build_virtual_machine.assert_called_once_with( - self._instance, self._context, image_info, vi.datastore, [], + self._instance, image_info, vi.datastore, [], extra_specs, self._get_metadata(is_image_used=False), 'fake_vm_folder') @@ -1800,7 +1807,7 @@ def test_get_ds_browser(self): moref = vmwareapi_fake.ManagedObjectReference(value='datastore-100') self.assertIsNone(cache.get(moref.value)) mock_call_method = mock.Mock(return_value=ds_browser) - with mock.patch.object(self._session, '_call_method', + with mock.patch.object(self._session, 'call_method', mock_call_method): ret = self._vmops._get_ds_browser(moref) mock_call_method.assert_called_once_with(vutil, @@ -1847,11 +1854,11 @@ def _test_use_disk_image_as_linked_clone(self, str(sized_cached_image_ds_loc)) mock_extend_if_required.assert_called_once_with( self._dc_info, - vi.ii, - vi.instance, str(sized_cached_image_ds_loc)) + vi.instance, + str(sized_cached_image_ds_loc)) mock_attach_disk_to_vm.assert_called_once_with( - "fake_vm_ref", self._instance, vi.ii.adapter_type, + "fake_vm_ref", vi.ii.adapter_type, vi.ii.disk_type, str(sized_cached_image_ds_loc), vi.root_gb * units.Mi, False, @@ -1899,11 +1906,11 @@ def _test_use_disk_image_as_full_clone(self, mock_extend_if_required.assert_called_once_with( self._dc_info, - vi.ii, - vi.instance, fake_path) + vi.instance, + fake_path) mock_attach_disk_to_vm.assert_called_once_with( - "fake_vm_ref", self._instance, vi.ii.adapter_type, + "fake_vm_ref", vi.ii.adapter_type, vi.ii.disk_type, fake_path, vi.root_gb * units.Mi, False, disk_io_limits=vi._extra_specs.disk_io_limits) @@ -1939,7 +1946,7 @@ def _test_use_iso_image(self, self._vmops._use_iso_image("fake_vm_ref", vi) mock_attach_cdrom.assert_called_once_with( - "fake_vm_ref", self._instance, self._ds.ref, + "fake_vm_ref", self._ds.ref, str(vi.cache_image_path)) fake_path = '[fake_ds] %(uuid)s/%(uuid)s.vmdk' % {'uuid': self._uuid} @@ -1951,7 +1958,7 @@ def _test_use_iso_image(self, vi.root_gb * units.Mi) linked_clone = False mock_attach_disk_to_vm.assert_called_once_with( - "fake_vm_ref", self._instance, + "fake_vm_ref", vi.ii.adapter_type, vi.ii.disk_type, fake_path, vi.root_gb * units.Mi, linked_clone, @@ -2062,8 +2069,8 @@ def _test_spawn(self, extra_specs = vm_util.ExtraSpecs() with test.nested( - mock.patch.object(self._session, '_wait_for_task'), - mock.patch.object(self._session, '_call_method', + mock.patch.object(self._session, 'wait_for_task'), + mock.patch.object(self._session, 'call_method', mock_call_method), mock.patch.object(uuidutils, 'generate_uuid', return_value='tmp-uuid'), @@ -2109,7 +2116,6 @@ def _test_spawn(self, metadata='fake-metadata') mock_create_vm.assert_called_once_with( self._session, - self._instance, 'fake_vm_folder', 'fake_create_spec', self._cluster.resourcePool) @@ -2123,7 +2129,7 @@ def _test_spawn(self, network_info, vm_ref='fake_vm_ref') mock_power_on_instance.assert_called_once_with( - self._session, self._instance, vm_ref='fake_vm_ref') + self._session, 'fake_vm_ref') if (block_device_info and 'block_device_mapping' in block_device_info): @@ -2341,7 +2347,6 @@ def test_spawn_with_ephemerals_and_swap(self, from_image, get_vm_config_info.assert_called_once_with(self._instance, image_info, extra_specs) build_virtual_machine.assert_called_once_with(self._instance, - self._context, image_info, vi.datastore, [], extra_specs, metadata, 'fake-folder') enlist_image.assert_called_once_with(image_info.image_id, vi.datastore, vi.dc_info.ref) @@ -2360,20 +2365,19 @@ def test_spawn_with_ephemerals_and_swap(self, from_image, self._uuid, 'swap.vmdk')) create_and_attach_thin_disk.assert_has_calls([ - mock.call(self._instance, 'fake-vm-ref', vi.dc_info, + mock.call('fake-vm-ref', vi.dc_info, ephemerals[0]['size'] * units.Mi, vi.ii.adapter_type, eph0_path), - mock.call(self._instance, 'fake-vm-ref', vi.dc_info, + mock.call('fake-vm-ref', vi.dc_info, ephemerals[1]['size'] * units.Mi, vi.ii.adapter_type, eph1_path), - mock.call(self._instance, 'fake-vm-ref', vi.dc_info, + mock.call('fake-vm-ref', vi.dc_info, swap['swap_size'] * units.Ki, vi.ii.adapter_type, swap_path) ]) power_on_instance.assert_called_once_with(self._session, - self._instance, - vm_ref='fake-vm-ref') + 'fake-vm-ref') def _get_fake_vi(self): image_info = images.VMwareImage( @@ -2393,8 +2397,7 @@ def test_create_and_attach_thin_disk(self, mock_create): path = str(ds_obj.DatastorePath(vi.datastore.name, self._uuid, 'fake-filename')) - self._vmops._create_and_attach_thin_disk(self._instance, - 'fake-vm-ref', + self._vmops._create_and_attach_thin_disk('fake-vm-ref', vi.dc_info, 1, 'fake-adapter-type', path) @@ -2402,7 +2405,7 @@ def test_create_and_attach_thin_disk(self, mock_create): self._session, self._dc_info.ref, 'fake-adapter-type', 'thin', path, 1) mock_attach_disk_to_vm.assert_called_once_with( - 'fake-vm-ref', self._instance, 'fake-adapter-type', + 'fake-vm-ref', 'fake-adapter-type', 'thin', path, 1, False) def test_create_ephemeral_with_bdi(self): @@ -2421,7 +2424,7 @@ def test_create_ephemeral_with_bdi(self): self._uuid, vi.ii.adapter_type) mock_caa.assert_called_once_with( - self._instance, 'fake-vm-ref', + 'fake-vm-ref', vi.dc_info, 1 * units.Mi, 'virtio', '[fake_ds] %s/ephemeral_0.vmdk' % self._uuid) @@ -2436,7 +2439,7 @@ def _test_create_ephemeral_from_instance(self, bdi): self._uuid, vi.ii.adapter_type) mock_caa.assert_called_once_with( - self._instance, 'fake-vm-ref', + 'fake-vm-ref', vi.dc_info, 1 * units.Mi, constants.DEFAULT_ADAPTER_TYPE, '[fake_ds] %s/ephemeral_0.vmdk' % self._uuid) @@ -2466,8 +2469,8 @@ def _test_create_swap_from_instance(self, bdi): size = swap.get('swap_size', 0) * units.Ki path = str(ds_obj.DatastorePath(vi.datastore.name, self._uuid, 'swap.vmdk')) - create_and_attach.assert_called_once_with(self._instance, - 'fake-vm-ref', vi.dc_info, size, 'lsiLogic', path) + create_and_attach.assert_called_once_with('fake-vm-ref', + vi.dc_info, size, 'lsiLogic', path) def test_create_swap_with_bdi(self): block_device_info = {'swap': {'disk_bus': None, @@ -2489,7 +2492,6 @@ def test_build_virtual_machine(self, mock_create_folder, extra_specs = vm_util.ExtraSpecs() vm_ref = self._vmops.build_virtual_machine(self._instance, - self._context, image, self._ds, self.network_info, @@ -2497,7 +2499,7 @@ def test_build_virtual_machine(self, mock_create_folder, self._metadata, None) - 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) @@ -2520,7 +2522,7 @@ def test_build_virtual_machine(self, mock_create_folder, 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 @@ -2820,7 +2822,7 @@ def test_fetch_vsphere_image(self): mock.patch.object( self._session, 'invoke_api', side_effect=[datacenter_moref, fake_copy_task]), - mock.patch.object(self._session, '_wait_for_task')) as ( + mock.patch.object(self._session, 'wait_for_task')) as ( invoke_api, wait_for_task): self._vmops._fetch_vsphere_image(self._context, vi, image_ds_loc) expected_calls = [ @@ -2909,7 +2911,7 @@ def test_fetch_image_as_vapp(self, mock_template_vm_name, vi.instance, self._session, 'fake-name', - self._ds.name, + self._ds, vi.dc_info.vmFolder, self._vmops._root_resource_pool, image_id=self._image_id) @@ -2937,7 +2939,7 @@ def test_fetch_image_as_ova(self, mock_template_vm_name, vi.instance, self._session, 'fake-name', - self._ds.name, + self._ds, vi.dc_info.vmFolder, self._vmops._root_resource_pool) self.assertEqual(vi.ii.file_size, 123) @@ -3149,12 +3151,13 @@ def fake_call_method(module, method, *args, **kwargs): with test.nested( mock.patch.object(vm_util, "get_vm_ref", return_value='fake-vm-ref'), - mock.patch.object(self._session, "_call_method", + mock.patch.object(self._session, "call_method", fake_call_method), - mock.patch.object(self._session, "_wait_for_task") + mock.patch.object(self._session, "wait_for_task") ) as (_get_vm_ref, fake_call_method, _wait_for_task): self._vmops.reboot(self._instance, self.network_info, reboot_type) _get_vm_ref.assert_called_once_with(self._session, + self._cluster.obj, self._instance) if reboot_type == "HARD": _wait_for_task.assert_has_calls([ @@ -3242,7 +3245,9 @@ def test_attach_interface(self, mock_get_vm_ref, mock_extra_specs.return_value = extra_specs self._vmops.attach_interface(self._context, self._instance, self._image_meta, self._network_values) - mock_get_vm_ref.assert_called_once_with(self._session, self._instance) + mock_get_vm_ref.assert_called_once_with(self._session, + self._cluster.obj, + self._instance) mock_get_attach_port_index.assert_called_once_with(self._session, 'fake-ref') mock_get_network_attach_config_spec.assert_called_once_with( @@ -3268,11 +3273,13 @@ def test_detach_interface(self, mock_get_vm_ref, _network_api = mock.Mock() self._vmops._network_api = _network_api - with mock.patch.object(self._session, '_call_method', + with mock.patch.object(self._session, 'call_method', return_value='hardware-devices'): self._vmops.detach_interface(self._context, self._instance, self._network_values) - mock_get_vm_ref.assert_called_once_with(self._session, self._instance) + mock_get_vm_ref.assert_called_once_with(self._session, + self._cluster.obj, + self._instance) mock_get_detach_port_index.assert_called_once_with(self._session, 'fake-ref', None) mock_get_network_detach_config_spec.assert_called_once_with( @@ -3291,7 +3298,7 @@ def test_get_mks_console(self, mock_get_vm_ref): ticket.ticket = 'fira' ticket.sslThumbprint = 'aa:bb:cc:dd:ee:ff' ticket.cfgFile = '[ds1] fira/foo.vmx' - with mock.patch.object(self._session, '_call_method', + with mock.patch.object(self._session, 'call_method', return_value=ticket): console = self._vmops.get_mks_console(self._instance) self.assertEqual('esx1', console.host) @@ -3351,7 +3358,9 @@ def test_attach_interface_with_limits(self, mock_get_vm_ref, self._vmops.attach_interface(self._context, self._instance, self._image_meta, self._network_values) - mock_get_vm_ref.assert_called_once_with(self._session, self._instance) + mock_get_vm_ref.assert_called_once_with(self._session, + self._cluster.obj, + self._instance) mock_get_attach_port_index.assert_called_once_with(self._session, 'fake-ref') mock_get_network_attach_config_spec.assert_called_once_with( diff --git a/nova/tests/unit/virt/vmwareapi/test_volumeops.py b/nova/tests/unit/virt/vmwareapi/test_volumeops.py index bdaa6beaaa8..10ac0adbfad 100644 --- a/nova/tests/unit/virt/vmwareapi/test_volumeops.py +++ b/nova/tests/unit/virt/vmwareapi/test_volumeops.py @@ -27,7 +27,7 @@ from nova.tests.unit.virt.vmwareapi import stubs from nova.tests import uuidsentinel from nova.virt.vmwareapi import constants -from nova.virt.vmwareapi import driver +from nova.virt.vmwareapi.session import VMwareAPISession from nova.virt.vmwareapi import vm_util from nova.virt.vmwareapi import volumeops @@ -39,10 +39,11 @@ def setUp(self): super(VMwareVolumeOpsTestCase, self).setUp() vmwareapi_fake.reset() stubs.set_stubs(self) - self._session = driver.VMwareAPISession() + self._session = VMwareAPISession() self._context = context.RequestContext('fake_user', 'fake_project') - - self._volumeops = volumeops.VMwareVolumeOps(self._session) + self._cluster = mock.sentinel.cluster + self._volumeops = volumeops.VMwareVolumeOps(self._session, + self._cluster) self._image_id = image_fake.get_valid_image_id() self._instance_values = { 'name': 'fake_name', @@ -72,8 +73,8 @@ def fake_call_method(module, method, *args, **kwargs): 'fileOperation')) return 'fake_configure_task' with test.nested( - mock.patch.object(self._session, '_wait_for_task'), - mock.patch.object(self._session, '_call_method', + mock.patch.object(self._session, 'wait_for_task'), + mock.patch.object(self._session, 'call_method', fake_call_method) ) as (_wait_for_task, _call_method): fake_device = vmwareapi_fake.DataObject() @@ -81,8 +82,8 @@ def fake_call_method(module, method, *args, **kwargs): fake_device.backing.fileName = 'fake_path' fake_device.key = 'fake_key' fake_vm_ref = vmwareapi_fake.ManagedObjectReference() - self._volumeops.detach_disk_from_vm(fake_vm_ref, self._instance, - fake_device, destroy_disk) + self._volumeops.detach_disk_from_vm(fake_vm_ref, fake_device, + destroy_disk) _wait_for_task.assert_has_calls([ mock.call('fake_configure_task')]) @@ -106,7 +107,7 @@ def test_get_volume_uuid(self): uuid = '1234' opt_val = vmwareapi_fake.OptionValue('volume-%s' % uuid, 'volume-val') fake_call = self._fake_call_get_object_property(uuid, opt_val) - with mock.patch.object(self._session, "_call_method", fake_call): + with mock.patch.object(self._session, "call_method", fake_call): val = self._volumeops._get_volume_uuid(vm_ref, uuid) self.assertEqual('volume-val', val) @@ -115,7 +116,7 @@ def test_get_volume_uuid_not_found(self): 'vm-134') uuid = '1234' fake_call = self._fake_call_get_object_property(uuid, None) - with mock.patch.object(self._session, "_call_method", fake_call): + with mock.patch.object(self._session, "call_method", fake_call): val = self._volumeops._get_volume_uuid(vm_ref, uuid) self.assertIsNone(val) @@ -129,7 +130,8 @@ def test_attach_volume_vmdk_invalid(self): constants.DISK_TYPE_PREALLOCATED, 1024, 'fake-device') with test.nested( - mock.patch.object(vm_util, 'get_vm_ref'), + mock.patch.object(vm_util, 'get_vm_ref', + return_value=mock.sentinel.vm_ref), mock.patch.object(self._volumeops, '_get_volume_ref'), mock.patch.object(vm_util, 'get_vmdk_info', return_value=vmdk_info), @@ -142,12 +144,13 @@ def test_attach_volume_vmdk_invalid(self): instance) get_vm_ref.assert_called_once_with(self._volumeops._session, + self._volumeops._cluster, instance) get_volume_ref.assert_called_once_with( connection_info['data']['volume']) self.assertTrue(get_vmdk_info.called) get_vm_state.assert_called_once_with(self._volumeops._session, - instance) + mock.sentinel.vm_ref) @mock.patch.object(vm_util, 'create_extra_config', return_value=mock.sentinel.extra_config) @@ -177,7 +180,7 @@ def test_get_vmdk_backed_disk_device(self, get_vmdk_backed_disk_device, session = mock.Mock() self._volumeops._session = session hardware_devices = mock.sentinel.hardware_devices - session._call_method.return_value = hardware_devices + session.call_method.return_value = hardware_devices disk_uuid = mock.sentinel.disk_uuid get_volume_uuid.return_value = disk_uuid @@ -191,7 +194,7 @@ def test_get_vmdk_backed_disk_device(self, get_vmdk_backed_disk_device, vm_ref, connection_info['data']) self.assertEqual(device, ret) - session._call_method.assert_called_once_with( + session.call_method.assert_called_once_with( vutil, "get_object_property", vm_ref, "config.hardware.device") get_volume_uuid.assert_called_once_with( vm_ref, connection_info['data']['volume_id']) @@ -205,7 +208,7 @@ def test_get_vmdk_backed_disk_device_with_missing_disk_device( session = mock.Mock() self._volumeops._session = session hardware_devices = mock.sentinel.hardware_devices - session._call_method.return_value = hardware_devices + session.call_method.return_value = hardware_devices disk_uuid = mock.sentinel.disk_uuid get_volume_uuid.return_value = disk_uuid @@ -217,7 +220,7 @@ def test_get_vmdk_backed_disk_device_with_missing_disk_device( self.assertRaises(exception.DiskNotFound, self._volumeops._get_vmdk_backed_disk_device, vm_ref, connection_info['data']) - session._call_method.assert_called_once_with( + session.call_method.assert_called_once_with( vutil, "get_object_property", vm_ref, "config.hardware.device") get_volume_uuid.assert_called_once_with( vm_ref, connection_info['data']['volume_id']) @@ -246,7 +249,7 @@ def test_detach_volume_vmdk(self): return_value='fake-disk-type'), mock.patch.object(self._volumeops, '_consolidate_vmdk_volume'), mock.patch.object(self._volumeops, 'detach_disk_from_vm'), - mock.patch.object(self._volumeops._session, '_call_method', + mock.patch.object(self._volumeops._session, 'call_method', return_value=[virtual_controller]) ) as (get_vm_ref, get_volume_ref, get_vmdk_backed_disk_device, _get_device_disk_type, consolidate_vmdk_volume, @@ -263,6 +266,7 @@ def test_detach_volume_vmdk(self): self._volumeops._detach_volume_vmdk(connection_info, instance) get_vm_ref.assert_called_once_with(self._volumeops._session, + self._volumeops._cluster, instance) get_volume_ref.assert_called_once_with( connection_info['data']['volume']) @@ -271,11 +275,11 @@ def test_detach_volume_vmdk(self): adapter_type = vm_util.CONTROLLER_TO_ADAPTER_TYPE.get( virtual_controller.__class__.__name__) consolidate_vmdk_volume.assert_called_once_with( - instance, mock.sentinel.vm_ref, virtual_disk, + mock.sentinel.vm_ref, virtual_disk, mock.sentinel.volume_ref, adapter_type=adapter_type, disk_type='fake-disk-type') detach_disk_from_vm.assert_called_once_with( - mock.sentinel.vm_ref, instance, virtual_disk, + mock.sentinel.vm_ref, virtual_disk, volume_uuid=connection_info['data']['volume_id']) def test_detach_volume_vmdk_invalid(self): @@ -302,7 +306,7 @@ def test_detach_volume_vmdk_invalid(self): return_value=virtual_disk), mock.patch.object(vm_util, 'get_vm_state', return_value=power_state.RUNNING), - mock.patch.object(self._volumeops._session, '_call_method', + mock.patch.object(self._volumeops._session, 'call_method', return_value=[virtual_controller]) ) as (get_vm_ref, get_volume_ref, get_vmdk_backed_disk_device, get_vm_state, session_call_method): @@ -311,13 +315,14 @@ def test_detach_volume_vmdk_invalid(self): instance) get_vm_ref.assert_called_once_with(self._volumeops._session, + self._volumeops._cluster, instance) get_volume_ref.assert_called_once_with( connection_info['data']['volume']) 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, - instance) + mock.sentinel.vm_ref) @mock.patch.object(vm_util, 'get_vm_ref') @mock.patch.object(vm_util, 'get_rdm_disk') @@ -335,7 +340,7 @@ def test_detach_volume_iscsi(self, detach_disk_from_vm, iscsi_get_target, session = mock.Mock() self._volumeops._session = session hardware_devices = mock.sentinel.hardware_devices - session._call_method.return_value = hardware_devices + session.call_method.return_value = hardware_devices device = mock.sentinel.device get_rdm_disk.return_value = device @@ -344,13 +349,13 @@ def test_detach_volume_iscsi(self, detach_disk_from_vm, iscsi_get_target, instance = mock.sentinel.instance self._volumeops._detach_volume_iscsi(connection_info, instance) - get_vm_ref.assert_called_once_with(session, instance) + get_vm_ref.assert_called_once_with(session, self._cluster, instance) iscsi_get_target.assert_called_once_with(connection_info['data']) - session._call_method.assert_called_once_with( + session.call_method.assert_called_once_with( vutil, "get_object_property", vm_ref, "config.hardware.device") get_rdm_disk.assert_called_once_with(hardware_devices, disk_uuid) detach_disk_from_vm.assert_called_once_with( - vm_ref, instance, device, destroy_disk=True) + vm_ref, device, destroy_disk=True) @mock.patch.object(vm_util, 'get_vm_ref') @mock.patch.object(volumeops.VMwareVolumeOps, '_iscsi_get_target') @@ -367,7 +372,9 @@ def test_detach_volume_iscsi_with_missing_iscsi_target( exception.StorageError, self._volumeops._detach_volume_iscsi, connection_info, instance) - get_vm_ref.assert_called_once_with(self._volumeops._session, instance) + get_vm_ref.assert_called_once_with(self._volumeops._session, + self._volumeops._cluster, + instance) iscsi_get_target.assert_called_once_with(connection_info['data']) @mock.patch.object(vm_util, 'get_vm_ref') @@ -387,7 +394,7 @@ def test_detach_volume_iscsi_with_missing_disk_device( session = mock.Mock() self._volumeops._session = session hardware_devices = mock.sentinel.hardware_devices - session._call_method.return_value = hardware_devices + session.call_method.return_value = hardware_devices get_rdm_disk.return_value = None @@ -396,9 +403,12 @@ def test_detach_volume_iscsi_with_missing_disk_device( self.assertRaises( exception.DiskNotFound, self._volumeops._detach_volume_iscsi, connection_info, instance) - get_vm_ref.assert_called_once_with(session, instance) + + get_vm_ref.assert_called_once_with(self._volumeops._session, + self._volumeops._cluster, + instance) iscsi_get_target.assert_called_once_with(connection_info['data']) - session._call_method.assert_called_once_with( + session.call_method.assert_called_once_with( vutil, "get_object_property", vm_ref, "config.hardware.device") get_rdm_disk.assert_called_once_with(hardware_devices, disk_uuid) self.assertFalse(detach_disk_from_vm.called) @@ -439,18 +449,19 @@ def _test_attach_volume_vmdk(self, adapter_type=None): adapter_type) get_vm_ref.assert_called_once_with(self._volumeops._session, + self._volumeops._cluster, self._instance) get_volume_ref.assert_called_once_with( connection_info['data']['volume']) self.assertTrue(get_vmdk_info.called) attach_disk_to_vm.assert_called_once_with( - vm_ref, self._instance, adapter_type, + vm_ref, adapter_type, constants.DISK_TYPE_PREALLOCATED, vmdk_path='fake-path', volume_uuid=connection_info['data']['volume_id'], backing_uuid=disk_uuid) if adapter_type == constants.ADAPTER_TYPE_IDE: get_vm_state.assert_called_once_with(self._volumeops._session, - self._instance) + vm_ref) else: self.assertFalse(get_vm_state.called) @@ -477,13 +488,14 @@ def _test_attach_volume_iscsi(self, adapter_type=None): adapter_type) get_vm_ref.assert_called_once_with(self._volumeops._session, + self._volumeops._cluster, self._instance) iscsi_discover_target.assert_called_once_with( connection_info['data']) if adapter_type is None: self.assertTrue(get_scsi_adapter_type.called) attach_disk_to_vm.assert_called_once_with(vm_ref, - self._instance, adapter_type, 'rdmp', + adapter_type, 'rdmp', device_name=mock.sentinel.device_name) def test_attach_volume_vmdk(self): @@ -516,7 +528,7 @@ def test_consolidate_vmdk_volume_with_no_relocate( volume_ref = mock.sentinel.volume_ref vm_ref = mock.sentinel.vm_ref - self._volumeops._consolidate_vmdk_volume(self._instance, vm_ref, + self._volumeops._consolidate_vmdk_volume(vm_ref, device, volume_ref) get_vmdk_base_volume_device.assert_called_once_with(volume_ref) @@ -549,23 +561,22 @@ def test_consolidate_vmdk_volume_with_relocate( detach_disk_from_vm.side_effect = [ oslo_vmw_exceptions.FileNotFoundException] - instance = self._instance volume_ref = vmwareapi_fake.ManagedObjectReference() vm_ref = vmwareapi_fake.ManagedObjectReference() adapter_type = constants.ADAPTER_TYPE_BUSLOGIC disk_type = constants.DISK_TYPE_EAGER_ZEROED_THICK - self._volumeops._consolidate_vmdk_volume(instance, vm_ref, device, + self._volumeops._consolidate_vmdk_volume(vm_ref, device, volume_ref, adapter_type, disk_type) get_vmdk_base_volume_device.assert_called_once_with(volume_ref) - relocate_vm.assert_called_once_with(self._session, + relocate_vm.assert_called_once_with(self._volumeops._session, volume_ref, rp, datastore, host) detach_disk_from_vm.assert_called_once_with( - volume_ref, instance, original_device, destroy_disk=True) + volume_ref, original_device, destroy_disk=True) attach_disk_to_vm.assert_called_once_with( - volume_ref, instance, adapter_type, disk_type, + volume_ref, adapter_type, disk_type, vmdk_path=new_file_name) @mock.patch.object(volumeops.VMwareVolumeOps, @@ -596,13 +607,12 @@ def test_consolidate_vmdk_volume_with_missing_vmdk( relocate_vm.side_effect = [ oslo_vmw_exceptions.FileNotFoundException, None] - instance = mock.sentinel.instance volume_ref = vmwareapi_fake.ManagedObjectReference() vm_ref = vmwareapi_fake.ManagedObjectReference() adapter_type = constants.ADAPTER_TYPE_BUSLOGIC disk_type = constants.DISK_TYPE_EAGER_ZEROED_THICK - self._volumeops._consolidate_vmdk_volume(instance, vm_ref, device, + self._volumeops._consolidate_vmdk_volume(vm_ref, device, volume_ref, adapter_type, disk_type) @@ -614,9 +624,9 @@ def test_consolidate_vmdk_volume_with_missing_vmdk( host)] self.assertEqual(relocate_calls, relocate_vm.call_args_list) detach_disk_from_vm.assert_called_once_with( - volume_ref, instance, original_device) + volume_ref, original_device) attach_disk_to_vm.assert_called_once_with( - volume_ref, instance, adapter_type, disk_type, + volume_ref, adapter_type, disk_type, vmdk_path=new_file_name) def test_iscsi_get_host_iqn(self): @@ -628,7 +638,7 @@ def test_iscsi_get_host_iqn(self): with test.nested( mock.patch.object(vm_util, 'get_host_ref_for_vm', return_value=host_mor), - mock.patch.object(self._volumeops._session, '_call_method', + mock.patch.object(self._volumeops._session, 'call_method', return_value=hbas) ) as (fake_get_host_ref_for_vm, fake_call_method): result = self._volumeops._iscsi_get_host_iqn(self._instance) @@ -653,15 +663,14 @@ def test_iscsi_get_host_iqn_instance_not_found(self): side_effect=exception.InstanceNotFound('fake')), mock.patch.object(vm_util, 'get_host_ref', return_value=host_mor), - mock.patch.object(self._volumeops._session, '_call_method', + mock.patch.object(self._volumeops._session, 'call_method', return_value=hbas) ) as (fake_get_host_ref_for_vm, fake_get_host_ref, fake_call_method): - result = self._volumeops._iscsi_get_host_iqn(self._instance) + result = self._volumeops._iscsi_get_host_iqn(None) - fake_get_host_ref_for_vm.assert_called_once_with( - self._volumeops._session, self._instance) + fake_get_host_ref_for_vm.assert_not_called() fake_get_host_ref.assert_called_once_with( self._volumeops._session, self._volumeops._cluster) fake_call_method.assert_called_once_with(vutil, @@ -686,8 +695,9 @@ def test_get_volume_connector(self): connector = self._volumeops.get_volume_connector(self._instance) fake_get_vm_ref.assert_called_once_with(self._volumeops._session, + self._volumeops._cluster, self._instance) - fake_iscsi_get_host_iqn.assert_called_once_with(self._instance) + fake_iscsi_get_host_iqn.assert_called_once_with(vm_ref) self.assertEqual(host_ip, connector['ip']) self.assertEqual(host_ip, connector['host']) diff --git a/nova/virt/vmwareapi/cluster_util.py b/nova/virt/vmwareapi/cluster_util.py index fcf45c2db6b..e805fa53d3c 100644 --- a/nova/virt/vmwareapi/cluster_util.py +++ b/nova/virt/vmwareapi/cluster_util.py @@ -25,7 +25,7 @@ def reconfigure_cluster(session, cluster, config_spec): - reconfig_task = session._call_method(session.vim, + reconfig_task = session.call_method(session.vim, "ReconfigureComputeResource_Task", cluster, spec=config_spec, modify=True) @@ -102,7 +102,7 @@ def fetch_cluster_groups(session, cluster_ref=None, cluster_config=None, raise exception.ValidationError(msg) if cluster_config is None: - cluster_config = session._call_method( + cluster_config = session.call_method( vutil, "get_object_property", cluster_ref, "configurationEx") groups = {} @@ -130,7 +130,7 @@ def fetch_cluster_rules(session, cluster_ref=None, cluster_config=None): raise exception.ValidationError(msg) if cluster_config is None: - cluster_config = session._call_method( + cluster_config = session.call_method( vutil, "get_object_property", cluster_ref, "configurationEx") return {r.name: r for r in getattr(cluster_config, 'rule', [])} @@ -163,7 +163,7 @@ def update_vm_group_membership(session, cluster, vm_group_name, vm_ref, The assumption is that an administrator defines rules with other means on that group. """ - cluster_config = session._call_method( + cluster_config = session.call_method( vutil, "get_object_property", cluster, "configurationEx") client_factory = session.vim.client.factory @@ -286,7 +286,7 @@ def add_rule(session, cluster_ref, rule): def get_rule(session, cluster_ref, rule_name): """Get a DRS rule from the cluster by name""" - cluster_config = session._call_method( + cluster_config = session.call_method( vutil, "get_object_property", cluster_ref, "configurationEx") return _get_rule(cluster_config, rule_name) @@ -305,7 +305,7 @@ def get_rules_by_prefix(session, cluster_ref, rule_prefix): Useful, if you don't know the policy of a server-group the rule was created for. """ - cluster_config = session._call_method( + cluster_config = session.call_method( vutil, "get_object_property", cluster_ref, "configurationEx") return [rule for rule in getattr(cluster_config, 'rules', []) @@ -330,7 +330,7 @@ def update_rule(session, cluster_ref, rule): def is_drs_enabled(session, cluster): """Check if DRS is enabled on a given cluster""" - drs_config = session._call_method(vutil, "get_object_property", cluster, + drs_config = session.call_method(vutil, "get_object_property", cluster, "configuration.drsConfig") if drs_config and hasattr(drs_config, 'enabled'): return drs_config.enabled diff --git a/nova/virt/vmwareapi/driver.py b/nova/virt/vmwareapi/driver.py index d94410009f9..b9a9bf7293f 100644 --- a/nova/virt/vmwareapi/driver.py +++ b/nova/virt/vmwareapi/driver.py @@ -31,10 +31,8 @@ from oslo_utils import excutils from oslo_utils import units from oslo_utils import versionutils as v_utils -from oslo_vmware import api from oslo_vmware import exceptions as vexc from oslo_vmware import pbm -from oslo_vmware import vim from oslo_vmware import vim_util from nova.compute import power_state @@ -54,13 +52,14 @@ from nova.virt.vmwareapi import constants from nova.virt.vmwareapi import ds_util from nova.virt.vmwareapi import error_util -from nova.virt.vmwareapi import host +from nova.virt.vmwareapi.host import VCState +from nova.virt.vmwareapi.session import VMwareAPISession from nova.virt.vmwareapi import special_spawning from nova.virt.vmwareapi import vif as vmwarevif from nova.virt.vmwareapi import vim_util as nova_vim_util from nova.virt.vmwareapi import vm_util -from nova.virt.vmwareapi import vmops -from nova.virt.vmwareapi import volumeops +from nova.virt.vmwareapi.vmops import VMwareVMOps +from nova.virt.vmwareapi.volumeops import VMwareVolumeOps from oslo_serialization import jsonutils LOG = logging.getLogger(__name__) @@ -137,17 +136,17 @@ def __init__(self, virtapi, scheme="https"): % self._cluster_name) self._vcenter_uuid = self._get_vcenter_uuid() self._nodename = self._create_nodename(self._cluster_ref.value) - self._volumeops = volumeops.VMwareVolumeOps(self._session, - self._cluster_ref) - self._vmops = vmops.VMwareVMOps(self._session, - virtapi, - self._volumeops, - self._cluster_ref, - datastore_regex=self._datastore_regex) - self._vc_state = host.VCState(self._session, - self._nodename, - self._cluster_ref, - self._datastore_regex) + self._volumeops = VMwareVolumeOps(self._session, + self._cluster_ref) + self._vmops = VMwareVMOps(self._session, + virtapi, + self._volumeops, + self._cluster_ref, + datastore_regex=self._datastore_regex) + self._vc_state = VCState(self._session, + self._nodename, + self._cluster_ref, + self._datastore_regex) self.capabilities['resource_scheduling'] = \ cluster_util.is_drs_enabled(self._session, self._cluster_ref) # Register the OpenStack extension @@ -213,11 +212,11 @@ def cleanup_host(self, host): def _register_openstack_extension(self): # Register an 'OpenStack' extension in vCenter - os_extension = self._session._call_method(vim_util, 'find_extension', + os_extension = self._session.call_method(vim_util, 'find_extension', constants.EXTENSION_KEY) if os_extension is None: try: - self._session._call_method(vim_util, 'register_extension', + self._session.call_method(vim_util, 'register_extension', constants.EXTENSION_KEY, constants.EXTENSION_TYPE_INSTANCE) LOG.info('Registered extension %s with vCenter', @@ -241,7 +240,8 @@ def resume_state_on_host_boot(self, context, instance, network_info, """resume guest state when a host is booted.""" # Check if the instance is running already and avoid doing # anything if it is. - state = vm_util.get_vm_state(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster_ref, instance) + state = vm_util.get_vm_state(self._session, vm_ref) ignored_states = [power_state.RUNNING, power_state.SUSPENDED] if state in ignored_states: return @@ -326,7 +326,7 @@ def get_console_output(self, context, instance): path = os.path.join(CONF.vmware.serial_log_dir, fname) if not os.path.exists(path): LOG.warning('The console log is missing. Check your VSPC ' - 'configuration', instance=instance) + 'configuration') return b"" read_log_data, remaining = nova.privsep.path.last_bytes( path, MAX_CONSOLE_BYTES) @@ -335,7 +335,7 @@ def get_console_output(self, context, instance): def _get_vcenter_uuid(self): """Retrieves the vCenter UUID.""" - about = self._session._call_method(nova_vim_util, 'get_about_info') + about = self._session.call_method(nova_vim_util, 'get_about_info') return about.instanceUuid def _create_nodename(self, mo_id): @@ -397,12 +397,12 @@ def get_cluster_metrics(self): self.datastore_free_space = 0 self.datastore_total = 0 - cluster_data = self._session._call_method(vim_util, + cluster_data = self._session.call_method(vim_util, 'get_object_properties_dict', cluster_ref, ['host', 'datastore', 'summary']) for datastore in cluster_data['datastore'][0]: - datastore_capacity = self._session._call_method( + datastore_capacity = self._session.call_method( vim_util, "get_object_properties_dict", datastore, @@ -412,7 +412,7 @@ def get_cluster_metrics(self): self.datastore_total += datastore_capacity['summary.capacity'] for cluster_host in cluster_data['host'][0]: - props = self._session._call_method(vim_util, + props = self._session.call_method(vim_util, "get_object_properties_dict", cluster_host, lst_properties) @@ -528,8 +528,7 @@ def detach_volume(self, context, connection_info, instance, mountpoint, """Detach volume storage to VM instance.""" if not self._vmops.is_instance_in_resource_pool(instance): LOG.debug("Not detaching %s, vm is in different cluster", - connection_info["volume_id"], - instance=instance) + connection_info["volume_id"]) return True # NOTE(claudiub): if context parameter is to be used in the future, # the _detach_instance_volumes method will have to be updated as well. @@ -572,15 +571,13 @@ def _detach_instance_volumes(self, instance, block_device_info): disk.get('device_name')) except exception.DiskNotFound: LOG.warning('The volume %s does not exist!', - disk.get('device_name'), - instance=instance) + disk.get('device_name')) except Exception as e: with excutils.save_and_reraise_exception(): LOG.error("Failed to detach %(device_name)s. " "Exception: %(exc)s", {'device_name': disk.get('device_name'), - 'exc': e}, - instance=instance) + 'exc': e}) def destroy(self, context, instance, network_info, block_device_info=None, destroy_disks=True): @@ -604,8 +601,7 @@ def destroy(self, context, instance, network_info, block_device_info=None, except (vexc.ManagedObjectNotFoundException, exception.InstanceNotFound): LOG.warning('Instance does not exists. Proceeding to ' - 'delete instance properties on datastore', - instance=instance) + 'delete instance properties on datastore') self._vmops.destroy(context, instance, destroy_disks) def pause(self, instance): @@ -851,7 +847,7 @@ def _pre_live_migration(self, context, instance, block_device_info, if hasattr(result, 'drsFault'): LOG.error("Placement Error: %s", vim_util.serialize_object( - result.drsFault), instance=instance) + result.drsFault)) if (not hasattr(result, 'recommendations') or not result.recommendations): @@ -906,12 +902,12 @@ def live_migration(self, context, instance, dest, """Live migration of an instance to another host.""" if not migrate_data: LOG.error("live_migration() called without migration_data" - " - cannot continue operations", instance=instance) + " - cannot continue operations") recover_method(context, instance, dest, migrate_data) raise ValueError("Missing migrate_data") if migrate_data.instance_already_migrated: - LOG.info("Recovering migration", instance=instance) + LOG.info("Recovering migration") post_method(context, instance, dest, block_migration, migrate_data) return @@ -933,16 +929,15 @@ def live_migration(self, context, instance, dest, required_volume_attributes) self._set_vif_infos(migrate_data, dest_session) self._vmops.live_migration(instance, migrate_data, volumes) - LOG.info("Migration operation completed", instance=instance) + LOG.info("Migration operation completed") post_method(context, instance, dest, block_migration, migrate_data) except Exception: - LOG.exception("Failed due to an exception", instance=instance) + LOG.exception("Failed due to an exception") with excutils.save_and_reraise_exception(): # We are still in the task-state migrating, so cannot # recover the DRS settings. We rely on the sync to do that LOG.debug("Calling live migration recover_method " - "for instance: %s", instance["name"], - instance=instance) + "for instance: %s", instance["name"]) recover_method(context, instance, dest, migrate_data) def _get_volume_mappings(self, context, instance): @@ -967,7 +962,7 @@ def _get_volume_mappings(self, context, instance): message = ("Could not parse connection_info for volume {}." " Reason: {}" ).format(bdm.volume_id, e) - LOG.warning(message, instance=instance) + LOG.warning(message) # Normalize the datastore reference # As it depends on the caller, if actually need the @@ -1019,9 +1014,9 @@ def rollback_live_migration_at_destination(self, context, instance, migrate_data=None): """Clean up destination node after a failed live migration.""" LOG.info("rollback_live_migration_at_destination %s", - block_device_info, instance=instance) + block_device_info) if not migrate_data.is_same_vcenter: - self._volumeops.delete_shadow_vms(block_device_info, instance) + self._volumeops.delete_shadow_vms(block_device_info) @contextlib.contextmanager def _error_out_instance_on_exception(self, instance, message): @@ -1067,7 +1062,7 @@ def post_live_migration_at_destination(self, context, instance, with self._error_out_instance_on_exception(instance, "fixup shadow vms"): volumes = self._get_volume_mappings(context, instance) - LOG.debug("Fixing shadow vms %s", volumes, instance=instance) + LOG.debug("Fixing shadow vms %s", volumes) self._volumeops.fixup_shadow_vms(instance, volumes) def ensure_filtering_rules_for_instance(self, instance, network_info): @@ -1075,49 +1070,3 @@ def ensure_filtering_rules_for_instance(self, instance, network_info): def unfilter_instance(self, instance, network_info): pass - - -class VMwareAPISession(api.VMwareAPISession): - """Sets up a session with the VC/ESX host and handles all - the calls made to the host. - """ - def __init__(self, host_ip=CONF.vmware.host_ip, - host_port=CONF.vmware.host_port, - username=CONF.vmware.host_username, - password=CONF.vmware.host_password, - retry_count=CONF.vmware.api_retry_count, - scheme="https", - cacert=CONF.vmware.ca_file, - insecure=CONF.vmware.insecure, - pool_size=CONF.vmware.connection_pool_size): - super(VMwareAPISession, self).__init__( - host=host_ip, - port=host_port, - server_username=username, - server_password=password, - api_retry_count=retry_count, - task_poll_interval=CONF.vmware.task_poll_interval, - scheme=scheme, - create_session=True, - cacert=cacert, - insecure=insecure, - pool_size=pool_size) - - def _is_vim_object(self, module): - """Check if the module is a VIM Object instance.""" - return isinstance(module, vim.Vim) - - def _call_method(self, module, method, *args, **kwargs): - """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) - - return self.invoke_api(module, method, *args, **kwargs) - - def _wait_for_task(self, task_ref): - """Return a Deferred that will give the result of the given task. - The task is polled until it completes. - """ - return self.wait_for_task(task_ref) diff --git a/nova/virt/vmwareapi/ds_util.py b/nova/virt/vmwareapi/ds_util.py index a2a4508e3a3..54e1256084f 100644 --- a/nova/virt/vmwareapi/ds_util.py +++ b/nova/virt/vmwareapi/ds_util.py @@ -113,7 +113,7 @@ def get_datastore(session, cluster, datastore_regex=None, storage_policy=None, allowed_ds_types=ALL_SUPPORTED_DS_TYPES): """Get the datastore list and choose the most preferable one.""" - datastore_ret = session._call_method(vutil, + datastore_ret = session.call_method(vutil, "get_object_property", cluster, "datastore") @@ -123,7 +123,7 @@ def get_datastore(session, cluster, datastore_regex=None, raise exception.DatastoreNotFound() datastore_mors = datastore_ret.ManagedObjectReference - result = session._call_method(vim_util, + result = session.call_method(vim_util, "get_properties_for_a_collection_of_objects", "Datastore", datastore_mors, ["summary.type", "summary.name", @@ -173,12 +173,12 @@ def get_available_datastores(session, cluster=None, datastore_regex=None, dc_ref=None): """Get the datastore list and choose the first local storage.""" if cluster: - ds = session._call_method(vutil, + ds = session.call_method(vutil, "get_object_property", cluster, "datastore") elif dc_ref: - ds = session._call_method(vutil, + ds = session.call_method(vutil, "get_object_property", dc_ref, "datastore") @@ -189,7 +189,7 @@ def get_available_datastores(session, cluster=None, datastore_regex=None, return [] data_store_mors = ds.ManagedObjectReference # NOTE(garyk): use utility method to retrieve remote objects - result = session._call_method(vim_util, + result = session.call_method(vim_util, "get_properties_for_a_collection_of_objects", "Datastore", data_store_mors, ["summary.type", "summary.name", "summary.accessible", @@ -207,7 +207,7 @@ def get_allowed_datastore_types(disk_type): def get_datacenter_ref(session, dc_path): - return session._call_method( + return session.call_method( session.vim, "FindByInventoryPath", session.vim.service_content.searchIndex, @@ -217,13 +217,13 @@ def get_datacenter_ref(session, dc_path): def file_delete(session, ds_path, dc_ref): LOG.debug("Deleting the datastore file %s", ds_path) vim = session.vim - file_delete_task = session._call_method( + file_delete_task = session.call_method( vim, "DeleteDatastoreFile_Task", vim.service_content.fileManager, name=str(ds_path), datacenter=dc_ref) - session._wait_for_task(file_delete_task) + session.wait_for_task(file_delete_task) LOG.debug("Deleted the datastore file") @@ -231,7 +231,7 @@ def file_copy(session, src_file, src_dc_ref, dst_file, dst_dc_ref): LOG.debug("Copying the datastore file from %(src)s to %(dst)s", {'src': src_file, 'dst': dst_file}) vim = session.vim - copy_task = session._call_method( + copy_task = session.call_method( vim, "CopyDatastoreFile_Task", vim.service_content.fileManager, @@ -239,7 +239,7 @@ def file_copy(session, src_file, src_dc_ref, dst_file, dst_dc_ref): sourceDatacenter=src_dc_ref, destinationName=dst_file, destinationDatacenter=dst_dc_ref) - session._wait_for_task(copy_task) + session.wait_for_task(copy_task) LOG.debug("Copied the datastore file") @@ -269,7 +269,7 @@ def disk_move(session, dc_ref, src_file, dst_file): """ LOG.debug("Moving virtual disk from %(src)s to %(dst)s.", {'src': src_file, 'dst': dst_file}) - move_task = session._call_method( + move_task = session.call_method( session.vim, "MoveVirtualDisk_Task", session.vim.service_content.virtualDiskManager, @@ -278,7 +278,7 @@ def disk_move(session, dc_ref, src_file, dst_file): destName=str(dst_file), destDatacenter=dc_ref, force=False) - session._wait_for_task(move_task) + session.wait_for_task(move_task) LOG.info("Moved virtual disk from %(src)s to %(dst)s.", {'src': src_file, 'dst': dst_file}) @@ -287,7 +287,7 @@ def disk_copy(session, dc_ref, src_file, dst_file): """Copies the source virtual disk to the destination.""" LOG.debug("Copying virtual disk from %(src)s to %(dst)s.", {'src': src_file, 'dst': dst_file}) - copy_disk_task = session._call_method( + copy_disk_task = session.call_method( session.vim, "CopyVirtualDisk_Task", session.vim.service_content.virtualDiskManager, @@ -296,7 +296,7 @@ def disk_copy(session, dc_ref, src_file, dst_file): destName=str(dst_file), destDatacenter=dc_ref, force=False) - session._wait_for_task(copy_disk_task) + session.wait_for_task(copy_disk_task) LOG.info("Copied virtual disk from %(src)s to %(dst)s.", {'src': src_file, 'dst': dst_file}) @@ -304,13 +304,13 @@ def disk_copy(session, dc_ref, src_file, dst_file): def disk_delete(session, dc_ref, file_path): """Deletes a virtual disk.""" LOG.debug("Deleting virtual disk %s", file_path) - delete_disk_task = session._call_method( + delete_disk_task = session.call_method( session.vim, "DeleteVirtualDisk_Task", session.vim.service_content.virtualDiskManager, name=str(file_path), datacenter=dc_ref) - session._wait_for_task(delete_disk_task) + session.wait_for_task(delete_disk_task) LOG.info("Deleted virtual disk %s.", file_path) @@ -341,7 +341,7 @@ def file_move(session, dc_ref, src_file, dst_file): LOG.debug("Moving file from %(src)s to %(dst)s.", {'src': src_file, 'dst': dst_file}) vim = session.vim - move_task = session._call_method( + move_task = session.call_method( vim, "MoveDatastoreFile_Task", vim.service_content.fileManager, @@ -349,7 +349,7 @@ def file_move(session, dc_ref, src_file, dst_file): sourceDatacenter=dc_ref, destinationName=str(dst_file), destinationDatacenter=dc_ref) - session._wait_for_task(move_task) + session.wait_for_task(move_task) LOG.debug("File moved") @@ -369,13 +369,13 @@ def file_exists(session, ds_browser, ds_path, file_name): """Check if the file exists on the datastore.""" client_factory = session.vim.client.factory search_spec = search_datastore_spec(client_factory, file_name) - search_task = session._call_method(session.vim, + search_task = session.call_method(session.vim, "SearchDatastore_Task", ds_browser, datastorePath=str(ds_path), searchSpec=search_spec) try: - task_info = session._wait_for_task(search_task) + task_info = session.wait_for_task(search_task) except vexc.FileNotFoundException: return False @@ -388,12 +388,12 @@ def file_size(session, ds_browser, ds_path, file_name): """Returns the size of the specified file.""" client_factory = session.vim.client.factory search_spec = search_datastore_spec(client_factory, file_name) - search_task = session._call_method(session.vim, + search_task = session.call_method(session.vim, "SearchDatastore_Task", ds_browser, datastorePath=str(ds_path), searchSpec=search_spec) - task_info = session._wait_for_task(search_task) + task_info = session.wait_for_task(search_task) if hasattr(task_info.result, 'file'): return task_info.result.file[0].fileSize @@ -404,7 +404,7 @@ def mkdir(session, ds_path, dc_ref): DataStore. """ LOG.debug("Creating directory with path %s", ds_path) - session._call_method(session.vim, "MakeDirectory", + session.call_method(session.vim, "MakeDirectory", session.vim.service_content.fileManager, name=str(ds_path), datacenter=dc_ref, createParentDirectories=True) @@ -416,13 +416,13 @@ def get_sub_folders(session, ds_browser, ds_path): If the path does not exist then an empty set is returned. """ - search_task = session._call_method( + search_task = session.call_method( session.vim, "SearchDatastore_Task", ds_browser, datastorePath=str(ds_path)) try: - task_info = session._wait_for_task(search_task) + task_info = session.wait_for_task(search_task) except vexc.FileNotFoundException: return set() # populate the folder entries @@ -489,7 +489,7 @@ def get_dc_info(session, ds_ref): """Get the datacenter name and the reference.""" dc_info = _DS_DC_MAPPING.get(ds_ref.value) if not dc_info: - dcs = session._call_method(vim_util, "get_objects", + dcs = session.call_method(vim_util, "get_objects", "Datacenter", ["name", "datastore", "vmFolder"]) _update_datacenter_cache_from_objects(session, dcs) dc_info = _DS_DC_MAPPING.get(ds_ref.value) @@ -508,7 +508,7 @@ def get_connected_hosts(session, datastore): :return: List of managed object references of all connected hosts """ - host_mounts = session._call_method(vutil, 'get_object_property', + host_mounts = session.call_method(vutil, 'get_object_property', datastore, 'host') if not hasattr(host_mounts, 'DatastoreHostMount'): return [] diff --git a/nova/virt/vmwareapi/host.py b/nova/virt/vmwareapi/host.py index ce9928cb855..ca90bed5270 100644 --- a/nova/virt/vmwareapi/host.py +++ b/nova/virt/vmwareapi/host.py @@ -72,7 +72,7 @@ def __init__(self, session, host_name, cluster, datastore_regex): except exception.ComputeHostNotFound: # this can happend on newly-added hosts self._auto_service_disabled = False - about_info = self._session._call_method(vim_util, "get_about_info") + about_info = self._session.call_method(vim_util, "get_about_info") self._hypervisor_type = about_info.name self._hypervisor_version = versionutils.convert_version_to_int( str(about_info.version)) diff --git a/nova/virt/vmwareapi/images.py b/nova/virt/vmwareapi/images.py index dac18c3c5fe..147ad03a0ee 100644 --- a/nova/virt/vmwareapi/images.py +++ b/nova/virt/vmwareapi/images.py @@ -227,8 +227,7 @@ def image_transfer(read_handle, write_handle): def upload_iso_to_datastore(iso_path, instance, **kwargs): - LOG.debug("Uploading iso %s to datastore", iso_path, - instance=instance) + LOG.debug("Uploading iso %s to datastore", iso_path) with open(iso_path, 'r') as iso_file: write_file_handle = rw_handles.FileWriteHandle( kwargs.get("host"), @@ -248,8 +247,7 @@ def upload_iso_to_datastore(iso_path, instance, **kwargs): data = iso_file.read(block_size) write_file_handle.close() - LOG.debug("Uploaded iso %s to datastore", iso_path, - instance=instance) + LOG.debug("Uploaded iso %s to datastore", iso_path) def fetch_image(context, instance, host, port, dc_name, ds_name, file_path, @@ -259,8 +257,7 @@ def fetch_image(context, instance, host, port, dc_name, ds_name, file_path, LOG.debug("Downloading image file data %(image_ref)s to the " "data store %(data_store_name)s", {'image_ref': image_ref, - 'data_store_name': ds_name}, - instance=instance) + 'data_store_name': ds_name}) metadata = IMAGE_API.get(context, image_ref) file_size = int(metadata['size']) @@ -274,8 +271,7 @@ def fetch_image(context, instance, host, port, dc_name, ds_name, file_path, "%(data_store_name)s", {'image_ref': image_ref, 'upload_name': 'n/a' if file_path is None else file_path, - 'data_store_name': 'n/a' if ds_name is None else ds_name}, - instance=instance) + 'data_store_name': 'n/a' if ds_name is None else ds_name}) def _build_shadow_vm_config_spec(session, name, size_kb, disk_type, ds_name): @@ -344,37 +340,37 @@ def _build_import_spec_for_import_vapp(session, vm_name, datastore_name): def fetch_image_stream_optimized(context, instance, session, vm_name, - ds_name, vm_folder_ref, res_pool_ref, + datastore, vm_folder_ref, res_pool_ref, image_id=None): """Fetch image from Glance to ESX datastore.""" image_ref = image_id if image_id else instance.image_ref LOG.debug("Downloading image file data %(image_ref)s to the ESX " "as VM named '%(vm_name)s'", - {'image_ref': image_ref, 'vm_name': vm_name}, - instance=instance) + {'image_ref': image_ref, 'vm_name': vm_name}) metadata = IMAGE_API.get(context, image_ref) file_size = int(metadata['size']) vm_import_spec = _build_import_spec_for_import_vapp( - session, vm_name, ds_name) + session, vm_name, datastore.name) read_iter = IMAGE_API.download(context, image_ref) read_handle = rw_handles.ImageReadHandle(read_iter) imported_vm_ref = _import_image(session, read_handle, vm_import_spec, vm_name, vm_folder_ref, res_pool_ref, + datastore.ref, file_size) LOG.info("Downloaded image file data %(image_ref)s", - {'image_ref': instance.image_ref}, instance=instance) + {'image_ref': instance.image_ref}) vmdk = vm_util.get_vmdk_info(session, imported_vm_ref, vm_name) - vm_util.mark_vm_as_template(session, instance, imported_vm_ref) + vm_util.mark_vm_as_template(session, imported_vm_ref) return vmdk.capacity_in_bytes, vmdk.path def _import_image(session, read_handle, vm_import_spec, vm_name, vm_folder_ref, - res_pool_ref, file_size): + res_pool_ref, datastore_ref, file_size): # retry in order to handle conflicts in case of parallel execution # (multiple agents) or previously failed import of the same image max_attempts = 3 @@ -395,21 +391,26 @@ def _import_image(session, read_handle, vm_import_spec, vm_name, vm_folder_ref, except vexc.DuplicateName: LOG.debug("Handling name duplication during import of VM %s", vm_name) - vm_ref = vm_util.get_vm_ref_from_name(session, vm_name) + vm_ref = vm_util.get_vm_ref_from_name(session, vm_name, + base_obj=vm_folder_ref, path="childEntity") + if not vm_ref: + # This only happens, if the owner of the image + # has been changed, while we where importing... rather unlikely + vm_ref = vm_util.get_vm_ref_from_name(session, vm_name, + base_obj=datastore_ref, path="vm") + waited_for_ongoing_import = _wait_for_import_task(session, vm_ref) if waited_for_ongoing_import: imported_vm_ref = vm_ref break - else: - try: - destroy_task = session._call_method(session.vim, - "Destroy_Task", - vm_ref) - session._wait_for_task(destroy_task) - vm_util.vm_ref_cache_delete(vm_name) - except vexc.ManagedObjectNotFoundException: - # another agent destroyed the VM in the meantime - pass + try: + destroy_task = session.call_method(session.vim, + "Destroy_Task", + vm_ref) + session.wait_for_task(destroy_task) + except vexc.ManagedObjectNotFoundException: + # another agent destroyed the VM in the meantime + pass if not imported_vm_ref: raise vexc.VMwareDriverException("Could not import image" @@ -430,13 +431,13 @@ def _wait_for_import_task(session, vm_ref): waited = False try: - task_collector = session._call_method(session.vim, + task_collector = session.call_method(session.vim, "CreateCollectorForTasks", session.vim.service_content.taskManager, filter=task_filter_spec) while True: - page_tasks = session._call_method(session.vim, + page_tasks = session.call_method(session.vim, "ReadNextTasks", task_collector, maxCount=10) @@ -446,7 +447,7 @@ def _wait_for_import_task(session, vm_ref): for ti in page_tasks: if ti.descriptionId == "ResourcePool.ImportVAppLRO": try: - session._wait_for_task(ti.task) + session.wait_for_task(ti.task) waited = True except vexc.VimException as e: LOG.debug("Awaiting previous import on VM %s " @@ -457,7 +458,7 @@ def _wait_for_import_task(session, vm_ref): return waited finally: if task_collector: - session._call_method(session.vim, + session.call_method(session.vim, "DestroyCollector", task_collector) @@ -479,7 +480,7 @@ def get_vmdk_name_from_ovf(xmlstr): return vmdk_name -def fetch_image_ova(context, instance, session, vm_name, ds_name, +def fetch_image_ova(context, instance, session, vm_name, datastore, vm_folder_ref, res_pool_ref): """Download the OVA image from the glance image server to the Nova compute node. @@ -487,14 +488,13 @@ def fetch_image_ova(context, instance, session, vm_name, ds_name, image_ref = instance.image_ref LOG.debug("Downloading OVA image file %(image_ref)s to the ESX " "as VM named '%(vm_name)s'", - {'image_ref': image_ref, 'vm_name': vm_name}, - instance=instance) + {'image_ref': image_ref, 'vm_name': vm_name}) metadata = IMAGE_API.get(context, image_ref) file_size = int(metadata['size']) vm_import_spec = _build_import_spec_for_import_vapp( - session, vm_name, ds_name) + session, vm_name, datastore.name) read_iter = IMAGE_API.download(context, image_ref) read_handle = rw_handles.ImageReadHandle(read_iter) @@ -512,14 +512,14 @@ def fetch_image_ova(context, instance, session, vm_name, ds_name, imported_vm_ref = _import_image(session, extracted, vm_import_spec, vm_name, vm_folder_ref, res_pool_ref, - file_size) + datastore.ref, file_size) LOG.info("Downloaded OVA image file %(image_ref)s", - {'image_ref': instance.image_ref}, instance=instance) + {'image_ref': instance.image_ref}) vmdk = vm_util.get_vmdk_info(session, imported_vm_ref, vm_name) - vm_util.mark_vm_as_template(session, instance, imported_vm_ref) + vm_util.mark_vm_as_template(session, imported_vm_ref) return vmdk.capacity_in_bytes, vmdk.path raise exception.ImageUnacceptable( reason=_("Extracting vmdk from OVA failed."), @@ -529,7 +529,7 @@ def fetch_image_ova(context, instance, session, vm_name, ds_name, def upload_image_stream_optimized(context, image_id, instance, session, vm, vmdk_size): """Upload the snapshotted vm disk file to Glance image server.""" - LOG.debug("Uploading image %s", image_id, instance=instance) + LOG.debug("Uploading image %s", image_id) metadata = IMAGE_API.get(context, image_id) read_handle = rw_handles.VmdkReadHandle(session, @@ -560,5 +560,4 @@ def upload_image_stream_optimized(context, image_id, instance, session, updater.stop() read_handle.close() - LOG.debug("Uploaded image %s to the Glance image server", image_id, - instance=instance) + LOG.debug("Uploaded image %s to the Glance image server", image_id) diff --git a/nova/virt/vmwareapi/network_util.py b/nova/virt/vmwareapi/network_util.py index fb80d022200..b78fc318538 100644 --- a/nova/virt/vmwareapi/network_util.py +++ b/nova/virt/vmwareapi/network_util.py @@ -74,7 +74,7 @@ def _get_network_obj(session, network_objects, network_name): for network in network_refs: # Get network properties if network._type == 'DistributedVirtualPortgroup': - props = session._call_method(vutil, + props = session.call_method(vutil, "get_object_property", network, "config") @@ -84,14 +84,14 @@ def _get_network_obj(session, network_objects, network_name): if network_name in net_name: network_obj['type'] = 'DistributedVirtualPortgroup' network_obj['dvpg'] = props.key - dvs_props = session._call_method(vutil, + dvs_props = session.call_method(vutil, "get_object_property", props.distributedVirtualSwitch, "uuid") network_obj['dvsw'] = dvs_props return network_obj else: - props = session._call_method(vutil, + props = session.call_method(vutil, "get_object_property", network, "summary.name") @@ -105,7 +105,7 @@ def get_network_with_the_name(session, network_name="vmnet0", cluster=None): """Gets reference to the network whose name is passed as the argument. """ - vm_networks = session._call_method(vim_util, + vm_networks = session.call_method(vim_util, 'get_object_properties', None, cluster, 'ClusterComputeResource', ['network']) @@ -124,7 +124,7 @@ def get_vswitch_for_vlan_interface(session, vlan_interface, cluster=None): """ # Get the list of vSwitches on the Host System host_mor = vm_util.get_host_ref(session, cluster) - vswitches_ret = session._call_method(vutil, + vswitches_ret = session.call_method(vutil, "get_object_property", host_mor, "config.network.vswitch") @@ -148,7 +148,7 @@ def get_vswitch_for_vlan_interface(session, vlan_interface, cluster=None): def check_if_vlan_interface_exists(session, vlan_interface, cluster=None): """Checks if the vlan_interface exists on the esx host.""" host_mor = vm_util.get_host_ref(session, cluster) - physical_nics_ret = session._call_method(vutil, + physical_nics_ret = session.call_method(vutil, "get_object_property", host_mor, "config.network.pnic") @@ -165,7 +165,7 @@ def check_if_vlan_interface_exists(session, vlan_interface, cluster=None): def get_vlanid_and_vswitch_for_portgroup(session, pg_name, cluster=None): """Get the vlan id and vswitch associated with the port group.""" host_mor = vm_util.get_host_ref(session, cluster) - port_grps_on_host_ret = session._call_method(vutil, + port_grps_on_host_ret = session.call_method(vutil, "get_object_property", host_mor, "config.network.portgroup") @@ -193,14 +193,14 @@ def create_port_group(session, pg_name, vswitch_name, vlan_id=0, cluster=None): pg_name, vlan_id) host_mor = vm_util.get_host_ref(session, cluster) - network_system_mor = session._call_method(vutil, + network_system_mor = session.call_method(vutil, "get_object_property", host_mor, "configManager.networkSystem") LOG.debug("Creating Port Group with name %s on " "the ESX host", pg_name) try: - session._call_method(session.vim, + session.call_method(session.vim, "AddPortGroup", network_system_mor, portgrp=add_prt_grp_spec) except vexc.AlreadyExistsException: diff --git a/nova/virt/vmwareapi/session.py b/nova/virt/vmwareapi/session.py new file mode 100644 index 00000000000..5e159c4ab69 --- /dev/null +++ b/nova/virt/vmwareapi/session.py @@ -0,0 +1,108 @@ +# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. +# Copyright (c) 2012 VMware, Inc. +# Copyright (c) 2011 Citrix Systems, Inc. +# Copyright 2011 OpenStack Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import abc +import six +import sys + +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 + + +@six.add_metaclass(abc.ABCMeta) +class StableMoRefProxy(object): + """Abstract Basis 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 + + @abc.abstractmethod + def fetch_moref(self): + """Updates the moref field or raises + same exception the initial search would have + """ + + def __getattr__(self, name): + return getattr(self.moref, name) + + +class VMwareAPISession(api.VMwareAPISession): + """Sets up a session with the VC/ESX host and handles all + the calls made to the host. + """ + def __init__(self, host_ip=CONF.vmware.host_ip, + host_port=CONF.vmware.host_port, + username=CONF.vmware.host_username, + password=CONF.vmware.host_password, + retry_count=CONF.vmware.api_retry_count, + scheme="https", + cacert=CONF.vmware.ca_file, + insecure=CONF.vmware.insecure, + pool_size=CONF.vmware.connection_pool_size): + super(VMwareAPISession, self).__init__( + host=host_ip, + port=host_port, + server_username=username, + server_password=password, + api_retry_count=retry_count, + task_poll_interval=CONF.vmware.task_poll_interval, + scheme=scheme, + create_session=True, + cacert=cacert, + insecure=insecure, + pool_size=pool_size) + + @staticmethod + def _is_vim_object(module): + """Check if the module is a VIM Object instance.""" + return isinstance(module, vim.Vim) + + def call_method(self, module, method, *args, **kwargs): + """Calls a method within the module specified with + args provided. + """ + 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: + obj = monfe.details.get("obj") + any_change = False + for arg in args: + if (isinstance(arg, StableMoRefProxy) + and obj == get_moref_value(arg.moref)): + arg.fetch_moref() + any_change = True + + if not any_change: + six.reraise(*sys.exc_info()) + + return self.call_method(module, method, *args, **kwargs) diff --git a/nova/virt/vmwareapi/special_spawning.py b/nova/virt/vmwareapi/special_spawning.py index e0bd02fc50c..4befa92c49c 100644 --- a/nova/virt/vmwareapi/special_spawning.py +++ b/nova/virt/vmwareapi/special_spawning.py @@ -75,7 +75,7 @@ def __init__(self, driver): def _get_group(self, cluster_config=None): """Return the hostgroup or None if not found.""" if cluster_config is None: - cluster_config = self._session._call_method( + cluster_config = self._session.call_method( vutil, "get_object_property", self._cluster, "configurationEx") if not cluster_config: # that should never happen. we should not procede with whatever @@ -100,7 +100,7 @@ def _get_group(self, cluster_config=None): def _get_hosts_in_cluster(self, cluster_ref): """Return a list of HostSystem morefs belonging to the cluster""" - result = self._session._call_method( + result = self._session.call_method( vim_util, 'get_inner_objects', cluster_ref, 'host', 'HostSystem') with vutil.WithRetrieval(self._session.vim, result) as objects: return [obj.obj for obj in objects] @@ -108,7 +108,7 @@ def _get_hosts_in_cluster(self, cluster_ref): def _get_vms_on_host(self, host_ref): """Return a list of VMs uuids with their memory size and state""" vm_data = [] - vm_ret = self._session._call_method(vutil, + vm_ret = self._session.call_method(vutil, "get_object_property", host_ref, "vm") @@ -117,7 +117,7 @@ def _get_vms_on_host(self, host_ref): return vm_data vm_mors = vm_ret.ManagedObjectReference - result = self._session._call_method(vutil, + result = self._session.call_method(vutil, "get_properties_for_a_collection_of_objects", "VirtualMachine", vm_mors, ["config.instanceUuid", "runtime.powerState", @@ -183,7 +183,7 @@ def free_host(self, context): hostgroup. If that's already the case, return whether there are running VMs left on the host, i.e. the process is finished. """ - cluster_config = self._session._call_method( + cluster_config = self._session.call_method( vutil, "get_object_property", self._cluster, "configurationEx") # check if DRS is enabled, so freeing up can work @@ -252,7 +252,7 @@ def free_host(self, context): return FREE_HOST_STATE_ERROR # filter hosts which are in a wrong state - result = self._session._call_method(vim_util, + result = self._session.call_method(vim_util, "get_properties_for_a_collection_of_objects", "HostSystem", [host_objs[h] for h in vms_per_host], @@ -319,7 +319,7 @@ def free_host(self, context): 'host.') return FREE_HOST_STATE_ERROR - runtime_summary = self._session._call_method( + runtime_summary = self._session.call_method( vutil, "get_object_property", host_ref, 'summary.runtime') if (runtime_summary.inMaintenanceMode is True or runtime_summary.connectionState != "connected"): diff --git a/nova/virt/vmwareapi/vim_util.py b/nova/virt/vmwareapi/vim_util.py index d835f25f916..0d83bc141ac 100644 --- a/nova/virt/vmwareapi/vim_util.py +++ b/nova/virt/vmwareapi/vim_util.py @@ -162,7 +162,7 @@ def get_about_info(vim): def get_entity_name(session, entity): - return session._call_method(vutil, 'get_object_property', + return session.call_method(vutil, 'get_object_property', entity, 'name') diff --git a/nova/virt/vmwareapi/vm_util.py b/nova/virt/vmwareapi/vm_util.py index 0a0a758f0a4..d59bb0ebf28 100644 --- a/nova/virt/vmwareapi/vm_util.py +++ b/nova/virt/vmwareapi/vm_util.py @@ -40,6 +40,7 @@ from nova.i18n import _ from nova.network import model as network_model from nova.virt.vmwareapi import constants +from nova.virt.vmwareapi.session import StableMoRefProxy from nova.virt.vmwareapi import vim_util LOG = logging.getLogger(__name__) @@ -140,11 +141,11 @@ def __iter__(self): self._page_items = None if self.reverse_page_order: - self.session._call_method(self.session.vim, + self.session.call_method(self.session.vim, "ResetCollector", self.history_collector) else: - self.session._call_method(self.session.vim, + self.session.call_method(self.session.vim, "RewindCollector", self.history_collector) @@ -164,7 +165,7 @@ def _load_page(self): self._load_latest_page() if not self._page_items: - self._page_items = self.session._call_method( + self._page_items = self.session.call_method( self.session.vim, self.read_page_method, self.history_collector, maxCount=self.max_page_size) @@ -182,7 +183,7 @@ def _load_latest_page(self): def destroy_collector(self): if self.history_collector: - self.session._call_method(self.session.vim, + self.session.call_method(self.session.vim, "DestroyCollector", self.history_collector) @@ -190,7 +191,7 @@ def destroy_collector(self): class TaskHistoryCollectorItems(HistoryCollectorItems): def __init__(self, session, task_filter_spec, reverse_page_order=False, max_page_size=10): - task_collector = session._call_method( + task_collector = session.call_method( session.vim, "CreateCollectorForTasks", session.vim.service_content.taskManager, @@ -212,7 +213,7 @@ def __del__(self): class EventHistoryCollectorItems(HistoryCollectorItems): def __init__(self, session, event_filter_spec, reverse_page_order=False, max_page_size=10): - event_collector = session._call_method( + event_collector = session.call_method( session.vim, "CreateCollectorForEvents", session.vim.service_content.eventManager, @@ -253,99 +254,16 @@ def vm_refs_cache_reset(): _VM_REFS_CACHE = {} -def vm_ref_cache_delete(id): - _VM_REFS_CACHE.pop(id, None) +def vm_ref_cache_delete(id_): + _VM_REFS_CACHE.pop(id_, None) -def vm_ref_cache_update(id, vm_ref): - _VM_REFS_CACHE[id] = vm_ref +def vm_ref_cache_update(id_, vm_ref): + _VM_REFS_CACHE[id_] = vm_ref -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): - @six.wraps(func) - def wrapper(session, instance): - id_ = instance.uuid - return _vm_ref_cache(id_, func, session, instance) - return wrapper - - -def vm_ref_cache_from_name(func): - @six.wraps(func) - def wrapper(session, name): - id_ = name - return _vm_ref_cache(id_, func, session, name) - return wrapper - - -def vm_ref_cache_heal_from_instance(func): - """Decorator for a function working with a cached ManagedObject reference - for an instance - - Invalidates the cache in case of matching ManagedObjectNotFoundException - Most functions rely on the reference to be stable over the life-time of an - instance, and do not handle this exception, they expect InstanceNotFound - - By invalidating the cache, we solve two issues: - 1. We have a chance to recover from such a rare change - 2. If not, we now raise InstanceNotFound, which is actually handled - - The main motivator though is the live-vm migration across vcenters, - which can make the VM "disappear" - - An operator also can de-register and re-register a vm, or need to recover - the vsphere service, resulting in changed mo-refs, - requiring a restart to clear the cache. - - WARNING: Care needs to be taken in applying the decorator: - It requires, that the function in question is idempotent (up to the point - where the vm_ref is being used) - """ - @six.wraps(func) - def wrapper(session, instance, *args, **kwargs): - try: - return func(session, instance, *args, **kwargs) - except vexc.ManagedObjectNotFoundException as e: - with excutils.save_and_reraise_exception() as ctx: - id_ = instance.uuid - vm_ref = vm_ref_cache_get(id_) - # if there was nothing in the cache, there's nothing to heal - if vm_ref is None: - return # noqa - - # we are missing details about the issue, so raise it - if not e.details: - return # noqa - - obj = e.details.get("obj") - # A different moref may be invalid, nothing we can do about it - if obj != vm_ref.value: - return # noqa - - vm_ref_cache_delete(id_) - ctx.reraise = False - - # In case the reference has been passed - kw_vm_ref = kwargs.get("vm_ref", None) - if kw_vm_ref and kw_vm_ref.value == vm_ref.value: - kwargs.pop("vm_ref") - - # Unlikely, but we might run into the same situation again. - LOG.info("Trying to recover possible vm-ref incoherence") - return wrapper(session, instance, *args, **kwargs) - - return wrapper +def vm_ref_cache_get(id_): + return _VM_REFS_CACHE.get(id_) # the config key which stores the VNC port @@ -913,7 +831,7 @@ def _get_device_disk_type(device): def get_hardware_devices(session, vm_ref): - hardware_devices = session._call_method(vutil, + hardware_devices = session.call_method(vutil, "get_object_property", vm_ref, "config.hardware.device") @@ -1227,9 +1145,9 @@ def relocate_vm(session, vm_ref, res_pool=None, datastore=None, host=None, client_factory = session.vim.client.factory rel_spec = spec or relocate_vm_spec(client_factory, res_pool, datastore, host, disk_move_type) - relocate_task = session._call_method(session.vim, "RelocateVM_Task", + relocate_task = session.call_method(session.vim, "RelocateVM_Task", vm_ref, spec=rel_spec) - session._wait_for_task(relocate_task) + session.wait_for_task(relocate_task) def get_machine_id_change_spec(client_factory, machine_id_str): @@ -1305,7 +1223,7 @@ def _get_allocated_vnc_ports(session): # TODO(rgerganov): bug #1256944 # The VNC port should be unique per host, not per vCenter vnc_ports = set() - result = session._call_method(vim_util, "get_objects", + result = session.call_method(vim_util, "get_objects", "VirtualMachine", [VNC_CONFIG_KEY]) with vutil.WithRetrieval(session.vim, result) as objects: for obj in objects: @@ -1336,23 +1254,27 @@ def _get_object_from_results(session, results, value, func): return func(objects, value) -def _get_vm_ref_from_name(session, vm_name): +def _get_vms_relative(session, base_obj, path, property_list): + return session.call_method(vim_util, "get_inner_objects", + base_obj, path, + "VirtualMachine", property_list) + + +def get_vm_ref_from_name(session, vm_name, base_obj=None, path=None): """Get reference to the VM with the name specified. This method reads all of the names of the VM's that are running on the backend, then it filters locally the matching vm_name. It is far more optimal to use _get_vm_ref_from_vm_uuid. """ - vms = session._call_method(vim_util, "get_objects", - "VirtualMachine", ["name"]) - return _get_object_from_results(session, vms, vm_name, - _get_object_for_value) + property_list = ["name"] + if not path or not base_obj: + raise ValueError("Method needs base_obj and path") + vms = _get_vms_relative(session, base_obj, path, property_list) -@vm_ref_cache_from_name -def get_vm_ref_from_name(session, vm_name): - return (_get_vm_ref_from_vm_uuid(session, vm_name) or - _get_vm_ref_from_name(session, vm_name)) + return _get_object_from_results(session, vms, vm_name, + _get_object_for_value) def _get_vm_ref_from_vm_uuid(session, instance_uuid): @@ -1363,7 +1285,7 @@ def _get_vm_ref_from_vm_uuid(session, instance_uuid): instance_uuid, more specifically all VM's on the backend that have 'config_spec.instanceUuid' set to 'instance_uuid'. """ - vm_refs = session._call_method( + vm_refs = session.call_method( session.vim, "FindAllByUuid", session.vim.service_content.searchIndex, @@ -1375,33 +1297,47 @@ def _get_vm_ref_from_vm_uuid(session, instance_uuid): def find_by_inventory_path(session, inv_path): - return session._call_method( + return session.call_method( session.vim, "FindByInventoryPath", session.vim.service_content.searchIndex, inventoryPath=inv_path) -def _get_vm_ref_from_extraconfig(session, instance_uuid): +def _get_vm_ref_from_extraconfig(session, cluster, instance_uuid): """Get reference to the VM with the uuid specified.""" - vms = session._call_method(vim_util, "get_objects", - "VirtualMachine", ['config.extraConfig["nvp.vm-uuid"]']) + + vms = _get_vms_relative(session, cluster, "vm", + ['config.extraConfig["nvp.vm-uuid"]']) + return _get_object_from_results(session, vms, instance_uuid, _get_object_for_optionvalue) -@vm_ref_cache_from_instance -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 +class StableVmRefUuid(StableMoRefProxy): + def __init__(self, session, cluster, uuid, moref=None): + super(StableVmRefUuid, self).__init__(moref) + self._session = session + self._cluster = cluster + self._uuid = uuid + if not moref: + self.fetch_moref() + + def fetch_moref(self): + vm_value_cache_delete(self._uuid) + self.moref = search_vm_ref_by_identifier(self._session, + self._cluster, self._uuid) + if not self.moref: + raise exception.InstanceNotFound(instance_id=self._uuid) + vm_ref_cache_update(self._uuid, self) + +def get_vm_ref(session, cluster, instance): + """Get reference to the VM through uuid.""" + return StableVmRefUuid(session, cluster, instance.uuid) -def search_vm_ref_by_identifier(session, identifier): + +def search_vm_ref_by_identifier(session, cluster, identifier): """Searches VM reference using the identifier. This method is primarily meant to separate out part of the logic for @@ -1410,32 +1346,27 @@ 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, cluster, identifier)) return vm_ref -@vm_ref_cache_heal_from_instance -def get_host_ref_for_vm(session, instance): +def get_host_ref_for_vm(session, vm_ref): """Get a MoRef to the ESXi host currently running an instance.""" - vm_ref = get_vm_ref(session, instance) - return session._call_method(vutil, "get_object_property", - vm_ref, "runtime.host") + return session.call_method(vutil, "get_object_property", + vm_ref, "runtime.host") -def get_host_name_for_vm(session, instance): +def get_host_name_for_vm(session, vm_ref): """Get the hostname of the ESXi host currently running an instance.""" - host_ref = get_host_ref_for_vm(session, instance) - return session._call_method(vutil, "get_object_property", - host_ref, "name") + host_ref = get_host_ref_for_vm(session, vm_ref) + return session.call_method(vutil, "get_object_property", + host_ref, "name") -@vm_ref_cache_heal_from_instance -def get_vm_state(session, instance): - vm_ref = get_vm_ref(session, instance) - vm_state = session._call_method(vutil, "get_object_property", +def get_vm_state(session, vm_ref): + vm_state = session.call_method(vutil, "get_object_property", vm_ref, "runtime.powerState") return constants.POWER_STATES[vm_state] @@ -1533,7 +1464,7 @@ def get_stats_from_cluster(session, cluster): get_hosts_and_reservations_for_cluster(session, cluster) if host_mors: - result = session._call_method(vim_util, + result = session.call_method(vim_util, "get_properties_for_a_collection_of_objects", "HostSystem", host_mors, ["summary.hardware", "summary.runtime", @@ -1600,7 +1531,7 @@ def get_hosts_and_reservations_for_cluster(session, cluster): props = ["host", "resourcePool", admission_policy_key] if CONF.vmware.hostgroup_reservations_json_file: props.append("configurationEx") - prop_dict = session._call_method(vutil, + prop_dict = session.call_method(vutil, "get_object_properties_dict", cluster, props) @@ -1627,13 +1558,13 @@ def get_hosts_and_reservations_for_cluster(session, cluster): def get_host_ref(session, cluster=None): """Get reference to a host within the cluster specified.""" if cluster is None: - results = session._call_method(vim_util, "get_objects", + results = session.call_method(vim_util, "get_objects", "HostSystem") - session._call_method(vutil, 'cancel_retrieval', + session.call_method(vutil, 'cancel_retrieval', results) host_mor = results.objects[0].obj else: - host_ret = session._call_method(vutil, "get_object_property", + host_ret = session.call_method(vutil, "get_object_property", cluster, "host") if not host_ret or not host_ret.ManagedObjectReference: msg = _('No host available on cluster') @@ -1682,7 +1613,7 @@ def get_vmdk_volume_disk(hardware_devices, path=None): def get_res_pool_ref(session, cluster): """Get the resource pool.""" # Get the root resource pool of the cluster - res_pool_ref = session._call_method(vutil, + res_pool_ref = session.call_method(vutil, "get_object_property", cluster, "resourcePool") @@ -1692,7 +1623,7 @@ def get_res_pool_ref(session, cluster): def get_all_cluster_mors(session): """Get all the clusters in the vCenter.""" try: - results = session._call_method(vim_util, "get_objects", + results = session.call_method(vim_util, "get_objects", "ClusterComputeResource", ["name"]) with vutil.WithRetrieval(session.vim, results) as objects: return list(objects) @@ -1724,15 +1655,15 @@ def get_vmdk_adapter_type(adapter_type): return vmdk_adapter_type -def create_vm(session, instance, vm_folder, config_spec, res_pool_ref): +def create_vm(session, vm_folder, config_spec, res_pool_ref): """Create VM on ESX host.""" - LOG.debug("Creating VM on the ESX host", instance=instance) - vm_create_task = session._call_method( + LOG.debug("Creating VM on the ESX host") + vm_create_task = session.call_method( session.vim, "CreateVM_Task", vm_folder, config=config_spec, pool=res_pool_ref) try: - task_info = session._wait_for_task(vm_create_task) + task_info = session.wait_for_task(vm_create_task) except vexc.VMwareDriverException: # An invalid guestId will result in an error with no specific fault # type and the generic error 'A specified parameter was not correct'. @@ -1748,46 +1679,37 @@ def create_vm(session, instance, vm_folder, config_spec, res_pool_ref): '\'%(ostype)s\'. An invalid os type may be ' 'one cause of this instance creation failure', {'ostype': config_spec.guestId}) - LOG.debug("Created VM on the ESX host", instance=instance) + LOG.debug("Created VM on the ESX host") return task_info.result -@vm_ref_cache_heal_from_instance -def _destroy_vm(session, instance, vm_ref=None): - if not vm_ref: - vm_ref = get_vm_ref(session, instance) - LOG.debug("Destroying the VM", instance=instance) - destroy_task = session._call_method(session.vim, "Destroy_Task", - vm_ref) - session._wait_for_task(destroy_task) - LOG.info("Destroyed the VM", instance=instance) - - -def destroy_vm(session, instance, vm_ref=None): +def destroy_vm(session, vm_ref): """Destroy a VM instance. Assumes VM is powered off.""" try: - return _destroy_vm(session, instance, vm_ref=vm_ref) + LOG.debug("Destroying the VM") + destroy_task = session.call_method(session.vim, "Destroy_Task", + vm_ref) + session.wait_for_task(destroy_task) + LOG.info("Destroyed the VM") except vexc.VimFaultException as e: with excutils.save_and_reraise_exception() as ctx: - LOG.exception(_('Destroy VM failed'), instance=instance) + LOG.exception(_('Destroy VM failed')) # we need the `InvalidArgument` fault to bubble out of this # function so it can be acted upon on higher levels if 'InvalidArgument' not in e.fault_list: ctx.reraise = False except Exception: - LOG.exception(_('Destroy VM failed'), instance=instance) + LOG.exception(_('Destroy VM failed')) -def mark_vm_as_template(session, instance, vm_ref=None): +def mark_vm_as_template(session, vm_ref): """Mark a VM instance as template. Assumes VM is powered off.""" try: - if not vm_ref: - vm_ref = get_vm_ref(session, instance) - LOG.debug("Marking the VM as template", instance=instance) - session._call_method(session.vim, "MarkAsTemplate", vm_ref) - LOG.info("Marked the VM as template", instance=instance) + LOG.debug("Marking the VM as template") + session.call_method(session.vim, "MarkAsTemplate", vm_ref) + LOG.info("Marked the VM as template") except Exception: - LOG.exception(_('Mark VM as template failed'), instance=instance) + LOG.exception(_('Mark VM as template failed')) def create_virtual_disk(session, dc_ref, adapter_type, disk_type, @@ -1808,7 +1730,7 @@ def create_virtual_disk(session, dc_ref, adapter_type, disk_type, adapter_type, disk_type) - vmdk_create_task = session._call_method( + vmdk_create_task = session.call_method( session.vim, "CreateVirtualDisk_Task", session.vim.service_content.virtualDiskManager, @@ -1816,7 +1738,7 @@ def create_virtual_disk(session, dc_ref, adapter_type, disk_type, datacenter=dc_ref, spec=vmdk_create_spec) - session._wait_for_task(vmdk_create_task) + session.wait_for_task(vmdk_create_task) LOG.debug("Created Virtual Disk of size %(vmdk_file_size_in_kb)s" " KB and type %(disk_type)s", {"vmdk_file_size_in_kb": size_in_kb, @@ -1839,46 +1761,41 @@ def copy_virtual_disk(session, dc_ref, source, dest): LOG.debug("Copying Virtual Disk %(source)s to %(dest)s", {'source': source, 'dest': dest}) vim = session.vim - vmdk_copy_task = session._call_method( + vmdk_copy_task = session.call_method( vim, "CopyVirtualDisk_Task", vim.service_content.virtualDiskManager, sourceName=source, sourceDatacenter=dc_ref, destName=dest) - session._wait_for_task(vmdk_copy_task) + session.wait_for_task(vmdk_copy_task) LOG.debug("Copied Virtual Disk %(source)s to %(dest)s", {'source': source, 'dest': dest}) def reconfigure_vm(session, vm_ref, config_spec): """Reconfigure a VM according to the config spec.""" - reconfig_task = session._call_method(session.vim, + reconfig_task = session.call_method(session.vim, "ReconfigVM_Task", vm_ref, spec=config_spec) - session._wait_for_task(reconfig_task) + session.wait_for_task(reconfig_task) -@vm_ref_cache_heal_from_instance -def power_on_instance(session, instance, vm_ref=None): +def power_on_instance(session, vm_ref): """Power on the specified instance.""" - - if vm_ref is None: - vm_ref = get_vm_ref(session, instance) - - LOG.debug("Powering on the VM", instance=instance) + LOG.debug("Powering on the VM") try: - poweron_task = session._call_method( + poweron_task = session.call_method( session.vim, "PowerOnVM_Task", vm_ref) - session._wait_for_task(poweron_task) - LOG.debug("Powered on the VM", instance=instance) + session.wait_for_task(poweron_task) + LOG.debug("Powered on the VM") except vexc.InvalidPowerStateException: - LOG.debug("VM already powered on", instance=instance) + LOG.debug("VM already powered on") def _get_vm_port_indices(session, vm_ref): - extra_config = session._call_method(vutil, + extra_config = session.call_method(vutil, 'get_object_property', vm_ref, 'config.extraConfig') @@ -1908,7 +1825,7 @@ def get_attach_port_index(session, vm_ref): def get_vm_detach_port_index(session, vm_ref, iface_id): - extra_config = session._call_method(vutil, + extra_config = session.call_method(vutil, 'get_object_property', vm_ref, 'config.extraConfig') @@ -1920,21 +1837,17 @@ def get_vm_detach_port_index(session, vm_ref, iface_id): return int(option.key.split('.')[2]) -@vm_ref_cache_heal_from_instance -def power_off_instance(session, instance, vm_ref=None): +def power_off_instance(session, vm_ref): """Power off the specified instance.""" - if vm_ref is None: - vm_ref = get_vm_ref(session, instance) - - LOG.debug("Powering off the VM", instance=instance) + LOG.debug("Powering off the VM") try: - poweroff_task = session._call_method(session.vim, + poweroff_task = session.call_method(session.vim, "PowerOffVM_Task", vm_ref) - session._wait_for_task(poweroff_task) - LOG.debug("Powered off the VM", instance=instance) + session.wait_for_task(poweroff_task) + LOG.debug("Powered off the VM") except vexc.InvalidPowerStateException: - LOG.debug("VM already powered off", instance=instance) + LOG.debug("VM already powered off") def find_rescue_device(hardware_devices, instance): @@ -2013,7 +1926,7 @@ def create_folder(session, parent_folder_ref, name): LOG.debug("Creating folder: %(name)s. Parent ref: %(parent)s.", {'name': name, 'parent': parent_folder_ref.value}) try: - folder = session._call_method(session.vim, "CreateFolder", + folder = session.call_method(session.vim, "CreateFolder", parent_folder_ref, name=name) LOG.info("Created folder: %(name)s in parent %(parent)s.", {'name': name, 'parent': parent_folder_ref.value}) @@ -2042,9 +1955,9 @@ def _get_vm_name(display_name, id_): 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, + rename_task = session.call_method(session.vim, "Rename_Task", vm_ref, newName=vm_name) - session._wait_for_task(rename_task) + session.wait_for_task(rename_task) def create_service_locator_name_password(client_factory, username, password): diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py index bacecd0e478..6d30f506375 100644 --- a/nova/virt/vmwareapi/vmops.py +++ b/nova/virt/vmwareapi/vmops.py @@ -49,7 +49,7 @@ from nova.console import type as ctype from nova import context as nova_context from nova import exception -from nova.i18n import _, _LI +from nova.i18n import _ from nova import network from nova import objects from nova.objects import fields @@ -176,11 +176,10 @@ def _get_base_folder(self): base_folder = CONF.image_cache_subdirectory_name return base_folder - def _extend_virtual_disk(self, instance, requested_size, name, dc_ref): + def _extend_virtual_disk(self, requested_size, name, dc_ref): service_content = self._session.vim.service_content - LOG.debug("Extending root virtual disk to %s", requested_size, - instance=instance) - vmdk_extend_task = self._session._call_method( + LOG.debug("Extending root virtual disk to %s", requested_size) + vmdk_extend_task = self._session.call_method( self._session.vim, "ExtendVirtualDisk_Task", service_content.virtualDiskManager, @@ -189,18 +188,18 @@ def _extend_virtual_disk(self, instance, requested_size, name, dc_ref): newCapacityKb=requested_size, eagerZero=False) try: - self._session._wait_for_task(vmdk_extend_task) + self._session.wait_for_task(vmdk_extend_task) except Exception as e: with excutils.save_and_reraise_exception(): LOG.error('Extending virtual disk failed with error: %s', - e, instance=instance) + e) # Clean up files created during the extend operation files = [name.replace(".vmdk", "-flat.vmdk"), name] for file in files: ds_path = ds_obj.DatastorePath.parse(file) self._delete_datastore_file(ds_path, dc_ref) - LOG.debug("Extended root virtual disk", instance=instance) + LOG.debug("Extended root virtual disk") def _delete_datastore_file(self, datastore_path, dc_ref): try: @@ -214,8 +213,7 @@ def _delete_datastore_file(self, datastore_path, dc_ref): {'ds': datastore_path}, exc_info=True) - def _extend_if_required(self, dc_info, image_info, instance, - root_vmdk_path): + def _extend_if_required(self, dc_info, instance, root_vmdk_path): root_vmdk = ds_obj.DatastorePath.parse(root_vmdk_path.replace( ".vmdk", "-flat.vmdk")) @@ -230,7 +228,7 @@ def _extend_if_required(self, dc_info, image_info, instance, root_vmdk.basename) if instance.flavor.root_gb * units.Gi > actual_file_size: size_in_kb = instance.flavor.root_gb * units.Mi - self._extend_virtual_disk(instance, size_in_kb, + self._extend_virtual_disk(size_in_kb, root_vmdk_path, dc_info.ref) def _configure_config_drive(self, context, instance, vm_ref, dc_info, @@ -249,10 +247,8 @@ def _configure_config_drive(self, context, instance, vm_ref, dc_info, instance.uuid, cookies) uploaded_iso_path = datastore.build_path(uploaded_iso_path) - self._attach_cdrom_to_vm( - vm_ref, instance, - datastore.ref, - str(uploaded_iso_path)) + self._attach_cdrom_to_vm(vm_ref, datastore.ref, + str(uploaded_iso_path)) def _get_instance_metadata(self, context, instance, flavor=None): if not flavor: @@ -312,7 +308,7 @@ def _get_vm_config_spec(self, instance, image_info, utils.is_neutron(), image_info.vif_model, network_info) - LOG.debug('Instance VIF info %s', vif_infos, instance=instance) + LOG.debug('Instance VIF info %s', vif_infos) if extra_specs.storage_policy: profile_spec = vm_util.get_storage_profile_spec( @@ -333,7 +329,7 @@ def _get_vm_config_spec(self, instance, image_info, return config_spec - def build_virtual_machine(self, instance, context, image_info, datastore, + def build_virtual_machine(self, instance, image_info, datastore, network_info, extra_specs, metadata, vm_folder, vm_name=None): config_spec = self._get_vm_config_spec(instance, @@ -345,7 +341,7 @@ def build_virtual_machine(self, instance, context, image_info, datastore, vm_name=vm_name) # Create the VM - vm_ref = vm_util.create_vm(self._session, instance, vm_folder, + vm_ref = vm_util.create_vm(self._session, vm_folder, config_spec, self._root_resource_pool) return vm_ref @@ -420,7 +416,7 @@ def _get_storage_policy(self, flavor): def _get_esx_host_and_cookies(self, datastore, dc_path, file_path): hosts = datastore.get_connected_hosts(self._session) host = ds_obj.Datastore.choose_host(hosts) - host_name = self._session._call_method(vutil, 'get_object_property', + host_name = self._session.call_method(vutil, 'get_object_property', host, 'name') url = ds_obj.DatastoreURL('https', host_name, file_path, dc_path, datastore.name) @@ -441,8 +437,7 @@ def _fetch_vsphere_image(self, context, vi, image_ds_loc): "%(datastore_name)s", {'image_id': vi.ii.image_id, 'file_path': image_ds_loc, - 'datastore_name': vi.datastore.name}, - instance=vi.instance) + 'datastore_name': vi.datastore.name}) location_url = ds_obj.DatastoreURL.urlparse(location) datacenter_path = location_url.datacenter_path @@ -460,8 +455,7 @@ def _fetch_vsphere_image(self, context, vi, image_ds_loc): "%(datastore_name)s", {'image_id': vi.ii.image_id, 'file_path': image_ds_loc, - 'datastore_name': vi.datastore.name}, - instance=vi.instance) + 'datastore_name': vi.datastore.name}) def _fetch_image_as_file(self, context, vi, image_ds_loc): """Download image as an individual file to host via HTTP PUT.""" @@ -472,8 +466,7 @@ def _fetch_image_as_file(self, context, vi, image_ds_loc): "%(datastore_name)s", {'image_id': vi.ii.image_id, 'file_path': image_ds_loc, - 'datastore_name': vi.datastore.name}, - instance=vi.instance) + 'datastore_name': vi.datastore.name}) # try to get esx cookie to upload try: @@ -481,8 +474,7 @@ def _fetch_image_as_file(self, context, vi, image_ds_loc): host, cookies = self._get_esx_host_and_cookies(vi.datastore, dc_path, image_ds_loc.rel_path) except Exception as e: - LOG.warning("Get esx cookies failed: %s", e, - instance=vi.instance) + LOG.warning("Get esx cookies failed: %s", e) dc_path = vutil.get_inventory_path(session.vim, vi.dc_info.ref) host = self._session._host @@ -513,15 +505,14 @@ def _fetch_image_as_vapp(self, context, vi, image_ds_loc): "%(datastore_name)s as vApp", {'image_id': vi.ii.image_id, 'vm_name': vm_name, - 'datastore_name': vi.datastore.name}, - instance=vi.instance) + 'datastore_name': vi.datastore.name}) image_size, src_folder_ds_path = images.fetch_image_stream_optimized( context, vi.instance, self._session, vm_name, - vi.datastore.name, + vi.datastore, self._get_project_folder(vi.dc_info, project_id=vi.ii.owner, type_='Images'), @@ -543,7 +534,7 @@ def _fetch_image_as_ova(self, context, vi, image_ds_loc): vi.instance, self._session, vm_name, - vi.datastore.name, + vi.datastore, self._get_project_folder(vi.dc_info, project_id=vi.ii.owner, type_='Images'), @@ -644,7 +635,7 @@ def _cache_vm_image(self, vi, tmp_image_ds_loc): except vexc.FileAlreadyExistsException: pass - def _unregister_template_vm(self, templ_vm_ref, instance=None): + def _unregister_template_vm(self, templ_vm_ref): """Unregister a template VM We need to Unregister instead of Destroy, if the datastore path does @@ -652,18 +643,17 @@ def _unregister_template_vm(self, templ_vm_ref, instance=None): """ try: LOG.debug("Unregistering the template VM %s", - templ_vm_ref.value, - instance=instance) - self._session._call_method(self._session.vim, + templ_vm_ref.value) + self._session.call_method(self._session.vim, "UnregisterVM", templ_vm_ref) - LOG.debug("Unregistered the template VM", instance=instance) + LOG.debug("Unregistered the template VM") except Exception as excep: LOG.warning("got this exception while un-registering a ", "template VM: %s", - excep, instance=instance) + excep) def _cache_vm_image_from_template(self, vi, templ_vm_ref): - LOG.debug("Caching VDMK from template VM", instance=vi.instance) + LOG.debug("Caching VDMK from template VM") vm_name = self._get_image_template_vm_name(vi.ii.image_id, vi.datastore.name) vmdk = vm_util.get_vmdk_info(self._session, templ_vm_ref, vm_name) @@ -675,11 +665,11 @@ def _cache_vm_image_from_template(self, vi, templ_vm_ref): self._cache_vm_image(vi, vmdk.path) except vexc.FileNotFoundException: LOG.warning("Could not find files for template VM %s", - templ_vm_ref.value, instance=vi.instance) - self._unregister_template_vm(templ_vm_ref, vi.instance) + templ_vm_ref.value) + self._unregister_template_vm(templ_vm_ref) return False - LOG.debug("Cached VDMK from template VM", instance=vi.instance) + LOG.debug("Cached VDMK from template VM") return True def _cache_stream_optimized_image(self, vi, tmp_image_ds_loc): @@ -774,7 +764,7 @@ def _fetch_image_from_other_datastores(self, vi): clone_spec = vm_util.clone_vm_spec(client_factory, rel_spec, template=True) - templ_vm_clone_task = self._session._call_method( + templ_vm_clone_task = self._session.call_method( self._session.vim, "CloneVM_Task", other_templ_vm_ref, @@ -786,10 +776,10 @@ def _fetch_image_from_other_datastores(self, vi): spec=clone_spec) try: task_info = \ - self._session._wait_for_task(templ_vm_clone_task) + self._session.wait_for_task(templ_vm_clone_task) except vexc.FileNotFoundException: LOG.warning("Could not find files for template VM %s", - other_templ_vm_ref.value, instance=vi.instance) + other_templ_vm_ref.value) continue except vexc.VimFaultException as e: if 'VirtualHardwareVersionNotSupported' in e.fault_list: @@ -805,7 +795,7 @@ def _fetch_image_from_other_datastores(self, vi): def _fetch_image_if_missing(self, context, vi): image_prepare, image_fetch, image_cache = self._get_image_callbacks(vi) - LOG.debug("Processing image %s", vi.ii.image_id, instance=vi.instance) + LOG.debug("Processing image %s", vi.ii.image_id) with lockutils.lock(str(vi.cache_image_path), lock_file_prefix='nova-vmware-fetch_image'): @@ -824,7 +814,7 @@ def _fetch_image_if_missing(self, context, vi): if not image_available: # no matter if image_as_template is set, we can use the # template_vm in any case - LOG.debug("Trying to find template VM", instance=vi.instance) + LOG.debug("Trying to find template VM") templ_vm_ref = self._find_image_template_vm(vi) image_available = (templ_vm_ref is not None) if image_available and not CONF.vmware.image_as_template: @@ -834,8 +824,7 @@ def _fetch_image_if_missing(self, context, vi): if (not image_available and CONF.vmware.fetch_image_from_other_datastores): # fetching from another DS is still faster - LOG.debug("Trying to find template VM on other DS", - instance=vi.instance) + LOG.debug("Trying to find template VM on other DS") templ_vm_ref = self._fetch_image_from_other_datastores(vi) image_available = (templ_vm_ref is not None) if image_available and not CONF.vmware.image_as_template: @@ -844,15 +833,13 @@ def _fetch_image_if_missing(self, context, vi): if not image_available: # we didn't find it anywhere. upload it - LOG.debug("Preparing fetch location", instance=vi.instance) + LOG.debug("Preparing fetch location") tmp_dir_loc, tmp_image_ds_loc = image_prepare(vi) - LOG.debug("Fetch image to %s", tmp_image_ds_loc, - instance=vi.instance) + LOG.debug("Fetch image to %s", tmp_image_ds_loc) image_fetch(context, vi, tmp_image_ds_loc) - LOG.debug("Caching image", instance=vi.instance) + LOG.debug("Caching image") image_cache(vi, tmp_image_ds_loc) - LOG.debug("Cleaning up location %s", str(tmp_dir_loc), - instance=vi.instance) + LOG.debug("Cleaning up location %s", str(tmp_dir_loc)) if tmp_dir_loc: self._delete_datastore_file(str(tmp_dir_loc), vi.dc_info.ref) @@ -862,7 +849,7 @@ def _fetch_image_if_missing(self, context, vi): if vi.ii.disk_type == constants.DISK_TYPE_SPARSE: self._update_image_size(vi) - def _create_and_attach_thin_disk(self, instance, vm_ref, dc_info, size, + def _create_and_attach_thin_disk(self, vm_ref, dc_info, size, adapter_type, path): disk_type = constants.DISK_TYPE_THIN vm_util.create_virtual_disk( @@ -873,7 +860,7 @@ def _create_and_attach_thin_disk(self, instance, vm_ref, dc_info, size, size) self._volumeops.attach_disk_to_vm( - vm_ref, instance, + vm_ref, adapter_type, disk_type, path, size, False) @@ -888,7 +875,7 @@ def _create_ephemeral(self, bdi, instance, vm_ref, dc_info, filename = vm_util.get_ephemeral_name(idx) path = str(ds_obj.DatastorePath(datastore.name, folder, filename)) - self._create_and_attach_thin_disk(instance, vm_ref, dc_info, + self._create_and_attach_thin_disk(vm_ref, dc_info, size, at, path) # There may be block devices defined but no ephemerals. In this case @@ -898,7 +885,7 @@ def _create_ephemeral(self, bdi, instance, vm_ref, dc_info, filename = vm_util.get_ephemeral_name(0) path = str(ds_obj.DatastorePath(datastore.name, folder, filename)) - self._create_and_attach_thin_disk(instance, vm_ref, dc_info, size, + self._create_and_attach_thin_disk(vm_ref, dc_info, size, adapter_type, path) def _create_swap(self, bdi, instance, vm_ref, dc_info, datastore, @@ -910,7 +897,7 @@ def _create_swap(self, bdi, instance, vm_ref, dc_info, datastore, swap = driver.block_device_info_get_swap(bdi) if driver.swap_is_usable(swap): size = swap['swap_size'] * units.Ki - self._create_and_attach_thin_disk(instance, vm_ref, dc_info, + self._create_and_attach_thin_disk(vm_ref, dc_info, size, adapter_type, path) else: # driver.block_device_info_get_swap returns @@ -922,7 +909,7 @@ def _create_swap(self, bdi, instance, vm_ref, dc_info, datastore, size = instance.flavor.swap * units.Ki if not swap and size > 0: - self._create_and_attach_thin_disk(instance, vm_ref, dc_info, size, + self._create_and_attach_thin_disk(vm_ref, dc_info, size, adapter_type, path) def _update_vnic_index(self, context, instance, network_info): @@ -950,13 +937,13 @@ def _create_image_template(self, context, vi, extra_specs): max_attempts = 2 for i in six.moves.range(max_attempts): + templ_vm_ref = None try: vm_folder = self._get_project_folder(vi.dc_info, project_id=vi.ii.owner, type_='Images') templ_vm_ref = self.build_virtual_machine(vi.instance, - context, vi.ii, vi.datastore, None, @@ -977,9 +964,7 @@ def _create_image_template(self, context, vi, extra_specs): else: self._use_disk_image_as_full_clone(templ_vm_ref, vi) - vm_util.mark_vm_as_template(self._session, - vi.instance, - templ_vm_ref) + vm_util.mark_vm_as_template(self._session, templ_vm_ref) return templ_vm_ref except Exception as create_templ_exc: @@ -988,16 +973,17 @@ def _create_image_template(self, context, vi, extra_specs): reraise=is_last_attempt): LOG.error('Creating VM template for image failed' ' with error: %s', - create_templ_exc, instance=vi.instance) + create_templ_exc) try: - vm_util.destroy_vm(self._session, vi.instance) + if templ_vm_ref: + vm_util.destroy_vm(self._session, templ_vm_ref) except Exception as destroy_templ_exc: LOG.error('Cleaning up VM template for' ' image failed with error: %s', - destroy_templ_exc, instance=vi.instance) + destroy_templ_exc) def _build_template_vm_inventory_path(self, vi): - vm_folder_name = self._session._call_method(vutil, + vm_folder_name = self._session.call_method(vutil, "get_object_property", vi.dc_info.vmFolder, "name") @@ -1067,7 +1053,7 @@ def _create_instance_from_image_template(self, context, res_pool=self._root_resource_pool, disk_move_type="moveAllDiskBackingsAndDisallowSharing") clone_spec = vm_util.clone_vm_spec(client_factory, rel_spec) - vm_clone_task = self._session._call_method( + vm_clone_task = self._session.call_method( self._session.vim, "CloneVM_Task", templ_vm_ref, @@ -1076,14 +1062,13 @@ def _create_instance_from_image_template(self, context, type_='Instances'), name=vi.instance.uuid, spec=clone_spec) - task_info = self._session._wait_for_task(vm_clone_task) + task_info = self._session.wait_for_task(vm_clone_task) vm_ref = task_info.result root_vmdk_info = vm_util.get_vmdk_info(self._session, vm_ref, uuid=vi.instance.uuid) self._extend_if_required(vi.dc_info, - vi.ii, vi.instance, root_vmdk_info.path) @@ -1160,7 +1145,7 @@ def update_admin_vm_group_membership(self, instance, remove=False): vm_group_name = self._get_admin_group_name_for_instance(instance) if not vm_group_name: return - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) cluster_util.update_vm_group_membership(self._session, self._cluster, vm_group_name, vm_ref, remove=remove) @@ -1198,7 +1183,6 @@ def spawn(self, context, instance, image_meta, injected_files, vm_folder = self._get_project_folder( vi.dc_info, project_id=instance.project_id, type_='Instances') vm_ref = self.build_virtual_machine(instance, - context, image_info, vi.datastore, network_info, @@ -1208,7 +1192,8 @@ def spawn(self, context, instance, image_meta, injected_files, # Cache the vm_ref. This saves a remote call to the VC. This uses the # instance uuid. - vm_util.vm_ref_cache_update(instance.uuid, vm_ref) + vm_util.vm_ref_cache_update(instance.uuid, vm_util.StableVmRefUuid( + self._session, self._cluster, instance.uuid, vm_ref)) # Update all DRS related rules self.update_cluster_placement(context, instance) @@ -1248,7 +1233,7 @@ def spawn(self, context, instance, image_meta, injected_files, msg = "Block device information present: %s" % block_device_info # NOTE(mriedem): block_device_info can contain an auth_password # so we have to scrub the message before logging it. - LOG.debug(strutils.mask_password(msg), instance=instance) + LOG.debug(strutils.mask_password(msg)) # Before attempting to attach any volume, make sure the # block_device_mapping (i.e. disk_bus) is valid @@ -1288,7 +1273,7 @@ def spawn(self, context, instance, image_meta, injected_files, # Make sure we don't automatically move around "big" VMs self.disable_drs_if_needed(instance) - vm_util.power_on_instance(self._session, instance, vm_ref=vm_ref) + vm_util.power_on_instance(self._session, vm_ref) self._clean_up_after_special_spawning(context, instance.memory_mb, instance.flavor) @@ -1297,9 +1282,8 @@ def disable_drs_if_needed(self, instance): if utils.is_big_vm(int(instance.memory_mb), instance.flavor) or \ utils.is_large_vm(int(instance.memory_mb), instance.flavor): behavior = constants.DRS_BEHAVIOR_PARTIALLY_AUTOMATED - LOG.debug("Adding DRS override '%s' for big VM.", behavior, - instance=instance) - vm_ref = vm_util.get_vm_ref(self._session, instance) + LOG.debug("Adding DRS override '%s' for big VM.", behavior) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) cluster_util.update_cluster_drs_vm_override(self._session, self._cluster, vm_ref, @@ -1357,7 +1341,7 @@ def _create_config_drive(self, context, instance, injected_files, CONF.config_drive_format) raise exception.InstancePowerOnFailure(reason=reason) - LOG.info('Using config drive for instance', instance=instance) + LOG.info('Using config drive for instance') extra_md = {} if admin_password: extra_md['admin_pass'] = admin_password @@ -1386,10 +1370,9 @@ def _create_config_drive(self, context, instance, injected_files, except Exception as e: with excutils.save_and_reraise_exception(): LOG.error('Creating config drive failed with error: %s', - e, instance=instance) + e) - def _attach_cdrom_to_vm(self, vm_ref, instance, - datastore, file_path): + def _attach_cdrom_to_vm(self, vm_ref, datastore, file_path): """Attach cdrom to VM by reconfiguration.""" client_factory = self._session.vim.client.factory devices = vm_util.get_hardware_devices(self._session, vm_ref) @@ -1405,23 +1388,23 @@ def _attach_cdrom_to_vm(self, vm_ref, instance, cdrom_attach_config_spec.deviceChange.append(controller_spec) LOG.debug("Reconfiguring VM instance to attach cdrom %s", - file_path, instance=instance) + file_path) vm_util.reconfigure_vm(self._session, vm_ref, cdrom_attach_config_spec) LOG.debug("Reconfigured VM instance to attach cdrom %s", - file_path, instance=instance) + file_path) def _create_vm_snapshot(self, instance, vm_ref, image_id=None): - LOG.debug("Creating Snapshot of the VM instance", instance=instance) - snapshot_task = self._session._call_method( + LOG.debug("Creating Snapshot of the VM instance") + snapshot_task = self._session.call_method( self._session.vim, "CreateSnapshot_Task", vm_ref, name="%s-snapshot" % (image_id or instance.uuid), description="Taking Snapshot of the VM", memory=False, quiesce=True) - self._session._wait_for_task(snapshot_task) - LOG.debug("Created Snapshot of the VM instance", instance=instance) - task_info = self._session._call_method(vutil, + self._session.wait_for_task(snapshot_task) + LOG.debug("Created Snapshot of the VM instance") + task_info = self._session.call_method(vutil, "get_object_property", snapshot_task, "info") @@ -1429,45 +1412,14 @@ def _create_vm_snapshot(self, instance, vm_ref, image_id=None): return snapshot @retry_if_task_in_progress - def _delete_vm_snapshot(self, instance, vm_ref, snapshot): - LOG.debug("Deleting Snapshot of the VM instance", instance=instance) - delete_snapshot_task = self._session._call_method( + def _delete_vm_snapshot(self, snapshot): + LOG.debug("Deleting Snapshot of the VM instance") + delete_snapshot_task = self._session.call_method( self._session.vim, "RemoveSnapshot_Task", snapshot, removeChildren=False, consolidate=True) - self._session._wait_for_task(delete_snapshot_task) - LOG.debug("Deleted Snapshot of the VM instance", instance=instance) - - def _create_linked_clone_from_snapshot(self, instance, - vm_ref, snapshot_ref, dc_info): - """Create linked clone VM to be deployed to same ds as source VM - """ - client_factory = self._session.vim.client.factory - rel_spec = vm_util.relocate_vm_spec( - client_factory, - datastore=None, - host=None, - disk_move_type="createNewChildDiskBacking") - clone_spec = vm_util.clone_vm_spec(client_factory, rel_spec, - power_on=False, snapshot=snapshot_ref, template=True) - vm_name = "%s_%s" % (constants.SNAPSHOT_VM_PREFIX, - uuidutils.generate_uuid()) - - LOG.debug("Creating linked-clone VM from snapshot", instance=instance) - vm_clone_task = self._session._call_method( - self._session.vim, - "CloneVM_Task", - vm_ref, - folder=dc_info.vmFolder, - name=vm_name, - spec=clone_spec) - self._session._wait_for_task(vm_clone_task) - LOG.info("Created linked-clone VM from snapshot", instance=instance) - task_info = self._session._call_method(vutil, - "get_object_property", - vm_clone_task, - "info") - return task_info.result + self._session.wait_for_task(delete_snapshot_task) + LOG.debug("Deleted Snapshot of the VM instance") def _create_vm_clone(self, instance, vm_ref, snapshot_ref, dc_info, disk_move_type=None, image_id=None, disks=None, @@ -1545,8 +1497,8 @@ def _create_vm_clone(self, instance, vm_ref, snapshot_ref, dc_info, template=True, config=config_spec) - LOG.debug("Cloning VM %s", vm_name, instance=instance) - vm_clone_task = self._session._call_method( + LOG.debug("Cloning VM %s", vm_name) + vm_clone_task = self._session.call_method( self._session.vim, "CloneVM_Task", vm_ref, @@ -1555,10 +1507,9 @@ def _create_vm_clone(self, instance, vm_ref, snapshot_ref, dc_info, type_='Images'), name=vm_name, spec=clone_spec) - self._session._wait_for_task(vm_clone_task) - LOG.info(_LI("Cloned VM %s"), vm_name, - instance=instance) - task_info = self._session._call_method(vutil, + self._session.wait_for_task(vm_clone_task) + LOG.info("Cloned VM %s", vm_name) + task_info = self._session.call_method(vutil, "get_object_property", vm_clone_task, "info") @@ -1580,19 +1531,18 @@ def snapshot(self, context, instance, image_id, update_task_state, 5. Delete the linked clone VM 6. Deletes the snapshot in original instance. """ - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) def _get_vm_and_vmdk_attribs(): # Get the vmdk info that the VM is pointing to vmdk = vm_util.get_vmdk_info(self._session, vm_ref, instance.uuid) if not vmdk.path: - LOG.debug("No root disk defined. Unable to snapshot.", - instance=instance) + LOG.debug("No root disk defined. Unable to snapshot.") raise error_util.NoRootDiskDefined() lst_properties = ["datastore", "summary.config.guestId"] - props = self._session._call_method(vutil, + props = self._session.call_method(vutil, "get_object_properties_dict", vm_ref, lst_properties) @@ -1642,8 +1592,7 @@ def _get_vm_and_vmdk_attribs(): finally: if snapshot_vm_ref: try: - vm_util.destroy_vm(self._session, instance, - snapshot_vm_ref) + vm_util.destroy_vm(self._session, snapshot_vm_ref) except Exception: # exception is logged inside the function. we can continue. pass @@ -1651,11 +1600,11 @@ def _get_vm_and_vmdk_attribs(): # based on it allows the instance vm's disks to be consolidated. # TODO(vui) Add handling for when vmdk volume is attached. if snapshot_ref: - self._delete_vm_snapshot(instance, vm_ref, snapshot_ref) + self._delete_vm_snapshot(snapshot_ref) def reboot(self, instance, network_info, reboot_type="SOFT"): """Reboot a VM instance.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) props = self._get_instance_props(vm_ref) pwr_state = props.get('runtime.powerState') @@ -1664,7 +1613,7 @@ def reboot(self, instance, network_info, reboot_type="SOFT"): # Raise an exception if the VM is not powered On. if pwr_state not in ["poweredOn"]: - reason = _("instance is not powered on") + reason = "instance is not powered on" raise exception.InstanceRebootFailure(reason=reason) # If latest vmware tools are installed in the VM, and that the tools @@ -1672,24 +1621,24 @@ def reboot(self, instance, network_info, reboot_type="SOFT"): if (tools_status == "toolsOk" and tools_running_status == "guestToolsRunning" and reboot_type == "SOFT"): - LOG.debug("Rebooting guest OS of VM", instance=instance) - self._session._call_method(self._session.vim, "RebootGuest", + LOG.debug("Rebooting guest OS of VM") + self._session.call_method(self._session.vim, "RebootGuest", vm_ref) - LOG.debug("Rebooted guest OS of VM", instance=instance) + LOG.debug("Rebooted guest OS of VM") else: - LOG.debug("Doing hard reboot of VM", instance=instance) - reset_task = self._session._call_method(self._session.vim, + LOG.debug("Doing hard reboot of VM") + reset_task = self._session.call_method(self._session.vim, "ResetVM_Task", vm_ref) - self._session._wait_for_task(reset_task) - LOG.debug("Did hard reboot of VM", instance=instance) + self._session.wait_for_task(reset_task) + LOG.debug("Did hard reboot of VM") - def _destroy_instance(self, context, instance, destroy_disks=True): + def _destroy_instance(self, instance, destroy_disks=True): # Destroy a VM instance try: - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) lst_properties = ["config.files.vmPathName", "runtime.powerState", "datastore"] - props = self._session._call_method(vutil, + props = self._session.call_method(vutil, "get_object_properties_dict", vm_ref, lst_properties) @@ -1703,18 +1652,18 @@ def _destroy_instance(self, context, instance, destroy_disks=True): # Power off the VM if it is in PoweredOn state. if pwr_state == "poweredOn": - vm_util.power_off_instance(self._session, instance, vm_ref) + vm_util.power_off_instance(self._session, vm_ref) # Un-register the VM try: - LOG.debug("Unregistering the VM", instance=instance) - self._session._call_method(self._session.vim, + LOG.debug("Unregistering the VM") + self._session.call_method(self._session.vim, "UnregisterVM", vm_ref) - LOG.debug("Unregistered the VM", instance=instance) + LOG.debug("Unregistered the VM") except Exception as excep: LOG.warning("In vmwareapi:vmops:_destroy_instance, got " "this exception while un-registering the VM: %s", - excep, instance=instance) + excep) # Delete the folder holding the VM related content on # the datastore. @@ -1723,8 +1672,7 @@ def _destroy_instance(self, context, instance, destroy_disks=True): dir_ds_compliant_path = vm_ds_path.parent LOG.debug("Deleting contents of the VM from " "datastore %(datastore_name)s", - {'datastore_name': vm_ds_path.datastore}, - instance=instance) + {'datastore_name': vm_ds_path.datastore}) ds_ref_ret = props['datastore'] ds_ref = ds_ref_ret.ManagedObjectReference[0] dc_info = self.get_datacenter_ref_and_name(ds_ref) @@ -1733,18 +1681,16 @@ def _destroy_instance(self, context, instance, destroy_disks=True): dc_info.ref) LOG.debug("Deleted contents of the VM from " "datastore %(datastore_name)s", - {'datastore_name': vm_ds_path.datastore}, - instance=instance) + {'datastore_name': vm_ds_path.datastore}) except Exception: LOG.warning("In vmwareapi:vmops:_destroy_instance, " "exception while deleting the VM contents " "from the disk", - exc_info=True, instance=instance) + exc_info=True) except exception.InstanceNotFound: - LOG.warning('Instance does not exist on backend', - instance=instance) + LOG.warning('Instance does not exist on backend') except Exception: - LOG.exception(_('Destroy instance failed'), instance=instance) + LOG.exception('Destroy instance failed') finally: vm_util.vm_ref_cache_delete(instance.uuid) @@ -1756,54 +1702,54 @@ def destroy(self, context, instance, destroy_disks=True): 2. Un-register. 3. Delete the contents of the folder holding the VM related data. """ - LOG.debug("Destroying instance", instance=instance) - self._destroy_instance(context, instance, destroy_disks=destroy_disks) - LOG.debug("Instance destroyed", instance=instance) + LOG.debug("Destroying instance") + self._destroy_instance(instance, destroy_disks=destroy_disks) + LOG.debug("Instance destroyed") def pause(self, instance): - msg = _("pause not supported for vmwareapi") + msg = "pause not supported for vmwareapi" raise NotImplementedError(msg) def unpause(self, instance): - msg = _("unpause not supported for vmwareapi") + msg = "unpause not supported for vmwareapi" raise NotImplementedError(msg) def suspend(self, instance): """Suspend the specified instance.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) - pwr_state = self._session._call_method(vutil, + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) + pwr_state = self._session.call_method(vutil, "get_object_property", vm_ref, "runtime.powerState") # Only PoweredOn VMs can be suspended. if pwr_state == "poweredOn": - LOG.debug("Suspending the VM", instance=instance) - suspend_task = self._session._call_method(self._session.vim, + LOG.debug("Suspending the VM") + suspend_task = self._session.call_method(self._session.vim, "SuspendVM_Task", vm_ref) - self._session._wait_for_task(suspend_task) - LOG.debug("Suspended the VM", instance=instance) + self._session.wait_for_task(suspend_task) + LOG.debug("Suspended the VM") # Raise Exception if VM is poweredOff elif pwr_state == "poweredOff": - reason = _("instance is powered off and cannot be suspended.") + reason = "instance is powered off and cannot be suspended." raise exception.InstanceSuspendFailure(reason=reason) else: LOG.debug("VM was already in suspended state. So returning " - "without doing anything", instance=instance) + "without doing anything") def resume(self, instance): """Resume the specified instance.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) - pwr_state = self._session._call_method(vutil, + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) + pwr_state = self._session.call_method(vutil, "get_object_property", vm_ref, "runtime.powerState") if pwr_state.lower() == "suspended": - LOG.debug("Resuming the VM", instance=instance) - suspend_task = self._session._call_method( + LOG.debug("Resuming the VM") + suspend_task = self._session.call_method( self._session.vim, "PowerOnVM_Task", vm_ref) - self._session._wait_for_task(suspend_task) - LOG.debug("Resumed the VM", instance=instance) + self._session.wait_for_task(suspend_task) + LOG.debug("Resumed the VM") else: reason = _("instance is not in a suspended state") raise exception.InstanceResumeFailure(reason=reason) @@ -1818,7 +1764,7 @@ def rescue(self, context, instance, network_info, image_meta): Attach the image that the instance was created from and boot from it. """ - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) # Get the root disk vmdk object vmdk = vm_util.get_vmdk_info(self._session, vm_ref, @@ -1836,7 +1782,7 @@ def rescue(self, context, instance, network_info, image_meta): datastore, dc_info, self._imagecache) - vm_util.power_off_instance(self._session, instance, vm_ref) + vm_util.power_off_instance(self._session, vm_ref) # Fetch the image if it does not exist in the cache self._fetch_image_if_missing(context, vi) @@ -1851,7 +1797,7 @@ def rescue(self, context, instance, network_info, image_meta): ds_util.disk_copy(self._session, dc_info.ref, vi.cache_image_path, rescue_disk_path) # Attach the rescue disk to the instance - self._volumeops.attach_disk_to_vm(vm_ref, instance, vmdk.adapter_type, + self._volumeops.attach_disk_to_vm(vm_ref, vmdk.adapter_type, vmdk.disk_type, rescue_disk_path) # Get the rescue device and configure the boot order to # boot from this device @@ -1860,24 +1806,23 @@ def rescue(self, context, instance, network_info, image_meta): boot_spec = vm_util.get_vm_boot_spec(factory, rescue_device) # Update the VM with the new boot order and power on vm_util.reconfigure_vm(self._session, vm_ref, boot_spec) - vm_util.power_on_instance(self._session, instance, vm_ref=vm_ref) + vm_util.power_on_instance(self._session, vm_ref) def unrescue(self, instance, power_on=True): """Unrescue the specified instance.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) # Get the rescue device and detach it from the instance. try: rescue_device = self._get_rescue_device(instance, vm_ref) except exception.NotFound: with excutils.save_and_reraise_exception(): - LOG.error('Unable to access the rescue disk', - instance=instance) - vm_util.power_off_instance(self._session, instance, vm_ref) - self._volumeops.detach_disk_from_vm(vm_ref, instance, rescue_device, + LOG.error('Unable to access the rescue disk') + vm_util.power_off_instance(self._session, vm_ref) + self._volumeops.detach_disk_from_vm(vm_ref, rescue_device, destroy_disk=True) if power_on: - vm_util.power_on_instance(self._session, instance, vm_ref=vm_ref) + vm_util.power_on_instance(self._session, vm_ref) def power_off(self, instance, timeout=0, retry_interval=0): """Power off the specified instance. @@ -1893,7 +1838,8 @@ def power_off(self, instance, timeout=0, retry_interval=0): retry_interval): return - vm_util.power_off_instance(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) + vm_util.power_off_instance(self._session, vm_ref) self.update_cached_instances() def _clean_shutdown(self, instance, timeout, retry_interval): @@ -1906,15 +1852,13 @@ def _clean_shutdown(self, instance, timeout, retry_interval): :return: True if the instance was shutdown within time limit, False otherwise. """ - LOG.debug("Performing Soft shutdown on instance", - instance=instance) - vm_ref = vm_util.get_vm_ref(self._session, instance) + LOG.debug("Performing Soft shutdown on instance") + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) props = self._get_instance_props(vm_ref) if props.get("runtime.powerState") != "poweredOn": - LOG.debug("Instance not in poweredOn state.", - instance=instance) + LOG.debug("Instance not in poweredOn state.") return False if ((props.get("summary.guest.toolsStatus") == "toolsOk") and @@ -1922,8 +1866,8 @@ def _clean_shutdown(self, instance, timeout, retry_interval): "guestToolsRunning")): LOG.debug("Soft shutdown instance, timeout: %d", - timeout, instance=instance) - self._session._call_method(self._session.vim, + timeout) + self._session.call_method(self._session.vim, "ShutdownGuest", vm_ref) @@ -1932,31 +1876,29 @@ def _clean_shutdown(self, instance, timeout, retry_interval): props = self._get_instance_props(vm_ref) if props.get("runtime.powerState") == "poweredOff": - LOG.info("Soft shutdown succeeded.", - instance=instance) + LOG.info("Soft shutdown succeeded.") return True time.sleep(wait_time) timeout -= retry_interval - LOG.warning("Timed out while waiting for soft shutdown.", - instance=instance) + LOG.warning("Timed out while waiting for soft shutdown.") else: - LOG.debug("VMware Tools not running", instance=instance) + LOG.debug("VMware Tools not running") return False def is_instance_in_resource_pool(self, instance): try: - vm_ref = vm_util.get_vm_ref(self._session, instance) - res_pool = self._session._call_method(vutil, "get_object_property", + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) + res_pool = self._session.call_method(vutil, "get_object_property", vm_ref, "resourcePool") return vutil.get_moref_value(res_pool) == \ vutil.get_moref_value(self._root_resource_pool) except (exception.InstanceNotFound, vexc.ManagedObjectNotFoundException): - LOG.debug("Failed to find instance", instance=instance) + LOG.debug("Failed to find instance") return False def _get_instance_props(self, vm_ref): @@ -1972,15 +1914,16 @@ def _get_instance_props(self, vm_ref): if set(vm_props.keys()).issuperset(lst_properties): return vm_props else: - return self._session._call_method( + return self._session.call_method( vutil, "get_object_properties_dict", vm_ref, lst_properties) def power_on(self, instance): - vm_util.power_on_instance(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) + vm_util.power_on_instance(self._session, vm_ref) self.update_cached_instances() - def _update_instance_progress(self, context, instance, step, total_steps): + def _update_instance_progress(self, instance, step, total_steps): """Update instance progress percent to reflect current step number """ # Divide the action's workflow into discrete steps and "bump" the @@ -1994,8 +1937,7 @@ def _update_instance_progress(self, context, instance, step, total_steps): instance_uuid = instance.uuid LOG.debug("Updating instance '%(instance_uuid)s' progress to" " %(progress)d", - {'instance_uuid': instance_uuid, 'progress': progress}, - instance=instance) + {'instance_uuid': instance_uuid, 'progress': progress}) instance.progress = progress instance.save() @@ -2023,8 +1965,7 @@ def _resize_vm(self, context, instance, vm_ref, flavor, image_meta): if not old_needs_override and new_needs_override: # Make sure we don't automatically move around "big" VMs behavior = constants.DRS_BEHAVIOR_PARTIALLY_AUTOMATED - LOG.debug("Adding DRS override '%s' for big VM.", behavior, - instance=instance) + LOG.debug("Adding DRS override '%s' for big VM.", behavior) cluster_util.update_cluster_drs_vm_override(self._session, self._cluster, vm_ref, @@ -2033,16 +1974,14 @@ def _resize_vm(self, context, instance, vm_ref, flavor, image_meta): elif old_needs_override and not new_needs_override: # remove the old override, if we had one before. make sure we don't # error out if it was already deleted another way - LOG.debug("Removing DRS override for former big VM.", - instance=instance) + LOG.debug("Removing DRS override for former big VM.") try: cluster_util.update_cluster_drs_vm_override(self._session, self._cluster, vm_ref, operation='remove') except Exception: - LOG.exception('Could not remove DRS override.', - instance=instance) + LOG.exception('Could not remove DRS override.') self._clean_up_after_special_spawning(context, flavor.memory_mb, flavor) @@ -2059,16 +1998,16 @@ def _resize_disk(self, instance, vm_ref, vmdk, flavor): 'resized.vmdk')) ds_util.disk_copy(self._session, dc_info.ref, vmdk.path, str(resized_disk)) - self._extend_virtual_disk(instance, root_disk_in_kb, resized_disk, + self._extend_virtual_disk(root_disk_in_kb, resized_disk, dc_info.ref) - self._volumeops.detach_disk_from_vm(vm_ref, instance, vmdk.device) + self._volumeops.detach_disk_from_vm(vm_ref, vmdk.device) original_disk = str(ds_obj.DatastorePath(datastore, folder, 'original.vmdk')) ds_util.disk_move(self._session, dc_info.ref, vmdk.path, original_disk) ds_util.disk_move(self._session, dc_info.ref, resized_disk, vmdk.path) - self._volumeops.attach_disk_to_vm(vm_ref, instance, + self._volumeops.attach_disk_to_vm(vm_ref, vmdk.adapter_type, vmdk.disk_type, vmdk.path) @@ -2086,7 +2025,7 @@ def _resize_create_ephemerals_and_swap(self, vm_ref, instance, vmdk = vm_util.get_vmdk_info(self._session, vm_ref, uuid=instance.uuid) if not vmdk.device: - LOG.debug("No root disk attached!", instance=instance) + LOG.debug("No root disk attached!") return ds_ref = vmdk.device.backing.datastore datastore = ds_obj.get_datastore_by_ref(self._session, ds_ref) @@ -2101,7 +2040,7 @@ def migrate_disk_and_power_off(self, context, instance, dest, flavor): """Transfers the disk of a running instance in multiple phases, turning off the instance before the end. """ - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) vmdk = vm_util.get_vmdk_info(self._session, vm_ref, uuid=instance.uuid) @@ -2118,19 +2057,19 @@ def migrate_disk_and_power_off(self, context, instance, dest, flavor): exception.ResizeError(reason=reason)) # 0. Zero out the progress to begin - self._update_instance_progress(context, instance, + self._update_instance_progress(instance, step=0, total_steps=RESIZE_TOTAL_STEPS) # 1. Power off the instance - vm_util.power_off_instance(self._session, instance, vm_ref) - self._update_instance_progress(context, instance, + vm_util.power_off_instance(self._session, vm_ref) + self._update_instance_progress(instance, step=1, total_steps=RESIZE_TOTAL_STEPS) def confirm_migration(self, migration, instance, network_info): """Confirms a resize, destroying the source VM.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) vmdk = vm_util.get_vmdk_info(self._session, vm_ref, uuid=instance.uuid) if not vmdk.device: @@ -2160,12 +2099,11 @@ def _revert_migration_update_disks(self, vm_ref, instance, vmdk, if ds_util.file_exists(self._session, ds_browser, original_disk.parent, original_disk.basename): - self._volumeops.detach_disk_from_vm(vm_ref, instance, - vmdk.device) + self._volumeops.detach_disk_from_vm(vm_ref, vmdk.device) ds_util.disk_delete(self._session, dc_info.ref, vmdk.path) ds_util.disk_move(self._session, dc_info.ref, str(original_disk), vmdk.path) - self._volumeops.attach_disk_to_vm(vm_ref, instance, + self._volumeops.attach_disk_to_vm(vm_ref, vmdk.adapter_type, vmdk.disk_type, vmdk.path) # Reconfigure ephemerals @@ -2176,9 +2114,9 @@ def _revert_migration_update_disks(self, vm_ref, instance, vmdk, def finish_revert_migration(self, context, instance, network_info, block_device_info, power_on=True): """Finish reverting a resize.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) # Ensure that the VM is off - vm_util.power_off_instance(self._session, instance, vm_ref) + vm_util.power_off_instance(self._session, vm_ref) client_factory = self._session.vim.client.factory # Reconfigure the VM properties extra_specs = self._get_extra_specs(instance.flavor, @@ -2203,29 +2141,26 @@ def finish_revert_migration(self, context, instance, network_info, adapter_type = vmdk.adapter_type self._detach_volumes(instance, block_device_info) - LOG.debug("Relocating VM for reverting migration", - instance=instance) + LOG.debug("Relocating VM for reverting migration") try: self._relocate_vm(vm_ref, context, instance, network_info) - LOG.debug("Relocated VM for reverting migration", - instance=instance) + LOG.debug("Relocated VM for reverting migration") except Exception as e: with excutils.save_and_reraise_exception(): - LOG.error("Relocating the VM failed: %s", e, - instance=instance) + LOG.error("Relocating the VM failed: %s", e) else: self.update_cluster_placement(context, instance) finally: self._attach_volumes(instance, block_device_info, adapter_type) if power_on: - vm_util.power_on_instance(self._session, instance) + vm_util.power_on_instance(self._session, vm_ref) def finish_migration(self, context, migration, instance, disk_info, network_info, image_meta, resize_instance=False, block_device_info=None, power_on=True): """Completes a resize, turning on the migrated instance.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) flavor = instance.flavor boot_from_volume = compute_utils.is_volume_backed_instance(context, @@ -2243,23 +2178,21 @@ def finish_migration(self, context, migration, instance, disk_info, self._detach_volumes(instance, block_device_info) reattach_volumes = True LOG.debug("Relocating VM for migration to %s", - migration.dest_compute, instance=instance) + migration.dest_compute) try: self._relocate_vm(vm_ref, context, instance, network_info, image_meta) - LOG.debug("Relocated VM to %s", migration.dest_compute, - instance=instance) + LOG.debug("Relocated VM to %s", migration.dest_compute) except Exception as e: with excutils.save_and_reraise_exception(): - LOG.error("Relocating the VM failed with error: %s", e, - instance=instance) + LOG.error("Relocating the VM failed with error: %s", e) self._attach_volumes(instance, block_device_info, adapter_type) self.update_cluster_placement(context, instance) self.disable_drs_if_needed(instance) - self._update_instance_progress(context, instance, + self._update_instance_progress(instance, step=2, total_steps=RESIZE_TOTAL_STEPS) # 3.Reconfigure the VM and disk @@ -2268,32 +2201,32 @@ def finish_migration(self, context, migration, instance, disk_info, vmdk = vm_util.get_vmdk_info(self._session, vm_ref, uuid=instance.uuid) self._resize_disk(instance, vm_ref, vmdk, flavor) - self._update_instance_progress(context, instance, + self._update_instance_progress(instance, step=3, total_steps=RESIZE_TOTAL_STEPS) # 4. Purge ephemeral and swap disks self._remove_ephemerals_and_swap(vm_ref) - self._update_instance_progress(context, instance, + self._update_instance_progress(instance, step=4, total_steps=RESIZE_TOTAL_STEPS) # 5. Update ephemerals self._resize_create_ephemerals_and_swap(vm_ref, instance, block_device_info) - self._update_instance_progress(context, instance, + self._update_instance_progress(instance, step=5, total_steps=RESIZE_TOTAL_STEPS) # 6. Attach the volumes (if necessary) if reattach_volumes: self._attach_volumes(instance, block_device_info, adapter_type) - self._update_instance_progress(context, instance, + self._update_instance_progress(instance, step=6, total_steps=RESIZE_TOTAL_STEPS) # 7. Start VM if power_on: - vm_util.power_on_instance(self._session, instance, vm_ref=vm_ref) - self._update_instance_progress(context, instance, + vm_util.power_on_instance(self._session, vm_ref) + self._update_instance_progress(instance, step=7, total_steps=RESIZE_TOTAL_STEPS) @@ -2383,7 +2316,7 @@ def moref(item): service["ssl_thumbprint"], ) - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) device_config_spec = [] relocate_spec.deviceChange = device_config_spec @@ -2457,7 +2390,7 @@ def poll_rebooting_instances(self, timeout, instances): "older than %(timeout)d seconds", instances_info) for instance in instances: - LOG.info("Automatically hard rebooting", instance=instance) + LOG.info("Automatically hard rebooting") self.compute_api.reboot(ctxt, instance, "HARD") def get_info(self, instance): @@ -2467,35 +2400,26 @@ def get_info(self, instance): if not vm_util._VM_VALUE_CACHE: self.update_cached_instances() - @vm_util.vm_ref_cache_heal_from_instance - def _get_vm_props(session, instance): - vm_ref = vm_util.get_vm_ref(self._session, instance) - vm_props = vm_util._VM_VALUE_CACHE.get(vm_ref.value, {}) - if vm_props and powerstate_property in vm_props: - return vm_props - + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) + vm_props = vm_util._VM_VALUE_CACHE.get(vm_ref.value, {}) + if not vm_props or powerstate_property not in vm_props: if CONF.vmware.use_property_collector: LOG.debug("VM instance data was not found on the cache.") - return session._call_method( - vutil, "get_object_properties_dict", - vm_ref, [powerstate_property]) - - try: - vm_props = _get_vm_props(self._session, instance) - except vexc.ManagedObjectNotFoundException: - raise exception.InstanceNotFound(instance_id=instance.uuid) + vm_props = self._session.call_method(vutil, + "get_object_properties_dict", + vm_ref, [powerstate_property]) return hardware.InstanceInfo( state=constants.POWER_STATES[vm_props[powerstate_property]]) def _get_diagnostics(self, instance): """Return data about VM diagnostics.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) lst_properties = ["summary.config", "summary.quickStats", "summary.runtime"] - vm_props = self._session._call_method(vutil, + vm_props = self._session.call_method(vutil, "get_object_properties_dict", vm_ref, lst_properties) @@ -2533,8 +2457,8 @@ def get_instance_diagnostics(self, instance): def _get_vnc_console_connection(self, instance): """Return connection info for a vnc console.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) - opt_value = self._session._call_method(vutil, + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) + opt_value = self._session.call_method(vutil, 'get_object_property', vm_ref, vm_util.VNC_CONFIG_KEY) @@ -2580,17 +2504,15 @@ def _set_machine_id(self, client_factory, instance, network_info, and reconfigure the network interfaces. """ if vm_ref is None: - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) machine_id_change_spec = vm_util.get_machine_id_change_spec( client_factory, self._get_machine_id_str(network_info)) - LOG.debug("Reconfiguring VM instance to set the machine id", - instance=instance) + LOG.debug("Reconfiguring VM instance to set the machine id") vm_util.reconfigure_vm(self._session, vm_ref, machine_id_change_spec) - LOG.debug("Reconfigured VM instance to set the machine id", - instance=instance) + LOG.debug("Reconfigured VM instance to set the machine id") @utils.synchronized('vmware.get_and_set_vnc_port') def _get_and_set_vnc_config(self, client_factory, instance, vm_ref): @@ -2600,17 +2522,15 @@ def _get_and_set_vnc_config(self, client_factory, instance, vm_ref): client_factory, port) LOG.debug("Reconfiguring VM instance to enable vnc on " - "port - %(port)s", {'port': port}, - instance=instance) + "port - %(port)s", {'port': port}) vm_util.reconfigure_vm(self._session, vm_ref, vnc_config_spec) LOG.debug("Reconfigured VM instance to enable vnc on " - "port - %(port)s", {'port': port}, - instance=instance) + "port - %(port)s", {'port': port}) def _get_ds_browser(self, ds_ref): ds_browser = self._datastore_browser_mapping.get(ds_ref.value) if not ds_browser: - ds_browser = self._session._call_method(vutil, + ds_browser = self._session.call_method(vutil, "get_object_property", ds_ref, "browser") @@ -2783,7 +2703,7 @@ def _destroy_expired_image_templates(self, templ_vm_folder_ref): msg = "Destroying expired image-template VM {}" LOG.debug(msg.format(templ_vm_name)) try: - vm_util.destroy_vm(self._session, None, templ_vm_ref) + vm_util.destroy_vm(self._session, templ_vm_ref) except vexc.VimFaultException as e: with excutils.save_and_reraise_exception() as ctx: if 'InvalidArgument' in e.fault_list \ @@ -2842,7 +2762,7 @@ def _get_valid_vms_from_retrieve_result(self, retrieve_result, def instance_exists(self, instance): try: - vm_util.get_vm_ref(self._session, instance) + vm_util.get_vm_ref(self._session, self._cluster, instance) return True except exception.InstanceNotFound: return False @@ -2854,7 +2774,7 @@ def attach_interface(self, context, instance, image_meta, vif): vif_model = vm_util.convert_vif_model(vif_model) vif_info = vmwarevif.get_vif_dict(self._session, self._cluster, vif_model, utils.is_neutron(), vif) - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) # Ensure that there is not a race with the port index management with lockutils.lock(instance.uuid, lock_file_prefix='nova-vmware-hot-plug'): @@ -2865,25 +2785,24 @@ def attach_interface(self, context, instance, image_meta, vif): attach_config_spec = vm_util.get_network_attach_config_spec( client_factory, vif_info, port_index, extra_specs.vif_limits) - LOG.debug("Reconfiguring VM to attach interface", - instance=instance) + LOG.debug("Reconfiguring VM to attach interface") try: vm_util.reconfigure_vm(self._session, vm_ref, attach_config_spec) except Exception as e: LOG.error('Attaching network adapter failed. Exception: %s', - e, instance=instance) + e) raise exception.InterfaceAttachFailed( instance_uuid=instance.uuid) self._network_api.update_instance_vnic_index( context, instance, vif, port_index) - LOG.debug("Reconfigured VM to attach interface", instance=instance) + LOG.debug("Reconfigured VM to attach interface") def detach_interface(self, context, instance, vif): """Detach an interface from the instance.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) # Ensure that there is not a race with the port index management with lockutils.lock(instance.uuid, lock_file_prefix='nova-vmware-hot-plug'): @@ -2910,17 +2829,16 @@ def detach_interface(self, context, instance, vif): client_factory = self._session.vim.client.factory detach_config_spec = vm_util.get_network_detach_config_spec( client_factory, device, port_index) - LOG.debug("Reconfiguring VM to detach interface", - instance=instance) + LOG.debug("Reconfiguring VM to detach interface") try: vm_util.reconfigure_vm(self._session, vm_ref, detach_config_spec) except Exception as e: LOG.error('Detaching network adapter failed. Exception: %s', - e, instance=instance) + e) raise exception.InterfaceDetachFailed( instance_uuid=instance.uuid) - LOG.debug("Reconfigured VM to detach interface", instance=instance) + LOG.debug("Reconfigured VM to detach interface") def _use_disk_image_as_full_clone(self, vm_ref, vi): """Uses cached image disk by copying it into the VM directory.""" @@ -2936,11 +2854,12 @@ def _use_disk_image_as_full_clone(self, vm_ref, vi): str(vi.cache_image_path), str(root_disk_ds_loc)) - self._extend_if_required( - vi.dc_info, vi.ii, vi.instance, str(root_disk_ds_loc)) + self._extend_if_required(vi.dc_info, + vi.instance, + str(root_disk_ds_loc)) self._volumeops.attach_disk_to_vm( - vm_ref, vi.instance, + vm_ref, vi.ii.adapter_type, vi.ii.disk_type, str(root_disk_ds_loc), vi.root_gb * units.Mi, False, @@ -3008,12 +2927,12 @@ def _use_disk_image_as_linked_clone(self, vm_ref, vi): # for cleanup up here, as _extend_virtual_disk # already does it self._extend_if_required( - vi.dc_info, vi.ii, vi.instance, str(sized_disk_ds_loc)) + vi.dc_info, vi.instance, str(sized_disk_ds_loc)) # Associate the sized image disk to the VM by attaching to the VM a # COW child of said disk. self._volumeops.attach_disk_to_vm( - vm_ref, vi.instance, + vm_ref, vi.ii.adapter_type, vi.ii.disk_type, str(sized_disk_ds_loc), vi.root_gb * units.Mi, vi.ii.linked_clone, @@ -3022,9 +2941,8 @@ def _use_disk_image_as_linked_clone(self, vm_ref, vi): def _use_iso_image(self, vm_ref, vi): """Uses cached image as a bootable virtual cdrom.""" - self._attach_cdrom_to_vm( - vm_ref, vi.instance, vi.datastore.ref, - str(vi.cache_image_path)) + self._attach_cdrom_to_vm(vm_ref, vi.datastore.ref, + str(vi.cache_image_path)) # Optionally create and attach blank disk if vi.root_gb > 0: @@ -3044,7 +2962,7 @@ def _use_iso_image(self, vm_ref, vi): vi.root_gb * units.Mi) self._volumeops.attach_disk_to_vm( - vm_ref, vi.instance, + vm_ref, vi.ii.adapter_type, vi.ii.disk_type, str(root_disk_ds_loc), vi.root_gb * units.Mi, linked_clone, @@ -3079,7 +2997,7 @@ def _list_instances_in_cluster(self, additional_properties=None, vutil.get_moref_value(self._cluster)) vms = [] if self._root_resource_pool: - vms = self._session._call_method( + vms = self._session.call_method( vim_util, 'get_inner_objects', self._root_resource_pool, 'vm', 'VirtualMachine', properties) return_properties = additional_properties is not None or include_moref @@ -3096,22 +3014,19 @@ def get_vnc_console(self, instance): # a VNC proxy. Instead, you need to tell OpenStack to talk # directly to the ESX host running the VM you are attempting # to connect to via VNC. - + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) vnc_console = self._get_vnc_console_connection(instance) - host_name = vm_util.get_host_name_for_vm( - self._session, - instance) + host_name = vm_util.get_host_name_for_vm(self._session, vm_ref) vnc_console['host'] = host_name # NOTE: VM can move hosts in some situations. Debug for admins. LOG.debug("VM %(uuid)s is currently on host %(host_name)s", - {'uuid': instance.uuid, 'host_name': host_name}, - instance=instance) + {'uuid': instance.uuid, 'host_name': host_name}) return ctype.ConsoleVNC(**vnc_console) def get_mks_console(self, instance): - vm_ref = vm_util.get_vm_ref(self._session, instance) - ticket = self._session._call_method(self._session.vim, + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) + ticket = self._session.call_method(self._session.vim, 'AcquireTicket', vm_ref, ticketType='mks') @@ -3146,7 +3061,7 @@ def update_cached_instances(self): if self._property_collector is None: pc = vim.service_content.propertyCollector - self._property_collector = self._session._call_method( + self._property_collector = self._session.call_method( self._session.vim, "CreatePropertyCollector", pc) vim.CreateFilter(self._property_collector, @@ -3185,7 +3100,9 @@ def update_cached_instances(self): instance_uuid = changes.get("config.instanceUuid") if update.kind == "enter": - vm_util.vm_ref_cache_update(instance_uuid, vm_ref) + vm_util.vm_ref_cache_update(instance_uuid, + vm_util.StableVmRefUuid(self._session, + self._cluster, instance_uuid, vm_ref)) elif update.kind == "modify": old_instance_uuid = values.get( "config.instanceUuid") @@ -3196,7 +3113,9 @@ def update_cached_instances(self): vm_util.vm_ref_cache_delete( old_instance_uuid) vm_util.vm_ref_cache_update( - instance_uuid, vm_ref) + instance_uuid, + vm_util.StableVmRefUuid(self._session, + self._cluster, instance_uuid, vm_ref)) values.update(changes) LOG.debug("%s.%s.%s -> %s", vm_ref["_type"], @@ -3253,7 +3172,8 @@ def update_vmref_cache(self): if vm_uuid != props.get('config.instanceUuid'): continue - vm_util.vm_ref_cache_update(vm_uuid, props['obj']) + vm_util.vm_ref_cache_update(vm_uuid, vm_util.StableVmRefUuid( + self._session, self._cluster, vm_uuid, props['obj'])) def set_compute_host(self, compute_host): """Called by the driver on init_host() so we know the compute host""" @@ -3372,7 +3292,8 @@ def _sync_sync_server_group(context, sg_uuid): continue try: - moref = vm_util.get_vm_ref(self._session, instance) + moref = vm_util.get_vm_ref(self._session, self._cluster, + instance) except exception.InstanceNotFound: LOG.warning('Could not find moref for instance %s. ' 'Ignoring member of server-group %s', @@ -3496,6 +3417,6 @@ def place_vm(self, context, instance): if getattr(rule, "vmGroupName", None) == vm_group_name: placement_rules.append(rule) - result = self._session._call_method(self._session.vim, "PlaceVm", + result = self._session.call_method(self._session.vim, "PlaceVm", self._cluster, placementSpec=placement_spec) return result diff --git a/nova/virt/vmwareapi/volumeops.py b/nova/virt/vmwareapi/volumeops.py index 8cd476692bb..5df63cecadf 100644 --- a/nova/virt/vmwareapi/volumeops.py +++ b/nova/virt/vmwareapi/volumeops.py @@ -36,11 +36,11 @@ class VMwareVolumeOps(object): """Management class for Volume-related tasks.""" - def __init__(self, session, cluster=None): + def __init__(self, session, cluster): self._session = session self._cluster = cluster - def attach_disk_to_vm(self, vm_ref, instance, + def attach_disk_to_vm(self, vm_ref, adapter_type, disk_type, vmdk_path=None, disk_size=None, linked_clone=False, device_name=None, disk_io_limits=None, @@ -67,7 +67,7 @@ def attach_disk_to_vm(self, vm_ref, instance, if volume_uuid and backing_uuid: LOG.debug("Adding volume details for %s to attach config spec.", - volume_uuid, instance=instance) + volume_uuid) self._add_volume_details_to_config_spec(vmdk_attach_config_spec, volume_uuid, backing_uuid) @@ -75,15 +75,13 @@ def attach_disk_to_vm(self, vm_ref, instance, "disk %(vmdk_path)s or device %(device_name)s with type " "%(disk_type)s", {'vm_ref': vm_ref.value, 'vmdk_path': vmdk_path, - 'device_name': device_name, 'disk_type': disk_type}, - instance=instance) + 'device_name': device_name, 'disk_type': disk_type}) vm_util.reconfigure_vm(self._session, vm_ref, vmdk_attach_config_spec) LOG.debug("Reconfigured VM instance %(vm_ref)s to attach " "disk %(vmdk_path)s or device %(device_name)s with type " "%(disk_type)s", {'vm_ref': vm_ref.value, 'vmdk_path': vmdk_path, - 'device_name': device_name, 'disk_type': disk_type}, - instance=instance) + 'device_name': device_name, 'disk_type': disk_type}) def _add_volume_details_to_config_spec(self, config_spec, volume_uuid, device_uuid): @@ -97,14 +95,14 @@ def _add_volume_details_to_config_spec(self, config_spec, volume_uuid, def _get_volume_uuid(self, vm_ref, volume_uuid): prop = 'config.extraConfig["volume-%s"]' % volume_uuid - opt_val = self._session._call_method(vutil, + opt_val = self._session.call_method(vutil, 'get_object_property', vm_ref, prop) if opt_val is not None: return opt_val.value - def detach_disk_from_vm(self, vm_ref, instance, device, + def detach_disk_from_vm(self, vm_ref, device, destroy_disk=False, volume_uuid=None): """Detach disk from VM by reconfiguration. @@ -118,20 +116,18 @@ def detach_disk_from_vm(self, vm_ref, instance, device, if volume_uuid is not None: LOG.debug("Adding volume details for %s to detach config spec.", - volume_uuid, instance=instance) + volume_uuid) self._add_volume_details_to_config_spec(vmdk_detach_config_spec, volume_uuid, '') disk_key = device.key LOG.debug("Reconfiguring VM instance %(vm_ref)s to detach " "disk %(disk_key)s", - {'vm_ref': vm_ref.value, 'disk_key': disk_key}, - instance=instance) + {'vm_ref': vm_ref.value, 'disk_key': disk_key}) vm_util.reconfigure_vm(self._session, vm_ref, vmdk_detach_config_spec) LOG.debug("Reconfigured VM instance %(vm_ref)s to detach " "disk %(disk_key)s", - {'vm_ref': vm_ref.value, 'disk_key': disk_key}, - instance=instance) + {'vm_ref': vm_ref.value, 'disk_key': disk_key}) def _iscsi_get_target(self, data): """Return the iSCSI Target given a volume info.""" @@ -142,7 +138,7 @@ def _iscsi_get_target(self, data): lst_properties = ["config.storageDevice.hostBusAdapter", "config.storageDevice.scsiTopology", "config.storageDevice.scsiLun"] - prop_dict = self._session._call_method(vutil, + prop_dict = self._session.call_method(vutil, "get_object_properties_dict", host_mor, lst_properties) @@ -212,19 +208,19 @@ def _iscsi_add_send_target_host(self, storage_system_mor, hba_device, send_tgt = client_factory.create('ns0:HostInternetScsiHbaSendTarget') (send_tgt.address, send_tgt.port) = target_portal.split(':') LOG.debug("Adding iSCSI host %s to send targets", send_tgt.address) - self._session._call_method( + self._session.call_method( self._session.vim, "AddInternetScsiSendTargets", storage_system_mor, iScsiHbaDevice=hba_device, targets=[send_tgt]) def _iscsi_rescan_hba(self, target_portal): """Rescan the iSCSI HBA to discover iSCSI targets.""" host_mor = vm_util.get_host_ref(self._session, self._cluster) - storage_system_mor = self._session._call_method( + storage_system_mor = self._session.call_method( vutil, "get_object_property", host_mor, "configManager.storageSystem") - hbas_ret = self._session._call_method( + hbas_ret = self._session.call_method( vutil, "get_object_property", storage_system_mor, @@ -252,7 +248,7 @@ def _iscsi_rescan_hba(self, target_portal): else: return LOG.debug("Rescanning HBA %s", hba_device) - self._session._call_method(self._session.vim, + self._session.call_method(self._session.vim, "RescanHba", storage_system_mor, hbaDevice=hba_device) LOG.debug("Rescanned HBA %s ", hba_device) @@ -285,14 +281,14 @@ def _iscsi_discover_target(self, data): 'target_portal': target_portal}) return (device_name, uuid) - def _iscsi_get_host_iqn(self, instance): + def _iscsi_get_host_iqn(self, vm_ref): """Return the host iSCSI IQN.""" - try: - host_mor = vm_util.get_host_ref_for_vm(self._session, instance) - except exception.InstanceNotFound: + if vm_ref: + host_mor = vm_util.get_host_ref_for_vm(self._session, vm_ref) + else: host_mor = vm_util.get_host_ref(self._session, self._cluster) - hbas_ret = self._session._call_method( + hbas_ret = self._session.call_method( vutil, "get_object_property", host_mor, @@ -315,10 +311,10 @@ def _get_connection_capabilities(self): def get_volume_connector(self, instance): """Return volume connector information.""" try: - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) except exception.InstanceNotFound: vm_ref = None - iqn = self._iscsi_get_host_iqn(instance) + iqn = self._iscsi_get_host_iqn(vm_ref) connector = {'ip': CONF.vmware.host_ip, 'initiator': iqn, 'host': CONF.vmware.host_ip} @@ -343,9 +339,8 @@ def _get_vmdk_base_volume_device(self, volume_ref): def _attach_volume_vmdk(self, connection_info, instance, adapter_type=None): """Attach vmdk volume storage to VM instance.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) - LOG.debug("_attach_volume_vmdk: %s", connection_info, - instance=instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) + LOG.debug("_attach_volume_vmdk: %s", connection_info) data = connection_info['data'] volume_ref = self._get_volume_ref(data['volume']) @@ -358,26 +353,25 @@ def _attach_volume_vmdk(self, connection_info, instance, # IDE does not support disk hotplug if adapter_type == constants.ADAPTER_TYPE_IDE: - state = vm_util.get_vm_state(self._session, instance) + state = vm_util.get_vm_state(self._session, vm_ref) if state != power_state.SHUTDOWN: raise exception.Invalid(_('%s does not support disk ' 'hotplug.') % adapter_type) # Attach the disk to virtual machine instance - self.attach_disk_to_vm(vm_ref, instance, adapter_type, vmdk.disk_type, + self.attach_disk_to_vm(vm_ref, adapter_type, vmdk.disk_type, vmdk_path=vmdk.path, volume_uuid=data['volume_id'], backing_uuid=vmdk.device.backing.uuid) - LOG.debug("Attached VMDK: %s", connection_info, instance=instance) + LOG.debug("Attached VMDK: %s", connection_info) def _attach_volume_iscsi(self, connection_info, instance, adapter_type=None): """Attach iscsi volume storage to VM instance.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) # Attach Volume to VM - LOG.debug("_attach_volume_iscsi: %s", connection_info, - instance=instance) + LOG.debug("_attach_volume_iscsi: %s", connection_info) data = connection_info['data'] @@ -392,16 +386,15 @@ def _attach_volume_iscsi(self, connection_info, instance, vm_ref) adapter_type = vm_util.get_scsi_adapter_type(hardware_devices) - self.attach_disk_to_vm(vm_ref, instance, + self.attach_disk_to_vm(vm_ref, adapter_type, 'rdmp', device_name=device_name) - LOG.debug("Attached ISCSI: %s", connection_info, instance=instance) + LOG.debug("Attached ISCSI: %s", connection_info) def attach_volume(self, connection_info, instance, adapter_type=None): """Attach volume storage to VM instance.""" driver_type = connection_info['driver_volume_type'] - LOG.debug("Volume attach. Driver type: %s", driver_type, - instance=instance) + LOG.debug("Volume attach. Driver type: %s", driver_type) if driver_type == constants.DISK_FORMAT_VMDK: self._attach_volume_vmdk(connection_info, instance, adapter_type) elif driver_type == constants.DISK_FORMAT_ISCSI: @@ -411,18 +404,18 @@ def attach_volume(self, connection_info, instance, adapter_type=None): def _get_host_of_vm(self, vm_ref): """Get the ESX host of given VM.""" - return self._session._call_method(vutil, 'get_object_property', + return self._session.call_method(vutil, 'get_object_property', vm_ref, 'runtime').host def _get_res_pool_of_host(self, host): """Get the resource pool of given host's cluster.""" # Get the compute resource, the host belongs to - compute_res = self._session._call_method(vutil, + compute_res = self._session.call_method(vutil, 'get_object_property', host, 'parent') # Get resource pool from the compute resource - return self._session._call_method(vutil, + return self._session.call_method(vutil, 'get_object_property', compute_res, 'resourcePool') @@ -434,7 +427,7 @@ def _get_res_pool_of_vm(self, vm_ref): # Get the resource pool of host's cluster. return self._get_res_pool_of_host(host) - def _consolidate_vmdk_volume(self, instance, vm_ref, device, volume_ref, + def _consolidate_vmdk_volume(self, vm_ref, device, volume_ref, adapter_type=None, disk_type=None): """Consolidate volume backing VMDK files if needed. @@ -494,7 +487,7 @@ def _consolidate_vmdk_volume(self, instance, vm_ref, device, volume_ref, original_device_path, exc_info=True) LOG.debug("Removing disk device of volume's backing and " "reattempting relocate.") - self.detach_disk_from_vm(volume_ref, instance, original_device) + self.detach_disk_from_vm(volume_ref, original_device) detached = True vm_util.relocate_vm(self._session, volume_ref, res_pool, datastore, host) @@ -503,14 +496,14 @@ def _consolidate_vmdk_volume(self, instance, vm_ref, device, volume_ref, # already. if not detached: try: - self.detach_disk_from_vm(volume_ref, instance, + self.detach_disk_from_vm(volume_ref, original_device, destroy_disk=True) except oslo_vmw_exceptions.FileNotFoundException: LOG.debug("Original volume backing %s is missing, no need " "to detach it", original_device.backing.fileName) # Attach the current volume to the volume_ref - self.attach_disk_to_vm(volume_ref, instance, + self.attach_disk_to_vm(volume_ref, adapter_type, disk_type, vmdk_path=current_device_path) @@ -529,10 +522,9 @@ def _get_vmdk_backed_disk_device(self, vm_ref, connection_info_data): def _detach_volume_vmdk(self, connection_info, instance): """Detach volume storage to VM instance.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) # Detach Volume from VM - LOG.debug("_detach_volume_vmdk: %s", connection_info, - instance=instance) + LOG.debug("_detach_volume_vmdk: %s", connection_info) data = connection_info['data'] volume_ref = self._get_volume_ref(data['volume']) @@ -548,28 +540,27 @@ def _detach_volume_vmdk(self, connection_info, instance): # IDE does not support disk hotplug if adapter_type == constants.ADAPTER_TYPE_IDE: - state = vm_util.get_vm_state(self._session, instance) + state = vm_util.get_vm_state(self._session, vm_ref) if state != power_state.SHUTDOWN: raise exception.Invalid(_('%s does not support disk ' 'hotplug.') % adapter_type) disk_type = vm_util._get_device_disk_type(device) - self._consolidate_vmdk_volume(instance, vm_ref, device, volume_ref, + self._consolidate_vmdk_volume(vm_ref, device, volume_ref, adapter_type=adapter_type, disk_type=disk_type) - self.detach_disk_from_vm(vm_ref, instance, device, + self.detach_disk_from_vm(vm_ref, device, volume_uuid=data['volume_id']) - LOG.debug("Detached VMDK: %s", connection_info, instance=instance) + LOG.debug("Detached VMDK: %s", connection_info) def _detach_volume_iscsi(self, connection_info, instance): """Detach volume storage to VM instance.""" - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) # Detach Volume from VM - LOG.debug("_detach_volume_iscsi: %s", connection_info, - instance=instance) + LOG.debug("_detach_volume_iscsi: %s", connection_info) data = connection_info['data'] # Discover iSCSI Target @@ -583,14 +574,13 @@ def _detach_volume_iscsi(self, connection_info, instance): device = vm_util.get_rdm_disk(hardware_devices, uuid) if device is None: raise exception.DiskNotFound(message=_("Unable to find volume")) - self.detach_disk_from_vm(vm_ref, instance, device, destroy_disk=True) - LOG.debug("Detached ISCSI: %s", connection_info, instance=instance) + self.detach_disk_from_vm(vm_ref, device, destroy_disk=True) + LOG.debug("Detached ISCSI: %s", connection_info) def detach_volume(self, connection_info, instance): """Detach volume storage to VM instance.""" driver_type = connection_info['driver_volume_type'] - LOG.debug("Volume detach. Driver type: %s", driver_type, - instance=instance) + LOG.debug("Volume detach. Driver type: %s", driver_type) if driver_type == constants.DISK_FORMAT_VMDK: self._detach_volume_vmdk(connection_info, instance) elif driver_type == constants.DISK_FORMAT_ISCSI: @@ -602,8 +592,7 @@ def attach_root_volume(self, connection_info, instance, datastore, adapter_type=None): """Attach a root volume to the VM instance.""" driver_type = connection_info['driver_volume_type'] - LOG.debug("Root volume attach. Driver type: %s", driver_type, - instance=instance) + LOG.debug("Root volume attach. Driver type: %s", driver_type) # NOTE(jkulik): Upstream moves the volume to the instance DS here. This # would violate the differentiation between ephemeral and volume DS, so # we don't do that. This comment should help us detect upstream changes @@ -636,7 +625,7 @@ def fixup_shadow_vms(self, instance, shadow_vms): # This should sensibly moved out to cinder: # Cinder can delete the old shadow-vm, as soon as the attachment # for the vm prior the vmotion gets deleted - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) for device in vm_util.get_hardware_devices(self._session, vm_ref): class_name = device.__class__.__name__ @@ -662,24 +651,21 @@ def fixup_shadow_vms(self, instance, shadow_vms): LOG.warning("Shadow-vm %s already has a disk" " attached at %s replacing it with %s", volume, original_device_path, current_device_path, - instance=instance ) - self.detach_disk_from_vm(self, volume_ref, instance, + self.detach_disk_from_vm(vm_ref, volume_ref, original_device, destroy_disk=True) disk_type = vm_util._get_device_disk_type(device) self.attach_disk_to_vm(volume_ref, - instance, constants.DEFAULT_ADAPTER_TYPE, disk_type, current_device_path ) except Exception: LOG.exception("Failed to attach volume {}. Device {}".format( - data["volume_id"], - device.key), instance=instance) + data["volume_id"], device.key)) - def delete_shadow_vms(self, block_device_info, instance=None): + def delete_shadow_vms(self, block_device_info): # We need to delete the migrated shadow vms # (until we implement it in cinder) block_device_mapping = driver.block_device_info_get_mapping( @@ -695,19 +681,19 @@ def delete_shadow_vms(self, block_device_info, instance=None): try: data = connection_info["data"] volume_ref = self._get_volume_ref(data["volume"]) - destroy_task = session._call_method(session.vim, + destroy_task = session.call_method(session.vim, "Destroy_Task", volume_ref) - session._wait_for_task(destroy_task) + session.wait_for_task(destroy_task) deleted.append("{volume_id} ({volume})".format(**data)) except oslo_vmw_exceptions.ManagedObjectNotFoundException: LOG.debug("Volume %s already deleted", - data.get("volume_id"), instance=instance) + data.get("volume_id")) except Exception: LOG.exception("Failed to delete volume %s", - data.get("volume_id"), instance=instance) + data.get("volume_id")) - LOG.info("Deleted %s", deleted, instance=instance) + LOG.info("Deleted %s", deleted) def map_volumes_to_devices(self, instance, disk_infos): """Maps a connection_info.data to a device of the instance by its key @@ -718,7 +704,7 @@ def map_volumes_to_devices(self, instance, disk_infos): dicts to a a device by the stored volume_id """ remapped = {} - vm_ref = vm_util.get_vm_ref(self._session, instance) + vm_ref = vm_util.get_vm_ref(self._session, self._cluster, instance) # TODO(fwiesel) Create a function # _get_vmdk_backed_disk_devices (plural) # so we do not have two calls for each device