cimproperty.value = 'OS-myhost-MV'
return cimproperty
+ def fake_getSupportedReplicationTypes(self):
+ cimproperty = Fake_CIMProperty()
+ cimproperty.value = [2L, 10L]
+ return cimproperty
+
class Fake_CIM_TierPolicyServiceCapabilities():
result = self._enum_storagesystems()
elif name == 'Symm_TierPolicyRule':
result = self._enum_policyrules()
+ elif name == 'CIM_ReplicationServiceCapabilities':
+ result = self._enum_repservcpbls()
else:
result = self._default_enum()
return result
result = self._getinstance_storagehardwareid(objectpath)
elif name == 'Symm_VirtualProvisioningPool':
result = self._getinstance_pool(objectpath)
+ elif name == 'Symm_ReplicationServiceCapabilities':
+ result = self._getinstance_replicationServCapabilities(objectpath)
else:
result = self._default_getinstance(objectpath)
result = self._enum_initMaskingGroup()
elif ResultClass == 'Symm_LunMaskingView':
result = self._enum_maskingView()
+ elif ResultClass == 'EMC_Meta':
+ result = self._enum_metavolume()
else:
result = self._default_assocnames(objectpath)
return result
svInstance['PercentSynced'] = 100
return svInstance
+ def _getinstance_replicationServCapabilities(self, objectpath):
+ repServCpblInstance = SYMM_SrpStoragePool()
+ classcimproperty = Fake_CIMProperty()
+ repTypesCimproperty = (
+ classcimproperty.fake_getSupportedReplicationTypes())
+ properties = {u'SupportedReplicationTypes': repTypesCimproperty}
+ repServCpblInstance.properties = properties
+ return repServCpblInstance
+
def _default_getinstance(self, objectpath):
return objectpath
portgroups.append(portgroup)
return portgroups
+ def _enum_metavolume(self):
+ return []
+
def _default_enum(self):
names = []
name = {}
self.data.test_volume,
EMCVMAXCommonData.test_source_volume)
- @mock.patch.object(
- emc_vmax_utils.EMCVMAXUtils,
- 'get_volume_meta_head',
- return_value=None)
- @mock.patch.object(
- emc_vmax_common.EMCVMAXCommon,
- '_find_storage_sync_sv_sv',
- return_value=(None, None))
- @mock.patch.object(
- FakeDB,
- 'volume_get',
- return_value=EMCVMAXCommonData.test_source_volume)
- @mock.patch.object(
- volume_types,
- 'get_volume_type_extra_specs',
- return_value={'volume_backend_name': 'ISCSIFAST'})
- def test_create_clone_simple_volume_fast_success(
- self, mock_volume_type, mock_volume, mock_sync_sv,
- mock_simple_volume):
- self.data.test_volume['volume_name'] = "vmax-1234567"
- self.driver.common.fast.is_volume_in_default_SG = (
- mock.Mock(return_value=True))
- self.driver.create_cloned_volume(self.data.test_volume,
- EMCVMAXCommonData.test_source_volume)
-
@mock.patch.object(
emc_vmax_common.EMCVMAXCommon,
'_get_pool_and_storage_system',
self.data.test_volume,
EMCVMAXCommonData.test_source_volume)
- @mock.patch.object(
- emc_vmax_utils.EMCVMAXUtils,
- 'get_volume_meta_head',
- return_value=None)
- @mock.patch.object(
- emc_vmax_common.EMCVMAXCommon,
- '_find_storage_sync_sv_sv',
- return_value=(None, None))
- @mock.patch.object(
- FakeDB,
- 'volume_get',
- return_value=EMCVMAXCommonData.test_source_volume)
- @mock.patch.object(
- volume_types,
- 'get_volume_type_extra_specs',
- return_value={'volume_backend_name': 'FCFAST'})
- def test_create_clone_simple_volume_fast_success(
- self, mock_volume_type, mock_volume, mock_sync_sv,
- mock_simple_volume):
+ def test_create_clone_simple_volume_fast_success(self):
+ extraSpecs = {'storagetype:fastpolicy': 'FC_GOLD1',
+ 'volume_backend_name': 'FCFAST',
+ 'isV3': False}
+ self.driver.common._initial_setup = (
+ mock.Mock(return_value=extraSpecs))
+ self.driver.common.extraSpecs = extraSpecs
+ self.driver.utils.is_clone_licensed = (
+ mock.Mock(return_value=True))
+ FakeDB.volume_get = (
+ mock.Mock(return_value=EMCVMAXCommonData.test_source_volume))
self.data.test_volume['volume_name'] = "vmax-1234567"
self.driver.common.fast.is_volume_in_default_SG = (
mock.Mock(return_value=True))
+ self.driver.utils.isArrayV3 = mock.Mock(return_value=False)
+ self.driver.common._find_storage_sync_sv_sv = (
+ mock.Mock(return_value=(None, None)))
self.driver.create_cloned_volume(self.data.test_volume,
EMCVMAXCommonData.test_source_volume)
self.driver.delete_cgsnapshot(
self.data.test_ctxt, self.data.test_CG_snapshot)
+ # Bug 1385450
+ def test_create_clone_without_license(self):
+ mockRepServCap = {}
+ mockRepServCap['InstanceID'] = 'SYMMETRIX+1385450'
+ self.driver.utils.find_replication_service_capabilities = (
+ mock.Mock(return_value=mockRepServCap))
+ self.driver.utils.is_clone_licensed = (
+ mock.Mock(return_value=False))
+ self.assertRaises(exception.VolumeBackendAPIException,
+ self.driver.create_cloned_volume,
+ self.data.test_volume,
+ EMCVMAXCommonData.test_source_volume)
+
def _cleanup(self):
bExists = os.path.exists(self.config_file_path)
if bExists:
STORAGEGROUPTYPE = 4
POSTGROUPTYPE = 3
+CLONE_REPLICATION_TYPE = 10
EMC_ROOT = 'root/emc'
CONCATENATED = 'concatenated'
raise exception.VolumeBackendAPIException(
data=exceptionMessage)
return instance
+
+ def find_replication_service_capabilities(self, conn, storageSystemName):
+ """Find the replication service capabilities instance name.
+
+ :param conn: the connection to the ecom server
+ :param storageSystemName: the storage system name
+ :returns: foundRepServCapability
+ """
+ foundRepServCapability = None
+ repservices = conn.EnumerateInstanceNames(
+ 'CIM_ReplicationServiceCapabilities')
+ for repservCap in repservices:
+ if storageSystemName in repservCap['InstanceID']:
+ foundRepServCapability = repservCap
+ LOG.debug("Found Replication Service Capabilities: "
+ "%(repservCap)s",
+ {'repservCap': repservCap})
+ break
+ if foundRepServCapability is None:
+ exceptionMessage = (_("Replication Service Capability not found "
+ "on %(storageSystemName)s.")
+ % {'storageSystemName': storageSystemName})
+ LOG.error(exceptionMessage)
+ raise exception.VolumeBackendAPIException(data=exceptionMessage)
+
+ return foundRepServCapability
+
+ def is_clone_licensed(self, conn, capabilityInstanceName):
+ """Check if the clone feature is licensed and enabled.
+
+ :param conn: the connection to the ecom server
+ :param capabilityInstanceName: the replication service capabilities
+ instance name
+ :returns: True if licensed and enabled; False otherwise.
+ """
+ capabilityInstance = conn.GetInstance(capabilityInstanceName)
+ propertiesList = capabilityInstance.properties.items()
+ for properties in propertiesList:
+ if properties[0] == 'SupportedReplicationTypes':
+ cimProperties = properties[1]
+ repTypes = cimProperties.value
+ LOG.debug("Found supported replication types: "
+ "%(repTypes)s",
+ {'repTypes': repTypes})
+ if CLONE_REPLICATION_TYPE in repTypes:
+ # Clone is a supported replication type.
+ LOG.debug("Clone is licensed and enabled.")
+ return True
+ return False