import re
import socket
-from cinder.brick.initiator import connector
from cinder import context
from cinder import exception
from cinder.openstack.common import excutils
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':
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'],
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([
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'
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':
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()
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()
# 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})
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'),
self._storage_nodes = {}
self._enabled_protocols = set()
self._compression_enabled = False
+ self._available_iogrps = []
self._context = None
# Build cleanup translation tables for host names
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)
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:
'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):
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:
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',
% {'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.