diff options
author | Arnaud Legendre <arnaudleg@gmail.com> | 2014-07-23 17:50:51 -0700 |
---|---|---|
committer | Arnaud Legendre <arnaudleg@gmail.com> | 2014-08-14 12:32:43 -0700 |
commit | e5c22fa8571c447ad9753980340ce2c6efa18a1d (patch) | |
tree | 8ad9cc57bee75505b7ef348e829673c007094c8a | |
parent | 81beebbc60b40a4e674269585108161767bda883 (diff) | |
download | oslo-vmware-e5c22fa8571c447ad9753980340ce2c6efa18a1d.tar.gz |
Add methods to the Datastore objects
This patch ports three methods:
- get_connected_hosts
- get_summary
- is_ds_mount_usable
These methods are used in Cinder (see http://goo.gl/yR5psg) and
Glance (see http://goo.gl/aDeyfa).
Change-Id: I568372fef6bb4e3e3d0d6da2c32c2e971b319ad7
-rw-r--r-- | oslo/vmware/objects/datastore.py | 46 | ||||
-rw-r--r-- | tests/objects/test_datastore.py | 69 |
2 files changed, 115 insertions, 0 deletions
diff --git a/oslo/vmware/objects/datastore.py b/oslo/vmware/objects/datastore.py index 83b09a4..9f41a0d 100644 --- a/oslo/vmware/objects/datastore.py +++ b/oslo/vmware/objects/datastore.py @@ -15,6 +15,7 @@ import posixpath from oslo.vmware.openstack.common.gettextutils import _ +from oslo.vmware import vim_util class Datastore(object): @@ -70,6 +71,51 @@ class Datastore(object): def __str__(self): return '[%s]' % self._name + def get_summary(self, session): + """Get datastore summary. + + :param datastore: Reference to the datastore + :return: 'summary' property of the datastore + """ + return session.invoke_api(vim_util, 'get_object_property', + session.vim, self.ref, 'summary') + + def get_connected_hosts(self, session): + """Get a list of usable (accessible, mounted, read-writable) hosts where + the datastore is mounted. + + :param: session: session + :return: list of HostSystem managed object references + """ + hosts = [] + summary = self.get_summary() + if not summary.accessible: + return hosts + host_mounts = session.invoke_api(vim_util, 'get_object_property', + session.vim, self.ref, 'host') + if not hasattr(host_mounts, 'DatastoreHostMount'): + return hosts + for host_mount in host_mounts.DatastoreHostMount: + if self.is_datastore_mount_usable(host_mount.mountInfo): + hosts.append(host_mount.key) + return hosts + + @staticmethod + def is_datastore_mount_usable(mount_info): + """Check if a datastore is usable as per the given mount info. + + The datastore is considered to be usable for a host only if it is + writable, mounted and accessible. + + :param mount_info: HostMountInfo data object + :return: True if datastore is usable + """ + writable = mount_info.accessMode == 'readWrite' + mounted = getattr(mount_info, 'mounted', True) + accessible = getattr(mount_info, 'accessible', False) + + return writable and mounted and accessible + class DatastorePath(object): diff --git a/tests/objects/test_datastore.py b/tests/objects/test_datastore.py index 7044cfb..411c786 100644 --- a/tests/objects/test_datastore.py +++ b/tests/objects/test_datastore.py @@ -12,11 +12,29 @@ # License for the specific language governing permissions and limitations # under the License. +import mock + from oslo.vmware.objects import datastore from oslo.vmware.openstack.common import units +from oslo.vmware import vim_util from tests import base +class HostMount(object): + + def __init__(self, key, mountInfo): + self.key = key + self.mountInfo = mountInfo + + +class MountInfo(object): + + def __init__(self, accessMode, mounted, accessible): + self.accessMode = accessMode + self.mounted = mounted + self.accessible = accessible + + class DatastoreTestCase(base.TestCase): """Test the Datastore object.""" @@ -49,6 +67,57 @@ class DatastoreTestCase(base.TestCase): ds_path = ds.build_path("some_dir", "foo.vmdk") self.assertEqual('[ds_name] some_dir/foo.vmdk', str(ds_path)) + def test_get_summary(self): + ds_ref = vim_util.get_moref('ds-0', 'Datastore') + ds = datastore.Datastore(ds_ref, 'ds-name') + summary = mock.sentinel.summary + session = mock.Mock() + session.invoke_api = mock.Mock() + session.invoke_api.return_value = summary + ret = ds.get_summary(session) + self.assertEqual(summary, ret) + session.invoke_api.assert_called_once_with(vim_util, + 'get_object_property', + session.vim, + ds.ref, 'summary') + + def test_get_connected_hosts(self): + session = mock.Mock() + ds_ref = vim_util.get_moref('ds-0', 'Datastore') + ds = datastore.Datastore(ds_ref, 'ds-name') + ds.get_summary = mock.Mock() + ds.get_summary.return_value.accessible = False + self.assertEqual([], ds.get_connected_hosts(session)) + ds.get_summary.return_value.accessible = True + m1 = HostMount("m1", MountInfo('readWrite', True, True)) + m2 = HostMount("m2", MountInfo('read', True, True)) + m3 = HostMount("m3", MountInfo('readWrite', False, True)) + m4 = HostMount("m4", MountInfo('readWrite', True, False)) + + class Prop(object): + DatastoreHostMount = [m1, m2, m3, m4] + session.invoke_api = mock.Mock() + session.invoke_api.return_value = Prop() + hosts = ds.get_connected_hosts(session) + self.assertEqual(1, len(hosts)) + self.assertEqual("m1", hosts.pop()) + + def test_is_datastore_mount_usable(self): + m = MountInfo('readWrite', True, True) + self.assertTrue(datastore.Datastore.is_datastore_mount_usable(m)) + m = MountInfo('read', True, True) + self.assertFalse(datastore.Datastore.is_datastore_mount_usable(m)) + m = MountInfo('readWrite', False, True) + self.assertFalse(datastore.Datastore.is_datastore_mount_usable(m)) + m = MountInfo('readWrite', True, False) + self.assertFalse(datastore.Datastore.is_datastore_mount_usable(m)) + m = MountInfo('readWrite', False, False) + self.assertFalse(datastore.Datastore.is_datastore_mount_usable(m)) + m = MountInfo('readWrite', None, None) + self.assertFalse(datastore.Datastore.is_datastore_mount_usable(m)) + m = MountInfo('readWrite', None, True) + self.assertFalse(datastore.Datastore.is_datastore_mount_usable(m)) + class DatastorePathTestCase(base.TestCase): |