summaryrefslogtreecommitdiff
path: root/nova/tests/unit/virt/vmwareapi
diff options
context:
space:
mode:
Diffstat (limited to 'nova/tests/unit/virt/vmwareapi')
-rw-r--r--nova/tests/unit/virt/vmwareapi/__init__.py20
-rw-r--r--nova/tests/unit/virt/vmwareapi/fake.py203
-rw-r--r--nova/tests/unit/virt/vmwareapi/stubs.py7
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_configdrive.py3
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_driver_api.py65
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_ds_util.py2
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_imagecache.py2
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_images.py10
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_network_util.py10
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_session.py208
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_vif.py3
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_vim_util.py6
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_vm_util.py91
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_vmops.py47
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_volumeops.py192
15 files changed, 661 insertions, 208 deletions
diff --git a/nova/tests/unit/virt/vmwareapi/__init__.py b/nova/tests/unit/virt/vmwareapi/__init__.py
index e69de29bb2..206b60cb8f 100644
--- a/nova/tests/unit/virt/vmwareapi/__init__.py
+++ b/nova/tests/unit/virt/vmwareapi/__init__.py
@@ -0,0 +1,20 @@
+# 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 unittest
+
+try:
+ import oslo_vmware # noqa: F401
+except ImportError:
+ raise unittest.SkipTest(
+ "The 'oslo.vmware' dependency is not installed."
+ )
diff --git a/nova/tests/unit/virt/vmwareapi/fake.py b/nova/tests/unit/virt/vmwareapi/fake.py
index b98a287613..2c09afb8ec 100644
--- a/nova/tests/unit/virt/vmwareapi/fake.py
+++ b/nova/tests/unit/virt/vmwareapi/fake.py
@@ -23,11 +23,11 @@ import collections
import sys
from oslo_log import log as logging
-from oslo_serialization import jsonutils
from oslo_utils import units
from oslo_utils import uuidutils
from oslo_vmware import exceptions as vexc
from oslo_vmware.objects import datastore as ds_obj
+from oslo_vmware import vim_util
from nova import exception
from nova.virt.vmwareapi import constants
@@ -76,23 +76,34 @@ def cleanup():
_db_content[c] = {}
-def _create_object(table, table_obj):
+def _create_object(table_obj):
"""Create an object in the db."""
- _db_content.setdefault(table, {})
- _db_content[table][table_obj.obj] = table_obj
+ _db_content.setdefault(table_obj.obj._type, {})
+ update_object(table_obj)
-def _get_object(obj_ref):
+def get_object(obj_ref):
"""Get object for the give reference."""
- return _db_content[obj_ref.type][obj_ref]
+ return _db_content[obj_ref.type][obj_ref.value]
-def _get_objects(obj_type):
+def get_objects(obj_type):
"""Get objects of the type."""
- lst_objs = FakeRetrieveResult()
- for key in _db_content[obj_type]:
- lst_objs.add_object(_db_content[obj_type][key])
- return lst_objs
+ return _db_content[obj_type].values()
+
+
+def get_first_object(obj_type):
+ """Get the first object of an object type"""
+ return next(iter(_db_content[obj_type].values()))
+
+
+def get_first_object_ref(obj_type):
+ """Get the first reference of an object type"""
+ return get_first_object(obj_type).obj
+
+
+def _no_objects_of_type(obj_type):
+ return not _db_content.get(obj_type)
def _convert_to_array_of_mor(mors):
@@ -135,21 +146,19 @@ class FakeRetrieveResult(object):
if token is not None:
self.token = token
- def add_object(self, object):
- self.objects.append(object)
+ def add_object(self, obj):
+ self.objects.append(obj)
-def _get_object_refs(obj_type):
- """Get object References of the type."""
- lst_objs = []
- for key in _db_content[obj_type]:
- lst_objs.append(key)
- return lst_objs
+def get_object_refs(obj_type):
+ """Get iterator over object References of the type."""
+ for obj in _db_content[obj_type].values():
+ yield obj.obj
-def _update_object(table, table_obj):
+def update_object(table_obj):
"""Update objects of the type."""
- _db_content[table][table_obj.obj] = table_obj
+ _db_content[table_obj.obj._type][table_obj.obj.value] = table_obj
class Prop(object):
@@ -177,6 +186,14 @@ class ManagedObjectReference(object):
self.type = name
self._type = name
+ def __repr__(self):
+ return f'{self._type}:{self.value}'
+
+ def __eq__(self, other):
+ return (other is not None and
+ vim_util.get_moref_value(other) == self.value and
+ vim_util.get_moref_type(other) == self.type)
+
class ObjectContent(object):
"""ObjectContent array holds dynamic properties."""
@@ -262,8 +279,11 @@ class ManagedObject(object):
return prefix + "-" + str(self.__class__._counter)
def __repr__(self):
- return jsonutils.dumps({elem.name: elem.val
- for elem in self.propSet})
+ # We can't just dump the managed-object, because it may be circular
+ return "{}:{}({})".format(self.obj._type, self.obj.value,
+ ", ".join(
+ "{}={}".format(p.name, p.val if p.name == "name" else "<>")
+ for p in self.propSet))
class DataObject(object):
@@ -593,8 +613,7 @@ class ResourcePool(ManagedObject):
class DatastoreHostMount(DataObject):
def __init__(self, value='host-100'):
super(DatastoreHostMount, self).__init__()
- host_ref = (_db_content["HostSystem"]
- [list(_db_content["HostSystem"].keys())[0]].obj)
+ host_ref = get_first_object_ref("HostSystem")
host_system = DataObject()
host_system.ManagedObjectReference = [host_ref]
host_system.value = value
@@ -621,9 +640,15 @@ class ClusterComputeResource(ManagedObject):
summary.effectiveCpu = 10000
self.set("summary", summary)
+ vm_list = DataObject()
+ vm_list.ManagedObjectReference = []
+ self.set("vm", vm_list)
+
def _add_root_resource_pool(self, r_pool):
if r_pool:
self.set("resourcePool", r_pool)
+ pool = get_object(r_pool)
+ self.set("vm", pool.get("vm"))
def _add_host(self, host_sys):
if host_sys:
@@ -659,7 +684,7 @@ class ClusterComputeResource(ManagedObject):
# Compute the aggregate stats
summary.numHosts = len(hosts.ManagedObjectReference)
for host_ref in hosts.ManagedObjectReference:
- host_sys = _get_object(host_ref)
+ host_sys = get_object(host_ref)
connected = host_sys.get("connected")
host_summary = host_sys.get("summary")
summary.numCpuCores += host_summary.hardware.numCpuCores
@@ -717,14 +742,17 @@ class HostSystem(ManagedObject):
maintenance_mode=False):
super(HostSystem, self).__init__("host")
self.set("name", name)
- if _db_content.get("HostNetworkSystem", None) is None:
+ if _no_objects_of_type("HostNetworkSystem"):
create_host_network_system()
- if not _get_object_refs('HostStorageSystem'):
+
+ if _no_objects_of_type("HostStorageSystem"):
create_host_storage_system()
- host_net_key = list(_db_content["HostNetworkSystem"].keys())[0]
- host_net_sys = _db_content["HostNetworkSystem"][host_net_key].obj
- self.set("configManager.networkSystem", host_net_sys)
- host_storage_sys_key = _get_object_refs('HostStorageSystem')[0]
+
+ host_net_obj = get_first_object("HostNetworkSystem")
+ host_net_ref = host_net_obj.obj
+ self.set("configManager.networkSystem", host_net_ref)
+
+ host_storage_sys_key = get_first_object_ref('HostStorageSystem')
self.set("configManager.storageSystem", host_storage_sys_key)
if not ds_ref:
@@ -779,10 +807,9 @@ class HostSystem(ManagedObject):
self.set("config.network.pnic", net_info_pnic)
self.set("connected", connected)
- if _db_content.get("Network", None) is None:
+ if _no_objects_of_type("Network"):
create_network()
- net_ref = _db_content["Network"][
- list(_db_content["Network"].keys())[0]].obj
+ net_ref = get_first_object_ref("Network")
network_do = DataObject()
network_do.ManagedObjectReference = [net_ref]
self.set("network", network_do)
@@ -792,9 +819,9 @@ class HostSystem(ManagedObject):
vswitch_do.name = "vSwitch0"
vswitch_do.portgroup = ["PortGroup-vmnet0"]
- net_swicth = DataObject()
- net_swicth.HostVirtualSwitch = [vswitch_do]
- self.set("config.network.vswitch", net_swicth)
+ net_switch = DataObject()
+ net_switch.HostVirtualSwitch = [vswitch_do]
+ self.set("config.network.vswitch", net_switch)
host_pg_do = DataObject()
host_pg_do.key = "PortGroup-vmnet0"
@@ -821,7 +848,7 @@ class HostSystem(ManagedObject):
self.set("config.storageDevice.hostBusAdapter", host_bus_adapter_array)
# Set the same on the storage system managed object
- host_storage_sys = _get_object(host_storage_sys_key)
+ host_storage_sys = get_object(host_storage_sys_key)
host_storage_sys.set('storageDeviceInfo.hostBusAdapter',
host_bus_adapter_array)
@@ -882,17 +909,15 @@ class Datacenter(ManagedObject):
def __init__(self, name="ha-datacenter", ds_ref=None):
super(Datacenter, self).__init__("dc")
self.set("name", name)
- if _db_content.get("Folder", None) is None:
+ if _no_objects_of_type("Folder"):
create_folder()
- folder_ref = _db_content["Folder"][
- list(_db_content["Folder"].keys())[0]].obj
+ folder_ref = get_first_object_ref("Folder")
folder_do = DataObject()
folder_do.ManagedObjectReference = [folder_ref]
self.set("vmFolder", folder_ref)
- if _db_content.get("Network", None) is None:
+ if _no_objects_of_type("Network"):
create_network()
- net_ref = _db_content["Network"][
- list(_db_content["Network"].keys())[0]].obj
+ net_ref = get_first_object_ref("Network")
network_do = DataObject()
network_do.ManagedObjectReference = [net_ref]
self.set("network", network_do)
@@ -927,54 +952,56 @@ class Task(ManagedObject):
def create_host_network_system():
host_net_system = HostNetworkSystem()
- _create_object("HostNetworkSystem", host_net_system)
+ _create_object(host_net_system)
def create_host_storage_system():
host_storage_system = HostStorageSystem()
- _create_object("HostStorageSystem", host_storage_system)
+ _create_object(host_storage_system)
def create_host(ds_ref=None):
host_system = HostSystem(ds_ref=ds_ref)
- _create_object('HostSystem', host_system)
+ _create_object(host_system)
def create_datacenter(name, ds_ref=None):
data_center = Datacenter(name, ds_ref)
- _create_object('Datacenter', data_center)
+ _create_object(data_center)
def create_datastore(name, capacity, free):
data_store = Datastore(name, capacity, free)
- _create_object('Datastore', data_store)
+ _create_object(data_store)
return data_store.obj
def create_res_pool():
res_pool = ResourcePool()
- _create_object('ResourcePool', res_pool)
+ _create_object(res_pool)
return res_pool.obj
def create_folder():
folder = Folder()
- _create_object('Folder', folder)
+ _create_object(folder)
return folder.obj
def create_network():
network = Network()
- _create_object('Network', network)
+ _create_object(network)
def create_cluster(name, ds_ref):
cluster = ClusterComputeResource(name=name)
- cluster._add_host(_get_object_refs("HostSystem")[0])
- cluster._add_host(_get_object_refs("HostSystem")[1])
+ for i, host in enumerate(get_object_refs("HostSystem")):
+ cluster._add_host(host)
+ if i >= 1:
+ break
cluster._add_datastore(ds_ref)
cluster._add_root_resource_pool(create_res_pool())
- _create_object('ClusterComputeResource', cluster)
+ _create_object(cluster)
return cluster
@@ -993,16 +1020,15 @@ def create_vm(uuid=None, name=None,
devices = []
if vmPathName is None:
- vm_path = ds_obj.DatastorePath(
- list(_db_content['Datastore'].values())[0])
+ vm_path = ds_obj.DatastorePath(get_first_object("Datastore"))
else:
vm_path = ds_obj.DatastorePath.parse(vmPathName)
if res_pool_ref is None:
- res_pool_ref = list(_db_content['ResourcePool'].keys())[0]
+ res_pool_ref = get_first_object_ref("ResourcePool")
if host_ref is None:
- host_ref = list(_db_content["HostSystem"].keys())[0]
+ host_ref = get_first_object_ref("HostSystem")
# Fill in the default path to the vmx file if we were only given a
# datastore. Note that if you create a VM with vmPathName '[foo]', when you
@@ -1011,9 +1037,9 @@ def create_vm(uuid=None, name=None,
if vm_path.rel_path == '':
vm_path = vm_path.join(name, name + '.vmx')
- for key, value in _db_content["Datastore"].items():
+ for value in get_objects("Datastore"):
if value.get('summary.name') == vm_path.datastore:
- ds = key
+ ds = value.obj
break
else:
ds = create_datastore(vm_path.datastore, 1024, 500)
@@ -1030,9 +1056,9 @@ def create_vm(uuid=None, name=None,
"instanceUuid": uuid,
"version": version}
vm = VirtualMachine(**vm_dict)
- _create_object("VirtualMachine", vm)
+ _create_object(vm)
- res_pool = _get_object(res_pool_ref)
+ res_pool = get_object(res_pool_ref)
res_pool.vm.ManagedObjectReference.append(vm.obj)
return vm.obj
@@ -1040,7 +1066,7 @@ def create_vm(uuid=None, name=None,
def create_task(task_name, state="running", result=None, error_fault=None):
task = Task(task_name, state, result, error_fault)
- _create_object("Task", task)
+ _create_object(task)
return task
@@ -1103,12 +1129,14 @@ def fake_fetch_image(context, instance, host, port, dc_name, ds_name,
def _get_vm_mdo(vm_ref):
"""Gets the Virtual Machine with the ref from the db."""
- if _db_content.get("VirtualMachine", None) is None:
+ vms = _db_content.get("VirtualMachine")
+ if not vms:
raise exception.NotFound("There is no VM registered")
- if vm_ref not in _db_content.get("VirtualMachine"):
+ try:
+ return vms[vm_ref.value]
+ except KeyError:
raise exception.NotFound("Virtual Machine with ref %s is not "
- "there" % vm_ref)
- return _db_content.get("VirtualMachine")[vm_ref]
+ "there" % vm_ref.value)
def _merge_extraconfig(existing, changes):
@@ -1354,11 +1382,10 @@ class FakeVim(object):
def _find_all_by_uuid(self, *args, **kwargs):
uuid = kwargs.get('uuid')
vm_refs = []
- for vm_ref in _db_content.get("VirtualMachine"):
- vm = _get_object(vm_ref)
+ for vm in get_objects("VirtualMachine"):
vm_uuid = vm.get("summary.config.instanceUuid")
if vm_uuid == uuid:
- vm_refs.append(vm_ref)
+ vm_refs.append(vm.obj)
return vm_refs
def _delete_snapshot(self, method, *args, **kwargs):
@@ -1412,7 +1439,7 @@ class FakeVim(object):
vm_dict["extra_config"] = extraConfigs
virtual_machine = VirtualMachine(**vm_dict)
- _create_object("VirtualMachine", virtual_machine)
+ _create_object(virtual_machine)
task_mdo = create_task(method, "success")
return task_mdo.obj
@@ -1420,7 +1447,7 @@ class FakeVim(object):
"""Unregisters a VM from the Host System."""
vm_ref = args[0]
_get_vm_mdo(vm_ref)
- del _db_content["VirtualMachine"][vm_ref]
+ del _db_content["VirtualMachine"][vm_ref.value]
task_mdo = create_task(method, "success")
return task_mdo.obj
@@ -1491,13 +1518,7 @@ class FakeVim(object):
def _set_power_state(self, method, vm_ref, pwr_state="poweredOn"):
"""Sets power state for the VM."""
- if _db_content.get("VirtualMachine", None) is None:
- raise exception.NotFound("No Virtual Machine has been "
- "registered yet")
- if vm_ref not in _db_content.get("VirtualMachine"):
- raise exception.NotFound("Virtual Machine with ref %s is not "
- "there" % vm_ref)
- vm_mdo = _db_content.get("VirtualMachine").get(vm_ref)
+ vm_mdo = _get_vm_mdo(vm_ref)
vm_mdo.set("runtime.powerState", pwr_state)
task_mdo = create_task(method, "success")
return task_mdo.obj
@@ -1526,7 +1547,7 @@ class FakeVim(object):
# This means that we are retrieving props for all managed
# data objects of the specified 'type' in the entire
# inventory. This gets invoked by vim_util.get_objects.
- mdo_refs = _db_content[spec_type]
+ mdo_refs = list(get_object_refs(spec_type))
elif obj_ref.type != spec_type:
# This means that we are retrieving props for the managed
# data objects in the parent object's 'path' property.
@@ -1536,7 +1557,7 @@ class FakeVim(object):
# path = 'datastore'
# the above will retrieve all datastores in the given
# cluster.
- parent_mdo = _db_content[obj_ref.type][obj_ref]
+ parent_mdo = get_object(obj_ref)
path = obj.selectSet[0].path
mdo_refs = parent_mdo.get(path).ManagedObjectReference
else:
@@ -1545,12 +1566,13 @@ class FakeVim(object):
# vim_util.get_properties_for_a_collection_of_objects.
mdo_refs = [obj_ref]
+ mdo_list = _db_content[spec_type]
for mdo_ref in mdo_refs:
- mdo = _db_content[spec_type][mdo_ref]
- prop_list = []
- for prop_name in properties:
- prop = Prop(prop_name, mdo.get(prop_name))
- prop_list.append(prop)
+ mdo = mdo_list[mdo_ref.value]
+ prop_list = [
+ Prop(prop_name, mdo.get(prop_name))
+ for prop_name in properties
+ ]
obj_content = ObjectContent(mdo.obj, prop_list)
lst_ret_objs.add_object(obj_content)
except Exception:
@@ -1560,14 +1582,13 @@ class FakeVim(object):
def _add_port_group(self, method, *args, **kwargs):
"""Adds a port group to the host system."""
- _host_sk = list(_db_content["HostSystem"].keys())[0]
- host_mdo = _db_content["HostSystem"][_host_sk]
+ host_mdo = get_first_object("HostSystem")
host_mdo._add_port_group(kwargs.get("portgrp"))
def _add_iscsi_send_tgt(self, method, *args, **kwargs):
"""Adds a iscsi send target to the hba."""
send_targets = kwargs.get('targets')
- host_storage_sys = _get_objects('HostStorageSystem').objects[0]
+ host_storage_sys = get_first_object('HostStorageSystem')
iscsi_hba_array = host_storage_sys.get('storageDeviceInfo'
'.hostBusAdapter')
iscsi_hba = iscsi_hba_array.HostHostBusAdapter[0]
diff --git a/nova/tests/unit/virt/vmwareapi/stubs.py b/nova/tests/unit/virt/vmwareapi/stubs.py
index d0caaae43e..a0406bdac5 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)
test.stub_out('nova.network.neutron.API.update_instance_vnic_index',
lambda *args, **kwargs: None)
diff --git a/nova/tests/unit/virt/vmwareapi/test_configdrive.py b/nova/tests/unit/virt/vmwareapi/test_configdrive.py
index de07444ddb..7e8b1c1b63 100644
--- a/nova/tests/unit/virt/vmwareapi/test_configdrive.py
+++ b/nova/tests/unit/virt/vmwareapi/test_configdrive.py
@@ -13,8 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
+
import fixtures
-import mock
from oslo_utils.fixture import uuidsentinel
from nova import context
diff --git a/nova/tests/unit/virt/vmwareapi/test_driver_api.py b/nova/tests/unit/virt/vmwareapi/test_driver_api.py
index 5889fb8239..ac473c8c09 100644
--- a/nova/tests/unit/virt/vmwareapi/test_driver_api.py
+++ b/nova/tests/unit/virt/vmwareapi/test_driver_api.py
@@ -21,9 +21,9 @@ Test suite for VMwareAPI.
import collections
import datetime
+from unittest import mock
from eventlet import greenthread
-import mock
import os_resource_classes as orc
from oslo_utils import fixture as utils_fixture
from oslo_utils.fixture import uuidsentinel
@@ -61,6 +61,7 @@ from nova.virt.vmwareapi import ds_util
from nova.virt.vmwareapi import error_util
from nova.virt.vmwareapi import imagecache
from nova.virt.vmwareapi import images
+from nova.virt.vmwareapi import session
from nova.virt.vmwareapi import vif
from nova.virt.vmwareapi import vim_util
from nova.virt.vmwareapi import vm_util
@@ -109,20 +110,11 @@ DEFAULT_FLAVOR_OBJS = [
]
-def _fake_create_session(inst):
- session = vmwareapi_fake.DataObject()
- session.key = 'fake_key'
- session.userName = 'fake_username'
- session._pbm_wsdl_loc = None
- session._pbm = None
- inst._session = session
-
-
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)
@@ -154,36 +146,6 @@ class VMwareDriverStartupTestCase(test.NoDBTestCase):
group='vmware'))
-class VMwareSessionTestCase(test.NoDBTestCase):
-
- @mock.patch.object(driver.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',
- _fake_create_session),
- mock.patch.object(driver.VMwareAPISession, 'invoke_api'),
- ) as (fake_create, fake_invoke):
- session = driver.VMwareAPISession()
- session._vim = mock.Mock()
- module = mock.Mock()
- session._call_method(module, 'fira')
- fake_invoke.assert_called_once_with(module, 'fira', session._vim)
-
- @mock.patch.object(driver.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',
- _fake_create_session),
- mock.patch.object(driver.VMwareAPISession, 'invoke_api'),
- ) as (fake_create, fake_invoke):
- session = driver.VMwareAPISession()
- module = mock.Mock()
- session._call_method(module, 'fira')
- fake_invoke.assert_called_once_with(module, 'fira')
-
-
class VMwareAPIVMTestCase(test.NoDBTestCase,
test_diagnostics.DiagnosticsComparisonMixin):
"""Unit tests for Vmware API connection calls."""
@@ -337,7 +299,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
_fake_check_session)
with mock.patch.object(greenthread, 'sleep'):
- self.conn = driver.VMwareAPISession()
+ self.conn = session.VMwareAPISession()
self.assertEqual(2, self.attempts)
def _get_flavor_by_name(self, type):
@@ -411,8 +373,8 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
def _get_vm_record(self):
# Get record for VM
- vms = vmwareapi_fake._get_objects("VirtualMachine")
- for vm in vms.objects:
+ vms = vmwareapi_fake.get_objects("VirtualMachine")
+ for vm in vms:
if vm.get('name') == vm_util._get_vm_name(self._display_name,
self.uuid):
return vm
@@ -1307,7 +1269,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
def _snapshot_delete_vm_snapshot_exception(self, exception, call_count=1):
self._create_vm()
- fake_vm = vmwareapi_fake._get_objects("VirtualMachine").objects[0].obj
+ fake_vm = vmwareapi_fake.get_first_object_ref("VirtualMachine")
snapshot_ref = vmwareapi_fake.ManagedObjectReference(
value="Snapshot-123",
name="VirtualMachineSnapshot")
@@ -1801,8 +1763,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
get_vm_ref.assert_called_once_with(self.conn._session,
self.instance)
- get_volume_ref.assert_called_once_with(
- connection_info['data']['volume'])
+ get_volume_ref.assert_called_once_with(connection_info['data'])
self.assertTrue(get_vmdk_info.called)
attach_disk_to_vm.assert_called_once_with(mock.sentinel.vm_ref,
self.instance, adapter_type, disk_type, vmdk_path='fake-path')
@@ -1878,8 +1839,8 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
def test_iscsi_rescan_hba(self):
fake_target_portal = 'fake_target_host:port'
- host_storage_sys = vmwareapi_fake._get_objects(
- "HostStorageSystem").objects[0]
+ host_storage_sys = vmwareapi_fake.get_first_object(
+ "HostStorageSystem")
iscsi_hba_array = host_storage_sys.get('storageDeviceInfo'
'.hostBusAdapter')
iscsi_hba = iscsi_hba_array.HostHostBusAdapter[0]
@@ -1899,7 +1860,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
def test_iscsi_get_target(self):
data = {'target_portal': 'fake_target_host:port',
'target_iqn': 'fake_target_iqn'}
- host = vmwareapi_fake._get_objects('HostSystem').objects[0]
+ host = vmwareapi_fake.get_first_object('HostSystem')
host._add_iscsi_target(data)
vops = volumeops.VMwareVolumeOps(self.conn._session)
result = vops._iscsi_get_target(data)
@@ -2162,7 +2123,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
'min_unit': 1,
'max_unit': 16,
'step_size': 1,
- 'allocation_ratio': 16.0,
+ 'allocation_ratio': 4.0,
},
orc.MEMORY_MB: {
'total': 2048,
@@ -2170,7 +2131,7 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
'min_unit': 1,
'max_unit': 1024,
'step_size': 1,
- 'allocation_ratio': 1.5,
+ 'allocation_ratio': 1.0,
},
orc.DISK_GB: {
'total': 95,
diff --git a/nova/tests/unit/virt/vmwareapi/test_ds_util.py b/nova/tests/unit/virt/vmwareapi/test_ds_util.py
index 3b909642fb..1716027afb 100644
--- a/nova/tests/unit/virt/vmwareapi/test_ds_util.py
+++ b/nova/tests/unit/virt/vmwareapi/test_ds_util.py
@@ -14,8 +14,8 @@
from contextlib import contextmanager
import re
+from unittest import mock
-import mock
from oslo_utils import units
from oslo_vmware import exceptions as vexc
from oslo_vmware.objects import datastore as ds_obj
diff --git a/nova/tests/unit/virt/vmwareapi/test_imagecache.py b/nova/tests/unit/virt/vmwareapi/test_imagecache.py
index 485b1ea4cd..1116804d2f 100644
--- a/nova/tests/unit/virt/vmwareapi/test_imagecache.py
+++ b/nova/tests/unit/virt/vmwareapi/test_imagecache.py
@@ -13,8 +13,8 @@
# under the License.
import datetime
+from unittest import mock
-import mock
from oslo_config import cfg
from oslo_utils import fixture as utils_fixture
from oslo_utils.fixture import uuidsentinel
diff --git a/nova/tests/unit/virt/vmwareapi/test_images.py b/nova/tests/unit/virt/vmwareapi/test_images.py
index 7cfec00c97..20abc063a0 100644
--- a/nova/tests/unit/virt/vmwareapi/test_images.py
+++ b/nova/tests/unit/virt/vmwareapi/test_images.py
@@ -17,8 +17,8 @@ Test suite for images.
import os
import tarfile
+from unittest import mock
-import mock
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import units
from oslo_vmware import rw_handles
@@ -117,13 +117,11 @@ class VMwareImagesTestCase(test.NoDBTestCase):
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(vm_util, 'get_vmdk_info')
) as (mock_image_api_get,
mock_image_api_download,
mock_image_transfer,
mock_build_shadow_vm_config_spec,
- mock_call_method,
mock_get_vmdk_info):
image_data = {'id': 'fake-id',
'disk_format': 'vmdk',
@@ -172,7 +170,7 @@ class VMwareImagesTestCase(test.NoDBTestCase):
mock_write_handle)
mock_get_vmdk_info.assert_called_once_with(
session, mock.sentinel.vm_ref, 'fake-vm')
- mock_call_method.assert_called_once_with(
+ session._call_method.assert_called_once_with(
session.vim, "UnregisterVM", mock.sentinel.vm_ref)
@mock.patch('oslo_vmware.rw_handles.ImageReadHandle')
@@ -188,13 +186,11 @@ class VMwareImagesTestCase(test.NoDBTestCase):
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(vm_util, 'get_vmdk_info')
) as (mock_image_api_get,
mock_image_api_download,
mock_image_transfer,
mock_build_shadow_vm_config_spec,
- mock_call_method,
mock_get_vmdk_info):
image_data = {'id': 'fake-id',
'disk_format': 'vmdk',
@@ -220,7 +216,7 @@ class VMwareImagesTestCase(test.NoDBTestCase):
mock_image_transfer.assert_called_once_with(mock_read_handle,
mock_write_handle)
- mock_call_method.assert_called_once_with(
+ session._call_method.assert_called_once_with(
session.vim, "UnregisterVM", mock.sentinel.vm_ref)
mock_get_vmdk_info.assert_called_once_with(
session, mock.sentinel.vm_ref, 'fake-vm')
diff --git a/nova/tests/unit/virt/vmwareapi/test_network_util.py b/nova/tests/unit/virt/vmwareapi/test_network_util.py
index 10f2583946..b3b5bb15ea 100644
--- a/nova/tests/unit/virt/vmwareapi/test_network_util.py
+++ b/nova/tests/unit/virt/vmwareapi/test_network_util.py
@@ -15,15 +15,15 @@
# under the License.
import collections
+from unittest import mock
-import mock
from oslo_vmware import vim_util
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 import session
ResultSet = collections.namedtuple('ResultSet', ['objects'])
@@ -36,12 +36,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 = session.VMwareAPISession()
def _build_cluster_networks(self, networks):
"""Returns a set of results for a cluster network lookup.
diff --git a/nova/tests/unit/virt/vmwareapi/test_session.py b/nova/tests/unit/virt/vmwareapi/test_session.py
new file mode 100644
index 0000000000..6088e1f5b2
--- /dev/null
+++ b/nova/tests/unit/virt/vmwareapi/test_session.py
@@ -0,0 +1,208 @@
+# Copyright (c) 2022 SAP SE
+# 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.
+
+
+"""
+Test suite for VMwareAPI Session
+"""
+
+from unittest import mock
+
+from oslo_vmware import exceptions as vexec
+
+from nova import test
+from nova.tests.unit.virt.vmwareapi import fake as vmwareapi_fake
+from nova.virt.vmwareapi import session
+
+
+def _fake_create_session(inst):
+ _session = vmwareapi_fake.DataObject()
+ _session.key = 'fake_key'
+ _session.userName = 'fake_username'
+ _session._pbm_wsdl_loc = None
+ _session._pbm = None
+ inst._session = _session
+
+
+def _fake_fetch_moref_impl(inst, _):
+ inst.moref = vmwareapi_fake.ManagedObjectReference(
+ value=mock.sentinel.moref2)
+
+
+class FakeStableMoRefProxy(session.StableMoRefProxy):
+ def __init__(self, ref=None):
+ super(FakeStableMoRefProxy, self).__init__(
+ ref or vmwareapi_fake.ManagedObjectReference(
+ value=mock.sentinel.moref))
+
+ def fetch_moref(self, session):
+ pass
+
+ def __repr__(self):
+ return "FakeStableMoRefProxy({!r})".format(self.moref)
+
+
+class StableMoRefProxyTestCase(test.NoDBTestCase):
+ def test_proxy(self):
+ ref = FakeStableMoRefProxy()
+ self.assertEqual(mock.sentinel.moref, ref.value)
+ self.assertEqual("ManagedObject", ref._type)
+
+ def test_proxy_classes(self):
+ # Necessary for suds serialisation
+ ref = FakeStableMoRefProxy()
+ self.assertEqual("ManagedObjectReference", ref.__class__.__name__)
+
+
+class VMwareSessionTestCase(test.NoDBTestCase):
+
+ @mock.patch.object(session.VMwareAPISession, '_is_vim_object',
+ return_value=False)
+ def test_call_method(self, mock_is_vim):
+ with test.nested(
+ mock.patch.object(session.VMwareAPISession,
+ '_create_session',
+ _fake_create_session),
+ mock.patch.object(session.VMwareAPISession,
+ 'invoke_api'),
+ ) as (fake_create, fake_invoke):
+ _session = session.VMwareAPISession()
+ _session._vim = mock.Mock()
+ module = mock.Mock()
+ _session._call_method(module, 'fira')
+ fake_invoke.assert_called_once_with(module, 'fira', _session._vim)
+
+ @mock.patch.object(session.VMwareAPISession, '_is_vim_object',
+ return_value=True)
+ def test_call_method_vim(self, mock_is_vim):
+ with test.nested(
+ mock.patch.object(session.VMwareAPISession,
+ '_create_session',
+ _fake_create_session),
+ mock.patch.object(session.VMwareAPISession,
+ 'invoke_api'),
+ ) as (fake_create, fake_invoke):
+ _session = session.VMwareAPISession()
+ module = mock.Mock()
+ _session._call_method(module, 'fira')
+ fake_invoke.assert_called_once_with(module, 'fira')
+
+ @mock.patch.object(session.VMwareAPISession, '_is_vim_object',
+ return_value=True)
+ def test_call_method_no_recovery(self, mock_is_vim):
+ with test.nested(
+ mock.patch.object(session.VMwareAPISession, '_create_session',
+ _fake_create_session),
+ mock.patch.object(session.VMwareAPISession, 'invoke_api'),
+ mock.patch.object(FakeStableMoRefProxy, 'fetch_moref'),
+ ) as (fake_create, fake_invoke, fake_fetch_moref):
+ _session = session.VMwareAPISession()
+ module = mock.Mock()
+ ref = FakeStableMoRefProxy()
+
+ _session._call_method(
+ module, mock.sentinel.method_arg, ref, ref=ref)
+
+ fake_invoke.assert_called_once_with(
+ module, mock.sentinel.method_arg, ref, ref=ref)
+ fake_fetch_moref.assert_not_called()
+
+ @mock.patch.object(session.VMwareAPISession, '_is_vim_object',
+ return_value=True)
+ def test_call_method_recovery_arg_failed(self, mock_is_vim):
+ with test.nested(
+ mock.patch.object(session.VMwareAPISession, '_create_session',
+ _fake_create_session),
+ mock.patch.object(session.VMwareAPISession, 'invoke_api'),
+ mock.patch.object(FakeStableMoRefProxy, 'fetch_moref'),
+ ) as (fake_create, fake_invoke, fake_fetch_moref):
+ _session = session.VMwareAPISession()
+ module = mock.Mock()
+ ref = FakeStableMoRefProxy()
+ fake_invoke.side_effect = [vexec.ManagedObjectNotFoundException]
+
+ self.assertRaises(vexec.ManagedObjectNotFoundException,
+ _session._call_method, module, mock.sentinel.method_arg, ref)
+
+ fake_invoke.assert_called_once_with(
+ module, mock.sentinel.method_arg, ref)
+ fake_fetch_moref.assert_not_called()
+
+ @mock.patch.object(session.VMwareAPISession, '_is_vim_object',
+ return_value=True)
+ def test_call_method_recovery_kwarg_failed(self, mock_is_vim):
+ with test.nested(
+ mock.patch.object(session.VMwareAPISession, '_create_session',
+ _fake_create_session),
+ mock.patch.object(session.VMwareAPISession, 'invoke_api'),
+ mock.patch.object(FakeStableMoRefProxy, 'fetch_moref'),
+ ) as (fake_create, fake_invoke, fake_fetch_moref):
+ _session = session.VMwareAPISession()
+ module = mock.Mock()
+ ref = FakeStableMoRefProxy()
+ fake_invoke.side_effect = [vexec.ManagedObjectNotFoundException]
+
+ self.assertRaises(vexec.ManagedObjectNotFoundException,
+ _session._call_method, module,
+ mock.sentinel.method_arg, ref=ref)
+
+ fake_invoke.assert_called_once_with(
+ module, mock.sentinel.method_arg, ref=ref)
+ fake_fetch_moref.assert_not_called()
+
+ @mock.patch.object(session.VMwareAPISession, '_is_vim_object',
+ return_value=True)
+ def test_call_method_recovery_arg_success(self, mock_is_vim):
+ with test.nested(
+ mock.patch.object(session.VMwareAPISession, '_create_session',
+ _fake_create_session),
+ mock.patch.object(session.VMwareAPISession, 'invoke_api'),
+ mock.patch.object(FakeStableMoRefProxy,
+ 'fetch_moref', _fake_fetch_moref_impl),
+ ) as (fake_create, fake_invoke, fake_fetch_moref):
+ _session = session.VMwareAPISession()
+ module = mock.Mock()
+ ref = FakeStableMoRefProxy()
+
+ fake_invoke.side_effect = [vexec.ManagedObjectNotFoundException(
+ details=dict(obj=mock.sentinel.moref),
+ ), None]
+ _session._call_method(module, mock.sentinel.method_arg, ref)
+ fake_invoke.assert_called_with(
+ module, mock.sentinel.method_arg, ref)
+
+ @mock.patch.object(session.VMwareAPISession, '_is_vim_object',
+ return_value=True)
+ def test_call_method_recovery_kwarg_success(self, mock_is_vim):
+ with test.nested(
+ mock.patch.object(session.VMwareAPISession, '_create_session',
+ _fake_create_session),
+ mock.patch.object(session.VMwareAPISession, 'invoke_api'),
+ mock.patch.object(FakeStableMoRefProxy,
+ 'fetch_moref', _fake_fetch_moref_impl),
+ ) as (fake_create, fake_invoke, fake_fetch_moref):
+ _session = session.VMwareAPISession()
+ module = mock.Mock()
+ ref = FakeStableMoRefProxy()
+
+ fake_invoke.side_effect = [vexec.ManagedObjectNotFoundException(
+ details=dict(obj=mock.sentinel.moref),
+ ), None]
+ _session._call_method(module, mock.sentinel.method_arg, ref=ref)
+ fake_invoke.assert_called_with(
+ module, mock.sentinel.method_arg, ref=ref)
diff --git a/nova/tests/unit/virt/vmwareapi/test_vif.py b/nova/tests/unit/virt/vmwareapi/test_vif.py
index b0fb9df47c..02d516fac7 100644
--- a/nova/tests/unit/virt/vmwareapi/test_vif.py
+++ b/nova/tests/unit/virt/vmwareapi/test_vif.py
@@ -13,7 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
from oslo_vmware import vim_util
from nova import exception
diff --git a/nova/tests/unit/virt/vmwareapi/test_vim_util.py b/nova/tests/unit/virt/vmwareapi/test_vim_util.py
index ebfa2010ee..b3057a99ac 100644
--- a/nova/tests/unit/virt/vmwareapi/test_vim_util.py
+++ b/nova/tests/unit/virt/vmwareapi/test_vim_util.py
@@ -28,11 +28,11 @@ class VMwareVIMUtilTestCase(test.NoDBTestCase):
def test_get_inner_objects(self):
property = ['summary.name']
# Get the fake datastores directly from the cluster
- cluster_refs = fake._get_object_refs('ClusterComputeResource')
- cluster = fake._get_object(cluster_refs[0])
+ cluster = fake.get_first_object('ClusterComputeResource')
+ cluster_ref = cluster.obj
expected_ds = cluster.datastore.ManagedObjectReference
# Get the fake datastores using inner objects utility method
result = vim_util.get_inner_objects(
- self.vim, cluster_refs[0], 'datastore', 'Datastore', property)
+ self.vim, cluster_ref, 'datastore', 'Datastore', property)
datastores = [oc.obj for oc in result.objects]
self.assertEqual(expected_ds, datastores)
diff --git a/nova/tests/unit/virt/vmwareapi/test_vm_util.py b/nova/tests/unit/virt/vmwareapi/test_vm_util.py
index ea30895a4d..82fa07a882 100644
--- a/nova/tests/unit/virt/vmwareapi/test_vm_util.py
+++ b/nova/tests/unit/virt/vmwareapi/test_vm_util.py
@@ -15,14 +15,15 @@
# under the License.
import collections
+from unittest import mock
-import mock
from oslo_service import fixture as oslo_svc_fixture
from oslo_utils import units
from oslo_utils import uuidutils
from oslo_vmware import exceptions as vexc
from oslo_vmware.objects import datastore as ds_obj
from oslo_vmware import pbm
+from oslo_vmware import vim_util as vutil
from nova import exception
from nova.network import model as network_model
@@ -31,7 +32,7 @@ from nova.tests.unit import fake_instance
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 import session as vmware_session
from nova.virt.vmwareapi import vm_util
@@ -375,7 +376,7 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
ide_controller = fake.VirtualIDEController()
devices.append(scsi_controller)
devices.append(ide_controller)
- fake._update_object("VirtualMachine", vm)
+ fake.update_object(vm)
# return the scsi type, not ide
self.assertEqual(constants.DEFAULT_ADAPTER_TYPE,
vm_util.get_scsi_adapter_type(devices))
@@ -387,7 +388,7 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
ide_controller = fake.VirtualIDEController()
devices.append(scsi_controller)
devices.append(ide_controller)
- fake._update_object("VirtualMachine", vm)
+ fake.update_object(vm)
# the controller is not suitable since the device under this controller
# has exceeded SCSI_MAX_CONNECT_NUMBER
for i in range(0, constants.SCSI_MAX_CONNECT_NUMBER):
@@ -1036,7 +1037,7 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
found[0] = True
mock_log_warn.side_effect = fake_log_warn
- session = driver.VMwareAPISession()
+ session = vmware_session.VMwareAPISession()
config_spec = vm_util.get_vm_create_spec(
session.vim.client.factory,
@@ -1987,23 +1988,85 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
mock_get_name.assert_called_once_with(self._instance.display_name,
self._instance.uuid)
-
-@mock.patch.object(driver.VMwareAPISession, 'vim', stubs.fake_vim_prop)
+ def test_create_fcd_id_obj(self):
+ fcd_id_obj = mock.Mock()
+ client_factory = mock.Mock()
+ client_factory.create.return_value = fcd_id_obj
+ fcd_id = mock.sentinel.fcd_id
+ ret = vm_util._create_fcd_id_obj(client_factory, fcd_id)
+
+ self.assertEqual(fcd_id_obj, ret)
+ self.assertEqual(fcd_id, ret.id)
+ client_factory.create.assert_called_once_with('ns0:ID')
+
+ @mock.patch.object(vm_util, '_create_fcd_id_obj')
+ @mock.patch.object(vutil, 'get_moref')
+ def test_attach_fcd(self, get_moref, create_fcd_id_obj):
+ disk_id = mock.sentinel.disk_id
+ create_fcd_id_obj.return_value = disk_id
+
+ ds_ref = mock.sentinel.ds_ref
+ get_moref.return_value = ds_ref
+
+ task = mock.sentinel.task
+ session = mock.Mock()
+ session._call_method.return_value = task
+
+ vm_ref = mock.sentinel.vm_ref
+ fcd_id = mock.sentinel.fcd_id
+ ds_ref_val = mock.sentinel.ds_ref_val
+ controller_key = mock.sentinel.controller_key
+ unit_number = mock.sentinel.unit_number
+ vm_util.attach_fcd(
+ session, vm_ref, fcd_id, ds_ref_val, controller_key, unit_number)
+
+ create_fcd_id_obj.assert_called_once_with(
+ session.vim.client.factory, fcd_id)
+ get_moref.assert_called_once_with(ds_ref_val, 'Datastore')
+ session._call_method.assert_called_once_with(
+ session.vim, "AttachDisk_Task", vm_ref, diskId=disk_id,
+ datastore=ds_ref, controllerKey=controller_key,
+ unitNumber=unit_number)
+ session._wait_for_task.assert_called_once_with(task)
+
+ @mock.patch.object(vm_util, '_create_fcd_id_obj')
+ def test_detach_fcd(self, create_fcd_id_obj):
+ disk_id = mock.sentinel.disk_id
+ create_fcd_id_obj.return_value = disk_id
+
+ task = mock.sentinel.task
+ session = mock.Mock()
+ session._call_method.return_value = task
+
+ vm_ref = mock.sentinel.vm_ref
+ fcd_id = mock.sentinel.fcd_id
+ vm_util.detach_fcd(session, vm_ref, fcd_id)
+
+ create_fcd_id_obj.assert_called_once_with(
+ session.vim.client.factory, fcd_id)
+ session._call_method.assert_called_once_with(
+ session.vim, "DetachDisk_Task", vm_ref, diskId=disk_id)
+ session._wait_for_task.assert_called_once_with(task)
+
+
+@mock.patch.object(vmware_session.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)
+ # session.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(vmware_session.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 = vmware_session.VMwareAPISession()
# Create a fake VirtualMachine running on a known host
- self.host_ref = list(fake._db_content['HostSystem'].keys())[0]
+ self.host_ref = fake.get_first_object_ref("HostSystem")
self.vm_ref = fake.create_vm(host_ref=self.host_ref)
@mock.patch.object(vm_util, 'get_vm_ref')
@@ -2019,7 +2082,7 @@ class VMwareVMUtilGetHostRefTestCase(test.NoDBTestCase):
def test_get_host_name_for_vm(self, mock_get_vm_ref):
mock_get_vm_ref.return_value = self.vm_ref
- host = fake._get_object(self.host_ref)
+ host = fake.get_object(self.host_ref)
ret = vm_util.get_host_name_for_vm(self.session, 'fake-instance')
diff --git a/nova/tests/unit/virt/vmwareapi/test_vmops.py b/nova/tests/unit/virt/vmwareapi/test_vmops.py
index f84c113758..19990b8b32 100644
--- a/nova/tests/unit/virt/vmwareapi/test_vmops.py
+++ b/nova/tests/unit/virt/vmwareapi/test_vmops.py
@@ -14,8 +14,8 @@
# under the License.
import time
+from unittest import mock
-import mock
from oslo_serialization import jsonutils
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_utils import units
@@ -37,9 +37,9 @@ from nova.tests.unit.virt.vmwareapi import stubs
from nova import version
from nova.virt import hardware
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 import session
from nova.virt.vmwareapi import vif
from nova.virt.vmwareapi import vim_util
from nova.virt.vmwareapi import vm_util
@@ -65,18 +65,20 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
self.flags(my_ip='',
flat_injected=True)
self._context = context.RequestContext('fake_user', 'fake_project')
- self._session = driver.VMwareAPISession()
+ self._session = session.VMwareAPISession()
self._virtapi = mock.Mock()
self._image_id = uuids.image
- fake_ds_ref = vmwareapi_fake.ManagedObjectReference(value='fake-ds')
+ fake_ds_ref = vmwareapi_fake.ManagedObjectReference(
+ name='Datastore', value='fake-ds')
self._ds = ds_obj.Datastore(
ref=fake_ds_ref, name='fake_ds',
capacity=10 * units.Gi,
freespace=10 * units.Gi)
self._dc_info = ds_util.DcInfo(
ref='fake_dc_ref', name='fake_dc',
- vmFolder='fake_vm_folder')
+ vmFolder=vmwareapi_fake.ManagedObjectReference(
+ name='Folder', value='fake_vm_folder'))
cluster = vmwareapi_fake.create_cluster('fake_cluster', fake_ds_ref)
self._uuid = uuids.foo
fake_info_cache = {
@@ -166,7 +168,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
"projectid:fake_project\n"
"projectname:None\n"
"flavor:name:m1.micro\n"
- "flavor:memory_mb:6\n"
+ "flavor:memory_mb:8\n"
"flavor:vcpus:28\n"
"flavor:ephemeral_gb:8128\n"
"flavor:root_gb:496\n"
@@ -297,7 +299,8 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
mock_save.assert_called_once_with()
self.assertEqual(50, self._instance.progress)
- @mock.patch.object(vm_util, 'get_vm_ref', return_value='fake_ref')
+ @mock.patch.object(vm_util, 'get_vm_ref',
+ return_value=vmwareapi_fake.ManagedObjectReference())
def test_get_info(self, mock_get_vm_ref):
result = {
'summary.config.numCpu': 4,
@@ -577,7 +580,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
vmware_tools_status="toolsOk",
succeeds=False)
- def test_clean_shutdown_no_vwaretools(self):
+ def test_clean_shutdown_no_vmwaretools(self):
self._test_clean_shutdown(timeout=10,
retry_interval=3,
returns_on=1,
@@ -1138,6 +1141,14 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
mock_attach_cdrom_to_vm.assert_called_once_with(
vm_ref, self._instance, self._ds.ref, str(upload_iso_path))
+ def test_prepare_for_spawn_invalid_ram(self):
+ instance = self._instance.obj_clone()
+ flavor = objects.Flavor(vcpus=1, memory_mb=6, ephemeral_gb=1,
+ swap=1024, extra_specs={})
+ instance.flavor = flavor
+ self.assertRaises(exception.InstanceUnacceptable,
+ self._vmops.prepare_for_spawn, instance)
+
@mock.patch('nova.image.glance.API.get')
@mock.patch.object(vmops.LOG, 'debug')
@mock.patch.object(vmops.VMwareVMOps, '_fetch_image_if_missing')
@@ -2051,7 +2062,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
extra_specs,
self._metadata)
- vm = vmwareapi_fake._get_object(vm_ref)
+ vm = vmwareapi_fake.get_object(vm_ref)
# Test basic VM parameters
self.assertEqual(self._instance.uuid, vm.name)
@@ -2074,7 +2085,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
datastores = vm.datastore.ManagedObjectReference
self.assertEqual(1, len(datastores))
- datastore = vmwareapi_fake._get_object(datastores[0])
+ datastore = vmwareapi_fake.get_object(datastores[0])
self.assertEqual(self._ds.name, datastore.get('summary.name'))
# Test that the VM's network is configured as specified
@@ -2176,7 +2187,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
def _validate_flavor_extra_specs(self, flavor_extra_specs, expected):
# Validate that the extra specs are parsed correctly
flavor = objects.Flavor(name='my-flavor',
- memory_mb=6,
+ memory_mb=8,
vcpus=28,
root_gb=496,
ephemeral_gb=8128,
@@ -2227,7 +2238,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
flavor_extra_specs = {'quota:cpu_limit': 7,
'quota:cpu_reservation': 6}
flavor = objects.Flavor(name='my-flavor',
- memory_mb=6,
+ memory_mb=8,
vcpus=28,
root_gb=496,
ephemeral_gb=8128,
@@ -2280,7 +2291,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
'quota:cpu_reservation': 6,
'hw_video:ram_max_mb': 100}
flavor = objects.Flavor(name='my-flavor',
- memory_mb=6,
+ memory_mb=8,
vcpus=28,
root_gb=496,
ephemeral_gb=8128,
@@ -2692,7 +2703,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
def test_get_storage_policy_none(self):
flavor = objects.Flavor(name='m1.small',
- memory_mb=6,
+ memory_mb=8,
vcpus=28,
root_gb=496,
ephemeral_gb=8128,
@@ -2706,7 +2717,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
def test_get_storage_policy_extra_specs(self):
extra_specs = {'vmware:storage_policy': 'flavor-policy'}
flavor = objects.Flavor(name='m1.small',
- memory_mb=6,
+ memory_mb=8,
vcpus=28,
root_gb=496,
ephemeral_gb=8128,
@@ -2781,7 +2792,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
def test_get_instance_metadata(self):
flavor = objects.Flavor(id=7,
name='m1.small',
- memory_mb=6,
+ memory_mb=8,
vcpus=28,
root_gb=496,
ephemeral_gb=8128,
@@ -2796,7 +2807,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
"projectid:fake_project\n"
"projectname:None\n"
"flavor:name:m1.small\n"
- "flavor:memory_mb:6\n"
+ "flavor:memory_mb:8\n"
"flavor:vcpus:28\n"
"flavor:ephemeral_gb:8128\n"
"flavor:root_gb:496\n"
@@ -2913,7 +2924,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
def test_get_cores_per_socket(self):
extra_specs = {'hw:cpu_sockets': 7}
flavor = objects.Flavor(name='m1.small',
- memory_mb=6,
+ memory_mb=8,
vcpus=28,
root_gb=496,
ephemeral_gb=8128,
diff --git a/nova/tests/unit/virt/vmwareapi/test_volumeops.py b/nova/tests/unit/virt/vmwareapi/test_volumeops.py
index 0a051d62f5..003cbb9283 100644
--- a/nova/tests/unit/virt/vmwareapi/test_volumeops.py
+++ b/nova/tests/unit/virt/vmwareapi/test_volumeops.py
@@ -12,7 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-import mock
+from unittest import mock
+
+import ddt
from oslo_utils.fixture import uuidsentinel as uuids
from oslo_vmware import exceptions as oslo_vmw_exceptions
from oslo_vmware import vim_util as vutil
@@ -26,11 +28,12 @@ from nova.tests.unit import fake_instance
from nova.tests.unit.virt.vmwareapi import fake as vmwareapi_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 import session
from nova.virt.vmwareapi import vm_util
from nova.virt.vmwareapi import volumeops
+@ddt.ddt
class VMwareVolumeOpsTestCase(test.NoDBTestCase):
def setUp(self):
@@ -38,7 +41,7 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
super(VMwareVolumeOpsTestCase, self).setUp()
vmwareapi_fake.reset()
stubs.set_stubs(self)
- self._session = driver.VMwareAPISession()
+ self._session = session.VMwareAPISession()
self._context = context.RequestContext('fake_user', 'fake_project')
self._volumeops = volumeops.VMwareVolumeOps(self._session)
@@ -141,8 +144,7 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
get_vm_ref.assert_called_once_with(self._volumeops._session,
instance)
- get_volume_ref.assert_called_once_with(
- connection_info['data']['volume'])
+ get_volume_ref.assert_called_once_with(connection_info['data'])
self.assertTrue(get_vmdk_info.called)
get_vm_state.assert_called_once_with(self._volumeops._session,
instance)
@@ -265,8 +267,7 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
get_vm_ref.assert_called_once_with(self._volumeops._session,
instance)
- get_volume_ref.assert_called_once_with(
- connection_info['data']['volume'])
+ get_volume_ref.assert_called_once_with(connection_info['data'])
get_vmdk_backed_disk_device.assert_called_once_with(
mock.sentinel.vm_ref, connection_info['data'])
adapter_type = vm_util.CONTROLLER_TO_ADAPTER_TYPE.get(
@@ -315,8 +316,7 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
get_vm_ref.assert_called_once_with(self._volumeops._session,
instance)
- get_volume_ref.assert_called_once_with(
- connection_info['data']['volume'])
+ get_volume_ref.assert_called_once_with(connection_info['data'])
get_vmdk_backed_disk_device.assert_called_once_with(
mock.sentinel.vm_ref, connection_info['data'])
get_vm_state.assert_called_once_with(self._volumeops._session,
@@ -406,6 +406,57 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
get_rdm_disk.assert_called_once_with(hardware_devices, disk_uuid)
self.assertFalse(detach_disk_from_vm.called)
+ @mock.patch.object(vm_util, 'get_vm_ref')
+ @mock.patch.object(vm_util, 'get_vm_state')
+ @mock.patch.object(vm_util, 'detach_fcd')
+ def _test__detach_volume_fcd(
+ self, detach_fcd, get_vm_state, get_vm_ref,
+ adapter_type=constants.ADAPTER_TYPE_IDE, powered_off=True):
+ vm_ref = mock.sentinel.vm_ref
+ get_vm_ref.return_value = vm_ref
+
+ if adapter_type == constants.ADAPTER_TYPE_IDE:
+ get_vm_state.return_value = (
+ power_state.SHUTDOWN if powered_off else power_state.RUNNING)
+
+ fcd_id = mock.sentinel.fcd_id
+ ds_ref_val = mock.sentinel.ds_ref_val
+ connection_info = {'data': {'id': fcd_id,
+ 'ds_ref_val': ds_ref_val,
+ 'adapter_type': adapter_type}}
+ instance = mock.sentinel.instance
+
+ if adapter_type == constants.ADAPTER_TYPE_IDE and not powered_off:
+ self.assertRaises(exception.Invalid,
+ self._volumeops._detach_volume_fcd,
+ connection_info,
+ instance)
+ detach_fcd.assert_not_called()
+ else:
+ self._volumeops._detach_volume_fcd(connection_info, instance)
+ detach_fcd.assert_called_once_with(
+ self._volumeops._session, vm_ref, fcd_id)
+
+ @ddt.data(
+ constants.ADAPTER_TYPE_BUSLOGIC, constants.ADAPTER_TYPE_IDE,
+ constants.ADAPTER_TYPE_LSILOGICSAS, constants.ADAPTER_TYPE_PARAVIRTUAL)
+ def test_detach_volume_fcd_powered_off_instance(self, adapter_type):
+ self._test__detach_volume_fcd(adapter_type=adapter_type)
+
+ @ddt.data(
+ constants.ADAPTER_TYPE_BUSLOGIC, constants.ADAPTER_TYPE_IDE,
+ constants.ADAPTER_TYPE_LSILOGICSAS, constants.ADAPTER_TYPE_PARAVIRTUAL)
+ def test_detach_volume_fcd_powered_on_instance(self, adapter_type):
+ self._test__detach_volume_fcd(adapter_type=adapter_type,
+ powered_off=False)
+
+ @mock.patch.object(volumeops.VMwareVolumeOps, '_detach_volume_fcd')
+ def test_detach_volume_fcd(self, detach_volume_fcd):
+ connection_info = {'driver_volume_type': constants.DISK_FORMAT_FCD}
+ instance = mock.sentinel.instance
+ self._volumeops.detach_volume(connection_info, instance)
+ detach_volume_fcd.assert_called_once_with(connection_info, instance)
+
def _test_attach_volume_vmdk(self, adapter_type=None):
connection_info = {'driver_volume_type': constants.DISK_FORMAT_VMDK,
'serial': 'volume-fake-id',
@@ -444,8 +495,7 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
get_vm_ref.assert_called_once_with(self._volumeops._session,
self._instance)
- get_volume_ref.assert_called_once_with(
- connection_info['data']['volume'])
+ get_volume_ref.assert_called_once_with(connection_info['data'])
self.assertTrue(get_vmdk_info.called)
attach_disk_to_vm.assert_called_once_with(
vm_ref, self._instance, adapter_type,
@@ -498,6 +548,126 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
constants.ADAPTER_TYPE_PARAVIRTUAL):
self._test_attach_volume_vmdk(adapter_type)
+ @mock.patch.object(vm_util, 'allocate_controller_key_and_unit_number')
+ def test_get_controller_key_and_unit(
+ self, allocate_controller_key_and_unit_number):
+ key = mock.sentinel.key
+ unit = mock.sentinel.unit
+ allocate_controller_key_and_unit_number.return_value = (
+ key, unit, None)
+
+ with mock.patch.object(self._volumeops, '_session') as session:
+ devices = mock.sentinel.devices
+ session._call_method.return_value = devices
+
+ vm_ref = mock.sentinel.vm_ref
+ adapter_type = mock.sentinel.adapter_type
+ ret = self._volumeops._get_controller_key_and_unit(
+ vm_ref, adapter_type)
+ self.assertEqual((key, unit, None), ret)
+ session._call_method.assert_called_once_with(
+ vutil, 'get_object_property', vm_ref, 'config.hardware.device')
+ allocate_controller_key_and_unit_number.assert_called_once_with(
+ session.vim.client.factory, devices, adapter_type)
+
+ @mock.patch.object(volumeops.VMwareVolumeOps,
+ '_get_controller_key_and_unit')
+ @mock.patch.object(vm_util, 'reconfigure_vm')
+ @mock.patch.object(vm_util, 'attach_fcd')
+ def _test_attach_fcd(
+ self, attach_fcd, reconfigure_vm, get_controller_key_and_unit,
+ existing_controller=True):
+ key = mock.sentinel.key
+ unit = mock.sentinel.unit
+ spec = mock.sentinel.spec
+ if existing_controller:
+ get_controller_key_and_unit.return_value = (key, unit, None)
+ else:
+ get_controller_key_and_unit.side_effect = [(None, None, spec),
+ (key, unit, None)]
+
+ with mock.patch.object(self._volumeops, '_session') as session:
+ config_spec = mock.Mock()
+ session.vim.client.factory.create.return_value = config_spec
+
+ vm_ref = mock.sentinel.vm_ref
+ adapter_type = mock.sentinel.adapter_type
+ fcd_id = mock.sentinel.fcd_id
+ ds_ref_val = mock.sentinel.ds_ref_val
+ self._volumeops._attach_fcd(
+ vm_ref, adapter_type, fcd_id, ds_ref_val)
+
+ attach_fcd.assert_called_once_with(
+ session, vm_ref, fcd_id, ds_ref_val, key, unit)
+ if existing_controller:
+ get_controller_key_and_unit.assert_called_once_with(
+ vm_ref, adapter_type)
+ reconfigure_vm.assert_not_called()
+ else:
+ exp_calls = [mock.call(vm_ref, adapter_type),
+ mock.call(vm_ref, adapter_type)]
+ get_controller_key_and_unit.assert_has_calls(exp_calls)
+ self.assertEqual([spec], config_spec.deviceChange)
+ reconfigure_vm.assert_called_once_with(
+ session, vm_ref, config_spec)
+
+ def test_attach_fcd_using_existing_controller(self):
+ self._test_attach_fcd()
+
+ def test_attach_fcd_using_new_controller(self):
+ self._test_attach_fcd(existing_controller=False)
+
+ @mock.patch.object(vm_util, 'get_vm_ref')
+ @mock.patch.object(vm_util, 'get_vm_state')
+ @mock.patch.object(volumeops.VMwareVolumeOps, '_attach_fcd')
+ def _test__attach_volume_fcd(
+ self, attach_fcd, get_vm_state, get_vm_ref,
+ adapter_type=constants.ADAPTER_TYPE_IDE, powered_off=True):
+ vm_ref = mock.sentinel.vm_ref
+ get_vm_ref.return_value = vm_ref
+
+ if adapter_type == constants.ADAPTER_TYPE_IDE:
+ get_vm_state.return_value = (
+ power_state.SHUTDOWN if powered_off else power_state.RUNNING)
+
+ fcd_id = mock.sentinel.fcd_id
+ ds_ref_val = mock.sentinel.ds_ref_val
+ connection_info = {'data': {'id': fcd_id,
+ 'ds_ref_val': ds_ref_val,
+ 'adapter_type': adapter_type}}
+ instance = mock.sentinel.instance
+
+ if adapter_type == constants.ADAPTER_TYPE_IDE and not powered_off:
+ self.assertRaises(exception.Invalid,
+ self._volumeops._attach_volume_fcd,
+ connection_info,
+ instance)
+ attach_fcd.assert_not_called()
+ else:
+ self._volumeops._attach_volume_fcd(connection_info, instance)
+ attach_fcd.assert_called_once_with(
+ vm_ref, adapter_type, fcd_id, ds_ref_val)
+
+ @ddt.data(
+ constants.ADAPTER_TYPE_BUSLOGIC, constants.ADAPTER_TYPE_IDE,
+ constants.ADAPTER_TYPE_LSILOGICSAS, constants.ADAPTER_TYPE_PARAVIRTUAL)
+ def test_attach_volume_fcd_powered_off_instance(self, adapter_type):
+ self._test__attach_volume_fcd(adapter_type=adapter_type)
+
+ @ddt.data(
+ constants.ADAPTER_TYPE_BUSLOGIC, constants.ADAPTER_TYPE_IDE,
+ constants.ADAPTER_TYPE_LSILOGICSAS, constants.ADAPTER_TYPE_PARAVIRTUAL)
+ def test_attach_volume_fcd_powered_on_instance(self, adapter_type):
+ self._test__attach_volume_fcd(adapter_type=adapter_type,
+ powered_off=False)
+
+ @mock.patch.object(volumeops.VMwareVolumeOps, '_attach_volume_fcd')
+ def test_attach_volume_fcd(self, attach_volume_fcd):
+ connection_info = {'driver_volume_type': constants.DISK_FORMAT_FCD}
+ instance = mock.sentinel.instance
+ self._volumeops.attach_volume(connection_info, instance)
+ attach_volume_fcd.assert_called_once_with(connection_info, instance)
+
def test_attach_volume_iscsi(self):
for adapter_type in (None, constants.DEFAULT_ADAPTER_TYPE,
constants.ADAPTER_TYPE_BUSLOGIC,