GUI -- Added updateDevice event handling.
- Display offline devices as grey.
- Tracing web socket messages (for now, in console; in future, to trace view).
- Captured sample events for use with test scenarios - both from and to the server.
- Added description to scenario file.
Change-Id: I7825b32d63496ebea2ab5789519fb0c6af6c5257
diff --git a/web/gui/src/main/webapp/index2.html b/web/gui/src/main/webapp/index2.html
index 66050c6..03272e9 100644
--- a/web/gui/src/main/webapp/index2.html
+++ b/web/gui/src/main/webapp/index2.html
@@ -44,6 +44,7 @@
<!-- This is where contributed stylesheets get INJECTED -->
<!-- TODO: replace with template marker and inject refs server-side -->
<link rel="stylesheet" href="topo2.css">
+ <link rel="stylesheet" href="webSockTrace.css">
<!-- General library modules included here-->
@@ -97,6 +98,7 @@
<!-- Contributed (application) views injected here -->
<!-- TODO: replace with template marker and inject refs server-side -->
+ <script src="webSockTrace.js"></script>
<script src="topo2.js"></script>
<!-- finally, build the UI-->
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/addDevice_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/rx/addDevice_ex1.json
new file mode 100644
index 0000000..f00cf2c
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/addDevice_ex1.json
@@ -0,0 +1,15 @@
+{
+ "event": "addDevice",
+ "payload": {
+ "id": "of:0000000000000003",
+ "type": "switch",
+ "online": true,
+ "labels": [
+ "of:0000000000000003",
+ "3",
+ "",
+ null
+ ],
+ "props": {}
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/addHost_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/rx/addHost_ex1.json
new file mode 100644
index 0000000..a97d15a
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/addHost_ex1.json
@@ -0,0 +1,17 @@
+{
+ "event": "addHost",
+ "payload": {
+ "id": "6A:40:24:F7:9C:2C/-1",
+ "ingress": "6A:40:24:F7:9C:2C/-1/0-of:0000000000000003/2",
+ "egress": "of:0000000000000003/2-6A:40:24:F7:9C:2C/-1/0",
+ "cp": {
+ "device": "of:0000000000000003",
+ "port": 2
+ },
+ "labels": [
+ "unknown",
+ "6A:40:24:F7:9C:2C"
+ ],
+ "props": {}
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/addLink_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/rx/addLink_ex1.json
new file mode 100644
index 0000000..92c7848
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/addLink_ex1.json
@@ -0,0 +1,12 @@
+{
+ "event": "addLink",
+ "payload": {
+ "id": "of:0000000000000007/4-of:0000000000000006/1",
+ "type": "direct",
+ "linkWidth": 2,
+ "src": "of:0000000000000007",
+ "srcPort": "4",
+ "dst": "of:0000000000000006",
+ "dstPort": "1"
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/removeDevice_fab.json b/web/gui/src/main/webapp/json/ev/_capture/rx/removeDevice_fab.json
new file mode 100644
index 0000000..0e8d47a
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/removeDevice_fab.json
@@ -0,0 +1,20 @@
+{
+ "__comments__": [
+ "fabricated event",
+ "not sure if this is the actual format",
+ "but we really only care about 'id' being in the payload"
+ ],
+ "event": "removeDevice",
+ "payload": {
+ "id": "of:0000000000000002",
+ "type": "switch",
+ "online": true,
+ "labels": [
+ "of:0000000000000002",
+ "2",
+ "",
+ null
+ ],
+ "props": {}
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/removeHost_fab.json b/web/gui/src/main/webapp/json/ev/_capture/rx/removeHost_fab.json
new file mode 100644
index 0000000..4237199
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/removeHost_fab.json
@@ -0,0 +1,22 @@
+{
+ "__comments__": [
+ "fabricated event",
+ "not sure if this is the actual format",
+ "but we really only care about 'id' being in the payload"
+ ],
+ "event": "removeHost",
+ "payload": {
+ "id": "6A:40:24:F7:9C:2C/-1",
+ "ingress": "6A:40:24:F7:9C:2C/-1/0-of:0000000000000003/2",
+ "egress": "of:0000000000000003/2-6A:40:24:F7:9C:2C/-1/0",
+ "cp": {
+ "device": "of:0000000000000003",
+ "port": 2
+ },
+ "labels": [
+ "unknown",
+ "6A:40:24:F7:9C:2C"
+ ],
+ "props": {}
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/removeLink_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/rx/removeLink_ex1.json
new file mode 100644
index 0000000..8d1dd03
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/removeLink_ex1.json
@@ -0,0 +1,12 @@
+{
+ "event": "removeLink",
+ "payload": {
+ "id": "of:0000000000000001/1-of:0000000000000002/4",
+ "type": "direct",
+ "linkWidth": 2,
+ "src": "of:0000000000000001",
+ "srcPort": "1",
+ "dst": "of:0000000000000002",
+ "dstPort": "4"
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/showPath_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/rx/showPath_ex1.json
new file mode 100644
index 0000000..de1023e
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/showPath_ex1.json
@@ -0,0 +1,15 @@
+{
+ "event": "showPath",
+ "sid": 15,
+ "payload": {
+ "links": [
+ "62:4F:65:BF:FF:B3/-1/0-of:000000000000000b/1",
+ "of:000000000000000b/4-of:000000000000000a/1",
+ "of:000000000000000a/4-of:0000000000000001/3",
+ "of:0000000000000001/1-of:0000000000000002/4",
+ "of:0000000000000002/1-of:0000000000000003/4",
+ "of:0000000000000003/1-CA:4B:EE:A4:B0:33/-1/0"
+ ],
+ "intentId": "0x52a914f9"
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/updateDevice_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/rx/updateDevice_ex1.json
new file mode 100644
index 0000000..dda6186
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/updateDevice_ex1.json
@@ -0,0 +1,15 @@
+{
+ "event": "updateDevice",
+ "payload": {
+ "id": "of:0000000000000002",
+ "type": "switch",
+ "online": true,
+ "labels": [
+ "of:0000000000000002",
+ "2",
+ "",
+ null
+ ],
+ "props": {}
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/updateDevice_ex2.json b/web/gui/src/main/webapp/json/ev/_capture/rx/updateDevice_ex2.json
new file mode 100644
index 0000000..d607f98
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/updateDevice_ex2.json
@@ -0,0 +1,15 @@
+{
+ "event": "updateDevice",
+ "payload": {
+ "id": "of:0000000000000002",
+ "type": "switch",
+ "online": false,
+ "labels": [
+ "of:0000000000000002",
+ "2",
+ "",
+ null
+ ],
+ "props": {}
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/updateHost.json b/web/gui/src/main/webapp/json/ev/_capture/rx/updateHost.json
new file mode 100644
index 0000000..fd7361c
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/updateHost.json
@@ -0,0 +1,17 @@
+{
+ "event": "updateHost",
+ "payload": {
+ "id": "AA:C2:74:3F:B8:06/-1",
+ "ingress": "AA:C2:74:3F:B8:06/-1/0-of:0000000000000005/3",
+ "egress": "of:0000000000000005/3-AA:C2:74:3F:B8:06/-1/0",
+ "cp": {
+ "device": "of:0000000000000005",
+ "port": 3
+ },
+ "labels": [
+ "10.0.0.9",
+ "AA:C2:74:3F:B8:06"
+ ],
+ "props":{}
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/rx/updateLink_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/rx/updateLink_ex1.json
new file mode 100644
index 0000000..3be5c5f
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/rx/updateLink_ex1.json
@@ -0,0 +1,12 @@
+{
+ "event": "updateLink",
+ "payload": {
+ "id": "of:0000000000000002/4-of:0000000000000001/1",
+ "type": "direct",
+ "linkWidth": 2,
+ "src": "of:0000000000000002",
+ "srcPort": "4",
+ "dst": "of:0000000000000001",
+ "dstPort": "1"
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/tx/requestPath_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/tx/requestPath_ex1.json
new file mode 100644
index 0000000..4963865
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/tx/requestPath_ex1.json
@@ -0,0 +1,8 @@
+{
+ "event": "requestPath",
+ "sid": 15,
+ "payload": {
+ "one": "62:4F:65:BF:FF:B3/-1",
+ "two": "CA:4B:EE:A4:B0:33/-1"
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/_capture/tx/updateMeta_ex1.json b/web/gui/src/main/webapp/json/ev/_capture/tx/updateMeta_ex1.json
new file mode 100644
index 0000000..c04727e
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/_capture/tx/updateMeta_ex1.json
@@ -0,0 +1,10 @@
+{
+ "event": "updateMeta",
+ "sid": 11,
+ "payload": {
+ "id": "62:4F:65:BF:FF:B3/-1",
+ "class": "host",
+ "x": 197,
+ "y": 177
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/intent/ev_1_ui.json b/web/gui/src/main/webapp/json/ev/intentSketch/ev_1_ui.json
similarity index 100%
rename from web/gui/src/main/webapp/json/ev/intent/ev_1_ui.json
rename to web/gui/src/main/webapp/json/ev/intentSketch/ev_1_ui.json
diff --git a/web/gui/src/main/webapp/json/ev/intent/ev_2_onos.json b/web/gui/src/main/webapp/json/ev/intentSketch/ev_2_onos.json
similarity index 100%
rename from web/gui/src/main/webapp/json/ev/intent/ev_2_onos.json
rename to web/gui/src/main/webapp/json/ev/intentSketch/ev_2_onos.json
diff --git a/web/gui/src/main/webapp/json/ev/intent/ev_3_ui.json b/web/gui/src/main/webapp/json/ev/intentSketch/ev_3_ui.json
similarity index 100%
rename from web/gui/src/main/webapp/json/ev/intent/ev_3_ui.json
rename to web/gui/src/main/webapp/json/ev/intentSketch/ev_3_ui.json
diff --git a/web/gui/src/main/webapp/json/ev/intent/ev_4_onos.json b/web/gui/src/main/webapp/json/ev/intentSketch/ev_4_onos.json
similarity index 100%
rename from web/gui/src/main/webapp/json/ev/intent/ev_4_onos.json
rename to web/gui/src/main/webapp/json/ev/intentSketch/ev_4_onos.json
diff --git a/web/gui/src/main/webapp/json/ev/intent/ev_5_onos.json b/web/gui/src/main/webapp/json/ev/intentSketch/ev_5_onos.json
similarity index 100%
rename from web/gui/src/main/webapp/json/ev/intent/ev_5_onos.json
rename to web/gui/src/main/webapp/json/ev/intentSketch/ev_5_onos.json
diff --git a/web/gui/src/main/webapp/json/ev/intent/ev_6_onos.json b/web/gui/src/main/webapp/json/ev/intentSketch/ev_6_onos.json
similarity index 100%
rename from web/gui/src/main/webapp/json/ev/intent/ev_6_onos.json
rename to web/gui/src/main/webapp/json/ev/intentSketch/ev_6_onos.json
diff --git a/web/gui/src/main/webapp/json/ev/intent/ev_7_ui.json b/web/gui/src/main/webapp/json/ev/intentSketch/ev_7_ui.json
similarity index 100%
rename from web/gui/src/main/webapp/json/ev/intent/ev_7_ui.json
rename to web/gui/src/main/webapp/json/ev/intentSketch/ev_7_ui.json
diff --git a/web/gui/src/main/webapp/json/ev/intent/scenario.json b/web/gui/src/main/webapp/json/ev/intentSketch/scenario.json
similarity index 100%
rename from web/gui/src/main/webapp/json/ev/intent/scenario.json
rename to web/gui/src/main/webapp/json/ev/intentSketch/scenario.json
diff --git a/web/gui/src/main/webapp/json/ev/simple/ev_8_ui.json b/web/gui/src/main/webapp/json/ev/simple/ev_10_ui.json
similarity index 100%
rename from web/gui/src/main/webapp/json/ev/simple/ev_8_ui.json
rename to web/gui/src/main/webapp/json/ev/simple/ev_10_ui.json
diff --git a/web/gui/src/main/webapp/json/ev/simple/ev_3_onos.json b/web/gui/src/main/webapp/json/ev/simple/ev_3_onos.json
index ac521c4..73013a4 100644
--- a/web/gui/src/main/webapp/json/ev/simple/ev_3_onos.json
+++ b/web/gui/src/main/webapp/json/ev/simple/ev_3_onos.json
@@ -1,15 +1,18 @@
{
- "event": "addLink",
+ "event": "updateDevice",
"payload": {
- "id": "of:0000ffffffff0003/21-of:0000ffffffff0008/20",
- "type": "direct",
- "linkWidth": 2,
- "src": "of:0000ffffffff0003",
- "srcPort": "21",
- "dst": "of:0000ffffffff0008",
- "dstPort": "20",
- "props" : {
- "BW": "70 G"
+ "id": "of:0000ffffffff0008",
+ "type": "switch",
+ "online": true,
+ "labels": [
+ "0000ffffffff0008",
+ "FF:FF:FF:FF:00:08",
+ "sw-8-yo",
+ ""
+ ],
+ "metaUi": {
+ "x": 400,
+ "y": 280
}
}
}
diff --git a/web/gui/src/main/webapp/json/ev/simple/ev_4_onos.json b/web/gui/src/main/webapp/json/ev/simple/ev_4_onos.json
index 993570b..958af28 100644
--- a/web/gui/src/main/webapp/json/ev/simple/ev_4_onos.json
+++ b/web/gui/src/main/webapp/json/ev/simple/ev_4_onos.json
@@ -1,17 +1,18 @@
{
- "event": "addHost",
+ "event": "updateDevice",
"payload": {
- "id": "0E:2A:69:30:13:86/-1",
- "ingress": "0E:2A:69:30:13:86/-1/0-of:0000ffffffff0003/2",
- "egress": "of:0000ffffffff0003/2-0E:2A:69:30:13:86/-1/0",
- "cp": {
- "device": "of:0000ffffffff0003",
- "port": 2
- },
+ "id": "of:0000ffffffff0003",
+ "type": "switch",
+ "online": true,
"labels": [
- "unknown",
- "0E:2A:69:30:13:86"
+ "0000ffffffff0003",
+ "FF:FF:FF:FF:00:03",
+ "sw-3-yo",
+ ""
],
- "props": {}
+ "metaUi": {
+ "x": 800,
+ "y": 280
+ }
}
}
diff --git a/web/gui/src/main/webapp/json/ev/simple/ev_5_onos.json b/web/gui/src/main/webapp/json/ev/simple/ev_5_onos.json
index 17864a6..ac521c4 100644
--- a/web/gui/src/main/webapp/json/ev/simple/ev_5_onos.json
+++ b/web/gui/src/main/webapp/json/ev/simple/ev_5_onos.json
@@ -1,17 +1,15 @@
{
- "event": "addHost",
+ "event": "addLink",
"payload": {
- "id": "A6:96:E5:03:52:5F/-1",
- "ingress": "A6:96:E5:03:52:5F/-1/0-of:0000ffffffff0008/1",
- "egress": "of:0000ffffffff0008/1-A6:96:E5:03:52:5F/-1/0",
- "cp": {
- "device": "of:0000ffffffff0008",
- "port": 1
- },
- "labels": [
- "unknown",
- "A6:96:E5:03:52:5F"
- ],
- "props": {}
+ "id": "of:0000ffffffff0003/21-of:0000ffffffff0008/20",
+ "type": "direct",
+ "linkWidth": 2,
+ "src": "of:0000ffffffff0003",
+ "srcPort": "21",
+ "dst": "of:0000ffffffff0008",
+ "dstPort": "20",
+ "props" : {
+ "BW": "70 G"
+ }
}
}
diff --git a/web/gui/src/main/webapp/json/ev/simple/ev_6_onos.json b/web/gui/src/main/webapp/json/ev/simple/ev_6_onos.json
index 3a3ea9e..993570b 100644
--- a/web/gui/src/main/webapp/json/ev/simple/ev_6_onos.json
+++ b/web/gui/src/main/webapp/json/ev/simple/ev_6_onos.json
@@ -1,5 +1,5 @@
{
- "event": "updateHost",
+ "event": "addHost",
"payload": {
"id": "0E:2A:69:30:13:86/-1",
"ingress": "0E:2A:69:30:13:86/-1/0-of:0000ffffffff0003/2",
@@ -9,7 +9,7 @@
"port": 2
},
"labels": [
- "10.0.0.13",
+ "unknown",
"0E:2A:69:30:13:86"
],
"props": {}
diff --git a/web/gui/src/main/webapp/json/ev/simple/ev_7_onos.json b/web/gui/src/main/webapp/json/ev/simple/ev_7_onos.json
index 0fb56fa..17864a6 100644
--- a/web/gui/src/main/webapp/json/ev/simple/ev_7_onos.json
+++ b/web/gui/src/main/webapp/json/ev/simple/ev_7_onos.json
@@ -1,5 +1,5 @@
{
- "event": "updateHost",
+ "event": "addHost",
"payload": {
"id": "A6:96:E5:03:52:5F/-1",
"ingress": "A6:96:E5:03:52:5F/-1/0-of:0000ffffffff0008/1",
@@ -9,7 +9,7 @@
"port": 1
},
"labels": [
- "10.0.0.17",
+ "unknown",
"A6:96:E5:03:52:5F"
],
"props": {}
diff --git a/web/gui/src/main/webapp/json/ev/simple/ev_8_onos.json b/web/gui/src/main/webapp/json/ev/simple/ev_8_onos.json
new file mode 100644
index 0000000..3a3ea9e
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/simple/ev_8_onos.json
@@ -0,0 +1,17 @@
+{
+ "event": "updateHost",
+ "payload": {
+ "id": "0E:2A:69:30:13:86/-1",
+ "ingress": "0E:2A:69:30:13:86/-1/0-of:0000ffffffff0003/2",
+ "egress": "of:0000ffffffff0003/2-0E:2A:69:30:13:86/-1/0",
+ "cp": {
+ "device": "of:0000ffffffff0003",
+ "port": 2
+ },
+ "labels": [
+ "10.0.0.13",
+ "0E:2A:69:30:13:86"
+ ],
+ "props": {}
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/simple/ev_9_onos.json b/web/gui/src/main/webapp/json/ev/simple/ev_9_onos.json
new file mode 100644
index 0000000..0fb56fa
--- /dev/null
+++ b/web/gui/src/main/webapp/json/ev/simple/ev_9_onos.json
@@ -0,0 +1,17 @@
+{
+ "event": "updateHost",
+ "payload": {
+ "id": "A6:96:E5:03:52:5F/-1",
+ "ingress": "A6:96:E5:03:52:5F/-1/0-of:0000ffffffff0008/1",
+ "egress": "of:0000ffffffff0008/1-A6:96:E5:03:52:5F/-1/0",
+ "cp": {
+ "device": "of:0000ffffffff0008",
+ "port": 1
+ },
+ "labels": [
+ "10.0.0.17",
+ "A6:96:E5:03:52:5F"
+ ],
+ "props": {}
+ }
+}
diff --git a/web/gui/src/main/webapp/json/ev/simple/scenario.json b/web/gui/src/main/webapp/json/ev/simple/scenario.json
index e320413..19d6190 100644
--- a/web/gui/src/main/webapp/json/ev/simple/scenario.json
+++ b/web/gui/src/main/webapp/json/ev/simple/scenario.json
@@ -6,5 +6,17 @@
"title": "Simple Startup Scenario",
"params": {
"lastAuto": 0
- }
+ },
+ "description": [
+ "1. add device [8] (offline)",
+ "2. add device [3] (offline)",
+ "3. update device [8] (online)",
+ "4. update device [3] (online)",
+ "5. add link [3] --> [8]",
+ "6. add host (to [3])",
+ "7. add host (to [8])",
+ "8. update host[3] (IP now 10.0.0.13)",
+ "9. update host[8] (IP now 10.0.0.17)",
+ ""
+ ]
}
\ No newline at end of file
diff --git a/web/gui/src/main/webapp/onos2.js b/web/gui/src/main/webapp/onos2.js
index a31b20f..f38b35f 100644
--- a/web/gui/src/main/webapp/onos2.js
+++ b/web/gui/src/main/webapp/onos2.js
@@ -33,7 +33,8 @@
var uiApi,
viewApi,
navApi,
- libApi;
+ libApi,
+ exported = {};
var defaultOptions = {
trace: false,
@@ -658,6 +659,7 @@
return makeUid(this, id);
},
+ // TODO : add exportApi and importApi methods
// TODO : implement custom dialogs
// Consider enhancing alert mechanism to handle multiples
@@ -737,6 +739,7 @@
// ..........................................................
// View API
+ // TODO: deprecated
viewApi = {
/** @api view empty( )
* Empties the current view.
@@ -802,7 +805,8 @@
lib: libApi,
//view: viewApi,
nav: navApi,
- buildUi: buildOnosUi
+ buildUi: buildOnosUi,
+ exported: exported
};
};
diff --git a/web/gui/src/main/webapp/topo2.css b/web/gui/src/main/webapp/topo2.css
index acd0bc9..6c0c313 100644
--- a/web/gui/src/main/webapp/topo2.css
+++ b/web/gui/src/main/webapp/topo2.css
@@ -41,11 +41,16 @@
stroke: #ccc;
}
-#topo svg .node.device.switch {
+/* note: device is offline without the 'online' class */
+#topo svg .node.device {
+ fill: #777;
+}
+
+#topo svg .node.device.switch.online {
fill: #17f;
}
-#topo svg .node.device.roadm {
+#topo svg .node.device.roadm.online {
fill: #03c;
}
@@ -53,12 +58,17 @@
fill: #846;
}
+/* note: device is offline without the 'online' class */
#topo svg .node.device text {
- fill: white;
+ fill: #aaa;
font: 10pt sans-serif;
pointer-events: none;
}
+#topo svg .node.device.online text {
+ fill: white;
+}
+
#topo svg .node.host text {
fill: #846;
font: 9pt sans-serif;
diff --git a/web/gui/src/main/webapp/topo2.js b/web/gui/src/main/webapp/topo2.js
index 55e463c..f6a8456 100644
--- a/web/gui/src/main/webapp/topo2.js
+++ b/web/gui/src/main/webapp/topo2.js
@@ -24,7 +24,8 @@
'use strict';
// shorter names for library APIs
- var d3u = onos.lib.d3util;
+ var d3u = onos.lib.d3util,
+ trace;
// configuration data
var config = {
@@ -241,8 +242,8 @@
}
function handleUiEvent(data) {
- testDebug('handleUiEvent(): ' + data.event);
- // TODO:
+ scenario.view.alert('UI Tx: ' + data.event + '\n\n' +
+ JSON.stringify(data));
}
function injectStartupEvents(view) {
@@ -259,32 +260,44 @@
bgImg.style('visibility', (vis === 'hidden') ? 'visible' : 'hidden');
}
+ function updateDeviceLabel(d) {
+ var label = niceLabel(deviceLabel(d)),
+ node = d.el,
+ box;
+
+ node.select('text')
+ .text(label)
+ .style('opacity', 0)
+ .transition()
+ .style('opacity', 1);
+
+ box = adjustRectToFitText(node);
+
+ node.select('rect')
+ .transition()
+ .attr(box);
+
+ node.select('image')
+ .transition()
+ .attr('x', box.x + config.icons.xoff)
+ .attr('y', box.y + config.icons.yoff);
+ }
+
+ function updateHostLabel(d) {
+ var label = hostLabel(d),
+ host = d.el;
+
+ host.select('text').text(label);
+ }
+
function cycleLabels() {
- deviceLabelIndex = (deviceLabelIndex === network.deviceLabelCount - 1) ? 0 : deviceLabelIndex + 1;
+ deviceLabelIndex = (deviceLabelIndex === network.deviceLabelCount - 1)
+ ? 0 : deviceLabelIndex + 1;
network.nodes.forEach(function (d) {
- if (d.class !== 'device') { return; }
-
- var label = niceLabel(deviceLabel(d)),
- node = d.el,
- box;
-
- node.select('text')
- .text(label)
- .style('opacity', 0)
- .transition()
- .style('opacity', 1);
-
- box = adjustRectToFitText(node);
-
- node.select('rect')
- .transition()
- .attr(box);
-
- node.select('image')
- .transition()
- .attr('x', box.x + config.icons.xoff)
- .attr('y', box.y + config.icons.yoff);
+ if (d.class === 'device') {
+ updateDeviceLabel(d);
+ }
});
}
@@ -348,15 +361,20 @@
// ==============================
// Event handlers for server-pushed events
+ function logicError(msg) {
+ // TODO, report logic error to server, via websock, so it can be logged
+ network.view.alert('Logic Error:\n\n' + msg);
+ }
+
var eventDispatch = {
addDevice: addDevice,
- updateDevice: stillToImplement,
- removeDevice: stillToImplement,
addLink: addLink,
- updateLink: stillToImplement,
- removeLink: stillToImplement,
addHost: addHost,
+ updateDevice: updateDevice,
+ updateLink: stillToImplement,
updateHost: updateHost,
+ removeDevice: stillToImplement,
+ removeLink: stillToImplement,
removeHost: stillToImplement,
showPath: showPath
};
@@ -364,8 +382,6 @@
function addDevice(data) {
var device = data.payload,
nodeData = createDeviceNode(device);
- note('addDevice', device.id);
-
network.nodes.push(nodeData);
network.lookup[nodeData.id] = nodeData;
updateNodes();
@@ -375,10 +391,7 @@
function addLink(data) {
var link = data.payload,
lnk = createLink(link);
-
if (lnk) {
- note('addLink', link.id);
-
network.links.push(lnk);
network.lookup[lnk.id] = lnk;
updateLinks();
@@ -390,8 +403,6 @@
var host = data.payload,
node = createHostNode(host),
lnk;
- note('addHost', node.id);
-
network.nodes.push(node);
network.lookup[host.id] = node;
updateNodes();
@@ -406,13 +417,28 @@
network.force.start();
}
+ function updateDevice(data) {
+ var device = data.payload,
+ id = device.id,
+ nodeData = network.lookup[id];
+ if (nodeData) {
+ $.extend(nodeData, device);
+ updateDeviceState(nodeData);
+ } else {
+ logicError('updateDevice lookup fail. ID = "' + id + '"');
+ }
+ }
+
function updateHost(data) {
var host = data.payload,
- hostData = network.lookup[host.id];
- note('updateHost', host.id);
-
- $.extend(hostData, host);
- updateNodes();
+ id = host.id,
+ hostData = network.lookup[id];
+ if (hostData) {
+ $.extend(hostData, host);
+ updateHostState(hostData);
+ } else {
+ logicError('updateHost lookup fail. ID = "' + id + '"');
+ }
}
function showPath(data) {
@@ -466,9 +492,8 @@
lnk;
if (!dstNode) {
- // TODO: send warning message back to server on websocket
- network.view.alert('switch not on map for link\n\n' +
- 'src = ' + src + '\ndst = ' + dst);
+ logicError('switch not on map for link\n\n' +
+ 'src = ' + src + '\ndst = ' + dst);
return null;
}
@@ -500,9 +525,8 @@
dstNode = network.lookup[dst];
if (!(srcNode && dstNode)) {
- // TODO: send warning message back to server on websocket
- network.view.alert('nodes not on map for link\n\n' +
- 'src = ' + src + '\ndst = ' + dst);
+ logicError('nodes not on map for link\n\n' +
+ 'src = ' + src + '\ndst = ' + dst);
return null;
}
@@ -578,11 +602,12 @@
function createDeviceNode(device) {
// start with the object as is
var node = device,
- type = device.type;
+ type = device.type,
+ svgCls = type ? 'node device ' + type : 'node device';
// Augment as needed...
node.class = 'device';
- node.svgClass = type ? 'node device ' + type : 'node device';
+ node.svgClass = device.online ? svgCls + ' online' : svgCls;
positionNode(node);
// cache label array length
@@ -669,15 +694,24 @@
return (label && label.trim()) ? label : '.';
}
+ function updateDeviceState(nodeData) {
+ nodeData.el.classed('online', nodeData.online);
+ updateDeviceLabel(nodeData);
+ // TODO: review what else might need to be updated
+ }
+
+ function updateHostState(hostData) {
+ updateHostLabel(hostData);
+ // TODO: review what else might need to be updated
+ }
+
+
function updateNodes() {
node = nodeG.selectAll('.node')
.data(network.nodes, function (d) { return d.id; });
// operate on existing nodes, if necessary
// update host labels
- node.filter('.host').select('text')
- .text(hostLabel);
-
//node .foo() .bar() ...
// operate on entering nodes:
@@ -828,7 +862,7 @@
webSock.ws.onmessage = function(m) {
if (m.data) {
- console.log(m.data);
+ wsTraceRx(m.data);
handleServerEvent(JSON.parse(m.data));
}
};
@@ -858,11 +892,28 @@
function sendMessage(evType, payload) {
var toSend = {
- event: evType,
- sid: ++sid,
- payload: payload
- };
- webSock.send(JSON.stringify(toSend));
+ event: evType,
+ sid: ++sid,
+ payload: payload
+ },
+ asText = JSON.stringify(toSend);
+ wsTraceTx(asText);
+ webSock.send(asText);
+ }
+
+ function wsTraceTx(msg) {
+ wsTrace('tx', msg);
+ }
+ function wsTraceRx(msg) {
+ wsTrace('rx', msg);
+ }
+ function wsTrace(rxtx, msg) {
+
+ console.log('[' + rxtx + '] ' + msg);
+ // TODO: integrate with trace view
+ //if (trace) {
+ // trace.output(rxtx, msg);
+ //}
}
@@ -944,12 +995,19 @@
sc.evNumber = 0;
d3.json(urlSc, function(err, data) {
- var p = data && data.params || {};
+ var p = data && data.params || {},
+ desc = data && data.description || null,
+ intro;
+
if (err) {
view.alert('No scenario found:\n\n' + urlSc + '\n\n' + err);
} else {
sc.params = p;
- view.alert("Scenario loaded: " + ctx + '\n\n' + data.title);
+ intro = "Scenario loaded: " + ctx + '\n\n' + data.title;
+ if (desc) {
+ intro += '\n\n ' + desc.join('\n ');
+ }
+ view.alert(intro);
}
});
@@ -967,6 +1025,9 @@
fpad = fcfg.pad,
forceDim = [w - 2*fpad, h - 2*fpad];
+ // TODO: set trace api
+ //trace = onos.exported.webSockTrace;
+
// NOTE: view.$div is a D3 selection of the view's div
svg = view.$div.append('svg');
setSize(svg, view);
diff --git a/web/gui/src/main/webapp/webSockTrace.css b/web/gui/src/main/webapp/webSockTrace.css
new file mode 100644
index 0000000..6669124
--- /dev/null
+++ b/web/gui/src/main/webapp/webSockTrace.css
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ ONOS GUI -- Web Socket Trace -- CSS file
+
+ @author Simon Hunt
+ */
+
+#webSockTrace .toolbar {
+ height: 36px;
+ padding: 4px;
+ vertical-align: baseline;
+ font-size: 12pt;
+ margin-top: 6px;
+}
+
+/* theme-related */
+#webSockTrace .toolbar {
+ background-color: #448;
+ color: #fff;
+}
+
+#webSockTrace .output {
+ overflow-y: scroll;
+}
+
+/* theme-related */
+#webSockTrace .output {
+ background-color: #eef;
+ color: #226;
+}
+
+#webSockTrace .output p {
+ margin: 2px 8px;
+ font-size: 10pt;
+ padding-left: 6px;
+}
+
+/* theme-related */
+#webSockTrace .output p.tx {
+ color: magenta;
+}
+#webSockTrace .output p.rx {
+ color: blue;
+}
+
+
+#webSockTrace .output p.subtitle {
+ margin: 6px 8px;
+ padding-left: 2px;
+ font-size: 12pt;
+ font-weight: bold;
+ font-style: italic;
+}
+
+/* theme-related */
+#webSockTrace .output p.subtitle {
+ color: #626;
+}
diff --git a/web/gui/src/main/webapp/webSockTrace.js b/web/gui/src/main/webapp/webSockTrace.js
new file mode 100644
index 0000000..2f09b31
--- /dev/null
+++ b/web/gui/src/main/webapp/webSockTrace.js
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ View that traces messages across the websocket.
+
+ @author Simon Hunt
+ */
+
+(function (onos) {
+ 'use strict';
+
+ var v,
+ $d,
+ tb,
+ out,
+ which = 'tx',
+ keyDispatch = {
+ space: function () {
+ output(which, "Simon woz 'ere... " + which);
+ which = (which === 'tx') ? 'rx' : 'tx';
+ }
+ };
+
+
+ function addHeader() {
+ tb = $d.append('div')
+ .attr('class', 'toolbar');
+ tb.append('span').text('Web Socket Trace');
+ }
+
+ function addOutput() {
+ out = $d.append('div')
+ .attr('class', 'output');
+ }
+
+ function subtitle(msg) {
+ out.append('p').attr('class', 'subtitle').text(msg);
+ }
+
+ function output(rxtx, msg) {
+ out.append('p').attr('class', rxtx).text(msg);
+ }
+
+ // invoked only the first time the view is loaded
+ function preload(view, ctx, flags) {
+ // NOTE: view.$div is a D3 selection of the view's div
+ v = view;
+ $d = v.$div;
+ addHeader();
+ addOutput();
+
+
+ // hack for now, to allow topo access to our API
+ // TODO: add 'exportApi' and 'importApi' to views.
+ onos.exported.webSockTrace = {
+ subtitle: subtitle,
+ output: output
+ };
+ }
+
+ // invoked just prior to loading the view
+ function reset(view, ctx, flags) {
+
+ }
+
+ // invoked when the view is loaded
+ function load(view, ctx, flags) {
+ resize(view, ctx, flags);
+ view.setKeys(keyDispatch);
+ subtitle('Waiting for messages...');
+ }
+
+ // invoked when the view is resized
+ function resize(view, ctx, flags) {
+ var h = view.height();
+ out.style('height', h + 'px');
+
+ }
+
+ // == register the view here, with links to lifecycle callbacks
+
+ onos.ui.addView('webSockTrace', {
+ preload: preload,
+ load: load,
+ resize: resize
+ });
+
+}(ONOS));