/* * Copyright (c) 2017 DELL EMC Corporation * All Rights Reserved */ package com.emc.sa.service.vipr.block; import static com.emc.sa.service.ServiceParams.HOST; import static com.emc.sa.service.ServiceParams.EXPORT; import static com.emc.sa.service.ServiceParams.MIN_PATHS; import static com.emc.sa.service.ServiceParams.MAX_PATHS; import static com.emc.sa.service.ServiceParams.PATHS_PER_INITIATOR; import static com.emc.sa.service.ServiceParams.PORTS; import static com.emc.sa.service.ServiceParams.STORAGE_SYSTEM; import static com.emc.sa.service.ServiceParams.VIRTUAL_ARRAY; import static com.emc.sa.service.ServiceParams.RESULTING_PATHS; import static com.emc.sa.service.ServiceParams.REMOVED_PATHS; import static com.emc.sa.service.ServiceParams.USE_EXISTING_PATHS; import static com.emc.sa.service.ServiceParams.SUSPEND_WAIT; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.emc.sa.engine.ExecutionUtils; import com.emc.sa.engine.bind.Param; import com.emc.sa.engine.service.Service; import com.emc.sa.service.vipr.ViPRService; import com.emc.sa.service.vipr.block.tasks.ExportPathsPreview; import com.emc.sa.util.CatalogSerializationUtils; import com.emc.storageos.model.NamedRelatedResourceRep; import com.emc.storageos.model.block.export.ExportPathsAdjustmentPreviewRestRep; import com.emc.storageos.model.block.export.InitiatorPathParam; import com.emc.storageos.model.block.export.InitiatorPortMapRestRep; @Service("ExportPathAdjustment") public class ExportPathAdjustmentService extends ViPRService { @Param(HOST) protected URI host; @Param(VIRTUAL_ARRAY) protected URI virtualArray; @Param(EXPORT) protected URI exportId; @Param(MIN_PATHS) protected Integer minPaths; @Param(MAX_PATHS) protected Integer maxPaths; @Param(PATHS_PER_INITIATOR) protected Integer pathsPerInitiator; @Param(USE_EXISTING_PATHS) protected String useExistingPaths; @Param(STORAGE_SYSTEM) protected URI storageSystem; @Param(value = PORTS, required = false) protected List<URI> ports; @Param(SUSPEND_WAIT) protected boolean suspendWait; @Param(value = RESULTING_PATHS, required = false) protected List<String> resultingPaths; @Param(value = REMOVED_PATHS, required = false) protected List<String> removedPaths; private Map<URI, List<URI>> resultingPathsMap = new HashMap<URI, List<URI>>(); private Map<URI, List<URI>> removedPathsMap = new HashMap<URI, List<URI>>(); @Override public void precheck() throws Exception { if ((resultingPaths == null || resultingPaths.isEmpty()) && (removedPaths == null || removedPaths.isEmpty())) { // if we have no affected or removed, the preview as likely not been generated, so we're going to // generate it before running the service. This is to support the api call and allowing the user // to omit sending the serialize string. runExportPathsPreview(); } else { try { if (resultingPaths != null) { for (String affected : resultingPaths) { Map<URI, List<URI>> port = (Map<URI, List<URI>>) CatalogSerializationUtils.serializeFromString(affected); resultingPathsMap.putAll(port); } } if (removedPaths != null) { for (String removed : removedPaths) { Map<URI, List<URI>> port = (Map<URI, List<URI>>) CatalogSerializationUtils.serializeFromString(removed); removedPathsMap.putAll(port); } } } catch (Exception ex) { ExecutionUtils.fail("failTask.AdjustExportPaths.deserialize", args(), ex.getMessage()); } } } @Override public void execute() throws Exception { // build affect paths List<InitiatorPathParam> toSendAffectedPaths = new ArrayList<InitiatorPathParam>(); for (Map.Entry<URI, List<URI>> entry : resultingPathsMap.entrySet()) { InitiatorPathParam pathParam = new InitiatorPathParam(); pathParam.setInitiator(entry.getKey()); pathParam.setStoragePorts(entry.getValue()); toSendAffectedPaths.add(pathParam); } // build removed paths List<InitiatorPathParam> toSendRemovedPaths = new ArrayList<InitiatorPathParam>(); for (Map.Entry<URI, List<URI>> entry : removedPathsMap.entrySet()) { InitiatorPathParam pathParam = new InitiatorPathParam(); pathParam.setInitiator(entry.getKey()); pathParam.setStoragePorts(entry.getValue()); toSendRemovedPaths.add(pathParam); } BlockStorageUtils.adjustExportPaths(virtualArray, minPaths, maxPaths, pathsPerInitiator, storageSystem, exportId, toSendAffectedPaths, toSendRemovedPaths, suspendWait); } private void runExportPathsPreview() { ExportPathsAdjustmentPreviewRestRep previewRestRep = execute(new ExportPathsPreview(host, virtualArray, exportId, minPaths, maxPaths, pathsPerInitiator, storageSystem, ports)); List<InitiatorPortMapRestRep> affectedPaths = previewRestRep.getAdjustedPaths(); List<InitiatorPortMapRestRep> removedPaths = previewRestRep.getRemovedPaths(); // build the affected path for (InitiatorPortMapRestRep ipm : affectedPaths) { List<URI> portList = new ArrayList<URI>(); for (NamedRelatedResourceRep port : ipm.getStoragePorts()) { portList.add(port.getId()); } resultingPathsMap.put(ipm.getInitiator().getId(), portList); } // build the removed path for (InitiatorPortMapRestRep ipm : removedPaths) { List<URI> portList = new ArrayList<URI>(); for (NamedRelatedResourceRep port : ipm.getStoragePorts()) { portList.add(port.getId()); } removedPathsMap.put(ipm.getInitiator().getId(), portList); } } }