use of com.emc.storageos.vplex.api.clientdata.PortInfo in project coprhd-controller by CoprHD.
the class VPlexDeviceController method storageViewRemoveInitiators.
/**
* Workflow step to remove an initiator from a single Storage View as given by the ExportMask URI.
* Note there is a dependence on ExportMask name equaling the Storage View name.
* Note that arguments must match storageViewRemoveInitiatorsMethod above (except stepId).
*
* @param vplexURI
* -- URI of Vplex Storage System.
* @param exportGroupURI
* -- URI of Export Group.
* @param exportMaskURI
* -- URI of one ExportMask. Call only processes indicaated mask.
* @param initiatorURIs
* -- URIs of Initiators to be removed.
* @param targetURIs
* -- optional targets to be removed from the Storage View.
* If non null, a list of URIs for VPlex front-end ports that will be removed from Storage View.
* @param taskCompleter
* -- the task completer, used to find the rollback context,
* which will be non-null in the case of rollback
* @param rollbackContextKey
* context key for rollback processing
* @param stepId
* -- Workflow step id.
* @throws WorkflowException
*/
public void storageViewRemoveInitiators(URI vplexURI, URI exportGroupURI, URI exportMaskURI, List<URI> initiatorURIs, List<URI> targetURIs, TaskCompleter taskCompleter, String rollbackContextKey, String stepId) throws WorkflowException {
ExportMaskRemoveInitiatorCompleter completer = null;
try {
WorkflowStepCompleter.stepExecuting(stepId);
List<URI> initiatorIdsToProcess = new ArrayList<>(initiatorURIs);
completer = new ExportMaskRemoveInitiatorCompleter(exportGroupURI, exportMaskURI, initiatorURIs, stepId);
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplexURI, client, _dbClient);
Map<String, String> targetPortMap = VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName);
VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
_log.info("Refreshing ExportMask {}", exportMask.getMaskName());
VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, targetPortMap, _networkDeviceController);
// get the context from the task completer, in case this is a rollback.
if (taskCompleter != null && rollbackContextKey != null) {
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(rollbackContextKey);
if (context != null) {
// a non-null context means this step is running as part of a rollback.
List<URI> addedInitiators = new ArrayList<>();
if (context.getOperations() != null) {
_log.info("Handling removeInitiators as a result of rollback");
ListIterator<ExportOperationContextOperation> li = context.getOperations().listIterator(context.getOperations().size());
while (li.hasPrevious()) {
ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
if (operation != null && VplexExportOperationContext.OPERATION_ADD_INITIATORS_TO_STORAGE_VIEW.equals(operation.getOperation())) {
addedInitiators = (List<URI>) 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 (URI initiator : initiatorIdsToProcess) {
if (addedInitiators == null || !addedInitiators.contains(initiator)) {
completer.removeInitiator(initiator);
}
}
if (addedInitiators == null || addedInitiators.isEmpty()) {
_log.info("There was no context found for add initiator. So there is nothing to rollback.");
completer.ready(_dbClient);
return;
}
// Change the list of initiators to process to the list
// that successfully were added during addInitiators.
initiatorIdsToProcess.clear();
initiatorIdsToProcess.addAll(addedInitiators);
}
}
// validate the remove initiator operation against the export mask volumes
List<URI> volumeURIList = (exportMask.getUserAddedVolumes() != null) ? URIUtil.toURIList(exportMask.getUserAddedVolumes().values()) : new ArrayList<URI>();
if (volumeURIList.isEmpty()) {
_log.warn("volume URI list for validating remove initiators is empty...");
}
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(vplex);
ctx.setExportMask(exportMask);
ctx.setBlockObjects(volumeURIList, _dbClient);
ctx.setAllowExceptions(!WorkflowService.getInstance().isStepInRollbackState(stepId));
validator.removeInitiators(ctx).validate();
// Invoke artificial failure to simulate invalid storageview name on vplex
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_060);
// removing all storage ports but leaving the existing initiators and volumes.
if (!exportMask.hasAnyExistingInitiators() && !exportMask.hasAnyExistingVolumes()) {
if (targetURIs != null && targetURIs.isEmpty() == false) {
List<PortInfo> targetPortInfos = new ArrayList<PortInfo>();
List<URI> targetsAddedToStorageView = new ArrayList<URI>();
for (URI target : targetURIs) {
// Do not try to remove a port twice.
if (!exportMask.getStoragePorts().contains(target.toString())) {
continue;
}
// Build the PortInfo structure for the port to be added
StoragePort port = getDataObject(StoragePort.class, target, _dbClient);
PortInfo pi = new PortInfo(port.getPortNetworkId().toUpperCase().replaceAll(":", ""), null, port.getPortName(), null);
targetPortInfos.add(pi);
targetsAddedToStorageView.add(target);
}
if (!targetPortInfos.isEmpty()) {
// Remove the targets from the VPLEX
client.removeTargetsFromStorageView(exportMask.getMaskName(), targetPortInfos);
}
}
}
// Update the initiators in the ExportMask.
List<PortInfo> initiatorPortInfo = new ArrayList<PortInfo>();
for (URI initiatorURI : initiatorIdsToProcess) {
Initiator initiator = getDataObject(Initiator.class, initiatorURI, _dbClient);
// We don't want to remove existing initiator, unless this is a rollback step
if (exportMask.hasExistingInitiator(initiator) && !WorkflowService.getInstance().isStepInRollbackState(stepId)) {
continue;
}
PortInfo portInfo = new PortInfo(initiator.getInitiatorPort().toUpperCase().replaceAll(":", ""), initiator.getInitiatorNode().toUpperCase().replaceAll(":", ""), initiator.getLabel(), getVPlexInitiatorType(initiator));
initiatorPortInfo.add(portInfo);
}
// Remove the initiators if there aren't any existing volumes, unless this is a rollback step or validation is disabled.
if (!initiatorPortInfo.isEmpty() && (!exportMask.hasAnyExistingVolumes() || !validatorConfig.isValidationEnabled() || WorkflowService.getInstance().isStepInRollbackState(stepId))) {
String lockName = null;
boolean lockAcquired = false;
try {
ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
String clusterId = ConnectivityUtil.getVplexClusterForVarray(exportGroup.getVirtualArray(), vplexURI, _dbClient);
lockName = _vplexApiLockManager.getLockName(vplexURI, clusterId);
lockAcquired = _vplexApiLockManager.acquireLock(lockName, LockTimeoutValue.get(LockType.VPLEX_API_LIB));
if (!lockAcquired) {
throw VPlexApiException.exceptions.couldNotObtainConcurrencyLock(vplex.getLabel());
}
// Remove the targets from the VPLEX
// Test mechanism to invoke a failure. No-op on production systems.
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_016);
client.removeInitiatorsFromStorageView(exportMask.getMaskName(), vplexClusterName, initiatorPortInfo);
} finally {
if (lockAcquired) {
_vplexApiLockManager.releaseLock(lockName);
}
}
}
completer.ready(_dbClient);
} catch (VPlexApiException vae) {
_log.error("Exception removing initiator from Storage View: " + vae.getMessage(), vae);
failStep(completer, stepId, vae);
} catch (Exception ex) {
_log.error("Exception removing initiator from Storage View: " + ex.getMessage(), ex);
String opName = ResourceOperationTypeEnum.DELETE_STORAGE_VIEW_INITIATOR.getName();
ServiceError serviceError = VPlexApiException.errors.storageViewRemoveInitiatorFailed(opName, ex);
failStep(completer, stepId, serviceError);
}
}
use of com.emc.storageos.vplex.api.clientdata.PortInfo in project coprhd-controller by CoprHD.
the class VPlexDeviceController method storageViewRemoveStoragePorts.
/**
* Workflow Step to remove storage ports from Storage View.
* Note arguments (except stepId) must match storageViewRemoveStoragePortsMethod above.
*
* @param vplexURI
* -- URI of VPlex StorageSystem
* @param exportURI
* -- ExportGroup URI
* @param maskURI
* -- ExportMask URI.
* @param targetURIs
* -- list of targets URIs (VPLEX FE ports) to be removed.
* If non null, the targets (VPlex front end ports) indicated by the targetURIs will be removed
* from the Storage View.
* @param rollbackContextKey
* -- Context token for rollback processing
* @param stepId
* -- Workflow step id.
* @throws WorkflowException
*/
public void storageViewRemoveStoragePorts(URI vplexURI, URI exportURI, URI maskURI, List<URI> targetURIs, String rollbackContextKey, String stepId) throws DeviceControllerException {
ExportMaskRemoveInitiatorCompleter completer = null;
try {
WorkflowStepCompleter.stepExecuting(stepId);
completer = new ExportMaskRemoveInitiatorCompleter(exportURI, maskURI, new ArrayList<URI>(), stepId);
StorageSystem vplex = getDataObject(StorageSystem.class, vplexURI, _dbClient);
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, maskURI);
VPlexApiClient client = getVPlexAPIClient(_vplexApiFactory, vplex, _dbClient);
String vplexClusterName = VPlexUtil.getVplexClusterName(exportMask, vplexURI, client, _dbClient);
Map<String, String> targetPortMap = VPlexControllerUtils.getTargetPortToPwwnMap(client, vplexClusterName);
VPlexStorageViewInfo storageView = client.getStorageView(vplexClusterName, exportMask.getMaskName());
_log.info("Refreshing ExportMask {}", exportMask.getMaskName());
VPlexControllerUtils.refreshExportMask(_dbClient, storageView, exportMask, targetPortMap, _networkDeviceController);
// get the context from the task completer, in case this is a rollback.
if (rollbackContextKey != null) {
ExportOperationContext context = (ExportOperationContext) WorkflowService.getInstance().loadStepData(rollbackContextKey);
if (context != null) {
// a non-null context means this step is running as part of a rollback.
List<URI> addedTargets = new ArrayList<>();
if (context.getOperations() != null) {
_log.info("Handling storageViewRemoveStoragePorts as a result of rollback");
ListIterator<ExportOperationContextOperation> li = context.getOperations().listIterator(context.getOperations().size());
while (li.hasPrevious()) {
ExportOperationContextOperation operation = (ExportOperationContextOperation) li.previous();
if (operation != null && VplexExportOperationContext.OPERATION_ADD_TARGETS_TO_STORAGE_VIEW.equals(operation.getOperation())) {
addedTargets = (List<URI>) operation.getArgs().get(0);
_log.info(String.format("Removing target port(s) %s from storage view %s as part of rollback", Joiner.on(',').join(addedTargets), exportMask.getMaskName()));
}
}
}
if (addedTargets == null || addedTargets.isEmpty()) {
_log.info("There was no context found for add target. So there is nothing to rollback.");
completer.ready(_dbClient);
return;
}
// Change the list of targets to process to the list
// that successfully were added during addStoragePorts.
targetURIs.clear();
targetURIs.addAll(addedTargets);
}
}
// validate the remove storage port operation against the export mask volumes
// this is conceptually the same as remove initiators, so will validate with volumes
List<URI> volumeURIList = (exportMask.getUserAddedVolumes() != null) ? URIUtil.toURIList(exportMask.getUserAddedVolumes().values()) : new ArrayList<URI>();
if (volumeURIList.isEmpty()) {
_log.warn("volume URI list for validating remove initiators is empty...");
}
// removing all storage ports but leaving the existing initiators and volumes.
if (!exportMask.hasAnyExistingInitiators() && !exportMask.hasAnyExistingVolumes()) {
ExportMaskValidationContext ctx = new ExportMaskValidationContext();
ctx.setStorage(vplex);
ctx.setExportMask(exportMask);
ctx.setBlockObjects(volumeURIList, _dbClient);
ctx.setAllowExceptions(!WorkflowService.getInstance().isStepInRollbackState(stepId));
validator.removeInitiators(ctx).validate();
if (targetURIs != null && targetURIs.isEmpty() == false) {
List<PortInfo> targetPortInfos = new ArrayList<PortInfo>();
List<URI> targetsToRemoveFromStorageView = new ArrayList<URI>();
for (URI target : targetURIs) {
// Do not try to remove a port twice.
if (!exportMask.getStoragePorts().contains(target.toString())) {
continue;
}
// Build the PortInfo structure for the port to be added
StoragePort port = getDataObject(StoragePort.class, target, _dbClient);
PortInfo pi = new PortInfo(port.getPortNetworkId().toUpperCase().replaceAll(":", ""), null, port.getPortName(), null);
targetPortInfos.add(pi);
targetsToRemoveFromStorageView.add(target);
}
if (!targetPortInfos.isEmpty()) {
// Remove the targets from the VPLEX
client.removeTargetsFromStorageView(exportMask.getMaskName(), targetPortInfos);
// Remove the targets to the database.
for (URI target : targetsToRemoveFromStorageView) {
exportMask.removeTarget(target);
}
_dbClient.updateObject(exportMask);
}
}
}
completer.ready(_dbClient);
} catch (VPlexApiException vae) {
_log.error("Exception removing storage ports from Storage View: " + vae.getMessage(), vae);
failStep(completer, stepId, vae);
} catch (Exception ex) {
_log.error("Exception removing storage ports from Storage View: " + ex.getMessage(), ex);
String opName = ResourceOperationTypeEnum.DELETE_STORAGE_VIEW_STORAGEPORTS.getName();
ServiceError serviceError = VPlexApiException.errors.storageViewRemoveStoragePortFailed(opName, ex);
failStep(completer, stepId, serviceError);
}
}
use of com.emc.storageos.vplex.api.clientdata.PortInfo in project coprhd-controller by CoprHD.
the class VPlexApiTest method testAddVirtualVolumesToStorageView.
/**
* Tests the API addVirtualVolumesToStorageView.
*/
@Test
public void testAddVirtualVolumesToStorageView() {
boolean wasException = false;
try {
// Get the storage view name
String storageViewName = _properties.getProperty(STORAGE_VIEW_NAME_PROP_KEY);
// Get the target ports
List<PortInfo> targetPortInfoList = new ArrayList<PortInfo>();
String storageViewTargetsStr = _properties.getProperty(STORAGE_VIEW_TARGETS_PROP_KEY);
StringTokenizer tokenizer = new StringTokenizer(storageViewTargetsStr, ",");
while (tokenizer.hasMoreTokens()) {
String portWWN = tokenizer.nextToken();
PortInfo targetPortInfo = new PortInfo(portWWN);
targetPortInfoList.add(targetPortInfo);
}
// Create the storage view
VPlexStorageViewInfo storageViewInfo = _client.createStorageView(storageViewName, targetPortInfoList, null, null);
Assert.assertNotNull(storageViewInfo);
Assert.assertEquals(storageViewInfo.getName(), storageViewName);
// Create a virtual volume.
VPlexVirtualVolumeInfo vvInfo = createSimpleVirtualVolume();
Assert.assertNotNull(vvInfo);
Map<String, Integer> vvMap = new HashMap<String, Integer>();
vvMap.put(vvInfo.getName(), Integer.valueOf(VPlexApiConstants.LUN_UNASSIGNED));
// Add the virtual volume to the storage view.
_client.addVirtualVolumesToStorageView(storageViewName, VPLEX_TEST_CLUSTER, vvMap);
// Cleanup
Boolean[] viewFound = new Boolean[] { new Boolean(false) };
_client.deleteStorageView(storageViewName, VPLEX_TEST_CLUSTER, viewFound);
_client.deleteVirtualVolume(vvInfo.getName(), true, false);
} catch (Exception e) {
wasException = true;
}
Assert.assertFalse(wasException);
}
use of com.emc.storageos.vplex.api.clientdata.PortInfo in project coprhd-controller by CoprHD.
the class VPlexApiTest method testCreateStorageViewWithVolumes.
/**
* Tests the API createStorageView when both target ports and virtual
* volumes are passed in the request.
*/
@Test
public void testCreateStorageViewWithVolumes() {
boolean wasException = false;
try {
// Get the storage view name
String storageViewName = _properties.getProperty(STORAGE_VIEW_NAME_PROP_KEY);
// Get the target ports
List<PortInfo> targetPortInfoList = new ArrayList<PortInfo>();
String storageViewTargetsStr = _properties.getProperty(STORAGE_VIEW_TARGETS_PROP_KEY);
StringTokenizer tokenizer = new StringTokenizer(storageViewTargetsStr, ",");
while (tokenizer.hasMoreTokens()) {
String portWWN = tokenizer.nextToken();
PortInfo targetPortInfo = new PortInfo(portWWN);
targetPortInfoList.add(targetPortInfo);
}
// Create the virtual volume.
VPlexVirtualVolumeInfo vvInfo = createSimpleVirtualVolume();
Assert.assertNotNull(vvInfo);
Map<String, Integer> vvMap = new HashMap<String, Integer>();
vvMap.put(vvInfo.getName(), Integer.valueOf(VPlexApiConstants.LUN_UNASSIGNED));
// Create the storage view
VPlexStorageViewInfo storageViewInfo = _client.createStorageView(storageViewName, targetPortInfoList, null, vvMap);
Assert.assertNotNull(storageViewInfo);
Assert.assertEquals(storageViewInfo.getName(), storageViewName);
// Cleanup
Boolean[] viewFound = new Boolean[] { new Boolean(false) };
_client.deleteStorageView(storageViewName, VPLEX_TEST_CLUSTER, viewFound);
_client.deleteVirtualVolume(vvInfo.getName(), true, false);
} catch (Exception e) {
wasException = true;
}
Assert.assertFalse(wasException);
}
use of com.emc.storageos.vplex.api.clientdata.PortInfo in project coprhd-controller by CoprHD.
the class VPlexApiTest method testCreateStorageViewNoViewName.
/**
* Tests the API createStorageView when the view name is not specified.
*/
@Test
public void testCreateStorageViewNoViewName() {
// Get the target ports
List<PortInfo> targetPortInfoList = new ArrayList<PortInfo>();
String storageViewTargetsStr = _properties.getProperty(STORAGE_VIEW_TARGETS_PROP_KEY);
StringTokenizer tokenizer = new StringTokenizer(storageViewTargetsStr, ",");
while (tokenizer.hasMoreTokens()) {
String portWWN = tokenizer.nextToken();
PortInfo targetPortInfo = new PortInfo(portWWN);
targetPortInfoList.add(targetPortInfo);
}
// Test with a null view name.
boolean wasException = false;
try {
Assert.assertTrue(!targetPortInfoList.isEmpty());
_client.createStorageView(null, targetPortInfoList, null, null);
} catch (VPlexApiException vae) {
wasException = true;
}
Assert.assertTrue(wasException);
// Test with a blank view name.
wasException = false;
try {
Assert.assertTrue(!targetPortInfoList.isEmpty());
_client.createStorageView("", targetPortInfoList, null, null);
} catch (VPlexApiException vae) {
wasException = true;
}
Assert.assertTrue(wasException);
// Test with a view name consisting only of white space.
wasException = false;
try {
Assert.assertTrue(!targetPortInfoList.isEmpty());
_client.createStorageView(" ", targetPortInfoList, null, null);
} catch (VPlexApiException vae) {
wasException = true;
}
Assert.assertTrue(wasException);
}
Aggregations