private void handleEndpointsAdded(Network tzone, Collection<String> endpoints) throws IOException { // find if the endpoints exit in some old transport zone Map<String, Network> transportZoneMap = NetworkAssociationHelper.getNetworksMap(endpoints, dbClient); if (!transportZoneMap.isEmpty()) { _log.info("Added endpoints {} to transport zone {}", endpoints.toArray(), tzone.getLabel()); // before we add the endpoints, they need to be removed from their old transport zones NetworkAssociationHelper.handleRemoveFromOldNetworks( transportZoneMap, tzone, dbClient, _coordinator); } // now, add the the endpoints NetworkAssociationHelper.handleEndpointsAdded(tzone, endpoints, dbClient, _coordinator); }
/** * Remove the transport zone for a given network system. This typically means to dis-associated it * unless this is the last network system associated with the transport zone. In this case, the * transport zone will be deleted if: * * <ul> * <li>It was discovered * <li>It does not have any user-created ports * <li>It does not have any registered ports * </ul> * * @param tzone * @param uri * @throws IOException */ public List<String> removeNetworkSystemTransportZone(Network tzone, String uri) throws IOException { tzone.removeNetworkSystems(Collections.singletonList(uri)); // dis-associate // list of end points getting deleted ArrayList<String> toRemove = new ArrayList<String>(); if (tzone.getNetworkSystems().isEmpty()) { // if this is the last network system List<String> userCreatedEndPoints = TransportZoneReconciler.getUserCreatedEndPoints(tzone); if (userCreatedEndPoints.isEmpty() && !tzone.assignedToVarray()) { // delete only if not modified by a user _log.info("Removing network {}", tzone.getLabel()); toRemove.addAll(tzone.retrieveEndpoints()); NetworkAssociationHelper.handleEndpointsRemoved(tzone, toRemove, dbClient, _coordinator); dbClient.markForDeletion(tzone); recordTransportZoneEvent( tzone, OperationTypeEnum.DELETE_NETWORK.getEvType(true), OperationTypeEnum.DELETE_NETWORK.getDescription()); } else { _log.info( "Network {} is changed by the user and will " + "not be removed. Discovered end points will be removed.", tzone.getLabel()); for (String pt : tzone.retrieveEndpoints()) { if (!userCreatedEndPoints.contains(pt)) { toRemove.add(pt); } } tzone.removeEndpoints(toRemove); NetworkAssociationHelper.handleEndpointsRemoved(tzone, toRemove, dbClient, _coordinator); _log.info("Discovered endpoints removed {}", toRemove.toArray()); dbClient.persistObject(tzone); recordTransportZoneEvent( tzone, OperationTypeEnum.UPDATE_NETWORK.getEvType(true), OperationTypeEnum.UPDATE_NETWORK.getDescription()); } } else { _log.info("Removing network {} from network system {}", tzone.getLabel(), uri); dbClient.persistObject(tzone); recordTransportZoneEvent( tzone, OperationTypeEnum.UPDATE_NETWORK.getEvType(true), OperationTypeEnum.UPDATE_NETWORK.getDescription()); } return toRemove; }
/** * Looks in the topology view for endpoints that accessible by routing * * @param networkSystem the network system being refreshed * @param updatedNetworks the networks that require updating * @param routedEndpoints the routed endpoints map of Fabric-WWN-to-endpoints-WWN * @throws Exception */ private void updateRoutedNetworks( NetworkSystem networkSystem, List<Network> updatedNetworks, Map<String, Set<String>> routedEndpoints) throws Exception { // for each network, get the list of routed ports and locate them in other networks StringSet routedNetworks = null; Network routedNetwork = null; // get the current networks from the database Map<URI, Network> allNetworks = DataObjectUtils.toMap(getCurrentTransportZones()); for (Network network : updatedNetworks) { // if this network has any routed endpoints Set<String> netRoutedEndpoints = routedEndpoints.get(NetworkUtil.getNetworkWwn(network)); if (netRoutedEndpoints == null || netRoutedEndpoints.isEmpty()) { _log.debug("No routed endpoint in network {}", network.getNativeGuid()); network.setRoutedNetworks(null); } else { _log.info( "Found {} routed endpoint in network {}", netRoutedEndpoints, network.getNativeGuid()); routedNetworks = new StringSet(); for (String endpoint : netRoutedEndpoints) { // find the source network of the routed endpoint routedNetwork = findNetworkForDiscoveredEndPoint(allNetworks.values(), endpoint, network); if (routedNetwork != null) { // it is possible we did not discover the source routedNetworks.add(routedNetwork.getId().toString()); } } network.setRoutedNetworks(routedNetworks); } dbClient.updateAndReindexObject(network); _log.info("Updated routed networks for {} to {}", network.getNativeGuid(), routedNetworks); } // clean up transit networks from any one-way associations. // Transit networks will show any endpoints routed thru them // which may cause one-way associations in the routedNetworks. // For example if network A has ep1 and B has ep2 and there is // a routed zone between A and B, the transit network C will // reports ep1 and ep2 but there is not actual routing between // C and A or C and B, so we want to remove these associations. for (URI id : allNetworks.keySet()) { Network net = allNetworks.get(id); boolean updated = false; if (net.getRoutedNetworks() != null) { routedNetworks = new StringSet(net.getRoutedNetworks()); // for each network this network is pointing to for (String strUri : net.getRoutedNetworks()) { // get the opposite network Network opNet = allNetworks.get(URI.create(strUri)); if (opNet != null // it is possible this network is getting removed - the next discovery // cleans up && opNet.getRoutedNetworks() != null // check for null in case the other network routed eps are not yet visible && !opNet .getRoutedNetworks() .contains(net.getId().toString())) { // if the opposite network is not seeing this // one // remove this association because the opposite network is does not have the matching // association routedNetworks.remove(opNet.getId().toString()); updated = true; } } if (updated) { _log.info("Reconciled routed networks for {} to {}", net.getNativeGuid(), routedNetworks); net.setRoutedNetworks(routedNetworks); dbClient.updateAndReindexObject(net); } } } for (Network network : allNetworks.values()) { NetworkAssociationHelper.setNetworkConnectedVirtualArrays(network, false, dbClient); } /* * COP-23266, COP-20698: Fix the problem that ViPR could not create IVR zone between VSANs routed by * transit VSAN(network), the "routedNetwork" field of "Network" data object should be updated based * on the transit network(s) if there is. */ this.updateTransitRoutedNetworks(networkSystem); }
/** * Given the updated list of end points for one network system, this function will update the * transport zones. Require lock when reconciles vsan in fabrics that are linked through ISL. * Without locking, multiple VSANs could have same native gui id within the same fabric. * * @param networkSystem the network system * @param routedEndpoints IN/OUT parameter to get the routed endpoints map of * Fabric-WWN-to-endpoints-WWN * @throws ControllerException */ private void reconcileTransportZones( NetworkSystem networkSystem, Map<String, Set<String>> routedEndpoints) throws ControllerException { _log.info("reconcileTransportZones for networkSystem {}", networkSystem.getId()); ControllerServiceImpl.Lock lock = ControllerServiceImpl.Lock.getLock(ControllerServiceImpl.DISCOVERY_RECONCILE_TZ); try { _log.debug( "Acquiring lock to reconcile transport zone for networkSystem {}", networkSystem.getId()); lock.acquire(); _log.info( "Acquired lock to reconcile transport zone for networkSystem {}", networkSystem.getId()); // get the network system's connections from the database Iterator<FCEndpoint> iNewEndPoints = getNetworkSystemEndPoints(networkSystem); // get all the transport zones we have in the DB List<Network> oldTransportZones = getCurrentTransportZones(); _log.info("Found {} existing transport zones", oldTransportZones.size()); // get the fabrics that exist on the network system Map<String, String> fabricIdsMap = getDevice().getFabricIdsMap(networkSystem); // get the list of fabrics added, removed, changed TransportZoneReconciler reconciler = new TransportZoneReconciler(); TransportZoneReconciler.Results results = reconciler.reconcile(networkSystem, iNewEndPoints, fabricIdsMap, oldTransportZones); String networkSystemUri = networkSystem.getId().toString(); for (Network tzone : results.getRemoved()) { List<String> removedEps = removeNetworkSystemTransportZone(tzone, networkSystemUri); _log.info( "Removed network {} which removed discovered endpoints {}", tzone.getNativeGuid(), removedEps); } for (Network tzone : results.getAdded()) { handleEndpointsAdded(tzone, tzone.retrieveEndpoints()); saveTransportZone(tzone, true); } for (Network tzone : results.getModified()) { if (results.getRemovedEndPoints().get(tzone) != null) { NetworkAssociationHelper.handleEndpointsRemoved( tzone, results.getRemovedEndPoints().get(tzone), dbClient, _coordinator); } if (results.getAddedEndPoints().get(tzone) != null) { handleEndpointsAdded(tzone, results.getAddedEndPoints().get(tzone)); } saveTransportZone(tzone, false); } // update routed networks for routed and modified networks updateRoutedNetworks(networkSystem, results.getAddedAndModified(), routedEndpoints); } catch (Exception ex) { throw NetworkDeviceControllerException.exceptions.reconcileTransportZonesFailedExc( new Date().toString(), ex); } finally { try { _log.debug( "Releasing reconcile transport zone lock for networkSystem {}", networkSystem.getId()); lock.release(); _log.info( "Released reconcile transport zone lock for networkSystem {}", networkSystem.getId()); } catch (Exception e) { _log.error( "Failed to release Lock while reconcile transport zone for network {} -->{}", networkSystem.getId(), e.getMessage()); } } }