--- /dev/null
+Create an affinity group:
+ /affinity/nb/v2/{container}/create/group/{name}
+
+Fetch an affinity group given its name:
+/affinity/nb/v2/{container}/group/{name}
+
+Add affinity element to affinity group:
+/affinity/nb/v2/{container}/add/{groupname}/mac/{address}
+ /affinity/nb/v2/{container}/add/{groupname}/ip/{address}
+/affinity/nb/v2/{container}/add/{groupname}/host/{address}
+
+Delete element from an affinity group.
+/affinity/nb/v2/{container}/delete/{groupname}/mac/{address}
+ /affinity/nb/v2/{container}/delete/{groupname}/ip/{address}
+/affinity/nb/v2/{container}/delete/{groupname}/host/{address}
+
+Add affinity link from one group to another:
+/affinity/nb/v2/{container}/create/link/{name}
+/affinity/nb/v2/{container}/from/{linkname}/{affinitygroup}
+/affinity/nb/v2/{container}/to/{linkname}/{affinitygroup}
+
+Create an affinity element:
+# For now, these are simple unary objects. Future implementations to include multiple attributes.
+/affinity/nb/v2/{container}/create/identifier/{name}/mac/{address}
+/affinity/nb/v2/{container}/create/identifier/{name}/ip/{address}
+/affinity/nb/v2/{container}/create/identifier/{hostname}/host/{address}
+
+List all affinities:
+/affinity/nb/v2/{container}/affinities
+
+List stats for affinities:
+...
Manifest-Version: 1.0\r
-Bnd-LastModified: 1376940266146\r
+Bnd-LastModified: 1377719211376\r
Build-Jdk: 1.6.0_37\r
Built-By: sraman\r
Bundle-ManifestVersion: 2\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
+Import-Package: javax.ws.rs;version="[1.1,2)",javax.ws.rs.core;version="\r
+ [1.1,2)",javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.annota\r
+ tion,org.apache.commons.lang3.builder;version="[3.1,4)",org.apache.feli\r
+ x.dm;version="[3.0,4)",org.eclipse.osgi.framework.console;version="[1.1\r
+ ,2)",org.opendaylight.controller.clustering.services;version="[0.4,1)",\r
+ org.opendaylight.controller.configuration;version="[0.4,1)",org.openday\r
+ light.controller.sal.core;version="[0.5,1)",org.opendaylight.controller\r
+ .sal.inventory;version="[0.5,1)",org.opendaylight.controller.sal.packet\r
+ ;version="[0.5,1)",org.opendaylight.controller.sal.utils;version="[0.5,\r
+ 1)",org.osgi.framework;version="[1.7,2)",org.slf4j;version="[1.7,2)",or\r
+ g.slf4j\r
Tool: Bnd-1.50.0\r
<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>
+ <enunciate.version>1.26.2</enunciate.version>
</properties>
<build>
<pluginManagement>
org.eclipse.osgi.framework.console,
org.osgi.framework,
javax.xml.bind.annotation,
- org.apache.commons.lang3.builder
+ org.apache.commons.lang3.builder,
+ javax.ws.rs,
+ javax.ws.rs.core,
+ javax.xml.bind.annotation,
+ javax.xml.bind,
+ org.slf4j,
+ !org.codehaus.enunciate.jaxrs
</Import-Package>
</instructions>
<manifestLocation>${project.basedir}/META-INF</manifestLocation>
</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>
<artifactId>sal</artifactId>
<version>0.5.0-SNAPSHOT</version>
</dependency>
+
+ <dependency>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>enunciate-core-annotations</artifactId>
+ <version>${enunciate.version}</version>
+ </dependency>
+
</dependencies>
</project>
+++ /dev/null
-
-/*
- * Copyright (c) 2013 Plexxi, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.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
+package org.opendaylight.controller.affinity;
+
+import org.opendaylight.controller.sal.utils.NetUtils;
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Map;
+import java.util.HashMap;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+
+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 javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class AffinityGroup implements Cloneable, Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @XmlAttribute
+ private String name;
+ @XmlElement
+ private final Map<String, AffinityIdentifier> elements;
+
+ public AffinityGroup(String name) {
+ this.name = name;
+ elements = new HashMap<String, AffinityIdentifier>();
+ }
+ public AffinityGroup(String name, HashMap<String, AffinityIdentifier> elements) {
+ this.name = name;
+ this.elements = elements;
+ }
+
+ // Basic affinity element, IP address
+ public Status add(String ipaddress) {
+ AffinityIdentifier<InetAddress> elem = new AffinityIdentifier();
+
+ elem.setName(ipaddress);
+ if (NetUtils.isIPAddressValid(ipaddress)) {
+ elem.set(NetUtils.parseInetAddress(ipaddress));
+ elements.put(ipaddress, elem);
+ return new Status(StatusCode.SUCCESS);
+ } else {
+ return new Status(StatusCode.BADREQUEST);
+ }
+ }
+
+ // Remove an affinity element given its IP address.
+ public void remove(String ipaddress) {
+ if (elements != null) {
+ elements.remove(ipaddress);
+ }
+ }
+ public Integer size() {
+ return (elements.size());
+ }
+ public void print() {
+ for (AffinityIdentifier value : elements.values()) {
+ value.print();
+ }
+ }
+ public String getName() {
+ return name;
+ }
+}
+
--- /dev/null
+package org.opendaylight.controller.affinity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/* Affinity identifier */
+public class AffinityIdentifier<T> {
+ private T value;
+ private String name;
+
+ public T get() {
+ return value;
+ }
+ public void set(T t) {
+ value = t;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public void print() {
+ System.out.println(value);
+ }
+}
+
--- /dev/null
+package org.opendaylight.controller.affinity;
+
+import org.opendaylight.controller.sal.utils.NetUtils;
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Map;
+import java.util.HashMap;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+
+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 javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class AffinityLink implements Cloneable, Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @XmlAttribute
+ private String name;
+ @XmlElement
+ AffinityGroup fromGroup;
+ @XmlElement
+ AffinityGroup toGroup;
+ @XmlElement
+ String affinityAttribute;
+
+ public AffinityLink() {
+ }
+ public AffinityLink(String name, AffinityGroup fromGroup, AffinityGroup toGroup) {
+ this.name = name;
+ this.fromGroup = fromGroup;
+ this.toGroup = toGroup;
+ }
+ public String getName() {
+ return this.name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public void setFromGroup(AffinityGroup fromGroup) {
+ this.fromGroup = fromGroup;
+ }
+ public void setToGroup(AffinityGroup toGroup) {
+ this.toGroup = toGroup;
+ }
+ public void setAttribute(String attribute) {
+ this.affinityAttribute = attribute;
+ }
+
+ public String getAttribute() {
+ return this.affinityAttribute;
+ }
+ public AffinityGroup getFromGroup() {
+ return this.fromGroup;
+ }
+ public AffinityGroup getToGroup() {
+ return this.toGroup;
+ }
+}
+
import java.net.InetAddress;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
import java.util.Set;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.Property;
import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.affinity.AffinityConfig;
+import org.opendaylight.controller.affinity.AffinityLink;
/**
* Primary purpose of this interface is to provide methods for
*/
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();
+ public Status addAffinityLink(AffinityLink al);
+ public Status removeAffinityLink(AffinityLink al);
+ public Status removeAffinityLink(String linkName);
+
+ public AffinityLink getAffinityLink(String name);
+ public List<AffinityLink> getAllAffinityLinks();
- /**
- * 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 Status addAffinityGroup(AffinityGroup ag);
+ public Status removeAffinityGroup(String name);
+
+ public AffinityGroup getAffinityGroup(String name);
+ public List<AffinityGroup> getAllAffinityGroups();
- public List<AffinityConfig> getAffinityConfigList();
- public AffinityConfig getAffinityConfig(String affinity);
+ /* Save all configs to their respective files. */
+ public Status saveAffinityConfig();
}
* the affinity config that was added or removed
* @param add true if add; false otherwise
*/
- public void affinityNotify(AffinityConfig aff, boolean add);
+ public void affinityLinkNotify(AffinityLink aff, boolean add);
+ public void affinityGroupNotify(AffinityGroup aff, boolean add);
/**
* Inform listeners that the network node has notified us about a failure in
Manifest-Version: 1.0\r
-Bnd-LastModified: 1376940268439\r
+Bnd-LastModified: 1377719213514\r
Build-Jdk: 1.6.0_37\r
Built-By: sraman\r
Bundle-Activator: org.opendaylight.controller.affinity.internal.Activato\r
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.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.AffinityGroup;
+import org.opendaylight.controller.affinity.AffinityLink;
import org.opendaylight.controller.affinity.IAffinityManager;
import org.opendaylight.controller.affinity.IAffinityManagerAware;
import org.slf4j.Logger;
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 String affinityLinkFileName = null;
+ private String affinityGroupFileName = null;
+ private ConcurrentMap<String, AffinityGroup> affinityGroupList;
+ private ConcurrentMap<String, AffinityLink> affinityLinkList;
private ConcurrentMap<Long, String> configSaveEvent;
+
private final Set<IAffinityManagerAware> affinityManagerAware = Collections
.synchronizedSet(new HashSet<IAffinityManagerAware>());
public void startUp() {
// Initialize configuration file names
- affinityConfigFileName = ROOT + "affinityConfig_" + this.getContainerName()
+ affinityLinkFileName = ROOT + "affinityConfig_link" + this.getContainerName()
+ + ".conf";
+ affinityGroupFileName = ROOT + "affinityConfig_group" + this.getContainerName()
+ ".conf";
// Instantiate cluster synced variables
* Read startup and build database if we have not already gotten the
* configurations synced from another node
*/
- if (affinityConfigList.isEmpty()) {
+ if (affinityGroupList.isEmpty() || affinityLinkList.isEmpty()) {
loadAffinityConfiguration();
}
}
log.warn("un-initialized clusterContainerService, can't create cache");
return;
}
-
try {
clusterContainerService.createCache(
- "affinity.affinityConfigList",
+ "affinity.affinityGroupList",
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+ clusterContainerService.createCache(
+ "affinity.affinityLinkList",
EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
clusterContainerService.createCache(
"affinity.configSaveEvent",
@SuppressWarnings({ "unchecked", "deprecation" })
private void retrieveCaches() {
if (this.clusterContainerService == null) {
- log.info("un-initialized clusterContainerService, can't create cache");
+ log.info("un-initialized clusterContainerService, can't retrieve cache");
return;
}
- affinityConfigList = (ConcurrentMap<String, AffinityConfig>) clusterContainerService
- .getCache("affinity.affinityConfigList");
- if (affinityConfigList == null) {
- log.error("\nFailed to get cache for affinityConfigList");
+ affinityGroupList = (ConcurrentMap<String, AffinityGroup>) clusterContainerService
+ .getCache("affinity.affinityGroupList");
+ if (affinityGroupList == null) {
+ log.error("\nFailed to get cache for affinityGroupList");
+ }
+ affinityLinkList = (ConcurrentMap<String, AffinityLink>) clusterContainerService
+ .getCache("affinity.affinityLinkList");
+ if (affinityLinkList == null) {
+ log.error("\nFailed to get cache for affinityLinkList");
}
+
configSaveEvent = (ConcurrentMap<Long, String>) clusterContainerService
.getCache("affinity.configSaveEvent");
if (configSaveEvent == null) {
}
private void nonClusterObjectCreate() {
- affinityConfigList = new ConcurrentHashMap<String, AffinityConfig>();
+ affinityLinkList = new ConcurrentHashMap<String, AffinityLink>();
+ affinityGroupList = new ConcurrentHashMap<String, AffinityGroup>();
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);
+ public Status addAffinityLink(AffinityLink al) {
+ boolean putNewLink = false;
+
+ if (affinityLinkList.containsKey(al.getName())) {
+ return new Status(StatusCode.CONFLICT,
+ "AffinityLink with the specified name already configured.");
+ }
+
+
+ AffinityLink alCurr = affinityLinkList.get(al.getName());
+ if (alCurr == null) {
+ if (affinityLinkList.putIfAbsent(al.getName(), al) == null) {
+ putNewLink = true;
+ }
+ } else {
+ putNewLink = affinityLinkList.replace(al.getName(), alCurr, al);
+ }
+
+ if (!putNewLink) {
+ String msg = "Cluster conflict: Conflict while adding the subnet " + al.getName();
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+
+ return new Status(StatusCode.SUCCESS);
}
+ public Status removeAffinityLink(String name) {
+ affinityLinkList.remove(name);
+ return new Status(StatusCode.SUCCESS);
+ }
+ public Status removeAffinityLink(AffinityLink al) {
+ AffinityLink alCurr = affinityLinkList.get(al.getName());
+ if (alCurr != null) {
+ affinityLinkList.remove(alCurr);
+ return new Status(StatusCode.SUCCESS);
+ } else {
+ String msg = "Affinity Link with specified name does not exist." + al.getName();
+ return new Status(StatusCode.INTERNALERROR, msg);
+ }
+ }
+
@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();
+ public AffinityLink getAffinityLink(String linkName) {
+ return affinityLinkList.get(linkName);
}
- @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);
- }
+ @Override
+ public List<AffinityLink> getAllAffinityLinks() {
+ return new ArrayList<AffinityLink>(affinityLinkList.values());
}
- /* Add if absent. */
@Override
- public Status updateAffinityConfig(AffinityConfig cfgObject) {
- // update default container only
- if (!isDefaultContainer) {
- return new Status(StatusCode.INTERNALERROR, "Not default container");
- }
+ public Status addAffinityGroup(AffinityGroup ag) {
+ boolean putNewGroup = false;
+ String name = ag.getName();
+ if (affinityGroupList.containsKey(name)) {
+ return new Status(StatusCode.CONFLICT,
+ "AffinityGroup with the specified name already configured.");
+ }
+ AffinityGroup agCurr = affinityGroupList.get(name);
+ if (agCurr == null) {
+ if (affinityGroupList.putIfAbsent(name, ag) == null) {
+ putNewGroup = true;
+ }
+ } else {
+ putNewGroup = affinityGroupList.replace(name, agCurr, ag);
+ }
+
+ if (!putNewGroup) {
+ String msg = "Cluster conflict: Conflict while adding the subnet " + name;
+ return new Status(StatusCode.CONFLICT, msg);
+ }
+
+ return new Status(StatusCode.SUCCESS);
+ }
- 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());
+ /* Check for errors. */
+ @Override
+ public Status removeAffinityGroup(String name) {
+ affinityGroupList.remove(name);
+ return new Status(StatusCode.SUCCESS);
}
+ @Override
+ public AffinityGroup getAffinityGroup(String groupName) {
+ return affinityGroupList.get(groupName);
+ }
- /* 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);
+ public List<AffinityGroup> getAllAffinityGroups() {
+ return new ArrayList<AffinityGroup>(affinityGroupList.values());
}
- /* Remove affinity config */
+
+ /* Find where this is used. */
@Override
- public Status removeAffinityConfigObject(AffinityConfig cfgObject) {
- // update default container only
- if (!isDefaultContainer) {
- return new Status(StatusCode.INTERNALERROR, "Not default container");
- }
+ 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();
+ }
- 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);
- }
+ @SuppressWarnings("unchecked")
+ private void loadAffinityConfiguration() {
+ ObjectReader objReader = new ObjectReader();
+ ConcurrentMap<String, AffinityGroup> groupList = (ConcurrentMap<String, AffinityGroup>) objReader.read(this, affinityGroupFileName);
+ ConcurrentMap<String, AffinityLink> linkList = (ConcurrentMap<String, AffinityLink>) objReader.read(this, affinityLinkFileName);
+
+ /* group list */
+ if (groupList != null) {
+ for (AffinityGroup ag : groupList.values()) {
+ addAffinityGroup(ag);
+ }
+ }
+
+ /* link list */
+ if (linkList != null) {
+ for (AffinityLink al : linkList.values()) {
+ addAffinityLink(al);
+ }
}
- return new Status(StatusCode.INTERNALERROR, "Remove failed: " + cfgObject.getName());
}
@Override
public Status saveConfiguration() {
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");
- }
+ retS = objWriter.write(new ConcurrentHashMap<String, AffinityLink>(
+ affinityLinkList), affinityLinkFileName);
+
+ retP = objWriter.write(new ConcurrentHashMap<String, AffinityGroup>(
+ affinityGroupList), affinityGroupFileName);
+
+ if (retS.isSuccess() && retP.isSuccess()) {
+ return new Status(StatusCode.SUCCESS, "Configuration saved.");
+ } else {
+ return new Status(StatusCode.INTERNALERROR, "Save failed");
+ }
}
@Override
}
void setClusterContainerService(IClusterContainerServices s) {
- log.debug("Cluster Service set for Statistics Mgr");
+ log.debug("Cluster Service set for affinity mgr");
this.clusterContainerService = s;
}
void unsetClusterContainerService(IClusterContainerServices s) {
if (this.clusterContainerService == s) {
- log.debug("Cluster Service removed for Statistics Mgr!");
+ log.debug("Cluster Service removed for affinity mgr!");
this.clusterContainerService = null;
}
}
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;
+import org.opendaylight.controller.affinity.AffinityGroup;
+import org.opendaylight.controller.affinity.AffinityLink;
public class AffinityManagerImplTest {
AffinityManagerImpl affinitymgr = new AffinityManagerImpl();
affinitymgr.startUp();
- AffinityConfig ac = new AffinityConfig("test_affinity1", "10.0.0.1", "10.0.0.2", "Isolate");
+ AffinityGroup ag1 = new AffinityGroup("group1");
- // Add status to update/add
- Status addResult = affinitymgr.updateAffinityConfig(ac);
- Assert.assertTrue(addResult.isSuccess());
+ // Add a valid IP and confirm.
+ Status ret1 = ag1.add("10.0.0.10");
+ Assert.assertTrue(ret1.isSuccess());
- Status removeResult = (affinitymgr.removeAffinityConfig(ac.getName()));
- Assert.assertTrue(removeResult.isSuccess());
+ Status ret2 = ag1.add("10.0.0.20");
+ Assert.assertTrue(ret2.isSuccess());
- AffinityConfig affinityConfigResult = affinitymgr.getAffinityConfig(ac.getName());
- Assert.assertTrue(affinityConfigResult == null);
- // System.out.println("*" + switchmgr.addSubnet(subnet) + "*");
+ // Add an invalid element.
+ Status ret3 = ag1.add("10");
+ System.out.println(ret3);
+ Assert.assertTrue(!ret3.isSuccess());
+
+ // Second affinity group.
+ AffinityGroup ag2 = new AffinityGroup("group2");
+ ag2.add("20.0.0.10");
+ ag2.add("20.0.0.20");
+
+ // Add an affinity link from ag1 to ag2.
+ AffinityLink al1 = new AffinityLink();
+ al1.setFromGroup(ag1);
+ al1.setToGroup(ag2);
+ al1.setName("link1");
+ al1.setAttribute("isolate");
+
+ // Add a self loop for ag2.
+ AffinityLink al2 = new AffinityLink("link2", ag2, ag2);
+ al2.setFromGroup(ag2);
+ al2.setToGroup(ag2);
+ al2.setName("link2");
+ al2.setAttribute("hopcount");
+
+ System.out.println("Affinity group size is " + ag1.size());
+ Assert.assertTrue(ag1.size() == 2);
+ ag1.print();
+
+ Status result;
+ result = affinitymgr.addAffinityGroup(ag1);
+ Assert.assertTrue(result.isSuccess());
+
+ result = affinitymgr.addAffinityGroup(ag2);
+ Assert.assertTrue(result.isSuccess());
+
+ result = affinitymgr.addAffinityLink(al1);
+ Assert.assertTrue(result.isSuccess());
+
+ result = affinitymgr.addAffinityLink(al2);
+ Assert.assertTrue(result.isSuccess());
+
+ /* Constraint checking? */
+ result = (affinitymgr.removeAffinityGroup(ag1.getName()));
+ Assert.assertTrue(result.isSuccess());
+
+ affinitymgr.saveConfiguration();
}
}
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.affinity.IAffinityManager;
import org.opendaylight.controller.affinity.AffinityConfig;
+import org.opendaylight.controller.affinity.AffinityGroup;
+import org.opendaylight.controller.affinity.AffinityLink;
/**
* The class provides Northbound REST APIs to access affinity configuration.
}
throw new InternalServerErrorException(ret.getDescription());
}
+
+
+ /**
+ * Add an affinity group to the configuration database
+ *
+ * @param containerName
+ * Name of the Container
+ * @param affinityGroup
+ * Name of the new affinity being added
+ * @return Response as dictated by the HTTP Response Status code
+ */
+
+ @Path("/{containerName}/create/group/{name}")
+ @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 addAffinityGroup(
+ @PathParam("containerName") String containerName,
+ @PathParam("groupName") String groupName) {
+
+ 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());
+ }
+
+ AffinityGroup ag = new AffinityGroup(groupName);
+ Status ret = affinityManager.addAffinityGroup(ag);
+ if (ret.isSuccess()) {
+ return Response.status(Response.Status.CREATED).build();
+ }
+ throw new InternalServerErrorException(ret.getDescription());
+ }
+
+ /**
+ * Add an element to an affinity group.
+ *
+ * @param containerName
+ * Name of the Container
+ * @param affinityGroup
+ * Name of the group
+ * @param address
+ * IP or Mac address of the
+ * @return Response as dictated by the HTTP Response Status code
+ */
+
+ @Path("/{containerName}/{groupname}/add/ip/{address}")
+ @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 addIpAddress(
+ @PathParam("containerName") String containerName,
+ @PathParam("groupName") String groupName,
+ @PathParam("address") String ipaddress) {
+
+ IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
+ if (affinityManager == null) {
+ throw new ServiceUnavailableException("Affinity Manager "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ AffinityGroup ag = affinityManager.getGroup(groupName);
+ Status ret = ag.addAffinityElement(ipaddress);
+
+ if (ret.isSuccess()) {
+ return Response.status(Response.Status.CREATED).build();
+ }
+ throw new InternalServerErrorException(ret.getDescription());
+ }
+
+
+ /**
+ * Delete an element from an affinity group.
+ *
+ * @param containerName
+ * Name of the Container
+ * @param affinityGroup
+ * Name of the group
+ * @param address
+ * IP or Mac address of the
+ * @return Response as dictated by the HTTP Response Status code
+ */
+
+ @Path("/{containerName}/{groupname}/delete/ip/{address}")
+ @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 deleteIpAddress(
+ @PathParam("containerName") String containerName,
+ @PathParam("groupName") String groupName,
+ @PathParam("address") String ipaddress) {
+
+ IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
+ if (affinityManager == null) {
+ throw new ServiceUnavailableException("Affinity Manager "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ AffinityGroup ag = affinityManager.getGroup(groupName);
+ Status ret = ag.removeAffinityElement(ipaddress);
+
+ if (ret.isSuccess()) {
+ return Response.status(Response.Status.CREATED).build();
+ }
+ throw new InternalServerErrorException(ret.getDescription());
+ }
+
+
+
+ /**
+ * Add an affinity link to the database and set its from/to groups.
+ *
+ * @param containerName
+ * Name of the Container
+ * @param affinityLink
+ * Name of the affinity link
+ * @param group1
+ * Name of the affinity group
+ * @param group2
+ * Name of the affinity group
+ * @return Response as dictated by the HTTP Response Status code
+ */
+
+ @Path("/{containerName}/create/link/{linkName}/from/{group1}/to/{group2}")
+ @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 addAffinityLink(
+ @PathParam("containerName") String containerName,
+ @PathParam("linkName") String linkName,
+ @PathParam("group1") String group1,
+ @PathParam("group2") String group2) {
+ IAffinityManager affinityManager = getIfAffinityManagerService(containerName);
+ if (affinityManager == null) {
+ throw new ServiceUnavailableException("Affinity Manager "
+ + RestMessages.SERVICEUNAVAILABLE.toString());
+ }
+
+ /* Add the new link object. */
+ AffinityLink al = new AffinityLink(linkName);
+ Status ret = affinityManager.addAffinityLink(al);
+ if (!ret.isSuccess()) {
+ throw new InternalServerErrorException(ret.getDescription());
+ }
+ AffinityGroup ag1 = affinityManager.getAffinityGroup(ag1);
+ AffinityGroup ag2 = affinityManager.getAffinityGroup(ag2);
+
+ al.setFromGroup(ag1);
+ al.setToGroup(ag2);
+
+ return Response.status(Response.Status.CREATED).build();
+ }
}
+
Manifest-Version: 1.0\r
-Bnd-LastModified: 1376940269425\r
+Bnd-LastModified: 1377097334954\r
Build-Jdk: 1.6.0_37\r
Built-By: sraman\r
Bundle-ManifestVersion: 2\r