[SVF]:Retype in-use hyperswap volume
[Spectrum Virtualize Family] During HyperSwap volume retype, adding site and io group information to host if not already added to host. Closes-Bug: #1920890 Change-Id: I2f52cc8e42c487c04ddb54cd2d7afe4b35d20eea
This commit is contained in:
parent
a22c913c79
commit
91c7f040ad
|
@ -4574,6 +4574,8 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||||
configuration=config)
|
configuration=config)
|
||||||
self._driver = storwize_svc_iscsi.StorwizeSVCISCSIDriver(
|
self._driver = storwize_svc_iscsi.StorwizeSVCISCSIDriver(
|
||||||
configuration=config)
|
configuration=config)
|
||||||
|
self.fcdriver = StorwizeSVCFcFakeDriver(
|
||||||
|
configuration=config)
|
||||||
wwpns = [
|
wwpns = [
|
||||||
six.text_type(random.randint(0, 9999999999999999)).zfill(16),
|
six.text_type(random.randint(0, 9999999999999999)).zfill(16),
|
||||||
six.text_type(random.randint(0, 9999999999999999)).zfill(16)]
|
six.text_type(random.randint(0, 9999999999999999)).zfill(16)]
|
||||||
|
@ -4586,6 +4588,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||||
self.sim = StorwizeSVCManagementSimulator(SVC_POOLS)
|
self.sim = StorwizeSVCManagementSimulator(SVC_POOLS)
|
||||||
|
|
||||||
self.driver.set_fake_storage(self.sim)
|
self.driver.set_fake_storage(self.sim)
|
||||||
|
self.fcdriver.set_fake_storage(self.sim)
|
||||||
self.ctxt = context.get_admin_context()
|
self.ctxt = context.get_admin_context()
|
||||||
else:
|
else:
|
||||||
self._reset_flags()
|
self._reset_flags()
|
||||||
|
@ -7695,6 +7698,28 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||||
snapshot_id=snapshot.id)
|
snapshot_id=snapshot.id)
|
||||||
self.driver.create_volume_from_snapshot(vol6, snapshot)
|
self.driver.create_volume_from_snapshot(vol6, snapshot)
|
||||||
|
|
||||||
|
@ddt.data({'pool': 'openstack2', 'peer_pool': 'openstack3'},
|
||||||
|
{'pool': 'openstack', 'peer_pool': None},
|
||||||
|
{'pool': None, 'peer_pool': 'openstack1'})
|
||||||
|
@mock.patch.object(storwize_svc_common.StorwizeSSH, 'lsmdiskgrp')
|
||||||
|
def test_storwize_svc_get_hyperswap_pool_io_grp(self, pools, lsmdiskgrp):
|
||||||
|
lsmdiskgrp.side_effect = [{'site_id': '1'},
|
||||||
|
{'site_id': '2'}]
|
||||||
|
|
||||||
|
if pools['pool'] and pools['peer_pool']:
|
||||||
|
iogrp_list = self.driver._helpers.get_hyperswap_pool_io_grp(
|
||||||
|
self.driver._state, pools['pool'], pools['peer_pool'])
|
||||||
|
lsmdiskgrp.assert_called()
|
||||||
|
self.assertEqual(2, lsmdiskgrp.call_count)
|
||||||
|
self.assertEqual(['0', '1'], iogrp_list)
|
||||||
|
else:
|
||||||
|
self.assertRaises(exception.InvalidInput,
|
||||||
|
self.driver._helpers.get_hyperswap_pool_io_grp,
|
||||||
|
self.driver._state, pools['pool'],
|
||||||
|
pools['peer_pool'])
|
||||||
|
lsmdiskgrp.assert_not_called()
|
||||||
|
self.assertEqual(0, lsmdiskgrp.call_count)
|
||||||
|
|
||||||
@ mock.patch.object(storwize_svc_common.StorwizeSSH, 'lsmdiskgrp')
|
@ mock.patch.object(storwize_svc_common.StorwizeSSH, 'lsmdiskgrp')
|
||||||
def test_storwize_svc_select_iogrp_with_pool_site(self, lsmdiskgrp):
|
def test_storwize_svc_select_iogrp_with_pool_site(self, lsmdiskgrp):
|
||||||
opts = {}
|
opts = {}
|
||||||
|
@ -8286,6 +8311,91 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||||
volume3['volume_type'] = non_hyper_type
|
volume3['volume_type'] = non_hyper_type
|
||||||
self.driver.delete_volume(volume3)
|
self.driver.delete_volume(volume3)
|
||||||
|
|
||||||
|
@mock.patch.object(storwize_svc_common.StorwizeSVCCommonDriver,
|
||||||
|
'_update_replication_properties')
|
||||||
|
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||||
|
'get_hyperswap_pool_io_grp')
|
||||||
|
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||||
|
'get_system_info')
|
||||||
|
def test_retype_hyperswap_inuse_volume_fc(self,
|
||||||
|
get_system_info,
|
||||||
|
get_hyperswap_pool_io_grp,
|
||||||
|
update_rep_prop):
|
||||||
|
get_system_info.return_value = {'code_level': (7, 7, 0, 0),
|
||||||
|
'topology': 'hyperswap',
|
||||||
|
'system_name': 'storwize-svc-sim',
|
||||||
|
'system_id': '0123456789ABCDEF'}
|
||||||
|
|
||||||
|
self.fcdriver.do_setup(None)
|
||||||
|
|
||||||
|
spec1 = {'drivers:iogrp': '0,1'}
|
||||||
|
non_hyper_type = self._create_volume_type(spec1, 'non_hyper_type')
|
||||||
|
|
||||||
|
volume = testutils.create_volume(self.ctxt,
|
||||||
|
volume_type_id=non_hyper_type.id,
|
||||||
|
host='openstack@svc#hyperswap1')
|
||||||
|
self.fcdriver.create_volume(volume)
|
||||||
|
volume.previous_status = 'in-use'
|
||||||
|
host = {'host': 'openstack@svc#hyperswap1'}
|
||||||
|
|
||||||
|
spec = {'drivers:volume_topology': 'hyperswap',
|
||||||
|
'peer_pool': 'hyperswap2'}
|
||||||
|
|
||||||
|
hyper_type = self._create_volume_type(spec, 'hypertype')
|
||||||
|
diff, _equal = volume_types.volume_types_diff(self.ctxt,
|
||||||
|
non_hyper_type['id'],
|
||||||
|
hyper_type['id'])
|
||||||
|
|
||||||
|
self.fcdriver.retype(self.ctxt, volume, hyper_type, diff, host)
|
||||||
|
|
||||||
|
self._assert_vol_exists(volume.name, True)
|
||||||
|
self._assert_vol_exists('site2' + volume.name, True)
|
||||||
|
self._assert_vol_exists('fcsite1' + volume.name, True)
|
||||||
|
self._assert_vol_exists('fcsite2' + volume.name, True)
|
||||||
|
|
||||||
|
get_hyperswap_pool_io_grp.assert_called()
|
||||||
|
|
||||||
|
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||||
|
'get_hyperswap_pool_io_grp')
|
||||||
|
@mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||||
|
'get_system_info')
|
||||||
|
def test_retype_hyperswap_inuse_volume_iscsi(self,
|
||||||
|
get_system_info,
|
||||||
|
get_hyperswap_pool_io_grp):
|
||||||
|
get_system_info.return_value = {'code_level': (7, 7, 0, 0),
|
||||||
|
'topology': 'hyperswap',
|
||||||
|
'system_name': 'storwize-svc-sim',
|
||||||
|
'system_id': '0123456789ABCDEF'}
|
||||||
|
|
||||||
|
self.driver.do_setup(None)
|
||||||
|
|
||||||
|
spec1 = {'drivers:iogrp': '0,1'}
|
||||||
|
non_hyper_type = self._create_volume_type(spec1, 'non_hyper_type')
|
||||||
|
|
||||||
|
volume = testutils.create_volume(self.ctxt,
|
||||||
|
volume_type_id=non_hyper_type.id,
|
||||||
|
host='openstack@svc#hyperswap1')
|
||||||
|
self.driver.create_volume(volume)
|
||||||
|
volume.previous_status = 'in-use'
|
||||||
|
host = {'host': 'openstack@svc#hyperswap1'}
|
||||||
|
|
||||||
|
spec = {'drivers:volume_topology': 'hyperswap',
|
||||||
|
'peer_pool': 'hyperswap2'}
|
||||||
|
|
||||||
|
hyper_type = self._create_volume_type(spec, 'hypertype')
|
||||||
|
diff, _equal = volume_types.volume_types_diff(self.ctxt,
|
||||||
|
non_hyper_type['id'],
|
||||||
|
hyper_type['id'])
|
||||||
|
|
||||||
|
self.driver.retype(self.ctxt, volume, hyper_type, diff, host)
|
||||||
|
|
||||||
|
self._assert_vol_exists(volume.name, True)
|
||||||
|
self._assert_vol_exists('site2' + volume.name, True)
|
||||||
|
self._assert_vol_exists('fcsite1' + volume.name, True)
|
||||||
|
self._assert_vol_exists('fcsite2' + volume.name, True)
|
||||||
|
|
||||||
|
get_hyperswap_pool_io_grp.assert_not_called()
|
||||||
|
|
||||||
def test_retype_hyperswap_volume_failure_case(self):
|
def test_retype_hyperswap_volume_failure_case(self):
|
||||||
with mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
with mock.patch.object(storwize_svc_common.StorwizeHelpers,
|
||||||
'get_system_info') as get_system_info:
|
'get_system_info') as get_system_info:
|
||||||
|
@ -8345,10 +8455,7 @@ class StorwizeSVCCommonDriverTestCase(test.TestCase):
|
||||||
diff, _equal = volume_types.volume_types_diff(
|
diff, _equal = volume_types.volume_types_diff(
|
||||||
self.ctxt, hyperswap_vol_type['id'],
|
self.ctxt, hyperswap_vol_type['id'],
|
||||||
inuse_type['id'])
|
inuse_type['id'])
|
||||||
self.assertRaises(exception.InvalidInput,
|
self.driver.retype(self.ctxt, volume, inuse_type, diff, host)
|
||||||
self.driver.retype,
|
|
||||||
self.ctxt, volume, inuse_type, diff,
|
|
||||||
host)
|
|
||||||
|
|
||||||
# retype from hyperswap volume to replication volume
|
# retype from hyperswap volume to replication volume
|
||||||
spec3 = {'replication_enabled': '<is> True',
|
spec3 = {'replication_enabled': '<is> True',
|
||||||
|
|
|
@ -271,6 +271,14 @@ class StorwizeSSH(object):
|
||||||
ssh_cmd = ['svctask', 'addhostport', '-force'] + port + ['"%s"' % host]
|
ssh_cmd = ['svctask', 'addhostport', '-force'] + port + ['"%s"' % host]
|
||||||
self.run_ssh_assert_no_output(ssh_cmd)
|
self.run_ssh_assert_no_output(ssh_cmd)
|
||||||
|
|
||||||
|
def addhostiogrp(self, host, iogrplist='all'):
|
||||||
|
ssh_cmd = ['svctask', 'addhostiogrp']
|
||||||
|
if iogrplist == 'all':
|
||||||
|
ssh_cmd += ['-iogrpall', '"%s"' % host]
|
||||||
|
else:
|
||||||
|
ssh_cmd += ['-iogrp', ':'.join(iogrplist), '"%s"' % host]
|
||||||
|
self.run_ssh_assert_no_output(ssh_cmd)
|
||||||
|
|
||||||
def lshost(self, host=None):
|
def lshost(self, host=None):
|
||||||
with_header = True
|
with_header = True
|
||||||
ssh_cmd = ['svcinfo', 'lshost', '-delim', '!']
|
ssh_cmd = ['svcinfo', 'lshost', '-delim', '!']
|
||||||
|
@ -285,7 +293,11 @@ class StorwizeSSH(object):
|
||||||
self.run_ssh_assert_no_output(ssh_cmd, log_cmd)
|
self.run_ssh_assert_no_output(ssh_cmd, log_cmd)
|
||||||
|
|
||||||
def chhost(self, host, site):
|
def chhost(self, host, site):
|
||||||
ssh_cmd = ['svctask', 'chhost', '-site', '"%s"' % site, '"%s"' % host]
|
ssh_cmd = ['svctask', 'chhost']
|
||||||
|
if site:
|
||||||
|
ssh_cmd += ['-site', '"%s"' % site, '"%s"' % host]
|
||||||
|
else:
|
||||||
|
ssh_cmd += ['-nosite', '"%s"' % host]
|
||||||
self.run_ssh_assert_no_output(ssh_cmd)
|
self.run_ssh_assert_no_output(ssh_cmd)
|
||||||
|
|
||||||
def lsiscsiauth(self):
|
def lsiscsiauth(self):
|
||||||
|
@ -701,6 +713,10 @@ class StorwizeSSH(object):
|
||||||
ssh_cmd = ['svctask', 'rmvdiskaccess', '-iogrp', iogrp, '"%s"' % vdisk]
|
ssh_cmd = ['svctask', 'rmvdiskaccess', '-iogrp', iogrp, '"%s"' % vdisk]
|
||||||
self.run_ssh_assert_no_output(ssh_cmd)
|
self.run_ssh_assert_no_output(ssh_cmd)
|
||||||
|
|
||||||
|
def lsvdiskaccess(self, vdisk):
|
||||||
|
ssh_cmd = ['svcinfo', 'lsvdiskaccess', '-delim', '!', '"%s"' % vdisk]
|
||||||
|
return self.run_ssh_info(ssh_cmd, with_header=True)
|
||||||
|
|
||||||
def lsportfc(self, node_id):
|
def lsportfc(self, node_id):
|
||||||
ssh_cmd = ['svcinfo', 'lsportfc', '-delim', '!',
|
ssh_cmd = ['svcinfo', 'lsportfc', '-delim', '!',
|
||||||
'-filtervalue', 'node_id=%s' % node_id]
|
'-filtervalue', 'node_id=%s' % node_id]
|
||||||
|
@ -891,6 +907,43 @@ class StorwizeHelpers(object):
|
||||||
raise exception.VolumeBackendAPIException(data=msg)
|
raise exception.VolumeBackendAPIException(data=msg)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def get_hyperswap_pool_io_grp(self, state, pool, peer_pool):
|
||||||
|
if not peer_pool or not pool:
|
||||||
|
raise exception.InvalidInput(
|
||||||
|
reason=_('The pool and peer pool is necessary for hyperswap '
|
||||||
|
'volume, please configure the pool and peer pool.'))
|
||||||
|
pool_data = None
|
||||||
|
peer_pool_data = None
|
||||||
|
for stat_pool in self.stats.get('pools', []):
|
||||||
|
if stat_pool['pool_name'] == pool:
|
||||||
|
pool_data = stat_pool
|
||||||
|
elif stat_pool['pool_name'] == peer_pool:
|
||||||
|
peer_pool_data = stat_pool
|
||||||
|
|
||||||
|
if pool_data is None or pool_data.get("site_id") is None:
|
||||||
|
pool_data = self.get_pool_attrs(pool)
|
||||||
|
if not pool_data['site_id']:
|
||||||
|
raise exception.InvalidInput(
|
||||||
|
reason=_('The pool with site is necessary for hyperswap '
|
||||||
|
'volume, please configure the pool with site.'))
|
||||||
|
|
||||||
|
if peer_pool_data is None or peer_pool_data.get("site_id") is None:
|
||||||
|
peer_pool_data = self.get_pool_attrs(peer_pool)
|
||||||
|
if not peer_pool_data['site_id']:
|
||||||
|
raise exception.InvalidInput(
|
||||||
|
reason=_('The peer pool with site is necessary for '
|
||||||
|
'hyperswap volume, please configure the peer '
|
||||||
|
'pool with site.'))
|
||||||
|
|
||||||
|
iogrp_list = []
|
||||||
|
for node in state['storage_nodes'].values():
|
||||||
|
if ((pool_data['site_id'] == node['site_id']) or
|
||||||
|
(peer_pool_data['site_id'] == node['site_id'])):
|
||||||
|
if node['IO_group'] not in iogrp_list:
|
||||||
|
iogrp_list.append(node['IO_group'])
|
||||||
|
|
||||||
|
return iogrp_list
|
||||||
|
|
||||||
def select_io_group(self, state, opts, pool):
|
def select_io_group(self, state, opts, pool):
|
||||||
selected_iog = 0
|
selected_iog = 0
|
||||||
iog_list = StorwizeHelpers._get_valid_requested_io_groups(state, opts)
|
iog_list = StorwizeHelpers._get_valid_requested_io_groups(state, opts)
|
||||||
|
@ -2114,7 +2167,7 @@ class StorwizeHelpers(object):
|
||||||
attrs = self._get_flashcopy_mapping_attributes(map_id)
|
attrs = self._get_flashcopy_mapping_attributes(map_id)
|
||||||
copy_rate = attrs['copy_rate']
|
copy_rate = attrs['copy_rate']
|
||||||
# update flashcopy rate for clone volume
|
# update flashcopy rate for clone volume
|
||||||
if copy_rate != '0':
|
if copy_rate != '0' and attrs['rc_controlled'] != 'yes':
|
||||||
self.ssh.chfcmap(map_id,
|
self.ssh.chfcmap(map_id,
|
||||||
copyrate=six.text_type(new_flashcopy_rate))
|
copyrate=six.text_type(new_flashcopy_rate))
|
||||||
|
|
||||||
|
@ -5073,11 +5126,6 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||||
'support pool change.') % volume.name)
|
'support pool change.') % volume.name)
|
||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise exception.InvalidInput(message=msg)
|
raise exception.InvalidInput(message=msg)
|
||||||
if volume.previous_status == 'in-use':
|
|
||||||
msg = _('Retype an in-use volume to a hyperswap '
|
|
||||||
'volume is not allowed.')
|
|
||||||
LOG.error(msg)
|
|
||||||
raise exception.InvalidInput(message=msg)
|
|
||||||
if not new_opts['easytier']:
|
if not new_opts['easytier']:
|
||||||
raise exception.InvalidInput(
|
raise exception.InvalidInput(
|
||||||
reason=_('The default easytier of hyperswap volume is '
|
reason=_('The default easytier of hyperswap volume is '
|
||||||
|
@ -5106,8 +5154,8 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise exception.InvalidInput(message=msg)
|
raise exception.InvalidInput(message=msg)
|
||||||
|
|
||||||
def _retype_hyperswap_volume(self, volume, host, old_opts, new_opts,
|
def _retype_hyperswap_volume(self, ctxt, volume, host, old_opts,
|
||||||
old_pool, new_pool, vdisk_changes,
|
new_opts, old_pool, new_pool, vdisk_changes,
|
||||||
need_copy, new_type):
|
need_copy, new_type):
|
||||||
if (old_opts['volume_topology'] != 'hyperswap' and
|
if (old_opts['volume_topology'] != 'hyperswap' and
|
||||||
new_opts['volume_topology'] == 'hyperswap'):
|
new_opts['volume_topology'] == 'hyperswap'):
|
||||||
|
@ -5216,9 +5264,10 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
||||||
change_mirror, new_rep_type,
|
change_mirror, new_rep_type,
|
||||||
old_rep_type, old_pool,
|
old_rep_type, old_pool,
|
||||||
new_pool, old_io_grp)
|
new_pool, old_io_grp)
|
||||||
self._retype_hyperswap_volume(volume, host, old_opts, new_opts,
|
self._retype_hyperswap_volume(ctxt, volume, host, old_opts,
|
||||||
old_pool, new_pool, vdisk_changes,
|
new_opts, old_pool, new_pool,
|
||||||
need_copy, new_type)
|
vdisk_changes, need_copy,
|
||||||
|
new_type)
|
||||||
# Updating Hyperswap volume replication properties
|
# Updating Hyperswap volume replication properties
|
||||||
model_update = self._update_replication_properties(ctxt, volume,
|
model_update = self._update_replication_properties(ctxt, volume,
|
||||||
model_update)
|
model_update)
|
||||||
|
|
|
@ -171,9 +171,11 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
||||||
volume_name, backend_helper, node_state = self._get_vol_sys_info(
|
volume_name, backend_helper, node_state = self._get_vol_sys_info(
|
||||||
volume)
|
volume)
|
||||||
|
|
||||||
host_site = self._get_volume_host_site_from_conf(volume,
|
host_site = None
|
||||||
connector)
|
|
||||||
is_hyper_volume = self.is_volume_hyperswap(volume)
|
is_hyper_volume = self.is_volume_hyperswap(volume)
|
||||||
|
if is_hyper_volume:
|
||||||
|
host_site = self._get_volume_host_site_from_conf(volume,
|
||||||
|
connector)
|
||||||
# The host_site is necessary for hyperswap volume.
|
# The host_site is necessary for hyperswap volume.
|
||||||
if is_hyper_volume and host_site is None:
|
if is_hyper_volume and host_site is None:
|
||||||
msg = (_('There is no correct storwize_preferred_host_site '
|
msg = (_('There is no correct storwize_preferred_host_site '
|
||||||
|
@ -365,3 +367,122 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
||||||
'conn': connector,
|
'conn': connector,
|
||||||
'info': info})
|
'info': info})
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
def _get_volume_connection_info(self, ctxt, volume, host_info,
|
||||||
|
iogrp_list):
|
||||||
|
connector = {'wwpns': []}
|
||||||
|
connection_info = {"driver_volume_type": "fibre_channel"}
|
||||||
|
data = {}
|
||||||
|
|
||||||
|
for wwpn in host_info.select('WWPN'):
|
||||||
|
connector['wwpns'].append(wwpn)
|
||||||
|
|
||||||
|
vol_name, backend_helper, node_state = self._get_vol_sys_info(volume)
|
||||||
|
|
||||||
|
data['target_discovered'] = False
|
||||||
|
data['volume_id'] = volume.id
|
||||||
|
|
||||||
|
conn_wwpns = []
|
||||||
|
for node in node_state['storage_nodes'].values():
|
||||||
|
if node['IO_group'] not in iogrp_list:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# The Storwize/svc release 7.7.0.0 introduced NPIV feature,
|
||||||
|
# Different commands be used to get the wwpns for host I/O
|
||||||
|
if node_state['code_level'] < (7, 7, 0, 0):
|
||||||
|
conn_wwpns.extend(node['WWPN'])
|
||||||
|
else:
|
||||||
|
npivwwpns = backend_helper.get_npiv_wwpns(node_id=node['id'],
|
||||||
|
host_io="yes")
|
||||||
|
conn_wwpns.extend(npivwwpns)
|
||||||
|
|
||||||
|
i_t_map = self._make_initiator_target_map(connector['wwpns'],
|
||||||
|
conn_wwpns)
|
||||||
|
data["initiator_target_map"] = i_t_map
|
||||||
|
data["target_wwn"] = conn_wwpns
|
||||||
|
|
||||||
|
connection_info['data'] = data
|
||||||
|
connection_info['connector'] = connector
|
||||||
|
|
||||||
|
return connection_info
|
||||||
|
|
||||||
|
def _retype_hyperswap_volume(self, ctxt, volume, host, old_opts,
|
||||||
|
new_opts, old_pool, new_pool, vdisk_changes,
|
||||||
|
need_copy, new_type):
|
||||||
|
if (old_opts['volume_topology'] != 'hyperswap' and
|
||||||
|
new_opts['volume_topology'] == 'hyperswap'):
|
||||||
|
LOG.debug('retype: Convert a normal volume %s to hyperswap '
|
||||||
|
'volume.', volume.name)
|
||||||
|
conn_info = {}
|
||||||
|
if volume.previous_status == 'in-use':
|
||||||
|
vdisk_info = self._helpers.ssh.lsvdiskhostmap(volume.name)
|
||||||
|
peer_pool = new_opts['peer_pool']
|
||||||
|
iogrp_list = self._helpers.get_hyperswap_pool_io_grp(
|
||||||
|
self._state, new_pool, peer_pool)
|
||||||
|
for mapping_info in vdisk_info:
|
||||||
|
host = mapping_info['host_name']
|
||||||
|
try:
|
||||||
|
host_info = self._helpers.ssh.lshost(host)
|
||||||
|
conn_info[host] = self._get_volume_connection_info(
|
||||||
|
ctxt, volume, host_info, iogrp_list)
|
||||||
|
host_site = self._get_volume_host_site_from_conf(
|
||||||
|
volume, conn_info[host].get('connector'))
|
||||||
|
self._update_host_site_for_hyperswap_volume(
|
||||||
|
host, host_site)
|
||||||
|
self._helpers.ssh.addhostiogrp(host,
|
||||||
|
iogrp_list)
|
||||||
|
except Exception as ex:
|
||||||
|
msg = _('Error updating host %(host)s due to %(ex)s',
|
||||||
|
{'host': host, 'ex': ex})
|
||||||
|
raise exception.VolumeBackendAPIException(data=msg)
|
||||||
|
self._helpers.convert_volume_to_hyperswap(volume.name,
|
||||||
|
new_opts,
|
||||||
|
self._state)
|
||||||
|
if volume.previous_status == 'in-use':
|
||||||
|
for host, info in conn_info.items():
|
||||||
|
try:
|
||||||
|
fczm_utils.add_fc_zone(info)
|
||||||
|
except Exception as ex:
|
||||||
|
self._helpers.convert_hyperswap_volume_to_normal(
|
||||||
|
volume.name, new_opts['peer_pool'])
|
||||||
|
msg = _('Zoning failed for volume %(vol)s and host '
|
||||||
|
'%(host)s due to %(ex)s.',
|
||||||
|
{'vol': volume.name, 'host': host, 'ex': ex})
|
||||||
|
raise exception.VolumeBackendAPIException(data=msg)
|
||||||
|
elif (old_opts['volume_topology'] == 'hyperswap' and
|
||||||
|
new_opts['volume_topology'] != 'hyperswap'):
|
||||||
|
LOG.debug('retype: Convert a hyperswap volume %s to normal '
|
||||||
|
'volume.', volume.name)
|
||||||
|
if new_pool == old_pool:
|
||||||
|
self._helpers.convert_hyperswap_volume_to_normal(
|
||||||
|
volume.name,
|
||||||
|
old_opts['peer_pool'])
|
||||||
|
elif new_pool == old_opts['peer_pool']:
|
||||||
|
self._helpers.convert_hyperswap_volume_to_normal(
|
||||||
|
volume.name,
|
||||||
|
old_pool)
|
||||||
|
if volume.previous_status == 'in-use':
|
||||||
|
vdisk_info = self._helpers.ssh.lsvdiskhostmap(volume.name)
|
||||||
|
for mapping_info in vdisk_info:
|
||||||
|
res = self._helpers.check_host_mapped_vols(
|
||||||
|
mapping_info['host_name'])
|
||||||
|
if len(res) == 1:
|
||||||
|
self._helpers.update_host(mapping_info['host_name'],
|
||||||
|
None)
|
||||||
|
else:
|
||||||
|
rel_info = self._helpers.get_relationship_info(volume.name)
|
||||||
|
aux_vdisk = rel_info['aux_vdisk_name']
|
||||||
|
if need_copy:
|
||||||
|
self.add_vdisk_copy(aux_vdisk, old_opts['peer_pool'], new_type,
|
||||||
|
auto_delete=True)
|
||||||
|
elif vdisk_changes:
|
||||||
|
self._helpers.change_vdisk_options(aux_vdisk,
|
||||||
|
vdisk_changes,
|
||||||
|
new_opts, self._state)
|
||||||
|
if need_copy:
|
||||||
|
self.add_vdisk_copy(volume.name, old_pool, new_type,
|
||||||
|
auto_delete=True)
|
||||||
|
elif vdisk_changes:
|
||||||
|
self._helpers.change_vdisk_options(volume.name,
|
||||||
|
vdisk_changes,
|
||||||
|
new_opts, self._state)
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
IBM Spectrum Virtualize Family driver `Bug #1920890
|
||||||
|
<https://bugs.launchpad.net/cinder/+bug/1920890>`_: Fixed issue in
|
||||||
|
retype_hyperswap_volume method to update site and iogrp information to
|
||||||
|
the host during a retype from a non-HyperSwap volume to a HyperSwap volume.
|
Loading…
Reference in New Issue