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