Thomas Vachuska | 781d18b | 2014-10-27 10:31:25 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one |
| 3 | * or more contributor license agreements. See the NOTICE file |
| 4 | * distributed with this work for additional information |
| 5 | * regarding copyright ownership. The ASF licenses this file |
| 6 | * to you under the Apache License, Version 2.0 (the |
| 7 | * "License"); you may not use this file except in compliance |
| 8 | * with the License. You may obtain a copy of the License at |
| 9 | * |
| 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | * |
| 12 | * Unless required by applicable law or agreed to in writing, |
| 13 | * software distributed under the License is distributed on an |
| 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | * KIND, either express or implied. See the License for the |
| 16 | * specific language governing permissions and limitations |
| 17 | * under the License. |
| 18 | */ |
weibit | 38c42ed | 2014-10-09 19:03:54 -0700 | [diff] [blame] | 19 | package org.onlab.onos.optical.cfg; |
| 20 | |
| 21 | import static org.onlab.onos.net.DeviceId.deviceId; |
| 22 | |
| 23 | import java.io.File; |
| 24 | import java.io.IOException; |
| 25 | import java.util.ArrayList; |
| 26 | import java.util.Iterator; |
| 27 | import java.util.List; |
| 28 | import java.util.Map; |
| 29 | import java.util.Set; |
| 30 | |
| 31 | import org.apache.felix.scr.annotations.Activate; |
| 32 | import org.apache.felix.scr.annotations.Component; |
| 33 | import org.apache.felix.scr.annotations.Deactivate; |
| 34 | import org.apache.felix.scr.annotations.Reference; |
| 35 | import org.apache.felix.scr.annotations.ReferenceCardinality; |
| 36 | import org.codehaus.jackson.JsonNode; |
| 37 | import org.codehaus.jackson.JsonParseException; |
| 38 | import org.codehaus.jackson.annotate.JsonIgnoreProperties; |
| 39 | import org.codehaus.jackson.map.JsonMappingException; |
| 40 | import org.codehaus.jackson.map.ObjectMapper; |
| 41 | import org.onlab.onos.net.ConnectPoint; |
| 42 | import org.onlab.onos.net.DefaultAnnotations; |
| 43 | import org.onlab.onos.net.Device; |
| 44 | import org.onlab.onos.net.DeviceId; |
| 45 | import org.onlab.onos.net.Link; |
| 46 | import org.onlab.onos.net.MastershipRole; |
| 47 | import org.onlab.onos.net.PortNumber; |
| 48 | import org.onlab.onos.net.device.DefaultDeviceDescription; |
| 49 | import org.onlab.onos.net.device.DeviceDescription; |
| 50 | import org.onlab.onos.net.device.DeviceProvider; |
| 51 | import org.onlab.onos.net.device.DeviceProviderRegistry; |
| 52 | import org.onlab.onos.net.device.DeviceProviderService; |
| 53 | import org.onlab.onos.net.link.DefaultLinkDescription; |
| 54 | import org.onlab.onos.net.link.LinkProvider; |
| 55 | import org.onlab.onos.net.link.LinkProviderRegistry; |
| 56 | import org.onlab.onos.net.link.LinkProviderService; |
| 57 | import org.onlab.onos.net.provider.AbstractProvider; |
| 58 | import org.onlab.onos.net.provider.ProviderId; |
| 59 | import org.onlab.packet.ChassisId; |
| 60 | import org.slf4j.Logger; |
| 61 | import org.slf4j.LoggerFactory; |
| 62 | |
| 63 | /** |
| 64 | * OpticalConfigProvider emulates the SB network provider for optical switches, |
| 65 | * optical links and any other state that needs to be configured for correct network |
| 66 | * operations. |
| 67 | * |
| 68 | */ |
| 69 | |
| 70 | @JsonIgnoreProperties(ignoreUnknown = true) |
| 71 | @Component(immediate = true) |
| 72 | public class OpticalConfigProvider extends AbstractProvider implements DeviceProvider, LinkProvider { |
| 73 | |
| 74 | protected static final Logger log = LoggerFactory |
| 75 | .getLogger(OpticalConfigProvider.class); |
| 76 | |
| 77 | // TODO: fix hard coded file path later. |
| 78 | private static final String DEFAULT_CONFIG_FILE = |
weibit | 50eb95b | 2014-10-25 21:47:54 -0700 | [diff] [blame] | 79 | "/opt/onos/config/demo-3-roadm-2-ps.json"; |
weibit | 38c42ed | 2014-10-09 19:03:54 -0700 | [diff] [blame] | 80 | private String configFileName = DEFAULT_CONFIG_FILE; |
| 81 | |
| 82 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 83 | protected LinkProviderRegistry linkProviderRegistry; |
| 84 | |
| 85 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 86 | protected DeviceProviderRegistry deviceProviderRegistry; |
| 87 | |
| 88 | private static final String OPTICAL_ANNOTATION = "optical."; |
| 89 | |
| 90 | private LinkProviderService linkProviderService; |
| 91 | private DeviceProviderService deviceProviderService; |
| 92 | |
| 93 | private static final List<Roadm> RAW_ROADMS = new ArrayList<>(); |
| 94 | private static final List<WdmLink> RAW_WDMLINKS = new ArrayList<>(); |
| 95 | private static final List<PktOptLink> RAW_PKTOPTLINKS = new ArrayList<>(); |
| 96 | |
| 97 | private static final String ROADM = "Roadm"; |
| 98 | private static final String WDM_LINK = "wdmLink"; |
| 99 | private static final String PKT_OPT_LINK = "pktOptLink"; |
| 100 | |
| 101 | protected OpticalNetworkConfig opticalNetworkConfig; |
| 102 | |
| 103 | public OpticalConfigProvider() { |
Praseed Balakrishnan | 69d95be | 2014-10-22 13:55:05 -0700 | [diff] [blame] | 104 | super(new ProviderId("optical", "org.onlab.onos.provider" + |
| 105 | ".opticalConfig")); |
weibit | 38c42ed | 2014-10-09 19:03:54 -0700 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | @Activate |
| 109 | protected void activate() { |
| 110 | linkProviderService = linkProviderRegistry.register(this); |
| 111 | deviceProviderService = deviceProviderRegistry.register(this); |
| 112 | log.info("Starting optical network configuration process..."); |
| 113 | log.info("Optical config file set to {}", configFileName); |
| 114 | |
| 115 | loadOpticalConfig(); |
| 116 | parseOpticalConfig(); |
| 117 | publishOpticalConfig(); |
| 118 | } |
| 119 | |
| 120 | @Deactivate |
| 121 | protected void deactivate() { |
| 122 | linkProviderRegistry.unregister(this); |
| 123 | linkProviderService = null; |
| 124 | deviceProviderRegistry.unregister(this); |
| 125 | deviceProviderService = null; |
| 126 | RAW_ROADMS.clear(); |
| 127 | RAW_WDMLINKS.clear(); |
| 128 | RAW_PKTOPTLINKS.clear(); |
| 129 | log.info("Stopped"); |
| 130 | } |
| 131 | |
| 132 | private void loadOpticalConfig() { |
| 133 | ObjectMapper mapper = new ObjectMapper(); |
| 134 | opticalNetworkConfig = new OpticalNetworkConfig(); |
| 135 | try { |
| 136 | opticalNetworkConfig = mapper.readValue(new File(configFileName), OpticalNetworkConfig.class); |
| 137 | } catch (JsonParseException e) { |
| 138 | String err = String.format("JsonParseException while loading network " |
| 139 | + "config from file: %s: %s", configFileName, e.getMessage()); |
| 140 | log.error(err, e); |
| 141 | } catch (JsonMappingException e) { |
| 142 | String err = String.format( |
| 143 | "JsonMappingException while loading network config " |
| 144 | + "from file: %s: %s", configFileName, e.getMessage()); |
| 145 | log.error(err, e); |
| 146 | } catch (IOException e) { |
| 147 | String err = String.format("IOException while loading network config " |
| 148 | + "from file: %s %s", configFileName, e.getMessage()); |
| 149 | log.error(err, e); |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | private void parseOpticalConfig() { |
| 154 | List<OpticalSwitchDescription> swList = opticalNetworkConfig.getOpticalSwitches(); |
| 155 | List<OpticalLinkDescription> lkList = opticalNetworkConfig.getOpticalLinks(); |
| 156 | |
| 157 | for (OpticalSwitchDescription sw : swList) { |
| 158 | String swtype = sw.getType(); |
| 159 | boolean allow = sw.isAllowed(); |
| 160 | if (swtype.equals(ROADM) && allow) { |
| 161 | int regNum = 0; |
| 162 | Set<Map.Entry<String, JsonNode>> m = sw.params.entrySet(); |
| 163 | for (Map.Entry<String, JsonNode> e : m) { |
| 164 | String key = e.getKey(); |
| 165 | JsonNode j = e.getValue(); |
| 166 | if (key.equals("numRegen")) { |
| 167 | regNum = j.asInt(); |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | Roadm newRoadm = new Roadm(); |
| 172 | newRoadm.setName(sw.name); |
| 173 | newRoadm.setNodeId(sw.nodeDpid); |
| 174 | newRoadm.setLongtitude(sw.longitude); |
| 175 | newRoadm.setLatitude(sw.latitude); |
| 176 | newRoadm.setRegenNum(regNum); |
| 177 | |
| 178 | RAW_ROADMS.add(newRoadm); |
| 179 | log.info(newRoadm.toString()); |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | for (OpticalLinkDescription lk : lkList) { |
| 184 | String lktype = lk.getType(); |
| 185 | switch (lktype) { |
| 186 | case WDM_LINK: |
| 187 | WdmLink newWdmLink = new WdmLink(); |
| 188 | newWdmLink.setSrcNodeId(lk.getNodeDpid1()); |
| 189 | newWdmLink.setSnkNodeId(lk.getNodeDpid2()); |
| 190 | newWdmLink.setAdminWeight(1000); // default weight for each WDM link. |
| 191 | Set<Map.Entry<String, JsonNode>> m = lk.params.entrySet(); |
| 192 | for (Map.Entry<String, JsonNode> e : m) { |
| 193 | String key = e.getKey(); |
| 194 | JsonNode j = e.getValue(); |
| 195 | if (key.equals("nodeName1")) { |
| 196 | newWdmLink.setSrcNodeName(j.asText()); |
| 197 | } else if (key.equals("nodeName2")) { |
| 198 | newWdmLink.setSnkNodeName(j.asText()); |
| 199 | } else if (key.equals("port1")) { |
| 200 | newWdmLink.setSrcPort(j.asInt()); |
| 201 | } else if (key.equals("port2")) { |
| 202 | newWdmLink.setSnkPort(j.asInt()); |
| 203 | } else if (key.equals("distKms")) { |
| 204 | newWdmLink.setDistance(j.asDouble()); |
| 205 | } else if (key.equals("numWaves")) { |
| 206 | newWdmLink.setWavelengthNumber(j.asInt()); |
| 207 | } else { |
| 208 | log.error("error found"); |
| 209 | // TODO add exception processing; |
| 210 | } |
| 211 | } |
| 212 | RAW_WDMLINKS.add(newWdmLink); |
| 213 | log.info(newWdmLink.toString()); |
| 214 | |
| 215 | break; |
| 216 | |
| 217 | case PKT_OPT_LINK: |
| 218 | PktOptLink newPktOptLink = new PktOptLink(); |
| 219 | newPktOptLink.setSrcNodeId(lk.getNodeDpid1()); |
| 220 | newPktOptLink.setSnkNodeId(lk.getNodeDpid2()); |
| 221 | newPktOptLink.setAdminWeight(10); // default weight for each packet-optical link. |
| 222 | Set<Map.Entry<String, JsonNode>> ptm = lk.params.entrySet(); |
| 223 | for (Map.Entry<String, JsonNode> e : ptm) { |
| 224 | String key = e.getKey(); |
| 225 | JsonNode j = e.getValue(); |
| 226 | if (key.equals("nodeName1")) { |
| 227 | newPktOptLink.setSrcNodeName(j.asText()); |
| 228 | } else if (key.equals("nodeName2")) { |
| 229 | newPktOptLink.setSnkNodeName(j.asText()); |
| 230 | } else if (key.equals("port1")) { |
| 231 | newPktOptLink.setSrcPort(j.asInt()); |
| 232 | } else if (key.equals("port2")) { |
| 233 | newPktOptLink.setSnkPort(j.asInt()); |
| 234 | } else if (key.equals("bandWidth")) { |
| 235 | newPktOptLink.setBandwdith(j.asDouble()); |
| 236 | } else { |
| 237 | log.error("error found"); |
| 238 | // TODO add exception processing; |
| 239 | } |
| 240 | } |
| 241 | |
| 242 | RAW_PKTOPTLINKS.add(newPktOptLink); |
| 243 | log.info(newPktOptLink.toString()); |
| 244 | break; |
| 245 | default: |
| 246 | } |
| 247 | } |
| 248 | } |
| 249 | |
| 250 | private void publishOpticalConfig() { |
| 251 | if (deviceProviderService == null || linkProviderService == null) { |
| 252 | return; |
| 253 | } |
| 254 | |
| 255 | // Discover the optical ROADM objects |
| 256 | Iterator<Roadm> iterWdmNode = RAW_ROADMS.iterator(); |
| 257 | while (iterWdmNode.hasNext()) { |
| 258 | Roadm value = iterWdmNode.next(); |
| 259 | DeviceId did = deviceId("of:" + value.getNodeId().replace(":", "")); |
Praseed Balakrishnan | 69d95be | 2014-10-22 13:55:05 -0700 | [diff] [blame] | 260 | ChassisId cid = new ChassisId(); |
weibit | 38c42ed | 2014-10-09 19:03:54 -0700 | [diff] [blame] | 261 | DefaultAnnotations extendedAttributes = DefaultAnnotations.builder() |
| 262 | .set(OPTICAL_ANNOTATION + "switchType", "ROADM") |
| 263 | .set(OPTICAL_ANNOTATION + "switchName", value.getName()) |
| 264 | .set(OPTICAL_ANNOTATION + "latitude", Double.toString(value.getLatitude())) |
| 265 | .set(OPTICAL_ANNOTATION + "longtitude", Double.toString(value.getLongtitude())) |
| 266 | .set(OPTICAL_ANNOTATION + "regNum", Integer.toString(value.getRegenNum())) |
| 267 | .build(); |
| 268 | |
| 269 | DeviceDescription description = |
| 270 | new DefaultDeviceDescription(did.uri(), |
| 271 | Device.Type.SWITCH, |
| 272 | "", |
| 273 | "", |
| 274 | "", |
| 275 | "", |
| 276 | cid, |
| 277 | extendedAttributes); |
| 278 | deviceProviderService.deviceConnected(did, description); |
| 279 | } |
| 280 | |
| 281 | // Discover the optical WDM link objects |
| 282 | Iterator<WdmLink> iterWdmlink = RAW_WDMLINKS.iterator(); |
| 283 | while (iterWdmlink.hasNext()) { |
| 284 | WdmLink value = iterWdmlink.next(); |
| 285 | |
| 286 | DeviceId srcNodeId = deviceId("of:" + value.getSrcNodeId().replace(":", "")); |
| 287 | DeviceId snkNodeId = deviceId("of:" + value.getSnkNodeId().replace(":", "")); |
| 288 | |
| 289 | PortNumber srcPort = PortNumber.portNumber(value.getSrcPort()); |
| 290 | PortNumber snkPort = PortNumber.portNumber(value.getSnkPort()); |
| 291 | |
| 292 | ConnectPoint srcPoint = new ConnectPoint(srcNodeId, srcPort); |
| 293 | ConnectPoint snkPoint = new ConnectPoint(snkNodeId, snkPort); |
| 294 | |
| 295 | DefaultAnnotations extendedAttributes = DefaultAnnotations.builder() |
| 296 | .set(OPTICAL_ANNOTATION + "linkType", "WDM") |
| 297 | .set(OPTICAL_ANNOTATION + "distance", Double.toString(value.getDistance())) |
| 298 | .set(OPTICAL_ANNOTATION + "cost", Double.toString(value.getDistance())) |
| 299 | .set(OPTICAL_ANNOTATION + "adminWeight", Double.toString(value.getAdminWeight())) |
| 300 | .set(OPTICAL_ANNOTATION + "wavelengthNum", Integer.toString(value.getWavelengthNumber())) |
| 301 | .build(); |
| 302 | |
| 303 | DefaultLinkDescription linkDescription = |
| 304 | new DefaultLinkDescription(srcPoint, |
| 305 | snkPoint, |
Thomas Vachuska | 0e752bd | 2014-10-22 22:33:41 -0700 | [diff] [blame] | 306 | Link.Type.OPTICAL, |
weibit | 38c42ed | 2014-10-09 19:03:54 -0700 | [diff] [blame] | 307 | extendedAttributes); |
| 308 | |
| 309 | linkProviderService.linkDetected(linkDescription); |
| 310 | log.info(String.format("WDM link: %s : %s", |
| 311 | linkDescription.src().toString(), linkDescription.dst().toString())); |
weibit | aca1460 | 2014-10-24 10:26:26 -0700 | [diff] [blame] | 312 | |
| 313 | |
| 314 | DefaultLinkDescription linkDescriptionReverse = |
| 315 | new DefaultLinkDescription(snkPoint, |
| 316 | srcPoint, |
| 317 | Link.Type.OPTICAL, |
| 318 | extendedAttributes); |
| 319 | |
| 320 | linkProviderService.linkDetected(linkDescriptionReverse); |
| 321 | log.info(String.format("WDM link: %s : %s", |
| 322 | linkDescriptionReverse.src().toString(), linkDescriptionReverse.dst().toString())); |
weibit | 38c42ed | 2014-10-09 19:03:54 -0700 | [diff] [blame] | 323 | } |
| 324 | |
| 325 | // Discover the packet optical link objects |
| 326 | Iterator<PktOptLink> iterPktOptlink = RAW_PKTOPTLINKS.iterator(); |
| 327 | while (iterPktOptlink.hasNext()) { |
| 328 | PktOptLink value = iterPktOptlink.next(); |
| 329 | DeviceId srcNodeId = deviceId("of:" + value.getSrcNodeId().replace(":", "")); |
| 330 | DeviceId snkNodeId = deviceId("of:" + value.getSnkNodeId().replace(":", "")); |
| 331 | |
| 332 | PortNumber srcPort = PortNumber.portNumber(value.getSrcPort()); |
| 333 | PortNumber snkPort = PortNumber.portNumber(value.getSnkPort()); |
| 334 | |
| 335 | ConnectPoint srcPoint = new ConnectPoint(srcNodeId, srcPort); |
| 336 | ConnectPoint snkPoint = new ConnectPoint(snkNodeId, snkPort); |
| 337 | |
| 338 | DefaultAnnotations extendedAttributes = DefaultAnnotations.builder() |
| 339 | .set(OPTICAL_ANNOTATION + "linkType", "PktOptLink") |
| 340 | .set(OPTICAL_ANNOTATION + "bandwidth", Double.toString(value.getBandwidth())) |
| 341 | .set(OPTICAL_ANNOTATION + "cost", Double.toString(value.getBandwidth())) |
| 342 | .set(OPTICAL_ANNOTATION + "adminWeight", Double.toString(value.getAdminWeight())) |
| 343 | .build(); |
| 344 | |
| 345 | DefaultLinkDescription linkDescription = |
| 346 | new DefaultLinkDescription(srcPoint, |
| 347 | snkPoint, |
Thomas Vachuska | 0e752bd | 2014-10-22 22:33:41 -0700 | [diff] [blame] | 348 | Link.Type.OPTICAL, |
weibit | 38c42ed | 2014-10-09 19:03:54 -0700 | [diff] [blame] | 349 | extendedAttributes); |
| 350 | |
| 351 | linkProviderService.linkDetected(linkDescription); |
| 352 | log.info(String.format("Packet-optical link: %s : %s", |
| 353 | linkDescription.src().toString(), linkDescription.dst().toString())); |
weibit | aca1460 | 2014-10-24 10:26:26 -0700 | [diff] [blame] | 354 | |
| 355 | DefaultLinkDescription linkDescriptionReverse = |
| 356 | new DefaultLinkDescription(snkPoint, |
| 357 | srcPoint, |
| 358 | Link.Type.OPTICAL, |
| 359 | extendedAttributes); |
| 360 | |
| 361 | linkProviderService.linkDetected(linkDescriptionReverse); |
| 362 | log.info(String.format("Packet-optical link: %s : %s", |
| 363 | linkDescriptionReverse.src().toString(), linkDescriptionReverse.dst().toString())); |
weibit | 38c42ed | 2014-10-09 19:03:54 -0700 | [diff] [blame] | 364 | } |
| 365 | |
| 366 | } |
| 367 | |
| 368 | @Override |
| 369 | public void triggerProbe(Device device) { |
| 370 | // TODO We may want to consider re-reading config files and publishing them based on this event. |
| 371 | } |
| 372 | |
| 373 | @Override |
| 374 | public void roleChanged(Device device, MastershipRole newRole) { |
| 375 | // TODO Auto-generated method stub. |
| 376 | } |
| 377 | |
| 378 | } |