<type>xml</type>
<classifier>features</classifier>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>odl-mdsal-model-inventory</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<groupId>org.opendaylight.netconf</groupId>
<artifactId>sal-netconf-connector</artifactId>
</dependency>
- <dependency>
- <groupId>org.opendaylight.controller.model</groupId>
- <artifactId>model-inventory</artifactId>
- <version>1.7.0-SNAPSHOT</version>
- </dependency>
<dependency>
<groupId>org.opendaylight.netconf</groupId>
<artifactId>netconf-topology</artifactId>
<version>1.4.0-SNAPSHOT</version>
<packaging>feature</packaging>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-artifacts</artifactId>
+ <version>${project.version}</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-artifacts</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
<dependencies>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>odl-aaa-encryption-service</artifactId>
+ <!-- FIXME: version declaration should be coming from aaa-artifacts -->
+ <version>0.7.0-SNAPSHOT</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-aaa-netconf-plugin</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-aaa-netconf-plugin-no-cluster</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-config-netconf-connector</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-all</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-api</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-client</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-impl</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-mapping-api</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-mdsal</artifactId>
- <version>1.7.0-SNAPSHOT</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-monitoring</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-netty-util</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-notifications-api</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-notifications-impl</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-ssh</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-tcp</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-netconf-util</artifactId>
- <version>${project.version}</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
- <dependency>
- <groupId>org.opendaylight.aaa</groupId>
- <artifactId>aaa-encrypt-service</artifactId>
- <version>0.7.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.aaa</groupId>
- <artifactId>aaa-encrypt-service</artifactId>
- <version>0.7.0-SNAPSHOT</version>
- <classifier>config</classifier>
- <type>xml</type>
- </dependency>
</dependencies>
</project>
<name>OpenDaylight :: Netconf :: Netty Util</name>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netconf-artifacts</artifactId>
+ <version>${project.version}</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-artifacts</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
<dependencies>
<dependency>
<groupId>org.apache.karaf.features</groupId>
<scope>runtime</scope>
</dependency>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>odl-netconf-api</artifactId>
- <version>${project.version}</version>
+ <groupId>org.opendaylight.odlparent</groupId>
+ <artifactId>odl-netty-4</artifactId>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>odl-aaa-encryption-service</artifactId>
+ <!-- FIXME: version declaration should be coming from aaa-artifacts -->
+ <version>0.7.0-SNAPSHOT</version>
<type>xml</type>
<classifier>features</classifier>
</dependency>
+
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>odl-netconf-mapping-api</artifactId>
- <version>${project.version}</version>
+ <artifactId>odl-netconf-api</artifactId>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
- <artifactId>odl-netconf-util</artifactId>
- <version>${project.version}</version>
+ <artifactId>odl-netconf-mapping-api</artifactId>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
- <groupId>org.opendaylight.odlparent</groupId>
- <artifactId>odl-netty-4</artifactId>
- <version>2.0.5</version>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>odl-netconf-util</artifactId>
<type>xml</type>
<classifier>features</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netconf-netty-util</artifactId>
- <version>${project.version}</version>
</dependency>
</dependencies>
-</project>
\ No newline at end of file
+</project>
import org.opendaylight.aaa.api.CredentialAuth;
import org.opendaylight.aaa.api.PasswordCredentials;
import org.opendaylight.netconf.auth.AuthProvider;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* AuthProvider implementation delegating to AAA CredentialAuth<PasswordCredentials> instance.
*/
-public final class CredentialServiceAuthProvider implements AuthProvider, AutoCloseable {
+public final class CredentialServiceAuthProvider implements AuthProvider {
private static final Logger LOG = LoggerFactory.getLogger(CredentialServiceAuthProvider.class);
// FIXME CredentialAuth is generic and it causes warnings during compilation
// Maybe there should be a PasswordCredentialAuth implements CredentialAuth<PasswordCredentials>
- private volatile CredentialAuth<PasswordCredentials> nullableCredService;
- private final ServiceTracker<CredentialAuth, CredentialAuth> listenerTracker;
+ private final CredentialAuth<PasswordCredentials> credService;
- public CredentialServiceAuthProvider(final BundleContext bundleContext) {
-
- final ServiceTrackerCustomizer<CredentialAuth, CredentialAuth> customizer =
- new ServiceTrackerCustomizer<CredentialAuth, CredentialAuth>() {
- @Override
- public CredentialAuth addingService(final ServiceReference<CredentialAuth> reference) {
- LOG.trace("Credential service {} added", reference);
- nullableCredService = bundleContext.getService(reference);
- return nullableCredService;
- }
-
- @Override
- public void modifiedService(final ServiceReference<CredentialAuth> reference,
- final CredentialAuth service) {
- LOG.trace("Replacing modified Credential service {}", reference);
- nullableCredService = service;
- }
-
- @Override
- public void removedService(final ServiceReference<CredentialAuth> reference, final CredentialAuth service) {
- LOG.trace("Removing Credential service {}. "
- + "This AuthProvider will fail to authenticate every time", reference);
- synchronized (CredentialServiceAuthProvider.this) {
- nullableCredService = null;
- }
- }
- };
- listenerTracker = new ServiceTracker<>(bundleContext, CredentialAuth.class, customizer);
- listenerTracker.open();
+ public CredentialServiceAuthProvider(final CredentialAuth<PasswordCredentials> credService) {
+ this.credService = credService;
}
/**
* Authenticate user. This implementation tracks CredentialAuth<PasswordCredentials>
- * and delegates the decision to it. If the service is not available, IllegalStateException is thrown.
+ * and delegates the decision to it.
*/
@Override
- public synchronized boolean authenticated(final String username, final String password) {
- if (nullableCredService == null) {
- LOG.warn("Cannot authenticate user '{}', Credential service is missing", username);
- throw new IllegalStateException("Credential service is not available");
- }
+ public boolean authenticated(final String username, final String password) {
Claim claim;
try {
- claim = nullableCredService.authenticate(new PasswordCredentialsWrapper(username, password));
+ claim = credService.authenticate(new PasswordCredentialsWrapper(username, password));
} catch (AuthenticationException e) {
LOG.debug("Authentication failed for user '{}' : {}", username, e);
return false;
return true;
}
- /**
- * Invoked by blueprint.
- */
- @Override
- public void close() {
- listenerTracker.close();
- nullableCredService = null;
- }
-
private static final class PasswordCredentialsWrapper implements PasswordCredentials {
private final String username;
private final String password;
xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
odl:use-default-for-reference-types="true">
- <bean id="credentialServiceAuthProvider"
- class="org.opendaylight.aaa.odl.CredentialServiceAuthProvider"
- destroy-method="close">
- <argument ref="blueprintBundleContext"/>
+ <reference id="credentialAuth" interface="org.opendaylight.aaa.api.CredentialAuth" odl:type="default" />
+
+ <bean id="credentialServiceAuthProvider" class="org.opendaylight.aaa.odl.CredentialServiceAuthProvider">
+ <argument ref="credentialAuth"/>
</bean>
<service ref="credentialServiceAuthProvider" interface="org.opendaylight.netconf.auth.AuthProvider"
odl:type="netconf-auth-provider"/>
-</blueprint>
\ No newline at end of file
+</blueprint>
package org.opendaylight.aaa.odl;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import org.opendaylight.aaa.api.Claim;
import org.opendaylight.aaa.api.CredentialAuth;
import org.opendaylight.aaa.api.PasswordCredentials;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Filter;
-import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
@Mock
private CredentialAuth<PasswordCredentials> credAuth;
- @Mock
- private BundleContext ctx;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- doReturn(mock(Filter.class)).when(ctx).createFilter(anyString());
}
- @Test(expected = IllegalStateException.class)
- public void testAuthenticatedNoDelegate() throws Exception {
- CredentialServiceAuthProvider credentialServiceAuthProvider = new CredentialServiceAuthProvider(ctx);
- credentialServiceAuthProvider.authenticated("user", "pwd");
- }
@Test
public void testAuthenticatedTrue() throws Exception {
ServiceReference serviceRef = mock(ServiceReference.class);
ServiceListenerAnswer answer = new ServiceListenerAnswer();
- doAnswer(answer).when(ctx).addServiceListener(any(ServiceListener.class), anyString());
Claim claim = mock(Claim.class);
doReturn("domain").when(claim).domain();
doReturn(claim).when(credAuth).authenticate(any(PasswordCredentials.class));
- doReturn(credAuth).when(ctx).getService(serviceRef);
- CredentialServiceAuthProvider credentialServiceAuthProvider = new CredentialServiceAuthProvider(ctx);
-
- answer.serviceListener.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, serviceRef));
- assertNotNull(answer.serviceListener);
-
+ CredentialServiceAuthProvider credentialServiceAuthProvider = new CredentialServiceAuthProvider(credAuth);
assertTrue(credentialServiceAuthProvider.authenticated("user", "pwd"));
}
@Test
public void testAuthenticatedFalse() throws Exception {
- ServiceReference serviceRef = mock(ServiceReference.class);
-
- ServiceListenerAnswer answer = new ServiceListenerAnswer();
- doAnswer(answer).when(ctx).addServiceListener(any(ServiceListener.class), anyString());
-
doThrow(AuthenticationException.class).when(credAuth).authenticate(any(PasswordCredentials.class));
-
- doReturn(credAuth).when(ctx).getService(serviceRef);
- CredentialServiceAuthProvider credentialServiceAuthProvider = new CredentialServiceAuthProvider(ctx);
-
- answer.serviceListener.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, serviceRef));
- assertNotNull(answer.serviceListener);
-
+ CredentialServiceAuthProvider credentialServiceAuthProvider = new CredentialServiceAuthProvider(credAuth);
assertFalse(credentialServiceAuthProvider.authenticated("user", "pwd"));
}
<groupId>org.opendaylight.netconf</groupId>
<artifactId>netconf-client</artifactId>
</dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcpkix-jdk15on</artifactId>
- </dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcprov-jdk15on</artifactId>
- </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import java.util.Collection;
import java.util.function.Consumer;
import javax.annotation.Nullable;
public void onFailure(Throwable throwable) {
LOG.warn("Unable to update netconf state", throwable);
}
- });
+ }, MoreExecutors.directExecutor());
}
private static void updateSessions(WriteTransaction tx, Collection<Session> sessions) {
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
public void onFailure(Throwable throwable) {
LOG.warn("Unable to clear streams", throwable);
}
- });
+ }, MoreExecutors.directExecutor());
notificationRegistration.close();
}
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
public void onFailure(final Throwable throwable) {
LOG.warn("Failed to update modules state", throwable);
}
- });
+ }, MoreExecutors.directExecutor());
}
private ModulesState createModuleStateFromModules(final Set<Module> modules) {
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
ImmutableList.of(netconfNode.getPort().getValue().toString()));
attributes.put(NetconfConsoleConstants.STATUS,
ImmutableList.of(netconfNode.getConnectionStatus().name()));
- attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES,
- netconfNode.getAvailableCapabilities().getAvailableCapability().stream()
- .map(AvailableCapability::getCapability).collect(Collectors.toList()));
+ if (netconfNode.getConnectionStatus().equals(
+ NetconfNodeConnectionStatus.ConnectionStatus.Connected)) {
+ attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES,
+ netconfNode.getAvailableCapabilities().getAvailableCapability().stream()
+ .map(AvailableCapability::getCapability).collect(Collectors.toList()));
+ } else {
+ attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES, Collections.singletonList(""));
+ }
device.put(node.getNodeId().getValue(), attributes);
}
}
ImmutableList.of(netconfNode.getPort().getValue().toString()));
attributes.put(NetconfConsoleConstants.STATUS,
ImmutableList.of(netconfNode.getConnectionStatus().name()));
- attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES,
- netconfNode.getAvailableCapabilities().getAvailableCapability().stream()
- .map(AvailableCapability::getCapability).collect(Collectors.toList()));
+ if (netconfNode.getConnectionStatus().equals(NetconfNodeConnectionStatus.ConnectionStatus.Connected)) {
+ attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES,
+ netconfNode.getAvailableCapabilities().getAvailableCapability().stream()
+ .map(AvailableCapability::getCapability).collect(Collectors.toList()));
+ } else {
+ attributes.put(NetconfConsoleConstants.AVAILABLE_CAPABILITIES, Collections.singletonList(""));
+ }
device.put(node.getNodeId().getValue(), attributes);
}
}
LOG.error("Failed to created NetconfNode={}", netconfNode);
throw new RuntimeException(throwable);
}
- });
+ }, MoreExecutors.directExecutor());
}
@Override
LOG.error("Failed to updated NetconfNode={}", netconfNode);
throw new RuntimeException(throwable);
}
- });
+ }, MoreExecutors.directExecutor());
return "NETCONF node: " + netconfNodeId + " updated successfully.";
} else {
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
public void onSuccess(final SshFutureListener<AuthFuture> result) {
sshAuthListener = result;
}
- });
+ }, MoreExecutors.directExecutor());
doReturn(authFuture).when(authHandler).authenticate(any(ClientSession.class));
}
public void onSuccess(final SshFutureListener<ConnectFuture> result) {
sshConnectListener = result;
}
- });
+ }, MoreExecutors.directExecutor());
doReturn(connectFuture).when(sshClient).connect("usr", remoteAddress);
}
doReturn(true).when(asyncOut).isClosed();
result.operationComplete(mockedReadFuture);
}
- });
+ }, MoreExecutors.directExecutor());
final IoOutputStream asyncIn = getMockedIoOutputStream();
final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
.removeListener(Matchers.<SshFutureListener<IoReadFuture>>any());
result.operationComplete(mockedReadFuture);
}
- });
+ }, MoreExecutors.directExecutor());
final IoOutputStream asyncIn = getMockedIoOutputStream();
final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
doReturn(true).when(asyncIn).isClosed();
result.operationComplete(ioWriteFuture);
}
- });
+ }, MoreExecutors.directExecutor());
final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
final ClientSession sshSession = getMockedSshSession(subsystemChannel);
doReturn(true).when(closeFuture).isClosed();
result.operationComplete(closeFuture);
}
- });
+ }, MoreExecutors.directExecutor());
doReturn(closeFuture).when(sshSession).close(false);
doReturn(subsystemChannel).when(sshSession).createSubsystemChannel(anyString());
public void onSuccess(final SshFutureListener<OpenFuture> result) {
sshChannelOpenListener = result;
}
- });
+ }, MoreExecutors.directExecutor());
doReturn(asyncOut).when(subsystemChannel).getAsyncOut();
public void onSuccess(final SshFutureListener<IoWriteFuture> result) {
result.operationComplete(ioWriteFuture);
}
- });
+ }, MoreExecutors.directExecutor());
doReturn(ioWriteFuture).when(mock).write(any(Buffer.class));
doReturn(false).when(mock).isClosed();
public void onSuccess(final SshFutureListener<IoReadFuture> result) {
result.operationComplete(ioReadFuture);
}
- });
+ }, MoreExecutors.directExecutor());
doReturn(ioReadFuture).when(mock).read(any(Buffer.class));
doReturn(false).when(mock).isClosed();
<groupId>org.opendaylight.mdsal.model</groupId>
<artifactId>ietf-inet-types-2013-07-15</artifactId>
</dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcpkix-jdk15on</artifactId>
- </dependency>
- <dependency>
- <groupId>org.bouncycastle</groupId>
- <artifactId>bcprov-jdk15on</artifactId>
- </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import io.netty.util.concurrent.EventExecutor;
import java.util.Collection;
import java.util.HashMap;
public void onFailure(@Nonnull final Throwable throwable) {
LOG.error("Unable to initialize netconf-topology, {}", throwable);
}
- });
+ }, MoreExecutors.directExecutor());
LOG.debug("Registering datastore listener");
return dataBroker.registerDataTreeChangeListener(
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
import io.netty.util.concurrent.EventExecutor;
import java.math.BigDecimal;
import java.net.InetSocketAddress;
public void onFailure(@Nullable final Throwable throwable) {
LOG.error("{}: Connector failed, {}", remoteDeviceId, throwable);
}
- });
+ }, MoreExecutors.directExecutor());
}
@SuppressWarnings("checkstyle:IllegalCatch")
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
public void onFailure(@Nonnull final Throwable throwable) {
sender.tell(throwable, getSelf());
}
- });
+ }, MoreExecutors.directExecutor());
}
private void invokeSlaveRpc(final SchemaPath schemaPath, final NormalizedNodeMessage normalizedNodeMessage,
public void onFailure(@Nonnull final Throwable throwable) {
recipient.tell(throwable, getSelf());
}
- });
+ }, MoreExecutors.directExecutor());
}
private void registerSlaveMountPoint(final ActorRef masterReference) {
public void onFailure(@Nonnull final Throwable throwable) {
LOG.error("{}: Failed to register mount point: {}", id, throwable);
}
- });
+ }, MoreExecutors.directExecutor());
}
private DOMRpcService getDOMRpcService(final ActorRef masterReference) {
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
public void onFailure(@Nonnull final Throwable throwable) {
sender.tell(throwable, self);
}
- });
+ }, MoreExecutors.directExecutor());
}
private void exists(final YangInstanceIdentifier path, final LogicalDatastoreType store, final ActorRef sender,
public void onFailure(@Nonnull final Throwable throwable) {
sender.tell(throwable, self);
}
- });
+ }, MoreExecutors.directExecutor());
}
}
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import javax.annotation.Nonnull;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
import org.opendaylight.netconf.topology.singleton.messages.transactions.DeleteRequest;
import org.opendaylight.netconf.topology.singleton.messages.transactions.MergeRequest;
import org.opendaylight.netconf.topology.singleton.messages.transactions.PutRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitFailedReply;
import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitReply;
import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
class WriteAdapter {
+
+ private static final Logger LOG = LoggerFactory.getLogger(WriteAdapter.class);
+
private final DOMDataWriteTransaction tx;
WriteAdapter(final DOMDataWriteTransaction tx) {
@Override
public void onFailure(@Nonnull final Throwable throwable) {
- requester.tell(throwable, self);
+ requester.tell(new SubmitFailedReply(throwable), self);
}
- });
+ }, MoreExecutors.directExecutor());
}
+ @SuppressWarnings("checkstyle:IllegalCatch")
public void handle(final Object message, final ActorRef sender, final ActorContext context, final ActorRef self) {
- if (message instanceof MergeRequest) {
- final MergeRequest mergeRequest = (MergeRequest) message;
- final NormalizedNodeMessage data = mergeRequest.getNormalizedNodeMessage();
- tx.merge(mergeRequest.getStore(), data.getIdentifier(), data.getNode());
- } else if (message instanceof PutRequest) {
- final PutRequest putRequest = (PutRequest) message;
- final NormalizedNodeMessage data = putRequest.getNormalizedNodeMessage();
- tx.put(putRequest.getStore(), data.getIdentifier(), data.getNode());
- } else if (message instanceof DeleteRequest) {
- final DeleteRequest deleteRequest = (DeleteRequest) message;
- tx.delete(deleteRequest.getStore(), deleteRequest.getPath());
- } else if (message instanceof CancelRequest) {
- cancel(context, sender, self);
- } else if (message instanceof SubmitRequest) {
- submit(sender, self, context);
+ // we need to catch everything, since an unchecked exception can be thrown from the underlying parse.
+ // TODO Maybe we should store it and fail the submit immediately?.
+ try {
+ if (message instanceof MergeRequest) {
+ final MergeRequest mergeRequest = (MergeRequest) message;
+ final NormalizedNodeMessage data = mergeRequest.getNormalizedNodeMessage();
+ tx.merge(mergeRequest.getStore(), data.getIdentifier(), data.getNode());
+ } else if (message instanceof PutRequest) {
+ final PutRequest putRequest = (PutRequest) message;
+ final NormalizedNodeMessage data = putRequest.getNormalizedNodeMessage();
+ tx.put(putRequest.getStore(), data.getIdentifier(), data.getNode());
+ } else if (message instanceof DeleteRequest) {
+ final DeleteRequest deleteRequest = (DeleteRequest) message;
+ tx.delete(deleteRequest.getStore(), deleteRequest.getPath());
+ } else if (message instanceof CancelRequest) {
+ cancel(context, sender, self);
+ } else if (message instanceof SubmitRequest) {
+ submit(sender, self, context);
+ }
+
+ } catch (final RuntimeException exception) {
+ LOG.error("Write command has failed.", exception);
}
}
}
} else {
if (success instanceof SubmitFailedReply) {
LOG.error("{}: Transaction was not submitted because already closed.", id);
+ settableFuture.setException(((SubmitFailedReply) success).getThrowable());
+ return;
}
+
settableFuture.set(null);
}
}
import java.io.Serializable;
/**
- * Message sent from master back to the slave when submit is not performed, tx is closed.
+ * Message sent from master back to the slave when submit fails, with the offending exception attached.
*/
public class SubmitFailedReply implements Serializable {
private static final long serialVersionUID = 1L;
+
+ private final Throwable throwable;
+
+ public SubmitFailedReply(final Throwable throwable) {
+ this.throwable = throwable;
+ }
+
+ public Throwable getThrowable() {
+ return throwable;
+ }
}
import org.opendaylight.netconf.topology.singleton.messages.transactions.MergeRequest;
import org.opendaylight.netconf.topology.singleton.messages.transactions.PutRequest;
import org.opendaylight.netconf.topology.singleton.messages.transactions.ReadRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitFailedReply;
import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitReply;
import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitRequest;
import org.opendaylight.yangtools.yang.common.QName;
when(deviceReadWriteTx.submit()).thenReturn(Futures.immediateFailedCheckedFuture(cause));
final Future<Object> submitFuture = Patterns.ask(actorRef, new SubmitRequest(), TIMEOUT);
final Object result = Await.result(submitFuture, TIMEOUT.duration());
- Assert.assertEquals(cause, result);
+ Assert.assertTrue(result instanceof SubmitFailedReply);
+ Assert.assertEquals(cause, ((SubmitFailedReply)result).getThrowable());
verify(deviceReadWriteTx).submit();
}
import org.opendaylight.netconf.topology.singleton.messages.transactions.DeleteRequest;
import org.opendaylight.netconf.topology.singleton.messages.transactions.MergeRequest;
import org.opendaylight.netconf.topology.singleton.messages.transactions.PutRequest;
+import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitFailedReply;
import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitReply;
import org.opendaylight.netconf.topology.singleton.messages.transactions.SubmitRequest;
import org.opendaylight.yangtools.yang.common.QName;
when(deviceWriteTx.submit()).thenReturn(Futures.immediateFailedCheckedFuture(cause));
final Future<Object> submitFuture = Patterns.ask(actorRef, new SubmitRequest(), TIMEOUT);
final Object result = Await.result(submitFuture, TIMEOUT.duration());
- Assert.assertEquals(cause, result);
+ Assert.assertTrue(result instanceof SubmitFailedReply);
+ Assert.assertEquals(cause, ((SubmitFailedReply)result).getThrowable());
verify(deviceWriteTx).submit();
}
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
import io.netty.util.concurrent.EventExecutor;
import java.io.File;
import java.math.BigDecimal;
LOG.error("Connector for : " + nodeId.getValue() + " failed");
// remove this node from active connectors?
}
- });
+ }, MoreExecutors.directExecutor());
return future;
}
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import javax.annotation.Nullable;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
public void onFailure(final Throwable throwable) {
LOG.error("Node {} creation failed: {}", instanceName, throwable);
}
- });
+ }, MoreExecutors.directExecutor());
return node;
}
}
\ No newline at end of file
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import io.netty.util.concurrent.EventExecutor;
import java.util.Collection;
import javax.annotation.Nonnull;
public void onFailure(final Throwable throwable) {
LOG.error("Unable to initialize netconf-topology, {}", throwable);
}
- });
+ }, MoreExecutors.directExecutor());
LOG.debug("Registering datastore listener");
datastoreListenerRegistration =
}
};
- Futures.addCallback(sourceResolverFuture, resolvedSourceCallback);
+ Futures.addCallback(sourceResolverFuture, resolvedSourceCallback, MoreExecutors.directExecutor());
}
private void registerToBaseNetconfStream(final NetconfDeviceRpc deviceRpc,
LOG.warn("Unable to subscribe to base notification stream. Schemas will not be reloaded on the fly",
throwable);
}
- });
+ }, MoreExecutors.directExecutor());
}
private boolean shouldListenOnSchemaChange(final NetconfSessionPreferences remoteSessionCapabilities) {
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
if (previousKeepalive != null && !previousKeepalive.isDone()) {
onFailure(new IllegalStateException("Previous keepalive timed out"));
} else {
- Futures.addCallback(currentDeviceRpc.invokeRpc(PATH, KEEPALIVE_PAYLOAD), this);
+ Futures.addCallback(currentDeviceRpc.invokeRpc(PATH, KEEPALIVE_PAYLOAD), this,
+ MoreExecutors.directExecutor());
}
} catch (NullPointerException e) {
LOG.debug("{}: Skipping keepalive while reconnecting", id);
final NormalizedNode<?, ?> input) {
final CheckedFuture<DOMRpcResult, DOMRpcException> domRpcResultDOMRpcExceptionCheckedFuture =
deviceRpc.invokeRpc(type, input);
- Futures.addCallback(domRpcResultDOMRpcExceptionCheckedFuture, resetKeepaliveTask);
+ Futures.addCallback(domRpcResultDOMRpcExceptionCheckedFuture, resetKeepaliveTask,
+ MoreExecutors.directExecutor());
final RequestTimeoutTask timeoutTask = new RequestTimeoutTask(domRpcResultDOMRpcExceptionCheckedFuture);
executor.schedule(timeoutTask, defaultRequestTimeoutMillis, TimeUnit.MILLISECONDS);
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
throw new IllegalStateException(
id + " Transaction(" + txType + ") not committed correctly", throwable);
}
- });
-
+ }, MoreExecutors.directExecutor());
}
private static Node getNodeWithId(final RemoteDeviceId id) {
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public void onFailure(final Throwable throwable) {
listeners.forEach(listener -> listener.onTransactionFailed(AbstractWriteTx.this, throwable));
}
- });
+ }, MoreExecutors.directExecutor());
return result;
}
DocumentedException.ErrorSeverity.ERROR);
transformed.setException(exception);
}
- });
+ }, MoreExecutors.directExecutor());
return transformed;
}
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
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.DOMDataReadOnlyTransaction;
+import org.opendaylight.mdsal.common.api.MappingCheckedFuture;
import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
import org.opendaylight.netconf.sal.connect.netconf.util.NetconfRpcFutureCallback;
import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.yangtools.util.concurrent.MappingCheckedFuture;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.slf4j.Logger;
public CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> read(
final LogicalDatastoreType store, final YangInstanceIdentifier path) {
switch (store) {
- case CONFIGURATION: {
+ case CONFIGURATION:
return readConfigurationData(path);
- }
- case OPERATIONAL: {
+ case OPERATIONAL:
return readOperationalData(path);
- }
- default: {
+ default:
LOG.info("Unknown datastore type: {}.", store);
- }
+ throw new IllegalArgumentException(String.format(
+ "%s, Cannot read data %s for %s datastore, unknown datastore type", id, path, store));
}
- throw new IllegalArgumentException(String.format(
- "%s, Cannot read data %s for %s datastore, unknown datastore type", id, path, store));
}
@Override
public CheckedFuture<Boolean, ReadFailedException> exists(final LogicalDatastoreType store,
final YangInstanceIdentifier path) {
- final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> data = read(store, path);
- final ListenableFuture<Boolean> result =
- Futures.transform(data, (Optional<NormalizedNode<?, ?>> optionalNode) ->
- optionalNode != null && optionalNode.isPresent());
+ final ListenableFuture<Boolean> result = Futures.transform(read(store, path),
+ optionalNode -> optionalNode != null && optionalNode.isPresent(), MoreExecutors.directExecutor());
return MappingCheckedFuture.create(result, ReadFailedException.MAPPER);
}
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
import javax.annotation.Nullable;
import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
// cleanup is trying to do unlock, but this will fail
cleanup();
}
- });
+ }, MoreExecutors.directExecutor());
return txResult;
}
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade.KeepaliveDOMRpcService;
final ListenableFuture<DOMRpcResult> future =
rpc.invokeRpc(toPath(NETCONF_LOCK_QNAME), getLockContent(datastore));
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
public ListenableFuture<DOMRpcResult> lockCandidate(final FutureCallback<DOMRpcResult> callback) {
final ListenableFuture<DOMRpcResult> future =
rpc.invokeRpc(toPath(NETCONF_LOCK_QNAME), getLockContent(NETCONF_CANDIDATE_QNAME));
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
public ListenableFuture<DOMRpcResult> lockRunning(final FutureCallback<DOMRpcResult> callback) {
final ListenableFuture<DOMRpcResult> future =
rpc.invokeRpc(toPath(NETCONF_LOCK_QNAME), getLockContent(NETCONF_RUNNING_QNAME));
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
final ListenableFuture<DOMRpcResult> future =
rpc.invokeRpc(toPath(NETCONF_UNLOCK_QNAME), getUnLockContent(datastore));
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
public ListenableFuture<DOMRpcResult> unlockRunning(final FutureCallback<DOMRpcResult> callback) {
final ListenableFuture<DOMRpcResult> future =
rpc.invokeRpc(toPath(NETCONF_UNLOCK_QNAME), getUnLockContent(NETCONF_RUNNING_QNAME));
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
public ListenableFuture<DOMRpcResult> unlockCandidate(final FutureCallback<DOMRpcResult> callback) {
final ListenableFuture<DOMRpcResult> future =
rpc.invokeRpc(toPath(NETCONF_UNLOCK_QNAME), getUnLockContent(NETCONF_CANDIDATE_QNAME));
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
Preconditions.checkNotNull(callback);
final ListenableFuture<DOMRpcResult> future = rpc.invokeRpc(toPath(NETCONF_DISCARD_CHANGES_QNAME), null);
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
final ListenableFuture<DOMRpcResult> future = rpc.invokeRpc(
toPath(NetconfMessageTransformUtil.NETCONF_COMMIT_QNAME), NetconfMessageTransformUtil.COMMIT_RPC_CONTENT);
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
final ListenableFuture<DOMRpcResult> future = rpc.invokeRpc(
toPath(NetconfMessageTransformUtil.NETCONF_VALIDATE_QNAME), getValidateContent(datastore));
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
final ListenableFuture<DOMRpcResult> future = rpc.invokeRpc(
toPath(NetconfMessageTransformUtil.NETCONF_COPY_CONFIG_QNAME), getCopyConfigContent(source, target));
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
NetconfMessageTransformUtil.wrap(NETCONF_GET_CONFIG_QNAME, getSourceNode(datastore)));
}
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
final ListenableFuture<DOMRpcResult> future = rpc.invokeRpc(toPath(NETCONF_EDIT_CONFIG_QNAME),
getEditConfigContent(datastore, editStructure, modifyAction, rollback));
- Futures.addCallback(future, callback);
+ Futures.addCallback(future, callback, MoreExecutors.directExecutor());
return future;
}
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import java.util.concurrent.Future;
import org.opendaylight.aaa.encrypt.AAAEncryptionService;
LOG.error("add-netconf-node RPC: Unable to add netconf node.", exception);
futureResult.setException(exception);
}
- });
+ }, MoreExecutors.directExecutor());
}
}
--- /dev/null
+# NetConf TestTool
+
+This project is used to simulate NetConf devices in order to test NetConf
+south-bound plugin and applications using this plugin. *netconf-testtool*
+project is designed as versatile java library to be used for custom NetConf device
+test simulations.
+
+## How to use as standalone application
+* compile project
+* start org.opendaylight.netconf.test.tool.Main
+
+## How to use it in your code
+* Use maven dependency in your project
+----
+<dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>netconf-testtool-core</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+</dependency>
+----
+* Prepare configuration - models are loaded by classloader
+ from classpath.
+----
+Set<String> models = ImmutableSet.of(
+ "models/iana-afn-safi@2013-07-04.yang",
+ "models/ietf-inet-types@2013-07-15.yang",
+ "models/ietf-netconf@2011-06-01.yang",
+ "models/ietf-netconf-monitoring@2010-10-04.yang",
+ "models/ietf-netconf-monitoring-extension@2013-12-10.yang",
+ "models/ietf-yang-library@2016-06-21.yang",
+ "models/ietf-yang-types@2013-07-15.yang",
+ "models/nc-notifications@2008-07-14.yang",
+ "models/notifications@2008-07-14.yang",
+ ...
+);
+----
+* Prepare list of capabilities
+----
+Set<String> capabilities = ImmutableSet.of(
+ "urn:ietf:params:netconf:base:1.0",
+ "urn:ietf:params:netconf:base:1.1",
+ ...
+);
+----
+* Override RPC mapping provider org.opendaylight.netconf.test.tool.rpchandler.RpcHandler
+----
+public class RpcHandlerImpl implements RpcHandler {
+ @Override
+ public Optional<Document> getResponse(XmlElement rpcElement) {
+ ...
+ return response;
+ }
+}
+
+----
+* Start NetConf device simulator in your code
+----
+public class Main {
+
+ public static void main(String[] args) {
+ Configuration configuration = new ConfigurationBuilder()
+ .setModels(models)
+ .setCapabilities(capabilities)
+ .setRpcHandler(new RpcHandlerImpl())
+ .build();
+ NetConfDeviceSimulator netConfDeviceSimulator =
+ new NetConfDeviceSimulator(configuration);
+ netConfDeviceSimulator.start();
+ }
+
+}
+----
import org.apache.karaf.features.internal.model.Feature;
import org.apache.karaf.features.internal.model.Features;
import org.apache.karaf.features.internal.model.JaxbUtil;
+import org.opendaylight.netconf.test.tool.config.Configuration;
+import org.opendaylight.netconf.test.tool.config.ConfigurationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
.getLogger(Logger.ROOT_LOGGER_NAME);
root.setLevel(params.debug ? Level.DEBUG : Level.INFO);
- final NetconfDeviceSimulator netconfDeviceSimulator = new NetconfDeviceSimulator(params.threadPoolSize);
+ final Configuration configuration = new ConfigurationBuilder().from(params).build();
+ final NetconfDeviceSimulator netconfDeviceSimulator = new NetconfDeviceSimulator(configuration);
try {
LOG.debug("Trying to start netconf test-tool with parameters {}", params);
- final List<Integer> openDevices = netconfDeviceSimulator.start(params);
+ final List<Integer> openDevices = netconfDeviceSimulator.start();
if (openDevices.size() == 0) {
LOG.error("Failed to start any simulated devices, exiting...");
System.exit(1);
import org.opendaylight.controller.config.util.capability.Capability;
import org.opendaylight.controller.config.util.capability.YangModuleCapability;
import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
-import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
import org.opendaylight.netconf.impl.NetconfServerDispatcherImpl;
import org.opendaylight.netconf.impl.NetconfServerSessionNegotiatorFactory;
import org.opendaylight.netconf.impl.SessionIdProvider;
import org.opendaylight.netconf.ssh.SshProxyServer;
import org.opendaylight.netconf.ssh.SshProxyServerConfiguration;
import org.opendaylight.netconf.ssh.SshProxyServerConfigurationBuilder;
+import org.opendaylight.netconf.test.tool.config.Configuration;
import org.opendaylight.netconf.test.tool.customrpc.SettableOperationProvider;
+import org.opendaylight.netconf.test.tool.operations.OperationsProvider;
+import org.opendaylight.netconf.test.tool.rpchandler.SettableOperationRpcProvider;
+import org.opendaylight.netconf.test.tool.schemacache.SchemaSourceCache;
import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
private final List<SshProxyServer> sshWrappers = Lists.newArrayList();
private final ScheduledExecutorService minaTimerExecutor;
private final ExecutorService nioExecutor;
+ private final Configuration configuration;
private SchemaContext schemaContext;
private boolean sendFakeSchema = false;
- public NetconfDeviceSimulator(final int threadPoolSize) {
- this(new NioEventLoopGroup(), new HashedWheelTimer(),
- Executors.newScheduledThreadPool(threadPoolSize,
- new ThreadFactoryBuilder().setNameFormat("netconf-ssh-server-mina-timers-%d").build()),
- ThreadUtils.newFixedThreadPool("netconf-ssh-server-nio-group", threadPoolSize));
- }
-
- private NetconfDeviceSimulator(final NioEventLoopGroup eventExecutors, final HashedWheelTimer hashedWheelTimer,
- final ScheduledExecutorService minaTimerExecutor, final ExecutorService nioExecutor) {
- this.nettyThreadgroup = eventExecutors;
- this.hashedWheelTimer = hashedWheelTimer;
- this.minaTimerExecutor = minaTimerExecutor;
- this.nioExecutor = nioExecutor;
+ public NetconfDeviceSimulator(Configuration configuration) {
+ this.configuration = configuration;
+ this.nettyThreadgroup = new NioEventLoopGroup();
+ this.hashedWheelTimer = new HashedWheelTimer();
+ this.minaTimerExecutor = Executors.newScheduledThreadPool(configuration.getThreadPoolSize(),
+ new ThreadFactoryBuilder().setNameFormat("netconf-ssh-server-mina-timers-%d").build());
+ this.nioExecutor = ThreadUtils
+ .newFixedThreadPool("netconf-ssh-server-nio-group", configuration.getThreadPoolSize());
}
private NetconfServerDispatcherImpl createDispatcher(final Set<Capability> capabilities,
- final SchemaSourceProvider<YangTextSchemaSource> sourceProvider, final TesttoolParameters params) {
+ final SchemaSourceProvider<YangTextSchemaSource> sourceProvider) {
final Set<Capability> transformedCapabilities = Sets.newHashSet(Collections2.transform(capabilities, input -> {
if (sendFakeSchema) {
final SessionIdProvider idProvider = new SessionIdProvider();
final NetconfOperationServiceFactory aggregatedNetconfOperationServiceFactory = createOperationServiceFactory(
- sourceProvider, params, transformedCapabilities, monitoringService1, idProvider);
+ sourceProvider, transformedCapabilities, monitoringService1, idProvider);
- final Set<String> serverCapabilities = params.exi
- ? NetconfServerSessionNegotiatorFactory.DEFAULT_BASE_CAPABILITIES
- : Sets.newHashSet(XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0,
- XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_1);
+ final Set<String> serverCapabilities = configuration.getCapabilities();
final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new TesttoolNegotiationFactory(
- hashedWheelTimer, aggregatedNetconfOperationServiceFactory, idProvider, params.generateConfigsTimeout,
+ hashedWheelTimer, aggregatedNetconfOperationServiceFactory, idProvider,
+ configuration.getGenerateConfigsTimeout(),
monitoringService1, serverCapabilities);
final NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer =
}
private NetconfOperationServiceFactory createOperationServiceFactory(
- final SchemaSourceProvider<YangTextSchemaSource> sourceProvider, final TesttoolParameters params,
+ final SchemaSourceProvider<YangTextSchemaSource> sourceProvider,
final Set<Capability> transformedCapabilities, final NetconfMonitoringService monitoringService1,
final SessionIdProvider idProvider) {
final AggregatedNetconfOperationServiceFactory aggregatedNetconfOperationServiceFactory =
new AggregatedNetconfOperationServiceFactory();
final NetconfOperationServiceFactory operationProvider;
- if (params.mdSal) {
+ if (configuration.isMdSal()) {
+ LOG.info("using MdsalOperationProvider.");
operationProvider = new MdsalOperationProvider(
idProvider, transformedCapabilities, schemaContext, sourceProvider);
- } else {
+ } else if (configuration.isXmlConfigurationProvided()) {
+ LOG.info("using SimulatedOperationProvider.");
operationProvider = new SimulatedOperationProvider(idProvider, transformedCapabilities,
- Optional.fromNullable(params.notificationFile),
- Optional.fromNullable(params.initialConfigXMLFile));
+ Optional.fromNullable(configuration.getNotificationFile()),
+ Optional.fromNullable(configuration.getInitialConfigXMLFile()));
+ } else {
+ LOG.info("using OperationsProvider.");
+ operationProvider = new OperationsProvider(idProvider, transformedCapabilities);
}
new NetconfMonitoringOperationService(monitoringService1));
aggregatedNetconfOperationServiceFactory.onAddNetconfOperationServiceFactory(operationProvider);
aggregatedNetconfOperationServiceFactory.onAddNetconfOperationServiceFactory(monitoringService);
- if (params.rpcConfig != null) {
- final SettableOperationProvider settableService = new SettableOperationProvider(params.rpcConfig);
+ if (configuration.getRpcConfigFile() != null) {
+ final SettableOperationProvider settableService =
+ new SettableOperationProvider(configuration.getRpcConfigFile());
+ aggregatedNetconfOperationServiceFactory.onAddNetconfOperationServiceFactory(settableService);
+ } else {
+ final SettableOperationRpcProvider settableService =
+ new SettableOperationRpcProvider(configuration.getRpcHandler());
aggregatedNetconfOperationServiceFactory.onAddNetconfOperationServiceFactory(settableService);
}
return aggregatedNetconfOperationServiceFactory;
}
- public List<Integer> start(final TesttoolParameters params) {
+ public List<Integer> start() {
LOG.info("Starting {}, {} simulated devices starting on port {}",
- params.deviceCount, params.ssh ? "SSH" : "TCP", params.startingPort);
+ configuration.getDeviceCount(), configuration.isSsh() ? "SSH" : "TCP", configuration.getStartingPort());
final SharedSchemaRepository schemaRepo = new SharedSchemaRepository("netconf-simulator");
- final Set<Capability> capabilities = parseSchemasToModuleCapabilities(params, schemaRepo);
+ final Set<Capability> capabilities = parseSchemasToModuleCapabilities(schemaRepo);
final NetconfServerDispatcherImpl dispatcher = createDispatcher(capabilities,
- sourceIdentifier -> schemaRepo.getSchemaSource(sourceIdentifier, YangTextSchemaSource.class), params);
+ sourceIdentifier -> schemaRepo.getSchemaSource(sourceIdentifier, YangTextSchemaSource.class));
- int currentPort = params.startingPort;
+ int currentPort = configuration.getStartingPort();
final List<Integer> openDevices = Lists.newArrayList();
// Generate key to temp folder
final PEMGeneratorHostKeyProvider keyPairProvider = getPemGeneratorHostKeyProvider();
- for (int i = 0; i < params.deviceCount; i++) {
+ for (int i = 0; i < configuration.getDeviceCount(); i++) {
if (currentPort > 65535) {
LOG.warn("Port cannot be greater than 65535, stopping further attempts.");
break;
}
- final InetSocketAddress address = getAddress(params.ip, currentPort);
+ final InetSocketAddress address = getAddress(configuration.getIp(), currentPort);
final ChannelFuture server;
- if (params.ssh) {
+ if (configuration.isSsh()) {
final InetSocketAddress bindingAddress = InetSocketAddress.createUnresolved("0.0.0.0", currentPort);
final LocalAddress tcpLocalAddress = new LocalAddress(address.toString());
openDevices.add(currentPort - 1);
}
- if (openDevices.size() == params.deviceCount) {
+ if (openDevices.size() == configuration.getDeviceCount()) {
LOG.info("All simulated devices started successfully from port {} to {}",
- params.startingPort, currentPort - 1);
+ configuration.getStartingPort(), currentPort - 1);
} else if (openDevices.size() == 0) {
LOG.warn("No simulated devices started.");
} else {
}
}
- private Set<Capability> parseSchemasToModuleCapabilities(final TesttoolParameters params,
- final SharedSchemaRepository consumer) {
+ private Set<Capability> parseSchemasToModuleCapabilities(final SharedSchemaRepository consumer) {
final Set<SourceIdentifier> loadedSources = Sets.newHashSet();
-
consumer.registerSchemaSourceListener(TextToASTTransformer.create(consumer, consumer));
-
consumer.registerSchemaSourceListener(new SchemaSourceListener() {
@Override
public void schemaSourceEncountered(final SchemaSourceRepresentation schemaSourceRepresentation) {}
public void schemaSourceUnregistered(final PotentialSchemaSource<?> potentialSchemaSource) {}
});
- if (params.schemasDir != null) {
+ if (configuration.getSchemasDir() != null) {
+ LOG.info("Loading models from directory.");
final FilesystemSchemaSourceCache<YangTextSchemaSource> cache = new FilesystemSchemaSourceCache<>(
- consumer, YangTextSchemaSource.class, params.schemasDir);
+ consumer, YangTextSchemaSource.class, configuration.getSchemasDir());
+ consumer.registerSchemaSourceListener(cache);
+ } else if (configuration.getModels() != null) {
+ LOG.info("Loading models from classpath.");
+ final SchemaSourceCache<YangTextSchemaSource> cache = new SchemaSourceCache<>(
+ consumer, YangTextSchemaSource.class, configuration.getModels());
consumer.registerSchemaSourceListener(cache);
+ } else {
+ LOG.info("Custom module loading skipped.");
}
addDefaultSchemas(consumer);
nettyThreadgroup.shutdownGracefully();
minaTimerExecutor.shutdownNow();
nioExecutor.shutdownNow();
- // close Everything
}
+
}
import java.util.regex.Pattern;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
+import org.opendaylight.netconf.test.tool.config.Configuration;
+import org.opendaylight.netconf.test.tool.config.ConfigurationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
while (true) {
root.warn("Starting scale test with {} devices", params.deviceCount);
final ScheduledFuture timeoutGuardFuture = EXECUTOR.schedule(new TimeoutGuard(), TIMEOUT, TimeUnit.MINUTES);
- final NetconfDeviceSimulator netconfDeviceSimulator = new NetconfDeviceSimulator(params.threadAmount);
+ final Configuration configuration = new ConfigurationBuilder().from(params).build();
+ final NetconfDeviceSimulator netconfDeviceSimulator = new NetconfDeviceSimulator(configuration);
try {
- final List<Integer> openDevices = netconfDeviceSimulator.start(params);
+ final List<Integer> openDevices = netconfDeviceSimulator.start();
if (openDevices.size() == 0) {
root.error("Failed to start any simulated devices, exiting...");
System.exit(1);
package org.opendaylight.netconf.test.tool;
-public class TestToolUtils {
+import java.io.InputStream;
+
+public final class TestToolUtils {
public static String getMac(long mac) {
final StringBuilder builder = new StringBuilder(Long.toString(mac, 16));
-
for (int i = builder.length(); i < 12; i++) {
builder.insert(0, "0");
}
-
for (int j = builder.length() - 2; j >= 2; j -= 2) {
builder.insert(j, ":");
}
-
return builder.toString();
}
+
+ public static InputStream getDataAsStream(final String path) {
+ return TestToolUtils.class.getClassLoader().getResourceAsStream(path);
+ }
+
}
@Arg(dest = "time-out")
public long timeOut;
private InputStream stream;
-
@Arg(dest = "ip")
public String ip;
-
@Arg(dest = "thread-pool-size")
public int threadPoolSize;
@Arg(dest = "rpc-config")
--- /dev/null
+/*
+ * 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.netconf.test.tool.config;
+
+import com.google.common.collect.ImmutableSet;
+import java.io.File;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.netconf.test.tool.rpchandler.RpcHandler;
+import org.opendaylight.netconf.test.tool.rpchandler.RpcHandlerDefault;
+
+
+public class Configuration {
+
+ public static final Set<String> DEFAULT_BASE_CAPABILITIES_EXI = ImmutableSet.of(
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_1,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_CAPABILITY_EXI_1_0
+ );
+
+ public static final Set<String> DEFAULT_BASE_CAPABILITIES = ImmutableSet.of(
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_0,
+ XmlNetconfConstants.URN_IETF_PARAMS_NETCONF_BASE_1_1
+ );
+
+ private int generateConfigsTimeout = (int) TimeUnit.MINUTES.toMillis(30);
+ private int threadPoolSize = 8;
+ private int startingPort = 17830;
+ private int deviceCount = 1;
+ private boolean ssh = true;
+ private String ip = "0.0.0.0";
+
+ private Set<String> models;
+ private Set<String> capabilities = DEFAULT_BASE_CAPABILITIES_EXI;
+ private RpcHandler rpcHandler = new RpcHandlerDefault();
+
+ @Deprecated
+ private boolean mdSal = false;
+
+ @Deprecated
+ private File rpcConfigFile;
+
+ @Deprecated
+ private File notificationFile;
+
+ @Deprecated
+ private File initialConfigXMLFile;
+
+ @Deprecated
+ private File schemasDir;
+
+ public Configuration() {
+ }
+
+ public int getThreadPoolSize() {
+ return threadPoolSize;
+ }
+
+ public void setThreadPoolSize(int threadPoolSize) {
+ this.threadPoolSize = threadPoolSize;
+ }
+
+ public int getStartingPort() {
+ return startingPort;
+ }
+
+ public void setStartingPort(int startingPort) {
+ this.startingPort = startingPort;
+ }
+
+ public int getDeviceCount() {
+ return deviceCount;
+ }
+
+ public void setDeviceCount(int deviceCount) {
+ this.deviceCount = deviceCount;
+ }
+
+ public int getGenerateConfigsTimeout() {
+ return generateConfigsTimeout;
+ }
+
+ public void setGenerateConfigsTimeout(int generateConfigsTimeout) {
+ this.generateConfigsTimeout = generateConfigsTimeout;
+ }
+
+ public boolean isSsh() {
+ return ssh;
+ }
+
+ public void setSsh(boolean ssh) {
+ this.ssh = ssh;
+ }
+
+ public String getIp() {
+ return ip;
+ }
+
+ public void setIp(String ip) {
+ this.ip = ip;
+ }
+
+ public Set<String> getModels() {
+ return models;
+ }
+
+ public void setModels(Set<String> models) {
+ this.models = models;
+ }
+
+ public Set<String> getCapabilities() {
+ return capabilities;
+ }
+
+ public void setCapabilities(Set<String> capabilities) {
+ this.capabilities = capabilities;
+ }
+
+ public RpcHandler getRpcHandler() {
+ return rpcHandler;
+ }
+
+ public void setRpcHandler(RpcHandler rpcHandler) {
+ this.rpcHandler = rpcHandler;
+ }
+
+ @Deprecated
+ public boolean isMdSal() {
+ return mdSal;
+ }
+
+ @Deprecated
+ public void setMdSal(boolean mdSal) {
+ this.mdSal = mdSal;
+ }
+
+ @Deprecated
+ public File getRpcConfigFile() {
+ return rpcConfigFile;
+ }
+
+ @Deprecated
+ public void setRpcConfigFile(File rpcConfigFile) {
+ this.rpcConfigFile = rpcConfigFile;
+ }
+
+ @Deprecated
+ public File getNotificationFile() {
+ return notificationFile;
+ }
+
+ @Deprecated
+ public void setNotificationFile(File notificationFile) {
+ this.notificationFile = notificationFile;
+ }
+
+ @Deprecated
+ public File getInitialConfigXMLFile() {
+ return initialConfigXMLFile;
+ }
+
+ @Deprecated
+ public void setInitialConfigXMLFile(File initialConfigXMLFile) {
+ this.initialConfigXMLFile = initialConfigXMLFile;
+ }
+
+ @Deprecated
+ public boolean isXmlConfigurationProvided() {
+ return initialConfigXMLFile != null && notificationFile != null;
+ }
+
+ @Deprecated
+ public File getSchemasDir() {
+ return schemasDir;
+ }
+
+ @Deprecated
+ public void setSchemasDir(File schemasDir) {
+ this.schemasDir = schemasDir;
+ }
+
+}
--- /dev/null
+/*
+ * 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.netconf.test.tool.config;
+
+import java.io.File;
+import java.util.Set;
+import org.opendaylight.netconf.test.tool.TesttoolParameters;
+import org.opendaylight.netconf.test.tool.rpchandler.RpcHandler;
+
+public class ConfigurationBuilder {
+
+ private Configuration configuration;
+
+ public ConfigurationBuilder() {
+ this.configuration = new Configuration();
+ }
+
+ public ConfigurationBuilder setThreadPoolSize(int threadPoolSize) {
+ this.configuration.setThreadPoolSize(threadPoolSize);
+ return this;
+ }
+
+ public ConfigurationBuilder setGenerateConfigsTimeout(int generateConfigsTimeout) {
+ this.configuration.setGenerateConfigsTimeout(generateConfigsTimeout);
+ return this;
+ }
+
+ public ConfigurationBuilder setModels(Set<String> models) {
+ this.configuration.setModels(models);
+ return this;
+ }
+
+ public ConfigurationBuilder setCapabilities(Set<String> capabilities) {
+ this.configuration.setCapabilities(capabilities);
+ return this;
+ }
+
+ public ConfigurationBuilder setStartingPort(int startingPort) {
+ this.configuration.setStartingPort(startingPort);
+ return this;
+ }
+
+ public ConfigurationBuilder setDeviceCount(int deviceCount) {
+ this.configuration.setDeviceCount(deviceCount);
+ return this;
+ }
+
+ public ConfigurationBuilder setSsh(boolean ssh) {
+ this.configuration.setSsh(ssh);
+ return this;
+ }
+
+ public ConfigurationBuilder setIp(String ip) {
+ this.configuration.setIp(ip);
+ return this;
+ }
+
+ public ConfigurationBuilder setRpcMapping(RpcHandler rpcHandler) {
+ this.configuration.setRpcHandler(rpcHandler);
+ return this;
+ }
+
+ @Deprecated
+ public ConfigurationBuilder setMdSal(boolean mdSal) {
+ this.configuration.setMdSal(mdSal);
+ return this;
+ }
+
+ @Deprecated
+ public ConfigurationBuilder setRpcConfigFile(File rpcConfigFile) {
+ this.configuration.setRpcConfigFile(rpcConfigFile);
+ return this;
+ }
+
+ @Deprecated
+ public ConfigurationBuilder setInitialConfigXMLFile(File initialConfigXMLFile) {
+ this.configuration.setInitialConfigXMLFile(initialConfigXMLFile);
+ return this;
+ }
+
+ @Deprecated
+ public ConfigurationBuilder setNotificationFile(File notificationFile) {
+ this.configuration.setNotificationFile(notificationFile);
+ return this;
+ }
+
+ public ConfigurationBuilder from(Configuration configuration) {
+ this.configuration.setThreadPoolSize(configuration.getThreadPoolSize());
+ this.configuration.setGenerateConfigsTimeout(configuration.getGenerateConfigsTimeout());
+ this.configuration.setModels(configuration.getModels());
+ this.configuration.setCapabilities(configuration.getCapabilities());
+ this.configuration.setStartingPort(configuration.getStartingPort());
+ this.configuration.setDeviceCount(configuration.getDeviceCount());
+ this.configuration.setSsh(configuration.isSsh());
+ this.configuration.setIp(configuration.getIp());
+ this.configuration.setRpcHandler(configuration.getRpcHandler());
+ this.configuration.setMdSal(configuration.isMdSal());
+ this.configuration.setRpcConfigFile(configuration.getRpcConfigFile());
+ this.configuration.setInitialConfigXMLFile(configuration.getInitialConfigXMLFile());
+ this.configuration.setNotificationFile(configuration.getNotificationFile());
+ this.configuration.setSchemasDir(configuration.getSchemasDir());
+ return this;
+ }
+
+ public ConfigurationBuilder from(TesttoolParameters testtoolParameters) {
+ this.configuration.setGenerateConfigsTimeout(testtoolParameters.generateConfigsTimeout);
+ this.configuration.setStartingPort(testtoolParameters.startingPort);
+ this.configuration.setDeviceCount(testtoolParameters.deviceCount);
+ this.configuration.setSsh(testtoolParameters.ssh);
+ this.configuration.setIp(testtoolParameters.ip);
+ this.configuration.setMdSal(testtoolParameters.mdSal);
+ this.configuration.setRpcConfigFile(testtoolParameters.rpcConfig);
+ this.configuration.setInitialConfigXMLFile(testtoolParameters.initialConfigXMLFile);
+ this.configuration.setNotificationFile(testtoolParameters.notificationFile);
+ this.configuration.setSchemasDir(testtoolParameters.schemasDir);
+ return this;
+ }
+
+ public Configuration build() {
+ return configuration;
+ }
+
+}
--- /dev/null
+/*
+ * 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.netconf.test.tool.operations;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+import java.util.Collections;
+import java.util.Set;
+import org.opendaylight.controller.config.util.capability.Capability;
+import org.opendaylight.netconf.api.monitoring.CapabilityListener;
+import org.opendaylight.netconf.impl.SessionIdProvider;
+import org.opendaylight.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.netconf.test.tool.rpc.DataList;
+import org.opendaylight.netconf.test.tool.rpc.SimulatedCommit;
+import org.opendaylight.netconf.test.tool.rpc.SimulatedCreateSubscription;
+import org.opendaylight.netconf.test.tool.rpc.SimulatedDiscardChanges;
+import org.opendaylight.netconf.test.tool.rpc.SimulatedEditConfig;
+import org.opendaylight.netconf.test.tool.rpc.SimulatedGet;
+import org.opendaylight.netconf.test.tool.rpc.SimulatedGetConfig;
+import org.opendaylight.netconf.test.tool.rpc.SimulatedLock;
+import org.opendaylight.netconf.test.tool.rpc.SimulatedUnLock;
+
+
+public class OperationsProvider implements NetconfOperationServiceFactory {
+ private final Set<Capability> caps;
+ private final SimulatedOperationService simulatedOperationService;
+
+ public OperationsProvider(final SessionIdProvider idProvider,
+ final Set<Capability> caps) {
+ this.caps = caps;
+ simulatedOperationService = new SimulatedOperationService(
+ idProvider.getCurrentSessionId());
+ }
+
+ @Override
+ public Set<Capability> getCapabilities() {
+ return caps;
+ }
+
+ @Override
+ public AutoCloseable registerCapabilityListener(
+ final CapabilityListener listener) {
+ listener.onCapabilitiesChanged(caps, Collections.<Capability>emptySet());
+ return new AutoCloseable() {
+ @Override
+ public void close() throws Exception {
+ }
+ };
+ }
+
+ @Override
+ public NetconfOperationService createService(
+ final String netconfSessionIdForReporting) {
+ return simulatedOperationService;
+ }
+
+ static class SimulatedOperationService implements NetconfOperationService {
+ private final long currentSessionId;
+
+ SimulatedOperationService(final long currentSessionId) {
+ this.currentSessionId = currentSessionId;
+ }
+
+ @Override
+ public Set<NetconfOperation> getNetconfOperations() {
+ final DataList storage = new DataList();
+ final SimulatedGet sGet = new SimulatedGet(String.valueOf(currentSessionId), storage);
+ final SimulatedEditConfig sEditConfig = new SimulatedEditConfig(String.valueOf(currentSessionId), storage);
+ final SimulatedGetConfig sGetConfig = new SimulatedGetConfig(
+ String.valueOf(currentSessionId), storage, Optional.absent());
+ final SimulatedCommit sCommit = new SimulatedCommit(String.valueOf(currentSessionId));
+ final SimulatedLock sLock = new SimulatedLock(String.valueOf(currentSessionId));
+ final SimulatedUnLock sUnlock = new SimulatedUnLock(String.valueOf(currentSessionId));
+ final SimulatedCreateSubscription sCreateSubs = new SimulatedCreateSubscription(
+ String.valueOf(currentSessionId), Optional.absent());
+ final SimulatedDiscardChanges sDiscardChanges = new SimulatedDiscardChanges(
+ String.valueOf(currentSessionId));
+ return Sets.newHashSet(
+ sGet, sGetConfig, sEditConfig, sCommit, sLock, sUnlock, sCreateSubs, sDiscardChanges);
+ }
+
+ @Override
+ public void close() {
+ }
+
+ }
+}
--- /dev/null
+/*
+ * 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.netconf.test.tool.rpchandler;
+
+import java.util.Optional;
+import org.opendaylight.controller.config.util.xml.XmlElement;
+import org.w3c.dom.Document;
+
+public interface RpcHandler {
+
+ Optional<Document> getResponse(XmlElement rpcElement);
+
+}
--- /dev/null
+/*
+ * 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.netconf.test.tool.rpchandler;
+
+import java.util.Optional;
+import org.opendaylight.controller.config.util.xml.XmlElement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+public class RpcHandlerDefault implements RpcHandler {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RpcHandlerDefault.class);
+
+ @Override
+ public Optional<Document> getResponse(XmlElement rpcElement) {
+ LOG.info("getResponse: {}", rpcElement.toString());
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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.netconf.test.tool.rpchandler;
+
+import java.util.Collections;
+import java.util.Set;
+import org.opendaylight.controller.config.util.capability.Capability;
+import org.opendaylight.netconf.api.monitoring.CapabilityListener;
+import org.opendaylight.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.netconf.mapping.api.NetconfOperationServiceFactory;
+
+public class SettableOperationRpcProvider implements NetconfOperationServiceFactory {
+
+ private final RpcHandler rpcHandler;
+
+ public SettableOperationRpcProvider(RpcHandler rpcHandler) {
+ this.rpcHandler = rpcHandler;
+ }
+
+ @Override
+ public Set<Capability> getCapabilities() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public AutoCloseable registerCapabilityListener(final CapabilityListener listener) {
+ return () -> {
+ //no op
+ };
+ }
+
+ @Override
+ public NetconfOperationService createService(final String netconfSessionIdForReporting) {
+ return new SettableOperationService(rpcHandler);
+ }
+
+ private static class SettableOperationService implements NetconfOperationService {
+
+ private final SettableRpc rpc;
+
+ private SettableOperationService(RpcHandler rpcHandler) {
+ this.rpc = new SettableRpc(rpcHandler);
+ }
+
+ @Override
+ public Set<NetconfOperation> getNetconfOperations() {
+ return Collections.singleton(rpc);
+ }
+
+ @Override
+ public void close() {
+ // no op
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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.netconf.test.tool.rpchandler;
+
+import java.util.Optional;
+import org.opendaylight.controller.config.util.xml.DocumentedException;
+import org.opendaylight.controller.config.util.xml.XmlElement;
+import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.netconf.mapping.api.NetconfOperationChainedExecution;
+import org.w3c.dom.Document;
+
+/**
+ * {@link NetconfOperation} implementation. It can be configured to intercept rpcs with defined input
+ * and reply with defined output. If input isn't defined, rpc handling is delegated to the subsequent
+ * {@link NetconfOperation} which is able to handle it.
+ */
+class SettableRpc implements NetconfOperation {
+
+ private final RpcHandler rpcHandler;
+
+ SettableRpc(RpcHandler rpcHandler) {
+ this.rpcHandler = rpcHandler;
+ }
+
+ @Override
+ public HandlingPriority canHandle(final Document message) throws DocumentedException {
+ return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.increasePriority(1000);
+ }
+
+ @Override
+ public Document handle(final Document requestMessage, final NetconfOperationChainedExecution subsequentOperation)
+ throws DocumentedException {
+ final XmlElement requestElement = XmlElement.fromDomDocument(requestMessage);
+ final XmlElement rpcElement = requestElement.getOnlyChildElement();
+ final String msgId = requestElement.getAttribute(XmlNetconfConstants.MESSAGE_ID);
+ final Optional<Document> response = rpcHandler.getResponse(rpcElement);
+ if (response.isPresent()) {
+ final Document document = response.get();
+ checkForError(document);
+ document.getDocumentElement().setAttribute(XmlNetconfConstants.MESSAGE_ID, msgId);
+ return document;
+ } else if (subsequentOperation.isExecutionTermination()) {
+ throw new DocumentedException("Mapping not found " + XmlUtil.toString(requestMessage),
+ DocumentedException.ErrorType.APPLICATION, DocumentedException.ErrorTag.OPERATION_NOT_SUPPORTED,
+ DocumentedException.ErrorSeverity.ERROR);
+ } else {
+ return subsequentOperation.execute(requestMessage);
+ }
+ }
+
+ private void checkForError(final Document document) throws DocumentedException {
+ final XmlElement rpcReply = XmlElement.fromDomDocument(document);
+ if (rpcReply.getOnlyChildElementOptionally("rpc-error").isPresent()) {
+ throw DocumentedException.fromXMLDocument(document);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.netconf.test.tool.schemacache;
+
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+
+public class ModelData {
+
+ private SourceIdentifier id;
+ private String path;
+
+ public ModelData(SourceIdentifier id, String path) {
+ this.id = id;
+ this.path = path;
+ }
+
+ public SourceIdentifier getId() {
+ return id;
+ }
+
+ public String getPath() {
+ return path;
+ }
+}
--- /dev/null
+/*
+ * 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.netconf.test.tool.schemacache;
+
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.opendaylight.netconf.test.tool.TestToolUtils;
+import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource.Costs;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
+import org.opendaylight.yangtools.yang.model.repo.util.AbstractSchemaSourceCache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Cache implementation that stores schemas in form of files under provided folder.
+ */
+public final class SchemaSourceCache<T extends SchemaSourceRepresentation>
+ extends AbstractSchemaSourceCache<T> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SchemaSourceCache.class);
+
+ public static final Pattern CACHED_FILE_PATTERN =
+ Pattern.compile(
+ ".*/(?<moduleName>[^@]+)" + "(@(?<revision>" + SourceIdentifier.REVISION_PATTERN + "))?.yang");
+
+ private final Class<T> representation;
+ private final Set<String> modelList;
+ private Map<String, ModelData> cachedSchemas;
+
+ public SchemaSourceCache(
+ final SchemaSourceRegistry consumer, final Class<T> representation, final Set<String> modelList) {
+ super(consumer, representation, Costs.LOCAL_IO);
+ this.representation = representation;
+ this.modelList = Preconditions.checkNotNull(modelList);
+ init();
+ }
+
+ /**
+ * Restore cache state.
+ */
+ private void init() {
+ cachedSchemas = new HashMap<>();
+ for (String modelPath: modelList) {
+ Optional<SourceIdentifier> sourceIdentifierOptional = getSourceIdentifier(modelPath);
+ if (sourceIdentifierOptional.isPresent()) {
+ SourceIdentifier sourceIdentifier = sourceIdentifierOptional.get();
+ cachedSchemas.put(sourceIdentifier.toYangFilename(), new ModelData(sourceIdentifier, modelPath));
+ } else {
+ LOG.debug("Skipping caching model {}, cannot restore source identifier from model path,"
+ + " does not match {}", modelPath, CACHED_FILE_PATTERN);
+ }
+ }
+ for (final ModelData cachedSchema : cachedSchemas.values()) {
+ register(cachedSchema.getId());
+ }
+ }
+
+ @Override
+ public synchronized CheckedFuture<? extends T, SchemaSourceException> getSource(
+ final SourceIdentifier sourceIdentifier) {
+ ModelData modelData = cachedSchemas.get(sourceIdentifier.toYangFilename());
+ if (modelData != null) {
+ final SchemaSourceRepresentation restored = restoreAsType(modelData.getId(), modelData.getPath());
+ return Futures.immediateCheckedFuture(representation.cast(restored));
+ } else {
+ LOG.debug("Source {} not found in cache as {}", sourceIdentifier);
+ return Futures.immediateFailedCheckedFuture(new MissingSchemaSourceException("Source not found",
+ sourceIdentifier));
+ }
+ }
+
+ @Override
+ protected synchronized void offer(final T source) {
+ LOG.trace("Source {} offered to cache", source.getIdentifier());
+ }
+
+ private YangTextSchemaSource restoreAsType(final SourceIdentifier sourceIdentifier, final String cachedSource) {
+ return new YangTextSchemaSource(sourceIdentifier) {
+
+ @Override
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper;
+ }
+
+ @Override
+ public InputStream openStream() throws IOException {
+ return TestToolUtils.getDataAsStream(cachedSource);
+ }
+ };
+ }
+
+ private static Optional<SourceIdentifier> getSourceIdentifier(final String fileName) {
+ final Matcher matcher = CACHED_FILE_PATTERN.matcher(fileName);
+ if (matcher.matches()) {
+ final String moduleName = matcher.group("moduleName");
+ final String revision = matcher.group("revision");
+ return Optional.of(RevisionSourceIdentifier.create(moduleName, Optional.fromNullable(revision)));
+ }
+ return Optional.absent();
+ }
+
+}
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public void onFailure(final Throwable throwable) {
LOG.warn("Unable to update modules state", throwable);
}
- });
+ }, MoreExecutors.directExecutor());
}
@Override
public void onFailure(final Throwable throwable) {
LOG.warn("Unable to update modules state", throwable);
}
- });
+ }, MoreExecutors.directExecutor());
}
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Collection;
ret.complete(path, ReadFailedException.MAPPER.apply(e));
}
- });
+ }, MoreExecutors.directExecutor());
}
return ret;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
new RestconfError(ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, throwable.getMessage()))));
waiter.countDown();
}
- });
+ }, MoreExecutors.directExecutor());
waiter.await();
return status.getStatus();
}
final UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder();
- int notificationPort = NOTIFICATION_PORT;
- try {
- final WebSocketServer webSocketServerInstance = WebSocketServer.getInstance();
- notificationPort = webSocketServerInstance.getPort();
- } catch (final NullPointerException e) {
- WebSocketServer.createInstance(NOTIFICATION_PORT);
- }
+
+ final WebSocketServer webSocketServerInstance = WebSocketServer.getInstance(NOTIFICATION_PORT);
+ final int notificationPort = webSocketServerInstance.getPort();
+
final UriBuilder uriToWebsocketServerBuilder = uriBuilder.port(notificationPort).scheme("ws");
- final URI uriToWebsocketServer = uriToWebsocketServerBuilder.replacePath(streamName).build();
- return uriToWebsocketServer;
+ return uriToWebsocketServerBuilder.replacePath(streamName).build();
}
/**
this.broker.registerToListenDataChanges(datastore, scope, listener);
final UriBuilder uriBuilder = uriInfo.getAbsolutePathBuilder();
- int notificationPort = NOTIFICATION_PORT;
- try {
- final WebSocketServer webSocketServerInstance = WebSocketServer.getInstance();
- notificationPort = webSocketServerInstance.getPort();
- } catch (final NullPointerException e) {
- WebSocketServer.createInstance(NOTIFICATION_PORT);
- }
+
+ final WebSocketServer webSocketServerInstance = WebSocketServer.getInstance(NOTIFICATION_PORT);
+ final int notificationPort = webSocketServerInstance.getPort();
+
final UriBuilder uriToWebsocketServerBuilder = uriBuilder.port(notificationPort).scheme("ws");
- final URI uriToWebsocketServer = uriToWebsocketServerBuilder.replacePath(streamName).build();
- return uriToWebsocketServer;
+ return uriToWebsocketServerBuilder.replacePath(streamName).build();
}
@SuppressWarnings("checkstyle:IllegalCatch")
*/
private static <T> T parseEnumTypeParameter(final ContainerNode value, final Class<T> classDescriptor,
final String paramName) {
- final Optional<DataContainerChild<? extends PathArgument, ?>> augNode =
- value.getChild(SAL_REMOTE_AUG_IDENTIFIER);
- if (!augNode.isPresent() && !(augNode instanceof AugmentationNode)) {
+ final Optional<DataContainerChild<? extends PathArgument, ?>> optAugNode = value.getChild(
+ SAL_REMOTE_AUG_IDENTIFIER);
+ if (!optAugNode.isPresent()) {
+ return null;
+ }
+ final DataContainerChild<? extends PathArgument, ?> augNode = optAugNode.get();
+ if (!(augNode instanceof AugmentationNode)) {
return null;
}
- final Optional<DataContainerChild<? extends PathArgument, ?>> enumNode = ((AugmentationNode) augNode.get())
- .getChild(new NodeIdentifier(QName.create(SAL_REMOTE_AUGMENT, paramName)));
+ final Optional<DataContainerChild<? extends PathArgument, ?>> enumNode = ((AugmentationNode) augNode).getChild(
+ new NodeIdentifier(QName.create(SAL_REMOTE_AUGMENT, paramName)));
if (!enumNode.isPresent()) {
return null;
}
instanceDataChildrenByName = ControllerContext.findInstanceDataChildrenByName(listStreamSchemaNode, "events");
final DataSchemaNode eventsSchemaNode = Iterables.getFirst(instanceDataChildrenByName, null);
Preconditions.checkState(eventsSchemaNode instanceof LeafSchemaNode);
- streamNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) eventsSchemaNode).withValue("").build());
+ streamNodeValues.withChild(Builders.leafBuilder((LeafSchemaNode) eventsSchemaNode).build());
return streamNodeValues.build();
}
import org.opendaylight.netconf.sal.restconf.impl.jmx.RestConnectorRuntimeMXBean;
import org.opendaylight.netconf.sal.restconf.impl.jmx.Rpcs;
import org.opendaylight.netconf.sal.streams.websockets.WebSocketServer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
private final DOMRpcService rpcService;
private final DOMNotificationService notificationService;
private final DOMMountPointService mountPointService;
+ private final IpAddress websocketAddress;
private final PortNumber websocketPort;
private final StatisticsRestconfServiceWrapper stats = StatisticsRestconfServiceWrapper.getInstance();
private ListenerRegistration<SchemaContextListener> listenerRegistration;
public RestconfProviderImpl(DOMDataBroker domDataBroker, SchemaService schemaService, DOMRpcService rpcService,
DOMNotificationService notificationService, DOMMountPointService mountPointService,
- PortNumber websocketPort) {
+ IpAddress websocketAddress, PortNumber websocketPort) {
super("Draft02ProviderStatistics", "restconf-connector", null);
this.domDataBroker = Preconditions.checkNotNull(domDataBroker);
this.schemaService = Preconditions.checkNotNull(schemaService);
this.rpcService = Preconditions.checkNotNull(rpcService);
this.notificationService = Preconditions.checkNotNull(notificationService);
this.mountPointService = Preconditions.checkNotNull(mountPointService);
+ this.websocketAddress = Preconditions.checkNotNull(websocketAddress);
this.websocketPort = Preconditions.checkNotNull(websocketPort);
}
ControllerContext.getInstance().setSchemas(schemaService.getGlobalContext());
ControllerContext.getInstance().setMountService(mountPointService);
- this.webSocketServerThread = new Thread(WebSocketServer.createInstance(websocketPort.getValue().intValue()));
+ this.webSocketServerThread = new Thread(WebSocketServer.createInstance(
+ new String(websocketAddress.getValue()), websocketPort.getValue()));
this.webSocketServerThread.setName("Web socket server on port " + websocketPort);
this.webSocketServerThread.start();
private static final Logger LOG = LoggerFactory.getLogger(WebSocketServer.class);
+ private static final String DEFAULT_ADDRESS = "0.0.0.0";
+
private static WebSocketServer instance = null;
+ private final String address;
private final int port;
private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;
- private WebSocketServer(final int port) {
+ private WebSocketServer(final String address, final int port) {
+ this.address = address;
this.port = port;
}
* @param port TCP port used for this server
* @return instance of {@link WebSocketServer}
*/
- public static WebSocketServer createInstance(final int port) {
+ private static WebSocketServer createInstance(final int port) {
+ instance = createInstance(DEFAULT_ADDRESS, port);
+ return instance;
+ }
+
+ public static WebSocketServer createInstance(final String address, final int port) {
Preconditions.checkState(instance == null, "createInstance() has already been called");
+ Preconditions.checkNotNull(address, "Address cannot be null.");
Preconditions.checkArgument(port >= 1024, "Privileged port (below 1024) is not allowed");
- instance = new WebSocketServer(port);
+ instance = new WebSocketServer(address, port);
return instance;
}
return instance;
}
+ /**
+ * Get instance of {@link WebSocketServer} created by {@link #createInstance(int)}.
+ * If an instance doesnt exist create one with the provided fallback port.
+ *
+ * @return instance of {@link WebSocketServer}
+ */
+ public static WebSocketServer getInstance(final int fallbackPort) {
+ if (instance != null) {
+ return instance;
+ }
+
+ LOG.warn("No instance for WebSocketServer found, creating one with a fallback port: {}", fallbackPort);
+ return createInstance(fallbackPort);
+ }
+
/**
* Destroy the existing instance.
*/
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
.childHandler(new WebSocketServerInitializer());
- final Channel channel = serverBootstrap.bind(port).sync().channel();
- LOG.info("Web socket server started at port {}.", port);
+ final Channel channel = serverBootstrap.bind(address, port).sync().channel();
+ LOG.info("Web socket server started at address {}, port {}.", address, port);
channel.closeFuture().sync();
} catch (final InterruptedException e) {
* Stops the web socket server and removes all listeners.
*/
private void stop() {
- LOG.debug("Stopping the web socket server instance on port {}", port);
+ LOG.info("Stopping the web socket server instance on port {}", port);
Notificator.removeAllListeners();
if (bossGroup != null) {
bossGroup.shutdownGracefully();
<cm:property-placeholder persistent-id="org.opendaylight.restconf" update-strategy="reload">
<cm:default-properties>
+ <cm:property name="websocket-address" value="0.0.0.0"/>
<cm:property name="websocket-port" value="8185"/>
</cm:default-properties>
</cm:property-placeholder>
<argument value="${websocket-port}"/>
</bean>
+ <bean id="webSocketAddress" class="org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress">
+ <argument value="${websocket-address}"/>
+ </bean>
+
<bean id="restconfProviderDraft02" class="org.opendaylight.netconf.sal.restconf.impl.RestconfProviderImpl"
init-method="start" destroy-method="close">
<argument ref="domDataBroker"/>
<argument ref="domRpcService"/>
<argument ref="domNotificationService"/>
<argument ref="domMountPointService"/>
+ <argument ref="webSocketAddress"/>
<argument ref="webSocketPort"/>
</bean>
}
private static <T> T parseEnum(final ContainerNode data, final Class<T> clazz, final String paramName) {
- final Optional<DataContainerChild<? extends PathArgument, ?>> augNode = data
- .getChild(RestconfStreamsConstants.SAL_REMOTE_AUG_IDENTIFIER);
- if (!augNode.isPresent() && !(augNode instanceof AugmentationNode)) {
+ final Optional<DataContainerChild<? extends PathArgument, ?>> optAugNode = data.getChild(
+ RestconfStreamsConstants.SAL_REMOTE_AUG_IDENTIFIER);
+ if (!optAugNode.isPresent()) {
return null;
}
- final Optional<DataContainerChild<? extends PathArgument, ?>> enumNode =
- ((AugmentationNode) augNode.get()).getChild(
- new NodeIdentifier(QName.create(RestconfStreamsConstants.SAL_REMOTE_AUGMENT, paramName)));
+ final DataContainerChild<? extends PathArgument, ?> augNode = optAugNode.get();
+ if (!(augNode instanceof AugmentationNode)) {
+ return null;
+ }
+ final Optional<DataContainerChild<? extends PathArgument, ?>> enumNode = ((AugmentationNode) augNode).getChild(
+ new NodeIdentifier(QName.create(RestconfStreamsConstants.SAL_REMOTE_AUGMENT, paramName)));
if (!enumNode.isPresent()) {
return null;
}
# The port for the web socket server.
+#websocket-address=0.0.0.0
#websocket-port=8185