use of com.emc.storageos.db.client.model.ZoneInfo 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);
}
}
use of com.emc.storageos.db.client.model.ZoneInfo in project coprhd-controller by CoprHD.
the class NetworkDeviceController method refreshFCZoneReferences.
/**
* Given the list of zone changes, the list of existing zone references for the initiators and ports,
* update the FCZoneReference instances in the database. This function ensures that the zone
* references updated are those of the export mask volumes.
*
* @param exportMask the export mask being refreshed
* @param existingRefs a map of zone-reference-key-to-zone-references for each initiator-port pair
* of the mask, including those that were removed. This list may contain zone references for
* volumes not in the export mask.
* @param addedZoneInfos the ZoneInfo instances of zones that were added in this refresh operation
* @param updatedZoneInfos the ZoneInfo instances of zones that were updated in this refresh operation
* @param removedZonesKeys the keys of the zones that were removed.
* @param userRemovedInitiators optional field can be null. List of user removed initiators for this refresh operation
*/
private void refreshFCZoneReferences(ExportMask exportMask, Map<String, List<FCZoneReference>> existingRefs, List<ZoneInfo> addedZoneInfos, List<ZoneInfo> updatedZoneInfos, List<String> removedZonesKeys, List<String> userRemovedInitiators) {
// get the export mask volumes and export groups because FCZoneReference are kept for each
Map<URI, Integer> exportMaskVolumes = StringMapUtil.stringMapToVolumeMap(exportMask.getVolumes());
List<ExportGroup> exportGroups = ExportUtils.getExportGroupsForMask(exportMask.getId(), _dbClient);
// start with removing references
List<FCZoneReference> temp = null;
List<FCZoneReference> refs = new ArrayList<FCZoneReference>();
for (String refKey : removedZonesKeys) {
temp = existingRefs.get(refKey);
if (temp == null) {
continue;
}
for (FCZoneReference ref : temp) {
for (ExportGroup exportGroup : exportGroups) {
if (exportGroup.getId().equals(ref.getGroupUri()) && exportGroup.hasBlockObject(ref.getVolumeUri()) && exportMaskVolumes.containsKey(ref.getVolumeUri())) /*
* &&
* ref.getExistingZone()
*/
{
if (isPartOfUserRemovedInitiator(ref, userRemovedInitiators)) {
_log.info("FCZoneReference {} for volume {} and exportGroup {} with userRemovedInitiators {} will not be deleted", new Object[] { ref.getPwwnKey(), ref.getVolumeUri(), ref.getGroupUri(), userRemovedInitiators });
} else {
_log.info("FCZoneReference {} for volume {} and exportGroup {} with userRemovedInitiators {} will be deleted", new Object[] { ref.getPwwnKey(), ref.getVolumeUri(), ref.getGroupUri(), userRemovedInitiators });
refs.add(ref);
}
}
}
}
}
_dbClient.markForDeletion(refs);
refs.clear();
// update zone references with new zone info in case the zone was renamed
for (ZoneInfo zoneInfo : updatedZoneInfos) {
String refKey = zoneInfo.getZoneReferenceKey();
temp = existingRefs.get(refKey);
if (temp == null) {
continue;
}
for (FCZoneReference ref : temp) {
for (ExportGroup exportGroup : exportGroups) {
if (exportGroup.getId().equals(ref.getGroupUri()) && exportGroup.hasBlockObject(ref.getVolumeUri()) && exportMaskVolumes.containsKey(ref.getVolumeUri())) {
// only update when there are changes to avoid unnecessary create/delete of indexes
if (zoneInfo.getZoneName() != null && !zoneInfo.getZoneName().equals(ref.getZoneName())) {
ref.setZoneName(zoneInfo.getZoneName());
ref.setExistingZone(true);
}
if (zoneInfo.getNetworkSystemId() != null && (ref.getNetworkSystemUri() == null || !zoneInfo.getNetworkSystemId().equals(ref.getNetworkSystemUri().toString()))) {
ref.setNetworkSystemUri(URI.create(zoneInfo.getNetworkSystemId()));
}
if (zoneInfo.getFabricId() != null && !zoneInfo.getFabricId().equals(ref.getFabricId())) {
ref.setFabricId(zoneInfo.getFabricId());
}
refs.add(ref);
}
}
}
}
_dbClient.updateAndReindexObject(refs);
refs.clear();
// Create zone references as needed, one per volume and export group
for (ZoneInfo zoneInfo : addedZoneInfos) {
for (URI volUri : exportMaskVolumes.keySet()) {
for (ExportGroup exportGroup : exportGroups) {
if (exportGroup.hasBlockObject(volUri)) {
// do I need to check duplicates?
refs.add(createFCZoneReference(zoneInfo, volUri, exportGroup));
_log.info("FCZoneReference {} for volume {} and exportGroup {} will be added", new Object[] { zoneInfo.getZoneReferenceKey(), volUri, exportGroup.getId() });
}
}
}
}
_dbClient.createObject(refs);
}
use of com.emc.storageos.db.client.model.ZoneInfo in project coprhd-controller by CoprHD.
the class ExportMaskUtils method getZoneMapFromZoneInfoMap.
/**
* Given zoneInfoMap stored in an UnManagedExportMask, create a zone map for the
* initiators in the list.
*
* @param zoneInfoMap zoneInfoMap stored from a UnManagedExportMask
* @param initiators a list of initiators for which the zone map should created
* @return a zone map of initiator-uri-to-list-of-ports-uris
*/
public static StringSetMap getZoneMapFromZoneInfoMap(ZoneInfoMap zoneInfoMap, List<Initiator> initiators) {
StringSetMap zoneMap = new StringSetMap();
if (zoneInfoMap != null && initiators != null) {
for (Initiator initiator : initiators) {
for (ZoneInfo info : zoneInfoMap.values()) {
if (info.getInitiatorId().equals(initiator.getId().toString())) {
zoneMap.put(initiator.getId().toString(), info.getPortId());
}
}
}
}
_log.info("getZoneMapFromZoneInfoMap created zone map {}", zoneMap);
return zoneMap;
}
use of com.emc.storageos.db.client.model.ZoneInfo in project coprhd-controller by CoprHD.
the class ExportMaskUtils method createFCZoneReferences.
/**
* Create FCZoneReference objects according to the list of zoneInfoMap.
* This is used for ingestion.
*
* The zones will be ingested as existingZone = false (allowing deletion of the zone when the last reference is removed)
* if all the following criteria are met:
* 1. The export mask being ingested must have no existing (non-vipr-created) volumes.
* 2. If the zone must not have more than two members (smartZone), as Vipr cannot yet manage smart zones.
* 3. The zone name that would be generated for the zone must be the same as the ingested zone's name, unless the
* controllersvc config variable controller_ingest_zones_with_non_vipr_name is set to true, bypassing the zone name check.
* 4. The zone must not be used in any other UnManagedExportMask (export mask which has not yet been ingested).
*
* @param volume the FCZoneReference volume
* @param exportGroup the FCZoneReference export group
* @param exportMask the ExportMask being ingested or initialized
* @param zoneInfoMap the zone info maps
* @param initiators the initiators
* @param updatedZoneReferences OUT parameter of zone references to be updated
* @param dbClient -- Database handle
* @return a list of FCZoneReference
*/
private static <T extends BlockObject> List<FCZoneReference> createFCZoneReferences(T volume, ExportGroup exportGroup, ExportMask exportMask, ZoneInfoMap zoneInfoMap, List<Initiator> initiators, List<FCZoneReference> updatedZoneReferences, DbClient dbClient) {
boolean bypassNameCheck = false;
if (coordinator == null) {
ApplicationContext context = AttributeMatcherFramework.getApplicationContext();
coordinator = (CoordinatorClient) context.getBean("coordinator");
}
bypassNameCheck = Boolean.valueOf(ControllerUtils.getPropertyValueFromCoordinator(coordinator, INGEST_ZONES_WITH_NON_VIPR_NAME));
List<FCZoneReference> createdRefs = new ArrayList<FCZoneReference>();
if (networkScheduler == null) {
ApplicationContext context = AttributeMatcherFramework.getApplicationContext();
networkScheduler = (NetworkScheduler) context.getBean("networkScheduler");
}
for (Initiator initiator : initiators) {
for (ZoneInfo info : zoneInfoMap.values()) {
if (info.getInitiatorId().equals(initiator.getId().toString())) {
Boolean hasExistingVolumes = exportMask.hasAnyExistingVolumes();
// Determine if the zone to be ingested has a compatible zone name.
Boolean lsanZone = networkScheduler.isLSANZone(info.getZoneName());
// Determine if the zone has more than two members. We can't currently manage smart zones fully.
Boolean smartZone = (info.getMemberCount() > 2);
_log.info(String.format("zone %s existingVolumes %s lsanZone %s smartZone %s", info.getZoneName(), hasExistingVolumes.toString(), lsanZone.toString(), smartZone.toString()));
String generatedZoneName = networkScheduler.nameZone(volume.getStorageController(), URI.create(info.getNetworkSystemId()), info.getInitiatorWwn(), info.getPortWwn(), info.getFabricId(), lsanZone);
_log.info(String.format("Zone name %s generated zone name %s", info.getZoneName(), generatedZoneName));
boolean usedInUnmanagedMasks = checkZoneUseInUnManagedExportMasks(exportMask.getMaskName(), info, dbClient);
boolean externalZone = hasExistingVolumes || (!bypassNameCheck && !generatedZoneName.equals(info.getZoneName())) || usedInUnmanagedMasks || smartZone;
if (!externalZone) {
// Find any existing zone references so they can be updated to fully managed (i.e. not existingZone)
List<FCZoneReference> existingZoneRefs = networkScheduler.getFCZoneReferencesForKey(info.getZoneReferenceKey());
for (FCZoneReference zoneRef : existingZoneRefs) {
// and the zoneRef URI is invalid, mark the zone reference for deletion as it is stale, and do not process it.
if (!exportGroup.hasBlockObject(zoneRef.getVolumeUri())) {
BlockObject blockObject = BlockObject.fetch(dbClient, zoneRef.getVolumeUri());
if (blockObject == null) {
_log.info(String.format("Deleting FCZoneReference %s which has invalid volume URI %s", zoneRef.getZoneName(), zoneRef.getVolumeUri()));
dbClient.markForDeletion(zoneRef);
continue;
}
}
// Update this reference to fully managed (existingZone = false)
zoneRef.setExistingZone(false);
updatedZoneReferences.add(zoneRef);
}
}
createdRefs.add(createFCZoneReference(info, initiator, volume, exportGroup, externalZone));
}
}
}
return createdRefs;
}
use of com.emc.storageos.db.client.model.ZoneInfo in project coprhd-controller by CoprHD.
the class ExternalDeviceUnManagedVolumeDiscoverer method updateZoningMap.
/**
* Updates zoning information in the unmanaged export mask for a given set of initiators and storage ports.
*
* @param mask unmanaged export [IN/OUT]
* @param initiators initiators for zone map [IN]
* @param storagePorts storage ports for zone map [IN]
*/
private void updateZoningMap(UnManagedExportMask mask, List<com.emc.storageos.db.client.model.Initiator> initiators, List<com.emc.storageos.db.client.model.StoragePort> storagePorts) {
ZoneInfoMap zoningMap = networkDeviceController.getInitiatorsZoneInfoMap(initiators, storagePorts);
for (ZoneInfo zoneInfo : zoningMap.values()) {
log.info("Found zone: {} for initiator {} and port {}", zoneInfo.getZoneName(), zoneInfo.getInitiatorWwn(), zoneInfo.getPortWwn());
}
mask.setZoningMap(zoningMap);
}
Aggregations