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