use of com.emc.storageos.xtremio.restapi.XtremIOClient in project coprhd-controller by CoprHD.
the class XtremIOStorageDevice method doDeleteVolumes.
@Override
public void doDeleteVolumes(StorageSystem storageSystem, String opId, List<Volume> volumes, TaskCompleter completer) throws DeviceControllerException {
Map<String, String> failedVolumes = new HashMap<String, String>();
try {
XtremIOClient client = XtremIOProvUtils.getXtremIOClient(dbClient, storageSystem, xtremioRestClientFactory);
String clusterName = client.getClusterDetails(storageSystem.getSerialNumber()).getName();
URI projectUri = volumes.get(0).getProject().getURI();
URI poolUri = volumes.get(0).getPool();
for (Volume volume : volumes) {
String volumeName = volume.getDeviceLabel() != null ? volume.getDeviceLabel() : volume.getLabel();
try {
if (null != XtremIOProvUtils.isVolumeAvailableInArray(client, volumeName, clusterName)) {
// Remove the volume from the consistency group
if (client.isVersion2() && !NullColumnValueGetter.isNullURI(volume.getConsistencyGroup()) && NullColumnValueGetter.isNotNullValue(volume.getReplicationGroupInstance())) {
BlockConsistencyGroup consistencyGroupObj = dbClient.queryObject(BlockConsistencyGroup.class, volume.getConsistencyGroup());
String cgName = volume.getReplicationGroupInstance();
XtremIOConsistencyGroup xioCG = XtremIOProvUtils.isCGAvailableInArray(client, cgName, clusterName);
// Check if CG has volumes
if (null != xioCG && null != xioCG.getVolList() && !xioCG.getVolList().isEmpty()) {
boolean isVolRemovedFromCG = false;
// Verify if the volumes is part of the CG or not. If Exists always remove from CG
if (checkIfVolumeExistsInCG(xioCG.getVolList(), volumeName)) {
_log.info("Removing volume {} from consistency group {}", volumeName, cgName);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_038);
client.removeVolumeFromConsistencyGroup(volumeName, cgName, clusterName);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_039);
isVolRemovedFromCG = true;
} else {
_log.info("Volume {} doesn't exist on CG {}", volumeName, cgName);
}
// Perform remove CG only when we removed the volume from CG.
if (isVolRemovedFromCG) {
// Query the CG to reflect the latest data on array.
xioCG = XtremIOProvUtils.isCGAvailableInArray(client, cgName, clusterName);
if (null == xioCG.getVolList() || xioCG.getVolList().isEmpty()) {
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_038);
client.removeConsistencyGroup(cgName, clusterName);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_039);
_log.info("CG is empty on array. Remove array association from the CG");
consistencyGroupObj.removeSystemConsistencyGroup(storageSystem.getId().toString(), cgName);
// clear the LOCAL type
StringSet types = consistencyGroupObj.getTypes();
if (types != null) {
types.remove(Types.LOCAL.name());
consistencyGroupObj.setTypes(types);
}
dbClient.updateObject(consistencyGroupObj);
}
}
}
}
// backing volume).
if (volume.checkForRp() || RPHelper.isAssociatedToAnyRpVplexTypes(volume, dbClient)) {
int attempt = 0;
while (attempt++ <= MAX_RP_RETRIES) {
try {
_log.info(String.format("Deleting RecoverPoint volume %s (attempt %s/%s)", volumeName, attempt, MAX_RP_RETRIES));
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_040);
client.deleteVolume(volumeName, clusterName);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_041);
break;
} catch (XtremIOApiException e) {
// volume removed from the consistency group.
if (attempt != MAX_RP_RETRIES && e.getMessage().contains("cannot_remove_volume_that_is_in_consistency_group")) {
_log.warn(String.format("Encountered exception attempting delete RP volume %s. Waiting %s milliseconds before trying again. Error: %s", volumeName, RP_WAIT_FOR_RETRY, e.getMessage()));
try {
Thread.sleep(RP_WAIT_FOR_RETRY);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
}
} else {
// re-throw the exception if this is not the one we care about
throw e;
}
}
}
} else {
_log.info("Deleting the volume {}", volumeName);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_040);
client.deleteVolume(volumeName, clusterName);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_041);
}
}
} catch (Exception e) {
_log.error("Error during volume {} delete.", volumeName, e);
failedVolumes.put(volumeName, ControllerUtils.getMessage(e));
}
}
if (!failedVolumes.isEmpty()) {
StringBuffer errMsg = new StringBuffer("Failed to delete volumes: ");
for (String failedVolume : failedVolumes.keySet()) {
errMsg.append(failedVolume).append(":").append(failedVolumes.get(failedVolume));
}
ServiceError error = DeviceControllerErrors.xtremio.deleteVolumeFailure(errMsg.toString());
completer.error(dbClient, error);
} else {
String volumeFolderName = getVolumeFolderName(projectUri, storageSystem);
XtremIOProvUtils.cleanupVolumeFoldersIfNeeded(client, clusterName, volumeFolderName, storageSystem);
completer.ready(dbClient);
}
// update StoragePool capacity for pools changed
StoragePool pool = dbClient.queryObject(StoragePool.class, poolUri);
try {
_log.info("Updating Pool {} Capacity", pool.getNativeGuid());
XtremIOProvUtils.updateStoragePoolCapacity(client, dbClient, pool);
} catch (Exception e) {
_log.warn("Error while updating pool capacity for pool {} ", poolUri, e);
}
} catch (Exception e) {
_log.error("Error while deleting volumes", e);
ServiceError error = DeviceControllerErrors.xtremio.deleteVolumeFailure(e.getMessage());
completer.error(dbClient, error);
}
}
use of com.emc.storageos.xtremio.restapi.XtremIOClient 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()));
// 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.XtremIOClient in project coprhd-controller by CoprHD.
the class XtremIOStorageDevice method doRestoreFromSnapshot.
@Override
public void doRestoreFromSnapshot(StorageSystem storage, URI volume, URI snapshot, TaskCompleter taskCompleter) throws DeviceControllerException {
_log.info("SnapShot Restore..... Started");
List<BlockSnapshot> snapshots = dbClient.queryObject(BlockSnapshot.class, Arrays.asList(snapshot));
XtremIOClient client = XtremIOProvUtils.getXtremIOClient(dbClient, storage, xtremioRestClientFactory);
if (client.isVersion2() && ControllerUtils.checkSnapshotsInConsistencyGroup(snapshots, dbClient, taskCompleter)) {
snapshotOperations.restoreGroupSnapshots(storage, volume, snapshot, taskCompleter);
} else {
snapshotOperations.restoreSingleVolumeSnapshot(storage, volume, snapshot, taskCompleter);
}
_log.info("SnapShot Restore..... End");
}
use of com.emc.storageos.xtremio.restapi.XtremIOClient in project coprhd-controller by CoprHD.
the class XtremIOExportOperations method findHLUsForInitiators.
@Override
public Set<Integer> findHLUsForInitiators(StorageSystem storage, List<String> initiatorNames, boolean mustHaveAllPorts) {
Set<Integer> usedHLUs = new HashSet<Integer>();
try {
XtremIOClient client = XtremIOProvUtils.getXtremIOClient(dbClient, storage, xtremioRestClientFactory);
Set<String> igNames = new HashSet<>();
String xioClusterName = client.getClusterDetails(storage.getSerialNumber()).getName();
for (String initiatorName : initiatorNames) {
initiatorName = Initiator.toPortNetworkId(initiatorName);
URIQueryResultList initiatorResult = new URIQueryResultList();
dbClient.queryByConstraint(AlternateIdConstraint.Factory.getInitiatorPortInitiatorConstraint(initiatorName), initiatorResult);
if (initiatorResult.iterator().hasNext()) {
Initiator initiator = dbClient.queryObject(Initiator.class, initiatorResult.iterator().next());
String igName = XtremIOProvUtils.getIGNameForInitiator(initiator, storage.getSerialNumber(), client, xioClusterName);
if (igName != null && !igName.isEmpty()) {
igNames.add(igName);
}
}
}
// get the lun maps for IGs
for (String igName : igNames) {
List<XtremIOObjectInfo> lunMapLinks = XtremIOProvUtils.getInitiatorGroupLunMaps(igName, xioClusterName, client);
List<XtremIOLunMap> lunMaps = client.getXtremIOLunMapsForLinks(lunMapLinks, xioClusterName);
for (XtremIOLunMap lunMap : lunMaps) {
_log.info("Looking at lun map {}; IG name: {}, Volume: {}, HLU: {}", lunMap.getMappingInfo().get(2), lunMap.getIgName(), lunMap.getVolumeName(), lunMap.getLun());
usedHLUs.add(Integer.valueOf(lunMap.getLun()));
}
}
_log.info(String.format("HLUs found for Initiators { %s }: %s", Joiner.on(',').join(initiatorNames), usedHLUs));
} catch (Exception e) {
String errMsg = "Encountered an error when attempting to query used HLUs for initiators: " + e.getMessage();
_log.error(errMsg, e);
throw XtremIOApiException.exceptions.hluRetrievalFailed(errMsg, e);
}
return usedHLUs;
}
use of com.emc.storageos.xtremio.restapi.XtremIOClient in project coprhd-controller by CoprHD.
the class XtremIOExportOperations method runLunMapDeletionAlgorithm.
private void runLunMapDeletionAlgorithm(StorageSystem storage, ExportMask exportMask, List<URI> volumes, List<Initiator> initiators, TaskCompleter taskCompleter) throws DeviceControllerException {
// find LunMap associated with Volume
// Then find initiatorGroup associated with this lun map
// find initiators associated with IG, if the given list is of initiators is same, then run
// removeLunMap
XtremIOClient client = null;
// Default_IG;
try {
String hostName = null;
String clusterName = null;
client = XtremIOProvUtils.getXtremIOClient(dbClient, storage, xtremioRestClientFactory);
String xioClusterName = client.getClusterDetails(storage.getSerialNumber()).getName();
for (Initiator initiator : initiators) {
if (null != initiator.getHostName()) {
// initiators already grouped by Host
hostName = initiator.getHostName();
clusterName = initiator.getClusterName();
break;
}
}
ArrayListMultimap<String, Initiator> groupInitiatorsByIG = XtremIOProvUtils.mapInitiatorToInitiatorGroup(storage.getSerialNumber(), initiators, null, xioClusterName, client);
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(storage);
ctx.setExportMask(exportMask);
ctx.setInitiators(initiators);
ctx.setAllowExceptions(!WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId()));
XtremIOExportMaskInitiatorsValidator initiatorsValidator = (XtremIOExportMaskInitiatorsValidator) validator.removeVolumes(ctx);
initiatorsValidator.setInitiatorToIGMap(groupInitiatorsByIG);
initiatorsValidator.validate();
Set<String> igNames = groupInitiatorsByIG.keySet();
List<String> failedVolumes = new ArrayList<String>();
for (URI volumeUri : volumes) {
BlockObject blockObj = BlockObject.fetch(dbClient, volumeUri);
_log.info("Block Obj {} , wwn {}", blockObj.getId(), blockObj.getWWN());
XtremIOVolume xtremIOVolume = null;
if (URIUtil.isType(volumeUri, Volume.class)) {
xtremIOVolume = XtremIOProvUtils.isVolumeAvailableInArray(client, blockObj.getDeviceLabel(), xioClusterName);
// returned value is null, check the snapshots.
if (xtremIOVolume == null) {
xtremIOVolume = XtremIOProvUtils.isSnapAvailableInArray(client, blockObj.getDeviceLabel(), xioClusterName);
}
} else {
xtremIOVolume = XtremIOProvUtils.isSnapAvailableInArray(client, blockObj.getDeviceLabel(), xioClusterName);
}
if (null != xtremIOVolume) {
// I need lun map id and igName
// if iGName is available in the above group, then remove lunMap
_log.info("Volume Details {}", xtremIOVolume.toString());
_log.info("Volume lunMap details {}", xtremIOVolume.getLunMaps().toString());
Set<String> lunMaps = new HashSet<String>();
String volId = xtremIOVolume.getVolInfo().get(2);
if (xtremIOVolume.getLunMaps().isEmpty()) {
// handle scenarios where volumes gets unexported already
_log.info("Volume {} doesn't have any existing export available on Array, unexported already.", xtremIOVolume.toString());
exportMask.removeFromUserCreatedVolumes(blockObj);
exportMask.removeVolume(blockObj.getId());
continue;
}
for (List<Object> lunMapEntries : xtremIOVolume.getLunMaps()) {
@SuppressWarnings("unchecked") List<Object> igDetails = (List<Object>) lunMapEntries.get(0);
String igName = (String) igDetails.get(1);
// Ig details is actually transforming to A double by deofault, even though
// its modeled as List<String>
// hence this logic
Double IgIdDouble = (Double) igDetails.get(2);
String igId = String.valueOf(IgIdDouble.intValue());
_log.info("IG Name: {} Id: {} found in Lun Map", igName, igId);
if (!igNames.contains(igName)) {
_log.info("Volume is associated with IG {} which is not in the removal list requested, ignoring..", igName);
continue;
}
@SuppressWarnings("unchecked") List<Object> tgtGroupDetails = (List<Object>) lunMapEntries.get(1);
Double tgIdDouble = (Double) tgtGroupDetails.get(2);
String tgtid = String.valueOf(tgIdDouble.intValue());
String lunMapId = volId.concat(XtremIOConstants.UNDERSCORE).concat(igId).concat(XtremIOConstants.UNDERSCORE).concat(tgtid);
_log.info("LunMap Id {} Found associated with Volume {}", lunMapId, blockObj.getDeviceLabel());
lunMaps.add(lunMapId);
}
// there will be only one lun map always
for (String lunMap : lunMaps) {
try {
client.deleteLunMap(lunMap, xioClusterName);
} catch (Exception e) {
failedVolumes.add(volumeUri.toString().concat(XtremIOConstants.DASH).concat(e.getMessage()));
_log.warn("Deletion of Lun Map {} failed}", lunMap, e);
}
}
} else {
exportMask.removeFromUserCreatedVolumes(blockObj);
exportMask.removeVolume(blockObj.getId());
}
}
dbClient.updateObject(exportMask);
if (!failedVolumes.isEmpty()) {
String errMsg = "Export Operations failed for these volumes: ".concat(Joiner.on(", ").join(failedVolumes));
ServiceError serviceError = DeviceControllerException.errors.jobFailedMsg(errMsg, null);
taskCompleter.error(dbClient, serviceError);
return;
}
// Clean IGs if empty
deleteInitiatorGroup(groupInitiatorsByIG, client, xioClusterName);
// delete IG Folder as well if IGs are empty
deleteInitiatorGroupFolder(client, xioClusterName, clusterName, hostName, storage);
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