blob: 4fa9644bdd1cacfdde87a71124fd80b14bf9ae22 [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;
25import java.net.URI;
26import java.net.URISyntaxException;
27import java.util.Collection;
28import java.util.Dictionary;
29import java.util.List;
30import java.util.Map;
31import java.util.Set;
32import java.util.concurrent.ConcurrentHashMap;
33
34import org.easymock.EasyMock;
35import org.junit.After;
36import org.junit.Before;
Sho SHIMIZU46e79ef2015-05-07 10:49:45 -070037import org.junit.Ignore;
Sanjay S0d4093f2015-05-06 14:55:04 +053038import 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
Sho SHIMIZU46e79ef2015-05-07 10:49:45 -0700182 @Ignore
Sanjay S0d4093f2015-05-06 14:55:04 +0530183 @Test(expected = IOException.class)
184 public void testSSHAuthentication() throws IOException, JNCException {
185 TestDeviceCreator objForTestDev = new TestDeviceCreator(
186 new NetconfDevice(
187 "10.18.14.19",
188 22,
189 "cisco",
190 "cisco"),
191 true);
192 objForTestDev.run();
193 }
194
195 @After
196 public void tearDown() {
197 provider.providerRegistry = null;
198 provider.cfgService = null;
199 }
200
201 @Test
202 public void testActiveWithComponentContext() {
203
204 ComponentContext componentContext = EasyMock
205 .createMock(ComponentContext.class);
206 getDictionaryMock(componentContext);
207 replay(componentContext);
208 provider.activate(componentContext);
209 }
210
211 // To check if deviceCfgValue is empty or null
212 @Test
213 public void testActiveWithcomponentContextIsNull() {
214
215 ComponentContext componentContext = EasyMock
216 .createMock(ComponentContext.class);
217 getDictionaryMockWithoutValues(componentContext);
218 replay(componentContext);
219 provider.activate(componentContext);
220 }
221
222 // To check deviceEntry and device is null
223 @Test
224 public void testActiveWithDeviceEntryIsNull() {
225
226 ComponentContext componentContext = EasyMock
227 .createMock(ComponentContext.class);
228 getDictionaryMockWithDeviceEntryNull(componentContext);
229 replay(componentContext);
230 provider.activate(componentContext);
231 }
232
233 @Test
234 public void testActiveWithDeviceEntryWithoutUsernameAndPassword() {
235
236 ComponentContext componentContext = EasyMock
237 .createMock(ComponentContext.class);
238 getDictionaryMockWithoutUsernameAndPassword(componentContext);
239 replay(componentContext);
240 provider.activate(componentContext);
241 }
242
243 @Test
244 public void testActiveWithDeviceEntryWithNumberFomatEx() {
245
246 ComponentContext componentContext = EasyMock
247 .createMock(ComponentContext.class);
248 getDictionaryMockDeviceEntryNumberFomatEx(componentContext);
249 replay(componentContext);
250 provider.activate(componentContext);
251 }
252
253 @Test
254 public void testActiveWithDeviceEntryWithDifferentDeviceState() {
255
256 ComponentContext componentContext = EasyMock
257 .createMock(ComponentContext.class);
258 getDictionaryMockWithDifferentDeviceState(componentContext);
259 replay(componentContext);
260 provider.activate(componentContext);
261 }
262
263 @Test
264 public void testActiveWithDeviceEntryWithArrayOutOFBoundEx() {
265
266 ComponentContext componentContext = EasyMock
267 .createMock(ComponentContext.class);
268 getDictionaryMockDeviceWithArrayOutOFBoundEx(componentContext);
269 replay(componentContext);
270 provider.activate(componentContext);
271 }
272
273 @Test
274 public void isReachableWithInvalidDeviceId() {
275 assertFalse("Initially the Device ID Should not be reachable",
276 provider.isReachable(DID1));
277 NetconfDevice device = new NetconfDevice("", 0, "", "");
278 provider.netconfDeviceMap.put(DID1, device);
279 assertFalse("Particular Device ID cannot be Reachable",
280 provider.isReachable(DID1));
281 }
282
283 @Test
284 public void testDeactivate() {
285
286 ComponentContext componentContext = EasyMock
287 .createMock(ComponentContext.class);
288 getDictionaryMockDeviceEntryForDeactivate(componentContext);
289 replay(componentContext);
290 testActiveWithComponentContext();
291 provider.deactivate(componentContext);
292 }
293
294 private class TestDeviceCreator {
295
296 private NetconfDevice device;
297 private boolean createFlag;
298
299 public TestDeviceCreator(NetconfDevice device, boolean createFlag) {
300 this.device = device;
301 this.createFlag = createFlag;
302 }
303
304 public void run() throws JNCException, IOException {
305 if (createFlag) {
306 log.info("Trying to create Device Info on ONOS core");
307 advertiseDevices();
308 } else {
309 log.info("Trying to remove Device Info on ONOS core");
310 removeDevices();
311 }
312 }
313
314 /**
315 * For each Netconf Device, remove the entry from the device store.
316 * @throws URISyntaxException
317 */
318 private void removeDevices() {
319 if (device == null) {
320 log.warn("The Request Netconf Device is null, cannot proceed further");
321 return;
322 }
323 try {
324 DeviceId did = getDeviceId();
325 if (!netconfDeviceMap.containsKey(did)) {
326 log.error("BAD Request: 'Currently device is not discovered, "
327 + "so cannot remove/disconnect the device: "
328 + device.deviceInfo() + "'");
329 return;
330 }
331 providerService.deviceDisconnected(did);
332 device.disconnect();
333 netconfDeviceMap.remove(did);
334 delay(EVENTINTERVAL);
335 } catch (URISyntaxException uriSyntaxExcpetion) {
336 log.error("Syntax Error while creating URI for the device: "
337 + device.deviceInfo()
338 + " couldn't remove the device from the store",
339 uriSyntaxExcpetion);
340 }
341 }
342
343 /**
344 * Initialize Netconf Device object, and notify core saying device
345 * connected.
346 */
347 private void advertiseDevices() throws JNCException, IOException {
348 try {
349 if (device == null) {
350 log.warn("The Request Netconf Device is null, cannot proceed further");
351 return;
352 }
353 device.init();
354 DeviceId did = getDeviceId();
355 ChassisId cid = new ChassisId();
356 DeviceDescription desc = new DefaultDeviceDescription(
357 did.uri(),
358 Device.Type.OTHER,
359 "", "",
360 "", "",
361 cid);
362 log.info("Persisting Device" + did.uri().toString());
363
364 netconfDeviceMap.put(did, device);
365 providerService.deviceConnected(did, desc);
366 log.info("Done with Device Info Creation on ONOS core. Device Info: "
367 + device.deviceInfo() + " " + did.uri().toString());
368 delay(EVENTINTERVAL);
369 } catch (URISyntaxException e) {
370 log.error("Syntax Error while creating URI for the device: "
371 + device.deviceInfo()
372 + " couldn't persist the device onto the store", e);
373 } catch (JNCException e) {
374 throw e;
375 } 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}