r4091 l2addressForDatabase(): signal error with exception, not NULL
[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
baf37d01
DO
1670// Log structure versions:
1671// 1: the whole structure is a list of code-message pairs
1672// 2 and later: there's a "v" field set, which indicates the version
1673// 2: there's a "m" list set to hold message code and optional arguments
1cb6adf5 1674function showMessageOrError ()
e673ee24 1675{
1cb6adf5
DO
1676 if (!isset ($_SESSION['log']))
1677 return;
1678 $log = $_SESSION['log'];
baf37d01
DO
1679 switch (TRUE)
1680 {
1681 case !isset ($log['v']):
ebb5441d 1682 case $log['v'] == 1:
baf37d01 1683 foreach ($log as $key => $record)
ebb5441d 1684 if ($key !== 'v')
baf37d01
DO
1685 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1686 break;
1687 case $log['v'] == 2:
1688 $msginfo = array
1689 (
8628ae44 1690// records 0~99 with success messages
950a1887 1691 0 => array ('code' => 'success', 'format' => '%s'),
baf37d01
DO
1692 1 => array ('code' => 'success', 'format' => '%u new records done, %u already existed'),
1693 2 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully added.'),
1694 3 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully deleted.'),
1695 4 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully updated'),
1696 5 => array ('code' => 'success', 'format' => 'Port %s was added successfully'),
1697 6 => array ('code' => 'success', 'format' => 'Port %s was updated successfully'),
1698 7 => array ('code' => 'success', 'format' => 'Port %s was deleted successfully'),
1699 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with port %s at object %s'),
1700 9 => array ('code' => 'success', 'format' => 'Port %s was successfully unlinked from %s@%s'),
1701 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1702 11 => array ('code' => 'success', 'format' => 'Reservation removed.'),
1703 12 => array ('code' => 'success', 'format' => 'allocation updated'),
1704 13 => array ('code' => 'success', 'format' => 'allocated'),
1705 14 => array ('code' => 'success', 'format' => 'deallocated'),
1706 15 => array ('code' => 'success', 'format' => 'Reset succeeded.'),
1707 16 => array ('code' => 'success', 'format' => 'Update done'),
1708 17 => array ('code' => 'success', 'format' => 'Update(s) succeeded.'),
1709 18 => array ('code' => 'success', 'format' => 'Load balancer was successfully added'),
1710 19 => array ('code' => 'success', 'format' => 'Load balancer was successfully deleted'),
1711 20 => array ('code' => 'success', 'format' => 'Load balancer info was successfully updated'),
1712 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1713 22 => array ('code' => 'success', 'format' => 'Chained %u tags'),
1714 23 => array ('code' => 'success', 'format' => 'IPv4 prefix successfully added'),
1715 24 => array ('code' => 'success', 'format' => 'IPv4 prefix deleted'),
1716 25 => array ('code' => 'success', 'format' => 'IPv4 prefix updated'),
1717 26 => array ('code' => 'success', 'format' => '%u IP address(es) were successfully updated'),
1718 27 => array ('code' => 'success', 'format' => 'IPv4 address updated'),
1719 28 => array ('code' => 'success', 'format' => 'Virtual service was successfully created'),
1720 29 => array ('code' => 'success', 'format' => 'Virtual service was successfully deleted'),
1721 30 => array ('code' => 'success', 'format' => 'Virtual service was successfully updated'),
1722 31 => array ('code' => 'success', 'format' => 'RS pool was successfully created'),
1723 32 => array ('code' => 'success', 'format' => 'RS pool was successfully deleted'),
1724 33 => array ('code' => 'success', 'format' => 'RS pool was successfully updated'),
1725 34 => array ('code' => 'success', 'format' => 'Real server was successfully added'),
1726 35 => array ('code' => 'success', 'format' => 'Real server was successfully deleted'),
1727 36 => array ('code' => 'success', 'format' => 'Real server was successfully updated'),
1728 37 => array ('code' => 'success', 'format' => 'Successfully added %u real servers'),
1729 38 => array ('code' => 'success', 'format' => '%u real server(s) were successfully (de)activated'),
1730 39 => array ('code' => 'success', 'format' => 'User account %s updated.'),
1731 40 => array ('code' => 'success', 'format' => 'User account %s created.'),
4492050b 1732 41 => array ('code' => 'success', 'format' => 'uplink ports reverb queued'),
79b8ad1e 1733// ...
baf37d01
DO
1734 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1735 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1736 45 => array ('code' => 'success', 'format' => "Attribute '%s' created."),
1737 46 => array ('code' => 'success', 'format' => 'Rename successful.'),
1738 47 => array ('code' => 'success', 'format' => 'Attribute was deleted.'),
1739 48 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1740 49 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1741 50 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1742 51 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1743 52 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1744 53 => array ('code' => 'success', 'format' => 'Chapter was deleted.'),
1745 54 => array ('code' => 'success', 'format' => 'Chapter was updated.'),
1746 55 => array ('code' => 'success', 'format' => 'Chapter was added.'),
1747 56 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1748 57 => array ('code' => 'success', 'format' => 'Reset complete'),
c615a655 1749 58 => array ('code' => 'success', 'format' => "Deleted tag '%s'."),
baf37d01
DO
1750 59 => array ('code' => 'success', 'format' => "Created tag '%s'."),
1751 60 => array ('code' => 'success', 'format' => "Updated tag '%s'."),
ebb5441d 1752 61 => array ('code' => 'success', 'format' => 'Password changed successfully.'),
24dcb9d8 1753 62 => array ('code' => 'success', 'format' => 'gw: %s'),
f0ff4930
DO
1754 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
1755 64 => array ('code' => 'success', 'format' => 'Port %s@%s has been assigned to VLAN %u'),
f19c75d6 1756 65 => array ('code' => 'success', 'format' => "Added new rack '%s'"),
03e6ef01 1757 66 => array ('code' => 'success', 'format' => "File sent Ok via handler '%s'"),
abef7149 1758 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
0c2b7c4a 1759 68 => array ('code' => 'success', 'format' => "Updated rack '%s'"),
7be51fea
DO
1760 69 => array ('code' => 'success', 'format' => 'File "%s" was added successfully'),
1761 70 => array ('code' => 'success', 'format' => 'File "%s" was updated successfully'),
1762 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
8bc5d1e4 1763 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
7be51fea 1764 73 => array ('code' => 'success', 'format' => 'File "%s" was deleted successfully'),
8ea2a193 1765 74 => array ('code' => 'success', 'format' => 'Record "%s" was added successfully'),
7be51fea
DO
1766 75 => array ('code' => 'success', 'format' => 'Row "%s" was updated successfully'),
1767 76 => array ('code' => 'success', 'format' => 'Object "%s" was deleted successfully'),
f78748cf 1768 77 => array ('code' => 'success', 'format' => 'Record "%s" was deleted successfully'),
7be51fea
DO
1769 78 => array ('code' => 'success', 'format' => 'File "%s" saved Ok'),
1770 79 => array ('code' => 'success', 'format' => 'Rack "%s" was deleted successfully'),
57777e4a 1771 80 => array ('code' => 'success', 'format' => "Added new object '%s'"),
56a797ef 1772 81 => array ('code' => 'success', 'format' => "SNMP: completed '%s' work"),
a1fc539a 1773 82 => array ('code' => 'success', 'format' => "Bulk port creation was successful. %u ports created, %u failed"),
abd1e9ac 1774 83 => array ('code' => 'success', 'format' => 'Object "%s" was reset successfully'),
21ee3351
AA
1775 84 => array ('code' => 'success', 'format' => 'IPv6 prefix successfully added'),
1776 85 => array ('code' => 'success', 'format' => 'IPv6 prefix deleted'),
1777 86 => array ('code' => 'success', 'format' => 'IPv6 prefix updated'),
f9428bc6 1778 87 => array ('code' => 'success', 'format' => '802.1Q recalculate: %d ports changed on %d switches'),
8628ae44 1779// records 100~199 with fatal error messages
950a1887 1780 100 => array ('code' => 'error', 'format' => '%s'),
ebb5441d
DO
1781 101 => array ('code' => 'error', 'format' => 'Port name cannot be empty'),
1782 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
b82cce3f 1783 103 => array ('code' => 'error', 'format' => 'User not found!'),
ebb5441d 1784 104 => array ('code' => 'error', 'format' => "Error updating user account '%s'"),
c48f2e18 1785 105 => array ('code' => 'error', 'format' => 'default VLAN cannot be changed'),
79b8ad1e 1786// ...
3a089a44 1787 107 => array ('code' => 'error', 'format' => 'Assertion failed: %s'),
ec523868 1788 108 => array ('code' => 'error', 'format' => 'Database error: %s'),
ebb5441d
DO
1789 109 => array ('code' => 'error', 'format' => 'Update failed!'),
1790 110 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1791 111 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1792 112 => array ('code' => 'error', 'format' => 'Error adding chapter.'),
1793 113 => array ('code' => 'error', 'format' => 'Error updating chapter.'),
1794 114 => array ('code' => 'error', 'format' => 'Error deleting chapter.'),
1795 115 => array ('code' => 'error', 'format' => 'Error renaming attribute.'),
1796 116 => array ('code' => 'error', 'format' => 'Error creating attribute.'),
1797 117 => array ('code' => 'error', 'format' => 'Error deleting attribute.'),
1798 118 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1799 119 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1800 120 => array ('code' => 'error', 'format' => 'Reset failed!'),
1801 121 => array ('code' => 'error', 'format' => 'commitUpdateObject() failed'),
1802 122 => array ('code' => 'error', 'format' => 'One or more update(s) failed!'),
1803 123 => array ('code' => 'error', 'format' => 'Cannot process submitted data: unknown format code.'),
1804 124 => array ('code' => 'error', 'format' => 'Error removing reservation!'),
1805 125 => array ('code' => 'error', 'format' => "Update failed with error: '%s'"),
1806 126 => array ('code' => 'error', 'format' => 'addRStoRSPool() failed'),
1807 127 => array ('code' => 'error', 'format' => 'Added %u real servers and encountered %u errors'),
1808 128 => array ('code' => 'error', 'format' => 'commitDeleteRS() failed'),
1809 129 => array ('code' => 'error', 'format' => 'commitDeleteLB() failed'),
1810 130 => array ('code' => 'error', 'format' => 'commitDeleteVS() failed'),
1811 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1812 132 => array ('code' => 'error', 'format' => 'invalid protocol'),
1813 133 => array ('code' => 'error', 'format' => 'commitUpdateRS() failed'),
1814 134 => array ('code' => 'error', 'format' => 'commitUpdateLB() failed'),
1815 135 => array ('code' => 'error', 'format' => 'commitUpdateVS() failed'),
1816 136 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1817 137 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1818 138 => array ('code' => 'error', 'format' => 'commitDeleteRSPool() failed'),
1819 139 => array ('code' => 'error', 'format' => 'commitUpdateRSPool() failed'),
1820 140 => array ('code' => 'error', 'format' => 'Encountered %u errors, (de)activated %u real servers'),
be28b696 1821 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u record(s)'),
ebb5441d
DO
1822 142 => array ('code' => 'error', 'format' => 'executeAutoPorts() failed'),
1823 143 => array ('code' => 'error', 'format' => 'Tried chaining %u tags, but experienced %u errors.'),
1824 144 => array ('code' => 'error', 'format' => "Error deleting tag: '%s'"),
1825 145 => array ('code' => 'error', 'format' => "Invalid tag name '%s'"),
f78748cf 1826 146 => array ('code' => 'error', 'format' => 'Error deleting record "%s"'),
6cfedb71 1827 147 => array ('code' => 'error', 'format' => "Could not create tag '%s'"),
a5c589d2 1828 148 => array ('code' => 'error', 'format' => "Could not update tag '%s'"),
ebb5441d
DO
1829 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1830 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1831 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1832 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1833 153 => array ('code' => 'error', 'format' => 'Password change failed.'),
1834 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1835 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1836 156 => array ('code' => 'error', 'format' => 'getSwitchVLANs() failed'),
e81fb764 1837 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
24dcb9d8
DO
1838 158 => array ('code' => 'error', 'format' => 'Ignoring malformed record #%u in form submit'),
1839 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1840 160 => array ('code' => 'error', 'format' => 'Invalid arguments'),
1841 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1842 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
1843 163 => array ('code' => 'error', 'format' => 'Failed to get any response from queryGateway() or the gateway died'),
c030232f 1844 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
24dcb9d8
DO
1845 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1846 166 => array ('code' => 'error', 'format' => 'gw: %s'),
f0ff4930
DO
1847 167 => array ('code' => 'error', 'format' => 'Could not find port %s'),
1848 168 => array ('code' => 'error', 'format' => 'Port %s is a trunk'),
1849 169 => array ('code' => 'error', 'format' => 'Failed to configure %s, connector returned code %u'),
5222f192 1850 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
f19c75d6
DO
1851 171 => array ('code' => 'error', 'format' => "Failed creating rack '%s'. Already exists in this row?"),
1852 172 => array ('code' => 'error', 'format' => 'Malformed request'),
e5c4506d
DO
1853 173 => array ('code' => 'error', 'format' => "Invalid IPv4 prefix '%s'"),
1854 174 => array ('code' => 'error', 'format' => 'Bad IPv4 address'),
1855 175 => array ('code' => 'error', 'format' => 'Invalid netmask'),
1856 176 => array ('code' => 'error', 'format' => 'This network already exists'),
0c2b7c4a 1857 177 => array ('code' => 'error', 'format' => 'commitUpdateRack() failed'),
121496b6 1858 178 => array ('code' => 'error', 'format' => 'file not found'),
07de6bb3 1859 179 => array ('code' => 'error', 'format' => 'Expired form has been declined.'),
70cb9b56 1860 180 => array ('code' => 'error', 'format' => 'Error saving file, all changes lost!'),
db55cf54
DO
1861 181 => array ('code' => 'error', 'format' => "file uploads not allowed, change 'file_uploads' parameter in php.ini"),
1862 182 => array ('code' => 'error', 'format' => 'SQL query failed: %s'),
c615a655 1863 183 => array ('code' => 'error', 'format' => "Tag id '%s' does not exist."),
57777e4a
DO
1864 184 => array ('code' => 'error', 'format' => 'Submitted form is invalid at line %u'),
1865 185 => array ('code' => 'error', 'format' => "Failed to add object '%s'"),
1866 186 => array ('code' => 'error', 'format' => 'Incomplete form has been ignored. Cheers.'),
9a61c175 1867 187 => array ('code' => 'error', 'format' => "Internal error in function '%s'"),
74aee2dc
DO
1868 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1869 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
8198f2c6 1870 190 => array ('code' => 'error', 'format' => "Invalid VLAN ID '%s'"),
ca5d4cbc 1871 191 => array ('code' => 'error', 'format' => "deploy was blocked due to conflicting configuration versions"),
fb3e3731 1872 192 => array ('code' => 'error', 'format' => "Permission denied"),
f0ff4930 1873
8628ae44 1874// records 200~299 with warnings
950a1887 1875 200 => array ('code' => 'warning', 'format' => '%s'),
24dcb9d8
DO
1876 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1877 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
f0ff4930
DO
1878 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1879 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1880 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
c8187437 1881 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
db55cf54 1882 207 => array ('code' => 'warning', 'format' => 'Ignored empty request'),
57777e4a 1883
24d3182a
DO
1884// records 300~399 with notices
1885 300 => array ('code' => 'neutral', 'format' => '%s'),
1886
baf37d01
DO
1887 );
1888 // Handle the arguments. Is there any better way to do it?
1889 foreach ($log['m'] as $record)
1890 {
5222f192
DO
1891 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1892 {
1893 echo '<div class=msg_neutral>(this message was lost)</div>';
1894 continue;
1895 }
baf37d01
DO
1896 if (isset ($record['a']))
1897 switch (count ($record['a']))
1898 {
1899 case 1:
1900 $msgtext = sprintf
1901 (
1902 $msginfo[$record['c']]['format'],
1903 $record['a'][0]
1904 );
1905 break;
1906 case 2:
1907 $msgtext = sprintf
1908 (
1909 $msginfo[$record['c']]['format'],
1910 $record['a'][0],
1911 $record['a'][1]
1912 );
1913 break;
1914 case 3:
1915 $msgtext = sprintf
1916 (
1917 $msginfo[$record['c']]['format'],
1918 $record['a'][0],
1919 $record['a'][1],
1920 $record['a'][2]
1921 );
1922 break;
1923 case 4:
1924 default:
1925 $msgtext = sprintf
1926 (
1927 $msginfo[$record['c']]['format'],
1928 $record['a'][0],
1929 $record['a'][1],
1930 $record['a'][2],
1931 $record['a'][3]
1932 );
1933 break;
1934 }
1935 else
1936 $msgtext = $msginfo[$record['c']]['format'];
1937 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1938 }
1939 break;
1940 default:
1941 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1942 break;
1943 }
1cb6adf5 1944 unset($_SESSION['log']);
e673ee24
DO
1945}
1946
65e557dd
AA
1947// renders two tables: port link status and learned MAC list
1948function renderPortsInfo($object_id)
1949{
1950 global $nextorder;
1951 echo "<table width='100%'><tr>";
1952
1953 if (permitted (NULL, NULL, 'get_link_status'))
1954 {
1955 try
1956 {
1957 $linkStatus = gwRetrieveDeviceConfig ($object_id, 'getportstatus');
1958 }
1959 catch (RackTablesError $e) {}
1960 if (! empty ($linkStatus))
1961 {
1962 echo "<td valign='top' width='50%'>";
1963 startPortlet('Link status');
1964 echo "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>Port<th>Link status<th>Link info</tr>";
1965 $order = 'even';
1966 foreach ($linkStatus as $pn => $link)
1967 {
1968 echo "<tr class='row_$order'>";
1969 $order = $nextorder[$order];
1970 echo '<td>' . $pn;
1971 echo '<td>' . $link['status'];
1972 $info = '';
1973 if (isset ($link['speed']))
1974 $info .= $link['speed'];
1975 if (isset ($link['duplex']))
1976 {
1977 if (! empty ($info))
1978 $info .= ', ';
1979 $info .= $link['duplex'];
1980 }
1981 echo '<td>' . $info;
1982 echo '</tr>';
1983 }
1984 echo "</table></td>";
1985 finishPortlet();
1986 }
1987 }
1988
1989 try
1990 {
1991 $macList = sortPortList (gwRetrieveDeviceConfig ($object_id, 'getmaclist'));
1992 }
1993 catch (RackTablesError $e) {}
1994 if (! empty ($macList))
1995 {
1996 echo "<td valign='top' width='50%'>";
1997 $rendered_macs = '';
1998 $mac_count = 0;
1999 $rendered_macs .= "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>MAC<th>Vlan<th>Port</tr>";
2000 $order = 'even';
2001 foreach ($macList as $pn => $list)
2002 {
2003 $order = $nextorder[$order];
2004 foreach ($list as $item)
2005 {
2006 ++$mac_count;
2007 $rendered_macs .= "<tr class='row_$order'>";
2008 $rendered_macs .= '<td style="font-family: monospace">' . $item['mac'];
2009 $rendered_macs .= '<td>' . $item['vid'];
2010 $rendered_macs .= '<td>' . $pn;
2011 $rendered_macs .= '</tr>';
2012 }
2013 }
2014 $rendered_macs .= "</table></td>";
2015
2016 startPortlet("Learned MACs ($mac_count)");
2017 echo $rendered_macs;
2018 finishPortlet();
2019 }
2020
2021 echo "</td></tr></table>";
2022}
2023
e673ee24 2024/*
51c18782 2025The following conditions must be met:
e673ee24
DO
20261. We can mount onto free atoms only. This means: if any record for an atom
2027already exists in RackSpace, it can't be used for mounting.
20282. We can't unmount from 'W' atoms. Operator should review appropriate comments
2029and either delete them before unmounting or refuse to unmount the object.
2030*/
7e1db771 2031function renderRackSpaceForObject ($object_id)
e673ee24 2032{
e673ee24
DO
2033 // Always process occupied racks plus racks chosen by user. First get racks with
2034 // already allocated rackspace...
51c18782 2035 $workingRacksData = getResidentRacksData ($object_id);
e673ee24 2036 // ...and then add those chosen by user (if any).
2135fd83 2037 if (isset($_REQUEST['rackmulti']))
e673ee24 2038 foreach ($_REQUEST['rackmulti'] as $cand_id)
e673ee24
DO
2039 if (!isset ($workingRacksData[$cand_id]))
2040 {
0cc24e9a 2041 $rackData = spotEntity ('rack', $cand_id);
61a1d996 2042 amplifyCell ($rackData);
e673ee24
DO
2043 $workingRacksData[$cand_id] = $rackData;
2044 }
51690ad4 2045
e673ee24
DO
2046 // Main layout starts.
2047 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
2048
2049 // Left portlet with rack list.
2050 echo "<td class=pcleft height='1%'>";
2051 startPortlet ('Racks');
a8efc03e 2052 $allRacksData = listCells ('rack');
4b8d413e 2053 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
61a1d996 2054 foreach ($allRacksData as $rack)
51c18782
DO
2055 if (!array_key_exists ($rack['id'], $workingRacksData))
2056 {
2057 amplifyCell ($rack);
2058 $workingRacksData[$rack['id']] = $rack;
2059 }
2060 foreach (array_keys ($workingRacksData) as $rackId)
2061 applyObjectMountMask ($workingRacksData[$rackId], $object_id);
2062 printOpFormIntro ('updateObjectAllocation');
4b8d413e 2063 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
51c18782 2064 echo "<br><br>";
e673ee24
DO
2065 finishPortlet();
2066 echo "</td>";
2067
2068 // Middle portlet with comment and submit.
2069 echo "<td class=pcleft>";
2070 startPortlet ('Comment');
2071 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
2072 echo "<input type=submit value='Save' name=got_atoms>\n";
51c18782 2073 echo "<br><br>";
e673ee24
DO
2074 finishPortlet();
2075 echo "</td>";
2076
2077 // Right portlet with rendered racks. If this form submit is not final, we have to
2078 // reflect the former state of the grid in current form.
2079 echo "<td class=pcright rowspan=2 height='1%'>";
2080 startPortlet ('Working copy');
65e557dd 2081 addJS ('js/racktables.js');
e673ee24
DO
2082 echo '<table border=0 cellspacing=10 align=center><tr>';
2083 foreach ($workingRacksData as $rack_id => $rackData)
2084 {
2085 // Order is important here: only original allocation is highlighted.
2086 highlightObject ($rackData, $object_id);
2087 markupAtomGrid ($rackData, 'T');
2088 // If we have a form processed, discard user input and show new database
2089 // contents.
51c18782 2090 if (isset ($_REQUEST['rackmulti'][0])) // is an update
e673ee24
DO
2091 mergeGridFormToRack ($rackData);
2092 echo "<td valign=top>";
2093 echo "<center>\n<h2>${rackData['name']}</h2>\n";
2094 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
57c69e9c 2095 echo "<tr><th width='10%'>&nbsp;</th>";
64259015
DO
2096 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>";
2097 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>";
2098 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 2099 renderAtomGrid ($rackData);
57c69e9c 2100 echo "<tr><th width='10%'>&nbsp;</th>";
64259015
DO
2101 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>";
2102 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>";
2103 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
2104 echo "</table></center>\n";
2105 echo '</td>';
2106 }
2107 echo "</tr></table>";
2108 finishPortlet();
2109 echo "</td>\n";
2110
2111 echo "</form>\n";
2112 echo "</tr></table>\n";
2113}
2114
2115function renderMolecule ($mdata, $object_id)
2116{
2117 // sort data out
2118 $rackpack = array();
2119 global $loclist;
64b95774 2120 foreach ($mdata as $rua)
e673ee24
DO
2121 {
2122 $rack_id = $rua['rack_id'];
2123 $unit_no = $rua['unit_no'];
2124 $atom = $rua['atom'];
2125 if (!isset ($rackpack[$rack_id]))
2126 {
61a1d996
DO
2127 $rackData = spotEntity ('rack', $rack_id);
2128 amplifyCell ($rackData);
e673ee24
DO
2129 for ($i = $rackData['height']; $i > 0; $i--)
2130 for ($locidx = 0; $locidx < 3; $locidx++)
2131 $rackData[$i][$locidx]['state'] = 'F';
2132 $rackpack[$rack_id] = $rackData;
2133 }
2134 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
2135 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
2136 }
2137 // now we have some racks to render
65e557dd 2138 addAtomCSS();
64b95774 2139 foreach ($rackpack as $rackData)
e673ee24
DO
2140 {
2141 markAllSpans ($rackData);
2142 echo "<table class=molecule cellspacing=0>\n";
2143 echo "<caption>${rackData['name']}</caption>\n";
2144 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
2145 for ($i = $rackData['height']; $i > 0; $i--)
2146 {
2147 echo "<tr><th>$i</th>";
2148 for ($locidx = 0; $locidx < 3; $locidx++)
2149 {
2150 $state = $rackData[$i][$locidx]['state'];
65e557dd 2151 echo "<td class='atom state_${state}'>&nbsp;</td>\n";
e673ee24
DO
2152 }
2153 echo "</tr>\n";
2154 }
2155 echo "</table>\n";
2156 }
2157}
2158
23cdc7e9 2159function renderDepot ()
e673ee24 2160{
23cdc7e9 2161 global $pageno, $nextorder;
23cdc7e9
DO
2162 $cellfilter = getCellFilter();
2163 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
2164
2165 echo "<table border=0 class=objectview>\n";
2166 echo "<tr><td class=pcleft>";
2167
1ebbf889 2168 if (! renderEmptyResults ($cellfilter, 'objects', count($objects)))
e673ee24 2169 {
1ebbf889
AA
2170 startPortlet ('Objects (' . count ($objects) . ')');
2171 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2172 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Row/Rack</th></tr>';
2173 $order = 'odd';
2174 foreach ($objects as $obj)
2175 {
2176 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
2177 $secondclass = 'tdleft port_highlight';
2178 else
2179 $secondclass = 'tdleft';
2180 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>";
2181 if (count ($obj['etags']))
2182 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
2183 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
2184 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
2185 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
2186 if ($obj['rack_id'])
2187 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>";
2188 else
2189 echo "<td class='${secondclass}'>Unmounted</td>";
2190 echo '</tr>';
2191 $order = $nextorder[$order];
2192 }
2193 echo '</table>';
2194 finishPortlet();
e673ee24 2195 }
23cdc7e9
DO
2196
2197 echo "</td><td class=pcright width='25%'>";
2198
95857b5c 2199 renderCellFilterPortlet ($cellfilter, 'object', $objects);
23cdc7e9 2200 echo "</td></tr></table>\n";
e673ee24
DO
2201}
2202
1ebbf889
AA
2203// This function returns TRUE if the result set is too big to be rendered, and no filter is set.
2204// In this case it renders the describing message instead.
2205function renderEmptyResults($cellfilter, $entities_name, $count = NULL)
2206{
2207 if (!$cellfilter['is_empty'])
2208 return FALSE;
2209 if (isset ($_REQUEST['show_all_objects']))
2210 return FALSE;
2211 $max = intval(getConfigVar('MAX_UNFILTERED_ENTITIES'));
2212 if (0 == $max || $count <= $max)
2213 return FALSE;
2214
2215 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
2216 $href_show_all .= htmlspecialchars('&show_all_objects=1');
2217 $suffix = isset ($count) ? " ($count)" : '';
2218 echo <<<END
2219<p>Please set a filter to display the corresponging $entities_name.
2220<br><a href="$href_show_all">Show all $entities_name$suffix</a>
2221END;
2222 return TRUE;
2223}
2224
e673ee24
DO
2225// History viewer for history-enabled simple dictionaries.
2226function renderHistory ($object_type, $object_id)
2227{
2228 switch ($object_type)
2229 {
2230 case 'row':
a5c589d2 2231 $query = "select ctime, user_name, name, comment from RackRowHistory where id = ? order by ctime";
aa9a0fb4
DO
2232 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>rack row comment</th></tr>';
2233 $extra = 3;
e673ee24
DO
2234 break;
2235 case 'rack':
2236 $query =
aa9a0fb4 2237 "select ctime, user_name, rh.name, rr.name as name, rh.height, rh.comment " .
51690ad4 2238 "from RackHistory as rh left join RackRow as rr on rh.row_id = rr.id " .
a5c589d2 2239 "where rh.id = ? order by ctime";
aa9a0fb4
DO
2240 $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>';
2241 $extra = 5;
e673ee24
DO
2242 break;
2243 case 'object':
2244 $query =
aa9a0fb4 2245 "select ctime, user_name, RackObjectHistory.name as name, label, barcode, asset_no, has_problems, dict_value, comment " .
00f6f1e4 2246 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key join Chapter on Dictionary.chapter_id = Chapter.id " .
a5c589d2 2247 "where Chapter.name = 'RackObjectType' and RackObjectHistory.id=? order by ctime";
aa9a0fb4
DO
2248 $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>';
2249 $extra = 8;
e673ee24
DO
2250 break;
2251 default:
3a089a44 2252 throw new InvalidArgException ('object_type', $object_type);
e673ee24 2253 }
a5c589d2 2254 $result = usePreparedSelectBlade ($query, array ($object_id));
e673ee24
DO
2255 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2256 $order = 'odd';
2257 global $nextorder;
2258 echo $header;
2259 while ($row = $result->fetch (PDO::FETCH_NUM))
2260 {
2261 echo "<tr class=row_${order}><td>${row[0]}</td>";
2262 for ($i = 1; $i <= $extra; $i++)
2263 echo "<td>" . $row[$i] . "</td>";
2264 echo "</tr>\n";
2265 $order = $nextorder[$order];
2266 }
2267 echo "</table><br>\n";
2268}
2269
2270function renderRackspaceHistory ()
2271{
4fbb5a00 2272 global $nextorder, $pageno, $tabno;
e673ee24
DO
2273 $order = 'odd';
2274 $history = getRackspaceHistory();
2275 // Show the last operation by default.
2276 if (isset ($_REQUEST['op_id']))
2277 $op_id = $_REQUEST['op_id'];
2278 elseif (isset ($history[0]['mo_id']))
2279 $op_id = $history[0]['mo_id'];
2280 else $op_id = NULL;
2281
2282 $omid = NULL;
2283 $nmid = NULL;
2284 $object_id = 1;
2285 if ($op_id)
2286 list ($omid, $nmid) = getOperationMolecules ($op_id);
2287
2288 // Main layout starts.
2289 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2290
2291 // Left top portlet with old allocation.
2292 echo "<tr><td class=pcleft>";
2293 startPortlet ('Old allocation');
2294 if ($omid)
2295 {
2296 $oldMolecule = getMolecule ($omid);
2297 renderMolecule ($oldMolecule, $object_id);
2298 }
2299 else
2300 echo "nothing";
2301 finishPortlet();
2302
2303 echo '</td><td class=pcright>';
2304
2305 // Right top portlet with new allocation
2306 startPortlet ('New allocation');
2307 if ($nmid)
2308 {
2309 $newMolecule = getMolecule ($nmid);
2310 renderMolecule ($newMolecule, $object_id);
2311 }
2312 else
2313 echo "nothing";
2314 finishPortlet();
737a3f72 2315
e673ee24 2316 echo '</td></tr><tr><td colspan=2>';
737a3f72 2317
e673ee24
DO
2318 // Bottom portlet with list
2319
2320 startPortlet ('Rackspace allocation history');
2321 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
7fa7047a 2322 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
e673ee24
DO
2323 foreach ($history as $row)
2324 {
2325 if ($row['mo_id'] == $op_id)
2326 $class = 'hl';
2327 else
2328 $class = "row_${order}";
4fbb5a00 2329 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
7fa7047a
DO
2330 echo "<td>${row['user_name']}</td><td>";
2331 renderCell (spotEntity ('object', $row['ro_id']));
2332 echo "</td><td>${row['comment']}</td>\n";
e673ee24
DO
2333 echo "</tr>\n";
2334 $order = $nextorder[$order];
2335 }
2336 echo "</table>\n";
2337 finishPortlet();
737a3f72 2338
e673ee24 2339 echo '</td></tr></table>';
e673ee24
DO
2340}
2341
1f54e1ba 2342function renderIPv4SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
d65353ad
DO
2343{
2344 $self = __FUNCTION__;
ca4eb604
DO
2345 static $vdomlist = NULL;
2346 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
e829e76b 2347 $vdomlist = getVLANDomainOptions();
00276508
AA
2348
2349 // scroll page to the highlighted item
2350 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 2351 addAutoScrollScript ("net-$target");
00276508 2352
d65353ad
DO
2353 foreach ($tree as $item)
2354 {
64347dcf 2355 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
64347dcf 2356 loadIPv4AddrList ($item); // necessary to compute router list and address counter
64347dcf
DO
2357 else
2358 {
2359 $item['addrlist'] = array();
2360 $item['addrc'] = 0;
2361 }
b1e39212
DO
2362 $used = $item['addrc'];
2363 $maxdirect = $item['addrt'];
2364 $maxtotal = binInvMaskFromDec ($item['mask']) + 1;
0137d53c
DO
2365 if (isset ($item['id']))
2366 {
1f54e1ba 2367 $decor = array ('indent' => $level);
fec0c8da 2368 if ($item['symbol'] == 'node-collapsed')
00276508 2369 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
fec0c8da 2370 elseif ($item['symbol'] == 'node-expanded')
00276508 2371 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}" : '');
0137d53c 2372 echo "<tr valign=top>";
21ee3351
AA
2373 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
2374 $decor['tdclass'] .= ' port_highlight';
2375 printIPNetInfoTDs ($item, $decor);
0137d53c 2376 echo "<td class=tdcenter>";
64347dcf
DO
2377 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2378 {
b1e39212
DO
2379 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2380 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small>';
64347dcf
DO
2381 }
2382 else
b1e39212 2383 echo "<small>${maxdirect}</small>";
64347dcf 2384 echo "</td>";
ca4eb604
DO
2385 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2386 {
a5f9d1ca
DO
2387 echo '<td class=tdleft>';
2388 if (count ($item['8021q']))
ca4eb604 2389 {
a5f9d1ca
DO
2390 echo '<ul>';
2391 foreach ($item['8021q'] as $binding)
2392 {
2393 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
e829e76b
DO
2394 // FIXME: would formatVLANName() do this?
2395 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
a5f9d1ca
DO
2396 }
2397 echo '</ul>';
ca4eb604
DO
2398 }
2399 echo '</td>';
2400 }
0137d53c 2401 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
4a47d34b 2402 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
0137d53c 2403 echo "</tr>";
fec0c8da 2404 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
1f54e1ba 2405 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
0137d53c
DO
2406 }
2407 else
2408 {
0137d53c 2409 echo "<tr valign=top>";
21ee3351 2410 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
0137d53c 2411 echo "<td class=tdcenter>";
64347dcf
DO
2412 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2413 {
b1e39212
DO
2414 renderProgressBar ($used/$maxtotal, 'sparenetwork');
2415 echo "<br><small>${used}/${maxtotal}</small>";
64347dcf
DO
2416 }
2417 else
b1e39212 2418 echo "<small>${maxtotal}</small>";
ee3eac34
DO
2419 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2420 echo '</td><td>&nbsp;</td>';
64347dcf 2421 echo "</td><td>&nbsp;</td></tr>";
0137d53c 2422 }
d65353ad
DO
2423 }
2424}
2425
21ee3351
AA
2426function renderIPv6SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
2427{
2428 $self = __FUNCTION__;
2429 static $vdomlist = NULL;
2430 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2431 $vdomlist = getVLANDomainOptions();
00276508
AA
2432
2433 // scroll page to the highlighted item
2434 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 2435 addAutoScrollScript ("net-$target");
00276508 2436
21ee3351
AA
2437 foreach ($tree as $item)
2438 {
2439 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2440 loadIPv6AddrList ($item); // necessary to compute router list and address counter
2441 else
2442 {
2443 $item['addrlist'] = array();
2444 $item['addrc'] = 0;
2445 }
2446 if (isset ($item['id']))
2447 {
2448 $decor = array ('indent' => $level);
2449 if ($item['symbol'] == 'node-collapsed')
00276508 2450 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
21ee3351
AA
2451 elseif ($item['symbol'] == 'node-expanded')
2452 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#net6id${item['parent_id']}" : '');
2453 echo "<tr valign=top>";
2454 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
2455 $decor['tdclass'] .= ' port_highlight';
2456 printIPNetInfoTDs ($item, $decor);
2457 echo "<td class=tdcenter>";
21ee3351
AA
2458 // show net usage
2459 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2460 echo "</td>";
2461 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2462 {
2463 echo '<td class=tdleft>';
2464 if (count ($item['8021q']))
2465 {
2466 echo '<ul>';
2467 foreach ($item['8021q'] as $binding)
2468 {
2469 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
2470 // FIXME: would formatVLANName() do this?
2471 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
2472 }
2473 echo '</ul>';
2474 }
2475 echo '</td>';
2476 }
2477 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2478 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
2479 echo "</tr>";
2480 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2481 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
2482 }
2483 /* do not display spare networks
2484 else
2485 { // display spare networks
2486 echo "<tr valign=top>";
2487 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
2488 echo "<td class=tdcenter>";
2489 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2490 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2491 echo '</td><td>&nbsp;</td>';
2492 echo "</td><td>&nbsp;</td></tr>";
2493 }*/
2494 }
2495}
2496
2497// if $used is NULL, returns only human-formatted mask.
2498// Otherwise returns "$used in/of " . human-formatted-mask
2499function formatIPv6NetUsage ($used, $mask)
2500{
2501 $prefixes = array
2502 (
2503 0 => '',
2504 3 => 'k',
2505 6 => 'M',
2506 9 => 'G',
2507 12 => 'T',
2508 15 => 'P',
2509 18 => 'E',
2510 21 => 'Z',
2511 24 => 'Y',
2512 );
2513
2514 if ($mask <= 64)
2515 {
2516 $what = '/64 net';
2517 $preposition = 'in';
2518 $mask += 64;
2519 }
2520 else
2521 {
2522 $what = 'IP';
2523 $preposition = 'of';
2524 }
2525 $what .= (0 == $mask % 64 ? '' : 's');
2526 $addrc = isset ($used) ? "$used $preposition " : '';
2527
2528 $dec_order = intval ((128 - $mask) / 10) * 3;
2529 $mult = isset ($prefixes[$dec_order]) ? $prefixes[$dec_order] : '??';
2530
2531 $cnt = 1 << ((128 - $mask) % 10);
2532 if ($cnt == 1 && $mult == '')
2533 $cnt = 'single';
2534
2535 return "<small>${addrc}${cnt}${mult} ${what}</small>";
2536}
2537
04d619d0 2538function renderIPv4Space ()
e673ee24 2539{
4fbb5a00 2540 global $pageno, $tabno;
31c941ec 2541 $cellfilter = getCellFilter();
1f54e1ba
DO
2542 $netlist = listCells ('ipv4net');
2543 $allcount = count ($netlist);
2544 $netlist = filterCellList ($netlist, $cellfilter['expression']);
573214e0 2545 array_walk ($netlist, 'amplifyCell');
4fbb5a00 2546
94a40058 2547 $netcount = count ($netlist);
5388794d
DO
2548 // expand request can take either natural values or "ALL". Zero means no expanding.
2549 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2550 $tree = prepareIPv4Tree ($netlist, $eid);
3630d1fb
DO
2551
2552 echo "<table border=0 class=objectview>\n";
2553 echo "<tr><td class=pcleft>";
1ebbf889
AA
2554 if (! renderEmptyResults($cellfilter, 'IPv4 nets', count($tree)))
2555 {
2556 startPortlet ("networks (${netcount})");
2557 echo '<h4>';
2558 if ($eid === 0)
2559 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2560 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2561 $cellfilter['urlextra'] . "'>expand all</a>)";
2562 elseif ($eid === 'ALL')
2563 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2564 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2565 else
2566 {
2567 $netinfo = spotEntity ('ipv4net', $eid);
2568 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2569 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2570 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2571 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2572 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2573 }
2574 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2575 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2576 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2577 echo '<th>VLAN</th>';
2578 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2579 echo "<th>routed by</th>";
2580 echo "</tr>\n";
2581 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2582 renderIPv4SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2583 echo "</table>\n";
2584 finishPortlet();
5388794d 2585 }
1ebbf889 2586
74ccacff 2587 echo '</td><td class=pcright>';
95857b5c 2588 renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
74ccacff 2589 echo "</td></tr></table>\n";
f973f491 2590}
a7fe7729 2591
21ee3351
AA
2592function renderIPv6Space ()
2593{
2594 global $pageno, $tabno;
2595 $cellfilter = getCellFilter();
2596 $netlist = listCells ('ipv6net');
2597 $allcount = count ($netlist);
2598 $netlist = filterCellList ($netlist, $cellfilter['expression']);
2599 array_walk ($netlist, 'amplifyCell');
2600
2601 $netcount = count ($netlist);
2602 // expand request can take either natural values or "ALL". Zero means no expanding.
2603 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2604 $tree = prepareIPv6Tree ($netlist, $eid);
2605
2606 echo "<table border=0 class=objectview>\n";
2607 echo "<tr><td class=pcleft>";
2608 if (! renderEmptyResults($cellfilter, 'IPv6 nets', count($tree)))
2609 {
2610 startPortlet ("networks (${netcount})");
2611 echo '<h4>';
2612 if ($eid === 0)
2613 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2614 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2615 $cellfilter['urlextra'] . "'>expand all</a>)";
2616 elseif ($eid === 'ALL')
2617 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2618 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2619 else
2620 {
2621 $netinfo = spotEntity ('ipv6net', $eid);
2622 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2623 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2624 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2625 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2626 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2627 }
2628 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2629 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2630 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2631 echo '<th>VLAN</th>';
2632 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2633 echo "<th>routed by</th>";
2634 echo "</tr>\n";
2635 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2636 renderIPv6SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2637 echo "</table>\n";
2638 finishPortlet();
2639 }
2640
2641 echo '</td><td class=pcright>';
2642 renderCellFilterPortlet ($cellfilter, 'ipv6net', $netlist);
2643 echo "</td></tr></table>\n";
2644}
2645
1f54e1ba
DO
2646function renderSLBDefConfig()
2647{
2648 $defaults = getSLBDefaults ();
2649 startPortlet ('SLB default configs');
2650 echo '<table cellspacing=0 cellpadding=5 align=center>';
2651 printOpFormIntro ('save');
2652 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>';
2653 echo '<td rowspan=2>';
2654 printImageHREF ('SAVE', 'Save changes', TRUE);
2655 echo '</td></tr>';
2656 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>';
2657 echo '</form></table>';
2658 finishPortlet();
2659}
2660
f973f491
DO
2661function renderIPv4SLB ()
2662{
4fbb5a00 2663 global $page, $nextorder;
a7fe7729 2664
6fec9f39 2665 startPortlet ('SLB configuration');
b3c50e6c 2666 echo "<table border=0 width='100%'><tr>";
ee437dab 2667 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
4fbb5a00 2668 echo "<td><h3><a href='".makeHref(array('page'=>$pno))."'>" . $page[$pno]['title'] . "</a></h3></td>";
b3c50e6c
DO
2669 echo '</tr></table>';
2670 finishPortlet();
2671
c3bdc503 2672 $summary = getSLBSummary();
6fec9f39 2673 startPortlet ('SLB tactical overview');
4cadac8f
DO
2674 // A single id-keyed array isn't used here to preserve existing
2675 // order of LBs returned by getSLBSummary()
c3bdc503
DO
2676 $lblist = array();
2677 $lbdname = array();
4cadac8f 2678 foreach ($summary as $vipdata)
da04825a 2679 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
c3bdc503
DO
2680 if (!in_array ($lb_object_id, $lblist))
2681 {
fb6e2f57 2682 $oi = spotEntity ('object', $lb_object_id);
c3bdc503
DO
2683 $lbdname[$lb_object_id] = $oi['dname'];
2684 $lblist[] = $lb_object_id;
2685 }
2686 if (!count ($summary))
2687 echo 'none configured';
2688 else
2689 {
80e85ea1 2690 $order = 'odd';
c3bdc503 2691 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
b1a970c7 2692 echo "<tr valign=top><td>&nbsp;</td>";
c3bdc503 2693 foreach ($lblist as $lb_object_id)
b1a970c7 2694 {
4fbb5a00 2695 #echo "<th><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$lb_object_id))."'>" . $lbdname[$lb_object_id] . "</a></th>";
b1a970c7
DO
2696 echo '<td>';
2697 renderLBCell ($lb_object_id);
2698 echo '</td>';
2699 }
c3bdc503 2700 echo "</tr>\n";
4cadac8f
DO
2701 foreach ($summary as $vsid => $vsdata)
2702 {
b1a970c7 2703 echo "<tr class=row_${order}><td class=tdleft>";
6df2025d 2704 renderCell (spotEntity ('ipv4vs', $vsid));
6fec9f39 2705 echo "</td>";
4cadac8f 2706 foreach ($lblist as $lb_object_id)
da04825a 2707 {
60fbcece 2708 echo '<td class=tdleft>';
2b4eee17 2709 if (!isset ($vsdata['lblist'][$lb_object_id]))
da04825a
DO
2710 echo '&nbsp;';
2711 else
6fec9f39
DO
2712 {
2713 echo $vsdata['lblist'][$lb_object_id]['size'];
4fbb5a00 2714// echo " (<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$vsdata['lblist'][$lb_object_id]['id'])). "'>";
79a9edb4 2715// echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
6fec9f39 2716 }
da04825a
DO
2717 echo '</td>';
2718 }
2719 echo "</tr>\n";
80e85ea1 2720 $order = $nextorder[$order];
4cadac8f 2721 }
c3bdc503
DO
2722 echo "</table>\n";
2723 }
a7fe7729 2724 finishPortlet ();
e673ee24
DO
2725}
2726
04d619d0 2727function renderIPv4SpaceEditor ()
e673ee24 2728{
a262e150 2729 // IPv4 validator
65e557dd
AA
2730 addJs ('js/live_validation.js');
2731 $regexp = addslashes ('^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$');
2732 addJs (<<<END
2733$(document).ready(function () {
2734 document.add_new_range.range.setAttribute('match', '$regexp');
2735 Validate.init();
2736});
2737END
2738 , TRUE);
a262e150 2739
f857f71f
DO
2740 function printNewItemTR ()
2741 {
2742 startPortlet ('Add new');
2743 echo '<table border=0 cellpadding=10 align=center>';
2744 // This form requires a name, so JavaScript validator can find it.
2745 // No printOpFormIntro() hence
2746 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2747 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2748 // tags column
2749 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2750 renderNewEntityTags ('ipv4net');
2751 echo '</td>';
2752 // inputs column
2753 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2754 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>";
2755 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2756 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2757 echo "<tr><td colspan=2>";
2758 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2759 echo '</td></tr>';
2760 echo "</form></table><br><br>\n";
2761 finishPortlet();
2762 }
2a201216 2763
f857f71f
DO
2764 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2765 printNewItemTR();
ab1283b7 2766 if (count ($addrspaceList = listCells ('ipv4net')))
e673ee24 2767 {
e43a2de4 2768 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
04d619d0 2769 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
b1e39212 2770 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
d3dcdfbb
DO
2771 array_walk ($addrspaceList, 'amplifyCell');
2772 $tree = prepareIPv4Tree ($addrspaceList, 'ALL');
2773 // this is only called for having "trace" set
2774 treeFromList ($addrspaceList);
0c16ef0c 2775 foreach ($addrspaceList as $netinfo)
e673ee24 2776 {
b1e39212
DO
2777 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2778 // now we have all subnets listed in netinfo
2779 loadIPv4AddrList ($netinfo);
2780 $used = $netinfo['addrc'];
2781 $maxdirect = $netinfo['addrt'];
2782 $maxtotal = binInvMaskFromDec ($netinfo['mask']) + 1;
e43a2de4 2783 echo "<tr valign=top><td>";
21ee3351
AA
2784 if (count ($netinfo['addrlist']) && getConfigVar ('IPV4_JAYWALK') == 'no')
2785 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2786 else
e43a2de4
DO
2787 {
2788 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2789 printImageHREF ('destroy', 'Delete this prefix');
2790 echo "</a>";
2791 }
21ee3351
AA
2792 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv4net', 'id' => $netinfo['id'])) . '">';
2793 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
2794 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2795 if (count ($netinfo['etags']))
2796 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2797 echo '</td><td>';
2798 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2799 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small></td>';
2800 echo '</tr>';
2801 }
2802 echo "</table>";
2803 finishPortlet();
2804 }
2805 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2806 printNewItemTR();
2807}
e43a2de4 2808
21ee3351
AA
2809function renderIPv6SpaceEditor ()
2810{
2811 // IPv6 validator
65e557dd
AA
2812 addJs ('js/live_validation.js');
2813 $regexp = addslashes ('^[a-fA-F0-9:]*:[a-fA-F0-9:\.]*/\d{1,3}$');
2814 addJs (<<<END
2815$(document).ready(function () {
2816 document.add_new_range.range.setAttribute('match', '$regexp');
2817 Validate.init();
2818});
2819END
2820 , TRUE);
21ee3351
AA
2821
2822 function printNewItemTR ()
2823 {
2824 startPortlet ('Add new');
2825 echo '<table border=0 cellpadding=10 align=center>';
2826 // This form requires a name, so JavaScript validator can find it.
2827 // No printOpFormIntro() hence
2828 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2829 echo "<input type=hidden name=op value=addIPv6Prefix>\n";
2830 // tags column
2831 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2832 renderNewEntityTags ('ipv4net');
2833 echo '</td>';
2834 // inputs column
2835 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2836 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>";
2837 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2838 echo "<tr><td colspan=2>";
2839 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2840 echo '</td></tr>';
2841 echo "</form></table><br><br>\n";
2842 finishPortlet();
2843 }
2844
2845 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2846 printNewItemTR();
2847 if (count ($addrspaceList = listCells ('ipv6net')))
2848 {
2849 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2850 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2851 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
2852 array_walk ($addrspaceList, 'amplifyCell');
2853 $tree = prepareIPv6Tree ($addrspaceList, 'ALL');
2854 // this is only called for having "trace" set
2855 treeFromList ($addrspaceList);
2856 foreach ($addrspaceList as $netinfo)
2857 {
2858 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2859 // now we have all subnets listed in netinfo
2860 loadIPv6AddrList ($netinfo);
2861 echo "<tr valign=top><td>";
2862 if (count ($netinfo['addrlist']) && getConfigVar ('IPV4_JAYWALK') == 'no')
2863 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2864 else
2865 {
2866 echo "<a href='".makeHrefProcess (array ('op' => 'delIPv6Prefix', 'id' => $netinfo['id'])) . "'>";
2867 printImageHREF ('destroy', 'Delete this prefix');
2868 echo "</a>";
e43a2de4 2869 }
21ee3351 2870 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv6net', 'id' => $netinfo['id'])) . '">';
ab1283b7 2871 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
1f54e1ba
DO
2872 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2873 if (count ($netinfo['etags']))
2874 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2875 echo '</td><td>';
21ee3351 2876 echo formatIPv6NetUsage ($netinfo['addrc'], $netinfo['mask']);
b1e39212 2877 echo '</tr>';
e673ee24 2878 }
04d619d0
DO
2879 echo "</table>";
2880 finishPortlet();
e673ee24 2881 }
f857f71f
DO
2882 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2883 printNewItemTR();
e673ee24
DO
2884}
2885
beb9e88a 2886function renderIPv4Network ($id)
e673ee24 2887{
c8824ff4 2888 global $pageno, $tabno, $aac2, $netmaskbylen, $wildcardbylen;
e673ee24 2889
d724d290 2890 $range = spotEntity ('ipv4net', $id);
a5f9d1ca 2891 amplifyCell ($range);
b6b87070 2892 loadIPv4AddrList ($range);
2034d968 2893 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
99ab184f
DO
2894 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2895 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2034d968
DO
2896
2897 echo "<tr><td class=pcleft width='50%'>";
2898 startPortlet ('summary');
2899 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2900 $used = count ($range['addrlist']);
2901 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
04d619d0
DO
2902
2903 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2034d968
DO
2904 renderProgressBar ($used/$total);
2905 echo "&nbsp;${used}/${total}</td></tr>\n";
04d619d0 2906
001e61fa
DO
2907 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2908 {
3444ecf2
DO
2909 // Build a backtrace from all parent networks.
2910 $clen = $range['mask'];
2911 $backtrace = array();
2912 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2913 {
d724d290 2914 $upperinfo = spotEntity ('ipv4net', $upperid);
3444ecf2 2915 $clen = $upperinfo['mask'];
d724d290 2916 $backtrace[] = $upperinfo;
3444ecf2
DO
2917 }
2918 $arrows = count ($backtrace);
d724d290 2919 foreach (array_reverse ($backtrace) as $ainfo)
001e61fa 2920 {
3444ecf2
DO
2921 echo "<tr><th width='50%' class=tdright>";
2922 for ($i = 0; $i < $arrows; $i++)
2923 echo '&uarr;';
2924 $arrows--;
5d3dcb8d 2925 echo "</th><td class=tdleft>";
6df2025d 2926 renderCell ($ainfo);
5d3dcb8d 2927 echo "</td></tr>";
001e61fa 2928 }
3444ecf2 2929 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
5d3dcb8d 2930 echo "<td class=tdleft>";
6df2025d 2931 renderCell ($range);
5d3dcb8d 2932 echo "</td></tr>";
001e61fa
DO
2933 // FIXME: get and display nested networks
2934 // $theitem = pickLeaf ($ipv4tree, $id);
2935 }
2936
545478d0
DO
2937 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2938 echo $netmaskbylen[$range['mask']];
2939 echo "</td></tr>\n";
04d619d0 2940
c607ab55
DO
2941 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2942 printf ('0x%08X', binMaskFromDec ($range['mask']));
2943 echo "</td></tr>\n";
2944
545478d0
DO
2945 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2946 echo $wildcardbylen[$range['mask']];
2947 echo "</td></tr>\n";
04d619d0 2948
a5f9d1ca 2949 foreach ($range['8021q'] as $item)
cbf78395 2950 {
a5f9d1ca 2951 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
cbf78395 2952 echo '<tr><th width="50%" class=tdright>VLAN:</th><td class=tdleft><a href="';
a5f9d1ca 2953 echo makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">';
a72aa89f 2954 echo formatVLANName ($vlaninfo, 'markup long');
ce85f5c8 2955 echo '</a></td></tr>';
cbf78395 2956 }
3a4f4023 2957 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
04d619d0 2958 {
57dece2f 2959 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
f3d0cb20 2960 printRoutersTD ($routers);
57dece2f 2961 echo "</tr>\n";
04d619d0
DO
2962 }
2963
9b57f793 2964 printTagTRs ($range, makeHref(array('page'=>'ipv4space', 'tab'=>'default'))."&");
2034d968
DO
2965 echo "</table><br>\n";
2966 finishPortlet();
e1ae3fb4 2967
99ab184f
DO
2968 if (strlen ($range['comment']))
2969 {
2970 startPortlet ('Comment');
2971 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2972 finishPortlet ();
2973 }
2974
e1ae3fb4 2975 renderFilesPortlet ('ipv4net', $id);
2034d968 2976 echo "</td>\n";
e673ee24 2977
2034d968
DO
2978 echo "<td class=pcright>";
2979 startPortlet ('details');
e673ee24
DO
2980 $startip = $range['ip_bin'] & $range['mask_bin'];
2981 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2982 $realstartip = $startip;
2983 $realendip = $endip;
e673ee24 2984
00276508
AA
2985 if (isset ($_REQUEST['hl_ipv4_addr']))
2986 {
2987 $hl_ip = ip2long ($_REQUEST['hl_ipv4_addr']);
2988 $hl_dottedquad = ip_long2quad ($hl_ip);
65e557dd 2989 addAutoScrollScript ("ip-$hl_dottedquad"); // scroll page to highlighted ip
00276508
AA
2990 }
2991
79b57b18
AA
2992 // pager
2993 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2994 $address_count = $endip - $startip + 1;
2995 $page = 0;
2996 if ($address_count > $maxperpage && $maxperpage > 0)
2997 {
2998 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? intval (($hl_ip - $startip) / $maxperpage) : 0);
2999 if ($numpages = ceil ($address_count / $maxperpage))
3000 {
3001 echo "<center>";
3002 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
3003 for ($i = 0; $i < $numpages; $i++)
3004 if ($i == $page)
3005 echo "<b>$i</b> ";
3006 else
3007 echo "<a href='".makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $id, 'pg' => $i)) . "'>$i</a> ";
3008 echo "</center>";
3009 }
3010 $startip = $startip + $page * $maxperpage;
3011 $endip = min ($startip + $maxperpage - 1, $endip);
3012 }
3013
beb9e88a 3014 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
e673ee24
DO
3015 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
3016
b2035dca 3017 for ($ip = $startip; $ip <= $endip; $ip++) :
00276508
AA
3018 $dottedquad = ip_long2quad($ip);
3019 $secondstyle = 'tdleft' . (isset ($hl_ip) && $hl_ip == $ip ? ' port_highlight' : '');
b2035dca 3020 if (!isset ($range['addrlist'][$ip]))
e673ee24 3021 {
00276508
AA
3022 echo "<tr><td class=tdleft><a name='ip-$dottedquad' href='" . makeHref(array('page'=>'ipaddress', 'ip' => $dottedquad)) . "'>$dottedquad</a></td>";
3023 echo "<td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
b2035dca
DO
3024 continue;
3025 }
b2035dca 3026 $addr = $range['addrlist'][$ip];
2d318652 3027 echo "<tr class='${addr['class']}'>";
e673ee24 3028
00276508 3029 echo "<td class=tdleft><a name='ip-$dottedquad' href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
b2035dca
DO
3030 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
3031 $delim = '';
3032 $prologue = '';
3033 if ( $addr['reserved'] == 'yes')
3034 {
2d318652 3035 echo "<strong>RESERVED</strong> ";
b2035dca
DO
3036 $delim = '; ';
3037 }
2d318652 3038 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
b2035dca 3039 {
beb9e88a 3040 echo $delim . $aac2[$ref['type']];
4fbb5a00 3041 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'hl_ipv4_addr'=>$addr['ip']))."'>";
59a83bd8 3042 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
b2035dca
DO
3043 echo "${ref['object_name']}</a>";
3044 $delim = '; ';
3045 }
3046 if ($delim != '')
3047 {
6131056c 3048 $delim = '';
b2035dca
DO
3049 $prologue = '<br>';
3050 }
2d318652 3051 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
b2035dca
DO
3052 {
3053 echo $prologue;
602663f4 3054 $prologue = '';
4fbb5a00
DY
3055 echo "${delim}<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id']))."'>";
3056 echo "${ref['object_name']}</a>:<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$ref['vs_id']))."'>";
b2035dca
DO
3057 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
3058 $delim = '; ';
3059 }
3060 if ($delim != '')
3061 {
3062 $delim = '';
3063 $prologue = '<br>';
e673ee24 3064 }
2d318652 3065 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
b2035dca
DO
3066 {
3067 echo $prologue;
3068 $prologue = '';
4fbb5a00 3069 echo "${delim}&rarr;${ref['rsport']}@<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$ref['rspool_id']))."'>";
b2035dca
DO
3070 echo "${ref['rspool_name']}</a>";
3071 $delim = '; ';
3072 }
3073 echo "</td></tr>\n";
3074 endfor;
2727c7df 3075 // end of iteration
e673ee24
DO
3076
3077 echo "</table>";
2034d968
DO
3078 finishPortlet();
3079 echo "</td></tr></table>\n";
e673ee24
DO
3080}
3081
21ee3351
AA
3082// based on renderIPv4Network
3083function renderIPv6Network ($id)
3084{
3085 $range = spotEntity ('ipv6net', $id);
3086 amplifyCell ($range);
3087 loadIPv6AddrList ($range);
3088 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
3089 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
3090 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
3091
3092 echo "<tr><td class=pcleft width='50%'>";
3093 startPortlet ('summary');
3094 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
3095 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
3096 echo "&nbsp;" . formatIPv6NetUsage (count ($range['addrlist']), $range['mask']) . "</td></tr>\n";
3097
3098 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
3099 {
3100 // Build a backtrace from all parent networks.
3101 $backtrace = array();
3102 $current = $range;
3103 while ($current['parent_id'])
3104 {
3105 $current = spotEntity ('ipv6net', $current['parent_id']);
3106 $backtrace[] = $current;
3107 }
3108 $arrows = count ($backtrace);
3109 foreach (array_reverse ($backtrace) as $ainfo)
3110 {
3111 echo "<tr><th width='50%' class=tdright>";
3112 for ($i = 0; $i < $arrows; $i++)
3113 echo '&uarr;';
3114 $arrows--;
3115 echo "</th><td class=tdleft>";
3116 renderCell ($ainfo);
3117 echo "</td></tr>";
3118 }
3119 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
3120 echo "<td class=tdleft>";
3121 renderCell ($range);
3122 echo "</td></tr>";
3123 // FIXME: get and display nested networks
3124 }
3125
3126 foreach ($range['8021q'] as $item)
3127 {
3128 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
3129 echo '<tr><th width="50%" class=tdright>VLAN:</th><td class=tdleft><a href="';
3130 echo makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">';
3131 echo formatVLANName ($vlaninfo, 'markup long');
3132 echo '</a></td></tr>';
3133 }
3134 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
3135 {
3136 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
3137 printRoutersTD ($routers);
3138 echo "</tr>\n";
3139 }
3140
3141 printTagTRs ($range, makeHref (array ('page' => 'ipv6space', 'tab' => 'default')) . "&");
3142 echo "</table><br>\n";
3143 finishPortlet();
3144
3145 if (strlen ($range['comment']))
3146 {
3147 startPortlet ('Comment');
3148 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
3149 finishPortlet ();
3150 }
3151
3152 renderFilesPortlet ('ipv6net', $id);
3153 echo "</td>\n";
3154
3155 // render address list
3156 echo "<td class=pcright>";
3157 startPortlet ('details');
3158 renderIPv6NetworkAddresses ($range);
3159 finishPortlet();
3160 echo "</td></tr></table>\n";
3161}
3162
3163// Used solely by renderSeparator
3164function renderEmptyIPv6 ($ip, $hl_ip)
3165{
3166 $class = 'tdleft';
3167 if (isset ($hl_ip) && $ip == $hl_ip)
3168 $class .= ' port_highlight';
3169 $fmt = $ip->format();
00276508 3170 echo "<tr><td class=tdleft><a name='ip-$fmt' href='" . makeHref (array ('page' => 'ipv6address', 'ip' => $fmt)) . "'>" . $fmt;
21ee3351
AA
3171 echo "</a></td><td class='${class}'>&nbsp;</td><td class='${class}'>&nbsp;</td></tr>\n";
3172}
3173
3174// Renders empty table line to shrink empty IPv6 address ranges.
3175// If the range consists of single address, renders the address instead of empty line.
3176// Renders address $hl_ip inside the range.
3177// Used solely by renderIPv6NetworkAddresses
3178function renderSeparator ($first, $after, $hl_ip)
3179{
3180 $self = __FUNCTION__;
3181 if (strcmp ($first, $after) >= 0)
3182 return;
3183 if ($first->next() == $after)
3184 renderEmptyIPv6 ($first, $hl_ip);
3185 elseif (isset ($hl_ip) && strcmp ($hl_ip, $first) >= 0 && strcmp ($hl_ip, $after) < 0)
3186 { // $hl_ip is inside the range $first - ($after-1)
3187 $self ($first, $hl_ip, $hl_ip);
3188 renderEmptyIPv6 ($hl_ip, $hl_ip);
3189 $self ($hl_ip->next(), $after, $hl_ip);
3190 }
3191 else
3192 echo "<tr><td colspan=3 class=tdleft></td></tr>\n";
3193}
3194
3195// calculates page number which contains given $ip (used by renderIPv6NetworkAddresses)
3196function getPageNumOfIPv6 ($list, $ip, $maxperpage)
3197{
3198 if (intval ($maxperpage) <= 0 || count ($list) <= $maxperpage)
3199 return 0;
3200 $bin_ip = (string)$ip;
3201 $keys = array_keys ($list);
3202 for ($i = 1; $i <= count ($keys); $i++)
3203 if (strcmp ($keys[$i-1], $bin_ip) >= 0)
3204 return intval ($i / $maxperpage);
3205 return intval (count ($list) / $maxperpage);
3206}
3207
3208function renderIPv6NetworkAddresses ($netinfo)
3209{
3210 global $pageno, $tabno, $aac2;
3211 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
3212 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
3213
3214 $hl_ip = new IPv6Address;
3215 if (! isset ($_REQUEST['hl_ipv6_addr']) || ! $hl_ip->parse ($_REQUEST['hl_ipv6_addr']))
3216 $hl_ip = NULL;
00276508 3217 else
65e557dd 3218 addAutoScrollScript ('ip-' . $hl_ip->format());
21ee3351
AA
3219
3220 $prev_ip = $netinfo['ip_bin']; // really this is the next to previosly seen ip.
3221 $addresses = $netinfo['addrlist'];
3222 ksort ($addresses);
3223
3224 // pager
3225 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
3226 if (count ($addresses) > $maxperpage && $maxperpage > 0)
3227 {
3228 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? getPageNumOfIPv6 ($addresses, $hl_ip, $maxperpage) : 0);
3229 $numpages = ceil (count ($addresses) / $maxperpage);
3230 echo "<center><h3>$numpages pages:</h3>";
3231 for ($i=0; $i<$numpages; $i++)
3232 {
3233 if ($i == $page)
3234 echo "<b>$i</b> ";
3235 else
3236 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $i)) . "'>$i</a> ";
3237 }
3238 echo "</center>";
3239 }
3240
3241 $i = 0;
3242 $interruped = FALSE;
3243 foreach ($addresses as $bin_ip => $addr)
3244 {
3245 if (isset ($page))
3246 {
3247 ++$i;
3248 if ($i <= $maxperpage * $page)
3249 continue;
3250 elseif ($i > $maxperpage * ($page + 1))
3251 {
3252 $interruped = TRUE;
3253 break;
3254 }
3255 }
3256
3257 $ipv6 = new IPv6Address ($bin_ip);
3258 if ($ipv6 != $prev_ip)
3259 renderSeparator ($prev_ip, $ipv6, $hl_ip);
3260 $prev_ip = $ipv6->next();
3261
3262 $secondstyle = 'tdleft';
3263 if (isset ($hl_ip) && $hl_ip == $ipv6)
3264 $secondstyle .= ' port_highlight';
3265 echo "<tr class='${addr['class']}'>";
00276508 3266 echo "<td class=tdleft><a name='ip-${addr['ip']}' href='" . makeHref (array ('page' => 'ipv6address', 'ip' => $addr['ip'])) . "'>${addr['ip']}</a></td>";
21ee3351
AA
3267 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
3268 $delim = '';
3269 $prologue = '';
3270 if ( $addr['reserved'] == 'yes')
3271 {
3272 echo "<strong>RESERVED</strong> ";
3273 $delim = '; ';
3274 }
3275 foreach ($addr['allocs'] as $ref)
3276 {
3277 echo $delim . $aac2[$ref['type']];
3278 echo "<a href='" . makeHref (array ('page' => 'object', 'object_id' => $ref['object_id'], 'hl_ipv6_addr' => $addr['ip'])) . "'>";
3279 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
3280 echo "${ref['object_name']}</a>";
3281 $delim = '; ';
3282 }
3283 if ($delim != '')
3284 {
3285 $delim = '';
3286 $prologue = '<br>';
3287 }
3288 echo "</td></tr>\n";
3289 }
3290 if (! $interruped)
3291 renderSeparator ($prev_ip, $netinfo['ip_bin']->get_last_subnet_address ($netinfo['mask'])->next(), $hl_ip);
3292 if (isset ($page))
3293 { // bottom pager
3294 echo "<tr><td colspan=3>";
3295 if ($page > 0)
3296 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page - 1)) . "'><< prev</a> ";
3297 if ($page < $numpages - 1)
3298 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page + 1)) . "'>next >></a> ";
3299 echo "</td></tr>";
3300 }
3301 echo "</table>";
3302}
3303
3304function renderIPNetworkProperties ($id)
e673ee24 3305{
21ee3351
AA
3306 global $pageno;
3307 $netdata = spotEntity ($pageno, $id);
53ef3908 3308 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
e673ee24 3309 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 3310 printOpFormIntro ('editRange');
99ab184f
DO
3311 echo '<tr><td class=tdright><label for=nameinput>Name:</label></td>';
3312 echo "<td class=tdleft><input type=text name=name id=nameinput size=80 maxlength=255 value='";
3313 echo htmlspecialchars ($netdata['name'], ENT_QUOTES, 'UTF-8') . "'></tr>";
3314 echo '<tr><td class=tdright><label for=commentinput>Comment:</label></td>';
3315 echo "<td class=tdleft><textarea name=comment id=commentinput cols=80 rows=25>\n";
3316 echo htmlspecialchars ($netdata['comment'], ENT_QUOTES, 'UTF-8') . "</textarea></tr>";
53ef3908