summaryrefslogtreecommitdiff
path: root/nova
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2014-07-18 17:55:05 +0000
committerGerrit Code Review <review@openstack.org>2014-07-18 17:55:05 +0000
commitff756a0184806a30902d5e68a8f30345b54a6ed1 (patch)
treefc7d8c94976e5b665a31af72eb75dad71efb8c75 /nova
parenta62aae8d54ebda9206febce07680e82480b75f59 (diff)
parentfc8a70a02a18ecc26d9cbc24deee1efe23603ecc (diff)
downloadnova-ff756a0184806a30902d5e68a8f30345b54a6ed1.tar.gz
Merge "VMware: consolidate datastore code"
Diffstat (limited to 'nova')
-rw-r--r--nova/tests/virt/vmwareapi/test_ds_util.py97
-rw-r--r--nova/tests/virt/vmwareapi/test_ds_util_datastore_selection.py (renamed from nova/tests/virt/vmwareapi/test_vm_util_datastore_selection.py)17
-rw-r--r--nova/tests/virt/vmwareapi/test_vm_util.py96
-rw-r--r--nova/tests/virt/vmwareapi/test_vmops.py2
-rw-r--r--nova/virt/vmwareapi/ds_util.py149
-rw-r--r--nova/virt/vmwareapi/host.py3
-rw-r--r--nova/virt/vmwareapi/vm_util.py142
-rw-r--r--nova/virt/vmwareapi/vmops.py6
8 files changed, 265 insertions, 247 deletions
diff --git a/nova/tests/virt/vmwareapi/test_ds_util.py b/nova/tests/virt/vmwareapi/test_ds_util.py
index 06fd242022..2b957e1c5f 100644
--- a/nova/tests/virt/vmwareapi/test_ds_util.py
+++ b/nova/tests/virt/vmwareapi/test_ds_util.py
@@ -13,9 +13,12 @@
# under the License.
import contextlib
+import re
import mock
+from nova import exception
+from nova.openstack.common.gettextutils import _
from nova.openstack.common import units
from nova import test
from nova.tests.virt.vmwareapi import fake
@@ -157,6 +160,100 @@ class DsUtilTestCase(test.NoDBTestCase):
'fake-browser', 'fake-path', 'fake-file')
self.assertFalse(file_exists)
+ def test_get_datastore(self):
+ fake_objects = fake.FakeRetrieveResult()
+ fake_objects.add_object(fake.Datastore())
+ result = ds_util.get_datastore(
+ fake.FakeObjectRetrievalSession(fake_objects))
+
+ self.assertEqual("fake-ds", result.name)
+ self.assertEqual(units.Ti, result.capacity)
+ self.assertEqual(500 * units.Gi, result.freespace)
+
+ def test_get_datastore_with_regex(self):
+ # Test with a regex that matches with a datastore
+ datastore_valid_regex = re.compile("^openstack.*\d$")
+ fake_objects = fake.FakeRetrieveResult()
+ fake_objects.add_object(fake.Datastore("openstack-ds0"))
+ fake_objects.add_object(fake.Datastore("fake-ds0"))
+ fake_objects.add_object(fake.Datastore("fake-ds1"))
+ result = ds_util.get_datastore(
+ fake.FakeObjectRetrievalSession(fake_objects), None, None,
+ datastore_valid_regex)
+ self.assertEqual("openstack-ds0", result.name)
+
+ def test_get_datastore_with_token(self):
+ regex = re.compile("^ds.*\d$")
+ fake0 = fake.FakeRetrieveResult()
+ fake0.add_object(fake.Datastore("ds0", 10 * units.Gi, 5 * units.Gi))
+ fake0.add_object(fake.Datastore("foo", 10 * units.Gi, 9 * units.Gi))
+ setattr(fake0, 'token', 'token-0')
+ fake1 = fake.FakeRetrieveResult()
+ fake1.add_object(fake.Datastore("ds2", 10 * units.Gi, 8 * units.Gi))
+ fake1.add_object(fake.Datastore("ds3", 10 * units.Gi, 1 * units.Gi))
+ result = ds_util.get_datastore(
+ fake.FakeObjectRetrievalSession(fake0, fake1), None, None, regex)
+ self.assertEqual("ds2", result.name)
+
+ def test_get_datastore_with_list(self):
+ # Test with a regex containing whitelist of datastores
+ datastore_valid_regex = re.compile("(openstack-ds0|openstack-ds2)")
+ fake_objects = fake.FakeRetrieveResult()
+ fake_objects.add_object(fake.Datastore("openstack-ds0"))
+ fake_objects.add_object(fake.Datastore("openstack-ds1"))
+ fake_objects.add_object(fake.Datastore("openstack-ds2"))
+ result = ds_util.get_datastore(
+ fake.FakeObjectRetrievalSession(fake_objects), None, None,
+ datastore_valid_regex)
+ self.assertNotEqual("openstack-ds1", result.name)
+
+ def test_get_datastore_with_regex_error(self):
+ # Test with a regex that has no match
+ # Checks if code raises DatastoreNotFound with a specific message
+ datastore_invalid_regex = re.compile("unknown-ds")
+ exp_message = (_("Datastore regex %s did not match any datastores")
+ % datastore_invalid_regex.pattern)
+ fake_objects = fake.FakeRetrieveResult()
+ fake_objects.add_object(fake.Datastore("fake-ds0"))
+ fake_objects.add_object(fake.Datastore("fake-ds1"))
+ # assertRaisesRegExp would have been a good choice instead of
+ # try/catch block, but it's available only from Py 2.7.
+ try:
+ ds_util.get_datastore(
+ fake.FakeObjectRetrievalSession(fake_objects), None, None,
+ datastore_invalid_regex)
+ except exception.DatastoreNotFound as e:
+ self.assertEqual(exp_message, e.args[0])
+ else:
+ self.fail("DatastoreNotFound Exception was not raised with "
+ "message: %s" % exp_message)
+
+ def test_get_datastore_without_datastore(self):
+
+ self.assertRaises(exception.DatastoreNotFound,
+ ds_util.get_datastore,
+ fake.FakeObjectRetrievalSession(None), host="fake-host")
+
+ self.assertRaises(exception.DatastoreNotFound,
+ ds_util.get_datastore,
+ fake.FakeObjectRetrievalSession(None), cluster="fake-cluster")
+
+ def test_get_datastore_no_host_in_cluster(self):
+ self.assertRaises(exception.DatastoreNotFound,
+ ds_util.get_datastore,
+ fake.FakeObjectRetrievalSession(""), 'fake_cluster')
+
+ def test_get_datastore_inaccessible_ds(self):
+ data_store = fake.Datastore()
+ data_store.set("summary.accessible", False)
+
+ fake_objects = fake.FakeRetrieveResult()
+ fake_objects.add_object(data_store)
+
+ self.assertRaises(exception.DatastoreNotFound,
+ ds_util.get_datastore,
+ fake.FakeObjectRetrievalSession(fake_objects))
+
class DatastoreTestCase(test.NoDBTestCase):
def test_ds(self):
diff --git a/nova/tests/virt/vmwareapi/test_vm_util_datastore_selection.py b/nova/tests/virt/vmwareapi/test_ds_util_datastore_selection.py
index b988b57486..c34e76f4c2 100644
--- a/nova/tests/virt/vmwareapi/test_vm_util_datastore_selection.py
+++ b/nova/tests/virt/vmwareapi/test_ds_util_datastore_selection.py
@@ -17,7 +17,6 @@ import re
from nova.openstack.common import units
from nova import test
from nova.virt.vmwareapi import ds_util
-from nova.virt.vmwareapi import vm_util
ResultSet = collections.namedtuple('ResultSet', ['objects'])
ResultSetToken = collections.namedtuple('ResultSet', ['objects', 'token'])
@@ -26,10 +25,10 @@ DynamicProperty = collections.namedtuple('Property', ['name', 'val'])
MoRef = collections.namedtuple('ManagedObjectReference', ['value'])
-class VMwareVMUtilDatastoreSelectionTestCase(test.NoDBTestCase):
+class VMwareDSUtilDatastoreSelectionTestCase(test.NoDBTestCase):
def setUp(self):
- super(VMwareVMUtilDatastoreSelectionTestCase, self).setUp()
+ super(VMwareDSUtilDatastoreSelectionTestCase, self).setUp()
self.data = [
['VMFS', 'os-some-name', True, 987654321, 12346789],
['NFS', 'another-name', True, 9876543210, 123467890],
@@ -63,7 +62,7 @@ class VMwareVMUtilDatastoreSelectionTestCase(test.NoDBTestCase):
datastores = self.build_result_set(self.data)
best_match = ds_util.Datastore(ref='fake_ref', name='ds',
capacity=0, freespace=0)
- rec = vm_util._select_datastore(datastores, best_match)
+ rec = ds_util._select_datastore(datastores, best_match)
self.assertIsNotNone(rec.ref, "could not find datastore!")
self.assertEqual('ds-001', rec.ref.value,
@@ -77,7 +76,7 @@ class VMwareVMUtilDatastoreSelectionTestCase(test.NoDBTestCase):
best_match = ds_util.Datastore(ref='fake_ref', name='ds',
capacity=0, freespace=0)
- rec = vm_util._select_datastore(datastores, best_match)
+ rec = ds_util._select_datastore(datastores, best_match)
self.assertEqual(rec, best_match)
@@ -87,7 +86,7 @@ class VMwareVMUtilDatastoreSelectionTestCase(test.NoDBTestCase):
best_match = ds_util.Datastore(ref='fake_ref', name='ds',
capacity=0, freespace=0)
- rec = vm_util._select_datastore(datastores,
+ rec = ds_util._select_datastore(datastores,
best_match,
datastore_regex)
@@ -108,7 +107,7 @@ class VMwareVMUtilDatastoreSelectionTestCase(test.NoDBTestCase):
best_match = ds_util.Datastore(ref='fake_ref', name='ds',
capacity=0, freespace=0)
- rec = vm_util._select_datastore(datastores,
+ rec = ds_util._select_datastore(datastores,
best_match,
datastore_regex)
@@ -135,7 +134,7 @@ class VMwareVMUtilDatastoreSelectionTestCase(test.NoDBTestCase):
best_match = ds_util.Datastore(ref='fake_ref', name='ds',
capacity=0, freespace=0)
- rec = vm_util._select_datastore(datastores, best_match)
+ rec = ds_util._select_datastore(datastores, best_match)
self.assertEqual(rec, best_match, "no matches were expected")
def test_filter_datastores_best_match(self):
@@ -153,7 +152,7 @@ class VMwareVMUtilDatastoreSelectionTestCase(test.NoDBTestCase):
# the current best match is better than all candidates
best_match = ds_util.Datastore(ref='ds-100', name='best-ds-good',
capacity=20 * units.Gi, freespace=19 * units.Gi)
- rec = vm_util._select_datastore(datastores,
+ rec = ds_util._select_datastore(datastores,
best_match,
datastore_regex)
self.assertEqual(rec, best_match, "did not match datastore properly")
diff --git a/nova/tests/virt/vmwareapi/test_vm_util.py b/nova/tests/virt/vmwareapi/test_vm_util.py
index d6d7285fae..0e7f30f1e2 100644
--- a/nova/tests/virt/vmwareapi/test_vm_util.py
+++ b/nova/tests/virt/vmwareapi/test_vm_util.py
@@ -22,8 +22,6 @@ import mock
from nova import exception
from nova.network import model as network_model
-from nova.openstack.common.gettextutils import _
-from nova.openstack.common import units
from nova.openstack.common import uuidutils
from nova import test
from nova.tests.virt.vmwareapi import fake
@@ -47,28 +45,6 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
super(VMwareVMUtilTestCase, self).tearDown()
fake.reset()
- def test_get_datastore(self):
- fake_objects = fake.FakeRetrieveResult()
- fake_objects.add_object(fake.Datastore())
- result = vm_util.get_datastore(
- fake.FakeObjectRetrievalSession(fake_objects))
-
- self.assertEqual("fake-ds", result.name)
- self.assertEqual(units.Ti, result.capacity)
- self.assertEqual(500 * units.Gi, result.freespace)
-
- def test_get_datastore_with_regex(self):
- # Test with a regex that matches with a datastore
- datastore_valid_regex = re.compile("^openstack.*\d$")
- fake_objects = fake.FakeRetrieveResult()
- fake_objects.add_object(fake.Datastore("openstack-ds0"))
- fake_objects.add_object(fake.Datastore("fake-ds0"))
- fake_objects.add_object(fake.Datastore("fake-ds1"))
- result = vm_util.get_datastore(
- fake.FakeObjectRetrievalSession(fake_objects),
- None, None, datastore_valid_regex)
- self.assertEqual("openstack-ds0", result.name)
-
def _test_get_stats_from_cluster(self, connection_state="connected",
maintenance_mode=False):
ManagedObjectRefs = [fake.ManagedObjectReference("host1",
@@ -148,62 +124,6 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
def test_get_stats_from_cluster_hosts_connected_and_maintenance(self):
self._test_get_stats_from_cluster(maintenance_mode=True)
- def test_get_datastore_with_token(self):
- regex = re.compile("^ds.*\d$")
- fake0 = fake.FakeRetrieveResult()
- fake0.add_object(fake.Datastore("ds0", 10 * units.Gi, 5 * units.Gi))
- fake0.add_object(fake.Datastore("foo", 10 * units.Gi, 9 * units.Gi))
- setattr(fake0, 'token', 'token-0')
- fake1 = fake.FakeRetrieveResult()
- fake1.add_object(fake.Datastore("ds2", 10 * units.Gi, 8 * units.Gi))
- fake1.add_object(fake.Datastore("ds3", 10 * units.Gi, 1 * units.Gi))
- result = vm_util.get_datastore(
- fake.FakeObjectRetrievalSession(fake0, fake1), None, None, regex)
- self.assertEqual("ds2", result.name)
-
- def test_get_datastore_with_list(self):
- # Test with a regex containing whitelist of datastores
- datastore_valid_regex = re.compile("(openstack-ds0|openstack-ds2)")
- fake_objects = fake.FakeRetrieveResult()
- fake_objects.add_object(fake.Datastore("openstack-ds0"))
- fake_objects.add_object(fake.Datastore("openstack-ds1"))
- fake_objects.add_object(fake.Datastore("openstack-ds2"))
- result = vm_util.get_datastore(
- fake.FakeObjectRetrievalSession(fake_objects),
- None, None, datastore_valid_regex)
- self.assertNotEqual("openstack-ds1", result.name)
-
- def test_get_datastore_with_regex_error(self):
- # Test with a regex that has no match
- # Checks if code raises DatastoreNotFound with a specific message
- datastore_invalid_regex = re.compile("unknown-ds")
- exp_message = (_("Datastore regex %s did not match any datastores")
- % datastore_invalid_regex.pattern)
- fake_objects = fake.FakeRetrieveResult()
- fake_objects.add_object(fake.Datastore("fake-ds0"))
- fake_objects.add_object(fake.Datastore("fake-ds1"))
- # assertRaisesRegExp would have been a good choice instead of
- # try/catch block, but it's available only from Py 2.7.
- try:
- vm_util.get_datastore(
- fake.FakeObjectRetrievalSession(fake_objects), None, None,
- datastore_invalid_regex)
- except exception.DatastoreNotFound as e:
- self.assertEqual(exp_message, e.args[0])
- else:
- self.fail("DatastoreNotFound Exception was not raised with "
- "message: %s" % exp_message)
-
- def test_get_datastore_without_datastore(self):
-
- self.assertRaises(exception.DatastoreNotFound,
- vm_util.get_datastore,
- fake.FakeObjectRetrievalSession(None), host="fake-host")
-
- self.assertRaises(exception.DatastoreNotFound,
- vm_util.get_datastore,
- fake.FakeObjectRetrievalSession(None), cluster="fake-cluster")
-
def test_get_host_ref_from_id(self):
fake_host_name = "ha-host"
fake_host_sys = fake.HostSystem(fake_host_name)
@@ -226,11 +146,6 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
vm_util.get_host_ref,
fake.FakeObjectRetrievalSession(""), 'fake_cluster')
- def test_get_datastore_no_host_in_cluster(self):
- self.assertRaises(exception.DatastoreNotFound,
- vm_util.get_datastore,
- fake.FakeObjectRetrievalSession(""), 'fake_cluster')
-
@mock.patch.object(vm_util, '_get_vm_ref_from_vm_uuid',
return_value=None)
def test_get_host_name_for_vm(self, _get_ref_from_uuid):
@@ -305,17 +220,6 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
self.assertIsNotNone(prop4)
self.assertEqual('bar1', prop4.val)
- def test_get_datastore_inaccessible_ds(self):
- data_store = fake.Datastore()
- data_store.set("summary.accessible", False)
-
- fake_objects = fake.FakeRetrieveResult()
- fake_objects.add_object(data_store)
-
- self.assertRaises(exception.DatastoreNotFound,
- vm_util.get_datastore,
- fake.FakeObjectRetrievalSession(fake_objects))
-
def test_get_resize_spec(self):
fake_instance = {'id': 7, 'name': 'fake!',
'uuid': 'bda5fb9e-b347-40e8-8256-42397848cb00',
diff --git a/nova/tests/virt/vmwareapi/test_vmops.py b/nova/tests/virt/vmwareapi/test_vmops.py
index 6d1b221f20..a093bff658 100644
--- a/nova/tests/virt/vmwareapi/test_vmops.py
+++ b/nova/tests/virt/vmwareapi/test_vmops.py
@@ -569,7 +569,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
recorded_methods = [c[1][1] for c in mock_call_method.mock_calls]
self.assertEqual(expected_methods, recorded_methods)
- @mock.patch('nova.virt.vmwareapi.vm_util.get_datastore')
+ @mock.patch('nova.virt.vmwareapi.ds_util.get_datastore')
@mock.patch(
'nova.virt.vmwareapi.vmops.VMwareVCVMOps.get_datacenter_ref_and_name')
@mock.patch('nova.virt.vmwareapi.vm_util.get_mo_id_from_instance',
diff --git a/nova/virt/vmwareapi/ds_util.py b/nova/virt/vmwareapi/ds_util.py
index ad3fa1eda7..cc76b9a700 100644
--- a/nova/virt/vmwareapi/ds_util.py
+++ b/nova/virt/vmwareapi/ds_util.py
@@ -17,9 +17,12 @@ Datastore utility functions
"""
import posixpath
+from nova import exception
from nova.openstack.common.gettextutils import _
from nova.openstack.common import log as logging
from nova.virt.vmwareapi import error_util
+from nova.virt.vmwareapi import vim_util
+from nova.virt.vmwareapi import vm_util
LOG = logging.getLogger(__name__)
@@ -158,6 +161,152 @@ def build_datastore_path(datastore_name, path):
return str(DatastorePath(datastore_name, path))
+# NOTE(mdbooth): this convenience function is temporarily duplicated in
+# vm_util. The correct fix is to handle paginated results as they are returned
+# from the relevant vim_util function. However, vim_util is currently
+# effectively deprecated as we migrate to oslo.vmware. This duplication will be
+# removed when we fix it properly in oslo.vmware.
+def _get_token(results):
+ """Get the token from the property results."""
+ return getattr(results, 'token', None)
+
+
+def _select_datastore(data_stores, best_match, datastore_regex=None):
+ """Find the most preferable datastore in a given RetrieveResult object.
+
+ :param data_stores: a RetrieveResult object from vSphere API call
+ :param best_match: the current best match for datastore
+ :param datastore_regex: an optional regular expression to match names
+ :return: datastore_ref, datastore_name, capacity, freespace
+ """
+
+ # data_stores is actually a RetrieveResult object from vSphere API call
+ for obj_content in data_stores.objects:
+ # the propset attribute "need not be set" by returning API
+ if not hasattr(obj_content, 'propSet'):
+ continue
+
+ propdict = vm_util.propset_dict(obj_content.propSet)
+ # Local storage identifier vSphere doesn't support CIFS or
+ # vfat for datastores, therefore filtered
+ ds_type = propdict['summary.type']
+ ds_name = propdict['summary.name']
+ if ((ds_type == 'VMFS' or ds_type == 'NFS') and
+ propdict.get('summary.accessible')):
+ if datastore_regex is None or datastore_regex.match(ds_name):
+ new_ds = Datastore(
+ ref=obj_content.obj,
+ name=ds_name,
+ capacity=propdict['summary.capacity'],
+ freespace=propdict['summary.freeSpace'])
+ # favor datastores with more free space
+ if (best_match is None or
+ new_ds.freespace > best_match.freespace):
+ best_match = new_ds
+
+ return best_match
+
+
+def get_datastore(session, cluster=None, host=None, datastore_regex=None):
+ """Get the datastore list and choose the most preferable one."""
+ if cluster is None and host is None:
+ data_stores = session._call_method(vim_util, "get_objects",
+ "Datastore", ["summary.type", "summary.name",
+ "summary.capacity", "summary.freeSpace",
+ "summary.accessible"])
+ else:
+ if cluster is not None:
+ datastore_ret = session._call_method(
+ vim_util,
+ "get_dynamic_property", cluster,
+ "ClusterComputeResource", "datastore")
+ else:
+ datastore_ret = session._call_method(
+ vim_util,
+ "get_dynamic_property", host,
+ "HostSystem", "datastore")
+
+ if not datastore_ret:
+ raise exception.DatastoreNotFound()
+ data_store_mors = datastore_ret.ManagedObjectReference
+ data_stores = session._call_method(vim_util,
+ "get_properties_for_a_collection_of_objects",
+ "Datastore", data_store_mors,
+ ["summary.type", "summary.name",
+ "summary.capacity", "summary.freeSpace",
+ "summary.accessible"])
+ best_match = None
+ while data_stores:
+ best_match = _select_datastore(data_stores, best_match,
+ datastore_regex)
+ token = _get_token(data_stores)
+ if not token:
+ break
+ data_stores = session._call_method(vim_util,
+ "continue_to_get_objects",
+ token)
+ if best_match:
+ return best_match
+ if datastore_regex:
+ raise exception.DatastoreNotFound(
+ _("Datastore regex %s did not match any datastores")
+ % datastore_regex.pattern)
+ else:
+ raise exception.DatastoreNotFound()
+
+
+def _get_allowed_datastores(data_stores, datastore_regex, allowed_types):
+ allowed = []
+ for obj_content in data_stores.objects:
+ # the propset attribute "need not be set" by returning API
+ if not hasattr(obj_content, 'propSet'):
+ continue
+
+ propdict = vm_util.propset_dict(obj_content.propSet)
+ # Local storage identifier vSphere doesn't support CIFS or
+ # vfat for datastores, therefore filtered
+ ds_type = propdict['summary.type']
+ ds_name = propdict['summary.name']
+ if (propdict['summary.accessible'] and ds_type in allowed_types):
+ if datastore_regex is None or datastore_regex.match(ds_name):
+ allowed.append({'ref': obj_content.obj, 'name': ds_name})
+
+ return allowed
+
+
+def get_available_datastores(session, cluster=None, datastore_regex=None):
+ """Get the datastore list and choose the first local storage."""
+ if cluster:
+ mobj = cluster
+ resource_type = "ClusterComputeResource"
+ else:
+ mobj = vm_util.get_host_ref(session)
+ resource_type = "HostSystem"
+ ds = session._call_method(vim_util, "get_dynamic_property", mobj,
+ resource_type, "datastore")
+ if not ds:
+ return []
+ data_store_mors = ds.ManagedObjectReference
+ # NOTE(garyk): use utility method to retrieve remote objects
+ data_stores = session._call_method(vim_util,
+ "get_properties_for_a_collection_of_objects",
+ "Datastore", data_store_mors,
+ ["summary.type", "summary.name", "summary.accessible"])
+
+ allowed = []
+ while data_stores:
+ allowed.extend(_get_allowed_datastores(data_stores, datastore_regex,
+ ['VMFS', 'NFS']))
+ token = _get_token(data_stores)
+ if not token:
+ break
+
+ data_stores = session._call_method(vim_util,
+ "continue_to_get_objects",
+ token)
+ return allowed
+
+
def file_delete(session, datastore_path, dc_ref):
LOG.debug("Deleting the datastore file %s", datastore_path)
vim = session._get_vim()
diff --git a/nova/virt/vmwareapi/host.py b/nova/virt/vmwareapi/host.py
index b1be80803c..ba9a01de75 100644
--- a/nova/virt/vmwareapi/host.py
+++ b/nova/virt/vmwareapi/host.py
@@ -21,6 +21,7 @@ from nova import exception
from nova.openstack.common import log as logging
from nova.openstack.common import units
from nova import utils
+from nova.virt.vmwareapi import ds_util
from nova.virt.vmwareapi import vim_util
from nova.virt.vmwareapi import vm_util
@@ -80,7 +81,7 @@ class Host(object):
def _get_ds_capacity_and_freespace(session, cluster=None):
try:
- ds = vm_util.get_datastore(session, cluster)
+ ds = ds_util.get_datastore(session, cluster)
return ds.capacity, ds.freespace
except exception.DatastoreNotFound:
return 0, 0
diff --git a/nova/virt/vmwareapi/vm_util.py b/nova/virt/vmwareapi/vm_util.py
index cbeea889e5..f6e3e7adf2 100644
--- a/nova/virt/vmwareapi/vm_util.py
+++ b/nova/virt/vmwareapi/vm_util.py
@@ -30,7 +30,6 @@ from nova.openstack.common import log as logging
from nova.openstack.common import units
from nova import utils
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 vim_util
@@ -689,6 +688,11 @@ def _get_allocated_vnc_ports(session):
return vnc_ports
+# NOTE(mdbooth): this convenience function is temporarily duplicated in
+# ds_util. The correct fix is to handle paginated results as they are returned
+# from the relevant vim_util function. However, vim_util is currently
+# effectively deprecated as we migrate to oslo.vmware. This duplication will be
+# removed when we fix it properly in oslo.vmware.
def _get_token(results):
"""Get the token from the property results."""
return getattr(results, 'token', None)
@@ -1011,142 +1015,6 @@ def propset_dict(propset):
return dict([(prop.name, prop.val) for prop in propset])
-def _select_datastore(data_stores, best_match, datastore_regex=None):
- """Find the most preferable datastore in a given RetrieveResult object.
-
- :param data_stores: a RetrieveResult object from vSphere API call
- :param best_match: the current best match for datastore
- :param datastore_regex: an optional regular expression to match names
- :return: datastore_ref, datastore_name, capacity, freespace
- """
-
- # data_stores is actually a RetrieveResult object from vSphere API call
- for obj_content in data_stores.objects:
- # the propset attribute "need not be set" by returning API
- if not hasattr(obj_content, 'propSet'):
- continue
-
- propdict = propset_dict(obj_content.propSet)
- # Local storage identifier vSphere doesn't support CIFS or
- # vfat for datastores, therefore filtered
- ds_type = propdict['summary.type']
- ds_name = propdict['summary.name']
- if ((ds_type == 'VMFS' or ds_type == 'NFS') and
- propdict.get('summary.accessible')):
- if datastore_regex is None or datastore_regex.match(ds_name):
- new_ds = ds_util.Datastore(
- ref=obj_content.obj,
- name=ds_name,
- capacity=propdict['summary.capacity'],
- freespace=propdict['summary.freeSpace'])
- # favor datastores with more free space
- if (best_match is None or
- new_ds.freespace > best_match.freespace):
- best_match = new_ds
-
- return best_match
-
-
-def get_datastore(session, cluster=None, host=None, datastore_regex=None):
- """Get the datastore list and choose the most preferable one."""
- if cluster is None and host is None:
- data_stores = session._call_method(vim_util, "get_objects",
- "Datastore", ["summary.type", "summary.name",
- "summary.capacity", "summary.freeSpace",
- "summary.accessible"])
- else:
- if cluster is not None:
- datastore_ret = session._call_method(
- vim_util,
- "get_dynamic_property", cluster,
- "ClusterComputeResource", "datastore")
- else:
- datastore_ret = session._call_method(
- vim_util,
- "get_dynamic_property", host,
- "HostSystem", "datastore")
-
- if not datastore_ret:
- raise exception.DatastoreNotFound()
- data_store_mors = datastore_ret.ManagedObjectReference
- data_stores = session._call_method(vim_util,
- "get_properties_for_a_collection_of_objects",
- "Datastore", data_store_mors,
- ["summary.type", "summary.name",
- "summary.capacity", "summary.freeSpace",
- "summary.accessible"])
- best_match = None
- while data_stores:
- best_match = _select_datastore(data_stores, best_match,
- datastore_regex)
- token = _get_token(data_stores)
- if not token:
- break
- data_stores = session._call_method(vim_util,
- "continue_to_get_objects",
- token)
- if best_match:
- return best_match
- if datastore_regex:
- raise exception.DatastoreNotFound(
- _("Datastore regex %s did not match any datastores")
- % datastore_regex.pattern)
- else:
- raise exception.DatastoreNotFound()
-
-
-def _get_allowed_datastores(data_stores, datastore_regex, allowed_types):
- allowed = []
- for obj_content in data_stores.objects:
- # the propset attribute "need not be set" by returning API
- if not hasattr(obj_content, 'propSet'):
- continue
-
- propdict = propset_dict(obj_content.propSet)
- # Local storage identifier vSphere doesn't support CIFS or
- # vfat for datastores, therefore filtered
- ds_type = propdict['summary.type']
- ds_name = propdict['summary.name']
- if (propdict['summary.accessible'] and ds_type in allowed_types):
- if datastore_regex is None or datastore_regex.match(ds_name):
- allowed.append({'ref': obj_content.obj, 'name': ds_name})
-
- return allowed
-
-
-def get_available_datastores(session, cluster=None, datastore_regex=None):
- """Get the datastore list and choose the first local storage."""
- if cluster:
- mobj = cluster
- resource_type = "ClusterComputeResource"
- else:
- mobj = get_host_ref(session)
- resource_type = "HostSystem"
- ds = session._call_method(vim_util, "get_dynamic_property", mobj,
- resource_type, "datastore")
- if not ds:
- return []
- data_store_mors = ds.ManagedObjectReference
- # NOTE(garyk): use utility method to retrieve remote objects
- data_stores = session._call_method(vim_util,
- "get_properties_for_a_collection_of_objects",
- "Datastore", data_store_mors,
- ["summary.type", "summary.name", "summary.accessible"])
-
- allowed = []
- while data_stores:
- allowed.extend(_get_allowed_datastores(data_stores, datastore_regex,
- ['VMFS', 'NFS']))
- token = _get_token(data_stores)
- if not token:
- break
-
- data_stores = session._call_method(vim_util,
- "continue_to_get_objects",
- token)
- return allowed
-
-
def get_vmdk_backed_disk_uuid(hardware_devices, volume_uuid):
if hardware_devices.__class__.__name__ == "ArrayOfVirtualDevice":
hardware_devices = hardware_devices.VirtualDevice
diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py
index 50057315dc..9d7093c7a4 100644
--- a/nova/virt/vmwareapi/vmops.py
+++ b/nova/virt/vmwareapi/vmops.py
@@ -195,7 +195,7 @@ class VMwareVMOps(object):
(file_type, is_iso) = self._get_disk_format(image_meta)
client_factory = self._session._get_vim().client.factory
- datastore = vm_util.get_datastore(
+ datastore = ds_util.get_datastore(
self._session, self._cluster,
datastore_regex=self._datastore_regex)
dc_info = self.get_datacenter_ref_and_name(datastore.ref)
@@ -1156,7 +1156,7 @@ class VMwareVMOps(object):
step=2,
total_steps=RESIZE_TOTAL_STEPS)
- ds_ref = vm_util.get_datastore(
+ ds_ref = ds_util.get_datastore(
self._session, self._cluster, host_ref,
datastore_regex=self._datastore_regex).ref
dc_info = self.get_datacenter_ref_and_name(ds_ref)
@@ -1470,7 +1470,7 @@ class VMwareVMOps(object):
LOG.debug("Image aging disabled. Aging will not be done.")
return
- datastores = vm_util.get_available_datastores(self._session,
+ datastores = ds_util.get_available_datastores(self._session,
self._cluster,
self._datastore_regex)
datastores_info = []