2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.netconf.it;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.mockito.Matchers.any;
13 import static org.mockito.Matchers.anySetOf;
14 import static org.mockito.Matchers.anyString;
15 import static org.mockito.Mockito.doNothing;
16 import static org.mockito.Mockito.mock;
18 import io.netty.channel.Channel;
19 import io.netty.channel.ChannelFuture;
20 import io.netty.channel.EventLoopGroup;
21 import io.netty.channel.local.LocalAddress;
22 import io.netty.channel.nio.NioEventLoopGroup;
23 import io.netty.util.HashedWheelTimer;
24 import io.netty.util.concurrent.GlobalEventExecutor;
25 import java.io.ByteArrayInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.net.InetSocketAddress;
29 import java.net.SocketAddress;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.HashSet;
35 import java.util.List;
36 import java.util.concurrent.TimeUnit;
37 import org.apache.commons.io.IOUtils;
38 import org.junit.After;
39 import org.junit.Before;
40 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
41 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
42 import org.opendaylight.controller.config.spi.ModuleFactory;
43 import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
44 import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory;
45 import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleFactory;
46 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
47 import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
48 import org.opendaylight.controller.netconf.api.NetconfMessage;
49 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
50 import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
51 import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener;
52 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
53 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
54 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
55 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService;
56 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
57 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl;
58 import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
59 import org.opendaylight.controller.netconf.impl.SessionIdProvider;
60 import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory;
61 import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
62 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
63 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator;
64 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService;
65 import org.opendaylight.controller.netconf.notifications.BaseNetconfNotificationListener;
66 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
67 import org.opendaylight.protocol.framework.NeverReconnectStrategy;
68 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChange;
69 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
70 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
71 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
72 import org.w3c.dom.Element;
74 public abstract class AbstractNetconfConfigTest extends AbstractConfigTest {
76 public static final String LOOPBACK_ADDRESS = "127.0.0.1";
77 public static final int SERVER_CONNECTION_TIMEOUT_MILLIS = 5000;
78 private static final int RESOURCE_TIMEOUT_MINUTES = 2;
80 static ModuleFactory[] FACTORIES = {new TestImplModuleFactory(),
81 new DepTestImplModuleFactory(),
82 new NetconfTestImplModuleFactory(),
83 new IdentityTestModuleFactory(),
84 new MultipleDependenciesModuleFactory() };
86 private EventLoopGroup nettyThreadgroup;
87 private HashedWheelTimer hashedWheelTimer;
89 private NetconfClientDispatcherImpl clientDispatcher;
90 private Channel serverTcpChannel;
92 private NetconfMessage getConfig;
93 private NetconfMessage get;
96 * @Before in subclasses is called after this method.
99 public void setUpAbstractNetconfConfigTest() throws Exception {
100 super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, FACTORIES));
102 nettyThreadgroup = new NioEventLoopGroup();
103 hashedWheelTimer = new HashedWheelTimer();
109 final AggregatedNetconfOperationServiceFactory factoriesListener = new AggregatedNetconfOperationServiceFactory();
110 final NetconfMonitoringService netconfMonitoringService = getNetconfMonitoringService(factoriesListener);
111 factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
112 factoriesListener.onAddNetconfOperationServiceFactory(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(new NetconfMonitoringOperationService(netconfMonitoringService)));
114 for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getAdditionalServiceFactories(factoriesListener)) {
115 factoriesListener.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory);
118 serverTcpChannel = startNetconfTcpServer(factoriesListener, netconfMonitoringService);
119 clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
123 * Called before setUp method is executed, so test classes can set up resources before setUpAbstractNetconfConfigTest method is called.
125 protected void setUpTestInitial() throws Exception {}
127 private void loadMessages() throws Exception {
128 this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
129 this.get = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/get.xml");
132 public NetconfMessage getGetConfig() {
136 public NetconfMessage getGet() {
140 private Channel startNetconfTcpServer(final AggregatedNetconfOperationServiceFactory listener, final NetconfMonitoringService monitoring) throws Exception {
141 final NetconfServerDispatcherImpl dispatch = createDispatcher(listener, monitoring, getNotificationProducer());
143 final ChannelFuture s;
144 if(getTcpServerAddress() instanceof LocalAddress) {
145 s = dispatch.createLocalServer(((LocalAddress) getTcpServerAddress()));
147 s = dispatch.createServer(((InetSocketAddress) getTcpServerAddress()));
149 s.await(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES);
153 protected DefaultCommitNotificationProducer getNotificationProducer() {
154 final DefaultCommitNotificationProducer notificationProducer = mock(DefaultCommitNotificationProducer.class);
155 doNothing().when(notificationProducer).close();
156 doNothing().when(notificationProducer).sendCommitNotification(anyString(), any(Element.class), anySetOf(String.class));
157 return notificationProducer;
160 protected Iterable<NetconfOperationServiceFactory> getAdditionalServiceFactories(final AggregatedNetconfOperationServiceFactory factoriesListener) throws Exception {
161 return Collections.emptySet();
164 protected NetconfMonitoringService getNetconfMonitoringService(final AggregatedNetconfOperationServiceFactory factoriesListener) throws Exception {
165 return new NetconfMonitoringServiceImpl(factoriesListener);
168 protected abstract SocketAddress getTcpServerAddress();
170 public NetconfClientDispatcherImpl getClientDispatcher() {
171 return clientDispatcher;
174 private HardcodedYangStoreService getYangStore() throws IOException {
175 final Collection<InputStream> yangDependencies = getBasicYangs();
176 return new HardcodedYangStoreService(yangDependencies);
179 static Collection<InputStream> getBasicYangs() throws IOException {
181 final List<String> paths = Arrays.asList(
182 "/META-INF/yang/config.yang",
183 "/META-INF/yang/rpc-context.yang",
184 "/META-INF/yang/config-test.yang",
185 "/META-INF/yang/config-test-impl.yang",
186 "/META-INF/yang/test-types.yang",
187 "/META-INF/yang/test-groups.yang",
188 "/META-INF/yang/ietf-inet-types.yang");
190 final Collection<InputStream> yangDependencies = new ArrayList<>();
191 final List<String> failedToFind = new ArrayList<>();
192 for (final String path : paths) {
193 final InputStream resourceAsStream = NetconfITTest.class.getResourceAsStream(path);
194 if (resourceAsStream == null) {
195 failedToFind.add(path);
197 yangDependencies.add(resourceAsStream);
200 assertEquals("Some yang files were not found", Collections.<String>emptyList(), failedToFind);
201 return yangDependencies;
204 protected NetconfServerDispatcherImpl createDispatcher(
205 final AggregatedNetconfOperationServiceFactory factoriesListener, final NetconfMonitoringService sessionMonitoringService,
206 final DefaultCommitNotificationProducer commitNotifier) {
207 final SessionIdProvider idProvider = new SessionIdProvider();
209 final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
210 hashedWheelTimer, factoriesListener, idProvider, SERVER_CONNECTION_TIMEOUT_MILLIS, commitNotifier, sessionMonitoringService);
212 final NetconfServerDispatcherImpl.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcherImpl.ServerChannelInitializer(
213 serverNegotiatorFactory);
214 return new NetconfServerDispatcherImpl(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
217 protected HashedWheelTimer getHashedWheelTimer() {
218 return hashedWheelTimer;
221 protected EventLoopGroup getNettyThreadgroup() {
222 return nettyThreadgroup;
226 * @After in subclasses is be called before this.
229 public void cleanUpNetconf() throws Exception {
230 serverTcpChannel.close().await(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES);
231 hashedWheelTimer.stop();
232 nettyThreadgroup.shutdownGracefully().await(RESOURCE_TIMEOUT_MINUTES, TimeUnit.MINUTES);
235 public NetconfClientConfiguration getClientConfiguration(final InetSocketAddress tcpAddress, final int timeout) {
236 final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create();
237 b.withAddress(tcpAddress);
238 b.withSessionListener(new SimpleNetconfClientSessionListener());
239 b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, timeout));
240 b.withConnectionTimeoutMillis(timeout);
244 public static final class HardcodedYangStoreService extends YangStoreService {
245 public HardcodedYangStoreService(final Collection<? extends InputStream> inputStreams) throws IOException {
246 super(new SchemaContextProvider() {
248 public SchemaContext getSchemaContext() {
249 return getSchema(inputStreams);
251 }, new BaseNetconfNotificationListener() {
253 public void onCapabilityChanged(final NetconfCapabilityChange capabilityChange) {
259 private static SchemaContext getSchema(final Collection<? extends InputStream> inputStreams) {
260 final ArrayList<InputStream> byteArrayInputStreams = new ArrayList<>();
261 for (final InputStream inputStream : inputStreams) {
262 assertNotNull(inputStream);
263 final byte[] content;
265 content = IOUtils.toByteArray(inputStream);
266 } catch (IOException e) {
267 throw new IllegalStateException("Cannot read " + inputStream, e);
269 final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
270 byteArrayInputStreams.add(byteArrayInputStream);
273 for (final InputStream inputStream : byteArrayInputStreams) {
276 } catch (final IOException e) {
277 throw new RuntimeException(e);
281 final YangParserImpl yangParser = new YangParserImpl();
282 return yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(byteArrayInputStreams).values()));