use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.
the class RPDeviceController method exportOrchestrationSteps.
/**
* @param volumeDescriptors
* - Volume descriptors
* @param rpSystemId
* - RP system
* @param taskId
* - task ID
* @return - True on success, false otherwise
* @throws InternalException
*/
public boolean exportOrchestrationSteps(List<VolumeDescriptor> volumeDescriptors, URI rpSystemId, String taskId) throws InternalException {
List<URI> volUris = VolumeDescriptor.getVolumeURIs(volumeDescriptors);
RPCGExportOrchestrationCompleter completer = new RPCGExportOrchestrationCompleter(volUris, taskId);
Workflow workflow = null;
boolean lockException = false;
Map<URI, Set<URI>> exportGroupVolumesAdded = new HashMap<URI, Set<URI>>();
exportGroupsCreated = new ArrayList<URI>();
final String COMPUTE_RESOURCE_CLUSTER = "cluster";
try {
final String workflowKey = "rpExportOrchestration";
if (!WorkflowService.getInstance().hasWorkflowBeenCreated(taskId, workflowKey)) {
// Generate the Workflow.
workflow = _workflowService.getNewWorkflow(this, EXPORT_ORCHESTRATOR_WF_NAME, true, taskId);
// the wait for key returned by previous call
String waitFor = null;
ProtectionSystem rpSystem = _dbClient.queryObject(ProtectionSystem.class, rpSystemId);
// Get the CG Params based on the volume descriptors
CGRequestParams params = this.getCGRequestParams(volumeDescriptors, rpSystem);
updateCGParams(params);
_log.info("Start adding RP Export Volumes steps....");
// Get the RP Exports from the CGRequestParams object
Collection<RPExport> rpExports = generateStorageSystemExportMaps(params, volumeDescriptors);
Map<String, Set<URI>> rpSiteInitiatorsMap = getRPSiteInitiators(rpSystem, rpExports);
// Acquire all the RP lock keys needed for export before we start assembling the export groups.
acquireRPLockKeysForExport(taskId, rpExports, rpSiteInitiatorsMap);
// or create a new one.
for (RPExport rpExport : rpExports) {
URI storageSystemURI = rpExport.getStorageSystem();
String internalSiteName = rpExport.getRpSite();
URI varrayURI = rpExport.getVarray();
List<URI> volumes = rpExport.getVolumes();
List<URI> initiatorSet = new ArrayList<URI>();
String rpSiteName = (rpSystem.getRpSiteNames() != null) ? rpSystem.getRpSiteNames().get(internalSiteName) : internalSiteName;
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, storageSystemURI);
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, varrayURI);
_log.info("--------------------");
_log.info(String.format("RP Export: StorageSystem = [%s] RPSite = [%s] VirtualArray = [%s]", storageSystem.getLabel(), rpSiteName, varray.getLabel()));
boolean isJournalExport = rpExport.getIsJournalExport();
String exportGroupGeneratedName = RPHelper.generateExportGroupName(rpSystem, storageSystem, internalSiteName, varray, isJournalExport);
// Setup the export group - we may or may not need to create it, but we need to have everything ready in case we do
ExportGroup exportGroup = RPHelper.createRPExportGroup(exportGroupGeneratedName, varray, _dbClient.queryObject(Project.class, params.getProject()), 0, isJournalExport);
// Get the initiators of the RP Cluster (all of the RPAs on one side of a configuration)
Map<String, Map<String, String>> rpaWWNs = RPHelper.getRecoverPointClient(rpSystem).getInitiatorWWNs(internalSiteName);
if (rpaWWNs == null || rpaWWNs.isEmpty()) {
throw DeviceControllerExceptions.recoverpoint.noInitiatorsFoundOnRPAs();
}
// Convert to initiator object
List<Initiator> initiators = new ArrayList<Initiator>();
for (String rpaId : rpaWWNs.keySet()) {
for (Map.Entry<String, String> rpaWWN : rpaWWNs.get(rpaId).entrySet()) {
Initiator initiator = ExportUtils.getInitiator(rpaWWN.getKey(), _dbClient);
initiators.add(initiator);
}
}
// We need to find and distill only those RP initiators that correspond to the network of the
// storage
// system and
// that network has front end port from the storage system.
// In certain lab environments, its quite possible that there are 2 networks one for the storage
// system
// FE ports and one for
// the BE ports.
// In such configs, RP initiators will be spread across those 2 networks. RP controller does not
// care
// about storage system
// back-end ports, so
// we will ignore those initiators that are connected to a network that has only storage system back
// end
// port connectivity.
Map<URI, Set<Initiator>> rpNetworkToInitiatorsMap = new HashMap<URI, Set<Initiator>>();
Set<URI> rpSiteInitiatorUris = rpSiteInitiatorsMap.get(internalSiteName);
if (rpSiteInitiatorUris != null) {
for (URI rpSiteInitiatorUri : rpSiteInitiatorUris) {
Initiator rpSiteInitiator = _dbClient.queryObject(Initiator.class, rpSiteInitiatorUri);
URI rpInitiatorNetworkURI = getInitiatorNetwork(exportGroup, rpSiteInitiator);
if (rpInitiatorNetworkURI != null) {
if (rpNetworkToInitiatorsMap.get(rpInitiatorNetworkURI) == null) {
rpNetworkToInitiatorsMap.put(rpInitiatorNetworkURI, new HashSet<Initiator>());
}
rpNetworkToInitiatorsMap.get(rpInitiatorNetworkURI).add(rpSiteInitiator);
_log.info(String.format("RP Initiator [%s] found on network: [%s]", rpSiteInitiator.getInitiatorPort(), rpInitiatorNetworkURI.toASCIIString()));
} else {
_log.info(String.format("RP Initiator [%s] was not found on any network. Excluding from automated exports", rpSiteInitiator.getInitiatorPort()));
}
}
}
// Compute numPaths. This is how its done:
// We know the RP site and the Network/TransportZone it is on.
// Determine all the storage ports for the storage array for all the networks they are on.
// Next, if we find the network for the RP site in the above list, return all the storage ports
// corresponding to that.
// For RP we will try and use as many Storage ports as possible.
Map<URI, List<StoragePort>> initiatorPortMap = getInitiatorPortsForArray(rpNetworkToInitiatorsMap, storageSystemURI, varrayURI, rpSiteName);
for (URI networkURI : initiatorPortMap.keySet()) {
for (StoragePort storagePort : initiatorPortMap.get(networkURI)) {
_log.info(String.format("Network : [%s] - Port : [%s]", networkURI.toString(), storagePort.getLabel()));
}
}
int numPaths = computeNumPaths(initiatorPortMap, varrayURI, storageSystem);
_log.info("Total paths = " + numPaths);
// Stems from above comment where we distill the RP network and the initiators in that network.
List<Initiator> initiatorList = new ArrayList<Initiator>();
for (URI rpNetworkURI : rpNetworkToInitiatorsMap.keySet()) {
if (initiatorPortMap.containsKey(rpNetworkURI)) {
initiatorList.addAll(rpNetworkToInitiatorsMap.get(rpNetworkURI));
}
}
for (Initiator initiator : initiatorList) {
initiatorSet.add(initiator.getId());
}
// See if the export group already exists
ExportGroup exportGroupInDB = exportGroupExistsInDB(exportGroup);
boolean addExportGroupToDB = false;
if (exportGroupInDB != null) {
exportGroup = exportGroupInDB;
// If the export already exists, check to see if any of the volumes have already been exported.
// No
// need to
// re-export volumes.
List<URI> volumesToRemove = new ArrayList<URI>();
for (URI volumeURI : volumes) {
if (exportGroup.getVolumes() != null && !exportGroup.getVolumes().isEmpty() && exportGroup.getVolumes().containsKey(volumeURI.toString())) {
_log.info(String.format("Volume [%s] already exported to export group [%s], " + "it will be not be re-exported", volumeURI.toString(), exportGroup.getGeneratedName()));
volumesToRemove.add(volumeURI);
}
}
// Remove volumes if they have already been exported
if (!volumesToRemove.isEmpty()) {
volumes.removeAll(volumesToRemove);
}
// nothing else needs to be done here.
if (volumes.isEmpty()) {
_log.info(String.format("No volumes needed to be exported to export group [%s], continue", exportGroup.getGeneratedName()));
continue;
}
} else {
addExportGroupToDB = true;
}
// Add volumes to the export group
Map<URI, Integer> volumesToAdd = new HashMap<URI, Integer>();
for (URI volumeID : volumes) {
exportGroup.addVolume(volumeID, ExportGroup.LUN_UNASSIGNED);
volumesToAdd.put(volumeID, ExportGroup.LUN_UNASSIGNED);
}
// Keep track of volumes added to export group
if (!volumesToAdd.isEmpty()) {
exportGroupVolumesAdded.put(exportGroup.getId(), volumesToAdd.keySet());
}
// volume
if (rpExport.getComputeResource() != null) {
URI computeResource = rpExport.getComputeResource();
_log.info(String.format("RP Export: ComputeResource : %s", computeResource.toString()));
if (computeResource.toString().toLowerCase().contains(COMPUTE_RESOURCE_CLUSTER)) {
Cluster cluster = _dbClient.queryObject(Cluster.class, computeResource);
exportGroup.addCluster(cluster);
} else {
Host host = _dbClient.queryObject(Host.class, rpExport.getComputeResource());
exportGroup.addHost(host);
}
}
// Persist the export group
if (addExportGroupToDB) {
exportGroup.addInitiators(initiatorSet);
exportGroup.setNumPaths(numPaths);
_dbClient.createObject(exportGroup);
// Keep track of newly created EGs in case of rollback
exportGroupsCreated.add(exportGroup.getId());
} else {
_dbClient.updateObject(exportGroup);
}
// If the export group already exists, add the volumes to it, otherwise create a brand new
// export group.
StringBuilder buffer = new StringBuilder();
buffer.append(String.format(DASHED_NEWLINE));
if (!addExportGroupToDB) {
buffer.append(String.format("Adding volumes to existing Export Group for Storage System [%s], RP Site [%s], Virtual Array [%s]%n", storageSystem.getLabel(), rpSiteName, varray.getLabel()));
buffer.append(String.format("Export Group name is : [%s]%n", exportGroup.getGeneratedName()));
buffer.append(String.format("Export Group will have these volumes added: [%s]%n", Joiner.on(',').join(volumes)));
buffer.append(String.format(DASHED_NEWLINE));
_log.info(buffer.toString());
waitFor = _exportWfUtils.generateExportGroupAddVolumes(workflow, STEP_EXPORT_GROUP, waitFor, storageSystemURI, exportGroup.getId(), volumesToAdd);
_log.info("Added Export Group add volumes step in workflow");
} else {
buffer.append(String.format("Creating new Export Group for Storage System [%s], RP Site [%s], Virtual Array [%s]%n", storageSystem.getLabel(), rpSiteName, varray.getLabel()));
buffer.append(String.format("Export Group name is: [%s]%n", exportGroup.getGeneratedName()));
buffer.append(String.format("Export Group will have these initiators: [%s]%n", Joiner.on(',').join(initiatorSet)));
buffer.append(String.format("Export Group will have these volumes added: [%s]%n", Joiner.on(',').join(volumes)));
buffer.append(String.format(DASHED_NEWLINE));
_log.info(buffer.toString());
String exportStep = workflow.createStepId();
initTaskStatus(exportGroup, exportStep, Operation.Status.pending, "create export");
waitFor = _exportWfUtils.generateExportGroupCreateWorkflow(workflow, STEP_EXPORT_GROUP, waitFor, storageSystemURI, exportGroup.getId(), volumesToAdd, initiatorSet);
_log.info("Added Export Group create step in workflow. New Export Group Id: " + exportGroup.getId());
}
}
String successMessage = "Export orchestration completed successfully";
// Finish up and execute the plan.
// The Workflow will handle the TaskCompleter
Object[] callbackArgs = new Object[] { volUris };
workflow.executePlan(completer, successMessage, new WorkflowCallback(), callbackArgs, null, null);
// Mark this workflow as created/executed so we don't do it again on retry/resume
WorkflowService.getInstance().markWorkflowBeenCreated(taskId, workflowKey);
}
} catch (LockRetryException ex) {
/**
* Added this catch block to mark the current workflow as completed so that lock retry will not get exception while creating new
* workflow using the same taskid.
*/
_log.warn(String.format("Lock retry exception key: %s remaining time %d", ex.getLockIdentifier(), ex.getRemainingWaitTimeSeconds()));
if (workflow != null && !NullColumnValueGetter.isNullURI(workflow.getWorkflowURI()) && workflow.getWorkflowState() == WorkflowState.CREATED) {
com.emc.storageos.db.client.model.Workflow wf = _dbClient.queryObject(com.emc.storageos.db.client.model.Workflow.class, workflow.getWorkflowURI());
if (!wf.getCompleted()) {
_log.error("Marking the status to completed for the newly created workflow {}", wf.getId());
wf.setCompleted(true);
_dbClient.updateObject(wf);
}
}
throw ex;
} catch (Exception ex) {
_log.error("Could not create volumes: " + volUris, ex);
// Rollback ViPR level RP export group changes
rpExportGroupRollback();
if (workflow != null) {
_workflowService.releaseAllWorkflowLocks(workflow);
}
String opName = ResourceOperationTypeEnum.CREATE_BLOCK_VOLUME.getName();
ServiceError serviceError = null;
if (lockException) {
serviceError = DeviceControllerException.errors.createVolumesAborted(volUris.toString(), ex);
} else {
serviceError = DeviceControllerException.errors.createVolumesFailed(volUris.toString(), opName, ex);
}
completer.error(_dbClient, _locker, serviceError);
return false;
}
_log.info("End adding RP Export Volumes steps.");
return true;
}
use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.
the class RPDeviceController method getRPSiteInitiators.
/**
* Build a map of initiators for each RP site/cluster in the export request.
*
* @param rpSystem
* RP system
* @param rpExports
* RP Export objects
* @return Map of RP site to its initiators
*/
private Map<String, Set<URI>> getRPSiteInitiators(ProtectionSystem rpSystem, Collection<RPExport> rpExports) {
Map<String, Set<URI>> rpSiteInitiators = new HashMap<String, Set<URI>>();
for (RPExport rpExport : rpExports) {
String rpSiteName = rpExport.getRpSite();
Map<String, Map<String, String>> rpaWWNs = RPHelper.getRecoverPointClient(rpSystem).getInitiatorWWNs(rpSiteName);
if (rpaWWNs == null || rpaWWNs.isEmpty()) {
throw DeviceControllerExceptions.recoverpoint.noInitiatorsFoundOnRPAs();
}
// Convert to initiator object
for (String rpaId : rpaWWNs.keySet()) {
for (Map.Entry<String, String> rpaWWN : rpaWWNs.get(rpaId).entrySet()) {
Initiator initiator = ExportUtils.getInitiator(rpaWWN.getKey(), _dbClient);
if (initiator == null) {
_log.error(String.format("Could not find initiator for %s on RP ID %s, site %s", rpaWWN.getKey(), rpaId, rpSiteName));
throw DeviceControllerExceptions.recoverpoint.noInitiatorsFoundOnRPAs();
}
if (!rpSiteInitiators.containsKey(rpSiteName)) {
rpSiteInitiators.put(rpSiteName, new HashSet<URI>());
}
_log.info(String.format("Adding initiator %s, port %s on RP ID %s, site %s", initiator.getId(), rpaWWN.getKey(), rpaId, rpSiteName));
rpSiteInitiators.get(rpSiteName).add(initiator.getId());
}
}
}
return rpSiteInitiators;
}
use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.
the class NetworkDeviceController method getZoneReferences.
/**
* Given the zoning map, find all the instances of FCZoneReference for each initiator-port pair.
*
* @param refreshMap the zoning map
* @param initiators the initiators
* @param ports the storage ports
* @return a map of zone key to a list of zone reference objects for the key.
*/
private Map<String, List<FCZoneReference>> getZoneReferences(StringSetMap refreshMap, Collection<Initiator> initiators, Collection<StoragePort> ports) {
Map<String, List<FCZoneReference>> map = new HashMap<String, List<FCZoneReference>>();
Initiator initiator = null;
StoragePort port = null;
Set<String> portsKey = null;
for (String initKey : refreshMap.keySet()) {
portsKey = refreshMap.get(initKey);
initiator = DataObjectUtils.findInCollection(initiators, initKey);
if (initiator == null) {
continue;
}
if (portsKey == null || portsKey.isEmpty()) {
continue;
}
for (String portkey : portsKey) {
port = DataObjectUtils.findInCollection(ports, portkey);
if (port == null) {
continue;
}
String key = FCZoneReference.makeEndpointsKey(initiator.getInitiatorPort(), port.getPortNetworkId());
Joiner joiner = dbModelClient.join(FCZoneReference.class, "refs", "pwwnKey", key).go();
List<FCZoneReference> list = joiner.list("refs");
if (list != null && !list.isEmpty()) {
map.put(key, list);
}
}
}
return map;
}
use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.
the class NetworkDeviceController method fetchInitiatorsZones.
/**
* For the given network and initiators, which are in the network,
* use one of the network's network system to get the zones and populate
* wwnToZones map with the zones found. Return the network system
* used to get the zones.
* <p>
* This function is created because to create the ZoneInfoMap of {@link #getInitiatorsInNetworkZoneInfoMap(NetworkLite, List, Map)},
* both the network system used and the zones are needed, while for {@link #getInitiatorsInNetworkZones(NetworkLite, List)} only the
* zones are needed. This solution was to support both calling functions.
* <p>
* Note if a zone is found that has more than one of the initiator, the zone will be returned once for each initiator.
*
* @param network the network of the initiators
* @param initiators the initiators
* @param wwnToZones a IN/OUT parameters which is a map to be populated
* with the zone mappings found
* @return the network system used to get the zones.
*/
private NetworkSystem fetchInitiatorsZones(NetworkLite network, List<Initiator> initiators, Map<String, List<Zone>> wwnToZones) {
// Check some network systems are discovered.
if (!NetworkUtil.areNetworkSystemDiscovered(_dbClient)) {
return null;
}
if (!Transport.FC.toString().equals(network.getTransportType())) {
return null;
}
if (initiators == null || initiators.isEmpty()) {
return null;
}
// Select the network system to use
NetworkSystem networkSystem = null;
Map<String, Initiator> wwnToInitiatorMap = wwnToInitiatorMap(initiators);
List<NetworkSystem> zoningNetworkSystems = _networkScheduler.getZoningNetworkSystems(network, null);
Iterator<NetworkSystem> itr = zoningNetworkSystems.iterator();
while (itr.hasNext()) {
networkSystem = itr.next();
try {
if (networkSystem != null) {
_log.info("Trying network system {} for network {} to get initiator zones.", networkSystem.getLabel(), network.getLabel());
wwnToZones.putAll(getDevice(networkSystem.getSystemType()).getEndpointsZones(networkSystem, NetworkUtil.getNetworkWwn(network), network.getNativeId(), wwnToInitiatorMap.keySet()));
// if we get here, we were successful at getting the zones, do not try any more network systems
break;
}
} catch (Exception ex) {
// if we hit and exception, log it and try the next network system;
wwnToZones.clear();
_log.error("Failed to get the zones for initiators {} in network {} " + "using network system {}. Will try the other available network systems", new Object[] { wwnToInitiatorMap.keySet(), network.getLabel(), networkSystem == null ? "null" : networkSystem.getLabel() });
}
networkSystem = null;
}
if (networkSystem == null) {
_log.error("Failed to find a registered network system in good discovery status to discover the zones");
throw NetworkDeviceControllerException.exceptions.failedToFindNetworkSystem(wwnToInitiatorMap.keySet(), network.getLabel());
}
return networkSystem;
}
use of com.emc.storageos.db.client.model.Initiator in project coprhd-controller by CoprHD.
the class NetworkDeviceController method refreshZoningMap.
/**
* Update the zoning map for as export mask previously "accepted". This applies to
* brown field scenarios where a export mask was found on the storage array. For
* those export masks, changes outside of the application are expected and the
* application should get the latest state before making any changes. This
* function is called from ExportMaskOperations#refreshZoneMap after all
* updates to the initiators, ports and volumes were made into the export mask and
* the export group. The update steps are as follow:
* <ol>
* <li>Get the current zones for those initiators that were not added by ViPR and the storage ports that exist in the mask.</li>
* <li>Diff the current zones with those in the export mask and update the zoning map</li>
* <li>Update the FCZoneReferences to match the zone updates</li>
* </ol>
* Note that ViPR does not keep FCZoneReferences only for volumes created by ViPR. As those
* volumes are not updated by ExportMaskOperations#refreshZoneMap, no additional code
* is needed to remove FCZoneReferences for removed volumes.
*
* @param exportMask the export mask being updated.
* @param removedInitiators the list of initiators that were removed. This is needed because
* these were removed from the zoingMap by {@link ExportMask#removeInitiators(Collection)}
* @param removedPorts the set of storage ports that were removed
* @param maskUpdated a flag that indicates if an update was made to the mask that requires
* a zoning refresh
* @param persist a boolean that indicates if the changes should be persisted in the db
*/
public void refreshZoningMap(ExportMask exportMask, Collection<String> removedInitiators, Collection<String> removedPorts, boolean maskUpdated, boolean persist) {
try {
// check if zoning is enabled for the mask
if (!zoningEnabled(exportMask)) {
_log.info("Zoning not enabled for export mask {}. Zoning refresh will not be done", exportMask.getMaskName());
return;
}
if (!(maskUpdated || alwaysRefreshZone())) {
_log.info("The mask ports and initiators were not modified and alwaysRefreshZones is false" + " Zoning refresh will not be done for mask {}", exportMask.getMaskName());
return;
}
List<Initiator> initiators = ExportUtils.getExportMaskInitiators(exportMask, _dbClient);
_log.info("Refreshing zones for export mask {}. \n\tCurrent initiators " + "in this mask are: {}. \n\tStorage ports in the mask are : {}. \n\tZoningMap is : {}. " + "\n\tRemoved initiators: {}. \n\tRemoved ports: {}", new Object[] { exportMask.getMaskName(), exportMask.getInitiators(), exportMask.getStoragePorts(), exportMask.getZoningMap(), removedInitiators, removedPorts });
Long start = System.currentTimeMillis();
// get the current zones in the network system for initiators and ports
List<StoragePort> storagePorts = ExportUtils.getStoragePorts(exportMask, _dbClient);
ZoneInfoMap zoneInfoMap = getInitiatorsZoneInfoMap(initiators, storagePorts);
// Get the full sets of initiators and ports affected. They will be used to find the FCZoneReferences to refresh
// These sets include new initiators and ports, existing ones that did not change, as well as removed ones
List<StoragePort> allStoragePorts = DataObjectUtils.iteratorToList(_dbClient.queryIterativeObjects(StoragePort.class, StringSetUtil.stringSetToUriList(removedPorts)));
allStoragePorts.addAll(storagePorts);
List<Initiator> allInitiators = DataObjectUtils.iteratorToList(_dbClient.queryIterativeObjects(Initiator.class, StringSetUtil.stringSetToUriList(removedInitiators)));
allInitiators.addAll(initiators);
// Make a copy of the zoning mask - Zones have already been removed for removed initiators, put them back
// This zoning map will be used to do diff between old and new and to get zone references
StringSetMap allZonesMap = new StringSetMap();
StringSetMap tempMap = exportMask.getZoningMap() == null ? new StringSetMap() : exportMask.getZoningMap();
for (String key : tempMap.keySet()) {
// when the zoning map is removed prematurely, this ports set is empty but not null
if (removedInitiators.contains(key) && (tempMap.get(key) == null || tempMap.get(key).isEmpty())) {
// this was prematurely cleared, we will assume all ports
// were zoned to make sure we clean up all FCZoneReferences
allZonesMap.put(key, new StringSet(removedPorts));
if (exportMask.getStoragePorts() != null) {
allZonesMap.get(key).addAll(exportMask.getStoragePorts());
}
} else {
allZonesMap.put(key, new StringSet(tempMap.get(key)));
}
}
// get all the zone references that exist in the database for this export mask.
Map<String, List<FCZoneReference>> existingRefs = getZoneReferences(allZonesMap, allInitiators, allStoragePorts);
// initialize results collections
List<ZoneInfo> addedZoneInfos = new ArrayList<ZoneInfo>();
List<ZoneInfo> updatedZoneInfos = new ArrayList<ZoneInfo>();
List<String> removedZonesKeys = new ArrayList<String>();
// Compare old and new zones. Initialize some loop variables.
ZoneInfo zoneInfo = null;
String initId = null;
String portId = null;
if (exportMask.getZoningMap() == null) {
exportMask.setZoningMap(new StringSetMap());
}
for (Entry<String, ZoneInfo> entry : zoneInfoMap.entrySet()) {
zoneInfo = entry.getValue();
initId = zoneInfo.getInitiatorId();
portId = zoneInfo.getPortId();
if (exportMask.getZoningMap().containsKey(initId) && exportMask.getZoningMap().get(initId).contains(portId)) {
_log.debug("Zoning between initiator {} and port {} did not change", zoneInfo.getInitiatorWwn(), zoneInfo.getPortWwn());
// This is accounted for, let's remove it from our diff map
allZonesMap.remove(initId, portId);
// add the zone info so that it can be updated for changes like zone name change
updatedZoneInfos.add(zoneInfo);
} else {
_log.info("New zone was found between initiator {} and port {} and will be added", zoneInfo.getInitiatorWwn(), zoneInfo.getPortWwn());
// sometimes zones have more than one initiator or port
if (exportMask.hasExistingInitiator(zoneInfo.getInitiatorWwn())) {
// This is a new entry, add it to the zoning map
exportMask.getZoningMap().put(initId, portId);
// add it to the results so that the appropriate FCZoneReferences are added
addedZoneInfos.add(zoneInfo);
}
// This zone is not expected to be in the diff map, but try anyway
allZonesMap.remove(initId, portId);
}
}
// If anything is remaining zones in the diff zoning map, these were removed in the network system
Initiator initiator = null;
StoragePort port = null;
for (String key : allZonesMap.keySet()) {
initiator = DataObjectUtils.findInCollection(allInitiators, key);
if (allZonesMap.get(key) != null && !allZonesMap.get(key).isEmpty()) {
for (String val : allZonesMap.get(key)) {
port = DataObjectUtils.findInCollection(allStoragePorts, val);
_log.info("Zone between initiator {} and port {} was removed from the network system" + " or no longer belongs to this mask.", key, val);
if (port == null || initiator == null) {
// the port or initiator were removed at some point
exportMask.getZoningMap().remove(key, val);
_log.info("Removed zoningMap entry between initiator {} and port {} because " + "the port and/or the initiator were removed from the mask", key, val);
} else if (removedInitiators.contains(key) || removedPorts.contains(val)) {
// the port or initiator were removed, remove the zone map entry
exportMask.getZoningMap().remove(key, val);
_log.info("Removed zoningMap entry between initiator {} and port {} because " + "the port and/or the initiator were removed from the mask", initiator.getInitiatorPort(), port.getPortNetworkId());
} else if (exportMask.hasExistingInitiator(WWNUtility.getUpperWWNWithNoColons(initiator.getInitiatorPort()))) {
exportMask.getZoningMap().remove(key, val);
_log.info("Removed zoningMap entry between initiator {} and port {} because " + "this was a brownfield zone for a brownfield initiator", initiator.getInitiatorPort(), port.getPortNetworkId());
} else {
_log.info("The zone between initiator {} and port {} was removed from " + " the network system but the zoningMap entry will be kept because it was" + " a ViPR initiator-port assignment", initiator.getInitiatorPort(), port.getPortNetworkId());
}
if (port != null && initiator != null) {
removedZonesKeys.add(FCZoneReference.makeEndpointsKey(initiator.getInitiatorPort(), port.getPortNetworkId()));
}
}
}
}
// get all the existing zone references from the database, these are
refreshFCZoneReferences(exportMask, existingRefs, addedZoneInfos, updatedZoneInfos, removedZonesKeys);
if (persist) {
_dbClient.updateAndReindexObject(exportMask);
}
_log.info("Changed zones for export mask {} to {}. \nRefreshing zones took {} ms", new Object[] { exportMask.getMaskName(), exportMask.getZoningMap(), (System.currentTimeMillis() - start) });
} catch (Exception ex) {
_log.error("An exception occurred while updating zoning map for export mask {} with message {}", new Object[] { exportMask.getMaskName(), ex.getMessage() }, ex);
}
}
Aggregations