use of com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation in project coprhd-controller by CoprHD.
the class VnxExportOperations method deleteExportMask.
/*
* (non-Javadoc)
*
* @see
* com.emc.storageos.volumecontroller.impl.smis.ExportMaskOperations#deleteExportMask(com.emc.storageos.db.client.
* model.StorageSystem, java.net.URI, java.util.List, java.util.List, java.util.List,
* com.emc.storageos.volumecontroller.TaskCompleter)
*
* IDs
* Note: No need to verify storage ports.
*/
@Override
public void deleteExportMask(StorageSystem storage, URI exportMaskURI, List<URI> volumeURIList, List<URI> targetURIList, List<Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException {
_log.info("{} deleteExportMask START...", storage.getSerialNumber());
try {
_log.info("Export mask id: {}", exportMaskURI);
if (volumeURIList != null) {
_log.info("deleteExportMask: volumes: {}", Joiner.on(',').join(volumeURIList));
}
if (targetURIList != null) {
_log.info("deleteExportMask: assignments: {}", Joiner.on(',').join(targetURIList));
}
if (initiatorList != null) {
_log.info("deleteExportMask: initiators: {}", Joiner.on(',').join(initiatorList));
}
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
String nativeId = exportMask.getNativeId();
if (Strings.isNullOrEmpty(nativeId)) {
_log.warn(String.format("ExportMask %s does not have a nativeID, " + "indicating that this export may not have been created " + "successfully. Marking the delete operation ready.", exportMaskURI.toString()));
// Perform post-mask-delete cleanup steps
ExportUtils.cleanupAssociatedMaskResources(_dbClient, exportMask);
taskCompleter.ready(_dbClient);
return;
}
boolean isRollback = WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId());
if (isRollback) {
boolean maskCreated = false;
// Get the context from the task completer as this is a rollback.
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
if (context != null && context.getOperations() != null) {
ListIterator li = context.getOperations().listIterator(context.getOperations().size());
while (li.hasPrevious()) {
ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
_log.info("Handling deleteExportMask as a result of rollback");
if (operation != null && VnxExportOperationContext.OPERATION_CREATE_STORAGE_GROUP.equals(operation.getOperation())) {
URI createdExportMaskURI = (URI) operation.getArgs().get(0);
if (exportMask.getId().equals(createdExportMaskURI)) {
maskCreated = true;
break;
}
}
}
}
if (!maskCreated) {
_log.warn(String.format("This is a case of rollback but the ExportMask %s was not found in the export context, " + "indicating that this export may not have been created successfully. Marking the delete operation ready.", exportMaskURI.toString()));
// Perform post-mask-delete cleanup steps
ExportUtils.cleanupAssociatedMaskResources(_dbClient, exportMask);
taskCompleter.ready(_dbClient);
return;
}
}
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(storage);
ctx.setExportMask(exportMask);
ctx.setBlockObjects(volumeURIList, _dbClient);
ctx.setInitiators(initiatorList);
ctx.setAllowExceptions(!isRollback);
validator.exportMaskDelete(ctx).validate();
CIMObjectPath protocolController = _cimPath.getClarProtocolControllers(storage, nativeId)[0];
CIMInstance instance = _helper.checkExists(storage, protocolController, true, true);
if (instance != null) {
_helper.setProtocolControllerNativeId(exportMaskURI, null);
ExportMask mask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
if (mask != null) {
List<URI> initiatorURIs = new ArrayList<URI>();
if (mask.getInitiators() != null) {
for (String initUriStr : mask.getInitiators()) {
initiatorURIs.add(URI.create(initUriStr));
}
}
List<Initiator> initiators = _dbClient.queryObject(Initiator.class, initiatorURIs);
deleteStorageHWIDs(storage, initiators);
deleteOrShrinkStorageGroup(storage, exportMaskURI, null, null);
}
}
// Perform post-mask-delete cleanup steps
ExportUtils.cleanupAssociatedMaskResources(_dbClient, exportMask);
taskCompleter.ready(_dbClient);
} catch (Exception e) {
_log.error("Unexpected error: deleteExportMask failed.", e);
ServiceError error = DeviceControllerErrors.smis.methodFailed("deleteExportMask", e.getMessage());
taskCompleter.error(_dbClient, error);
}
_log.info("{} deleteExportMask END...", storage.getSerialNumber());
}
use of com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation in project coprhd-controller by CoprHD.
the class VnxExportOperations method removeVolumes.
/*
* (non-Javadoc)
*
* @see
* com.emc.storageos.volumecontroller.impl.smis.ExportMaskOperations#removeVolume(com.emc.storageos.db.client.model.
* StorageSystem, java.net.URI, java.util.List, com.emc.storageos.volumecontroller.TaskCompleter)
*
*/
@Override
public void removeVolumes(StorageSystem storage, URI exportMaskURI, List<URI> volumeURIList, List<Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException {
_log.info("{} removeVolumes START...", storage.getSerialNumber());
try {
_log.info("removeVolumes: Export mask id: {}", exportMaskURI);
_log.info("removeVolumes: volumes: {}", Joiner.on(',').join(volumeURIList));
if (initiatorList != null) {
_log.info("removeVolumes: impacted initiators: {}", Joiner.on(",").join(initiatorList));
}
boolean isRollback = WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId());
if (isRollback) {
_log.info("Handling removeVolumes as a result of rollback");
List<URI> addedVolumes = new ArrayList<URI>();
// Get the context from the task completer as this is a rollback.
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
if (context != null && context.getOperations() != null) {
ListIterator li = context.getOperations().listIterator(context.getOperations().size());
while (li.hasPrevious()) {
ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
if (operation != null && VnxExportOperationContext.OPERATION_ADD_VOLUMES_TO_STORAGE_GROUP.equals(operation.getOperation())) {
addedVolumes = (List<URI>) operation.getArgs().get(0);
_log.info("Removing volumes {} as part of rollback", Joiner.on(',').join(addedVolumes));
}
}
}
volumeURIList = addedVolumes;
if (volumeURIList == null || volumeURIList.isEmpty()) {
_log.info("There was no context found for add volumes. So there is nothing to rollback.");
taskCompleter.ready(_dbClient);
return;
}
}
if (null == volumeURIList || volumeURIList.isEmpty()) {
taskCompleter.ready(_dbClient);
_log.warn("{} removeVolumes invoked with zero volumes, resulting in no-op....", storage.getSerialNumber());
return;
}
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(storage);
ctx.setExportMask(exportMask);
ctx.setInitiators(initiatorList);
ctx.setAllowExceptions(!isRollback);
validator.removeVolumes(ctx).validate();
String[] volumeNames = null;
volumeNames = _helper.getBlockObjectAlternateNames(volumeURIList);
/**
* This extra condition makes sure ViPR do not pass null as volume name while invoking HidePaths.
* If we pass null into HidePaths call, SMI will remove the entire storage group and that will give DU.
*/
if (volumeNames == null || volumeNames.length == 0) {
_log.error("Volume's {} alternate name can not be null", volumeURIList);
ServiceError error = DeviceControllerException.errors.removeVolumeFromMaskFailed(volumeURIList.toString());
taskCompleter.error(_dbClient, error);
} else {
deleteOrShrinkStorageGroup(storage, exportMaskURI, volumeURIList, null);
taskCompleter.ready(_dbClient);
}
} catch (Exception e) {
_log.error("Unexpected error: removeVolumes failed.", e);
ServiceError error = DeviceControllerErrors.smis.methodFailed("removeVolumes", e.getMessage());
taskCompleter.error(_dbClient, error);
}
_log.info("{} removeVolumes END...", storage.getSerialNumber());
}
use of com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation in project coprhd-controller by CoprHD.
the class VNXeExportOperations method removeVolumes.
@Override
public void removeVolumes(StorageSystem storage, URI exportMaskUri, List<URI> volumes, List<Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException {
_logger.info("{} removeVolumes: START...", storage.getSerialNumber());
try {
_logger.info("removeVolumes: Export mask id: {}", exportMaskUri);
_logger.info("removeVolumes: volumes: {}", Joiner.on(',').join(volumes));
if (initiatorList != null) {
_logger.info("removeVolumes: impacted initiators: {}", Joiner.on(",").join(initiatorList));
}
boolean isRollback = WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId());
if (isRollback) {
List<URI> addedVolumes = new ArrayList<URI>();
// Get the context from the task completer, in case this is a rollback.
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
if (context != null && context.getOperations() != null) {
_logger.info("Handling removeVolumes as a result of rollback");
ListIterator li = context.getOperations().listIterator(context.getOperations().size());
while (li.hasPrevious()) {
ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
if (operation != null & VNXeExportOperationContext.OPERATION_ADD_VOLUMES_TO_HOST_EXPORT.equals(operation.getOperation())) {
addedVolumes = (List<URI>) operation.getArgs().get(0);
_logger.info("Removing volumes {} as part of rollback", Joiner.on(',').join(addedVolumes));
}
}
}
volumes = addedVolumes;
if (volumes == null || volumes.isEmpty()) {
_logger.info("There was no context found for add volumes. So there is nothing to rollback.");
taskCompleter.ready(_dbClient);
return;
}
}
if (volumes == null || volumes.isEmpty()) {
taskCompleter.ready(_dbClient);
_logger.warn("{} removeVolumes invoked with zero volumes, resulting in no-op....", storage.getSerialNumber());
return;
}
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskUri);
if (exportMask == null || exportMask.getInactive()) {
throw new DeviceControllerException("Invalid ExportMask URI: " + exportMaskUri);
}
List<Initiator> initiators = ExportUtils.getExportMaskInitiators(exportMask, _dbClient);
VNXeApiClient apiClient = getVnxeClient(storage);
String hostId = getHostIdFromInitiators(initiators, apiClient);
if (hostId != null) {
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(storage);
ctx.setExportMask(exportMask);
ctx.setInitiators(initiatorList);
// Allow exceptions to be thrown when not rolling back
ctx.setAllowExceptions(!isRollback);
AbstractVNXeValidator removeVolumesValidator = (AbstractVNXeValidator) validator.removeVolumes(ctx);
removeVolumesValidator.setHostId(hostId);
removeVolumesValidator.validate();
}
String opId = taskCompleter.getOpId();
Set<String> processedCGs = new HashSet<String>();
StringMap volsMap = exportMask.getVolumes();
for (URI volUri : volumes) {
if (hostId != null && volsMap != null && !volsMap.isEmpty() && volsMap.keySet().contains(volUri.toString())) {
BlockObject blockObject = BlockObject.fetch(_dbClient, volUri);
// COP-25254 this method could be called when delete vplex volume created from snapshot. in this case
// the volume passed in is an internal volume, representing the snapshot. we need to find the snapshot
// with the same nativeGUID, then unexport the snapshot.
BlockObject snapshot = findSnapshotByInternalVolume(blockObject);
if (snapshot != null) {
blockObject = snapshot;
exportMask.removeVolume(volUri);
volUri = blockObject.getId();
}
String cgName = VNXeUtils.getBlockObjectCGName(blockObject, _dbClient);
if (cgName != null && !processedCGs.contains(cgName)) {
processedCGs.add(cgName);
VNXeUtils.getCGLock(workflowService, storage, cgName, opId);
}
String nativeId = blockObject.getNativeId();
if (URIUtil.isType(volUri, Volume.class)) {
apiClient.unexportLun(hostId, nativeId);
} else if (URIUtil.isType(volUri, BlockSnapshot.class)) {
apiClient.unexportSnap(hostId, nativeId);
setSnapWWN(apiClient, blockObject, nativeId);
}
}
// update the exportMask object
exportMask.removeVolume(volUri);
}
_dbClient.updateObject(exportMask);
taskCompleter.ready(_dbClient);
} catch (Exception e) {
_logger.error("Unexpected error: removeVolumes failed.", e);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("remove volumes failed", e.getMessage());
taskCompleter.error(_dbClient, error);
}
_logger.info("{} removeVolumes END...", storage.getSerialNumber());
}
use of com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation in project coprhd-controller by CoprHD.
the class XtremIOExportOperations method removeInitiators.
@Override
public void removeInitiators(StorageSystem storage, URI exportMaskURI, List<URI> volumeURIList, List<Initiator> initiators, List<URI> targets, TaskCompleter taskCompleter) throws DeviceControllerException {
_log.info("{} removeInitiators START...", storage.getSerialNumber());
boolean isRollback = WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId());
if (isRollback) {
_log.info("Handling removeInitiators as a result of rollback");
List<Initiator> addedInitiators = new ArrayList<Initiator>();
// Get the context from the task completer.
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
if (context != null && context.getOperations() != null) {
ListIterator li = context.getOperations().listIterator(context.getOperations().size());
while (li.hasPrevious()) {
ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
if (operation != null && XtremIOExportOperationContext.OPERATION_ADD_INITIATORS_TO_INITIATOR_GROUP.equals(operation.getOperation())) {
addedInitiators = (List<Initiator>) operation.getArgs().get(0);
_log.info("Removing initiators {} as part of rollback", Joiner.on(',').join(addedInitiators));
}
}
}
// Update the initiators in the task completer such that we update the export mask/group correctly
for (Initiator initiator : initiators) {
if (addedInitiators == null || !addedInitiators.contains(initiator)) {
((ExportMaskRemoveInitiatorCompleter) taskCompleter).removeInitiator(initiator.getId());
}
}
initiators = addedInitiators;
if (initiators == null || initiators.isEmpty()) {
_log.info("There was no context found for add initiator. So there is nothing to rollback.");
taskCompleter.ready(dbClient);
return;
}
}
ExportMask exportMask = dbClient.queryObject(ExportMask.class, exportMaskURI);
if (exportMask == null || exportMask.getInactive()) {
throw new DeviceControllerException("Invalid ExportMask URI: " + exportMaskURI);
}
XtremIOClient client = null;
// if host Name is not available in at least one of the initiator, then set it to
// Default_IG;
List<String> failedIGs = new ArrayList<String>();
ArrayListMultimap<String, Initiator> groupInitiatorsByIG = ArrayListMultimap.create();
try {
String hostName = null;
String clusterName = null;
client = XtremIOProvUtils.getXtremIOClient(dbClient, storage, xtremioRestClientFactory);
String xioClusterName = client.getClusterDetails(storage.getSerialNumber()).getName();
Iterator<Initiator> iniItr = initiators.iterator();
while (iniItr.hasNext()) {
Initiator initiator = iniItr.next();
String igName = null;
if (null != initiator.getHostName()) {
// initiators already grouped by Host
hostName = initiator.getHostName();
clusterName = initiator.getClusterName();
}
igName = XtremIOProvUtils.getIGNameForInitiator(initiator, storage.getSerialNumber(), client, xioClusterName);
if (igName != null && !igName.isEmpty()) {
groupInitiatorsByIG.put(igName, initiator);
} else {
// initiator not found in Array, remove from DB
exportMask.removeFromExistingInitiators(initiator);
exportMask.removeFromUserCreatedInitiators(initiator);
iniItr.remove();
}
}
// We need to look at all related initiators from the affected EM. We can use this list
// to then find all related volumes across all EMs. This will allow us to properly
// perform our validations.
List<Initiator> relatedInitiators = new ArrayList<Initiator>();
if (exportMask.getInitiators() != null && !exportMask.getInitiators().isEmpty()) {
Collection<URI> relatedInitiatorURIs = Collections2.transform(exportMask.getInitiators(), CommonTransformerFunctions.FCTN_STRING_TO_URI);
relatedInitiators.addAll(dbClient.queryObject(Initiator.class, relatedInitiatorURIs));
} else {
relatedInitiators.addAll(initiators);
}
Set<URI> allRelatedVolumes = new HashSet<URI>();
allRelatedVolumes.addAll(findAllRelatedExportMaskVolumesForInitiator(relatedInitiators, exportMask.getStorageDevice()));
_log.info("removeInitiators: Export mask id: {}", exportMaskURI);
if (!CollectionUtils.isEmpty(allRelatedVolumes)) {
_log.info("removeInitiators: volumes : {}", Joiner.on(',').join(allRelatedVolumes));
}
_log.info("removeInitiators: initiators : {}", Joiner.on(',').join(initiators));
_log.info("removeInitiators: targets : {}", Joiner.on(',').join(targets));
_log.info("List of IGs found {} with size : {}", Joiner.on(",").join(groupInitiatorsByIG.asMap().entrySet()), groupInitiatorsByIG.size());
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(storage);
ctx.setExportMask(exportMask);
ctx.setBlockObjects(allRelatedVolumes, dbClient);
ctx.setAllowExceptions(!isRollback);
XtremIOExportMaskVolumesValidator volumeValidator = (XtremIOExportMaskVolumesValidator) validator.removeInitiators(ctx);
volumeValidator.setIgNames(groupInitiatorsByIG.keySet());
volumeValidator.validate();
// lun map
for (Initiator initiator : initiators) {
try {
client.deleteInitiator(initiator.getMappedInitiatorName(storage.getSerialNumber()), xioClusterName);
exportMask.removeFromExistingInitiators(initiator);
exportMask.removeFromUserCreatedInitiators(initiator);
} catch (Exception e) {
failedIGs.add(initiator.getLabel().concat(XtremIOConstants.DASH).concat(e.getMessage()));
_log.warn("Removal of Initiator {} failed", initiator.getLabel(), e);
}
}
dbClient.updateObject(exportMask);
if (!failedIGs.isEmpty()) {
String errMsg = "Export Operations failed deleting these initiators: ".concat(Joiner.on(", ").join(failedIGs));
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 ex) {
_log.error("Problem in removeInitiators: ", ex);
ServiceError serviceError = DeviceControllerErrors.xtremio.operationFailed("removeInitiators", ex.getMessage());
taskCompleter.error(dbClient, serviceError);
return;
}
_log.info("{} removeInitiators END...", storage.getSerialNumber());
}
use of com.emc.storageos.volumecontroller.impl.utils.ExportOperationContext.ExportOperationContextOperation in project coprhd-controller by CoprHD.
the class XtremIOExportOperations method removeVolumes.
@Override
public void removeVolumes(StorageSystem storage, URI exportMaskURI, List<URI> volumeUris, List<Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException {
_log.info("{} removeVolumes START...", storage.getSerialNumber());
try {
_log.info("removeVolumes: Export mask id: {}", exportMaskURI);
_log.info("removeVolumes: volumes: {}", Joiner.on(',').join(volumeUris));
if (initiatorList != null) {
_log.info("removeVolumes: impacted initiators: {}", Joiner.on(",").join(initiatorList));
}
boolean isRollback = WorkflowService.getInstance().isStepInRollbackState(taskCompleter.getOpId());
if (isRollback) {
_log.info("Handling removeVolumes as a result of rollback");
List<URI> addedVolumes = new ArrayList<URI>();
// Get the context from the task completer.
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(taskCompleter.getOpId());
if (context != null && context.getOperations() != null) {
ListIterator li = context.getOperations().listIterator(context.getOperations().size());
while (li.hasPrevious()) {
ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
if (operation != null && XtremIOExportOperationContext.OPERATION_ADD_VOLUMES_TO_INITIATOR_GROUP.equals(operation.getOperation())) {
addedVolumes = (List<URI>) operation.getArgs().get(0);
_log.info("Removing volumes {} as part of rollback", Joiner.on(',').join(addedVolumes));
}
}
}
volumeUris = addedVolumes;
if (volumeUris == null || volumeUris.isEmpty()) {
_log.info("There was no context found for add volumes. So there is nothing to rollback.");
taskCompleter.ready(dbClient);
return;
}
}
ExportMask exportMask = dbClient.queryObject(ExportMask.class, exportMaskURI);
if (exportMask == null || exportMask.getInactive()) {
throw new DeviceControllerException("Invalid ExportMask URI: " + exportMaskURI);
}
runLunMapDeletionAlgorithm(storage, exportMask, volumeUris, initiatorList, taskCompleter);
} catch (final Exception ex) {
_log.error("Problem in removeVolumes: ", ex);
ServiceError serviceError = DeviceControllerErrors.xtremio.operationFailed("removeVolumes", ex.getMessage());
taskCompleter.error(dbClient, serviceError);
}
_log.info("{} removeVolumes END...", storage.getSerialNumber());
}
Aggregations