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