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