From: Tom Pantelis Date: Thu, 19 Feb 2015 20:57:45 +0000 (+0000) Subject: Merge "Bug 2538: Remove redundant Augmentation checks and tests" X-Git-Tag: release/lithium~537 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=d2d4cefa4d8d662554b7f2fc0b0dd568d0db1180;hp=2b2f00723a3159218b3e00cf8d30802b4fbbf840 Merge "Bug 2538: Remove redundant Augmentation checks and tests" --- diff --git a/features/mdsal/pom.xml b/features/mdsal/pom.xml index 5e6afd248f..c63b39c74d 100644 --- a/features/mdsal/pom.xml +++ b/features/mdsal/pom.xml @@ -113,6 +113,12 @@ features xml + + org.opendaylight.controller + features-netconf + features + xml + org.opendaylight.controller features-config-persister diff --git a/features/mdsal/src/main/resources/features.xml b/features/mdsal/src/main/resources/features.xml index 8c166e6382..5b9f4a674a 100644 --- a/features/mdsal/src/main/resources/features.xml +++ b/features/mdsal/src/main/resources/features.xml @@ -7,6 +7,7 @@ mvn:org.opendaylight.controller/features-config/${config.version}/xml/features mvn:org.opendaylight.controller/features-config-persister/${config.version}/xml/features mvn:org.opendaylight.controller/features-config-netty/${config.version}/xml/features + mvn:org.opendaylight.controller/features-netconf/${netconf.version}/xml/features mvn:org.opendaylight.controller/features-akka/${commons.opendaylight.version}/xml/features odl-mdsal-broker @@ -21,6 +22,20 @@ mvn:org.opendaylight.controller/sal-common-impl/${mdsal.version} mvn:org.opendaylight.controller/sal-common-util/${mdsal.version} + + + + odl-config-all + odl-netconf-all + mvn:org.opendaylight.controller/netconf-ssh/${netconf.version} + odl-mdsal-broker + mvn:org.opendaylight.controller/mdsal-netconf-connector/${netconf.version} + + mvn:org.opendaylight.controller/netconf-config-dispatcher/${config.version} + mvn:org.opendaylight.controller/netconf-config/${netconf.version}/xml/config + mvn:org.opendaylight.controller/netconf-mdsal-config/${netconf.version}/xml/config + + odl-yangtools-common odl-yangtools-binding diff --git a/features/netconf-connector/pom.xml b/features/netconf-connector/pom.xml index c69ee197be..4e94996634 100644 --- a/features/netconf-connector/pom.xml +++ b/features/netconf-connector/pom.xml @@ -119,6 +119,10 @@ org.opendaylight.controller netconf-config-dispatcher + + org.opendaylight.controller + mdsal-netconf-connector + org.opendaylight.controller netconf-tcp diff --git a/features/netconf-connector/src/main/resources/features.xml b/features/netconf-connector/src/main/resources/features.xml index 863833bcc0..92e6507d21 100644 --- a/features/netconf-connector/src/main/resources/features.xml +++ b/features/netconf-connector/src/main/resources/features.xml @@ -42,6 +42,8 @@ --> odl-netconf-connector odl-netconf-connector-ssh + + - 4.1 - 1.50 - 2.4.0 0.5.0-SNAPSHOT 0.5.0-SNAPSHOT 0.5.0-SNAPSHOT - 2.12 0.6.0-SNAPSHOT 0.5.0-SNAPSHOT 0.5.0-SNAPSHOT @@ -49,17 +42,13 @@ 7.0.53.v201406070630 0.1.0-SNAPSHOT - 1.2.2 0.2.0-SNAPSHOT - 2.4 - 3.1 0.1.0-SNAPSHOT 3.0.1 0.2.0-SNAPSHOT 0.6.0-SNAPSHOT 1.5.0-SNAPSHOT 1.1.0-SNAPSHOT - 2.3.2 0.2.0-SNAPSHOT 0.6.0-SNAPSHOT 1.4 @@ -72,6 +61,7 @@ 04-xsql.xml 01-netconf.xml 03-toaster-sample.xml + 08-mdsal-netconf.xml 10-rest-connector.xml 99-netconf-connector.xml 0.5.0-SNAPSHOT @@ -87,12 +77,8 @@ 30-statistics-manager.xml 2.5.0 3.8.0.I20120518-2145 - - 1.3.1 - 1.28 - 0000.0002.0038.0 1.6.0 1.5.0-SNAPSHOT @@ -127,7 +113,6 @@ 0.7 1.8 1.0.0 - 1.0.9 0.5.0-SNAPSHOT 3.0.5 1.9.4 diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModule.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModule.java index a97f65e941..31e7a24fee 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModule.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModule.java @@ -17,6 +17,7 @@ import org.opendaylight.protocol.framework.ReconnectStrategyFactory; /** * */ +@Deprecated public final class NeverReconnectStrategyFactoryModule extends org.opendaylight.controller.config.yang.protocol.framework.AbstractNeverReconnectStrategyFactoryModule { diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModuleFactory.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModuleFactory.java index bbdc9394cf..7dfe2c9083 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModuleFactory.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/NeverReconnectStrategyFactoryModuleFactory.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.config.yang.protocol.framework; /** * */ +@Deprecated public class NeverReconnectStrategyFactoryModuleFactory extends org.opendaylight.controller.config.yang.protocol.framework.AbstractNeverReconnectStrategyFactoryModuleFactory { diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java index 12b771df80..af86a249df 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModule.java @@ -17,6 +17,7 @@ import org.opendaylight.protocol.framework.ReconnectStrategyFactory; /** * */ +@Deprecated public final class ReconnectImmediatelyStrategyFactoryModule extends org.opendaylight.controller.config.yang.protocol.framework.AbstractReconnectImmediatelyStrategyFactoryModule { diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModuleFactory.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModuleFactory.java index 6e72458be8..7aa31f30cd 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModuleFactory.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/ReconnectImmediatelyStrategyFactoryModuleFactory.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.config.yang.protocol.framework; /** * */ +@Deprecated public class ReconnectImmediatelyStrategyFactoryModuleFactory extends org.opendaylight.controller.config.yang.protocol.framework.AbstractReconnectImmediatelyStrategyFactoryModuleFactory { diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java index 0b4a7baf6f..ab0602a965 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModule.java @@ -19,6 +19,7 @@ import com.google.common.base.Preconditions; /** * */ +@Deprecated public final class TimedReconnectStrategyFactoryModule extends org.opendaylight.controller.config.yang.protocol.framework.AbstractTimedReconnectStrategyFactoryModule { diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModuleFactory.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModuleFactory.java index 7f92e3a408..eac0c66fd8 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModuleFactory.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/controller/config/yang/protocol/framework/TimedReconnectStrategyFactoryModuleFactory.java @@ -10,6 +10,7 @@ package org.opendaylight.controller.config.yang.protocol.framework; /** * */ +@Deprecated public class TimedReconnectStrategyFactoryModuleFactory extends org.opendaylight.controller.config.yang.protocol.framework.AbstractTimedReconnectStrategyFactoryModuleFactory { diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java index 7f5233c827..7b8816bd1b 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractDispatcher.java @@ -39,6 +39,7 @@ import io.netty.util.concurrent.Promise; * Dispatcher class for creating servers and clients. The idea is to first create servers and clients and the run the * start method that will handle sockets in different thread. */ +@Deprecated public abstract class AbstractDispatcher, L extends SessionListener> implements Closeable { diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractProtocolSession.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractProtocolSession.java index af196a941a..44afc4e7a1 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractProtocolSession.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractProtocolSession.java @@ -13,6 +13,7 @@ import io.netty.channel.SimpleChannelInboundHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@Deprecated public abstract class AbstractProtocolSession extends SimpleChannelInboundHandler implements ProtocolSession { private static final Logger LOG = LoggerFactory.getLogger(AbstractProtocolSession.class); diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractSessionNegotiator.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractSessionNegotiator.java index 2ecd267b9f..8a19828c57 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractSessionNegotiator.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractSessionNegotiator.java @@ -27,6 +27,7 @@ import com.google.common.base.Preconditions; * @param Protocol message type * @param Protocol session type, has to extend ProtocolSession */ +@Deprecated public abstract class AbstractSessionNegotiator> extends ChannelInboundHandlerAdapter implements SessionNegotiator { private final Logger LOG = LoggerFactory.getLogger(AbstractSessionNegotiator.class); private final Promise promise; diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/NeverReconnectStrategy.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/NeverReconnectStrategy.java index c480294417..926183f973 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/NeverReconnectStrategy.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/NeverReconnectStrategy.java @@ -18,6 +18,7 @@ import com.google.common.base.Preconditions; * Utility ReconnectStrategy singleton, which will cause the reconnect process * to always fail. */ +@Deprecated @ThreadSafe public final class NeverReconnectStrategy implements ReconnectStrategy { private final EventExecutor executor; diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSession.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSession.java index 6e79d6765d..b99844112f 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSession.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSession.java @@ -17,6 +17,7 @@ import java.io.Closeable; * * This interface should be implemented by a final class representing a protocol specific session. */ +@Deprecated public interface ProtocolSession extends Closeable { @Override void close(); diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionPromise.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionPromise.java index a38db61ead..b64c4828a4 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionPromise.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ProtocolSessionPromise.java @@ -23,6 +23,7 @@ import javax.annotation.concurrent.ThreadSafe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@Deprecated @ThreadSafe final class ProtocolSessionPromise> extends DefaultPromise { private static final Logger LOG = LoggerFactory.getLogger(ProtocolSessionPromise.class); diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectImmediatelyStrategy.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectImmediatelyStrategy.java index a567af1f76..56cdcfb0c3 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectImmediatelyStrategy.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectImmediatelyStrategy.java @@ -21,6 +21,7 @@ import com.google.common.base.Preconditions; * Utility ReconnectStrategy singleton, which will cause the reconnect process * to immediately schedule a reconnection attempt. */ +@Deprecated @ThreadSafe public final class ReconnectImmediatelyStrategy implements ReconnectStrategy { private static final Logger LOG = LoggerFactory.getLogger(ReconnectImmediatelyStrategy.class); diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectPromise.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectPromise.java index 865c666ad2..e57976449b 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectPromise.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectPromise.java @@ -21,6 +21,7 @@ import java.net.InetSocketAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@Deprecated final class ReconnectPromise, L extends SessionListener> extends DefaultPromise { private static final Logger LOG = LoggerFactory.getLogger(ReconnectPromise.class); diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectStrategy.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectStrategy.java index 24ff84b6ab..a0a9150799 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectStrategy.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectStrategy.java @@ -23,6 +23,7 @@ import io.netty.util.concurrent.Future; * not attempt any more connection attempts and should abort the reconnection * process. */ +@Deprecated public interface ReconnectStrategy { /** * Query the strategy for the connect timeout. diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectStrategyFactory.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectStrategyFactory.java index 3c61044bee..a71fa677c8 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectStrategyFactory.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/ReconnectStrategyFactory.java @@ -12,6 +12,7 @@ package org.opendaylight.protocol.framework; * primarily useful for allowing injection of a specific type of strategy for * on-demand use, pretty much like you would use a ThreadFactory. */ +@Deprecated public interface ReconnectStrategyFactory { /** * Create a new ReconnectStrategy. diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java index a756a0da7e..dfe0208c54 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListener.java @@ -14,6 +14,7 @@ import java.util.EventListener; * implemented by a protocol specific abstract class, that is extended by * a final class that implements the methods. */ +@Deprecated public interface SessionListener, T extends TerminationReason> extends EventListener { /** * Fired when the session was established successfully. diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListenerFactory.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListenerFactory.java index 11871286cf..99087a5434 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListenerFactory.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionListenerFactory.java @@ -13,6 +13,7 @@ package org.opendaylight.protocol.framework; * implemented by a protocol specific abstract class, that is extended by * a final class that implements the methods. */ +@Deprecated public interface SessionListenerFactory> { /** * Returns one session listener diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionNegotiator.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionNegotiator.java index 3de64b07ff..c2abf50716 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionNegotiator.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionNegotiator.java @@ -17,6 +17,7 @@ import io.netty.channel.ChannelInboundHandler; * * @param Protocol session type. */ +@Deprecated public interface SessionNegotiator> extends ChannelInboundHandler { } diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionNegotiatorFactory.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionNegotiatorFactory.java index 90844ca712..66293f368f 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionNegotiatorFactory.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/SessionNegotiatorFactory.java @@ -15,6 +15,7 @@ import io.netty.util.concurrent.Promise; * * @param session type */ +@Deprecated public interface SessionNegotiatorFactory, L extends SessionListener> { /** * Create a new negotiator attached to a channel, which will notify diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/TerminationReason.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/TerminationReason.java index 1a6179dc35..19d11125e5 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/TerminationReason.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/TerminationReason.java @@ -10,6 +10,7 @@ package org.opendaylight.protocol.framework; /** * Marker interface for grouping session termination cause. */ +@Deprecated public interface TerminationReason { /** diff --git a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/TimedReconnectStrategy.java b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/TimedReconnectStrategy.java index 8bb326821d..ecb9e65a52 100644 --- a/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/TimedReconnectStrategy.java +++ b/opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/TimedReconnectStrategy.java @@ -42,6 +42,7 @@ import com.google.common.base.Preconditions; * * Both these caps can be combined, with the strategy giving up as soon as the first one is reached. */ +@Deprecated @ThreadSafe public final class TimedReconnectStrategy implements ReconnectStrategy { private static final Logger LOG = LoggerFactory.getLogger(TimedReconnectStrategy.class); diff --git a/opendaylight/config/config-api/pom.xml b/opendaylight/config/config-api/pom.xml index eff635c17e..d76bd50a3d 100644 --- a/opendaylight/config/config-api/pom.xml +++ b/opendaylight/config/config-api/pom.xml @@ -28,6 +28,10 @@ org.osgi org.osgi.core + + + compile org.opendaylight.yangtools diff --git a/opendaylight/config/config-persister-feature-adapter/src/main/java/org/opendaylight/controller/configpusherfeature/internal/ConfigPushingRunnable.java b/opendaylight/config/config-persister-feature-adapter/src/main/java/org/opendaylight/controller/configpusherfeature/internal/ConfigPushingRunnable.java index 5c257effba..a32a0ac28f 100644 --- a/opendaylight/config/config-persister-feature-adapter/src/main/java/org/opendaylight/controller/configpusherfeature/internal/ConfigPushingRunnable.java +++ b/opendaylight/config/config-persister-feature-adapter/src/main/java/org/opendaylight/controller/configpusherfeature/internal/ConfigPushingRunnable.java @@ -33,7 +33,7 @@ public class ConfigPushingRunnable implements Runnable { @Override public void run() { List toInstall = new ArrayList(); - FeatureEvent event; + FeatureEvent event = null; boolean interuppted = false; while(true) { try { @@ -54,7 +54,7 @@ public class ConfigPushingRunnable implements Runnable { LOG.error("ConfigPushingRunnable - interupted"); interuppted = true; } catch (Exception e) { - LOG.error("Exception while processing features ", e); + LOG.error("Exception while processing features {} event {}", toInstall, event, e); } } } diff --git a/opendaylight/md-sal/mdsal-artifacts/pom.xml b/opendaylight/md-sal/mdsal-artifacts/pom.xml index f88e09cecb..420f888cf1 100644 --- a/opendaylight/md-sal/mdsal-artifacts/pom.xml +++ b/opendaylight/md-sal/mdsal-artifacts/pom.xml @@ -309,6 +309,18 @@ xml + + + org.opendaylight.controller + message-bus-api + ${project.version} + + + org.opendaylight.controller + message-bus-impl + ${project.version} + + diff --git a/opendaylight/md-sal/messagebus-api/pom.xml b/opendaylight/md-sal/messagebus-api/pom.xml new file mode 100644 index 0000000000..542308a96f --- /dev/null +++ b/opendaylight/md-sal/messagebus-api/pom.xml @@ -0,0 +1,104 @@ + + + + 4.0.0 + + + org.opendaylight.controller + sal-parent + 1.2.0-SNAPSHOT + + + message-bus-api + ${project.artifactId} + + bundle + + + + org.opendaylight.controller.model + model-inventory + + + org.opendaylight.yangtools.model + yang-ext + + + org.opendaylight.yangtools.model + ietf-topology + + + + + + + org.opendaylight.yangtools + yang-maven-plugin + + + + generate-sources + + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + ${project.build.directory}/generated-sources/sal + + + org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + ${project.build.directory}/generated-sources/config + + urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang + + + + org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl + target/site/models + + + true + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.8 + + + add-source + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/config + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.* + + + + + + diff --git a/opendaylight/md-sal/messagebus-api/src/main/yang/event-aggregator.yang b/opendaylight/md-sal/messagebus-api/src/main/yang/event-aggregator.yang new file mode 100644 index 0000000000..ad7b573396 --- /dev/null +++ b/opendaylight/md-sal/messagebus-api/src/main/yang/event-aggregator.yang @@ -0,0 +1,131 @@ +module event-aggregator { + // FIXME: this module needs to be split up to concepts and API + // as the concepts are shared with the other model in this + // package. + yang-version 1; + namespace "urn:cisco:params:xml:ns:yang:messagebus:eventaggregator"; + prefix "eventaggregator"; + + organization "Cisco Systems, Inc."; + contact "Robert Gallas"; + + description + "Module implementing message but RPC. + + Copyright (c)2014 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 "2014-12-02" { + description "Initial revision"; + } + + typedef pattern { + type string { + length 1..max; + } + + // FIXME: make this a regular expression + description "A match pattern. Specifically this is a wildcard pattern."; + } + + typedef notification-pattern { + type pattern; + description + "Pattern for matching candidate notification types. This pattern is to be + applied against the concatenation of the namespace of the module which + defines that particular notification, followed by a single colon, and + then followed by notification identifier, as supplied in the argument to + the notification statement."; + } + + typedef topic-id { + type string { + length 1..max; + } + description + "A topic identifier. It uniquely defines a topic as seen by the the user + of this model's RPCs"; + } + + // FIXME: we would really like to share instances here, but that requires some sort + // of sane reference counting. The reason for sharing is the data path part + // of notification delivery -- multiple creators of topics can still share + // a single data path. + rpc create-topic { + description + "Create a new topic. A topic is an aggregation of several notification + types from a set of nodes. Each successful invocation results in a unique + topic being created. The caller is responsible for removing the topic + once it is no longer needed."; + + input { + leaf notification-pattern { + type notification-pattern; + mandatory true; + description + "Pattern matching notification which should be forwarded into this + topic."; + } + + leaf node-id-pattern { + type pattern; + mandatory true; + description + "Pattern for matching candidate event source nodes when looking + for contributors to the topic. The pattern will be applied against + /network-topology/topology/node/node-id"; + } + } + + output { + leaf topic-id { + type topic-id; + mandatory true; + } + } + } + + rpc destroy-topic { + description + "Destroy a topic. No further messages will be delivered to it."; + + input { + leaf topic-id { + type topic-id; + mandatory true; + } + } + } + + notification topic-notification { + description + "Notification of an event occuring on a particular node. This notification + acts as an encapsulation for the event being delivered."; + + leaf topic-id { + type topic-id; + mandatory true; + description + "Topic to which this event is being delivered."; + } + + leaf node-id { + // FIXME: should be topology node ID + type string; + mandatory true; + description + "Node ID of the node which generated the event."; + } + + anyxml payload { + mandatory true; + description + "Encapsulated notification. The format is the XML representation of + a notification according to RFC6020 section 7.14.2."; + } + } +} diff --git a/opendaylight/md-sal/messagebus-api/src/main/yang/event-source.yang b/opendaylight/md-sal/messagebus-api/src/main/yang/event-source.yang new file mode 100644 index 0000000000..5dd416cde6 --- /dev/null +++ b/opendaylight/md-sal/messagebus-api/src/main/yang/event-source.yang @@ -0,0 +1,85 @@ +module event-source { + yang-version 1; + namespace "urn:cisco:params:xml:ns:yang:messagebus:eventsource"; + prefix "eventsource"; + + import event-aggregator { prefix aggr; } + import network-topology { prefix nt; revision-date "2013-10-21"; } + import opendaylight-inventory {prefix inv; revision-date "2013-08-19"; } + import yang-ext {prefix ext; revision-date "2013-07-09"; } + + organization "Cisco Systems, Inc."; + contact "Robert Gallas"; + + description + "Base model for a topology where individual nodes can produce events. + + Module implementing event source topology and encapped notification. + + Copyright (c)2014 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 "2014-12-02" { + description "first revision"; + } + + // FIXME: expand this + typedef join-topic-status { + type enumeration { + enum up; + enum down; + } + description "Object status"; + } + + // FIXME: migrate to topology + typedef node-ref { + type leafref { + path "/inv:nodes/inv:node/inv:id"; + } + } + + grouping topology-event-source-type { + container topology-event-source { + presence "indicates an event source-aware topology"; + } + } + + rpc join-topic { + input { + leaf node { + ext:context-reference "inv:node-context"; + type "instance-identifier"; + } + leaf topic-id { + type aggr:topic-id; + description "in current implementation notification-pattern is defined by topic-id. + By persisting topic definition we could omit notification-pattern"; + } + leaf notification-pattern { + type aggr:notification-pattern; + } + } + + output { + leaf status { + type join-topic-status; + } + } + } + + augment "/nt:network-topology/nt:topology/nt:topology-types" { + uses topology-event-source-type; + } + + augment "/nt:network-topology/nt:topology/nt:node" { + when "../../nt:topology-types/topology-event-source"; + leaf event-source-node { + type node-ref; + } + } +} diff --git a/opendaylight/md-sal/messagebus-impl/pom.xml b/opendaylight/md-sal/messagebus-impl/pom.xml new file mode 100644 index 0000000000..8e088ba578 --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/pom.xml @@ -0,0 +1,116 @@ + + + 4.0.0 + + + org.opendaylight.controller + sal-parent + 1.2.0-SNAPSHOT + + + message-bus-impl + ${project.artifactId} + + bundle + + + + org.opendaylight.controller + ietf-netconf-notifications + 0.3.0-SNAPSHOT + + + org.opendaylight.controller + sal-binding-api + + + org.opendaylight.controller + sal-core-api + + + org.opendaylight.controller + sal-common-util + + + org.opendaylight.yangtools + yang-data-impl + + + org.opendaylight.controller + config-api + + + org.opendaylight.controller + message-bus-api + + + org.opendaylight.controller + sal-binding-config + + + + + + + org.opendaylight.yangtools + yang-maven-plugin + + + + generate-sources + + + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + + + ${project.build.directory}/generated-sources/sal + + + + + org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + + ${project.build.directory}/generated-sources/config + + + urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang + + + + + org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl + target/site/models + + + true + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.8 + + + add-source + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/config + + + + + + + + diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/config/yang/messagebus/app/impl/MessageBusAppImplModule.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/config/yang/messagebus/app/impl/MessageBusAppImplModule.java new file mode 100644 index 0000000000..1c2b78a85b --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/config/yang/messagebus/app/impl/MessageBusAppImplModule.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2014 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.config.yang.messagebus.app.impl; + +import org.opendaylight.controller.config.api.DependencyResolver; +import org.opendaylight.controller.config.api.ModuleIdentifier; +import org.opendaylight.controller.mdsal.InitializationContext; +import org.opendaylight.controller.mdsal.Providers; +import org.osgi.framework.BundleContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class MessageBusAppImplModule extends org.opendaylight.controller.config.yang.messagebus.app.impl.AbstractMessageBusAppImplModule { + private static final Logger LOGGER = LoggerFactory.getLogger(MessageBusAppImplModule.class); + + private BundleContext bundleContext; + + public BundleContext getBundleContext() { + return bundleContext; + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + public MessageBusAppImplModule( ModuleIdentifier identifier, DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public MessageBusAppImplModule( ModuleIdentifier identifier, + DependencyResolver dependencyResolver, + MessageBusAppImplModule oldModule, + java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + protected void customValidation() {} + + @Override + public java.lang.AutoCloseable createInstance() { + List namespaceMapping = getNamespaceToStream(); + InitializationContext ic = new InitializationContext(namespaceMapping); + + final Providers.BindingAware bap = new Providers.BindingAware(ic); + final Providers.BindingIndependent bip = new Providers.BindingIndependent(ic); + + getBindingBrokerDependency().registerProvider(bap, getBundleContext()); + getDomBrokerDependency().registerProvider(bip); + + AutoCloseable closer = new AutoCloseable() { + @Override public void close() { + closeProvider(bap); + closeProvider(bip); + } + }; + + return closer; + } + + private void closeProvider(AutoCloseable closable) { + try { + closable.close(); + } catch (Exception e) { + LOGGER.error("Exception while closing: {}\n Exception: {}", closable, e); + } + } +} diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/config/yang/messagebus/app/impl/MessageBusAppImplModuleFactory.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/config/yang/messagebus/app/impl/MessageBusAppImplModuleFactory.java new file mode 100644 index 0000000000..8bee2d1d12 --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/config/yang/messagebus/app/impl/MessageBusAppImplModuleFactory.java @@ -0,0 +1,51 @@ +/* +* Generated file +* +* Generated from: yang module name: message-bus-app-impl yang module local name: messagebus-app-impl +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Tue Feb 03 09:03:11 CET 2015 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.controller.config.yang.messagebus.app.impl; + +import org.opendaylight.controller.config.api.DependencyResolver; +import org.opendaylight.controller.config.api.DynamicMBeanWithInstance; +import org.opendaylight.controller.config.spi.Module; +import org.osgi.framework.BundleContext; + +public class MessageBusAppImplModuleFactory extends org.opendaylight.controller.config.yang.messagebus.app.impl.AbstractMessageBusAppImplModuleFactory { + @Override + public Module createModule(String instanceName, + DependencyResolver dependencyResolver, + BundleContext bundleContext) { + + MessageBusAppImplModule module = + (MessageBusAppImplModule) super.createModule(instanceName, + dependencyResolver, + bundleContext); + + module.setBundleContext(bundleContext); + + return module; + } + + @Override + public Module createModule(String instanceName, + DependencyResolver dependencyResolver, + DynamicMBeanWithInstance old, + BundleContext bundleContext) + throws Exception { + + MessageBusAppImplModule module = + (MessageBusAppImplModule) super.createModule(instanceName, + dependencyResolver, + old, + bundleContext); + + module.setBundleContext(bundleContext); + + return module; + } + +} diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/DataStore.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/DataStore.java new file mode 100644 index 0000000000..a881fac850 --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/DataStore.java @@ -0,0 +1,80 @@ +/* + * 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.mdsal; + +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class DataStore { + private static final FutureCallback DEFAULT_CALLBACK = + new FutureCallback() { + public void onSuccess(Void result) { + // TODO: Implement default behaviour + } + + public void onFailure(Throwable t) { + // TODO: Implement default behaviour + }; + }; + + private final MdSAL mdSAL; + + public DataStore(MdSAL mdSAL) { + this.mdSAL = mdSAL; + } + + public ListenerRegistration registerDataChangeListener(LogicalDatastoreType store, + InstanceIdentifier path, + DataChangeListener listener, + AsyncDataBroker.DataChangeScope triggeringScope) { + return mdSAL.getDataBroker().registerDataChangeListener(store, path, listener, triggeringScope); + } + + public void asyncPUT(LogicalDatastoreType datastoreType, + InstanceIdentifier path, + T data) { + asyncPUT(datastoreType, path, data, DEFAULT_CALLBACK); + } + + public void asyncPUT(LogicalDatastoreType datastoreType, + InstanceIdentifier path, + T data, + FutureCallback callback) { + WriteTransaction tx = mdSAL.getDataBroker().newWriteOnlyTransaction(); + tx.put(datastoreType, path, data, true); + execPut(tx, callback); + } + + public T read(LogicalDatastoreType datastoreType, + InstanceIdentifier path) { + + ReadOnlyTransaction tx = mdSAL.getDataBroker().newReadOnlyTransaction(); + T result = null; + + try { + result = tx.read(datastoreType, path).get().get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return result; + } + + private static void execPut(WriteTransaction tx, FutureCallback callback) { + Futures.addCallback(tx.submit(), callback); + } +} diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/InitializationContext.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/InitializationContext.java new file mode 100644 index 0000000000..c73fb2ad83 --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/InitializationContext.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2014 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.mdsal; + +import org.opendaylight.controller.config.yang.messagebus.app.impl.NamespaceToStream; +import org.opendaylight.controller.messagebus.app.impl.EventAggregator; +import org.opendaylight.controller.messagebus.app.impl.EventSourceManager; +import org.opendaylight.controller.messagebus.app.impl.EventSourceTopology; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.controller.sal.core.api.Broker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class InitializationContext { + private static final Logger LOGGER = LoggerFactory.getLogger(InitializationContext.class); + + private final MdSAL mdSal; + private final DataStore dataStore; + private final EventSourceTopology eventSourceTopology; + private final EventSourceManager eventSourceManager; + private final EventAggregator eventAggregator; + + public InitializationContext(List namespaceMapping) { + this.mdSal = new MdSAL(); + this.dataStore = new DataStore(mdSal); + this.eventSourceTopology = new EventSourceTopology(dataStore); + this.eventSourceManager = new EventSourceManager(dataStore, mdSal, eventSourceTopology, namespaceMapping); + this.eventAggregator = new EventAggregator(mdSal, eventSourceTopology); + } + + public synchronized void set(BindingAwareBroker.ProviderContext session) { + mdSal.setBindingAwareContext(session); + + if (mdSal.isReady()) { + initialize(); + } + } + + public synchronized void set(Broker.ProviderSession session) { + mdSal.setBindingIndependentContext(session); + + if (mdSal.isReady()) { + initialize(); + } + } + + private void initialize() { + eventSourceTopology.mdsalReady(); + eventSourceManager.mdsalReady(); + eventAggregator.mdsalReady(); + + LOGGER.info("InitializationContext started."); + } +} diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/MdSAL.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/MdSAL.java new file mode 100644 index 0000000000..03b220a5fd --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/MdSAL.java @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2014 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.mdsal; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.controller.sal.binding.api.BindingAwareService; +import org.opendaylight.controller.sal.binding.api.mount.MountInstance; +import org.opendaylight.controller.sal.binding.api.mount.MountProviderService; +import org.opendaylight.controller.sal.core.api.Broker; +import org.opendaylight.controller.sal.core.api.BrokerService; +import org.opendaylight.controller.sal.core.api.notify.NotificationListener; +import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService; +import org.opendaylight.controller.sal.core.api.notify.NotificationService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.RpcService; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MdSAL { + private static final Logger LOGGER = LoggerFactory.getLogger(MdSAL.class); + + private BindingAwareBroker.ProviderContext bindingAwareContext; + private Broker.ProviderSession bindingIndependentContext; + + // ----------------------------- + // ----- FRAMEWORK METHODS ----- + // ----------------------------- + public void setBindingAwareContext(BindingAwareBroker.ProviderContext bindingAwareContext) { + this.bindingAwareContext = bindingAwareContext; + } + + public void setBindingIndependentContext(Broker.ProviderSession bindingIndependentContext) { + this.bindingIndependentContext = bindingIndependentContext; + } + + //TODO: We should hide brokers and expose functionalities instead + public DataBroker getDataBroker() { + return getBaSalService(DataBroker.class); + } + + public synchronized boolean isReady() { + return (bindingAwareContext != null && bindingIndependentContext != null); + } + + // ----------------------- + // ----- API METHODS ----- + // ----------------------- + // TODO: Factor out API methods to interface + // method does not return registration object. Rather will hold references internally and manipulate using node id and API + public void addRpcImplementation(Class serviceInterface, + T implementation) + throws IllegalStateException { + bindingAwareContext.addRpcImplementation(serviceInterface, implementation); + } + + // method does not return registration object. Rather will hold references internally and manipulate using node id and API + public void addRpcImplementation(Node node, + Class serviceInterface, + T implementation) + throws IllegalStateException { + BindingAwareBroker.RoutedRpcRegistration registration + = addRoutedRpcImplementation(serviceInterface, implementation); + + NodeRef nodeRef = createNodeRef(node.getId()); + registration.registerPath(NodeContext.class, nodeRef.getValue()); + } + + public ListenerRegistration addNotificationListener(String nodeId, + QName notification, + NotificationListener listener) { + YangInstanceIdentifier yii = inventoryNodeBIIdentifier(nodeId); + + NotificationService notificationService = + getBiSalService(DOMMountPointService.class) + .getMountPoint(yii) + .get() + .getService(NotificationPublishService.class) + .get(); + + ListenerRegistration registration = + notificationService.addNotificationListener(notification, listener); + + LOGGER.info("Notification listener registered for {}, at node {}", notification, nodeId); + + return registration; + } + + public ListenerRegistration addNotificationListener(QName notification, + NotificationListener listener) { + NotificationService notificationService = + getBiSalService(NotificationPublishService.class); + + ListenerRegistration registration = + notificationService.addNotificationListener(notification, listener); + + LOGGER.info("Notification listener registered for {}.", notification); + + return registration; + } + + public T getRpcService(Class serviceInterface) { + return bindingAwareContext.getRpcService(serviceInterface); + } + + public T getRpcService(String nodeId, Class serviceInterface) { + MountProviderService mountProviderService = getBaSalService(MountProviderService.class); + + InstanceIdentifier key = InstanceIdentifier.create(Nodes.class) + .child(Node.class, + new NodeKey(new NodeId(nodeId))); + + MountInstance mountPoint = mountProviderService.getMountPoint(key); + return mountPoint.getRpcService(serviceInterface); + } + + public void publishNotification(CompositeNode notification) { + getBiSalService(NotificationPublishService.class).publish(notification); + } + + public SchemaContext getSchemaContext(String nodeId) { + YangInstanceIdentifier yii = inventoryNodeBIIdentifier(nodeId); + + SchemaContext schemaContext = + getBiSalService(DOMMountPointService.class) + .getMountPoint(yii) + .get().getSchemaContext(); + + return schemaContext; + } + + // --------------------------- + // ----- UTILITY METHODS ----- + // --------------------------- + private T getBaSalService(Class service) { + return bindingAwareContext.getSALService(service); + } + + private T getBiSalService(Class service) { + return bindingIndependentContext.getService(service); + } + + private static final String NODE_ID_NAME = "id"; + + public static YangInstanceIdentifier inventoryNodeBIIdentifier(String nodeId) { + return YangInstanceIdentifier.builder() + .node(Nodes.QNAME) + .nodeWithKey(Node.QNAME, + QName.create(Node.QNAME.getNamespace(), + Node.QNAME.getRevision(), + NODE_ID_NAME), + nodeId) + .build(); + } + + private BindingAwareBroker.RoutedRpcRegistration addRoutedRpcImplementation(Class serviceInterface, + T implementation) + throws IllegalStateException { + return bindingAwareContext.addRoutedRpcImplementation(serviceInterface, implementation); + } + + public static NodeRef createNodeRef(NodeId nodeId) { + NodeKey nodeKey = new NodeKey(nodeId); + InstanceIdentifier path = InstanceIdentifier + .builder(Nodes.class) + .child(Node.class, nodeKey) + .build(); + return new NodeRef(path); + } +} diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/Providers.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/Providers.java new file mode 100644 index 0000000000..a28e588d43 --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/mdsal/Providers.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2014 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.mdsal; + +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; +import org.opendaylight.controller.sal.core.api.AbstractProvider; +import org.opendaylight.controller.sal.core.api.Broker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Providers { + private static final Logger LOGGER = LoggerFactory.getLogger(Providers.class); + + public static class BindingAware implements BindingAwareProvider, AutoCloseable { + private final InitializationContext initializationContext; + + public BindingAware(InitializationContext ic) { + this.initializationContext = ic; + } + + @Override + public void onSessionInitiated(BindingAwareBroker.ProviderContext session) { + initializationContext.set(session); + + LOGGER.info("BindingAwareBroker.ProviderContext initialized"); + } + + @Override + public void close() throws Exception {} + } + + public static class BindingIndependent extends AbstractProvider implements AutoCloseable { + private final InitializationContext initializationContext; + + public BindingIndependent(InitializationContext ic) { + this.initializationContext = ic; + } + + @Override + public void onSessionInitiated(Broker.ProviderSession session) { + initializationContext.set(session); + + LOGGER.info("Broker.ProviderSession initialized"); + } + + @Override + public void close() throws Exception {} + } + +} diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/EventAggregator.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/EventAggregator.java new file mode 100644 index 0000000000..4b77bf2a4c --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/EventAggregator.java @@ -0,0 +1,75 @@ +/* + * 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.messagebus.app.impl; + +import java.util.List; +import java.util.concurrent.Future; +import org.opendaylight.controller.mdsal.MdSAL; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.CreateTopicInput; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.CreateTopicOutput; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.CreateTopicOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.DestroyTopicInput; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.EventAggregatorService; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.NotificationPattern; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.Node1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +// TODO: implement topic created notification +public class EventAggregator implements EventAggregatorService { + private static final Logger LOGGER = LoggerFactory.getLogger(EventAggregator.class); + + private final MdSAL mdSAL; + private final EventSourceTopology eventSourceTopology; + + public EventAggregator(final MdSAL mdSAL, final EventSourceTopology eventSourceTopology) { + this.mdSAL = mdSAL; + this.eventSourceTopology = eventSourceTopology; + } + + public void mdsalReady() { + mdSAL.addRpcImplementation(EventAggregatorService.class, this); + } + + @Override + public Future> createTopic(final CreateTopicInput input) { + LOGGER.info("Received Topic creation request: NotificationPattern -> {}, NodeIdPattern -> {}", + input.getNotificationPattern(), + input.getNodeIdPattern()); + + Topic topic = new Topic(new NotificationPattern(input.getNotificationPattern()), input.getNodeIdPattern().getValue(), mdSAL); + + //# Make sure we capture all nodes from now on + eventSourceTopology.registerDataChangeListener(topic); + + //# Notify existing nodes + //# Code reader note: Context of Node type is NetworkTopology + List nodes = eventSourceTopology.snapshot(); + for (Node node : nodes) { + NodeId nodeIdToNotify = node.getAugmentation(Node1.class).getEventSourceNode(); + topic.notifyNode(nodeIdToNotify); + } + + CreateTopicOutput cto = new CreateTopicOutputBuilder() + .setTopicId(topic.getTopicId()) + .build(); + + return Util.resultFor(cto); + } + + @Override + public Future> destroyTopic(final DestroyTopicInput input) { + // 1. UNREGISTER DATA CHANGE LISTENER -> ? + // 2. CLOSE TOPIC + return null; + } +} diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/EventSourceManager.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/EventSourceManager.java new file mode 100644 index 0000000000..a84eddd458 --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/EventSourceManager.java @@ -0,0 +1,126 @@ +/* + * 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.messagebus.app.impl; + +import org.opendaylight.controller.config.yang.messagebus.app.impl.NamespaceToStream; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.mdsal.DataStore; +import org.opendaylight.controller.mdsal.MdSAL; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.EventSourceService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public final class EventSourceManager implements DataChangeListener { + private static final Logger LOGGER = LoggerFactory.getLogger(EventSourceManager.class); + private static final InstanceIdentifier INVENTORY_PATH = InstanceIdentifier.create(Nodes.class) + .child(Node.class); + private final DataStore dataStore; + private final MdSAL mdSal; + private final EventSourceTopology eventSourceTopology; + private final Map streamMap; + + public EventSourceManager(DataStore dataStore, + MdSAL mdSal, + EventSourceTopology eventSourceTopology, + List namespaceMapping) { + this.dataStore = dataStore; + this.mdSal = mdSal; + this.eventSourceTopology = eventSourceTopology; + this.streamMap = namespaceToStreamMapping(namespaceMapping); + } + + private Map namespaceToStreamMapping(List namespaceMapping) { + Map streamMap = new HashMap<>(namespaceMapping.size()); + + for (NamespaceToStream nToS : namespaceMapping) { + streamMap.put(nToS.getUrnPrefix(), nToS.getStreamName()); + } + + return streamMap; + } + + public void mdsalReady() { + dataStore.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + INVENTORY_PATH, + this, + DataBroker.DataChangeScope.SUBTREE); + + LOGGER.info("EventSourceManager initialized."); + } + + @Override + public void onDataChanged(AsyncDataChangeEvent, DataObject> event) { + //FIXME: Prevent creating new event source on subsequent changes in inventory, like disconnect. + LOGGER.debug("[DataChangeEvent, DataObject>: {}]", event); + + Node node = Util.getAffectedNode(event); + // we listen on node tree, therefore we should rather throw IllegalStateException when node is null + if ( node == null ) { + LOGGER.debug("OnDataChanged Event. Node is null."); + return; + } + if ( isNetconfNode(node) == false ) { + LOGGER.debug("OnDataChanged Event. Not a Netconf node."); + return; + } + if ( isEventSource(node) == false ) { + LOGGER.debug("OnDataChanged Event. Node an EventSource node."); + return; + } + + NetconfEventSource netconfEventSource = new NetconfEventSource(mdSal, + node.getKey().getId().getValue(), + streamMap); + mdSal.addRpcImplementation(node, EventSourceService.class, netconfEventSource); + + InstanceIdentifier nodeInstanceIdentifier = + InstanceIdentifier.create(Nodes.class) + .child(Node.class, node.getKey()) + .augmentation(NetconfNode.class); + + dataStore.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + nodeInstanceIdentifier, + netconfEventSource, + DataBroker.DataChangeScope.SUBTREE); + + eventSourceTopology.insert(node); + } + + private boolean isNetconfNode(Node node) { + return node.getAugmentation(NetconfNode.class) != null ; + } + + public boolean isEventSource(Node node) { + NetconfNode netconfNode = node.getAugmentation(NetconfNode.class); + + return isEventSource(netconfNode); + } + + private boolean isEventSource(NetconfNode node) { + for (String capability : node.getInitialCapability()) { + if(capability.startsWith("urn:ietf:params:xml:ns:netconf:notification")) { + return true; + } + } + + return false; + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/EventSourceTopology.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/EventSourceTopology.java new file mode 100644 index 0000000000..c0700971dd --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/EventSourceTopology.java @@ -0,0 +1,106 @@ +/* + * 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.messagebus.app.impl; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.mdsal.DataStore; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.Node1; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.Node1Builder; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.TopologyTypes1; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.TopologyTypes1Builder; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.topology.event.source.type.TopologyEventSource; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.topology.event.source.type.TopologyEventSourceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class EventSourceTopology { + private static final Logger LOGGER = LoggerFactory.getLogger(EventSourceTopology.class); + + private static final String topologyId = "EVENT-SOURCE-TOPOLOGY" ; + private static final TopologyKey topologyKey = new TopologyKey(new TopologyId(topologyId)); + private static final LogicalDatastoreType datastoreType = LogicalDatastoreType.OPERATIONAL; + + private static final InstanceIdentifier topologyInstanceIdentifier = + InstanceIdentifier.create(NetworkTopology.class) + .child(Topology.class, topologyKey); + + private static final InstanceIdentifier topologyTypeInstanceIdentifier = + topologyInstanceIdentifier + .child(TopologyTypes.class) + .augmentation(TopologyTypes1.class); + + private static final InstanceIdentifier eventSourceTopologyPath = + InstanceIdentifier.create(NetworkTopology.class) + .child(Topology.class) + .child(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang + .network.topology.rev131021.network.topology.topology.Node.class); + + private final Map> registrations = + new ConcurrentHashMap<>(); + + private final DataStore dataStore; + + public EventSourceTopology(DataStore dataStore) { + this.dataStore = dataStore; + } + + public void mdsalReady() { + TopologyEventSource topologySource = new TopologyEventSourceBuilder().build(); + TopologyTypes1 topologyTypeAugment = new TopologyTypes1Builder().setTopologyEventSource(topologySource).build(); + + dataStore.asyncPUT(datastoreType, topologyTypeInstanceIdentifier, topologyTypeAugment); + } + + public void insert(Node node) { + String nodeId = node.getKey().getId().getValue(); + NodeKey nodeKey = new NodeKey(new NodeId(nodeId)); + InstanceIdentifier topologyNodeAugment + = topologyInstanceIdentifier + .child(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang + .network.topology.rev131021.network.topology.topology.Node.class, nodeKey) + .augmentation(Node1.class); + + Node1 nodeAgument = new Node1Builder().setEventSourceNode(node.getId()).build(); + dataStore.asyncPUT(datastoreType, topologyNodeAugment, nodeAgument); + } + + // TODO: Should we expose this functioanlity over RPC? + public List snapshot() { + Topology topology = dataStore.read(datastoreType, topologyInstanceIdentifier); + return topology.getNode(); + } + + public void registerDataChangeListener(DataChangeListener listener) { + ListenerRegistration listenerRegistration = dataStore.registerDataChangeListener(datastoreType, + eventSourceTopologyPath, + listener, + DataBroker.DataChangeScope.SUBTREE); + + registrations.put(listener, listenerRegistration); + } +} diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/NetconfEventSource.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/NetconfEventSource.java new file mode 100644 index 0000000000..9c0697f3fb --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/NetconfEventSource.java @@ -0,0 +1,190 @@ +/* + * 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.messagebus.app.impl; + +import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Future; +import java.util.regex.Pattern; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.mdsal.MdSAL; +import org.opendaylight.controller.sal.core.api.notify.NotificationListener; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.NotificationPattern; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.TopicNotification; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.EventSourceService; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.JoinTopicInput; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.JoinTopicOutput; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionInput; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionInputBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.NotificationsService; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.StreamNameType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode; +import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NetconfEventSource implements EventSourceService, NotificationListener, DataChangeListener { + private static final Logger LOGGER = LoggerFactory.getLogger(NetconfEventSource.class); + + private final MdSAL mdSal; + private final String nodeId; + + private final List activeStreams = new ArrayList<>(); + + private final Map urnPrefixToStreamMap; + + public NetconfEventSource(final MdSAL mdSal, final String nodeId, final Map streamMap) { + Preconditions.checkNotNull(mdSal); + Preconditions.checkNotNull(nodeId); + + this.mdSal = mdSal; + this.nodeId = nodeId; + this.urnPrefixToStreamMap = streamMap; + + LOGGER.info("NetconfEventSource [{}] created.", nodeId); + } + + @Override + public Future> joinTopic(final JoinTopicInput input) { + final NotificationPattern notificationPattern = input.getNotificationPattern(); + + // FIXME: default language should already be regex + final String regex = Util.wildcardToRegex(notificationPattern.getValue()); + + final Pattern pattern = Pattern.compile(regex); + List matchingNotifications = Util.expandQname(availableNotifications(), pattern); + registerNotificationListener(matchingNotifications); + return null; + } + + private List availableNotifications() { + // FIXME: use SchemaContextListener to get changes asynchronously + Set availableNotifications = mdSal.getSchemaContext(nodeId).getNotifications(); + List qNs = new ArrayList<>(availableNotifications.size()); + for (NotificationDefinition nd : availableNotifications) { + qNs.add(nd.getQName()); + } + + return qNs; + } + + private void registerNotificationListener(final List notificationsToSubscribe) { + for (QName qName : notificationsToSubscribe) { + startSubscription(qName); + // FIXME: do not lose this registration + final ListenerRegistration reg = mdSal.addNotificationListener(nodeId, qName, this); + } + } + + private synchronized void startSubscription(final QName qName) { + String streamName = resolveStream(qName); + + if (streamIsActive(streamName) == false) { + LOGGER.info("Stream {} is not active on node {}. Will subscribe.", streamName, nodeId); + startSubscription(streamName); + } + } + + private synchronized void resubscribeToActiveStreams() { + for (String streamName : activeStreams) { + startSubscription(streamName); + } + } + + private synchronized void startSubscription(final String streamName) { + CreateSubscriptionInput subscriptionInput = getSubscriptionInput(streamName); + mdSal.getRpcService(nodeId, NotificationsService.class).createSubscription(subscriptionInput); + activeStreams.add(streamName); + } + + private static CreateSubscriptionInput getSubscriptionInput(final String streamName) { + CreateSubscriptionInputBuilder csib = new CreateSubscriptionInputBuilder(); + csib.setStream(new StreamNameType(streamName)); + return csib.build(); + } + + private String resolveStream(final QName qName) { + String streamName = null; + + for (Map.Entry entry : urnPrefixToStreamMap.entrySet()) { + String nameSpace = qName.getNamespace().toString(); + String urnPrefix = entry.getKey(); + if( nameSpace.startsWith(urnPrefix) ) { + streamName = entry.getValue(); + break; + } + } + + return streamName; + } + + private boolean streamIsActive(final String streamName) { + return activeStreams.contains(streamName); + } + + // PASS + @Override public Set getSupportedNotifications() { + return null; + } + + @Override + public void onNotification(final CompositeNode notification) { + LOGGER.info("NetconfEventSource {} received notification {}. Will publish to MD-SAL.", nodeId, notification); + ImmutableCompositeNode payload = ImmutableCompositeNode.builder() + .setQName(QName.create(TopicNotification.QNAME, "payload")) + .add(notification).toInstance(); + ImmutableCompositeNode icn = ImmutableCompositeNode.builder() + .setQName(TopicNotification.QNAME) + .add(payload) + .addLeaf("event-source", nodeId) + .toInstance(); + + mdSal.publishNotification(icn); + } + + @Override + public void onDataChanged(final AsyncDataChangeEvent, DataObject> change) { + boolean wasConnected = false; + boolean nowConnected = false; + + for (Map.Entry, DataObject> changeEntry : change.getOriginalData().entrySet()) { + if ( isNetconfNode(changeEntry) ) { + NetconfNode nn = (NetconfNode)changeEntry.getValue(); + wasConnected = nn.isConnected(); + } + } + + for (Map.Entry, DataObject> changeEntry : change.getUpdatedData().entrySet()) { + if ( isNetconfNode(changeEntry) ) { + NetconfNode nn = (NetconfNode)changeEntry.getValue(); + nowConnected = nn.isConnected(); + } + } + + if (wasConnected == false && nowConnected == true) { + resubscribeToActiveStreams(); + } + } + + private static boolean isNetconfNode(final Map.Entry, DataObject> changeEntry ) { + return NetconfNode.class.equals(changeEntry.getKey().getTargetType()); + } + +} diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/Topic.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/Topic.java new file mode 100644 index 0000000000..aebde0c043 --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/Topic.java @@ -0,0 +1,84 @@ +/* + * 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.messagebus.app.impl; + +import com.google.common.base.Preconditions; +import java.util.regex.Pattern; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.mdsal.MdSAL; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.NotificationPattern; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventaggregator.rev141202.TopicId; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.EventSourceService; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.JoinTopicInput; +import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.messagebus.eventsource.rev141202.JoinTopicInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.LoggerFactory; + +public class Topic implements DataChangeListener { + private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(Topic.class); + private final NotificationPattern notificationPattern; + private final Pattern nodeIdPattern; + private final TopicId topicId; + private final MdSAL mdSal; + + public Topic(final NotificationPattern notificationPattern, final String nodeIdPattern, final MdSAL mdSal) { + this.notificationPattern = Preconditions.checkNotNull(notificationPattern); + + // FIXME: regex should be the language of nodeIdPattern + final String regex = Util.wildcardToRegex(nodeIdPattern); + this.nodeIdPattern = Pattern.compile(regex); + this.mdSal = Preconditions.checkNotNull(mdSal); + + // FIXME: We need to perform some salting in order to make + // the topic IDs less predictable. + this.topicId = new TopicId(Util.md5String(notificationPattern + nodeIdPattern)); + } + + public TopicId getTopicId() { + return topicId; + } + + @Override + public void onDataChanged(final AsyncDataChangeEvent, DataObject> event) { + // TODO: affected must return topologyNode !!! + final Node node = Util.getAffectedNode(event); + if (nodeIdPattern.matcher(node.getId().getValue()).matches()) { + notifyNode(node.getId()); + } else { + LOG.debug("Skipping node {}", node.getId()); + } + } + + public void notifyNode(final NodeId nodeId) { + JoinTopicInput jti = getJoinTopicInputArgument(nodeId); + EventSourceService ess = mdSal.getRpcService(EventSourceService.class); + + if (ess == null) { + throw new IllegalStateException("EventSourceService is not registered."); + } + + ess.joinTopic(jti); + } + + private JoinTopicInput getJoinTopicInputArgument(final NodeId nodeId) { + NodeRef nodeRef = MdSAL.createNodeRef(nodeId); + JoinTopicInput jti = + new JoinTopicInputBuilder() + .setNode(nodeRef.getValue()) + .setTopicId(topicId) + .setNotificationPattern(notificationPattern) + .build(); + return jti; + } +} diff --git a/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/Util.java b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/Util.java new file mode 100644 index 0000000000..9927d85c3e --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/java/org/opendaylight/controller/messagebus/app/impl/Util.java @@ -0,0 +1,137 @@ +/* + * 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.messagebus.app.impl; + +import com.google.common.util.concurrent.Futures; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Future; +import java.util.regex.Pattern; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; +import org.opendaylight.controller.sal.common.util.Rpcs; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.common.RpcResult; + +public final class Util { + private static final MessageDigest messageDigestTemplate = getDigestInstance(); + + private static MessageDigest getDigestInstance() { + try { + return MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("Unable to get MD5 instance"); + } + } + + public static String md5String(final String inputString) { + + try { + MessageDigest md = (MessageDigest)messageDigestTemplate.clone(); + md.update(inputString.getBytes("UTF-8"), 0, inputString.length()); + return new BigInteger(1, md.digest()).toString(16); + } catch (Exception e) { + throw new RuntimeException("Unable to get MD5 instance"); + } + } + + public static Future> resultFor(final T output) { + RpcResult result = Rpcs.getRpcResult(true, output, Collections.emptyList()); + return Futures.immediateFuture(result); + } + + /** + * Extracts affected node from data change event. + * @param event + * @return + */ + public static Node getAffectedNode(final AsyncDataChangeEvent, DataObject> event) { + // TODO: expect listener method to be called even when change impact node + // TODO: test with change.getCreatedData() + for (Map.Entry, DataObject> changeEntry : event.getUpdatedData().entrySet()) { + if (isNode(changeEntry)) { + return (Node) changeEntry.getValue(); + } + } + + return null; + } + + private static boolean isNode(final Map.Entry, DataObject> changeEntry ) { + return Node.class.equals(changeEntry.getKey().getTargetType()); + } + + /** + * Method filters qnames based on wildcard strings + * + * @param availableQnames + * @param patterh matching pattern + * @return list of filtered qnames + */ + public static List expandQname(final List availableQnames, final Pattern pattern) { + List matchingQnames = new ArrayList<>(); + + for (QName qname : availableQnames) { + String namespace = qname.getNamespace().toString(); + if (pattern.matcher(namespace).matches()) { + matchingQnames.add(qname); + } + } + + return matchingQnames; + } + + /** + * CREDIT to http://www.rgagnon.com/javadetails/java-0515.html + * @param wildcard + * @return + */ + static String wildcardToRegex(final String wildcard){ + StringBuffer s = new StringBuffer(wildcard.length()); + s.append('^'); + for (char c : wildcard.toCharArray()) { + switch(c) { + case '*': + s.append(".*"); + break; + case '?': + s.append('.'); + break; + // escape special regexp-characters + case '(': + case ')': + case '[': + case ']': + case '$': + case '^': + case '.': + case '{': + case '}': + case '|': + case '\\': + s.append("\\"); + s.append(c); + break; + default: + s.append(c); + break; + } + } + s.append('$'); + return s.toString(); + } +} diff --git a/opendaylight/md-sal/messagebus-impl/src/main/yang/messagebus-app-impl.yang b/opendaylight/md-sal/messagebus-impl/src/main/yang/messagebus-app-impl.yang new file mode 100644 index 0000000000..bed6b1085a --- /dev/null +++ b/opendaylight/md-sal/messagebus-impl/src/main/yang/messagebus-app-impl.yang @@ -0,0 +1,64 @@ +module messagebus-app-impl { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:messagebus:app:impl"; + prefix "binding-impl"; + + import config { prefix config; revision-date 2013-04-05; } + import opendaylight-md-sal-binding {prefix sal;} + import opendaylight-md-sal-dom {prefix dom;} + + + description + "Service definition for Message Bus application implementation."; + + revision "2015-02-03" { + description "Second revision. Message Bus opensourcing"; + } + + identity messagebus-app-impl { + base config:module-type; + config:java-name-prefix MessageBusAppImpl; + } + + augment "/config:modules/config:module/config:configuration" { + case messagebus-app-impl { + when "/config:modules/config:module/config:type = 'messagebus-app-impl'"; + + container binding-broker { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity sal:binding-broker-osgi-registry; + } + } + } + + container dom-broker { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity dom:dom-broker-osgi-registry; + } + } + } + + list namespace-to-stream { + key urn-prefix; + + leaf urn-prefix { + type string; + } + + leaf stream-name { + type string; + } + } + } + } + + augment "/config:modules/config:module/config:state" { + case messagebus-app-impl { + when "/config:modules/config:module/config:type = 'messagebus-app-impl'"; + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/pom.xml b/opendaylight/md-sal/pom.xml index 1743b62180..bdeb8a65a8 100644 --- a/opendaylight/md-sal/pom.xml +++ b/opendaylight/md-sal/pom.xml @@ -90,6 +90,10 @@ sal-remoterpc-connector + + + messagebus-api + messagebus-impl diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java index d1c3fefee8..e2aa16918e 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImpl.java @@ -41,7 +41,7 @@ public abstract class AbstractReplicatedLogImpl implements ReplicatedLog { } protected int adjustedIndex(long logEntryIndex) { - if(snapshotIndex < 0){ + if (snapshotIndex < 0) { return (int) logEntryIndex; } return (int) (logEntryIndex - (snapshotIndex + 1)); @@ -134,6 +134,11 @@ public abstract class AbstractReplicatedLogImpl implements ReplicatedLog { return journal.size(); } + @Override + public int dataSize() { + return dataSize; + } + @Override public boolean isPresent(long logEntryIndex) { if (logEntryIndex > lastIndex()) { @@ -200,6 +205,11 @@ public abstract class AbstractReplicatedLogImpl implements ReplicatedLog { previousSnapshotIndex = -1; previousSnapshotTerm = -1; dataSize = 0; + // need to recalc the datasize based on the entries left after precommit. + for(ReplicatedLogEntry logEntry : journal) { + dataSize += logEntry.size(); + } + } @Override diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java index 0fed63098d..935c4f0bbd 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImpl.java @@ -19,7 +19,7 @@ public class FollowerLogInformationImpl implements FollowerLogInformation { private final String id; - private final Stopwatch stopwatch = new Stopwatch(); + private final Stopwatch stopwatch = Stopwatch.createUnstarted(); private final long followerTimeoutMillis; diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java index 3dc6ae469a..854ceb23d0 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/RaftActor.java @@ -31,16 +31,13 @@ import org.opendaylight.controller.cluster.raft.base.messages.ApplyState; import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot; import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply; import org.opendaylight.controller.cluster.raft.base.messages.Replicate; -import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat; import org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot; import org.opendaylight.controller.cluster.raft.behaviors.AbstractRaftActorBehavior; import org.opendaylight.controller.cluster.raft.behaviors.Follower; import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior; import org.opendaylight.controller.cluster.raft.client.messages.FindLeader; import org.opendaylight.controller.cluster.raft.client.messages.FindLeaderReply; -import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply; import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload; -import org.opendaylight.controller.protobuff.messages.cluster.raft.AppendEntriesMessages; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -126,8 +123,7 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor { private void initRecoveryTimer() { if(recoveryTimer == null) { - recoveryTimer = new Stopwatch(); - recoveryTimer.start(); + recoveryTimer = Stopwatch.createStarted(); } } @@ -190,8 +186,7 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor { context.setLastApplied(snapshot.getLastAppliedIndex()); context.setCommitIndex(snapshot.getLastAppliedIndex()); - Stopwatch timer = new Stopwatch(); - timer.start(); + Stopwatch timer = Stopwatch.createStarted(); // Apply the snapshot to the actors state applyRecoverySnapshot(snapshot.getState()); @@ -360,13 +355,6 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor { handleCaptureSnapshotReply(((CaptureSnapshotReply) message).getSnapshot()); } else { - if (!(message instanceof AppendEntriesMessages.AppendEntries) - && !(message instanceof AppendEntriesReply) && !(message instanceof SendHeartBeat)) { - if(LOG.isDebugEnabled()) { - LOG.debug("{}: onReceiveCommand: message: {}", persistenceId(), message.getClass()); - } - } - RaftActorBehavior oldBehavior = currentBehavior; currentBehavior = currentBehavior.handleMessage(getSender(), message); @@ -575,7 +563,7 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor { /** * This method is called during recovery to reconstruct the state of the actor. * - * @param snapshot A snapshot of the state of the actor + * @param snapshotBytes A snapshot of the state of the actor */ protected abstract void applyRecoverySnapshot(byte[] snapshotBytes); @@ -670,12 +658,21 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor { LOG.info("{}: Persisting of snapshot done:{}", persistenceId(), sn.getLogMessage()); - //be greedy and remove entries from in-mem journal which are in the snapshot - // and update snapshotIndex and snapshotTerm without waiting for the success, + long dataThreshold = Runtime.getRuntime().totalMemory() * + getRaftActorContext().getConfigParams().getSnapshotDataThresholdPercentage() / 100; + if (context.getReplicatedLog().dataSize() > dataThreshold) { + // if memory is less, clear the log based on lastApplied. + // this could/should only happen if one of the followers is down + // as normally we keep removing from the log when its replicated to all. + context.getReplicatedLog().snapshotPreCommit(captureSnapshot.getLastAppliedIndex(), + captureSnapshot.getLastAppliedTerm()); - context.getReplicatedLog().snapshotPreCommit( - captureSnapshot.getLastAppliedIndex(), - captureSnapshot.getLastAppliedTerm()); + } else { + // clear the log based on replicatedToAllIndex + context.getReplicatedLog().snapshotPreCommit(captureSnapshot.getReplicatedToAllIndex(), + captureSnapshot.getReplicatedToAllTerm()); + } + getCurrentBehavior().setReplicatedToAllIndex(captureSnapshot.getReplicatedToAllIndex()); LOG.info("{}: Removed in-memory snapshotted entries, adjusted snaphsotIndex:{} " + "and term:{}", persistenceId(), captureSnapshot.getLastAppliedIndex(), @@ -719,13 +716,14 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor { // FIXME: Maybe this should be done after the command is saved journal.subList(adjustedIndex , journal.size()).clear(); - persistence().persist(new DeleteEntries(adjustedIndex), new Procedure(){ + persistence().persist(new DeleteEntries(adjustedIndex), new Procedure() { - @Override public void apply(DeleteEntries param) - throws Exception { + @Override + public void apply(DeleteEntries param) + throws Exception { //FIXME : Doing nothing for now dataSize = 0; - for(ReplicatedLogEntry entry : journal){ + for (ReplicatedLogEntry entry : journal) { dataSize += entry.size(); } } @@ -737,11 +735,6 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor { appendAndPersist(replicatedLogEntry, null); } - @Override - public int dataSize() { - return dataSize; - } - public void appendAndPersist( final ReplicatedLogEntry replicatedLogEntry, final Procedure callback) { @@ -768,7 +761,7 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor { long dataSizeForCheck = dataSize; dataSizeSinceLastSnapshot += logEntrySize; - long journalSize = lastIndex()+1; + long journalSize = lastIndex() + 1; if(!hasFollowers()) { // When we do not have followers we do not maintain an in-memory log @@ -819,12 +812,15 @@ public abstract class RaftActor extends AbstractUntypedPersistentActor { } // send a CaptureSnapshot to self to make the expensive operation async. - getSelf().tell(new CaptureSnapshot( - lastIndex(), lastTerm(), lastAppliedIndex, lastAppliedTerm), + long replicatedToAllIndex = getCurrentBehavior().getReplicatedToAllIndex(); + ReplicatedLogEntry replicatedToAllEntry = context.getReplicatedLog().get(replicatedToAllIndex); + getSelf().tell(new CaptureSnapshot(lastIndex(), lastTerm(), lastAppliedIndex, lastAppliedTerm, + (replicatedToAllEntry != null ? replicatedToAllEntry.getIndex() : -1), + (replicatedToAllEntry != null ? replicatedToAllEntry.getTerm() : -1)), null); context.setSnapshotCaptureInitiated(true); } - if(callback != null){ + if (callback != null){ callback.apply(replicatedLogEntry); } } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java index 80b7ad90d0..82d0839bee 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/ReplicatedLog.java @@ -145,14 +145,14 @@ public interface ReplicatedLog { * sets snapshot term * @param snapshotTerm */ - public void setSnapshotTerm(long snapshotTerm); + void setSnapshotTerm(long snapshotTerm); /** * Clears the journal entries with startIndex(inclusive) and endIndex (exclusive) * @param startIndex * @param endIndex */ - public void clear(int startIndex, int endIndex); + void clear(int startIndex, int endIndex); /** * Handles all the bookkeeping in order to perform a rollback in the @@ -160,20 +160,21 @@ public interface ReplicatedLog { * @param snapshotCapturedIndex * @param snapshotCapturedTerm */ - public void snapshotPreCommit(long snapshotCapturedIndex, long snapshotCapturedTerm); + void snapshotPreCommit(long snapshotCapturedIndex, long snapshotCapturedTerm); /** * Sets the Replicated log to state after snapshot success. */ - public void snapshotCommit(); + void snapshotCommit(); /** * Restores the replicated log to a state in the event of a save snapshot failure */ - public void snapshotRollback(); + void snapshotRollback(); /** * Size of the data in the log (in bytes) */ - public int dataSize(); + int dataSize(); + } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/CaptureSnapshot.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/CaptureSnapshot.java index d4dd3350f3..a96b1e435c 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/CaptureSnapshot.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/CaptureSnapshot.java @@ -14,19 +14,23 @@ public class CaptureSnapshot { private long lastIndex; private long lastTerm; private boolean installSnapshotInitiated; + private long replicatedToAllIndex; + private long replicatedToAllTerm; public CaptureSnapshot(long lastIndex, long lastTerm, - long lastAppliedIndex, long lastAppliedTerm) { - this(lastIndex, lastTerm, lastAppliedIndex, lastAppliedTerm, false); + long lastAppliedIndex, long lastAppliedTerm, long replicatedToAllIndex, long replicatedToAllTerm) { + this(lastIndex, lastTerm, lastAppliedIndex, lastAppliedTerm, replicatedToAllIndex , replicatedToAllTerm, false); } public CaptureSnapshot(long lastIndex, long lastTerm,long lastAppliedIndex, - long lastAppliedTerm, boolean installSnapshotInitiated) { + long lastAppliedTerm, long replicatedToAllIndex, long replicatedToAllTerm, boolean installSnapshotInitiated) { this.lastIndex = lastIndex; this.lastTerm = lastTerm; this.lastAppliedIndex = lastAppliedIndex; this.lastAppliedTerm = lastAppliedTerm; this.installSnapshotInitiated = installSnapshotInitiated; + this.replicatedToAllIndex = replicatedToAllIndex; + this.replicatedToAllTerm = replicatedToAllTerm; } public long getLastAppliedIndex() { @@ -48,4 +52,12 @@ public class CaptureSnapshot { public boolean isInstallSnapshotInitiated() { return installSnapshotInitiated; } + + public long getReplicatedToAllIndex() { + return replicatedToAllIndex; + } + + public long getReplicatedToAllTerm() { + return replicatedToAllTerm; + } } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeader.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeader.java index 9b6c08857a..b2bb127eab 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeader.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractLeader.java @@ -34,7 +34,6 @@ import org.opendaylight.controller.cluster.raft.RaftActorContext; import org.opendaylight.controller.cluster.raft.RaftState; import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry; import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot; -import org.opendaylight.controller.cluster.raft.base.messages.InitiateInstallSnapshot; import org.opendaylight.controller.cluster.raft.base.messages.Replicate; import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat; import org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot; @@ -92,10 +91,8 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { private Optional snapshot; - private long replicatedToAllIndex = -1; - public AbstractLeader(RaftActorContext context) { - super(context); + super(context, RaftState.Leader); final Builder ftlBuilder = ImmutableMap.builder(); for (String followerId : context.getPeerAddresses().keySet()) { @@ -110,7 +107,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { leaderId = context.getId(); - LOG.debug("{}: Election: Leader has following peers: {}", context.getId(), getFollowerIds()); + LOG.debug("{}: Election: Leader has following peers: {}", logName(), getFollowerIds()); minReplicationCount = getMajorityVoteCount(getFollowerIds().size()); @@ -128,7 +125,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { // Upon election: send initial empty AppendEntries RPCs // (heartbeat) to each server; repeat during idle periods to // prevent election timeouts (§5.2) - sendAppendEntries(0); + sendAppendEntries(0, false); } /** @@ -140,10 +137,6 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { return followerToLog.keySet(); } - private Optional getSnapshot() { - return snapshot; - } - @VisibleForTesting void setSnapshot(Optional snapshot) { this.snapshot = snapshot; @@ -153,9 +146,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { protected RaftActorBehavior handleAppendEntries(ActorRef sender, AppendEntries appendEntries) { - if(LOG.isDebugEnabled()) { - LOG.debug("{}: handleAppendEntries: {}", context.getId(), appendEntries); - } + LOG.debug("{}: handleAppendEntries: {}", logName(), appendEntries); return this; } @@ -164,10 +155,10 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { protected RaftActorBehavior handleAppendEntriesReply(ActorRef sender, AppendEntriesReply appendEntriesReply) { - if(! appendEntriesReply.isSuccess()) { - if(LOG.isDebugEnabled()) { - LOG.debug("{}: handleAppendEntriesReply: {}", context.getId(), appendEntriesReply); - } + if(LOG.isTraceEnabled()) { + LOG.trace("{}: handleAppendEntriesReply: {}", logName(), appendEntriesReply); + } else if(LOG.isDebugEnabled() && !appendEntriesReply.isSuccess()) { + LOG.debug("{}: handleAppendEntriesReply: {}", logName(), appendEntriesReply); } // Update the FollowerLogInformation @@ -176,7 +167,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { followerToLog.get(followerId); if(followerLogInformation == null){ - LOG.error("{}: handleAppendEntriesReply - unknown follower {}", context.getId(), followerId); + LOG.error("{}: handleAppendEntriesReply - unknown follower {}", logName(), followerId); return this; } @@ -224,6 +215,9 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { // Apply the change to the state machine if (context.getCommitIndex() > context.getLastApplied()) { + LOG.debug("{}: handleAppendEntriesReply: applying to log - commitIndex: {}, lastAppliedIndex: {}", + logName(), context.getCommitIndex(), context.getLastApplied()); + applyLogToStateMachine(context.getCommitIndex()); } @@ -232,20 +226,21 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { } //Send the next log entry immediately, if possible, no need to wait for heartbeat to trigger that event - sendUpdatesToFollower(followerId, followerLogInformation, false); + sendUpdatesToFollower(followerId, followerLogInformation, false, false); return this; } private void purgeInMemoryLog() { - //find the lowest index across followers which has been replicated to all. -1 if there are no followers. + //find the lowest index across followers which has been replicated to all. + // lastApplied if there are no followers, so that we keep clearing the log for single-node // we would delete the in-mem log from that index on, in-order to minimize mem usage // we would also share this info thru AE with the followers so that they can delete their log entries as well. - long minReplicatedToAllIndex = followerToLog.isEmpty() ? -1 : Long.MAX_VALUE; + long minReplicatedToAllIndex = followerToLog.isEmpty() ? context.getLastApplied() : Long.MAX_VALUE; for (FollowerLogInformation info : followerToLog.values()) { minReplicatedToAllIndex = Math.min(minReplicatedToAllIndex, info.getMatchIndex()); } - replicatedToAllIndex = fakeSnapshot(minReplicatedToAllIndex, replicatedToAllIndex); + super.performSnapshotWithoutCapture(minReplicatedToAllIndex); } @Override @@ -278,11 +273,6 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { return this; } - @Override - public RaftState state() { - return RaftState.Leader; - } - @Override public RaftActorBehavior handleMessage(ActorRef sender, Object originalMessage) { Preconditions.checkNotNull(sender, "sender should not be null"); @@ -295,8 +285,8 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { // set currentTerm = T, convert to follower (§5.1) // This applies to all RPC messages and responses if (rpc.getTerm() > context.getTermInformation().getCurrentTerm()) { - LOG.debug("{}: Term {} in \"{}\" message is greater than leader's term {}", context.getId(), - rpc.getTerm(), rpc, context.getTermInformation().getCurrentTerm()); + LOG.debug("{}: Term {} in \"{}\" message is greater than leader's term {} - switching to Follower", + logName(), rpc.getTerm(), rpc, context.getTermInformation().getCurrentTerm()); context.getTermInformation().updateAndPersist(rpc.getTerm(), null); @@ -309,9 +299,6 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { sendHeartBeat(); return this; - } else if(message instanceof InitiateInstallSnapshot) { - installSnapshotIfNeeded(); - } else if(message instanceof SendInstallSnapshot) { // received from RaftActor setSnapshot(Optional.of(((SendInstallSnapshot) message).getSnapshot())); @@ -332,12 +319,14 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { } private void handleInstallSnapshotReply(InstallSnapshotReply reply) { + LOG.debug("{}: handleInstallSnapshotReply: {}", logName(), reply); + String followerId = reply.getFollowerId(); FollowerToSnapshot followerToSnapshot = mapFollowerToSnapshot.get(followerId); if (followerToSnapshot == null) { LOG.error("{}: FollowerId {} in InstallSnapshotReply not known to Leader", - context.getId(), followerId); + logName(), followerId); return; } @@ -351,8 +340,8 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { //this was the last chunk reply if(LOG.isDebugEnabled()) { LOG.debug("{}: InstallSnapshotReply received, " + - "last chunk received, Chunk:{}. Follower:{} Setting nextIndex:{}", - context.getId(), reply.getChunkIndex(), followerId, + "last chunk received, Chunk: {}. Follower: {} Setting nextIndex: {}", + logName(), reply.getChunkIndex(), followerId, context.getReplicatedLog().getSnapshotIndex() + 1 ); } @@ -363,10 +352,9 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { context.getReplicatedLog().getSnapshotIndex() + 1); mapFollowerToSnapshot.remove(followerId); - if(LOG.isDebugEnabled()) { - LOG.debug("{}: followerToLog.get(followerId).getNextIndex()=" + - context.getId(), followerToLog.get(followerId).getNextIndex()); - } + LOG.debug("{}: follower: {}, matchIndex set to {}, nextIndex set to {}", + logName(), followerId, followerLogInformation.getMatchIndex(), + followerLogInformation.getNextIndex()); if (mapFollowerToSnapshot.isEmpty()) { // once there are no pending followers receiving snapshots @@ -380,7 +368,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { } } else { LOG.info("{}: InstallSnapshotReply received sending snapshot chunk failed, Will retry, Chunk: {}", - context.getId(), reply.getChunkIndex()); + logName(), reply.getChunkIndex()); followerToSnapshot.markSendStatus(false); } @@ -394,7 +382,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { } else { LOG.error("{}: Chunk index {} in InstallSnapshotReply from follower {} does not match expected index {}", - context.getId(), reply.getChunkIndex(), followerId, + logName(), reply.getChunkIndex(), followerId, followerToSnapshot.getChunkIndex()); if(reply.getChunkIndex() == INVALID_CHUNK_INDEX){ @@ -408,9 +396,8 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { private void replicate(Replicate replicate) { long logIndex = replicate.getReplicatedLogEntry().getIndex(); - if(LOG.isDebugEnabled()) { - LOG.debug("{}: Replicate message {}", context.getId(), logIndex); - } + LOG.debug("{}: Replicate message: identifier: {}, logIndex: {}", logName(), + replicate.getIdentifier(), logIndex); // Create a tracker entry we will use this later to notify the // client actor @@ -424,11 +411,11 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { context.setCommitIndex(logIndex); applyLogToStateMachine(logIndex); } else { - sendAppendEntries(0); + sendAppendEntries(0, false); } } - private void sendAppendEntries(long timeSinceLastActivityInterval) { + private void sendAppendEntries(long timeSinceLastActivityInterval, boolean isHeartbeat) { // Send an AppendEntries to all followers for (Entry e : followerToLog.entrySet()) { final String followerId = e.getKey(); @@ -436,7 +423,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { // This checks helps not to send a repeat message to the follower if(!followerLogInformation.isFollowerActive() || followerLogInformation.timeSinceLastActivity() >= timeSinceLastActivityInterval) { - sendUpdatesToFollower(followerId, followerLogInformation, true); + sendUpdatesToFollower(followerId, followerLogInformation, true, isHeartbeat); } } } @@ -449,7 +436,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { */ private void sendUpdatesToFollower(String followerId, FollowerLogInformation followerLogInformation, - boolean sendHeartbeat) { + boolean sendHeartbeat, boolean isHeartbeat) { ActorSelection followerActor = context.getPeerActorSelection(followerId); if (followerActor != null) { @@ -468,32 +455,41 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { } else { long leaderLastIndex = context.getReplicatedLog().lastIndex(); long leaderSnapShotIndex = context.getReplicatedLog().getSnapshotIndex(); - if (isFollowerActive && - context.getReplicatedLog().isPresent(followerNextIndex)) { + + if(!isHeartbeat || LOG.isTraceEnabled()) { + LOG.debug("{}: Checking sendAppendEntries for follower {}, leaderLastIndex: {}, leaderSnapShotIndex: {}", + logName(), followerId, leaderLastIndex, leaderSnapShotIndex); + } + + if (isFollowerActive && context.getReplicatedLog().isPresent(followerNextIndex)) { + + LOG.debug("{}: sendAppendEntries: {} is present for follower {}", logName(), + followerNextIndex, followerId); + // FIXME : Sending one entry at a time final List entries = context.getReplicatedLog().getFrom(followerNextIndex, 1); sendAppendEntriesToFollower(followerActor, followerNextIndex, entries, followerId); } else if (isFollowerActive && followerNextIndex >= 0 && - leaderLastIndex >= followerNextIndex) { + leaderLastIndex > followerNextIndex && !context.isSnapshotCaptureInitiated()) { // if the followers next index is not present in the leaders log, and // if the follower is just not starting and if leader's index is more than followers index // then snapshot should be sent if (LOG.isDebugEnabled()) { - LOG.debug("InitiateInstallSnapshot to follower:{}," + - "follower-nextIndex:{}, leader-snapshot-index:{}, " + - "leader-last-index:{}", followerId, - followerNextIndex, leaderSnapShotIndex, leaderLastIndex - ); + LOG.debug(String.format("%s: InitiateInstallSnapshot to follower: %s," + + "follower-nextIndex: %d, leader-snapshot-index: %d, " + + "leader-last-index: %d", logName(), followerId, + followerNextIndex, leaderSnapShotIndex, leaderLastIndex)); } - actor().tell(new InitiateInstallSnapshot(), actor()); // Send heartbeat to follower whenever install snapshot is initiated. sendAppendEntriesToFollower(followerActor, followerLogInformation.getNextIndex(), Collections.emptyList(), followerId); + initiateCaptureSnapshot(followerId, followerNextIndex); + } else if(sendHeartbeat) { //we send an AppendEntries, even if the follower is inactive // in-order to update the followers timestamp, in case it becomes active again @@ -510,10 +506,10 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { AppendEntries appendEntries = new AppendEntries(currentTerm(), context.getId(), prevLogIndex(followerNextIndex), prevLogTerm(followerNextIndex), entries, - context.getCommitIndex(), replicatedToAllIndex); + context.getCommitIndex(), super.getReplicatedToAllIndex()); - if(!entries.isEmpty()) { - LOG.debug("{}: Sending AppendEntries to follower {}: {}", context.getId(), followerId, + if(!entries.isEmpty() || LOG.isTraceEnabled()) { + LOG.debug("{}: Sending AppendEntries to follower {}: {}", logName(), followerId, appendEntries); } @@ -521,78 +517,60 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { } /** - * An installSnapshot is scheduled at a interval that is a multiple of - * a HEARTBEAT_INTERVAL. This is to avoid the need to check for installing - * snapshots at every heartbeat. - * * Install Snapshot works as follows - * 1. Leader sends a InitiateInstallSnapshot message to self - * 2. Leader then initiates the capture snapshot by sending a CaptureSnapshot message to actor - * 3. RaftActor on receipt of the CaptureSnapshotReply (from Shard), stores the received snapshot in the replicated log + * 1. Leader initiates the capture snapshot by sending a CaptureSnapshot message to actor + * 2. RaftActor on receipt of the CaptureSnapshotReply (from Shard), stores the received snapshot in the replicated log * and makes a call to Leader's handleMessage , with SendInstallSnapshot message. - * 4. Leader , picks the snapshot from im-mem ReplicatedLog and sends it in chunks to the Follower - * 5. On complete, Follower sends back a InstallSnapshotReply. - * 6. On receipt of the InstallSnapshotReply for the last chunk, Leader marks the install complete for that follower + * 3. Leader , picks the snapshot from im-mem ReplicatedLog and sends it in chunks to the Follower + * 4. On complete, Follower sends back a InstallSnapshotReply. + * 5. On receipt of the InstallSnapshotReply for the last chunk, Leader marks the install complete for that follower * and replenishes the memory by deleting the snapshot in Replicated log. - * + * 6. If another follower requires a snapshot and a snapshot has been collected (via CaptureSnapshotReply) + * then send the existing snapshot in chunks to the follower. + * @param followerId + * @param followerNextIndex */ - private void installSnapshotIfNeeded() { - if(LOG.isDebugEnabled()) { - LOG.debug("{}: installSnapshotIfNeeded, followers {}", context.getId(), followerToLog.keySet()); - } - - for (Entry e : followerToLog.entrySet()) { - final ActorSelection followerActor = context.getPeerActorSelection(e.getKey()); - - if (followerActor != null) { - long nextIndex = e.getValue().getNextIndex(); - - if (!context.getReplicatedLog().isPresent(nextIndex) && - context.getReplicatedLog().isInSnapshot(nextIndex)) { - LOG.info("{}: {} follower needs a snapshot install", context.getId(), e.getKey()); - if (snapshot.isPresent()) { - // if a snapshot is present in the memory, most likely another install is in progress - // no need to capture snapshot - sendSnapshotChunk(followerActor, e.getKey()); - - } else if (!context.isSnapshotCaptureInitiated()) { - initiateCaptureSnapshot(); - //we just need 1 follower who would need snapshot to be installed. - // when we have the snapshot captured, we would again check (in SendInstallSnapshot) - // who needs an install and send to all who need - break; - } + private void initiateCaptureSnapshot(String followerId, long followerNextIndex) { + if (!context.getReplicatedLog().isPresent(followerNextIndex) && + context.getReplicatedLog().isInSnapshot(followerNextIndex)) { + if (snapshot.isPresent()) { + // if a snapshot is present in the memory, most likely another install is in progress + // no need to capture snapshot. + // This could happen if another follower needs an install when one is going on. + final ActorSelection followerActor = context.getPeerActorSelection(followerId); + sendSnapshotChunk(followerActor, followerId); + + } else if (!context.isSnapshotCaptureInitiated()) { + + LOG.info("{}: Initiating Snapshot Capture to Install Snapshot, Leader:{}", logName(), getLeaderId()); + ReplicatedLogEntry lastAppliedEntry = context.getReplicatedLog().get(context.getLastApplied()); + long lastAppliedIndex = -1; + long lastAppliedTerm = -1; + + if (lastAppliedEntry != null) { + lastAppliedIndex = lastAppliedEntry.getIndex(); + lastAppliedTerm = lastAppliedEntry.getTerm(); + } else if (context.getReplicatedLog().getSnapshotIndex() > -1) { + lastAppliedIndex = context.getReplicatedLog().getSnapshotIndex(); + lastAppliedTerm = context.getReplicatedLog().getSnapshotTerm(); } + + boolean isInstallSnapshotInitiated = true; + long replicatedToAllIndex = super.getReplicatedToAllIndex(); + ReplicatedLogEntry replicatedToAllEntry = context.getReplicatedLog().get(replicatedToAllIndex); + actor().tell(new CaptureSnapshot(lastIndex(), lastTerm(), lastAppliedIndex, lastAppliedTerm, + (replicatedToAllEntry != null ? replicatedToAllEntry.getIndex() : -1), + (replicatedToAllEntry != null ? replicatedToAllEntry.getTerm() : -1), + isInstallSnapshotInitiated), actor()); + context.setSnapshotCaptureInitiated(true); } } } - // on every install snapshot, we try to capture the snapshot. - // Once a capture is going on, another one issued will get ignored by RaftActor. - private void initiateCaptureSnapshot() { - LOG.info("{}: Initiating Snapshot Capture to Install Snapshot, Leader:{}", context.getId(), getLeaderId()); - ReplicatedLogEntry lastAppliedEntry = context.getReplicatedLog().get(context.getLastApplied()); - long lastAppliedIndex = -1; - long lastAppliedTerm = -1; - - if (lastAppliedEntry != null) { - lastAppliedIndex = lastAppliedEntry.getIndex(); - lastAppliedTerm = lastAppliedEntry.getTerm(); - } else if (context.getReplicatedLog().getSnapshotIndex() > -1) { - lastAppliedIndex = context.getReplicatedLog().getSnapshotIndex(); - lastAppliedTerm = context.getReplicatedLog().getSnapshotTerm(); - } - - boolean isInstallSnapshotInitiated = true; - actor().tell(new CaptureSnapshot(lastIndex(), lastTerm(), - lastAppliedIndex, lastAppliedTerm, isInstallSnapshotInitiated), - actor()); - context.setSnapshotCaptureInitiated(true); - } - private void sendInstallSnapshot() { + LOG.debug("{}: sendInstallSnapshot", logName()); for (Entry e : followerToLog.entrySet()) { ActorSelection followerActor = context.getPeerActorSelection(e.getKey()); @@ -625,19 +603,19 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { context.getReplicatedLog().getSnapshotIndex(), context.getReplicatedLog().getSnapshotTerm(), nextSnapshotChunk, - followerToSnapshot.incrementChunkIndex(), - followerToSnapshot.getTotalChunks(), + followerToSnapshot.incrementChunkIndex(), + followerToSnapshot.getTotalChunks(), Optional.of(followerToSnapshot.getLastChunkHashCode()) ).toSerializable(), actor() ); LOG.info("{}: InstallSnapshot sent to follower {}, Chunk: {}/{}", - context.getId(), followerActor.path(), + logName(), followerActor.path(), followerToSnapshot.getChunkIndex(), followerToSnapshot.getTotalChunks()); } } catch (IOException e) { - LOG.error("{}: InstallSnapshot failed for Leader.", context.getId(), e); + LOG.error("{}: InstallSnapshot failed for Leader.", logName(), e); } } @@ -652,15 +630,16 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { mapFollowerToSnapshot.put(followerId, followerToSnapshot); } ByteString nextChunk = followerToSnapshot.getNextChunk(); - if (LOG.isDebugEnabled()) { - LOG.debug("{}: Leader's snapshot nextChunk size:{}", context.getId(), nextChunk.size()); - } + + LOG.debug("{}: next snapshot chunk size for follower {}: {}", logName(), followerId, nextChunk.size()); + return nextChunk; } private void sendHeartBeat() { if (!followerToLog.isEmpty()) { - sendAppendEntries(context.getConfigParams().getHeartBeatInterval().toMillis()); + LOG.trace("{}: Sending heartbeat", logName()); + sendAppendEntries(context.getConfigParams().getHeartBeatInterval().toMillis(), true); } } @@ -735,7 +714,7 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { ((size % context.getConfigParams().getSnapshotChunkSize()) > 0 ? 1 : 0); if(LOG.isDebugEnabled()) { LOG.debug("{}: Snapshot {} bytes, total chunks to send:{}", - context.getId(), size, totalChunks); + logName(), size, totalChunks); } replyReceivedForOffset = -1; chunkIndex = AbstractLeader.FIRST_CHUNK_INDEX; @@ -803,10 +782,10 @@ public abstract class AbstractLeader extends AbstractRaftActorBehavior { } } - if(LOG.isDebugEnabled()) { - LOG.debug("{}: Next chunk: length={}, offset={},size={}", context.getId(), + + LOG.debug("{}: Next chunk: length={}, offset={},size={}", logName(), snapshotLength, start, size); - } + ByteString substring = getSnapshotBytes().substring(start, start + size); nextChunkHashCode = substring.hashCode(); return substring; diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java index 075b2873e4..0b0b4c7cd6 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehavior.java @@ -14,6 +14,7 @@ import java.util.Random; import java.util.concurrent.TimeUnit; import org.opendaylight.controller.cluster.raft.ClientRequestTracker; import org.opendaylight.controller.cluster.raft.RaftActorContext; +import org.opendaylight.controller.cluster.raft.RaftState; import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry; import org.opendaylight.controller.cluster.raft.SerializationUtils; import org.opendaylight.controller.cluster.raft.base.messages.ApplyLogEntries; @@ -58,10 +59,37 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior { */ protected String leaderId = null; + private long replicatedToAllIndex = -1; - protected AbstractRaftActorBehavior(RaftActorContext context) { + private final String logName; + + private final RaftState state; + + protected AbstractRaftActorBehavior(RaftActorContext context, RaftState state) { this.context = context; + this.state = state; this.LOG = context.getLogger(); + + logName = String.format("%s (%s)", context.getId(), state); + } + + @Override + public RaftState state() { + return state; + } + + public String logName() { + return logName; + } + + @Override + public void setReplicatedToAllIndex(long replicatedToAllIndex) { + this.replicatedToAllIndex = replicatedToAllIndex; + } + + @Override + public long getReplicatedToAllIndex() { + return replicatedToAllIndex; } /** @@ -95,7 +123,7 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior { if (appendEntries.getTerm() < currentTerm()) { if(LOG.isDebugEnabled()) { LOG.debug("{}: Cannot append entries because sender term {} is less than {}", - context.getId(), appendEntries.getTerm(), currentTerm()); + logName(), appendEntries.getTerm(), currentTerm()); } sender.tell( @@ -132,12 +160,9 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior { * @param requestVote * @return */ - protected RaftActorBehavior requestVote(ActorRef sender, - RequestVote requestVote) { + protected RaftActorBehavior requestVote(ActorRef sender, RequestVote requestVote) { - if(LOG.isDebugEnabled()) { - LOG.debug("{}: Received {}", context.getId(), requestVote); - } + LOG.debug("{}: In requestVote: {}", logName(), requestVote); boolean grantVote = false; @@ -173,7 +198,11 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior { } } - sender.tell(new RequestVoteReply(currentTerm(), grantVote), actor()); + RequestVoteReply reply = new RequestVoteReply(currentTerm(), grantVote); + + LOG.debug("{}: requestVote returning: {}", logName(), reply); + + sender.tell(reply, actor()); return this; } @@ -351,12 +380,12 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior { // around as the rest wont be present either LOG.warn( "{}: Missing index {} from log. Cannot apply state. Ignoring {} to {}", - context.getId(), i, i, index); + logName(), i, i, index); break; } } if(LOG.isDebugEnabled()) { - LOG.debug("{}: Setting last applied to {}", context.getId(), newLastApplied); + LOG.debug("{}: Setting last applied to {}", logName(), newLastApplied); } context.setLastApplied(newLastApplied); @@ -390,11 +419,11 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior { } protected RaftActorBehavior switchBehavior(RaftActorBehavior behavior) { - LOG.info("{} :- Switching from behavior {} to {}", context.getId(), this.state(), behavior.state()); + LOG.info("{} :- Switching from behavior {} to {}", logName(), this.state(), behavior.state()); try { close(); } catch (Exception e) { - LOG.error("{}: Failed to close behavior : {}", context.getId(), this.state(), e); + LOG.error("{}: Failed to close behavior : {}", logName(), this.state(), e); } return behavior; @@ -423,17 +452,28 @@ public abstract class AbstractRaftActorBehavior implements RaftActorBehavior { } - protected long fakeSnapshot(final long minReplicatedToAllIndex, final long currentReplicatedIndex) { + /** + * Performs a snapshot with no capture on the replicated log. + * It clears the log from the supplied index or last-applied-1 which ever is minimum. + * + * @param snapshotCapturedIndex + */ + protected void performSnapshotWithoutCapture(final long snapshotCapturedIndex) { // we would want to keep the lastApplied as its used while capturing snapshots - long tempMin = Math.min(minReplicatedToAllIndex, - (context.getLastApplied() > -1 ? context.getLastApplied() - 1 : -1)); + long lastApplied = context.getLastApplied(); + long tempMin = Math.min(snapshotCapturedIndex, (lastApplied > -1 ? lastApplied - 1 : -1)); if (tempMin > -1 && context.getReplicatedLog().isPresent(tempMin)) { - context.getReplicatedLog().snapshotPreCommit(tempMin, context.getTermInformation().getCurrentTerm()); + LOG.debug("{}: fakeSnapshot purging log to {} for term {}", logName(), tempMin, + context.getTermInformation().getCurrentTerm()); + + //use the term of the temp-min, since we check for isPresent, entry will not be null + ReplicatedLogEntry entry = context.getReplicatedLog().get(tempMin); + context.getReplicatedLog().snapshotPreCommit(tempMin, entry.getTerm()); context.getReplicatedLog().snapshotCommit(); - return tempMin; + setReplicatedToAllIndex(tempMin); } - return currentReplicatedIndex; } + } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Candidate.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Candidate.java index 09ffe056c3..b36c41abf2 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Candidate.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Candidate.java @@ -47,12 +47,12 @@ public class Candidate extends AbstractRaftActorBehavior { private final Set peers; public Candidate(RaftActorContext context) { - super(context); + super(context, RaftState.Candidate); peers = context.getPeerAddresses().keySet(); if(LOG.isDebugEnabled()) { - LOG.debug("{}: Election: Candidate has following peers: {}", context.getId(), peers); + LOG.debug("{}: Election: Candidate has following peers: {}", logName(), peers); } votesRequired = getMajorityVoteCount(peers.size()); @@ -65,7 +65,7 @@ public class Candidate extends AbstractRaftActorBehavior { AppendEntries appendEntries) { if(LOG.isDebugEnabled()) { - LOG.debug("{}: handleAppendEntries: {}", context.getId(), appendEntries); + LOG.debug("{}: handleAppendEntries: {}", logName(), appendEntries); } return this; @@ -78,7 +78,10 @@ public class Candidate extends AbstractRaftActorBehavior { } @Override protected RaftActorBehavior handleRequestVoteReply(ActorRef sender, - RequestVoteReply requestVoteReply) { + RequestVoteReply requestVoteReply) { + + LOG.debug("{}: handleRequestVoteReply: {}, current voteCount: {}", logName(), requestVoteReply, + voteCount); if (requestVoteReply.isVoteGranted()) { voteCount++; @@ -91,10 +94,6 @@ public class Candidate extends AbstractRaftActorBehavior { return this; } - @Override public RaftState state() { - return RaftState.Candidate; - } - @Override public RaftActorBehavior handleMessage(ActorRef sender, Object originalMessage) { @@ -105,7 +104,7 @@ public class Candidate extends AbstractRaftActorBehavior { RaftRPC rpc = (RaftRPC) message; if(LOG.isDebugEnabled()) { - LOG.debug("{}: RaftRPC message received {} my term is {}", context.getId(), rpc, + LOG.debug("{}: RaftRPC message received {}, my term is {}", logName(), rpc, context.getTermInformation().getCurrentTerm()); } @@ -120,6 +119,8 @@ public class Candidate extends AbstractRaftActorBehavior { } if (message instanceof ElectionTimeout) { + LOG.debug("{}: Received ElectionTimeout", logName()); + if (votesRequired == 0) { // If there are no peers then we should be a Leader // We wait for the election timeout to occur before declare @@ -146,12 +147,10 @@ public class Candidate extends AbstractRaftActorBehavior { // Increment the election term and vote for self long currentTerm = context.getTermInformation().getCurrentTerm(); - context.getTermInformation().updateAndPersist(currentTerm + 1, - context.getId()); + long newTerm = currentTerm + 1; + context.getTermInformation().updateAndPersist(newTerm, context.getId()); - if(LOG.isDebugEnabled()) { - LOG.debug("{}: Starting new term {}", context.getId(), (currentTerm + 1)); - } + LOG.debug("{}: Starting new term {}", logName(), newTerm); // Request for a vote // TODO: Retry request for vote if replies do not arrive in a reasonable @@ -159,17 +158,17 @@ public class Candidate extends AbstractRaftActorBehavior { for (String peerId : peers) { ActorSelection peerActor = context.getPeerActorSelection(peerId); if(peerActor != null) { - peerActor.tell(new RequestVote( + RequestVote requestVote = new RequestVote( context.getTermInformation().getCurrentTerm(), context.getId(), context.getReplicatedLog().lastIndex(), - context.getReplicatedLog().lastTerm()), - context.getActor() - ); - } - } + context.getReplicatedLog().lastTerm()); + LOG.debug("{}: Sending {} to peer {}", logName(), requestVote, peerId); + peerActor.tell(requestVote, context.getActor()); + } + } } @Override public void close() throws Exception { diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java index 8a0788702d..1e4fcf7225 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/Follower.java @@ -40,7 +40,7 @@ public class Follower extends AbstractRaftActorBehavior { private SnapshotTracker snapshotTracker = null; public Follower(RaftActorContext context) { - super(context); + super(context, RaftState.Follower); scheduleElection(electionDuration()); } @@ -75,10 +75,11 @@ public class Follower extends AbstractRaftActorBehavior { @Override protected RaftActorBehavior handleAppendEntries(ActorRef sender, AppendEntries appendEntries) { - if(appendEntries.getEntries() != null && appendEntries.getEntries().size() > 0) { - if(LOG.isDebugEnabled()) { - LOG.debug("{}: handleAppendEntries: {}", context.getId(), appendEntries); - } + int numLogEntries = appendEntries.getEntries() != null ? appendEntries.getEntries().size() : 0; + if(LOG.isTraceEnabled()) { + LOG.trace("{}: handleAppendEntries: {}", logName(), appendEntries); + } else if(LOG.isDebugEnabled() && numLogEntries > 0) { + LOG.debug("{}: handleAppendEntries: {}", logName(), appendEntries); } // TODO : Refactor this method into a bunch of smaller methods @@ -101,44 +102,31 @@ public class Follower extends AbstractRaftActorBehavior { boolean outOfSync = true; // First check if the logs are in sync or not - if (lastIndex() == -1 - && appendEntries.getPrevLogIndex() != -1) { + long lastIndex = lastIndex(); + if (lastIndex == -1 && appendEntries.getPrevLogIndex() != -1) { // The follower's log is out of sync because the leader does have // an entry at prevLogIndex and this follower has no entries in // it's log. - if(LOG.isDebugEnabled()) { - LOG.debug("{}: The followers log is empty and the senders prevLogIndex is {}", - context.getId(), appendEntries.getPrevLogIndex()); - } - - } else if (lastIndex() > -1 - && appendEntries.getPrevLogIndex() != -1 - && !prevEntryPresent) { + LOG.debug("{}: The followers log is empty and the senders prevLogIndex is {}", + logName(), appendEntries.getPrevLogIndex()); + } else if (lastIndex > -1 && appendEntries.getPrevLogIndex() != -1 && !prevEntryPresent) { // The follower's log is out of sync because the Leader's // prevLogIndex entry was not found in it's log - if(LOG.isDebugEnabled()) { - LOG.debug("{}: The log is not empty but the prevLogIndex {} was not found in it", - context.getId(), appendEntries.getPrevLogIndex()); - } - - } else if (lastIndex() > -1 - && prevEntryPresent - && prevLogTerm != appendEntries.getPrevLogTerm()) { + LOG.debug("{}: The log is not empty but the prevLogIndex {} was not found in it", + logName(), appendEntries.getPrevLogIndex()); + } else if (lastIndex > -1 && prevEntryPresent && prevLogTerm != appendEntries.getPrevLogTerm()) { // The follower's log is out of sync because the Leader's // prevLogIndex entry does exist in the follower's log but it has // a different term in it - if (LOG.isDebugEnabled()) { - LOG.debug( - "{}: Cannot append entries because previous entry term {} is not equal to append entries prevLogTerm {}" - , context.getId(), prevLogTerm - , appendEntries.getPrevLogTerm()); - } + LOG.debug( + "{}: Cannot append entries because previous entry term {} is not equal to append entries prevLogTerm {}", + logName(), prevLogTerm, appendEntries.getPrevLogTerm()); } else { outOfSync = false; } @@ -146,25 +134,19 @@ public class Follower extends AbstractRaftActorBehavior { if (outOfSync) { // We found that the log was out of sync so just send a negative // reply and return - if(LOG.isDebugEnabled()) { - LOG.debug("{}: Follower ({}) is out-of-sync, " + - "so sending negative reply, lastIndex():{}, lastTerm():{}", - context.getId(), context.getId(), lastIndex(), lastTerm() - ); - } - sender.tell( - new AppendEntriesReply(context.getId(), currentTerm(), false, - lastIndex(), lastTerm()), actor() - ); + + LOG.debug("{}: Follower is out-of-sync, so sending negative reply, lastIndex: {}, lastTerm: {}", + logName(), lastIndex, lastTerm()); + + sender.tell(new AppendEntriesReply(context.getId(), currentTerm(), false, lastIndex, + lastTerm()), actor()); return this; } - if (appendEntries.getEntries() != null - && appendEntries.getEntries().size() > 0) { - if(LOG.isDebugEnabled()) { - LOG.debug("{}: Number of entries to be appended = {}", context.getId(), + if (appendEntries.getEntries() != null && appendEntries.getEntries().size() > 0) { + + LOG.debug("{}: Number of entries to be appended = {}", logName(), appendEntries.getEntries().size()); - } // 3. If an existing entry conflicts with a new one (same index // but different terms), delete the existing entry and all that @@ -182,80 +164,75 @@ public class Follower extends AbstractRaftActorBehavior { break; } - if (newEntry.getTerm() == matchEntry - .getTerm()) { + if (newEntry.getTerm() == matchEntry.getTerm()) { continue; } - if(LOG.isDebugEnabled()) { - LOG.debug("{}: Removing entries from log starting at {}", context.getId(), + LOG.debug("{}: Removing entries from log starting at {}", logName(), matchEntry.getIndex()); - } // Entries do not match so remove all subsequent entries - context.getReplicatedLog() - .removeFromAndPersist(matchEntry.getIndex()); + context.getReplicatedLog().removeFromAndPersist(matchEntry.getIndex()); break; } } - if(LOG.isDebugEnabled()) { - LOG.debug("{}: After cleanup entries to be added from = {}", context.getId(), - (addEntriesFrom + lastIndex())); - } + lastIndex = lastIndex(); + LOG.debug("{}: After cleanup entries to be added from = {}", logName(), + (addEntriesFrom + lastIndex)); // 4. Append any new entries not already in the log - for (int i = addEntriesFrom; - i < appendEntries.getEntries().size(); i++) { + for (int i = addEntriesFrom; i < appendEntries.getEntries().size(); i++) { + ReplicatedLogEntry entry = appendEntries.getEntries().get(i); - if(LOG.isDebugEnabled()) { - LOG.debug("{}: Append entry to log {}", context.getId(), - appendEntries.getEntries().get(i).getData()); - } - context.getReplicatedLog().appendAndPersist(appendEntries.getEntries().get(i)); - } + LOG.debug("{}: Append entry to log {}", logName(), entry.getData()); - if(LOG.isDebugEnabled()) { - LOG.debug("{}: Log size is now {}", context.getId(), context.getReplicatedLog().size()); + context.getReplicatedLog().appendAndPersist(entry); } - } + LOG.debug("{}: Log size is now {}", logName(), context.getReplicatedLog().size()); + } // 5. If leaderCommit > commitIndex, set commitIndex = // min(leaderCommit, index of last new entry) + lastIndex = lastIndex(); long prevCommitIndex = context.getCommitIndex(); - context.setCommitIndex(Math.min(appendEntries.getLeaderCommit(), - context.getReplicatedLog().lastIndex())); + context.setCommitIndex(Math.min(appendEntries.getLeaderCommit(), lastIndex)); if (prevCommitIndex != context.getCommitIndex()) { - if(LOG.isDebugEnabled()) { - LOG.debug("{}: Commit index set to {}", context.getId(), context.getCommitIndex()); - } + LOG.debug("{}: Commit index set to {}", logName(), context.getCommitIndex()); } // If commitIndex > lastApplied: increment lastApplied, apply // log[lastApplied] to state machine (§5.3) // check if there are any entries to be applied. last-applied can be equal to last-index if (appendEntries.getLeaderCommit() > context.getLastApplied() && - context.getLastApplied() < lastIndex()) { + context.getLastApplied() < lastIndex) { if(LOG.isDebugEnabled()) { LOG.debug("{}: applyLogToStateMachine, " + - "appendEntries.getLeaderCommit():{}," + - "context.getLastApplied():{}, lastIndex():{}", context.getId(), - appendEntries.getLeaderCommit(), context.getLastApplied(), lastIndex() - ); + "appendEntries.getLeaderCommit(): {}," + + "context.getLastApplied(): {}, lastIndex(): {}", logName(), + appendEntries.getLeaderCommit(), context.getLastApplied(), lastIndex); } applyLogToStateMachine(appendEntries.getLeaderCommit()); } - sender.tell(new AppendEntriesReply(context.getId(), currentTerm(), true, - lastIndex(), lastTerm()), actor()); + AppendEntriesReply reply = new AppendEntriesReply(context.getId(), currentTerm(), true, + lastIndex, lastTerm()); + + if(LOG.isTraceEnabled()) { + LOG.trace("{}: handleAppendEntries returning : {}", logName(), reply); + } else if(LOG.isDebugEnabled() && numLogEntries > 0) { + LOG.debug("{}: handleAppendEntries returning : {}", logName(), reply); + } + + sender.tell(reply, actor()); if (!context.isSnapshotCaptureInitiated()) { - fakeSnapshot(appendEntries.getReplicatedToAllIndex(), appendEntries.getReplicatedToAllIndex()); + super.performSnapshotWithoutCapture(appendEntries.getReplicatedToAllIndex()); } return this; @@ -271,10 +248,6 @@ public class Follower extends AbstractRaftActorBehavior { return this; } - @Override public RaftState state() { - return RaftState.Follower; - } - @Override public RaftActorBehavior handleMessage(ActorRef sender, Object originalMessage) { Object message = fromSerializableMessage(originalMessage); @@ -285,11 +258,15 @@ public class Follower extends AbstractRaftActorBehavior { // set currentTerm = T, convert to follower (§5.1) // This applies to all RPC messages and responses if (rpc.getTerm() > context.getTermInformation().getCurrentTerm()) { + LOG.debug("{}: Term {} in \"{}\" message is greater than follower's term {} - updating term", + logName(), rpc.getTerm(), rpc, context.getTermInformation().getCurrentTerm()); + context.getTermInformation().updateAndPersist(rpc.getTerm(), null); } } if (message instanceof ElectionTimeout) { + LOG.debug("{}: Received ElectionTimeout - switching to Candidate", logName()); return switchBehavior(new Candidate(context)); } else if (message instanceof InstallSnapshot) { @@ -304,12 +281,10 @@ public class Follower extends AbstractRaftActorBehavior { private void handleInstallSnapshot(ActorRef sender, InstallSnapshot installSnapshot) { - if(LOG.isDebugEnabled()) { - LOG.debug("{}: InstallSnapshot received by follower " + - "datasize:{} , Chunk:{}/{}", context.getId(), installSnapshot.getData().size(), - installSnapshot.getChunkIndex(), installSnapshot.getTotalChunks() - ); - } + + LOG.debug("{}: InstallSnapshot received from leader {}, datasize: {} , Chunk: {}/{}", + logName(), installSnapshot.getLeaderId(), installSnapshot.getData().size(), + installSnapshot.getChunkIndex(), installSnapshot.getTotalChunks()); if(snapshotTracker == null){ snapshotTracker = new SnapshotTracker(LOG, installSnapshot.getTotalChunks()); @@ -331,18 +306,23 @@ public class Follower extends AbstractRaftActorBehavior { } - sender.tell(new InstallSnapshotReply( - currentTerm(), context.getId(), installSnapshot.getChunkIndex(), - true), actor()); + InstallSnapshotReply reply = new InstallSnapshotReply( + currentTerm(), context.getId(), installSnapshot.getChunkIndex(), true); + + LOG.debug("{}: handleInstallSnapshot returning: {}", logName(), reply); + + sender.tell(reply, actor()); } catch (SnapshotTracker.InvalidChunkException e) { + LOG.debug("{}: Exception in InstallSnapshot of follower", logName(), e); sender.tell(new InstallSnapshotReply(currentTerm(), context.getId(), -1, false), actor()); snapshotTracker = null; } catch (Exception e){ - LOG.error("{}: Exception in InstallSnapshot of follower", context.getId(), e); + LOG.error("{}: Exception in InstallSnapshot of follower", logName(), e); + //send reply with success as false. The chunk will be sent again on failure sender.tell(new InstallSnapshotReply(currentTerm(), context.getId(), installSnapshot.getChunkIndex(), false), actor()); @@ -358,6 +338,4 @@ public class Follower extends AbstractRaftActorBehavior { ByteString getSnapshotChunksCollected(){ return snapshotTracker != null ? snapshotTracker.getCollectedChunks() : ByteString.EMPTY; } - - } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/RaftActorBehavior.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/RaftActorBehavior.java index 064cd8b88c..b766e0ce39 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/RaftActorBehavior.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/behaviors/RaftActorBehavior.java @@ -50,4 +50,16 @@ public interface RaftActorBehavior extends AutoCloseable{ * @return */ String getLeaderId(); + + /** + * setting the index of the log entry which is replicated to all nodes + * @param replicatedToAllIndex + */ + void setReplicatedToAllIndex(long replicatedToAllIndex); + + /** + * getting the index of the log entry which is replicated to all nodes + * @return + */ + long getReplicatedToAllIndex(); } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntries.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntries.java index 97bcd6a708..d2ea0c50cd 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntries.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntries.java @@ -110,19 +110,15 @@ public class AppendEntries extends AbstractRaftRPC { return replicatedToAllIndex; } + @Override public String toString() { - final StringBuilder sb = - new StringBuilder("AppendEntries{"); - sb.append("term=").append(getTerm()); - sb.append("leaderId='").append(leaderId).append('\''); - sb.append(", prevLogIndex=").append(prevLogIndex); - sb.append(", prevLogTerm=").append(prevLogTerm); - sb.append(", entries=").append(entries); - sb.append(", leaderCommit=").append(leaderCommit); - sb.append(", replicatedToAllIndex=").append(replicatedToAllIndex); - sb.append('}'); - return sb.toString(); + StringBuilder builder = new StringBuilder(); + builder.append("AppendEntries [term=").append(term).append(", leaderId=").append(leaderId) + .append(", prevLogIndex=").append(prevLogIndex).append(", prevLogTerm=").append(prevLogTerm) + .append(", entries=").append(entries).append(", leaderCommit=").append(leaderCommit) + .append(", replicatedToAllIndex=").append(replicatedToAllIndex).append("]"); + return builder.toString(); } public Object toSerializable() { diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesReply.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesReply.java index 32ed85b281..01fef006a9 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesReply.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/AppendEntriesReply.java @@ -59,15 +59,12 @@ public class AppendEntriesReply extends AbstractRaftRPC { return followerId; } - @Override public String toString() { - final StringBuilder sb = - new StringBuilder("AppendEntriesReply{"); - sb.append("term=").append(term); - sb.append(", success=").append(success); - sb.append(", logLastIndex=").append(logLastIndex); - sb.append(", logLastTerm=").append(logLastTerm); - sb.append(", followerId='").append(followerId).append('\''); - sb.append('}'); - return sb.toString(); + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("AppendEntriesReply [term=").append(term).append(", success=").append(success) + .append(", logLastIndex=").append(logLastIndex).append(", logLastTerm=").append(logLastTerm) + .append(", followerId=").append(followerId).append("]"); + return builder.toString(); } } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java index 6337f8f6dc..119b43ce83 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshot.java @@ -102,4 +102,15 @@ public class InstallSnapshot extends AbstractRaftRPC { return installSnapshot; } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("InstallSnapshot [term=").append(term).append(", leaderId=").append(leaderId) + .append(", lastIncludedIndex=").append(lastIncludedIndex).append(", lastIncludedTerm=") + .append(lastIncludedTerm).append(", data=").append(data).append(", chunkIndex=").append(chunkIndex) + .append(", totalChunks=").append(totalChunks).append(", lastChunkHashCode=").append(lastChunkHashCode) + .append("]"); + return builder.toString(); + } } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshotReply.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshotReply.java index 15621bf894..77efa53dfd 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshotReply.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/InstallSnapshotReply.java @@ -36,4 +36,12 @@ public class InstallSnapshotReply extends AbstractRaftRPC { public boolean isSuccess() { return success; } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("InstallSnapshotReply [term=").append(term).append(", followerId=").append(followerId) + .append(", chunkIndex=").append(chunkIndex).append(", success=").append(success).append("]"); + return builder.toString(); + } } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVote.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVote.java index 9ba5acb664..8f162ae254 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVote.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVote.java @@ -64,14 +64,12 @@ public class RequestVote extends AbstractRaftRPC { this.lastLogTerm = lastLogTerm; } - @Override public String toString() { - final StringBuilder sb = - new StringBuilder("RequestVote{"); - sb.append("term='").append(getTerm()).append('\''); - sb.append("candidateId='").append(candidateId).append('\''); - sb.append(", lastLogIndex=").append(lastLogIndex); - sb.append(", lastLogTerm=").append(lastLogTerm); - sb.append('}'); - return sb.toString(); + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("RequestVote [term=").append(term).append(", candidateId=").append(candidateId) + .append(", lastLogIndex=").append(lastLogIndex).append(", lastLogTerm=").append(lastLogTerm) + .append("]"); + return builder.toString(); } } diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVoteReply.java b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVoteReply.java index b3c95d6eca..865d4c287b 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVoteReply.java +++ b/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/messages/RequestVoteReply.java @@ -27,4 +27,11 @@ public class RequestVoteReply extends AbstractRaftRPC { public boolean isVoteGranted() { return voteGranted; } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("RequestVoteReply [term=").append(term).append(", voteGranted=").append(voteGranted).append("]"); + return builder.toString(); + } } diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java index ffd8edfbe1..885c3ab109 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/AbstractReplicatedLogImplTest.java @@ -20,6 +20,7 @@ import org.junit.Before; import org.junit.Test; import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload; import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockReplicatedLogEntry; + /** * */ @@ -130,11 +131,17 @@ public class AbstractReplicatedLogImplTest { @Test public void testSnapshotPreCommit() { + //add 4 more entries replicatedLogImpl.append(new MockReplicatedLogEntry(2, 4, new MockPayload("E"))); replicatedLogImpl.append(new MockReplicatedLogEntry(2, 5, new MockPayload("F"))); replicatedLogImpl.append(new MockReplicatedLogEntry(3, 6, new MockPayload("G"))); replicatedLogImpl.append(new MockReplicatedLogEntry(3, 7, new MockPayload("H"))); + //sending negative values should not cause any changes + replicatedLogImpl.snapshotPreCommit(-1, -1); + assertEquals(8, replicatedLogImpl.size()); + assertEquals(-1, replicatedLogImpl.getSnapshotIndex()); + replicatedLogImpl.snapshotPreCommit(4, 3); assertEquals(3, replicatedLogImpl.size()); assertEquals(4, replicatedLogImpl.getSnapshotIndex()); @@ -152,7 +159,31 @@ public class AbstractReplicatedLogImplTest { assertEquals(0, replicatedLogImpl.size()); assertEquals(7, replicatedLogImpl.getSnapshotIndex()); + } + + @Test + public void testIsPresent() { + assertTrue(replicatedLogImpl.isPresent(0)); + assertTrue(replicatedLogImpl.isPresent(1)); + assertTrue(replicatedLogImpl.isPresent(2)); + assertTrue(replicatedLogImpl.isPresent(3)); + + replicatedLogImpl.append(new MockReplicatedLogEntry(2, 4, new MockPayload("D"))); + replicatedLogImpl.snapshotPreCommit(3, 2); //snapshot on 3 + replicatedLogImpl.snapshotCommit(); + + assertFalse(replicatedLogImpl.isPresent(0)); + assertFalse(replicatedLogImpl.isPresent(1)); + assertFalse(replicatedLogImpl.isPresent(2)); + assertFalse(replicatedLogImpl.isPresent(3)); + assertTrue(replicatedLogImpl.isPresent(4)); + + replicatedLogImpl.snapshotPreCommit(4, 2); //snapshot on 4 + replicatedLogImpl.snapshotCommit(); + assertFalse(replicatedLogImpl.isPresent(4)); + replicatedLogImpl.append(new MockReplicatedLogEntry(2, 5, new MockPayload("D"))); + assertTrue(replicatedLogImpl.isPresent(5)); } // create a snapshot for test diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImplTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImplTest.java index a092c46533..84d1545a65 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImplTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/FollowerLogInformationImplTest.java @@ -55,8 +55,7 @@ public class FollowerLogInformationImplTest { // hence getting the actual elapsed time and do a match. // if the sleep has spilled over, then return the test gracefully private long sleepWithElaspsedTimeReturned(long millis) { - Stopwatch stopwatch = new Stopwatch(); - stopwatch.start(); + Stopwatch stopwatch = Stopwatch.createStarted(); Uninterruptibles.sleepUninterruptibly(millis, TimeUnit.MILLISECONDS); stopwatch.stop(); return stopwatch.elapsed(TimeUnit.MILLISECONDS); diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java index 56bf6200dc..1cd8550be7 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/RaftActorTest.java @@ -60,7 +60,7 @@ import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot; import org.opendaylight.controller.cluster.raft.base.messages.ApplyState; import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot; import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply; -import org.opendaylight.controller.cluster.raft.base.messages.InitiateInstallSnapshot; +import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat; import org.opendaylight.controller.cluster.raft.behaviors.Follower; import org.opendaylight.controller.cluster.raft.behaviors.Leader; import org.opendaylight.controller.cluster.raft.client.messages.FindLeader; @@ -691,7 +691,7 @@ public class RaftActorTest extends AbstractActorTest { new MockRaftActorContext.MockPayload("C"), new MockRaftActorContext.MockPayload("D"))); - mockRaftActor.onReceiveCommand(new CaptureSnapshot(-1, 1, -1, 1)); + mockRaftActor.onReceiveCommand(new CaptureSnapshot(-1, 1,-1, 1, -1, 1)); RaftActorContext raftActorContext = mockRaftActor.getRaftActorContext(); @@ -737,7 +737,8 @@ public class RaftActorTest extends AbstractActorTest { RaftActorContext raftActorContext = mockRaftActor.getRaftActorContext(); mockRaftActor.setCurrentBehavior(new Follower(raftActorContext)); - mockRaftActor.onReceiveCommand(new CaptureSnapshot(-1, 1, 2, 1)); + long replicatedToAllIndex = 1; + mockRaftActor.onReceiveCommand(new CaptureSnapshot(-1, 1, 2, 1, replicatedToAllIndex, 1)); verify(mockRaftActor.delegate).createSnapshot(); @@ -749,13 +750,16 @@ public class RaftActorTest extends AbstractActorTest { verify(dataPersistenceProvider).deleteMessages(100); - assertEquals(2, mockRaftActor.getReplicatedLog().size()); + assertEquals(3, mockRaftActor.getReplicatedLog().size()); + assertEquals(1, mockRaftActor.getCurrentBehavior().getReplicatedToAllIndex()); + assertNotNull(mockRaftActor.getReplicatedLog().get(2)); assertNotNull(mockRaftActor.getReplicatedLog().get(3)); assertNotNull(mockRaftActor.getReplicatedLog().get(4)); // Index 2 will not be in the log because it was removed due to snapshotting - assertNull(mockRaftActor.getReplicatedLog().get(2)); + assertNull(mockRaftActor.getReplicatedLog().get(1)); + assertNull(mockRaftActor.getReplicatedLog().get(0)); } }; @@ -870,7 +874,7 @@ public class RaftActorTest extends AbstractActorTest { mockRaftActor.setCurrentBehavior(new Leader(raftActorContext)); - mockRaftActor.onReceiveCommand(new CaptureSnapshot(-1, 1, -1, 1)); + mockRaftActor.onReceiveCommand(new CaptureSnapshot(-1, 1, -1, 1, -1, 1)); mockRaftActor.onReceiveCommand(new CaptureSnapshotReply(snapshotBytes.toByteArray())); @@ -962,7 +966,8 @@ public class RaftActorTest extends AbstractActorTest { assertEquals(8, leaderActor.getReplicatedLog().size()); - leaderActor.onReceiveCommand(new CaptureSnapshot(6, 1, 4, 1)); + leaderActor.onReceiveCommand(new CaptureSnapshot(6, 1, 4, 1, 4, 1)); + leaderActor.getRaftActorContext().setSnapshotCaptureInitiated(true); verify(leaderActor.delegate).createSnapshot(); @@ -1040,19 +1045,21 @@ public class RaftActorTest extends AbstractActorTest { followerActor.waitForInitializeBehaviorComplete(); - // create 8 entries in the log - 0 to 4 are applied and will get picked up as part of the capture snapshot + Follower follower = new Follower(followerActor.getRaftActorContext()); followerActor.setCurrentBehavior(follower); assertEquals(RaftState.Follower, followerActor.getCurrentBehavior().state()); + // create 6 entries in the log - 0 to 4 are applied and will get picked up as part of the capture snapshot MockRaftActorContext.MockReplicatedLogBuilder logBuilder = new MockRaftActorContext.MockReplicatedLogBuilder(); followerActor.getRaftActorContext().setReplicatedLog(logBuilder.createEntries(0, 6, 1).build()); - // log as indices 0-5 + // log has indices 0-5 assertEquals(6, followerActor.getReplicatedLog().size()); //snapshot on 4 - followerActor.onReceiveCommand(new CaptureSnapshot(5, 1, 4, 1)); + followerActor.onReceiveCommand(new CaptureSnapshot(5, 1, 4, 1, 4, 1)); + followerActor.getRaftActorContext().setSnapshotCaptureInitiated(true); verify(followerActor.delegate).createSnapshot(); @@ -1090,7 +1097,7 @@ public class RaftActorTest extends AbstractActorTest { followerActor.onReceiveCommand(new CaptureSnapshotReply(snapshotBytes.toByteArray())); assertFalse(followerActor.getRaftActorContext().isSnapshotCaptureInitiated()); - // capture snapshot reply should remove the snapshotted entries only + // capture snapshot reply should remove the snapshotted entries only till replicatedToAllIndex assertEquals(3, followerActor.getReplicatedLog().size()); //indexes 5,6,7 left in the log assertEquals(7, followerActor.getReplicatedLog().lastIndex()); @@ -1150,19 +1157,25 @@ public class RaftActorTest extends AbstractActorTest { // create 5 entries in the log MockRaftActorContext.MockReplicatedLogBuilder logBuilder = new MockRaftActorContext.MockReplicatedLogBuilder(); leaderActor.getRaftActorContext().setReplicatedLog(logBuilder.createEntries(5, 10, 1).build()); + //set the snapshot index to 4 , 0 to 4 are snapshotted leaderActor.getRaftActorContext().getReplicatedLog().setSnapshotIndex(4); + //setting replicatedToAllIndex = 9, for the log to clear + leader.setReplicatedToAllIndex(9); assertEquals(5, leaderActor.getReplicatedLog().size()); + assertEquals(RaftState.Leader, leaderActor.getCurrentBehavior().state()); leaderActor.onReceiveCommand(new AppendEntriesReply(follower1Id, 1, true, 9, 1)); assertEquals(5, leaderActor.getReplicatedLog().size()); + assertEquals(RaftState.Leader, leaderActor.getCurrentBehavior().state()); // set the 2nd follower nextIndex to 1 which has been snapshotted leaderActor.onReceiveCommand(new AppendEntriesReply(follower2Id, 1, true, 0, 1)); assertEquals(5, leaderActor.getReplicatedLog().size()); + assertEquals(RaftState.Leader, leaderActor.getCurrentBehavior().state()); // simulate a real snapshot - leaderActor.onReceiveCommand(new InitiateInstallSnapshot()); + leaderActor.onReceiveCommand(new SendHeartBeat()); assertEquals(5, leaderActor.getReplicatedLog().size()); assertEquals(String.format("expected to be Leader but was %s. Current Leader = %s ", leaderActor.getCurrentBehavior().state(), leaderActor.getLeaderId()) @@ -1182,7 +1195,7 @@ public class RaftActorTest extends AbstractActorTest { leaderActor.onReceiveCommand(new CaptureSnapshotReply(snapshotBytes.toByteArray())); assertFalse(leaderActor.getRaftActorContext().isSnapshotCaptureInitiated()); - assertEquals("Real snapshot didn't clear the log till lastApplied", 0, leaderActor.getReplicatedLog().size()); + assertEquals("Real snapshot didn't clear the log till replicatedToAllIndex", 0, leaderActor.getReplicatedLog().size()); //reply from a slow follower after should not raise errors leaderActor.onReceiveCommand(new AppendEntriesReply(follower2Id, 1, true, 5, 1)); diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehaviorTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehaviorTest.java index 42a7911be3..c133c0615f 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehaviorTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehaviorTest.java @@ -1,8 +1,12 @@ package org.opendaylight.controller.cluster.raft.behaviors; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import akka.actor.ActorRef; import akka.actor.Props; import akka.testkit.JavaTestKit; +import java.util.ArrayList; +import java.util.List; import org.junit.Test; import org.opendaylight.controller.cluster.raft.AbstractActorTest; import org.opendaylight.controller.cluster.raft.MockRaftActorContext; @@ -17,12 +21,6 @@ import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply; import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload; import org.opendaylight.controller.cluster.raft.utils.DoNothingActor; -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest { private final ActorRef behaviorActor = getSystem().actorOf(Props.create( @@ -302,38 +300,52 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest { } @Test - public void testFakeSnapshots() { + public void testPerformSnapshot() { MockRaftActorContext context = new MockRaftActorContext("test", getSystem(), behaviorActor); - AbstractRaftActorBehavior behavior = new Leader(context); - context.getTermInformation().update(1, "leader"); + AbstractRaftActorBehavior abstractBehavior = (AbstractRaftActorBehavior) createBehavior(context); + if (abstractBehavior instanceof Candidate) { + return; + } - //entry with 1 index=0 entry with replicatedToAllIndex = 0, does not do anything, returns the + context.getTermInformation().update(1, "test"); + + //log has 1 entry with replicatedToAllIndex = 0, does not do anything, returns the context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 1, 1).build()); context.setLastApplied(0); - assertEquals(-1, behavior.fakeSnapshot(0, -1)); + abstractBehavior.performSnapshotWithoutCapture(0); + assertEquals(-1, abstractBehavior.getReplicatedToAllIndex()); assertEquals(1, context.getReplicatedLog().size()); //2 entries, lastApplied still 0, no purging. - context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0,2,1).build()); + context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 2, 1).build()); context.setLastApplied(0); - assertEquals(-1, behavior.fakeSnapshot(0, -1)); + abstractBehavior.performSnapshotWithoutCapture(0); + assertEquals(-1, abstractBehavior.getReplicatedToAllIndex()); assertEquals(2, context.getReplicatedLog().size()); //2 entries, lastApplied still 0, no purging. - context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0,2,1).build()); + context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 2, 1).build()); context.setLastApplied(1); - assertEquals(0, behavior.fakeSnapshot(0, -1)); + abstractBehavior.performSnapshotWithoutCapture(0); + assertEquals(0, abstractBehavior.getReplicatedToAllIndex()); assertEquals(1, context.getReplicatedLog().size()); //5 entries, lastApplied =2 and replicatedIndex = 3, but since we want to keep the lastapplied, indices 0 and 1 will only get purged - context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0,5,1).build()); + context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 5, 1).build()); context.setLastApplied(2); - assertEquals(1, behavior.fakeSnapshot(3, 1)); + abstractBehavior.performSnapshotWithoutCapture(3); + assertEquals(1, abstractBehavior.getReplicatedToAllIndex()); assertEquals(3, context.getReplicatedLog().size()); - + // scenario where Last applied > Replicated to all index (becoz of a slow follower) + context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(0, 3, 1).build()); + context.setLastApplied(2); + abstractBehavior.performSnapshotWithoutCapture(1); + assertEquals(1, abstractBehavior.getReplicatedToAllIndex()); + assertEquals(1, context.getReplicatedLog().size()); } + protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm( ActorRef actorRef, RaftRPC rpc) { diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java index 8251c6b265..119b958799 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java @@ -31,7 +31,6 @@ import org.opendaylight.controller.cluster.raft.SerializationUtils; import org.opendaylight.controller.cluster.raft.base.messages.ApplyLogEntries; import org.opendaylight.controller.cluster.raft.base.messages.ApplyState; import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot; -import org.opendaylight.controller.cluster.raft.base.messages.InitiateInstallSnapshot; import org.opendaylight.controller.cluster.raft.base.messages.IsolatedLeaderCheck; import org.opendaylight.controller.cluster.raft.base.messages.Replicate; import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat; @@ -359,23 +358,23 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest { assertTrue(raftBehavior instanceof Leader); - // we might receive some heartbeat messages, so wait till we InitiateInstallSnapshot + // we might receive some heartbeat messages, so wait till we get CaptureSnapshot Boolean[] matches = new ReceiveWhile(Boolean.class, duration("2 seconds")) { @Override protected Boolean match(Object o) throws Exception { - if (o instanceof InitiateInstallSnapshot) { + if (o instanceof CaptureSnapshot) { return true; } return false; } }.get(); - boolean initiateInitiateInstallSnapshot = false; + boolean captureSnapshot = false; for (Boolean b: matches) { - initiateInitiateInstallSnapshot = b | initiateInitiateInstallSnapshot; + captureSnapshot = b | captureSnapshot; } - assertTrue(initiateInitiateInstallSnapshot); + assertTrue(captureSnapshot); }}; } @@ -388,12 +387,9 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest { ActorRef followerActor = getTestActor(); Map peerAddresses = new HashMap<>(); - peerAddresses.put(followerActor.path().toString(), - followerActor.path().toString()); - + peerAddresses.put(followerActor.path().toString(), followerActor.path().toString()); - MockRaftActorContext actorContext = - (MockRaftActorContext) createActorContext(leaderActor); + MockRaftActorContext actorContext = (MockRaftActorContext) createActorContext(leaderActor); actorContext.setPeerAddresses(peerAddresses); Map leadersSnapshot = new HashMap<>(); @@ -421,15 +417,16 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest { leader.setSnapshot(Optional.absent()); // new entry - ReplicatedLogImplEntry entry = - new ReplicatedLogImplEntry(newEntryIndex, currentTerm, + ReplicatedLogImplEntry entry = new ReplicatedLogImplEntry(newEntryIndex, currentTerm, new MockRaftActorContext.MockPayload("D")); actorContext.getReplicatedLog().append(entry); - // this should invoke a sendinstallsnapshot as followersLastIndex < snapshotIndex + //update follower timestamp + leader.markFollowerActive(followerActor.path().toString()); + RaftActorBehavior raftBehavior = leader.handleMessage( - leaderActor, new InitiateInstallSnapshot()); + senderActor, new Replicate(null, "state-id", entry)); CaptureSnapshot cs = MessageCollectorActor. getFirstMatching(leaderActor, CaptureSnapshot.class); @@ -443,7 +440,7 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest { assertEquals(2, cs.getLastTerm()); // if an initiate is started again when first is in progress, it shouldnt initiate Capture - raftBehavior = leader.handleMessage(leaderActor, new InitiateInstallSnapshot()); + leader.handleMessage(senderActor, new Replicate(null, "state-id", entry)); List captureSnapshots = MessageCollectorActor.getAllMatching(leaderActor, CaptureSnapshot.class); assertEquals("CaptureSnapshot should not get invoked when initiate is in progress", 1, captureSnapshots.size()); diff --git a/opendaylight/md-sal/sal-binding-dom-it/pom.xml b/opendaylight/md-sal/sal-binding-dom-it/pom.xml index 01cd1f88ba..d6a5e498b6 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/pom.xml +++ b/opendaylight/md-sal/sal-binding-dom-it/pom.xml @@ -29,11 +29,6 @@ test-jar test - - org.opendaylight.controller.model - model-flow-service - test - org.ops4j.pax.exam pax-exam-container-native @@ -49,10 +44,14 @@ yang-parser-impl test - - org.opendaylight.controller - sal-test-model - + + org.opendaylight.controller + sal-test-model + + + org.opendaylight.yangtools.model + opendaylight-l2-types + diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ConcurrentImplicitCreateTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ConcurrentImplicitCreateTest.java index aefc53b124..3d25018e24 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ConcurrentImplicitCreateTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/ConcurrentImplicitCreateTest.java @@ -17,26 +17,25 @@ import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; -/* +/** * FIXME: THis test should be moved to sal-binding-broker and rewriten * to use new DataBroker API */ @SuppressWarnings("deprecation") public class ConcurrentImplicitCreateTest extends AbstractDataServiceTest { - private static final NodeKey NODE_FOO_KEY = new NodeKey(new NodeId("foo")); - private static final NodeKey NODE_BAR_KEY = new NodeKey(new NodeId("foo")); - private static InstanceIdentifier NODES_PATH = InstanceIdentifier.builder(Nodes.class).build(); - private static InstanceIdentifier NODE_FOO_PATH = NODES_PATH.child(Node.class, NODE_FOO_KEY); - private static InstanceIdentifier NODE_BAR_PATH = NODES_PATH.child(Node.class, NODE_FOO_KEY); + private static final TopLevelListKey FOO_KEY = new TopLevelListKey("foo"); + private static final TopLevelListKey BAR_KEY = new TopLevelListKey("bar"); + private static InstanceIdentifier TOP_PATH = InstanceIdentifier.builder(Top.class).build(); + private static InstanceIdentifier FOO_PATH = TOP_PATH.child(TopLevelList.class, FOO_KEY); + private static InstanceIdentifier BAR_PATH = TOP_PATH.child(TopLevelList.class, BAR_KEY); @Test public void testConcurrentCreate() throws InterruptedException, ExecutionException { @@ -44,8 +43,8 @@ public class ConcurrentImplicitCreateTest extends AbstractDataServiceTest { DataModificationTransaction fooTx = baDataService.beginTransaction(); DataModificationTransaction barTx = baDataService.beginTransaction(); - fooTx.putOperationalData(NODE_FOO_PATH, new NodeBuilder().setKey(NODE_FOO_KEY).build()); - barTx.putOperationalData(NODE_BAR_PATH, new NodeBuilder().setKey(NODE_BAR_KEY).build()); + fooTx.putOperationalData(FOO_PATH, new TopLevelListBuilder().setKey(FOO_KEY).build()); + barTx.putOperationalData(BAR_PATH, new TopLevelListBuilder().setKey(BAR_KEY).build()); Future> fooFuture = fooTx.commit(); Future> barFuture = barTx.commit(); diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java index 2b5171369b..0a611a75d0 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/md/sal/binding/data/WildcardedDataChangeListenerTest.java @@ -22,87 +22,75 @@ import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.controller.sal.binding.api.data.DataProviderService; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures; -import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeaturesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ContainerWithUses; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUses; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ListViaUsesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import com.google.common.util.concurrent.SettableFuture; -/* - * FIXME: THis test should be moved to compat test-suite and rewriten - * to use sal-test-model +/** + * FIXME: THis test should be moved to compat test-suite */ @SuppressWarnings("deprecation") public class WildcardedDataChangeListenerTest extends AbstractDataServiceTest { - private static final NodeKey NODE_0_KEY = new NodeKey(new NodeId("test:0")); - private static final NodeKey NODE_1_KEY = new NodeKey(new NodeId("test:1")); + private static final TopLevelListKey TOP_LEVEL_LIST_0_KEY = new TopLevelListKey("test:0"); + private static final TopLevelListKey TOP_LEVEL_LIST_1_KEY = new TopLevelListKey("test:1"); - public static final InstanceIdentifier DEEP_WILDCARDED_PATH = InstanceIdentifier.builder(Nodes.class) - .child(Node.class) // - .augmentation(FlowCapableNode.class) // - .child(Table.class) // - .child(Flow.class) // + protected static final InstanceIdentifier DEEP_WILDCARDED_PATH = InstanceIdentifier + .builder(Top.class) + .child(TopLevelList.class) // + .augmentation(TreeComplexUsesAugment.class) // + .child(ListViaUses.class) // .build(); - private static final TableKey TABLE_0_KEY = new TableKey((short) 0); - private static final TableFeaturesKey TABLE_FEATURES_KEY = new TableFeaturesKey((short) 0); - - private static final InstanceIdentifier NODE_0_TABLE_PATH = InstanceIdentifier.builder(Nodes.class) - .child(Node.class, NODE_0_KEY) // - .augmentation(FlowCapableNode.class) // - .child(Table.class, TABLE_0_KEY) // + private static final InstanceIdentifier NODE_0_TCU_PATH = InstanceIdentifier + .builder(Top.class) + .child(TopLevelList.class, TOP_LEVEL_LIST_0_KEY) // + .augmentation(TreeComplexUsesAugment.class) // .build(); - private static final InstanceIdentifier
NODE_1_TABLE_PATH = InstanceIdentifier.builder(Nodes.class) - .child(Node.class, NODE_1_KEY) // - .augmentation(FlowCapableNode.class) // - .child(Table.class, TABLE_0_KEY) // + private static final InstanceIdentifier NODE_1_TCU_PATH = InstanceIdentifier + .builder(Top.class) + .child(TopLevelList.class, TOP_LEVEL_LIST_1_KEY) // + .augmentation(TreeComplexUsesAugment.class) // .build(); - private static final FlowKey FLOW_KEY = new FlowKey(new FlowId("test")); - private static final InstanceIdentifier NODE_0_FLOW_PATH = NODE_0_TABLE_PATH.child(Flow.class, FLOW_KEY); + private static final ListViaUsesKey LIST_VIA_USES_KEY = new ListViaUsesKey("test"); + + private static final InstanceIdentifier NODE_0_LVU_PATH = NODE_0_TCU_PATH.child(ListViaUses.class, LIST_VIA_USES_KEY); - private static final InstanceIdentifier NODE_1_FLOW_PATH = NODE_1_TABLE_PATH.child(Flow.class, FLOW_KEY); + private static final InstanceIdentifier NODE_1_LVU_PATH = NODE_1_TCU_PATH.child(ListViaUses.class, LIST_VIA_USES_KEY); - private static final InstanceIdentifier NODE_0_TABLE_FEATURES_PATH = - NODE_0_TABLE_PATH.child(TableFeatures.class, TABLE_FEATURES_KEY); + private static final InstanceIdentifier NODE_0_CWU_PATH = + NODE_0_TCU_PATH.child(ContainerWithUses.class); - private static final TableFeatures TABLE_FEATURES = new TableFeaturesBuilder()// - .setKey(TABLE_FEATURES_KEY) // - .setName("Foo") // - .setMaxEntries(1000L) // + private static final ContainerWithUses CWU= new ContainerWithUsesBuilder()// + .setLeafFromGrouping("some container value") // .build(); - private static final Flow FLOW = new FlowBuilder() // - .setKey(FLOW_KEY) // - .setBarrier(true) // - .setStrict(true) // + private static final ListViaUses LVU = new ListViaUsesBuilder() // + .setKey(LIST_VIA_USES_KEY) // + .setName("john") .build(); @Test - public void testSepareteWrites() throws InterruptedException, TimeoutException, ExecutionException { + public void testSeparateWrites() throws InterruptedException, TimeoutException, ExecutionException { DataProviderService dataBroker = testContext.getBindingDataBroker(); final SettableFuture, DataObject>> eventFuture = SettableFuture.create(); dataBroker.registerDataChangeListener(DEEP_WILDCARDED_PATH, new DataChangeListener() { - @Override public void onDataChanged(final DataChangeEvent, DataObject> dataChangeEvent) { eventFuture.set(dataChangeEvent); @@ -110,9 +98,9 @@ public class WildcardedDataChangeListenerTest extends AbstractDataServiceTest { }); DataModificationTransaction transaction = dataBroker.beginTransaction(); - transaction.putOperationalData(NODE_0_TABLE_FEATURES_PATH, TABLE_FEATURES); - transaction.putOperationalData(NODE_0_FLOW_PATH, FLOW); - transaction.putOperationalData(NODE_1_FLOW_PATH, FLOW); + transaction.putOperationalData(NODE_0_CWU_PATH, CWU); + transaction.putOperationalData(NODE_0_LVU_PATH, LVU); + transaction.putOperationalData(NODE_1_LVU_PATH, LVU); transaction.commit().get(); DataChangeEvent, DataObject> event = eventFuture.get(1000, TimeUnit.MILLISECONDS); @@ -127,29 +115,26 @@ public class WildcardedDataChangeListenerTest extends AbstractDataServiceTest { final SettableFuture, DataObject>> eventFuture = SettableFuture.create(); dataBroker.registerDataChangeListener(DEEP_WILDCARDED_PATH, new DataChangeListener() { - @Override public void onDataChanged(final DataChangeEvent, DataObject> dataChangeEvent) { eventFuture.set(dataChangeEvent); } }); - DataModificationTransaction tableTx = dataBroker.beginTransaction(); - tableTx.putOperationalData(NODE_0_TABLE_FEATURES_PATH, TABLE_FEATURES); - tableTx.commit().get(); + DataModificationTransaction cwuTx = dataBroker.beginTransaction(); + cwuTx.putOperationalData(NODE_0_CWU_PATH, CWU); + cwuTx.commit().get(); assertFalse(eventFuture.isDone()); - DataModificationTransaction flowTx = dataBroker.beginTransaction(); + DataModificationTransaction lvuTx = dataBroker.beginTransaction(); - Table table = new TableBuilder() // - .setKey(TABLE_0_KEY) // - .setFlow(Collections.singletonList(FLOW)) // - .build(); + TreeComplexUsesAugment tcua = new TreeComplexUsesAugmentBuilder() + .setListViaUses(Collections.singletonList(LVU)).build(); - flowTx.putOperationalData(NODE_0_TABLE_PATH, table); - flowTx.putOperationalData(NODE_1_FLOW_PATH, FLOW); - flowTx.commit().get(); + lvuTx.putOperationalData(NODE_0_TCU_PATH, tcua); + lvuTx.putOperationalData(NODE_1_LVU_PATH, LVU); + lvuTx.commit().get(); validateEvent(eventFuture.get(1000, TimeUnit.MILLISECONDS)); } @@ -161,7 +146,7 @@ public class WildcardedDataChangeListenerTest extends AbstractDataServiceTest { // We wrote initial state NODE_0_FLOW DataModificationTransaction transaction = dataBroker.beginTransaction(); - transaction.putOperationalData(NODE_0_FLOW_PATH, FLOW); + transaction.putOperationalData(NODE_0_LVU_PATH, LVU); transaction.commit().get(); // We registered DataChangeListener @@ -176,23 +161,23 @@ public class WildcardedDataChangeListenerTest extends AbstractDataServiceTest { assertFalse(eventFuture.isDone()); DataModificationTransaction secondTx = dataBroker.beginTransaction(); - secondTx.putOperationalData(NODE_0_FLOW_PATH, FLOW); - secondTx.putOperationalData(NODE_1_FLOW_PATH, FLOW); + secondTx.putOperationalData(NODE_0_LVU_PATH, LVU); + secondTx.putOperationalData(NODE_1_LVU_PATH, LVU); secondTx.commit().get(); DataChangeEvent, DataObject> event = (eventFuture.get(1000, TimeUnit.MILLISECONDS)); assertNotNull(event); // Data change should contains NODE_1 Flow - which was added - assertTrue(event.getCreatedOperationalData().containsKey(NODE_1_FLOW_PATH)); + assertTrue(event.getCreatedOperationalData().containsKey(NODE_1_LVU_PATH)); // Data change must not containe NODE_0 Flow which was replaced with same value. - assertFalse(event.getUpdatedOperationalData().containsKey(NODE_0_FLOW_PATH)); + assertFalse(event.getUpdatedOperationalData().containsKey(NODE_0_LVU_PATH)); } private static void validateEvent(final DataChangeEvent, DataObject> event) { assertNotNull(event); - assertTrue(event.getCreatedOperationalData().containsKey(NODE_1_FLOW_PATH)); - assertTrue(event.getCreatedOperationalData().containsKey(NODE_0_FLOW_PATH)); - assertFalse(event.getCreatedOperationalData().containsKey(NODE_0_TABLE_FEATURES_PATH)); + assertTrue(event.getCreatedOperationalData().containsKey(NODE_1_LVU_PATH)); + assertTrue(event.getCreatedOperationalData().containsKey(NODE_0_LVU_PATH)); + assertFalse(event.getCreatedOperationalData().containsKey(NODE_0_CWU_PATH)); } } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java index bddbc4e954..d85cb7a0a2 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug02Test.java @@ -21,9 +21,9 @@ import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactory; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.TopBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; @@ -33,7 +33,7 @@ import com.google.common.util.concurrent.MoreExecutors; @SuppressWarnings("deprecation") public class DOMCodecBug02Test extends AbstractDataServiceTest { - private static final InstanceIdentifier NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // + private static final InstanceIdentifier TOP_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) // .toInstance(); /** @@ -66,10 +66,10 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest { .submit(new Callable>>() { @Override public Future> call() throws Exception { - NodesBuilder nodesBuilder = new NodesBuilder(); - nodesBuilder.setNode(Collections. emptyList()); + TopBuilder topBuilder = new TopBuilder(); + topBuilder.setTopLevelList(Collections. emptyList()); DataModificationTransaction transaction = baDataService.beginTransaction(); - transaction.putOperationalData(NODES_INSTANCE_ID_BA, nodesBuilder.build()); + transaction.putOperationalData(TOP_INSTANCE_ID_BA, topBuilder.build()); return transaction.commit(); } }); @@ -77,13 +77,13 @@ public class DOMCodecBug02Test extends AbstractDataServiceTest { RpcResult result = future.get().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - Nodes nodes = checkForNodes(); - assertNotNull(nodes); + Top top = checkForTop(); + assertNotNull(top); } - private Nodes checkForNodes() { - return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA); + private Top checkForTop() { + return (Top) baDataService.readOperationalData(TOP_INSTANCE_ID_BA); } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java index c07125a5dc..ba4a024b7c 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DOMCodecBug03Test.java @@ -22,22 +22,20 @@ import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.SupportedActions; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.SupportedActionsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.supported.actions.ActionType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.supported.actions.ActionTypeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.SupportType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.CustomEnum; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugmentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.Cont2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.Cont2Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.cont2.Contlist1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.cont2.Contlist1Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedListKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.QName; @@ -49,42 +47,42 @@ import com.google.common.util.concurrent.SettableFuture; @SuppressWarnings("deprecation") public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataChangeListener { - private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id"); - private static final String NODE_ID = "openflow:1"; + private static final QName TOP_LEVEL_LIST_NAME_QNAME = QName.create(TopLevelList.QNAME, "name"); + private static final String TOP_LEVEL_LIST_NAME = "tll:foo"; - private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); + private static final TopLevelListKey TLL_KEY = new TopLevelListKey(TOP_LEVEL_LIST_NAME); - private static final Map NODE_KEY_BI = Collections. singletonMap(NODE_ID_QNAME, - NODE_ID); + private static final Map TLL_KEY_BI = Collections. singletonMap(TOP_LEVEL_LIST_NAME_QNAME, + TOP_LEVEL_LIST_NAME); - private static final InstanceIdentifier NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // + private static final InstanceIdentifier TOP_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) // .toInstance(); - private static final InstanceIdentifier NODE_INSTANCE_ID_BA = NODES_INSTANCE_ID_BA.child(Node.class, NODE_KEY); + private static final InstanceIdentifier TLL_INSTANCE_ID_BA = TOP_INSTANCE_ID_BA.child(TopLevelList.class, TLL_KEY); - private static final InstanceIdentifier SUPPORTED_ACTIONS_INSTANCE_ID_BA = // - NODES_INSTANCE_ID_BA.builder() // - .child(Node.class, NODE_KEY) // - .augmentation(FlowCapableNode.class) // - .child(SupportedActions.class) + private static final InstanceIdentifier CONT2_INSTANCE_ID_BA = // + TOP_INSTANCE_ID_BA.builder() // + .child(TopLevelList.class, TLL_KEY) // + .augmentation(TllComplexAugment.class) // + .child(Cont2.class) .toInstance(); - private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier NODE_INSTANCE_ID_BI = // + private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier TLL_INSTANCE_ID_BI = // org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder() // - .node(Nodes.QNAME) // - .nodeWithKey(Node.QNAME, NODE_KEY_BI) // + .node(Top.QNAME) // + .nodeWithKey(TopLevelList.QNAME, TLL_KEY_BI) // .toInstance(); - private static final QName SUPPORTED_ACTIONS_QNAME = QName.create(FlowCapableNode.QNAME, SupportedActions.QNAME.getLocalName()); + private static final QName CONT2_QNAME = QName.create(TllComplexAugment.QNAME, Cont2.QNAME.getLocalName()); - private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier SUPPORTED_ACTIONS_INSTANCE_ID_BI = // + private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier CONT2_INSTANCE_ID_BI = // org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder() // - .node(Nodes.QNAME) // - .nodeWithKey(Node.QNAME, NODE_KEY_BI) // - .node(SUPPORTED_ACTIONS_QNAME) // + .node(Top.QNAME) // + .nodeWithKey(TopLevelList.QNAME, TLL_KEY_BI) // + .node(CONT2_QNAME) // .toInstance(); private final SettableFuture, DataObject>> receivedChangeEvent = SettableFuture.create(); @@ -100,24 +98,22 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh public void testAugmentSerialization() throws Exception { - baDataService.registerDataChangeListener(NODES_INSTANCE_ID_BA, this); + baDataService.registerDataChangeListener(TOP_INSTANCE_ID_BA, this); - NodeBuilder nodeBuilder = new NodeBuilder(); - nodeBuilder.setId(new NodeId(NODE_ID)); - nodeBuilder.setKey(NODE_KEY); + TopLevelListBuilder tllBuilder = new TopLevelListBuilder(); + tllBuilder.setKey(TLL_KEY); DataModificationTransaction transaction = baDataService.beginTransaction(); - FlowCapableNodeBuilder fnub = new FlowCapableNodeBuilder(); - fnub.setHardware("Hardware Foo"); - fnub.setManufacturer("Manufacturer Foo"); - fnub.setSerialNumber("Serial Foo"); - fnub.setDescription("Description Foo"); - fnub.setSoftware("JUnit emulated"); - FlowCapableNode fnu = fnub.build(); - nodeBuilder.addAugmentation(FlowCapableNode.class, fnu); - Node original = nodeBuilder.build(); - transaction.putOperationalData(NODE_INSTANCE_ID_BA, original); + TllComplexAugmentBuilder tllcab = new TllComplexAugmentBuilder(); + tllcab.setAttrStr1("Hardware Foo"); + tllcab.setAttrStr2("Manufacturer Foo"); + tllcab.setAttrStr3("Serial Foo"); + tllcab.setAttrStr4("Description Foo"); + TllComplexAugment tlca = tllcab.build(); + tllBuilder.addAugmentation(TllComplexAugment.class, tlca); + TopLevelList original = tllBuilder.build(); + transaction.putOperationalData(TLL_INSTANCE_ID_BA, original); RpcResult result = transaction.commit().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); @@ -125,13 +121,13 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh DataChangeEvent, DataObject> potential = receivedChangeEvent.get(1000,TimeUnit.MILLISECONDS); assertNotNull(potential); - verifyNodes((Nodes) potential.getUpdatedOperationalSubtree(),original); - assertBindingIndependentVersion(NODE_INSTANCE_ID_BI); - Nodes nodes = checkForNodes(); - verifyNodes(nodes,original); + verifyTll((Top) potential.getUpdatedOperationalSubtree(),original); + assertBindingIndependentVersion(TLL_INSTANCE_ID_BI); + Top top = checkForTop(); + verifyTll(top,original); testAddingNodeConnector(); - testNodeRemove(); + testTllRemove(); } @@ -139,69 +135,66 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh public void testAugmentNestedSerialization() throws Exception { DataModificationTransaction transaction = baDataService.beginTransaction(); - SupportedActionsBuilder actions = new SupportedActionsBuilder(); - ActionTypeBuilder action = new ActionTypeBuilder(); - action.setAction("foo-action"); - action.setSupportState(SupportType.Native); - List actionTypes = Collections.singletonList(action.build()); - actions.setActionType(actionTypes ); + Cont2Builder cont2b = new Cont2Builder(); + Contlist1Builder cl1b = new Contlist1Builder(); + cl1b.setAttrStr("foo-action"); + cl1b.setAttrEnum(CustomEnum.Type1); + List contlists = Collections.singletonList(cl1b.build()); + cont2b.setContlist1(contlists); - transaction.putOperationalData(SUPPORTED_ACTIONS_INSTANCE_ID_BA, actions.build()); + transaction.putOperationalData(CONT2_INSTANCE_ID_BA, cont2b.build()); RpcResult putResult = transaction.commit().get(); assertNotNull(putResult); assertEquals(TransactionStatus.COMMITED, putResult.getResult()); - SupportedActions readedTable = (SupportedActions) baDataService.readOperationalData(SUPPORTED_ACTIONS_INSTANCE_ID_BA); + Cont2 readedTable = (Cont2) baDataService.readOperationalData(CONT2_INSTANCE_ID_BA); assertNotNull(readedTable); - CompositeNode biSupportedActions = biDataService.readOperationalData(SUPPORTED_ACTIONS_INSTANCE_ID_BI); + CompositeNode biSupportedActions = biDataService.readOperationalData(CONT2_INSTANCE_ID_BI); assertNotNull(biSupportedActions); } private void testAddingNodeConnector() throws Exception { - - NodeConnectorId ncId = new NodeConnectorId("openflow:1:bar"); - NodeConnectorKey nodeKey = new NodeConnectorKey(ncId ); - InstanceIdentifier ncInstanceId = NODE_INSTANCE_ID_BA.child(NodeConnector.class, nodeKey); - NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder(); - ncBuilder.setId(ncId); - ncBuilder.setKey(nodeKey); - NodeConnector connector = ncBuilder.build(); + NestedListKey nlKey = new NestedListKey("test:0:0"); + InstanceIdentifier ncInstanceId = TLL_INSTANCE_ID_BA.child(NestedList.class, nlKey); + NestedListBuilder nlBuilder = new NestedListBuilder(); + nlBuilder.setKey(nlKey); + NestedList nestedList = nlBuilder.build(); DataModificationTransaction transaction = baDataService.beginTransaction(); - transaction.putOperationalData(ncInstanceId, connector); + transaction.putOperationalData(ncInstanceId, nestedList); RpcResult result = transaction.commit().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - Node node = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA); - assertNotNull(node); - assertNotNull(node.getNodeConnector()); - assertFalse(node.getNodeConnector().isEmpty()); - NodeConnector readedNc = node.getNodeConnector().get(0); - assertNotNull(readedNc); + TopLevelList tll = (TopLevelList) baDataService.readOperationalData(TLL_INSTANCE_ID_BA); + assertNotNull(tll); + assertNotNull(tll.getNestedList()); + assertFalse(tll.getNestedList().isEmpty()); + NestedList readedNl = tll.getNestedList().get(0); + assertNotNull(readedNl); } - private void testNodeRemove() throws Exception { + private void testTllRemove() throws Exception { DataModificationTransaction transaction = baDataService.beginTransaction(); - transaction.removeOperationalData(NODE_INSTANCE_ID_BA); + transaction.removeOperationalData(TLL_INSTANCE_ID_BA); RpcResult result = transaction.commit().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - Node node = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA); - assertNull(node); + TopLevelList tll = (TopLevelList) baDataService.readOperationalData(TLL_INSTANCE_ID_BA); + assertNull(tll); } - private void verifyNodes(final Nodes nodes,final Node original) { - assertNotNull(nodes); - assertNotNull(nodes.getNode()); - assertEquals(1, nodes.getNode().size()); - Node readedNode = nodes.getNode().get(0); - assertEquals(original.getId(), readedNode.getId()); + private void verifyTll(final Top top,final TopLevelList original) { + assertNotNull(top); + assertNotNull(top.getTopLevelList()); + assertEquals(1, top.getTopLevelList().size()); + TopLevelList readedNode = top.getTopLevelList().get(0); + assertEquals(original.getName(), readedNode.getName()); assertEquals(original.getKey(), readedNode.getKey()); - FlowCapableNode fnu = original.getAugmentation(FlowCapableNode.class); - FlowCapableNode readedAugment = readedNode.getAugmentation(FlowCapableNode.class); + TllComplexAugment fnu = original.getAugmentation(TllComplexAugment.class); + TllComplexAugment readedAugment = readedNode.getAugmentation(TllComplexAugment.class); assertNotNull(fnu); - assertEquals(fnu.getDescription(), readedAugment.getDescription()); - assertEquals(fnu.getSerialNumber(), readedAugment.getSerialNumber()); + assertEquals(fnu.getAttrStr2(), readedAugment.getAttrStr2()); + assertEquals(fnu.getAttrStr3(), readedAugment.getAttrStr3()); } @@ -211,8 +204,8 @@ public class DOMCodecBug03Test extends AbstractDataServiceTest implements DataCh assertNotNull(node); } - private Nodes checkForNodes() { - return (Nodes) baDataService.readOperationalData(NODES_INSTANCE_ID_BA); + private Top checkForTop() { + return (Top) baDataService.readOperationalData(TOP_INSTANCE_ID_BA); } @Override diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java index 735138a530..40d4591001 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/DeleteNestedAugmentationListenParentTest.java @@ -9,21 +9,17 @@ import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsData; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.FlowStatisticsDataBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.List11SimpleAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.List11SimpleAugmentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -32,20 +28,20 @@ import com.google.common.util.concurrent.SettableFuture; @SuppressWarnings("deprecation") public class DeleteNestedAugmentationListenParentTest extends AbstractDataServiceTest { - private static final NodeKey NODE_KEY = new NodeKey(new NodeId("foo")); + private static final TopLevelListKey FOO_KEY = new TopLevelListKey("foo"); - private static final TableKey TABLE_KEY = new TableKey((short) 0); + private static final List1Key LIST1_KEY = new List1Key("one"); - private static final FlowKey FLOW_KEY = new FlowKey(new FlowId("100")); + private static final List11Key LIST11_KEY = new List11Key(100); - private static final InstanceIdentifier NODE_AUGMENT_PATH = InstanceIdentifier.builder(Nodes.class) - .child(Node.class,NODE_KEY) - .augmentation(FlowCapableNode.class) + private static final InstanceIdentifier TLL_COMPLEX_AUGMENT_PATH = InstanceIdentifier.builder(Top.class) + .child(TopLevelList.class,FOO_KEY) + .augmentation(TllComplexAugment.class) .build(); - private static final InstanceIdentifier FLOW_PATH = NODE_AUGMENT_PATH.builder() - .child(Table.class,TABLE_KEY) - .child(Flow.class,FLOW_KEY) + private static final InstanceIdentifier LIST11_PATH = TLL_COMPLEX_AUGMENT_PATH.builder() + .child(List1.class,LIST1_KEY) + .child(List11.class,LIST11_KEY) .build(); @@ -53,12 +49,12 @@ public class DeleteNestedAugmentationListenParentTest extends AbstractDataServic public void deleteChildListenParent() throws InterruptedException, ExecutionException { DataModificationTransaction initTx = baDataService.beginTransaction(); - initTx.putOperationalData(FLOW_PATH, flow()); + initTx.putOperationalData(LIST11_PATH, createList11()); initTx.commit().get(); final SettableFuture, DataObject>> event = SettableFuture.create(); - baDataService.registerDataChangeListener(FLOW_PATH, new DataChangeListener() { + baDataService.registerDataChangeListener(LIST11_PATH, new DataChangeListener() { @Override public void onDataChanged(final DataChangeEvent, DataObject> change) { @@ -67,23 +63,19 @@ public class DeleteNestedAugmentationListenParentTest extends AbstractDataServic }); DataModificationTransaction deleteTx = baDataService.beginTransaction(); - deleteTx.removeOperationalData(FLOW_PATH.augmentation(FlowStatisticsData.class)); + deleteTx.removeOperationalData(LIST11_PATH.augmentation(List11SimpleAugment.class)); deleteTx.commit().get(); DataChangeEvent, DataObject> receivedEvent = event.get(); - assertFalse(receivedEvent.getRemovedOperationalData().contains(NODE_AUGMENT_PATH)); + assertFalse(receivedEvent.getRemovedOperationalData().contains(TLL_COMPLEX_AUGMENT_PATH)); } - private Flow flow() { - FlowBuilder builder = new FlowBuilder() - .setKey(FLOW_KEY) - .addAugmentation(FlowStatisticsData.class,new FlowStatisticsDataBuilder() - .setFlowStatistics(new FlowStatisticsBuilder().build()) - .build()) - .setBarrier(true) - .setMatch(new MatchBuilder() - .build()) - ; + private List11 createList11() { + List11Builder builder = new List11Builder() + .setKey(LIST11_KEY) + .addAugmentation(List11SimpleAugment.class,new List11SimpleAugmentBuilder() + .setAttrStr2("bad").build()) + .setAttrStr("good"); return builder.build(); } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java index 7143352c1f..9ad46bb99f 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/FlagsSerializationTest.java @@ -11,39 +11,20 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.BitFlags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.QName; @@ -54,41 +35,36 @@ import com.google.common.collect.ImmutableSet; @SuppressWarnings("deprecation") public class FlagsSerializationTest extends AbstractDataServiceTest { - - private static final String FLOW_ID = "1234"; - private static final short TABLE_ID = (short)0; - private static final String NODE_ID = "node:1"; - - private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); - private static final FlowKey FLOW_KEY = new FlowKey(new FlowId(FLOW_ID)); - private static final TableKey TABLE_KEY = new TableKey(TABLE_ID); - - private static final InstanceIdentifier NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // - .child(Node.class, NODE_KEY).toInstance(); - - private static final InstanceIdentifier FLOW_INSTANCE_ID_BA = // - NODE_INSTANCE_ID_BA.builder() // - .augmentation(FlowCapableNode.class) - .child(Table.class,TABLE_KEY) - .child(Flow.class, FLOW_KEY) // + private static final TopLevelListKey TLL_KEY = new TopLevelListKey("foo"); + private static final List11Key LIST11_KEY = new List11Key(1234); + private static final List1Key LIST1_KEY = new List1Key("1"); + + private static final InstanceIdentifier TLL_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) // + .child(TopLevelList.class, TLL_KEY).toInstance(); + + private static final InstanceIdentifier LIST11_INSTANCE_ID_BA = // + TLL_INSTANCE_ID_BA.builder() // + .augmentation(TllComplexAugment.class) + .child(List1.class,LIST1_KEY) + .child(List11.class, LIST11_KEY) // .toInstance(); - private static final QName FLOW_FLAGS_QNAME = QName.create(Flow.QNAME, "flags"); + private static final QName LIST11_FLAGS_QNAME = QName.create(List11.QNAME, "flags"); @Test public void testIndirectGeneration() throws Exception { - FlowModFlags checkOverlapFlags = new FlowModFlags(true,false,false,false,false); - ImmutableSet domCheckOverlapFlags = ImmutableSet.of("CHECK_OVERLAP"); + BitFlags checkOverlapFlags = new BitFlags(true,false,false,false,false); + ImmutableSet domCheckOverlapFlags = ImmutableSet.of("FLAG_FIVE"); testFlags(checkOverlapFlags,domCheckOverlapFlags); - FlowModFlags allFalseFlags = new FlowModFlags(false,false,false,false,false); + BitFlags allFalseFlags = new BitFlags(false,false,false,false,false); ImmutableSet domAllFalseFlags = ImmutableSet.of(); testFlags(allFalseFlags,domAllFalseFlags); - FlowModFlags allTrueFlags = new FlowModFlags(true,true,true,true,true); - ImmutableSet domAllTrueFlags = ImmutableSet.of("CHECK_OVERLAP","NO_BYT_COUNTS", "NO_PKT_COUNTS", "RESET_COUNTS", "SEND_FLOW_REM"); + BitFlags allTrueFlags = new BitFlags(true,true,true,true,true); + ImmutableSet domAllTrueFlags = ImmutableSet.of("FLAG_ONE","FLAG_TWO","FLAG_THREE","FLAG_FOUR","FLAG_FIVE"); testFlags(allTrueFlags,domAllTrueFlags); testFlags(null,null); @@ -97,14 +73,14 @@ public class FlagsSerializationTest extends AbstractDataServiceTest { } - private void testFlags(final FlowModFlags flagsToTest, final ImmutableSet domFlags) throws Exception { - Flow flow = createFlow(flagsToTest); - assertNotNull(flow); + private void testFlags(final BitFlags flagsToTest, final ImmutableSet domFlags) throws Exception { + List11 list11 = createList11(flagsToTest); + assertNotNull(list11); - CompositeNode domFlow = biDataService.readConfigurationData(mappingService.toDataDom(FLOW_INSTANCE_ID_BA)); + CompositeNode domList11 = biDataService.readConfigurationData(mappingService.toDataDom(LIST11_INSTANCE_ID_BA)); - assertNotNull(domFlow); - org.opendaylight.yangtools.yang.data.api.Node readedFlags = domFlow.getFirstSimpleByName(FLOW_FLAGS_QNAME); + assertNotNull(domList11); + org.opendaylight.yangtools.yang.data.api.Node readedFlags = domList11.getFirstSimpleByName(LIST11_FLAGS_QNAME); if(domFlags != null) { assertNotNull(readedFlags); @@ -112,55 +88,30 @@ public class FlagsSerializationTest extends AbstractDataServiceTest { } else { assertNull(readedFlags); } - assertEquals(flagsToTest, flow.getFlags()); + assertEquals(flagsToTest, list11.getFlags()); DataModificationTransaction transaction = baDataService.beginTransaction(); - transaction.removeConfigurationData(FLOW_INSTANCE_ID_BA); + transaction.removeConfigurationData(LIST11_INSTANCE_ID_BA); RpcResult result = transaction.commit().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); } - private Flow createFlow(final FlowModFlags flagsToTest) throws Exception { + private List11 createList11(final BitFlags flagsToTest) throws Exception { DataModificationTransaction modification = baDataService.beginTransaction(); - FlowBuilder flow = new FlowBuilder(); - MatchBuilder match = new MatchBuilder(); - VlanMatchBuilder vlanBuilder = new VlanMatchBuilder(); - VlanIdBuilder vlanIdBuilder = new VlanIdBuilder(); - VlanId vlanId = new VlanId(10); - vlanBuilder.setVlanId(vlanIdBuilder.setVlanId(vlanId).build()); - match.setVlanMatch(vlanBuilder.build()); - - flow.setKey(FLOW_KEY); - flow.setMatch(match.build()); - - flow.setFlags(flagsToTest); - - InstructionsBuilder instructions = new InstructionsBuilder(); - InstructionBuilder instruction = new InstructionBuilder(); - - instruction.setOrder(10); - ApplyActionsBuilder applyActions = new ApplyActionsBuilder(); - List actionList = new ArrayList<>(); - PopMplsActionBuilder popMplsAction = new PopMplsActionBuilder(); - popMplsAction.setEthernetType(34); - actionList.add(new ActionBuilder().setAction(new PopMplsActionCaseBuilder().setPopMplsAction(popMplsAction.build()).build()).setOrder(10).build()); - - applyActions.setAction(actionList ); - - instruction.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(applyActions.build()).build()); + List11Builder list11b = new List11Builder(); + list11b.setKey(LIST11_KEY); + list11b.setAttrStr("list:1:1"); - List instructionList = Collections.singletonList(instruction.build()); - instructions.setInstruction(instructionList ); + list11b.setFlags(flagsToTest); - flow.setInstructions(instructions.build()); - modification.putConfigurationData(FLOW_INSTANCE_ID_BA, flow.build()); + modification.putConfigurationData(LIST11_INSTANCE_ID_BA, list11b.build()); RpcResult ret = modification.commit().get(); assertNotNull(ret); assertEquals(TransactionStatus.COMMITED, ret.getResult()); - return (Flow) baDataService.readConfigurationData(FLOW_INSTANCE_ID_BA); + return (List11) baDataService.readConfigurationData(LIST11_INSTANCE_ID_BA); } } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java index 767ccaade3..9bf6c4d291 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/PutAugmentationTest.java @@ -23,19 +23,18 @@ import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.NestedListSimpleAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.NestedListSimpleAugmentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugmentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.top.level.list.NestedListKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.QName; @@ -47,35 +46,35 @@ import com.google.common.util.concurrent.SettableFuture; @SuppressWarnings("deprecation") public class PutAugmentationTest extends AbstractDataServiceTest implements DataChangeListener { - private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id"); - private static final String NODE_ID = "openflow:1"; + private static final QName TLL_NAME_QNAME = QName.create(TopLevelList.QNAME, "name"); + private static final String TLL_NAME = "foo"; - private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); + private static final TopLevelListKey TLL_KEY = new TopLevelListKey(TLL_NAME); - private static final Map NODE_KEY_BI = Collections. singletonMap(NODE_ID_QNAME, - NODE_ID); + private static final Map TLL_KEY_BI = Collections. singletonMap(TLL_NAME_QNAME, + TLL_NAME); - private static final InstanceIdentifier NODES_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // + private static final InstanceIdentifier TOP_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) // .toInstance(); - private static final InstanceIdentifier NODE_INSTANCE_ID_BA = // - NODES_INSTANCE_ID_BA.builder() // - .child(Node.class, NODE_KEY).toInstance(); + private static final InstanceIdentifier TLL_INSTANCE_ID_BA = // + TOP_INSTANCE_ID_BA.builder() // + .child(TopLevelList.class, TLL_KEY).toInstance(); - private static final InstanceIdentifier ALL_FLOW_CAPABLE_NODES = // - NODES_INSTANCE_ID_BA.builder() // - .child(Node.class) // - .augmentation(FlowCapableNode.class) // + private static final InstanceIdentifier ALL_TCA = // + TOP_INSTANCE_ID_BA.builder() // + .child(TopLevelList.class) // + .augmentation(TllComplexAugment.class) // .build(); - private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier NODE_INSTANCE_ID_BI = // + private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier TLL_INSTANCE_ID_BI = // org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder() // - .node(Nodes.QNAME) // - .nodeWithKey(Node.QNAME, NODE_KEY_BI) // + .node(Top.QNAME) // + .nodeWithKey(TopLevelList.QNAME, TLL_KEY_BI) // .toInstance(); - private static final InstanceIdentifier FLOW_AUGMENTATION_PATH = - NODE_INSTANCE_ID_BA.builder() // - .augmentation(FlowCapableNode.class) // + private static final InstanceIdentifier TCA_AUGMENTATION_PATH = + TLL_INSTANCE_ID_BA.builder() // + .augmentation(TllComplexAugment.class) // .build(); private SettableFuture, DataObject>> lastReceivedChangeEvent; @@ -89,32 +88,28 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data @Ignore public void putNodeAndAugmentation() throws Exception { lastReceivedChangeEvent = SettableFuture.create(); - baDataService.registerDataChangeListener(ALL_FLOW_CAPABLE_NODES, this); + baDataService.registerDataChangeListener(ALL_TCA, this); - NodeBuilder nodeBuilder = new NodeBuilder(); - nodeBuilder.setId(new NodeId(NODE_ID)); - nodeBuilder.setKey(NODE_KEY); + TopLevelListBuilder nodeBuilder = new TopLevelListBuilder(); + nodeBuilder.setKey(TLL_KEY); DataModificationTransaction baseTransaction = baDataService.beginTransaction(); - baseTransaction.putOperationalData(NODE_INSTANCE_ID_BA, nodeBuilder.build()); + baseTransaction.putOperationalData(TLL_INSTANCE_ID_BA, nodeBuilder.build()); RpcResult result = baseTransaction.commit().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - Node node = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA); - assertNotNull(node); - assertEquals(NODE_KEY, node.getKey()); - - FlowCapableNodeBuilder fnub = new FlowCapableNodeBuilder(); - fnub.setHardware("Hardware Foo"); - fnub.setManufacturer("Manufacturer Foo"); - fnub.setSerialNumber("Serial Foo"); - fnub.setDescription("Description Foo"); - fnub.setSoftware("JUnit emulated"); - FlowCapableNode fnu = fnub.build(); - InstanceIdentifier augmentIdentifier = NODE_INSTANCE_ID_BA - .augmentation(FlowCapableNode.class); + TopLevelList tll = (TopLevelList) baDataService.readOperationalData(TLL_INSTANCE_ID_BA); + assertNotNull(tll); + assertEquals(TLL_KEY, tll.getKey()); + + TllComplexAugmentBuilder tcab = new TllComplexAugmentBuilder(); + tcab.setAttrStr1("FooFoo"); + tcab.setAttrStr2("BarBar"); + TllComplexAugment tca = tcab.build(); + InstanceIdentifier augmentIdentifier = TLL_INSTANCE_ID_BA + .augmentation(TreeComplexUsesAugment.class); DataModificationTransaction augmentedTransaction = baDataService.beginTransaction(); - augmentedTransaction.putOperationalData(augmentIdentifier, fnu); + augmentedTransaction.putOperationalData(augmentIdentifier, tca); lastReceivedChangeEvent = SettableFuture.create(); @@ -123,102 +118,98 @@ public class PutAugmentationTest extends AbstractDataServiceTest implements Data DataChangeEvent, DataObject> potential = lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS); assertNotNull(potential); - assertTrue(potential.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH)); + assertTrue(potential.getCreatedOperationalData().containsKey(TCA_AUGMENTATION_PATH)); lastReceivedChangeEvent = SettableFuture.create(); - Node augmentedNode = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA); - assertNotNull(node); - assertEquals(NODE_KEY, augmentedNode.getKey()); + TopLevelList augmentedTll = (TopLevelList) baDataService.readOperationalData(TLL_INSTANCE_ID_BA); + assertNotNull(tll); + assertEquals(TLL_KEY, augmentedTll.getKey()); System.out.println("Before assertion"); - assertNotNull(augmentedNode.getAugmentation(FlowCapableNode.class)); - FlowCapableNode readedAugmentation = augmentedNode.getAugmentation(FlowCapableNode.class); - assertEquals(fnu.getDescription(), readedAugmentation.getDescription()); - assertBindingIndependentVersion(NODE_INSTANCE_ID_BI); - testNodeRemove(); - assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH)); + assertNotNull(augmentedTll.getAugmentation(TllComplexAugment.class)); + TllComplexAugment readedAugmentation = augmentedTll.getAugmentation(TllComplexAugment.class); + assertEquals(tca.getAttrStr2(), readedAugmentation.getAttrStr2()); + assertBindingIndependentVersion(TLL_INSTANCE_ID_BI); + testTllRemove(); + assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(TCA_AUGMENTATION_PATH)); } @Test @Ignore public void putNodeWithAugmentation() throws Exception { lastReceivedChangeEvent = SettableFuture.create(); - baDataService.registerDataChangeListener(ALL_FLOW_CAPABLE_NODES, this); - - NodeBuilder nodeBuilder = new NodeBuilder(); - nodeBuilder.setId(new NodeId(NODE_ID)); - nodeBuilder.setKey(NODE_KEY); - FlowCapableNodeBuilder fnub = new FlowCapableNodeBuilder(); - fnub.setHardware("Hardware Foo"); - fnub.setManufacturer("Manufacturer Foo"); - fnub.setSerialNumber("Serial Foo"); - fnub.setDescription("Description Foo"); - fnub.setSoftware("JUnit emulated"); - FlowCapableNode fnu = fnub.build(); - - nodeBuilder.addAugmentation(FlowCapableNode.class, fnu); + baDataService.registerDataChangeListener(ALL_TCA, this); + + TopLevelListBuilder nodeBuilder = new TopLevelListBuilder(); + nodeBuilder.setKey(TLL_KEY); + TllComplexAugmentBuilder tcab = new TllComplexAugmentBuilder(); + tcab.setAttrStr1("FooFoo"); + tcab.setAttrStr2("BarBar"); + TllComplexAugment tca = tcab.build(); + + nodeBuilder.addAugmentation(TreeComplexUsesAugment.class, tca); DataModificationTransaction baseTransaction = baDataService.beginTransaction(); - baseTransaction.putOperationalData(NODE_INSTANCE_ID_BA, nodeBuilder.build()); + baseTransaction.putOperationalData(TLL_INSTANCE_ID_BA, nodeBuilder.build()); RpcResult result = baseTransaction.commit().get(); DataChangeEvent, DataObject> potential = lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS); assertNotNull(potential); - assertTrue(potential.getCreatedOperationalData().containsKey(FLOW_AUGMENTATION_PATH)); + assertTrue(potential.getCreatedOperationalData().containsKey(TCA_AUGMENTATION_PATH)); lastReceivedChangeEvent = SettableFuture.create(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - FlowCapableNode readedAugmentation = (FlowCapableNode) baDataService.readOperationalData( - NODE_INSTANCE_ID_BA.augmentation(FlowCapableNode.class)); + TllComplexAugment readedAugmentation = (TllComplexAugment) baDataService.readOperationalData( + TLL_INSTANCE_ID_BA.augmentation(TllComplexAugment.class)); assertNotNull(readedAugmentation); - assertEquals(fnu.getHardware(), readedAugmentation.getHardware()); + assertEquals(tca.getAttrStr1(), readedAugmentation.getAttrStr1()); testPutNodeConnectorWithAugmentation(); lastReceivedChangeEvent = SettableFuture.create(); - testNodeRemove(); + testTllRemove(); - assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(FLOW_AUGMENTATION_PATH)); + assertTrue(lastReceivedChangeEvent.get(1000,TimeUnit.MILLISECONDS).getRemovedOperationalData().contains(TCA_AUGMENTATION_PATH)); } private void testPutNodeConnectorWithAugmentation() throws Exception { - NodeConnectorKey ncKey = new NodeConnectorKey(new NodeConnectorId("test:0:0")); - InstanceIdentifier ncPath = NODE_INSTANCE_ID_BA - .child(NodeConnector.class, ncKey); - InstanceIdentifier ncAugmentPath = ncPath - .augmentation(FlowCapableNodeConnector.class); + NestedListKey ncKey = new NestedListKey("test:0:0"); + InstanceIdentifier ncPath = TLL_INSTANCE_ID_BA + .child(NestedList.class, ncKey); + InstanceIdentifier ncAugmentPath = ncPath + .augmentation(NestedListSimpleAugment.class); - NodeConnectorBuilder nc = new NodeConnectorBuilder(); + NestedListBuilder nc = new NestedListBuilder(); nc.setKey(ncKey); - FlowCapableNodeConnectorBuilder fncb = new FlowCapableNodeConnectorBuilder(); - fncb.setName("Baz"); - nc.addAugmentation(FlowCapableNodeConnector.class, fncb.build()); + NestedListSimpleAugmentBuilder fncb = new NestedListSimpleAugmentBuilder(); + fncb.setType("Baz"); + nc.addAugmentation(NestedListSimpleAugment.class, fncb.build()); DataModificationTransaction baseTransaction = baDataService.beginTransaction(); baseTransaction.putOperationalData(ncPath, nc.build()); RpcResult result = baseTransaction.commit().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - FlowCapableNodeConnector readedAugmentation = (FlowCapableNodeConnector) baDataService + NestedListSimpleAugment readedAugmentation = (NestedListSimpleAugment) baDataService .readOperationalData(ncAugmentPath); assertNotNull(readedAugmentation); - assertEquals(fncb.getName(), readedAugmentation.getName()); + assertEquals(fncb.getType(), readedAugmentation.getType()); } - private void testNodeRemove() throws Exception { + private void testTllRemove() throws Exception { DataModificationTransaction transaction = baDataService.beginTransaction(); - transaction.removeOperationalData(NODE_INSTANCE_ID_BA); + transaction.removeOperationalData(TLL_INSTANCE_ID_BA); RpcResult result = transaction.commit().get(); assertEquals(TransactionStatus.COMMITED, result.getResult()); - Node node = (Node) baDataService.readOperationalData(NODE_INSTANCE_ID_BA); - assertNull(node); + TopLevelList tll = (TopLevelList) baDataService.readOperationalData(TLL_INSTANCE_ID_BA); + assertNull(tll); } - private void assertBindingIndependentVersion(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier nodeId) { - CompositeNode node = biDataService.readOperationalData(nodeId); - assertNotNull(node); + private void assertBindingIndependentVersion(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier tllId) { + CompositeNode tll = biDataService.readOperationalData(tllId); + assertNotNull(tll); } @Override diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java index b09ba39a65..0f9051d41c 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentListenAugmentTest.java @@ -18,13 +18,13 @@ import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugmentBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; @@ -34,17 +34,17 @@ import com.google.common.util.concurrent.SettableFuture; @SuppressWarnings("deprecation") public class WriteParentListenAugmentTest extends AbstractDataServiceTest { - private static final String NODE_ID = "node:1"; + private static final String TLL_NAME = "foo"; - private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); - private static final InstanceIdentifier NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // - .child(Node.class, NODE_KEY).toInstance(); + private static final TopLevelListKey TLL_KEY = new TopLevelListKey(TLL_NAME); + private static final InstanceIdentifier TLL_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) // + .child(TopLevelList.class, TLL_KEY).toInstance(); - private static final InstanceIdentifier AUGMENT_WILDCARDED_PATH = InstanceIdentifier - .builder(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class).toInstance(); + private static final InstanceIdentifier AUGMENT_WILDCARDED_PATH = InstanceIdentifier + .builder(Top.class).child(TopLevelList.class).augmentation(TreeComplexUsesAugment.class).toInstance(); - private static final InstanceIdentifier AUGMENT_NODE_PATH = InstanceIdentifier - .builder(Nodes.class).child(Node.class, NODE_KEY).augmentation(FlowCapableNode.class).toInstance(); + private static final InstanceIdentifier AUGMENT_TLL_PATH = InstanceIdentifier + .builder(Top.class).child(TopLevelList.class, TLL_KEY).augmentation(TreeComplexUsesAugment.class).toInstance(); @Test public void writeNodeListenAugment() throws Exception { @@ -62,29 +62,29 @@ public class WriteParentListenAugmentTest extends AbstractDataServiceTest { DataModificationTransaction modification = baDataService.beginTransaction(); - Node node = new NodeBuilder() // - .setKey(NODE_KEY) // - .addAugmentation(FlowCapableNode.class, flowCapableNode("one")).build(); - modification.putOperationalData(NODE_INSTANCE_ID_BA, node); + TopLevelList tll = new TopLevelListBuilder() // + .setKey(TLL_KEY) // + .addAugmentation(TreeComplexUsesAugment.class, treeComplexUsesAugment("one")).build(); + modification.putOperationalData(TLL_INSTANCE_ID_BA, tll); modification.commit().get(); DataChangeEvent, DataObject> receivedEvent = event.get(1000, TimeUnit.MILLISECONDS); - assertTrue(receivedEvent.getCreatedOperationalData().containsKey(AUGMENT_NODE_PATH)); + assertTrue(receivedEvent.getCreatedOperationalData().containsKey(AUGMENT_TLL_PATH)); dclRegistration.close(); DataModificationTransaction mod2 = baDataService.beginTransaction(); - mod2.putOperationalData(AUGMENT_NODE_PATH, flowCapableNode("two")); + mod2.putOperationalData(AUGMENT_TLL_PATH, treeComplexUsesAugment("two")); mod2.commit().get(); - FlowCapableNode readedAug = (FlowCapableNode) baDataService.readOperationalData(AUGMENT_NODE_PATH); - assertEquals("two", readedAug.getDescription()); + TreeComplexUsesAugment readedAug = (TreeComplexUsesAugment) baDataService.readOperationalData(AUGMENT_TLL_PATH); + assertEquals("two", readedAug.getContainerWithUses().getLeafFromGrouping()); } - private FlowCapableNode flowCapableNode(final String description) { - return new FlowCapableNodeBuilder() // - .setDescription(description) // + private TreeComplexUsesAugment treeComplexUsesAugment(final String value) { + return new TreeComplexUsesAugmentBuilder() // + .setContainerWithUses(new ContainerWithUsesBuilder().setLeafFromGrouping(value).build()) // .build(); } } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java index ad02d9a6f6..7941f4d4ae 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/bugfix/WriteParentReadChildTest.java @@ -16,24 +16,16 @@ import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; @@ -43,23 +35,23 @@ import com.google.common.collect.ImmutableList; @SuppressWarnings("deprecation") public class WriteParentReadChildTest extends AbstractDataServiceTest { - private static final String FLOW_ID = "1234"; - private static final short TABLE_ID = (short) 0; - private static final String NODE_ID = "node:1"; + private static final int LIST11_ID = 1234; + private static final String LIST1_NAME = "bar"; + private static final String TLL_NAME = "foo"; - private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); - private static final FlowKey FLOW_KEY = new FlowKey(new FlowId(FLOW_ID)); - private static final TableKey TABLE_KEY = new TableKey(TABLE_ID); + private static final TopLevelListKey TLL_KEY = new TopLevelListKey(TLL_NAME); + private static final List11Key LIST11_KEY = new List11Key(LIST11_ID); + private static final List1Key LIST1_KEY = new List1Key(LIST1_NAME); - private static final InstanceIdentifier NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // - .child(Node.class, NODE_KEY).toInstance(); + private static final InstanceIdentifier TLL_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) // + .child(TopLevelList.class, TLL_KEY).toInstance(); - private static final InstanceIdentifier
TABLE_INSTANCE_ID_BA = // - NODE_INSTANCE_ID_BA.builder() // - .augmentation(FlowCapableNode.class).child(Table.class, TABLE_KEY).build(); + private static final InstanceIdentifier LIST1_INSTANCE_ID_BA = // + TLL_INSTANCE_ID_BA.builder() // + .augmentation(TllComplexAugment.class).child(List1.class, LIST1_KEY).build(); - private static final InstanceIdentifier FLOW_INSTANCE_ID_BA = // - TABLE_INSTANCE_ID_BA.child(Flow.class, FLOW_KEY); + private static final InstanceIdentifier LIST11_INSTANCE_ID_BA = // + LIST1_INSTANCE_ID_BA.child(List11.class, LIST11_KEY); /** * * The scenario tests writing parent node, which also contains child items @@ -70,43 +62,33 @@ public class WriteParentReadChildTest extends AbstractDataServiceTest { * @throws Exception */ @Test - public void writeTableReadFlow() throws Exception { + public void writeParentReadChild() throws Exception { DataModificationTransaction modification = baDataService.beginTransaction(); - Flow flow = new FlowBuilder() // - .setKey(FLOW_KEY) // - .setMatch(new MatchBuilder() // - .setVlanMatch(new VlanMatchBuilder() // - .setVlanId(new VlanIdBuilder() // - .setVlanId(new VlanId(10)) // - .build()) // - .build()) // - .build()) // - .setInstructions(new InstructionsBuilder() // - .setInstruction(ImmutableList.builder() // - .build()) // - .build()) // + List11 list11 = new List11Builder() // + .setKey(LIST11_KEY) // + .setAttrStr("primary") .build(); - Table table = new TableBuilder() - .setKey(TABLE_KEY) - .setFlow(ImmutableList.of(flow)) + List1 list1 = new List1Builder() + .setKey(LIST1_KEY) + .setList11(ImmutableList.of(list11)) .build(); - modification.putConfigurationData(TABLE_INSTANCE_ID_BA, table); + modification.putConfigurationData(LIST1_INSTANCE_ID_BA, list1); RpcResult ret = modification.commit().get(); assertNotNull(ret); assertEquals(TransactionStatus.COMMITED, ret.getResult()); - DataObject readedTable = baDataService.readConfigurationData(TABLE_INSTANCE_ID_BA); - assertNotNull("Readed table should not be nul.", readedTable); - assertTrue(readedTable instanceof Table); + DataObject readList1 = baDataService.readConfigurationData(LIST1_INSTANCE_ID_BA); + assertNotNull("Readed table should not be nul.", readList1); + assertTrue(readList1 instanceof List1); - DataObject readedFlow = baDataService.readConfigurationData(FLOW_INSTANCE_ID_BA); - assertNotNull("Readed flow should not be null.",readedFlow); - assertTrue(readedFlow instanceof Flow); - assertEquals(flow, readedFlow); + DataObject readList11 = baDataService.readConfigurationData(LIST11_INSTANCE_ID_BA); + assertNotNull("Readed flow should not be null.",readList11); + assertTrue(readList11 instanceof List11); + assertEquals(list11, readList11); } } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java index 481a7ddfa2..48027114d7 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java @@ -17,30 +17,37 @@ import org.junit.Test; import org.opendaylight.controller.md.sal.common.api.TransactionStatus; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; -// FIXME: Migrate to use new Data Broker APIs +/** + * FIXME: Migrate to use new Data Broker APIs + */ @SuppressWarnings("deprecation") public class BrokerIntegrationTest extends AbstractDataServiceTest { + private static final TopLevelListKey TLL_FOO_KEY = new TopLevelListKey("foo"); + private static final TopLevelListKey TLL_BAR_KEY = new TopLevelListKey("bar"); + private static final TopLevelListKey TLL_BAZ_KEY = new TopLevelListKey("baz"); + private static final InstanceIdentifier TOP_PATH = InstanceIdentifier.builder(Top.class).build(); + private static final InstanceIdentifier FOO_PATH = TOP_PATH.child(TopLevelList.class, TLL_FOO_KEY); + private static final InstanceIdentifier BAR_PATH = TOP_PATH.child(TopLevelList.class, TLL_BAR_KEY); + private static final InstanceIdentifier BAZ_PATH = TOP_PATH.child(TopLevelList.class, TLL_BAZ_KEY); + @Test public void simpleModifyOperation() throws Exception { - NodeRef node1 = createNodeRef("0"); - DataObject node = baDataService.readConfigurationData(node1.getValue()); - assertNull(node); - Node nodeData1 = createNode("0"); + DataObject tllFoo = baDataService.readConfigurationData(FOO_PATH); + assertNull(tllFoo); + TopLevelList tllFooData = createTll(TLL_FOO_KEY); DataModificationTransaction transaction = baDataService.beginTransaction(); - transaction.putConfigurationData(node1.getValue(), nodeData1); + transaction.putConfigurationData(FOO_PATH, tllFooData); Future> commitResult = transaction.commit(); assertNotNull(commitResult); @@ -50,29 +57,26 @@ public class BrokerIntegrationTest extends AbstractDataServiceTest { assertNotNull(result.getResult()); assertEquals(TransactionStatus.COMMITED, result.getResult()); - Node readedData = (Node) baDataService.readConfigurationData(node1.getValue()); + TopLevelList readedData = (TopLevelList) baDataService.readConfigurationData(FOO_PATH); assertNotNull(readedData); - assertEquals(nodeData1.getKey(), readedData.getKey()); + assertEquals(tllFooData.getKey(), readedData.getKey()); - NodeRef nodeFoo = createNodeRef("foo"); - NodeRef nodeBar = createNodeRef("bar"); - Node nodeFooData = createNode("foo"); - Node nodeBarData = createNode("bar"); + TopLevelList nodeBarData = createTll(TLL_BAR_KEY); + TopLevelList nodeBazData = createTll(TLL_BAZ_KEY); DataModificationTransaction insertMoreTr = baDataService.beginTransaction(); - insertMoreTr.putConfigurationData(nodeFoo.getValue(), nodeFooData); - insertMoreTr.putConfigurationData(nodeBar.getValue(), nodeBarData); + insertMoreTr.putConfigurationData(BAR_PATH, nodeBarData); + insertMoreTr.putConfigurationData(BAZ_PATH, nodeBazData); RpcResult result2 = insertMoreTr.commit().get(); assertNotNull(result2); assertNotNull(result2.getResult()); assertEquals(TransactionStatus.COMMITED, result.getResult()); - Nodes allNodes = (Nodes) baDataService.readConfigurationData(InstanceIdentifier.builder(Nodes.class) - .toInstance()); - assertNotNull(allNodes); - assertNotNull(allNodes.getNode()); - assertEquals(3, allNodes.getNode().size()); + Top top = (Top) baDataService.readConfigurationData(TOP_PATH); + assertNotNull(top); + assertNotNull(top.getTopLevelList()); + assertEquals(3, top.getTopLevelList().size()); /** * We create transaction no 2 @@ -85,7 +89,7 @@ public class BrokerIntegrationTest extends AbstractDataServiceTest { * We remove node 1 * */ - removalTransaction.removeConfigurationData(node1.getValue()); + removalTransaction.removeConfigurationData(BAR_PATH); /** * We commit transaction @@ -99,21 +103,13 @@ public class BrokerIntegrationTest extends AbstractDataServiceTest { assertNotNull(result3.getResult()); assertEquals(TransactionStatus.COMMITED, result2.getResult()); - DataObject readedData2 = baDataService.readConfigurationData(node1.getValue()); + DataObject readedData2 = baDataService.readConfigurationData(BAR_PATH); assertNull(readedData2); } - private static NodeRef createNodeRef(final String string) { - NodeKey key = new NodeKey(new NodeId(string)); - InstanceIdentifier path = InstanceIdentifier.builder(Nodes.class).child(Node.class, key) - .toInstance(); - return new NodeRef(path); - } - - private static Node createNode(final String string) { - NodeBuilder ret = new NodeBuilder(); - ret.setId(new NodeId(string)); - ret.setKey(new NodeKey(ret.getId())); + private static TopLevelList createTll(final TopLevelListKey key) { + TopLevelListBuilder ret = new TopLevelListBuilder(); + ret.setKey(key); return ret.build(); } } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java index a3b0819501..25b159b43b 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/ChangeOriginatedInDomBrokerTest.java @@ -11,9 +11,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import java.util.ArrayList; import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -23,34 +21,17 @@ import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent; import org.opendaylight.controller.sal.binding.api.data.DataChangeListener; import org.opendaylight.controller.sal.binding.test.AbstractDataServiceTest; import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion; -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.action.types.rev131112.action.action.DecNwTtlCaseBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtl; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.dec.nw.ttl._case.DecNwTtlBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder; -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.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List12Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List12Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.QName; @@ -59,83 +40,79 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.SettableFuture; -// FIXME: Migrate to use new Data Broker APIs +/** + * FIXME: Migrate to use new Data Broker APIs + */ @SuppressWarnings("deprecation") public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest { - private static final Logger LOG = LoggerFactory.getLogger(ChangeOriginatedInDomBrokerTest.class); - - private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id"); - private static final QName FLOW_ID_QNAME = QName.create(Flow.QNAME, "id"); - private static final QName TABLE_ID_QNAME = QName.create(Table.QNAME, "id"); + protected static final Logger LOG = LoggerFactory.getLogger(ChangeOriginatedInDomBrokerTest.class); - private static final String NODE_ID = "node:1"; - private static final FlowId FLOW_ID = new FlowId("1234"); - private static final Short TABLE_ID = Short.valueOf((short) 0); + private static final QName TLL_NAME_QNAME = QName.create(TopLevelList.QNAME, "name"); + private static final QName LIST1_ATTR_STR_QNAME = QName.create(List1.QNAME, "attr-str"); - private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); - private static final FlowKey FLOW_KEY = new FlowKey(FLOW_ID); + private static final String TLL_NAME = "1"; + private static final int LIST11_ATTR_INT = 1234; + private static final String LIST1_ATTR_STR = "foo:foo"; - private final SettableFuture, DataObject>> modificationCapture = SettableFuture.create(); + private static final TopLevelListKey TLL_KEY = new TopLevelListKey(TLL_NAME); + private static final List1Key LIST1_KEY = new List1Key(LIST1_ATTR_STR); + private static final List11Key LIST11_KEY = new List11Key(LIST11_ATTR_INT); - private static final Map NODE_KEY_BI = Collections. singletonMap(NODE_ID_QNAME, - NODE_ID); + protected final SettableFuture, DataObject>> modificationCapture = SettableFuture.create(); - private static final InstanceIdentifier NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // - .child(Node.class, NODE_KEY).toInstance(); + private static final Map TLL_KEY_BI = Collections. singletonMap(TLL_NAME_QNAME, + TLL_NAME); - private static final Map FLOW_KEY_BI = // - ImmutableMap. of(FLOW_ID_QNAME, FLOW_ID.getValue()); + private static final InstanceIdentifier NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) // + .child(TopLevelList.class, TLL_KEY).toInstance(); - private static final Map TABLE_KEY_BI = // - ImmutableMap. of(TABLE_ID_QNAME, TABLE_ID);; + private static final Map LIST1_KEY_BI = // + ImmutableMap. of(LIST1_ATTR_STR_QNAME, LIST1_ATTR_STR);; - private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier FLOW_INSTANCE_ID_BI = // + private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier LIST1_INSTANCE_ID_BI = // org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder() // - .node(Nodes.QNAME) // - .nodeWithKey(Node.QNAME, NODE_KEY_BI) // - .nodeWithKey(Table.QNAME, TABLE_KEY_BI) // - .nodeWithKey(Flow.QNAME, FLOW_KEY_BI) // + .node(Top.QNAME) // + .nodeWithKey(TopLevelList.QNAME, TLL_KEY_BI) // + .nodeWithKey(List1.QNAME, LIST1_KEY_BI) // .toInstance(); - private static final TableKey TABLE_KEY_BA = new TableKey((short) 0); - private static final InstanceIdentifier FLOWS_PATH_BA = // + private static final InstanceIdentifier LIST1_PATH_BA = // NODE_INSTANCE_ID_BA.builder() // - .augmentation(FlowCapableNode.class) // - .child(Table.class, TABLE_KEY_BA) // - .child(Flow.class) // + .augmentation(TllComplexAugment.class) // + .child(List1.class, LIST1_KEY) // .toInstance(); - private static final InstanceIdentifier FLOW_INSTANCE_ID_BA = // - FLOWS_PATH_BA.firstIdentifierOf(Table.class).child(Flow.class, FLOW_KEY); - @Test public void simpleModifyOperation() throws Exception { - assertNull(biDataService.readConfigurationData(FLOW_INSTANCE_ID_BI)); + assertNull(biDataService.readConfigurationData(LIST1_INSTANCE_ID_BI)); registerChangeListener(); - CompositeNode domflow = createTestFlow(); + CompositeNode domflow = createTestList1(); DataModificationTransaction biTransaction = biDataService.beginTransaction(); - biTransaction.putConfigurationData(FLOW_INSTANCE_ID_BI, domflow); + biTransaction.putConfigurationData(LIST1_INSTANCE_ID_BI, domflow); RpcResult biResult = biTransaction.commit().get(); assertEquals(TransactionStatus.COMMITED, biResult.getResult()); DataChangeEvent, DataObject> event = modificationCapture.get(1000,TimeUnit.MILLISECONDS); assertNotNull(event); LOG.info("Created Configuration :{}",event.getCreatedConfigurationData()); - Flow flow = (Flow) event.getCreatedConfigurationData().get(FLOW_INSTANCE_ID_BA); - assertNotNull(flow); - assertNotNull(flow.getMatch()); + List1 list1 = (List1) event.getCreatedConfigurationData().get(LIST1_PATH_BA); + assertNotNull(list1); + assertNotNull(list1.getAttrStr()); + assertNotNull(list1.getList11()); + assertNotNull(list1.getList12()); assertEquals(TransactionStatus.COMMITED, biResult.getResult()); } private void registerChangeListener() { - baDataService.registerDataChangeListener(FLOWS_PATH_BA, new DataChangeListener() { + baDataService.registerDataChangeListener(LIST1_PATH_BA, new DataChangeListener() { @Override public void onDataChanged(final DataChangeEvent, DataObject> change) { @@ -145,61 +122,18 @@ public class ChangeOriginatedInDomBrokerTest extends AbstractDataServiceTest { }); } - private CompositeNode createTestFlow() { - FlowBuilder flow = new FlowBuilder(); - flow.setKey(FLOW_KEY); - Short tableId = 0; - flow.setTableId(tableId); - MatchBuilder match = new MatchBuilder(); - match.setIpMatch(new IpMatchBuilder().setIpProto(IpVersion.Ipv4).build()); - Ipv4MatchBuilder ipv4Match = new Ipv4MatchBuilder(); - // ipv4Match.setIpv4Destination(new Ipv4Prefix(cliInput.get(4))); - Ipv4Prefix prefix = new Ipv4Prefix("10.0.0.1/24"); - ipv4Match.setIpv4Destination(prefix); - Ipv4Match i4m = ipv4Match.build(); - match.setLayer3Match(i4m); - flow.setMatch(match.build()); - - - - // Create a drop action - /* - * Note: We are mishandling drop actions DropAction dropAction = new - * DropActionBuilder().build(); ActionBuilder ab = new ActionBuilder(); - * ab.setAction(dropAction); - */ - - DecNwTtl decNwTtl = new DecNwTtlBuilder().build(); - ActionBuilder ab = new ActionBuilder(); - ActionKey actionKey = new ActionKey(0); - ab.setKey(actionKey ); - ab.setAction(new DecNwTtlCaseBuilder().setDecNwTtl(decNwTtl).build()); - - // Add our drop action to a list - List actionList = new ArrayList(); - actionList.add(ab.build()); - - // Create an Apply Action - ApplyActionsBuilder aab = new ApplyActionsBuilder(); - aab.setAction(actionList); - - // Wrap our Apply Action in an Instruction - InstructionBuilder ib = new InstructionBuilder(); - ib.setOrder(0); - ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build()); - - // Put our Instruction in a list of Instructions - InstructionsBuilder isb = new InstructionsBuilder(); - List instructions = new ArrayList(); - instructions.add(ib.build()); - isb.setInstruction(instructions); - - // Add our instructions to the flow - flow.setInstructions(isb.build()); - - flow.setPriority(2); - flow.setFlowName("Foo Name"); - CompositeNode domFlow = mappingService.toDataDom(flow.build()); - return domFlow; + private CompositeNode createTestList1() { + List1Builder l1b = new List1Builder(); + List11Builder l11b = new List11Builder(); + List12Builder l12b = new List12Builder(); + l11b.setKey(LIST11_KEY); + l11b.setAttrStr("foo:foo:foo"); + l12b.setKey(new List12Key(321)); + l12b.setAttrStr("foo:foo:bar"); + l1b.setKey(LIST1_KEY); + l1b.setList11(ImmutableList.of(l11b.build())); + l1b.setList12(ImmutableList.of(l12b.build())); + CompositeNode domList1 = mappingService.toDataDom(l1b.build()); + return domList1; } } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerMountPointTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerMountPointTest.java index d87470a5e9..f199d71aa5 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerMountPointTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerMountPointTest.java @@ -7,10 +7,9 @@ */ package org.opendaylight.controller.sal.binding.test.connect.dom; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; -import java.math.BigInteger; import java.util.Collections; import java.util.Map; @@ -23,16 +22,16 @@ import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactor import org.opendaylight.controller.sal.binding.test.util.BindingTestContext; import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance; import org.opendaylight.controller.sal.core.api.mount.MountProvisionService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.NodeGroupStatistics; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.statistics.rev131111.group.statistics.GroupStatistics; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; -import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.List11SimpleAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.TllComplexAugment; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.List1Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.aug.grouping.list1.List11Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.top.top.level.list.list1.list1._1.Cont; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.CompositeNode; @@ -43,39 +42,45 @@ import com.google.common.util.concurrent.MoreExecutors; @SuppressWarnings("deprecation") public class CrossBrokerMountPointTest { - private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id"); - private static final String NODE_ID = "node:1"; + private static final QName TLL_NAME_QNAME = QName.create(TopLevelList.QNAME, "name"); + private static final String TLL_NAME = "foo:1"; + + private static final TopLevelListKey TLL_KEY = new TopLevelListKey(TLL_NAME); - private static final NodeKey NODE_KEY = new NodeKey(new NodeId(NODE_ID)); + private static final Map TLL_KEY_BI = Collections. singletonMap(TLL_NAME_QNAME, + TLL_NAME); - private static final Map NODE_KEY_BI = Collections. singletonMap(NODE_ID_QNAME, - NODE_ID); + private static final InstanceIdentifier TLL_INSTANCE_ID_BA = InstanceIdentifier.builder(Top.class) // + .child(TopLevelList.class, TLL_KEY).build(); - private static final InstanceIdentifier NODE_INSTANCE_ID_BA = InstanceIdentifier.builder(Nodes.class) // - .child(Node.class, NODE_KEY).toInstance(); - private static GroupKey GROUP_KEY = new GroupKey(new GroupId(0L)); + private static final List1Key LIST1_KEY = new List1Key("foo"); + private static final List11Key LIST11_KEY = new List11Key(1); - private static final InstanceIdentifier GROUP_STATISTICS_ID_BA = NODE_INSTANCE_ID_BA - .builder().augmentation(FlowCapableNode.class) // - .child(Group.class, GROUP_KEY) // - .augmentation(NodeGroupStatistics.class) // - .child(GroupStatistics.class) // - .toInstance(); + private static final InstanceIdentifier AUG_CONT_ID_BA = TLL_INSTANCE_ID_BA + .builder().augmentation(TllComplexAugment.class) // + .child(List1.class, LIST1_KEY) // + .child(List11.class, LIST11_KEY) // + .augmentation(List11SimpleAugment.class) // + .child(Cont.class) // + .build(); - private static final QName AUGMENTED_GROUP_STATISTICS = QName.create(NodeGroupStatistics.QNAME, - GroupStatistics.QNAME.getLocalName()); + private static final QName AUG_CONT = QName.create(List11.QNAME, + Cont.QNAME.getLocalName()); - private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier NODE_INSTANCE_ID_BI = // + private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier TLL_INSTANCE_ID_BI = // org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder() // - .node(Nodes.QNAME) // - .nodeWithKey(Node.QNAME, NODE_KEY_BI) // - .toInstance(); + .node(Top.QNAME) // + .nodeWithKey(TopLevelList.QNAME, TLL_KEY_BI) // + .build(); private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier GROUP_STATISTICS_ID_BI = org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier // - .builder(NODE_INSTANCE_ID_BI) - .nodeWithKey(QName.create(FlowCapableNode.QNAME, "group"), QName.create(FlowCapableNode.QNAME, "group-id"), - 0L).node(AUGMENTED_GROUP_STATISTICS).toInstance(); + .builder(TLL_INSTANCE_ID_BI) + .nodeWithKey(QName.create(TllComplexAugment.QNAME, "list1"), QName.create(TllComplexAugment.QNAME, "attr-str"), + LIST1_KEY.getAttrStr()) + .nodeWithKey(QName.create(TllComplexAugment.QNAME, "list1-1"), QName.create(TllComplexAugment.QNAME, "attr-int"), + LIST11_KEY.getAttrInt()) + .node(AUG_CONT).build(); private BindingTestContext testContext; private MountProviderService bindingMountPointService; @@ -102,14 +107,14 @@ public class CrossBrokerMountPointTest { @Test public void testMountPoint() { - testContext.getBindingDataBroker().readOperationalData(NODE_INSTANCE_ID_BA); + testContext.getBindingDataBroker().readOperationalData(TLL_INSTANCE_ID_BA); - MountProvisionInstance domMountPoint = domMountPointService.createMountPoint(NODE_INSTANCE_ID_BI); + MountProvisionInstance domMountPoint = domMountPointService.createMountPoint(TLL_INSTANCE_ID_BI); assertNotNull(domMountPoint); - MountProviderInstance bindingMountPoint = bindingMountPointService.getMountPoint(NODE_INSTANCE_ID_BA); + MountProviderInstance bindingMountPoint = bindingMountPointService.getMountPoint(TLL_INSTANCE_ID_BA); assertNotNull(bindingMountPoint); - final BigInteger packetCount = BigInteger.valueOf(500L); + final Integer attrIntalue = 500; DataReader simpleReader = new DataReader() { @@ -125,9 +130,9 @@ public class CrossBrokerMountPointTest { if (arg0.equals(GROUP_STATISTICS_ID_BI)) { ImmutableCompositeNode data = ImmutableCompositeNode .builder() - .setQName(AUGMENTED_GROUP_STATISTICS) - .addLeaf(QName.create(AUGMENTED_GROUP_STATISTICS, "packet-count"), packetCount) // - .toInstance(); + .setQName(AUG_CONT) + .addLeaf(QName.create(AUG_CONT, "attr-int"), attrIntalue) // + .build(); return data; } @@ -135,10 +140,10 @@ public class CrossBrokerMountPointTest { } }; - domMountPoint.registerOperationalReader(NODE_INSTANCE_ID_BI, simpleReader); + domMountPoint.registerOperationalReader(TLL_INSTANCE_ID_BI, simpleReader); - GroupStatistics data = (GroupStatistics) bindingMountPoint.readOperationalData(GROUP_STATISTICS_ID_BA); + Cont data = (Cont) bindingMountPoint.readOperationalData(AUG_CONT_ID_BA); assertNotNull(data); - assertEquals(packetCount,data.getPacketCount().getValue()); + assertEquals(attrIntalue ,data.getAttrInt()); } } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerRpcTest.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerRpcTest.java index ba75d578fb..83c2f88376 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerRpcTest.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerRpcTest.java @@ -12,11 +12,10 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; -import java.math.BigInteger; -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.Future; - +import com.google.common.collect.ImmutableSet; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -25,19 +24,15 @@ import org.opendaylight.controller.sal.binding.test.util.BindingBrokerTestFactor import org.opendaylight.controller.sal.binding.test.util.BindingTestContext; import org.opendaylight.controller.sal.core.api.RpcImplementation; import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlowRemoved; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.KnockKnockInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.KnockKnockInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.KnockKnockOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.KnockKnockOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.OpendaylightOfMigrationTestModelService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.rpc.routing.rev140701.TestContext; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.QName; @@ -45,38 +40,31 @@ import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl; - -import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.MoreExecutors; +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.Future; public class CrossBrokerRpcTest { - protected RpcProviderRegistry baRpcRegistry; - protected RpcProvisionRegistry biRpcRegistry; + protected RpcProviderRegistry providerRegistry; + protected RpcProvisionRegistry provisionRegistry; private BindingTestContext testContext; private RpcImplementation biRpcInvoker; - private MessageCapturingFlowService flowService; + private MessageCapturingFlowService knockService; - public static final NodeId NODE_A = new NodeId("a"); - public static final NodeId NODE_B = new NodeId("b"); - public static final NodeId NODE_C = new NodeId("c"); - public static final NodeId NODE_D = new NodeId("d"); + public static final TopLevelListKey NODE_A = new TopLevelListKey("a"); + public static final TopLevelListKey NODE_B = new TopLevelListKey("b"); + public static final TopLevelListKey NODE_C = new TopLevelListKey("c"); - private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id"); - private static final QName ADD_FLOW_QNAME = QName.create(NodeFlowRemoved.QNAME, "add-flow"); + private static final QName NODE_ID_QNAME = QName.create(TopLevelList.QNAME, "name"); + private static final QName KNOCK_KNOCK_QNAME = QName.create(KnockKnockOutput.QNAME, "knock-knock"); - public static final InstanceIdentifier BA_NODE_A_ID = createBANodeIdentifier(NODE_A); - public static final InstanceIdentifier BA_NODE_B_ID = createBANodeIdentifier(NODE_B); - public static final InstanceIdentifier BA_NODE_C_ID = createBANodeIdentifier(NODE_C); - public static final InstanceIdentifier BA_NODE_D_ID = createBANodeIdentifier(NODE_D); + public static final InstanceIdentifier NODES_PATH = InstanceIdentifier.builder(Top.class).build(); + public static final InstanceIdentifier BA_NODE_A_ID = NODES_PATH.child(TopLevelList.class, NODE_A); + public static final InstanceIdentifier BA_NODE_B_ID = NODES_PATH.child(TopLevelList.class, NODE_B); + public static final InstanceIdentifier BA_NODE_C_ID = NODES_PATH.child(TopLevelList.class, NODE_C); - public static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier BI_NODE_A_ID = createBINodeIdentifier(NODE_A); - public static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier BI_NODE_B_ID = createBINodeIdentifier(NODE_B); public static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier BI_NODE_C_ID = createBINodeIdentifier(NODE_C); - public static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier BI_NODE_D_ID = createBINodeIdentifier(NODE_D); - @Before @@ -87,48 +75,49 @@ public class CrossBrokerRpcTest { testContext = testFactory.getTestContext(); testContext.start(); - baRpcRegistry = testContext.getBindingRpcRegistry(); - biRpcRegistry = testContext.getDomRpcRegistry(); + providerRegistry = testContext.getBindingRpcRegistry(); + provisionRegistry = testContext.getDomRpcRegistry(); biRpcInvoker = testContext.getDomRpcInvoker(); - assertNotNull(baRpcRegistry); - assertNotNull(biRpcRegistry); + assertNotNull(providerRegistry); + assertNotNull(provisionRegistry); - flowService = MessageCapturingFlowService.create(baRpcRegistry); + knockService = MessageCapturingFlowService.create(providerRegistry); } @Test public void bindingRoutedRpcProvider_DomInvokerTest() throws Exception { - flowService// - .registerPath(NodeContext.class, BA_NODE_A_ID) // - .registerPath(NodeContext.class, BA_NODE_B_ID) // - .setAddFlowResult(addFlowResult(true, 10)); + knockService// + .registerPath(TestContext.class, BA_NODE_A_ID) // + .registerPath(TestContext.class, BA_NODE_B_ID) // + .setKnockKnockResult(knockResult(true, "open")); - SalFlowService baFlowInvoker = baRpcRegistry.getRpcService(SalFlowService.class); - assertNotSame(flowService, baFlowInvoker); + OpendaylightOfMigrationTestModelService baKnockInvoker = + providerRegistry.getRpcService(OpendaylightOfMigrationTestModelService.class); + assertNotSame(knockService, baKnockInvoker); - AddFlowInput addFlowA = addFlow(BA_NODE_A_ID) // - .setPriority(100).setBarrier(true).build(); + KnockKnockInput knockKnockA = knockKnock(BA_NODE_A_ID) // + .setQuestion("who's there?").build(); - CompositeNode addFlowDom = toDomRpc(ADD_FLOW_QNAME, addFlowA); - assertNotNull(addFlowDom); - RpcResult domResult = biRpcInvoker.invokeRpc(ADD_FLOW_QNAME, addFlowDom).get(); + CompositeNode knockKnockDom = toDomRpc(KNOCK_KNOCK_QNAME, knockKnockA); + assertNotNull(knockKnockDom); + RpcResult domResult = biRpcInvoker.invokeRpc(KNOCK_KNOCK_QNAME, knockKnockDom).get(); assertNotNull(domResult); assertTrue("DOM result is successful.", domResult.isSuccessful()); - assertTrue("Bidning Add Flow RPC was captured.", flowService.getReceivedAddFlows().containsKey(BA_NODE_A_ID)); - assertEquals(addFlowA, flowService.getReceivedAddFlows().get(BA_NODE_A_ID).iterator().next()); + assertTrue("Bidning Add Flow RPC was captured.", knockService.getReceivedKnocks().containsKey(BA_NODE_A_ID)); + assertEquals(knockKnockA, knockService.getReceivedKnocks().get(BA_NODE_A_ID).iterator().next()); } @Test public void bindingRpcInvoker_DomRoutedProviderTest() throws Exception { - AddFlowOutputBuilder builder = new AddFlowOutputBuilder(); - builder.setTransactionId(new TransactionId(BigInteger.valueOf(10))); - final AddFlowOutput output = builder.build(); - org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration registration = biRpcRegistry.addRoutedRpcImplementation(ADD_FLOW_QNAME, new RpcImplementation() { + KnockKnockOutputBuilder builder = new KnockKnockOutputBuilder(); + builder.setAnswer("open"); + final KnockKnockOutput output = builder.build(); + org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration registration = provisionRegistry.addRoutedRpcImplementation(KNOCK_KNOCK_QNAME, new RpcImplementation() { @Override public Set getSupportedRpcs() { - return ImmutableSet.of(ADD_FLOW_QNAME); + return ImmutableSet.of(KNOCK_KNOCK_QNAME); } @Override @@ -137,12 +126,14 @@ public class CrossBrokerRpcTest { return Futures.immediateFuture(RpcResultBuilder.success(result).build()); } }); - registration.registerPath(NodeContext.QNAME, BI_NODE_C_ID); + registration.registerPath(TestContext.QNAME, BI_NODE_C_ID); + - SalFlowService baFlowInvoker = baRpcRegistry.getRpcService(SalFlowService.class); - Future> baResult = baFlowInvoker.addFlow(addFlow(BA_NODE_C_ID).setPriority(500).build()); + OpendaylightOfMigrationTestModelService baKnockInvoker = + providerRegistry.getRpcService(OpendaylightOfMigrationTestModelService.class); + Future> baResult = baKnockInvoker.knockKnock((knockKnock(BA_NODE_C_ID).setQuestion("Who's there?").build())); assertNotNull(baResult); - assertEquals(output,baResult.get().getResult()); + assertEquals(output, baResult.get().getResult()); } private CompositeNode toDomRpcInput(DataObject addFlowA) { @@ -154,30 +145,26 @@ public class CrossBrokerRpcTest { testContext.close(); } - private static InstanceIdentifier createBANodeIdentifier(NodeId node) { - return InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(node)).toInstance(); - } - - private static org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier createBINodeIdentifier(NodeId node) { - return org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder().node(Nodes.QNAME) - .nodeWithKey(Node.QNAME, NODE_ID_QNAME, node.getValue()).toInstance(); + private static org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier createBINodeIdentifier(TopLevelListKey listKey) { + return org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.builder().node(Top.QNAME) + .nodeWithKey(TopLevelList.QNAME, NODE_ID_QNAME, listKey.getName()).toInstance(); } - private Future> addFlowResult(boolean success, long xid) { - AddFlowOutput output = new AddFlowOutputBuilder() // - .setTransactionId(new TransactionId(BigInteger.valueOf(xid))).build(); - RpcResult result = RpcResultBuilder.status(success).withResult(output).build(); + private Future> knockResult(boolean success, String answer) { + KnockKnockOutput output = new KnockKnockOutputBuilder() // + .setAnswer(answer).build(); + RpcResult result = RpcResultBuilder.status(success).withResult(output).build(); return Futures.immediateFuture(result); } - private static AddFlowInputBuilder addFlow(InstanceIdentifier nodeId) { - AddFlowInputBuilder builder = new AddFlowInputBuilder(); - builder.setNode(new NodeRef(nodeId)); + private static KnockKnockInputBuilder knockKnock(InstanceIdentifier listId) { + KnockKnockInputBuilder builder = new KnockKnockInputBuilder(); + builder.setKnockerId(listId); return builder; } - private CompositeNode toDomRpc(QName rpcName, AddFlowInput addFlowA) { + private CompositeNode toDomRpc(QName rpcName, KnockKnockInput knockInput) { return new CompositeNodeTOImpl(rpcName, null, - Collections.> singletonList(toDomRpcInput(addFlowA))); + Collections.>singletonList(toDomRpcInput(knockInput))); } } diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/DOMRpcServiceTestBugfix560.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/DOMRpcServiceTestBugfix560.java index 7d616ca62c..7595ec0105 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/DOMRpcServiceTestBugfix560.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/DOMRpcServiceTestBugfix560.java @@ -28,12 +28,11 @@ import org.opendaylight.controller.sal.binding.test.util.BindingTestContext; import org.opendaylight.controller.sal.core.api.RpcImplementation; import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance; import org.opendaylight.controller.sal.core.api.mount.MountProvisionService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; -import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.bi.ba.rpcservice.rev140701.OpendaylightTestRpcServiceService; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.bi.ba.rpcservice.rev140701.RockTheHouseInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.util.BindingReflections; import org.opendaylight.yangtools.yang.common.QName; @@ -64,11 +63,11 @@ public class DOMRpcServiceTestBugfix560 { private final static QName RPC_NAME = QName.create(RPC_SERVICE_NAMESPACE, REVISION_DATE, "rock-the-house"); - private static final NodeId MOUNT_NODE = new NodeId("id"); - private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id"); + private static final String TLL_NAME = "id"; + private static final QName TLL_NAME_QNAME = QName.create(TopLevelList.QNAME, "name"); - private static final InstanceIdentifier BA_MOUNT_ID = createBANodeIdentifier(MOUNT_NODE); - private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier BI_MOUNT_ID = createBINodeIdentifier(MOUNT_NODE); + private static final InstanceIdentifier BA_MOUNT_ID = createBATllIdentifier(TLL_NAME); + private static final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier BI_MOUNT_ID = createBITllIdentifier(TLL_NAME); private BindingTestContext testContext; private MountProvisionService domMountPointService; @@ -104,18 +103,18 @@ public class DOMRpcServiceTestBugfix560 { schemaContext = mountSchemaContext; } - private static org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier createBINodeIdentifier( - final NodeId mountNode) { + private static org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier createBITllIdentifier( + final String mount) { return org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier - .builder().node(Nodes.QNAME) - .nodeWithKey(Node.QNAME, NODE_ID_QNAME, mountNode.getValue()) + .builder().node(Top.QNAME) + .nodeWithKey(TopLevelList.QNAME, TLL_NAME_QNAME, mount) .toInstance(); } - private static InstanceIdentifier createBANodeIdentifier( - final NodeId mountNode) { - return InstanceIdentifier.builder(Nodes.class) - .child(Node.class, new NodeKey(mountNode)).toInstance(); + private static InstanceIdentifier createBATllIdentifier( + final String mount) { + return InstanceIdentifier.builder(Top.class) + .child(TopLevelList.class, new TopLevelListKey(mount)).toInstance(); } @SuppressWarnings("deprecation") diff --git a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MessageCapturingFlowService.java b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MessageCapturingFlowService.java index 47e79650fe..0f9389703f 100644 --- a/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MessageCapturingFlowService.java +++ b/opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MessageCapturingFlowService.java @@ -11,15 +11,11 @@ import static org.junit.Assert.assertNotNull; import java.util.concurrent.Future; -import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput; +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.KnockKnockInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.KnockKnockOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.of.migration.test.model.rev150210.OpendaylightOfMigrationTestModelService; import org.opendaylight.yangtools.yang.binding.BaseIdentity; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; @@ -27,76 +23,28 @@ import org.opendaylight.yangtools.yang.common.RpcResult; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; -public class MessageCapturingFlowService implements SalFlowService, AutoCloseable { - - private Future> addFlowResult; - private Future> removeFlowResult; - private Future> updateFlowResult; - - private final Multimap, AddFlowInput> receivedAddFlows = HashMultimap.create(); - private final Multimap, RemoveFlowInput> receivedRemoveFlows = HashMultimap.create(); - private final Multimap, UpdateFlowInput> receivedUpdateFlows = HashMultimap.create(); - private RoutedRpcRegistration registration; - - @Override - public Future> addFlow(AddFlowInput arg0) { - receivedAddFlows.put(arg0.getNode().getValue(), arg0); - return addFlowResult; - } - - @Override - public Future> removeFlow(RemoveFlowInput arg0) { - receivedRemoveFlows.put(arg0.getNode().getValue(), arg0); - return removeFlowResult; - } - - @Override - public Future> updateFlow(UpdateFlowInput arg0) { - receivedUpdateFlows.put(arg0.getNode().getValue(), arg0); - return updateFlowResult; - } - - public Future> getAddFlowResult() { - return addFlowResult; - } +public class MessageCapturingFlowService implements OpendaylightOfMigrationTestModelService, AutoCloseable { - public MessageCapturingFlowService setAddFlowResult(Future> addFlowResult) { - this.addFlowResult = addFlowResult; - return this; - } + private Future> knockKnockResult; - public Future> getRemoveFlowResult() { - return removeFlowResult; - } - - public MessageCapturingFlowService setRemoveFlowResult(Future> removeFlowResult) { - this.removeFlowResult = removeFlowResult; - return this; - } + private final Multimap, KnockKnockInput> receivedKnocks = HashMultimap.create(); + private RoutedRpcRegistration registration; - public Future> getUpdateFlowResult() { - return updateFlowResult; + public Future> getKnockKnockResult() { + return knockKnockResult; } - public MessageCapturingFlowService setUpdateFlowResult(Future> updateFlowResult) { - this.updateFlowResult = updateFlowResult; + public MessageCapturingFlowService setKnockKnockResult(Future> kkOutput) { + this.knockKnockResult = kkOutput; return this; } - public Multimap, AddFlowInput> getReceivedAddFlows() { - return receivedAddFlows; - } - - public Multimap, RemoveFlowInput> getReceivedRemoveFlows() { - return receivedRemoveFlows; - } - - public Multimap, UpdateFlowInput> getReceivedUpdateFlows() { - return receivedUpdateFlows; + public Multimap, KnockKnockInput> getReceivedKnocks() { + return receivedKnocks; } public MessageCapturingFlowService registerTo(RpcProviderRegistry registry) { - registration = registry.addRoutedRpcImplementation(SalFlowService.class, this); + registration = registry.addRoutedRpcImplementation(OpendaylightOfMigrationTestModelService.class, this); assertNotNull(registration); return this; } @@ -125,5 +73,11 @@ public class MessageCapturingFlowService implements SalFlowService, AutoCloseabl return ret; } + @Override + public Future> knockKnock(KnockKnockInput input) { + receivedKnocks.put(input.getKnockerId(), input); + return knockKnockResult; + } + } diff --git a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/common/actor/AbstractUntypedPersistentActor.java b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/common/actor/AbstractUntypedPersistentActor.java index 95ee21674a..432c2d5615 100644 --- a/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/common/actor/AbstractUntypedPersistentActor.java +++ b/opendaylight/md-sal/sal-clustering-commons/src/main/java/org/opendaylight/controller/cluster/common/actor/AbstractUntypedPersistentActor.java @@ -20,8 +20,8 @@ public abstract class AbstractUntypedPersistentActor extends UntypedPersistentAc protected final Logger LOG = LoggerFactory.getLogger(getClass()); public AbstractUntypedPersistentActor() { - if(LOG.isDebugEnabled()) { - LOG.debug("Actor created {}", getSelf()); + if(LOG.isTraceEnabled()) { + LOG.trace("Actor created {}", getSelf()); } getContext(). system(). @@ -33,24 +33,24 @@ public abstract class AbstractUntypedPersistentActor extends UntypedPersistentAc @Override public void onReceiveCommand(Object message) throws Exception { final String messageType = message.getClass().getSimpleName(); - if(LOG.isDebugEnabled()) { - LOG.debug("Received message {}", messageType); + if(LOG.isTraceEnabled()) { + LOG.trace("Received message {}", messageType); } handleCommand(message); - if(LOG.isDebugEnabled()) { - LOG.debug("Done handling message {}", messageType); + if(LOG.isTraceEnabled()) { + LOG.trace("Done handling message {}", messageType); } } @Override public void onReceiveRecover(Object message) throws Exception { final String messageType = message.getClass().getSimpleName(); - if(LOG.isDebugEnabled()) { - LOG.debug("Received message {}", messageType); + if(LOG.isTraceEnabled()) { + LOG.trace("Received message {}", messageType); } handleRecover(message); - if(LOG.isDebugEnabled()) { - LOG.debug("Done handling message {}", messageType); + if(LOG.isTraceEnabled()) { + LOG.trace("Done handling message {}", messageType); } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java index 87a0fb931e..21d74a6e1a 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/Shard.java @@ -229,10 +229,6 @@ public class Shard extends RaftActor { @Override public void onReceiveCommand(final Object message) throws Exception { - if(LOG.isDebugEnabled()) { - LOG.debug("{}: onReceiveCommand: Received message {} from {}", persistenceId(), message, getSender()); - } - if (message.getClass().equals(CreateTransaction.SERIALIZABLE_CLASS)) { handleCreateTransaction(message); } else if(message instanceof ForwardedReadyTransaction) { diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java index 3dbac003b9..d52965e055 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardManager.java @@ -271,7 +271,7 @@ public class ShardManager extends AbstractUntypedPersistentActorWithMetering { if(newModules.containsAll(knownModules)) { - LOG.info("New SchemaContext has a super set of current knownModules - persisting info"); + LOG.debug("New SchemaContext has a super set of current knownModules - persisting info"); knownModules = ImmutableSet.copyOf(newModules); @@ -279,7 +279,7 @@ public class ShardManager extends AbstractUntypedPersistentActorWithMetering { @Override public void apply(SchemaContextModules param) throws Exception { - LOG.info("Sending new SchemaContext to Shards"); + LOG.debug("Sending new SchemaContext to Shards"); for (ShardInformation info : localShards.values()) { if (info.getActor() == null) { info.setActor(getContext().actorOf(Shard.props(info.getShardId(), @@ -293,7 +293,8 @@ public class ShardManager extends AbstractUntypedPersistentActorWithMetering { }); } else { - LOG.info("Rejecting schema context update because it is not a super set of previously known modules"); + LOG.debug("Rejecting schema context update - not a super set of previously known modules:\nUPDATE: {}\nKNOWN: {}", + newModules, knownModules); } } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java index 1e2386ae1b..af25df13d2 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/ShardTransaction.java @@ -134,7 +134,7 @@ public abstract class ShardTransaction extends AbstractUntypedActorWithMetering sender().tell((returnSerialized ? readDataReply.toSerializable(clientTxVersion): readDataReply), self()); } catch (Exception e) { - LOG.error(String.format("Unexpected error reading path %s", path), e); + LOG.debug(String.format("Unexpected error reading path %s", path), e); shardStats.incrementFailedReadTransactionsCount(); sender().tell(new akka.actor.Status.Failure(e), self()); } diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java index 94b9698abf..4b0651a48e 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/ShardTest.java @@ -1467,7 +1467,7 @@ public class ShardTest extends AbstractActorTest { NormalizedNode expectedRoot = readStore(shard, YangInstanceIdentifier.builder().build()); - CaptureSnapshot capture = new CaptureSnapshot(-1, -1, -1, -1); + CaptureSnapshot capture = new CaptureSnapshot(-1, -1, -1, -1, -1, -1); shard.tell(capture, getRef()); assertEquals("Snapshot saved", true, latch.get().await(5, TimeUnit.SECONDS)); diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/MutableCompositeModificationTest.java b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/MutableCompositeModificationTest.java index 8ae2a8657d..b9d44b2586 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/MutableCompositeModificationTest.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/modification/MutableCompositeModificationTest.java @@ -80,8 +80,7 @@ public class MutableCompositeModificationTest extends AbstractModificationTest { compositeModification.addModification(new WriteModification(writePath, writeData)); } - Stopwatch sw = new Stopwatch(); - sw.start(); + Stopwatch sw = Stopwatch.createStarted(); for(int i = 0; i < 1000; i++) { new ModificationPayload(compositeModification); } diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcIdentifier.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcIdentifier.java index 1976913a17..4e6c7a5f7f 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcIdentifier.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/md/sal/dom/api/DOMRpcIdentifier.java @@ -7,6 +7,7 @@ */ package org.opendaylight.controller.md.sal.dom.api; +import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; import java.util.Objects; import javax.annotation.Nonnull; @@ -119,6 +120,6 @@ public abstract class DOMRpcIdentifier { @Override public final String toString() { - return com.google.common.base.Objects.toStringHelper(this).omitNullValues().add("type", type).add("contextReference", getContextReference()).toString(); + return MoreObjects.toStringHelper(this).omitNullValues().add("type", type).add("contextReference", getContextReference()).toString(); } } diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java index da592e9b22..5d086e59a7 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcConsumptionRegistry.java @@ -8,11 +8,14 @@ package org.opendaylight.controller.sal.core.api; import java.util.concurrent.Future; - import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; +/** + * @deprecated Use {@link org.opendaylight.controller.md.sal.dom.api.DOMRpcService} instead. + */ +@Deprecated public interface RpcConsumptionRegistry { /** * Sends an RPC to other components registered to the broker. diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementation.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementation.java index d14910055b..5055ad1430 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementation.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementation.java @@ -7,14 +7,12 @@ */ package org.opendaylight.controller.sal.core.api; +import com.google.common.util.concurrent.ListenableFuture; import java.util.Set; - import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.data.api.CompositeNode; -import com.google.common.util.concurrent.ListenableFuture; - /** * {@link Provider}'s implementation of an RPC. * @@ -42,7 +40,10 @@ import com.google.common.util.concurrent.ListenableFuture; * {@link RpcResult} *
  • {@link Broker} returns the {@link RpcResult} to {@link Consumer} * + * + * @deprecated Use {@link org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementation} instead. */ +@Deprecated public interface RpcImplementation extends Provider.ProviderFunctionality { /** diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementationUnavailableException.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementationUnavailableException.java index 371082223a..45f13654d8 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementationUnavailableException.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementationUnavailableException.java @@ -9,7 +9,10 @@ package org.opendaylight.controller.sal.core.api; /** * Exception reported when no RPC implementation is found in the system. + * + * @deprecated Use {@link org.opendaylight.controller.md.sal.dom.api.DOMRpcImplementationNotAvailableException} instead. */ +@Deprecated public class RpcImplementationUnavailableException extends RuntimeException { private static final long serialVersionUID = 1L; diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java index 050225c5c2..1caed09437 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcProvisionRegistry.java @@ -15,6 +15,10 @@ import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +/** + * @deprecated Use {@link org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService} and {@link org.opendaylight.controller.md.sal.dom.api.DOMRpcService} instead. + */ +@Deprecated public interface RpcProvisionRegistry extends RpcImplementation, BrokerService, RouteChangePublisher, DOMService { /** diff --git a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcRegistrationListener.java b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcRegistrationListener.java index a0be886b24..df20650ac4 100644 --- a/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcRegistrationListener.java +++ b/opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcRegistrationListener.java @@ -8,9 +8,12 @@ package org.opendaylight.controller.sal.core.api; import java.util.EventListener; - import org.opendaylight.yangtools.yang.common.QName; +/** + * @deprecated Use {@link org.opendaylight.controller.md.sal.dom.api.DOMRpcAvailabilityListener} instead. + */ +@Deprecated public interface RpcRegistrationListener extends EventListener { public void onRpcImplementationAdded(QName name); diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/PingPongTransaction.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/PingPongTransaction.java index fdb80ebcbe..51b28e1450 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/PingPongTransaction.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/PingPongTransaction.java @@ -7,8 +7,8 @@ */ package org.opendaylight.controller.md.sal.dom.broker.impl; -import com.google.common.base.Objects; -import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.MoreObjects; +import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.FutureCallback; @@ -73,7 +73,7 @@ final class PingPongTransaction implements FutureCallback { @Override public String toString() { - return addToStringAttributes(Objects.toStringHelper(this)).toString(); + return addToStringAttributes(MoreObjects.toStringHelper(this)).toString(); } protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { diff --git a/opendaylight/md-sal/sal-dummy-distributed-datastore/src/main/java/org/opendaylight/controller/dummy/datastore/DummyShard.java b/opendaylight/md-sal/sal-dummy-distributed-datastore/src/main/java/org/opendaylight/controller/dummy/datastore/DummyShard.java index 34b41ccfca..3dffdfce57 100644 --- a/opendaylight/md-sal/sal-dummy-distributed-datastore/src/main/java/org/opendaylight/controller/dummy/datastore/DummyShard.java +++ b/opendaylight/md-sal/sal-dummy-distributed-datastore/src/main/java/org/opendaylight/controller/dummy/datastore/DummyShard.java @@ -11,6 +11,7 @@ package org.opendaylight.controller.dummy.datastore; import akka.actor.Props; import akka.actor.UntypedActor; import akka.japi.Creator; +import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry; import org.opendaylight.controller.cluster.raft.messages.AppendEntries; import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply; import org.opendaylight.controller.cluster.raft.messages.InstallSnapshot; @@ -24,6 +25,8 @@ public class DummyShard extends UntypedActor{ private final Configuration configuration; private final String followerId; private final Logger LOG = LoggerFactory.getLogger(DummyShard.class); + private long lastMessageIndex = -1; + private long lastMessageSize = 0; public DummyShard(Configuration configuration, String followerId) { this.configuration = configuration; @@ -54,12 +57,25 @@ public class DummyShard extends UntypedActor{ } protected void handleAppendEntries(AppendEntries req) throws InterruptedException { - LOG.info("{} - Received AppendEntries message : leader term, index, size = {}, {}, {}", followerId, req.getTerm(),req.getLeaderCommit(), req.getEntries().size()); + + LOG.info("{} - Received AppendEntries message : leader term = {}, index = {}, prevLogIndex = {}, size = {}", + followerId, req.getTerm(),req.getLeaderCommit(), req.getPrevLogIndex(), req.getEntries().size()); + + if(lastMessageIndex == req.getLeaderCommit() && req.getEntries().size() > 0 && lastMessageSize > 0){ + LOG.error("{} - Duplicate message with leaderCommit = {} prevLogIndex = {} received", followerId, req.getLeaderCommit(), req.getPrevLogIndex()); + } + + lastMessageIndex = req.getLeaderCommit(); + lastMessageSize = req.getEntries().size(); + long lastIndex = req.getLeaderCommit(); - if (req.getEntries().size() > 0) - lastIndex = req.getEntries().get(0).getIndex(); + if (req.getEntries().size() > 0) { + for(ReplicatedLogEntry entry : req.getEntries()) { + lastIndex = entry.getIndex(); + } + } - if (configuration.shouldCauseTrouble()) { + if (configuration.shouldCauseTrouble() && req.getEntries().size() > 0) { boolean ignore = false; if (configuration.shouldDropReplies()) { diff --git a/opendaylight/md-sal/sal-dummy-distributed-datastore/src/main/resources/simplelogger.properties b/opendaylight/md-sal/sal-dummy-distributed-datastore/src/main/resources/simplelogger.properties new file mode 100644 index 0000000000..067c048231 --- /dev/null +++ b/opendaylight/md-sal/sal-dummy-distributed-datastore/src/main/resources/simplelogger.properties @@ -0,0 +1,6 @@ +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=hh:mm:ss,S a +org.slf4j.simpleLogger.logFile=System.out +org.slf4j.simpleLogger.showShortLogName=true +org.slf4j.simpleLogger.levelInBrackets=true +org.slf4j.simpleLogger.defaultLogLevel=info \ No newline at end of file diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDOMStoreTransaction.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDOMStoreTransaction.java index 6cc5939047..8d040f612e 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDOMStoreTransaction.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/AbstractDOMStoreTransaction.java @@ -7,10 +7,9 @@ */ package org.opendaylight.controller.md.sal.dom.store.impl; -import com.google.common.base.Objects; -import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.MoreObjects; +import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Preconditions; - import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransaction; import org.slf4j.Logger; @@ -42,7 +41,7 @@ abstract class AbstractDOMStoreTransaction implements DOMStoreTransaction { @Override public final String toString() { - return addToStringAttributes(Objects.toStringHelper(this)).toString(); + return addToStringAttributes(MoreObjects.toStringHelper(this)).toString(); } /** diff --git a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedWriteTransaction.java b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedWriteTransaction.java index 60a23403b3..faddbae850 100644 --- a/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedWriteTransaction.java +++ b/opendaylight/md-sal/sal-inmemory-datastore/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/SnapshotBackedWriteTransaction.java @@ -8,7 +8,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl; import static com.google.common.base.Preconditions.checkState; -import com.google.common.base.Objects.ToStringHelper; +import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Throwables; diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/ReadOnlyTx.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/ReadOnlyTx.java index a3186f8e69..00bdbb6db0 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/ReadOnlyTx.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/ReadOnlyTx.java @@ -110,7 +110,7 @@ public final class ReadOnlyTx implements DOMDataReadOnlyTransaction { private CheckedFuture>, ReadFailedException> readOperationalData( final YangInstanceIdentifier path) { - final ListenableFuture> configCandidate = netconfOps.getConfigRunning(loggingCallback, Optional.fromNullable(path)); + final ListenableFuture> configCandidate = netconfOps.get(loggingCallback, Optional.fromNullable(path)); // Find data node and normalize its content final ListenableFuture>> transformedFuture = Futures.transform(configCandidate, new Function, Optional>>() { diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/NetconfRemoteSchemaYangSourceProvider.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/NetconfRemoteSchemaYangSourceProvider.java index 5a528bc418..3565ba1113 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/NetconfRemoteSchemaYangSourceProvider.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/schema/NetconfRemoteSchemaYangSourceProvider.java @@ -8,7 +8,7 @@ package org.opendaylight.controller.sal.connect.netconf.schema; import com.google.common.base.Function; -import com.google.common.base.Objects; +import com.google.common.base.MoreObjects; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.CheckedFuture; @@ -166,7 +166,7 @@ public final class NetconfRemoteSchemaYangSourceProvider implements SchemaSource } @Override - protected Objects.ToStringHelper addToStringAttributes(final Objects.ToStringHelper toStringHelper) { + protected MoreObjects.ToStringHelper addToStringAttributes(final MoreObjects.ToStringHelper toStringHelper) { return toStringHelper.add("device", id); } diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfBaseOps.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfBaseOps.java index 8ac8a48b45..40e890e80c 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfBaseOps.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfBaseOps.java @@ -174,33 +174,17 @@ public final class NetconfBaseOps { return getConfig(callback, NETCONF_CANDIDATE_QNAME, filterPath); } - public ListenableFuture> get(final FutureCallback> callback, final QName datastore, final Optional filterPath) { + public ListenableFuture> get(final FutureCallback> callback, final Optional filterPath) { Preconditions.checkNotNull(callback); - Preconditions.checkNotNull(datastore); final ListenableFuture> future; - if (filterPath.isPresent()) { - final Node node = toFilterStructure(filterPath.get()); - future = rpc.invokeRpc(NETCONF_GET_QNAME, - NetconfMessageTransformUtil.wrap(NETCONF_GET_QNAME, getSourceNode(datastore), node)); - } else { - future = rpc.invokeRpc(NETCONF_GET_QNAME, - NetconfMessageTransformUtil.wrap(NETCONF_GET_QNAME, getSourceNode(datastore))); - } + final Node node = filterPath.isPresent() ? toFilterStructure(filterPath.get()) : NetconfMessageTransformUtil.GET_RPC_CONTENT; + future = rpc.invokeRpc(NETCONF_GET_QNAME, NetconfMessageTransformUtil.wrap(NETCONF_GET_QNAME, node)); Futures.addCallback(future, callback); return future; } - public ListenableFuture> getRunning(final FutureCallback> callback, final Optional filterPath) { - return get(callback, NETCONF_RUNNING_QNAME, filterPath); - } - - public ListenableFuture> getCandidate(final FutureCallback> callback, final Optional filterPath) { - return get(callback, NETCONF_CANDIDATE_QNAME, filterPath); - } - - public ListenableFuture> editConfigCandidate(final FutureCallback> callback, final CompositeNode editStructure, final ModifyAction modifyAction, final boolean rollback) { return editConfig(callback, NETCONF_CANDIDATE_QNAME, editStructure, Optional.of(modifyAction), rollback); } diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java index 5e3ad2c1fb..371907e0fe 100644 --- a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java +++ b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/util/NetconfMessageTransformUtil.java @@ -113,6 +113,10 @@ public class NetconfMessageTransformUtil { public static final CompositeNode COMMIT_RPC_CONTENT = NodeFactory.createImmutableCompositeNode(NETCONF_COMMIT_QNAME, null, Collections.>emptyList()); + // Get message + public static final CompositeNode GET_RPC_CONTENT = + NodeFactory.createImmutableCompositeNode(NETCONF_GET_QNAME, null, Collections.>emptyList()); + // Create-subscription changes message public static final CompositeNode CREATE_SUBSCRIPTION_RPC_CONTENT = NodeFactory.createImmutableCompositeNode(CREATE_SUBSCRIPTION_RPC_QNAME, null, Collections.>emptyList()); diff --git a/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java new file mode 100644 index 0000000000..072cb185d0 --- /dev/null +++ b/opendaylight/md-sal/sal-netconf-connector/src/test/java/org/opendaylight/controller/sal/connect/netconf/sal/tx/ReadOnlyTxTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015 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.sal.connect.netconf.sal.tx; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; + +import java.net.InetSocketAddress; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException; +import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer; +import org.opendaylight.controller.sal.connect.netconf.util.NetconfBaseOps; +import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil; +import org.opendaylight.controller.sal.connect.util.RemoteDeviceId; +import org.opendaylight.controller.sal.core.api.RpcImplementation; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; + +public class ReadOnlyTxTest { + + private static final YangInstanceIdentifier path = YangInstanceIdentifier.create(); + + @Mock + private RpcImplementation rpc; + @Mock + private DataNormalizer normalizer; + @Mock + private CompositeNode mockedNode; + + @Before + public void setUp() throws DataNormalizationException { + MockitoAnnotations.initMocks(this); + doReturn(path).when(normalizer).toLegacy(any(YangInstanceIdentifier.class)); + doReturn(com.google.common.util.concurrent.Futures.immediateFuture(RpcResultBuilder.success(mockedNode).build())).when(rpc).invokeRpc(any(org.opendaylight.yangtools.yang.common.QName.class), any(CompositeNode.class)); + doReturn("node").when(mockedNode).toString(); + } + + @Test + public void testRead() throws Exception { + final NetconfBaseOps netconfOps = new NetconfBaseOps(rpc); + + final ReadOnlyTx readOnlyTx = new ReadOnlyTx(netconfOps, normalizer, new RemoteDeviceId("a", new InetSocketAddress("localhost", 196))); + + readOnlyTx.read(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create()); + verify(rpc).invokeRpc(Mockito.same(NetconfMessageTransformUtil.NETCONF_GET_CONFIG_QNAME), any(CompositeNode.class)); + readOnlyTx.read(LogicalDatastoreType.OPERATIONAL, path); + verify(rpc).invokeRpc(Mockito.same(NetconfMessageTransformUtil.NETCONF_GET_QNAME), any(CompositeNode.class)); + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-of-migration-test-model.yang b/opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-of-migration-test-model.yang new file mode 100644 index 0000000000..24ff5dd965 --- /dev/null +++ b/opendaylight/md-sal/sal-test-model/src/main/yang/opendaylight-of-migration-test-model.yang @@ -0,0 +1,156 @@ +module opendaylight-of-migration-test-model { + + namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:of-migration-test-model"; + prefix of-migration-test; + + import opendaylight-mdsal-list-test {prefix test;} + import yang-ext {prefix ext;} + import opendaylight-mdsal-augment-test {prefix aug;} + import opendaylight-test-routed-rpc {prefix routed;} + + description + "This module contains a collection of YANG definitions used for + test cases that used to depend on flow model."; + + revision 2015-02-10 { + } + + typedef bit-flags { + type bits { + bit FLAG_ONE; + bit FLAG_TWO; + bit FLAG_THREE; + bit FLAG_FOUR; + bit FLAG_FIVE; + } + } + + typedef custom-enum { + type enumeration { + enum type1; + enum type2; + enum type3; + } + } + + grouping enum-grouping { + leaf attr-enum { + type custom-enum; + } + } + + grouping aug-grouping { + container cont1 { + leaf attr-str { + type string; + } + } + + container cont2 { + list contlist1 { + key "attr-str"; + + leaf attr-str { + type string; + } + + uses enum-grouping; + } + } + + leaf attr-str1 { + type string; + } + + leaf attr-str2 { + type string; + } + + leaf attr-str3 { + type string; + } + + leaf attr-str4 { + type string; + } + + list list1 { + key "attr-str"; + leaf attr-str { + type string; + } + + list list1-1 { + key "attr-int"; + leaf attr-int { + type int32; + } + + leaf attr-str { + type string; + } + + leaf flags { + type bit-flags; + } + } + + list list1-2 { + key "attr-int"; + leaf attr-int { + type int32; + } + + leaf attr-str { + type string; + } + } + } + } + + augment "/test:top/test:top-level-list" { + ext:augment-identifier tll-complex-augment; + uses aug-grouping; + } + + augment "/test:top/test:top-level-list/list1/list1-1" { + ext:augment-identifier list11-simple-augment; + + leaf attr-str2 { + type string; + } + + container cont { + leaf attr-int { + type int32; + } + } + } + + augment "/test:top/test:top-level-list/test:nested-list/" { + ext:augment-identifier nested-list-simple-augment; + + leaf type { + type string; + } + } + + rpc knock-knock { + input { + leaf knocker-id { + ext:context-reference routed:test-context; + type instance-identifier; + } + + leaf question { + type string; + } + } + + output { + leaf answer { + type string; + } + } + } +} diff --git a/opendaylight/md-sal/topology-lldp-discovery/pom.xml b/opendaylight/md-sal/topology-lldp-discovery/pom.xml index cc684a58b2..70cd4b8702 100644 --- a/opendaylight/md-sal/topology-lldp-discovery/pom.xml +++ b/opendaylight/md-sal/topology-lldp-discovery/pom.xml @@ -12,7 +12,6 @@ bundle 2.4.0 - 14.0.1 2.5 diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java index 1579d1927f..f39a21d16b 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java @@ -12,6 +12,7 @@ import static com.google.common.base.Preconditions.checkState; import java.util.Dictionary; import java.util.Hashtable; +import org.opendaylight.controller.netconf.api.util.NetconfConstants; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; import org.osgi.framework.BundleActivator; @@ -91,7 +92,7 @@ public class Activator implements BundleActivator { NetconfOperationServiceFactoryImpl factory = new NetconfOperationServiceFactoryImpl(yangStoreService); LOG.debug("Registering into OSGi"); Dictionary properties = new Hashtable<>(); - properties.put("name", "config-netconf-connector"); + properties.put(NetconfConstants.SERVICE_NAME, NetconfConstants.CONFIG_NETCONF_CONNECTOR); osgiRegistration = context.registerService(NetconfOperationServiceFactory.class, factory, properties); } } diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusherImpl.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusherImpl.java index cf9958e7f8..0aebc68bbe 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusherImpl.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusherImpl.java @@ -115,7 +115,7 @@ public class ConfigPusherImpl implements ConfigPusher { */ private synchronized EditAndCommitResponse pushConfigWithConflictingVersionRetries(ConfigSnapshotHolder configSnapshotHolder) throws NetconfDocumentedException { ConflictingVersionException lastException; - Stopwatch stopwatch = new Stopwatch(); + Stopwatch stopwatch = Stopwatch.createUnstarted(); do { String idForReporting = configSnapshotHolder.toString(); SortedSet expectedCapabilities = checkNotNull(configSnapshotHolder.getCapabilities(), @@ -137,7 +137,7 @@ public class ConfigPusherImpl implements ConfigPusher { } private NetconfOperationService getOperationServiceWithRetries(Set expectedCapabilities, String idForReporting) { - Stopwatch stopwatch = new Stopwatch().start(); + Stopwatch stopwatch = Stopwatch.createStarted(); NotEnoughCapabilitiesException lastException; do { try { @@ -230,7 +230,7 @@ public class ConfigPusherImpl implements ConfigPusher { throw new IllegalStateException("Cannot parse " + configSnapshotHolder); } LOG.trace("Pushing last configuration to netconf: {}", configSnapshotHolder); - Stopwatch stopwatch = new Stopwatch().start(); + Stopwatch stopwatch = Stopwatch.createStarted(); NetconfMessage editConfigMessage = createEditConfigMessage(xmlToBePersisted); Document editResponseMessage = sendRequestGetResponseCheckIsOK(editConfigMessage, operationService, diff --git a/opendaylight/netconf/mdsal-netconf-connector/pom.xml b/opendaylight/netconf/mdsal-netconf-connector/pom.xml new file mode 100644 index 0000000000..2808672ca2 --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/pom.xml @@ -0,0 +1,117 @@ + + + 4.0.0 + + + org.opendaylight.controller + netconf-subsystem + 0.3.0-SNAPSHOT + + mdsal-netconf-connector + bundle + ${project.artifactId} + + + + ${project.groupId} + netconf-api + + + ${project.groupId} + netconf-mapping-api + + + ${project.groupId} + netconf-util + + + com.google.guava + guava + + + org.opendaylight.yangtools + yang-data-impl + + + org.opendaylight.controller + sal-core-api + + + org.opendaylight.controller + commons.logback_settings + + + org.opendaylight.yangtools + mockito-configuration + + + org.slf4j + slf4j-api + + + org.opendaylight.controller + sal-core-api + + + org.opendaylight.controller + config-util + + + org.opendaylight.yangtools + yang-data-operations + 0.7.0-SNAPSHOT + + + + + + + + org.apache.felix + maven-bundle-plugin + + + * + + + + + + org.opendaylight.yangtools + yang-maven-plugin + + + config + + generate-sources + + + + + org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + ${jmxGeneratorPath} + + urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + ${salGeneratorPath} + + + true + + + + + + org.opendaylight.controller + yang-jmx-generator-plugin + ${config.version} + + + + + + + diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/mapper/NetconfMdsalMapperModule.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/mapper/NetconfMdsalMapperModule.java new file mode 100644 index 0000000000..ccf751285a --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/mapper/NetconfMdsalMapperModule.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 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.config.yang.netconf.mdsal.mapper; + +import org.opendaylight.controller.netconf.mdsal.connector.MdsalNetconfOperationServiceFactory; + +public class NetconfMdsalMapperModule extends org.opendaylight.controller.config.yang.netconf.mdsal.mapper.AbstractNetconfMdsalMapperModule { + public NetconfMdsalMapperModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public NetconfMdsalMapperModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.netconf.mdsal.mapper.NetconfMdsalMapperModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + // add custom validation form module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + return new MdsalNetconfOperationServiceFactory(getRootSchemaServiceDependency(), getDomBrokerDependency()); + } + +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/mapper/NetconfMdsalMapperModuleFactory.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/mapper/NetconfMdsalMapperModuleFactory.java new file mode 100644 index 0000000000..4eb0563ad4 --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/config/yang/netconf/mdsal/mapper/NetconfMdsalMapperModuleFactory.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 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 + */ + +/* +* Generated file +* +* Generated from: yang module name: netconf-mdsal-mapper yang module local name: netconf-mdsal-mapper +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Wed Jan 14 14:58:42 CET 2015 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.controller.config.yang.netconf.mdsal.mapper; +public class NetconfMdsalMapperModuleFactory extends org.opendaylight.controller.config.yang.netconf.mdsal.mapper.AbstractNetconfMdsalMapperModuleFactory { + +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/CurrentSchemaContext.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/CurrentSchemaContext.java new file mode 100644 index 0000000000..df671e8f4f --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/CurrentSchemaContext.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015 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.mdsal.connector; + +import com.google.common.base.Preconditions; +import java.util.concurrent.atomic.AtomicReference; +import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaContextListener; + +public class CurrentSchemaContext implements SchemaContextListener, AutoCloseable { + final AtomicReference currentContext = new AtomicReference(); + private final ListenerRegistration schemaContextListenerListenerRegistration; + + public SchemaContext getCurrentContext() { + Preconditions.checkState(currentContext.get() != null, "Current context not received"); + return currentContext.get(); + } + + public CurrentSchemaContext(final SchemaService schemaService) { + schemaContextListenerListenerRegistration = schemaService.registerSchemaContextListener(this); + } + + @Override + public void onGlobalContextUpdated(final SchemaContext schemaContext) { + currentContext.set(schemaContext); + } + + @Override + public void close() throws Exception { + schemaContextListenerListenerRegistration.close(); + currentContext.set(null); + } +} \ No newline at end of file diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationService.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationService.java new file mode 100644 index 0000000000..f54c5e9838 --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationService.java @@ -0,0 +1,158 @@ +/* + * 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.mdsal.connector; + +import com.google.common.base.Optional; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.netconf.mapping.api.Capability; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; +import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MdsalNetconfOperationService implements NetconfOperationService { + + private static final Logger LOG = LoggerFactory.getLogger(MdsalNetconfOperationService.class); + + private final CurrentSchemaContext schemaContext; + private final String netconfSessionIdForReporting; + private final OperationProvider operationProvider; + + public MdsalNetconfOperationService(final CurrentSchemaContext schemaContext, final String netconfSessionIdForReporting, + final DOMDataBroker dataBroker) { + this.schemaContext = schemaContext; + // TODO schema contexts are different in data broker and the one we receive here ... the one received here should be updated same way as broker is + this.netconfSessionIdForReporting = netconfSessionIdForReporting; + this.operationProvider = new OperationProvider(netconfSessionIdForReporting, schemaContext, dataBroker); + } + + @Override + public void close() { + + } + + // TODO does this get called dynamically ? + @Override + public Set getCapabilities() { + final Set capabilities = new HashSet<>(); + // [RFC6241] 8.3. Candidate Configuration Capability + capabilities.add(new BasicCapability("urn:ietf:params:netconf:capability:candidate:1.0")); + + final SchemaContext currentContext = schemaContext.getCurrentContext(); + final Set modules = currentContext.getModules(); + for (final Module module : modules) { + if(currentContext.getModuleSource(module).isPresent()) { + capabilities.add(new YangStoreCapability(module, currentContext.getModuleSource(module).get())); + } else { + LOG.warn("Missing source for module {}. This module will not be available from netconf server for session {}", + module, netconfSessionIdForReporting); + } + } + + return capabilities; + } + + @Override + public Set getNetconfOperations() { + return operationProvider.getOperations(); + } + + // TODO reuse from netconf impl + private static class BasicCapability implements Capability { + + private final String capability; + + private BasicCapability(final String capability) { + this.capability = capability; + } + + @Override + public String getCapabilityUri() { + return capability; + } + + @Override + public Optional getModuleNamespace() { + return Optional.absent(); + } + + @Override + public Optional getModuleName() { + return Optional.absent(); + } + + @Override + public Optional getRevision() { + return Optional.absent(); + } + + @Override + public Optional getCapabilitySchema() { + return Optional.absent(); + } + + @Override + public Collection getLocation() { + return Collections.emptyList(); + } + + @Override + public String toString() { + return capability; + } + } + + private static final class YangStoreCapability extends BasicCapability { + + private final String content; + private final String revision; + private final String moduleName; + private final String moduleNamespace; + + public YangStoreCapability(final Module module, final String moduleContent) { + super(toCapabilityURI(module)); + this.content = moduleContent; + this.moduleName = module.getName(); + this.moduleNamespace = module.getNamespace().toString(); + this.revision = SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision()); + } + + @Override + public Optional getCapabilitySchema() { + return Optional.of(content); + } + + private static String toCapabilityURI(final Module module) { + return String.valueOf(module.getNamespace()) + "?module=" + + module.getName() + "&revision=" + SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision()); + } + + @Override + public Optional getModuleName() { + return Optional.of(moduleName); + } + + @Override + public Optional getModuleNamespace() { + return Optional.of(moduleNamespace); + } + + @Override + public Optional getRevision() { + return Optional.of(revision); + } + } +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java new file mode 100644 index 0000000000..098f25bf4a --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/MdsalNetconfOperationServiceFactory.java @@ -0,0 +1,35 @@ +/* + * 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.mdsal.connector; + +import com.google.common.base.Preconditions; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; +import org.opendaylight.controller.sal.core.api.model.SchemaService; + +public class MdsalNetconfOperationServiceFactory implements NetconfOperationServiceFactory, AutoCloseable { + + private final DOMDataBroker dataBroker; + private final CurrentSchemaContext currentSchemaContext; + + public MdsalNetconfOperationServiceFactory(final SchemaService schemaService, final DOMDataBroker domDataBroker) { + this.currentSchemaContext = new CurrentSchemaContext(Preconditions.checkNotNull(schemaService)); + this.dataBroker = Preconditions.checkNotNull(domDataBroker); + } + + @Override + public MdsalNetconfOperationService createService(final String netconfSessionIdForReporting) { + return new MdsalNetconfOperationService(currentSchemaContext, netconfSessionIdForReporting, dataBroker); + } + + @Override + public void close() throws Exception { + currentSchemaContext.close(); + } +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/OperationProvider.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/OperationProvider.java new file mode 100644 index 0000000000..c881ae2e4e --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/OperationProvider.java @@ -0,0 +1,50 @@ +/* + * 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.mdsal.connector; + +import com.google.common.collect.Sets; +import java.util.Set; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; +import org.opendaylight.controller.netconf.mdsal.connector.ops.Commit; +import org.opendaylight.controller.netconf.mdsal.connector.ops.DiscardChanges; +import org.opendaylight.controller.netconf.mdsal.connector.ops.EditConfig; +import org.opendaylight.controller.netconf.mdsal.connector.ops.Lock; +import org.opendaylight.controller.netconf.mdsal.connector.ops.Unlock; +import org.opendaylight.controller.netconf.mdsal.connector.ops.get.Get; +import org.opendaylight.controller.netconf.mdsal.connector.ops.get.GetConfig; + +final class OperationProvider { + + private final String netconfSessionIdForReporting; + private final CurrentSchemaContext schemaContext; + private final DOMDataBroker dataBroker; + private final TransactionProvider transactionProvider; + + public OperationProvider(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext, final DOMDataBroker dataBroker) { + this.netconfSessionIdForReporting = netconfSessionIdForReporting; + this.schemaContext = schemaContext; + this.dataBroker = dataBroker; + this.transactionProvider = new TransactionProvider(dataBroker, netconfSessionIdForReporting); + + } + + Set getOperations() { + return Sets.newHashSet( + new Commit(netconfSessionIdForReporting, transactionProvider), + new DiscardChanges(netconfSessionIdForReporting, transactionProvider), + new EditConfig(netconfSessionIdForReporting, schemaContext, transactionProvider), + new Get(netconfSessionIdForReporting, schemaContext, transactionProvider), + new GetConfig(netconfSessionIdForReporting, schemaContext, transactionProvider), + new Lock(netconfSessionIdForReporting), + new Unlock(netconfSessionIdForReporting) + ); + } + +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/TransactionProvider.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/TransactionProvider.java new file mode 100644 index 0000000000..f1b214b83e --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/TransactionProvider.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015 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.mdsal.connector; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.util.concurrent.CheckedFuture; +import java.util.ArrayList; +import java.util.List; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +//TODO make a global TransactionProvider for all Netconf sessions instead of each session having one. +public class TransactionProvider implements AutoCloseable{ + + private static final Logger LOG = LoggerFactory.getLogger(TransactionProvider.class); + + private final DOMDataBroker dataBroker; + + private DOMDataReadWriteTransaction candidateTransaction = null; + private DOMDataReadWriteTransaction runningTransaction = null; + private final List allOpenReadWriteTransactions = new ArrayList<>(); + + private final String netconfSessionIdForReporting; + + private static final String NO_TRANSACTION_FOUND_FOR_SESSION = "No candidateTransaction found for session "; + + + public TransactionProvider(DOMDataBroker dataBroker, String netconfSessionIdForReporting) { + this.dataBroker = dataBroker; + this.netconfSessionIdForReporting = netconfSessionIdForReporting; + } + + @Override + public synchronized void close() throws Exception { + for (DOMDataReadWriteTransaction rwt : allOpenReadWriteTransactions) { + rwt.cancel(); + } + + allOpenReadWriteTransactions.clear(); + } + + public synchronized Optional getCandidateTransaction() { + if (candidateTransaction == null) { + return Optional.absent(); + } + + return Optional.of(candidateTransaction); + } + + public synchronized DOMDataReadWriteTransaction getOrCreateTransaction() { + if (getCandidateTransaction().isPresent()) { + return getCandidateTransaction().get(); + } + + candidateTransaction = dataBroker.newReadWriteTransaction(); + allOpenReadWriteTransactions.add(candidateTransaction); + return candidateTransaction; + } + + public synchronized boolean commitTransaction() throws NetconfDocumentedException { + if (!getCandidateTransaction().isPresent()) { + throw new NetconfDocumentedException(NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting, + ErrorType.application, ErrorTag.operation_failed, ErrorSeverity.error); + } + + CheckedFuture future = candidateTransaction.submit(); + try { + future.checkedGet(); + } catch (TransactionCommitFailedException e) { + LOG.debug("Transaction {} failed on", candidateTransaction, e); + throw new NetconfDocumentedException("Transaction commit failed on " + e.getMessage() + " " + netconfSessionIdForReporting, + ErrorType.application, ErrorTag.operation_failed, ErrorSeverity.error); + } + allOpenReadWriteTransactions.remove(candidateTransaction); + candidateTransaction = null; + + return true; + } + + public synchronized void abortTransaction() { + LOG.debug("Aborting current candidateTransaction"); + Optional otx = getCandidateTransaction(); + Preconditions.checkState(otx.isPresent(), NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting); + candidateTransaction.cancel(); + allOpenReadWriteTransactions.remove(candidateTransaction); + candidateTransaction = null; + } + + public synchronized DOMDataReadWriteTransaction createRunningTransaction() { + runningTransaction = dataBroker.newReadWriteTransaction(); + allOpenReadWriteTransactions.add(runningTransaction); + return runningTransaction; + } + + public synchronized boolean commitRunningTransaction(DOMDataReadWriteTransaction tx) throws NetconfDocumentedException { + allOpenReadWriteTransactions.remove(tx); + + CheckedFuture future = tx.submit(); + try { + future.checkedGet(); + } catch (TransactionCommitFailedException e) { + LOG.debug("Transaction {} failed on", tx, e); + throw new NetconfDocumentedException("Transaction commit failed on " + e.getMessage() + " " + netconfSessionIdForReporting, + ErrorType.application, ErrorTag.operation_failed, ErrorSeverity.error); + } + + return true; + } + + public synchronized void abortRunningTransaction(DOMDataReadWriteTransaction tx) { + LOG.debug("Aborting current running Transaction"); + Preconditions.checkState(runningTransaction != null, NO_TRANSACTION_FOUND_FOR_SESSION + netconfSessionIdForReporting); + tx.cancel(); + allOpenReadWriteTransactions.remove(tx); + } + +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Commit.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Commit.java new file mode 100644 index 0000000000..15396cfbf8 --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Commit.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 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.mdsal.connector.ops; + +import com.google.common.base.Optional; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider; +import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class Commit extends AbstractLastNetconfOperation{ + + private static final Logger LOG = LoggerFactory.getLogger(Commit.class); + + private static final String OPERATION_NAME = "commit"; + private final TransactionProvider transactionProvider; + + public Commit(final String netconfSessionIdForReporting, final TransactionProvider transactionProvider) { + super(netconfSessionIdForReporting); + this.transactionProvider = transactionProvider; + + } + + @Override + protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException { + + boolean commitStatus = transactionProvider.commitTransaction(); + LOG.trace("Transaction commited succesfuly", commitStatus); + + return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.absent()); + } + + @Override + protected String getOperationName() { + return OPERATION_NAME; + } + +} diff --git a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/InitiateInstallSnapshot.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Datastore.java similarity index 51% rename from opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/InitiateInstallSnapshot.java rename to opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Datastore.java index 7844914873..0f86c5a1d1 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/main/java/org/opendaylight/controller/cluster/raft/base/messages/InitiateInstallSnapshot.java +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Datastore.java @@ -1,16 +1,13 @@ /* - * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2015 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.cluster.raft.base.messages; +package org.opendaylight.controller.netconf.mdsal.connector.ops; -/** - * Internal message by Leader to initiate an install snapshot - */ -public class InitiateInstallSnapshot { +public enum Datastore { + candidate, running } - diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/DiscardChanges.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/DiscardChanges.java new file mode 100644 index 0000000000..36f6d8e3cf --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/DiscardChanges.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015 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.mdsal.connector.ops; + +import com.google.common.base.Optional; +import java.util.HashMap; +import java.util.Map; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType; +import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider; +import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class DiscardChanges extends AbstractLastNetconfOperation{ + + private static final Logger LOG = LoggerFactory.getLogger(DiscardChanges.class); + + private static final String OPERATION_NAME = "discard-changes"; + + private final TransactionProvider transactionProvider; + + public DiscardChanges(final String netconfSessionIdForReporting, final TransactionProvider transactionProvider) { + super(netconfSessionIdForReporting); + this.transactionProvider = transactionProvider; + } + + @Override + protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException { + operationElement.getOnlyChildElement(OPERATION_NAME); + + try { + transactionProvider.abortTransaction(); + } catch (IllegalStateException e) { + LOG.warn("Abort failed ", e); + final Map errorInfo = new HashMap<>(); + errorInfo + .put(ErrorTag.operation_failed.name(), + "Operation failed. Use 'get-config' or 'edit-config' before triggering 'discard-changes' operation"); + throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.application, ErrorTag.operation_failed, + ErrorSeverity.error, errorInfo); + } + return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.absent()); + } + + @Override + protected String getOperationName() { + return OPERATION_NAME; + } +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/EditConfig.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/EditConfig.java new file mode 100644 index 0000000000..09be4163df --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/EditConfig.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2015 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.mdsal.connector.ops; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.CheckedFuture; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType; +import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext; +import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider; +import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory; +import org.opendaylight.yangtools.yang.data.operations.DataModificationException; +import org.opendaylight.yangtools.yang.data.operations.DataModificationException.DataExistsException; +import org.opendaylight.yangtools.yang.data.operations.DataModificationException.DataMissingException; +import org.opendaylight.yangtools.yang.data.operations.DataOperations; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +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.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class EditConfig extends AbstractLastNetconfOperation { + + private static final Logger LOG = LoggerFactory.getLogger(EditConfig.class); + + private static final String OPERATION_NAME = "edit-config"; + private static final String CONFIG_KEY = "config"; + + private final CurrentSchemaContext schemaContext; + private final TransactionProvider transactionProvider; + + public EditConfig(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext, final TransactionProvider transactionProvider) { + super(netconfSessionIdForReporting); + this.schemaContext = schemaContext; + this.transactionProvider = transactionProvider; + } + + @Override + protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException { + final XmlElement configElement = getConfigElement(operationElement); + + for (XmlElement element : configElement.getChildElements()) { + final String ns = element.getNamespace(); + final DataSchemaNode schemaNode = getSchemaNodeFromNamespace(ns, element).get(); + YangInstanceIdentifier ident = YangInstanceIdentifier.of(schemaNode.getQName()); + + final NormalizedNode storedNode = readStoredNode(LogicalDatastoreType.CONFIGURATION, ident); + try { + final Optional> newNode = modifyNode(schemaNode, element, storedNode); + final DOMDataReadWriteTransaction rwTx = transactionProvider.getOrCreateTransaction(); + if (newNode.isPresent()) { + rwTx.put(LogicalDatastoreType.CONFIGURATION, ident, newNode.get()); + } else { + rwTx.delete(LogicalDatastoreType.CONFIGURATION, ident); + } + } catch (final DataModificationException e) { + if (e instanceof DataExistsException) { + throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.data_exists, ErrorSeverity.error); + } else if (e instanceof DataMissingException) { + throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.data_missing, ErrorSeverity.error); + } else { + //should never happen, since in edit-config only the 2 previous cases can happen + throw new NetconfDocumentedException(e.getMessage(), e, ErrorType.protocol, ErrorTag.operation_failed, ErrorSeverity.error); + } + } + } + + return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.absent()); + } + + private NormalizedNode readStoredNode(final LogicalDatastoreType logicalDatastoreType, final YangInstanceIdentifier path) throws NetconfDocumentedException{ + final DOMDataReadWriteTransaction rwTx = transactionProvider.getOrCreateTransaction(); + final CheckedFuture>, ReadFailedException> readFuture = rwTx.read(logicalDatastoreType, path); + try { + if (readFuture.checkedGet().isPresent()) { + final NormalizedNode node = readFuture.checkedGet().get(); + return node; + } else { + LOG.warn("Unable to read node : {} from {} datastore", path, logicalDatastoreType); + } + } catch (final ReadFailedException e) { + //only log this since DataOperations.modify will handle throwing an exception or writing the node. + LOG.warn("Unable to read stored data: {}", path, e); + } + + //we can return null here since DataOperations.modify handles null as input + return null; + } + + private Optional getSchemaNodeFromNamespace(final String namespace, final XmlElement element){ + Optional dataSchemaNode = Optional.absent(); + try { + //returns module with newest revision since findModuleByNamespace returns a set of modules and we only need the newest one + final Module module = schemaContext.getCurrentContext().findModuleByNamespaceAndRevision(new URI(namespace), null); + dataSchemaNode = Optional.of(module.getDataChildByName(element.getName())); + } catch (URISyntaxException e) { + LOG.debug("Unable to create URI for namespace : {}", namespace); + } + + return dataSchemaNode; + } + + private Optional> modifyNode(final DataSchemaNode schemaNode, final XmlElement element, final NormalizedNode storedNode) throws DataModificationException{ + if (schemaNode instanceof ContainerSchemaNode) { + final ContainerNode modifiedNode = + DomToNormalizedNodeParserFactory + .getInstance(DomUtils.defaultValueCodecProvider()) + .getContainerNodeParser() + .parse(Collections.singletonList(element.getDomElement()), (ContainerSchemaNode) schemaNode); + + final Optional oNode = DataOperations.modify((ContainerSchemaNode) schemaNode, (ContainerNode) storedNode, modifiedNode); + if (!oNode.isPresent()) { + return Optional.absent(); + } + + final NormalizedNode node = oNode.get(); + return Optional.>of(node); + } else if (schemaNode instanceof ListSchemaNode) { + final MapNode modifiedNode = + DomToNormalizedNodeParserFactory + .getInstance(DomUtils.defaultValueCodecProvider()) + .getMapNodeParser() + .parse(Collections.singletonList(element.getDomElement()), (ListSchemaNode) schemaNode); + + final Optional oNode = DataOperations.modify((ListSchemaNode) schemaNode, (MapNode) storedNode, modifiedNode); + if (!oNode.isPresent()) { + return Optional.absent(); + } + + final NormalizedNode node = oNode.get(); + return Optional.>of(node); + } else { + //this should never happen since edit-config on any other node type should not be possible nor makes sense + LOG.debug("DataNode from module is not ContainerSchemaNode nor ListSchemaNode, aborting.."); + return Optional.absent(); + } + + } + + private XmlElement getConfigElement(final XmlElement operationElement) throws NetconfDocumentedException{ + final Optional configChildNode = operationElement.getOnlyChildElementOptionally(CONFIG_KEY); + if (!configChildNode.isPresent()) { + throw new NetconfDocumentedException("Can't get child element with name: " + CONFIG_KEY, + ErrorType.application, + ErrorTag.unknown_element, + ErrorSeverity.error); + } + + return configChildNode.get(); + } + + @Override + protected String getOperationName() { + return OPERATION_NAME; + } +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Lock.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Lock.java new file mode 100644 index 0000000000..db912c5fc0 --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Lock.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 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.mdsal.connector.ops; + +import com.google.common.base.Optional; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; +import org.opendaylight.controller.netconf.util.exception.UnexpectedNamespaceException; +import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class Lock extends AbstractLastNetconfOperation{ + + private static final Logger LOG = LoggerFactory.getLogger(Lock.class); + + private static final String OPERATION_NAME = "lock"; + private static final String TARGET_KEY = "target"; + + public Lock(final String netconfSessionIdForReporting) { + super(netconfSessionIdForReporting); + } + + @Override + protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException { + final Datastore targetDatastore = extractTargetParameter(operationElement); + if (targetDatastore == Datastore.candidate) { + LOG.debug("Locking candidate datastore on session: {}", getNetconfSessionIdForReporting()); + return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.absent()); + } + + throw new NetconfDocumentedException("Unable to lock " + targetDatastore + " datastore", NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_not_supported, NetconfDocumentedException.ErrorSeverity.error); + } + + static Datastore extractTargetParameter(final XmlElement operationElement) throws NetconfDocumentedException { + final XmlElement targetChildNode; + try { + final XmlElement targetElement = operationElement.getOnlyChildElementWithSameNamespace(TARGET_KEY); + targetChildNode = targetElement.getOnlyChildElementWithSameNamespace(); + } catch (final MissingNameSpaceException | UnexpectedNamespaceException e) { + LOG.trace("Can't get only child element with same namespace", e); + throw NetconfDocumentedException.wrap(e); + } + + return Datastore.valueOf(targetChildNode.getName()); + } + + @Override + protected String getOperationName() { + return OPERATION_NAME; + } +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Unlock.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Unlock.java new file mode 100644 index 0000000000..2dd26633dd --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/Unlock.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 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.mdsal.connector.ops; + +import com.google.common.base.Optional; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class Unlock extends AbstractLastNetconfOperation{ + + private static final Logger LOG = LoggerFactory.getLogger(Unlock.class); + + private static final String OPERATION_NAME = "unlock"; + private static final String TARGET_KEY = "target"; + + public Unlock(final String netconfSessionIdForReporting) { + super(netconfSessionIdForReporting); + } + + @Override + protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) throws NetconfDocumentedException { + final Datastore targetDatastore = Lock.extractTargetParameter(operationElement); + if (targetDatastore == Datastore.candidate) { + LOG.debug("Unlocking candidate datastore on session: {}", getNetconfSessionIdForReporting()); + return XmlUtil.createElement(document, XmlNetconfConstants.OK, Optional.absent()); + } + + throw new NetconfDocumentedException("Unable to unlock " + targetDatastore + " datastore", NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.operation_not_supported, NetconfDocumentedException.ErrorSeverity.error); + } + + @Override + protected String getOperationName() { + return OPERATION_NAME; + } + +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java new file mode 100644 index 0000000000..e0c004461c --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/AbstractGet.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015 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.mdsal.connector.ops.get; + +import com.google.common.base.Function; +import com.google.common.base.Throwables; +import com.google.common.collect.Iterables; +import java.io.IOException; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.dom.DOMResult; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext; +import org.opendaylight.controller.netconf.mdsal.connector.ops.Datastore; +import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; +import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XMLStreamNormalizedNodeStreamWriter; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +public abstract class AbstractGet extends AbstractLastNetconfOperation { + + protected static final YangInstanceIdentifier ROOT = YangInstanceIdentifier.builder().build(); + + protected final CurrentSchemaContext schemaContext; + + + public AbstractGet(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext) { + super(netconfSessionIdForReporting); + this.schemaContext = schemaContext; + } + + private static final XMLOutputFactory XML_OUTPUT_FACTORY; + + static { + XML_OUTPUT_FACTORY = XMLOutputFactory.newFactory(); + XML_OUTPUT_FACTORY.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true); + } + + protected Node transformNormalizedNode(final Document document, final NormalizedNode data, final YangInstanceIdentifier dataRoot) { +// boolean isDataRoot = true; + + final DOMResult result = new DOMResult(document.createElement(XmlNetconfConstants.DATA_KEY)); + + final XMLStreamWriter xmlWriter = getXmlStreamWriter(result); + + final NormalizedNodeStreamWriter nnStreamWriter = XMLStreamNormalizedNodeStreamWriter.create(xmlWriter, + schemaContext.getCurrentContext(), getSchemaPath(dataRoot)); + + final NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(nnStreamWriter); + +// if (isDataRoot) { + writeRootElement(xmlWriter, nnWriter, (ContainerNode) data); +// } else { +// if (data instanceof MapEntryNode) { +// // Restconf allows returning one list item. We need to wrap it +// // in map node in order to serialize it properly +// data = ImmutableNodes.mapNodeBuilder(data.getNodeType()).addChild((MapEntryNode) data).build(); +// } +// nnWriter.write(data); +// nnWriter.flush(); +// } + return result.getNode(); + } + + private XMLStreamWriter getXmlStreamWriter(final DOMResult result) { + try { + return XML_OUTPUT_FACTORY.createXMLStreamWriter(result); + } catch (final XMLStreamException e) { + throw new RuntimeException(e); + } + } + + private static final Function PATH_ARG_TO_QNAME = new Function() { + @Override + public QName apply(final YangInstanceIdentifier.PathArgument input) { + return input.getNodeType(); + } + }; + + private SchemaPath getSchemaPath(final YangInstanceIdentifier dataRoot) { + return SchemaPath.create(Iterables.transform(dataRoot.getPathArguments(), PATH_ARG_TO_QNAME), dataRoot.equals(ROOT)); + } + + // TODO this code is located in Restconf already + private void writeRootElement(final XMLStreamWriter xmlWriter, final NormalizedNodeWriter nnWriter, final ContainerNode data) { + try { + final QName name = SchemaContext.NAME; + for (final DataContainerChild child : data.getValue()) { + nnWriter.write(child); + } + nnWriter.flush(); + xmlWriter.flush(); + } catch (XMLStreamException | IOException e) { + Throwables.propagate(e); + } + } + + protected static final class GetConfigExecution { + private final Datastore datastore; + + public GetConfigExecution(final Datastore datastore) { + this.datastore = datastore; + } + + public Datastore getDatastore() { + return datastore; + } + + static GetConfigExecution fromXml(final XmlElement xml, final String operationName) throws NetconfDocumentedException { + try { + validateInputRpc(xml, operationName); + } catch (final NetconfDocumentedException e) { + throw new NetconfDocumentedException("Incorrect RPC: " + e.getMessage(), e.getErrorType(), e.getErrorTag(), e.getErrorSeverity(), e.getErrorInfo()); + } + + final Datastore sourceDatastore; + try { + sourceDatastore = parseSource(xml); + } catch (final NetconfDocumentedException e) { + throw new NetconfDocumentedException("Get-config source attribute error: " + e.getMessage(), e.getErrorType(), e.getErrorTag(), e.getErrorSeverity(), e.getErrorInfo()); + } + + // Add filter + + return new GetConfigExecution(sourceDatastore); + } + + private static Datastore parseSource(final XmlElement xml) throws NetconfDocumentedException { + final Datastore sourceDatastore; + final XmlElement sourceElement = xml.getOnlyChildElement(XmlNetconfConstants.SOURCE_KEY, + XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); + + final String sourceParsed = sourceElement.getOnlyChildElement().getName(); + sourceDatastore = Datastore.valueOf(sourceParsed); + return sourceDatastore; + } + + private static void validateInputRpc(final XmlElement xml, String operationName) throws NetconfDocumentedException{ + xml.checkName(operationName); + xml.checkNamespace(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); + } + } + +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/Get.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/Get.java new file mode 100644 index 0000000000..a2b2fbb0db --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/Get.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015 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.mdsal.connector.ops.get; + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType; +import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext; +import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider; +import org.opendaylight.controller.netconf.mdsal.connector.ops.Datastore; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class Get extends AbstractGet { + + private static final Logger LOG = LoggerFactory.getLogger(Get.class); + + private static final String OPERATION_NAME = "get"; + + private final TransactionProvider transactionProvider; + + public Get(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext, final TransactionProvider transactionProvider) { + super(netconfSessionIdForReporting, schemaContext); + this.transactionProvider = transactionProvider; + } + + @Override + protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement) throws NetconfDocumentedException { + GetConfigExecution getConfigExecution = null; + try { + getConfigExecution = GetConfigExecution.fromXml(operationElement, OPERATION_NAME); + + } catch (final NetconfDocumentedException e) { + LOG.warn("Get request processing failed on session: {}", getNetconfSessionIdForReporting(), e); + throw e; + } + + final YangInstanceIdentifier dataRoot = ROOT; + DOMDataReadWriteTransaction rwTx = getTransaction(getConfigExecution.getDatastore()); + try { + final Optional> normalizedNodeOptional = rwTx.read(LogicalDatastoreType.OPERATIONAL, dataRoot).checkedGet(); + if (getConfigExecution.getDatastore() == Datastore.running) { + transactionProvider.abortRunningTransaction(rwTx); + rwTx = null; + } + return (Element) transformNormalizedNode(document, normalizedNodeOptional.get(), dataRoot); + } catch (ReadFailedException e) { + LOG.warn("Unable to read data: {}", dataRoot, e); + throw new IllegalStateException("Unable to read data " + dataRoot, e); + } + } + + private DOMDataReadWriteTransaction getTransaction(Datastore datastore) throws NetconfDocumentedException{ + if (datastore == Datastore.candidate) { + return transactionProvider.getOrCreateTransaction(); + } else if (datastore == Datastore.running) { + return transactionProvider.createRunningTransaction(); + } + throw new NetconfDocumentedException("Incorrect Datastore: ", ErrorType.protocol, ErrorTag.bad_element, ErrorSeverity.error); + } + + @Override + protected String getOperationName() { + return OPERATION_NAME; + } +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/GetConfig.java b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/GetConfig.java new file mode 100644 index 0000000000..b56bcc795c --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/java/org/opendaylight/controller/netconf/mdsal/connector/ops/get/GetConfig.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015 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.mdsal.connector.ops.get; + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorTag; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorType; +import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext; +import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider; +import org.opendaylight.controller.netconf.mdsal.connector.ops.Datastore; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class GetConfig extends AbstractGet { + + private static final Logger LOG = LoggerFactory.getLogger(GetConfig.class); + + private static final String OPERATION_NAME = "get-config"; + + private final TransactionProvider transactionProvider; + + public GetConfig(final String netconfSessionIdForReporting, final CurrentSchemaContext schemaContext, final TransactionProvider transactionProvider) { + super(netconfSessionIdForReporting, schemaContext); + this.transactionProvider = transactionProvider; + } + + @Override + protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement) throws NetconfDocumentedException { + GetConfigExecution getConfigExecution = null; + try { + getConfigExecution = GetConfigExecution.fromXml(operationElement, OPERATION_NAME); + + } catch (final NetconfDocumentedException e) { + LOG.warn("Get request processing failed on session: {}", getNetconfSessionIdForReporting(), e); + throw e; + } + + final YangInstanceIdentifier dataRoot = ROOT; + DOMDataReadWriteTransaction rwTx = getTransaction(getConfigExecution.getDatastore()); + try { + final Optional> normalizedNodeOptional = rwTx.read(LogicalDatastoreType.CONFIGURATION, dataRoot).checkedGet(); + if (getConfigExecution.getDatastore() == Datastore.running) { + transactionProvider.abortRunningTransaction(rwTx); + rwTx = null; + } + return (Element) transformNormalizedNode(document, normalizedNodeOptional.get(), dataRoot); + } catch (ReadFailedException e) { + LOG.warn("Unable to read data: {}", dataRoot, e); + throw new IllegalStateException("Unable to read data " + dataRoot, e); + } + } + + private DOMDataReadWriteTransaction getTransaction(Datastore datastore) throws NetconfDocumentedException{ + if (datastore == Datastore.candidate) { + return transactionProvider.getOrCreateTransaction(); + } else if (datastore == Datastore.running) { + return transactionProvider.createRunningTransaction(); + } + throw new NetconfDocumentedException("Incorrect Datastore: ", ErrorType.protocol, ErrorTag.bad_element, ErrorSeverity.error); + } + + @Override + protected String getOperationName() { + return OPERATION_NAME; + } + +} diff --git a/opendaylight/netconf/mdsal-netconf-connector/src/main/yang/netconf-mdsal-mapper.yang b/opendaylight/netconf/mdsal-netconf-connector/src/main/yang/netconf-mdsal-mapper.yang new file mode 100644 index 0000000000..b1d04106d7 --- /dev/null +++ b/opendaylight/netconf/mdsal-netconf-connector/src/main/yang/netconf-mdsal-mapper.yang @@ -0,0 +1,50 @@ +module netconf-mdsal-mapper { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:netconf:mdsal:mapper"; + prefix "nmm"; + + import netconf-northbound-mapper { prefix nnm; revision-date 2015-01-14; } + import opendaylight-md-sal-dom { prefix md-sal-dom; revision-date 2013-10-28; } + import config { prefix config; revision-date 2013-04-05; } + + organization "Cisco Systems, Inc."; + + description + "This module contains the base YANG definitions for + an MD-SAL mapper implementation"; + + revision "2015-01-14" { + description + "Initial revision."; + } + + identity netconf-mdsal-mapper { + base config:module-type; + config:provided-service nnm:netconf-northbound-mapper; + } + + augment "/config:modules/config:module/config:configuration" { + case netconf-mdsal-mapper { + when "/config:modules/config:module/config:type = 'netconf-mdsal-mapper'"; + + container root-schema-service { + uses config:service-ref { + refine type { + mandatory false; + config:required-identity md-sal-dom:schema-service; + } + } + } + + container dom-broker { + uses config:service-ref { + refine type { + mandatory false; + config:required-identity md-sal-dom:dom-async-data-broker; + } + } + } + } + } + +} diff --git a/opendaylight/netconf/netconf-api/pom.xml b/opendaylight/netconf/netconf-api/pom.xml index 18bbce4e30..965747c2ea 100644 --- a/opendaylight/netconf/netconf-api/pom.xml +++ b/opendaylight/netconf/netconf-api/pom.xml @@ -43,15 +43,42 @@ org.apache.felix maven-bundle-plugin - - - org.opendaylight.controller.netconf.api, - org.opendaylight.controller.netconf.api.jmx, - org.opendaylight.controller.netconf.api.xml, - org.opendaylight.controller.netconf.api.monitoring, - - + + org.opendaylight.yangtools + yang-maven-plugin + + + config + + generate-sources + + + + + org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + ${jmxGeneratorPath} + + urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + ${salGeneratorPath} + + + true + + + + + + org.opendaylight.controller + yang-jmx-generator-plugin + ${config.version} + + + diff --git a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfServerDispatcher.java b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfServerDispatcher.java new file mode 100644 index 0000000000..6bf21c1d5d --- /dev/null +++ b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfServerDispatcher.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015 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.api; + +import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import java.net.InetSocketAddress; + +public interface NetconfServerDispatcher { + + ChannelFuture createServer(InetSocketAddress address); + + ChannelFuture createLocalServer(LocalAddress address); +} diff --git a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/util/NetconfConstants.java b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/util/NetconfConstants.java new file mode 100644 index 0000000000..b9c4dcaf4a --- /dev/null +++ b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/util/NetconfConstants.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2015 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.api.util; + +public final class NetconfConstants { + /* + * TODO define marker interface in mapping-api that the serviceFactories in cofing subsystem + * will implement so we can check for services with instanceof instead of constants + */ + public static final String SERVICE_NAME = "name"; + public static final String CONFIG_NETCONF_CONNECTOR = "config-netconf-connector"; + public static final String NETCONF_MONITORING = "ietf-netconf-monitoring"; +} diff --git a/opendaylight/netconf/netconf-api/src/main/yang/netconf-northbound.yang b/opendaylight/netconf/netconf-api/src/main/yang/netconf-northbound.yang new file mode 100644 index 0000000000..f775da91c0 --- /dev/null +++ b/opendaylight/netconf/netconf-api/src/main/yang/netconf-northbound.yang @@ -0,0 +1,22 @@ +module netconf-northbound { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound"; + prefix "nn"; + + import config { prefix config; revision-date 2013-04-05; } + + description + "This module contains the base YANG definitions for + netconf northbound server API"; + + revision "2015-01-14" { + description + "Initial revision."; + } + + identity netconf-server-dispatcher { + base "config:service-type"; + config:java-class "org.opendaylight.controller.netconf.api.NetconfServerDispatcher"; + } + +} \ No newline at end of file diff --git a/opendaylight/netconf/netconf-artifacts/pom.xml b/opendaylight/netconf/netconf-artifacts/pom.xml index 3487aa7be3..1248933915 100644 --- a/opendaylight/netconf/netconf-artifacts/pom.xml +++ b/opendaylight/netconf/netconf-artifacts/pom.xml @@ -62,6 +62,16 @@ netconf-connector-config ${project.version} + + ${project.groupId} + netconf-mdsal-config + ${project.version} + + + ${project.groupId} + mdsal-netconf-connector + ${project.version} + ${project.groupId} netconf-impl diff --git a/opendaylight/netconf/netconf-config/src/main/resources/initial/01-netconf.xml b/opendaylight/netconf/netconf-config/src/main/resources/initial/01-netconf.xml index f81a332ab6..06a5e65149 100644 --- a/opendaylight/netconf/netconf-config/src/main/resources/initial/01-netconf.xml +++ b/opendaylight/netconf/netconf-config/src/main/resources/initial/01-netconf.xml @@ -49,6 +49,17 @@ global-netconf-processing-executor-threadfactory + + + prefix:threadpool-scheduled + global-netconf-ssh-scheduled-executor + 8 + + + prefix:threadfactory + global-netconf-processing-executor-threadfactory + + @@ -72,6 +83,10 @@ global-netconf-processing-executor /modules/module[type='threadpool-flexible'][name='global-netconf-processing-executor'] + + global-netconf-ssh-scheduled-executor + /modules/module[type='threadpool-scheduled'][name='global-netconf-ssh-scheduled-executor'] + @@ -81,5 +96,6 @@ urn:opendaylight:params:xml:ns:yang:controller:config:netconf:client:dispatcher?module=odl-netconfig-client-cfg&revision=2014-04-08 urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl?module=threadpool-impl&revision=2013-04-05 urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:flexible?module=threadpool-impl-flexible&revision=2013-12-01 + urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:scheduled?module=threadpool-impl-scheduled&revision=2013-12-01 diff --git a/opendaylight/netconf/netconf-connector-config/src/main/resources/initial/99-netconf-connector.xml b/opendaylight/netconf/netconf-connector-config/src/main/resources/initial/99-netconf-connector.xml index 2bd919df94..28c61b9946 100644 --- a/opendaylight/netconf/netconf-connector-config/src/main/resources/initial/99-netconf-connector.xml +++ b/opendaylight/netconf/netconf-connector-config/src/main/resources/initial/99-netconf-connector.xml @@ -42,7 +42,7 @@ global-netconf-processing-executor - + diff --git a/opendaylight/netconf/netconf-impl/pom.xml b/opendaylight/netconf/netconf-impl/pom.xml index 310073fc72..6f19731f01 100644 --- a/opendaylight/netconf/netconf-impl/pom.xml +++ b/opendaylight/netconf/netconf-impl/pom.xml @@ -110,6 +110,7 @@ org.opendaylight.controller.netconf.impl.osgi.NetconfImplActivator + org.opendaylight.controller.netconf.impl.* @@ -125,6 +126,41 @@ + + org.opendaylight.yangtools + yang-maven-plugin + + + config + + generate-sources + + + + + org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + ${jmxGeneratorPath} + + urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + ${salGeneratorPath} + + + true + + + + + + org.opendaylight.controller + yang-jmx-generator-plugin + ${config.version} + + + diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModule.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModule.java new file mode 100644 index 0000000000..e64620d4ad --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModule.java @@ -0,0 +1,60 @@ +package org.opendaylight.controller.config.yang.config.netconf.northbound.impl; + +import org.opendaylight.controller.config.api.JmxAttributeValidationException; +import org.opendaylight.controller.netconf.impl.CommitNotifier; +import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl; +import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; +import org.opendaylight.controller.netconf.impl.SessionIdProvider; +import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; +import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; +import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; + +public class NetconfServerDispatcherModule extends org.opendaylight.controller.config.yang.config.netconf.northbound.impl.AbstractNetconfServerDispatcherModule { + public NetconfServerDispatcherModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public NetconfServerDispatcherModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.netconf.northbound.impl.NetconfServerDispatcherModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + JmxAttributeValidationException.checkCondition(getConnectionTimeoutMillis() > 0, "Invalid connection timeout", connectionTimeoutMillisJmxAttribute); + } + + @Override + public java.lang.AutoCloseable createInstance() { + + final NetconfOperationServiceFactoryListenerImpl aggregatedOpProvider = getAggregatedOpProvider(); + final SessionMonitoringService monitoringService = startMonitoringService(aggregatedOpProvider); + final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory( + getTimerDependency(), aggregatedOpProvider, new SessionIdProvider(), getConnectionTimeoutMillis(), CommitNotifier.NoopCommitNotifier.getInstance(), monitoringService); + final NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer( + serverNegotiatorFactory); + + return new NetconfServerDispatcherImpl(serverChannelInitializer, getBossThreadGroupDependency(), getWorkerThreadGroupDependency()) { + + @Override + public void close() { + // NOOP, close should not be present here, the deprecated method closes injected evet loop groups + } + }; + + } + + private NetconfMonitoringServiceImpl startMonitoringService(final NetconfOperationServiceFactoryListenerImpl netconfOperationProvider) { + return new NetconfMonitoringServiceImpl(netconfOperationProvider); + } + + private NetconfOperationServiceFactoryListenerImpl getAggregatedOpProvider() { + final NetconfOperationServiceFactoryListenerImpl netconfOperationProvider = new NetconfOperationServiceFactoryListenerImpl(); + for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getMappersDependency()) { + netconfOperationProvider.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory); + } + return netconfOperationProvider; + } + + +} diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModuleFactory.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModuleFactory.java new file mode 100644 index 0000000000..de44caddac --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/config/yang/config/netconf/northbound/impl/NetconfServerDispatcherModuleFactory.java @@ -0,0 +1,13 @@ +/* +* Generated file +* +* Generated from: yang module name: netconf-northbound-impl yang module local name: netconf-server-dispatcher-impl +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Thu Feb 12 11:32:29 CET 2015 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.controller.config.yang.config.netconf.northbound.impl; +public class NetconfServerDispatcherModuleFactory extends org.opendaylight.controller.config.yang.config.netconf.northbound.impl.AbstractNetconfServerDispatcherModuleFactory { + +} diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CommitNotifier.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CommitNotifier.java new file mode 100644 index 0000000000..d9f8e34da9 --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CommitNotifier.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 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.impl; + +import java.util.Set; +import org.w3c.dom.Element; + +public interface CommitNotifier { + void sendCommitNotification(String message, Element cfgSnapshot, Set capabilities); + + public static final class NoopCommitNotifier implements CommitNotifier { + + private static final CommitNotifier INSTANCE = new NoopCommitNotifier(); + + private NoopCommitNotifier() {} + + public static CommitNotifier getInstance() { + return INSTANCE; + } + + @Override + public void sendCommitNotification(final String message, final Element cfgSnapshot, final Set capabilities) { + // NOOP + } + } +} diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/DefaultCommitNotificationProducer.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/DefaultCommitNotificationProducer.java index ab37bac683..88ff928c51 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/DefaultCommitNotificationProducer.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/DefaultCommitNotificationProducer.java @@ -24,7 +24,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Element; public class DefaultCommitNotificationProducer extends NotificationBroadcasterSupport implements - DefaultCommitOperationMXBean, AutoCloseable { + DefaultCommitOperationMXBean, AutoCloseable, CommitNotifier { private static final Logger LOG = LoggerFactory.getLogger(DefaultCommitNotificationProducer.class); @@ -46,6 +46,7 @@ public class DefaultCommitNotificationProducer extends NotificationBroadcasterSu } } + @Override public void sendCommitNotification(String message, Element cfgSnapshot, Set capabilities) { CommitJMXNotification notif = NetconfJMXNotification.afterCommit(this, message, cfgSnapshot, capabilities); LOG.debug("Notification about commit {} sent", notif); diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcher.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcherImpl.java similarity index 86% rename from opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcher.java rename to opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcherImpl.java index 4dfb749818..a040b8b87b 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcher.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcherImpl.java @@ -8,7 +8,6 @@ package org.opendaylight.controller.netconf.impl; -import com.google.common.annotations.VisibleForTesting; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; @@ -18,23 +17,23 @@ import io.netty.channel.local.LocalServerChannel; import io.netty.channel.socket.SocketChannel; import io.netty.util.concurrent.Promise; import java.net.InetSocketAddress; +import org.opendaylight.controller.netconf.api.NetconfServerDispatcher; import org.opendaylight.controller.netconf.impl.util.DeserializerExceptionHandler; import org.opendaylight.controller.netconf.nettyutil.AbstractChannelInitializer; import org.opendaylight.protocol.framework.AbstractDispatcher; -public class NetconfServerDispatcher extends AbstractDispatcher { +public class NetconfServerDispatcherImpl extends AbstractDispatcher implements NetconfServerDispatcher { private final ServerChannelInitializer initializer; - public NetconfServerDispatcher(ServerChannelInitializer serverChannelInitializer, EventLoopGroup bossGroup, - EventLoopGroup workerGroup) { + public NetconfServerDispatcherImpl(ServerChannelInitializer serverChannelInitializer, EventLoopGroup bossGroup, + EventLoopGroup workerGroup) { super(bossGroup, workerGroup); this.initializer = serverChannelInitializer; } - @VisibleForTesting + @Override public ChannelFuture createServer(InetSocketAddress address) { - return super.createServer(address, new PipelineInitializer() { @Override public void initializeChannel(final SocketChannel ch, final Promise promise) { @@ -43,6 +42,7 @@ public class NetconfServerDispatcher extends AbstractDispatcher() { @Override diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java index 0537942487..604cc5f55b 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java @@ -17,12 +17,12 @@ import org.opendaylight.protocol.framework.SessionListenerFactory; public class NetconfServerSessionListenerFactory implements SessionListenerFactory { - private final DefaultCommitNotificationProducer commitNotifier; + private final CommitNotifier commitNotifier; private final SessionMonitoringService monitor; private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot; private final CapabilityProvider capabilityProvider; - public NetconfServerSessionListenerFactory(final DefaultCommitNotificationProducer commitNotifier, + public NetconfServerSessionListenerFactory(final CommitNotifier commitNotifier, final SessionMonitoringService monitor, final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot, final CapabilityProvider capabilityProvider) { diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java index 34f4f0e653..451c066b77 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java @@ -44,7 +44,7 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF private final SessionIdProvider idProvider; private final NetconfOperationProvider netconfOperationProvider; private final long connectionTimeoutMillis; - private final DefaultCommitNotificationProducer commitNotificationProducer; + private final CommitNotifier commitNotificationProducer; private final SessionMonitoringService monitoringService; private static final Logger LOG = LoggerFactory.getLogger(NetconfServerSessionNegotiatorFactory.class); private final Set baseCapabilities; @@ -52,7 +52,7 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF // TODO too many params, refactor public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationProvider netconfOperationProvider, SessionIdProvider idProvider, long connectionTimeoutMillis, - DefaultCommitNotificationProducer commitNot, + CommitNotifier commitNot, SessionMonitoringService monitoringService) { this(timer, netconfOperationProvider, idProvider, connectionTimeoutMillis, commitNot, monitoringService, DEFAULT_BASE_CAPABILITIES); } @@ -60,7 +60,7 @@ public class NetconfServerSessionNegotiatorFactory implements SessionNegotiatorF // TODO too many params, refactor public NetconfServerSessionNegotiatorFactory(Timer timer, NetconfOperationProvider netconfOperationProvider, SessionIdProvider idProvider, long connectionTimeoutMillis, - DefaultCommitNotificationProducer commitNot, + CommitNotifier commitNot, SessionMonitoringService monitoringService, Set baseCapabilities) { this.timer = timer; this.netconfOperationProvider = netconfOperationProvider; diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java index fbe855f8be..742255f973 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java @@ -12,7 +12,7 @@ import com.google.common.base.Preconditions; import java.io.InputStream; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; -import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; +import org.opendaylight.controller.netconf.impl.CommitNotifier; import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouter; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; @@ -31,11 +31,11 @@ public class DefaultCommit extends AbstractNetconfOperation { private static final String NOTIFY_ATTR = "notify"; - private final DefaultCommitNotificationProducer notificationProducer; + private final CommitNotifier notificationProducer; private final CapabilityProvider cap; private final NetconfOperationRouter operationRouter; - public DefaultCommit(DefaultCommitNotificationProducer notifier, CapabilityProvider cap, + public DefaultCommit(CommitNotifier notifier, CapabilityProvider cap, String netconfSessionIdForReporting, NetconfOperationRouter netconfOperationRouter) { super(netconfSessionIdForReporting); this.notificationProducer = notifier; diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java index 27423c09b7..a55e32a954 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java @@ -16,7 +16,7 @@ import java.util.Hashtable; import java.util.concurrent.TimeUnit; import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; -import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; +import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl; import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; import org.opendaylight.controller.netconf.impl.SessionIdProvider; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider; @@ -57,9 +57,9 @@ public class NetconfImplActivator implements BundleActivator { eventLoopGroup = new NioEventLoopGroup(); - NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer( + NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer( serverNegotiatorFactory); - NetconfServerDispatcher dispatch = new NetconfServerDispatcher(serverChannelInitializer, eventLoopGroup, eventLoopGroup); + NetconfServerDispatcherImpl dispatch = new NetconfServerDispatcherImpl(serverChannelInitializer, eventLoopGroup, eventLoopGroup); LocalAddress address = NetconfConfigUtil.getNetconfLocalAddress(); LOG.trace("Starting local netconf server at {}", address); diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java index 2178d4eedf..c8fa341747 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java @@ -17,7 +17,7 @@ import java.util.NavigableMap; import java.util.Set; import java.util.TreeMap; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; -import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; +import org.opendaylight.controller.netconf.impl.CommitNotifier; import org.opendaylight.controller.netconf.impl.NetconfServerSession; import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession; @@ -44,7 +44,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { private final Collection allNetconfOperations; public NetconfOperationRouterImpl(final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot, final CapabilityProvider capabilityProvider, - final DefaultCommitNotificationProducer commitNotifier) { + final CommitNotifier commitNotifier) { this.netconfOperationServiceSnapshot = Preconditions.checkNotNull(netconfOperationServiceSnapshot); final String sessionId = netconfOperationServiceSnapshot.getNetconfSessionIdForReporting(); diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTracker.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTracker.java index c1d9317c29..9a077a6130 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTracker.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTracker.java @@ -7,6 +7,7 @@ */ package org.opendaylight.controller.netconf.impl.osgi; +import org.opendaylight.controller.netconf.api.util.NetconfConstants; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; @@ -24,15 +25,23 @@ class NetconfOperationServiceFactoryTracker extends @Override public NetconfOperationServiceFactory addingService(ServiceReference reference) { - NetconfOperationServiceFactory netconfOperationServiceFactory = super.addingService(reference); - factoriesListener.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory); - return netconfOperationServiceFactory; + Object property = reference.getProperty(NetconfConstants.SERVICE_NAME); + if (property != null + && (property.equals(NetconfConstants.CONFIG_NETCONF_CONNECTOR) + || property.equals(NetconfConstants.NETCONF_MONITORING))) { + NetconfOperationServiceFactory netconfOperationServiceFactory = super.addingService(reference); + factoriesListener.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory); + return netconfOperationServiceFactory; + } + + return null; } @Override public void removedService(ServiceReference reference, NetconfOperationServiceFactory netconfOperationServiceFactory) { - factoriesListener.onRemoveNetconfOperationServiceFactory(netconfOperationServiceFactory); + if (netconfOperationServiceFactory != null) + factoriesListener.onRemoveNetconfOperationServiceFactory(netconfOperationServiceFactory); } } diff --git a/opendaylight/netconf/netconf-impl/src/main/yang/netconf-northbound-impl.yang b/opendaylight/netconf/netconf-impl/src/main/yang/netconf-northbound-impl.yang new file mode 100644 index 0000000000..6ca0a7781c --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/main/yang/netconf-northbound-impl.yang @@ -0,0 +1,80 @@ +// vi: set smarttab et sw=4 tabstop=4: +module netconf-northbound-impl { + + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound:impl"; + prefix "cfg-net-s-i"; + + import config { prefix config; revision-date 2013-04-05; } + import netconf-northbound-mapper { prefix nnm; revision-date 2015-01-14; } + import netconf-northbound { prefix nn; revision-date 2015-01-14; } + import netty {prefix netty; } + + description + "This module contains the base YANG definitions for + netconf-server-dispatcher implementation. + + 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 "2015-01-12" { + description + "Initial revision."; + } + + identity netconf-server-dispatcher-impl { + base config:module-type; + config:provided-service nn:netconf-server-dispatcher; + config:java-name-prefix NetconfServerDispatcher; + } + + augment "/config:modules/config:module/config:configuration" { + case netconf-server-dispatcher-impl { + when "/config:modules/config:module/config:type = 'netconf-server-dispatcher-impl'"; + + leaf connection-timeout-millis { + description "Specifies timeout in milliseconds after which connection must be established."; + type uint32; + default 20000; + } + + container boss-thread-group { + uses config:service-ref { + refine type { + config:required-identity netty:netty-threadgroup; + } + } + } + + container worker-thread-group { + uses config:service-ref { + refine type { + config:required-identity netty:netty-threadgroup; + } + } + } + + list mappers { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity nnm:netconf-northbound-mapper; + } + } + } + + container timer { + uses config:service-ref { + refine type { + config:required-identity netty:netty-timer; + } + } + } + } + } + +} \ No newline at end of file diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java index 3b83daa693..8e8a73b914 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java @@ -155,8 +155,8 @@ public class ConcurrentClientsTest { commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer()); - NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(serverNegotiatorFactory); - final NetconfServerDispatcher dispatch = new NetconfServerDispatcher(serverChannelInitializer, nettyGroup, nettyGroup); + NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer(serverNegotiatorFactory); + final NetconfServerDispatcherImpl dispatch = new NetconfServerDispatcherImpl(serverChannelInitializer, nettyGroup, nettyGroup); ChannelFuture s = dispatch.createServer(netconfAddress); s.await(); diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java index ecc33ca90f..df4069ac17 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java @@ -22,7 +22,7 @@ import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFact public class NetconfDispatcherImplTest { private EventLoopGroup nettyGroup; - private NetconfServerDispatcher dispatch; + private NetconfServerDispatcherImpl dispatch; private DefaultCommitNotificationProducer commitNot; private HashedWheelTimer hashedWheelTimer; @@ -40,9 +40,9 @@ public class NetconfDispatcherImplTest { NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory( hashedWheelTimer, factoriesListener, idProvider, 5000, commitNot, ConcurrentClientsTest.createMockedMonitoringService()); - NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(serverNegotiatorFactory); + NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer(serverNegotiatorFactory); - dispatch = new NetconfServerDispatcher( + dispatch = new NetconfServerDispatcherImpl( serverChannelInitializer, nettyGroup, nettyGroup); } diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTrackerTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTrackerTest.java index d744504bb2..8cb569eaa2 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTrackerTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryTrackerTest.java @@ -20,6 +20,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.netconf.api.util.NetconfConstants; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.osgi.framework.BundleContext; import org.osgi.framework.Filter; @@ -46,6 +47,7 @@ public class NetconfOperationServiceFactoryTrackerTest { doNothing().when(listener).onRemoveNetconfOperationServiceFactory(any(NetconfOperationServiceFactory.class)); doReturn(filter).when(context).createFilter(anyString()); doReturn("").when(reference).toString(); + doReturn(NetconfConstants.CONFIG_NETCONF_CONNECTOR).when(reference).getProperty(NetconfConstants.SERVICE_NAME); doReturn(factory).when(context).getService(any(ServiceReference.class)); doReturn("").when(factory).toString(); doNothing().when(listener).onAddNetconfOperationServiceFactory(any(NetconfOperationServiceFactory.class)); diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java index bf1385398b..b70e97bac9 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java @@ -54,7 +54,7 @@ import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguratio import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; -import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; +import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl; import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; import org.opendaylight.controller.netconf.impl.SessionIdProvider; import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; @@ -138,7 +138,7 @@ public abstract class AbstractNetconfConfigTest extends AbstractConfigTest { } private Channel startNetconfTcpServer(final NetconfOperationServiceFactoryListenerImpl factoriesListener) throws Exception { - final NetconfServerDispatcher dispatch = createDispatcher(factoriesListener, getNetconfMonitoringService(), getNotificationProducer()); + final NetconfServerDispatcherImpl dispatch = createDispatcher(factoriesListener, getNetconfMonitoringService(), getNotificationProducer()); final ChannelFuture s; if(getTcpServerAddress() instanceof LocalAddress) { @@ -205,7 +205,7 @@ public abstract class AbstractNetconfConfigTest extends AbstractConfigTest { return yangDependencies; } - protected NetconfServerDispatcher createDispatcher( + protected NetconfServerDispatcherImpl createDispatcher( final NetconfOperationServiceFactoryListenerImpl factoriesListener, final SessionMonitoringService sessionMonitoringService, final DefaultCommitNotificationProducer commitNotifier) { final SessionIdProvider idProvider = new SessionIdProvider(); @@ -213,9 +213,9 @@ public abstract class AbstractNetconfConfigTest extends AbstractConfigTest { final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory( hashedWheelTimer, factoriesListener, idProvider, SERVER_CONNECTION_TIMEOUT_MILLIS, commitNotifier, sessionMonitoringService); - final NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer( + final NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer( serverNegotiatorFactory); - return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup); + return new NetconfServerDispatcherImpl(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup); } protected HashedWheelTimer getHashedWheelTimer() { diff --git a/opendaylight/netconf/netconf-mapping-api/pom.xml b/opendaylight/netconf/netconf-mapping-api/pom.xml index f5ae0ec610..21e50cd2ea 100644 --- a/opendaylight/netconf/netconf-mapping-api/pom.xml +++ b/opendaylight/netconf/netconf-mapping-api/pom.xml @@ -29,12 +29,42 @@ org.apache.felix maven-bundle-plugin - - - org.opendaylight.controller.netconf.mapping.api, - - + + org.opendaylight.yangtools + yang-maven-plugin + + + config + + generate-sources + + + + + org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + ${jmxGeneratorPath} + + urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + ${salGeneratorPath} + + + true + + + + + + org.opendaylight.controller + yang-jmx-generator-plugin + ${config.version} + + + diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/yang/netconf-northbound-mapper.yang b/opendaylight/netconf/netconf-mapping-api/src/main/yang/netconf-northbound-mapper.yang new file mode 100644 index 0000000000..a709665c63 --- /dev/null +++ b/opendaylight/netconf/netconf-mapping-api/src/main/yang/netconf-northbound-mapper.yang @@ -0,0 +1,22 @@ +module netconf-northbound-mapper { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:netconf:north:mapper"; + prefix "nnm"; + + import config { prefix config; revision-date 2013-04-05; } + + description + "This module contains the base YANG definitions for + mapping services plugged into a netconf northbound server"; + + revision "2015-01-14" { + description + "Initial revision."; + } + + identity netconf-northbound-mapper { + base "config:service-type"; + config:java-class "org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory"; + } + +} \ No newline at end of file diff --git a/opendaylight/netconf/netconf-mdsal-config/pom.xml b/opendaylight/netconf/netconf-mdsal-config/pom.xml new file mode 100644 index 0000000000..f3c931345f --- /dev/null +++ b/opendaylight/netconf/netconf-mdsal-config/pom.xml @@ -0,0 +1,46 @@ + + + + + 4.0.0 + + org.opendaylight.controller + netconf-subsystem + 0.3.0-SNAPSHOT + + netconf-mdsal-config + Configuration files for netconf for mdsal + jar + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + + attach-artifact + + package + + + + ${project.build.directory}/classes/initial/08-netconf-mdsal.xml + xml + config + + + + + + + + + diff --git a/opendaylight/netconf/netconf-mdsal-config/src/main/resources/initial/08-netconf-mdsal.xml b/opendaylight/netconf/netconf-mdsal-config/src/main/resources/initial/08-netconf-mdsal.xml new file mode 100644 index 0000000000..042447b1e6 --- /dev/null +++ b/opendaylight/netconf/netconf-mdsal-config/src/main/resources/initial/08-netconf-mdsal.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + prefix:netconf-mdsal-mapper + netconf-mdsal-mapper + + dom:schema-service + yang-schema-service + + + dom:dom-async-data-broker + inmemory-data-broker + + + + + prefix:netconf-server-dispatcher-impl + netconf-mdsal-server-dispatcher + + dom:netconf-northbound-mapper + netconf-mdsal-mapper + + + prefix:netty-threadgroup + global-boss-group + + + prefix:netty-threadgroup + global-worker-group + + + prefix:netty-timer + global-timer + + + + + prefix:netconf-northbound-ssh + netconf-mdsal-ssh-server + + + prefix:netty-event-executor + global-event-executor + + + prefix:netty-threadgroup + global-worker-group + + + prefix:threadpool + global-netconf-ssh-scheduled-executor + + + prefix:netconf-server-dispatcher + netconf-mdsal-server-dispatcher + + + admin + admin + + + + + + + prefix:netconf-northbound-mapper + + netconf-mdsal-mapper + /modules/module[type='netconf-mdsal-mapper'][name='netconf-mdsal-mapper'] + + + + prefix:netconf-server-dispatcher + + netconf-mdsal-server-dispatcher + /modules/module[type='netconf-server-dispatcher-impl'][name='netconf-mdsal-server-dispatcher'] + + + + + + + + urn:opendaylight:params:xml:ns:yang:controller:netconf:mdsal:mapper?module=netconf-mdsal-mapper&revision=2015-01-14 + urn:opendaylight:params:xml:ns:yang:controller:netconf:northbound:ssh?module=netconf-northbound-ssh&revision=2015-01-14 + urn:opendaylight:params:xml:ns:yang:controller:config:netconf:northbound:impl?module=netconf-northbound-impl&revision=2015-01-12 + urn:opendaylight:params:xml:ns:yang:controller:threadpool:impl:scheduled?module=threadpool-impl-scheduled&revision=2013-12-01 + + diff --git a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringServiceTracker.java b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringServiceTracker.java index 0b4d1c2688..9e7c105aa4 100644 --- a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringServiceTracker.java +++ b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringServiceTracker.java @@ -8,8 +8,10 @@ package org.opendaylight.controller.netconf.monitoring.osgi; import com.google.common.base.Preconditions; +import java.util.Dictionary; import java.util.Hashtable; import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; +import org.opendaylight.controller.netconf.api.util.NetconfConstants; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; @@ -39,7 +41,9 @@ public class NetconfMonitoringServiceTracker extends ServiceTracker()); + Dictionary properties = new Hashtable<>(); + properties.put(NetconfConstants.SERVICE_NAME, NetconfConstants.NETCONF_MONITORING); + reg = context.registerService(NetconfOperationServiceFactory.class, factory, properties); return netconfMonitoringService; } diff --git a/opendaylight/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/controller/netconf/notifications/impl/osgi/Activator.java b/opendaylight/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/controller/netconf/notifications/impl/osgi/Activator.java index ef950f8a78..9eab5caff7 100644 --- a/opendaylight/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/controller/netconf/notifications/impl/osgi/Activator.java +++ b/opendaylight/netconf/netconf-notifications-impl/src/main/java/org/opendaylight/controller/netconf/notifications/impl/osgi/Activator.java @@ -12,8 +12,10 @@ import com.google.common.base.Optional; import com.google.common.collect.Sets; import java.util.Collection; import java.util.Collections; +import java.util.Dictionary; import java.util.Hashtable; import java.util.Set; +import org.opendaylight.controller.netconf.api.util.NetconfConstants; import org.opendaylight.controller.netconf.mapping.api.Capability; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; @@ -66,7 +68,9 @@ public class Activator implements BundleActivator { } }; - operationaServiceRegistration = context.registerService(NetconfOperationServiceFactory.class, netconfOperationServiceFactory, new Hashtable()); + Dictionary properties = new Hashtable<>(); + properties.put(NetconfConstants.SERVICE_NAME, NetconfConstants.NETCONF_MONITORING); + operationaServiceRegistration = context.registerService(NetconfOperationServiceFactory.class, netconfOperationServiceFactory, properties); } diff --git a/opendaylight/netconf/netconf-ssh/pom.xml b/opendaylight/netconf/netconf-ssh/pom.xml index 2371ede577..03f7a2fac2 100644 --- a/opendaylight/netconf/netconf-ssh/pom.xml +++ b/opendaylight/netconf/netconf-ssh/pom.xml @@ -24,9 +24,27 @@ ${project.groupId} netconf-util + + ${project.groupId} + netconf-impl + commons-io commons-io + + + org.opendaylight.controller + threadpool-config-api + + + org.opendaylight.controller + netty-config-api + 0.3.0-SNAPSHOT + + + + org.opendaylight.yangtools.model + ietf-inet-types org.bouncycastle @@ -87,6 +105,41 @@ + + org.opendaylight.yangtools + yang-maven-plugin + + + config + + generate-sources + + + + + org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator + ${jmxGeneratorPath} + + urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + ${salGeneratorPath} + + + true + + + + + + org.opendaylight.controller + yang-jmx-generator-plugin + ${config.version} + + + diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/config/yang/netconf/northbound/ssh/NetconfNorthboundSshModule.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/config/yang/netconf/northbound/ssh/NetconfNorthboundSshModule.java new file mode 100644 index 0000000000..f17bc3cceb --- /dev/null +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/config/yang/netconf/northbound/ssh/NetconfNorthboundSshModule.java @@ -0,0 +1,122 @@ +package org.opendaylight.controller.config.yang.netconf.northbound.ssh; + +import io.netty.channel.ChannelFuture; +import io.netty.channel.local.LocalAddress; +import io.netty.util.concurrent.GenericFutureListener; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.concurrent.Executors; +import org.apache.sshd.server.PasswordAuthenticator; +import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider; +import org.apache.sshd.server.session.ServerSession; +import org.opendaylight.controller.netconf.api.NetconfServerDispatcher; +import org.opendaylight.controller.netconf.ssh.SshProxyServer; +import org.opendaylight.controller.netconf.ssh.SshProxyServerConfigurationBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NetconfNorthboundSshModule extends org.opendaylight.controller.config.yang.netconf.northbound.ssh.AbstractNetconfNorthboundSshModule { + + private static final Logger LOG = LoggerFactory.getLogger(NetconfNorthboundSshModule.class); + + public NetconfNorthboundSshModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public NetconfNorthboundSshModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final org.opendaylight.controller.config.yang.netconf.northbound.ssh.NetconfNorthboundSshModule oldModule, final java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + // add custom validation form module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + final NetconfServerDispatcher dispatch = getDispatcherDependency(); + + final LocalAddress localAddress = new LocalAddress(getPort().toString()); + final ChannelFuture localServer = dispatch.createLocalServer(localAddress); + + final SshProxyServer sshProxyServer = new SshProxyServer(Executors.newScheduledThreadPool(1), getWorkerThreadGroupDependency(), getEventExecutorDependency()); + + final InetSocketAddress bindingAddress = getInetAddress(); + final SshProxyServerConfigurationBuilder sshProxyServerConfigurationBuilder = new SshProxyServerConfigurationBuilder(); + sshProxyServerConfigurationBuilder.setBindingAddress(bindingAddress); + sshProxyServerConfigurationBuilder.setLocalAddress(localAddress); + sshProxyServerConfigurationBuilder.setAuthenticator(new UserAuthenticator(getUsername(), getPassword())); + sshProxyServerConfigurationBuilder.setIdleTimeout(Integer.MAX_VALUE); + sshProxyServerConfigurationBuilder.setKeyPairProvider(new PEMGeneratorHostKeyProvider()); + + localServer.addListener(new GenericFutureListener() { + + @Override + public void operationComplete(final ChannelFuture future) { + if(future.isDone() && !future.isCancelled()) { + try { + sshProxyServer.bind(sshProxyServerConfigurationBuilder.createSshProxyServerConfiguration()); + LOG.info("Netconf SSH endpoint started successfully at {}", bindingAddress); + } catch (final IOException e) { + throw new RuntimeException("Unable to start SSH netconf server", e); + } + } else { + LOG.warn("Unable to start SSH netconf server at {}", bindingAddress, future.cause()); + throw new RuntimeException("Unable to start SSH netconf server", future.cause()); + } + } + }); + + return new NetconfServerCloseable(localServer, sshProxyServer); + } + + private InetSocketAddress getInetAddress() { + try { + final InetAddress inetAd = InetAddress.getByName(getBindingAddress().getIpv4Address() == null ? getBindingAddress().getIpv6Address().getValue() : getBindingAddress().getIpv4Address().getValue()); + return new InetSocketAddress(inetAd, getPort().getValue()); + } catch (final UnknownHostException e) { + throw new IllegalArgumentException("Unable to bind netconf endpoint to address " + getBindingAddress(), e); + } + } + + private static final class NetconfServerCloseable implements AutoCloseable { + private final ChannelFuture localServer; + private final SshProxyServer sshProxyServer; + + public NetconfServerCloseable(final ChannelFuture localServer, final SshProxyServer sshProxyServer) { + this.localServer = localServer; + this.sshProxyServer = sshProxyServer; + } + + @Override + public void close() throws Exception { + sshProxyServer.close(); + + if(localServer.isDone()) { + localServer.channel().close(); + } else { + localServer.cancel(true); + } + } + } + + + private static final class UserAuthenticator implements PasswordAuthenticator { + + private final String username; + private final String password; + + public UserAuthenticator(final String username, final String password) { + this.username = username; + this.password = password; + } + + @Override + public boolean authenticate(final String username, final String password, final ServerSession session) { + // FIXME use aaa stuff here instead + return this.username.equals(username) && this.password.equals(password); + } + } +} diff --git a/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/config/yang/netconf/northbound/ssh/NetconfNorthboundSshModuleFactory.java b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/config/yang/netconf/northbound/ssh/NetconfNorthboundSshModuleFactory.java new file mode 100644 index 0000000000..4e107ec24d --- /dev/null +++ b/opendaylight/netconf/netconf-ssh/src/main/java/org/opendaylight/controller/config/yang/netconf/northbound/ssh/NetconfNorthboundSshModuleFactory.java @@ -0,0 +1,13 @@ +/* +* Generated file +* +* Generated from: yang module name: netconf-northbound-ssh yang module local name: netconf-northbound-ssh +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Mon Feb 09 14:09:07 CET 2015 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.controller.config.yang.netconf.northbound.ssh; +public class NetconfNorthboundSshModuleFactory extends org.opendaylight.controller.config.yang.netconf.northbound.ssh.AbstractNetconfNorthboundSshModuleFactory { + +} diff --git a/opendaylight/netconf/netconf-ssh/src/main/yang/netconf-northbound-ssh.yang b/opendaylight/netconf/netconf-ssh/src/main/yang/netconf-northbound-ssh.yang new file mode 100644 index 0000000000..2e9d0b15b4 --- /dev/null +++ b/opendaylight/netconf/netconf-ssh/src/main/yang/netconf-northbound-ssh.yang @@ -0,0 +1,94 @@ +module netconf-northbound-ssh { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:netconf:northbound:ssh"; + prefix "nni"; + + import netconf-northbound-mapper { prefix nnm; revision-date 2015-01-14; } + import netconf-northbound { prefix nn; revision-date 2015-01-14; } + import config { prefix config; revision-date 2013-04-05; } + import threadpool {prefix th;} + import netty {prefix netty;} + import ietf-inet-types { prefix inet; revision-date 2010-09-24; } + + organization "Cisco Systems, Inc."; + + description + "This module contains the base YANG definitions for + a default implementation of netconf northbound server"; + + revision "2015-01-14" { + description + "Initial revision."; + } + + identity netconf-northbound-ssh { + base config:module-type; + config:java-name-prefix NetconfNorthboundSsh; + } + + augment "/config:modules/config:module/config:configuration" { + case netconf-northbound-ssh { + when "/config:modules/config:module/config:type = 'netconf-northbound-ssh'"; + + leaf port { + type inet:port-number; + default 2830; + } + + leaf binding-address { + type inet:ip-address; + default "0.0.0.0"; + } + + container processing-executor { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity th:scheduled-threadpool; + } + } + + description "Required by the mina-ssh library used in SSH endpoint"; + } + + container event-executor { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity netty:netty-event-executor; + } + } + } + + container worker-thread-group { + uses config:service-ref { + refine type { + config:required-identity netty:netty-threadgroup; + } + } + } + + container dispatcher { + uses config:service-ref { + refine type { + config:required-identity nn:netconf-server-dispatcher; + } + } + } + + // FIXME use auth provider from aaa instead + leaf username { + description "Specifies username credential"; + type string; + } + + leaf password { + description "Specifies password credential"; + type string; + } + + + } + } + +} \ No newline at end of file diff --git a/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/netty/SSHTest.java b/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/netty/SSHTest.java index 72534e242e..ab73126021 100644 --- a/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/netty/SSHTest.java +++ b/opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/netty/SSHTest.java @@ -84,7 +84,7 @@ public class SSHTest { final EchoClientHandler echoClientHandler = connectClient(addr); - Stopwatch stopwatch = new Stopwatch().start(); + Stopwatch stopwatch = Stopwatch.createStarted(); while(echoClientHandler.isConnected() == false && stopwatch.elapsed(TimeUnit.SECONDS) < 30) { Thread.sleep(500); } @@ -131,7 +131,7 @@ public class SSHTest { public void testClientWithoutServer() throws Exception { final InetSocketAddress address = new InetSocketAddress(12345); final EchoClientHandler echoClientHandler = connectClient(address); - final Stopwatch stopwatch = new Stopwatch().start(); + final Stopwatch stopwatch = Stopwatch.createStarted(); while(echoClientHandler.getState() == State.CONNECTING && stopwatch.elapsed(TimeUnit.SECONDS) < 5) { Thread.sleep(100); } diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java index 0d7ee3b945..30b3076589 100644 --- a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java +++ b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java @@ -10,7 +10,7 @@ package org.opendaylight.controller.netconf.test.tool; import com.google.common.base.Charsets; import com.google.common.base.Function; -import com.google.common.base.Objects; +import com.google.common.base.MoreObjects; import com.google.common.base.Optional; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; @@ -58,7 +58,7 @@ import org.apache.sshd.server.session.ServerSession; import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; -import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; +import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl; import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; import org.opendaylight.controller.netconf.impl.SessionIdProvider; import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; @@ -125,7 +125,7 @@ public class NetconfDeviceSimulator implements Closeable { this.nioExecutor = nioExecutor; } - private NetconfServerDispatcher createDispatcher(final Map moduleBuilders, final boolean exi, final int generateConfigsTimeout, final Optional notificationsFile) { + private NetconfServerDispatcherImpl createDispatcher(final Map moduleBuilders, final boolean exi, final int generateConfigsTimeout, final Optional notificationsFile) { final Set capabilities = Sets.newHashSet(Collections2.transform(moduleBuilders.keySet(), new Function() { @Override @@ -154,9 +154,9 @@ public class NetconfDeviceSimulator implements Closeable { final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory( hashedWheelTimer, simulatedOperationProvider, idProvider, generateConfigsTimeout, commitNotifier, new LoggingMonitoringService(), serverCapabilities); - final NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer( + final NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer( serverNegotiatorFactory); - return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup); + return new NetconfServerDispatcherImpl(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup); } private Map toModuleBuilders(final Map> sources) { @@ -192,7 +192,7 @@ public class NetconfDeviceSimulator implements Closeable { final Map moduleBuilders = parseSchemasToModuleBuilders(params); - final NetconfServerDispatcher dispatcher = createDispatcher(moduleBuilders, params.exi, params.generateConfigsTimeout, Optional.fromNullable(params.notificationFile)); + final NetconfServerDispatcherImpl dispatcher = createDispatcher(moduleBuilders, params.exi, params.generateConfigsTimeout, Optional.fromNullable(params.notificationFile)); int currentPort = params.startingPort; @@ -360,7 +360,7 @@ public class NetconfDeviceSimulator implements Closeable { public CheckedFuture getSource(final SourceIdentifier sourceIdentifier) { return Futures.immediateCheckedFuture(new YangTextSchemaSource(sourceId) { @Override - protected Objects.ToStringHelper addToStringAttributes(final Objects.ToStringHelper toStringHelper) { + protected MoreObjects.ToStringHelper addToStringAttributes(final MoreObjects.ToStringHelper toStringHelper) { return toStringHelper; } diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java index e1331b1380..176a0de9a4 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java @@ -10,11 +10,9 @@ package org.opendaylight.controller.netconf.util.test; import com.google.common.base.Charsets; import com.google.common.base.Preconditions; -import com.google.common.io.CharStreams; -import com.google.common.io.InputSupplier; +import com.google.common.io.ByteSource; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import javax.xml.parsers.ParserConfigurationException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -51,17 +49,13 @@ public class XmlFileLoader { public static String fileToString(final String fileName) throws IOException { try (InputStream resourceAsStream = XmlFileLoader.class.getClassLoader().getResourceAsStream(fileName)) { Preconditions.checkNotNull(resourceAsStream); - - InputSupplier supplier = new InputSupplier() { + return new ByteSource() { @Override - public InputStream getInput() throws IOException { + public InputStream openStream() { return resourceAsStream; } - }; - - InputSupplier readerSupplier = CharStreams.newReaderSupplier(supplier, Charsets.UTF_8); + }.asCharSource(Charsets.UTF_8).read(); - return CharStreams.toString(readerSupplier); } } diff --git a/opendaylight/netconf/pom.xml b/opendaylight/netconf/pom.xml index 653dd70b29..4566845e4f 100644 --- a/opendaylight/netconf/pom.xml +++ b/opendaylight/netconf/pom.xml @@ -20,6 +20,7 @@ netconf-config netconf-impl config-netconf-connector + mdsal-netconf-connector netconf-util netconf-netty-util config-persister-impl @@ -33,6 +34,7 @@ ietf-netconf-notifications ietf-netconf-monitoring-extension netconf-connector-config + netconf-mdsal-config netconf-auth netconf-usermanager netconf-testtool diff --git a/opendaylight/networkconfiguration/neutron/northbound/pom.xml b/opendaylight/networkconfiguration/neutron/northbound/pom.xml index e61a8e5118..1e7bcf0ae6 100644 --- a/opendaylight/networkconfiguration/neutron/northbound/pom.xml +++ b/opendaylight/networkconfiguration/neutron/northbound/pom.xml @@ -35,6 +35,10 @@ org.opendaylight.controller networkconfig.neutron + + org.osgi + org.osgi.core +