blob: af37f479bd4fdbcc4f04915940f56175e426e094 [file] [log] [blame]
Andrea Campanellad8d92db2016-01-14 16:24:41 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Andrea Campanellad8d92db2016-01-14 16:24:41 -08003 *
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
Andrea Campanella238d96e2016-01-20 11:52:02 -080017package org.onosproject.drivers.utilities;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080018
19import com.google.common.collect.Lists;
20import org.apache.commons.configuration.ConfigurationException;
21import org.apache.commons.configuration.HierarchicalConfiguration;
22import org.apache.commons.configuration.XMLConfiguration;
23import org.apache.commons.configuration.tree.ConfigurationNode;
24import org.onlab.packet.IpAddress;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080025import org.onosproject.net.AnnotationKeys;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080026import org.onosproject.net.ChannelSpacing;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080027import org.onosproject.net.CltSignalType;
28import org.onosproject.net.DefaultAnnotations;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080029import org.onosproject.net.GridType;
30import org.onosproject.net.OchSignal;
31import org.onosproject.net.OduSignalType;
32import org.onosproject.net.PortNumber;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080033import org.onosproject.net.behaviour.ControllerInfo;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080034import org.onosproject.net.device.PortDescription;
35import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
37
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -080038import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -070039import static org.onosproject.net.optical.device.OduCltPortHelper.oduCltPortDescription;
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -080040
Andrea Campanellad8d92db2016-01-14 16:24:41 -080041import java.io.InputStream;
42import java.io.StringWriter;
43import java.util.ArrayList;
44import java.util.List;
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080045import java.util.concurrent.atomic.AtomicInteger;
46
Andrea Campanellad8d92db2016-01-14 16:24:41 -080047
48/**
49 * Parser for Netconf XML configurations and replys.
50 */
51public final class XmlConfigParser {
52 public static final Logger log = LoggerFactory
53 .getLogger(XmlConfigParser.class);
54
55 private XmlConfigParser() {
56 //not called, preventing any allocation
57 }
58
59
60 public static HierarchicalConfiguration loadXml(InputStream xmlStream) {
61 XMLConfiguration cfg = new XMLConfiguration();
62 try {
63 cfg.load(xmlStream);
64 return cfg;
65 } catch (ConfigurationException e) {
66 throw new IllegalArgumentException("Cannot load xml from Stream", e);
67 }
68 }
69
70 public static List<ControllerInfo> parseStreamControllers(HierarchicalConfiguration cfg) {
71 List<ControllerInfo> controllers = new ArrayList<>();
72 List<HierarchicalConfiguration> fields =
73 cfg.configurationsAt("data.capable-switch." +
74 "logical-switches." +
75 "switch.controllers.controller");
76 for (HierarchicalConfiguration sub : fields) {
77 controllers.add(new ControllerInfo(
78 IpAddress.valueOf(sub.getString("ip-address")),
79 Integer.parseInt(sub.getString("port")),
80 sub.getString("protocol")));
81 }
82 return controllers;
83 }
84
Aaron Kruglikov17b4c852016-01-15 16:37:04 -080085 /**
86 * Parses a configuration and returns a set of ports for the fujitsu T100.
87 * @param cfg a hierarchical configuration
88 * @return a list of port descriptions
89 */
90 public static List<PortDescription> parseFujitsuT100Ports(HierarchicalConfiguration cfg) {
91 AtomicInteger counter = new AtomicInteger(1);
92 List<PortDescription> portDescriptions = Lists.newArrayList();
93 List<HierarchicalConfiguration> subtrees =
94 cfg.configurationsAt("data.interfaces.interface");
95 for (HierarchicalConfiguration portConfig : subtrees) {
96 if (!portConfig.getString("name").contains("LCN") &&
97 !portConfig.getString("name").contains("LMP") &&
98 portConfig.getString("type").equals("ianaift:ethernetCsmacd")) {
99 portDescriptions.add(parseT100OduPort(portConfig, counter.getAndIncrement()));
100 } else if (portConfig.getString("type").equals("ianaift:otnOtu")) {
101 portDescriptions.add(parseT100OchPort(portConfig, counter.getAndIncrement()));
102 }
103 }
104 return portDescriptions;
105 }
106
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -0800107 private static PortDescription parseT100OchPort(HierarchicalConfiguration cfg, long count) {
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800108 PortNumber portNumber = PortNumber.portNumber(count);
109 HierarchicalConfiguration otuConfig = cfg.configurationAt("otu");
110 boolean enabled = otuConfig.getString("administrative-state").equals("up");
111 OduSignalType signalType = otuConfig.getString("rate").equals("OTU4") ? OduSignalType.ODU4 : null;
112 //Unsure how to retreive, outside knowledge it is tunable.
113 boolean isTunable = true;
114 OchSignal lambda = new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, 0, 4);
115 DefaultAnnotations annotations = DefaultAnnotations.builder().
116 set(AnnotationKeys.PORT_NAME, cfg.getString("name")).
117 build();
HIGUCHI Yuta34a3f692016-01-09 21:08:57 -0800118 return ochPortDescription(portNumber, enabled, signalType, isTunable, lambda, annotations);
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800119 }
120
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700121 private static PortDescription parseT100OduPort(HierarchicalConfiguration cfg, long count) {
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800122 PortNumber portNumber = PortNumber.portNumber(count);
123 HierarchicalConfiguration ethernetConfig = cfg.configurationAt("ethernet");
124 boolean enabled = ethernetConfig.getString("administrative-state").equals("up");
125 //Rate is in kbps
126 CltSignalType signalType = ethernetConfig.getString("rate").equals("100000000") ?
127 CltSignalType.CLT_100GBE : null;
128 DefaultAnnotations annotations = DefaultAnnotations.builder().
129 set(AnnotationKeys.PORT_NAME, cfg.getString("name")).
130 build();
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700131 return oduCltPortDescription(portNumber, enabled, signalType, annotations);
Aaron Kruglikov17b4c852016-01-15 16:37:04 -0800132 }
133
134 protected static String parseSwitchId(HierarchicalConfiguration cfg) {
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800135 HierarchicalConfiguration field =
136 cfg.configurationAt("data.capable-switch." +
137 "logical-switches." +
138 "switch");
139 return field.getProperty("id").toString();
140 }
141
142 public static String parseCapableSwitchId(HierarchicalConfiguration cfg) {
143 HierarchicalConfiguration field =
144 cfg.configurationAt("data.capable-switch");
145 return field.getProperty("id").toString();
146 }
147
148 public static String createControllersConfig(HierarchicalConfiguration cfg,
149 HierarchicalConfiguration actualCfg,
150 String target, String netconfOperation,
151 String controllerOperation,
152 List<ControllerInfo> controllers) {
153 //cfg.getKeys().forEachRemaining(key -> System.out.println(key));
154 cfg.setProperty("edit-config.target", target);
155 cfg.setProperty("edit-config.default-operation", netconfOperation);
156 cfg.setProperty("edit-config.config.capable-switch.id",
157 parseCapableSwitchId(actualCfg));
158 cfg.setProperty("edit-config.config.capable-switch." +
159 "logical-switches.switch.id", parseSwitchId(actualCfg));
160 List<ConfigurationNode> newControllers = new ArrayList<>();
161 for (ControllerInfo ci : controllers) {
162 XMLConfiguration controller = new XMLConfiguration();
163 controller.setRoot(new HierarchicalConfiguration.Node("controller"));
164 String id = ci.type() + ":" + ci.ip() + ":" + ci.port();
165 controller.setProperty("id", id);
166 controller.setProperty("ip-address", ci.ip());
167 controller.setProperty("port", ci.port());
168 controller.setProperty("protocol", ci.type());
169 newControllers.add(controller.getRootNode());
170 }
171 cfg.addNodes("edit-config.config.capable-switch.logical-switches." +
172 "switch.controllers", newControllers);
173 XMLConfiguration editcfg = (XMLConfiguration) cfg;
174 StringWriter stringWriter = new StringWriter();
175 try {
176 editcfg.save(stringWriter);
177 } catch (ConfigurationException e) {
178 log.error("createControllersConfig()", e);
179 }
180 String s = stringWriter.toString()
181 .replaceAll("<controller>",
182 "<controller nc:operation=\"" + controllerOperation + "\">");
183 s = s.replace("<target>" + target + "</target>",
184 "<target><" + target + "/></target>");
185 return s;
186
187 }
188
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800189 //TODO implement mor methods for parsing configuration when you need them
Andreas Papazois1dff77c2016-02-16 16:27:33 +0200190
191 /**
192 * Parses a config reply and returns the result.
193 * @param reply a tree-like source
194 * @return the configuration result
195 */
196 public static boolean configSuccess(HierarchicalConfiguration reply) {
197 if (reply != null) {
198 if (reply.containsKey("ok")) {
199 return true;
200 }
201 }
202 return false;
203 }
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800204}