Merge "IBM Storwize with pool-aware-cinder-scheduler"

This commit is contained in:
Jenkins 2016-03-01 16:38:10 +00:00 committed by Gerrit Code Review
commit ca90a150b8
5 changed files with 257 additions and 134 deletions

View File

@ -45,6 +45,7 @@ from cinder.volume.drivers.ibm.storwize_svc import storwize_svc_common
from cinder.volume.drivers.ibm.storwize_svc import storwize_svc_fc
from cinder.volume.drivers.ibm.storwize_svc import storwize_svc_iscsi
from cinder.volume import qos_specs
from cinder.volume import utils as volume_utils
from cinder.volume import volume_types
@ -379,25 +380,30 @@ class StorwizeSVCManagementSimulator(object):
# Print mostly made-up stuff in the correct syntax, assume -bytes passed
def _cmd_lsmdiskgrp(self, **kwargs):
rows = [None] * 4
rows[0] = ['id', 'name', 'status', 'mdisk_count',
'vdisk_count', 'capacity', 'extent_size',
'free_capacity', 'virtual_capacity', 'used_capacity',
'real_capacity', 'overallocation', 'warning',
'easy_tier', 'easy_tier_status']
rows[1] = ['1', self._flags['storwize_svc_volpool_name'], 'online',
'1', six.text_type(len(self._volumes_list)),
'3573412790272', '256', '3529926246400', '1693247906775',
'277841182', '38203734097', '47', '80', 'auto',
'inactive']
rows[2] = ['2', 'openstack2', 'online',
'1', '0', '3573412790272', '256',
'3529432325160', '1693247906775', '277841182',
'38203734097', '47', '80', 'auto', 'inactive']
rows[3] = ['3', 'openstack3', 'online',
'1', '0', '3573412790272', '128',
'3529432325160', '1693247906775', '277841182',
'38203734097', '47', '80', 'auto', 'inactive']
pool_num = len(self._flags['storwize_svc_volpool_name'])
rows = []
rows.append(['id', 'name', 'status', 'mdisk_count',
'vdisk_count', 'capacity', 'extent_size',
'free_capacity', 'virtual_capacity', 'used_capacity',
'real_capacity', 'overallocation', 'warning',
'easy_tier', 'easy_tier_status'])
for i in range(0, pool_num):
row_data = [str(i + 1),
self._flags['storwize_svc_volpool_name'][i], 'online',
'1', six.text_type(len(self._volumes_list)),
'3573412790272', '256', '3529926246400',
'1693247906775',
'26843545600', '38203734097', '47', '80', 'auto',
'inactive']
rows.append(row_data)
rows.append([str(pool_num + 1), 'openstack2', 'online',
'1', '0', '3573412790272', '256',
'3529432325160', '1693247906775', '26843545600',
'38203734097', '47', '80', 'auto', 'inactive'])
rows.append([str(pool_num + 2), 'openstack3', 'online',
'1', '0', '3573412790272', '128',
'3529432325160', '1693247906775', '26843545600',
'38203734097', '47', '80', 'auto', 'inactive'])
if 'obj' not in kwargs:
return self._print_info_cmd(rows=rows, **kwargs)
else:
@ -405,19 +411,20 @@ class StorwizeSVCManagementSimulator(object):
if pool_name == kwargs['obj']:
raise exception.InvalidInput(
reason=_('obj missing quotes %s') % kwargs['obj'])
elif pool_name == self._flags['storwize_svc_volpool_name']:
row = rows[1]
elif pool_name in self._flags['storwize_svc_volpool_name']:
for each_row in rows:
if pool_name in each_row:
row = each_row
break
elif pool_name == 'openstack2':
row = rows[2]
row = rows[-2]
elif pool_name == 'openstack3':
row = rows[3]
row = rows[-1]
else:
return self._errors['CMMVC5754E']
objrows = []
for idx, val in enumerate(rows[0]):
objrows.append([val, row[idx]])
if 'nohdr' in kwargs:
for index in range(len(objrows)):
objrows[index] = ' '.join(objrows[index][1:])
@ -428,6 +435,19 @@ class StorwizeSVCManagementSimulator(object):
return ('%s' % '\n'.join(objrows), '')
def _get_mdiskgrp_id(self, mdiskgrp):
grp_num = len(self._flags['storwize_svc_volpool_name'])
if mdiskgrp in self._flags['storwize_svc_volpool_name']:
for i in range(grp_num):
if mdiskgrp == self._flags['storwize_svc_volpool_name'][i]:
return i + 1
elif mdiskgrp == 'openstack2':
return grp_num + 1
elif mdiskgrp == 'openstack3':
return grp_num + 2
else:
return None
# Print mostly made-up stuff in the correct syntax
def _cmd_lsnodecanister(self, **kwargs):
rows = [None] * 3
@ -622,6 +642,14 @@ port_speed!N/A
volume_info['id'] = self._find_unused_id(self._volumes_list)
volume_info['uid'] = ('ABCDEF' * 3) + ('0' * 14) + volume_info['id']
mdiskgrp = kwargs['mdiskgrp'].strip('\'\"')
if mdiskgrp == kwargs['mdiskgrp']:
raise exception.InvalidInput(
reason=_('mdiskgrp missing quotes %s') % kwargs['mdiskgrp'])
mdiskgrp_id = self._get_mdiskgrp_id(mdiskgrp)
volume_info['mdisk_grp_name'] = mdiskgrp
volume_info['mdisk_grp_id'] = str(mdiskgrp_id)
if 'name' in kwargs:
volume_info['name'] = kwargs['name'].strip('\'\"')
else:
@ -679,17 +707,12 @@ port_speed!N/A
'status': 'online',
'sync': 'yes',
'primary': 'yes',
'mdisk_grp_id': '1',
'mdisk_grp_name': self._flags['storwize_svc_volpool_name'],
'mdisk_grp_id': str(mdiskgrp_id),
'mdisk_grp_name': mdiskgrp,
'easy_tier': volume_info['easy_tier'],
'compressed_copy': volume_info['compressed_copy']}
volume_info['copies'] = {'0': vol_cp}
mdiskgrp = kwargs['mdiskgrp'].strip('\'\"')
if mdiskgrp == kwargs['mdiskgrp']:
raise exception.InvalidInput(
reason=_('mdiskgrp missing quotes %s') % kwargs['mdiskgrp'])
if volume_info['name'] in self._volumes_list:
return self._errors['CMMVC6035E']
else:
@ -775,13 +798,12 @@ port_speed!N/A
rows.append([six.text_type(vol['id']), vol['name'],
vol['IO_group_id'],
vol['IO_group_name'], 'online', '0',
self._flags['storwize_svc_volpool_name'],
self._flags['storwize_svc_volpool_name'][0],
cap, 'striped',
fcmap_info['fc_id'], fcmap_info['fc_name'],
'', '', vol['uid'],
fcmap_info['fc_map_count'], '1', 'empty',
'1', 'no'])
if 'obj' not in kwargs:
return self._print_info_cmd(rows=rows, **kwargs)
else:
@ -1512,12 +1534,8 @@ port_speed!N/A
copy_info['sync'] = 'no'
copy_info['primary'] = 'no'
copy_info['mdisk_grp_name'] = mdiskgrp
if mdiskgrp == self._flags['storwize_svc_volpool_name']:
copy_info['mdisk_grp_id'] = '1'
elif mdiskgrp == 'openstack2':
copy_info['mdisk_grp_id'] = '2'
elif mdiskgrp == 'openstack3':
copy_info['mdisk_grp_id'] = '3'
copy_info['mdisk_grp_id'] = str(self._get_mdiskgrp_id(mdiskgrp))
if 'easytier' in kwargs:
if kwargs['easytier'] == 'on':
copy_info['easy_tier'] = 'on'
@ -1778,7 +1796,7 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
self._def_flags = {'san_ip': 'hostname',
'san_login': 'user',
'san_password': 'pass',
'storwize_svc_volpool_name': 'openstack',
'storwize_svc_volpool_name': ['openstack'],
'storwize_svc_flashcopy_timeout': 20,
'storwize_svc_flashcopy_rate': 49,
'storwize_svc_multipath_enabled': False,
@ -1792,7 +1810,7 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
'host': 'storwize-svc-test',
'wwpns': wwpns,
'initiator': initiator}
self.sim = StorwizeSVCManagementSimulator('openstack')
self.sim = StorwizeSVCManagementSimulator(['openstack'])
self.iscsi_driver.set_fake_storage(self.sim)
self.ctxt = context.get_admin_context()
@ -1816,6 +1834,12 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
self._set_flag(k, v)
def _create_volume(self, **kwargs):
pool = self._def_flags['storwize_svc_volpool_name'][0]
prop = {'host': 'openstack@svc#%s' % pool,
'size': 1}
for p in prop.keys():
if p not in kwargs:
kwargs[p] = prop[p]
vol = testutils.create_volume(self.ctxt, **kwargs)
self.iscsi_driver.create_volume(vol)
return vol
@ -1825,6 +1849,7 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
self.db.volume_destroy(self.ctxt, volume['id'])
def _generate_vol_info(self, vol_name, vol_id):
pool = self._def_flags['storwize_svc_volpool_name'][0]
rand_id = six.text_type(random.randint(10000, 99999))
if vol_name:
return {'name': 'snap_volume%s' % rand_id,
@ -1832,13 +1857,14 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
'id': rand_id,
'volume_id': vol_id,
'volume_size': 10,
'mdisk_grp_name': 'openstack'}
'mdisk_grp_name': pool}
else:
return {'name': 'test_volume%s' % rand_id,
'size': 10,
'id': rand_id,
'volume_type_id': None,
'mdisk_grp_name': 'openstack'}
'mdisk_grp_name': pool,
'host': 'openstack@svc#%s' % pool}
def _assert_vol_exists(self, name, exists):
is_vol_defined = self.iscsi_driver._helpers.is_vdisk_defined(name)
@ -2106,7 +2132,8 @@ class StorwizeSVCFcDriverTestCase(test.TestCase):
self._def_flags = {'san_ip': 'hostname',
'san_login': 'user',
'san_password': 'pass',
'storwize_svc_volpool_name': 'openstack',
'storwize_svc_volpool_name':
['openstack', 'openstack1'],
'storwize_svc_flashcopy_timeout': 20,
'storwize_svc_flashcopy_rate': 49,
'storwize_svc_multipath_enabled': False,
@ -2120,7 +2147,8 @@ class StorwizeSVCFcDriverTestCase(test.TestCase):
'host': 'storwize-svc-test',
'wwpns': wwpns,
'initiator': initiator}
self.sim = StorwizeSVCManagementSimulator('openstack')
self.sim = StorwizeSVCManagementSimulator(['openstack',
'openstack1'])
self.fc_driver.set_fake_storage(self.sim)
self.ctxt = context.get_admin_context()
@ -2144,6 +2172,12 @@ class StorwizeSVCFcDriverTestCase(test.TestCase):
self._set_flag(k, v)
def _create_volume(self, **kwargs):
pool = self._def_flags['storwize_svc_volpool_name'][0]
prop = {'host': 'openstack@svc#%s' % pool,
'size': 1}
for p in prop.keys():
if p not in kwargs:
kwargs[p] = prop[p]
vol = testutils.create_volume(self.ctxt, **kwargs)
self.fc_driver.create_volume(vol)
return vol
@ -2153,6 +2187,7 @@ class StorwizeSVCFcDriverTestCase(test.TestCase):
self.db.volume_destroy(self.ctxt, volume['id'])
def _generate_vol_info(self, vol_name, vol_id):
pool = self._def_flags['storwize_svc_volpool_name'][0]
rand_id = six.text_type(random.randint(10000, 99999))
if vol_name:
return {'name': 'snap_volume%s' % rand_id,
@ -2160,13 +2195,14 @@ class StorwizeSVCFcDriverTestCase(test.TestCase):
'id': rand_id,
'volume_id': vol_id,
'volume_size': 10,
'mdisk_grp_name': 'openstack'}
'mdisk_grp_name': pool}
else:
return {'name': 'test_volume%s' % rand_id,
'size': 10,
'id': '%s' % rand_id,
'volume_type_id': None,
'mdisk_grp_name': 'openstack'}
'mdisk_grp_name': pool,
'host': 'openstack@svc#%s' % pool}
def _assert_vol_exists(self, name, exists):
is_vol_defined = self.fc_driver._helpers.is_vdisk_defined(name)
@ -2534,7 +2570,8 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
'storwize_san_secondary_ip': 'secondaryname',
'san_login': 'user',
'san_password': 'pass',
'storwize_svc_volpool_name': 'openstack',
'storwize_svc_volpool_name':
['openstack', 'openstack1'],
'storwize_svc_flashcopy_timeout': 20,
'storwize_svc_flashcopy_rate': 49,
'storwize_svc_allow_tenant_qos': True}
@ -2547,7 +2584,8 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
'host': 'storwize-svc-test',
'wwpns': wwpns,
'initiator': initiator}
self.sim = StorwizeSVCManagementSimulator('openstack')
self.sim = StorwizeSVCManagementSimulator(['openstack',
'openstack1'])
self.driver.set_fake_storage(self.sim)
self.ctxt = context.get_admin_context()
@ -2698,6 +2736,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
max_size=self._driver.configuration.ssh_max_pool_conn)
def _generate_vol_info(self, vol_name, vol_id):
pool = self._def_flags['storwize_svc_volpool_name'][0]
rand_id = six.text_type(random.randint(10000, 99999))
if vol_name:
return {'name': 'snap_volume%s' % rand_id,
@ -2705,15 +2744,22 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
'id': rand_id,
'volume_id': vol_id,
'volume_size': 10,
'mdisk_grp_name': 'openstack'}
'mdisk_grp_name': pool}
else:
return {'name': 'test_volume%s' % rand_id,
'size': 10,
'id': '%s' % rand_id,
'volume_type_id': None,
'mdisk_grp_name': 'openstack'}
'mdisk_grp_name': pool,
'host': 'openstack@svc#%s' % pool}
def _create_volume(self, **kwargs):
pool = self._def_flags['storwize_svc_volpool_name'][0]
prop = {'host': 'openstack@svc#%s' % pool,
'size': 1}
for p in prop.keys():
if p not in kwargs:
kwargs[p] = prop[p]
vol = testutils.create_volume(self.ctxt, **kwargs)
self.driver.create_volume(vol)
return vol
@ -3020,7 +3066,8 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
attributes = self.driver._helpers.get_vdisk_attributes(volume['name'])
attr_size = float(attributes['capacity']) / units.Gi # bytes to GB
self.assertEqual(attr_size, float(volume['size']))
pool = self.driver.configuration.local_conf.storwize_svc_volpool_name
pool =\
self.driver.configuration.local_conf.storwize_svc_volpool_name[0]
self.assertEqual(attributes['mdisk_grp_name'], pool)
# Try to create the volume again (should fail)
@ -3106,10 +3153,12 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
self.driver.do_setup(None)
rand_id = random.randint(10000, 99999)
pool = self._def_flags['storwize_svc_volpool_name'][0]
volume1 = {'name': u'unicode1_volume%s' % rand_id,
'size': 2,
'id': 1,
'volume_type_id': None}
'volume_type_id': None,
'host': 'openstack@svc#%s' % pool}
self.driver.create_volume(volume1)
self._assert_vol_exists(volume1['name'], True)
@ -3225,15 +3274,39 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
def test_storwize_svc_get_volume_stats(self):
self._set_flag('reserved_percentage', 25)
stats = self.driver.get_volume_stats()
self.assertLessEqual(stats['free_capacity_gb'],
stats['total_capacity_gb'])
self.assertEqual(25, stats['reserved_percentage'])
pool = self.driver.configuration.local_conf.storwize_svc_volpool_name
for each_pool in stats['pools']:
self.assertIn(each_pool['pool_name'],
self._def_flags['storwize_svc_volpool_name'])
self.assertLessEqual(each_pool['free_capacity_gb'],
each_pool['total_capacity_gb'])
self.assertLessEqual(each_pool['allocated_capacity_gb'],
each_pool['total_capacity_gb'])
self.assertEqual(25, each_pool['reserved_percentage'])
if self.USESIM:
expected = 'storwize-svc-sim_' + pool
expected = 'storwize-svc-sim'
self.assertEqual(expected, stats['volume_backend_name'])
self.assertAlmostEqual(3328.0, stats['total_capacity_gb'])
self.assertAlmostEqual(3287.5, stats['free_capacity_gb'])
for each_pool in stats['pools']:
self.assertIn(each_pool['pool_name'],
self._def_flags['storwize_svc_volpool_name'])
self.assertAlmostEqual(3328.0, each_pool['total_capacity_gb'])
self.assertAlmostEqual(3287.5, each_pool['free_capacity_gb'])
self.assertAlmostEqual(25.0,
each_pool['allocated_capacity_gb'])
def test_get_pool(self):
ctxt = testutils.get_test_admin_context()
type_ref = volume_types.create(ctxt, 'testtype', None)
volume = self._generate_vol_info(None, None)
type_id = type_ref['id']
type_ref = volume_types.get_volume_type(ctxt, type_id)
volume['volume_type_id'] = type_id
volume['volume_type'] = type_ref
self.driver.create_volume(volume)
self.assertEqual(volume['mdisk_grp_name'],
self.driver.get_pool(volume))
self.driver.delete_volume(volume)
volume_types.destroy(ctxt, type_ref['id'])
def test_storwize_svc_extend_volume(self):
volume = self._create_volume()
@ -3326,7 +3399,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
loc = ('StorwizeSVCDriver:' + self.driver._state['system_id'] +
':openstack2')
cap = {'location_info': loc, 'extent_size': '256'}
host = {'host': 'foo', 'capabilities': cap}
host = {'host': 'openstack@svc#openstack2', 'capabilities': cap}
ctxt = context.get_admin_context()
volume = self._create_volume()
volume['volume_type_id'] = None
@ -3444,7 +3517,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
':openstack')
cap = {'location_info': loc, 'extent_size': '128'}
self.driver._stats = {'location_info': loc}
host = {'host': 'foo', 'capabilities': cap}
host = {'host': 'openstack@svc#openstack', 'capabilities': cap}
ctxt = context.get_admin_context()
key_specs_old = {'easytier': False, 'warning': 2, 'autoexpand': True}
@ -3458,7 +3531,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
volume = self._generate_vol_info(None, None)
old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
volume['volume_type'] = old_type
volume['host'] = host
volume['host'] = 'openstack@svc#openstack'
new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])
self.driver.create_volume(volume)
@ -3534,7 +3607,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
':openstack')
cap = {'location_info': loc, 'extent_size': '128'}
self.driver._stats = {'location_info': loc}
host = {'host': 'foo', 'capabilities': cap}
host = {'host': 'openstack@svc#openstack', 'capabilities': cap}
ctxt = context.get_admin_context()
key_specs_old = {'iogrp': 0}
@ -3548,7 +3621,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
volume = self._generate_vol_info(None, None)
old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
volume['volume_type'] = old_type
volume['host'] = host
volume['host'] = 'openstack@svc#openstack'
new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])
self.driver.create_volume(volume)
@ -3569,7 +3642,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
':openstack')
cap = {'location_info': loc, 'extent_size': '128'}
self.driver._stats = {'location_info': loc}
host = {'host': 'foo', 'capabilities': cap}
host = {'host': 'openstack@svc#openstack', 'capabilities': cap}
ctxt = context.get_admin_context()
key_specs_old = {'compression': True, 'iogrp': 0}
@ -3583,7 +3656,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
volume = self._generate_vol_info(None, None)
old_type = volume_types.get_volume_type(ctxt, old_type_ref['id'])
volume['volume_type'] = old_type
volume['host'] = host
volume['host'] = 'openstack@svc#openstack'
new_type = volume_types.get_volume_type(ctxt, new_type_ref['id'])
self.driver.create_volume(volume)
@ -3688,7 +3761,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
ctxt = testutils.get_test_admin_context()
volume = self._create_volume()
driver = self.driver
dest_pool = self.driver.configuration.storwize_svc_volpool_name
dest_pool = volume_utils.extract_host(volume['host'], 'pool')
new_ops = driver._helpers.add_vdisk_copy(volume['name'], dest_pool,
None, self.driver._state,
self.driver.configuration)
@ -3864,7 +3937,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
':openstack')
cap = {'location_info': loc, 'extent_size': '128'}
self.driver._stats = {'location_info': loc}
host = {'host': 'foo', 'capabilities': cap}
host = {'host': 'openstack@svc#openstack', 'capabilities': cap}
ctxt = context.get_admin_context()
disable_type = self._create_replication_volume_type(False)
@ -3875,7 +3948,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
enable_type['id'])
volume = self._generate_vol_info(None, None)
volume['host'] = host
volume['host'] = 'openstack@svc#openstack'
volume['volume_type_id'] = disable_type['id']
volume['volume_type'] = disable_type
volume['replication_status'] = None
@ -3900,7 +3973,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
':openstack')
cap = {'location_info': loc, 'extent_size': '128'}
self.driver._stats = {'location_info': loc}
host = {'host': 'foo', 'capabilities': cap}
host = {'host': 'openstack@svc#openstack', 'capabilities': cap}
ctxt = context.get_admin_context()
volume = self._generate_vol_info(None, None)
@ -3908,6 +3981,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
volume['volume_type'] = None
volume['replication_status'] = "disabled"
volume['replication_extended_status'] = None
volume['host'] = 'openstack@svc#openstack'
# Create volume which is not volume replication
model_update = self.driver.create_volume(volume)
@ -4048,14 +4122,16 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
cg_type = self._create_consistency_group_volume_type()
self.ctxt.user_id = 'fake_user_id'
self.ctxt.project_id = 'fake_project_id'
pool = self._def_flags['storwize_svc_volpool_name'][0]
# Create cg in db
cg = self._create_consistencygroup_in_db(volume_type_id=cg_type['id'])
# Create volumes in db
testutils.create_volume(self.ctxt, volume_type_id=cg_type['id'],
consistencygroup_id=cg['id'])
consistencygroup_id=cg['id'],
host='openstack@svc#%s' % pool)
testutils.create_volume(self.ctxt, volume_type_id=cg_type['id'],
consistencygroup_id=cg['id'])
consistencygroup_id=cg['id'],
host='openstack@svc#%s' % pool)
volumes = (
self.db.volume_get_all_by_group(self.ctxt.elevated(), cg['id']))
@ -4073,6 +4149,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
cgsnapshot, snapshots = self._create_cgsnapshot(source_cg['id'])
# Create cg from source cg
model_update, volumes_model_update = (
self.driver.create_consistencygroup_from_src(self.ctxt,
cg,
@ -4336,7 +4413,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
new_volume['volume_type_id'] = type_thick_ref['id']
no_exist_pool = 'i-dont-exist-%s' % random.randint(10000, 99999)
self._set_flag('storwize_svc_volpool_name', no_exist_pool)
new_volume['host'] = 'openstack@svc#%s' % no_exist_pool
self.assertRaises(exception.ManageExistingVolumeTypeMismatch,
self.driver.manage_existing, new_volume, ref)
@ -4654,13 +4731,15 @@ class StorwizeSVCReplicationMirrorTestCase(test.TestCase):
self.svc_driver.replication_factory(self.rep_type, fake_target))
self.ctxt = context.get_admin_context()
rand_id = six.text_type(uuid.uuid4())
pool = self.svc_driver.configuration.storwize_svc_volpool_name[0]
self.volume = {'name': 'volume-%s' % rand_id,
'size': 10, 'id': '%s' % rand_id,
'volume_type_id': None,
'mdisk_grp_name': 'openstack',
'replication_status': 'disabled',
'replication_extended_status': None,
'volume_metadata': None}
'volume_metadata': None,
'host': 'openstack@svc#%s' % pool}
spec = {'replication_enabled': '<is> True',
'replication_type': extra_spec_rep_type}
type_ref = volume_types.create(self.ctxt, "replication", spec)
@ -4731,13 +4810,15 @@ class StorwizeSVCReplicationMirrorTestCase(test.TestCase):
get_vdisk_params.return_value = {'replication': None,
'qos': None}
rand_id = six.text_type(random.randint(10000, 99999))
pool = self.svc_driver.configuration.storwize_svc_volpool_name[0]
target_volume = {'name': 'test_volume%s' % rand_id,
'size': 10, 'id': '%s' % rand_id,
'volume_type_id': None,
'mdisk_grp_name': 'openstack',
'replication_status': 'disabled',
'replication_extended_status': None,
'volume_metadata': None}
'volume_metadata': None,
'host': 'openstack@svc#%s' % pool}
target_volume['volume_type_id'] = self.replication_type['id']
target_volume['volume_type'] = self.replication_type
model_update = self.svc_driver.create_cloned_volume(

View File

@ -52,9 +52,10 @@ DEFAULT_TIMEOUT = 15
LOG = logging.getLogger(__name__)
storwize_svc_opts = [
cfg.StrOpt('storwize_svc_volpool_name',
default='volpool',
help='Storage system storage pool for volumes'),
cfg.ListOpt('storwize_svc_volpool_name',
default=['volpool'],
help='Comma separated list of storage system storage '
'pools for volumes.'),
cfg.IntOpt('storwize_svc_vol_rsize',
default=2,
min=-1, max=100,
@ -1293,11 +1294,12 @@ class StorwizeHelpers(object):
for source, target in zip(sources, targets):
opts = self.get_vdisk_params(config, state,
source['volume_type_id'])
pool = utils.extract_host(target['host'], 'pool')
self.create_flashcopy_to_consistgrp(source['name'],
target['name'],
fc_consistgrp,
config, opts,
True)
True, pool=pool)
self.prepare_fc_consistgrp(fc_consistgrp, timeout)
self.start_fc_consistgrp(fc_consistgrp)
self.delete_fc_consistgrp(fc_consistgrp)
@ -1367,7 +1369,7 @@ class StorwizeHelpers(object):
src_size = src_attrs['capacity']
# In case we need to use a specific pool
if not pool:
pool = config.storwize_svc_volpool_name
pool = src_attrs['mdisk_grp_name']
self.create_vdisk(target, src_size, 'b', pool, opts)
self.ssh.mkfcmap(source, target, full_copy,
@ -1554,7 +1556,7 @@ class StorwizeHelpers(object):
src_size = src_attrs['capacity']
# In case we need to use a specific pool
if not pool:
pool = config.storwize_svc_volpool_name
pool = src_attrs['mdisk_grp_name']
self.create_vdisk(tgt, src_size, 'b', pool, opts)
timeout = config.storwize_svc_flashcopy_timeout
try:
@ -1898,12 +1900,7 @@ class StorwizeSVCCommonDriver(san.SanDriver,
self.replication = storwize_rep.StorwizeSVCReplication.factory(self)
# Validate that the pool exists
pool = self.configuration.storwize_svc_volpool_name
try:
self._helpers.get_pool_attrs(pool)
except exception.VolumeBackendAPIException:
msg = _('Failed getting details for pool %s.') % pool
raise exception.InvalidInput(reason=msg)
self._validate_pools_exist()
# Check if compression is supported
self._state['compression_enabled'] = (self._helpers.
@ -1940,6 +1937,16 @@ class StorwizeSVCCommonDriver(san.SanDriver,
# v2 replication setup
self._do_replication_setup()
def _validate_pools_exist(self):
# Validate that the pool exists
pools = self.configuration.storwize_svc_volpool_name
for pool in pools:
try:
self._helpers.get_pool_attrs(pool)
except exception.VolumeBackendAPIException:
msg = _('Failed getting details for pool %s.') % pool
raise exception.InvalidInput(reason=msg)
def check_for_setup_error(self):
"""Ensure that the flags are set properly."""
LOG.debug('enter: check_for_setup_error')
@ -2096,7 +2103,7 @@ class StorwizeSVCCommonDriver(san.SanDriver,
opts = self._get_vdisk_params(volume['volume_type_id'],
volume_metadata=
volume.get('volume_metadata'))
pool = self.configuration.storwize_svc_volpool_name
pool = utils.extract_host(volume['host'], 'pool')
self._helpers.create_vdisk(volume['name'], str(volume['size']),
'gb', pool, opts)
if opts['qos']:
@ -2142,10 +2149,11 @@ class StorwizeSVCCommonDriver(san.SanDriver,
msg = (_('create_snapshot: get source volume failed.'))
LOG.error(msg)
raise exception.VolumeDriverException(message=msg)
pool = utils.extract_host(source_vol['host'], 'pool')
opts = self._get_vdisk_params(source_vol['volume_type_id'])
self._helpers.create_copy(snapshot['volume_name'], snapshot['name'],
snapshot['volume_id'], self.configuration,
opts, False)
opts, False, pool=pool)
def delete_snapshot(self, snapshot):
self._helpers.delete_vdisk(snapshot['name'], False)
@ -2160,9 +2168,10 @@ class StorwizeSVCCommonDriver(san.SanDriver,
opts = self._get_vdisk_params(volume['volume_type_id'],
volume_metadata=
volume.get('volume_metadata'))
pool = utils.extract_host(volume['host'], 'pool')
self._helpers.create_copy(snapshot['name'], volume['name'],
snapshot['id'], self.configuration,
opts, True)
opts, True, pool=pool)
if opts['qos']:
self._helpers.add_vdisk_qos(volume['name'], opts['qos'])
@ -2190,9 +2199,10 @@ class StorwizeSVCCommonDriver(san.SanDriver,
opts = self._get_vdisk_params(tgt_volume['volume_type_id'],
volume_metadata=
tgt_volume.get('volume_metadata'))
pool = utils.extract_host(tgt_volume['host'], 'pool')
self._helpers.create_copy(src_volume['name'], tgt_volume['name'],
src_volume['id'], self.configuration,
opts, True)
opts, True, pool=pool)
if opts['qos']:
self._helpers.add_vdisk_qos(tgt_volume['name'], opts['qos'])
@ -2626,8 +2636,8 @@ class StorwizeSVCCommonDriver(san.SanDriver,
elif key in no_copy_keys:
vdisk_changes.append(key)
dest_location = host['capabilities'].get('location_info')
if self._stats['location_info'] != dest_location:
if (utils.extract_host(volume['host'], 'pool') !=
utils.extract_host(host['host'], 'pool')):
need_copy = True
if need_copy:
@ -2772,9 +2782,8 @@ class StorwizeSVCCommonDriver(san.SanDriver,
{'vdisk_iogrp': vdisk['IO_group_name'],
'opt_iogrp': opts['iogrp']})
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
if (vdisk['mdisk_grp_name'] !=
self.configuration.storwize_svc_volpool_name):
pool = utils.extract_host(volume['host'], 'pool')
if vdisk['mdisk_grp_name'] != pool:
msg = (_("Failed to manage existing volume due to the "
"pool of the volume to be managed does not "
"match the backend pool. Pool of the "
@ -2944,6 +2953,17 @@ class StorwizeSVCCommonDriver(san.SanDriver,
return model_update, snapshots_model
def get_pool(self, volume):
attr = self._helpers.get_vdisk_attributes(volume['name'])
if attr is None:
msg = (_('get_pool: Failed to get attributes for volume '
'%s') % volume['name'])
LOG.error(msg)
raise exception.VolumeDriverException(message=msg)
return attr['mdisk_grp_name']
def _update_volume_stats(self):
"""Retrieve stats info from volume group."""
@ -2953,47 +2973,64 @@ class StorwizeSVCCommonDriver(san.SanDriver,
data['vendor_name'] = 'IBM'
data['driver_version'] = self.VERSION
data['storage_protocol'] = self.protocol
data['pools'] = []
data['total_capacity_gb'] = 0 # To be overwritten
data['free_capacity_gb'] = 0 # To be overwritten
data['reserved_percentage'] = self.configuration.reserved_percentage
data['multiattach'] = (self.configuration.
storwize_svc_multihostmap_enabled)
data['QoS_support'] = True
data['consistencygroup_support'] = True
pool = self.configuration.storwize_svc_volpool_name
backend_name = self.configuration.safe_get('volume_backend_name')
if not backend_name:
backend_name = '%s_%s' % (self._state['system_name'], pool)
data['volume_backend_name'] = backend_name
attributes = self._helpers.get_pool_attrs(pool)
if not attributes:
LOG.error(_LE('Could not get pool data from the storage.'))
exception_message = (_('_update_volume_stats: '
'Could not get storage pool data.'))
raise exception.VolumeBackendAPIException(data=exception_message)
data['total_capacity_gb'] = (float(attributes['capacity']) /
units.Gi)
data['free_capacity_gb'] = (float(attributes['free_capacity']) /
units.Gi)
data['easytier_support'] = attributes['easy_tier'] in ['on', 'auto']
data['compression_support'] = self._state['compression_enabled']
data['location_info'] = ('StorwizeSVCDriver:%(sys_id)s:%(pool)s' %
{'sys_id': self._state['system_id'],
'pool': pool})
if self._replication_enabled:
data['replication_enabled'] = self._replication_enabled
data['replication_type'] = self._supported_replication_types
data['replication_count'] = len(self._replication_targets)
elif self.replication:
data.update(self.replication.get_replication_info())
data['volume_backend_name'] = (backend_name or
self._state['system_name'])
data['pools'] = [self._build_pool_stats(pool)
for pool in
self.configuration.storwize_svc_volpool_name]
self._stats = data
def _build_pool_stats(self, pool):
"""Build pool status"""
QoS_support = True
pool_stats = {}
try:
pool_data = self._helpers.get_pool_attrs(pool)
if pool_data:
easy_tier = pool_data['easy_tier'] in ['on', 'auto']
total_capacity_gb = float(pool_data['capacity']) / units.Gi
free_capacity_gb = float(pool_data['free_capacity']) / units.Gi
allocated_capacity_gb = (float(pool_data['used_capacity']) /
units.Gi)
location_info = ('StorwizeSVCDriver:%(sys_id)s:%(pool)s' %
{'sys_id': self._state['system_id'],
'pool': pool_data['name']})
pool_stats = {
'pool_name': pool_data['name'],
'total_capacity_gb': total_capacity_gb,
'free_capacity_gb': free_capacity_gb,
'allocated_capacity_gb': allocated_capacity_gb,
'easytier_support': easy_tier,
'compression_support': self._state['compression_enabled'],
'reserved_percentage':
self.configuration.reserved_percentage,
'QoS_support': QoS_support,
'consistencygroup_support': True,
'location_info': location_info,
'easytier_support': easy_tier
}
if self._replication_enabled:
pool_stats.update({
'replication_enabled': self._replication_enabled,
'replication_type': self._supported_replication_types,
'replication_count': len(self._replication_targets)
})
elif self.replication:
pool_stats.update(self.replication.get_replication_info())
except exception.VolumeBackendAPIException:
msg = _('Failed getting details for pool %s.') % pool
raise exception.VolumeBackendAPIException(data=msg)
return pool_stats
def _manage_input_check(self, ref):
"""Verify the input of manage function."""
# Check that the reference is valid

View File

@ -79,9 +79,10 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
1.3.3 - Update driver to use ABC metaclasses
2.0 - Code refactor, split init file and placed shared methods for
FC and iSCSI within the StorwizeSVCCommonDriver class
2.0.1 - Added support for multiple pools with model update
"""
VERSION = "2.0"
VERSION = "2.0.1"
def __init__(self, *args, **kwargs):
super(StorwizeSVCFCDriver, self).__init__(*args, **kwargs)

View File

@ -79,9 +79,10 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
1.3.3 - Update driver to use ABC metaclasses
2.0 - Code refactor, split init file and placed shared methods for
FC and iSCSI within the StorwizeSVCCommonDriver class
2.0.1 - Added support for multiple pools with model update
"""
VERSION = "2.0"
VERSION = "2.0.1"
def __init__(self, *args, **kwargs):
super(StorwizeSVCISCSIDriver, self).__init__(*args, **kwargs)

View File

@ -0,0 +1,3 @@
---
features:
- Add multiple pools support to Storwize SVC driver.