use of com.emc.storageos.networkcontroller.NetworkFCZoneInfo in project coprhd-controller by CoprHD.
the class NetworkDeviceController method zoneRollback.
/**
* Rollback any of the zoning operations.
*
* @param exportGroupURI
* -- The ExportGroup URI
* @param contextKey
* -- The context which indicates what zones were configured on the device.
* @param taskId
* -- String task identifier for WorkflowTaskCompleter.
* @return
* @throws DeviceControllerException
*/
public boolean zoneRollback(URI exportGroupURI, String contextKey, String taskId) throws DeviceControllerException {
TaskCompleter taskCompleter = null;
try {
NetworkFCContext context = (NetworkFCContext) WorkflowService.getInstance().loadStepData(contextKey);
if (context == null) {
_log.warn("No zone rollback information for Step: " + contextKey + " , Export Group: " + exportGroupURI.toString() + ", and Task: " + taskId + ". The zoning step either did not complete or encountered an error.");
WorkflowStepCompleter.stepSucceded(taskId);
return true;
}
logZones(context.getZoneInfos());
WorkflowStepCompleter.stepExecuting(taskId);
_log.info("Beginning zone rollback");
_log.info("context.isAddingZones -{}", context.isAddingZones());
// Determine what needs to be rolled back.
List<NetworkFCZoneInfo> lastReferenceZoneInfo = new ArrayList<NetworkFCZoneInfo>();
List<NetworkFCZoneInfo> rollbackList = new ArrayList<NetworkFCZoneInfo>();
for (NetworkFCZoneInfo info : context.getZoneInfos()) {
if (info.canBeRolledBack()) {
// We should not blindly set last reference to true, removed code which does that earlier.
rollbackList.add(info);
} else {
// Even though we cannot rollback the zone (because we didn't create it, it previously existed,
// must remove the FCZoneReference that we created.
deleteFCZoneReference(info);
}
}
// Update the zone infos with the correct lastRef setting for those zones that can be rolled back
_networkScheduler.determineIfLastZoneReferences(rollbackList);
taskCompleter = new ZoneReferencesRemoveCompleter(NetworkUtil.getFCZoneReferences(rollbackList), context.isAddingZones(), taskId);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_020);
// Changed this parameter to true, so that the last reference validation runs all the time in placeZones()
BiosCommandResult result = addRemoveZones(exportGroupURI, rollbackList, true);
InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_021);
if (result.isCommandSuccess() && !lastReferenceZoneInfo.isEmpty()) {
_log.info("There seems to be last reference zones that were removed, clean those zones from the zoning map.");
updateZoningMap(lastReferenceZoneInfo, exportGroupURI, null);
}
completeWorkflowState(taskCompleter, taskId, "ZoneRollback", result, null);
return result.isCommandSuccess();
} catch (Exception ex) {
_log.error("Exception occurred while doing zone rollback", ex);
ServiceError svcError = NetworkDeviceControllerException.errors.zoneRollbackFailedExc(exportGroupURI.toString(), ex);
taskCompleter.error(_dbClient, svcError);
WorkflowStepCompleter.stepFailed(taskId, svcError);
return false;
}
}
use of com.emc.storageos.networkcontroller.NetworkFCZoneInfo in project coprhd-controller by CoprHD.
the class NetworkDeviceController method addRemoveZones.
/**
* Adds/removes a bunch of zones based on their NetworkFCZoneInfo structures.
* They are split into groups and subgroups, first by the device/networkSystem used for zoning, and then by the fabricId to be zoned.
* Then each subgroup is processed separately.
*
* @param exportGroupUri
* @param fabricInfos
* @return BiosCommandResult
* @throws ControllerException
*/
public BiosCommandResult addRemoveZones(URI exportGroupUri, List<NetworkFCZoneInfo> fabricInfos, boolean doRemove) throws ControllerException {
// Group the fabric infos together based on which devices should zone them.
Map<URI, NetworkSystem> networkSystemId2NetworkSystem = new HashMap<URI, NetworkSystem>();
Map<URI, List<NetworkFCZoneInfo>> networkSystemId2NetworkFabricInfos = new HashMap<>();
for (NetworkFCZoneInfo fabricInfo : fabricInfos) {
URI networkSystemId = fabricInfo.getNetworkDeviceId();
URI altNetworkSystemId = fabricInfo.getAltNetworkDeviceId();
NetworkSystem networkSystem = null;
// Determine network system. The network system structures are cached in networkSystemId2NetworkSystem
networkSystem = networkSystemId2NetworkSystem.get(networkSystemId);
if (networkSystem == null) {
networkSystem = getNetworkSystemObject(networkSystemId);
if (networkSystem != null && networkSystem.getInactive() == false) {
networkSystemId2NetworkSystem.put(networkSystemId, networkSystem);
} else if (altNetworkSystemId != null) {
networkSystem = networkSystemId2NetworkSystem.get(altNetworkSystemId);
if (networkSystem == null) {
networkSystem = getNetworkSystemObject(altNetworkSystemId);
if (networkSystem != null && networkSystem.getInactive() == false) {
networkSystemId2NetworkSystem.put(altNetworkSystemId, networkSystem);
}
}
}
}
if (networkSystem == null) {
throw NetworkDeviceControllerException.exceptions.addRemoveZonesFailedNoDev(networkSystemId.toString());
}
List<NetworkFCZoneInfo> finfos = networkSystemId2NetworkFabricInfos.get(networkSystem.getId());
if (finfos == null) {
finfos = new ArrayList<NetworkFCZoneInfo>();
networkSystemId2NetworkFabricInfos.put(networkSystem.getId(), finfos);
}
finfos.add(fabricInfo);
}
// Now loop through each network system, splitting the collection of fabric infos by fabric ID/WWN.
StringBuilder messageBuffer = new StringBuilder();
for (URI deviceId : networkSystemId2NetworkFabricInfos.keySet()) {
NetworkSystem device = networkSystemId2NetworkSystem.get(deviceId);
Map<String, List<NetworkFCZoneInfo>> fabric2FabricInfos = new HashMap<String, List<NetworkFCZoneInfo>>();
Map<String, NetworkLite> fabricId2Network = new HashMap<String, NetworkLite>();
List<NetworkFCZoneInfo> finfos = networkSystemId2NetworkFabricInfos.get(deviceId);
for (NetworkFCZoneInfo fabricInfo : finfos) {
String fabricId = fabricInfo.getFabricId();
String fabricWwn = fabricInfo.getFabricWwn();
String key = (fabricWwn != null) ? fabricWwn : fabricId;
updateAltDeviceid(fabricInfo, fabricId, fabricWwn, key, fabricId2Network);
List<NetworkFCZoneInfo> singleFabricInfos = fabric2FabricInfos.get(key);
if (singleFabricInfos == null) {
singleFabricInfos = new ArrayList<NetworkFCZoneInfo>();
fabric2FabricInfos.put(key, singleFabricInfos);
}
singleFabricInfos.add(fabricInfo);
}
// Now for each fabric, do the zoning.
for (String key : fabric2FabricInfos.keySet()) {
List<NetworkFCZoneInfo> singleFabricInfos = fabric2FabricInfos.get(key);
String fabricId = singleFabricInfos.get(0).getFabricId();
String fabricWwn = singleFabricInfos.get(0).getFabricWwn();
BiosCommandResult rslt = addRemoveZones(device, fabricId, fabricWwn, exportGroupUri, singleFabricInfos, doRemove, true);
if (messageBuffer.length() > 0) {
messageBuffer.append("; ");
}
messageBuffer.append(rslt.getMessage());
}
}
BiosCommandResult result = BiosCommandResult.createSuccessfulResult();
return result;
}
use of com.emc.storageos.networkcontroller.NetworkFCZoneInfo in project coprhd-controller by CoprHD.
the class NetworkDeviceController method generateExistingZoneWarningMessages.
/**
* Generating warning messages if there are any zoneInfos that won't be deleted because
* their existingZone value is true (and we are removing the last reference.)
* @param zoneInfos -- list of NetworkFCZoneInfo representingzones to be delete.
* @return -- Warning message text (may include information about multiple zones)
*/
private String generateExistingZoneWarningMessages(List<NetworkFCZoneInfo> zoneInfos) {
StringBuilder buf = new StringBuilder();
StringSet zoneNames = new StringSet();
;
// Issue warning for zones that are lastRef but existing, as they won't be removed.
for (NetworkFCZoneInfo zoneInfo : zoneInfos) {
if (zoneInfo.isLastReference() && zoneInfo.isExistingZone()) {
zoneNames.add(zoneInfo.getZoneName());
}
}
if (!zoneNames.isEmpty()) {
buf.append("Zones which will not be deleted because they may be used externally: ");
buf.append(com.google.common.base.Joiner.on(' ').join(zoneNames));
}
return buf.toString();
}
use of com.emc.storageos.networkcontroller.NetworkFCZoneInfo in project coprhd-controller by CoprHD.
the class NetworkDeviceController method addRemoveZones.
/**
* Add/remove a group of zones as given by their NetworkFabricInfo structures.
* ALL fabricInfos must be using the same NetworkDevice, and the same fabricId. There is a higher level
* subroutine to split complex requests into sets of requests with the same NetworkDevice and fabricId.
*
* @param networkSystem NetworkDevice
* @param fabricId String
* @param exportGroupUri The ExportGroup URI. Used for reference counting.
* @param fabricInfos - Describe each zone.
* @param activateZones - activate active zoneset after zones change
* @param retryAltNetworkDevice - a boolean to indicate if re-try to be done.
* This is to stop this function from running again after the alternate
* system is retried once.
* @return BiosCommandResult
* @throws ControllerException
*/
private BiosCommandResult addRemoveZones(NetworkSystem networkSystem, String fabricId, String fabricWwn, URI exportGroupUri, List<NetworkFCZoneInfo> fabricInfos, boolean doRemove, boolean retryAltNetworkDevice) throws ControllerException {
BiosCommandResult result = null;
String taskId = UUID.randomUUID().toString();
List<Zone> zones = new ArrayList<Zone>();
// Make the zone operations. Don't make the same zone more than once,
// as determined by its key. The same zone shows up multiple times because it
// must be recorded for each volume in the FCZoneReference table.
HashSet<String> keySet = new HashSet<String>();
for (NetworkFCZoneInfo fabricInfo : fabricInfos) {
String key = fabricInfo.makeEndpointsKey();
if (false == keySet.contains(key)) {
keySet.add(key);
// neither create nor delete zones found on the switch
if (fabricInfo.isExistingZone()) {
_log.info("Zone {} will not be created or removed on {}, as it is not vipr created. ", fabricInfo.getZoneName(), fabricInfo.toString());
// neither create nor delete zones found on the switch
continue;
}
// Don't actually remove the zone if it's not the last reference
if (doRemove && !fabricInfo._isLastReference) {
_log.info("Zone {} will not be removed on {}, as still the zone is used to expose other volumes in export groups ", fabricInfo.getZoneName(), fabricInfo.toString());
continue;
}
Zone zone = new Zone(fabricInfo.getZoneName());
for (String address : fabricInfo.getEndPoints()) {
ZoneMember member = new ZoneMember(address, ConnectivityMemberType.WWPN);
zone.getMembers().add(member);
}
zones.add(zone);
}
}
// Get the network device reference for the type of network device managed
// by the controller.
NetworkSystemDevice networkDevice = getDevice(networkSystem.getSystemType());
if (networkDevice == null) {
throw NetworkDeviceControllerException.exceptions.addRemoveZonesFailedNull(networkSystem.getSystemType());
}
// Lock to prevent concurrent operations on the same VSAN / FABRIC.
InterProcessLock fabricLock = NetworkFabricLocker.lockFabric(fabricId, _coordinator);
try {
if (doRemove) {
/* Removing zones */
result = networkDevice.removeZones(networkSystem, zones, fabricId, fabricWwn, true);
if (result.isCommandSuccess()) {
for (NetworkFCZoneInfo fabricInfo : fabricInfos) {
String refKey = fabricInfo.getZoneName() + " " + fabricInfo.getFcZoneReferenceId().toString();
try {
FCZoneReference ref = deleteFCZoneReference(fabricInfo);
if (ref != null && !zones.isEmpty()) {
recordZoneEvent(ref, OperationTypeEnum.REMOVE_SAN_ZONE.name(), OperationTypeEnum.REMOVE_SAN_ZONE.getDescription());
}
} catch (DatabaseException ex) {
_log.error("Could not delete FCZoneReference: " + refKey);
}
}
}
} else {
/* Adding zones */
_log.debug("Adding zones on network system {} ", networkSystem.getNativeGuid());
result = networkDevice.addZones(networkSystem, zones, fabricId, fabricWwn, true);
if (result.isCommandSuccess()) {
for (NetworkFCZoneInfo fabricInfo : fabricInfos) {
String refKey = fabricInfo.getZoneName() + " " + fabricInfo.getVolumeId().toString();
try {
String[] newOrExisting = new String[1];
FCZoneReference ref = addZoneReference(exportGroupUri, fabricInfo, newOrExisting);
// this is needed for rollback
fabricInfo.setFcZoneReferenceId(ref.getId());
_log.info(String.format("%s FCZoneReference key: %s volume %s group %s", newOrExisting[0], ref.getPwwnKey(), ref.getVolumeUri(), exportGroupUri));
if (!zones.isEmpty()) {
recordZoneEvent(ref, OperationTypeEnum.ADD_SAN_ZONE.name(), OperationTypeEnum.ADD_SAN_ZONE.getDescription());
}
} catch (DatabaseException ex) {
_log.error("Could not persist FCZoneReference: " + refKey);
}
}
}
}
// Update the FCZoneInfo structures if we changed device state for rollback.
Map<String, String> map = (Map<String, String>) result.getObjectList().get(0);
for (NetworkFCZoneInfo info : fabricInfos) {
if (NetworkSystemDevice.SUCCESS.equals(map.get(info.getZoneName()))) {
info.setCanBeRolledBack(true);
} else {
info.setCanBeRolledBack(false);
}
}
if (!result.isCommandSuccess()) {
ServiceError serviceError = NetworkDeviceControllerException.errors.addRemoveZonesFailed(networkSystem.getSystemType());
setStatus(ExportGroup.class, exportGroupUri, taskId, false, serviceError);
} else {
setStatus(ExportGroup.class, exportGroupUri, taskId, true, null);
}
return result;
} catch (ControllerException ex) {
String operation = doRemove ? "Remove Zones" : "Add Zones";
_log.info(String.format("waiting for 2 min before retrying %s with alternate device", operation));
try {
Thread.sleep(1000 * 120);
} catch (InterruptedException e) {
_log.warn("Thread sleep interrupted. Allowing to continue without sleep");
}
NetworkFCZoneInfo fabricInfo = fabricInfos.get(0);
URI primaryUri = fabricInfo.getNetworkDeviceId();
URI altUri = fabricInfo.getAltNetworkDeviceId();
// If we took an error, attempt a retry with an alternate device if possible.
if (altUri != null && retryAltNetworkDevice) {
NetworkFabricLocker.unlockFabric(fabricId, fabricLock);
fabricLock = null;
_log.error("Zone operation failed using device: " + primaryUri + " retrying with alternate device: " + altUri);
fabricInfo.setNetworkDeviceId(altUri);
networkSystem = getNetworkSystemObject(altUri);
return addRemoveZones(networkSystem, fabricId, fabricWwn, exportGroupUri, fabricInfos, doRemove, false);
} else {
if (result != null) {
if (!result.isCommandSuccess()) {
ServiceError serviceError = NetworkDeviceControllerException.errors.addRemoveZonesFailed(networkSystem.getSystemType());
setStatus(ExportGroup.class, exportGroupUri, taskId, false, serviceError);
} else {
setStatus(ExportGroup.class, exportGroupUri, taskId, true, null);
}
}
throw ex;
}
} finally {
NetworkFabricLocker.unlockFabric(fabricId, fabricLock);
}
}
use of com.emc.storageos.networkcontroller.NetworkFCZoneInfo in project coprhd-controller by CoprHD.
the class NetworkDeviceController method updateZoningMap.
/**
* This method updates zoning map. This will mostly be called when volume(s) is/are removed
* from the ExportMask which is shared across two/more varrays and varrays do not have same
* storage ports which results in creating zoning based on the ports in the varray.
*
* lastReferenceZoneInfo contains the zones that were removed from the device,
* according to this if there is initiator in the zoningMap with just one storage port
* for which zone is removed then that entry is removed from the zoningMap.
* If initiator has more than one storage port in the zoningMap for the initiator then
* only storage port for which zone is removed is removed from the zoning map.
* ExportMasks with ImmutableZoningMap set are skipped.
*
* @param lastReferenceZoneInfo list of NetworkFCZoneInfo for the zones that are removed.
* @param exportGroupURI reference to exportGroup
* @param exportMaskURIs list of reference to exportMask
*/
private void updateZoningMap(List<NetworkFCZoneInfo> lastReferenceZoneInfo, URI exportGroupURI, List<URI> exportMaskURIs) {
List<URI> emURIs = new ArrayList<URI>();
if (exportMaskURIs == null || exportMaskURIs.isEmpty()) {
ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
List<ExportMask> exportMasks = ExportMaskUtils.getExportMasks(_dbClient, exportGroup);
if (exportGroup != null && !exportMasks.isEmpty()) {
for (ExportMask mask : exportMasks) {
emURIs.add(mask.getId());
}
}
} else {
emURIs.addAll(exportMaskURIs);
}
for (URI emURI : emURIs) {
ExportMask exportMask = _dbClient.queryObject(ExportMask.class, emURI);
if (exportMask != null && !exportMask.getInactive() && !exportMask.fetchDeviceDataMapEntry(ExportMask.DeviceDataMapKeys.ImmutableZoningMap.name()).contains(Boolean.TRUE.toString())) {
for (NetworkFCZoneInfo zoneInfo : lastReferenceZoneInfo) {
StringSetMap existingZoningMap = exportMask.getZoningMap();
if (exportMask.getVolumes() == null) {
continue;
}
Set<String> exportMaskVolumes = exportMask.getVolumes().keySet();
if (existingZoningMap != null && zoneInfo.getVolumeId() != null && exportMaskVolumes.contains(zoneInfo.getVolumeId().toString()) && zoneInfo.getEndPoints().size() == 2) {
Initiator initiator = NetworkUtil.findInitiatorInDB(zoneInfo.getEndPoints().get(0), _dbClient);
List<StoragePort> storagePorts = NetworkUtil.findStoragePortsInDB(zoneInfo.getEndPoints().get(1), _dbClient);
for (StoragePort storagePort : storagePorts) {
if (initiator != null && storagePort != null) {
for (String initiatorId : existingZoningMap.keySet()) {
if (initiator.getId().toString().equals(initiatorId)) {
StringSet ports = existingZoningMap.get(initiatorId);
if (ports != null) {
if (ports.contains(storagePort.getId().toString())) {
ports.remove(storagePort.getId().toString());
if (ports.isEmpty()) {
exportMask.removeZoningMapEntry(initiatorId);
_log.info("Removing zoning map entry for initiator {}, in exportmask {}", initiatorId, emURI);
} else {
exportMask.addZoningMapEntry(initiatorId, ports);
_log.info("Removing storagePort " + storagePort.getId() + " from zoning map for initiator " + initiatorId + " in export mask " + emURI);
}
}
}
}
}
}
}
}
_dbClient.persistObject(exportMask);
}
}
}
}
Aggregations