*/
package org.opendaylight.controller.netconf.it;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anySetOf;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
+import io.netty.channel.local.LocalAddress;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.HashedWheelTimer;
+import io.netty.util.concurrent.GlobalEventExecutor;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
+import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener;
+import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
+import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreServiceImpl;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
-import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
+import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.w3c.dom.Element;
+
+public abstract class AbstractNetconfConfigTest extends AbstractConfigTest {
+
+ public static final String LOOPBACK_ADDRESS = "127.0.0.1";
+ public static final int SERVER_CONNECTION_TIMEOUT_MILLIS = 5000;
-public class AbstractNetconfConfigTest extends AbstractConfigTest {
+ static ModuleFactory[] FACTORIES = { new TestImplModuleFactory(),
+ new DepTestImplModuleFactory(), new NetconfTestImplModuleFactory(),
+ new IdentityTestModuleFactory(), new MultipleDependenciesModuleFactory() };
- protected EventLoopGroup nettyThreadgroup;
+ private EventLoopGroup nettyThreadgroup;
private HashedWheelTimer hashedWheelTimer;
+ private NetconfClientDispatcherImpl clientDispatcher;
+ private Channel serverTcpChannel;
+
+ private NetconfMessage getConfig;
+ private NetconfMessage get;
+
+ /**
+ * @Before in subclasses is called after this method.
+ */
@Before
- public void setUpAbstractNetconfConfigTest() {
+ public void setUpAbstractNetconfConfigTest() throws Exception {
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, FACTORIES));
+
nettyThreadgroup = new NioEventLoopGroup();
hashedWheelTimer = new HashedWheelTimer();
+
+ loadMessages();
+
+ setUpTestInitial();
+
+ final NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
+ factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
+
+ for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getAdditionalServiceFactories()) {
+ factoriesListener.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory);
+ }
+
+ serverTcpChannel = startNetconfTcpServer(factoriesListener);
+ clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
}
+ /**
+ * Called before setUp method is executed, so test classes can set up resources before setUpAbstractNetconfConfigTest method is called.
+ */
+ protected void setUpTestInitial() throws Exception {}
- protected NetconfServerDispatcher createDispatcher(
- NetconfOperationServiceFactoryListenerImpl factoriesListener, SessionMonitoringService sessionMonitoringService,
- DefaultCommitNotificationProducer commitNotifier) {
- SessionIdProvider idProvider = new SessionIdProvider();
+ private void loadMessages() throws Exception {
+ this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
+ this.get = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/get.xml");
+ }
+
+ public NetconfMessage getGetConfig() {
+ return getConfig;
+ }
+
+ public NetconfMessage getGet() {
+ return get;
+ }
+
+ private Channel startNetconfTcpServer(final NetconfOperationServiceFactoryListenerImpl factoriesListener) throws Exception {
+ final NetconfServerDispatcher dispatch = createDispatcher(factoriesListener, getNetconfMonitoringService(), getNotificationProducer());
+
+ final ChannelFuture s;
+ if(getTcpServerAddress() instanceof LocalAddress) {
+ s = dispatch.createLocalServer(((LocalAddress) getTcpServerAddress()));
+ } else {
+ s = dispatch.createServer(((InetSocketAddress) getTcpServerAddress()));
+ }
+ s.await();
+ return s.channel();
+ }
+
+ protected DefaultCommitNotificationProducer getNotificationProducer() {
+ final DefaultCommitNotificationProducer notificationProducer = mock(DefaultCommitNotificationProducer.class);
+ doNothing().when(notificationProducer).close();
+ doNothing().when(notificationProducer).sendCommitNotification(anyString(), any(Element.class), anySetOf(String.class));
+ return notificationProducer;
+ }
+
+ protected Iterable<NetconfOperationServiceFactory> getAdditionalServiceFactories() {
+ return Collections.emptySet();
+ }
+
+ protected SessionMonitoringService getNetconfMonitoringService() throws Exception {
+ final NetconfOperationProvider netconfOperationProvider = mock(NetconfOperationProvider.class);
+ final NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class);
+ doReturn(Collections.<NetconfOperationService>emptySet()).when(snap).getServices();
+ doReturn(snap).when(netconfOperationProvider).openSnapshot(anyString());
+ return new NetconfMonitoringServiceImpl(netconfOperationProvider);
+ }
+
+ protected abstract SocketAddress getTcpServerAddress();
+
+ public NetconfClientDispatcherImpl getClientDispatcher() {
+ return clientDispatcher;
+ }
- NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
- hashedWheelTimer, factoriesListener, idProvider, 5000);
+ private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
+ final Collection<InputStream> yangDependencies = getBasicYangs();
+ return new HardcodedYangStoreService(yangDependencies);
+ }
+
+ static Collection<InputStream> getBasicYangs() throws IOException {
+
+ final List<String> paths = Arrays.asList(
+ "/META-INF/yang/config.yang",
+ "/META-INF/yang/rpc-context.yang",
+ "/META-INF/yang/config-test.yang",
+ "/META-INF/yang/config-test-impl.yang",
+ "/META-INF/yang/test-types.yang",
+ "/META-INF/yang/ietf-inet-types.yang");
- NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
- factoriesListener, commitNotifier, idProvider,
- sessionMonitoringService);
+ final Collection<InputStream> yangDependencies = new ArrayList<>();
+ final List<String> failedToFind = new ArrayList<>();
+ for (final String path : paths) {
+ final InputStream resourceAsStream = NetconfITTest.class.getResourceAsStream(path);
+ if (resourceAsStream == null) {
+ failedToFind.add(path);
+ } else {
+ yangDependencies.add(resourceAsStream);
+ }
+ }
+ assertEquals("Some yang files were not found", Collections.<String>emptyList(), failedToFind);
+ return yangDependencies;
+ }
+
+ protected NetconfServerDispatcher createDispatcher(
+ final NetconfOperationServiceFactoryListenerImpl factoriesListener, final SessionMonitoringService sessionMonitoringService,
+ final DefaultCommitNotificationProducer commitNotifier) {
+ final SessionIdProvider idProvider = new SessionIdProvider();
- NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
- serverNegotiatorFactory, listenerFactory);
+ final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
+ hashedWheelTimer, factoriesListener, idProvider, SERVER_CONNECTION_TIMEOUT_MILLIS, commitNotifier, sessionMonitoringService);
+
+ final NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
+ serverNegotiatorFactory);
return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
}
+ protected HashedWheelTimer getHashedWheelTimer() {
+ return hashedWheelTimer;
+ }
+
+ protected EventLoopGroup getNettyThreadgroup() {
+ return nettyThreadgroup;
+ }
+ /**
+ * @After in subclasses is be called before this.
+ */
@After
- public void cleanUpTimer() {
+ public void cleanUpNetconf() throws Exception {
+ serverTcpChannel.close().await();
hashedWheelTimer.stop();
- nettyThreadgroup.shutdownGracefully();
+ nettyThreadgroup.shutdownGracefully().await();
+ }
+
+ public NetconfClientConfiguration getClientConfiguration(final InetSocketAddress tcpAddress, final int timeout) {
+ final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create();
+ b.withAddress(tcpAddress);
+ b.withSessionListener(new SimpleNetconfClientSessionListener());
+ b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, timeout));
+ b.withConnectionTimeoutMillis(timeout);
+ return b.build();
}
+ public static final class HardcodedYangStoreService implements YangStoreService {
+
+ private final List<InputStream> byteArrayInputStreams;
+
+ public HardcodedYangStoreService(final Collection<? extends InputStream> inputStreams) throws YangStoreException, IOException {
+ byteArrayInputStreams = new ArrayList<>();
+ for (final InputStream inputStream : inputStreams) {
+ assertNotNull(inputStream);
+ final byte[] content = IOUtils.toByteArray(inputStream);
+ final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
+ byteArrayInputStreams.add(byteArrayInputStream);
+ }
+ }
+
+ @Override
+ public YangStoreSnapshot getYangStoreSnapshot() throws YangStoreException {
+ for (final InputStream inputStream : byteArrayInputStreams) {
+ try {
+ inputStream.reset();
+ } catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ final YangParserImpl yangParser = new YangParserImpl();
+ final SchemaContext schemaContext = yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(byteArrayInputStreams).values()));
+ final YangStoreServiceImpl yangStoreService = new YangStoreServiceImpl(new SchemaContextProvider() {
+ @Override
+ public SchemaContext getSchemaContext() {
+ return schemaContext ;
+ }
+ });
+ return yangStoreService.getYangStoreSnapshot();
+ }
+ }
}