r4188 update: UI: ability to clear object ports list at one blow
[racktables] / inc / interface.php
CommitLineData
b325120a 1<?php
e673ee24
DO
2/*
3*
4* This file contains frontend functions for RackTables.
5*
6*/
7
e82deb48 8require_once 'ajax-interface.php';
65e557dd 9
9c0b0016
DO
10// Interface function's special.
11$nextorder['odd'] = 'even';
12$nextorder['even'] = 'odd';
13
52c836b1
DO
14// address allocation type
15$aat = array
16(
17 'regular' => 'Connected',
18 'virtual' => 'Loopback',
19 'shared' => 'Shared',
20 'router' => 'Router',
21);
beb9e88a 22// address allocation code, IPv4 addresses and objects view
52c836b1
DO
23$aac = array
24(
25 'regular' => '',
26 'virtual' => '<strong>L</strong>',
27 'shared' => '<strong>S</strong>',
28 'router' => '<strong>R</strong>',
29);
beb9e88a
DO
30// address allocation code, IPv4 networks view
31$aac2 = array
32(
33 'regular' => '',
34 'virtual' => '<strong>L:</strong>',
29025f8e 35 'shared' => '<strong>S:</strong>',
beb9e88a
DO
36 'router' => '<strong>R:</strong>',
37);
52c836b1 38
0dabdc53
DO
39$vtdecoder = array
40(
41 'ondemand' => '',
54b7ced3
DO
42 'compulsory' => 'P',
43# 'alien' => 'NT',
0dabdc53
DO
44);
45
46$vtoptions = array
47(
54b7ced3
DO
48 'ondemand' => 'auto',
49 'compulsory' => 'permanent',
50# 'alien' => 'never touch',
0dabdc53
DO
51);
52
7056988c
DO
53// Let's have it here, so extensions can add their own images.
54$image = array();
7056988c
DO
55$image['logo']['path'] = 'pix/defaultlogo.png';
56$image['logo']['width'] = 210;
57$image['logo']['height'] = 40;
58$image['rackspace']['path'] = 'pix/racks.png';
59$image['rackspace']['width'] = 218;
60$image['rackspace']['height'] = 200;
61$image['objects']['path'] = 'pix/server.png';
62$image['objects']['width'] = 218;
63$image['objects']['height'] = 200;
4b680876
DO
64$image['depot']['path'] = 'pix/server.png';
65$image['depot']['width'] = 218;
66$image['depot']['height'] = 200;
e1ae3fb4
AD
67$image['files']['path'] = 'pix/files.png';
68$image['files']['width'] = 218;
69$image['files']['height'] = 200;
7056988c
DO
70$image['ipv4space']['path'] = 'pix/addressspace.png';
71$image['ipv4space']['width'] = 218;
72$image['ipv4space']['height'] = 200;
21ee3351
AA
73$image['ipv6space']['path'] = 'pix/addressspacev6.png';
74$image['ipv6space']['width'] = 218;
75$image['ipv6space']['height'] = 200;
7056988c
DO
76$image['ipv4slb']['path'] = 'pix/slb.png';
77$image['ipv4slb']['width'] = 218;
78$image['ipv4slb']['height'] = 200;
79$image['config']['path'] = 'pix/configuration.png';
80$image['config']['width'] = 218;
81$image['config']['height'] = 200;
82$image['reports']['path'] = 'pix/report.png';
83$image['reports']['width'] = 218;
84$image['reports']['height'] = 200;
e0d188ef
DO
85$image['8021q']['path'] = 'pix/8021q.png';
86$image['8021q']['width'] = 218;
87$image['8021q']['height'] = 200;
9a90adc4
DO
88$image['objectlog']['path'] = 'pix/crystal-mimetypes-shellscript-218x200.png';
89$image['objectlog']['width'] = 218;
90$image['objectlog']['height'] = 200;
0682218d
AD
91$image['virtual']['path'] = 'pix/virtualresources.png';
92$image['virtual']['width'] = 218;
93$image['virtual']['height'] = 200;
e1ae3fb4
AD
94$image['download']['path'] = 'pix/download.png';
95$image['download']['width'] = 16;
96$image['download']['height'] = 16;
08cd1902
AD
97$image['DOWNLOAD']['path'] = 'pix/download-big.png';
98$image['DOWNLOAD']['width'] = 32;
99$image['DOWNLOAD']['height'] = 32;
5ccd99a0
DO
100$image['plug']['path'] = 'pix/tango-network-wired.png';
101$image['plug']['width'] = 16;
102$image['plug']['height'] = 16;
103$image['cut']['path'] = 'pix/tango-edit-cut-16x16.png';
104$image['cut']['width'] = 16;
105$image['cut']['height'] = 16;
8ab86984
DO
106$image['Cut']['path'] = 'pix/tango-edit-cut-22x22.png';
107$image['Cut']['width'] = 22;
108$image['Cut']['height'] = 22;
5ccd99a0
DO
109$image['CUT']['path'] = 'pix/tango-edit-cut-32x32.png';
110$image['CUT']['width'] = 32;
111$image['CUT']['height'] = 32;
7056988c
DO
112$image['add']['path'] = 'pix/tango-list-add.png';
113$image['add']['width'] = 16;
114$image['add']['height'] = 16;
a685a26a
DO
115$image['ADD']['path'] = 'pix/tango-list-add-big.png';
116$image['ADD']['width'] = 32;
117$image['ADD']['height'] = 32;
7056988c
DO
118$image['delete']['path'] = 'pix/tango-list-remove.png';
119$image['delete']['width'] = 16;
120$image['delete']['height'] = 16;
f857f71f
DO
121$image['DELETE']['path'] = 'pix/tango-list-remove-32x32.png';
122$image['DELETE']['width'] = 32;
123$image['DELETE']['height'] = 32;
d3c27c5c 124$image['destroy']['path'] = 'pix/tango-user-trash-16x16.png';
1bdc2bfc
DO
125$image['destroy']['width'] = 16;
126$image['destroy']['height'] = 16;
d3c27c5c 127$image['nodestroy']['path'] = 'pix/tango-user-trash-16x16-gray.png';
1bdc2bfc
DO
128$image['nodestroy']['width'] = 16;
129$image['nodestroy']['height'] = 16;
8bc5d1e4
DO
130$image['NODESTROY']['path'] = 'pix/tango-user-trash-32x32-gray.png';
131$image['NODESTROY']['width'] = 32;
132$image['NODESTROY']['height'] = 32;
d3c27c5c 133$image['DESTROY']['path'] = 'pix/tango-user-trash-32x32.png';
97b1f33b
DO
134$image['DESTROY']['width'] = 32;
135$image['DESTROY']['height'] = 32;
7056988c
DO
136$image['nodelete']['path'] = 'pix/tango-list-remove-shadow.png';
137$image['nodelete']['width'] = 16;
138$image['nodelete']['height'] = 16;
7056988c
DO
139$image['inservice']['path'] = 'pix/tango-emblem-system.png';
140$image['inservice']['width'] = 16;
141$image['inservice']['height'] = 16;
142$image['notinservice']['path'] = 'pix/tango-dialog-error.png';
143$image['notinservice']['width'] = 16;
144$image['notinservice']['height'] = 16;
7056988c
DO
145$image['find']['path'] = 'pix/tango-system-search.png';
146$image['find']['width'] = 16;
147$image['find']['height'] = 16;
7056988c
DO
148$image['next']['path'] = 'pix/tango-go-next.png';
149$image['next']['width'] = 32;
150$image['next']['height'] = 32;
151$image['prev']['path'] = 'pix/tango-go-previous.png';
152$image['prev']['width'] = 32;
153$image['prev']['height'] = 32;
11a3d669
DO
154$image['COMMIT']['path'] = 'pix/tango-go-prev-next-32x32.png';
155$image['COMMIT']['width'] = 32;
156$image['COMMIT']['height'] = 32;
24832534 157$image['COMMIT gray']['path'] = 'pix/tango-go-prev-next-gray-32x32.png';
11a3d669
DO
158$image['COMMIT gray']['width'] = 32;
159$image['COMMIT gray']['height'] = 32;
f9428bc6
AA
160$image['RECALC']['path'] = 'pix/tango-view-refresh-32x32.png';
161$image['RECALC']['width'] = 32;
162$image['RECALC']['height'] = 32;
7056988c
DO
163$image['clear']['path'] = 'pix/tango-edit-clear.png';
164$image['clear']['width'] = 16;
165$image['clear']['height'] = 16;
61a61189
DO
166$image['CLEAR']['path'] = 'pix/tango-edit-clear-big.png';
167$image['CLEAR']['width'] = 32;
168$image['CLEAR']['height'] = 32;
f3d274bf
DO
169$image['CLEAR gray']['path'] = 'pix/tango-edit-clear-gray-32x32.png';
170$image['CLEAR gray']['width'] = 32;
171$image['CLEAR gray']['height'] = 32;
384b98c9 172$image['save']['path'] = 'pix/tango-document-save-16x16.png';
7056988c
DO
173$image['save']['width'] = 16;
174$image['save']['height'] = 16;
384b98c9 175$image['SAVE']['path'] = 'pix/tango-document-save-32x32.png';
7056988c
DO
176$image['SAVE']['width'] = 32;
177$image['SAVE']['height'] = 32;
fdf2edef
DO
178$image['NOSAVE']['path'] = 'pix/tango-document-save-32x32-gray.png';
179$image['NOSAVE']['width'] = 32;
180$image['NOSAVE']['height'] = 32;
7056988c
DO
181$image['create']['path'] = 'pix/tango-document-new.png';
182$image['create']['width'] = 16;
183$image['create']['height'] = 16;
184$image['CREATE']['path'] = 'pix/tango-document-new-big.png';
185$image['CREATE']['width'] = 32;
186$image['CREATE']['height'] = 32;
187$image['DENIED']['path'] = 'pix/tango-dialog-error-big.png';
188$image['DENIED']['width'] = 32;
189$image['DENIED']['height'] = 32;
737a3f72
DO
190$image['node-collapsed']['path'] = 'pix/node-collapsed.png';
191$image['node-collapsed']['width'] = 16;
192$image['node-collapsed']['height'] = 16;
193$image['node-expanded']['path'] = 'pix/node-expanded.png';
194$image['node-expanded']['width'] = 16;
195$image['node-expanded']['height'] = 16;
fec0c8da
DO
196$image['node-expanded-static']['path'] = 'pix/node-expanded-static.png';
197$image['node-expanded-static']['width'] = 16;
198$image['node-expanded-static']['height'] = 16;
09620506 199$image['dragons']['path'] = 'pix/mitsudragon.png';
9eaf7cc2
DO
200$image['dragons']['width'] = 195;
201$image['dragons']['height'] = 33;
b1a970c7
DO
202$image['LB']['path'] = 'pix/loadbalancer.png';
203$image['LB']['width'] = 32;
204$image['LB']['height'] = 32;
205$image['RS pool']['path'] = 'pix/serverpool.png';
206$image['RS pool']['width'] = 48;
207$image['RS pool']['height'] = 16;
208$image['VS']['path'] = 'pix/servicesign.png';
209$image['VS']['width'] = 39;
210$image['VS']['height'] = 62;
8b3874a5
DO
211$image['router']['path'] = 'pix/router.png';
212$image['router']['width'] = 32;
213$image['router']['height'] = 32;
cd72ee55
DO
214$image['object']['path'] = 'pix/bracket-16x16.png';
215$image['object']['width'] = 16;
216$image['object']['height'] = 16;
217$image['OBJECT']['path'] = 'pix/bracket-32x32.png';
218$image['OBJECT']['width'] = 32;
219$image['OBJECT']['height'] = 32;
0682218d
AD
220$image['attach']['path'] = 'pix/tango-mail-attachment-16x16.png';
221$image['attach']['width'] = 16;
222$image['attach']['height'] = 16;
83f24ae5 223$image['Attach']['path'] = 'pix/tango-mail-attachment-22x22.png';
8ab86984
DO
224$image['Attach']['width'] = 22;
225$image['Attach']['height'] = 22;
0682218d
AD
226$image['ATTACH']['path'] = 'pix/tango-mail-attachment-32x32.png';
227$image['ATTACH']['width'] = 32;
228$image['ATTACH']['height'] = 32;
7a0f5847
DO
229$image['favorite']['path'] = 'pix/tango-emblem-favorite.png';
230$image['favorite']['width'] = 16;
231$image['favorite']['height'] = 16;
4f12d88f
DO
232$image['computer']['path'] = 'pix/tango-computer.png';
233$image['computer']['width'] = 16;
234$image['computer']['height'] = 16;
0b9c98d7
DO
235$image['empty file']['path'] = 'pix/crystal-file-empty-32x32.png';
236$image['empty file']['width'] = 32;
237$image['empty file']['height'] = 32;
238$image['text file']['path'] = 'pix/crystal-file-text-32x32.png';
239$image['text file']['width'] = 32;
240$image['text file']['height'] = 32;
241$image['image file']['path'] = 'pix/crystal-file-image-32x32.png';
242$image['image file']['width'] = 32;
243$image['image file']['height'] = 32;
5c0964ef
DO
244$image['text']['path'] = 'pix/tango-text-x-generic-16x16.png';
245$image['text']['width'] = 16;
246$image['text']['height'] = 16;
9e5f20ce 247$image['NET']['path'] = 'pix/crystal-network_local-32x32.png';
0b9c98d7
DO
248$image['NET']['width'] = 32;
249$image['NET']['height'] = 32;
9e5f20ce
DO
250$image['net']['path'] = 'pix/crystal-network_local-16x16.png';
251$image['net']['width'] = 16;
252$image['net']['height'] = 16;
19dac9c3
DO
253$image['USER']['path'] = 'pix/crystal-edit-user-32x32.png';
254$image['USER']['width'] = 32;
255$image['USER']['height'] = 32;
4eccef54
DO
256$image['setfilter']['path'] = 'pix/pgadmin3-viewfiltereddata.png';
257$image['setfilter']['width'] = 32;
258$image['setfilter']['height'] = 32;
e23f76ea
DO
259$image['setfilter gray']['path'] = 'pix/pgadmin3-viewfiltereddata-grayscale.png';
260$image['setfilter gray']['width'] = 32;
261$image['setfilter gray']['height'] = 32;
4eccef54
DO
262$image['resetfilter']['path'] = 'pix/pgadmin3-viewdata.png';
263$image['resetfilter']['width'] = 32;
264$image['resetfilter']['height'] = 32;
e23f76ea
DO
265$image['resetfilter gray']['path'] = 'pix/pgadmin3-viewdata-grayscale.png';
266$image['resetfilter gray']['width'] = 32;
267$image['resetfilter gray']['height'] = 32;
f06fe423 268$image['knight']['path'] = 'pix/smiley_knight.png';
9eaf7cc2 269$image['knight']['width'] = 72;
f06fe423 270$image['knight']['height'] = 33;
4be13f24
DO
271$image['Zoom']['path'] = 'pix/tango-system-search-22x22.png';
272$image['Zoom']['width'] = 22;
273$image['Zoom']['height'] = 22;
274$image['Zooming']['path'] = 'pix/tango-view-fullscreen-22x22.png';
275$image['Zooming']['width'] = 22;
276$image['Zooming']['height'] = 22;
d7fee738
DO
277$image['UNLOCK']['path'] = 'pix/crystal-actions-unlock-32x32.png';
278$image['UNLOCK']['width'] = 32;
279$image['UNLOCK']['height'] = 32;
76452d15
DO
280$image['CLOCK']['path'] = 'pix/tango-appointment-32x32.png';
281$image['CLOCK']['width'] = 32;
282$image['CLOCK']['height'] = 32;
283$image['DQUEUE done']['path'] = 'pix/crystal-ok-32x32.png';
284$image['DQUEUE done']['width'] = 32;
285$image['DQUEUE done']['height'] = 32;
611b5e46
DO
286$image['DQUEUE sync_aging']['path'] = 'pix/tango-appointment-32x32.png';
287$image['DQUEUE sync_aging']['width'] = 32;
288$image['DQUEUE sync_aging']['height'] = 32;
289$image['DQUEUE resync_aging']['path'] = 'pix/tango-appointment-32x32.png';
290$image['DQUEUE resync_aging']['width'] = 32;
291$image['DQUEUE resync_aging']['height'] = 32;
292$image['DQUEUE sync_ready']['path'] = 'pix/tango-emblem-system-32x32.png';
293$image['DQUEUE sync_ready']['width'] = 32;
294$image['DQUEUE sync_ready']['height'] = 32;
295$image['DQUEUE resync_ready']['path'] = 'pix/tango-emblem-important-32x32.png';
296$image['DQUEUE resync_ready']['width'] = 32;
297$image['DQUEUE resync_ready']['height'] = 32;
76452d15
DO
298$image['DQUEUE failed']['path'] = 'pix/tango-emblem-unreadable-32x32.png';
299$image['DQUEUE failed']['width'] = 32;
300$image['DQUEUE failed']['height'] = 32;
301$image['DQUEUE disabled']['path'] = 'pix/tango-emblem-readonly-32x32.png';
302$image['DQUEUE disabled']['width'] = 32;
303$image['DQUEUE disabled']['height'] = 32;
de8aa722
DO
304$image['COPY']['path'] = 'pix/tango-edit-copy-32x32.png';
305$image['COPY']['width'] = 32;
306$image['COPY']['height'] = 32;
740b4f5e
AA
307$image['html']['path'] = 'pix/tango-text-html.png';
308$image['html']['width'] = 16;
309$image['html']['height'] = 16;
7056988c 310
e5c4506d
DO
311// This may be populated later onsite, report rendering function will use it.
312// See the $systemreport for structure.
313$localreports = array();
d6adad3e 314
9db67d95
DO
315$CodePressMap = array
316(
317 'sql' => 'sql',
318 'php' => 'php',
319 'html' => 'html',
320 'css' => 'css',
321 'js' => 'javascript',
322);
e5c4506d 323
8d4f7d18
DO
324$attrtypes = array
325(
326 'uint' => '[U] unsigned integer',
327 'float' => '[F] floating point',
328 'string' => '[S] string',
329 'dict' => '[D] dictionary record'
330);
331
e673ee24 332// Main menu.
4b680876
DO
333function renderIndexItem ($ypageno) {
334 global $page;
335 if (permitted($ypageno)) {
21ee3351
AA
336 $title = isset ($page[$ypageno]['title']) ? $page[$ypageno]['title'] : dynamic_title_decoder ($ypageno);
337 if (is_array ($title))
338 $title = $title['name'];
4b680876 339 print " <td>\n";
21ee3351 340 print " <h1><a href='".makeHref(array('page'=>$ypageno))."'>".$title."<br>\n";
4b680876
DO
341 printImageHREF ($ypageno);
342 print "</a></h1>\n";
343 print " </td>\n";
344 } else {
345 print " <td>&nbsp;</td>\n";
346 }
347}
348
e673ee24
DO
349function renderIndex ()
350{
67c5c049 351 global $indexlayout;
e673ee24
DO
352?>
353<table border=0 cellpadding=0 cellspacing=0 width='100%'>
354 <tr>
355 <td>
356 <div style='text-align: center; margin: 10px; '>
a544d2c4 357 <table width='100%' cellspacing=0 cellpadding=20 class=mainmenu border=0>
4b680876 358<?php
67c5c049
DO
359foreach ($indexlayout as $row)
360{
361 echo '<tr>';
362 foreach ($row as $column)
363 if ($column === NULL)
364 echo '<td>&nbsp;</td>';
365 else
366 renderIndexItem ($column);
367 echo '</tr>';
368}
369?>
e673ee24
DO
370 </table>
371 </div>
372 </td>
373 </tr>
374</table>
b325120a 375<?php
e673ee24
DO
376}
377
378function renderRackspace ()
379{
95857b5c
DO
380 $found_racks = array();
381 $rows = array();
a8efc03e 382 $cellfilter = getCellFilter();
1ebbf889 383 $rackCount = 0;
95857b5c
DO
384 foreach (getRackRows() as $row_id => $row_name) {
385 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
386 $found_racks = array_merge($found_racks, $rackList);
387 $rows[] = array(
388 'row_id' => $row_id,
389 'row_name' => $row_name,
390 'racks' => $rackList
391 );
1ebbf889 392 $rackCount += count($rackList);
95857b5c 393 }
1ebbf889 394
95857b5c
DO
395 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
396 renderCellFilterPortlet ($cellfilter, 'rack', $found_racks);
489a7502 397 echo '</td><td class=pcright>';
1ebbf889
AA
398
399 if (! renderEmptyResults($cellfilter, 'racks', $rackCount))
e673ee24 400 {
1ebbf889
AA
401 echo '<table border=0 cellpadding=10 cellpadding=1>';
402 // generate thumb gallery
403 global $nextorder;
404 $rackwidth = getRackImageWidth();
405 // Zero value effectively disables the limit.
406 $maxPerRow = getConfigVar ('RACKS_PER_ROW');
407 $order = 'odd';
408 foreach ($rows as $row)
409 {
410 $row_id = $row['row_id'];
411 $row_name = $row['row_name'];
412 $rackList = $row['racks'];
413
414 if (!count ($rackList) and count ($cellfilter['expression']))
415 continue;
416 $rackListIdx = 0;
417 echo "<tr class=row_${order}><th class=tdleft>";
418 echo "<a href='".makeHref(array('page'=>'row', 'row_id'=>$row_id))."${cellfilter['urlextra']}'>";
419 echo "${row_name}</a></th><td><table border=0 cellspacing=5><tr>";
420 if (!count ($rackList))
421 echo "<td>(empty row)</td>";
422 else
423 foreach ($rackList as $rack)
48325652 424 {
1ebbf889
AA
425 if ($rackListIdx > 0 and $maxPerRow > 0 and $rackListIdx % $maxPerRow == 0)
426 {
427 echo '</tr></table></tr>';
428 echo "<tr class=row_${order}><th class=tdleft>${row_name} (continued)";
429 echo "</th><td><table border=0 cellspacing=5><tr>";
430 }
431 echo "<td align=center><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
432 echo "<img border=0 width=${rackwidth} height=";
433 echo getRackImageHeight ($rack['height']);
434 echo " title='${rack['height']} units'";
435 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
436 echo "<br>${rack['name']}</a></td>";
437 $rackListIdx++;
48325652 438 }
1ebbf889
AA
439 $order = $nextorder[$order];
440 echo "</tr></table></tr>\n";
441 }
442 echo "</table>\n";
e673ee24 443 }
489a7502 444 echo "</td></tr></table>\n";
e673ee24
DO
445}
446
345fd640
AD
447function renderRackspaceRowEditor ()
448{
449 function printNewItemTR ()
450 {
451 printOpFormIntro ('addRow');
7be51fea
DO
452 echo "<tr><td>";
453 printImageHREF ('create', 'Add new row', TRUE);
454 echo "</td><td><input type=text name=name tabindex=100></td><td>";
345fd640 455 printImageHREF ('create', 'Add new row', TRUE, 101);
7be51fea 456 echo "</td></tr></form>";
345fd640 457 }
d732e47e 458 startPortlet ('Rows');
345fd640 459 echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
7be51fea 460 echo "<tr><th>&nbsp;</th><th>Name</th><th>&nbsp;</th></tr>\n";
345fd640
AD
461 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
462 printNewItemTR();
c40666f5 463 foreach (getRackRows() as $row_id => $row_name)
345fd640 464 {
7be51fea 465 echo "<tr><td>";
a8efc03e 466 if ($rc = count (listCells ('rack', $row_id)))
6c18dd08 467 printImageHREF ('nodestroy', "${rc} rack(s) here");
7be51fea 468 else
5af82683 469 {
c40666f5 470 echo "<a href=\"".makeHrefProcess(array('op'=>'delete', 'row_id'=>$row_id))."\">";
7be51fea 471 printImageHREF ('destroy', 'Delete row');
5af82683
DY
472 echo "</a>";
473 }
c40666f5
DO
474 printOpFormIntro ('updateRow', array ('row_id' => $row_id));
475 echo "</td><td><input type=text name=name value='${row_name}'></td><td>";
7be51fea
DO
476 printImageHREF ('save', 'Save changes', TRUE);
477 echo "</form></td></tr>\n";
345fd640
AD
478 }
479 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
480 printNewItemTR();
481 echo "</table><br>\n";
482 finishPortlet();
483}
484
7e1db771 485function renderRow ($row_id)
e673ee24 486{
0cc24e9a 487 $rowInfo = getRackRowInfo ($row_id);
a8efc03e
DO
488 $cellfilter = getCellFilter();
489 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
e673ee24
DO
490 // Main layout starts.
491 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
492
493 // Left portlet with row information.
494 echo "<tr><td class=pcleft>";
a8ce7234 495 startPortlet ($rowInfo['name']);
e673ee24 496 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
5af82683
DY
497 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
498 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
04d619d0 499 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
114e50af
DO
500 renderProgressBar (getRSUforRackRow ($rackList));
501 echo "</td></tr>\n";
e673ee24
DO
502 echo "</table><br>\n";
503 finishPortlet();
95857b5c 504 renderCellFilterPortlet ($cellfilter, 'rack', $rackList, 'row_id', $row_id);
e673ee24 505
48325652 506 echo "</td><td class=pcright>";
e673ee24 507
4fbb5a00 508 global $nextorder;
d5157018 509 $rackwidth = getRackImageWidth() * getConfigVar ('ROW_SCALE');
f5883ec1
DO
510 // Maximum number of racks per row is proportionally less, but at least 1.
511 $maxPerRow = max (floor (getConfigVar ('RACKS_PER_ROW') / getConfigVar ('ROW_SCALE')), 1);
512 $rackListIdx = 0;
e673ee24
DO
513 $order = 'odd';
514 startPortlet ('Racks');
515 echo "<table border=0 cellspacing=5 align='center'><tr>";
64b95774 516 foreach ($rackList as $rack)
e673ee24 517 {
f5883ec1
DO
518 if ($rackListIdx % $maxPerRow == 0)
519 {
520 if ($rackListIdx > 0)
521 echo '</tr>';
522 echo '<tr>';
523 }
4fbb5a00 524 echo "<td align=center class=row_${order}><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
d5157018 525 echo "<img border=0 width=${rackwidth} height=" . (getRackImageHeight ($rack['height']) * getConfigVar ('ROW_SCALE'));
e673ee24 526 echo " title='${rack['height']} units'";
d2ec5490 527 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
e673ee24
DO
528 echo "<br>${rack['name']}</a></td>";
529 $order = $nextorder[$order];
f5883ec1 530 $rackListIdx++;
e673ee24
DO
531 }
532 echo "</tr></table>\n";
533 finishPortlet();
e673ee24
DO
534 echo "</td></tr></table>";
535}
536
e673ee24 537// This function renders rack as HTML table.
7e1db771 538function renderRack ($rack_id, $hl_obj_id = 0)
e673ee24 539{
61a1d996
DO
540 $rackData = spotEntity ('rack', $rack_id);
541 amplifyCell ($rackData);
e673ee24
DO
542 markAllSpans ($rackData);
543 if ($hl_obj_id > 0)
544 highlightObject ($rackData, $hl_obj_id);
545 markupObjectProblems ($rackData);
546 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
547 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
d48d8820 548 echo "<center><table border=0><tr valign=middle>";
4fbb5a00 549 echo "<td><h2><a href='".makeHref(array('page'=>'row', 'row_id'=>$rackData['row_id']))."'>${rackData['row_name']}</a> :</h2></td>";
e673ee24
DO
550 // FIXME: use 'bypass'?
551 if ($prev_id != NULL)
9803c56c 552 {
4fbb5a00 553 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$prev_id))."'>";
9803c56c 554 printImageHREF ('prev', 'previous rack');
d48d8820 555 echo "</a></td>";
9803c56c 556 }
4fbb5a00 557 echo "<td><h2><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rackData['id']))."'>${rackData['name']}</a></h2></td>";
e673ee24 558 if ($next_id != NULL)
9803c56c 559 {
4fbb5a00 560 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$next_id))."'>";
f444c095 561 printImageHREF ('next', 'next rack');
d48d8820 562 echo "</a></td>";
9803c56c 563 }
d48d8820 564 echo "</h2></td></tr></table>\n";
e673ee24 565 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
d08147d6
DO
566 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
567 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
65e557dd 568 addAtomCSS();
e673ee24
DO
569 for ($i = $rackData['height']; $i > 0; $i--)
570 {
d08147d6 571 echo "<tr><th>${i}</th>";
e673ee24
DO
572 for ($locidx = 0; $locidx < 3; $locidx++)
573 {
574 if (isset ($rackData[$i][$locidx]['skipped']))
575 continue;
576 $state = $rackData[$i][$locidx]['state'];
65e557dd 577 echo "<td class='atom state_${state}";
e673ee24
DO
578 if (isset ($rackData[$i][$locidx]['hl']))
579 echo $rackData[$i][$locidx]['hl'];
65e557dd 580 echo "'";
e673ee24
DO
581 if (isset ($rackData[$i][$locidx]['colspan']))
582 echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
583 if (isset ($rackData[$i][$locidx]['rowspan']))
584 echo ' rowspan=' . $rackData[$i][$locidx]['rowspan'];
585 echo ">";
586 switch ($state)
587 {
588 case 'T':
fb6e2f57 589 $objectData = spotEntity ('object', $rackData[$i][$locidx]['object_id']);
59a83bd8 590 if (strlen ($objectData['asset_no']))
e673ee24
DO
591 $prefix = "<div title='${objectData['asset_no']}";
592 else
593 $prefix = "<div title='no asset tag";
594 // Don't tell about label, if it matches common name.
0682218d 595 $body = '';
59a83bd8 596 if ($objectData['name'] != $objectData['label'] and strlen ($objectData['label']))
0682218d
AD
597 $body = ", visible label is \"${objectData['label']}\"";
598 // Display list of child objects, if any
599 $objectChildren = getEntityRelatives ('children', 'object', $objectData['id']);
600 if (count($objectChildren) > 0)
601 {
602 foreach ($objectChildren as $child)
603 $childNames[] = $child['name'];
604 natsort($childNames);
605 $suffix = sprintf(", contains %s'>", implode(', ', $childNames));
606 }
e673ee24
DO
607 else
608 $suffix = "'>";
0682218d 609 echo $prefix . $body . $suffix;
4fbb5a00 610 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$objectData['id']))."'>${objectData['dname']}</a></div>";
e673ee24
DO
611 break;
612 case 'A':
613 echo '<div title="This rackspace does not exist">&nbsp;</div>';
614 break;
615 case 'F':
616 echo '<div title="Free rackspace">&nbsp;</div>';
617 break;
618 case 'U':
619 echo '<div title="Problematic rackspace, you CAN\'T mount here">&nbsp;</div>';
620 break;
621 default:
622 echo '<div title="No data">&nbsp;</div>';
623 break;
624 }
625 echo '</td>';
626 }
627 echo "</tr>\n";
628 }
629 echo "</table></center>\n";
630}
631
e673ee24
DO
632function renderNewRackForm ($row_id)
633{
50b4ba85 634 startPortlet ('Add one');
f19c75d6 635 printOpFormIntro ('addRack', array ('got_data' => 'TRUE'));
e673ee24 636 echo '<table border=0 align=center>';
b901bf1f
DO
637 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
638 if ($defh == 0)
639 $defh = '';
72d52730
DO
640 echo "<tr><th class=tdright>Rack name (*):</th><td class=tdleft><input type=text name=rack_name tabindex=1></td>";
641 echo "<td rowspan=4>Assign tags:<br>";
a26a6ccc 642 renderNewEntityTags ('rack');
72d52730 643 echo "</td></tr>\n";
b8094ae4 644 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";
4134b5c0 645 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
f19c75d6
DO
646 echo "<tr><td class=submit colspan=2>";
647 printImageHREF ('CREATE', 'Add', TRUE);
648 echo "</td></tr></table></form>";
406b54bd 649 finishPortlet();
406b54bd 650
50b4ba85 651 startPortlet ('Add many');
f19c75d6 652 printOpFormIntro ('addRack', array ('got_mdata' => 'TRUE'));
50b4ba85
DO
653 echo '<table border=0 align=center>';
654 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
655 if ($defh == 0)
656 $defh = '';
72d52730
DO
657 echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=rack_height2 value='${defh}'></td>";
658 echo "<td rowspan=3 valign=top>Assign tags:<br>";
a26a6ccc 659 renderNewEntityTags ('rack');
72d52730 660 echo "</td></tr>\n";
50b4ba85 661 echo "<tr><th class=tdright>Rack names (*):</th><td class=tdleft><textarea name=rack_names cols=40 rows=25></textarea></td></tr>\n";
f19c75d6
DO
662 echo "<tr><td class=submit colspan=2>";
663 printImageHREF ('CREATE', 'Add', TRUE);
e673ee24
DO
664 echo '</form></table>';
665 finishPortlet();
666}
667
668function renderEditObjectForm ($object_id)
669{
e10f583a 670 global $pageno;
fb6e2f57 671 $object = spotEntity ('object', $object_id);
cdd3efe9 672 startPortlet ();
43fb6eaf 673 printOpFormIntro ('update');
cdd3efe9
AD
674
675 // static attributes
e10f583a
DO
676 echo '<table border=0 cellspacing=0 cellpadding=3 align=center>';
677 echo "<tr><td>&nbsp;</td><th colspan=2><h2>Attributes</h2></th></tr>";
22bb04da 678 // baseline info
e10f583a 679 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";
0682218d
AD
680 if (considerConfiguredConstraint ($object, 'VIRTUAL_OBJ_LISTSRC'))
681 {
682 echo "<input type=hidden name=object_label value=''>\n";
683 echo "<input type=hidden name=object_asset_no value=''>\n";
684 echo "<input type=hidden name=object_barcode value=''>\n";
685 }
686 else
687 {
688 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";
689 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";
690 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";
691 }
692 // parent selection
693 if (rackObjectTypeMayHaveParent ($object['objtype_id']))
694 {
695 $parents = getEntityRelatives ('parents', 'object', $object_id);
696 foreach ($parents as $link_id => $parent_details)
697 {
698 if (!isset($label))
699 $label = count($parents) > 1 ? 'Containers:' : 'Container:';
700 echo "<tr><td>&nbsp;</td>";
701 echo "<th class=tdright>${label}</th><td class=tdleft>";
702 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$parent_details['entity_id']))."'>${parent_details['name']}</a>";
703 echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
704 echo "<a href='".
705 makeHrefProcess(array(
706 'op'=>'unlinkEntities',
707 'link_id'=>$link_id,
708 'object_id'=>$object_id,
709 'page='=>'object',
710 'tab'=>'edit')).
711 "'>";
712 printImageHREF ('cut', 'Unlink container');
713 echo "</a>";
714 echo "</td></tr>\n";
715 $label = '&nbsp;';
716 }
717 echo "<tr><td>&nbsp;</td>";
718 echo "<th class=tdright>Select container:</th><td class=tdleft>";
719 echo "<span";
720 $helper_args = array ('object_id' => $object_id);
721 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
722 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
723 echo " onclick='window.open(\"" . makeHrefForHelper ('objlist', $helper_args);
724 echo "\",\"findlink\",\"${popup_args}\");'>";
725 printImageHREF ('attach', 'Select a container');
726 echo "</span></td></tr>\n";
727 }
cdd3efe9 728 // optional attributes
e673ee24 729 $values = getAttrValues ($object_id);
0f63538a 730 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
2b98d5a2 731 if (count($values) > 0)
e673ee24 732 {
2b98d5a2
AD
733 $i = 0;
734 foreach ($values as $record)
e673ee24 735 {
2b98d5a2
AD
736 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
737 echo '<tr><td>';
59a83bd8 738 if (strlen ($record['value']))
2b98d5a2 739 {
4fbb5a00 740 echo "<a href='".makeHrefProcess(array('op'=>'clearSticker', 'object_id'=>$object_id, 'attr_id'=>$record['id']))."'>";
2b98d5a2
AD
741 printImageHREF ('clear', 'Clear value');
742 echo '</a>';
743 }
744 else
745 echo '&nbsp;';
746 echo '</td>';
e10f583a 747 echo "<th class=sticker>${record['name']}:</th><td class=tdleft>";
2b98d5a2
AD
748 switch ($record['type'])
749 {
750 case 'uint':
751 case 'float':
752 case 'string':
753 echo "<input type=text name=${i}_value value='${record['value']}'>";
754 break;
755 case 'dict':
7fa7047a 756 $chapter = readChapter ($record['chapter_id'], 'o');
2b98d5a2 757 $chapter[0] = '-- NOT SET --';
f3d274bf 758 $chapter = cookOptgroups ($chapter, $object['objtype_id'], $record['key']);
cd3775e9 759 printNiftySelect ($chapter, array ('name' => "${i}_value"), $record['key']);
2b98d5a2
AD
760 break;
761 }
762 echo "</td></tr>\n";
763 $i++;
e673ee24 764 }
e673ee24 765 }
e10f583a
DO
766 echo "<tr><td>&nbsp;</td><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
767 if ($object['has_problems'] == 'yes')
768 echo ' checked';
769 echo "></td></tr>\n";
abd1e9ac
DO
770 echo "<tr><td>&nbsp;</td><th class=tdright>Actions:</th><td class=tdleft>";
771 echo "<a href='".
3067f362 772 makeHrefProcess(array('op'=>'deleteObject', 'page'=>'depot', 'tab'=>'addmore', 'object_id'=>$object_id)).
abd1e9ac
DO
773 "' onclick=\"javascript:return confirm('Are you sure you want to delete the object?')\">" . getImageHREF ('destroy', 'Delete object') . "</a>";
774 echo "&nbsp;";
775 echo "<a href='".
776 makeHrefProcess(array ('op'=>'resetObject', 'page' => 'object', 'tab' => 'edit', 'object_id' => $object_id)).
777 "' onclick=\"javascript:return confirm('Are you sure you want to reset most of object properties?')\">" . getImageHREF ('clear', 'Reset (cleanup) object') . "</a>";
778 echo "</td></tr>\n";
e10f583a 779 echo "<tr><td colspan=3><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
cdd3efe9 780
e10f583a 781 echo "<tr><th class=submit colspan=3>";
5bbbeaa2 782 printImageHREF ('SAVE', 'Save changes', TRUE);
cdd3efe9 783 echo "</form></th></tr></table>\n";
e673ee24 784 finishPortlet();
e673ee24 785
cdd3efe9 786 echo '<table border=0 width=100%><tr><td>';
e673ee24
DO
787 startPortlet ('history');
788 renderHistory ($pageno, $object_id);
789 finishPortlet();
cdd3efe9 790 echo '</td></tr></table>';
e673ee24
DO
791}
792
793// This is a clone of renderEditObjectForm().
794function renderEditRackForm ($rack_id)
795{
0c2b7c4a 796 global $pageno;
61a1d996
DO
797 $rack = spotEntity ('rack', $rack_id);
798 amplifyCell ($rack);
e673ee24 799
e673ee24 800 startPortlet ('Rack attributes');
7056988c 801 printOpFormIntro ('updateRack');
e673ee24
DO
802 echo '<table border=0 align=center>';
803 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
cd3775e9 804 printSelect (getRackRows(), array ('name' => 'rack_row_id'), $rack['row_id']);
e673ee24
DO
805 echo "</td></tr>\n";
806 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
807 echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
808 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
c8187437
DY
809 if (count ($rack['mountedObjects']) == 0)
810 {
811 echo "<tr><th class=tdright>Actions:</th><td class=tdleft><a href='".
812 makeHrefProcess(array('op'=>'deleteRack', 'rack_id'=>$rack_id)).
813 "' onclick=\"javascript:return confirm('Are you sure you want to delete the rack?')\">Delete rack</a></td></tr>\n";
814 }
7056988c
DO
815 echo "<tr><td class=submit colspan=2>";
816 printImageHREF ('SAVE', 'Save changes', TRUE);
817 echo "</td></tr>\n";
e673ee24
DO
818 echo '</form></table><br>';
819 finishPortlet();
820
821 startPortlet ('History');
822 renderHistory ($pageno, $rack_id);
823 finishPortlet();
824}
825
01a0f80e 826function printSelect ($optionList, $select_attrs = array(), $selected_id = NULL)
4c9066b0
DO
827{
828 echo getSelect ($optionList, $select_attrs, $selected_id);
829}
830
831// Input array keys are OPTION VALUEs and input array values are OPTION text.
832function getSelect ($optionList, $select_attrs = array(), $selected_id = NULL)
e673ee24 833{
c71a8459 834 $ret = '';
cd3775e9 835 if (!array_key_exists ('name', $select_attrs))
c71a8459 836 return '';
6bc35283
DO
837 // handle two corner cases in a specific way
838 if (count ($optionList) == 0)
e88f212b 839 return '(none)';
6bc35283
DO
840 if (count ($optionList) == 1)
841 {
842 $value = current (array_keys ($optionList));
8e87af1f 843 return "<input type=hidden name=${select_attrs['name']} id=${select_attrs['name']} value=${value}>" . current ($optionList);
6bc35283 844 }
2177264c
DO
845 if (!array_key_exists ('id', $select_attrs))
846 $select_attrs['id'] = $select_attrs['name'];
c71a8459 847 $ret .= '<select';
cd3775e9 848 foreach ($select_attrs as $attr_name => $attr_value)
c71a8459
DO
849 $ret .= " ${attr_name}=${attr_value}";
850 $ret .= '>';
f3d274bf 851 foreach ($optionList as $dict_key => $dict_value)
c71a8459
DO
852 $ret .= "<option value='${dict_key}'" . ($dict_key == $selected_id ? ' selected' : '') . ">${dict_value}</option>";
853 $ret .= '</select>';
854 return $ret;
f3d274bf
DO
855}
856
eea3ca5e 857function printNiftySelect ($groupList, $select_attrs = array(), $selected_id = NULL, $autocomplete = false)
7d4db2b9
DO
858{
859 echo getNiftySelect ($groupList, $select_attrs, $selected_id);
860}
861
f3d274bf
DO
862// Input is a cooked list of OPTGROUPs, each with own sub-list of OPTIONs in the same
863// format as printSelect() expects.
7d4db2b9 864function getNiftySelect ($groupList, $select_attrs, $selected_id = NULL)
f3d274bf
DO
865{
866 // special treatment for ungrouped data
867 if (count ($groupList) == 1 and isset ($groupList['other']))
7d4db2b9 868 return getSelect ($groupList['other'], $select_attrs, $selected_id);
cd3775e9 869 if (!array_key_exists ('name', $select_attrs))
7d4db2b9 870 return '';
2177264c
DO
871 if (!array_key_exists ('id', $select_attrs))
872 $select_attrs['id'] = $select_attrs['name'];
7d4db2b9 873 $ret = '<select';
cd3775e9 874 foreach ($select_attrs as $attr_name => $attr_value)
7d4db2b9
DO
875 $ret .= " ${attr_name}=${attr_value}";
876 $ret .= '>';
f3d274bf 877 foreach ($groupList as $groupname => $groupdata)
9e7f32a7 878 {
7d4db2b9 879 $ret .= "<optgroup label='${groupname}'>";
f3d274bf 880 foreach ($groupdata as $dict_key => $dict_value)
7d4db2b9
DO
881 $ret .= "<option value='${dict_key}'" . ($dict_key == $selected_id ? ' selected' : '') . ">${dict_value}</option>";
882 $ret .= '</optgroup>';
e673ee24 883 }
7d4db2b9
DO
884 $ret .= '</select>';
885 return $ret;
e673ee24
DO
886}
887
254673dd
DO
888// used by renderGridForm() and renderRackPage()
889function renderRackInfoPortlet ($rackData)
890{
891 startPortlet ('summary');
892 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
893 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
894 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
895 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
04d619d0 896 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
254673dd
DO
897 renderProgressBar (getRSUforRack ($rackData));
898 echo "</td></tr>\n";
899 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
61a1d996 900 echo count ($rackData['mountedObjects']);
254673dd 901 echo "</td></tr>\n";
9b57f793 902 printTagTRs ($rackData, makeHref(array('page'=>'rackspace', 'tab'=>'default'))."&");
59a83bd8 903 if (strlen ($rackData['comment']))
254673dd
DO
904 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
905 echo '</table>';
906 finishPortlet();
907}
908
e673ee24 909// This is a universal editor of rack design/waste.
7056988c 910// FIXME: switch to using printOpFormIntro()
7e1db771 911function renderGridForm ($rack_id, $filter, $header, $submit, $state1, $state2)
e673ee24 912{
61a1d996
DO
913 $rackData = spotEntity ('rack', $rack_id);
914 amplifyCell ($rackData);
254673dd 915 $filter ($rackData);
e673ee24
DO
916 markupObjectProblems ($rackData);
917
e673ee24
DO
918 // Render the result whatever it is.
919 // Main layout.
920 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
921 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
922
923 // Left column with information portlet.
924 echo "<tr><td class=pcleft height='1%' width='50%'>";
254673dd 925 renderRackInfoPortlet ($rackData);
e673ee24 926 echo "</td>\n";
bb09cca0 927 echo "<td class=pcright>";
e673ee24
DO
928
929 // Grid form.
930 startPortlet ($header);
65e557dd 931 addJS ('js/racktables.js');
e673ee24
DO
932 echo "<center>\n";
933 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
57c69e9c 934 echo "<tr><th width='10%'>&nbsp;</th>";
64259015
DO
935 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>";
936 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>";
937 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";
4fbb5a00 938 printOpFormIntro ('updateRack');
e673ee24
DO
939 markupAtomGrid ($rackData, $state2);
940 renderAtomGrid ($rackData);
941 echo "</table></center>\n";
942 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
943 finishPortlet();
bb09cca0 944 echo "</td></tr></table>\n";
e673ee24
DO
945}
946
947function renderRackDesign ($rack_id)
948{
bb09cca0 949 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
e673ee24
DO
950}
951
7e1db771 952function renderRackProblems ($rack_id)
e673ee24 953{
bb09cca0 954 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
e673ee24
DO
955}
956
957function startPortlet ($title = '')
958{
959 echo "<div class=portlet><h2>${title}</h2>";
960}
961
962function finishPortlet ()
963{
964 echo "</div>\n";
965}
966
7e1db771 967function renderRackObject ($object_id)
e673ee24 968{
4fbb5a00 969 global $nextorder, $aac;
fb6e2f57
DO
970 $info = spotEntity ('object', $object_id);
971 // FIXME: employ amplifyCell() instead of calling loader functions directly
94fe6370 972 amplifyCell ($info);
e673ee24
DO
973 // Main layout starts.
974 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
975 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
976 // left column with uknown number of portlets
977 echo "<tr><td class=pcleft>";
0ab782bc 978 startPortlet ('summary');
e673ee24 979 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
59a83bd8 980 if (strlen ($info['name']))
e673ee24 981 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
212c9d8a 982 // FIXME: don't call spotEntity() each time, do it once in the beginning.
94fe6370 983 elseif (considerConfiguredConstraint ($info, 'NAMEWARN_LISTSRC'))
a0ec6295 984 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
341fd895
DO
985 echo "<tr><th width='50%' class=tdright>Object type:</th><td class=tdleft><a href='";
986 echo makeHref (array (
987 'page' => 'depot',
988 'tab' => 'default',
989 'cfe' => '{$typeid_' . $info['objtype_id'] . '}'
990 ));
7fa7047a 991 echo "'>" . decodeObjectType ($info['objtype_id'], 'o') . '</a></td></tr>';
59a83bd8 992 if (strlen ($info['asset_no']))
e673ee24 993 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
212c9d8a 994 // FIXME: ditto
d4e8ddeb 995 elseif (considerConfiguredConstraint ($info, 'ASSETWARN_LISTSRC'))
a0ec6295 996 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
59a83bd8 997 if (strlen ($info['label']))
e673ee24 998 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
59a83bd8 999 if (strlen ($info['barcode']))
e673ee24 1000 echo "<tr><th width='50%' class=tdright>Barcode:</th><td class=tdleft>${info['barcode']}</td></tr>\n";
0682218d
AD
1001 if ($parents = getEntityRelatives ('parents', 'object', $object_id))
1002 {
1003 foreach ($parents as $parent)
1004 {
1005 if (!isset($label))
1006 $label = count($parents) > 1 ? 'Containers:' : 'Container:';
1007 echo "<tr><th width='50%' class=tdright>${label}</th><td class=tdleft>";
1008 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$parent['entity_id']))."'>${parent['name']}</a>";
1009 echo "</td></tr>\n";
1010 $label = '&nbsp;';
1011 }
1012 unset ($label);
1013 }
1014 if ($children = getEntityRelatives ('children', 'object', $object_id))
1015 {
1016 foreach ($children as $child)
1017 {
1018 if (!isset($label))
1019 $label = 'Contains:';
1020 echo "<tr><th width='50%' class=tdright>${label}</th><td class=tdleft>";
1021 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$child['entity_id']))."'>${child['name']}</a>";
1022 echo "</td></tr>\n";
1023 $label = '&nbsp;';
1024 }
1025 }
e673ee24
DO
1026 if ($info['has_problems'] == 'yes')
1027 echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
8ad59489 1028 foreach (getAttrValues ($object_id) as $record)
59a83bd8 1029 if (strlen ($record['value']))
0794fb66
AA
1030 {
1031 echo "<tr><th width='50%' class=sticker>${record['name']}:</th><td class=sticker>" .
8ad59489 1032 formatAttributeValue ($record) .
0794fb66
AA
1033 "</td></tr>\n";
1034 }
341fd895
DO
1035 printTagTRs
1036 (
9b57f793 1037 $info,
341fd895
DO
1038 makeHref
1039 (
1040 array
1041 (
1042 'page'=>'depot',
1043 'tab'=>'default',
1044 'andor' => 'and',
a8efc03e 1045 'cfe' => '{$typeid_' . $info['objtype_id'] . '}',
341fd895
DO
1046 )
1047 )."&"
1048 );
e673ee24
DO
1049 echo "</table><br>\n";
1050 finishPortlet();
1051
59a83bd8 1052 if (strlen ($info['comment']))
e673ee24
DO
1053 {
1054 startPortlet ('Comment');
6cc5d6cd 1055 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
e673ee24
DO
1056 finishPortlet ();
1057 }
1058
9a90adc4
DO
1059 if (count ($logrecords = getLogRecordsForObject ($_REQUEST['object_id'])))
1060 {
1061 startPortlet ('log records');
1062 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='100%'>";
1063 $order = 'odd';
1064 foreach (getLogRecordsForObject ($_REQUEST['object_id']) as $row)
1065 {
1066 echo "<tr class=row_${order} valign=top>";
1067 echo '<td class=tdleft>' . $row['date'] . '<br>' . $row['user'] . '</td>';
1068 echo '<td class="slbconf rsvtext">' . string_insert_hrefs ($row['content']) . '</td>';
1069 echo '</tr>';
1070 $order = $nextorder[$order];
1071 }
1072 echo '</table>';
1073 finishPortlet();
1074 }
1075
65e557dd 1076 switchportInfoJS ($object_id); // load JS code to make portnames interactive
e1ae3fb4
AD
1077 renderFilesPortlet ('object', $object_id);
1078
9f75e165 1079 if (count ($info['ports']))
e673ee24 1080 {
0ab782bc 1081 startPortlet ('ports and links');
9f75e165
DO
1082 $hl_port_id = 0;
1083 if (isset ($_REQUEST['hl_port_id']))
e673ee24 1084 {
0cc24e9a 1085 assertUIntArg ('hl_port_id');
9f75e165 1086 $hl_port_id = $_REQUEST['hl_port_id'];
65e557dd 1087 addAutoScrollScript ("port-$hl_port_id");
9f75e165
DO
1088 }
1089 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>";
1090 echo '<tr><th class=tdleft>Local name</th><th class=tdleft>Visible label</th>';
0d59a51c 1091 echo '<th class=tdleft>Interface</th><th class=tdleft>L2 address</th>';
0c7c9f8b
DO
1092 echo '<th class=tdcenter colspan=2>Remote object and port</th>';
1093 echo '<th class=tdleft>Cable ID</th></tr>';
9f75e165
DO
1094 foreach ($info['ports'] as $port)
1095 {
1096 echo '<tr';
1097 if ($hl_port_id == $port['id'])
1098 echo ' class=port_highlight';
65e557dd
AA
1099 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
1100 echo "><td class='tdleft' NOWRAP><a name='port-${port['id']}' class='interactive-portname nolink $a_class'>${port['name']}</a></td>";
1101 echo "<td class=tdleft>${port['label']}</td>";
1102 echo "<td class=tdleft>" . formatPortIIFOIF ($port) . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
9f75e165 1103 if ($port['remote_object_id'])
e673ee24 1104 {
cd3775e9
DO
1105 $remote_object = spotEntity ('object', $port['remote_object_id']);
1106 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>";
9f75e165 1107 echo "<td class=tdleft>${port['remote_name']}</td>";
0c7c9f8b 1108 echo "<td class='tdleft rsvtext'>${port['cableid']}</td>";
e673ee24 1109 }
9f75e165 1110 elseif (strlen ($port['reservation_comment']))
e673ee24 1111 {
9f75e165 1112 echo "<td class=tdleft><b>Reserved:</b></td>";
d362ab69 1113 echo "<td class='tdleft rsvtext'>${port['reservation_comment']}</td><td>&nbsp;</td>";
e673ee24 1114 }
9f75e165 1115 else
d362ab69 1116 echo '<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>';
9f75e165 1117 echo "</tr>";
e673ee24 1118 }
9f75e165 1119 echo "</table><br>";
e673ee24
DO
1120 finishPortlet();
1121 }
85970da2 1122
21ee3351 1123 if (count ($info['ipv4']) + count ($info['ipv6']))
e673ee24 1124 {
21ee3351 1125 startPortlet ('IP addresses');
e673ee24 1126 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
f0ed1181 1127 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
0b9c98d7 1128 echo "<tr><th>OS interface</th><th>IP address</th><th>network</th><th>routed by</th><th>peers</th></tr>\n";
83fdf85f
DO
1129 else
1130 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
21ee3351
AA
1131 $hl_ip_addr = '';
1132 if (isset ($_REQUEST['hl_ipv6_addr']))
1133 {
1134 if ($hl_ipv6 = assertIPv6Arg ('hl_ipv6_addr'))
1135 $hl_ip_addr = $hl_ipv6->format();
1136 }
1137 elseif (isset ($_REQUEST['hl_ipv4_addr']))
1138 $hl_ip_addr = $_REQUEST['hl_ipv4_addr'];
00276508 1139 if ($hl_ip_addr)
65e557dd 1140 addAutoScrollScript ("ip-$hl_ip_addr");
21ee3351
AA
1141
1142 // group IP allocations by interface name instead of address family
1143 $allocs_by_iface = array();
1144 foreach (array ('ipv4', 'ipv6') as $ip_v)
1145 foreach ($info[$ip_v] as $dottedquad => $alloc)
1146 $allocs_by_iface[$alloc['osif']][$dottedquad] = $alloc;
1147
1148 // sort allocs array by portnames
1149 foreach (sortPortList ($allocs_by_iface) as $iface_name => $alloclist)
1150 {
1151 $is_first_row = TRUE;
1152 foreach ($alloclist as $dottedquad => $alloc)
b90c3907 1153 {
21ee3351
AA
1154 if ($alloc['addrinfo']['version'] == 6)
1155 {
1156 $addr_page_name = 'ipv6address';
1157 $ipv6_address = new IPv6Address ($dottedquad);
1158 $dottedquad = $ipv6_address->format();
1159 if ($netid = getIPv6AddressNetworkId ($ipv6_address))
1160 {
1161 $netinfo = spotEntity ('ipv6net', $netid);
1162 loadIPv6AddrList ($netinfo);
1163 }
1164 }
1165 else
1166 {
1167 $addr_page_name = 'ipaddress';
1168 if ($netid = getIPv4AddressNetworkId ($dottedquad))
1169 {
1170 $netinfo = spotEntity ('ipv4net', $netid);
1171 loadIPv4AddrList ($netinfo);
1172 }
1173 }
1174 $address_name = niftyString ($alloc['addrinfo']['name']);
1175 $class = $alloc['addrinfo']['class'];
1176 $secondclass = ($hl_ip_addr == $dottedquad) ? 'tdleft port_highlight' : 'tdleft';
1177 echo "<tr class='${class}' valign=top>";
1178
1179 // display iface name (common cell for both address families)
1180 if ($is_first_row)
1181 {
1182 $rowspan = count ($alloclist) > 1 ? 'rowspan="' . count ($alloclist) . '"' : '';
1183 echo "<td class=tdleft $rowspan>$iface_name</td>";
1184 $is_first_row = FALSE;
1185 }
1186 echo "<td class='${secondclass}'>";
1187 if (NULL !== $netid)
00276508 1188 echo "<a name='ip-$dottedquad' href='index.php?page=$addr_page_name&hl_object_id=$object_id&ip=$dottedquad'>${dottedquad}</a>";
83fdf85f 1189 else
21ee3351
AA
1190 echo $dottedquad;
1191 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1192 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1193 echo '&nbsp;' . $aac[$alloc['type']];
1194 if (strlen ($alloc['addrinfo']['name']))
1195 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1196 echo '</td>';
1197 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
83fdf85f 1198 {
21ee3351
AA
1199 if (NULL === $netid)
1200 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
0b9c98d7 1201 else
21ee3351
AA
1202 {
1203 echo "<td class='${secondclass}'>";
1204 renderCell ($netinfo);
1205 echo "</td>";
1206 // filter out self-allocation
1207 $other_routers = array();
1208 foreach (findRouters ($netinfo['addrlist']) as $router)
1209 if ($router['id'] != $object_id)
1210 $other_routers[] = $router;
1211 if (count ($other_routers))
1212 printRoutersTD ($other_routers);
1213 else
1214 echo "<td class='${secondclass}'>&nbsp;</td>";
1215 }
83fdf85f 1216 }
21ee3351
AA
1217 // peers
1218 echo "<td class='${secondclass}'>\n";
1219 $prefix = '';
1220 if ($alloc['addrinfo']['reserved'] == 'yes')
1221 {
1222 echo $prefix . '<strong>RESERVED</strong>';
1223 $prefix = '; ';
1224 }
1225 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1226 {
1227 if ($allocpeer['object_id'] == $object_id)
1228 continue;
1229 echo $prefix . "<a href='" . makeHref (array ('page' => 'object', 'object_id' => $allocpeer['object_id'])) . "'>";
1230 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
1231 echo $allocpeer['osif'] . '@';
1232 echo $allocpeer['object_name'] . '</a>';
1233 $prefix = '; ';
1234 }
1235 echo "</td></tr>\n";
b90c3907 1236 }
e673ee24
DO
1237 }
1238 echo "</table><br>\n";
1239 finishPortlet();
1240 }
1241
94fe6370 1242 $forwards = $info['nat4'];
e673ee24
DO
1243 if (count($forwards['in']) or count($forwards['out']))
1244 {
f28fbe8b 1245 startPortlet('NATv4');
e673ee24
DO
1246
1247 if (count($forwards['out']))
1248 {
1249
f28fbe8b 1250 echo "<h3>locally performed NAT</h3>";
e673ee24 1251
105a3bc8 1252 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 1253 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
e673ee24
DO
1254
1255 foreach ($forwards['out'] as $pf)
1256 {
2c817354
DO
1257 $class = 'trerror';
1258 $osif = '';
1259 if (isset ($alloclist [$pf['localip']]))
1260 {
1261 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
1262 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
1263 }
e673ee24 1264 echo "<tr class='$class'>";
4fbb5a00
DY
1265 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>";
1266 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
53ef3908 1267 $address = getIPv4Address ($pf['remoteip']);
e673ee24 1268 echo "<td class='description'>";
53ef3908
DO
1269 if (count ($address['allocs']))
1270 foreach($address['allocs'] as $bond)
4fbb5a00 1271 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
59a83bd8 1272 elseif (strlen ($pf['remote_addr_name']))
f28fbe8b 1273 echo '(' . $pf['remote_addr_name'] . ')';
53ef3908 1274 echo "</td><td class='description'>${pf['description']}</td></tr>";
e673ee24
DO
1275 }
1276 echo "</table><br><br>";
1277 }
1278 if (count($forwards['in']))
1279 {
f28fbe8b 1280 echo "<h3>arriving NAT connections</h3>";
105a3bc8 1281 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 1282 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
e673ee24
DO
1283 foreach ($forwards['in'] as $pf)
1284 {
1285 echo "<tr>";
4fbb5a00
DY
1286 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
1287 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
1288 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24
DO
1289 echo "<td class='description'>${pf['description']}</td></tr>";
1290 }
e673ee24
DO
1291 echo "</table><br><br>";
1292 }
1293 finishPortlet();
1294 }
1295
94fe6370 1296 $pools = $info['ipv4rspools'];
78e7b769
DO
1297 if (count ($pools))
1298 {
300826cb 1299 $order = 'odd';
8128c257 1300 startPortlet ('Real server pools (' . count ($pools) . ')');
78e7b769 1301 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
1f54e1ba 1302 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";
3d26a66e 1303 foreach ($pools as $vs_id => $vs_info)
78e7b769 1304 {
b1a970c7 1305 echo "<tr valign=top class=row_${order}><td class=tdleft>";
6df2025d 1306 renderCell (spotEntity ('ipv4vs', $vs_id));
b1a970c7 1307 echo "</td><td class=tdleft>";
3d26a66e
AA
1308 renderCell (spotEntity ('ipv4rspool', $vs_info['pool_id']));
1309 echo '</td><td class=tdleft>' . $vs_info['rscount'] . '</td>';
1310 echo "<td class=slbconf>${vs_info['vsconfig']}</td>";
1311 echo "<td class=slbconf>${vs_info['rsconfig']}</td>";
1312 echo "<td class=slbconf>${vs_info['prio']}</td>";
78e7b769 1313 echo "</tr>\n";
300826cb 1314 $order = $nextorder[$order];
78e7b769
DO
1315 }
1316 echo "</table>\n";
1317 finishPortlet();
1318 }
e673ee24
DO
1319 echo "</td>\n";
1320
7056988c 1321 // After left column we have (surprise!) right column with rackspace portlet only.
e673ee24 1322 echo "<td class=pcright>";
0682218d
AD
1323 if (!considerConfiguredConstraint ($info, 'VIRTUAL_OBJ_LISTSRC'))
1324 {
1325 // rackspace portlet
1326 startPortlet ('rackspace allocation');
1327 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1328 renderRack ($rack_id, $object_id);
1329 echo '<br>';
1330 finishPortlet();
1331 }
e673ee24
DO
1332 echo "</td></tr>";
1333 echo "</table>\n";
1334}
1335
1336function renderRackMultiSelect ($sname, $racks, $selected)
1337{
04571888
DO
1338 // Transform the given flat list into a list of groups, each representing a rack row.
1339 $rdata = array();
e673ee24 1340 foreach ($racks as $rack)
04571888
DO
1341 if (!isset ($rdata[$rack['row_name']]))
1342 $rdata[$rack['row_name']] = array ($rack['id'] => $rack['name']);
1343 else
1344 $rdata[$rack['row_name']][$rack['id']] = $rack['name'];
4fbb5a00 1345 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementsByName(\"updateObjectAllocation\")[0].submit()'>\n";
04571888 1346 foreach ($rdata as $optgroup => $racklist)
e673ee24 1347 {
04571888
DO
1348 echo "<optgroup label='${optgroup}'>";
1349 foreach ($racklist as $rack_id => $rack_name)
1350 {
1351 echo "<option value=${rack_id}";
1352 if (!(array_search ($rack_id, $selected) === FALSE))
1353 echo ' selected';
1354 echo">${rack_name}</option>\n";
1355 }
e673ee24
DO
1356 }
1357 echo "</select>\n";
1358}
1359
e673ee24 1360// This function renders a form for port edition.
7e1db771 1361function renderPortsForObject ($object_id)
e673ee24 1362{
3153a326
DO
1363 $prefs = getPortListPrefs();
1364 function printNewItemTR ($prefs)
39b4abd0
DO
1365 {
1366 printOpFormIntro ('addPort');
1367 echo "<tr><td>";
f5ff50f5 1368 printImageHREF ('add', 'add a port', TRUE);
65e557dd 1369 echo "</td><td class='tdleft'><input type=text size=8 name=port_name tabindex=100></td>\n";
cd3775e9
DO
1370 echo "<td><input type=text name=port_label tabindex=101></td><td>";
1371 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 102), $prefs['selected']);
1372 echo "<td><input type=text name=port_l2address tabindex=103 size=18 maxlength=24></td>\n";
9318d2ef
DO
1373 echo "<td colspan=3>&nbsp;</td><td>";
1374 printImageHREF ('add', 'add a port', TRUE, 104);
1375 echo "</td></tr></form>";
39b4abd0 1376 }
a1fc539a 1377 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes' || getConfigVar('ENABLE_BULKPORT_FORM') == 'yes' )
f44fdef9
DO
1378 startPortlet ('Ports and interfaces');
1379 else
1380 echo '<br>';
9f75e165
DO
1381 $object = spotEntity ('object', $object_id);
1382 amplifyCell ($object);
a1fc539a
RF
1383 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1384 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1385 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>";
1386 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1387 printOpFormIntro ('addBulkPorts');
1388 echo "<tr><td>";
1389 printImageHREF ('add', 'add ports', TRUE);
1390 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1391 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1392 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1393 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1394 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1395 echo "<td>&nbsp;</td><td>";
1396 printImageHREF ('add', 'add ports', TRUE, 110);
1397 echo "</td></tr></form>";
1398 echo "</table><br>\n";
1399 }
1400
e673ee24 1401 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
0d59a51c 1402 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>";
0c7c9f8b 1403 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";
39b4abd0 1404 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
3153a326 1405 printNewItemTR ($prefs);
45ff9012
AA
1406
1407 // clear ports link
1408 echo "<a href='".
1409 makeHrefProcess(array ('op'=>'deleteAll', 'page' => 'object', 'tab' => 'ports', 'object_id' => $object_id)).
1410 "' onclick=\"javascript:return confirm('Are you sure you want to delete all existing ports?')\">" . getImageHREF ('clear', 'Clear port list') . " Clear port list</a>";
1411
00276508
AA
1412 if (isset ($_REQUEST['hl_port_id']))
1413 {
1414 assertUIntArg ('hl_port_id');
1415 $hl_port_id = intval ($_REQUEST['hl_port_id']);
65e557dd 1416 addAutoScrollScript ("port-$hl_port_id");
00276508 1417 }
65e557dd 1418 switchportInfoJS ($object_id); // load JS code to make portnames interactive
9f75e165 1419 foreach ($object['ports'] as $port)
e673ee24 1420 {
00276508 1421 $tr_class = isset ($hl_port_id) && $hl_port_id == $port['id'] ? 'class="port_highlight"' : '';
7056988c 1422 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
10005279 1423 echo "<tr $tr_class><td><a name='port-${port['id']}' href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id'], 'object_id'=>$object_id))."'>";
e673ee24
DO
1424 printImageHREF ('delete', 'Unlink and Delete this port');
1425 echo "</a></td>\n";
65e557dd
AA
1426 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
1427 echo "<td class='tdleft' NOWRAP><input type=text name=name class='interactive-portname $a_class' value='${port['name']}' size=8></td>";
cd3775e9 1428 echo "<td><input type=text name=label value='${port['label']}'></td>";
611170af
AD
1429 if (!$port['remote_object_id'])
1430 {
3153a326
DO
1431 echo '<td>';
1432 if ($port['iif_id'] != 1)
1433 echo '<label>' . $port['iif_name'] . ' ';
cd3775e9 1434 printSelect (getExistingPortTypeOptions ($port['id']), array ('name' => 'port_type_id'), $port['oif_id']);
3153a326
DO
1435 if ($port['iif_id'] != 1)
1436 echo '</label>';
1437 echo '</td>';
611170af
AD
1438 }
1439 else
1440 {
045bab87 1441 echo "<input type=hidden name=port_type_id value='${port['oif_id']}'><td class=tdleft>";
e9d357e1 1442 echo formatPortIIFOIF ($port) . '</td>';
611170af 1443 }
cd3775e9
DO
1444 // 18 is enough to fit 6-byte MAC address in its longest form,
1445 // while 24 should be Ok for WWN
1446 echo "<td><input type=text name=l2address value='${port['l2address']}' size=18 maxlength=24></td>\n";
e673ee24
DO
1447 if ($port['remote_object_id'])
1448 {
cd3775e9 1449 $remote_object = spotEntity ('object', $port['remote_object_id']);
0c7c9f8b 1450 echo "<td>${port['cableid']}&nbsp;<a href='".makeHref(array('page'=>'object', 'object_id'=>$port['remote_object_id']))."'>${remote_object['dname']}</a></td>";
995e7d5b 1451 echo "<td>${port['remote_name']}<input type=hidden name=reservation_comment value=''></td>";
3153a326 1452 echo "<td class=tdcenter><a href='".
4fbb5a00
DY
1453 makeHrefProcess(array(
1454 'op'=>'unlinkPort',
cd3775e9 1455 'port_id'=>$port['id'],
cd3775e9 1456 'object_id'=>$object_id)).
4fbb5a00 1457 "'>";
5ccd99a0 1458 printImageHREF ('cut', 'Unlink this port');
e673ee24
DO
1459 echo "</a></td>";
1460 }
59a83bd8 1461 elseif (strlen ($port['reservation_comment']))
e673ee24 1462 {
3153a326 1463 echo "<td><b>Reserved:</b></td>";
e673ee24 1464 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
3153a326 1465 echo "<td class=tdcenter><a href='".
4fbb5a00
DY
1466 makeHrefProcess(array(
1467 'op'=>'useup',
1468 'port_id'=>$port['id'],
1469 'object_id'=>$object_id)).
1470 "'>";
39be655e 1471 printImageHREF ('clear', 'Use up this port');
e673ee24
DO
1472 echo "</a></td>";
1473 }
1474 else
1475 {
cd3775e9
DO
1476 //echo "<td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><a href='javascript:;'";
1477 echo "<td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><span";
1478 $helper_args = array
1479 (
1480 'port' => $port['id'],
cd3775e9
DO
1481 'in_rack' => 'n',
1482 );
1483 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
9e214652 1484 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
cd3775e9
DO
1485 echo " ondblclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1486 echo "\",\"findlink\",\"${popup_args}\");'";
1487 // end of onclick=
1488 $helper_args['in_rack'] = 'y';
1489 echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1490 echo "\",\"findlink\",\"${popup_args}\");'";
1491 // end of onclick=
1492 echo '>';
1493 // end of <a>
5ccd99a0 1494 printImageHREF ('plug', 'Link this port');
cd3775e9
DO
1495 echo "</span>";
1496 echo " <input type=text name=reservation_comment></td>\n";
e673ee24 1497 }
5bbbeaa2
DO
1498 echo "<td>";
1499 printImageHREF ('save', 'Save changes', TRUE);
1500 echo "</td></form></tr>\n";
e673ee24 1501 }
39b4abd0 1502 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
3153a326 1503 printNewItemTR ($prefs);
e673ee24 1504 echo "</table><br>\n";
a1fc539a
RF
1505 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1506 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1507 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>";
1508 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1509 printOpFormIntro ('addBulkPorts');
1510 echo "<tr><td>";
1511 printImageHREF ('add', 'add ports', TRUE);
1512 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1513 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1514 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1515 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1516 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1517 echo "<td>&nbsp;</td><td>";
1518 printImageHREF ('add', 'add ports', TRUE, 110);
1519 echo "</td></tr></form>";
1520 echo "</table><br>\n";
1521 }
f44fdef9
DO
1522 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes')
1523 finishPortlet();
1524 if (getConfigVar('ENABLE_MULTIPORT_FORM') != 'yes')
1525 return;
e673ee24
DO
1526
1527 startPortlet ('Add/update multiple ports');
7056988c 1528 printOpFormIntro ('addMultiPorts');
f7a3c94a 1529 echo 'Format: <select name=format tabindex=201>';
e673ee24
DO
1530 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1531 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
e673ee24 1532 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
351d4dbf 1533 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
e673ee24
DO
1534 echo "</select>";
1535 echo 'Default port type: ';
cd3775e9 1536 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type', 'tabindex' => 202), $prefs['selected']);
f7a3c94a
DO
1537 echo "<input type=submit value='Parse output' tabindex=204><br>\n";
1538 echo "<textarea name=input cols=100 rows=50 tabindex=203></textarea><br>\n";
e673ee24
DO
1539 echo '</form>';
1540 finishPortlet();
1541}
1542
7e1db771 1543function renderIPv4ForObject ($object_id)
e673ee24 1544{
39b4abd0
DO
1545 function printNewItemTR ()
1546 {
1547 global $aat;
1548 printOpFormIntro ('addIPv4Allocation');
1549 echo "<tr><td>";
f5ff50f5 1550 printImageHREF ('add', 'allocate', TRUE);
39b4abd0
DO
1551 echo "</td>";
1552 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1553 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
0b9c98d7 1554 echo "<td colspan=2>&nbsp;</td><td>";
01abf1de 1555 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), 'regular');
9318d2ef 1556 echo "</td><td>&nbsp;</td><td>";
f5ff50f5 1557 printImageHREF ('add', 'allocate', TRUE, 103);
9318d2ef 1558 echo "</td></tr></form>";
39b4abd0 1559 }
94fe6370
DO
1560 $focus = spotEntity ('object', $object_id);
1561 amplifyCell ($focus);
b82cce3f 1562 global $aat;
72d8ced3 1563 startPortlet ('Allocations');
e673ee24 1564 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
79e45b4c
DO
1565 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1566 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
0b9c98d7 1567 echo '<th>network</th><th>routed by</th>';
79e45b4c 1568 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
09620506 1569
39b4abd0
DO
1570 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1571 printNewItemTR();
94fe6370 1572 foreach ($focus['ipv4'] as $dottedquad => $alloc)
e673ee24 1573 {
85970da2 1574 $class = $alloc['addrinfo']['class'];
79e45b4c 1575 $netid = getIPv4AddressNetworkId ($dottedquad);
d7a8186d
DO
1576 if (NULL !== $netid)
1577 {
d724d290 1578 $netinfo = spotEntity ('ipv4net', $netid);
d7a8186d
DO
1579 loadIPv4AddrList ($netinfo);
1580 }
85970da2 1581 printOpFormIntro ('updIPv4Allocation', array ('ip' => $dottedquad));
4fbb5a00 1582 echo "<tr class='$class' valign=top><td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$object_id))."'>";
e673ee24
DO
1583 printImageHREF ('delete', 'Delete this IPv4 address');
1584 echo "</a></td>";
d7a8186d
DO
1585 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td><td class=tdleft>";
1586 if (NULL !== $netid)
4fbb5a00 1587 echo "<a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$dottedquad))."'>${dottedquad}</a>";
d7a8186d
DO
1588 else
1589 echo $dottedquad;
79e45b4c 1590 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
d7a8186d 1591 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
59a83bd8 1592 if (strlen ($alloc['addrinfo']['name']))
28a664e7 1593 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
79e45b4c
DO
1594 echo '</td>';
1595 // FIXME: this a copy-and-paste from renderRackObject()
1596 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1597 {
1598 if (NULL === $netid)
0b9c98d7 1599 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
79e45b4c 1600 else
79e45b4c 1601 {
0b9c98d7 1602 echo '<td>';
6df2025d 1603 renderCell ($netinfo);
d7a8186d 1604 echo '</td>';
0b9c98d7
DO
1605 // filter out self-allocation
1606 $other_routers = array();
1607 foreach (findRouters ($netinfo['addrlist']) as $router)
1608 if ($router['id'] != $object_id)
1609 $other_routers[] = $router;
1610 if (count ($other_routers))
1611 printRoutersTD ($other_routers);
1612 else
1613 echo "<td>&nbsp;</td>";
79e45b4c 1614 }
79e45b4c
DO
1615 }
1616 echo '<td>';
cd3775e9 1617 printSelect ($aat, array ('name' => 'bond_type'), $alloc['type']);
e673ee24 1618 echo "</td><td>";
85970da2 1619 $prefix = '';
4940e4d5 1620 if ($alloc['addrinfo']['reserved'] == 'yes')
e673ee24 1621 {
85970da2
DO
1622 echo $prefix . '<strong>RESERVED</strong>';
1623 $prefix = '; ';
e673ee24 1624 }
85970da2 1625 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
e673ee24 1626 {
85970da2
DO
1627 if ($allocpeer['object_id'] == $object_id)
1628 continue;
4fbb5a00 1629 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
43eb71f1 1630 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
85970da2
DO
1631 echo $allocpeer['osif'] . '@';
1632 echo $allocpeer['object_name'] . '</a>';
1633 $prefix = '; ';
e673ee24 1634 }
d54b9495
DO
1635 echo "</td><td>";
1636 printImageHREF ('save', 'Save changes', TRUE);
1637 echo "</td></form></tr>\n";
e673ee24 1638 }
39b4abd0
DO
1639 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1640 printNewItemTR();
e673ee24 1641
09620506 1642 echo "</table><br>\n";
e673ee24
DO
1643 finishPortlet();
1644
1645}
1646
21ee3351
AA
1647function renderIPv6ForObject ($object_id)
1648{
1649 function printNewItemTR ()
1650 {
1651 global $aat;
1652 printOpFormIntro ('addIPv6Allocation');
1653 echo "<tr><td>";
1654 printImageHREF ('add', 'allocate', TRUE);
1655 echo "</td>";
1656 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1657 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
1658 echo "<td colspan=2>&nbsp;</td><td>";
1659 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), 'regular');
1660 echo "</td><td>&nbsp;</td><td>";
1661 printImageHREF ('add', 'allocate', TRUE, 103);
1662 echo "</td></tr></form>";
1663 }
1664 $focus = spotEntity ('object', $object_id);
1665 amplifyCell ($focus);
1666 global $aat;
1667 startPortlet ('Allocations');
1668 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1669 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1670 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1671 echo '<th>network</th><th>routed by</th>';
1672 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1673
1674 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1675 printNewItemTR();
1676 foreach ($focus['ipv6'] as $bin_str => $alloc)
1677 {
1678 $ipv6 = new IPv6Address ($bin_str);
1679 $dottedquad = $ipv6->format();
1680 $class = $alloc['addrinfo']['class'];
1681 $netid = getIPv6AddressNetworkId ($ipv6);
1682 if (NULL !== $netid)
1683 {
1684 $netinfo = spotEntity ('ipv6net', $netid);
1685 loadIPv6AddrList ($netinfo);
1686 }
1687 printOpFormIntro ('updIPv6Allocation', array ('ip' => $dottedquad));
1688 echo "<tr class='$class' valign=top><td><a href='".makeHrefProcess(array('op'=>'delIPv6Allocation', 'ip'=>$dottedquad, 'object_id'=>$object_id))."'>";
1689 printImageHREF ('delete', 'Delete this IPv6 address');
1690 echo "</a></td>";
1691 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td><td class=tdleft>";
1692 if (NULL !== $netid)
1693 echo "<a href='index.php?page=ipv6address&ip=$dottedquad'>$dottedquad</a>";
1694 else
1695 echo $dottedquad;
1696 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1697 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1698 if (strlen ($alloc['addrinfo']['name']))
1699 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1700 echo '</td>';
1701 // FIXME: this a copy-and-paste from renderRackObject()
1702 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1703 {
1704 if (NULL === $netid)
1705 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1706 else
1707 {
1708 echo '<td>';
1709 renderCell ($netinfo);
1710 echo '</td>';
1711 // filter out self-allocation
1712 $other_routers = array();
1713 foreach (findRouters ($netinfo['addrlist']) as $router)
1714 if ($router['id'] != $object_id)
1715 $other_routers[] = $router;
1716 if (count ($other_routers))
1717 printRoutersTD ($other_routers);
1718 else
1719 echo "<td>&nbsp;</td>";
1720 }
1721 }
1722 echo '<td>';
1723 printSelect ($aat, array ('name' => 'bond_type'), $alloc['type']);
1724 echo "</td><td>";
1725 $prefix = '';
1726 if ($alloc['addrinfo']['reserved'] == 'yes')
1727 {
1728 echo $prefix . '<strong>RESERVED</strong>';
1729 $prefix = '; ';
1730 }
1731 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1732 {
1733 if ($allocpeer['object_id'] == $object_id)
1734 continue;
1735 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1736 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
1737 echo $allocpeer['osif'] . '@';
1738 echo $allocpeer['object_name'] . '</a>';
1739 $prefix = '; ';
1740 }
1741 echo "</td><td>";
1742 printImageHREF ('save', 'Save changes', TRUE);
1743 echo "</td></form></tr>\n";
1744 }
1745 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1746 printNewItemTR();
1747
1748 echo "</table><br>\n";
1749 finishPortlet();
1750
1751}
1752
08408472
AA
1753// This function is deprecated. Do not rely on its internals,
1754// it will probably be removed in the next major relese.
1755// Use new showError, showWarning, showSuccess functions.
baf37d01
DO
1756// Log structure versions:
1757// 1: the whole structure is a list of code-message pairs
1758// 2 and later: there's a "v" field set, which indicates the version
1759// 2: there's a "m" list set to hold message code and optional arguments
1cb6adf5 1760function showMessageOrError ()
e673ee24 1761{
1cb6adf5
DO
1762 if (!isset ($_SESSION['log']))
1763 return;
1764 $log = $_SESSION['log'];
baf37d01
DO
1765 switch (TRUE)
1766 {
1767 case !isset ($log['v']):
ebb5441d 1768 case $log['v'] == 1:
baf37d01 1769 foreach ($log as $key => $record)
ebb5441d 1770 if ($key !== 'v')
baf37d01
DO
1771 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1772 break;
1773 case $log['v'] == 2:
1774 $msginfo = array
1775 (
8628ae44 1776// records 0~99 with success messages
950a1887 1777 0 => array ('code' => 'success', 'format' => '%s'),
baf37d01 1778 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with port %s at object %s'),
00e93d63
DO
1779 5 => array ('code' => 'success', 'format' => 'added record "%s" successfully'),
1780 6 => array ('code' => 'success', 'format' => 'updated record "%s" successfully'),
1781 7 => array ('code' => 'success', 'format' => 'deleted record "%s" successfully'),
baf37d01 1782 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
baf37d01 1783 21 => array ('code' => 'success', 'format' => 'Generation complete'),
00e93d63
DO
1784 26 => array ('code' => 'success', 'format' => 'updated %u record(s) successfully'),
1785 37 => array ('code' => 'success', 'format' => 'added %u records successfully'),
4492050b 1786 41 => array ('code' => 'success', 'format' => 'uplink ports reverb queued'),
baf37d01
DO
1787 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1788 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
00e93d63
DO
1789 48 => array ('code' => 'success', 'format' => 'added a record successfully'),
1790 49 => array ('code' => 'success', 'format' => 'deleted a record successfully'),
1791 51 => array ('code' => 'success', 'format' => 'updated a record successfully'),
baf37d01 1792 57 => array ('code' => 'success', 'format' => 'Reset complete'),
24dcb9d8 1793 62 => array ('code' => 'success', 'format' => 'gw: %s'),
f0ff4930
DO
1794 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
1795 64 => array ('code' => 'success', 'format' => 'Port %s@%s has been assigned to VLAN %u'),
03e6ef01 1796 66 => array ('code' => 'success', 'format' => "File sent Ok via handler '%s'"),
abef7149 1797 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
7be51fea 1798 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
8bc5d1e4 1799 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
57777e4a 1800 80 => array ('code' => 'success', 'format' => "Added new object '%s'"),
56a797ef 1801 81 => array ('code' => 'success', 'format' => "SNMP: completed '%s' work"),
a1fc539a 1802 82 => array ('code' => 'success', 'format' => "Bulk port creation was successful. %u ports created, %u failed"),
f9428bc6 1803 87 => array ('code' => 'success', 'format' => '802.1Q recalculate: %d ports changed on %d switches'),
8628ae44 1804// records 100~199 with fatal error messages
950a1887 1805 100 => array ('code' => 'error', 'format' => '%s'),
ebb5441d 1806 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
00e93d63 1807 104 => array ('code' => 'error', 'format' => "failed updating record '%s'"),
c48f2e18 1808 105 => array ('code' => 'error', 'format' => 'default VLAN cannot be changed'),
3a089a44 1809 107 => array ('code' => 'error', 'format' => 'Assertion failed: %s'),
ec523868 1810 108 => array ('code' => 'error', 'format' => 'Database error: %s'),
00e93d63
DO
1811 109 => array ('code' => 'error', 'format' => 'failed updating a record'),
1812 110 => array ('code' => 'error', 'format' => 'failed adding a record'),
1813 111 => array ('code' => 'error', 'format' => 'failed deleting a record'),
ebb5441d 1814 120 => array ('code' => 'error', 'format' => 'Reset failed!'),
ebb5441d 1815 127 => array ('code' => 'error', 'format' => 'Added %u real servers and encountered %u errors'),
ebb5441d 1816 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
be28b696 1817 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u record(s)'),
ebb5441d
DO
1818 142 => array ('code' => 'error', 'format' => 'executeAutoPorts() failed'),
1819 143 => array ('code' => 'error', 'format' => 'Tried chaining %u tags, but experienced %u errors.'),
1820 144 => array ('code' => 'error', 'format' => "Error deleting tag: '%s'"),
00e93d63 1821 147 => array ('code' => 'error', 'format' => 'failed adding record "%s"'),
ebb5441d
DO
1822 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1823 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1824 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1825 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1826 153 => array ('code' => 'error', 'format' => 'Password change failed.'),
1827 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1828 155 => array ('code' => 'error', 'format' => 'Save failed.'),
e81fb764 1829 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
24dcb9d8
DO
1830 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1831 160 => array ('code' => 'error', 'format' => 'Invalid arguments'),
1832 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1833 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
c030232f 1834 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
24dcb9d8
DO
1835 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1836 166 => array ('code' => 'error', 'format' => 'gw: %s'),
f0ff4930
DO
1837 167 => array ('code' => 'error', 'format' => 'Could not find port %s'),
1838 168 => array ('code' => 'error', 'format' => 'Port %s is a trunk'),
1839 169 => array ('code' => 'error', 'format' => 'Failed to configure %s, connector returned code %u'),
5222f192 1840 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
f19c75d6 1841 172 => array ('code' => 'error', 'format' => 'Malformed request'),
07de6bb3 1842 179 => array ('code' => 'error', 'format' => 'Expired form has been declined.'),
57777e4a 1843 184 => array ('code' => 'error', 'format' => 'Submitted form is invalid at line %u'),
57777e4a 1844 186 => array ('code' => 'error', 'format' => 'Incomplete form has been ignored. Cheers.'),
74aee2dc
DO
1845 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1846 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
8198f2c6 1847 190 => array ('code' => 'error', 'format' => "Invalid VLAN ID '%s'"),
ca5d4cbc 1848 191 => array ('code' => 'error', 'format' => "deploy was blocked due to conflicting configuration versions"),
f0ff4930 1849
8628ae44 1850// records 200~299 with warnings
950a1887 1851 200 => array ('code' => 'warning', 'format' => '%s'),
24dcb9d8
DO
1852 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1853 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
f0ff4930
DO
1854 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1855 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1856 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
c8187437 1857 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
db55cf54 1858 207 => array ('code' => 'warning', 'format' => 'Ignored empty request'),
57777e4a 1859
24d3182a
DO
1860// records 300~399 with notices
1861 300 => array ('code' => 'neutral', 'format' => '%s'),
1862
baf37d01
DO
1863 );
1864 // Handle the arguments. Is there any better way to do it?
1865 foreach ($log['m'] as $record)
1866 {
5222f192
DO
1867 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1868 {
1869 echo '<div class=msg_neutral>(this message was lost)</div>';
1870 continue;
1871 }
baf37d01
DO
1872 if (isset ($record['a']))
1873 switch (count ($record['a']))
1874 {
1875 case 1:
1876 $msgtext = sprintf
1877 (
1878 $msginfo[$record['c']]['format'],
1879 $record['a'][0]
1880 );
1881 break;
1882 case 2:
1883 $msgtext = sprintf
1884 (
1885 $msginfo[$record['c']]['format'],
1886 $record['a'][0],
1887 $record['a'][1]
1888 );
1889 break;
1890 case 3:
1891 $msgtext = sprintf
1892 (
1893 $msginfo[$record['c']]['format'],
1894 $record['a'][0],
1895 $record['a'][1],
1896 $record['a'][2]
1897 );
1898 break;
1899 case 4:
1900 default:
1901 $msgtext = sprintf
1902 (
1903 $msginfo[$record['c']]['format'],
1904 $record['a'][0],
1905 $record['a'][1],
1906 $record['a'][2],
1907 $record['a'][3]
1908 );
1909 break;
1910 }
1911 else
1912 $msgtext = $msginfo[$record['c']]['format'];
1913 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1914 }
1915 break;
1916 default:
1917 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1918 break;
1919 }
1d4d254b 1920 clearMessages();
e673ee24
DO
1921}
1922
65e557dd
AA
1923// renders two tables: port link status and learned MAC list
1924function renderPortsInfo($object_id)
1925{
1926 global $nextorder;
1927 echo "<table width='100%'><tr>";
1928
1929 if (permitted (NULL, NULL, 'get_link_status'))
1930 {
1931 try
1932 {
1933 $linkStatus = gwRetrieveDeviceConfig ($object_id, 'getportstatus');
1934 }
1935 catch (RackTablesError $e) {}
1936 if (! empty ($linkStatus))
1937 {
1938 echo "<td valign='top' width='50%'>";
1939 startPortlet('Link status');
1940 echo "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>Port<th>Link status<th>Link info</tr>";
1941 $order = 'even';
1942 foreach ($linkStatus as $pn => $link)
1943 {
1944 echo "<tr class='row_$order'>";
1945 $order = $nextorder[$order];
1946 echo '<td>' . $pn;
1947 echo '<td>' . $link['status'];
1948 $info = '';
1949 if (isset ($link['speed']))
1950 $info .= $link['speed'];
1951 if (isset ($link['duplex']))
1952 {
1953 if (! empty ($info))
1954 $info .= ', ';
1955 $info .= $link['duplex'];
1956 }
1957 echo '<td>' . $info;
1958 echo '</tr>';
1959 }
1960 echo "</table></td>";
1961 finishPortlet();
1962 }
1963 }
1964
1965 try
1966 {
1967 $macList = sortPortList (gwRetrieveDeviceConfig ($object_id, 'getmaclist'));
1968 }
1969 catch (RackTablesError $e) {}
1970 if (! empty ($macList))
1971 {
1972 echo "<td valign='top' width='50%'>";
1973 $rendered_macs = '';
1974 $mac_count = 0;
1975 $rendered_macs .= "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>MAC<th>Vlan<th>Port</tr>";
1976 $order = 'even';
1977 foreach ($macList as $pn => $list)
1978 {
1979 $order = $nextorder[$order];
1980 foreach ($list as $item)
1981 {
1982 ++$mac_count;
1983 $rendered_macs .= "<tr class='row_$order'>";
1984 $rendered_macs .= '<td style="font-family: monospace">' . $item['mac'];
1985 $rendered_macs .= '<td>' . $item['vid'];
1986 $rendered_macs .= '<td>' . $pn;
1987 $rendered_macs .= '</tr>';
1988 }
1989 }
1990 $rendered_macs .= "</table></td>";
1991
1992 startPortlet("Learned MACs ($mac_count)");
1993 echo $rendered_macs;
1994 finishPortlet();
1995 }
1996
1997 echo "</td></tr></table>";
1998}
1999
e673ee24 2000/*
51c18782 2001The following conditions must be met:
e673ee24
DO
20021. We can mount onto free atoms only. This means: if any record for an atom
2003already exists in RackSpace, it can't be used for mounting.
20042. We can't unmount from 'W' atoms. Operator should review appropriate comments
2005and either delete them before unmounting or refuse to unmount the object.
2006*/
7e1db771 2007function renderRackSpaceForObject ($object_id)
e673ee24 2008{
e673ee24
DO
2009 // Always process occupied racks plus racks chosen by user. First get racks with
2010 // already allocated rackspace...
51c18782 2011 $workingRacksData = getResidentRacksData ($object_id);
e673ee24 2012 // ...and then add those chosen by user (if any).
2135fd83 2013 if (isset($_REQUEST['rackmulti']))
e673ee24 2014 foreach ($_REQUEST['rackmulti'] as $cand_id)
e673ee24
DO
2015 if (!isset ($workingRacksData[$cand_id]))
2016 {
0cc24e9a 2017 $rackData = spotEntity ('rack', $cand_id);
61a1d996 2018 amplifyCell ($rackData);
e673ee24
DO
2019 $workingRacksData[$cand_id] = $rackData;
2020 }
51690ad4 2021
e673ee24
DO
2022 // Main layout starts.
2023 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
2024
2025 // Left portlet with rack list.
2026 echo "<td class=pcleft height='1%'>";
2027 startPortlet ('Racks');
a8efc03e 2028 $allRacksData = listCells ('rack');
4b8d413e 2029 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
61a1d996 2030 foreach ($allRacksData as $rack)
51c18782
DO
2031 if (!array_key_exists ($rack['id'], $workingRacksData))
2032 {
2033 amplifyCell ($rack);
2034 $workingRacksData[$rack['id']] = $rack;
2035 }
2036 foreach (array_keys ($workingRacksData) as $rackId)
2037 applyObjectMountMask ($workingRacksData[$rackId], $object_id);
2038 printOpFormIntro ('updateObjectAllocation');
4b8d413e 2039 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
51c18782 2040 echo "<br><br>";
e673ee24
DO
2041 finishPortlet();
2042 echo "</td>";
2043
2044 // Middle portlet with comment and submit.
2045 echo "<td class=pcleft>";
2046 startPortlet ('Comment');
2047 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
2048 echo "<input type=submit value='Save' name=got_atoms>\n";
51c18782 2049 echo "<br><br>";
e673ee24
DO
2050 finishPortlet();
2051 echo "</td>";
2052
2053 // Right portlet with rendered racks. If this form submit is not final, we have to
2054 // reflect the former state of the grid in current form.
2055 echo "<td class=pcright rowspan=2 height='1%'>";
2056 startPortlet ('Working copy');
65e557dd 2057 addJS ('js/racktables.js');
e673ee24
DO
2058 echo '<table border=0 cellspacing=10 align=center><tr>';
2059 foreach ($workingRacksData as $rack_id => $rackData)
2060 {
2061 // Order is important here: only original allocation is highlighted.
2062 highlightObject ($rackData, $object_id);
2063 markupAtomGrid ($rackData, 'T');
2064 // If we have a form processed, discard user input and show new database
2065 // contents.
51c18782 2066 if (isset ($_REQUEST['rackmulti'][0])) // is an update
e673ee24
DO
2067 mergeGridFormToRack ($rackData);
2068 echo "<td valign=top>";
2069 echo "<center>\n<h2>${rackData['name']}</h2>\n";
2070 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
57c69e9c 2071 echo "<tr><th width='10%'>&nbsp;</th>";
64259015
DO
2072 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>";
2073 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>";
2074 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";
e673ee24 2075 renderAtomGrid ($rackData);
57c69e9c 2076 echo "<tr><th width='10%'>&nbsp;</th>";
64259015
DO
2077 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>";
2078 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>";
2079 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";
e673ee24
DO
2080 echo "</table></center>\n";
2081 echo '</td>';
2082 }
2083 echo "</tr></table>";
2084 finishPortlet();
2085 echo "</td>\n";
2086
2087 echo "</form>\n";
2088 echo "</tr></table>\n";
2089}
2090
2091function renderMolecule ($mdata, $object_id)
2092{
2093 // sort data out
2094 $rackpack = array();
2095 global $loclist;
64b95774 2096 foreach ($mdata as $rua)
e673ee24
DO
2097 {
2098 $rack_id = $rua['rack_id'];
2099 $unit_no = $rua['unit_no'];
2100 $atom = $rua['atom'];
2101 if (!isset ($rackpack[$rack_id]))
2102 {
61a1d996
DO
2103 $rackData = spotEntity ('rack', $rack_id);
2104 amplifyCell ($rackData);
e673ee24
DO
2105 for ($i = $rackData['height']; $i > 0; $i--)
2106 for ($locidx = 0; $locidx < 3; $locidx++)
2107 $rackData[$i][$locidx]['state'] = 'F';
2108 $rackpack[$rack_id] = $rackData;
2109 }
2110 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
2111 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
2112 }
2113 // now we have some racks to render
65e557dd 2114 addAtomCSS();
64b95774 2115 foreach ($rackpack as $rackData)
e673ee24
DO
2116 {
2117 markAllSpans ($rackData);
2118 echo "<table class=molecule cellspacing=0>\n";
2119 echo "<caption>${rackData['name']}</caption>\n";
2120 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
2121 for ($i = $rackData['height']; $i > 0; $i--)
2122 {
2123 echo "<tr><th>$i</th>";
2124 for ($locidx = 0; $locidx < 3; $locidx++)
2125 {
2126 $state = $rackData[$i][$locidx]['state'];
65e557dd 2127 echo "<td class='atom state_${state}'>&nbsp;</td>\n";
e673ee24
DO
2128 }
2129 echo "</tr>\n";
2130 }
2131 echo "</table>\n";
2132 }
2133}
2134
23cdc7e9 2135function renderDepot ()
e673ee24 2136{
23cdc7e9 2137 global $pageno, $nextorder;
23cdc7e9
DO
2138 $cellfilter = getCellFilter();
2139 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
2140
2141 echo "<table border=0 class=objectview>\n";
2142 echo "<tr><td class=pcleft>";
2143
1ebbf889 2144 if (! renderEmptyResults ($cellfilter, 'objects', count($objects)))
e673ee24 2145 {
4899096d 2146 if (count($objects) > 0)
1ebbf889 2147 {
4899096d
AD
2148 startPortlet ('Objects (' . count ($objects) . ')');
2149 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2150 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Row/Rack</th></tr>';
2151 $order = 'odd';
2152 foreach ($objects as $obj)
2153 {
2154 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
2155 $secondclass = 'tdleft port_highlight';
2156 else
2157 $secondclass = 'tdleft';
2158 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>";
2159 if (count ($obj['etags']))
2160 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
2161 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
2162 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
2163 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
2164 if ($obj['rack_id'])
2165 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>";
2166 else
2167 echo "<td class='${secondclass}'>Unmounted</td>";
2168 echo '</tr>';
2169 $order = $nextorder[$order];
2170 }
2171 echo '</table>';
2172 finishPortlet();
1ebbf889 2173 }
4899096d
AD
2174 else
2175 echo '<h2>No objects exist</h2>';
e673ee24 2176 }
23cdc7e9
DO
2177
2178 echo "</td><td class=pcright width='25%'>";
2179
95857b5c 2180 renderCellFilterPortlet ($cellfilter, 'object', $objects);
23cdc7e9 2181 echo "</td></tr></table>\n";
e673ee24
DO
2182}
2183
1ebbf889
AA
2184// This function returns TRUE if the result set is too big to be rendered, and no filter is set.
2185// In this case it renders the describing message instead.
2186function renderEmptyResults($cellfilter, $entities_name, $count = NULL)
2187{
2188 if (!$cellfilter['is_empty'])
2189 return FALSE;
2190 if (isset ($_REQUEST['show_all_objects']))
2191 return FALSE;
2192 $max = intval(getConfigVar('MAX_UNFILTERED_ENTITIES'));
2193 if (0 == $max || $count <= $max)
2194 return FALSE;
2195
2196 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
2197 $href_show_all .= htmlspecialchars('&show_all_objects=1');
2198 $suffix = isset ($count) ? " ($count)" : '';
2199 echo <<<END
2200<p>Please set a filter to display the corresponging $entities_name.
2201<br><a href="$href_show_all">Show all $entities_name$suffix</a>
2202END;
2203 return TRUE;
2204}
2205
e673ee24
DO
2206// History viewer for history-enabled simple dictionaries.
2207function renderHistory ($object_type, $object_id)
2208{
2209 switch ($object_type)
2210 {
2211 case 'row':
a5c589d2 2212 $query = "select ctime, user_name, name, comment from RackRowHistory where id = ? order by ctime";
aa9a0fb4
DO
2213 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>rack row comment</th></tr>';
2214 $extra = 3;
e673ee24
DO
2215 break;
2216 case 'rack':
2217 $query =
aa9a0fb4 2218 "select ctime, user_name, rh.name, rr.name as name, rh.height, rh.comment " .
51690ad4 2219 "from RackHistory as rh left join RackRow as rr on rh.row_id = rr.id " .
a5c589d2 2220 "where rh.id = ? order by ctime";
aa9a0fb4
DO
2221 $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>';
2222 $extra = 5;
e673ee24
DO
2223 break;
2224 case 'object':
2225 $query =
aa9a0fb4 2226 "select ctime, user_name, RackObjectHistory.name as name, label, barcode, asset_no, has_problems, dict_value, comment " .
00f6f1e4 2227 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key join Chapter on Dictionary.chapter_id = Chapter.id " .
a5c589d2 2228 "where Chapter.name = 'RackObjectType' and RackObjectHistory.id=? order by ctime";
aa9a0fb4
DO
2229 $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>';
2230 $extra = 8;
e673ee24
DO
2231 break;
2232 default:
3a089a44 2233 throw new InvalidArgException ('object_type', $object_type);
e673ee24 2234 }
a5c589d2 2235 $result = usePreparedSelectBlade ($query, array ($object_id));
e673ee24
DO
2236 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2237 $order = 'odd';
2238 global $nextorder;
2239 echo $header;
2240 while ($row = $result->fetch (PDO::FETCH_NUM))
2241 {
2242 echo "<tr class=row_${order}><td>${row[0]}</td>";
2243 for ($i = 1; $i <= $extra; $i++)
2244 echo "<td>" . $row[$i] . "</td>";
2245 echo "</tr>\n";
2246 $order = $nextorder[$order];
2247 }
2248 echo "</table><br>\n";
2249}
2250
2251function renderRackspaceHistory ()
2252{
4fbb5a00 2253 global $nextorder, $pageno, $tabno;
e673ee24
DO
2254 $order = 'odd';
2255 $history = getRackspaceHistory();
2256 // Show the last operation by default.
2257 if (isset ($_REQUEST['op_id']))
2258 $op_id = $_REQUEST['op_id'];
2259 elseif (isset ($history[0]['mo_id']))
2260 $op_id = $history[0]['mo_id'];
2261 else $op_id = NULL;
2262
2263 $omid = NULL;
2264 $nmid = NULL;
2265 $object_id = 1;
2266 if ($op_id)
2267 list ($omid, $nmid) = getOperationMolecules ($op_id);
2268
2269 // Main layout starts.
2270 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2271
2272 // Left top portlet with old allocation.
2273 echo "<tr><td class=pcleft>";
2274 startPortlet ('Old allocation');
2275 if ($omid)
2276 {
2277 $oldMolecule = getMolecule ($omid);
2278 renderMolecule ($oldMolecule, $object_id);
2279 }
2280 else
2281 echo "nothing";
2282 finishPortlet();
2283
2284 echo '</td><td class=pcright>';
2285
2286 // Right top portlet with new allocation
2287 startPortlet ('New allocation');
2288 if ($nmid)
2289 {
2290 $newMolecule = getMolecule ($nmid);
2291 renderMolecule ($newMolecule, $object_id);
2292 }
2293 else
2294 echo "nothing";
2295 finishPortlet();
737a3f72 2296
e673ee24 2297 echo '</td></tr><tr><td colspan=2>';
737a3f72 2298
e673ee24
DO
2299 // Bottom portlet with list
2300
2301 startPortlet ('Rackspace allocation history');
2302 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
7fa7047a 2303 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
e673ee24
DO
2304 foreach ($history as $row)
2305 {
2306 if ($row['mo_id'] == $op_id)
2307 $class = 'hl';
2308 else
2309 $class = "row_${order}";
4fbb5a00 2310 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
7fa7047a
DO
2311 echo "<td>${row['user_name']}</td><td>";
2312 renderCell (spotEntity ('object', $row['ro_id']));
9c6222ef 2313 echo '</td><td>' . niftyString ($row['comment'], 0) . '</td></tr>';
e673ee24
DO
2314 $order = $nextorder[$order];
2315 }
2316 echo "</table>\n";
2317 finishPortlet();
737a3f72 2318
e673ee24 2319 echo '</td></tr></table>';
e673ee24
DO
2320}
2321
1f54e1ba 2322function renderIPv4SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
d65353ad
DO
2323{
2324 $self = __FUNCTION__;
ca4eb604
DO
2325 static $vdomlist = NULL;
2326 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
e829e76b 2327 $vdomlist = getVLANDomainOptions();
00276508
AA
2328
2329 // scroll page to the highlighted item
2330 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 2331 addAutoScrollScript ("net-$target");
00276508 2332
d65353ad
DO
2333 foreach ($tree as $item)
2334 {
64347dcf 2335 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
64347dcf 2336 loadIPv4AddrList ($item); // necessary to compute router list and address counter
64347dcf
DO
2337 else
2338 {
2339 $item['addrlist'] = array();
2340 $item['addrc'] = 0;
2341 }
b1e39212
DO
2342 $used = $item['addrc'];
2343 $maxdirect = $item['addrt'];
2344 $maxtotal = binInvMaskFromDec ($item['mask']) + 1;
0137d53c
DO
2345 if (isset ($item['id']))
2346 {
1f54e1ba 2347 $decor = array ('indent' => $level);
fec0c8da 2348 if ($item['symbol'] == 'node-collapsed')
00276508 2349 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
fec0c8da 2350 elseif ($item['symbol'] == 'node-expanded')
00276508 2351 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}" : '');
0137d53c 2352 echo "<tr valign=top>";
21ee3351
AA
2353 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
2354 $decor['tdclass'] .= ' port_highlight';
2355 printIPNetInfoTDs ($item, $decor);
0137d53c 2356 echo "<td class=tdcenter>";
64347dcf
DO
2357 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2358 {
b1e39212
DO
2359 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2360 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small>';
64347dcf
DO
2361 }
2362 else
b1e39212 2363 echo "<small>${maxdirect}</small>";
64347dcf 2364 echo "</td>";
ca4eb604
DO
2365 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2366 {
a5f9d1ca
DO
2367 echo '<td class=tdleft>';
2368 if (count ($item['8021q']))
ca4eb604 2369 {
a5f9d1ca
DO
2370 echo '<ul>';
2371 foreach ($item['8021q'] as $binding)
2372 {
2373 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
e829e76b
DO
2374 // FIXME: would formatVLANName() do this?
2375 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
a5f9d1ca
DO
2376 }
2377 echo '</ul>';
ca4eb604
DO
2378 }
2379 echo '</td>';
2380 }
0137d53c 2381 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
4a47d34b 2382 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
0137d53c 2383 echo "</tr>";
fec0c8da 2384 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
1f54e1ba 2385 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
0137d53c
DO
2386 }
2387 else
2388 {
0137d53c 2389 echo "<tr valign=top>";
21ee3351 2390 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
0137d53c 2391 echo "<td class=tdcenter>";
64347dcf
DO
2392 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2393 {
b1e39212
DO
2394 renderProgressBar ($used/$maxtotal, 'sparenetwork');
2395 echo "<br><small>${used}/${maxtotal}</small>";
64347dcf
DO
2396 }
2397 else
b1e39212 2398 echo "<small>${maxtotal}</small>";
ee3eac34
DO
2399 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2400 echo '</td><td>&nbsp;</td>';
64347dcf 2401 echo "</td><td>&nbsp;</td></tr>";
0137d53c 2402 }
d65353ad
DO
2403 }
2404}
2405
21ee3351
AA
2406function renderIPv6SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
2407{
2408 $self = __FUNCTION__;
2409 static $vdomlist = NULL;
2410 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2411 $vdomlist = getVLANDomainOptions();
00276508
AA
2412
2413 // scroll page to the highlighted item
2414 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 2415 addAutoScrollScript ("net-$target");
00276508 2416
21ee3351
AA
2417 foreach ($tree as $item)
2418 {
2419 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2420 loadIPv6AddrList ($item); // necessary to compute router list and address counter
2421 else
2422 {
2423 $item['addrlist'] = array();
2424 $item['addrc'] = 0;
2425 }
2426 if (isset ($item['id']))
2427 {
2428 $decor = array ('indent' => $level);
2429 if ($item['symbol'] == 'node-collapsed')
00276508 2430 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
21ee3351
AA
2431 elseif ($item['symbol'] == 'node-expanded')
2432 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#net6id${item['parent_id']}" : '');
2433 echo "<tr valign=top>";
2434 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
2435 $decor['tdclass'] .= ' port_highlight';
2436 printIPNetInfoTDs ($item, $decor);
2437 echo "<td class=tdcenter>";
21ee3351
AA
2438 // show net usage
2439 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2440 echo "</td>";
2441 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2442 {
2443 echo '<td class=tdleft>';
2444 if (count ($item['8021q']))
2445 {
2446 echo '<ul>';
2447 foreach ($item['8021q'] as $binding)
2448 {
2449 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
2450 // FIXME: would formatVLANName() do this?
2451 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
2452 }
2453 echo '</ul>';
2454 }
2455 echo '</td>';
2456 }
2457 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2458 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
2459 echo "</tr>";
2460 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2461 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
2462 }
2463 /* do not display spare networks
2464 else
2465 { // display spare networks
2466 echo "<tr valign=top>";
2467 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
2468 echo "<td class=tdcenter>";
2469 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2470 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2471 echo '</td><td>&nbsp;</td>';
2472 echo "</td><td>&nbsp;</td></tr>";
2473 }*/
2474 }
2475}
2476
2477// if $used is NULL, returns only human-formatted mask.
2478// Otherwise returns "$used in/of " . human-formatted-mask
2479function formatIPv6NetUsage ($used, $mask)
2480{
2481 $prefixes = array
2482 (
2483 0 => '',
2484 3 => 'k',
2485 6 => 'M',
2486 9 => 'G',
2487 12 => 'T',
2488 15 => 'P',
2489 18 => 'E',
2490 21 => 'Z',
2491 24 => 'Y',
2492 );
2493
2494 if ($mask <= 64)
2495 {
2496 $what = '/64 net';
2497 $preposition = 'in';
2498 $mask += 64;
2499 }
2500 else
2501 {
2502 $what = 'IP';
2503 $preposition = 'of';
2504 }
2505 $what .= (0 == $mask % 64 ? '' : 's');
2506 $addrc = isset ($used) ? "$used $preposition " : '';
2507
2508 $dec_order = intval ((128 - $mask) / 10) * 3;
2509 $mult = isset ($prefixes[$dec_order]) ? $prefixes[$dec_order] : '??';
2510
2511 $cnt = 1 << ((128 - $mask) % 10);
2512 if ($cnt == 1 && $mult == '')
2513 $cnt = 'single';
2514
2515 return "<small>${addrc}${cnt}${mult} ${what}</small>";
2516}
2517
04d619d0 2518function renderIPv4Space ()
e673ee24 2519{
4fbb5a00 2520 global $pageno, $tabno;
31c941ec 2521 $cellfilter = getCellFilter();
1f54e1ba
DO
2522 $netlist = listCells ('ipv4net');
2523 $allcount = count ($netlist);
2524 $netlist = filterCellList ($netlist, $cellfilter['expression']);
573214e0 2525 array_walk ($netlist, 'amplifyCell');
4fbb5a00 2526
94a40058 2527 $netcount = count ($netlist);
5388794d
DO
2528 // expand request can take either natural values or "ALL". Zero means no expanding.
2529 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2530 $tree = prepareIPv4Tree ($netlist, $eid);
3630d1fb
DO
2531
2532 echo "<table border=0 class=objectview>\n";
2533 echo "<tr><td class=pcleft>";
1ebbf889
AA
2534 if (! renderEmptyResults($cellfilter, 'IPv4 nets', count($tree)))
2535 {
2536 startPortlet ("networks (${netcount})");
2537 echo '<h4>';
2538 if ($eid === 0)
2539 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2540 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2541 $cellfilter['urlextra'] . "'>expand all</a>)";
2542 elseif ($eid === 'ALL')
2543 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2544 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2545 else
2546 {
2547 $netinfo = spotEntity ('ipv4net', $eid);
2548 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2549 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2550 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2551 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2552 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2553 }
2554 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2555 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2556 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2557 echo '<th>VLAN</th>';
2558 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2559 echo "<th>routed by</th>";
2560 echo "</tr>\n";
2561 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2562 renderIPv4SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2563 echo "</table>\n";
2564 finishPortlet();
5388794d 2565 }
1ebbf889 2566
74ccacff 2567 echo '</td><td class=pcright>';
95857b5c 2568 renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
74ccacff 2569 echo "</td></tr></table>\n";
f973f491 2570}
a7fe7729 2571
21ee3351
AA
2572function renderIPv6Space ()
2573{
2574 global $pageno, $tabno;
2575 $cellfilter = getCellFilter();
2576 $netlist = listCells ('ipv6net');
2577 $allcount = count ($netlist);
2578 $netlist = filterCellList ($netlist, $cellfilter['expression']);
2579 array_walk ($netlist, 'amplifyCell');
2580
2581 $netcount = count ($netlist);
2582 // expand request can take either natural values or "ALL". Zero means no expanding.
2583 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2584 $tree = prepareIPv6Tree ($netlist, $eid);
2585
2586 echo "<table border=0 class=objectview>\n";
2587 echo "<tr><td class=pcleft>";
2588 if (! renderEmptyResults($cellfilter, 'IPv6 nets', count($tree)))
2589 {
2590 startPortlet ("networks (${netcount})");
2591 echo '<h4>';
2592 if ($eid === 0)
2593 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2594 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2595 $cellfilter['urlextra'] . "'>expand all</a>)";
2596 elseif ($eid === 'ALL')
2597 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2598 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2599 else
2600 {
2601 $netinfo = spotEntity ('ipv6net', $eid);
2602 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2603 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2604 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2605 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2606 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2607 }
2608 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2609 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2610 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2611 echo '<th>VLAN</th>';
2612 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2613 echo "<th>routed by</th>";
2614 echo "</tr>\n";
2615 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2616 renderIPv6SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2617 echo "</table>\n";
2618 finishPortlet();
2619 }
2620
2621 echo '</td><td class=pcright>';
2622 renderCellFilterPortlet ($cellfilter, 'ipv6net', $netlist);
2623 echo "</td></tr></table>\n";
2624}
2625
1f54e1ba
DO
2626function renderSLBDefConfig()
2627{
2628 $defaults = getSLBDefaults ();
2629 startPortlet ('SLB default configs');
2630 echo '<table cellspacing=0 cellpadding=5 align=center>';
2631 printOpFormIntro ('save');
2632 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>';
2633 echo '<td rowspan=2>';
2634 printImageHREF ('SAVE', 'Save changes', TRUE);
2635 echo '</td></tr>';
2636 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>';
2637 echo '</form></table>';
2638 finishPortlet();
2639}
2640
f973f491
DO
2641function renderIPv4SLB ()
2642{
4fbb5a00 2643 global $page, $nextorder;
a7fe7729 2644
6fec9f39 2645 startPortlet ('SLB configuration');
b3c50e6c 2646 echo "<table border=0 width='100%'><tr>";
ee437dab 2647 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
4fbb5a00 2648 echo "<td><h3><a href='".makeHref(array('page'=>$pno))."'>" . $page[$pno]['title'] . "</a></h3></td>";
b3c50e6c
DO
2649 echo '</tr></table>';
2650 finishPortlet();
2651
c3bdc503 2652 $summary = getSLBSummary();
6fec9f39 2653 startPortlet ('SLB tactical overview');
4cadac8f
DO
2654 // A single id-keyed array isn't used here to preserve existing
2655 // order of LBs returned by getSLBSummary()
c3bdc503
DO
2656 $lblist = array();
2657 $lbdname = array();
4cadac8f 2658 foreach ($summary as $vipdata)
da04825a 2659 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
c3bdc503
DO
2660 if (!in_array ($lb_object_id, $lblist))
2661 {
fb6e2f57 2662 $oi = spotEntity ('object', $lb_object_id);
c3bdc503
DO
2663 $lbdname[$lb_object_id] = $oi['dname'];
2664 $lblist[] = $lb_object_id;
2665 }
2666 if (!count ($summary))
2667 echo 'none configured';
2668 else
2669 {
80e85ea1 2670 $order = 'odd';
c3bdc503 2671 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
b1a970c7 2672 echo "<tr valign=top><td>&nbsp;</td>";
c3bdc503 2673 foreach ($lblist as $lb_object_id)
b1a970c7 2674 {
4fbb5a00 2675 #echo "<th><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$lb_object_id))."'>" . $lbdname[$lb_object_id] . "</a></th>";
b1a970c7
DO
2676 echo '<td>';
2677 renderLBCell ($lb_object_id);
2678 echo '</td>';
2679 }
c3bdc503 2680 echo "</tr>\n";
4cadac8f
DO
2681 foreach ($summary as $vsid => $vsdata)
2682 {
b1a970c7 2683 echo "<tr class=row_${order}><td class=tdleft>";
6df2025d 2684 renderCell (spotEntity ('ipv4vs', $vsid));
6fec9f39 2685 echo "</td>";
4cadac8f 2686 foreach ($lblist as $lb_object_id)
da04825a 2687 {
60fbcece 2688 echo '<td class=tdleft>';
2b4eee17 2689 if (!isset ($vsdata['lblist'][$lb_object_id]))
da04825a
DO
2690 echo '&nbsp;';
2691 else
6fec9f39
DO
2692 {
2693 echo $vsdata['lblist'][$lb_object_id]['size'];
4fbb5a00 2694// echo " (<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$vsdata['lblist'][$lb_object_id]['id'])). "'>";
79a9edb4 2695// echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
6fec9f39 2696 }
da04825a
DO
2697 echo '</td>';
2698 }
2699 echo "</tr>\n";
80e85ea1 2700 $order = $nextorder[$order];
4cadac8f 2701 }
c3bdc503
DO
2702 echo "</table>\n";
2703 }
a7fe7729 2704 finishPortlet ();
e673ee24
DO
2705}
2706
04d619d0 2707function renderIPv4SpaceEditor ()
e673ee24 2708{
a262e150 2709 // IPv4 validator
65e557dd
AA
2710 addJs ('js/live_validation.js');
2711 $regexp = addslashes ('^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$');
2712 addJs (<<<END
2713$(document).ready(function () {
2714 document.add_new_range.range.setAttribute('match', '$regexp');
2715 Validate.init();
2716});
2717END
2718 , TRUE);
a262e150 2719
f857f71f
DO
2720 function printNewItemTR ()
2721 {
2722 startPortlet ('Add new');
2723 echo '<table border=0 cellpadding=10 align=center>';
2724 // This form requires a name, so JavaScript validator can find it.
2725 // No printOpFormIntro() hence
2726 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2727 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2728 // tags column
2729 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2730 renderNewEntityTags ('ipv4net');
2731 echo '</td>';
2732 // inputs column
2733 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2734 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>";
2735 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2736 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2737 echo "<tr><td colspan=2>";
2738 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2739 echo '</td></tr>';
2740 echo "</form></table><br><br>\n";
2741 finishPortlet();
2742 }
2a201216 2743
f857f71f
DO
2744 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2745 printNewItemTR();
ab1283b7 2746 if (count ($addrspaceList = listCells ('ipv4net')))
e673ee24 2747 {
e43a2de4 2748 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
04d619d0 2749 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
b1e39212 2750 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
d3dcdfbb
DO
2751 array_walk ($addrspaceList, 'amplifyCell');
2752 $tree = prepareIPv4Tree ($addrspaceList, 'ALL');
2753 // this is only called for having "trace" set
2754 treeFromList ($addrspaceList);
0c16ef0c 2755 foreach ($addrspaceList as $netinfo)
e673ee24 2756 {
b1e39212
DO
2757 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2758 // now we have all subnets listed in netinfo
2759 loadIPv4AddrList ($netinfo);
2760 $used = $netinfo['addrc'];
2761 $maxdirect = $netinfo['addrt'];
2762 $maxtotal = binInvMaskFromDec ($netinfo['mask']) + 1;
e43a2de4 2763 echo "<tr valign=top><td>";
21ee3351
AA
2764 if (count ($netinfo['addrlist']) && getConfigVar ('IPV4_JAYWALK') == 'no')
2765 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2766 else
e43a2de4
DO
2767 {
2768 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2769 printImageHREF ('destroy', 'Delete this prefix');
2770 echo "</a>";
2771 }
21ee3351
AA
2772 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv4net', 'id' => $netinfo['id'])) . '">';
2773 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
2774 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2775 if (count ($netinfo['etags']))
2776 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2777 echo '</td><td>';
2778 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2779 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small></td>';
2780 echo '</tr>';
2781 }
2782 echo "</table>";
2783 finishPortlet();
2784 }
2785 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2786 printNewItemTR();
2787}
e43a2de4 2788
21ee3351
AA
2789function renderIPv6SpaceEditor ()
2790{
2791 // IPv6 validator
65e557dd
AA
2792 addJs ('js/live_validation.js');
2793 $regexp = addslashes ('^[a-fA-F0-9:]*:[a-fA-F0-9:\.]*/\d{1,3}$');
2794 addJs (<<<END
2795$(document).ready(function () {
2796 document.add_new_range.range.setAttribute('match', '$regexp');
2797 Validate.init();
2798});
2799END
2800 , TRUE);
21ee3351
AA
2801
2802 function printNewItemTR ()
2803 {
2804 startPortlet ('Add new');
2805 echo '<table border=0 cellpadding=10 align=center>';
2806 // This form requires a name, so JavaScript validator can find it.
2807 // No printOpFormIntro() hence
2808 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2809 echo "<input type=hidden name=op value=addIPv6Prefix>\n";
2810 // tags column
2811 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2812 renderNewEntityTags ('ipv4net');
2813 echo '</td>';
2814 // inputs column
2815 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2816 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=36 class='live-validate' tabindex=1 value='${prefix_value}'></td>";
2817 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2818 echo "<tr><td colspan=2>";
2819 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2820 echo '</td></tr>';
2821 echo "</form></table><br><br>\n";
2822 finishPortlet();
2823 }
2824
2825 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2826 printNewItemTR();
2827 if (count ($addrspaceList = listCells ('ipv6net')))
2828 {
2829 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2830 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2831 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
2832 array_walk ($addrspaceList, 'amplifyCell');
2833 $tree = prepareIPv6Tree ($addrspaceList, 'ALL');
2834 // this is only called for having "trace" set
2835 treeFromList ($addrspaceList);
2836 foreach ($addrspaceList as $netinfo)
2837 {
2838 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2839 // now we have all subnets listed in netinfo
2840 loadIPv6AddrList ($netinfo);
2841 echo "<tr valign=top><td>";
2842 if (count ($netinfo['addrlist']) && getConfigVar ('IPV4_JAYWALK') == 'no')
2843 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2844 else
2845 {
2846 echo "<a href='".makeHrefProcess (array ('op' => 'delIPv6Prefix', 'id' => $netinfo['id'])) . "'>";
2847 printImageHREF ('destroy', 'Delete this prefix');
2848 echo "</a>";
e43a2de4 2849 }
21ee3351 2850 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv6net', 'id' => $netinfo['id'])) . '">';
ab1283b7 2851 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
1f54e1ba
DO
2852 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2853 if (count ($netinfo['etags']))
2854 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2855 echo '</td><td>';
21ee3351 2856 echo formatIPv6NetUsage ($netinfo['addrc'], $netinfo['mask']);
b1e39212 2857 echo '</tr>';
e673ee24 2858 }
04d619d0
DO
2859 echo "</table>";
2860 finishPortlet();
e673ee24 2861 }
f857f71f
DO
2862 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2863 printNewItemTR();
e673ee24
DO
2864}
2865
beb9e88a 2866function renderIPv4Network ($id)
e673ee24 2867{
c8824ff4 2868 global $pageno, $tabno, $aac2, $netmaskbylen, $wildcardbylen;
e673ee24 2869
d724d290 2870 $range = spotEntity ('ipv4net', $id);
a5f9d1ca 2871 amplifyCell ($range);
b6b87070 2872 loadIPv4AddrList ($range);
2034d968 2873 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
99ab184f
DO
2874 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2875 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2034d968
DO
2876
2877 echo "<tr><td class=pcleft width='50%'>";
2878 startPortlet ('summary');
2879 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2880 $used = count ($range['addrlist']);
2881 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
04d619d0
DO
2882
2883 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2034d968
DO
2884 renderProgressBar ($used/$total);
2885 echo "&nbsp;${used}/${total}</td></tr>\n";
04d619d0 2886
001e61fa
DO
2887 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2888 {
3444ecf2
DO
2889 // Build a backtrace from all parent networks.
2890 $clen = $range['mask'];
2891 $backtrace = array();
2892 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2893 {
d724d290 2894 $upperinfo = spotEntity ('ipv4net', $upperid);
3444ecf2 2895 $clen = $upperinfo['mask'];
d724d290 2896 $backtrace[] = $upperinfo;
3444ecf2
DO
2897 }
2898 $arrows = count ($backtrace);
d724d290 2899 foreach (array_reverse ($backtrace) as $ainfo)
001e61fa 2900 {
3444ecf2
DO
2901 echo "<tr><th width='50%' class=tdright>";
2902 for ($i = 0; $i < $arrows; $i++)
2903 echo '&uarr;';
2904 $arrows--;
5d3dcb8d 2905 echo "</th><td class=tdleft>";
6df2025d 2906 renderCell ($ainfo);
5d3dcb8d 2907 echo "</td></tr>";
001e61fa 2908 }
3444ecf2 2909 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
5d3dcb8d 2910 echo "<td class=tdleft>";
6df2025d 2911 renderCell ($range);
5d3dcb8d 2912 echo "</td></tr>";
001e61fa
DO
2913 // FIXME: get and display nested networks
2914 // $theitem = pickLeaf ($ipv4tree, $id);
2915 }
2916
545478d0
DO
2917 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2918 echo $netmaskbylen[$range['mask']];
2919 echo "</td></tr>\n";
04d619d0 2920
c607ab55
DO
2921 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2922 printf ('0x%08X', binMaskFromDec ($range['mask']));
2923 echo "</td></tr>\n";
2924
545478d0
DO
2925 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2926 echo $wildcardbylen[$range['mask']];
2927 echo "</td></tr>\n";
04d619d0 2928
a5f9d1ca 2929 foreach ($range['8021q'] as $item)
cbf78395 2930 {
a5f9d1ca 2931 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
cbf78395 2932 echo '<tr><th width="50%" class=tdright>VLAN:</th><td class=tdleft><a href="';
a5f9d1ca 2933 echo makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">';
a72aa89f 2934 echo formatVLANName ($vlaninfo, 'markup long');
ce85f5c8 2935 echo '</a></td></tr>';
cbf78395 2936 }
3a4f4023 2937 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
04d619d0 2938 {
57dece2f 2939 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
f3d0cb20 2940 printRoutersTD ($routers);
57dece2f 2941 echo "</tr>\n";
04d619d0
DO
2942 }
2943
9b57f793 2944 printTagTRs ($range, makeHref(array('page'=>'ipv4space', 'tab'=>'default'))."&");
2034d968
DO
2945 echo "</table><br>\n";
2946 finishPortlet();
e1ae3fb4 2947
99ab184f
DO
2948 if (strlen ($range['comment']))
2949 {
2950 startPortlet ('Comment');
2951 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2952 finishPortlet ();
2953 }
2954
e1ae3fb4 2955 renderFilesPortlet ('ipv4net', $id);
2034d968 2956 echo "</td>\n";
e673ee24 2957
2034d968
DO
2958 echo "<td class=pcright>";
2959 startPortlet ('details');
e673ee24
DO
2960 $startip = $range['ip_bin'] & $range['mask_bin'];
2961 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2962 $realstartip = $startip;
2963 $realendip = $endip;
e673ee24 2964
00276508
AA
2965 if (isset ($_REQUEST['hl_ipv4_addr']))
2966 {
2967 $hl_ip = ip2long ($_REQUEST['hl_ipv4_addr']);
2968 $hl_dottedquad = ip_long2quad ($hl_ip);
65e557dd 2969 addAutoScrollScript ("ip-$hl_dottedquad"); // scroll page to highlighted ip
00276508
AA
2970 }
2971
79b57b18
AA
2972 // pager
2973 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2974 $address_count = $endip - $startip + 1;
2975 $page = 0;
2976 if ($address_count > $maxperpage && $maxperpage > 0)
2977 {
2978 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? intval (($hl_ip - $startip) / $maxperpage) : 0);
2979 if ($numpages = ceil ($address_count / $maxperpage))
2980 {
2981 echo "<center>";
2982 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2983 for ($i = 0; $i < $numpages; $i++)
2984 if ($i == $page)
2985 echo "<b>$i</b> ";
2986 else
2987 echo "<a href='".makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $id, 'pg' => $i)) . "'>$i</a> ";
2988 echo "</center>";
2989 }
2990 $startip = $startip + $page * $maxperpage;
2991 $endip = min ($startip + $maxperpage - 1, $endip);
2992 }
2993
beb9e88a 2994 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
e673ee24
DO
2995 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2996
b2035dca 2997 for ($ip = $startip; $ip <= $endip; $ip++) :
00276508
AA
2998 $dottedquad = ip_long2quad($ip);
2999 $secondstyle = 'tdleft' . (isset ($hl_ip) && $hl_ip == $ip ? ' port_highlight' : '');
b2035dca 3000 if (!isset ($range['addrlist'][$ip]))
e673ee24 3001 {
00276508
AA
3002 echo "<tr><td class=tdleft><a name='ip-$dottedquad' href='" . makeHref(array('page'=>'ipaddress', 'ip' => $dottedquad)) . "'>$dottedquad</a></td>";
3003 echo "<td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
b2035dca
DO
3004 continue;
3005 }
b2035dca 3006 $addr = $range['addrlist'][$ip];
2d318652 3007 echo "<tr class='${addr['class']}'>";
e673ee24 3008
00276508 3009 echo "<td class=tdleft><a name='ip-$dottedquad' href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
b2035dca
DO
3010 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
3011 $delim = '';
3012 $prologue = '';
3013 if ( $addr['reserved'] == 'yes')
3014 {
2d318652 3015 echo "<strong>RESERVED</strong> ";
b2035dca
DO
3016 $delim = '; ';
3017 }
2d318652 3018 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
b2035dca 3019 {
beb9e88a 3020 echo $delim . $aac2[$ref['type']];
4fbb5a00 3021 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'hl_ipv4_addr'=>$addr['ip']))."'>";
59a83bd8 3022 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
b2035dca
DO
3023 echo "${ref['object_name']}</a>";
3024 $delim = '; ';
3025 }
3026 if ($delim != '')
3027 {
6131056c 3028 $delim = '';
b2035dca
DO
3029 $prologue = '<br>';
3030 }
2d318652 3031 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
b2035dca
DO
3032 {
3033 echo $prologue;
602663f4 3034 $prologue = '';
4fbb5a00
DY
3035 echo "${delim}<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id']))."'>";
3036 echo "${ref['object_name']}</a>:<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$ref['vs_id']))."'>";
b2035dca
DO
3037 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
3038 $delim = '; ';
3039 }
3040 if ($delim != '')
3041 {
3042 $delim = '';
3043 $prologue = '<br>';
e673ee24 3044 }
2d318652 3045 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
b2035dca
DO
3046 {
3047 echo $prologue;
3048 $prologue = '';
4fbb5a00 3049 echo "${delim}&rarr;${ref['rsport']}@<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$ref['rspool_id']))."'>";
b2035dca
DO
3050 echo "${ref['rspool_name']}</a>";
3051 $delim = '; ';
3052 }
3053 echo "</td></tr>\n";
3054 endfor;
2727c7df 3055 // end of iteration
e673ee24
DO
3056
3057 echo "</table>";
2034d968
DO
3058 finishPortlet();
3059 echo "</td></tr></table>\n";
e673ee24
DO
3060}
3061
21ee3351
AA
3062// based on renderIPv4Network
3063function renderIPv6Network ($id)
3064{
3065 $range = spotEntity ('ipv6net', $id);
3066 amplifyCell ($range);
3067 loadIPv6AddrList ($range);
3068 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
3069 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
3070 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
3071
3072 echo "<tr><td class=pcleft width='50%'>";
3073 startPortlet ('summary');
3074 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
3075 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
3076 echo "&nbsp;" . formatIPv6NetUsage (count ($range['addrlist']), $range['mask']) . "</td></tr>\n";
3077
3078 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
3079 {
3080 // Build a backtrace from all parent networks.
3081 $backtrace = array();
3082 $current = $range;
3083 while ($current['parent_id'])
3084 {
3085 $current = spotEntity ('ipv6net', $current['parent_id']);
3086 $backtrace[] = $current;
3087 }
3088 $arrows = count ($backtrace);
3089 foreach (array_reverse ($backtrace) as $ainfo)
3090 {
3091 echo "<tr><th width='50%' class=tdright>";
3092 for ($i = 0; $i < $arrows; $i++)
3093 echo '&uarr;';
3094 $arrows--;
3095 echo "</th><td class=tdleft>";
3096 renderCell ($ainfo);
3097 echo "</td></tr>";
3098 }
3099 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
3100 echo "<td class=tdleft>";
3101 renderCell ($range);
3102 echo "</td></tr>";
3103 // FIXME: get and display nested networks
3104 }
3105
3106 foreach ($range['8021q'] as $item)
3107 {
3108 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
3109 echo '<tr><th width="50%" class=tdright>VLAN:</th><td class=tdleft><a href="';
3110 echo makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">';
3111 echo formatVLANName ($vlaninfo, 'markup long');
3112 echo '</a></td></tr>';
3113 }
3114 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
3115 {
3116 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
3117 printRoutersTD ($routers);
3118 echo "</tr>\n";
3119 }
3120
3121 printTagTRs ($range, makeHref (array ('page' => 'ipv6space', 'tab' => 'default')) . "&");
3122 echo "</table><br>\n";
3123 finishPortlet();
3124
3125 if (strlen ($range['comment']))
3126 {
3127 startPortlet ('Comment');
3128 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
3129 finishPortlet ();
3130 }
3131
3132 renderFilesPortlet ('ipv6net', $id);
3133 echo "</td>\n";
3134
3135 // render address list
3136 echo "<td class=pcright>";
3137 startPortlet ('details');
3138 renderIPv6NetworkAddresses ($range);
3139 finishPortlet();
3140 echo "</td></tr></table>\n";
3141}
3142
3143// Used solely by renderSeparator
3144function renderEmptyIPv6 ($ip, $hl_ip)
3145{
3146 $class = 'tdleft';
3147 if (isset ($hl_ip) && $ip == $hl_ip)
3148 $class .= ' port_highlight';
3149 $fmt = $ip->format();
00276508 3150 echo "<tr><td class=tdleft><a name='ip-$fmt' href='" . makeHref (array ('page' => 'ipv6address', 'ip' => $fmt)) . "'>" . $fmt;
21ee3351
AA
3151 echo "</a></td><td class='${class}'>&nbsp;</td><td class='${class}'>&nbsp;</td></tr>\n";
3152}
3153
3154// Renders empty table line to shrink empty IPv6 address ranges.
3155// If the range consists of single address, renders the address instead of empty line.
3156// Renders address $hl_ip inside the range.
3157// Used solely by renderIPv6NetworkAddresses
3158function renderSeparator ($first, $after, $hl_ip)
3159{
3160 $self = __FUNCTION__;
3161 if (strcmp ($first, $after) >= 0)
3162 return;
3163 if ($first->next() == $after)
3164 renderEmptyIPv6 ($first, $hl_ip);
3165 elseif (isset ($hl_ip) && strcmp ($hl_ip, $first) >= 0 && strcmp ($hl_ip, $after) < 0)
3166 { // $hl_ip is inside the range $first - ($after-1)
3167 $self ($first, $hl_ip, $hl_ip);
3168 renderEmptyIPv6 ($hl_ip, $hl_ip);
3169 $self ($hl_ip->next(), $after, $hl_ip);
3170 }
3171 else
3172 echo "<tr><td colspan=3 class=tdleft></td></tr>\n";
3173}
3174
3175// calculates page number which contains given $ip (used by renderIPv6NetworkAddresses)
3176function getPageNumOfIPv6 ($list, $ip, $maxperpage)
3177{
3178 if (intval ($maxperpage) <= 0 || count ($list) <= $maxperpage)
3179 return 0;
3180 $bin_ip = (string)$ip;
3181 $keys = array_keys ($list);
3182 for ($i = 1; $i <= count ($keys); $i++)
3183 if (strcmp ($keys[$i-1], $bin_ip) >= 0)
3184 return intval ($i / $maxperpage);
3185 return intval (count ($list) / $maxperpage);
3186}
3187
3188function renderIPv6NetworkAddresses ($netinfo)
3189{
3190 global $pageno, $tabno, $aac2;
3191 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
3192 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
3193
3194 $hl_ip = new IPv6Address;
3195 if (! isset ($_REQUEST['hl_ipv6_addr']) || ! $hl_ip->parse ($_REQUEST['hl_ipv6_addr']))
3196 $hl_ip = NULL;
00276508 3197 else
65e557dd 3198 addAutoScrollScript ('ip-' . $hl_ip->format());
21ee3351
AA
3199
3200 $prev_ip = $netinfo['ip_bin']; // really this is the next to previosly seen ip.
3201 $addresses = $netinfo['addrlist'];
3202 ksort ($addresses);
3203
3204 // pager
3205 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
3206 if (count ($addresses) > $maxperpage && $maxperpage > 0)
3207 {
3208 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? getPageNumOfIPv6 ($addresses, $hl_ip, $maxperpage) : 0);
3209 $numpages = ceil (count ($addresses) / $maxperpage);
3210 echo "<center><h3>$numpages pages:</h3>";
3211 for ($i=0; $i<$numpages; $i++)
3212 {
3213 if ($i == $page)
3214 echo "<b>$i</b> ";
3215 else
3216 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $i)) . "'>$i</a> ";
3217 }
3218 echo "</center>";
3219 }
3220
3221 $i = 0;
3222 $interruped = FALSE;
3223 foreach ($addresses as $bin_ip => $addr)
3224 {
3225 if (isset ($page))
3226 {
3227 ++$i;
3228 if ($i <= $maxperpage * $page)
3229 continue;
3230 elseif ($i > $maxperpage * ($page + 1))
3231 {
3232 $interruped = TRUE;
3233 break;
3234 }
3235 }
3236
3237 $ipv6 = new IPv6Address ($bin_ip);
3238 if ($ipv6 != $prev_ip)
3239 renderSeparator ($prev_ip, $ipv6, $hl_ip);
3240 $prev_ip = $ipv6->next();
3241
3242 $secondstyle = 'tdleft';
3243 if (isset ($hl_ip) && $hl_ip == $ipv6)
3244 $secondstyle .= ' port_highlight';
3245 echo "<tr class='${addr['class']}'>";
00276508 3246 echo "<td class=tdleft><a name='ip-${addr['ip']}' href='" . makeHref (array ('page' => 'ipv6address', 'ip' => $addr['ip'])) . "'>${addr['ip']}</a></td>";
21ee3351
AA
3247 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
3248 $delim = '';
3249 $prologue = '';
3250 if ( $addr['reserved'] == 'yes')
3251 {
3252 echo "<strong>RESERVED</strong> ";
3253 $delim = '; ';
3254 }
3255 foreach ($addr['allocs'] as $ref)
3256 {
3257 echo $delim . $aac2[$ref['type']];
3258 echo "<a href='" . makeHref (array ('page' => 'object', 'object_id' => $ref['object_id'], 'hl_ipv6_addr' => $addr['ip'])) . "'>";
3259 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
3260 echo "${ref['object_name']}</a>";
3261 $delim = '; ';
3262 }
3263 if ($delim != '')
3264 {
3265 $delim = '';
3266 $prologue = '<br>';
3267 }
3268 echo "</td></tr>\n";
3269 }
3270 if (! $interruped)
3271 renderSeparator ($prev_ip, $netinfo['ip_bin']->get_last_subnet_address ($netinfo['mask'])->next(), $hl_ip);
3272 if (isset ($page))
3273 { // bottom pager
3274 echo "<tr><td colspan=3>";
3275 if ($page > 0)
3276 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page - 1)) . "'><< prev</a> ";
3277 if ($page < $numpages - 1)
3278 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page + 1)) . "'>next >></a> ";
3279 echo "</td></tr>";
3280 }
3281 echo "</table>";
3282}
3283
3284function renderIPNetworkProperties ($id)
e673ee24 3285{
21ee3351
AA
3286 global $pageno;
3287 $netdata = spotEntity ($pageno, $id);
53ef3908 3288 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
e673ee24 3289 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 3290 printOpFormIntro ('editRange');
99ab184f
DO
3291 echo '<tr><td class=tdright><label for=nameinput>Name:</label></td>';
3292 echo "<td class=tdleft><input type=text name=name id=nameinput size=80 maxlength=255 value='";
3293 echo htmlspecialchars ($netdata['name'], ENT_QUOTES, 'UTF-8') . "'></tr>";
3294 echo '<tr><td class=tdright><label for=commentinput>Comment:</label></td>';
3295 echo "<td class=tdleft><textarea name=comment id=commentinput cols=80 rows=25>\n";
3296 echo htmlspecialchars ($netdata['comment'], ENT_QUOTES, 'UTF-8') . "</textarea></tr>";
53ef3908
DO
3297 echo "<tr><td colspan=2 class=tdcenter>";
3298 printImageHREF ('SAVE', 'Save changes', TRUE);
3299 echo "</td></form></tr></table>\n";
e673ee24
DO
3300}
3301
21ee3351 3302function renderIPAddress ($dottedquad)
e673ee24 3303{
46098972 3304 global $aat, $nextorder;
21ee3351 3305 $address = getIPAddress ($dottedquad);
68225375 3306 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
21ee3351 3307 echo "<tr><td colspan=2 align=center><h1>${address['ip']}</h1></td></tr>\n";
e673ee24 3308
68225375
DO
3309 echo "<tr><td class=pcleft>";
3310 startPortlet ('summary');
3311 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
423c4216
DO
3312 if (strlen ($address['name']))
3313 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${address['name']}</td></tr>";
04d619d0 3314 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
21ee3351
AA
3315 if ($address['version'] == 4)
3316 {
3317 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
3318 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
3319 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
3320 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
3321 }
68225375
DO
3322 echo "</table><br>\n";
3323 finishPortlet();
3324 echo "</td>\n";
e673ee24 3325
68225375 3326 echo "<td class=pcright>";
f74d96c6 3327 if (isset ($address['class']))
59bebe2b 3328 {
8e700dd1 3329 startPortlet ('allocations');
2d318652
DO
3330 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
3331 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
3332 $class = $address['class'];
3333 // render all allocation records for this address the same way
59bebe2b