]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Storwize/SVC: allow setting of I/O group
authorAvishay Traeger <avishay@il.ibm.com>
Thu, 22 Aug 2013 20:17:57 +0000 (23:17 +0300)
committerAvishay Traeger <avishay@il.ibm.com>
Fri, 23 Aug 2013 04:58:36 +0000 (07:58 +0300)
Allow setting the I/O group via config option or volume type. Also
updated comments and checks regarding iSCSI multipath, which is in Nova
and is not controlled by the driver.

Fixes: bug 1215363
Change-Id: Ia67fcb9991e21990cc81830145b8fd934a23488e

cinder/tests/test_storwize_svc.py
cinder/volume/drivers/storwize_svc.py

index 4192a37ce1d4e70b1d2d819ce43ca688fa26e6ac..b2a4949e5cf1bd2eb1b6db06011a4630596816fe 100644 (file)
@@ -29,7 +29,6 @@ import random
 import re
 import socket
 
-from cinder.brick.initiator import connector
 from cinder import context
 from cinder import exception
 from cinder.openstack.common import excutils
@@ -514,6 +513,8 @@ port_speed!N/A
         capacity = int(kwargs['size'])
         unit = kwargs['unit']
         volume_info['capacity'] = self._convert_units_bytes(capacity, unit)
+        volume_info['IO_group_id'] = kwargs['iogrp']
+        volume_info['IO_group_name'] = 'io_grp%s' % kwargs['iogrp']
 
         if 'easytier' in kwargs:
             if kwargs['easytier'] == 'on':
@@ -631,8 +632,8 @@ port_speed!N/A
                     cap = self._convert_bytes_units(vol['capacity'])
                 else:
                     cap = vol['capacity']
-                rows.append([str(vol['id']), vol['name'], '0', 'io_grp0',
-                            'online', '0',
+                rows.append([str(vol['id']), vol['name'], vol['IO_group_id'],
+                            vol['IO_group_name'], 'online', '0',
                             self._flags['storwize_svc_volpool_name'],
                             cap, 'striped',
                             fcmap_info['fc_id'], fcmap_info['fc_name'],
@@ -658,8 +659,8 @@ port_speed!N/A
 
             rows.append(['id', str(vol['id'])])
             rows.append(['name', vol['name']])
-            rows.append(['IO_group_id', '0'])
-            rows.append(['IO_group_name', 'io_grp0'])
+            rows.append(['IO_group_id', vol['IO_group_id']])
+            rows.append(['IO_group_name', vol['IO_group_name']])
             rows.append(['status', 'online'])
             rows.append(['mdisk_grp_id', '0'])
             rows.append([
@@ -712,6 +713,16 @@ port_speed!N/A
 
             return ('%s' % '\n'.join(rows), '')
 
+    def _cmd_lsiogrp(self, **kwargs):
+        rows = [None] * 6
+        rows[0] = ['id', 'name', 'node_count', 'vdisk_count', 'host_count']
+        rows[1] = ['0', 'io_grp0', '2', '22', '4']
+        rows[2] = ['1', 'io_grp1', '2', '22', '4']
+        rows[3] = ['2', 'io_grp2', '0', '0', '4']
+        rows[4] = ['3', 'io_grp3', '0', '0', '4']
+        rows[5] = ['4', 'recovery_io_grp', '0', '0', '0']
+        return self._print_info_cmd(rows=rows, **kwargs)
+
     def _add_port_to_host(self, host_info, **kwargs):
         if 'iscsiname' in kwargs:
             added_key = 'iscsi_names'
@@ -1178,6 +1189,8 @@ port_speed!N/A
             out, err = self._cmd_expandvdisksize(**kwargs)
         elif command == 'lsvdisk':
             out, err = self._cmd_lsvdisk(**kwargs)
+        elif command == 'lsiogrp':
+            out, err = self._cmd_lsiogrp(**kwargs)
         elif command == 'mkhost':
             out, err = self._cmd_mkhost(**kwargs)
         elif command == 'addhostport':
@@ -1297,7 +1310,7 @@ class StorwizeSVCDriverTestCase(test.TestCase):
             self.driver.configuration.set_override('rootwrap_config',
                                                    '/etc/cinder/rootwrap.conf',
                                                    config_group)
-            self._connector = connector.get_connector_properties()
+            self._connector = utils.brick_get_connector_properties()
 
         self._reset_flags()
         self.driver.db = StorwizeSVCFakeDB()
@@ -1385,8 +1398,7 @@ class StorwizeSVCDriverTestCase(test.TestCase):
                           self.driver.check_for_setup_error)
         self._reset_flags()
 
-        self._set_flag('storwize_svc_connection_protocol', 'iSCSI')
-        self._set_flag('storwize_svc_multipath_enabled', True)
+        self._set_flag('storwize_svc_vol_iogrp', 5)
         self.assertRaises(exception.InvalidInput,
                           self.driver.check_for_setup_error)
         self._reset_flags()
@@ -1590,17 +1602,22 @@ class StorwizeSVCDriverTestCase(test.TestCase):
         # compression   False   2,3
         # easytier      True    1,3
         # easytier      False   2
+        # iogrp         0       1
+        # iogrp         1       2
 
         opts_list = []
         chck_list = []
-        opts_list.append({'rsize': -1, 'easytier': True})
-        chck_list.append({'free_capacity': '0', 'easy_tier': 'on'})
+        opts_list.append({'rsize': -1, 'easytier': True, 'iogrp': 0})
+        chck_list.append({'free_capacity': '0', 'easy_tier': 'on',
+                          'IO_group_id': '0'})
+        test_iogrp = 1 if self.USESIM else 0
         opts_list.append({'rsize': 2, 'compression': False, 'warning': 0,
                           'autoexpand': True, 'grainsize': 32,
-                          'easytier': False})
+                          'easytier': False, 'iogrp': test_iogrp})
         chck_list.append({'-free_capacity': '0', 'compressed_copy': 'no',
                           'warning': '0', 'autoexpand': 'on',
-                          'grainsize': '32', 'easy_tier': 'off'})
+                          'grainsize': '32', 'easy_tier': 'off',
+                          'IO_group_id': str(test_iogrp)})
         opts_list.append({'rsize': 2, 'compression': False, 'warning': 80,
                           'autoexpand': False, 'grainsize': 256,
                           'easytier': True})
index 345e8e1c598fe3834b403ffba71ff0d301acf6b0..a6350796e558949706ea99a74cec50aa535b4180 100644 (file)
@@ -84,16 +84,20 @@ storwize_svc_opts = [
     cfg.BoolOpt('storwize_svc_vol_easytier',
                 default=True,
                 help='Enable Easy Tier for volumes'),
+    cfg.IntOpt('storwize_svc_vol_iogrp',
+               default=0,
+               help='The I/O group in which to allocate volumes'),
     cfg.IntOpt('storwize_svc_flashcopy_timeout',
                default=120,
                help='Maximum number of seconds to wait for FlashCopy to be '
-                    'prepared. Maximum value is 600 seconds (10 minutes).'),
+                    'prepared. Maximum value is 600 seconds (10 minutes)'),
     cfg.StrOpt('storwize_svc_connection_protocol',
                default='iSCSI',
                help='Connection protocol (iSCSI/FC)'),
     cfg.BoolOpt('storwize_svc_multipath_enabled',
                 default=False,
-                help='Connect with multipath (currently FC-only)'),
+                help='Connect with multipath (FC only; iSCSI multipath is '
+                     'controlled by Nova)'),
     cfg.BoolOpt('storwize_svc_multihostmap_enabled',
                 default=True,
                 help='Allows vdisk to multi host mapping'),
@@ -125,6 +129,7 @@ class StorwizeSVCDriver(san.SanDriver):
         self._storage_nodes = {}
         self._enabled_protocols = set()
         self._compression_enabled = False
+        self._available_iogrps = []
         self._context = None
 
         # Build cleanup translation tables for host names
@@ -209,6 +214,34 @@ class StorwizeSVCDriver(san.SanDriver):
         except exception.ProcessExecutionError:
             LOG.exception(_('Failed to get license information.'))
 
+        # Get the available I/O groups
+        ssh_cmd = ['svcinfo', 'lsiogrp', '-delim', '!']
+        out, err = self._run_ssh(ssh_cmd)
+        self._assert_ssh_return(len(out.strip()), 'do_setup',
+                                ssh_cmd, out, err)
+        iogrps = out.strip().split('\n')
+        self._assert_ssh_return(len(iogrps), 'do_setup', ssh_cmd, out, err)
+        header = iogrps.pop(0)
+        for iogrp_line in iogrps:
+            try:
+                iogrp_data = self._get_hdr_dic(header, iogrp_line, '!')
+                if (int(iogrp_data['node_count']) > 0 and
+                        int(iogrp_data['vdisk_count']) > 0):
+                    self._available_iogrps.append(int(iogrp_data['id']))
+            except exception.VolumeBackendAPIException:
+                with excutils.save_and_reraise_exception():
+                    self._log_cli_output_error('do_setup',
+                                               ssh_cmd, out, err)
+            except KeyError:
+                self._handle_keyerror('lsnode', header)
+            except ValueError:
+                msg = (_('Expected integers for node_count and vdisk_count, '
+                         'svcinfo lsiogrp returned: %(node)s and %(vdisk)s') %
+                       {'node': iogrp_data['node_count'],
+                        'vdisk': iogrp_data['vdisk_count']})
+                LOG.error(msg)
+                raise exception.VolumeBackendAPIException(data=msg)
+
         # Get the iSCSI and FC names of the Storwize/SVC nodes
         ssh_cmd = ['svcinfo', 'lsnode', '-delim', '!']
         out, err = self._run_ssh(ssh_cmd)
@@ -216,8 +249,7 @@ class StorwizeSVCDriver(san.SanDriver):
                                 ssh_cmd, out, err)
 
         nodes = out.strip().split('\n')
-        self._assert_ssh_return(len(nodes),
-                                'do_setup', ssh_cmd, out, err)
+        self._assert_ssh_return(len(nodes), 'do_setup', ssh_cmd, out, err)
         header = nodes.pop(0)
         for node_line in nodes:
             try:
@@ -285,7 +317,8 @@ class StorwizeSVCDriver(san.SanDriver):
                'compression': self.configuration.storwize_svc_vol_compression,
                'easytier': self.configuration.storwize_svc_vol_easytier,
                'protocol': protocol,
-               'multipath': self.configuration.storwize_svc_multipath_enabled}
+               'multipath': self.configuration.storwize_svc_multipath_enabled,
+               'iogrp': self.configuration.storwize_svc_vol_iogrp}
         return opt
 
     def check_for_setup_error(self):
@@ -760,8 +793,6 @@ class StorwizeSVCDriver(san.SanDriver):
             properties['volume_id'] = volume['id']
             if vol_opts['protocol'] == 'iSCSI':
                 type_str = 'iscsi'
-                # We take the first IP address for now. Ideally, OpenStack will
-                # support iSCSI multipath for improved performance.
                 if len(preferred_node_entry['ipv4']):
                     ipaddr = preferred_node_entry['ipv4'][0]
                 else:
@@ -949,7 +980,7 @@ class StorwizeSVCDriver(san.SanDriver):
 
         ssh_cmd = ['svctask', 'mkvdisk', '-name', name, '-mdiskgrp',
                    self.configuration.storwize_svc_volpool_name,
-                   '-iogrp', '0', '-size', size, '-unit',
+                   '-iogrp', str(opts['iogrp']), '-size', size, '-unit',
                    units, '-easytier', easytier] + ssh_cmd_se_opt
         out, err = self._run_ssh(ssh_cmd)
         self._assert_ssh_return(len(out.strip()), '_create_vdisk',
@@ -1476,12 +1507,12 @@ class StorwizeSVCDriver(san.SanDriver):
                 % {'prot': opts['protocol'],
                    'enabled': ','.join(self._enabled_protocols)})
 
-        # Check that multipath is only enabled for fc
-        if opts['protocol'] != 'FC' and opts['multipath']:
+        if opts['iogrp'] not in self._available_iogrps:
             raise exception.InvalidInput(
-                reason=_('Multipath is currently only supported for FC '
-                         'connections and not iSCSI.  (This is a Nova '
-                         'limitation.)'))
+                reason=_('I/O group %(iogrp)d is not valid; available '
+                         'I/O groups are %(avail)s')
+                % {'iogrp': opts['iogrp'],
+                   'avail': ''.join(str(e) for e in self._available_iogrps)})
 
     def _execute_command_and_parse_attributes(self, ssh_cmd):
         """Execute command on the Storwize/SVC and parse attributes.