]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
VMware: Fix datastore selection with single host
authorVipin Balachandran <vbala@vmware.com>
Wed, 10 Dec 2014 07:11:08 +0000 (12:41 +0530)
committerVipin Balachandran <vbala@vmware.com>
Wed, 10 Dec 2014 12:39:20 +0000 (18:09 +0530)
Currently, the select_datastore method is called with an empty list of
ESX hosts. This causes the method to retrieve all the hosts in vCenter
as candidates for selecting a datastore. The reference to a retrieved
host is stored in attribute 'obj'. Some of the future bug fixes will
need to invoke this method with reference to a single ESX host. Such
invocations will fail with attribute error: 'val instance has no
attribute 'obj''. This patch fixes the attribute error.

Closes-Bug: #1401052
Change-Id: Ib4f48d2ebfbfa3a9ce6a402300d41351548932ef

cinder/tests/test_vmware_datastore.py
cinder/volume/drivers/vmware/datastore.py

index e5206369ffd92508bf0d9539082c7da552b7126c..a118a52d00b32e2dfc897441e04089332e391963 100644 (file)
@@ -60,6 +60,12 @@ class DatastoreTest(test.TestCase):
         return mock.Mock(datastore=ds, freeSpace=free_space, type=_type,
                          capacity=capacity)
 
+    def _create_host(self, value):
+        host = mock.Mock(spec=['_type', 'value'])
+        host._type = 'HostSystem'
+        host.value = value
+        return host
+
     @mock.patch('cinder.volume.drivers.vmware.datastore.DatastoreSelector.'
                 '_filter_by_profile')
     def test_filter_datastores(self, filter_by_profile):
@@ -181,13 +187,14 @@ class DatastoreTest(test.TestCase):
                                          free_space=units.Mi,
                                          capacity=4 * units.Mi)
 
-        host_1 = mock.sentinel.host_1
-        host_2 = mock.sentinel.host_3
-        host_3 = mock.sentinel.host_3
+        host_1 = self._create_host('host-1')
+        host_2 = self._create_host('host-2')
+        host_3 = self._create_host('host-3')
 
-        connected_hosts = {mock.sentinel.ds_1: [host_1],
-                           mock.sentinel.ds_2: [host_1, host_2],
-                           mock.sentinel.ds_3: [host_1, host_2, host_3]}
+        connected_hosts = {mock.sentinel.ds_1: [host_1.value],
+                           mock.sentinel.ds_2: [host_1.value, host_2.value],
+                           mock.sentinel.ds_3: [host_1.value, host_2.value,
+                                                host_3.value]}
         self._vops.get_connected_hosts.side_effect = (
             lambda summary: connected_hosts[summary])
 
@@ -228,7 +235,7 @@ class DatastoreTest(test.TestCase):
         self._vops.get_hosts.assert_called_once_with()
 
         # Test with single host with no valid datastores.
-        host_1 = mock.sentinel.host_1
+        host_1 = self._create_host('host-1')
         self._vops.get_hosts.return_value = mock.Mock(
             objects=[mock.Mock(obj=host_1)])
         self._vops.continue_retrieval.return_value = None
@@ -240,8 +247,8 @@ class DatastoreTest(test.TestCase):
         # Test with three hosts and vCenter connection problem while fetching
         # datastores for the second host.
         self._vops.get_dss_rp.reset_mock()
-        host_2 = mock.sentinel.host_2
-        host_3 = mock.sentinel.host_3
+        host_2 = self._create_host('host-2')
+        host_3 = self._create_host('host-3')
         self._vops.get_hosts.return_value = mock.Mock(
             objects=[mock.Mock(obj=host_1),
                      mock.Mock(obj=host_2),
@@ -347,6 +354,30 @@ class DatastoreTest(test.TestCase):
         # Clear side effects.
         self._vops.get_dss_rp.side_effect = None
 
+    @mock.patch('cinder.volume.drivers.vmware.datastore.DatastoreSelector.'
+                '_filter_datastores')
+    def test_select_datastore_with_single_host(self, filter_datastores):
+        host = self._create_host('host-1')
+        req = {self._ds_sel.SIZE_BYTES: units.Gi}
+
+        ds = mock.sentinel.ds
+        rp = mock.sentinel.rp
+        self._vops.get_dss_rp.return_value = ([ds], rp)
+
+        summary = self._create_summary(ds, free_space=2 * units.Gi,
+                                       capacity=3 * units.Gi)
+        filter_datastores.return_value = [summary]
+        self._vops.get_connected_hosts.return_value = [host.value]
+
+        self.assertEqual((host, rp, summary),
+                         self._ds_sel.select_datastore(req, [host]))
+
+        # reset mocks
+        self._vops.get_dss_rp.reset_mock()
+        self._vops.get_dss_rp.return_value = None
+        self._vops.get_connected_hosts.reset_mock()
+        self._vops.get_connected_hosts.return_value = None
+
     @mock.patch('cinder.volume.drivers.vmware.datastore.DatastoreSelector.'
                 '_filter_by_profile')
     def test_is_datastore_compliant(self, filter_by_profile):
index f686596bd23a9cf724b2419940b51a95fa1d52b4..0c052720b87d2a886ffcc8292283fa7be8154289 100644 (file)
@@ -122,7 +122,8 @@ class DatastoreSelector(object):
             if not hosts:
                 break
 
-            all_hosts.extend(hosts)
+            for host in hosts:
+                all_hosts.append(host.obj)
             retrieve_result = self._vops.continue_retrieval(
                 retrieve_result)
         return all_hosts
@@ -203,8 +204,7 @@ class DatastoreSelector(object):
                   "requirements: %(req)s.",
                   {'hosts': hosts,
                    'req': req})
-        for host in hosts:
-            host_ref = host.obj
+        for host_ref in hosts:
             try:
                 (datastores, rp) = self._vops.get_dss_rp(host_ref)
             except error_util.VimConnectionException: