summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2014-08-21 21:30:38 +0000
committerGerrit Code Review <review@openstack.org>2014-08-21 21:30:38 +0000
commit05cc277475d02a4f415e4c5edac76cf7266145ee (patch)
tree18ab7d5ed10883cefa431680c1bcb647743203d1
parente8a91a781b9c594c1baba0f054fc9837b1bf3185 (diff)
parentc5de5e7ab166e29304a01d7e310ae6ed32d22090 (diff)
downloadnova-05cc277475d02a4f415e4c5edac76cf7266145ee.tar.gz
Merge "VMWare Driver - Ignore datastore in maintenance mode"
-rw-r--r--nova/tests/virt/vmwareapi/fake.py6
-rw-r--r--nova/tests/virt/vmwareapi/test_ds_util.py62
-rw-r--r--nova/tests/virt/vmwareapi/test_ds_util_datastore_selection.py25
-rw-r--r--nova/tests/virt/vmwareapi/test_vm_util.py1
-rw-r--r--nova/virt/vmwareapi/ds_util.py68
5 files changed, 124 insertions, 38 deletions
diff --git a/nova/tests/virt/vmwareapi/fake.py b/nova/tests/virt/vmwareapi/fake.py
index e12d917258..43a3754ef9 100644
--- a/nova/tests/virt/vmwareapi/fake.py
+++ b/nova/tests/virt/vmwareapi/fake.py
@@ -636,13 +636,15 @@ class ClusterComputeResource(ManagedObject):
class Datastore(ManagedObject):
"""Datastore class."""
- def __init__(self, name="fake-ds", capacity=1024, free=500):
+ def __init__(self, name="fake-ds", capacity=1024, free=500,
+ accessible=True, maintenance_mode="normal"):
super(Datastore, self).__init__("ds")
self.set("summary.type", "VMFS")
self.set("summary.name", name)
self.set("summary.capacity", capacity * units.Gi)
self.set("summary.freeSpace", free * units.Gi)
- self.set("summary.accessible", True)
+ self.set("summary.accessible", accessible)
+ self.set("summary.maintenanceMode", maintenance_mode)
self.set("browser", "")
diff --git a/nova/tests/virt/vmwareapi/test_ds_util.py b/nova/tests/virt/vmwareapi/test_ds_util.py
index 610fc9110c..1c0aef6470 100644
--- a/nova/tests/virt/vmwareapi/test_ds_util.py
+++ b/nova/tests/virt/vmwareapi/test_ds_util.py
@@ -164,6 +164,10 @@ class DsUtilTestCase(test.NoDBTestCase):
def test_get_datastore(self):
fake_objects = fake.FakeRetrieveResult()
fake_objects.add_object(fake.Datastore())
+ fake_objects.add_object(fake.Datastore("fake-ds-2", 2048, 1000,
+ False, "normal"))
+ fake_objects.add_object(fake.Datastore("fake-ds-3", 4096, 2000,
+ True, "inMaintenance"))
result = ds_util.get_datastore(
fake.FakeObjectRetrievalSession(fake_objects))
@@ -255,6 +259,64 @@ class DsUtilTestCase(test.NoDBTestCase):
ds_util.get_datastore,
fake.FakeObjectRetrievalSession(fake_objects))
+ def test_get_datastore_ds_in_maintenance(self):
+ data_store = fake.Datastore()
+ data_store.set("summary.maintenanceMode", "inMaintenance")
+
+ fake_objects = fake.FakeRetrieveResult()
+ fake_objects.add_object(data_store)
+
+ self.assertRaises(exception.DatastoreNotFound,
+ ds_util.get_datastore,
+ fake.FakeObjectRetrievalSession(fake_objects))
+
+ def _test_is_datastore_valid(self, accessible=True,
+ maintenance_mode="normal",
+ type="VMFS",
+ datastore_regex=None):
+ propdict = {}
+ propdict["summary.accessible"] = accessible
+ propdict["summary.maintenanceMode"] = maintenance_mode
+ propdict["summary.type"] = type
+ propdict["summary.name"] = "ds-1"
+
+ return ds_util._is_datastore_valid(propdict, datastore_regex)
+
+ def test_is_datastore_valid(self):
+ for ds_type in ds_util.ALLOWED_DATASTORE_TYPES:
+ self.assertTrue(self._test_is_datastore_valid(True,
+ "normal",
+ ds_type))
+
+ def test_is_datastore_valid_inaccessible_ds(self):
+ self.assertFalse(self._test_is_datastore_valid(False,
+ "normal",
+ "VMFS"))
+
+ def test_is_datastore_valid_ds_in_maintenance(self):
+ self.assertFalse(self._test_is_datastore_valid(True,
+ "inMaintenance",
+ "VMFS"))
+
+ def test_is_datastore_valid_ds_type_invalid(self):
+ self.assertFalse(self._test_is_datastore_valid(True,
+ "normal",
+ "vfat"))
+
+ def test_is_datastore_valid_not_matching_regex(self):
+ datastore_regex = re.compile("ds-2")
+ self.assertFalse(self._test_is_datastore_valid(True,
+ "normal",
+ "VMFS",
+ datastore_regex))
+
+ def test_is_datastore_valid_matching_regex(self):
+ datastore_regex = re.compile("ds-1")
+ self.assertTrue(self._test_is_datastore_valid(True,
+ "normal",
+ "VMFS",
+ datastore_regex))
+
class DatastoreTestCase(test.NoDBTestCase):
def test_ds(self):
diff --git a/nova/tests/virt/vmwareapi/test_ds_util_datastore_selection.py b/nova/tests/virt/vmwareapi/test_ds_util_datastore_selection.py
index c34e76f4c2..ca211902cf 100644
--- a/nova/tests/virt/vmwareapi/test_ds_util_datastore_selection.py
+++ b/nova/tests/virt/vmwareapi/test_ds_util_datastore_selection.py
@@ -30,10 +30,11 @@ class VMwareDSUtilDatastoreSelectionTestCase(test.NoDBTestCase):
def setUp(self):
super(VMwareDSUtilDatastoreSelectionTestCase, self).setUp()
self.data = [
- ['VMFS', 'os-some-name', True, 987654321, 12346789],
- ['NFS', 'another-name', True, 9876543210, 123467890],
- ['BAD', 'some-name-bad', True, 98765432100, 1234678900],
- ['VMFS', 'some-name-good', False, 987654321, 12346789],
+ ['VMFS', 'os-some-name', True, 'normal', 987654321, 12346789],
+ ['NFS', 'another-name', True, 'normal', 9876543210, 123467890],
+ ['BAD', 'some-name-bad', True, 'normal', 98765432100, 1234678900],
+ ['VMFS', 'some-name-good', False, 'normal', 987654321, 12346789],
+ ['VMFS', 'new-name', True, 'inMaintenance', 987654321, 12346789]
]
def build_result_set(self, mock_data, name_list=None):
@@ -56,7 +57,8 @@ class VMwareDSUtilDatastoreSelectionTestCase(test.NoDBTestCase):
@property
def propset_name_list(self):
return ['summary.type', 'summary.name', 'summary.accessible',
- 'summary.capacity', 'summary.freeSpace']
+ 'summary.maintenanceMode', 'summary.capacity',
+ 'summary.freeSpace']
def test_filter_datastores_simple(self):
datastores = self.build_result_set(self.data)
@@ -95,11 +97,14 @@ class VMwareDSUtilDatastoreSelectionTestCase(test.NoDBTestCase):
def test_filter_datastores_specific_match(self):
data = [
- ['VMFS', 'os-some-name', True, 987654321, 1234678],
- ['NFS', 'another-name', True, 9876543210, 123467890],
- ['BAD', 'some-name-bad', True, 98765432100, 1234678900],
- ['VMFS', 'some-name-good', True, 987654321, 12346789],
- ['VMFS', 'some-other-good', False, 987654321000, 12346789000],
+ ['VMFS', 'os-some-name', True, 'normal', 987654321, 1234678],
+ ['NFS', 'another-name', True, 'normal', 9876543210, 123467890],
+ ['BAD', 'some-name-bad', True, 'normal', 98765432100, 1234678900],
+ ['VMFS', 'some-name-good', True, 'normal', 987654321, 12346789],
+ ['VMFS', 'some-other-good', False, 'normal', 987654321000,
+ 12346789000],
+ ['VMFS', 'new-name', True, 'inMaintenance', 987654321000,
+ 12346789000]
]
# only the DS some-name-good is accessible and matches the regex
datastores = self.build_result_set(data)
diff --git a/nova/tests/virt/vmwareapi/test_vm_util.py b/nova/tests/virt/vmwareapi/test_vm_util.py
index 74fd99debe..5bff7e896d 100644
--- a/nova/tests/virt/vmwareapi/test_vm_util.py
+++ b/nova/tests/virt/vmwareapi/test_vm_util.py
@@ -251,6 +251,7 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
},
'backing': {
'datastore': {
+ "summary.maintenanceMode": "normal",
"summary.type": "VMFS",
"summary.accessible":true,
"summary.name": "fake-ds",
diff --git a/nova/virt/vmwareapi/ds_util.py b/nova/virt/vmwareapi/ds_util.py
index 7b0b25bc20..004f47a562 100644
--- a/nova/virt/vmwareapi/ds_util.py
+++ b/nova/virt/vmwareapi/ds_util.py
@@ -25,6 +25,7 @@ from nova.virt.vmwareapi import vim_util
from nova.virt.vmwareapi import vm_util
LOG = logging.getLogger(__name__)
+ALLOWED_DATASTORE_TYPES = ['VMFS', 'NFS']
class Datastore(object):
@@ -196,33 +197,51 @@ def _select_datastore(data_stores, best_match, datastore_regex=None):
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(
+ if _is_datastore_valid(propdict, datastore_regex):
+ new_ds = Datastore(
ref=obj_content.obj,
- name=ds_name,
+ name=propdict['summary.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
+ # 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 _is_datastore_valid(propdict, datastore_regex):
+ """Checks if a datastore is valid based on the following criteria.
+
+ Criteria:
+ - Datastore is accessible
+ - Datastore is not in maintenance mode (optional)
+ - Datastore is of a supported disk type
+ - Datastore matches the supplied regex (optional)
+
+ :param propdict: datastore summary dict
+ :param datastore_regex : Regex to match the name of a datastore.
+ """
+
+ # Local storage identifier vSphere doesn't support CIFS or
+ # vfat for datastores, therefore filtered
+ return (propdict.get('summary.accessible') and
+ (propdict.get('summary.maintenanceMode') is None or
+ propdict.get('summary.maintenanceMode') == 'normal') and
+ propdict['summary.type'] in ALLOWED_DATASTORE_TYPES and
+ (datastore_regex is None or
+ datastore_regex.match(propdict['summary.name'])))
+
+
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"])
+ "summary.accessible",
+ "summary.maintenanceMode"])
else:
if cluster is not None:
datastore_ret = session._call_method(
@@ -243,7 +262,8 @@ def get_datastore(session, cluster=None, host=None, datastore_regex=None):
"Datastore", data_store_mors,
["summary.type", "summary.name",
"summary.capacity", "summary.freeSpace",
- "summary.accessible"])
+ "summary.accessible",
+ "summary.maintenanceMode"])
best_match = None
while data_stores:
best_match = _select_datastore(data_stores, best_match,
@@ -264,7 +284,7 @@ def get_datastore(session, cluster=None, host=None, datastore_regex=None):
raise exception.DatastoreNotFound()
-def _get_allowed_datastores(data_stores, datastore_regex, allowed_types):
+def _get_allowed_datastores(data_stores, datastore_regex):
allowed = []
for obj_content in data_stores.objects:
# the propset attribute "need not be set" by returning API
@@ -272,13 +292,9 @@ def _get_allowed_datastores(data_stores, datastore_regex, allowed_types):
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(Datastore(ref=obj_content.obj, name=ds_name))
+ if _is_datastore_valid(propdict, datastore_regex):
+ allowed.append(Datastore(ref=obj_content.obj,
+ name=propdict['summary.name']))
return allowed
@@ -300,12 +316,12 @@ def get_available_datastores(session, cluster=None, datastore_regex=None):
data_stores = session._call_method(vim_util,
"get_properties_for_a_collection_of_objects",
"Datastore", data_store_mors,
- ["summary.type", "summary.name", "summary.accessible"])
+ ["summary.type", "summary.name", "summary.accessible",
+ "summary.maintenanceMode"])
allowed = []
while data_stores:
- allowed.extend(_get_allowed_datastores(data_stores, datastore_regex,
- ['VMFS', 'NFS']))
+ allowed.extend(_get_allowed_datastores(data_stores, datastore_regex))
token = _get_token(data_stores)
if not token:
break