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