package org.opennaas.extensions.network.capability.topology; /* * #%L * OpenNaaS :: Network :: Basic capability * %% * Copyright (C) 2007 - 2014 FundaciĆ³ Privada i2CAT, Internet i InnovaciĆ³ a Catalunya * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opennaas.core.resources.ActivatorException; import org.opennaas.core.resources.IResource; import org.opennaas.core.resources.IResourceManager; import org.opennaas.core.resources.ResourceException; import org.opennaas.core.resources.action.IAction; import org.opennaas.core.resources.action.IActionSet; import org.opennaas.core.resources.capability.AbstractCapability; import org.opennaas.core.resources.capability.CapabilityException; import org.opennaas.core.resources.descriptor.CapabilityDescriptor; import org.opennaas.extensions.network.capability.topology.api.Device; import org.opennaas.extensions.network.capability.topology.api.Link; import org.opennaas.extensions.network.capability.topology.api.NetworkTopology; import org.opennaas.extensions.network.capability.topology.api.Port; import org.opennaas.extensions.router.capability.topologydiscovery.model.LocalInformation; import org.opennaas.extensions.router.capability.topologydiscovery.model.Neighbours; /** * {@link ITopologyDiscoveryCapability} implementation * * @author Julio Carlos Barrera * */ public class TopologyDiscoveryCapability extends AbstractCapability implements ITopologyDiscoveryCapability { public static final String CAPABILITY_TYPE = "topology"; private final static Log log = LogFactory.getLog(TopologyDiscoveryCapability.class); private String resourceId = ""; private IResourceManager resourceManager; private Set<IResource> resources = new HashSet<IResource>(); public TopologyDiscoveryCapability(CapabilityDescriptor descriptor, String resourceId) { super(descriptor); this.resourceId = resourceId; log.debug("Built new Topology Discovery Capability"); } @Override public void activate() throws CapabilityException { registerService(Activator.getContext(), CAPABILITY_TYPE, getResourceType(), getResourceName(), ITopologyDiscoveryCapability.class.getName()); super.activate(); try { resourceManager = Activator.getResourceManagerService(); } catch (ActivatorException e) { throw new CapabilityException("Could not find required Resource Manager service!", e); } } @Override public void deactivate() throws CapabilityException { registration.unregister(); super.deactivate(); } @Override public String getCapabilityName() { return CAPABILITY_TYPE; } @Override public NetworkTopology getNetworkTopology() throws CapabilityException { NetworkTopology networkTopology = new NetworkTopology(); // key: resourceId Map<String, RouterTopologyInfo> resourceRouterInfoMap = new HashMap<String, TopologyDiscoveryCapability.RouterTopologyInfo>(); Set<Device> devices = new HashSet<Device>(); // resource iteration to fill all Devices that are resources in OpenNaaS and their Ports for (IResource router : resources) { String resourceId = router.getResourceIdentifier().getId(); // get topology information of router LocalInformation localInformation = getRouterLocalInformation(router); Neighbours neighbours = getRouterNeighbours(router); // fill the map resourceRouterInfoMap.put(resourceId, new RouterTopologyInfo(localInformation, neighbours)); /* * create device and fill IDs */ Device device = new Device(); // OpenNaaS resourceId device.setResourceID(resourceId); // underlying topology discovery protocol ID device.setId(localInformation.getDeviceId()); /* * create and fill ports. add them to device */ Set<Port> ports = new HashSet<Port>(); for (String portId : localInformation.getInterfacesMap().keySet()) { Port port = new Port(); // interface name port.setId(localInformation.getInterfacesMap().get(portId)); // Device ID of this Port port.setDeviceId(localInformation.getDeviceId()); ports.add(port); } device.setPorts(ports); // add device to devices set devices.add(device); } Set<Link> links = new HashSet<Link>(); // device iteration to fill Links for (Device device : devices) { // get topology information of router // LocalInformation localInformation = resourceRouterInfoMap.get(device.getResourceID()).getLocalInformation(); Neighbours neighbours = resourceRouterInfoMap.get(device.getResourceID()).getNeighbours(); /* * create device links */ Set<Link> deviceLinks = new HashSet<Link>(); for (Port port : device.getPorts()) { Link deviceLink = new Link(); // from is just this port deviceLink.setFrom(port); // get remote router from local Port org.opennaas.extensions.router.capability.topologydiscovery.model.Port remoteRouterPort = getRouterPortFromInterfaceName( port.getId(), neighbours.getDevicePortMap()); if (remoteRouterPort == null) { // this port is not connected to any remote device continue; } String remoteDeviceId = remoteRouterPort.getDeviceId(); // look for remote port in devices present in OpenNaaS as resources Device remoteDevice = getDeviceFromId(remoteDeviceId, devices); if (remoteDevice != null) { // check if remote device is an OpenNaaS resource for (Port p : remoteDevice.getPorts()) { // check if candidate remote Port ID matches remote ID if (remoteDevice.getResourceID() != null && p.getId() != null && p.getId().equals( resourceRouterInfoMap.get(remoteDevice.getResourceID()).getLocalInformation().getInterfacesMap() .get(remoteRouterPort.getPortId()))) { // match: remote device is an OpenNaaS resource with a well known port deviceLink.setTo(p); break; } } // device is not an OpenNaaS resource if (deviceLink.getTo() == null) { // check if unknown remote device was already created Port to = new Port(); to.setDeviceId(remoteDeviceId); // we don't know remote interface name, it is not possible setting port ID // add port to device addPortToDevice(remoteDevice, to); // add Port to Link deviceLink.setTo(to); } } // remote device is not yet tracked else { // create unknown remote Device remoteDevice = new Device(); remoteDevice.setId(remoteDeviceId); Port remotePort = new Port(); remotePort.setDeviceId(remoteDeviceId); // we don't know remote interface name, it is not possible setting port ID // add port to new device addPortToDevice(remoteDevice, remotePort); // add Port to Link deviceLink.setTo(remotePort); } deviceLinks.add(deviceLink); } links.addAll(deviceLinks); } networkTopology.setLinks(links); networkTopology.setDevices(devices); return networkTopology; } private static org.opennaas.extensions.router.capability.topologydiscovery.model.Port getRouterPortFromInterfaceName(String interfaceName, Map<String, org.opennaas.extensions.router.capability.topologydiscovery.model.Port> devicePortMap) { return devicePortMap.get(interfaceName); } private static void addPortToDevice(Device device, Port port) { if (device.getPorts() == null) { device.setPorts(new HashSet<Port>()); } device.getPorts().add(port); } private static Device getDeviceFromId(String deviceId, Set<Device> devices) { for (Device device : devices) { if (device.getId().equals(deviceId)) { return device; } } return null; } public static <T, E> T getKeyByValue(Map<T, E> map, E value) { for (Entry<T, E> entry : map.entrySet()) { if (value.equals(entry.getValue())) { return entry.getKey(); } } return null; } @Override public void addResource(String resourceId) throws CapabilityException { try { IResource resourceToAdd = resourceManager.getResourceById(resourceId); addResource(resourceToAdd); } catch (ResourceException e) { throw new CapabilityException("Could not find resource with ID = " + resourceId, e); } } @Override public void addResource(IResource resourceToAdd) throws CapabilityException { try { resourceToAdd.getCapabilityByInterface(org.opennaas.extensions.router.capability.topologydiscovery.ITopologyDiscoveryCapability.class); } catch (ResourceException e) { throw new CapabilityException("Resource with ID = " + resourceToAdd.getResourceIdentifier().getId() + " and name = " + resourceToAdd .getResourceDescriptor().getInformation().getName() + " has not Topology Discovery Capability!"); } resources.add(resourceToAdd); } @Override public void removeResource(String resourceId) throws CapabilityException { try { IResource resourceToRemove = resourceManager.getResourceById(resourceId); removeResource(resourceToRemove); } catch (ResourceException e) { throw new CapabilityException("Could not find resource with ID = " + resourceId, e); } } @Override public void removeResource(IResource resourceToRemove) throws CapabilityException { if (!resources.contains(resourceToRemove)) { throw new CapabilityException( "Resource with ID = " + resourceToRemove.getResourceIdentifier().getId() + " and name = " + resourceToRemove .getResourceDescriptor().getInformation().getName() + " was not previously added!"); } resources.remove(resourceToRemove); } @Override public IActionSet getActionSet() throws CapabilityException { // this capability does not have action set return null; } @Override public void queueAction(IAction arg0) throws CapabilityException { // this capability does not use queue throw new UnsupportedOperationException("Not Implemented. This capability is not using the queue."); } private org.opennaas.extensions.router.capability.topologydiscovery.ITopologyDiscoveryCapability getRouterTopologyDiscoveryCapability( IResource resource) throws CapabilityException { try { return (org.opennaas.extensions.router.capability.topologydiscovery.ITopologyDiscoveryCapability) resource .getCapabilityByInterface(org.opennaas.extensions.router.capability.topologydiscovery.ITopologyDiscoveryCapability.class); } catch (ResourceException e) { throw new CapabilityException("Resource with ID = " + resource.getResourceIdentifier().getId() + " and name = " + resource .getResourceDescriptor().getInformation().getName() + " has not Topology Discovery Capability!", e); } } private LocalInformation getRouterLocalInformation(IResource resource) throws CapabilityException { return getRouterTopologyDiscoveryCapability(resource).getLocalInformation(); } private Neighbours getRouterNeighbours(IResource resource) throws CapabilityException { return getRouterTopologyDiscoveryCapability(resource).getNeighbours(); } /** * RouterTopologyInfo containing LocalInformation and Neighbours */ private class RouterTopologyInfo { private LocalInformation localInformation; private Neighbours neighbours; public RouterTopologyInfo(LocalInformation localInformation, Neighbours neighbours) { this.localInformation = localInformation; this.neighbours = neighbours; } public LocalInformation getLocalInformation() { return localInformation; } public Neighbours getNeighbours() { return neighbours; } } }