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