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