org.opendaylight.controller.sal.core,
org.opendaylight.controller.sal.utils,
org.opendaylight.controller.sal.packet,
+ org.opendaylight.controller.sal.routing,
org.opendaylight.controller.switchmanager,
org.opendaylight.controller.topologymanager,
org.opendaylight.controller.clustering.services,
import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
import org.opendaylight.controller.sal.packet.IDataPacketService;
import org.opendaylight.controller.sal.packet.IListenDataPacket;
+import org.opendaylight.controller.sal.routing.IRouting;
import org.opendaylight.controller.switchmanager.ISwitchManager;
import org.opendaylight.controller.topologymanager.ITopologyManager;
import org.slf4j.Logger;
"setClusterContainerService", "unsetClusterContainerService")
.setRequired(true));
+ c.add(createContainerServiceDependency(containerName).setService(
+ IRouting.class).setCallbacks("setRouting","unsetRouting")
+ .setRequired(false));
+
// the Host Listener is optional
c.add(createContainerServiceDependency(containerName).setService(
IfHostListener.class).setCallbacks("setHostListener",
import org.opendaylight.controller.sal.packet.Packet;
import org.opendaylight.controller.sal.packet.PacketResult;
import org.opendaylight.controller.sal.packet.RawPacket;
+import org.opendaylight.controller.sal.routing.IRouting;
import org.opendaylight.controller.sal.utils.EtherTypes;
import org.opendaylight.controller.sal.utils.HexEncode;
import org.opendaylight.controller.sal.utils.NetUtils;
private ISwitchManager switchManager;
private ITopologyManager topologyManager;
private IDataPacketService dataPacketService;
+ private IRouting routing;
private IClusterContainerServices clusterContainerService;
private IConnectionManager connectionManager;
private Set<IfHostListener> hostListeners = new CopyOnWriteArraySet<IfHostListener>();
}
}
+ void setRouting(IRouting r) {
+ this.routing = r;
+ }
+
+ void unsetRouting(IRouting r) {
+ if (this.routing == r) {
+ this.routing = null;
+ }
+ }
+
void setHostListener(IfHostListener s) {
if (this.hostListeners != null) {
this.hostListeners.add(s);
if (host == null) {
// if we don't, know about the host, try to find it
- log.trace("Punted IP pkt from {}, sending bcast ARP event...",
+ log.trace("Punted IP pkt to {}, sending bcast ARP event...",
dIP);
/*
* unknown destination host, initiate bcast ARP request
*/
arpRequestReplyEvent.put(new ARPRequest(dIP, subnet), false);
- }else{
- // we know about the host, send the packet the right place
+ } else if (routing == null ||
+ routing.getRoute(p.getNode(), host.getnodeconnectorNode()) != null) {
+ /* if IRouting is available, make sure that this packet can get it's
+ * destination normally before teleporting it there. If it's not
+ * available, then assume it's reachable.
+ *
+ * TODO: come up with a way to do this in the absence of IRouting
+ */
+
+ log.trace("forwarding punted IP pkt to {} received at {}", dIP, p);
+
+ /* if we know where the host is and there's a path from where this
+ * packet was punted to where the host is, then deliver it to the
+ * host for now */
NodeConnector nc = host.getnodeConnector();
// re-encode the Ethernet packet (the parent of the IPv4 packet)
RawPacket rp = this.dataPacketService.encodeDataPacket(pkt.getParent());
rp.setOutgoingNodeConnector(nc);
this.dataPacketService.transmitDataPacket(rp);
+ } else {
+ log.trace("ignoring punted IP pkt to {} because there is no route from {}",
+ dIP, p);
}
}
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>commons.logback_settings</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.parent</artifactId>
+ <version>1.0.1-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+</project>
<artifactId>jolokia-osgi</artifactId>
<version>${jolokia.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>properties-maven-plugin</artifactId>
- <version>${propertymavenplugin.version}</version>
- <executions>
- <execution>
- <goals>
- <goal>set-system-properties</goal>
- </goals>
- <configuration>
- <properties>
- <property>
- <name>logback.configurationFile</name>
- <value>${project.parent.basedir}/logback.xml</value>
- </property>
- </properties>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>com.googlecode.maven-java-formatter-plugin</groupId>
- <artifactId>maven-java-formatter-plugin</artifactId>
- <version>0.3.1</version>
- <configuration>
- <compilerSource>1.6</compilerSource>
- <compilerCompliance>1.6</compilerCompliance>
- <compilerTargetPlatform>1.6</compilerTargetPlatform>
- <configFile>${project.parent.basedir}/sun_coding_style.xml</configFile>
- </configuration>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>${failsafe.version}</version>
<configuration>
<argLine>${testvm.argLine}</argLine>
+ <systemProperties>
+ <property>
+ <name>logback.configurationFile</name>
+ <value>logback.xml</value>
+ </property>
+ </systemProperties>
</configuration>
<executions>
<execution>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
+ <configuration>
+ <systemProperties>
+ <property>
+ <name>logback.configurationFile</name>
+ <value>logback.xml</value>
+ </property>
+ </systemProperties>
+ </configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
</goals>
</execution>
</executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
+++ /dev/null
-<configuration scan="true">
-
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
- <encoder>
- <pattern>%date{"yyyy-MM-dd HH:mm:ss.SSS z"} [%thread] %-5level %logger{36} - %msg%n</pattern>
- </encoder>
- </appender>
-
- <root level="error">
- <appender-ref ref="STDOUT" />
- </root>
-</configuration>
+++ /dev/null
-<?xml version="1.0"?>\r
-<!DOCTYPE module PUBLIC\r
- "-//Puppy Crawl//DTD Check Configuration 1.2//EN"\r
- "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">\r
-\r
-<module name="Checker">\r
- <module name="FileTabCharacter">\r
- <property name="eachLine" value="true"/>\r
- </module>\r
-\r
- <module name="RegexpSingleline">\r
- <!-- \s matches whitespace character, $ matches end of line. -->\r
- <property name="format" value="\s+$"/>\r
- <property name="message" value="Line has trailing spaces."/>\r
- </module>\r
-\r
-</module>\r
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-subsystem</artifactId>
+ <version>0.2.3-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>netty-event-executor-config</artifactId>
+ <description>Configuration Wrapper around netty's event executor</description>
+ <packaging>bundle</packaging>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>threadpool-config-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+ <!--test dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-manager</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-manager</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>mockito-configuration</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Export-Package>
+ </Export-Package>
+ <Import-Package>
+ com.google.common.base,
+ org.opendaylight.controller.config.yang.threadpool,
+ io.netty.util.concurrent,
+ org.opendaylight.controller.config.api,
+ org.opendaylight.controller.config.api.annotations,
+ org.opendaylight.controller.config.api.runtime,
+ org.opendaylight.controller.config.spi,
+ org.slf4j,
+ org.osgi.framework
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <distributionManagement>
+ <site>
+ <id>${project.artifactId}</id>
+ <name>NETTY-EVENT-EXECUTOR-CONFIG Module site</name>
+ <url>${basedir}/target/site/${project.artifactId}</url>
+ </site>
+ </distributionManagement>
+
+</project>
\ No newline at end of file
--- /dev/null
+/**
+ * Generated file
+
+ * Generated from: yang module name: netty-event-executor yang module local name: netty-global-event-executor
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Tue Nov 12 10:44:21 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.controller.config.yang.netty.eventexecutor;
+
+import io.netty.util.concurrent.AbstractEventExecutor;
+import io.netty.util.concurrent.EventExecutor;
+import io.netty.util.concurrent.EventExecutorGroup;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GlobalEventExecutor;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+*
+*/
+public final class GlobalEventExecutorModule extends
+ org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModule {
+
+ public GlobalEventExecutorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public GlobalEventExecutorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ GlobalEventExecutorModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void validate() {
+ super.validate();
+ // Add custom validation for module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ return new GlobalEventExecutorCloseable(GlobalEventExecutor.INSTANCE);
+ }
+
+ static final private class GlobalEventExecutorCloseable extends AbstractEventExecutor implements AutoCloseable {
+
+ private EventExecutor executor;
+
+ public GlobalEventExecutorCloseable(EventExecutor executor) {
+ this.executor = executor;
+ }
+
+ @Override
+ public EventExecutorGroup parent() {
+ return this.executor.parent();
+ }
+
+ @Override
+ public boolean inEventLoop(Thread thread) {
+ return this.executor.inEventLoop(thread);
+ }
+
+ @Override
+ public boolean isShuttingDown() {
+ return this.executor.isShuttingDown();
+ }
+
+ @Override
+ public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
+ return this.executor.shutdownGracefully(quietPeriod, timeout, unit);
+ }
+
+ @Override
+ public Future<?> terminationFuture() {
+ return this.executor.terminationFuture();
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return this.executor.isShutdown();
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return this.executor.isTerminated();
+ }
+
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ return this.executor.awaitTermination(timeout, unit);
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ this.executor.execute(command);
+ }
+
+ @Override
+ public void close() throws Exception {
+ shutdownGracefully();
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void shutdown() {
+ this.executor.shutdown();
+ }
+
+ }
+}
--- /dev/null
+/**
+* Generated file
+
+* Generated from: yang module name: netty-event-executor yang module local name: netty-global-event-executor
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Tue Nov 12 10:44:21 CET 2013
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.netty.eventexecutor;
+
+/**
+*
+*/
+public class GlobalEventExecutorModuleFactory extends org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModuleFactory
+{
+
+
+}
--- /dev/null
+// vi: set smarttab et sw=4 tabstop=4:
+module netty-event-executor {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor";
+ prefix "netty-t";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import threadpool { prefix th; revision-date 2013-04-09; }
+
+ organization "Cisco Systems, Inc.";
+
+ contact "Milos Fabian <milfabia@cisco.com>";
+
+ description
+ "This module contains the base YANG definitions for NS-OS
+ thread-related services.
+
+ Copyright (c)2013 Cisco Systems, Inc. All rights reserved.;
+
+ This program and the accompanying materials are made available
+ under the terms of the Eclipse Public License v1.0 which
+ accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/epl-v10.html";
+
+ revision "2013-11-12" {
+ description
+ "Initial revision";
+ }
+
+ identity netty-global-event-executor {
+ base config:module-type;
+ config:provided-service th:netty-event-executor;
+ config:java-name-prefix GlobalEventExecutor;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case netty-global-event-executor {
+ when "/config:modules/config:module/config:type = 'netty-global-event-executor'";
+
+ }
+ }
+
+
+}
--- /dev/null
+package org.opendaylight.controller.config.yang.netty.eventexecutor;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+
+public class GlobalEventExecutorModuleTest extends AbstractConfigTest {
+
+ private GlobalEventExecutorModuleFactory factory;
+ private final String instanceName = "netty1";
+
+ @Before
+ public void setUp() {
+ factory = new GlobalEventExecutorModuleFactory();
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory));
+ }
+
+ @Test
+ public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,
+ ConflictingVersionException {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+ createInstance(transaction, instanceName);
+ createInstance(transaction, instanceName + 2);
+ transaction.validateConfig();
+ CommitStatus status = transaction.commit();
+
+ assertBeanCount(2, factory.getImplementationName());
+ assertStatus(status, 2, 0, 0);
+ }
+
+ @Test
+ public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,
+ ValidationException {
+
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+ createInstance(transaction, instanceName);
+
+ transaction.commit();
+
+ transaction = configRegistryClient.createTransaction();
+ assertBeanCount(1, factory.getImplementationName());
+ CommitStatus status = transaction.commit();
+
+ assertBeanCount(1, factory.getImplementationName());
+ assertStatus(status, 0, 0, 1);
+ }
+
+ private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName)
+ throws InstanceAlreadyExistsException {
+ ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+ transaction.newMBeanProxy(nameCreated, GlobalEventExecutorModuleMXBean.class);
+ return nameCreated;
+ }
+
+}
<module>threadpool-config-api</module>
<module>threadpool-config-impl</module>
<module>netty-threadgroup-config</module>
+ <module>netty-event-executor-config</module>
</modules>
<profiles>
org.opendaylight.controller.config.api.*,
com.google.common.eventbus,
io.netty.channel,
+ io.netty.util.concurrent
</Import-Package>
<Export-Package>
org.opendaylight.controller.config.threadpool,
base "config:service-type";
config:java-class "io.netty.channel.EventLoopGroup";
}
+
+ identity netty-event-executor {
+ description
+ "Configuration wrapper around netty's event executor";
+
+ base "config:service-type";
+ config:java-class "io.netty.util.concurrent.EventExecutor";
+ }
}
<artifactId>yang-jmx-generator-plugin</artifactId>
<version>${config.version}</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-jmx-generator-it</artifactId>
- <version>${config.version}</version>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>yang-store-api</artifactId>
<artifactId>yang-store-impl</artifactId>
<version>${config.version}</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>yang-test</artifactId>
- <version>${config.version}</version>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>logback-config</artifactId>
</dependency>
</dependencies>
</profile>
+ <profile>
+ <id>integrationtests</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.8</version>
+ <executions>
+ <execution>
+ <id>copy</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sanitytest</artifactId>
+ <version>${controller.version}</version>
+ <type>jar</type>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ <executions>
+ <execution>
+ <id>sanity-test</id>
+ <phase>package</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <executable>${java.home}/bin/java</executable>
+ <arguments>
+ <argument>-cp</argument>
+ <argument>./target/dependency/*</argument>
+ <argument>org.opendaylight.controller.distribution.Sanity</argument>
+ </arguments>
+ <environmentVariables>
+ <JAVA_HOME>
+ ${java.home}
+ </JAVA_HOME>
+ </environmentVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
</profiles>
<artifactId>distribution.opendaylight</artifactId>
</execution>
</executions>
</plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <version>2.8</version>
- <executions>
- <execution>
- <id>copy</id>
- <phase>package</phase>
- <goals>
- <goal>copy</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sanitytest</artifactId>
- <version>${controller.version}</version>
- <type>jar</type>
- </artifactItem>
- </artifactItems>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>exec-maven-plugin</artifactId>
- <version>1.2.1</version>
- <executions>
- <execution>
- <id>sanity-test</id>
- <phase>package</phase>
- <goals>
- <goal>exec</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <executable>${java.home}/bin/java</executable>
- <arguments>
- <argument>-cp</argument>
- <argument>./target/dependency/*</argument>
- <argument>org.opendaylight.controller.distribution.Sanity</argument>
- </arguments>
- <environmentVariables>
- <JAVA_HOME>
- ${java.home}
- </JAVA_HOME>
- </environmentVariables>
- </configuration>
- </plugin>
</plugins>
</build>
</project>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
</project>
+++ /dev/null
-<configuration scan="true">\r
-\r
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
- <encoder>\r
- <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
- </pattern>\r
- </encoder>\r
- </appender>\r
-\r
- <root level="error">\r
- <appender-ref ref="STDOUT" />\r
- </root>\r
-</configuration>\r
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
</project>
+++ /dev/null
-<configuration scan="true">\r
-\r
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
- <encoder>\r
- <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
- </pattern>\r
- </encoder>\r
- </appender>\r
-\r
- <root level="error">\r
- <appender-ref ref="STDOUT" />\r
- </root>\r
-</configuration>\r
<configuration>
<instructions>
<Export-Package>
+ org.opendaylight.controller.datastore
</Export-Package>
<Import-Package>
javax.xml.bind.annotation,
org.opendaylight.controller.sal.topology,
org.opendaylight.controller.clustering.services,
org.opendaylight.controller.md.sal.common.api.data,
+ org.opendaylight.controller.sal.common.util,
org.opendaylight.yangtools.yang.binding,
org.osgi.service.component,
org.slf4j,
org.apache.commons.lang3.builder,
org.apache.commons.lang3.tuple,
org.eclipse.osgi.framework.console,
- org.osgi.framework
+ org.osgi.framework,
+ com.google.common.base
</Import-Package>
<Bundle-Activator>
org.opendaylight.controller.datastore.internal.Activator
public static final String OPERATIONAL_DATA_CACHE = "clustered_data_store.operational_data_cache";
public static final String CONFIGURATION_DATA_CACHE = "clustered_data_store.configuration_data_cache";
- private ConcurrentMap operationalDataCache;
- private ConcurrentMap configurationDataCache;
+ private final ConcurrentMap operationalDataCache;
+ private final ConcurrentMap configurationDataCache;
public ClusteredDataStoreImpl(IClusterGlobalServices clusterGlobalServices) throws CacheExistException, CacheConfigException {
Preconditions.checkNotNull(clusterGlobalServices, "clusterGlobalServices cannot be null");
- operationalDataCache = clusterGlobalServices.createCache(OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+ operationalDataCache = getOrCreateCache(clusterGlobalServices, OPERATIONAL_DATA_CACHE);
if(operationalDataCache == null){
Preconditions.checkNotNull(operationalDataCache, "operationalDataCache cannot be null");
}
- configurationDataCache = clusterGlobalServices.createCache(CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+ configurationDataCache = getOrCreateCache(clusterGlobalServices, CONFIGURATION_DATA_CACHE);
if(configurationDataCache == null){
Preconditions.checkNotNull(configurationDataCache, "configurationDataCache cannot be null");
return Rpcs.<Void>getRpcResult(true, null, _emptySet);
}
+
+ private ConcurrentMap getOrCreateCache(IClusterGlobalServices clusterGlobalServices, String name) throws CacheConfigException {
+ ConcurrentMap cache = clusterGlobalServices.getCache(name);
+
+ if(cache == null) {
+ try {
+ cache = clusterGlobalServices.createCache(name, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+ } catch (CacheExistException e) {
+ cache = clusterGlobalServices.getCache(name);
+ }
+ }
+ return cache;
+ }
+
private class ClusteredDataStoreTransaction implements DataCommitTransaction<InstanceIdentifier<? extends Object>, Object> {
private final DataModification<InstanceIdentifier<? extends Object>,Object> modification;
}
}
+ @Test
+ public void constructor_WhenOperationalDataCacheIsAlreadyPresent_ShouldNotAttemptToCreateCache() throws CacheExistException, CacheConfigException {
+ IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
+
+ new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+ verify(mockClusterGlobalServices, never()).createCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+ }
+
+ @Test
+ public void constructor_WhenConfigurationDataCacheIsAlreadyPresent_ShouldNotAttemptToCreateCache() throws CacheExistException, CacheConfigException {
+ IClusterGlobalServices mockClusterGlobalServices = mock(IClusterGlobalServices.class);
+
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.OPERATIONAL_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
+ Mockito.<ConcurrentMap<?,?>>when(mockClusterGlobalServices.getCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE)).thenReturn(new ConcurrentHashMap<Object, Object>());
+
+ new ClusteredDataStoreImpl(mockClusterGlobalServices);
+
+ verify(mockClusterGlobalServices, never()).createCache(ClusteredDataStoreImpl.CONFIGURATION_DATA_CACHE, EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+ }
+
+
@Test
public void constructor_WhenPassedAValidClusteringServices_ShouldNotThrowAnyExceptions() throws CacheExistException, CacheConfigException {
IClusterGlobalServices mockClusterGlobalServices = createClusterGlobalServices();
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
package org.opendaylight.controller.datastore.internal;
import org.apache.felix.dm.Component;
<artifactId>clustered-datastore.integrationtest</artifactId>
<version>0.4.0-SNAPSHOT</version>
<dependencies>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>clustering.services</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>protocol_plugins.stub</artifactId>
<version>0.4.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>sal</artifactId>
- <version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>containermanager.it.implementation</artifactId>
<version>0.5.0-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>clustering.services</artifactId>
- <version>0.4.0-SNAPSHOT</version>
- </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>clustering.stub</artifactId>
<version>0.4.1-SNAPSHOT</version>
</dependency>
- </dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>concepts</artifactId>
+ <version>0.1.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>1.9.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>5.0.0</version>
+ </dependency>
+
+</dependencies>
<properties>
<!-- Sonar jacoco plugin to get integration test coverage info -->
<sonar.jacoco.reportPath>../implementation/target/jacoco.exec</sonar.jacoco.reportPath>
package org.opendaylight.controller.datastore;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.util.PathUtils;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
-import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.systemPackages;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.controller.md.sal.common.api.data.DataModification;
+import static org.mockito.Mockito.mock;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
@RunWith(PaxExam.class)
public class ClusteredDataStoreIT {
// get the OSGI bundle context
@Inject
private BundleContext bc;
-
+ @Inject
+ private ClusteredDataStore clusteredDS;
// Configure the OSGi container
@Configuration
public Option[] config() {
systemProperty("osgi.console").value("2401"),
// Set the systemPackages (used by clustering)
systemPackages("sun.reflect", "sun.reflect.misc", "sun.misc"),
+ systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("DEBUG"),
// List framework bundles
mavenBundle("equinoxSDK381", "org.eclipse.equinox.console").versionAsInProject(),
mavenBundle("equinoxSDK381", "org.eclipse.equinox.util").versionAsInProject(),
mavenBundle("org.opendaylight.controller", "protocol_plugins.stub")
.versionAsInProject(),
+ //clustered-data-store-implementation dependencies
+ mavenBundle("com.google.guava", "guava")
+ .versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "sal-common-api")
+ .versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "sal-common-util")
+ .versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "sal-common-impl")
+ .versionAsInProject(),
+ mavenBundle("org.opendaylight.yangtools", "yang-binding")
+ .versionAsInProject(),
+
+
+ //sal-common-api dependencies
+ mavenBundle("org.opendaylight.controller", "sal-common")
+ .versionAsInProject(),
+ mavenBundle("org.opendaylight.yangtools", "yang-common")
+ .versionAsInProject(),
+ mavenBundle("org.opendaylight.yangtools", "concepts")
+ .versionAsInProject(),
+ mavenBundle("org.osgi", "org.osgi.core")
+ .versionAsInProject(),
+ //adding new maven bundles
+ mavenBundle("org.mockito", "mockito-all")
+ .versionAsInProject(),
+
// needed by hosttracker
mavenBundle("org.opendaylight.controller", "clustered-datastore-implementation")
.versionAsInProject(),
}
}
+ @Before
+ public void areWeReady() {
+ assertNotNull(bc);
+ boolean debugit = false;
+ Bundle b[] = bc.getBundles();
+ for (int i = 0; i < b.length; i++) {
+ int state = b[i].getState();
+ if (state != Bundle.ACTIVE && state != Bundle.RESOLVED) {
+ log.debug("Bundle:" + b[i].getSymbolicName() + " state:"
+ + stateToString(state));
+ debugit = true;
+ }
+ }
+ if (debugit) {
+ log.debug("Do some debugging because some bundle is "
+ + "unresolved");
+ }
+ }
+
+ @Test
+ public void testBundleContextClusteredDS_NotNull() throws Exception{
+ ServiceReference serviceReference = bc.getServiceReference(ClusteredDataStore.class);
+ ClusteredDataStore store = ClusteredDataStore.class.cast(bc.getService(serviceReference));
+ assertNotNull(store);
+ }
+
+ @Test
+ public void testInjected_ClusteredDS_NotNull(){
+ assertNotNull(clusteredDS);
+ }
+
@Test
- public void testDoNothing() throws Exception{
- assertTrue(true);
+ public void requestCommit_readConfigurationData_ShouldVerifyDataAndNoException(){
+ DataModification dataModification = mock(DataModification.class);
+ HashMap map = new HashMap();
+ List list = new ArrayList();
+ list.add("key");
+ InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+ map.put(key, "value");
+ when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
+ DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+ dataCommitTrans.finish();
+ String value = (String)clusteredDS.readConfigurationData(key);
+ assertEquals("value",value);
}
+ @Test(expected = NullPointerException.class)
+ public void requestCommit_ShouldThrowException(){
+ DataModification dataModification = null;
+ DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+ dataCommitTrans.finish();
+ }
+
+ @Test
+ public void requestCommit_readOperationalData_ShouldVerifyDataAndNoException(){
+ DataModification dataModification = mock(DataModification.class);
+ HashMap map = new HashMap();
+ List list = new ArrayList();
+ list.add("key");
+ InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+ map.put(key, "value");
+ when(dataModification.getUpdatedOperationalData()).thenReturn(map);
+ DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+ dataCommitTrans.finish();
+ String value = (String)clusteredDS.readOperationalData(key);
+ assertEquals("value",value);
+ }
+
+ @Test
+ public void requestCommit_readConfigurationData_NonExistingKey_ShouldVerifyNoMappedValueAndNoException(){
+ DataModification dataModification = mock(DataModification.class);
+ HashMap map = new HashMap();
+ List list = new ArrayList();
+ list.add("key");
+ InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+ map.put(key, "value");
+ when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
+ DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+ dataCommitTrans.finish();
+ list = new ArrayList();
+ list.add("key1");
+ InstanceIdentifier key1 = new InstanceIdentifier(list,String.class);
+
+ String value = (String)clusteredDS.readConfigurationData(key1);
+ assertNull(value);
+ }
+
+ @Test
+ public void requestCommit_readOperationalData_NonExistingKey_ShouldVerifyNoMappedValueAndNoException(){
+ DataModification dataModification = mock(DataModification.class);
+ HashMap map = new HashMap();
+ List list = new ArrayList();
+ list.add("key");
+ InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+ map.put(key, "value");
+ when(dataModification.getUpdatedOperationalData()).thenReturn(map);
+ DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+ dataCommitTrans.finish();
+ list = new ArrayList();
+ list.add("key1");
+ InstanceIdentifier key1 = new InstanceIdentifier(list,String.class);
+
+ String value = (String)clusteredDS.readOperationalData(key1);
+ assertNull(value);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void requestCommit_readConfigurationData_WithNullPathShouldThrowException(){
+ DataModification dataModification = mock(DataModification.class);
+ HashMap map = new HashMap();
+ List list = new ArrayList();
+ list.add("key");
+ InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+ map.put(key, "value");
+ when(dataModification.getUpdatedConfigurationData()).thenReturn(map);
+ DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+ dataCommitTrans.finish();
+ String value = (String)clusteredDS.readConfigurationData(null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void requestCommit_readOperationalData_WithNullPathShouldThrowException(){
+ DataModification dataModification = mock(DataModification.class);
+ HashMap map = new HashMap();
+ List list = new ArrayList();
+ list.add("key");
+ InstanceIdentifier key = new InstanceIdentifier(list,String.class);
+ map.put(key, "value");
+ when(dataModification.getOriginalOperationalData()).thenReturn(map);
+ DataCommitTransaction dataCommitTrans = clusteredDS.requestCommit(dataModification);
+ dataCommitTrans.finish();
+ String value = (String)clusteredDS.readOperationalData(null);
+ }
}
<module>compatibility</module>
<module>sal-zeromq-connector</module>
- <module>test</module>
</modules>
<modules>
<module>sal-binding-it</module>
<module>clustered-data-store/integrationtest</module>
+ <module>test</module>
</modules>
</profile>
</profiles>
<build>
<pluginManagement>
<plugins>
- <!--This plugin's configuration is used to store Eclipse
- m2e settings only. It has no influence on the Maven build itself. -->
- <plugin>
- <groupId>org.eclipse.m2e</groupId>
- <artifactId>lifecycle-mapping</artifactId>
- <version>1.0.0</version>
- <configuration>
- <lifecycleMappingMetadata>
- <pluginExecutions>
- <pluginExecution>
- <pluginExecutionFilter>
- <groupId>org.jacoco</groupId>
- <artifactId>jacoco-maven-plugin</artifactId>
- <versionRange>[0.0,)</versionRange>
- <goals>
- <goal>prepare-agent</goal>
- <goal>pre-test</goal>
- <goal>post-test</goal>
- </goals>
- </pluginExecutionFilter>
- <action>
- <ignore />
- </action>
- </pluginExecution>
- </pluginExecutions>
- </lifecycleMappingMetadata>
- </configuration>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
- <groupId>
- org.opendaylight.yangtools
- </groupId>
- <artifactId>
- yang-maven-plugin
- </artifactId>
- <versionRange>
- [0.5,)
- </versionRange>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore/>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>net.alchim31.maven</groupId>
+ <artifactId>scala-maven-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
<goals>
- <goal>
- generate-sources
- </goal>
+ <goal>compile</goal>
+ <goal>testCompile</goal>
</goals>
</pluginExecutionFilter>
<action>
- <ignore></ignore>
+ <ignore/>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.jacoco</groupId>
- <artifactId>
- jacoco-maven-plugin
- </artifactId>
- <versionRange>
- [0.5.3.201107060350,)
- </versionRange>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
<goals>
<goal>prepare-agent</goal>
</goals>
</pluginExecutionFilter>
<action>
- <ignore></ignore>
+ <ignore/>
</action>
</pluginExecution>
</pluginExecutions>
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.options.DefaultCompositeOption;
+import org.ops4j.pax.exam.util.PathUtils;
import org.osgi.framework.BundleContext;
@RunWith(PaxExam.class)
public Option[] config() {
return options(systemProperty("osgi.console").value("2401"), mavenBundle("org.slf4j", "slf4j-api")
.versionAsInProject(), //
+ systemProperty("logback.configurationFile").value(
+ "file:" + PathUtils.getBaseDir()
+ + "/src/test/resources/logback.xml"),
mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), //
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import org.ops4j.pax.exam.util.PathUtils;
@RunWith(PaxExam.class)
public class ToasterTest {
@Configuration
public Option[] config() {
return options(systemProperty("osgi.console").value("2401"),
+ systemProperty("logback.configurationFile").value(
+ "file:" + PathUtils.getBaseDir()
+ + "/src/test/resources/logback.xml"),
mavenBundle("org.slf4j", "slf4j-api").versionAsInProject(), //
mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), //
mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), //
<configuration scan="true">
+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
<version>${bgpcep.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
<build>
import org.opendaylight.controller.netconf.api.NetconfMessage;
import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.util.AbstractSslChannelInitializer;
import org.opendaylight.protocol.framework.AbstractDispatcher;
import org.opendaylight.protocol.framework.ReconnectStrategy;
import org.opendaylight.protocol.framework.SessionListener;
}
private void initialize(SocketChannel ch, Promise<NetconfClientSession> promise) {
- new ClientChannelInitializer(maybeContext, negotatorFactory, sessionListener).initialize(ch, promise);
+ new ClientSslChannelInitializer(maybeContext, negotatorFactory, sessionListener).initialize(ch, promise);
}
});
}
- private static class ClientChannelInitializer extends AbstractChannelInitializer {
+ private static class ClientSslChannelInitializer extends AbstractSslChannelInitializer {
private final NetconfClientSessionNegotiatorFactory negotiatorFactory;
private final NetconfClientSessionListener sessionListener;
- private ClientChannelInitializer(Optional<SSLContext> maybeContext,
- NetconfClientSessionNegotiatorFactory negotiatorFactory, NetconfClientSessionListener sessionListener) {
+ private ClientSslChannelInitializer(Optional<SSLContext> maybeContext,
+ NetconfClientSessionNegotiatorFactory negotiatorFactory, NetconfClientSessionListener sessionListener) {
super(maybeContext);
this.negotiatorFactory = negotiatorFactory;
this.sessionListener = sessionListener;
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.client;
+
+public class NetconfSshClientDispatcher extends NetconfClientDispatcher {
+ public NetconfSshClientDispatcher() {
+ super(null);
+ }
+}
<artifactId>netconf-client</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
<build>
import io.netty.util.concurrent.Promise;
import org.opendaylight.controller.netconf.api.NetconfSession;
import org.opendaylight.controller.netconf.impl.util.DeserializerExceptionHandler;
-import org.opendaylight.controller.netconf.util.AbstractChannelInitializer;
+import org.opendaylight.controller.netconf.util.AbstractSslChannelInitializer;
import org.opendaylight.protocol.framework.AbstractDispatcher;
import javax.net.ssl.SSLContext;
public class NetconfServerDispatcher extends AbstractDispatcher<NetconfSession, NetconfServerSessionListener> {
- private final ServerChannelInitializer initializer;
+ private final ServerSslChannelInitializer initializer;
public NetconfServerDispatcher(final Optional<SSLContext> maybeContext,
NetconfServerSessionNegotiatorFactory serverNegotiatorFactory,
NetconfServerSessionListenerFactory listenerFactory) {
- this.initializer = new ServerChannelInitializer(maybeContext, serverNegotiatorFactory, listenerFactory);
+ this.initializer = new ServerSslChannelInitializer(maybeContext, serverNegotiatorFactory, listenerFactory);
}
// FIXME change headers for all new source code files
});
}
- private static class ServerChannelInitializer extends AbstractChannelInitializer {
+ private static class ServerSslChannelInitializer extends AbstractSslChannelInitializer {
private final NetconfServerSessionNegotiatorFactory negotiatorFactory;
private final NetconfServerSessionListenerFactory listenerFactory;
- private ServerChannelInitializer(Optional<SSLContext> maybeContext,
- NetconfServerSessionNegotiatorFactory negotiatorFactory,
- NetconfServerSessionListenerFactory listenerFactory) {
+ private ServerSslChannelInitializer(Optional<SSLContext> maybeContext,
+ NetconfServerSessionNegotiatorFactory negotiatorFactory,
+ NetconfServerSessionListenerFactory listenerFactory) {
super(maybeContext);
this.negotiatorFactory = negotiatorFactory;
this.listenerFactory = listenerFactory;
<artifactId>mockito-configuration</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
<build>
package org.opendaylight.controller.netconf.util;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-
-import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.api.NetconfSession;
-import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
-import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageFactory;
-import org.opendaylight.protocol.framework.ProtocolHandlerFactory;
-import org.opendaylight.protocol.framework.ProtocolMessageDecoder;
-import org.opendaylight.protocol.framework.ProtocolMessageEncoder;
-
-import com.google.common.base.Optional;
-
-import io.netty.channel.ChannelHandler;
import io.netty.channel.socket.SocketChannel;
-import io.netty.handler.ssl.SslHandler;
import io.netty.util.concurrent.Promise;
+import org.opendaylight.controller.netconf.api.NetconfSession;
public abstract class AbstractChannelInitializer {
- private final Optional<SSLContext> maybeContext;
- private final NetconfHandlerFactory handlerFactory;
-
- public AbstractChannelInitializer(Optional<SSLContext> maybeContext) {
- this.maybeContext = maybeContext;
- this.handlerFactory = new NetconfHandlerFactory(new NetconfMessageFactory());
- }
-
- public void initialize(SocketChannel ch, Promise<? extends NetconfSession> promise) {
- if (maybeContext.isPresent()) {
- initSsl(ch);
- }
-
- ch.pipeline().addLast("aggregator", new NetconfMessageAggregator(FramingMechanism.EOM));
- ch.pipeline().addLast(handlerFactory.getDecoders());
- initializeAfterDecoder(ch, promise);
- ch.pipeline().addLast("frameEncoder", FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM));
- ch.pipeline().addLast(handlerFactory.getEncoders());
- }
+ public abstract void initialize(SocketChannel ch, Promise<? extends NetconfSession> promise);
protected abstract void initializeAfterDecoder(SocketChannel ch, Promise<? extends NetconfSession> promise);
- private void initSsl(SocketChannel ch) {
- SSLEngine sslEngine = maybeContext.get().createSSLEngine();
- initSslEngine(sslEngine);
- final SslHandler handler = new SslHandler(sslEngine);
- ch.pipeline().addLast("ssl", handler);
- }
-
- protected abstract void initSslEngine(SSLEngine sslEngine);
-
- private static final class NetconfHandlerFactory extends ProtocolHandlerFactory<NetconfMessage> {
-
- public NetconfHandlerFactory(final NetconfMessageFactory msgFactory) {
- super(msgFactory);
- }
-
- @Override
- public ChannelHandler[] getEncoders() {
- return new ChannelHandler[] { new ProtocolMessageEncoder(this.msgFactory) };
- }
-
- @Override
- public ChannelHandler[] getDecoders() {
- return new ChannelHandler[] { new ProtocolMessageDecoder(this.msgFactory) };
- }
- }
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.util;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.NetconfSession;
+import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
+import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageFactory;
+import org.opendaylight.protocol.framework.ProtocolHandlerFactory;
+import org.opendaylight.protocol.framework.ProtocolMessageDecoder;
+import org.opendaylight.protocol.framework.ProtocolMessageEncoder;
+
+import com.google.common.base.Optional;
+
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.util.concurrent.Promise;
+
+public abstract class AbstractSslChannelInitializer extends AbstractChannelInitializer {
+
+ private final Optional<SSLContext> maybeContext;
+ private final NetconfHandlerFactory handlerFactory;
+
+ public AbstractSslChannelInitializer(Optional<SSLContext> maybeContext) {
+ this.maybeContext = maybeContext;
+ this.handlerFactory = new NetconfHandlerFactory(new NetconfMessageFactory());
+ }
+
+ @Override
+ public void initialize(SocketChannel ch, Promise<? extends NetconfSession> promise) {
+ if (maybeContext.isPresent()) {
+ initSsl(ch);
+ }
+
+ ch.pipeline().addLast("aggregator", new NetconfMessageAggregator(FramingMechanism.EOM));
+ ch.pipeline().addLast(handlerFactory.getDecoders());
+ initializeAfterDecoder(ch, promise);
+ ch.pipeline().addLast("frameEncoder", FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM));
+ ch.pipeline().addLast(handlerFactory.getEncoders());
+ }
+
+ private void initSsl(SocketChannel ch) {
+ SSLEngine sslEngine = maybeContext.get().createSSLEngine();
+ initSslEngine(sslEngine);
+ final SslHandler handler = new SslHandler(sslEngine);
+ ch.pipeline().addLast("ssl", handler);
+ }
+
+ protected abstract void initSslEngine(SSLEngine sslEngine);
+
+ private static final class NetconfHandlerFactory extends ProtocolHandlerFactory<NetconfMessage> {
+
+ public NetconfHandlerFactory(final NetconfMessageFactory msgFactory) {
+ super(msgFactory);
+ }
+
+ @Override
+ public ChannelHandler[] getEncoders() {
+ return new ChannelHandler[] { new ProtocolMessageEncoder(this.msgFactory) };
+ }
+
+ @Override
+ public ChannelHandler[] getDecoders() {
+ return new ChannelHandler[] { new ProtocolMessageDecoder(this.msgFactory) };
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0"?>
+<enunciate label="full" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.26.xsd">
+
+ <services> </services>
+
+ <modules>
+ <!-- Disable doc generation -->
+ <docs disabled="true"/>
+
+ <!-- Disable all the client generation tools -->
+ <basic-app disabled="true" />
+ <c disabled="true" />
+ <csharp disabled="true" />
+ <jaxws-client disabled="true" />
+ <jaxws-ri disabled="true" />
+ <jaxws-support disabled="true" />
+ <obj-c disabled="true" />
+ <ruby disabled="true"/>
+ <php disabled="true"/>
+
+ <!-- enable only the java clients -->
+ <xml disabled="false" />
+ <java-client disabled="false"/>
+ </modules>
+
+ <api-classes>
+ <include pattern="org.opendaylight.controller.**"/>
+ </api-classes>
+
+ <api-import pattern="org.opendaylight.controller.**"/>
+</enunciate>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.opendaylight</artifactId>
+ <version>1.4.1-SNAPSHOT</version>
+ <relativePath>../../commons/opendaylight</relativePath>
+ </parent>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+
+ <artifactId>northbound.client</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <properties>
+ <docs.output.dir>${project.build.directory}/rest-api-docs</docs.output.dir>
+ <java-client>${project.build.directory}/enunciate/build/java-client/full-client.jar</java-client>
+ <java-client-sources>${project.build.directory}/enunciate/build/java-client/full-client-sources.jar</java-client-sources>
+ <json-client>${project.build.directory}/enunciate/build/java-client/full-json-client.jar</json-client>
+ <json-client-sources>${project.build.directory}/enunciate/build/java-client/full-json-client-sources.jar</json-client-sources>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>maven-enunciate-plugin</artifactId>
+ <version>${enunciate.version}</version>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.5</version>
+ <executions>
+ <execution>
+ <phase>install</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <target>
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties"
+ classpathref="maven.plugin.classpath" />
+ <patternset id="rest.paths">
+ <include name="**/target/site/wsdocs/**"/>
+ <exclude name="**/java-client/**"/>
+ </patternset>
+
+ <echo message="======== Assembling enunciate docs ========"/>
+ <!-- cleanup existing generated files -->
+ <delete dir="${docs.output.dir}"/>
+ <delete file="${docs.output.dir}.zip"/>
+ <mkdir dir="${docs.output.dir}"/>
+ <!-- copy enunciate docs to stage -->
+ <copy todir="${docs.output.dir}">
+ <fileset dir="${basedir}/../../..">
+ <patternset refid="rest.paths"/>
+ </fileset>
+ <mapper type="regexp"
+ from="^(.*)/([^/]+)/target/site/wsdocs/(.*)$$"
+ to="\2/\3"/>
+ </copy>
+ <!-- generate index.html -->
+ <!-- append header -->
+ <echo file="${docs.output.dir}/index.html" append="true">
+<![CDATA[
+<html>
+ <head>
+ <title> OpenDaylight REST API Documentation </title>
+ </head>
+ <body>
+ <h2>OpenDaylight REST API Documentation</h2>
+ <p> OpenDaylight supports the following <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">Representational State Transfer (REST)</a> APIs: </p>
+ <h4>
+]]>
+ </echo>
+ <dirset id="nbset" dir="${docs.output.dir}">
+ <include name="*"/>
+ </dirset>
+ <pathconvert pathsep="&#36;{line.separator}"
+ property="nbs"
+ refid="nbset"/>
+ <echo file="${docs.output.dir}/index.html"
+ append="true"
+ message="${nbs}"/>
+ <replaceregexp file="${docs.output.dir}/index.html"
+ match="^\${docs.output.dir}/(.*)$"
+ replace="&lt;li&gt;&lt;a href=\1/index.html&gt; \1 &lt;/a&gt;&lt;/li&gt;"
+ byline="true"/>
+
+ <!-- append footer -->
+ <echo file="${docs.output.dir}/index.html" append="true">
+<![CDATA[
+ </h4>
+ <i>---</i>
+ </body>
+</html>
+]]>
+ </echo>
+ <!-- archive all the docs excluding whatever is not needed -->
+ <echo message="======== Archiving enunciate docs ========"/>
+ <zip destfile="${docs.output.dir}.zip">
+ <zipfileset dir="${docs.output.dir}"/>
+ </zip>
+
+ <echo message="======== Build successful ========"/>
+ <echo message="REST docs archive: ${docs.output.dir}.zip"/>
+ </target>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>ant-contrib</groupId>
+ <artifactId>ant-contrib</artifactId>
+ <version>20020829</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.5</version>
+ <configuration>
+ <packaging>jar</packaging>
+ <groupId>${project.groupId}</groupId>
+ <version>${project.version}</version>
+ </configuration>
+ <executions>
+ <execution>
+ <!-- skip default install -->
+ <id>default-install</id>
+ <phase>install</phase>
+ <goals>
+ <goal>install</goal>
+ </goals>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </execution>
+ <execution>
+ <!-- install full java client -->
+ <id>install-full-client</id>
+ <phase>install</phase>
+ <goals>
+ <goal>install-file</goal>
+ </goals>
+ <configuration>
+ <artifactId>${project.artifactId}.full-client</artifactId>
+ <file>${java-client}</file>
+ <sources>${java-client-sources}</sources>
+ </configuration>
+ </execution>
+ <execution>
+ <!-- install full java json client -->
+ <id>install-full-json-client</id>
+ <phase>install</phase>
+ <goals>
+ <goal>install-file</goal>
+ </goals>
+ <configuration>
+ <artifactId>${project.artifactId}.full-json-client</artifactId>
+ <file>${json-client}</file>
+ <sources>${json-client-sources}</sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <version>2.5</version>
+ <configuration>
+ <packaging>jar</packaging>
+ <generatePom>true</generatePom>
+ <groupId>${project.groupId}</groupId>
+ <version>${project.version}</version>
+ <url>${project.distributionManagement.repository.url}</url>
+ </configuration>
+ <executions>
+ <execution>
+ <!-- skip default deploy -->
+ <id>default-deploy</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>deploy</goal>
+ </goals>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </execution>
+ <execution>
+ <!-- deploy full java client -->
+ <id>deploy-full-client</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>deploy-file</goal>
+ </goals>
+ <configuration>
+ <artifactId>${project.artifactId}.full-client</artifactId>
+ <file>${java-client}</file>
+ <sources>${java-client-sources}</sources>
+ </configuration>
+ </execution>
+ <execution>
+ <!-- deploy full java json client -->
+ <id>deploy-full-json-client</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>deploy-file</goal>
+ </goals>
+ <configuration>
+ <artifactId>${project.artifactId}.full-json-client</artifactId>
+ <file>${json-client}</file>
+ <sources>${json-client-sources}</sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.enunciate</groupId>
+ <artifactId>enunciate-core-annotations</artifactId>
+ <version>${enunciate.version}</version>
+ </dependency>
+
+ <!-- add dependency on all northbound bundles -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>connectionmanager.northbound</artifactId>
+ <version>0.1.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>controllermanager.northbound</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>flowprogrammer.northbound</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>hosttracker.northbound</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>networkconfig.bridgedomain.northbound</artifactId>
+ <version>0.0.2-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>networkconfig.neutron.northbound</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>forwarding.staticrouting.northbound</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>statistics.northbound</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>subnets.northbound</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>switchmanager.northbound</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>topology.northbound</artifactId>
+ <version>0.4.1-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>usermanager.northbound</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
+ </dependency>
</dependencies>
</project>
<artifactId>junit</artifactId>
</dependency>
<dependency>
- <groupId>equinoxSDK381</groupId>
- <artifactId>org.apache.felix.gogo.runtime</artifactId>
+ <groupId>equinoxSDK381</groupId>
+ <artifactId>org.apache.felix.gogo.runtime</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>commons.logback_settings</artifactId>
</dependency>
</dependencies>
</project>
+++ /dev/null
-<configuration scan="true">\r
-\r
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
- <encoder>\r
- <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n\r
- </pattern>\r
- </encoder>\r
- </appender>\r
-\r
- <root level="error">\r
- <appender-ref ref="STDOUT" />\r
- </root>\r
-</configuration>\r
*/
@RequestMapping(value = "/users", method = RequestMethod.POST)
@ResponseBody
- public String saveLocalUserConfig(@RequestParam(required = true) String json,
+ public Status saveLocalUserConfig(@RequestParam(required = true) String json,
@RequestParam(required = true) String action, HttpServletRequest request) {
IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
if (userManager == null) {
- return "Internal Error";
+ return new Status(StatusCode.NOSERVICE, "User Manager unavailable");
}
if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
- return "Operation not permitted";
+ return new Status(StatusCode.UNAUTHORIZED, "Operation not permitted");
}
Gson gson = new Gson();
Status result = (action.equals("add")) ? userManager.addLocalUser(config) : userManager.removeLocalUser(config);
if (result.isSuccess()) {
- String userAction = (action.equals("add")) ? "added" : "removed";
if (action.equals("add")) {
- String userRoles = "";
- for (String userRole : config.getRoles()) {
- userRoles = userRoles + userRole + ",";
- }
- DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), userAction, config.getUser()
- + " as " + userRoles.substring(0, userRoles.length() - 1));
+ DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "added", config.getUser()
+ + " as " + config.getRoles().toString());
} else {
- DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), userAction, config.getUser());
+ DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "removed", config.getUser());
}
- return "Success";
}
- return result.getDescription();
+ return result;
}
+ @RequestMapping(value = "/user/modify", method = RequestMethod.POST)
+ @ResponseBody
+ public Status modifyUser(@RequestParam(required = true) String json,
+ @RequestParam(required = true) String action, HttpServletRequest request) {
+
+ IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
+ if (userManager == null) {
+ return new Status(StatusCode.NOSERVICE, "User Manager unavailable");
+ }
+
+ if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
+ return new Status(StatusCode.UNAUTHORIZED, "Operation not permitted");
+ }
+
+ UserConfig newConfig = gson.fromJson(json, UserConfig.class);
+ List<UserConfig> currentUserConfig = userManager.getLocalUserList();
+ String password = null;
+ String user = newConfig.getUser();
+ for (UserConfig userConfig : currentUserConfig) {
+ if(userConfig.getUser().equals(user)){
+ password = userConfig.getPassword();
+ break;
+ }
+ }
+ if (password == null) {
+ String msg = String.format("User %s not found in configuration database", user);
+ return new Status(StatusCode.NOTFOUND, msg);
+ }
+
+ //While modifying a user role, the password is not provided from GUI for any user.
+ //The password is stored in hash mode, hence it cannot be retrieved and added to UserConfig object
+ //The hashed password is injected below to the json string containing username and new roles before
+ //converting to UserConfig object.
+ json = json.replace("\"roles\"", "\"password\":\""+ password + "\",\"roles\"");
+ Gson gson = new Gson();
+ newConfig = gson.fromJson(json, UserConfig.class);
+
+ Status result = userManager.modifyLocalUser(newConfig);
+ if (result.isSuccess()) {
+ DaylightWebUtil.auditlog("Roles of", request.getUserPrincipal().getName(), "updated", newConfig.getUser()
+ + " to " + newConfig.getRoles().toString());
+ }
+ return result;
+ }
+
+
@RequestMapping(value = "/users/{username}", method = RequestMethod.POST)
@ResponseBody
- public String removeLocalUser(@PathVariable("username") String userName, HttpServletRequest request) {
+ public Status removeLocalUser(@PathVariable("username") String userName, HttpServletRequest request) {
- String username = request.getUserPrincipal().getName();
- if (username.equals(userName)) {
- return "Invalid Request: User cannot delete itself";
+ String loggedInUser = request.getUserPrincipal().getName();
+ if (loggedInUser.equals(userName)) {
+ String msg = "Invalid Request: User cannot delete itself";
+ return new Status(StatusCode.NOTALLOWED, msg);
}
IUserManager userManager = (IUserManager) ServiceHelper.getGlobalInstance(IUserManager.class, this);
if (userManager == null) {
- return "Internal Error";
+ return new Status(StatusCode.NOSERVICE, "User Manager unavailable");
}
if (!authorize(userManager, UserLevel.NETWORKADMIN, request)) {
- return "Operation not permitted";
+ return new Status(StatusCode.UNAUTHORIZED, "Operation not permitted");
}
- Status result = userManager.removeLocalUser(userName);
- if (result.isSuccess()) {
+ Status status = userManager.removeLocalUser(userName);
+ if (status.isSuccess()) {
DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "removed", userName);
- return "Success";
+ return status;
}
- return result.getDescription();
+ return status;
}
@RequestMapping(value = "/users/password/{username}", method = RequestMethod.POST)
}
if (status.isSuccess()) {
- DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), " changed password for User ",
+ DaylightWebUtil.auditlog("User", request.getUserPrincipal().getName(), "changed password for",
username);
}
return status;
close : "one_main_admin_id_modal_remove_close",
password : 'one_main_admin_id_modal_remove_password'
},
+ modify : {
+ user : "one_main_admin_id_modal_modify_user",
+ },
password : {
modal : 'one_main_admin_id_modal_password_modal',
submit : 'one_main_admin_id_modal_password_submit',
add : {
user : "one_main_admin_id_add_user"
}
+ },
+ registry :{
+
},
address : {
root : "/admin",
users : "/users",
+ modifyUser : "/user/modify",
password : '/admin/users/password/'
},
modal : {
$.getJSON(one.main.admin.address.root
+ one.main.admin.address.users, function(data) {
var body = one.main.admin.data.users(data);
+ one.main.admin.registry["users"] = data;
var $body = one.main.admin.body.users(body);
callback($body);
});
remove : {
modal : {
initialize : function(id) {
- var h3 = "Edit User";
+ var h3 = "Manage user - " + id;
var footer = one.main.admin.remove.footer();
var $body = one.main.admin.remove.body();
var $modal = one.lib.modal.spawn(one.main.admin.id.modal.user,
$('#'+one.main.admin.id.modal.remove.close, $modal).click(function() {
$modal.modal('hide');
});
+ // close binding
+ $('#'+one.main.admin.id.modal.modify.user, $modal).click(function() {
+ one.main.admin.add.modal.initialize(id, true);
+ });
// remove binding
$('#' + one.main.admin.id.modal.remove.user, $modal).click(function() {
one.main.admin.remove.modal.ajax(id, function(result) {
- if (result == 'Success') {
+ if (result.description == 'Success') {
$modal.modal('hide');
// body inject
var $admin = $('#'+one.main.admin.id.modal.main);
one.lib.modal.inject.body($admin, $body);
});
} else {
- alert("Failed to remove user: " + result);
+ alert("Failed to remove user: " + result.description);
}
});
});
one.main.admin.id.modal.remove.user, "btn-danger", "");
var $removeButton = one.lib.dashlet.button.button(removeButton);
footer.push($removeButton);
+ var modifyButton = one.lib.dashlet.button.single("Change Role",
+ one.main.admin.id.modal.modify.user, "btn-success", "");
+ var $modifyButton = one.lib.dashlet.button.button(modifyButton);
+ footer.push($modifyButton);
var change = one.lib.dashlet.button.single('Change Password',
one.main.admin.id.modal.remove.password, 'btn-success', '');
var $change = one.lib.dashlet.button.button(change);
},
add : {
modal : {
- initialize : function() {
- var h3 = "Add User";
- var footer = one.main.admin.add.footer();
- var $body = one.main.admin.add.body();
+ initialize : function(id, edit) {
+ var h3 = edit? "Change Role of user " + id:"Add User";
+ var footer = one.main.admin.add.footer(edit);
+ var $body = one.main.admin.add.body(id, edit);
var $modal = one.lib.modal.spawn(one.main.admin.id.modal.user,
h3, $body, footer);
// close binding
});
// add binding
$('#' + one.main.admin.id.modal.add.user, $modal).click(function() {
- one.main.admin.add.modal.add($modal, function(result) {
- if (result == 'Success') {
+ one.main.admin.add.modal.add($modal, edit, function(result) {
+ if (result.description == 'Success') {
$modal.modal('hide');
// body inject
var $admin = $('#'+one.main.admin.id.modal.main);
one.main.admin.ajax.users(function($body) {
- one.lib.modal.inject.body($admin, $body);
+ one.lib.modal.inject.body($admin, $body);
});
} else {
- alert("Failed to add user: "+result);
+ var action = edit? "edit" :"add";
+ alert("Failed to "+ action +" user: "+result.description);
}
});
});
$modal.modal();
},
- add : function($modal, callback) {
+ add : function($modal, edit, callback) {
var user = {};
user['user'] = $modal.find(
'#' + one.main.admin.id.modal.add.form.name).val();
- user['password'] = $modal.find(
- '#' + one.main.admin.id.modal.add.form.password).val();
+ if (!edit) {
+ user['password'] = $modal.find(
+ '#' + one.main.admin.id.modal.add.form.password).val();
+ }
roles = new Array();
roles[0] = $modal.find(
'#' + one.main.admin.id.modal.add.form.role).find(
'option:selected').attr('value');
user['roles'] = roles;
- // password check
- var verify = $('#'+one.main.admin.id.modal.add.form.verify).val();
- if (user.password != verify) {
- alert('Passwords do not match');
- return false;
+ if (!edit) {
+ // password check
+ var verify = $('#'+one.main.admin.id.modal.add.form.verify).val();
+ if (user.password != verify) {
+ alert('Passwords do not match');
+ return false;
+ }
}
-
var resource = {};
resource['json'] = JSON.stringify(user);
resource['action'] = 'add'
- one.main.admin.add.modal.ajax(resource, callback);
+ one.main.admin.add.modal.ajax(resource, edit, callback);
},
- ajax : function(data, callback) {
- $.post(one.main.admin.address.root
- + one.main.admin.address.users, data, function(data) {
- callback(data);
- });
+ ajax : function(data, edit, callback) {
+ if(edit) {
+ $.post(one.main.admin.address.root
+ + one.main.admin.address.modifyUser, data, function(data) {
+ callback(data);
+ });
+ } else {
+ $.post(one.main.admin.address.root
+ + one.main.admin.address.users, data, function(data) {
+ callback(data);
+ });
+ }
}
},
- body : function() {
+ body : function(id, edit) {
var $form = $(document.createElement('form'));
var $fieldset = $(document.createElement('fieldset'));
+ var users = one.main.admin.registry["users"];
+ var currentUser;
+ if(edit) {
+ $(users).each(function(index, val) {
+ if(val.user == id){
+ currentUser = val;
+ }
+ });
+ }
+
// user
var $label = one.lib.form.label('Username');
var $input = one.lib.form.input('Username');
$input.attr('id', one.main.admin.id.modal.add.form.name);
+ if(edit) {
+ $input.attr("disabled",true);
+ $input.val(id);
+ }
$fieldset.append($label).append($input);
- // password
- var $label = one.lib.form.label('Password');
- var $input = one.lib.form.input('Password');
- $input.attr('id', one.main.admin.id.modal.add.form.password);
- $input.attr('type', 'password');
- $fieldset.append($label).append($input);
- // password verify
- var $label = one.lib.form.label('Verify Password');
- var $input = one.lib.form.input('Verify Password');
- $input.attr('id', one.main.admin.id.modal.add.form.verify);
- $input.attr('type', 'password');
- $fieldset.append($label).append($input);
+ if(!edit) {
+ // password
+ var $label = one.lib.form.label('Password');
+ var $input = one.lib.form.input('Password');
+ $input.attr('id', one.main.admin.id.modal.add.form.password);
+ $input.attr('type', 'password');
+ $fieldset.append($label).append($input);
+ // password verify
+ var $label = one.lib.form.label('Verify Password');
+ var $input = one.lib.form.input('Verify Password');
+ $input.attr('id', one.main.admin.id.modal.add.form.verify);
+ $input.attr('type', 'password');
+ $fieldset.append($label).append($input);
+ }
// roles
var $label = one.lib.form.label('Roles');
var options = {
};
var $select = one.lib.form.select.create(options);
$select.attr('id', one.main.admin.id.modal.add.form.role);
+ if(edit) {
+ $select.children().each(function() {
+ this.selected = (this.text == options[currentUser.roles[0]]);
+ });
+ }
+
$fieldset.append($label).append($select);
$form.append($fieldset);
return $form;
},
- footer : function() {
+ footer : function(edit) {
var footer = [];
- var addButton = one.lib.dashlet.button.single("Add User",
+ var buttonText = edit ? "Update User" : "Add User";
+
+ var addButton = one.lib.dashlet.button.single(buttonText,
one.main.admin.id.modal.add.user, "btn-primary", "");
var $addButton = one.lib.dashlet.button.button(addButton);
footer.push($addButton);
});
/** MAIN PAGE LOAD */
-one.main.menu.load();
+one.main.menu.load();
\ No newline at end of file
<module>opendaylight/commons/checkstyle</module>
<module>opendaylight/commons/opendaylight</module>
<module>opendaylight/commons/parent</module>
+ <module>opendaylight/commons/logback_settings</module>
</modules>
<profiles>
<module>opendaylight/distribution/sanitytest/</module>
</modules>
</profile>
+ <profile>
+ <id>docs</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <modules>
+ <module>opendaylight/northbound/java-client</module>
+ </modules>
+ </profile>
</profiles>
</project>