/** * Search all the remote FCEndpoints, remove those having the same RemotePortName that are in a * different fabric from a different device. * * @param remoteWwpn RemotePortName of new entry * @param fabricWwn FabricWwn of new entry * @param deviceId Device that found the updated connections * @return count of those removed * @throws IOException */ private int removeConflictingEndpoints(String remoteWwpn, String fabricWwn, URI deviceId) throws IOException { int removedCount = 0; URIQueryResultList uriList = new URIQueryResultList(); dbClient.queryByConstraint( AlternateIdConstraint.Factory.getFCEndpointRemotePortNameConstraint(remoteWwpn), uriList); for (URI uri : uriList) { FCEndpoint ep = dbClient.queryObject(FCEndpoint.class, uri); if (ep == null) { continue; } if (ep.getNetworkDevice().equals(deviceId)) { continue; } if (ep.getRemotePortName().equals(remoteWwpn) == false) { continue; } if (ep.getFabricWwn().equals(fabricWwn)) { continue; } dbClient.removeObject(ep); removedCount++; } return removedCount; }
/** * Returns true if any fields of significance has been modified. * * @param existing * @param current * @return false if no updates, true if updated */ private boolean checkUpdated(FCEndpoint existing, FCEndpoint current) { boolean updated = false; if (existing.getInactive() == true) { existing.setInactive(false); updated = true; } if (checkAttributeChanged(existing.getRemotePortName(), current.getRemotePortName())) { existing.setRemotePortName(current.getRemotePortName()); updated = true; } if (checkAttributeChanged(existing.getRemoteNodeName(), current.getRemoteNodeName())) { existing.setRemoteNodeName(current.getRemoteNodeName()); updated = true; } if (checkAttributeChanged(existing.getRemotePortAlias(), current.getRemotePortAlias())) { existing.setRemotePortAlias( current.getRemotePortAlias() == null ? "" : current.getRemotePortAlias()); updated = true; } if (checkAttributeChanged(existing.getFabricId(), current.getFabricId())) { existing.setFabricId(current.getFabricId()); updated = true; } if (checkAttributeChanged(existing.getFcid(), current.getFcid())) { existing.setFcid(current.getFcid()); updated = true; } if (checkAttributeChanged(existing.getSwitchInterface(), current.getSwitchInterface())) { existing.setSwitchInterface(current.getSwitchInterface()); updated = true; } if (checkAttributeChanged(existing.getSwitchName(), current.getSwitchName())) { existing.setSwitchName(current.getSwitchName()); updated = true; } if (checkAttributeChanged(existing.getSwitchPortName(), current.getSwitchPortName())) { existing.setSwitchPortName(current.getSwitchPortName()); updated = true; } if (checkAttributeChanged(existing.getFabricWwn(), current.getFabricWwn())) { existing.setFabricWwn(current.getFabricWwn()); updated = true; } return updated; }
/** * Reconciles the current set of a Device's endpoints with what is persisted. Updates the database * accordingly. * * @param dev * @param currentConnections * @throws IOException */ private void reconcileFCEndpoints(NetworkSystem dev, List<FCEndpoint> currentConnections) throws IOException { // First, read all the existing connections from the device, and put them into a map // keyed by remote wwpn. URIQueryResultList uriList = new URIQueryResultList(); dbClient.queryByConstraint( ContainmentConstraint.Factory.getNetworkSystemFCPortConnectionConstraint(dev.getId()), uriList); Map<String, FCEndpoint> existingEndpoints = new HashMap<String, FCEndpoint>(); for (URI uriold : uriList) { FCEndpoint connection = dbClient.queryObject(FCEndpoint.class, uriold); if (connection != null) { existingEndpoints.put(connection.getRemotePortName().toUpperCase(), connection); } } // Now, scan the new endpoints, looking for added or updated records by // comparing them with the existing endpoints. Keep track of what was processed // so can do deletions on anything not seen in the currentConnections. List<FCEndpoint> updated = new ArrayList<FCEndpoint>(); List<FCEndpoint> created = new ArrayList<FCEndpoint>(); Set<String> processedWwpns = new HashSet<String>(); int conflictingEndpoints = 0; for (FCEndpoint current : currentConnections) { String key = current.getRemotePortName().toUpperCase(); processedWwpns.add(key); FCEndpoint existing = existingEndpoints.get(key); if (existing == null) { current.setNetworkDevice(dev.getId()); current.setId(URIUtil.createId(FCEndpoint.class)); created.add(current); conflictingEndpoints += removeConflictingEndpoints(key, current.getFabricWwn(), dev.getId()); } else { boolean modified = checkUpdated(existing, current); if (existing.getAwolCount() > 0) { modified = true; existing.setAwolCount(0); existing.setAwolTime(null); } if (modified) { updated.add(existing); conflictingEndpoints += removeConflictingEndpoints(key, current.getFabricWwn(), dev.getId()); } } } // Determine those to be deleted. Remove all the processed records from the existing set. // What was left were not seen this time. for (String key : processedWwpns) { existingEndpoints.remove(key); } // The remaining existingEndpoints can be processed for removal. // They are removed after a minimum number of samples and minimum amount of time has transpired. Integer removedCount = 0; for (FCEndpoint entry : existingEndpoints.values()) { int count = entry.getAwolCount(); if (count == 0) { entry.setAwolTime(System.currentTimeMillis()); } entry.setAwolCount(++count); if (count >= _minAwolSamples && (System.currentTimeMillis() - entry.getAwolTime()) > _minAwolTime) { removedCount++; dbClient.removeObject(entry); } else { updated.add(entry); // update counters } } // Persist created, modified. dbClient.createObject(created); dbClient.updateAndReindexObject(updated); _log.info(MessageFormat.format("{0} new connections persisted", created.size()).toString()); _log.info(MessageFormat.format("{0} updated connections persisted", updated.size()).toString()); _log.info( MessageFormat.format("{0} missing connections", existingEndpoints.values().size()) .toString()); _log.info(MessageFormat.format("{0} removed connections", removedCount.toString())); _log.info(MessageFormat.format("{0} conflicting connections (removed)", conflictingEndpoints)); }