Added server-side code to create host-to-host intent. Still WIP.
Change-Id: I80626aa9ecb38802ddca4be3bce3def85ccfdb88
Showing
4 changed files
with
157 additions
and
34 deletions
| ... | @@ -296,7 +296,7 @@ public class FlowRuleManager | ... | @@ -296,7 +296,7 @@ public class FlowRuleManager |
| 296 | post(event); | 296 | post(event); |
| 297 | } | 297 | } |
| 298 | } else { | 298 | } else { |
| 299 | - log.info("Removing flow rules...."); | 299 | + log.debug("Removing flow rules...."); |
| 300 | removeFlowRules(flowEntry); | 300 | removeFlowRules(flowEntry); |
| 301 | } | 301 | } |
| 302 | 302 | ... | ... |
| ... | @@ -20,12 +20,17 @@ import com.fasterxml.jackson.databind.ObjectMapper; | ... | @@ -20,12 +20,17 @@ import com.fasterxml.jackson.databind.ObjectMapper; |
| 20 | import com.fasterxml.jackson.databind.node.ArrayNode; | 20 | import com.fasterxml.jackson.databind.node.ArrayNode; |
| 21 | import com.fasterxml.jackson.databind.node.ObjectNode; | 21 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 22 | import org.eclipse.jetty.websocket.WebSocket; | 22 | import org.eclipse.jetty.websocket.WebSocket; |
| 23 | +import org.onlab.onos.core.ApplicationId; | ||
| 24 | +import org.onlab.onos.core.CoreService; | ||
| 23 | import org.onlab.onos.mastership.MastershipEvent; | 25 | import org.onlab.onos.mastership.MastershipEvent; |
| 24 | import org.onlab.onos.mastership.MastershipListener; | 26 | import org.onlab.onos.mastership.MastershipListener; |
| 25 | import org.onlab.onos.mastership.MastershipService; | 27 | import org.onlab.onos.mastership.MastershipService; |
| 26 | import org.onlab.onos.net.Annotations; | 28 | import org.onlab.onos.net.Annotations; |
| 29 | +import org.onlab.onos.net.ConnectPoint; | ||
| 30 | +import org.onlab.onos.net.DefaultEdgeLink; | ||
| 27 | import org.onlab.onos.net.Device; | 31 | import org.onlab.onos.net.Device; |
| 28 | import org.onlab.onos.net.DeviceId; | 32 | import org.onlab.onos.net.DeviceId; |
| 33 | +import org.onlab.onos.net.ElementId; | ||
| 29 | import org.onlab.onos.net.Host; | 34 | import org.onlab.onos.net.Host; |
| 30 | import org.onlab.onos.net.HostId; | 35 | import org.onlab.onos.net.HostId; |
| 31 | import org.onlab.onos.net.HostLocation; | 36 | import org.onlab.onos.net.HostLocation; |
| ... | @@ -34,28 +39,41 @@ import org.onlab.onos.net.Path; | ... | @@ -34,28 +39,41 @@ import org.onlab.onos.net.Path; |
| 34 | import org.onlab.onos.net.device.DeviceEvent; | 39 | import org.onlab.onos.net.device.DeviceEvent; |
| 35 | import org.onlab.onos.net.device.DeviceListener; | 40 | import org.onlab.onos.net.device.DeviceListener; |
| 36 | import org.onlab.onos.net.device.DeviceService; | 41 | import org.onlab.onos.net.device.DeviceService; |
| 42 | +import org.onlab.onos.net.flow.DefaultTrafficSelector; | ||
| 43 | +import org.onlab.onos.net.flow.DefaultTrafficTreatment; | ||
| 37 | import org.onlab.onos.net.host.HostEvent; | 44 | import org.onlab.onos.net.host.HostEvent; |
| 38 | import org.onlab.onos.net.host.HostListener; | 45 | import org.onlab.onos.net.host.HostListener; |
| 39 | import org.onlab.onos.net.host.HostService; | 46 | import org.onlab.onos.net.host.HostService; |
| 47 | +import org.onlab.onos.net.intent.HostToHostIntent; | ||
| 48 | +import org.onlab.onos.net.intent.Intent; | ||
| 49 | +import org.onlab.onos.net.intent.IntentEvent; | ||
| 40 | import org.onlab.onos.net.intent.IntentId; | 50 | import org.onlab.onos.net.intent.IntentId; |
| 51 | +import org.onlab.onos.net.intent.IntentListener; | ||
| 52 | +import org.onlab.onos.net.intent.IntentService; | ||
| 53 | +import org.onlab.onos.net.intent.PathIntent; | ||
| 41 | import org.onlab.onos.net.link.LinkEvent; | 54 | import org.onlab.onos.net.link.LinkEvent; |
| 42 | import org.onlab.onos.net.link.LinkListener; | 55 | import org.onlab.onos.net.link.LinkListener; |
| 43 | import org.onlab.onos.net.link.LinkService; | 56 | import org.onlab.onos.net.link.LinkService; |
| 57 | +import org.onlab.onos.net.provider.ProviderId; | ||
| 44 | import org.onlab.onos.net.topology.PathService; | 58 | import org.onlab.onos.net.topology.PathService; |
| 45 | import org.onlab.osgi.ServiceDirectory; | 59 | import org.onlab.osgi.ServiceDirectory; |
| 46 | import org.onlab.packet.IpAddress; | 60 | import org.onlab.packet.IpAddress; |
| 47 | 61 | ||
| 48 | import java.io.IOException; | 62 | import java.io.IOException; |
| 49 | -import java.util.HashMap; | ||
| 50 | import java.util.Iterator; | 63 | import java.util.Iterator; |
| 64 | +import java.util.List; | ||
| 51 | import java.util.Map; | 65 | import java.util.Map; |
| 52 | import java.util.Set; | 66 | import java.util.Set; |
| 67 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 53 | 68 | ||
| 54 | import static com.google.common.base.Preconditions.checkNotNull; | 69 | import static com.google.common.base.Preconditions.checkNotNull; |
| 55 | import static org.onlab.onos.net.DeviceId.deviceId; | 70 | import static org.onlab.onos.net.DeviceId.deviceId; |
| 56 | import static org.onlab.onos.net.HostId.hostId; | 71 | import static org.onlab.onos.net.HostId.hostId; |
| 72 | +import static org.onlab.onos.net.PortNumber.portNumber; | ||
| 57 | import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_ADDED; | 73 | import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_ADDED; |
| 58 | import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_REMOVED; | 74 | import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_REMOVED; |
| 75 | +import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED; | ||
| 76 | +import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED; | ||
| 59 | import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED; | 77 | import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED; |
| 60 | import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED; | 78 | import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED; |
| 61 | 79 | ||
| ... | @@ -64,6 +82,10 @@ import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED; | ... | @@ -64,6 +82,10 @@ import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED; |
| 64 | */ | 82 | */ |
| 65 | public class TopologyWebSocket implements WebSocket.OnTextMessage { | 83 | public class TopologyWebSocket implements WebSocket.OnTextMessage { |
| 66 | 84 | ||
| 85 | + private static final String APP_ID = "org.onlab.onos.gui"; | ||
| 86 | + private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true); | ||
| 87 | + | ||
| 88 | + private final ApplicationId appId; | ||
| 67 | private final ServiceDirectory directory; | 89 | private final ServiceDirectory directory; |
| 68 | 90 | ||
| 69 | private final ObjectMapper mapper = new ObjectMapper(); | 91 | private final ObjectMapper mapper = new ObjectMapper(); |
| ... | @@ -74,14 +96,19 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { | ... | @@ -74,14 +96,19 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { |
| 74 | private final LinkService linkService; | 96 | private final LinkService linkService; |
| 75 | private final HostService hostService; | 97 | private final HostService hostService; |
| 76 | private final MastershipService mastershipService; | 98 | private final MastershipService mastershipService; |
| 99 | + private final IntentService intentService; | ||
| 77 | 100 | ||
| 78 | private final DeviceListener deviceListener = new InternalDeviceListener(); | 101 | private final DeviceListener deviceListener = new InternalDeviceListener(); |
| 79 | private final LinkListener linkListener = new InternalLinkListener(); | 102 | private final LinkListener linkListener = new InternalLinkListener(); |
| 80 | private final HostListener hostListener = new InternalHostListener(); | 103 | private final HostListener hostListener = new InternalHostListener(); |
| 81 | private final MastershipListener mastershipListener = new InternalMastershipListener(); | 104 | private final MastershipListener mastershipListener = new InternalMastershipListener(); |
| 105 | + private final IntentListener intentListener = new InternalIntentListener(); | ||
| 82 | 106 | ||
| 83 | // TODO: extract into an external & durable state; good enough for now and demo | 107 | // TODO: extract into an external & durable state; good enough for now and demo |
| 84 | - private static Map<String, ObjectNode> metaUi = new HashMap<>(); | 108 | + private static Map<String, ObjectNode> metaUi = new ConcurrentHashMap<>(); |
| 109 | + | ||
| 110 | + // Intents that are being monitored for the GUI | ||
| 111 | + private static Map<IntentId, Long> intentsToMonitor = new ConcurrentHashMap<>(); | ||
| 85 | 112 | ||
| 86 | private static final String COMPACT = "%s/%s-%s/%s"; | 113 | private static final String COMPACT = "%s/%s-%s/%s"; |
| 87 | 114 | ||
| ... | @@ -97,6 +124,9 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { | ... | @@ -97,6 +124,9 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { |
| 97 | linkService = directory.get(LinkService.class); | 124 | linkService = directory.get(LinkService.class); |
| 98 | hostService = directory.get(HostService.class); | 125 | hostService = directory.get(HostService.class); |
| 99 | mastershipService = directory.get(MastershipService.class); | 126 | mastershipService = directory.get(MastershipService.class); |
| 127 | + intentService = directory.get(IntentService.class); | ||
| 128 | + | ||
| 129 | + appId = directory.get(CoreService.class).registerApplication(APP_ID); | ||
| 100 | } | 130 | } |
| 101 | 131 | ||
| 102 | @Override | 132 | @Override |
| ... | @@ -106,9 +136,17 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { | ... | @@ -106,9 +136,17 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { |
| 106 | linkService.addListener(linkListener); | 136 | linkService.addListener(linkListener); |
| 107 | hostService.addListener(hostListener); | 137 | hostService.addListener(hostListener); |
| 108 | mastershipService.addListener(mastershipListener); | 138 | mastershipService.addListener(mastershipListener); |
| 139 | + intentService.addListener(intentListener); | ||
| 109 | 140 | ||
| 110 | sendAllDevices(); | 141 | sendAllDevices(); |
| 111 | sendAllLinks(); | 142 | sendAllLinks(); |
| 143 | + sendAllHosts(); | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + private void sendAllHosts() { | ||
| 147 | + for (Host host : hostService.getHosts()) { | ||
| 148 | + sendMessage(hostMessage(new HostEvent(HOST_ADDED, host))); | ||
| 149 | + } | ||
| 112 | } | 150 | } |
| 113 | 151 | ||
| 114 | private void sendAllDevices() { | 152 | private void sendAllDevices() { |
| ... | @@ -141,14 +179,15 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { | ... | @@ -141,14 +179,15 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { |
| 141 | } else if (type.equals("updateMeta")) { | 179 | } else if (type.equals("updateMeta")) { |
| 142 | updateMetaInformation(event); | 180 | updateMetaInformation(event); |
| 143 | } else if (type.equals("requestPath")) { | 181 | } else if (type.equals("requestPath")) { |
| 144 | - sendPath(event); | 182 | + createHostIntent(event); |
| 145 | } else if (type.equals("requestTraffic")) { | 183 | } else if (type.equals("requestTraffic")) { |
| 146 | sendTraffic(event); | 184 | sendTraffic(event); |
| 147 | } else if (type.equals("cancelTraffic")) { | 185 | } else if (type.equals("cancelTraffic")) { |
| 148 | cancelTraffic(event); | 186 | cancelTraffic(event); |
| 149 | } | 187 | } |
| 150 | - } catch (IOException e) { | 188 | + } catch (Exception e) { |
| 151 | - System.out.println("Received: " + data); | 189 | + System.out.println("WTF?! " + data); |
| 190 | + e.printStackTrace(); | ||
| 152 | } | 191 | } |
| 153 | } | 192 | } |
| 154 | 193 | ||
| ... | @@ -250,19 +289,19 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { | ... | @@ -250,19 +289,19 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { |
| 250 | metaUi.put(string(payload, "id"), payload); | 289 | metaUi.put(string(payload, "id"), payload); |
| 251 | } | 290 | } |
| 252 | 291 | ||
| 253 | - // Sends path message. | 292 | + // Creates host-to-host intent. |
| 254 | - private void sendPath(ObjectNode event) { | 293 | + private void createHostIntent(ObjectNode event) { |
| 255 | ObjectNode payload = payload(event); | 294 | ObjectNode payload = payload(event); |
| 256 | long id = number(event, "sid"); | 295 | long id = number(event, "sid"); |
| 257 | - DeviceId one = deviceId(string(payload, "one")); | 296 | + // TODO: add protection against device ids and non-existent hosts. |
| 258 | - DeviceId two = deviceId(string(payload, "two")); | 297 | + HostId one = hostId(string(payload, "one")); |
| 298 | + HostId two = hostId(string(payload, "two")); | ||
| 259 | 299 | ||
| 260 | - ObjectNode response = findPath(one, two); | 300 | + HostToHostIntent hostIntent = new HostToHostIntent(appId, one, two, |
| 261 | - if (response != null) { | 301 | + DefaultTrafficSelector.builder().build(), |
| 262 | - sendMessage(envelope("showPath", id, response)); | 302 | + DefaultTrafficTreatment.builder().build()); |
| 263 | - } else { | 303 | + intentsToMonitor.put(hostIntent.id(), number(event, "sid")); |
| 264 | - sendMessage(message("warn", id, "No path found")); | 304 | + intentService.submit(hostIntent); |
| 265 | - } | ||
| 266 | } | 305 | } |
| 267 | 306 | ||
| 268 | // Sends traffic message. | 307 | // Sends traffic message. |
| ... | @@ -314,8 +353,8 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { | ... | @@ -314,8 +353,8 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { |
| 314 | * @return formatted link string | 353 | * @return formatted link string |
| 315 | */ | 354 | */ |
| 316 | public static String compactLinkString(Link link) { | 355 | public static String compactLinkString(Link link) { |
| 317 | - return String.format(COMPACT, link.src().deviceId(), link.src().port(), | 356 | + return String.format(COMPACT, link.src().elementId(), link.src().port(), |
| 318 | - link.dst().deviceId(), link.dst().port()); | 357 | + link.dst().elementId(), link.dst().port()); |
| 319 | } | 358 | } |
| 320 | 359 | ||
| 321 | 360 | ||
| ... | @@ -337,11 +376,7 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { | ... | @@ -337,11 +376,7 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { |
| 337 | // Add labels, props and stuff the payload into envelope. | 376 | // Add labels, props and stuff the payload into envelope. |
| 338 | payload.set("labels", labels); | 377 | payload.set("labels", labels); |
| 339 | payload.set("props", props(device.annotations())); | 378 | payload.set("props", props(device.annotations())); |
| 340 | - | 379 | + addMetaUi(device.id(), payload); |
| 341 | - ObjectNode meta = metaUi.get(device.id().toString()); | ||
| 342 | - if (meta != null) { | ||
| 343 | - payload.set("metaUi", meta); | ||
| 344 | - } | ||
| 345 | 380 | ||
| 346 | String type = (event.type() == DEVICE_ADDED) ? "addDevice" : | 381 | String type = (event.type() == DEVICE_ADDED) ? "addDevice" : |
| 347 | ((event.type() == DEVICE_REMOVED) ? "removeDevice" : "updateDevice"); | 382 | ((event.type() == DEVICE_REMOVED) ? "removeDevice" : "updateDevice"); |
| ... | @@ -368,11 +403,30 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { | ... | @@ -368,11 +403,30 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { |
| 368 | private ObjectNode hostMessage(HostEvent event) { | 403 | private ObjectNode hostMessage(HostEvent event) { |
| 369 | Host host = event.subject(); | 404 | Host host = event.subject(); |
| 370 | ObjectNode payload = mapper.createObjectNode() | 405 | ObjectNode payload = mapper.createObjectNode() |
| 371 | - .put("id", host.id().toString()); | 406 | + .put("id", host.id().toString()) |
| 407 | + .put("ingress", compactLinkString(edgeLink(host, true))) | ||
| 408 | + .put("egress", compactLinkString(edgeLink(host, false))); | ||
| 372 | payload.set("cp", location(mapper, host.location())); | 409 | payload.set("cp", location(mapper, host.location())); |
| 373 | payload.set("labels", labels(mapper, ip(host.ipAddresses()), | 410 | payload.set("labels", labels(mapper, ip(host.ipAddresses()), |
| 374 | host.mac().toString())); | 411 | host.mac().toString())); |
| 375 | - return payload; | 412 | + payload.set("props", props(host.annotations())); |
| 413 | + addMetaUi(host.id(), payload); | ||
| 414 | + | ||
| 415 | + String type = (event.type() == HOST_ADDED) ? "addHost" : | ||
| 416 | + ((event.type() == HOST_REMOVED) ? "removeHost" : "updateHost"); | ||
| 417 | + return envelope(type, 0, payload); | ||
| 418 | + } | ||
| 419 | + | ||
| 420 | + private DefaultEdgeLink edgeLink(Host host, boolean ingress) { | ||
| 421 | + return new DefaultEdgeLink(PID, new ConnectPoint(host.id(), portNumber(0)), | ||
| 422 | + host.location(), ingress); | ||
| 423 | + } | ||
| 424 | + | ||
| 425 | + private void addMetaUi(ElementId id, ObjectNode payload) { | ||
| 426 | + ObjectNode meta = metaUi.get(id.toString()); | ||
| 427 | + if (meta != null) { | ||
| 428 | + payload.set("metaUi", meta); | ||
| 429 | + } | ||
| 376 | } | 430 | } |
| 377 | 431 | ||
| 378 | 432 | ||
| ... | @@ -468,5 +522,22 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { | ... | @@ -468,5 +522,22 @@ public class TopologyWebSocket implements WebSocket.OnTextMessage { |
| 468 | 522 | ||
| 469 | } | 523 | } |
| 470 | } | 524 | } |
| 525 | + | ||
| 526 | + private class InternalIntentListener implements IntentListener { | ||
| 527 | + @Override | ||
| 528 | + public void event(IntentEvent event) { | ||
| 529 | + Intent intent = event.subject(); | ||
| 530 | + Long sid = intentsToMonitor.get(intent.id()); | ||
| 531 | + if (sid != null) { | ||
| 532 | + List<Intent> installable = intentService.getInstallableIntents(intent.id()); | ||
| 533 | + if (installable != null && !installable.isEmpty()) { | ||
| 534 | + PathIntent pathIntent = (PathIntent) installable.iterator().next(); | ||
| 535 | + Path path = pathIntent.path(); | ||
| 536 | + ObjectNode payload = pathMessage(path).put("intentId", intent.id().toString()); | ||
| 537 | + sendMessage(envelope("showPath", sid, payload)); | ||
| 538 | + } | ||
| 539 | + } | ||
| 540 | + } | ||
| 541 | + } | ||
| 471 | } | 542 | } |
| 472 | 543 | ... | ... |
| ... | @@ -71,6 +71,11 @@ | ... | @@ -71,6 +71,11 @@ |
| 71 | opacity: .7; | 71 | opacity: .7; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | +#topo svg .link.showPath { | ||
| 75 | + stroke: #f00; | ||
| 76 | + stroke-width: 4px; | ||
| 77 | +} | ||
| 78 | + | ||
| 74 | /* for debugging */ | 79 | /* for debugging */ |
| 75 | #topo svg .node circle.debug { | 80 | #topo svg .node circle.debug { |
| 76 | fill: white; | 81 | fill: white; | ... | ... |
| ... | @@ -383,6 +383,7 @@ | ... | @@ -383,6 +383,7 @@ |
| 383 | note('addLink', lnk.id); | 383 | note('addLink', lnk.id); |
| 384 | 384 | ||
| 385 | network.links.push(lnk); | 385 | network.links.push(lnk); |
| 386 | + network.lookup[lnk.id] = lnk; | ||
| 386 | updateLinks(); | 387 | updateLinks(); |
| 387 | network.force.start(); | 388 | network.force.start(); |
| 388 | } | 389 | } |
| ... | @@ -401,13 +402,29 @@ | ... | @@ -401,13 +402,29 @@ |
| 401 | lnk = createHostLink(host); | 402 | lnk = createHostLink(host); |
| 402 | if (lnk) { | 403 | if (lnk) { |
| 403 | network.links.push(lnk); | 404 | network.links.push(lnk); |
| 405 | + network.lookup[host.ingress] = lnk; | ||
| 406 | + network.lookup[host.egress] = lnk; | ||
| 404 | updateLinks(); | 407 | updateLinks(); |
| 405 | } | 408 | } |
| 406 | network.force.start(); | 409 | network.force.start(); |
| 407 | } | 410 | } |
| 408 | 411 | ||
| 409 | function showPath(data) { | 412 | function showPath(data) { |
| 410 | - network.view.alert(data.event + "\n" + data.payload.links.length); | 413 | + var links = data.payload.links, |
| 414 | + s = [ data.event + "\n" + links.length ]; | ||
| 415 | + links.forEach(function (d, i) { | ||
| 416 | + s.push(d); | ||
| 417 | + }); | ||
| 418 | + network.view.alert(s.join('\n')); | ||
| 419 | + | ||
| 420 | + links.forEach(function (d, i) { | ||
| 421 | + var link = network.lookup[d]; | ||
| 422 | + if (link) { | ||
| 423 | + d3.select('#' + link.svgId).classed('showPath', true); | ||
| 424 | + } | ||
| 425 | + }); | ||
| 426 | + | ||
| 427 | + // TODO: add selection-highlite lines to links | ||
| 411 | } | 428 | } |
| 412 | 429 | ||
| 413 | // ............................... | 430 | // ............................... |
| ... | @@ -415,7 +432,7 @@ | ... | @@ -415,7 +432,7 @@ |
| 415 | function stillToImplement(data) { | 432 | function stillToImplement(data) { |
| 416 | var p = data.payload; | 433 | var p = data.payload; |
| 417 | note(data.event, p.id); | 434 | note(data.event, p.id); |
| 418 | - network.view.alert('Not yet implemented: "' + data.event + '"'); | 435 | + //network.view.alert('Not yet implemented: "' + data.event + '"'); |
| 419 | } | 436 | } |
| 420 | 437 | ||
| 421 | function unknownEvent(data) { | 438 | function unknownEvent(data) { |
| ... | @@ -437,6 +454,7 @@ | ... | @@ -437,6 +454,7 @@ |
| 437 | function createHostLink(host) { | 454 | function createHostLink(host) { |
| 438 | var src = host.id, | 455 | var src = host.id, |
| 439 | dst = host.cp.device, | 456 | dst = host.cp.device, |
| 457 | + id = host.id, | ||
| 440 | srcNode = network.lookup[src], | 458 | srcNode = network.lookup[src], |
| 441 | dstNode = network.lookup[dst], | 459 | dstNode = network.lookup[dst], |
| 442 | lnk; | 460 | lnk; |
| ... | @@ -449,7 +467,8 @@ | ... | @@ -449,7 +467,8 @@ |
| 449 | } | 467 | } |
| 450 | 468 | ||
| 451 | lnk = { | 469 | lnk = { |
| 452 | - id: safeId(src) + '~' + safeId(dst), | 470 | + svgId: safeId(src) + '-' + safeId(dst), |
| 471 | + id: id, | ||
| 453 | source: srcNode, | 472 | source: srcNode, |
| 454 | target: dstNode, | 473 | target: dstNode, |
| 455 | class: 'link', | 474 | class: 'link', |
| ... | @@ -467,6 +486,7 @@ | ... | @@ -467,6 +486,7 @@ |
| 467 | var type = link.type, | 486 | var type = link.type, |
| 468 | src = link.src, | 487 | src = link.src, |
| 469 | dst = link.dst, | 488 | dst = link.dst, |
| 489 | + id = link.id, | ||
| 470 | w = link.linkWidth, | 490 | w = link.linkWidth, |
| 471 | srcNode = network.lookup[src], | 491 | srcNode = network.lookup[src], |
| 472 | dstNode = network.lookup[dst], | 492 | dstNode = network.lookup[dst], |
| ... | @@ -480,7 +500,8 @@ | ... | @@ -480,7 +500,8 @@ |
| 480 | } | 500 | } |
| 481 | 501 | ||
| 482 | lnk = { | 502 | lnk = { |
| 483 | - id: safeId(src) + '~' + safeId(dst), | 503 | + svgId: safeId(src) + '-' + safeId(dst), |
| 504 | + id: id, | ||
| 484 | source: srcNode, | 505 | source: srcNode, |
| 485 | target: dstNode, | 506 | target: dstNode, |
| 486 | class: 'link', | 507 | class: 'link', |
| ... | @@ -511,7 +532,7 @@ | ... | @@ -511,7 +532,7 @@ |
| 511 | var entering = link.enter() | 532 | var entering = link.enter() |
| 512 | .append('line') | 533 | .append('line') |
| 513 | .attr({ | 534 | .attr({ |
| 514 | - id: function (d) { return d.id; }, | 535 | + id: function (d) { return d.svgId; }, |
| 515 | class: function (d) { return d.svgClass; }, | 536 | class: function (d) { return d.svgClass; }, |
| 516 | x1: function (d) { return d.x1; }, | 537 | x1: function (d) { return d.x1; }, |
| 517 | y1: function (d) { return d.y1; }, | 538 | y1: function (d) { return d.y1; }, |
| ... | @@ -529,6 +550,19 @@ | ... | @@ -529,6 +550,19 @@ |
| 529 | // augment links | 550 | // augment links |
| 530 | // TODO: add src/dst port labels etc. | 551 | // TODO: add src/dst port labels etc. |
| 531 | 552 | ||
| 553 | + | ||
| 554 | + // operate on both existing and new links, if necessary | ||
| 555 | + //link .foo() .bar() ... | ||
| 556 | + | ||
| 557 | + // operate on exiting links: | ||
| 558 | + // TODO: figure out how to remove the node 'g' AND its children | ||
| 559 | + link.exit() | ||
| 560 | + .transition() | ||
| 561 | + .duration(750) | ||
| 562 | + .attr({ | ||
| 563 | + opacity: 0 | ||
| 564 | + }) | ||
| 565 | + .remove(); | ||
| 532 | } | 566 | } |
| 533 | 567 | ||
| 534 | function createDeviceNode(device) { | 568 | function createDeviceNode(device) { |
| ... | @@ -756,7 +790,6 @@ | ... | @@ -756,7 +790,6 @@ |
| 756 | webSock.ws = new WebSocket(webSockUrl()); | 790 | webSock.ws = new WebSocket(webSockUrl()); |
| 757 | 791 | ||
| 758 | webSock.ws.onopen = function() { | 792 | webSock.ws.onopen = function() { |
| 759 | - webSock._send("Hi there!"); | ||
| 760 | }; | 793 | }; |
| 761 | 794 | ||
| 762 | webSock.ws.onmessage = function(m) { | 795 | webSock.ws.onmessage = function(m) { |
| ... | @@ -932,10 +965,12 @@ | ... | @@ -932,10 +965,12 @@ |
| 932 | node = nodeG.selectAll('.node'); | 965 | node = nodeG.selectAll('.node'); |
| 933 | 966 | ||
| 934 | function ldist(d) { | 967 | function ldist(d) { |
| 935 | - return fcfg.linkDistance[d.class] || 150; | 968 | + return 2 * 30; |
| 969 | + //return fcfg.linkDistance[d.class] || 150; | ||
| 936 | } | 970 | } |
| 937 | function lstrg(d) { | 971 | function lstrg(d) { |
| 938 | - return fcfg.linkStrength[d.class] || 1; | 972 | + return 2 * 0.6; |
| 973 | + //return fcfg.linkStrength[d.class] || 1; | ||
| 939 | } | 974 | } |
| 940 | function lchrg(d) { | 975 | function lchrg(d) { |
| 941 | return fcfg.charge[d.class] || -200; | 976 | return fcfg.charge[d.class] || -200; |
| ... | @@ -968,11 +1003,23 @@ | ... | @@ -968,11 +1003,23 @@ |
| 968 | .size(forceDim) | 1003 | .size(forceDim) |
| 969 | .nodes(network.nodes) | 1004 | .nodes(network.nodes) |
| 970 | .links(network.links) | 1005 | .links(network.links) |
| 971 | - .charge(lchrg) | 1006 | + .gravity(0.3) |
| 1007 | + .charge(-15000) | ||
| 1008 | + .friction(0.1) | ||
| 1009 | + //.charge(lchrg) | ||
| 972 | .linkDistance(ldist) | 1010 | .linkDistance(ldist) |
| 973 | .linkStrength(lstrg) | 1011 | .linkStrength(lstrg) |
| 974 | .on('tick', tick); | 1012 | .on('tick', tick); |
| 975 | 1013 | ||
| 1014 | + // TVUE | ||
| 1015 | + //.gravity(0.3) | ||
| 1016 | + //.charge(-15000) | ||
| 1017 | + //.friction(0.1) | ||
| 1018 | + //.linkDistance(function(d) { return d.value * 30; }) | ||
| 1019 | + //.linkStrength(function(d) { return d.value * 0.6; }) | ||
| 1020 | + //.size([w, h]) | ||
| 1021 | + //.start(); | ||
| 1022 | + | ||
| 976 | network.drag = d3u.createDragBehavior(network.force, selectCb, atDragEnd); | 1023 | network.drag = d3u.createDragBehavior(network.force, selectCb, atDragEnd); |
| 977 | } | 1024 | } |
| 978 | 1025 | ... | ... |
-
Please register or login to post a comment