blob: 6bb8082a37f577be3cd76a6da1bb921db926129b [file] [log] [blame]
Sanjay S0d4093f2015-05-06 14:55:04 +05301/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.provider.netconf.device.impl;
17
18import static org.easymock.EasyMock.expect;
19import static org.easymock.EasyMock.replay;
20import static org.junit.Assert.assertFalse;
21import static org.onlab.util.Tools.delay;
22import static org.slf4j.LoggerFactory.getLogger;
23
24import java.io.IOException;
Sanjay S59f86fd2015-05-20 12:23:48 +053025import java.net.SocketTimeoutException;
Sanjay S0d4093f2015-05-06 14:55:04 +053026import java.net.URI;
27import java.net.URISyntaxException;
28import java.util.Collection;
29import java.util.Dictionary;
30import java.util.List;
31import java.util.Map;
32import java.util.Set;
33import java.util.concurrent.ConcurrentHashMap;
34
35import org.easymock.EasyMock;
36import org.junit.After;
37import org.junit.Before;
38import org.junit.Test;
39import org.onlab.packet.ChassisId;
40import org.onosproject.cfg.ComponentConfigService;
41import org.onosproject.net.Device;
42import org.onosproject.net.DeviceId;
43import org.onosproject.net.MastershipRole;
44import org.onosproject.net.device.DefaultDeviceDescription;
45import org.onosproject.net.device.DeviceDescription;
46import org.onosproject.net.device.DeviceProvider;
47import org.onosproject.net.device.DeviceProviderRegistry;
48import org.onosproject.net.device.DeviceProviderService;
49import org.onosproject.net.device.PortDescription;
50import org.onosproject.net.device.PortStatistics;
51import org.onosproject.net.provider.ProviderId;
52import org.osgi.service.component.ComponentContext;
53import org.slf4j.Logger;
54
55import com.tailf.jnc.JNCException;
56
57/**
58 * Test Case to Validate Netconf Device Provider.
59 *
60 */
61public class NetconfDeviceProviderTest {
62 // private NetconfDevice device;
63
64 TestDeviceCreator create;
65
66 private final Logger log = getLogger(NetconfDeviceProviderTest.class);
67
68 private Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>();
69
70 private DeviceProviderService providerService;
71
72 private static final int EVENTINTERVAL = 5;
73
74 private static final String SCHEME = "netconf";
75
76 private static final DeviceId DID1 = DeviceId
77 .deviceId("of:0000000000000001");
78
79 private final NetconfDeviceProvider provider = new NetconfDeviceProvider();
80 private final TestDeviceRegistry registry = new TestDeviceRegistry();
81
82 private ComponentConfigService mockCfgService;
83
84 @Before
85 public void setUp() {
86 mockCfgService = EasyMock.createMock(ComponentConfigService.class);
87 provider.cfgService = mockCfgService;
88 provider.providerRegistry = registry;
89 }
90
91 @SuppressWarnings("unchecked")
92 private Dictionary<String, String> getDictionaryMock(ComponentContext componentContext) {
93 Dictionary<String, String> dictionary = EasyMock
94 .createMock(Dictionary.class);
95 expect(dictionary.get("devConfigs"))
96 .andReturn("cisco:cisco@10.18.11.14:22:active,"
97 + "sanjay:b33rb3lly@10.18.24.122:2022:inactive");
98 replay(dictionary);
99 expect(componentContext.getProperties()).andReturn(dictionary);
100 return dictionary;
101 }
102
103 @SuppressWarnings("unchecked")
104 private Dictionary<String, String> getDictionaryMockWithoutValues(ComponentContext componentContext) {
105 Dictionary<String, String> dictionary = EasyMock
106 .createMock(Dictionary.class);
107 expect(dictionary.get("devConfigs")).andReturn("");
108 replay(dictionary);
109 expect(componentContext.getProperties()).andReturn(dictionary);
110 return dictionary;
111 }
112
113 @SuppressWarnings("unchecked")
114 private Dictionary<String, String> getDictionaryMockWithDeviceEntryNull(ComponentContext componentContext) {
115 Dictionary<String, String> dictionary = EasyMock
116 .createMock(Dictionary.class);
117 expect(dictionary.get("devConfigs")).andReturn("null,null");
118 replay(dictionary);
119 expect(componentContext.getProperties()).andReturn(dictionary);
120 return dictionary;
121 }
122
123 @SuppressWarnings("unchecked")
124 private Dictionary<String, String> getDictionaryMockDeviceEntryNumberFomatEx(ComponentContext componentContext) {
125 Dictionary<String, String> dictionary = EasyMock
126 .createMock(Dictionary.class);
127 expect(dictionary.get("devConfigs"))
128 .andReturn("cisco:cisco@10.18.11.14:cisco:active")
129 .andThrow(new NumberFormatException());
130 replay(dictionary);
131 expect(componentContext.getProperties()).andReturn(dictionary);
132 return dictionary;
133 }
134
135 @SuppressWarnings("unchecked")
136 private Dictionary<String, String> getDictionaryMockWithoutUsernameAndPassword(ComponentContext componentContext) {
137 Dictionary<String, String> dictionary = EasyMock
138 .createMock(Dictionary.class);
139 expect(dictionary.get("devConfigs"))
140 .andReturn("null:null@null:0:active");
141 replay(dictionary);
142 expect(componentContext.getProperties()).andReturn(dictionary);
143 return dictionary;
144 }
145
146 @SuppressWarnings("unchecked")
147 private Dictionary<String, String> getDictionaryMockWithDifferentDeviceState(ComponentContext componentContext) {
148 Dictionary<String, String> dictionary = EasyMock
149 .createMock(Dictionary.class);
150 expect(dictionary.get("devConfigs"))
151 .andReturn("cisco:cisco@10.18.11.14:22:active,cisco:cisco@10.18.11.18:22:inactive,"
152 + "cisco:cisco@10.18.11.14:22:invalid,cisco:cisco@10.18.11.14:22:null");
153 replay(dictionary);
154 expect(componentContext.getProperties()).andReturn(dictionary);
155 return dictionary;
156 }
157
158 @SuppressWarnings("unchecked")
159 private Dictionary<String, String> getDictionaryMockDeviceWithArrayOutOFBoundEx(ComponentContext componentContext) {
160 Dictionary<String, String> dictionary = EasyMock
161 .createMock(Dictionary.class);
162 expect(dictionary.get("devConfigs"))
163 .andReturn("@10.18.11.14:22:active")
164 .andThrow(new ArrayIndexOutOfBoundsException());
165 replay(dictionary);
166 expect(componentContext.getProperties()).andReturn(dictionary);
167 return dictionary;
168 }
169
170 @SuppressWarnings("unchecked")
171 private Dictionary<String, String> getDictionaryMockDeviceEntryForDeactivate(ComponentContext componentContext) {
172 Dictionary<String, String> dictionary = EasyMock
173 .createMock(Dictionary.class);
174 expect(dictionary.get("devConfigs"))
175 .andReturn("netconf:cisco@10.18.11.14:22:active")
176 .andThrow(new ArrayIndexOutOfBoundsException());
177 replay(dictionary);
178 expect(componentContext.getProperties()).andReturn(dictionary);
179 return dictionary;
180 }
181
Sanjay S59f86fd2015-05-20 12:23:48 +0530182 @Test(expected = SocketTimeoutException.class)
183 public void testSSHAuthentication() throws JNCException, IOException {
184 NetconfDevice netconfDevice = new NetconfDevice("10.18.14.19", 22,
185 "cisco", "cisco");
186 netconfDevice.setConnectTimeout(1000);
187 TestDeviceCreator objForTestDev = new TestDeviceCreator(netconfDevice,
Sanjay S0d4093f2015-05-06 14:55:04 +0530188 true);
189 objForTestDev.run();
190 }
191
192 @After
193 public void tearDown() {
194 provider.providerRegistry = null;
195 provider.cfgService = null;
196 }
197
198 @Test
199 public void testActiveWithComponentContext() {
200
201 ComponentContext componentContext = EasyMock
202 .createMock(ComponentContext.class);
203 getDictionaryMock(componentContext);
204 replay(componentContext);
205 provider.activate(componentContext);
206 }
207
208 // To check if deviceCfgValue is empty or null
209 @Test
210 public void testActiveWithcomponentContextIsNull() {
211
212 ComponentContext componentContext = EasyMock
213 .createMock(ComponentContext.class);
214 getDictionaryMockWithoutValues(componentContext);
215 replay(componentContext);
216 provider.activate(componentContext);
217 }
218
219 // To check deviceEntry and device is null
220 @Test
221 public void testActiveWithDeviceEntryIsNull() {
222
223 ComponentContext componentContext = EasyMock
224 .createMock(ComponentContext.class);
225 getDictionaryMockWithDeviceEntryNull(componentContext);
226 replay(componentContext);
227 provider.activate(componentContext);
228 }
229
230 @Test
231 public void testActiveWithDeviceEntryWithoutUsernameAndPassword() {
232
233 ComponentContext componentContext = EasyMock
234 .createMock(ComponentContext.class);
235 getDictionaryMockWithoutUsernameAndPassword(componentContext);
236 replay(componentContext);
237 provider.activate(componentContext);
238 }
239
240 @Test
241 public void testActiveWithDeviceEntryWithNumberFomatEx() {
242
243 ComponentContext componentContext = EasyMock
244 .createMock(ComponentContext.class);
245 getDictionaryMockDeviceEntryNumberFomatEx(componentContext);
246 replay(componentContext);
247 provider.activate(componentContext);
248 }
249
250 @Test
251 public void testActiveWithDeviceEntryWithDifferentDeviceState() {
252
253 ComponentContext componentContext = EasyMock
254 .createMock(ComponentContext.class);
255 getDictionaryMockWithDifferentDeviceState(componentContext);
256 replay(componentContext);
257 provider.activate(componentContext);
258 }
259
260 @Test
261 public void testActiveWithDeviceEntryWithArrayOutOFBoundEx() {
262
263 ComponentContext componentContext = EasyMock
264 .createMock(ComponentContext.class);
265 getDictionaryMockDeviceWithArrayOutOFBoundEx(componentContext);
266 replay(componentContext);
267 provider.activate(componentContext);
268 }
269
270 @Test
271 public void isReachableWithInvalidDeviceId() {
272 assertFalse("Initially the Device ID Should not be reachable",
273 provider.isReachable(DID1));
274 NetconfDevice device = new NetconfDevice("", 0, "", "");
275 provider.netconfDeviceMap.put(DID1, device);
276 assertFalse("Particular Device ID cannot be Reachable",
277 provider.isReachable(DID1));
278 }
279
280 @Test
281 public void testDeactivate() {
282
283 ComponentContext componentContext = EasyMock
284 .createMock(ComponentContext.class);
285 getDictionaryMockDeviceEntryForDeactivate(componentContext);
286 replay(componentContext);
287 testActiveWithComponentContext();
288 provider.deactivate(componentContext);
289 }
290
291 private class TestDeviceCreator {
292
293 private NetconfDevice device;
294 private boolean createFlag;
295
296 public TestDeviceCreator(NetconfDevice device, boolean createFlag) {
297 this.device = device;
298 this.createFlag = createFlag;
299 }
300
301 public void run() throws JNCException, IOException {
302 if (createFlag) {
303 log.info("Trying to create Device Info on ONOS core");
304 advertiseDevices();
305 } else {
306 log.info("Trying to remove Device Info on ONOS core");
307 removeDevices();
308 }
309 }
310
311 /**
312 * For each Netconf Device, remove the entry from the device store.
313 * @throws URISyntaxException
314 */
315 private void removeDevices() {
316 if (device == null) {
317 log.warn("The Request Netconf Device is null, cannot proceed further");
318 return;
319 }
320 try {
321 DeviceId did = getDeviceId();
322 if (!netconfDeviceMap.containsKey(did)) {
323 log.error("BAD Request: 'Currently device is not discovered, "
324 + "so cannot remove/disconnect the device: "
325 + device.deviceInfo() + "'");
326 return;
327 }
328 providerService.deviceDisconnected(did);
329 device.disconnect();
330 netconfDeviceMap.remove(did);
331 delay(EVENTINTERVAL);
332 } catch (URISyntaxException uriSyntaxExcpetion) {
333 log.error("Syntax Error while creating URI for the device: "
334 + device.deviceInfo()
335 + " couldn't remove the device from the store",
336 uriSyntaxExcpetion);
337 }
338 }
339
340 /**
341 * Initialize Netconf Device object, and notify core saying device
342 * connected.
343 */
Sanjay S59f86fd2015-05-20 12:23:48 +0530344 private void advertiseDevices()
345 throws JNCException, IOException, SocketTimeoutException {
Sanjay S0d4093f2015-05-06 14:55:04 +0530346 try {
347 if (device == null) {
348 log.warn("The Request Netconf Device is null, cannot proceed further");
349 return;
350 }
351 device.init();
352 DeviceId did = getDeviceId();
353 ChassisId cid = new ChassisId();
354 DeviceDescription desc = new DefaultDeviceDescription(
355 did.uri(),
356 Device.Type.OTHER,
357 "", "",
358 "", "",
359 cid);
360 log.info("Persisting Device" + did.uri().toString());
361
362 netconfDeviceMap.put(did, device);
363 providerService.deviceConnected(did, desc);
364 log.info("Done with Device Info Creation on ONOS core. Device Info: "
365 + device.deviceInfo() + " " + did.uri().toString());
366 delay(EVENTINTERVAL);
367 } catch (URISyntaxException e) {
368 log.error("Syntax Error while creating URI for the device: "
369 + device.deviceInfo()
370 + " couldn't persist the device onto the store", e);
371 } catch (JNCException e) {
372 throw e;
Sanjay S59f86fd2015-05-20 12:23:48 +0530373 } catch (SocketTimeoutException e) {
374 throw e;
Sanjay S0d4093f2015-05-06 14:55:04 +0530375 } catch (IOException e) {
376 throw e;
377 } catch (Exception e) {
378 log.error("Error while initializing session for the device: "
379 + device.deviceInfo(), e);
380 }
381 }
382
383 private DeviceId getDeviceId() throws URISyntaxException {
384 String additionalSSP = new StringBuilder(device.getUsername())
385 .append("@").append(device.getSshHost()).append(":")
386 .append(device.getSshPort()).toString();
387 DeviceId did = DeviceId.deviceId(new URI(SCHEME, additionalSSP,
388 null));
389 return did;
390 }
391 }
392
393 private class TestDeviceRegistry implements DeviceProviderRegistry {
394
395 @Override
396 public DeviceProviderService register(DeviceProvider provider) {
397 return new TestProviderService();
398 }
399
400 @Override
401 public void unregister(DeviceProvider provider) {
402 }
403
404 @Override
405 public Set<ProviderId> getProviders() {
406 return null;
407 }
408
409 private class TestProviderService implements DeviceProviderService {
410
411 public DeviceProvider provider() {
412 return null;
413 }
414
415 public void deviceConnected(DeviceId deviceId,
416 DeviceDescription deviceDescription) {
417 }
418
419 public void deviceDisconnected(DeviceId deviceId) {
420
421 }
422
423 public void updatePorts(DeviceId deviceId,
424 List<PortDescription> portDescriptions) {
425
426 }
427
428 public void portStatusChanged(DeviceId deviceId,
429 PortDescription portDescription) {
430
431 }
432
433 public void receivedRoleReply(DeviceId deviceId,
434 MastershipRole requested,
435 MastershipRole response) {
436
437 }
438
439 public void updatePortStatistics(DeviceId deviceId,
440 Collection<PortStatistics> portStatistics) {
441
442 }
443 }
444 }
445}