[ONOS-6076] Moving NETCONF devices configuration under devices key
Change-Id: I5a0dc2c2d33c7cd79655497f66373c6f4f9af656
diff --git a/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceConfig.java b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceConfig.java
new file mode 100644
index 0000000..ea17015
--- /dev/null
+++ b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceConfig.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2015-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.provider.netconf.device.impl;
+
+import com.google.common.annotations.Beta;
+import org.apache.commons.lang3.tuple.Pair;
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.Config;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Configuration for Netconf provider.
+ */
+@Beta
+public class NetconfDeviceConfig extends Config<DeviceId> {
+
+ private static final String IP = "ip";
+ private static final String PORT = "port";
+ private static final String USERNAME = "username";
+ private static final String PASSWORD = "password";
+ private static final String SSHKEY = "sshkey";
+
+ @Override
+ public boolean isValid() {
+ return hasOnlyFields(IP, PORT, USERNAME, PASSWORD, SSHKEY) &&
+ ip() != null;
+ }
+
+ /**
+ * Gets the Ip of the NETCONF device.
+ *
+ * @return ip
+ */
+ public IpAddress ip() {
+ return IpAddress.valueOf(get(IP, checkNotNull(extractIpPort()).getKey()));
+ }
+
+ /**
+ * Gets the port of the NETCONF device.
+ *
+ * @return port
+ */
+ public int port() {
+ return get(PORT, checkNotNull(extractIpPort()).getValue());
+ }
+
+ /**
+ * Gets the username of the NETCONF device.
+ *
+ * @return username
+ */
+ public String username() {
+ return get(USERNAME, "");
+ }
+
+ /**
+ * Gets the password of the NETCONF device.
+ *
+ * @return password
+ */
+ public String password() {
+ return get(PASSWORD, "");
+ }
+
+ /**
+ * Gets the sshKey of the NETCONF device.
+ *
+ * @return sshkey
+ */
+ public String sshKey() {
+ return get(SSHKEY, "");
+ }
+
+ /**
+ * Sets the Ip for the Device.
+ *
+ * @param ip the ip
+ * @return instance for chaining
+ */
+ public NetconfDeviceConfig setIp(String ip) {
+ return (NetconfDeviceConfig) setOrClear(IP, ip);
+ }
+
+ /**
+ * Sets the Port for the Device.
+ *
+ * @param port the port
+ * @return instance for chaining
+ */
+ public NetconfDeviceConfig setPort(int port) {
+ return (NetconfDeviceConfig) setOrClear(PORT, port);
+ }
+
+ /**
+ * Sets the username for the Device.
+ *
+ * @param username username
+ * @return instance for chaining
+ */
+ public NetconfDeviceConfig setUsername(String username) {
+ return (NetconfDeviceConfig) setOrClear(USERNAME, username);
+ }
+
+ /**
+ * Sets the password for the Device.
+ *
+ * @param password password
+ * @return instance for chaining
+ */
+ public NetconfDeviceConfig setPassword(String password) {
+ return (NetconfDeviceConfig) setOrClear(PASSWORD, password);
+ }
+
+ /**
+ * Sets the SshKey for the Device.
+ *
+ * @param sshKey sshKey as string
+ * @return instance for chaining
+ */
+ public NetconfDeviceConfig setSshKey(String sshKey) {
+ return (NetconfDeviceConfig) setOrClear(SSHKEY, sshKey);
+ }
+
+ private Pair<String, Integer> extractIpPort() {
+ String info = subject.toString();
+ if (info.startsWith(NetconfDeviceProvider.SCHEME_NAME)) {
+ //+1 is due to length of colon separator
+ String ip = info.substring(info.indexOf(":") + 1, info.lastIndexOf(":"));
+ int port = Integer.parseInt(info.substring(info.lastIndexOf(":") + 1));
+ return Pair.of(ip, port);
+ }
+ return null;
+ }
+}
diff --git a/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java
index 215f104..c66643f 100644
--- a/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java
+++ b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java
@@ -16,8 +16,11 @@
package org.onosproject.provider.netconf.device.impl;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -44,6 +47,7 @@
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceDescriptionDiscovery;
@@ -73,6 +77,8 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
+import java.util.List;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -119,7 +125,7 @@
protected static final String APP_NAME = "org.onosproject.netconf";
- private static final String SCHEME_NAME = "netconf";
+ protected static final String SCHEME_NAME = "netconf";
private static final String DEVICE_PROVIDER_PACKAGE = "org.onosproject.netconf.provider.device";
private static final String UNKNOWN = "unknown";
protected static final String ISNULL = "NetconfDeviceInfo is null";
@@ -147,7 +153,15 @@
private InternalDeviceListener deviceListener = new InternalDeviceListener();
protected ScheduledFuture<?> scheduledTask;
- private final ConfigFactory factory =
+ protected final List<ConfigFactory> factories = ImmutableList.of(
+ new ConfigFactory<DeviceId, NetconfDeviceConfig>(
+ SubjectFactories.DEVICE_SUBJECT_FACTORY,
+ NetconfDeviceConfig.class, SCHEME_NAME) {
+ @Override
+ public NetconfDeviceConfig createConfig() {
+ return new NetconfDeviceConfig();
+ }
+ },
new ConfigFactory<ApplicationId, NetconfProviderConfig>(APP_SUBJECT_FACTORY,
NetconfProviderConfig.class,
"devices",
@@ -156,7 +170,8 @@
public NetconfProviderConfig createConfig() {
return new NetconfProviderConfig();
}
- };
+ });
+
protected final NetworkConfigListener cfgListener = new InternalNetworkConfigListener();
private ApplicationId appId;
private boolean active;
@@ -168,10 +183,11 @@
componentConfigService.registerProperties(getClass());
providerService = providerRegistry.register(this);
appId = coreService.registerApplication(APP_NAME);
- cfgService.registerConfigFactory(factory);
+ factories.forEach(cfgService::registerConfigFactory);
cfgService.addListener(cfgListener);
controller.addDeviceListener(innerNodeListener);
deviceService.addListener(deviceListener);
+ translateConfig();
executor.execute(NetconfDeviceProvider.this::connectDevices);
modified(context);
log.info("Started");
@@ -191,7 +207,7 @@
deviceService.removeListener(deviceListener);
providerRegistry.unregister(this);
providerService = null;
- cfgService.unregisterConfigFactory(factory);
+ factories.forEach(cfgService::unregisterConfigFactory);
scheduledTask.cancel(true);
executor.shutdown();
log.info("Stopped");
@@ -343,49 +359,31 @@
}
private void connectDevices() {
- NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class);
- if (cfg != null) {
- try {
- cfg.getDevicesAddresses().forEach(addr -> {
- DeviceId deviceId = getDeviceId(addr.ip().toString(), addr.port());
- Preconditions.checkNotNull(deviceId, ISNULL);
- //Netconf configuration object
- ChassisId cid = new ChassisId();
- String ipAddress = addr.ip().toString();
- SparseAnnotations annotations = DefaultAnnotations.builder()
- .set(IPADDRESS, ipAddress)
- .set(PORT, String.valueOf(addr.port()))
- .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
- .build();
- DeviceDescription deviceDescription = new DefaultDeviceDescription(
- deviceId.uri(),
- Device.Type.SWITCH,
- UNKNOWN, UNKNOWN,
- UNKNOWN, UNKNOWN,
- cid, false,
- annotations);
- storeDeviceKey(addr, deviceId);
-
- if (deviceService.getDevice(deviceId) == null) {
- providerService.deviceConnected(deviceId, deviceDescription);
- }
- try {
- checkAndUpdateDevice(deviceId, deviceDescription);
- } catch (Exception e) {
- log.error("Unhandled exception checking {}", deviceId, e);
- }
- });
- } catch (ConfigException e) {
- log.error("Cannot read config error " + e);
+ Set<DeviceId> deviceSubjects =
+ cfgService.getSubjects(DeviceId.class, NetconfDeviceConfig.class);
+ deviceSubjects.forEach(deviceId -> {
+ NetconfDeviceConfig config =
+ cfgService.getConfig(deviceId, NetconfDeviceConfig.class);
+ DeviceDescription deviceDescription = createDeviceRepresentation(deviceId, config);
+ log.debug("Connecting NETCONF device {}, on {}:{} with username {}",
+ deviceId, config.ip(), config.port(), config.username());
+ storeDeviceKey(config.sshKey(), config.username(), config.password(), deviceId);
+ if (deviceService.getDevice(deviceId) == null) {
+ providerService.deviceConnected(deviceId, deviceDescription);
}
- }
+ try {
+ checkAndUpdateDevice(deviceId, deviceDescription);
+ } catch (Exception e) {
+ log.error("Unhandled exception checking {}", deviceId, e);
+ }
+ });
}
private void checkAndUpdateDevice(DeviceId deviceId, DeviceDescription deviceDescription) {
Device device = deviceService.getDevice(deviceId);
if (device == null) {
log.warn("Device {} has not been added to store, " +
- "maybe due to a problem in connectivity", deviceId);
+ "since it's not reachable", deviceId);
} else {
boolean isReachable = isReachable(deviceId);
if (isReachable && !deviceService.isAvailable(deviceId)) {
@@ -393,16 +391,19 @@
if (mastershipService.isLocalMaster(deviceId)) {
DeviceDescriptionDiscovery deviceDescriptionDiscovery =
device.as(DeviceDescriptionDiscovery.class);
- DeviceDescription updatedDeviceDescription = deviceDescriptionDiscovery.discoverDeviceDetails();
+ DeviceDescription updatedDeviceDescription =
+ deviceDescriptionDiscovery.discoverDeviceDetails();
if (updatedDeviceDescription != null &&
!descriptionEquals(device, updatedDeviceDescription)) {
providerService.deviceConnected(
deviceId, new DefaultDeviceDescription(
- updatedDeviceDescription, true, updatedDeviceDescription.annotations()));
+ updatedDeviceDescription, true,
+ updatedDeviceDescription.annotations()));
} else if (updatedDeviceDescription == null) {
providerService.deviceConnected(
deviceId, new DefaultDeviceDescription(
- deviceDescription, true, deviceDescription.annotations()));
+ deviceDescription, true,
+ deviceDescription.annotations()));
}
//if ports are not discovered, retry the discovery
if (deviceService.getPorts(deviceId).isEmpty()) {
@@ -451,48 +452,48 @@
}
private void checkAndUpdateDevices() {
- NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class);
- if (cfg != null) {
- log.info("Checking connection to devices in configuration");
- try {
- cfg.getDevicesAddresses().forEach(addr -> {
- DeviceId deviceId = getDeviceId(addr.ip().toString(), addr.port());
- Preconditions.checkNotNull(deviceId, ISNULL);
- //Netconf configuration object
- ChassisId cid = new ChassisId();
- String ipAddress = addr.ip().toString();
- SparseAnnotations annotations = DefaultAnnotations.builder()
- .set(IPADDRESS, ipAddress)
- .set(PORT, String.valueOf(addr.port()))
- .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
- .build();
- DeviceDescription deviceDescription = new DefaultDeviceDescription(
- deviceId.uri(),
- Device.Type.SWITCH,
- UNKNOWN, UNKNOWN,
- UNKNOWN, UNKNOWN,
- cid, false,
- annotations);
- storeDeviceKey(addr, deviceId);
- checkAndUpdateDevice(deviceId, deviceDescription);
- });
- } catch (ConfigException e) {
- log.error("Cannot read config error " + e);
- }
- }
+ Set<DeviceId> deviceSubjects =
+ cfgService.getSubjects(DeviceId.class, NetconfDeviceConfig.class);
+ deviceSubjects.forEach(deviceId -> {
+ NetconfDeviceConfig config =
+ cfgService.getConfig(deviceId, NetconfDeviceConfig.class);
+ DeviceDescription deviceDescription = createDeviceRepresentation(deviceId, config);
+ storeDeviceKey(config.sshKey(), config.username(), config.password(), deviceId);
+ checkAndUpdateDevice(deviceId, deviceDescription);
+ });
}
- private void storeDeviceKey(NetconfProviderConfig.NetconfDeviceAddress addr, DeviceId deviceId) {
- if (addr.sshkey().equals("")) {
+ private DeviceDescription createDeviceRepresentation(DeviceId deviceId, NetconfDeviceConfig config) {
+ Preconditions.checkNotNull(deviceId, ISNULL);
+ //Netconf configuration object
+ ChassisId cid = new ChassisId();
+ String ipAddress = config.ip().toString();
+ SparseAnnotations annotations = DefaultAnnotations.builder()
+ .set(IPADDRESS, ipAddress)
+ .set(PORT, String.valueOf(config.port()))
+ .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
+ .build();
+ return new DefaultDeviceDescription(
+ deviceId.uri(),
+ Device.Type.SWITCH,
+ UNKNOWN, UNKNOWN,
+ UNKNOWN, UNKNOWN,
+ cid, false,
+ annotations);
+ }
+
+ private void storeDeviceKey(String sshKey, String username, String password, DeviceId deviceId) {
+ if (sshKey.equals("")) {
deviceKeyAdminService.addKey(
DeviceKey.createDeviceKeyUsingUsernamePassword(
DeviceKeyId.deviceKeyId(deviceId.toString()),
- null, addr.name(), addr.password()));
+ null, username, password));
} else {
deviceKeyAdminService.addKey(
DeviceKey.createDeviceKeyUsingSshKey(
DeviceKeyId.deviceKeyId(deviceId.toString()),
- null, addr.name(), addr.password(), addr.sshkey()));
+ null, username, password,
+ sshKey));
}
}
@@ -508,7 +509,7 @@
}
deviceKeyAdminService.removeKey(DeviceKeyId.deviceKeyId(deviceId.toString()));
throw new RuntimeException(new NetconfException(
- "Can't connect to NETCONF " + "device on " + deviceId + ":" + deviceId, e));
+ "Can't connect to NETCONF device " + deviceId, e));
}
}
@@ -549,6 +550,38 @@
}
}
+
+ protected void translateConfig() {
+ NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class);
+ if (cfg != null) {
+ try {
+ cfg.getDevicesAddresses().forEach(addr -> {
+ DeviceId deviceId = getDeviceId(addr.ip().toString(), addr.port());
+ log.info("Translating config for device {}", deviceId);
+ if (cfgService.getConfig(deviceId, NetconfDeviceConfig.class) == null) {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode device = mapper.createObjectNode();
+ device.put("ip", addr.ip().toString());
+ device.put("port", addr.port());
+ device.put("username", addr.name());
+ device.put("password", addr.password());
+ device.put("sshkey", addr.sshkey());
+ cfgService.applyConfig(deviceId, NetconfDeviceConfig.class, device);
+ } else {
+ // This is a corner case where new updated config is
+ // pushed with old /app tree after an initial with the
+ // new device/ tree. Since old method will be deprecated
+ // it's ok to ignore
+ log.warn("Config for device {} already exists, ignoring", deviceId);
+ }
+
+ });
+ } catch (ConfigException e) {
+ log.error("Cannot read config error " + e);
+ }
+ }
+ }
+
/**
* Listener for configuration events.
*/
@@ -557,12 +590,20 @@
@Override
public void event(NetworkConfigEvent event) {
- executor.execute(NetconfDeviceProvider.this::connectDevices);
+ if (event.configClass().equals(NetconfDeviceConfig.class)) {
+ executor.execute(NetconfDeviceProvider.this::connectDevices);
+ } else {
+ log.warn("Injecting device via this Json is deprecated, " +
+ "please put configuration under devices/ as shown in the wiki");
+ translateConfig();
+ }
+
}
@Override
public boolean isRelevant(NetworkConfigEvent event) {
- return event.configClass().equals(NetconfProviderConfig.class) &&
+ return (event.configClass().equals(NetconfDeviceConfig.class) ||
+ event.configClass().equals(NetconfProviderConfig.class)) &&
(event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED);
}
diff --git a/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfProviderConfig.java b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfProviderConfig.java
index 2cdeb53..59cffb6 100644
--- a/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfProviderConfig.java
+++ b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfProviderConfig.java
@@ -28,8 +28,10 @@
/**
* Configuration for Netconf provider.
+ * @deprecated 1.10.0 Kingfisher
*/
@Beta
+@Deprecated
public class NetconfProviderConfig extends Config<ApplicationId> {
public static final String CONFIG_VALUE_ERROR = "Error parsing config value";
@@ -42,7 +44,6 @@
public Set<NetconfDeviceAddress> getDevicesAddresses() throws ConfigException {
Set<NetconfDeviceAddress> devicesAddresses = Sets.newHashSet();
-
try {
for (JsonNode node : array) {
String ip = node.path(IP).asText();
@@ -61,7 +62,8 @@
return devicesAddresses;
}
- public class NetconfDeviceAddress {
+ public class
+ NetconfDeviceAddress {
private final IpAddress ip;
private final int port;
private final String name;
@@ -105,4 +107,4 @@
}
}
-}
+}
\ No newline at end of file
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) {
+ }
+ }
}
diff --git a/providers/netconf/device/src/test/resources/device.json b/providers/netconf/device/src/test/resources/device.json
new file mode 100644
index 0000000..f11a264
--- /dev/null
+++ b/providers/netconf/device/src/test/resources/device.json
@@ -0,0 +1,6 @@
+{
+ "ip":"1.1.1.1",
+ "port":830,
+ "username":"test",
+ "password":"test"
+}
diff --git a/providers/netconf/device/src/test/resources/deviceSshKey.json b/providers/netconf/device/src/test/resources/deviceSshKey.json
new file mode 100644
index 0000000..c799935
--- /dev/null
+++ b/providers/netconf/device/src/test/resources/deviceSshKey.json
@@ -0,0 +1,7 @@
+{
+ "ip":"1.1.1.1",
+ "port":830,
+ "username":"test",
+ "password":"test",
+ "sshkey":"test"
+}