Storwize: add backup snapshots support
This patch adds backup snapshots support for Storwize/SVC driver. The change implements attach and detach snapshot: initialize_connection_snapshot terminate_connection_snapshot Implements: blueprint storwize-backup-snapshots Change-Id: I65393a6a5f995d609152d4b8546c055d7bf0b253
This commit is contained in:
parent
6af48d7bd9
commit
f68847353e
@ -2758,6 +2758,12 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
|
|||||||
vol = testutils.create_volume(self.ctxt, **prop)
|
vol = testutils.create_volume(self.ctxt, **prop)
|
||||||
return vol
|
return vol
|
||||||
|
|
||||||
|
def _generate_snap_info(self, vol_id, size=10):
|
||||||
|
prop = {'volume_id': vol_id,
|
||||||
|
'volume_size': size}
|
||||||
|
snap = testutils.create_snapshot(self.ctxt, **prop)
|
||||||
|
return snap
|
||||||
|
|
||||||
def _assert_vol_exists(self, name, exists):
|
def _assert_vol_exists(self, name, exists):
|
||||||
is_vol_defined = self.iscsi_driver._helpers.is_vdisk_defined(name)
|
is_vol_defined = self.iscsi_driver._helpers.is_vdisk_defined(name)
|
||||||
self.assertEqual(exists, is_vol_defined)
|
self.assertEqual(exists, is_vol_defined)
|
||||||
@ -2797,6 +2803,43 @@ class StorwizeSVCISCSIDriverTestCase(test.TestCase):
|
|||||||
self.iscsi_driver.initialize_connection(volume_iSCSI, connector)
|
self.iscsi_driver.initialize_connection(volume_iSCSI, connector)
|
||||||
self.iscsi_driver.terminate_connection(volume_iSCSI, connector)
|
self.iscsi_driver.terminate_connection(volume_iSCSI, connector)
|
||||||
|
|
||||||
|
def test_storwize_iscsi_connection_snapshot(self):
|
||||||
|
# create a iSCSI volume
|
||||||
|
volume_iSCSI = self._create_volume()
|
||||||
|
snapshot = self._generate_snap_info(volume_iSCSI.id)
|
||||||
|
self.iscsi_driver.create_snapshot(snapshot)
|
||||||
|
connector = {'host': 'storwize-svc-host',
|
||||||
|
'wwnns': ['20000090fa17311e', '20000090fa17311f'],
|
||||||
|
'wwpns': ['ff00000000000000', 'ff00000000000001'],
|
||||||
|
'initiator': 'iqn.1993-08.org.debian:01:eac5ccc1aaa'}
|
||||||
|
|
||||||
|
self.iscsi_driver.initialize_connection_snapshot(snapshot, connector)
|
||||||
|
self.iscsi_driver.terminate_connection_snapshot(snapshot, connector)
|
||||||
|
|
||||||
|
def test_storwize_replication_failover_iscsi_connection_snapshot(self):
|
||||||
|
volume_iSCSI = self._create_volume()
|
||||||
|
snapshot = self._generate_snap_info(volume_iSCSI.id)
|
||||||
|
self.iscsi_driver.create_snapshot(snapshot)
|
||||||
|
connector = {'host': 'storwize-svc-host',
|
||||||
|
'wwnns': ['20000090fa17311e', '20000090fa17311f'],
|
||||||
|
'wwpns': ['ff00000000000000', 'ff00000000000001'],
|
||||||
|
'initiator': 'iqn.1993-08.org.debian:01:eac5ccc1aaa'}
|
||||||
|
# a snapshot of a replication failover volume. attach will be failed
|
||||||
|
with mock.patch.object(storwize_svc_common.StorwizeSVCCommonDriver,
|
||||||
|
'_get_volume_replicated_type') as rep_type:
|
||||||
|
rep_type.return_value = True
|
||||||
|
with mock.patch.object(storwize_svc_common.StorwizeSVCCommonDriver,
|
||||||
|
'_get_vol_sys_info') as sys_info:
|
||||||
|
sys_info.return_value = {'volume_name': 'voliscsi',
|
||||||
|
'backend_helper':
|
||||||
|
'self._aux_backend_helpers',
|
||||||
|
'node_state': 'self._state'}
|
||||||
|
self.assertRaises(exception.VolumeDriverException,
|
||||||
|
self.iscsi_driver.
|
||||||
|
initialize_connection_snapshot,
|
||||||
|
snapshot,
|
||||||
|
connector)
|
||||||
|
|
||||||
@mock.patch.object(storwize_svc_iscsi.StorwizeSVCISCSIDriver,
|
@mock.patch.object(storwize_svc_iscsi.StorwizeSVCISCSIDriver,
|
||||||
'_do_terminate_connection')
|
'_do_terminate_connection')
|
||||||
@mock.patch.object(storwize_svc_iscsi.StorwizeSVCISCSIDriver,
|
@mock.patch.object(storwize_svc_iscsi.StorwizeSVCISCSIDriver,
|
||||||
@ -3298,6 +3341,12 @@ class StorwizeSVCFcDriverTestCase(test.TestCase):
|
|||||||
vol = testutils.create_volume(self.ctxt, **prop)
|
vol = testutils.create_volume(self.ctxt, **prop)
|
||||||
return vol
|
return vol
|
||||||
|
|
||||||
|
def _generate_snap_info(self, vol_id, size=10):
|
||||||
|
prop = {'volume_id': vol_id,
|
||||||
|
'volume_size': size}
|
||||||
|
snap = testutils.create_snapshot(self.ctxt, **prop)
|
||||||
|
return snap
|
||||||
|
|
||||||
def _assert_vol_exists(self, name, exists):
|
def _assert_vol_exists(self, name, exists):
|
||||||
is_vol_defined = self.fc_driver._helpers.is_vdisk_defined(name)
|
is_vol_defined = self.fc_driver._helpers.is_vdisk_defined(name)
|
||||||
self.assertEqual(exists, is_vol_defined)
|
self.assertEqual(exists, is_vol_defined)
|
||||||
@ -3315,6 +3364,44 @@ class StorwizeSVCFcDriverTestCase(test.TestCase):
|
|||||||
|
|
||||||
self.assertIsNotNone(host_name)
|
self.assertIsNotNone(host_name)
|
||||||
|
|
||||||
|
def test_storwize_fc_connection_snapshot(self):
|
||||||
|
# create a iSCSI volume
|
||||||
|
volume_fc = self._create_volume()
|
||||||
|
snapshot = self._generate_snap_info(volume_fc.id)
|
||||||
|
self.fc_driver.create_snapshot(snapshot)
|
||||||
|
connector = {'host': 'storwize-svc-host',
|
||||||
|
'wwnns': ['20000090fa17311e', '20000090fa17311f'],
|
||||||
|
'wwpns': ['ff00000000000000', 'ff00000000000001'],
|
||||||
|
'initiator': 'iqn.1993-08.org.debian:01:eac5ccc1aaa'}
|
||||||
|
|
||||||
|
self.fc_driver.initialize_connection_snapshot(snapshot, connector)
|
||||||
|
self.fc_driver.terminate_connection_snapshot(snapshot, connector)
|
||||||
|
|
||||||
|
def test_storwize_replication_failover_fc_connection_snapshot(self):
|
||||||
|
volume_fc = self._create_volume()
|
||||||
|
volume_fc['replication_status'] = fields.ReplicationStatus.FAILED_OVER
|
||||||
|
snapshot = self._generate_snap_info(volume_fc.id)
|
||||||
|
self.fc_driver.create_snapshot(snapshot)
|
||||||
|
connector = {'host': 'storwize-svc-host',
|
||||||
|
'wwnns': ['20000090fa17311e', '20000090fa17311f'],
|
||||||
|
'wwpns': ['ff00000000000000', 'ff00000000000001'],
|
||||||
|
'initiator': 'iqn.1993-08.org.debian:01:eac5ccc1aaa'}
|
||||||
|
# a snapshot of a replication failover volume. attach will be failed
|
||||||
|
with mock.patch.object(storwize_svc_common.StorwizeSVCCommonDriver,
|
||||||
|
'_get_volume_replicated_type') as rep_type:
|
||||||
|
rep_type.return_value = True
|
||||||
|
with mock.patch.object(storwize_svc_common.StorwizeSVCCommonDriver,
|
||||||
|
'_get_vol_sys_info') as sys_info:
|
||||||
|
sys_info.return_value = {'volume_name': 'volfc',
|
||||||
|
'backend_helper':
|
||||||
|
'self._aux_backend_helpers',
|
||||||
|
'node_state': 'self._state'}
|
||||||
|
self.assertRaises(exception.VolumeDriverException,
|
||||||
|
self.fc_driver.
|
||||||
|
initialize_connection_snapshot,
|
||||||
|
snapshot,
|
||||||
|
connector)
|
||||||
|
|
||||||
def test_storwize_get_host_with_fc_connection_with_volume(self):
|
def test_storwize_get_host_with_fc_connection_with_volume(self):
|
||||||
# create a FC volume
|
# create a FC volume
|
||||||
volume_fc = self._generate_vol_info(None, None)
|
volume_fc = self._generate_vol_info(None, None)
|
||||||
|
@ -2578,6 +2578,13 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
|||||||
def remove_export(self, ctxt, volume):
|
def remove_export(self, ctxt, volume):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def create_export_snapshot(self, ctxt, snapshot, connector):
|
||||||
|
model_update = None
|
||||||
|
return model_update
|
||||||
|
|
||||||
|
def remove_export_snapshot(self, ctxt, snapshot):
|
||||||
|
pass
|
||||||
|
|
||||||
def _get_vdisk_params(self, type_id, volume_type=None,
|
def _get_vdisk_params(self, type_id, volume_type=None,
|
||||||
volume_metadata=None):
|
volume_metadata=None):
|
||||||
return self._helpers.get_vdisk_params(self.configuration,
|
return self._helpers.get_vdisk_params(self.configuration,
|
||||||
@ -3860,6 +3867,21 @@ class StorwizeSVCCommonDriver(san.SanDriver,
|
|||||||
|
|
||||||
return tgt_vol, backend_helper, node_state
|
return tgt_vol, backend_helper, node_state
|
||||||
|
|
||||||
|
def _check_snapshot_replica_volume_status(self, snapshot):
|
||||||
|
ctxt = context.get_admin_context()
|
||||||
|
if self._get_volume_replicated_type(ctxt, None,
|
||||||
|
snapshot.volume_type_id):
|
||||||
|
LOG.debug('It is a replication volume snapshot for backup.')
|
||||||
|
rep_volume = objects.Volume.get_by_id(ctxt, snapshot.volume_id)
|
||||||
|
volume_name, backend_helper, node_state = self._get_vol_sys_info(
|
||||||
|
rep_volume)
|
||||||
|
if backend_helper != self._helpers or self._active_backend_id:
|
||||||
|
msg = (_('The snapshot of the replication volume %s has '
|
||||||
|
'failed over to the aux backend. It can not attach'
|
||||||
|
' to the aux backend.') % volume_name)
|
||||||
|
LOG.error(msg)
|
||||||
|
raise exception.VolumeDriverException(message=msg)
|
||||||
|
|
||||||
def migrate_volume(self, ctxt, volume, host):
|
def migrate_volume(self, ctxt, volume, host):
|
||||||
"""Migrate directly if source and dest are managed by same storage.
|
"""Migrate directly if source and dest are managed by same storage.
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ localized format.
|
|||||||
are of different sizes, is not supported.
|
are of different sizes, is not supported.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import collections
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
@ -93,6 +94,7 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
2.2.1 - Add vdisk mirror/stretch cluster support
|
2.2.1 - Add vdisk mirror/stretch cluster support
|
||||||
2.2.2 - Add npiv support
|
2.2.2 - Add npiv support
|
||||||
2.2.3 - Add replication group support
|
2.2.3 - Add replication group support
|
||||||
|
2.2.4 - Add backup snapshots support
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VERSION = "2.2.3"
|
VERSION = "2.2.3"
|
||||||
@ -114,6 +116,21 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
raise exception.InvalidConnectorException(
|
raise exception.InvalidConnectorException(
|
||||||
missing='wwpns')
|
missing='wwpns')
|
||||||
|
|
||||||
|
def initialize_connection_snapshot(self, snapshot, connector):
|
||||||
|
"""Perform attach snapshot for backup snapshots."""
|
||||||
|
# If the snapshot's source volume is a replication volume and the
|
||||||
|
# replication volume has failed over to aux_backend,
|
||||||
|
# attach the snapshot will be failed.
|
||||||
|
self._check_snapshot_replica_volume_status(snapshot)
|
||||||
|
|
||||||
|
vol_attrs = ['id', 'name', 'display_name']
|
||||||
|
Volume = collections.namedtuple('Volume', vol_attrs)
|
||||||
|
volume = Volume(id=snapshot.id,
|
||||||
|
name=snapshot.name,
|
||||||
|
display_name='backup-snapshot')
|
||||||
|
|
||||||
|
return self.initialize_connection(volume, connector)
|
||||||
|
|
||||||
@fczm_utils.add_fc_zone
|
@fczm_utils.add_fc_zone
|
||||||
def initialize_connection(self, volume, connector):
|
def initialize_connection(self, volume, connector):
|
||||||
"""Perform necessary work to make a FC connection."""
|
"""Perform necessary work to make a FC connection."""
|
||||||
@ -136,9 +153,16 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
LOG.debug('enter: initialize_connection: volume %(vol)s with connector'
|
LOG.debug('enter: initialize_connection: volume %(vol)s with connector'
|
||||||
' %(conn)s', {'vol': volume['id'], 'conn': connector})
|
' %(conn)s', {'vol': volume.id, 'conn': connector})
|
||||||
volume_name, backend_helper, node_state = self._get_vol_sys_info(
|
if volume.display_name == 'backup-snapshot':
|
||||||
volume)
|
LOG.debug('It is a virtual volume %(vol)s for attach snapshot.',
|
||||||
|
{'vol': volume.id})
|
||||||
|
volume_name = volume.name
|
||||||
|
backend_helper = self._helpers
|
||||||
|
node_state = self._state
|
||||||
|
else:
|
||||||
|
volume_name, backend_helper, node_state = self._get_vol_sys_info(
|
||||||
|
volume)
|
||||||
|
|
||||||
# Check if a host object is defined for this host name
|
# Check if a host object is defined for this host name
|
||||||
host_name = backend_helper.get_host_from_connector(connector)
|
host_name = backend_helper.get_host_from_connector(connector)
|
||||||
@ -192,7 +216,7 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
properties = {}
|
properties = {}
|
||||||
properties['target_discovered'] = False
|
properties['target_discovered'] = False
|
||||||
properties['target_lun'] = lun_id
|
properties['target_lun'] = lun_id
|
||||||
properties['volume_id'] = volume['id']
|
properties['volume_id'] = volume.id
|
||||||
|
|
||||||
conn_wwpns = backend_helper.get_conn_fc_wwpns(host_name)
|
conn_wwpns = backend_helper.get_conn_fc_wwpns(host_name)
|
||||||
|
|
||||||
@ -234,7 +258,7 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
|
|
||||||
LOG.debug('leave: initialize_connection:\n volume: %(vol)s\n '
|
LOG.debug('leave: initialize_connection:\n volume: %(vol)s\n '
|
||||||
'connector %(conn)s\n properties: %(prop)s',
|
'connector %(conn)s\n properties: %(prop)s',
|
||||||
{'vol': volume['id'], 'conn': connector,
|
{'vol': volume.id, 'conn': connector,
|
||||||
'prop': properties})
|
'prop': properties})
|
||||||
|
|
||||||
return {'driver_volume_type': 'fibre_channel', 'data': properties, }
|
return {'driver_volume_type': 'fibre_channel', 'data': properties, }
|
||||||
@ -249,6 +273,16 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
|
|
||||||
return i_t_map
|
return i_t_map
|
||||||
|
|
||||||
|
def terminate_connection_snapshot(self, snapshot, connector, **kwargs):
|
||||||
|
"""Perform detach snapshot for backup snapshots."""
|
||||||
|
vol_attrs = ['id', 'name', 'display_name']
|
||||||
|
Volume = collections.namedtuple('Volume', vol_attrs)
|
||||||
|
volume = Volume(id=snapshot.id,
|
||||||
|
name=snapshot.name,
|
||||||
|
display_name='backup-snapshot')
|
||||||
|
|
||||||
|
return self.terminate_connection(volume, connector, **kwargs)
|
||||||
|
|
||||||
@fczm_utils.remove_fc_zone
|
@fczm_utils.remove_fc_zone
|
||||||
def terminate_connection(self, volume, connector, **kwargs):
|
def terminate_connection(self, volume, connector, **kwargs):
|
||||||
"""Cleanup after an FC connection has been terminated."""
|
"""Cleanup after an FC connection has been terminated."""
|
||||||
@ -276,8 +310,16 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
automatically by this driver when mappings are created)
|
automatically by this driver when mappings are created)
|
||||||
"""
|
"""
|
||||||
LOG.debug('enter: terminate_connection: volume %(vol)s with connector'
|
LOG.debug('enter: terminate_connection: volume %(vol)s with connector'
|
||||||
' %(conn)s', {'vol': volume['id'], 'conn': connector})
|
' %(conn)s', {'vol': volume.id, 'conn': connector})
|
||||||
vol_name, backend_helper, node_state = self._get_vol_sys_info(volume)
|
if volume.display_name == 'backup-snapshot':
|
||||||
|
LOG.debug('It is a virtual volume %(vol)s for detach snapshot.',
|
||||||
|
{'vol': volume.id})
|
||||||
|
vol_name = volume.name
|
||||||
|
backend_helper = self._helpers
|
||||||
|
node_state = self._state
|
||||||
|
else:
|
||||||
|
vol_name, backend_helper, node_state = self._get_vol_sys_info(
|
||||||
|
volume)
|
||||||
|
|
||||||
info = {}
|
info = {}
|
||||||
if 'host' in connector:
|
if 'host' in connector:
|
||||||
@ -324,6 +366,6 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
backend_helper.delete_host(host_name)
|
backend_helper.delete_host(host_name)
|
||||||
|
|
||||||
LOG.debug('leave: terminate_connection: volume %(vol)s with '
|
LOG.debug('leave: terminate_connection: volume %(vol)s with '
|
||||||
'connector %(conn)s', {'vol': volume['id'],
|
'connector %(conn)s', {'vol': volume.id,
|
||||||
'conn': connector})
|
'conn': connector})
|
||||||
return info
|
return info
|
||||||
|
@ -33,6 +33,7 @@ localized format.
|
|||||||
are of different sizes, is not supported.
|
are of different sizes, is not supported.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
import collections
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
@ -92,6 +93,7 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
2.2 - Add CG capability to generic volume groups
|
2.2 - Add CG capability to generic volume groups
|
||||||
2.2.1 - Add vdisk mirror/stretch cluster support
|
2.2.1 - Add vdisk mirror/stretch cluster support
|
||||||
2.2.2 - Add replication group support
|
2.2.2 - Add replication group support
|
||||||
|
2.2.3 - Add backup snapshots support
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VERSION = "2.2.2"
|
VERSION = "2.2.2"
|
||||||
@ -113,6 +115,21 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
raise exception.InvalidConnectorException(
|
raise exception.InvalidConnectorException(
|
||||||
missing='initiator')
|
missing='initiator')
|
||||||
|
|
||||||
|
def initialize_connection_snapshot(self, snapshot, connector):
|
||||||
|
"""Perform attach snapshot for backup snapshots."""
|
||||||
|
# If the snapshot's source volume is a replication volume and the
|
||||||
|
# replication volume has failed over to aux_backend,
|
||||||
|
# attach the snapshot will be failed.
|
||||||
|
self._check_snapshot_replica_volume_status(snapshot)
|
||||||
|
|
||||||
|
vol_attrs = ['id', 'name', 'display_name']
|
||||||
|
Volume = collections.namedtuple('Volume', vol_attrs)
|
||||||
|
volume = Volume(id=snapshot.id,
|
||||||
|
name=snapshot.name,
|
||||||
|
display_name='backup-snapshot')
|
||||||
|
|
||||||
|
return self.initialize_connection(volume, connector)
|
||||||
|
|
||||||
def initialize_connection(self, volume, connector):
|
def initialize_connection(self, volume, connector):
|
||||||
"""Perform necessary work to make an iSCSI connection."""
|
"""Perform necessary work to make an iSCSI connection."""
|
||||||
@utils.synchronized('storwize-host' + self._state['system_id'] +
|
@utils.synchronized('storwize-host' + self._state['system_id'] +
|
||||||
@ -133,9 +150,16 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
proper I/O group)
|
proper I/O group)
|
||||||
"""
|
"""
|
||||||
LOG.debug('enter: initialize_connection: volume %(vol)s with connector'
|
LOG.debug('enter: initialize_connection: volume %(vol)s with connector'
|
||||||
' %(conn)s', {'vol': volume['id'], 'conn': connector})
|
' %(conn)s', {'vol': volume.id, 'conn': connector})
|
||||||
volume_name, backend_helper, node_state = self._get_vol_sys_info(
|
if volume.display_name == 'backup-snapshot':
|
||||||
volume)
|
LOG.debug('It is a virtual volume %(vol)s for attach snapshot.',
|
||||||
|
{'vol': volume.id})
|
||||||
|
volume_name = volume.name
|
||||||
|
backend_helper = self._helpers
|
||||||
|
node_state = self._state
|
||||||
|
else:
|
||||||
|
volume_name, backend_helper, node_state = self._get_vol_sys_info(
|
||||||
|
volume)
|
||||||
|
|
||||||
# Check if a host object is defined for this host name
|
# Check if a host object is defined for this host name
|
||||||
host_name = backend_helper.get_host_from_connector(connector,
|
host_name = backend_helper.get_host_from_connector(connector,
|
||||||
@ -178,7 +202,7 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
|
|
||||||
LOG.debug('leave: initialize_connection:\n volume: %(vol)s\n '
|
LOG.debug('leave: initialize_connection:\n volume: %(vol)s\n '
|
||||||
'connector: %(conn)s\n properties: %(prop)s',
|
'connector: %(conn)s\n properties: %(prop)s',
|
||||||
{'vol': volume['id'], 'conn': connector,
|
{'vol': volume.id, 'conn': connector,
|
||||||
'prop': properties})
|
'prop': properties})
|
||||||
|
|
||||||
return {'driver_volume_type': 'iscsi', 'data': properties, }
|
return {'driver_volume_type': 'iscsi', 'data': properties, }
|
||||||
@ -186,11 +210,19 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
def _get_single_iscsi_data(self, volume, connector, lun_id, chap_secret):
|
def _get_single_iscsi_data(self, volume, connector, lun_id, chap_secret):
|
||||||
LOG.debug('enter: _get_single_iscsi_data: volume %(vol)s with '
|
LOG.debug('enter: _get_single_iscsi_data: volume %(vol)s with '
|
||||||
'connector %(conn)s lun_id %(lun_id)s',
|
'connector %(conn)s lun_id %(lun_id)s',
|
||||||
{'vol': volume['id'], 'conn': connector,
|
{'vol': volume.id, 'conn': connector,
|
||||||
'lun_id': lun_id})
|
'lun_id': lun_id})
|
||||||
|
|
||||||
volume_name, backend_helper, node_state = self._get_vol_sys_info(
|
if volume.display_name == 'backup-snapshot':
|
||||||
volume)
|
LOG.debug('It is a virtual volume %(vol)s for attach snapshot',
|
||||||
|
{'vol': volume.name})
|
||||||
|
volume_name = volume.name
|
||||||
|
backend_helper = self._helpers
|
||||||
|
node_state = self._state
|
||||||
|
else:
|
||||||
|
volume_name, backend_helper, node_state = self._get_vol_sys_info(
|
||||||
|
volume)
|
||||||
|
|
||||||
volume_attributes = backend_helper.get_vdisk_attributes(volume_name)
|
volume_attributes = backend_helper.get_vdisk_attributes(volume_name)
|
||||||
if volume_attributes is None:
|
if volume_attributes is None:
|
||||||
msg = (_('_get_single_iscsi_data: Failed to get attributes'
|
msg = (_('_get_single_iscsi_data: Failed to get attributes'
|
||||||
@ -311,6 +343,16 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
|
|
||||||
return properties
|
return properties
|
||||||
|
|
||||||
|
def terminate_connection_snapshot(self, snapshot, connector, **kwargs):
|
||||||
|
"""Perform detach snapshot for backup snapshots."""
|
||||||
|
vol_attrs = ['id', 'name', 'display_name']
|
||||||
|
Volume = collections.namedtuple('Volume', vol_attrs)
|
||||||
|
volume = Volume(id=snapshot.id,
|
||||||
|
name=snapshot.name,
|
||||||
|
display_name='backup-snapshot')
|
||||||
|
|
||||||
|
return self.terminate_connection(volume, connector, **kwargs)
|
||||||
|
|
||||||
def terminate_connection(self, volume, connector, **kwargs):
|
def terminate_connection(self, volume, connector, **kwargs):
|
||||||
"""Cleanup after an iSCSI connection has been terminated."""
|
"""Cleanup after an iSCSI connection has been terminated."""
|
||||||
# If a fake connector is generated by nova when the host
|
# If a fake connector is generated by nova when the host
|
||||||
@ -337,8 +379,16 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
automatically by this driver when mappings are created)
|
automatically by this driver when mappings are created)
|
||||||
"""
|
"""
|
||||||
LOG.debug('enter: terminate_connection: volume %(vol)s with connector'
|
LOG.debug('enter: terminate_connection: volume %(vol)s with connector'
|
||||||
' %(conn)s', {'vol': volume['id'], 'conn': connector})
|
' %(conn)s', {'vol': volume.id, 'conn': connector})
|
||||||
vol_name, backend_helper, node_state = self._get_vol_sys_info(volume)
|
if volume.display_name == 'backup-snapshot':
|
||||||
|
LOG.debug('It is a virtual volume %(vol)s for detach snapshot.',
|
||||||
|
{'vol': volume.id})
|
||||||
|
vol_name = volume.name
|
||||||
|
backend_helper = self._helpers
|
||||||
|
node_state = self._state
|
||||||
|
else:
|
||||||
|
vol_name, backend_helper, node_state = self._get_vol_sys_info(
|
||||||
|
volume)
|
||||||
|
|
||||||
info = {}
|
info = {}
|
||||||
if 'host' in connector:
|
if 'host' in connector:
|
||||||
@ -366,6 +416,6 @@ class StorwizeSVCISCSIDriver(storwize_common.StorwizeSVCCommonDriver):
|
|||||||
backend_helper.delete_host(host_name)
|
backend_helper.delete_host(host_name)
|
||||||
|
|
||||||
LOG.debug('leave: terminate_connection: volume %(vol)s with '
|
LOG.debug('leave: terminate_connection: volume %(vol)s with '
|
||||||
'connector %(conn)s', {'vol': volume['id'],
|
'connector %(conn)s', {'vol': volume.id,
|
||||||
'conn': connector})
|
'conn': connector})
|
||||||
return info
|
return info
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Add backup snapshots support for Storwize/SVC driver.
|
Loading…
x
Reference in New Issue
Block a user