--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.opendaylight</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../../commons/opendaylight</relativePath>
+ </parent>
+ <artifactId>analytics</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.6</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ org.opendaylight.controller.sal.core,
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.controller.analytics
+ </Export-Package>
+ </instructions>
+ <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 Plexxi, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.analytics;
+
+import org.opendaylight.controller.sal.core.Host;
+
+public interface IAnalyticsManager {
+
+ long getByteCountBetweenHosts(Host src, Host dst);
+
+ double getBitRateBetweenHosts(Host src, Host dst);
+}
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>affinity</artifactId>
- <version>0.4.1-SNAPSHOT</version>
- <relativePath>..</relativePath>
+ <artifactId>commons.opendaylight</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../commons/opendaylight</relativePath>
</parent>
- <artifactId>analytics</artifactId>
- <version>0.4.1-SNAPSHOT</version>
+ <artifactId>analytics.implementation</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<build>
<configuration>
<instructions>
<Import-Package>
+ org.opendaylight.controller.analytics,
org.opendaylight.controller.clustering.services,
- org.opendaylight.controller.containermanager,
- org.opendaylight.controller.forwardingrulesmanager,
org.opendaylight.controller.hosttracker,
org.opendaylight.controller.hosttracker.hostAware,
org.opendaylight.controller.sal.core,
org.opendaylight.controller.sal.flowprogrammer,
- org.opendaylight.controller.sal.inventory,
org.opendaylight.controller.sal.match,
- org.opendaylight.controller.sal.packet,
org.opendaylight.controller.sal.packet.address,
org.opendaylight.controller.sal.reader,
org.opendaylight.controller.sal.utils,
<dependencies>
<dependency>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>containermanager</artifactId>
+ <artifactId>analytics</artifactId>
<version>0.4.0-SNAPSHOT</version>
</dependency>
<dependency>
<artifactId>clustering.services</artifactId>
<version>0.4.0-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>forwardingrulesmanager</artifactId>
- <version>0.4.0-SNAPSHOT</version>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>hosttracker</artifactId>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager</artifactId>
- <version>0.4.0-SNAPSHOT</version>
+ <version>0.5.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.opendaylight.controller.analytics.IAnalyticsManager;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.hosttracker.IfIptoHost;
-import org.opendaylight.controller.hosttracker.IfHostListener;
import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+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;
if (imp.equals(AnalyticsManager.class)) {
// set interfaces
c.setInterface(new String[] {
- IReadServiceListener.class.getName() }, null);
+ IReadServiceListener.class.getName(),
+ IAnalyticsManager.class.getName()}, null);
c.add(createContainerServiceDependency(containerName).setService(IfIptoHost.class)
.setCallbacks("setHostTracker", "unsetHostTracker").setRequired(true));
.setCallbacks("setStatisticsManager", "unsetStatisticsManager").setRequired(false));
c.add(createContainerServiceDependency(containerName).setService(ISwitchManager.class)
.setCallbacks("setSwitchManager", "unsetSwitchManager").setRequired(true));
+
+ c.add(createContainerServiceDependency(containerName).setService(IReadService.class)
+ .setCallbacks("setReaderService", "unsetReaderService").setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(IClusterContainerServices.class)
+ .setCallbacks("setClusterContainerService", "unsetClusterContainerService").setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(IContainer.class)
+ .setCallbacks("setIContainer", "unsetIContainer").setRequired(true));
}
}
}
package org.opendaylight.controller.analytics.internal;
-import java.lang.reflect.Constructor;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.opendaylight.controller.containermanager.IContainerManager;
+import org.opendaylight.controller.analytics.IAnalyticsManager;
import org.opendaylight.controller.hosttracker.IfIptoHost;
-import org.opendaylight.controller.hosttracker.IfHostListener;
import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
import org.opendaylight.controller.sal.core.Host;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.match.Match;
import org.opendaylight.controller.sal.match.MatchField;
import org.opendaylight.controller.sal.match.MatchType;
-import org.opendaylight.controller.sal.packet.address.DataLinkAddress;
import org.opendaylight.controller.sal.packet.address.EthernetAddress;
import org.opendaylight.controller.sal.reader.FlowOnNode;
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.ServiceHelper;
-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 {
+public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager {
private static final Logger log = LoggerFactory.getLogger(AnalyticsManager.class);
private ISwitchManager switchManager;
private IfIptoHost hostTracker;
- private Map<Host, Map<Host, Object>> hostToFlowStats; // TODO: Tighter object types
private Map<MatchField, Host> destinationHostCache;
private Map<MatchField, Host> sourceHostCache;
+ private Map<Host, Map<Host, HostStats>> hostsToStats;
void init() {
log.debug("INIT called!");
- this.hostToFlowStats = new HashMap<Host, Map<Host, Object>>();
this.destinationHostCache = new HashMap<MatchField, Host>();
this.sourceHostCache = new HashMap<MatchField, Host>();
+ this.hostsToStats = new HashMap<Host, Map<Host, HostStats>>();
}
void destroy() {
// Add a default subnet to allow the hostTracker to populate
// the host lists.
- //
- // TODO: Is this really the correct way to get the hosts
- // populated?
- //
- // TODO: This is should really use the second SubnetConfig
- // constructor; see a note in that file.
- SubnetConfig defaultSubnet = new SubnetConfig();
+ SubnetConfig defaultSubnet = new SubnetConfig("default", "10.0.0.254/8", new HashSet<String>());
this.switchManager.addSubnet(defaultSubnet);
}
/* Returns the destination host associated with this flow, if one
* exists. Returns null otherwise.
*/
- private Host getDestinationHostFromFlow(Flow flow) {
+ protected Host getDestinationHostFromFlow(Flow flow, Set<HostNodeConnector> hosts) {
Host dstHost = null;
Match match = flow.getMatch();
// strings (comparing MAC address bytes, surprisingly, did
// not work).
String dstMac = MatchType.DL_DST.stringify(dlDst.getValue());
- for (HostNodeConnector h : this.hostTracker.getAllHosts()) {
+ for (HostNodeConnector h : hosts) {
String hostMac = ((EthernetAddress) h.getDataLayerAddress()).getMacAddress();
if (dstMac.equals(hostMac)) {
dstHost = h;
/* Returns the source Host associated with this flow, if one
* exists. Returns null otherwise.
*/
- private Host getSourceHostFromFlow(Flow flow) {
+ protected Host getSourceHostFromFlow(Flow flow, Set<HostNodeConnector> hosts) {
Host srcHost = null;
Match match = flow.getMatch();
// Find the source host by comparing the NodeConnectors
NodeConnector inPortNc = (NodeConnector) inPort.getValue();
- for (HostNodeConnector h : this.hostTracker.getAllHosts()) {
+ for (HostNodeConnector h : hosts) {
NodeConnector hostNc = h.getnodeConnector();
if (hostNc.equals(inPortNc)) {
srcHost = h;
public long getByteCountBetweenHosts(Host src, Host dst) {
- // TODO: Need a cache so that we don't have to search through all nodes.
-
- List<FlowOnNode> relevantFlows = new ArrayList<FlowOnNode>();
-
- Set<Node> allNodes = this.switchManager.getNodes();
- for (Node node : allNodes) {
- List<FlowOnNode> flowsOnNode = this.statisticsManager.getFlows(node);
- for (FlowOnNode f : flowsOnNode) {
- Host dstHost = getDestinationHostFromFlow(f.getFlow());
- Host srcHost = getSourceHostFromFlow(f.getFlow());
-
- // This does not indicate error, it's just a flow we're
- // not interested in (ARP traffic, e.g.)
- if (dstHost == null || srcHost == null) {
- continue;
- }
-
- if (dstHost.equals(dst) && srcHost.equals(src)) {
- relevantFlows.add(f);
- }
- }
- }
-
long byteCount = 0;
- for (FlowOnNode f : relevantFlows) {
- if (f.getByteCount() > byteCount) {
- byteCount = f.getByteCount();
- }
+ if (this.hostsToStats.get(src) != null &&
+ this.hostsToStats.get(src).get(dst) != null) {
+ byteCount = this.hostsToStats.get(src).get(dst).getByteCount();
}
return byteCount;
}
+ public double getBitRateBetweenHosts(Host src, Host dst) {
+ double bitRate = 0;
+ if (this.hostsToStats.get(src) != null &&
+ this.hostsToStats.get(src).get(dst) != null) {
+ bitRate = this.hostsToStats.get(src).get(dst).getBitRate();
+ }
+
+ return bitRate;
+ }
+
@Override
public void nodeFlowStatisticsUpdated(Node node, List<FlowOnNode> flowStatsList) {
- // TODO: un-comment out if testing
- /*
- for (HostNodeConnector h1 : this.hostTracker.getAllHosts()) {
- for (HostNodeConnector h2 : this.hostTracker.getAllHosts()) {
- long b = getByteCountBetweenHosts(h1, h2);
- System.out.println("!!! result:");
- System.out.println("!!! " + h1);
- System.out.println("!!! " + h2);
- System.out.println("!!! " + b);
+
+ Set<HostNodeConnector> allHosts = this.hostTracker.getAllHosts();
+ for (FlowOnNode f : flowStatsList) {
+ Host srcHost = getSourceHostFromFlow(f.getFlow(), allHosts);
+ Host dstHost = getDestinationHostFromFlow(f.getFlow(), allHosts);
+
+ if (this.hostsToStats.get(srcHost) == null) {
+ this.hostsToStats.put(srcHost, new HashMap<Host, HostStats>());
}
- }*/
+ if (this.hostsToStats.get(srcHost).get(dstHost) == null) {
+ this.hostsToStats.get(srcHost).put(dstHost, new HostStats());
+ }
+ this.hostsToStats.get(srcHost).get(dstHost).setStatsFromFlow(f);
+ }
}
@Override
public void descriptionStatisticsUpdated(Node node, NodeDescription nodeDescription) {
// Not interested in this update
}
-}
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2013 Plexxi, Inc. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.analytics.internal;
+
+import org.opendaylight.controller.sal.reader.FlowOnNode;
+
+public class HostStats {
+
+ private long byteCount;
+ private double duration;
+
+ public HostStats() {
+ this.byteCount = 0;
+ this.duration = 0;
+ }
+
+ public long getByteCount() {
+ return this.byteCount;
+ }
+
+ public void setByteCount(long byteCount) {
+ this.byteCount = byteCount;
+ }
+
+ public double getDuration() {
+ return this.duration;
+ }
+
+ public void setDuration(double duration) {
+ this.duration = duration;
+ }
+
+ public void setStatsFromFlow(FlowOnNode flow) {
+ this.byteCount = flow.getByteCount();
+ this.duration = flow.getDurationSeconds() + .000000001 * flow.getDurationNanoseconds();
+ }
+
+ 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
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Plexxi, Inc. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.analytics.internal;\r
+\r
+import java.net.InetAddress;\r
+import java.net.UnknownHostException;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import junit.framework.TestCase;\r
+import org.junit.Assert;\r
+import org.junit.Test;\r
+\r
+import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;\r
+import org.opendaylight.controller.sal.core.ConstructionException;\r
+import org.opendaylight.controller.sal.core.Host;\r
+import org.opendaylight.controller.sal.core.Node;\r
+import org.opendaylight.controller.sal.core.NodeConnector;\r
+import org.opendaylight.controller.sal.flowprogrammer.Flow;\r
+import org.opendaylight.controller.sal.match.Match;\r
+import org.opendaylight.controller.sal.match.MatchField;\r
+import org.opendaylight.controller.sal.match.MatchType;\r
+import org.opendaylight.controller.sal.reader.FlowOnNode;\r
+\r
+public class AnalyticsManagerTest extends TestCase {\r
+\r
+ @Test\r
+ public void testAnalyticsManagerCreation() {\r
+ AnalyticsManager am = new AnalyticsManager();\r
+ Assert.assertTrue(am != null);\r
+ }\r
+\r
+ @Test\r
+ public void testGetHostsFromFlows() {\r
+\r
+ AnalyticsManager am = new AnalyticsManager();\r
+ am.init();\r
+\r
+ try {\r
+ // Set up nodes\r
+ Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(100L));\r
+ Node n2 = new Node(Node.NodeIDType.OPENFLOW, new Long(101L));\r
+ Node n3 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L));\r
+ Node n4 = new Node(Node.NodeIDType.OPENFLOW, new Long(111L));\r
+\r
+ // Set up node connectors\r
+ NodeConnector nc1 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, new Short((short) 0xCAFC), n1);\r
+ NodeConnector nc2 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, new Short((short) 0xCAFD), n2);\r
+ NodeConnector nc3 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, new Short((short) 0xCAFE), n3);\r
+ NodeConnector nc4 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, new Short((short) 0xCAFF), n4);\r
+\r
+ // Set up host node connectors\r
+ HostNodeConnector hnc1 = new HostNodeConnector(new byte[]{0,0,0,0,0,1}, InetAddress.getByName("10.0.0.1"), nc1, (short) 1);\r
+ HostNodeConnector hnc2 = new HostNodeConnector(new byte[]{0,0,0,0,0,2}, InetAddress.getByName("10.0.0.2"), nc2, (short) 1);\r
+ HostNodeConnector hnc3 = new HostNodeConnector(new byte[]{0,0,0,0,0,3}, InetAddress.getByName("10.0.0.3"), nc3, (short) 1);\r
+ Set<HostNodeConnector> hosts = new HashSet<HostNodeConnector>(Arrays.asList(hnc1, hnc2, hnc3));\r
+\r
+ // Set up a flow from nc1 to nc2\r
+ Match match = new Match();\r
+ match.setField(new MatchField(MatchType.IN_PORT, nc1));\r
+ match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,2}));\r
+ Flow f = new Flow();\r
+ f.setMatch(match);\r
+\r
+ Host dstHost = am.getDestinationHostFromFlow(f, hosts);\r
+ Host srcHost = am.getSourceHostFromFlow(f, hosts);\r
+\r
+ Assert.assertTrue(dstHost.equals(hnc2));\r
+ Assert.assertTrue(srcHost.equals(hnc1));\r
+\r
+ // Set up a flow from nc3 to nc1\r
+ match = new Match();\r
+ match.setField(new MatchField(MatchType.IN_PORT, nc3));\r
+ match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,1}));\r
+ f = new Flow();\r
+ f.setMatch(match);\r
+\r
+ dstHost = am.getDestinationHostFromFlow(f, hosts);\r
+ srcHost = am.getSourceHostFromFlow(f, hosts);\r
+\r
+ Assert.assertTrue(dstHost.equals(hnc1));\r
+ Assert.assertTrue(srcHost.equals(hnc3));\r
+\r
+ // Set up a flow from a switch to a non-host..\r
+ match = new Match();\r
+ match.setField(new MatchField(MatchType.IN_PORT, nc4));\r
+ match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,2}));\r
+ f = new Flow();\r
+ f.setMatch(match);\r
+\r
+ dstHost = am.getDestinationHostFromFlow(f, hosts);\r
+ srcHost = am.getSourceHostFromFlow(f, hosts);\r
+\r
+ Assert.assertTrue(dstHost.equals(hnc2));\r
+ Assert.assertTrue(srcHost == null);\r
+ } catch (ConstructionException e) {\r
+ Assert.assertTrue(false);\r
+ } catch (UnknownHostException e ) {\r
+ Assert.assertTrue(false);\r
+ } finally {\r
+ am.destroy();\r
+ }\r
+ }\r
+\r
+ @Test\r
+ public void testGetByteCountBetweenHosts() {\r
+ // TODO: This test should exist, but it involves a lot of\r
+ // integration with the statisticsManager, switchManager, and\r
+ // hostTracker, and I'm not entirely sure how to go about that.\r
+ Assert.assertTrue(true);\r
+ }\r
+}\r
--- /dev/null
+<?xml version="1.0"?>
+<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+
+ <services>
+ <rest defaultRestSubcontext="/controller/nb/v2/analytics"/>
+ </services>
+
+ <modules>
+ <docs docsDir="rest" title="Analytics REST API" includeExampleXml="true" includeExampleJson="true"/>
+ </modules>
+</enunciate>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.opendaylight</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../../commons/opendaylight</relativePath>
+ </parent>
+
+ <artifactId>analytics.northbound</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>maven-enunciate-plugin</artifactId>
+ <version>${enunciate.version}</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.6</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ </Export-Package>
+ <Import-Package>
+ com.sun.jersey.spi.container.servlet,
+ javax.ws.rs,
+ javax.ws.rs.core,
+ javax.xml.bind.annotation,
+ org.opendaylight.controller.analytics,
+ org.opendaylight.controller.containermanager,
+ org.opendaylight.controller.hosttracker,
+ org.opendaylight.controller.hosttracker.hostAware,
+ org.opendaylight.controller.northbound.commons,
+ org.opendaylight.controller.northbound.commons.exception,
+ org.opendaylight.controller.northbound.commons.utils,
+ org.opendaylight.controller.sal.authorization,
+ org.opendaylight.controller.sal.core,
+ org.opendaylight.controller.sal.utils,
+ org.opendaylight.controller.switchmanager,
+ !org.codehaus.enunciate.jaxrs
+ </Import-Package>
+ <Export-Package>
+ </Export-Package>
+ <Web-ContextPath>/controller/nb/v2/analytics</Web-ContextPath>
+ </instructions>
+ <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>analytics</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>hosttracker</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.thirdparty</groupId>
+ <artifactId>com.sun.jersey.jersey-servlet</artifactId>
+ <version>1.17-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.northbound</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>enunciate-core-annotations</artifactId>
+ <version>${enunciate.version}</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 Plexxi, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.analytics.northbound;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Set;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.SecurityContext;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+import org.codehaus.enunciate.jaxrs.TypeHint;
+
+import org.opendaylight.controller.analytics.IAnalyticsManager;
+import org.opendaylight.controller.containermanager.IContainerManager;
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.*;
+import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
+import org.opendaylight.controller.sal.authorization.Privilege;
+import org.opendaylight.controller.sal.core.Host;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+
+/**
+ * Northbound APIs that returns various Analytics exposed by the Southbound
+ * plugins such as Openflow.
+ *
+ * <br>
+ * <br>
+ * Authentication scheme : <b>HTTP Basic</b><br>
+ * Authentication realm : <b>opendaylight</b><br>
+ * Transport : <b>HTTP and HTTPS</b><br>
+ * <br>
+ * HTTPS Authentication is disabled by default. Administrator can enable it in
+ * tomcat-server.xml after adding a proper keystore / SSL certificate from a
+ * trusted authority.<br>
+ * More info :
+ * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration
+ *
+ */
+@Path("/")
+public class AnalyticsNorthbound {
+
+ private String username;
+
+ @Context
+ public void setSecurityContext(SecurityContext context) {
+ username = context.getUserPrincipal().getName();
+ }
+
+ protected String getUserName() {
+ return username;
+ }
+
+ private IAnalyticsManager getAnalyticsService(String containerName) {
+ IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(IContainerManager.class, this);
+ if (containerManager == null) {
+ throw new ServiceUnavailableException("Container " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ boolean found = false;
+ List<String> containerNames = containerManager.getContainerNames();
+ for (String cName : containerNames) {
+ if (cName.trim().equalsIgnoreCase(containerName.trim())) {
+ found = true;
+ }
+ }
+
+ if (found == false) {
+ throw new ResourceNotFoundException(containerName + " " + RestMessages.NOCONTAINER.toString());
+ }
+
+ IAnalyticsManager analyticsManager = (IAnalyticsManager) ServiceHelper.getInstance(IAnalyticsManager.class, containerName, this);
+ if (analyticsManager == null) {
+ throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ return analyticsManager;
+ }
+
+ /**
+ * Returns a list of Host Statistics for a given Node.
+ *
+ * @param containerName
+ * Name of the Container. The Container name for the base
+ * controller is "default".
+ * @param dataLayerAddr
+ * DataLayerAddress for the host
+ * @param networkAddr
+ * NetworkAddress for the host
+ * @return List of Flow Statistics for a given Node. // TODO:
+ */
+ @Path("/{containerName}/hoststats/{srcNetworkAddr}/{dstNetworkAddr}")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @TypeHint(HostStatistics.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 404, condition = "The containerName is not found"),
+ @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
+ // TODO: This will need other parameters
+ public HostStatistics getHostStatistics(
+ @PathParam("containerName") String containerName,
+ @PathParam("srcNetworkAddr") String srcNetworkAddr,
+ @PathParam("dstNetworkAddr") String dstNetworkAddr) {
+ if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
+ throw new UnauthorizedException("User is not authorized to perform this operation on container " + containerName);
+ }
+ handleDefaultDisabled(containerName);
+
+ IAnalyticsManager analyticsManager = getAnalyticsService(containerName);
+ if (analyticsManager == null) {
+ throw new ServiceUnavailableException("Analytics " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
+ if (switchManager == null) {
+ throw new ServiceUnavailableException("Switch manager " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ Host srcHost = handleHostAvailability(containerName, srcNetworkAddr);
+ Host dstHost = handleHostAvailability(containerName, dstNetworkAddr);
+ long byteCount = analyticsManager.getByteCountBetweenHosts(srcHost, dstHost);
+ double bitRate = analyticsManager.getBitRateBetweenHosts(srcHost, dstHost);
+
+ return new HostStatistics(srcHost, dstHost, byteCount, bitRate);
+
+ }
+
+ private void handleDefaultDisabled(String containerName) {
+ IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(IContainerManager.class, this);
+ if (containerManager == null) {
+ throw new InternalServerErrorException(RestMessages.INTERNALERROR.toString());
+ }
+
+ if (containerName.equals(GlobalConstants.DEFAULT.toString()) && containerManager.hasNonDefaultContainer()) {
+ throw new ResourceConflictException(RestMessages.DEFAULTDISABLED.toString());
+ }
+ }
+
+ private Host handleHostAvailability(String containerName, String networkAddr) {
+
+ IfIptoHost hostTracker = (IfIptoHost) ServiceHelper.getInstance(IfIptoHost.class, containerName, this);
+ if (hostTracker == null) {
+ throw new ServiceUnavailableException("Host tracker " + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ Set<HostNodeConnector> allHosts = hostTracker.getAllHosts();
+ if (allHosts == null) {
+ throw new ResourceNotFoundException(networkAddr + " : " + RestMessages.NOHOST.toString());
+ }
+
+ Host host = null;
+ try {
+ InetAddress networkAddress = InetAddress.getByName(networkAddr);
+ for (Host h : allHosts) {
+ if (h.getNetworkAddress().equals(networkAddress)) {
+ host = h;
+ break;
+ }
+ }
+ } catch (UnknownHostException e) {
+ }
+
+ if (host == null) {
+ throw new ResourceNotFoundException(networkAddr + " : " + RestMessages.NOHOST.toString());
+ }
+
+ return host;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2013 Plexxio, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.analytics.northbound;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.ws.rs.core.Application;
+
+/**
+ * Instance of javax.ws.rs.core.Application used to return the classes
+ * that will be instantiated for JAXRS processing, this is necessary
+ * because the package scanning in jersey doesn't yet work in OSGi
+ * environment.
+ *
+ */
+public class AnalyticsNorthboundRSApplication extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ Set<Class<?>> classes = new HashSet<Class<?>>();
+ classes.add(AnalyticsNorthbound.class);
+ return classes;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Plexxi, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.analytics.northbound;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import org.opendaylight.controller.sal.core.Host;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class HostStatistics {
+ @XmlElement
+ private Host srcHost;
+ @XmlElement
+ private Host dstHost;
+ @XmlElement(name="byteCount")
+ private long byteCount;
+ @XmlElement(name="bitRate")
+ private double bitRate;
+
+ // To satisfy JAXB
+ @SuppressWarnings("unused")
+ private HostStatistics() {
+ }
+
+ public HostStatistics(Host srcHost, Host dstHost, long byteCount, double bitRate) {
+ super();
+ this.srcHost = srcHost;
+ this.dstHost = dstHost;
+ this.byteCount = byteCount;
+ this.bitRate = bitRate;
+ }
+
+ public Host getSrcHost() {
+ return this.srcHost;
+ }
+
+ public void setSrcHost(Host host) {
+ this.srcHost = host;
+ }
+
+ public Host getDstHost() {
+ return this.dstHost;
+ }
+
+ public void setDstHost(Host host) {
+ this.dstHost = host;
+ }
+
+ public long getByteCount() {
+ return this.byteCount;
+ }
+
+ public void setByteCount(long byteCount) {
+ this.byteCount = byteCount;
+ }
+
+ public double getBitRate() {
+ return this.bitRate;
+ }
+
+ public void setBitRate(double bitRate) {
+ this.bitRate = bitRate;
+ }
+}
--- /dev/null
+org.springframework.beans.BeanInfoFactory=org.springframework.beans.ExtendedBeanInfoFactory
--- /dev/null
+http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
+http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
+http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
+http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
+http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler
+http\://www.springframework.org/schema/c=org.springframework.beans.factory.xml.SimpleConstructorNamespaceHandler
+http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
+http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler
+http\://www.springframework.org/schema/mvc=org.springframework.web.servlet.config.MvcNamespaceHandler
+http\://www.springframework.org/schema/security=org.springframework.security.config.SecurityNamespaceHandler
--- /dev/null
+http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
+http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
+http\://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
+http\://www.springframework.org/schema/beans/spring-beans-3.1.xsd=org/springframework/beans/factory/xml/spring-beans-3.1.xsd
+http\://www.springframework.org/schema/beans/spring-beans-3.2.xsd=org/springframework/beans/factory/xml/spring-beans-3.2.xsd
+http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.2.xsd
+http\://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd
+http\://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd
+http\://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
+http\://www.springframework.org/schema/tool/spring-tool-3.1.xsd=org/springframework/beans/factory/xml/spring-tool-3.1.xsd
+http\://www.springframework.org/schema/tool/spring-tool-3.2.xsd=org/springframework/beans/factory/xml/spring-tool-3.2.xsd
+http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.2.xsd
+http\://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd
+http\://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd
+http\://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
+http\://www.springframework.org/schema/util/spring-util-3.1.xsd=org/springframework/beans/factory/xml/spring-util-3.1.xsd
+http\://www.springframework.org/schema/util/spring-util-3.2.xsd=org/springframework/beans/factory/xml/spring-util-3.2.xsd
+http\://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.2.xsd
+http\://www.springframework.org/schema/context/spring-context-2.5.xsd=org/springframework/context/config/spring-context-2.5.xsd
+http\://www.springframework.org/schema/context/spring-context-3.0.xsd=org/springframework/context/config/spring-context-3.0.xsd
+http\://www.springframework.org/schema/context/spring-context-3.1.xsd=org/springframework/context/config/spring-context-3.1.xsd
+http\://www.springframework.org/schema/context/spring-context-3.2.xsd=org/springframework/context/config/spring-context-3.2.xsd
+http\://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context-3.2.xsd
+http\://www.springframework.org/schema/jee/spring-jee-2.0.xsd=org/springframework/ejb/config/spring-jee-2.0.xsd
+http\://www.springframework.org/schema/jee/spring-jee-2.5.xsd=org/springframework/ejb/config/spring-jee-2.5.xsd
+http\://www.springframework.org/schema/jee/spring-jee-3.0.xsd=org/springframework/ejb/config/spring-jee-3.0.xsd
+http\://www.springframework.org/schema/jee/spring-jee-3.1.xsd=org/springframework/ejb/config/spring-jee-3.1.xsd
+http\://www.springframework.org/schema/jee/spring-jee-3.2.xsd=org/springframework/ejb/config/spring-jee-3.2.xsd
+http\://www.springframework.org/schema/jee/spring-jee.xsd=org/springframework/ejb/config/spring-jee-3.2.xsd
+http\://www.springframework.org/schema/lang/spring-lang-2.0.xsd=org/springframework/scripting/config/spring-lang-2.0.xsd
+http\://www.springframework.org/schema/lang/spring-lang-2.5.xsd=org/springframework/scripting/config/spring-lang-2.5.xsd
+http\://www.springframework.org/schema/lang/spring-lang-3.0.xsd=org/springframework/scripting/config/spring-lang-3.0.xsd
+http\://www.springframework.org/schema/lang/spring-lang-3.1.xsd=org/springframework/scripting/config/spring-lang-3.1.xsd
+http\://www.springframework.org/schema/lang/spring-lang-3.2.xsd=org/springframework/scripting/config/spring-lang-3.2.xsd
+http\://www.springframework.org/schema/lang/spring-lang.xsd=org/springframework/scripting/config/spring-lang-3.2.xsd
+http\://www.springframework.org/schema/task/spring-task-3.0.xsd=org/springframework/scheduling/config/spring-task-3.0.xsd
+http\://www.springframework.org/schema/task/spring-task-3.1.xsd=org/springframework/scheduling/config/spring-task-3.1.xsd
+http\://www.springframework.org/schema/task/spring-task-3.2.xsd=org/springframework/scheduling/config/spring-task-3.2.xsd
+http\://www.springframework.org/schema/task/spring-task.xsd=org/springframework/scheduling/config/spring-task-3.2.xsd
+http\://www.springframework.org/schema/cache/spring-cache-3.1.xsd=org/springframework/cache/config/spring-cache-3.1.xsd
+http\://www.springframework.org/schema/cache/spring-cache-3.2.xsd=org/springframework/cache/config/spring-cache-3.2.xsd
+http\://www.springframework.org/schema/cache/spring-cache.xsd=org/springframework/cache/config/spring-cache-3.2.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd=org/springframework/web/servlet/config/spring-mvc-3.0.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd=org/springframework/web/servlet/config/spring-mvc-3.1.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd=org/springframework/web/servlet/config/spring-mvc-3.2.xsd
+http\://www.springframework.org/schema/mvc/spring-mvc.xsd=org/springframework/web/servlet/config/spring-mvc-3.2.xsd
+http\://www.springframework.org/schema/security/spring-security-3.1.xsd=org/springframework/security/config/spring-security-3.1.xsd
+http\://www.springframework.org/schema/security/spring-security-3.2.xsd=org/springframework/security/config/spring-security-3.2.xsd
+
--- /dev/null
+# Tooling related information for the beans namespace
+http\://www.springframework.org/schema/beans@name=beans Namespace
+http\://www.springframework.org/schema/beans@prefix=beans
+http\://www.springframework.org/schema/beans@icon=org/springframework/beans/factory/xml/spring-beans.gif
+
+# Tooling related information for the util namespace
+http\://www.springframework.org/schema/util@name=util Namespace
+http\://www.springframework.org/schema/util@prefix=util
+http\://www.springframework.org/schema/util@icon=org/springframework/beans/factory/xml/spring-util.gif
+
+# Tooling related information for the context namespace
+http\://www.springframework.org/schema/context@name=context Namespace
+http\://www.springframework.org/schema/context@prefix=context
+http\://www.springframework.org/schema/context@icon=org/springframework/context/config/spring-context.gif
+
+# Tooling related information for the jee namespace
+http\://www.springframework.org/schema/jee@name=jee Namespace
+http\://www.springframework.org/schema/jee@prefix=jee
+http\://www.springframework.org/schema/jee@icon=org/springframework/ejb/config/spring-jee.gif
+
+# Tooling related information for the scheduling namespace
+http\://www.springframework.org/schema/task@name=task Namespace
+http\://www.springframework.org/schema/task@prefix=task
+http\://www.springframework.org/schema/task@icon=org/springframework/scheduling/config/spring-task.gif
+
+# Tooling related information for the lang namespace
+http\://www.springframework.org/schema/lang@name=lang Namespace
+http\://www.springframework.org/schema/lang@prefix=lang
+http\://www.springframework.org/schema/lang@icon=org/springframework/scripting/config/spring-lang.gif
+
+# Tooling related information for the cache namespace
+http\://www.springframework.org/schema/cache@name=cache Namespace
+http\://www.springframework.org/schema/cache@prefix=cache
+http\://www.springframework.org/schema/cache@icon=org/springframework/cache/config/spring-cache.gif
+
+# Tooling related information for the mvc namespace
+http\://www.springframework.org/schema/mvc@name=mvc Namespace
+http\://www.springframework.org/schema/mvc@prefix=mvc
+http\://www.springframework.org/schema/mvc@icon=org/springframework/web/servlet/config/spring-mvc.gif
--- /dev/null
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <servlet>
+ <servlet-name>JAXRSAnalytics</servlet-name>
+ <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.opendaylight.controller.analytics.northbound.AnalyticsNorthboundRSApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>JAXRSAnalytics</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>NB api</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>System-Admin</role-name>
+ <role-name>Network-Admin</role-name>
+ <role-name>Network-Operator</role-name>
+ <role-name>Container-User</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <security-role>
+ <role-name>System-Admin</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Network-Admin</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Network-Operator</role-name>
+ </security-role>
+ <security-role>
+ <role-name>Container-User</role-name>
+ </security-role>
+
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>opendaylight</realm-name>
+ </login-config>
+</web-app>
--- /dev/null
+/*
+ * Copyright (c) 2013 Plexxi, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.analytics.northbound;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class AnalyticsNorthboundTest extends TestCase {
+
+ @Test
+ public void testAnalytics() {
+ Assert.assertTrue(true);
+ }
+}
+++ /dev/null
-/*\r
- * Copyright (c) 2013 Plexxi, Inc. All rights reserved.\r
- *\r
- * This program and the accompanying materials are made available under the\r
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
- * and is available at http://www.eclipse.org/legal/epl-v10.html\r
- */\r
-\r
-package org.opendaylight.controller.analytics.internal;\r
-\r
-\r
-import junit.framework.TestCase;\r
-\r
-import org.junit.Assert;\r
-import org.junit.Test;\r
-\r
-public class AnalyticsManagerTest extends TestCase {\r
-\r
- @Test\r
- public void testAnalyticsManagerCreation() {\r
- AnalyticsManager am = new AnalyticsManager();\r
- Assert.assertTrue(am != null);\r
- }\r
-\r
-}\r
<module>affinity/api</module>\r
<module>affinity/implementation</module>\r
<module>affinity/northbound</module>\r
- <module>analytics</module>\r
+ <module>analytics/api</module>\r
+ <module>analytics/implementation</module>\r
+ <module>analytics/northbound</module>\r
</modules>\r
\r
<repositories>\r
--- /dev/null
+#!/usr/local/bin/python
+
+import httplib2
+import json
+import sys
+
+# 1. Start the controller
+# 2. On the mininet VM, run:
+# > sudo mn --controller=remote,ip=192.168.56.1 --topo tree,2
+# > h1 ping h2
+# 3. On the local machine (e.g., your laptop), run this script.
+# > python analytics.py
+# Should see output like: "xxx bytes between 10.0.0.1 and 10.0.0.2",
+# where xxx is a positive integer.
+
+class HostStats:
+
+ def __init__(self, src, dst):
+ self.http = httplib2.Http(".cache")
+ self.http.add_credentials('admin', 'admin')
+ self.refresh()
+
+ def refresh(self):
+ resp, content = self.http.request("http://localhost:8080/controller/nb/v2/analytics/default/hoststats/" + src + "/" + dst, "GET")
+ if (resp.status == 404):
+ print "404 Error; exiting"
+ sys.exit()
+ if (resp.status == 503):
+ print "503 Error; exiting"
+ sys.exit()
+ 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
+ return bytes
+
+ def get_bit_rate(self):
+
+ try:
+ bitrate = float(self.host_stats["bitRate"])
+ except Exception as e:
+ print "exception: ", e
+ bitrate = None
+ return bitrate
+
+src = "10.0.0.1"
+dst = "10.0.0.2"
+
+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))