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