Simon Hunt

GUI - reworked to allow for event-based topology building, in preparation for we…

…b-socket connection to the server.
 - device nodes will enter in a fixed location, if metaUi data is included in the addDevice event.
 - device nodes now adjust their bounds to fit the text (and show an icon).
 - added cycle labels function (press the 'L' key).
 - links now appear with "transition" animation.
 NOTE: this is still WIP.

Change-Id: I3adbe9895e189e482316e86384dd53fd27781cd3
Showing 42 changed files with 918 additions and 2035 deletions
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffffff08",
5 + "type": "roadm",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffffff08",
9 + "FF:FF:FF:FF:FF:08",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 539,
14 + "y": 186
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffffff04",
5 + "type": "roadm",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffffff04",
9 + "FF:FF:FF:FF:FF:04",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 322,
14 + "y": 138
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff000A",
5 + "type": "switch",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffff000A",
9 + "FF:FF:FF:FF:00:0A",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 832,
14 + "y": 223
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff0001",
5 + "type": "switch",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffff0001",
9 + "FF:FF:FF:FF:00:01",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 167,
14 + "y": 403
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffffff01",
5 + "type": "roadm",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffffff01",
9 + "FF:FF:FF:FF:FF:01",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 227,
14 + "y": 460
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff0004",
5 + "type": "switch",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffff0004",
9 + "FF:FF:FF:FF:00:04",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 317,
14 + "y": 73
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffffff0A",
5 + "type": "roadm",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffffff0A",
9 + "FF:FF:FF:FF:FF:0A",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 840,
14 + "y": 290
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffffff09",
5 + "type": "roadm",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffffff09",
9 + "FF:FF:FF:FF:FF:09",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 1010,
14 + "y": 229
15 + }
16 + }
17 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff02",
5 + "srcPort": "20",
6 + "dst": "of:0000ffffffffff05",
7 + "dstPort": "10",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "80 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffff000A",
5 + "srcPort": "2",
6 + "dst": "of:0000ffffffffff0A",
7 + "dstPort": "1",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "100 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff03",
5 + "srcPort": "10",
6 + "dst": "of:0000ffffffffff02",
7 + "dstPort": "10",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffffff03",
5 + "type": "roadm",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffffff03",
9 + "FF:FF:FF:FF:FF:03",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 95,
14 + "y": 225
15 + }
16 + }
17 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff07",
5 + "srcPort": "21",
6 + "dst": "of:0000ffffffffff05",
7 + "dstPort": "20",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffff0001",
5 + "srcPort": "2",
6 + "dst": "of:0000ffffffffff01",
7 + "dstPort": "1",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff09",
5 + "srcPort": "20",
6 + "dst": "of:0000ffffffffff0A",
7 + "dstPort": "20",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff06",
5 + "srcPort": "20",
6 + "dst": "of:0000ffffffffff05",
7 + "dstPort": "30",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff07",
5 + "srcPort": "30",
6 + "dst": "of:0000ffffffffff08",
7 + "dstPort": "20",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff03",
5 + "srcPort": "20",
6 + "dst": "of:0000ffffffffff06",
7 + "dstPort": "10",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff02",
5 + "srcPort": "10",
6 + "dst": "of:0000ffffffffff01",
7 + "dstPort": "10",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff09",
5 + "srcPort": "1",
6 + "dst": "of:0000ffffffff0009",
7 + "dstPort": "2",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff03",
5 + "srcPort": "30",
6 + "dst": "of:0000ffffffffff04",
7 + "dstPort": "10",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff07",
5 + "srcPort": "20",
6 + "dst": "of:0000ffffffffff09",
7 + "dstPort": "10",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff0007",
5 + "type": "switch",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffff0007",
9 + "FF:FF:FF:FF:00:07",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 890,
14 + "y": 375
15 + }
16 + }
17 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff0A",
5 + "srcPort": "10",
6 + "dst": "of:0000ffffffffff08",
7 + "dstPort": "30",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffff0004",
5 + "srcPort": "2",
6 + "dst": "of:0000ffffffffff04",
7 + "dstPort": "1",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff07",
5 + "srcPort": "1",
6 + "dst": "of:0000ffffffff0007",
7 + "dstPort": "2",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffff0003",
5 + "srcPort": "2",
6 + "dst": "of:0000ffffffffff03",
7 + "dstPort": "1",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addLink",
3 + "payload": {
4 + "src": "of:0000ffffffffff06",
5 + "srcPort": "30",
6 + "dst": "of:0000ffffffffff08",
7 + "dstPort": "10",
8 + "type": "optical",
9 + "linkWidth": 2,
10 + "props" : {
11 + "BW": "70 G"
12 + }
13 + }
14 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff0009",
5 + "type": "switch",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffff0009",
9 + "FF:FF:FF:FF:00:09",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 1004,
14 + "y": 163
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffffff02",
5 + "type": "roadm",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffffff02",
9 + "FF:FF:FF:FF:FF:02",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 211,
14 + "y": 307
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffff0003",
5 + "type": "switch",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffff0003",
9 + "FF:FF:FF:FF:00:03",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 114,
14 + "y": 158
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffffff07",
5 + "type": "roadm",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffffff07",
9 + "FF:FF:FF:FF:FF:07",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 925,
14 + "y": 446
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffffff06",
5 + "type": "roadm",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffffff06",
9 + "FF:FF:FF:FF:FF:06",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 336,
14 + "y": 254
15 + }
16 + }
17 +}
1 +{
2 + "event": "addDevice",
3 + "payload": {
4 + "id": "of:0000ffffffffff05",
5 + "type": "roadm",
6 + "online": false,
7 + "labels": [
8 + "0000ffffffffff05",
9 + "FF:FF:FF:FF:FF:05",
10 + "?"
11 + ],
12 + "metaUi": {
13 + "x": 539,
14 + "y": 524
15 + }
16 + }
17 +}
1 -{
2 - "comment": [
3 - "2 links removed from base",
4 - " ff07 - ff09 ",
5 - " ff01 - 0001 "
6 - ],
7 - "devices": [
8 - {
9 - "id": "of:0000ffffffffff08",
10 - "type": "roadm",
11 - "online": false,
12 - "labels": [
13 - "0000ffffffffff08",
14 - "FF:FF:FF:FF:FF:08",
15 - "?"
16 - ]
17 - },
18 - {
19 - "id": "of:0000ffffffffff03",
20 - "type": "roadm",
21 - "online": false,
22 - "labels": [
23 - "0000ffffffffff03",
24 - "FF:FF:FF:FF:FF:03",
25 - "?"
26 - ]
27 - },
28 - {
29 - "id": "of:0000ffffffffff02",
30 - "type": "roadm",
31 - "online": false,
32 - "labels": [
33 - "0000ffffffffff02",
34 - "FF:FF:FF:FF:FF:02",
35 - "?"
36 - ]
37 - },
38 - {
39 - "id": "of:0000ffffffff0003",
40 - "type": "switch",
41 - "online": false,
42 - "labels": [
43 - "0000ffffffff0003",
44 - "FF:FF:FF:FF:00:03",
45 - "?"
46 - ]
47 - },
48 - {
49 - "id": "of:0000ffffffffff07",
50 - "type": "roadm",
51 - "online": false,
52 - "labels": [
53 - "0000ffffffffff07",
54 - "FF:FF:FF:FF:FF:07",
55 - "?"
56 - ]
57 - },
58 - {
59 - "id": "of:0000ffffffffff06",
60 - "type": "roadm",
61 - "online": false,
62 - "labels": [
63 - "0000ffffffffff06",
64 - "FF:FF:FF:FF:FF:06",
65 - "?"
66 - ]
67 - },
68 - {
69 - "id": "of:0000ffffffff0007",
70 - "type": "switch",
71 - "online": false,
72 - "labels": [
73 - "0000ffffffff0007",
74 - "FF:FF:FF:FF:00:07",
75 - "?"
76 - ]
77 - },
78 - {
79 - "id": "of:0000ffffffffff05",
80 - "type": "roadm",
81 - "online": false,
82 - "labels": [
83 - "0000ffffffffff05",
84 - "FF:FF:FF:FF:FF:05",
85 - "?"
86 - ]
87 - },
88 - {
89 - "id": "of:0000ffffffff0009",
90 - "type": "switch",
91 - "online": false,
92 - "labels": [
93 - "0000ffffffff0009",
94 - "FF:FF:FF:FF:00:09",
95 - "?"
96 - ]
97 - },
98 - {
99 - "id": "of:0000ffffffffff04",
100 - "type": "roadm",
101 - "online": false,
102 - "labels": [
103 - "0000ffffffffff04",
104 - "FF:FF:FF:FF:FF:04",
105 - "?"
106 - ]
107 - },
108 - {
109 - "id": "of:0000ffffffff000A",
110 - "type": "switch",
111 - "online": false,
112 - "labels": [
113 - "0000ffffffff000A",
114 - "FF:FF:FF:FF:00:0A",
115 - "?"
116 - ]
117 - },
118 - {
119 - "id": "of:0000ffffffff0001",
120 - "type": "switch",
121 - "online": false,
122 - "labels": [
123 - "0000ffffffff0001",
124 - "FF:FF:FF:FF:00:01",
125 - "?"
126 - ]
127 - },
128 - {
129 - "id": "of:0000ffffffffff01",
130 - "type": "roadm",
131 - "online": false,
132 - "labels": [
133 - "0000ffffffffff01",
134 - "FF:FF:FF:FF:FF:01",
135 - "?"
136 - ]
137 - },
138 - {
139 - "id": "of:0000ffffffff0004",
140 - "type": "switch",
141 - "online": false,
142 - "labels": [
143 - "0000ffffffff0004",
144 - "FF:FF:FF:FF:00:04",
145 - "?"
146 - ]
147 - },
148 - {
149 - "id": "of:0000ffffffffff0A",
150 - "type": "roadm",
151 - "online": false,
152 - "labels": [
153 - "0000ffffffffff0A",
154 - "FF:FF:FF:FF:FF:0A",
155 - "?"
156 - ]
157 - },
158 - {
159 - "id": "of:0000ffffffffff09",
160 - "type": "roadm",
161 - "online": false,
162 - "labels": [
163 - "0000ffffffffff09",
164 - "FF:FF:FF:FF:FF:09",
165 - "?"
166 - ]
167 - }
168 - ],
169 - "links": [
170 - {
171 - "src": "of:0000ffffffffff02",
172 - "srcPort": "20",
173 - "dst": "of:0000ffffffffff05",
174 - "dstPort": "10",
175 - "type": "optical",
176 - "linkWidth": 2
177 - },
178 - {
179 - "src": "of:0000ffffffff000A",
180 - "srcPort": "2",
181 - "dst": "of:0000ffffffffff0A",
182 - "dstPort": "1",
183 - "type": "optical",
184 - "linkWidth": 2
185 - },
186 - {
187 - "src": "of:0000ffffffffff03",
188 - "srcPort": "10",
189 - "dst": "of:0000ffffffffff02",
190 - "dstPort": "10",
191 - "type": "optical",
192 - "linkWidth": 2
193 - },
194 - {
195 - "src": "of:0000ffffffffff07",
196 - "srcPort": "21",
197 - "dst": "of:0000ffffffffff05",
198 - "dstPort": "20",
199 - "type": "optical",
200 - "linkWidth": 2
201 - },
202 - {
203 - "src": "of:0000ffffffffff09",
204 - "srcPort": "20",
205 - "dst": "of:0000ffffffffff0A",
206 - "dstPort": "20",
207 - "type": "optical",
208 - "linkWidth": 2
209 - },
210 - {
211 - "src": "of:0000ffffffffff06",
212 - "srcPort": "20",
213 - "dst": "of:0000ffffffffff05",
214 - "dstPort": "30",
215 - "type": "optical",
216 - "linkWidth": 2
217 - },
218 - {
219 - "src": "of:0000ffffffffff07",
220 - "srcPort": "30",
221 - "dst": "of:0000ffffffffff08",
222 - "dstPort": "20",
223 - "type": "optical",
224 - "linkWidth": 2
225 - },
226 - {
227 - "src": "of:0000ffffffffff03",
228 - "srcPort": "20",
229 - "dst": "of:0000ffffffffff06",
230 - "dstPort": "10",
231 - "type": "optical",
232 - "linkWidth": 2
233 - },
234 - {
235 - "src": "of:0000ffffffffff02",
236 - "srcPort": "10",
237 - "dst": "of:0000ffffffffff01",
238 - "dstPort": "10",
239 - "type": "optical",
240 - "linkWidth": 2
241 - },
242 - {
243 - "src": "of:0000ffffffffff09",
244 - "srcPort": "1",
245 - "dst": "of:0000ffffffff0009",
246 - "dstPort": "2",
247 - "type": "optical",
248 - "linkWidth": 2
249 - },
250 - {
251 - "src": "of:0000ffffffffff03",
252 - "srcPort": "30",
253 - "dst": "of:0000ffffffffff04",
254 - "dstPort": "10",
255 - "type": "optical",
256 - "linkWidth": 2
257 - },
258 - {
259 - "src": "of:0000ffffffffff0A",
260 - "srcPort": "10",
261 - "dst": "of:0000ffffffffff08",
262 - "dstPort": "30",
263 - "type": "optical",
264 - "linkWidth": 2
265 - },
266 - {
267 - "src": "of:0000ffffffff0004",
268 - "srcPort": "2",
269 - "dst": "of:0000ffffffffff04",
270 - "dstPort": "1",
271 - "type": "optical",
272 - "linkWidth": 2
273 - },
274 - {
275 - "src": "of:0000ffffffffff07",
276 - "srcPort": "1",
277 - "dst": "of:0000ffffffff0007",
278 - "dstPort": "2",
279 - "type": "optical",
280 - "linkWidth": 2
281 - },
282 - {
283 - "src": "of:0000ffffffff0003",
284 - "srcPort": "2",
285 - "dst": "of:0000ffffffffff03",
286 - "dstPort": "1",
287 - "type": "optical",
288 - "linkWidth": 2
289 - },
290 - {
291 - "src": "of:0000ffffffffff06",
292 - "srcPort": "30",
293 - "dst": "of:0000ffffffffff08",
294 - "dstPort": "10",
295 - "type": "optical",
296 - "linkWidth": 2
297 - }
298 - ],
299 - "hosts": [
300 - {
301 - "id": "00:00:00:00:00:03/-1",
302 - "cp": {
303 - "device": "of:0000ffffffff0003",
304 - "port": 1
305 - },
306 - "labels": [
307 - "10.0.0.3",
308 - "00:00:00:00:00:03"
309 - ]
310 - },
311 - {
312 - "id": "00:00:00:00:00:04/-1",
313 - "cp": {
314 - "device": "of:0000ffffffff0004",
315 - "port": 1
316 - },
317 - "labels": [
318 - "10.0.0.4",
319 - "00:00:00:00:00:04"
320 - ]
321 - },
322 - {
323 - "id": "00:00:00:00:00:0A/-1",
324 - "cp": {
325 - "device": "of:0000ffffffff000A",
326 - "port": 1
327 - },
328 - "labels": [
329 - "10.0.0.10",
330 - "00:00:00:00:00:0A"
331 - ]
332 - },
333 - {
334 - "id": "00:00:00:00:00:09/-1",
335 - "cp": {
336 - "device": "of:0000ffffffff0009",
337 - "port": 1
338 - },
339 - "labels": [
340 - "10.0.0.9",
341 - "00:00:00:00:00:09"
342 - ]
343 - },
344 - {
345 - "id": "00:00:00:00:00:07/-1",
346 - "cp": {
347 - "device": "of:0000ffffffff0007",
348 - "port": 1
349 - },
350 - "labels": [
351 - "10.0.0.7",
352 - "00:00:00:00:00:07"
353 - ]
354 - },
355 - {
356 - "id": "00:00:00:00:00:01/-1",
357 - "cp": {
358 - "device": "of:0000ffffffff0001",
359 - "port": 1
360 - },
361 - "labels": [
362 - "10.0.0.1",
363 - "00:00:00:00:00:01"
364 - ]
365 - }
366 - ]
367 -}
1 -{
2 - "comment": [
3 - "1 packet switch removed from base",
4 - " 0007 "
5 - ],
6 - "devices": [
7 - {
8 - "id": "of:0000ffffffffff08",
9 - "type": "roadm",
10 - "online": false,
11 - "labels": [
12 - "0000ffffffffff08",
13 - "FF:FF:FF:FF:FF:08",
14 - "?"
15 - ]
16 - },
17 - {
18 - "id": "of:0000ffffffffff03",
19 - "type": "roadm",
20 - "online": false,
21 - "labels": [
22 - "0000ffffffffff03",
23 - "FF:FF:FF:FF:FF:03",
24 - "?"
25 - ]
26 - },
27 - {
28 - "id": "of:0000ffffffffff02",
29 - "type": "roadm",
30 - "online": false,
31 - "labels": [
32 - "0000ffffffffff02",
33 - "FF:FF:FF:FF:FF:02",
34 - "?"
35 - ]
36 - },
37 - {
38 - "id": "of:0000ffffffff0003",
39 - "type": "switch",
40 - "online": false,
41 - "labels": [
42 - "0000ffffffff0003",
43 - "FF:FF:FF:FF:00:03",
44 - "?"
45 - ]
46 - },
47 - {
48 - "id": "of:0000ffffffffff07",
49 - "type": "roadm",
50 - "online": false,
51 - "labels": [
52 - "0000ffffffffff07",
53 - "FF:FF:FF:FF:FF:07",
54 - "?"
55 - ]
56 - },
57 - {
58 - "id": "of:0000ffffffffff06",
59 - "type": "roadm",
60 - "online": false,
61 - "labels": [
62 - "0000ffffffffff06",
63 - "FF:FF:FF:FF:FF:06",
64 - "?"
65 - ]
66 - },
67 - {
68 - "id": "of:0000ffffffffff05",
69 - "type": "roadm",
70 - "online": false,
71 - "labels": [
72 - "0000ffffffffff05",
73 - "FF:FF:FF:FF:FF:05",
74 - "?"
75 - ]
76 - },
77 - {
78 - "id": "of:0000ffffffff0009",
79 - "type": "switch",
80 - "online": false,
81 - "labels": [
82 - "0000ffffffff0009",
83 - "FF:FF:FF:FF:00:09",
84 - "?"
85 - ]
86 - },
87 - {
88 - "id": "of:0000ffffffffff04",
89 - "type": "roadm",
90 - "online": false,
91 - "labels": [
92 - "0000ffffffffff04",
93 - "FF:FF:FF:FF:FF:04",
94 - "?"
95 - ]
96 - },
97 - {
98 - "id": "of:0000ffffffff000A",
99 - "type": "switch",
100 - "online": false,
101 - "labels": [
102 - "0000ffffffff000A",
103 - "FF:FF:FF:FF:00:0A",
104 - "?"
105 - ]
106 - },
107 - {
108 - "id": "of:0000ffffffff0001",
109 - "type": "switch",
110 - "online": false,
111 - "labels": [
112 - "0000ffffffff0001",
113 - "FF:FF:FF:FF:00:01",
114 - "?"
115 - ]
116 - },
117 - {
118 - "id": "of:0000ffffffffff01",
119 - "type": "roadm",
120 - "online": false,
121 - "labels": [
122 - "0000ffffffffff01",
123 - "FF:FF:FF:FF:FF:01",
124 - "?"
125 - ]
126 - },
127 - {
128 - "id": "of:0000ffffffff0004",
129 - "type": "switch",
130 - "online": false,
131 - "labels": [
132 - "0000ffffffff0004",
133 - "FF:FF:FF:FF:00:04",
134 - "?"
135 - ]
136 - },
137 - {
138 - "id": "of:0000ffffffffff0A",
139 - "type": "roadm",
140 - "online": false,
141 - "labels": [
142 - "0000ffffffffff0A",
143 - "FF:FF:FF:FF:FF:0A",
144 - "?"
145 - ]
146 - },
147 - {
148 - "id": "of:0000ffffffffff09",
149 - "type": "roadm",
150 - "online": false,
151 - "labels": [
152 - "0000ffffffffff09",
153 - "FF:FF:FF:FF:FF:09",
154 - "?"
155 - ]
156 - }
157 - ],
158 - "links": [
159 - {
160 - "src": "of:0000ffffffffff02",
161 - "srcPort": "20",
162 - "dst": "of:0000ffffffffff05",
163 - "dstPort": "10",
164 - "type": "optical",
165 - "linkWidth": 2
166 - },
167 - {
168 - "src": "of:0000ffffffff000A",
169 - "srcPort": "2",
170 - "dst": "of:0000ffffffffff0A",
171 - "dstPort": "1",
172 - "type": "optical",
173 - "linkWidth": 2
174 - },
175 - {
176 - "src": "of:0000ffffffffff03",
177 - "srcPort": "10",
178 - "dst": "of:0000ffffffffff02",
179 - "dstPort": "10",
180 - "type": "optical",
181 - "linkWidth": 2
182 - },
183 - {
184 - "src": "of:0000ffffffffff07",
185 - "srcPort": "21",
186 - "dst": "of:0000ffffffffff05",
187 - "dstPort": "20",
188 - "type": "optical",
189 - "linkWidth": 2
190 - },
191 - {
192 - "src": "of:0000ffffffff0001",
193 - "srcPort": "2",
194 - "dst": "of:0000ffffffffff01",
195 - "dstPort": "1",
196 - "type": "optical",
197 - "linkWidth": 2
198 - },
199 - {
200 - "src": "of:0000ffffffffff09",
201 - "srcPort": "20",
202 - "dst": "of:0000ffffffffff0A",
203 - "dstPort": "20",
204 - "type": "optical",
205 - "linkWidth": 2
206 - },
207 - {
208 - "src": "of:0000ffffffffff06",
209 - "srcPort": "20",
210 - "dst": "of:0000ffffffffff05",
211 - "dstPort": "30",
212 - "type": "optical",
213 - "linkWidth": 2
214 - },
215 - {
216 - "src": "of:0000ffffffffff07",
217 - "srcPort": "30",
218 - "dst": "of:0000ffffffffff08",
219 - "dstPort": "20",
220 - "type": "optical",
221 - "linkWidth": 2
222 - },
223 - {
224 - "src": "of:0000ffffffffff03",
225 - "srcPort": "20",
226 - "dst": "of:0000ffffffffff06",
227 - "dstPort": "10",
228 - "type": "optical",
229 - "linkWidth": 2
230 - },
231 - {
232 - "src": "of:0000ffffffffff02",
233 - "srcPort": "10",
234 - "dst": "of:0000ffffffffff01",
235 - "dstPort": "10",
236 - "type": "optical",
237 - "linkWidth": 2
238 - },
239 - {
240 - "src": "of:0000ffffffffff09",
241 - "srcPort": "1",
242 - "dst": "of:0000ffffffff0009",
243 - "dstPort": "2",
244 - "type": "optical",
245 - "linkWidth": 2
246 - },
247 - {
248 - "src": "of:0000ffffffffff03",
249 - "srcPort": "30",
250 - "dst": "of:0000ffffffffff04",
251 - "dstPort": "10",
252 - "type": "optical",
253 - "linkWidth": 2
254 - },
255 - {
256 - "src": "of:0000ffffffffff07",
257 - "srcPort": "20",
258 - "dst": "of:0000ffffffffff09",
259 - "dstPort": "10",
260 - "type": "optical",
261 - "linkWidth": 2
262 - },
263 - {
264 - "src": "of:0000ffffffffff0A",
265 - "srcPort": "10",
266 - "dst": "of:0000ffffffffff08",
267 - "dstPort": "30",
268 - "type": "optical",
269 - "linkWidth": 2
270 - },
271 - {
272 - "src": "of:0000ffffffff0004",
273 - "srcPort": "2",
274 - "dst": "of:0000ffffffffff04",
275 - "dstPort": "1",
276 - "type": "optical",
277 - "linkWidth": 2
278 - },
279 - {
280 - "src": "of:0000ffffffffff07",
281 - "srcPort": "1",
282 - "dst": "of:0000ffffffff0007",
283 - "dstPort": "2",
284 - "type": "optical",
285 - "linkWidth": 2
286 - },
287 - {
288 - "src": "of:0000ffffffff0003",
289 - "srcPort": "2",
290 - "dst": "of:0000ffffffffff03",
291 - "dstPort": "1",
292 - "type": "optical",
293 - "linkWidth": 2
294 - },
295 - {
296 - "src": "of:0000ffffffffff06",
297 - "srcPort": "30",
298 - "dst": "of:0000ffffffffff08",
299 - "dstPort": "10",
300 - "type": "optical",
301 - "linkWidth": 2
302 - }
303 - ],
304 - "hosts": [
305 - {
306 - "id": "00:00:00:00:00:03/-1",
307 - "cp": {
308 - "device": "of:0000ffffffff0003",
309 - "port": 1
310 - },
311 - "labels": [
312 - "10.0.0.3",
313 - "00:00:00:00:00:03"
314 - ]
315 - },
316 - {
317 - "id": "00:00:00:00:00:04/-1",
318 - "cp": {
319 - "device": "of:0000ffffffff0004",
320 - "port": 1
321 - },
322 - "labels": [
323 - "10.0.0.4",
324 - "00:00:00:00:00:04"
325 - ]
326 - },
327 - {
328 - "id": "00:00:00:00:00:0A/-1",
329 - "cp": {
330 - "device": "of:0000ffffffff000A",
331 - "port": 1
332 - },
333 - "labels": [
334 - "10.0.0.10",
335 - "00:00:00:00:00:0A"
336 - ]
337 - },
338 - {
339 - "id": "00:00:00:00:00:09/-1",
340 - "cp": {
341 - "device": "of:0000ffffffff0009",
342 - "port": 1
343 - },
344 - "labels": [
345 - "10.0.0.9",
346 - "00:00:00:00:00:09"
347 - ]
348 - },
349 - {
350 - "id": "00:00:00:00:00:07/-1",
351 - "cp": {
352 - "device": "of:0000ffffffff0007",
353 - "port": 1
354 - },
355 - "labels": [
356 - "10.0.0.7",
357 - "00:00:00:00:00:07"
358 - ]
359 - },
360 - {
361 - "id": "00:00:00:00:00:01/-1",
362 - "cp": {
363 - "device": "of:0000ffffffff0001",
364 - "port": 1
365 - },
366 - "labels": [
367 - "10.0.0.1",
368 - "00:00:00:00:00:01"
369 - ]
370 - }
371 - ]
372 -}
1 -{
2 - "comment": [
3 - "1 optical switch removed from base",
4 - " ff07 "
5 - ],
6 - "devices": [
7 - {
8 - "id": "of:0000ffffffffff08",
9 - "type": "roadm",
10 - "online": false,
11 - "labels": [
12 - "0000ffffffffff08",
13 - "FF:FF:FF:FF:FF:08",
14 - "?"
15 - ]
16 - },
17 - {
18 - "id": "of:0000ffffffffff03",
19 - "type": "roadm",
20 - "online": false,
21 - "labels": [
22 - "0000ffffffffff03",
23 - "FF:FF:FF:FF:FF:03",
24 - "?"
25 - ]
26 - },
27 - {
28 - "id": "of:0000ffffffffff02",
29 - "type": "roadm",
30 - "online": false,
31 - "labels": [
32 - "0000ffffffffff02",
33 - "FF:FF:FF:FF:FF:02",
34 - "?"
35 - ]
36 - },
37 - {
38 - "id": "of:0000ffffffff0003",
39 - "type": "switch",
40 - "online": false,
41 - "labels": [
42 - "0000ffffffff0003",
43 - "FF:FF:FF:FF:00:03",
44 - "?"
45 - ]
46 - },
47 - {
48 - "id": "of:0000ffffffffff06",
49 - "type": "roadm",
50 - "online": false,
51 - "labels": [
52 - "0000ffffffffff06",
53 - "FF:FF:FF:FF:FF:06",
54 - "?"
55 - ]
56 - },
57 - {
58 - "id": "of:0000ffffffff0007",
59 - "type": "switch",
60 - "online": false,
61 - "labels": [
62 - "0000ffffffff0007",
63 - "FF:FF:FF:FF:00:07",
64 - "?"
65 - ]
66 - },
67 - {
68 - "id": "of:0000ffffffffff05",
69 - "type": "roadm",
70 - "online": false,
71 - "labels": [
72 - "0000ffffffffff05",
73 - "FF:FF:FF:FF:FF:05",
74 - "?"
75 - ]
76 - },
77 - {
78 - "id": "of:0000ffffffff0009",
79 - "type": "switch",
80 - "online": false,
81 - "labels": [
82 - "0000ffffffff0009",
83 - "FF:FF:FF:FF:00:09",
84 - "?"
85 - ]
86 - },
87 - {
88 - "id": "of:0000ffffffffff04",
89 - "type": "roadm",
90 - "online": false,
91 - "labels": [
92 - "0000ffffffffff04",
93 - "FF:FF:FF:FF:FF:04",
94 - "?"
95 - ]
96 - },
97 - {
98 - "id": "of:0000ffffffff000A",
99 - "type": "switch",
100 - "online": false,
101 - "labels": [
102 - "0000ffffffff000A",
103 - "FF:FF:FF:FF:00:0A",
104 - "?"
105 - ]
106 - },
107 - {
108 - "id": "of:0000ffffffff0001",
109 - "type": "switch",
110 - "online": false,
111 - "labels": [
112 - "0000ffffffff0001",
113 - "FF:FF:FF:FF:00:01",
114 - "?"
115 - ]
116 - },
117 - {
118 - "id": "of:0000ffffffffff01",
119 - "type": "roadm",
120 - "online": false,
121 - "labels": [
122 - "0000ffffffffff01",
123 - "FF:FF:FF:FF:FF:01",
124 - "?"
125 - ]
126 - },
127 - {
128 - "id": "of:0000ffffffff0004",
129 - "type": "switch",
130 - "online": false,
131 - "labels": [
132 - "0000ffffffff0004",
133 - "FF:FF:FF:FF:00:04",
134 - "?"
135 - ]
136 - },
137 - {
138 - "id": "of:0000ffffffffff0A",
139 - "type": "roadm",
140 - "online": false,
141 - "labels": [
142 - "0000ffffffffff0A",
143 - "FF:FF:FF:FF:FF:0A",
144 - "?"
145 - ]
146 - },
147 - {
148 - "id": "of:0000ffffffffff09",
149 - "type": "roadm",
150 - "online": false,
151 - "labels": [
152 - "0000ffffffffff09",
153 - "FF:FF:FF:FF:FF:09",
154 - "?"
155 - ]
156 - }
157 - ],
158 - "links": [
159 - {
160 - "src": "of:0000ffffffffff02",
161 - "srcPort": "20",
162 - "dst": "of:0000ffffffffff05",
163 - "dstPort": "10",
164 - "type": "optical",
165 - "linkWidth": 2
166 - },
167 - {
168 - "src": "of:0000ffffffff000A",
169 - "srcPort": "2",
170 - "dst": "of:0000ffffffffff0A",
171 - "dstPort": "1",
172 - "type": "optical",
173 - "linkWidth": 2
174 - },
175 - {
176 - "src": "of:0000ffffffffff03",
177 - "srcPort": "10",
178 - "dst": "of:0000ffffffffff02",
179 - "dstPort": "10",
180 - "type": "optical",
181 - "linkWidth": 2
182 - },
183 - {
184 - "src": "of:0000ffffffffff07",
185 - "srcPort": "21",
186 - "dst": "of:0000ffffffffff05",
187 - "dstPort": "20",
188 - "type": "optical",
189 - "linkWidth": 2
190 - },
191 - {
192 - "src": "of:0000ffffffff0001",
193 - "srcPort": "2",
194 - "dst": "of:0000ffffffffff01",
195 - "dstPort": "1",
196 - "type": "optical",
197 - "linkWidth": 2
198 - },
199 - {
200 - "src": "of:0000ffffffffff09",
201 - "srcPort": "20",
202 - "dst": "of:0000ffffffffff0A",
203 - "dstPort": "20",
204 - "type": "optical",
205 - "linkWidth": 2
206 - },
207 - {
208 - "src": "of:0000ffffffffff06",
209 - "srcPort": "20",
210 - "dst": "of:0000ffffffffff05",
211 - "dstPort": "30",
212 - "type": "optical",
213 - "linkWidth": 2
214 - },
215 - {
216 - "src": "of:0000ffffffffff07",
217 - "srcPort": "30",
218 - "dst": "of:0000ffffffffff08",
219 - "dstPort": "20",
220 - "type": "optical",
221 - "linkWidth": 2
222 - },
223 - {
224 - "src": "of:0000ffffffffff03",
225 - "srcPort": "20",
226 - "dst": "of:0000ffffffffff06",
227 - "dstPort": "10",
228 - "type": "optical",
229 - "linkWidth": 2
230 - },
231 - {
232 - "src": "of:0000ffffffffff02",
233 - "srcPort": "10",
234 - "dst": "of:0000ffffffffff01",
235 - "dstPort": "10",
236 - "type": "optical",
237 - "linkWidth": 2
238 - },
239 - {
240 - "src": "of:0000ffffffffff09",
241 - "srcPort": "1",
242 - "dst": "of:0000ffffffff0009",
243 - "dstPort": "2",
244 - "type": "optical",
245 - "linkWidth": 2
246 - },
247 - {
248 - "src": "of:0000ffffffffff03",
249 - "srcPort": "30",
250 - "dst": "of:0000ffffffffff04",
251 - "dstPort": "10",
252 - "type": "optical",
253 - "linkWidth": 2
254 - },
255 - {
256 - "src": "of:0000ffffffffff07",
257 - "srcPort": "20",
258 - "dst": "of:0000ffffffffff09",
259 - "dstPort": "10",
260 - "type": "optical",
261 - "linkWidth": 2
262 - },
263 - {
264 - "src": "of:0000ffffffffff0A",
265 - "srcPort": "10",
266 - "dst": "of:0000ffffffffff08",
267 - "dstPort": "30",
268 - "type": "optical",
269 - "linkWidth": 2
270 - },
271 - {
272 - "src": "of:0000ffffffff0004",
273 - "srcPort": "2",
274 - "dst": "of:0000ffffffffff04",
275 - "dstPort": "1",
276 - "type": "optical",
277 - "linkWidth": 2
278 - },
279 - {
280 - "src": "of:0000ffffffffff07",
281 - "srcPort": "1",
282 - "dst": "of:0000ffffffff0007",
283 - "dstPort": "2",
284 - "type": "optical",
285 - "linkWidth": 2
286 - },
287 - {
288 - "src": "of:0000ffffffff0003",
289 - "srcPort": "2",
290 - "dst": "of:0000ffffffffff03",
291 - "dstPort": "1",
292 - "type": "optical",
293 - "linkWidth": 2
294 - },
295 - {
296 - "src": "of:0000ffffffffff06",
297 - "srcPort": "30",
298 - "dst": "of:0000ffffffffff08",
299 - "dstPort": "10",
300 - "type": "optical",
301 - "linkWidth": 2
302 - }
303 - ],
304 - "hosts": [
305 - {
306 - "id": "00:00:00:00:00:03/-1",
307 - "cp": {
308 - "device": "of:0000ffffffff0003",
309 - "port": 1
310 - },
311 - "labels": [
312 - "10.0.0.3",
313 - "00:00:00:00:00:03"
314 - ]
315 - },
316 - {
317 - "id": "00:00:00:00:00:04/-1",
318 - "cp": {
319 - "device": "of:0000ffffffff0004",
320 - "port": 1
321 - },
322 - "labels": [
323 - "10.0.0.4",
324 - "00:00:00:00:00:04"
325 - ]
326 - },
327 - {
328 - "id": "00:00:00:00:00:0A/-1",
329 - "cp": {
330 - "device": "of:0000ffffffff000A",
331 - "port": 1
332 - },
333 - "labels": [
334 - "10.0.0.10",
335 - "00:00:00:00:00:0A"
336 - ]
337 - },
338 - {
339 - "id": "00:00:00:00:00:09/-1",
340 - "cp": {
341 - "device": "of:0000ffffffff0009",
342 - "port": 1
343 - },
344 - "labels": [
345 - "10.0.0.9",
346 - "00:00:00:00:00:09"
347 - ]
348 - },
349 - {
350 - "id": "00:00:00:00:00:07/-1",
351 - "cp": {
352 - "device": "of:0000ffffffff0007",
353 - "port": 1
354 - },
355 - "labels": [
356 - "10.0.0.7",
357 - "00:00:00:00:00:07"
358 - ]
359 - },
360 - {
361 - "id": "00:00:00:00:00:01/-1",
362 - "cp": {
363 - "device": "of:0000ffffffff0001",
364 - "port": 1
365 - },
366 - "labels": [
367 - "10.0.0.1",
368 - "00:00:00:00:00:01"
369 - ]
370 - }
371 - ]
372 -}
1 -{
2 - "comment": [
3 - "3 hosts added to base",
4 - " 2 to 000A, 1 to 0007 "
5 - ],
6 - "devices": [
7 - {
8 - "id": "of:0000ffffffffff08",
9 - "type": "roadm",
10 - "online": false,
11 - "labels": [
12 - "0000ffffffffff08",
13 - "FF:FF:FF:FF:FF:08",
14 - "?"
15 - ]
16 - },
17 - {
18 - "id": "of:0000ffffffffff03",
19 - "type": "roadm",
20 - "online": false,
21 - "labels": [
22 - "0000ffffffffff03",
23 - "FF:FF:FF:FF:FF:03",
24 - "?"
25 - ]
26 - },
27 - {
28 - "id": "of:0000ffffffffff02",
29 - "type": "roadm",
30 - "online": false,
31 - "labels": [
32 - "0000ffffffffff02",
33 - "FF:FF:FF:FF:FF:02",
34 - "?"
35 - ]
36 - },
37 - {
38 - "id": "of:0000ffffffff0003",
39 - "type": "switch",
40 - "online": false,
41 - "labels": [
42 - "0000ffffffff0003",
43 - "FF:FF:FF:FF:00:03",
44 - "?"
45 - ]
46 - },
47 - {
48 - "id": "of:0000ffffffffff07",
49 - "type": "roadm",
50 - "online": false,
51 - "labels": [
52 - "0000ffffffffff07",
53 - "FF:FF:FF:FF:FF:07",
54 - "?"
55 - ]
56 - },
57 - {
58 - "id": "of:0000ffffffffff06",
59 - "type": "roadm",
60 - "online": false,
61 - "labels": [
62 - "0000ffffffffff06",
63 - "FF:FF:FF:FF:FF:06",
64 - "?"
65 - ]
66 - },
67 - {
68 - "id": "of:0000ffffffff0007",
69 - "type": "switch",
70 - "online": false,
71 - "labels": [
72 - "0000ffffffff0007",
73 - "FF:FF:FF:FF:00:07",
74 - "?"
75 - ]
76 - },
77 - {
78 - "id": "of:0000ffffffffff05",
79 - "type": "roadm",
80 - "online": false,
81 - "labels": [
82 - "0000ffffffffff05",
83 - "FF:FF:FF:FF:FF:05",
84 - "?"
85 - ]
86 - },
87 - {
88 - "id": "of:0000ffffffff0009",
89 - "type": "switch",
90 - "online": false,
91 - "labels": [
92 - "0000ffffffff0009",
93 - "FF:FF:FF:FF:00:09",
94 - "?"
95 - ]
96 - },
97 - {
98 - "id": "of:0000ffffffffff04",
99 - "type": "roadm",
100 - "online": false,
101 - "labels": [
102 - "0000ffffffffff04",
103 - "FF:FF:FF:FF:FF:04",
104 - "?"
105 - ]
106 - },
107 - {
108 - "id": "of:0000ffffffff000A",
109 - "type": "switch",
110 - "online": false,
111 - "labels": [
112 - "0000ffffffff000A",
113 - "FF:FF:FF:FF:00:0A",
114 - "?"
115 - ]
116 - },
117 - {
118 - "id": "of:0000ffffffff0001",
119 - "type": "switch",
120 - "online": false,
121 - "labels": [
122 - "0000ffffffff0001",
123 - "FF:FF:FF:FF:00:01",
124 - "?"
125 - ]
126 - },
127 - {
128 - "id": "of:0000ffffffffff01",
129 - "type": "roadm",
130 - "online": false,
131 - "labels": [
132 - "0000ffffffffff01",
133 - "FF:FF:FF:FF:FF:01",
134 - "?"
135 - ]
136 - },
137 - {
138 - "id": "of:0000ffffffff0004",
139 - "type": "switch",
140 - "online": false,
141 - "labels": [
142 - "0000ffffffff0004",
143 - "FF:FF:FF:FF:00:04",
144 - "?"
145 - ]
146 - },
147 - {
148 - "id": "of:0000ffffffffff0A",
149 - "type": "roadm",
150 - "online": false,
151 - "labels": [
152 - "0000ffffffffff0A",
153 - "FF:FF:FF:FF:FF:0A",
154 - "?"
155 - ]
156 - },
157 - {
158 - "id": "of:0000ffffffffff09",
159 - "type": "roadm",
160 - "online": false,
161 - "labels": [
162 - "0000ffffffffff09",
163 - "FF:FF:FF:FF:FF:09",
164 - "?"
165 - ]
166 - }
167 - ],
168 - "links": [
169 - {
170 - "src": "of:0000ffffffffff02",
171 - "srcPort": "20",
172 - "dst": "of:0000ffffffffff05",
173 - "dstPort": "10",
174 - "type": "optical",
175 - "linkWidth": 2
176 - },
177 - {
178 - "src": "of:0000ffffffff000A",
179 - "srcPort": "2",
180 - "dst": "of:0000ffffffffff0A",
181 - "dstPort": "1",
182 - "type": "optical",
183 - "linkWidth": 2
184 - },
185 - {
186 - "src": "of:0000ffffffffff03",
187 - "srcPort": "10",
188 - "dst": "of:0000ffffffffff02",
189 - "dstPort": "10",
190 - "type": "optical",
191 - "linkWidth": 2
192 - },
193 - {
194 - "src": "of:0000ffffffffff07",
195 - "srcPort": "21",
196 - "dst": "of:0000ffffffffff05",
197 - "dstPort": "20",
198 - "type": "optical",
199 - "linkWidth": 2
200 - },
201 - {
202 - "src": "of:0000ffffffff0001",
203 - "srcPort": "2",
204 - "dst": "of:0000ffffffffff01",
205 - "dstPort": "1",
206 - "type": "optical",
207 - "linkWidth": 2
208 - },
209 - {
210 - "src": "of:0000ffffffffff09",
211 - "srcPort": "20",
212 - "dst": "of:0000ffffffffff0A",
213 - "dstPort": "20",
214 - "type": "optical",
215 - "linkWidth": 2
216 - },
217 - {
218 - "src": "of:0000ffffffffff06",
219 - "srcPort": "20",
220 - "dst": "of:0000ffffffffff05",
221 - "dstPort": "30",
222 - "type": "optical",
223 - "linkWidth": 2
224 - },
225 - {
226 - "src": "of:0000ffffffffff07",
227 - "srcPort": "30",
228 - "dst": "of:0000ffffffffff08",
229 - "dstPort": "20",
230 - "type": "optical",
231 - "linkWidth": 2
232 - },
233 - {
234 - "src": "of:0000ffffffffff03",
235 - "srcPort": "20",
236 - "dst": "of:0000ffffffffff06",
237 - "dstPort": "10",
238 - "type": "optical",
239 - "linkWidth": 2
240 - },
241 - {
242 - "src": "of:0000ffffffffff02",
243 - "srcPort": "10",
244 - "dst": "of:0000ffffffffff01",
245 - "dstPort": "10",
246 - "type": "optical",
247 - "linkWidth": 2
248 - },
249 - {
250 - "src": "of:0000ffffffffff09",
251 - "srcPort": "1",
252 - "dst": "of:0000ffffffff0009",
253 - "dstPort": "2",
254 - "type": "optical",
255 - "linkWidth": 2
256 - },
257 - {
258 - "src": "of:0000ffffffffff03",
259 - "srcPort": "30",
260 - "dst": "of:0000ffffffffff04",
261 - "dstPort": "10",
262 - "type": "optical",
263 - "linkWidth": 2
264 - },
265 - {
266 - "src": "of:0000ffffffffff07",
267 - "srcPort": "20",
268 - "dst": "of:0000ffffffffff09",
269 - "dstPort": "10",
270 - "type": "optical",
271 - "linkWidth": 2
272 - },
273 - {
274 - "src": "of:0000ffffffffff0A",
275 - "srcPort": "10",
276 - "dst": "of:0000ffffffffff08",
277 - "dstPort": "30",
278 - "type": "optical",
279 - "linkWidth": 2
280 - },
281 - {
282 - "src": "of:0000ffffffff0004",
283 - "srcPort": "2",
284 - "dst": "of:0000ffffffffff04",
285 - "dstPort": "1",
286 - "type": "optical",
287 - "linkWidth": 2
288 - },
289 - {
290 - "src": "of:0000ffffffffff07",
291 - "srcPort": "1",
292 - "dst": "of:0000ffffffff0007",
293 - "dstPort": "2",
294 - "type": "optical",
295 - "linkWidth": 2
296 - },
297 - {
298 - "src": "of:0000ffffffff0003",
299 - "srcPort": "2",
300 - "dst": "of:0000ffffffffff03",
301 - "dstPort": "1",
302 - "type": "optical",
303 - "linkWidth": 2
304 - },
305 - {
306 - "src": "of:0000ffffffffff06",
307 - "srcPort": "30",
308 - "dst": "of:0000ffffffffff08",
309 - "dstPort": "10",
310 - "type": "optical",
311 - "linkWidth": 2
312 - }
313 - ],
314 - "hosts": [
315 - {
316 - "id": "00:00:00:00:00:03/-1",
317 - "cp": {
318 - "device": "of:0000ffffffff0003",
319 - "port": 1
320 - },
321 - "labels": [
322 - "10.0.0.3",
323 - "00:00:00:00:00:03"
324 - ]
325 - },
326 - {
327 - "id": "00:00:00:00:00:04/-1",
328 - "cp": {
329 - "device": "of:0000ffffffff0004",
330 - "port": 1
331 - },
332 - "labels": [
333 - "10.0.0.4",
334 - "00:00:00:00:00:04"
335 - ]
336 - },
337 - {
338 - "id": "00:00:00:00:00:0A/-1",
339 - "cp": {
340 - "device": "of:0000ffffffff000A",
341 - "port": 1
342 - },
343 - "labels": [
344 - "10.0.0.10",
345 - "00:00:00:00:00:0A"
346 - ]
347 - },
348 - {
349 - "id": "00:00:00:00:65:0A/-1",
350 - "cp": {
351 - "device": "of:0000ffffffff000A",
352 - "port": 101
353 - },
354 - "labels": [
355 - "10.0.0.101",
356 - "00:00:00:00:65:0A"
357 - ]
358 - },
359 - {
360 - "id": "00:00:00:00:66:0A/-1",
361 - "cp": {
362 - "device": "of:0000ffffffff000A",
363 - "port": 102
364 - },
365 - "labels": [
366 - "10.0.0.102",
367 - "00:00:00:00:66:0A"
368 - ]
369 - },
370 - {
371 - "id": "00:00:00:00:00:09/-1",
372 - "cp": {
373 - "device": "of:0000ffffffff0009",
374 - "port": 1
375 - },
376 - "labels": [
377 - "10.0.0.9",
378 - "00:00:00:00:00:09"
379 - ]
380 - },
381 - {
382 - "id": "00:00:00:00:00:07/-1",
383 - "cp": {
384 - "device": "of:0000ffffffff0007",
385 - "port": 1
386 - },
387 - "labels": [
388 - "10.0.0.7",
389 - "00:00:00:00:00:07"
390 - ]
391 - },
392 - {
393 - "id": "00:00:00:00:67:07/-1",
394 - "cp": {
395 - "device": "of:0000ffffffff0007",
396 - "port": 103
397 - },
398 - "labels": [
399 - "10.0.0.73",
400 - "00:00:00:00:67:07"
401 - ]
402 - },
403 - {
404 - "id": "00:00:00:00:00:01/-1",
405 - "cp": {
406 - "device": "of:0000ffffffff0001",
407 - "port": 1
408 - },
409 - "labels": [
410 - "10.0.0.1",
411 - "00:00:00:00:00:01"
412 - ]
413 - }
414 - ]
415 -}
1 -{
2 - "devices": [
3 - {
4 - "id": "of:0000ffffffffff08",
5 - "type": "roadm",
6 - "online": false,
7 - "labels": [
8 - "0000ffffffffff08",
9 - "FF:FF:FF:FF:FF:08",
10 - "?"
11 - ]
12 - },
13 - {
14 - "id": "of:0000ffffffffff03",
15 - "type": "roadm",
16 - "online": false,
17 - "labels": [
18 - "0000ffffffffff03",
19 - "FF:FF:FF:FF:FF:03",
20 - "?"
21 - ]
22 - },
23 - {
24 - "id": "of:0000ffffffffff02",
25 - "type": "roadm",
26 - "online": false,
27 - "labels": [
28 - "0000ffffffffff02",
29 - "FF:FF:FF:FF:FF:02",
30 - "?"
31 - ]
32 - },
33 - {
34 - "id": "of:0000ffffffff0003",
35 - "type": "switch",
36 - "online": false,
37 - "labels": [
38 - "0000ffffffff0003",
39 - "FF:FF:FF:FF:00:03",
40 - "?"
41 - ]
42 - },
43 - {
44 - "id": "of:0000ffffffffff07",
45 - "type": "roadm",
46 - "online": false,
47 - "labels": [
48 - "0000ffffffffff07",
49 - "FF:FF:FF:FF:FF:07",
50 - "?"
51 - ]
52 - },
53 - {
54 - "id": "of:0000ffffffffff06",
55 - "type": "roadm",
56 - "online": false,
57 - "labels": [
58 - "0000ffffffffff06",
59 - "FF:FF:FF:FF:FF:06",
60 - "?"
61 - ]
62 - },
63 - {
64 - "id": "of:0000ffffffff0007",
65 - "type": "switch",
66 - "online": false,
67 - "labels": [
68 - "0000ffffffff0007",
69 - "FF:FF:FF:FF:00:07",
70 - "?"
71 - ]
72 - },
73 - {
74 - "id": "of:0000ffffffffff05",
75 - "type": "roadm",
76 - "online": false,
77 - "labels": [
78 - "0000ffffffffff05",
79 - "FF:FF:FF:FF:FF:05",
80 - "?"
81 - ]
82 - },
83 - {
84 - "id": "of:0000ffffffff0009",
85 - "type": "switch",
86 - "online": false,
87 - "labels": [
88 - "0000ffffffff0009",
89 - "FF:FF:FF:FF:00:09",
90 - "?"
91 - ]
92 - },
93 - {
94 - "id": "of:0000ffffffffff04",
95 - "type": "roadm",
96 - "online": false,
97 - "labels": [
98 - "0000ffffffffff04",
99 - "FF:FF:FF:FF:FF:04",
100 - "?"
101 - ]
102 - },
103 - {
104 - "id": "of:0000ffffffff000A",
105 - "type": "switch",
106 - "online": false,
107 - "labels": [
108 - "0000ffffffff000A",
109 - "FF:FF:FF:FF:00:0A",
110 - "?"
111 - ]
112 - },
113 - {
114 - "id": "of:0000ffffffff0001",
115 - "type": "switch",
116 - "online": false,
117 - "labels": [
118 - "0000ffffffff0001",
119 - "FF:FF:FF:FF:00:01",
120 - "?"
121 - ]
122 - },
123 - {
124 - "id": "of:0000ffffffffff01",
125 - "type": "roadm",
126 - "online": false,
127 - "labels": [
128 - "0000ffffffffff01",
129 - "FF:FF:FF:FF:FF:01",
130 - "?"
131 - ]
132 - },
133 - {
134 - "id": "of:0000ffffffff0004",
135 - "type": "switch",
136 - "online": false,
137 - "labels": [
138 - "0000ffffffff0004",
139 - "FF:FF:FF:FF:00:04",
140 - "?"
141 - ]
142 - },
143 - {
144 - "id": "of:0000ffffffffff0A",
145 - "type": "roadm",
146 - "online": false,
147 - "labels": [
148 - "0000ffffffffff0A",
149 - "FF:FF:FF:FF:FF:0A",
150 - "?"
151 - ]
152 - },
153 - {
154 - "id": "of:0000ffffffffff09",
155 - "type": "roadm",
156 - "online": false,
157 - "labels": [
158 - "0000ffffffffff09",
159 - "FF:FF:FF:FF:FF:09",
160 - "?"
161 - ]
162 - }
163 - ],
164 - "links": [
165 - {
166 - "src": "of:0000ffffffffff02",
167 - "srcPort": "20",
168 - "dst": "of:0000ffffffffff05",
169 - "dstPort": "10",
170 - "type": "optical",
171 - "linkWidth": 2
172 - },
173 - {
174 - "src": "of:0000ffffffff000A",
175 - "srcPort": "2",
176 - "dst": "of:0000ffffffffff0A",
177 - "dstPort": "1",
178 - "type": "optical",
179 - "linkWidth": 2
180 - },
181 - {
182 - "src": "of:0000ffffffffff03",
183 - "srcPort": "10",
184 - "dst": "of:0000ffffffffff02",
185 - "dstPort": "10",
186 - "type": "optical",
187 - "linkWidth": 2
188 - },
189 - {
190 - "src": "of:0000ffffffffff07",
191 - "srcPort": "21",
192 - "dst": "of:0000ffffffffff05",
193 - "dstPort": "20",
194 - "type": "optical",
195 - "linkWidth": 2
196 - },
197 - {
198 - "src": "of:0000ffffffff0001",
199 - "srcPort": "2",
200 - "dst": "of:0000ffffffffff01",
201 - "dstPort": "1",
202 - "type": "optical",
203 - "linkWidth": 2
204 - },
205 - {
206 - "src": "of:0000ffffffffff09",
207 - "srcPort": "20",
208 - "dst": "of:0000ffffffffff0A",
209 - "dstPort": "20",
210 - "type": "optical",
211 - "linkWidth": 2
212 - },
213 - {
214 - "src": "of:0000ffffffffff06",
215 - "srcPort": "20",
216 - "dst": "of:0000ffffffffff05",
217 - "dstPort": "30",
218 - "type": "optical",
219 - "linkWidth": 2
220 - },
221 - {
222 - "src": "of:0000ffffffffff07",
223 - "srcPort": "30",
224 - "dst": "of:0000ffffffffff08",
225 - "dstPort": "20",
226 - "type": "optical",
227 - "linkWidth": 2
228 - },
229 - {
230 - "src": "of:0000ffffffffff03",
231 - "srcPort": "20",
232 - "dst": "of:0000ffffffffff06",
233 - "dstPort": "10",
234 - "type": "optical",
235 - "linkWidth": 2
236 - },
237 - {
238 - "src": "of:0000ffffffffff02",
239 - "srcPort": "10",
240 - "dst": "of:0000ffffffffff01",
241 - "dstPort": "10",
242 - "type": "optical",
243 - "linkWidth": 2
244 - },
245 - {
246 - "src": "of:0000ffffffffff09",
247 - "srcPort": "1",
248 - "dst": "of:0000ffffffff0009",
249 - "dstPort": "2",
250 - "type": "optical",
251 - "linkWidth": 2
252 - },
253 - {
254 - "src": "of:0000ffffffffff03",
255 - "srcPort": "30",
256 - "dst": "of:0000ffffffffff04",
257 - "dstPort": "10",
258 - "type": "optical",
259 - "linkWidth": 2
260 - },
261 - {
262 - "src": "of:0000ffffffffff07",
263 - "srcPort": "20",
264 - "dst": "of:0000ffffffffff09",
265 - "dstPort": "10",
266 - "type": "optical",
267 - "linkWidth": 2
268 - },
269 - {
270 - "src": "of:0000ffffffffff0A",
271 - "srcPort": "10",
272 - "dst": "of:0000ffffffffff08",
273 - "dstPort": "30",
274 - "type": "optical",
275 - "linkWidth": 2
276 - },
277 - {
278 - "src": "of:0000ffffffff0004",
279 - "srcPort": "2",
280 - "dst": "of:0000ffffffffff04",
281 - "dstPort": "1",
282 - "type": "optical",
283 - "linkWidth": 2
284 - },
285 - {
286 - "src": "of:0000ffffffffff07",
287 - "srcPort": "1",
288 - "dst": "of:0000ffffffff0007",
289 - "dstPort": "2",
290 - "type": "optical",
291 - "linkWidth": 2
292 - },
293 - {
294 - "src": "of:0000ffffffff0003",
295 - "srcPort": "2",
296 - "dst": "of:0000ffffffffff03",
297 - "dstPort": "1",
298 - "type": "optical",
299 - "linkWidth": 2
300 - },
301 - {
302 - "src": "of:0000ffffffffff06",
303 - "srcPort": "30",
304 - "dst": "of:0000ffffffffff08",
305 - "dstPort": "10",
306 - "type": "optical",
307 - "linkWidth": 2
308 - }
309 - ],
310 - "hosts": [
311 - {
312 - "id": "00:00:00:00:00:03/-1",
313 - "cp": {
314 - "device": "of:0000ffffffff0003",
315 - "port": 1
316 - },
317 - "labels": [
318 - "10.0.0.3",
319 - "00:00:00:00:00:03"
320 - ]
321 - },
322 - {
323 - "id": "00:00:00:00:00:04/-1",
324 - "cp": {
325 - "device": "of:0000ffffffff0004",
326 - "port": 1
327 - },
328 - "labels": [
329 - "10.0.0.4",
330 - "00:00:00:00:00:04"
331 - ]
332 - },
333 - {
334 - "id": "00:00:00:00:00:0A/-1",
335 - "cp": {
336 - "device": "of:0000ffffffff000A",
337 - "port": 1
338 - },
339 - "labels": [
340 - "10.0.0.10",
341 - "00:00:00:00:00:0A"
342 - ]
343 - },
344 - {
345 - "id": "00:00:00:00:00:09/-1",
346 - "cp": {
347 - "device": "of:0000ffffffff0009",
348 - "port": 1
349 - },
350 - "labels": [
351 - "10.0.0.9",
352 - "00:00:00:00:00:09"
353 - ]
354 - },
355 - {
356 - "id": "00:00:00:00:00:07/-1",
357 - "cp": {
358 - "device": "of:0000ffffffff0007",
359 - "port": 1
360 - },
361 - "labels": [
362 - "10.0.0.7",
363 - "00:00:00:00:00:07"
364 - ]
365 - },
366 - {
367 - "id": "00:00:00:00:00:01/-1",
368 - "cp": {
369 - "device": "of:0000ffffffff0001",
370 - "port": 1
371 - },
372 - "labels": [
373 - "10.0.0.1",
374 - "00:00:00:00:00:01"
375 - ]
376 - }
377 - ]
378 -}
...@@ -55,19 +55,10 @@ svg #bg { ...@@ -55,19 +55,10 @@ svg #bg {
55 */ 55 */
56 56
57 svg .link { 57 svg .link {
58 - fill: none;
59 - stroke: #666;
60 - stroke-width: 2.0px;
61 opacity: .7; 58 opacity: .7;
62 -
63 - transition: opacity 250ms;
64 - -webkit-transition: opacity 250ms;
65 - -moz-transition: opacity 250ms;
66 } 59 }
67 60
68 svg .link.host { 61 svg .link.host {
69 - stroke: #666;
70 - stroke-width: 1px;
71 } 62 }
72 63
73 svg g.portLayer rect.port { 64 svg g.portLayer rect.port {
...@@ -81,10 +72,6 @@ svg g.portLayer text { ...@@ -81,10 +72,6 @@ svg g.portLayer text {
81 72
82 svg .node.device rect { 73 svg .node.device rect {
83 stroke-width: 1.5px; 74 stroke-width: 1.5px;
84 -
85 - transition: opacity 250ms;
86 - -webkit-transition: opacity 250ms;
87 - -moz-transition: opacity 250ms;
88 } 75 }
89 76
90 svg .node.device.fixed rect { 77 svg .node.device.fixed rect {
......
...@@ -24,6 +24,34 @@ svg #topo-bg { ...@@ -24,6 +24,34 @@ svg #topo-bg {
24 opacity: 0.5; 24 opacity: 0.5;
25 } 25 }
26 26
27 -svg .node { 27 +svg .node.device {
28 + stroke: none;
29 + stroke-width: 1.5px;
30 + cursor: pointer;
31 +}
32 +
33 +svg .node.device.fixed rect {
34 + stroke-width: 1.5;
35 + stroke: #ccc;
36 +}
37 +
38 +svg .node.device.switch {
39 + fill: #17f;
40 +}
41 +
42 +svg .node.device.roadm {
28 fill: #03c; 43 fill: #03c;
29 } 44 }
45 +
46 +svg .node text {
47 + stroke: none;
48 + fill: white;
49 + font: 10pt sans-serif;
50 + pointer-events: none;
51 +}
52 +
53 +/* for debugging */
54 +svg .node circle.debug {
55 + fill: white;
56 + stroke: red;
57 +}
......
...@@ -25,11 +25,11 @@ ...@@ -25,11 +25,11 @@
25 25
26 // configuration data 26 // configuration data
27 var config = { 27 var config = {
28 - useLiveData: true, 28 + useLiveData: false,
29 debugOn: false, 29 debugOn: false,
30 debug: { 30 debug: {
31 - showNodeXY: false, 31 + showNodeXY: true,
32 - showKeyHandler: true 32 + showKeyHandler: false
33 }, 33 },
34 options: { 34 options: {
35 layering: true, 35 layering: true,
...@@ -49,6 +49,24 @@ ...@@ -49,6 +49,24 @@
49 detailSuffix: '.json' 49 detailSuffix: '.json'
50 } 50 }
51 }, 51 },
52 + labels: {
53 + imgPad: 16,
54 + padLR: 4,
55 + padTB: 3,
56 + marginLR: 3,
57 + marginTB: 2,
58 + port: {
59 + gap: 3,
60 + width: 18,
61 + height: 14
62 + }
63 + },
64 + icons: {
65 + w: 28,
66 + h: 28,
67 + xoff: -12,
68 + yoff: -8
69 + },
52 iconUrl: { 70 iconUrl: {
53 device: 'img/device.png', 71 device: 'img/device.png',
54 host: 'img/host.png', 72 host: 'img/host.png',
...@@ -87,7 +105,9 @@ ...@@ -87,7 +105,9 @@
87 105
88 // key bindings 106 // key bindings
89 var keyDispatch = { 107 var keyDispatch = {
90 - Q: getUpdatedNetworkData, 108 + space: injectTestEvent, // TODO: remove (testing only)
109 + // M: testMe, // TODO: remove (testing only)
110 +
91 B: toggleBg, 111 B: toggleBg,
92 G: toggleLayout, 112 G: toggleLayout,
93 L: cycleLabels, 113 L: cycleLabels,
...@@ -96,7 +116,12 @@ ...@@ -96,7 +116,12 @@
96 }; 116 };
97 117
98 // state variables 118 // state variables
99 - var network = {}, 119 + var network = {
120 + nodes: [],
121 + links: [],
122 + lookup: {}
123 + },
124 + labelIdx = 0,
100 selected = {}, 125 selected = {},
101 highlighted = null, 126 highlighted = null,
102 hovered = null, 127 hovered = null,
...@@ -115,32 +140,51 @@ ...@@ -115,32 +140,51 @@
115 // ============================== 140 // ==============================
116 // For Debugging / Development 141 // For Debugging / Development
117 142
118 - var topoPrefix = 'json/topoTest_', 143 + var eventPrefix = 'json/eventTest_',
119 - lastFlavor = 4, 144 + eventNumber = 0;
120 - topoBase = true,
121 - topoFlavor = 1;
122 145
123 - function nextTopo() { 146 + function note(label, msg) {
124 - if (topoBase) { 147 + console.log('NOTE: ' + label + ': ' + msg);
125 - topoBase = false;
126 - } else {
127 - topoBase = true;
128 - topoFlavor = (topoFlavor === lastFlavor) ? 1 : topoFlavor + 1
129 - }
130 } 148 }
131 149
132 - // TODO change this to return the live data URL 150 + function debug(what) {
133 - function getTopoUrl() { 151 + return config.debugOn && config.debug[what];
134 - var suffix = topoBase ? 'base' : topoFlavor;
135 - return topoPrefix + suffix + '.json';
136 } 152 }
137 153
154 +
138 // ============================== 155 // ==============================
139 // Key Callbacks 156 // Key Callbacks
140 157
141 - function getUpdatedNetworkData(view) { 158 + function testMe(view) {
142 - nextTopo(); 159 + svg.append('line')
143 - getNetworkData(view); 160 + .attr({
161 + x1: 100,
162 + y1: 100,
163 + x2: 500,
164 + y2: 400,
165 + stroke: '#2f3',
166 + 'stroke-width': 8
167 + })
168 + .transition()
169 + .duration(1200)
170 + .attr({
171 + stroke: '#666',
172 + 'stroke-width': 6
173 + });
174 + }
175 +
176 + function injectTestEvent(view) {
177 + eventNumber++;
178 + var eventUrl = eventPrefix + eventNumber + '.json';
179 +
180 + console.log('Fetching JSON: ' + eventUrl);
181 + d3.json(eventUrl, function(err, data) {
182 + if (err) {
183 + view.dataLoadError(err, eventUrl);
184 + } else {
185 + handleServerEvent(data);
186 + }
187 + });
144 } 188 }
145 189
146 function toggleBg() { 190 function toggleBg() {
...@@ -152,8 +196,30 @@ ...@@ -152,8 +196,30 @@
152 196
153 } 197 }
154 198
155 - function cycleLabels(view) { 199 + function cycleLabels() {
156 - 200 + labelIdx = (labelIdx === network.deviceLabelCount - 1) ? 0 : labelIdx + 1;
201 + network.nodes.forEach(function (d) {
202 + var idx = (labelIdx < d.labels.length) ? labelIdx : 0,
203 + node = d3.select('#' + safeId(d.id)),
204 + box;
205 +
206 + node.select('text')
207 + .text(d.labels[idx])
208 + .style('opacity', 0)
209 + .transition()
210 + .style('opacity', 1);
211 +
212 + box = adjustRectToFitText(node);
213 +
214 + node.select('rect')
215 + .transition()
216 + .attr(box);
217 +
218 + node.select('image')
219 + .transition()
220 + .attr('x', box.x + config.icons.xoff)
221 + .attr('y', box.y + config.icons.yoff);
222 + });
157 } 223 }
158 224
159 function togglePorts(view) { 225 function togglePorts(view) {
...@@ -191,6 +257,10 @@ ...@@ -191,6 +257,10 @@
191 // ============================== 257 // ==============================
192 // Private functions 258 // Private functions
193 259
260 + function safeId(s) {
261 + return s.replace(/[^a-z0-9]/gi, '-');
262 + }
263 +
194 // set the size of the given element to that of the view (reduced if padded) 264 // set the size of the given element to that of the view (reduced if padded)
195 function setSize(el, view, pad) { 265 function setSize(el, view, pad) {
196 var padding = pad ? pad * 2 : 0; 266 var padding = pad ? pad * 2 : 0;
...@@ -200,127 +270,288 @@ ...@@ -200,127 +270,288 @@
200 }); 270 });
201 } 271 }
202 272
203 - function getNetworkData(view) { 273 + function establishWebSocket() {
204 - var url = getTopoUrl(); 274 + // TODO: establish a real web-socket
275 + // NOTE, for now, we are using the 'Q' key to artificially inject
276 + // "events" from the server.
277 + }
205 278
206 - console.log('Fetching JSON: ' + url); 279 + // ==============================
207 - d3.json(url, function(err, data) { 280 + // Event handlers for server-pushed events
208 - if (err) { 281 +
209 - view.dataLoadError(err, url); 282 + var eventDispatch = {
210 - } else { 283 + addDevice: addDevice,
211 - network.data = data; 284 + updateDevice: updateDevice,
212 - drawNetwork(view); 285 + removeDevice: removeDevice,
286 + addLink: addLink
287 + };
288 +
289 + function addDevice(data) {
290 + var device = data.payload,
291 + node = createDeviceNode(device);
292 + note('addDevice', device.id);
293 +
294 + network.nodes.push(node);
295 + network.lookup[node.id] = node;
296 + updateNodes();
297 + network.force.start();
213 } 298 }
214 - }); 299 +
300 + function updateDevice(data) {
301 + var device = data.payload;
302 + note('updateDevice', device.id);
303 +
215 } 304 }
216 305
217 - function drawNetwork(view) { 306 + function removeDevice(data) {
218 - preprocessData(view); 307 + var device = data.payload;
219 - updateLayout(view); 308 + note('removeDevice', device.id);
309 +
220 } 310 }
221 311
222 - function preprocessData(view) { 312 + function addLink(data) {
223 - var w = view.width(), 313 + var link = data.payload,
224 - h = view.height(), 314 + lnk = createLink(link);
225 - hDevice = h * 0.6, 315 +
226 - hHost = h * 0.3, 316 + if (lnk) {
227 - data = network.data, 317 + note('addLink', lnk.id);
228 - deviceLayout = computeInitLayout(w, hDevice, data.devices.length), 318 +
229 - hostLayout = computeInitLayout(w, hHost, data.hosts.length); 319 + network.links.push(lnk);
230 - 320 + updateLinks();
231 - network.lookup = {}; 321 + network.force.start();
232 - network.nodes = []; 322 + }
233 - network.links = []; 323 + }
234 - // we created new arrays, so need to set the refs in the force layout 324 +
235 - network.force.nodes(network.nodes); 325 + // ....
236 - network.force.links(network.links); 326 +
237 - 327 + function unknownEvent(data) {
238 - // let's just start with the nodes 328 + // TODO: use dialog, not alert
239 - 329 + alert('Unknown event type: "' + data.event + '"');
240 - // note that both 'devices' and 'hosts' get mapped into the nodes array 330 + }
241 - function makeNode(d, cls, layout) { 331 +
242 - var node = { 332 + function handleServerEvent(data) {
243 - id: d.id, 333 + var fn = eventDispatch[data.event] || unknownEvent;
244 - labels: d.labels, 334 + fn(data);
245 - class: cls, 335 + }
246 - icon: cls, 336 +
247 - type: d.type, 337 + // ==============================
248 - x: layout.x(), 338 + // force layout modification functions
249 - y: layout.y() 339 +
340 + function translate(x, y) {
341 + return 'translate(' + x + ',' + y + ')';
342 + }
343 +
344 + function createLink(link) {
345 + var type = link.type,
346 + src = link.src,
347 + dst = link.dst,
348 + w = link.linkWidth,
349 + srcNode = network.lookup[src],
350 + dstNode = network.lookup[dst],
351 + lnk;
352 +
353 + if (!(srcNode && dstNode)) {
354 + alert('nodes not on map');
355 + return null;
356 + }
357 +
358 + lnk = {
359 + id: safeId(src) + '~' + safeId(dst),
360 + source: srcNode,
361 + target: dstNode,
362 + class: 'link',
363 + svgClass: type ? 'link ' + type : 'link',
364 + x1: srcNode.x,
365 + y1: srcNode.y,
366 + x2: dstNode.x,
367 + y2: dstNode.y,
368 + width: w
250 }; 369 };
251 - network.lookup[d.id] = node; 370 + return lnk;
252 - network.nodes.push(node);
253 } 371 }
254 372
255 - // first the devices... 373 + function updateLinks() {
256 - network.data.devices.forEach(function (d) { 374 + link = linkG.selectAll('.link')
257 - makeNode(d, 'device', deviceLayout); 375 + .data(network.links, function (d) { return d.id; });
258 - });
259 376
260 - // then the hosts... 377 + // operate on existing links, if necessary
261 - network.data.hosts.forEach(function (d) { 378 + // link .foo() .bar() ...
262 - makeNode(d, 'host', hostLayout); 379 +
380 + // operate on entering links:
381 + var entering = link.enter()
382 + .append('line')
383 + .attr({
384 + id: function (d) { return d.id; },
385 + class: function (d) { return d.svgClass; },
386 + x1: function (d) { return d.x1; },
387 + y1: function (d) { return d.y1; },
388 + x2: function (d) { return d.x2; },
389 + y2: function (d) { return d.y2; },
390 + stroke: '#66f',
391 + 'stroke-width': 10
392 + })
393 + .transition().duration(1000)
394 + .attr({
395 + 'stroke-width': function (d) { return d.width; },
396 + stroke: '#666' // TODO: remove explicit stroke, rather...
263 }); 397 });
264 398
265 - // TODO: process links 399 + // augment links
400 + // TODO: add src/dst port labels etc.
401 +
266 } 402 }
267 403
268 - function computeInitLayout(w, h, n) { 404 + function createDeviceNode(device) {
269 - var maxdw = 60, 405 + // start with the object as is
270 - compdw, dw, ox, layout; 406 + var node = device,
407 + type = device.type;
271 408
272 - if (n < 2) { 409 + // Augment as needed...
273 - layout = { ox: w/2, dw: 0 } 410 + node.class = 'device';
274 - } else { 411 + node.svgClass = type ? 'node device ' + type : 'node device';
275 - compdw = (0.8 * w) / (n - 1); 412 + positionNode(node);
276 - dw = Math.min(maxdw, compdw); 413 +
277 - ox = w/2 - ((n - 1)/2 * dw); 414 + // cache label array length
278 - layout = { ox: ox, dw: dw } 415 + network.deviceLabelCount = device.labels.length;
416 +
417 + return node;
279 } 418 }
280 419
281 - layout.i = 0; 420 + function positionNode(node) {
421 + var meta = node.metaUi,
422 + x = 0,
423 + y = 0;
282 424
283 - layout.x = function () { 425 + if (meta) {
284 - var x = layout.ox + layout.i*layout.dw; 426 + x = meta.x;
285 - layout.i++; 427 + y = meta.y;
286 - return x; 428 + }
287 - }; 429 + if (x && y) {
430 + node.fixed = true;
431 + }
432 + node.x = x || network.view.width() / 2;
433 + node.y = y || network.view.height() / 2;
434 + }
288 435
289 - layout.y = function () {
290 - return h;
291 - };
292 436
293 - return layout; 437 + function iconUrl(d) {
438 + return 'img/' + d.type + '.png';
439 + }
440 +
441 + // returns the newly computed bounding box of the rectangle
442 + function adjustRectToFitText(n) {
443 + var text = n.select('text'),
444 + box = text.node().getBBox(),
445 + lab = config.labels;
446 +
447 + text.attr('text-anchor', 'middle')
448 + .attr('y', '-0.8em')
449 + .attr('x', lab.imgPad/2);
450 +
451 + // translate the bbox so that it is centered on [x,y]
452 + box.x = -box.width / 2;
453 + box.y = -box.height / 2;
454 +
455 + // add padding
456 + box.x -= (lab.padLR + lab.imgPad/2);
457 + box.width += lab.padLR * 2 + lab.imgPad;
458 + box.y -= lab.padTB;
459 + box.height += lab.padTB * 2;
460 +
461 + return box;
294 } 462 }
295 463
296 - function linkId(d) { 464 + function updateNodes() {
297 - return d.source.id + '~' + d.target.id; 465 + node = nodeG.selectAll('.node')
466 + .data(network.nodes, function (d) { return d.id; });
467 +
468 + // operate on existing nodes, if necessary
469 + //node .foo() .bar() ...
470 +
471 + // operate on entering nodes:
472 + var entering = node.enter()
473 + .append('g')
474 + .attr({
475 + id: function (d) { return safeId(d.id); },
476 + class: function (d) { return d.svgClass; },
477 + transform: function (d) { return translate(d.x, d.y); },
478 + opacity: 0
479 + })
480 + //.call(network.drag)
481 + //.on('mouseover', function (d) {})
482 + //.on('mouseover', function (d) {})
483 + .transition()
484 + .attr('opacity', 1);
485 +
486 + // augment device nodes...
487 + entering.filter('.device').each(function (d) {
488 + var node = d3.select(this),
489 + icon = iconUrl(d),
490 + idx = (labelIdx < d.labels.length) ? labelIdx : 0,
491 + box;
492 +
493 + node.append('rect')
494 + .attr({
495 + 'rx': 5,
496 + 'ry': 5
497 + });
498 +
499 + node.append('text')
500 + .text(d.labels[idx])
501 + .attr('dy', '1.1em');
502 +
503 + box = adjustRectToFitText(node);
504 +
505 + node.select('rect')
506 + .attr(box);
507 +
508 + if (icon) {
509 + var cfg = config.icons;
510 + node.append('svg:image')
511 + .attr({
512 + x: box.x + config.icons.xoff,
513 + y: box.y + config.icons.yoff,
514 + width: cfg.w,
515 + height: cfg.h,
516 + 'xlink:href': icon
517 + });
298 } 518 }
299 519
300 - function nodeId(d) { 520 + // debug function to show the modelled x,y coordinates of nodes...
301 - return d.id; 521 + if (debug('showNodeXY')) {
522 + node.select('rect').attr('fill-opacity', 0.5);
523 + node.append('circle')
524 + .attr({
525 + class: 'debug',
526 + cx: 0,
527 + cy: 0,
528 + r: '3px'
529 + });
302 } 530 }
531 + });
303 532
304 - function updateLayout(view) {
305 - link = link.data(network.force.links(), linkId);
306 - link.enter().append('line')
307 - .attr('class', 'link');
308 - link.exit().remove();
309 533
310 - node = node.data(network.force.nodes(), nodeId); 534 + // operate on both existing and new nodes, if necessary
311 - node.enter().append('circle') 535 + //node .foo() .bar() ...
312 - .attr('id', function (d) { return 'nodeId-' + d.id; })
313 - .attr('class', function (d) { return 'node'; })
314 - .attr('r', 12);
315 536
316 - network.force.start(); 537 + // operate on exiting nodes:
538 + // TODO: figure out how to remove the node 'g' AND its children
539 + node.exit()
540 + .transition()
541 + .duration(750)
542 + .attr({
543 + opacity: 0,
544 + cx: 0,
545 + cy: 0,
546 + r: 0
547 + })
548 + .remove();
317 } 549 }
318 550
319 551
320 function tick() { 552 function tick() {
321 node.attr({ 553 node.attr({
322 - cx: function(d) { return d.x; }, 554 + transform: function (d) { return translate(d.x, d.y); }
323 - cy: function(d) { return d.y; }
324 }); 555 });
325 556
326 link.attr({ 557 link.attr({
...@@ -371,28 +602,45 @@ ...@@ -371,28 +602,45 @@
371 link = linkG.selectAll('.link'); 602 link = linkG.selectAll('.link');
372 node = nodeG.selectAll('.node'); 603 node = nodeG.selectAll('.node');
373 604
605 + function ldist(d) {
606 + return fcfg.linkDistance[d.class] || 150;
607 + }
608 + function lstrg(d) {
609 + return fcfg.linkStrength[d.class] || 1;
610 + }
611 + function lchrg(d) {
612 + return fcfg.charge[d.class] || -200;
613 + }
614 +
374 // set up the force layout 615 // set up the force layout
375 network.force = d3.layout.force() 616 network.force = d3.layout.force()
376 .size(forceDim) 617 .size(forceDim)
377 .nodes(network.nodes) 618 .nodes(network.nodes)
378 .links(network.links) 619 .links(network.links)
379 - .charge(function (d) { return fcfg.charge[d.class]; }) 620 + .charge(lchrg)
380 - .linkDistance(function (d) { return fcfg.linkDistance[d.class]; }) 621 + .linkDistance(ldist)
381 - .linkStrength(function (d) { return fcfg.linkStrength[d.class]; }) 622 + .linkStrength(lstrg)
382 .on('tick', tick); 623 .on('tick', tick);
383 } 624 }
384 625
385 626
386 function load(view, ctx) { 627 function load(view, ctx) {
628 + // cache the view token, so network topo functions can access it
629 + network.view = view;
630 +
631 + // set our radio buttons and key bindings
387 view.setRadio(btnSet); 632 view.setRadio(btnSet);
388 view.setKeys(keyDispatch); 633 view.setKeys(keyDispatch);
389 634
390 - getNetworkData(view); 635 + establishWebSocket();
391 } 636 }
392 637
393 function resize(view, ctx) { 638 function resize(view, ctx) {
394 setSize(svg, view); 639 setSize(svg, view);
395 setSize(bgImg, view); 640 setSize(bgImg, view);
641 +
642 + // TODO: hook to recompute layout, perhaps? work with zoom/pan code
643 + // adjust force layout size
396 } 644 }
397 645
398 646
......