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