Committed by
Gerrit Code Review
[ONOS-3253/3144] Insert support for Netconf device configuration, set and get controllers commands
Change-Id: I99188aa18207b9d0b0d935b9f9e61e547f4ddab1
Showing
33 changed files
with
1812 additions
and
1161 deletions
... | @@ -59,8 +59,11 @@ public class DeviceSetControllersCommand extends AbstractShellCommand { | ... | @@ -59,8 +59,11 @@ public class DeviceSetControllersCommand extends AbstractShellCommand { |
59 | ControllerConfig config = h.behaviour(ControllerConfig.class); | 59 | ControllerConfig config = h.behaviour(ControllerConfig.class); |
60 | print("before:"); | 60 | print("before:"); |
61 | config.getControllers().forEach(c -> print(c.target())); | 61 | config.getControllers().forEach(c -> print(c.target())); |
62 | - | 62 | + try { |
63 | config.setControllers(newControllers); | 63 | config.setControllers(newControllers); |
64 | + } catch (NullPointerException e) { | ||
65 | + print("No Device with requested parameters {} ", uri); | ||
66 | + } | ||
64 | print("after:"); | 67 | print("after:"); |
65 | config.getControllers().forEach(c -> print(c.target())); | 68 | config.getControllers().forEach(c -> print(c.target())); |
66 | print("size %d", config.getControllers().size()); | 69 | print("size %d", config.getControllers().size()); | ... | ... |
... | @@ -24,5 +24,7 @@ | ... | @@ -24,5 +24,7 @@ |
24 | 24 | ||
25 | <bundle>mvn:${project.groupId}/onos-ovsdb-api/${project.version}</bundle> | 25 | <bundle>mvn:${project.groupId}/onos-ovsdb-api/${project.version}</bundle> |
26 | <bundle>mvn:${project.groupId}/onos-ovsdb-rfc/${project.version}</bundle> | 26 | <bundle>mvn:${project.groupId}/onos-ovsdb-rfc/${project.version}</bundle> |
27 | + | ||
28 | + <bundle>mvn:${project.groupId}/onos-netconf-api/${project.version}</bundle> | ||
27 | </feature> | 29 | </feature> |
28 | </features> | 30 | </features> | ... | ... |
... | @@ -67,6 +67,11 @@ | ... | @@ -67,6 +67,11 @@ |
67 | <artifactId>easymock</artifactId> | 67 | <artifactId>easymock</artifactId> |
68 | <scope>test</scope> | 68 | <scope>test</scope> |
69 | </dependency> | 69 | </dependency> |
70 | + <dependency> | ||
71 | + <groupId>org.onosproject</groupId> | ||
72 | + <artifactId>onos-netconf-api</artifactId> | ||
73 | + <version>${project.version}</version> | ||
74 | + </dependency> | ||
70 | 75 | ||
71 | <dependency> | 76 | <dependency> |
72 | <groupId>org.apache.felix</groupId> | 77 | <groupId>org.apache.felix</groupId> | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.driver.netconf; | ||
18 | + | ||
19 | +import com.google.common.base.Preconditions; | ||
20 | +import org.onosproject.net.DeviceId; | ||
21 | +import org.onosproject.net.behaviour.ControllerConfig; | ||
22 | +import org.onosproject.net.behaviour.ControllerInfo; | ||
23 | +import org.onosproject.net.driver.AbstractHandlerBehaviour; | ||
24 | +import org.onosproject.net.driver.DriverHandler; | ||
25 | +import org.onosproject.netconf.NetconfController; | ||
26 | +import org.onosproject.netconf.NetconfDevice; | ||
27 | +import org.slf4j.Logger; | ||
28 | + | ||
29 | +import java.io.ByteArrayInputStream; | ||
30 | +import java.nio.charset.StandardCharsets; | ||
31 | +import java.util.ArrayList; | ||
32 | +import java.util.List; | ||
33 | + | ||
34 | +import static org.slf4j.LoggerFactory.getLogger; | ||
35 | + | ||
36 | +/** | ||
37 | + * Implementation of controller config which allows to get and set controllers | ||
38 | + * through the Netconf protocol. | ||
39 | + */ | ||
40 | +public class NetconfControllerConfig extends AbstractHandlerBehaviour | ||
41 | + implements ControllerConfig { | ||
42 | + | ||
43 | + private final Logger log = getLogger(NetconfControllerConfig.class); | ||
44 | + | ||
45 | + @Override | ||
46 | + public List<ControllerInfo> getControllers() { | ||
47 | + DriverHandler handler = handler(); | ||
48 | + NetconfController controller = handler.get(NetconfController.class); | ||
49 | + DeviceId ofDeviceId = handler.data().deviceId(); | ||
50 | + Preconditions.checkNotNull(controller, "Netconf controller is null"); | ||
51 | + List<ControllerInfo> controllers = new ArrayList<>(); | ||
52 | + controllers.addAll(XmlConfigParser.parseStreamControllers(XmlConfigParser. | ||
53 | + loadXml(new ByteArrayInputStream(controller. | ||
54 | + getDevicesMap().get(ofDeviceId).getSession(). | ||
55 | + getConfig("running").getBytes(StandardCharsets.UTF_8))))); | ||
56 | + return controllers; | ||
57 | + } | ||
58 | + | ||
59 | + @Override | ||
60 | + public void setControllers(List<ControllerInfo> controllers) { | ||
61 | + DriverHandler handler = handler(); | ||
62 | + NetconfController controller = handler.get(NetconfController.class); | ||
63 | + DeviceId deviceId = handler.data().deviceId(); | ||
64 | + Preconditions.checkNotNull(controller, "Netconf controller is null"); | ||
65 | + try { | ||
66 | + NetconfDevice device = controller.getNetconfDevice(deviceId); | ||
67 | + log.warn("provider map {}", controller.getDevicesMap()); | ||
68 | + String config = XmlConfigParser.createControllersConfig( | ||
69 | + XmlConfigParser.loadXml(getClass().getResourceAsStream("controllers.xml")), | ||
70 | + XmlConfigParser.loadXml( | ||
71 | + new ByteArrayInputStream(device.getSession() | ||
72 | + .getConfig("running") | ||
73 | + .getBytes( | ||
74 | + StandardCharsets.UTF_8))), | ||
75 | + "running", "merge", "create", controllers | ||
76 | + ); | ||
77 | + device.getSession().editConfig(config.substring(config.indexOf("-->") + 3)); | ||
78 | + } catch (NullPointerException e) { | ||
79 | + log.warn("No NETCONF device with requested parameters " + e); | ||
80 | + throw new NullPointerException("No NETCONF device with requested parameters " + e); | ||
81 | + } | ||
82 | + | ||
83 | + } | ||
84 | + | ||
85 | + //TODO maybe put method getNetconfClientService like in ovsdb if we need it | ||
86 | + | ||
87 | +} | ||
88 | + | ||
89 | + |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.driver.netconf; | ||
18 | + | ||
19 | +import org.apache.commons.configuration.ConfigurationException; | ||
20 | +import org.apache.commons.configuration.HierarchicalConfiguration; | ||
21 | +import org.apache.commons.configuration.XMLConfiguration; | ||
22 | +import org.apache.commons.configuration.tree.ConfigurationNode; | ||
23 | +import org.onlab.packet.IpAddress; | ||
24 | +import org.onosproject.net.behaviour.ControllerInfo; | ||
25 | +import org.slf4j.Logger; | ||
26 | +import org.slf4j.LoggerFactory; | ||
27 | + | ||
28 | +import java.io.InputStream; | ||
29 | +import java.io.StringWriter; | ||
30 | +import java.util.ArrayList; | ||
31 | +import java.util.List; | ||
32 | + | ||
33 | +/** | ||
34 | + * Parser for Netconf XML configurations and replys. | ||
35 | + */ | ||
36 | +final class XmlConfigParser { | ||
37 | + public static final Logger log = LoggerFactory | ||
38 | + .getLogger(XmlConfigParser.class); | ||
39 | + | ||
40 | + private XmlConfigParser() { | ||
41 | + //not called, preventing any allocation | ||
42 | + } | ||
43 | + | ||
44 | + | ||
45 | + protected static HierarchicalConfiguration loadXml(InputStream xmlStream) { | ||
46 | + XMLConfiguration cfg = new XMLConfiguration(); | ||
47 | + try { | ||
48 | + cfg.load(xmlStream); | ||
49 | + return cfg; | ||
50 | + } catch (ConfigurationException e) { | ||
51 | + throw new IllegalArgumentException("Cannot load xml from Stream", e); | ||
52 | + } | ||
53 | + } | ||
54 | + | ||
55 | + protected static List<ControllerInfo> parseStreamControllers(HierarchicalConfiguration cfg) { | ||
56 | + List<ControllerInfo> controllers = new ArrayList<>(); | ||
57 | + List<HierarchicalConfiguration> fields = | ||
58 | + cfg.configurationsAt("data.capable-switch." + | ||
59 | + "logical-switches." + | ||
60 | + "switch.controllers.controller"); | ||
61 | + for (HierarchicalConfiguration sub : fields) { | ||
62 | + controllers.add(new ControllerInfo( | ||
63 | + IpAddress.valueOf(sub.getString("ip-address")), | ||
64 | + Integer.parseInt(sub.getString("port")), | ||
65 | + sub.getString("protocol"))); | ||
66 | + } | ||
67 | + return controllers; | ||
68 | + } | ||
69 | + | ||
70 | + protected static String parseSwitchId(HierarchicalConfiguration cfg) { | ||
71 | + HierarchicalConfiguration field = | ||
72 | + cfg.configurationAt("data.capable-switch." + | ||
73 | + "logical-switches." + | ||
74 | + "switch"); | ||
75 | + return field.getProperty("id").toString(); | ||
76 | + } | ||
77 | + | ||
78 | + protected static String parseCapableSwitchId(HierarchicalConfiguration cfg) { | ||
79 | + HierarchicalConfiguration field = | ||
80 | + cfg.configurationAt("data.capable-switch"); | ||
81 | + return field.getProperty("id").toString(); | ||
82 | + } | ||
83 | + | ||
84 | + protected static String createControllersConfig(HierarchicalConfiguration cfg, | ||
85 | + HierarchicalConfiguration actualCfg, | ||
86 | + String target, String netconfOperation, | ||
87 | + String controllerOperation, | ||
88 | + List<ControllerInfo> controllers) { | ||
89 | + //cfg.getKeys().forEachRemaining(key -> System.out.println(key)); | ||
90 | + cfg.setProperty("edit-config.target", target); | ||
91 | + cfg.setProperty("edit-config.default-operation", netconfOperation); | ||
92 | + cfg.setProperty("edit-config.config.capable-switch.id", | ||
93 | + parseCapableSwitchId(actualCfg)); | ||
94 | + cfg.setProperty("edit-config.config.capable-switch." + | ||
95 | + "logical-switches.switch.id", parseSwitchId(actualCfg)); | ||
96 | + List<ConfigurationNode> newControllers = new ArrayList<>(); | ||
97 | + for (ControllerInfo ci : controllers) { | ||
98 | + XMLConfiguration controller = new XMLConfiguration(); | ||
99 | + controller.setRoot(new HierarchicalConfiguration.Node("controller")); | ||
100 | + String id = ci.type() + ":" + ci.ip() + ":" + ci.port(); | ||
101 | + controller.setProperty("id", id); | ||
102 | + controller.setProperty("ip-address", ci.ip()); | ||
103 | + controller.setProperty("port", ci.port()); | ||
104 | + controller.setProperty("protocol", ci.type()); | ||
105 | + newControllers.add(controller.getRootNode()); | ||
106 | + } | ||
107 | + cfg.addNodes("edit-config.config.capable-switch.logical-switches." + | ||
108 | + "switch.controllers", newControllers); | ||
109 | + XMLConfiguration editcfg = (XMLConfiguration) cfg; | ||
110 | + StringWriter stringWriter = new StringWriter(); | ||
111 | + try { | ||
112 | + editcfg.save(stringWriter); | ||
113 | + } catch (ConfigurationException e) { | ||
114 | + e.printStackTrace(); | ||
115 | + } | ||
116 | + String s = stringWriter.toString() | ||
117 | + .replaceAll("<controller>", | ||
118 | + "<controller nc:operation=\"" + controllerOperation + "\">"); | ||
119 | + s = s.replace("<target>" + target + "</target>", | ||
120 | + "<target><" + target + "/></target>"); | ||
121 | + return s; | ||
122 | + | ||
123 | + } | ||
124 | + | ||
125 | + //TODO implement mor methods for parsing configuration when you need them | ||
126 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +/** | ||
18 | + * Implementations of the Netconf driver behaviours. | ||
19 | + */ | ||
20 | +package org.onosproject.driver.netconf; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -37,6 +37,13 @@ | ... | @@ -37,6 +37,13 @@ |
37 | <behaviour api="org.onosproject.net.behaviour.ExtensionResolver" | 37 | <behaviour api="org.onosproject.net.behaviour.ExtensionResolver" |
38 | impl="org.onosproject.driver.extensions.NiciraExtensionInterpreter" /> | 38 | impl="org.onosproject.driver.extensions.NiciraExtensionInterpreter" /> |
39 | </driver> | 39 | </driver> |
40 | + <driver name="ovs-netconf" extends="default" | ||
41 | + manufacturer="Nicira, Inc\." hwVersion="Open vSwitch" swVersion="2\..*"> | ||
42 | + <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver" | ||
43 | + impl="org.onosproject.driver.handshaker.NiciraSwitchHandshaker"/> | ||
44 | + <behaviour api="org.onosproject.net.behaviour.ControllerConfig" | ||
45 | + impl="org.onosproject.driver.netconf.NetconfControllerConfig"/> | ||
46 | + </driver> | ||
40 | <driver name="ovs-corsa" extends="ovs" | 47 | <driver name="ovs-corsa" extends="ovs" |
41 | manufacturer="Corsa" hwVersion="emulation" swVersion="0.0.0"> | 48 | manufacturer="Corsa" hwVersion="emulation" swVersion="0.0.0"> |
42 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | 49 | <behaviour api="org.onosproject.net.behaviour.Pipeliner" | ... | ... |
1 | +<!-- | ||
2 | + ~ Copyright 2015 Open Networking Laboratory | ||
3 | + ~ | ||
4 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + ~ you may not use this file except in compliance with the License. | ||
6 | + ~ You may obtain a copy of the License at | ||
7 | + ~ | ||
8 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + ~ | ||
10 | + ~ Unless required by applicable law or agreed to in writing, software | ||
11 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + ~ See the License for the specific language governing permissions and | ||
14 | + ~ limitations under the License. | ||
15 | + --> | ||
16 | + | ||
17 | +<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> | ||
18 | + <edit-config> | ||
19 | + <target> | ||
20 | + </target> | ||
21 | + <default-operation> | ||
22 | + </default-operation> | ||
23 | + <config> | ||
24 | + <capable-switch xmlns="urn:onf:config:yang"> | ||
25 | + <id></id> | ||
26 | + <logical-switches> | ||
27 | + <switch> | ||
28 | + <id></id> | ||
29 | + <controllers> | ||
30 | + </controllers> | ||
31 | + </switch> | ||
32 | + </logical-switches> | ||
33 | + </capable-switch> | ||
34 | + </config> | ||
35 | + </edit-config> | ||
36 | +</rpc> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.driver.netconf; | ||
18 | + | ||
19 | +import org.junit.Test; | ||
20 | +import org.onlab.packet.IpAddress; | ||
21 | +import org.onosproject.net.behaviour.ControllerInfo; | ||
22 | + | ||
23 | +import java.io.IOException; | ||
24 | +import java.io.InputStream; | ||
25 | +import java.util.ArrayList; | ||
26 | +import java.util.Arrays; | ||
27 | +import java.util.List; | ||
28 | + | ||
29 | +import static org.junit.Assert.assertTrue; | ||
30 | +import static org.onosproject.driver.netconf.XmlConfigParser.*; | ||
31 | + | ||
32 | +//import static org.junit.Assert.*; | ||
33 | + | ||
34 | +/** | ||
35 | + * Test the XML document Parsing for netconf configuration. | ||
36 | + */ | ||
37 | +public class XmlConfigParserTest { | ||
38 | + | ||
39 | + | ||
40 | + @Test | ||
41 | + public void basics() throws IOException { | ||
42 | + InputStream stream = getClass().getResourceAsStream("testConfig.xml"); | ||
43 | + List<ControllerInfo> controllers = parseStreamControllers(loadXml(stream)); | ||
44 | + assertTrue(controllers.get(0).equals(new ControllerInfo( | ||
45 | + IpAddress.valueOf("10.128.12.1"), 6653, "tcp"))); | ||
46 | + assertTrue(controllers.get(1).equals(new ControllerInfo( | ||
47 | + IpAddress.valueOf("10.128.12.2"), 6654, "tcp"))); | ||
48 | + | ||
49 | + } | ||
50 | + | ||
51 | + @Test | ||
52 | + public void switchId() { | ||
53 | + InputStream stream = getClass().getResourceAsStream("testConfig.xml"); | ||
54 | + String switchId = parseSwitchId(loadXml(stream)); | ||
55 | + assertTrue(switchId.equals("ofc-bridge")); | ||
56 | + } | ||
57 | + | ||
58 | + @Test | ||
59 | + public void capableSwitchId() { | ||
60 | + InputStream stream = getClass().getResourceAsStream("testConfig.xml"); | ||
61 | + String capableSwitchId = parseCapableSwitchId(loadXml(stream)); | ||
62 | + assertTrue(capableSwitchId.equals("openvswitch")); | ||
63 | + } | ||
64 | + | ||
65 | + @Test | ||
66 | + public void controllersConfig() { | ||
67 | + InputStream streamOrig = getClass().getResourceAsStream("testConfig.xml"); | ||
68 | + InputStream streamCFG = XmlConfigParser.class | ||
69 | + .getResourceAsStream("controllers.xml"); | ||
70 | + String config = createControllersConfig(loadXml(streamCFG), | ||
71 | + loadXml(streamOrig), "running", "merge", | ||
72 | + "create", new ArrayList<>(Arrays.asList( | ||
73 | + new ControllerInfo(IpAddress.valueOf("192.168.1.1"), | ||
74 | + 5000, "tcp")))); | ||
75 | + assertTrue(config.contains("192.168.1.1")); | ||
76 | + assertTrue(config.contains("tcp")); | ||
77 | + assertTrue(config.contains("5000")); | ||
78 | + | ||
79 | + } | ||
80 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2015 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | + | ||
18 | +<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="7"> | ||
19 | + <data> | ||
20 | + <capable-switch xmlns="urn:onf:config:yang"> | ||
21 | + <id>openvswitch</id> | ||
22 | + <resources> | ||
23 | + <port> | ||
24 | + <name>ofc-bridge</name> | ||
25 | + <requested-number>666</requested-number> | ||
26 | + <configuration> | ||
27 | + <admin-state>down</admin-state> | ||
28 | + <no-receive>false</no-receive> | ||
29 | + <no-forward>false</no-forward> | ||
30 | + <no-packet-in>false</no-packet-in> | ||
31 | + </configuration> | ||
32 | + </port> | ||
33 | + </resources> | ||
34 | + <logical-switches> | ||
35 | + <switch> | ||
36 | + <id>ofc-bridge</id> | ||
37 | + <datapath-id>00:01:02:03:04:05:06:07</datapath-id> | ||
38 | + <lost-connection-behavior>failSecureMode</lost-connection-behavior> | ||
39 | + <controllers> | ||
40 | + <controller> | ||
41 | + <id>(null)</id> | ||
42 | + <ip-address>10.128.12.1</ip-address> | ||
43 | + <port>6653</port> | ||
44 | + <protocol>tcp</protocol> | ||
45 | + </controller> | ||
46 | + <controller> | ||
47 | + <id>(null)</id> | ||
48 | + <ip-address>10.128.12.2</ip-address> | ||
49 | + <port>6654</port> | ||
50 | + <protocol>tcp</protocol> | ||
51 | + </controller> | ||
52 | + </controllers> | ||
53 | + <resources> | ||
54 | + <port>ofc-bridge</port> | ||
55 | + </resources> | ||
56 | + </switch> | ||
57 | + </logical-switches> | ||
58 | + </capable-switch> | ||
59 | + </data> | ||
60 | +</rpc-reply> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -40,11 +40,6 @@ | ... | @@ -40,11 +40,6 @@ |
40 | <artifactId>netty-transport-native-epoll</artifactId> | 40 | <artifactId>netty-transport-native-epoll</artifactId> |
41 | <version>${netty4.version}</version> | 41 | <version>${netty4.version}</version> |
42 | </dependency> | 42 | </dependency> |
43 | - <dependency> | ||
44 | - <groupId>org.onosproject</groupId> | ||
45 | - <artifactId>onos-netconf-rfc</artifactId> | ||
46 | - <version>${project.version}</version> | ||
47 | - </dependency> | ||
48 | </dependencies> | 43 | </dependencies> |
49 | 44 | ||
50 | </project> | 45 | </project> | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.netconf; | ||
18 | + | ||
19 | +import org.onlab.packet.IpAddress; | ||
20 | +import org.onosproject.net.DeviceId; | ||
21 | + | ||
22 | +import java.util.Map; | ||
23 | + | ||
24 | +/** | ||
25 | + * Abstraction of an NETCONF controller. Serves as a one stop shop for obtaining | ||
26 | + * NetconfDevice and (un)register listeners on NETCONF device events. | ||
27 | + */ | ||
28 | +public interface NetconfController { | ||
29 | + | ||
30 | + /** | ||
31 | + * Adds Device Event Listener. | ||
32 | + * | ||
33 | + * @param listener node listener | ||
34 | + */ | ||
35 | + void addDeviceListener(NetconfDeviceListener listener); | ||
36 | + | ||
37 | + /** | ||
38 | + * Removes Device Listener. | ||
39 | + * | ||
40 | + * @param listener node listener | ||
41 | + */ | ||
42 | + void removeDeviceListener(NetconfDeviceListener listener); | ||
43 | + | ||
44 | + /** | ||
45 | + * Tries to connect to a specific NETCONF device, if the connection is succesful | ||
46 | + * it creates and adds the device to the ONOS core as a NetconfDevice. | ||
47 | + * | ||
48 | + * @param deviceInfo info about the device to add | ||
49 | + * @return NetconfDevice Netconf device | ||
50 | + */ | ||
51 | + NetconfDevice connectDevice(NetconfDeviceInfo deviceInfo); | ||
52 | + | ||
53 | + /** | ||
54 | + * Removes a Netconf device. | ||
55 | + * | ||
56 | + * @param deviceInfo info about the device to remove | ||
57 | + */ | ||
58 | + void removeDevice(NetconfDeviceInfo deviceInfo); | ||
59 | + | ||
60 | + /** | ||
61 | + * Gets all the nodes information. | ||
62 | + * | ||
63 | + * @return map of devices | ||
64 | + */ | ||
65 | + Map<DeviceId, NetconfDevice> getDevicesMap(); | ||
66 | + | ||
67 | + /** | ||
68 | + * Gets a Netconf Device by node identifier. | ||
69 | + * | ||
70 | + * @param deviceInfo node identifier | ||
71 | + * @return NetconfDevice Netconf device | ||
72 | + */ | ||
73 | + NetconfDevice getNetconfDevice(DeviceId deviceInfo); | ||
74 | + | ||
75 | + /** | ||
76 | + * Gets a Netconf Device by node identifier. | ||
77 | + * | ||
78 | + * @param ip device ip | ||
79 | + * @param port device port | ||
80 | + * @return NetconfDevice Netconf device | ||
81 | + */ | ||
82 | + NetconfDevice getNetconfDevice(IpAddress ip, int port); | ||
83 | + | ||
84 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.netconf; | ||
18 | + | ||
19 | +/** | ||
20 | + * Interface representing a NETCONF device. | ||
21 | + */ | ||
22 | +public interface NetconfDevice { | ||
23 | + | ||
24 | + | ||
25 | + /** | ||
26 | + * Returns whether a device is a NETCONF device with a capabilities list | ||
27 | + * and is accessible. | ||
28 | + * | ||
29 | + * @return true if device is accessible, false otherwise | ||
30 | + */ | ||
31 | + boolean isActive(); | ||
32 | + | ||
33 | + /** | ||
34 | + * Returns a NETCONF session context for this device. | ||
35 | + * | ||
36 | + * @return netconf session | ||
37 | + */ | ||
38 | + NetconfSession getSession(); | ||
39 | + | ||
40 | + /** | ||
41 | + * Ensures that all sessions are closed. | ||
42 | + * A device cannot be used after disconnect is called. | ||
43 | + */ | ||
44 | + void disconnect(); | ||
45 | + | ||
46 | + /** | ||
47 | + * return all the info associated with this device. | ||
48 | + * @return NetconfDeviceInfo | ||
49 | + */ | ||
50 | + NetconfDeviceInfo getDeviceInfo(); | ||
51 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.netconf; | ||
18 | + | ||
19 | +import com.google.common.base.Preconditions; | ||
20 | +import org.onlab.packet.IpAddress; | ||
21 | +import org.onosproject.net.DeviceId; | ||
22 | +import org.slf4j.Logger; | ||
23 | +import org.slf4j.LoggerFactory; | ||
24 | + | ||
25 | +import java.io.File; | ||
26 | +import java.net.URI; | ||
27 | +import java.net.URISyntaxException; | ||
28 | +import java.util.Objects; | ||
29 | + | ||
30 | +/** | ||
31 | + * Represents a Netconf device information. | ||
32 | + */ | ||
33 | +public class NetconfDeviceInfo { | ||
34 | + | ||
35 | + public static final Logger log = LoggerFactory | ||
36 | + .getLogger(NetconfDeviceInfo.class); | ||
37 | + | ||
38 | + private String name; | ||
39 | + private String password; | ||
40 | + private IpAddress ipAddress; | ||
41 | + private int port; | ||
42 | + private File keyFile; | ||
43 | + | ||
44 | + | ||
45 | + /** | ||
46 | + * Information for contacting the controller. | ||
47 | + * | ||
48 | + * @param name the connection type | ||
49 | + * @param password the password for the device | ||
50 | + * @param ipAddress the ip address | ||
51 | + * @param port the tcp port | ||
52 | + */ | ||
53 | + public NetconfDeviceInfo(String name, String password, IpAddress ipAddress, | ||
54 | + int port) { | ||
55 | + Preconditions.checkArgument(!name.equals(""), "Empty device name"); | ||
56 | + Preconditions.checkNotNull(port > 0, "Negative port"); | ||
57 | + Preconditions.checkNotNull(ipAddress, "Null ip address"); | ||
58 | + this.name = name; | ||
59 | + this.password = password; | ||
60 | + this.ipAddress = ipAddress; | ||
61 | + this.port = port; | ||
62 | + } | ||
63 | + | ||
64 | + /** | ||
65 | + * Information for contacting the controller. | ||
66 | + * | ||
67 | + * @param name the connection type | ||
68 | + * @param password the password for the device | ||
69 | + * @param ipAddress the ip address | ||
70 | + * @param port the tcp port | ||
71 | + * @param keyString the string cointaing the key. | ||
72 | + */ | ||
73 | + public NetconfDeviceInfo(String name, String password, IpAddress ipAddress, | ||
74 | + int port, String keyString) { | ||
75 | + Preconditions.checkArgument(!name.equals(""), "Empty device name"); | ||
76 | + Preconditions.checkNotNull(port > 0, "Negative port"); | ||
77 | + Preconditions.checkNotNull(ipAddress, "Null ip address"); | ||
78 | + this.name = name; | ||
79 | + this.password = password; | ||
80 | + this.ipAddress = ipAddress; | ||
81 | + this.port = port; | ||
82 | + this.keyFile = new File(keyString); | ||
83 | + } | ||
84 | + | ||
85 | + /** | ||
86 | + * Exposes the name of the controller. | ||
87 | + * | ||
88 | + * @return String name | ||
89 | + */ | ||
90 | + public String name() { | ||
91 | + return name; | ||
92 | + } | ||
93 | + | ||
94 | + /** | ||
95 | + * Exposes the password of the controller. | ||
96 | + * | ||
97 | + * @return String password | ||
98 | + */ | ||
99 | + public String password() { | ||
100 | + return password; | ||
101 | + } | ||
102 | + | ||
103 | + /** | ||
104 | + * Exposes the ip address of the controller. | ||
105 | + * | ||
106 | + * @return IpAddress ip address | ||
107 | + */ | ||
108 | + public IpAddress ip() { | ||
109 | + return ipAddress; | ||
110 | + } | ||
111 | + | ||
112 | + /** | ||
113 | + * Exposes the port of the controller. | ||
114 | + * | ||
115 | + * @return int port address | ||
116 | + */ | ||
117 | + public int port() { | ||
118 | + return port; | ||
119 | + } | ||
120 | + | ||
121 | + /** | ||
122 | + * Exposes the keyFile of the controller. | ||
123 | + * | ||
124 | + * @return int port address | ||
125 | + */ | ||
126 | + public File getKeyFile() { | ||
127 | + return keyFile; | ||
128 | + } | ||
129 | + | ||
130 | + /** | ||
131 | + * Return the info about the device in a string. | ||
132 | + * String format: "netconf:name@ip:port" | ||
133 | + * | ||
134 | + * @return String device info | ||
135 | + */ | ||
136 | + public String toString() { | ||
137 | + return "netconf:" + name + "@" + ipAddress + ":" + port; | ||
138 | + } | ||
139 | + | ||
140 | + /** | ||
141 | + * Return the DeviceId about the device containing the URI. | ||
142 | + * | ||
143 | + * @return DeviceId | ||
144 | + */ | ||
145 | + public DeviceId getDeviceId() { | ||
146 | + | ||
147 | + try { | ||
148 | + return DeviceId.deviceId(new URI(this.toString())); | ||
149 | + } catch (URISyntaxException e) { | ||
150 | + log.debug("Unable to build deviceID for device {} ", this, e); | ||
151 | + } | ||
152 | + return null; | ||
153 | + } | ||
154 | + | ||
155 | + @Override | ||
156 | + public int hashCode() { | ||
157 | + return Objects.hash(ipAddress, port, name); | ||
158 | + } | ||
159 | + | ||
160 | + @Override | ||
161 | + public boolean equals(Object toBeCompared) { | ||
162 | + if (toBeCompared instanceof NetconfDeviceInfo) { | ||
163 | + NetconfDeviceInfo netconfDeviceInfo = (NetconfDeviceInfo) toBeCompared; | ||
164 | + if (netconfDeviceInfo.name().equals(name) | ||
165 | + && netconfDeviceInfo.ip().equals(ipAddress) | ||
166 | + && netconfDeviceInfo.port() == port | ||
167 | + && netconfDeviceInfo.password().equals(password)) { | ||
168 | + return true; | ||
169 | + } | ||
170 | + } | ||
171 | + return false; | ||
172 | + } | ||
173 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.netconf; | ||
18 | + | ||
19 | +/** | ||
20 | + * Allows for providers interested in node events to be notified. | ||
21 | + */ | ||
22 | +public interface NetconfDeviceListener { | ||
23 | + | ||
24 | + /** | ||
25 | + * Notifies that the node was added. | ||
26 | + * | ||
27 | + * @param nodeId the node where the event occurred | ||
28 | + */ | ||
29 | + void deviceAdded(NetconfDeviceInfo nodeId); | ||
30 | + | ||
31 | + /** | ||
32 | + * Notifies that the node was removed. | ||
33 | + * | ||
34 | + * @param nodeId the node where the event occurred | ||
35 | + */ | ||
36 | + void deviceRemoved(NetconfDeviceInfo nodeId); | ||
37 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.netconf; | ||
18 | + | ||
19 | +import java.util.List; | ||
20 | + | ||
21 | +/** | ||
22 | + * NETCONF session object that allows NETCONF operations on top with the physical | ||
23 | + * device on top of an SSH connection. | ||
24 | + */ | ||
25 | +// TODO change return type of methdos to <Capability, XMLdoc, string or yang obj> | ||
26 | +public interface NetconfSession { | ||
27 | + | ||
28 | + /** | ||
29 | + * Retrives the requested configuration, different from get-config. | ||
30 | + * @param request the XML containing the request to the server. | ||
31 | + * @return device running configuration | ||
32 | + */ | ||
33 | + String get(String request); | ||
34 | + | ||
35 | + /** | ||
36 | + * Executes an RPC to the server. | ||
37 | + * @param request the XML containing the RPC for the server. | ||
38 | + * @return Server response or ERROR | ||
39 | + */ | ||
40 | + String doRPC(String request); | ||
41 | + | ||
42 | + /** | ||
43 | + * Retrives the specified configuration. | ||
44 | + * | ||
45 | + * @param targetConfiguration the type of configuration to retrieve. | ||
46 | + * @return specified configuration. | ||
47 | + */ | ||
48 | + String getConfig(String targetConfiguration); | ||
49 | + | ||
50 | + /** | ||
51 | + * Retrives part of the specivied configuration based on the filterSchema. | ||
52 | + * | ||
53 | + * @param targetConfiguration the type of configuration to retrieve. | ||
54 | + * @param configurationFilterSchema XML schema to filter the configuration | ||
55 | + * elements we are interested in | ||
56 | + * @return device running configuration. | ||
57 | + */ | ||
58 | + String getConfig(String targetConfiguration, String configurationFilterSchema); | ||
59 | + | ||
60 | + /** | ||
61 | + * Retrives part of the specified configuration based on the filterSchema. | ||
62 | + * | ||
63 | + * @param newConfiguration configuration to set | ||
64 | + * @return true if the configuration was edited correctly | ||
65 | + */ | ||
66 | + | ||
67 | + boolean editConfig(String newConfiguration); | ||
68 | + | ||
69 | + /** | ||
70 | + * Copies the new configuration, an Url or a complete configuration xml tree | ||
71 | + * to the target configuration. | ||
72 | + * The target configuration can't be the running one | ||
73 | + * | ||
74 | + * @param targetConfiguration the type of configuration to retrieve. | ||
75 | + * @param newConfiguration configuration to set | ||
76 | + * @return true if the configuration was copied correctly | ||
77 | + */ | ||
78 | + boolean copyConfig(String targetConfiguration, String newConfiguration); | ||
79 | + | ||
80 | + /** | ||
81 | + * Deletes part of the specified configuration based on the filterSchema. | ||
82 | + * | ||
83 | + * @param targetConfiguration the name of the configuration to delete | ||
84 | + * @return true if the configuration was copied correctly | ||
85 | + */ | ||
86 | + boolean deleteConfig(String targetConfiguration); | ||
87 | + | ||
88 | + /** | ||
89 | + * Locks the candidate configuration. | ||
90 | + * | ||
91 | + * @return true if successful. | ||
92 | + */ | ||
93 | + boolean lock(); | ||
94 | + | ||
95 | + /** | ||
96 | + * Unlocks the candidate configuration. | ||
97 | + * | ||
98 | + * @return true if successful. | ||
99 | + */ | ||
100 | + boolean unlock(); | ||
101 | + | ||
102 | + /** | ||
103 | + * Closes the Netconf session with the device. | ||
104 | + * the first time it tries gracefully, then kills it forcefully | ||
105 | + * @return true if closed | ||
106 | + */ | ||
107 | + boolean close(); | ||
108 | + | ||
109 | + /** | ||
110 | + * Gets the session ID of the Netconf session. | ||
111 | + * | ||
112 | + * @return Session ID as a string. | ||
113 | + */ | ||
114 | + String getSessionId(); | ||
115 | + | ||
116 | + /** | ||
117 | + * Gets the capabilities of the Netconf server associated to this session. | ||
118 | + * | ||
119 | + * @return Network capabilities as a string. | ||
120 | + */ | ||
121 | + String getServerCapabilities(); | ||
122 | + | ||
123 | + /** | ||
124 | + * Sets the device capabilities. | ||
125 | + * @param capabilities list of capabilities the device has. | ||
126 | + */ | ||
127 | + void setDeviceCapabilities(List<String> capabilities); | ||
128 | + | ||
129 | +} |
... | @@ -39,9 +39,53 @@ | ... | @@ -39,9 +39,53 @@ |
39 | <version>${project.version}</version> | 39 | <version>${project.version}</version> |
40 | </dependency> | 40 | </dependency> |
41 | <dependency> | 41 | <dependency> |
42 | - <groupId>org.onosproject</groupId> | 42 | + <groupId>ch.ethz.ganymed</groupId> |
43 | - <artifactId>onos-netconf-rfc</artifactId> | 43 | + <artifactId>ganymed-ssh2</artifactId> |
44 | - <version>${project.version}</version> | 44 | + <version>262</version> |
45 | </dependency> | 45 | </dependency> |
46 | </dependencies> | 46 | </dependencies> |
47 | + | ||
48 | + <build> | ||
49 | + <plugins> | ||
50 | + <!--plugin> | ||
51 | + <groupId>org.apache.maven.plugins</groupId> | ||
52 | + <artifactId>maven-shade-plugin</artifactId> | ||
53 | + <version>2.3</version> | ||
54 | + <configuration> | ||
55 | + <filters> | ||
56 | + <filter> | ||
57 | + <artifact>ch.ethz.ganymed:ganymed-ssh2</artifact> | ||
58 | + <includes> | ||
59 | + <include>ch/ethz/ssh2/**</include> | ||
60 | + </includes> | ||
61 | + </filter> | ||
62 | + <filter> | ||
63 | + <artifact>org.jdom:jdom2</artifact> | ||
64 | + <includes> | ||
65 | + <include>org/jdom2/**</include> | ||
66 | + </includes> | ||
67 | + </filter> | ||
68 | + </filters> | ||
69 | + </configuration> | ||
70 | + <executions> | ||
71 | + <execution> | ||
72 | + <phase>package</phase> | ||
73 | + <goals> | ||
74 | + <goal>shade</goal> | ||
75 | + </goals> | ||
76 | + </execution> | ||
77 | + </executions> | ||
78 | + </plugin--> | ||
79 | + <plugin> | ||
80 | + <groupId>org.apache.felix</groupId> | ||
81 | + <artifactId>maven-bundle-plugin</artifactId> | ||
82 | + <configuration> | ||
83 | + <instructions> | ||
84 | + <Private-Package>ch.ethz.ssh2.*</Private-Package> | ||
85 | + <Embed-Dependecy>ganymed-ssh2</Embed-Dependecy> | ||
86 | + </instructions> | ||
87 | + </configuration> | ||
88 | + </plugin> | ||
89 | + </plugins> | ||
90 | + </build> | ||
47 | </project> | 91 | </project> | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.netconf.ctl; | ||
18 | + | ||
19 | +import org.apache.felix.scr.annotations.Activate; | ||
20 | +import org.apache.felix.scr.annotations.Component; | ||
21 | +import org.apache.felix.scr.annotations.Deactivate; | ||
22 | +import org.apache.felix.scr.annotations.Service; | ||
23 | +import org.onlab.packet.IpAddress; | ||
24 | +import org.onosproject.net.DeviceId; | ||
25 | +import org.onosproject.netconf.NetconfController; | ||
26 | +import org.onosproject.netconf.NetconfDevice; | ||
27 | +import org.onosproject.netconf.NetconfDeviceInfo; | ||
28 | +import org.onosproject.netconf.NetconfDeviceListener; | ||
29 | +import org.osgi.service.component.ComponentContext; | ||
30 | +import org.slf4j.Logger; | ||
31 | +import org.slf4j.LoggerFactory; | ||
32 | + | ||
33 | +import java.io.IOException; | ||
34 | +import java.util.Map; | ||
35 | +import java.util.Set; | ||
36 | +import java.util.concurrent.ConcurrentHashMap; | ||
37 | +import java.util.concurrent.CopyOnWriteArraySet; | ||
38 | + | ||
39 | +/** | ||
40 | + * The implementation of NetconfController. | ||
41 | + */ | ||
42 | +@Component(immediate = true) | ||
43 | +@Service | ||
44 | +public class NetconfControllerImpl implements NetconfController { | ||
45 | + | ||
46 | + public static final Logger log = LoggerFactory | ||
47 | + .getLogger(NetconfControllerImpl.class); | ||
48 | + | ||
49 | + public Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<>(); | ||
50 | + | ||
51 | + protected Set<NetconfDeviceListener> netconfDeviceListeners = new CopyOnWriteArraySet<>(); | ||
52 | + | ||
53 | + @Activate | ||
54 | + public void activate(ComponentContext context) { | ||
55 | + log.info("Started"); | ||
56 | + } | ||
57 | + | ||
58 | + @Deactivate | ||
59 | + public void deactivate() { | ||
60 | + netconfDeviceMap.clear(); | ||
61 | + log.info("Stopped"); | ||
62 | + } | ||
63 | + | ||
64 | + @Override | ||
65 | + public void addDeviceListener(NetconfDeviceListener listener) { | ||
66 | + if (!netconfDeviceListeners.contains(listener)) { | ||
67 | + netconfDeviceListeners.add(listener); | ||
68 | + } | ||
69 | + } | ||
70 | + | ||
71 | + @Override | ||
72 | + public void removeDeviceListener(NetconfDeviceListener listener) { | ||
73 | + netconfDeviceListeners.remove(listener); | ||
74 | + } | ||
75 | + | ||
76 | + @Override | ||
77 | + public NetconfDevice getNetconfDevice(DeviceId deviceInfo) { | ||
78 | + return netconfDeviceMap.get(deviceInfo); | ||
79 | + } | ||
80 | + | ||
81 | + @Override | ||
82 | + public NetconfDevice getNetconfDevice(IpAddress ip, int port) { | ||
83 | + NetconfDevice device = null; | ||
84 | + for (DeviceId info : netconfDeviceMap.keySet()) { | ||
85 | + if (IpAddress.valueOf(info.uri().getHost()).equals(ip) && | ||
86 | + info.uri().getPort() == port) { | ||
87 | + return netconfDeviceMap.get(info); | ||
88 | + } | ||
89 | + } | ||
90 | + return device; | ||
91 | + } | ||
92 | + | ||
93 | + @Override | ||
94 | + public NetconfDevice connectDevice(NetconfDeviceInfo deviceInfo) { | ||
95 | + if (netconfDeviceMap.containsKey(deviceInfo.getDeviceId())) { | ||
96 | + log.warn("Device {} is already present"); | ||
97 | + return netconfDeviceMap.get(deviceInfo.getDeviceId()); | ||
98 | + } else { | ||
99 | + log.info("Creating NETCONF device {}", deviceInfo); | ||
100 | + return createDevice(deviceInfo); | ||
101 | + } | ||
102 | + } | ||
103 | + | ||
104 | + @Override | ||
105 | + public void removeDevice(NetconfDeviceInfo deviceInfo) { | ||
106 | + if (netconfDeviceMap.containsKey(deviceInfo.getDeviceId())) { | ||
107 | + log.warn("Device {} is not present"); | ||
108 | + } else { | ||
109 | + stopDevice(deviceInfo); | ||
110 | + } | ||
111 | + } | ||
112 | + | ||
113 | + private NetconfDevice createDevice(NetconfDeviceInfo deviceInfo) { | ||
114 | + NetconfDevice netconfDevice = null; | ||
115 | + try { | ||
116 | + netconfDevice = new NetconfDeviceImpl(deviceInfo); | ||
117 | + for (NetconfDeviceListener l : netconfDeviceListeners) { | ||
118 | + l.deviceAdded(deviceInfo); | ||
119 | + } | ||
120 | + netconfDeviceMap.put(deviceInfo.getDeviceId(), netconfDevice); | ||
121 | + } catch (IOException e) { | ||
122 | + throw new IllegalStateException("Cannot create NETCONF device " + | ||
123 | + "with device Info: " + | ||
124 | + deviceInfo + " \n" + e); | ||
125 | + } | ||
126 | + return netconfDevice; | ||
127 | + } | ||
128 | + | ||
129 | + private void stopDevice(NetconfDeviceInfo deviceInfo) { | ||
130 | + netconfDeviceMap.get(deviceInfo.getDeviceId()).disconnect(); | ||
131 | + netconfDeviceMap.remove(deviceInfo.getDeviceId()); | ||
132 | + for (NetconfDeviceListener l : netconfDeviceListeners) { | ||
133 | + l.deviceRemoved(deviceInfo); | ||
134 | + } | ||
135 | + } | ||
136 | + | ||
137 | + @Override | ||
138 | + public Map<DeviceId, NetconfDevice> getDevicesMap() { | ||
139 | + return netconfDeviceMap; | ||
140 | + } | ||
141 | + | ||
142 | + | ||
143 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.netconf.ctl; | ||
18 | + | ||
19 | +import org.onosproject.netconf.NetconfDevice; | ||
20 | +import org.onosproject.netconf.NetconfDeviceInfo; | ||
21 | +import org.onosproject.netconf.NetconfSession; | ||
22 | + | ||
23 | +import java.io.IOException; | ||
24 | + | ||
25 | +/** | ||
26 | + * Implementation of a NETCONF device. | ||
27 | + */ | ||
28 | +public class NetconfDeviceImpl implements NetconfDevice { | ||
29 | + | ||
30 | + private NetconfDeviceInfo netconfDeviceInfo; | ||
31 | + private boolean deviceState = false; | ||
32 | + private NetconfSession netconfSession; | ||
33 | + //private String config; | ||
34 | + | ||
35 | + public NetconfDeviceImpl(NetconfDeviceInfo deviceInfo) throws IOException { | ||
36 | + netconfDeviceInfo = deviceInfo; | ||
37 | + try { | ||
38 | + netconfSession = new NetconfSessionImpl(netconfDeviceInfo); | ||
39 | + } catch (IOException e) { | ||
40 | + throw new IOException("Cannot create connection and session", e); | ||
41 | + } | ||
42 | + deviceState = true; | ||
43 | + //config = netconfSession.getConfig("running"); | ||
44 | + } | ||
45 | + | ||
46 | + @Override | ||
47 | + public boolean isActive() { | ||
48 | + return deviceState; | ||
49 | + } | ||
50 | + | ||
51 | + @Override | ||
52 | + public NetconfSession getSession() { | ||
53 | + return netconfSession; | ||
54 | + } | ||
55 | + | ||
56 | + @Override | ||
57 | + public void disconnect() { | ||
58 | + deviceState = false; | ||
59 | + netconfSession.close(); | ||
60 | + } | ||
61 | + | ||
62 | + @Override | ||
63 | + public NetconfDeviceInfo getDeviceInfo() { | ||
64 | + return netconfDeviceInfo; | ||
65 | + } | ||
66 | +} |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.netconf.ctl; | ||
18 | + | ||
19 | +import ch.ethz.ssh2.Connection; | ||
20 | +import ch.ethz.ssh2.Session; | ||
21 | +import com.google.common.base.Preconditions; | ||
22 | +import org.onosproject.netconf.NetconfDeviceInfo; | ||
23 | +import org.onosproject.netconf.NetconfSession; | ||
24 | +import org.slf4j.Logger; | ||
25 | +import org.slf4j.LoggerFactory; | ||
26 | + | ||
27 | +import java.io.BufferedReader; | ||
28 | +import java.io.IOException; | ||
29 | +import java.io.InputStreamReader; | ||
30 | +import java.io.PrintWriter; | ||
31 | +import java.io.StringWriter; | ||
32 | +import java.util.ArrayList; | ||
33 | +import java.util.Arrays; | ||
34 | +import java.util.List; | ||
35 | + | ||
36 | +/** | ||
37 | + * Implementation of a NETCONF session to talk to a device. | ||
38 | + */ | ||
39 | +public class NetconfSessionImpl implements NetconfSession { | ||
40 | + | ||
41 | + public static final Logger log = LoggerFactory | ||
42 | + .getLogger(NetconfSessionImpl.class); | ||
43 | + private static final int CONNECTION_TIMEOUT = 0; | ||
44 | + | ||
45 | + | ||
46 | + private Connection netconfConnection; | ||
47 | + private NetconfDeviceInfo deviceInfo; | ||
48 | + private Session sshSession; | ||
49 | + private boolean connectionActive; | ||
50 | + private BufferedReader bufferReader = null; | ||
51 | + private PrintWriter out = null; | ||
52 | + private int messageID = 0; | ||
53 | + | ||
54 | + private List<String> deviceCapabilities = | ||
55 | + new ArrayList<>( | ||
56 | + Arrays.asList("urn:ietf:params:netconf:base:1.0")); | ||
57 | + | ||
58 | + private String serverCapabilities; | ||
59 | + private String endpattern = "]]>]]>"; | ||
60 | + | ||
61 | + | ||
62 | + public NetconfSessionImpl(NetconfDeviceInfo deviceInfo) throws IOException { | ||
63 | + this.deviceInfo = deviceInfo; | ||
64 | + connectionActive = false; | ||
65 | + startConnection(); | ||
66 | + } | ||
67 | + | ||
68 | + | ||
69 | + private void startConnection() throws IOException { | ||
70 | + if (!connectionActive) { | ||
71 | + netconfConnection = new Connection(deviceInfo.ip().toString(), deviceInfo.port()); | ||
72 | + netconfConnection.connect(null, CONNECTION_TIMEOUT, 0); | ||
73 | + boolean isAuthenticated; | ||
74 | + try { | ||
75 | + if (deviceInfo.getKeyFile() != null) { | ||
76 | + isAuthenticated = netconfConnection.authenticateWithPublicKey( | ||
77 | + deviceInfo.name(), deviceInfo.getKeyFile(), | ||
78 | + deviceInfo.password()); | ||
79 | + } else { | ||
80 | + log.info("authenticate with username {} and password {}", | ||
81 | + deviceInfo.name(), deviceInfo.password()); | ||
82 | + isAuthenticated = netconfConnection.authenticateWithPassword( | ||
83 | + deviceInfo.name(), deviceInfo.password()); | ||
84 | + } | ||
85 | + } catch (IOException e) { | ||
86 | + throw new IOException("Authentication connection failed:" + | ||
87 | + e.getMessage()); | ||
88 | + } | ||
89 | + | ||
90 | + connectionActive = true; | ||
91 | + Preconditions.checkArgument(isAuthenticated, | ||
92 | + "Authentication password and username failed"); | ||
93 | + startSshSession(); | ||
94 | + } | ||
95 | + } | ||
96 | + | ||
97 | + private void startSshSession() throws IOException { | ||
98 | + try { | ||
99 | + sshSession = netconfConnection.openSession(); | ||
100 | + sshSession.startSubSystem("netconf"); | ||
101 | + bufferReader = new BufferedReader(new InputStreamReader( | ||
102 | + sshSession.getStdout())); | ||
103 | + out = new PrintWriter(sshSession.getStdin()); | ||
104 | + sendHello(); | ||
105 | + } catch (IOException e) { | ||
106 | + throw new IOException("Failed to create ch.ethz.ssh2.Session session:" + | ||
107 | + e.getMessage()); | ||
108 | + } | ||
109 | + } | ||
110 | + | ||
111 | + private void sendHello() throws IOException { | ||
112 | + serverCapabilities = doRequest(createHelloString()); | ||
113 | + } | ||
114 | + | ||
115 | + private String createHelloString() { | ||
116 | + StringBuilder hellobuffer = new StringBuilder(); | ||
117 | + hellobuffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); | ||
118 | + hellobuffer.append("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"); | ||
119 | + hellobuffer.append(" <capabilities>\n"); | ||
120 | + deviceCapabilities.forEach( | ||
121 | + cap -> hellobuffer.append(" <capability>" + cap + "</capability>\n")); | ||
122 | + hellobuffer.append(" </capabilities>\n"); | ||
123 | + hellobuffer.append("</hello>\n"); | ||
124 | + hellobuffer.append(endpattern); | ||
125 | + return hellobuffer.toString(); | ||
126 | + | ||
127 | + } | ||
128 | + | ||
129 | + @Override | ||
130 | + public String doRPC(String request) { | ||
131 | + String reply = "ERROR"; | ||
132 | + try { | ||
133 | + reply = doRequest(request); | ||
134 | + if (checkReply(reply)) { | ||
135 | + return reply; | ||
136 | + } else { | ||
137 | + return "ERROR " + reply; | ||
138 | + } | ||
139 | + } catch (IOException e) { | ||
140 | + log.error("Problem in the reading from the SSH connection " + e); | ||
141 | + } | ||
142 | + return reply; | ||
143 | + } | ||
144 | + | ||
145 | + private String doRequest(String request) throws IOException { | ||
146 | + log.info("sshState " + sshSession.getState() + "request" + request); | ||
147 | + if (sshSession.getState() != 2) { | ||
148 | + try { | ||
149 | + startSshSession(); | ||
150 | + } catch (IOException e) { | ||
151 | + log.info("the connection had to be reopened"); | ||
152 | + startConnection(); | ||
153 | + } | ||
154 | + sendHello(); | ||
155 | + } | ||
156 | + log.info("sshState after" + sshSession.getState()); | ||
157 | + out.print(request); | ||
158 | + out.flush(); | ||
159 | + messageID++; | ||
160 | + return readOne(); | ||
161 | + } | ||
162 | + | ||
163 | + @Override | ||
164 | + public String get(String request) { | ||
165 | + return doRPC(request); | ||
166 | + } | ||
167 | + | ||
168 | + @Override | ||
169 | + public String getConfig(String targetConfiguration) { | ||
170 | + return getConfig(targetConfiguration, null); | ||
171 | + } | ||
172 | + | ||
173 | + @Override | ||
174 | + public String getConfig(String targetConfiguration, String configurationSchema) { | ||
175 | + StringBuilder rpc = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); | ||
176 | + rpc.append("<rpc message-id=\"" + messageID + "\" " | ||
177 | + + "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"); | ||
178 | + rpc.append("<get-config>\n"); | ||
179 | + rpc.append("<source>\n"); | ||
180 | + rpc.append("<" + targetConfiguration + "/>"); | ||
181 | + rpc.append("</source>"); | ||
182 | + if (configurationSchema != null) { | ||
183 | + rpc.append("<filter type=\"subtree\">\n"); | ||
184 | + rpc.append(configurationSchema + "\n"); | ||
185 | + rpc.append("</filter>\n"); | ||
186 | + } | ||
187 | + rpc.append("</get-config>\n"); | ||
188 | + rpc.append("</rpc>\n"); | ||
189 | + rpc.append(endpattern); | ||
190 | + String reply = null; | ||
191 | + try { | ||
192 | + reply = doRequest(rpc.toString()); | ||
193 | + } catch (IOException e) { | ||
194 | + e.printStackTrace(); | ||
195 | + } | ||
196 | + | ||
197 | + return checkReply(reply) ? reply : null; | ||
198 | + } | ||
199 | + | ||
200 | + @Override | ||
201 | + public boolean editConfig(String newConfiguration) { | ||
202 | + newConfiguration = newConfiguration + endpattern; | ||
203 | + String reply = null; | ||
204 | + try { | ||
205 | + reply = doRequest(newConfiguration); | ||
206 | + } catch (IOException e) { | ||
207 | + e.printStackTrace(); | ||
208 | + } | ||
209 | + return checkReply(reply); | ||
210 | + } | ||
211 | + | ||
212 | + @Override | ||
213 | + public boolean copyConfig(String targetConfiguration, String newConfiguration) { | ||
214 | + newConfiguration = newConfiguration.trim(); | ||
215 | + if (!newConfiguration.startsWith("<configuration>")) { | ||
216 | + newConfiguration = "<configuration>" + newConfiguration | ||
217 | + + "</configuration>"; | ||
218 | + } | ||
219 | + StringBuilder rpc = new StringBuilder("<?xml version=\"1.0\" " + | ||
220 | + "encoding=\"UTF-8\"?>"); | ||
221 | + rpc.append("<rpc>"); | ||
222 | + rpc.append("<copy-config>"); | ||
223 | + rpc.append("<target>"); | ||
224 | + rpc.append("<" + targetConfiguration + "/>"); | ||
225 | + rpc.append("</target>"); | ||
226 | + rpc.append("<source>"); | ||
227 | + rpc.append("<" + newConfiguration + "/>"); | ||
228 | + rpc.append("</source>"); | ||
229 | + rpc.append("</copy-config>"); | ||
230 | + rpc.append("</rpc>"); | ||
231 | + rpc.append(endpattern); | ||
232 | + String reply = null; | ||
233 | + try { | ||
234 | + reply = doRequest(rpc.toString()); | ||
235 | + } catch (IOException e) { | ||
236 | + e.printStackTrace(); | ||
237 | + } | ||
238 | + | ||
239 | + return checkReply(reply); | ||
240 | + } | ||
241 | + | ||
242 | + @Override | ||
243 | + public boolean deleteConfig(String targetConfiguration) { | ||
244 | + if (targetConfiguration.equals("running")) { | ||
245 | + log.warn("Target configuration for delete operation can't be \"running\"", | ||
246 | + targetConfiguration); | ||
247 | + return false; | ||
248 | + } | ||
249 | + StringBuilder rpc = new StringBuilder("<?xml version=\"1.0\" " + | ||
250 | + "encoding=\"UTF-8\"?>"); | ||
251 | + rpc.append("<rpc>"); | ||
252 | + rpc.append("<delete-config>"); | ||
253 | + rpc.append("<target>"); | ||
254 | + rpc.append("<" + targetConfiguration + "/>"); | ||
255 | + rpc.append("</target>"); | ||
256 | + rpc.append("</delete-config>"); | ||
257 | + rpc.append("</rpc>"); | ||
258 | + rpc.append(endpattern); | ||
259 | + String reply = null; | ||
260 | + try { | ||
261 | + reply = doRequest(rpc.toString()); | ||
262 | + } catch (IOException e) { | ||
263 | + e.printStackTrace(); | ||
264 | + } | ||
265 | + | ||
266 | + return checkReply(reply); | ||
267 | + } | ||
268 | + | ||
269 | + @Override | ||
270 | + public boolean lock() { | ||
271 | + StringBuilder rpc = new StringBuilder("<?xml version=\"1.0\" " + | ||
272 | + "encoding=\"UTF-8\"?>"); | ||
273 | + rpc.append("<rpc>"); | ||
274 | + rpc.append("<lock>"); | ||
275 | + rpc.append("<target>"); | ||
276 | + rpc.append("<candidate/>"); | ||
277 | + rpc.append("</target>"); | ||
278 | + rpc.append("</lock>"); | ||
279 | + rpc.append("</rpc>"); | ||
280 | + rpc.append(endpattern); | ||
281 | + String reply = null; | ||
282 | + try { | ||
283 | + reply = doRequest(rpc.toString()); | ||
284 | + } catch (IOException e) { | ||
285 | + e.printStackTrace(); | ||
286 | + } | ||
287 | + return checkReply(reply); | ||
288 | + } | ||
289 | + | ||
290 | + @Override | ||
291 | + public boolean unlock() { | ||
292 | + StringBuilder rpc = new StringBuilder("<?xml version=\"1.0\" " + | ||
293 | + "encoding=\"UTF-8\"?>"); | ||
294 | + rpc.append("<rpc>"); | ||
295 | + rpc.append("<unlock>"); | ||
296 | + rpc.append("<target>"); | ||
297 | + rpc.append("<candidate/>"); | ||
298 | + rpc.append("</target>"); | ||
299 | + rpc.append("</unlock>"); | ||
300 | + rpc.append("</rpc>"); | ||
301 | + rpc.append(endpattern); | ||
302 | + String reply = null; | ||
303 | + try { | ||
304 | + reply = doRequest(rpc.toString()); | ||
305 | + } catch (IOException e) { | ||
306 | + e.printStackTrace(); | ||
307 | + } | ||
308 | + return checkReply(reply); | ||
309 | + } | ||
310 | + | ||
311 | + @Override | ||
312 | + public boolean close() { | ||
313 | + return close(false); | ||
314 | + } | ||
315 | + | ||
316 | + private boolean close(boolean force) { | ||
317 | + StringBuilder rpc = new StringBuilder(); | ||
318 | + rpc.append("<rpc>"); | ||
319 | + if (force) { | ||
320 | + rpc.append("<kill-configuration/>"); | ||
321 | + } else { | ||
322 | + rpc.append("<close-configuration/>"); | ||
323 | + } | ||
324 | + rpc.append("<close-configuration/>"); | ||
325 | + rpc.append("</rpc>"); | ||
326 | + rpc.append(endpattern); | ||
327 | + return checkReply(rpc.toString()) ? true : close(true); | ||
328 | + } | ||
329 | + | ||
330 | + @Override | ||
331 | + public String getSessionId() { | ||
332 | + if (serverCapabilities.contains("<session-id>")) { | ||
333 | + String[] outer = serverCapabilities.split("<session-id>"); | ||
334 | + Preconditions.checkArgument(outer.length != 1, | ||
335 | + "Error in retrieving the session id"); | ||
336 | + String[] value = outer[1].split("</session-id>"); | ||
337 | + Preconditions.checkArgument(value.length != 1, | ||
338 | + "Error in retrieving the session id"); | ||
339 | + return value[0]; | ||
340 | + } else { | ||
341 | + return String.valueOf(-1); | ||
342 | + } | ||
343 | + } | ||
344 | + | ||
345 | + @Override | ||
346 | + public String getServerCapabilities() { | ||
347 | + return serverCapabilities; | ||
348 | + } | ||
349 | + | ||
350 | + @Override | ||
351 | + public void setDeviceCapabilities(List<String> capabilities) { | ||
352 | + deviceCapabilities = capabilities; | ||
353 | + } | ||
354 | + | ||
355 | + private boolean checkReply(String reply) { | ||
356 | + if (reply != null) { | ||
357 | + if (!reply.contains("<rpc-error>")) { | ||
358 | + return true; | ||
359 | + } else if (reply.contains("<ok/>") | ||
360 | + || (reply.contains("<rpc-error>") | ||
361 | + && reply.contains("warning"))) { | ||
362 | + return true; | ||
363 | + } | ||
364 | + } | ||
365 | + return false; | ||
366 | + } | ||
367 | + | ||
368 | + private String readOne() throws IOException { | ||
369 | + //TODO try a simple string | ||
370 | + final StringWriter reply = new StringWriter(); | ||
371 | + while (true) { | ||
372 | + int charRead = bufferReader.read(); | ||
373 | + if (charRead == -1) { | ||
374 | + throw new IOException("Session closed"); | ||
375 | + } | ||
376 | + | ||
377 | + for (int i = 0; i < endpattern.length(); i++) { | ||
378 | + if (charRead == endpattern.charAt(i)) { | ||
379 | + if (i < endpattern.length() - 1) { | ||
380 | + charRead = bufferReader.read(); | ||
381 | + } else { | ||
382 | + return reply.getBuffer().toString(); | ||
383 | + } | ||
384 | + } else { | ||
385 | + String s = endpattern.substring(0, i); | ||
386 | + for (int j = 0; i < s.length(); j++) { | ||
387 | + reply.write(s.charAt(j)); | ||
388 | + } | ||
389 | + reply.write(charRead); | ||
390 | + break; | ||
391 | + } | ||
392 | + } | ||
393 | + } | ||
394 | + } | ||
395 | + | ||
396 | +} |
... | @@ -27,6 +27,12 @@ | ... | @@ -27,6 +27,12 @@ |
27 | <artifactId>onos-netconf</artifactId> | 27 | <artifactId>onos-netconf</artifactId> |
28 | <packaging>pom</packaging> | 28 | <packaging>pom</packaging> |
29 | 29 | ||
30 | + <modules> | ||
31 | + <module>api</module> | ||
32 | + <module>rfc</module> | ||
33 | + <module>ctl</module> | ||
34 | + </modules> | ||
35 | + | ||
30 | <description>ONOS NETCONF southbound libraries</description> | 36 | <description>ONOS NETCONF southbound libraries</description> |
31 | <dependencies> | 37 | <dependencies> |
32 | <dependency> | 38 | <dependency> |
... | @@ -54,6 +60,11 @@ | ... | @@ -54,6 +60,11 @@ |
54 | <groupId>org.apache.felix</groupId> | 60 | <groupId>org.apache.felix</groupId> |
55 | <artifactId>org.apache.felix.scr.annotations</artifactId> | 61 | <artifactId>org.apache.felix.scr.annotations</artifactId> |
56 | </dependency> | 62 | </dependency> |
63 | + <dependency> | ||
64 | + <groupId>org.onosproject</groupId> | ||
65 | + <artifactId>onos-core-net</artifactId> | ||
66 | + <version>${project.version}</version> | ||
67 | + </dependency> | ||
57 | </dependencies> | 68 | </dependencies> |
58 | 69 | ||
59 | <build> | 70 | <build> |
... | @@ -68,10 +79,4 @@ | ... | @@ -68,10 +79,4 @@ |
68 | </plugin> | 79 | </plugin> |
69 | </plugins> | 80 | </plugins> |
70 | </build> | 81 | </build> |
71 | - | ||
72 | - <modules> | ||
73 | - <module>api</module> | ||
74 | - <module>rfc</module> | ||
75 | - <module>ctl</module> | ||
76 | - </modules> | ||
77 | </project> | 82 | </project> | ... | ... |
... | @@ -19,6 +19,13 @@ | ... | @@ -19,6 +19,13 @@ |
19 | features="${project.artifactId}"> | 19 | features="${project.artifactId}"> |
20 | <description>${project.description}</description> | 20 | <description>${project.description}</description> |
21 | 21 | ||
22 | + <artifact>mvn:${project.groupId}/onos-netconf-rfc/${project.version}</artifact> | ||
23 | + <artifact>mvn:${project.groupId}/onos-netconf-api/${project.version}</artifact> | ||
24 | + <artifact>mvn:${project.groupId}/onos-netconf-ctl/${project.version}</artifact> | ||
25 | + <artifact>mvn:${project.groupId}/onos-drivers/${project.version}</artifact> | ||
26 | + | ||
22 | <artifact>mvn:${project.groupId}/onos-netconf-provider-device/${project.version}</artifact> | 27 | <artifact>mvn:${project.groupId}/onos-netconf-provider-device/${project.version}</artifact> |
28 | + | ||
29 | + <!--<artifact>mvn:${project.groupId}/onos-netconf-provider-device/${project.version}</artifact>--> | ||
23 | <!-- Question: should there be the jnc stuff here? Or is it just for testing --> | 30 | <!-- Question: should there be the jnc stuff here? Or is it just for testing --> |
24 | </app> | 31 | </app> | ... | ... |
... | @@ -20,6 +20,9 @@ | ... | @@ -20,6 +20,9 @@ |
20 | description="${project.description}"> | 20 | description="${project.description}"> |
21 | <feature>onos-api</feature> | 21 | <feature>onos-api</feature> |
22 | <bundle>mvn:io.netty/netty/3.9.2.Final</bundle> | 22 | <bundle>mvn:io.netty/netty/3.9.2.Final</bundle> |
23 | + <bundle>mvn:${project.groupId}/onos-netconf-api/${project.version}</bundle> | ||
24 | + <bundle>mvn:${project.groupId}/onos-netconf-ctl/${project.version}</bundle> | ||
25 | + | ||
23 | <bundle>mvn:${project.groupId}/onos-netconf-provider-device/${project.version}</bundle> | 26 | <bundle>mvn:${project.groupId}/onos-netconf-provider-device/${project.version}</bundle> |
24 | <!-- Question: should there be the jnc stuff here? Or is it just for testing --> | 27 | <!-- Question: should there be the jnc stuff here? Or is it just for testing --> |
25 | </feature> | 28 | </feature> | ... | ... |
... | @@ -33,129 +33,29 @@ | ... | @@ -33,129 +33,29 @@ |
33 | 33 | ||
34 | <dependencies> | 34 | <dependencies> |
35 | <dependency> | 35 | <dependency> |
36 | - <groupId>org.osgi</groupId> | ||
37 | - <artifactId>org.osgi.compendium</artifactId> | ||
38 | - </dependency> | ||
39 | - <dependency> | ||
40 | - <groupId>ch.ethz.ganymed</groupId> | ||
41 | - <artifactId>ganymed-ssh2</artifactId> | ||
42 | - <version>262</version> | ||
43 | - </dependency> | ||
44 | - <dependency> | ||
45 | - <!-- TODO: change this appropriately when the official TailF JNC is available --> | ||
46 | <groupId>org.onosproject</groupId> | 36 | <groupId>org.onosproject</groupId> |
47 | - <artifactId>jnc</artifactId> | 37 | + <artifactId>onlab-junit</artifactId> |
48 | - <version>1.0</version> | 38 | + <scope>test</scope> |
49 | - </dependency> | ||
50 | - <dependency> | ||
51 | - <groupId>org.jdom</groupId> | ||
52 | - <artifactId>jdom2</artifactId> | ||
53 | - <version>2.0.5</version> | ||
54 | - </dependency> | ||
55 | - <dependency> | ||
56 | - <groupId>jaxen</groupId> | ||
57 | - <artifactId>jaxen</artifactId> | ||
58 | - <version>1.1.4</version> | ||
59 | - <optional>true</optional> | ||
60 | - </dependency> | ||
61 | - <dependency> | ||
62 | - <groupId>org.osgi</groupId> | ||
63 | - <artifactId>org.osgi.core</artifactId> | ||
64 | </dependency> | 39 | </dependency> |
65 | <dependency> | 40 | <dependency> |
66 | <groupId>org.onosproject</groupId> | 41 | <groupId>org.onosproject</groupId> |
67 | - <artifactId>onlab-junit</artifactId> | 42 | + <artifactId>onos-netconf-api</artifactId> |
68 | - <scope>test</scope> | 43 | + <version>${project.version}</version> |
69 | </dependency> | 44 | </dependency> |
70 | <dependency> | 45 | <dependency> |
71 | - <groupId>org.easymock</groupId> | 46 | + <groupId>org.onosproject</groupId> |
72 | - <artifactId>easymock</artifactId> | 47 | + <artifactId>onos-netconf-ctl</artifactId> |
73 | - <scope>test</scope> | 48 | + <version>${project.version}</version> |
74 | </dependency> | 49 | </dependency> |
75 | </dependencies> | 50 | </dependencies> |
76 | 51 | ||
77 | <build> | 52 | <build> |
78 | <plugins> | 53 | <plugins> |
79 | <plugin> | 54 | <plugin> |
80 | - <groupId>org.apache.maven.plugins</groupId> | ||
81 | - <artifactId>maven-shade-plugin</artifactId> | ||
82 | - <version>2.3</version> | ||
83 | - <configuration> | ||
84 | - <filters> | ||
85 | - <filter> | ||
86 | - <artifact>com.tailf:JNC</artifact> | ||
87 | - <includes> | ||
88 | - <include>com/tailf/jnc/**</include> | ||
89 | - </includes> | ||
90 | - </filter> | ||
91 | - <filter> | ||
92 | - <artifact>ch.ethz.ganymed:ganymed-ssh2</artifact> | ||
93 | - <includes> | ||
94 | - <include>ch/ethz/ssh2/**</include> | ||
95 | - </includes> | ||
96 | - </filter> | ||
97 | - <filter> | ||
98 | - <artifact>org.jdom:jdom2</artifact> | ||
99 | - <includes> | ||
100 | - <include>org/jdom2/**</include> | ||
101 | - </includes> | ||
102 | - </filter> | ||
103 | - </filters> | ||
104 | - </configuration> | ||
105 | - <executions> | ||
106 | - <execution> | ||
107 | - <phase>package</phase> | ||
108 | - <goals> | ||
109 | - <goal>shade</goal> | ||
110 | - </goals> | ||
111 | - </execution> | ||
112 | - </executions> | ||
113 | - </plugin> | ||
114 | - <plugin> | ||
115 | <groupId>org.apache.felix</groupId> | 55 | <groupId>org.apache.felix</groupId> |
116 | <artifactId>maven-scr-plugin</artifactId> | 56 | <artifactId>maven-scr-plugin</artifactId> |
117 | </plugin> | 57 | </plugin> |
118 | <plugin> | 58 | <plugin> |
119 | - <groupId>org.apache.felix</groupId> | ||
120 | - <artifactId>maven-bundle-plugin</artifactId> | ||
121 | - <configuration> | ||
122 | - <instructions> | ||
123 | - <Export-Package> | ||
124 | - com.tailf.jnc, | ||
125 | - ch.ethz.ssh2, | ||
126 | - ch.ethz.ssh2.auth, | ||
127 | - ch.ethz.ssh2.channel, | ||
128 | - ch.ethz.ssh2.crypto, | ||
129 | - ch.ethz.ssh2.crypto.cipher, | ||
130 | - ch.ethz.ssh2.crypto.dh, | ||
131 | - ch.ethz.ssh2.crypto.digest, | ||
132 | - ch.ethz.ssh2.log, | ||
133 | - ch.ethz.ssh2.packets, | ||
134 | - ch.ethz.ssh2.server, | ||
135 | - ch.ethz.ssh2.sftp, | ||
136 | - ch.ethz.ssh2.signature, | ||
137 | - ch.ethz.ssh2.transport, | ||
138 | - ch.ethz.ssh2.util, | ||
139 | - org.jdom2, | ||
140 | - org.jdom2.input, | ||
141 | - org.jdom2.output, | ||
142 | - org.jdom2.adapters, | ||
143 | - org.jdom2.filter, | ||
144 | - org.jdom2.internal, | ||
145 | - org.jdom2.located, | ||
146 | - org.jdom2.transform, | ||
147 | - org.jdom2.util, | ||
148 | - org.jdom2.xpath, | ||
149 | - org.jdom2.input.sax, | ||
150 | - org.jdom2.input.stax, | ||
151 | - org.jdom2.output.support, | ||
152 | - org.jdom2.xpath.jaxen, | ||
153 | - org.jdom2.xpath.util | ||
154 | - </Export-Package> | ||
155 | - </instructions> | ||
156 | - </configuration> | ||
157 | - </plugin> | ||
158 | - <plugin> | ||
159 | <groupId>org.onosproject</groupId> | 59 | <groupId>org.onosproject</groupId> |
160 | <artifactId>onos-maven-plugin</artifactId> | 60 | <artifactId>onos-maven-plugin</artifactId> |
161 | </plugin> | 61 | </plugin> | ... | ... |
1 | -/* | ||
2 | - * Copyright 2015 Open Networking Laboratory | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.onosproject.provider.netconf.device.impl; | ||
17 | - | ||
18 | -import static com.google.common.base.Preconditions.checkNotNull; | ||
19 | -import static org.onlab.util.Tools.delay; | ||
20 | -import static org.slf4j.LoggerFactory.getLogger; | ||
21 | - | ||
22 | -import java.io.IOException; | ||
23 | -import java.io.StringReader; | ||
24 | -import java.util.ArrayList; | ||
25 | -import java.util.List; | ||
26 | - | ||
27 | -import org.jdom2.Document; | ||
28 | -import org.jdom2.Element; | ||
29 | -import org.jdom2.input.SAXBuilder; | ||
30 | -import org.jdom2.output.Format; | ||
31 | -import org.jdom2.output.XMLOutputter; | ||
32 | -import org.slf4j.Logger; | ||
33 | - | ||
34 | -import com.tailf.jnc.Capabilities; | ||
35 | -import com.tailf.jnc.JNCException; | ||
36 | -import com.tailf.jnc.SSHConnection; | ||
37 | -import com.tailf.jnc.SSHSession; | ||
38 | - | ||
39 | -/** | ||
40 | - * This is a logical representation of actual NETCONF device, carrying all the | ||
41 | - * necessary information to connect and execute NETCONF operations. | ||
42 | - */ | ||
43 | -public class NetconfDevice { | ||
44 | - private final Logger log = getLogger(NetconfDevice.class); | ||
45 | - | ||
46 | - /** | ||
47 | - * The Device State is used to determine whether the device is active or | ||
48 | - * inactive. This state infomation will help Device Creator to add or delete | ||
49 | - * the device from the core. | ||
50 | - */ | ||
51 | - public static enum DeviceState { | ||
52 | - /* Used to specify Active state of the device */ | ||
53 | - ACTIVE, | ||
54 | - /* Used to specify inactive state of the device */ | ||
55 | - INACTIVE, | ||
56 | - /* Used to specify invalid state of the device */ | ||
57 | - INVALID | ||
58 | - } | ||
59 | - | ||
60 | - private static final int DEFAULT_SSH_PORT = 22; | ||
61 | - private static final int DEFAULT_CON_TIMEOUT = 0; | ||
62 | - private static final String XML_CAPABILITY_KEY = "capability"; | ||
63 | - private static final int EVENTINTERVAL = 2000; | ||
64 | - private static final int CONNECTION_CHECK_INTERVAL = 3; | ||
65 | - private static final String INPUT_HELLO_XML_MSG = new StringBuilder( | ||
66 | - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>") | ||
67 | - .append("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">") | ||
68 | - .append("<capabilities><capability>urn:ietf:params:netconf:base:1.0</capability>") | ||
69 | - .append("</capabilities></hello>").toString(); | ||
70 | - | ||
71 | - private String sshHost; | ||
72 | - private int sshPort = DEFAULT_SSH_PORT; | ||
73 | - private int connectTimeout = DEFAULT_CON_TIMEOUT; | ||
74 | - private String username; | ||
75 | - private String password; | ||
76 | - private boolean reachable = false; | ||
77 | - | ||
78 | - private List<String> capabilities = new ArrayList<String>(); | ||
79 | - private SSHConnection sshConnection = null; | ||
80 | - | ||
81 | - private DeviceState deviceState = DeviceState.INVALID; | ||
82 | - | ||
83 | - protected NetconfDevice(String sshHost, int sshPort, String username, | ||
84 | - String password) { | ||
85 | - this.username = checkNotNull(username, | ||
86 | - "Netconf Username Cannot be null"); | ||
87 | - this.sshHost = checkNotNull(sshHost, "Netconf Device IP cannot be null"); | ||
88 | - this.sshPort = checkNotNull(sshPort, | ||
89 | - "Netconf Device SSH port cannot be null"); | ||
90 | - this.password = password; | ||
91 | - } | ||
92 | - | ||
93 | - /** | ||
94 | - * This will try to connect to NETCONF device and find all the capabilities. | ||
95 | - * | ||
96 | - * @throws Exception if unable to connect to the device | ||
97 | - */ | ||
98 | - // FIXME: this should not be a generic Exception; perhaps wrap in some RuntimeException | ||
99 | - public void init() throws Exception { | ||
100 | - try { | ||
101 | - if (sshConnection == null) { | ||
102 | - sshConnection = new SSHConnection(sshHost, sshPort, connectTimeout); | ||
103 | - sshConnection.authenticateWithPassword(username, password); | ||
104 | - } | ||
105 | - // Send hello message to retrieve capabilities. | ||
106 | - } catch (IOException e) { | ||
107 | - log.error("Fatal Error while creating connection to the device: " | ||
108 | - + deviceInfo(), e); | ||
109 | - throw e; | ||
110 | - } catch (JNCException e) { | ||
111 | - log.error("Failed to connect to the device: " + deviceInfo(), e); | ||
112 | - throw e; | ||
113 | - } | ||
114 | - | ||
115 | - hello(); | ||
116 | - } | ||
117 | - | ||
118 | - private void hello() { | ||
119 | - SSHSession ssh = null; | ||
120 | - try { | ||
121 | - ssh = new SSHSession(sshConnection); | ||
122 | - String helloRequestXML = INPUT_HELLO_XML_MSG.trim(); | ||
123 | - | ||
124 | - log.debug("++++++++++++++++++++++++++++++++++Sending Hello: " | ||
125 | - + sshConnection.getGanymedConnection().getHostname() | ||
126 | - + "++++++++++++++++++++++++++++++++++"); | ||
127 | - printPrettyXML(helloRequestXML); | ||
128 | - ssh.print(helloRequestXML); | ||
129 | - // ssh.print(endCharSeq); | ||
130 | - ssh.flush(); | ||
131 | - String xmlResponse = null; | ||
132 | - int i = CONNECTION_CHECK_INTERVAL; | ||
133 | - while (!ssh.ready() && i > 0) { | ||
134 | - delay(EVENTINTERVAL); | ||
135 | - i--; | ||
136 | - } | ||
137 | - | ||
138 | - if (ssh.ready()) { | ||
139 | - StringBuffer readOne = ssh.readOne(); | ||
140 | - if (readOne == null) { | ||
141 | - log.error("The Hello Contains No Capabilites"); | ||
142 | - throw new JNCException( | ||
143 | - JNCException.SESSION_ERROR, | ||
144 | - "server does not support NETCONF base capability: " | ||
145 | - + Capabilities.NETCONF_BASE_CAPABILITY); | ||
146 | - } else { | ||
147 | - xmlResponse = readOne.toString().trim(); | ||
148 | - | ||
149 | - log.debug("++++++++++++++++++++++++++++++++++Reading Capabilities: " | ||
150 | - + sshConnection.getGanymedConnection() | ||
151 | - .getHostname() | ||
152 | - + "++++++++++++++++++++++++++++++++++"); | ||
153 | - | ||
154 | - printPrettyXML(xmlResponse); | ||
155 | - processCapabilities(xmlResponse); | ||
156 | - } | ||
157 | - } | ||
158 | - reachable = true; | ||
159 | - } catch (IOException e) { | ||
160 | - log.error("Fatal Error while sending Hello Message to the device: " | ||
161 | - + deviceInfo(), e); | ||
162 | - } catch (JNCException e) { | ||
163 | - log.error("Fatal Error while sending Hello Message to the device: " | ||
164 | - + deviceInfo(), e); | ||
165 | - } finally { | ||
166 | - log.debug("Closing the session after successful execution"); | ||
167 | - if (ssh != null) { | ||
168 | - ssh.close(); | ||
169 | - } | ||
170 | - } | ||
171 | - } | ||
172 | - | ||
173 | - private void processCapabilities(String xmlResponse) throws JNCException { | ||
174 | - if (xmlResponse.isEmpty()) { | ||
175 | - log.error("The capability response cannot be empty"); | ||
176 | - throw new JNCException( | ||
177 | - JNCException.SESSION_ERROR, | ||
178 | - "server does not support NETCONF base capability: " | ||
179 | - + Capabilities.NETCONF_BASE_CAPABILITY); | ||
180 | - } | ||
181 | - try { | ||
182 | - Document doc = new SAXBuilder() | ||
183 | - .build(new StringReader(xmlResponse)); | ||
184 | - Element rootElement = doc.getRootElement(); | ||
185 | - processCapabilities(rootElement); | ||
186 | - } catch (Exception e) { | ||
187 | - log.error("ERROR while parsing the XML " + xmlResponse); | ||
188 | - } | ||
189 | - } | ||
190 | - | ||
191 | - private void processCapabilities(Element rootElement) { | ||
192 | - List<Element> children = rootElement.getChildren(); | ||
193 | - if (children.isEmpty()) { | ||
194 | - return; | ||
195 | - } | ||
196 | - for (Element child : children) { | ||
197 | - | ||
198 | - if (child.getName().equals(XML_CAPABILITY_KEY)) { | ||
199 | - capabilities.add(child.getValue()); | ||
200 | - } | ||
201 | - if (!child.getChildren().isEmpty()) { | ||
202 | - processCapabilities(child); | ||
203 | - } | ||
204 | - } | ||
205 | - } | ||
206 | - | ||
207 | - private void printPrettyXML(String xmlstring) { | ||
208 | - try { | ||
209 | - Document doc = new SAXBuilder().build(new StringReader(xmlstring)); | ||
210 | - XMLOutputter xmOut = new XMLOutputter(Format.getPrettyFormat()); | ||
211 | - String outputString = xmOut.outputString(doc); | ||
212 | - log.debug(outputString); | ||
213 | - } catch (Exception e) { | ||
214 | - log.error("ERROR while parsing the XML " + xmlstring, e); | ||
215 | - | ||
216 | - } | ||
217 | - } | ||
218 | - | ||
219 | - /** | ||
220 | - * This would return host IP and host Port, used by this particular Netconf | ||
221 | - * Device. | ||
222 | - * @return Device Information. | ||
223 | - */ | ||
224 | - public String deviceInfo() { | ||
225 | - return new StringBuilder("host: ").append(sshHost).append(". port: ") | ||
226 | - .append(sshPort).toString(); | ||
227 | - } | ||
228 | - | ||
229 | - /** | ||
230 | - * This will terminate the device connection. | ||
231 | - */ | ||
232 | - public void disconnect() { | ||
233 | - sshConnection.close(); | ||
234 | - reachable = false; | ||
235 | - } | ||
236 | - | ||
237 | - /** | ||
238 | - * This will list down all the capabilities supported on the device. | ||
239 | - * @return Capability list. | ||
240 | - */ | ||
241 | - public List<String> getCapabilities() { | ||
242 | - return capabilities; | ||
243 | - } | ||
244 | - | ||
245 | - /** | ||
246 | - * This api is intended to know whether the device is connected or not. | ||
247 | - * @return true if connected | ||
248 | - */ | ||
249 | - public boolean isReachable() { | ||
250 | - return reachable; | ||
251 | - } | ||
252 | - | ||
253 | - /** | ||
254 | - * This will return the IP used connect ssh on the device. | ||
255 | - * @return Netconf Device IP | ||
256 | - */ | ||
257 | - public String getSshHost() { | ||
258 | - return sshHost; | ||
259 | - } | ||
260 | - | ||
261 | - /** | ||
262 | - * This will return the SSH Port used connect the device. | ||
263 | - * @return SSH Port number | ||
264 | - */ | ||
265 | - public int getSshPort() { | ||
266 | - return sshPort; | ||
267 | - } | ||
268 | - | ||
269 | - /** | ||
270 | - * The usename used to connect Netconf Device. | ||
271 | - * @return Device Username | ||
272 | - */ | ||
273 | - public String getUsername() { | ||
274 | - return username; | ||
275 | - } | ||
276 | - | ||
277 | - /** | ||
278 | - * Retrieve current state of the device. | ||
279 | - * @return Current Device State | ||
280 | - */ | ||
281 | - public DeviceState getDeviceState() { | ||
282 | - return deviceState; | ||
283 | - } | ||
284 | - | ||
285 | - /** | ||
286 | - * This is set the state information for the device. | ||
287 | - * @param deviceState Next Device State | ||
288 | - */ | ||
289 | - public void setDeviceState(DeviceState deviceState) { | ||
290 | - this.deviceState = deviceState; | ||
291 | - } | ||
292 | - | ||
293 | - /** | ||
294 | - * Check whether the device is in Active state. | ||
295 | - * @return true if the device is Active | ||
296 | - */ | ||
297 | - public boolean isActive() { | ||
298 | - return deviceState == DeviceState.ACTIVE ? true : false; | ||
299 | - } | ||
300 | - | ||
301 | - public void setConnectTimeout(int connectTimeout) { | ||
302 | - this.connectTimeout = connectTimeout; | ||
303 | - } | ||
304 | -} |
... | @@ -13,39 +13,28 @@ | ... | @@ -13,39 +13,28 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.onosproject.provider.netconf.device.impl; | ||
17 | - | ||
18 | -import static com.google.common.base.Strings.isNullOrEmpty; | ||
19 | -import static org.onlab.util.Tools.delay; | ||
20 | -import static org.onlab.util.Tools.get; | ||
21 | -import static org.onlab.util.Tools.groupedThreads; | ||
22 | -import static org.slf4j.LoggerFactory.getLogger; | ||
23 | 16 | ||
24 | -import java.io.IOException; | 17 | +package org.onosproject.provider.netconf.device.impl; |
25 | -import java.net.SocketTimeoutException; | ||
26 | -import java.net.URI; | ||
27 | -import java.net.URISyntaxException; | ||
28 | -import java.util.Dictionary; | ||
29 | -import java.util.Map; | ||
30 | -import java.util.Map.Entry; | ||
31 | -import java.util.concurrent.ConcurrentHashMap; | ||
32 | -import java.util.concurrent.ExecutorService; | ||
33 | -import java.util.concurrent.Executors; | ||
34 | -import java.util.concurrent.TimeUnit; | ||
35 | 18 | ||
19 | +import com.google.common.base.Preconditions; | ||
36 | import org.apache.felix.scr.annotations.Activate; | 20 | import org.apache.felix.scr.annotations.Activate; |
37 | import org.apache.felix.scr.annotations.Component; | 21 | import org.apache.felix.scr.annotations.Component; |
38 | import org.apache.felix.scr.annotations.Deactivate; | 22 | import org.apache.felix.scr.annotations.Deactivate; |
39 | -import org.apache.felix.scr.annotations.Modified; | ||
40 | -import org.apache.felix.scr.annotations.Property; | ||
41 | import org.apache.felix.scr.annotations.Reference; | 23 | import org.apache.felix.scr.annotations.Reference; |
42 | import org.apache.felix.scr.annotations.ReferenceCardinality; | 24 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
43 | import org.onlab.packet.ChassisId; | 25 | import org.onlab.packet.ChassisId; |
44 | -import org.onosproject.cfg.ComponentConfigService; | 26 | +import org.onosproject.core.ApplicationId; |
45 | -import org.onosproject.cluster.ClusterService; | 27 | +import org.onosproject.core.CoreService; |
28 | +import org.onosproject.incubator.net.config.basics.ConfigException; | ||
29 | +import org.onosproject.net.DefaultAnnotations; | ||
46 | import org.onosproject.net.Device; | 30 | import org.onosproject.net.Device; |
47 | import org.onosproject.net.DeviceId; | 31 | import org.onosproject.net.DeviceId; |
48 | import org.onosproject.net.MastershipRole; | 32 | import org.onosproject.net.MastershipRole; |
33 | +import org.onosproject.net.SparseAnnotations; | ||
34 | +import org.onosproject.net.config.ConfigFactory; | ||
35 | +import org.onosproject.net.config.NetworkConfigEvent; | ||
36 | +import org.onosproject.net.config.NetworkConfigListener; | ||
37 | +import org.onosproject.net.config.NetworkConfigRegistry; | ||
49 | import org.onosproject.net.device.DefaultDeviceDescription; | 38 | import org.onosproject.net.device.DefaultDeviceDescription; |
50 | import org.onosproject.net.device.DeviceDescription; | 39 | import org.onosproject.net.device.DeviceDescription; |
51 | import org.onosproject.net.device.DeviceProvider; | 40 | import org.onosproject.net.device.DeviceProvider; |
... | @@ -54,305 +43,180 @@ import org.onosproject.net.device.DeviceProviderService; | ... | @@ -54,305 +43,180 @@ import org.onosproject.net.device.DeviceProviderService; |
54 | import org.onosproject.net.device.DeviceService; | 43 | import org.onosproject.net.device.DeviceService; |
55 | import org.onosproject.net.provider.AbstractProvider; | 44 | import org.onosproject.net.provider.AbstractProvider; |
56 | import org.onosproject.net.provider.ProviderId; | 45 | import org.onosproject.net.provider.ProviderId; |
57 | -import org.onosproject.provider.netconf.device.impl.NetconfDevice.DeviceState; | 46 | +import org.onosproject.netconf.NetconfController; |
58 | -import org.osgi.service.component.ComponentContext; | 47 | +import org.onosproject.netconf.NetconfDevice; |
48 | +import org.onosproject.netconf.NetconfDeviceInfo; | ||
49 | +import org.onosproject.netconf.NetconfDeviceListener; | ||
59 | import org.slf4j.Logger; | 50 | import org.slf4j.Logger; |
60 | 51 | ||
52 | +import java.util.Map; | ||
53 | + | ||
54 | +import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY; | ||
55 | +import static org.slf4j.LoggerFactory.getLogger; | ||
56 | + | ||
61 | /** | 57 | /** |
62 | - * Provider which will try to fetch the details of NETCONF devices from the core | 58 | + * Provider which uses an NETCONF controller to detect device. |
63 | - * and run a capability discovery on each of the device. | ||
64 | */ | 59 | */ |
65 | @Component(immediate = true) | 60 | @Component(immediate = true) |
66 | public class NetconfDeviceProvider extends AbstractProvider | 61 | public class NetconfDeviceProvider extends AbstractProvider |
67 | implements DeviceProvider { | 62 | implements DeviceProvider { |
68 | - | 63 | + private final Logger log = getLogger(getClass()); |
69 | - private final Logger log = getLogger(NetconfDeviceProvider.class); | ||
70 | - | ||
71 | - protected Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>(); | ||
72 | - | ||
73 | - private DeviceProviderService providerService; | ||
74 | 64 | ||
75 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 65 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
76 | protected DeviceProviderRegistry providerRegistry; | 66 | protected DeviceProviderRegistry providerRegistry; |
77 | 67 | ||
78 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 68 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
79 | protected DeviceService deviceService; | 69 | protected DeviceService deviceService; |
80 | - | ||
81 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 70 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
82 | - protected ClusterService clusterService; | 71 | + protected NetconfController controller; //where is initiated ? |
83 | 72 | ||
84 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 73 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
85 | - protected ComponentConfigService cfgService; | 74 | + protected NetworkConfigRegistry cfgService; |
86 | - | ||
87 | - private ExecutorService deviceBuilder = Executors | ||
88 | - .newFixedThreadPool(1, groupedThreads("onos/netconf", "device-creator")); | ||
89 | - | ||
90 | - // Delay between events in ms. | ||
91 | - private static final int EVENTINTERVAL = 5; | ||
92 | - | ||
93 | - private static final String SCHEME = "netconf"; | ||
94 | 75 | ||
95 | - @Property(name = "devConfigs", value = "", label = "Instance-specific configurations") | 76 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
96 | - private String devConfigs = null; | 77 | + protected CoreService coreService; |
97 | 78 | ||
98 | - @Property(name = "devPasswords", value = "", label = "Instance-specific password") | ||
99 | - private String devPasswords = null; | ||
100 | 79 | ||
101 | - /** | 80 | + private DeviceProviderService providerService; |
102 | - * Creates a provider with the supplier identifier. | 81 | + private NetconfDeviceListener innerNodeListener = new InnerNetconfDeviceListener(); |
103 | - */ | 82 | + protected static final String ISNOTNULL = "NetconfDeviceInfo is not null"; |
104 | - public NetconfDeviceProvider() { | 83 | + private static final String UNKNOWN = "unknown"; |
105 | - super(new ProviderId("netconf", "org.onosproject.provider.netconf")); | 84 | + |
85 | + private final ConfigFactory factory = | ||
86 | + new ConfigFactory<ApplicationId, NetconfProviderConfig>(APP_SUBJECT_FACTORY, | ||
87 | + NetconfProviderConfig.class, | ||
88 | + "devices", | ||
89 | + true) { | ||
90 | + @Override | ||
91 | + public NetconfProviderConfig createConfig() { | ||
92 | + return new NetconfProviderConfig(); | ||
106 | } | 93 | } |
94 | + }; | ||
95 | + private final NetworkConfigListener cfgLister = new InternalNetworkConfigListener(); | ||
96 | + private ApplicationId appId; | ||
97 | + | ||
107 | 98 | ||
108 | @Activate | 99 | @Activate |
109 | - public void activate(ComponentContext context) { | 100 | + public void activate() { |
110 | - cfgService.registerProperties(getClass()); | ||
111 | providerService = providerRegistry.register(this); | 101 | providerService = providerRegistry.register(this); |
112 | - modified(context); | 102 | + cfgService.registerConfigFactory(factory); |
103 | + cfgService.addListener(cfgLister); | ||
104 | + controller.addDeviceListener(innerNodeListener); | ||
105 | + connectExistingDevices(); | ||
113 | log.info("Started"); | 106 | log.info("Started"); |
114 | } | 107 | } |
115 | 108 | ||
109 | + | ||
116 | @Deactivate | 110 | @Deactivate |
117 | - public void deactivate(ComponentContext context) { | 111 | + public void deactivate() { |
118 | - cfgService.unregisterProperties(getClass(), false); | ||
119 | - try { | ||
120 | - for (Entry<DeviceId, NetconfDevice> deviceEntry : netconfDeviceMap | ||
121 | - .entrySet()) { | ||
122 | - deviceBuilder.submit(new DeviceCreator(deviceEntry.getValue(), | ||
123 | - false)); | ||
124 | - } | ||
125 | - deviceBuilder.awaitTermination(1000, TimeUnit.MILLISECONDS); | ||
126 | - } catch (InterruptedException e) { | ||
127 | - log.error("Device builder did not terminate"); | ||
128 | - } | ||
129 | - deviceBuilder.shutdownNow(); | ||
130 | - netconfDeviceMap.clear(); | ||
131 | providerRegistry.unregister(this); | 112 | providerRegistry.unregister(this); |
132 | providerService = null; | 113 | providerService = null; |
114 | + cfgService.unregisterConfigFactory(factory); | ||
133 | log.info("Stopped"); | 115 | log.info("Stopped"); |
134 | } | 116 | } |
135 | 117 | ||
136 | - @Modified | 118 | + public NetconfDeviceProvider() { |
137 | - public void modified(ComponentContext context) { | 119 | + super(new ProviderId("netconf", "org.onosproject.netconf.provider.device")); |
138 | - if (context == null) { | ||
139 | - log.info("No configuration file"); | ||
140 | - return; | ||
141 | - } | ||
142 | - Dictionary<?, ?> properties = context.getProperties(); | ||
143 | - String deviceCfgValue = get(properties, "devConfigs"); | ||
144 | - log.info("Settings: devConfigs={}", deviceCfgValue); | ||
145 | - if (!isNullOrEmpty(deviceCfgValue)) { | ||
146 | - addOrRemoveDevicesConfig(deviceCfgValue); | ||
147 | - } | ||
148 | - } | ||
149 | - | ||
150 | - private void addOrRemoveDevicesConfig(String deviceConfig) { | ||
151 | - for (String deviceEntry : deviceConfig.split(",")) { | ||
152 | - NetconfDevice device = processDeviceEntry(deviceEntry); | ||
153 | - if (device != null) { | ||
154 | - log.info("Device Detail: username: {}, host={}, port={}, state={}", | ||
155 | - device.getUsername(), device.getSshHost(), | ||
156 | - device.getSshPort(), device.getDeviceState().name()); | ||
157 | - if (device.isActive()) { | ||
158 | - deviceBuilder.submit(new DeviceCreator(device, true)); | ||
159 | - } else { | ||
160 | - deviceBuilder.submit(new DeviceCreator(device, false)); | ||
161 | - } | ||
162 | - } | ||
163 | - } | ||
164 | - } | ||
165 | - | ||
166 | - private NetconfDevice processDeviceEntry(String deviceEntry) { | ||
167 | - if (deviceEntry == null) { | ||
168 | - log.info("No content for Device Entry, so cannot proceed further."); | ||
169 | - return null; | ||
170 | - } | ||
171 | - log.info("Trying to convert Device Entry String: " + deviceEntry | ||
172 | - + " to a Netconf Device Object"); | ||
173 | - NetconfDevice device = null; | ||
174 | - try { | ||
175 | - String userInfo = deviceEntry.substring(0, deviceEntry | ||
176 | - .lastIndexOf('@')); | ||
177 | - String hostInfo = deviceEntry.substring(deviceEntry | ||
178 | - .lastIndexOf('@') + 1); | ||
179 | - String[] infoSplit = userInfo.split(":"); | ||
180 | - String username = infoSplit[0]; | ||
181 | - String password = infoSplit[1]; | ||
182 | - infoSplit = hostInfo.split(":"); | ||
183 | - String hostIp = infoSplit[0]; | ||
184 | - Integer hostPort; | ||
185 | - try { | ||
186 | - hostPort = Integer.parseInt(infoSplit[1]); | ||
187 | - } catch (NumberFormatException nfe) { | ||
188 | - log.error("Bad Configuration Data: Failed to parse host port number string: " | ||
189 | - + infoSplit[1]); | ||
190 | - throw nfe; | ||
191 | - } | ||
192 | - String deviceState = infoSplit[2]; | ||
193 | - if (isNullOrEmpty(username) || isNullOrEmpty(password) | ||
194 | - || isNullOrEmpty(hostIp) || hostPort == 0) { | ||
195 | - log.warn("Bad Configuration Data: both user and device information parts of Configuration " | ||
196 | - + deviceEntry + " should be non-nullable"); | ||
197 | - } else { | ||
198 | - device = new NetconfDevice(hostIp, hostPort, username, password); | ||
199 | - if (!isNullOrEmpty(deviceState)) { | ||
200 | - if (deviceState.toUpperCase().equals(DeviceState.ACTIVE | ||
201 | - .name())) { | ||
202 | - device.setDeviceState(DeviceState.ACTIVE); | ||
203 | - } else if (deviceState.toUpperCase() | ||
204 | - .equals(DeviceState.INACTIVE.name())) { | ||
205 | - device.setDeviceState(DeviceState.INACTIVE); | ||
206 | - } else { | ||
207 | - log.warn("Device State Information can not be empty, so marking the state as INVALID"); | ||
208 | - device.setDeviceState(DeviceState.INVALID); | ||
209 | - } | ||
210 | - } else { | ||
211 | - log.warn("The device entry do not specify state information, so marking the state as INVALID"); | ||
212 | - device.setDeviceState(DeviceState.INVALID); | ||
213 | - } | ||
214 | - } | ||
215 | - } catch (ArrayIndexOutOfBoundsException aie) { | ||
216 | - log.error("Error while reading config infromation from the config file: " | ||
217 | - + "The user, host and device state infomation should be " | ||
218 | - + "in the order 'userInfo@hostInfo:deviceState'" | ||
219 | - + deviceEntry, aie); | ||
220 | - } catch (Exception e) { | ||
221 | - log.error("Error while parsing config information for the device entry: " | ||
222 | - + deviceEntry, e); | ||
223 | - } | ||
224 | - return device; | ||
225 | } | 120 | } |
226 | 121 | ||
227 | @Override | 122 | @Override |
228 | public void triggerProbe(DeviceId deviceId) { | 123 | public void triggerProbe(DeviceId deviceId) { |
229 | - // TODO Auto-generated method stub | 124 | + // TODO: This will be implemented later. |
125 | + log.info("Triggering probe on device {}", deviceId); | ||
230 | } | 126 | } |
231 | 127 | ||
232 | @Override | 128 | @Override |
233 | public void roleChanged(DeviceId deviceId, MastershipRole newRole) { | 129 | public void roleChanged(DeviceId deviceId, MastershipRole newRole) { |
234 | - | 130 | + // TODO: This will be implemented later. |
235 | } | 131 | } |
236 | 132 | ||
237 | @Override | 133 | @Override |
238 | public boolean isReachable(DeviceId deviceId) { | 134 | public boolean isReachable(DeviceId deviceId) { |
239 | - NetconfDevice netconfDevice = netconfDeviceMap.get(deviceId); | 135 | + Map<DeviceId, NetconfDevice> devices = controller.getDevicesMap(); |
136 | + | ||
137 | + NetconfDevice netconfDevice = null; | ||
138 | + for (DeviceId key : devices.keySet()) { | ||
139 | + if (key.equals(deviceId)) { | ||
140 | + netconfDevice = controller.getDevicesMap().get(key); | ||
141 | + } | ||
142 | + } | ||
240 | if (netconfDevice == null) { | 143 | if (netconfDevice == null) { |
241 | log.warn("BAD REQUEST: the requested device id: " | 144 | log.warn("BAD REQUEST: the requested device id: " |
242 | + deviceId.toString() | 145 | + deviceId.toString() |
243 | + " is not associated to any NETCONF Device"); | 146 | + " is not associated to any NETCONF Device"); |
244 | return false; | 147 | return false; |
245 | } | 148 | } |
246 | - return netconfDevice.isReachable(); | 149 | + return netconfDevice.isActive(); |
247 | } | 150 | } |
248 | 151 | ||
249 | - /** | 152 | + private class InnerNetconfDeviceListener implements NetconfDeviceListener { |
250 | - * This class is intended to add or remove Configured Netconf Devices. | ||
251 | - * Functionality relies on 'createFlag' and 'NetconfDevice' content. The | ||
252 | - * functionality runs as a thread and dependening on the 'createFlag' value | ||
253 | - * it will create or remove Device entry from the core. | ||
254 | - */ | ||
255 | - private class DeviceCreator implements Runnable { | ||
256 | 153 | ||
257 | - private NetconfDevice device; | 154 | + @Override |
258 | - private boolean createFlag; | 155 | + public void deviceAdded(NetconfDeviceInfo nodeId) { |
156 | + Preconditions.checkNotNull(nodeId, ISNOTNULL); | ||
157 | + DeviceId deviceId = nodeId.getDeviceId(); | ||
158 | + //TODO filter for not netconf devices | ||
159 | + //Netconf configuration object | ||
160 | + ChassisId cid = new ChassisId(); | ||
161 | + String ipAddress = nodeId.ip().toString(); | ||
162 | + SparseAnnotations annotations = DefaultAnnotations.builder() | ||
163 | + .set("ipaddress", ipAddress).build(); | ||
164 | + DeviceDescription deviceDescription = new DefaultDeviceDescription( | ||
165 | + deviceId.uri(), | ||
166 | + Device.Type.SWITCH, | ||
167 | + UNKNOWN, UNKNOWN, | ||
168 | + UNKNOWN, UNKNOWN, | ||
169 | + cid, | ||
170 | + annotations); | ||
171 | + providerService.deviceConnected(deviceId, deviceDescription); | ||
259 | 172 | ||
260 | - public DeviceCreator(NetconfDevice device, boolean createFlag) { | ||
261 | - this.device = device; | ||
262 | - this.createFlag = createFlag; | ||
263 | } | 173 | } |
264 | 174 | ||
265 | @Override | 175 | @Override |
266 | - public void run() { | 176 | + public void deviceRemoved(NetconfDeviceInfo nodeId) { |
267 | - if (createFlag) { | 177 | + Preconditions.checkNotNull(nodeId, ISNOTNULL); |
268 | - log.info("Trying to create Device Info on ONOS core"); | 178 | + DeviceId deviceId = nodeId.getDeviceId(); |
269 | - advertiseDevices(); | 179 | + providerService.deviceDisconnected(deviceId); |
270 | - } else { | 180 | + |
271 | - log.info("Trying to remove Device Info on ONOS core"); | ||
272 | - removeDevices(); | ||
273 | } | 181 | } |
274 | } | 182 | } |
275 | 183 | ||
276 | - /** | 184 | + private void connectExistingDevices() { |
277 | - * For each Netconf Device, remove the entry from the device store. | 185 | + //TODO consolidate |
278 | - */ | 186 | + appId = coreService.registerApplication("org.onosproject.netconf"); |
279 | - private void removeDevices() { | 187 | + connectDevices(); |
280 | - if (device == null) { | ||
281 | - log.warn("The Request Netconf Device is null, cannot proceed further"); | ||
282 | - return; | ||
283 | } | 188 | } |
189 | + | ||
190 | + private void connectDevices() { | ||
191 | + NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class); | ||
192 | + if (cfg != null) { | ||
193 | + log.info("cfg {}", cfg); | ||
284 | try { | 194 | try { |
285 | - DeviceId did = getDeviceId(); | 195 | + cfg.getDevicesAddresses().stream().forEach(addr -> controller |
286 | - if (!netconfDeviceMap.containsKey(did)) { | 196 | + .connectDevice(new NetconfDeviceInfo(addr.name(), |
287 | - log.error("BAD Request: 'Currently device is not discovered, " | 197 | + addr.password(), |
288 | - + "so cannot remove/disconnect the device: " | 198 | + addr.ip(), |
289 | - + device.deviceInfo() + "'"); | 199 | + addr.port()))); |
290 | - return; | 200 | + } catch (ConfigException e) { |
201 | + log.error("Cannot read config error " + e); | ||
291 | } | 202 | } |
292 | - providerService.deviceDisconnected(did); | ||
293 | - device.disconnect(); | ||
294 | - netconfDeviceMap.remove(did); | ||
295 | - delay(EVENTINTERVAL); | ||
296 | - } catch (URISyntaxException uriSyntaxExcpetion) { | ||
297 | - log.error("Syntax Error while creating URI for the device: " | ||
298 | - + device.deviceInfo() | ||
299 | - + " couldn't remove the device from the store", | ||
300 | - uriSyntaxExcpetion); | ||
301 | } | 203 | } |
302 | } | 204 | } |
303 | 205 | ||
304 | - /** | 206 | + private class InternalNetworkConfigListener implements NetworkConfigListener { |
305 | - * Initialize Netconf Device object, and notify core saying device | 207 | + |
306 | - * connected. | 208 | + |
307 | - */ | 209 | + @Override |
308 | - private void advertiseDevices() { | 210 | + public void event(NetworkConfigEvent event) { |
309 | - try { | 211 | + connectDevices(); |
310 | - if (device == null) { | ||
311 | - log.warn("The Request Netconf Device is null, cannot proceed further"); | ||
312 | - return; | ||
313 | - } | ||
314 | - device.init(); | ||
315 | - DeviceId did = getDeviceId(); | ||
316 | - ChassisId cid = new ChassisId(); | ||
317 | - DeviceDescription desc = new DefaultDeviceDescription( | ||
318 | - did.uri(), | ||
319 | - Device.Type.OTHER, | ||
320 | - "", "", | ||
321 | - "", "", | ||
322 | - cid); | ||
323 | - log.info("Persisting Device" + did.uri().toString()); | ||
324 | - | ||
325 | - netconfDeviceMap.put(did, device); | ||
326 | - providerService.deviceConnected(did, desc); | ||
327 | - log.info("Done with Device Info Creation on ONOS core. Device Info: " | ||
328 | - + device.deviceInfo() + " " + did.uri().toString()); | ||
329 | - delay(EVENTINTERVAL); | ||
330 | - } catch (URISyntaxException e) { | ||
331 | - log.error("Syntax Error while creating URI for the device: " | ||
332 | - + device.deviceInfo() | ||
333 | - + " couldn't persist the device onto the store", e); | ||
334 | - } catch (SocketTimeoutException e) { | ||
335 | - log.error("Error while setting connection for the device: " | ||
336 | - + device.deviceInfo(), e); | ||
337 | - } catch (IOException e) { | ||
338 | - log.error("Error while setting connection for the device: " | ||
339 | - + device.deviceInfo(), e); | ||
340 | - } catch (Exception e) { | ||
341 | - log.error("Error while initializing session for the device: " | ||
342 | - + (device != null ? device.deviceInfo() : null), e); | ||
343 | - } | ||
344 | } | 212 | } |
345 | 213 | ||
346 | - /** | 214 | + @Override |
347 | - * This will build a device id for the device. | 215 | + public boolean isRelevant(NetworkConfigEvent event) { |
348 | - */ | 216 | + //TODO refactor |
349 | - private DeviceId getDeviceId() throws URISyntaxException { | 217 | + return event.configClass().equals(NetconfProviderConfig.class) && |
350 | - String additionalSSP = new StringBuilder(device.getUsername()) | 218 | + (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED || |
351 | - .append("@").append(device.getSshHost()).append(":") | 219 | + event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED); |
352 | - .append(device.getSshPort()).toString(); | ||
353 | - DeviceId did = DeviceId.deviceId(new URI(SCHEME, additionalSSP, | ||
354 | - null)); | ||
355 | - return did; | ||
356 | } | 220 | } |
357 | } | 221 | } |
358 | } | 222 | } | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.provider.netconf.device.impl; | ||
18 | + | ||
19 | +import com.fasterxml.jackson.databind.JsonNode; | ||
20 | +import com.google.common.annotations.Beta; | ||
21 | +import com.google.common.collect.Sets; | ||
22 | +import org.onlab.packet.IpAddress; | ||
23 | +import org.onosproject.core.ApplicationId; | ||
24 | +import org.onosproject.incubator.net.config.basics.ConfigException; | ||
25 | +import org.onosproject.net.config.Config; | ||
26 | + | ||
27 | +import java.util.Set; | ||
28 | + | ||
29 | +/** | ||
30 | + * Configuration for Netconf provider. | ||
31 | + */ | ||
32 | +@Beta | ||
33 | +public class NetconfProviderConfig extends Config<ApplicationId> { | ||
34 | + | ||
35 | + public static final String CONFIG_VALUE_ERROR = "Error parsing config value"; | ||
36 | + private static final String IP = "ip"; | ||
37 | + private static final int DEFAULT_TCP_PORT = 830; | ||
38 | + private static final String PORT = "port"; | ||
39 | + private static final String NAME = "name"; | ||
40 | + private static final String PASSWORD = "password"; | ||
41 | + | ||
42 | + public Set<NetconfDeviceAddress> getDevicesAddresses() throws ConfigException { | ||
43 | + Set<NetconfDeviceAddress> devicesAddresses = Sets.newHashSet(); | ||
44 | + | ||
45 | + try { | ||
46 | + for (JsonNode node : array) { | ||
47 | + String ip = node.path(IP).asText(); | ||
48 | + IpAddress ipAddr = ip.isEmpty() ? null : IpAddress.valueOf(ip); | ||
49 | + int port = node.path(PORT).asInt(DEFAULT_TCP_PORT); | ||
50 | + String name = node.path(NAME).asText(); | ||
51 | + String password = node.path(PASSWORD).asText(); | ||
52 | + devicesAddresses.add(new NetconfDeviceAddress(ipAddr, port, name, password)); | ||
53 | + | ||
54 | + } | ||
55 | + } catch (IllegalArgumentException e) { | ||
56 | + throw new ConfigException(CONFIG_VALUE_ERROR, e); | ||
57 | + } | ||
58 | + | ||
59 | + return devicesAddresses; | ||
60 | + } | ||
61 | + | ||
62 | + public class NetconfDeviceAddress { | ||
63 | + private final IpAddress ip; | ||
64 | + private final int port; | ||
65 | + private final String name; | ||
66 | + private final String password; | ||
67 | + | ||
68 | + public NetconfDeviceAddress(IpAddress ip, int port, String name, String password) { | ||
69 | + this.ip = ip; | ||
70 | + this.port = port; | ||
71 | + this.name = name; | ||
72 | + this.password = password; | ||
73 | + } | ||
74 | + | ||
75 | + public IpAddress ip() { | ||
76 | + return ip; | ||
77 | + } | ||
78 | + | ||
79 | + public int port() { | ||
80 | + return port; | ||
81 | + } | ||
82 | + | ||
83 | + public String name() { | ||
84 | + return name; | ||
85 | + } | ||
86 | + | ||
87 | + public String password() { | ||
88 | + return password; | ||
89 | + } | ||
90 | + } | ||
91 | + | ||
92 | + | ||
93 | +} |
1 | -/* | ||
2 | - * Copyright 2015 Open Networking Laboratory | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.onosproject.provider.netconf.device.impl; | ||
17 | - | ||
18 | -import static org.easymock.EasyMock.expect; | ||
19 | -import static org.easymock.EasyMock.replay; | ||
20 | -import static org.junit.Assert.assertFalse; | ||
21 | -import static org.onlab.util.Tools.delay; | ||
22 | -import static org.onosproject.provider.netconf.device.impl.NetconfDeviceProviderTestConstant.*; | ||
23 | -import static org.slf4j.LoggerFactory.getLogger; | ||
24 | - | ||
25 | -import java.io.IOException; | ||
26 | -import java.net.URI; | ||
27 | -import java.net.URISyntaxException; | ||
28 | -import java.util.Collection; | ||
29 | -import java.util.Dictionary; | ||
30 | -import java.util.List; | ||
31 | -import java.util.Map; | ||
32 | -import java.util.Set; | ||
33 | -import java.util.concurrent.ConcurrentHashMap; | ||
34 | - | ||
35 | -import org.easymock.EasyMock; | ||
36 | -import org.junit.After; | ||
37 | -import org.junit.Before; | ||
38 | -import org.junit.Ignore; | ||
39 | -import org.junit.Test; | ||
40 | -import org.onlab.packet.ChassisId; | ||
41 | -import org.onosproject.cfg.ComponentConfigService; | ||
42 | -import org.onosproject.net.Device; | ||
43 | -import org.onosproject.net.DeviceId; | ||
44 | -import org.onosproject.net.MastershipRole; | ||
45 | -import org.onosproject.net.device.DefaultDeviceDescription; | ||
46 | -import org.onosproject.net.device.DeviceDescription; | ||
47 | -import org.onosproject.net.device.DeviceProvider; | ||
48 | -import org.onosproject.net.device.DeviceProviderRegistry; | ||
49 | -import org.onosproject.net.device.DeviceProviderService; | ||
50 | -import org.onosproject.net.device.PortDescription; | ||
51 | -import org.onosproject.net.device.PortStatistics; | ||
52 | -import org.onosproject.net.provider.ProviderId; | ||
53 | -import org.osgi.service.component.ComponentContext; | ||
54 | -import org.slf4j.Logger; | ||
55 | - | ||
56 | -import com.tailf.jnc.JNCException; | ||
57 | - | ||
58 | -/** | ||
59 | - * Test Case to Validate Netconf Device Provider. | ||
60 | - */ | ||
61 | -public class NetconfDeviceProviderTest { | ||
62 | - TestDeviceCreator create; | ||
63 | - | ||
64 | - private final Logger log = getLogger(NetconfDeviceProviderTest.class); | ||
65 | - | ||
66 | - private Map<DeviceId, NetconfDevice> netconfDeviceMap = new ConcurrentHashMap<DeviceId, NetconfDevice>(); | ||
67 | - | ||
68 | - private DeviceProviderService providerService; | ||
69 | - | ||
70 | - private static final DeviceId DID1 = DeviceId.deviceId(DEVICE_ID); | ||
71 | - | ||
72 | - private final NetconfDeviceProvider provider = new NetconfDeviceProvider(); | ||
73 | - private final TestDeviceRegistry registry = new TestDeviceRegistry(); | ||
74 | - | ||
75 | - private ComponentConfigService mockCfgService; | ||
76 | - | ||
77 | - @Before | ||
78 | - public void setUp() { | ||
79 | - mockCfgService = EasyMock.createMock(ComponentConfigService.class); | ||
80 | - provider.cfgService = mockCfgService; | ||
81 | - provider.providerRegistry = registry; | ||
82 | - } | ||
83 | - | ||
84 | - @SuppressWarnings("unchecked") | ||
85 | - private Dictionary<String, String> getDictionaryMockWithoutValues(ComponentContext componentContext) { | ||
86 | - Dictionary<String, String> dictionary = EasyMock | ||
87 | - .createMock(Dictionary.class); | ||
88 | - expect(dictionary.get(DEV_CONFIG)).andReturn(NULL); | ||
89 | - replay(dictionary); | ||
90 | - expect(componentContext.getProperties()).andReturn(dictionary); | ||
91 | - return dictionary; | ||
92 | - } | ||
93 | - | ||
94 | - @SuppressWarnings("unchecked") | ||
95 | - private Dictionary<String, String> getDictionaryMockWithDeviceEntryNull(ComponentContext componentContext) { | ||
96 | - Dictionary<String, String> dictionary = EasyMock | ||
97 | - .createMock(Dictionary.class); | ||
98 | - expect(dictionary.get(DEV_CONFIG)).andReturn(NULL_NULL); | ||
99 | - replay(dictionary); | ||
100 | - expect(componentContext.getProperties()).andReturn(dictionary); | ||
101 | - return dictionary; | ||
102 | - } | ||
103 | - | ||
104 | - @SuppressWarnings("unchecked") | ||
105 | - private Dictionary<String, String> getDictionaryMockDeviceEntryNumberFomatEx(ComponentContext componentContext) { | ||
106 | - Dictionary<String, String> dictionary = EasyMock | ||
107 | - .createMock(Dictionary.class); | ||
108 | - expect(dictionary.get(DEV_CONFIG)) | ||
109 | - .andReturn(CONFIG_WITH_INVALID_ENTRY_NUMBER) | ||
110 | - .andThrow(new NumberFormatException()); | ||
111 | - replay(dictionary); | ||
112 | - expect(componentContext.getProperties()).andReturn(dictionary); | ||
113 | - return dictionary; | ||
114 | - } | ||
115 | - | ||
116 | - @SuppressWarnings("unchecked") | ||
117 | - private Dictionary<String, String> getDictionaryMockWithoutUsernameAndPassword(ComponentContext componentContext) { | ||
118 | - Dictionary<String, String> dictionary = EasyMock | ||
119 | - .createMock(Dictionary.class); | ||
120 | - expect(dictionary.get(DEV_CONFIG)).andReturn(CONFIG_WITH_NULL_ENTRY); | ||
121 | - replay(dictionary); | ||
122 | - expect(componentContext.getProperties()).andReturn(dictionary); | ||
123 | - return dictionary; | ||
124 | - } | ||
125 | - | ||
126 | - @SuppressWarnings("unchecked") | ||
127 | - private Dictionary<String, String> getDictionaryMockWithDifferentDeviceState(ComponentContext componentContext) { | ||
128 | - Dictionary<String, String> dictionary = EasyMock | ||
129 | - .createMock(Dictionary.class); | ||
130 | - expect(dictionary.get(DEV_CONFIG)) | ||
131 | - .andReturn(CONFIG_WITH_DIFFERENT_DEVICE_STATE); | ||
132 | - replay(dictionary); | ||
133 | - expect(componentContext.getProperties()).andReturn(dictionary); | ||
134 | - return dictionary; | ||
135 | - } | ||
136 | - | ||
137 | - @SuppressWarnings("unchecked") | ||
138 | - private Dictionary<String, String> getDictionaryMockDeviceWithArrayOutOFBoundEx(ComponentContext componentContext) { | ||
139 | - Dictionary<String, String> dictionary = EasyMock | ||
140 | - .createMock(Dictionary.class); | ||
141 | - expect(dictionary.get(DEV_CONFIG)) | ||
142 | - .andReturn(CONFIG_WITH_ARRAY_OUT_OF_BOUNDEX) | ||
143 | - .andThrow(new ArrayIndexOutOfBoundsException()); | ||
144 | - replay(dictionary); | ||
145 | - expect(componentContext.getProperties()).andReturn(dictionary); | ||
146 | - return dictionary; | ||
147 | - } | ||
148 | - | ||
149 | - @SuppressWarnings("unchecked") | ||
150 | - private Dictionary<String, String> getDictionaryMockDeviceEntryForDeactivate(ComponentContext componentContext) { | ||
151 | - Dictionary<String, String> dictionary = EasyMock | ||
152 | - .createMock(Dictionary.class); | ||
153 | - expect(dictionary.get(DEV_CONFIG)) | ||
154 | - .andReturn(CONFIG_ENTRY_FOR_DEACTIVATE) | ||
155 | - .andThrow(new ArrayIndexOutOfBoundsException()); | ||
156 | - replay(dictionary); | ||
157 | - expect(componentContext.getProperties()).andReturn(dictionary); | ||
158 | - return dictionary; | ||
159 | - } | ||
160 | - | ||
161 | - @Ignore | ||
162 | - @Test(expected = IOException.class) | ||
163 | - public void testSSHAuthentication() throws IOException, JNCException { | ||
164 | - TestDeviceCreator objForTestDev = new TestDeviceCreator( | ||
165 | - new NetconfDevice( | ||
166 | - DEVICE_IP, | ||
167 | - DEVICE_PORT, | ||
168 | - DEVICE_USERNAME, | ||
169 | - DEVICE_PASSWORD), | ||
170 | - true); | ||
171 | - objForTestDev.run(); | ||
172 | - } | ||
173 | - | ||
174 | - @After | ||
175 | - public void tearDown() { | ||
176 | - provider.providerRegistry = null; | ||
177 | - provider.cfgService = null; | ||
178 | - } | ||
179 | - | ||
180 | - // To check if deviceCfgValue is empty or null | ||
181 | - @Test | ||
182 | - public void testActiveWithcomponentContextIsNull() { | ||
183 | - | ||
184 | - ComponentContext componentContext = EasyMock | ||
185 | - .createMock(ComponentContext.class); | ||
186 | - getDictionaryMockWithoutValues(componentContext); | ||
187 | - replay(componentContext); | ||
188 | - provider.activate(componentContext); | ||
189 | - } | ||
190 | - | ||
191 | - // To check deviceEntry and device is null | ||
192 | - @Test | ||
193 | - public void testActiveWithDeviceEntryIsNull() { | ||
194 | - | ||
195 | - ComponentContext componentContext = EasyMock | ||
196 | - .createMock(ComponentContext.class); | ||
197 | - getDictionaryMockWithDeviceEntryNull(componentContext); | ||
198 | - replay(componentContext); | ||
199 | - provider.activate(componentContext); | ||
200 | - } | ||
201 | - | ||
202 | - @Test | ||
203 | - public void testActiveWithDeviceEntryWithoutUsernameAndPassword() { | ||
204 | - | ||
205 | - ComponentContext componentContext = EasyMock | ||
206 | - .createMock(ComponentContext.class); | ||
207 | - getDictionaryMockWithoutUsernameAndPassword(componentContext); | ||
208 | - replay(componentContext); | ||
209 | - provider.activate(componentContext); | ||
210 | - } | ||
211 | - | ||
212 | - @Test | ||
213 | - public void testActiveWithDeviceEntryWithNumberFomatEx() { | ||
214 | - | ||
215 | - ComponentContext componentContext = EasyMock | ||
216 | - .createMock(ComponentContext.class); | ||
217 | - getDictionaryMockDeviceEntryNumberFomatEx(componentContext); | ||
218 | - replay(componentContext); | ||
219 | - provider.activate(componentContext); | ||
220 | - } | ||
221 | - | ||
222 | - @Test | ||
223 | - public void testActiveWithDeviceEntryWithDifferentDeviceState() { | ||
224 | - | ||
225 | - ComponentContext componentContext = EasyMock | ||
226 | - .createMock(ComponentContext.class); | ||
227 | - getDictionaryMockWithDifferentDeviceState(componentContext); | ||
228 | - replay(componentContext); | ||
229 | - provider.activate(componentContext); | ||
230 | - } | ||
231 | - | ||
232 | - @Test | ||
233 | - public void testActiveWithDeviceEntryWithArrayOutOFBoundEx() { | ||
234 | - | ||
235 | - ComponentContext componentContext = EasyMock | ||
236 | - .createMock(ComponentContext.class); | ||
237 | - getDictionaryMockDeviceWithArrayOutOFBoundEx(componentContext); | ||
238 | - replay(componentContext); | ||
239 | - provider.activate(componentContext); | ||
240 | - } | ||
241 | - | ||
242 | - @Test | ||
243 | - public void isReachableWithInvalidDeviceId() { | ||
244 | - assertFalse("Initially the Device ID Should not be reachable", | ||
245 | - provider.isReachable(DID1)); | ||
246 | - NetconfDevice device = new NetconfDevice(NULL, ZERO, NULL, NULL); | ||
247 | - provider.netconfDeviceMap.put(DID1, device); | ||
248 | - assertFalse("Particular Device ID cannot be Reachable", | ||
249 | - provider.isReachable(DID1)); | ||
250 | - } | ||
251 | - | ||
252 | - @Test | ||
253 | - public void testDeactivate() { | ||
254 | - | ||
255 | - ComponentContext componentContext = EasyMock | ||
256 | - .createMock(ComponentContext.class); | ||
257 | - getDictionaryMockDeviceEntryForDeactivate(componentContext); | ||
258 | - replay(componentContext); | ||
259 | - testActiveWithDeviceEntryWithDifferentDeviceState(); | ||
260 | - provider.deactivate(componentContext); | ||
261 | - } | ||
262 | - | ||
263 | - private class TestDeviceCreator { | ||
264 | - | ||
265 | - private NetconfDevice device; | ||
266 | - private boolean createFlag; | ||
267 | - | ||
268 | - public TestDeviceCreator(NetconfDevice device, boolean createFlag) { | ||
269 | - this.device = device; | ||
270 | - this.createFlag = createFlag; | ||
271 | - } | ||
272 | - | ||
273 | - public void run() throws JNCException, IOException { | ||
274 | - if (createFlag) { | ||
275 | - log.info("Trying to create Device Info on ONOS core"); | ||
276 | - advertiseDevices(); | ||
277 | - } else { | ||
278 | - log.info("Trying to remove Device Info on ONOS core"); | ||
279 | - removeDevices(); | ||
280 | - } | ||
281 | - } | ||
282 | - | ||
283 | - /** | ||
284 | - * For each Netconf Device, remove the entry from the device store. | ||
285 | - */ | ||
286 | - private void removeDevices() { | ||
287 | - if (device == null) { | ||
288 | - log.warn("The Request Netconf Device is null, cannot proceed further"); | ||
289 | - return; | ||
290 | - } | ||
291 | - try { | ||
292 | - DeviceId did = getDeviceId(); | ||
293 | - if (!netconfDeviceMap.containsKey(did)) { | ||
294 | - log.error("BAD Request: 'Currently device is not discovered, " | ||
295 | - + "so cannot remove/disconnect the device: " | ||
296 | - + device.deviceInfo() + "'"); | ||
297 | - return; | ||
298 | - } | ||
299 | - providerService.deviceDisconnected(did); | ||
300 | - device.disconnect(); | ||
301 | - netconfDeviceMap.remove(did); | ||
302 | - delay(EVENTINTERVAL); | ||
303 | - } catch (URISyntaxException uriSyntaxExcpetion) { | ||
304 | - log.error("Syntax Error while creating URI for the device: " | ||
305 | - + device.deviceInfo() | ||
306 | - + " couldn't remove the device from the store", | ||
307 | - uriSyntaxExcpetion); | ||
308 | - } | ||
309 | - } | ||
310 | - | ||
311 | - /** | ||
312 | - * Initialize Netconf Device object, and notify core saying device | ||
313 | - * connected. | ||
314 | - */ | ||
315 | - private void advertiseDevices() throws JNCException, IOException { | ||
316 | - try { | ||
317 | - if (device == null) { | ||
318 | - log.warn("The Request Netconf Device is null, cannot proceed further"); | ||
319 | - return; | ||
320 | - } | ||
321 | - device.init(); | ||
322 | - DeviceId did = getDeviceId(); | ||
323 | - ChassisId cid = new ChassisId(); | ||
324 | - DeviceDescription desc = new DefaultDeviceDescription( | ||
325 | - did.uri(), | ||
326 | - Device.Type.OTHER, | ||
327 | - NULL, | ||
328 | - NULL, | ||
329 | - NULL, | ||
330 | - NULL, cid); | ||
331 | - log.info("Persisting Device" + did.uri().toString()); | ||
332 | - | ||
333 | - netconfDeviceMap.put(did, device); | ||
334 | - providerService.deviceConnected(did, desc); | ||
335 | - log.info("Done with Device Info Creation on ONOS core. Device Info: " | ||
336 | - + device.deviceInfo() + " " + did.uri().toString()); | ||
337 | - delay(EVENTINTERVAL); | ||
338 | - } catch (URISyntaxException e) { | ||
339 | - log.error("Syntax Error while creating URI for the device: " | ||
340 | - + device.deviceInfo() | ||
341 | - + " couldn't persist the device onto the store", e); | ||
342 | - } catch (JNCException e) { | ||
343 | - throw e; | ||
344 | - } catch (IOException e) { | ||
345 | - throw e; | ||
346 | - } catch (Exception e) { | ||
347 | - log.error("Error while initializing session for the device: " | ||
348 | - + device.deviceInfo(), e); | ||
349 | - } | ||
350 | - } | ||
351 | - | ||
352 | - private DeviceId getDeviceId() throws URISyntaxException { | ||
353 | - String additionalSSP = new StringBuilder(device.getUsername()) | ||
354 | - .append(AT_THE_RATE).append(device.getSshHost()) | ||
355 | - .append(COLON).append(device.getSshPort()).toString(); | ||
356 | - DeviceId did = DeviceId.deviceId(new URI(SCHEME_NETCONF, | ||
357 | - additionalSSP, null)); | ||
358 | - return did; | ||
359 | - } | ||
360 | - } | ||
361 | - | ||
362 | - private class TestDeviceRegistry implements DeviceProviderRegistry { | ||
363 | - | ||
364 | - @Override | ||
365 | - public DeviceProviderService register(DeviceProvider provider) { | ||
366 | - return new TestProviderService(); | ||
367 | - } | ||
368 | - | ||
369 | - @Override | ||
370 | - public void unregister(DeviceProvider provider) { | ||
371 | - } | ||
372 | - | ||
373 | - @Override | ||
374 | - public Set<ProviderId> getProviders() { | ||
375 | - return null; | ||
376 | - } | ||
377 | - | ||
378 | - private class TestProviderService implements DeviceProviderService { | ||
379 | - | ||
380 | - @Override | ||
381 | - public DeviceProvider provider() { | ||
382 | - return null; | ||
383 | - } | ||
384 | - | ||
385 | - @Override | ||
386 | - public void deviceConnected(DeviceId deviceId, | ||
387 | - DeviceDescription deviceDescription) { | ||
388 | - } | ||
389 | - | ||
390 | - @Override | ||
391 | - public void deviceDisconnected(DeviceId deviceId) { | ||
392 | - | ||
393 | - } | ||
394 | - | ||
395 | - @Override | ||
396 | - public void updatePorts(DeviceId deviceId, | ||
397 | - List<PortDescription> portDescriptions) { | ||
398 | - | ||
399 | - } | ||
400 | - | ||
401 | - @Override | ||
402 | - public void portStatusChanged(DeviceId deviceId, | ||
403 | - PortDescription portDescription) { | ||
404 | - | ||
405 | - } | ||
406 | - | ||
407 | - @Override | ||
408 | - public void receivedRoleReply(DeviceId deviceId, | ||
409 | - MastershipRole requested, | ||
410 | - MastershipRole response) { | ||
411 | - | ||
412 | - } | ||
413 | - | ||
414 | - @Override | ||
415 | - public void updatePortStatistics(DeviceId deviceId, | ||
416 | - Collection<PortStatistics> portStatistics) { | ||
417 | - | ||
418 | - } | ||
419 | - } | ||
420 | - } | ||
421 | -} |
1 | -/* | ||
2 | - * Copyright 2015 Open Networking Laboratory | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.onosproject.provider.netconf.device.impl; | ||
17 | - | ||
18 | -public final class NetconfDeviceProviderTestConstant { | ||
19 | - | ||
20 | - private NetconfDeviceProviderTestConstant() { | ||
21 | - } | ||
22 | - | ||
23 | - public static final int ZERO = 0; | ||
24 | - public static final int EVENTINTERVAL = 5; | ||
25 | - public static final String DEV_CONFIG = "devConfigs"; | ||
26 | - public static final String CONFIG_WITH_INVALID_ENTRY_NUMBER = "cisco:cisco" | ||
27 | - + "@10.18.11.14:cisco:active"; | ||
28 | - public static final String CONFIG_WITH_NULL_ENTRY = "null:null@null:0:active"; | ||
29 | - public static final String CONFIG_WITH_DIFFERENT_DEVICE_STATE = "cisco:cisco@10.18.11.14:22:active," | ||
30 | - + "cisco:cisco@10.18.11.18:22:inactive,cisco:cisco@10.18.11.14:22:invalid," | ||
31 | - + "cisco:cisco@10.18.11.14:22:null"; | ||
32 | - public static final String CONFIG_WITH_ARRAY_OUT_OF_BOUNDEX = "@10.18.11.14:22:active"; | ||
33 | - public static final String CONFIG_ENTRY_FOR_DEACTIVATE = "netconf:cisco" | ||
34 | - + "@10.18.11.14:22:active"; | ||
35 | - public static final String DEVICE_IP = "10.18.14.19"; | ||
36 | - public static final int DEVICE_PORT = 22; | ||
37 | - public static final String DEVICE_USERNAME = "cisco"; | ||
38 | - public static final String DEVICE_PASSWORD = "cisco"; | ||
39 | - public static final String AT_THE_RATE = "@"; | ||
40 | - public static final String COLON = ":"; | ||
41 | - public static final String NULL = ""; | ||
42 | - public static final String NULL_NULL = "null,null"; | ||
43 | - public static final String SCHEME_NETCONF = "netconf"; | ||
44 | - public static final String DEVICE_ID = "of:0000000000000001"; | ||
45 | - | ||
46 | -} |
tools/test/configs/netconf-cfg.json
0 → 100644
1 | +{ | ||
2 | + "devices":{ | ||
3 | + "netconf:mininet@10.1.9.24:1830":{ | ||
4 | + "basic":{ | ||
5 | + "driver":"ovs-netconf" | ||
6 | + } | ||
7 | + } | ||
8 | + }, | ||
9 | + "apps":{ | ||
10 | + "org.onosproject.netconf":{ | ||
11 | + "devices":[{ | ||
12 | + "name":"mininet", | ||
13 | + "password":"mininet", | ||
14 | + "ip":"10.1.9.24", | ||
15 | + "port":1830 | ||
16 | + }] | ||
17 | + } | ||
18 | + } | ||
19 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment