Merge "Conversion class FromSalConversionsUtils."
authorGiovanni Meo <gmeo@cisco.com>
Sun, 22 Sep 2013 13:01:25 +0000 (13:01 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Sun, 22 Sep 2013 13:01:25 +0000 (13:01 +0000)
21 files changed:
opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/Activator.java
opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerCLI.java [new file with mode: 0644]
opendaylight/clustering/test/pom.xml
opendaylight/clustering/test/src/main/java/org/opendaylight/controller/clustering/test/internal/SimpleClient.java
opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/ContainerFlowConfig.java
opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java
opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java
opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java
opendaylight/northbound/containermanager/src/main/java/org/opendaylight/controller/containermanager/northbound/ContainerManagerNorthbound.java
opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java
opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java
opendaylight/northbound/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/northbound/StaticRoutingNorthbound.java
opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java
opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthbound.java
opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java
opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchField.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/IPProtocols.java
opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/IPProtocolsTest.java [new file with mode: 0644]
opendaylight/web/topology/src/main/java/org/opendaylight/controller/topology/web/Topology.java

index 5a39e9ec4f6d3c1501d04a74869e41b7c2c8b36b..17df387d3e3bb156fab1bbdf350283652f496f8d 100644 (file)
@@ -55,7 +55,7 @@ public class Activator extends ComponentActivatorAbstractBase {
      */
     @Override
     public Object[] getGlobalImplementations() {
-        Object[] res = { ClusterManager.class, ClusterGlobalManager.class };
+        Object[] res = { ClusterManager.class, ClusterGlobalManager.class, ClusterManagerCLI.class };
         return res;
     }
 
diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerCLI.java b/opendaylight/clustering/services_implementation/src/main/java/org/opendaylight/controller/clustering/services_implementation/internal/ClusterManagerCLI.java
new file mode 100644 (file)
index 0000000..e7927db
--- /dev/null
@@ -0,0 +1,69 @@
+package org.opendaylight.controller.clustering.services_implementation.internal;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.service.command.Descriptor;
+import org.infinispan.AdvancedCache;
+import org.infinispan.distribution.DistributionManager;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.osgi.framework.ServiceRegistration;
+
+public class ClusterManagerCLI {
+    @SuppressWarnings("rawtypes")
+    private ServiceRegistration sr = null;
+
+    public void init() {
+    }
+
+    public void destroy() {
+    }
+
+    public void start() {
+        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put("osgi.command.scope", "odpcontroller");
+        props.put("osgi.command.function", new String[] { "getContainerAdvancedCacheInfo" });
+        this.sr = ServiceHelper.registerGlobalServiceWReg(ClusterManagerCLI.class, this, props);
+    }
+
+    public void stop() {
+        if (this.sr != null) {
+            this.sr.unregister();
+            this.sr = null;
+        }
+    }
+
+    @Descriptor("Get advanced cache infos")
+    public void getContainerAdvancedCacheInfo(@Descriptor("Container for the cache to be fetched") String container,
+            @Descriptor("cache to get information about") String cacheName) {
+        IClusterContainerServices s =
+                (IClusterContainerServices) ServiceHelper.getInstance(IClusterContainerServices.class, container, this);
+        if (s == null) {
+            System.out.println("Could not get an handle to the container cluster service:" + container);
+            return;
+        }
+        if (!s.existCache(cacheName)) {
+            System.out.println("Could not get cache named:" + cacheName);
+        }
+        ConcurrentMap<?, ?> aC = s.getCache(cacheName);
+        if (aC == null) {
+            System.out.println("Could not get cache named:" + cacheName);
+            return;
+        }
+        if (aC instanceof AdvancedCache) {
+            @SuppressWarnings("rawtypes")
+            AdvancedCache advCache = (AdvancedCache) aC;
+            System.out.println("AdvancedCache retrieved!");
+            DistributionManager dMgr = advCache.getDistributionManager();
+            if (dMgr == null) {
+                return;
+            }
+            System.out.println("Routing Table for the Hash:" + dMgr.getConsistentHash()
+                    .getRoutingTableAsString());
+            System.out.println("Get Members:" + dMgr.getConsistentHash()
+                    .getMembers());
+        }
+    }
+}
index 9952069f013c130cfa527abe1e2e6bb8e25b8eb6..0b09f41de54fb987300f797086796d18f65852ef 100644 (file)
@@ -35,6 +35,9 @@
             org.opendaylight.controller.sal.core,
             org.apache.felix.dm
           </Import-Package>
+          <Export-Package>
+            org.opendaylight.controller.clustering.test.internal
+          </Export-Package>
           <Bundle-Activator>
             org.opendaylight.controller.clustering.test.internal.Activator
           </Bundle-Activator>
index 60be87b86d4add14a4feaabae6a211c2d34f981b..52cc56e377e0529c3c39ca4ecf8cd278614cc904 100644 (file)
@@ -344,7 +344,13 @@ public class SimpleClient implements CommandProvider {
                 containerName, cacheName);
         if (c != null) {
             ci.println("\nAdd mapping " + key + " = " + sValue);
-            c.put(key, new StringContainer(sValue));
+            try {
+                c.put(key, new StringContainer(sValue));
+            } catch (Exception e) {
+                ci.println("Exception raised:" + e);
+                ci.println("\tStacktrace:");
+                e.printStackTrace();
+            }
         } else {
             ci.println("Cache " + cacheName + " on container " + containerName
                     + " not existant!");
index 488f8928de478ec8faab7122d93fd8f21cda0a62..2520172d8959a62f5a7fb2af37826c0a27a59dd9 100644 (file)
@@ -479,12 +479,12 @@ public class ContainerFlowConfig implements Serializable {
     }
 
     /**
-     * Returns the protocol
+     * Get the IP protocol value
      *
      * @return the protocol
      */
     public Short getProtoNum() {
-        return protocol == null ? IPProtocols.ANY.shortValue() : IPProtocols.getProtocolNumberShort(protocol);
+        return protocol == null ? null : IPProtocols.getProtocolNumberShort(protocol);
     }
 
     /**
@@ -578,16 +578,15 @@ public class ContainerFlowConfig implements Serializable {
 
     /**
      * Validate the protocol field. Either it can be a enum defined in IPProtocols.java
-     * or a value between 1 and 255
+     * or a valid IP proto value between 0 and 255, see:
+     * http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
+     * for more details.
      *
      * @return true if a valid protocol value
      */
     private boolean hasValidProtocol() {
-        if (protocol != null && !protocol.isEmpty()) {
-            short proto = this.getProtoNum();
-            return (((proto != 0) && (proto > 0) && (proto < 256)) || protocol.equalsIgnoreCase("any"));
-        }
-        return true;
+        IPProtocols p = IPProtocols.fromString(protocol);
+        return p != null;
     }
 
     /**
@@ -664,9 +663,8 @@ public class ContainerFlowConfig implements Serializable {
             mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
             match.setField(MatchType.NW_DST, ip, mask);
         }
-        if (this.protocol != null && !this.protocol.trim().isEmpty() && !this.protocol.equalsIgnoreCase("any")) {
-            match.setField(MatchType.NW_PROTO, IPProtocols
-                    .getProtocolNumberByte(this.protocol));
+        if (IPProtocols.fromString(this.protocol) != IPProtocols.ANY) {
+            match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol));
         }
         if (this.tpSrc != null && !this.tpSrc.trim().isEmpty()) {
             match.setField(MatchType.TP_SRC, Integer.valueOf(tpSrc).shortValue());
index 89d24192455231487b926ce1b727b9cb76c4c71d..1027f8d170d06048d813d6ecdc3cf12616aac17d 100644 (file)
@@ -16,7 +16,6 @@ import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.nio.ByteBuffer;
 import java.util.Collections;
-import java.util.Date;
 import java.util.Dictionary;
 import java.util.EnumSet;
 import java.util.HashSet;
@@ -101,11 +100,6 @@ public class StaticRoutingImplementation implements IfNewHostNotify,
         return staticRouteConfigs;
     }
 
-    public void setStaticRouteConfigs(
-            ConcurrentMap<String, StaticRouteConfig> staticRouteConfigs) {
-        this.staticRouteConfigs = staticRouteConfigs;
-    }
-
     @Override
     public Object readObject(ObjectInputStream ois)
             throws FileNotFoundException, IOException, ClassNotFoundException {
@@ -209,10 +203,13 @@ public class StaticRoutingImplementation implements IfNewHostNotify,
     }
 
     private class NotifyStaticRouteWorker implements Callable<Object> {
+
+        private String name;
         private StaticRoute staticRoute;
         private boolean added;
 
-        public NotifyStaticRouteWorker(StaticRoute s, boolean update) {
+        public NotifyStaticRouteWorker(String name, StaticRoute s, boolean update) {
+            this.name = name;
             this.staticRoute = s;
             this.added = update;
         }
@@ -241,6 +238,10 @@ public class StaticRoutingImplementation implements IfNewHostNotify,
                 if (host != null) {
                     log.debug("Next hop {} is found", nh.getHostAddress());
                     staticRoute.setHost(host);
+                    // static route object has changed
+                    // put the changed object back in the cache
+                    // for it to sync
+                    staticRoutes.put(name, staticRoute);
                     notifyStaticRouteUpdate(staticRoute, added);
                 } else {
                     log.debug("Next hop {}  is still not present, try again later", nh.getHostAddress());
@@ -250,8 +251,8 @@ public class StaticRoutingImplementation implements IfNewHostNotify,
         }
     }
 
-    private void checkAndUpdateListeners(StaticRoute staticRoute, boolean added) {
-        NotifyStaticRouteWorker worker = new NotifyStaticRouteWorker(staticRoute, added);
+    private void checkAndUpdateListeners(String name, StaticRoute staticRoute, boolean added) {
+        NotifyStaticRouteWorker worker = new NotifyStaticRouteWorker(name, staticRoute, added);
         try {
             executor.submit(worker);
         } catch (Exception e) {
@@ -263,17 +264,22 @@ public class StaticRoutingImplementation implements IfNewHostNotify,
         if (host == null) {
             return;
         }
-        for (StaticRoute s : staticRoutes.values()) {
-            if (s.getType() == StaticRoute.NextHopType.SWITCHPORT) {
+        for (Map.Entry<String, StaticRoute> s : staticRoutes.entrySet()) {
+            StaticRoute route = s.getValue();
+            if (route.getType() == StaticRoute.NextHopType.SWITCHPORT) {
                 continue;
             }
-            if (s.getNextHopAddress().equals(host.getNetworkAddress())) {
+            if (route.getNextHopAddress().equals(host.getNetworkAddress())) {
                 if (added) {
-                    s.setHost(host);
+                    route.setHost(host);
                 } else {
-                    s.setHost(null);
+                    route.setHost(null);
                 }
-                notifyStaticRouteUpdate(s, added);
+                // static route object has changed
+                // put the changed object back in the cache
+                // for it to sync
+                staticRoutes.put(s.getKey(), route);
+                notifyStaticRouteUpdate(route, added);
             }
         }
     }
@@ -384,7 +390,7 @@ public class StaticRoutingImplementation implements IfNewHostNotify,
         staticRouteConfigs.put(config.getName(), config);
 
         // Notify
-        checkAndUpdateListeners(sRoute, true);
+        checkAndUpdateListeners(config.getName(), sRoute, true);
         return status;
     }
 
@@ -393,7 +399,7 @@ public class StaticRoutingImplementation implements IfNewHostNotify,
         staticRouteConfigs.remove(name);
         StaticRoute sRoute = staticRoutes.remove(name);
         if (sRoute != null) {
-            checkAndUpdateListeners(sRoute, false);
+            checkAndUpdateListeners(name, sRoute, false);
             return new Status(StatusCode.SUCCESS, null);
         }
         return new Status(StatusCode.NOTFOUND,
@@ -448,10 +454,11 @@ public class StaticRoutingImplementation implements IfNewHostNotify,
         gatewayProbeTimer.schedule(new TimerTask() {
             @Override
             public void run() {
-                for (StaticRoute s : staticRoutes.values()) {
-                    if ((s.getType() == StaticRoute.NextHopType.IPADDRESS)
-                            && s.getHost() == null) {
-                        checkAndUpdateListeners(s, true);
+                for (Map.Entry<String, StaticRoute> s : staticRoutes.entrySet()) {
+                    StaticRoute route = s.getValue();
+                    if ((route.getType() == StaticRoute.NextHopType.IPADDRESS)
+                            && route.getHost() == null) {
+                        checkAndUpdateListeners(s.getKey(), route, true);
                     }
                 }
             }
index 62d6855e109f77ac97baf5107fb2c0efbcaa603e..e0b8e9a786878fe6af6b67dd04aeee52958118db 100644 (file)
@@ -656,11 +656,8 @@ public class FlowConfig implements Serializable {
     }
 
     public boolean isProtocolValid(String protocol) {
-        int protocol_number = IPProtocols.getProtocolNumberInt(protocol);
-        if (protocol_number < 1 || protocol_number > 255) {
-            return false;
-        }
-        return true;
+        IPProtocols proto = IPProtocols.fromString(protocol);
+        return (proto != null);
     }
 
     private Status conflictWithContainerFlow(IContainer container) {
@@ -1033,7 +1030,7 @@ public class FlowConfig implements Serializable {
             mask = NetUtils.getInetNetworkMask(maskLen, ip instanceof Inet6Address);
             match.setField(MatchType.NW_DST, ip, mask);
         }
-        if (this.protocol != null) {
+        if (IPProtocols.fromString(this.protocol) != IPProtocols.ANY) {
             match.setField(MatchType.NW_PROTO, IPProtocols.getProtocolNumberByte(this.protocol));
         }
         if (this.tosBits != null) {
index 6e3e6b6633b0fc6098ee6795dac661df71a20fed..fc18079b0afb4537bb7a38a5da3d01fe3736b07d 100644 (file)
@@ -202,59 +202,6 @@ public class ForwardingRulesManager implements
     private ConcurrentMap<FlowEntryDistributionOrder, FlowEntryDistributionOrderFutureTask> workMonitor =
             new ConcurrentHashMap<FlowEntryDistributionOrder, FlowEntryDistributionOrderFutureTask>();
 
-    /*
-     * Create an executor pool to create the distributionOrder, this is a stop
-     * gap solution caused by an issue with non-transactional caches in the
-     * implementation we use, being currently worked on. It has been noticed in
-     * fact that when non-transactional caches are being used sometime the key
-     * are no distributed to all the nodes properly. To workaround the issue
-     * transactional caches are being used, but there was a reason for using
-     * non-transactional caches to start with, in fact we needed to be able in
-     * the context of a northbound transaction to program the FRM entries
-     * irrespective of the fact that transaction would commit or no else we
-     * would not be able to achieve the entry programming and implement the
-     * scheme for recovery from network element failures. Bottom line, now in
-     * order to make sure an update on a transactional cache goes out while in a
-     * transaction that need to be initiated by a different thread.
-     */
-    private ExecutorService executor;
-
-    class DistributeOrderCallable implements Callable<Future<Status>> {
-        private FlowEntryInstall e;
-        private FlowEntryInstall u;
-        private UpdateType t;
-        DistributeOrderCallable(FlowEntryInstall e, FlowEntryInstall u, UpdateType t) {
-            this.e = e;
-            this.u = u;
-            this.t = t;
-        }
-
-        @Override
-        public Future<Status> call() throws Exception {
-            if (e == null || t == null) {
-                logsync.error("Unexpected null Entry up update type");
-                return null;
-            }
-            // Create the work order and distribute it
-            FlowEntryDistributionOrder fe =
-                    new FlowEntryDistributionOrder(e, t, clusterContainerService.getMyAddress());
-            // First create the monitor job
-            FlowEntryDistributionOrderFutureTask ret = new FlowEntryDistributionOrderFutureTask(fe);
-            logsync.trace("Node {} not local so sending fe {}", e.getNode(), fe);
-            workMonitor.put(fe, ret);
-            if (t.equals(UpdateType.CHANGED)) {
-                // Then distribute the work
-                workOrder.put(fe, u);
-            } else {
-                // Then distribute the work
-                workOrder.put(fe, e);
-            }
-            logsync.trace("WorkOrder requested");
-            // Now create an Handle to monitor the execution of the operation
-            return ret;
-        }
-    }
-
     /**
      * @param e
      *            Entry being installed/updated/removed
@@ -275,21 +222,23 @@ public class ForwardingRulesManager implements
 
         Node n = e.getNode();
         if (connectionManager.getLocalityStatus(n) == ConnectionLocality.NOT_LOCAL) {
-            Callable<Future<Status>> worker = new DistributeOrderCallable(e, u, t);
-            if (worker != null) {
-                Future<Future<Status>> workerRes = this.executor.submit(worker);
-                try {
-                    return workerRes.get();
-                } catch (InterruptedException e1) {
-                    // we where interrupted, not a big deal.
-                    return null;
-                } catch (ExecutionException e1) {
-                    logsync.error(
-                            "We got an execution exception {} we cannot much, so returning we don't have nothing to wait for",
-                            e);
-                    return null;
-                }
+            // Create the work order and distribute it
+            FlowEntryDistributionOrder fe =
+                    new FlowEntryDistributionOrder(e, t, clusterContainerService.getMyAddress());
+            // First create the monitor job
+            FlowEntryDistributionOrderFutureTask ret = new FlowEntryDistributionOrderFutureTask(fe);
+            logsync.trace("Node {} not local so sending fe {}", n, fe);
+            workMonitor.put(fe, ret);
+            if (t.equals(UpdateType.CHANGED)) {
+                // Then distribute the work
+                workOrder.put(fe, u);
+            } else {
+                // Then distribute the work
+                workOrder.put(fe, e);
             }
+            logsync.trace("WorkOrder requested");
+            // Now create an Handle to monitor the execution of the operation
+            return ret;
         }
 
         logsync.trace("Node {} could be local. so processing Entry:{} UpdateType:{}", n, e, t);
@@ -1407,10 +1356,10 @@ public class ForwardingRulesManager implements
                     EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
 
             clusterContainerService.createCache(WORKSTATUSCACHE,
- EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
 
             clusterContainerService.createCache(WORKORDERCACHE,
- EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
 
         } catch (CacheConfigException cce) {
             log.error("CacheConfigException");
@@ -2112,6 +2061,7 @@ public class ForwardingRulesManager implements
      *      pratice to have in it's context operations that can take time,
      *      hence moving off to a different thread for async processing.
      */
+    private ExecutorService executor;
     @Override
     public void modeChangeNotify(final Node node, final boolean proactive) {
         Callable<Status> modeChangeCallable = new Callable<Status>() {
@@ -2512,6 +2462,14 @@ public class ForwardingRulesManager implements
                             } else {
                                 log.warn("Not expected null WorkStatus", work);
                             }
+                        }  else if (event instanceof ContainerFlowChangeEvent) {
+                            /*
+                             * Whether it is an addition or removal, we have to
+                             * recompute the merged flows entries taking into
+                             * account all the current container flows because
+                             * flow merging is not an injective function
+                             */
+                            updateFlowsContainerFlow();
                         } else {
                             log.warn("Dequeued unknown event {}", event.getClass()
                                     .getSimpleName());
@@ -2610,12 +2568,8 @@ public class ForwardingRulesManager implements
         }
         log.trace("Container {}: Updating installed flows because of container flow change: {} {}",
                 container.getName(), t, current);
-        /*
-         * Whether it is an addition or removal, we have to recompute the merged
-         * flows entries taking into account all the current container flows
-         * because flow merging is not an injective function
-         */
-        updateFlowsContainerFlow();
+        ContainerFlowChangeEvent ev = new ContainerFlowChangeEvent(previous, current, t);
+        pendingEvents.offer(ev);
     }
 
     @Override
@@ -2783,6 +2737,30 @@ public class ForwardingRulesManager implements
             return newEntry;
         }
     }
+    private class ContainerFlowChangeEvent extends FRMEvent {
+        private final ContainerFlow previous;
+        private final ContainerFlow current;
+        private final UpdateType type;
+
+        public ContainerFlowChangeEvent(ContainerFlow previous, ContainerFlow current, UpdateType type) {
+            this.previous = previous;
+            this.current = current;
+            this.type = type;
+        }
+
+        public ContainerFlow getPrevious() {
+            return this.previous;
+        }
+
+        public ContainerFlow getCurrent() {
+            return this.current;
+        }
+
+        public UpdateType getType() {
+            return this.type;
+        }
+    }
+
 
     private class WorkStatusCleanup extends FRMEvent {
         private FlowEntryDistributionOrder fe;
index e5d2b48d99b98f2b2d9b9a9d8c145c5b485309c1..e2e1a62325e8198a0367da866d6298e75cd6a81f 100644 (file)
@@ -18,7 +18,6 @@ import java.util.Set;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
-import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
@@ -28,12 +27,14 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriInfo;
-import javax.xml.bind.JAXBElement;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
 import org.codehaus.enunciate.jaxrs.TypeHint;
+import org.opendaylight.controller.containermanager.ContainerConfig;
+import org.opendaylight.controller.containermanager.ContainerFlowConfig;
 import org.opendaylight.controller.containermanager.IContainerAuthorization;
+import org.opendaylight.controller.containermanager.IContainerManager;
 import org.opendaylight.controller.northbound.commons.RestMessages;
 import org.opendaylight.controller.northbound.commons.exception.BadRequestException;
 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
@@ -49,10 +50,6 @@ import org.opendaylight.controller.sal.utils.ServiceHelper;
 import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.usermanager.IUserManager;
 
-import org.opendaylight.controller.containermanager.ContainerFlowConfig;
-import org.opendaylight.controller.containermanager.IContainerManager;
-import org.opendaylight.controller.containermanager.ContainerConfig;
-
 /**
  * Container Manager Northbound API
  *
@@ -117,7 +114,7 @@ public class ContainerManagerNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/containermanager/containers
      *
-     * Response Payload in XML:
+     * Response body in XML:
      * &lt;container-config-list&gt;
      *    &#x20;&#x20;&#x20;&lt;container-config&gt;
      *    &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;container&gt;black&lt;/container&gt;
@@ -141,10 +138,32 @@ public class ContainerManagerNorthbound {
      *  &#x20;&#x20;&#x20;&#x20;&lt;/container-config&gt;
      * &lt;/container-config-list&gt;
      *
-     * Response Payload in JSON:
-     * { "container-config" : [ { "container" : "black", "nodeConnectors" : ["OF|1@OF|00:00:00:00:00:00:00:01", "OF|23@OF|00:00:00:00:00:00:20:21"], "staticVlan" : "10", "flowSpecs : [{ "name": "udp", "protocol": "UDP" }] } ] }
-     * { "container-config" : [ { "container" : "red", "nodeConnectors" : ["OF|1@OF|00:00:00:00:00:00:00:01", "OF|23@OF|00:00:00:00:00:00:20:21"], "staticVlan" : "20", "flowSpecs": [{ "name": "tcp", "protocol": "TCP" }] } ] }
-     *
+     * Response body in JSON:
+     * { "container-config" : [
+     *     { "container" : "black",
+     *       "nodeConnectors" : [
+     *          "OF|1@OF|00:00:00:00:00:00:00:01", "OF|23@OF|00:00:00:00:00:00:20:21"
+     *       ],
+     *       "staticVlan" : "10",
+     *       "flowSpecs : [
+     *          { "name": "udp",
+     *            "protocol": "UDP" }
+     *       ]
+     *     },
+     *     { "container" : "red",
+     *       "nodeConnectors" : [
+     *          "OF|1@OF|00:00:00:00:00:00:00:01",
+     *          "OF|23@OF|00:00:00:00:00:00:20:21"
+     *       ],
+     *       "staticVlan" : "20",
+     *       "flowSpecs": [
+     *          { "name": "tcp",
+     *            "protocol": "TCP"
+     *          }
+     *       ]
+     *     }
+     *   ]
+     * }
      * </pre>
      */
     @Path("/containers")
@@ -177,7 +196,7 @@ public class ContainerManagerNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/containermanager/container/blue
      *
-     * Response Payload in XML:
+     * Response body in XML:
      * &lt;container-config&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;container&gt;blue&lt;/container&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;staticVlan&gt;10&lt;/staticVlan&gt;
@@ -185,9 +204,20 @@ public class ContainerManagerNorthbound {
      *  &#x20;&#x20;&#x20;&#x20;&lt;nodeConnectors&gt;OF|23@OF|00:00:00:00:00:00:20:21&lt;/nodeConnectors&gt;
      * &lt;/container-config&gt;
      *
-     * Response Payload in JSON:
-     * { "container" : "blue", "nodeConnectors" : ["OF|1@OF|00:00:00:00:00:00:00:01", "OF|23@OF|00:00:00:00:00:00:20:21"], "staticVlan" : "10" }
-     *
+     * Response body in JSON:
+     * {
+     *    "container-config": [
+     *       {
+     *        "container": "yellow",
+     *        "staticVlan": "10",
+     *        "nodeConnectors": [
+     *           "OF|1@OF|00:00:00:00:00:00:00:01",
+     *           "OF|2@OF|00:00:00:00:00:00:00:02"
+     *        ],
+     *        "flowSpecs": []
+     *       }
+     *    ]
+     * }
      * </pre>
      */
     @Path("/container/{container}")
@@ -229,15 +259,22 @@ public class ContainerManagerNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/containermanager/container/yellow
      *
-     * Request Payload in XML:
+     * Request body in XML:
      * &lt;container-config&gt;
      *   &#x20;&#x20;&#x20;&#x20;&lt;container&gt;yellow&lt;/container&gt;
      *   &#x20;&#x20;&#x20;&#x20;&lt;staticVlan&gt;10&lt;/staticVlan&gt;
      *   &#x20;&#x20;&#x20;&#x20;&lt;nodeConnectors&gt;&lt;/nodeConnectors&gt;
      * &lt;/container-config&gt;
      *
-     * Request Payload in JSON:
-     * { "container" : "yellow", "nodeConnectors" : ["OF|1@OF|00:00:00:00:00:00:00:01", "OF|23@OF|00:00:00:00:00:00:20:21"], "staticVlan" : "10"}
+     * Request body in JSON:
+     * {
+     *    "container" : "yellow",
+     *    "nodeConnectors" : [
+     *       "OF|1@OF|00:00:00:00:00:00:00:01",
+     *       "OF|23@OF|00:00:00:00:00:00:20:21"
+     *    ],
+     *    "staticVlan" : "10"
+     * }
      *
      * </pre>
      */
@@ -324,18 +361,25 @@ public class ContainerManagerNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/containermanager/container/green/flowspec/ssh
      *
-     * Response Payload in XML:
-     * &lt;container-flowconfig&gt;
+     * Response body in XML:
+     * &lt;flow-spec-config&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;name&gt;ssh&lt;/name&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;nwSrc&gt;10.0.0.101&lt;/nwSrc&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;nwDst&gt;10.0.0.102&lt;/nwDst&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;protocol&gt;IPv4&lt;/protocol&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;tpSrc&gt;80&lt;/tpSrc&gt;
      *  &#x20;&#x20;&#x20;&#x20;&lt;tpDst&gt;100&lt;/tpDst&gt;
-     * &lt;/container-flowconfig&gt;
-     *
-     * Response Payload in JSON:
-     * { "protocol" : "IPv4", "nwDst" : "10.0.0.102", "name" : "ssh", "nwSrc" : "10.0.0.101", "tpSrc" : "80", "tpDst" : "100" }
+     * &lt;/flow-spec-config&gt;
+     *
+     * Response body in JSON:
+     * {
+     *    "protocol" : "IPv4",
+     *    "nwDst" : "10.0.0.102",
+     *    "name" : "ssh",
+     *    "nwSrc" : "10.0.0.101",
+     *    "tpSrc" : "80",
+     *    "tpDst" : "100"
+     * }
      *
      * </pre>
      */
@@ -381,29 +425,47 @@ public class ContainerManagerNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/containermanager/container/red/flowspec
      *
-     * Response Payload in XML:
-     * &lt;container-flowconfigs&gt;
-     *   &#x20;&#x20;&#x20;&#x20;&lt;container-flowconfig&gt;
+     * Response body in XML:
+     * &lt;flow-spec-configs&gt;
+     *   &#x20;&#x20;&#x20;&#x20;&lt;flow-spec-config&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;name&gt;ssh&lt;/name&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;nwSrc&gt;10.0.0.101&lt;/nwSrc&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;nwDst&gt;10.0.0.102&lt;/nwDst&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;protocol&gt;IPv4&lt;/protocol&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;tpSrc&gt;23&lt;/tpSrc&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;tpDst&gt;100&lt;/tpDst&gt;
-     *   &#x20;&#x20;&#x20;&#x20;&lt;/container-flowconfig&gt;
-     *   &#x20;&#x20;&#x20;&#x20;&lt;container-flowconfig&gt;
+     *   &#x20;&#x20;&#x20;&#x20;&lt;/flow-spec-config&gt;
+     *   &#x20;&#x20;&#x20;&#x20;&lt;flow-spec-config&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;name&gt;http2&lt;/name&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;nwSrc&gt;10.0.0.201&lt;/nwSrc&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;nwDst&gt;10.0.0.202&lt;/nwDst&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;protocol&gt;&lt;/protocol&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;tpSrc&gt;80&lt;/tpSrc&gt;
      *     &#x20;&#x20;&#x20;&#x20;&#x20;&#x20;&lt;tpDst&gt;100&lt;/tpDst&gt;
-     *   &#x20;&#x20;&#x20;&#x20;&lt;/container-flowconfig&gt;
-     * &lt;/container-flowconfigs&gt;
-     *
-     * Response Payload in JSON:
-     * { "protocol" : "IPv4", "nwDst" : "10.0.0.102", "name" : "ssh" , "nwSrc" : "10.0.0.101", "tpSrc" : "23", "tpDst" : "100" }
-     * { "protocol" : "", "nwDst" : "10.0.0.202", "name" : "http" , "nwSrc" : "10.0.0.201", "tpSrc" : "80", "tpDst" : "100" }
+     *   &#x20;&#x20;&#x20;&#x20;&lt;/flow-spec-config&gt;
+     * &lt;/flow-spec-configs&gt;
+     *
+      * Response body in JSON:
+     * {
+     *   "flow-spec-config": [
+     *     {
+     *       "name": "http",
+     *       "nwSrc": "10.0.0.201",
+     *       "nwDst": "10.0.0.202",
+     *       "protocol": "",
+     *       "tpSrc": "80",
+     *       "tpDst": "100"
+     *     },
+     *     {
+     *       "name": "ssh",
+     *       "nwSrc": "10.0.0.101",
+     *       "nwDst": "10.0.0.102",
+     *       "protocol": "IPv4",
+     *       "tpSrc": "23",
+     *       "tpDst": "100"
+     *     }
+     *   ]
+     * }
      *
      * </pre>
      */
@@ -446,18 +508,25 @@ public class ContainerManagerNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/containermanager/container/purple/flowspec/http
      *
-     * Request Payload in XML:
-     *   &lt;container-flowconfig&gt;
+     * Request body in XML:
+     *   &lt;flow-spec-config&gt;
      *     &#x20;&#x20;&#x20;&#x20;&lt;name&gt;http&lt;/name&gt;
      *     &#x20;&#x20;&#x20;&#x20;&lt;nwSrc&gt;10.0.0.101&lt;/nwSrc&gt;
      *     &#x20;&#x20;&#x20;&#x20;&lt;nwDst&gt;10.0.0.102&lt;/nwDst&gt;
      *     &#x20;&#x20;&#x20;&#x20;&lt;protocol&gt;&lt;/protocol&gt;
      *     &#x20;&#x20;&#x20;&#x20;&lt;tpSrc&gt;80&lt;/tpSrc&gt;
      *     &#x20;&#x20;&#x20;&#x20;&lt;tpDst&gt;100&lt;/tpDst&gt;
-     *   &lt;/container-flowconfig&gt;
-     *
-     * Request Payload in JSON:
-     * { "protocol" : "", "nwDst" : "10.0.0.102", "name" : "http", "nwSrc" : "10.0.0.101", "tpSrc" : "80", "tpDst" : "100" }
+     *   &lt;/flow-spec-config&gt;
+     *
+     * Request body in JSON:
+     * {
+     *    "protocol" : "",
+     *    "nwDst" : "10.0.0.102",
+     *    "name" : "http",
+     *    "nwSrc" : "10.0.0.101",
+     *    "tpSrc" : "80",
+     *    "tpDst" : "100"
+     * }
      *
      * </pre>
      */
@@ -554,16 +623,23 @@ public class ContainerManagerNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/containermanager/container/green/nodeconnector
      *
-     * Request Payload in XML:
-     * &lt;list&gt;
+     * Request body in XML:
+     * &lt;nodeConnectors&gt;
      *     &lt;nodeConnectors&gt;OF|1@OF|00:00:00:00:00:00:00:01&lt;/nodeConnectors&gt;
      *     &lt;nodeConnectors&gt;OF|2@OF|00:00:00:00:00:00:00:01&lt;/nodeConnectors&gt;
      *     &lt;nodeConnectors&gt;OF|3@OF|00:00:00:00:00:00:00:22&lt;/nodeConnectors&gt;
      *     &lt;nodeConnectors&gt;OF|4@OF|00:00:00:00:00:00:00:22&lt;/nodeConnectors&gt;
-     * &lt;/list&gt;
-     *
-     * Request Payload in JSON:
-     * { "nodeConnectors" : ["OF|1@OF|00:00:00:00:00:00:00:01", "OF|2@OF|00:00:00:00:00:00:00:01", "OF|3@OF|00:00:00:00:00:00:00:22", "OF|4@OF|00:00:00:00:00:00:00:22" }
+     * &lt;/nodeConnectors&gt;
+     *
+     * Request body in JSON:
+     * {
+     *    "nodeConnectors" : [
+     *       "OF|1@OF|00:00:00:00:00:00:00:01",
+     *       "OF|2@OF|00:00:00:00:00:00:00:01",
+     *       "OF|3@OF|00:00:00:00:00:00:00:22",
+     *       "OF|4@OF|00:00:00:00:00:00:00:22"
+     *    ]
+     * }
      *
      * </pre>
      */
@@ -609,16 +685,23 @@ public class ContainerManagerNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/containermanager/container/red/nodeconnector
      *
-     * Request Payload in XML:
-     * &lt;list&gt;
+     * Request body in XML:
+     * &lt;nodeConnectors&gt;
      *     &lt;nodeConnectors&gt;OF|1@OF|00:00:00:00:00:00:00:01&lt;/nodeConnectors&gt;
      *     &lt;nodeConnectors&gt;OF|2@OF|00:00:00:00:00:00:00:01&lt;/nodeConnectors&gt;
      *     &lt;nodeConnectors&gt;OF|3@OF|00:00:00:00:00:00:00:22&lt;/nodeConnectors&gt;
      *     &lt;nodeConnectors&gt;OF|4@OF|00:00:00:00:00:00:00:22&lt;/nodeConnectors&gt;
-     * &lt;/list&gt;
-     *
-     * Request Payload in JSON:
-     * { "nodeConnectors" : ["OF|1@OF|00:00:00:00:00:00:00:01", "OF|2@OF|00:00:00:00:00:00:00:01", "OF|3@OF|00:00:00:00:00:00:00:22", "OF|4@OF|00:00:00:00:00:00:00:22" }
+     * &lt;/nodeConnectors&gt;
+     *
+     * Request body in JSON:
+     * {
+     *    "nodeConnectors" : [
+     *       "OF|1@OF|00:00:00:00:00:00:00:01",
+     *       "OF|2@OF|00:00:00:00:00:00:00:01",
+     *       "OF|3@OF|00:00:00:00:00:00:00:22",
+     *       "OF|4@OF|00:00:00:00:00:00:00:22"
+     *       ]
+     * }
      *
      * </pre>
      */
index 1e88c4430548f6de805ee67c4441f49e6db89f3c..c53e2d0a5ea0f11a03475e0c182236ae8d9271da 100644 (file)
@@ -145,10 +145,10 @@ public class FlowProgrammerNorthbound {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/flowprogrammer/default
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
      * &lt;list&gt;
      *     &#x20;&#x20;&#x20;&lt;flowConfig&gt;
@@ -166,10 +166,26 @@ public class FlowProgrammerNorthbound {
      *     &#x20;&#x20;&#x20;&lt;/flowConfig&gt;
      * &lt;/list&gt;
      *
-     * Response in JSON:
-     * {"flowConfig":{"installInHw":"true","name":"flow1","node":{"id":"00:00:00:00:00:00:00:01","type":"OF"},
-     * "ingressPort":"1","priority":"500","etherType":"0x800","nwSrc":"9.9.1.1","actions":"OUTPUT=2"}}
-     *
+     * Response body in JSON:
+     * {
+     *   "flowConfig": [
+     *      {
+     *         "installInHw": "true",
+     *         "name": "flow1",
+     *         "node": {
+     *            "type": "OF",
+     *            "id": "00:00:00:00:00:00:00:01"
+     *         },
+     *         "ingressPort": "1",
+     *         "priority": "500",
+     *         "etherType": "0x800",
+     *         "nwSrc":"9.9.1.1",
+     *         "actions": [
+     *           "OUTPUT=2"
+     *         ]
+     *      }
+     *    ]
+     * }
      * </pre>
      */
     @Path("/{containerName}")
@@ -205,10 +221,10 @@ public class FlowProgrammerNorthbound {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:00:00:00:00:00:01
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
      * &lt;list&gt;
      *     &#x20;&#x20;&#x20;&lt;flowConfig&gt;
@@ -226,10 +242,26 @@ public class FlowProgrammerNorthbound {
      *     &#x20;&#x20;&#x20;&lt;/flowConfig&gt;
      * &lt;/list&gt;
      *
-     * Response in JSON:
-     * {"flowConfig":{"installInHw":"true","name":"flow1","node":{"id":"00:00:00:00:00:00:00:01","type":"OF"},
-     * "ingressPort":"1","priority":"500","etherType":"0x800","nwSrc":"9.9.1.1","actions":"OUTPUT=2"}}
-     *
+    * Response body in JSON:
+     * {
+     *   "flowConfig": [
+     *      {
+     *         "installInHw": "true",
+     *         "name": "flow1",
+     *         "node": {
+     *            "type": "OF",
+     *            "id": "00:00:00:00:00:00:00:01"
+     *         },
+     *         "ingressPort": "1",
+     *         "priority": "500",
+     *         "etherType": "0x800",
+     *         "nwSrc":"9.9.1.1",
+     *         "actions": [
+     *           "OUTPUT=2"
+     *         ]
+     *       }
+     *    ]
+     * }
      * </pre>
      */
     @Path("/{containerName}/node/{nodeType}/{nodeId}")
@@ -272,10 +304,10 @@ public class FlowProgrammerNorthbound {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:00:00:00:00:00:01/staticFlow/flow1
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
      * &lt;flowConfig&gt;
      *     &#x20;&#x20;&#x20;&lt;installInHw&gt;true&lt;/installInHw&gt;
@@ -291,9 +323,22 @@ public class FlowProgrammerNorthbound {
      *     &#x20;&#x20;&#x20;&lt;actions&gt;OUTPUT=2&lt;/actions&gt;
      * &lt;/flowConfig&gt;
      *
-     * Response in JSON:
-     * {"installInHw":"true","name":"flow1","node":{"id":"00:00:00:00:00:00:00:01","type":"OF"},
-     * "ingressPort":"1","priority":"500","etherType":"0x800","nwSrc":"9.9.1.1","actions":"OUTPUT=2"}
+    * Response body in JSON:
+     * {
+     *    "installInHw":"true",
+     *    "name":"flow1",
+     *    "node":{
+     *       "id":"00:00:00:00:00:00:00:01",
+     *       "type":"OF"
+     *    },
+     *    "ingressPort":"1",
+     *    "priority":"500",
+     *    "etherType":"0x800",
+     *    "nwSrc":"9.9.1.1",
+     *    "actions":[
+     *       "OUTPUT=2"
+     *    ]
+     * }
      *
      * </pre>
      */
@@ -347,10 +392,10 @@ public class FlowProgrammerNorthbound {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/flowprogrammer/default/node/OF/00:00:00:00:00:00:00:01/staticFlow/flow1
      *
-     * Request in XML:
+     * Request body in XML:
      * &lt;flowConfig&gt;
      *         &#x20;&#x20;&#x20;&lt;installInHw&gt;true&lt;/installInHw&gt;
      *         &#x20;&#x20;&#x20;&lt;name&gt;flow1&lt;/name&gt;
@@ -365,10 +410,22 @@ public class FlowProgrammerNorthbound {
      *         &#x20;&#x20;&#x20;&lt;actions&gt;OUTPUT=2&lt;/actions&gt;
      * &lt;/flowConfig&gt;
      *
-     * Request in JSON:
-     * {"installInHw":"true","name":"flow1","node":{"id":"00:00:00:00:00:00:00:01","type":"OF"},
-     * "ingressPort":"1","priority":"500","etherType":"0x800","nwSrc":"9.9.1.1","actions":"OUTPUT=2"}
-     *
+     * Request body in JSON:
+      * {
+     *    "installInHw":"true",
+     *    "name":"flow1",
+     *    "node":{
+     *       "id":"00:00:00:00:00:00:00:01",
+     *       "type":"OF"
+     *    },
+     *    "ingressPort":"1",
+     *    "priority":"500",
+     *    "etherType":"0x800",
+     *    "nwSrc":"9.9.1.1",
+     *    "actions":[
+     *       "OUTPUT=2"
+     *    ]
+     * }
      * </pre>
      */
 
index 836bfa2d60fdd59b62e14d8d8a2c2d9fd247e898..12a49f0996b2652123ce0eb810a5c685801dbf26 100644 (file)
@@ -26,7 +26,6 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriInfo;
-import javax.xml.bind.JAXBElement;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -131,11 +130,10 @@ public class HostTrackerNorthbound {
      *
      * Example:
      *
-     * RequestURL:
-     *
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/hosttracker/default/hosts/active
      *
-     * Response in XML
+     * Response body in XML
      *
      * &lt;list&gt;
      * &#x20;&lt;hostConfig&gt;
@@ -160,7 +158,7 @@ public class HostTrackerNorthbound {
      * &#x20;&lt;/hostConfig&gt;
      * &lt;/list&gt;
      *
-     * Response in JSON:
+     * Response body in JSON:
      *
      * {
      * &#x20;"hostConfig":[
@@ -218,11 +216,10 @@ public class HostTrackerNorthbound {
      *
      * Example:
      *
-     * RequestURL:
-     *
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/hosttracker/default/hosts/inactive
      *
-     * Response in XML
+     * Response body in XML
      *
      * &lt;list&gt;
      * &#x20;&lt;hostConfig&gt;
@@ -247,7 +244,7 @@ public class HostTrackerNorthbound {
      * &#x20;&lt;/hostConfig&gt;
      * &lt;/list&gt;
      *
-     * Response in JSON:
+     * Response body in JSON:
      *
      * {
      * &#x20;"hostConfig":[
@@ -306,11 +303,10 @@ public class HostTrackerNorthbound {
      *
      * Example:
      *
-     * RequestURL:
-     *
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/hosttracker/default/address/1.1.1.1
      *
-     * Response in XML
+     * Response body in XML
      *
      * &lt;hostConfig&gt;
      * &#x20;&lt;dataLayerAddress&gt;00:00:00:00:01:01&lt;/dataLayerAddress&gt;
@@ -323,7 +319,7 @@ public class HostTrackerNorthbound {
      * &#x20;&lt;staticHost&gt;false&lt;/staticHost&gt;
      * &lt;/hostConfig&gt;
      *
-     * Response in JSON:
+     * Response body in JSON:
      *
      * {
      * &#x20;"dataLayerAddress":"00:00:00:00:01:01",
@@ -386,11 +382,10 @@ public class HostTrackerNorthbound {
      *
      * Example:
      *
-     * RequestURL:
-     *
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/hosttracker/default/address/1.1.1.1
      *
-     * Request in XML
+     * Request body in XML
      *
      * &lt;hostConfig&gt;
      * &#x20;&lt;dataLayerAddress&gt;00:00:00:00:01:01&lt;/dataLayerAddress&gt;
@@ -403,7 +398,7 @@ public class HostTrackerNorthbound {
      * &#x20;&lt;staticHost&gt;false&lt;/staticHost&gt;
      * &lt;/hostConfig&gt;
      *
-     * Request in JSON:
+     * Request body in JSON:
      *
      * {
      * &#x20;"dataLayerAddress":"00:00:00:00:01:01",
@@ -472,6 +467,12 @@ public class HostTrackerNorthbound {
      * @param networkAddress
      *            IP Address
      * @return Response as dictated by the HTTP Response code.
+     *
+     * Example:
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/hosttracker/default/address/1.1.1.1
+     *
      */
 
     @Path("/{containerName}/address/{networkAddress}")
index 07f125dae3f79a8428d7609a18c1f4194b2553a1..e765af524d5a6e215531bc7682a644b3d277339c 100644 (file)
@@ -15,7 +15,6 @@ import java.util.List;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
-import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
@@ -25,7 +24,6 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
 import javax.ws.rs.core.UriInfo;
-import javax.xml.bind.JAXBElement;
 
 import org.codehaus.enunciate.jaxrs.ResponseCode;
 import org.codehaus.enunciate.jaxrs.StatusCodes;
@@ -57,7 +55,12 @@ import org.opendaylight.controller.sal.utils.Status;
  * HTTP/1.1 200 OK
  * Content-Type: application/json
  *
- * {"staticRoute":{"name":"route-1","prefix":"10.10.1.0/24","nextHop":"1.1.1.1"}}
+ * { "staticRoute":[
+ *       "name":"route-1",
+ *       "prefix":"10.10.1.0/24",
+ *       "nextHop":"1.1.1.1"
+ *   ]
+ * }
  *
  * </pre>
  *
@@ -114,9 +117,9 @@ public class StaticRoutingNorthbound {
      * Example:
      *
      * Request URL:
-     * GET http://localhost:8080/controller/nb/v2/staticroute/default/routes
+     * http://localhost:8080/controller/nb/v2/staticroute/default/routes
      *
-     * Response in XML:
+     * Response body in XML:
      *  &lt;list&gt;
      *   &lt;staticRoute&gt;
      *     &lt;name&gt;route-1&lt;/name&gt;
@@ -125,9 +128,16 @@ public class StaticRoutingNorthbound {
      *   &lt;/staticRoute&gt;
      *  &lt;/list&gt;
      *
-     * Response in JSON:
-     * {"staticRoute":{"name":"route-1","prefix":"10.10.1.0/24","nextHop":"1.1.1.1"}}
-     *
+     * Response body in JSON:
+     * {
+     *    "staticRoute": [
+     *      {
+     *       "name": "route-1",
+     *       "prefix": "10.10.1.0/24",
+     *       "nextHop": "1.1.1.1"
+     *      }
+     *    ]
+     * }
      * </pre>
      */
     @Path("/{containerName}/routes")
@@ -160,9 +170,9 @@ public class StaticRoutingNorthbound {
      * Example:
      *
      * Request URL:
-     * GET http://localhost:8080/controller/nb/v2/staticroute/default/route/route-1
+     * http://localhost:8080/controller/nb/v2/staticroute/default/route/route-1
      *
-     * Response in XML:
+     * Response body in XML:
      *
      *   &lt;staticRoute&gt;
      *     &lt;name&gt;route-1&lt;/name&gt;
@@ -170,8 +180,12 @@ public class StaticRoutingNorthbound {
      *     &lt;nextHop&gt;1.1.1.1&lt;/nextHop&gt;
      *   &lt;/staticRoute&gt;
      *
-     * Response in JSON:
-     * {"name":"route-1","prefix":"10.10.1.0/24","nextHop":"1.1.1.1"}
+     * Response body in JSON:
+     * {
+     *    "name":"route-1",
+     *    "prefix":"10.10.1.0/24",
+     *    "nextHop":"1.1.1.1"
+     * }
      *
      * </pre>
      */
@@ -216,11 +230,20 @@ public class StaticRoutingNorthbound {
      * Example:
      *
      * Request URL:
-     * PUT http://localhost:8080/controller/nb/v2/staticroute/default/route/route-1
-     *
-     * Request payload in JSON:
-     * {"name":"route-1","prefix":"10.10.1.0/24","nextHop":"1.1.1.1"}
+     * http://localhost:8080/controller/nb/v2/staticroute/default/route/route-1
      *
+     * Request body in XML:
+     * &lt;staticRoute&gt;
+     *   &lt;name&gt;route-1&lt;/name&gt;
+     *   &lt;prefix>10.10.1.0/24&lt;/prefix&gt;
+     *   &lt;nextHop&gt;1.1.1.1&lt;/nextHop&gt;
+     *   &lt;/staticRoute&gt;
+     * Request body in JSON:
+     * {
+     *    "name":"route-1",
+     *    "prefix":"10.10.1.0/24",
+     *    "nextHop":"1.1.1.1"
+     * }
      * </pre>
      */
     @Path("/{containerName}/route/{route}")
index a47bfa70b77e9fa2d0657529df2e676f8ab98f2a..05cb500273c2bca5c2012b251ebea9db02344ebe 100644 (file)
@@ -114,7 +114,7 @@ public class StatisticsNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/statistics/default/flow
      *
-     * Response in JSON:
+     * Response body in JSON:
      * {
      *     "flowStatistics": [
      *         {
@@ -171,7 +171,7 @@ public class StatisticsNorthbound {
      *     ]
      * }
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
      * &lt;list&gt;
      *     &lt;flowStatistics&gt;
@@ -287,7 +287,7 @@ public class StatisticsNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/statistics/default/flow/node/OF/00:00:00:00:00:00:00:01
      *
-     * Response in JSON:
+     * Response body in JSON:
      * {
      *     "node": {
      *         "id":"00:00:00:00:00:00:00:01",
@@ -340,7 +340,7 @@ public class StatisticsNorthbound {
      *     ]
      * }
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
      *     &lt;nodeFlowStatistics&gt;
      *         &lt;node&gt;
@@ -474,7 +474,7 @@ public class StatisticsNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/statistics/default/port
      *
-     * Response in JSON:
+     * Response body in JSON:
      * {
      *     "portStatistics": [
      *         {
@@ -544,7 +544,7 @@ public class StatisticsNorthbound {
      *     ]
      * }
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
      * &lt;list&gt;
      *     &lt;portStatistics&gt;
@@ -662,7 +662,7 @@ public class StatisticsNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/statistics/default/port/node/OF/00:00:00:00:00:00:00:01
      *
-     * Response in JSON:
+     * Response body in JSON:
      * {
      *     "node": {
      *         "id":"00:00:00:00:00:00:00:01",
@@ -716,7 +716,7 @@ public class StatisticsNorthbound {
      *     ]
      * }
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
      * &lt;nodePortStatistics&gt;
      *     &lt;node&gt;
@@ -825,7 +825,7 @@ public class StatisticsNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/statistics/default/table
      *
-     * Response in JSON:
+     * Response body in JSON:
      * {
      *     "tableStatistics": [
      *         {
@@ -857,7 +857,7 @@ public class StatisticsNorthbound {
      *     ]
      * }
      *
-     *  Response in XML:
+     *  Response body in XML:
      *  &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
      *  &lt;list&gt;
      *  &lt;tableStatistics&gt;
@@ -970,7 +970,7 @@ public class StatisticsNorthbound {
      * Request URL:
      * http://localhost:8080/controller/nb/v2/statistics/default/table/node/OF/00:00:00:00:00:00:00:01
      *
-     * Response in JSON:
+     * Response body in JSON:
      * {
      *     "node": {
      *         "id":"00:00:00:00:00:00:00:01",
@@ -1004,7 +1004,7 @@ public class StatisticsNorthbound {
      *    ]
      * }
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
      * &lt;nodeTableStatistics&gt;
      *     &lt;node&gt;
index eb91206bfcdf9bfdf151010e51e54961a43f4f7e..3465dc95addd727ade9243e3410208cc7735ec40 100644 (file)
@@ -112,12 +112,14 @@ public class SubnetsNorthbound {
      *
      * @return a List of SubnetConfig
      *
-     *         <pre>
+     * <pre>
      * Example:
      *
-     * Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnets
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/subnetservice/default/subnets
      *
-     * Response in XML:
+     * Response body in XML:
+     * &lt;list&gt;
      * &lt;subnetConfig&gt;
      *    &lt;name&gt;marketingdepartment&lt;/name&gt;
      *    &lt;subnet&gt;30.31.54.254/24&lt;/subnet&gt;
@@ -125,20 +127,32 @@ public class SubnetsNorthbound {
      * &lt;subnetConfig&gt;
      *    &lt;name&gt;salesdepartment&lt;/name&gt;
      *    &lt;subnet&gt;20.18.1.254/16&lt;/subnet&gt;
-     *    &lt;nodeConnectors&gt;0F|11@OF|00:00:00:aa:bb:cc:dd:ee&gt;/nodeConnectors&gt;
-     *    &lt;nodeConnectors&gt;0F|13@OF|00:00:00:aa:bb:cc:dd:ee&gt;/nodeConnectors&gt;
+     *    &lt;nodeConnectors&gt;OF|11@OF|00:00:00:aa:bb:cc:dd:ee&lt;/nodeConnectors&gt;
+     *    &lt;nodeConnectors&gt;OF|13@OF|00:00:00:aa:bb:cc:dd:ee&lt;/nodeConnectors&gt;
      * &lt;/subnetConfig&gt;
-     *
-     * Response in JSON:
+     * &lt;/list&gt;
+     * Response body in JSON:
      * {
-     *  "name":"marketingdepartment",
-     *  "subnet":"30.31.54.254/24",
-     * }
-     * {
-     *  "name":"salesdepartment",
-     *  "subnet":"20.18.1.254/16",
-     *  "nodeConnectors":["0F|11@OF|00:00:00:aa:bb:cc:dd:ee", "0F|13@OF|00:00:00:aa:bb:cc:dd:ee"]
+     *   "subnetConfig": [
+     *     {
+     *       "name": "marketingdepartment",
+     *       "subnet": "30.31.54.254/24",
+     *       "nodeConnectors": [
+     *           "OF|04@OF|00:00:00:00:00:00:00:04",
+     *           "OF|07@OF|00:00:00:00:00:00:00:07"
+     *       ]
+     *     },
+     *     {
+     *       "name":"salesdepartment",
+     *       "subnet":"20.18.1.254/16",
+     *       "nodeConnectors": [
+     *            "OF|11@OF|00:00:00:aa:bb:cc:dd:ee",
+     *            "OF|13@OF|00:00:00:aa:bb:cc:dd:ee"
+     *        ]
+     *      }
+     *   ]
      * }
+     *
      * </pre>
      */
     @Path("/{containerName}/subnets")
@@ -176,21 +190,25 @@ public class SubnetsNorthbound {
      *         <pre>
      * Example:
      *
-     * Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/marketingdepartment
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/marketingdepartment
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;subnetConfig&gt;
      *    &lt;name&gt;marketingdepartment&lt;/name&gt;
      *    &lt;subnet&gt;30.0.0.1/24&lt;/subnet&gt;
-     *    &lt;nodeConnectors&gt;0F|1@OF|00:00:11:22:33:44:55:66&gt;/nodePorts&gt;
-     *    &lt;nodeConnectors&gt;0F|3@OF|00:00:11:22:33:44:55:66&gt;/nodePorts&gt;
+     *    &lt;nodeConnectors&gt;OF|1@OF|00:00:00:00:00:00:00:01&lt;/nodePorts&gt;
+     *    &lt;nodeConnectors&gt;OF|3@OF|00:00:00:00:00:00:00:03&lt;/nodePorts&gt;
      * &lt;/subnetConfig&gt;
      *
-     * Response in JSON:
+     * Response body in JSON:
      * {
      *  "name":"marketingdepartment",
      *  "subnet":"30.0.0.1/24",
-     *  "nodeConnectors":["0F|1@OF|00:00:11:22:33:44:55:66", "0F|3@OF|00:00:11:22:33:44:55:66"]
+     *  "nodeConnectors":[
+     *       "OF|1@OF|00:00:00:00:00:00:00:01",
+     *       "OF|3@OF|00:00:00:00:00:00:00:03"
+     *   ]
      * }
      * </pre>
      */
@@ -239,21 +257,25 @@ public class SubnetsNorthbound {
      *         <pre>
      * Example:
      *
-     * Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/salesdepartment
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/salesdepartment
      *
-     * Request XML:
+     * Request body in XML:
      *  &lt;subnetConfig&gt;
      *      &lt;name&gt;salesdepartment&lt;/name&gt;
      *      &lt;subnet&gt;172.173.174.254/24&lt;/subnet&gt;
-     *      &lt;nodeConnectors&gt;0F|22@OF|00:00:11:22:33:44:55:66&gt;/nodeConnectors&gt;
-     *      &lt;nodeConnectors&gt;0F|39@OF|00:00:ab:cd:33:44:55:66&gt;/nodeConnectors&gt;
+     *      &lt;nodeConnectors&gt;OF|22@OF|00:00:11:22:33:44:55:66&lt;/nodeConnectors&gt;
+     *      &lt;nodeConnectors&gt;OF|39@OF|00:00:ab:cd:33:44:55:66&lt;/nodeConnectors&gt;
      *  &lt;/subnetConfig&gt;
      *
-     * Request in JSON:
+     * Request body in JSON:
      * {
      *  "name":"salesdepartment",
-     *  "subnet":"172.173.174.254/24"
-     *  "nodeConnectors":["0F|22@OF|00:00:11:22:33:44:55:66", "0F|39@OF|00:00:ab:cd:33:44:55:66"]
+     *  "subnet":"172.173.174.254/24",
+     *  "nodeConnectors":[
+     *       "OF|22@OF|00:00:11:22:33:44:55:66",
+     *       "OF|39@OF|00:00:ab:cd:33:44:55:66"
+     *       ]
      * }
      * </pre>
      */
@@ -308,9 +330,11 @@ public class SubnetsNorthbound {
      *            name of new subnet to be deleted
      * @return Response as dictated by the HTTP Response Status code
      *
-     *         <pre>
+     * <pre>
      * Example:
-     *            Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/engdepartment
+     *
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/engdepartment
      *
      * </pre>
      */
@@ -361,21 +385,25 @@ public class SubnetsNorthbound {
      *         <pre>
      * Example:
      *
-     * Request URL: http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/salesdepartment
+     * Request URL:
+     * http://localhost:8080/controller/nb/v2/subnetservice/default/subnet/salesdepartment
      *
-     *  Request in XML:
+     *  Request body in XML:
      *  &lt;subnetConfig&gt;
      *      &lt;name&gt;salesdepartment&lt;/name&gt;
      *      &lt;subnet&gt;172.173.174.254/24&lt;/subnet&gt;
-     *      &lt;nodeConnectors&gt;0F|22@OF|00:00:11:22:33:44:55:66&gt;/nodeConnectors&gt;
-     *      &lt;nodeConnectors&gt;0F|39@OF|00:00:ab:cd:33:44:55:66&gt;/nodeConnectors&gt;
+     *      &lt;nodeConnectors&gt;OF|22@OF|00:00:11:22:33:44:55:66&lt;/nodeConnectors&gt;
+     *      &lt;nodeConnectors&gt;OF|39@OF|00:00:ab:cd:33:44:55:66&lt;/nodeConnectors&gt;
      *  &lt;/subnetConfig&gt;
      *
-     * Request in JSON:
+     * Request body in JSON:
      * {
      *  "name":"salesdepartment",
-     *  "subnet":"172.173.174.254/24"
-     *  "nodeConnectors":["0F|22@OF|00:00:11:22:33:44:55:66", "0F|39@OF|00:00:ab:cd:33:44:55:66"]
+     *  "subnet":"172.173.174.254/24",
+     *  "nodeConnectors":[
+     *      "OF|22@OF|00:00:11:22:33:44:55:66",
+     *      "OF|39@OF|00:00:ab:cd:33:44:55:66"
+     *  ]
      * }
      * </pre>
      */
index 1777f1a8edcfc0f991acd65ccce6bda77b673ae3..8eff06a763692a4774afe57c7b6a816a0a07d2f3 100644 (file)
@@ -117,10 +117,10 @@ public class SwitchNorthbound {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/switchmanager/default/nodes
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
      * &lt;list&gt;
      *     &#x20;&#x20;&#x20;&lt;nodeProperties&gt;
@@ -155,10 +155,41 @@ public class SwitchNorthbound {
      *     &#x20;&#x20;&#x20;&lt;/nodeProperties&gt;
      * &lt;/list&gt;
      *
-     * Response in JSON:
-     * {"nodeProperties":[{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},"properties":{"tables":{"value":"-1"},
-     * "description":{"value":"None"},"actions":{"value":"4095"},"macAddress":{"value":"00:00:00:00:00:02"},"capabilities"
-     * :{"value":"199"},"timeStamp":{"value":"1377291227877","name":"connectedSince"},"buffers":{"value":"256"}}}]}
+     * Response body in JSON:
+     * {
+     *    "nodeProperties":[
+     *       {
+     *          "node":{
+     *             "id":"00:00:00:00:00:00:00:02",
+     *             "type":"OF"
+     *          },
+     *          "properties":{
+     *             "tables":{
+     *                "value":"-1"
+     *             },
+     *             "description":{
+     *                "value":"None"
+     *             },
+     *             "actions":{
+     *                "value":"4095"
+     *             },
+     *             "macAddress":{
+     *                "value":"00:00:00:00:00:02"
+     *             },
+     *             "capabilities":{
+     *                "value":"199"
+     *             },
+     *             "timeStamp":{
+     *                "value":"1377291227877",
+     *                "name":"connectedSince"
+     *             },
+     *             "buffers":{
+     *                "value":"256"
+     *             }
+     *          }
+     *       }
+     *    ]
+     * }
      *
      * </pre>
      */
@@ -233,7 +264,7 @@ public class SwitchNorthbound {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:03/property/description/Switch3
      *
      * </pre>
@@ -308,7 +339,7 @@ public class SwitchNorthbound {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:03/property/forwarding
      *
      * </pre>
@@ -389,10 +420,10 @@ public class SwitchNorthbound {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/switchmanager/default/node/OF/00:00:00:00:00:00:00:01
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
      * &lt;list&gt;
      *     &#x20;&#x20;&#x20;&lt;nodeConnectorProperties&gt;
@@ -418,9 +449,32 @@ public class SwitchNorthbound {
      *     &#x20;&#x20;&#x20;&lt;/nodeConnectorProperties&gt;
      * &lt;/list&gt;
      *
-     * Response in JSON:
-     * {"nodeConnectorProperties":[{"nodeconnector":{"node":{"id":"00:00:00:00:00:00:00:01","type":"OF"},"id":"2","type":"OF"},
-     * "properties":{"state":{"value":"1"},"config":{"value":"1"},"name":{"value":"L1_2-C2_1"}}}]}
+     * Response body in JSON:
+     * {
+     *    "nodeConnectorProperties":[
+     *       {
+     *          "nodeconnector":{
+     *             "node":{
+     *                "id":"00:00:00:00:00:00:00:01",
+     *                "type":"OF"
+     *             },
+     *             "id":"2",
+     *             "type":"OF"
+     *          },
+     *          "properties":{
+     *             "state":{
+     *                "value":"1"
+     *             },
+     *             "config":{
+     *                "value":"1"
+     *             },
+     *             "name":{
+     *                "value":"L1_2-C2_1"
+     *             }
+     *          }
+     *       }
+     *    ]
+     * }
      *
      * </pre>
      */
@@ -502,7 +556,7 @@ public class SwitchNorthbound {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/switchmanager/default/nodeconnector/OF/00:00:00:00:00:00:00:01/OF/2/property/bandwidth/1
      *
      * </pre>
@@ -582,7 +636,7 @@ public class SwitchNorthbound {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/switchmanager/default/nodeconnector/OF/00:00:00:00:00:00:00:01/OF/2/property/bandwidth
      *
      * </pre>
@@ -638,7 +692,7 @@ public class SwitchNorthbound {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/switchmanager/default/save
      *
      * </pre>
index 461f452d188611cb02f3d9312c2b58f6ea3f4f59..427aa1c1deaaf98c86fa3ecd072757bc6331892c 100644 (file)
@@ -86,10 +86,10 @@ public class TopologyNorthboundJAXRS {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/topology/default
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
      * &lt;topology&gt;
      *     &lt;edgeProperties&gt;
@@ -164,14 +164,75 @@ public class TopologyNorthboundJAXRS {
      *     &lt;/edgeProperties&gt;
      * &lt;/topology&gt;
      *
-     * Response in JSON:
-     * {"edgeProperties":[{"edge":{"tailNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},
-     * "id":"2","type":"OF"},"headNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:51","type":"OF"},"id":
-     * "2","type":"OF"}},"properties":{"timeStamp":{"value":"1377278961017","name":"creation"}}},
-     * {"edge":{"tailNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:51","type":"OF"},"id":
-     * "2","type":"OF"}},"headNodeConnector":{"node":{"id":"00:00:00:00:00:00:00:02","type":"OF"},
-     * "id":"2","type":"OF"}},"properties":{"timeStamp":{"value":"1377278961018","name":"creation"}}}]}
-     *
+     * Response body in JSON:
+     * {
+     *    "edgeProperties":[
+     *       {
+     *          "edge":{
+     *             "tailNodeConnector":{
+     *                "node":{
+     *                   "id":"00:00:00:00:00:00:00:02",
+     *                   "type":"OF"
+     *                },
+     *                "id":"2",
+     *                "type":"OF"
+     *             },
+     *             "headNodeConnector":{
+     *                "node":{
+     *                   "id":"00:00:00:00:00:00:00:51",
+     *                   "type":"OF"
+     *                },
+     *                "id":"2",
+     *                "type":"OF"
+     *             }
+     *          },
+     *          "properties":{
+     *             "timeStamp": {
+     *                "value": 1379527162648,
+     *                "name": "creation",
+     *             },
+     *             "name": {
+     *                "value": "s2-eth3"
+     *             },
+     *             "state": {
+     *                "value": 1
+     *             },
+     *             "config": {
+     *                "value": 1
+     *             },
+     *             "bandwidth": {
+     *                "value": 10000000000
+     *             }
+     *          }
+     *       },
+     *       {
+     *          "edge":{
+     *             "tailNodeConnector":{
+     *                "node":{
+     *                   "id":"00:00:00:00:00:00:00:51",
+     *                   "type":"OF"
+     *                },
+     *                "id":"2",
+     *                "type":"OF"
+     *             },
+     *             "headNodeConnector":{
+     *                "node":{
+     *                   "id":"00:00:00:00:00:00:00:02",
+     *                   "type":"OF"
+     *                },
+     *                "id":"2",
+     *                "type":"OF"
+     *             }
+     *           },
+     *           "properties":{
+     *             "timeStamp": {
+     *                "value": 1379527162648,
+     *                "name": "creation",
+     *             }
+     *          }
+     *        }
+     *     ]
+     *  }
      * </pre>
      */
     @Path("/{containerName}")
@@ -217,23 +278,31 @@ public class TopologyNorthboundJAXRS {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/topology/default/userLinks
      *
-     * Response in XML:
+     * Response body in XML:
      * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
-     * &lt;topologyUserLinks&gt;
+     * &lt;list&gt;
      * &lt;userLinks&gt;
      * &lt;status&gt;Success&lt;/status&gt;
      * &lt;name&gt;link1&lt;/name&gt;
      * &lt;srcNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:02&lt;/srcNodeConnector&gt;
      * &lt;dstNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:51&lt;/dstNodeConnector&gt;
      * &lt;/userLinks&gt;
-     * &lt;/topologyUserLinks&gt;
+     * &lt;/list&gt;
      *
-     * Response in JSON:
-     * {"userLinks":{"status":"Success","name":"link1","srcNodeConnector":
-     * "OF|2@OF|00:00:00:00:00:00:00:02","dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"}}
+     * Response body in JSON:
+    * {
+     *   "userLinks": [
+     *    {
+     *      "status": "Success",
+     *      "name": "link1",
+     *      "srcNodeConnector": "OF|2@OF|00:00:00:00:00:00:00:02",
+     *      "dstNodeConnector": "OF|5@OF|00:00:00:00:00:00:00:05"
+     *    }
+     *  ]
+     * }
      *
      * </pre>
      */
@@ -278,20 +347,25 @@ public class TopologyNorthboundJAXRS {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/topology/default/userLink/link1
      *
-     * Request in XML:
+     * Request body in XML:
      * &lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;
-     * &lt;topologyUserLinks&gt;
+     * &lt;topologyUserLinkConfig&gt;
      * &lt;status&gt;Success&lt;/status&gt;
      * &lt;name&gt;link1&lt;/name&gt;
      * &lt;srcNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:02&lt;/srcNodeConnector&gt;
      * &lt;dstNodeConnector&gt;OF|2@OF|00:00:00:00:00:00:00:51&lt;/dstNodeConnector&gt;
-     * &lt;/topologyUserLinks&gt;
+     * &lt;/topologyUserLinkConfig&gt;
      *
-     * Request in JSON:
-     * {"status":"Success","name":"link1","srcNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:02","dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"}
+     * Request body in JSON:
+     * {
+     *    "status":"Success",
+     *    "name":"link1",
+     *    "srcNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:02",
+     *    "dstNodeConnector":"OF|2@OF|00:00:00:00:00:00:00:51"
+     * }
      *
      * </pre>
      */
@@ -346,7 +420,7 @@ public class TopologyNorthboundJAXRS {
      *
      * Example:
      *
-     * RequestURL:
+     * Request URL:
      * http://localhost:8080/controller/nb/v2/topology/default/userLink/config1
      *
      * </pre>
index 2b8f6553d61cb6202f0576b92b4b5890bc30e7f5..daf1aa8b7168a8b3a4670f21d0468036e42a380f 100644 (file)
@@ -557,6 +557,7 @@ public class FlowConverter {
                         byte tos = (byte) (dscp >> 2);
                         salMatch.setField(MatchType.NW_TOS, tos);
                     }
+                    //TODO: NW protocol 0 is a valid protocol
                     if (ofMatch.getNetworkProtocol() != 0) {
                         salMatch.setField(MatchType.NW_PROTO,
                                 ofMatch.getNetworkProtocol());
index 54be4c67189412a208dc5cfebb6fef2ff49f0301..554d7e2fb3df93564cc7575fe6a83486deaa131f 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.controller.sal.match;
 
 import java.io.Serializable;
+
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
@@ -31,7 +32,7 @@ public class MatchField implements Cloneable, Serializable {
     private Object value; // the value of the field we want to match
     private Object mask; // the value of the mask we want to match on the
     // specified field
-    private transient boolean isValid;
+    private boolean isValid;
 
     // To satisfy JAXB
     @SuppressWarnings("unused")
@@ -176,6 +177,8 @@ public class MatchField implements Cloneable, Serializable {
                     cloned.mask = ((byte[]) this.mask).clone();
                 }
             }
+            cloned.type = this.type;
+            cloned.isValid = this.isValid;
         } catch (CloneNotSupportedException e) {
             logger.error("", e);
         }
index 66e6e65706fc2b23a1498b589a4e94fafbe3e7bf..d3d3142cdfbcf7f06dc81d5cd49d95f0038ee971 100644 (file)
@@ -13,24 +13,25 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * It represents the most common IP protocols numbers
- * It provides the binding between IP protocol names and numbers
- * and provides APIs to read and parse them in either of the two forms
- *
+ * Enum represents the most common IP protocols numbers It provides the binding
+ * between IP protocol names and numbers and provides APIs to read and parse
+ * them in either of the two forms
  *
+ * NOTE: Openflow 1.0 supports the IP Proto match only for ICMP, TCP and UDP
  *
+ * references:
+ * http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
  */
-// Openflow 1.0 supports the IP Proto match only for ICMP, TCP and UDP
 public enum IPProtocols {
-    ANY("any", 0),
-    /*  HOPOPT("HOPOPT",0),
-     */ICMP("ICMP", 1),
-    /*  IGMP("IGMP",2),
+     ANY("any", -1),
+     HOPOPT("HOPOPT",0),
+     ICMP("ICMP", 1),
+     IGMP("IGMP",2),
      GGP("GGP",3),
      IPV4("IPv4",4),
      ST("ST",5),
-     */TCP("TCP", 6),
-    /*  CBT("CBT",7),
+     TCP("TCP", 6),
+     CBT("CBT",7),
      EGP("EGP",8),
      IGP("IGP",9),
      BBNRCCMON("BBN-RCC-MON",10),
@@ -40,8 +41,8 @@ public enum IPProtocols {
      EMCON("EMCON",14),
      XNET("XNET",15),
      CHAOS("CHAOS",16),
-     */UDP("UDP", 17),
-    /*  MUX("MUX",18),
+     UDP("UDP", 17),
+     MUX("MUX",18),
      DCNMEAS("DCN-MEAS",19),
      HMP("HMP",20),
      PRM("PRM",21),
@@ -81,8 +82,8 @@ public enum IPProtocols {
      MOBILE("MOBILE",55),
      TLSP("TLSP",56),
      SKIP("SKIP",57),
-     */IPV6ICMP("IPv6-ICMP", 58);
-    /*  IPV6NoNxt("IPv6-NoNxt",59),
+     IPV6ICMP("IPv6-ICMP", 58),
+     IPV6NoNxt("IPv6-NoNxt",59),
      IPV6Opts("IPv6-Opts",60),
      ANYHOST("ANY-HOST",61),
      CFTP("CFTP",62),
@@ -166,10 +167,15 @@ public enum IPProtocols {
      HIP("HIP",139),
      SHIM6("Shim6",140),
      WESP("WESP",141),
-     ROHC("ROHC",142);
-     */
-    private static final String regexDecimalString = "^[0-9]{3}$";
-    private static final String regexHexString = "^(0(x|X))[0-9a-fA-F]{2}$";
+     ROHC("ROHC",142),
+     /*143-252 Unassigned by IANA*/
+
+     //Experimebtal protocol numbers (http://tools.ietf.org/html/rfc3692)
+     EXP1("Experimental1", 253),
+     EXP2("Experimental2", 254),
+
+     RESERVED("RESERVED",255);
+
     private String protocolName;
     private int protocolNumber;
 
@@ -190,6 +196,7 @@ public enum IPProtocols {
         return ((Integer) protocolNumber).byteValue();
     }
 
+    @Override
     public String toString() {
         return protocolName;
     }
@@ -199,11 +206,11 @@ public enum IPProtocols {
     }
 
     public static String getProtocolName(short number) {
-        return getProtocolNameInternal((int) number & 0xffff);
+        return getProtocolNameInternal(number & 0xffff);
     }
 
     public static String getProtocolName(byte number) {
-        return getProtocolNameInternal((int) number & 0xff);
+        return getProtocolNameInternal(number & 0xff);
     }
 
     private static String getProtocolNameInternal(int number) {
@@ -212,52 +219,35 @@ public enum IPProtocols {
                 return proto.toString();
             }
         }
+        //TODO: this is for backwards compatibility
         return "0x" + Integer.toHexString(number);
     }
 
     public static short getProtocolNumberShort(String name) {
-        if (name.matches(regexHexString)) {
-            return Short.valueOf(Short.decode(name));
-        }
-        if (name.matches(regexDecimalString)) {
-            return Short.valueOf(name);
+        IPProtocols p = fromString(name);
+        if (p != null) {
+            return p.shortValue();
         }
-        for (IPProtocols proto : IPProtocols.values()) {
-            if (proto.protocolName.equalsIgnoreCase(name)) {
-                return proto.shortValue();
-            }
-        }
-        return 0;
+        //This method should be called after validation only
+        throw new IllegalArgumentException("Illegal IP protocol value: " + name);
     }
 
     public static int getProtocolNumberInt(String name) {
-        if (name.matches(regexHexString)) {
-            return Integer.valueOf(Integer.decode(name));
-        }
-        if (name.matches(regexDecimalString)) {
-            return Integer.valueOf(name);
-        }
-        for (IPProtocols proto : IPProtocols.values()) {
-            if (proto.protocolName.equalsIgnoreCase(name)) {
-                return proto.intValue();
-            }
+        IPProtocols p = fromString(name);
+        if (p != null) {
+            return p.intValue();
         }
-        return 0;
+        //This method should be called after validation only
+        throw new IllegalArgumentException("Illegal IP protocol value: " + name);
     }
 
     public static byte getProtocolNumberByte(String name) {
-        if (name.matches(regexHexString)) {
-            return Integer.valueOf(Integer.decode(name)).byteValue();
+        IPProtocols p = fromString(name);
+        if (p != null) {
+            return p.byteValue();
         }
-        if (name.matches(regexDecimalString)) {
-            return Integer.valueOf(name).byteValue();
-        }
-        for (IPProtocols proto : IPProtocols.values()) {
-            if (proto.protocolName.equalsIgnoreCase(name)) {
-                return proto.byteValue();
-            }
-        }
-        return 0;
+        //This method should be called after validation only
+        throw new IllegalArgumentException("Illegal IP protocol value: " + name);
     }
 
     public static List<String> getProtocolNameList() {
@@ -267,4 +257,47 @@ public enum IPProtocols {
         }
         return protoList;
     }
+
+    /**
+     * Method to parse an IPProtocol from a numeric string
+     * (see: {@link Java.Lang.Integer.decode(java.lang.String)} for parsable strings),
+     * or this enum's name string.
+     *
+     * @param s
+     *            The IP protocol string to be parsed
+     * @return The IP protocol Enum, or null if invalid protocol string is passed
+     */
+    public static IPProtocols fromString(String s) {
+        // null/empty/any/* evaluates to ANY
+        if (s == null || s.isEmpty() || s.equalsIgnoreCase("any") || s.equals("*")) {
+            return IPProtocols.ANY;
+        }
+
+        // Try parsing numeric and find the related ENUM
+        try {
+            int protoNum = Integer.decode(s);
+            for (IPProtocols protoEnum : IPProtocols.values()) {
+                if (protoEnum.protocolNumber == protoNum) {
+                    return protoEnum;
+                }
+            }
+            // At this point it's an invalid number (i.e. out of range or not a valid proto num)
+            return null;
+        } catch (NumberFormatException nfe) {
+            // numeric failed try by NAME
+            try {
+                return valueOf(s);
+            } catch(IllegalArgumentException e) {
+                // Neither numeric nor enum NAME, attempt human readable name
+                for (IPProtocols protoEnum : IPProtocols.values()) {
+                    if (protoEnum.toString().equalsIgnoreCase(s)) {
+                        return protoEnum;
+                    }
+                }
+                //couldn't parse, signifies an invalid proto field!
+                return null;
+            }
+
+        }
+    }
 }
diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/IPProtocolsTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/utils/IPProtocolsTest.java
new file mode 100644 (file)
index 0000000..fc6d78c
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ *
+ */
+package org.opendaylight.controller.sal.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/**
+ * @author ykhodork
+ *
+ */
+public class IPProtocolsTest {
+
+    static short shortVal = 1;
+    static int   intVal = 1;
+    static byte  byteVal = 1;
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.utils.IPProtocols#getProtocolName(int)}.
+     */
+    @Test
+    public void testGetProtocolNameInt() {
+        assertEquals("ICMP", IPProtocols.getProtocolName(1));
+        assertEquals("0x4d2", IPProtocols.getProtocolName(1234));
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.utils.IPProtocols#getProtocolName(short)}.
+     */
+    @Test
+    public void testGetProtocolNameShort() {
+        assertEquals("ICMP", IPProtocols.getProtocolName(shortVal));
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.utils.IPProtocols#getProtocolName(byte)}.
+     */
+    @Test
+    public void testGetProtocolNameByte() {
+        assertEquals("ICMP", IPProtocols.getProtocolName(byteVal));
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.utils.IPProtocols#getProtocolNumberShort(java.lang.String)}.
+     */
+    @Test
+    public void testGetProtocolNumberShort() {
+        assertEquals(shortVal, IPProtocols.getProtocolNumberShort("ICMP"));
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.utils.IPProtocols#getProtocolNumberInt(java.lang.String)}.
+     */
+    @Test
+    public void testGetProtocolNumberInt() {
+        assertEquals(intVal, IPProtocols.getProtocolNumberInt("ICMP"));
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.utils.IPProtocols#getProtocolNumberByte(java.lang.String)}.
+     */
+    @Test
+    public void testGetProtocolNumberByte() {
+        assertEquals(byteVal, IPProtocols.getProtocolNumberByte("ICMP"));
+    }
+
+    /**
+     * Test method for {@link org.opendaylight.controller.sal.utils.IPProtocols#fromString(java.lang.String)}.
+     */
+    @Test
+    public void testFromString() {
+        assertTrue(null == IPProtocols.fromString("Not a protocol"));
+        assertTrue(null == IPProtocols.fromString("0xFFF"));
+        assertTrue(null == IPProtocols.fromString("-2"));
+
+        assertTrue(IPProtocols.ANY == IPProtocols.fromString("any"));
+        assertTrue(IPProtocols.ANY == IPProtocols.fromString("ANY"));
+        assertTrue(IPProtocols.ANY == IPProtocols.fromString("*"));
+        assertTrue(IPProtocols.ANY == IPProtocols.fromString(null));
+
+        assertTrue(IPProtocols.TCP == IPProtocols.fromString("TCP"));
+        assertTrue(IPProtocols.TCP == IPProtocols.fromString("tcp"));
+        assertTrue(IPProtocols.UDP == IPProtocols.fromString("0x11"));
+        assertTrue(IPProtocols.UDP == IPProtocols.fromString("0X11"));
+
+    }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
index a6c390d799bb1fa54ac1329436ab2a3b47d2b037..29d2d2b4051a6b89ced33b5e17d81f4f59f47f62 100644 (file)
@@ -114,6 +114,7 @@ public class Topology implements IObjectReader, IConfigurationAware {
         Map<Node, Set<Edge>> nodeEdges = topologyManager.getNodeEdges();
         Map<Node, Set<NodeConnector>> hostEdges = topologyManager
                 .getNodesWithNodeConnectorHost();
+        int hostEdgesHashCode = getHostHashCode(hostEdges, topologyManager);
         List<Switch> nodes = switchManager.getNetworkDevices();
 
         List<SwitchConfig> switchConfigurations = new ArrayList<SwitchConfig>();
@@ -136,14 +137,14 @@ public class Topology implements IObjectReader, IConfigurationAware {
         // return cache if topology hasn't changed
         if (
                 (metaNodeHash.get(containerName) != null && metaHostHash.get(containerName) != null && metaNodeSingleHash.get(containerName) != null && metaNodeConfigurationHash.get(containerName) != null) &&
-                metaNodeHash.get(containerName).equals(nodeEdges.hashCode()) && metaHostHash.get(containerName).equals(hostEdges.hashCode()) && metaNodeSingleHash.get(containerName).equals(nodes.hashCode()) && metaNodeConfigurationHash.get(containerName).equals(switchConfigurations.hashCode())
+                metaNodeHash.get(containerName).equals(nodeEdges.hashCode()) && metaHostHash.get(containerName).equals(hostEdgesHashCode) && metaNodeSingleHash.get(containerName).equals(nodes.hashCode()) && metaNodeConfigurationHash.get(containerName).equals(switchConfigurations.hashCode())
         ) {
                 return metaCache.get(containerName).values();
         }
 
         // cache has changed, we must assign the new values
         metaNodeHash.put(containerName, nodeEdges.hashCode());
-        metaHostHash.put(containerName, hostEdges.hashCode());
+        metaHostHash.put(containerName, hostEdgesHashCode);
         metaNodeSingleHash.put(containerName, nodes.hashCode());
         metaNodeConfigurationHash.put(containerName, switchConfigurations.hashCode());
 
@@ -192,7 +193,11 @@ public class Topology implements IObjectReader, IConfigurationAware {
                 if (edgeIgnore(link)) {
                     continue;
                 }
-                for (Property p : properties.get(link)) {
+                Set<Property> props = properties.get(link);
+                if (props == null) {
+                    continue;
+                }
+                for (Property p : props) {
                     if (p instanceof Bandwidth) {
                         bandwidth = (Bandwidth) p;
                         break;
@@ -330,6 +335,29 @@ public class Topology implements IObjectReader, IConfigurationAware {
         }
     }
 
+    /**
+     * Calculate the total host hashcode
+     *
+     * This is to handle cases where there are multiple hosts per NodeConnector
+     *
+     * @param hostEdges
+     *            - hostEdges data structure
+     * @param topology
+     *            - topology bundle
+     * @return this topology's host hashcode
+     */
+    private int getHostHashCode(Map<Node, Set<NodeConnector>> hostEdges, ITopologyManager topology) {
+        List<Host> hosts = new ArrayList<Host>();
+        for (Set<NodeConnector> nodeConnectors : hostEdges.values()) {
+            for (NodeConnector nodeConnector : nodeConnectors) {
+                List<Host> theseHosts = topology.getHostsAttachedToNodeConnector(nodeConnector);
+                hosts.addAll(theseHosts);
+            }
+        }
+
+        return hosts.hashCode();
+    }
+
     /**
      * Add regular hosts to main topology
      *