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
9 package org.opendaylight.controller.netconf.it;
11 import static java.util.Collections.emptyList;
12 import static junit.framework.Assert.assertEquals;
13 import static junit.framework.Assert.assertNotNull;
14 import static junit.framework.Assert.assertTrue;
15 import static org.mockito.Matchers.anyLong;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.mock;
18 import io.netty.channel.ChannelFuture;
19 import io.netty.channel.EventLoopGroup;
20 import io.netty.channel.nio.NioEventLoopGroup;
21 import io.netty.util.HashedWheelTimer;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.lang.management.ManagementFactory;
26 import java.net.InetSocketAddress;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.List;
33 import java.util.concurrent.TimeUnit;
35 import javax.management.ObjectName;
36 import javax.xml.parsers.ParserConfigurationException;
38 import junit.framework.Assert;
40 import org.junit.After;
41 import org.junit.Before;
42 import org.junit.Ignore;
43 import org.junit.Test;
44 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
45 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
46 import org.opendaylight.controller.config.spi.ModuleFactory;
47 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
48 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
49 import org.opendaylight.controller.config.yang.store.impl.HardcodedYangStoreService;
50 import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
51 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
52 import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean;
53 import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
54 import org.opendaylight.controller.netconf.api.NetconfMessage;
55 import org.opendaylight.controller.netconf.client.NetconfClient;
56 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
57 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
58 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
59 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
60 import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
61 import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
62 import org.opendaylight.controller.netconf.impl.SessionIdProvider;
63 import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler;
64 import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;
65 import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
66 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener;
67 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
68 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot;
69 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
70 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
71 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
72 import org.opendaylight.controller.netconf.util.xml.ExiParameters;
73 import org.opendaylight.controller.netconf.util.xml.XmlElement;
74 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77 import org.w3c.dom.Document;
78 import org.w3c.dom.Element;
79 import org.w3c.dom.NamedNodeMap;
80 import org.w3c.dom.Node;
81 import org.xml.sax.SAXException;
83 import ch.ethz.ssh2.Connection;
84 import ch.ethz.ssh2.Session;
86 import com.google.common.collect.Lists;
87 import com.google.common.collect.Sets;
89 public class NetconfITTest extends AbstractConfigTest {
91 // TODO refactor, pull common code up to AbstractNetconfITTest
93 private static final Logger logger = LoggerFactory.getLogger(NetconfITTest.class);
95 private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
96 private static final InetSocketAddress sshAddress = new InetSocketAddress("127.0.0.1", 10830);
97 private static final String USERNAME = "netconf";
98 private static final String PASSWORD = "netconf";
100 private NetconfMessage getConfig, getConfigCandidate, editConfig,
101 closeSession, startExi, stopExi;
102 private DefaultCommitNotificationProducer commitNot;
103 private NetconfServerDispatcher dispatch;
104 private EventLoopGroup nettyThreadgroup;
106 private NetconfClientDispatcher clientDispatcher;
109 public void setUp() throws Exception {
110 super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(getModuleFactories().toArray(
111 new ModuleFactory[0])));
115 NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
116 factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
118 nettyThreadgroup = new NioEventLoopGroup();
120 commitNot = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
122 dispatch = createDispatcher(factoriesListener);
123 ChannelFuture s = dispatch.createServer(tcpAddress);
126 clientDispatcher = new NetconfClientDispatcher( nettyThreadgroup, nettyThreadgroup);
129 private NetconfServerDispatcher createDispatcher(NetconfOperationServiceFactoryListenerImpl factoriesListener) {
130 SessionIdProvider idProvider = new SessionIdProvider();
131 NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
132 new HashedWheelTimer(5000, TimeUnit.MILLISECONDS), factoriesListener, idProvider);
134 NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
135 factoriesListener, commitNot, idProvider, getNetconfMonitoringListenerService());
137 NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
138 serverNegotiatorFactory, listenerFactory);
139 return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
142 static NetconfMonitoringServiceImpl getNetconfMonitoringListenerService() {
143 NetconfOperationServiceFactoryListener factoriesListener = mock(NetconfOperationServiceFactoryListener.class);
144 NetconfOperationServiceSnapshot snap = mock(NetconfOperationServiceSnapshot.class);
145 doReturn(Collections.<NetconfOperationService>emptySet()).when(snap).getServices();
146 doReturn(snap).when(factoriesListener).getSnapshot(anyLong());
147 return new NetconfMonitoringServiceImpl(factoriesListener);
151 public void tearDown() throws Exception {
153 nettyThreadgroup.shutdownGracefully();
154 clientDispatcher.close();
157 private void loadMessages() throws IOException, SAXException, ParserConfigurationException {
158 this.editConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/edit_config.xml");
159 this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
160 this.getConfigCandidate = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig_candidate.xml");
161 this.startExi = XmlFileLoader
162 .xmlFileToNetconfMessage("netconfMessages/startExi.xml");
163 this.stopExi = XmlFileLoader
164 .xmlFileToNetconfMessage("netconfMessages/stopExi.xml");
165 this.closeSession = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/closeSession.xml");
168 private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
169 final Collection<InputStream> yangDependencies = getBasicYangs();
170 return new HardcodedYangStoreService(yangDependencies);
173 static Collection<InputStream> getBasicYangs() throws IOException {
174 List<String> paths = Arrays.asList("/META-INF/yang/config.yang", "/META-INF/yang/rpc-context.yang",
175 "/META-INF/yang/config-test.yang", "/META-INF/yang/config-test-impl.yang", "/META-INF/yang/test-types.yang",
176 "/META-INF/yang/ietf-inet-types.yang");
177 final Collection<InputStream> yangDependencies = new ArrayList<>();
178 List<String> failedToFind = new ArrayList<>();
179 for (String path : paths) {
180 InputStream resourceAsStream = NetconfITTest.class.getResourceAsStream(path);
181 if (resourceAsStream == null) {
182 failedToFind.add(path);
184 yangDependencies.add(resourceAsStream);
187 assertEquals("Some yang files were not found",emptyList(), failedToFind);
188 return yangDependencies;
191 protected List<ModuleFactory> getModuleFactories() {
192 return getModuleFactoriesS();
194 static List<ModuleFactory> getModuleFactoriesS() {
195 return Lists.newArrayList(new TestImplModuleFactory(), new DepTestImplModuleFactory(),
196 new NetconfTestImplModuleFactory());
200 public void testNetconfClientDemonstration() throws Exception {
201 try (NetconfClient netconfClient = new NetconfClient("client", tcpAddress, 4000, clientDispatcher)) {
203 Set<String> capabilitiesFromNetconfServer = netconfClient.getCapabilities();
204 long sessionId = netconfClient.getSessionId();
206 // NetconfMessage can be created :
207 // new NetconfMessage(XmlUtil.readXmlToDocument("<xml/>"));
209 NetconfMessage response = netconfClient.sendMessage(getConfig);
210 response.getDocument();
215 public void testTwoSessions() throws Exception {
216 try (NetconfClient netconfClient = new NetconfClient("1", tcpAddress, 10000, clientDispatcher)) {
217 try (NetconfClient netconfClient2 = new NetconfClient("2", tcpAddress, 10000, clientDispatcher)) {
223 //TODO: test persister actually
225 @Test(timeout = 10000)
226 public void testPersister() throws Exception {
227 // Persister persister = mock(Persister.class);
228 // doReturn("mockPersister").when(persister).toString();
229 // doReturn(Collections.emptyList()).when(persister).loadLastConfigs();
230 // ConfigPersisterNotificationHandler h =
231 // new ConfigPersisterNotificationHandler(persister, tcpAddress, ManagementFactory.getPlatformMBeanServer(),
232 // Pattern.compile(ConfigPersisterActivator.DEFAULT_IGNORED_REGEX));
238 public void waitingTest() throws Exception {
239 final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
240 transaction.createModule(DepTestImplModuleFactory.NAME, "eb");
241 transaction.commit();
242 Thread.currentThread().suspend();
246 public void rpcReplyContainsAllAttributesTest() throws Exception {
247 try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
248 final String rpc = "<rpc message-id=\"5\" a=\"a\" b=\"44\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
249 + "<get/>" + "</rpc>";
250 final Document doc = XmlUtil.readXmlToDocument(rpc);
251 final NetconfMessage message = netconfClient.sendMessage(new NetconfMessage(doc));
252 assertNotNull(message);
253 final NamedNodeMap expectedAttributes = doc.getDocumentElement().getAttributes();
254 final NamedNodeMap returnedAttributes = message.getDocument().getDocumentElement().getAttributes();
256 assertSameAttributes(expectedAttributes, returnedAttributes);
260 private void assertSameAttributes(final NamedNodeMap expectedAttributes, final NamedNodeMap returnedAttributes) {
261 assertNotNull("Expecting 4 attributes", returnedAttributes);
262 assertEquals(expectedAttributes.getLength(), returnedAttributes.getLength());
264 for (int i = 0; i < expectedAttributes.getLength(); i++) {
265 final Node expAttr = expectedAttributes.item(i);
266 final Node attr = returnedAttributes.item(i);
267 assertEquals(expAttr.getNodeName(), attr.getNodeName());
268 assertEquals(expAttr.getNamespaceURI(), attr.getNamespaceURI());
269 assertEquals(expAttr.getTextContent(), attr.getTextContent());
274 public void rpcReplyErrorContainsAllAttributesTest() throws Exception {
275 try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
276 final String rpc = "<rpc message-id=\"1\" a=\"adada\" b=\"4\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
277 + "<commit/>" + "</rpc>";
278 final Document doc = XmlUtil.readXmlToDocument(rpc);
279 final NetconfMessage message = netconfClient.sendMessage(new NetconfMessage(doc));
280 final NamedNodeMap expectedAttributes = doc.getDocumentElement().getAttributes();
281 final NamedNodeMap returnedAttributes = message.getDocument().getDocumentElement().getAttributes();
283 assertSameAttributes(expectedAttributes, returnedAttributes);
288 public void rpcOutputContainsCorrectNamespace() throws Exception {
289 final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
290 ObjectName dep = transaction.createModule(DepTestImplModuleFactory.NAME, "instanceD");
291 ObjectName impl = transaction.createModule(NetconfTestImplModuleFactory.NAME, "instance");
292 NetconfTestImplModuleMXBean proxy = configRegistryClient
293 .newMXBeanProxy(impl, NetconfTestImplModuleMXBean.class);
294 proxy.setTestingDep(dep);
295 proxy.setSimpleShort((short)0);
297 transaction.commit();
299 try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
300 final String expectedNamespace = "urn:opendaylight:params:xml:ns:yang:controller:test:impl";
302 final String rpc = "<rpc message-id=\"5\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
306 + "<context-instance>/modules/module[type='impl-netconf'][name='instance']</context-instance>"
307 + "<arg1>argument1</arg1>" + "</no-arg>" + "</rpc>";
308 final Document doc = XmlUtil.readXmlToDocument(rpc);
309 final NetconfMessage message = netconfClient.sendMessage(new NetconfMessage(doc));
311 final Element rpcReply = message.getDocument().getDocumentElement();
312 final XmlElement resultElement = XmlElement.fromDomElement(rpcReply).getOnlyChildElement();
313 assertEquals("result", resultElement.getName());
315 final String namespace = resultElement.getNamespaceAttribute();
316 assertEquals(expectedNamespace, namespace);
322 public void testStartExi() throws Exception {
323 try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
326 Document rpcReply = netconfClient.sendMessage(this.startExi)
328 assertIsOK(rpcReply);
330 ExiParameters exiParams = new ExiParameters();
331 exiParams.setParametersFromXmlElement(XmlElement.fromDomDocument(this.startExi.getDocument()));
333 netconfClient.getClientSession().addExiDecoder(ExiDecoderHandler.HANDLER_NAME, new ExiDecoderHandler(exiParams));
334 netconfClient.getClientSession().addExiEncoder(ExiEncoderHandler.HANDLER_NAME, new ExiEncoderHandler(exiParams));
336 rpcReply = netconfClient.sendMessage(this.editConfig)
338 assertIsOK(rpcReply);
340 rpcReply = netconfClient.sendMessage(this.stopExi)
342 assertIsOK(rpcReply);
348 public void testCloseSession() throws Exception {
349 try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
352 Document rpcReply = netconfClient.sendMessage(this.editConfig)
354 assertIsOK(rpcReply);
356 rpcReply = netconfClient.sendMessage(this.closeSession)
359 assertIsOK(rpcReply);
364 public void testEditConfig() throws Exception {
365 try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
366 // send edit_config.xml
367 final Document rpcReply = netconfClient.sendMessage(this.editConfig).getDocument();
368 assertIsOK(rpcReply);
373 public void testValidate() throws Exception {
374 try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
376 Document rpcReply = netconfClient.sendMessage(getConfigCandidate).getDocument();
377 assertEquals("data", XmlElement.fromDomDocument(rpcReply).getOnlyChildElement().getName());
380 rpcReply = netconfClient.sendMessage(XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/validate.xml"))
382 assertIsOK(rpcReply);
386 private void assertIsOK(final Document rpcReply) {
387 assertEquals("rpc-reply", rpcReply.getDocumentElement().getLocalName());
388 assertEquals("ok", XmlElement.fromDomDocument(rpcReply).getOnlyChildElement().getName());
391 private Document assertGetConfigWorks(final NetconfClient netconfClient) throws InterruptedException {
392 return assertGetConfigWorks(netconfClient, this.getConfig);
395 private Document assertGetConfigWorks(final NetconfClient netconfClient, final NetconfMessage getConfigMessage)
396 throws InterruptedException {
397 final NetconfMessage rpcReply = netconfClient.sendMessage(getConfigMessage);
398 assertNotNull(rpcReply);
399 assertEquals("data", XmlElement.fromDomDocument(rpcReply.getDocument()).getOnlyChildElement().getName());
400 return rpcReply.getDocument();
404 public void testGetConfig() throws Exception {
405 try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
406 assertGetConfigWorks(netconfClient);
411 public void createYangTestBasedOnYuma() throws Exception {
412 try (NetconfClient netconfClient = createSession(tcpAddress, "1")) {
413 Document rpcReply = netconfClient.sendMessage(
414 XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig_merge_yang-test.xml"))
416 assertEquals("rpc-reply", rpcReply.getDocumentElement().getTagName());
417 assertIsOK(rpcReply);
418 assertGetConfigWorks(netconfClient, this.getConfigCandidate);
419 rpcReply = netconfClient.sendMessage(XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml"))
421 assertIsOK(rpcReply);
423 final ObjectName on = new ObjectName(
424 "org.opendaylight.controller:instanceName=impl-dep-instance,type=Module,moduleFactoryName=impl-dep");
425 Set<ObjectName> cfgBeans = configRegistryClient.lookupConfigBeans();
426 assertEquals(cfgBeans, Sets.newHashSet(on));
430 private NetconfClient createSession(final InetSocketAddress address, final String expected) throws Exception {
431 final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, clientDispatcher);
432 assertEquals(expected, Long.toString(netconfClient.getSessionId()));
433 return netconfClient;
436 private void startSSHServer() throws Exception{
437 logger.info("Creating SSH server");
438 Thread sshServerThread = new Thread(NetconfSSHServer.start(10830,tcpAddress));
439 sshServerThread.setDaemon(true);
440 sshServerThread.start();
441 logger.info("SSH server on");
445 public void sshTest() throws Exception {
447 logger.info("creating connection");
448 Connection conn = new Connection(sshAddress.getHostName(),sshAddress.getPort());
449 Assert.assertNotNull(conn);
450 logger.info("connection created");
452 boolean isAuthenticated = conn.authenticateWithPassword(USERNAME,PASSWORD);
453 assertTrue(isAuthenticated);
454 logger.info("user authenticated");
455 final Session sess = conn.openSession();
456 sess.startSubSystem("netconf");
457 logger.info("user authenticated");
458 sess.getStdin().write(XmlUtil.toString(this.getConfig.getDocument()).getBytes());
463 byte[] bytes = new byte[1024];
466 c = sess.getStdout().read(bytes);
467 } catch (IOException e) {
468 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
470 logger.info("got data:"+bytes);