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