14f70d398c6874f5922488fbb802540d5d97bc95
[controller.git] / opendaylight / netconf / netconf-it / src / test / java / org / opendaylight / controller / netconf / it / NetconfConfigPersisterITTest.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.netconf.it;
9
10 import com.google.common.collect.Lists;
11 import com.google.common.collect.Sets;
12 import io.netty.channel.ChannelFuture;
13 import io.netty.channel.EventLoopGroup;
14 import io.netty.channel.nio.NioEventLoopGroup;
15 import io.netty.util.HashedWheelTimer;
16 import org.apache.commons.lang3.StringUtils;
17 import org.junit.Assert;
18 import org.junit.Before;
19 import org.junit.Test;
20 import org.junit.matchers.JUnitMatchers;
21 import org.mockito.invocation.InvocationOnMock;
22 import org.mockito.stubbing.Answer;
23 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
24 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
25 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
26 import org.opendaylight.controller.config.persist.api.Persister;
27 import org.opendaylight.controller.config.spi.ModuleFactory;
28 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
29 import org.opendaylight.controller.config.yang.store.impl.HardcodedYangStoreService;
30 import org.opendaylight.controller.netconf.api.NetconfMessage;
31 import org.opendaylight.controller.netconf.api.jmx.CommitJMXNotification;
32 import org.opendaylight.controller.netconf.api.monitoring.NetconfManagementSession;
33 import org.opendaylight.controller.netconf.client.NetconfClient;
34 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
35 import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
36 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
37 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
38 import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory;
39 import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
40 import org.opendaylight.controller.netconf.impl.SessionIdProvider;
41 import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
42 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener;
43 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
44 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot;
45 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
46 import org.opendaylight.controller.netconf.mapping.api.Capability;
47 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
48 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator;
49 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService;
50 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
51 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
52 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55 import org.w3c.dom.Element;
56
57 import javax.management.InstanceNotFoundException;
58 import javax.management.Notification;
59 import javax.management.NotificationListener;
60 import java.io.IOException;
61 import java.io.InputStream;
62 import java.net.InetSocketAddress;
63 import java.util.Collection;
64 import java.util.List;
65 import java.util.Set;
66 import java.util.concurrent.TimeUnit;
67 import java.util.regex.Pattern;
68
69 import static junit.framework.Assert.assertEquals;
70 import static org.mockito.Matchers.any;
71 import static org.mockito.Matchers.anyLong;
72 import static org.mockito.Mockito.doAnswer;
73 import static org.mockito.Mockito.doNothing;
74 import static org.mockito.Mockito.doReturn;
75 import static org.mockito.Mockito.mock;
76
77 public class NetconfConfigPersisterITTest extends AbstractConfigTest {
78
79     private static final Logger logger =  LoggerFactory.getLogger(NetconfConfigPersisterITTest.class);
80
81     private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
82
83     private EventLoopGroup nettyThreadgroup;
84
85     private NetconfClientDispatcher clientDispatcher;
86
87     @Before
88     public void setUp() throws Exception {
89         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(NetconfITTest.getModuleFactoriesS().toArray(
90                 new ModuleFactory[0])));
91
92         NetconfMonitoringServiceImpl monitoringService = new NetconfMonitoringServiceImpl(getFactoriesListener());
93
94         NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
95         factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
96         factoriesListener
97                 .onAddNetconfOperationServiceFactory(new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
98                         new NetconfMonitoringOperationService(monitoringService)));
99
100         nettyThreadgroup = new NioEventLoopGroup();
101
102         NetconfServerDispatcher dispatch = createDispatcher(factoriesListener);
103         ChannelFuture s = dispatch.createServer(tcpAddress);
104         s.await();
105
106         clientDispatcher = new NetconfClientDispatcher(nettyThreadgroup, nettyThreadgroup);
107     }
108
109     private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
110         final Collection<InputStream> yangDependencies = NetconfITTest.getBasicYangs();
111         return new HardcodedYangStoreService(yangDependencies);
112     }
113
114     private NetconfServerDispatcher createDispatcher(
115                                                      NetconfOperationServiceFactoryListenerImpl factoriesListener) {
116         SessionIdProvider idProvider = new SessionIdProvider();
117         NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
118                 new HashedWheelTimer(5000, TimeUnit.MILLISECONDS), factoriesListener, idProvider);
119
120         NetconfServerSessionListenerFactory listenerFactory = new NetconfServerSessionListenerFactory(
121                 factoriesListener, new DefaultCommitNotificationProducer(platformMBeanServer), idProvider, mockSessionMonitoringService());
122
123         NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
124                 serverNegotiatorFactory, listenerFactory);
125         return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
126     }
127
128     private SessionMonitoringService mockSessionMonitoringService() {
129         SessionMonitoringService mockedSessionMonitor = mock(SessionMonitoringService.class);
130         doNothing().when(mockedSessionMonitor).onSessionUp(any(NetconfManagementSession.class));
131         doNothing().when(mockedSessionMonitor).onSessionDown(any(NetconfManagementSession.class));
132         return mockedSessionMonitor;
133     }
134
135     @Test
136     public void testNetconfCommitNotifications() throws Exception {
137
138         VerifyingNotificationListener notificationVerifier = createCommitNotificationListener();
139         VerifyingPersister mockedAggregator = mockAggregator();
140
141         try (NetconfClient persisterClient = new NetconfClient("persister", tcpAddress, 4000, clientDispatcher)) {
142             ConfigPersisterNotificationHandler configPersisterNotificationHandler = new ConfigPersisterNotificationHandler(
143                     platformMBeanServer, persisterClient, mockedAggregator,
144                     Pattern.compile(""));
145             configPersisterNotificationHandler.init();
146
147             try (NetconfClient netconfClient = new NetconfClient("client", tcpAddress, 4000, clientDispatcher)) {
148                 NetconfMessage response = netconfClient.sendMessage(loadGetConfigMessage());
149                 assertResponse(response, "<modules");
150                 assertResponse(response, "<services");
151                 response = netconfClient.sendMessage(loadCommitMessage());
152                 assertResponse(response, "ok");
153
154                 response = netconfClient.sendMessage(loadEditConfigMessage());
155                 assertResponse(response, "ok");
156                 response = netconfClient.sendMessage(loadCommitMessage());
157                 assertResponse(response, "ok");
158             }
159         }
160
161         notificationVerifier.assertNotificationCount(2);
162         notificationVerifier.assertNotificationContent(0, 0, 0, 9);
163         notificationVerifier.assertNotificationContent(1, 4, 4, 9);
164
165         mockedAggregator.assertSnapshotCount(2);
166         // Capabilities are stripped for persister
167         mockedAggregator.assertSnapshotContent(0, 0, 0, 1);
168         mockedAggregator.assertSnapshotContent(1, 4, 4, 3);
169     }
170
171     private VerifyingPersister mockAggregator() throws IOException {
172         return new VerifyingPersister();
173     }
174
175     private VerifyingNotificationListener createCommitNotificationListener() throws InstanceNotFoundException {
176         VerifyingNotificationListener listener = new VerifyingNotificationListener();
177         platformMBeanServer.addNotificationListener(DefaultCommitNotificationProducer.objectName, listener, null, null);
178         return listener;
179     }
180
181     private void assertResponse(NetconfMessage response, String content) {
182         Assert.assertThat(XmlUtil.toString(response.getDocument()), JUnitMatchers.containsString(content));
183     }
184
185     private NetconfMessage loadGetConfigMessage() throws Exception {
186         return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
187     }
188
189     private NetconfMessage loadEditConfigMessage() throws Exception {
190         return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/editConfig.xml");
191     }
192
193     private NetconfMessage loadCommitMessage() throws Exception {
194         return XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/commit.xml");
195     }
196
197
198     public NetconfOperationServiceFactoryListener getFactoriesListener() {
199         NetconfOperationServiceFactoryListener factoriesListener = mock(NetconfOperationServiceFactoryListener.class);
200         NetconfOperationServiceSnapshot snap = mock(NetconfOperationServiceSnapshot.class);
201         NetconfOperationService service = mock(NetconfOperationService.class);
202         Set<Capability> caps = Sets.newHashSet();
203         doReturn(caps).when(service).getCapabilities();
204         Set<NetconfOperationService> services = Sets.newHashSet(service);
205         doReturn(services).when(snap).getServices();
206         doReturn(snap).when(factoriesListener).getSnapshot(anyLong());
207
208         return factoriesListener;
209     }
210
211     private static class VerifyingNotificationListener implements NotificationListener {
212         public List<Notification> notifications = Lists.newArrayList();
213
214         @Override
215         public void handleNotification(Notification notification, Object handback) {
216             this.notifications.add(notification);
217         }
218
219         void assertNotificationCount(Object size) {
220             assertEquals(size, notifications.size());
221         }
222
223         void assertNotificationContent(int notificationIndex, int expectedModulesSize, int expectedServicesSize, int expectedCapsSize) {
224             Notification notification = notifications.get(notificationIndex);
225             assertEquals(CommitJMXNotification.class, notification.getClass());
226             int capsSize = ((CommitJMXNotification) notification).getCapabilities().size();
227             assertEquals("Expected capabilities count", expectedCapsSize, capsSize);
228             Element configSnapshot = ((CommitJMXNotification) notification).getConfigSnapshot();
229             int modulesSize = configSnapshot.getElementsByTagName("module").getLength();
230             assertEquals("Expected modules count", expectedModulesSize, modulesSize);
231             int servicesSize = configSnapshot.getElementsByTagName("instance").getLength();
232             assertEquals("Expected services count", expectedServicesSize, servicesSize);
233         }
234     }
235
236     private static class VerifyingPersister implements Persister {
237
238         public List<ConfigSnapshotHolder> snapshots = Lists.newArrayList();
239         private Persister mockedPersister;
240
241         public VerifyingPersister() throws IOException {
242             Persister mockedAggregator = mock(Persister.class);
243
244             doAnswer(new Answer() {
245                 @Override
246                 public Object answer(InvocationOnMock invocation) throws Throwable {
247                     ConfigSnapshotHolder configSnapshot = (ConfigSnapshotHolder) invocation.getArguments()[0];
248                     snapshots.add(configSnapshot);
249                     return null;
250                 }
251             }).when(mockedAggregator).persistConfig(any(ConfigSnapshotHolder.class));
252
253             this.mockedPersister = mockedAggregator;
254         }
255
256         void assertSnapshotCount(Object size) {
257             assertEquals(size, snapshots.size());
258         }
259
260         void assertSnapshotContent(int notificationIndex, int expectedModulesSize, int expectedServicesSize, int expectedCapsSize) {
261             ConfigSnapshotHolder snapshot = snapshots.get(notificationIndex);
262             int capsSize = snapshot.getCapabilities().size();
263             assertEquals("Expected capabilities count", expectedCapsSize, capsSize);
264             String configSnapshot = snapshot.getConfigSnapshot();
265             int modulesSize = StringUtils.countMatches(configSnapshot, "<module>");
266             assertEquals("Expected modules count", expectedModulesSize, modulesSize);
267             int servicesSize = StringUtils.countMatches(configSnapshot, "<instance>");
268             assertEquals("Expected services count", expectedServicesSize, servicesSize);
269         }
270
271         @Override
272         public void persistConfig(ConfigSnapshotHolder configSnapshotHolder) throws IOException {
273             mockedPersister.persistConfig(configSnapshotHolder);
274         }
275
276         @Override
277         public List<ConfigSnapshotHolder> loadLastConfigs() throws IOException {
278             return mockedPersister.loadLastConfigs();
279         }
280
281         @Override
282         public void close() {
283             mockedPersister.close();
284         }
285     }
286 }