45e0b084ac7bd6fbb76373572a9737734993a8bc
[racktables] / inc / interface.php
1 <?php
2 /*
3 *
4 * This file contains frontend functions for RackTables.
5 *
6 */
7
8 include_once 'ajax-interface.php';
9
10 // Interface function's special.
11 $nextorder['odd'] = 'even';
12 $nextorder['even'] = 'odd';
13
14 // address allocation type
15 $aat = array
16 (
17 'regular' => 'Connected',
18 'virtual' => 'Loopback',
19 'shared' => 'Shared',
20 'router' => 'Router',
21 );
22 // address allocation code, IPv4 addresses and objects view
23 $aac = array
24 (
25 'regular' => '',
26 'virtual' => '<strong>L</strong>',
27 'shared' => '<strong>S</strong>',
28 'router' => '<strong>R</strong>',
29 );
30 // address allocation code, IPv4 networks view
31 $aac2 = array
32 (
33 'regular' => '',
34 'virtual' => '<strong>L:</strong>',
35 'shared' => '<strong>S:</strong>',
36 'router' => '<strong>R:</strong>',
37 );
38
39 $vtdecoder = array
40 (
41 'ondemand' => '',
42 'compulsory' => 'P',
43 # 'alien' => 'NT',
44 );
45
46 $vtoptions = array
47 (
48 'ondemand' => 'auto',
49 'compulsory' => 'permanent',
50 # 'alien' => 'never touch',
51 );
52
53 // 802.1Q deploy queue titles
54 $dqtitle = array
55 (
56 'sync_aging' => 'Normal, aging',
57 'resync_aging' => 'Version conflict, aging',
58 'sync_ready' => 'Normal, ready for sync',
59 'resync_ready' => 'Version conflict, ready for retry',
60 'failed' => 'Failed',
61 'disabled' => 'Sync disabled',
62 'done' => 'Up to date',
63 );
64
65 // Let's have it here, so extensions can add their own images.
66 $image = array();
67 $image['error']['path'] = 'pix/error.png';
68 $image['error']['width'] = 76;
69 $image['error']['height'] = 17;
70 $image['logo']['path'] = 'pix/defaultlogo.png';
71 $image['logo']['width'] = 210;
72 $image['logo']['height'] = 40;
73 $image['rackspace']['path'] = 'pix/racks.png';
74 $image['rackspace']['width'] = 218;
75 $image['rackspace']['height'] = 200;
76 $image['objects']['path'] = 'pix/server.png';
77 $image['objects']['width'] = 218;
78 $image['objects']['height'] = 200;
79 $image['depot']['path'] = 'pix/server.png';
80 $image['depot']['width'] = 218;
81 $image['depot']['height'] = 200;
82 $image['files']['path'] = 'pix/files.png';
83 $image['files']['width'] = 218;
84 $image['files']['height'] = 200;
85 $image['ipv4space']['path'] = 'pix/addressspace.png';
86 $image['ipv4space']['width'] = 218;
87 $image['ipv4space']['height'] = 200;
88 $image['ipv6space']['path'] = 'pix/addressspacev6.png';
89 $image['ipv6space']['width'] = 218;
90 $image['ipv6space']['height'] = 200;
91 $image['ipv4slb']['path'] = 'pix/slb.png';
92 $image['ipv4slb']['width'] = 218;
93 $image['ipv4slb']['height'] = 200;
94 $image['config']['path'] = 'pix/configuration.png';
95 $image['config']['width'] = 218;
96 $image['config']['height'] = 200;
97 $image['reports']['path'] = 'pix/report.png';
98 $image['reports']['width'] = 218;
99 $image['reports']['height'] = 200;
100 $image['8021q']['path'] = 'pix/8021q.png';
101 $image['8021q']['width'] = 218;
102 $image['8021q']['height'] = 200;
103 $image['objectlog']['path'] = 'pix/crystal-mimetypes-shellscript-218x200.png';
104 $image['objectlog']['width'] = 218;
105 $image['objectlog']['height'] = 200;
106 $image['download']['path'] = 'pix/download.png';
107 $image['download']['width'] = 16;
108 $image['download']['height'] = 16;
109 $image['DOWNLOAD']['path'] = 'pix/download-big.png';
110 $image['DOWNLOAD']['width'] = 32;
111 $image['DOWNLOAD']['height'] = 32;
112 $image['plug']['path'] = 'pix/tango-network-wired.png';
113 $image['plug']['width'] = 16;
114 $image['plug']['height'] = 16;
115 $image['cut']['path'] = 'pix/tango-edit-cut-16x16.png';
116 $image['cut']['width'] = 16;
117 $image['cut']['height'] = 16;
118 $image['Cut']['path'] = 'pix/tango-edit-cut-22x22.png';
119 $image['Cut']['width'] = 22;
120 $image['Cut']['height'] = 22;
121 $image['CUT']['path'] = 'pix/tango-edit-cut-32x32.png';
122 $image['CUT']['width'] = 32;
123 $image['CUT']['height'] = 32;
124 $image['add']['path'] = 'pix/tango-list-add.png';
125 $image['add']['width'] = 16;
126 $image['add']['height'] = 16;
127 $image['ADD']['path'] = 'pix/tango-list-add-big.png';
128 $image['ADD']['width'] = 32;
129 $image['ADD']['height'] = 32;
130 $image['delete']['path'] = 'pix/tango-list-remove.png';
131 $image['delete']['width'] = 16;
132 $image['delete']['height'] = 16;
133 $image['DELETE']['path'] = 'pix/tango-list-remove-32x32.png';
134 $image['DELETE']['width'] = 32;
135 $image['DELETE']['height'] = 32;
136 $image['destroy']['path'] = 'pix/tango-user-trash-16x16.png';
137 $image['destroy']['width'] = 16;
138 $image['destroy']['height'] = 16;
139 $image['nodestroy']['path'] = 'pix/tango-user-trash-16x16-gray.png';
140 $image['nodestroy']['width'] = 16;
141 $image['nodestroy']['height'] = 16;
142 $image['NODESTROY']['path'] = 'pix/tango-user-trash-32x32-gray.png';
143 $image['NODESTROY']['width'] = 32;
144 $image['NODESTROY']['height'] = 32;
145 $image['DESTROY']['path'] = 'pix/tango-user-trash-32x32.png';
146 $image['DESTROY']['width'] = 32;
147 $image['DESTROY']['height'] = 32;
148 $image['nodelete']['path'] = 'pix/tango-list-remove-shadow.png';
149 $image['nodelete']['width'] = 16;
150 $image['nodelete']['height'] = 16;
151 $image['inservice']['path'] = 'pix/tango-emblem-system.png';
152 $image['inservice']['width'] = 16;
153 $image['inservice']['height'] = 16;
154 $image['notinservice']['path'] = 'pix/tango-dialog-error.png';
155 $image['notinservice']['width'] = 16;
156 $image['notinservice']['height'] = 16;
157 $image['find']['path'] = 'pix/tango-system-search.png';
158 $image['find']['width'] = 16;
159 $image['find']['height'] = 16;
160 $image['next']['path'] = 'pix/tango-go-next.png';
161 $image['next']['width'] = 32;
162 $image['next']['height'] = 32;
163 $image['prev']['path'] = 'pix/tango-go-previous.png';
164 $image['prev']['width'] = 32;
165 $image['prev']['height'] = 32;
166 $image['COMMIT']['path'] = 'pix/tango-go-prev-next-32x32.png';
167 $image['COMMIT']['width'] = 32;
168 $image['COMMIT']['height'] = 32;
169 $image['COMMIT gray']['path'] = 'pix/tango-go-prev-next-gray-32x32.png';
170 $image['COMMIT gray']['width'] = 32;
171 $image['COMMIT gray']['height'] = 32;
172 $image['RECALC']['path'] = 'pix/tango-view-refresh-32x32.png';
173 $image['RECALC']['width'] = 32;
174 $image['RECALC']['height'] = 32;
175 $image['clear']['path'] = 'pix/tango-edit-clear.png';
176 $image['clear']['width'] = 16;
177 $image['clear']['height'] = 16;
178 $image['CLEAR']['path'] = 'pix/tango-edit-clear-big.png';
179 $image['CLEAR']['width'] = 32;
180 $image['CLEAR']['height'] = 32;
181 $image['CLEAR gray']['path'] = 'pix/tango-edit-clear-gray-32x32.png';
182 $image['CLEAR gray']['width'] = 32;
183 $image['CLEAR gray']['height'] = 32;
184 $image['save']['path'] = 'pix/tango-document-save-16x16.png';
185 $image['save']['width'] = 16;
186 $image['save']['height'] = 16;
187 $image['SAVE']['path'] = 'pix/tango-document-save-32x32.png';
188 $image['SAVE']['width'] = 32;
189 $image['SAVE']['height'] = 32;
190 $image['NOSAVE']['path'] = 'pix/tango-document-save-32x32-gray.png';
191 $image['NOSAVE']['width'] = 32;
192 $image['NOSAVE']['height'] = 32;
193 $image['create']['path'] = 'pix/tango-document-new.png';
194 $image['create']['width'] = 16;
195 $image['create']['height'] = 16;
196 $image['CREATE']['path'] = 'pix/tango-document-new-big.png';
197 $image['CREATE']['width'] = 32;
198 $image['CREATE']['height'] = 32;
199 $image['DENIED']['path'] = 'pix/tango-dialog-error-big.png';
200 $image['DENIED']['width'] = 32;
201 $image['DENIED']['height'] = 32;
202 $image['node-collapsed']['path'] = 'pix/node-collapsed.png';
203 $image['node-collapsed']['width'] = 16;
204 $image['node-collapsed']['height'] = 16;
205 $image['node-expanded']['path'] = 'pix/node-expanded.png';
206 $image['node-expanded']['width'] = 16;
207 $image['node-expanded']['height'] = 16;
208 $image['node-expanded-static']['path'] = 'pix/node-expanded-static.png';
209 $image['node-expanded-static']['width'] = 16;
210 $image['node-expanded-static']['height'] = 16;
211 $image['dragons']['path'] = 'pix/mitsudragon.png';
212 $image['dragons']['width'] = 195;
213 $image['dragons']['height'] = 33;
214 $image['LB']['path'] = 'pix/loadbalancer.png';
215 $image['LB']['width'] = 32;
216 $image['LB']['height'] = 32;
217 $image['RS pool']['path'] = 'pix/serverpool.png';
218 $image['RS pool']['width'] = 48;
219 $image['RS pool']['height'] = 16;
220 $image['VS']['path'] = 'pix/servicesign.png';
221 $image['VS']['width'] = 39;
222 $image['VS']['height'] = 62;
223 $image['router']['path'] = 'pix/router.png';
224 $image['router']['width'] = 32;
225 $image['router']['height'] = 32;
226 $image['object']['path'] = 'pix/bracket-16x16.png';
227 $image['object']['width'] = 16;
228 $image['object']['height'] = 16;
229 $image['OBJECT']['path'] = 'pix/bracket-32x32.png';
230 $image['OBJECT']['width'] = 32;
231 $image['OBJECT']['height'] = 32;
232 $image['ATTACH']['path'] = 'pix/tango-mail-attachment-32x32.png';
233 $image['ATTACH']['width'] = 32;
234 $image['ATTACH']['height'] = 32;
235 $image['Attach']['path'] = 'pix/tango-mail-attachment-22x22.png';
236 $image['Attach']['width'] = 22;
237 $image['Attach']['height'] = 22;
238 $image['favorite']['path'] = 'pix/tango-emblem-favorite.png';
239 $image['favorite']['width'] = 16;
240 $image['favorite']['height'] = 16;
241 $image['computer']['path'] = 'pix/tango-computer.png';
242 $image['computer']['width'] = 16;
243 $image['computer']['height'] = 16;
244 $image['empty file']['path'] = 'pix/crystal-file-empty-32x32.png';
245 $image['empty file']['width'] = 32;
246 $image['empty file']['height'] = 32;
247 $image['text file']['path'] = 'pix/crystal-file-text-32x32.png';
248 $image['text file']['width'] = 32;
249 $image['text file']['height'] = 32;
250 $image['image file']['path'] = 'pix/crystal-file-image-32x32.png';
251 $image['image file']['width'] = 32;
252 $image['image file']['height'] = 32;
253 $image['text']['path'] = 'pix/tango-text-x-generic-16x16.png';
254 $image['text']['width'] = 16;
255 $image['text']['height'] = 16;
256 $image['NET']['path'] = 'pix/crystal-network_local-32x32.png';
257 $image['NET']['width'] = 32;
258 $image['NET']['height'] = 32;
259 $image['net']['path'] = 'pix/crystal-network_local-16x16.png';
260 $image['net']['width'] = 16;
261 $image['net']['height'] = 16;
262 $image['USER']['path'] = 'pix/crystal-edit-user-32x32.png';
263 $image['USER']['width'] = 32;
264 $image['USER']['height'] = 32;
265 $image['setfilter']['path'] = 'pix/pgadmin3-viewfiltereddata.png';
266 $image['setfilter']['width'] = 32;
267 $image['setfilter']['height'] = 32;
268 $image['setfilter gray']['path'] = 'pix/pgadmin3-viewfiltereddata-grayscale.png';
269 $image['setfilter gray']['width'] = 32;
270 $image['setfilter gray']['height'] = 32;
271 $image['resetfilter']['path'] = 'pix/pgadmin3-viewdata.png';
272 $image['resetfilter']['width'] = 32;
273 $image['resetfilter']['height'] = 32;
274 $image['resetfilter gray']['path'] = 'pix/pgadmin3-viewdata-grayscale.png';
275 $image['resetfilter gray']['width'] = 32;
276 $image['resetfilter gray']['height'] = 32;
277 $image['knight']['path'] = 'pix/smiley_knight.png';
278 $image['knight']['width'] = 72;
279 $image['knight']['height'] = 33;
280 $image['Zoom']['path'] = 'pix/tango-system-search-22x22.png';
281 $image['Zoom']['width'] = 22;
282 $image['Zoom']['height'] = 22;
283 $image['Zooming']['path'] = 'pix/tango-view-fullscreen-22x22.png';
284 $image['Zooming']['width'] = 22;
285 $image['Zooming']['height'] = 22;
286 $image['UNLOCK']['path'] = 'pix/crystal-actions-unlock-32x32.png';
287 $image['UNLOCK']['width'] = 32;
288 $image['UNLOCK']['height'] = 32;
289 $image['CLOCK']['path'] = 'pix/tango-appointment-32x32.png';
290 $image['CLOCK']['width'] = 32;
291 $image['CLOCK']['height'] = 32;
292 $image['DQUEUE done']['path'] = 'pix/crystal-ok-32x32.png';
293 $image['DQUEUE done']['width'] = 32;
294 $image['DQUEUE done']['height'] = 32;
295 $image['DQUEUE sync_aging']['path'] = 'pix/tango-appointment-32x32.png';
296 $image['DQUEUE sync_aging']['width'] = 32;
297 $image['DQUEUE sync_aging']['height'] = 32;
298 $image['DQUEUE resync_aging']['path'] = 'pix/tango-appointment-32x32.png';
299 $image['DQUEUE resync_aging']['width'] = 32;
300 $image['DQUEUE resync_aging']['height'] = 32;
301 $image['DQUEUE sync_ready']['path'] = 'pix/tango-emblem-system-32x32.png';
302 $image['DQUEUE sync_ready']['width'] = 32;
303 $image['DQUEUE sync_ready']['height'] = 32;
304 $image['DQUEUE resync_ready']['path'] = 'pix/tango-emblem-important-32x32.png';
305 $image['DQUEUE resync_ready']['width'] = 32;
306 $image['DQUEUE resync_ready']['height'] = 32;
307 $image['DQUEUE failed']['path'] = 'pix/tango-emblem-unreadable-32x32.png';
308 $image['DQUEUE failed']['width'] = 32;
309 $image['DQUEUE failed']['height'] = 32;
310 $image['DQUEUE disabled']['path'] = 'pix/tango-emblem-readonly-32x32.png';
311 $image['DQUEUE disabled']['width'] = 32;
312 $image['DQUEUE disabled']['height'] = 32;
313 $image['COPY']['path'] = 'pix/tango-edit-copy-32x32.png';
314 $image['COPY']['width'] = 32;
315 $image['COPY']['height'] = 32;
316
317 // This may be populated later onsite, report rendering function will use it.
318 // See the $systemreport for structure.
319 $localreports = array();
320
321 $CodePressMap = array
322 (
323 'sql' => 'sql',
324 'php' => 'php',
325 'html' => 'html',
326 'css' => 'css',
327 'js' => 'javascript',
328 );
329
330 $attrtypes = array
331 (
332 'uint' => '[U] unsigned integer',
333 'float' => '[F] floating point',
334 'string' => '[S] string',
335 'dict' => '[D] dictionary record'
336 );
337
338 // Main menu.
339 function renderIndexItem ($ypageno) {
340 global $page;
341 if (permitted($ypageno)) {
342 $title = isset ($page[$ypageno]['title']) ? $page[$ypageno]['title'] : dynamic_title_decoder ($ypageno);
343 if (is_array ($title))
344 $title = $title['name'];
345 print " <td>\n";
346 print " <h1><a href='".makeHref(array('page'=>$ypageno))."'>".$title."<br>\n";
347 printImageHREF ($ypageno);
348 print "</a></h1>\n";
349 print " </td>\n";
350 } else {
351 print " <td>&nbsp;</td>\n";
352 }
353 }
354
355 function renderIndex ()
356 {
357 global $indexlayout;
358 ?>
359 <table border=0 cellpadding=0 cellspacing=0 width='100%'>
360 <tr>
361 <td>
362 <div style='text-align: center; margin: 10px; '>
363 <table width='100%' cellspacing=0 cellpadding=20 class=mainmenu border=0>
364 <?php
365 foreach ($indexlayout as $row)
366 {
367 echo '<tr>';
368 foreach ($row as $column)
369 if ($column === NULL)
370 echo '<td>&nbsp;</td>';
371 else
372 renderIndexItem ($column);
373 echo '</tr>';
374 }
375 ?>
376 </table>
377 </div>
378 </td>
379 </tr>
380 </table>
381 <?php
382 }
383
384 function renderRackspace ()
385 {
386 $found_racks = array();
387 $rows = array();
388 $cellfilter = getCellFilter();
389 $rackCount = 0;
390 foreach (getRackRows() as $row_id => $row_name) {
391 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
392 $found_racks = array_merge($found_racks, $rackList);
393 $rows[] = array(
394 'row_id' => $row_id,
395 'row_name' => $row_name,
396 'racks' => $rackList
397 );
398 $rackCount += count($rackList);
399 }
400
401 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
402 renderCellFilterPortlet ($cellfilter, 'rack', $found_racks);
403 echo '</td><td class=pcright>';
404
405 if (! renderEmptyResults($cellfilter, 'racks', $rackCount))
406 {
407 echo '<table border=0 cellpadding=10 cellpadding=1>';
408 // generate thumb gallery
409 global $nextorder;
410 $rackwidth = getRackImageWidth();
411 // Zero value effectively disables the limit.
412 $maxPerRow = getConfigVar ('RACKS_PER_ROW');
413 $order = 'odd';
414 foreach ($rows as $row)
415 {
416 $row_id = $row['row_id'];
417 $row_name = $row['row_name'];
418 $rackList = $row['racks'];
419
420 if (!count ($rackList) and count ($cellfilter['expression']))
421 continue;
422 $rackListIdx = 0;
423 echo "<tr class=row_${order}><th class=tdleft>";
424 echo "<a href='".makeHref(array('page'=>'row', 'row_id'=>$row_id))."${cellfilter['urlextra']}'>";
425 echo "${row_name}</a></th><td><table border=0 cellspacing=5><tr>";
426 if (!count ($rackList))
427 echo "<td>(empty row)</td>";
428 else
429 foreach ($rackList as $rack)
430 {
431 if ($rackListIdx > 0 and $maxPerRow > 0 and $rackListIdx % $maxPerRow == 0)
432 {
433 echo '</tr></table></tr>';
434 echo "<tr class=row_${order}><th class=tdleft>${row_name} (continued)";
435 echo "</th><td><table border=0 cellspacing=5><tr>";
436 }
437 echo "<td align=center><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
438 echo "<img border=0 width=${rackwidth} height=";
439 echo getRackImageHeight ($rack['height']);
440 echo " title='${rack['height']} units'";
441 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
442 echo "<br>${rack['name']}</a></td>";
443 $rackListIdx++;
444 }
445 $order = $nextorder[$order];
446 echo "</tr></table></tr>\n";
447 }
448 echo "</table>\n";
449 }
450 echo "</td></tr></table>\n";
451 }
452
453 function renderRackspaceRowEditor ()
454 {
455 function printNewItemTR ()
456 {
457 printOpFormIntro ('addRow');
458 echo "<tr><td>";
459 printImageHREF ('create', 'Add new row', TRUE);
460 echo "</td><td><input type=text name=name tabindex=100></td><td>";
461 printImageHREF ('create', 'Add new row', TRUE, 101);
462 echo "</td></tr></form>";
463 }
464 startPortlet ('Rows');
465 echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
466 echo "<tr><th>&nbsp;</th><th>Name</th><th>&nbsp;</th></tr>\n";
467 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
468 printNewItemTR();
469 foreach (getRackRows() as $row_id => $row_name)
470 {
471 echo "<tr><td>";
472 if ($rc = count (listCells ('rack', $row_id)))
473 printImageHREF ('nodestroy', "${rc} rack(s) here");
474 else
475 {
476 echo "<a href=\"".makeHrefProcess(array('op'=>'delete', 'row_id'=>$row_id))."\">";
477 printImageHREF ('destroy', 'Delete row');
478 echo "</a>";
479 }
480 printOpFormIntro ('updateRow', array ('row_id' => $row_id));
481 echo "</td><td><input type=text name=name value='${row_name}'></td><td>";
482 printImageHREF ('save', 'Save changes', TRUE);
483 echo "</form></td></tr>\n";
484 }
485 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
486 printNewItemTR();
487 echo "</table><br>\n";
488 finishPortlet();
489 }
490
491 function renderRow ($row_id)
492 {
493 $rowInfo = getRackRowInfo ($row_id);
494 $cellfilter = getCellFilter();
495 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
496 // Main layout starts.
497 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
498
499 // Left portlet with row information.
500 echo "<tr><td class=pcleft>";
501 startPortlet ($rowInfo['name']);
502 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
503 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
504 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
505 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
506 renderProgressBar (getRSUforRackRow ($rackList));
507 echo "</td></tr>\n";
508 echo "</table><br>\n";
509 finishPortlet();
510 renderCellFilterPortlet ($cellfilter, 'rack', $rackList, 'row_id', $row_id);
511
512 echo "</td><td class=pcright>";
513
514 global $nextorder;
515 $rackwidth = getRackImageWidth() * getConfigVar ('ROW_SCALE');
516 // Maximum number of racks per row is proportionally less, but at least 1.
517 $maxPerRow = max (floor (getConfigVar ('RACKS_PER_ROW') / getConfigVar ('ROW_SCALE')), 1);
518 $rackListIdx = 0;
519 $order = 'odd';
520 startPortlet ('Racks');
521 echo "<table border=0 cellspacing=5 align='center'><tr>";
522 foreach ($rackList as $rack)
523 {
524 if ($rackListIdx % $maxPerRow == 0)
525 {
526 if ($rackListIdx > 0)
527 echo '</tr>';
528 echo '<tr>';
529 }
530 echo "<td align=center class=row_${order}><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
531 echo "<img border=0 width=${rackwidth} height=" . (getRackImageHeight ($rack['height']) * getConfigVar ('ROW_SCALE'));
532 echo " title='${rack['height']} units'";
533 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
534 echo "<br>${rack['name']}</a></td>";
535 $order = $nextorder[$order];
536 $rackListIdx++;
537 }
538 echo "</tr></table>\n";
539 finishPortlet();
540 echo "</td></tr></table>";
541 }
542
543 // This function renders rack as HTML table.
544 function renderRack ($rack_id, $hl_obj_id = 0)
545 {
546 $rackData = spotEntity ('rack', $rack_id);
547 amplifyCell ($rackData);
548 markAllSpans ($rackData);
549 if ($hl_obj_id > 0)
550 highlightObject ($rackData, $hl_obj_id);
551 markupObjectProblems ($rackData);
552 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
553 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
554 echo "<center><table border=0><tr valign=middle>";
555 echo "<td><h2><a href='".makeHref(array('page'=>'row', 'row_id'=>$rackData['row_id']))."'>${rackData['row_name']}</a> :</h2></td>";
556 // FIXME: use 'bypass'?
557 if ($prev_id != NULL)
558 {
559 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$prev_id))."'>";
560 printImageHREF ('prev', 'previous rack');
561 echo "</a></td>";
562 }
563 echo "<td><h2><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rackData['id']))."'>${rackData['name']}</a></h2></td>";
564 if ($next_id != NULL)
565 {
566 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$next_id))."'>";
567 printImageHREF ('next', 'next rack');
568 echo "</a></td>";
569 }
570 echo "</h2></td></tr></table>\n";
571 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
572 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
573 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
574 addAtomCSS();
575 for ($i = $rackData['height']; $i > 0; $i--)
576 {
577 echo "<tr><th>${i}</th>";
578 for ($locidx = 0; $locidx < 3; $locidx++)
579 {
580 if (isset ($rackData[$i][$locidx]['skipped']))
581 continue;
582 $state = $rackData[$i][$locidx]['state'];
583 echo "<td class='atom state_${state}";
584 if (isset ($rackData[$i][$locidx]['hl']))
585 echo $rackData[$i][$locidx]['hl'];
586 echo "'";
587 if (isset ($rackData[$i][$locidx]['colspan']))
588 echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
589 if (isset ($rackData[$i][$locidx]['rowspan']))
590 echo ' rowspan=' . $rackData[$i][$locidx]['rowspan'];
591 echo ">";
592 switch ($state)
593 {
594 case 'T':
595 $objectData = spotEntity ('object', $rackData[$i][$locidx]['object_id']);
596 if (strlen ($objectData['asset_no']))
597 $prefix = "<div title='${objectData['asset_no']}";
598 else
599 $prefix = "<div title='no asset tag";
600 // Don't tell about label, if it matches common name.
601 if ($objectData['name'] != $objectData['label'] and strlen ($objectData['label']))
602 $suffix = ", visible label is \"${objectData['label']}\"'>";
603 else
604 $suffix = "'>";
605 echo $prefix . $suffix;
606 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$objectData['id']))."'>${objectData['dname']}</a></div>";
607 break;
608 case 'A':
609 echo '<div title="This rackspace does not exist">&nbsp;</div>';
610 break;
611 case 'F':
612 echo '<div title="Free rackspace">&nbsp;</div>';
613 break;
614 case 'U':
615 echo '<div title="Problematic rackspace, you CAN\'T mount here">&nbsp;</div>';
616 break;
617 default:
618 echo '<div title="No data">&nbsp;</div>';
619 break;
620 }
621 echo '</td>';
622 }
623 echo "</tr>\n";
624 }
625 echo "</table></center>\n";
626 }
627
628 function renderNewRackForm ($row_id)
629 {
630 startPortlet ('Add one');
631 printOpFormIntro ('addRack', array ('got_data' => 'TRUE'));
632 echo '<table border=0 align=center>';
633 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
634 if ($defh == 0)
635 $defh = '';
636 echo "<tr><th class=tdright>Rack name (*):</th><td class=tdleft><input type=text name=rack_name tabindex=1></td>";
637 echo "<td rowspan=4>Assign tags:<br>";
638 renderNewEntityTags ('rack');
639 echo "</td></tr>\n";
640 echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=rack_height1 tabindex=2 value='${defh}'></td></tr>\n";
641 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
642 echo "<tr><td class=submit colspan=2>";
643 printImageHREF ('CREATE', 'Add', TRUE);
644 echo "</td></tr></table></form>";
645 finishPortlet();
646
647 startPortlet ('Add many');
648 printOpFormIntro ('addRack', array ('got_mdata' => 'TRUE'));
649 echo '<table border=0 align=center>';
650 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
651 if ($defh == 0)
652 $defh = '';
653 echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=rack_height2 value='${defh}'></td>";
654 echo "<td rowspan=3 valign=top>Assign tags:<br>";
655 renderNewEntityTags ('rack');
656 echo "</td></tr>\n";
657 echo "<tr><th class=tdright>Rack names (*):</th><td class=tdleft><textarea name=rack_names cols=40 rows=25></textarea></td></tr>\n";
658 echo "<tr><td class=submit colspan=2>";
659 printImageHREF ('CREATE', 'Add', TRUE);
660 echo '</form></table>';
661 finishPortlet();
662 }
663
664 function renderEditObjectForm ($object_id)
665 {
666 global $pageno;
667 $object = spotEntity ('object', $object_id);
668 startPortlet ();
669 printOpFormIntro ('update');
670
671 // static attributes
672 echo '<table border=0 cellspacing=0 cellpadding=3 align=center>';
673 echo "<tr><td>&nbsp;</td><th colspan=2><h2>Attributes</h2></th></tr>";
674 echo "<tr><td>&nbsp;</td><th class=tdright>Type:</th><td class=tdleft>";
675 printNiftySelect (cookOptgroups (readChapter (CHAP_OBJTYPE, 'o')), array ('name' => 'object_type_id'), $object['objtype_id']);
676 echo "</td></tr>\n";
677 // baseline info
678 echo "<tr><td>&nbsp;</td><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name value='${object['name']}'></td></tr>\n";
679 echo "<tr><td>&nbsp;</td><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label value='${object['label']}'></td></tr>\n";
680 echo "<tr><td>&nbsp;</td><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=object_asset_no value='${object['asset_no']}'></td></tr>\n";
681 echo "<tr><td>&nbsp;</td><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode value='${object['barcode']}'></td></tr>\n";
682 // optional attributes
683 $values = getAttrValues ($object_id);
684 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
685 if (count($values) > 0)
686 {
687 $i = 0;
688 foreach ($values as $record)
689 {
690 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
691 echo '<tr><td>';
692 if (strlen ($record['value']))
693 {
694 echo "<a href='".makeHrefProcess(array('op'=>'clearSticker', 'object_id'=>$object_id, 'attr_id'=>$record['id']))."'>";
695 printImageHREF ('clear', 'Clear value');
696 echo '</a>';
697 }
698 else
699 echo '&nbsp;';
700 echo '</td>';
701 echo "<th class=sticker>${record['name']}:</th><td class=tdleft>";
702 switch ($record['type'])
703 {
704 case 'uint':
705 case 'float':
706 case 'string':
707 echo "<input type=text name=${i}_value value='${record['value']}'>";
708 break;
709 case 'dict':
710 $chapter = readChapter ($record['chapter_id'], 'o');
711 $chapter[0] = '-- NOT SET --';
712 $chapter = cookOptgroups ($chapter, $object['objtype_id'], $record['key']);
713 printNiftySelect ($chapter, array ('name' => "${i}_value"), $record['key']);
714 break;
715 }
716 echo "</td></tr>\n";
717 $i++;
718 }
719 }
720 echo "<tr><td>&nbsp;</td><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
721 if ($object['has_problems'] == 'yes')
722 echo ' checked';
723 echo "></td></tr>\n";
724 echo "<tr><td>&nbsp;</td><th class=tdright>Actions:</th><td class=tdleft>";
725 echo "<a href='".
726 makeHrefProcess(array('op'=>'deleteObject', 'page'=>'depot', 'tab'=>'addmore', 'object_id'=>$object_id)).
727 "' onclick=\"javascript:return confirm('Are you sure you want to delete the object?')\">" . getImageHREF ('destroy', 'Delete object') . "</a>";
728 echo "&nbsp;";
729 echo "<a href='".
730 makeHrefProcess(array ('op'=>'resetObject', 'page' => 'object', 'tab' => 'edit', 'object_id' => $object_id)).
731 "' onclick=\"javascript:return confirm('Are you sure you want to reset most of object properties?')\">" . getImageHREF ('clear', 'Reset (cleanup) object') . "</a>";
732 echo "</td></tr>\n";
733 echo "<tr><td colspan=3><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
734
735 echo "<tr><th class=submit colspan=3>";
736 printImageHREF ('SAVE', 'Save changes', TRUE);
737 echo "</form></th></tr></table>\n";
738 finishPortlet();
739
740 echo '<table border=0 width=100%><tr><td>';
741 startPortlet ('history');
742 renderHistory ($pageno, $object_id);
743 finishPortlet();
744 echo '</td></tr></table>';
745 }
746
747 // This is a clone of renderEditObjectForm().
748 function renderEditRackForm ($rack_id)
749 {
750 global $pageno;
751 $rack = spotEntity ('rack', $rack_id);
752 amplifyCell ($rack);
753
754 startPortlet ('Rack attributes');
755 printOpFormIntro ('updateRack');
756 echo '<table border=0 align=center>';
757 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
758 printSelect (getRackRows(), array ('name' => 'rack_row_id'), $rack['row_id']);
759 echo "</td></tr>\n";
760 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
761 echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
762 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
763 if (count ($rack['mountedObjects']) == 0)
764 {
765 echo "<tr><th class=tdright>Actions:</th><td class=tdleft><a href='".
766 makeHrefProcess(array('op'=>'deleteRack', 'rack_id'=>$rack_id)).
767 "' onclick=\"javascript:return confirm('Are you sure you want to delete the rack?')\">Delete rack</a></td></tr>\n";
768 }
769 echo "<tr><td class=submit colspan=2>";
770 printImageHREF ('SAVE', 'Save changes', TRUE);
771 echo "</td></tr>\n";
772 echo '</form></table><br>';
773 finishPortlet();
774
775 startPortlet ('History');
776 renderHistory ($pageno, $rack_id);
777 finishPortlet();
778 }
779
780 function printSelect ($optionList, $select_attrs = array(), $selected_id = NULL)
781 {
782 echo getSelect ($optionList, $select_attrs, $selected_id);
783 }
784
785 // Input array keys are OPTION VALUEs and input array values are OPTION text.
786 function getSelect ($optionList, $select_attrs = array(), $selected_id = NULL)
787 {
788 $ret = '';
789 if (!array_key_exists ('name', $select_attrs))
790 return '';
791 // handle two corner cases in a specific way
792 if (count ($optionList) == 0)
793 return '(none)';
794 if (count ($optionList) == 1)
795 {
796 $value = current (array_keys ($optionList));
797 return "<input type=hidden name=${select_attrs['name']} id=${select_attrs['name']} value=${value}>" . current ($optionList);
798 }
799 if (!array_key_exists ('id', $select_attrs))
800 $select_attrs['id'] = $select_attrs['name'];
801 $ret .= '<select';
802 foreach ($select_attrs as $attr_name => $attr_value)
803 $ret .= " ${attr_name}=${attr_value}";
804 $ret .= '>';
805 foreach ($optionList as $dict_key => $dict_value)
806 $ret .= "<option value='${dict_key}'" . ($dict_key == $selected_id ? ' selected' : '') . ">${dict_value}</option>";
807 $ret .= '</select>';
808 return $ret;
809 }
810
811 function printNiftySelect ($groupList, $select_attrs = array(), $selected_id = NULL, $autocomplete = false)
812 {
813 echo getNiftySelect ($groupList, $select_attrs, $selected_id);
814 }
815
816 // Input is a cooked list of OPTGROUPs, each with own sub-list of OPTIONs in the same
817 // format as printSelect() expects.
818 function getNiftySelect ($groupList, $select_attrs, $selected_id = NULL)
819 {
820 // special treatment for ungrouped data
821 if (count ($groupList) == 1 and isset ($groupList['other']))
822 return getSelect ($groupList['other'], $select_attrs, $selected_id);
823 if (!array_key_exists ('name', $select_attrs))
824 return '';
825 if (!array_key_exists ('id', $select_attrs))
826 $select_attrs['id'] = $select_attrs['name'];
827 $ret = '<select';
828 foreach ($select_attrs as $attr_name => $attr_value)
829 $ret .= " ${attr_name}=${attr_value}";
830 $ret .= '>';
831 foreach ($groupList as $groupname => $groupdata)
832 {
833 $ret .= "<optgroup label='${groupname}'>";
834 foreach ($groupdata as $dict_key => $dict_value)
835 $ret .= "<option value='${dict_key}'" . ($dict_key == $selected_id ? ' selected' : '') . ">${dict_value}</option>";
836 $ret .= '</optgroup>';
837 }
838 $ret .= '</select>';
839 return $ret;
840 }
841
842 // used by renderGridForm() and renderRackPage()
843 function renderRackInfoPortlet ($rackData)
844 {
845 startPortlet ('summary');
846 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
847 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
848 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
849 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
850 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
851 renderProgressBar (getRSUforRack ($rackData));
852 echo "</td></tr>\n";
853 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
854 echo count ($rackData['mountedObjects']);
855 echo "</td></tr>\n";
856 printTagTRs ($rackData, makeHref(array('page'=>'rackspace', 'tab'=>'default'))."&");
857 if (strlen ($rackData['comment']))
858 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
859 echo '</table>';
860 finishPortlet();
861 }
862
863 // This is a universal editor of rack design/waste.
864 // FIXME: switch to using printOpFormIntro()
865 function renderGridForm ($rack_id, $filter, $header, $submit, $state1, $state2)
866 {
867 $rackData = spotEntity ('rack', $rack_id);
868 amplifyCell ($rackData);
869 $filter ($rackData);
870 markupObjectProblems ($rackData);
871
872 // Render the result whatever it is.
873 // Main layout.
874 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
875 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
876
877 // Left column with information portlet.
878 echo "<tr><td class=pcleft height='1%' width='50%'>";
879 renderRackInfoPortlet ($rackData);
880 echo "</td>\n";
881 echo "<td class=pcright>";
882
883 // Grid form.
884 startPortlet ($header);
885 addJS ('js/racktables.js');
886 echo "<center>\n";
887 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
888 echo "<tr><th width='10%'>&nbsp;</th>";
889 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
890 echo "<th width='50%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
891 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
892 printOpFormIntro ('updateRack');
893 markupAtomGrid ($rackData, $state2);
894 renderAtomGrid ($rackData);
895 echo "</table></center>\n";
896 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
897 finishPortlet();
898 echo "</td></tr></table>\n";
899 }
900
901 function renderRackDesign ($rack_id)
902 {
903 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
904 }
905
906 function renderRackProblems ($rack_id)
907 {
908 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
909 }
910
911 function startPortlet ($title = '')
912 {
913 echo "<div class=portlet><h2>${title}</h2>";
914 }
915
916 function finishPortlet ()
917 {
918 echo "</div>\n";
919 }
920
921 function renderRackObject ($object_id)
922 {
923 global $nextorder, $aac;
924 $info = spotEntity ('object', $object_id);
925 // FIXME: employ amplifyCell() instead of calling loader functions directly
926 amplifyCell ($info);
927 // Main layout starts.
928 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
929 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
930 // left column with uknown number of portlets
931 echo "<tr><td class=pcleft>";
932 startPortlet ('summary');
933 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
934 if (strlen ($info['name']))
935 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
936 // FIXME: don't call spotEntity() each time, do it once in the beginning.
937 elseif (considerConfiguredConstraint ($info, 'NAMEWARN_LISTSRC'))
938 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
939 echo "<tr><th width='50%' class=tdright>Object type:</th><td class=tdleft><a href='";
940 echo makeHref (array (
941 'page' => 'depot',
942 'tab' => 'default',
943 'cfe' => '{$typeid_' . $info['objtype_id'] . '}'
944 ));
945 echo "'>" . decodeObjectType ($info['objtype_id'], 'o') . '</a></td></tr>';
946 if (strlen ($info['asset_no']))
947 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
948 // FIXME: ditto
949 elseif (considerConfiguredConstraint ($info, 'ASSETWARN_LISTSRC'))
950 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
951 if (strlen ($info['label']))
952 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
953 if (strlen ($info['barcode']))
954 echo "<tr><th width='50%' class=tdright>Barcode:</th><td class=tdleft>${info['barcode']}</td></tr>\n";
955 if ($info['has_problems'] == 'yes')
956 echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
957 foreach (getAttrValues ($object_id) as $attr_id => $record)
958 if (strlen ($record['value']))
959 {
960 echo "<tr><th width='50%' class=sticker>${record['name']}:</th><td class=sticker>" .
961 formatAttributeValue($attr_id, $record) .
962 "</td></tr>\n";
963 }
964 printTagTRs
965 (
966 $info,
967 makeHref
968 (
969 array
970 (
971 'page'=>'depot',
972 'tab'=>'default',
973 'andor' => 'and',
974 'cfe' => '{$typeid_' . $info['objtype_id'] . '}',
975 )
976 )."&"
977 );
978 echo "</table><br>\n";
979 finishPortlet();
980
981 if (strlen ($info['comment']))
982 {
983 startPortlet ('Comment');
984 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
985 finishPortlet ();
986 }
987
988 if (count ($logrecords = getLogRecordsForObject ($_REQUEST['object_id'])))
989 {
990 startPortlet ('log records');
991 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='100%'>";
992 $order = 'odd';
993 foreach (getLogRecordsForObject ($_REQUEST['object_id']) as $row)
994 {
995 echo "<tr class=row_${order} valign=top>";
996 echo '<td class=tdleft>' . $row['date'] . '<br>' . $row['user'] . '</td>';
997 echo '<td class="slbconf rsvtext">' . string_insert_hrefs ($row['content']) . '</td>';
998 echo '</tr>';
999 $order = $nextorder[$order];
1000 }
1001 echo '</table>';
1002 finishPortlet();
1003 }
1004
1005 switchportInfoJS ($object_id); // load JS code to make portnames interactive
1006 renderFilesPortlet ('object', $object_id);
1007
1008 if (count ($info['ports']))
1009 {
1010 startPortlet ('ports and links');
1011 $hl_port_id = 0;
1012 if (isset ($_REQUEST['hl_port_id']))
1013 {
1014 assertUIntArg ('hl_port_id');
1015 $hl_port_id = $_REQUEST['hl_port_id'];
1016 addAutoScrollScript ("port-$hl_port_id");
1017 }
1018 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>";
1019 echo '<tr><th class=tdleft>Local name</th><th class=tdleft>Visible label</th>';
1020 echo '<th class=tdleft>Interface</th><th class=tdleft>L2 address</th>';
1021 echo '<th class=tdcenter colspan=2>Remote object and port</th>';
1022 echo '<th class=tdleft>Cable ID</th></tr>';
1023 foreach ($info['ports'] as $port)
1024 {
1025 echo '<tr';
1026 if ($hl_port_id == $port['id'])
1027 echo ' class=port_highlight';
1028 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
1029 echo "><td class='tdleft' NOWRAP><a name='port-${port['id']}' class='interactive-portname nolink $a_class'>${port['name']}</a></td>";
1030 echo "<td class=tdleft>${port['label']}</td>";
1031 echo "<td class=tdleft>" . formatPortIIFOIF ($port) . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
1032 if ($port['remote_object_id'])
1033 {
1034 $remote_object = spotEntity ('object', $port['remote_object_id']);
1035 echo "<td class=tdleft><a href='".makeHref(array('page'=>'object', 'object_id'=>$port['remote_object_id'], 'hl_port_id'=>$port['remote_id']))."'>${remote_object['dname']}</a></td>";
1036 echo "<td class=tdleft>${port['remote_name']}</td>";
1037 echo "<td class='tdleft rsvtext'>${port['cableid']}</td>";
1038 }
1039 elseif (strlen ($port['reservation_comment']))
1040 {
1041 echo "<td class=tdleft><b>Reserved:</b></td>";
1042 echo "<td class='tdleft rsvtext'>${port['reservation_comment']}</td><td>&nbsp;</td>";
1043 }
1044 else
1045 echo '<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>';
1046 echo "</tr>";
1047 }
1048 echo "</table><br>";
1049 finishPortlet();
1050 }
1051
1052 if (count ($info['ipv4']) + count ($info['ipv6']))
1053 {
1054 startPortlet ('IP addresses');
1055 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1056 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1057 echo "<tr><th>OS interface</th><th>IP address</th><th>network</th><th>routed by</th><th>peers</th></tr>\n";
1058 else
1059 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
1060 $hl_ip_addr = '';
1061 if (isset ($_REQUEST['hl_ipv6_addr']))
1062 {
1063 if ($hl_ipv6 = assertIPv6Arg ('hl_ipv6_addr'))
1064 $hl_ip_addr = $hl_ipv6->format();
1065 }
1066 elseif (isset ($_REQUEST['hl_ipv4_addr']))
1067 $hl_ip_addr = $_REQUEST['hl_ipv4_addr'];
1068 if ($hl_ip_addr)
1069 addAutoScrollScript ("ip-$hl_ip_addr");
1070
1071 // group IP allocations by interface name instead of address family
1072 $allocs_by_iface = array();
1073 foreach (array ('ipv4', 'ipv6') as $ip_v)
1074 foreach ($info[$ip_v] as $dottedquad => $alloc)
1075 $allocs_by_iface[$alloc['osif']][$dottedquad] = $alloc;
1076
1077 // sort allocs array by portnames
1078 foreach (sortPortList ($allocs_by_iface) as $iface_name => $alloclist)
1079 {
1080 $is_first_row = TRUE;
1081 foreach ($alloclist as $dottedquad => $alloc)
1082 {
1083 if ($alloc['addrinfo']['version'] == 6)
1084 {
1085 $addr_page_name = 'ipv6address';
1086 $ipv6_address = new IPv6Address ($dottedquad);
1087 $dottedquad = $ipv6_address->format();
1088 if ($netid = getIPv6AddressNetworkId ($ipv6_address))
1089 {
1090 $netinfo = spotEntity ('ipv6net', $netid);
1091 loadIPv6AddrList ($netinfo);
1092 }
1093 }
1094 else
1095 {
1096 $addr_page_name = 'ipaddress';
1097 if ($netid = getIPv4AddressNetworkId ($dottedquad))
1098 {
1099 $netinfo = spotEntity ('ipv4net', $netid);
1100 loadIPv4AddrList ($netinfo);
1101 }
1102 }
1103 $address_name = niftyString ($alloc['addrinfo']['name']);
1104 $class = $alloc['addrinfo']['class'];
1105 $secondclass = ($hl_ip_addr == $dottedquad) ? 'tdleft port_highlight' : 'tdleft';
1106 echo "<tr class='${class}' valign=top>";
1107
1108 // display iface name (common cell for both address families)
1109 if ($is_first_row)
1110 {
1111 $rowspan = count ($alloclist) > 1 ? 'rowspan="' . count ($alloclist) . '"' : '';
1112 echo "<td class=tdleft $rowspan>$iface_name</td>";
1113 $is_first_row = FALSE;
1114 }
1115 echo "<td class='${secondclass}'>";
1116 if (NULL !== $netid)
1117 echo "<a name='ip-$dottedquad' href='index.php?page=$addr_page_name&hl_object_id=$object_id&ip=$dottedquad'>${dottedquad}</a>";
1118 else
1119 echo $dottedquad;
1120 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1121 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1122 echo '&nbsp;' . $aac[$alloc['type']];
1123 if (strlen ($alloc['addrinfo']['name']))
1124 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1125 echo '</td>';
1126 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1127 {
1128 if (NULL === $netid)
1129 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1130 else
1131 {
1132 echo "<td class='${secondclass}'>";
1133 renderCell ($netinfo);
1134 echo "</td>";
1135 // filter out self-allocation
1136 $other_routers = array();
1137 foreach (findRouters ($netinfo['addrlist']) as $router)
1138 if ($router['id'] != $object_id)
1139 $other_routers[] = $router;
1140 if (count ($other_routers))
1141 printRoutersTD ($other_routers);
1142 else
1143 echo "<td class='${secondclass}'>&nbsp;</td>";
1144 }
1145 }
1146 // peers
1147 echo "<td class='${secondclass}'>\n";
1148 $prefix = '';
1149 if ($alloc['addrinfo']['reserved'] == 'yes')
1150 {
1151 echo $prefix . '<strong>RESERVED</strong>';
1152 $prefix = '; ';
1153 }
1154 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1155 {
1156 if ($allocpeer['object_id'] == $object_id)
1157 continue;
1158 echo $prefix . "<a href='" . makeHref (array ('page' => 'object', 'object_id' => $allocpeer['object_id'])) . "'>";
1159 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
1160 echo $allocpeer['osif'] . '@';
1161 echo $allocpeer['object_name'] . '</a>';
1162 $prefix = '; ';
1163 }
1164 echo "</td></tr>\n";
1165 }
1166 }
1167 echo "</table><br>\n";
1168 finishPortlet();
1169 }
1170
1171 $forwards = $info['nat4'];
1172 if (count($forwards['in']) or count($forwards['out']))
1173 {
1174 startPortlet('NATv4');
1175
1176 if (count($forwards['out']))
1177 {
1178
1179 echo "<h3>locally performed NAT</h3>";
1180
1181 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
1182 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
1183
1184 foreach ($forwards['out'] as $pf)
1185 {
1186 $class = 'trerror';
1187 $osif = '';
1188 if (isset ($alloclist [$pf['localip']]))
1189 {
1190 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
1191 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
1192 }
1193 echo "<tr class='$class'>";
1194 echo "<td>${pf['proto']}</td><td class=tdleft>${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
1195 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
1196 $address = getIPv4Address ($pf['remoteip']);
1197 echo "<td class='description'>";
1198 if (count ($address['allocs']))
1199 foreach($address['allocs'] as $bond)
1200 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
1201 elseif (strlen ($pf['remote_addr_name']))
1202 echo '(' . $pf['remote_addr_name'] . ')';
1203 echo "</td><td class='description'>${pf['description']}</td></tr>";
1204 }
1205 echo "</table><br><br>";
1206 }
1207 if (count($forwards['in']))
1208 {
1209 echo "<h3>arriving NAT connections</h3>";
1210 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
1211 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
1212 foreach ($forwards['in'] as $pf)
1213 {
1214 echo "<tr>";
1215 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
1216 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
1217 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
1218 echo "<td class='description'>${pf['description']}</td></tr>";
1219 }
1220 echo "</table><br><br>";
1221 }
1222 finishPortlet();
1223 }
1224
1225 $pools = $info['ipv4rspools'];
1226 if (count ($pools))
1227 {
1228 $order = 'odd';
1229 startPortlet ('Real server pools (' . count ($pools) . ')');
1230 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
1231 echo "<tr><th>VS</th><th>RS pool</th><th>RS</th><th>VS config</th><th>RS config</th><th>Prio</th></tr>\n";
1232 foreach ($pools as $vs_id => $info)
1233 {
1234 echo "<tr valign=top class=row_${order}><td class=tdleft>";
1235 renderCell (spotEntity ('ipv4vs', $vs_id));
1236 echo "</td><td class=tdleft>";
1237 renderCell (spotEntity ('ipv4rspool', $info['pool_id']));
1238 echo '</td><td class=tdleft>' . $info['rscount'] . '</td>';
1239 echo "<td class=slbconf>${info['vsconfig']}</td>";
1240 echo "<td class=slbconf>${info['rsconfig']}</td>";
1241 echo "<td class=slbconf>${info['prio']}</td>";
1242 echo "</tr>\n";
1243 $order = $nextorder[$order];
1244 }
1245 echo "</table>\n";
1246 finishPortlet();
1247 }
1248 echo "</td>\n";
1249
1250 // After left column we have (surprise!) right column with rackspace portlet only.
1251 echo "<td class=pcright>";
1252 // rackspace portlet
1253 startPortlet ('rackspace allocation');
1254 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1255 renderRack ($rack_id, $object_id);
1256 echo '<br>';
1257 finishPortlet();
1258 echo "</td></tr>";
1259 echo "</table>\n";
1260 }
1261
1262 function renderRackMultiSelect ($sname, $racks, $selected)
1263 {
1264 // Transform the given flat list into a list of groups, each representing a rack row.
1265 $rdata = array();
1266 foreach ($racks as $rack)
1267 if (!isset ($rdata[$rack['row_name']]))
1268 $rdata[$rack['row_name']] = array ($rack['id'] => $rack['name']);
1269 else
1270 $rdata[$rack['row_name']][$rack['id']] = $rack['name'];
1271 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementsByName(\"updateObjectAllocation\")[0].submit()'>\n";
1272 foreach ($rdata as $optgroup => $racklist)
1273 {
1274 echo "<optgroup label='${optgroup}'>";
1275 foreach ($racklist as $rack_id => $rack_name)
1276 {
1277 echo "<option value=${rack_id}";
1278 if (!(array_search ($rack_id, $selected) === FALSE))
1279 echo ' selected';
1280 echo">${rack_name}</option>\n";
1281 }
1282 }
1283 echo "</select>\n";
1284 }
1285
1286 // This function renders a form for port edition.
1287 function renderPortsForObject ($object_id)
1288 {
1289 $prefs = getPortListPrefs();
1290 function printNewItemTR ($prefs)
1291 {
1292 printOpFormIntro ('addPort');
1293 echo "<tr><td>";
1294 printImageHREF ('add', 'add a port', TRUE);
1295 echo "</td><td class='tdleft'><input type=text size=8 name=port_name tabindex=100></td>\n";
1296 echo "<td><input type=text name=port_label tabindex=101></td><td>";
1297 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 102), $prefs['selected']);
1298 echo "<td><input type=text name=port_l2address tabindex=103 size=18 maxlength=24></td>\n";
1299 echo "<td colspan=3>&nbsp;</td><td>";
1300 printImageHREF ('add', 'add a port', TRUE, 104);
1301 echo "</td></tr></form>";
1302 }
1303 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes' || getConfigVar('ENABLE_BULKPORT_FORM') == 'yes' )
1304 startPortlet ('Ports and interfaces');
1305 else
1306 echo '<br>';
1307 $object = spotEntity ('object', $object_id);
1308 amplifyCell ($object);
1309 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1310 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1311 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>Start Number</th>";
1312 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1313 printOpFormIntro ('addBulkPorts');
1314 echo "<tr><td>";
1315 printImageHREF ('add', 'add ports', TRUE);
1316 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1317 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1318 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1319 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1320 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1321 echo "<td>&nbsp;</td><td>";
1322 printImageHREF ('add', 'add ports', TRUE, 110);
1323 echo "</td></tr></form>";
1324 echo "</table><br>\n";
1325 }
1326
1327 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1328 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>L2 address</th>";
1329 echo "<th class=tdcenter colspan=2>Cable, Remote object and port</th><th class=tdcenter>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
1330 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1331 printNewItemTR ($prefs);
1332 if (isset ($_REQUEST['hl_port_id']))
1333 {
1334 assertUIntArg ('hl_port_id');
1335 $hl_port_id = intval ($_REQUEST['hl_port_id']);
1336 addAutoScrollScript ("port-$hl_port_id");
1337 }
1338 switchportInfoJS ($object_id); // load JS code to make portnames interactive
1339 foreach ($object['ports'] as $port)
1340 {
1341 $tr_class = isset ($hl_port_id) && $hl_port_id == $port['id'] ? 'class="port_highlight"' : '';
1342 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
1343 echo "<tr $tr_class><td><a name='port-${port['id']}' href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id'], 'object_id'=>$object_id, 'port_name'=>$port['name']))."'>";
1344 printImageHREF ('delete', 'Unlink and Delete this port');
1345 echo "</a></td>\n";
1346 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
1347 echo "<td class='tdleft' NOWRAP><input type=text name=name class='interactive-portname $a_class' value='${port['name']}' size=8></td>";
1348 echo "<td><input type=text name=label value='${port['label']}'></td>";
1349 if (!$port['remote_object_id'])
1350 {
1351 echo '<td>';
1352 if ($port['iif_id'] != 1)
1353 echo '<label>' . $port['iif_name'] . ' ';
1354 printSelect (getExistingPortTypeOptions ($port['id']), array ('name' => 'port_type_id'), $port['oif_id']);
1355 if ($port['iif_id'] != 1)
1356 echo '</label>';
1357 echo '</td>';
1358 }
1359 else
1360 {
1361 echo "<input type=hidden name=port_type_id value='${port['oif_id']}'><td class=tdleft>";
1362 echo formatPortIIFOIF ($port) . '</td>';
1363 }
1364 // 18 is enough to fit 6-byte MAC address in its longest form,
1365 // while 24 should be Ok for WWN
1366 echo "<td><input type=text name=l2address value='${port['l2address']}' size=18 maxlength=24></td>\n";
1367 if ($port['remote_object_id'])
1368 {
1369 $remote_object = spotEntity ('object', $port['remote_object_id']);
1370 echo "<td>${port['cableid']}&nbsp;<a href='".makeHref(array('page'=>'object', 'object_id'=>$port['remote_object_id']))."'>${remote_object['dname']}</a></td>";
1371 echo "<td>${port['remote_name']}<input type=hidden name=reservation_comment value=''></td>";
1372 echo "<td class=tdcenter><a href='".
1373 makeHrefProcess(array(
1374 'op'=>'unlinkPort',
1375 'port_id'=>$port['id'],
1376 'remote_port_id' => $port['remote_id'],
1377 'object_id'=>$object_id)).
1378 "'>";
1379 printImageHREF ('cut', 'Unlink this port');
1380 echo "</a></td>";
1381 }
1382 elseif (strlen ($port['reservation_comment']))
1383 {
1384 echo "<td><b>Reserved:</b></td>";
1385 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
1386 echo "<td class=tdcenter><a href='".
1387 makeHrefProcess(array(
1388 'op'=>'useup',
1389 'port_id'=>$port['id'],
1390 'object_id'=>$object_id)).
1391 "'>";
1392 printImageHREF ('clear', 'Use up this port');
1393 echo "</a></td>";
1394 }
1395 else
1396 {
1397 //echo "<td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><a href='javascript:;'";
1398 echo "<td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><span";
1399 $helper_args = array
1400 (
1401 'port' => $port['id'],
1402 'in_rack' => 'n',
1403 );
1404 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
1405 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
1406 echo " ondblclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1407 echo "\",\"findlink\",\"${popup_args}\");'";
1408 // end of onclick=
1409 $helper_args['in_rack'] = 'y';
1410 echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1411 echo "\",\"findlink\",\"${popup_args}\");'";
1412 // end of onclick=
1413 echo '>';
1414 // end of <a>
1415 printImageHREF ('plug', 'Link this port');
1416 echo "</span>";
1417 echo " <input type=text name=reservation_comment></td>\n";
1418 }
1419 echo "<td>";
1420 printImageHREF ('save', 'Save changes', TRUE);
1421 echo "</td></form></tr>\n";
1422 }
1423 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1424 printNewItemTR ($prefs);
1425 echo "</table><br>\n";
1426 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1427 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1428 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>Start Number</th>";
1429 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1430 printOpFormIntro ('addBulkPorts');
1431 echo "<tr><td>";
1432 printImageHREF ('add', 'add ports', TRUE);
1433 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1434 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1435 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1436 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1437 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1438 echo "<td>&nbsp;</td><td>";
1439 printImageHREF ('add', 'add ports', TRUE, 110);
1440 echo "</td></tr></form>";
1441 echo "</table><br>\n";
1442 }
1443 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes')
1444 finishPortlet();
1445 if (getConfigVar('ENABLE_MULTIPORT_FORM') != 'yes')
1446 return;
1447
1448 startPortlet ('Add/update multiple ports');
1449 printOpFormIntro ('addMultiPorts');
1450 echo 'Format: <select name=format tabindex=201>';
1451 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1452 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
1453 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
1454 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
1455 echo "</select>";
1456 echo 'Default port type: ';
1457 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type', 'tabindex' => 202), $prefs['selected']);
1458 echo "<input type=submit value='Parse output' tabindex=204><br>\n";
1459 echo "<textarea name=input cols=100 rows=50 tabindex=203></textarea><br>\n";
1460 echo '</form>';
1461 finishPortlet();
1462 }
1463
1464 function renderIPv4ForObject ($object_id)
1465 {
1466 function printNewItemTR ()
1467 {
1468 global $aat;
1469 printOpFormIntro ('addIPv4Allocation');
1470 echo "<tr><td>";
1471 printImageHREF ('add', 'allocate', TRUE);
1472 echo "</td>";
1473 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1474 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
1475 echo "<td colspan=2>&nbsp;</td><td>";
1476 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), 'regular');
1477 echo "</td><td>&nbsp;</td><td>";
1478 printImageHREF ('add', 'allocate', TRUE, 103);
1479 echo "</td></tr></form>";
1480 }
1481 $focus = spotEntity ('object', $object_id);
1482 amplifyCell ($focus);
1483 global $aat;
1484 startPortlet ('Allocations');
1485 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1486 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1487 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1488 echo '<th>network</th><th>routed by</th>';
1489 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1490
1491 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1492 printNewItemTR();
1493 foreach ($focus['ipv4'] as $dottedquad => $alloc)
1494 {
1495 $class = $alloc['addrinfo']['class'];
1496 $netid = getIPv4AddressNetworkId ($dottedquad);
1497 if (NULL !== $netid)
1498 {
1499 $netinfo = spotEntity ('ipv4net', $netid);
1500 loadIPv4AddrList ($netinfo);
1501 }
1502 printOpFormIntro ('updIPv4Allocation', array ('ip' => $dottedquad));
1503 echo "<tr class='$class' valign=top><td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$object_id))."'>";
1504 printImageHREF ('delete', 'Delete this IPv4 address');
1505 echo "</a></td>";
1506 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td><td class=tdleft>";
1507 if (NULL !== $netid)
1508 echo "<a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$dottedquad))."'>${dottedquad}</a>";
1509 else
1510 echo $dottedquad;
1511 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1512 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1513 if (strlen ($alloc['addrinfo']['name']))
1514 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1515 echo '</td>';
1516 // FIXME: this a copy-and-paste from renderRackObject()
1517 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1518 {
1519 if (NULL === $netid)
1520 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1521 else
1522 {
1523 echo '<td>';
1524 renderCell ($netinfo);
1525 echo '</td>';
1526 // filter out self-allocation
1527 $other_routers = array();
1528 foreach (findRouters ($netinfo['addrlist']) as $router)
1529 if ($router['id'] != $object_id)
1530 $other_routers[] = $router;
1531 if (count ($other_routers))
1532 printRoutersTD ($other_routers);
1533 else
1534 echo "<td>&nbsp;</td>";
1535 }
1536 }
1537 echo '<td>';
1538 printSelect ($aat, array ('name' => 'bond_type'), $alloc['type']);
1539 echo "</td><td>";
1540 $prefix = '';
1541 if ($alloc['addrinfo']['reserved'] == 'yes')
1542 {
1543 echo $prefix . '<strong>RESERVED</strong>';
1544 $prefix = '; ';
1545 }
1546 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1547 {
1548 if ($allocpeer['object_id'] == $object_id)
1549 continue;
1550 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1551 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
1552 echo $allocpeer['osif'] . '@';
1553 echo $allocpeer['object_name'] . '</a>';
1554 $prefix = '; ';
1555 }
1556 echo "</td><td>";
1557 printImageHREF ('save', 'Save changes', TRUE);
1558 echo "</td></form></tr>\n";
1559 }
1560 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1561 printNewItemTR();
1562
1563 echo "</table><br>\n";
1564 finishPortlet();
1565
1566 }
1567
1568 function renderIPv6ForObject ($object_id)
1569 {
1570 function printNewItemTR ()
1571 {
1572 global $aat;
1573 printOpFormIntro ('addIPv6Allocation');
1574 echo "<tr><td>";
1575 printImageHREF ('add', 'allocate', TRUE);
1576 echo "</td>";
1577 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1578 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
1579 echo "<td colspan=2>&nbsp;</td><td>";
1580 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), 'regular');
1581 echo "</td><td>&nbsp;</td><td>";
1582 printImageHREF ('add', 'allocate', TRUE, 103);
1583 echo "</td></tr></form>";
1584 }
1585 $focus = spotEntity ('object', $object_id);
1586 amplifyCell ($focus);
1587 global $aat;
1588 startPortlet ('Allocations');
1589 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1590 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1591 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1592 echo '<th>network</th><th>routed by</th>';
1593 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1594
1595 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1596 printNewItemTR();
1597 foreach ($focus['ipv6'] as $bin_str => $alloc)
1598 {
1599 $ipv6 = new IPv6Address ($bin_str);
1600 $dottedquad = $ipv6->format();
1601 $class = $alloc['addrinfo']['class'];
1602 $netid = getIPv6AddressNetworkId ($ipv6);
1603 if (NULL !== $netid)
1604 {
1605 $netinfo = spotEntity ('ipv6net', $netid);
1606 loadIPv6AddrList ($netinfo);
1607 }
1608 printOpFormIntro ('updIPv6Allocation', array ('ip' => $dottedquad));
1609 echo "<tr class='$class' valign=top><td><a href='".makeHrefProcess(array('op'=>'delIPv6Allocation', 'ip'=>$dottedquad, 'object_id'=>$object_id))."'>";
1610 printImageHREF ('delete', 'Delete this IPv6 address');
1611 echo "</a></td>";
1612 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td><td class=tdleft>";
1613 if (NULL !== $netid)
1614 echo "<a href='index.php?page=ipv6address&ip=$dottedquad'>$dottedquad</a>";
1615 else
1616 echo $dottedquad;
1617 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1618 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1619 if (strlen ($alloc['addrinfo']['name']))
1620 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1621 echo '</td>';
1622 // FIXME: this a copy-and-paste from renderRackObject()
1623 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1624 {
1625 if (NULL === $netid)
1626 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1627 else
1628 {
1629 echo '<td>';
1630 renderCell ($netinfo);
1631 echo '</td>';
1632 // filter out self-allocation
1633 $other_routers = array();
1634 foreach (findRouters ($netinfo['addrlist']) as $router)
1635 if ($router['id'] != $object_id)
1636 $other_routers[] = $router;
1637 if (count ($other_routers))
1638 printRoutersTD ($other_routers);
1639 else
1640 echo "<td>&nbsp;</td>";
1641 }
1642 }
1643 echo '<td>';
1644 printSelect ($aat, array ('name' => 'bond_type'), $alloc['type']);
1645 echo "</td><td>";
1646 $prefix = '';
1647 if ($alloc['addrinfo']['reserved'] == 'yes')
1648 {
1649 echo $prefix . '<strong>RESERVED</strong>';
1650 $prefix = '; ';
1651 }
1652 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1653 {
1654 if ($allocpeer['object_id'] == $object_id)
1655 continue;
1656 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1657 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
1658 echo $allocpeer['osif'] . '@';
1659 echo $allocpeer['object_name'] . '</a>';
1660 $prefix = '; ';
1661 }
1662 echo "</td><td>";
1663 printImageHREF ('save', 'Save changes', TRUE);
1664 echo "</td></form></tr>\n";
1665 }
1666 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1667 printNewItemTR();
1668
1669 echo "</table><br>\n";
1670 finishPortlet();
1671
1672 }
1673
1674 // Log structure versions:
1675 // 1: the whole structure is a list of code-message pairs
1676 // 2 and later: there's a "v" field set, which indicates the version
1677 // 2: there's a "m" list set to hold message code and optional arguments
1678 function showMessageOrError ()
1679 {
1680 if (!isset ($_SESSION['log']))
1681 return;
1682 $log = $_SESSION['log'];
1683 switch (TRUE)
1684 {
1685 case !isset ($log['v']):
1686 case $log['v'] == 1:
1687 foreach ($log as $key => $record)
1688 if ($key !== 'v')
1689 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1690 break;
1691 case $log['v'] == 2:
1692 $msginfo = array
1693 (
1694 // records 0~99 with success messages
1695 0 => array ('code' => 'success', 'format' => '%s'),
1696 1 => array ('code' => 'success', 'format' => '%u new records done, %u already existed'),
1697 2 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully added.'),
1698 3 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully deleted.'),
1699 4 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully updated'),
1700 5 => array ('code' => 'success', 'format' => 'Port %s was added successfully'),
1701 6 => array ('code' => 'success', 'format' => 'Port %s was updated successfully'),
1702 7 => array ('code' => 'success', 'format' => 'Port %s was deleted successfully'),
1703 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with port %s at object %s'),
1704 9 => array ('code' => 'success', 'format' => 'Port %s was successfully unlinked from %s@%s'),
1705 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1706 11 => array ('code' => 'success', 'format' => 'Reservation removed.'),
1707 12 => array ('code' => 'success', 'format' => 'allocation updated'),
1708 13 => array ('code' => 'success', 'format' => 'allocated'),
1709 14 => array ('code' => 'success', 'format' => 'deallocated'),
1710 15 => array ('code' => 'success', 'format' => 'Reset succeeded.'),
1711 16 => array ('code' => 'success', 'format' => 'Update done'),
1712 17 => array ('code' => 'success', 'format' => 'Update(s) succeeded.'),
1713 18 => array ('code' => 'success', 'format' => 'Load balancer was successfully added'),
1714 19 => array ('code' => 'success', 'format' => 'Load balancer was successfully deleted'),
1715 20 => array ('code' => 'success', 'format' => 'Load balancer info was successfully updated'),
1716 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1717 22 => array ('code' => 'success', 'format' => 'Chained %u tags'),
1718 23 => array ('code' => 'success', 'format' => 'IPv4 prefix successfully added'),
1719 24 => array ('code' => 'success', 'format' => 'IPv4 prefix deleted'),
1720 25 => array ('code' => 'success', 'format' => 'IPv4 prefix updated'),
1721 26 => array ('code' => 'success', 'format' => '%u IP address(es) were successfully updated'),
1722 27 => array ('code' => 'success', 'format' => 'IPv4 address updated'),
1723 28 => array ('code' => 'success', 'format' => 'Virtual service was successfully created'),
1724 29 => array ('code' => 'success', 'format' => 'Virtual service was successfully deleted'),
1725 30 => array ('code' => 'success', 'format' => 'Virtual service was successfully updated'),
1726 31 => array ('code' => 'success', 'format' => 'RS pool was successfully created'),
1727 32 => array ('code' => 'success', 'format' => 'RS pool was successfully deleted'),
1728 33 => array ('code' => 'success', 'format' => 'RS pool was successfully updated'),
1729 34 => array ('code' => 'success', 'format' => 'Real server was successfully added'),
1730 35 => array ('code' => 'success', 'format' => 'Real server was successfully deleted'),
1731 36 => array ('code' => 'success', 'format' => 'Real server was successfully updated'),
1732 37 => array ('code' => 'success', 'format' => 'Successfully added %u real servers'),
1733 38 => array ('code' => 'success', 'format' => '%u real server(s) were successfully (de)activated'),
1734 39 => array ('code' => 'success', 'format' => 'User account %s updated.'),
1735 40 => array ('code' => 'success', 'format' => 'User account %s created.'),
1736 41 => array ('code' => 'success', 'format' => 'uplink ports reverb queued'),
1737 // ...
1738 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1739 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1740 45 => array ('code' => 'success', 'format' => "Attribute '%s' created."),
1741 46 => array ('code' => 'success', 'format' => 'Rename successful.'),
1742 47 => array ('code' => 'success', 'format' => 'Attribute was deleted.'),
1743 48 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1744 49 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1745 50 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1746 51 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1747 52 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1748 53 => array ('code' => 'success', 'format' => 'Chapter was deleted.'),
1749 54 => array ('code' => 'success', 'format' => 'Chapter was updated.'),
1750 55 => array ('code' => 'success', 'format' => 'Chapter was added.'),
1751 56 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1752 57 => array ('code' => 'success', 'format' => 'Reset complete'),
1753 58 => array ('code' => 'success', 'format' => "Deleted tag '%s'."),
1754 59 => array ('code' => 'success', 'format' => "Created tag '%s'."),
1755 60 => array ('code' => 'success', 'format' => "Updated tag '%s'."),
1756 61 => array ('code' => 'success', 'format' => 'Password changed successfully.'),
1757 62 => array ('code' => 'success', 'format' => 'gw: %s'),
1758 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
1759 64 => array ('code' => 'success', 'format' => 'Port %s@%s has been assigned to VLAN %u'),
1760 65 => array ('code' => 'success', 'format' => "Added new rack '%s'"),
1761 66 => array ('code' => 'success', 'format' => "File sent Ok via handler '%s'"),
1762 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1763 68 => array ('code' => 'success', 'format' => "Updated rack '%s'"),
1764 69 => array ('code' => 'success', 'format' => 'File "%s" was added successfully'),
1765 70 => array ('code' => 'success', 'format' => 'File "%s" was updated successfully'),
1766 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
1767 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
1768 73 => array ('code' => 'success', 'format' => 'File "%s" was deleted successfully'),
1769 74 => array ('code' => 'success', 'format' => 'Record "%s" was added successfully'),
1770 75 => array ('code' => 'success', 'format' => 'Row "%s" was updated successfully'),
1771 76 => array ('code' => 'success', 'format' => 'Object "%s" was deleted successfully'),
1772 77 => array ('code' => 'success', 'format' => 'Record "%s" was deleted successfully'),
1773 78 => array ('code' => 'success', 'format' => 'File "%s" saved Ok'),
1774 79 => array ('code' => 'success', 'format' => 'Rack "%s" was deleted successfully'),
1775 80 => array ('code' => 'success', 'format' => "Added new object '%s'"),
1776 81 => array ('code' => 'success', 'format' => "SNMP: completed '%s' work"),
1777 82 => array ('code' => 'success', 'format' => "Bulk port creation was successful. %u ports created, %u failed"),
1778 83 => array ('code' => 'success', 'format' => 'Object "%s" was reset successfully'),
1779 84 => array ('code' => 'success', 'format' => 'IPv6 prefix successfully added'),
1780 85 => array ('code' => 'success', 'format' => 'IPv6 prefix deleted'),
1781 86 => array ('code' => 'success', 'format' => 'IPv6 prefix updated'),
1782 87 => array ('code' => 'success', 'format' => '802.1Q recalculate: %d ports changed on %d switches'),
1783 // records 100~199 with fatal error messages
1784 100 => array ('code' => 'error', 'format' => '%s'),
1785 101 => array ('code' => 'error', 'format' => 'Port name cannot be empty'),
1786 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
1787 103 => array ('code' => 'error', 'format' => 'User not found!'),
1788 104 => array ('code' => 'error', 'format' => "Error updating user account '%s'"),
1789 105 => array ('code' => 'error', 'format' => 'default VLAN cannot be changed'),
1790 // ...
1791 107 => array ('code' => 'error', 'format' => 'Assertion failed: %s'),
1792 108 => array ('code' => 'error', 'format' => 'Database error: %s'),
1793 109 => array ('code' => 'error', 'format' => 'Update failed!'),
1794 110 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1795 111 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1796 112 => array ('code' => 'error', 'format' => 'Error adding chapter.'),
1797 113 => array ('code' => 'error', 'format' => 'Error updating chapter.'),
1798 114 => array ('code' => 'error', 'format' => 'Error deleting chapter.'),
1799 115 => array ('code' => 'error', 'format' => 'Error renaming attribute.'),
1800 116 => array ('code' => 'error', 'format' => 'Error creating attribute.'),
1801 117 => array ('code' => 'error', 'format' => 'Error deleting attribute.'),
1802 118 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1803 119 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1804 120 => array ('code' => 'error', 'format' => 'Reset failed!'),
1805 121 => array ('code' => 'error', 'format' => 'commitUpdateObject() failed'),
1806 122 => array ('code' => 'error', 'format' => 'One or more update(s) failed!'),
1807 123 => array ('code' => 'error', 'format' => 'Cannot process submitted data: unknown format code.'),
1808 124 => array ('code' => 'error', 'format' => 'Error removing reservation!'),
1809 125 => array ('code' => 'error', 'format' => "Update failed with error: '%s'"),
1810 126 => array ('code' => 'error', 'format' => 'addRStoRSPool() failed'),
1811 127 => array ('code' => 'error', 'format' => 'Added %u real servers and encountered %u errors'),
1812 128 => array ('code' => 'error', 'format' => 'commitDeleteRS() failed'),
1813 129 => array ('code' => 'error', 'format' => 'commitDeleteLB() failed'),
1814 130 => array ('code' => 'error', 'format' => 'commitDeleteVS() failed'),
1815 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1816 132 => array ('code' => 'error', 'format' => 'invalid protocol'),
1817 133 => array ('code' => 'error', 'format' => 'commitUpdateRS() failed'),
1818 134 => array ('code' => 'error', 'format' => 'commitUpdateLB() failed'),
1819 135 => array ('code' => 'error', 'format' => 'commitUpdateVS() failed'),
1820 136 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1821 137 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1822 138 => array ('code' => 'error', 'format' => 'commitDeleteRSPool() failed'),
1823 139 => array ('code' => 'error', 'format' => 'commitUpdateRSPool() failed'),
1824 140 => array ('code' => 'error', 'format' => 'Encountered %u errors, (de)activated %u real servers'),
1825 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u record(s)'),
1826 142 => array ('code' => 'error', 'format' => 'executeAutoPorts() failed'),
1827 143 => array ('code' => 'error', 'format' => 'Tried chaining %u tags, but experienced %u errors.'),
1828 144 => array ('code' => 'error', 'format' => "Error deleting tag: '%s'"),
1829 145 => array ('code' => 'error', 'format' => "Invalid tag name '%s'"),
1830 146 => array ('code' => 'error', 'format' => 'Error deleting record "%s"'),
1831 147 => array ('code' => 'error', 'format' => "Could not create tag '%s'"),
1832 148 => array ('code' => 'error', 'format' => "Could not update tag '%s'"),
1833 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1834 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1835 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1836 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1837 153 => array ('code' => 'error', 'format' => 'Password change failed.'),
1838 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1839 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1840 156 => array ('code' => 'error', 'format' => 'getSwitchVLANs() failed'),
1841 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
1842 158 => array ('code' => 'error', 'format' => 'Ignoring malformed record #%u in form submit'),
1843 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1844 160 => array ('code' => 'error', 'format' => 'Invalid arguments'),
1845 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1846 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
1847 163 => array ('code' => 'error', 'format' => 'Failed to get any response from queryGateway() or the gateway died'),
1848 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
1849 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1850 166 => array ('code' => 'error', 'format' => 'gw: %s'),
1851 167 => array ('code' => 'error', 'format' => 'Could not find port %s'),
1852 168 => array ('code' => 'error', 'format' => 'Port %s is a trunk'),
1853 169 => array ('code' => 'error', 'format' => 'Failed to configure %s, connector returned code %u'),
1854 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1855 171 => array ('code' => 'error', 'format' => "Failed creating rack '%s'. Already exists in this row?"),
1856 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1857 173 => array ('code' => 'error', 'format' => "Invalid IPv4 prefix '%s'"),
1858 174 => array ('code' => 'error', 'format' => 'Bad IPv4 address'),
1859 175 => array ('code' => 'error', 'format' => 'Invalid netmask'),
1860 176 => array ('code' => 'error', 'format' => 'This network already exists'),
1861 177 => array ('code' => 'error', 'format' => 'commitUpdateRack() failed'),
1862 178 => array ('code' => 'error', 'format' => 'file not found'),
1863 179 => array ('code' => 'error', 'format' => 'Expired form has been declined.'),
1864 180 => array ('code' => 'error', 'format' => 'Error saving file, all changes lost!'),
1865 181 => array ('code' => 'error', 'format' => "file uploads not allowed, change 'file_uploads' parameter in php.ini"),
1866 182 => array ('code' => 'error', 'format' => 'SQL query failed: %s'),
1867 183 => array ('code' => 'error', 'format' => "Tag id '%s' does not exist."),
1868 184 => array ('code' => 'error', 'format' => 'Submitted form is invalid at line %u'),
1869 185 => array ('code' => 'error', 'format' => "Failed to add object '%s'"),
1870 186 => array ('code' => 'error', 'format' => 'Incomplete form has been ignored. Cheers.'),
1871 187 => array ('code' => 'error', 'format' => "Internal error in function '%s'"),
1872 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1873 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
1874 190 => array ('code' => 'error', 'format' => "Invalid VLAN ID '%s'"),
1875 191 => array ('code' => 'error', 'format' => "deploy was blocked due to conflicting configuration versions"),
1876 192 => array ('code' => 'error', 'format' => "Permission denied"),
1877
1878 // records 200~299 with warnings
1879 200 => array ('code' => 'warning', 'format' => '%s'),
1880 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1881 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
1882 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1883 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1884 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
1885 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
1886 207 => array ('code' => 'warning', 'format' => 'Ignored empty request'),
1887
1888 // records 300~399 with notices
1889 300 => array ('code' => 'neutral', 'format' => '%s'),
1890
1891 );
1892 // Handle the arguments. Is there any better way to do it?
1893 foreach ($log['m'] as $record)
1894 {
1895 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1896 {
1897 echo '<div class=msg_neutral>(this message was lost)</div>';
1898 continue;
1899 }
1900 if (isset ($record['a']))
1901 switch (count ($record['a']))
1902 {
1903 case 1:
1904 $msgtext = sprintf
1905 (
1906 $msginfo[$record['c']]['format'],
1907 $record['a'][0]
1908 );
1909 break;
1910 case 2:
1911 $msgtext = sprintf
1912 (
1913 $msginfo[$record['c']]['format'],
1914 $record['a'][0],
1915 $record['a'][1]
1916 );
1917 break;
1918 case 3:
1919 $msgtext = sprintf
1920 (
1921 $msginfo[$record['c']]['format'],
1922 $record['a'][0],
1923 $record['a'][1],
1924 $record['a'][2]
1925 );
1926 break;
1927 case 4:
1928 default:
1929 $msgtext = sprintf
1930 (
1931 $msginfo[$record['c']]['format'],
1932 $record['a'][0],
1933 $record['a'][1],
1934 $record['a'][2],
1935 $record['a'][3]
1936 );
1937 break;
1938 }
1939 else
1940 $msgtext = $msginfo[$record['c']]['format'];
1941 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1942 }
1943 break;
1944 default:
1945 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1946 break;
1947 }
1948 unset($_SESSION['log']);
1949 }
1950
1951 // renders two tables: port link status and learned MAC list
1952 function renderPortsInfo($object_id)
1953 {
1954 global $nextorder;
1955 echo "<table width='100%'><tr>";
1956
1957 if (permitted (NULL, NULL, 'get_link_status'))
1958 {
1959 try
1960 {
1961 $linkStatus = gwRetrieveDeviceConfig ($object_id, 'getportstatus');
1962 }
1963 catch (RackTablesError $e) {}
1964 if (! empty ($linkStatus))
1965 {
1966 echo "<td valign='top' width='50%'>";
1967 startPortlet('Link status');
1968 echo "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>Port<th>Link status<th>Link info</tr>";
1969 $order = 'even';
1970 foreach ($linkStatus as $pn => $link)
1971 {
1972 echo "<tr class='row_$order'>";
1973 $order = $nextorder[$order];
1974 echo '<td>' . $pn;
1975 echo '<td>' . $link['status'];
1976 $info = '';
1977 if (isset ($link['speed']))
1978 $info .= $link['speed'];
1979 if (isset ($link['duplex']))
1980 {
1981 if (! empty ($info))
1982 $info .= ', ';
1983 $info .= $link['duplex'];
1984 }
1985 echo '<td>' . $info;
1986 echo '</tr>';
1987 }
1988 echo "</table></td>";
1989 finishPortlet();
1990 }
1991 }
1992
1993 try
1994 {
1995 $macList = sortPortList (gwRetrieveDeviceConfig ($object_id, 'getmaclist'));
1996 }
1997 catch (RackTablesError $e) {}
1998 if (! empty ($macList))
1999 {
2000 echo "<td valign='top' width='50%'>";
2001 $rendered_macs = '';
2002 $mac_count = 0;
2003 $rendered_macs .= "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>MAC<th>Vlan<th>Port</tr>";
2004 $order = 'even';
2005 foreach ($macList as $pn => $list)
2006 {
2007 $order = $nextorder[$order];
2008 foreach ($list as $item)
2009 {
2010 ++$mac_count;
2011 $rendered_macs .= "<tr class='row_$order'>";
2012 $rendered_macs .= '<td style="font-family: monospace">' . $item['mac'];
2013 $rendered_macs .= '<td>' . $item['vid'];
2014 $rendered_macs .= '<td>' . $pn;
2015 $rendered_macs .= '</tr>';
2016 }
2017 }
2018 $rendered_macs .= "</table></td>";
2019
2020 startPortlet("Learned MACs ($mac_count)");
2021 echo $rendered_macs;
2022 finishPortlet();
2023 }
2024
2025 echo "</td></tr></table>";
2026 }
2027
2028 /*
2029 The following conditions must be met:
2030 1. We can mount onto free atoms only. This means: if any record for an atom
2031 already exists in RackSpace, it can't be used for mounting.
2032 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
2033 and either delete them before unmounting or refuse to unmount the object.
2034 */
2035 function renderRackSpaceForObject ($object_id)
2036 {
2037 // Always process occupied racks plus racks chosen by user. First get racks with
2038 // already allocated rackspace...
2039 $workingRacksData = getResidentRacksData ($object_id);
2040 // ...and then add those chosen by user (if any).
2041 if (isset($_REQUEST['rackmulti']))
2042 foreach ($_REQUEST['rackmulti'] as $cand_id)
2043 if (!isset ($workingRacksData[$cand_id]))
2044 {
2045 $rackData = spotEntity ('rack', $cand_id);
2046 amplifyCell ($rackData);
2047 $workingRacksData[$cand_id] = $rackData;
2048 }
2049
2050 // Main layout starts.
2051 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
2052
2053 // Left portlet with rack list.
2054 echo "<td class=pcleft height='1%'>";
2055 startPortlet ('Racks');
2056 $allRacksData = listCells ('rack');
2057 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
2058 foreach ($allRacksData as $rack)
2059 if (!array_key_exists ($rack['id'], $workingRacksData))
2060 {
2061 amplifyCell ($rack);
2062 $workingRacksData[$rack['id']] = $rack;
2063 }
2064 foreach (array_keys ($workingRacksData) as $rackId)
2065 applyObjectMountMask ($workingRacksData[$rackId], $object_id);
2066 printOpFormIntro ('updateObjectAllocation');
2067 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
2068 echo "<br><br>";
2069 finishPortlet();
2070 echo "</td>";
2071
2072 // Middle portlet with comment and submit.
2073 echo "<td class=pcleft>";
2074 startPortlet ('Comment');
2075 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
2076 echo "<input type=submit value='Save' name=got_atoms>\n";
2077 echo "<br><br>";
2078 finishPortlet();
2079 echo "</td>";
2080
2081 // Right portlet with rendered racks. If this form submit is not final, we have to
2082 // reflect the former state of the grid in current form.
2083 echo "<td class=pcright rowspan=2 height='1%'>";
2084 startPortlet ('Working copy');
2085 addJS ('js/racktables.js');
2086 echo '<table border=0 cellspacing=10 align=center><tr>';
2087 foreach ($workingRacksData as $rack_id => $rackData)
2088 {
2089 // Order is important here: only original allocation is highlighted.
2090 highlightObject ($rackData, $object_id);
2091 markupAtomGrid ($rackData, 'T');
2092 // If we have a form processed, discard user input and show new database
2093 // contents.
2094 if (isset ($_REQUEST['rackmulti'][0])) // is an update
2095 mergeGridFormToRack ($rackData);
2096 echo "<td valign=top>";
2097 echo "<center>\n<h2>${rackData['name']}</h2>\n";
2098 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
2099 echo "<tr><th width='10%'>&nbsp;</th>";
2100 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
2101 echo "<th width='50%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
2102 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
2103 renderAtomGrid ($rackData);
2104 echo "<tr><th width='10%'>&nbsp;</th>";
2105 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
2106 echo "<th width='50%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
2107 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
2108 echo "</table></center>\n";
2109 echo '</td>';
2110 }
2111 echo "</tr></table>";
2112 finishPortlet();
2113 echo "</td>\n";
2114
2115 echo "</form>\n";
2116 echo "</tr></table>\n";
2117 }
2118
2119 function renderMolecule ($mdata, $object_id)
2120 {
2121 // sort data out
2122 $rackpack = array();
2123 global $loclist;
2124 foreach ($mdata as $rua)
2125 {
2126 $rack_id = $rua['rack_id'];
2127 $unit_no = $rua['unit_no'];
2128 $atom = $rua['atom'];
2129 if (!isset ($rackpack[$rack_id]))
2130 {
2131 $rackData = spotEntity ('rack', $rack_id);
2132 amplifyCell ($rackData);
2133 for ($i = $rackData['height']; $i > 0; $i--)
2134 for ($locidx = 0; $locidx < 3; $locidx++)
2135 $rackData[$i][$locidx]['state'] = 'F';
2136 $rackpack[$rack_id] = $rackData;
2137 }
2138 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
2139 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
2140 }
2141 // now we have some racks to render
2142 addAtomCSS();
2143 foreach ($rackpack as $rackData)
2144 {
2145 markAllSpans ($rackData);
2146 echo "<table class=molecule cellspacing=0>\n";
2147 echo "<caption>${rackData['name']}</caption>\n";
2148 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
2149 for ($i = $rackData['height']; $i > 0; $i--)
2150 {
2151 echo "<tr><th>$i</th>";
2152 for ($locidx = 0; $locidx < 3; $locidx++)
2153 {
2154 $state = $rackData[$i][$locidx]['state'];
2155 echo "<td class='atom state_${state}'>&nbsp;</td>\n";
2156 }
2157 echo "</tr>\n";
2158 }
2159 echo "</table>\n";
2160 }
2161 }
2162
2163 function renderDepot ()
2164 {
2165 global $pageno, $nextorder;
2166 $cellfilter = getCellFilter();
2167 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
2168
2169 echo "<table border=0 class=objectview>\n";
2170 echo "<tr><td class=pcleft>";
2171
2172 if (! renderEmptyResults ($cellfilter, 'objects', count($objects)))
2173 {
2174 startPortlet ('Objects (' . count ($objects) . ')');
2175 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2176 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Row/Rack</th></tr>';
2177 $order = 'odd';
2178 foreach ($objects as $obj)
2179 {
2180 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
2181 $secondclass = 'tdleft port_highlight';
2182 else
2183 $secondclass = 'tdleft';
2184 echo "<tr class=row_${order} valign=top><td class='${secondclass}'><a href='".makeHref(array('page'=>'object', 'object_id'=>$obj['id']))."'><strong>${obj['dname']}</strong></a>";
2185 if (count ($obj['etags']))
2186 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
2187 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
2188 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
2189 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
2190 if ($obj['rack_id'])
2191 echo "<td class='${secondclass}'><a href='".makeHref(array('page'=>'row', 'row_id'=>$obj['row_id']))."'>${obj['Row_name']}</a>/<a href='".makeHref(array('page'=>'rack', 'rack_id'=>$obj['rack_id']))."'>${obj['Rack_name']}</a></td>";
2192 else
2193 echo "<td class='${secondclass}'>Unmounted</td>";
2194 echo '</tr>';
2195 $order = $nextorder[$order];
2196 }
2197 echo '</table>';
2198 finishPortlet();
2199 }
2200
2201 echo "</td><td class=pcright width='25%'>";
2202
2203 renderCellFilterPortlet ($cellfilter, 'object', $objects);
2204 echo "</td></tr></table>\n";
2205 }
2206
2207 // This function returns TRUE if the result set is too big to be rendered, and no filter is set.
2208 // In this case it renders the describing message instead.
2209 function renderEmptyResults($cellfilter, $entities_name, $count = NULL)
2210 {
2211 if (!$cellfilter['is_empty'])
2212 return FALSE;
2213 if (isset ($_REQUEST['show_all_objects']))
2214 return FALSE;
2215 $max = intval(getConfigVar('MAX_UNFILTERED_ENTITIES'));
2216 if (0 == $max || $count <= $max)
2217 return FALSE;
2218
2219 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
2220 $href_show_all .= htmlspecialchars('&show_all_objects=1');
2221 $suffix = isset ($count) ? " ($count)" : '';
2222 echo <<<END
2223 <p>Please set a filter to display the corresponging $entities_name.
2224 <br><a href="$href_show_all">Show all $entities_name$suffix</a>
2225 END;
2226 return TRUE;
2227 }
2228
2229 // History viewer for history-enabled simple dictionaries.
2230 function renderHistory ($object_type, $object_id)
2231 {
2232 switch ($object_type)
2233 {
2234 case 'row':
2235 $query = "select ctime, user_name, name, comment from RackRowHistory where id = ? order by ctime";
2236 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>rack row comment</th></tr>';
2237 $extra = 3;
2238 break;
2239 case 'rack':
2240 $query =
2241 "select ctime, user_name, rh.name, rr.name as name, rh.height, rh.comment " .
2242 "from RackHistory as rh left join RackRow as rr on rh.row_id = rr.id " .
2243 "where rh.id = ? order by ctime";
2244 $header = '<tr><th>change time</th><th>author</th><th>rack name</th><th>rack row name</th><th>rack height</th><th>rack comment</th></tr>';
2245 $extra = 5;
2246 break;
2247 case 'object':
2248 $query =
2249 "select ctime, user_name, RackObjectHistory.name as name, label, barcode, asset_no, has_problems, dict_value, comment " .
2250 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key join Chapter on Dictionary.chapter_id = Chapter.id " .
2251 "where Chapter.name = 'RackObjectType' and RackObjectHistory.id=? order by ctime";
2252 $header = '<tr><th>change time</th><th>author</th><th>common name</th><th>visible label</th><th>barcode</th><th>asset no</th><th>has problems?</th><th>object type</th><th>comment</th></tr>';
2253 $extra = 8;
2254 break;
2255 default:
2256 throw new InvalidArgException ('object_type', $object_type);
2257 }
2258 $result = usePreparedSelectBlade ($query, array ($object_id));
2259 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2260 $order = 'odd';
2261 global $nextorder;
2262 echo $header;
2263 while ($row = $result->fetch (PDO::FETCH_NUM))
2264 {
2265 echo "<tr class=row_${order}><td>${row[0]}</td>";
2266 for ($i = 1; $i <= $extra; $i++)
2267 echo "<td>" . $row[$i] . "</td>";
2268 echo "</tr>\n";
2269 $order = $nextorder[$order];
2270 }
2271 echo "</table><br>\n";
2272 }
2273
2274 function renderRackspaceHistory ()
2275 {
2276 global $nextorder, $pageno, $tabno;
2277 $order = 'odd';
2278 $history = getRackspaceHistory();
2279 // Show the last operation by default.
2280 if (isset ($_REQUEST['op_id']))
2281 $op_id = $_REQUEST['op_id'];
2282 elseif (isset ($history[0]['mo_id']))
2283 $op_id = $history[0]['mo_id'];
2284 else $op_id = NULL;
2285
2286 $omid = NULL;
2287 $nmid = NULL;
2288 $object_id = 1;
2289 if ($op_id)
2290 list ($omid, $nmid) = getOperationMolecules ($op_id);
2291
2292 // Main layout starts.
2293 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2294
2295 // Left top portlet with old allocation.
2296 echo "<tr><td class=pcleft>";
2297 startPortlet ('Old allocation');
2298 if ($omid)
2299 {
2300 $oldMolecule = getMolecule ($omid);
2301 renderMolecule ($oldMolecule, $object_id);
2302 }
2303 else
2304 echo "nothing";
2305 finishPortlet();
2306
2307 echo '</td><td class=pcright>';
2308
2309 // Right top portlet with new allocation
2310 startPortlet ('New allocation');
2311 if ($nmid)
2312 {
2313 $newMolecule = getMolecule ($nmid);
2314 renderMolecule ($newMolecule, $object_id);
2315 }
2316 else
2317 echo "nothing";
2318 finishPortlet();
2319
2320 echo '</td></tr><tr><td colspan=2>';
2321
2322 // Bottom portlet with list
2323
2324 startPortlet ('Rackspace allocation history');
2325 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
2326 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
2327 foreach ($history as $row)
2328 {
2329 if ($row['mo_id'] == $op_id)
2330 $class = 'hl';
2331 else
2332 $class = "row_${order}";
2333 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
2334 echo "<td>${row['user_name']}</td><td>";
2335 renderCell (spotEntity ('object', $row['ro_id']));
2336 echo "</td><td>${row['comment']}</td>\n";
2337 echo "</tr>\n";
2338 $order = $nextorder[$order];
2339 }
2340 echo "</table>\n";
2341 finishPortlet();
2342
2343 echo '</td></tr></table>';
2344 }
2345
2346 function renderIPv4SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
2347 {
2348 $self = __FUNCTION__;
2349 static $vdomlist = NULL;
2350 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2351 $vdomlist = getVLANDomainOptions();
2352
2353 // scroll page to the highlighted item
2354 if ($target && isset ($_REQUEST['hl_net']))
2355 addAutoScrollScript ("net-$target");
2356
2357 foreach ($tree as $item)
2358 {
2359 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2360 loadIPv4AddrList ($item); // necessary to compute router list and address counter
2361 else
2362 {
2363 $item['addrlist'] = array();
2364 $item['addrc'] = 0;
2365 }
2366 $used = $item['addrc'];
2367 $maxdirect = $item['addrt'];
2368 $maxtotal = binInvMaskFromDec ($item['mask']) + 1;
2369 if (isset ($item['id']))
2370 {
2371 $decor = array ('indent' => $level);
2372 if ($item['symbol'] == 'node-collapsed')
2373 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
2374 elseif ($item['symbol'] == 'node-expanded')
2375 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}" : '');
2376 echo "<tr valign=top>";
2377 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
2378 $decor['tdclass'] .= ' port_highlight';
2379 printIPNetInfoTDs ($item, $decor);
2380 echo "<td class=tdcenter>";
2381 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2382 {
2383 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2384 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small>';
2385 }
2386 else
2387 echo "<small>${maxdirect}</small>";
2388 echo "</td>";
2389 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2390 {
2391 echo '<td class=tdleft>';
2392 if (count ($item['8021q']))
2393 {
2394 echo '<ul>';
2395 foreach ($item['8021q'] as $binding)
2396 {
2397 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
2398 // FIXME: would formatVLANName() do this?
2399 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
2400 }
2401 echo '</ul>';
2402 }
2403 echo '</td>';
2404 }
2405 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2406 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
2407 echo "</tr>";
2408 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2409 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
2410 }
2411 else
2412 {
2413 echo "<tr valign=top>";
2414 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
2415 echo "<td class=tdcenter>";
2416 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2417 {
2418 renderProgressBar ($used/$maxtotal, 'sparenetwork');
2419 echo "<br><small>${used}/${maxtotal}</small>";
2420 }
2421 else
2422 echo "<small>${maxtotal}</small>";
2423 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2424 echo '</td><td>&nbsp;</td>';
2425 echo "</td><td>&nbsp;</td></tr>";
2426 }
2427 }
2428 }
2429
2430 function renderIPv6SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
2431 {
2432 $self = __FUNCTION__;
2433 static $vdomlist = NULL;
2434 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2435 $vdomlist = getVLANDomainOptions();
2436
2437 // scroll page to the highlighted item
2438 if ($target && isset ($_REQUEST['hl_net']))
2439 addAutoScrollScript ("net-$target");
2440
2441 foreach ($tree as $item)
2442 {
2443 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2444 loadIPv6AddrList ($item); // necessary to compute router list and address counter
2445 else
2446 {
2447 $item['addrlist'] = array();
2448 $item['addrc'] = 0;
2449 }
2450 if (isset ($item['id']))
2451 {
2452 $decor = array ('indent' => $level);
2453 if ($item['symbol'] == 'node-collapsed')
2454 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
2455 elseif ($item['symbol'] == 'node-expanded')
2456 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#net6id${item['parent_id']}" : '');
2457 echo "<tr valign=top>";
2458 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
2459 $decor['tdclass'] .= ' port_highlight';
2460 printIPNetInfoTDs ($item, $decor);
2461 echo "<td class=tdcenter>";
2462 // show net usage
2463 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2464 echo "</td>";
2465 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2466 {
2467 echo '<td class=tdleft>';
2468 if (count ($item['8021q']))
2469 {
2470 echo '<ul>';
2471 foreach ($item['8021q'] as $binding)
2472 {
2473 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
2474 // FIXME: would formatVLANName() do this?
2475 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
2476 }
2477 echo '</ul>';
2478 }
2479 echo '</td>';
2480 }
2481 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2482 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
2483 echo "</tr>";
2484 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2485 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
2486 }
2487 /* do not display spare networks
2488 else
2489 { // display spare networks
2490 echo "<tr valign=top>";
2491 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
2492 echo "<td class=tdcenter>";
2493 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2494 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2495 echo '</td><td>&nbsp;</td>';
2496 echo "</td><td>&nbsp;</td></tr>";
2497 }*/
2498 }
2499 }
2500
2501 // if $used is NULL, returns only human-formatted mask.
2502 // Otherwise returns "$used in/of " . human-formatted-mask
2503 function formatIPv6NetUsage ($used, $mask)
2504 {
2505 $prefixes = array
2506 (
2507 0 => '',
2508 3 => 'k',
2509 6 => 'M',
2510 9 => 'G',
2511 12 => 'T',
2512 15 => 'P',
2513 18 => 'E',
2514 21 => 'Z',
2515 24 => 'Y',
2516 );
2517
2518 if ($mask <= 64)
2519 {
2520 $what = '/64 net';
2521 $preposition = 'in';
2522 $mask += 64;
2523 }
2524 else
2525 {
2526 $what = 'IP';
2527 $preposition = 'of';
2528 }
2529 $what .= (0 == $mask % 64 ? '' : 's');
2530 $addrc = isset ($used) ? "$used $preposition " : '';
2531
2532 $dec_order = intval ((128 - $mask) / 10) * 3;
2533 $mult = isset ($prefixes[$dec_order]) ? $prefixes[$dec_order] : '??';
2534
2535 $cnt = 1 << ((128 - $mask) % 10);
2536 if ($cnt == 1 && $mult == '')
2537 $cnt = 'single';
2538
2539 return "<small>${addrc}${cnt}${mult} ${what}</small>";
2540 }
2541
2542 function renderIPv4Space ()
2543 {
2544 global $pageno, $tabno;
2545 $cellfilter = getCellFilter();
2546 $netlist = listCells ('ipv4net');
2547 $allcount = count ($netlist);
2548 $netlist = filterCellList ($netlist, $cellfilter['expression']);
2549 array_walk ($netlist, 'amplifyCell');
2550
2551 $netcount = count ($netlist);
2552 // expand request can take either natural values or "ALL". Zero means no expanding.
2553 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2554 $tree = prepareIPv4Tree ($netlist, $eid);
2555
2556 echo "<table border=0 class=objectview>\n";
2557 echo "<tr><td class=pcleft>";
2558 if (! renderEmptyResults($cellfilter, 'IPv4 nets', count($tree)))
2559 {
2560 startPortlet ("networks (${netcount})");
2561 echo '<h4>';
2562 if ($eid === 0)
2563 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2564 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2565 $cellfilter['urlextra'] . "'>expand all</a>)";
2566 elseif ($eid === 'ALL')
2567 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2568 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2569 else
2570 {
2571 $netinfo = spotEntity ('ipv4net', $eid);
2572 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2573 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2574 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2575 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2576 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2577 }
2578 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2579 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2580 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2581 echo '<th>VLAN</th>';
2582 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2583 echo "<th>routed by</th>";
2584 echo "</tr>\n";
2585 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2586 renderIPv4SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2587 echo "</table>\n";
2588 finishPortlet();
2589 }
2590
2591 echo '</td><td class=pcright>';
2592 renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
2593 echo "</td></tr></table>\n";
2594 }
2595
2596 function renderIPv6Space ()
2597 {
2598 global $pageno, $tabno;
2599 $cellfilter = getCellFilter();
2600 $netlist = listCells ('ipv6net');
2601 $allcount = count ($netlist);
2602 $netlist = filterCellList ($netlist, $cellfilter['expression']);
2603 array_walk ($netlist, 'amplifyCell');
2604
2605 $netcount = count ($netlist);
2606 // expand request can take either natural values or "ALL". Zero means no expanding.
2607 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2608 $tree = prepareIPv6Tree ($netlist, $eid);
2609
2610 echo "<table border=0 class=objectview>\n";
2611 echo "<tr><td class=pcleft>";
2612 if (! renderEmptyResults($cellfilter, 'IPv6 nets', count($tree)))
2613 {
2614 startPortlet ("networks (${netcount})");
2615 echo '<h4>';
2616 if ($eid === 0)
2617 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2618 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2619 $cellfilter['urlextra'] . "'>expand all</a>)";
2620 elseif ($eid === 'ALL')
2621 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2622 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2623 else
2624 {
2625 $netinfo = spotEntity ('ipv6net', $eid);
2626 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2627 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2628 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2629 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2630 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2631 }
2632 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2633 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2634 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2635 echo '<th>VLAN</th>';
2636 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2637 echo "<th>routed by</th>";
2638 echo "</tr>\n";
2639 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2640 renderIPv6SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2641 echo "</table>\n";
2642 finishPortlet();
2643 }
2644
2645 echo '</td><td class=pcright>';
2646 renderCellFilterPortlet ($cellfilter, 'ipv6net', $netlist);
2647 echo "</td></tr></table>\n";
2648 }
2649
2650 function renderSLBDefConfig()
2651 {
2652 $defaults = getSLBDefaults ();
2653 startPortlet ('SLB default configs');
2654 echo '<table cellspacing=0 cellpadding=5 align=center>';
2655 printOpFormIntro ('save');
2656 echo '<tr><th class=tdright>VS config</th><td colspan=2><textarea tabindex=103 name=vsconfig rows=10 cols=80>' . htmlspecialchars($defaults['vs']) . '</textarea></td>';
2657 echo '<td rowspan=2>';
2658 printImageHREF ('SAVE', 'Save changes', TRUE);
2659 echo '</td></tr>';
2660 echo '<tr><th class=tdright>RS config</th><td colspan=2><textarea tabindex=104 name=rsconfig rows=10 cols=80>' . htmlspecialchars($defaults['rs']) . '</textarea></td></tr>';
2661 echo '</form></table>';
2662 finishPortlet();
2663 }
2664
2665 function renderIPv4SLB ()
2666 {
2667 global $page, $nextorder;
2668
2669 startPortlet ('SLB configuration');
2670 echo "<table border=0 width='100%'><tr>";
2671 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2672 echo "<td><h3><a href='".makeHref(array('page'=>$pno))."'>" . $page[$pno]['title'] . "</a></h3></td>";
2673 echo '</tr></table>';
2674 finishPortlet();
2675
2676 $summary = getSLBSummary();
2677 startPortlet ('SLB tactical overview');
2678 // A single id-keyed array isn't used here to preserve existing
2679 // order of LBs returned by getSLBSummary()
2680 $lblist = array();
2681 $lbdname = array();
2682 foreach ($summary as $vipdata)
2683 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2684 if (!in_array ($lb_object_id, $lblist))
2685 {
2686 $oi = spotEntity ('object', $lb_object_id);
2687 $lbdname[$lb_object_id] = $oi['dname'];
2688 $lblist[] = $lb_object_id;
2689 }
2690 if (!count ($summary))
2691 echo 'none configured';
2692 else
2693 {
2694 $order = 'odd';
2695 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2696 echo "<tr valign=top><td>&nbsp;</td>";
2697 foreach ($lblist as $lb_object_id)
2698 {
2699 #echo "<th><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$lb_object_id))."'>" . $lbdname[$lb_object_id] . "</a></th>";
2700 echo '<td>';
2701 renderLBCell ($lb_object_id);
2702 echo '</td>';
2703 }
2704 echo "</tr>\n";
2705 foreach ($summary as $vsid => $vsdata)
2706 {
2707 echo "<tr class=row_${order}><td class=tdleft>";
2708 renderCell (spotEntity ('ipv4vs', $vsid));
2709 echo "</td>";
2710 foreach ($lblist as $lb_object_id)
2711 {
2712 echo '<td class=tdleft>';
2713 if (!isset ($vsdata['lblist'][$lb_object_id]))
2714 echo '&nbsp;';
2715 else
2716 {
2717 echo $vsdata['lblist'][$lb_object_id]['size'];
2718 // echo " (<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$vsdata['lblist'][$lb_object_id]['id'])). "'>";
2719 // echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2720 }
2721 echo '</td>';
2722 }
2723 echo "</tr>\n";
2724 $order = $nextorder[$order];
2725 }
2726 echo "</table>\n";
2727 }
2728 finishPortlet ();
2729 }
2730
2731 function renderIPv4SpaceEditor ()
2732 {
2733 // IPv4 validator
2734 addJs ('js/live_validation.js');
2735 $regexp = addslashes ('^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$');
2736 addJs (<<<END
2737 $(document).ready(function () {
2738 document.add_new_range.range.setAttribute('match', '$regexp');
2739 Validate.init();
2740 });
2741 END
2742 , TRUE);
2743
2744 function printNewItemTR ()
2745 {
2746 startPortlet ('Add new');
2747 echo '<table border=0 cellpadding=10 align=center>';
2748 // This form requires a name, so JavaScript validator can find it.
2749 // No printOpFormIntro() hence
2750 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2751 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2752 // tags column
2753 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2754 renderNewEntityTags ('ipv4net');
2755 echo '</td>';
2756 // inputs column
2757 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2758 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=18 class='live-validate' tabindex=1 value='${prefix_value}'></td>";
2759 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2760 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2761 echo "<tr><td colspan=2>";
2762 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2763 echo '</td></tr>';
2764 echo "</form></table><br><br>\n";
2765 finishPortlet();
2766 }
2767
2768 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2769 printNewItemTR();
2770 if (count ($addrspaceList = listCells ('ipv4net')))
2771 {
2772 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2773 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2774 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
2775 array_walk ($addrspaceList, 'amplifyCell');
2776 $tree = prepareIPv4Tree ($addrspaceList, 'ALL');
2777 // this is only called for having "trace" set
2778 treeFromList ($addrspaceList);
2779 foreach ($addrspaceList as $netinfo)
2780 {
2781 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2782 // now we have all subnets listed in netinfo
2783 loadIPv4AddrList ($netinfo);
2784 $used = $netinfo['addrc'];
2785 $maxdirect = $netinfo['addrt'];
2786 $maxtotal = binInvMaskFromDec ($netinfo['mask']) + 1;
2787 echo "<tr valign=top><td>";
2788 if (count ($netinfo['addrlist']) && getConfigVar ('IPV4_JAYWALK') == 'no')
2789 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2790 else
2791 {
2792 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>"