use of com.emc.storageos.volumecontroller.VPlexRecommendation in project coprhd-controller by CoprHD.
the class VPlexBlockServiceApiImpl method importVirtualVolume.
/**
* Import an existing volume to a VPLEX to make it a Virtual Volume.
* Outline: 1. Determine the VPLEX(s) that could be used. 2. If this is to
* become a distributed virtual volume, get a Recommendation for the pool
* for the haVirtualArray of the Virtual Volume. 3. Create a Virtual Volume
* and link it to the existing Volume. 4. If this is a distributed virtual
* volume, create a new Volume and link it to the virtual volume. 5. Format
* the parameters and call the controller.
*
* @param arrayURI -- the URI of the Storage Array holding the existing
* Volume.
* @param importVolume -- An existing Volume that has been provisioned.
* @param vpool -- The vpool requested on the vpool change request.
* @param taskId -- The taskId
* @throws InternalException
*/
public void importVirtualVolume(URI arrayURI, Volume importVolume, VirtualPool vpool, String taskId) throws InternalException {
VirtualArray neighborhood = _dbClient.queryObject(VirtualArray.class, importVolume.getVirtualArray());
Project project = _dbClient.queryObject(Project.class, importVolume.getProject());
URI nullPoolURI = NullColumnValueGetter.getNullURI();
BlockConsistencyGroup consistencyGroup = null;
if (importVolume.getConsistencyGroup() != null) {
consistencyGroup = _dbClient.queryObject(BlockConsistencyGroup.class, importVolume.getConsistencyGroup());
}
// Determine the VPLEX(s) that could be used.
Set<URI> vplexes = ConnectivityUtil.getVPlexSystemsAssociatedWithArray(_dbClient, arrayURI);
Iterator<URI> vplexIter = vplexes.iterator();
while (vplexIter.hasNext()) {
StorageSystem vplex = _dbClient.queryObject(StorageSystem.class, vplexIter.next());
StringSet vplexVarrays = vplex.getVirtualArrays();
if ((vplexVarrays == null) || (vplexVarrays.isEmpty()) || (!vplexVarrays.contains(neighborhood.getId().toString()))) {
vplexIter.remove();
}
}
if (vplexes.isEmpty()) {
throw APIException.badRequests.noVPlexSystemsAssociatedWithStorageSystem(arrayURI);
}
// If distributed virtual volume, get a recommendation.
// Then create the volume.
List<VolumeDescriptor> descriptors = new ArrayList<VolumeDescriptor>();
URI vplexURI = null;
StorageSystem vplexSystem = null;
Volume createVolume = null;
Project vplexProject;
if (vpool.getHighAvailability().equals(VirtualPool.HighAvailabilityType.vplex_distributed.name())) {
// Determine if the user requested a specific HA VirtualArray and an associated HA VirtualPool.
VirtualArray requestedHaVarray = null;
VirtualPool requestedHaVirtualPool = vpool;
try {
if (vpool.getHaVarrayVpoolMap() != null && !vpool.getHaVarrayVpoolMap().isEmpty()) {
for (String haNH : vpool.getHaVarrayVpoolMap().keySet()) {
if (haNH.equals(NullColumnValueGetter.getNullURI().toString())) {
continue;
}
requestedHaVarray = _dbClient.queryObject(VirtualArray.class, new URI(haNH));
String haVirtualPool = vpool.getHaVarrayVpoolMap().get(haNH);
if (haVirtualPool.equals(NullColumnValueGetter.getNullURI().toString())) {
continue;
}
requestedHaVirtualPool = _dbClient.queryObject(VirtualPool.class, new URI(haVirtualPool));
break;
}
}
} catch (URISyntaxException ex) {
s_logger.error("URISyntaxException", ex);
}
VirtualPoolCapabilityValuesWrapper cosCapabilities = new VirtualPoolCapabilityValuesWrapper();
cosCapabilities.put(VirtualPoolCapabilityValuesWrapper.SIZE, getVolumeCapacity(importVolume));
cosCapabilities.put(VirtualPoolCapabilityValuesWrapper.RESOURCE_COUNT, new Integer(1));
cosCapabilities.put(VirtualPoolCapabilityValuesWrapper.THIN_PROVISIONING, importVolume.getThinlyProvisioned());
// Get the recommendations and pick one.
List<Recommendation> recommendations = getBlockScheduler().scheduleStorageForImport(neighborhood, vplexes, requestedHaVarray, requestedHaVirtualPool, cosCapabilities);
if (recommendations.isEmpty()) {
throw APIException.badRequests.noStorageFoundForVolumeMigration(requestedHaVirtualPool.getLabel(), requestedHaVarray.getLabel(), importVolume.getId());
}
Recommendation recommendation = recommendations.get(0);
VPlexRecommendation vplexRecommendation = (VPlexRecommendation) recommendation;
vplexURI = vplexRecommendation.getVPlexStorageSystem();
vplexSystem = _dbClient.queryObject(StorageSystem.class, vplexURI);
vplexProject = getVplexProject(vplexSystem, _dbClient, _tenantsService);
// Prepare the created volume.
VirtualArray haVirtualArray = _dbClient.queryObject(VirtualArray.class, vplexRecommendation.getVirtualArray());
createVolume = prepareVolumeForRequest(getVolumeCapacity(importVolume), vplexProject, haVirtualArray, vpool, vplexRecommendation.getSourceStorageSystem(), vplexRecommendation.getSourceStoragePool(), importVolume.getLabel() + "-1", ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME, taskId, _dbClient);
createVolume.addInternalFlags(Flag.INTERNAL_OBJECT);
_dbClient.updateObject(createVolume);
VolumeDescriptor desc = new VolumeDescriptor(VolumeDescriptor.Type.BLOCK_DATA, createVolume.getStorageController(), createVolume.getId(), createVolume.getPool(), cosCapabilities);
descriptors.add(desc);
} else {
vplexURI = vplexes.toArray(new URI[0])[0];
vplexSystem = _dbClient.queryObject(StorageSystem.class, vplexURI);
vplexProject = getVplexProject(vplexSystem, _dbClient, _tenantsService);
}
// Prepare the VPLEX Virtual volume.
Volume vplexVolume = prepareVolumeForRequest(getVolumeCapacity(importVolume), project, neighborhood, vpool, vplexURI, nullPoolURI, importVolume.getLabel(), ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME, taskId, _dbClient);
vplexVolume.setAssociatedVolumes(new StringSet());
vplexVolume.getAssociatedVolumes().add(importVolume.getId().toString());
if (createVolume != null) {
vplexVolume.getAssociatedVolumes().add(createVolume.getId().toString());
}
if (consistencyGroup != null) {
// If the volume being converted to a virtual volume has a CG, make the virtual
// volume a member of the CG.
vplexVolume.setConsistencyGroup(consistencyGroup.getId());
consistencyGroup.addRequestedTypes(Arrays.asList(BlockConsistencyGroup.Types.VPLEX.name()));
_dbClient.updateObject(consistencyGroup);
}
vplexVolume.setVirtualPool(vpool.getId());
_dbClient.updateObject(vplexVolume);
// Add a descriptor for the VPLEX_VIRT_VOLUME
VolumeDescriptor desc = new VolumeDescriptor(VolumeDescriptor.Type.VPLEX_VIRT_VOLUME, vplexURI, vplexVolume.getId(), null, null);
descriptors.add(desc);
// Add a descriptor for the import volume too!
desc = new VolumeDescriptor(VolumeDescriptor.Type.VPLEX_IMPORT_VOLUME, importVolume.getStorageController(), importVolume.getId(), importVolume.getPool(), null);
descriptors.add(desc);
// Now send the command to the controller.
try {
s_logger.info("Calling VPlex controller.");
VPlexController controller = getController();
controller.importVolume(vplexURI, descriptors, vplexProject.getId(), vplexProject.getTenantOrg().getURI(), vpool.getId(), importVolume.getLabel() + SRC_BACKEND_VOL_LABEL_SUFFIX, null, Boolean.TRUE, taskId);
} catch (InternalException ex) {
s_logger.error("ControllerException on importVolume", ex);
String errMsg = String.format("ControllerException: %s", ex.getMessage());
Operation statusUpdate = new Operation(Operation.Status.error.name(), errMsg);
_dbClient.updateTaskOpStatus(Volume.class, vplexVolume.getId(), taskId, statusUpdate);
_dbClient.markForDeletion(vplexVolume);
if (createVolume != null) {
_dbClient.markForDeletion(createVolume);
}
throw ex;
}
}
use of com.emc.storageos.volumecontroller.VPlexRecommendation in project coprhd-controller by CoprHD.
the class VPlexBlockServiceApiImpl method makeBackendVolumeDescriptors.
/**
* Takes a list of recommendations and makes the backend volumes and volume descriptors needed to
* provision. When possible (e.g. for SRDF and Block), All recommendations must be in single varray.
* calls the underlying storage routine createVolumesAndDescriptors().
*
* @param recommendations -- a VPlex recommendation list
* @param project - Project containing the Vplex volumes
* @param vplexProject -- private project of the Vplex
* @param rootVpool -- top level Virtual Pool (VpoolUse.ROOT)
* @param varrayCount -- instance count of the varray being provisioned
* @param size -- size of each volume
* @param backendCG -- the CG to be used on the backend Storage Systems
* @param vPoolCapabilities - a VirtualPoolCapabilityValuesWrapper containing provisioning arguments
* @param createTask -- boolean if true creates a task
* @param task -- Overall task id
* @return -- list of VolumeDescriptors to be provisioned
*/
private List<VolumeDescriptor> makeBackendVolumeDescriptors(List<VPlexRecommendation> recommendations, Project project, Project vplexProject, VirtualPool rootVpool, String volumeLabel, int varrayCount, long size, BlockConsistencyGroup backendCG, VirtualPoolCapabilityValuesWrapper vPoolCapabilities, boolean createTask, String task) {
VPlexRecommendation firstRecommendation = recommendations.get(0);
List<VolumeDescriptor> descriptors = new ArrayList<VolumeDescriptor>();
URI varrayId = firstRecommendation.getVirtualArray();
VirtualPool vpool = firstRecommendation.getVirtualPool();
s_logger.info("Generated backend descriptors for {} recommendations varray {}", recommendations.size(), varrayCount);
vPoolCapabilities.put(VirtualPoolCapabilityValuesWrapper.AUTO_TIER__POLICY_NAME, vpool.getAutoTierPolicyName());
if (firstRecommendation.getRecommendation() != null) {
// If these recommendations have lower level recommendation, process them.
// This path is used for the source side of Distributed Volumes and for Local volumes
// where we support building on top of SRDF or the BlockStorage as appropriate.
List<Recommendation> childRecommendations = new ArrayList<Recommendation>();
Recommendation childRecommendation = null;
for (VPlexRecommendation recommendation : recommendations) {
childRecommendation = recommendation.getRecommendation();
childRecommendations.add(childRecommendation);
}
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, varrayId);
String newVolumeLabel = generateVolumeLabel(volumeLabel, varrayCount, 0, 0);
boolean srdfTarget = (childRecommendation instanceof SRDFCopyRecommendation);
boolean srdfSource = (childRecommendation instanceof SRDFRecommendation);
if (srdfTarget) {
newVolumeLabel = newVolumeLabel + "-target";
} else if (srdfSource) {
} else {
// nothing special about these volumes, hide them in the vplex project
// We can't use the vplexProject for SRDF volumes as they determine their RDF group
// grom the project.
project = vplexProject;
}
TaskList taskList = new TaskList();
descriptors = super.createVolumesAndDescriptors(descriptors, newVolumeLabel, size, project, varray, vpool, childRecommendations, taskList, task, vPoolCapabilities);
VolumeDescriptor.Type[] types;
if (srdfTarget) {
types = new VolumeDescriptor.Type[] { VolumeDescriptor.Type.SRDF_TARGET };
} else {
types = new VolumeDescriptor.Type[] { VolumeDescriptor.Type.BLOCK_DATA, VolumeDescriptor.Type.SRDF_SOURCE, VolumeDescriptor.Type.SRDF_EXISTING_SOURCE };
}
descriptors = VolumeDescriptor.filterByType(descriptors, types);
for (VolumeDescriptor descriptor : descriptors) {
Volume volume = _dbClient.queryObject(Volume.class, descriptor.getVolumeURI());
s_logger.info(String.format("Received prepared volume %s (%s, args) type %s", volume.getLabel(), volume.getId(), descriptor.getType().name()));
volume.addInternalFlags(DataObject.Flag.INTERNAL_OBJECT);
configureCGAndReplicationGroup(rootVpool, vPoolCapabilities, backendCG, volume);
_dbClient.updateObject(volume);
}
return descriptors;
}
// Sum resourceCount across all recommendations
int totalResourceCount = 0;
for (VPlexRecommendation recommendation : recommendations) {
totalResourceCount += recommendation.getResourceCount();
}
// The code below is used for the HA side of distributed volumes.
// The HA side does not currently call the lower level schedulers to get descriptors.
s_logger.info("Processing recommendations for Virtual Array {}", varrayId);
int volumeCounter = 0;
for (VPlexRecommendation recommendation : recommendations) {
for (int i = 0; i < recommendation.getResourceCount(); i++) {
vpool = recommendation.getVirtualPool();
URI storageDeviceURI = recommendation.getSourceStorageSystem();
URI storagePoolURI = recommendation.getSourceStoragePool();
String newVolumeLabel = generateVolumeLabel(volumeLabel, varrayCount, volumeCounter, totalResourceCount);
validateVolumeLabel(newVolumeLabel, project);
s_logger.info("Volume label is {}", newVolumeLabel);
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, varrayId);
// This is also handled in StorageScheduler.prepareRecomendedVolumes
long thinVolumePreAllocationSize = 0;
if (null != vpool.getThinVolumePreAllocationPercentage()) {
thinVolumePreAllocationSize = VirtualPoolUtil.getThinVolumePreAllocationSize(vpool.getThinVolumePreAllocationPercentage(), size);
}
Volume volume = prepareVolume(VolumeType.BLOCK_VOLUME, null, size, thinVolumePreAllocationSize, vplexProject, varray, vpool, storageDeviceURI, storagePoolURI, newVolumeLabel, backendCG, vPoolCapabilities);
configureCGAndReplicationGroup(rootVpool, vPoolCapabilities, backendCG, volume);
volume.addInternalFlags(Flag.INTERNAL_OBJECT);
_dbClient.persistObject(volume);
if (createTask) {
_dbClient.createTaskOpStatus(Volume.class, volume.getId(), task, ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME);
}
s_logger.info("Prepared volume {} ({}) ", volume.getLabel(), volume.getId());
VolumeDescriptor descriptor = new VolumeDescriptor(VolumeDescriptor.Type.BLOCK_DATA, storageDeviceURI, volume.getId(), storagePoolURI, backendCG == null ? null : backendCG.getId(), vPoolCapabilities, size);
descriptors.add(descriptor);
volumeCounter++;
}
}
return descriptors;
}
use of com.emc.storageos.volumecontroller.VPlexRecommendation in project coprhd-controller by CoprHD.
the class VPlexBlockServiceApiImpl method createVPlexVolumeDescriptors.
/**
* Create the necessary volume descriptors for Vplex volumes, including the backend
* volume descriptors and the virtual volume descriptors.
*
* @param param
* - the VolumeCreate parameters
* @param project
* -- user's project
* @param vArray
* -- virtual array volumes are created in
* @param vPool
* -- virtual pool (ROOT) used to create the volumes
* @param recommendations
* -- recommendations received from placement
* @param task
* -- a task identifier
* @param vPoolCapabilities
* - VirtualPoolCapabilitiesWrapper
* @param blockConsistencyGroupURI
* - the block consistency group URI
* @param taskList
* - OUTPUT list of tasks created
* @param allVolumes
* - OUTPUT - list of volumes created
* @param createTask
* -- boolean flag indicating to create tasks
* @return
*/
public List<VolumeDescriptor> createVPlexVolumeDescriptors(VolumeCreate param, Project project, final VirtualArray vArray, final VirtualPool vPool, List<Recommendation> recommendations, String task, VirtualPoolCapabilityValuesWrapper vPoolCapabilities, URI blockConsistencyGroupURI, TaskList taskList, List<URI> allVolumes, boolean createTask) {
s_logger.info("Request to create {} VPlex virtual volume(s)", vPoolCapabilities.getResourceCount());
// Determine if we're processing an SRDF copy so we can set appropriate name.
boolean srdfCopy = false;
if (recommendations.get(0).getRecommendation() != null && recommendations.get(0).getRecommendation() instanceof SRDFCopyRecommendation) {
srdfCopy = true;
}
// Sort the recommendations by VirtualArray. There can be up to two
// VirtualArrays, the requested VirtualArray and the HA VirtualArray
// either passed or determined by the placement when HA virtual volumes
// are being created. We also set the VPlex storage system, which
// should be the same for all recommendations.
URI vplexStorageSystemURI = null;
URI[] vplexSystemURIOut = new URI[1];
Map<String, List<VPlexRecommendation>> varrayRecommendationsMap = sortRecommendationsByVarray(recommendations, vplexSystemURIOut);
vplexStorageSystemURI = vplexSystemURIOut[0];
// for the srdf copies, since they are already pre-created.
if (!srdfCopy) {
validateVolumeLabels(param.getName(), project, vPoolCapabilities, varrayRecommendationsMap);
}
// Determine the project to be used for the VPlex's artifacts
StorageSystem vplexStorageSystem = _dbClient.queryObject(StorageSystem.class, vplexStorageSystemURI);
Project vplexProject = getVplexProject(vplexStorageSystem, _dbClient, _tenantsService);
// The volume size.
long size = SizeUtil.translateSize(param.getSize());
// The consistency group or null when not specified.
final BlockConsistencyGroup consistencyGroup = blockConsistencyGroupURI == null ? null : _dbClient.queryObject(BlockConsistencyGroup.class, blockConsistencyGroupURI);
// Find all volumes assigned to the group
boolean cgContainsVolumes = false;
if (consistencyGroup != null) {
final List<Volume> activeCGVolumes = getActiveCGVolumes(consistencyGroup);
cgContainsVolumes = (activeCGVolumes != null && !activeCGVolumes.isEmpty());
}
// If the consistency group is created but does not specify the LOCAL
// type, the CG must be a CG created prior to 2.2 or an ingested CG. In
// this case, we don't want a volume creation to result in backend CGs.
// The only exception is if the CG does not reference any volumes. In
// this case, if the LOCAL type isn't specified, we can create backend
// CGs.
BlockConsistencyGroup backendCG = null;
if (consistencyGroup != null && (!consistencyGroup.created() || !cgContainsVolumes || consistencyGroup.getTypes().contains(Types.LOCAL.toString()))) {
backendCG = consistencyGroup;
}
// Prepare Bourne volumes to represent the backend volumes for the
// recommendations in each VirtualArray.
int varrayCount = 0;
String volumeLabel = param.getName();
List<VolumeDescriptor> descriptors = new ArrayList<VolumeDescriptor>();
URI[][] varrayVolumeURIs = new URI[2][vPoolCapabilities.getResourceCount()];
Iterator<String> varrayIter = varrayRecommendationsMap.keySet().iterator();
while (varrayIter.hasNext()) {
String varrayId = varrayIter.next();
s_logger.info("Processing backend recommendations for Virtual Array {}", varrayId);
List<VPlexRecommendation> vplexRecommendations = varrayRecommendationsMap.get(varrayId);
List<VolumeDescriptor> varrayDescriptors = makeBackendVolumeDescriptors(vplexRecommendations, project, vplexProject, vPool, volumeLabel, varrayCount, size, backendCG, vPoolCapabilities, createTask, task);
descriptors.addAll(varrayDescriptors);
List<URI> varrayURIs = VolumeDescriptor.getVolumeURIs(varrayDescriptors);
allVolumes.addAll(varrayURIs);
for (int i = 0; i < varrayURIs.size(); i++) {
varrayVolumeURIs[varrayCount][i] = varrayURIs.get(i);
}
varrayCount++;
}
// Prepare Bourne volumes to represent the highly available virtual
// volumes and associate the virtual volumes with their associated
// backend volumes.
s_logger.info("Preparing virtual volumes");
List<URI> virtualVolumeURIs = new ArrayList<URI>();
URI nullPoolURI = NullColumnValueGetter.getNullURI();
vPoolCapabilities.put(VirtualPoolCapabilityValuesWrapper.AUTO_TIER__POLICY_NAME, null);
for (int i = 0; i < vPoolCapabilities.getResourceCount(); i++) {
// Compute the volume label based on the label of the underlying volume
String volumeLabelBuilt = null;
Volume associatedVolume = _dbClient.queryObject(Volume.class, varrayVolumeURIs[0][i]);
// Get the virtual volume backing replication group instance name, if available.
String backingReplicationGroupInstance = null;
if (associatedVolume != null) {
volumeLabelBuilt = generateLabelFromAssociatedVolume(volumeLabel, associatedVolume);
backingReplicationGroupInstance = NullColumnValueGetter.isNotNullValue(associatedVolume.getReplicationGroupInstance()) ? associatedVolume.getReplicationGroupInstance() : NullColumnValueGetter.getNullStr();
} else {
volumeLabelBuilt = AbstractBlockServiceApiImpl.generateDefaultVolumeLabel(volumeLabel, i, vPoolCapabilities.getResourceCount());
}
s_logger.info("Volume label is {}", volumeLabelBuilt);
Volume volume = StorageScheduler.getPrecreatedVolume(_dbClient, taskList, volumeLabelBuilt);
boolean volumePrecreated = false;
if (volume != null) {
volumePrecreated = true;
}
long thinVolumePreAllocationSize = 0;
if (null != vPool.getThinVolumePreAllocationPercentage()) {
thinVolumePreAllocationSize = VirtualPoolUtil.getThinVolumePreAllocationSize(vPool.getThinVolumePreAllocationPercentage(), size);
}
volume = prepareVolume(VolumeType.VPLEX_VIRTUAL_VOLUME, volume, size, thinVolumePreAllocationSize, project, vArray, vPool, vplexStorageSystemURI, nullPoolURI, volumeLabelBuilt, consistencyGroup, vPoolCapabilities);
StringSet associatedVolumes = new StringSet();
associatedVolumes.add(varrayVolumeURIs[0][i].toString());
s_logger.info("Associating volume {}", varrayVolumeURIs[0][i].toString());
// associated with the virtual volume.
if (varrayCount > 1) {
associatedVolumes.add(varrayVolumeURIs[1][i].toString());
s_logger.info("Associating volume {}", varrayVolumeURIs[1][i].toString());
}
volume.setAssociatedVolumes(associatedVolumes);
if (null != backingReplicationGroupInstance) {
s_logger.info("Setting virtual volume backingReplicationGroupInstance to {}", backingReplicationGroupInstance);
volume.setBackingReplicationGroupInstance(backingReplicationGroupInstance);
}
_dbClient.updateObject(volume);
URI volumeId = volume.getId();
s_logger.info("Prepared virtual volume {}", volumeId);
virtualVolumeURIs.add(volumeId);
allVolumes.add(volumeId);
if (createTask && !volumePrecreated) {
Operation op = _dbClient.createTaskOpStatus(Volume.class, volume.getId(), task, ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME);
TaskResourceRep volumeTask = toTask(volume, task, op);
taskList.getTaskList().add(volumeTask);
}
VolumeDescriptor descriptor = new VolumeDescriptor(VolumeDescriptor.Type.VPLEX_VIRT_VOLUME, vplexStorageSystemURI, volumeId, null, consistencyGroup == null ? null : consistencyGroup.getId(), vPoolCapabilities, volume.getCapacity());
// Set the compute resource in the descriptor if the volume to be created will be exported
// to a host/cluster after it has been created so that the compute resource name can be
// included in the volume name if the custom volume naming is so configured. Do not set the
// compute resource if the descriptor is for an SRDF target as the target is not exported
// to the compute resource.
URI computeResourceURI = param.getComputeResource();
if ((computeResourceURI != null) && (!srdfCopy)) {
s_logger.info(String.format("Volume %s - will be exported to Host/Cluster: %s", volume.getLabel(), computeResourceURI.toString()));
descriptor.setComputeResource(computeResourceURI);
}
descriptors.add(descriptor);
}
return descriptors;
}
use of com.emc.storageos.volumecontroller.VPlexRecommendation in project coprhd-controller by CoprHD.
the class VPlexBlockServiceApiImpl method validateVolumeLabels.
/**
* Convenient method to generate volume labels and check for duplicate. If there is a duplicate, throw exception
*
* @param baseVolumeLabel
* - volume prefix
* @param project
* - project volume creates within
* @param vArray
* - virtual array where volume is create
* @param vPool
* - volume's vpool
* @param vPoolCapabilities
* - vpool capabilities
* @param varrayRecomendationsMap
* - map of virtual array to its list of recommendation
*/
private void validateVolumeLabels(String baseVolumeLabel, Project project, VirtualPoolCapabilityValuesWrapper vPoolCapabilities, Map<String, List<VPlexRecommendation>> varrayRecomendationsMap) {
int varrayCount = 0;
Iterator<String> varrayIter = varrayRecomendationsMap.keySet().iterator();
while (varrayIter.hasNext()) {
String varrayId = varrayIter.next();
s_logger.info("Processing recommendations for virtual array {}", varrayId);
int volumeCounter = 0;
// Sum the resource counts from all recommendations.
int totalResourceCount = 0;
for (VPlexRecommendation recommendation : varrayRecomendationsMap.get(varrayId)) {
totalResourceCount += recommendation.getResourceCount();
}
Iterator<VPlexRecommendation> recommendationsIter = varrayRecomendationsMap.get(varrayId).iterator();
while (recommendationsIter.hasNext()) {
VPlexRecommendation recommendation = recommendationsIter.next();
URI storagePoolURI = recommendation.getSourceStoragePool();
VirtualPool volumeVpool = recommendation.getVirtualPool();
s_logger.info("Volume virtual pool is {}", volumeVpool.getId().toString());
vPoolCapabilities.put(VirtualPoolCapabilityValuesWrapper.AUTO_TIER__POLICY_NAME, volumeVpool.getAutoTierPolicyName());
s_logger.info("Recommendation is for {} resources in pool {}", recommendation.getResourceCount(), storagePoolURI.toString());
for (int i = 0; i < recommendation.getResourceCount(); i++) {
// Each volume has a unique label based off the passed
// value. Note that the way the storage system creates
// the actual volumes in a multi volume request, the
// names given the Bourne volumes here likely will not
// match the names given by the storage system. If desired,
// we will need to update the actual volumes after they
// are created to match the names given here. Currently,
// this is not implemented.
String volumeLabel = generateVolumeLabel(baseVolumeLabel, varrayCount, volumeCounter, totalResourceCount);
// throw exception of duplicate found
validateVolumeLabel(volumeLabel, project);
s_logger.info("Volume label is {}", volumeLabel);
volumeCounter++;
}
}
varrayCount++;
}
}
use of com.emc.storageos.volumecontroller.VPlexRecommendation in project coprhd-controller by CoprHD.
the class PlacementTests method testPlacementVPlexXIO.
/**
* Simple VPLEX local XIO block placement.
*/
@Test
public void testPlacementVPlexXIO() {
String[] vplexFE = { "FE:FE:FE:FE:FE:FE:FE:00", "FE:FE:FE:FE:FE:FE:FE:01" };
String[] vplexBE = { "BE:BE:BE:BE:BE:BE:BE:00", "BE:BE:BE:BE:BE:BE:BE:01" };
String[] xio1FE = { "50:FE:FE:FE:FE:FE:FE:00", "50:FE:FE:FE:FE:FE:FE:01" };
String[] xio2FE = { "51:FE:FE:FE:FE:FE:FE:00", "51:FE:FE:FE:FE:FE:FE:01" };
String[] xio3FE = { "52:FE:FE:FE:FE:FE:FE:00", "52:FE:FE:FE:FE:FE:FE:01" };
// Create a Network
Network networkFE = PlacementTestUtils.createNetwork(_dbClient, vplexFE, "VSANFE", "FC+BROCADE+FE", null);
Network networkBE = PlacementTestUtils.createNetwork(_dbClient, vplexBE, "VSANBE", "FC+BROCADE+BE", null);
// Create a Virtual Array
VirtualArray varray = PlacementTestUtils.createVirtualArray(_dbClient, "varray1");
// Create 3 storage systems for xio
StorageSystem storageSystem1 = PlacementTestUtils.createStorageSystem(_dbClient, "xtremio", "xtremio1");
StorageSystem storageSystem2 = PlacementTestUtils.createStorageSystem(_dbClient, "xtremio", "xtremio2");
StorageSystem storageSystem3 = PlacementTestUtils.createStorageSystem(_dbClient, "xtremio", "xtremio3");
// Create two front-end storage ports xio1
List<StoragePort> xio1Ports = new ArrayList<StoragePort>();
for (int i = 0; i < xio1FE.length; i++) {
xio1Ports.add(PlacementTestUtils.createStoragePort(_dbClient, storageSystem1, networkBE, xio1FE[i], varray, StoragePort.PortType.frontend.name(), "portGroupXio1" + i, "C0+FC0" + i));
}
// Create two front-end storage ports xio2
List<StoragePort> xio2Ports = new ArrayList<StoragePort>();
for (int i = 0; i < xio2FE.length; i++) {
xio2Ports.add(PlacementTestUtils.createStoragePort(_dbClient, storageSystem2, networkBE, xio2FE[i], varray, StoragePort.PortType.frontend.name(), "portGroupXio2" + i, "D0+FC0" + i));
}
// Create two front-end storage ports xio3
List<StoragePort> xio3Ports = new ArrayList<StoragePort>();
for (int i = 0; i < xio3FE.length; i++) {
xio3Ports.add(PlacementTestUtils.createStoragePort(_dbClient, storageSystem3, networkBE, xio3FE[i], varray, StoragePort.PortType.frontend.name(), "portGroupXio3" + i, "E0+FC0" + i));
}
// Create a VPLEX storage system
StorageSystem vplexStorageSystem = PlacementTestUtils.createStorageSystem(_dbClient, "vplex", "vplex1");
// Create two front-end storage ports VPLEX
List<StoragePort> fePorts = new ArrayList<StoragePort>();
for (int i = 0; i < vplexFE.length; i++) {
fePorts.add(PlacementTestUtils.createStoragePort(_dbClient, vplexStorageSystem, networkFE, vplexFE[i], varray, StoragePort.PortType.frontend.name(), "portGroupFE" + i, "A0+FC0" + i));
}
// Create two back-end storage ports VPLEX
List<StoragePort> bePorts = new ArrayList<StoragePort>();
for (int i = 0; i < vplexBE.length; i++) {
bePorts.add(PlacementTestUtils.createStoragePort(_dbClient, vplexStorageSystem, networkBE, vplexBE[i], varray, StoragePort.PortType.backend.name(), "portGroupBE" + i, "B0+FC0" + i));
}
// Create a storage pool on xio1
StoragePool pool1 = PlacementTestUtils.createStoragePool(_dbClient, varray, storageSystem1, "pool1", "Pool1", Long.valueOf(1024 * 1024 * 10), Long.valueOf(1024 * 1024 * 10), 300, 300, StoragePool.SupportedResourceTypes.THIN_ONLY.toString());
// Create a storage pool on xio2
StoragePool pool2 = PlacementTestUtils.createStoragePool(_dbClient, varray, storageSystem2, "pool2", "Pool2", Long.valueOf(1024 * 1024 * 1), Long.valueOf(1024 * 1024 * 1), 100, 100, StoragePool.SupportedResourceTypes.THIN_ONLY.toString());
// Create a storage pool on xio3
StoragePool pool3 = PlacementTestUtils.createStoragePool(_dbClient, varray, storageSystem3, "pool3", "Pool3", Long.valueOf(1024 * 10), Long.valueOf(1024 * 1024 * 10), 300, 300, StoragePool.SupportedResourceTypes.THIN_ONLY.toString());
// Create a virtual pool
VirtualPool vpool = new VirtualPool();
vpool.setId(URI.create("vpool"));
vpool.setLabel("vpool");
vpool.setSupportedProvisioningType(VirtualPool.ProvisioningType.Thin.name());
vpool.setDriveType(SupportedDriveTypes.FC.name());
StringSet matchedPools = new StringSet();
matchedPools.add(pool1.getId().toString());
matchedPools.add(pool2.getId().toString());
matchedPools.add(pool3.getId().toString());
vpool.setMatchedStoragePools(matchedPools);
vpool.setUseMatchedPools(true);
_dbClient.createObject(vpool);
// Create a VPLEX virtual pool
VirtualPool vplexVpool = new VirtualPool();
vplexVpool.setId(URI.create("vplexVpool"));
vplexVpool.setLabel("vplexVpool");
vplexVpool.setSupportedProvisioningType(VirtualPool.ProvisioningType.Thin.name());
vplexVpool.setHighAvailability(VirtualPool.HighAvailabilityType.vplex_local.name());
//
vplexVpool.setDriveType(SupportedDriveTypes.FC.name());
matchedPools = new StringSet();
matchedPools.add(pool1.getId().toString());
matchedPools.add(pool2.getId().toString());
matchedPools.add(pool3.getId().toString());
vplexVpool.setMatchedStoragePools(matchedPools);
vplexVpool.setUseMatchedPools(true);
_dbClient.createObject(vplexVpool);
// Create a project object
Project project = new Project();
project.setId(URI.create("project"));
project.setLabel("project");
_dbClient.createObject(project);
VirtualPoolCapabilityValuesWrapper capabilities = PlacementTestUtils.createCapabilities("2GB", 1, null);
// Run single volume placement: Run 10 times to make sure pool2 nRever comes up.
for (int i = 0; i < 10; i++) {
List recommendations = PlacementTestUtils.invokePlacement(_dbClient, _coordinator, varray, project, vplexVpool, capabilities);
assertNotNull(recommendations);
assertTrue(!recommendations.isEmpty());
assertNotNull(recommendations.get(0));
VPlexRecommendation rec = (VPlexRecommendation) recommendations.get(0);
assertNotNull(rec.getSourceStoragePool());
assertNotNull(rec.getSourceStorageSystem());
assertNotNull(rec.getVPlexStorageSystem());
assertTrue(("xtremio3".equals(rec.getSourceStorageSystem().toString())) || ("xtremio1".equals(rec.getSourceStorageSystem().toString())));
assertTrue("vplex1".equals(rec.getVPlexStorageSystem().toString()));
assertTrue(("pool3".equals(rec.getSourceStoragePool().toString())) || ("pool1".equals(rec.getSourceStoragePool().toString())));
_log.info("Recommendation " + i + ": " + recommendations.size() + ", Pool Chosen: " + rec.getSourceStoragePool().toString());
_log.info(rec.toString());
}
}
Aggregations