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