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