diff options
author | Jenkins <jenkins@review.openstack.org> | 2014-08-21 21:30:38 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2014-08-21 21:30:38 +0000 |
commit | 05cc277475d02a4f415e4c5edac76cf7266145ee (patch) | |
tree | 18ab7d5ed10883cefa431680c1bcb647743203d1 | |
parent | e8a91a781b9c594c1baba0f054fc9837b1bf3185 (diff) | |
parent | c5de5e7ab166e29304a01d7e310ae6ed32d22090 (diff) | |
download | nova-05cc277475d02a4f415e4c5edac76cf7266145ee.tar.gz |
Merge "VMWare Driver - Ignore datastore in maintenance mode"
-rw-r--r-- | nova/tests/virt/vmwareapi/fake.py | 6 | ||||
-rw-r--r-- | nova/tests/virt/vmwareapi/test_ds_util.py | 62 | ||||
-rw-r--r-- | nova/tests/virt/vmwareapi/test_ds_util_datastore_selection.py | 25 | ||||
-rw-r--r-- | nova/tests/virt/vmwareapi/test_vm_util.py | 1 | ||||
-rw-r--r-- | nova/virt/vmwareapi/ds_util.py | 68 |
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 |