r2704 - renderRow(): assertion has already been checked at this point, remove
[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 // Let's have it here, so extensions can add their own images.
38 $image = array();
39 $image['error']['path'] = 'pix/error.png';
40 $image['error']['width'] = 76;
41 $image['error']['height'] = 17;
42 $image['logo']['path'] = 'pix/defaultlogo.png';
43 $image['logo']['width'] = 210;
44 $image['logo']['height'] = 40;
45 $image['rackspace']['path'] = 'pix/racks.png';
46 $image['rackspace']['width'] = 218;
47 $image['rackspace']['height'] = 200;
48 $image['objects']['path'] = 'pix/server.png';
49 $image['objects']['width'] = 218;
50 $image['objects']['height'] = 200;
51 $image['files']['path'] = 'pix/files.png';
52 $image['files']['width'] = 218;
53 $image['files']['height'] = 200;
54 $image['ipv4space']['path'] = 'pix/addressspace.png';
55 $image['ipv4space']['width'] = 218;
56 $image['ipv4space']['height'] = 200;
57 $image['ipv4slb']['path'] = 'pix/slb.png';
58 $image['ipv4slb']['width'] = 218;
59 $image['ipv4slb']['height'] = 200;
60 $image['config']['path'] = 'pix/configuration.png';
61 $image['config']['width'] = 218;
62 $image['config']['height'] = 200;
63 $image['reports']['path'] = 'pix/report.png';
64 $image['reports']['width'] = 218;
65 $image['reports']['height'] = 200;
66 $image['download']['path'] = 'pix/download.png';
67 $image['download']['width'] = 16;
68 $image['download']['height'] = 16;
69 $image['DOWNLOAD']['path'] = 'pix/download-big.png';
70 $image['DOWNLOAD']['width'] = 32;
71 $image['DOWNLOAD']['height'] = 32;
72 $image['plug']['path'] = 'pix/tango-network-wired.png';
73 $image['plug']['width'] = 16;
74 $image['plug']['height'] = 16;
75 $image['cut']['path'] = 'pix/tango-edit-cut-16x16.png';
76 $image['cut']['width'] = 16;
77 $image['cut']['height'] = 16;
78 $image['CUT']['path'] = 'pix/tango-edit-cut-32x32.png';
79 $image['CUT']['width'] = 32;
80 $image['CUT']['height'] = 32;
81 $image['add']['path'] = 'pix/tango-list-add.png';
82 $image['add']['width'] = 16;
83 $image['add']['height'] = 16;
84 $image['ADD']['path'] = 'pix/tango-list-add-big.png';
85 $image['ADD']['width'] = 32;
86 $image['ADD']['height'] = 32;
87 $image['delete']['path'] = 'pix/tango-list-remove.png';
88 $image['delete']['width'] = 16;
89 $image['delete']['height'] = 16;
90 $image['destroy']['path'] = 'pix/tango-user-trash-16x16.png';
91 $image['destroy']['width'] = 16;
92 $image['destroy']['height'] = 16;
93 $image['nodestroy']['path'] = 'pix/tango-user-trash-16x16-gray.png';
94 $image['nodestroy']['width'] = 16;
95 $image['nodestroy']['height'] = 16;
96 $image['NODESTROY']['path'] = 'pix/tango-user-trash-32x32-gray.png';
97 $image['NODESTROY']['width'] = 32;
98 $image['NODESTROY']['height'] = 32;
99 $image['DESTROY']['path'] = 'pix/tango-user-trash-32x32.png';
100 $image['DESTROY']['width'] = 32;
101 $image['DESTROY']['height'] = 32;
102 $image['nodelete']['path'] = 'pix/tango-list-remove-shadow.png';
103 $image['nodelete']['width'] = 16;
104 $image['nodelete']['height'] = 16;
105 $image['inservice']['path'] = 'pix/tango-emblem-system.png';
106 $image['inservice']['width'] = 16;
107 $image['inservice']['height'] = 16;
108 $image['notinservice']['path'] = 'pix/tango-dialog-error.png';
109 $image['notinservice']['width'] = 16;
110 $image['notinservice']['height'] = 16;
111 $image['find']['path'] = 'pix/tango-system-search.png';
112 $image['find']['width'] = 16;
113 $image['find']['height'] = 16;
114 $image['next']['path'] = 'pix/tango-go-next.png';
115 $image['next']['width'] = 32;
116 $image['next']['height'] = 32;
117 $image['prev']['path'] = 'pix/tango-go-previous.png';
118 $image['prev']['width'] = 32;
119 $image['prev']['height'] = 32;
120 $image['clear']['path'] = 'pix/tango-edit-clear.png';
121 $image['clear']['width'] = 16;
122 $image['clear']['height'] = 16;
123 $image['CLEAR']['path'] = 'pix/tango-edit-clear-big.png';
124 $image['CLEAR']['width'] = 32;
125 $image['CLEAR']['height'] = 32;
126 $image['CLEAR gray']['path'] = 'pix/tango-edit-clear-gray-32x32.png';
127 $image['CLEAR gray']['width'] = 32;
128 $image['CLEAR gray']['height'] = 32;
129 $image['save']['path'] = 'pix/tango-document-save.png';
130 $image['save']['width'] = 16;
131 $image['save']['height'] = 16;
132 $image['SAVE']['path'] = 'pix/tango-document-save-big.png';
133 $image['SAVE']['width'] = 32;
134 $image['SAVE']['height'] = 32;
135 $image['create']['path'] = 'pix/tango-document-new.png';
136 $image['create']['width'] = 16;
137 $image['create']['height'] = 16;
138 $image['CREATE']['path'] = 'pix/tango-document-new-big.png';
139 $image['CREATE']['width'] = 32;
140 $image['CREATE']['height'] = 32;
141 $image['DENIED']['path'] = 'pix/tango-dialog-error-big.png';
142 $image['DENIED']['width'] = 32;
143 $image['DENIED']['height'] = 32;
144 $image['apply']['path'] = 'pix/tango-emblem-system.png';
145 $image['apply']['width'] = 16;
146 $image['apply']['height'] = 16;
147 $image['node-collapsed']['path'] = 'pix/node-collapsed.png';
148 $image['node-collapsed']['width'] = 16;
149 $image['node-collapsed']['height'] = 16;
150 $image['node-expanded']['path'] = 'pix/node-expanded.png';
151 $image['node-expanded']['width'] = 16;
152 $image['node-expanded']['height'] = 16;
153 $image['node-expanded-static']['path'] = 'pix/node-expanded-static.png';
154 $image['node-expanded-static']['width'] = 16;
155 $image['node-expanded-static']['height'] = 16;
156 $image['dragons']['path'] = 'pix/mitsudragon.png';
157 $image['dragons']['width'] = 125;
158 $image['dragons']['height'] = 21;
159 $image['LB']['path'] = 'pix/loadbalancer.png';
160 $image['LB']['width'] = 32;
161 $image['LB']['height'] = 32;
162 $image['RS pool']['path'] = 'pix/serverpool.png';
163 $image['RS pool']['width'] = 48;
164 $image['RS pool']['height'] = 16;
165 $image['VS']['path'] = 'pix/servicesign.png';
166 $image['VS']['width'] = 39;
167 $image['VS']['height'] = 62;
168 $image['router']['path'] = 'pix/router.png';
169 $image['router']['width'] = 32;
170 $image['router']['height'] = 32;
171 $image['ATTACH']['path'] = 'pix/crystal-attach-32x32.png';
172 $image['ATTACH']['width'] = 32;
173 $image['ATTACH']['height'] = 32;
174 $image['favorite']['path'] = 'pix/tango-emblem-favorite.png';
175 $image['favorite']['width'] = 16;
176 $image['favorite']['height'] = 16;
177 $image['computer']['path'] = 'pix/tango-computer.png';
178 $image['computer']['width'] = 16;
179 $image['computer']['height'] = 16;
180 $image['empty file']['path'] = 'pix/crystal-file-empty-32x32.png';
181 $image['empty file']['width'] = 32;
182 $image['empty file']['height'] = 32;
183 $image['text file']['path'] = 'pix/crystal-file-text-32x32.png';
184 $image['text file']['width'] = 32;
185 $image['text file']['height'] = 32;
186 $image['image file']['path'] = 'pix/crystal-file-image-32x32.png';
187 $image['image file']['width'] = 32;
188 $image['image file']['height'] = 32;
189 $image['NET']['path'] = 'pix/crystal-network-32x32.png';
190 $image['NET']['width'] = 32;
191 $image['NET']['height'] = 32;
192 $image['USER']['path'] = 'pix/crystal-edit-user-32x32.png';
193 $image['USER']['width'] = 32;
194 $image['USER']['height'] = 32;
195
196 // This may be populated later onsite, report rendering function will use it.
197 // See the $systemreport for structure.
198 $localreports = array();
199 $CodePressMap = array
200 (
201 'sql' => 'sql',
202 'php' => 'php',
203 'html' => 'html',
204 'css' => 'css',
205 'js' => 'javascript',
206 );
207
208 $attrtypes = array
209 (
210 'uint' => '[U] unsigned integer',
211 'float' => '[F] floating point',
212 'string' => '[S] string',
213 'dict' => '[D] dictionary record'
214 );
215
216 // Rack thumbnail image width summands: "front", "interior" and "rear" elements w/o surrounding border.
217 $rtwidth = array
218 (
219 0 => 9,
220 1 => 21,
221 2 => 9
222 );
223
224 // Main menu.
225 function renderIndex ()
226 {
227 ?>
228 <table border=0 cellpadding=0 cellspacing=0 width='100%'>
229 <tr>
230 <td>
231 <div style='text-align: center; margin: 10px; '>
232 <table width='100%' cellspacing=0 cellpadding=30 class=mainmenu border=0>
233 <tr>
234 <td>
235 <h1><a href='<?php echo makeHref(array('page'=>'rackspace')) ?>'>Rackspace<br>
236 <?php printImageHREF ('rackspace'); ?></a></h1>
237 </td>
238 <td>
239 <h1><a href='<?php echo makeHref(array('page'=>'depot')) ?>'>Objects<br>
240 <?php printImageHREF ('objects'); ?></a></h1>
241 </td>
242 <td>
243 <h1><a href='<?php echo makeHref(array('page'=>'ipv4space')) ?>'>IPv4 space<br>
244 <?php printImageHREF ('ipv4space'); ?></a></h1>
245 </td>
246 <td>
247 <h1><a href='<?php echo makeHref(array('page'=>'files')) ?>'>Files<br>
248 <?php printImageHREF ('files'); ?></a></h1>
249 </td>
250 </tr>
251 <tr>
252 <td>
253 <h1><a href='<?php echo makeHref(array('page'=>'config')) ?>'>Configuration<br>
254 <?php printImageHREF ('config'); ?></a></h1>
255 </td>
256 <td>
257 <h1><a href='<?php echo makeHref(array('page'=>'reports')) ?>'>Reports<br>
258 <?php printImageHREF ('reports'); ?></a></h1>
259 </td>
260 <td>
261 <h1><a href='<?php echo makeHref(array('page'=>'ipv4slb')) ?>'>IPv4 SLB<br>
262 <?php printImageHREF ('ipv4slb'); ?></a></h1>
263 </td>
264 <td>&nbsp;</td>
265 </tr>
266 </table>
267 </div>
268 </td>
269 </tr>
270 </table>
271 <?php
272 }
273
274 function renderRackspace ()
275 {
276 showMessageOrError();
277 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
278 $cellfilter = getCellFilter();
279 renderCellFilterPortlet ($cellfilter, 'rack');
280 echo '</td><td class=pcright>';
281 echo '<table border=0 cellpadding=10 cellpadding=1>';
282 // generate thumb gallery
283 global $nextorder;
284 $rackwidth = getRackImageWidth();
285 // Zero value effectively disables the limit.
286 $maxPerRow = getConfigVar ('RACKS_PER_ROW');
287 $order = 'odd';
288 foreach (getRackRows() as $row_id => $row_name)
289 {
290 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
291 if (!count ($rackList) and count ($cellfilter['expression']))
292 continue;
293 $rackListIdx = 0;
294 echo "<tr class=row_${order}><th class=tdleft>";
295 echo "<a href='".makeHref(array('page'=>'row', 'row_id'=>$row_id))."${cellfilter['urlextra']}'>";
296 echo "${row_name}</a></th><td><table border=0 cellspacing=5><tr>";
297 if (!count ($rackList))
298 echo "<td>(empty row)</td>";
299 else
300 foreach ($rackList as $rack)
301 {
302 if ($rackListIdx > 0 and $maxPerRow > 0 and $rackListIdx % $maxPerRow == 0)
303 {
304 echo '</tr></table></tr>';
305 echo "<tr class=row_${order}><th class=tdleft>${row_name} (continued)";
306 echo "</th><td><table border=0 cellspacing=5><tr>";
307 $order = $nextorder[$order];
308 }
309 echo "<td align=center><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
310 echo "<img border=0 width=${rackwidth} height=";
311 echo getRackImageHeight ($rack['height']);
312 echo " title='${rack['height']} units'";
313 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
314 echo "<br>${rack['name']}</a></td>";
315 $rackListIdx++;
316 }
317 echo "</tr></table></tr>\n";
318 }
319 echo "</table>\n";
320 echo "</td></tr></table>\n";
321 }
322
323 function renderRackspaceRowEditor ()
324 {
325 function printNewItemTR ()
326 {
327 printOpFormIntro ('addRow');
328 echo "<tr><td>";
329 printImageHREF ('create', 'Add new row', TRUE);
330 echo "</td><td><input type=text name=name tabindex=100></td><td>";
331 printImageHREF ('create', 'Add new row', TRUE, 101);
332 echo "</td></tr></form>";
333 }
334 showMessageOrError();
335 startPortlet ('Rows');
336 echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
337 echo "<tr><th>&nbsp;</th><th>Name</th><th>&nbsp;</th></tr>\n";
338 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
339 printNewItemTR();
340 foreach (getRackRows() as $row_id => $row_name)
341 {
342 echo "<tr><td>";
343 if ($rc = count (listCells ('rack', $row_id)))
344 printImageHREF ('nodestroy', "${rc} rack(s) here");
345 else
346 {
347 echo "<a href=\"".makeHrefProcess(array('op'=>'delete', 'row_id'=>$row_id))."\">";
348 printImageHREF ('destroy', 'Delete row');
349 echo "</a>";
350 }
351 printOpFormIntro ('updateRow', array ('row_id' => $row_id));
352 echo "</td><td><input type=text name=name value='${row_name}'></td><td>";
353 printImageHREF ('save', 'Save changes', TRUE);
354 echo "</form></td></tr>\n";
355 }
356 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
357 printNewItemTR();
358 echo "</table><br>\n";
359 finishPortlet();
360 }
361
362 function renderRow ($row_id)
363 {
364 if (($rowInfo = getRackRowInfo ($row_id)) == NULL)
365 {
366 showError ('getRackRowInfo() failed', __FUNCTION__);
367 return;
368 }
369 $cellfilter = getCellFilter();
370 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
371 // Main layout starts.
372 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
373
374 // Left portlet with row information.
375 echo "<tr><td class=pcleft>";
376 startPortlet ($rowInfo['name']);
377 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
378 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
379 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
380 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
381 renderProgressBar (getRSUforRackRow ($rackList));
382 echo "</td></tr>\n";
383 echo "</table><br>\n";
384 finishPortlet();
385 renderCellFilterPortlet ($cellfilter, 'rack', 'row_id', $row_id);
386
387 echo "</td><td class=pcright>";
388
389 global $nextorder;
390 $rackwidth = getRackImageWidth() * getConfigVar ('ROW_SCALE');
391 // Maximum number of racks per row is proportionally less, but at least 1.
392 $maxPerRow = max (floor (getConfigVar ('RACKS_PER_ROW') / getConfigVar ('ROW_SCALE')), 1);
393 $rackListIdx = 0;
394 $order = 'odd';
395 startPortlet ('Racks');
396 echo "<table border=0 cellspacing=5 align='center'><tr>";
397 foreach ($rackList as $rack)
398 {
399 if ($rackListIdx % $maxPerRow == 0)
400 {
401 if ($rackListIdx > 0)
402 echo '</tr>';
403 echo '<tr>';
404 }
405 echo "<td align=center class=row_${order}><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
406 echo "<img border=0 width=${rackwidth} height=" . (getRackImageHeight ($rack['height']) * getConfigVar ('ROW_SCALE'));
407 echo " title='${rack['height']} units'";
408 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
409 echo "<br>${rack['name']}</a></td>";
410 $order = $nextorder[$order];
411 $rackListIdx++;
412 }
413 echo "</tr></table>\n";
414 finishPortlet();
415 echo "</td></tr></table>";
416 }
417
418 function showError ($info = '', $location = 'N/A')
419 {
420 if (preg_match ('/\.php$/', $location))
421 $location = basename ($location);
422 elseif ($location != 'N/A')
423 $location = $location . '()';
424 echo "<div class=msg_error>An error has occured in [${location}]. ";
425 if (empty ($info))
426 echo 'No additional information is available.';
427 else
428 echo "Additional information:<br><p>\n<pre>\n${info}\n</pre></p>";
429 echo "Go back or try starting from <a href='".makeHref()."'>index page</a>.<br></div>\n";
430 }
431
432 // This function assures that specified argument was passed
433 // and is a number greater than zero.
434 function assertUIntArg ($argname, $caller = 'N/A', $allow_zero = FALSE)
435 {
436 if (!isset ($_REQUEST[$argname]))
437 {
438 showError ("Parameter '${argname}' is missing (calling function is [${caller}]).", __FUNCTION__);
439 die();
440 }
441 if (!is_numeric ($_REQUEST[$argname]))
442 {
443 showError ("Parameter '${argname}' is not a number (calling function is [${caller}]).", __FUNCTION__);
444 die();
445 }
446 if ($_REQUEST[$argname] < 0)
447 {
448 showError ("Parameter '${argname}' is less than zero (calling function is [${caller}]).", __FUNCTION__);
449 die();
450 }
451 if (!$allow_zero and $_REQUEST[$argname] == 0)
452 {
453 showError ("Parameter '${argname}' is equal to zero (calling function is [${caller}]).", __FUNCTION__);
454 die();
455 }
456 }
457
458 // This function assures that specified argument was passed
459 // and is a non-empty string.
460 function assertStringArg ($argname, $caller = 'N/A', $ok_if_empty = FALSE)
461 {
462 if (!isset ($_REQUEST[$argname]))
463 {
464 showError ("Parameter '${argname}' is missing (calling function is [${caller}]).", __FUNCTION__);
465 die();
466 }
467 if (!is_string ($_REQUEST[$argname]))
468 {
469 showError ("Parameter '${argname}' is not a string (calling function is [${caller}]).", __FUNCTION__);
470 die();
471 }
472 if (!$ok_if_empty and empty ($_REQUEST[$argname]))
473 {
474 showError ("Parameter '${argname}' is an empty string (calling function is [${caller}]).", __FUNCTION__);
475 die();
476 }
477 }
478
479 function assertBoolArg ($argname, $caller = 'N/A', $ok_if_empty = FALSE)
480 {
481 if (!isset ($_REQUEST[$argname]))
482 {
483 showError ("Parameter '${argname}' is missing (calling function is [${caller}]).", __FUNCTION__);
484 die();
485 }
486 if (!is_string ($_REQUEST[$argname]) or $_REQUEST[$argname] != 'on')
487 {
488 showError ("Parameter '${argname}' is not a string (calling function is [${caller}]).", __FUNCTION__);
489 die();
490 }
491 if (!$ok_if_empty and empty ($_REQUEST[$argname]))
492 {
493 showError ("Parameter '${argname}' is an empty string (calling function is [${caller}]).", __FUNCTION__);
494 die();
495 }
496 }
497
498 function assertIPv4Arg ($argname, $caller = 'N/A', $ok_if_empty = FALSE)
499 {
500 assertStringArg ($argname, $caller, $ok_if_empty);
501 if (!empty ($_REQUEST[$argname]) and long2ip (ip2long ($_REQUEST[$argname])) !== $_REQUEST[$argname])
502 {
503 showError ("IPv4 address validation failed for value '" . $_REQUEST[$argname] . "' (calling function is [${caller}]).", __FUNCTION__);
504 die();
505 }
506 }
507
508 // This function renders rack as HTML table.
509 function renderRack ($rack_id, $hl_obj_id = 0)
510 {
511 if (($rackData = getRackData ($rack_id)) == NULL)
512 {
513 showError ('getRackData() failed', __FUNCTION__);
514 return;
515 }
516 markAllSpans ($rackData);
517 if ($hl_obj_id > 0)
518 highlightObject ($rackData, $hl_obj_id);
519 markupObjectProblems ($rackData);
520 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
521 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
522 echo "<center><table border=0><tr valign=middle>";
523 echo "<td><h2><a href='".makeHref(array('page'=>'row', 'row_id'=>$rackData['row_id']))."'>${rackData['row_name']}</a> :</h2></td>";
524 // FIXME: use 'bypass'?
525 if ($prev_id != NULL)
526 {
527 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$prev_id))."'>";
528 printImageHREF ('prev', 'previous rack');
529 echo "</a></td>";
530 }
531 echo "<td><h2><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rackData['id']))."'>${rackData['name']}</a></h2></td>";
532 if ($next_id != NULL)
533 {
534 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$next_id))."'>";
535 printImageHREF ('next', 'next rack');
536 echo "</a></td>";
537 }
538 echo "</h2></td></tr></table>\n";
539 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
540 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
541 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
542 for ($i = $rackData['height']; $i > 0; $i--)
543 {
544 echo "<tr><th>${i}</th>";
545 for ($locidx = 0; $locidx < 3; $locidx++)
546 {
547 if (isset ($rackData[$i][$locidx]['skipped']))
548 continue;
549 $state = $rackData[$i][$locidx]['state'];
550 echo "<td class=state_${state}";
551 if (isset ($rackData[$i][$locidx]['hl']))
552 echo $rackData[$i][$locidx]['hl'];
553 if (isset ($rackData[$i][$locidx]['colspan']))
554 echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
555 if (isset ($rackData[$i][$locidx]['rowspan']))
556 echo ' rowspan=' . $rackData[$i][$locidx]['rowspan'];
557 echo ">";
558 switch ($state)
559 {
560 case 'T':
561 $objectData = getObjectInfo ($rackData[$i][$locidx]['object_id']);
562 if (!empty ($objectData['asset_no']))
563 $prefix = "<div title='${objectData['asset_no']}";
564 else
565 $prefix = "<div title='no asset tag";
566 // Don't tell about label, if it matches common name.
567 if ($objectData['name'] != $objectData['label'] and !empty ($objectData['label']))
568 $suffix = ", visible label is \"${objectData['label']}\"'>";
569 else
570 $suffix = "'>";
571 echo $prefix . $suffix;
572 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$objectData['id']))."'>${objectData['dname']}</a></div>";
573 break;
574 case 'A':
575 echo '<div title="This rackspace does not exist">&nbsp;</div>';
576 break;
577 case 'F':
578 echo '<div title="Free rackspace">&nbsp;</div>';
579 break;
580 case 'U':
581 echo '<div title="Problematic rackspace, you CAN\'T mount here">&nbsp;</div>';
582 break;
583 default:
584 echo '<div title="No data">&nbsp;</div>';
585 break;
586 }
587 echo '</td>';
588 }
589 echo "</tr>\n";
590 }
591 echo "</table></center>\n";
592 }
593
594 function renderNewRackForm ($row_id)
595 {
596 showMessageOrError();
597
598 startPortlet ('Add one');
599 printOpFormIntro ('addRack', array ('got_data' => 'TRUE'));
600 echo '<table border=0 align=center>';
601 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
602 if ($defh == 0)
603 $defh = '';
604 echo "<tr><th class=tdright>Rack name (*):</th><td class=tdleft><input type=text name=rack_name tabindex=1></td>";
605 echo "<td rowspan=4>Assign tags:<br>";
606 renderNewEntityTags();
607 echo "</td></tr>\n";
608 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";
609 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
610 echo "<tr><td class=submit colspan=2>";
611 printImageHREF ('CREATE', 'Add', TRUE);
612 echo "</td></tr></table></form>";
613 finishPortlet();
614
615 startPortlet ('Add many');
616 printOpFormIntro ('addRack', array ('got_mdata' => 'TRUE'));
617 echo '<table border=0 align=center>';
618 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
619 if ($defh == 0)
620 $defh = '';
621 echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=rack_height2 value='${defh}'></td>";
622 echo "<td rowspan=3 valign=top>Assign tags:<br>";
623 renderNewEntityTags();
624 echo "</td></tr>\n";
625 echo "<tr><th class=tdright>Rack names (*):</th><td class=tdleft><textarea name=rack_names cols=40 rows=25></textarea></td></tr>\n";
626 echo "<tr><td class=submit colspan=2>";
627 printImageHREF ('CREATE', 'Add', TRUE);
628 echo '</form></table>';
629 finishPortlet();
630 }
631
632 function renderEditObjectForm ($object_id)
633 {
634 showMessageOrError();
635
636 global $pageno;
637 $object = getObjectInfo ($object_id);
638 if ($object == NULL)
639 {
640 showError ('getObjectInfo() failed', __FUNCTION__);
641 return;
642 }
643 startPortlet ();
644 printOpFormIntro ('update');
645
646 // static attributes
647 echo '<table border=0 cellspacing=0 cellpadding=3 align=center>';
648 echo "<tr><td>&nbsp;</td><th colspan=2><h2>Attributes</h2></th></tr>";
649 echo "<tr><td>&nbsp;</td><th class=tdright>Type:</th><td class=tdleft>";
650 printSelect (getObjectTypeList(), 'object_type_id', $object['objtype_id']);
651 echo "</td></tr>\n";
652 // baseline info
653 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";
654 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";
655 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";
656 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";
657 // optional attributes
658 $values = getAttrValues ($object_id);
659 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
660 if (count($values) > 0)
661 {
662 $i = 0;
663 foreach ($values as $record)
664 {
665 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
666 echo '<tr><td>';
667 if (!empty ($record['value']))
668 {
669 echo "<a href='".makeHrefProcess(array('op'=>'clearSticker', 'object_id'=>$object_id, 'attr_id'=>$record['id']))."'>";
670 printImageHREF ('clear', 'Clear value');
671 echo '</a>';
672 }
673 else
674 echo '&nbsp;';
675 echo '</td>';
676 echo "<th class=sticker>${record['name']}:</th><td class=tdleft>";
677 switch ($record['type'])
678 {
679 case 'uint':
680 case 'float':
681 case 'string':
682 echo "<input type=text name=${i}_value value='${record['value']}'>";
683 break;
684 case 'dict':
685 $chapter = readChapter ($record['chapter_name']);
686 $chapter[0] = '-- NOT SET --';
687 $chapter = cookOptgroups ($chapter, $object['objtype_id'], $record['key']);
688 printNiftySelect ($chapter, "${i}_value", $record['key']);
689 break;
690 }
691 echo "</td></tr>\n";
692 $i++;
693 }
694 }
695 echo "<tr><td>&nbsp;</td><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
696 if ($object['has_problems'] == 'yes')
697 echo ' checked';
698 echo "></td></tr>\n";
699 echo "<tr><td>&nbsp;</td><th class=tdright>Actions:</th><td class=tdleft><a href='".
700 makeHrefProcess(array('op'=>'deleteObject', 'page'=>'depot', 'tab'=>'default', 'object_id'=>$object_id)).
701 "' onclick=\"javascript:return confirm('Are you sure you want to delete the object?')\">Delete object</a></td></tr>\n";
702 echo "<tr><td colspan=3><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
703
704 echo "<tr><th class=submit colspan=3>";
705 printImageHREF ('SAVE', 'Save changes', TRUE);
706 echo "</form></th></tr></table>\n";
707 finishPortlet();
708
709 echo '<table border=0 width=100%><tr><td>';
710 startPortlet ('history');
711 renderHistory ($pageno, $object_id);
712 finishPortlet();
713 echo '</td></tr></table>';
714 }
715
716 // This is a clone of renderEditObjectForm().
717 function renderEditRackForm ($rack_id)
718 {
719 showMessageOrError();
720 global $pageno;
721 $rack = getRackData ($rack_id);
722 if ($rack == NULL)
723 {
724 showError ('getRackData() failed', __FUNCTION__);
725 return;
726 }
727
728 startPortlet ('Rack attributes');
729 printOpFormIntro ('updateRack');
730 echo '<table border=0 align=center>';
731 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
732 printSelect (getRackRows(), 'rack_row_id', $rack['row_id']);
733 echo "</td></tr>\n";
734 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
735 echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
736 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
737 if (count ($rack['mountedObjects']) == 0)
738 {
739 echo "<tr><th class=tdright>Actions:</th><td class=tdleft><a href='".
740 makeHrefProcess(array('op'=>'deleteRack', 'rack_id'=>$rack_id)).
741 "' onclick=\"javascript:return confirm('Are you sure you want to delete the rack?')\">Delete rack</a></td></tr>\n";
742 }
743 echo "<tr><td class=submit colspan=2>";
744 printImageHREF ('SAVE', 'Save changes', TRUE);
745 echo "</td></tr>\n";
746 echo '</form></table><br>';
747 finishPortlet();
748
749 startPortlet ('History');
750 renderHistory ($pageno, $rack_id);
751 finishPortlet();
752 }
753
754 // This is a helper for creators and editors.
755 // Input array keys are OPTION VALUEs and input array values are OPTION text.
756 function printSelect ($optionList, $select_name, $selected_id = NULL, $tabindex = NULL)
757 {
758 echo "<select name=${select_name}" . ($tabindex ? " tabindex=${tabindex}" : '') . '>';
759 foreach ($optionList as $dict_key => $dict_value)
760 echo "<option value='${dict_key}'" . ($dict_key == $selected_id ? ' selected' : '') . ">${dict_value}</option>";
761 echo "</select>";
762 }
763
764 // Input is a cooked list of OPTGROUPs, each with own sub-list of OPTIONs in the same
765 // format as printSelect() expects.
766 function printNiftySelect ($groupList, $select_name, $selected_id = NULL, $tabindex = NULL)
767 {
768 // special treatment for ungrouped data
769 if (count ($groupList) == 1 and isset ($groupList['other']))
770 {
771 printSelect ($groupList['other'], $select_name, $selected_id, $tabindex);
772 return;
773 }
774 echo "<select name=${select_name}" . ($tabindex ? " tabindex=${tabindex}" : '') . '>';
775 foreach ($groupList as $groupname => $groupdata)
776 {
777 echo "<optgroup label='${groupname}'>";
778 foreach ($groupdata as $dict_key => $dict_value)
779 echo "<option value='${dict_key}'" . ($dict_key == $selected_id ? ' selected' : '') . ">${dict_value}</option>";
780 echo "</optgroup>\n";
781 }
782 echo "</select>";
783 }
784
785 // used by renderGridForm() and renderRackPage()
786 function renderRackInfoPortlet ($rackData)
787 {
788 startPortlet ('summary');
789 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
790 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
791 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
792 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
793 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
794 renderProgressBar (getRSUforRack ($rackData));
795 echo "</td></tr>\n";
796 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
797 echo count (stuffInRackspace ($rackData));
798 echo "</td></tr>\n";
799 printTagTRs (makeHref(array('page'=>'rackspace', 'tab'=>'default'))."&");
800 if (!empty ($rackData['comment']))
801 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
802 echo '</table>';
803 finishPortlet();
804 }
805
806 // This is a universal editor of rack design/waste.
807 // FIXME: switch to using printOpFormIntro()
808 function renderGridForm ($rack_id, $filter, $header, $submit, $state1, $state2)
809 {
810 if (($rackData = getRackData ($rack_id)) == NULL)
811 {
812 showError ('getRackData() failed', __FUNCTION__);
813 return;
814 }
815 showMessageOrError();
816 $filter ($rackData);
817 markupObjectProblems ($rackData);
818
819 // Render the result whatever it is.
820 // Main layout.
821 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
822 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
823
824 // Left column with information portlet.
825 echo "<tr><td class=pcleft height='1%' width='50%'>";
826 renderRackInfoPortlet ($rackData);
827 echo "</td>\n";
828 echo "<td class=pcright>";
829
830 // Grid form.
831 startPortlet ($header);
832 echo "<center>\n";
833 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
834 echo "<tr><th width='10%'>&nbsp;</th>";
835 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
836 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
837 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
838 printOpFormIntro ('updateRack');
839 markupAtomGrid ($rackData, $state2);
840 renderAtomGrid ($rackData);
841 echo "</table></center>\n";
842 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
843 finishPortlet();
844 echo "</td></tr></table>\n";
845 }
846
847 function renderRackDesign ($rack_id)
848 {
849 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
850 }
851
852 function renderRackProblems ($rack_id)
853 {
854 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
855 }
856
857 function startPortlet ($title = '')
858 {
859 echo "<div class=portlet><h2>${title}</h2>";
860 }
861
862 function finishPortlet ()
863 {
864 echo "</div>\n";
865 }
866
867 function renderRackObject ($object_id)
868 {
869 global $nextorder, $aac;
870 $info = getObjectInfo ($object_id);
871 if ($info == NULL)
872 {
873 showError ('getObjectInfo() failed', __FUNCTION__);
874 return;
875 }
876 // Main layout starts.
877 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
878 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
879 // left column with uknown number of portlets
880 echo "<tr><td class=pcleft>";
881 startPortlet ('summary');
882 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
883 if (!empty ($info['name']))
884 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
885 elseif (considerConfiguredConstraint ('object', $object_id, 'NAMEWARN_LISTSRC'))
886 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
887 echo "<tr><th width='50%' class=tdright>Object type:</th><td class=tdleft><a href='";
888 echo makeHref (array (
889 'page' => 'depot',
890 'tab' => 'default',
891 'cfe' => '{$typeid_' . $info['objtype_id'] . '}'
892 ));
893 echo "'>${info['objtype_name']}</a></td></tr>\n";
894 if (!empty ($info['asset_no']))
895 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
896 elseif (considerConfiguredConstraint ('object', $object_id, 'ASSETWARN_LISTSRC'))
897 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
898 if (!empty ($info['label']))
899 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
900 if (!empty ($info['barcode']))
901 echo "<tr><th width='50%' class=tdright>Barcode:</th><td class=tdleft>${info['barcode']}</td></tr>\n";
902 if ($info['has_problems'] == 'yes')
903 echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
904 foreach (getAttrValues ($object_id, TRUE) as $record)
905 if (!empty ($record['value']))
906 echo "<tr><th width='50%' class=sticker>${record['name']}:</th><td class=sticker>${record['a_value']}</td></tr>\n";
907 printTagTRs
908 (
909 makeHref
910 (
911 array
912 (
913 'page'=>'depot',
914 'tab'=>'default',
915 'andor' => 'and',
916 'cfe' => '{$typeid_' . $info['objtype_id'] . '}',
917 )
918 )."&"
919 );
920 echo "</table><br>\n";
921 finishPortlet();
922
923 if (!empty ($info['comment']))
924 {
925 startPortlet ('Comment');
926 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
927 finishPortlet ();
928 }
929
930 renderFilesPortlet ('object', $object_id);
931
932 $ports = getObjectPortsAndLinks ($object_id);
933 if (count ($ports))
934 {
935 startPortlet ('ports and links');
936 usort($ports, 'sortByName');
937 if ($ports)
938 {
939 $hl_port_id = 0;
940 if (isset ($_REQUEST['hl_port_id']))
941 {
942 assertUIntArg ('hl_port_id', __FUNCTION__);
943 $hl_port_id = $_REQUEST['hl_port_id'];
944 }
945 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
946 echo "<tr><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
947 echo "<th>Rem. Object</th><th>Rem. port</th></tr>\n";
948 foreach ($ports as $port)
949 {
950 echo '<tr';
951 if ($hl_port_id == $port['id'])
952 echo ' class=port_highlight';
953 echo "><td>${port['name']}</td><td>${port['label']}</td><td>${port['type']}</td>";
954 echo "<td>${port['l2address']}</td>";
955 if ($port['remote_object_id'])
956 {
957 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$port['remote_object_id'], 'hl_port_id'=>$port['remote_id']))."'>${port['remote_object_name']}</a></td>";
958 echo "<td>${port['remote_name']}</td>";
959 }
960 elseif (!empty ($port['reservation_comment']))
961 {
962 echo "<td><b>Reserved;</b></td>";
963 echo "<td>${port['reservation_comment']}</td>";
964 }
965 else
966 echo '<td>&nbsp;</td><td>&nbsp;</td>';
967 echo "</tr>\n";
968 }
969 echo "</table><br>\n";
970 }
971 finishPortlet();
972 }
973
974 $alloclist = getObjectIPv4Allocations ($object_id);
975 if (count ($alloclist))
976 {
977 startPortlet ('IPv4 addresses');
978 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
979 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
980 echo "<tr><th>OS interface</th><th>IP address</th><th>network</th><th>routed by</th><th>peers</th></tr>\n";
981 else
982 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
983 $hl_ipv4_addr = '';
984 if (isset ($_REQUEST['hl_ipv4_addr']))
985 {
986 assertIPv4Arg ('hl_ipv4_addr', __FUNCTION__);
987 $hl_ipv4_addr = $_REQUEST['hl_ipv4_addr'];
988 }
989 foreach ($alloclist as $dottedquad => $alloc)
990 {
991 $address_name = niftyString ($alloc['addrinfo']['name']);
992 $class = $alloc['addrinfo']['class'];
993 $secondclass = ($hl_ipv4_addr == $dottedquad) ? 'tdleft port_highlight' : 'tdleft';
994 $netid = getIPv4AddressNetworkId ($dottedquad);
995 if (NULL !== $netid)
996 {
997 $netinfo = getIPv4NetworkInfo ($netid);
998 loadIPv4AddrList ($netinfo);
999 }
1000 echo "<tr class='${class}' valign=top><td class=tdleft>${alloc['osif']}</td><td class='${secondclass}'>";
1001 if (NULL !== $netid)
1002 echo "<a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$dottedquad, 'hl_object_id'=>$object_id))."'>${dottedquad}</a>";
1003 else
1004 echo $dottedquad;
1005 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1006 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1007 echo '&nbsp;' . $aac[$alloc['type']];
1008 if (!empty ($alloc['addrinfo']['name']))
1009 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1010 echo '</td>';
1011 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1012 {
1013 if (NULL === $netid)
1014 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1015 else
1016 {
1017 echo "<td class='${secondclass}'>";
1018 renderIPv4NetCell ($netinfo);
1019 echo "</td>";
1020 // filter out self-allocation
1021 $other_routers = array();
1022 foreach (findRouters ($netinfo['addrlist']) as $router)
1023 if ($router['id'] != $object_id)
1024 $other_routers[] = $router;
1025 if (count ($other_routers))
1026 printRoutersTD ($other_routers);
1027 else
1028 echo "<td class='${secondclass}'>&nbsp;</td>";
1029 }
1030 }
1031 // peers
1032 echo "<td class='${secondclass}'>\n";
1033 $prefix = '';
1034 if ($alloc['addrinfo']['reserved'] == 'yes')
1035 {
1036 echo $prefix . '<strong>RESERVED</strong>';
1037 $prefix = '; ';
1038 }
1039 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1040 {
1041 if ($allocpeer['object_id'] == $object_id)
1042 continue;
1043 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1044 if (!empty ($allocpeer['osif']))
1045 echo $allocpeer['osif'] . '@';
1046 echo $allocpeer['object_name'] . '</a>';
1047 $prefix = '; ';
1048 }
1049 echo "</td></tr>\n";
1050 }
1051 echo "</table><br>\n";
1052 finishPortlet();
1053 }
1054
1055 $forwards = getNATv4ForObject ($object_id);
1056 if (count($forwards['in']) or count($forwards['out']))
1057 {
1058 startPortlet('NATv4');
1059
1060 if (count($forwards['out']))
1061 {
1062
1063 echo "<h3>locally performed NAT</h3>";
1064
1065 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
1066 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
1067
1068 foreach ($forwards['out'] as $pf)
1069 {
1070 $class = 'trerror';
1071 $osif = '';
1072 if (isset ($alloclist [$pf['localip']]))
1073 {
1074 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
1075 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
1076 }
1077 echo "<tr class='$class'>";
1078 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>";
1079 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
1080 $address = getIPv4Address ($pf['remoteip']);
1081 echo "<td class='description'>";
1082 if (count ($address['allocs']))
1083 foreach($address['allocs'] as $bond)
1084 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
1085 elseif (!empty ($pf['remote_addr_name']))
1086 echo '(' . $pf['remote_addr_name'] . ')';
1087 echo "</td><td class='description'>${pf['description']}</td></tr>";
1088 }
1089 echo "</table><br><br>";
1090 }
1091 if (count($forwards['in']))
1092 {
1093 echo "<h3>arriving NAT connections</h3>";
1094 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
1095 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
1096 foreach ($forwards['in'] as $pf)
1097 {
1098 echo "<tr>";
1099 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
1100 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
1101 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
1102 echo "<td class='description'>${pf['description']}</td></tr>";
1103 }
1104 echo "</table><br><br>";
1105 }
1106 finishPortlet();
1107 }
1108
1109 $pools = getRSPoolsForObject ($object_id);
1110 if (count ($pools))
1111 {
1112 $order = 'odd';
1113 startPortlet ('Real server pools (' . count ($pools) . ')');
1114 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
1115 echo "<tr><th>VS</th><th>RS pool</th><th>RS</th><th>VS config</th><th>RS config</th></tr>\n";
1116 foreach ($pools as $vs_id => $info)
1117 {
1118 echo "<tr valign=top class=row_${order}><td class=tdleft>";
1119 renderVSCell ($vs_id);
1120 echo "</td><td class=tdleft>";
1121 renderRSPoolCell ($info['pool_id'], $info['pool_name']);
1122 echo '</td><td class=tdleft>' . $info['rscount'] . '</td>';
1123 echo "<td class=slbconf>${info['vsconfig']}</td>";
1124 echo "<td class=slbconf>${info['rsconfig']}</td>";
1125 echo "</tr>\n";
1126 $order = $nextorder[$order];
1127 }
1128 echo "</table>\n";
1129 finishPortlet();
1130 }
1131 echo "</td>\n";
1132
1133 // After left column we have (surprise!) right column with rackspace portlet only.
1134 echo "<td class=pcright>";
1135 // rackspace portlet
1136 startPortlet ('rackspace allocation');
1137 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1138 renderRack ($rack_id, $object_id);
1139 echo '<br>';
1140 finishPortlet();
1141 echo "</td></tr>";
1142 echo "</table>\n";
1143 }
1144
1145 function renderRackMultiSelect ($sname, $racks, $selected)
1146 {
1147 // Transform the given flat list into a list of groups, each representing a rack row.
1148 $rdata = array();
1149 foreach ($racks as $rack)
1150 if (!isset ($rdata[$rack['row_name']]))
1151 $rdata[$rack['row_name']] = array ($rack['id'] => $rack['name']);
1152 else
1153 $rdata[$rack['row_name']][$rack['id']] = $rack['name'];
1154 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementsByName(\"updateObjectAllocation\")[0].submit()'>\n";
1155 foreach ($rdata as $optgroup => $racklist)
1156 {
1157 echo "<optgroup label='${optgroup}'>";
1158 foreach ($racklist as $rack_id => $rack_name)
1159 {
1160 echo "<option value=${rack_id}";
1161 if (!(array_search ($rack_id, $selected) === FALSE))
1162 echo ' selected';
1163 echo">${rack_name}</option>\n";
1164 }
1165 }
1166 echo "</select>\n";
1167 }
1168
1169 function showMessageOrError ()
1170 {
1171 if (isset ($_SESSION['log']))
1172 {
1173 printLog ($_SESSION['log']);
1174 unset($_SESSION['log']);
1175 }
1176 }
1177
1178 // This function renders a form for port edition.
1179 function renderPortsForObject ($object_id)
1180 {
1181 function printNewItemTR ()
1182 {
1183 printOpFormIntro ('addPort');
1184 echo "<tr><td>";
1185 printImageHREF ('add', 'add a port', TRUE);
1186 echo "</td><td><input type=text size=8 name=port_name tabindex=100></td>\n";
1187 echo "<td><input type=text size=24 name=port_label tabindex=101></td><td>";
1188 printSelect (getPortTypes(), 'port_type_id', getConfigVar ('default_port_type'), 102);
1189 echo "<td><input type=text name=port_l2address tabindex=103></td>\n";
1190 echo "<td colspan=3>&nbsp;</td><td>";
1191 printImageHREF ('add', 'add a port', TRUE, 104);
1192 echo "</td></tr></form>";
1193 }
1194 showMessageOrError();
1195 startPortlet ('Ports and interfaces');
1196 $ports = getObjectPortsAndLinks ($object_id);
1197 usort($ports, 'sortByName');
1198 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1199 echo "<tr><th>&nbsp;</th><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
1200 echo "<th>Rem. object</th><th>Rem. port</th><th>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
1201 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1202 printNewItemTR();
1203 foreach ($ports as $port)
1204 {
1205 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
1206 echo "<tr><td><a href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id'], 'object_id'=>$object_id, 'port_name'=>$port['name']))."'>";
1207 printImageHREF ('delete', 'Unlink and Delete this port');
1208 echo "</a></td>\n";
1209 echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
1210 echo "<td><input type=text name=label value='${port['label']}' size=24></td>";
1211 if (!$port['remote_object_id'])
1212 {
1213 echo "<td>";
1214 printSelect (getPortTypes(), 'port_type_id', $port['type_id']);
1215 echo "</td>";
1216 }
1217 else
1218 {
1219 echo "<input type=hidden name=port_type_id value='${port['type_id']}'>";
1220 echo "<td class=tdleft>${port['type']}</td>\n";
1221 }
1222 echo "<td><input type=text name=l2address value='${port['l2address']}'></td>\n";
1223 if ($port['remote_object_id'])
1224 {
1225 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$port['remote_object_id']))."'>${port['remote_object_name']}</a></td>";
1226 echo "<td>${port['remote_name']}</td>";
1227 echo "<td><a href='".
1228 makeHrefProcess(array(
1229 'op'=>'unlinkPort',
1230 'port_id'=>$port['id'],
1231 'object_id'=>$object_id,
1232 'port_name'=>$port['name'],
1233 'remote_port_name'=>$port['remote_name'],
1234 'remote_object_name'=>$port['remote_object_name'])).
1235 "'>";
1236 printImageHREF ('cut', 'Unlink this port');
1237 echo "</a></td>";
1238 }
1239 elseif (!empty ($port['reservation_comment']))
1240 {
1241 echo "<td><b>Reserved;</b></td>";
1242 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
1243 echo "<td><a href='".
1244 makeHrefProcess(array(
1245 'op'=>'useup',
1246 'port_id'=>$port['id'],
1247 'object_id'=>$object_id)).
1248 "'>";
1249 printImageHREF ('clear', 'Use up this port');
1250 echo "</a></td>";
1251 }
1252 else
1253 {
1254 echo "<td>&nbsp;</td><td>&nbsp;</td>";
1255 echo "<td>";
1256 echo "<a href='javascript:;' onclick='window.open(\"".makeHrefForHelper('portlist', array('port'=>$port['id'], 'type'=>$port['type_id'], 'object_id'=>$object_id, 'port_name'=>$port['name']))."\",\"findlink\",\"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
1257 printImageHREF ('plug', 'Link this port');
1258 echo "</a> <input type=text name=reservation_comment>";
1259 echo "</td>\n";
1260 }
1261 echo "<td>";
1262 printImageHREF ('save', 'Save changes', TRUE);
1263 echo "</td></form></tr>\n";
1264 }
1265 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1266 printNewItemTR();
1267 echo "</table><br>\n";
1268 finishPortlet();
1269
1270 startPortlet ('Add/update multiple ports');
1271 printOpFormIntro ('addMultiPorts');
1272 echo 'Format: <select name=format tabindex=201>';
1273 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1274 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
1275 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
1276 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
1277 echo "</select>";
1278 echo 'Default port type: ';
1279 printSelect (getPortTypes(), 'port_type', getConfigVar ('default_port_type'), 202);
1280 echo "<input type=submit value='Parse output' tabindex=204><br>\n";
1281 echo "<textarea name=input cols=100 rows=50 tabindex=203></textarea><br>\n";
1282 echo '</form>';
1283 finishPortlet();
1284 }
1285
1286 function renderIPv4ForObject ($object_id)
1287 {
1288 function printNewItemTR ()
1289 {
1290 global $aat;
1291 printOpFormIntro ('addIPv4Allocation');
1292 echo "<tr><td>";
1293 printImageHREF ('add', 'allocate', TRUE);
1294 echo "</td>";
1295 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1296 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
1297 echo "<td colspan=2>&nbsp;</td><td>";
1298 printSelect ($aat, 'bond_type', NULL, 102);
1299 echo "</td><td>&nbsp;</td><td>";
1300 printImageHREF ('add', 'allocate', TRUE, 103);
1301 echo "</td></tr></form>";
1302 }
1303 global $aat;
1304 showMessageOrError();
1305 startPortlet ('Allocations');
1306 $alloclist = getObjectIPv4Allocations ($object_id);
1307 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1308 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1309 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1310 echo '<th>network</th><th>routed by</th>';
1311 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1312
1313 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1314 printNewItemTR();
1315 foreach ($alloclist as $dottedquad => $alloc)
1316 {
1317 $class = $alloc['addrinfo']['class'];
1318 $netid = getIPv4AddressNetworkId ($dottedquad);
1319 if (NULL !== $netid)
1320 {
1321 $netinfo = getIPv4NetworkInfo ($netid);
1322 loadIPv4AddrList ($netinfo);
1323 }
1324 printOpFormIntro ('updIPv4Allocation', array ('ip' => $dottedquad));
1325 echo "<tr class='$class' valign=top><td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$object_id))."'>";
1326 printImageHREF ('delete', 'Delete this IPv4 address');
1327 echo "</a></td>";
1328 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td><td class=tdleft>";
1329 if (NULL !== $netid)
1330 echo "<a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$dottedquad))."'>${dottedquad}</a>";
1331 else
1332 echo $dottedquad;
1333 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1334 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1335 if (!empty ($alloc['addrinfo']['name']))
1336 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1337 echo '</td>';
1338 // FIXME: this a copy-and-paste from renderRackObject()
1339 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1340 {
1341 if (NULL === $netid)
1342 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1343 else
1344 {
1345 echo '<td>';
1346 renderIPv4NetCell ($netinfo);
1347 echo '</td>';
1348 // filter out self-allocation
1349 $other_routers = array();
1350 foreach (findRouters ($netinfo['addrlist']) as $router)
1351 if ($router['id'] != $object_id)
1352 $other_routers[] = $router;
1353 if (count ($other_routers))
1354 printRoutersTD ($other_routers);
1355 else
1356 echo "<td>&nbsp;</td>";
1357 }
1358 }
1359 echo '<td>';
1360 printSelect ($aat, 'bond_type', $alloc['type']);
1361 echo "</td><td>";
1362 $prefix = '';
1363 if ($alloc['addrinfo']['reserved'] == 'yes')
1364 {
1365 echo $prefix . '<strong>RESERVED</strong>';
1366 $prefix = '; ';
1367 }
1368 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1369 {
1370 if ($allocpeer['object_id'] == $object_id)
1371 continue;
1372 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1373 if (!empty ($allocpeer['osif']))
1374 echo $allocpeer['osif'] . '@';
1375 echo $allocpeer['object_name'] . '</a>';
1376 $prefix = '; ';
1377 }
1378 echo "</td><td>";
1379 printImageHREF ('save', 'Save changes', TRUE);
1380 echo "</td></form></tr>\n";
1381 }
1382 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1383 printNewItemTR();
1384
1385 echo "</table><br>\n";
1386 finishPortlet();
1387
1388 }
1389
1390 // Log structure versions:
1391 // 1: the whole structure is a list of code-message pairs
1392 // 2 and later: there's a "v" field set, which indicates the version
1393 // 2: there's a "m" list set to hold message code and optional arguments
1394 function printLog ($log)
1395 {
1396 switch (TRUE)
1397 {
1398 case !isset ($log['v']):
1399 case $log['v'] == 1:
1400 foreach ($log as $key => $record)
1401 if ($key !== 'v')
1402 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1403 break;
1404 case $log['v'] == 2:
1405 $msginfo = array
1406 (
1407 // records 0~99 with success messages
1408 0 => array ('code' => 'success', 'format' => '%s'),
1409 1 => array ('code' => 'success', 'format' => '%u new records done, %u already existed'),
1410 2 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully added.'),
1411 3 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully deleted.'),
1412 4 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully updated'),
1413 5 => array ('code' => 'success', 'format' => 'Port %s was added successfully'),
1414 6 => array ('code' => 'success', 'format' => 'Port %s was updated successfully'),
1415 7 => array ('code' => 'success', 'format' => 'Port %s was deleted successfully'),
1416 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with port %s at object %s'),
1417 9 => array ('code' => 'success', 'format' => 'Port %s was successfully unlinked from %s@%s'),
1418 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1419 11 => array ('code' => 'success', 'format' => 'Reservation removed.'),
1420 12 => array ('code' => 'success', 'format' => 'allocation updated'),
1421 13 => array ('code' => 'success', 'format' => 'allocated'),
1422 14 => array ('code' => 'success', 'format' => 'deallocated'),
1423 15 => array ('code' => 'success', 'format' => 'Reset succeeded.'),
1424 16 => array ('code' => 'success', 'format' => 'Update done'),
1425 17 => array ('code' => 'success', 'format' => 'Update(s) succeeded.'),
1426 18 => array ('code' => 'success', 'format' => 'Load balancer was successfully added'),
1427 19 => array ('code' => 'success', 'format' => 'Load balancer was successfully deleted'),
1428 20 => array ('code' => 'success', 'format' => 'Load balancer info was successfully updated'),
1429 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1430 22 => array ('code' => 'success', 'format' => 'Chained %u tags'),
1431 23 => array ('code' => 'success', 'format' => 'IPv4 prefix successfully added'),
1432 24 => array ('code' => 'success', 'format' => 'IPv4 prefix deleted'),
1433 25 => array ('code' => 'success', 'format' => 'IPv4 prefix updated'),
1434 26 => array ('code' => 'success', 'format' => '%u IP address(es) were successfully updated'),
1435 27 => array ('code' => 'success', 'format' => 'IPv4 address updated'),
1436 28 => array ('code' => 'success', 'format' => 'Virtual service was successfully created'),
1437 29 => array ('code' => 'success', 'format' => 'Virtual service was successfully deleted'),
1438 30 => array ('code' => 'success', 'format' => 'Virtual service was successfully updated'),
1439 31 => array ('code' => 'success', 'format' => 'RS pool was successfully created'),
1440 32 => array ('code' => 'success', 'format' => 'RS pool was successfully deleted'),
1441 33 => array ('code' => 'success', 'format' => 'RS pool was successfully updated'),
1442 34 => array ('code' => 'success', 'format' => 'Real server was successfully added'),
1443 35 => array ('code' => 'success', 'format' => 'Real server was successfully deleted'),
1444 36 => array ('code' => 'success', 'format' => 'Real server was successfully updated'),
1445 37 => array ('code' => 'success', 'format' => 'Successfully added %u real servers'),
1446 38 => array ('code' => 'success', 'format' => '%u real server(s) were successfully (de)activated'),
1447 39 => array ('code' => 'success', 'format' => 'User account %s updated.'),
1448 40 => array ('code' => 'success', 'format' => 'User account %s created.'),
1449 // ...
1450 // ...
1451 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1452 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1453 45 => array ('code' => 'success', 'format' => "Attribute '%s' created."),
1454 46 => array ('code' => 'success', 'format' => 'Rename successful.'),
1455 47 => array ('code' => 'success', 'format' => 'Attribute was deleted.'),
1456 48 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1457 49 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1458 50 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1459 51 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1460 52 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1461 53 => array ('code' => 'success', 'format' => 'Chapter was deleted.'),
1462 54 => array ('code' => 'success', 'format' => 'Chapter was updated.'),
1463 55 => array ('code' => 'success', 'format' => 'Chapter was added.'),
1464 56 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1465 57 => array ('code' => 'success', 'format' => 'Reset complete'),
1466 58 => array ('code' => 'success', 'format' => "Deleted tag '%s'."),
1467 59 => array ('code' => 'success', 'format' => "Created tag '%s'."),
1468 60 => array ('code' => 'success', 'format' => "Updated tag '%s'."),
1469 61 => array ('code' => 'success', 'format' => 'Password changed successfully.'),
1470 62 => array ('code' => 'success', 'format' => 'gw: %s'),
1471 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
1472 64 => array ('code' => 'success', 'format' => 'Port %s@%s has been assigned to VLAN %u'),
1473 65 => array ('code' => 'success', 'format' => "Added new rack '%s'"),
1474 66 => array ('code' => 'success', 'format' => "File sent Ok via handler '%s'"),
1475 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1476 68 => array ('code' => 'success', 'format' => "Updated rack '%s'"),
1477 69 => array ('code' => 'success', 'format' => 'File "%s" was added successfully'),
1478 70 => array ('code' => 'success', 'format' => 'File "%s" was updated successfully'),
1479 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
1480 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
1481 73 => array ('code' => 'success', 'format' => 'File "%s" was deleted successfully'),
1482 74 => array ('code' => 'success', 'format' => 'Row "%s" was added successfully'),
1483 75 => array ('code' => 'success', 'format' => 'Row "%s" was updated successfully'),
1484 76 => array ('code' => 'success', 'format' => 'Object "%s" was deleted successfully'),
1485 77 => array ('code' => 'success', 'format' => 'Row "%s" was deleted successfully'),
1486 78 => array ('code' => 'success', 'format' => 'File "%s" saved Ok'),
1487 79 => array ('code' => 'success', 'format' => 'Rack "%s" was deleted successfully'),
1488 80 => array ('code' => 'success', 'format' => "Added new object '%s'"),
1489
1490 // records 100~199 with fatal error messages
1491 100 => array ('code' => 'error', 'format' => '%s'),
1492 101 => array ('code' => 'error', 'format' => 'Port name cannot be empty'),
1493 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
1494 103 => array ('code' => 'error', 'format' => 'User not found!'),
1495 104 => array ('code' => 'error', 'format' => "Error updating user account '%s'"),
1496 // ...
1497 // ...
1498 // ...
1499 108 => array ('code' => 'error', 'format' => '%u failures and %u successfull changes.'),
1500 109 => array ('code' => 'error', 'format' => 'Update failed!'),
1501 110 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1502 111 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1503 112 => array ('code' => 'error', 'format' => 'Error adding chapter.'),
1504 113 => array ('code' => 'error', 'format' => 'Error updating chapter.'),
1505 114 => array ('code' => 'error', 'format' => 'Error deleting chapter.'),
1506 115 => array ('code' => 'error', 'format' => 'Error renaming attribute.'),
1507 116 => array ('code' => 'error', 'format' => 'Error creating attribute.'),
1508 117 => array ('code' => 'error', 'format' => 'Error deleting attribute.'),
1509 118 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1510 119 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1511 120 => array ('code' => 'error', 'format' => 'Reset failed!'),
1512 121 => array ('code' => 'error', 'format' => 'commitUpdateObject() failed'),
1513 122 => array ('code' => 'error', 'format' => 'One or more update(s) failed!'),
1514 123 => array ('code' => 'error', 'format' => 'Cannot process submitted data: unknown format code.'),
1515 124 => array ('code' => 'error', 'format' => 'Error removing reservation!'),
1516 125 => array ('code' => 'error', 'format' => "Update failed with error: '%s'"),
1517 126 => array ('code' => 'error', 'format' => 'addRStoRSPool() failed'),
1518 127 => array ('code' => 'error', 'format' => 'Added %u real servers and encountered %u errors'),
1519 128 => array ('code' => 'error', 'format' => 'commitDeleteRS() failed'),
1520 129 => array ('code' => 'error', 'format' => 'commitDeleteLB() failed'),
1521 130 => array ('code' => 'error', 'format' => 'commitDeleteVS() failed'),
1522 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1523 132 => array ('code' => 'error', 'format' => 'invalid protocol'),
1524 133 => array ('code' => 'error', 'format' => 'commitUpdateRS() failed'),
1525 134 => array ('code' => 'error', 'format' => 'commitUpdateLB() failed'),
1526 135 => array ('code' => 'error', 'format' => 'commitUpdateVS() failed'),
1527 136 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1528 137 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1529 138 => array ('code' => 'error', 'format' => 'commitDeleteRSPool() failed'),
1530 139 => array ('code' => 'error', 'format' => 'commitUpdateRSPool() failed'),
1531 140 => array ('code' => 'error', 'format' => 'Encountered %u errors, (de)activated %u real servers'),
1532 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u IP address(es)'),
1533 142 => array ('code' => 'error', 'format' => 'executeAutoPorts() failed'),
1534 143 => array ('code' => 'error', 'format' => 'Tried chaining %u tags, but experienced %u errors.'),
1535 144 => array ('code' => 'error', 'format' => "Error deleting tag: '%s'"),
1536 145 => array ('code' => 'error', 'format' => "Invalid tag name '%s'"),
1537 // ...
1538 147 => array ('code' => 'error', 'format' => "Could not create tag '%s': %s"),
1539 148 => array ('code' => 'error', 'format' => "Could not update tag '%s': %s"),
1540 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1541 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1542 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1543 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1544 153 => array ('code' => 'error', 'format' => 'Password change failed.'),
1545 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1546 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1547 156 => array ('code' => 'error', 'format' => 'getSwitchVLANs() failed'),
1548 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
1549 158 => array ('code' => 'error', 'format' => 'Ignoring malformed record #%u in form submit'),
1550 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1551 160 => array ('code' => 'error', 'format' => 'Invalid arguments'),
1552 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1553 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
1554 163 => array ('code' => 'error', 'format' => 'Failed to get any response from queryGateway() or the gateway died'),
1555 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
1556 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1557 166 => array ('code' => 'error', 'format' => 'gw: %s'),
1558 167 => array ('code' => 'error', 'format' => 'Could not find port %s'),
1559 168 => array ('code' => 'error', 'format' => 'Port %s is a trunk'),
1560 169 => array ('code' => 'error', 'format' => 'Failed to configure %s, connector returned code %u'),
1561 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1562 171 => array ('code' => 'error', 'format' => "Failed creating rack '%s'. Already exists in this row?"),
1563 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1564 173 => array ('code' => 'error', 'format' => "Invalid IPv4 prefix '%s'"),
1565 174 => array ('code' => 'error', 'format' => 'Bad IPv4 address'),
1566 175 => array ('code' => 'error', 'format' => 'Invalid netmask'),
1567 176 => array ('code' => 'error', 'format' => 'This network already exists'),
1568 177 => array ('code' => 'error', 'format' => 'commitUpdateRack() failed'),
1569 178 => array ('code' => 'error', 'format' => 'file not found'),
1570 179 => array ('code' => 'error', 'format' => 'Declining outdated text. Re-edit the file for consistency.'),
1571 180 => array ('code' => 'error', 'format' => 'Error saving file, all changes lost!'),
1572 181 => array ('code' => 'error', 'format' => "file uploads not allowed, change 'file_uploads' parameter in php.ini"),
1573 182 => array ('code' => 'error', 'format' => 'SQL query failed: %s'),
1574 183 => array ('code' => 'error', 'format' => "Tag id '%s' does not exist."),
1575 184 => array ('code' => 'error', 'format' => 'Submitted form is invalid at line %u'),
1576 185 => array ('code' => 'error', 'format' => "Failed to add object '%s'"),
1577 186 => array ('code' => 'error', 'format' => 'Incomplete form has been ignored. Cheers.'),
1578 187 => array ('code' => 'error', 'format' => "Internal error in function '%s'"),
1579
1580 // records 200~299 with warnings
1581 200 => array ('code' => 'warning', 'format' => '%s'),
1582 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1583 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
1584 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1585 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1586 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
1587 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
1588 207 => array ('code' => 'warning', 'format' => 'Ignored empty request'),
1589
1590 );
1591 // Handle the arguments. Is there any better way to do it?
1592 foreach ($log['m'] as $record)
1593 {
1594 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1595 {
1596 echo '<div class=msg_neutral>(this message was lost)</div>';
1597 continue;
1598 }
1599 if (isset ($record['a']))
1600 switch (count ($record['a']))
1601 {
1602 case 1:
1603 $msgtext = sprintf
1604 (
1605 $msginfo[$record['c']]['format'],
1606 $record['a'][0]
1607 );
1608 break;
1609 case 2:
1610 $msgtext = sprintf
1611 (
1612 $msginfo[$record['c']]['format'],
1613 $record['a'][0],
1614 $record['a'][1]
1615 );
1616 break;
1617 case 3:
1618 $msgtext = sprintf
1619 (
1620 $msginfo[$record['c']]['format'],
1621 $record['a'][0],
1622 $record['a'][1],
1623 $record['a'][2]
1624 );
1625 break;
1626 case 4:
1627 default:
1628 $msgtext = sprintf
1629 (
1630 $msginfo[$record['c']]['format'],
1631 $record['a'][0],
1632 $record['a'][1],
1633 $record['a'][2],
1634 $record['a'][3]
1635 );
1636 break;
1637 }
1638 else
1639 $msgtext = $msginfo[$record['c']]['format'];
1640 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1641 }
1642 break;
1643 default:
1644 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1645 break;
1646 }
1647 }
1648
1649 /*
1650 The following conditions must be followed:
1651 1. We can mount onto free atoms only. This means: if any record for an atom
1652 already exists in RackSpace, it can't be used for mounting.
1653 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1654 and either delete them before unmounting or refuse to unmount the object.
1655 */
1656
1657 // We extensively use $_REQUEST in the function.
1658 function renderRackSpaceForObject ($object_id)
1659 {
1660 $is_update = isset ($_REQUEST['rackmulti'][0]);
1661 $info = getObjectInfo ($object_id);
1662 if ($info == NULL)
1663 {
1664 showError ('getObjectInfo() failed', __FUNCTION__);
1665 return;
1666 }
1667 // Always process occupied racks plus racks chosen by user. First get racks with
1668 // already allocated rackspace...
1669 if (NULL === ($workingRacksData = getResidentRacksData ($object_id)))
1670 die; // some error already shown
1671
1672 // ...and then add those chosen by user (if any).
1673 if (isset($_REQUEST['rackmulti']))
1674 foreach ($_REQUEST['rackmulti'] as $cand_id)
1675 {
1676 if (!isset ($workingRacksData[$cand_id]))
1677 {
1678 $rackData = getRackData ($cand_id);
1679 if ($rackData == NULL)
1680 {
1681 showError ('getRackData() failed', __FUNCTION__);
1682 return NULL;
1683 }
1684 $workingRacksData[$cand_id] = $rackData;
1685 }
1686 }
1687
1688 printOpFormIntro ('updateObjectAllocation');
1689
1690 // Do it only once...
1691 foreach ($workingRacksData as $rackId => &$rackData)
1692 {
1693 applyObjectMountMask ($rackData, $object_id);
1694 echo "<input type=\"hidden\" name=\"rackmulti[]\" value=\"$rackId\">";
1695 }
1696 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1697 unset ($rackData);
1698
1699 // This is the time for rendering.
1700 showMessageOrError();
1701
1702 // Main layout starts.
1703 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1704
1705 // Left portlet with rack list.
1706 echo "<td class=pcleft height='1%'>";
1707 startPortlet ('Racks');
1708 $allRacksData = listCells ('rack');
1709 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1710 {
1711 foreach (array_keys ($allRacksData) as $rack_id)
1712 {
1713 $rackData = getRackData ($rack_id);
1714 if ($rackData == NULL)
1715 {
1716 showError ('getRackData() failed', __FUNCTION__);
1717 return NULL;
1718 }
1719 $workingRacksData[$rack_id] = $rackData;
1720 }
1721 foreach ($workingRacksData as &$rackData)
1722 applyObjectMountMask ($rackData, $object_id);
1723 unset ($rackData);
1724 }
1725 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1726 echo "<br>";
1727 echo "<br>";
1728 finishPortlet();
1729 echo "</td>";
1730
1731 // Middle portlet with comment and submit.
1732 echo "<td class=pcleft>";
1733 startPortlet ('Comment');
1734 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1735 echo "<input type=submit value='Save' name=got_atoms>\n";
1736 echo "<br>";
1737 echo "<br>";
1738 finishPortlet();
1739 echo "</td>";
1740
1741 // Right portlet with rendered racks. If this form submit is not final, we have to
1742 // reflect the former state of the grid in current form.
1743 echo "<td class=pcright rowspan=2 height='1%'>";
1744 startPortlet ('Working copy');
1745 echo '<table border=0 cellspacing=10 align=center><tr>';
1746 foreach ($workingRacksData as $rack_id => $rackData)
1747 {
1748 // Order is important here: only original allocation is highlighted.
1749 highlightObject ($rackData, $object_id);
1750 markupAtomGrid ($rackData, 'T');
1751 // If we have a form processed, discard user input and show new database
1752 // contents.
1753 if ($is_update)
1754 mergeGridFormToRack ($rackData);
1755 echo "<td valign=top>";
1756 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1757 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1758 echo "<tr><th width='10%'>&nbsp;</th>";
1759 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1760 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1761 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1762 renderAtomGrid ($rackData);
1763 echo "<tr><th width='10%'>&nbsp;</th>";
1764 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1765 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1766 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1767 echo "</table></center>\n";
1768 echo '</td>';
1769 }
1770 echo "</tr></table>";
1771 finishPortlet();
1772 echo "</td>\n";
1773
1774
1775 echo "</form>\n";
1776 echo "</tr></table>\n";
1777 }
1778
1779 function renderMolecule ($mdata, $object_id)
1780 {
1781 // sort data out
1782 $rackpack = array();
1783 global $loclist;
1784 foreach ($mdata as $rua)
1785 {
1786 $rack_id = $rua['rack_id'];
1787 $unit_no = $rua['unit_no'];
1788 $atom = $rua['atom'];
1789 if (!isset ($rackpack[$rack_id]))
1790 {
1791 $rackData = getRackData ($rack_id);
1792 for ($i = $rackData['height']; $i > 0; $i--)
1793 for ($locidx = 0; $locidx < 3; $locidx++)
1794 $rackData[$i][$locidx]['state'] = 'F';
1795 $rackpack[$rack_id] = $rackData;
1796 }
1797 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1798 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1799 }
1800 // now we have some racks to render
1801 foreach ($rackpack as $rackData)
1802 {
1803 markAllSpans ($rackData);
1804 echo "<table class=molecule cellspacing=0>\n";
1805 echo "<caption>${rackData['name']}</caption>\n";
1806 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1807 for ($i = $rackData['height']; $i > 0; $i--)
1808 {
1809 echo "<tr><th>$i</th>";
1810 for ($locidx = 0; $locidx < 3; $locidx++)
1811 {
1812 $state = $rackData[$i][$locidx]['state'];
1813 echo "<td class=state_${state}>&nbsp;</td>\n";
1814 }
1815 echo "</tr>\n";
1816 }
1817 echo "</table>\n";
1818 }
1819 }
1820
1821 function renderEmptyPortsSelect ($port_id, $type_id)
1822 {
1823 $ports = getEmptyPortsOfType($type_id);
1824 usort($ports, 'sortEmptyPorts');
1825 foreach ($ports as $port)
1826 {
1827 if ($port_id == $port['Port_id'])
1828 continue;
1829 echo "<option value='${port['Port_id']}' onclick='getElementById(\"remote_port_name\").value=\"${port['Port_name']}\"; getElementById(\"remote_object_name\").value=\"${port['Object_name']}\";'>${port['Object_name']} ${port['Port_name']}</option>\n";
1830 }
1831 }
1832
1833 function renderDepot ()
1834 {
1835 global $pageno, $nextorder;
1836 showMessageOrError();
1837 $cellfilter = getCellFilter();
1838 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
1839
1840 echo "<table border=0 class=objectview>\n";
1841 echo "<tr><td class=pcleft>";
1842
1843 startPortlet ('Objects (' . count ($objects) . ')');
1844 if ($objects === NULL)
1845 {
1846 showError ('Fatal error retrieving object list', __FUNCTION__);
1847 return;
1848 }
1849 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1850 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Row/Rack</th></tr>';
1851 $order = 'odd';
1852 foreach ($objects as $obj)
1853 {
1854 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1855 $secondclass = 'tdleft port_highlight';
1856 else
1857 $secondclass = 'tdleft';
1858 $tags = loadEntityTags ('object', $obj['id']);
1859 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>";
1860 if (count ($tags))
1861 echo '<br><small>' . serializeTags ($tags, makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
1862 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
1863 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
1864 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
1865 if ($obj['rack_id'])
1866 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>";
1867 else
1868 echo "<td class='${secondclass}'>Unmounted</td>";
1869 echo '</tr>';
1870 $order = $nextorder[$order];
1871 }
1872 echo '</table>';
1873 finishPortlet();
1874
1875 echo "</td><td class=pcright width='25%'>";
1876
1877 renderCellFilterPortlet ($cellfilter, 'object');
1878 echo "</td></tr></table>\n";
1879 }
1880
1881 // History viewer for history-enabled simple dictionaries.
1882 function renderHistory ($object_type, $object_id)
1883 {
1884 switch ($object_type)
1885 {
1886 case 'row':
1887 $query = "select ctime, user_name, name, comment from RackRowHistory where id = ${object_id} order by ctime";
1888 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>rack row comment</th></tr>';
1889 $extra = 3;
1890 break;
1891 case 'rack':
1892 $query =
1893 "select ctime, user_name, rh.name, rr.name as name, rh.height, rh.comment " .
1894 "from RackHistory as rh left join RackRow as rr on rh.row_id = rr.id " .
1895 "where rh.id = ${object_id} order by ctime";
1896 $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>';
1897 $extra = 5;
1898 break;
1899 case 'object':
1900 $query =
1901 "select ctime, user_name, RackObjectHistory.name as name, label, barcode, asset_no, has_problems, dict_value, comment " .
1902 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key join Chapter on Dictionary.chapter_id = Chapter.id " .
1903 "where Chapter.name = 'RackObjectType' and RackObjectHistory.id=${object_id} order by ctime";
1904 $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>';
1905 $extra = 8;
1906 break;
1907 default:
1908 showError ("Uknown object type '${object_type}'", __FUNCTION__);
1909 return;
1910 }
1911 global $dbxlink;
1912 $result = $dbxlink->query ($query);
1913 if ($result == NULL)
1914 {
1915 showError ('SQL query failed', __FUNCTION__);
1916 return;
1917 }
1918 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1919 $order = 'odd';
1920 global $nextorder;
1921 echo $header;
1922 while ($row = $result->fetch (PDO::FETCH_NUM))
1923 {
1924 echo "<tr class=row_${order}><td>${row[0]}</td>";
1925 for ($i = 1; $i <= $extra; $i++)
1926 echo "<td>" . $row[$i] . "</td>";
1927 echo "</tr>\n";
1928 $order = $nextorder[$order];
1929 }
1930 echo "</table><br>\n";
1931 }
1932
1933 function renderRackspaceHistory ()
1934 {
1935 global $nextorder, $pageno, $tabno;
1936 $order = 'odd';
1937 $history = getRackspaceHistory();
1938 // Show the last operation by default.
1939 if (isset ($_REQUEST['op_id']))
1940 $op_id = $_REQUEST['op_id'];
1941 elseif (isset ($history[0]['mo_id']))
1942 $op_id = $history[0]['mo_id'];
1943 else $op_id = NULL;
1944
1945 $omid = NULL;
1946 $nmid = NULL;
1947 $object_id = 1;
1948 if ($op_id)
1949 list ($omid, $nmid) = getOperationMolecules ($op_id);
1950
1951 // Main layout starts.
1952 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1953
1954 // Left top portlet with old allocation.
1955 echo "<tr><td class=pcleft>";
1956 startPortlet ('Old allocation');
1957 if ($omid)
1958 {
1959 $oldMolecule = getMolecule ($omid);
1960 renderMolecule ($oldMolecule, $object_id);
1961 }
1962 else
1963 echo "nothing";
1964 finishPortlet();
1965
1966 echo '</td><td class=pcright>';
1967
1968 // Right top portlet with new allocation
1969 startPortlet ('New allocation');
1970 if ($nmid)
1971 {
1972 $newMolecule = getMolecule ($nmid);
1973 renderMolecule ($newMolecule, $object_id);
1974 }
1975 else
1976 echo "nothing";
1977 finishPortlet();
1978
1979 echo '</td></tr><tr><td colspan=2>';
1980
1981 // Bottom portlet with list
1982
1983 startPortlet ('Rackspace allocation history');
1984 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1985 echo "<tr><th>timestamp</th><th>author</th><th>rack object ID</th><th>rack object type</th><th>rack object name</th><th>comment</th></tr>\n";
1986 foreach ($history as $row)
1987 {
1988 if ($row['mo_id'] == $op_id)
1989 $class = 'hl';
1990 else
1991 $class = "row_${order}";
1992 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
1993 echo "<td>${row['user_name']}</td>";
1994 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
1995 echo "</tr>\n";
1996 $order = $nextorder[$order];
1997 }
1998 echo "</table>\n";
1999 finishPortlet();
2000
2001 echo '</td></tr></table>';
2002 }
2003
2004 function renderIPv4SpaceRecords ($tree, &$tagcache, $baseurl, $target = 0, $level = 1)
2005 {
2006 $self = __FUNCTION__;
2007 foreach ($tree as $item)
2008 {
2009 $total = $item['addrt'];
2010 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2011 {
2012 loadIPv4AddrList ($item); // necessary to compute router list and address counter
2013 $used = $item['addrc'];
2014 }
2015 else
2016 {
2017 $item['addrlist'] = array();
2018 $item['addrc'] = 0;
2019 }
2020 if (isset ($item['id']))
2021 {
2022 if ($item['symbol'] == 'node-collapsed')
2023 $expandurl = "${baseurl}&eid=" . $item['id'] . "#netid" . $item['id'];
2024 elseif ($item['symbol'] == 'node-expanded')
2025 $expandurl = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#netid${item['parent_id']}" : '');
2026 else
2027 $expandurl = '';
2028 echo "<tr valign=top>";
2029 printIPv4NetInfoTDs ($item, 'tdleft', $level, $item['symbol'], $expandurl);
2030 echo "<td class=tdcenter>";
2031 if ($target == $item['id'])
2032 echo "<a name=netid${target}></a>";
2033 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2034 {
2035 renderProgressBar ($total ? $used/$total : 0);
2036 echo "<br><small>${used}/${total}</small>";
2037 }
2038 else
2039 echo "<small>${total}</small>";
2040 echo "</td>";
2041 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2042 printRoutersTD (findRouters ($item['addrlist']), $tagcache);
2043 echo "</tr>";
2044 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2045 $self ($item['kids'], $tagcache, $baseurl, $target, $level + 1);
2046 }
2047 else
2048 {
2049 echo "<tr valign=top>";
2050 printIPv4NetInfoTDs ($item, 'tdleft sparenetwork', $level, $item['symbol']);
2051 echo "<td class=tdcenter>";
2052 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2053 {
2054 renderProgressBar ($used/$total, 'sparenetwork');
2055 echo "<br><small>${used}/${total}</small>";
2056 }
2057 else
2058 echo "<small>${total}</small>";
2059 echo "</td><td>&nbsp;</td></tr>";
2060 }
2061 }
2062 }
2063
2064 function renderIPv4Space ()
2065 {
2066 global $pageno, $tabno;
2067 $cellfilter = getCellFilter();
2068 $netlist = filterCellList (listCells ('ipv4net'), $cellfilter['expression']);
2069 array_walk ($netlist, 'amplifyCell');
2070
2071 $netcount = count ($netlist);
2072 // expand request can take either natural values or "ALL". Zero means no expanding.
2073 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2074 $tree = prepareIPv4Tree ($netlist, $eid);
2075
2076 echo "<table border=0 class=objectview>\n";
2077 echo "<tr><td class=pcleft>";
2078 startPortlet ("networks (${netcount})");
2079 echo '<h4>';
2080 if ($eid === 0)
2081 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') . " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL'))."'>expand all</a>)";
2082 elseif ($eid === 'ALL')
2083 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno))."'>auto-collapse</a>)";
2084 else
2085 {
2086 $netinfo = getIPv4NetworkInfo ($eid);
2087 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno))."'>auto-collapse</a> / <a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL'))."'>expand&nbsp;all</a>)";
2088 }
2089 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2090 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2091 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2092 echo "<th>routed by</th>";
2093 echo "</tr>\n";
2094 $tagcache = array();
2095 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2096 renderIPv4SpaceRecords ($tree, $tagcache, $baseurl, $eid);
2097 echo "</table>\n";
2098 finishPortlet();
2099 echo '</td><td class=pcright>';
2100 renderCellFilterPortlet ($cellfilter, 'ipv4net');
2101 echo "</td></tr></table>\n";
2102 }
2103
2104 function renderIPv4SLB ()
2105 {
2106 global $page, $nextorder;
2107
2108 startPortlet ('SLB configuration');
2109 echo "<table border=0 width='100%'><tr>";
2110 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2111 echo "<td><h3><a href='".makeHref(array('page'=>$pno))."'>" . $page[$pno]['title'] . "</a></h3></td>";
2112 echo '</tr></table>';
2113 finishPortlet();
2114
2115 $summary = getSLBSummary();
2116 startPortlet ('SLB tactical overview');
2117 // A single id-keyed array isn't used here to preserve existing
2118 // order of LBs returned by getSLBSummary()
2119 $lblist = array();
2120 $lbdname = array();
2121 foreach ($summary as $vipdata)
2122 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2123 if (!in_array ($lb_object_id, $lblist))
2124 {
2125 $oi = getObjectInfo ($lb_object_id);
2126 $lbdname[$lb_object_id] = $oi['dname'];
2127 $lblist[] = $lb_object_id;
2128 }
2129 if (!count ($summary))
2130 echo 'none configured';
2131 else
2132 {
2133 $order = 'odd';
2134 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2135 echo "<tr valign=top><td>&nbsp;</td>";
2136 foreach ($lblist as $lb_object_id)
2137 {
2138 #echo "<th><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$lb_object_id))."'>" . $lbdname[$lb_object_id] . "</a></th>";
2139 echo '<td>';
2140 renderLBCell ($lb_object_id);
2141 echo '</td>';
2142 }
2143 echo "</tr>\n";
2144 foreach ($summary as $vsid => $vsdata)
2145 {
2146 echo "<tr class=row_${order}><td class=tdleft>";
2147 renderVSCell ($vsid);
2148 echo "</td>";
2149 foreach ($lblist as $lb_object_id)
2150 {
2151 echo '<td class=tdleft>';
2152 if (!isset ($vsdata['lblist'][$lb_object_id]))
2153 echo '&nbsp;';
2154 else
2155 {
2156 echo $vsdata['lblist'][$lb_object_id]['size'];
2157 // echo " (<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$vsdata['lblist'][$lb_object_id]['id'])). "'>";
2158 // echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2159 }
2160 echo '</td>';
2161 }
2162 echo "</tr>\n";
2163 $order = $nextorder[$order];
2164 }
2165 echo "</table>\n";
2166 }
2167 finishPortlet ();
2168 }
2169
2170 function renderIPv4SpaceEditor ()
2171 {
2172 showMessageOrError();
2173
2174 // IPv4 validator
2175 ?>
2176 <script type="text/javascript">
2177 function init() {
2178 document.add_new_range.range.setAttribute('match', "^\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\/\\d\\d?$");
2179
2180 Validate.init();
2181 }
2182 window.onload=init;
2183 </script>
2184 <?php
2185
2186 startPortlet ("Add new");
2187 echo '<table border=0 cellpadding=10 align=center>';
2188 // This form requires a name, so JavaScript validator can find it.
2189 // No printOpFormIntro() hence
2190 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2191 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2192 // tags column
2193 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2194 renderNewEntityTags();
2195 echo '</td>';
2196 // inputs column
2197 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=18 class='live-validate' tabindex=1></td>";
2198 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2199 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2200 echo "<tr><td colspan=2>";
2201 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2202 echo '</td></tr>';
2203 echo "</form></table><br><br>\n";
2204 finishPortlet();
2205
2206 $addrspaceList = listCells ('ipv4net');
2207 array_walk ($addrspaceList, 'amplifyCell');
2208 if (count ($addrspaceList))
2209 {
2210 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2211 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2212 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>&nbsp;</th></tr>";
2213 foreach ($addrspaceList as $netinfo)
2214 {
2215 echo "<form method=post action='".makeHrefProcess(array('op'=>'updIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2216 echo "<tr valign=top><td>";
2217 if (getConfigVar ('IPV4_JAYWALK') == 'yes')
2218 {
2219 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2220 printImageHREF ('destroy', 'Delete this prefix');
2221 echo "</a>";
2222 }
2223 else // only render clickable image for empty networks
2224 {
2225 $netdata = getIPv4NetworkInfo ($netinfo['id']);
2226 loadIPv4AddrList ($netdata);
2227 if (count ($netdata['addrlist']))
2228 printImageHREF ('nodestroy', 'There are ' . count ($netdata['addrlist']) . ' allocations inside');
2229 else
2230 {
2231 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2232 printImageHREF ('destroy', 'Delete this prefix');
2233 echo "</a>";
2234 }
2235
2236 }
2237 echo "</td>\n<td class=tdleft>${netinfo['ip']}/${netinfo['mask']}</td>";
2238 echo "<td><input type=text name=name size=40 value='${netinfo['name']}'>";
2239 echo "</td><td>";
2240 printImageHREF ('save', 'Save changes', TRUE);
2241 echo "</td></tr></form>\n";
2242 }
2243 echo "</table>";
2244 finishPortlet();
2245 }
2246 }
2247
2248 function renderIPv4Network ($id)
2249 {
2250 global $pageno, $tabno, $aac2;
2251 $netmaskbylen = array
2252 (
2253 32 => '255.255.255.255',
2254 31 => '255.255.255.254',
2255 30 => '255.255.255.252',
2256 29 => '255.255.255.248',
2257 28 => '255.255.255.240',
2258 27 => '255.255.255.224',
2259 26 => '255.255.255.192',
2260 25 => '255.255.255.128',
2261 24 => '255.255.255.0',
2262 23 => '255.255.254.0',
2263 22 => '255.255.252.0',
2264 21 => '255.255.248.0',
2265 20 => '255.255.240.0',
2266 19 => '255.255.224.0',
2267 18 => '255.255.192.0',
2268 17 => '255.255.128.0',
2269 16 => '255.255.0.0',
2270 15 => '255.254.0.0',
2271 14 => '255.252.0.0',
2272 13 => '255.248.0.0',
2273 12 => '255.240.0.0',
2274 11 => '255.224.0.0',
2275 10 => '255.192.0.0',
2276 9 => '255.128.0.0',
2277 8 => '255.0.0.0',
2278 7 => '254.0.0.0',
2279 6 => '252.0.0.0',
2280 5 => '248.0.0.0',
2281 4 => '240.0.0.0',
2282 3 => '224.0.0.0',
2283 2 => '192.0.0.0',
2284 1 => '128.0.0.0'
2285 );
2286 $wildcardbylen = array
2287 (
2288 32 => '0.0.0.0',
2289 31 => '0.0.0.1',
2290 30 => '0.0.0.3',
2291 29 => '0.0.0.7',
2292 28 => '0.0.0.15',
2293 27 => '0.0.0.31',
2294 26 => '0.0.0.63',
2295 25 => '0.0.0.127',
2296 24 => '0.0.0.255',
2297 23 => '0.0.1.255',
2298 22 => '0.0.3.255',
2299 21 => '0.0.7.255',
2300 20 => '0.0.15.255',
2301 19 => '0.0.31.255',
2302 18 => '0.0.63.255',
2303 17 => '0.0.127.255',
2304 16 => '0.0.255.25',
2305 15 => '0.1.255.255',
2306 14 => '0.3.255.255',
2307 13 => '0.7.255.255',
2308 12 => '0.15.255.255',
2309 11 => '0.31.255.255',
2310 10 => '0.63.255.255',
2311 9 => '0.127.255.255',
2312 8 => '0.255.255.255',
2313 7 => '1.255.255.255',
2314 6 => '3.255.255.255',
2315 5 => '7.255.255.255',
2316 4 => '15.255.255.255',
2317 3 => '31.255.255.255',
2318 2 => '63.255.255.255',
2319 1 => '127.255.255.255'
2320 );
2321 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2322 if (isset($_REQUEST['pg']))
2323 $page = $_REQUEST['pg'];
2324 else
2325 $page=0;
2326
2327 $range = getIPv4NetworkInfo ($id);
2328 loadIPv4AddrList ($range);
2329 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2330 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></td></tr>\n";
2331
2332 echo "<tr><td class=pcleft width='50%'>";
2333 startPortlet ('summary');
2334 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2335 $used = count ($range['addrlist']);
2336 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2337
2338 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2339 renderProgressBar ($used/$total);
2340 echo "&nbsp;${used}/${total}</td></tr>\n";
2341
2342 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2343 {
2344 // Build a backtrace from all parent networks.
2345 $clen = $range['mask'];
2346 $backtrace = array();
2347 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2348 {
2349 $upperinfo = getIPv4NetworkInfo ($upperid);
2350 $clen = $upperinfo['mask'];
2351 $backtrace[] = $upperid;
2352 }
2353 $arrows = count ($backtrace);
2354 foreach (array_reverse ($backtrace) as $ancestorid)
2355 {
2356 $ainfo = getIPv4NetworkInfo ($ancestorid);
2357 echo "<tr><th width='50%' class=tdright>";
2358 for ($i = 0; $i < $arrows; $i++)
2359 echo '&uarr;';
2360 $arrows--;
2361 echo "</th><td class=tdleft>";
2362 renderIPv4NetCell ($ainfo);
2363 echo "</td></tr>";
2364 }
2365 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
2366 echo "<td class=tdleft>";
2367 renderIPv4NetCell ($range);
2368 echo "</td></tr>";
2369 // FIXME: get and display nested networks
2370 // $theitem = pickLeaf ($ipv4tree, $id);
2371 }
2372
2373 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2374 echo $netmaskbylen[$range['mask']];
2375 echo "</td></tr>\n";
2376
2377 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2378 printf ('0x%08X', binMaskFromDec ($range['mask']));
2379 echo "</td></tr>\n";
2380
2381 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2382 echo $wildcardbylen[$range['mask']];
2383 echo "</td></tr>\n";
2384
2385 $routers = findRouters ($range['addrlist']);
2386 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers))
2387 {
2388 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2389 printRoutersTD ($routers);
2390 echo "</tr>\n";
2391 }
2392
2393 printTagTRs (makeHref(array('page'=>'ipv4space', 'tab'=>'default'))."&");
2394 echo "</table><br>\n";
2395 finishPortlet();
2396
2397 renderFilesPortlet ('ipv4net', $id);
2398 echo "</td>\n";
2399
2400 echo "<td class=pcright>";
2401 startPortlet ('details');
2402 $startip = $range['ip_bin'] & $range['mask_bin'];
2403 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2404 $realstartip = $startip;
2405 $realendip = $endip;
2406 $numpages = 0;
2407 if($endip - $startip > $maxperpage)
2408 {
2409 $numpages = ($endip - $startip)/$maxperpage;
2410 $startip = $startip + $page * $maxperpage;
2411 $endip = $startip + $maxperpage-1;
2412 }
2413 echo "<center>";
2414 if ($numpages)
2415 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2416 for ($i=0; $i<$numpages; $i++)
2417 {
2418 if ($i == $page)
2419 echo "<b>$i</b> ";
2420 else
2421 echo "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'id'=>$id, 'pg'=>$i))."'>$i</a> ";
2422 }
2423 echo "</center>";
2424
2425 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2426 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2427
2428
2429 for ($ip = $startip; $ip <= $endip; $ip++) :
2430 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2431 $secondstyle = 'tdleft port_highlight';
2432 else
2433 $secondstyle = 'tdleft';
2434 if (!isset ($range['addrlist'][$ip]))
2435 {
2436 echo "<tr><td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>ip_long2quad($ip)))."'>" . ip_long2quad($ip);
2437 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2438 continue;
2439 }
2440 $addr = $range['addrlist'][$ip];
2441 echo "<tr class='${addr['class']}'>";
2442
2443 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
2444 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2445 $delim = '';
2446 $prologue = '';
2447 if ( $addr['reserved'] == 'yes')
2448 {
2449 echo "<strong>RESERVED</strong> ";
2450 $delim = '; ';
2451 }
2452 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2453 {
2454 echo $delim . $aac2[$ref['type']];
2455 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'hl_ipv4_addr'=>$addr['ip']))."'>";
2456 echo $ref['name'] . (empty ($ref['name']) ? '' : '@');
2457 echo "${ref['object_name']}</a>";
2458 $delim = '; ';
2459 }
2460 if ($delim != '')
2461 {
2462 $delim = '';
2463 $prologue = '<br>';
2464 }
2465 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2466 {
2467 echo $prologue;
2468 $prologue = '';
2469 echo "${delim}<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id']))."'>";
2470 echo "${ref['object_name']}</a>:<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$ref['vs_id']))."'>";
2471 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2472 $delim = '; ';
2473 }
2474 if ($delim != '')
2475 {
2476 $delim = '';
2477 $prologue = '<br>';
2478 }
2479 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2480 {
2481 echo $prologue;
2482 $prologue = '';
2483 echo "${delim}&rarr;${ref['rsport']}@<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$ref['rspool_id']))."'>";
2484 echo "${ref['rspool_name']}</a>";
2485 $delim = '; ';
2486 }
2487 echo "</td></tr>\n";
2488 endfor;
2489 // end of iteration
2490
2491 echo "</table>";
2492 finishPortlet();
2493 echo "</td></tr></table>\n";
2494 }
2495
2496 function renderIPv4NetworkProperties ($id)
2497 {
2498 showMessageOrError();
2499 $netdata = getIPv4NetworkInfo ($id);
2500 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
2501 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2502 printOpFormIntro ('editRange');
2503 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${netdata['name']}'></tr>";
2504 echo "<tr><td colspan=2 class=tdcenter>";
2505 printImageHREF ('SAVE', 'Save changes', TRUE);
2506 echo "</td></form></tr></table>\n";
2507 }
2508
2509 function renderIPv4Address ($dottedquad)
2510 {
2511 global $aat;
2512 $address = getIPv4Address ($dottedquad);
2513 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2514 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2515 if (!empty ($address['name']))
2516 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
2517
2518 echo "<tr><td class=pcleft>";
2519 startPortlet ('summary');
2520 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2521 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
2522 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2523 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2524 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
2525 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2526 printTagTRs();
2527 echo "</table><br>\n";
2528 finishPortlet();
2529 echo "</td>\n";
2530
2531 echo "<td class=pcright>";
2532
2533 if (isset ($address['class']))
2534 {
2535 startPortlet ('allocations');
2536 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2537 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2538 $class = $address['class'];
2539 // render all allocation records for this address the same way
2540 if ($address['reserved'] == 'yes')
2541 echo "<tr class='${class}'><td colspan=2>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td></tr>";
2542 foreach ($address['allocs'] as $bond)
2543 {
2544 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2545 $secondclass = 'tdleft port_highlight';
2546 else
2547 $secondclass = 'tdleft';
2548 echo "<tr class='$class'><td class=tdleft><a href='".makeHref(array('page'=>'object', 'object_id'=>$bond['object_id'], 'hl_ipv4_addr'=>$dottedquad))."'>${bond['object_name']}</td><td class='${secondclass}'>${bond['name']}</td><td class='${secondclass}'><strong>";
2549 echo $aat[$bond['type']];
2550 echo "</strong></td></tr>\n";
2551 }
2552 echo "</table><br><br>";
2553 finishPortlet();
2554 }
2555
2556 // FIXME: The returned list is structured differently, than we expect it to be. One of the sides
2557 // must be fixed.
2558 if (count ($address['lblist']))
2559 {
2560 startPortlet ('Virtual services (' . count ($address['lblist']) . ')');
2561 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2562 echo "<tr><th>VS</th><th>name</th></tr>\n";
2563 foreach ($address['lblist'] as $vsinfo)
2564 {
2565 echo "<tr><td class=tdleft><a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$vsinfo['vs_id']))."'>";
2566 echo buildVServiceName ($vsinfo) . "</a></td><td class=tdleft>";
2567 echo $vsinfo['name'] . "</td></tr>\n";
2568 }
2569 echo "</table><br><br>";
2570 finishPortlet();
2571 }
2572
2573 if (count ($address['rslist']))
2574 {
2575 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2576 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2577 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
2578 foreach ($address['rslist'] as $rsinfo)
2579 {
2580 echo "<tr><td>";
2581 if ($rsinfo['inservice'] == 'yes')
2582 printImageHREF ('inservice', 'in service');
2583 else
2584 printImageHREF ('notinservice', 'NOT in service');
2585 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsinfo['rspool_id']))."'>";
2586 echo $rsinfo['rspool_name'] . "</a></td></tr>\n";
2587 }
2588 echo "</table><br><br>";
2589 finishPortlet();
2590 }
2591
2592 if (count ($address['outpf']))
2593 {
2594 startPortlet ('departing NAT rules');
2595 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2596 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2597 foreach ($address['outpf'] as $rule)
2598 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2599 echo "</table>";
2600 finishPortlet();
2601 }
2602
2603 if (count ($address['inpf']))
2604 {
2605 startPortlet ('arriving NAT rules');
2606 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2607 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2608 foreach ($address['inpf'] as $rule)
2609 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2610 echo "</table>";
2611 finishPortlet();
2612 }
2613
2614 echo "</td></tr>";
2615 echo "</table>\n";
2616 }
2617
2618 function renderIPv4AddressProperties ($dottedquad)
2619 {
2620 showMessageOrError();
2621 $address = getIPv4Address ($dottedquad);
2622 echo "<center><h1>$dottedquad</h1></center>\n";
2623
2624 startPortlet ('update');
2625 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2626 printOpFormIntro ('editAddress');
2627 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2628 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2629 echo ($address['reserved']=='yes') ? 'checked' : '';
2630 echo "></tr><tr><td class=tdleft>";
2631 printImageHREF ('SAVE', 'Save changes', TRUE);
2632 echo "</td></form><td class=tdright>";
2633 if (empty ($address['name']) and $address['reserved'] == 'no')
2634 printImageHREF ('CLEAR gray');
2635 else
2636 {
2637 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2638 printImageHREF ('CLEAR', 'Release', TRUE);
2639 echo "</form>";
2640 }
2641 echo "</td></tr></table>\n";
2642 finishPortlet();
2643 }
2644
2645 function renderIPv4AddressAllocations ($dottedquad)
2646 {
2647 showMessageOrError();
2648 function printNewItemTR ()
2649 {
2650 global $aat;
2651 printOpFormIntro ('addIPv4Allocation');
2652 echo "<tr><td>";
2653 printImageHREF ('add', 'allocate', TRUE);
2654 echo "</td><td>";
2655 printSelect (getNarrowObjectList ('IPV4OBJ_LISTSRC'), 'object_id', NULL, 100);
2656 echo "</td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
2657 printSelect ($aat, 'bond_type', NULL, 102);
2658 echo "</td><td>";
2659 printImageHREF ('add', 'allocate', TRUE, 103);
2660 echo "</td></form></tr>";
2661 }
2662 global $aat;
2663
2664 $address = getIPv4Address ($dottedquad);
2665
2666 echo "<center><h1>${dottedquad}</h1></center>\n";
2667 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2668 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
2669
2670 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2671 printNewItemTR();
2672 if (isset ($address['class']))
2673 {
2674 $class = $address['class'];
2675 if ($address['reserved'] == 'yes')
2676 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2677 foreach ($address['allocs'] as $bond)
2678 {
2679 echo "<tr class='$class'>";
2680 printOpFormIntro ('updIPv4Allocation', array ('object_id' => $bond['object_id']));
2681 echo "<td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$bond['object_id']))."'>";
2682 printImageHREF ('delete', 'Unallocate address');
2683 echo "</a></td>";
2684 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$bond['object_id'], 'hl_ipv4_addr'=>$dottedquad))."'>${bond['object_name']}</td>";
2685 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
2686 printSelect ($aat, 'bond_type', $bond['type']);
2687 echo "</td><td>";
2688 printImageHREF ('save', 'Save changes', TRUE);
2689 echo "</td></form></tr>\n";
2690 }
2691 }
2692 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2693 printNewItemTR();
2694 echo "</table><br><br>";
2695 }
2696
2697 function renderNATv4ForObject ($object_id)
2698 {
2699 function printNewItemTR ($alloclist)
2700 {
2701 printOpFormIntro ('addNATv4Rule');
2702 echo "<tr align='center'><td>";
2703 printImageHREF ('add', 'Add new NAT rule', TRUE);
2704 echo '</td><td>';
2705 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
2706 echo "<select name='localip' tabindex=1>";
2707
2708 foreach ($alloclist as $dottedquad => $alloc)
2709 {
2710 $name = empty ($alloc['addrinfo']['name']) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2711 $osif = empty ($alloc['osif']) ? '' : ($alloc['osif'] . ': ');
2712 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
2713 }
2714
2715 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2716 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2717 echo "<a href='javascript:;' onclick='window.open(\"" . makeHrefForHelper ('inet4list');
2718 echo "\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
2719 printImageHREF ('find', 'Find object');
2720 echo "</a>";
2721 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2722 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
2723 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
2724 echo "</td></tr></form>";
2725 }
2726
2727 $info = getObjectInfo ($object_id);
2728 $forwards = getNATv4ForObject ($object_id);
2729 $alloclist = getObjectIPv4Allocations ($object_id);
2730 showMessageOrError();
2731 echo "<center><h2>locally performed NAT</h2></center>";
2732
2733 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2734 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
2735
2736 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2737 printNewItemTR ($alloclist);
2738 foreach ($forwards['out'] as $pf)
2739 {
2740 $class = 'trerror';
2741 $osif = '';
2742 if (isset ($alloclist [$pf['localip']]))
2743 {
2744 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
2745 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
2746 }
2747
2748 echo "<tr class='$class'>";
2749 echo "<td><a href='".
2750 makeHrefProcess(array(
2751 'op'=>'delNATv4Rule',
2752 'localip'=>$pf['localip'],
2753 'localport'=>$pf['localport'],
2754 'remoteip'=>$pf['remoteip'],
2755 'remoteport'=>$pf['remoteport'],
2756 'proto'=>$pf['proto'],
2757 'object_id'=>$object_id)).
2758 "'>";
2759 printImageHREF ('delete', 'Delete NAT rule');
2760 echo "</a></td>";
2761 echo "<td>${pf['proto']}/${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}";
2762 if (!empty ($pf['local_addr_name']))
2763 echo ' (' . $pf['local_addr_name'] . ')';
2764 echo "</td>";
2765 echo "<td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2766
2767 $address = getIPv4Address ($pf['remoteip']);
2768
2769 echo "<td class='description'>";
2770 if (count ($address['allocs']))
2771 foreach ($address['allocs'] as $bond)
2772 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
2773 elseif (!empty ($pf['remote_addr_name']))
2774 echo '(' . $pf['remote_addr_name'] . ')';
2775 printOpFormIntro
2776 (
2777 'updNATv4Rule',
2778 array
2779 (
2780 'localip' => $pf['localip'],
2781 'localport' => $pf['localport'],
2782 'remoteip' => $pf['remoteip'],
2783 'remoteport' => $pf['remoteport'],
2784 'proto' => $pf['proto']
2785 )
2786 );
2787 echo "</td><td class='description'>";
2788 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2789 printImageHREF ('save', 'Save changes', TRUE);
2790 echo "</td></form></tr>";
2791 }
2792 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2793 printNewItemTR ($alloclist);
2794
2795 echo "</table><br><br>";
2796
2797 echo "<center><h2>arriving NAT connections</h2></center>";
2798 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2799 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2800
2801 foreach ($forwards['in'] as $pf)
2802 {
2803 echo "<tr><td><a href='".
2804 makeHrefProcess(array(
2805 'op'=>'delNATv4Rule',
2806 'localip'=>$pf['localip'],
2807 'localport'=>$pf['localport'],
2808 'remoteip'=>$pf['remoteip'],
2809 'remoteport'=>$pf['remoteport'],
2810 'proto'=>$pf['proto'],
2811 'object_id'=>$pf['object_id']
2812 )).
2813 "'>";
2814 printImageHREF ('delete', 'Delete NAT rule');
2815 echo "</a></td>";
2816 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
2817 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
2818 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2819 echo "<td class='description'>${pf['description']}</td></tr>";
2820 }
2821
2822 echo "</table><br><br>";
2823 }
2824
2825 function renderAddMultipleObjectsForm ()
2826 {
2827 showMessageOrError();
2828 $typelist = getObjectTypeList();
2829 $typelist[0] = 'select type...';
2830 $max = getConfigVar ('MASSCOUNT');
2831 $tabindex = 100;
2832
2833 startPortlet ('Distinct types, same tags');
2834 printOpFormIntro ('addObjects');
2835 echo '<table border=0 align=center>';
2836 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
2837 echo "<th>Asset tag</th><th>Barcode</th><th>Tags</th></tr>\n";
2838 for ($i = 0; $i < $max; $i++)
2839 {
2840 echo '<tr><td>';
2841 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2842 printSelect ($typelist, "${i}_object_type_id", 0, $tabindex);
2843 echo '</td>';
2844 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
2845 echo "<td><input type=text size=30 name=${i}_object_label tabindex=${tabindex}></td>";
2846 echo "<td><input type=text size=20 name=${i}_object_asset_no tabindex=${tabindex}></td>";
2847 echo "<td><input type=text size=10 name=${i}_object_barcode tabindex=${tabindex}></td>";
2848 if ($i == 0)
2849 {
2850 echo "<td valign=top rowspan=${max}>";
2851 renderNewEntityTags();
2852 echo "</td>\n";
2853 }
2854 echo "</tr>\n";
2855 $tabindex++;
2856 }
2857 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2858 echo "</form></table>\n";
2859 finishPortlet();
2860
2861 startPortlet ('Same type, same tags');
2862 printOpFormIntro ('addLotOfObjects');
2863 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2864 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
2865 echo "</textarea></td><td valign=top>";
2866 printSelect ($typelist, "global_type_id", getConfigVar ('DEFAULT_OBJECT_TYPE'));
2867 echo "</td></tr>";
2868 echo "<tr><th>Tags</th></tr>";
2869 echo "<tr><td valign=top>";
2870 renderNewEntityTags();
2871 echo "</td></tr>";
2872 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2873 echo "</form>\n";
2874 finishPortlet();
2875 }
2876
2877 function printGreeting ()
2878 {
2879 global $root, $remote_username, $remote_displayname;
2880 echo "Hello, <a href='${root}?page=myaccount&tab=default'>${remote_displayname}</a>. This is RackTables " .
2881 CODE_VERSION .
2882 ". Click <a href='${root}?logout'>here</a> to logout.";
2883 }
2884
2885 function renderSearchResults ()
2886 {
2887 global $root;