<artifactId>ietf-netconf-monitoring</artifactId>
<version>${netconf.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ietf-netconf-monitoring-extension</artifactId>
+ <version>${netconf.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-persister-impl</artifactId>
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(), //
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,
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;
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 {
long deadline = pollingStart + timeout;
+ String additionalHeader = NetconfMessageAdditionalHeader.toString("unknown", address.getAddress().getHostAddress(),
+ Integer.toString(address.getPort()), "tcp", Optional.of("persister"));
+
Set<String> 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);
--- /dev/null
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>netconf-subsystem</artifactId>
+ <groupId>org.opendaylight.controller</groupId>
+ <version>0.2.3-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>ietf-netconf-monitoring-extension</artifactId>
+ <name>${project.artifactId}</name>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>ietf-netconf-monitoring</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ </dependencies>
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>src/main/yang</yangFilesRootDir>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
+ </codeGeneratorClass>
+ <outputBaseDir>
+ target/generated-sources/monitoring
+ </outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <version>${yangtools.binding.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.7</version>
+ <executions>
+ <execution>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>target/generated-sources/sal</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ 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,
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210,
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
--- /dev/null
+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
<groupId>${project.groupId}</groupId>
<artifactId>ietf-netconf-monitoring</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ietf-netconf-monitoring-extension</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.bgpcep</groupId>
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.
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Optional;
+
public class NetconfClientDispatcher extends AbstractDispatcher<NetconfClientSession, NetconfClientSessionListener> implements Closeable {
private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class);
public NetconfClientDispatcher(EventLoopGroup bossGroup, EventLoopGroup workerGroup) {
super(bossGroup, workerGroup);
timer = new HashedWheelTimer();
- this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer);
+ this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.<String>absent());
+ }
+
+ public NetconfClientDispatcher(EventLoopGroup bossGroup, EventLoopGroup workerGroup, String additionalHeader) {
+ super(bossGroup, workerGroup);
+ timer = new HashedWheelTimer();
+ this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.of(additionalHeader));
}
public Future<NetconfClientSession> createClient(InetSocketAddress address,
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;
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<String> additionalHeader;
+
+ public NetconfClientSessionNegotiatorFactory(Timer timer, Optional<String> additionalHeader) {
this.timer = timer;
+ this.additionalHeader = additionalHeader;
}
private static NetconfMessage loadHelloMessageTemplate() {
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());
}
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;
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;
super(bossGroup, workerGroup);
this.authHandler = authHandler;
this.timer = new HashedWheelTimer();
- this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer);
+ this.negotatorFactory = new NetconfClientSessionNegotiatorFactory(timer, Optional.<String>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<NetconfClientSession> createClient(InetSocketAddress address,
<groupId>${project.groupId}</groupId>
<artifactId>ietf-netconf-monitoring</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ietf-netconf-monitoring-extension</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netconf-util</artifactId>
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,
</Import-Package>
</instructions>
</configuration>
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;
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 {
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<? extends Transport> 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);
}
}
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<NetconfServerSessionPreferences, NetconfServerSession> {
static final Logger logger = LoggerFactory.getLogger(NetconfServerSessionNegotiator.class);
- private static final AdditionalHeader DEFAULT_HEADER = new AdditionalHeader();
-
protected NetconfServerSessionNegotiator(NetconfServerSessionPreferences sessionPreferences,
Promise<NetconfServerSession> promise, Channel channel, Timer timer, SessionListener sessionListener) {
super(sessionPreferences, promise, channel, timer, sessionListener);
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("\\[(?<username>[^;]+);(?<address>[0-9\\.]+)[:/](?<port>[0-9]+);(?<transport>[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() {
return transport;
}
+ String getSessionType() {
+ return sessionIdentifier;
+ }
+
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("AdditionalHeader{");
return sb.toString();
}
}
+
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.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("\\[(?<username>[^;]+);(?<address>[0-9\\.]+)[:/](?<port>[0-9]+);(?<transport>[a-z]+)[^\\]]+\\]");
+ private static final Pattern customHeaderPattern = Pattern
+ .compile("\\[(?<username>[^;]+);(?<address>[0-9\\.]+)[:/](?<port>[0-9]+);(?<transport>[a-z]+);(?<sessionIdentifier>[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);
+ }
+
+}
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());
@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());
@Test(expected = IllegalArgumentException.class)
public void testParsingNoUsername() throws Exception {
String s = "[10.12.0.102:48528;ssh;;;;;;]";
- new NetconfServerSessionNegotiator.AdditionalHeader(s);
+ AdditionalHeaderUtil.fromString(s);
}
}
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;
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;
*/
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;
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 {
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,
</Import-Package>
</instructions>
</configuration>
*/
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
@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")
*/
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;
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 {
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();
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;
}
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.util.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.
+ * <pre>
+ * 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.
+ * </pre>
+ */
+public class NetconfMessageAdditionalHeader {
+
+ private static final String SC = ";";
+
+ public static String toString(String userName, String hostAddress, String port, String transport,
+ Optional<String> 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();
+ }
+}
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;
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.
Comment comment = netconfMessage.getDocument().createComment("clientId:" + clientId.get());
netconfMessage.getDocument().appendChild(comment);
}
- final ByteBuffer msgBytes = Charsets.UTF_8.encode(xmlToString(netconfMessage.getDocument()));
+ ByteBuffer msgBytes;
+ if(netconfMessage.getAdditionalHeader().isPresent()) {
+ String header = netconfMessage.getAdditionalHeader().get();
+ logger.trace("Header of netconf message parsed \n{}", header);
+ msgBytes = Charsets.UTF_8.encode(header + xmlToString(netconfMessage.getDocument()));
+ } else {
+ msgBytes = Charsets.UTF_8.encode(xmlToString(netconfMessage.getDocument()));
+ }
String content = xmlToString(netconfMessage.getDocument());
logger.trace("Putting message \n{}", content);
<module>../../third-party/com.siemens.ct.exi</module>
<module>netconf-monitoring</module>
<module>ietf-netconf-monitoring</module>
+ <module>ietf-netconf-monitoring-extension</module>
</modules>
<profiles>