Merge "VMAX driver - volume and snapshot treated as dicts in attach snapshot" into stable/ocata

This commit is contained in:
Jenkins 2017-08-01 19:58:32 +00:00 committed by Gerrit Code Review
commit 16852f9048
4 changed files with 117 additions and 32 deletions

View File

@ -33,6 +33,9 @@ from cinder.objects import consistencygroup
from cinder.objects import fields
from cinder.objects import qos_specs
from cinder import test
from cinder.tests.unit import fake_constants
from cinder.tests.unit import fake_snapshot
from cinder.tests.unit import fake_volume
from cinder.tests.unit import utils as unit_utils
from cinder import utils as cinder_utils
@ -753,6 +756,17 @@ class VMAXCommonData(object):
UNSYNCHRONIZED = 3
multiPoolSupportEnabled = True
test_vol_obj = fake_volume.fake_volume_obj(
context='context', expected_attrs=[], name='vol1', size=2,
provider_auth=None, host=fake_host,
volume_type_id=fake_constants.VOLUME_TYPE_ID,
provider_location=six.text_type(provider_location))
test_snap_obj = fake_snapshot.fake_snapshot_obj(
context='context', name='ss1', size=2, id=fake_constants.SNAPSHOT_ID,
provider_location=six.text_type(provider_location),
host=fake_host, volume=test_vol_obj)
class FakeLookupService(object):
def get_device_mapping_from_network(self, initiator_wwns, target_wwns):
@ -8506,7 +8520,7 @@ class VMAXFCTest(test.TestCase):
@mock.patch.object(
common.VMAXCommon,
'initialize_connection',
'initialize_connection_snapshot',
return_value=VMAXCommonData.fc_device_info)
@mock.patch.object(
fc.VMAXFCDriver,
@ -8515,13 +8529,14 @@ class VMAXFCTest(test.TestCase):
VMAXCommonData.end_point_map))
def test_initialize_connection_snapshot(self, mock_map, mock_conn):
data = self.driver.initialize_connection_snapshot(
self.data.test_snapshot_v3, self.data.connector)
self.data.test_snap_obj,
self.data.connector)
self.assertEqual('fibre_channel', data['driver_volume_type'])
self.assertEqual(3, data['data']['target_lun'])
@mock.patch.object(
common.VMAXCommon,
'_unmap_lun')
'_unmap_lun_snapshot')
@mock.patch.object(
fc.VMAXFCDriver,
'_get_zoning_mappings',
@ -8535,7 +8550,7 @@ class VMAXFCTest(test.TestCase):
common = self.driver.common
common.conn = FakeEcomConnection()
data = self.driver.terminate_connection_snapshot(
self.data.test_snapshot_v3, self.data.connector)
self.data.test_snap_obj, self.data.connector)
self.assertEqual('fibre_channel', data['driver_volume_type'])
self.assertEqual(2, len(data['data']['target_wwn']))
@ -10116,24 +10131,25 @@ class VMAXISCSITest(test.TestCase):
False, {}))
@mock.patch.object(
common.VMAXCommon,
'initialize_connection',
'initialize_connection_snapshot',
return_value=VMAXCommonData.iscsi_device_info)
def test_initialize_connection_snapshot(self, mock_conn, mock_num):
data = self.driver.initialize_connection_snapshot(
self.data.test_snapshot_v3, self.data.connector)
self.data.test_snap_obj, self.data.connector)
self.assertEqual('iscsi', data['driver_volume_type'])
self.assertEqual(1, data['data']['target_lun'])
@mock.patch.object(
common.VMAXCommon,
'_unmap_lun')
'_unmap_lun_snapshot')
def test_terminate_connection_snapshot(self, mock_unmap):
common = self.driver.common
common.conn = FakeEcomConnection()
self.driver.terminate_connection_snapshot(
self.data.test_snapshot_v3, self.data.connector)
common._unmap_lun.assert_called_once_with(
self.data.test_snapshot_v3, self.data.connector)
self.data.test_snap_obj, self.data.connector)
common._unmap_lun_snapshot.assert_called_once_with(
self.data.test_snap_obj, self.data.test_vol_obj,
self.data.connector)
@mock.patch.object(
masking.VMAXMasking,

View File

@ -514,6 +514,27 @@ class VMAXCommon(object):
if self.utils.is_volume_failed_over(volume):
extraSpecs = self._get_replication_extraSpecs(
extraSpecs, self.rep_config)
self._unmap_lun_common(volume, connector, extraSpecs)
def _unmap_lun_snapshot(self, snapshot, volume, connector):
"""Unmaps a snapshot from the host.
:param snapshot: the snapshot Object
:param volume: the volume Object
:param connector: the connector Object
:raises: VolumeBackendAPIException
"""
extraSpecs = self._initial_setup(volume)
self._unmap_lun_common(snapshot, connector, extraSpecs)
def _unmap_lun_common(self, volume, connector, extraSpecs):
"""Unmaps a volume from the host.
:param volume: the volume Object
:param connector: the connector Object
:param extraSpecs: extra specifications
:raises: VolumeBackendAPIException
"""
volumename = volume['name']
LOG.info(_LI("Unmap volume: %(volume)s."),
{'volume': volumename})
@ -569,6 +590,23 @@ class VMAXCommon(object):
def initialize_connection(self, volume, connector):
"""Initializes the connection and returns device and connection info.
:param volume: volume Object
:param connector: the connector Object
:returns: dict -- deviceInfoDict - device information dict
:raises: VolumeBackendAPIException
"""
extraSpecs = self._initial_setup(volume)
if self.utils.is_volume_failed_over(volume):
extraSpecs = self._get_replication_extraSpecs(
extraSpecs, self.rep_config)
return self.initialize_connection_common(
volume, connector, extraSpecs)
def initialize_connection_common(self, volume, connector, extraSpecs):
"""Initializes the connection and returns device and connection info.
The volume may be already mapped, if this is so the deviceInfo tuple
is returned. If the volume is not already mapped then we need to
gather information to either 1. Create an new masking view or 2. Add
@ -592,11 +630,10 @@ class VMAXCommon(object):
:param volume: volume Object
:param connector: the connector Object
:param extraSpecs: extra specifications
:returns: dict -- deviceInfoDict - device information dict
:raises: VolumeBackendAPIException
"""
portGroupName = None
extraSpecs = self._initial_setup(volume)
is_multipath = connector.get('multipath', False)
volumeName = volume['name']
@ -604,9 +641,6 @@ class VMAXCommon(object):
{'volume': volumeName})
self.conn = self._get_ecom_connection()
if self.utils.is_volume_failed_over(volume):
extraSpecs = self._get_replication_extraSpecs(
extraSpecs, self.rep_config)
deviceInfoDict, isLiveMigration, sourceInfoDict = (
self._wrap_find_device_number(
volume, connector['host']))
@ -1835,10 +1869,10 @@ class VMAXCommon(object):
name = ast.literal_eval(loc)
keys = name['keybindings']
systemName = keys['SystemName']
admin_metadata = {}
admin_metadata = None
if 'admin_metadata' in volume:
admin_metadata = volume.admin_metadata
if 'targetVolumeName' in admin_metadata:
if admin_metadata and 'targetVolumeName' in admin_metadata:
targetVolName = admin_metadata['targetVolumeName']
prefix1 = 'SYMMETRIX+'
prefix2 = 'SYMMETRIX-+-'
@ -6059,3 +6093,32 @@ class VMAXCommon(object):
if self.multiPoolSupportEnabled:
self.multiPoolSupportEnabled = False
return secondaryInfo
def initialize_connection_snapshot(
self, snapshot, volume, connector):
"""Initializes the connection and returns device and connection info.
:param snapshot: snapshot Object
:param volume: volume Object
:param connector: the connector Object
:returns: dict -- deviceInfoDict - device information dict
:raises: VolumeBackendAPIException
"""
extraSpecs = self._initial_setup(volume)
return self.initialize_connection_common(
snapshot, connector, extraSpecs)
def terminate_connection_snapshot(self, snapshot, volume, connector):
"""Disallow connection from connector.
:param snapshot: the snapshot Object
:param volume: the volume Object
:param connector: the connector Object
"""
if not connector:
exception_message = (_("The connector object from nova "
"cannot be None."))
raise exception.VolumeBackendAPIException(
data=exception_message)
self._unmap_lun_snapshot(snapshot, volume, connector)

View File

@ -496,10 +496,10 @@ class VMAXFCDriver(driver.FibreChannelDriver):
:param kwargs: additional parameters
:returns: data dict
"""
src_volume = snapshot['volume']
snapshot['host'] = src_volume['host']
return self.initialize_connection(snapshot, connector)
src_volume = snapshot.volume
device_info = self.common.initialize_connection_snapshot(
snapshot, src_volume, connector)
return self.populate_data(device_info, snapshot, connector)
def terminate_connection_snapshot(self, snapshot, connector, **kwargs):
"""Disallows connection to snapshot.
@ -508,9 +508,17 @@ class VMAXFCDriver(driver.FibreChannelDriver):
:param connector: the connector object
:param kwargs: additional parameters
"""
src_volume = snapshot['volume']
snapshot['host'] = src_volume['host']
return self.terminate_connection(snapshot, connector, **kwargs)
src_volume = snapshot.volume
data = {'driver_volume_type': 'fibre_channel',
'data': {}}
zoning_mappings = (
self._get_zoning_mappings(snapshot, connector))
if zoning_mappings:
self.common.terminate_connection_snapshot(
snapshot, src_volume, connector)
data = self._cleanup_zones(zoning_mappings)
return data
def backup_use_temp_snapshot(self):
return True

View File

@ -418,10 +418,9 @@ class VMAXISCSIDriver(driver.ISCSIDriver):
:param kwargs: additional parameters
:returns: iscsi dict
"""
src_volume = snapshot['volume']
snapshot['host'] = src_volume['host']
device_info = self.common.initialize_connection(
snapshot, connector)
src_volume = snapshot.volume
device_info = self.common.initialize_connection_snapshot(
snapshot, src_volume, connector)
return self.get_iscsi_dict(
device_info, snapshot, connector)
@ -432,10 +431,9 @@ class VMAXISCSIDriver(driver.ISCSIDriver):
:param connector: the connector object
:param kwargs: additional parameters
"""
src_volume = snapshot['volume']
snapshot['host'] = src_volume['host']
return self.common.terminate_connection(snapshot,
connector)
src_volume = snapshot.volume
return self.common.terminate_connection_snapshot(
snapshot, src_volume, connector)
def backup_use_temp_snapshot(self):
return True