[ONOS-6076] Moving NETCONF devices configuration under devices key

Change-Id: I5a0dc2c2d33c7cd79655497f66373c6f4f9af656
diff --git a/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java b/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java
index a0b84ca..6ebaef9 100644
--- a/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java
+++ b/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java
@@ -16,9 +16,11 @@
 
 package org.onosproject.provider.netconf.device.impl;
 
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.ImmutableSet;
+import org.apache.commons.lang.StringUtils;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.onlab.packet.ChassisId;
 import org.onlab.packet.IpAddress;
@@ -35,6 +37,7 @@
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.config.Config;
+import org.onosproject.net.config.ConfigApplyDelegate;
 import org.onosproject.net.config.ConfigFactory;
 import org.onosproject.net.config.NetworkConfigEvent;
 import org.onosproject.net.config.NetworkConfigListener;
@@ -67,6 +70,8 @@
 import org.onosproject.netconf.NetconfController;
 import org.onosproject.netconf.NetconfDeviceListener;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -75,6 +80,7 @@
 import java.util.concurrent.CopyOnWriteArraySet;
 
 import static org.easymock.EasyMock.*;
+import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.*;
 import static org.onlab.junit.TestTools.assertAfter;
 import static org.onosproject.provider.netconf.device.impl.NetconfDeviceProvider.APP_NAME;
@@ -94,17 +100,45 @@
     private final MastershipService mastershipService = new MockMastershipService();
     private final Driver driver = new MockDriver();
     private final NetworkConfigRegistry cfgService = new MockNetworkConfigRegistry();
+    private final Set<ConfigFactory> cfgFactories = new HashSet<>();
     private final DeviceKeyAdminService deviceKeyAdminService = new DeviceKeyAdminServiceAdapter();
     private final DeviceStore deviceStore = new MockDeviceStore();
 
     //Class for testing
     private final NetworkConfigEvent deviceAddedEvent =
             new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_ADDED,
+                                   DeviceId.deviceId(NETCONF_DEVICE_ID_STRING), NetconfDeviceConfig.class);
+    private final NetconfDeviceConfig netconfDeviceConfig = new NetconfDeviceConfig();
+    private final NetconfDeviceConfig netconfDeviceConfigSshKey = new NetconfDeviceConfig();
+    private final NetconfDeviceConfig netconfDeviceConfigEmptyIpv4 = new NetconfDeviceConfig();
+    private final NetconfDeviceConfig netconfDeviceConfigEmptyIpv6 = new NetconfDeviceConfig();
+    private final NetworkConfigEvent deviceAddedEventOld =
+            new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_ADDED,
                                    null, NetconfProviderConfig.class);
+    private final NetworkConfigEvent deviceAddedEventTranslated =
+            new NetworkConfigEvent(NetworkConfigEvent.Type.CONFIG_ADDED,
+                                   DeviceId.deviceId(NETCONF_DEVICE_ID_STRING_OLD),
+                                   NetconfDeviceConfig.class);
     private final NetconfProviderConfig netconfProviderConfig = new MockNetconfProviderConfig();
-    private static final String IP = "1.1.1.1";
+    private static final String NETCONF_DEVICE_ID_STRING = "netconf:1.1.1.1:830";
+    private static final String NETCONF_DEVICE_ID_STRING_OLD = "netconf:1.1.1.2:1";
+    private static final String NETCONF_DEVICE_ID_STRING_IPv6 = "netconf:2001:0db8:0000:0000:0000:ff00:0042:8329:830";
+    private static final String IP_STRING = "1.1.1.1";
+    private static final String IP_STRING_OLD = "1.1.1.2";
+    private static final String IP_STRING_IPv6 = "2001:0db8:0000:0000:0000:ff00:0042:8329";
+    private static final IpAddress IP = IpAddress.valueOf(IP_STRING);
+    private static final IpAddress IP_OLD = IpAddress.valueOf(IP_STRING_OLD);
+    private static final IpAddress IP_v6 = IpAddress.valueOf(IP_STRING_IPv6);
+    private static final int PORT = 830;
     private static final String TEST = "test";
     private static final int DELAY_DISCOVERY = 500;
+    private static final int DELAY_DURATION_DISCOVERY = 1500;
+
+    //Testing Files
+    InputStream jsonStream = NetconfDeviceProviderTest.class
+            .getResourceAsStream("/device.json");
+    InputStream jsonStreamSshKey = NetconfDeviceProviderTest.class
+            .getResourceAsStream("/deviceSshKey.json");
 
     //Provider related classes
     private CoreService coreService;
@@ -112,15 +146,16 @@
             new DefaultApplicationId(100, APP_NAME);
     private DeviceDescriptionDiscovery descriptionDiscovery = new TestDescription();
     private Set<DeviceListener> deviceListeners = new HashSet<>();
-    private ConfigFactory cfgFactory;
     private Set<NetworkConfigListener> netCfgListeners = new HashSet<>();
     private HashMap<DeviceId, Device> devices = new HashMap<>();
 
     //Controller related classes
     private Set<NetconfDeviceListener> netconfDeviceListeners = new CopyOnWriteArraySet<>();
+    private boolean available = false;
+    private boolean firstRequest = true;
 
     @Before
-    public void setUp() {
+    public void setUp() throws IOException {
         coreService = createMock(CoreService.class);
         expect(coreService.registerApplication(APP_NAME))
                 .andReturn(appId).anyTimes();
@@ -135,6 +170,21 @@
         provider.componentConfigService = new ComponentConfigAdapter();
         AbstractProjectableModel.setDriverService(null, new DriverServiceAdapter());
         provider.activate(null);
+        devices.clear();
+        available = false;
+        firstRequest = true;
+        DeviceId subject = DeviceId.deviceId(NETCONF_DEVICE_ID_STRING);
+        DeviceId subjectIpv6 = DeviceId.deviceId(NETCONF_DEVICE_ID_STRING_IPv6);
+        String key = "netconf";
+        ObjectMapper mapper = new ObjectMapper();
+        JsonNode jsonNode = mapper.readTree(jsonStream);
+        ConfigApplyDelegate delegate = new MockDelegate();
+        netconfDeviceConfig.init(subject, key, jsonNode, mapper, delegate);
+        JsonNode jsonNodesshKey = mapper.readTree(jsonStreamSshKey);
+        netconfDeviceConfigSshKey.init(subject, key, jsonNodesshKey, mapper, delegate);
+        JsonNode jsonNodeEmpty = mapper.createObjectNode();
+        netconfDeviceConfigEmptyIpv4.init(subject, key, jsonNodeEmpty, mapper, delegate);
+        netconfDeviceConfigEmptyIpv6.init(subjectIpv6, key, jsonNodeEmpty, mapper, delegate);
     }
 
     @Test
@@ -142,6 +192,7 @@
         assertTrue("Provider should be registered", deviceRegistry.getProviders().contains(provider.id()));
         assertEquals("Incorrect device service", deviceService, provider.deviceService);
         assertEquals("Incorrect provider service", providerService, provider.providerService);
+        assertTrue("Incorrect config factories", cfgFactories.containsAll(provider.factories));
         assertEquals("Device listener should be added", 1, deviceListeners.size());
         assertFalse("Thread to connect device should be running",
                     provider.executor.isShutdown() || provider.executor.isTerminated());
@@ -156,18 +207,69 @@
         assertTrue("Thread to connect device should be shutdown", provider.executor.isShutdown());
         assertTrue("Scheduled task to update device should be shutdown", provider.scheduledTask.isCancelled());
         assertNull("Provider service should be null", provider.providerService);
+        assertTrue("Network config factories not removed", cfgFactories.isEmpty());
         assertEquals("Controller listener should be removed", 0, netconfDeviceListeners.size());
     }
 
     @Test
-    @Ignore("Test is brittle")
-    public void addDevice() {
+    public void configuration() {
+        assertTrue("Configuration should be valid", netconfDeviceConfig.isValid());
+        assertThat(netconfDeviceConfig.ip(), is(IP));
+        assertThat(netconfDeviceConfig.port(), is(PORT));
+        assertThat(netconfDeviceConfig.username(), is(TEST));
+        assertThat(netconfDeviceConfig.password(), is(TEST));
+        assertThat(netconfDeviceConfigSshKey.sshKey(), is(TEST));
+    }
+
+    @Test
+    public void configurationDeviceIdIpv4() {
+        assertTrue("Configuration should be valid", netconfDeviceConfigEmptyIpv4.isValid());
+        assertThat(netconfDeviceConfigEmptyIpv4.ip(), is(IP));
+        assertThat(netconfDeviceConfigEmptyIpv4.port(), is(PORT));
+        assertThat(netconfDeviceConfigEmptyIpv4.username(), is(StringUtils.EMPTY));
+        assertThat(netconfDeviceConfigEmptyIpv4.password(), is(StringUtils.EMPTY));
+        assertThat(netconfDeviceConfigEmptyIpv4.sshKey(), is(StringUtils.EMPTY));
+    }
+
+    @Test
+    public void configurationDeviceIdIpv6() {
+        assertTrue("Configuration should be valid", netconfDeviceConfigEmptyIpv6.isValid());
+        assertThat(netconfDeviceConfigEmptyIpv6.ip(), is(IP_v6));
+        assertThat(netconfDeviceConfigEmptyIpv6.port(), is(PORT));
+        assertThat(netconfDeviceConfigEmptyIpv6.username(), is(StringUtils.EMPTY));
+        assertThat(netconfDeviceConfigEmptyIpv6.password(), is(StringUtils.EMPTY));
+        assertThat(netconfDeviceConfigEmptyIpv6.sshKey(), is(StringUtils.EMPTY));
+    }
+
+    @Test
+    public void addDeviceOld() {
         assertNotNull(providerService);
         assertTrue("Event should be relevant", provider.cfgListener.isRelevant(deviceAddedEvent));
+        assertTrue("Event should be relevant", provider.cfgListener.isRelevant(deviceAddedEventOld));
+        available = true;
+        provider.cfgListener.event(deviceAddedEventOld);
+
+        assertAfter(DELAY_DISCOVERY, DELAY_DURATION_DISCOVERY, () -> {
+            assertEquals("Device should be added", 1, deviceStore.getDeviceCount());
+            assertTrue("Device incorrectly added" + NETCONF_DEVICE_ID_STRING_OLD,
+                       devices.containsKey(DeviceId.deviceId(NETCONF_DEVICE_ID_STRING_OLD)));
+        });
+        devices.clear();
+    }
+
+    @Test
+    public void addDeviceNew() {
+        assertNotNull(providerService);
+        assertTrue("Event should be relevant", provider.cfgListener.isRelevant(deviceAddedEvent));
+        assertTrue("Event should be relevant", provider.cfgListener.isRelevant(deviceAddedEventOld));
+        available = true;
         provider.cfgListener.event(deviceAddedEvent);
 
-        assertAfter(DELAY_DISCOVERY, () ->
-                assertEquals("Device should be added", 1, deviceStore.getDeviceCount()));
+        assertAfter(DELAY_DISCOVERY, DELAY_DURATION_DISCOVERY, () -> {
+            assertEquals("Device should be added", 1, deviceStore.getDeviceCount());
+            assertTrue("Device incorrectly added" + NETCONF_DEVICE_ID_STRING,
+                       devices.containsKey(DeviceId.deviceId(NETCONF_DEVICE_ID_STRING)));
+        });
         devices.clear();
     }
 
@@ -244,7 +346,6 @@
                                                     desc.manufacturer(), desc.hwVersion(),
                                                     desc.swVersion(), desc.serialNumber(),
                                                     desc.chassisId(), desc.annotations()));
-
             return null;
         }
 
@@ -269,15 +370,16 @@
     }
 
     private class MockNetworkConfigRegistry extends NetworkConfigRegistryAdapter {
+        NetconfDeviceConfig cfg = null;
 
         @Override
         public void registerConfigFactory(ConfigFactory configFactory) {
-            cfgFactory = configFactory;
+            cfgFactories.add(configFactory);
         }
 
         @Override
         public void unregisterConfigFactory(ConfigFactory configFactory) {
-            cfgFactory = null;
+            cfgFactories.remove(configFactory);
         }
 
         @Override
@@ -293,17 +395,61 @@
 
         @Override
         public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
-            if (configClass.equals(NetconfProviderConfig.class)) {
-                return (C) netconfProviderConfig;
-            } else {
-                return (C) new BasicDeviceConfig();
+            if (available) {
+                if (configClass.equals(NetconfProviderConfig.class)) {
+                    return (C) netconfProviderConfig;
+                }
+                DeviceId did = (DeviceId) subject;
+                if (configClass.equals(NetconfDeviceConfig.class)
+                        && did.equals(DeviceId.deviceId(NETCONF_DEVICE_ID_STRING))) {
+                    return (C) netconfDeviceConfig;
+                } else if (configClass.equals(NetconfDeviceConfig.class)
+                        && did.equals(DeviceId.deviceId(NETCONF_DEVICE_ID_STRING_OLD))) {
+                    if (firstRequest) {
+                        firstRequest = false;
+                        return null;
+                    }
+                    return (C) cfg;
+                } else {
+                    return (C) new BasicDeviceConfig();
+                }
             }
+            return null;
         }
+
+        @Override
+        public <S, C extends Config<S>> C applyConfig(S subject, Class<C> configClass,
+                                                      JsonNode json) {
+            cfg = new NetconfDeviceConfig();
+            ObjectMapper mapper = new ObjectMapper();
+            cfg.init((DeviceId) subject, "netconf", mapper.createObjectNode(), mapper, null);
+            cfg.setIp(json.get("ip").asText())
+                    .setPort(json.get("port").asInt())
+                    .setUsername(json.get("username").asText())
+                    .setPassword(json.get("password").asText())
+                    .setSshKey(json.get("sshkey").asText());
+            provider.cfgListener.event(deviceAddedEventTranslated);
+            return (C) cfg;
+        }
+
+        @Override
+        public <S, C extends Config<S>> Set<S> getSubjects(Class<S> subjectClass, Class<C> configClass) {
+            Set<S> subjects = new HashSet<S>();
+            if (available) {
+                if (cfg != null) {
+                    subjects.add((S) DeviceId.deviceId(NETCONF_DEVICE_ID_STRING_OLD));
+                } else {
+                    subjects.add((S) DeviceId.deviceId(NETCONF_DEVICE_ID_STRING));
+                }
+            }
+            return subjects;
+        }
+
     }
 
     private class MockNetconfProviderConfig extends NetconfProviderConfig {
         protected NetconfDeviceAddress deviceInfo =
-                new NetconfDeviceAddress(IpAddress.valueOf(IP), 1, TEST, TEST);
+                new NetconfDeviceAddress(IP_OLD, 1, TEST, TEST);
 
         @Override
         public Set<NetconfProviderConfig.NetconfDeviceAddress> getDevicesAddresses() throws ConfigException {
@@ -362,4 +508,10 @@
             portDescriptions.add(portDescription);
         }
     }
+
+    private class MockDelegate implements ConfigApplyDelegate {
+        @Override
+        public void onApply(Config configFile) {
+        }
+    }
 }