VMware: fix list_instances for multi-node driver

VMwareVCDriver should only list instances in the nodes managed by
it. Currently, it uses the an implementation that lists instances
in the vCenter server inventory even if they are not in the nodes
managed by the driver.

Closes-bug: #1272286
Change-Id: I56c81a759eacc8c595e97ac5ca372834b675ebff
This commit is contained in:
Sabari Kumar Murugesan
2013-10-18 15:42:49 -07:00
committed by Gerrit Code Review
parent 8205093350
commit 923c38c51f
5 changed files with 99 additions and 22 deletions

View File

@@ -1834,6 +1834,22 @@ class VMwareAPIVCDriverTestCase(VMwareAPIVMTestCase):
super(VMwareAPIVCDriverTestCase, self).tearDown()
vmwareapi_fake.cleanup()
def test_list_instances(self):
instances = self.conn.list_instances()
self.assertEqual(0, len(instances))
def test_list_instances_from_nodes(self):
# Create instance on node1
self._create_vm(self.node_name)
# Create instances on the other node
self._create_vm(self.node_name2, num_instances=2)
self._create_vm(self.node_name2, num_instances=3)
node1_vmops = self.conn._get_vmops_for_compute_node(self.node_name)
node2_vmops = self.conn._get_vmops_for_compute_node(self.node_name2)
self.assertEqual(1, len(node1_vmops.list_instances()))
self.assertEqual(2, len(node2_vmops.list_instances()))
self.assertEqual(3, len(self.conn.list_instances()))
def _setup_mocks_for_session(self, mock_init):
mock_init.return_value = None

View File

@@ -180,6 +180,28 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
"folder", "some_file")
ops._create_folder_if_missing.assert_called_once()
def test_get_valid_vms_from_retrieve_result(self):
ops = vmops.VMwareVMOps(mock.Mock(), mock.Mock(), mock.Mock())
fake_objects = vmwareapi_fake.FakeRetrieveResult()
fake_objects.add_object(vmwareapi_fake.VirtualMachine())
fake_objects.add_object(vmwareapi_fake.VirtualMachine())
fake_objects.add_object(vmwareapi_fake.VirtualMachine())
vms = ops._get_valid_vms_from_retrieve_result(fake_objects)
self.assertEqual(3, len(vms))
def test_get_valid_vms_from_retrieve_result_with_invalid(self):
ops = vmops.VMwareVMOps(mock.Mock(), mock.Mock(), mock.Mock())
fake_objects = vmwareapi_fake.FakeRetrieveResult()
fake_objects.add_object(vmwareapi_fake.VirtualMachine())
invalid_vm1 = vmwareapi_fake.VirtualMachine()
invalid_vm1.set('runtime.connectionState', 'orphaned')
invalid_vm2 = vmwareapi_fake.VirtualMachine()
invalid_vm2.set('runtime.connectionState', 'inaccessible')
fake_objects.add_object(invalid_vm1)
fake_objects.add_object(invalid_vm2)
vms = ops._get_valid_vms_from_retrieve_result(fake_objects)
self.assertEqual(1, len(vms))
def test_delete_vm_snapshot(self):
def fake_call_method(module, method, *args, **kwargs):
self.assertEqual('RemoveSnapshot_Task', method)

View File

@@ -412,6 +412,15 @@ class VMwareVCDriver(VMwareESXDriver):
self._volumeops = self._resources.get(first_cluster).get('volumeops')
self._vc_state = self._resources.get(first_cluster).get('vcstate')
def list_instances(self):
"""List VM instances from all nodes."""
instances = []
nodes = self.get_available_nodes()
for node in nodes:
vmops = self._get_vmops_for_compute_node(node)
instances.extend(vmops.list_instances())
return instances
def migrate_disk_and_power_off(self, context, instance, dest,
flavor, network_info,
block_device_info=None):

View File

@@ -492,6 +492,7 @@ class ResourcePool(ManagedObject):
memoryAllocation = DataObject()
cpuAllocation = DataObject()
vm_list = DataObject()
memory.maxUsage = 1000 * units.Mi
memory.overallUsage = 500 * units.Mi
@@ -505,9 +506,11 @@ class ResourcePool(ManagedObject):
memoryAllocation.reservation = 1024
config.memoryAllocation = memoryAllocation
config.cpuAllocation = cpuAllocation
vm_list.ManagedObjectReference = []
self.set("summary", summary)
self.set("summary.runtime.memory", memory)
self.set("config", config)
self.set("vm", vm_list)
parent = ManagedObjectReference(value=value,
name=name)
owner = ManagedObjectReference(value=value,
@@ -862,6 +865,7 @@ def create_datastore(name, capacity, free):
def create_res_pool():
res_pool = ResourcePool()
_create_object('ResourcePool', res_pool)
return res_pool.obj
def create_network():
@@ -874,7 +878,7 @@ def create_cluster(name, ds_ref):
cluster._add_host(_get_object_refs("HostSystem")[0])
cluster._add_host(_get_object_refs("HostSystem")[1])
cluster._add_datastore(ds_ref)
cluster._add_root_resource_pool(_get_object_refs("ResourcePool")[0])
cluster._add_root_resource_pool(create_res_pool())
_create_object('ClusterComputeResource', cluster)
@@ -1050,6 +1054,7 @@ class FakeVim(object):
def _create_vm(self, method, *args, **kwargs):
"""Creates and registers a VM object with the Host System."""
config_spec = kwargs.get("config")
pool = kwargs.get('pool')
ds = _db_content["Datastore"].keys()[0]
host = _db_content["HostSystem"].keys()[0]
vm_dict = {"name": config_spec.name,
@@ -1064,6 +1069,8 @@ class FakeVim(object):
"instanceUuid": config_spec.instanceUuid}
virtual_machine = VirtualMachine(**vm_dict)
_create_object("VirtualMachine", virtual_machine)
res_pool = _get_object(pool)
res_pool.vm.ManagedObjectReference.append(virtual_machine.obj)
task_mdo = create_task(method, "success")
return task_mdo.obj

View File

@@ -118,27 +118,7 @@ class VMwareVMOps(object):
vms = self._session._call_method(vim_util, "get_objects",
"VirtualMachine",
["name", "runtime.connectionState"])
lst_vm_names = []
while vms:
token = vm_util._get_token(vms)
for vm in vms.objects:
vm_name = None
conn_state = None
for prop in vm.propSet:
if prop.name == "name":
vm_name = prop.val
elif prop.name == "runtime.connectionState":
conn_state = prop.val
# Ignoring the orphaned or inaccessible VMs
if conn_state not in ["orphaned", "inaccessible"]:
lst_vm_names.append(vm_name)
if token:
vms = self._session._call_method(vim_util,
"continue_to_get_objects",
token)
else:
break
lst_vm_names = self._get_valid_vms_from_retrieve_result(vms)
LOG.debug(_("Got total of %s instances") % str(len(lst_vm_names)))
return lst_vm_names
@@ -1667,6 +1647,31 @@ class VMwareVMOps(object):
datastores_info.append((ds, ds_info))
self._imagecache.update(context, instances, datastores_info)
def _get_valid_vms_from_retrieve_result(self, retrieve_result):
"""Returns list of valid vms from RetrieveResult object."""
lst_vm_names = []
while retrieve_result:
token = vm_util._get_token(retrieve_result)
for vm in retrieve_result.objects:
vm_name = None
conn_state = None
for prop in vm.propSet:
if prop.name == "name":
vm_name = prop.val
elif prop.name == "runtime.connectionState":
conn_state = prop.val
# Ignoring the orphaned or inaccessible VMs
if conn_state not in ["orphaned", "inaccessible"]:
lst_vm_names.append(vm_name)
if token:
retrieve_result = self._session._call_method(vim_util,
"continue_to_get_objects",
token)
else:
break
return lst_vm_names
class VMwareVCVMOps(VMwareVMOps):
"""Management class for VM-related tasks.
@@ -1725,3 +1730,21 @@ class VMwareVCVMOps(VMwareVMOps):
self._update_datacenter_cache_from_objects(dcs)
dc_info = self._datastore_dc_mapping.get(ds_ref.value)
return dc_info
def list_instances(self):
"""Lists the VM instances that are registered with vCenter cluster."""
properties = ['name', 'runtime.connectionState']
LOG.debug(_("Getting list of instances from cluster %s"),
self._cluster)
vms = []
root_res_pool = self._session._call_method(
vim_util, "get_dynamic_property", self._cluster,
'ClusterComputeResource', 'resourcePool')
if root_res_pool:
vms = self._session._call_method(
vim_util, 'get_inner_objects', root_res_pool, 'vm',
'VirtualMachine', properties)
lst_vm_names = self._get_valid_vms_from_retrieve_result(vms)
LOG.debug(_("Got total of %s instances") % str(len(lst_vm_names)))
return lst_vm_names