]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
NetApp E-Series: Refactor class structure for FC
authorAlex Meade <mr.alex.meade@gmail.com>
Tue, 28 Apr 2015 01:19:36 +0000 (21:19 -0400)
committerAlex Meade <mr.alex.meade@gmail.com>
Thu, 11 Jun 2015 14:21:37 +0000 (10:21 -0400)
This patch moves classes to mimic the NetApp ONTAP drivers class
structure by creating a library module, making the iSCSI driver
a thin layer. This way the E-Series FC driver can be added in a
similar manner.

Change-Id: I8b4ed6a7b2d43cd93da5c340646405e3041a312a

cinder/tests/unit/test_netapp_eseries_iscsi.py
cinder/tests/unit/volume/drivers/netapp/eseries/test_iscsi_driver.py [new file with mode: 0644]
cinder/tests/unit/volume/drivers/netapp/eseries/test_library.py [moved from cinder/tests/unit/volume/drivers/netapp/eseries/test_iscsi.py with 61% similarity]
cinder/volume/drivers/netapp/common.py
cinder/volume/drivers/netapp/eseries/iscsi_driver.py [new file with mode: 0644]
cinder/volume/drivers/netapp/eseries/library.py [moved from cinder/volume/drivers/netapp/eseries/iscsi.py with 97% similarity]

index 8c0225cf81d473a3fca1d764f89fba20c095bb1f..52477f18a0fe27517f36daea9de6eedb5521f968 100644 (file)
@@ -32,7 +32,7 @@ from cinder import test
 from cinder.volume import configuration as conf
 from cinder.volume.drivers.netapp import common
 from cinder.volume.drivers.netapp.eseries import client
-from cinder.volume.drivers.netapp.eseries import iscsi
+from cinder.volume.drivers.netapp.eseries import library
 from cinder.volume.drivers.netapp.eseries import utils
 from cinder.volume.drivers.netapp import options
 import cinder.volume.drivers.netapp.utils as na_utils
@@ -671,6 +671,7 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         self.mock_object(na_utils, 'OpenStackInfo')
         configuration = self._set_config(create_configuration())
         self.driver = common.NetAppDriver(configuration=configuration)
+        self.library = self.driver.library
         self.mock_object(requests, 'Session', FakeEseriesHTTPSession)
         self.driver.do_setup(context='context')
         self.driver.check_for_setup_error()
@@ -695,7 +696,7 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         configuration.netapp_controller_ips = '127.0.0.1,127.0.0.3'
         driver = common.NetAppDriver(configuration=configuration)
         driver.do_setup(context='context')
-        self.assertEqual(driver._client.get_system_id(),
+        self.assertEqual(driver.library._client.get_system_id(),
                          '1fa6efb5-f07b-4de4-9f0e-52e5f7ff5d1b')
 
     def test_check_system_pwd_not_sync(self):
@@ -705,8 +706,8 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
                 return {'status': 'passwordoutofsync'}
             return {'status': 'needsAttention'}
 
-        self.driver._client.list_storage_system = mock.Mock(wraps=list_system)
-        result = self.driver._check_storage_system()
+        self.library._client.list_storage_system = mock.Mock(wraps=list_system)
+        result = self.library._check_storage_system()
         self.assertTrue(result)
 
     def test_connect(self):
@@ -720,10 +721,10 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         self.driver.get_volume_stats(refresh=False)
 
     def test_get_pool(self):
-        self.mock_object(self.driver, '_get_volume',
+        self.mock_object(self.library, '_get_volume',
                          mock.Mock(return_value={
                              'volumeGroupRef': 'fake_ref'}))
-        self.mock_object(self.driver._client, "get_storage_pool",
+        self.mock_object(self.library._client, "get_storage_pool",
                          mock.Mock(return_value={'volumeGroupRef': 'fake_ref',
                                                  'label': 'ddp1'}))
 
@@ -732,21 +733,23 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         self.assertEqual(pool, 'ddp1')
 
     def test_get_pool_no_pools(self):
-        self.mock_object(self.driver, '_get_volume',
+        self.mock_object(self.library, '_get_volume',
                          mock.Mock(return_value={
                              'volumeGroupRef': 'fake_ref'}))
-        self.mock_object(self.driver._client, "get_storage_pool",
+        self.mock_object(self.library._client, "get_storage_pool",
                          mock.Mock(return_value=None))
 
         pool = self.driver.get_pool({'name_id': 'fake-uuid'})
 
         self.assertEqual(pool, None)
 
-    @mock.patch.object(iscsi.NetAppEseriesISCSIDriver, '_create_volume',
+    @mock.patch.object(library.NetAppESeriesLibrary, '_create_volume',
                        mock.Mock())
     def test_create_volume(self):
+
         self.driver.create_volume(self.volume)
-        self.driver._create_volume.assert_called_with(
+
+        self.library._create_volume.assert_called_with(
             'DDP', self.fake_eseries_volume_label, self.volume['size'])
 
     def test_create_volume_no_pool_provided_by_scheduler(self):
@@ -765,10 +768,12 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         fake_list_pools.return_value = fake_pools
         wrong_eseries_pool_label = 'hostname@backend'
         self.assertRaises(exception.NetAppDriverException,
-                          self.driver._create_volume, wrong_eseries_pool_label,
-                          self.fake_eseries_volume_label, self.fake_size_gb)
+                          self.library._create_volume,
+                          wrong_eseries_pool_label,
+                          self.fake_eseries_volume_label,
+                          self.fake_size_gb)
 
-    @mock.patch.object(iscsi.LOG, 'info')
+    @mock.patch.object(library.LOG, 'info')
     @mock.patch.object(client.RestClient, 'list_storage_pools')
     @mock.patch.object(client.RestClient, 'create_volume',
                        mock.MagicMock(return_value='CorrectVolume'))
@@ -779,7 +784,7 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         fake_pool['raidLevel'] = 'raidDiskPool'
         fake_pools = [fake_pool]
         storage_pools.return_value = fake_pools
-        storage_vol = self.driver._create_volume(
+        storage_vol = self.library._create_volume(
             self.fake_eseries_pool_label,
             self.fake_eseries_volume_label,
             self.fake_size_gb)
@@ -791,7 +796,7 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
     @mock.patch.object(client.RestClient, 'create_volume',
                        mock.MagicMock(
                            side_effect=exception.NetAppDriverException))
-    @mock.patch.object(iscsi.LOG, 'info', mock.Mock())
+    @mock.patch.object(library.LOG, 'info', mock.Mock())
     def test_create_volume_check_exception(self, fake_list_pools):
         fake_pool = {}
         fake_pool['label'] = self.fake_eseries_pool_label
@@ -800,7 +805,7 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         fake_pools = [fake_pool]
         fake_list_pools.return_value = fake_pools
         self.assertRaises(exception.NetAppDriverException,
-                          self.driver._create_volume,
+                          self.library._create_volume,
                           self.fake_eseries_pool_label,
                           self.fake_eseries_volume_label, self.fake_size_gb)
 
@@ -809,9 +814,9 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         vol_nomatch = {'id': 'vol_id', 'currentManager': 'ctrl3'}
         portals = [{'controller': 'ctrl2', 'iqn': 'iqn2'},
                    {'controller': 'ctrl1', 'iqn': 'iqn1'}]
-        portal = self.driver._get_iscsi_portal_for_vol(volume, portals)
+        portal = self.library._get_iscsi_portal_for_vol(volume, portals)
         self.assertEqual(portal, {'controller': 'ctrl1', 'iqn': 'iqn1'})
-        portal = self.driver._get_iscsi_portal_for_vol(vol_nomatch, portals)
+        portal = self.library._get_iscsi_portal_for_vol(vol_nomatch, portals)
         self.assertEqual(portal, {'controller': 'ctrl2', 'iqn': 'iqn2'})
 
     def test_portal_for_vol_any_false(self):
@@ -819,7 +824,7 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         portals = [{'controller': 'ctrl2', 'iqn': 'iqn2'},
                    {'controller': 'ctrl1', 'iqn': 'iqn1'}]
         self.assertRaises(exception.NetAppDriverException,
-                          self.driver._get_iscsi_portal_for_vol,
+                          self.library._get_iscsi_portal_for_vol,
                           vol_nomatch, portals, False)
 
     def test_setup_error_unsupported_host_type(self):
@@ -827,20 +832,20 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         configuration.netapp_host_type = 'garbage'
         driver = common.NetAppDriver(configuration=configuration)
         self.assertRaises(exception.NetAppDriverException,
-                          driver.check_for_setup_error)
+                          driver.library.check_for_setup_error)
 
     def test_check_host_type_default(self):
         configuration = self._set_config(create_configuration())
         driver = common.NetAppDriver(configuration=configuration)
-        driver._check_host_type()
-        self.assertEqual('LnxALUA', driver.host_type)
+        driver.library._check_host_type()
+        self.assertEqual('LnxALUA', driver.library.host_type)
 
     def test_do_setup_all_default(self):
         configuration = self._set_config(create_configuration())
         driver = common.NetAppDriver(configuration=configuration)
-        driver._check_mode_get_or_register_storage_system = mock.Mock()
+        driver.library._check_mode_get_or_register_storage_system = mock.Mock()
         driver.do_setup(context='context')
-        url = urllib.parse.urlparse(driver._client._endpoint)
+        url = urllib.parse.urlparse(driver.library._client._endpoint)
         port = url.port
         scheme = url.scheme
         self.assertEqual(8080, port)
@@ -850,9 +855,9 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         configuration = self._set_config(create_configuration())
         configuration.netapp_transport_type = 'http'
         driver = common.NetAppDriver(configuration=configuration)
-        driver._check_mode_get_or_register_storage_system = mock.Mock()
+        driver.library._check_mode_get_or_register_storage_system = mock.Mock()
         driver.do_setup(context='context')
-        url = urllib.parse.urlparse(driver._client._endpoint)
+        url = urllib.parse.urlparse(driver.library._client._endpoint)
         port = url.port
         scheme = url.scheme
         self.assertEqual(8080, port)
@@ -862,9 +867,9 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         configuration = self._set_config(create_configuration())
         configuration.netapp_transport_type = 'https'
         driver = common.NetAppDriver(configuration=configuration)
-        driver._check_mode_get_or_register_storage_system = mock.Mock()
+        driver.library._check_mode_get_or_register_storage_system = mock.Mock()
         driver.do_setup(context='context')
-        url = urllib.parse.urlparse(driver._client._endpoint)
+        url = urllib.parse.urlparse(driver.library._client._endpoint)
         port = url.port
         scheme = url.scheme
         self.assertEqual(8443, port)
@@ -874,9 +879,9 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         configuration = self._set_config(create_configuration())
         configuration.netapp_server_port = 81
         driver = common.NetAppDriver(configuration=configuration)
-        driver._check_mode_get_or_register_storage_system = mock.Mock()
+        driver.library._check_mode_get_or_register_storage_system = mock.Mock()
         driver.do_setup(context='context')
-        url = urllib.parse.urlparse(driver._client._endpoint)
+        url = urllib.parse.urlparse(driver.library._client._endpoint)
         port = url.port
         scheme = url.scheme
         self.assertEqual(81, port)
@@ -887,9 +892,9 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         configuration.netapp_transport_type = 'https'
         configuration.netapp_server_port = 446
         driver = common.NetAppDriver(configuration=configuration)
-        driver._check_mode_get_or_register_storage_system = mock.Mock()
+        driver.library._check_mode_get_or_register_storage_system = mock.Mock()
         driver.do_setup(context='context')
-        url = urllib.parse.urlparse(driver._client._endpoint)
+        url = urllib.parse.urlparse(driver.library._client._endpoint)
         port = url.port
         scheme = url.scheme
         self.assertEqual(446, port)
@@ -899,13 +904,13 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         configuration = self._set_config(create_configuration())
         configuration.netapp_controller_ips = '127.0.0.1'
         driver = common.NetAppDriver(configuration=configuration)
-        driver._check_mode_get_or_register_storage_system
+        driver.library._check_mode_get_or_register_storage_system
 
     def test_setup_good_controller_ips(self):
         configuration = self._set_config(create_configuration())
         configuration.netapp_controller_ips = '127.0.0.2,127.0.0.1'
         driver = common.NetAppDriver(configuration=configuration)
-        driver._check_mode_get_or_register_storage_system
+        driver.library._check_mode_get_or_register_storage_system
 
     def test_setup_missing_controller_ip(self):
         configuration = self._set_config(create_configuration())
@@ -918,33 +923,37 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         configuration = self._set_config(create_configuration())
         configuration.netapp_controller_ips = '987.65.43.21'
         driver = common.NetAppDriver(configuration=configuration)
-        self.assertRaises(exception.NoValidHost,
-                          driver._check_mode_get_or_register_storage_system)
+        self.assertRaises(
+            exception.NoValidHost,
+            driver.library._check_mode_get_or_register_storage_system)
 
     def test_setup_error_invalid_first_controller_ip(self):
         configuration = self._set_config(create_configuration())
         configuration.netapp_controller_ips = '987.65.43.21,127.0.0.1'
         driver = common.NetAppDriver(configuration=configuration)
-        self.assertRaises(exception.NoValidHost,
-                          driver._check_mode_get_or_register_storage_system)
+        self.assertRaises(
+            exception.NoValidHost,
+            driver.library._check_mode_get_or_register_storage_system)
 
     def test_setup_error_invalid_second_controller_ip(self):
         configuration = self._set_config(create_configuration())
         configuration.netapp_controller_ips = '127.0.0.1,987.65.43.21'
         driver = common.NetAppDriver(configuration=configuration)
-        self.assertRaises(exception.NoValidHost,
-                          driver._check_mode_get_or_register_storage_system)
+        self.assertRaises(
+            exception.NoValidHost,
+            driver.library._check_mode_get_or_register_storage_system)
 
     def test_setup_error_invalid_both_controller_ips(self):
         configuration = self._set_config(create_configuration())
         configuration.netapp_controller_ips = '564.124.1231.1,987.65.43.21'
         driver = common.NetAppDriver(configuration=configuration)
-        self.assertRaises(exception.NoValidHost,
-                          driver._check_mode_get_or_register_storage_system)
+        self.assertRaises(
+            exception.NoValidHost,
+            driver.library._check_mode_get_or_register_storage_system)
 
     def test_get_vol_with_label_wwn_missing(self):
         self.assertRaises(exception.InvalidInput,
-                          self.driver._get_volume_with_label_wwn,
+                          self.library._get_volume_with_label_wwn,
                           None, None)
 
     def test_get_vol_with_label_wwn_found(self):
@@ -954,10 +963,11 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
                         {'volumeRef': '2', 'volumeUse': 'standardVolume',
                          'label': 'l2', 'volumeGroupRef': 'g2',
                          'worldWideName': 'w2ghyu'}]
-        self.driver._get_storage_pools = mock.Mock(return_value=['g2', 'g3'])
-        self.driver._client.list_volumes = mock.Mock(return_value=fake_vl_list)
-        vol = self.driver._get_volume_with_label_wwn('l2', 'w2:gh:yu')
-        self.assertEqual(1, self.driver._client.list_volumes.call_count)
+        self.library._get_storage_pools = mock.Mock(return_value=['g2', 'g3'])
+        self.library._client.list_volumes = mock.Mock(
+            return_value=fake_vl_list)
+        vol = self.library._get_volume_with_label_wwn('l2', 'w2:gh:yu')
+        self.assertEqual(1, self.library._client.list_volumes.call_count)
         self.assertEqual('2', vol['volumeRef'])
 
     def test_get_vol_with_label_wwn_unmatched(self):
@@ -967,23 +977,24 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
                         {'volumeRef': '2', 'volumeUse': 'standardVolume',
                          'label': 'l2', 'volumeGroupRef': 'g2',
                          'worldWideName': 'w2ghyu'}]
-        self.driver._get_storage_pools = mock.Mock(return_value=['g2', 'g3'])
-        self.driver._client.list_volumes = mock.Mock(return_value=fake_vl_list)
-        self.assertRaises(KeyError, self.driver._get_volume_with_label_wwn,
+        self.library._get_storage_pools = mock.Mock(return_value=['g2', 'g3'])
+        self.library._client.list_volumes = mock.Mock(
+            return_value=fake_vl_list)
+        self.assertRaises(KeyError, self.library._get_volume_with_label_wwn,
                           'l2', 'abcdef')
-        self.assertEqual(1, self.driver._client.list_volumes.call_count)
+        self.assertEqual(1, self.library._client.list_volumes.call_count)
 
     def test_manage_existing_get_size(self):
-        self.driver._get_existing_vol_with_manage_ref = mock.Mock(
+        self.library._get_existing_vol_with_manage_ref = mock.Mock(
             return_value=self.fake_ret_vol)
         size = self.driver.manage_existing_get_size(self.volume, self.fake_ref)
         self.assertEqual(3, size)
-        self.driver._get_existing_vol_with_manage_ref.assert_called_once_with(
+        self.library._get_existing_vol_with_manage_ref.assert_called_once_with(
             self.volume, self.fake_ref)
 
     def test_get_exist_vol_source_name_missing(self):
         self.assertRaises(exception.ManageExistingInvalidReference,
-                          self.driver._get_existing_vol_with_manage_ref,
+                          self.library._get_existing_vol_with_manage_ref,
                           self.volume, {'id': '1234'})
 
     def test_get_exist_vol_source_not_found(self):
@@ -991,53 +1002,53 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
             d = {'id': '1'}
             return d[v_id]
 
-        self.driver._get_volume_with_label_wwn = mock.Mock(wraps=_get_volume)
+        self.library._get_volume_with_label_wwn = mock.Mock(wraps=_get_volume)
         self.assertRaises(exception.ManageExistingInvalidReference,
-                          self.driver._get_existing_vol_with_manage_ref,
+                          self.library._get_existing_vol_with_manage_ref,
                           {'id': 'id2'}, {'source-name': 'name2'})
-        self.driver._get_volume_with_label_wwn.assert_called_once_with(
+        self.library._get_volume_with_label_wwn.assert_called_once_with(
             'name2', None)
 
     def test_get_exist_vol_with_manage_ref(self):
         fake_ret_vol = {'id': 'right'}
-        self.driver._get_volume_with_label_wwn = mock.Mock(
+        self.library._get_volume_with_label_wwn = mock.Mock(
             return_value=fake_ret_vol)
-        actual_vol = self.driver._get_existing_vol_with_manage_ref(
+        actual_vol = self.library._get_existing_vol_with_manage_ref(
             {'id': 'id2'}, {'source-name': 'name2'})
-        self.driver._get_volume_with_label_wwn.assert_called_once_with(
+        self.library._get_volume_with_label_wwn.assert_called_once_with(
             'name2', None)
         self.assertEqual(fake_ret_vol, actual_vol)
 
     @mock.patch.object(utils, 'convert_uuid_to_es_fmt')
     def test_manage_existing_same_label(self, mock_convert_es_fmt):
-        self.driver._get_existing_vol_with_manage_ref = mock.Mock(
+        self.library._get_existing_vol_with_manage_ref = mock.Mock(
             return_value=self.fake_ret_vol)
         mock_convert_es_fmt.return_value = 'label'
         self.driver.manage_existing(self.volume, self.fake_ref)
-        self.driver._get_existing_vol_with_manage_ref.assert_called_once_with(
+        self.library._get_existing_vol_with_manage_ref.assert_called_once_with(
             self.volume, self.fake_ref)
         mock_convert_es_fmt.assert_called_once_with(
             '114774fb-e15a-4fae-8ee2-c9723e3645ef')
 
     @mock.patch.object(utils, 'convert_uuid_to_es_fmt')
     def test_manage_existing_new(self, mock_convert_es_fmt):
-        self.driver._get_existing_vol_with_manage_ref = mock.Mock(
+        self.library._get_existing_vol_with_manage_ref = mock.Mock(
             return_value=self.fake_ret_vol)
         mock_convert_es_fmt.return_value = 'vol_label'
-        self.driver._client.update_volume = mock.Mock(
+        self.library._client.update_volume = mock.Mock(
             return_value={'id': 'update', 'worldWideName': 'wwn'})
         self.driver.manage_existing(self.volume, self.fake_ref)
-        self.driver._get_existing_vol_with_manage_ref.assert_called_once_with(
+        self.library._get_existing_vol_with_manage_ref.assert_called_once_with(
             self.volume, self.fake_ref)
         mock_convert_es_fmt.assert_called_once_with(
             '114774fb-e15a-4fae-8ee2-c9723e3645ef')
-        self.driver._client.update_volume.assert_called_once_with(
+        self.library._client.update_volume.assert_called_once_with(
             'vol_id', 'vol_label')
 
-    @mock.patch.object(iscsi.LOG, 'info')
+    @mock.patch.object(library.LOG, 'info')
     def test_unmanage(self, log_info):
-        self.driver._get_volume = mock.Mock(return_value=self.fake_ret_vol)
+        self.library._get_volume = mock.Mock(return_value=self.fake_ret_vol)
         self.driver.unmanage(self.volume)
-        self.driver._get_volume.assert_called_once_with(
+        self.library._get_volume.assert_called_once_with(
             '114774fb-e15a-4fae-8ee2-c9723e3645ef')
         self.assertEqual(1, log_info.call_count)
diff --git a/cinder/tests/unit/volume/drivers/netapp/eseries/test_iscsi_driver.py b/cinder/tests/unit/volume/drivers/netapp/eseries/test_iscsi_driver.py
new file mode 100644 (file)
index 0000000..42e1e63
--- /dev/null
@@ -0,0 +1,29 @@
+# Copyright (c) 2015 Alex Meade.  All rights reserved.
+# 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.
+
+import mock
+
+from cinder import test
+import cinder.volume.drivers.netapp.eseries.iscsi_driver as iscsi
+from cinder.volume.drivers.netapp import utils as na_utils
+
+
+class NetAppESeriesISCSIDriverTestCase(test.TestCase):
+
+    @mock.patch.object(na_utils, 'validate_instantiation')
+    def test_instantiation(self, mock_validate_instantiation):
+        iscsi.NetAppEseriesISCSIDriver(configuration=mock.Mock())
+
+        self.assertTrue(mock_validate_instantiation.called)
similarity index 61%
rename from cinder/tests/unit/volume/drivers/netapp/eseries/test_iscsi.py
rename to cinder/tests/unit/volume/drivers/netapp/eseries/test_library.py
index fac76dec956eab8357e967872fcb1d59cb55bee3..eb2652e607c7cac6ebb9a11e7e8c4aade77cc919 100644 (file)
@@ -14,9 +14,6 @@
 #    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 E-series iscsi driver
-"""
 
 import copy
 
@@ -30,7 +27,7 @@ from cinder.tests.unit.volume.drivers.netapp.eseries import fakes as \
     eseries_fakes
 from cinder.volume.drivers.netapp.eseries import client as es_client
 from cinder.volume.drivers.netapp.eseries import host_mapper
-from cinder.volume.drivers.netapp.eseries import iscsi as es_iscsi
+from cinder.volume.drivers.netapp.eseries import library
 from cinder.volume.drivers.netapp.eseries import utils
 from cinder.volume.drivers.netapp import utils as na_utils
 
@@ -48,24 +45,24 @@ def get_fake_volume():
     }
 
 
-class NetAppEseriesISCSIDriverTestCase(test.TestCase):
+class NetAppEseriesLibraryTestCase(test.TestCase):
     def setUp(self):
-        super(NetAppEseriesISCSIDriverTestCase, self).setUp()
+        super(NetAppEseriesLibraryTestCase, self).setUp()
 
         kwargs = {'configuration':
                   eseries_fakes.create_configuration_eseries()}
 
-        self.driver = es_iscsi.NetAppEseriesISCSIDriver(**kwargs)
-        self.driver._client = eseries_fakes.FakeEseriesClient()
-        self.driver.check_for_setup_error()
+        self.library = library.NetAppESeriesLibrary('FAKE', **kwargs)
+        self.library._client = eseries_fakes.FakeEseriesClient()
+        self.library.check_for_setup_error()
 
     def test_do_setup(self):
-        self.mock_object(es_iscsi.NetAppEseriesISCSIDriver,
+        self.mock_object(self.library,
                          '_check_mode_get_or_register_storage_system')
         self.mock_object(es_client, 'RestClient',
                          eseries_fakes.FakeEseriesClient)
         mock_check_flags = self.mock_object(na_utils, 'check_flags')
-        self.driver.do_setup(mock.Mock())
+        self.library.do_setup(mock.Mock())
 
         self.assertTrue(mock_check_flags.called)
 
@@ -73,21 +70,21 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
         drives = [{'currentVolumeGroupRef': 'test_vg1',
                    'driveMediaType': 'ssd'}]
 
-        self.driver._get_storage_pools = mock.Mock(return_value=['test_vg1'])
-        self.driver._client.list_storage_pools = mock.Mock(return_value=[])
-        self.driver._client.list_drives = mock.Mock(return_value=drives)
+        self.library._get_storage_pools = mock.Mock(return_value=['test_vg1'])
+        self.library._client.list_storage_pools = mock.Mock(return_value=[])
+        self.library._client.list_drives = mock.Mock(return_value=drives)
 
-        self.driver._update_ssc_info()
+        self.library._update_ssc_info()
 
         self.assertEqual({'test_vg1': {'netapp_disk_type': 'SSD'}},
-                         self.driver._ssc_stats)
+                         self.library._ssc_stats)
 
     def test_update_ssc_disk_types_ssd(self):
         drives = [{'currentVolumeGroupRef': 'test_vg1',
                    'driveMediaType': 'ssd'}]
-        self.driver._client.list_drives = mock.Mock(return_value=drives)
+        self.library._client.list_drives = mock.Mock(return_value=drives)
 
-        ssc_stats = self.driver._update_ssc_disk_types(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_types(['test_vg1'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_type': 'SSD'}},
                          ssc_stats)
@@ -95,9 +92,9 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
     def test_update_ssc_disk_types_scsi(self):
         drives = [{'currentVolumeGroupRef': 'test_vg1',
                    'interfaceType': {'driveType': 'scsi'}}]
-        self.driver._client.list_drives = mock.Mock(return_value=drives)
+        self.library._client.list_drives = mock.Mock(return_value=drives)
 
-        ssc_stats = self.driver._update_ssc_disk_types(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_types(['test_vg1'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_type': 'SCSI'}},
                          ssc_stats)
@@ -105,9 +102,9 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
     def test_update_ssc_disk_types_fcal(self):
         drives = [{'currentVolumeGroupRef': 'test_vg1',
                    'interfaceType': {'driveType': 'fibre'}}]
-        self.driver._client.list_drives = mock.Mock(return_value=drives)
+        self.library._client.list_drives = mock.Mock(return_value=drives)
 
-        ssc_stats = self.driver._update_ssc_disk_types(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_types(['test_vg1'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_type': 'FCAL'}},
                          ssc_stats)
@@ -115,9 +112,9 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
     def test_update_ssc_disk_types_sata(self):
         drives = [{'currentVolumeGroupRef': 'test_vg1',
                    'interfaceType': {'driveType': 'sata'}}]
-        self.driver._client.list_drives = mock.Mock(return_value=drives)
+        self.library._client.list_drives = mock.Mock(return_value=drives)
 
-        ssc_stats = self.driver._update_ssc_disk_types(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_types(['test_vg1'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_type': 'SATA'}},
                          ssc_stats)
@@ -125,9 +122,9 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
     def test_update_ssc_disk_types_sas(self):
         drives = [{'currentVolumeGroupRef': 'test_vg1',
                    'interfaceType': {'driveType': 'sas'}}]
-        self.driver._client.list_drives = mock.Mock(return_value=drives)
+        self.library._client.list_drives = mock.Mock(return_value=drives)
 
-        ssc_stats = self.driver._update_ssc_disk_types(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_types(['test_vg1'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_type': 'SAS'}},
                          ssc_stats)
@@ -135,9 +132,9 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
     def test_update_ssc_disk_types_unknown(self):
         drives = [{'currentVolumeGroupRef': 'test_vg1',
                    'interfaceType': {'driveType': 'unknown'}}]
-        self.driver._client.list_drives = mock.Mock(return_value=drives)
+        self.library._client.list_drives = mock.Mock(return_value=drives)
 
-        ssc_stats = self.driver._update_ssc_disk_types(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_types(['test_vg1'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_type': 'unknown'}},
                          ssc_stats)
@@ -145,54 +142,54 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
     def test_update_ssc_disk_types_undefined(self):
         drives = [{'currentVolumeGroupRef': 'test_vg1',
                    'interfaceType': {'driveType': '__UNDEFINED'}}]
-        self.driver._client.list_drives = mock.Mock(return_value=drives)
+        self.library._client.list_drives = mock.Mock(return_value=drives)
 
-        ssc_stats = self.driver._update_ssc_disk_types(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_types(['test_vg1'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_type': 'unknown'}},
                          ssc_stats)
 
     def test_update_ssc_disk_encryption_SecType_enabled(self):
         pools = [{'volumeGroupRef': 'test_vg1', 'securityType': 'enabled'}]
-        self.driver._client.list_storage_pools = mock.Mock(return_value=pools)
+        self.library._client.list_storage_pools = mock.Mock(return_value=pools)
 
-        ssc_stats = self.driver._update_ssc_disk_encryption(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_encryption(['test_vg1'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_encryption': 'true'}},
                          ssc_stats)
 
     def test_update_ssc_disk_encryption_SecType_unknown(self):
         pools = [{'volumeGroupRef': 'test_vg1', 'securityType': 'unknown'}]
-        self.driver._client.list_storage_pools = mock.Mock(return_value=pools)
+        self.library._client.list_storage_pools = mock.Mock(return_value=pools)
 
-        ssc_stats = self.driver._update_ssc_disk_encryption(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_encryption(['test_vg1'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_encryption': 'false'}},
                          ssc_stats)
 
     def test_update_ssc_disk_encryption_SecType_none(self):
         pools = [{'volumeGroupRef': 'test_vg1', 'securityType': 'none'}]
-        self.driver._client.list_storage_pools = mock.Mock(return_value=pools)
+        self.library._client.list_storage_pools = mock.Mock(return_value=pools)
 
-        ssc_stats = self.driver._update_ssc_disk_encryption(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_encryption(['test_vg1'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_encryption': 'false'}},
                          ssc_stats)
 
     def test_update_ssc_disk_encryption_SecType_capable(self):
         pools = [{'volumeGroupRef': 'test_vg1', 'securityType': 'capable'}]
-        self.driver._client.list_storage_pools = mock.Mock(return_value=pools)
+        self.library._client.list_storage_pools = mock.Mock(return_value=pools)
 
-        ssc_stats = self.driver._update_ssc_disk_encryption(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_encryption(['test_vg1'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_encryption': 'false'}},
                          ssc_stats)
 
     def test_update_ssc_disk_encryption_SecType_garbage(self):
         pools = [{'volumeGroupRef': 'test_vg1', 'securityType': 'garbage'}]
-        self.driver._client.list_storage_pools = mock.Mock(return_value=pools)
+        self.library._client.list_storage_pools = mock.Mock(return_value=pools)
 
-        ssc_stats = self.driver._update_ssc_disk_encryption(['test_vg1'])
+        ssc_stats = self.library._update_ssc_disk_encryption(['test_vg1'])
 
         self.assertRaises(TypeError, 'test_vg1',
                           {'netapp_disk_encryption': 'false'}, ssc_stats)
@@ -200,102 +197,104 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
     def test_update_ssc_disk_encryption_multiple(self):
         pools = [{'volumeGroupRef': 'test_vg1', 'securityType': 'none'},
                  {'volumeGroupRef': 'test_vg2', 'securityType': 'enabled'}]
-        self.driver._client.list_storage_pools = mock.Mock(return_value=pools)
+        self.library._client.list_storage_pools = mock.Mock(return_value=pools)
 
-        ssc_stats = self.driver._update_ssc_disk_encryption(['test_vg1',
-                                                            'test_vg2'])
+        ssc_stats = self.library._update_ssc_disk_encryption(['test_vg1',
+                                                              'test_vg2'])
 
         self.assertEqual({'test_vg1': {'netapp_disk_encryption': 'false'},
                           'test_vg2': {'netapp_disk_encryption': 'true'}},
                          ssc_stats)
 
-    def test_terminate_connection_no_hosts(self):
+    def test_terminate_connection_iscsi_no_hosts(self):
         connector = {'initiator': eseries_fakes.INITIATOR_NAME}
 
-        self.mock_object(self.driver._client, 'list_hosts',
+        self.mock_object(self.library._client, 'list_hosts',
                          mock.Mock(return_value=[]))
 
         self.assertRaises(exception.NotFound,
-                          self.driver.terminate_connection,
+                          self.library.terminate_connection_iscsi,
                           get_fake_volume(),
                           connector)
 
-    def test_terminate_connection_volume_not_mapped(self):
+    def test_terminate_connection_iscsi_volume_not_mapped(self):
         connector = {'initiator': eseries_fakes.INITIATOR_NAME}
         err = self.assertRaises(exception.NetAppDriverException,
-                                self.driver.terminate_connection,
+                                self.library.terminate_connection_iscsi,
                                 get_fake_volume(),
                                 connector)
         self.assertIn("not currently mapped to host", six.text_type(err))
 
-    def test_terminate_connection_volume_mapped(self):
+    def test_terminate_connection_iscsi_volume_mapped(self):
         connector = {'initiator': eseries_fakes.INITIATOR_NAME}
         fake_eseries_volume = copy.deepcopy(eseries_fakes.VOLUME)
         fake_eseries_volume['listOfMappings'] = [
             eseries_fakes.VOLUME_MAPPING
         ]
-        self.mock_object(self.driver._client, 'list_volumes',
+        self.mock_object(self.library._client, 'list_volumes',
                          mock.Mock(return_value=[fake_eseries_volume]))
         self.mock_object(host_mapper, 'unmap_volume_from_host')
 
-        self.driver.terminate_connection(get_fake_volume(), connector)
+        self.library.terminate_connection_iscsi(get_fake_volume(), connector)
 
         self.assertTrue(host_mapper.unmap_volume_from_host.called)
 
-    def test_terminate_connection_volume_not_mapped_initiator_does_not_exist(
+    def test_terminate_connection_iscsi_not_mapped_initiator_does_not_exist(
             self):
         connector = {'initiator': eseries_fakes.INITIATOR_NAME}
-        self.mock_object(self.driver._client, 'list_hosts',
+        self.mock_object(self.library._client, 'list_hosts',
                          mock.Mock(return_value=[eseries_fakes.HOST_2]))
         self.assertRaises(exception.NotFound,
-                          self.driver.terminate_connection,
+                          self.library.terminate_connection_iscsi,
                           get_fake_volume(),
                           connector)
 
-    def test_initialize_connection_volume_not_mapped(self):
+    def test_initialize_connection_iscsi_volume_not_mapped(self):
         connector = {'initiator': eseries_fakes.INITIATOR_NAME}
-        self.mock_object(self.driver._client, 'get_volume_mappings',
+        self.mock_object(self.library._client, 'get_volume_mappings',
                          mock.Mock(return_value=[]))
         self.mock_object(host_mapper, 'map_volume_to_single_host',
                          mock.Mock(
                              return_value=eseries_fakes.VOLUME_MAPPING))
 
-        self.driver.initialize_connection(get_fake_volume(), connector)
+        self.library.initialize_connection_iscsi(get_fake_volume(), connector)
 
-        self.assertTrue(self.driver._client.get_volume_mappings.called)
+        self.assertTrue(self.library._client.get_volume_mappings.called)
         self.assertTrue(host_mapper.map_volume_to_single_host.called)
 
-    def test_initialize_connection_volume_not_mapped_host_does_not_exist(self):
+    def test_initialize_connection_iscsi_volume_not_mapped_host_does_not_exist(
+            self):
         connector = {'initiator': eseries_fakes.INITIATOR_NAME}
-        self.mock_object(self.driver._client, 'get_volume_mappings',
+        self.mock_object(self.library._client, 'get_volume_mappings',
                          mock.Mock(return_value=[]))
-        self.mock_object(self.driver._client, 'list_hosts',
+        self.mock_object(self.library._client, 'list_hosts',
                          mock.Mock(return_value=[]))
-        self.mock_object(self.driver._client, 'create_host_with_port',
+        self.mock_object(self.library._client, 'create_host_with_port',
                          mock.Mock(return_value=eseries_fakes.HOST))
         self.mock_object(host_mapper, 'map_volume_to_single_host',
                          mock.Mock(
                              return_value=eseries_fakes.VOLUME_MAPPING))
 
-        self.driver.initialize_connection(get_fake_volume(), connector)
+        self.library.initialize_connection_iscsi(get_fake_volume(), connector)
 
-        self.assertTrue(self.driver._client.get_volume_mappings.called)
-        self.assertTrue(self.driver._client.list_hosts.called)
-        self.assertTrue(self.driver._client.create_host_with_port.called)
+        self.assertTrue(self.library._client.get_volume_mappings.called)
+        self.assertTrue(self.library._client.list_hosts.called)
+        self.assertTrue(self.library._client.create_host_with_port.called)
         self.assertTrue(host_mapper.map_volume_to_single_host.called)
 
-    def test_initialize_connection_volume_already_mapped_to_target_host(self):
+    def test_initialize_connection_iscsi_volume_already_mapped_to_target_host(
+            self):
         """Should be a no-op"""
         connector = {'initiator': eseries_fakes.INITIATOR_NAME}
         self.mock_object(host_mapper, 'map_volume_to_single_host',
                          mock.Mock(
                              return_value=eseries_fakes.VOLUME_MAPPING))
 
-        self.driver.initialize_connection(get_fake_volume(), connector)
+        self.library.initialize_connection_iscsi(get_fake_volume(), connector)
 
         self.assertTrue(host_mapper.map_volume_to_single_host.called)
 
-    def test_initialize_connection_volume_mapped_to_another_host(self):
+    def test_initialize_connection_iscsi_volume_mapped_to_another_host(self):
         """Should raise error saying multiattach not enabled"""
         connector = {'initiator': eseries_fakes.INITIATOR_NAME}
         fake_mapping_to_other_host = copy.deepcopy(
@@ -307,38 +306,38 @@ class NetAppEseriesISCSIDriverTestCase(test.TestCase):
                              side_effect=exception.NetAppDriverException))
 
         self.assertRaises(exception.NetAppDriverException,
-                          self.driver.initialize_connection,
+                          self.library.initialize_connection_iscsi,
                           get_fake_volume(), connector)
 
         self.assertTrue(host_mapper.map_volume_to_single_host.called)
 
 
-class NetAppEseriesISCSIDriverMultiAttachTestCase(test.TestCase):
+class NetAppEseriesLibraryMultiAttachTestCase(test.TestCase):
     """Test driver behavior when the netapp_enable_multiattach
     configuration option is True.
     """
 
     def setUp(self):
-        super(NetAppEseriesISCSIDriverMultiAttachTestCase, self).setUp()
+        super(NetAppEseriesLibraryMultiAttachTestCase, self).setUp()
         config = eseries_fakes.create_configuration_eseries()
         config.netapp_enable_multiattach = True
 
         kwargs = {'configuration': config}
 
-        self.driver = es_iscsi.NetAppEseriesISCSIDriver(**kwargs)
-        self.driver._client = eseries_fakes.FakeEseriesClient()
-        self.driver.check_for_setup_error()
+        self.library = library.NetAppESeriesLibrary("FAKE", **kwargs)
+        self.library._client = eseries_fakes.FakeEseriesClient()
+        self.library.check_for_setup_error()
 
     def test_do_setup_host_group_already_exists(self):
         mock_check_flags = self.mock_object(na_utils, 'check_flags')
-        self.mock_object(es_iscsi.NetAppEseriesISCSIDriver,
+        self.mock_object(self.library,
                          '_check_mode_get_or_register_storage_system')
         fake_rest_client = eseries_fakes.FakeEseriesClient()
-        self.mock_object(self.driver, '_create_rest_client',
+        self.mock_object(self.library, '_create_rest_client',
                          mock.Mock(return_value=fake_rest_client))
         mock_create = self.mock_object(fake_rest_client, 'create_host_group')
 
-        self.driver.do_setup(mock.Mock())
+        self.library.do_setup(mock.Mock())
 
         self.assertTrue(mock_check_flags.called)
         self.assertFalse(mock_create.call_count)
@@ -346,178 +345,180 @@ class NetAppEseriesISCSIDriverMultiAttachTestCase(test.TestCase):
     def test_do_setup_host_group_does_not_exist(self):
         mock_check_flags = self.mock_object(na_utils, 'check_flags')
         fake_rest_client = eseries_fakes.FakeEseriesClient()
-        self.mock_object(self.driver, '_create_rest_client',
+        self.mock_object(self.library, '_create_rest_client',
                          mock.Mock(return_value=fake_rest_client))
         mock_get_host_group = self.mock_object(
             fake_rest_client, "get_host_group_by_name",
             mock.Mock(side_effect=exception.NotFound))
-        self.mock_object(es_iscsi.NetAppEseriesISCSIDriver,
+        self.mock_object(self.library,
                          '_check_mode_get_or_register_storage_system')
 
-        self.driver.do_setup(mock.Mock())
+        self.library.do_setup(mock.Mock())
 
         self.assertTrue(mock_check_flags.called)
         self.assertTrue(mock_get_host_group.call_count)
 
     def test_create_volume(self):
-        self.driver._client.create_volume = mock.Mock(
+        self.library._client.create_volume = mock.Mock(
             return_value=eseries_fakes.VOLUME)
 
-        self.driver.create_volume(get_fake_volume())
-        self.assertTrue(self.driver._client.create_volume.call_count)
+        self.library.create_volume(get_fake_volume())
+        self.assertTrue(self.library._client.create_volume.call_count)
 
     def test_create_volume_too_many_volumes(self):
-        self.driver._client.list_volumes = mock.Mock(
+        self.library._client.list_volumes = mock.Mock(
             return_value=[eseries_fakes.VOLUME for __ in
                           range(utils.MAX_LUNS_PER_HOST_GROUP + 1)])
-        self.driver._client.create_volume = mock.Mock(
+        self.library._client.create_volume = mock.Mock(
             return_value=eseries_fakes.VOLUME)
 
         self.assertRaises(exception.NetAppDriverException,
-                          self.driver.create_volume,
+                          self.library.create_volume,
                           get_fake_volume())
-        self.assertFalse(self.driver._client.create_volume.call_count)
+        self.assertFalse(self.library._client.create_volume.call_count)
 
     def test_create_volume_from_snapshot(self):
         fake_eseries_volume = copy.deepcopy(eseries_fakes.VOLUME)
-        self.mock_object(self.driver, "_schedule_and_create_volume",
+        self.mock_object(self.library, "_schedule_and_create_volume",
                          mock.Mock(return_value=fake_eseries_volume))
-        self.mock_object(self.driver, "_create_snapshot_volume",
+        self.mock_object(self.library, "_create_snapshot_volume",
                          mock.Mock(return_value=fake_eseries_volume))
-        self.mock_object(self.driver._client, "delete_snapshot_volume")
+        self.mock_object(self.library._client, "delete_snapshot_volume")
 
-        self.driver.create_volume_from_snapshot(
+        self.library.create_volume_from_snapshot(
             get_fake_volume(), fake_snapshot.fake_snapshot_obj(None))
 
         self.assertEqual(
-            1, self.driver._schedule_and_create_volume.call_count)
-        self.assertEqual(1, self.driver._create_snapshot_volume.call_count)
+            1, self.library._schedule_and_create_volume.call_count)
+        self.assertEqual(1, self.library._create_snapshot_volume.call_count)
         self.assertEqual(
-            1, self.driver._client.delete_snapshot_volume.call_count)
+            1, self.library._client.delete_snapshot_volume.call_count)
 
     def test_create_volume_from_snapshot_create_fails(self):
         fake_dest_eseries_volume = copy.deepcopy(eseries_fakes.VOLUME)
-        self.mock_object(self.driver, "_schedule_and_create_volume",
+        self.mock_object(self.library, "_schedule_and_create_volume",
                          mock.Mock(return_value=fake_dest_eseries_volume))
-        self.mock_object(self.driver, "_create_snapshot_volume",
+        self.mock_object(self.library, "_create_snapshot_volume",
                          mock.Mock(side_effect=exception.NetAppDriverException)
                          )
-        self.mock_object(self.driver._client, "delete_snapshot_volume")
-        self.mock_object(self.driver._client, "delete_volume")
+        self.mock_object(self.library._client, "delete_snapshot_volume")
+        self.mock_object(self.library._client, "delete_volume")
 
         self.assertRaises(exception.NetAppDriverException,
-                          self.driver.create_volume_from_snapshot,
+                          self.library.create_volume_from_snapshot,
                           get_fake_volume(),
                           fake_snapshot.fake_snapshot_obj(None))
 
         self.assertEqual(
-            1, self.driver._schedule_and_create_volume.call_count)
-        self.assertEqual(1, self.driver._create_snapshot_volume.call_count)
+            1, self.library._schedule_and_create_volume.call_count)
+        self.assertEqual(1, self.library._create_snapshot_volume.call_count)
         self.assertEqual(
-            0, self.driver._client.delete_snapshot_volume.call_count)
+            0, self.library._client.delete_snapshot_volume.call_count)
         # Ensure the volume we were going to copy to is cleaned up
-        self.driver._client.delete_volume.assert_called_once_with(
+        self.library._client.delete_volume.assert_called_once_with(
             fake_dest_eseries_volume['volumeRef'])
 
     def test_create_volume_from_snapshot_copy_job_fails(self):
         fake_dest_eseries_volume = copy.deepcopy(eseries_fakes.VOLUME)
-        self.mock_object(self.driver, "_schedule_and_create_volume",
+        self.mock_object(self.library, "_schedule_and_create_volume",
                          mock.Mock(return_value=fake_dest_eseries_volume))
-        self.mock_object(self.driver, "_create_snapshot_volume",
+        self.mock_object(self.library, "_create_snapshot_volume",
                          mock.Mock(return_value=fake_dest_eseries_volume))
-        self.mock_object(self.driver._client, "delete_snapshot_volume")
-        self.mock_object(self.driver._client, "delete_volume")
+        self.mock_object(self.library._client, "delete_snapshot_volume")
+        self.mock_object(self.library._client, "delete_volume")
 
         fake_failed_volume_copy_job = copy.deepcopy(
             eseries_fakes.VOLUME_COPY_JOB)
         fake_failed_volume_copy_job['status'] = 'failed'
-        self.mock_object(self.driver._client,
+        self.mock_object(self.library._client,
                          "create_volume_copy_job",
                          mock.Mock(return_value=fake_failed_volume_copy_job))
-        self.mock_object(self.driver._client,
+        self.mock_object(self.library._client,
                          "list_vol_copy_job",
                          mock.Mock(return_value=fake_failed_volume_copy_job))
 
         self.assertRaises(exception.NetAppDriverException,
-                          self.driver.create_volume_from_snapshot,
+                          self.library.create_volume_from_snapshot,
                           get_fake_volume(),
                           fake_snapshot.fake_snapshot_obj(None))
 
         self.assertEqual(
-            1, self.driver._schedule_and_create_volume.call_count)
-        self.assertEqual(1, self.driver._create_snapshot_volume.call_count)
+            1, self.library._schedule_and_create_volume.call_count)
+        self.assertEqual(1, self.library._create_snapshot_volume.call_count)
         self.assertEqual(
-            1, self.driver._client.delete_snapshot_volume.call_count)
+            1, self.library._client.delete_snapshot_volume.call_count)
         # Ensure the volume we were going to copy to is cleaned up
-        self.driver._client.delete_volume.assert_called_once_with(
+        self.library._client.delete_volume.assert_called_once_with(
             fake_dest_eseries_volume['volumeRef'])
 
     def test_create_volume_from_snapshot_fail_to_delete_snapshot_volume(self):
         fake_dest_eseries_volume = copy.deepcopy(eseries_fakes.VOLUME)
         fake_dest_eseries_volume['volumeRef'] = 'fake_volume_ref'
-        self.mock_object(self.driver, "_schedule_and_create_volume",
+        self.mock_object(self.library, "_schedule_and_create_volume",
                          mock.Mock(return_value=fake_dest_eseries_volume))
-        self.mock_object(self.driver, "_create_snapshot_volume",
+        self.mock_object(self.library, "_create_snapshot_volume",
                          mock.Mock(return_value=copy.deepcopy(
                              eseries_fakes.VOLUME)))
-        self.mock_object(self.driver._client, "delete_snapshot_volume",
+        self.mock_object(self.library._client, "delete_snapshot_volume",
                          mock.Mock(side_effect=exception.NetAppDriverException)
                          )
-        self.mock_object(self.driver._client, "delete_volume")
+        self.mock_object(self.library._client, "delete_volume")
 
-        self.driver.create_volume_from_snapshot(
+        self.library.create_volume_from_snapshot(
             get_fake_volume(), fake_snapshot.fake_snapshot_obj(None))
 
         self.assertEqual(
-            1, self.driver._schedule_and_create_volume.call_count)
-        self.assertEqual(1, self.driver._create_snapshot_volume.call_count)
+            1, self.library._schedule_and_create_volume.call_count)
+        self.assertEqual(1, self.library._create_snapshot_volume.call_count)
         self.assertEqual(
-            1, self.driver._client.delete_snapshot_volume.call_count)
+            1, self.library._client.delete_snapshot_volume.call_count)
         # Ensure the volume we created is not cleaned up
-        self.assertEqual(0, self.driver._client.delete_volume.call_count)
+        self.assertEqual(0, self.library._client.delete_volume.call_count)
 
-    def test_initialize_connection_volume_not_mapped(self):
-        """Map the volume directly to destination host.
-        """
-        connector = {'initiator': eseries_fakes.INITIATOR_NAME_2}
-        self.mock_object(self.driver._client, 'get_volume_mappings',
+    def test_map_volume_to_host_volume_not_mapped(self):
+        """Map the volume directly to destination host."""
+        self.mock_object(self.library._client, 'get_volume_mappings',
                          mock.Mock(return_value=[]))
         self.mock_object(host_mapper, 'map_volume_to_single_host',
                          mock.Mock(
                              return_value=eseries_fakes.VOLUME_MAPPING))
 
-        self.driver.initialize_connection(get_fake_volume(), connector)
+        self.library.map_volume_to_host(get_fake_volume(),
+                                        eseries_fakes.VOLUME,
+                                        eseries_fakes.INITIATOR_NAME_2)
 
-        self.assertTrue(self.driver._client.get_volume_mappings.called)
+        self.assertTrue(self.library._client.get_volume_mappings.called)
         self.assertTrue(host_mapper.map_volume_to_single_host.called)
 
-    def test_initialize_connection_volume_not_mapped_host_does_not_exist(self):
+    def test_map_volume_to_host_volume_not_mapped_host_does_not_exist(self):
         """Should create the host map directly to the host."""
-        connector = {'initiator': eseries_fakes.INITIATOR_NAME_2}
-        self.mock_object(self.driver._client, 'list_hosts',
+        self.mock_object(self.library._client, 'list_hosts',
                          mock.Mock(return_value=[]))
-        self.mock_object(self.driver._client, 'create_host_with_port',
+        self.mock_object(self.library._client, 'create_host_with_port',
                          mock.Mock(
                              return_value=eseries_fakes.HOST_2))
-        self.mock_object(self.driver._client, 'get_volume_mappings',
+        self.mock_object(self.library._client, 'get_volume_mappings',
                          mock.Mock(return_value=[]))
         self.mock_object(host_mapper, 'map_volume_to_single_host',
                          mock.Mock(
                              return_value=eseries_fakes.VOLUME_MAPPING))
 
-        self.driver.initialize_connection(get_fake_volume(), connector)
+        self.library.map_volume_to_host(get_fake_volume(),
+                                        eseries_fakes.VOLUME,
+                                        eseries_fakes.INITIATOR_NAME_2)
 
-        self.assertTrue(self.driver._client.create_host_with_port.called)
-        self.assertTrue(self.driver._client.get_volume_mappings.called)
+        self.assertTrue(self.library._client.create_host_with_port.called)
+        self.assertTrue(self.library._client.get_volume_mappings.called)
         self.assertTrue(host_mapper.map_volume_to_single_host.called)
 
-    def test_initialize_connection_volume_already_mapped(self):
+    def test_map_volume_to_host_volume_already_mapped(self):
         """Should be a no-op."""
-        connector = {'initiator': eseries_fakes.INITIATOR_NAME}
         self.mock_object(host_mapper, 'map_volume_to_multiple_hosts',
                          mock.Mock(
                              return_value=eseries_fakes.VOLUME_MAPPING))
 
-        self.driver.initialize_connection(get_fake_volume(), connector)
+        self.library.map_volume_to_host(get_fake_volume(),
+                                        eseries_fakes.VOLUME,
+                                        eseries_fakes.INITIATOR_NAME)
 
         self.assertTrue(host_mapper.map_volume_to_multiple_hosts.called)
index c08932eee3b1fd8c328baf1b827a4c5de74c3c3f..90480993b9728d42123ba47703c035b82bf4403e 100644 (file)
@@ -49,7 +49,7 @@ NETAPP_UNIFIED_DRIVER_REGISTRY = {
     },
     'eseries':
     {
-        'iscsi': ESERIES_PATH + '.iscsi.NetAppEseriesISCSIDriver'
+        'iscsi': ESERIES_PATH + '.iscsi_driver.NetAppEseriesISCSIDriver'
     }}
 
 
diff --git a/cinder/volume/drivers/netapp/eseries/iscsi_driver.py b/cinder/volume/drivers/netapp/eseries/iscsi_driver.py
new file mode 100644 (file)
index 0000000..3de100b
--- /dev/null
@@ -0,0 +1,97 @@
+# Copyright (c) 2014 NetApp, Inc.  All Rights Reserved.
+# Copyright (c) 2015 Alex Meade.  All Rights Reserved.
+# Copyright (c) 2015 Rushil Chugh.  All Rights Reserved.
+# Copyright (c) 2015 Navneet Singh.  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.
+"""
+iSCSI driver for NetApp E-series storage systems.
+"""
+
+from oslo_log import log as logging
+
+from cinder.volume import driver
+from cinder.volume.drivers.netapp.eseries import library
+from cinder.volume.drivers.netapp import utils as na_utils
+
+
+LOG = logging.getLogger(__name__)
+
+
+class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
+
+    DRIVER_NAME = 'NetApp_iSCSI_ESeries'
+
+    def __init__(self, *args, **kwargs):
+        super(NetAppEseriesISCSIDriver, self).__init__(*args, **kwargs)
+        na_utils.validate_instantiation(**kwargs)
+        self.library = library.NetAppESeriesLibrary(self.DRIVER_NAME,
+                                                    'iSCSI', **kwargs)
+
+    def do_setup(self, context):
+        self.library.do_setup(context)
+
+    def check_for_setup_error(self):
+        self.library.check_for_setup_error()
+
+    def create_volume(self, volume):
+        self.library.create_volume(volume)
+
+    def create_volume_from_snapshot(self, volume, snapshot):
+        self.library.create_volume_from_snapshot(volume, snapshot)
+
+    def create_cloned_volume(self, volume, src_vref):
+        self.library.create_cloned_volume(volume, src_vref)
+
+    def delete_volume(self, volume):
+        self.library.delete_volume(volume)
+
+    def create_snapshot(self, snapshot):
+        self.library.create_snapshot(snapshot)
+
+    def delete_snapshot(self, snapshot):
+        self.library.delete_snapshot(snapshot)
+
+    def get_volume_stats(self, refresh=False):
+        return self.library.get_volume_stats(refresh)
+
+    def extend_volume(self, volume, new_size):
+        self.library.extend_volume(volume, new_size)
+
+    def ensure_export(self, context, volume):
+        return self.library.ensure_export(context, volume)
+
+    def create_export(self, context, volume):
+        return self.library.create_export(context, volume)
+
+    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)
+
+    def initialize_connection(self, volume, connector):
+        return self.library.initialize_connection_iscsi(volume, connector)
+
+    def terminate_connection(self, volume, connector, **kwargs):
+        return self.library.terminate_connection_iscsi(volume, connector,
+                                                       **kwargs)
+
+    def get_pool(self, volume):
+        return self.library.get_pool(volume)
similarity index 97%
rename from cinder/volume/drivers/netapp/eseries/iscsi.py
rename to cinder/volume/drivers/netapp/eseries/library.py
index d4a288ff825d846b8dcce23248eedeaa6ae36b61..ff8ef845421d44f744ad0c616f0ad50fa8dab9af 100644 (file)
@@ -14,9 +14,6 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
-"""
-iSCSI driver for NetApp E-series storage systems.
-"""
 
 import copy
 import math
@@ -34,7 +31,6 @@ from cinder import exception
 from cinder.i18n import _, _LE, _LI, _LW
 from cinder.openstack.common import loopingcall
 from cinder import utils as cinder_utils
-from cinder.volume import driver
 from cinder.volume.drivers.netapp.eseries import client
 from cinder.volume.drivers.netapp.eseries import exception as eseries_exc
 from cinder.volume.drivers.netapp.eseries import host_mapper
@@ -46,7 +42,6 @@ from cinder.volume import utils as volume_utils
 
 LOG = logging.getLogger(__name__)
 
-
 CONF = cfg.CONF
 CONF.register_opts(na_opts.netapp_basicauth_opts)
 CONF.register_opts(na_opts.netapp_connection_opts)
@@ -55,7 +50,7 @@ CONF.register_opts(na_opts.netapp_transport_opts)
 CONF.register_opts(na_opts.netapp_san_opts)
 
 
-class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
+class NetAppESeriesLibrary(object):
     """Executes commands relating to Volumes."""
 
     VERSION = "1.0.0"
@@ -97,9 +92,9 @@ class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
 
     DEFAULT_HOST_TYPE = 'linux_dm_mp'
 
-    def __init__(self, *args, **kwargs):
-        super(NetAppEseriesISCSIDriver, self).__init__(*args, **kwargs)
-        na_utils.validate_instantiation(**kwargs)
+    def __init__(self, driver_name, driver_protocol="iSCSI",
+                 configuration=None, **kwargs):
+        self.configuration = configuration
         self.configuration.append_config_values(na_opts.netapp_basicauth_opts)
         self.configuration.append_config_values(
             na_opts.netapp_connection_opts)
@@ -108,6 +103,9 @@ class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
         self.configuration.append_config_values(na_opts.netapp_san_opts)
         self._backend_name = self.configuration.safe_get(
             "volume_backend_name") or "NetApp_ESeries"
+        self.driver_name = driver_name
+        self.driver_protocol = driver_protocol
+        self._stats = {}
         self._ssc_stats = {}
 
     def do_setup(self, context):
@@ -457,7 +455,8 @@ class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
 
     def create_cloned_volume(self, volume, src_vref):
         """Creates a clone of the specified volume."""
-        snapshot = {'id': uuid.uuid4(), 'volume_id': src_vref['id']}
+        snapshot = {'id': uuid.uuid4(), 'volume_id': src_vref['id'],
+                    'volume': src_vref}
         self.create_snapshot(snapshot)
         try:
             self.create_volume_from_snapshot(volume, snapshot)
@@ -481,7 +480,7 @@ class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
         """Creates a snapshot."""
         snap_grp, snap_image = None, None
         snapshot_name = utils.convert_uuid_to_es_fmt(snapshot['id'])
-        os_vol = self.db.volume_get(self.context, snapshot['volume_id'])
+        os_vol = snapshot['volume']
         vol = self._get_volume(os_vol['name_id'])
         vol_size_gb = int(vol['totalSizeInBytes']) / units.Gi
         pools = self._get_sorted_available_storage_pools(vol_size_gb)
@@ -517,12 +516,10 @@ class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
         """Removes an export for a volume."""
         pass
 
-    def initialize_connection(self, volume, connector):
-        """Allow connection to connector and return connection info."""
-        initiator_name = connector['initiator']
-        eseries_vol = self._get_volume(volume['name_id'])
+    def map_volume_to_host(self, volume, eseries_volume, initiator_name):
+        """Ensures the specified initiator has access to the volume."""
         existing_maps = host_mapper.get_host_mapping_for_vol_frm_array(
-            self._client, eseries_vol)
+            self._client, eseries_volume)
         host = self._get_or_create_host(initiator_name, self.host_type)
         # There can only be one or zero mappings on a volume in E-Series
         current_map = existing_maps[0] if existing_maps else None
@@ -531,13 +528,20 @@ class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
             self._ensure_multi_attach_host_group_exists()
             mapping = host_mapper.map_volume_to_multiple_hosts(self._client,
                                                                volume,
-                                                               eseries_vol,
+                                                               eseries_volume,
                                                                host,
                                                                current_map)
         else:
             mapping = host_mapper.map_volume_to_single_host(
-                self._client, volume, eseries_vol, host, current_map,
+                self._client, volume, eseries_volume, host, current_map,
                 self.configuration.netapp_enable_multiattach)
+        return mapping
+
+    def initialize_connection_iscsi(self, volume, connector):
+        """Allow connection to connector and return connection info."""
+        initiator_name = connector['initiator']
+        eseries_vol = self._get_volume(volume['name_id'])
+        mapping = self.map_volume_to_host(volume, eseries_vol, initiator_name)
 
         lun_id = mapping['lun']
         msg_fmt = {'id': volume['id'], 'initiator_name': initiator_name}
@@ -644,7 +648,7 @@ class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
                 return ht
         raise exception.NotFound(_("Host type %s not supported.") % host_type)
 
-    def terminate_connection(self, volume, connector, **kwargs):
+    def terminate_connection_iscsi(self, volume, connector, **kwargs):
         """Disallow connection from connector."""
         eseries_vol = self._get_volume(volume['name_id'])
         initiator = connector['initiator']
@@ -675,7 +679,7 @@ class NetAppEseriesISCSIDriver(driver.ISCSIDriver):
         data["volume_backend_name"] = self._backend_name
         data["vendor_name"] = "NetApp"
         data["driver_version"] = self.VERSION
-        data["storage_protocol"] = "iSCSI"
+        data["storage_protocol"] = self.driver_protocol
         data["pools"] = []
 
         for storage_pool in self._get_storage_pools():