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