From e63291850fd0795c5700e25e67e5dee89ba54c5f Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Tue, 1 Dec 2015 05:49:27 -0800 Subject: onos commit hash c2999f30c69e50df905a9d175ef80b3f23a98514 Change-Id: I2bb8562c4942b6d6a6d60b663db2e17540477b81 Signed-off-by: Ashlee Young --- framework/src/onos/protocols/netconf/api/pom.xml | 45 +++ .../org/onosproject/netconf/NetconfController.java | 84 +++++ .../org/onosproject/netconf/NetconfDevice.java | 51 +++ .../org/onosproject/netconf/NetconfDeviceInfo.java | 173 +++++++++ .../onosproject/netconf/NetconfDeviceListener.java | 37 ++ .../org/onosproject/netconf/NetconfSession.java | 129 +++++++ .../java/org/onosproject/netconf/package-info.java | 20 ++ framework/src/onos/protocols/netconf/ctl/pom.xml | 91 +++++ .../netconf/ctl/NetconfControllerImpl.java | 143 ++++++++ .../onosproject/netconf/ctl/NetconfDeviceImpl.java | 66 ++++ .../netconf/ctl/NetconfSessionImpl.java | 396 +++++++++++++++++++++ .../org/onosproject/netconf/ctl/package-info.java | 20 ++ framework/src/onos/protocols/netconf/pom.xml | 83 +++++ framework/src/onos/protocols/netconf/rfc/pom.xml | 30 ++ .../main/java/org/onosproject/netconf/rfc/Foo.java | 7 + .../org/onosproject/netconf/rfc/package-info.java | 20 ++ 16 files changed, 1395 insertions(+) create mode 100644 framework/src/onos/protocols/netconf/api/pom.xml create mode 100644 framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfController.java create mode 100644 framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDevice.java create mode 100644 framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java create mode 100644 framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceListener.java create mode 100644 framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfSession.java create mode 100644 framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/package-info.java create mode 100644 framework/src/onos/protocols/netconf/ctl/pom.xml create mode 100644 framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfControllerImpl.java create mode 100644 framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfDeviceImpl.java create mode 100644 framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfSessionImpl.java create mode 100644 framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/package-info.java create mode 100644 framework/src/onos/protocols/netconf/pom.xml create mode 100644 framework/src/onos/protocols/netconf/rfc/pom.xml create mode 100644 framework/src/onos/protocols/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/Foo.java create mode 100644 framework/src/onos/protocols/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/package-info.java (limited to 'framework/src/onos/protocols/netconf') diff --git a/framework/src/onos/protocols/netconf/api/pom.xml b/framework/src/onos/protocols/netconf/api/pom.xml new file mode 100644 index 00000000..ed8a5302 --- /dev/null +++ b/framework/src/onos/protocols/netconf/api/pom.xml @@ -0,0 +1,45 @@ + + + + 4.0.0 + + org.onosproject + onos-netconf + 1.4.0-SNAPSHOT + + onos-netconf-api + bundle + + ONOS NETCONF plugin API + + + commons-pool + commons-pool + + + io.netty + netty-transport + + + io.netty + netty-transport-native-epoll + ${netty4.version} + + + + diff --git a/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfController.java b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfController.java new file mode 100644 index 00000000..6411c011 --- /dev/null +++ b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfController.java @@ -0,0 +1,84 @@ +/* + * 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.netconf; + +import org.onlab.packet.IpAddress; +import org.onosproject.net.DeviceId; + +import java.util.Map; + +/** + * Abstraction of an NETCONF controller. Serves as a one stop shop for obtaining + * NetconfDevice and (un)register listeners on NETCONF device events. + */ +public interface NetconfController { + + /** + * Adds Device Event Listener. + * + * @param listener node listener + */ + void addDeviceListener(NetconfDeviceListener listener); + + /** + * Removes Device Listener. + * + * @param listener node listener + */ + void removeDeviceListener(NetconfDeviceListener listener); + + /** + * Tries to connect to a specific NETCONF device, if the connection is succesful + * it creates and adds the device to the ONOS core as a NetconfDevice. + * + * @param deviceInfo info about the device to add + * @return NetconfDevice Netconf device + */ + NetconfDevice connectDevice(NetconfDeviceInfo deviceInfo); + + /** + * Removes a Netconf device. + * + * @param deviceInfo info about the device to remove + */ + void removeDevice(NetconfDeviceInfo deviceInfo); + + /** + * Gets all the nodes information. + * + * @return map of devices + */ + Map getDevicesMap(); + + /** + * Gets a Netconf Device by node identifier. + * + * @param deviceInfo node identifier + * @return NetconfDevice Netconf device + */ + NetconfDevice getNetconfDevice(DeviceId deviceInfo); + + /** + * Gets a Netconf Device by node identifier. + * + * @param ip device ip + * @param port device port + * @return NetconfDevice Netconf device + */ + NetconfDevice getNetconfDevice(IpAddress ip, int port); + +} diff --git a/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDevice.java b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDevice.java new file mode 100644 index 00000000..1974782b --- /dev/null +++ b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDevice.java @@ -0,0 +1,51 @@ +/* + * 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.netconf; + +/** + * Interface representing a NETCONF device. + */ +public interface NetconfDevice { + + + /** + * Returns whether a device is a NETCONF device with a capabilities list + * and is accessible. + * + * @return true if device is accessible, false otherwise + */ + boolean isActive(); + + /** + * Returns a NETCONF session context for this device. + * + * @return netconf session + */ + NetconfSession getSession(); + + /** + * Ensures that all sessions are closed. + * A device cannot be used after disconnect is called. + */ + void disconnect(); + + /** + * return all the info associated with this device. + * @return NetconfDeviceInfo + */ + NetconfDeviceInfo getDeviceInfo(); +} \ No newline at end of file diff --git a/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java new file mode 100644 index 00000000..cb0e240a --- /dev/null +++ b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java @@ -0,0 +1,173 @@ +/* + * 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.netconf; + +import com.google.common.base.Preconditions; +import org.onlab.packet.IpAddress; +import org.onosproject.net.DeviceId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Objects; + +/** + * Represents a Netconf device information. + */ +public class NetconfDeviceInfo { + + public static final Logger log = LoggerFactory + .getLogger(NetconfDeviceInfo.class); + + private String name; + private String password; + private IpAddress ipAddress; + private int port; + private File keyFile; + + + /** + * Information for contacting the controller. + * + * @param name the connection type + * @param password the password for the device + * @param ipAddress the ip address + * @param port the tcp port + */ + public NetconfDeviceInfo(String name, String password, IpAddress ipAddress, + int port) { + Preconditions.checkArgument(!name.equals(""), "Empty device name"); + Preconditions.checkNotNull(port > 0, "Negative port"); + Preconditions.checkNotNull(ipAddress, "Null ip address"); + this.name = name; + this.password = password; + this.ipAddress = ipAddress; + this.port = port; + } + + /** + * Information for contacting the controller. + * + * @param name the connection type + * @param password the password for the device + * @param ipAddress the ip address + * @param port the tcp port + * @param keyString the string cointaing the key. + */ + public NetconfDeviceInfo(String name, String password, IpAddress ipAddress, + int port, String keyString) { + Preconditions.checkArgument(!name.equals(""), "Empty device name"); + Preconditions.checkNotNull(port > 0, "Negative port"); + Preconditions.checkNotNull(ipAddress, "Null ip address"); + this.name = name; + this.password = password; + this.ipAddress = ipAddress; + this.port = port; + this.keyFile = new File(keyString); + } + + /** + * Exposes the name of the controller. + * + * @return String name + */ + public String name() { + return name; + } + + /** + * Exposes the password of the controller. + * + * @return String password + */ + public String password() { + return password; + } + + /** + * Exposes the ip address of the controller. + * + * @return IpAddress ip address + */ + public IpAddress ip() { + return ipAddress; + } + + /** + * Exposes the port of the controller. + * + * @return int port address + */ + public int port() { + return port; + } + + /** + * Exposes the keyFile of the controller. + * + * @return int port address + */ + public File getKeyFile() { + return keyFile; + } + + /** + * Return the info about the device in a string. + * String format: "netconf:name@ip:port" + * + * @return String device info + */ + public String toString() { + return "netconf:" + name + "@" + ipAddress + ":" + port; + } + + /** + * Return the DeviceId about the device containing the URI. + * + * @return DeviceId + */ + public DeviceId getDeviceId() { + + try { + return DeviceId.deviceId(new URI(this.toString())); + } catch (URISyntaxException e) { + log.debug("Unable to build deviceID for device {} ", this, e); + } + return null; + } + + @Override + public int hashCode() { + return Objects.hash(ipAddress, port, name); + } + + @Override + public boolean equals(Object toBeCompared) { + if (toBeCompared instanceof NetconfDeviceInfo) { + NetconfDeviceInfo netconfDeviceInfo = (NetconfDeviceInfo) toBeCompared; + if (netconfDeviceInfo.name().equals(name) + && netconfDeviceInfo.ip().equals(ipAddress) + && netconfDeviceInfo.port() == port + && netconfDeviceInfo.password().equals(password)) { + return true; + } + } + return false; + } +} diff --git a/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceListener.java b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceListener.java new file mode 100644 index 00000000..9c46d4f6 --- /dev/null +++ b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceListener.java @@ -0,0 +1,37 @@ +/* + * 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.netconf; + +/** + * Allows for providers interested in node events to be notified. + */ +public interface NetconfDeviceListener { + + /** + * Notifies that the node was added. + * + * @param nodeId the node where the event occurred + */ + void deviceAdded(NetconfDeviceInfo nodeId); + + /** + * Notifies that the node was removed. + * + * @param nodeId the node where the event occurred + */ + void deviceRemoved(NetconfDeviceInfo nodeId); +} diff --git a/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfSession.java b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfSession.java new file mode 100644 index 00000000..73c435f6 --- /dev/null +++ b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfSession.java @@ -0,0 +1,129 @@ +/* + * 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.netconf; + +import java.util.List; + +/** + * NETCONF session object that allows NETCONF operations on top with the physical + * device on top of an SSH connection. + */ +// TODO change return type of methdos to +public interface NetconfSession { + + /** + * Retrives the requested configuration, different from get-config. + * @param request the XML containing the request to the server. + * @return device running configuration + */ + String get(String request); + + /** + * Executes an RPC to the server. + * @param request the XML containing the RPC for the server. + * @return Server response or ERROR + */ + String doRPC(String request); + + /** + * Retrives the specified configuration. + * + * @param targetConfiguration the type of configuration to retrieve. + * @return specified configuration. + */ + String getConfig(String targetConfiguration); + + /** + * Retrives part of the specivied configuration based on the filterSchema. + * + * @param targetConfiguration the type of configuration to retrieve. + * @param configurationFilterSchema XML schema to filter the configuration + * elements we are interested in + * @return device running configuration. + */ + String getConfig(String targetConfiguration, String configurationFilterSchema); + + /** + * Retrives part of the specified configuration based on the filterSchema. + * + * @param newConfiguration configuration to set + * @return true if the configuration was edited correctly + */ + + boolean editConfig(String newConfiguration); + + /** + * Copies the new configuration, an Url or a complete configuration xml tree + * to the target configuration. + * The target configuration can't be the running one + * + * @param targetConfiguration the type of configuration to retrieve. + * @param newConfiguration configuration to set + * @return true if the configuration was copied correctly + */ + boolean copyConfig(String targetConfiguration, String newConfiguration); + + /** + * Deletes part of the specified configuration based on the filterSchema. + * + * @param targetConfiguration the name of the configuration to delete + * @return true if the configuration was copied correctly + */ + boolean deleteConfig(String targetConfiguration); + + /** + * Locks the candidate configuration. + * + * @return true if successful. + */ + boolean lock(); + + /** + * Unlocks the candidate configuration. + * + * @return true if successful. + */ + boolean unlock(); + + /** + * Closes the Netconf session with the device. + * the first time it tries gracefully, then kills it forcefully + * @return true if closed + */ + boolean close(); + + /** + * Gets the session ID of the Netconf session. + * + * @return Session ID as a string. + */ + String getSessionId(); + + /** + * Gets the capabilities of the Netconf server associated to this session. + * + * @return Network capabilities as a string. + */ + String getServerCapabilities(); + + /** + * Sets the device capabilities. + * @param capabilities list of capabilities the device has. + */ + void setDeviceCapabilities(List capabilities); + +} diff --git a/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/package-info.java b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/package-info.java new file mode 100644 index 00000000..5562bd33 --- /dev/null +++ b/framework/src/onos/protocols/netconf/api/src/main/java/org/onosproject/netconf/package-info.java @@ -0,0 +1,20 @@ +/* + * 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. + */ + +/** + * Created by ray on 10/30/15. + */ +package org.onosproject.netconf; diff --git a/framework/src/onos/protocols/netconf/ctl/pom.xml b/framework/src/onos/protocols/netconf/ctl/pom.xml new file mode 100644 index 00000000..e022acba --- /dev/null +++ b/framework/src/onos/protocols/netconf/ctl/pom.xml @@ -0,0 +1,91 @@ + + + + 4.0.0 + + org.onosproject + onos-netconf + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-netconf-ctl + bundle + + + + org.osgi + org.osgi.compendium + + + org.onosproject + onos-netconf-api + ${project.version} + + + ch.ethz.ganymed + ganymed-ssh2 + 262 + + + + + + + + org.apache.felix + maven-bundle-plugin + + + ch.ethz.ssh2.* + ganymed-ssh2 + + + + + + diff --git a/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfControllerImpl.java b/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfControllerImpl.java new file mode 100644 index 00000000..a572a2bc --- /dev/null +++ b/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfControllerImpl.java @@ -0,0 +1,143 @@ +/* + * 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.netconf.ctl; + +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.Service; +import org.onlab.packet.IpAddress; +import org.onosproject.net.DeviceId; +import org.onosproject.netconf.NetconfController; +import org.onosproject.netconf.NetconfDevice; +import org.onosproject.netconf.NetconfDeviceInfo; +import org.onosproject.netconf.NetconfDeviceListener; +import org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; + +/** + * The implementation of NetconfController. + */ +@Component(immediate = true) +@Service +public class NetconfControllerImpl implements NetconfController { + + public static final Logger log = LoggerFactory + .getLogger(NetconfControllerImpl.class); + + public Map netconfDeviceMap = new ConcurrentHashMap<>(); + + protected Set netconfDeviceListeners = new CopyOnWriteArraySet<>(); + + @Activate + public void activate(ComponentContext context) { + log.info("Started"); + } + + @Deactivate + public void deactivate() { + netconfDeviceMap.clear(); + log.info("Stopped"); + } + + @Override + public void addDeviceListener(NetconfDeviceListener listener) { + if (!netconfDeviceListeners.contains(listener)) { + netconfDeviceListeners.add(listener); + } + } + + @Override + public void removeDeviceListener(NetconfDeviceListener listener) { + netconfDeviceListeners.remove(listener); + } + + @Override + public NetconfDevice getNetconfDevice(DeviceId deviceInfo) { + return netconfDeviceMap.get(deviceInfo); + } + + @Override + public NetconfDevice getNetconfDevice(IpAddress ip, int port) { + NetconfDevice device = null; + for (DeviceId info : netconfDeviceMap.keySet()) { + if (IpAddress.valueOf(info.uri().getHost()).equals(ip) && + info.uri().getPort() == port) { + return netconfDeviceMap.get(info); + } + } + return device; + } + + @Override + public NetconfDevice connectDevice(NetconfDeviceInfo deviceInfo) { + if (netconfDeviceMap.containsKey(deviceInfo.getDeviceId())) { + log.warn("Device {} is already present"); + return netconfDeviceMap.get(deviceInfo.getDeviceId()); + } else { + log.info("Creating NETCONF device {}", deviceInfo); + return createDevice(deviceInfo); + } + } + + @Override + public void removeDevice(NetconfDeviceInfo deviceInfo) { + if (netconfDeviceMap.containsKey(deviceInfo.getDeviceId())) { + log.warn("Device {} is not present"); + } else { + stopDevice(deviceInfo); + } + } + + private NetconfDevice createDevice(NetconfDeviceInfo deviceInfo) { + NetconfDevice netconfDevice = null; + try { + netconfDevice = new NetconfDeviceImpl(deviceInfo); + for (NetconfDeviceListener l : netconfDeviceListeners) { + l.deviceAdded(deviceInfo); + } + netconfDeviceMap.put(deviceInfo.getDeviceId(), netconfDevice); + } catch (IOException e) { + throw new IllegalStateException("Cannot create NETCONF device " + + "with device Info: " + + deviceInfo + " \n" + e); + } + return netconfDevice; + } + + private void stopDevice(NetconfDeviceInfo deviceInfo) { + netconfDeviceMap.get(deviceInfo.getDeviceId()).disconnect(); + netconfDeviceMap.remove(deviceInfo.getDeviceId()); + for (NetconfDeviceListener l : netconfDeviceListeners) { + l.deviceRemoved(deviceInfo); + } + } + + @Override + public Map getDevicesMap() { + return netconfDeviceMap; + } + + +} diff --git a/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfDeviceImpl.java b/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfDeviceImpl.java new file mode 100644 index 00000000..3141aafc --- /dev/null +++ b/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfDeviceImpl.java @@ -0,0 +1,66 @@ +/* + * 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.netconf.ctl; + +import org.onosproject.netconf.NetconfDevice; +import org.onosproject.netconf.NetconfDeviceInfo; +import org.onosproject.netconf.NetconfSession; + +import java.io.IOException; + +/** + * Implementation of a NETCONF device. + */ +public class NetconfDeviceImpl implements NetconfDevice { + + private NetconfDeviceInfo netconfDeviceInfo; + private boolean deviceState = false; + private NetconfSession netconfSession; + //private String config; + + public NetconfDeviceImpl(NetconfDeviceInfo deviceInfo) throws IOException { + netconfDeviceInfo = deviceInfo; + try { + netconfSession = new NetconfSessionImpl(netconfDeviceInfo); + } catch (IOException e) { + throw new IOException("Cannot create connection and session", e); + } + deviceState = true; + //config = netconfSession.getConfig("running"); + } + + @Override + public boolean isActive() { + return deviceState; + } + + @Override + public NetconfSession getSession() { + return netconfSession; + } + + @Override + public void disconnect() { + deviceState = false; + netconfSession.close(); + } + + @Override + public NetconfDeviceInfo getDeviceInfo() { + return netconfDeviceInfo; + } +} diff --git a/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfSessionImpl.java b/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfSessionImpl.java new file mode 100644 index 00000000..8619abc0 --- /dev/null +++ b/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfSessionImpl.java @@ -0,0 +1,396 @@ +/* + * 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.netconf.ctl; + +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.Session; +import com.google.common.base.Preconditions; +import org.onosproject.netconf.NetconfDeviceInfo; +import org.onosproject.netconf.NetconfSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Implementation of a NETCONF session to talk to a device. + */ +public class NetconfSessionImpl implements NetconfSession { + + public static final Logger log = LoggerFactory + .getLogger(NetconfSessionImpl.class); + private static final int CONNECTION_TIMEOUT = 0; + + + private Connection netconfConnection; + private NetconfDeviceInfo deviceInfo; + private Session sshSession; + private boolean connectionActive; + private BufferedReader bufferReader = null; + private PrintWriter out = null; + private int messageID = 0; + + private List deviceCapabilities = + new ArrayList<>( + Arrays.asList("urn:ietf:params:netconf:base:1.0")); + + private String serverCapabilities; + private String endpattern = "]]>]]>"; + + + public NetconfSessionImpl(NetconfDeviceInfo deviceInfo) throws IOException { + this.deviceInfo = deviceInfo; + connectionActive = false; + startConnection(); + } + + + private void startConnection() throws IOException { + if (!connectionActive) { + netconfConnection = new Connection(deviceInfo.ip().toString(), deviceInfo.port()); + netconfConnection.connect(null, CONNECTION_TIMEOUT, 0); + boolean isAuthenticated; + try { + if (deviceInfo.getKeyFile() != null) { + isAuthenticated = netconfConnection.authenticateWithPublicKey( + deviceInfo.name(), deviceInfo.getKeyFile(), + deviceInfo.password()); + } else { + log.info("authenticate with username {} and password {}", + deviceInfo.name(), deviceInfo.password()); + isAuthenticated = netconfConnection.authenticateWithPassword( + deviceInfo.name(), deviceInfo.password()); + } + } catch (IOException e) { + throw new IOException("Authentication connection failed:" + + e.getMessage()); + } + + connectionActive = true; + Preconditions.checkArgument(isAuthenticated, + "Authentication password and username failed"); + startSshSession(); + } + } + + private void startSshSession() throws IOException { + try { + sshSession = netconfConnection.openSession(); + sshSession.startSubSystem("netconf"); + bufferReader = new BufferedReader(new InputStreamReader( + sshSession.getStdout())); + out = new PrintWriter(sshSession.getStdin()); + sendHello(); + } catch (IOException e) { + throw new IOException("Failed to create ch.ethz.ssh2.Session session:" + + e.getMessage()); + } + } + + private void sendHello() throws IOException { + serverCapabilities = doRequest(createHelloString()); + } + + private String createHelloString() { + StringBuilder hellobuffer = new StringBuilder(); + hellobuffer.append("\n"); + hellobuffer.append("\n"); + hellobuffer.append(" \n"); + deviceCapabilities.forEach( + cap -> hellobuffer.append(" " + cap + "\n")); + hellobuffer.append(" \n"); + hellobuffer.append("\n"); + hellobuffer.append(endpattern); + return hellobuffer.toString(); + + } + + @Override + public String doRPC(String request) { + String reply = "ERROR"; + try { + reply = doRequest(request); + if (checkReply(reply)) { + return reply; + } else { + return "ERROR " + reply; + } + } catch (IOException e) { + log.error("Problem in the reading from the SSH connection " + e); + } + return reply; + } + + private String doRequest(String request) throws IOException { + log.info("sshState " + sshSession.getState() + "request" + request); + if (sshSession.getState() != 2) { + try { + startSshSession(); + } catch (IOException e) { + log.info("the connection had to be reopened"); + startConnection(); + } + sendHello(); + } + log.info("sshState after" + sshSession.getState()); + out.print(request); + out.flush(); + messageID++; + return readOne(); + } + + @Override + public String get(String request) { + return doRPC(request); + } + + @Override + public String getConfig(String targetConfiguration) { + return getConfig(targetConfiguration, null); + } + + @Override + public String getConfig(String targetConfiguration, String configurationSchema) { + StringBuilder rpc = new StringBuilder(""); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("<" + targetConfiguration + "/>"); + rpc.append(""); + if (configurationSchema != null) { + rpc.append("\n"); + rpc.append(configurationSchema + "\n"); + rpc.append("\n"); + } + rpc.append("\n"); + rpc.append("\n"); + rpc.append(endpattern); + String reply = null; + try { + reply = doRequest(rpc.toString()); + } catch (IOException e) { + e.printStackTrace(); + } + + return checkReply(reply) ? reply : null; + } + + @Override + public boolean editConfig(String newConfiguration) { + newConfiguration = newConfiguration + endpattern; + String reply = null; + try { + reply = doRequest(newConfiguration); + } catch (IOException e) { + e.printStackTrace(); + } + return checkReply(reply); + } + + @Override + public boolean copyConfig(String targetConfiguration, String newConfiguration) { + newConfiguration = newConfiguration.trim(); + if (!newConfiguration.startsWith("")) { + newConfiguration = "" + newConfiguration + + ""; + } + StringBuilder rpc = new StringBuilder(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append("<" + targetConfiguration + "/>"); + rpc.append(""); + rpc.append(""); + rpc.append("<" + newConfiguration + "/>"); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(endpattern); + String reply = null; + try { + reply = doRequest(rpc.toString()); + } catch (IOException e) { + e.printStackTrace(); + } + + return checkReply(reply); + } + + @Override + public boolean deleteConfig(String targetConfiguration) { + if (targetConfiguration.equals("running")) { + log.warn("Target configuration for delete operation can't be \"running\"", + targetConfiguration); + return false; + } + StringBuilder rpc = new StringBuilder(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append("<" + targetConfiguration + "/>"); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(endpattern); + String reply = null; + try { + reply = doRequest(rpc.toString()); + } catch (IOException e) { + e.printStackTrace(); + } + + return checkReply(reply); + } + + @Override + public boolean lock() { + StringBuilder rpc = new StringBuilder(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(endpattern); + String reply = null; + try { + reply = doRequest(rpc.toString()); + } catch (IOException e) { + e.printStackTrace(); + } + return checkReply(reply); + } + + @Override + public boolean unlock() { + StringBuilder rpc = new StringBuilder(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(""); + rpc.append(endpattern); + String reply = null; + try { + reply = doRequest(rpc.toString()); + } catch (IOException e) { + e.printStackTrace(); + } + return checkReply(reply); + } + + @Override + public boolean close() { + return close(false); + } + + private boolean close(boolean force) { + StringBuilder rpc = new StringBuilder(); + rpc.append(""); + if (force) { + rpc.append(""); + } else { + rpc.append(""); + } + rpc.append(""); + rpc.append(""); + rpc.append(endpattern); + return checkReply(rpc.toString()) ? true : close(true); + } + + @Override + public String getSessionId() { + if (serverCapabilities.contains("")) { + String[] outer = serverCapabilities.split(""); + Preconditions.checkArgument(outer.length != 1, + "Error in retrieving the session id"); + String[] value = outer[1].split(""); + Preconditions.checkArgument(value.length != 1, + "Error in retrieving the session id"); + return value[0]; + } else { + return String.valueOf(-1); + } + } + + @Override + public String getServerCapabilities() { + return serverCapabilities; + } + + @Override + public void setDeviceCapabilities(List capabilities) { + deviceCapabilities = capabilities; + } + + private boolean checkReply(String reply) { + if (reply != null) { + if (!reply.contains("")) { + return true; + } else if (reply.contains("") + || (reply.contains("") + && reply.contains("warning"))) { + return true; + } + } + return false; + } + + private String readOne() throws IOException { + //TODO try a simple string + final StringWriter reply = new StringWriter(); + while (true) { + int charRead = bufferReader.read(); + if (charRead == -1) { + throw new IOException("Session closed"); + } + + for (int i = 0; i < endpattern.length(); i++) { + if (charRead == endpattern.charAt(i)) { + if (i < endpattern.length() - 1) { + charRead = bufferReader.read(); + } else { + return reply.getBuffer().toString(); + } + } else { + String s = endpattern.substring(0, i); + for (int j = 0; i < s.length(); j++) { + reply.write(s.charAt(j)); + } + reply.write(charRead); + break; + } + } + } + } + +} diff --git a/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/package-info.java b/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/package-info.java new file mode 100644 index 00000000..84992bf2 --- /dev/null +++ b/framework/src/onos/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/package-info.java @@ -0,0 +1,20 @@ +/* + * 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. + */ + +/** + * Created by ray on 10/30/15. + */ +package org.onosproject.netconf.ctl; diff --git a/framework/src/onos/protocols/netconf/pom.xml b/framework/src/onos/protocols/netconf/pom.xml new file mode 100644 index 00000000..d2f5c432 --- /dev/null +++ b/framework/src/onos/protocols/netconf/pom.xml @@ -0,0 +1,83 @@ + + + + 4.0.0 + + org.onosproject + onos-protocols + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-netconf + pom + + + api + rfc + ctl + + + ONOS NETCONF southbound libraries + + + junit + junit + test + + + org.onosproject + onlab-misc + + + org.onosproject + onlab-junit + + + io.netty + netty-buffer + + + io.netty + netty-handler + + + org.apache.felix + org.apache.felix.scr.annotations + + + org.onosproject + onos-core-net + ${project.version} + + + + + + + org.apache.felix + maven-bundle-plugin + + + org.apache.felix + maven-scr-plugin + + + + diff --git a/framework/src/onos/protocols/netconf/rfc/pom.xml b/framework/src/onos/protocols/netconf/rfc/pom.xml new file mode 100644 index 00000000..832937bc --- /dev/null +++ b/framework/src/onos/protocols/netconf/rfc/pom.xml @@ -0,0 +1,30 @@ + + + + 4.0.0 + + org.onosproject + onos-netconf + 1.4.0-SNAPSHOT + ../pom.xml + + + onos-netconf-rfc + bundle + diff --git a/framework/src/onos/protocols/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/Foo.java b/framework/src/onos/protocols/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/Foo.java new file mode 100644 index 00000000..06963b0c --- /dev/null +++ b/framework/src/onos/protocols/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/Foo.java @@ -0,0 +1,7 @@ +package org.onosproject.netconf.rfc; + +/** + * Created by tom on 10/19/15. + */ +public class Foo { +} diff --git a/framework/src/onos/protocols/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/package-info.java b/framework/src/onos/protocols/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/package-info.java new file mode 100644 index 00000000..616a7ce5 --- /dev/null +++ b/framework/src/onos/protocols/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/package-info.java @@ -0,0 +1,20 @@ +/* + * 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. + */ + +/** + * Created by ray on 10/30/15. + */ +package org.onosproject.netconf.rfc; -- cgit 1.2.3-korg