diff options
author | Ashlee Young <ashlee@wildernessvoice.com> | 2015-11-22 10:02:05 -0800 |
---|---|---|
committer | Ashlee Young <ashlee@wildernessvoice.com> | 2015-11-22 10:02:05 -0800 |
commit | 77ce3be7567bd01c66d8ee88a93b485666723501 (patch) | |
tree | 283e7f39a501750bbd705fbb91645b20198900f1 /framework/src/onos/providers/netconf/device | |
parent | 00e6500d0813dcbccaaa741ef38cc1eae6d11e07 (diff) |
Removed patch path since changes have been merged upstream to a different path. Updated README with directions.
Change-Id: Ie419abd2d3d3ef7315de9f607dcd757a78190995
Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/onos/providers/netconf/device')
5 files changed, 129 insertions, 1136 deletions
diff --git a/framework/src/onos/providers/netconf/device/pom.xml b/framework/src/onos/providers/netconf/device/pom.xml index 3465bc3a..15ad475a 100644 --- a/framework/src/onos/providers/netconf/device/pom.xml +++ b/framework/src/onos/providers/netconf/device/pom.xml @@ -33,129 +33,29 @@ <dependencies> <dependency> - <groupId>org.osgi</groupId> - <artifactId>org.osgi.compendium</artifactId> - </dependency> - <dependency> - <groupId>ch.ethz.ganymed</groupId> - <artifactId>ganymed-ssh2</artifactId> - <version>262</version> - </dependency> - <dependency> - <!-- TODO: change this appropriately when the official TailF JNC is available --> <groupId>org.onosproject</groupId> - <artifactId>jnc</artifactId> - <version>1.0</version> - </dependency> - <dependency> - <groupId>org.jdom</groupId> - <artifactId>jdom2</artifactId> - <version>2.0.5</version> - </dependency> - <dependency> - <groupId>jaxen</groupId> - <artifactId>jaxen</artifactId> - <version>1.1.4</version> - <optional>true</optional> - </dependency> - <dependency> - <groupId>org.osgi</groupId> - <artifactId>org.osgi.core</artifactId> + <artifactId>onlab-junit</artifactId> + <scope>test</scope> </dependency> <dependency> <groupId>org.onosproject</groupId> - <artifactId>onlab-junit</artifactId> - <scope>test</scope> + <artifactId>onos-netconf-api</artifactId> + <version>${project.version}</version> </dependency> <dependency> - <groupId>org.easymock</groupId> - <artifactId>easymock</artifactId> - <scope>test</scope> + <groupId>org.onosproject</groupId> + <artifactId>onos-netconf-ctl</artifactId> + <version>${project.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-shade-plugin</artifactId> - <version>2.3</version> - <configuration> - <filters> - <filter> - <artifact>com.tailf:JNC</artifact> - <includes> - <include>com/tailf/jnc/**</include> - </includes> - </filter> - <filter> - <artifact>ch.ethz.ganymed:ganymed-ssh2</artifact> - <includes> - <include>ch/ethz/ssh2/**</include> - </includes> - </filter> - <filter> - <artifact>org.jdom:jdom2</artifact> - <includes> - <include>org/jdom2/**</include> - </includes> - </filter> - </filters> - </configuration> - <executions> - <execution> - <phase>package</phase> - <goals> - <goal>shade</goal> - </goals> - </execution> - </executions> - </plugin> - <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-scr-plugin</artifactId> </plugin> <plugin> - <groupId>org.apache.felix</groupId> - <artifactId>maven-bundle-plugin</artifactId> - <configuration> - <instructions> - <Export-Package> - com.tailf.jnc, - ch.ethz.ssh2, - ch.ethz.ssh2.auth, - ch.ethz.ssh2.channel, - ch.ethz.ssh2.crypto, - ch.ethz.ssh2.crypto.cipher, - ch.ethz.ssh2.crypto.dh, - ch.ethz.ssh2.crypto.digest, - ch.ethz.ssh2.log, - ch.ethz.ssh2.packets, - ch.ethz.ssh2.server, - ch.ethz.ssh2.sftp, - ch.ethz.ssh2.signature, - ch.ethz.ssh2.transport, - ch.ethz.ssh2.util, - org.jdom2, - org.jdom2.input, - org.jdom2.output, - org.jdom2.adapters, - org.jdom2.filter, - org.jdom2.internal, - org.jdom2.located, - org.jdom2.transform, - org.jdom2.util, - org.jdom2.xpath, - org.jdom2.input.sax, - org.jdom2.input.stax, - org.jdom2.output.support, - org.jdom2.xpath.jaxen, - org.jdom2.xpath.util - </Export-Package> - </instructions> - </configuration> - </plugin> - <plugin> <groupId>org.onosproject</groupId> <artifactId>onos-maven-plugin</artifactId> </plugin> diff --git a/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDevice.java b/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDevice.java deleted file mode 100644 index b3d26b06..00000000 --- a/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDevice.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright 2015 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 static com.google.common.base.Preconditions.checkNotNull; -import static org.onlab.util.Tools.delay; -import static org.slf4j.LoggerFactory.getLogger; - -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.List; - -import org.jdom2.Document; -import org.jdom2.Element; -import org.jdom2.input.SAXBuilder; -import org.jdom2.output.Format; -import org.jdom2.output.XMLOutputter; -import org.slf4j.Logger; - -import com.tailf.jnc.Capabilities; -import com.tailf.jnc.JNCException; -import com.tailf.jnc.SSHConnection; -import com.tailf.jnc.SSHSession; - -/** - * This is a logical representation of actual NETCONF device, carrying all the - * necessary information to connect and execute NETCONF operations. - */ -public class NetconfDevice { - private final Logger log = getLogger(NetconfDevice.class); - - /** - * The Device State is used to determine whether the device is active or - * inactive. This state infomation will help Device Creator to add or delete - * the device from the core. - */ - public static enum DeviceState { - /* Used to specify Active state of the device */ - ACTIVE, - /* Used to specify inactive state of the device */ - INACTIVE, - /* Used to specify invalid state of the device */ - INVALID - } - - private static final int DEFAULT_SSH_PORT = 22; - private static final int DEFAULT_CON_TIMEOUT = 0; - private static final String XML_CAPABILITY_KEY = "capability"; - private static final int EVENTINTERVAL = 2000; - private static final int CONNECTION_CHECK_INTERVAL = 3; - private static final String INPUT_HELLO_XML_MSG = new StringBuilder( - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>") - .append("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">") - .append("<capabilities><capability>urn:ietf:params:netconf:base:1.0</capability>") - .append("</capabilities></hello>").toString(); - - private String sshHost; - private int sshPort = DEFAULT_SSH_PORT; - private int connectTimeout = DEFAULT_CON_TIMEOUT; - private String username; - private String password; - private boolean reachable = false; - - private List<String> capabilities = new ArrayList<String>(); - private SSHConnection sshConnection = null; - - private DeviceState deviceState = DeviceState.INVALID; - - protected NetconfDevice(String sshHost, int sshPort, String username, - String password) { - this.username = checkNotNull(username, - "Netconf Username Cannot be null"); - this.sshHost = checkNotNull(sshHost, "Netconf Device IP cannot be null"); - this.sshPort = checkNotNull(sshPort, - "Netconf Device SSH port cannot be null"); - this.password = password; - } - - /** - * This will try to connect to NETCONF device and find all the capabilities. - * - * @throws Exception if unable to connect to the device - */ - // FIXME: this should not be a generic Exception; perhaps wrap in some RuntimeException - public void init() throws Exception { - try { - if (sshConnection == null) { - sshConnection = new SSHConnection(sshHost, sshPort, connectTimeout); - sshConnection.authenticateWithPassword(username, password); - } - // Send hello message to retrieve capabilities. - } catch (IOException e) { - log.error("Fatal Error while creating connection to the device: " - + deviceInfo(), e); - throw e; - } catch (JNCException e) { - log.error("Failed to connect to the device: " + deviceInfo(), e); - throw e; - } - - hello(); - } - - private void hello() { - SSHSession ssh = null; - try { - ssh = new SSHSession(sshConnection); - String helloRequestXML = INPUT_HELLO_XML_MSG.trim(); - - log.debug("++++++++++++++++++++++++++++++++++Sending Hello: " - + sshConnection.getGanymedConnection().getHostname() - + "++++++++++++++++++++++++++++++++++"); - printPrettyXML(helloRequestXML); - ssh.print(helloRequestXML); - // ssh.print(endCharSeq); - ssh.flush(); - String xmlResponse = null; - int i = CONNECTION_CHECK_INTERVAL; - while (!ssh.ready() && i > 0) { - delay(EVENTINTERVAL); - i--; - } - - if (ssh.ready()) { - StringBuffer readOne = ssh.readOne(); - if (readOne == null) { - log.error("The Hello Contains No Capabilites"); - throw new JNCException( - JNCException.SESSION_ERROR, - "server does not support NETCONF base capability: " - + Capabilities.NETCONF_BASE_CAPABILITY); - } else { - xmlResponse = readOne.toString().trim(); - - log.debug("++++++++++++++++++++++++++++++++++Reading Capabilities: " - + sshConnection.getGanymedConnection() - .getHostname() - + "++++++++++++++++++++++++++++++++++"); - - printPrettyXML(xmlResponse); - processCapabilities(xmlResponse); - } - } - reachable = true; - } catch (IOException e) { - log.error("Fatal Error while sending Hello Message to the device: " - + deviceInfo(), e); - } catch (JNCException e) { - log.error("Fatal Error while sending Hello Message to the device: " - + deviceInfo(), e); - } finally { - log.debug("Closing the session after successful execution"); - if (ssh != null) { - ssh.close(); - } - } - } - - private void processCapabilities(String xmlResponse) throws JNCException { - if (xmlResponse.isEmpty()) { - log.error("The capability response cannot be empty"); - throw new JNCException( - JNCException.SESSION_ERROR, - "server does not support NETCONF base capability: " - + Capabilities.NETCONF_BASE_CAPABILITY); - } - try { - Document doc = new SAXBuilder() - .build(new StringReader(xmlResponse)); - Element rootElement = doc.getRootElement(); - processCapabilities(rootElement); - } catch (Exception e) { - log.error("ERROR while parsing the XML " + xmlResponse); - } - } - - private void processCapabilities(Element rootElement) { - List<Element> children = rootElement.getChildren(); - if (children.isEmpty()) { - return; - } - for (Element child : children) { - - if (child.getName().equals(XML_CAPABILITY_KEY)) { - capabilities.add(child.getValue()); - } - if (!child.getChildren().isEmpty()) { - processCapabilities(child); - } - } - } - - private void printPrettyXML(String xmlstring) { - try { - Document doc = new SAXBuilder().build(new StringReader(xmlstring)); - XMLOutputter xmOut = new XMLOutputter(Format.getPrettyFormat()); - String outputString = xmOut.outputString(doc); - log.debug(outputString); - } catch (Exception e) { - log.error("ERROR while parsing the XML " + xmlstring, e); - - } - } - - /** - * This would return host IP and host Port, used by this particular Netconf - * Device. - * @return Device Information. - */ - public String deviceInfo() { - return new StringBuilder("host: ").append(sshHost).append(". port: ") - .append(sshPort).toString(); - } - - /** - * This will terminate the device connection. - */ - public void disconnect() { - sshConnection.close(); - reachable = false; - } - - /** - * This will list down all the capabilities supported on the device. - * @return Capability list. - */ - public List<String> getCapabilities() { - return capabilities; - } - - /** - * This api is intended to know whether the device is connected or not. - * @return true if connected - */ - public boolean isReachable() { - return reachable; - } - - /** - * This will return the IP used connect ssh on the device. - * @return Netconf Device IP - */ - public String getSshHost() { - return sshHost; - } - - /** - * This will return the SSH Port used connect the device. - * @return SSH Port number - */ - public int getSshPort() { - return sshPort; - } - - /** - * The usename used to connect Netconf Device. - * @return Device Username - */ - public String getUsername() { - return username; - } - - /** - * Retrieve current state of the device. - * @return Current Device State - */ - public DeviceState getDeviceState() { - return deviceState; - } - - /** - * This is set the state information for the device. - * @param deviceState Next Device State - */ - public void setDeviceState(DeviceState deviceState) { - this.deviceState = deviceState; - } - - /** - * Check whether the device is in Active state. - * @return true if the device is Active - */ - public boolean isActive() { - return deviceState == DeviceState.ACTIVE ? true : false; - } - - public void setConnectTimeout(int connectTimeout) { - this.connectTimeout = connectTimeout; - } -} diff --git a/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java b/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java index f9194a7e..d12c6474 100644 --- a/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java +++ b/framework/src/onos/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java @@ -13,39 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onosproject.provider.netconf.device.impl; - -import static com.google.common.base.Strings.isNullOrEmpty; -import static org.onlab.util.Tools.delay; -import static org.onlab.util.Tools.get; -import static org.onlab.util.Tools.groupedThreads; -import static org.slf4j.LoggerFactory.getLogger; -import java.io.IOException; -import java.net.SocketTimeoutException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Dictionary; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; +package org.onosproject.provider.netconf.device.impl; +import com.google.common.base.Preconditions; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Modified; -import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.onlab.packet.ChassisId; -import org.onosproject.cfg.ComponentConfigService; -import org.onosproject.cluster.ClusterService; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.incubator.net.config.basics.ConfigException; +import org.onosproject.net.DefaultAnnotations; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.MastershipRole; +import org.onosproject.net.SparseAnnotations; +import org.onosproject.net.config.ConfigFactory; +import org.onosproject.net.config.NetworkConfigEvent; +import org.onosproject.net.config.NetworkConfigListener; +import org.onosproject.net.config.NetworkConfigRegistry; import org.onosproject.net.device.DefaultDeviceDescription; import org.onosproject.net.device.DeviceDescription; import org.onosproject.net.device.DeviceProvider; @@ -54,305 +43,180 @@ import org.onosproject.net.device.DeviceProviderService; import org.onosproject.net.device.DeviceService; import org.onosproject.net.provider.AbstractProvider; import org.onosproject.net.provider.ProviderId; -import org.onosproject.provider.netconf.device.impl.NetconfDevice.DeviceState; -import org.osgi.service.component.ComponentContext; +import org.onosproject.netconf.NetconfController; +import org.onosproject.netconf.NetconfDevice; +import org.onosproject.netconf.NetconfDeviceInfo; +import org.onosproject.netconf.NetconfDeviceListener; import org.slf4j.Logger; +import java.util.Map; + +import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY; +import static org.slf4j.LoggerFactory.getLogger; + /** - * Provider which will try to fetch the details of NETCONF devices from the core - * and run a capability discovery on each of the device. + * Provider which uses an NETCONF controller to detect device. */ @Component(immediate = true) public class NetconfDeviceProvider extends AbstractProvider implements DeviceProvider { - - private final Logger log = getLogger(NetconfDeviceProvider.class); - - protected Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>(); - - private DeviceProviderService providerService; + private final Logger log = getLogger(getClass()); @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected DeviceProviderRegistry providerRegistry; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected DeviceService deviceService; - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ClusterService clusterService; + protected NetconfController controller; //where is initiated ? @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected ComponentConfigService cfgService; - - private ExecutorService deviceBuilder = Executors - .newFixedThreadPool(1, groupedThreads("onos/netconf", "device-creator")); + protected NetworkConfigRegistry cfgService; - // Delay between events in ms. - private static final int EVENTINTERVAL = 5; - - private static final String SCHEME = "netconf"; + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; - @Property(name = "devConfigs", value = "", label = "Instance-specific configurations") - private String devConfigs = null; - @Property(name = "devPasswords", value = "", label = "Instance-specific password") - private String devPasswords = null; + private DeviceProviderService providerService; + private NetconfDeviceListener innerNodeListener = new InnerNetconfDeviceListener(); + protected static final String ISNOTNULL = "NetconfDeviceInfo is not null"; + private static final String UNKNOWN = "unknown"; + + private final ConfigFactory factory = + new ConfigFactory<ApplicationId, NetconfProviderConfig>(APP_SUBJECT_FACTORY, + NetconfProviderConfig.class, + "devices", + true) { + @Override + public NetconfProviderConfig createConfig() { + return new NetconfProviderConfig(); + } + }; + private final NetworkConfigListener cfgLister = new InternalNetworkConfigListener(); + private ApplicationId appId; - /** - * Creates a provider with the supplier identifier. - */ - public NetconfDeviceProvider() { - super(new ProviderId("netconf", "org.onosproject.provider.netconf")); - } @Activate - public void activate(ComponentContext context) { - cfgService.registerProperties(getClass()); + public void activate() { providerService = providerRegistry.register(this); - modified(context); + cfgService.registerConfigFactory(factory); + cfgService.addListener(cfgLister); + controller.addDeviceListener(innerNodeListener); + connectExistingDevices(); log.info("Started"); } + @Deactivate - public void deactivate(ComponentContext context) { - cfgService.unregisterProperties(getClass(), false); - try { - for (Entry<DeviceId, NetconfDevice> deviceEntry : netconfDeviceMap - .entrySet()) { - deviceBuilder.submit(new DeviceCreator(deviceEntry.getValue(), - false)); - } - deviceBuilder.awaitTermination(1000, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - log.error("Device builder did not terminate"); - } - deviceBuilder.shutdownNow(); - netconfDeviceMap.clear(); + public void deactivate() { providerRegistry.unregister(this); providerService = null; + cfgService.unregisterConfigFactory(factory); log.info("Stopped"); } - @Modified - public void modified(ComponentContext context) { - if (context == null) { - log.info("No configuration file"); - return; - } - Dictionary<?, ?> properties = context.getProperties(); - String deviceCfgValue = get(properties, "devConfigs"); - log.info("Settings: devConfigs={}", deviceCfgValue); - if (!isNullOrEmpty(deviceCfgValue)) { - addOrRemoveDevicesConfig(deviceCfgValue); - } - } - - private void addOrRemoveDevicesConfig(String deviceConfig) { - for (String deviceEntry : deviceConfig.split(",")) { - NetconfDevice device = processDeviceEntry(deviceEntry); - if (device != null) { - log.info("Device Detail: username: {}, host={}, port={}, state={}", - device.getUsername(), device.getSshHost(), - device.getSshPort(), device.getDeviceState().name()); - if (device.isActive()) { - deviceBuilder.submit(new DeviceCreator(device, true)); - } else { - deviceBuilder.submit(new DeviceCreator(device, false)); - } - } - } - } - - private NetconfDevice processDeviceEntry(String deviceEntry) { - if (deviceEntry == null) { - log.info("No content for Device Entry, so cannot proceed further."); - return null; - } - log.info("Trying to convert Device Entry String: " + deviceEntry - + " to a Netconf Device Object"); - NetconfDevice device = null; - try { - String userInfo = deviceEntry.substring(0, deviceEntry - .lastIndexOf('@')); - String hostInfo = deviceEntry.substring(deviceEntry - .lastIndexOf('@') + 1); - String[] infoSplit = userInfo.split(":"); - String username = infoSplit[0]; - String password = infoSplit[1]; - infoSplit = hostInfo.split(":"); - String hostIp = infoSplit[0]; - Integer hostPort; - try { - hostPort = Integer.parseInt(infoSplit[1]); - } catch (NumberFormatException nfe) { - log.error("Bad Configuration Data: Failed to parse host port number string: " - + infoSplit[1]); - throw nfe; - } - String deviceState = infoSplit[2]; - if (isNullOrEmpty(username) || isNullOrEmpty(password) - || isNullOrEmpty(hostIp) || hostPort == 0) { - log.warn("Bad Configuration Data: both user and device information parts of Configuration " - + deviceEntry + " should be non-nullable"); - } else { - device = new NetconfDevice(hostIp, hostPort, username, password); - if (!isNullOrEmpty(deviceState)) { - if (deviceState.toUpperCase().equals(DeviceState.ACTIVE - .name())) { - device.setDeviceState(DeviceState.ACTIVE); - } else if (deviceState.toUpperCase() - .equals(DeviceState.INACTIVE.name())) { - device.setDeviceState(DeviceState.INACTIVE); - } else { - log.warn("Device State Information can not be empty, so marking the state as INVALID"); - device.setDeviceState(DeviceState.INVALID); - } - } else { - log.warn("The device entry do not specify state information, so marking the state as INVALID"); - device.setDeviceState(DeviceState.INVALID); - } - } - } catch (ArrayIndexOutOfBoundsException aie) { - log.error("Error while reading config infromation from the config file: " - + "The user, host and device state infomation should be " - + "in the order 'userInfo@hostInfo:deviceState'" - + deviceEntry, aie); - } catch (Exception e) { - log.error("Error while parsing config information for the device entry: " - + deviceEntry, e); - } - return device; + public NetconfDeviceProvider() { + super(new ProviderId("netconf", "org.onosproject.netconf.provider.device")); } @Override public void triggerProbe(DeviceId deviceId) { - // TODO Auto-generated method stub + // TODO: This will be implemented later. + log.info("Triggering probe on device {}", deviceId); } @Override public void roleChanged(DeviceId deviceId, MastershipRole newRole) { - + // TODO: This will be implemented later. } @Override public boolean isReachable(DeviceId deviceId) { - NetconfDevice netconfDevice = netconfDeviceMap.get(deviceId); + Map<DeviceId, NetconfDevice> devices = controller.getDevicesMap(); + + NetconfDevice netconfDevice = null; + for (DeviceId key : devices.keySet()) { + if (key.equals(deviceId)) { + netconfDevice = controller.getDevicesMap().get(key); + } + } if (netconfDevice == null) { log.warn("BAD REQUEST: the requested device id: " - + deviceId.toString() - + " is not associated to any NETCONF Device"); + + deviceId.toString() + + " is not associated to any NETCONF Device"); return false; } - return netconfDevice.isReachable(); + return netconfDevice.isActive(); } - /** - * This class is intended to add or remove Configured Netconf Devices. - * Functionality relies on 'createFlag' and 'NetconfDevice' content. The - * functionality runs as a thread and dependening on the 'createFlag' value - * it will create or remove Device entry from the core. - */ - private class DeviceCreator implements Runnable { + private class InnerNetconfDeviceListener implements NetconfDeviceListener { - private NetconfDevice device; - private boolean createFlag; + @Override + public void deviceAdded(NetconfDeviceInfo nodeId) { + Preconditions.checkNotNull(nodeId, ISNOTNULL); + DeviceId deviceId = nodeId.getDeviceId(); + //TODO filter for not netconf devices + //Netconf configuration object + ChassisId cid = new ChassisId(); + String ipAddress = nodeId.ip().toString(); + SparseAnnotations annotations = DefaultAnnotations.builder() + .set("ipaddress", ipAddress).build(); + DeviceDescription deviceDescription = new DefaultDeviceDescription( + deviceId.uri(), + Device.Type.SWITCH, + UNKNOWN, UNKNOWN, + UNKNOWN, UNKNOWN, + cid, + annotations); + providerService.deviceConnected(deviceId, deviceDescription); - public DeviceCreator(NetconfDevice device, boolean createFlag) { - this.device = device; - this.createFlag = createFlag; } @Override - public void run() { - if (createFlag) { - log.info("Trying to create Device Info on ONOS core"); - advertiseDevices(); - } else { - log.info("Trying to remove Device Info on ONOS core"); - removeDevices(); - } + public void deviceRemoved(NetconfDeviceInfo nodeId) { + Preconditions.checkNotNull(nodeId, ISNOTNULL); + DeviceId deviceId = nodeId.getDeviceId(); + providerService.deviceDisconnected(deviceId); + } + } - /** - * For each Netconf Device, remove the entry from the device store. - */ - private void removeDevices() { - if (device == null) { - log.warn("The Request Netconf Device is null, cannot proceed further"); - return; - } + private void connectExistingDevices() { + //TODO consolidate + appId = coreService.registerApplication("org.onosproject.netconf"); + connectDevices(); + } + + private void connectDevices() { + NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class); + if (cfg != null) { + log.info("cfg {}", cfg); try { - DeviceId did = getDeviceId(); - if (!netconfDeviceMap.containsKey(did)) { - log.error("BAD Request: 'Currently device is not discovered, " - + "so cannot remove/disconnect the device: " - + device.deviceInfo() + "'"); - return; - } - providerService.deviceDisconnected(did); - device.disconnect(); - netconfDeviceMap.remove(did); - delay(EVENTINTERVAL); - } catch (URISyntaxException uriSyntaxExcpetion) { - log.error("Syntax Error while creating URI for the device: " - + device.deviceInfo() - + " couldn't remove the device from the store", - uriSyntaxExcpetion); + cfg.getDevicesAddresses().stream().forEach(addr -> controller + .connectDevice(new NetconfDeviceInfo(addr.name(), + addr.password(), + addr.ip(), + addr.port()))); + } catch (ConfigException e) { + log.error("Cannot read config error " + e); } } + } - /** - * Initialize Netconf Device object, and notify core saying device - * connected. - */ - private void advertiseDevices() { - try { - if (device == null) { - log.warn("The Request Netconf Device is null, cannot proceed further"); - return; - } - device.init(); - DeviceId did = getDeviceId(); - ChassisId cid = new ChassisId(); - DeviceDescription desc = new DefaultDeviceDescription( - did.uri(), - Device.Type.OTHER, - "", "", - "", "", - cid); - log.info("Persisting Device" + did.uri().toString()); - - netconfDeviceMap.put(did, device); - providerService.deviceConnected(did, desc); - log.info("Done with Device Info Creation on ONOS core. Device Info: " - + device.deviceInfo() + " " + did.uri().toString()); - delay(EVENTINTERVAL); - } catch (URISyntaxException e) { - log.error("Syntax Error while creating URI for the device: " - + device.deviceInfo() - + " couldn't persist the device onto the store", e); - } catch (SocketTimeoutException e) { - log.error("Error while setting connection for the device: " - + device.deviceInfo(), e); - } catch (IOException e) { - log.error("Error while setting connection for the device: " - + device.deviceInfo(), e); - } catch (Exception e) { - log.error("Error while initializing session for the device: " - + (device != null ? device.deviceInfo() : null), e); - } + private class InternalNetworkConfigListener implements NetworkConfigListener { + + + @Override + public void event(NetworkConfigEvent event) { + connectDevices(); } - /** - * This will build a device id for the device. - */ - private DeviceId getDeviceId() throws URISyntaxException { - String additionalSSP = new StringBuilder(device.getUsername()) - .append("@").append(device.getSshHost()).append(":") - .append(device.getSshPort()).toString(); - DeviceId did = DeviceId.deviceId(new URI(SCHEME, additionalSSP, - null)); - return did; + @Override + public boolean isRelevant(NetworkConfigEvent event) { + //TODO refactor + return event.configClass().equals(NetconfProviderConfig.class) && + (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED || + event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED); } } } diff --git a/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java b/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java deleted file mode 100644 index e56c5959..00000000 --- a/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright 2015 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 static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.junit.Assert.assertFalse; -import static org.onlab.util.Tools.delay; -import static org.onosproject.provider.netconf.device.impl.NetconfDeviceProviderTestConstant.*; -import static org.slf4j.LoggerFactory.getLogger; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collection; -import java.util.Dictionary; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import org.easymock.EasyMock; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.onlab.packet.ChassisId; -import org.onosproject.cfg.ComponentConfigService; -import org.onosproject.net.Device; -import org.onosproject.net.DeviceId; -import org.onosproject.net.MastershipRole; -import org.onosproject.net.device.DefaultDeviceDescription; -import org.onosproject.net.device.DeviceDescription; -import org.onosproject.net.device.DeviceProvider; -import org.onosproject.net.device.DeviceProviderRegistry; -import org.onosproject.net.device.DeviceProviderService; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.device.PortStatistics; -import org.onosproject.net.provider.ProviderId; -import org.osgi.service.component.ComponentContext; -import org.slf4j.Logger; - -import com.tailf.jnc.JNCException; - -/** - * Test Case to Validate Netconf Device Provider. - */ -public class NetconfDeviceProviderTest { - TestDeviceCreator create; - - private final Logger log = getLogger(NetconfDeviceProviderTest.class); - - private Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>(); - - private DeviceProviderService providerService; - - private static final DeviceId DID1 = DeviceId.deviceId(DEVICE_ID); - - private final NetconfDeviceProvider provider = new NetconfDeviceProvider(); - private final TestDeviceRegistry registry = new TestDeviceRegistry(); - - private ComponentConfigService mockCfgService; - - @Before - public void setUp() { - mockCfgService = EasyMock.createMock(ComponentConfigService.class); - provider.cfgService = mockCfgService; - provider.providerRegistry = registry; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockWithoutValues(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)).andReturn(NULL); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockWithDeviceEntryNull(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)).andReturn(NULL_NULL); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockDeviceEntryNumberFomatEx(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)) - .andReturn(CONFIG_WITH_INVALID_ENTRY_NUMBER) - .andThrow(new NumberFormatException()); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockWithoutUsernameAndPassword(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)).andReturn(CONFIG_WITH_NULL_ENTRY); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockWithDifferentDeviceState(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)) - .andReturn(CONFIG_WITH_DIFFERENT_DEVICE_STATE); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockDeviceWithArrayOutOFBoundEx(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)) - .andReturn(CONFIG_WITH_ARRAY_OUT_OF_BOUNDEX) - .andThrow(new ArrayIndexOutOfBoundsException()); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @SuppressWarnings("unchecked") - private Dictionary<String, String> getDictionaryMockDeviceEntryForDeactivate(ComponentContext componentContext) { - Dictionary<String, String> dictionary = EasyMock - .createMock(Dictionary.class); - expect(dictionary.get(DEV_CONFIG)) - .andReturn(CONFIG_ENTRY_FOR_DEACTIVATE) - .andThrow(new ArrayIndexOutOfBoundsException()); - replay(dictionary); - expect(componentContext.getProperties()).andReturn(dictionary); - return dictionary; - } - - @Ignore - @Test(expected = IOException.class) - public void testSSHAuthentication() throws IOException, JNCException { - TestDeviceCreator objForTestDev = new TestDeviceCreator( - new NetconfDevice( - DEVICE_IP, - DEVICE_PORT, - DEVICE_USERNAME, - DEVICE_PASSWORD), - true); - objForTestDev.run(); - } - - @After - public void tearDown() { - provider.providerRegistry = null; - provider.cfgService = null; - } - - // To check if deviceCfgValue is empty or null - @Test - public void testActiveWithcomponentContextIsNull() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockWithoutValues(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - // To check deviceEntry and device is null - @Test - public void testActiveWithDeviceEntryIsNull() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockWithDeviceEntryNull(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - @Test - public void testActiveWithDeviceEntryWithoutUsernameAndPassword() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockWithoutUsernameAndPassword(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - @Test - public void testActiveWithDeviceEntryWithNumberFomatEx() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockDeviceEntryNumberFomatEx(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - @Test - public void testActiveWithDeviceEntryWithDifferentDeviceState() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockWithDifferentDeviceState(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - @Test - public void testActiveWithDeviceEntryWithArrayOutOFBoundEx() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockDeviceWithArrayOutOFBoundEx(componentContext); - replay(componentContext); - provider.activate(componentContext); - } - - @Test - public void isReachableWithInvalidDeviceId() { - assertFalse("Initially the Device ID Should not be reachable", - provider.isReachable(DID1)); - NetconfDevice device = new NetconfDevice(NULL, ZERO, NULL, NULL); - provider.netconfDeviceMap.put(DID1, device); - assertFalse("Particular Device ID cannot be Reachable", - provider.isReachable(DID1)); - } - - @Test - public void testDeactivate() { - - ComponentContext componentContext = EasyMock - .createMock(ComponentContext.class); - getDictionaryMockDeviceEntryForDeactivate(componentContext); - replay(componentContext); - testActiveWithDeviceEntryWithDifferentDeviceState(); - provider.deactivate(componentContext); - } - - private class TestDeviceCreator { - - private NetconfDevice device; - private boolean createFlag; - - public TestDeviceCreator(NetconfDevice device, boolean createFlag) { - this.device = device; - this.createFlag = createFlag; - } - - public void run() throws JNCException, IOException { - if (createFlag) { - log.info("Trying to create Device Info on ONOS core"); - advertiseDevices(); - } else { - log.info("Trying to remove Device Info on ONOS core"); - removeDevices(); - } - } - - /** - * For each Netconf Device, remove the entry from the device store. - */ - private void removeDevices() { - if (device == null) { - log.warn("The Request Netconf Device is null, cannot proceed further"); - return; - } - try { - DeviceId did = getDeviceId(); - if (!netconfDeviceMap.containsKey(did)) { - log.error("BAD Request: 'Currently device is not discovered, " - + "so cannot remove/disconnect the device: " - + device.deviceInfo() + "'"); - return; - } - providerService.deviceDisconnected(did); - device.disconnect(); - netconfDeviceMap.remove(did); - delay(EVENTINTERVAL); - } catch (URISyntaxException uriSyntaxExcpetion) { - log.error("Syntax Error while creating URI for the device: " - + device.deviceInfo() - + " couldn't remove the device from the store", - uriSyntaxExcpetion); - } - } - - /** - * Initialize Netconf Device object, and notify core saying device - * connected. - */ - private void advertiseDevices() throws JNCException, IOException { - try { - if (device == null) { - log.warn("The Request Netconf Device is null, cannot proceed further"); - return; - } - device.init(); - DeviceId did = getDeviceId(); - ChassisId cid = new ChassisId(); - DeviceDescription desc = new DefaultDeviceDescription( - did.uri(), - Device.Type.OTHER, - NULL, - NULL, - NULL, - NULL, cid); - log.info("Persisting Device" + did.uri().toString()); - - netconfDeviceMap.put(did, device); - providerService.deviceConnected(did, desc); - log.info("Done with Device Info Creation on ONOS core. Device Info: " - + device.deviceInfo() + " " + did.uri().toString()); - delay(EVENTINTERVAL); - } catch (URISyntaxException e) { - log.error("Syntax Error while creating URI for the device: " - + device.deviceInfo() - + " couldn't persist the device onto the store", e); - } catch (JNCException e) { - throw e; - } catch (IOException e) { - throw e; - } catch (Exception e) { - log.error("Error while initializing session for the device: " - + device.deviceInfo(), e); - } - } - - private DeviceId getDeviceId() throws URISyntaxException { - String additionalSSP = new StringBuilder(device.getUsername()) - .append(AT_THE_RATE).append(device.getSshHost()) - .append(COLON).append(device.getSshPort()).toString(); - DeviceId did = DeviceId.deviceId(new URI(SCHEME_NETCONF, - additionalSSP, null)); - return did; - } - } - - private class TestDeviceRegistry implements DeviceProviderRegistry { - - @Override - public DeviceProviderService register(DeviceProvider provider) { - return new TestProviderService(); - } - - @Override - public void unregister(DeviceProvider provider) { - } - - @Override - public Set<ProviderId> getProviders() { - return null; - } - - private class TestProviderService implements DeviceProviderService { - - @Override - public DeviceProvider provider() { - return null; - } - - @Override - public void deviceConnected(DeviceId deviceId, - DeviceDescription deviceDescription) { - } - - @Override - public void deviceDisconnected(DeviceId deviceId) { - - } - - @Override - public void updatePorts(DeviceId deviceId, - List<PortDescription> portDescriptions) { - - } - - @Override - public void portStatusChanged(DeviceId deviceId, - PortDescription portDescription) { - - } - - @Override - public void receivedRoleReply(DeviceId deviceId, - MastershipRole requested, - MastershipRole response) { - - } - - @Override - public void updatePortStatistics(DeviceId deviceId, - Collection<PortStatistics> portStatistics) { - - } - } - } -} diff --git a/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTestConstant.java b/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTestConstant.java deleted file mode 100644 index 1d848e26..00000000 --- a/framework/src/onos/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTestConstant.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2015 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; - -public final class NetconfDeviceProviderTestConstant { - - private NetconfDeviceProviderTestConstant() { - } - - public static final int ZERO = 0; - public static final int EVENTINTERVAL = 5; - public static final String DEV_CONFIG = "devConfigs"; - public static final String CONFIG_WITH_INVALID_ENTRY_NUMBER = "cisco:cisco" - + "@10.18.11.14:cisco:active"; - public static final String CONFIG_WITH_NULL_ENTRY = "null:null@null:0:active"; - public static final String CONFIG_WITH_DIFFERENT_DEVICE_STATE = "cisco:cisco@10.18.11.14:22:active," - + "cisco:cisco@10.18.11.18:22:inactive,cisco:cisco@10.18.11.14:22:invalid," - + "cisco:cisco@10.18.11.14:22:null"; - public static final String CONFIG_WITH_ARRAY_OUT_OF_BOUNDEX = "@10.18.11.14:22:active"; - public static final String CONFIG_ENTRY_FOR_DEACTIVATE = "netconf:cisco" - + "@10.18.11.14:22:active"; - public static final String DEVICE_IP = "10.18.14.19"; - public static final int DEVICE_PORT = 22; - public static final String DEVICE_USERNAME = "cisco"; - public static final String DEVICE_PASSWORD = "cisco"; - public static final String AT_THE_RATE = "@"; - public static final String COLON = ":"; - public static final String NULL = ""; - public static final String NULL_NULL = "null,null"; - public static final String SCHEME_NETCONF = "netconf"; - public static final String DEVICE_ID = "of:0000000000000001"; - -} |