553a444610c0a24f3aa2d8802f6e0d34d4b14940
[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') .
2070 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2071 $cellfilter['urlextra'] . "'>expand all</a>)";
2072 elseif ($eid === 'ALL')
2073 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2074 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2075 else
2076 {
2077 $netinfo = getIPv4NetworkInfo ($eid);
2078 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>)";
2079 }
2080 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2081 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2082 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2083 echo "<th>routed by</th>";
2084 echo "</tr>\n";
2085 $tagcache = array();
2086 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2087 renderIPv4SpaceRecords ($tree, $tagcache, $baseurl, $eid);
2088 echo "</table>\n";
2089 finishPortlet();
2090 echo '</td><td class=pcright>';
2091 renderCellFilterPortlet ($cellfilter, 'ipv4net');
2092 echo "</td></tr></table>\n";
2093 }
2094
2095 function renderIPv4SLB ()
2096 {
2097 global $page, $nextorder;
2098
2099 startPortlet ('SLB configuration');
2100 echo "<table border=0 width='100%'><tr>";
2101 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2102 echo "<td><h3><a href='".makeHref(array('page'=>$pno))."'>" . $page[$pno]['title'] . "</a></h3></td>";
2103 echo '</tr></table>';
2104 finishPortlet();
2105
2106 $summary = getSLBSummary();
2107 startPortlet ('SLB tactical overview');
2108 // A single id-keyed array isn't used here to preserve existing
2109 // order of LBs returned by getSLBSummary()
2110 $lblist = array();
2111 $lbdname = array();
2112 foreach ($summary as $vipdata)
2113 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2114 if (!in_array ($lb_object_id, $lblist))
2115 {
2116 $oi = getObjectInfo ($lb_object_id);
2117 $lbdname[$lb_object_id] = $oi['dname'];
2118 $lblist[] = $lb_object_id;
2119 }
2120 if (!count ($summary))
2121 echo 'none configured';
2122 else
2123 {
2124 $order = 'odd';
2125 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2126 echo "<tr valign=top><td>&nbsp;</td>";
2127 foreach ($lblist as $lb_object_id)
2128 {
2129 #echo "<th><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$lb_object_id))."'>" . $lbdname[$lb_object_id] . "</a></th>";
2130 echo '<td>';
2131 renderLBCell ($lb_object_id);
2132 echo '</td>';
2133 }
2134 echo "</tr>\n";
2135 foreach ($summary as $vsid => $vsdata)
2136 {
2137 echo "<tr class=row_${order}><td class=tdleft>";
2138 renderVSCell ($vsid);
2139 echo "</td>";
2140 foreach ($lblist as $lb_object_id)
2141 {
2142 echo '<td class=tdleft>';
2143 if (!isset ($vsdata['lblist'][$lb_object_id]))
2144 echo '&nbsp;';
2145 else
2146 {
2147 echo $vsdata['lblist'][$lb_object_id]['size'];
2148 // echo " (<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$vsdata['lblist'][$lb_object_id]['id'])). "'>";
2149 // echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2150 }
2151 echo '</td>';
2152 }
2153 echo "</tr>\n";
2154 $order = $nextorder[$order];
2155 }
2156 echo "</table>\n";
2157 }
2158 finishPortlet ();
2159 }
2160
2161 function renderIPv4SpaceEditor ()
2162 {
2163 // IPv4 validator
2164 ?>
2165 <script type="text/javascript">
2166 function init() {
2167 document.add_new_range.range.setAttribute('match', "^\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\/\\d\\d?$");
2168
2169 Validate.init();
2170 }
2171 window.onload=init;
2172 </script>
2173 <?php
2174
2175 startPortlet ("Add new");
2176 echo '<table border=0 cellpadding=10 align=center>';
2177 // This form requires a name, so JavaScript validator can find it.
2178 // No printOpFormIntro() hence
2179 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2180 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2181 // tags column
2182 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2183 renderNewEntityTags();
2184 echo '</td>';
2185 // inputs column
2186 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=18 class='live-validate' tabindex=1></td>";
2187 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2188 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2189 echo "<tr><td colspan=2>";
2190 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2191 echo '</td></tr>';
2192 echo "</form></table><br><br>\n";
2193 finishPortlet();
2194
2195 $addrspaceList = listCells ('ipv4net');
2196 array_walk ($addrspaceList, 'amplifyCell');
2197 if (count ($addrspaceList))
2198 {
2199 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2200 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2201 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>&nbsp;</th></tr>";
2202 foreach ($addrspaceList as $netinfo)
2203 {
2204 echo "<form method=post action='".makeHrefProcess(array('op'=>'updIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2205 echo "<tr valign=top><td>";
2206 if (getConfigVar ('IPV4_JAYWALK') == 'yes')
2207 {
2208 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2209 printImageHREF ('destroy', 'Delete this prefix');
2210 echo "</a>";
2211 }
2212 else // only render clickable image for empty networks
2213 {
2214 $netdata = getIPv4NetworkInfo ($netinfo['id']);
2215 loadIPv4AddrList ($netdata);
2216 if (count ($netdata['addrlist']))
2217 printImageHREF ('nodestroy', 'There are ' . count ($netdata['addrlist']) . ' allocations inside');
2218 else
2219 {
2220 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2221 printImageHREF ('destroy', 'Delete this prefix');
2222 echo "</a>";
2223 }
2224
2225 }
2226 echo "</td>\n<td class=tdleft>${netinfo['ip']}/${netinfo['mask']}</td>";
2227 echo "<td><input type=text name=name size=40 value='${netinfo['name']}'>";
2228 echo "</td><td>";
2229 printImageHREF ('save', 'Save changes', TRUE);
2230 echo "</td></tr></form>\n";
2231 }
2232 echo "</table>";
2233 finishPortlet();
2234 }
2235 }
2236
2237 function renderIPv4Network ($id)
2238 {
2239 global $pageno, $tabno, $aac2;
2240 $netmaskbylen = array
2241 (
2242 32 => '255.255.255.255',
2243 31 => '255.255.255.254',
2244 30 => '255.255.255.252',
2245 29 => '255.255.255.248',
2246 28 => '255.255.255.240',
2247 27 => '255.255.255.224',
2248 26 => '255.255.255.192',
2249 25 => '255.255.255.128',
2250 24 => '255.255.255.0',
2251 23 => '255.255.254.0',
2252 22 => '255.255.252.0',
2253 21 => '255.255.248.0',
2254 20 => '255.255.240.0',
2255 19 => '255.255.224.0',
2256 18 => '255.255.192.0',
2257 17 => '255.255.128.0',
2258 16 => '255.255.0.0',
2259 15 => '255.254.0.0',
2260 14 => '255.252.0.0',
2261 13 => '255.248.0.0',
2262 12 => '255.240.0.0',
2263 11 => '255.224.0.0',
2264 10 => '255.192.0.0',
2265 9 => '255.128.0.0',
2266 8 => '255.0.0.0',
2267 7 => '254.0.0.0',
2268 6 => '252.0.0.0',
2269 5 => '248.0.0.0',
2270 4 => '240.0.0.0',
2271 3 => '224.0.0.0',
2272 2 => '192.0.0.0',
2273 1 => '128.0.0.0'
2274 );
2275 $wildcardbylen = array
2276 (
2277 32 => '0.0.0.0',
2278 31 => '0.0.0.1',
2279 30 => '0.0.0.3',
2280 29 => '0.0.0.7',
2281 28 => '0.0.0.15',
2282 27 => '0.0.0.31',
2283 26 => '0.0.0.63',
2284 25 => '0.0.0.127',
2285 24 => '0.0.0.255',
2286 23 => '0.0.1.255',
2287 22 => '0.0.3.255',
2288 21 => '0.0.7.255',
2289 20 => '0.0.15.255',
2290 19 => '0.0.31.255',
2291 18 => '0.0.63.255',
2292 17 => '0.0.127.255',
2293 16 => '0.0.255.25',
2294 15 => '0.1.255.255',
2295 14 => '0.3.255.255',
2296 13 => '0.7.255.255',
2297 12 => '0.15.255.255',
2298 11 => '0.31.255.255',
2299 10 => '0.63.255.255',
2300 9 => '0.127.255.255',
2301 8 => '0.255.255.255',
2302 7 => '1.255.255.255',
2303 6 => '3.255.255.255',
2304 5 => '7.255.255.255',
2305 4 => '15.255.255.255',
2306 3 => '31.255.255.255',
2307 2 => '63.255.255.255',
2308 1 => '127.255.255.255'
2309 );
2310 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2311 if (isset($_REQUEST['pg']))
2312 $page = $_REQUEST['pg'];
2313 else
2314 $page=0;
2315
2316 $range = getIPv4NetworkInfo ($id);
2317 loadIPv4AddrList ($range);
2318 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2319 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></td></tr>\n";
2320
2321 echo "<tr><td class=pcleft width='50%'>";
2322 startPortlet ('summary');
2323 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2324 $used = count ($range['addrlist']);
2325 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2326
2327 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2328 renderProgressBar ($used/$total);
2329 echo "&nbsp;${used}/${total}</td></tr>\n";
2330
2331 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2332 {
2333 // Build a backtrace from all parent networks.
2334 $clen = $range['mask'];
2335 $backtrace = array();
2336 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2337 {
2338 $upperinfo = getIPv4NetworkInfo ($upperid);
2339 $clen = $upperinfo['mask'];
2340 $backtrace[] = $upperid;
2341 }
2342 $arrows = count ($backtrace);
2343 foreach (array_reverse ($backtrace) as $ancestorid)
2344 {
2345 $ainfo = getIPv4NetworkInfo ($ancestorid);
2346 echo "<tr><th width='50%' class=tdright>";
2347 for ($i = 0; $i < $arrows; $i++)
2348 echo '&uarr;';
2349 $arrows--;
2350 echo "</th><td class=tdleft>";
2351 renderIPv4NetCell ($ainfo);
2352 echo "</td></tr>";
2353 }
2354 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
2355 echo "<td class=tdleft>";
2356 renderIPv4NetCell ($range);
2357 echo "</td></tr>";
2358 // FIXME: get and display nested networks
2359 // $theitem = pickLeaf ($ipv4tree, $id);
2360 }
2361
2362 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2363 echo $netmaskbylen[$range['mask']];
2364 echo "</td></tr>\n";
2365
2366 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2367 printf ('0x%08X', binMaskFromDec ($range['mask']));
2368 echo "</td></tr>\n";
2369
2370 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2371 echo $wildcardbylen[$range['mask']];
2372 echo "</td></tr>\n";
2373
2374 $routers = findRouters ($range['addrlist']);
2375 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers))
2376 {
2377 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2378 printRoutersTD ($routers);
2379 echo "</tr>\n";
2380 }
2381
2382 printTagTRs (makeHref(array('page'=>'ipv4space', 'tab'=>'default'))."&");
2383 echo "</table><br>\n";
2384 finishPortlet();
2385
2386 renderFilesPortlet ('ipv4net', $id);
2387 echo "</td>\n";
2388
2389 echo "<td class=pcright>";
2390 startPortlet ('details');
2391 $startip = $range['ip_bin'] & $range['mask_bin'];
2392 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2393 $realstartip = $startip;
2394 $realendip = $endip;
2395 $numpages = 0;
2396 if($endip - $startip > $maxperpage)
2397 {
2398 $numpages = ($endip - $startip)/$maxperpage;
2399 $startip = $startip + $page * $maxperpage;
2400 $endip = $startip + $maxperpage-1;
2401 }
2402 echo "<center>";
2403 if ($numpages)
2404 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2405 for ($i=0; $i<$numpages; $i++)
2406 {
2407 if ($i == $page)
2408 echo "<b>$i</b> ";
2409 else
2410 echo "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'id'=>$id, 'pg'=>$i))."'>$i</a> ";
2411 }
2412 echo "</center>";
2413
2414 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2415 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2416
2417
2418 for ($ip = $startip; $ip <= $endip; $ip++) :
2419 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2420 $secondstyle = 'tdleft port_highlight';
2421 else
2422 $secondstyle = 'tdleft';
2423 if (!isset ($range['addrlist'][$ip]))
2424 {
2425 echo "<tr><td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>ip_long2quad($ip)))."'>" . ip_long2quad($ip);
2426 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2427 continue;
2428 }
2429 $addr = $range['addrlist'][$ip];
2430 echo "<tr class='${addr['class']}'>";
2431
2432 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
2433 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2434 $delim = '';
2435 $prologue = '';
2436 if ( $addr['reserved'] == 'yes')
2437 {
2438 echo "<strong>RESERVED</strong> ";
2439 $delim = '; ';
2440 }
2441 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2442 {
2443 echo $delim . $aac2[$ref['type']];
2444 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'hl_ipv4_addr'=>$addr['ip']))."'>";
2445 echo $ref['name'] . (empty ($ref['name']) ? '' : '@');
2446 echo "${ref['object_name']}</a>";
2447 $delim = '; ';
2448 }
2449 if ($delim != '')
2450 {
2451 $delim = '';
2452 $prologue = '<br>';
2453 }
2454 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2455 {
2456 echo $prologue;
2457 $prologue = '';
2458 echo "${delim}<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id']))."'>";
2459 echo "${ref['object_name']}</a>:<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$ref['vs_id']))."'>";
2460 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2461 $delim = '; ';
2462 }
2463 if ($delim != '')
2464 {
2465 $delim = '';
2466 $prologue = '<br>';
2467 }
2468 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2469 {
2470 echo $prologue;
2471 $prologue = '';
2472 echo "${delim}&rarr;${ref['rsport']}@<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$ref['rspool_id']))."'>";
2473 echo "${ref['rspool_name']}</a>";
2474 $delim = '; ';
2475 }
2476 echo "</td></tr>\n";
2477 endfor;
2478 // end of iteration
2479
2480 echo "</table>";
2481 finishPortlet();
2482 echo "</td></tr></table>\n";
2483 }
2484
2485 function renderIPv4NetworkProperties ($id)
2486 {
2487 $netdata = getIPv4NetworkInfo ($id);
2488 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
2489 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2490 printOpFormIntro ('editRange');
2491 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${netdata['name']}'></tr>";
2492 echo "<tr><td colspan=2 class=tdcenter>";
2493 printImageHREF ('SAVE', 'Save changes', TRUE);
2494 echo "</td></form></tr></table>\n";
2495 }
2496
2497 function renderIPv4Address ($dottedquad)
2498 {
2499 global $aat;
2500 $address = getIPv4Address ($dottedquad);
2501 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2502 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2503 if (!empty ($address['name']))
2504 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
2505
2506 echo "<tr><td class=pcleft>";
2507 startPortlet ('summary');
2508 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2509 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
2510 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2511 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2512 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
2513 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2514 printTagTRs();
2515 echo "</table><br>\n";
2516 finishPortlet();
2517 echo "</td>\n";
2518
2519 echo "<td class=pcright>";
2520
2521 if (isset ($address['class']))
2522 {
2523 startPortlet ('allocations');
2524 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2525 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2526 $class = $address['class'];
2527 // render all allocation records for this address the same way
2528 if ($address['reserved'] == 'yes')
2529 echo "<tr class='${class}'><td colspan=2>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td></tr>";
2530 foreach ($address['allocs'] as $bond)
2531 {
2532 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2533 $secondclass = 'tdleft port_highlight';
2534 else
2535 $secondclass = 'tdleft';
2536 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>";
2537 echo $aat[$bond['type']];
2538 echo "</strong></td></tr>\n";
2539 }
2540 echo "</table><br><br>";
2541 finishPortlet();
2542 }
2543
2544 // FIXME: The returned list is structured differently, than we expect it to be. One of the sides
2545 // must be fixed.
2546 if (count ($address['lblist']))
2547 {
2548 startPortlet ('Virtual services (' . count ($address['lblist']) . ')');
2549 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2550 echo "<tr><th>VS</th><th>name</th></tr>\n";
2551 foreach ($address['lblist'] as $vsinfo)
2552 {
2553 echo "<tr><td class=tdleft><a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$vsinfo['vs_id']))."'>";
2554 echo buildVServiceName ($vsinfo) . "</a></td><td class=tdleft>";
2555 echo $vsinfo['name'] . "</td></tr>\n";
2556 }
2557 echo "</table><br><br>";
2558 finishPortlet();
2559 }
2560
2561 if (count ($address['rslist']))
2562 {
2563 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2564 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2565 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
2566 foreach ($address['rslist'] as $rsinfo)
2567 {
2568 echo "<tr><td>";
2569 if ($rsinfo['inservice'] == 'yes')
2570 printImageHREF ('inservice', 'in service');
2571 else
2572 printImageHREF ('notinservice', 'NOT in service');
2573 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsinfo['rspool_id']))."'>";
2574 echo $rsinfo['rspool_name'] . "</a></td></tr>\n";
2575 }
2576 echo "</table><br><br>";
2577 finishPortlet();
2578 }
2579
2580 if (count ($address['outpf']))
2581 {
2582 startPortlet ('departing NAT rules');
2583 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2584 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2585 foreach ($address['outpf'] as $rule)
2586 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2587 echo "</table>";
2588 finishPortlet();
2589 }
2590
2591 if (count ($address['inpf']))
2592 {
2593 startPortlet ('arriving NAT rules');
2594 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2595 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2596 foreach ($address['inpf'] as $rule)
2597 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2598 echo "</table>";
2599 finishPortlet();
2600 }
2601
2602 echo "</td></tr>";
2603 echo "</table>\n";
2604 }
2605
2606 function renderIPv4AddressProperties ($dottedquad)
2607 {
2608 $address = getIPv4Address ($dottedquad);
2609 echo "<center><h1>$dottedquad</h1></center>\n";
2610
2611 startPortlet ('update');
2612 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2613 printOpFormIntro ('editAddress');
2614 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2615 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2616 echo ($address['reserved']=='yes') ? 'checked' : '';
2617 echo "></tr><tr><td class=tdleft>";
2618 printImageHREF ('SAVE', 'Save changes', TRUE);
2619 echo "</td></form><td class=tdright>";
2620 if (empty ($address['name']) and $address['reserved'] == 'no')
2621 printImageHREF ('CLEAR gray');
2622 else
2623 {
2624 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2625 printImageHREF ('CLEAR', 'Release', TRUE);
2626 echo "</form>";
2627 }
2628 echo "</td></tr></table>\n";
2629 finishPortlet();
2630 }
2631
2632 function renderIPv4AddressAllocations ($dottedquad)
2633 {
2634 function printNewItemTR ()
2635 {
2636 global $aat;
2637 printOpFormIntro ('addIPv4Allocation');
2638 echo "<tr><td>";
2639 printImageHREF ('add', 'allocate', TRUE);
2640 echo "</td><td>";
2641 printSelect (getNarrowObjectList ('IPV4OBJ_LISTSRC'), 'object_id', NULL, 100);
2642 echo "</td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
2643 printSelect ($aat, 'bond_type', NULL, 102);
2644 echo "</td><td>";
2645 printImageHREF ('add', 'allocate', TRUE, 103);
2646 echo "</td></form></tr>";
2647 }
2648 global $aat;
2649
2650 $address = getIPv4Address ($dottedquad);
2651
2652 echo "<center><h1>${dottedquad}</h1></center>\n";
2653 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2654 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
2655
2656 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2657 printNewItemTR();
2658 if (isset ($address['class']))
2659 {
2660 $class = $address['class'];
2661 if ($address['reserved'] == 'yes')
2662 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2663 foreach ($address['allocs'] as $bond)
2664 {
2665 echo "<tr class='$class'>";
2666 printOpFormIntro ('updIPv4Allocation', array ('object_id' => $bond['object_id']));
2667 echo "<td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$bond['object_id']))."'>";
2668 printImageHREF ('delete', 'Unallocate address');
2669 echo "</a></td>";
2670 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$bond['object_id'], 'hl_ipv4_addr'=>$dottedquad))."'>${bond['object_name']}</td>";
2671 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
2672 printSelect ($aat, 'bond_type', $bond['type']);
2673 echo "</td><td>";
2674 printImageHREF ('save', 'Save changes', TRUE);
2675 echo "</td></form></tr>\n";
2676 }
2677 }
2678 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2679 printNewItemTR();
2680 echo "</table><br><br>";
2681 }
2682
2683 function renderNATv4ForObject ($object_id)
2684 {
2685 function printNewItemTR ($alloclist)
2686 {
2687 printOpFormIntro ('addNATv4Rule');
2688 echo "<tr align='center'><td>";
2689 printImageHREF ('add', 'Add new NAT rule', TRUE);
2690 echo '</td><td>';
2691 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
2692 echo "<select name='localip' tabindex=1>";
2693
2694 foreach ($alloclist as $dottedquad => $alloc)
2695 {
2696 $name = empty ($alloc['addrinfo']['name']) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2697 $osif = empty ($alloc['osif']) ? '' : ($alloc['osif'] . ': ');
2698 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
2699 }
2700
2701 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2702 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2703 echo "<a href='javascript:;' onclick='window.open(\"" . makeHrefForHelper ('inet4list');
2704 echo "\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
2705 printImageHREF ('find', 'Find object');
2706 echo "</a>";
2707 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2708 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
2709 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
2710 echo "</td></tr></form>";
2711 }
2712
2713 $info = getObjectInfo ($object_id);
2714 $forwards = getNATv4ForObject ($object_id);
2715 $alloclist = getObjectIPv4Allocations ($object_id);
2716 echo "<center><h2>locally performed NAT</h2></center>";
2717
2718 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2719 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
2720
2721 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2722 printNewItemTR ($alloclist);
2723 foreach ($forwards['out'] as $pf)
2724 {
2725 $class = 'trerror';
2726 $osif = '';
2727 if (isset ($alloclist [$pf['localip']]))
2728 {
2729 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
2730 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
2731 }
2732
2733 echo "<tr class='$class'>";
2734 echo "<td><a href='".
2735 makeHrefProcess(array(
2736 'op'=>'delNATv4Rule',
2737 'localip'=>$pf['localip'],
2738 'localport'=>$pf['localport'],
2739 'remoteip'=>$pf['remoteip'],
2740 'remoteport'=>$pf['remoteport'],
2741 'proto'=>$pf['proto'],
2742 'object_id'=>$object_id)).
2743 "'>";
2744 printImageHREF ('delete', 'Delete NAT rule');
2745 echo "</a></td>";
2746 echo "<td>${pf['proto']}/${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}";
2747 if (!empty ($pf['local_addr_name']))
2748 echo ' (' . $pf['local_addr_name'] . ')';
2749 echo "</td>";
2750 echo "<td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2751
2752 $address = getIPv4Address ($pf['remoteip']);
2753
2754 echo "<td class='description'>";
2755 if (count ($address['allocs']))
2756 foreach ($address['allocs'] as $bond)
2757 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
2758 elseif (!empty ($pf['remote_addr_name']))
2759 echo '(' . $pf['remote_addr_name'] . ')';
2760 printOpFormIntro
2761 (
2762 'updNATv4Rule',
2763 array
2764 (
2765 'localip' => $pf['localip'],
2766 'localport' => $pf['localport'],
2767 'remoteip' => $pf['remoteip'],
2768 'remoteport' => $pf['remoteport'],
2769 'proto' => $pf['proto']
2770 )
2771 );
2772 echo "</td><td class='description'>";
2773 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2774 printImageHREF ('save', 'Save changes', TRUE);
2775 echo "</td></form></tr>";
2776 }
2777 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2778 printNewItemTR ($alloclist);
2779
2780 echo "</table><br><br>";
2781
2782 echo "<center><h2>arriving NAT connections</h2></center>";
2783 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2784 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2785
2786 foreach ($forwards['in'] as $pf)
2787 {
2788 echo "<tr><td><a href='".
2789 makeHrefProcess(array(
2790 'op'=>'delNATv4Rule',
2791 'localip'=>$pf['localip'],
2792 'localport'=>$pf['localport'],
2793 'remoteip'=>$pf['remoteip'],
2794 'remoteport'=>$pf['remoteport'],
2795 'proto'=>$pf['proto'],
2796 'object_id'=>$pf['object_id']
2797 )).
2798 "'>";
2799 printImageHREF ('delete', 'Delete NAT rule');
2800 echo "</a></td>";
2801 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
2802 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
2803 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2804 echo "<td class='description'>${pf['description']}</td></tr>";
2805 }
2806
2807 echo "</table><br><br>";
2808 }
2809
2810 function renderAddMultipleObjectsForm ()
2811 {
2812 $typelist = getObjectTypeList();
2813 $typelist[0] = 'select type...';
2814 $max = getConfigVar ('MASSCOUNT');
2815 $tabindex = 100;
2816
2817 startPortlet ('Distinct types, same tags');
2818 printOpFormIntro ('addObjects');
2819 echo '<table border=0 align=center>';
2820 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
2821 echo "<th>Asset tag</th><th>Barcode</th><th>Tags</th></tr>\n";
2822 for ($i = 0; $i < $max; $i++)
2823 {
2824 echo '<tr><td>';
2825 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2826 printSelect ($typelist, "${i}_object_type_id", 0, $tabindex);
2827 echo '</td>';
2828 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
2829 echo "<td><input type=text size=30 name=${i}_object_label tabindex=${tabindex}></td>";
2830 echo "<td><input type=text size=20 name=${i}_object_asset_no tabindex=${tabindex}></td>";
2831 echo "<td><input type=text size=10 name=${i}_object_barcode tabindex=${tabindex}></td>";
2832 if ($i == 0)
2833 {
2834 echo "<td valign=top rowspan=${max}>";
2835 renderNewEntityTags();
2836 echo "</td>\n";
2837 }
2838 echo "</tr>\n";
2839 $tabindex++;
2840 }
2841 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2842 echo "</form></table>\n";
2843 finishPortlet();
2844
2845 startPortlet ('Same type, same tags');
2846 printOpFormIntro ('addLotOfObjects');
2847 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2848 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
2849 echo "</textarea></td><td valign=top>";
2850 printSelect ($typelist, "global_type_id", getConfigVar ('DEFAULT_OBJECT_TYPE'));
2851 echo "</td></tr>";
2852 echo "<tr><th>Tags</th></tr>";
2853 echo "<tr><td valign=top>";
2854 renderNewEntityTags();
2855 echo "</td></tr>";
2856 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2857 echo "</form>\n";
2858 finishPortlet();
2859 }
2860
2861 function printGreeting ()
2862 {
2863 global $root, $remote_username, $remote_displayname;
2864 echo "Hello, <a href='${root}?page=myaccount&tab=default'>${remote_displayname}</a>. This is RackTables " .
2865 CODE_VERSION .
2866 ". Click <a href='${root}?logout'>here</a> to logout.";
2867 }
2868
2869 function renderSearchResults ()
2870 {
2871 global $root;
2872 $terms = trim ($_REQUEST['q']);
2873 if (empty ($terms))
2874 {
2875 showError ('Search string cannot be empty.', __FUNCTION__);
2876 return;