/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package com.emc.storageos.networkcontroller.impl.brocade; import java.lang.reflect.Method; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import javax.cim.CIMInstance; import javax.cim.CIMObjectPath; import javax.security.auth.Subject; import javax.wbem.WBEMException; import javax.wbem.client.PasswordCredential; import javax.wbem.client.UserPrincipal; import javax.wbem.client.WBEMClient; import javax.wbem.client.WBEMClientConstants; import javax.wbem.client.WBEMClientFactory; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.cimadapter.connections.cim.CimConstants; import com.emc.storageos.cimadapter.connections.cim.CimObjectPathCreator; import com.emc.storageos.coordinator.client.service.CoordinatorClient; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.FCEndpoint; import com.emc.storageos.db.client.model.NetworkSystem; import com.emc.storageos.exceptions.DeviceControllerException; import com.emc.storageos.networkcontroller.exceptions.NetworkDeviceControllerException; import com.emc.storageos.networkcontroller.impl.NetworkSystemDevice; import com.emc.storageos.networkcontroller.impl.NetworkSystemDeviceImpl; import com.emc.storageos.networkcontroller.impl.mds.Zone; import com.emc.storageos.networkcontroller.impl.mds.ZoneMember; import com.emc.storageos.networkcontroller.impl.mds.ZoneUpdate; import com.emc.storageos.networkcontroller.impl.mds.ZoneWwnAlias; import com.emc.storageos.networkcontroller.impl.mds.ZoneWwnAliasUpdate; import com.emc.storageos.networkcontroller.impl.mds.Zoneset; import com.emc.storageos.util.InvokeTestFailure; import com.emc.storageos.util.NetworkLite; import com.emc.storageos.util.NetworkUtil; import com.emc.storageos.volumecontroller.impl.BiosCommandResult; import com.emc.storageos.volumecontroller.impl.ControllerUtils; public class BrocadeNetworkSystemDevice extends NetworkSystemDeviceImpl implements NetworkSystemDevice { private static final Logger _log = LoggerFactory.getLogger(BrocadeNetworkSystemDevice.class); private static final int ZONE_NAME_MAX_LENGTH = 64; private DbClient _dbClient; private CoordinatorClient _coordinator; BrocadeNetworkSMIS _smisHelper = new BrocadeNetworkSMIS(); public void setDbClient(DbClient dbClient) { if (_dbClient == null) { _dbClient = dbClient; } } public void setCoordinator(CoordinatorClient coordinator) { if (_coordinator == null) { _coordinator = coordinator; } } @Override public BiosCommandResult doConnect(NetworkSystem network) { BiosCommandResult result = BiosCommandResult.createSuccessfulResult(); return result; } @Override public BiosCommandResult doDisconnect(NetworkSystem network) { BiosCommandResult result = BiosCommandResult.createSuccessfulResult(); return result; } @Override public List<FCEndpoint> getPortConnections(NetworkSystem network, Map<String, Set<String>> routedConnections) throws Exception { try { WBEMClient client = getNetworkDeviceClient(network); return _smisHelper.getPortConnections(client, routedConnections, discoverEndpointsByFabric()); } catch (WBEMException ex) { String exMsg = ex.getLocalizedMessage(); if (exMsg.equals("Unable to connect")) { exMsg = "Unable to connect on port " + network.getSmisPortNumber() + ", please check that the port is active"; } String msg = MessageFormat.format("Cannot get port connections for network device {0}: {1}", network.getLabel(), exMsg); _log.error(msg); throw NetworkDeviceControllerException.exceptions.getPortConnectionsFailed(network.getLabel(), exMsg, ex); } } @Override public Map<String, String> getFabricIdsMap(NetworkSystem network) throws Exception { try { WBEMClient client = getNetworkDeviceClient(network); return _smisHelper.getFabricIdsMap(client); } catch (WBEMException ex) { _log.error("Cannot get fabric ids map for network device " + network.getLabel() + ": " + ex.getLocalizedMessage()); throw ex; } } @Override public List<String> getFabricIds(NetworkSystem network) throws Exception { try { WBEMClient client = getNetworkDeviceClient(network); return _smisHelper.getFabricIds(client); } catch (WBEMException ex) { _log.error("Cannot get fabricIds for network device " + network.getLabel() + ": " + ex.getLocalizedMessage()); throw ex; } } @Override public List<Zoneset> getZonesets(NetworkSystem network, String fabricId, String fabricWwn, String zoneName, boolean excludeMembers, boolean excludeAliases) throws Exception { try { validateFabric(network, fabricWwn, fabricId); return _smisHelper.getZoneSets(getNetworkDeviceClient(network), fabricId, fabricWwn, zoneName, excludeMembers, excludeAliases); } catch (Exception ex) { _log.error("Cannot get zonesets for fabricId " + fabricId + " on network device " + network.getLabel() + ": " + ex.getLocalizedMessage()); throw ex; } } @Override public BiosCommandResult addZones(NetworkSystem networkSystem, List<Zone> zones, String fabricId, String fabricWwn, boolean activateZones) throws NetworkDeviceControllerException { BiosCommandResult result = null; // a zone-name-to-result map to hold the results for each zone Map<String, String> addZonesResults = new HashMap<String, String>(); try { validateFabric(networkSystem, fabricWwn, fabricId); Map<NetworkLite, List<Zone>> zonesPerFabric = getAllZonesForZones(zones, false, fabricId, fabricWwn); WBEMClient client = getNetworkDeviceClient(networkSystem); for (NetworkLite network : zonesPerFabric.keySet()) { addZonesResults.putAll(addZonesStrategy( client, zonesPerFabric.get(network), network.getNativeId(), NetworkUtil.getNetworkWwn(network), activateZones)); } _log.info(toMessage(addZonesResults)); result = getBiosCommandResult(addZonesResults); } catch (NetworkDeviceControllerException ex) { _log.error("Cannot add zones: " + ex.getLocalizedMessage()); throw ex; } return result; } /** * For a list of zones requested by clients, check is routing is needed and created * the required zone to support both use cases: switched and routed endpoints. For * switched endpoints the same list of zone is returned. For routed endpoints, * for each zone in the primary fabrics, an identical zone in the target fabrics * will also be created. * * @param zones the zones to be created or deleted. * * @return a map of zones to be created grouped by fabric. When the zone members * are in different fabrics (i.e. routed), there will be a zone to create in each * member's fabric */ private Map<NetworkLite, List<Zone>> getAllZonesForZones(List<Zone> zones, boolean delete, String fabricId, String fabricWwn) { Map<NetworkLite, List<Zone>> allZones = new HashMap<NetworkLite, List<Zone>>(); // we need to ensure that all endpoints belong to one network // or two networks that are routed to each other for (Zone zone : zones) { Map<ZoneMember, NetworkLite> epNetworks = getEndpointNetworks(zone, fabricId, fabricWwn); if (!epNetworks.isEmpty()) { Set<NetworkLite> networks = new HashSet<NetworkLite>(epNetworks.values()); if (networks.size() == 2) { // need to create zone for // ensure the other members can be routed as well NetworkLite network = networks.iterator().next(); for (ZoneMember member : epNetworks.keySet()) { if (network.getId().equals(epNetworks.get(member).getId()) || (network.hasRoutedNetworks( epNetworks.get(member).getId()))) { _log.info("Verified zone {} endpoints are connected", zone.getName()); } else { if (!delete) { // only error on create. For delete, always try. _log.info( "Cannot create zone {} because the member are found to be not connected", zone.getName()); throw NetworkDeviceControllerException.exceptions .zoneEndpointsNotConnected(zone.getName()); } } } // If this code is reached from the API test interface for creating // zones, the zone may not be properly named. if (!delete) { if (zone.getName() != null && !zone.getName().toLowerCase().startsWith("lsan_")) { String name = "lsan_" + (zone.getName() == null ? "" : zone.getName()); if (name.length() > ZONE_NAME_MAX_LENGTH) { name = name.substring(0, ZONE_NAME_MAX_LENGTH - 1); } zone.setName(name); } } } for (NetworkLite network : networks) { List<Zone> netZones = allZones.get(network); if (netZones == null) { netZones = new ArrayList<Zone>(); allZones.put(network, netZones); } netZones.add(zone); } } else if (delete) { // if delete zone does not have member or member that are not in end point list // include them anyway for deletion NetworkLite networkLite = NetworkUtil.getNetworkLiteByFabricId(fabricId, fabricWwn, _dbClient); if (networkLite != null) { List<Zone> zoneList = allZones.get(networkLite); if (zoneList == null) { zoneList = new ArrayList<Zone>(); allZones.put(networkLite, zoneList); } zoneList.add(zone); } } } return allZones; } /** * This is function is used at the time an 'add zone' request is received when we need * to decide if the zone request requires creating an LSAN zone or a regular zone. For * each member find the network the member is in. Note, zones can be created for WWNs * that are not logged into the switch, or for aliases. In this case, we assume only * regular zones will be created. * * @param zone the zone to be added. * @return A map of zoneMember-to-network */ private Map<ZoneMember, NetworkLite> getEndpointNetworks(Zone zone, String fabricId, String fabricWwn) { NetworkLite network = NetworkUtil.getNetworkLiteByFabricId(fabricId, fabricWwn, _dbClient); Map<ZoneMember, NetworkLite> epNetworks = new HashMap<ZoneMember, NetworkLite>(); NetworkLite loopNetwork = null; for (ZoneMember member : zone.getMembers()) { // TODO - At this time routed zones are supported for zones with WWN-type members. // For alias-type members, more investigation is needed. if (!StringUtils.isEmpty(member.getAddress())) { loopNetwork = NetworkUtil.getEndpointNetworkLite(member.getAddress(), _dbClient); } // If the zone member is not logged into any network or is an alias, then assume // it belongs to the request network. if (loopNetwork == null && network != null) { loopNetwork = network; } if (loopNetwork != null) { epNetworks.put(member, loopNetwork); } } return epNetworks; } public BiosCommandResult removeZones(NetworkSystem networkSystem, List<Zone> zones, String fabricId, String fabricWwn, boolean activateZones) throws NetworkDeviceControllerException { BiosCommandResult result = null; Map<String, String> removedZoneResults = new HashMap<String, String>(); try { validateFabric(networkSystem, fabricWwn, fabricId); Map<NetworkLite, List<Zone>> zonesPerFabric = getAllZonesForZones(zones, true, fabricId, fabricWwn); for (NetworkLite network : zonesPerFabric.keySet()) { WBEMClient client = getNetworkDeviceClient(networkSystem); removedZoneResults.putAll(removeZonesStrategy( client, zonesPerFabric.get(network), network.getNativeId(), NetworkUtil.getNetworkWwn(network), activateZones)); } result = getBiosCommandResult(removedZoneResults); _log.info("Remove zone results {}", toMessage(removedZoneResults)); } catch (NetworkDeviceControllerException ex) { _log.error("Cannot remove zones: " + ex.getLocalizedMessage()); throw ex; } return result; } private WBEMClient getNetworkDeviceClient(NetworkSystem network) throws NetworkDeviceControllerException { return getWBEMClient(network.getSmisProviderIP(), network .getSmisPortNumber().toString(), network.getSmisUserName(), network.getSmisPassword(), network.getSmisUseSSL()); } private WBEMClient getWBEMClient(String ipaddress, String smisport, String username, String password, boolean useSSL) throws NetworkDeviceControllerException { try { InvokeTestFailure.internalOnlyInvokeTestFailure(InvokeTestFailure.ARTIFICIAL_FAILURE_049); WBEMClient client = WBEMClientFactory .getClient(WBEMClientConstants.PROTOCOL_CIMXML); String protocol = useSSL ? CimConstants.SECURE_PROTOCOL : CimConstants.DEFAULT_PROTOCOL; CIMObjectPath path = CimObjectPathCreator.createInstance(protocol, ipaddress, smisport.toString(), BrocadeNetworkSMIS.getNamespace(), null, null); final Subject subject = new Subject(); subject.getPrincipals().add(new UserPrincipal(username)); subject.getPrivateCredentials().add( new PasswordCredential(password)); client.initialize(path, subject, new Locale[] { Locale.US }); return client; } catch (WBEMException ex) { _log.info("Failed to connect to Brocade at IP: " + ipaddress + " because: " + ex.getLocalizedMessage()); throw NetworkDeviceControllerException.exceptions.getWBEMClientFailed(ipaddress, ex); } } /** * This function creates one or more zones in the active zoneset. * * @param client * - the WBEMClient of the SMI-S provider * @param zones * - Zones to be created * @param fabricId * - the fabric where the zones will be created * @return a map that contains the outcome for each zone keyed by zone name * @throws NetworkDeviceControllerException */ public Map<String, String> addZonesStrategy(WBEMClient client, List<Zone> zones, String fabricId, String fabricWwn, boolean activateZones) throws NetworkDeviceControllerException { // a zone-name-to-result map to hold the results for each zone Map<String, String> addedZonesResult = new HashMap<String, String>(); if (zones.isEmpty()) { throw DeviceControllerException.exceptions.entityNullOrEmpty("zones"); } CIMInstance zoneServiceIns = null; try { _log.info("add zones started."); _log.info("Attempting to start a zoning session"); zoneServiceIns = _smisHelper.startSession(client, fabricId, fabricWwn); if (zoneServiceIns == null) { _log.info("Failed to start a zoning session."); throw NetworkDeviceControllerException.exceptions.startZoningSessionFailed(); } // First determine if there is an active zoneset. CIMObjectPath zonesetPath = null; CIMInstance activeZonesetIns = _smisHelper .getActiveZonesetInstance(client, fabricId, fabricWwn); // There is no active zoneset. So we'll throw an exception. if (activeZonesetIns == null) { _log.info("No active zoneset fabrics: " + fabricId); throw NetworkDeviceControllerException.exceptions.noActiveZonesetForFabric(fabricId); } else { // For Brocade, the active zoneset is a copy of a configuration zoneset. To make a change, we // need to modify the configuration zoneset and activate it. Get the configuration zoneset. zonesetPath = _smisHelper.getShadowZonesetPath(client, fabricId, fabricWwn, activeZonesetIns); } for (Zone zone : zones) { try { if (checkAndCreateZone(client, zoneServiceIns, fabricId, fabricWwn, zonesetPath, zone, activateZones)) { addedZonesResult.put(zone.getName(), SUCCESS); } else { addedZonesResult.put(zone.getName(), NO_CHANGE); } } catch (Exception ex) { addedZonesResult.put(zone.getName(), ERROR + ": " + ex.getMessage()); handleZonesStrategyException(ex, activateZones); } } _log.info("Attempting to close zoning session."); // If there are no zones that need to be added, just close the session without commit and return. if (!hasResult(addedZonesResult, SUCCESS)) { _log.info("No zones were added. Closing the session with no commit"); if (!_smisHelper.endSession(client, zoneServiceIns, false)) { _log.info("Failed to terminate zoning session. Ignoring as session may have expired."); } return addedZonesResult; } else { // if zones were added, commit them before ending the session if (_smisHelper.endSession(client, zoneServiceIns, true)) { if (activateZones) { _log.info("Attempting to activate the zoneset."); if (_smisHelper.activateZoneSet(client, zoneServiceIns, zonesetPath, true)) { _log.info("The zoneset was activated succcessfully."); } else { _log.info("Failed to activate the zoneset"); } } } else { throw NetworkDeviceControllerException.exceptions.addZonesStrategyFailedZoneCommit(); } } _log.info("Add zone completed successfully."); } catch (Exception e1) { try { if (zoneServiceIns != null) { _log.info("Attempting to terminate zoning session."); _smisHelper.endSession(client, zoneServiceIns, false); } } catch (WBEMException e) { _log.error("Failed to terminate zoning session." + e.getLocalizedMessage(), e); } _log.error("Failed to create zones: " + e1.getLocalizedMessage(), e1); throw NetworkDeviceControllerException.exceptions.addZonesStrategyFailed(e1); } return addedZonesResult; } /** * Checks if a zone with the same name already exists before the zone is created. The * rules for creating a zone are: * <ul> * <li>If an active zone with the same name exists, ensure that all the desired members are in the zone. If this is true, consider the * zone created. If not, error because the application is not going to modify an existing zone.</li> * <li>If an inactive zone with the same name exists, delete the inactive zone and then create the new one.</li> * </ul> * This function assumes the zoning session is already acquired. * * @param client an instance of the SMI client * @param zoneServiceIns the instance of SMI zoneServices * @param fabricId the fabric id where the zone should created * @param fabricWwn the fabric WWN where the zone should created * @param zonesetPath the SMI path of the active zoneset for the fabric * @param zone the zone to be created * @return a boolean to indicated if a zone was created or not. * @throws WBEMException */ private boolean checkAndCreateZone(WBEMClient client, CIMInstance zoneServiceIns, String fabricId, String fabricWwn, CIMObjectPath zonesetPath, Zone zone, boolean activateZones) throws WBEMException { boolean added = false; _log.info("Starting create zone with name " + zone.getName()); // check if an active zone with the same name exists Zone zoneInFabric = _smisHelper.getZone(client, zone.getName(), fabricWwn, true, true, true); if (zoneInFabric != null) { _log.info("Found an active zone with the name " + zone.getName()); // I have a active zone with the same name but it does not have all the members we // need - at this time we're not modifying zones that already exist // and this one cannot be used without adding the missing members, so error if (!sameMembers(zoneInFabric, zone)) { throw NetworkDeviceControllerException.exceptions.activeZoneWithSameNameExists(zone.getName()); } } else { // check if an inactive zone with the same name exists zoneInFabric = _smisHelper.getZone(client, zone.getName(), fabricWwn, false, true, true); if (zoneInFabric != null) { _log.info("Found an inactive zone with the name " + zone.getName()); if (activateZones) { // This is the export path - delete the zone we will create the new one removeZone(client, fabricId, fabricWwn, zoneInFabric); // create the new zone createZone(client, zoneServiceIns, fabricId, fabricWwn, zonesetPath, zone); added = true; } else { // This is the API path - Error and let the caller provide the right input throw NetworkDeviceControllerException.exceptions.inactiveZoneWithSameNameExists(zone.getName()); } } else { // create the new zone added = createZone(client, zoneServiceIns, fabricId, fabricWwn, zonesetPath, zone); } } return added; } /** * Creates the zone in the fabric's active zoneset * * @param client an instance of the SMI client * @param zoneServiceIns the instance of SMI zoneServices * @param fabricId the fabric id where the zone should created * @param fabricWwn the fabric WWN where the zone should created * @param zonesetPath the SMI path of the active zoneset for the fabric * @param zone the zone to be created * @return a boolean to indicated if a zone was created or not. * @throws WBEMException */ private boolean createZone(WBEMClient client, CIMInstance zoneServiceIns, String fabricId, String fabricWwn, CIMObjectPath zonesetPath, Zone zone) throws WBEMException { _log.info("Creating a new zone " + zone.getName()); CIMObjectPath zonePath = _smisHelper.addZone(client, zoneServiceIns, zonesetPath, zone.getName(), fabricId, fabricWwn); if (zonePath != null) { boolean success = false; String name = null; for (ZoneMember member : zone.getMembers()) { name = member.getAlias() == null ? member.getAddress() : member.getAlias(); _log.info("Creating zone member: " + name + " zone: " + zone.getName()); success = _smisHelper.addZoneOrAliasMember(client, zoneServiceIns, fabricWwn, zonePath, name); if (!success) { _log.info("Failed to create memeber " + name + " for zone : " + zone.getName()); throw NetworkDeviceControllerException.exceptions.addZonesMemberFailedPath(zone.getName(), name); } } } else { _log.info("Failed to create zone : " + zone.getName()); throw NetworkDeviceControllerException.exceptions.addZonesStrategyFailedPath(); } return true; } /** * Remove a zone from the network system * * @param client an instance of the SMI client * @param fabricId the if of the zone's fabric * @param fabricWwn the WWN of the zone's fabric * @param zone the zone to be deleted. It must contain the SMI object path * @throws WBEMException */ private void removeZone(WBEMClient client, String fabricId, String fabricWwn, Zone zone) throws WBEMException { _log.info("Removing zone: " + zone.getName() + " for fabric: " + fabricId == null ? fabricWwn : fabricId); _smisHelper.removeZone(client, zone); } /** * This function removed one or more zones from the active zoneset. This function will not * error if a zone to be removed was not found. * <p> * Removing zones typical flow is: * <ol> * <li>find the zones that can be deleted</li> * <li>get the session lock</li> * <li>delete the zones</li> * <li>commit which releases the lock</li> * <li>activate if requested</li> * </ol> * This flow is different when we're removing the last zones in a zoneset. If the zoneset becomes empty, it needs to be removed too or * commit would fail. In order to remove the zoneset, it has to first be deactivated. The flow for removing the last zones in a zoneset * is * <ol> * <li>find the zones that can be deleted</li> * <li>deactivate the zoneset</li> * <li>get the session lock</li> * <li>delete the zones</li> * <li>delete the zoneset</li> * <li>commit which releases the lock</li> * </ol> * * @param client an instance of the SMI client * @param zones the list if zones to be deleted. * @param fabricId the id of the fabric where the zones will be removed * @param activateZones a boolean that indicates if immediate activation is requested. * @return a map that contains the outcome for each zone keyed by zone name * @throws NetworkDeviceControllerException */ public Map<String, String> removeZonesStrategy(WBEMClient client, List<Zone> zones, String fabricId, String fabricWwn, boolean activateZones) throws NetworkDeviceControllerException { long start = System.currentTimeMillis(); // a zone-name-to-result map to hold the results for each zone Map<String, String> removedZoneResults = new HashMap<String, String>(); CIMInstance zoneServiceIns = null; boolean wasDeactivated = false; CIMObjectPath shadowZonsetPath = null; boolean empty = false; try { _log.info("Remove zones started."); zoneServiceIns = _smisHelper.getZoneServiceInstance(client, fabricId, fabricWwn); if (zoneServiceIns == null) { _log.info("Failed to get zoning service."); throw NetworkDeviceControllerException.exceptions.removeZonesStrategyFailedSvc(); } // get active zoneset. CIMInstance activeZonesetIns = _smisHelper .getActiveZonesetInstance(client, fabricId, fabricWwn); if (activeZonesetIns == null) { String defaultZonesetName = getDefaultZonesetName(fabricId); // if no active zone set, get pending default active zone set activeZonesetIns = _smisHelper.getZoneset(client, fabricId, fabricWwn, defaultZonesetName); if (activeZonesetIns == null) { _log.warn("No active/default zoneset found: " + defaultZonesetName); throw NetworkDeviceControllerException.exceptions.noActiveZonesetForFabric(fabricId); } } // The actual work should be done on an inactive shadowZonsetPath = _smisHelper.getShadowZonesetPath(client, fabricId, fabricWwn, activeZonesetIns); Map<String, Zone> zonesInFabric = _smisHelper.getZones(client, getZoneNames(zones), fabricWwn, false, true, true); // Find the set of zones to be actually deleted. // We don't attempt to delete zones that are already gone. // And we don't delete zones that Bourne didn't create. List<Zone> zonesToBeDeleted = getZonesToBeDeleted(zones, zonesInFabric.values(), new Integer[1], removedZoneResults); // check if we need to deactivate if (!zonesToBeDeleted.isEmpty()) { empty = !_smisHelper.zonesetHasMore(client, shadowZonsetPath, zonesToBeDeleted.size()); if (empty) { _log.info("All zones will be removed so deactivate the zoneset"); _log.info("Attempting to deactivate the zoneset."); wasDeactivated = _smisHelper.activateZoneSet(client, zoneServiceIns, activeZonesetIns.getObjectPath(), false); } // now start removing zones _log.info("Attempting to start a zoning session"); zoneServiceIns = _smisHelper.startSession(client, fabricId, fabricWwn); for (Zone curZone : zonesToBeDeleted) { try { _log.info("Removing zone: " + curZone.getName() + " fabric: " + fabricId); _smisHelper.removeZone(client, curZone); removedZoneResults.put(curZone.getName(), SUCCESS); } catch (Exception ex) { removedZoneResults.put(curZone.getName(), ERROR + " : " + ex.getMessage()); handleZonesStrategyException(ex, activateZones); } } // get the current state of the zoneset to make sure it is indeed empty empty = _smisHelper.isEmptyZoneset(client, shadowZonsetPath); if (empty) { client.deleteInstance(shadowZonsetPath); } } // first close the session, commit if we have successful deletes, otherwise rollback _log.info("Attempting to close zoning session."); if (_smisHelper.endSession(client, zoneServiceIns, hasResult(removedZoneResults, SUCCESS))) { // last activate/deactivate as needed // we want to activate if the zoneset is not empty and we either has deactivated it or // we actually deleted some zones and the caller requested re-activation. boolean shouldActivate = ((activateZones && hasResult(removedZoneResults, SUCCESS)) || wasDeactivated) && !empty; if (shouldActivate) { _log.info("Attempting to activate the zoneset."); _smisHelper.activateZoneSet(client, zoneServiceIns, shadowZonsetPath, true); } } else { if (hasResult(removedZoneResults, SUCCESS)) { // only throw an exception if we were trying to commit changes throw NetworkDeviceControllerException.exceptions.removeZonesStrategyFailedCommit(); } else { _log.info("Failed to terminate zoning session. Ignoring as the session may have expired."); } } _log.info("Remove zone completed successfully and took " + (System.currentTimeMillis() - start)); return removedZoneResults; } catch (Exception e1) { try { if (zoneServiceIns != null) { _log.info("Attempting to terminate zoning session."); _smisHelper.endSession(client, zoneServiceIns, false); if (shadowZonsetPath != null && wasDeactivated) { _log.info("Attempting to re-activate the zoneset because it was deactivated earlier."); _smisHelper.activateZoneSet(client, zoneServiceIns, shadowZonsetPath, true); } } } catch (Exception ex) { _log.error("Failed terminate the zoning session and to reactivate the zoneset."); } _log.error("Failed to remove zones " + e1.getMessage()); throw NetworkDeviceControllerException.exceptions.removeZonesStrategyFailed(e1); } } @Override public String getVersion(NetworkSystem network) throws Exception { try { WBEMClient client = getNetworkDeviceClient(network); return _smisHelper.getVersion(client); } catch (WBEMException ex) { String exMsg = ex.getLocalizedMessage(); if ((exMsg != null) && exMsg.equals("Unable to connect")) { exMsg = "Unable to connect to device " + network.getLabel() + ": Unable to connect to ip " + network.getIpAddress() + " on port " + network.getSmisPortNumber(); } String msg = MessageFormat.format("Failed to get version: {0}", exMsg); _log.error(msg); throw NetworkDeviceControllerException.exceptions.getVersionFailed(exMsg, ex); } } @Override public String getUptime(NetworkSystem network) throws Exception { try { WBEMClient client = getNetworkDeviceClient(network); return _smisHelper.getUptime(client); } catch (WBEMException ex) { String exMsg = ex.getLocalizedMessage(); if (exMsg.equals("Unable to connect")) { exMsg = "Unable to get uptime for device " + network.getLabel() + ": Unable to connect to ip " + network.getIpAddress() + " on port " + network.getSmisPortNumber(); } else { exMsg = "Unable to get uptime for device " + network.getLabel(); } String msg = MessageFormat.format("Failed to get uptime: {0}", exMsg); _log.error(msg); throw NetworkDeviceControllerException.exceptions.getUptimeFailed(exMsg, ex); } } @Override public Set<String> getRoutedEndpoints(NetworkSystem networkSystem, String fabricId, String fabricWwn) throws Exception { WBEMClient client = getNetworkDeviceClient(networkSystem); return _smisHelper.getRoutedEndpoints(client, fabricId, fabricWwn); } @Override public BiosCommandResult updateZones(NetworkSystem networkSystem, List<ZoneUpdate> zoneUpdates, String fabricId, String fabricWwn, boolean activateZoneset) throws NetworkDeviceControllerException { BiosCommandResult cmdResults = null; try { WBEMClient client = getNetworkDeviceClient(networkSystem); validateFabric(networkSystem, fabricWwn, fabricId); Map<String, String> results = updateZonesStrategy(client, zoneUpdates, fabricId, fabricWwn, activateZoneset); cmdResults = getBiosCommandResult(results); _log.info("Update zone results {}", toMessage(results)); } catch (NetworkDeviceControllerException ex) { _log.error("Cannot update zones: " + ex.getLocalizedMessage()); throw ex; } return cmdResults; } /** * Updates one or more zones by adding/removing members as requested for each zone. * * @param client and instance of {@link WBEMClient} connected to the provider * @param zones the list of zone update requests * @param fabricId the name of the fabric where the zones exist * @param fabricWwn the WWN of the fabric where the zones exist * @param activateZones a boolean to indicate if the zoneset should be activated * following successful updates * @return a map of the update results by zone keyed by zone name * @throws NetworkDeviceControllerException */ public Map<String, String> updateZonesStrategy(WBEMClient client, List<ZoneUpdate> zones, String fabricId, String fabricWwn, boolean activateZones) throws NetworkDeviceControllerException { // to do - Make sure fabric // id and fabric wwn are not // null or only request // needed params // a zone-name-to-result map to hold the results for each zone Map<String, String> zoneUpdateResults = new HashMap<String, String>(); if (zones.isEmpty()) { throw DeviceControllerException.exceptions.entityNullOrEmpty("zones"); } CIMInstance zoneServiceIns = null; try { _log.info("Update zones started."); _log.info("Attempting to start a zoning session"); if (fabricWwn == null) { fabricWwn = _smisHelper.getFabricWwn(client, fabricId); } zoneServiceIns = _smisHelper.startSession(client, fabricId, fabricWwn); if (zoneServiceIns == null) { _log.info("Failed to start a zoning session."); throw NetworkDeviceControllerException.exceptions.startZoningSessionFailed(); } // First determine if there is an active zoneset. CIMObjectPath zonesetPath = null; CIMInstance activeZonesetIns = _smisHelper .getActiveZonesetInstance(client, fabricId, fabricWwn); // There is no active zoneset, error if (activeZonesetIns == null) { _log.info("Cannot find active zoneset."); throw NetworkDeviceControllerException.exceptions.noActiveZonesetForFabric(fabricId); } else { // For Brocade, the active zoneset is a copy of a configuration zoneset. To make a change, we // need to modify the configuration zoneset and activate it. Get the configuration zoneset. zonesetPath = _smisHelper.getShadowZonesetPath(client, fabricId, fabricWwn, activeZonesetIns); } Map<String, Zone> zonesInFabric = _smisHelper.getZones(client, getZoneNames(zones), fabricWwn, false, true, true); for (ZoneUpdate zone : zones) { try { if (checkAndUpdateZone(client, zoneServiceIns, fabricId, fabricWwn, zonesetPath, zonesInFabric, zone)) { zoneUpdateResults.put(zone.getName(), SUCCESS); } else { zoneUpdateResults.put(zone.getName(), NO_CHANGE); } } catch (Exception ex) { zoneUpdateResults.put(zone.getName(), ERROR + " : " + ex.getMessage()); handleZonesStrategyException(ex, activateZones); } } _log.info("Attempting to close zoning session."); // If there were no zones updated, just close the session without commit and return. if (!hasResult(zoneUpdateResults, SUCCESS)) { _log.info("No zones were updates. Closing the session with no commit"); if (!_smisHelper.endSession(client, zoneServiceIns, false)) { _log.info("Failed to terminate zoning session. Ignoring as session may have expired."); } } else { // if zones were updated, commit them before ending the session if (_smisHelper.endSession(client, zoneServiceIns, true)) { if (activateZones) { _log.info("Attempting to activate the zoneset."); if (_smisHelper.activateZoneSet(client, zoneServiceIns, zonesetPath, true)) { _log.info("The zoneset was activated succcessfully."); } else { _log.info("Failed to activate the zoneset"); } } } else { throw NetworkDeviceControllerException.exceptions.updateZonesStrategyFailedCommit(); } } _log.info("Update zones strategy completed successfully."); } catch (Exception e1) { try { if (zoneServiceIns != null) { _log.info("Attempting to terminate zoning session."); _smisHelper.endSession(client, zoneServiceIns, false); } } catch (WBEMException e) { _log.error("Failed to terminate zoning session." + e.getLocalizedMessage(), e); } _log.error("Failed to update zones: " + e1.getLocalizedMessage(), e1); throw NetworkDeviceControllerException.exceptions.updateZonesStrategyFailed(e1); } return zoneUpdateResults; } /** * Add and remove members from/to a zone. This function will not fail if * a member to be removed is not in the zone or if a member that will be * added is already in the zone. * <p> * A member of type alias can be remove using its alias or its WWN. * <p> * If the zone already has the WWN of an alias and now the user is trying to add the alias into the zone, the alias will not be added. * The WWN has to be removed first. * <p> * Replacing a WWN with its alias should be possible in a single call by specifying the WWN in the remove list and alias in the add * list. * <p> * Note this function will delete the zone if the zone has no remaining members. * * @param client an instance of WBEMClient * @param zoneServiceIns an instance of ZoneService * @param fabricId the fabric name or vsan id * @param fabricWwn the fabric WWN * @param zonesetPath CIM path of the zoneset * @param zonesInFabric a map of all zones in the zoneset * @param zoneUpdate the changes to be made to the zone * @return true if the update completed successfully. */ private boolean checkAndUpdateZone(WBEMClient client, CIMInstance zoneServiceIns, String fabricId, String fabricWwn, CIMObjectPath zonesetPath, Map<String, Zone> zonesInFabric, ZoneUpdate zoneUpdate) { boolean success = false; ZoneMember curMember = null; try { if (zonesInFabric.containsKey(zoneUpdate.getName())) { _log.info("Start update zone {}", zoneUpdate.getName()); Zone zone = zonesInFabric.get(zoneUpdate.getName()); Map<String, ZoneMember> members = getZoneMembersMap(client, zone.getName(), (CIMObjectPath) zone.getCimObjectPath()); // handle removed members if (zoneUpdate.getRemoveZones() != null) { for (ZoneMember remMember : zoneUpdate.getRemoveZones()) { curMember = members.containsKey(remMember.getAlias()) ? members.get(remMember.getAlias()) : members.get(remMember.getAddress()); if (curMember != null && curMember.isAliasType() && !StringUtils.isEmpty(remMember.getAlias())) { _log.info("Removing alia smember {}", remMember.getAlias()); _smisHelper.removeZoneOrAliasMember(client, (CIMObjectPath) curMember.getCimAliasPath(), (CIMObjectPath) zone.getCimObjectPath(), true); members.remove(curMember.getAlias()); members.remove(curMember.getAddress()); success = true; } else if (curMember != null && !curMember.isAliasType() && !StringUtils.isEmpty(remMember.getAddress())) { _log.info("Removing WWN member {}", remMember.getAddress()); _smisHelper.removeZoneOrAliasMember(client, (CIMObjectPath) curMember.getCimObjectPath(), (CIMObjectPath) zone.getCimObjectPath(), false); members.remove(curMember.getAlias()); members.remove(curMember.getAddress()); success = true; } else { _log.warn("Did not remove zone member with alias " + remMember.getAlias() + " and WWN " + remMember.getAddress() + " because it was not found."); } } } // handle added members if (zoneUpdate.getAddZones() != null) { for (ZoneMember addMember : zoneUpdate.getAddZones()) { curMember = members.containsKey(addMember.getAlias()) ? members.get(addMember.getAlias()) : members.get(addMember.getAddress()); if (curMember == null) { String name = addMember.hasAlias() ? addMember.getAlias() : addMember.getAddress(); _log.info("Adding zone member {} ", name); _smisHelper.addZoneOrAliasMember(client, zoneServiceIns, fabricWwn, (CIMObjectPath) zone.getCimObjectPath(), name); members.put(name, addMember); success = true; } else { _log.warn("Did not add zone member with alias " + addMember.getAlias() + " and WWN " + addMember.getAddress() + " because it already exists."); } } } // check to see if the zone is now empty if (members.isEmpty()) { _log.error("Deleting Zone " + zoneUpdate.getName() + " because it is now empty."); _smisHelper.removeZone(client, zone); } } else { _log.error("Failed to update zones: " + zoneUpdate.getName() + ". The zone was not found in the active zoneset"); throw NetworkDeviceControllerException.exceptions.updateZonesStrategyFailedNotFound(zoneUpdate.getName()); } } catch (WBEMException ex) { _log.error("Failed to update zone: " + zoneUpdate.getName() + ". Error message" + ex.getLocalizedMessage(), ex); throw NetworkDeviceControllerException.exceptions.updateZonesStrategyFailed(ex); } return success; } /** * Returns a map of the zone members keyed by either alias or WWN * depending on the member type. For members of type alias, the * member will appear in the map twice once keyed by alias and * once by WWN to facilitate the look up. * * @param client and instance of WBEMClient * @param name the zone name * @param path CIM path of the zone * @return a map of the zone members keyed by either alias or WWN * @throws WBEMException */ private Map<String, ZoneMember> getZoneMembersMap(WBEMClient client, String name, CIMObjectPath path) throws WBEMException { Map<String, ZoneMember> map = new HashMap<String, ZoneMember>(); try { List<ZoneMember> members = _smisHelper.getZoneMembers(client, path, true); for (ZoneMember member : members) { if (member.hasAlias()) { map.put(member.getAlias(), member); } map.put(member.getAddress(), member); } return map; } catch (WBEMException e) { _log.error("Failed to get the zone members for zone " + name + ". Error message" + e.getLocalizedMessage()); throw e; } } @Override public BiosCommandResult activateZones(NetworkSystem networkSystem, String fabricId, String fabricWwn) throws NetworkDeviceControllerException { BiosCommandResult result = null; NetworkDeviceControllerException exception = null; try { WBEMClient client = getNetworkDeviceClient(networkSystem); CIMInstance zonesetIns = _smisHelper.getActiveZonesetInstance(client, fabricId, fabricWwn); if (zonesetIns != null) { CIMObjectPath shadowZonesetPath = _smisHelper.getShadowZonesetPath(client, fabricId, fabricWwn, zonesetIns); CIMInstance zoneServiceIns = _smisHelper.getZoneServiceInstance(client, fabricId, fabricWwn); boolean activate = !_smisHelper.isEmptyZoneset(client, shadowZonesetPath); if (_smisHelper.activateZoneSet(client, zoneServiceIns, zonesetIns.getObjectPath(), activate)) { _log.info("The active zoneset for fabric " + fabricId + " was " + (activate ? "re-activated" : "deactivated")); } else { _log.error("Failed to re-activate zoneset"); exception = NetworkDeviceControllerException.exceptions.zonesetActivationFailed(fabricId, new Throwable()); } } else { exception = NetworkDeviceControllerException.exceptions.noActiveZonesetForFabric(fabricId); } result = BiosCommandResult.createSuccessfulResult(); } catch (Exception ex) { _log.error("Cannot re-activate zoneset: " + ex.getLocalizedMessage()); exception = NetworkDeviceControllerException.exceptions.zonesetActivationFailed(fabricId, ex); } if (exception != null) { throw exception; } return result; } protected String getDefaultZonesetName(String fabricId) { return "Zoneset_" + fabricId.replace("-", "_").replaceAll("[^A-Za-z0-9_]", ""); } @Override public List<ZoneWwnAlias> getAliases(NetworkSystem network, String fabricId, String fabricWwn) throws Exception { WBEMClient client = getNetworkDeviceClient(network); validateFabric(network, fabricWwn, fabricId); return _smisHelper.getAliases(client, fabricId, fabricWwn); } @Override public BiosCommandResult addAliases(NetworkSystem networkSystem, List<ZoneWwnAlias> aliases, String fabricId, String fabricWwn) throws NetworkDeviceControllerException { return executeInSession(networkSystem, aliases, fabricId, fabricWwn, "checkAndCreateAlias", "add aliases"); } /** * Check if an alias exists before creating a new one. If the alias exists and for * the same WWN, then nothing will be done but if the alias name is used for another * WWN, then this is an error condition. * * @param client an instance of WBEMClient * @param zoneServiceIns the zone service holding the zoning session * @param fabricId the fabric name * @param fabricWwn the fabric WWN * @param alias the alias to be created * @return true if an alias was indeed created * @throws WBEMException */ public boolean checkAndCreateAlias(WBEMClient client, CIMInstance zoneServiceIns, String fabricId, String fabricWwn, ZoneWwnAlias alias) throws WBEMException { boolean added = false; _log.info("Starting create alias with name " + alias.getName()); // check if an alias with the same name exists ZoneWwnAlias existingAlias = _smisHelper.getAlias(client, alias.getName(), fabricWwn, true); if (existingAlias != null) { _log.info("Found alias {}", alias.getName()); if (StringUtils.equalsIgnoreCase(existingAlias.getAddress(), alias.getAddress())) { // alias already exists - this is not an error unless it is for different member _log.info("The existing alias is for the same WWN {}. Nothing to do.", alias.getAddress()); } else { throw NetworkDeviceControllerException.exceptions.aliasWithSameNameExists(alias.getName(), existingAlias.getAddress(), alias.getAddress()); } } else { // create the new alias added = _smisHelper.addZoneAlias(client, zoneServiceIns, fabricId, fabricWwn, alias) != null; } return added; } /** * Check if an alias exists before updating it. If the alias does not exist * then nothing will be done. * * @param client an instance of WBEMClient * @param zoneServiceIns the zone service holding the zoning session * @param fabricId the fabric name * @param fabricWwn the fabric WWN * @param alias the alias to be created * @return true if an alias was indeed created * @throws WBEMException */ public boolean checkAndRemoveAlias(WBEMClient client, CIMInstance zoneServiceIns, String fabricId, String fabricWwn, ZoneWwnAlias alias) throws WBEMException { boolean removed = false; _log.info("Starting remove alias with name {}", alias.getName()); // check if an alias with the same name exists ZoneWwnAlias existingAlias = null; if (alias.getAddress() != null && alias.getAddress().length() > 0) { // we need to verify that the alias member matches before removing it existingAlias = _smisHelper.getAlias(client, alias.getName(), fabricWwn, true); if (existingAlias != null && !StringUtils.equalsIgnoreCase(existingAlias.getAddress(), alias.getAddress())) { _log.info("The existing alias has a WWN other than the expected {}. It will not be removed.", alias.getAddress()); throw NetworkDeviceControllerException.exceptions.aliasWithDifferentWwnExists(alias.getName(), existingAlias.getAddress(), alias.getAddress()); } } else { existingAlias = _smisHelper.getAlias(client, alias.getName(), fabricWwn, false); } if (existingAlias != null) { _log.info("Found alias {}. The alias will be removed.", alias.getName()); _smisHelper.removeInstance(client, (CIMObjectPath) existingAlias.getCimObjectPath()); removed = true; } else { _log.info("Did not find alias {}. Nothing to do.", alias.getName()); } return removed; } /** * Check if an alias exists before removing it. If the alias does not exist * then nothing will be done. * * @param client an instance of WBEMClient * @param zoneServiceIns the zone service holding the zoning session * @param fabricId the fabric name * @param fabricWwn the fabric WWN * @param updateAlias the alias to be created * @return true if an alias was indeed created * @throws WBEMException */ public boolean checkAndUpdateAlias(WBEMClient client, CIMInstance zoneServiceIns, String fabricId, String fabricWwn, ZoneWwnAlias alias) throws WBEMException { boolean success = false; ZoneWwnAliasUpdate updateAlias = (ZoneWwnAliasUpdate) alias; _log.info("Starting update alias {}", updateAlias.getName()); // check if the alias exists ZoneWwnAlias existingAlias = _smisHelper.getAlias(client, updateAlias.getName(), fabricWwn, true); if (existingAlias != null) { _log.info("Found alias {}", updateAlias.getName()); // check if the alias is how we expect it to be if (!StringUtils.isEmpty(updateAlias.getNewName())) { _log.warn("Rename alias is request and is not supported for Brocade.", existingAlias.getName()); if (StringUtils.equals(existingAlias.getName(), updateAlias.getNewName())) { _log.info("The existing alias already has the requested name {}. Ignoring.", existingAlias.getName()); } else { _log.error("A request is made to update alias name from {} to {}. Rename is not supported for Brocade", existingAlias.getName(), updateAlias.getNewName()); throw NetworkDeviceControllerException.exceptions.renameAliasNotSupported(alias.getName()); } } // check if the alias is how we expect it to be if (!StringUtils.isEmpty(updateAlias.getAddress()) && !StringUtils.equalsIgnoreCase(existingAlias.getAddress(), updateAlias.getAddress())) { _log.info("The existing alias has a WWN other than the expected {}. It will not be updated.", updateAlias.getAddress()); throw NetworkDeviceControllerException.exceptions.aliasWithDifferentWwnExists(alias.getName(), existingAlias.getAddress(), updateAlias.getAddress()); } if (!StringUtils.isEmpty(updateAlias.getNewAddress())) { if (StringUtils.equalsIgnoreCase(existingAlias.getAddress(), updateAlias.getNewAddress())) { _log.info("The existing alias already has the requested WWN {}. WWN will not change.", existingAlias.getAddress()); } else { _log.info("Updating alias member from {} to {}", existingAlias.getAddress(), updateAlias.getNewAddress()); _smisHelper.removeZoneOrAliasMember(client, (CIMObjectPath) existingAlias.getCimMemberPath(), (CIMObjectPath) existingAlias.getCimObjectPath(), false); success = _smisHelper.addZoneOrAliasMember(client, zoneServiceIns, fabricWwn, (CIMObjectPath) existingAlias.getCimObjectPath(), updateAlias.getNewAddress()); // If member change fails, exit this function if (!success) { return success; } } } } else { throw NetworkDeviceControllerException.exceptions.aliasNotFound(updateAlias.getName()); } return success; } @Override public BiosCommandResult removeAliases(NetworkSystem networkSystem, List<ZoneWwnAlias> aliases, String fabricId, String fabricWwn) throws NetworkDeviceControllerException { return executeInSession(networkSystem, aliases, fabricId, fabricWwn, "checkAndRemoveAlias", "remove aliases"); } @Override public BiosCommandResult updateAliases(NetworkSystem networkSystem, List<ZoneWwnAliasUpdate> aliases, String fabricId, String fabricWwn) throws NetworkDeviceControllerException { List<ZoneWwnAlias> newList = new ArrayList<ZoneWwnAlias>(); newList.addAll(aliases); return executeInSession(networkSystem, newList, fabricId, fabricWwn, "checkAndUpdateAlias", "update aliases"); } /** * Common code for opening sessions and executing alias-type commands * * @param networkSystem the network system when the commands will execute * @param aliases a list of aliases to be created/updated/deleted * @param fabricId the name of fabric where the aliases will be changed * @param fabricWwn the WWN of fabric where the aliases will be changed * @param methodName the method to be executed * @param methodLogName the method name to be used for logging * @return the command that contains a map of results-per-alias keyed * by alias name * @throws NetworkDeviceControllerException */ private BiosCommandResult executeInSession(NetworkSystem networkSystem, List<ZoneWwnAlias> aliases, String fabricId, String fabricWwn, String methodName, String methodLogName) throws NetworkDeviceControllerException { // a alias-name-to-result map to hold the results for each alias Map<String, String> aliasUpdateResults = new HashMap<String, String>(); if (aliases.isEmpty()) { throw DeviceControllerException.exceptions.entityNullOrEmpty("aliases"); } WBEMClient client = getNetworkDeviceClient(networkSystem); CIMInstance zoneServiceIns = null; try { if (fabricWwn == null) { fabricWwn = _smisHelper.getFabricWwn(client, fabricId); } else { validateFabric(networkSystem, fabricWwn, fabricId); } _log.info("{} started.", methodLogName); _log.info("Attempting to start a zoning session"); zoneServiceIns = _smisHelper.startSession(client, fabricId, fabricWwn); if (zoneServiceIns == null) { _log.info("Failed to start a zoning session."); throw NetworkDeviceControllerException.exceptions.startZoningSessionFailed(); } Method method = getClass().getMethod(methodName, new Class[] { WBEMClient.class, CIMInstance.class, String.class, String.class, ZoneWwnAlias.class }); for (ZoneWwnAlias alias : aliases) { try { if ((Boolean) method.invoke(this, client, zoneServiceIns, fabricId, fabricWwn, alias)) { aliasUpdateResults.put(alias.getName(), SUCCESS); } else { aliasUpdateResults.put(alias.getName(), NO_CHANGE); } } catch (Exception ex) { aliasUpdateResults.put(alias.getName(), ERROR + " : " + ex.getMessage()); _log.info("Exception was encountered but will try the rest of the batch. Error message: ", ex); } } _log.info("Attempting to close zoning session."); // If no aliases were changed, just close the session without commit and return. if (!hasResult(aliasUpdateResults, SUCCESS)) { _log.info("{} was not successful for any entity. Closing the session with no commit", methodLogName); if (!_smisHelper.endSession(client, zoneServiceIns, false)) { _log.info("Failed to terminate zoning session. Ignoring as session may have expired."); } } else { // if aliases were changed, commit them before ending the session if (!_smisHelper.endSession(client, zoneServiceIns, true)) { throw NetworkDeviceControllerException.exceptions.zoneSessionCommitFailed(fabricId); } } _log.info("{} completed successfully.", methodLogName); } catch (Exception e1) { try { if (zoneServiceIns != null) { _log.info("Attempting to terminate zoning session."); _smisHelper.endSession(client, zoneServiceIns, false); } } catch (WBEMException e) { _log.error("Failed to terminate zoning session." + e.getLocalizedMessage(), e); } _log.error("Failed to " + methodLogName + ": " + e1.getLocalizedMessage(), e1); throw NetworkDeviceControllerException.exceptions.operationFailed(methodLogName, e1); } _log.info(methodLogName + " results: " + toMessage(aliasUpdateResults)); return getBiosCommandResult(aliasUpdateResults); } private <T extends Zone> List<String> getZoneNames(List<T> zones) { List<String> names = new ArrayList<String>(); if (zones != null) { for (Zone zone : zones) { names.add(zone.getName()); } } return names; } private void validateFabric(NetworkSystem networkSystem, String fabricWwn, String fabricId) throws NetworkDeviceControllerException { try { Map<String, String> map = getFabricIdsMap(networkSystem); if (!map.containsKey(fabricWwn) && !map.containsValue(fabricId)) { throw NetworkDeviceControllerException.exceptions.fabricNotFoundInNetwork(fabricId, networkSystem.getLabel()); } } catch (Exception ex) { _log.info("Failed to get fabrics : " + ex.getMessage()); throw NetworkDeviceControllerException.exceptions.failedToGetFabricsInNetwork(networkSystem.getLabel(), ex.getMessage()); } } @Override public Map<String, List<Zone>> getEndpointsZones(NetworkSystem networkSystem, String fabricWwn, String nativeId, Collection<String> endpointsWwn) { Map<String, List<Zone>> zones = new HashMap<String, List<Zone>>(); Map<CIMObjectPath, Zone> cachedZones = new HashMap<CIMObjectPath, Zone>(); try { WBEMClient client = getNetworkDeviceClient(networkSystem); for (String endpointWwn : endpointsWwn) { _log.info("getting zones for endpoint {} in network {} ", endpointWwn, nativeId == null ? fabricWwn : nativeId); zones.put(endpointWwn, _smisHelper.getEndpointZones(client, fabricWwn, endpointWwn, cachedZones)); } } catch (Exception ex) { _log.info("Failed to get zones for endpoints {} : ", endpointsWwn, ex.getMessage()); throw NetworkDeviceControllerException.exceptions.failedToGetEndpointZones( endpointsWwn, networkSystem.getLabel(), ex.getMessage()); } return zones; } /** * Get the value of the system configuration that governs how endpoints will be retrieved * from the SMIS provider. * <ol> * <li>The default way of getting TopologyView instances is by fabric. This can be slow for some configurations</li> * <li>The alternative way is to get all TopologyView instances and group them into theit fabrics using DependentSystem property. This * does not work well for FDMI hosts as multiple associations need to be traversed. This mode should only be used by customer not * deploying FDMI</li> * </ol> * * @return */ private boolean discoverEndpointsByFabric() { boolean byFabric = false; // default to true try { byFabric = Boolean.valueOf(ControllerUtils.getPropertyValueFromCoordinator( _coordinator, "controller_ns_brocade_discovery_by_fabric_association")); } catch (Exception ex) { _log.warn("Failed to get the values for controller_ns_brocade_discovery_by_fabric_association from system configurations " + ex.getMessage()); } return byFabric; } @Override public boolean isCapableOfRouting(NetworkSystem networkSystem) { return true; } }