r2460 - restore the check removed by changeset:2211, make it depend on IPV4_JAYWALK...
[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 if (count ($addrspaceList))
2283 {
2284 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2285 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2286 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>&nbsp;</th></tr>";
2287 foreach ($addrspaceList as $netinfo)
2288 {
2289 echo "<form method=post action='".makeHrefProcess(array('op'=>'updIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2290 echo "<tr valign=top><td>";
2291 if (getConfigVar ('IPV4_JAYWALK') == 'yes')
2292 {
2293 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2294 printImageHREF ('destroy', 'Delete this prefix');
2295 echo "</a>";
2296 }
2297 else // only render clickable image for empty networks
2298 {
2299 $netdata = getIPv4NetworkInfo ($netinfo['id']);
2300 loadIPv4AddrList ($netdata);
2301 if (count ($netdata['addrlist']))
2302 printImageHREF ('nodestroy', 'There are ' . count ($netdata['addrlist']) . ' allocations inside');
2303 else
2304 {
2305 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2306 printImageHREF ('destroy', 'Delete this prefix');
2307 echo "</a>";
2308 }
2309
2310 }
2311 echo "</td>\n<td class=tdleft>${netinfo['ip']}/${netinfo['mask']}</td>";
2312 echo "<td><input type=text name=name size=40 value='${netinfo['name']}'>";
2313 echo "</td><td>";
2314 printImageHREF ('save', 'Save changes', TRUE);
2315 echo "</td></tr></form>\n";
2316 }
2317 echo "</table>";
2318 finishPortlet();
2319 }
2320 }
2321
2322 function renderIPv4Network ($id)
2323 {
2324 global $pageno, $tabno, $aac2;
2325 $netmaskbylen = array
2326 (
2327 32 => '255.255.255.255',
2328 31 => '255.255.255.254',
2329 30 => '255.255.255.252',
2330 29 => '255.255.255.248',
2331 28 => '255.255.255.240',
2332 27 => '255.255.255.224',
2333 26 => '255.255.255.192',
2334 25 => '255.255.255.128',
2335 24 => '255.255.255.0',
2336 23 => '255.255.254.0',
2337 22 => '255.255.252.0',
2338 21 => '255.255.248.0',
2339 20 => '255.255.240.0',
2340 19 => '255.255.224.0',
2341 18 => '255.255.192.0',
2342 17 => '255.255.128.0',
2343 16 => '255.255.0.0',
2344 15 => '255.254.0.0',
2345 14 => '255.252.0.0',
2346 13 => '255.248.0.0',
2347 12 => '255.240.0.0',
2348 11 => '255.224.0.0',
2349 10 => '255.192.0.0',
2350 9 => '255.128.0.0',
2351 8 => '255.0.0.0',
2352 7 => '254.0.0.0',
2353 6 => '252.0.0.0',
2354 5 => '248.0.0.0',
2355 4 => '240.0.0.0',
2356 3 => '224.0.0.0',
2357 2 => '192.0.0.0',
2358 1 => '128.0.0.0'
2359 );
2360 $wildcardbylen = array
2361 (
2362 32 => '0.0.0.0',
2363 31 => '0.0.0.1',
2364 30 => '0.0.0.3',
2365 29 => '0.0.0.7',
2366 28 => '0.0.0.15',
2367 27 => '0.0.0.31',
2368 26 => '0.0.0.63',
2369 25 => '0.0.0.127',
2370 24 => '0.0.0.255',
2371 23 => '0.0.1.255',
2372 22 => '0.0.3.255',
2373 21 => '0.0.7.255',
2374 20 => '0.0.15.255',
2375 19 => '0.0.31.255',
2376 18 => '0.0.63.255',
2377 17 => '0.0.127.255',
2378 16 => '0.0.255.25',
2379 15 => '0.1.255.255',
2380 14 => '0.3.255.255',
2381 13 => '0.7.255.255',
2382 12 => '0.15.255.255',
2383 11 => '0.31.255.255',
2384 10 => '0.63.255.255',
2385 9 => '0.127.255.255',
2386 8 => '0.255.255.255',
2387 7 => '1.255.255.255',
2388 6 => '3.255.255.255',
2389 5 => '7.255.255.255',
2390 4 => '15.255.255.255',
2391 3 => '31.255.255.255',
2392 2 => '63.255.255.255',
2393 1 => '127.255.255.255'
2394 );
2395 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2396 if (isset($_REQUEST['pg']))
2397 $page = $_REQUEST['pg'];
2398 else
2399 $page=0;
2400
2401 $range = getIPv4NetworkInfo ($id);
2402 loadIPv4AddrList ($range);
2403 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2404 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></td></tr>\n";
2405
2406 echo "<tr><td class=pcleft width='50%'>";
2407 startPortlet ('summary');
2408 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2409 $used = count ($range['addrlist']);
2410 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2411
2412 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2413 renderProgressBar ($used/$total);
2414 echo "&nbsp;${used}/${total}</td></tr>\n";
2415
2416 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2417 {
2418 // Build a backtrace from all parent networks.
2419 $clen = $range['mask'];
2420 $backtrace = array();
2421 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2422 {
2423 $upperinfo = getIPv4NetworkInfo ($upperid);
2424 $clen = $upperinfo['mask'];
2425 $backtrace[] = $upperid;
2426 }
2427 $arrows = count ($backtrace);
2428 foreach (array_reverse ($backtrace) as $ancestorid)
2429 {
2430 $ainfo = getIPv4NetworkInfo ($ancestorid);
2431 echo "<tr><th width='50%' class=tdright>";
2432 for ($i = 0; $i < $arrows; $i++)
2433 echo '&uarr;';
2434 $arrows--;
2435 echo "</th><td class=tdleft><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'id'=>$ainfo['id']))."'>${ainfo['ip']}/${ainfo['mask']}</a></td></tr>";
2436 }
2437 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
2438 echo "<td class=tdleft>${range['ip']}/${range['mask']}</td></tr>";
2439 // FIXME: get and display nested networks
2440 // $theitem = pickLeaf ($ipv4tree, $id);
2441 }
2442
2443 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2444 echo $netmaskbylen[$range['mask']];
2445 echo "</td></tr>\n";
2446
2447 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2448 printf ('0x%08X', binMaskFromDec ($range['mask']));
2449 echo "</td></tr>\n";
2450
2451 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2452 echo $wildcardbylen[$range['mask']];
2453 echo "</td></tr>\n";
2454
2455 $routers = findRouters ($range['addrlist']);
2456 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers))
2457 {
2458 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2459 printRoutersTD ($routers);
2460 echo "</tr>\n";
2461 }
2462
2463 printTagTRs (makeHref(array('page'=>'ipv4space', 'tab'=>'default'))."&");
2464 echo "</table><br>\n";
2465 finishPortlet();
2466
2467 renderFilesPortlet ('ipv4net', $id);
2468 echo "</td>\n";
2469
2470 echo "<td class=pcright>";
2471 startPortlet ('details');
2472 $startip = $range['ip_bin'] & $range['mask_bin'];
2473 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2474 $realstartip = $startip;
2475 $realendip = $endip;
2476 $numpages = 0;
2477 if($endip - $startip > $maxperpage)
2478 {
2479 $numpages = ($endip - $startip)/$maxperpage;
2480 $startip = $startip + $page * $maxperpage;
2481 $endip = $startip + $maxperpage-1;
2482 }
2483 echo "<center>";
2484 if ($numpages)
2485 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2486 for ($i=0; $i<$numpages; $i++)
2487 {
2488 if ($i == $page)
2489 echo "<b>$i</b> ";
2490 else
2491 echo "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'id'=>$id, 'pg'=>$i))."'>$i</a> ";
2492 }
2493 echo "</center>";
2494
2495 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2496 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2497
2498
2499 for ($ip = $startip; $ip <= $endip; $ip++) :
2500 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2501 $secondstyle = 'tdleft port_highlight';
2502 else
2503 $secondstyle = 'tdleft';
2504 if (!isset ($range['addrlist'][$ip]))
2505 {
2506 echo "<tr><td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>ip_long2quad($ip)))."'>" . ip_long2quad($ip);
2507 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2508 continue;
2509 }
2510 $addr = $range['addrlist'][$ip];
2511 echo "<tr class='${addr['class']}'>";
2512
2513 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
2514 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2515 $delim = '';
2516 $prologue = '';
2517 if ( $addr['reserved'] == 'yes')
2518 {
2519 echo "<strong>RESERVED</strong> ";
2520 $delim = '; ';
2521 }
2522 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2523 {
2524 echo $delim . $aac2[$ref['type']];
2525 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'hl_ipv4_addr'=>$addr['ip']))."'>";
2526 echo $ref['name'] . (empty ($ref['name']) ? '' : '@');
2527 echo "${ref['object_name']}</a>";
2528 $delim = '; ';
2529 }
2530 if ($delim != '')
2531 {
2532 $delim = '';
2533 $prologue = '<br>';
2534 }
2535 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2536 {
2537 echo $prologue;
2538 $prologue = '';
2539 echo "${delim}<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id']))."'>";
2540 echo "${ref['object_name']}</a>:<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$ref['vs_id']))."'>";
2541 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2542 $delim = '; ';
2543 }
2544 if ($delim != '')
2545 {
2546 $delim = '';
2547 $prologue = '<br>';
2548 }
2549 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2550 {
2551 echo $prologue;
2552 $prologue = '';
2553 echo "${delim}&rarr;${ref['rsport']}@<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$ref['rspool_id']))."'>";
2554 echo "${ref['rspool_name']}</a>";
2555 $delim = '; ';
2556 }
2557 echo "</td></tr>\n";
2558 endfor;
2559 // end of iteration
2560
2561 echo "</table>";
2562 finishPortlet();
2563 echo "</td></tr></table>\n";
2564 }
2565
2566 function renderIPv4NetworkProperties ($id)
2567 {
2568 showMessageOrError();
2569 $netdata = getIPv4NetworkInfo ($id);
2570 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
2571 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2572 printOpFormIntro ('editRange');
2573 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${netdata['name']}'></tr>";
2574 echo "<tr><td colspan=2 class=tdcenter>";
2575 printImageHREF ('SAVE', 'Save changes', TRUE);
2576 echo "</td></form></tr></table>\n";
2577 }
2578
2579 function renderIPv4Address ($dottedquad)
2580 {
2581 global $aat;
2582 $address = getIPv4Address ($dottedquad);
2583 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2584 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2585 if (!empty ($address['name']))
2586 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
2587
2588 echo "<tr><td class=pcleft>";
2589 startPortlet ('summary');
2590 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2591 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
2592 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2593 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2594 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
2595 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2596 printTagTRs();
2597 echo "</table><br>\n";
2598 finishPortlet();
2599 echo "</td>\n";
2600
2601 echo "<td class=pcright>";
2602
2603 if (isset ($address['class']))
2604 {
2605 startPortlet ('allocations');
2606 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2607 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2608 $class = $address['class'];
2609 // render all allocation records for this address the same way
2610 if ($address['reserved'] == 'yes')
2611 echo "<tr class='${class}'><td colspan=2>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td></tr>";
2612 foreach ($address['allocs'] as $bond)
2613 {
2614 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2615 $secondclass = 'tdleft port_highlight';
2616 else
2617 $secondclass = 'tdleft';
2618 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>";
2619 echo $aat[$bond['type']];
2620 echo "</strong></td></tr>\n";
2621 }
2622 echo "</table><br><br>";
2623 finishPortlet();
2624 }
2625
2626 // FIXME: The returned list is structured differently, than we expect it to be. One of the sides
2627 // must be fixed.
2628 if (count ($address['lblist']))
2629 {
2630 startPortlet ('Virtual services (' . count ($address['lblist']) . ')');
2631 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2632 echo "<tr><th>VS</th><th>name</th></tr>\n";
2633 foreach ($address['lblist'] as $vsinfo)
2634 {
2635 echo "<tr><td class=tdleft><a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$vsinfo['vs_id']))."'>";
2636 echo buildVServiceName ($vsinfo) . "</a></td><td class=tdleft>";
2637 echo $vsinfo['name'] . "</td></tr>\n";
2638 }
2639 echo "</table><br><br>";
2640 finishPortlet();
2641 }
2642
2643 if (count ($address['rslist']))
2644 {
2645 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2646 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2647 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
2648 foreach ($address['rslist'] as $rsinfo)
2649 {
2650 echo "<tr><td>";
2651 if ($rsinfo['inservice'] == 'yes')
2652 printImageHREF ('inservice', 'in service');
2653 else
2654 printImageHREF ('notinservice', 'NOT in service');
2655 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsinfo['rspool_id']))."'>";
2656 echo $rsinfo['rspool_name'] . "</a></td></tr>\n";
2657 }
2658 echo "</table><br><br>";
2659 finishPortlet();
2660 }
2661
2662 if (count ($address['outpf']))
2663 {
2664 startPortlet ('departing NAT rules');
2665 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2666 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2667 foreach ($address['outpf'] as $rule)
2668 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2669 echo "</table>";
2670 finishPortlet();
2671 }
2672
2673 if (count ($address['inpf']))
2674 {
2675 startPortlet ('arriving NAT rules');
2676 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2677 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2678 foreach ($address['inpf'] as $rule)
2679 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2680 echo "</table>";
2681 finishPortlet();
2682 }
2683
2684 echo "</td></tr>";
2685 echo "</table>\n";
2686 }
2687
2688 function renderIPv4AddressProperties ($dottedquad)
2689 {
2690 showMessageOrError();
2691 $address = getIPv4Address ($dottedquad);
2692 echo "<center><h1>$dottedquad</h1></center>\n";
2693
2694 startPortlet ('update');
2695 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2696 printOpFormIntro ('editAddress');
2697 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2698 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2699 echo ($address['reserved']=='yes') ? 'checked' : '';
2700 echo "></tr><tr><td colspan=2 class='tdcenter'>";
2701 printImageHREF ('SAVE', 'Save changes', TRUE);
2702 echo "</td></form></tr></table>\n";
2703 finishPortlet();
2704 if (empty ($address['name']) and $address['reserved'] == 'no')
2705 return;
2706
2707 startPortlet ('release');
2708 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2709 echo "<input type=submit value='release'></form>";
2710 finishPortlet();
2711 }
2712
2713 function renderIPv4AddressAllocations ($dottedquad)
2714 {
2715 showMessageOrError();
2716 function printNewItemTR ()
2717 {
2718 global $aat;
2719 printOpFormIntro ('addIPv4Allocation');
2720 echo "<tr><td>";
2721 printImageHREF ('add', 'allocate', TRUE);
2722 echo "</td><td><select name='object_id' tabindex=100>";
2723
2724 foreach (explode (',', getConfigVar ('IPV4_PERFORMERS')) as $type)
2725 foreach (getNarrowObjectList ($type) as $object)
2726 echo "<option value='${object['id']}'>${object['dname']}</option>";
2727
2728 echo "</select></td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
2729 printSelect ($aat, 'bond_type', NULL, 102);
2730 echo "</td><td>";
2731 printImageHREF ('add', 'allocate', TRUE, 103);
2732 echo "</td></form></tr>";
2733 }
2734 global $pageno, $tabno, $aat;
2735
2736 $address = getIPv4Address ($dottedquad);
2737
2738 echo "<center><h1>${dottedquad}</h1></center>\n";
2739 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2740 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
2741
2742 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2743 printNewItemTR();
2744 if (isset ($address['class']))
2745 {
2746 $class = $address['class'];
2747 if ($address['reserved'] == 'yes')
2748 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2749 foreach ($address['allocs'] as $bond)
2750 {
2751 echo "<tr class='$class'>";
2752 printOpFormIntro ('updIPv4Allocation', array ('object_id' => $bond['object_id']));
2753 echo "<td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$bond['object_id']))."'>";
2754 printImageHREF ('delete', 'Unallocate address');
2755 echo "</a></td>";
2756 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$bond['object_id'], 'hl_ipv4_addr'=>$dottedquad))."'>${bond['object_name']}</td>";
2757 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
2758 printSelect ($aat, 'bond_type', $bond['type']);
2759 echo "</td><td>";
2760 printImageHREF ('save', 'Save changes', TRUE);
2761 echo "</td></form></tr>\n";
2762 }
2763 }
2764 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2765 printNewItemTR();
2766 echo "</table><br><br>";
2767 }
2768
2769 function renderNATv4ForObject ($object_id = 0)
2770 {
2771 global $root;
2772 function printNewItemTR ($alloclist)
2773 {
2774 global $root;
2775 printOpFormIntro ('addNATv4Rule');
2776 echo "<tr align='center'><td>";
2777 printImageHREF ('add', 'Add new NAT rule', TRUE);
2778 echo '</td><td>';
2779 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
2780 echo "<select name='localip' tabindex=1>";
2781
2782 foreach ($alloclist as $dottedquad => $alloc)
2783 {
2784 $name = empty ($alloc['addrinfo']['name']) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2785 $osif = empty ($alloc['osif']) ? '' : ($alloc['osif'] . ': ');
2786 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
2787 }
2788
2789 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2790 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2791 echo "<a href='javascript:;' onclick='window.open(\"" . makeHrefForHelper ('inet4list');
2792 echo "\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
2793 printImageHREF ('find', 'Find object');
2794 echo "</a>";
2795 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2796 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
2797 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
2798 echo "</td></tr></form>";
2799 }
2800 global $pageno, $tabno;
2801
2802 $info = getObjectInfo ($object_id);
2803 $forwards = getNATv4ForObject ($object_id);
2804 $alloclist = getObjectIPv4Allocations ($object_id);
2805 showMessageOrError();
2806 echo "<center><h2>locally performed NAT</h2></center>";
2807
2808 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2809 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
2810
2811 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2812 printNewItemTR ($alloclist);
2813 foreach ($forwards['out'] as $pf)
2814 {
2815 $class = 'trerror';
2816 $osif = '';
2817 if (isset ($alloclist [$pf['localip']]))
2818 {
2819 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
2820 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
2821 }
2822
2823 echo "<tr class='$class'>";
2824 echo "<td><a href='".
2825 makeHrefProcess(array(
2826 'op'=>'delNATv4Rule',
2827 'localip'=>$pf['localip'],
2828 'localport'=>$pf['localport'],
2829 'remoteip'=>$pf['remoteip'],
2830 'remoteport'=>$pf['remoteport'],
2831 'proto'=>$pf['proto'],
2832 'object_id'=>$object_id)).
2833 "'>";
2834 printImageHREF ('delete', 'Delete NAT rule');
2835 echo "</a></td>";
2836 echo "<td>${pf['proto']}/${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}";
2837 if (!empty ($pf['local_addr_name']))
2838 echo ' (' . $pf['local_addr_name'] . ')';
2839 echo "</td>";
2840 echo "<td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2841
2842 $address = getIPv4Address ($pf['remoteip']);
2843
2844 echo "<td class='description'>";
2845 if (count ($address['allocs']))
2846 foreach ($address['allocs'] as $bond)
2847 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
2848 elseif (!empty ($pf['remote_addr_name']))
2849 echo '(' . $pf['remote_addr_name'] . ')';
2850 printOpFormIntro
2851 (
2852 'updNATv4Rule',
2853 array
2854 (
2855 'localip' => $pf['localip'],
2856 'localport' => $pf['localport'],
2857 'remoteip' => $pf['remoteip'],
2858 'remoteport' => $pf['remoteport'],
2859 'proto' => $pf['proto']
2860 )
2861 );
2862 echo "</td><td class='description'>";
2863 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2864 printImageHREF ('save', 'Save changes', TRUE);
2865 echo "</td></form></tr>";
2866 }
2867 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2868 printNewItemTR ($alloclist);
2869
2870 echo "</table><br><br>";
2871
2872 echo "<center><h2>arriving NAT connections</h2></center>";
2873 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2874 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2875
2876 foreach ($forwards['in'] as $pf)
2877 {
2878 echo "<tr><td><a href='".
2879 makeHrefProcess(array(
2880 'op'=>'delNATv4Rule',
2881 'localip'=>$pf['localip'],
2882 'localport'=>$pf['localport'],
2883 'remoteip'=>$pf['remoteip'],
2884 'remoteport'=>$pf['remoteport'],
2885 'proto'=>$pf['proto'],
2886 'object_id'=>$pf['object_id']
2887 )).
2888 "'>";
2889 printImageHREF ('delete', 'Delete NAT rule');
2890 echo "</a></td>";
2891 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
2892 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
2893 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2894 echo "<td class='description'>${pf['description']}</td></tr>";
2895 }
2896
2897 echo "</table><br><br>";
2898 }
2899
2900 // FIXME: move related code away into ophandler(s)
2901 function renderAddMultipleObjectsForm ()
2902 {
2903 global $root, $pageno, $tabno, $nextorder;
2904
2905 $type_id = array();
2906 $global_type_id = 0;
2907 $name = array();
2908