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