e56c5959c7665ad86ed6daf078ad3ecac467611c
[onosfw.git] /
1 /*
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  */
16 package org.onosproject.provider.netconf.device.impl;
17
18 import static org.easymock.EasyMock.expect;
19 import static org.easymock.EasyMock.replay;
20 import static org.junit.Assert.assertFalse;
21 import static org.onlab.util.Tools.delay;
22 import static org.onosproject.provider.netconf.device.impl.NetconfDeviceProviderTestConstant.*;
23 import static org.slf4j.LoggerFactory.getLogger;
24
25 import java.io.IOException;
26 import java.net.URI;
27 import java.net.URISyntaxException;
28 import java.util.Collection;
29 import java.util.Dictionary;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.concurrent.ConcurrentHashMap;
34
35 import org.easymock.EasyMock;
36 import org.junit.After;
37 import org.junit.Before;
38 import org.junit.Ignore;
39 import org.junit.Test;
40 import org.onlab.packet.ChassisId;
41 import org.onosproject.cfg.ComponentConfigService;
42 import org.onosproject.net.Device;
43 import org.onosproject.net.DeviceId;
44 import org.onosproject.net.MastershipRole;
45 import org.onosproject.net.device.DefaultDeviceDescription;
46 import org.onosproject.net.device.DeviceDescription;
47 import org.onosproject.net.device.DeviceProvider;
48 import org.onosproject.net.device.DeviceProviderRegistry;
49 import org.onosproject.net.device.DeviceProviderService;
50 import org.onosproject.net.device.PortDescription;
51 import org.onosproject.net.device.PortStatistics;
52 import org.onosproject.net.provider.ProviderId;
53 import org.osgi.service.component.ComponentContext;
54 import org.slf4j.Logger;
55
56 import com.tailf.jnc.JNCException;
57
58 /**
59  * Test Case to Validate Netconf Device Provider.
60  */
61 public class NetconfDeviceProviderTest {
62     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
70     private static final DeviceId DID1 = DeviceId.deviceId(DEVICE_ID);
71
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")
85     private Dictionary<String, String> getDictionaryMockWithoutValues(ComponentContext componentContext) {
86         Dictionary<String, String> dictionary = EasyMock
87                 .createMock(Dictionary.class);
88         expect(dictionary.get(DEV_CONFIG)).andReturn(NULL);
89         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);
98         expect(dictionary.get(DEV_CONFIG)).andReturn(NULL_NULL);
99         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);
108         expect(dictionary.get(DEV_CONFIG))
109                 .andReturn(CONFIG_WITH_INVALID_ENTRY_NUMBER)
110                 .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);
120         expect(dictionary.get(DEV_CONFIG)).andReturn(CONFIG_WITH_NULL_ENTRY);
121         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);
130         expect(dictionary.get(DEV_CONFIG))
131                 .andReturn(CONFIG_WITH_DIFFERENT_DEVICE_STATE);
132         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);
141         expect(dictionary.get(DEV_CONFIG))
142                 .andReturn(CONFIG_WITH_ARRAY_OUT_OF_BOUNDEX)
143                 .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);
153         expect(dictionary.get(DEV_CONFIG))
154                 .andReturn(CONFIG_ENTRY_FOR_DEACTIVATE)
155                 .andThrow(new ArrayIndexOutOfBoundsException());
156         replay(dictionary);
157         expect(componentContext.getProperties()).andReturn(dictionary);
158         return dictionary;
159     }
160
161     @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),
170                                                                 true);
171         objForTestDev.run();
172     }
173
174     @After
175     public void tearDown() {
176         provider.providerRegistry = null;
177         provider.cfgService = null;
178     }
179
180     // 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));
246         NetconfDevice device = new NetconfDevice(NULL, ZERO, NULL, NULL);
247         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);
259         testActiveWithDeviceEntryWithDifferentDeviceState();
260         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.
285          */
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          */
315         private void advertiseDevices() throws JNCException, IOException {
316             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,
327                                                                       NULL,
328                                                                       NULL,
329                                                                       NULL,
330                                                                       NULL, cid);
331                 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;
344             } catch (IOException e) {
345                 throw e;
346             } catch (Exception e) {
347                 log.error("Error while initializing session for the device: "
348                         + device.deviceInfo(), e);
349             }
350         }
351
352         private DeviceId getDeviceId() throws URISyntaxException {
353             String additionalSSP = new StringBuilder(device.getUsername())
354                     .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));
358             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
380             @Override
381             public DeviceProvider provider() {
382                 return null;
383             }
384
385             @Override
386             public void deviceConnected(DeviceId deviceId,
387                                         DeviceDescription deviceDescription) {
388             }
389
390             @Override
391             public void deviceDisconnected(DeviceId deviceId) {
392
393             }
394
395             @Override
396             public void updatePorts(DeviceId deviceId,
397                                     List<PortDescription> portDescriptions) {
398
399             }
400
401             @Override
402             public void portStatusChanged(DeviceId deviceId,
403                                           PortDescription portDescription) {
404
405             }
406
407             @Override
408             public void receivedRoleReply(DeviceId deviceId,
409                                           MastershipRole requested,
410                                           MastershipRole response) {
411
412             }
413
414             @Override
415             public void updatePortStatistics(DeviceId deviceId,
416                                              Collection<PortStatistics> portStatistics) {
417
418             }
419         }
420     }
421 }