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