r4024 A patch by Jeroen Benda (#380, JS checkbox helpers)
[racktables] / inc / interface.php
1 <?php
2 /*
3 *
4 * This file contains frontend functions for RackTables.
5 *
6 */
7
8 // Interface function's special.
9 $nextorder['odd'] = 'even';
10 $nextorder['even'] = 'odd';
11
12 // address allocation type
13 $aat = array
14 (
15 'regular' => 'Connected',
16 'virtual' => 'Loopback',
17 'shared' => 'Shared',
18 'router' => 'Router',
19 );
20 // address allocation code, IPv4 addresses and objects view
21 $aac = array
22 (
23 'regular' => '',
24 'virtual' => '<strong>L</strong>',
25 'shared' => '<strong>S</strong>',
26 'router' => '<strong>R</strong>',
27 );
28 // address allocation code, IPv4 networks view
29 $aac2 = array
30 (
31 'regular' => '',
32 'virtual' => '<strong>L:</strong>',
33 'shared' => '<strong>S:</strong>',
34 'router' => '<strong>R:</strong>',
35 );
36
37 $vtdecoder = array
38 (
39 'ondemand' => '',
40 'compulsory' => 'P',
41 # 'alien' => 'NT',
42 );
43
44 $vtoptions = array
45 (
46 'ondemand' => 'auto',
47 'compulsory' => 'permanent',
48 # 'alien' => 'never touch',
49 );
50
51 // 802.1Q deploy queue titles
52 $dqtitle = array
53 (
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',
58 'failed' => 'Failed',
59 'disabled' => 'Sync disabled',
60 'done' => 'Up to date',
61 );
62
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
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;
88 $image['depot']['path'] = 'pix/server.png';
89 $image['depot']['width'] = 218;
90 $image['depot']['height'] = 200;
91 $image['files']['path'] = 'pix/files.png';
92 $image['files']['width'] = 218;
93 $image['files']['height'] = 200;
94 $image['ipv4space']['path'] = 'pix/addressspace.png';
95 $image['ipv4space']['width'] = 218;
96 $image['ipv4space']['height'] = 200;
97 $image['ipv6space']['path'] = 'pix/addressspacev6.png';
98 $image['ipv6space']['width'] = 218;
99 $image['ipv6space']['height'] = 200;
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;
109 $image['8021q']['path'] = 'pix/8021q.png';
110 $image['8021q']['width'] = 218;
111 $image['8021q']['height'] = 200;
112 $image['download']['path'] = 'pix/download.png';
113 $image['download']['width'] = 16;
114 $image['download']['height'] = 16;
115 $image['DOWNLOAD']['path'] = 'pix/download-big.png';
116 $image['DOWNLOAD']['width'] = 32;
117 $image['DOWNLOAD']['height'] = 32;
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;
124 $image['Cut']['path'] = 'pix/tango-edit-cut-22x22.png';
125 $image['Cut']['width'] = 22;
126 $image['Cut']['height'] = 22;
127 $image['CUT']['path'] = 'pix/tango-edit-cut-32x32.png';
128 $image['CUT']['width'] = 32;
129 $image['CUT']['height'] = 32;
130 $image['add']['path'] = 'pix/tango-list-add.png';
131 $image['add']['width'] = 16;
132 $image['add']['height'] = 16;
133 $image['ADD']['path'] = 'pix/tango-list-add-big.png';
134 $image['ADD']['width'] = 32;
135 $image['ADD']['height'] = 32;
136 $image['delete']['path'] = 'pix/tango-list-remove.png';
137 $image['delete']['width'] = 16;
138 $image['delete']['height'] = 16;
139 $image['DELETE']['path'] = 'pix/tango-list-remove-32x32.png';
140 $image['DELETE']['width'] = 32;
141 $image['DELETE']['height'] = 32;
142 $image['destroy']['path'] = 'pix/tango-user-trash-16x16.png';
143 $image['destroy']['width'] = 16;
144 $image['destroy']['height'] = 16;
145 $image['nodestroy']['path'] = 'pix/tango-user-trash-16x16-gray.png';
146 $image['nodestroy']['width'] = 16;
147 $image['nodestroy']['height'] = 16;
148 $image['NODESTROY']['path'] = 'pix/tango-user-trash-32x32-gray.png';
149 $image['NODESTROY']['width'] = 32;
150 $image['NODESTROY']['height'] = 32;
151 $image['DESTROY']['path'] = 'pix/tango-user-trash-32x32.png';
152 $image['DESTROY']['width'] = 32;
153 $image['DESTROY']['height'] = 32;
154 $image['nodelete']['path'] = 'pix/tango-list-remove-shadow.png';
155 $image['nodelete']['width'] = 16;
156 $image['nodelete']['height'] = 16;
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;
163 $image['find']['path'] = 'pix/tango-system-search.png';
164 $image['find']['width'] = 16;
165 $image['find']['height'] = 16;
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;
172 $image['COMMIT']['path'] = 'pix/tango-go-prev-next-32x32.png';
173 $image['COMMIT']['width'] = 32;
174 $image['COMMIT']['height'] = 32;
175 $image['COMMIT gray']['path'] = 'pix/tango-go-prev-next-gray-32x32.png';
176 $image['COMMIT gray']['width'] = 32;
177 $image['COMMIT gray']['height'] = 32;
178 $image['RECALC']['path'] = 'pix/tango-view-refresh-32x32.png';
179 $image['RECALC']['width'] = 32;
180 $image['RECALC']['height'] = 32;
181 $image['clear']['path'] = 'pix/tango-edit-clear.png';
182 $image['clear']['width'] = 16;
183 $image['clear']['height'] = 16;
184 $image['CLEAR']['path'] = 'pix/tango-edit-clear-big.png';
185 $image['CLEAR']['width'] = 32;
186 $image['CLEAR']['height'] = 32;
187 $image['CLEAR gray']['path'] = 'pix/tango-edit-clear-gray-32x32.png';
188 $image['CLEAR gray']['width'] = 32;
189 $image['CLEAR gray']['height'] = 32;
190 $image['save']['path'] = 'pix/tango-document-save-16x16.png';
191 $image['save']['width'] = 16;
192 $image['save']['height'] = 16;
193 $image['SAVE']['path'] = 'pix/tango-document-save-32x32.png';
194 $image['SAVE']['width'] = 32;
195 $image['SAVE']['height'] = 32;
196 $image['NOSAVE']['path'] = 'pix/tango-document-save-32x32-gray.png';
197 $image['NOSAVE']['width'] = 32;
198 $image['NOSAVE']['height'] = 32;
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;
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;
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;
217 $image['dragons']['path'] = 'pix/mitsudragon.png';
218 $image['dragons']['width'] = 195;
219 $image['dragons']['height'] = 33;
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;
229 $image['router']['path'] = 'pix/router.png';
230 $image['router']['width'] = 32;
231 $image['router']['height'] = 32;
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;
238 $image['ATTACH']['path'] = 'pix/tango-mail-attachment-32x32.png';
239 $image['ATTACH']['width'] = 32;
240 $image['ATTACH']['height'] = 32;
241 $image['Attach']['path'] = 'pix/tango-mail-attachment-22x22.png';
242 $image['Attach']['width'] = 22;
243 $image['Attach']['height'] = 22;
244 $image['favorite']['path'] = 'pix/tango-emblem-favorite.png';
245 $image['favorite']['width'] = 16;
246 $image['favorite']['height'] = 16;
247 $image['computer']['path'] = 'pix/tango-computer.png';
248 $image['computer']['width'] = 16;
249 $image['computer']['height'] = 16;
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;
259 $image['text']['path'] = 'pix/tango-text-x-generic-16x16.png';
260 $image['text']['width'] = 16;
261 $image['text']['height'] = 16;
262 $image['NET']['path'] = 'pix/crystal-network_local-32x32.png';
263 $image['NET']['width'] = 32;
264 $image['NET']['height'] = 32;
265 $image['net']['path'] = 'pix/crystal-network_local-16x16.png';
266 $image['net']['width'] = 16;
267 $image['net']['height'] = 16;
268 $image['USER']['path'] = 'pix/crystal-edit-user-32x32.png';
269 $image['USER']['width'] = 32;
270 $image['USER']['height'] = 32;
271 $image['setfilter']['path'] = 'pix/pgadmin3-viewfiltereddata.png';
272 $image['setfilter']['width'] = 32;
273 $image['setfilter']['height'] = 32;
274 $image['setfilter gray']['path'] = 'pix/pgadmin3-viewfiltereddata-grayscale.png';
275 $image['setfilter gray']['width'] = 32;
276 $image['setfilter gray']['height'] = 32;
277 $image['resetfilter']['path'] = 'pix/pgadmin3-viewdata.png';
278 $image['resetfilter']['width'] = 32;
279 $image['resetfilter']['height'] = 32;
280 $image['resetfilter gray']['path'] = 'pix/pgadmin3-viewdata-grayscale.png';
281 $image['resetfilter gray']['width'] = 32;
282 $image['resetfilter gray']['height'] = 32;
283 $image['knight']['path'] = 'pix/smiley_knight.png';
284 $image['knight']['width'] = 72;
285 $image['knight']['height'] = 33;
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;
292 $image['UNLOCK']['path'] = 'pix/crystal-actions-unlock-32x32.png';
293 $image['UNLOCK']['width'] = 32;
294 $image['UNLOCK']['height'] = 32;
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;
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;
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;
319 $image['COPY']['path'] = 'pix/tango-edit-copy-32x32.png';
320 $image['COPY']['width'] = 32;
321 $image['COPY']['height'] = 32;
322
323 // This may be populated later onsite, report rendering function will use it.
324 // See the $systemreport for structure.
325 $localreports = array();
326
327 $CodePressMap = array
328 (
329 'sql' => 'sql',
330 'php' => 'php',
331 'html' => 'html',
332 'css' => 'css',
333 'js' => 'javascript',
334 );
335
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
344 // Main menu.
345 function renderIndexItem ($ypageno) {
346 global $page;
347 if (permitted($ypageno)) {
348 $title = isset ($page[$ypageno]['title']) ? $page[$ypageno]['title'] : dynamic_title_decoder ($ypageno);
349 if (is_array ($title))
350 $title = $title['name'];
351 print " <td>\n";
352 print " <h1><a href='".makeHref(array('page'=>$ypageno))."'>".$title."<br>\n";
353 printImageHREF ($ypageno);
354 print "</a></h1>\n";
355 print " </td>\n";
356 } else {
357 print " <td>&nbsp;</td>\n";
358 }
359 }
360
361 function renderIndex ()
362 {
363 global $indexlayout;
364 ?>
365 <table border=0 cellpadding=0 cellspacing=0 width='100%'>
366 <tr>
367 <td>
368 <div style='text-align: center; margin: 10px; '>
369 <table width='100%' cellspacing=0 cellpadding=20 class=mainmenu border=0>
370 <?php
371 foreach ($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 ?>
382 </table>
383 </div>
384 </td>
385 </tr>
386 </table>
387 <?php
388 }
389
390 function renderRackspace ()
391 {
392 $found_racks = array();
393 $rows = array();
394 $cellfilter = getCellFilter();
395 $rackCount = 0;
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 );
404 $rackCount += count($rackList);
405 }
406
407 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
408 renderCellFilterPortlet ($cellfilter, 'rack', $found_racks);
409 echo '</td><td class=pcright>';
410
411 if (! renderEmptyResults($cellfilter, 'racks', $rackCount))
412 {
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)
436 {
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++;
450 }
451 $order = $nextorder[$order];
452 echo "</tr></table></tr>\n";
453 }
454 echo "</table>\n";
455 }
456 echo "</td></tr></table>\n";
457 }
458
459 function renderRackspaceRowEditor ()
460 {
461 function printNewItemTR ()
462 {
463 printOpFormIntro ('addRow');
464 echo "<tr><td>";
465 printImageHREF ('create', 'Add new row', TRUE);
466 echo "</td><td><input type=text name=name tabindex=100></td><td>";
467 printImageHREF ('create', 'Add new row', TRUE, 101);
468 echo "</td></tr></form>";
469 }
470 startPortlet ('Rows');
471 echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
472 echo "<tr><th>&nbsp;</th><th>Name</th><th>&nbsp;</th></tr>\n";
473 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
474 printNewItemTR();
475 foreach (getRackRows() as $row_id => $row_name)
476 {
477 echo "<tr><td>";
478 if ($rc = count (listCells ('rack', $row_id)))
479 printImageHREF ('nodestroy', "${rc} rack(s) here");
480 else
481 {
482 echo "<a href=\"".makeHrefProcess(array('op'=>'delete', 'row_id'=>$row_id))."\">";
483 printImageHREF ('destroy', 'Delete row');
484 echo "</a>";
485 }
486 printOpFormIntro ('updateRow', array ('row_id' => $row_id));
487 echo "</td><td><input type=text name=name value='${row_name}'></td><td>";
488 printImageHREF ('save', 'Save changes', TRUE);
489 echo "</form></td></tr>\n";
490 }
491 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
492 printNewItemTR();
493 echo "</table><br>\n";
494 finishPortlet();
495 }
496
497 function renderRow ($row_id)
498 {
499 $rowInfo = getRackRowInfo ($row_id);
500 $cellfilter = getCellFilter();
501 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
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>";
507 startPortlet ($rowInfo['name']);
508 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
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";
511 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
512 renderProgressBar (getRSUforRackRow ($rackList));
513 echo "</td></tr>\n";
514 echo "</table><br>\n";
515 finishPortlet();
516 renderCellFilterPortlet ($cellfilter, 'rack', $rackList, 'row_id', $row_id);
517
518 echo "</td><td class=pcright>";
519
520 global $nextorder;
521 $rackwidth = getRackImageWidth() * getConfigVar ('ROW_SCALE');
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;
525 $order = 'odd';
526 startPortlet ('Racks');
527 echo "<table border=0 cellspacing=5 align='center'><tr>";
528 foreach ($rackList as $rack)
529 {
530 if ($rackListIdx % $maxPerRow == 0)
531 {
532 if ($rackListIdx > 0)
533 echo '</tr>';
534 echo '<tr>';
535 }
536 echo "<td align=center class=row_${order}><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
537 echo "<img border=0 width=${rackwidth} height=" . (getRackImageHeight ($rack['height']) * getConfigVar ('ROW_SCALE'));
538 echo " title='${rack['height']} units'";
539 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
540 echo "<br>${rack['name']}</a></td>";
541 $order = $nextorder[$order];
542 $rackListIdx++;
543 }
544 echo "</tr></table>\n";
545 finishPortlet();
546 echo "</td></tr></table>";
547 }
548
549 // This function renders rack as HTML table.
550 function renderRack ($rack_id, $hl_obj_id = 0)
551 {
552 $rackData = spotEntity ('rack', $rack_id);
553 amplifyCell ($rackData);
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);
560 echo "<center><table border=0><tr valign=middle>";
561 echo "<td><h2><a href='".makeHref(array('page'=>'row', 'row_id'=>$rackData['row_id']))."'>${rackData['row_name']}</a> :</h2></td>";
562 // FIXME: use 'bypass'?
563 if ($prev_id != NULL)
564 {
565 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$prev_id))."'>";
566 printImageHREF ('prev', 'previous rack');
567 echo "</a></td>";
568 }
569 echo "<td><h2><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rackData['id']))."'>${rackData['name']}</a></h2></td>";
570 if ($next_id != NULL)
571 {
572 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$next_id))."'>";
573 printImageHREF ('next', 'next rack');
574 echo "</a></td>";
575 }
576 echo "</h2></td></tr></table>\n";
577 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
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";
580 for ($i = $rackData['height']; $i > 0; $i--)
581 {
582 echo "<tr><th>${i}</th>";
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':
599 $objectData = spotEntity ('object', $rackData[$i][$locidx]['object_id']);
600 if (strlen ($objectData['asset_no']))
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.
605 if ($objectData['name'] != $objectData['label'] and strlen ($objectData['label']))
606 $suffix = ", visible label is \"${objectData['label']}\"'>";
607 else
608 $suffix = "'>";
609 echo $prefix . $suffix;
610 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$objectData['id']))."'>${objectData['dname']}</a></div>";
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
632 function renderNewRackForm ($row_id)
633 {
634 startPortlet ('Add one');
635 printOpFormIntro ('addRack', array ('got_data' => 'TRUE'));
636 echo '<table border=0 align=center>';
637 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
638 if ($defh == 0)
639 $defh = '';
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>";
642 renderNewEntityTags ('rack');
643 echo "</td></tr>\n";
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";
645 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
646 echo "<tr><td class=submit colspan=2>";
647 printImageHREF ('CREATE', 'Add', TRUE);
648 echo "</td></tr></table></form>";
649 finishPortlet();
650
651 startPortlet ('Add many');
652 printOpFormIntro ('addRack', array ('got_mdata' => 'TRUE'));
653 echo '<table border=0 align=center>';
654 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
655 if ($defh == 0)
656 $defh = '';
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>";
659 renderNewEntityTags ('rack');
660 echo "</td></tr>\n";
661 echo "<tr><th class=tdright>Rack names (*):</th><td class=tdleft><textarea name=rack_names cols=40 rows=25></textarea></td></tr>\n";
662 echo "<tr><td class=submit colspan=2>";
663 printImageHREF ('CREATE', 'Add', TRUE);
664 echo '</form></table>';
665 finishPortlet();
666 }
667
668 function renderEditObjectForm ($object_id)
669 {
670 global $pageno;
671 $object = spotEntity ('object', $object_id);
672 startPortlet ();
673 printOpFormIntro ('update');
674
675 // static attributes
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>";
679 printNiftySelect (cookOptgroups (readChapter (CHAP_OBJTYPE, 'o')), array ('name' => 'object_type_id'), $object['objtype_id']);
680 echo "</td></tr>\n";
681 // baseline info
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";
686 // optional attributes
687 $values = getAttrValues ($object_id);
688 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
689 if (count($values) > 0)
690 {
691 $i = 0;
692 foreach ($values as $record)
693 {
694 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
695 echo '<tr><td>';
696 if (strlen ($record['value']))
697 {
698 echo "<a href='".makeHrefProcess(array('op'=>'clearSticker', 'object_id'=>$object_id, 'attr_id'=>$record['id']))."'>";
699 printImageHREF ('clear', 'Clear value');
700 echo '</a>';
701 }
702 else
703 echo '&nbsp;';
704 echo '</td>';
705 echo "<th class=sticker>${record['name']}:</th><td class=tdleft>";
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':
714 $chapter = readChapter ($record['chapter_id'], 'o');
715 $chapter[0] = '-- NOT SET --';
716 $chapter = cookOptgroups ($chapter, $object['objtype_id'], $record['key']);
717 printNiftySelect ($chapter, array ('name' => "${i}_value"), $record['key']);
718 break;
719 }
720 echo "</td></tr>\n";
721 $i++;
722 }
723 }
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";
728 echo "<tr><td>&nbsp;</td><th class=tdright>Actions:</th><td class=tdleft>";
729 echo "<a href='".
730 makeHrefProcess(array('op'=>'deleteObject', 'page'=>'depot', 'tab'=>'addmore', 'object_id'=>$object_id)).
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";
737 echo "<tr><td colspan=3><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
738
739 echo "<tr><th class=submit colspan=3>";
740 printImageHREF ('SAVE', 'Save changes', TRUE);
741 echo "</form></th></tr></table>\n";
742 finishPortlet();
743
744 echo '<table border=0 width=100%><tr><td>';
745 startPortlet ('history');
746 renderHistory ($pageno, $object_id);
747 finishPortlet();
748 echo '</td></tr></table>';
749 }
750
751 // This is a clone of renderEditObjectForm().
752 function renderEditRackForm ($rack_id)
753 {
754 global $pageno;
755 $rack = spotEntity ('rack', $rack_id);
756 amplifyCell ($rack);
757
758 startPortlet ('Rack attributes');
759 printOpFormIntro ('updateRack');
760 echo '<table border=0 align=center>';
761 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
762 printSelect (getRackRows(), array ('name' => 'rack_row_id'), $rack['row_id']);
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";
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 }
773 echo "<tr><td class=submit colspan=2>";
774 printImageHREF ('SAVE', 'Save changes', TRUE);
775 echo "</td></tr>\n";
776 echo '</form></table><br>';
777 finishPortlet();
778
779 startPortlet ('History');
780 renderHistory ($pageno, $rack_id);
781 finishPortlet();
782 }
783
784 function printSelect ($optionList, $select_attrs = array(), $selected_id = NULL, $autocomplete = false)
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.
790 function getSelect ($optionList, $select_attrs = array(), $selected_id = NULL)
791 {
792 $ret = '';
793 if (!array_key_exists ('name', $select_attrs))
794 return '';
795 // handle two corner cases in a specific way
796 if (count ($optionList) == 0)
797 return '(none)';
798 if (count ($optionList) == 1)
799 {
800 $value = current (array_keys ($optionList));
801 return "<input type=hidden name=${select_attrs['name']} id=${select_attrs['name']} value=${value}>" . current ($optionList);
802 }
803 if (!array_key_exists ('id', $select_attrs))
804 $select_attrs['id'] = $select_attrs['name'];
805 $ret .= '<select';
806 foreach ($select_attrs as $attr_name => $attr_value)
807 $ret .= " ${attr_name}=${attr_value}";
808 $ret .= '>';
809 foreach ($optionList as $dict_key => $dict_value)
810 $ret .= "<option value='${dict_key}'" . ($dict_key == $selected_id ? ' selected' : '') . ">${dict_value}</option>";
811 $ret .= '</select>';
812 return $ret;
813 }
814
815 function printNiftySelect ($groupList, $select_attrs = array(), $selected_id = NULL, $autocomplete = false)
816 {
817 echo getNiftySelect ($groupList, $select_attrs, $selected_id);
818 }
819
820 // Input is a cooked list of OPTGROUPs, each with own sub-list of OPTIONs in the same
821 // format as printSelect() expects.
822 function getNiftySelect ($groupList, $select_attrs, $selected_id = NULL)
823 {
824 // special treatment for ungrouped data
825 if (count ($groupList) == 1 and isset ($groupList['other']))
826 return getSelect ($groupList['other'], $select_attrs, $selected_id);
827 if (!array_key_exists ('name', $select_attrs))
828 return '';
829 if (!array_key_exists ('id', $select_attrs))
830 $select_attrs['id'] = $select_attrs['name'];
831 $ret = '<select';
832 foreach ($select_attrs as $attr_name => $attr_value)
833 $ret .= " ${attr_name}=${attr_value}";
834 $ret .= '>';
835 foreach ($groupList as $groupname => $groupdata)
836 {
837 $ret .= "<optgroup label='${groupname}'>";
838 foreach ($groupdata as $dict_key => $dict_value)
839 $ret .= "<option value='${dict_key}'" . ($dict_key == $selected_id ? ' selected' : '') . ">${dict_value}</option>";
840 $ret .= '</optgroup>';
841 }
842 $ret .= '</select>';
843 return $ret;
844 }
845
846 // used by renderGridForm() and renderRackPage()
847 function 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";
854 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
855 renderProgressBar (getRSUforRack ($rackData));
856 echo "</td></tr>\n";
857 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
858 echo count ($rackData['mountedObjects']);
859 echo "</td></tr>\n";
860 printTagTRs ($rackData, makeHref(array('page'=>'rackspace', 'tab'=>'default'))."&");
861 if (strlen ($rackData['comment']))
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
867 // This is a universal editor of rack design/waste.
868 // FIXME: switch to using printOpFormIntro()
869 function renderGridForm ($rack_id, $filter, $header, $submit, $state1, $state2)
870 {
871 $rackData = spotEntity ('rack', $rack_id);
872 amplifyCell ($rackData);
873 $filter ($rackData);
874 markupObjectProblems ($rackData);
875
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%'>";
883 renderRackInfoPortlet ($rackData);
884 echo "</td>\n";
885 echo "<td class=pcright>";
886
887 // Grid form.
888 startPortlet ($header);
889 echo "<center>\n";
890 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
891 echo "<tr><th width='10%'>&nbsp;</th>";
892 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
893 echo "<th width='50%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
894 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
895 printOpFormIntro ('updateRack');
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();
901 echo "</td></tr></table>\n";
902 }
903
904 function renderRackDesign ($rack_id)
905 {
906 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
907 }
908
909 function renderRackProblems ($rack_id)
910 {
911 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
912 }
913
914 function startPortlet ($title = '')
915 {
916 echo "<div class=portlet><h2>${title}</h2>";
917 }
918
919 function finishPortlet ()
920 {
921 echo "</div>\n";
922 }
923
924 function renderRackObject ($object_id)
925 {
926 global $nextorder, $aac;
927 $info = spotEntity ('object', $object_id);
928 // FIXME: employ amplifyCell() instead of calling loader functions directly
929 amplifyCell ($info);
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>";
935 startPortlet ('summary');
936 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
937 if (strlen ($info['name']))
938 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
939 // FIXME: don't call spotEntity() each time, do it once in the beginning.
940 elseif (considerConfiguredConstraint ($info, 'NAMEWARN_LISTSRC'))
941 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
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 ));
948 echo "'>" . decodeObjectType ($info['objtype_id'], 'o') . '</a></td></tr>';
949 if (strlen ($info['asset_no']))
950 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
951 // FIXME: ditto
952 elseif (considerConfiguredConstraint ($info, 'ASSETWARN_LISTSRC'))
953 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
954 if (strlen ($info['label']))
955 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
956 if (strlen ($info['barcode']))
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";
960 foreach (getAttrValues ($object_id) as $attr_id => $record)
961 if (strlen ($record['value']))
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 }
967 printTagTRs
968 (
969 $info,
970 makeHref
971 (
972 array
973 (
974 'page'=>'depot',
975 'tab'=>'default',
976 'andor' => 'and',
977 'cfe' => '{$typeid_' . $info['objtype_id'] . '}',
978 )
979 )."&"
980 );
981 echo "</table><br>\n";
982 finishPortlet();
983
984 if (strlen ($info['comment']))
985 {
986 startPortlet ('Comment');
987 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
988 finishPortlet ();
989 }
990
991 renderFilesPortlet ('object', $object_id);
992
993 if (count ($info['ports']))
994 {
995 startPortlet ('ports and links');
996 $hl_port_id = 0;
997 if (isset ($_REQUEST['hl_port_id']))
998 {
999 assertUIntArg ('hl_port_id');
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>';
1004 echo '<th class=tdleft>Interface</th><th class=tdleft>L2 address</th>';
1005 echo '<th class=tdcenter colspan=2>Remote object and port</th>';
1006 echo '<th class=tdleft>Cable ID</th></tr>';
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>";
1013 echo formatPortIIFOIF ($port) . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
1014 if ($port['remote_object_id'])
1015 {
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>";
1018 echo "<td class=tdleft>${port['remote_name']}</td>";
1019 echo "<td class='tdleft rsvtext'>${port['cableid']}</td>";
1020 }
1021 elseif (strlen ($port['reservation_comment']))
1022 {
1023 echo "<td class=tdleft><b>Reserved:</b></td>";
1024 echo "<td class='tdleft rsvtext'>${port['reservation_comment']}</td><td>&nbsp;</td>";
1025 }
1026 else
1027 echo '<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>';
1028 echo "</tr>";
1029 }
1030 echo "</table><br>";
1031 finishPortlet();
1032 }
1033
1034 if (count ($info['ipv4']) + count ($info['ipv6']))
1035 {
1036 startPortlet ('IP addresses');
1037 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1038 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1039 echo "<tr><th>OS interface</th><th>IP address</th><th>network</th><th>routed by</th><th>peers</th></tr>\n";
1040 else
1041 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
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)
1062 {
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>";
1098 else
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')
1107 {
1108 if (NULL === $netid)
1109 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1110 else
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 }
1125 }
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";
1145 }
1146 }
1147 echo "</table><br>\n";
1148 finishPortlet();
1149 }
1150
1151 $forwards = $info['nat4'];
1152 if (count($forwards['in']) or count($forwards['out']))
1153 {
1154 startPortlet('NATv4');
1155
1156 if (count($forwards['out']))
1157 {
1158
1159 echo "<h3>locally performed NAT</h3>";
1160
1161 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
1162 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
1163
1164 foreach ($forwards['out'] as $pf)
1165 {
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 }
1173 echo "<tr class='$class'>";
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>";
1176 $address = getIPv4Address ($pf['remoteip']);
1177 echo "<td class='description'>";
1178 if (count ($address['allocs']))
1179 foreach($address['allocs'] as $bond)
1180 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
1181 elseif (strlen ($pf['remote_addr_name']))
1182 echo '(' . $pf['remote_addr_name'] . ')';
1183 echo "</td><td class='description'>${pf['description']}</td></tr>";
1184 }
1185 echo "</table><br><br>";
1186 }
1187 if (count($forwards['in']))
1188 {
1189 echo "<h3>arriving NAT connections</h3>";
1190 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
1191 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
1192 foreach ($forwards['in'] as $pf)
1193 {
1194 echo "<tr>";
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>";
1198 echo "<td class='description'>${pf['description']}</td></tr>";
1199 }
1200 echo "</table><br><br>";
1201 }
1202 finishPortlet();
1203 }
1204
1205 $pools = $info['ipv4rspools'];
1206 if (count ($pools))
1207 {
1208 $order = 'odd';
1209 startPortlet ('Real server pools (' . count ($pools) . ')');
1210 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
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";
1212 foreach ($pools as $vs_id => $info)
1213 {
1214 echo "<tr valign=top class=row_${order}><td class=tdleft>";
1215 renderCell (spotEntity ('ipv4vs', $vs_id));
1216 echo "</td><td class=tdleft>";
1217 renderCell (spotEntity ('ipv4rspool', $info['pool_id']));
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>";
1221 echo "<td class=slbconf>${info['prio']}</td>";
1222 echo "</tr>\n";
1223 $order = $nextorder[$order];
1224 }
1225 echo "</table>\n";
1226 finishPortlet();
1227 }
1228 echo "</td>\n";
1229
1230 // After left column we have (surprise!) right column with rackspace portlet only.
1231 echo "<td class=pcright>";
1232 // rackspace portlet
1233 startPortlet ('rackspace allocation');
1234 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1235 renderRack ($rack_id, $object_id);
1236 echo '<br>';
1237 finishPortlet();
1238 echo "</td></tr>";
1239 echo "</table>\n";
1240 }
1241
1242 function renderRackMultiSelect ($sname, $racks, $selected)
1243 {
1244 // Transform the given flat list into a list of groups, each representing a rack row.
1245 $rdata = array();
1246 foreach ($racks as $rack)
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'];
1251 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementsByName(\"updateObjectAllocation\")[0].submit()'>\n";
1252 foreach ($rdata as $optgroup => $racklist)
1253 {
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 }
1262 }
1263 echo "</select>\n";
1264 }
1265
1266 // This function renders a form for port edition.
1267 function renderPortsForObject ($object_id)
1268 {
1269 $prefs = getPortListPrefs();
1270 function printNewItemTR ($prefs)
1271 {
1272 printOpFormIntro ('addPort');
1273 echo "<tr><td>";
1274 printImageHREF ('add', 'add a port', TRUE);
1275 echo "</td><td><input type=text size=8 name=port_name tabindex=100></td>\n";
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";
1279 echo "<td colspan=3>&nbsp;</td><td>";
1280 printImageHREF ('add', 'add a port', TRUE, 104);
1281 echo "</td></tr></form>";
1282 }
1283 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes' || getConfigVar('ENABLE_BULKPORT_FORM') == 'yes' )
1284 startPortlet ('Ports and interfaces');
1285 else
1286 echo '<br>';
1287 $object = spotEntity ('object', $object_id);
1288 amplifyCell ($object);
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
1307 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1308 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>L2 address</th>";
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";
1310 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1311 printNewItemTR ($prefs);
1312 foreach ($object['ports'] as $port)
1313 {
1314 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
1315 echo "<tr><td><a href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id'], 'object_id'=>$object_id, 'port_name'=>$port['name']))."'>";
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>";
1319 echo "<td><input type=text name=label value='${port['label']}'></td>";
1320 if (!$port['remote_object_id'])
1321 {
1322 echo '<td>';
1323 if ($port['iif_id'] != 1)
1324 echo '<label>' . $port['iif_name'] . ' ';
1325 printSelect (getExistingPortTypeOptions ($port['id']), array ('name' => 'port_type_id'), $port['oif_id']);
1326 if ($port['iif_id'] != 1)
1327 echo '</label>';
1328 echo '</td>';
1329 }
1330 else
1331 {
1332 echo "<input type=hidden name=port_type_id value='${port['oif_id']}'><td class=tdleft>";
1333 echo formatPortIIFOIF ($port) . '</td>';
1334 }
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";
1338 if ($port['remote_object_id'])
1339 {
1340 $remote_object = spotEntity ('object', $port['remote_object_id']);
1341 echo "<td>${port['cableid']}&nbsp;<a href='".makeHref(array('page'=>'object', 'object_id'=>$port['remote_object_id']))."'>${remote_object['dname']}</a></td>";
1342 echo "<td>${port['remote_name']}<input type=hidden name=reservation_comment value=''></td>";
1343 echo "<td class=tdcenter><a href='".
1344 makeHrefProcess(array(
1345 'op'=>'unlinkPort',
1346 'port_id'=>$port['id'],
1347 'remote_port_id' => $port['remote_id'],
1348 'object_id'=>$object_id)).
1349 "'>";
1350 printImageHREF ('cut', 'Unlink this port');
1351 echo "</a></td>";
1352 }
1353 elseif (strlen ($port['reservation_comment']))
1354 {
1355 echo "<td><b>Reserved:</b></td>";
1356 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
1357 echo "<td class=tdcenter><a href='".
1358 makeHrefProcess(array(
1359 'op'=>'useup',
1360 'port_id'=>$port['id'],
1361 'object_id'=>$object_id)).
1362 "'>";
1363 printImageHREF ('clear', 'Use up this port');
1364 echo "</a></td>";
1365 }
1366 else
1367 {
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'],
1373 'in_rack' => 'n',
1374 );
1375 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
1376 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
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>
1386 printImageHREF ('plug', 'Link this port');
1387 echo "</span>";
1388 echo " <input type=text name=reservation_comment></td>\n";
1389 }
1390 echo "<td>";
1391 printImageHREF ('save', 'Save changes', TRUE);
1392 echo "</td></form></tr>\n";
1393 }
1394 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1395 printNewItemTR ($prefs);
1396 echo "</table><br>\n";
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 }
1414 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes')
1415 finishPortlet();
1416 if (getConfigVar('ENABLE_MULTIPORT_FORM') != 'yes')
1417 return;
1418
1419 startPortlet ('Add/update multiple ports');
1420 printOpFormIntro ('addMultiPorts');
1421 echo 'Format: <select name=format tabindex=201>';
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>';
1424 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
1425 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
1426 echo "</select>";
1427 echo 'Default port type: ';
1428 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type', 'tabindex' => 202), $prefs['selected']);
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";
1431 echo '</form>';
1432 finishPortlet();
1433 }
1434
1435 function renderIPv4ForObject ($object_id)
1436 {
1437 function printNewItemTR ()
1438 {
1439 global $aat;
1440 printOpFormIntro ('addIPv4Allocation');
1441 echo "<tr><td>";
1442 printImageHREF ('add', 'allocate', TRUE);
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";
1446 echo "<td colspan=2>&nbsp;</td><td>";
1447 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), 'regular');
1448 echo "</td><td>&nbsp;</td><td>";
1449 printImageHREF ('add', 'allocate', TRUE, 103);
1450 echo "</td></tr></form>";
1451 }
1452 $focus = spotEntity ('object', $object_id);
1453 amplifyCell ($focus);
1454 global $aat;
1455 startPortlet ('Allocations');
1456 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1457 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1458 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1459 echo '<th>network</th><th>routed by</th>';
1460 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1461
1462 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1463 printNewItemTR();
1464 foreach ($focus['ipv4'] as $dottedquad => $alloc)
1465 {
1466 $class = $alloc['addrinfo']['class'];
1467 $netid = getIPv4AddressNetworkId ($dottedquad);
1468 if (NULL !== $netid)
1469 {
1470 $netinfo = spotEntity ('ipv4net', $netid);
1471 loadIPv4AddrList ($netinfo);
1472 }
1473 printOpFormIntro ('updIPv4Allocation', array ('ip' => $dottedquad));
1474 echo "<tr class='$class' valign=top><td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$object_id))."'>";
1475 printImageHREF ('delete', 'Delete this IPv4 address');
1476 echo "</a></td>";
1477 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td><td class=tdleft>";
1478 if (NULL !== $netid)
1479 echo "<a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$dottedquad))."'>${dottedquad}</a>";
1480 else
1481 echo $dottedquad;
1482 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1483 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1484 if (strlen ($alloc['addrinfo']['name']))
1485 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1486 echo '</td>';
1487 // FIXME: this a copy-and-paste from renderRackObject()
1488 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1489 {
1490 if (NULL === $netid)
1491 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1492 else
1493 {
1494 echo '<td>';
1495 renderCell ($netinfo);
1496 echo '</td>';
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>";
1506 }
1507 }
1508 echo '<td>';
1509 printSelect ($aat, array ('name' => 'bond_type'), $alloc['type']);
1510 echo "</td><td>";
1511 $prefix = '';
1512 if ($alloc['addrinfo']['reserved'] == 'yes')
1513 {
1514 echo $prefix . '<strong>RESERVED</strong>';
1515 $prefix = '; ';
1516 }
1517 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1518 {
1519 if ($allocpeer['object_id'] == $object_id)
1520 continue;
1521 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1522 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
1523 echo $allocpeer['osif'] . '@';
1524 echo $allocpeer['object_name'] . '</a>';
1525 $prefix = '; ';
1526 }
1527 echo "</td><td>";
1528 printImageHREF ('save', 'Save changes', TRUE);
1529 echo "</td></form></tr>\n";
1530 }
1531 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1532 printNewItemTR();
1533
1534 echo "</table><br>\n";
1535 finishPortlet();
1536
1537 }
1538
1539 function 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
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
1649 function showMessageOrError ()
1650 {
1651 if (!isset ($_SESSION['log']))
1652 return;
1653 $log = $_SESSION['log'];
1654 switch (TRUE)
1655 {
1656 case !isset ($log['v']):
1657 case $log['v'] == 1:
1658 foreach ($log as $key => $record)
1659 if ($key !== 'v')
1660 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1661 break;
1662 case $log['v'] == 2:
1663 $msginfo = array
1664 (
1665 // records 0~99 with success messages
1666 0 => array ('code' => 'success', 'format' => '%s'),
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.'),
1707 41 => array ('code' => 'success', 'format' => 'uplink ports reverb queued'),
1708 // ...
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'),
1724 58 => array ('code' => 'success', 'format' => "Deleted tag '%s'."),
1725 59 => array ('code' => 'success', 'format' => "Created tag '%s'."),
1726 60 => array ('code' => 'success', 'format' => "Updated tag '%s'."),
1727 61 => array ('code' => 'success', 'format' => 'Password changed successfully.'),
1728 62 => array ('code' => 'success', 'format' => 'gw: %s'),
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'),
1731 65 => array ('code' => 'success', 'format' => "Added new rack '%s'"),
1732 66 => array ('code' => 'success', 'format' => "File sent Ok via handler '%s'"),
1733 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1734 68 => array ('code' => 'success', 'format' => "Updated rack '%s'"),
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'),
1738 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
1739 73 => array ('code' => 'success', 'format' => 'File "%s" was deleted successfully'),
1740 74 => array ('code' => 'success', 'format' => 'Record "%s" was added successfully'),
1741 75 => array ('code' => 'success', 'format' => 'Row "%s" was updated successfully'),
1742 76 => array ('code' => 'success', 'format' => 'Object "%s" was deleted successfully'),
1743 77 => array ('code' => 'success', 'format' => 'Record "%s" was deleted successfully'),
1744 78 => array ('code' => 'success', 'format' => 'File "%s" saved Ok'),
1745 79 => array ('code' => 'success', 'format' => 'Rack "%s" was deleted successfully'),
1746 80 => array ('code' => 'success', 'format' => "Added new object '%s'"),
1747 81 => array ('code' => 'success', 'format' => "SNMP: completed '%s' work"),
1748 82 => array ('code' => 'success', 'format' => "Bulk port creation was successful. %u ports created, %u failed"),
1749 83 => array ('code' => 'success', 'format' => 'Object "%s" was reset successfully'),
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'),
1753 87 => array ('code' => 'success', 'format' => '802.1Q recalculate: %d ports changed on %d switches'),
1754 // records 100~199 with fatal error messages
1755 100 => array ('code' => 'error', 'format' => '%s'),
1756 101 => array ('code' => 'error', 'format' => 'Port name cannot be empty'),
1757 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
1758 103 => array ('code' => 'error', 'format' => 'User not found!'),
1759 104 => array ('code' => 'error', 'format' => "Error updating user account '%s'"),
1760 105 => array ('code' => 'error', 'format' => 'default VLAN cannot be changed'),
1761 // ...
1762 107 => array ('code' => 'error', 'format' => 'Assertion failed: %s'),
1763 108 => array ('code' => 'error', 'format' => 'Database error: %s'),
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'),
1796 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u record(s)'),
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'"),
1801 146 => array ('code' => 'error', 'format' => 'Error deleting record "%s"'),
1802 147 => array ('code' => 'error', 'format' => "Could not create tag '%s'"),
1803 148 => array ('code' => 'error', 'format' => "Could not update tag '%s'"),
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'),
1812 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
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'),
1819 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
1820 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1821 166 => array ('code' => 'error', 'format' => 'gw: %s'),
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'),
1825 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1826 171 => array ('code' => 'error', 'format' => "Failed creating rack '%s'. Already exists in this row?"),
1827 172 => array ('code' => 'error', 'format' => 'Malformed request'),
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'),
1832 177 => array ('code' => 'error', 'format' => 'commitUpdateRack() failed'),
1833 178 => array ('code' => 'error', 'format' => 'file not found'),
1834 179 => array ('code' => 'error', 'format' => 'Expired form has been declined.'),
1835 180 => array ('code' => 'error', 'format' => 'Error saving file, all changes lost!'),
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'),
1838 183 => array ('code' => 'error', 'format' => "Tag id '%s' does not exist."),
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.'),
1842 187 => array ('code' => 'error', 'format' => "Internal error in function '%s'"),
1843 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1844 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
1845 190 => array ('code' => 'error', 'format' => "Invalid VLAN ID '%s'"),
1846 191 => array ('code' => 'error', 'format' => "deploy was blocked due to conflicting configuration versions"),
1847 192 => array ('code' => 'error', 'format' => "Permission denied"),
1848
1849 // records 200~299 with warnings
1850 200 => array ('code' => 'warning', 'format' => '%s'),
1851 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1852 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
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'),
1856 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
1857 207 => array ('code' => 'warning', 'format' => 'Ignored empty request'),
1858
1859 // records 300~399 with notices
1860 300 => array ('code' => 'neutral', 'format' => '%s'),
1861
1862 );
1863 // Handle the arguments. Is there any better way to do it?
1864 foreach ($log['m'] as $record)
1865 {
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 }
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 }
1919 unset($_SESSION['log']);
1920 }
1921
1922 /*
1923 The following conditions must be met:
1924 1. We can mount onto free atoms only. This means: if any record for an atom
1925 already exists in RackSpace, it can't be used for mounting.
1926 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1927 and either delete them before unmounting or refuse to unmount the object.
1928 */
1929 function renderRackSpaceForObject ($object_id)
1930 {
1931 // Always process occupied racks plus racks chosen by user. First get racks with
1932 // already allocated rackspace...
1933 $workingRacksData = getResidentRacksData ($object_id);
1934 // ...and then add those chosen by user (if any).
1935 if (isset($_REQUEST['rackmulti']))
1936 foreach ($_REQUEST['rackmulti'] as $cand_id)
1937 if (!isset ($workingRacksData[$cand_id]))
1938 {
1939 $rackData = spotEntity ('rack', $cand_id);
1940 amplifyCell ($rackData);
1941 $workingRacksData[$cand_id] = $rackData;
1942 }
1943
1944 // Main layout starts.
1945 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1946
1947 // Left portlet with rack list.
1948 echo "<td class=pcleft height='1%'>";
1949 startPortlet ('Racks');
1950 $allRacksData = listCells ('rack');
1951 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1952 foreach ($allRacksData as $rack)
1953 if (!array_key_exists ($rack['id'], $workingRacksData))
1954 {
1955 amplifyCell ($rack);
1956 $workingRacksData[$rack['id']] = $rack;
1957 }
1958 foreach (array_keys ($workingRacksData) as $rackId)
1959 applyObjectMountMask ($workingRacksData[$rackId], $object_id);
1960 printOpFormIntro ('updateObjectAllocation');
1961 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1962 echo "<br><br>";
1963 finishPortlet();
1964 echo "</td>";
1965
1966 // Middle portlet with comment and submit.
1967 echo "<td class=pcleft>";
1968 startPortlet ('Comment');
1969 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1970 echo "<input type=submit value='Save' name=got_atoms>\n";
1971 echo "<br><br>";
1972 finishPortlet();
1973 echo "</td>";
1974
1975 // Right portlet with rendered racks. If this form submit is not final, we have to
1976 // reflect the former state of the grid in current form.
1977 echo "<td class=pcright rowspan=2 height='1%'>";
1978 startPortlet ('Working copy');
1979 echo '<table border=0 cellspacing=10 align=center><tr>';
1980 foreach ($workingRacksData as $rack_id => $rackData)
1981 {
1982 // Order is important here: only original allocation is highlighted.
1983 highlightObject ($rackData, $object_id);
1984 markupAtomGrid ($rackData, 'T');
1985 // If we have a form processed, discard user input and show new database
1986 // contents.
1987 if (isset ($_REQUEST['rackmulti'][0])) // is an update
1988 mergeGridFormToRack ($rackData);
1989 echo "<td valign=top>";
1990 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1991 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1992 echo "<tr><th width='10%'>&nbsp;</th>";
1993 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1994 echo "<th width='50%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1995 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1996 renderAtomGrid ($rackData);
1997 echo "<tr><th width='10%'>&nbsp;</th>";
1998 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1999 echo "<th width='50%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
2000 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
2001 echo "</table></center>\n";
2002 echo '</td>';
2003 }
2004 echo "</tr></table>";
2005 finishPortlet();
2006 echo "</td>\n";
2007
2008 echo "</form>\n";
2009 echo "</tr></table>\n";
2010 }
2011
2012 function renderMolecule ($mdata, $object_id)
2013 {
2014 // sort data out
2015 $rackpack = array();
2016 global $loclist;
2017 foreach ($mdata as $rua)
2018 {
2019 $rack_id = $rua['rack_id'];
2020 $unit_no = $rua['unit_no'];
2021 $atom = $rua['atom'];
2022 if (!isset ($rackpack[$rack_id]))
2023 {
2024 $rackData = spotEntity ('rack', $rack_id);
2025 amplifyCell ($rackData);
2026 for ($i = $rackData['height']; $i > 0; $i--)
2027 for ($locidx = 0; $locidx < 3; $locidx++)
2028 $rackData[$i][$locidx]['state'] = 'F';
2029 $rackpack[$rack_id] = $rackData;
2030 }
2031 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
2032 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
2033 }
2034 // now we have some racks to render
2035 foreach ($rackpack as $rackData)
2036 {
2037 markAllSpans ($rackData);
2038 echo "<table class=molecule cellspacing=0>\n";
2039 echo "<caption>${rackData['name']}</caption>\n";
2040 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
2041 for ($i = $rackData['height']; $i > 0; $i--)
2042 {
2043 echo "<tr><th>$i</th>";
2044 for ($locidx = 0; $locidx < 3; $locidx++)
2045 {
2046 $state = $rackData[$i][$locidx]['state'];
2047 echo "<td class=state_${state}>&nbsp;</td>\n";
2048 }
2049 echo "</tr>\n";
2050 }
2051 echo "</table>\n";
2052 }
2053 }
2054
2055 function renderDepot ()
2056 {
2057 global $pageno, $nextorder;
2058 $cellfilter = getCellFilter();
2059 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
2060
2061 echo "<table border=0 class=objectview>\n";
2062 echo "<tr><td class=pcleft>";
2063
2064 if (! renderEmptyResults ($cellfilter, 'objects', count($objects)))
2065 {
2066 startPortlet ('Objects (' . count ($objects) . ')');
2067 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2068 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Row/Rack</th></tr>';
2069 $order = 'odd';
2070 foreach ($objects as $obj)
2071 {
2072 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
2073 $secondclass = 'tdleft port_highlight';
2074 else
2075 $secondclass = 'tdleft';
2076 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>";
2077 if (count ($obj['etags']))
2078 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
2079 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
2080 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
2081 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
2082 if ($obj['rack_id'])
2083 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>";
2084 else
2085 echo "<td class='${secondclass}'>Unmounted</td>";
2086 echo '</tr>';
2087 $order = $nextorder[$order];
2088 }
2089 echo '</table>';
2090 finishPortlet();
2091 }
2092
2093 echo "</td><td class=pcright width='25%'>";
2094
2095 renderCellFilterPortlet ($cellfilter, 'object', $objects);
2096 echo "</td></tr></table>\n";
2097 }
2098
2099 // This function returns TRUE if the result set is too big to be rendered, and no filter is set.
2100 // In this case it renders the describing message instead.
2101 function renderEmptyResults($cellfilter, $entities_name, $count = NULL)
2102 {
2103 if (!$cellfilter['is_empty'])
2104 return FALSE;
2105 if (isset ($_REQUEST['show_all_objects']))
2106 return FALSE;
2107 $max = intval(getConfigVar('MAX_UNFILTERED_ENTITIES'));
2108 if (0 == $max || $count <= $max)
2109 return FALSE;
2110
2111 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
2112 $href_show_all .= htmlspecialchars('&show_all_objects=1');
2113 $suffix = isset ($count) ? " ($count)" : '';
2114 echo <<<END
2115 <p>Please set a filter to display the corresponging $entities_name.
2116 <br><a href="$href_show_all">Show all $entities_name$suffix</a>
2117 END;
2118 return TRUE;
2119 }
2120
2121 // History viewer for history-enabled simple dictionaries.
2122 function renderHistory ($object_type, $object_id)
2123 {
2124 switch ($object_type)
2125 {
2126 case 'row':
2127 $query = "select ctime, user_name, name, comment from RackRowHistory where id = ? order by ctime";
2128 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>rack row comment</th></tr>';
2129 $extra = 3;
2130 break;
2131 case 'rack':
2132 $query =
2133 "select ctime, user_name, rh.name, rr.name as name, rh.height, rh.comment " .
2134 "from RackHistory as rh left join RackRow as rr on rh.row_id = rr.id " .
2135 "where rh.id = ? order by ctime";
2136 $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>';
2137 $extra = 5;
2138 break;
2139 case 'object':
2140 $query =
2141 "select ctime, user_name, RackObjectHistory.name as name, label, barcode, asset_no, has_problems, dict_value, comment " .
2142 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key join Chapter on Dictionary.chapter_id = Chapter.id " .
2143 "where Chapter.name = 'RackObjectType' and RackObjectHistory.id=? order by ctime";
2144 $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>';
2145 $extra = 8;
2146 break;
2147 default:
2148 throw new InvalidArgException ('object_type', $object_type);
2149 }
2150 $result = usePreparedSelectBlade ($query, array ($object_id));
2151 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2152 $order = 'odd';
2153 global $nextorder;
2154 echo $header;
2155 while ($row = $result->fetch (PDO::FETCH_NUM))
2156 {
2157 echo "<tr class=row_${order}><td>${row[0]}</td>";
2158 for ($i = 1; $i <= $extra; $i++)
2159 echo "<td>" . $row[$i] . "</td>";
2160 echo "</tr>\n";
2161 $order = $nextorder[$order];
2162 }
2163 echo "</table><br>\n";
2164 }
2165
2166 function renderRackspaceHistory ()
2167 {
2168 global $nextorder, $pageno, $tabno;
2169 $order = 'odd';
2170 $history = getRackspaceHistory();
2171 // Show the last operation by default.
2172 if (isset ($_REQUEST['op_id']))
2173 $op_id = $_REQUEST['op_id'];
2174 elseif (isset ($history[0]['mo_id']))
2175 $op_id = $history[0]['mo_id'];
2176 else $op_id = NULL;
2177
2178 $omid = NULL;
2179 $nmid = NULL;
2180 $object_id = 1;
2181 if ($op_id)
2182 list ($omid, $nmid) = getOperationMolecules ($op_id);
2183
2184 // Main layout starts.
2185 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2186
2187 // Left top portlet with old allocation.
2188 echo "<tr><td class=pcleft>";
2189 startPortlet ('Old allocation');
2190 if ($omid)
2191 {
2192 $oldMolecule = getMolecule ($omid);
2193 renderMolecule ($oldMolecule, $object_id);
2194 }
2195 else
2196 echo "nothing";
2197 finishPortlet();
2198
2199 echo '</td><td class=pcright>';
2200
2201 // Right top portlet with new allocation
2202 startPortlet ('New allocation');
2203 if ($nmid)
2204 {
2205 $newMolecule = getMolecule ($nmid);
2206 renderMolecule ($newMolecule, $object_id);
2207 }
2208 else
2209 echo "nothing";
2210 finishPortlet();
2211
2212 echo '</td></tr><tr><td colspan=2>';
2213
2214 // Bottom portlet with list
2215
2216 startPortlet ('Rackspace allocation history');
2217 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
2218 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
2219 foreach ($history as $row)
2220 {
2221 if ($row['mo_id'] == $op_id)
2222 $class = 'hl';
2223 else
2224 $class = "row_${order}";
2225 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
2226 echo "<td>${row['user_name']}</td><td>";
2227 renderCell (spotEntity ('object', $row['ro_id']));
2228 echo "</td><td>${row['comment']}</td>\n";
2229 echo "</tr>\n";
2230 $order = $nextorder[$order];
2231 }
2232 echo "</table>\n";
2233 finishPortlet();
2234
2235 echo '</td></tr></table>';
2236 }
2237
2238 function renderIPv4SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
2239 {
2240 $self = __FUNCTION__;
2241 static $vdomlist = NULL;
2242 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2243 $vdomlist = getVLANDomainOptions();
2244 foreach ($tree as $item)
2245 {
2246 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2247 loadIPv4AddrList ($item); // necessary to compute router list and address counter
2248 else
2249 {
2250 $item['addrlist'] = array();
2251 $item['addrc'] = 0;
2252 }
2253 $used = $item['addrc'];
2254 $maxdirect = $item['addrt'];
2255 $maxtotal = binInvMaskFromDec ($item['mask']) + 1;
2256 if (isset ($item['id']))
2257 {
2258 $decor = array ('indent' => $level);
2259 if ($item['symbol'] == 'node-collapsed')
2260 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'] . "#netid" . $item['id'];
2261 elseif ($item['symbol'] == 'node-expanded')
2262 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#netid${item['parent_id']}" : '');
2263 echo "<tr valign=top>";
2264 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
2265 $decor['tdclass'] .= ' port_highlight';
2266 printIPNetInfoTDs ($item, $decor);
2267 echo "<td class=tdcenter>";
2268 if ($target == $item['id'])
2269 echo "<a name=netid${target}></a>";
2270 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2271 {
2272 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2273 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small>';
2274 }
2275 else
2276 echo "<small>${maxdirect}</small>";
2277 echo "</td>";
2278 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2279 {
2280 echo '<td class=tdleft>';
2281 if (count ($item['8021q']))
2282 {
2283 echo '<ul>';
2284 foreach ($item['8021q'] as $binding)
2285 {
2286 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
2287 // FIXME: would formatVLANName() do this?
2288 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
2289 }
2290 echo '</ul>';
2291 }
2292 echo '</td>';
2293 }
2294 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2295 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
2296 echo "</tr>";
2297 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2298 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
2299 }
2300 else
2301 {
2302 echo "<tr valign=top>";
2303 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
2304 echo "<td class=tdcenter>";
2305 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2306 {
2307 renderProgressBar ($used/$maxtotal, 'sparenetwork');
2308 echo "<br><small>${used}/${maxtotal}</small>";
2309 }
2310 else
2311 echo "<small>${maxtotal}</small>";
2312 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2313 echo '</td><td>&nbsp;</td>';
2314 echo "</td><td>&nbsp;</td></tr>";
2315 }
2316 }
2317 }
2318
2319 function renderIPv6SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
2320 {
2321 $self = __FUNCTION__;
2322 static $vdomlist = NULL;
2323 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2324 $vdomlist = getVLANDomainOptions();
2325 foreach ($tree as $item)
2326 {
2327 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2328 loadIPv6AddrList ($item); // necessary to compute router list and address counter
2329 else
2330 {
2331 $item['addrlist'] = array();
2332 $item['addrc'] = 0;
2333 }
2334 if (isset ($item['id']))
2335 {
2336 $decor = array ('indent' => $level);
2337 if ($item['symbol'] == 'node-collapsed')
2338 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'] . "#netid" . $item['id'];
2339 elseif ($item['symbol'] == 'node-expanded')
2340 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#net6id${item['parent_id']}" : '');
2341 echo "<tr valign=top>";
2342 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
2343 $decor['tdclass'] .= ' port_highlight';
2344 printIPNetInfoTDs ($item, $decor);
2345 echo "<td class=tdcenter>";
2346 if ($target == $item['id'])
2347 echo "<a name=netid${target}></a>";
2348 // show net usage
2349 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2350 echo "</td>";
2351 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2352 {
2353 echo '<td class=tdleft>';
2354 if (count ($item['8021q']))
2355 {
2356 echo '<ul>';
2357 foreach ($item['8021q'] as $binding)
2358 {
2359 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
2360 // FIXME: would formatVLANName() do this?
2361 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
2362 }
2363 echo '</ul>';
2364 }
2365 echo '</td>';
2366 }
2367 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2368 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
2369 echo "</tr>";
2370 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2371 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
2372 }
2373 /* do not display spare networks
2374 else
2375 { // display spare networks
2376 echo "<tr valign=top>";
2377 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
2378 echo "<td class=tdcenter>";
2379 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2380 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2381 echo '</td><td>&nbsp;</td>';
2382 echo "</td><td>&nbsp;</td></tr>";
2383 }*/
2384 }
2385 }
2386
2387 // if $used is NULL, returns only human-formatted mask.
2388 // Otherwise returns "$used in/of " . human-formatted-mask
2389 function formatIPv6NetUsage ($used, $mask)
2390 {
2391 $prefixes = array
2392 (
2393 0 => '',
2394 3 => 'k',
2395 6 => 'M',
2396 9 => 'G',
2397 12 => 'T',
2398 15 => 'P',
2399 18 => 'E',
2400 21 => 'Z',
2401 24 => 'Y',
2402 );
2403
2404 if ($mask <= 64)
2405 {
2406 $what = '/64 net';
2407 $preposition = 'in';
2408 $mask += 64;
2409 }
2410 else
2411 {
2412 $what = 'IP';
2413 $preposition = 'of';
2414 }
2415 $what .= (0 == $mask % 64 ? '' : 's');
2416 $addrc = isset ($used) ? "$used $preposition " : '';
2417
2418 $dec_order = intval ((128 - $mask) / 10) * 3;
2419 $mult = isset ($prefixes[$dec_order]) ? $prefixes[$dec_order] : '??';
2420
2421 $cnt = 1 << ((128 - $mask) % 10);
2422 if ($cnt == 1 && $mult == '')
2423 $cnt = 'single';
2424
2425 return "<small>${addrc}${cnt}${mult} ${what}</small>";
2426 }
2427
2428 function renderIPv4Space ()
2429 {
2430 global $pageno, $tabno;
2431 $cellfilter = getCellFilter();
2432 $netlist = listCells ('ipv4net');
2433 $allcount = count ($netlist);
2434 $netlist = filterCellList ($netlist, $cellfilter['expression']);
2435 array_walk ($netlist, 'amplifyCell');
2436
2437 $netcount = count ($netlist);
2438 // expand request can take either natural values or "ALL". Zero means no expanding.
2439 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2440 $tree = prepareIPv4Tree ($netlist, $eid);
2441
2442 echo "<table border=0 class=objectview>\n";
2443 echo "<tr><td class=pcleft>";
2444 if (! renderEmptyResults($cellfilter, 'IPv4 nets', count($tree)))
2445 {
2446 startPortlet ("networks (${netcount})");
2447 echo '<h4>';
2448 if ($eid === 0)
2449 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2450 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2451 $cellfilter['urlextra'] . "'>expand all</a>)";
2452 elseif ($eid === 'ALL')
2453 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2454 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2455 else
2456 {
2457 $netinfo = spotEntity ('ipv4net', $eid);
2458 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2459 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2460 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2461 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2462 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2463 }
2464 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2465 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2466 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2467 echo '<th>VLAN</th>';
2468 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2469 echo "<th>routed by</th>";
2470 echo "</tr>\n";
2471 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2472 renderIPv4SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2473 echo "</table>\n";
2474 finishPortlet();
2475 }
2476
2477 echo '</td><td class=pcright>';
2478 renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
2479 echo "</td></tr></table>\n";
2480 }
2481
2482 function renderIPv6Space ()
2483 {
2484 global $pageno, $tabno;
2485 $cellfilter = getCellFilter();
2486 $netlist = listCells ('ipv6net');
2487 $allcount = count ($netlist);
2488 $netlist = filterCellList ($netlist, $cellfilter['expression']);
2489 array_walk ($netlist, 'amplifyCell');
2490
2491 $netcount = count ($netlist);
2492 // expand request can take either natural values or "ALL". Zero means no expanding.
2493 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2494 $tree = prepareIPv6Tree ($netlist, $eid);
2495
2496 echo "<table border=0 class=objectview>\n";
2497 echo "<tr><td class=pcleft>";
2498 if (! renderEmptyResults($cellfilter, 'IPv6 nets', count($tree)))
2499 {
2500 startPortlet ("networks (${netcount})");
2501 echo '<h4>';
2502 if ($eid === 0)
2503 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2504 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2505 $cellfilter['urlextra'] . "'>expand all</a>)";
2506 elseif ($eid === 'ALL')
2507 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2508 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2509 else
2510 {
2511 $netinfo = spotEntity ('ipv6net', $eid);
2512 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2513 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2514 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2515 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2516 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2517 }
2518 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2519 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2520 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2521 echo '<th>VLAN</th>';
2522 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2523 echo "<th>routed by</th>";
2524 echo "</tr>\n";
2525 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2526 renderIPv6SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2527 echo "</table>\n";
2528 finishPortlet();
2529 }
2530
2531 echo '</td><td class=pcright>';
2532 renderCellFilterPortlet ($cellfilter, 'ipv6net', $netlist);
2533 echo "</td></tr></table>\n";
2534 }
2535
2536 function renderSLBDefConfig()
2537 {
2538 $defaults = getSLBDefaults ();
2539 startPortlet ('SLB default configs');
2540 echo '<table cellspacing=0 cellpadding=5 align=center>';
2541 printOpFormIntro ('save');
2542 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>';
2543 echo '<td rowspan=2>';
2544 printImageHREF ('SAVE', 'Save changes', TRUE);
2545 echo '</td></tr>';
2546 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>';
2547 echo '</form></table>';
2548 finishPortlet();
2549 }
2550
2551 function renderIPv4SLB ()
2552 {
2553 global $page, $nextorder;
2554
2555 startPortlet ('SLB configuration');
2556 echo "<table border=0 width='100%'><tr>";
2557 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2558 echo "<td><h3><a href='".makeHref(array('page'=>$pno))."'>" . $page[$pno]['title'] . "</a></h3></td>";
2559 echo '</tr></table>';
2560 finishPortlet();
2561
2562 $summary = getSLBSummary();
2563 startPortlet ('SLB tactical overview');
2564 // A single id-keyed array isn't used here to preserve existing
2565 // order of LBs returned by getSLBSummary()
2566 $lblist = array();
2567 $lbdname = array();
2568 foreach ($summary as $vipdata)
2569 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2570 if (!in_array ($lb_object_id, $lblist))
2571 {
2572 $oi = spotEntity ('object', $lb_object_id);
2573 $lbdname[$lb_object_id] = $oi['dname'];
2574 $lblist[] = $lb_object_id;
2575 }
2576 if (!count ($summary))
2577 echo 'none configured';
2578 else
2579 {
2580 $order = 'odd';
2581 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2582 echo "<tr valign=top><td>&nbsp;</td>";
2583 foreach ($lblist as $lb_object_id)
2584 {
2585 #echo "<th><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$lb_object_id))."'>" . $lbdname[$lb_object_id] . "</a></th>";
2586 echo '<td>';
2587 renderLBCell ($lb_object_id);
2588 echo '</td>';
2589 }
2590 echo "</tr>\n";
2591 foreach ($summary as $vsid => $vsdata)
2592 {
2593 echo "<tr class=row_${order}><td class=tdleft>";
2594 renderCell (spotEntity ('ipv4vs', $vsid));
2595 echo "</td>";
2596 foreach ($lblist as $lb_object_id)
2597 {
2598 echo '<td class=tdleft>';
2599 if (!isset ($vsdata['lblist'][$lb_object_id]))
2600 echo '&nbsp;';
2601 else
2602 {
2603 echo $vsdata['lblist'][$lb_object_id]['size'];
2604 // echo " (<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$vsdata['lblist'][$lb_object_id]['id'])). "'>";
2605 // echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2606 }
2607 echo '</td>';
2608 }
2609 echo "</tr>\n";
2610 $order = $nextorder[$order];
2611 }
2612 echo "</table>\n";
2613 }
2614 finishPortlet ();
2615 }
2616
2617 function renderIPv4SpaceEditor ()
2618 {
2619 // IPv4 validator
2620 ?>
2621 <script type="text/javascript">
2622 function init() {
2623 document.add_new_range.range.setAttribute('match', "^\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\/\\d\\d?$");
2624
2625 Validate.init();
2626 }
2627 window.onload=init;
2628 </script>
2629 <?php
2630
2631 function printNewItemTR ()
2632 {
2633 startPortlet ('Add new');
2634 echo '<table border=0 cellpadding=10 align=center>';
2635 // This form requires a name, so JavaScript validator can find it.
2636 // No printOpFormIntro() hence
2637 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2638 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2639 // tags column
2640 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2641 renderNewEntityTags ('ipv4net');
2642 echo '</td>';
2643 // inputs column
2644 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2645 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>";
2646 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2647 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2648 echo "<tr><td colspan=2>";
2649 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2650 echo '</td></tr>';
2651 echo "</form></table><br><br>\n";
2652 finishPortlet();
2653 }
2654
2655 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2656 printNewItemTR();
2657 if (count ($addrspaceList = listCells ('ipv4net')))
2658 {
2659 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2660 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2661 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
2662 array_walk ($addrspaceList, 'amplifyCell');
2663 $tree = prepareIPv4Tree ($addrspaceList, 'ALL');
2664 // this is only called for having "trace" set
2665 treeFromList ($addrspaceList);
2666 foreach ($addrspaceList as $netinfo)
2667 {
2668 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2669 // now we have all subnets listed in netinfo
2670 loadIPv4AddrList ($netinfo);
2671 $used = $netinfo['addrc'];
2672 $maxdirect = $netinfo['addrt'];
2673 $maxtotal = binInvMaskFromDec ($netinfo['mask']) + 1;
2674 echo "<tr valign=top><td>";
2675 if (count ($netinfo['addrlist']) && getConfigVar ('IPV4_JAYWALK') == 'no')
2676 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2677 else
2678 {
2679 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2680 printImageHREF ('destroy', 'Delete this prefix');
2681 echo "</a>";
2682 }
2683 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv4net', 'id' => $netinfo['id'])) . '">';
2684 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
2685 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2686 if (count ($netinfo['etags']))
2687 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2688 echo '</td><td>';
2689 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2690 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small></td>';
2691 echo '</tr>';
2692 }
2693 echo "</table>";
2694 finishPortlet();
2695 }
2696 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2697 printNewItemTR();
2698 }
2699
2700 function renderIPv6SpaceEditor ()
2701 {
2702 // IPv6 validator
2703 ?>
2704 <script type="text/javascript">
2705 function init() {
2706 document.add_new_range.range.setAttribute ('match', '^[a-fA-F0-9:]*:[a-fA-F0-9:\\.]*\/\\d{1,3}$');
2707
2708 Validate.init();
2709 }
2710 window.onload=init;
2711 </script>
2712 <?php
2713
2714 function printNewItemTR ()
2715 {
2716 startPortlet ('Add new');
2717 echo '<table border=0 cellpadding=10 align=center>';
2718 // This form requires a name, so JavaScript validator can find it.
2719 // No printOpFormIntro() hence
2720 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2721 echo "<input type=hidden name=op value=addIPv6Prefix>\n";
2722 // tags column
2723 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2724 renderNewEntityTags ('ipv4net');
2725 echo '</td>';
2726 // inputs column
2727 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2728 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>";
2729 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2730 echo "<tr><td colspan=2>";
2731 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2732 echo '</td></tr>';
2733 echo "</form></table><br><br>\n";
2734 finishPortlet();
2735 }
2736
2737 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2738 printNewItemTR();
2739 if (count ($addrspaceList = listCells ('ipv6net')))
2740 {
2741 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2742 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2743 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
2744 array_walk ($addrspaceList, 'amplifyCell');
2745 $tree = prepareIPv6Tree ($addrspaceList, 'ALL');
2746 // this is only called for having "trace" set
2747 treeFromList ($addrspaceList);
2748 foreach ($addrspaceList as $netinfo)
2749 {
2750 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2751 // now we have all subnets listed in netinfo
2752 loadIPv6AddrList ($netinfo);
2753 echo "<tr valign=top><td>";
2754 if (count ($netinfo['addrlist']) && getConfigVar ('IPV4_JAYWALK') == 'no')
2755 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2756 else
2757 {
2758 echo "<a href='".makeHrefProcess (array ('op' => 'delIPv6Prefix', 'id' => $netinfo['id'])) . "'>";
2759 printImageHREF ('destroy', 'Delete this prefix');
2760 echo "</a>";
2761 }
2762 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv6net', 'id' => $netinfo['id'])) . '">';
2763 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
2764 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2765 if (count ($netinfo['etags']))
2766 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2767 echo '</td><td>';
2768 echo formatIPv6NetUsage ($netinfo['addrc'], $netinfo['mask']);
2769 echo '</tr>';
2770 }
2771 echo "</table>";
2772 finishPortlet();
2773 }
2774 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2775 printNewItemTR();
2776 }
2777
2778 function renderIPv4Network ($id)
2779 {
2780 global $pageno, $tabno, $aac2, $netmaskbylen, $wildcardbylen;
2781 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2782 if (isset($_REQUEST['pg']))
2783 $page = $_REQUEST['pg'];
2784 else
2785 $page=0;
2786