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