package org.opennaas.extensions.bod.autobahn.bod; import static com.google.common.collect.Iterables.concat; import static com.google.common.collect.Iterables.size; import java.util.ArrayList; import java.util.List; import java.util.Map; import net.geant.autobahn.administration.Administration; import net.geant.autobahn.administration.ReservationType; import net.geant.autobahn.administration.ServiceType; import net.geant.autobahn.useraccesspoint.PortType; import net.geant.autobahn.useraccesspoint.UserAccessPoint; import net.geant.autobahn.useraccesspoint.UserAccessPointException_Exception; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opennaas.core.resources.action.ActionException; import org.opennaas.core.resources.action.ActionResponse; import org.opennaas.core.resources.command.Response; import org.opennaas.core.resources.protocol.IProtocolSessionManager; import org.opennaas.core.resources.protocol.ProtocolException; import org.opennaas.extensions.bod.autobahn.AutobahnAction; import org.opennaas.extensions.bod.autobahn.model.AutobahnInterface; import org.opennaas.extensions.bod.autobahn.model.AutobahnLink; import org.opennaas.extensions.network.model.NetworkModel; import com.google.common.collect.Maps; public class GetTopologyAction extends AutobahnAction { public final static String ACTIONID = "getTopology"; private final Log log = LogFactory.getLog(GetTopologyAction.class); public GetTopologyAction() { setActionID(ACTIONID); } @Override public ActionResponse execute(IProtocolSessionManager protocolSessionManager) throws ActionException { try { log.info("Retrieving Autobahn topology"); Iterable<PortType> localPorts = queryLocalPorts(protocolSessionManager); Iterable<PortType> allPorts = queryAllPorts(protocolSessionManager); Iterable<ServiceType> services = queryServices(protocolSessionManager); updateModel((NetworkModel) modelToUpdate, localPorts, allPorts, services); return okResponse(allPorts, services); } catch (UserAccessPointException_Exception e) { throw new ActionException(e); } catch (ProtocolException e) { throw new ActionException(e); } } private ActionResponse okResponse(Iterable<PortType> ports, Iterable<ServiceType> services) { ActionResponse response = new ActionResponse(); response.setActionID(getActionID()); response.setStatus(ActionResponse.STATUS.OK); response.setInformation("Discovered " + size(ports) + " ports " + "and " + size(services) + " services"); for (PortType port : ports) { response.addResponse(newPortResponse(port)); } return response; } private Response newPortResponse(PortType port) { return Response.okResponse("getPort", port.getAddress() + " (" + port.getDescription() + ")"); } private Iterable<PortType> queryLocalPorts(IProtocolSessionManager protocolSessionManager) throws ProtocolException, UserAccessPointException_Exception { UserAccessPoint userAccessPoint = getUserAccessPointService(protocolSessionManager); return userAccessPoint.getDomainClientPorts(); } private Iterable<PortType> queryAllPorts(IProtocolSessionManager protocolSessionManager) throws ProtocolException, UserAccessPointException_Exception { UserAccessPoint userAccessPoint = getUserAccessPointService(protocolSessionManager); List<PortType> clientPorts = userAccessPoint.getAllClientPorts(); List<PortType> idcpPorts = userAccessPoint.getIdcpPorts(); return concat(clientPorts, idcpPorts); } private Iterable<ServiceType> queryServices(IProtocolSessionManager protocolSessionManager) throws ProtocolException { Administration administration = getAdministrationService(protocolSessionManager); return administration.getServices(); } private void updateModel(NetworkModel model, Iterable<PortType> localPorts, Iterable<PortType> allPorts, Iterable<ServiceType> services) { Map<String, AutobahnInterface> interfaces = Maps.newHashMap(); for (PortType port : allPorts) { interfaces.put(port.getAddress(), ParameterTranslator.createInterface(port, false)); } for (PortType port : localPorts) { // Note that this will replace interfaces created above interfaces.put(port.getAddress(), ParameterTranslator.createInterface(port, true)); } List<AutobahnLink> links = new ArrayList<AutobahnLink>(); for (ServiceType service : services) { for (ReservationType reservation : service.getReservations()) { if (!isFinalState(reservation.getState())) { AutobahnLink link = updateLinkTo(interfaces, service, reservation); if (link != null) { // ".link" suffix is added in the key to avoid replacing potentially existing interfaces with same name interfaces.put(link.getSource().getName() + ".link", (AutobahnInterface) link.getSource()); interfaces.put(link.getSink().getName() + ".link", (AutobahnInterface) link.getSink()); links.add(link); } } } } model.getNetworkElements().addAll(interfaces.values()); model.getNetworkElements().addAll(links); } private boolean isFinalState(int state) { return state >= 20; } private AutobahnLink createLink(AutobahnInterface source, AutobahnInterface sink, ServiceType service, ReservationType reservation) { AutobahnInterface sourceClientIface = createClientInterface(source, reservation.getStartPort(), reservation.getUserStartVlan()); AutobahnInterface sinkClientIface = createClientInterface(sink, reservation.getEndPort(), reservation.getUserEndVlan()); AutobahnLink link = new AutobahnLink(); link.setName(service.getBodID()); link.setSource(sourceClientIface); link.setSink(sinkClientIface); link.setBidirectional(reservation.isBidirectional()); link.setReservation(reservation); link.setService(service); sourceClientIface.setLinkTo(link); if (link.isBidirectional()) sinkClientIface.setLinkTo(link); return link; } private AutobahnInterface createClientInterface(AutobahnInterface iface, PortType port, int vlan) { AutobahnInterface clientInterface; if (vlan >= 0) { clientInterface = ParameterTranslator.createInterface(port, iface.isLocal()); // there may be two interfaces with same name if generated name is a valid autobahn id clientInterface.setName(port.getAddress() + "." + port.getVlan()); clientInterface.setServerInterface(iface); } else { clientInterface = iface; } return clientInterface; } private AutobahnLink updateLinkTo(Map<String, AutobahnInterface> interfaces, ServiceType service, ReservationType reservation) { AutobahnInterface source = interfaces.get(reservation.getStartPort().getAddress()); AutobahnInterface sink = interfaces.get(reservation.getEndPort().getAddress()); if (source != null && sink != null) { AutobahnLink link = createLink(source, sink, service, reservation); List<AutobahnInterface> ifaces = new ArrayList<AutobahnInterface>(2); ifaces.add(source); ifaces.add(sink); link.setRequestParameters(ParameterTranslator.createRequestParameters(reservation, ifaces)); log.info("Discovered reservation " + service.getBodID() + " from " + source.getName() + " to " + sink.getName()); return link; } else { return null; } } }