X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fnetconf-it%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Fit%2FAbstractNetconfConfigTest.java;h=c2812dbf61af7241323941a9317780dd4e7df100;hp=b81f950cb362cf8f810201bfe98c983e1bf0988d;hb=5c008222efa5c0af49cf8a52881a6299b1e249dc;hpb=1745f92957146128e8a4a111adb7ed830f737e0a diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java index b81f950cb3..c2812dbf61 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java @@ -7,49 +7,279 @@ */ 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.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 java.util.concurrent.TimeUnit; +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.api.monitoring.NetconfMonitoringService; +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.YangStoreService; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; -import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; +import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl; import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; import org.opendaylight.controller.netconf.impl.SessionIdProvider; -import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; -import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService; +import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory; +import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl; +import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; +import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator; +import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService; +import org.opendaylight.controller.netconf.notifications.BaseNetconfNotificationListener; +import org.opendaylight.controller.netconf.util.test.XmlFileLoader; +import org.opendaylight.protocol.framework.NeverReconnectStrategy; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChange; +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; + private static final int RESOURCE_TIMEOUT_MINUTES = 2; -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 AggregatedNetconfOperationServiceFactory factoriesListener = new AggregatedNetconfOperationServiceFactory(); + final NetconfMonitoringService netconfMonitoringService = getNetconfMonitoringService(factoriesListener); + factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore())); + factoriesListener.onAddNetconfOperationServiceFactory(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(new NetconfMonitoringOperationService(netconfMonitoringService))); + + for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getAdditionalServiceFactories(factoriesListener)) { + factoriesListener.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory); + } + + serverTcpChannel = startNetconfTcpServer(factoriesListener, netconfMonitoringService); + 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 {} + + 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 AggregatedNetconfOperationServiceFactory listener, final NetconfMonitoringService monitoring) throws Exception { + final NetconfServerDispatcherImpl dispatch = createDispatcher(listener, monitoring, getNotificationProducer()); + + final ChannelFuture s; + if(getTcpServerAddress() instanceof LocalAddress) { + s = dispatch.createLocalServer(((LocalAddress) getTcpServerAddress())); + } else { + s = dispatch.createServer(((InetSocketAddress) getTcpServerAddress())); + } + s.await(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES); + 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 getAdditionalServiceFactories(final AggregatedNetconfOperationServiceFactory factoriesListener) throws Exception { + return Collections.emptySet(); } + protected NetconfMonitoringService getNetconfMonitoringService(final AggregatedNetconfOperationServiceFactory factoriesListener) throws Exception { + return new NetconfMonitoringServiceImpl(factoriesListener); + } + + protected abstract SocketAddress getTcpServerAddress(); + + public NetconfClientDispatcherImpl getClientDispatcher() { + return clientDispatcher; + } + + private HardcodedYangStoreService getYangStore() throws IOException { + final Collection yangDependencies = getBasicYangs(); + return new HardcodedYangStoreService(yangDependencies); + } + + static Collection getBasicYangs() throws IOException { + + final List 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/test-groups.yang", + "/META-INF/yang/ietf-inet-types.yang"); - protected NetconfServerDispatcher createDispatcher( - NetconfOperationServiceFactoryListenerImpl factoriesListener, SessionMonitoringService sessionMonitoringService, - DefaultCommitNotificationProducer commitNotifier) { - SessionIdProvider idProvider = new SessionIdProvider(); + final Collection yangDependencies = new ArrayList<>(); + final List 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.emptyList(), failedToFind); + return yangDependencies; + } + + protected NetconfServerDispatcherImpl createDispatcher( + final AggregatedNetconfOperationServiceFactory factoriesListener, final NetconfMonitoringService sessionMonitoringService, + final DefaultCommitNotificationProducer commitNotifier) { + final SessionIdProvider idProvider = new SessionIdProvider(); - NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory( - hashedWheelTimer, factoriesListener, idProvider, 5000, commitNotifier, sessionMonitoringService); + final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory( + hashedWheelTimer, factoriesListener, idProvider, SERVER_CONNECTION_TIMEOUT_MILLIS, commitNotifier, sessionMonitoringService); - NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer( + final NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer( serverNegotiatorFactory); - return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup); + return new NetconfServerDispatcherImpl(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup); + } + + protected HashedWheelTimer getHashedWheelTimer() { + 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(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES); hashedWheelTimer.stop(); - nettyThreadgroup.shutdownGracefully(); + nettyThreadgroup.shutdownGracefully().await(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES); } + 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 extends YangStoreService { + public HardcodedYangStoreService(final Collection inputStreams) throws IOException { + super(new SchemaContextProvider() { + @Override + public SchemaContext getSchemaContext() { + return getSchema(inputStreams); + } + }, new BaseNetconfNotificationListener() { + @Override + public void onCapabilityChanged(final NetconfCapabilityChange capabilityChange) { + // NOOP + } + }); + } + + private static SchemaContext getSchema(final Collection inputStreams) { + final ArrayList byteArrayInputStreams = new ArrayList<>(); + for (final InputStream inputStream : inputStreams) { + assertNotNull(inputStream); + final byte[] content; + try { + content = IOUtils.toByteArray(inputStream); + } catch (IOException e) { + throw new IllegalStateException("Cannot read " + inputStream, e); + } + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content); + byteArrayInputStreams.add(byteArrayInputStream); + } + + for (final InputStream inputStream : byteArrayInputStreams) { + try { + inputStream.reset(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + final YangParserImpl yangParser = new YangParserImpl(); + return yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(byteArrayInputStreams).values())); + } + } }