From: Ed Warnicke Date: Mon, 16 Dec 2013 15:52:41 +0000 (+0000) Subject: Merge "Fixed netconf monitoring." X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~187 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=d1ab4c3ea79bcd74e02aa9334bc660cb7fc6d037;hp=ff42855d9de0ab5e8c409ccde914e6f501676ddb Merge "Fixed netconf monitoring." --- diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index e519a04a57..35e160e827 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -285,6 +285,11 @@ ietf-netconf-monitoring ${netconf.version} + + ${project.groupId} + ietf-netconf-monitoring-extension + ${netconf.version} + org.opendaylight.controller config-persister-impl diff --git a/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java b/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java index 15616215d3..112b57cd33 100644 --- a/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java +++ b/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java @@ -54,6 +54,7 @@ public class TestHelper { mavenBundle(CONTROLLER, "config-persister-api").versionAsInProject(), // mavenBundle(CONTROLLER, "netconf-api").versionAsInProject(), // mavenBundle(CONTROLLER, "ietf-netconf-monitoring").versionAsInProject(), // + mavenBundle(CONTROLLER, "ietf-netconf-monitoring-extension").versionAsInProject(), // mavenBundle(CONTROLLER, "netconf-monitoring").versionAsInProject(), // mavenBundle(CONTROLLER, "netconf-client").versionAsInProject(), // diff --git a/opendaylight/netconf/config-persister-impl/pom.xml b/opendaylight/netconf/config-persister-impl/pom.xml index 7fc2b584b8..20bd386063 100644 --- a/opendaylight/netconf/config-persister-impl/pom.xml +++ b/opendaylight/netconf/config-persister-impl/pom.xml @@ -90,6 +90,7 @@ org.opendaylight.controller.netconf.client, org.opendaylight.controller.netconf.util.osgi, org.opendaylight.controller.netconf.util.xml, + org.opendaylight.controller.netconf.util.messages, io.netty.channel, io.netty.channel.nio, io.netty.util.concurrent, diff --git a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java index 89c2703285..0b623baaa4 100644 --- a/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java +++ b/opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPusher.java @@ -8,14 +8,24 @@ package org.opendaylight.controller.netconf.persist.impl; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import io.netty.channel.EventLoopGroup; + +import java.io.IOException; +import java.io.InputStream; +import java.net.InetSocketAddress; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.annotation.concurrent.Immutable; + import org.opendaylight.controller.config.api.ConflictingVersionException; import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.client.NetconfClient; import org.opendaylight.controller.netconf.client.NetconfClientDispatcher; +import org.opendaylight.controller.netconf.util.messages.NetconfMessageAdditionalHeader; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -25,14 +35,8 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.SAXException; -import javax.annotation.concurrent.Immutable; -import java.io.IOException; -import java.io.InputStream; -import java.net.InetSocketAddress; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; @Immutable public class ConfigPusher { @@ -127,10 +131,14 @@ public class ConfigPusher { long deadline = pollingStart + timeout; + String additionalHeader = NetconfMessageAdditionalHeader.toString("unknown", address.getAddress().getHostAddress(), + Integer.toString(address.getPort()), "tcp", Optional.of("persister")); + Set latestCapabilities = new HashSet<>(); while (System.currentTimeMillis() < deadline) { attempt++; - NetconfClientDispatcher netconfClientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup); + NetconfClientDispatcher netconfClientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, + nettyThreadgroup, additionalHeader); NetconfClient netconfClient; try { netconfClient = new NetconfClient(this.toString(), address, delay, netconfClientDispatcher); diff --git a/opendaylight/netconf/ietf-netconf-monitoring-extension/pom.xml b/opendaylight/netconf/ietf-netconf-monitoring-extension/pom.xml new file mode 100644 index 0000000000..aebaaebc1a --- /dev/null +++ b/opendaylight/netconf/ietf-netconf-monitoring-extension/pom.xml @@ -0,0 +1,101 @@ + + + netconf-subsystem + org.opendaylight.controller + 0.2.3-SNAPSHOT + + 4.0.0 + ietf-netconf-monitoring-extension + ${project.artifactId} + bundle + + + + org.opendaylight.controller + ietf-netconf-monitoring + + + com.google.guava + guava + + + org.slf4j + slf4j-api + + + + + + + + org.opendaylight.yangtools + yang-maven-plugin + ${yangtools.version} + + + + generate-sources + + + src/main/yang + + + + org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl + + + target/generated-sources/monitoring + + + + true + + + + + + org.opendaylight.yangtools + maven-sal-api-gen-plugin + ${yangtools.binding.version} + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.7 + + + generate-sources + + add-source + + + + target/generated-sources/sal + + + + + + + + org.apache.felix + maven-bundle-plugin + + + + com.google.common.collect, + org.opendaylight.yangtools.yang.binding, + org.opendaylight.yangtools.yang.common, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004, + + + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210, + + + + + + + \ No newline at end of file diff --git a/opendaylight/netconf/ietf-netconf-monitoring-extension/src/main/yang/ietf-netconf-monitoring-extension.yang b/opendaylight/netconf/ietf-netconf-monitoring-extension/src/main/yang/ietf-netconf-monitoring-extension.yang new file mode 100644 index 0000000000..e8f2ec324b --- /dev/null +++ b/opendaylight/netconf/ietf-netconf-monitoring-extension/src/main/yang/ietf-netconf-monitoring-extension.yang @@ -0,0 +1,31 @@ +module ietf-netconf-monitoring-extension { + + yang-version 1; + + namespace + "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring-extension"; + + prefix ncme; + + import ietf-netconf-monitoring { + prefix ncm; + } + + revision "2013-12-10" { + description "Initial revision."; + + } + + identity netconf-tcp { + base ncm:transport; + description + "NETCONF over TCP."; + } + + augment "/ncm:netconf-state/ncm:sessions/ncm:session" { + leaf session-identifier { + type string; + } + } + +} \ No newline at end of file diff --git a/opendaylight/netconf/netconf-api/pom.xml b/opendaylight/netconf/netconf-api/pom.xml index 0fce4748a4..856bd77c20 100644 --- a/opendaylight/netconf/netconf-api/pom.xml +++ b/opendaylight/netconf/netconf-api/pom.xml @@ -30,6 +30,11 @@ ${project.groupId} ietf-netconf-monitoring + + ${project.groupId} + ietf-netconf-monitoring-extension + ${project.version} + org.opendaylight.bgpcep diff --git a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfMessage.java b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfMessage.java index a0fddd79f2..7877843ccb 100644 --- a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfMessage.java +++ b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfMessage.java @@ -8,9 +8,10 @@ package org.opendaylight.controller.netconf.api; -import com.google.common.base.Optional; import org.w3c.dom.Document; +import com.google.common.base.Optional; + /** * NetconfMessage represents a wrapper around org.w3c.dom.Document. Needed for * implementing ProtocolMessage interface. diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java index 6ac57a88c9..fc6f87db5d 100644 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientDispatcher.java @@ -13,8 +13,10 @@ import io.netty.channel.socket.SocketChannel; import io.netty.util.HashedWheelTimer; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Promise; + import java.io.Closeable; import java.net.InetSocketAddress; + import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.NetconfSession; import org.opendaylight.controller.netconf.api.NetconfTerminationReason; @@ -26,6 +28,8 @@ import org.opendaylight.protocol.framework.SessionListenerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Optional; + public class NetconfClientDispatcher extends AbstractDispatcher implements Closeable { private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class); @@ -36,7 +40,13 @@ public class NetconfClientDispatcher extends AbstractDispatcherabsent()); + } + + public NetconfClientDispatcher(EventLoopGroup bossGroup, EventLoopGroup workerGroup, String additionalHeader) { + super(bossGroup, workerGroup); + timer = new HashedWheelTimer(); + this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.of(additionalHeader)); } public Future createClient(InetSocketAddress address, diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java index db0b953bdd..abfbdd526c 100644 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java @@ -8,10 +8,13 @@ package org.opendaylight.controller.netconf.client; -import com.google.common.base.Preconditions; import io.netty.channel.Channel; import io.netty.util.Timer; import io.netty.util.concurrent.Promise; + +import java.io.IOException; +import java.io.InputStream; + import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.NetconfSessionPreferences; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -20,15 +23,18 @@ import org.opendaylight.protocol.framework.SessionNegotiator; import org.opendaylight.protocol.framework.SessionNegotiatorFactory; import org.xml.sax.SAXException; -import java.io.IOException; -import java.io.InputStream; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; public class NetconfClientSessionNegotiatorFactory implements SessionNegotiatorFactory { private final Timer timer; - public NetconfClientSessionNegotiatorFactory(Timer timer) { + private final Optional additionalHeader; + + public NetconfClientSessionNegotiatorFactory(Timer timer, Optional additionalHeader) { this.timer = timer; + this.additionalHeader = additionalHeader; } private static NetconfMessage loadHelloMessageTemplate() { @@ -45,7 +51,11 @@ public class NetconfClientSessionNegotiatorFactory implements SessionNegotiatorF public SessionNegotiator getSessionNegotiator(SessionListenerFactory sessionListenerFactory, Channel channel, Promise promise) { // Hello message needs to be recreated every time - NetconfSessionPreferences proposal = new NetconfSessionPreferences(loadHelloMessageTemplate()); + NetconfMessage helloMessage = loadHelloMessageTemplate(); + if(this.additionalHeader.isPresent()) { + helloMessage = new NetconfMessage(helloMessage.getDocument(), additionalHeader.get()); + } + NetconfSessionPreferences proposal = new NetconfSessionPreferences(helloMessage); return new NetconfClientSessionNegotiator(proposal, promise, channel, timer, sessionListenerFactory.getSessionListener()); } diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java index 4de6cc35c0..ee07b3949d 100644 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfSshClientDispatcher.java @@ -14,8 +14,10 @@ import io.netty.channel.socket.SocketChannel; import io.netty.util.HashedWheelTimer; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.Promise; + import java.io.IOException; import java.net.InetSocketAddress; + import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.NetconfSession; import org.opendaylight.controller.netconf.api.NetconfTerminationReason; @@ -31,6 +33,8 @@ import org.opendaylight.protocol.framework.ReconnectStrategy; import org.opendaylight.protocol.framework.SessionListener; import org.opendaylight.protocol.framework.SessionListenerFactory; +import com.google.common.base.Optional; + public class NetconfSshClientDispatcher extends NetconfClientDispatcher { private AuthenticationHandler authHandler; @@ -42,7 +46,15 @@ public class NetconfSshClientDispatcher extends NetconfClientDispatcher { super(bossGroup, workerGroup); this.authHandler = authHandler; this.timer = new HashedWheelTimer(); - this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer); + this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.absent()); + } + + public NetconfSshClientDispatcher(AuthenticationHandler authHandler, EventLoopGroup bossGroup, + EventLoopGroup workerGroup, String additionalHeader) { + super(bossGroup, workerGroup, additionalHeader); + this.authHandler = authHandler; + this.timer = new HashedWheelTimer(); + this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.of(additionalHeader)); } public Future createClient(InetSocketAddress address, diff --git a/opendaylight/netconf/netconf-impl/pom.xml b/opendaylight/netconf/netconf-impl/pom.xml index e073aaca8d..b056f9be87 100644 --- a/opendaylight/netconf/netconf-impl/pom.xml +++ b/opendaylight/netconf/netconf-impl/pom.xml @@ -23,6 +23,11 @@ ${project.groupId} ietf-netconf-monitoring + + ${project.groupId} + ietf-netconf-monitoring-extension + ${project.version} + ${project.groupId} netconf-util @@ -150,6 +155,8 @@ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210, + org.opendaylight.yangtools.yang.binding, diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java index b692179429..4cc05b7b42 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java @@ -8,13 +8,21 @@ package org.opendaylight.controller.netconf.impl; -import com.google.common.base.Preconditions; import io.netty.channel.Channel; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import org.opendaylight.controller.netconf.api.NetconfSession; import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession; import org.opendaylight.protocol.framework.SessionListener; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.DomainName; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.NetconfTcp; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1Builder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Transport; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session; @@ -25,10 +33,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types. import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import com.google.common.base.Preconditions; public class NetconfServerSession extends NetconfSession implements NetconfManagementSession { @@ -91,14 +96,18 @@ public class NetconfServerSession extends NetconfSession implements NetconfManag builder.setOutNotifications(new ZeroBasedCounter32(0L)); builder.setKey(new SessionKey(getSessionId())); + + Session1Builder builder1 = new Session1Builder(); + builder1.setSessionIdentifier(header.getSessionType()); + builder.addAugmentation(Session1.class, builder1.build()); + return builder.build(); } private Class getTransportForString(String transport) { switch(transport) { case "ssh" : return NetconfSsh.class; - // TODO what about tcp - case "tcp" : return NetconfSsh.class; + case "tcp" : return NetconfTcp.class; default: throw new IllegalArgumentException("Unknown transport type " + transport); } } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiator.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiator.java index 01ac018b3e..8ba4cdc052 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiator.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiator.java @@ -8,28 +8,27 @@ package org.opendaylight.controller.netconf.impl; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; import io.netty.channel.Channel; import io.netty.util.Timer; import io.netty.util.concurrent.Promise; + +import java.net.InetSocketAddress; + import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.api.NetconfServerSessionPreferences; +import org.opendaylight.controller.netconf.impl.util.AdditionalHeaderUtil; import org.opendaylight.controller.netconf.util.AbstractNetconfSessionNegotiator; import org.opendaylight.protocol.framework.SessionListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import com.google.common.base.Optional; public class NetconfServerSessionNegotiator extends AbstractNetconfSessionNegotiator { static final Logger logger = LoggerFactory.getLogger(NetconfServerSessionNegotiator.class); - private static final AdditionalHeader DEFAULT_HEADER = new AdditionalHeader(); - protected NetconfServerSessionNegotiator(NetconfServerSessionPreferences sessionPreferences, Promise promise, Channel channel, Timer timer, SessionListener sessionListener) { super(sessionPreferences, promise, channel, timer, sessionListener); @@ -41,36 +40,28 @@ public class NetconfServerSessionNegotiator extends AdditionalHeader parsedHeader; if (additionalHeader.isPresent()) { - parsedHeader = new AdditionalHeader(additionalHeader.get()); + parsedHeader = AdditionalHeaderUtil.fromString(additionalHeader.get()); } else { - parsedHeader = DEFAULT_HEADER; + parsedHeader = new AdditionalHeader("unknown", ((InetSocketAddress)channel.localAddress()).getHostString(), + "tcp", "client"); } logger.debug("Additional header from hello parsed as {} from {}", parsedHeader, additionalHeader); return new NetconfServerSession(sessionListener, channel, sessionPreferences.getSessionId(), parsedHeader); } - static class AdditionalHeader { + public static class AdditionalHeader { - private static final Pattern pattern = Pattern - .compile("\\[(?[^;]+);(?
[0-9\\.]+)[:/](?[0-9]+);(?[a-z]+)[^\\]]+\\]"); private final String username; private final String address; private final String transport; + private final String sessionIdentifier; - public AdditionalHeader(String addHeaderAsString) { - addHeaderAsString = addHeaderAsString.trim(); - Matcher matcher = pattern.matcher(addHeaderAsString); - Preconditions.checkArgument(matcher.matches(), "Additional header in wrong format %s, expected %s", - addHeaderAsString, pattern); - this.username = matcher.group("username"); - this.address = matcher.group("address"); - this.transport = matcher.group("transport"); - } - - private AdditionalHeader() { - this.username = this.address = "unknown"; - this.transport = "ssh"; + public AdditionalHeader(String userName, String hostAddress, String transport, String sessionIdentifier) { + this.address = hostAddress; + this.username = userName; + this.transport = transport; + this.sessionIdentifier = sessionIdentifier; } String getUsername() { @@ -85,6 +76,10 @@ public class NetconfServerSessionNegotiator extends return transport; } + String getSessionType() { + return sessionIdentifier; + } + @Override public String toString() { final StringBuffer sb = new StringBuffer("AdditionalHeader{"); @@ -95,4 +90,5 @@ public class NetconfServerSessionNegotiator extends return sb.toString(); } } + } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/util/AdditionalHeaderUtil.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/util/AdditionalHeaderUtil.java new file mode 100644 index 0000000000..5c630dd343 --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/util/AdditionalHeaderUtil.java @@ -0,0 +1,41 @@ +/* + * 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.impl.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiator.AdditionalHeader; + +import com.google.common.base.Preconditions; + +public class AdditionalHeaderUtil { + + private static final Pattern pattern = Pattern + .compile("\\[(?[^;]+);(?
[0-9\\.]+)[:/](?[0-9]+);(?[a-z]+)[^\\]]+\\]"); + private static final Pattern customHeaderPattern = Pattern + .compile("\\[(?[^;]+);(?
[0-9\\.]+)[:/](?[0-9]+);(?[a-z]+);(?[a-z]+)[^\\]]+\\]"); + + public static AdditionalHeader fromString(String additionalHeader) { + additionalHeader = additionalHeader.trim(); + Matcher matcher = pattern.matcher(additionalHeader); + Matcher matcher2 = customHeaderPattern.matcher(additionalHeader); + Preconditions.checkArgument(matcher.matches(), "Additional header in wrong format %s, expected %s", + additionalHeader, pattern); + String username = matcher.group("username"); + String address = matcher.group("address"); + String transport = matcher.group("transport"); + String sessionIdentifier = "client"; + if (matcher2.matches()) { + sessionIdentifier = matcher2.group("sessionIdentifier"); + } + return new AdditionalHeader(username, address, transport, sessionIdentifier); + } + +} diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/AdditionalHeaderParserTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/AdditionalHeaderParserTest.java index 2f8fac23f5..97d9a98b57 100644 --- a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/AdditionalHeaderParserTest.java +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/AdditionalHeaderParserTest.java @@ -8,14 +8,16 @@ package org.opendaylight.controller.netconf.impl; import junit.framework.Assert; + import org.junit.Test; +import org.opendaylight.controller.netconf.impl.util.AdditionalHeaderUtil; public class AdditionalHeaderParserTest { @Test public void testParsing() throws Exception { String s = "[netconf;10.12.0.102:48528;ssh;;;;;;]"; - NetconfServerSessionNegotiator.AdditionalHeader header = new NetconfServerSessionNegotiator.AdditionalHeader(s); + NetconfServerSessionNegotiator.AdditionalHeader header = AdditionalHeaderUtil.fromString(s); Assert.assertEquals("netconf", header.getUsername()); Assert.assertEquals("10.12.0.102", header.getAddress()); Assert.assertEquals("ssh", header.getTransport()); @@ -24,7 +26,7 @@ public class AdditionalHeaderParserTest { @Test public void testParsing2() throws Exception { String s = "[tomas;10.0.0.0/10000;tcp;1000;1000;;/home/tomas;;]"; - NetconfServerSessionNegotiator.AdditionalHeader header = new NetconfServerSessionNegotiator.AdditionalHeader(s); + NetconfServerSessionNegotiator.AdditionalHeader header = AdditionalHeaderUtil.fromString(s); Assert.assertEquals("tomas", header.getUsername()); Assert.assertEquals("10.0.0.0", header.getAddress()); Assert.assertEquals("tcp", header.getTransport()); @@ -33,6 +35,6 @@ public class AdditionalHeaderParserTest { @Test(expected = IllegalArgumentException.class) public void testParsingNoUsername() throws Exception { String s = "[10.12.0.102:48528;ssh;;;;;;]"; - new NetconfServerSessionNegotiator.AdditionalHeader(s); + AdditionalHeaderUtil.fromString(s); } } 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 ce5233c494..8d3476f4b8 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 @@ -8,12 +8,31 @@ package org.opendaylight.controller.netconf.impl; -import com.google.common.base.Optional; -import com.google.common.collect.Sets; +import static com.google.common.base.Preconditions.checkNotNull; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.HashedWheelTimer; + +import java.io.DataOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.management.ManagementFactory; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.management.ObjectName; + import org.apache.commons.io.IOUtils; import org.junit.After; import org.junit.AfterClass; @@ -44,31 +63,15 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; -import javax.management.ObjectName; -import java.io.DataOutputStream; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.management.ManagementFactory; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; +import com.google.common.base.Optional; +import com.google.common.collect.Sets; public class ConcurrentClientsTest { private static final int CONCURRENCY = 16; private static EventLoopGroup nettyGroup = new NioEventLoopGroup(); - public static final NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER = new NetconfClientDispatcher( nettyGroup, nettyGroup); + public static final NetconfClientDispatcher NETCONF_CLIENT_DISPATCHER = + new NetconfClientDispatcher( nettyGroup, nettyGroup); @Mock private YangStoreService yangStoreService; diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java index 244e4ba4a9..3a7b7de7a0 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java @@ -7,14 +7,27 @@ */ package org.opendaylight.controller.netconf.it; -import com.google.common.base.Charsets; -import com.google.common.base.Optional; -import com.google.common.collect.Sets; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.util.HashedWheelTimer; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + import junit.framework.Assert; + import org.junit.Before; import org.junit.Test; import org.junit.matchers.JUnitMatchers; @@ -48,20 +61,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; +import com.google.common.base.Charsets; +import com.google.common.base.Optional; +import com.google.common.collect.Sets; public class NetconfMonitoringITTest extends AbstractConfigTest { diff --git a/opendaylight/netconf/netconf-monitoring/pom.xml b/opendaylight/netconf/netconf-monitoring/pom.xml index 31e427191c..8e1e599c71 100644 --- a/opendaylight/netconf/netconf-monitoring/pom.xml +++ b/opendaylight/netconf/netconf-monitoring/pom.xml @@ -79,10 +79,13 @@ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924, org.osgi.util.tracker, + org.opendaylight.yangtools.yang.common, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas, + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210, + org.opendaylight.yangtools.yang.binding, diff --git a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/xml/model/MonitoringSession.java b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/xml/model/MonitoringSession.java index 25fb5d44dc..55aee72fda 100644 --- a/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/xml/model/MonitoringSession.java +++ b/opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/xml/model/MonitoringSession.java @@ -7,13 +7,13 @@ */ package org.opendaylight.controller.netconf.monitoring.xml.model; -import com.google.common.base.Preconditions; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session; - import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlTransient; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session; +import org.opendaylight.yangtools.yang.common.QName; + final class MonitoringSession { @XmlTransient @@ -67,8 +67,17 @@ final class MonitoringSession { @XmlElement(name = "transport") public String getTransport() { - Preconditions.checkState(managementSession.getTransport() == NetconfSsh.class); - return "netconf-ssh"; + try { + QName qName = (QName) managementSession.getTransport().getField("QNAME").get(null); + return qName.getLocalName(); + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { + throw new IllegalArgumentException("Unknown transport type " + managementSession.getTransport(), e); + } + } + + @XmlElement(name= "session-identifier") + public String getSessionType() { + return managementSession.getAugmentation(Session1.class).getSessionIdentifier(); } @XmlElement(name = "username") diff --git a/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java b/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java index cb6e59f83f..1e3f343624 100644 --- a/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java +++ b/opendaylight/netconf/netconf-monitoring/src/test/java/org/opendaylight/controller/netconf/monitoring/xml/JaxBSerializerTest.java @@ -7,13 +7,18 @@ */ package org.opendaylight.controller.netconf.monitoring.xml; -import com.google.common.collect.Lists; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import java.util.Date; + import org.junit.Test; import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService; import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.DomainName; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Host; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.Session1; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.SchemasBuilder; @@ -25,10 +30,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types. import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.ZeroBasedCounter32; import org.w3c.dom.Element; -import java.util.Date; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; +import com.google.common.collect.Lists; public class JaxBSerializerTest { @@ -54,6 +56,8 @@ public class JaxBSerializerTest { private Session getMockSession() { Session mocked = mock(Session.class); + Session1 mockedSession1 = mock(Session1.class); + doReturn("client").when(mockedSession1).getSessionIdentifier(); doReturn(1L).when(mocked).getSessionId(); doReturn(new DateAndTime(new Date().toString())).when(mocked).getLoginTime(); doReturn(new Host(new DomainName("address/port"))).when(mocked).getSourceHost(); @@ -63,6 +67,7 @@ public class JaxBSerializerTest { doReturn(new ZeroBasedCounter32(0L)).when(mocked).getOutRpcErrors(); doReturn(NetconfSsh.class).when(mocked).getTransport(); doReturn("username").when(mocked).getUsername(); + doReturn(mockedSession1).when(mocked).getAugmentation(Session1.class); return mocked; } } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageAdditionalHeader.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageAdditionalHeader.java new file mode 100644 index 0000000000..457e226e01 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageAdditionalHeader.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.messages; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; + +/** + * Additional header can be used with hello message to carry information about + * session's connection. Provided information can be reported via netconf + * monitoring. + *
+ * It has pattern "[username; host-address:port; transport; session-identifier;]"
+ * username - name of account on a remote
+ * host-address - client's IP address
+ * port - port number
+ * transport - tcp, ssh
+ * session-identifier - persister, client
+ * Session-identifier is optional, others mandatory.
+ * 
+ */ +public class NetconfMessageAdditionalHeader { + + private static final String SC = ";"; + + public static String toString(String userName, String hostAddress, String port, String transport, + Optional sessionIdentifier) { + Preconditions.checkNotNull(userName); + Preconditions.checkNotNull(hostAddress); + Preconditions.checkNotNull(port); + Preconditions.checkNotNull(transport); + String identifier = sessionIdentifier.isPresent() ? sessionIdentifier.get() : ""; + return "[" + userName + SC + hostAddress + ":" + port + SC + transport + SC + identifier + SC + "]" + + System.lineSeparator(); + } +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageFactory.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageFactory.java index 891d40cf74..526708ab58 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageFactory.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageFactory.java @@ -8,9 +8,12 @@ package org.opendaylight.controller.netconf.util.messages; -import com.google.common.base.Charsets; -import com.google.common.base.Optional; -import com.google.common.collect.Lists; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.List; + import org.opendaylight.controller.netconf.api.NetconfDeserializerException; import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.xml.XmlUtil; @@ -24,11 +27,9 @@ import org.w3c.dom.Comment; import org.w3c.dom.Document; import org.xml.sax.SAXException; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.List; +import com.google.common.base.Charsets; +import com.google.common.base.Optional; +import com.google.common.collect.Lists; /** * NetconfMessageFactory for (de)serializing DOM documents. @@ -114,7 +115,14 @@ public final class NetconfMessageFactory implements ProtocolMessageFactory../../third-party/com.siemens.ct.exi netconf-monitoring ietf-netconf-monitoring + ietf-netconf-monitoring-extension