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