Akihiro Yamanouchi
Committed by Gerrit Code Review

[ONOS-4747] NETCONF function for FUJITSU OLT #2

 - Enhanced device-setcontrollers command to apply additional key-value pair.
    e.g. onos> device-setcontrollers netconf:10.10.1.11:830 tcp:10.10.1.11:6630,ofconfig-id=1

Change-Id: I2cb5941dbd9829ade6fa89d5546bbc6aab44f83f
...@@ -18,7 +18,10 @@ package org.onosproject.cli.net; ...@@ -18,7 +18,10 @@ package org.onosproject.cli.net;
18 18
19 import org.apache.karaf.shell.commands.Argument; 19 import org.apache.karaf.shell.commands.Argument;
20 import org.apache.karaf.shell.commands.Command; 20 import org.apache.karaf.shell.commands.Command;
21 +import org.onlab.packet.IpAddress;
21 import org.onosproject.cli.AbstractShellCommand; 22 import org.onosproject.cli.AbstractShellCommand;
23 +import org.onosproject.net.Annotations;
24 +import org.onosproject.net.DefaultAnnotations;
22 import org.onosproject.net.DeviceId; 25 import org.onosproject.net.DeviceId;
23 import org.onosproject.net.behaviour.ControllerConfig; 26 import org.onosproject.net.behaviour.ControllerConfig;
24 import org.onosproject.net.behaviour.ControllerInfo; 27 import org.onosproject.net.behaviour.ControllerInfo;
...@@ -52,7 +55,7 @@ public class DeviceSetControllersCommand extends AbstractShellCommand { ...@@ -52,7 +55,7 @@ public class DeviceSetControllersCommand extends AbstractShellCommand {
52 protected void execute() { 55 protected void execute() {
53 56
54 Arrays.asList(controllersListStrings).forEach( 57 Arrays.asList(controllersListStrings).forEach(
55 - cInfoString -> newControllers.add(new ControllerInfo(cInfoString))); 58 + cInfoString -> newControllers.add(parseCInfoString(cInfoString)));
56 DriverService service = get(DriverService.class); 59 DriverService service = get(DriverService.class);
57 deviceId = DeviceId.deviceId(uri); 60 deviceId = DeviceId.deviceId(uri);
58 DriverHandler h = service.createHandler(deviceId); 61 DriverHandler h = service.createHandler(deviceId);
...@@ -69,4 +72,31 @@ public class DeviceSetControllersCommand extends AbstractShellCommand { ...@@ -69,4 +72,31 @@ public class DeviceSetControllersCommand extends AbstractShellCommand {
69 print("size %d", config.getControllers().size()); 72 print("size %d", config.getControllers().size());
70 } 73 }
71 74
75 +
76 + private ControllerInfo parseCInfoString(String cInfoString) {
77 + Annotations annotation;
78 +
79 + String[] config = cInfoString.split(",");
80 + if (config.length == 2) {
81 + String[] pair = config[1].split("=");
82 +
83 + if (pair.length == 2) {
84 + annotation = DefaultAnnotations.builder()
85 + .set(pair[0], pair[1]).build();
86 + } else {
87 + print("Wrong format {}", config[1]);
88 + return null;
89 + }
90 +
91 + String[] data = config[0].split(":");
92 + String type = data[0];
93 + IpAddress ip = IpAddress.valueOf(data[1]);
94 + int port = Integer.parseInt(data[2]);
95 +
96 + return new ControllerInfo(ip, port, type, annotation);
97 + } else {
98 + print(config[0]);
99 + return new ControllerInfo(config[0]);
100 + }
101 + }
72 } 102 }
......
...@@ -17,17 +17,23 @@ package org.onosproject.net.behaviour; ...@@ -17,17 +17,23 @@ package org.onosproject.net.behaviour;
17 17
18 import com.google.common.base.Preconditions; 18 import com.google.common.base.Preconditions;
19 import org.onlab.packet.IpAddress; 19 import org.onlab.packet.IpAddress;
20 +import org.onosproject.net.Annotated;
21 +import org.onosproject.net.Annotations;
22 +import org.onosproject.net.DefaultAnnotations;
23 +
24 +import static com.google.common.base.Preconditions.checkNotNull;
20 25
21 import java.util.Objects; 26 import java.util.Objects;
22 27
23 /** 28 /**
24 * Represents information for a device to connect to a controller. 29 * Represents information for a device to connect to a controller.
25 */ 30 */
26 -public class ControllerInfo { 31 +public class ControllerInfo implements Annotated {
27 32
28 private IpAddress ip = IpAddress.valueOf("0.0.0.0"); 33 private IpAddress ip = IpAddress.valueOf("0.0.0.0");
29 private int port = 6653; 34 private int port = 6653;
30 private String type = "error"; 35 private String type = "error";
36 + private final Annotations annotations;
31 37
32 /** 38 /**
33 * Information for contacting the controller. 39 * Information for contacting the controller.
...@@ -37,18 +43,36 @@ public class ControllerInfo { ...@@ -37,18 +43,36 @@ public class ControllerInfo {
37 * @param type the connection type 43 * @param type the connection type
38 */ 44 */
39 public ControllerInfo(IpAddress ip, int port, String type) { 45 public ControllerInfo(IpAddress ip, int port, String type) {
40 - this.ip = ip; 46 + this(ip, port, type, DefaultAnnotations.EMPTY);
47 + }
48 +
49 + /**
50 + * Information for contacting the controller.
51 + *
52 + * @param ip the ip address
53 + * @param port the tcp port
54 + * @param type the connection type
55 + * @param annotations optional key/value annotations
56 + */
57 + public ControllerInfo(IpAddress ip, int port, String type, Annotations annotations) {
58 + this.ip = checkNotNull(ip);
41 this.port = port; 59 this.port = port;
42 - this.type = type; 60 + this.type = checkNotNull(type);
61 + this.annotations = checkNotNull(annotations);
43 } 62 }
44 63
64 + // TODO Factory method equivalent to this method
65 + // should probably live in OVSDB, NETCONF package.
45 /** 66 /**
46 * Information for contacting the controller, if some information 67 * Information for contacting the controller, if some information
47 * is not contained in the target string because it's optional 68 * is not contained in the target string because it's optional
48 * it's leaved as in the field declaration (default values). 69 * it's leaved as in the field declaration (default values).
49 * 70 *
50 * @param target column returned from ovsdb query 71 * @param target column returned from ovsdb query
72 + *
73 + * @deprecated in Hummingbird (1.7.0)
51 */ 74 */
75 + @Deprecated
52 public ControllerInfo(String target) { 76 public ControllerInfo(String target) {
53 String[] data = target.split(":"); 77 String[] data = target.split(":");
54 this.type = data[0]; 78 this.type = data[0];
...@@ -69,6 +93,7 @@ public class ControllerInfo { ...@@ -69,6 +93,7 @@ public class ControllerInfo {
69 this.port = Integer.parseInt(data[2]); 93 this.port = Integer.parseInt(data[2]);
70 } 94 }
71 } 95 }
96 + this.annotations = DefaultAnnotations.EMPTY;
72 } 97 }
73 98
74 /** 99 /**
...@@ -98,11 +123,24 @@ public class ControllerInfo { ...@@ -98,11 +123,24 @@ public class ControllerInfo {
98 return type; 123 return type;
99 } 124 }
100 125
126 + @Override
127 + public Annotations annotations() {
128 + return annotations;
129 + }
130 +
131 + // TODO Method equivalent to this method
132 + // should probably live in OVSDB, NETCONF package.
133 + // @deprecated in Hummingbird (1.7.0)
134 + @Deprecated
101 public String target() { 135 public String target() {
102 if (type.startsWith("p")) { 136 if (type.startsWith("p")) {
103 return type + ":" + port + ":" + ip; 137 return type + ":" + port + ":" + ip;
104 } else { 138 } else {
139 + if (annotations.equals(DefaultAnnotations.EMPTY)) {
105 return type + ":" + ip + ":" + port; 140 return type + ":" + ip + ":" + port;
141 + } else {
142 + return type + ":" + ip + ":" + port + ":" + annotations.toString();
143 + }
106 } 144 }
107 } 145 }
108 146
...@@ -115,12 +153,10 @@ public class ControllerInfo { ...@@ -115,12 +153,10 @@ public class ControllerInfo {
115 @Override 153 @Override
116 public boolean equals(Object toBeCompared) { 154 public boolean equals(Object toBeCompared) {
117 if (toBeCompared instanceof ControllerInfo) { 155 if (toBeCompared instanceof ControllerInfo) {
118 - ControllerInfo controllerInfo = (ControllerInfo) toBeCompared; 156 + ControllerInfo that = (ControllerInfo) toBeCompared;
119 - if (controllerInfo.type().equals(this.type) 157 + return Objects.equals(this.type, that.type) &&
120 - && controllerInfo.ip().equals(this.ip()) 158 + Objects.equals(this.ip, that.ip) &&
121 - && controllerInfo.port() == this.port) { 159 + Objects.equals(this.port, that.port);
122 - return true;
123 - }
124 } 160 }
125 return false; 161 return false;
126 } 162 }
......
...@@ -19,18 +19,26 @@ package org.onosproject.drivers.fujitsu; ...@@ -19,18 +19,26 @@ package org.onosproject.drivers.fujitsu;
19 import com.google.common.collect.ImmutableList; 19 import com.google.common.collect.ImmutableList;
20 import org.apache.commons.configuration.HierarchicalConfiguration; 20 import org.apache.commons.configuration.HierarchicalConfiguration;
21 import org.onosproject.drivers.utilities.XmlConfigParser; 21 import org.onosproject.drivers.utilities.XmlConfigParser;
22 +import org.apache.commons.configuration.ConfigurationException;
23 +import org.apache.commons.configuration.XMLConfiguration;
24 +import org.apache.commons.configuration.tree.ConfigurationNode;
22 import org.onlab.packet.IpAddress; 25 import org.onlab.packet.IpAddress;
23 import org.onosproject.mastership.MastershipService; 26 import org.onosproject.mastership.MastershipService;
27 +import org.onosproject.net.Annotations;
28 +import org.onosproject.net.DefaultAnnotations;
24 import org.onosproject.net.DeviceId; 29 import org.onosproject.net.DeviceId;
25 import org.onosproject.net.behaviour.ControllerConfig; 30 import org.onosproject.net.behaviour.ControllerConfig;
26 import org.onosproject.net.behaviour.ControllerInfo; 31 import org.onosproject.net.behaviour.ControllerInfo;
27 import org.onosproject.net.driver.AbstractHandlerBehaviour; 32 import org.onosproject.net.driver.AbstractHandlerBehaviour;
28 import org.onosproject.net.driver.DriverHandler; 33 import org.onosproject.net.driver.DriverHandler;
29 import org.onosproject.netconf.NetconfController; 34 import org.onosproject.netconf.NetconfController;
35 +import org.onosproject.netconf.NetconfDevice;
36 +import org.onosproject.netconf.NetconfException;
30 import org.slf4j.Logger; 37 import org.slf4j.Logger;
31 38
32 import java.io.ByteArrayInputStream; 39 import java.io.ByteArrayInputStream;
33 import java.io.IOException; 40 import java.io.IOException;
41 +import java.io.StringWriter;
34 import java.nio.charset.StandardCharsets; 42 import java.nio.charset.StandardCharsets;
35 import java.util.ArrayList; 43 import java.util.ArrayList;
36 import java.util.List; 44 import java.util.List;
...@@ -46,8 +54,11 @@ public class FujitsuVoltControllerConfig extends AbstractHandlerBehaviour ...@@ -46,8 +54,11 @@ public class FujitsuVoltControllerConfig extends AbstractHandlerBehaviour
46 implements ControllerConfig { 54 implements ControllerConfig {
47 55
48 private final Logger log = getLogger(FujitsuVoltControllerConfig.class); 56 private final Logger log = getLogger(FujitsuVoltControllerConfig.class);
57 + private static final String RESOURCE_XML = "voltcontrollers.xml";
49 58
50 private static final String DOT = "."; 59 private static final String DOT = ".";
60 + private static final String L_ANGLE_BR = "<";
61 + private static final String R_ANGLE_BR = "/>";
51 private static final String VOLT_NE_NAMESPACE = 62 private static final String VOLT_NE_NAMESPACE =
52 "xmlns=\"http://fujitsu.com/ns/volt/1.1\""; 63 "xmlns=\"http://fujitsu.com/ns/volt/1.1\"";
53 private static final String DATA = "data"; 64 private static final String DATA = "data";
...@@ -60,14 +71,35 @@ public class FujitsuVoltControllerConfig extends AbstractHandlerBehaviour ...@@ -60,14 +71,35 @@ public class FujitsuVoltControllerConfig extends AbstractHandlerBehaviour
60 private static final String IP_ADDRESS = "ip-address"; 71 private static final String IP_ADDRESS = "ip-address";
61 private static final String PORT = "port"; 72 private static final String PORT = "port";
62 private static final String PROTOCOL = "protocol"; 73 private static final String PROTOCOL = "protocol";
74 + private static final String CONFIG = "config";
75 + private static final String OFCONFIG_ID = "ofconfig-id";
76 + private static final String EDIT_CONFIG = "edit-config";
77 + private static final String TARGET = "target";
78 + private static final String RUNNING = "running";
79 + private static final String MERGE = "merge";
80 + private static final String DEFAULT_OPERATION = "default-operation";
63 81
64 private static final String VOLT_NE_OPEN = "<" + VOLT_NE + " "; 82 private static final String VOLT_NE_OPEN = "<" + VOLT_NE + " ";
65 private static final String VOLT_NE_CLOSE = "</" + VOLT_NE + ">"; 83 private static final String VOLT_NE_CLOSE = "</" + VOLT_NE + ">";
66 private static final String VOLT_OFCONFIG_EL = "<" + VOLT_OFCONFIG + "/>\n"; 84 private static final String VOLT_OFCONFIG_EL = "<" + VOLT_OFCONFIG + "/>\n";
85 + private static final String TARGET_OPEN = "<" + TARGET + ">";
86 + private static final String TARGET_CLOSE = "</" + TARGET + ">";
87 + private static final String END_LICENSE_HEADER = "-->";
67 88
68 private static final String VOLT_DATACONFIG = DATA + DOT + VOLT_NE + DOT + 89 private static final String VOLT_DATACONFIG = DATA + DOT + VOLT_NE + DOT +
69 VOLT_OFCONFIG + DOT + OF_CONTROLLERS + DOT + OF_CONTROLLER; 90 VOLT_OFCONFIG + DOT + OF_CONTROLLERS + DOT + OF_CONTROLLER;
70 91
92 + private static final String EDIT_CONFIG_TG = EDIT_CONFIG + DOT + TARGET;
93 + private static final String EDIT_CONFIG_DO = EDIT_CONFIG + DOT + DEFAULT_OPERATION;
94 + private static final String CONTROLLER_INFO_ID = CONTROLLER_INFO + DOT + "id";
95 + private static final String CONTROLLER_INFO_IP = CONTROLLER_INFO + DOT + IP_ADDRESS;
96 + private static final String CONTROLLER_INFO_PORT = CONTROLLER_INFO + DOT + PORT;
97 + private static final String CONTROLLER_INFO_PROTOCOL = CONTROLLER_INFO + DOT + PROTOCOL;
98 +
99 + private static final String VOLT_EDITCONFIG = EDIT_CONFIG + DOT +
100 + CONFIG + DOT + VOLT_NE + DOT + VOLT_OFCONFIG + DOT + OF_CONTROLLERS;
101 +
102 +
71 @Override 103 @Override
72 public List<ControllerInfo> getControllers() { 104 public List<ControllerInfo> getControllers() {
73 DriverHandler handler = handler(); 105 DriverHandler handler = handler();
...@@ -103,10 +135,31 @@ public class FujitsuVoltControllerConfig extends AbstractHandlerBehaviour ...@@ -103,10 +135,31 @@ public class FujitsuVoltControllerConfig extends AbstractHandlerBehaviour
103 135
104 @Override 136 @Override
105 public void setControllers(List<ControllerInfo> controllers) { 137 public void setControllers(List<ControllerInfo> controllers) {
106 - // TODO update later 138 + DriverHandler handler = handler();
107 - log.warn("Operation not supported"); 139 + NetconfController controller = handler.get(NetconfController.class);
140 + MastershipService mastershipService = handler.get(MastershipService.class);
141 + DeviceId ncdeviceId = handler.data().deviceId();
142 + checkNotNull(controller, "Netconf controller is null");
143 + if (mastershipService.isLocalMaster(ncdeviceId)) {
144 + try {
145 + NetconfDevice device = controller.getNetconfDevice(ncdeviceId);
146 + String config = createVoltControllersConfig(
147 + XmlConfigParser.loadXml(getClass().
148 + getResourceAsStream(RESOURCE_XML)),
149 + RUNNING, MERGE, controllers);
150 + device.getSession().editConfig(config.substring(
151 + config.indexOf(END_LICENSE_HEADER) + END_LICENSE_HEADER.length()));
152 + } catch (NetconfException e) {
153 + log.error("Cannot communicate to device {} , exception ", ncdeviceId, e);
154 + }
155 + } else {
156 + log.warn("I'm not master for {} please use master, {} to execute command",
157 + ncdeviceId,
158 + mastershipService.getMasterFor(ncdeviceId));
159 + }
108 } 160 }
109 161
162 +
110 /** 163 /**
111 * Parses XML string to get controller information. 164 * Parses XML string to get controller information.
112 * 165 *
...@@ -123,17 +176,67 @@ public class FujitsuVoltControllerConfig extends AbstractHandlerBehaviour ...@@ -123,17 +176,67 @@ public class FujitsuVoltControllerConfig extends AbstractHandlerBehaviour
123 sub.configurationsAt(CONTROLLER_INFO); 176 sub.configurationsAt(CONTROLLER_INFO);
124 177
125 for (HierarchicalConfiguration child : childFields) { 178 for (HierarchicalConfiguration child : childFields) {
179 + Annotations annotations = DefaultAnnotations.builder()
180 + .set(OFCONFIG_ID, sub.getString(OFCONFIG_ID)).build();
126 ControllerInfo controller = new ControllerInfo( 181 ControllerInfo controller = new ControllerInfo(
127 IpAddress.valueOf(child.getString(IP_ADDRESS)), 182 IpAddress.valueOf(child.getString(IP_ADDRESS)),
128 Integer.parseInt(child.getString(PORT)), 183 Integer.parseInt(child.getString(PORT)),
129 - child.getString(PROTOCOL)); 184 + child.getString(PROTOCOL), annotations);
130 185
131 - log.debug("VOLT: OFCONTROLLER: PROTOCOL={}, IP={}, PORT={} ", 186 + log.debug("VOLT: OFCONTROLLER: PROTOCOL={}, IP={}, PORT={}, ID={} ",
132 - controller.type(), controller.ip(), controller.port()); 187 + controller.type(), controller.ip(),
188 + controller.port(), controller.annotations().value(OFCONFIG_ID));
133 controllers.add(controller); 189 controllers.add(controller);
134 } 190 }
135 } 191 }
136 return controllers; 192 return controllers;
137 } 193 }
138 194
195 + /**
196 + * Forms XML string to change controller information.
197 + *
198 + * @param cfg a hierarchical configuration
199 + * @param target the type of configuration
200 + * @param netconfOperation operation type
201 + * @param controllers list of controllers
202 + * @return XML string
203 + */
204 + public static String createVoltControllersConfig(HierarchicalConfiguration cfg,
205 + String target, String netconfOperation,
206 + List<ControllerInfo> controllers) {
207 + XMLConfiguration editcfg = null;
208 +
209 + cfg.setProperty(EDIT_CONFIG_TG, target);
210 + cfg.setProperty(EDIT_CONFIG_DO, netconfOperation);
211 +
212 + List<ConfigurationNode> newControllers = new ArrayList<>();
213 + for (ControllerInfo ci : controllers) {
214 + XMLConfiguration controller = new XMLConfiguration();
215 + controller.setRoot(new HierarchicalConfiguration.Node(OF_CONTROLLER));
216 + controller.setProperty(OFCONFIG_ID, ci.annotations().value(OFCONFIG_ID));
217 + controller.setProperty(CONTROLLER_INFO_ID, ci.annotations().value(OFCONFIG_ID));
218 + controller.setProperty(CONTROLLER_INFO_IP, ci.ip());
219 + controller.setProperty(CONTROLLER_INFO_PORT, ci.port());
220 + controller.setProperty(CONTROLLER_INFO_PROTOCOL, ci.type());
221 + newControllers.add(controller.getRootNode());
222 + }
223 + cfg.addNodes(VOLT_EDITCONFIG, newControllers);
224 +
225 + try {
226 + editcfg = (XMLConfiguration) cfg;
227 + } catch (ClassCastException e) {
228 + e.printStackTrace();
229 + }
230 + StringWriter stringWriter = new StringWriter();
231 + try {
232 + editcfg.save(stringWriter);
233 + } catch (ConfigurationException e) {
234 + e.printStackTrace();
235 + }
236 + String s = stringWriter.toString();
237 + s = s.replace(TARGET_OPEN + target + TARGET_CLOSE,
238 + TARGET_OPEN + L_ANGLE_BR + target + R_ANGLE_BR + TARGET_CLOSE);
239 + return s;
240 + }
241 +
139 } 242 }
......
1 +<!--
2 + ~ Copyright 2016-present 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 + <volt-ne xmlns="http://fujitsu.com/ns/volt/1.1">
25 + <volt-ofconfig>
26 + <of-controllers>
27 + </of-controllers>
28 + </volt-ofconfig>
29 + </volt-ne>
30 + </config>
31 + </edit-config>
32 +</rpc>