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