]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Add iscsi_target_flags configuration option
authorPavel Boldin <pboldin@mirantis.com>
Wed, 13 May 2015 22:01:36 +0000 (01:01 +0300)
committerPavel Boldin <pboldin@mirantis.com>
Fri, 19 Jun 2015 21:12:24 +0000 (00:12 +0300)
Newly introduced `iscsi_target_flags' allows to specify `tgtd'
backing storage flags. This can be used to instruct `tgtd' to
open backing device file using `O_DIRECT' flag ensuring direct
access without cache.

DocImpact
Closes-Bug: #1441935
Change-Id: I9c7c88a7ae75096042104849c1b00aa47728e0d4

cinder/tests/unit/targets/test_tgt_driver.py
cinder/volume/driver.py
cinder/volume/targets/tgt.py

index e9455af85c89bf3401fe8f142baa7d8497d1f1a2..efcbe089df9ca4fdfa9eaa112a78b999aa063986 100644 (file)
@@ -28,6 +28,8 @@ class TestTgtAdmDriver(tf.TargetDriverFixture):
 
     def setUp(self):
         super(TestTgtAdmDriver, self).setUp()
+        self.configuration.get = mock.Mock(side_effect=self.fake_get)
+
         self.target = tgt.TgtAdm(root_helper=utils.get_root_helper(),
                                  configuration=self.configuration)
         self.testvol_path = \
@@ -74,6 +76,10 @@ class TestTgtAdmDriver(tf.TargetDriverFixture):
              '        ALL"\n' % {'test_vol': self.test_vol,
                                  'bspath': self.testvol_path})
 
+    def fake_get(self, value, default):
+        if value in ('iscsi_target_flags', 'iscsi_write_cache'):
+            return getattr(self, value, default)
+
     def test_iscsi_protocol(self):
         self.assertEqual(self.target.iscsi_protocol, 'iscsi')
 
@@ -183,6 +189,42 @@ class TestTgtAdmDriver(tf.TargetDriverFixture):
                     0,
                     self.fake_volumes_dir))
 
+    def test_create_iscsi_target_content(self):
+
+        self.iscsi_target_flags = 'foo'
+        self.iscsi_write_cache = 'bar'
+
+        mock_open = mock.mock_open()
+        with mock.patch('cinder.utils.execute', return_value=('', '')),\
+                mock.patch.object(self.target, '_get_target',
+                                  side_effect=lambda x: 1),\
+                mock.patch.object(self.target, '_verify_backing_lun',
+                                  side_effect=lambda x, y: True),\
+                mock.patch('cinder.volume.targets.tgt.open',
+                           mock_open, create=True):
+            self.assertEqual(
+                1,
+                self.target.create_iscsi_target(
+                    self.test_vol,
+                    1,
+                    0,
+                    self.testvol_path,
+                    chap_auth=('chap_foo', 'chap_bar')))
+
+        mock_open.assert_called_once_with(
+            os.path.join(self.fake_volumes_dir, self.test_vol.split(':')[1]),
+            'w+')
+        expected = ('\n<target iqn.2010-10.org.openstack:volume-%(id)s>\n'
+                    '    backing-store %(bspath)s\n'
+                    '    driver iscsi\n'
+                    '    incominguser chap_foo chap_bar\n'
+                    '    bsoflags foo\n'
+                    '    write-cache bar\n'
+                    '</target>\n' % {'id': self.VOLUME_ID,
+                                     'bspath': self.testvol_path})
+        self.assertEqual(expected,
+                         mock_open.return_value.write.call_args[0][0])
+
     def test_create_iscsi_target_already_exists(self):
         def _fake_execute(*args, **kwargs):
             if 'update' in args:
index 9704496956430ec7ec3ce9ea2e9a7f35bbd7819e..84ae879e6ebd3dd791de8d02e5fcc68199512fdc 100644 (file)
@@ -143,6 +143,12 @@ volume_opts = [
                     'perform write-back(on) or write-through(off). '
                     'This parameter is valid if iscsi_helper is set '
                     'to tgtadm or iseradm.'),
+    cfg.StrOpt('iscsi_target_flags',
+               default='',
+               help='Sets the target-specific flags for the iSCSI target. '
+                    'Only used for tgtadm to specify backing device flags '
+                    'using bsoflags option. The specified string is passed '
+                    'as is to the underlying tool.'),
     cfg.StrOpt('iscsi_protocol',
                default='iscsi',
                choices=['iscsi', 'iser'],
index 2b29536d9222386268f21f56e2dd1287a6644054..89be331b9ca4f1adc35b19e06d5fc6fa54337aa6 100644 (file)
@@ -12,6 +12,7 @@
 
 import os
 import re
+import textwrap
 import time
 
 from oslo_concurrency import processutils as putils
@@ -35,21 +36,15 @@ class TgtAdm(iscsi.ISCSITarget):
     etc.
     """
 
-    VOLUME_CONF = """
-                <target %s>
-                    backing-store %s
-                    driver %s
-                    write-cache %s
+    VOLUME_CONF = textwrap.dedent("""
+                <target %(name)s>
+                    backing-store %(path)s
+                    driver %(driver)s
+                    %(chap_auth)s
+                    %(target_flags)s
+                    write-cache %(write_cache)s
                 </target>
-                  """
-    VOLUME_CONF_WITH_CHAP_AUTH = """
-                                <target %s>
-                                    backing-store %s
-                                    driver %s
-                                    %s
-                                    write-cache %s
-                                </target>
-                                 """
+                  """)
 
     def __init__(self, *args, **kwargs):
         super(TgtAdm, self).__init__(*args, **kwargs)
@@ -178,14 +173,20 @@ class TgtAdm(iscsi.ISCSITarget):
         vol_id = name.split(':')[1]
         write_cache = self.configuration.get('iscsi_write_cache', 'on')
         driver = self.iscsi_protocol
+        chap_str = ''
 
-        if chap_auth is None:
-            volume_conf = self.VOLUME_CONF % (name, path, driver, write_cache)
-        else:
+        if chap_auth is not None:
             chap_str = 'incominguser %s %s' % chap_auth
-            volume_conf = self.VOLUME_CONF_WITH_CHAP_AUTH % (name, path,
-                                                             driver, chap_str,
-                                                             write_cache)
+
+        target_flags = self.configuration.get('iscsi_target_flags', '')
+        if target_flags:
+            target_flags = 'bsoflags ' + target_flags
+
+        volume_conf = self.VOLUME_CONF % {
+            'name': name, 'path': path, 'driver': driver,
+            'chap_auth': chap_str, 'target_flags': target_flags,
+            'write_cache': write_cache}
+
         LOG.debug('Creating iscsi_target for Volume ID: %s', vol_id)
         volumes_dir = self.volumes_dir
         volume_path = os.path.join(volumes_dir, vol_id)