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