r2765 - renderNATv4ForObject(): remove unnecessary getObjectInfo() call
[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 (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 makeHref
896 (
897 array
898 (
899 'page'=>'depot',
900 'tab'=>'default',
901 'andor' => 'and',
902 'cfe' => '{$typeid_' . $info['objtype_id'] . '}',
903 )
904 )."&"
905 );
906 echo "</table><br>\n";
907 finishPortlet();
908
909 if (!empty ($info['comment']))
910 {
911 startPortlet ('Comment');
912 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
913 finishPortlet ();
914 }
915
916 renderFilesPortlet ('object', $object_id);
917
918 $ports = getObjectPortsAndLinks ($object_id);
919 if (count ($ports))
920 {
921 startPortlet ('ports and links');
922 usort($ports, 'sortByName');
923 if ($ports)
924 {
925 $hl_port_id = 0;
926 if (isset ($_REQUEST['hl_port_id']))
927 {
928 assertUIntArg ('hl_port_id', __FUNCTION__);
929 $hl_port_id = $_REQUEST['hl_port_id'];
930 }
931 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
932 echo "<tr><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
933 echo "<th>Rem. Object</th><th>Rem. port</th></tr>\n";
934 foreach ($ports as $port)
935 {
936 echo '<tr';
937 if ($hl_port_id == $port['id'])
938 echo ' class=port_highlight';
939 echo "><td>${port['name']}</td><td>${port['label']}</td><td>${port['type']}</td>";
940 echo "<td>${port['l2address']}</td>";
941 if ($port['remote_object_id'])
942 {
943 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>";
944 echo "<td>${port['remote_name']}</td>";
945 }
946 elseif (!empty ($port['reservation_comment']))
947 {
948 echo "<td><b>Reserved;</b></td>";
949 echo "<td>${port['reservation_comment']}</td>";
950 }
951 else
952 echo '<td>&nbsp;</td><td>&nbsp;</td>';
953 echo "</tr>\n";
954 }
955 echo "</table><br>\n";
956 }
957 finishPortlet();
958 }
959
960 $alloclist = getObjectIPv4Allocations ($object_id);
961 if (count ($alloclist))
962 {
963 startPortlet ('IPv4 addresses');
964 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
965 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
966 echo "<tr><th>OS interface</th><th>IP address</th><th>network</th><th>routed by</th><th>peers</th></tr>\n";
967 else
968 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
969 $hl_ipv4_addr = '';
970 if (isset ($_REQUEST['hl_ipv4_addr']))
971 {
972 assertIPv4Arg ('hl_ipv4_addr', __FUNCTION__);
973 $hl_ipv4_addr = $_REQUEST['hl_ipv4_addr'];
974 }
975 foreach ($alloclist as $dottedquad => $alloc)
976 {
977 $address_name = niftyString ($alloc['addrinfo']['name']);
978 $class = $alloc['addrinfo']['class'];
979 $secondclass = ($hl_ipv4_addr == $dottedquad) ? 'tdleft port_highlight' : 'tdleft';
980 $netid = getIPv4AddressNetworkId ($dottedquad);
981 if (NULL !== $netid)
982 {
983 $netinfo = spotEntity ('ipv4net', $netid);
984 loadIPv4AddrList ($netinfo);
985 }
986 echo "<tr class='${class}' valign=top><td class=tdleft>${alloc['osif']}</td><td class='${secondclass}'>";
987 if (NULL !== $netid)
988 echo "<a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$dottedquad, 'hl_object_id'=>$object_id))."'>${dottedquad}</a>";
989 else
990 echo $dottedquad;
991 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
992 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
993 echo '&nbsp;' . $aac[$alloc['type']];
994 if (!empty ($alloc['addrinfo']['name']))
995 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
996 echo '</td>';
997 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
998 {
999 if (NULL === $netid)
1000 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1001 else
1002 {
1003 echo "<td class='${secondclass}'>";
1004 renderCell ($netinfo);
1005 echo "</td>";
1006 // filter out self-allocation
1007 $other_routers = array();
1008 foreach (findRouters ($netinfo['addrlist']) as $router)
1009 if ($router['id'] != $object_id)
1010 $other_routers[] = $router;
1011 if (count ($other_routers))
1012 printRoutersTD ($other_routers);
1013 else
1014 echo "<td class='${secondclass}'>&nbsp;</td>";
1015 }
1016 }
1017 // peers
1018 echo "<td class='${secondclass}'>\n";
1019 $prefix = '';
1020 if ($alloc['addrinfo']['reserved'] == 'yes')
1021 {
1022 echo $prefix . '<strong>RESERVED</strong>';
1023 $prefix = '; ';
1024 }
1025 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1026 {
1027 if ($allocpeer['object_id'] == $object_id)
1028 continue;
1029 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1030 if (!empty ($allocpeer['osif']))
1031 echo $allocpeer['osif'] . '@';
1032 echo $allocpeer['object_name'] . '</a>';
1033 $prefix = '; ';
1034 }
1035 echo "</td></tr>\n";
1036 }
1037 echo "</table><br>\n";
1038 finishPortlet();
1039 }
1040
1041 $forwards = getNATv4ForObject ($object_id);
1042 if (count($forwards['in']) or count($forwards['out']))
1043 {
1044 startPortlet('NATv4');
1045
1046 if (count($forwards['out']))
1047 {
1048
1049 echo "<h3>locally performed NAT</h3>";
1050
1051 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
1052 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
1053
1054 foreach ($forwards['out'] as $pf)
1055 {
1056 $class = 'trerror';
1057 $osif = '';
1058 if (isset ($alloclist [$pf['localip']]))
1059 {
1060 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
1061 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
1062 }
1063 echo "<tr class='$class'>";
1064 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>";
1065 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
1066 $address = getIPv4Address ($pf['remoteip']);
1067 echo "<td class='description'>";
1068 if (count ($address['allocs']))
1069 foreach($address['allocs'] as $bond)
1070 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
1071 elseif (!empty ($pf['remote_addr_name']))
1072 echo '(' . $pf['remote_addr_name'] . ')';
1073 echo "</td><td class='description'>${pf['description']}</td></tr>";
1074 }
1075 echo "</table><br><br>";
1076 }
1077 if (count($forwards['in']))
1078 {
1079 echo "<h3>arriving NAT connections</h3>";
1080 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
1081 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
1082 foreach ($forwards['in'] as $pf)
1083 {
1084 echo "<tr>";
1085 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
1086 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
1087 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
1088 echo "<td class='description'>${pf['description']}</td></tr>";
1089 }
1090 echo "</table><br><br>";
1091 }
1092 finishPortlet();
1093 }
1094
1095 $pools = getRSPoolsForObject ($object_id);
1096 if (count ($pools))
1097 {
1098 $order = 'odd';
1099 startPortlet ('Real server pools (' . count ($pools) . ')');
1100 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
1101 echo "<tr><th>VS</th><th>RS pool</th><th>RS</th><th>VS config</th><th>RS config</th></tr>\n";
1102 foreach ($pools as $vs_id => $info)
1103 {
1104 echo "<tr valign=top class=row_${order}><td class=tdleft>";
1105 renderCell (spotEntity ('ipv4vs', $vs_id));
1106 echo "</td><td class=tdleft>";
1107 renderCell (spotEntity ('ipv4rspool', $info['pool_id']));
1108 echo '</td><td class=tdleft>' . $info['rscount'] . '</td>';
1109 echo "<td class=slbconf>${info['vsconfig']}</td>";
1110 echo "<td class=slbconf>${info['rsconfig']}</td>";
1111 echo "</tr>\n";
1112 $order = $nextorder[$order];
1113 }
1114 echo "</table>\n";
1115 finishPortlet();
1116 }
1117 echo "</td>\n";
1118
1119 // After left column we have (surprise!) right column with rackspace portlet only.
1120 echo "<td class=pcright>";
1121 // rackspace portlet
1122 startPortlet ('rackspace allocation');
1123 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1124 renderRack ($rack_id, $object_id);
1125 echo '<br>';
1126 finishPortlet();
1127 echo "</td></tr>";
1128 echo "</table>\n";
1129 }
1130
1131 function renderRackMultiSelect ($sname, $racks, $selected)
1132 {
1133 // Transform the given flat list into a list of groups, each representing a rack row.
1134 $rdata = array();
1135 foreach ($racks as $rack)
1136 if (!isset ($rdata[$rack['row_name']]))
1137 $rdata[$rack['row_name']] = array ($rack['id'] => $rack['name']);
1138 else
1139 $rdata[$rack['row_name']][$rack['id']] = $rack['name'];
1140 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementsByName(\"updateObjectAllocation\")[0].submit()'>\n";
1141 foreach ($rdata as $optgroup => $racklist)
1142 {
1143 echo "<optgroup label='${optgroup}'>";
1144 foreach ($racklist as $rack_id => $rack_name)
1145 {
1146 echo "<option value=${rack_id}";
1147 if (!(array_search ($rack_id, $selected) === FALSE))
1148 echo ' selected';
1149 echo">${rack_name}</option>\n";
1150 }
1151 }
1152 echo "</select>\n";
1153 }
1154
1155 function showMessageOrError ()
1156 {
1157 if (isset ($_SESSION['log']))
1158 {
1159 printLog ($_SESSION['log']);
1160 unset($_SESSION['log']);
1161 }
1162 }
1163
1164 // This function renders a form for port edition.
1165 function renderPortsForObject ($object_id)
1166 {
1167 function printNewItemTR ()
1168 {
1169 printOpFormIntro ('addPort');
1170 echo "<tr><td>";
1171 printImageHREF ('add', 'add a port', TRUE);
1172 echo "</td><td><input type=text size=8 name=port_name tabindex=100></td>\n";
1173 echo "<td><input type=text size=24 name=port_label tabindex=101></td><td>";
1174 printSelect (getPortTypes(), 'port_type_id', getConfigVar ('default_port_type'), 102);
1175 echo "<td><input type=text name=port_l2address tabindex=103></td>\n";
1176 echo "<td colspan=3>&nbsp;</td><td>";
1177 printImageHREF ('add', 'add a port', TRUE, 104);
1178 echo "</td></tr></form>";
1179 }
1180 startPortlet ('Ports and interfaces');
1181 $ports = getObjectPortsAndLinks ($object_id);
1182 usort($ports, 'sortByName');
1183 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1184 echo "<tr><th>&nbsp;</th><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
1185 echo "<th>Rem. object</th><th>Rem. port</th><th>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
1186 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1187 printNewItemTR();
1188 foreach ($ports as $port)
1189 {
1190 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
1191 echo "<tr><td><a href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id'], 'object_id'=>$object_id, 'port_name'=>$port['name']))."'>";
1192 printImageHREF ('delete', 'Unlink and Delete this port');
1193 echo "</a></td>\n";
1194 echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
1195 echo "<td><input type=text name=label value='${port['label']}' size=24></td>";
1196 if (!$port['remote_object_id'])
1197 {
1198 echo "<td>";
1199 printSelect (getPortTypes(), 'port_type_id', $port['type_id']);
1200 echo "</td>";
1201 }
1202 else
1203 {
1204 echo "<input type=hidden name=port_type_id value='${port['type_id']}'>";
1205 echo "<td class=tdleft>${port['type']}</td>\n";
1206 }
1207 echo "<td><input type=text name=l2address value='${port['l2address']}'></td>\n";
1208 if ($port['remote_object_id'])
1209 {
1210 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$port['remote_object_id']))."'>${port['remote_object_name']}</a></td>";
1211 echo "<td>${port['remote_name']}</td>";
1212 echo "<td><a href='".
1213 makeHrefProcess(array(
1214 'op'=>'unlinkPort',
1215 'port_id'=>$port['id'],
1216 'object_id'=>$object_id,
1217 'port_name'=>$port['name'],
1218 'remote_port_name'=>$port['remote_name'],
1219 'remote_object_name'=>$port['remote_object_name'])).
1220 "'>";
1221 printImageHREF ('cut', 'Unlink this port');
1222 echo "</a></td>";
1223 }
1224 elseif (!empty ($port['reservation_comment']))
1225 {
1226 echo "<td><b>Reserved;</b></td>";
1227 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
1228 echo "<td><a href='".
1229 makeHrefProcess(array(
1230 'op'=>'useup',
1231 'port_id'=>$port['id'],
1232 'object_id'=>$object_id)).
1233 "'>";
1234 printImageHREF ('clear', 'Use up this port');
1235 echo "</a></td>";
1236 }
1237 else
1238 {
1239 echo "<td>&nbsp;</td><td>&nbsp;</td>";
1240 echo "<td>";
1241 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\");'>";
1242 printImageHREF ('plug', 'Link this port');
1243 echo "</a> <input type=text name=reservation_comment>";
1244 echo "</td>\n";
1245 }
1246 echo "<td>";
1247 printImageHREF ('save', 'Save changes', TRUE);
1248 echo "</td></form></tr>\n";
1249 }
1250 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1251 printNewItemTR();
1252 echo "</table><br>\n";
1253 finishPortlet();
1254
1255 startPortlet ('Add/update multiple ports');
1256 printOpFormIntro ('addMultiPorts');
1257 echo 'Format: <select name=format tabindex=201>';
1258 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1259 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
1260 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
1261 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
1262 echo "</select>";
1263 echo 'Default port type: ';
1264 printSelect (getPortTypes(), 'port_type', getConfigVar ('default_port_type'), 202);
1265 echo "<input type=submit value='Parse output' tabindex=204><br>\n";
1266 echo "<textarea name=input cols=100 rows=50 tabindex=203></textarea><br>\n";
1267 echo '</form>';
1268 finishPortlet();
1269 }
1270
1271 function renderIPv4ForObject ($object_id)
1272 {
1273 function printNewItemTR ()
1274 {
1275 global $aat;
1276 printOpFormIntro ('addIPv4Allocation');
1277 echo "<tr><td>";
1278 printImageHREF ('add', 'allocate', TRUE);
1279 echo "</td>";
1280 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1281 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
1282 echo "<td colspan=2>&nbsp;</td><td>";
1283 printSelect ($aat, 'bond_type', NULL, 102);
1284 echo "</td><td>&nbsp;</td><td>";
1285 printImageHREF ('add', 'allocate', TRUE, 103);
1286 echo "</td></tr></form>";
1287 }
1288 global $aat;
1289 startPortlet ('Allocations');
1290 $alloclist = getObjectIPv4Allocations ($object_id);
1291 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1292 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1293 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1294 echo '<th>network</th><th>routed by</th>';
1295 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1296
1297 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1298 printNewItemTR();
1299 foreach ($alloclist as $dottedquad => $alloc)
1300 {
1301 $class = $alloc['addrinfo']['class'];
1302 $netid = getIPv4AddressNetworkId ($dottedquad);
1303 if (NULL !== $netid)
1304 {
1305 $netinfo = spotEntity ('ipv4net', $netid);
1306 loadIPv4AddrList ($netinfo);
1307 }
1308 printOpFormIntro ('updIPv4Allocation', array ('ip' => $dottedquad));
1309 echo "<tr class='$class' valign=top><td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$object_id))."'>";
1310 printImageHREF ('delete', 'Delete this IPv4 address');
1311 echo "</a></td>";
1312 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td><td class=tdleft>";
1313 if (NULL !== $netid)
1314 echo "<a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$dottedquad))."'>${dottedquad}</a>";
1315 else
1316 echo $dottedquad;
1317 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1318 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1319 if (!empty ($alloc['addrinfo']['name']))
1320 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1321 echo '</td>';
1322 // FIXME: this a copy-and-paste from renderRackObject()
1323 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1324 {
1325 if (NULL === $netid)
1326 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1327 else
1328 {
1329 echo '<td>';
1330 renderCell ($netinfo);
1331 echo '</td>';
1332 // filter out self-allocation
1333 $other_routers = array();
1334 foreach (findRouters ($netinfo['addrlist']) as $router)
1335 if ($router['id'] != $object_id)
1336 $other_routers[] = $router;
1337 if (count ($other_routers))
1338 printRoutersTD ($other_routers);
1339 else
1340 echo "<td>&nbsp;</td>";
1341 }
1342 }
1343 echo '<td>';
1344 printSelect ($aat, 'bond_type', $alloc['type']);
1345 echo "</td><td>";
1346 $prefix = '';
1347 if ($alloc['addrinfo']['reserved'] == 'yes')
1348 {
1349 echo $prefix . '<strong>RESERVED</strong>';
1350 $prefix = '; ';
1351 }
1352 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1353 {
1354 if ($allocpeer['object_id'] == $object_id)
1355 continue;
1356 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1357 if (!empty ($allocpeer['osif']))
1358 echo $allocpeer['osif'] . '@';
1359 echo $allocpeer['object_name'] . '</a>';
1360 $prefix = '; ';
1361 }
1362 echo "</td><td>";
1363 printImageHREF ('save', 'Save changes', TRUE);
1364 echo "</td></form></tr>\n";
1365 }
1366 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1367 printNewItemTR();
1368
1369 echo "</table><br>\n";
1370 finishPortlet();
1371
1372 }
1373
1374 // Log structure versions:
1375 // 1: the whole structure is a list of code-message pairs
1376 // 2 and later: there's a "v" field set, which indicates the version
1377 // 2: there's a "m" list set to hold message code and optional arguments
1378 function printLog ($log)
1379 {
1380 switch (TRUE)
1381 {
1382 case !isset ($log['v']):
1383 case $log['v'] == 1:
1384 foreach ($log as $key => $record)
1385 if ($key !== 'v')
1386 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1387 break;
1388 case $log['v'] == 2:
1389 $msginfo = array
1390 (
1391 // records 0~99 with success messages
1392 0 => array ('code' => 'success', 'format' => '%s'),
1393 1 => array ('code' => 'success', 'format' => '%u new records done, %u already existed'),
1394 2 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully added.'),
1395 3 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully deleted.'),
1396 4 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully updated'),
1397 5 => array ('code' => 'success', 'format' => 'Port %s was added successfully'),
1398 6 => array ('code' => 'success', 'format' => 'Port %s was updated successfully'),
1399 7 => array ('code' => 'success', 'format' => 'Port %s was deleted successfully'),
1400 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with port %s at object %s'),
1401 9 => array ('code' => 'success', 'format' => 'Port %s was successfully unlinked from %s@%s'),
1402 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1403 11 => array ('code' => 'success', 'format' => 'Reservation removed.'),
1404 12 => array ('code' => 'success', 'format' => 'allocation updated'),
1405 13 => array ('code' => 'success', 'format' => 'allocated'),
1406 14 => array ('code' => 'success', 'format' => 'deallocated'),
1407 15 => array ('code' => 'success', 'format' => 'Reset succeeded.'),
1408 16 => array ('code' => 'success', 'format' => 'Update done'),
1409 17 => array ('code' => 'success', 'format' => 'Update(s) succeeded.'),
1410 18 => array ('code' => 'success', 'format' => 'Load balancer was successfully added'),
1411 19 => array ('code' => 'success', 'format' => 'Load balancer was successfully deleted'),
1412 20 => array ('code' => 'success', 'format' => 'Load balancer info was successfully updated'),
1413 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1414 22 => array ('code' => 'success', 'format' => 'Chained %u tags'),
1415 23 => array ('code' => 'success', 'format' => 'IPv4 prefix successfully added'),
1416 24 => array ('code' => 'success', 'format' => 'IPv4 prefix deleted'),
1417 25 => array ('code' => 'success', 'format' => 'IPv4 prefix updated'),
1418 26 => array ('code' => 'success', 'format' => '%u IP address(es) were successfully updated'),
1419 27 => array ('code' => 'success', 'format' => 'IPv4 address updated'),
1420 28 => array ('code' => 'success', 'format' => 'Virtual service was successfully created'),
1421 29 => array ('code' => 'success', 'format' => 'Virtual service was successfully deleted'),
1422 30 => array ('code' => 'success', 'format' => 'Virtual service was successfully updated'),
1423 31 => array ('code' => 'success', 'format' => 'RS pool was successfully created'),
1424 32 => array ('code' => 'success', 'format' => 'RS pool was successfully deleted'),
1425 33 => array ('code' => 'success', 'format' => 'RS pool was successfully updated'),
1426 34 => array ('code' => 'success', 'format' => 'Real server was successfully added'),
1427 35 => array ('code' => 'success', 'format' => 'Real server was successfully deleted'),
1428 36 => array ('code' => 'success', 'format' => 'Real server was successfully updated'),
1429 37 => array ('code' => 'success', 'format' => 'Successfully added %u real servers'),
1430 38 => array ('code' => 'success', 'format' => '%u real server(s) were successfully (de)activated'),
1431 39 => array ('code' => 'success', 'format' => 'User account %s updated.'),
1432 40 => array ('code' => 'success', 'format' => 'User account %s created.'),
1433 // ...
1434 // ...
1435 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1436 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1437 45 => array ('code' => 'success', 'format' => "Attribute '%s' created."),
1438 46 => array ('code' => 'success', 'format' => 'Rename successful.'),
1439 47 => array ('code' => 'success', 'format' => 'Attribute was deleted.'),
1440 48 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1441 49 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1442 50 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1443 51 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1444 52 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1445 53 => array ('code' => 'success', 'format' => 'Chapter was deleted.'),
1446 54 => array ('code' => 'success', 'format' => 'Chapter was updated.'),
1447 55 => array ('code' => 'success', 'format' => 'Chapter was added.'),
1448 56 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1449 57 => array ('code' => 'success', 'format' => 'Reset complete'),
1450 58 => array ('code' => 'success', 'format' => "Deleted tag '%s'."),
1451 59 => array ('code' => 'success', 'format' => "Created tag '%s'."),
1452 60 => array ('code' => 'success', 'format' => "Updated tag '%s'."),
1453 61 => array ('code' => 'success', 'format' => 'Password changed successfully.'),
1454 62 => array ('code' => 'success', 'format' => 'gw: %s'),
1455 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
1456 64 => array ('code' => 'success', 'format' => 'Port %s@%s has been assigned to VLAN %u'),
1457 65 => array ('code' => 'success', 'format' => "Added new rack '%s'"),
1458 66 => array ('code' => 'success', 'format' => "File sent Ok via handler '%s'"),
1459 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1460 68 => array ('code' => 'success', 'format' => "Updated rack '%s'"),
1461 69 => array ('code' => 'success', 'format' => 'File "%s" was added successfully'),
1462 70 => array ('code' => 'success', 'format' => 'File "%s" was updated successfully'),
1463 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
1464 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
1465 73 => array ('code' => 'success', 'format' => 'File "%s" was deleted successfully'),
1466 74 => array ('code' => 'success', 'format' => 'Row "%s" was added successfully'),
1467 75 => array ('code' => 'success', 'format' => 'Row "%s" was updated successfully'),
1468 76 => array ('code' => 'success', 'format' => 'Object "%s" was deleted successfully'),
1469 77 => array ('code' => 'success', 'format' => 'Row "%s" was deleted successfully'),
1470 78 => array ('code' => 'success', 'format' => 'File "%s" saved Ok'),
1471 79 => array ('code' => 'success', 'format' => 'Rack "%s" was deleted successfully'),
1472 80 => array ('code' => 'success', 'format' => "Added new object '%s'"),
1473
1474 // records 100~199 with fatal error messages
1475 100 => array ('code' => 'error', 'format' => '%s'),
1476 101 => array ('code' => 'error', 'format' => 'Port name cannot be empty'),
1477 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
1478 103 => array ('code' => 'error', 'format' => 'User not found!'),
1479 104 => array ('code' => 'error', 'format' => "Error updating user account '%s'"),
1480 // ...
1481 // ...
1482 // ...
1483 108 => array ('code' => 'error', 'format' => '%u failures and %u successfull changes.'),
1484 109 => array ('code' => 'error', 'format' => 'Update failed!'),
1485 110 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1486 111 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1487 112 => array ('code' => 'error', 'format' => 'Error adding chapter.'),
1488 113 => array ('code' => 'error', 'format' => 'Error updating chapter.'),
1489 114 => array ('code' => 'error', 'format' => 'Error deleting chapter.'),
1490 115 => array ('code' => 'error', 'format' => 'Error renaming attribute.'),
1491 116 => array ('code' => 'error', 'format' => 'Error creating attribute.'),
1492 117 => array ('code' => 'error', 'format' => 'Error deleting attribute.'),
1493 118 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1494 119 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1495 120 => array ('code' => 'error', 'format' => 'Reset failed!'),
1496 121 => array ('code' => 'error', 'format' => 'commitUpdateObject() failed'),
1497 122 => array ('code' => 'error', 'format' => 'One or more update(s) failed!'),
1498 123 => array ('code' => 'error', 'format' => 'Cannot process submitted data: unknown format code.'),
1499 124 => array ('code' => 'error', 'format' => 'Error removing reservation!'),
1500 125 => array ('code' => 'error', 'format' => "Update failed with error: '%s'"),
1501 126 => array ('code' => 'error', 'format' => 'addRStoRSPool() failed'),
1502 127 => array ('code' => 'error', 'format' => 'Added %u real servers and encountered %u errors'),
1503 128 => array ('code' => 'error', 'format' => 'commitDeleteRS() failed'),
1504 129 => array ('code' => 'error', 'format' => 'commitDeleteLB() failed'),
1505 130 => array ('code' => 'error', 'format' => 'commitDeleteVS() failed'),
1506 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1507 132 => array ('code' => 'error', 'format' => 'invalid protocol'),
1508 133 => array ('code' => 'error', 'format' => 'commitUpdateRS() failed'),
1509 134 => array ('code' => 'error', 'format' => 'commitUpdateLB() failed'),
1510 135 => array ('code' => 'error', 'format' => 'commitUpdateVS() failed'),
1511 136 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1512 137 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1513 138 => array ('code' => 'error', 'format' => 'commitDeleteRSPool() failed'),
1514 139 => array ('code' => 'error', 'format' => 'commitUpdateRSPool() failed'),
1515 140 => array ('code' => 'error', 'format' => 'Encountered %u errors, (de)activated %u real servers'),
1516 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u IP address(es)'),
1517 142 => array ('code' => 'error', 'format' => 'executeAutoPorts() failed'),
1518 143 => array ('code' => 'error', 'format' => 'Tried chaining %u tags, but experienced %u errors.'),
1519 144 => array ('code' => 'error', 'format' => "Error deleting tag: '%s'"),
1520 145 => array ('code' => 'error', 'format' => "Invalid tag name '%s'"),
1521 // ...
1522 147 => array ('code' => 'error', 'format' => "Could not create tag '%s': %s"),
1523 148 => array ('code' => 'error', 'format' => "Could not update tag '%s': %s"),
1524 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1525 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1526 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1527 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1528 153 => array ('code' => 'error', 'format' => 'Password change failed.'),
1529 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1530 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1531 156 => array ('code' => 'error', 'format' => 'getSwitchVLANs() failed'),
1532 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
1533 158 => array ('code' => 'error', 'format' => 'Ignoring malformed record #%u in form submit'),
1534 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1535 160 => array ('code' => 'error', 'format' => 'Invalid arguments'),
1536 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1537 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
1538 163 => array ('code' => 'error', 'format' => 'Failed to get any response from queryGateway() or the gateway died'),
1539 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
1540 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1541 166 => array ('code' => 'error', 'format' => 'gw: %s'),
1542 167 => array ('code' => 'error', 'format' => 'Could not find port %s'),
1543 168 => array ('code' => 'error', 'format' => 'Port %s is a trunk'),
1544 169 => array ('code' => 'error', 'format' => 'Failed to configure %s, connector returned code %u'),
1545 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1546 171 => array ('code' => 'error', 'format' => "Failed creating rack '%s'. Already exists in this row?"),
1547 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1548 173 => array ('code' => 'error', 'format' => "Invalid IPv4 prefix '%s'"),
1549 174 => array ('code' => 'error', 'format' => 'Bad IPv4 address'),
1550 175 => array ('code' => 'error', 'format' => 'Invalid netmask'),
1551 176 => array ('code' => 'error', 'format' => 'This network already exists'),
1552 177 => array ('code' => 'error', 'format' => 'commitUpdateRack() failed'),
1553 178 => array ('code' => 'error', 'format' => 'file not found'),
1554 179 => array ('code' => 'error', 'format' => 'Declining outdated text. Re-edit the file for consistency.'),
1555 180 => array ('code' => 'error', 'format' => 'Error saving file, all changes lost!'),
1556 181 => array ('code' => 'error', 'format' => "file uploads not allowed, change 'file_uploads' parameter in php.ini"),
1557 182 => array ('code' => 'error', 'format' => 'SQL query failed: %s'),
1558 183 => array ('code' => 'error', 'format' => "Tag id '%s' does not exist."),
1559 184 => array ('code' => 'error', 'format' => 'Submitted form is invalid at line %u'),
1560 185 => array ('code' => 'error', 'format' => "Failed to add object '%s'"),
1561 186 => array ('code' => 'error', 'format' => 'Incomplete form has been ignored. Cheers.'),
1562 187 => array ('code' => 'error', 'format' => "Internal error in function '%s'"),
1563
1564 // records 200~299 with warnings
1565 200 => array ('code' => 'warning', 'format' => '%s'),
1566 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1567 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
1568 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1569 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1570 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
1571 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
1572 207 => array ('code' => 'warning', 'format' => 'Ignored empty request'),
1573
1574 );
1575 // Handle the arguments. Is there any better way to do it?
1576 foreach ($log['m'] as $record)
1577 {
1578 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1579 {
1580 echo '<div class=msg_neutral>(this message was lost)</div>';
1581 continue;
1582 }
1583 if (isset ($record['a']))
1584 switch (count ($record['a']))
1585 {
1586 case 1:
1587 $msgtext = sprintf
1588 (
1589 $msginfo[$record['c']]['format'],
1590 $record['a'][0]
1591 );
1592 break;
1593 case 2:
1594 $msgtext = sprintf
1595 (
1596 $msginfo[$record['c']]['format'],
1597 $record['a'][0],
1598 $record['a'][1]
1599 );
1600 break;
1601 case 3:
1602 $msgtext = sprintf
1603 (
1604 $msginfo[$record['c']]['format'],
1605 $record['a'][0],
1606 $record['a'][1],
1607 $record['a'][2]
1608 );
1609 break;
1610 case 4:
1611 default:
1612 $msgtext = sprintf
1613 (
1614 $msginfo[$record['c']]['format'],
1615 $record['a'][0],
1616 $record['a'][1],
1617 $record['a'][2],
1618 $record['a'][3]
1619 );
1620 break;
1621 }
1622 else
1623 $msgtext = $msginfo[$record['c']]['format'];
1624 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1625 }
1626 break;
1627 default:
1628 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1629 break;
1630 }
1631 }
1632
1633 /*
1634 The following conditions must be followed:
1635 1. We can mount onto free atoms only. This means: if any record for an atom
1636 already exists in RackSpace, it can't be used for mounting.
1637 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1638 and either delete them before unmounting or refuse to unmount the object.
1639 */
1640
1641 // We extensively use $_REQUEST in the function.
1642 function renderRackSpaceForObject ($object_id)
1643 {
1644 $is_update = isset ($_REQUEST['rackmulti'][0]);
1645 $info = spotEntity ('object', $object_id);
1646 if ($info == NULL)
1647 {
1648 showError ('Error loading data', __FUNCTION__);
1649 return;
1650 }
1651 // Always process occupied racks plus racks chosen by user. First get racks with
1652 // already allocated rackspace...
1653 if (NULL === ($workingRacksData = getResidentRacksData ($object_id)))
1654 die; // some error already shown
1655
1656 // ...and then add those chosen by user (if any).
1657 if (isset($_REQUEST['rackmulti']))
1658 foreach ($_REQUEST['rackmulti'] as $cand_id)
1659 {
1660 if (!isset ($workingRacksData[$cand_id]))
1661 {
1662 if (NULL == ($rackData = spotEntity ('rack', $cand_id)))
1663 {
1664 showError ('Rack not found', __FUNCTION__);
1665 return NULL;
1666 }
1667 amplifyCell ($rackData);
1668 $workingRacksData[$cand_id] = $rackData;
1669 }
1670 }
1671
1672 printOpFormIntro ('updateObjectAllocation');
1673
1674 // Do it only once...
1675 foreach ($workingRacksData as $rackId => &$rackData)
1676 {
1677 applyObjectMountMask ($rackData, $object_id);
1678 echo "<input type=\"hidden\" name=\"rackmulti[]\" value=\"$rackId\">";
1679 }
1680 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1681 unset ($rackData);
1682
1683 // This is the time for rendering.
1684
1685 // Main layout starts.
1686 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1687
1688 // Left portlet with rack list.
1689 echo "<td class=pcleft height='1%'>";
1690 startPortlet ('Racks');
1691 $allRacksData = listCells ('rack');
1692 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1693 {
1694 foreach ($allRacksData as $rack)
1695 {
1696 amplifyCell ($rack);
1697 $workingRacksData[$rack_id] = $rack;
1698 }
1699 foreach ($workingRacksData as &$rackData)
1700 applyObjectMountMask ($rackData, $object_id);
1701 unset ($rackData);
1702 }
1703 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1704 echo "<br>";
1705 echo "<br>";
1706 finishPortlet();
1707 echo "</td>";
1708
1709 // Middle portlet with comment and submit.
1710 echo "<td class=pcleft>";
1711 startPortlet ('Comment');
1712 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1713 echo "<input type=submit value='Save' name=got_atoms>\n";
1714 echo "<br>";
1715 echo "<br>";
1716 finishPortlet();
1717 echo "</td>";
1718
1719 // Right portlet with rendered racks. If this form submit is not final, we have to
1720 // reflect the former state of the grid in current form.
1721 echo "<td class=pcright rowspan=2 height='1%'>";
1722 startPortlet ('Working copy');
1723 echo '<table border=0 cellspacing=10 align=center><tr>';
1724 foreach ($workingRacksData as $rack_id => $rackData)
1725 {
1726 // Order is important here: only original allocation is highlighted.
1727 highlightObject ($rackData, $object_id);
1728 markupAtomGrid ($rackData, 'T');
1729 // If we have a form processed, discard user input and show new database
1730 // contents.
1731 if ($is_update)
1732 mergeGridFormToRack ($rackData);
1733 echo "<td valign=top>";
1734 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1735 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1736 echo "<tr><th width='10%'>&nbsp;</th>";
1737 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1738 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1739 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1740 renderAtomGrid ($rackData);
1741 echo "<tr><th width='10%'>&nbsp;</th>";
1742 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1743 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1744 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1745 echo "</table></center>\n";
1746 echo '</td>';
1747 }
1748 echo "</tr></table>";
1749 finishPortlet();
1750 echo "</td>\n";
1751
1752
1753 echo "</form>\n";
1754 echo "</tr></table>\n";
1755 }
1756
1757 function renderMolecule ($mdata, $object_id)
1758 {
1759 // sort data out
1760 $rackpack = array();
1761 global $loclist;
1762 foreach ($mdata as $rua)
1763 {
1764 $rack_id = $rua['rack_id'];
1765 $unit_no = $rua['unit_no'];
1766 $atom = $rua['atom'];
1767 if (!isset ($rackpack[$rack_id]))
1768 {
1769 $rackData = spotEntity ('rack', $rack_id);
1770 amplifyCell ($rackData);
1771 for ($i = $rackData['height']; $i > 0; $i--)
1772 for ($locidx = 0; $locidx < 3; $locidx++)
1773 $rackData[$i][$locidx]['state'] = 'F';
1774 $rackpack[$rack_id] = $rackData;
1775 }
1776 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1777 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1778 }
1779 // now we have some racks to render
1780 foreach ($rackpack as $rackData)
1781 {
1782 markAllSpans ($rackData);
1783 echo "<table class=molecule cellspacing=0>\n";
1784 echo "<caption>${rackData['name']}</caption>\n";
1785 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1786 for ($i = $rackData['height']; $i > 0; $i--)
1787 {
1788 echo "<tr><th>$i</th>";
1789 for ($locidx = 0; $locidx < 3; $locidx++)
1790 {
1791 $state = $rackData[$i][$locidx]['state'];
1792 echo "<td class=state_${state}>&nbsp;</td>\n";
1793 }
1794 echo "</tr>\n";
1795 }
1796 echo "</table>\n";
1797 }
1798 }
1799
1800 function renderEmptyPortsSelect ($port_id, $type_id)
1801 {
1802 $ports = getEmptyPortsOfType($type_id);
1803 usort($ports, 'sortEmptyPorts');
1804 foreach ($ports as $port)
1805 {
1806 if ($port_id == $port['Port_id'])
1807 continue;
1808 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";
1809 }
1810 }
1811
1812 function renderDepot ()
1813 {
1814 global $pageno, $nextorder;
1815 $cellfilter = getCellFilter();
1816 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
1817
1818 echo "<table border=0 class=objectview>\n";
1819 echo "<tr><td class=pcleft>";
1820
1821 startPortlet ('Objects (' . count ($objects) . ')');
1822 if ($objects === NULL)
1823 {
1824 showError ('Fatal error retrieving object list', __FUNCTION__);
1825 return;
1826 }
1827 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1828 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Row/Rack</th></tr>';
1829 $order = 'odd';
1830 foreach ($objects as $obj)
1831 {
1832 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1833 $secondclass = 'tdleft port_highlight';
1834 else
1835 $secondclass = 'tdleft';
1836 $tags = loadEntityTags ('object', $obj['id']);
1837 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>";
1838 if (count ($tags))
1839 echo '<br><small>' . serializeTags ($tags, makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
1840 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
1841 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
1842 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
1843 if ($obj['rack_id'])
1844 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>";
1845 else
1846 echo "<td class='${secondclass}'>Unmounted</td>";
1847 echo '</tr>';
1848 $order = $nextorder[$order];
1849 }
1850 echo '</table>';
1851 finishPortlet();
1852
1853 echo "</td><td class=pcright width='25%'>";
1854
1855 renderCellFilterPortlet ($cellfilter, 'object');
1856 echo "</td></tr></table>\n";
1857 }
1858
1859 // History viewer for history-enabled simple dictionaries.
1860 function renderHistory ($object_type, $object_id)
1861 {
1862 switch ($object_type)
1863 {
1864 case 'row':
1865 $query = "select ctime, user_name, name, comment from RackRowHistory where id = ${object_id} order by ctime";
1866 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>rack row comment</th></tr>';
1867 $extra = 3;
1868 break;
1869 case 'rack':
1870 $query =
1871 "select ctime, user_name, rh.name, rr.name as name, rh.height, rh.comment " .
1872 "from RackHistory as rh left join RackRow as rr on rh.row_id = rr.id " .
1873 "where rh.id = ${object_id} order by ctime";
1874 $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>';
1875 $extra = 5;
1876 break;
1877 case 'object':
1878 $query =
1879 "select ctime, user_name, RackObjectHistory.name as name, label, barcode, asset_no, has_problems, dict_value, comment " .
1880 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key join Chapter on Dictionary.chapter_id = Chapter.id " .
1881 "where Chapter.name = 'RackObjectType' and RackObjectHistory.id=${object_id} order by ctime";
1882 $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>';
1883 $extra = 8;
1884 break;
1885 default:
1886 showError ("Uknown object type '${object_type}'", __FUNCTION__);
1887 return;
1888 }
1889 global $dbxlink;
1890 $result = $dbxlink->query ($query);
1891 if ($result == NULL)
1892 {
1893 showError ('SQL query failed', __FUNCTION__);
1894 return;
1895 }
1896 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1897 $order = 'odd';
1898 global $nextorder;
1899 echo $header;
1900 while ($row = $result->fetch (PDO::FETCH_NUM))
1901 {
1902 echo "<tr class=row_${order}><td>${row[0]}</td>";
1903 for ($i = 1; $i <= $extra; $i++)
1904 echo "<td>" . $row[$i] . "</td>";
1905 echo "</tr>\n";
1906 $order = $nextorder[$order];
1907 }
1908 echo "</table><br>\n";
1909 }
1910
1911 function renderRackspaceHistory ()
1912 {
1913 global $nextorder, $pageno, $tabno;
1914 $order = 'odd';
1915 $history = getRackspaceHistory();
1916 // Show the last operation by default.
1917 if (isset ($_REQUEST['op_id']))
1918 $op_id = $_REQUEST['op_id'];
1919 elseif (isset ($history[0]['mo_id']))
1920 $op_id = $history[0]['mo_id'];
1921 else $op_id = NULL;
1922
1923 $omid = NULL;
1924 $nmid = NULL;
1925 $object_id = 1;
1926 if ($op_id)
1927 list ($omid, $nmid) = getOperationMolecules ($op_id);
1928
1929 // Main layout starts.
1930 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1931
1932 // Left top portlet with old allocation.
1933 echo "<tr><td class=pcleft>";
1934 startPortlet ('Old allocation');
1935 if ($omid)
1936 {
1937 $oldMolecule = getMolecule ($omid);
1938 renderMolecule ($oldMolecule, $object_id);
1939 }
1940 else
1941 echo "nothing";
1942 finishPortlet();
1943
1944 echo '</td><td class=pcright>';
1945
1946 // Right top portlet with new allocation
1947 startPortlet ('New allocation');
1948 if ($nmid)
1949 {
1950 $newMolecule = getMolecule ($nmid);
1951 renderMolecule ($newMolecule, $object_id);
1952 }
1953 else
1954 echo "nothing";
1955 finishPortlet();
1956
1957 echo '</td></tr><tr><td colspan=2>';
1958
1959 // Bottom portlet with list
1960
1961 startPortlet ('Rackspace allocation history');
1962 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1963 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";
1964 foreach ($history as $row)
1965 {
1966 if ($row['mo_id'] == $op_id)
1967 $class = 'hl';
1968 else
1969 $class = "row_${order}";
1970 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
1971 echo "<td>${row['user_name']}</td>";
1972 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
1973 echo "</tr>\n";
1974 $order = $nextorder[$order];
1975 }
1976 echo "</table>\n";
1977 finishPortlet();
1978
1979 echo '</td></tr></table>';
1980 }
1981
1982 function renderIPv4SpaceRecords ($tree, &$tagcache, $baseurl, $target = 0, $level = 1)
1983 {
1984 $self = __FUNCTION__;
1985 foreach ($tree as $item)
1986 {
1987 $total = $item['addrt'];
1988 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
1989 {
1990 loadIPv4AddrList ($item); // necessary to compute router list and address counter
1991 $used = $item['addrc'];
1992 }
1993 else
1994 {
1995 $item['addrlist'] = array();
1996 $item['addrc'] = 0;
1997 }
1998 if (isset ($item['id']))
1999 {
2000 if ($item['symbol'] == 'node-collapsed')
2001 $expandurl = "${baseurl}&eid=" . $item['id'] . "#netid" . $item['id'];
2002 elseif ($item['symbol'] == 'node-expanded')
2003 $expandurl = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#netid${item['parent_id']}" : '');
2004 else
2005 $expandurl = '';
2006 echo "<tr valign=top>";
2007 printIPv4NetInfoTDs ($item, 'tdleft', $level, $item['symbol'], $expandurl);
2008 echo "<td class=tdcenter>";
2009 if ($target == $item['id'])
2010 echo "<a name=netid${target}></a>";
2011 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2012 {
2013 renderProgressBar ($total ? $used/$total : 0);
2014 echo "<br><small>${used}/${total}</small>";
2015 }
2016 else
2017 echo "<small>${total}</small>";
2018 echo "</td>";
2019 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2020 printRoutersTD (findRouters ($item['addrlist']), $tagcache);
2021 echo "</tr>";
2022 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2023 $self ($item['kids'], $tagcache, $baseurl, $target, $level + 1);
2024 }
2025 else
2026 {
2027 echo "<tr valign=top>";
2028 printIPv4NetInfoTDs ($item, 'tdleft sparenetwork', $level, $item['symbol']);
2029 echo "<td class=tdcenter>";
2030 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2031 {
2032 renderProgressBar ($used/$total, 'sparenetwork');
2033 echo "<br><small>${used}/${total}</small>";
2034 }
2035 else
2036 echo "<small>${total}</small>";
2037 echo "</td><td>&nbsp;</td></tr>";
2038 }
2039 }
2040 }
2041
2042 function renderIPv4Space ()
2043 {
2044 global $pageno, $tabno;
2045 $cellfilter = getCellFilter();
2046 $netlist = filterCellList (listCells ('ipv4net'), $cellfilter['expression']);
2047 array_walk ($netlist, 'amplifyCell');
2048
2049 $netcount = count ($netlist);
2050 // expand request can take either natural values or "ALL". Zero means no expanding.
2051 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2052 $tree = prepareIPv4Tree ($netlist, $eid);
2053
2054 echo "<table border=0 class=objectview>\n";
2055 echo "<tr><td class=pcleft>";
2056 startPortlet ("networks (${netcount})");
2057 echo '<h4>';
2058 if ($eid === 0)
2059 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2060 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2061 $cellfilter['urlextra'] . "'>expand all</a>)";
2062 elseif ($eid === 'ALL')
2063 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2064 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2065 else
2066 {
2067 $netinfo = spotEntity ('ipv4net', $eid);
2068 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>)";
2069 }
2070 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2071 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2072 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2073 echo "<th>routed by</th>";
2074 echo "</tr>\n";
2075 $tagcache = array();
2076 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2077 renderIPv4SpaceRecords ($tree, $tagcache, $baseurl, $eid);
2078 echo "</table>\n";
2079 finishPortlet();
2080 echo '</td><td class=pcright>';
2081 renderCellFilterPortlet ($cellfilter, 'ipv4net');
2082 echo "</td></tr></table>\n";
2083 }
2084
2085 function renderIPv4SLB ()
2086 {
2087 global $page, $nextorder;
2088
2089 startPortlet ('SLB configuration');
2090 echo "<table border=0 width='100%'><tr>";
2091 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2092 echo "<td><h3><a href='".makeHref(array('page'=>$pno))."'>" . $page[$pno]['title'] . "</a></h3></td>";
2093 echo '</tr></table>';
2094 finishPortlet();
2095
2096 $summary = getSLBSummary();
2097 startPortlet ('SLB tactical overview');
2098 // A single id-keyed array isn't used here to preserve existing
2099 // order of LBs returned by getSLBSummary()
2100 $lblist = array();
2101 $lbdname = array();
2102 foreach ($summary as $vipdata)
2103 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2104 if (!in_array ($lb_object_id, $lblist))
2105 {
2106 $oi = spotEntity ('object', $lb_object_id);
2107 $lbdname[$lb_object_id] = $oi['dname'];
2108 $lblist[] = $lb_object_id;
2109 }
2110 if (!count ($summary))
2111 echo 'none configured';
2112 else
2113 {
2114 $order = 'odd';
2115 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2116 echo "<tr valign=top><td>&nbsp;</td>";
2117 foreach ($lblist as $lb_object_id)
2118 {
2119 #echo "<th><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$lb_object_id))."'>" . $lbdname[$lb_object_id] . "</a></th>";
2120 echo '<td>';
2121 renderLBCell ($lb_object_id);
2122 echo '</td>';
2123 }
2124 echo "</tr>\n";
2125 foreach ($summary as $vsid => $vsdata)
2126 {
2127 echo "<tr class=row_${order}><td class=tdleft>";
2128 renderCell (spotEntity ('ipv4vs', $vsid));
2129 echo "</td>";
2130 foreach ($lblist as $lb_object_id)
2131 {
2132 echo '<td class=tdleft>';
2133 if (!isset ($vsdata['lblist'][$lb_object_id]))
2134 echo '&nbsp;';
2135 else
2136 {
2137 echo $vsdata['lblist'][$lb_object_id]['size'];
2138 // echo " (<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$vsdata['lblist'][$lb_object_id]['id'])). "'>";
2139 // echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2140 }
2141 echo '</td>';
2142 }
2143 echo "</tr>\n";
2144 $order = $nextorder[$order];
2145 }
2146 echo "</table>\n";
2147 }
2148 finishPortlet ();
2149 }
2150
2151 function renderIPv4SpaceEditor ()
2152 {
2153 // IPv4 validator
2154 ?>
2155 <script type="text/javascript">
2156 function init() {
2157 document.add_new_range.range.setAttribute('match', "^\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\/\\d\\d?$");
2158
2159 Validate.init();
2160 }
2161 window.onload=init;
2162 </script>
2163 <?php
2164
2165 startPortlet ("Add new");
2166 echo '<table border=0 cellpadding=10 align=center>';
2167 // This form requires a name, so JavaScript validator can find it.
2168 // No printOpFormIntro() hence
2169 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2170 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2171 // tags column
2172 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2173 renderNewEntityTags();
2174 echo '</td>';
2175 // inputs column
2176 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=18 class='live-validate' tabindex=1></td>";
2177 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2178 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2179 echo "<tr><td colspan=2>";
2180 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2181 echo '</td></tr>';
2182 echo "</form></table><br><br>\n";
2183 finishPortlet();
2184
2185 $addrspaceList = listCells ('ipv4net');
2186 array_walk ($addrspaceList, 'amplifyCell');
2187 if (count ($addrspaceList))
2188 {
2189 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2190 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2191 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>&nbsp;</th></tr>";
2192 foreach ($addrspaceList as $netinfo)
2193 {
2194 echo "<form method=post action='".makeHrefProcess(array('op'=>'updIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2195 echo "<tr valign=top><td>";
2196 if (getConfigVar ('IPV4_JAYWALK') == 'yes')
2197 {
2198 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2199 printImageHREF ('destroy', 'Delete this prefix');
2200 echo "</a>";
2201 }
2202 else // only render clickable image for empty networks
2203 {
2204 $netdata = spotEntity ('ipv4net', $netinfo['id']);
2205 loadIPv4AddrList ($netdata);
2206 if (count ($netdata['addrlist']))
2207 printImageHREF ('nodestroy', 'There are ' . count ($netdata['addrlist']) . ' allocations inside');
2208 else
2209 {
2210 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2211 printImageHREF ('destroy', 'Delete this prefix');
2212 echo "</a>";
2213 }
2214
2215 }
2216 echo "</td>\n<td class=tdleft>${netinfo['ip']}/${netinfo['mask']}</td>";
2217 echo "<td><input type=text name=name size=40 value='${netinfo['name']}'>";
2218 echo "</td><td>";
2219 printImageHREF ('save', 'Save changes', TRUE);
2220 echo "</td></tr></form>\n";
2221 }
2222 echo "</table>";
2223 finishPortlet();
2224 }
2225 }
2226
2227 function renderIPv4Network ($id)
2228 {
2229 global $pageno, $tabno, $aac2;
2230 $netmaskbylen = array
2231 (
2232 32 => '255.255.255.255',
2233 31 => '255.255.255.254',
2234 30 => '255.255.255.252',
2235 29 => '255.255.255.248',
2236 28 => '255.255.255.240',
2237 27 => '255.255.255.224',
2238 26 => '255.255.255.192',
2239 25 => '255.255.255.128',
2240 24 => '255.255.255.0',
2241 23 => '255.255.254.0',
2242 22 => '255.255.252.0',
2243 21 => '255.255.248.0',
2244 20 => '255.255.240.0',
2245 19 => '255.255.224.0',
2246 18 => '255.255.192.0',
2247 17 => '255.255.128.0',
2248 16 => '255.255.0.0',
2249 15 => '255.254.0.0',
2250 14 => '255.252.0.0',
2251 13 => '255.248.0.0',
2252 12 => '255.240.0.0',
2253 11 => '255.224.0.0',
2254 10 => '255.192.0.0',
2255 9 => '255.128.0.0',
2256 8 => '255.0.0.0',
2257 7 => '254.0.0.0',
2258 6 => '252.0.0.0',
2259 5 => '248.0.0.0',
2260 4 => '240.0.0.0',
2261 3 => '224.0.0.0',
2262 2 => '192.0.0.0',
2263 1 => '128.0.0.0'
2264 );
2265 $wildcardbylen = array
2266 (
2267 32 => '0.0.0.0',
2268 31 => '0.0.0.1',
2269 30 => '0.0.0.3',
2270 29 => '0.0.0.7',
2271 28 => '0.0.0.15',
2272 27 => '0.0.0.31',
2273 26 => '0.0.0.63',
2274 25 => '0.0.0.127',
2275 24 => '0.0.0.255',
2276 23 => '0.0.1.255',
2277 22 => '0.0.3.255',
2278 21 => '0.0.7.255',
2279 20 => '0.0.15.255',
2280 19 => '0.0.31.255',
2281 18 => '0.0.63.255',
2282 17 => '0.0.127.255',
2283 16 => '0.0.255.25',
2284 15 => '0.1.255.255',
2285 14 => '0.3.255.255',
2286 13 => '0.7.255.255',
2287 12 => '0.15.255.255',
2288 11 => '0.31.255.255',
2289 10 => '0.63.255.255',
2290 9 => '0.127.255.255',
2291 8 => '0.255.255.255',
2292 7 => '1.255.255.255',
2293 6 => '3.255.255.255',
2294 5 => '7.255.255.255',
2295 4 => '15.255.255.255',
2296 3 => '31.255.255.255',
2297 2 => '63.255.255.255',
2298 1 => '127.255.255.255'
2299 );
2300 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2301 if (isset($_REQUEST['pg']))
2302 $page = $_REQUEST['pg'];
2303 else
2304 $page=0;
2305
2306 $range = spotEntity ('ipv4net', $id);
2307 loadIPv4AddrList ($range);
2308 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2309 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></td></tr>\n";
2310
2311 echo "<tr><td class=pcleft width='50%'>";
2312 startPortlet ('summary');
2313 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2314 $used = count ($range['addrlist']);
2315 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2316
2317 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2318 renderProgressBar ($used/$total);
2319 echo "&nbsp;${used}/${total}</td></tr>\n";
2320
2321 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2322 {
2323 // Build a backtrace from all parent networks.
2324 $clen = $range['mask'];
2325 $backtrace = array();
2326 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2327 {
2328 $upperinfo = spotEntity ('ipv4net', $upperid);
2329 $clen = $upperinfo['mask'];
2330 $backtrace[] = $upperinfo;
2331 }
2332 $arrows = count ($backtrace);
2333 foreach (array_reverse ($backtrace) as $ainfo)
2334 {
2335 echo "<tr><th width='50%' class=tdright>";
2336 for ($i = 0; $i < $arrows; $i++)
2337 echo '&uarr;';
2338 $arrows--;
2339 echo "</th><td class=tdleft>";
2340 renderCell ($ainfo);
2341 echo "</td></tr>";
2342 }
2343 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
2344 echo "<td class=tdleft>";
2345 renderCell ($range);
2346 echo "</td></tr>";
2347 // FIXME: get and display nested networks
2348 // $theitem = pickLeaf ($ipv4tree, $id);
2349 }
2350
2351 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2352 echo $netmaskbylen[$range['mask']];
2353 echo "</td></tr>\n";
2354
2355 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2356 printf ('0x%08X', binMaskFromDec ($range['mask']));
2357 echo "</td></tr>\n";
2358
2359 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2360 echo $wildcardbylen[$range['mask']];
2361 echo "</td></tr>\n";
2362
2363 $routers = findRouters ($range['addrlist']);
2364 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers))
2365 {
2366 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2367 printRoutersTD ($routers);
2368 echo "</tr>\n";
2369 }
2370
2371 printTagTRs (makeHref(array('page'=>'ipv4space', 'tab'=>'default'))."&");
2372 echo "</table><br>\n";
2373 finishPortlet();
2374
2375 renderFilesPortlet ('ipv4net', $id);
2376 echo "</td>\n";
2377
2378 echo "<td class=pcright>";
2379 startPortlet ('details');
2380 $startip = $range['ip_bin'] & $range['mask_bin'];
2381 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2382 $realstartip = $startip;
2383 $realendip = $endip;
2384 $numpages = 0;
2385 if($endip - $startip > $maxperpage)
2386 {
2387 $numpages = ($endip - $startip)/$maxperpage;
2388 $startip = $startip + $page * $maxperpage;
2389 $endip = $startip + $maxperpage-1;
2390 }
2391 echo "<center>";
2392 if ($numpages)
2393 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2394 for ($i=0; $i<$numpages; $i++)
2395 {
2396 if ($i == $page)
2397 echo "<b>$i</b> ";
2398 else
2399 echo "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'id'=>$id, 'pg'=>$i))."'>$i</a> ";
2400 }
2401 echo "</center>";
2402
2403 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2404 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2405
2406
2407 for ($ip = $startip; $ip <= $endip; $ip++) :
2408 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2409 $secondstyle = 'tdleft port_highlight';
2410 else
2411 $secondstyle = 'tdleft';
2412 if (!isset ($range['addrlist'][$ip]))
2413 {
2414 echo "<tr><td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>ip_long2quad($ip)))."'>" . ip_long2quad($ip);
2415 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2416 continue;
2417 }
2418 $addr = $range['addrlist'][$ip];
2419 echo "<tr class='${addr['class']}'>";
2420
2421 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
2422 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2423 $delim = '';
2424 $prologue = '';
2425 if ( $addr['reserved'] == 'yes')
2426 {
2427 echo "<strong>RESERVED</strong> ";
2428 $delim = '; ';
2429 }
2430 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2431 {
2432 echo $delim . $aac2[$ref['type']];
2433 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'hl_ipv4_addr'=>$addr['ip']))."'>";
2434 echo $ref['name'] . (empty ($ref['name']) ? '' : '@');
2435 echo "${ref['object_name']}</a>";
2436 $delim = '; ';
2437 }
2438 if ($delim != '')
2439 {
2440 $delim = '';
2441 $prologue = '<br>';
2442 }
2443 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2444 {
2445 echo $prologue;
2446 $prologue = '';
2447 echo "${delim}<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id']))."'>";
2448 echo "${ref['object_name']}</a>:<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$ref['vs_id']))."'>";
2449 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2450 $delim = '; ';
2451 }
2452 if ($delim != '')
2453 {
2454 $delim = '';
2455 $prologue = '<br>';
2456 }
2457 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2458 {
2459 echo $prologue;
2460 $prologue = '';
2461 echo "${delim}&rarr;${ref['rsport']}@<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$ref['rspool_id']))."'>";
2462 echo "${ref['rspool_name']}</a>";
2463 $delim = '; ';
2464 }
2465 echo "</td></tr>\n";
2466 endfor;
2467 // end of iteration
2468
2469 echo "</table>";
2470 finishPortlet();
2471 echo "</td></tr></table>\n";
2472 }
2473
2474 function renderIPv4NetworkProperties ($id)
2475 {
2476 $netdata = spotEntity ('ipv4net', $id);
2477 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
2478 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2479 printOpFormIntro ('editRange');
2480 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${netdata['name']}'></tr>";
2481 echo "<tr><td colspan=2 class=tdcenter>";
2482 printImageHREF ('SAVE', 'Save changes', TRUE);
2483 echo "</td></form></tr></table>\n";
2484 }
2485
2486 function renderIPv4Address ($dottedquad)
2487 {
2488 global $aat;
2489 $address = getIPv4Address ($dottedquad);
2490 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2491 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2492 if (!empty ($address['name']))
2493 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
2494
2495 echo "<tr><td class=pcleft>";
2496 startPortlet ('summary');
2497 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2498 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
2499 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2500 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2501 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
2502 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2503 printTagTRs();
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 preg_match (RE_L2_IPCFG, $terms