Update the (unused) StorPool iSCSI support patch.

Change-Id: I32d12951663dab5fb3d675ad50ced70a426234f3
diff --git a/patches/openstack/cinder/storpool-iscsi.patch b/patches/openstack/cinder/storpool-iscsi.patch
index aade528..1f8dbbc 100644
--- a/patches/openstack/cinder/storpool-iscsi.patch
+++ b/patches/openstack/cinder/storpool-iscsi.patch
@@ -1,14 +1,19 @@
-From 48844314b876fd8f6983b457ba1e22e6e845a818 Mon Sep 17 00:00:00 2001
+From d3730dc49d52228fc771d514b853dc536ef1b534 Mon Sep 17 00:00:00 2001
 From: Peter Penchev <openstack-dev@storpool.com>
 Date: Mon, 12 Mar 2018 12:00:10 +0200
-Subject: [PATCH] Add iSCSI export support to the StorPool driver.
+Subject: [PATCH 8/8] Add iSCSI export support to the StorPool driver
 
 Add four new driver options:
 - iscsi_cinder_volume: use StorPool iSCSI attachments whenever
   the cinder-volume service needs to attach a volume to the controller,
   e.g. for copying an image to a volume or vice versa
-- iscsi_export_to: a list of IQN patterns that the driver should export
-  volumes to using iSCSI and not the native StorPool protocol
+- iscsi_export_to:
+  - an empty string to use the StorPool native protocol for exporting volumes
+    protocol for exporting volumes)
+  - the string "*" to always use iSCSI for exporting volumes
+  - an experimental, not fully supported list of IQN patterns to export
+    volumes to using iSCSI; this results in a Cinder driver that exports
+    different volumes using different storage protocols
 - iscsi_portal_group: the name of the iSCSI portal group defined in
   the StorPool configuration to use for these export
 - iscsi_learn_initiator_iqns: automatically create StorPool configuration
@@ -16,15 +21,23 @@
 
 Change-Id: I9de64306e0e6976268df782053b0651dd1cca96f
 ---
- .../unit/volume/drivers/test_storpool.py      |   7 +-
- cinder/volume/drivers/storpool.py             | 354 +++++++++++++++++-
- 2 files changed, 357 insertions(+), 4 deletions(-)
+ .../unit/volume/drivers/test_storpool.py      |  64 ++-
+ cinder/volume/drivers/storpool.py             | 369 +++++++++++++++++-
+ 2 files changed, 429 insertions(+), 4 deletions(-)
 
 diff --git a/cinder/tests/unit/volume/drivers/test_storpool.py b/cinder/tests/unit/volume/drivers/test_storpool.py
-index 843283db4..df57dee5d 100644
+index 51db7f292..aafaf7108 100644
 --- a/cinder/tests/unit/volume/drivers/test_storpool.py
 +++ b/cinder/tests/unit/volume/drivers/test_storpool.py
-@@ -181,6 +181,9 @@ class StorPoolTestCase(test.TestCase):
+@@ -32,6 +32,7 @@ fakeStorPool.sptypes = mock.Mock()
+ sys.modules['storpool'] = fakeStorPool
+ 
+ 
++from cinder.common import constants
+ from cinder import exception
+ from cinder.tests.unit import test
+ from cinder.volume import configuration as conf
+@@ -219,7 +220,14 @@ class StorPoolTestCase(test.TestCase):
          self.cfg.volume_backend_name = 'storpool_test'
          self.cfg.storpool_template = None
          self.cfg.storpool_replication = 3
@@ -32,9 +45,14 @@
 +        self.cfg.iscsi_export_to = ''
 +        self.cfg.iscsi_portal_group = 'test-group'
  
++        self._setup_test_driver()
++
++    def _setup_test_driver(self):
++        """Initialize a StorPool driver as per the current configuration."""
          mock_exec = mock.Mock()
          mock_exec.return_value = ('', '')
-@@ -190,7 +193,7 @@ class StorPoolTestCase(test.TestCase):
+ 
+@@ -228,7 +236,7 @@ class StorPoolTestCase(test.TestCase):
          self.driver.check_for_setup_error()
  
      @ddt.data(
@@ -43,7 +61,7 @@
          ({'no-host': None}, KeyError),
          ({'host': 'sbad'}, driver.StorPoolConfigurationInvalid),
          ({'host': 's01'}, None),
-@@ -206,7 +209,7 @@ class StorPoolTestCase(test.TestCase):
+@@ -244,7 +252,7 @@ class StorPoolTestCase(test.TestCase):
                                conn)
  
      @ddt.data(
@@ -52,8 +70,64 @@
          ({'no-host': None}, KeyError),
          ({'host': 'sbad'}, driver.StorPoolConfigurationInvalid),
      )
+@@ -635,3 +643,55 @@ class StorPoolTestCase(test.TestCase):
+                          self.driver.get_pool({
+                              'volume_type': volume_type
+                          }))
++
++    @ddt.data(
++        # The default values
++        ('', False, constants.STORPOOL, 'beleriand', False),
++
++        # Export to all
++        ('*', True, constants.ISCSI, 'beleriand', True),
++        ('*', True, constants.ISCSI, 'beleriand', True),
++
++        # Only export to the controller
++        ('', False, constants.STORPOOL, 'beleriand', False),
++
++        # Some of the not-fully-supported pattern lists
++        ('roh*', False, constants.STORPOOL, 'beleriand', False),
++        ('roh*', False, constants.STORPOOL, 'rohan', True),
++        ('*riand roh*', False, constants.STORPOOL, 'beleriand', True),
++        ('*riand roh*', False, constants.STORPOOL, 'rohan', True),
++    )
++    @ddt.unpack
++    def test_wants_iscsi(self, iscsi_export_to, use_iscsi, storage_protocol,
++                         hostname, expected):
++        """Check the "should this export use iSCSI?" detection."""
++        self.cfg.iscsi_export_to = iscsi_export_to
++        self._setup_test_driver()
++        self.assertEqual(self.driver._use_iscsi, use_iscsi)
++
++        # Make sure the driver reports the correct protocol in the stats
++        self.driver._update_volume_stats()
++        self.assertEqual(self.driver._stats["vendor_name"], "StorPool")
++        self.assertEqual(self.driver._stats["storage_protocol"],
++                         storage_protocol)
++
++        def check(conn, forced, expected):
++            """Pass partially or completely valid connector info."""
++            for initiator in (None, hostname):
++                for host in (None, 'gondor'):
++                    self.assertEqual(
++                        self.driver._connector_wants_iscsi({
++                            "host": host,
++                            "initiator": initiator,
++                            **conn,
++                        }),
++                        expected if initiator is not None and host is not None
++                        else forced)
++
++        # If iscsi_cinder_volume is set and this is the controller, then yes.
++        check({"storpool_wants_iscsi": True}, True, True)
++
++        # If iscsi_cinder_volume is not set or this is not the controller, then
++        # look at the specified expected value.
++        check({"storpool_wants_iscsi": False}, use_iscsi, expected)
++        check({}, use_iscsi, expected)
 diff --git a/cinder/volume/drivers/storpool.py b/cinder/volume/drivers/storpool.py
-index 0d2903684..7ab46e2a3 100644
+index 401e3709a..aeed8dc62 100644
 --- a/cinder/volume/drivers/storpool.py
 +++ b/cinder/volume/drivers/storpool.py
 @@ -15,6 +15,7 @@
@@ -64,7 +138,7 @@
  import platform
  
  from oslo_config import cfg
-@@ -41,6 +42,24 @@ if storpool:
+@@ -44,6 +45,31 @@ if storpool:
  
  
  storpool_opts = [
@@ -76,9 +150,16 @@
 +                     'an image or vice versa.'),
 +    cfg.StrOpt('iscsi_export_to',
 +               default='',
-+               help='Export volumes via iSCSI to the hosts with IQNs that '
-+                    'match the patterns in this list, e.g. '
-+                    '"iqn.1991-05.com.microsoft:*" for Windows hosts'),
++               help='Whether to export volumes using iSCSI. '
++                    'An empty string (the default) makes the driver export '
++                    'all volumes using the StorPool native network protocol. '
++                    'The value "*" makes the driver export all volumes using '
++                    'iSCSI. '
++                    'Any other value leads to an experimental not fully '
++                    'supported configuration and is interpreted as '
++                    'a whitespace-separated list of patterns for IQNs for '
++                    'hosts that need volumes to be exported via iSCSI, e.g. '
++                    '"iqn.1991-05.com.microsoft:*" for Windows hosts.'),
 +    cfg.BoolOpt('iscsi_learn_initiator_iqns',
 +                default=True,
 +                help='Create a StorPool record for a new initiator as soon as '
@@ -89,19 +170,23 @@
      cfg.StrOpt('storpool_template',
                 default=None,
                 help='The StorPool template for volumes with no type.'),
-@@ -92,9 +111,10 @@ class StorPoolDriver(driver.VolumeDriver):
-         1.2.3   - Advertise some more driver capabilities.
-         2.0.0   - Drop _attach_volume() and _detach_volume(), our os-brick
-                   connector will handle this.
-+                - Add support for exporting volumes via iSCSI.
+@@ -102,6 +128,7 @@ class StorPoolDriver(driver.VolumeDriver):
+                 - Declare the capability to clone a volume into a different
+                   pool, thus enabling the use of create_cloned_volume() for
+                   Cinder-backed Glance images on StorPool volumes
++                - Add support for exporting volumes via iSCSI
      """
  
--    VERSION = '1.2.3'
-+    VERSION = '2.0.0'
-     CI_WIKI_NAME = 'StorPool_distributed_storage_CI'
+     VERSION = '2.0.0'
+@@ -114,6 +141,7 @@ class StorPoolDriver(driver.VolumeDriver):
+         self._ourId = None
+         self._ourIdInt = None
+         self._attach = None
++        self._use_iscsi = None
  
-     def __init__(self, *args, **kwargs):
-@@ -161,10 +181,319 @@ class StorPoolDriver(driver.VolumeDriver):
+     @staticmethod
+     def get_driver_options():
+@@ -171,10 +199,322 @@ class StorPoolDriver(driver.VolumeDriver):
              raise StorPoolConfigurationInvalid(
                  section=hostname, param='SP_OURID', error=e)
  
@@ -115,6 +200,9 @@
 +        """
 +        if connector is None:
 +            return False
++        if self._use_iscsi:
++            LOG.debug('  - forcing iSCSI for all exported volumes')
++            return True
 +        if connector.get('storpool_wants_iscsi'):
 +            LOG.debug('  - forcing iSCSI for the controller')
 +            return True
@@ -421,7 +509,7 @@
          return {'driver_volume_type': 'storpool',
                  'data': {
                      'client_id': self._storpool_client_id(connector),
-@@ -173,6 +502,9 @@ class StorPoolDriver(driver.VolumeDriver):
+@@ -183,6 +523,9 @@ class StorPoolDriver(driver.VolumeDriver):
                  }}
  
      def terminate_connection(self, volume, connector, **kwargs):
@@ -431,8 +519,8 @@
          pass
  
      def create_snapshot(self, snapshot):
-@@ -224,11 +556,20 @@ class StorPoolDriver(driver.VolumeDriver):
-                           {'name': snapname, 'msg': e})
+@@ -284,11 +627,20 @@ class StorPoolDriver(driver.VolumeDriver):
+                     )
  
      def create_export(self, context, volume, connector):
 -        pass
@@ -453,7 +541,7 @@
      def delete_volume(self, volume):
          name = self._attach.volumeName(volume['id'])
          try:
-@@ -265,6 +606,15 @@ class StorPoolDriver(driver.VolumeDriver):
+@@ -325,6 +677,17 @@ class StorPoolDriver(driver.VolumeDriver):
              LOG.error("StorPoolDriver API initialization failed: %s", e)
              raise
  
@@ -466,9 +554,22 @@
 +                    'any patterns are listed in "iscsi_export_to"')
 +            raise exception.VolumeDriverException(message=msg)
 +
++        self._use_iscsi = export_to == "*"
++
      def _update_volume_stats(self):
          try:
              dl = self._attach.api().disksList()
+@@ -368,7 +731,9 @@ class StorPoolDriver(driver.VolumeDriver):
+                 'volume_backend_name') or 'storpool',
+             'vendor_name': 'StorPool',
+             'driver_version': self.VERSION,
+-            'storage_protocol': constants.STORPOOL,
++            'storage_protocol': (
++                constants.ISCSI if self._use_iscsi else constants.STORPOOL
++            ),
+ 
+             'clone_across_pools': True,
+             'sparse_copy_volume': True,
 -- 
-2.33.0
+2.35.1