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