<groupId>org.opendaylight.controller</groupId>
<artifactId>usermanager</artifactId>
</dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
- <dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>javax.servlet</artifactId>
- </dependency>
- <!-- Spring security -->
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-config</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-taglibs</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.transaction</artifactId>
- </dependency>
</dependencies>
</project>
</plugins>
</build>
<dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal.connection</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager</artifactId>
<opendaylight-l2-types.version>2013.08.27.2-SNAPSHOT</opendaylight-l2-types.version>
<yang-ext.version>2013.09.07.2-SNAPSHOT</yang-ext.version>
<javassist.version>3.17.1-GA</javassist.version>
- <sample-toaster.version>1.0-SNAPSHOT</sample-toaster.version>
<releaseplugin.version>2.3.2</releaseplugin.version>
<commons.lang.version>3.1</commons.lang.version>
<jacoco.version>0.5.3.201107060350</jacoco.version>
<enforcer.version>1.3.1</enforcer.version>
<bundle.plugin.version>2.3.7</bundle.plugin.version>
<junit.version>4.8.1</junit.version>
- <bgpcep.version>0.3.0-SNAPSHOT</bgpcep.version>
<yangtools.version>0.6.0-SNAPSHOT</yangtools.version>
<!--versions for bits of the controller -->
<controller.version>0.4.1-SNAPSHOT</controller.version>
<!-- Third party version -->
<jersey-servlet.version>1.17</jersey-servlet.version>
<corsfilter.version>7.0.42</corsfilter.version>
- <!-- Northbound API version -->
- <commons.northbound.version>0.4.1-SNAPSHOT</commons.northbound.version>
<!-- Sonar properties using jacoco to retrieve integration test results -->
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.language>java</sonar.language>
<artifactId>enunciate-core-annotations</artifactId>
<version>${enunciate.version}</version>
</dependency>
+
+ <!-- md-sal -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-netconf-connector</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-api</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-broker-impl</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-spi</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-api</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-impl</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-compatibility</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-connector-api</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-rest-connector</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-inventory</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-base</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-statistics</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-flow-management</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.md</groupId>
+ <artifactId>inventory-manager</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.md</groupId>
+ <artifactId>forwardingrules-manager</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.md</groupId>
+ <artifactId>topology-lldp-discovery</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.md</groupId>
+ <artifactId>topology-manager</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.md</groupId>
+ <artifactId>statistics-manager</artifactId>
+ <version>${mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>concepts</artifactId>
+ <version>${concepts.version}</version>
+ </dependency>
+
+
+ <!-- config-->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-manager</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-jmx-generator</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-store-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-store-impl</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>logback-config</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-file-adapter</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-file-xml-adapter</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-directory-adapter</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-directory-xml-adapter</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-directory-autodetect-adapter</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>shutdown-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>shutdown-impl</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+
+ <!-- Netconf -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-api</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-impl</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-util</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-client</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-mapping-api</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-ssh</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-netconf-connector</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netconf-monitoring</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ietf-netconf-monitoring</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ietf-netconf-monitoring-extension</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-persister-impl</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
+
+ <!-- threadpool -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>threadpool-config-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netty-config-api</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>threadpool-config-impl</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netty-threadgroup-config</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netty-event-executor-config</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>netty-timer-config</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>configuration</artifactId>
+ <version>${configuration.version}</version>
+ </dependency>
+
</dependencies>
</dependencyManagement>
<configuration>
<instructions>
<Import-Package>
- org.opendaylight.controller.sal.utils,
- org.apache.commons.lang3.builder
+ org.opendaylight.controller.sal.utils
</Import-Package>
<Export-Package>
org.opendaylight.controller.configuration
package org.opendaylight.controller.configuration;
+import java.util.List;
+
+import org.opendaylight.controller.sal.utils.IObjectReader;
import org.opendaylight.controller.sal.utils.Status;
/**
* @return the Status object representing the result of the saving request
*/
Status saveConfigurations();
+
+ /**
+ * Bundle will call this function to ask Configuration Manager to persist
+ * their configurations. It is up to the Configuration Manager to decide
+ * how the configuration will be persisted
+ *
+ * @param config
+ * The bundle configuration as a collection of
+ * ConfigurationObject
+ * @param storeName
+ * The identifier for this configuration
+ * @return The Status of the operation
+ */
+ Status persistConfiguration(List<ConfigurationObject> config, String storeName);
+
+ /**
+ * Bundle will call this function to ask Configuration Manager to retrieve
+ * the configuration identified by the passed store name
+ *
+ * @param reader
+ * The reader object for parsing the configuration provided by
+ * the caller
+ * @param storeName
+ * The identifier for the configuration
+ * @return The retrieved configuration as a collection of
+ * ConfigurationObject
+ */
+ List<ConfigurationObject> retrieveConfiguration(IObjectReader reader, String storeName);
}
// export the service
c.setInterface(
new String[] { IConfigurationService.class.getName(),
- ICacheUpdateAware.class.getName()},
- props);
+ ICacheUpdateAware.class.getName() }, props);
c.add(createServiceDependency().setService(
IClusterGlobalServices.class).setCallbacks(
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
import org.opendaylight.controller.configuration.ConfigurationEvent;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationAware;
import org.opendaylight.controller.configuration.IConfigurationService;
-import org.opendaylight.controller.sal.utils.StatusCode;
+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.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory
.getLogger(ConfigurationService.class);
public static final String SAVE_EVENT_CACHE = "config.event.save";
+ private static final Object ROOT = GlobalConstants.STARTUPHOME.toString();
private IClusterGlobalServices clusterServices;
private ConcurrentMap <ConfigurationEvent, String> configEvent;
private Set<IConfigurationAware> configurationAwareList = Collections
.synchronizedSet(new HashSet<IConfigurationAware>());
+ private ObjectReader objReader;
+ private ObjectWriter objWriter;
public int getConfigurationAwareListSize() {
public void start() {
allocateCache();
retrieveCache();
+ objReader = new ObjectReader();
+ objWriter = new ObjectWriter();
}
public void destroy() {
logger.error("Failed to retrieve configuration Cache");
}
}
+
+ @Override
+ public Status persistConfiguration(List<ConfigurationObject> config, String fileName) {
+ String destination = String.format("%s%s", ROOT, fileName);
+ return objWriter.write(config, destination);
+ }
+
+ @Override
+ public List<ConfigurationObject> retrieveConfiguration(IObjectReader reader, String fileName) {
+ if (!clusterServices.amICoordinator()) {
+ return Collections.emptyList();
+ }
+ String source = String.format("%s%s", ROOT, fileName);
+ Object obj = objReader.read(reader, source);
+ return (obj == null || !(obj instanceof List)) ? Collections.<ConfigurationObject> emptyList()
+ : (List<ConfigurationObject>) obj;
+ }
}
package org.opendaylight.controller.configuration.internal;
+import java.io.File;
import java.util.Collections;
+import java.util.Dictionary;
import java.util.EnumSet;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
+import org.apache.felix.dm.Component;
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.ConfigurationEvent;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationAware;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
import org.opendaylight.controller.configuration.IConfigurationContainerService;
+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.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.slf4j.Logger;
*
* @brief Backend functionality for all ConfigurationService related tasks.
*
- *
*/
-public class ContainerConfigurationService implements IConfigurationContainerService, IConfigurationAware,
- ICacheUpdateAware<ConfigurationEvent, String> {
+public class ContainerConfigurationService implements IConfigurationContainerService,
+ IConfigurationAware, ICacheUpdateAware<ConfigurationEvent, String> {
public static final String CONTAINER_SAVE_EVENT_CACHE = "config.container.event.save";
private static final Logger logger = LoggerFactory.getLogger(ContainerConfigurationService.class);
private IClusterContainerServices clusterServices;
*/
private Set<IConfigurationContainerAware> configurationAwareList = Collections
.synchronizedSet(new HashSet<IConfigurationContainerAware>());
+ private String root;
+ private ObjectReader objReader;
+ private ObjectWriter objWriter;
public void addConfigurationContainerAware(
IConfigurationContainerAware configurationAware) {
}
}
- public void init() {
+ void init(Component c) {
+ Dictionary<?, ?> props = c.getServiceProperties();
+ String containerName = (props != null) ? (String) props.get("containerName") : GlobalConstants.DEFAULT.toString();
+ root = String.format("%s%s/", GlobalConstants.STARTUPHOME.toString(), containerName);
+ if (!new File(root).exists()) {
+ boolean created = new File(root).mkdir();
+ if (!created) {
+ logger.error("Failed to create startup config directory for container {}", containerName);
+ }
+ }
}
public void start() {
allocateCache();
retrieveCache();
+ objReader = new ObjectReader();
+ objWriter = new ObjectWriter();
}
public void destroy() {
this.configurationAwareList.clear();
}
+ /**
+ * Function called by the dependency manager before Container is Stopped and Destroyed.
+ */
+ public void containerStop() {
+ // Remove container directory along with its startup files
+ File[] files = new File(root).listFiles();
+ for (File file : files) {
+ file.delete();
+ }
+ new File(root).delete();
+ }
+
@Override
public Status saveConfiguration() {
boolean success = true;
logger.error("Failed to retrieve configuration Cache");
}
}
+
+ @Override
+ public Status persistConfiguration(List<ConfigurationObject> config, String fileName) {
+ String destination = String.format("%s%s", root, fileName);
+ return objWriter.write(config, destination);
+ }
+
+ @Override
+ public List<ConfigurationObject> retrieveConfiguration(IObjectReader reader, String fileName) {
+ if (!clusterServices.amICoordinator()) {
+ return Collections.emptyList();
+ }
+ String source = String.format("%s%s", root, fileName);
+ Object obj = objReader.read(reader, source);
+ return (obj == null || !(obj instanceof List)) ? Collections.<ConfigurationObject> emptyList()
+ : (List<ConfigurationObject>) obj;
+ }
}
org.opendaylight.controller.sal.utils,
org.opendaylight.controller.sal.core,
org.opendaylight.controller.sal.action,
- org.opendaylight.controller.sal.flowprogrammer,
org.opendaylight.controller.sal.match,
org.opendaylight.controller.sal.packet,
org.opendaylight.controller.sal.reader,
- org.apache.commons.lang3.builder,
org.slf4j,
javax.xml.bind.annotation,
javax.xml.bind
<Import-Package>
org.opendaylight.controller.containermanager,
org.opendaylight.controller.appauth.authorization,
- org.opendaylight.controller.usermanager,
org.opendaylight.controller.configuration,
org.opendaylight.controller.clustering.services,
org.opendaylight.controller.sal.authorization,
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>usermanager</artifactId>
- </dependency>
</dependencies>
</project>
import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
import org.opendaylight.controller.configuration.IConfigurationAware;
+import org.opendaylight.controller.configuration.IConfigurationService;
import org.opendaylight.controller.containermanager.IContainerAuthorization;
import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
import org.opendaylight.controller.sal.core.IContainer;
.setCallbacks("setClusterServices", "unsetClusterServices")
.setRequired(true));
+ c.add(createServiceDependency().setService(
+ IConfigurationService.class).setCallbacks(
+ "setConfigurationService",
+ "unsetConfigurationService").setRequired(true));
+
// Key kick-starter for container creation in each component
c.add(createServiceDependency().setService(IContainerAware.class)
.setCallbacks("setIContainerAware", "unsetIContainerAware")
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationAware;
import org.opendaylight.controller.configuration.IConfigurationService;
import org.opendaylight.controller.containermanager.ContainerChangeEvent;
import org.opendaylight.controller.sal.utils.IObjectReader;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
import org.opendaylight.controller.sal.utils.NodeCreator;
-import org.opendaylight.controller.sal.utils.ObjectReader;
-import org.opendaylight.controller.sal.utils.ObjectWriter;
import org.opendaylight.controller.sal.utils.ServiceHelper;
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
CommandProvider, ICacheUpdateAware<String, Object>, IContainerInternal, IContainerAuthorization,
IConfigurationAware {
private static final Logger logger = LoggerFactory.getLogger(ContainerManager.class);
- private static String ROOT = GlobalConstants.STARTUPHOME.toString();
- private static String containersFileName = ROOT + "containers.conf";
+ private static String CONTAINERS_FILE_NAME = "containers.conf";
private static final String allContainersGroup = "allContainers";
private IClusterGlobalServices clusterServices;
+ private IConfigurationService configurationService;
/*
* Collection containing the configuration objects. This is configuration
* world: container names (also the map key) are maintained as they were
}
}
+ public void setConfigurationService(IConfigurationService service) {
+ logger.trace("Got configuration service set request {}", service);
+ this.configurationService = service;
+ }
+
+ public void unsetConfigurationService(IConfigurationService service) {
+ logger.trace("Got configuration service UNset request");
+ this.configurationService = null;
+ }
+
private void allocateCaches() {
logger.debug("Container Manager allocating caches");
createDefaultAuthorizationGroups();
// Read startup configuration and create local database
- loadConfigurations();
+ loadContainerConfig();
}
public void destroy() {
return flowSpecConfig;
}
- private void loadConfigurations() {
- /*
- * Read containers, container flows and finally containers' entries from file
- * and program the database accordingly
- */
- if ((clusterServices != null) && (clusterServices.amICoordinator())) {
- loadContainerConfig();
- }
- }
-
private Status saveContainerConfig() {
return saveContainerConfigLocal();
}
public Status saveContainerConfigLocal() {
- ObjectWriter objWriter = new ObjectWriter();
+ Status status = configurationService.persistConfiguration(
+ new ArrayList<ConfigurationObject>(containerConfigs.values()), CONTAINERS_FILE_NAME);
- Status status = objWriter.write(new ConcurrentHashMap<String, ContainerConfig>(containerConfigs), containersFileName);
if (!status.isSuccess()) {
return new Status(StatusCode.INTERNALERROR, "Failed to save container configurations: "
+ status.getDescription());
}
- return new Status(StatusCode.SUCCESS);
+ return status;
}
private void removeComponentsStartUpfiles(String containerName) {
return ois.readObject();
}
- @SuppressWarnings("unchecked")
private void loadContainerConfig() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, ContainerConfig> configMap = (ConcurrentMap<String, ContainerConfig>) objReader.read(this,
- containersFileName);
-
- if (configMap == null) {
- return;
- }
-
- for (Map.Entry<String, ContainerConfig> configEntry : configMap.entrySet()) {
- addContainer(configEntry.getValue());
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, CONTAINERS_FILE_NAME)) {
+ addContainer((ContainerConfig) conf);
}
}
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sanitytest</artifactId>
+ <version>${controller.version}</version>
+ </dependency>
+ </dependencies>
<executions>
<execution>
<id>copy</id>
</plugin>
</plugins>
</build>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sanitytest</artifactId>
+ </dependency>
+ </dependencies>
</profile>
</profiles>
# The maximum number of ports handled in one discovery batch (default 512)
# of.discoveryBatchMaxPorts=512
+# OVSDB configuration
+# ovsdb plugin supports both active and passive connections. It listens on port 6640 by default for Active connections.
+ovsdb.listenPort=6640
+
+# ovsdb creates Openflow nodes/bridges. This configuration configures the bridge's Openflow version.
+# default Openflow version = 1.0, we also support 1.3.
+# ovsdb.of.version=1.3
+
# TLS configuration
# To enable TLS, set secureChannelEnabled=true and specify the location of controller Java KeyStore and TrustStore files.
# The Java KeyStore contains controller's private key and certificate. The Java TrustStore contains the trusted certificate
<appender-ref ref="opendaylight.log"/>
</logger>
+ <!-- To debug MD-SAL schema loading issues, uncomment this -->
+ <!--logger name="org.opendaylight.yangtools.yang.parser.impl.util.URLSchemaContextResolver" level="DEBUG"/>
+ <logger name="org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl" level="TRACE"/-->
+
<!-- additivity=false ensures analytics data only goes to the analytics log -->
<logger name="audit" level="INFO" additivity="false">
<appender-ref ref="audit-file"/>
org.opendaylight.controller.sal.utils,
org.opendaylight.controller.sal.core,
org.opendaylight.controller.configuration,
- org.opendaylight.controller.forwardingrulesmanager,
org.opendaylight.controller.hosttracker,
org.opendaylight.controller.hosttracker.hostAware,
org.opendaylight.controller.clustering.services,
org.opendaylight.controller.sal.packet,
org.opendaylight.controller.sal.routing,
- org.opendaylight.controller.topologymanager,
org.eclipse.osgi.framework.console,
org.osgi.framework,
org.slf4j,
- org.apache.felix.dm,
- org.apache.commons.lang3.builder
+ org.apache.felix.dm
</Import-Package>
<Export-Package>
org.opendaylight.controller.forwarding.staticrouting
<dependencies>
<dependency>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>topologymanager</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>forwardingrulesmanager</artifactId>
+ <artifactId>clustering.services</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.hosttracker.IfIptoHost;
import org.opendaylight.controller.hosttracker.IfNewHostNotify;
* instantiated in order to get an fully working implementation
* Object
*/
+ @Override
public Object[] getImplementations() {
Object[] res = { StaticRoutingImplementation.class };
return res;
* also optional per-container different behavior if needed, usually
* should not be the case though.
*/
+ @Override
public void configureInstance(Component c, Object imp, String containerName) {
if (imp.equals(StaticRoutingImplementation.class)) {
c.setInterface(new String[] {
IStaticRoutingAware.class).setCallbacks(
"setStaticRoutingAware", "unsetStaticRoutingAware")
.setRequired(false));
+
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
}
}
}
import java.net.Inet4Address;
import java.net.InetAddress;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.EnumSet;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.opendaylight.controller.clustering.services.CacheExistException;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.forwarding.staticrouting.IForwardingStaticRouting;
import org.opendaylight.controller.forwarding.staticrouting.IStaticRoutingAware;
import org.opendaylight.controller.forwarding.staticrouting.StaticRoute;
import org.opendaylight.controller.hosttracker.IfIptoHost;
import org.opendaylight.controller.hosttracker.IfNewHostNotify;
import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
-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.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.slf4j.Logger;
public class StaticRoutingImplementation implements IfNewHostNotify, IForwardingStaticRouting, IObjectReader,
IConfigurationContainerAware {
private static Logger log = LoggerFactory.getLogger(StaticRoutingImplementation.class);
- private static String ROOT = GlobalConstants.STARTUPHOME.toString();
+ private static final String STATIC_ROUTES_FILE_NAME = "staticRouting.conf";
ConcurrentMap<String, StaticRoute> staticRoutes;
ConcurrentMap<String, StaticRouteConfig> staticRouteConfigs;
private IfIptoHost hostTracker;
private Timer gatewayProbeTimer;
- private String staticRoutesFileName = null;
private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
private Set<IStaticRoutingAware> staticRoutingAware = Collections
.synchronizedSet(new HashSet<IStaticRoutingAware>());
private ExecutorService executor;
}
}
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ log.trace("Got configuration service set request {}", service);
+ this.configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ log.trace("Got configuration service UNset request");
+ this.configurationService = null;
+ }
+
@Override
public ConcurrentMap<String, StaticRouteConfig> getStaticRouteConfigs() {
return staticRouteConfigs;
return ois.readObject();
}
- @SuppressWarnings("unchecked")
- private void loadConfiguration() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, StaticRouteConfig> confList = (ConcurrentMap<String, StaticRouteConfig>) objReader.read(
- this, staticRoutesFileName);
-
- if (confList == null) {
- return;
- }
- for (StaticRouteConfig conf : confList.values()) {
- addStaticRoute(conf);
+ private void loadConfiguration() {
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, STATIC_ROUTES_FILE_NAME)) {
+ addStaticRoute((StaticRouteConfig) conf);
}
}
}
public Status saveConfigInternal() {
- Status status;
- ObjectWriter objWriter = new ObjectWriter();
-
- status = objWriter.write(new ConcurrentHashMap<String, StaticRouteConfig>(staticRouteConfigs),
- staticRoutesFileName);
+ Status status = configurationService.persistConfiguration(
+ new ArrayList<ConfigurationObject>(staticRouteConfigs.values()), STATIC_ROUTES_FILE_NAME);
if (status.isSuccess()) {
return status;
}
}
- @SuppressWarnings("deprecation")
private void allocateCaches() {
if (this.clusterContainerService == null) {
log.trace("un-initialized clusterContainerService, can't create cache");
}
}
- @SuppressWarnings({ "unchecked", "deprecation" })
+ @SuppressWarnings({ "unchecked" })
private void retrieveCaches() {
if (this.clusterContainerService == null) {
log.warn("un-initialized clusterContainerService, can't retrieve cache");
containerName = "";
}
- staticRoutesFileName = ROOT + "staticRouting_" + containerName + ".conf";
-
log.debug("forwarding.staticrouting starting on container {}", containerName);
allocateCaches();
retrieveCaches();
this.executor = Executors.newFixedThreadPool(1);
- if ((clusterContainerService != null) && (clusterContainerService.amICoordinator())) {
- loadConfiguration();
- }
+ loadConfiguration();
/*
* Slow probe to identify any gateway that might have silently appeared
org.opendaylight.controller.forwardingrulesmanager
</Export-Package>
<Import-Package>
- org.opendaylight.controller.clustering.services,
org.opendaylight.controller.configuration,
- org.opendaylight.controller.hosttracker,
- org.opendaylight.controller.hosttracker.hostAware,
org.opendaylight.controller.switchmanager,
org.opendaylight.controller.sal.action,
org.opendaylight.controller.sal.core,
</plugins>
</build>
<dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>hosttracker</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>configuration</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>clustering.services</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager</artifactId>
import java.util.ArrayList;
import java.util.List;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
/**
* PortGroupConfig class represents the User's Configuration with a Opaque
* Regular Expression String that is parsed and handled by PortGroupProvider.
*
*
*/
-public class PortGroupConfig implements Serializable {
+public class PortGroupConfig extends ConfigurationObject implements Serializable {
private static final long serialVersionUID = 1L;
private static final String prettyFields[] = { "Name", "Match Criteria" };
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
PortGroupConfig other = (PortGroupConfig) obj;
if (matchString == null) {
- if (other.matchString != null)
+ if (other.matchString != null) {
return false;
- } else if (!matchString.equals(other.matchString))
+ }
+ } else if (!matchString.equals(other.matchString)) {
return false;
+ }
if (name == null) {
- if (other.name != null)
+ if (other.name != null) {
return false;
- } else if (!name.equals(other.name))
+ }
+ } else if (!name.equals(other.name)) {
return false;
+ }
return true;
}
org.opendaylight.controller.clustering.services,
org.opendaylight.controller.configuration,
org.opendaylight.controller.containermanager,
- org.opendaylight.controller.hosttracker,
- org.opendaylight.controller.hosttracker.hostAware,
org.opendaylight.controller.switchmanager,
org.opendaylight.controller.sal.action,
org.opendaylight.controller.sal.core,
</plugins>
</build>
<dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>hosttracker</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>configuration</artifactId>
<groupId>equinoxSDK381</groupId>
<artifactId>org.apache.felix.gogo.runtime</artifactId>
</dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>connectionmanager</artifactId>
import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.connectionmanager.IConnectionManager;
import org.opendaylight.controller.containermanager.IContainerManager;
import org.opendaylight.controller.forwardingrulesmanager.IForwardingRulesManager;
.setCallbacks("setIContainer", "unsetIContainer").setRequired(true));
c.add(createServiceDependency().setService(IConnectionManager.class)
.setCallbacks("setIConnectionManager", "unsetIConnectionManager").setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
if (GlobalConstants.DEFAULT.toString().equals(containerName)) {
c.add(createServiceDependency().setService(IContainerManager.class)
.setCallbacks("setIContainerManager", "unsetIContainerManager").setRequired(true));
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.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.connectionmanager.IConnectionManager;
import org.opendaylight.controller.containermanager.IContainerManager;
import org.opendaylight.controller.forwardingrulesmanager.FlowConfig;
import org.opendaylight.controller.sal.utils.EtherTypes;
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.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.switchmanager.IInventoryListener;
private static final String PORT_REMOVED = "Port removed";
private static final String NODE_DOWN = "Node is Down";
private static final String INVALID_FLOW_ENTRY = "Invalid FlowEntry";
- private String frmFileName;
- private String portGroupFileName;
+ private static final String STATIC_FLOWS_FILE_NAME = "frm_staticflows.conf";
+ private static final String PORT_GROUP_FILE_NAME = "portgroup.conf";
private ConcurrentMap<Integer, FlowConfig> staticFlows;
private ConcurrentMap<Integer, Integer> staticFlowsOrdinal;
private ConcurrentMap<String, PortGroupConfig> portGroupConfigs;
private ConcurrentMap<PortGroupConfig, Map<Node, PortGroup>> portGroupData;
private ConcurrentMap<String, Object> TSPolicies;
private IContainerManager containerManager;
+ private IConfigurationContainerService configurationService;
private boolean inContainerMode; // being used by global instance only
protected boolean stopping;
@Override
public List<FlowConfig> getStaticFlows() {
- return getStaticFlowsOrderedList(staticFlows, staticFlowsOrdinal.get(0).intValue());
- }
-
- // TODO: need to come out with a better algorithm for maintaining the order
- // of the configuration entries
- // with actual one, index associated to deleted entries cannot be reused and
- // map grows...
- private List<FlowConfig> getStaticFlowsOrderedList(ConcurrentMap<Integer, FlowConfig> flowMap, int maxKey) {
- List<FlowConfig> orderedList = new ArrayList<FlowConfig>();
- for (int i = 0; i <= maxKey; i++) {
- FlowConfig entry = flowMap.get(i);
- if (entry != null) {
- orderedList.add(entry);
- }
- }
- return orderedList;
+ return new ArrayList<FlowConfig>(staticFlows.values());
}
@Override
return new ArrayList<Node>(set);
}
- @SuppressWarnings("unchecked")
private void loadFlowConfiguration() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<Integer, FlowConfig> confList = (ConcurrentMap<Integer, FlowConfig>) objReader.read(this,
- frmFileName);
-
- ConcurrentMap<String, PortGroupConfig> pgConfig = (ConcurrentMap<String, PortGroupConfig>) objReader.read(this,
- portGroupFileName);
-
- if (pgConfig != null) {
- for (ConcurrentMap.Entry<String, PortGroupConfig> entry : pgConfig.entrySet()) {
- addPortGroupConfig(entry.getKey(), entry.getValue().getMatchString(), true);
- }
- }
-
- if (confList == null) {
- return;
- }
-
- int maxKey = 0;
- for (Integer key : confList.keySet()) {
- if (key.intValue() > maxKey) {
- maxKey = key.intValue();
- }
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, PORT_GROUP_FILE_NAME)) {
+ addPortGroupConfig(((PortGroupConfig) conf).getName(), ((PortGroupConfig) conf).getMatchString(), true);
}
- for (FlowConfig conf : getStaticFlowsOrderedList(confList, maxKey)) {
- addStaticFlowInternal(conf, true);
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, STATIC_FLOWS_FILE_NAME)) {
+ addStaticFlowInternal((FlowConfig) conf, true);
}
}
}
private Status saveConfigInternal() {
- ObjectWriter objWriter = new ObjectWriter();
- ConcurrentMap<Integer, FlowConfig> nonDynamicFlows = new ConcurrentHashMap<Integer, FlowConfig>();
+ List<ConfigurationObject> nonDynamicFlows = new ArrayList<ConfigurationObject>();
+
for (Integer ordinal : staticFlows.keySet()) {
FlowConfig config = staticFlows.get(ordinal);
// Do not save dynamic and controller generated static flows
if (config.isDynamic() || config.isInternalFlow()) {
continue;
}
- nonDynamicFlows.put(ordinal, config);
+ nonDynamicFlows.add(config);
}
- objWriter.write(nonDynamicFlows, frmFileName);
- objWriter.write(new ConcurrentHashMap<String, PortGroupConfig>(portGroupConfigs), portGroupFileName);
- return new Status(StatusCode.SUCCESS, null);
+
+ configurationService.persistConfiguration(nonDynamicFlows, STATIC_FLOWS_FILE_NAME);
+ configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(portGroupConfigs.values()),
+ PORT_GROUP_FILE_NAME);
+
+ return new Status(StatusCode.SUCCESS);
}
@Override
}
}
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ log.trace("Got configuration service set request {}", service);
+ this.configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ log.trace("Got configuration service UNset request");
+ this.configurationService = null;
+ }
+
@Override
public PortGroupProvider getPortGroupProvider() {
return portGroupProvider;
*
*/
void init() {
- frmFileName = GlobalConstants.STARTUPHOME.toString() + "frm_staticflows_" + this.getContainerName() + ".conf";
- portGroupFileName = GlobalConstants.STARTUPHOME.toString() + "portgroup_" + this.getContainerName() + ".conf";
inContainerMode = false;
/*
* Read startup and build database if we are the coordinator
*/
- if ((clusterContainerService != null) && (clusterContainerService.amICoordinator())) {
- loadFlowConfiguration();
- }
+ loadFlowConfiguration();
}
/**
<Import-Package>
org.opendaylight.controller.sal.core,
org.opendaylight.controller.sal.utils,
- org.opendaylight.controller.topologymanager,
org.opendaylight.controller.sal.packet.address,
- org.opendaylight.controller.switchmanager,
- org.opendaylight.controller.clustering.services,
javax.xml.bind.annotation,
javax.xml.bind,
org.apache.felix.dm,
- org.apache.commons.lang3.builder,
org.osgi.service.component,
org.slf4j,
org.eclipse.osgi.framework.console,
</plugins>
</build>
<dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>topologymanager</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>switchmanager</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>clustering.services</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
</plugins>
</build>
<dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>connectionmanager</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>connectionmanager.implementation</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal.connection</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal.connection.implementation</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>topologymanager</artifactId>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>commons.logback_settings</artifactId>
- </dependency>
</dependencies>
</project>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal.implementation</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal.connection</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal.connection.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>connectionmanager</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>connectionmanager.implementation</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>containermanager</artifactId>
import org.opendaylight.yangtools.concepts.Registration\r
import org.opendaylight.yangtools.yang.binding.Notification\r
import org.slf4j.LoggerFactory\r
-import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder\r
-\r
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder\rimport com.google.common.collect.Multimaps
+
class NotificationBrokerImpl implements NotificationProviderService, AutoCloseable {\r
\r
val Multimap<Class<? extends Notification>, NotificationListener<?>> listeners;\r
var ExecutorService executor;\r
\r
new() {\r
- listeners = HashMultimap.create()\r
+ listeners = Multimaps.synchronizedSetMultimap(HashMultimap.create())\r
}\r
\r
@Deprecated\r
new(ExecutorService executor) {\r
- listeners = HashMultimap.create()\r
+ listeners = Multimaps.synchronizedSetMultimap(HashMultimap.create())\r
this.executor = executor;\r
}\r
\r
mavenBundle(CONTROLLER, "netconf-client").versionAsInProject(), //
mavenBundle(CONTROLLER, "netconf-util").versionAsInProject(), //
- mavenBundle(CONTROLLER + ".thirdparty", "ganymed", "1.0-SNAPSHOT"), //
+ mavenBundle(CONTROLLER + ".thirdparty", "ganymed").versionAsInProject(), //
mavenBundle(CONTROLLER, "netconf-mapping-api").versionAsInProject(), //
mavenBundle(CONTROLLER, "config-persister-impl").versionAsInProject(), //
import com.google.common.collect.FluentIterable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
/**
* Base abstract implementation of DataReadRouter, which performs
*/
public abstract class AbstractDataReadRouter<P extends Path<P>, D> implements DataReader<P, D> {
- Multimap<P, DataReaderRegistration<P, D>> configReaders = HashMultimap.create();
- Multimap<P, DataReaderRegistration<P, D>> operationalReaders = HashMultimap.create();
+ Multimap<P, DataReaderRegistration<P, D>> configReaders = Multimaps.synchronizedSetMultimap(HashMultimap.<P, DataReaderRegistration<P, D>>create());
+ Multimap<P, DataReaderRegistration<P, D>> operationalReaders = Multimaps.synchronizedSetMultimap(HashMultimap.<P, DataReaderRegistration<P, D>>create());
@Override
public D readConfigurationData(P path) {
import org.slf4j.LoggerFactory\r
\r
import static com.google.common.base.Preconditions.*\rimport org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent
+import com.google.common.collect.Multimaps
abstract class AbstractDataBroker<P extends Path<P>, D, DCL extends DataChangeListener<P, D>> implements DataModificationTransactionFactory<P, D>, //\r
DataReader<P, D>, //\r
@Property\r
private val AtomicLong finishedTransactionsCount = new AtomicLong\r
\r
- Multimap<P, DataChangeListenerRegistration<P, D, DCL>> listeners = HashMultimap.create();\r
- Multimap<P, DataCommitHandlerRegistrationImpl<P, D>> commitHandlers = HashMultimap.create();\r
+ Multimap<P, DataChangeListenerRegistration<P, D, DCL>> listeners = Multimaps.synchronizedSetMultimap(HashMultimap.create());\r
+ Multimap<P, DataCommitHandlerRegistrationImpl<P, D>> commitHandlers = Multimaps.synchronizedSetMultimap(HashMultimap.create());\r
\r
val ListenerRegistry<RegistrationListener<DataCommitHandlerRegistration<P,D>>> commitHandlerRegistrationListeners = new ListenerRegistry();\r
public new() {\r
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
public class NotificationRouterImpl implements NotificationRouter {
private static Logger log = LoggerFactory.getLogger(NotificationRouterImpl.class);
- private Multimap<QName, Registration<NotificationListener>> listeners = HashMultimap.create();
+ private Multimap<QName, Registration<NotificationListener>> listeners = Multimaps.synchronizedSetMultimap(HashMultimap.<QName, Registration<NotificationListener>>create());
private void sendNotification(CompositeNode notification) {
QName type = notification.getNodeType();
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.IdentityValue;
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.Predicate;
import org.opendaylight.controller.sal.restconf.impl.RestCodec;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
import org.slf4j.Logger;
private MountInstance mountPoint;
private final Logger logger = LoggerFactory.getLogger(JsonMapper.class);
- public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema, MountInstance mountPoint) throws IOException {
+ public void write(JsonWriter writer, CompositeNode data, DataNodeContainer schema, MountInstance mountPoint)
+ throws IOException {
Preconditions.checkNotNull(writer);
Preconditions.checkNotNull(data);
Preconditions.checkNotNull(schema);
this.mountPoint = mountPoint;
-
+
writer.beginObject();
if (schema instanceof ContainerSchemaNode) {
// TODO check InstanceIdentifierTypeDefinition
if (baseType instanceof IdentityrefTypeDefinition) {
if (node.getValue() instanceof QName) {
- IdentityValuesDTO valueDTO = (IdentityValuesDTO) RestCodec.from(baseType, mountPoint).serialize(node.getValue());
+ IdentityValuesDTO valueDTO = (IdentityValuesDTO) RestCodec.from(baseType, mountPoint).serialize(
+ node.getValue());
IdentityValue valueFromDTO = valueDTO.getValuesWithNamespaces().get(0);
String moduleName;
if (mountPoint != null) {
}
writer.value(moduleName + ":" + valueFromDTO.getValue());
} else {
- Object value = node.getValue();
- logger.debug("Value of " + baseType.getQName().getNamespace() + ":"
- + baseType.getQName().getLocalName() + " is not instance of " + QName.class + " but is "
- + (value != null ? value.getClass() : "null"));
- if (value == null) {
- writer.value("");
- } else {
- writer.value(String.valueOf(value));
- }
+ writeStringRepresentation(writer, node, baseType, QName.class);
+ }
+ } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
+ if (node.getValue() instanceof InstanceIdentifier) {
+ IdentityValuesDTO valueDTO = (IdentityValuesDTO) RestCodec.from(baseType, mountPoint).serialize(
+ node.getValue());
+ writeIdentityValuesDTOToJson(writer, valueDTO);
+ } else {
+ writeStringRepresentation(writer, node, baseType, InstanceIdentifier.class);
}
} else if (baseType instanceof DecimalTypeDefinition || baseType instanceof IntegerTypeDefinition
|| baseType instanceof UnsignedIntegerTypeDefinition) {
- writer.value(new NumberForJsonWriter((String) RestCodec.from(baseType, mountPoint).serialize(node.getValue())));
+ writer.value(new NumberForJsonWriter((String) RestCodec.from(baseType, mountPoint).serialize(
+ node.getValue())));
} else if (baseType instanceof BooleanTypeDefinition) {
writer.value(Boolean.parseBoolean((String) RestCodec.from(baseType, mountPoint).serialize(node.getValue())));
} else if (baseType instanceof EmptyTypeDefinition) {
}
}
+ private void writeIdentityValuesDTOToJson(JsonWriter writer, IdentityValuesDTO valueDTO) throws IOException {
+ StringBuilder result = new StringBuilder();
+ for (IdentityValue identityValue : valueDTO.getValuesWithNamespaces()) {
+ result.append("/");
+
+ writeModuleNameAndIdentifier(result, identityValue);
+ if (identityValue.getPredicates() != null) {
+ for (Predicate predicate : identityValue.getPredicates()) {
+ IdentityValue identityValuePredicate = predicate.getName();
+ result.append("[");
+ writeModuleNameAndIdentifier(result, identityValuePredicate);
+ result.append("=\"");
+ result.append(predicate.getValue());
+ result.append("\"");
+ result.append("]");
+ }
+ }
+ }
+
+ writer.value(result.toString());
+ }
+
+ private void writeModuleNameAndIdentifier(StringBuilder result, IdentityValue identityValue) {
+ String moduleName = ControllerContext.getInstance().findModuleNameByNamespace(
+ URI.create(identityValue.getNamespace()));
+ if (moduleName != null && !moduleName.isEmpty()) {
+ result.append(moduleName);
+ result.append(":");
+ }
+ result.append(identityValue.getValue());
+ }
+
+ private void writeStringRepresentation(JsonWriter writer, SimpleNode<?> node, TypeDefinition<?> baseType,
+ Class<?> requiredType) throws IOException {
+ Object value = node.getValue();
+ logger.debug("Value of " + baseType.getQName().getNamespace() + ":" + baseType.getQName().getLocalName()
+ + " is not instance of " + requiredType.getClass() + " but is " + node.getValue().getClass());
+ if (value == null) {
+ writer.value("");
+ } else {
+ writer.value(String.valueOf(value));
+ }
+ }
+
private void writeEmptyDataTypeToJson(JsonWriter writer) throws IOException {
writer.beginArray();
writer.nullValue();
import java.util.Map.Entry;
import java.util.Set;
+import org.opendaylight.controller.sal.rest.impl.RestUtil.PrefixMapingFromJson;
import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
+import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
import com.google.common.collect.Lists;
import com.google.gson.JsonElement;
private void addChildToParent(String childName, JsonElement childType, CompositeNodeWrapper parent) {
if (childType.isJsonObject()) {
- CompositeNodeWrapper child = new CompositeNodeWrapper(getNamespaceFor(childName),
- getLocalNameFor(childName));
+ CompositeNodeWrapper child = new CompositeNodeWrapper(getNamespaceFor(childName), getLocalNameFor(childName));
parent.addValue(child);
for (Entry<String, JsonElement> childOfChild : childType.getAsJsonObject().entrySet()) {
addChildToParent(childOfChild.getKey(), childOfChild.getValue(), child);
private URI getNamespaceFor(String jsonElementName) {
String[] moduleNameAndLocalName = jsonElementName.split(":");
- if (moduleNameAndLocalName.length != 2) { // it is not "moduleName:localName"
+ // it is not "moduleName:localName"
+ if (moduleNameAndLocalName.length != 2) {
return null;
}
return URI.create(moduleNameAndLocalName[0]);
private String getLocalNameFor(String jsonElementName) {
String[] moduleNameAndLocalName = jsonElementName.split(":");
- if (moduleNameAndLocalName.length != 2) { // it is not "moduleName:localName"
+ // it is not "moduleName:localName"
+ if (moduleNameAndLocalName.length != 2) {
return jsonElementName;
}
return moduleNameAndLocalName[1];
}
- /**
- * @param value
- * value of json element
- * @return if value is "moduleName:localName" then {@link IdentityValuesDTO} else
- * the same string as parameter "value"
- */
private Object resolveValueOfElement(String value) {
+ // it could be instance-identifier Built-In Type
+ if (value.startsWith("/")) {
+ IdentityValuesDTO resolvedValue = RestUtil.asInstanceIdentifier(value, new PrefixMapingFromJson());
+ if (resolvedValue != null) {
+ return resolvedValue;
+ }
+ }
+ // it could be identityref Built-In Type
URI namespace = getNamespaceFor(value);
- return namespace == null ? value : new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null);
+ if (namespace != null) {
+ return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null);
+ }
+ // it is not "prefix:value" but just "value"
+ return value;
}
}
package org.opendaylight.controller.sal.rest.impl;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.stream.events.StartElement;
+
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.IdentityValue;
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.Predicate;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
public final class RestUtil {
+
+ public static final String SQUOTE = "'";
+ public static final String DQUOTE = "\"";
+ private static final Pattern PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
public final static TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
TypeDefinition<?> superType = type;
return superType;
}
+ public static IdentityValuesDTO asInstanceIdentifier(String value, PrefixesMaping prefixMap) {
+ String valueTrimmed = value.trim();
+ if (!valueTrimmed.startsWith("/")) {
+ return null;
+ }
+ String[] xPathParts = valueTrimmed.split("/");
+ if (xPathParts.length < 2) { // must be at least "/pr:node"
+ return null;
+ }
+ IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO();
+ for (int i = 1; i < xPathParts.length; i++) {
+ String xPathPartTrimmed = xPathParts[i].trim();
+
+ String xPathPartStr = getIdAndPrefixAsStr(xPathPartTrimmed);
+ IdentityValue identityValue = toIdentity(xPathPartStr, prefixMap);
+ if (identityValue == null) {
+ return null;
+ }
+
+ List<Predicate> predicates = toPredicates(xPathPartTrimmed, prefixMap);
+ if (predicates == null) {
+ return null;
+ }
+ identityValue.setPredicates(predicates);
+
+ identityValuesDTO.add(identityValue);
+ }
+ return identityValuesDTO.getValuesWithNamespaces().isEmpty() ? null : identityValuesDTO;
+ }
+
+ private static String getIdAndPrefixAsStr(String pathPart) {
+ int predicateStartIndex = pathPart.indexOf("[");
+ return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
+ }
+
+ private static IdentityValue toIdentity(String xPathPart, PrefixesMaping prefixMap) {
+ String xPathPartTrimmed = xPathPart.trim();
+ if (xPathPartTrimmed.isEmpty()) {
+ return null;
+ }
+ String[] prefixAndIdentifier = xPathPartTrimmed.split(":");
+ // it is not "prefix:value"
+ if (prefixAndIdentifier.length != 2) {
+ return null;
+ }
+ String prefix = prefixAndIdentifier[0].trim();
+ String identifier = prefixAndIdentifier[1].trim();
+ if (prefix.isEmpty() || identifier.isEmpty()) {
+ return null;
+ }
+ String namespace = prefixMap.getNamespace(prefix);
+ return new IdentityValue(namespace, identifier, namespace.equals(prefix) ? null : prefix);
+ }
+
+ private static List<Predicate> toPredicates(String predicatesStr, PrefixesMaping prefixMap) {
+ List<Predicate> result = new ArrayList<>();
+ List<String> predicates = new ArrayList<>();
+ Matcher matcher = PREDICATE_PATTERN.matcher(predicatesStr);
+ while (matcher.find()) {
+ predicates.add(matcher.group(1).trim());
+ }
+ for (String predicate : predicates) {
+ int indexOfEqualityMark = predicate.indexOf("=");
+ if (indexOfEqualityMark != -1) {
+ String predicateValue = toPredicateValue(predicate.substring(indexOfEqualityMark + 1));
+ if (predicate.startsWith(".")) { // it is leaf-list
+ if (predicateValue == null) {
+ return null;
+ }
+ result.add(new Predicate(null, predicateValue));
+ } else {
+ IdentityValue identityValue = toIdentity(predicate.substring(0, indexOfEqualityMark),
+ prefixMap);
+ if (identityValue == null || predicateValue == null) {
+ return null;
+ }
+ result.add(new Predicate(identityValue, predicateValue));
+ }
+ }
+ }
+ return result;
+ }
+
+ private static String toPredicateValue(String predicatedValue) {
+ String predicatedValueTrimmed = predicatedValue.trim();
+ if ((predicatedValueTrimmed.startsWith(DQUOTE) || predicatedValueTrimmed.startsWith(SQUOTE))
+ && (predicatedValueTrimmed.endsWith(DQUOTE) || predicatedValueTrimmed.endsWith(SQUOTE))) {
+ return predicatedValueTrimmed.substring(1, predicatedValueTrimmed.length() - 1);
+ }
+ return null;
+ }
+
+ public interface PrefixesMaping {
+ public String getNamespace(String prefix);
+ }
+
+ public static class PrefixMapingFromXml implements PrefixesMaping {
+ StartElement startElement = null;
+
+ public PrefixMapingFromXml(StartElement startElement) {
+ this.startElement = startElement;
+ }
+
+ @Override
+ public String getNamespace(String prefix) {
+ return startElement.getNamespaceContext().getNamespaceURI(prefix);
+ }
+ }
+
+ public static class PrefixMapingFromJson implements PrefixesMaping {
+
+ @Override
+ public String getNamespace(String prefix) {
+ return prefix;
+ }
+ }
+
}
import org.opendaylight.controller.sal.core.api.Provider;
import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
import org.opendaylight.controller.sal.core.api.model.SchemaService;
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
import org.opendaylight.controller.sal.core.api.mount.MountService;
import org.opendaylight.controller.sal.restconf.impl.BrokerFacade;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import javax.xml.stream.events.XMLEvent;
import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
-import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO;
import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
import org.opendaylight.yangtools.yang.data.api.Node;
final Characters chars = innerEvent.asCharacters();
if (!chars.isWhiteSpace()) {
data = innerEvent.asCharacters().getData();
+ data = data + getAdditionalData(eventReader.nextEvent());
}
} else if (innerEvent.isEndElement()) {
if (startElement.getLocation().getCharacterOffset() == innerEvent.getLocation().getCharacterOffset()) {
return data;
}
+ private String getAdditionalData(XMLEvent event) throws XMLStreamException {
+ String data = "";
+ if (eventReader.hasNext()) {
+ final XMLEvent innerEvent = eventReader.peek();
+ if (innerEvent.isCharacters() && !innerEvent.isEndElement()) {
+ final Characters chars = innerEvent.asCharacters();
+ if (!chars.isWhiteSpace()) {
+ data = innerEvent.asCharacters().getData();
+ data = data + getAdditionalData(eventReader.nextEvent());
+ }
+ }
+ }
+ return data;
+ }
+
private String getLocalNameFor(StartElement startElement) {
return startElement.getName().getLocalPart();
}
return namespaceURI.isEmpty() ? null : URI.create(namespaceURI);
}
- /**
- * @param value
- * value of startElement
- * @param startElement
- * element containing value
- * @return if value is "prefix:value" then {@link IdentityValuesDTO} else the same
- * string as parameter "value"
- */
private Object resolveValueOfElement(String value, StartElement startElement) {
- String[] namespaceAndValue = value.split(":");
- if (namespaceAndValue.length != 2) { // it is not "prefix:value"
- return value;
+ // it could be instance-identifier Built-In Type
+ if (value.startsWith("/")) {
+ IdentityValuesDTO iiValue = RestUtil.asInstanceIdentifier(value, new RestUtil.PrefixMapingFromXml(startElement));
+ if (iiValue != null) {
+ return iiValue;
+ }
}
- String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]);
- if (namespace != null && !namespace.isEmpty()) {
- return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0]);
+ // it could be identityref Built-In Type
+ String[] namespaceAndValue = value.split(":");
+ if (namespaceAndValue.length == 2) {
+ String namespace = startElement.getNamespaceContext().getNamespaceURI(namespaceAndValue[0]);
+ if (namespace != null && !namespace.isEmpty()) {
+ return new IdentityValuesDTO(namespace, namespaceAndValue[1], namespaceAndValue[0]);
+ }
}
+ // it is not "prefix:value" but just "value"
return value;
}
Preconditions.checkState(compositeNode == null, "Cannot change the object, due to data inconsistencies.");
this.name = name;
}
+
+ @Override
+ public QName getQname() {
+ return name;
+ }
@Override
public String getLocalName() {
package org.opendaylight.controller.sal.restconf.impl
+import com.google.common.base.Preconditions
import com.google.common.collect.BiMap
import com.google.common.collect.FluentIterable
import com.google.common.collect.HashBiMap
import java.net.URI
import java.net.URLDecoder
import java.net.URLEncoder
+import java.util.ArrayList
import java.util.HashMap
import java.util.List
import java.util.Map
import java.util.concurrent.ConcurrentHashMap
-import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener
+import org.opendaylight.controller.sal.core.api.mount.MountInstance
import org.opendaylight.controller.sal.core.api.mount.MountService
import org.opendaylight.controller.sal.rest.impl.RestUtil
import org.opendaylight.controller.sal.rest.impl.RestconfProvider
import org.opendaylight.yangtools.yang.model.api.Module
import org.opendaylight.yangtools.yang.model.api.RpcDefinition
import org.opendaylight.yangtools.yang.model.api.SchemaContext
+import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener
import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
import org.slf4j.LoggerFactory
import static com.google.common.base.Preconditions.*
import static javax.ws.rs.core.Response.Status.*
-import org.opendaylight.controller.sal.core.api.mount.MountInstance
class ControllerContext implements SchemaServiceListener {
val static LOG = LoggerFactory.getLogger(ControllerContext)
@Property
var SchemaContext globalSchema;
-
+
@Property
var MountService mountService;
val modules = schema.modules.filter[m|m.name == moduleName]
return modules.filterLatestModule
}
-
+
private def filterLatestModule(Iterable<Module> modules) {
var latestModule = modules.head
for (module : modules) {
}
return latestModule
}
-
+
def findModuleByName(String moduleName) {
checkPreconditions
checkArgument(moduleName !== null && !moduleName.empty)
return globalSchema.getLatestModule(moduleName)
}
-
+
def findModuleByName(MountInstance mountPoint, String moduleName) {
checkArgument(moduleName !== null && mountPoint !== null)
val mountPointSchema = mountPoint.schemaContext;
return mountPointSchema?.getLatestModule(moduleName);
}
-
+
def findModuleByNamespace(URI namespace) {
checkPreconditions
checkArgument(namespace !== null)
val moduleSchemas = globalSchema.findModuleByNamespace(namespace)
return moduleSchemas?.filterLatestModule
}
-
+
def findModuleByNamespace(MountInstance mountPoint, URI namespace) {
checkArgument(namespace !== null && mountPoint !== null)
val mountPointSchema = mountPoint.schemaContext;
}
return moduleName
}
-
+
def findModuleNameByNamespace(MountInstance mountPoint, URI namespace) {
val module = mountPoint.findModuleByNamespace(namespace);
return module?.name
}
return namespace
}
-
+
def findNamespaceByModuleName(MountInstance mountPoint, String moduleName) {
val module = mountPoint.findModuleByName(moduleName)
return module?.namespace
if(object === null) return "";
return URLEncoder.encode(object.toString)
}
-
+
private def InstanceIdWithSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List<String> strings,
DataNodeContainer parentNode, MountInstance mountPoint) {
checkNotNull(strings)
if (strings.empty) {
return new InstanceIdWithSchemaNode(builder.toInstance, parentNode as DataSchemaNode, mountPoint)
}
-
+
val nodeName = strings.head.toNodeName
val moduleName = strings.head.toModuleName
var DataSchemaNode targetNode = null
if (mountPoint !== null) {
throw new ResponseException(BAD_REQUEST, "Restconf supports just one mount point in URI.")
}
-
+
if (mountService === null) {
- throw new ResponseException(SERVICE_UNAVAILABLE, "MountService was not found. "
+ throw new ResponseException(SERVICE_UNAVAILABLE, "MountService was not found. "
+ "Finding behind mount points does not work."
)
}
-
+
val partialPath = builder.toInstance;
val mount = mountService.getMountPoint(partialPath)
if (mount === null) {
LOG.debug("Instance identifier to missing mount point: {}", partialPath)
throw new ResponseException(BAD_REQUEST, "Mount point does not exist.")
}
-
+
val mountPointSchema = mount.schemaContext;
if (mountPointSchema === null) {
throw new ResponseException(BAD_REQUEST, "Mount point does not contain any schema with modules.")
}
-
+
if (strings.size == 1) { // any data node is not behind mount point
return new InstanceIdWithSchemaNode(InstanceIdentifier.builder().toInstance, mountPointSchema, mount)
}
-
+
val moduleNameBehindMountPoint = strings.get(1).toModuleName()
if (moduleNameBehindMountPoint === null) {
throw new ResponseException(BAD_REQUEST,
"First node after mount point in URI has to be in format \"moduleName:nodeName\"")
}
-
+
val moduleBehindMountPoint = mountPointSchema.getLatestModule(moduleNameBehindMountPoint)
if (moduleBehindMountPoint === null) {
throw new ResponseException(BAD_REQUEST,
"URI has bad format. \"" + moduleName + "\" module does not exist in mount point.")
}
-
+
return collectPathArguments(InstanceIdentifier.builder(), strings.subList(1, strings.size),
moduleBehindMountPoint, mount);
}
-
+
var Module module = null;
if (mountPoint === null) {
module = globalSchema.getLatestModule(moduleName)
"URI has bad format. \"" + moduleName + "\" module does not exist in mount point.")
}
}
- targetNode = parentNode.findInstanceDataChild(nodeName, module.namespace)
+ targetNode = parentNode.findInstanceDataChildByNameAndNamespace(nodeName, module.namespace)
if (targetNode === null) {
- throw new ResponseException(BAD_REQUEST, "URI has bad format. Possible reasons:\n" +
- "1. \"" + strings.head + "\" was not found in parent data node.\n" +
+ throw new ResponseException(BAD_REQUEST, "URI has bad format. Possible reasons:\n" +
+ "1. \"" + strings.head + "\" was not found in parent data node.\n" +
"2. \"" + strings.head + "\" is behind mount point. Then it should be in format \"/" + MOUNT + "/" + strings.head + "\".")
}
} else { // string without module name
- targetNode = parentNode.findInstanceDataChild(nodeName, null)
+ val potentialSchemaNodes = parentNode.findInstanceDataChildrenByName(nodeName)
+ if (potentialSchemaNodes.size > 1) {
+ val StringBuilder namespacesOfPotentialModules = new StringBuilder;
+ for (potentialNodeSchema : potentialSchemaNodes) {
+ namespacesOfPotentialModules.append(" ").append(potentialNodeSchema.QName.namespace.toString).append("\n")
+ }
+ throw new ResponseException(BAD_REQUEST, "URI has bad format. Node \"" + nodeName + "\" is added as augment from more than one module. "
+ + "Therefore the node must have module name and it has to be in format \"moduleName:nodeName\"."
+ + "\nThe node is added as augment from modules with namespaces:\n" + namespacesOfPotentialModules)
+ }
+ targetNode = potentialSchemaNodes.head
if (targetNode === null) {
throw new ResponseException(BAD_REQUEST, "URI has bad format. \"" + nodeName + "\" was not found in parent data node.\n")
}
}
-
+
+ if (!(targetNode instanceof ListSchemaNode) && !(targetNode instanceof ContainerSchemaNode)) {
+ throw new ResponseException(BAD_REQUEST,"URI has bad format. Node \"" + strings.head + "\" must be Container or List yang type.")
+ }
// Number of consumed elements
var consumed = 1;
if (targetNode instanceof ListSchemaNode) {
// key value cannot be NULL
if (uriKeyValue.equals(NULL_VALUE)) {
- throw new ResponseException(BAD_REQUEST, "URI has bad format. List \"" + listNode.QName.localName
+ throw new ResponseException(BAD_REQUEST, "URI has bad format. List \"" + listNode.QName.localName
+ "\" cannot contain \"null\" value as a key."
)
}
return new InstanceIdWithSchemaNode(builder.toInstance, targetNode, mountPoint)
}
- def DataSchemaNode findInstanceDataChild(DataNodeContainer container, String name, URI moduleNamespace) {
- var DataSchemaNode potentialNode = null
- if (moduleNamespace === null) {
- potentialNode = container.getDataChildByName(name);
- } else {
- potentialNode = container.childNodes.filter[n|n.QName.localName == name && n.QName.namespace == moduleNamespace].head
- }
-
- if (potentialNode.instantiatedDataSchema) {
- return potentialNode;
+ def DataSchemaNode findInstanceDataChildByNameAndNamespace(DataNodeContainer container,
+ String name, URI namespace) {
+ Preconditions.checkNotNull(namespace)
+ val potentialSchemaNodes = container.findInstanceDataChildrenByName(name)
+ return potentialSchemaNodes.filter[n|n.QName.namespace == namespace].head
+ }
+
+ def List<DataSchemaNode> findInstanceDataChildrenByName(DataNodeContainer container, String name) {
+ Preconditions.checkNotNull(container)
+ Preconditions.checkNotNull(name)
+ val instantiatedDataNodeContainers = new ArrayList
+ instantiatedDataNodeContainers.collectInstanceDataNodeContainers(container, name)
+ return instantiatedDataNodeContainers
+ }
+
+ private def void collectInstanceDataNodeContainers(List<DataSchemaNode> potentialSchemaNodes, DataNodeContainer container,
+ String name) {
+ val nodes = container.childNodes.filter[n|n.QName.localName == name]
+ for (potentialNode : nodes) {
+ if (potentialNode.isInstantiatedDataSchema) {
+ potentialSchemaNodes.add(potentialNode)
+ }
}
val allCases = container.childNodes.filter(ChoiceNode).map[cases].flatten
for (caze : allCases) {
- potentialNode = caze.findInstanceDataChild(name, moduleNamespace);
- if (potentialNode !== null) {
- return potentialNode;
- }
+ collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name)
}
- return null;
}
-
- static def boolean isInstantiatedDataSchema(DataSchemaNode node) {
+
+ def boolean isInstantiatedDataSchema(DataSchemaNode node) {
switch node {
LeafSchemaNode: return true
LeafListSchemaNode: return true
default: return false
}
}
-
+
private def void addKeyValue(HashMap<QName, Object> map, DataSchemaNode node, String uriValue) {
checkNotNull(uriValue);
checkArgument(node instanceof LeafSchemaNode);
val urlDecoded = URLDecoder.decode(uriValue);
val typedef = (node as LeafSchemaNode).type;
-
+
var decoded = TypeDefinitionAwareCodec.from(typedef)?.deserialize(urlDecoded)
if(decoded === null) {
var baseType = RestUtil.resolveBaseTypeFrom(typedef)
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.ModifyAction;
-import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import com.google.common.base.Preconditions;
this.name = name;
}
+ @Override
+ public QName getQname() {
+ return name;
+ }
+
@Override
public String getLocalName() {
if (unwrapped != null) {
public IdentityValuesDTO(String namespace, String value, String prefix) {
elementData.add(new IdentityValue(namespace, value, prefix));
}
+
+ public IdentityValuesDTO() {
+
+ }
public void add(String namespace, String value, String prefix) {
elementData.add(new IdentityValue(namespace, value, prefix));
}
+
+ public void add(IdentityValue identityValue) {
+ elementData.add(identityValue);
+ }
+
public List<IdentityValue> getValuesWithNamespaces() {
return Collections.unmodifiableList(elementData);
}
+
+ @Override
+ public String toString() {
+ return elementData.toString();
+ }
public static final class IdentityValue {
- private String namespace;
- private String value;
- private String prefix;
+ private final String namespace;
+ private final String value;
+ private final String prefix;
+ private List<Predicate> predicates;
public IdentityValue(String namespace, String value, String prefix) {
this.namespace = namespace;
return namespace;
}
- public void setNamespace(String namespace) {
- this.namespace = namespace;
- }
-
public String getValue() {
return value;
}
- public void setValue(String value) {
- this.value = value;
- }
-
public String getPrefix() {
return prefix;
}
- public void setPrefix(String prefix) {
- this.prefix = prefix;
+ public List<Predicate> getPredicates() {
+ if (predicates == null) {
+ return Collections.emptyList();
+ }
+ return Collections.unmodifiableList(predicates);
}
+ public void setPredicates(List<Predicate> predicates) {
+ this.predicates = predicates;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if (namespace != null) {
+ sb.append(namespace);
+ }
+ if (prefix != null) {
+ sb.append("(").append(prefix).append(")");
+ }
+ if (value != null) {
+ sb.append(" - ").append(value);
+ }
+ if (predicates != null && !predicates.isEmpty()) {
+ for (Predicate predicate : predicates) {
+ sb.append("[");
+ predicate.toString();
+ sb.append("]");
+ }
+ }
+ return sb.toString();
+ }
+
+ }
+
+ public static final class Predicate {
+
+ private final IdentityValue name;
+ private final String value;
+
+ public Predicate(IdentityValue name, String value) {
+ super();
+ this.name = name;
+ this.value = value;
+ }
+
+ public IdentityValue getName() {
+ return name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if (name != null) {
+ sb.append(name.toString());
+ }
+ if (value != null) {
+ sb.append("=").append(value);
+ }
+ return sb.toString();
+ }
+
+ public boolean isLeafList() {
+ return name == null ? true : false;
+ }
+
}
}
void setQname(QName name);
+ QName getQname();
+
T unwrap();
boolean isChangeAllowed();
package org.opendaylight.controller.sal.restconf.impl;
import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import org.opendaylight.controller.sal.core.api.mount.MountInstance;
import org.opendaylight.controller.sal.rest.impl.RestUtil;
import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.IdentityValue;
+import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.Predicate;
import org.opendaylight.yangtools.concepts.Codec;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.codec.IdentityrefCodec;
+import org.opendaylight.yangtools.yang.data.api.codec.InstanceIdentifierCodec;
import org.opendaylight.yangtools.yang.data.api.codec.LeafrefCodec;
import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RestCodec {
+
+ private static final Logger logger = LoggerFactory.getLogger(RestCodec.class);
private RestCodec() {
}
private final Logger logger = LoggerFactory.getLogger(RestCodec.class);
public static final Codec LEAFREF_DEFAULT_CODEC = new LeafrefCodecImpl();
+ private final Codec instanceIdentifier;
private final Codec identityrefCodec;
private final TypeDefinition<?> type;
} else {
identityrefCodec = null;
}
+ if (type instanceof InstanceIdentifierTypeDefinition) {
+ instanceIdentifier = new InstanceIdentifierCodecImpl(mountPoint);
+ } else {
+ instanceIdentifier = null;
+ }
}
@SuppressWarnings("unchecked")
public Object deserialize(Object input) {
try {
if (type instanceof IdentityrefTypeDefinition) {
- return identityrefCodec.deserialize(input);
+ if (input instanceof IdentityValuesDTO) {
+ return identityrefCodec.deserialize(input);
+ }
+ logger.info(
+ "Value is not instance of IdentityrefTypeDefinition but is {}. Therefore NULL is used as translation of - {}",
+ input == null ? "null" : input.getClass(), String.valueOf(input));
+ return null;
} else if (type instanceof LeafrefTypeDefinition) {
return LEAFREF_DEFAULT_CODEC.deserialize(input);
+ } else if (type instanceof InstanceIdentifierTypeDefinition) {
+ if (input instanceof IdentityValuesDTO) {
+ return instanceIdentifier.deserialize(input);
+ }
+ logger.info(
+ "Value is not instance of InstanceIdentifierTypeDefinition but is {}. Therefore NULL is used as translation of - {}",
+ input == null ? "null" : input.getClass(), String.valueOf(input));
+ return null;
} else {
TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> typeAwarecodec = TypeDefinitionAwareCodec
.from(type);
logger.error(
"ClassCastException was thrown when codec is invoked with parameter " + String.valueOf(input),
e);
- return input;
+ return null;
}
}
return identityrefCodec.serialize(input);
} else if (type instanceof LeafrefTypeDefinition) {
return LEAFREF_DEFAULT_CODEC.serialize(input);
+ } else if (type instanceof InstanceIdentifierTypeDefinition) {
+ return instanceIdentifier.serialize(input);
} else {
TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> typeAwarecodec = TypeDefinitionAwareCodec
.from(type);
public static class IdentityrefCodecImpl implements IdentityrefCodec<IdentityValuesDTO> {
+ private final Logger logger = LoggerFactory.getLogger(IdentityrefCodecImpl.class);
+
private final MountInstance mountPoint;
-
+
public IdentityrefCodecImpl(MountInstance mountPoint) {
this.mountPoint = mountPoint;
}
-
+
@Override
public IdentityValuesDTO serialize(QName data) {
return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix());
@Override
public QName deserialize(IdentityValuesDTO data) {
IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0);
- String namespace = valueWithNamespace.getNamespace();
- URI validNamespace;
- if (mountPoint != null) {
- validNamespace = ControllerContext.getInstance().findNamespaceByModuleName(mountPoint, namespace);
- } else {
- validNamespace = ControllerContext.getInstance().findNamespaceByModuleName(namespace);
+ Module module = getModuleByNamespace(valueWithNamespace.getNamespace(), mountPoint);
+ if (module == null) {
+ logger.info("Module was not found for namespace {}", valueWithNamespace.getNamespace());
+ logger.info("Idenetityref will be translated as NULL for data - {}", String.valueOf(valueWithNamespace));
+ return null;
}
- if (validNamespace == null) {
- validNamespace = URI.create(namespace);
- }
- return QName.create(validNamespace, null, valueWithNamespace.getValue());
+
+ return QName.create(module.getNamespace(), module.getRevision(), valueWithNamespace.getValue());
}
-
+
}
public static class LeafrefCodecImpl implements LeafrefCodec<String> {
}
+ public static class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec<IdentityValuesDTO> {
+ private final Logger logger = LoggerFactory.getLogger(InstanceIdentifierCodecImpl.class);
+ private final MountInstance mountPoint;
+
+ public InstanceIdentifierCodecImpl(MountInstance mountPoint) {
+ this.mountPoint = mountPoint;
+ }
+
+ @Override
+ public IdentityValuesDTO serialize(InstanceIdentifier data) {
+ List<PathArgument> pathArguments = data.getPath();
+ IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO();
+ for (PathArgument pathArgument : pathArguments) {
+ IdentityValue identityValue = qNameToIdentityValue(pathArgument.getNodeType());
+ if (pathArgument instanceof NodeIdentifierWithPredicates && identityValue != null) {
+ List<Predicate> predicates = keyValuesToPredicateList(((NodeIdentifierWithPredicates) pathArgument)
+ .getKeyValues());
+ identityValue.setPredicates(predicates);
+ }
+ identityValuesDTO.add(identityValue);
+ }
+ return identityValuesDTO;
+ }
+
+ @Override
+ public InstanceIdentifier deserialize(IdentityValuesDTO data) {
+ List<PathArgument> result = new ArrayList<PathArgument>();
+ IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0);
+ Module module = getModuleByNamespace(valueWithNamespace.getNamespace(), mountPoint);
+ if (module == null) {
+ logger.info("Module by namespace '{}' of first node in instance-identiefier was not found.", valueWithNamespace.getNamespace());
+ logger.info("Instance-identifier will be translated as NULL for data - {}", String.valueOf(valueWithNamespace.getValue()));
+ return null;
+ }
+
+ DataNodeContainer parentContainer = module;
+ List<IdentityValue> identities = data.getValuesWithNamespaces();
+ for (int i = 0; i < identities.size(); i++) {
+ IdentityValue identityValue = identities.get(i);
+ URI validNamespace = resolveValidNamespace(identityValue.getNamespace(), mountPoint);
+ DataSchemaNode node = ControllerContext.getInstance().findInstanceDataChildByNameAndNamespace(
+ parentContainer, identityValue.getValue(), validNamespace);
+ if (node == null) {
+ logger.info("'{}' node was not found in {}", identityValue, parentContainer.getChildNodes());
+ logger.info("Instance-identifier will be translated as NULL for data - {}", String.valueOf(identityValue.getValue()));
+ return null;
+ }
+ QName qName = node.getQName();
+ PathArgument pathArgument = null;
+ if (identityValue.getPredicates().isEmpty()) {
+ pathArgument = new NodeIdentifier(qName);
+ } else {
+ if (node instanceof LeafListSchemaNode) { // predicate is value of leaf-list entry
+ Predicate leafListPredicate = identityValue.getPredicates().get(0);
+ if (!leafListPredicate.isLeafList()) {
+ logger.info("Predicate's data is not type of leaf-list. It should be in format \".='value'\"");
+ logger.info("Instance-identifier will be translated as NULL for data - {}", String.valueOf(identityValue.getValue()));
+ return null;
+ }
+ pathArgument = new NodeWithValue(qName, leafListPredicate.getValue());
+ } else if (node instanceof ListSchemaNode) { // predicates are keys of list
+ DataNodeContainer listNode = (DataNodeContainer) node;
+ Map<QName, Object> predicatesMap = new HashMap<>();
+ for (Predicate predicate : identityValue.getPredicates()) {
+ validNamespace = resolveValidNamespace(predicate.getName().getNamespace(), mountPoint);
+ DataSchemaNode listKey = ControllerContext.getInstance().findInstanceDataChildByNameAndNamespace(
+ listNode, predicate.getName().getValue(), validNamespace);
+ predicatesMap.put(listKey.getQName(), predicate.getValue());
+ }
+ pathArgument = new NodeIdentifierWithPredicates(qName, predicatesMap);
+ } else {
+ logger.info("Node {} is not List or Leaf-list.", node);
+ logger.info("Instance-identifier will be translated as NULL for data - {}", String.valueOf(identityValue.getValue()));
+ return null;
+ }
+ }
+ result.add(pathArgument);
+ if (i < identities.size() - 1) { // last element in instance-identifier can be other than DataNodeContainer
+ if (node instanceof DataNodeContainer) {
+ parentContainer = (DataNodeContainer) node;
+ } else {
+ logger.info("Node {} isn't instance of DataNodeContainer", node);
+ logger.info("Instance-identifier will be translated as NULL for data - {}", String.valueOf(identityValue.getValue()));
+ return null;
+ }
+ }
+ }
+
+ return result.isEmpty() ? null : new InstanceIdentifier(result);
+ }
+
+ private List<Predicate> keyValuesToPredicateList(Map<QName, Object> keyValues) {
+ List<Predicate> result = new ArrayList<>();
+ for (QName qName : keyValues.keySet()) {
+ Object value = keyValues.get(qName);
+ result.add(new Predicate(qNameToIdentityValue(qName), String.valueOf(value)));
+ }
+ return result;
+ }
+
+ private IdentityValue qNameToIdentityValue(QName qName) {
+ if (qName != null) {
+ return new IdentityValue(qName.getNamespace().toString(), qName.getLocalName(), qName.getPrefix());
+ }
+ return null;
+ }
+ }
+
+ private static Module getModuleByNamespace(String namespace, MountInstance mountPoint) {
+ URI validNamespace = resolveValidNamespace(namespace, mountPoint);
+
+ Module module = null;
+ if (mountPoint != null) {
+ module = ControllerContext.getInstance().findModuleByNamespace(mountPoint, validNamespace);
+ } else {
+ module = ControllerContext.getInstance().findModuleByNamespace(validNamespace);
+ }
+ if (module == null) {
+ logger.info("Module for namespace " + validNamespace + " wasn't found.");
+ return null;
+ }
+ return module;
+ }
+
+ private static URI resolveValidNamespace(String namespace, MountInstance mountPoint) {
+ URI validNamespace;
+ if (mountPoint != null) {
+ validNamespace = ControllerContext.getInstance().findNamespaceByModuleName(mountPoint, namespace);
+ } else {
+ validNamespace = ControllerContext.getInstance().findNamespaceByModuleName(namespace);
+ }
+ if (validNamespace == null) {
+ validNamespace = URI.create(namespace);
+ }
+
+ return validNamespace;
+ }
+
}
import java.util.ArrayList
import java.util.HashMap
import java.util.List
-import java.util.Set
import javax.ws.rs.core.Response
import org.opendaylight.controller.md.sal.common.api.TransactionStatus
import org.opendaylight.controller.sal.core.api.mount.MountInstance
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdentifierBuilder
import org.opendaylight.yangtools.yang.data.api.Node
import org.opendaylight.yangtools.yang.data.impl.NodeFactory
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
import org.opendaylight.yangtools.yang.model.api.Module
import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
import org.opendaylight.yangtools.yang.model.api.TypeDefinition
import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition
import static javax.ws.rs.core.Response.Status.*
-import org.opendaylight.yangtools.yang.model.api.SchemaContext
class RestconfImpl implements RestconfService {
}
override readAllData() {
-// return broker.readOperationalData("".toInstanceIdentifier.getInstanceIdentifier);
+
+ // return broker.readOperationalData("".toInstanceIdentifier.getInstanceIdentifier);
throw new UnsupportedOperationException("Reading all data is currently not supported.")
}
override invokeRpc(String identifier, CompositeNode payload) {
return callRpc(identifier.rpcDefinition, payload)
}
-
+
override invokeRpc(String identifier) {
return callRpc(identifier.rpcDefinition, null)
}
-
+
private def StructuredData callRpc(RpcDefinition rpc, CompositeNode payload) {
if (rpc === null) {
throw new ResponseException(NOT_FOUND, "RPC does not exist.");
if (payload.representsMountPointRootData) { // payload represents mount point data and URI represents path to the mount point
if (identifier.endsWithMountPoint) {
throw new ResponseException(BAD_REQUEST,
- "URI has bad format. URI should be without \"" + ControllerContext.MOUNT + "\" for POST operation.");
+ "URI has bad format. URI should be without \"" + ControllerContext.MOUNT + "\" for POST operation.");
}
val completIdentifier = identifier.addMountPointIdentifier
iiWithData = completIdentifier.toInstanceIdentifier
} else {
val uncompleteInstIdWithData = identifier.toInstanceIdentifier
val parentSchema = uncompleteInstIdWithData.schemaNode as DataNodeContainer
- val namespace = uncompleteInstIdWithData.mountPoint.findModule(payload)?.namespace
- val schemaNode = parentSchema.findInstanceDataChild(payload.name, namespace)
+ val module = uncompleteInstIdWithData.mountPoint.findModule(payload)
+ if (module === null) {
+ throw new ResponseException(BAD_REQUEST, "Module was not found for \"" + payload.namespace + "\"")
+ }
+ val schemaNode = parentSchema.findInstanceDataChildByNameAndNamespace(payload.name, module.namespace)
value = normalizeNode(payload, schemaNode, uncompleteInstIdWithData.mountPoint)
iiWithData = uncompleteInstIdWithData.addLastIdentifierFromData(value, schemaNode)
}
default: Response.status(INTERNAL_SERVER_ERROR).build
}
}
-
+
override createConfigurationData(CompositeNode payload) {
if (payload.namespace === null) {
throw new ResponseException(BAD_REQUEST,
throw new ResponseException(BAD_REQUEST,
"Data has bad format. Root element node has incorrect namespace (XML format) or module name(JSON format)");
}
- val schemaNode = module.findInstanceDataChild(payload.name, module.namespace)
+ val schemaNode = module.findInstanceDataChildByNameAndNamespace(payload.name, module.namespace)
val value = normalizeNode(payload, schemaNode, null)
val iiWithData = addLastIdentifierFromData(null, value, schemaNode)
var RpcResult<TransactionStatus> status = null
default: Response.status(INTERNAL_SERVER_ERROR).build
}
}
-
+
override deleteConfigurationData(String identifier) {
val iiWithData = identifier.toInstanceIdentifier
var RpcResult<TransactionStatus> status = null
default: Response.status(INTERNAL_SERVER_ERROR).build
}
}
-
+
private def dispatch URI namespace(CompositeNode data) {
return data.nodeType.namespace
}
-
+
private def dispatch URI namespace(CompositeNodeWrapper data) {
return data.namespace
}
-
+
private def dispatch String localName(CompositeNode data) {
return data.nodeType.localName
}
-
+
private def dispatch String localName(CompositeNodeWrapper data) {
return data.localName
}
}
return module
}
-
+
private def dispatch getName(CompositeNode data) {
return data.nodeType.localName
}
-
+
private def dispatch getName(CompositeNodeWrapper data) {
return data.localName
}
-
+
private def InstanceIdWithSchemaNode addLastIdentifierFromData(InstanceIdWithSchemaNode identifierWithSchemaNode,
CompositeNode data, DataSchemaNode schemaOfData) {
val iiOriginal = identifierWithSchemaNode?.instanceIdentifier
}
return keyValues
}
-
+
private def endsWithMountPoint(String identifier) {
return (identifier.endsWith(ControllerContext.MOUNT) || identifier.endsWith(ControllerContext.MOUNT + "/"))
}
-
+
private def representsMountPointRootData(CompositeNode data) {
return ((data.namespace == SchemaContext.NAME.namespace || data.namespace == MOUNT_POINT_MODULE_NAME) &&
data.localName == SchemaContext.NAME.localName)
}
-
+
private def addMountPointIdentifier(String identifier) {
if (identifier.endsWith("/")) {
return identifier + ControllerContext.MOUNT
}
return identifier + "/" + ControllerContext.MOUNT
}
-
+
private def CompositeNode normalizeNode(CompositeNode node, DataSchemaNode schema, MountInstance mountPoint) {
if (schema === null) {
- throw new ResponseException(INTERNAL_SERVER_ERROR, "Data schema node was not found for " + node?.nodeType?.localName)
+ throw new ResponseException(INTERNAL_SERVER_ERROR,
+ "Data schema node was not found for " + node?.nodeType?.localName)
}
if (!(schema instanceof DataNodeContainer)) {
throw new ResponseException(BAD_REQUEST, "Root element has to be container or list yang datatype.");
}
return node
}
-
+
private def void normalizeNode(NodeWrapper<?> nodeBuilder, DataSchemaNode schema, QName previousAugment,
MountInstance mountPoint) {
if (schema === null) {
throw new ResponseException(BAD_REQUEST,
"Data has bad format.\n\"" + nodeBuilder.localName + "\" does not exist in yang schema.");
}
- var validQName = schema.QName
- var currentAugment = previousAugment;
- if (schema.augmenting) {
- currentAugment = schema.QName
- } else if (previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
- validQName = QName.create(currentAugment, schema.QName.localName);
- }
- var String moduleName = null;
- if (mountPoint === null) {
- moduleName = controllerContext.findModuleNameByNamespace(validQName.namespace);
- } else {
- moduleName = controllerContext.findModuleNameByNamespace(mountPoint, validQName.namespace)
- }
- if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace ||
- nodeBuilder.namespace.toString == moduleName || nodeBuilder.namespace == MOUNT_POINT_MODULE_NAME) {
- nodeBuilder.qname = validQName
+
+ var QName currentAugment;
+ if (nodeBuilder.qname !== null) {
+ currentAugment = previousAugment
} else {
- throw new ResponseException(BAD_REQUEST,
- "Data has bad format.\nIf data is in XML format then namespace for \"" + nodeBuilder.localName +
- "\" should be \"" + schema.QName.namespace + "\".\nIf data is in Json format then module name for \"" +
- nodeBuilder.localName + "\" should be \"" + moduleName + "\".");
+ currentAugment = normalizeNodeName(nodeBuilder, schema, previousAugment, mountPoint)
+ if (nodeBuilder.qname === null) {
+ throw new ResponseException(BAD_REQUEST,
+ "Data has bad format.\nIf data is in XML format then namespace for \"" + nodeBuilder.localName +
+ "\" should be \"" + schema.QName.namespace + "\".\n" +
+ "If data is in JSON format then module name for \"" + nodeBuilder.localName +
+ "\" should be corresponding to namespace \"" + schema.QName.namespace + "\".");
+ }
}
if (nodeBuilder instanceof CompositeNodeWrapper) {
val List<NodeWrapper<?>> children = (nodeBuilder as CompositeNodeWrapper).getValues
for (child : children) {
- normalizeNode(child,
- findFirstSchemaByLocalName(child.localName, (schema as DataNodeContainer).childNodes),
- currentAugment, mountPoint)
+ val potentialSchemaNodes = (schema as DataNodeContainer).findInstanceDataChildrenByName(child.localName)
+ if (potentialSchemaNodes.size > 1 && child.namespace === null) {
+ val StringBuilder namespacesOfPotentialModules = new StringBuilder;
+ for (potentialSchemaNode : potentialSchemaNodes) {
+ namespacesOfPotentialModules.append(" ").append(potentialSchemaNode.QName.namespace.toString).append("\n")
+ }
+ throw new ResponseException(BAD_REQUEST,
+ "Node \"" + child.localName + "\" is added as augment from more than one module. "
+ + "Therefore node must have namespace (XML format) or module name (JSON format)."
+ + "\nThe node is added as augment from modules with namespaces:\n" + namespacesOfPotentialModules)
+ }
+ var rightNodeSchemaFound = false
+ for (potentialSchemaNode : potentialSchemaNodes) {
+ if (!rightNodeSchemaFound) {
+ val potentialCurrentAugment = normalizeNodeName(child, potentialSchemaNode, currentAugment,
+ mountPoint)
+ if (child.qname !== null) {
+ normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint)
+ rightNodeSchemaFound = true
+ }
+ }
+ }
+ if (!rightNodeSchemaFound) {
+ throw new ResponseException(BAD_REQUEST,
+ "Schema node \"" + child.localName + "\" was not found in module.")
+ }
}
- if(schema instanceof ListSchemaNode) {
+ if (schema instanceof ListSchemaNode) {
val listKeys = (schema as ListSchemaNode).keyDefinition
for (listKey : listKeys) {
var foundKey = false
}
if (!foundKey) {
throw new ResponseException(BAD_REQUEST,
- "Missing key in URI \"" + listKey.localName + "\" of list \"" + schema.QName.localName + "\"")
+ "Missing key in URI \"" + listKey.localName + "\" of list \"" + schema.QName.localName +
+ "\"")
}
}
}
val simpleNode = (nodeBuilder as SimpleNodeWrapper)
val value = simpleNode.value
var inputValue = value;
-
+
if (schema.typeDefinition instanceof IdentityrefTypeDefinition) {
if (value instanceof String) {
- inputValue = new IdentityValuesDTO(validQName.namespace.toString, value as String, null)
- } // else value is instance of ValuesDTO
+ inputValue = new IdentityValuesDTO(nodeBuilder.namespace.toString, value as String, null)
+ } // else value is already instance of IdentityValuesDTO
}
val outputValue = RestCodec.from(schema.typeDefinition, mountPoint)?.deserialize(inputValue);
}
baseType
}
-
- private def DataSchemaNode findFirstSchemaByLocalName(String localName, Set<DataSchemaNode> schemas) {
- for (schema : schemas) {
- if (schema instanceof ChoiceNode) {
- for (caze : (schema as ChoiceNode).cases) {
- val result = findFirstSchemaByLocalName(localName, caze.childNodes)
- if (result !== null) {
- return result
- }
- }
- } else {
- val result = schemas.findFirst[n|n.QName.localName.equals(localName)]
- if (result !== null) {
- return result;
-
- }
- }
+
+ private def QName normalizeNodeName(NodeWrapper<?> nodeBuilder, DataSchemaNode schema, QName previousAugment,
+ MountInstance mountPoint) {
+ var validQName = schema.QName
+ var currentAugment = previousAugment;
+ if (schema.augmenting) {
+ currentAugment = schema.QName
+ } else if (previousAugment !== null && schema.QName.namespace !== previousAugment.namespace) {
+ validQName = QName.create(currentAugment, schema.QName.localName);
+ }
+ var String moduleName = null;
+ if (mountPoint === null) {
+ moduleName = controllerContext.findModuleNameByNamespace(validQName.namespace);
+ } else {
+ moduleName = controllerContext.findModuleNameByNamespace(mountPoint, validQName.namespace)
+ }
+ if (nodeBuilder.namespace === null || nodeBuilder.namespace == validQName.namespace ||
+ nodeBuilder.namespace.toString == moduleName || nodeBuilder.namespace == MOUNT_POINT_MODULE_NAME) {
+ nodeBuilder.qname = validQName
}
- return null
+ return currentAugment
}
}
this.name = name;
}
+ @Override
+ public QName getQname() {
+ return name;
+ }
+
@Override
public String getLocalName() {
if (simpleNode != null) {
--- /dev/null
+package org.opendaylight.controller.sal.restconf.iml.varioustests;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
+import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.w3c.dom.Document;
+
+
+public class VariousTest {
+
+ @Ignore
+ @Test
+ public void test() {
+ String[] split = "/something:dfsa/s:sda".split("/");
+ System.out.println(split.length);
+ for (String str : split) {
+ System.out.println(">"+str+"<");
+ }
+
+ }
+
+ @Test
+ public void loadXml() {
+ TestUtils.readInputToCnSn("/varioustest/xmldata.xml", XmlToCompositeNodeProvider.INSTANCE);
+// TestUtils.normalizeCompositeNode(compositeNode, modules, schemaNodePath)
+ }
+
+ @Test
+ public void buildXml() {
+// Document doc;
+// doc.createElementNS(namespaceURI, qualifiedName)
+ }
+
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl.cnsn.to.xml.test;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import javax.ws.rs.WebApplicationException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
+import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
+import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+
+/**
+ *
+ * CnSn = Composite node and Simple node data structure Class contains test of
+ * serializing simple nodes data values according data types from YANG schema to
+ * XML file
+ *
+ */
+public class CnSnInstanceIdentifierToXmlTest extends YangAndXmlAndDataSchemaLoader {
+
+ @BeforeClass
+ public static void initialization() throws URISyntaxException {
+ dataLoad("/instanceidentifier/yang", 3, "instance-identifier-module", "cont");
+ }
+
+ @Test
+ public void snAsYangInstanceIdentifier() throws WebApplicationException, IOException, URISyntaxException {
+ CompositeNode cnSnData = prepareCnStructForYangData( );
+ String xmlOutput = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSnData, modules, dataSchemaNode,
+ StructuredDataToXmlProvider.INSTANCE);
+ assertNotNull(xmlOutput);
+ }
+
+ private CompositeNode prepareCnStructForYangData() throws URISyntaxException {
+ CompositeNodeWrapper cont = new CompositeNodeWrapper(new URI("instance:identifier:module"), "cont");
+ CompositeNodeWrapper cont1 = new CompositeNodeWrapper(new URI("augment:module"), "cont1");
+ cont.addValue(cont1);
+ SimpleNodeWrapper lf11 = new SimpleNodeWrapper(new URI("augment:augment:module"), "lf11", "/cont/cont1/lf12");
+ SimpleNodeWrapper lf12 = new SimpleNodeWrapper(new URI("augment:augment:module"), "lf12", "lf12 value");
+ cont1.addValue(lf11);
+ cont1.addValue(lf12);
+ cont.unwrap();
+ return cont;
+ }
+
+}
import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
import org.opendaylight.controller.sal.restconf.impl.test.YangAndXmlAndDataSchemaLoader;
-import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.MutableSimpleNode;
import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
serializeToXml(prepareLeafrefData(), "<lfBoolean>true</lfBoolean>", "<lfLfref>true</lfLfref>");
}
+
@Test
public void snAsYangStringToXmlTest() {
serializeToXml(
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.WebApplicationException;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToXmlProvider;
+import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
+import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+
+public class CnSnToXmlAndJsonInstanceIdentifierTest extends YangAndXmlAndDataSchemaLoader {
+
+ @BeforeClass
+ public static void initialize() {
+ dataLoad("/instanceidentifier/yang", 3, "instance-identifier-module", "cont");
+ }
+
+ @Test
+ public void saveCnSnToXml() throws WebApplicationException, IOException, URISyntaxException, XMLStreamException {
+ CompositeNode cnSn = prepareCnSn();
+ String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode,
+ StructuredDataToXmlProvider.INSTANCE);
+ validateXmlOutput(output);
+ // System.out.println(output);
+
+ }
+
+ @Test
+ public void saveCnSnToJson() throws WebApplicationException, IOException, URISyntaxException {
+ CompositeNode cnSn = prepareCnSn();
+ String output = TestUtils.writeCompNodeWithSchemaContextToOutput(cnSn, modules, dataSchemaNode,
+ StructuredDataToJsonProvider.INSTANCE);
+ assertTrue(output
+ .contains("\"augment-augment-module:lf111\": \"/instance-identifier-module:cont/instance-identifier-module:cont1/augment-module:lst11[augment-module:keyvalue111=\\\"value1\\\"][augment-module:keyvalue112=\\\"value2\\\"]/augment-augment-module:lf112\""));
+ // System.out.println(output);
+ }
+
+ private void validateXmlOutput(String xml) throws XMLStreamException {
+ XMLInputFactory xmlInFactory = XMLInputFactory.newInstance();
+ XMLEventReader eventReader;
+
+ eventReader = xmlInFactory.createXMLEventReader(new ByteArrayInputStream(xml.getBytes()));
+ String aaModulePrefix = null;
+ String aModulePrefix = null;
+ String iiModulePrefix = null;
+ while (eventReader.hasNext()) {
+ XMLEvent nextEvent = eventReader.nextEvent();
+ if (nextEvent.isStartElement()) {
+ StartElement startElement = (StartElement) nextEvent;
+ if (startElement.getName().getLocalPart().equals("lf111")) {
+ Iterator prefixes = startElement.getNamespaceContext().getPrefixes("augment:augment:module");
+
+ while (prefixes.hasNext() && aaModulePrefix == null) {
+ String prefix = (String) prefixes.next();
+ if (!prefix.isEmpty()) {
+ aaModulePrefix = prefix;
+ }
+ }
+
+ aModulePrefix = startElement.getNamespaceContext().getPrefix("augment:module");
+ iiModulePrefix = startElement.getNamespaceContext().getPrefix("instance:identifier:module");
+ break;
+ }
+ }
+ }
+
+ assertNotNull(aaModulePrefix);
+ assertNotNull(aModulePrefix);
+ assertNotNull(iiModulePrefix);
+
+ String instanceIdentifierValue = "/" + iiModulePrefix + ":cont/" + iiModulePrefix + ":cont1/" + aModulePrefix
+ + ":lst11[" + aModulePrefix + ":keyvalue111='value1'][" + aModulePrefix + ":keyvalue112='value2']/"
+ + aaModulePrefix + ":lf112";
+
+// System.out.println(xml);
+ assertTrue(xml.contains(instanceIdentifierValue));
+
+ }
+
+ private CompositeNode prepareCnSn() throws URISyntaxException {
+ CompositeNodeWrapper cont = new CompositeNodeWrapper(new URI("instance:identifier:module"), "cont");
+ CompositeNodeWrapper cont1 = new CompositeNodeWrapper(new URI("instance:identifier:module"), "cont1");
+ CompositeNodeWrapper lst11 = new CompositeNodeWrapper(new URI("augment:module"), "lst11");
+ InstanceIdentifier instanceIdentifier = createInstanceIdentifier();
+ SimpleNodeWrapper lf111 = new SimpleNodeWrapper(new URI("augment:augment:module"), "lf111", instanceIdentifier);
+
+ lst11.addValue(lf111);
+ cont1.addValue(lst11);
+ cont.addValue(cont1);
+
+ return cont;
+ }
+
+ private InstanceIdentifier createInstanceIdentifier() throws URISyntaxException {
+ List<PathArgument> pathArguments = new ArrayList<>();
+ pathArguments.add(new NodeIdentifier(new QName(new URI("instance:identifier:module"), "cont")));
+ pathArguments.add(new NodeIdentifier(new QName(new URI("instance:identifier:module"), "cont1")));
+
+ QName qName = new QName(new URI("augment:module"), "lst11");
+ Map<QName, Object> keyValues = new HashMap<>();
+ keyValues.put(new QName(new URI("augment:module"), "keyvalue111"), "value1");
+ keyValues.put(new QName(new URI("augment:module"), "keyvalue112"), "value2");
+ NodeIdentifierWithPredicates nodeIdentifierWithPredicates = new NodeIdentifierWithPredicates(qName, keyValues);
+ pathArguments.add(nodeIdentifierWithPredicates);
+
+ pathArguments.add(new NodeIdentifier(new QName(new URI("augment:augment:module"), "lf112")));
+
+ return new InstanceIdentifier(pathArguments);
+ }
+
+}
package org.opendaylight.controller.sal.restconf.impl.test;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import org.junit.Test;
IdentityrefTypeDefinition mockedIidentityrefType = mock(IdentityrefTypeDefinition.class);
Codec<Object, Object> codec = RestCodec.from(mockedIidentityrefType, null);
- String serializedValue = (String) codec.deserialize("incorrect value"); // IdentityValuesDTO
- // object
- // expected
- assertEquals("incorrect value", serializedValue);
+ assertNull(codec.deserialize("incorrect value"));
}
}
package org.opendaylight.controller.sal.restconf.impl.test;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import java.io.FileNotFoundException;
-import java.io.UnsupportedEncodingException;
-import java.net.URISyntaxException;
-import org.junit.Ignore;
+import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.opendaylight.controller.sal.restconf.impl.ControllerContext;
import org.opendaylight.controller.sal.restconf.impl.InstanceIdWithSchemaNode;
import org.opendaylight.controller.sal.restconf.impl.ResponseException;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
public class RestGetAugmentedElementWhenEqualNamesTest {
-
- @Ignore
- @Test
- public void getDataWithUrlMountPoint() throws UnsupportedEncodingException, URISyntaxException,
- FileNotFoundException {
- boolean exceptionCaught = false;
-
+
+ private static ControllerContext controllerContext = ControllerContext.getInstance();
+
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ @BeforeClass
+ public static void init() throws FileNotFoundException {
SchemaContext schemaContextTestModule = TestUtils.loadSchemaContext("/common/augment/yang");
- ControllerContext controllerContext = ControllerContext.getInstance();
controllerContext.setSchemas(schemaContextTestModule);
+ }
+ @Test
+ public void augmentedNodesInUri() {
+ InstanceIdWithSchemaNode iiWithData = controllerContext.toInstanceIdentifier("main:cont/augment-main-a:cont1");
+ assertEquals("ns:augment:main:a", iiWithData.getSchemaNode().getQName().getNamespace().toString());
+ iiWithData = controllerContext.toInstanceIdentifier("main:cont/augment-main-b:cont1");
+ assertEquals("ns:augment:main:b", iiWithData.getSchemaNode().getQName().getNamespace().toString());
+ }
+
+ @Test
+ public void nodeWithoutNamespaceHasMoreAugments() {
+ boolean exceptionCaught = false;
try {
- InstanceIdWithSchemaNode instanceIdentifierA = controllerContext
- .toInstanceIdentifier("main:cont/augment-main-a:cont1");
- InstanceIdWithSchemaNode instanceIdentifierB = controllerContext
- .toInstanceIdentifier("main:cont/augment-main-b:cont1");
-
- assertEquals("ns:augment:main:a", instanceIdentifierA.getSchemaNode().getQName().getNamespace().toString());
- assertEquals("ns:augment:main:b", instanceIdentifierB.getSchemaNode().getQName().getNamespace());
+ controllerContext.toInstanceIdentifier("main:cont/cont1");
} catch (ResponseException e) {
+ assertTrue(((String) e.getResponse().getEntity()).contains("is added as augment from more than one module"));
exceptionCaught = true;
}
-
- assertFalse(exceptionCaught);
-
+ assertTrue(exceptionCaught);
}
}
.toInstanceIdentifier("simple-nodes:userWithoutClass/foo");
assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "userWithoutClass");
- instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:userWithoutClass/foo/full-name");
- assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "full-name");
+ instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:userWithoutClass/foo");
+ assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "userWithoutClass");
instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:user/foo/boo");
assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "user");
instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:user//boo");
assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "user");
- instanceIdentifier = controllerContext.toInstanceIdentifier("simple-nodes:users/user/foo");
- assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "user");
}
@Test
@Test
public void testToInstanceIdentifierChoice() throws FileNotFoundException {
InstanceIdWithSchemaNode instanceIdentifier = controllerContext
- .toInstanceIdentifier("simple-nodes:food/nonalcoholic/beer");
- assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "beer");
+ .toInstanceIdentifier("simple-nodes:food/nonalcoholic");
+ assertEquals(instanceIdentifier.getSchemaNode().getQName().getLocalName(), "nonalcoholic");
}
@Test
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.WebApplicationException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.controller.sal.rest.impl.JsonToCompositeNodeProvider;
+import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
+
+public class XmlAndJsonToCnSnInstanceIdentifierTest extends YangAndXmlAndDataSchemaLoader {
+
+ @BeforeClass
+ public static void initialize() {
+ dataLoad("/instanceidentifier/yang", 3, "instance-identifier-module", "cont");
+ }
+
+ @Test
+ public void loadXmlToCnSn() throws WebApplicationException, IOException, URISyntaxException {
+ CompositeNode cnSn = TestUtils.readInputToCnSn("/instanceidentifier/xml/xmldata.xml",
+ XmlToCompositeNodeProvider.INSTANCE);
+ TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
+ verify(cnSn);
+ }
+
+ @Test
+ public void loadJsonToCnSn() throws WebApplicationException, IOException, URISyntaxException {
+ CompositeNode cnSn = TestUtils.readInputToCnSn("/instanceidentifier/json/jsondata.json",
+ JsonToCompositeNodeProvider.INSTANCE);
+ TestUtils.normalizeCompositeNode(cnSn, modules, schemaNodePath);
+ verify(cnSn);
+ }
+
+ private void verify(CompositeNode cnSn) throws URISyntaxException {
+ SimpleNode<?> lf111 = getSnWithInstanceIdentifier(cnSn);
+ Object value = lf111.getValue();
+ assertTrue(value instanceof InstanceIdentifier);
+
+ InstanceIdentifier instanceIdentifier = (InstanceIdentifier) value;
+ List<PathArgument> pathArguments = instanceIdentifier.getPath();
+ assertEquals(4, pathArguments.size());
+ String revisionDate = "2014-01-17";
+ assertEquals(TestUtils.buildQName("cont", "instance:identifier:module", revisionDate), pathArguments.get(0)
+ .getNodeType());
+ assertEquals(TestUtils.buildQName("cont1", "instance:identifier:module", revisionDate), pathArguments.get(1)
+ .getNodeType());
+ assertEquals(TestUtils.buildQName("lst11", "augment:module", revisionDate), pathArguments.get(2).getNodeType());
+ assertEquals(TestUtils.buildQName("lf112", "augment:augment:module", revisionDate), pathArguments.get(3)
+ .getNodeType());
+
+ assertTrue(pathArguments.get(2) instanceof NodeIdentifierWithPredicates);
+ Map<QName, Object> predicates = ((NodeIdentifierWithPredicates) pathArguments.get(2)).getKeyValues();
+ assertEquals(2, predicates.size());
+ assertEquals("value1", predicates.get(TestUtils.buildQName("keyvalue111", "augment:module", revisionDate)));
+ assertEquals("value2", predicates.get(TestUtils.buildQName("keyvalue112", "augment:module", revisionDate)));
+ }
+
+ private SimpleNode<?> getSnWithInstanceIdentifier(CompositeNode cnSn) throws URISyntaxException {
+ CompositeNode cont1 = cnSn.getFirstCompositeByName(TestUtils.buildQName("cont1", "instance:identifier:module",
+ "2014-01-17"));
+ assertNotNull(cont1);
+ CompositeNode lst11 = cont1.getFirstCompositeByName(TestUtils.buildQName("lst11", "augment:module",
+ "2014-01-17"));
+ assertNotNull(lst11);
+ SimpleNode<?> lf111 = lst11.getFirstSimpleByName(TestUtils.buildQName("lf111", "augment:augment:module",
+ "2014-01-17"));
+ assertNotNull(lf111);
+ return lf111;
+ }
+
+}
package org.opendaylight.controller.sal.restconf.impl.xml.to.cnsn.test;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import java.util.Set;
-import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
-import org.opendaylight.controller.sal.restconf.impl.ResponseException;
import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.api.Module;
public class XmlAugmentedElementToCnSnTest {
- @Ignore
@Test
public void loadDataAugmentedSchemaMoreEqualNamesTest() {
- boolean exceptionCaught = false;
- try {
- loadAndNormalizeData("/common/augment/xml/dataa.xml", "/common/augment/yang", "main","cont");
- loadAndNormalizeData("/common/augment/xml/datab.xml", "/common/augment/yang", "main","cont");
- } catch (ResponseException e) {
- exceptionCaught = true;
- }
-
- assertFalse(exceptionCaught);
+ loadAndNormalizeData("/common/augment/xml/dataa.xml", "/common/augment/yang", "main","cont");
+ loadAndNormalizeData("/common/augment/xml/datab.xml", "/common/augment/yang", "main","cont");
}
-
private void loadAndNormalizeData(String xmlPath, String yangPath, String topLevelElementName, String moduleName) {
CompositeNode compNode = TestUtils.readInputToCnSn(xmlPath, false,
XmlToCompositeNodeProvider.INSTANCE);
package org.opendaylight.controller.sal.restconf.impl.xml.to.cnsn.test;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import java.util.List;
import java.util.Set;
+import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.controller.sal.rest.impl.XmlToCompositeNodeProvider;
import org.opendaylight.controller.sal.restconf.impl.test.TestUtils;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.*;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
* Test case like <cont1 xmlns="namespace1" xmlns:x="namespace">
* <lf11>x:identity</lf11> </cont1>
*/
+ @Ignore
@Test
public void testIdentityrefNmspcInParrentElement() {
testIdentityrefToCnSn("/xml-to-cnsn/identityref/xml/data-nmspc-in-parrent-element.xml",
"/xml-to-cnsn/identityref", "identityref-module", "cont", 2, "iden", "z:namespace");
-
}
/**
}
}
+ leaf lfInIdentifier {
+ type instance-identifier;
+ }
+
}
}
\ No newline at end of file
--- /dev/null
+{
+ "instance-identifier-module:cont": {
+ "cont1": {
+ "augment-module:lst11": [
+ {
+ "keyvalue111":"value1",
+ "keyvalue112":"value2",
+ "augment-augment-module:lf111":"/instance-identifier-module:cont/instance-identifier-module:cont1/augment-module:lst11[augment-module:keyvalue111=\"value1\"][augment-module:keyvalue112=\"value2\"]/augment-augment-module:lf112",
+ "augment-augment-module:lf112":"lf112 value"
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<cont xmlns="instance:identifier:module">
+ <cont1>
+ <lst11 xmlns="augment:module" xmlns:c="augment:augment:module">
+ <keyvalue111>value1</keyvalue111>
+ <keyvalue112>value2</keyvalue112>
+ <lf111 xmlns="augment:augment:module" xmlns:a="instance:identifier:module" xmlns:b="augment:module" >/a:cont/a:cont1/b:lst11[b:keyvalue111="value1"][b:keyvalue112="value2"]/c:lf112</lf111>
+ <lf112 xmlns="augment:augment:module">lf112 value</lf112>
+ </lst11>
+ </cont1>
+</cont>
--- /dev/null
+module augment-augment-module {
+ namespace "augment:augment:module";
+
+ prefix "aamodule";
+
+ import augment-module {prefix amodule; revision-date 2014-01-17;}
+ import instance-identifier-module {prefix imodule; revision-date 2014-01-17;}
+
+ revision 2014-01-17 {
+ }
+
+ augment "/imodule:cont/imodule:cont1/amodule:lst11" {
+ leaf lf111 {
+ type instance-identifier;
+ }
+ leaf lf112 {
+ type string;
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+module augment-module {
+ namespace "augment:module";
+
+ prefix "amodule";
+
+ import instance-identifier-module {prefix imodule; revision-date 2014-01-17;}
+
+ revision 2014-01-17 {
+ }
+
+ augment "/imodule:cont/imodule:cont1" {
+ list lst11 {
+ key "keyvalue111 keyvalue112";
+ leaf keyvalue111 {
+ type string;
+ }
+ leaf keyvalue112 {
+ type string;
+ }
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+module instance-identifier-module {
+ namespace "instance:identifier:module";
+
+ prefix "iimodule";
+ revision 2014-01-17 {
+ }
+
+ container cont {
+ container cont1 {
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<cont xmlns="generalnamespace">
+ <cont1>
+ <lf1 xmlns:prefix="prefix:name" xmlns:prefix2="prefix2:name">/prefix:somepath1/prefix2:somepath2</lf1>
+ </cont1>
+</cont>
\ No newline at end of file
NodeRef targetNodeRef = new NodeRef(targetInstanceId);
try{
- sendAggregateFlowsStatsFromAllTablesRequest(targetNode.getKey());
-
- sendAllFlowsStatsFromAllTablesRequest(targetNodeRef);
-
- sendAllNodeConnectorsStatisticsRequest(targetNodeRef);
-
- sendAllFlowTablesStatisticsRequest(targetNodeRef);
-
- sendAllQueueStatsFromAllNodeConnector (targetNodeRef);
-
- sendAllGroupStatisticsRequest(targetNodeRef);
-
- sendAllMeterStatisticsRequest(targetNodeRef);
-
- sendGroupDescriptionRequest(targetNodeRef);
-
- sendMeterConfigStatisticsRequest(targetNodeRef);
+ if(flowStatsService != null){
+ sendAggregateFlowsStatsFromAllTablesRequest(targetNode.getKey());
+ sendAllFlowsStatsFromAllTablesRequest(targetNodeRef);
+ }
+ if(flowTableStatsService != null){
+ sendAllFlowTablesStatisticsRequest(targetNodeRef);
+ }
+ if(portStatsService != null){
+ sendAllNodeConnectorsStatisticsRequest(targetNodeRef);
+ }
+ if(groupStatsService != null){
+ sendAllGroupStatisticsRequest(targetNodeRef);
+ sendGroupDescriptionRequest(targetNodeRef);
+ }
+ if(meterStatsService != null){
+ sendAllMeterStatisticsRequest(targetNodeRef);
+ sendMeterConfigStatisticsRequest(targetNodeRef);
+ }
+ if(queueStatsService != null){
+ sendAllQueueStatsFromAllNodeConnector (targetNodeRef);
+ }
}catch(Exception e){
spLogger.error("Exception occured while sending statistics requests : {}", e);
}
if(tablesId.size() != 0){
for(Short id : tablesId){
- spLogger.debug("Send aggregate stats request for flow table {} to node {}",id,targetNodeKey);
- GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder input =
- new GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder();
-
- input.setNode(new NodeRef(InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).toInstance()));
- input.setTableId(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId(id));
- Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>> response =
- flowStatsService.getAggregateFlowStatisticsFromFlowTableForAllFlows(input.build());
-
- multipartMessageManager.setTxIdAndTableIdMapEntry(targetNodeKey.getId(), response.get().getResult().getTransactionId(), id);
- this.multipartMessageManager.addTxIdToRequestTypeEntry(targetNodeKey.getId(), response.get().getResult().getTransactionId()
- , StatsRequestType.AGGR_FLOW);
+ sendAggregateFlowsStatsFromTableRequest(targetNodeKey,id);
}
}else{
spLogger.debug("No details found in data store for flow tables associated with Node {}",targetNodeKey);
}
}
+
+ public void sendAggregateFlowsStatsFromTableRequest(NodeKey targetNodeKey,Short tableId) throws InterruptedException, ExecutionException{
+
+ spLogger.debug("Send aggregate stats request for flow table {} to node {}",tableId,targetNodeKey);
+ GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder input =
+ new GetAggregateFlowStatisticsFromFlowTableForAllFlowsInputBuilder();
+
+ input.setNode(new NodeRef(InstanceIdentifier.builder(Nodes.class).child(Node.class, targetNodeKey).toInstance()));
+ input.setTableId(new org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TableId(tableId));
+ Future<RpcResult<GetAggregateFlowStatisticsFromFlowTableForAllFlowsOutput>> response =
+ flowStatsService.getAggregateFlowStatisticsFromFlowTableForAllFlows(input.build());
+
+ multipartMessageManager.setTxIdAndTableIdMapEntry(targetNodeKey.getId(), response.get().getResult().getTransactionId(), tableId);
+ this.multipartMessageManager.addTxIdToRequestTypeEntry(targetNodeKey.getId(), response.get().getResult().getTransactionId()
+ , StatsRequestType.AGGR_FLOW);
+ }
public void sendAllNodeConnectorsStatisticsRequest(NodeRef targetNode) throws InterruptedException, ExecutionException{
*/
package org.opendaylight.controller.md.statistics.manager;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import org.opendaylight.controller.md.statistics.manager.NodeStatisticsAger.FlowEntry;
import org.opendaylight.controller.md.statistics.manager.NodeStatisticsAger.QueueEntry;
import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.statistics.rev131111.nodes.node.meter.MeterStatisticsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.config.stats.reply.MeterConfigStats;
import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.types.rev130918.meter.statistics.reply.MeterStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.statistics.types.rev130925.GenericStatistics;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsData;
import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.FlowCapableNodeConnectorStatisticsDataBuilder;
//TODO: Not a good way to do it, need to figure out better way.
//TODO: major issue in any alternate approach is that flow key is incrementally assigned
//to the flows stored in data store.
+ // Augment same statistics to all the matching masked flow
if(table != null){
for(Flow existingFlow : table.getFlow()){
sucLogger.debug("Existing flow in data store : {}",existingFlow.toString());
if(flowEquals(flowRule,existingFlow)){
+ it = this.statisticsManager.startChange();
InstanceIdentifier<Flow> flowRef = InstanceIdentifier.builder(Nodes.class).child(Node.class, key)
.augmentation(FlowCapableNode.class)
.child(Table.class, new TableKey(tableId))
foundOriginalFlow = true;
it.putOperationalData(flowRef, flowBuilder.build());
it.commit();
- break;
}
}
}
else if(!matchEquals(statsFlow.getMatch(), storedFlow.getMatch())) {
return false;
}
- if (statsFlow.getPriority() == null) {
- if (storedFlow.getPriority() != null) {
+ if (storedFlow.getPriority() == null) {
+ if (statsFlow.getPriority() != null && statsFlow.getPriority()!= 0x8000) {
return false;
}
} else if(!statsFlow.getPriority().equals(storedFlow.getPriority())) {
/**
* Explicit equals method to compare the 'match' for flows stored in the data-stores and flow fetched from the switch.
- * Usecase: e.g If user don't set any ethernet source and destination address for match,data store will store null for
- * these address.
- * e.g [_ethernetMatch=EthernetMatch [_ethernetDestination=null, _ethernetSource=null, _ethernetType=
- * EthernetType [_type=EtherType [_value=2048], _mask=null, augmentation=[]]
+ * Flow installation process has three steps
+ * 1) Store flow in config data store
+ * 2) and send it to plugin for installation
+ * 3) Flow gets installed in switch
*
- * But when you fetch the flows from switch, openflow driver library converts all zero bytes of mac address in the
- * message stream to 00:00:00:00:00:00. Following string shows how library interpret the zero mac address bytes and
- * eventually when translator convert it to MD-SAL match, this is how it looks
- * [_ethernetDestination=EthernetDestination [_address=MacAddress [_value=00:00:00:00:00:00], _mask=null, augmentation=[]],
- * _ethernetSource=EthernetSource [_address=MacAddress [_value=00:00:00:00:00:00], _mask=null, augmentation=[]],
- * _ethernetType=EthernetType [_type=EtherType [_value=2048], _mask=null, augmentation=[]]
+ * The flow user wants to install and what finally gets installed in switch can be slightly different.
+ * E.g, If user installs flow with src/dst ip=10.0.0.1/24, when it get installed in the switch
+ * src/dst ip will be changes to 10.0.0.0/24 because of netmask of 24. When statistics manager fetch
+ * stats it gets 10.0.0.0/24 rather then 10.0.0.1/24. Custom match takes care of by using masked ip
+ * while comparing two ip addresses.
*
- * Similarly for inPort, if user/application don't set any value for it, FRM will store null value for it in data store.
- * When we fetch the same flow (with its statistics) from switch, plugin converts its value to openflow:X:0.
- * e.g _inPort=Uri [_value=openflow:1:0]
+ * Sometimes when user don't provide few values that is required by flow installation request, like
+ * priority,hard timeout, idle timeout, cookies etc, plugin usages default values before sending
+ * request to the switch. So when statistics manager gets flow statistics, it gets the default value.
+ * But the flow stored in config data store don't have those defaults value. I included those checks
+ * in the customer flow/match equal function.
*
- * So this custom equals method add additional check to take care of these scenario, in case any match element is null in data-store-flow, but not
- * in the flow fetched from switch.
*
* @param statsFlow
* @param storedFlow
if (statsFlow.getLayer3Match() != null) {
return false;
}
- } else if(!storedFlow.getLayer3Match().equals(statsFlow.getLayer3Match())) {
+ } else if(!layer3MatchEquals(statsFlow.getLayer3Match(),storedFlow.getLayer3Match())) {
return false;
}
if (storedFlow.getLayer4Match()== null) {
}
return true;
}
+
+ private boolean layer3MatchEquals(Layer3Match statsLayer3Match, Layer3Match storedLayer3Match){
+
+ if(statsLayer3Match instanceof Ipv4Match && storedLayer3Match instanceof Ipv4Match){
+ Ipv4Match statsIpv4Match = (Ipv4Match)statsLayer3Match;
+ Ipv4Match storedIpv4Match = (Ipv4Match)storedLayer3Match;
+
+ if (storedIpv4Match.getIpv4Destination()== null) {
+ if (statsIpv4Match.getIpv4Destination()!= null) {
+ return false;
+ }
+ } else if(!IpAddressEquals(statsIpv4Match.getIpv4Destination(),storedIpv4Match.getIpv4Destination())){
+ return false;
+ }
+ if (storedIpv4Match.getIpv4Source() == null) {
+ if (statsIpv4Match.getIpv4Source() != null) {
+ return false;
+ }
+ } else if(!IpAddressEquals(statsIpv4Match.getIpv4Source(),storedIpv4Match.getIpv4Source())) {
+ return false;
+ }
+
+ return true;
+ }else{
+ return storedLayer3Match.equals(statsLayer3Match);
+ }
+ }
+
+ private boolean IpAddressEquals(Ipv4Prefix statsIpAddress, Ipv4Prefix storedIpAddress) {
+ IntegerIpAddress statsIpAddressInt = StrIpToIntIp(statsIpAddress.getValue());
+ IntegerIpAddress storedIpAddressInt = StrIpToIntIp(storedIpAddress.getValue());
+
+ if(IpAndMaskBasedMatch(statsIpAddressInt,storedIpAddressInt)){
+ return true;
+ }
+ if(IpBasedMatch(statsIpAddressInt,storedIpAddressInt)){
+ return true;
+ }
+ return false;
+ }
+
+ private boolean IpAndMaskBasedMatch(IntegerIpAddress statsIpAddressInt,IntegerIpAddress storedIpAddressInt){
+ return ((statsIpAddressInt.getIp() & statsIpAddressInt.getMask()) == (storedIpAddressInt.getIp() & storedIpAddressInt.getMask()));
+ }
+
+ private boolean IpBasedMatch(IntegerIpAddress statsIpAddressInt,IntegerIpAddress storedIpAddressInt){
+ return (statsIpAddressInt.getIp() == storedIpAddressInt.getIp());
+ }
+
+ /*
+ * Method return integer version of ip address. Converted int will be mask if
+ * mask specified
+ */
+ private IntegerIpAddress StrIpToIntIp(String ipAddresss){
+
+ String[] parts = ipAddresss.split("/");
+ String ip = parts[0];
+ int prefix;
+
+ if (parts.length < 2) {
+ prefix = 32;
+ } else {
+ prefix = Integer.parseInt(parts[1]);
+ }
+
+ Inet4Address addr =null;
+ try {
+ addr = (Inet4Address) InetAddress.getByName(ip);
+ } catch (UnknownHostException e){}
+
+ byte[] addrBytes = addr.getAddress();
+ int ipInt = ((addrBytes[0] & 0xFF) << 24) |
+ ((addrBytes[1] & 0xFF) << 16) |
+ ((addrBytes[2] & 0xFF) << 8) |
+ ((addrBytes[3] & 0xFF) << 0);
+
+ int mask = 0xffffffff << 32 - prefix;
+
+ return new IntegerIpAddress(ipInt, mask);
+ }
+
+ class IntegerIpAddress{
+ int ip;
+ int mask;
+ public IntegerIpAddress(int ip, int mask) {
+ this.ip = ip;
+ this.mask = mask;
+ }
+ public int getIp() {
+ return ip;
+ }
+ public int getMask() {
+ return mask;
+ }
+ }
}
+
mavenBundle(ODL, "netconf-impl").versionAsInProject(),
mavenBundle(ODL, "netconf-client").versionAsInProject(),
mavenBundle(ODL, "netconf-util").versionAsInProject(),
- mavenBundle(ODL + ".thirdparty", "ganymed", "1.0-SNAPSHOT"),
+ mavenBundle(ODL + ".thirdparty", "ganymed").versionAsInProject(),
mavenBundle(ODL, "netconf-mapping-api").versionAsInProject(),
mavenBundle(ODL, "config-netconf-connector").versionAsInProject(),
mavenBundle(ODL, "config-persister-impl").versionAsInProject(),
public class NetconfOperationServiceFactoryImpl implements NetconfOperationServiceFactory {
public static final int ATTEMPT_TIMEOUT_MS = 1000;
+ private static final int SILENT_ATTEMPTS = 30;
private final YangStoreService yangStoreService;
private final ConfigRegistryJMXClient jmxClient;
public NetconfOperationServiceFactoryImpl(YangStoreService yangStoreService, MBeanServer mBeanServer) {
this.yangStoreService = yangStoreService;
+ ConfigRegistryJMXClient configRegistryJMXClient;
+ int i = 0;
// Config registry might not be present yet, but will be eventually
while(true) {
- final ConfigRegistryJMXClient configRegistryJMXClient;
try {
configRegistryJMXClient = new ConfigRegistryJMXClient(mBeanServer);
+ break;
} catch (IllegalStateException e) {
- logger.debug("Jmx client could not be created, reattempting");
+ ++i;
+ if (i > SILENT_ATTEMPTS) {
+ logger.info("JMX client not created after {} attempts, still trying", i, e);
+ } else {
+ logger.debug("JMX client could not be created, reattempting, try {}", i, e);
+ }
try {
Thread.sleep(ATTEMPT_TIMEOUT_MS);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
- throw new RuntimeException(e1);
+ throw new RuntimeException("Interrupted while reattempting connection", e1);
}
- continue;
}
+ }
- jmxClient = configRegistryJMXClient;
- break;
+ jmxClient = configRegistryJMXClient;
+ if (i > SILENT_ATTEMPTS) {
+ logger.info("Created JMX client after {} attempts", i);
+ } else {
+ logger.debug("Created JMX client after {} attempts", i);
}
}
// start pushing snapshots:
for (ConfigSnapshotHolder configSnapshotHolder: configs){
netconfClient = pushSnapshotWithRetries(configSnapshotHolder, Optional.of(netconfClient));
+ logger.debug("Config snapshot pushed successfully: {}", configSnapshotHolder);
}
+
+ logger.debug("All configuration snapshots have been pushed successfully.");
return netconfClient;
}
// uncaught exception handler will deal with this failure
throw new RuntimeException("Interrupted while waiting for netconf connection", e);
}
+ logger.info("Configuration Persister initialization completed.");
}
};
initializationThread = new Thread(initializationRunnable, "ConfigPersister-registrator");
<module>netconf-mapping-api</module>
<module>netconf-client</module>
<module>netconf-ssh</module>
- <module>../../third-party/ganymed</module>
<module>netconf-monitoring</module>
<module>ietf-netconf-monitoring</module>
<module>ietf-netconf-monitoring-extension</module>
import org.slf4j.LoggerFactory;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
.setService(IClusterContainerServices.class)
.setCallbacks("setClusterContainerService",
"unsetClusterContainerService").setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
}
if (imp.equals(NeutronRouterInterface.class)) {
// export the service
.setService(IClusterContainerServices.class)
.setCallbacks("setClusterContainerService",
"unsetClusterContainerService").setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
}
if (imp.equals(NeutronPortInterface.class)) {
// export the service
.setService(IClusterContainerServices.class)
.setCallbacks("setClusterContainerService",
"unsetClusterContainerService").setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
}
if (imp.equals(NeutronSubnetInterface.class)) {
// export the service
.setService(IClusterContainerServices.class)
.setCallbacks("setClusterContainerService",
"unsetClusterContainerService").setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
}
if (imp.equals(NeutronNetworkInterface.class)) {
// export the service
.setService(IClusterContainerServices.class)
.setCallbacks("setClusterContainerService",
"unsetClusterContainerService").setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
}
}
}
import java.util.List;
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.opendaylight.controller.clustering.services.CacheExistException;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP;
import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
-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.utils.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NeutronFloatingIPInterface implements INeutronFloatingIPCRUD, IConfigurationContainerAware,
IObjectReader {
private static final Logger logger = LoggerFactory.getLogger(NeutronFloatingIPInterface.class);
- private static String ROOT = GlobalConstants.STARTUPHOME.toString();
- private static final String FILENAME ="neutron.floatingip";
- private static String fileName;
+ private static final String FILE_NAME = "neutron.floatingip.conf";
private String containerName = null;
private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
private ConcurrentMap<String, NeutronFloatingIP> floatingIPDB;
// methods needed for creating caches
}
}
- @SuppressWarnings("deprecation")
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ this.configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ this.configurationService = null;
+ }
+
private void allocateCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterContainerService, can't create cache");
logger.debug("Cache successfully created for NeutronFloatingIps");
}
- @SuppressWarnings({ "unchecked", "deprecation" })
+ @SuppressWarnings({ "unchecked" })
private void retrieveCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterContainerService, can't retrieve cache");
logger.debug("Cache was successfully retrieved for Neutron FloatingIPs");
}
- @SuppressWarnings("deprecation")
private void destroyCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterMger, can't destroy cache");
private void startUp() {
allocateCache();
retrieveCache();
- if ((clusterContainerService != null) && (clusterContainerService.amICoordinator())) {
- loadConfiguration();
- }
+ loadConfiguration();
}
/**
// In the Global instance case the containerName is empty
this.containerName = "";
}
- fileName = ROOT + FILENAME + "_" + containerName + ".conf";
startUp();
}
// this method uses reflection to update an object from it's delta.
+ @SuppressWarnings("unused")
private boolean overwrite(Object target, Object delta) {
Method[] methods = target.getClass().getMethods();
@Override
public NeutronFloatingIP getFloatingIP(String uuid) {
- if (!floatingIPExists(uuid))
+ if (!floatingIPExists(uuid)) {
return null;
+ }
return floatingIPDB.get(uuid);
}
INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
- if (floatingIPExists(input.getID()))
+ if (floatingIPExists(input.getID())) {
return false;
+ }
//if floating_ip_address isn't there, allocate from the subnet pool
NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(input.getFloatingNetworkUUID()).getSubnets().get(0));
- if (input.getFloatingIPAddress() == null)
+ if (input.getFloatingIPAddress() == null) {
input.setFloatingIPAddress(subnet.getLowAddr());
+ }
subnet.allocateIP(input.getFloatingIPAddress());
//if port_id is there, bind port to this floating ip
INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this);
INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
- if (!floatingIPExists(uuid))
+ if (!floatingIPExists(uuid)) {
return false;
+ }
NeutronFloatingIP floatIP = getFloatingIP(uuid);
//if floating_ip_address isn't there, allocate from the subnet pool
NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(floatIP.getFloatingNetworkUUID()).getSubnets().get(0));
public boolean updateFloatingIP(String uuid, NeutronFloatingIP delta) {
INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this);
- if (!floatingIPExists(uuid))
+ if (!floatingIPExists(uuid)) {
return false;
+ }
NeutronFloatingIP target = floatingIPDB.get(uuid);
if (target.getPortUUID() != null) {
NeutronPort port = portCRUD.getPort(target.getPortUUID());
return true;
}
- @SuppressWarnings("unchecked")
private void loadConfiguration() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, NeutronFloatingIP> confList = (ConcurrentMap<String, NeutronFloatingIP>)
- objReader.read(this, fileName);
-
- if (confList == null) {
- return;
- }
-
- for (String key : confList.keySet()) {
- floatingIPDB.put(key, confList.get(key));
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronFloatingIP nfIP = (NeutronFloatingIP) conf;
+ floatingIPDB.put(nfIP.getID(), nfIP);
}
}
@Override
public Status saveConfiguration() {
- ObjectWriter objWriter = new ObjectWriter();
- return objWriter.write(new ConcurrentHashMap<String, NeutronFloatingIP>(floatingIPDB), fileName);
+ return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(floatingIPDB.values()),
+ FILE_NAME);
}
@Override
import java.util.List;
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.opendaylight.controller.clustering.services.CacheExistException;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
-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.utils.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NeutronNetworkInterface implements INeutronNetworkCRUD, IConfigurationContainerAware,
IObjectReader {
private static final Logger logger = LoggerFactory.getLogger(NeutronNetworkInterface.class);
- private static String ROOT = GlobalConstants.STARTUPHOME.toString();
- private static final String FILENAME ="neutron.network";
- private static String fileName;
+ private static final String FILE_NAME ="neutron.network.conf";
private String containerName = null;
private ConcurrentMap<String, NeutronNetwork> networkDB;
private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
// methods needed for creating caches
}
}
- @SuppressWarnings("deprecation")
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ this.configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ this.configurationService = null;
+ }
+
private void allocateCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterContainerService, can't create cache");
logger.debug("Cache successfully created for Neutron Networks");
}
- @SuppressWarnings({ "unchecked", "deprecation" })
+ @SuppressWarnings({ "unchecked" })
private void retrieveCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterContainerService, can't retrieve cache");
private void startUp() {
allocateCache();
retrieveCache();
- if ((clusterContainerService != null) && (clusterContainerService.amICoordinator())) {
- loadConfiguration();
- }
+ loadConfiguration();
}
/**
// In the Global instance case the containerName is empty
this.containerName = "";
}
- fileName = ROOT + FILENAME + "_" + containerName + ".conf";
startUp();
}
- @SuppressWarnings("deprecation")
private void destroyCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterMger, can't destroy cache");
@Override
public NeutronNetwork getNetwork(String uuid) {
- if (!networkExists(uuid))
+ if (!networkExists(uuid)) {
return null;
+ }
return networkDB.get(uuid);
}
@Override
public boolean addNetwork(NeutronNetwork input) {
- if (networkExists(input.getID()))
+ if (networkExists(input.getID())) {
return false;
+ }
networkDB.putIfAbsent(input.getID(), input);
//TODO: add code to find INeutronNetworkAware services and call newtorkCreated on them
return true;
@Override
public boolean removeNetwork(String uuid) {
- if (!networkExists(uuid))
+ if (!networkExists(uuid)) {
return false;
+ }
networkDB.remove(uuid);
//TODO: add code to find INeutronNetworkAware services and call newtorkDeleted on them
return true;
@Override
public boolean updateNetwork(String uuid, NeutronNetwork delta) {
- if (!networkExists(uuid))
+ if (!networkExists(uuid)) {
return false;
+ }
NeutronNetwork target = networkDB.get(uuid);
return overwrite(target, delta);
}
@Override
public boolean networkInUse(String netUUID) {
- if (!networkExists(netUUID))
+ if (!networkExists(netUUID)) {
return true;
+ }
NeutronNetwork target = networkDB.get(netUUID);
- if (target.getPortsOnNetwork().size() > 0)
+ if (target.getPortsOnNetwork().size() > 0) {
return true;
+ }
return false;
}
- @SuppressWarnings("unchecked")
private void loadConfiguration() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, NeutronNetwork> confList = (ConcurrentMap<String, NeutronNetwork>)
- objReader.read(this, fileName);
-
- if (confList == null) {
- return;
- }
-
- for (String key : confList.keySet()) {
- networkDB.put(key, confList.get(key));
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronNetwork nn = (NeutronNetwork) conf;
+ networkDB.put(nn.getID(), nn);
}
}
@Override
public Status saveConfiguration() {
- ObjectWriter objWriter = new ObjectWriter();
- return objWriter.write(new ConcurrentHashMap<String, NeutronNetwork>(networkDB), fileName);
+ return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(networkDB.values()),
+ FILE_NAME);
}
@Override
import java.util.List;
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.opendaylight.controller.clustering.services.CacheExistException;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
import org.opendaylight.controller.networkconfig.neutron.NeutronPort;
import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs;
-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.utils.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NeutronPortInterface implements INeutronPortCRUD, IConfigurationContainerAware,
IObjectReader {
private static final Logger logger = LoggerFactory.getLogger(NeutronPortInterface.class);
- private static String ROOT = GlobalConstants.STARTUPHOME.toString();
- private static final String FILENAME ="neutron.port";
- private static String fileName;
+ private static final String FILE_NAME ="neutron.port.conf";
private String containerName = null;
private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
private ConcurrentMap<String, NeutronPort> portDB;
// methods needed for creating caches
}
}
- @SuppressWarnings("deprecation")
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ configurationService = null;
+ }
+
private void allocateCache() {
if (clusterContainerService == null) {
logger.error("un-initialized clusterContainerService, can't create cache");
logger.debug("Cache successfully created for OpenDOVE");
}
- @SuppressWarnings({ "unchecked", "deprecation" })
+ @SuppressWarnings({ "unchecked" })
private void retrieveCache() {
if (clusterContainerService == null) {
logger.error("un-initialized clusterContainerService, can't retrieve cache");
logger.debug("Cache was successfully retrieved for Neutron Ports");
}
- @SuppressWarnings("deprecation")
private void destroyCache() {
if (clusterContainerService == null) {
logger.error("un-initialized clusterMger, can't destroy cache");
private void startUp() {
allocateCache();
retrieveCache();
- if ((clusterContainerService != null) && (clusterContainerService.amICoordinator())) {
- loadConfiguration();
- }
-
+ loadConfiguration();
}
/**
// In the Global instance case the containerName is empty
containerName = "";
}
- fileName = ROOT + FILENAME + "_" + containerName + ".conf";
startUp();
}
return null;
}
- @SuppressWarnings("unchecked")
private void loadConfiguration() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, NeutronPort> confList = (ConcurrentMap<String, NeutronPort>)
- objReader.read(this, fileName);
-
- if (confList == null) {
- return;
- }
-
- for (String key : confList.keySet()) {
- portDB.put(key, confList.get(key));
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronPort nn = (NeutronPort) conf;
+ portDB.put(nn.getID(), nn);
}
}
@Override
public Status saveConfiguration() {
- ObjectWriter objWriter = new ObjectWriter();
- return objWriter.write(new ConcurrentHashMap<String, NeutronPort>(portDB), fileName);
+ return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(portDB.values()),
+ FILE_NAME);
}
@Override
import java.util.List;
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.opendaylight.controller.clustering.services.CacheExistException;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD;
import org.opendaylight.controller.networkconfig.neutron.NeutronRouter;
-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.utils.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NeutronRouterInterface implements INeutronRouterCRUD, IConfigurationContainerAware,
IObjectReader {
private static final Logger logger = LoggerFactory.getLogger(NeutronRouterInterface.class);
- private static String ROOT = GlobalConstants.STARTUPHOME.toString();
- private static final String FILENAME ="neutron.router";
- private static String fileName;
+ private static final String FILE_NAME ="neutron.router.conf";
private String containerName = null;
private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
private ConcurrentMap<String, NeutronRouter> routerDB;
// methods needed for creating caches
}
}
- @SuppressWarnings("deprecation")
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ this.configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ this.configurationService = null;
+ }
+
private void allocateCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterContainerService, can't create cache");
logger.debug("Cache successfully created for Neutron Routers");
}
- @SuppressWarnings({ "unchecked", "deprecation" })
+ @SuppressWarnings({ "unchecked" })
private void retrieveCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterContainerService, can't retrieve cache");
logger.debug("Cache was successfully retrieved for Neutron Routers");
}
- @SuppressWarnings("deprecation")
private void destroyCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterMger, can't destroy cache");
private void startUp() {
allocateCache();
retrieveCache();
- if ((clusterContainerService != null) && (clusterContainerService.amICoordinator())) {
- loadConfiguration();
- }
-
+ loadConfiguration();
}
/**
// In the Global instance case the containerName is empty
this.containerName = "";
}
- fileName = ROOT + FILENAME + "_" + containerName + ".conf";
startUp();
}
@Override
public NeutronRouter getRouter(String uuid) {
- if (!routerExists(uuid))
+ if (!routerExists(uuid)) {
return null;
+ }
return routerDB.get(uuid);
}
@Override
public boolean addRouter(NeutronRouter input) {
- if (routerExists(input.getID()))
+ if (routerExists(input.getID())) {
return false;
+ }
routerDB.putIfAbsent(input.getID(), input);
return true;
}
@Override
public boolean removeRouter(String uuid) {
- if (!routerExists(uuid))
+ if (!routerExists(uuid)) {
return false;
+ }
routerDB.remove(uuid);
return true;
}
@Override
public boolean updateRouter(String uuid, NeutronRouter delta) {
- if (!routerExists(uuid))
+ if (!routerExists(uuid)) {
return false;
+ }
NeutronRouter target = routerDB.get(uuid);
return overwrite(target, delta);
}
@Override
public boolean routerInUse(String routerUUID) {
- if (!routerExists(routerUUID))
+ if (!routerExists(routerUUID)) {
return true;
+ }
NeutronRouter target = routerDB.get(routerUUID);
return (target.getInterfaces().size() > 0);
}
- @SuppressWarnings("unchecked")
private void loadConfiguration() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, NeutronRouter> confList = (ConcurrentMap<String, NeutronRouter>)
- objReader.read(this, fileName);
-
- if (confList == null) {
- return;
- }
-
- for (String key : confList.keySet()) {
- routerDB.put(key, confList.get(key));
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronRouter nr = (NeutronRouter) conf;
+ routerDB.put(nr.getID(), nr);
}
}
@Override
public Status saveConfiguration() {
- ObjectWriter objWriter = new ObjectWriter();
- return objWriter.write(new ConcurrentHashMap<String, NeutronRouter>(routerDB), fileName);
+ return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(routerDB.values()),
+ FILE_NAME);
}
@Override
import java.util.List;
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.opendaylight.controller.clustering.services.CacheExistException;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD;
import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD;
import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces;
import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork;
import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet;
-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.utils.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class NeutronSubnetInterface implements INeutronSubnetCRUD, IConfigurationContainerAware,
IObjectReader {
private static final Logger logger = LoggerFactory.getLogger(NeutronSubnetInterface.class);
- private static String ROOT = GlobalConstants.STARTUPHOME.toString();
- private static final String FILENAME ="neutron.subnet";
- private static String fileName;
+ private static final String FILE_NAME ="neutron.subnet.conf";
private String containerName = null;
private IClusterContainerServices clusterContainerService = null;
+ private IConfigurationContainerService configurationService;
private ConcurrentMap<String, NeutronSubnet> subnetDB;
// methods needed for creating caches
}
}
- @SuppressWarnings("deprecation")
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service set: {}", service);
+ this.configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ logger.trace("Configuration service removed: {}", service);
+ this.configurationService = null;
+ }
+
private void allocateCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterContainerService, can't create cache");
logger.debug("Cache successfully created for Neutron Subnets");
}
- @SuppressWarnings({ "unchecked", "deprecation" })
+ @SuppressWarnings({ "unchecked" })
private void retrieveCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterContainerService, can't retrieve cache");
logger.debug("Cache was successfully retrieved for Neutron Subnets");
}
- @SuppressWarnings("deprecation")
private void destroyCache() {
if (this.clusterContainerService == null) {
logger.error("un-initialized clusterMger, can't destroy cache");
private void startUp() {
allocateCache();
retrieveCache();
- if ((clusterContainerService != null) && (clusterContainerService.amICoordinator())) {
- loadConfiguration();
- }
-
+ loadConfiguration();
}
/**
// In the Global instance case the containerName is empty
this.containerName = "";
}
- fileName = ROOT + FILENAME + "_" + containerName + ".conf";
startUp();
}
@Override
public NeutronSubnet getSubnet(String uuid) {
- if (!subnetExists(uuid))
+ if (!subnetExists(uuid)) {
return null;
+ }
return subnetDB.get(uuid);
}
@Override
public boolean addSubnet(NeutronSubnet input) {
String id = input.getID();
- if (subnetExists(id))
+ if (subnetExists(id)) {
return false;
+ }
subnetDB.putIfAbsent(id, input);
INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
@Override
public boolean removeSubnet(String uuid) {
- if (!subnetExists(uuid))
+ if (!subnetExists(uuid)) {
return false;
+ }
NeutronSubnet target = subnetDB.get(uuid);
INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this);
@Override
public boolean updateSubnet(String uuid, NeutronSubnet delta) {
- if (!subnetExists(uuid))
+ if (!subnetExists(uuid)) {
return false;
+ }
NeutronSubnet target = subnetDB.get(uuid);
return overwrite(target, delta);
}
@Override
public boolean subnetInUse(String subnetUUID) {
- if (!subnetExists(subnetUUID))
+ if (!subnetExists(subnetUUID)) {
return true;
+ }
NeutronSubnet target = subnetDB.get(subnetUUID);
return (target.getPortsInSubnet().size() > 0);
}
- @SuppressWarnings("unchecked")
private void loadConfiguration() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, NeutronSubnet> confList = (ConcurrentMap<String, NeutronSubnet>)
- objReader.read(this, fileName);
-
- if (confList == null) {
- return;
- }
-
- for (String key : confList.keySet()) {
- subnetDB.put(key, confList.get(key));
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, FILE_NAME)) {
+ NeutronSubnet ns = (NeutronSubnet) conf;
+ subnetDB.put(ns.getID(), ns);
}
}
@Override
public Status saveConfiguration() {
- ObjectWriter objWriter = new ObjectWriter();
- return objWriter.write(new ConcurrentHashMap<String, NeutronSubnet>(subnetDB), fileName);
+ return configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(subnetDB.values()),
+ FILE_NAME);
}
@Override
<configuration>
<instructions>
<Import-Package>
+ org.opendaylight.controller.configuration,
org.opendaylight.controller.clustering.services,
org.opendaylight.controller.sal.core,
org.opendaylight.controller.sal.utils,
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.services</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>configuration</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
-public class NeutronFloatingIP implements Serializable {
+public class NeutronFloatingIP extends ConfigurationObject implements Serializable {
private static final long serialVersionUID = 1L;
// See OpenStack Network API v2.0 Reference for description of
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
@XmlRootElement(name = "network")
@XmlAccessorType(XmlAccessType.NONE)
-public class NeutronNetwork implements Serializable {
+public class NeutronNetwork extends ConfigurationObject implements Serializable {
// See OpenStack Network API v2.0 Reference for description of
// annotated attributes
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
-public class NeutronPort implements Serializable {
+public class NeutronPort extends ConfigurationObject implements Serializable {
private static final long serialVersionUID = 1L;
// See OpenStack Network API v2.0 Reference for description of
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
-public class NeutronRouter implements Serializable {
+public class NeutronRouter extends ConfigurationObject implements Serializable {
private static final long serialVersionUID = 1L;
// See OpenStack Network API v2.0 Reference for description of
import org.apache.commons.net.util.SubnetUtils;
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
+import org.opendaylight.controller.configuration.ConfigurationObject;
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
-public class NeutronSubnet implements Serializable {
+public class NeutronSubnet extends ConfigurationObject implements Serializable {
private static final long serialVersionUID = 1L;
// See OpenStack Network API v2.0 Reference for description of
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
-public class Neutron_IPs implements Serializable {
+public class Neutron_IPs extends ConfigurationObject implements Serializable {
private static final long serialVersionUID = 1L;
// See OpenStack Network API v2.0 Reference for description of
</plugins>
</build>
<dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>containermanager</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>switchmanager</artifactId>
<artifactId>bundlescanner</artifactId>
</dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- </dependency>
-
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </dependency>
-
- <dependency>
+ <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</plugins>
</build>
<dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
<instructions>
<Import-Package>
org.opendaylight.controller.forwardingrulesmanager,
- org.opendaylight.controller.containermanager,
org.opendaylight.controller.sal.core,
org.opendaylight.controller.sal.flowprogrammer, org.slf4j,
org.opendaylight.controller.sal.reader,
<groupId>org.opendaylight.controller</groupId>
<artifactId>sal</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>containermanager</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>forwardingrulesmanager</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>clustering.services</artifactId>
- </dependency>
</dependencies>
</project>
<instructions>
<Import-Package>
org.opendaylight.controller.clustering.services,
- org.opendaylight.controller.containermanager,
org.opendaylight.controller.sal.core,
org.opendaylight.controller.sal.flowprogrammer,
org.opendaylight.controller.sal.reader,
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>containermanager</artifactId>
+ <artifactId>sal.connection</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>switchmanager</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>commons.logback_settings</artifactId>
- </dependency>
</dependencies>
</project>
org.opendaylight.controller.switchmanager
</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
+ javax.xml.bind.annotation
</Import-Package>
</instructions>
<manifestLocation>${project.basedir}/META-INF</manifestLocation>
</plugins>
</build>
<dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>clustering.services</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>configuration</artifactId>
import java.util.ArrayList;
import java.util.List;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.core.NodeConnector;
import org.opendaylight.controller.sal.utils.GUIField;
/**
* The class represents a Span Port configuration for a network node.
*/
-public class SpanConfig implements Serializable {
+public class SpanConfig extends ConfigurationObject implements Serializable {
protected static final Logger logger = LoggerFactory
.getLogger(SpanConfig.class);
private static final long serialVersionUID = 1L;
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
SpanConfig other = (SpanConfig) obj;
if (nodeId == null) {
- if (other.nodeId != null)
+ if (other.nodeId != null) {
return false;
- } else if (!nodeId.equals(other.nodeId))
+ }
+ } else if (!nodeId.equals(other.nodeId)) {
return false;
+ }
if (spanPort == null) {
- if (other.spanPort != null)
+ if (other.spanPort != null) {
return false;
- } else if (!spanPort.equals(other.spanPort))
+ }
+ } else if (!spanPort.equals(other.spanPort)) {
return false;
+ }
return true;
}
import java.util.HashMap;
import java.util.Map;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.sal.core.Description;
import org.opendaylight.controller.sal.core.ForwardingMode;
import org.opendaylight.controller.sal.core.Property;
/**
* The class describes a switch configuration
*/
-public class SwitchConfig implements Cloneable, Serializable {
+public class SwitchConfig extends ConfigurationObject implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private final String nodeId;
private final Map<String, Property> nodeProperties;
<Export-Package>
</Export-Package>
<Import-Package>
+ org.opendaylight.controller.configuration,
org.opendaylight.controller.switchmanager,
org.opendaylight.controller.clustering.services,
- org.opendaylight.controller.configuration,
org.opendaylight.controller.sal.core,
org.opendaylight.controller.sal.utils,
org.opendaylight.controller.sal.packet,
<dependencies>
<dependency>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>clustering.services</artifactId>
+ <artifactId>configuration</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
- <artifactId>configuration</artifactId>
+ <artifactId>clustering.services</artifactId>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
</dependency>
<dependency>
<groupId>equinoxSDK381</groupId>
- <artifactId>org.apache.felix.gogo.runtime</artifactId>
+ <artifactId>org.eclipse.osgi</artifactId>
</dependency>
<dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>commons.logback_settings</artifactId>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.apache.felix.gogo.runtime</artifactId>
</dependency>
</dependencies>
</project>
import org.apache.felix.dm.Component;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
import org.opendaylight.controller.sal.inventory.IInventoryService;
import org.opendaylight.controller.sal.inventory.IListenInventoryUpdates;
IClusterContainerServices.class).setCallbacks(
"setClusterContainerService",
"unsetClusterContainerService").setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
}
}
import org.opendaylight.controller.clustering.services.CacheExistException;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.sal.core.Bandwidth;
import org.opendaylight.controller.sal.core.Config;
import org.opendaylight.controller.sal.core.ConstructionException;
import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.HexEncode;
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.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.statisticsmanager.IStatisticsManager;
public class SwitchManager implements ISwitchManager, IConfigurationContainerAware,
IObjectReader, IListenInventoryUpdates, CommandProvider {
private static Logger log = LoggerFactory.getLogger(SwitchManager.class);
- private static String ROOT = GlobalConstants.STARTUPHOME.toString();
- private String subnetFileName, spanFileName, switchConfigFileName;
+ private static final String SUBNETS_FILE_NAME = "subnets.conf";
+ private static final String SPAN_FILE_NAME = "spanPorts.conf";
+ private static final String SWITCH_CONFIG_FILE_NAME = "switchConfig.conf";
private final List<NodeConnector> spanNodeConnectors = new CopyOnWriteArrayList<NodeConnector>();
// Collection of Subnets keyed by the InetAddress
private ConcurrentMap<InetAddress, Subnet> subnets;
private ConcurrentMap<String, Property> controllerProps;
private IInventoryService inventoryService;
private IStatisticsManager statisticsManager;
+ private IConfigurationContainerService configurationService;
private final Set<ISwitchManagerAware> switchManagerAware = Collections
.synchronizedSet(new HashSet<ISwitchManagerAware>());
private final Set<IInventoryListener> inventoryListeners = Collections
* only subnet returned. As soon as a user-configured subnet is created this one will
* vanish.
*/
- protected static SubnetConfig DEFAULT_SUBNETCONFIG;
- protected static Subnet DEFAULT_SUBNET;
- protected static String DEFAULT_SUBNET_NAME = "default (cannot be modifed)";
+ protected static final SubnetConfig DEFAULT_SUBNETCONFIG;
+ protected static final Subnet DEFAULT_SUBNET;
+ protected static final String DEFAULT_SUBNET_NAME = "default (cannot be modifed)";
static{
DEFAULT_SUBNETCONFIG = new SubnetConfig(DEFAULT_SUBNET_NAME, "0.0.0.0/0", new ArrayList<String>());
DEFAULT_SUBNET = new Subnet(DEFAULT_SUBNETCONFIG);
}
public void startUp() {
- String container = this.getContainerName();
- // Initialize configuration file names
- subnetFileName = ROOT + "subnets_" + container + ".conf";
- spanFileName = ROOT + "spanPorts_" + container + ".conf";
- switchConfigFileName = ROOT + "switchConfig_" + container + ".conf";
-
// Instantiate cluster synced variables
allocateCaches();
retrieveCaches();
- /*
- * Read startup and build database if we are the coordinator
- */
- if ((clusterContainerService != null) && (clusterContainerService.amICoordinator())) {
- loadSubnetConfiguration();
- loadSpanConfiguration();
- loadSwitchConfiguration();
- }
-
// Add controller MAC, if first node in the cluster
if (!controllerProps.containsKey(MacAddress.name)) {
byte controllerMac[] = getHardwareMAC();
if (controllerMac != null) {
Property existing = controllerProps.putIfAbsent(MacAddress.name, new MacAddress(controllerMac));
if (existing == null && log.isTraceEnabled()) {
- log.trace("Container {}: Setting controller MAC address in the cluster: {}", container,
+ log.trace("Container {}: Setting controller MAC address in the cluster: {}", getContainerName(),
HexEncode.bytesToHexStringFormat(controllerMac));
}
}
@Override
public List<Switch> getNetworkDevices() {
- Set<Node> nodeSet = getNodes();
List<Switch> swList = new ArrayList<Switch>();
- if (nodeSet != null) {
- for (Node node : nodeSet) {
- swList.add(getSwitchByNode(node));
- }
+ for (Node node : getNodes()) {
+ swList.add(getSwitchByNode(node));
}
-
return swList;
}
return ois.readObject();
}
- @SuppressWarnings("unchecked")
private void loadSubnetConfiguration() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, SubnetConfig> confList = (ConcurrentMap<String, SubnetConfig>) objReader
- .read(this, subnetFileName);
-
- if (confList == null) {
- return;
- }
-
- for (SubnetConfig conf : confList.values()) {
- addSubnet(conf);
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, SUBNETS_FILE_NAME)) {
+ addSubnet((SubnetConfig) conf);
}
}
- @SuppressWarnings("unchecked")
private void loadSpanConfiguration() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<Integer, SpanConfig> confList = (ConcurrentMap<Integer, SpanConfig>) objReader
- .read(this, spanFileName);
-
- if (confList == null) {
- return;
- }
-
- for (SpanConfig conf : confList.values()) {
- addSpanConfig(conf);
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, SPAN_FILE_NAME)) {
+ addSpanConfig((SpanConfig) conf);
}
}
- @SuppressWarnings("unchecked")
private void loadSwitchConfiguration() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, SwitchConfig> confList = (ConcurrentMap<String, SwitchConfig>) objReader
- .read(this, switchConfigFileName);
-
- if (confList == null) {
- return;
- }
-
- for (SwitchConfig conf : confList.values()) {
- updateNodeConfig(conf);
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, SWITCH_CONFIG_FILE_NAME)) {
+ updateNodeConfig((SwitchConfig) conf);
}
}
}
public Status saveSwitchConfigInternal() {
- Status retS = null, retP = null;
- ObjectWriter objWriter = new ObjectWriter();
-
- retS = objWriter.write(new ConcurrentHashMap<String, SubnetConfig>(
- subnetsConfigList), subnetFileName);
- retP = objWriter.write(new ConcurrentHashMap<SpanConfig, SpanConfig>(
- spanConfigList), spanFileName);
- retS = objWriter.write(new ConcurrentHashMap<String, SwitchConfig>(
- nodeConfigList), switchConfigFileName);
- if (retS.equals(retP)) {
- if (retS.isSuccess()) {
- return retS;
- } else {
- return new Status(StatusCode.INTERNALERROR, "Save failed");
- }
+ Status status;
+ short number = 0;
+ status = configurationService.persistConfiguration(
+ new ArrayList<ConfigurationObject>(subnetsConfigList.values()), SUBNETS_FILE_NAME);
+ if (status.isSuccess()) {
+ number++;
+ } else {
+ log.warn("Failed to save subnet gateway configurations: " + status.getDescription());
+ }
+ status = configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(spanConfigList.values()),
+ SPAN_FILE_NAME);
+ if (status.isSuccess()) {
+ number++;
} else {
+ log.warn("Failed to save span port configurations: " + status.getDescription());
+ }
+ status = configurationService.persistConfiguration(new ArrayList<ConfigurationObject>(nodeConfigList.values()),
+ SWITCH_CONFIG_FILE_NAME);
+ if (status.isSuccess()) {
+ number++;
+ } else {
+ log.warn("Failed to save node configurations: " + status.getDescription());
+ }
+ if (number == 0) {
+ return new Status(StatusCode.INTERNALERROR, "Save failed");
+ }
+ if (number < 3) {
return new Status(StatusCode.INTERNALERROR, "Partial save failure");
}
+ return status;
}
@Override
isDefaultContainer = containerName.equals(GlobalConstants.DEFAULT
.toString());
- startUp();
}
/**
*
*/
void start() {
+ startUp();
+
+ /*
+ * Read startup and build database if we are the coordinator
+ */
+ loadSubnetConfiguration();
+ loadSpanConfiguration();
+ loadSwitchConfiguration();
+
// OSGI console
registerWithOSGIConsole();
}
void stop() {
}
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ log.trace("Got configuration service set request {}", service);
+ this.configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ log.trace("Got configuration service UNset request");
+ this.configurationService = null;
+ }
+
public void setInventoryService(IInventoryService service) {
log.trace("Got inventory service set request {}", service);
this.inventoryService = service;
if (configuredNotConnectedNodes != null) {
for (Node node : configuredNotConnectedNodes) {
Switch sw = getSwitchByNode(node);
- if (sw != null) {
- configuredNotConnectedSwitches.add(sw);
- }
+ configuredNotConnectedSwitches.add(sw);
}
}
return configuredNotConnectedSwitches;
<groupId>org.opendaylight.controller</groupId>
<artifactId>configuration.implementation</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>hosttracker</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>hosttracker.implementation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>topologymanager</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>protocol_plugins.stub</artifactId>
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.sal.core.NodeConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
-public class TopologyUserLinkConfig implements Serializable {
+public class TopologyUserLinkConfig extends ConfigurationObject implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(TopologyUserLinkConfig.class);
private String name;
+ @Override
public String toString() {
return name;
}
public static STATUS fromString(String str) {
- if (str == null)
+ if (str == null) {
return LINKDOWN;
- if (str.equals(SUCCESS.toString()))
+ }
+ if (str.equals(SUCCESS.toString())) {
return SUCCESS;
- if (str.equals(LINKDOWN.toString()))
+ }
+ if (str.equals(LINKDOWN.toString())) {
return LINKDOWN;
- if (str.equals(INCORRECT.toString()))
+ }
+ if (str.equals(INCORRECT.toString())) {
return INCORRECT;
+ }
return LINKDOWN;
}
}
}
public boolean isValidNodeConnector(String nodeConnectorStr) {
- NodeConnector nc = NodeConnector.fromString(nodeConnectorStr);
- if (nc == null) return false;
- return true;
+ return (NodeConnector.fromString(nodeConnectorStr) != null);
}
public boolean isValid() {
- if (name == null || srcNodeConnector == null || dstNodeConnector == null) {
+ if (!isValidResourceName(name)) {
+ logger.debug("Invalid name in user link: {}", name);
return false;
}
if (!isValidNodeConnector(srcNodeConnector) ||
!isValidNodeConnector(dstNodeConnector)) {
- logger.debug("Invalid NodeConnector in user link: {}", this);
+ logger.debug("Invalid NodeConnector in user link: {}", name);
return false;
}
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
TopologyUserLinkConfig other = (TopologyUserLinkConfig) obj;
if (dstNodeConnector == null) {
- if (other.dstNodeConnector != null)
+ if (other.dstNodeConnector != null) {
return false;
- } else if (!dstNodeConnector.equals(other.dstNodeConnector))
+ }
+ } else if (!dstNodeConnector.equals(other.dstNodeConnector)) {
return false;
+ }
if (srcNodeConnector == null) {
- if (other.srcNodeConnector != null)
+ if (other.srcNodeConnector != null) {
return false;
- } else if (!srcNodeConnector.equals(other.srcNodeConnector))
+ }
+ } else if (!srcNodeConnector.equals(other.srcNodeConnector)) {
return false;
+ }
return true;
}
import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
import org.opendaylight.controller.sal.topology.IListenTopoUpdates;
import org.opendaylight.controller.sal.topology.ITopologyService;
IClusterContainerServices.class).setCallbacks(
"setClusterContainerService",
"unsetClusterContainerService").setRequired(true));
+
+ c.add(createContainerServiceDependency(containerName).setService(
+ IConfigurationContainerService.class).setCallbacks(
+ "setConfigurationContainerService",
+ "unsetConfigurationContainerService").setRequired(true));
}
}
}
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.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
import org.opendaylight.controller.sal.core.Edge;
import org.opendaylight.controller.sal.core.Host;
import org.opendaylight.controller.sal.core.Node;
import org.opendaylight.controller.sal.topology.IListenTopoUpdates;
import org.opendaylight.controller.sal.topology.ITopologyService;
import org.opendaylight.controller.sal.topology.TopoEdgeUpdate;
-import org.opendaylight.controller.sal.utils.GlobalConstants;
import org.opendaylight.controller.sal.utils.IObjectReader;
import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
-import org.opendaylight.controller.sal.utils.ObjectReader;
-import org.opendaylight.controller.sal.utils.ObjectWriter;
import org.opendaylight.controller.sal.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.switchmanager.ISwitchManager;
protected static final String TOPOHOSTSDB = "topologymanager.hostsDB";
protected static final String TOPONODECONNECTORDB = "topologymanager.nodeConnectorDB";
protected static final String TOPOUSERLINKSDB = "topologymanager.userLinksDB";
+ private static final String USER_LINKS_FILE_NAME = "userTopology.conf";
private static final Logger log = LoggerFactory.getLogger(TopologyManagerImpl.class);
private ITopologyService topoService;
private IClusterContainerServices clusterContainerService;
+ private IConfigurationContainerService configurationService;
private ISwitchManager switchManager;
// DB of all the Edges with properties which constitute our topology
private ConcurrentMap<Edge, Set<Property>> edgesDB;
// Topology Manager Aware listeners - for clusterwide updates
private Set<ITopologyManagerClusterWideAware> topologyManagerClusterWideAware =
new CopyOnWriteArraySet<ITopologyManagerClusterWideAware>();
- private static String ROOT = GlobalConstants.STARTUPHOME.toString();
- private String userLinksFileName;
private ConcurrentMap<String, TopologyUserLinkConfig> userLinksDB;
private BlockingQueue<TopoEdgeUpdate> notifyQ = new LinkedBlockingQueue<TopoEdgeUpdate>();
private volatile Boolean shuttingDown = false;
}
}
+ public void setConfigurationContainerService(IConfigurationContainerService service) {
+ log.trace("Got configuration service set request {}", service);
+ this.configurationService = service;
+ }
+
+ public void unsetConfigurationContainerService(IConfigurationContainerService service) {
+ log.trace("Got configuration service UNset request");
+ this.configurationService = null;
+ }
+
void setSwitchManager(ISwitchManager s) {
log.debug("Adding ISwitchManager: {}", s);
this.switchManager = s;
containerName = "UNKNOWN";
}
- userLinksFileName = ROOT + "userTopology_" + containerName + ".conf";
registerWithOSGIConsole();
- if ((clusterContainerService != null) && (clusterContainerService.amICoordinator())) {
- loadConfiguration();
- }
+ loadConfiguration();
+
// Restore the shuttingDown status on init of the component
shuttingDown = false;
notifyThread = new Thread(new TopologyNotify(notifyQ));
notifyThread = null;
}
- @SuppressWarnings("unchecked")
private void loadConfiguration() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, TopologyUserLinkConfig> confList =
- (ConcurrentMap<String, TopologyUserLinkConfig>) objReader.read(this, userLinksFileName);
-
- if (confList != null) {
- for (TopologyUserLinkConfig conf : confList.values()) {
- addUserLink(conf);
- }
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, USER_LINKS_FILE_NAME)) {
+ addUserLink((TopologyUserLinkConfig) conf);
}
}
}
public Status saveConfigInternal() {
- ObjectWriter objWriter = new ObjectWriter();
-
- Status saveStatus = objWriter.write(
- new ConcurrentHashMap<String, TopologyUserLinkConfig>(userLinksDB), userLinksFileName);
+ Status saveStatus = configurationService.persistConfiguration(
+ new ArrayList<ConfigurationObject>(userLinksDB.values()), USER_LINKS_FILE_NAME);
- if (! saveStatus.isSuccess()) {
+ if (!saveStatus.isSuccess()) {
return new Status(StatusCode.INTERNALERROR, "Topology save failed: " + saveStatus.getDescription());
}
return saveStatus;
<configuration>
<instructions>
<Import-Package>
- org.opendaylight.controller.clustering.services,
org.opendaylight.controller.configuration,
org.opendaylight.controller.sal.authorization,
org.opendaylight.controller.sal.core,
org.opendaylight.controller.sal.packet,
org.opendaylight.controller.sal.utils,
- org.opendaylight.controller.containermanager,
org.slf4j,
org.eclipse.osgi.framework.console,
org.osgi.framework,
org.apache.felix.dm,
- org.apache.commons.lang3.builder,
org.apache.commons.logging,
javax.servlet,
javax.servlet.http,
org.springframework.security.web.context,
org.springframework.security.core,
org.springframework.security.core.context,
- org.apache.commons.lang3,
org.springframework.security.authentication,
org.springframework.security.core.authority,
org.springframework.security.core.userdetails,
</plugins>
</build>
<dependencies>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>containermanager</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>clustering.services</artifactId>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>configuration</artifactId>
<artifactId>javax.servlet</artifactId>
</dependency>
<!-- Spring security -->
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-config</artifactId>
- </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-taglibs</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>org.springframework.transaction</artifactId>
- </dependency>
</dependencies>
</project>
import java.io.Serializable;
+import org.opendaylight.controller.configuration.ConfigurationObject;
+
/**
* Configuration Java Object which represents a Remote AAA server configuration
* information for User Manager.
*/
-public class ServerConfig implements Serializable {
+public class ServerConfig extends ConfigurationObject implements Serializable {
private static final long serialVersionUID = 1L;
// Order matters: JSP file expects following fields in the following order
@Override
public boolean equals(Object obj) {
- if (this == obj)
+ if (this == obj) {
return true;
- if (obj == null)
+ }
+ if (obj == null) {
return false;
- if (getClass() != obj.getClass())
+ }
+ if (getClass() != obj.getClass()) {
return false;
+ }
ServerConfig other = (ServerConfig) obj;
if (ip == null) {
- if (other.ip != null)
+ if (other.ip != null) {
return false;
- } else if (!ip.equals(other.ip))
+ }
+ } else if (!ip.equals(other.ip)) {
return false;
+ }
if (protocol == null) {
- if (other.protocol != null)
+ if (other.protocol != null) {
return false;
- } else if (!protocol.equals(other.protocol))
+ }
+ } else if (!protocol.equals(other.protocol)) {
return false;
+ }
if (secret == null) {
- if (other.secret != null)
+ if (other.secret != null) {
return false;
- } else if (!secret.equals(other.secret))
+ }
+ } else if (!secret.equals(other.secret)) {
return false;
+ }
return true;
}
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.sal.authorization.AuthResultEnum;
import org.opendaylight.controller.sal.packet.BitBufferHelper;
import org.opendaylight.controller.sal.utils.HexEncode;
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
-public class UserConfig implements Serializable {
+public class UserConfig extends ConfigurationObject implements Serializable {
private static final long serialVersionUID = 1L;
private static Logger log = LoggerFactory.getLogger(UserConfig.class);
private static final boolean strongPasswordCheck = Boolean.getBoolean("enableStrongPasswordCheck");
<configuration>
<instructions>
<Import-Package>
- org.opendaylight.controller.clustering.services,
org.opendaylight.controller.configuration,
+ org.opendaylight.controller.clustering.services,
org.opendaylight.controller.sal.authorization,
org.opendaylight.controller.sal.core,
org.opendaylight.controller.sal.packet,
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
+
</dependencies>
</project>
import org.apache.felix.dm.Component;
import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
import org.opendaylight.controller.configuration.IConfigurationAware;
+import org.opendaylight.controller.configuration.IConfigurationService;
import org.opendaylight.controller.containermanager.IContainerAuthorization;
import org.opendaylight.controller.sal.authorization.IResourceAuthorization;
import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
"setClusterGlobalService", "unsetClusterGlobalService")
.setRequired(true));
+ c.add(createServiceDependency().setService(
+ IConfigurationService.class).setCallbacks(
+ "setConfigurationService",
+ "unsetConfigurationService").setRequired(true));
+
c.add(createServiceDependency().setService(IAAAProvider.class)
.setCallbacks("addAAAProvider", "removeAAAProvider")
.setRequired(false));
import org.opendaylight.controller.clustering.services.CacheExistException;
import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.ConfigurationObject;
import org.opendaylight.controller.configuration.IConfigurationAware;
+import org.opendaylight.controller.configuration.IConfigurationService;
import org.opendaylight.controller.containermanager.IContainerAuthorization;
import org.opendaylight.controller.sal.authorization.AuthResultEnum;
import org.opendaylight.controller.sal.authorization.IResourceAuthorization;
import org.opendaylight.controller.sal.authorization.UserLevel;
-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.utils.Status;
import org.opendaylight.controller.sal.utils.StatusCode;
import org.opendaylight.controller.usermanager.AuthResponse;
private static final String DEFAULT_ADMIN = "admin";
private static final String DEFAULT_ADMIN_PASSWORD = "admin";
private static final String DEFAULT_ADMIN_ROLE = UserLevel.NETWORKADMIN.toString();
- private static final String ROOT = GlobalConstants.STARTUPHOME.toString();
- private static final String USERS_FILE_NAME = ROOT + "users.conf";
- private static final String SERVERS_FILE_NAME = ROOT + "servers.conf";
- private static final String AUTH_FILE_NAME = ROOT + "authorization.conf";
- private static final String RECOVERY_FILE = ROOT + "NETWORK_ADMIN_PASSWORD_RECOVERY";
+ private static final String USERS_FILE_NAME = "users.conf";
+ private static final String SERVERS_FILE_NAME = "servers.conf";
+ private static final String AUTH_FILE_NAME = "authorization.conf";
+ private static final String RECOVERY_FILE = "NETWORK_ADMIN_PASSWORD_RECOVERY";
private ConcurrentMap<String, UserConfig> localUserConfigList;
private ConcurrentMap<String, ServerConfig> remoteServerConfigList;
// local authorization info for remotely authenticated users
private ConcurrentMap<String, AuthenticatedUser> activeUsers;
private ConcurrentMap<String, IAAAProvider> authProviders;
private IClusterGlobalServices clusterGlobalService = null;
+ private IConfigurationService configurationService;
private SecurityContextRepository securityContextRepo = new UserSecurityContextRepository();
private IContainerAuthorization containerAuthorizationClient;
private Set<IResourceAuthorization> applicationAuthorizationClients;
/*
* Do not load local startup file if we are not the coordinator
*/
- if ((clusterGlobalService != null) && (clusterGlobalService.amICoordinator())) {
- loadUserConfig();
- loadServerConfig();
- loadAuthConfig();
- }
+ loadUserConfig();
+ loadServerConfig();
+ loadAuthConfig();
}
private void loadSecurityKeys() {
}
private Status saveLocalUserListInternal() {
- ObjectWriter objWriter = new ObjectWriter();
- return objWriter.write(new ConcurrentHashMap<String, UserConfig>(
- localUserConfigList), USERS_FILE_NAME);
+ return configurationService.persistConfiguration(
+ new ArrayList<ConfigurationObject>(localUserConfigList.values()), USERS_FILE_NAME);
}
@Override
}
private Status saveAAAServerListInternal() {
- ObjectWriter objWriter = new ObjectWriter();
- return objWriter.write(new ConcurrentHashMap<String, ServerConfig>(
- remoteServerConfigList), SERVERS_FILE_NAME);
+ return configurationService.persistConfiguration(
+ new ArrayList<ConfigurationObject>(remoteServerConfigList.values()), SERVERS_FILE_NAME);
}
@Override
}
private Status saveAuthorizationListInternal() {
- ObjectWriter objWriter = new ObjectWriter();
- return objWriter.write(
- new ConcurrentHashMap<String, AuthorizationConfig>(
- authorizationConfList), AUTH_FILE_NAME);
+ return configurationService.persistConfiguration(
+ new ArrayList<ConfigurationObject>(authorizationConfList.values()), AUTH_FILE_NAME);
}
@Override
return ois.readObject();
}
- @SuppressWarnings("unchecked")
private void loadUserConfig() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, UserConfig> confList = (ConcurrentMap<String, UserConfig>) objReader
- .read(this, USERS_FILE_NAME);
-
- if (confList == null) {
- return;
- }
-
- for (UserConfig conf : confList.values()) {
- addRemoveLocalUserInternal(conf, false);
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, USERS_FILE_NAME)) {
+ addRemoveLocalUserInternal((UserConfig) conf, false);
}
}
- @SuppressWarnings("unchecked")
private void loadServerConfig() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, ServerConfig> confList = (ConcurrentMap<String, ServerConfig>) objReader
- .read(this, SERVERS_FILE_NAME);
-
- if (confList == null) {
- return;
- }
-
- for (ServerConfig conf : confList.values()) {
- addAAAServer(conf);
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, SERVERS_FILE_NAME)) {
+ addAAAServer((ServerConfig) conf);
}
}
- @SuppressWarnings("unchecked")
private void loadAuthConfig() {
- ObjectReader objReader = new ObjectReader();
- ConcurrentMap<String, AuthorizationConfig> confList = (ConcurrentMap<String, AuthorizationConfig>) objReader
- .read(this, AUTH_FILE_NAME);
-
- if (confList == null) {
- return;
- }
-
- for (AuthorizationConfig conf : confList.values()) {
- addAuthInfo(conf);
+ for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, AUTH_FILE_NAME)) {
+ addAuthInfo((AuthorizationConfig) conf);
}
}
}
}
+ public void setConfigurationService(IConfigurationService service) {
+ logger.trace("Got configuration service set request {}", service);
+ this.configurationService = service;
+ }
+
+ public void unsetConfigurationService(IConfigurationService service) {
+ logger.trace("Got configuration service UNset request");
+ this.configurationService = null;
+ }
+
void unsetContainerAuthClient(IContainerAuthorization s) {
if (this.containerAuthorizationClient == s) {
this.containerAuthorizationClient = null;
<packaging>pom</packaging>
<modules>
<module>opendaylight/distribution/opendaylight</module>
- <module>opendaylight/archetypes</module>
<module>opendaylight/forwarding/staticrouting</module>
<module>opendaylight/clustering/services</module>
<module>opendaylight/clustering/services_implementation</module>
<!-- <module>third-party/net.sf.jung2</module> -->
<!-- <module>third-party/jersey-servlet</module> -->
<!-- <module>third-party/org.apache.catalina.filters.CorsFilter</module> -->
- <!-- <module>third-party/ganymed</module> -->
+ <module>third-party/ganymed</module>
<module>third-party/commons/thirdparty</module>