Removed the subnet code from AnalyticsManager.java; it's now handled 93/1093/1
authorKatrina LaCurts <katrina.lacurts@plexxi.com>
Wed, 4 Sep 2013 20:06:10 +0000 (16:06 -0400)
committerKatrina LaCurts <katrina.lacurts@plexxi.com>
Wed, 4 Sep 2013 20:06:10 +0000 (16:06 -0400)
by northbound API calls (see analytics.py).

Signed-off-by: Katrina LaCurts <katrina.lacurts@plexxi.com>
analytics/implementation/pom.xml
analytics/implementation/src/main/java/org/opendaylight/controller/analytics/internal/Activator.java
analytics/implementation/src/main/java/org/opendaylight/controller/analytics/internal/AnalyticsManager.java
analytics/implementation/src/main/java/org/opendaylight/controller/analytics/internal/HostStats.java
scripts/analytics.py

index 14702499a40187f9859684aedaacaf583f2f6a9f..a8c0d5dcc60065f1246fbc639f7283deffb4c5a0 100644 (file)
@@ -23,6 +23,7 @@
         <configuration>
           <instructions>
             <Import-Package>
+              org.opendaylight.controller.affinity,
               org.opendaylight.controller.analytics,
               org.opendaylight.controller.clustering.services,
               org.opendaylight.controller.hosttracker,
@@ -34,7 +35,6 @@
               org.opendaylight.controller.sal.reader,
               org.opendaylight.controller.sal.utils,
               org.opendaylight.controller.statisticsmanager,
-              org.opendaylight.controller.switchmanager,
               org.apache.felix.dm,
               org.slf4j
             </Import-Package>
     </plugins>
   </build>
   <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>affinity</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
       <artifactId>analytics</artifactId>
       <artifactId>statisticsmanager</artifactId>
       <version>0.4.0-SNAPSHOT</version>
     </dependency>
-    <dependency>
-      <groupId>org.opendaylight.controller</groupId>
-      <artifactId>switchmanager</artifactId>
-      <version>0.5.0-SNAPSHOT</version>
-    </dependency>
   </dependencies>
 </project>
index e3dfac2e29081d54f2a0bf1850986eb4baa1fb97..cf7de7fb90a961d2cd8ac129d57a83fbfa198406 100644 (file)
@@ -13,6 +13,7 @@ import org.apache.felix.dm.Component;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.opendaylight.controller.affinity.IAffinityManager;
 import org.opendaylight.controller.analytics.IAnalyticsManager;
 import org.opendaylight.controller.clustering.services.IClusterContainerServices;
 import org.opendaylight.controller.hosttracker.IfIptoHost;
@@ -21,7 +22,6 @@ import org.opendaylight.controller.sal.core.IContainer;
 import org.opendaylight.controller.sal.reader.IReadService;
 import org.opendaylight.controller.sal.reader.IReadServiceListener;
 import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
 
 public class Activator extends ComponentActivatorAbstractBase {
     protected static final Logger logger = LoggerFactory
@@ -79,8 +79,8 @@ public class Activator extends ComponentActivatorAbstractBase {
                   .setCallbacks("setHostTracker", "unsetHostTracker").setRequired(true));
             c.add(createServiceDependency().setService(IStatisticsManager.class)
                   .setCallbacks("setStatisticsManager", "unsetStatisticsManager").setRequired(false));
-            c.add(createContainerServiceDependency(containerName).setService(ISwitchManager.class)
-                  .setCallbacks("setSwitchManager", "unsetSwitchManager").setRequired(true));
+            c.add(createContainerServiceDependency(containerName).setService(IAffinityManager.class)
+                  .setCallbacks("setAffinityManager", "unsetAffinityManager").setRequired(true));
 
             c.add(createContainerServiceDependency(containerName).setService(IReadService.class)
                     .setCallbacks("setReaderService", "unsetReaderService").setRequired(true));
index 68f1f632b8b248159d7ff32a4756c94ace5f2c43..8795289bce4f1645973c403a84d1b9b27385177c 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.controller.analytics.internal;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -18,6 +20,8 @@ import java.util.Set;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.opendaylight.controller.affinity.AffinityGroup;
+import org.opendaylight.controller.affinity.IAffinityManager;
 import org.opendaylight.controller.analytics.IAnalyticsManager;
 import org.opendaylight.controller.hosttracker.IfIptoHost;
 import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
@@ -34,16 +38,15 @@ import org.opendaylight.controller.sal.reader.IReadServiceListener;
 import org.opendaylight.controller.sal.reader.NodeConnectorStatistics;
 import org.opendaylight.controller.sal.reader.NodeDescription;
 import org.opendaylight.controller.sal.reader.NodeTableStatistics;
+import org.opendaylight.controller.sal.utils.Status;
 import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.switchmanager.SubnetConfig;
 
 public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager {
 
     private static final Logger log = LoggerFactory.getLogger(AnalyticsManager.class);
 
+    private IAffinityManager affinityManager;
     private IStatisticsManager statisticsManager;
-    private ISwitchManager switchManager;
     private IfIptoHost hostTracker;
 
     private Map<MatchField, Host> destinationHostCache;
@@ -72,6 +75,26 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
         log.debug("STOP called!");
     }
 
+    void setAffinityManager(IAffinityManager a) {
+        this.affinityManager = a;
+
+        // TODO: This is just for testing
+        AffinityGroup ag1 = new AffinityGroup("testAG1");
+        ag1.add("10.0.0.1");
+        ag1.add("10.0.0.2");
+        AffinityGroup ag2 = new AffinityGroup("testAG2");
+        ag2.add("10.0.0.3");
+        ag2.add("10.0.0.4");
+        this.affinityManager.addAffinityGroup(ag1);
+        this.affinityManager.addAffinityGroup(ag2);
+    }
+
+    void unsetAffinityManager(IAffinityManager a) {
+        if (this.affinityManager.equals(a)) {
+            this.affinityManager = null;
+        }
+    }
+
     void setStatisticsManager(IStatisticsManager s) {
         this.statisticsManager = s;
     }
@@ -92,21 +115,6 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
         }
     }
 
-    void setSwitchManager(ISwitchManager s) {
-        this.switchManager = s;
-
-        // Add a default subnet to allow the hostTracker to populate
-        // the host lists.
-        SubnetConfig defaultSubnet = new SubnetConfig("default", "10.0.0.254/8", new HashSet<String>());
-        this.switchManager.addSubnet(defaultSubnet);
-    }
-
-    void unsetSwitchManager(ISwitchManager s) {
-        if (this.switchManager.equals(s)) {
-            this.switchManager = null;
-        }
-    }
-
     /* Returns the destination host associated with this flow, if one
      * exists.  Returns null otherwise.
      */
@@ -195,9 +203,47 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
         return bitRate;
     }
 
+    // TODO: This functionality should be more general, and a part of
+    // the affinity group class.
+    private boolean hostIsInAffinity(Host h, AffinityGroup a) {
+        Set<String> ips = a.getIPs();
+        InetAddress hostAddress = h.getNetworkAddress();
+        for (String ip : ips) {
+            try {
+                InetAddress thisAddress = InetAddress.getByName(ip);
+                if (hostAddress.equals(thisAddress)) {
+                    return true;
+                }
+            } catch (UnknownHostException e) {
+            }
+        }
+        return false;
+    }
+
+    public long getByteCountBetweenAffinities(AffinityGroup a1, AffinityGroup a2) {
+        // TODO: Cache for host-to-AG mapping
+        Set<HostNodeConnector> allHosts = this.hostTracker.getAllHosts();
+        long b = 0;
+        for (Host h1 : allHosts) {
+            for (Host h2 : allHosts) {
+                if (hostIsInAffinity(h1, a1) && hostIsInAffinity(h2, a2)) {
+                    b += getByteCountBetweenHosts(h1, h2);
+                }
+            }
+        }
+        return b;
+    }
+
     @Override
     public void nodeFlowStatisticsUpdated(Node node, List<FlowOnNode> flowStatsList) {
 
+        // TODO: Start testing
+        /*AffinityGroup ag1 = this.affinityManager.getAffinityGroup("testAG1");
+        AffinityGroup ag2 = this.affinityManager.getAffinityGroup("testAG2");
+        long b = getByteCountBetweenAffinities(ag1, ag2);
+        System.out.println("!!! " + b + " bytes");*/
+        // TODO: End testing
+
         Set<HostNodeConnector> allHosts = this.hostTracker.getAllHosts();
         for (FlowOnNode f : flowStatsList) {
             Host srcHost = getSourceHostFromFlow(f.getFlow(), allHosts);
index 0ac28ec4d518731dc225588835c9950e9824a1f0..2965ecc55951257406a4104e260c8fb7c57156c5 100644 (file)
@@ -42,8 +42,6 @@ public class HostStats {
     }
 
     public double getBitRate() {
-        System.out.println("!!! byte count: " + this.byteCount);
-        System.out.println("!!! duration: " + this.duration);
         return (this.byteCount * 8)/(this.duration);
     }
 }
\ No newline at end of file
index ed47e3a296c511cbd6b82e1c52a7e93db9c66c03..c87b36e3cd49595c9bd726088242569d64161d9e 100644 (file)
@@ -13,6 +13,9 @@ import sys
 # Should see output like: "xxx bytes between 10.0.0.1 and 10.0.0.2",
 # where xxx is a positive integer.
 
+'''
+Class to keep track of host statistics (byte count, bit rate)
+'''
 class HostStats:
 
     def __init__(self, src, dst):
@@ -25,19 +28,16 @@ class HostStats:
     def refresh(self):
         resp, content = self.http.request("http://localhost:8080/controller/nb/v2/analytics/default/hoststats/" + self.src + "/" + self.dst, "GET")
         if (resp.status == 404):
-            print "404 Error; exiting"
-            sys.exit()
+            return
         if (resp.status == 503):
-            print "503 Error; exiting"
-            sys.exit()
+            return
         self.host_stats = json.loads(content)
 
     def get_bytes(self):
         try:
             bytes = long(self.host_stats["byteCount"])
         except Exception as e:
-            print "exception: ", e
-            bytes = None
+            bytes = 0
         return bytes
 
     def get_bit_rate(self):
@@ -45,17 +45,59 @@ class HostStats:
         try:
             bitrate = float(self.host_stats["bitRate"])
         except Exception as e:
-            print "exception: ", e
-            bitrate = None
+            bitrate = 0.0
         return bitrate
 
+'''
+Class for controlling subnets.  Right now, just adds subnets and
+checks whether they exist, because that's all we need.
+'''
+class SubnetControl:
+
+    def __init__(self):
+        self.http = httplib2.Http(".cache")
+        self.http.add_credentials("admin", "admin")
+
+    # Checks whether subnet exists.  Checks against the actual subnet
+    # string (e.g., "10.0.0.255/1"), not the subnet name.  Will not
+    # catch things like overlapping subnets.
+    def exists(self, subnet):
+        resp, content = self.http.request("http://localhost:8080/controller/nb/v2/subnet/default/subnet/all", "GET")
+        data = json.loads(content)
+        for key in data:
+            if (data[key]["subnet"] == subnet):
+                return True
+        return False
+
+    # Add a subnet if it doesn't already exist.
+    def add_subnet(self, subnet_name, subnet):
+        if (self.exists(subnet)):
+            print "subnet", subnet, "already exists"
+            return
+        subnet_config = dict(name=subnet_name, subnet=subnet)
+        json_data = json.dumps(subnet_config)
+        resp, content = self.http.request("http://localhost:8080/controller/nb/v2/subnet/default/subnet/" + subnet_name, "POST", json_data, {'Content-Type': 'application/json'})
+        if (resp.status == 201):
+            print "subnet", subnet, "added"
+        else:
+            print "subnet", subnet, "could not be added"
+
+
 def main():
+
+    # Default subnet is required for the host tracker to work.  Run
+    # this script once *before* you start mininet.
+    subnet_control = SubnetControl()
+    subnet_control.add_subnet("defaultSubnet", "10.0.0.254/8")
+
     src = "10.0.0.1"
     dst = "10.0.0.2"
+    host_stat = HostStats(src, dst)
+
+    # These counts should be nonzero
+    print("%d bytes between %s and %s" % (host_stat.get_bytes(), src, dst))
+    print("%f mbit/s between %s and %s" % (host_stat.get_bit_rate(), src, dst))
 
-    h = HostStats(src, dst)
-    print("%d bytes between %s and %s" % (h.get_bytes(), src, dst))
-    print("%f mbit/s between %s and %s" % (h.get_bit_rate(), src, dst))
 
 if __name__ == "__main__":
     main()