blob: e56c5959c7665ad86ed6daf078ad3ecac467611c [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;
Samir Anand7b270f52015-07-13 17:27:11 +053022import static org.onosproject.provider.netconf.device.impl.NetconfDeviceProviderTestConstant.*;
Sanjay S0d4093f2015-05-06 14:55:04 +053023import static org.slf4j.LoggerFactory.getLogger;
24
25import java.io.IOException;
26import 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;
HIGUCHI Yutaea39db52015-06-12 12:02:38 -070038import org.junit.Ignore;
Sanjay S0d4093f2015-05-06 14:55:04 +053039import org.junit.Test;
40import org.onlab.packet.ChassisId;
41import org.onosproject.cfg.ComponentConfigService;
42import org.onosproject.net.Device;
43import org.onosproject.net.DeviceId;
44import org.onosproject.net.MastershipRole;
45import org.onosproject.net.device.DefaultDeviceDescription;
46import org.onosproject.net.device.DeviceDescription;
47import org.onosproject.net.device.DeviceProvider;
48import org.onosproject.net.device.DeviceProviderRegistry;
49import org.onosproject.net.device.DeviceProviderService;
50import org.onosproject.net.device.PortDescription;
51import org.onosproject.net.device.PortStatistics;
52import org.onosproject.net.provider.ProviderId;
53import org.osgi.service.component.ComponentContext;
54import org.slf4j.Logger;
55
56import com.tailf.jnc.JNCException;
57
58/**
59 * Test Case to Validate Netconf Device Provider.
Sanjay S0d4093f2015-05-06 14:55:04 +053060 */
61public class NetconfDeviceProviderTest {
Sanjay S0d4093f2015-05-06 14:55:04 +053062 TestDeviceCreator create;
63
64 private final Logger log = getLogger(NetconfDeviceProviderTest.class);
65
66 private Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>();
67
68 private DeviceProviderService providerService;
69
Samir Anand7b270f52015-07-13 17:27:11 +053070 private static final DeviceId DID1 = DeviceId.deviceId(DEVICE_ID);
Sanjay S0d4093f2015-05-06 14:55:04 +053071
72 private final NetconfDeviceProvider provider = new NetconfDeviceProvider();
73 private final TestDeviceRegistry registry = new TestDeviceRegistry();
74
75 private ComponentConfigService mockCfgService;
76
77 @Before
78 public void setUp() {
79 mockCfgService = EasyMock.createMock(ComponentConfigService.class);
80 provider.cfgService = mockCfgService;
81 provider.providerRegistry = registry;
82 }
83
84 @SuppressWarnings("unchecked")
Sanjay S0d4093f2015-05-06 14:55:04 +053085 private Dictionary<String, String> getDictionaryMockWithoutValues(ComponentContext componentContext) {
86 Dictionary<String, String> dictionary = EasyMock
87 .createMock(Dictionary.class);
Samir Anand7b270f52015-07-13 17:27:11 +053088 expect(dictionary.get(DEV_CONFIG)).andReturn(NULL);
Sanjay S0d4093f2015-05-06 14:55:04 +053089 replay(dictionary);
90 expect(componentContext.getProperties()).andReturn(dictionary);
91 return dictionary;
92 }
93
94 @SuppressWarnings("unchecked")
95 private Dictionary<String, String> getDictionaryMockWithDeviceEntryNull(ComponentContext componentContext) {
96 Dictionary<String, String> dictionary = EasyMock
97 .createMock(Dictionary.class);
Samir Anand7b270f52015-07-13 17:27:11 +053098 expect(dictionary.get(DEV_CONFIG)).andReturn(NULL_NULL);
Sanjay S0d4093f2015-05-06 14:55:04 +053099 replay(dictionary);
100 expect(componentContext.getProperties()).andReturn(dictionary);
101 return dictionary;
102 }
103
104 @SuppressWarnings("unchecked")
105 private Dictionary<String, String> getDictionaryMockDeviceEntryNumberFomatEx(ComponentContext componentContext) {
106 Dictionary<String, String> dictionary = EasyMock
107 .createMock(Dictionary.class);
Samir Anand7b270f52015-07-13 17:27:11 +0530108 expect(dictionary.get(DEV_CONFIG))
109 .andReturn(CONFIG_WITH_INVALID_ENTRY_NUMBER)
Sanjay S0d4093f2015-05-06 14:55:04 +0530110 .andThrow(new NumberFormatException());
111 replay(dictionary);
112 expect(componentContext.getProperties()).andReturn(dictionary);
113 return dictionary;
114 }
115
116 @SuppressWarnings("unchecked")
117 private Dictionary<String, String> getDictionaryMockWithoutUsernameAndPassword(ComponentContext componentContext) {
118 Dictionary<String, String> dictionary = EasyMock
119 .createMock(Dictionary.class);
Samir Anand7b270f52015-07-13 17:27:11 +0530120 expect(dictionary.get(DEV_CONFIG)).andReturn(CONFIG_WITH_NULL_ENTRY);
Sanjay S0d4093f2015-05-06 14:55:04 +0530121 replay(dictionary);
122 expect(componentContext.getProperties()).andReturn(dictionary);
123 return dictionary;
124 }
125
126 @SuppressWarnings("unchecked")
127 private Dictionary<String, String> getDictionaryMockWithDifferentDeviceState(ComponentContext componentContext) {
128 Dictionary<String, String> dictionary = EasyMock
129 .createMock(Dictionary.class);
Samir Anand7b270f52015-07-13 17:27:11 +0530130 expect(dictionary.get(DEV_CONFIG))
131 .andReturn(CONFIG_WITH_DIFFERENT_DEVICE_STATE);
Sanjay S0d4093f2015-05-06 14:55:04 +0530132 replay(dictionary);
133 expect(componentContext.getProperties()).andReturn(dictionary);
134 return dictionary;
135 }
136
137 @SuppressWarnings("unchecked")
138 private Dictionary<String, String> getDictionaryMockDeviceWithArrayOutOFBoundEx(ComponentContext componentContext) {
139 Dictionary<String, String> dictionary = EasyMock
140 .createMock(Dictionary.class);
Samir Anand7b270f52015-07-13 17:27:11 +0530141 expect(dictionary.get(DEV_CONFIG))
142 .andReturn(CONFIG_WITH_ARRAY_OUT_OF_BOUNDEX)
Sanjay S0d4093f2015-05-06 14:55:04 +0530143 .andThrow(new ArrayIndexOutOfBoundsException());
144 replay(dictionary);
145 expect(componentContext.getProperties()).andReturn(dictionary);
146 return dictionary;
147 }
148
149 @SuppressWarnings("unchecked")
150 private Dictionary<String, String> getDictionaryMockDeviceEntryForDeactivate(ComponentContext componentContext) {
151 Dictionary<String, String> dictionary = EasyMock
152 .createMock(Dictionary.class);
Samir Anand7b270f52015-07-13 17:27:11 +0530153 expect(dictionary.get(DEV_CONFIG))
154 .andReturn(CONFIG_ENTRY_FOR_DEACTIVATE)
Sanjay S0d4093f2015-05-06 14:55:04 +0530155 .andThrow(new ArrayIndexOutOfBoundsException());
156 replay(dictionary);
157 expect(componentContext.getProperties()).andReturn(dictionary);
158 return dictionary;
159 }
160
Samir Anand7b270f52015-07-13 17:27:11 +0530161 @Ignore
162 @Test(expected = IOException.class)
163 public void testSSHAuthentication() throws IOException, JNCException {
164 TestDeviceCreator objForTestDev = new TestDeviceCreator(
165 new NetconfDevice(
166 DEVICE_IP,
167 DEVICE_PORT,
168 DEVICE_USERNAME,
169 DEVICE_PASSWORD),
Sanjay S0d4093f2015-05-06 14:55:04 +0530170 true);
171 objForTestDev.run();
172 }
173
174 @After
175 public void tearDown() {
176 provider.providerRegistry = null;
177 provider.cfgService = null;
178 }
179
Sanjay S0d4093f2015-05-06 14:55:04 +0530180 // To check if deviceCfgValue is empty or null
181 @Test
182 public void testActiveWithcomponentContextIsNull() {
183
184 ComponentContext componentContext = EasyMock
185 .createMock(ComponentContext.class);
186 getDictionaryMockWithoutValues(componentContext);
187 replay(componentContext);
188 provider.activate(componentContext);
189 }
190
191 // To check deviceEntry and device is null
192 @Test
193 public void testActiveWithDeviceEntryIsNull() {
194
195 ComponentContext componentContext = EasyMock
196 .createMock(ComponentContext.class);
197 getDictionaryMockWithDeviceEntryNull(componentContext);
198 replay(componentContext);
199 provider.activate(componentContext);
200 }
201
202 @Test
203 public void testActiveWithDeviceEntryWithoutUsernameAndPassword() {
204
205 ComponentContext componentContext = EasyMock
206 .createMock(ComponentContext.class);
207 getDictionaryMockWithoutUsernameAndPassword(componentContext);
208 replay(componentContext);
209 provider.activate(componentContext);
210 }
211
212 @Test
213 public void testActiveWithDeviceEntryWithNumberFomatEx() {
214
215 ComponentContext componentContext = EasyMock
216 .createMock(ComponentContext.class);
217 getDictionaryMockDeviceEntryNumberFomatEx(componentContext);
218 replay(componentContext);
219 provider.activate(componentContext);
220 }
221
222 @Test
223 public void testActiveWithDeviceEntryWithDifferentDeviceState() {
224
225 ComponentContext componentContext = EasyMock
226 .createMock(ComponentContext.class);
227 getDictionaryMockWithDifferentDeviceState(componentContext);
228 replay(componentContext);
229 provider.activate(componentContext);
230 }
231
232 @Test
233 public void testActiveWithDeviceEntryWithArrayOutOFBoundEx() {
234
235 ComponentContext componentContext = EasyMock
236 .createMock(ComponentContext.class);
237 getDictionaryMockDeviceWithArrayOutOFBoundEx(componentContext);
238 replay(componentContext);
239 provider.activate(componentContext);
240 }
241
242 @Test
243 public void isReachableWithInvalidDeviceId() {
244 assertFalse("Initially the Device ID Should not be reachable",
245 provider.isReachable(DID1));
Samir Anand7b270f52015-07-13 17:27:11 +0530246 NetconfDevice device = new NetconfDevice(NULL, ZERO, NULL, NULL);
Sanjay S0d4093f2015-05-06 14:55:04 +0530247 provider.netconfDeviceMap.put(DID1, device);
248 assertFalse("Particular Device ID cannot be Reachable",
249 provider.isReachable(DID1));
250 }
251
252 @Test
253 public void testDeactivate() {
254
255 ComponentContext componentContext = EasyMock
256 .createMock(ComponentContext.class);
257 getDictionaryMockDeviceEntryForDeactivate(componentContext);
258 replay(componentContext);
Samir Anand7b270f52015-07-13 17:27:11 +0530259 testActiveWithDeviceEntryWithDifferentDeviceState();
Sanjay S0d4093f2015-05-06 14:55:04 +0530260 provider.deactivate(componentContext);
261 }
262
263 private class TestDeviceCreator {
264
265 private NetconfDevice device;
266 private boolean createFlag;
267
268 public TestDeviceCreator(NetconfDevice device, boolean createFlag) {
269 this.device = device;
270 this.createFlag = createFlag;
271 }
272
273 public void run() throws JNCException, IOException {
274 if (createFlag) {
275 log.info("Trying to create Device Info on ONOS core");
276 advertiseDevices();
277 } else {
278 log.info("Trying to remove Device Info on ONOS core");
279 removeDevices();
280 }
281 }
282
283 /**
284 * For each Netconf Device, remove the entry from the device store.
Sanjay S0d4093f2015-05-06 14:55:04 +0530285 */
286 private void removeDevices() {
287 if (device == null) {
288 log.warn("The Request Netconf Device is null, cannot proceed further");
289 return;
290 }
291 try {
292 DeviceId did = getDeviceId();
293 if (!netconfDeviceMap.containsKey(did)) {
294 log.error("BAD Request: 'Currently device is not discovered, "
295 + "so cannot remove/disconnect the device: "
296 + device.deviceInfo() + "'");
297 return;
298 }
299 providerService.deviceDisconnected(did);
300 device.disconnect();
301 netconfDeviceMap.remove(did);
302 delay(EVENTINTERVAL);
303 } catch (URISyntaxException uriSyntaxExcpetion) {
304 log.error("Syntax Error while creating URI for the device: "
305 + device.deviceInfo()
306 + " couldn't remove the device from the store",
307 uriSyntaxExcpetion);
308 }
309 }
310
311 /**
312 * Initialize Netconf Device object, and notify core saying device
313 * connected.
314 */
Samir Anand7b270f52015-07-13 17:27:11 +0530315 private void advertiseDevices() throws JNCException, IOException {
Sanjay S0d4093f2015-05-06 14:55:04 +0530316 try {
317 if (device == null) {
318 log.warn("The Request Netconf Device is null, cannot proceed further");
319 return;
320 }
321 device.init();
322 DeviceId did = getDeviceId();
323 ChassisId cid = new ChassisId();
324 DeviceDescription desc = new DefaultDeviceDescription(
325 did.uri(),
326 Device.Type.OTHER,
Samir Anand7b270f52015-07-13 17:27:11 +0530327 NULL,
328 NULL,
329 NULL,
330 NULL, cid);
Sanjay S0d4093f2015-05-06 14:55:04 +0530331 log.info("Persisting Device" + did.uri().toString());
332
333 netconfDeviceMap.put(did, device);
334 providerService.deviceConnected(did, desc);
335 log.info("Done with Device Info Creation on ONOS core. Device Info: "
336 + device.deviceInfo() + " " + did.uri().toString());
337 delay(EVENTINTERVAL);
338 } catch (URISyntaxException e) {
339 log.error("Syntax Error while creating URI for the device: "
340 + device.deviceInfo()
341 + " couldn't persist the device onto the store", e);
342 } catch (JNCException e) {
343 throw e;
Sanjay S0d4093f2015-05-06 14:55:04 +0530344 } catch (IOException e) {
345 throw e;
346 } catch (Exception e) {
347 log.error("Error while initializing session for the device: "
Samir Anand7b270f52015-07-13 17:27:11 +0530348 + device.deviceInfo(), e);
Sanjay S0d4093f2015-05-06 14:55:04 +0530349 }
350 }
351
352 private DeviceId getDeviceId() throws URISyntaxException {
353 String additionalSSP = new StringBuilder(device.getUsername())
Samir Anand7b270f52015-07-13 17:27:11 +0530354 .append(AT_THE_RATE).append(device.getSshHost())
355 .append(COLON).append(device.getSshPort()).toString();
356 DeviceId did = DeviceId.deviceId(new URI(SCHEME_NETCONF,
357 additionalSSP, null));
Sanjay S0d4093f2015-05-06 14:55:04 +0530358 return did;
359 }
360 }
361
362 private class TestDeviceRegistry implements DeviceProviderRegistry {
363
364 @Override
365 public DeviceProviderService register(DeviceProvider provider) {
366 return new TestProviderService();
367 }
368
369 @Override
370 public void unregister(DeviceProvider provider) {
371 }
372
373 @Override
374 public Set<ProviderId> getProviders() {
375 return null;
376 }
377
378 private class TestProviderService implements DeviceProviderService {
379
HIGUCHI Yutaea39db52015-06-12 12:02:38 -0700380 @Override
Sanjay S0d4093f2015-05-06 14:55:04 +0530381 public DeviceProvider provider() {
382 return null;
383 }
384
HIGUCHI Yutaea39db52015-06-12 12:02:38 -0700385 @Override
Sanjay S0d4093f2015-05-06 14:55:04 +0530386 public void deviceConnected(DeviceId deviceId,
387 DeviceDescription deviceDescription) {
388 }
389
HIGUCHI Yutaea39db52015-06-12 12:02:38 -0700390 @Override
Sanjay S0d4093f2015-05-06 14:55:04 +0530391 public void deviceDisconnected(DeviceId deviceId) {
392
393 }
394
HIGUCHI Yutaea39db52015-06-12 12:02:38 -0700395 @Override
Sanjay S0d4093f2015-05-06 14:55:04 +0530396 public void updatePorts(DeviceId deviceId,
397 List<PortDescription> portDescriptions) {
398
399 }
400
HIGUCHI Yutaea39db52015-06-12 12:02:38 -0700401 @Override
Sanjay S0d4093f2015-05-06 14:55:04 +0530402 public void portStatusChanged(DeviceId deviceId,
403 PortDescription portDescription) {
404
405 }
406
HIGUCHI Yutaea39db52015-06-12 12:02:38 -0700407 @Override
Sanjay S0d4093f2015-05-06 14:55:04 +0530408 public void receivedRoleReply(DeviceId deviceId,
409 MastershipRole requested,
410 MastershipRole response) {
411
412 }
413
HIGUCHI Yutaea39db52015-06-12 12:02:38 -0700414 @Override
Sanjay S0d4093f2015-05-06 14:55:04 +0530415 public void updatePortStatistics(DeviceId deviceId,
416 Collection<PortStatistics> portStatistics) {
417
418 }
419 }
420 }
421}