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