--- /dev/null
+*.class
+**/target
+**/bin
+dist
+**/logs
+products
+repository
+workspace
+*~
+target
+.classpath
+.project
+.settings
+MANIFEST.MF
+opendaylight/northbound/integrationtest/logs/*
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>switchmanager</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/test/java=UTF-8
+encoding/<project>=UTF-8
--- /dev/null
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
--- /dev/null
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
--- /dev/null
+Manifest-Version: 1.0\r
+Bnd-LastModified: 1376940266146\r
+Build-Jdk: 1.6.0_37\r
+Built-By: sraman\r
+Bundle-ManifestVersion: 2\r
+Bundle-Name: affinity\r
+Bundle-SymbolicName: org.opendaylight.controller.affinity\r
+Bundle-Version: 0.4.0.SNAPSHOT\r
+Created-By: Apache Maven Bundle Plugin\r
+Export-Package: org.opendaylight.controller.affinity;uses:="javax.xml.bi\r
+ nd.annotation,org.opendaylight.controller.sal.utils";version="0.4.0.SNA\r
+ PSHOT"\r
+Import-Package: javax.xml.bind.annotation,org.apache.commons.lang3.build\r
+ er;version="[3.1,4)",org.apache.felix.dm;version="[3.0,4)",org.eclipse.\r
+ osgi.framework.console;version="[1.1,2)",org.opendaylight.controller.cl\r
+ ustering.services;version="[0.4,1)",org.opendaylight.controller.configu\r
+ ration;version="[0.4,1)",org.opendaylight.controller.sal.core;version="\r
+ [0.5,1)",org.opendaylight.controller.sal.inventory;version="[0.5,1)",or\r
+ g.opendaylight.controller.sal.packet;version="[0.5,1)",org.opendaylight\r
+ .controller.sal.utils;version="[0.5,1)",org.osgi.framework;version="[1.\r
+ 7,2)",org.slf4j;version="[1.7,2)"\r
+Tool: Bnd-1.50.0\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+<!-- <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>affinity</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ </parent> -->
+
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>affinity</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <!-- Sonar properties using jacoco to retrieve integration test results -->
+ <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
+ <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
+ <sonar.jacoco.Reportpath>target/jacoco.exec</sonar.jacoco.Reportpath>
+ <sonar.jacoco.itReportPath>target/jacoco-it.exec</sonar.jacoco.itReportPath>
+ <sonar.language>java</sonar.language>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>0.5.3.201107060350</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.6</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.opendaylight.controller.affinity
+ </Export-Package>
+ <Import-Package>
+ org.opendaylight.controller.clustering.services,
+ org.opendaylight.controller.configuration,
+ org.opendaylight.controller.sal.core,
+ org.opendaylight.controller.sal.utils,
+ org.opendaylight.controller.sal.packet,
+ org.opendaylight.controller.sal.inventory,
+ org.slf4j,
+ org.apache.felix.dm,
+ org.eclipse.osgi.framework.console,
+ org.osgi.framework,
+ javax.xml.bind.annotation,
+ org.apache.commons.lang3.builder
+ </Import-Package>
+ </instructions>
+ <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <configuration>
+ <includes>org.opendaylight.controller.*</includes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>pre-test</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>post-test</id>
+ <phase>test</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>configuration</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <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.affinity;
+
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+//import org.opendaylight.controller.sal.utils;
+
+/**
+ * The class represents an affinity configuration.
+ */
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class AffinityConfig implements Cloneable, Serializable {
+ //static fields are by default excluded by Gson parser
+ private static final long serialVersionUID = 1L;
+
+ /* private static final String affinityFields[] = { GUIField.NAME.toString(),
+ GUIField.AFFINITYFROM.toString(),
+ GUIField.AFFINITYTO.toString(),
+ GUIField.AFFINITYTYPE.toString() };
+ */
+
+ // Order matters: JSP file expects following fields in the
+ // following order
+ @XmlAttribute
+ private String name;
+ @XmlAttribute
+ private String fromIp; // A.B.C.D
+ private String toIp; // A.B.C.D
+ private String affinityType;
+
+ public AffinityConfig() {
+ }
+
+ public AffinityConfig(String desc, String from, String to, String aType) {
+ name = desc;
+ fromIp = from;
+ toIp = to;
+ affinityType = aType;
+ }
+
+ public AffinityConfig(AffinityConfig ac) {
+ name = ac.name;
+ fromIp = ac.fromIp;
+ toIp = ac.toIp;
+ affinityType = ac.affinityType;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public InetAddress getFromIP() {
+ InetAddress ip = null;
+ try {
+ ip = InetAddress.getByName(fromIp);
+ } catch (UnknownHostException e1) {
+ return null;
+ }
+ return ip;
+ }
+
+ public InetAddress getToIP() {
+ InetAddress ip = null;
+ try {
+ ip = InetAddress.getByName(toIp);
+ } catch (UnknownHostException e1) {
+ return null;
+ }
+ return ip;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ /*
+ * Configuration will be stored in collection only if it is valid
+ * Hence we don't check here for uninitialized fields
+ */
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ AffinityConfig that = (AffinityConfig) obj;
+ if (this.fromIp.equals(that.fromIp) && this.toIp.equals(that.toIp) && (this.affinityType.equals(that.affinityType))) {
+ return true;
+ }
+ return false;
+ }
+ /*
+ public static List<String> getGuiFieldsNames() {
+ List<String> fieldList = new ArrayList<String>();
+ for (String str : affinityFields) {
+ fieldList.add(str);
+ }
+ return fieldList;
+ }
+ */
+ @Override
+ public String toString() {
+ return ("AffinityConfig [Description=" + name + ", From=" + fromIp
+ + ", To=" + toIp + ", Type=" + affinityType + "]");
+ }
+
+ /**
+ * Implement clonable interface
+ */
+ @Override
+ public AffinityConfig clone() {
+ return new AffinityConfig(this);
+ }
+
+}
--- /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.affinity;
+
+import java.net.InetAddress;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.utils.Status;
+
+import org.opendaylight.controller.affinity.AffinityConfig;
+
+/**
+ * Primary purpose of this interface is to provide methods for
+ * applications to set affinity configuration.
+ */
+public interface IAffinityManager {
+
+ /**
+ * Remove an affinity configuration
+ *
+ * @param configObject refer to {@link Open Declaration org.opendaylight.controller.affinitymanager.AffinityConfig}
+ * @return "Success" or failure reason
+ */
+ public Status removeAffinityConfigObject(AffinityConfig configObject);
+
+ /**
+ * Remove an affinity configuration given the name
+ *
+ * @param name affinity name
+ * @return "Success" or failure reason
+ */
+ public Status removeAffinityConfig(String name);
+
+ /**
+ * Save the current affinity configurations
+ *
+ * @return the status code
+ */
+ public Status saveAffinityConfig();
+
+ /**
+ * Update Switch specific configuration such as Affinity name and type. Add if absent.
+ *
+ * @param cfgConfig refer to {@link Open Declaration org.opendaylight.controller.affinity.AffinityConfig}
+ */
+ public Status updateAffinityConfig(AffinityConfig cfgObject);
+
+ public List<AffinityConfig> getAffinityConfigList();
+ public AffinityConfig getAffinityConfig(String affinity);
+}
--- /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.affinity;
+
+/**
+ * The interface which describes the methods forwarding rules manager will call
+ * for notifying the listeners of policy installation updates.
+ */
+public interface IAffinityManagerAware {
+
+ /**
+ * Inform the listeners that specified affinity was updated.
+ *
+ * @param aff
+ * the affinity config that was added or removed
+ * @param add true if add; false otherwise
+ */
+ public void affinityNotify(AffinityConfig aff, boolean add);
+
+ /**
+ * Inform listeners that the network node has notified us about a failure in
+ * executing the controller generated asynchronous request identified by the
+ * passed unique id.
+ *
+ * @param requestId
+ * the unique id associated with the request which failed to be
+ * executed on the network node
+ * @param error
+ * the string describing the error reported by the network node
+ */
+ public void requestFailed(long requestId, String error);
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java">
+ <attributes>
+ <attribute name="optional" value="true"/>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+ <attributes>
+ <attribute name="maven.pomderived" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>switchmanager.implementation</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/test/java=UTF-8
+encoding//src/test/resources=UTF-8
+encoding/<project>=UTF-8
--- /dev/null
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
--- /dev/null
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
--- /dev/null
+Manifest-Version: 1.0\r
+Bnd-LastModified: 1376940268439\r
+Build-Jdk: 1.6.0_37\r
+Built-By: sraman\r
+Bundle-Activator: org.opendaylight.controller.affinity.internal.Activato\r
+ r\r
+Bundle-ManifestVersion: 2\r
+Bundle-Name: implementation\r
+Bundle-SymbolicName: org.opendaylight.controller.affinity.implementation\r
+Bundle-Version: 0.4.0.SNAPSHOT\r
+Created-By: Apache Maven Bundle Plugin\r
+Import-Package: javax.xml.bind.annotation,org.apache.commons.lang3.build\r
+ er;version="[3.1,4)",org.apache.felix.dm;version="[3.0,4)",org.eclipse.\r
+ osgi.framework.console;version="[1.1,2)",org.opendaylight.controller.af\r
+ finity;version="[0.4,1)",org.opendaylight.controller.clustering.service\r
+ s;version="[0.4,1)",org.opendaylight.controller.configuration;version="\r
+ [0.4,1)",org.opendaylight.controller.sal.core;version="[0.5,1)",org.ope\r
+ ndaylight.controller.sal.inventory;version="[0.5,1)",org.opendaylight.c\r
+ ontroller.sal.packet;version="[0.5,1)",org.opendaylight.controller.sal.\r
+ utils;version="[0.5,1)",org.osgi.framework;version="[1.7,2)",org.slf4j;\r
+ version="[1.7,2)"\r
+Tool: Bnd-1.50.0\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+<!-- <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>affinity</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ </parent> -->
+
+ <groupId>org.opendaylight.controller.affinity</groupId>
+ <artifactId>implementation</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <!-- Sonar properties using jacoco to retrieve integration test results -->
+ <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
+ <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
+ <sonar.jacoco.Reportpath>target/jacoco.exec</sonar.jacoco.Reportpath>
+ <sonar.jacoco.itReportPath>target/jacoco-it.exec</sonar.jacoco.itReportPath>
+ <sonar.language>java</sonar.language>
+ <junit.version>4.10</junit.version>
+ </properties>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>0.5.3.201107060350</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.6</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.opendaylight.controller.affinity.implementation
+ </Export-Package>
+ <Import-Package>
+ org.opendaylight.controller.affinity,
+ org.opendaylight.controller.clustering.services,
+ org.opendaylight.controller.configuration,
+ org.opendaylight.controller.sal.core,
+ org.opendaylight.controller.sal.utils,
+ org.opendaylight.controller.sal.packet,
+ org.opendaylight.controller.sal.inventory,
+ org.slf4j,
+ org.apache.felix.dm,
+ org.eclipse.osgi.framework.console,
+ org.osgi.framework,
+ javax.xml.bind.annotation,
+ org.apache.commons.lang3.builder
+ </Import-Package>
+ <Bundle-Activator>
+ org.opendaylight.controller.affinity.internal.Activator
+ </Bundle-Activator>
+ </instructions>
+ <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <configuration>
+ <includes>org.opendaylight.controller.*</includes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>pre-test</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>post-test</id>
+ <phase>test</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>configuration</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</groupId>
+ <artifactId>forwardingrulesmanager</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>affinity</artifactId>
+ <version>0.4.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.affinity.internal;
+
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.opendaylight.controller.affinity.IAffinityManager;
+import org.opendaylight.controller.affinity.IAffinityManagerAware;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * AffinityManager Bundle Activator
+ *
+ *
+ */
+public class Activator extends ComponentActivatorAbstractBase {
+ protected static final Logger logger = LoggerFactory
+ .getLogger(Activator.class);
+
+ /**
+ * Function called when the activator starts just after some
+ * initializations are done by the
+ * ComponentActivatorAbstractBase.
+ *
+ */
+ public void init() {
+
+ }
+
+ /**
+ * Function called when the activator stops just before the
+ * cleanup done by ComponentActivatorAbstractBase
+ *
+ */
+ public void destroy() {
+
+ }
+
+ /**
+ * Function that is used to communicate to dependency manager the
+ * list of known implementations for services inside a container
+ *
+ *
+ * @return An array containing all the CLASS objects that will be
+ * instantiated in order to get an fully working implementation
+ * Object
+ */
+ public Object[] getImplementations() {
+ Object[] res = { AffinityManagerImpl.class };
+ return res;
+ }
+
+ /**
+ * Function that is called when configuration of the dependencies
+ * is required.
+ *
+ * @param c dependency manager Component object, used for
+ * configuring the dependencies exported and imported
+ * @param imp Implementation class that is being configured,
+ * needed as long as the same routine can configure multiple
+ * implementations
+ * @param containerName The containerName being configured, this allow
+ * also optional per-container different behavior if needed, usually
+ * should not be the case though.
+ */
+ public void configureInstance(Component c, Object imp, String containerName) {
+ if (imp.equals(AffinityManagerImpl.class)) {
+ Dictionary<String, Set<String>> props = new Hashtable<String, Set<String>>();
+ Set<String> propSet = new HashSet<String>();
+ propSet.add("affinitymanager.configSaveEvent");
+ props.put("cachenames", propSet);
+ // export the service
+ c.setInterface(new String[] {
+ IAffinityManager.class.getName(),
+ ICacheUpdateAware.class.getName(),
+ IConfigurationContainerAware.class.getName() }, props);
+
+ // Now lets add a service dependency to make sure the
+ // provider of service exists
+ c.add(createContainerServiceDependency(containerName).setService(
+ IAffinityManagerAware.class).setCallbacks(
+ "setAffinityManagerAware", "unsetAffinityManagerAware")
+ .setRequired(false));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IClusterContainerServices.class).setCallbacks(
+ "setClusterContainerService",
+ "unsetClusterContainerService").setRequired(true));
+ }
+ }
+}
--- /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.affinity.internal;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.felix.dm.Component;
+import org.eclipse.osgi.framework.console.CommandInterpreter;
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.forwardingrulesmanager.FlowEntry;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.core.NodeTable;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.core.UpdateType;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
+import org.opendaylight.controller.sal.reader.FlowOnNode;
+import org.opendaylight.controller.sal.reader.IReadService;
+import org.opendaylight.controller.sal.reader.IReadServiceListener;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.ObjectReader;
+import org.opendaylight.controller.sal.utils.ObjectWriter;
+
+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.sal.utils.StatusCode;
+
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.affinity.AffinityConfig;
+import org.opendaylight.controller.affinity.IAffinityManager;
+import org.opendaylight.controller.affinity.IAffinityManagerAware;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The class caches latest network nodes statistics as notified by reader
+ * services and provides API to retrieve them.
+ */
+public class AffinityManagerImpl implements IAffinityManager, IConfigurationContainerAware, IObjectReader, ICacheUpdateAware<Long, String> {
+ private static final Logger log = LoggerFactory.getLogger(AffinityManagerImpl.class);
+
+
+ private static String ROOT = GlobalConstants.STARTUPHOME.toString();
+ private static final String SAVE = "Save";
+ private String affinityConfigFileName = null;
+ private ConcurrentMap<String, AffinityConfig> affinityConfigList;
+
+ private ConcurrentMap<Long, String> configSaveEvent;
+ private final Set<IAffinityManagerAware> affinityManagerAware = Collections
+ .synchronizedSet(new HashSet<IAffinityManagerAware>());
+
+ private byte[] MAC;
+ private static boolean hostRefresh = true;
+ private int hostRetryCount = 5;
+ private IClusterContainerServices clusterContainerService = null;
+ private String containerName = null;
+ private boolean isDefaultContainer = true;
+ private static final int REPLACE_RETRY = 1;
+
+ public enum ReasonCode {
+ SUCCESS("Success"), FAILURE("Failure"), INVALID_CONF(
+ "Invalid Configuration"), EXIST("Entry Already Exist"), CONFLICT(
+ "Configuration Conflict with Existing Entry");
+
+ private final String name;
+
+ private ReasonCode(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ /* Only default container. */
+ public String getContainerName() {
+ return containerName;
+ }
+
+ public void startUp() {
+ // Initialize configuration file names
+ affinityConfigFileName = ROOT + "affinityConfig_" + this.getContainerName()
+ + ".conf";
+
+ // Instantiate cluster synced variables
+ allocateCaches();
+ retrieveCaches();
+
+ /*
+ * Read startup and build database if we have not already gotten the
+ * configurations synced from another node
+ */
+ if (affinityConfigList.isEmpty()) {
+ loadAffinityConfiguration();
+ }
+ }
+
+ public void shutDown() {
+ }
+
+ @SuppressWarnings("deprecation")
+ private void allocateCaches() {
+ if (this.clusterContainerService == null) {
+ this.nonClusterObjectCreate();
+ log.warn("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+
+ try {
+ clusterContainerService.createCache(
+ "affinity.affinityConfigList",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ clusterContainerService.createCache(
+ "affinity.configSaveEvent",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ } catch (CacheConfigException cce) {
+ log.error("\nCache configuration invalid - check cache mode");
+ } catch (CacheExistException ce) {
+ log.error("\nCache already exits - destroy and recreate if needed");
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "deprecation" })
+ private void retrieveCaches() {
+ if (this.clusterContainerService == null) {
+ log.info("un-initialized clusterContainerService, can't create cache");
+ return;
+ }
+ affinityConfigList = (ConcurrentMap<String, AffinityConfig>) clusterContainerService
+ .getCache("affinity.affinityConfigList");
+ if (affinityConfigList == null) {
+ log.error("\nFailed to get cache for affinityConfigList");
+ }
+ configSaveEvent = (ConcurrentMap<Long, String>) clusterContainerService
+ .getCache("affinity.configSaveEvent");
+ if (configSaveEvent == null) {
+ log.error("\nFailed to get cache for configSaveEvent");
+ }
+ }
+
+ private void nonClusterObjectCreate() {
+ affinityConfigList = new ConcurrentHashMap<String, AffinityConfig>();
+ configSaveEvent = new ConcurrentHashMap<Long, String>();
+ }
+
+ @Override
+ public List<AffinityConfig> getAffinityConfigList() {
+ return new ArrayList<AffinityConfig>(affinityConfigList.values());
+ }
+
+ @Override
+ public AffinityConfig getAffinityConfig(String affinity) {
+ return affinityConfigList.get(affinity);
+ }
+
+
+ @Override
+ public Object readObject(ObjectInputStream ois)
+ throws FileNotFoundException, IOException, ClassNotFoundException {
+ // Perform the class deserialization locally, from inside the package
+ // where the class is defined
+ return ois.readObject();
+ }
+
+ @SuppressWarnings("unchecked")
+ private void loadAffinityConfiguration() {
+ ObjectReader objReader = new ObjectReader();
+ ConcurrentMap<String, AffinityConfig> confList = (ConcurrentMap<String, AffinityConfig>) objReader
+ .read(this, affinityConfigFileName);
+
+ if (confList == null) {
+ return;
+ }
+
+ for (AffinityConfig conf : confList.values()) {
+ updateAffinityConfig(conf);
+ }
+ }
+
+ /* Add if absent. */
+ @Override
+ public Status updateAffinityConfig(AffinityConfig cfgObject) {
+ // update default container only
+ if (!isDefaultContainer) {
+ return new Status(StatusCode.INTERNALERROR, "Not default container");
+ }
+
+ AffinityConfig ac = affinityConfigList.get(cfgObject.getName());
+ if (ac == null) {
+ if (affinityConfigList.putIfAbsent(cfgObject.getName(), cfgObject) != null) {
+ return new Status(StatusCode.CONFLICT, "affinity configuration already exists" + cfgObject.getName());
+ }
+ } else {
+ if (!affinityConfigList.replace(cfgObject.getName(), ac, cfgObject)) {
+ return new Status(StatusCode.INTERNALERROR, "Failed to add affinity configuration.");
+ }
+ }
+ return new Status(StatusCode.SUCCESS, "Updated affinity configuration " + cfgObject.getName());
+ }
+
+
+ /* Remove affinity config */
+ @Override
+ public Status removeAffinityConfig(String cfgName) {
+ // update default container only
+ if (!isDefaultContainer) {
+ return new Status(StatusCode.INTERNALERROR, "Not default container");
+ }
+ AffinityConfig ac = affinityConfigList.get(cfgName);
+ if (ac != null) {
+ return removeAffinityConfigObject(ac);
+ }
+ return new Status(StatusCode.INTERNALERROR, "Missing affinity config" + cfgName);
+ }
+ /* Remove affinity config */
+ @Override
+ public Status removeAffinityConfigObject(AffinityConfig cfgObject) {
+ // update default container only
+ if (!isDefaultContainer) {
+ return new Status(StatusCode.INTERNALERROR, "Not default container");
+ }
+
+ AffinityConfig ac = affinityConfigList.get(cfgObject.getName());
+ if (ac != null) {
+ if (affinityConfigList.remove(cfgObject.getName(), ac)) {
+ return new Status(StatusCode.SUCCESS, "Configuration removed: " + cfgObject.getName());
+ } else {
+ String msg = "Remove failed " + cfgObject.getName();
+ return new Status(StatusCode.INTERNALERROR, msg);
+ }
+ }
+ return new Status(StatusCode.INTERNALERROR, "Remove failed: " + cfgObject.getName());
+ }
+ @Override
+ public Status saveConfiguration() {
+ return saveAffinityConfig();
+ }
+
+ @Override
+ public Status saveAffinityConfig() {
+ // Publish the save config event to the cluster nodes
+ configSaveEvent.put(new Date().getTime(), SAVE);
+ return saveAffinityConfigInternal();
+ }
+
+ public Status saveAffinityConfigInternal() {
+ Status retS = null, retP = null;
+ ObjectWriter objWriter = new ObjectWriter();
+
+ retS = objWriter.write(new ConcurrentHashMap<String, AffinityConfig>(
+ affinityConfigList), affinityConfigFileName);
+
+ if (retS.equals(retP)) {
+ if (retS.isSuccess()) {
+ return retS;
+ } else {
+ return new Status(StatusCode.INTERNALERROR, "Save failed");
+ }
+ } else {
+ return new Status(StatusCode.INTERNALERROR, "Partial save failure");
+ }
+ }
+
+ @Override
+ public void entryCreated(Long key, String cacheName, boolean local) {
+ }
+
+ @Override
+ public void entryUpdated(Long key, String new_value, String cacheName,
+ boolean originLocal) {
+ saveAffinityConfigInternal();
+ }
+
+ @Override
+ public void entryDeleted(Long key, String cacheName, boolean originLocal) {
+ }
+
+ /**
+ * Function called by the dependency manager when all the required
+ * dependencies are satisfied
+ *
+ */
+ void init() {
+ log.debug("INIT called!");
+ containerName = GlobalConstants.DEFAULT.toString();
+ startUp();
+ }
+
+ /**
+ * Function called by the dependency manager when at least one
+ * dependency become unsatisfied or when the component is shutting
+ * down because for example bundle is being stopped.
+ *
+ */
+ void destroy() {
+ log.debug("DESTROY called!");
+ }
+
+ /**
+ * Function called by dependency manager after "init ()" is called
+ * and after the services provided by the class are registered in
+ * the service registry
+ *
+ */
+ void start() {
+ log.debug("START called!");
+ }
+
+ /**
+ * Function called after registering the service in OSGi service registry.
+ */
+ void started(){
+ // Retrieve current statistics so we don't have to wait for next refresh
+ IAffinityManager affinityManager = (IAffinityManager) ServiceHelper.getInstance(
+ IAffinityManager.class, this.getContainerName(), this);
+ if (affinityManager != null) {
+ log.debug("STARTED method called!");
+ }
+ }
+
+ /**
+ * Function called by the dependency manager before the services
+ * exported by the component are unregistered, this will be
+ * followed by a "destroy ()" calls
+ *
+ */
+ void stop() {
+ log.debug("STOP called!");
+ }
+
+ void setClusterContainerService(IClusterContainerServices s) {
+ log.debug("Cluster Service set for Statistics Mgr");
+ this.clusterContainerService = s;
+ }
+
+ void unsetClusterContainerService(IClusterContainerServices s) {
+ if (this.clusterContainerService == s) {
+ log.debug("Cluster Service removed for Statistics Mgr!");
+ this.clusterContainerService = null;
+ }
+ }
+}
--- /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.affinity.internal;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.sal.core.Bandwidth;
+import org.opendaylight.controller.sal.core.Latency;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.core.State;
+import org.opendaylight.controller.sal.core.UpdateType;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.affinity.AffinityConfig;
+
+public class AffinityManagerImplTest {
+
+ @Test
+ public void testAffinityManagerAddRemoveConfig() {
+ AffinityManagerImpl affinitymgr = new AffinityManagerImpl();
+ affinitymgr.startUp();
+
+ AffinityConfig ac = new AffinityConfig("test_affinity1", "10.0.0.1", "10.0.0.2", "Isolate");
+
+ // Add status to update/add
+ Status addResult = affinitymgr.updateAffinityConfig(ac);
+ Assert.assertTrue(addResult.isSuccess());
+
+ Status removeResult = (affinitymgr.removeAffinityConfig(ac.getName()));
+ Assert.assertTrue(removeResult.isSuccess());
+
+ AffinityConfig affinityConfigResult = affinitymgr.getAffinityConfig(ac.getName());
+ Assert.assertTrue(affinityConfigResult == null);
+ // System.out.println("*" + switchmgr.addSubnet(subnet) + "*");
+ }
+}
--- /dev/null
+<configuration scan="true">\r
+\r
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
+ <encoder>\r
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
+ </pattern>\r
+ </encoder>\r
+ </appender>\r
+\r
+ <root level="error">\r
+ <appender-ref ref="STDOUT" />\r
+ </root>\r
+</configuration>\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/affinity"/>
+ </services>
+
+ <modules>
+ <docs docsDir="rest" title="Affinity 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>affinity</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ </parent> -->
+
+ <groupId>org.opendaylight.controller.affinity</groupId>
+ <artifactId>northbound</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <properties>
+ <propertymavenplugin.version>1.0-alpha-2</propertymavenplugin.version>
+ <sonar.host.url>https://sonar.opendaylight.org/</sonar.host.url>
+ <sitedeploy>dav:http://nexus.opendaylight.org/content/sites/site</sitedeploy>
+ <siteplugin>3.2</siteplugin>
+ <projectinfo>2.6</projectinfo>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <compiler.version>2.3.2</compiler.version>
+ <surefire.version>2.15</surefire.version>
+ <failsafe.version>2.15</failsafe.version>
+ <exam.version>3.0.0</exam.version>
+ <url.version>1.5.0</url.version>
+ <enunciate.version>1.26.2</enunciate.version>
+ <sonar.branch>${user.name}-private-view</sonar.branch>
+ <sonar.skippedModules>org.openflow.openflowj,net.sf.jung2</sonar.skippedModules>
+ <logback.version>1.0.9</logback.version>
+ <slf4j.version>1.7.2</slf4j.version>
+ <jackson.version>1.9.8</jackson.version>
+ <spring.version>3.1.3.RELEASE</spring.version>
+ <spring-security.version>3.1.3.RELEASE</spring-security.version>
+ <jersey.version>1.17</jersey.version>
+ <virgo.version>3.6.0.RELEASE</virgo.version>
+ <geminiweb.version>2.2.0.RELEASE</geminiweb.version>
+ <checkstyle.version>2.10</checkstyle.version>
+ <testvm.argLine>-Xmx1024m -XX:MaxPermSize=256m</testvm.argLine>
+ <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
+ </properties>
+
+ <repositories>
+ <!-- OpenDayLight Snapshot artifact -->
+ <repository>
+ <id>opendaylight-snapshot</id>
+ <name>opendaylight-snapshot</name>
+ <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ </repository>
+ </repositories>
+ <distributionManagement>
+ <!-- OpenDayLight Snapshot artifact -->
+ <snapshotRepository>
+ <id>opendaylight-snapshot</id>
+ <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+ </snapshotRepository>
+ <!-- Site deployment -->
+ <site>
+ <id>website</id>
+ <url>${sitedeploy}</url>
+ </site>
+ </distributionManagement>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>maven-enunciate-plugin</artifactId>
+ <version>${enunciate.version}</version>
+ <configuration>
+ <javacCheck>true</javacCheck>
+ </configuration>
+ <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>
+ <Import-Package>
+ org.opendaylight.controller.sal.core,
+ org.opendaylight.controller.sal.utils,
+ org.opendaylight.controller.containermanager,
+ org.opendaylight.controller.affinity,
+ org.opendaylight.controller.usermanager,
+ org.apache.commons.lang3.tuple,
+ org.apache.commons.logging,
+ com.sun.jersey.spi.container.servlet,
+ org.opendaylight.controller.northbound.commons,
+ org.opendaylight.controller.northbound.commons.exception,
+ org.opendaylight.controller.northbound.commons.utils,
+ org.opendaylight.controller.sal.authorization,
+ javax.ws.rs,
+ javax.ws.rs.core,
+ javax.xml.bind.annotation,
+ javax.xml.bind,
+ org.slf4j,
+ !org.codehaus.enunciate.jaxrs
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.controller.affinity.northbound
+ </Export-Package>
+ <Web-ContextPath>/controller/nb/v2/affinity</Web-ContextPath>
+ </instructions>
+ <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <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>affinity</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>sal</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.northbound</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>${spring.version}</version>
+ <scope>provided</scope>
+ </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.affinity.northbound;
+
+import java.util.List;
+
+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.affinity.AffinityConfig;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class Affinities {
+ @XmlElement (name="affinity")
+ List<AffinityConfig> affinityList;
+
+ public Affinities() {
+ }
+ public Affinities (List<AffinityConfig> aff) {
+ this.affinityList = aff;
+ }
+ public List<AffinityConfig> getAffinityList() {
+ return affinityList;
+ }
+ public void setAffinityList(List<AffinityConfig> aff) {
+ this.affinityList = aff;
+ }
+}
--- /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.affinity.northbound;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+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;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+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.containermanager.IContainerManager;
+import org.opendaylight.controller.northbound.commons.RestMessages;
+import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
+import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
+import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
+import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
+import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
+import org.opendaylight.controller.sal.authorization.Privilege;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.affinity.IAffinityManager;
+import org.opendaylight.controller.affinity.AffinityConfig;
+
+/**
+ * The class provides Northbound REST APIs to access affinity configuration.
+ *
+ */
+
+@Path("/")
+public class AffinityNorthbound {
+
+ private String username;
+
+ @Context
+ public void setSecurityContext(SecurityContext context) {
+ username = context.getUserPrincipal().getName();
+ }
+
+ protected String getUserName() {
+ return username;
+ }
+
+ private IAffinityManager getIfAffinityManagerService(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;
+ break;
+ }
+ }
+
+ if (found == false) {
+ throw new ResourceNotFoundException(containerName + " "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ IAffinityManager affinityManager = (IAffinityManager) ServiceHelper
+ .getInstance(IAffinityManager.class, containerName, this);
+
+ if (affinityManager == null) {
+ throw new ServiceUnavailableException("Affinity Manager "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ return affinityManager;
+ }
+
+/*
+ * getAllAffinities()
+ * getAffinity(String name)
+ * addAffinity(name, ip1, ip2, type)
+ * removeAffinity(String name)
+ */
+ /**
+ * Retrieve a list of all affinities in this container.
+ */
+ @Path("/{containerName}/affinities")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @TypeHint(Affinities.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") })
+ public Affinities getAllAffinities(@PathParam("containerName") String containerName) {
+
+ if (!NorthboundUtils.isAuthorized(
+ getUserName(), containerName, Privilege.READ, this)) {
+ throw new UnauthorizedException(
+ "User is not authorized to perform this operation on container "
+ + containerName);
+ }
+
+ IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
+ if (affinityManager == null) {
+ throw new ServiceUnavailableException("Affinity Manager "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+ return new Affinities(affinityManager.getAffinityConfigList());
+ }
+ /**
+ * Returns details of affinityName affinity.
+ *
+ * @param containerName
+ * Name of the Container. The Container name for the base
+ * controller is "default".
+ * @param affinityName
+ * Name of the affinity being retrieved.
+ * @return affinity configuration that matches the affinity name.
+ */
+ @Path("/{containerName}/{affinityName}")
+ @GET
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @TypeHint(AffinityConfig.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 404, condition = "The containerName is not found"),
+ @ResponseCode(code = 415, condition = "Affinity name is not found"),
+ @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
+ public AffinityConfig getAffinityDetails(
+ @PathParam("containerName") String containerName,
+ @PathParam("affinityName") String affinityName) {
+ if (!NorthboundUtils.isAuthorized(
+ getUserName(), containerName, Privilege.READ, this)) {
+ throw new UnauthorizedException(
+ "User is not authorized to perform this operation on container "
+ + containerName);
+ }
+ IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
+ if (affinityManager == null) {
+ throw new ServiceUnavailableException("Affinity "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ AffinityConfig ac = affinityManager.getAffinityConfig(affinityName);
+ if (ac == null) {
+ throw new ResourceNotFoundException(RestMessages.SERVICEUNAVAILABLE.toString());
+ } else {
+ return ac;
+ }
+ }
+ /**
+ * Delete an affinity
+ *
+ * @param containerName
+ * Name of the Container
+ * @param affinityName
+ * affinity name 'String'
+ * @return Response as dictated by the HTTP Response Status code
+ */
+
+ @Path("/{containerName}/{affinityName}")
+ @DELETE
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @TypeHint(Response.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+ @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
+ public Response deleteAffinity(
+ @PathParam("containerName") String containerName,
+ @PathParam("affinityName") String affinityName) {
+
+ if (!NorthboundUtils.isAuthorized(
+ getUserName(), containerName, Privilege.WRITE, this)) {
+ throw new UnauthorizedException(
+ "User is not authorized to perform this operation on container "
+ + containerName);
+ }
+
+ IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
+ if (affinityManager == null) {
+ throw new ServiceUnavailableException("Affinity Manager "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ Status ret = affinityManager.removeAffinityConfig(affinityName);
+ if (ret.isSuccess()) {
+ return Response.ok().build();
+ }
+ throw new ResourceNotFoundException(ret.getDescription());
+ }
+
+ /**
+ * Add an affinity to the configuration database
+ *
+ * @param containerName
+ * Name of the Container
+ * @param affinityName
+ * Name of the new affinity being added
+ * @param networkAddress1
+ * IP address of the flow source
+ * @param networkAddress2
+ * IP address of the flow destination
+ * @param affinityAttribute
+ * Type of affinity being added
+ * @return Response as dictated by the HTTP Response Status code
+ */
+
+ @Path("/{containerName}/{affinityName}/{networkAddress1}/{networkAddress2}/{affinityAttribute}")
+ @PUT
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @TypeHint(Response.class)
+ @StatusCodes({
+ @ResponseCode(code = 200, condition = "Operation successful"),
+ @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+ @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
+ public Response addAffinity(
+ @PathParam("containerName") String containerName,
+ @PathParam("affinityName") String affinityName,
+ @PathParam("networkAddress1") String networkAddress1,
+ @PathParam("networkAddress2") String networkAddress2,
+ @PathParam("affinityAttribute") String affinityAttribute) {
+
+ if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+ throw new UnauthorizedException("User is not authorized to perform this operation on container "
+ + containerName);
+ }
+
+ IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
+ if (affinityManager == null) {
+ throw new ServiceUnavailableException("Affinity Manager "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ AffinityConfig ac = new AffinityConfig(affinityName, networkAddress1, networkAddress2, affinityAttribute);
+ Status ret = affinityManager.updateAffinityConfig(ac);
+ if (ret.isSuccess()) {
+ return Response.status(Response.Status.CREATED).build();
+ }
+ throw new InternalServerErrorException(ret.getDescription());
+ }
+}
--- /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.affinity.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 AffinityNorthboundRSApplication extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ Set<Class<?>> classes = new HashSet<Class<?>>();
+ classes.add(AffinityNorthbound.class);
+ return classes;
+ }
+}
--- /dev/null
+Manifest-Version: 1.0\r
+Bnd-LastModified: 1376940269425\r
+Build-Jdk: 1.6.0_37\r
+Built-By: sraman\r
+Bundle-ManifestVersion: 2\r
+Bundle-Name: northbound\r
+Bundle-SymbolicName: org.opendaylight.controller.affinity.northbound\r
+Bundle-Version: 0.4.0.SNAPSHOT\r
+Created-By: Apache Maven Bundle Plugin\r
+Export-Package: org.opendaylight.controller.affinity.northbound;uses:="o\r
+ rg.opendaylight.controller.affinity,javax.xml.bind.annotation,javax.ws.\r
+ rs,org.opendaylight.controller.northbound.commons,org.opendaylight.cont\r
+ roller.sal.utils,org.opendaylight.controller.containermanager,org.opend\r
+ aylight.controller.sal.authorization,org.opendaylight.controller.northb\r
+ ound.commons.utils,org.opendaylight.controller.northbound.commons.excep\r
+ tion,javax.ws.rs.core";version="0.4.0.SNAPSHOT"\r
+Ignore-Package: org.codehaus.enunciate.jaxrs\r
+Import-Package: com.sun.jersey.spi.container.servlet;version="[1.17,2)",\r
+ javax.ws.rs;version="[1.1,2)",javax.ws.rs.core;version="[1.1,2)",javax.\r
+ xml.bind,javax.xml.bind.annotation,org.apache.commons.lang3.tuple;versi\r
+ on="[3.1,4)",org.apache.commons.logging;version="[1.1,2)",org.opendayli\r
+ ght.controller.affinity;version="[0.4,1)",org.opendaylight.controller.c\r
+ ontainermanager;version="[0.4,1)",org.opendaylight.controller.northboun\r
+ d.commons;version="[0.4,1)",org.opendaylight.controller.northbound.comm\r
+ ons.exception;version="[0.4,1)",org.opendaylight.controller.northbound.\r
+ commons.utils;version="[0.4,1)",org.opendaylight.controller.sal.authori\r
+ zation;version="[0.5,1)",org.opendaylight.controller.sal.core;version="\r
+ [0.5,1)",org.opendaylight.controller.sal.utils;version="[0.5,1)",org.op\r
+ endaylight.controller.usermanager;version="[0.4,1)",org.slf4j;version="\r
+ [1.7,2)"\r
+Originally-Created-By: Apache Maven Bundle Plugin\r
+Tool: Bnd-1.50.0\r
+Web-ContextPath: /controller/nb/v2/affinity\r
--- /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>JAXRSSwitchManager</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.switchmanager.northbound.SwitchNorthboundRSApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>JAXRSSwitchManager</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>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>affinity</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <artifactId>analytics</artifactId>
+ <version>0.4.1-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.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,
+ org.opendaylight.controller.statisticsmanager,
+ org.opendaylight.controller.switchmanager,
+ org.apache.felix.dm,
+ org.slf4j
+ </Import-Package>
+ <Bundle-Activator>
+ org.opendaylight.controller.analytics.internal.Activator
+ </Bundle-Activator>
+ </instructions>
+ <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <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>
+ <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</groupId>
+ <artifactId>statisticsmanager</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>switchmanager</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project>
--- /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.apache.felix.dm.Component;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.hosttracker.IfHostListener;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+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
+ .getLogger(Activator.class);
+
+ /**
+ * Function called when the activator starts just after some
+ * initializations are done by the
+ * ComponentActivatorAbstractBase.
+ */
+ public void init() {
+ }
+
+ /**
+ * Function called when the activator stops just before the
+ * cleanup done by ComponentActivatorAbstractBase
+ */
+ public void destroy() {
+ }
+
+ /**
+ * Function that is used to communicate to dependency manager the
+ * list of known implementations for services inside a container
+ *
+ * @return An array containing all the CLASS objects that will be
+ * instantiated in order to get an fully working implementation
+ * Object
+ */
+ public Object[] getImplementations() {
+ Object[] res = { AnalyticsManager.class };
+ return res;
+ }
+
+ /**
+ * Function that is called when configuration of the dependencies
+ * is required.
+ *
+ * @param c dependency manager Component object, used for
+ * configuring the dependencies exported and imported
+ * @param imp Implementation class that is being configured,
+ * needed as long as the same routine can configure multiple
+ * implementations
+ * @param containerName The containerName being configured, this allow
+ * also optional per-container different behavior if needed, usually
+ * should not be the case though.
+ */
+ public void configureInstance(Component c, Object imp, String containerName) {
+ if (imp.equals(AnalyticsManager.class)) {
+ // set interfaces
+ c.setInterface(new String[] {
+ IReadServiceListener.class.getName() }, null);
+
+ c.add(createContainerServiceDependency(containerName).setService(IfIptoHost.class)
+ .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));
+ }
+ }
+}
--- /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 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.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.core.NodeConnector;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+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 {
+
+ private static final Logger log = LoggerFactory.getLogger(AnalyticsManager.class);
+
+ private IStatisticsManager statisticsManager;
+ 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;
+
+ 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>();
+ }
+
+ void destroy() {
+ log.debug("DESTROY called!");
+ }
+
+ void start() {
+ log.debug("START called!");
+ }
+
+ void started(){
+ }
+
+ void stop() {
+ log.debug("STOP called!");
+ }
+
+ void setStatisticsManager(IStatisticsManager s) {
+ this.statisticsManager = s;
+ }
+
+ void unsetStatisticsManager(IStatisticsManager s) {
+ if (this.statisticsManager.equals(s)) {
+ this.statisticsManager = null;
+ }
+ }
+
+ void setHostTracker(IfIptoHost h) {
+ this.hostTracker = h;
+ }
+
+ void unsetHostTracker(IfIptoHost h) {
+ if (this.hostTracker.equals(h)) {
+ this.hostTracker = null;
+ }
+ }
+
+ void setSwitchManager(ISwitchManager s) {
+ this.switchManager = s;
+
+ // 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();
+ 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.
+ */
+ private Host getDestinationHostFromFlow(Flow flow) {
+ Host dstHost = null;
+ Match match = flow.getMatch();
+
+ // Flow has to have DL_DST field
+ if (match.isPresent(MatchType.DL_DST)) {
+ MatchField dlDst = match.getField(MatchType.DL_DST);
+
+ // Check cache
+ Host cacheHit = this.destinationHostCache.get(dlDst);
+ if (cacheHit != null) {
+ return cacheHit;
+ }
+
+ // Find the destination host by comparing the MAC address
+ // strings (comparing MAC address bytes, surprisingly, did
+ // not work).
+ String dstMac = MatchType.DL_DST.stringify(dlDst.getValue());
+ for (HostNodeConnector h : this.hostTracker.getAllHosts()) {
+ String hostMac = ((EthernetAddress) h.getDataLayerAddress()).getMacAddress();
+ if (dstMac.equals(hostMac)) {
+ dstHost = h;
+ this.destinationHostCache.put(dlDst, dstHost); // Add to cache
+ break;
+ }
+ }
+ }
+
+ return dstHost;
+ }
+
+ /* Returns the source Host associated with this flow, if one
+ * exists. Returns null otherwise.
+ */
+ private Host getSourceHostFromFlow(Flow flow) {
+ Host srcHost = null;
+ Match match = flow.getMatch();
+
+ // Flow must have IN_PORT field (DL_SRC rarely (never?)
+ // exists).
+ if (match.isPresent(MatchType.IN_PORT)) {
+ MatchField inPort = match.getField(MatchType.IN_PORT);
+
+ // Check cache
+ Host cacheHit = this.sourceHostCache.get(inPort);
+ if (cacheHit != null) {
+ return cacheHit;
+ }
+
+ // Find the source host by comparing the NodeConnectors
+ NodeConnector inPortNc = (NodeConnector) inPort.getValue();
+ for (HostNodeConnector h : this.hostTracker.getAllHosts()) {
+ NodeConnector hostNc = h.getnodeConnector();
+ if (hostNc.equals(inPortNc)) {
+ srcHost = h;
+ this.sourceHostCache.put(inPort, h); // Add to cache
+ break;
+ }
+ }
+ }
+
+ return srcHost;
+ }
+
+ 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();
+ }
+ }
+
+ return byteCount;
+ }
+
+ @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);
+ }
+ }*/
+ }
+
+ @Override
+ public void nodeConnectorStatisticsUpdated(Node node, List<NodeConnectorStatistics> ncStatsList) {
+ // Not interested in this update
+ }
+
+ @Override
+ public void nodeTableStatisticsUpdated(Node node, List<NodeTableStatistics> tableStatsList) {
+ // Not interested in this update
+ }
+
+ @Override
+ public void descriptionStatisticsUpdated(Node node, NodeDescription nodeDescription) {
+ // Not interested in this update
+ }
+}
--- /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
--- /dev/null
+<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">\r
+ <modelVersion>4.0.0</modelVersion>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>affinity</artifactId>\r
+ <version>0.4.1-SNAPSHOT</version>\r
+ <packaging>pom</packaging>\r
+\r
+ <scm>\r
+ <connection>scm:git:http://git.opendaylight.org/gerrit/p/affinity.git</connection>\r
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/affinity.git</developerConnection>\r
+ </scm>\r
+ <properties>\r
+ <propertymavenplugin.version>1.0-alpha-2</propertymavenplugin.version>\r
+ <sonar.host.url>https://sonar.opendaylight.org/</sonar.host.url>\r
+ <sitedeploy>dav:http://nexus.opendaylight.org/content/sites/site</sitedeploy>\r
+ <siteplugin>3.2</siteplugin>\r
+ <projectinfo>2.6</projectinfo>\r
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r
+ <compiler.version>2.3.2</compiler.version>\r
+ <surefire.version>2.15</surefire.version>\r
+ <failsafe.version>2.15</failsafe.version>\r
+ <exam.version>3.0.0</exam.version>\r
+ <url.version>1.5.0</url.version>\r
+ <enunciate.version>1.26.2</enunciate.version>\r
+ <sonar.branch>${user.name}-private-view</sonar.branch>\r
+ <sonar.skippedModules>org.openflow.openflowj,net.sf.jung2</sonar.skippedModules>\r
+ <logback.version>1.0.9</logback.version>\r
+ <slf4j.version>1.7.2</slf4j.version>\r
+ <jackson.version>1.9.8</jackson.version>\r
+ <spring.version>3.1.3.RELEASE</spring.version>\r
+ <spring-security.version>3.1.3.RELEASE</spring-security.version>\r
+ <jersey.version>1.17</jersey.version>\r
+ <virgo.version>3.6.0.RELEASE</virgo.version>\r
+ <geminiweb.version>2.2.0.RELEASE</geminiweb.version>\r
+ <checkstyle.version>2.10</checkstyle.version>\r
+ <testvm.argLine>-Xmx1024m -XX:MaxPermSize=256m</testvm.argLine>\r
+ </properties>\r
+\r
+ <modules>\r
+ <module>affinity/api</module>\r
+ <module>affinity/implementation</module>\r
+ <module>affinity/northbound</module>\r
+ <module>analytics</module>\r
+ </modules>\r
+\r
+ <repositories>\r
+ <!-- To get SVNKit -->\r
+ <repository>\r
+ <id>svnkit-snapshots</id>\r
+ <name>svnkit-snapshots</name>\r
+ <url>${nexusproxy}/repositories/svnkit-snapshots/</url>\r
+ </repository>\r
+ <!-- OpenDayLight Released artifact -->\r
+ <repository>\r
+ <id>opendaylight-release</id>\r
+ <name>opendaylight-release</name>\r
+ <url>${nexusproxy}/repositories/opendaylight.release/</url>\r
+ </repository>\r
+ <!-- OpenDayLight Snapshot artifact -->\r
+ <repository>\r
+ <id>opendaylight-snapshot</id>\r
+ <name>opendaylight-snapshot</name>\r
+ <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>\r
+ </repository>\r
+ </repositories>\r
+ <distributionManagement>\r
+ <!-- OpenDayLight Released artifact -->\r
+ <repository>\r
+ <id>opendaylight-release</id>\r
+ <url>${nexusproxy}/repositories/opendaylight.release/</url>\r
+ </repository>\r
+ <!-- OpenDayLight Snapshot artifact -->\r
+ <snapshotRepository>\r
+ <id>opendaylight-snapshot</id>\r
+ <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>\r
+ </snapshotRepository>\r
+ <!-- Site deployment -->\r
+ <site>\r
+ <id>website</id>\r
+ <url>${sitedeploy}</url>\r
+ </site>\r
+ </distributionManagement>\r
+\r
+ <dependencies>\r
+\r
+ <dependency>\r
+ <groupId>junit</groupId>\r
+ <artifactId>junit</artifactId>\r
+ <version>4.10</version>\r
+ <scope>test</scope>\r
+ <optional>true</optional>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.slf4j</groupId>\r
+ <artifactId>slf4j-api</artifactId>\r
+ <version>1.7.2</version>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.slf4j</groupId>\r
+ <artifactId>slf4j-simple</artifactId>\r
+ <version>1.7.2</version>\r
+ </dependency>\r
+ </dependencies>\r
+\r
+ <build>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.codehaus.mojo</groupId>\r
+ <artifactId>buildnumber-maven-plugin</artifactId>\r
+ <version>1.2</version>\r
+ <executions>\r
+ <execution>\r
+ <phase>validate</phase>\r
+ <goals>\r
+ <goal>create</goal>\r
+ </goals>\r
+ </execution>\r
+ </executions>\r
+ <configuration>\r
+ <doCheck>false</doCheck>\r
+ <doUpdate>false</doUpdate>\r
+ <providerImplementations>\r
+ <svn>javasvn</svn>\r
+ </providerImplementations>\r
+ <revisionOnScmFailure>VersionUnknown</revisionOnScmFailure>\r
+ </configuration>\r
+ <dependencies>\r
+ <dependency>\r
+ <groupId>com.google.code.maven-scm-provider-svnjava</groupId>\r
+ <artifactId>maven-scm-provider-svnjava</artifactId>\r
+ <version>2.0.5</version>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.tmatesoft.svnkit</groupId>\r
+ <artifactId>svnkit</artifactId>\r
+ <version>1.7.4-v1</version>\r
+ </dependency>\r
+ <dependency>\r
+ <groupId>org.apache.maven.scm</groupId>\r
+ <artifactId>maven-scm-provider-svn-commons</artifactId>\r
+ <version>1.7</version>\r
+ </dependency>\r
+ </dependencies>\r
+ </plugin>\r
+ </plugins>\r
+ </build>\r
+ <reporting>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.codehaus.mojo</groupId>\r
+ <artifactId>findbugs-maven-plugin</artifactId>\r
+ <version>2.4.0</version>\r
+ <configuration>\r
+ <effort>Max</effort>\r
+ <threshold>Low</threshold>\r
+ <goal>site</goal>\r
+ </configuration>\r
+ </plugin>\r
+ <plugin>\r
+ <groupId>org.codehaus.mojo</groupId>\r
+ <artifactId>jdepend-maven-plugin</artifactId>\r
+ <version>2.0-beta-2</version>\r
+ </plugin>\r
+ </plugins>\r
+ </reporting>\r
+</project>\r
--- /dev/null
+import httplib2
+import json
+
+h = httplib2.Http(".cache")
+h.add_credentials('admin', 'admin')
+
+resp, content = h.request('http://localhost:8080/controller/nb/v2/affinity/default/affinities', "GET")
+content
+
+put_url = 'http://localhost:8080/controller/nb/v2/affinity/default/test1/192.168.1.1/192.168.1.2/isolate'
+resp, content = h.request(put_url, "PUT")
+resp
+content
+
+resp, content = h.request('http://localhost:8080/controller/nb/v2/affinity/default/affinities', "GET")
+content
+
+#####
+
+resp, content = h.request('http://localhost:8080/controller/nb/v2/statistics/default/flowstats', "GET")
+resp
+content
+
+post_url = 'http://localhost:8080/controller/nb/v2/affinity/default/affinity-config'
+resp, content = h.request(post_url, "POST")
+resp
+content
--- /dev/null
+install file:/Users/sraman/.m2/repository/org/opendaylight/controller/affinity/0.4.1-SNAPSHOT/affinity-0.4.1-SNAPSHOT.jar
+install file:/Users/sraman/.m2/repository/org/opendaylight/controller/affinity/implementation/0.4.1-SNAPSHOT/implementation-0.4.1-SNAPSHOT.jar
+install file:/Users/sraman/.m2/repository/org/opendaylight/controller/affinity/northbound/0.4.1-SNAPSHOT/northbound-0.4.1-SNAPSHOT.jar
+
+ss | grep affinity
+start <id_affinity>
+start <id_affinityapi>
+start <id_affinityimpl>
+
+# install file:/Users/sraman/.m2/repository/org/opendaylight/controller/tutorial_L2_forwarding/0.4.1-SNAPSHOT/tutorial_L2_forwarding-0.4.1-SNAPSHOT.jar
+#ls -l /Users/sraman/.m2/repository/org/opendaylight/controller/affinity/0.4.1-SNAPSHOT/affinity-0.4.1-SNAPSHOT.jar
+#ls -l /Users/sraman/.m2/repository/org/opendaylight/controller/affinity/implementation/0.4.1-SNAPSHOT/implementation-0.4.1-SNAPSHOT.jar
+#ls -l /Users/sraman/.m2/repository/org/opendaylight/controller/affinity/northbound/0.4.1-SNAPSHOT/northbound-0.4.1-SNAPSHOT.jar
+
+
--- /dev/null
+import httplib2
+import json
+
+h = httplib2.Http(".cache")
+h.add_credentials('admin', 'admin')
+
+resp, content = h.request('http://localhost:8080/controller/nb/v2/statistics/default/flowstats', "GET")
+allFlowStats = json.loads(content)
+flowStats = allFlowStats['flowStatistics']
+print flowStats
+
+# These JSON dumps were handy when trying to parse the responses
+#print json.dumps(flowStats[0]['flowStat'][1], indent = 2)
+#print json.dumps(flowStats[4], indent = 2)
+for fs in flowStats:
+ print "\nSwitch ID : " + fs['node']['@id']
+ print '{0:8} {1:8} {2:5} {3:15}'.format('Count', 'Action', 'Port', 'DestIP')
+ for aFlow in fs['flowStat']:
+ count = aFlow['packetCount']
+actions = aFlow['flow']['actions']
+actionType = ''
+actionPort = ''
+#print actions
+if(type(actions) == type(list())):
+ actionType = actions[1]['@type']
+ actionPort = actions[1]['port']['@id']
+else:
+ actionType = actions['@type']
+ actionPort = actions['port']['@id']
+dst = aFlow['flow']['match']['matchField'][0]['value']
+print '{0:8} {1:8} {2:5} {3:15}'.format(count, actionType, actionPort, dst)
--- /dev/null
+import json
+import networkx as nx
+from networkx.readwrite import json_graph
+import httplib2
+
+baseUrl = 'http://localhost:8080/controller/nb/v2/'
+containerName = 'default/'
+
+h = httplib2.Http(".cache")
+h.add_credentials('admin', 'admin')
+
+# Get all the edges/links
+resp, content = h.request(baseUrl + 'topology/' + containerName, "GET")
+edgeProperties = json.loads(content)
+odlEdges = edgeProperties['edgeProperties']
+print json.dumps(odlEdges, indent = 2)
+
+# Get all the nodes/switches
+resp, content = h.request(baseUrl + 'switch/' + containerName + 'nodes/', "GET")
+nodeProperties = json.loads(content)
+odlNodes = nodeProperties['nodeProperties']
+print json.dumps(odlNodes, indent = 2)
+
+# Put nodes and edges into a graph
+graph = nx.Graph()
+for node in odlNodes:
+ graph.add_node(node['node']['@id'])
+for edge in odlEdges:
+ e = (edge['edge']['headNodeConnector']['node']['@id'], edge['edge']['tailNodeConnector']['node']['@id'])
+ graph.add_edge(*e)
+# Print out graph info as a sanity check
+print graph.number_of_nodes()
+print graph.nodes()
+#print json.dumps(odlNodes, indent = 2)
+# These JSON dumps were handy when trying to parse the responses
+#print json.dumps(topo[0], indent = 2)
+
+
+# write json formatted data to use in visualization
+d = json_graph.node_link_data(graph)
+json.dump(d, open('topo.json','w'))
+print('Wrote node-link JSON data')