use of com.emc.storageos.xtremio.restapi.model.response.XtremIOVolume in project coprhd-controller by CoprHD.
the class XtremIOSnapshotOperations method createV1Snapshot.
private XtremIOVolume createV1Snapshot(XtremIOClient client, StorageSystem storage, BlockSnapshot snap, String snapLabel, Boolean readOnly, TaskCompleter taskCompleter) throws Exception {
Volume parentVolume = dbClient.queryObject(Volume.class, snap.getParent().getURI());
URI projectUri = snap.getProject().getURI();
String clusterName = client.getClusterDetails(storage.getSerialNumber()).getName();
String snapFolderName = XtremIOProvUtils.createFoldersForVolumeAndSnaps(client, getVolumeFolderName(projectUri, storage)).get(XtremIOConstants.SNAPSHOT_KEY);
String snapshotType = readOnly ? XtremIOConstants.XTREMIO_READ_ONLY_TYPE : XtremIOConstants.XTREMIO_REGULAR_TYPE;
client.createVolumeSnapshot(parentVolume.getDeviceLabel(), snapLabel, snapFolderName, snapshotType, clusterName);
XtremIOVolume createdSnap = client.getSnapShotDetails(snap.getLabel(), clusterName);
return createdSnap;
}
use of com.emc.storageos.xtremio.restapi.model.response.XtremIOVolume in project coprhd-controller by CoprHD.
the class XtremIOSnapshotOperations method createV2Snapshot.
private XtremIOVolume createV2Snapshot(XtremIOClient client, StorageSystem storage, String xioClusterName, BlockSnapshot snap, String snapLabel, Boolean readOnly, TaskCompleter taskCompleter) throws Exception {
Volume parentVolume = dbClient.queryObject(Volume.class, snap.getParent().getURI());
URI projectUri = snap.getProject().getURI();
String clusterName = client.getClusterDetails(storage.getSerialNumber()).getName();
String snapTagName = XtremIOProvUtils.createTagsForVolumeAndSnaps(client, getVolumeFolderName(projectUri, storage), clusterName).get(XtremIOConstants.SNAPSHOT_KEY);
String snapshotType = readOnly ? XtremIOConstants.XTREMIO_READ_ONLY_TYPE : XtremIOConstants.XTREMIO_REGULAR_TYPE;
client.createVolumeSnapshot(parentVolume.getDeviceLabel(), snapLabel, snapTagName, snapshotType, clusterName);
// Get the snapset details
XtremIOConsistencyGroup snapset = client.getSnapshotSetDetails(snapLabel, xioClusterName);
List<Object> snapDetails = snapset.getVolList().get(0);
XtremIOVolume xioSnap = client.getSnapShotDetails(snapDetails.get(1).toString(), xioClusterName);
// tag the created the snap
client.tagObject(snapTagName, XTREMIO_ENTITY_TYPE.SnapshotSet.name(), snapLabel, clusterName);
return xioSnap;
}
use of com.emc.storageos.xtremio.restapi.model.response.XtremIOVolume in project coprhd-controller by CoprHD.
the class XtremIOStorageDevice method doCreateVolumes.
@Override
public void doCreateVolumes(StorageSystem storage, StoragePool storagePool, String opId, List<Volume> volumes, VirtualPoolCapabilityValuesWrapper capabilities, TaskCompleter taskCompleter) throws DeviceControllerException {
Map<String, String> failedVolumes = new HashMap<String, String>();
XtremIOClient client = null;
try {
client = XtremIOProvUtils.getXtremIOClient(dbClient, storage, xtremioRestClientFactory);
BlockConsistencyGroup cgObj = null;
boolean isCG = false;
Volume vol = volumes.get(0);
// If the volume is regular volume and in CG
if (!NullColumnValueGetter.isNullURI(vol.getConsistencyGroup())) {
cgObj = dbClient.queryObject(BlockConsistencyGroup.class, vol.getConsistencyGroup());
if (cgObj != null && cgObj.created(storage.getId())) {
// Only set this flag to true if the CG reference is valid
// and it is already created on the storage system.
isCG = true;
// RP back-end volumes DO NOT have personality flag set. All RP volumes will satisfy checkForRP
// Find out out if this is a RP volume that is not a back-end volume to a RP+VPLEX volume.
boolean excludeRPNotBackendVolumes = vol.checkForRp() && (NullColumnValueGetter.isNotNullValue(vol.getPersonality()));
// Only XIO volumes that are back-end volumes to RP+VPLEX volumes will be in an array CG if arrayConsistency is chosen.
if (excludeRPNotBackendVolumes || (Volume.checkForVplexBackEndVolume(dbClient, vol) && NullColumnValueGetter.isNullValue(vol.getReplicationGroupInstance()))) {
isCG = false;
}
}
}
// find the project this volume belongs to.
URI projectUri = volumes.get(0).getProject().getURI();
String clusterName = client.getClusterDetails(storage.getSerialNumber()).getName();
// For version 1 APIs, find the volume folder corresponding to this project
// if not found ,create new folder, else reuse this folder and add volume to it.
// For version 2 APIs, find tags corresponding to this project
// if not found ,create new tag, else reuse this tag and tag the volume.
boolean isVersion2 = client.isVersion2();
String volumesFolderName = "";
if (isVersion2) {
volumesFolderName = XtremIOProvUtils.createTagsForVolumeAndSnaps(client, getVolumeFolderName(projectUri, storage), clusterName).get(XtremIOConstants.VOLUME_KEY);
} else {
volumesFolderName = XtremIOProvUtils.createFoldersForVolumeAndSnaps(client, getVolumeFolderName(projectUri, storage)).get(XtremIOConstants.VOLUME_KEY);
}
Random randomNumber = new Random();
for (Volume volume : volumes) {
try {
XtremIOVolume createdVolume = null;
String userDefinedLabel = _nameGenerator.generate("", volume.getLabel(), "", '_', XtremIOConstants.XTREMIO_MAX_VOL_LENGTH);
volume.setLabel(userDefinedLabel);
while (null != XtremIOProvUtils.isVolumeAvailableInArray(client, volume.getLabel(), clusterName)) {
_log.info("Volume with name {} already exists", volume.getLabel());
String tempLabel = userDefinedLabel.concat("_").concat(String.valueOf(randomNumber.nextInt(1000)));
volume.setLabel(tempLabel);
_log.info("Retrying volume creation with label {}", tempLabel);
}
// If the volume is a recoverpoint protected volume, the capacity has already been
// adjusted in the RPBlockServiceApiImpl class therefore there is no need to adjust it here.
// If it is not, add 1 MB extra to make up the missing bytes due to divide by 1024 (Usecase: XIO on HA side of VPLEX Distributed)
// If there are no additional bytes requested, don't add that extra 1 MB.
int amountToAdjustCapacity = 1;
if (Volume.checkForProtectedVplexBackendVolume(dbClient, volume) || volume.checkForRp() || ((volume.getCapacity().doubleValue() / (1024 * 1024)) % 1) == 0) {
amountToAdjustCapacity = 0;
}
Long capacityInMB = new Long(volume.getCapacity() / (1024 * 1024) + amountToAdjustCapacity);
String capacityInMBStr = String.valueOf(capacityInMB).concat("m");
_log.info("Sending create volume request with name: {}, size: {}", volume.getLabel(), capacityInMBStr);
client.createVolume(volume.getLabel(), capacityInMBStr, volumesFolderName, clusterName);
createdVolume = client.getVolumeDetails(volume.getLabel(), clusterName);
_log.info("Created volume details {}", createdVolume.toString());
volume.setNativeId(createdVolume.getVolInfo().get(0));
volume.setWWN(createdVolume.getVolInfo().get(0));
volume.setDeviceLabel(volume.getLabel());
volume.setAccessState(Volume.VolumeAccessState.READWRITE.name());
// If the REST API wwn field is populated, then use it.
if (!createdVolume.getWwn().isEmpty()) {
volume.setWWN(createdVolume.getWwn());
}
String nativeGuid = NativeGUIDGenerator.generateNativeGuid(dbClient, volume);
volume.setNativeGuid(nativeGuid);
volume.setProvisionedCapacity(Long.parseLong(createdVolume.getAllocatedCapacity()) * 1024);
volume.setAllocatedCapacity(Long.parseLong(createdVolume.getAllocatedCapacity()) * 1024);
dbClient.updateObject(volume);
// For version 2, tag the created volume
if (isVersion2) {
client.tagObject(volumesFolderName, XTREMIO_ENTITY_TYPE.Volume.name(), volume.getLabel(), clusterName);
// Do not add RP+VPlex journal or target backing volumes to consistency groups.
// This causes issues with local array snapshots of RP+VPlex volumes.
String cgName = volume.getReplicationGroupInstance();
if (isCG && !RPHelper.isAssociatedToRpVplexType(volume, dbClient, PersonalityTypes.METADATA, PersonalityTypes.TARGET) && NullColumnValueGetter.isNotNullValue(cgName)) {
client.addVolumeToConsistencyGroup(volume.getLabel(), cgName, clusterName);
}
}
} catch (Exception e) {
failedVolumes.put(volume.getLabel(), ControllerUtils.getMessage(e));
_log.error("Error during volume create.", e);
}
}
if (!failedVolumes.isEmpty()) {
StringBuffer errMsg = new StringBuffer("Failed to create volumes: ");
for (String failedVolume : failedVolumes.keySet()) {
errMsg.append(failedVolume).append(":").append(failedVolumes.get(failedVolume));
}
ServiceError error = DeviceControllerErrors.xtremio.createVolumeFailure(errMsg.toString());
taskCompleter.error(dbClient, error);
} else {
taskCompleter.ready(dbClient);
}
} catch (Exception e) {
_log.error("Error while creating volumes", e);
ServiceError error = DeviceControllerErrors.xtremio.createVolumeFailure(e.getMessage());
taskCompleter.error(dbClient, error);
}
// update StoragePool capacity
try {
XtremIOProvUtils.updateStoragePoolCapacity(client, dbClient, storagePool);
} catch (Exception e) {
_log.warn("Error while updating pool capacity", e);
}
}
use of com.emc.storageos.xtremio.restapi.model.response.XtremIOVolume in project coprhd-controller by CoprHD.
the class XtremIOUnManagedVolumeDiscoverer method discoverVolumeSnaps.
private StringSet discoverVolumeSnaps(StorageSystem system, List<List<Object>> snapDetails, String parentGUID, StringSet parentMatchedVPools, XtremIOClient xtremIOClient, String xioClusterName, DbClient dbClient, Map<String, List<UnManagedVolume>> igUnmanagedVolumesMap, Map<String, StringSet> igKnownVolumesMap) throws Exception {
StringSet snaps = new StringSet();
Object snapNameToProcess;
for (List<Object> snapDetail : snapDetails) {
// This can't be null
snapNameToProcess = snapDetail.get(1);
if ((null == snapNameToProcess || snapNameToProcess.toString().length() == 0) || null == snapDetail.get(2)) {
log.warn("Skipping snapshot as it is null for volume {}", parentGUID);
continue;
}
// If this name is a trigger/match for RP automated snapshots, ignore it as well
String snapName = (String) snapNameToProcess;
if ((snapName.contains(RP_SNAPSHOT_CRITERIA1) || snapName.contains(RP_SNAPSHOT_CRITERIA2)) && snapName.contains(RP_SNAPSHOT_CRITERIA3)) {
log.warn("Skipping snapshot {} because it is internal to RP for volume {}", snapName, parentGUID);
continue;
}
XtremIOVolume snap = xtremIOClient.getSnapShotDetails(snapNameToProcess.toString(), xioClusterName);
UnManagedVolume unManagedVolume = null;
boolean isExported = !snap.getLunMaps().isEmpty();
String managedSnapNativeGuid = NativeGUIDGenerator.generateNativeGuidForVolumeOrBlockSnapShot(system.getNativeGuid(), snap.getVolInfo().get(0));
BlockSnapshot viprSnap = DiscoveryUtils.checkBlockSnapshotExistsInDB(dbClient, managedSnapNativeGuid);
if (null != viprSnap) {
log.info("Skipping snapshot {} as it is already managed by ViPR", managedSnapNativeGuid);
// export masks.
if (isExported) {
populateKnownVolsMap(snap, viprSnap, igKnownVolumesMap);
}
snaps.add(managedSnapNativeGuid);
continue;
}
String unManagedVolumeNatvieGuid = NativeGUIDGenerator.generateNativeGuidForPreExistingVolume(system.getNativeGuid(), snap.getVolInfo().get(0));
unManagedVolume = DiscoveryUtils.checkUnManagedVolumeExistsInDB(dbClient, unManagedVolumeNatvieGuid);
unManagedVolume = createUnManagedVolume(unManagedVolume, unManagedVolumeNatvieGuid, snap, igUnmanagedVolumesMap, system, null, dbClient);
populateSnapInfo(unManagedVolume, snap, parentGUID, parentMatchedVPools);
snaps.add(unManagedVolumeNatvieGuid);
allCurrentUnManagedVolumeUris.add(unManagedVolume.getId());
// is associated with a cg, if it is process the snap same as any unmanaged volume
if (snap.getSnapSetList() != null && !snap.getSnapSetList().isEmpty()) {
Object snapSetNameToProcess = null;
if (snap.getSnapSetList().size() > 1) {
// snaps that belong to multiple snap sets are not supported in ViPR
log.warn("Skipping snapshot {} as it belongs to multiple snapSets and this is not supported", snap.getVolInfo().get(0));
// add all the snap sets that this volume belongs to to the list that are unsupported for ingestion
for (List<Object> snapSet : snap.getSnapSetList()) {
snapSetNameToProcess = snapSet.get(1);
log.warn("Skipping SnapSet {} as it contains volumes belonging to multiple CGs and this is not supported", snapSetNameToProcess.toString());
}
} else {
for (List<Object> snapSet : snap.getSnapSetList()) {
snapSetNameToProcess = snapSet.get(1);
XtremIOConsistencyGroup snapSetDetails = xtremIOClient.getSnapshotSetDetails(snapSetNameToProcess.toString(), xioClusterName);
if (snapSetDetails != null && snapSetDetails.getCgName() != null) {
log.info("Snapshot {} belongs to consistency group {} on the array", snapSetNameToProcess.toString(), snapSetDetails.getCgName());
addObjectToUnManagedConsistencyGroup(xtremIOClient, unManagedVolume, snapSetDetails.getCgName(), system, xioClusterName, dbClient);
} else {
log.info("Snapshot {} does not belong to a consistency group.", snapSetNameToProcess.toString());
}
}
}
}
}
return snaps;
}
use of com.emc.storageos.xtremio.restapi.model.response.XtremIOVolume in project coprhd-controller by CoprHD.
the class XtremIOExportOperations method runLunMapCreationAlgorithm.
private void runLunMapCreationAlgorithm(StorageSystem storage, ExportMask exportMask, VolumeURIHLU[] volumeURIHLUs, List<Initiator> initiators, List<URI> targets, XtremIOClient client, String xioClusterName, ArrayListMultimap<String, Initiator> initiatorToIGMap, List<Initiator> initiatorsToBeCreated, TaskCompleter taskCompleter) throws DeviceControllerException {
Set<String> igNames = null;
List<URI> mappedVolumes = new ArrayList<URI>();
// Default_IG;
try {
String hostName = null;
String clusterName = null;
_log.info("Finding re-usable IGs available on Array {}", storage.getNativeGuid());
List<URI> initiatorIds = new ArrayList<>();
for (Initiator initiator : initiators) {
initiatorIds.add(initiator.getId());
if (null != initiator.getHostName()) {
// initiators already grouped by Host
hostName = initiator.getHostName();
clusterName = initiator.getClusterName();
break;
}
}
// since we're reusing existing IGs, volumes might get exposed to other initiators in
// IG.
// for initiators without label, create IGs and add them to a host folder by name
// initiator.getHost() in cases ,where initiator.getLabel() is not present, we try
// creating IG, if fails
// then we consider that it's already created
igNames = new HashSet<String>();
igNames.addAll(initiatorToIGMap.keySet());
if (initiatorsToBeCreated != null && !initiatorsToBeCreated.isEmpty()) {
// create new initiator and add to IG; add IG to IG folder
addInitiatorToInitiatorGroup(client, xioClusterName, clusterName, hostName, initiatorsToBeCreated, igNames, exportMask, storage, taskCompleter);
List<URI> volumeURIs = new ArrayList<URI>();
for (VolumeURIHLU volURIHLU : volumeURIHLUs) {
volumeURIs.add(volURIHLU.getVolumeURI());
}
XtremIOExportMaskVolumesValidator volumeValidator = (XtremIOExportMaskVolumesValidator) validator.addInitiators(storage, exportMask, volumeURIs);
volumeValidator.setIgNames(initiatorToIGMap.keySet());
volumeValidator.validate();
}
if (igNames.isEmpty()) {
ServiceError serviceError = DeviceControllerException.errors.xtremioInitiatorGroupsNotDetected(storage.getNativeGuid());
taskCompleter.error(dbClient, serviceError);
return;
}
// Small block of declarations/initializations to assist with vblock boot volume check in below block.
Set<String> vblockConflictIgNames = new HashSet<>();
Map<URI, Integer> volumeMap = new HashMap<>();
for (VolumeURIHLU volumeIdHlu : volumeURIHLUs) {
volumeMap.put(volumeIdHlu.getVolumeURI(), Integer.valueOf(volumeIdHlu.getHLU()));
}
// Check for volumes which are already mapped to the IG. We do not need to create lun map for them.
ArrayListMultimap<String, String> volumesToIGMap = ArrayListMultimap.create();
for (String igName : igNames) {
List<XtremIOVolume> igVols = XtremIOProvUtils.getInitiatorGroupVolumes(igName, xioClusterName, client);
for (XtremIOVolume igVolume : igVols) {
volumesToIGMap.put(igName, igVolume.getVolInfo().get(1));
/**
* COP-28674: During Vblock Boot volume export, if existing masking views are found then check for existing volumes
* If found throw exception. This condition is valid only for boot volume vblock export.
*/
if (ExportMaskUtils.isVblockHost(initiatorIds, dbClient) && ExportMaskUtils.isBootVolume(dbClient, volumeMap)) {
_log.error(String.format("VBlock boot volume Export: found existing IG (%s) with volumes in it on %s.", igName, storage.getNativeGuid()));
vblockConflictIgNames.add(igName);
}
}
}
// error for the customer.
if (!vblockConflictIgNames.isEmpty()) {
ServiceError serviceError = DeviceControllerException.errors.existingMaskFoundDuringBootVolumeExportXio(Joiner.on(',').join(vblockConflictIgNames), hostName);
taskCompleter.error(dbClient, serviceError);
return;
}
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_052);
// create Lun Maps
for (VolumeURIHLU volURIHLU : volumeURIHLUs) {
BlockObject blockObj = BlockObject.fetch(dbClient, volURIHLU.getVolumeURI());
String hluValue = volURIHLU.getHLU().equalsIgnoreCase(ExportGroup.LUN_UNASSIGNED_STR) ? "-1" : volURIHLU.getHLU();
_log.info("HLU value {}", hluValue);
for (String igName : igNames) {
List<String> igVols = volumesToIGMap.get(igName);
if (igVols != null && !igVols.contains(blockObj.getDeviceLabel())) {
// Create lun map
_log.info("Creating Lun Map for Volume {} using IG {}", blockObj.getDeviceLabel(), igName);
client.createLunMap(blockObj.getDeviceLabel(), igName, hluValue, xioClusterName);
mappedVolumes.add(blockObj.getId());
}
}
}
// post process created lun maps
for (VolumeURIHLU volURIHLU : volumeURIHLUs) {
BlockObject blockObj = BlockObject.fetch(dbClient, volURIHLU.getVolumeURI());
Integer hluNumberFound = 0;
// get volume/snap details again and populate wwn and hlu
XtremIOVolume xtremIOVolume = null;
String deviceName = blockObj.getDeviceLabel();
xtremIOVolume = XtremIOProvUtils.isVolumeAvailableInArray(client, deviceName, xioClusterName);
// COP-19828: If we can't find a volume by the given name, try to find a snap with the given name
if (xtremIOVolume == null) {
xtremIOVolume = XtremIOProvUtils.isSnapAvailableInArray(client, deviceName, xioClusterName);
}
if (xtremIOVolume != null) {
_log.info("Volume lunMap details Found {}", xtremIOVolume.getLunMaps().toString());
if (!xtremIOVolume.getWwn().isEmpty()) {
blockObj.setWWN(xtremIOVolume.getWwn());
blockObj.setNativeId(xtremIOVolume.getWwn());
dbClient.updateObject(blockObj);
}
for (String igName : igNames) {
for (List<Object> lunMapEntries : xtremIOVolume.getLunMaps()) {
@SuppressWarnings("unchecked") List<Object> // This can't be null
igDetails = (List<Object>) lunMapEntries.get(0);
if (null == igDetails.get(1) || null == lunMapEntries.get(2)) {
_log.warn("IG Name is null in returned lun map response for volume {}", xtremIOVolume.toString());
continue;
}
String igNameToProcess = (String) igDetails.get(1);
_log.info("IG Name: {} found in Lun Map", igNameToProcess);
if (!igName.equalsIgnoreCase(igNameToProcess)) {
_log.info("Volume is associated with IG {} which is not in the expected list requested, ignoring..", igNameToProcess);
continue;
}
Double hluNumber = (Double) lunMapEntries.get(2);
_log.info("Found HLU {} for volume {}", hluNumber, blockObj.getDeviceLabel());
// for each IG involved, the same volume is visible thro different HLUs.
// TODO we might need a list of HLU for each Volume URI
hluNumberFound = hluNumber.intValue();
exportMask.addVolume(blockObj.getId(), hluNumberFound);
exportMask.addToUserCreatedVolumes(blockObj);
}
}
}
}
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_053);
ExportOperationContext.insertContextOperation(taskCompleter, XtremIOExportOperationContext.OPERATION_ADD_VOLUMES_TO_INITIATOR_GROUP, mappedVolumes);
_log.info("Updated Volumes with HLUs {} after successful export", Joiner.on(",").join(exportMask.getVolumes().entrySet()));
dbClient.updateObject(exportMask);
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_003);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_002);
taskCompleter.ready(dbClient);
} catch (Exception e) {
_log.error(String.format("Export Operations failed - maskName: %s", exportMask.getId().toString()), e);
ServiceError serviceError = DeviceControllerException.errors.jobFailed(e);
taskCompleter.error(dbClient, serviceError);
}
}
Aggregations