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