use of com.emc.storageos.volumecontroller.SRDFRecommendation in project coprhd-controller by CoprHD.
the class PlacementTests method testSRDFBasicPlacement.
@Test
public void testSRDFBasicPlacement() {
String[] vmax1FE = { "50:FE:FE:FE:FE:FE:FE:00", "50:FE:FE:FE:FE:FE:FE:01" };
String[] vmax2FE = { "51:FE:FE:FE:FE:FE:FE:00", "51:FE:FE:FE:FE:FE:FE:01" };
// Create 2 Virtual Arrays
VirtualArray srcVarray = PlacementTestUtils.createVirtualArray(_dbClient, "srcVarray");
VirtualArray tgtVarray = PlacementTestUtils.createVirtualArray(_dbClient, "tgtVarray");
// Create 2 Networks
StringSet connVA = new StringSet();
connVA.add(srcVarray.getId().toString());
Network network1 = PlacementTestUtils.createNetwork(_dbClient, vmax1FE, "VSANSite1", "FC+BROCADE+FE", connVA);
connVA = new StringSet();
connVA.add(tgtVarray.getId().toString());
Network network2 = PlacementTestUtils.createNetwork(_dbClient, vmax2FE, "VSANSite2", "FC+CISCO+FE", connVA);
// Create 2 storage systems
StorageSystem[] storageSystems = PlacementTestUtils.createSRDFStorageSystems(_dbClient, "vmax1", network1, vmax1FE, srcVarray, "vmax2", network2, vmax2FE, tgtVarray);
StorageSystem storageSystem1 = storageSystems[1];
StorageSystem storageSystem2 = storageSystems[2];
StoragePool[] storagePools = PlacementTestUtils.createStoragePoolsForTwo(_dbClient, storageSystem1, srcVarray, storageSystem2, tgtVarray);
// Create a target virtual pool
VirtualPool tgtVpool = new VirtualPool();
tgtVpool.setId(URI.create("tgtVpool"));
tgtVpool.setLabel("Target Vpool");
tgtVpool.setSupportedProvisioningType(VirtualPool.ProvisioningType.Thin.name());
tgtVpool.setDriveType(SupportedDriveTypes.FC.name());
StringSet matchedPools2 = new StringSet();
matchedPools2.add(storagePools[4].getId().toString());
matchedPools2.add(storagePools[5].getId().toString());
matchedPools2.add(storagePools[6].getId().toString());
tgtVpool.setMatchedStoragePools(matchedPools2);
tgtVpool.setUseMatchedPools(true);
StringSet virtualArrays2 = new StringSet();
virtualArrays2.add(tgtVarray.getId().toString());
tgtVpool.setVirtualArrays(virtualArrays2);
_dbClient.createObject(tgtVpool);
// Make a remote copy protection setting
VpoolRemoteCopyProtectionSettings settings = new VpoolRemoteCopyProtectionSettings();
settings.setId(URI.create("remoteCopySettings"));
settings.setCopyMode(VpoolRemoteCopyProtectionSettings.CopyModes.ASYNCHRONOUS.name());
settings.setVirtualArray(tgtVarray.getId());
settings.setVirtualPool(tgtVpool.getId());
_dbClient.createObject(settings);
// Create an SRDF source virtual pool
VirtualPool srcVpool = new VirtualPool();
srcVpool.setId(URI.create("srcVpool"));
srcVpool.setLabel("Source Vpool");
srcVpool.setSupportedProvisioningType(VirtualPool.ProvisioningType.Thin.name());
srcVpool.setDriveType(SupportedDriveTypes.FC.name());
StringSet matchedPools1 = new StringSet();
matchedPools1.add(storagePools[1].getId().toString());
matchedPools1.add(storagePools[2].getId().toString());
matchedPools1.add(storagePools[3].getId().toString());
srcVpool.setMatchedStoragePools(matchedPools1);
srcVpool.setUseMatchedPools(true);
StringSet virtualArrays1 = new StringSet();
virtualArrays1.add(srcVarray.getId().toString());
srcVpool.setVirtualArrays(virtualArrays1);
StringMap remoteProtectionSettings = new StringMap();
remoteProtectionSettings.put(tgtVarray.getId().toString(), settings.getId().toString());
srcVpool.setProtectionRemoteCopySettings(remoteProtectionSettings);
_dbClient.createObject(srcVpool);
// Create Tenant
TenantOrg tenant = new TenantOrg();
tenant.setId(URI.create("tenant"));
_dbClient.createObject(tenant);
// Create a project object
Project project = new Project();
project.setId(URI.create("project"));
project.setLabel("RDG1");
project.setTenantOrg(new NamedURI(tenant.getId(), project.getLabel()));
_dbClient.createObject(project);
// Create capabilities
VirtualPoolCapabilityValuesWrapper capabilities = PlacementTestUtils.createCapabilities("2GB", 1, null);
// Run single volume placement: Run 10 times to make sure pool3 never comes up for source and pool6 for target.
for (int i = 0; i < 10; i++) {
Map<VpoolUse, List<Recommendation>> recommendationsMap = PlacementTestUtils.invokePlacementForVpool(_dbClient, _coordinator, srcVarray, project, srcVpool, capabilities);
List<Recommendation> recommendations = recommendationsMap.get(VpoolUse.ROOT);
assertNotNull(recommendations);
assertTrue(!recommendations.isEmpty());
assertNotNull(recommendations.get(0));
assert (recommendations.get(0) instanceof SRDFRecommendation);
SRDFRecommendation srdfRecommendation = (SRDFRecommendation) recommendations.get(0);
URI srcStoragePool = srdfRecommendation.getSourceStoragePool();
assert (srcStoragePool.equals(storagePools[1].getId()) || srcStoragePool.equals(storagePools[2].getId()));
recommendations = recommendationsMap.get(VpoolUse.SRDF_COPY);
assertTrue(!recommendations.isEmpty());
assertNotNull(recommendations.get(0));
assert (recommendations.get(0) instanceof SRDFCopyRecommendation);
SRDFCopyRecommendation srdfCopyRecommendation = (SRDFCopyRecommendation) recommendations.get(0);
URI tgtStoragePool = srdfCopyRecommendation.getSourceStoragePool();
assert (tgtStoragePool.equals(storagePools[4].getId()) || tgtStoragePool.equals(storagePools[5].getId()));
}
}
use of com.emc.storageos.volumecontroller.SRDFRecommendation in project coprhd-controller by CoprHD.
the class SRDFBlockServiceApiImpl method upgradeToSRDFTargetVolume.
/**
* Upgrade a local block volume to a protected SRDF volume
*
* @param volume
* -- srdf source volume (existing).
* @param vpool
* -- Requested vpool.
* @param taskId
* @throws InternalException
*/
private List<VolumeDescriptor> upgradeToSRDFTargetVolume(final Volume volume, final VirtualPool vpool, final VirtualPoolChangeParam cosChangeParam, final String taskId) throws InternalException {
VirtualPoolCapabilityValuesWrapper capabilities = new VirtualPoolCapabilityValuesWrapper();
capabilities.put(VirtualPoolCapabilityValuesWrapper.BLOCK_CONSISTENCY_GROUP, volume.getConsistencyGroup());
List<Recommendation> recommendations = getRecommendationsForVirtualPoolChangeRequest(volume, vpool, cosChangeParam);
if (recommendations.isEmpty()) {
throw APIException.badRequests.noStorageFoundForVolume();
}
// Call out to the respective block service implementation to prepare and create the
// volumes based on the recommendations.
Project project = _dbClient.queryObject(Project.class, volume.getProject());
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, volume.getVirtualArray());
// Generate a VolumeCreate object that contains the information that createVolumes likes to
// consume.
VolumeCreate param = new VolumeCreate(volume.getLabel(), String.valueOf(volume.getCapacity()), 1, vpool.getId(), volume.getVirtualArray(), volume.getProject().getURI());
capabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, new Integer(1));
if (volume.getIsComposite()) {
// add meta volume properties to the capabilities instance
capabilities.put(VirtualPoolCapabilityValuesWrapper.IS_META_VOLUME, volume.getIsComposite());
capabilities.put(VirtualPoolCapabilityValuesWrapper.META_VOLUME_TYPE, volume.getCompositionType());
capabilities.put(VirtualPoolCapabilityValuesWrapper.META_VOLUME_MEMBER_COUNT, volume.getMetaMemberCount());
capabilities.put(VirtualPoolCapabilityValuesWrapper.META_VOLUME_MEMBER_SIZE, volume.getMetaMemberSize());
_log.debug(String.format("Capabilities : isMeta: %s, Meta Type: %s, Member size: %s, Count: %s", capabilities.getIsMetaVolume(), capabilities.getMetaVolumeType(), capabilities.getMetaVolumeMemberSize(), capabilities.getMetaVolumeMemberCount()));
}
TaskList taskList = new TaskList();
// Prepare the Bourne Volumes to be created and associated
// with the actual storage system volumes created. Also create
// a BlockTaskList containing the list of task resources to be
// returned for the purpose of monitoring the volume creation
// operation for each volume to be created.
String volumeLabel = param.getName();
final BlockConsistencyGroup consistencyGroup = capabilities.getBlockConsistencyGroup() == null ? null : _dbClient.queryObject(BlockConsistencyGroup.class, capabilities.getBlockConsistencyGroup());
// prepare the volumes
List<URI> volumeURIs = prepareRecommendedVolumes(taskId, taskList, project, varray, vpool, capabilities.getResourceCount(), recommendations, consistencyGroup, volumeLabel, param.getSize());
List<VolumeDescriptor> resultListVolumeDescriptors = new ArrayList<>();
// Execute the volume creations requests for each recommendation.
Iterator<Recommendation> recommendationsIter = recommendations.iterator();
while (recommendationsIter.hasNext()) {
Recommendation recommendation = recommendationsIter.next();
try {
List<VolumeDescriptor> volumeDescriptors = createVolumeDescriptors((SRDFRecommendation) recommendation, volumeURIs, capabilities);
// Log volume descriptor information
logVolumeDescriptorPrecreateInfo(volumeDescriptors, taskId);
resultListVolumeDescriptors.addAll(volumeDescriptors);
} catch (InternalException e) {
if (_log.isErrorEnabled()) {
_log.error("Controller error", e);
}
String errorMsg = String.format("Controller error: %s", e.getMessage());
if (volumeURIs != null) {
for (URI volumeURI : volumeURIs) {
Volume volume1 = _dbClient.queryObject(Volume.class, volumeURI);
if (volume1 != null) {
Operation op = new Operation();
ServiceCoded coded = ServiceError.buildServiceError(ServiceCode.API_RP_VOLUME_CREATE_ERROR, errorMsg.toString());
op.setMessage(errorMsg);
op.error(coded);
_dbClient.createTaskOpStatus(Volume.class, volumeURI, taskId, op);
TaskResourceRep volumeTask = toTask(volume1, taskId, op);
if (volume1.getPersonality() != null && volume1.getPersonality().equals(Volume.PersonalityTypes.SOURCE.toString())) {
taskList.getTaskList().add(volumeTask);
}
}
}
}
// the user what succeeded and what failed.
throw APIException.badRequests.cannotCreateSRDFVolumes(e);
}
}
return resultListVolumeDescriptors;
}
use of com.emc.storageos.volumecontroller.SRDFRecommendation in project coprhd-controller by CoprHD.
the class SRDFBlockServiceApiImpl method prepareRecommendedVolumes.
/**
* Prepare Recommended Volumes for SRDF scenarios only.
*
* This method is responsible for acting the same as the unprotected "prepareRecommendedVolumes"
* call, however it needs to create multiple volumes per single volume requests in order to
* generate SRDF protection.
*
* Those most typical scenario is, that for any one volume requested in an SRDF configuration,
* we create: 1. One Source Volume 3. One Target Volume on target varrays
*
* @param param
* volume create request
* @param task
* task from request or generated
* @param taskList
* task list
* @param project
* project from request
* @param varray
* varray from request
* @param vpool
* vpool from request
* @param volumeCount
* volume count from the request
* @param recommendations
* list of resulting recommendations from placement
* @param consistencyGroup
* consistency group ID
* @return list of volume URIs created
*/
private List<URI> prepareRecommendedVolumes(final String task, final TaskList taskList, final Project project, final VirtualArray varray, final VirtualPool vpool, final Integer volumeCount, final List<Recommendation> recommendations, final BlockConsistencyGroup consistencyGroup, final String volumeLabel, final String size) {
List<URI> volumeURIs = new ArrayList<URI>();
try {
// Create an entire Protection object for each recommendation result.
Iterator<Recommendation> recommendationsIter = recommendations.iterator();
while (recommendationsIter.hasNext()) {
SRDFRecommendation recommendation = (SRDFRecommendation) recommendationsIter.next();
// until we (later) fix creating volumes while in SWAPPED state.
for (SRDFRecommendation.Target target : recommendation.getVirtualArrayTargetMap().values()) {
if (target != null && SRDFScheduler.rdfGroupHasSwappedVolumes(_dbClient, project.getId(), target.getSourceRAGroup())) {
RemoteDirectorGroup rdg = _dbClient.queryObject(RemoteDirectorGroup.class, target.getSourceRAGroup());
throw BadRequestException.badRequests.cannotAddVolumesToSwappedReplicationGroup(rdg.getLabel());
}
}
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, recommendation.getSourceStorageSystem());
// operation for each volume to be created.
for (int i = 0; i < volumeCount; i++) {
// get generated volume name
String newVolumeLabel = generateDefaultVolumeLabel(volumeLabel, i, volumeCount);
// Grab the existing volume and task object from the incoming task list
Volume srcVolume = StorageScheduler.getPrecreatedVolume(_dbClient, taskList, newVolumeLabel);
boolean volumePrecreated = false;
if (srcVolume != null) {
volumePrecreated = true;
}
// number of targets.
if (recommendation.getVpoolChangeVolume() == null) {
srcVolume = prepareVolume(srcVolume, project, varray, vpool, size, recommendation, newVolumeLabel, consistencyGroup, task, false, Volume.PersonalityTypes.SOURCE, null, null, null);
volumeURIs.add(srcVolume.getId());
if (!volumePrecreated) {
taskList.getTaskList().add(toTask(srcVolume, task));
}
} else {
srcVolume = _dbClient.queryObject(Volume.class, recommendation.getVpoolChangeVolume());
Operation op = _dbClient.createTaskOpStatus(Volume.class, srcVolume.getId(), task, ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME);
// Fill in additional information that prepare would've filled in that's specific to SRDF.
// Best to only fill in information here that isn't harmful if a rollback occurred,
// and the protection never got set up.
volumeURIs.add(srcVolume.getId());
taskList.getTaskList().add(toTask(srcVolume, task, op));
}
// Remove "-source" designation in the label if found
if (newVolumeLabel.contains("-source")) {
newVolumeLabel = newVolumeLabel.replaceAll("-source", "");
}
Map<URI, VpoolRemoteCopyProtectionSettings> settingMap = VirtualPool.getRemoteProtectionSettings(vpool, _dbClient);
for (VirtualArray protectionVirtualArray : SRDFScheduler.getTargetVirtualArraysForVirtualPool(project, vpool, _dbClient, _permissionsHelper)) {
VpoolRemoteCopyProtectionSettings settings = settingMap.get(protectionVirtualArray.getId());
// COP-16363 Create target BCG in controllersvc
// Prepare and populate CG request for the SRDF targets
volumeURIs.addAll(prepareTargetVolumes(project, vpool, recommendation, new StringBuilder(newVolumeLabel), protectionVirtualArray, settings, srcVolume, task, taskList, size));
}
}
}
} catch (InternalException e) {
_log.error("Rolling back the created CGs if any.");
throw e;
} catch (BadRequestException e) {
_log.info("Bad request exception: " + e.getMessage());
throw e;
} catch (Exception e) {
_log.error("Rolling back the created CGs if any.");
throw APIException.badRequests.srdfInternalError(e);
}
return volumeURIs;
}
Aggregations