Merge "VMware: consolidate datastore code"
This commit is contained in:
commit
ff756a0184
nova
tests/virt/vmwareapi
virt/vmwareapi
@ -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):
|
||||
|
@ -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")
|
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 = []
|
||||
|
Loading…
x
Reference in New Issue
Block a user