]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
NetApp FC driver shims missing manage/unmanage
authorClinton Knight <cknight@netapp.com>
Wed, 15 Apr 2015 14:50:49 +0000 (10:50 -0400)
committerClinton Knight <cknight@netapp.com>
Thu, 28 May 2015 18:21:51 +0000 (18:21 +0000)
The NetApp FC drivers' passthrough shim layers are missing the
manage/unmanage methods, causing the manage/unmanage functions
to fail.  The necessary functionality is already present in
the underlying library layer, so the trivial fix is to add the
functions to the passthrough layers. This patch also adds a
unit test to ensure the four block storage driver interfaces
remain in sync.

Change-Id: I0fa7e16b23e5148f82a8b51bf4380f4384c35759
Closes-Bug: #1444517

cinder/tests/unit/volume/drivers/netapp/dataontap/test_block_driver_interfaces.py [new file with mode: 0644]
cinder/volume/drivers/netapp/dataontap/fc_7mode.py
cinder/volume/drivers/netapp/dataontap/fc_cmode.py

diff --git a/cinder/tests/unit/volume/drivers/netapp/dataontap/test_block_driver_interfaces.py b/cinder/tests/unit/volume/drivers/netapp/dataontap/test_block_driver_interfaces.py
new file mode 100644 (file)
index 0000000..e192d9b
--- /dev/null
@@ -0,0 +1,73 @@
+# Copyright (c) 2015 Clinton Knight.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+"""
+Mock unit tests for the NetApp block storage driver interfaces
+"""
+
+
+import mock
+import six
+
+from cinder import test
+from cinder.volume.drivers.netapp.dataontap import block_7mode
+from cinder.volume.drivers.netapp.dataontap import block_cmode
+from cinder.volume.drivers.netapp.dataontap import fc_7mode
+from cinder.volume.drivers.netapp.dataontap import fc_cmode
+from cinder.volume.drivers.netapp.dataontap import iscsi_7mode
+from cinder.volume.drivers.netapp.dataontap import iscsi_cmode
+
+
+class NetAppBlockStorageDriverInterfaceTestCase(test.TestCase):
+
+    def setUp(self):
+        super(NetAppBlockStorageDriverInterfaceTestCase, self).setUp()
+
+        self.mock_object(block_cmode.NetAppBlockStorageCmodeLibrary,
+                         '__init__',
+                         mock.Mock(return_value=None))
+        self.mock_object(block_7mode.NetAppBlockStorage7modeLibrary,
+                         '__init__',
+                         mock.Mock(return_value=None))
+
+        self.iscsi_7mode_driver = iscsi_7mode.NetApp7modeISCSIDriver()
+        self.iscsi_cmode_driver = iscsi_cmode.NetAppCmodeISCSIDriver()
+        self.fc_7mode_driver = fc_7mode.NetApp7modeFibreChannelDriver()
+        self.fc_cmode_driver = fc_cmode.NetAppCmodeFibreChannelDriver()
+
+    def test_driver_interfaces_match(self):
+        """Ensure the NetApp block storage driver interfaces match.
+
+        The four block storage Cinder drivers from NetApp (iSCSI/FC,
+        7-mode/C-mode) are merely passthrough shim layers atop a common
+        block storage library. Bugs have been introduced when a Cinder
+        method was exposed via a subset of those driver shims.  This test
+        ensures they remain in sync and the library features are uniformly
+        available in the four drivers.
+        """
+
+        # Get local functions of each driver interface
+        iscsi_7mode = self._get_local_functions(self.iscsi_7mode_driver)
+        iscsi_cmode = self._get_local_functions(self.iscsi_cmode_driver)
+        fc_7mode = self._get_local_functions(self.fc_7mode_driver)
+        fc_cmode = self._get_local_functions(self.fc_cmode_driver)
+
+        # Ensure NetApp block storage driver shims are identical
+        self.assertSetEqual(iscsi_7mode, iscsi_cmode)
+        self.assertSetEqual(iscsi_7mode, fc_7mode)
+        self.assertSetEqual(iscsi_7mode, fc_cmode)
+
+    def _get_local_functions(self, obj):
+        """Get function names of an object without superclass functions."""
+        return set([key for key, value in six.iteritems(type(obj).__dict__)
+                    if callable(value)])
index 4bf2f8409fff2dab5397a59ae8f9a3bba7b0d2b8..8b06e621670c09788fb4efb963e27a19e2aba8c9 100644 (file)
@@ -21,6 +21,7 @@ from cinder.volume import driver
 from cinder.volume.drivers.netapp.dataontap import block_7mode
 from cinder.zonemanager import utils as fczm_utils
 
+
 LOG = logging.getLogger(__name__)
 
 
@@ -73,6 +74,15 @@ class NetApp7modeFibreChannelDriver(driver.FibreChannelDriver):
     def remove_export(self, context, volume):
         self.library.remove_export(context, volume)
 
+    def manage_existing(self, volume, existing_ref):
+        return self.library.manage_existing(volume, existing_ref)
+
+    def manage_existing_get_size(self, volume, existing_ref):
+        return self.library.manage_existing_get_size(volume, existing_ref)
+
+    def unmanage(self, volume):
+        return self.library.unmanage(volume)
+
     @fczm_utils.AddFCZone
     def initialize_connection(self, volume, connector):
         return self.library.initialize_connection_fc(volume, connector)
index 9f49ddb58844ba9ad530d0edb129d1d7e636f758..856d8b510480de9e17839753da585cc943e7d613 100644 (file)
@@ -21,6 +21,7 @@ from cinder.volume import driver
 from cinder.volume.drivers.netapp.dataontap import block_cmode
 from cinder.zonemanager import utils as fczm_utils
 
+
 LOG = logging.getLogger(__name__)
 
 
@@ -73,6 +74,15 @@ class NetAppCmodeFibreChannelDriver(driver.FibreChannelDriver):
     def remove_export(self, context, volume):
         self.library.remove_export(context, volume)
 
+    def manage_existing(self, volume, existing_ref):
+        return self.library.manage_existing(volume, existing_ref)
+
+    def manage_existing_get_size(self, volume, existing_ref):
+        return self.library.manage_existing_get_size(volume, existing_ref)
+
+    def unmanage(self, volume):
+        return self.library.unmanage(volume)
+
     @fczm_utils.AddFCZone
     def initialize_connection(self, volume, connector):
         return self.library.initialize_connection_fc(volume, connector)