b464e3e56fb79b5d27a460f6cc5f5d099cd130c7
[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 getObjectCount ($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
1293 100 => array ('code' => 'error', 'format' => 'Generic error: %s'),
1294 101 => array ('code' => 'error', 'format' => 'Port name cannot be empty'),
1295 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
1296 103 => array ('code' => 'error', 'format' => 'getHashByID() failed'),
1297 104 => array ('code' => 'error', 'format' => "Error updating user account '%s'"),
1298 105 => array ('code' => 'error', 'format' => 'Error enabling user account.'),
1299 106 => array ('code' => 'error', 'format' => 'Error disabling user account.'),
1300 107 => array ('code' => 'error', 'format' => 'Admin account cannot be disabled'),
1301 108 => array ('code' => 'error', 'format' => '%u failures and %u successfull changes.'),
1302 109 => array ('code' => 'error', 'format' => 'Update failed!'),
1303 110 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1304 111 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1305 112 => array ('code' => 'error', 'format' => 'Error adding chapter.'),
1306 113 => array ('code' => 'error', 'format' => 'Error updating chapter.'),
1307 114 => array ('code' => 'error', 'format' => 'Error deleting chapter.'),
1308 115 => array ('code' => 'error', 'format' => 'Error renaming attribute.'),
1309 116 => array ('code' => 'error', 'format' => 'Error creating attribute.'),
1310 117 => array ('code' => 'error', 'format' => 'Error deleting attribute.'),
1311 118 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1312 119 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1313 120 => array ('code' => 'error', 'format' => 'Reset failed!'),
1314 121 => array ('code' => 'error', 'format' => 'commitUpdateObject() failed'),
1315 122 => array ('code' => 'error', 'format' => 'One or more update(s) failed!'),
1316 123 => array ('code' => 'error', 'format' => 'Cannot process submitted data: unknown format code.'),
1317 124 => array ('code' => 'error', 'format' => 'Error removing reservation!'),
1318 125 => array ('code' => 'error', 'format' => "Update failed with error: '%s'"),
1319 126 => array ('code' => 'error', 'format' => 'addRStoRSPool() failed'),
1320 127 => array ('code' => 'error', 'format' => 'Added %u real servers and encountered %u errors'),
1321 128 => array ('code' => 'error', 'format' => 'commitDeleteRS() failed'),
1322 129 => array ('code' => 'error', 'format' => 'commitDeleteLB() failed'),
1323 130 => array ('code' => 'error', 'format' => 'commitDeleteVS() failed'),
1324 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1325 132 => array ('code' => 'error', 'format' => 'invalid protocol'),
1326 133 => array ('code' => 'error', 'format' => 'commitUpdateRS() failed'),
1327 134 => array ('code' => 'error', 'format' => 'commitUpdateLB() failed'),
1328 135 => array ('code' => 'error', 'format' => 'commitUpdateVS() failed'),
1329 136 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1330 137 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1331 138 => array ('code' => 'error', 'format' => 'commitDeleteRSPool() failed'),
1332 139 => array ('code' => 'error', 'format' => 'commitUpdateRSPool() failed'),
1333 140 => array ('code' => 'error', 'format' => 'Encountered %u errors, (de)activated %u real servers'),
1334 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u IP address(es)'),
1335 142 => array ('code' => 'error', 'format' => 'executeAutoPorts() failed'),
1336 143 => array ('code' => 'error', 'format' => 'Tried chaining %u tags, but experienced %u errors.'),
1337 144 => array ('code' => 'error', 'format' => "Error deleting tag: '%s'"),
1338 145 => array ('code' => 'error', 'format' => "Invalid tag name '%s'"),
1339 146 => array ('code' => 'error', 'format' => "Tag '%s' (or similar name) already exists"),
1340 147 => array ('code' => 'error', 'format' => "Could not create tag '%s' because of error '%s'"),
1341 148 => array ('code' => 'error', 'format' => "Could not update tag '%s' because of error '%s'"),
1342 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1343 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1344 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1345 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1346 153 => array ('code' => 'error', 'format' => 'Password change failed.'),
1347 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1348 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1349 156 => array ('code' => 'error', 'format' => 'getSwitchVLANs() failed'),
1350 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
1351 158 => array ('code' => 'error', 'format' => 'Ignoring malformed record #%u in form submit'),
1352 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1353 160 => array ('code' => 'error', 'format' => 'Invalid arguments'),
1354 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1355 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
1356 163 => array ('code' => 'error', 'format' => 'Failed to get any response from queryGateway() or the gateway died'),
1357 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
1358 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1359 166 => array ('code' => 'error', 'format' => 'gw: %s'),
1360 167 => array ('code' => 'error', 'format' => 'Could not find port %s'),
1361 168 => array ('code' => 'error', 'format' => 'Port %s is a trunk'),
1362 169 => array ('code' => 'error', 'format' => 'Failed to configure %s, connector returned code %u'),
1363 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1364 171 => array ('code' => 'error', 'format' => "Failed creating rack '%s'. Already exists in this row?"),
1365 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1366 173 => array ('code' => 'error', 'format' => "Invalid IPv4 prefix '%s'"),
1367 174 => array ('code' => 'error', 'format' => 'Bad IPv4 address'),
1368 175 => array ('code' => 'error', 'format' => 'Invalid netmask'),
1369 176 => array ('code' => 'error', 'format' => 'This network already exists'),
1370
1371 200 => array ('code' => 'warning', 'format' => 'generic warning: %s'),
1372 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1373 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
1374 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1375 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1376 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
1377 );
1378 // Handle the arguments. Is there any better way to do it?
1379 foreach ($log['m'] as $record)
1380 {
1381 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1382 {
1383 echo '<div class=msg_neutral>(this message was lost)</div>';
1384 continue;
1385 }
1386 if (isset ($record['a']))
1387 switch (count ($record['a']))
1388 {
1389 case 1:
1390 $msgtext = sprintf
1391 (
1392 $msginfo[$record['c']]['format'],
1393 $record['a'][0]
1394 );
1395 break;
1396 case 2:
1397 $msgtext = sprintf
1398 (
1399 $msginfo[$record['c']]['format'],
1400 $record['a'][0],
1401 $record['a'][1]
1402 );
1403 break;
1404 case 3:
1405 $msgtext = sprintf
1406 (
1407 $msginfo[$record['c']]['format'],
1408 $record['a'][0],
1409 $record['a'][1],
1410 $record['a'][2]
1411 );
1412 break;
1413 case 4:
1414 default:
1415 $msgtext = sprintf
1416 (
1417 $msginfo[$record['c']]['format'],
1418 $record['a'][0],
1419 $record['a'][1],
1420 $record['a'][2],
1421 $record['a'][3]
1422 );
1423 break;
1424 }
1425 else
1426 $msgtext = $msginfo[$record['c']]['format'];
1427 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1428 }
1429 break;
1430 default:
1431 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1432 break;
1433 }
1434 }
1435
1436 /*
1437 The following conditions must be followed:
1438 1. We can mount onto free atoms only. This means: if any record for an atom
1439 already exists in RackSpace, it can't be used for mounting.
1440 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1441 and either delete them before unmounting or refuse to unmount the object.
1442 */
1443
1444 // We extensively use $_REQUEST in the function.
1445 // FIXME: move related code into ophandler
1446 function renderRackSpaceForObject ($object_id = 0)
1447 {
1448 if ($object_id <= 0)
1449 {
1450 showError ('Invalid object_id', __FUNCTION__);
1451 return;
1452 }
1453 $is_submit = isset ($_REQUEST['got_atoms']);
1454 $is_update = isset ($_REQUEST['rackmulti'][0]);
1455 $info = getObjectInfo ($object_id);
1456 if ($info == NULL)
1457 {
1458 showError ('getObjectInfo() failed', __FUNCTION__);
1459 return;
1460 }
1461 // Always process occupied racks plus racks chosen by user. First get racks with
1462 // already allocated rackspace...
1463 $workingRacksData = getResidentRacksData ($object_id);
1464 if ($workingRacksData === NULL)
1465 {
1466 print_r ($workingRacksData);
1467 showError ('getResidentRacksData() failed', __FUNCTION__);
1468 return;
1469 }
1470
1471 // ...and then add those chosen by user (if any).
1472 if ($is_update)
1473 foreach ($_REQUEST['rackmulti'] as $cand_id)
1474 {
1475 if (!isset ($workingRacksData[$cand_id]))
1476 {
1477 $rackData = getRackData ($cand_id);
1478 if ($rackData == NULL)
1479 {
1480 showError ('getRackData() failed', __FUNCTION__);
1481 return NULL;
1482 }
1483 $workingRacksData[$cand_id] = $rackData;
1484 }
1485 }
1486
1487 // Do it only once...
1488 foreach ($workingRacksData as &$rackData)
1489 applyObjectMountMask ($rackData, $object_id);
1490 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1491 unset ($rackData);
1492
1493 // Here we process form submit by trying to save all submitted info to database.
1494 if ($is_submit)
1495 {
1496 $oldMolecule = getMoleculeForObject ($object_id);
1497 $worldchanged = FALSE;
1498 $log = array();
1499 foreach ($workingRacksData as $rack_id => $rackData)
1500 {
1501 $logrecord = processGridForm ($rackData, 'F', 'T', $object_id);
1502 $log[] = $logrecord;
1503 if ($logrecord['code'] != 300)
1504 {
1505 $worldchanged = TRUE;
1506 // Reload our working copy after form processing.
1507 $rackData = getRackData ($rack_id);
1508 if ($rackData == NULL)
1509 $log[] = array ('code' => 500, 'message' => 'Working copy update failed in ', __FUNCTION__);
1510 applyObjectMountMask ($rackData, $object_id);
1511 $workingRacksData[$rack_id] = $rackData;
1512 }
1513 }
1514 if ($worldchanged)
1515 {
1516 // Log a record.
1517 $newMolecule = getMoleculeForObject ($object_id);
1518 $oc = count ($oldMolecule);
1519 $nc = count ($newMolecule);
1520 $omid = $oc ? createMolecule ($oldMolecule) : 'NULL';
1521 $nmid = $nc ? createMolecule ($newMolecule) : 'NULL';
1522 global $remote_username;
1523 $comment = empty ($_REQUEST['comment']) ? 'NULL' : "'${_REQUEST['comment']}'";
1524 $query =
1525 "insert into MountOperation(object_id, old_molecule_id, new_molecule_id, user_name, comment) " .
1526 "values (${object_id}, ${omid}, ${nmid}, '${remote_username}', ${comment})";
1527 global $dbxlink;
1528 $result = $dbxlink->query ($query);
1529 if ($result == NULL)
1530 $log[] = array ('code' => 'error', 'message' => 'SQL query failed during history logging.');
1531 else
1532 $log[] = array ('code' => 'success', 'message' => 'History logged.');
1533 }
1534 printLog ($log);
1535 }
1536
1537 // This is the time for rendering.
1538 global $root, $pageno, $tabno;
1539 echo "<form id='racks' action='${root}'>";
1540 echo "<input type=hidden name=page value='${pageno}'>\n";
1541 echo "<input type=hidden name=tab value='${tabno}'>\n";
1542 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1543 // Main layout starts.
1544 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1545
1546 // Left portlet with rack list.
1547 echo "<td class=pcleft height='1%'>";
1548 startPortlet ('Racks');
1549 $allRacksData = getRacksForRow();
1550 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1551 {
1552 foreach (array_keys ($allRacksData) as $rack_id)
1553 {
1554 $rackData = getRackData ($rack_id);
1555 if ($rackData == NULL)
1556 {
1557 showError ('getRackData() failed', __FUNCTION__);
1558 return NULL;
1559 }
1560 $workingRacksData[$rack_id] = $rackData;
1561 }
1562 foreach ($workingRacksData as &$rackData)
1563 applyObjectMountMask ($rackData, $object_id);
1564 unset ($rackData);
1565 }
1566 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1567 echo "<br>";
1568 echo "<br>";
1569 finishPortlet();
1570 echo "</td>";
1571
1572 // Middle portlet with comment and submit.
1573 echo "<td class=pcleft>";
1574 startPortlet ('Comment');
1575 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1576 echo "<input type=submit value='Save' name=got_atoms>\n";
1577 echo "<br>";
1578 echo "<br>";
1579 finishPortlet();
1580 echo "</td>";
1581
1582 // Right portlet with rendered racks. If this form submit is not final, we have to
1583 // reflect the former state of the grid in current form.
1584 echo "<td class=pcright rowspan=2 height='1%'>";
1585 startPortlet ('Working copy');
1586 echo '<table border=0 cellspacing=10 align=center><tr>';
1587 foreach ($workingRacksData as $rack_id => $rackData)
1588 {
1589 // Order is important here: only original allocation is highlighted.
1590 highlightObject ($rackData, $object_id);
1591 markupAtomGrid ($rackData, 'T');
1592 // If we have a form processed, discard user input and show new database
1593 // contents.
1594 if (!$is_submit and $is_update)
1595 mergeGridFormToRack ($rackData);
1596 echo "<td valign=top>";
1597 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1598 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1599 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1600 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1601 renderAtomGrid ($rackData);
1602 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1603 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1604 echo "</table></center>\n";
1605 echo '</td>';
1606 }
1607 echo "</tr></table>";
1608 finishPortlet();
1609 echo "</td>\n";
1610
1611 echo "</form>\n";
1612 echo "</tr></table>\n";
1613 }
1614
1615 function renderMolecule ($mdata, $object_id)
1616 {
1617 // sort data out
1618 $rackpack = array();
1619 global $loclist;
1620 foreach ($mdata as $rua)
1621 {
1622 $rack_id = $rua['rack_id'];
1623 $unit_no = $rua['unit_no'];
1624 $atom = $rua['atom'];
1625 if (!isset ($rackpack[$rack_id]))
1626 {
1627 $rackData = getRackData ($rack_id);
1628 for ($i = $rackData['height']; $i > 0; $i--)
1629 for ($locidx = 0; $locidx < 3; $locidx++)
1630 $rackData[$i][$locidx]['state'] = 'F';
1631 $rackpack[$rack_id] = $rackData;
1632 }
1633 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1634 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1635 }
1636 // now we have some racks to render
1637 foreach ($rackpack as $rackData)
1638 {
1639 markAllSpans ($rackData);
1640 echo "<table class=molecule cellspacing=0>\n";
1641 echo "<caption>${rackData['name']}</caption>\n";
1642 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1643 for ($i = $rackData['height']; $i > 0; $i--)
1644 {
1645 echo "<tr><th>$i</th>";
1646 for ($locidx = 0; $locidx < 3; $locidx++)
1647 {
1648 $state = $rackData[$i][$locidx]['state'];
1649 echo "<td class=state_${state}>&nbsp;</td>\n";
1650 }
1651 echo "</tr>\n";
1652 }
1653 echo "</table>\n";
1654 }
1655 }
1656
1657 function renderUnmountedObjectsPortlet ()
1658 {
1659 startPortlet ('Unmounted objects');
1660 $objs = getUnmountedObjects();
1661 if ($objs === NULL)
1662 {
1663 showError ('getUnmountedObjects() failed', __FUNCTION__);
1664 return;
1665 }
1666 global $root, $nextorder;
1667 $order = 'odd';
1668 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1669 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset number</th><th>Barcode</th></tr>';
1670 foreach ($objs as $obj)
1671 {
1672 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1673 echo "<td>${obj['label']}</td>";
1674 echo "<td>${obj['asset_no']}</td>";
1675 echo "<td>${obj['barcode']}</td></tr>";
1676 $order = $nextorder[$order];
1677 }
1678 echo "</table><br>\n";
1679 finishPortlet();
1680 }
1681
1682 function renderProblematicObjectsPortlet ()
1683 {
1684 startPortlet ('Problematic objects');
1685 $objs = getProblematicObjects();
1686 if ($objs === NULL)
1687 {
1688 showError ('getProblematicObjects() failed', __FUNCTION__);
1689 return;
1690 }
1691 global $root, $nextorder;
1692 $order = 'odd';
1693 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1694 echo '<tr><th>Type</th><th>Common name</th></tr>';
1695 foreach ($objs as $obj)
1696 {
1697 echo "<tr class=row_${order}><td>${obj['objtype_name']}</td>";
1698 echo "<td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></tr>";
1699 $order = $nextorder[$order];
1700 }
1701 echo "</table><br>\n";
1702 finishPortlet();
1703 }
1704
1705 function renderObjectSpace ()
1706 {
1707 global $root, $taglist, $tagtree;
1708 echo "<table border=0 class=objectview>\n";
1709 echo "<tr><td class=pcleft width='50%'>";
1710 startPortlet ('View all by type');
1711 $groupInfo = getObjectGroupInfo();
1712 if ($groupInfo === NULL)
1713 {
1714 showError ('getObjectGroupInfo() failed', __FUNCTION__);
1715 return;
1716 }
1717 if (count ($groupInfo) == 0)
1718 echo "No objects exist in DB";
1719 else
1720 {
1721 echo '<div align=left><ul>';
1722 foreach ($groupInfo as $gi)
1723 echo "<li><a href='${root}?page=objgroup&group_id=${gi['id']}'>${gi['name']}</a> (${gi['count']})</li>";
1724 echo '</ul></div>';
1725 }
1726 finishPortlet();
1727
1728 echo '</td><td class=pcright>';
1729
1730 startPortlet ('View all by tag');
1731 if (count ($taglist) == 0)
1732 echo "No tags exist in DB";
1733 else
1734 renderTagCloud ('object');
1735 finishPortlet();
1736 echo "</td></tr></table>\n";
1737 }
1738
1739 function renderObjectGroup ()
1740 {
1741 global $root, $pageno, $tabno, $nextorder, $taglist, $tagtree;
1742 assertUIntArg ('group_id', __FUNCTION__, TRUE);
1743 $group_id = $_REQUEST['group_id'];
1744 $tagfilter = getTagFilter();
1745 $tagfilter_str = getTagFilterStr ($tagfilter);
1746 echo "<table border=0 class=objectview>\n";
1747 echo "<tr><td class=pcleft width='25%'>";
1748 startPortlet ('change type');
1749 $groupInfo = getObjectGroupInfo();
1750 if ($groupInfo === NULL)
1751 {
1752 showError ('getObjectGroupInfo() failed', __FUNCTION__);
1753 return;
1754 }
1755 if (count ($groupInfo) == 0)
1756 echo "No objects exist in DB";
1757 else
1758 {
1759 echo '<div align=left><ul>';
1760 foreach ($groupInfo as $gi)
1761 {
1762 echo "<li><a href='${root}?page=${pageno}&group_id=${gi['id']}${tagfilter_str}'>";
1763 if ($gi['id'] == $group_id)
1764 echo '<strong>';
1765 echo "${gi['name']}</a>";
1766 if ($gi['id'] == $group_id)
1767 echo '</strong>';
1768 echo " (${gi['count']})";
1769 if ($gi['id'] == $group_id)
1770 echo ' &larr;';
1771 echo "</li>";
1772 }
1773 echo '</ul></div>';
1774 }
1775 finishPortlet();
1776
1777 echo '</td><td class=pcleft>';
1778
1779 startPortlet ('Objects');
1780 $objects = getObjectList ($group_id, $tagfilter, getTFMode());
1781 if ($objects === NULL)
1782 {
1783 showError ('getObjectList() failed', __FUNCTION__);
1784 return;
1785 }
1786 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1787 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Rack</th></tr>';
1788 $order = 'odd';
1789 foreach ($objects as $obj)
1790 {
1791 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1792 $secondclass = 'tdleft port_highlight';
1793 else
1794 $secondclass = 'tdleft';
1795 echo "<tr class=row_${order}><td class='${secondclass}'><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1796 echo "<td class='${secondclass}'>${obj['label']}</td>";
1797 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
1798 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
1799 if ($obj['rack_id'])
1800 echo "<td class='${secondclass}'><a href='${root}?page=rack&rack_id=${obj['rack_id']}'>${obj['Rack_name']}</a></td>";
1801 else
1802 echo "<td class='${secondclass}'>Unmounted</td>";
1803 echo '</tr>';
1804 $order = $nextorder[$order];
1805 }
1806 echo '</table>';
1807 finishPortlet();
1808
1809 echo "</td><td class=pcright width='25%'>";
1810
1811 renderTagFilterPortlet ($tagfilter, 'object', 'group_id', $group_id);
1812 echo "</td></tr></table>\n";
1813 }
1814
1815 function renderEmptyPortsSelect ($port_id, $type_id)
1816 {
1817 $ports = getEmptyPortsOfType($type_id);
1818 usort($ports, 'sortEmptyPorts');
1819 foreach ($ports as $port)
1820 {
1821 if ($port_id == $port['Port_id'])
1822 continue;
1823 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";
1824 }
1825 }
1826
1827 function renderAllIPv4Allocations ()
1828 {
1829 $addresses = getAllIPv4Allocations();
1830 usort($addresses, 'sortObjectAddressesAndNames');
1831 foreach ($addresses as $address)
1832 {
1833 echo "<option value='${address['ip']}' onclick='getElementById(\"ip\").value=\"${address['ip']}\";'>${address['object_name']} ${address['name']} ${address['ip']}</option>\n";
1834 }
1835 }
1836
1837 // History viewer for history-enabled simple dictionaries.
1838 function renderHistory ($object_type, $object_id)
1839 {
1840 switch ($object_type)
1841 {
1842 case 'row':
1843 $query = "select ctime, user_name, name, deleted, comment from RackRowHistory where id = ${object_id} order by ctime";
1844 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>is deleted?</th><th>rack row comment</th></tr>';
1845 $extra = 4;
1846 break;
1847 case 'rack':
1848 $query =
1849 "select ctime, user_name, rh.name, rh.deleted, d.dict_value as name, rh.height, rh.comment " .
1850 "from RackHistory as rh left join Dictionary as d on rh.row_id = d.dict_key " .
1851 "natural join Chapter " .
1852 "where chapter_name = 'RackRow' and rh.id = ${object_id} order by ctime";
1853 $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>';
1854 $extra = 6;
1855 break;
1856 case 'object':
1857 $query =
1858 "select ctime, user_name, name, label, barcode, asset_no, deleted, has_problems, dict_value, comment " .
1859 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key natural join Chapter " .
1860 "where chapter_name = 'RackObjectType' and id=${object_id} order by ctime";
1861 $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>';
1862 $extra = 9;
1863 break;
1864 default:
1865 showError ("Uknown object type '${object_type}'", __FUNCTION__);
1866 return;
1867 }
1868 global $dbxlink;
1869 $result = $dbxlink->query ($query);
1870 if ($result == NULL)
1871 {
1872 showError ('SQL query failed', __FUNCTION__);
1873 return;
1874 }
1875 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1876 $order = 'odd';
1877 global $nextorder;
1878 echo $header;
1879 while ($row = $result->fetch (PDO::FETCH_NUM))
1880 {
1881 echo "<tr class=row_${order}><td>${row[0]}</td>";
1882 for ($i = 1; $i <= $extra; $i++)
1883 echo "<td>" . $row[$i] . "</td>";
1884 echo "</tr>\n";
1885 $order = $nextorder[$order];
1886 }
1887 echo "</table><br>\n";
1888 }
1889
1890 function renderRackspaceHistory ()
1891 {
1892 global $root, $nextorder, $pageno, $tabno;
1893 $order = 'odd';
1894 $history = getRackspaceHistory();
1895 // Show the last operation by default.
1896 if (isset ($_REQUEST['op_id']))
1897 $op_id = $_REQUEST['op_id'];
1898 elseif (isset ($history[0]['mo_id']))
1899 $op_id = $history[0]['mo_id'];
1900 else $op_id = NULL;
1901
1902 $omid = NULL;
1903 $nmid = NULL;
1904 $object_id = 1;
1905 if ($op_id)
1906 list ($omid, $nmid) = getOperationMolecules ($op_id);
1907
1908 // Main layout starts.
1909 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1910
1911 // Left top portlet with old allocation.
1912 echo "<tr><td class=pcleft>";
1913 startPortlet ('Old allocation');
1914 if ($omid)
1915 {
1916 $oldMolecule = getMolecule ($omid);
1917 renderMolecule ($oldMolecule, $object_id);
1918 }
1919 else
1920 echo "nothing";
1921 finishPortlet();
1922
1923 echo '</td><td class=pcright>';
1924
1925 // Right top portlet with new allocation
1926 startPortlet ('New allocation');
1927 if ($nmid)
1928 {
1929 $newMolecule = getMolecule ($nmid);
1930 renderMolecule ($newMolecule, $object_id);
1931 }
1932 else
1933 echo "nothing";
1934 finishPortlet();
1935
1936 echo '</td></tr><tr><td colspan=2>';
1937
1938 // Bottom portlet with list
1939
1940 startPortlet ('Rackspace allocation history');
1941 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1942 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";
1943 foreach ($history as $row)
1944 {
1945 if ($row['mo_id'] == $op_id)
1946 $class = 'hl';
1947 else
1948 $class = "row_${order}";
1949 echo "<tr class=${class}><td><a href='${root}?page=${pageno}&tab=${tabno}&op_id=${row['mo_id']}'>${row['ctime']}</a></td>";
1950 echo "<td>${row['user_name']}</td>";
1951 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
1952 echo "</tr>\n";
1953 $order = $nextorder[$order];
1954 }
1955 echo "</table>\n";
1956 finishPortlet();
1957
1958 echo '</td></tr></table>';
1959
1960 }
1961
1962 function renderIPv4Space ()
1963 {
1964 global $root, $pageno;
1965
1966 echo "<table border=0 class=objectview>\n";
1967 echo "<tr><td class=pcleft>";
1968
1969 $tagfilter = getTagFilter();
1970 $addrspaceList = getAddressspaceList ($tagfilter, getTFMode());
1971 $tagcache = array();
1972 startPortlet ('networks (' . count ($addrspaceList) . ')');
1973 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
1974 echo "<tr><th>prefix</th><th>name/tags</th><th>%% used</th>";
1975 if (getConfigVar ('DECODE_IPV4_ADDR') == 'yes')
1976 echo "<th>routed by</th>";
1977 echo "</tr>\n";
1978 foreach ($addrspaceList as $iprange)
1979 {
1980 $netdata = getIPv4Network ($iprange['id']);
1981 $prefixtags = loadIPv4PrefixTags ($iprange['id']);
1982 $total = ($netdata['ip_bin'] | $netdata['mask_bin_inv']) - ($netdata['ip_bin'] & $netdata['mask_bin']) + 1;
1983 $used = count ($netdata['addrlist']);
1984 echo "<tr valign=top><td class=tdleft><a href='${root}?page=iprange&id=${iprange['id']}'>${iprange['ip']}/${netdata['mask']}</a></td>";
1985 echo "<td class=tdleft>${netdata['name']}";
1986 if (count ($prefixtags))
1987 {
1988 echo "<br>";
1989 echo serializeTags ($prefixtags, "${root}?page=${pageno}&tab=default&");
1990 }
1991 echo "</td><td class=tdcenter>";
1992 renderProgressBar ($used/$total);
1993 echo "<br><small>${used}/${total}</small></td>";
1994 if (getConfigVar ('DECODE_IPV4_ADDR') == 'yes')
1995 printRoutersTD (findRouters ($netdata['addrlist']), $tagcache);
1996 echo "</tr>";
1997 }
1998 echo "</table>\n";
1999 finishPortlet();
2000 echo '</td><td class=pcright>';
2001 renderTagFilterPortlet ($tagfilter, 'ipv4net');
2002 echo "</td></tr></table>\n";
2003 }
2004
2005 function renderIPv4SLB ()
2006 {
2007 global $root, $page, $nextorder;
2008
2009 startPortlet ('SLB configuration');
2010 echo "<table border=0 width='100%'><tr>";
2011 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2012 echo "<td><h3><a href='${root}?page=${pno}'>" . $page[$pno]['title'] . "</a></h3></td>";
2013 echo '</tr></table>';
2014 finishPortlet();
2015
2016 $summary = getSLBSummary();
2017 startPortlet ('SLB tactical overview');
2018 // A single id-keyed array isn't used here to preserve existing
2019 // order of LBs returned by getSLBSummary()
2020 $lblist = array();
2021 $lbdname = array();
2022 foreach ($summary as $vipdata)
2023 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2024 if (!in_array ($lb_object_id, $lblist))
2025 {
2026 $oi = getObjectInfo ($lb_object_id);
2027 $lbdname[$lb_object_id] = $oi['dname'];
2028 $lblist[] = $lb_object_id;
2029 }
2030 if (!count ($summary))
2031 echo 'none configured';
2032 else
2033 {
2034 $order = 'odd';
2035 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2036 echo "<tr><th>VS&nbsp;&darr; LB&nbsp;&rarr;</th>";
2037 foreach ($lblist as $lb_object_id)
2038 echo "<th><a href='${root}?page=object&tab=default&object_id=${lb_object_id}'>" . $lbdname[$lb_object_id] . "</a></th>";
2039 echo "</tr>\n";
2040 foreach ($summary as $vsid => $vsdata)
2041 {
2042 echo "<tr class=row_${order}><td class=tdleft><a href='$root?page=ipv4vs&tab=default&vs_id=${vsid}'>";
2043 echo buildVServiceName ($vsdata);
2044 echo '</a>';
2045 if (!empty ($vsdata['name']))
2046 echo "<br>${vsdata['name']}";
2047 echo "</td>";
2048 foreach ($lblist as $lb_object_id)
2049 {
2050 echo '<td class=tdleft>';
2051 if (!isset ($vsdata['lblist'][$lb_object_id]))
2052 echo '&nbsp;';
2053 else
2054 {
2055 echo $vsdata['lblist'][$lb_object_id]['size'];
2056 echo " (<a href='${root}?page=ipv4rsp&pool_id=";
2057 echo $vsdata['lblist'][$lb_object_id]['id'] . "'>";
2058 echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2059 }
2060 echo '</td>';
2061 }
2062 echo "</tr>\n";
2063 $order = $nextorder[$order];
2064 }
2065 echo "</table>\n";
2066 }
2067 finishPortlet ();
2068 }
2069
2070 function renderIPv4SpaceEditor ()
2071 {
2072 global $root, $pageno, $tabno;
2073 showMessageOrError();
2074
2075 startPortlet ("Add new");
2076 echo '<table border=0 cellpadding=10 align=center>';
2077 // This form requires a name, so JavaScript validator can find it.
2078 // No printOpFormIntro() hence
2079 echo "<form method=post name='add_new_range' action='${root}process.php'>\n";
2080 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2081 echo "<input type=hidden name=page value='${pageno}'>\n";
2082 echo "<input type=hidden name=tab value='${tabno}'>\n";
2083 // tags column
2084 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2085 renderTagSelect();
2086 echo '</td>';
2087 // inputs column
2088 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=18 class='live-validate' tabindex=1></td>";
2089 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2090 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3 checked></td></tr>";
2091 echo "<tr><td colspan=2>";
2092 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2093 echo '</td></tr>';
2094 echo "</form></table><br><br>\n";
2095 finishPortlet();
2096
2097 $addrspaceList = getAddressspaceList();
2098 if (count ($addrspaceList))
2099 {
2100 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2101 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2102 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>&nbsp;</th></tr>";
2103 foreach ($addrspaceList as $iprange)
2104 {
2105 $netdata = getIPv4Network ($iprange['id']);
2106 $usedips = count ($netdata['addrlist']);
2107 $totalips = ($netdata['ip_bin'] | $netdata['mask_bin_inv']) - ($netdata['ip_bin'] & $netdata['mask_bin']) + 1;
2108 echo "<form method=post action='${root}process.php?page=${pageno}&tab=${tabno}&op=updIPv4Prefix&id=${iprange['id']}'>";
2109 echo '<tr valign=top><td>';
2110 if ($usedips == 0)
2111 {
2112 echo "<a href='${root}process.php?op=delIPv4Prefix&page=${pageno}&tab=${tabno}&id=${iprange['id']}'>";
2113 printImageHREF ('delete', 'Delete this IP range');
2114 echo "</a>";
2115 }
2116 else
2117 printImageHREF ('nodelete', 'There are IP addresses allocated or reserved');
2118 echo "</td>\n<td class=tdleft>${netdata['ip']}/${netdata['mask']}</td>";
2119 echo "<td><input type=text name=name size=40 value='${netdata['name']}'>";
2120 echo "</td><td>";
2121 printImageHREF ('save', 'Save changes', TRUE);
2122 echo "</td></tr></form>\n";
2123 }
2124 echo "</table>";
2125 finishPortlet();
2126 }
2127 }
2128
2129 function renderIPv4Network ($id)
2130 {
2131 global $root, $pageno, $tabno, $aac2;
2132 $netmaskbylen = array
2133 (
2134 32 => '255.255.255.255',
2135 31 => '255.255.255.254',
2136 30 => '255.255.255.252',
2137 29 => '255.255.255.248',
2138 28 => '255.255.255.240',
2139 27 => '255.255.255.224',
2140 26 => '255.255.255.192',
2141 25 => '255.255.255.128',
2142 24 => '255.255.255.0',
2143 23 => '255.255.254.0',
2144 22 => '255.255.252.0',
2145 21 => '255.255.248.0',
2146 20 => '255.255.240.0',
2147 19 => '255.255.224.0',
2148 18 => '255.255.192.0',
2149 17 => '255.255.128.0',
2150 16 => '255.255.0.0',
2151 15 => '255.254.0.0',
2152 14 => '255.252.0.0',
2153 13 => '255.248.0.0',
2154 12 => '255.240.0.0',
2155 11 => '255.224.0.0',
2156 10 => '255.192.0.0',
2157 9 => '255.128.0.0',
2158 8 => '255.0.0.0',
2159 7 => '254.0.0.0',
2160 6 => '252.0.0.0',
2161 5 => '248.0.0.0',
2162 4 => '240.0.0.0',
2163 3 => '224.0.0.0',
2164 2 => '192.0.0.0',
2165 1 => '128.0.0.0'
2166 );
2167 $wildcardbylen = array
2168 (
2169 32 => '0.0.0.0',
2170 31 => '0.0.0.1',
2171 30 => '0.0.0.3',
2172 29 => '0.0.0.7',
2173 28 => '0.0.0.15',
2174 27 => '0.0.0.31',
2175 26 => '0.0.0.63',
2176 25 => '0.0.0.127',
2177 24 => '0.0.0.255',
2178 23 => '0.0.1.255',
2179 22 => '0.0.3.255',
2180 21 => '0.0.7.255',
2181 20 => '0.0.15.255',
2182 19 => '0.0.31.255',
2183 18 => '0.0.63.255',
2184 17 => '0.0.127.255',
2185 16 => '0.0.255.25',
2186 15 => '0.1.255.255',
2187 14 => '0.3.255.255',
2188 13 => '0.7.255.255',
2189 12 => '0.15.255.255',
2190 11 => '0.31.255.255',
2191 10 => '0.63.255.255',
2192 9 => '0.127.255.255',
2193 8 => '0.255.255.255',
2194 7 => '1.255.255.255',
2195 6 => '3.255.255.255',
2196 5 => '7.255.255.255',
2197 4 => '15.255.255.255',
2198 3 => '31.255.255.255',
2199 2 => '63.255.255.255',
2200 1 => '127.255.255.255'
2201 );
2202 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2203 if (isset($_REQUEST['pg']))
2204 $page = $_REQUEST['pg'];
2205 else
2206 $page=0;
2207
2208 $range = getIPv4Network ($id);
2209 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2210 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></td></tr>\n";
2211
2212 echo "<tr><td class=pcleft width='50%'>";
2213 startPortlet ('summary');
2214 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2215 $used = count ($range['addrlist']);
2216 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2217
2218 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2219 renderProgressBar ($used/$total);
2220 echo "&nbsp;${used}/${total}</td></tr>\n";
2221
2222 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2223 echo $netmaskbylen[$range['mask']];
2224 echo "</td></tr>\n";
2225
2226 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2227 echo $wildcardbylen[$range['mask']];
2228 echo "</td></tr>\n";
2229
2230 $routers = findRouters ($range['addrlist']);
2231 if (getConfigVar ('DECODE_IPV4_ADDR') == 'yes' and count ($routers))
2232 {
2233 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2234 printRoutersTD ($routers);
2235 echo "</tr>\n";
2236 }
2237
2238 printTagTRs ("${root}?page=ipv4space&");
2239 echo "</table><br>\n";
2240 finishPortlet();
2241 echo "</td>\n";
2242
2243 echo "<td class=pcright>";
2244 startPortlet ('details');
2245 $startip = $range['ip_bin'] & $range['mask_bin'];
2246 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2247 $realstartip = $startip;
2248 $realendip = $endip;
2249 $numpages = 0;
2250 if($endip - $startip > $maxperpage)
2251 {
2252 $numpages = ($endip - $startip)/$maxperpage;
2253 $startip = $startip + $page * $maxperpage;
2254 $endip = $startip + $maxperpage-1;
2255 }
2256 echo "<center>";
2257 if ($numpages)
2258 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2259 for ($i=0; $i<$numpages; $i++)
2260 {
2261 if ($i == $page)
2262 echo "<b>$i</b> ";
2263 else
2264 echo "<a href='${root}?page=${pageno}&tab=${tabno}&id=$id&pg=$i'>$i</a> ";
2265 }
2266 echo "</center>";
2267
2268 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2269 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2270
2271
2272 for ($ip = $startip; $ip <= $endip; $ip++) :
2273 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2274 $secondstyle = 'tdleft port_highlight';
2275 else
2276 $secondstyle = 'tdleft';
2277 if (!isset ($range['addrlist'][$ip]))
2278 {
2279 echo "<tr><td class=tdleft><a href='${root}?page=ipaddress&ip=" . long2ip ($ip) . "'>" . long2ip ($ip);
2280 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2281 continue;
2282 }
2283 $addr = $range['addrlist'][$ip];
2284 echo "<tr class='${addr['class']}'>";
2285
2286 echo "<td class=tdleft><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
2287 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2288 $delim = '';
2289 $prologue = '';
2290 if ( $addr['reserved'] == 'yes')
2291 {
2292 echo "<strong>RESERVED</strong> ";
2293 $delim = '; ';
2294 }
2295 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2296 {
2297 echo $delim . $aac2[$ref['type']];
2298 echo "<a href='${root}?page=object&object_id=${ref['object_id']}";
2299 echo "&hl_ipv4_addr=${addr['ip']}'>";
2300 echo $ref['name'] . (empty ($ref['name']) ? '' : '@');
2301 echo "${ref['object_name']}</a>";
2302 $delim = '; ';
2303 }
2304 if ($delim != '')
2305 {
2306 $delim = '';
2307 $prologue = '<br>';
2308 }
2309 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2310 {
2311 echo $prologue;
2312 $prologue = '';
2313 echo "${delim}<a href='${root}?page=object&object_id=${ref['object_id']}'>";
2314 echo "${ref['object_name']}</a>:<a href='${root}?page=ipv4vs&vs_id=${ref['vs_id']}'>";
2315 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2316 $delim = '; ';
2317 }
2318 if ($delim != '')
2319 {
2320 $delim = '';
2321 $prologue = '<br>';
2322 }
2323 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2324 {
2325 echo $prologue;
2326 $prologue = '';
2327 echo "${delim}&rarr;${ref['rsport']}@<a href='${root}?page=ipv4rsp&pool_id=${ref['rspool_id']}'>";
2328 echo "${ref['rspool_name']}</a>";
2329 $delim = '; ';
2330 }
2331 echo "</td></tr>\n";
2332 endfor;
2333 // end of iteration
2334
2335 echo "</table>";
2336 finishPortlet();
2337 echo "</td></tr></table>\n";
2338 }
2339
2340 function renderIPv4NetworkProperties ($id)
2341 {
2342 showMessageOrError();
2343 $netdata = getIPv4NetworkInfo ($id);
2344 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
2345 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2346 printOpFormIntro ('editRange');
2347 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${netdata['name']}'></tr>";
2348 echo "<tr><td colspan=2 class=tdcenter>";
2349 printImageHREF ('SAVE', 'Save changes', TRUE);
2350 echo "</td></form></tr></table>\n";
2351
2352 }
2353
2354 function renderIPv4Address ($dottedquad)
2355 {
2356 global $root, $aat;
2357 $address = getIPv4Address ($dottedquad);
2358 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2359 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2360 if (!empty ($address['name']))
2361 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
2362
2363 echo "<tr><td class=pcleft>";
2364 startPortlet ('summary');
2365 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2366 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
2367 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2368 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2369 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
2370 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2371 printTagTRs();
2372 echo "</table><br>\n";
2373 finishPortlet();
2374 echo "</td>\n";
2375
2376 echo "<td class=pcright>";
2377
2378 if (!empty ($address['class']))
2379 {
2380 startPortlet ('allocations');
2381 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2382 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2383 $class = $address['class'];
2384 // render all allocation records for this address the same way
2385 if ($address['reserved'] == 'yes')
2386 echo "<tr class='${class}'><td colspan=2>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td></tr>";
2387 foreach ($address['allocs'] as $bond)
2388 {
2389 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2390 $secondclass = 'tdleft port_highlight';
2391 else
2392 $secondclass = 'tdleft';
2393 echo "<tr class='$class'><td class=tdleft><a href='${root}?page=object&object_id=${bond['object_id']}";
2394 echo "&hl_ipv4_addr=${dottedquad}'>${bond['object_name']}</td><td class='${secondclass}'>${bond['name']}</td><td class='${secondclass}'><strong>";
2395 echo $aat[$bond['type']];
2396 echo "</strong></td></tr>\n";
2397 }
2398 echo "</table><br><br>";
2399 finishPortlet();
2400 }
2401
2402 // FIXME: The returned list is structured differently, than we expect it to be. One of the sides
2403 // must be fixed.
2404 if (count ($address['lblist']))
2405 {
2406 startPortlet ('Virtual services (' . count ($address['lblist']) . ')');
2407 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2408 echo "<tr><th>VS</th><th>name</th></tr>\n";
2409 foreach ($address['lblist'] as $vsinfo)
2410 {
2411 echo "<tr><td class=tdleft><a href='${root}?page=ipv4vs&vs_id=${vsinfo['vs_id']}'>";
2412 echo buildVServiceName ($vsinfo) . "</a></td><td class=tdleft>";
2413 echo $vsinfo['name'] . "</td></tr>\n";
2414 }
2415 echo "</table><br><br>";
2416 finishPortlet();
2417 }
2418
2419 if (count ($address['rslist']))
2420 {
2421 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2422 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2423 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
2424 foreach ($address['rslist'] as $rsinfo)
2425 {
2426 echo "<tr><td>";
2427 if ($rsinfo['inservice'] == 'yes')
2428 printImageHREF ('inservice', 'in service');
2429 else
2430 printImageHREF ('notinservice', 'NOT in service');
2431 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='${root}?page=ipv4rsp&pool_id=${rsinfo['rspool_id']}'>";
2432 echo $rsinfo['rspool_name'] . "</a></td></tr>\n";
2433 }
2434 echo "</table><br><br>";
2435 finishPortlet();
2436 }
2437
2438 if (count ($address['outpf']))
2439 {
2440 startPortlet ('departing NAT rules');
2441 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2442 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2443 foreach ($address['outpf'] as $rule)
2444 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['localport']}</td><td>${rule['description']}</td></tr>";
2445 echo "</table>";
2446 finishPortlet();
2447 }
2448
2449 if (count ($address['inpf']))
2450 {
2451 startPortlet ('arriving NAT rules');
2452 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2453 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2454 foreach ($address['inpf'] as $rule)
2455 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['localport']}</td><td>${rule['description']}</td></tr>";
2456 echo "</table>";
2457 finishPortlet();
2458 }
2459
2460 echo "</td></tr>";
2461 echo "</table>\n";
2462 }
2463
2464 function renderIPv4AddressProperties ($dottedquad)
2465 {
2466 showMessageOrError();
2467 $address = getIPv4Address ($dottedquad);
2468 echo "<center><h1>$dottedquad</h1></center>\n";
2469
2470 startPortlet ('update');
2471 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2472 printOpFormIntro ('editAddress');
2473 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2474 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2475 echo ($address['reserved']=='yes') ? 'checked' : '';
2476 echo "></tr><tr><td colspan=2 class='tdcenter'>";
2477 printImageHREF ('SAVE', 'Save changes', TRUE);
2478 echo "</td></form></tr></table>\n";
2479 finishPortlet();
2480 if (empty ($address['name']) and $address['reserved'] == 'no')
2481 return;
2482
2483 startPortlet ('release');
2484 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2485 echo "<input type=submit value='release'></form>";
2486 finishPortlet();
2487 }
2488
2489 function renderIPv4AddressAllocations ($dottedquad)
2490 {
2491 showMessageOrError();
2492 global $pageno, $tabno, $root, $aat;
2493
2494 $address = getIPv4Address ($dottedquad);
2495 $class = $address['class'];
2496 echo "<center><h1>${dottedquad}</h1></center>\n";
2497 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2498 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
2499
2500 if ($address['reserved'] == 'yes')
2501 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2502 foreach ($address['allocs'] as $bond)
2503 {
2504 echo "<tr class='$class'>";
2505 printOpFormIntro ('updIPv4Allocation', array ('object_id' => $bond['object_id']));
2506 echo "<td><a href='${root}process.php?op=delIPv4Allocation&page=${pageno}&tab=${tabno}&ip=${dottedquad}&object_id=${bond['object_id']}'>";
2507 printImageHREF ('delete', 'Unallocate address');
2508 echo "</a></td>";
2509 echo "<td><a href='${root}?page=object&object_id=${bond['object_id']}&hl_ipv4_addr=${dottedquad}'>${bond['object_name']}</td>";
2510 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
2511 printSelect ($aat, 'bond_type', $bond['type']);
2512 echo "</td><td>";
2513 printImageHREF ('save', 'Save changes', TRUE);
2514 echo "</td></form></tr>\n";
2515 }
2516 printOpFormIntro ('addIPv4Allocation');
2517 echo "<td>";
2518 printImageHREF ('add', 'new allocation', TRUE);
2519 echo "</td><td><select name='object_id'>";
2520
2521 foreach (explode (',', getConfigVar ('IPV4_PERFORMERS')) as $type)
2522 foreach (getNarrowObjectList ($type) as $object)
2523 echo "<option value='${object['id']}'>${object['dname']}</option>";
2524
2525 echo "</select></td><td><input type='text' name='bond_name' value='' size=10></td><td>";
2526 printSelect ($aat, 'bond_type');
2527 echo "</td><td>&nbsp;</td></form></tr>";
2528 echo "</table><br><br>";
2529
2530 }
2531
2532 function renderNATv4ForObject ($object_id = 0)
2533 {
2534 global $pageno, $tabno, $root;
2535
2536 $info = getObjectInfo ($object_id);
2537 $forwards = getNATv4ForObject ($object_id);
2538 $alloclist = getObjectIPv4Allocations ($object_id);
2539 showMessageOrError();
2540 echo "<center><h2>locally performed NAT</h2></center>";
2541
2542 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2543 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
2544
2545 foreach ($forwards['out'] as $pf)
2546 {
2547 $class = 'trerror';
2548 $osif = '';
2549 if (isset ($alloclist [$pf['localip']]))
2550 {
2551 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
2552 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
2553 }
2554
2555 echo "<tr class='$class'>";
2556 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}'>";
2557 printImageHREF ('delete', 'Delete NAT rule');
2558 echo "</a></td>";
2559 echo "<td>${pf['proto']}/${osif}<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}";
2560 if (!empty ($pf['local_addr_name']))
2561 echo ' (' . $pf['local_addr_name'] . ')';
2562 echo "</td>";
2563 echo "<td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2564
2565 $address = getIPv4Address ($pf['remoteip']);
2566
2567 echo "<td class='description'>";
2568 if (count ($address['allocs']))
2569 foreach ($address['allocs'] as $bond)
2570 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
2571 elseif (!empty ($pf['remote_addr_name']))
2572 echo '(' . $pf['remote_addr_name'] . ')';
2573 printOpFormIntro
2574 (
2575 'updNATv4Rule',
2576 array
2577 (
2578 'localip' => $pf['localip'],
2579 'localport' => $pf['localport'],
2580 'remoteip' => $pf['remoteip'],
2581 'remoteport' => $pf['remoteport'],
2582 'proto' => $pf['proto']
2583 )
2584 );
2585 echo "</td><td class='description'>";
2586 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2587 printImageHREF ('save', 'Save changes', TRUE);
2588 echo "</td></form></tr>";
2589 }
2590 printOpFormIntro ('addNATv4Rule');
2591 echo "<tr align='center'><td>";
2592 printImageHREF ('add', 'Add new NAT rule', TRUE);
2593 echo '</td><td>';
2594 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
2595 echo "<select name='localip' tabindex=1>";
2596
2597 foreach ($alloclist as $dottedquad => $alloc)
2598 {
2599 $name = empty ($alloc['addrinfo']['name']) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2600 $osif = empty ($alloc['osif']) ? '' : ($alloc['osif'] . ': ');
2601 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
2602 }
2603
2604 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2605 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2606 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\");'>";
2607 printImageHREF ('find', 'Find object');
2608 echo "</a>";
2609 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2610 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>&nbsp;</td></tr>";
2611 echo "</form>";
2612
2613 echo "</table><br><br>";
2614
2615 echo "<center><h2>arriving NAT connections</h2></center>";
2616 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2617 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2618
2619 foreach ($forwards['in'] as $pf)
2620 {
2621 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}'>";
2622 printImageHREF ('delete', 'Delete NAT rule');
2623 echo "</a></td>";
2624 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
2625 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
2626 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2627 echo "<td class='description'>${pf['description']}</td></tr>";
2628 }
2629
2630 echo "</table><br><br>";
2631 }
2632
2633 // FIXME: move related code away into ophandler(s)
2634 function renderAddMultipleObjectsForm ()
2635 {
2636 global $root, $pageno, $tabno, $nextorder;
2637
2638 $type_id = array();
2639 $global_type_id = 0;
2640 $name = array();
2641 $asset_no = array();
2642 $keepvalues1 = $keepvalues2 = FALSE;
2643 $log = array();
2644 // Look for current submit.
2645 if (isset ($_REQUEST['got_fast_data']))
2646 {
2647 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
2648 $keepvalues1 = TRUE;
2649 $max = getConfigVar ('MASSCOUNT');
2650 for ($i = 0; $i < $max; $i++)
2651 {
2652 if (!isset ($_REQUEST["${i}_object_type_id"]))
2653 {
2654 $log[] = array ('code' => 'error', 'message' => "Submitted form is invalid at line " . $i + 1);
2655 break;
2656 }
2657 assertUIntArg ("${i}_object_type_id", __FUNCTION__, TRUE);
2658 assertStringArg ("${i}_object_name", __FUNCTION__, TRUE);
2659 assertStringArg ("${i}_object_label", __FUNCTION__, TRUE);
2660 assertStringArg ("${i}_object_asset_no", __FUNCTION__, TRUE);
2661 assertStringArg ("${i}_object_barcode", __FUNCTION__, TRUE);
2662 $type_id[$i] = $_REQUEST["${i}_object_type_id"];
2663 // Save user input for possible rendering.
2664 $name[$i] = $_REQUEST["${i}_object_name"];
2665 $label[$i] = $_REQUEST["${i}_object_label"];
2666 $asset_no[$i] = $_REQUEST["${i}_object_asset_no"];
2667 $barcode[$i] = $_REQUEST["${i}_object_barcode"];
2668
2669 // It's better to skip silently, than to print a notice.
2670 if ($type_id[$i] == 0)
2671 continue;
2672 if (commitAddObject ($name[$i], $label[$i], $barcode[$i], $type_id[$i], $asset_no[$i], $taglist) === TRUE)
2673 $log[] = array ('code' => 'success', 'message' => "Added new object '${name[$i]}'");
2674 else
2675 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitAddObject() failed');
2676 }
2677 }
2678 elseif (isset ($_REQUEST['got_very_fast_data']))
2679 {
2680 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
2681 $keepvalues2 = TRUE;
2682 assertUIntArg ('global_type_id', __FUNCTION__, TRUE);
2683 assertStringArg ('namelist', __FUNCTION__, TRUE);
2684 $global_type_id = $_REQUEST['global_type_id'];
2685 if ($global_type_id == 0)
2686 {
2687 if (!empty ($_REQUEST['namelist']))
2688 $log[] = array ('code' => 'error', 'message' => 'Object type is not selected, check the form below');
2689 else
2690 $log[] = array ('code' => 'error', 'message' => 'Empty form has been ignored. Cheers.');
2691 }
2692 else
2693 {
2694 // The name extractor below was stolen from ophandlers.php:addMultiPorts()
2695 $names1 = explode ('\n', $_REQUEST['namelist']);
2696 $names2 = array();
2697 foreach ($names1 as $line)
2698 {
2699 $parts = explode ('\r', $line);
2700 reset ($parts);
2701 if (empty ($parts[0]))
2702 continue;
2703 else
2704 $names2[] = rtrim ($parts[0]);
2705 }
2706 foreach ($names2 as $cname)
2707 if (commitAddObject ($cname, '', '', $global_type_id, '', $taglist) === TRUE)
2708 $log[] = array ('code' => 'success', 'message' => "Added new object '${cname}'");
2709 else
2710 $log[] = array ('code' => 'error', 'message' => "Could not add '${cname}'");
2711 }
2712 }
2713 printLog ($log);
2714
2715 // Render a form for the next.
2716 $typelist = getObjectTypeList();
2717 $typelist[0] = 'select type...';
2718
2719 startPortlet ('Distinct types, same tags');
2720 $max = getConfigVar ('MASSCOUNT');
2721 echo "<form name=fastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
2722 echo '<table border=0 align=center>';
2723 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
2724 echo "<th>Asset tag</th><th>Barcode</th><th>Tags</th></tr>\n";
2725 // If a user forgot to select object type on input, we keep his
2726 // previous input in the form.
2727 for ($i = 0; $i < $max; $i++)
2728 {
2729 echo '<tr><td>';
2730 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2731 printSelect ($typelist, "${i}_object_type_id", 0);
2732 echo '</td>';
2733 echo "<td><input type=text size=30 name=${i}_object_name";
2734 if ($keepvalues1 and isset ($name[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2735 echo " value='${name[$i]}'";
2736 echo "></td>";
2737 echo "<td><input type=text size=30 name=${i}_object_label";
2738 if ($keepvalues1 and isset ($label[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2739 echo " value='${label[$i]}'";
2740 echo "></td>";
2741 echo "<td><input type=text size=20 name=${i}_object_asset_no";
2742 if ($keepvalues1 and isset ($asset_no[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2743 echo " value='${asset_no[$i]}'";
2744 echo "></td>";
2745 echo "<td><input type=text size=10 name=${i}_object_barcode";
2746 if ($keepvalues1 and isset ($barcode[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2747 echo " value='${barcode[$i]}'";
2748 echo "></td>";
2749 if ($i == 0)
2750 {
2751 echo "<td valign=top rowspan=${max}>";
2752 renderTagSelect();
2753 echo "</td>\n";
2754 }
2755 echo "</tr>\n";
2756 }
2757 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2758 echo "</form></table>\n";
2759 finishPortlet();
2760
2761 startPortlet ('Same type, same tags');
2762 echo "<form name=veryfastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
2763 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2764 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
2765 if ($keepvalues2 and $global_type_id == 0)
2766 echo $_REQUEST['namelist'];
2767 echo "</textarea></td><td valign=top>";
2768 printSelect ($typelist, "global_type_id", getConfigVar ('DEFAULT_OBJECT_TYPE'));
2769 echo "</td></tr>";
2770 echo "<tr><th>Tags</th></tr>";
2771 echo "<tr><td valign=top>";
2772 renderTagSelect();
2773 echo "</td></tr>";
2774 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2775 echo "</form>\n";
2776 finishPortlet();
2777 }
2778
2779 function printGreeting ()
2780 {
2781 global $remote_username, $accounts, $root;
2782 $account = $accounts[$remote_username];
2783 $person = empty ($account['user_realname']) ? $account['user_name'] : $account['user_realname'];
2784 echo "Hello, ${person}. This is RackTables " . CODE_VERSION . ". Click <a href='${root}?logout'>here</a> to logout.";
2785 }
2786
2787 function renderSearchResults ()
2788 {
2789 global $remote_username, $root;
2790 $terms = trim ($_REQUEST['q']);
2791 if (empty ($terms))
2792 {
2793 showError ('Search string cannot be empty.', __FUNCTION__);
2794 return;
2795 }
2796 if (!permitted ('objects', 'default'))
2797 {
2798 showError ('You are not authorized for viewing information about objects.', __FUNCTION__);
2799 return;
2800 }
2801 $nhits = 0;
2802 // If we search for L2 address, we can either find one or find none.
2803 if
2804 (
2805 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
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 // STP bridge ID: bridge priotity + port MAC address. Cut off first 4 chars and look for MAC address.
2809 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)
2810 )
2811 // Search for L2 address.
2812 {
2813 $terms = str_replace ('.', '', $terms);
2814 $terms = str_replace (':', '', $terms);
2815 $terms = substr ($terms, -12);
2816 $result = searchByl2address ($terms);
2817 if ($result !== NULL)
2818 {
2819 $nhits++;
2820 $lasthit = 'port';
2821 $summary['port'][] = $result;
2822 }
2823 }
2824 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))
2825 // Search for IP address.
2826 {
2827 if (NULL !== getIPv4AddressNetworkId ($terms))
2828 {
2829 $nhits++;
2830 $lasthit = 'ipv4addressbydq';
2831 $summary['ipv4addressbydq'][] = $terms;
2832 }
2833 }
2834 else
2835 // Search for objects, addresses, networks, virtual services and RS pools by their description.
2836 {
2837 $tmp = getObjectSearchResults ($terms);
2838 if (count ($tmp))
2839 {
2840 $nhits += count ($tmp);
2841 $lasthit = 'object';
2842 $summary['object'] = $tmp;
2843 }
2844 $tmp = getIPv4AddressSearchResult ($terms);
2845 if (count ($tmp))
2846 {
2847 $nhits += count ($tmp);
2848 $lasthit = 'ipv4addressbydescr';
2849 $summary['ipv4addressbydescr'] = $tmp;
2850 }
2851 $tmp = getIPv4PrefixSearchResult ($terms);
2852 if (count ($tmp))
2853 {
2854 $nhits += count ($tmp);
2855 $lasthit = 'ipv4network';
2856 $summary['ipv4network'] = $tmp;
2857 }
2858 $tmp = getIPv4RSPoolSearchResult ($terms);
2859 if (count ($tmp))
2860 {
2861 $nhits += count ($tmp);
2862 $lasthit = 'ipv4rspool';
2863 $summary['ipv4rspool'] = $tmp;
2864 }
2865 $tmp = getIPv4VServiceSearchResult ($terms);
2866 if (count ($tmp))
2867 {
2868 $nhits += count ($tmp);
2869 $lasthit = 'ipv4vs';
2870 $summary['ipv4vs'] = $tmp;
2871 }
2872 $tmp = getAccountSearchResult ($terms);
2873 if (count ($tmp))
2874 {
2875 $nhits += count ($tmp);
2876 $lasthit = 'user';
2877 $summary['user'] = $tmp;
2878 }
2879 }
2880 if ($nhits == 0)
2881 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
2882 elseif ($nhits == 1)
2883 {
2884 $record = current ($summary[$lasthit]);
2885 switch ($lasthit)
2886 {
2887 case 'port':
2888 echo "<script language='Javascript'>document.location='${root}?page=object";
2889 echo "&hl_port_id=" . $record['port_id'];
2890 echo "&object_id=" . $record['object_id'] . "';//</script>";
2891 break;
2892 case 'ipv4addressbydq':
2893 $parentnet = getIPv4AddressNetworkId ($record);
2894 if ($parentnet !== NULL)
2895 echo "<script language='Javascript'>document.location='${root}?page=iprange&id=${parentnet}&hl_ipv4_addr=${record}';//</script>";
2896 else
2897 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record}';//</script>";
2898 break;
2899 case 'ipv4addressbydescr':
2900 $parentnet = getIPv4AddressNetworkId ($record['ip']);
2901 if ($parentnet !== NULL)
2902 echo "<script language='Javascript'>document.location='${root}?page=iprange&id=${parentnet}&hl_ipv4_addr=${record['ip']}';//</script>";
2903 else
2904 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record['ip']}';//</script>";
2905 break;
2906 case 'ipv4network':
2907 echo "<script language='Javascript'>document.location='${root}?page=iprange";
2908 echo "&id=${record['id']}";
2909 echo "';//</script>";
2910 break;
2911 case 'object':
2912 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${record['id']}';//</script>";
2913 break;
2914 case 'ipv4rspool':
2915 echo "<script language='Javascript'>document.location='${root}?page=ipv4rsp&pool_id=${record['pool_id']}';//</script>";
2916 break;
2917 case 'ipv4vs':
2918 echo "<script language='Javascript'>document.location='${root}?page=ipv4vs&vs_id=${record['id']}';//</script>";
2919 break;
2920 case 'user':
2921 echo "<script language='Javascript'>document.location='${root}?page=user&user_id=${record['user_id']}';//</script>";
2922 break;
2923 }
2924 return;
2925 }
2926 else
2927 {
2928 global $nextorder;
2929 $order = 'odd';
2930 echo "<center><h2>${nhits} result(s) found for '${terms}'</h2></center>";
2931 foreach ($summary as $where => $what)
2932 switch ($where)
2933 {
2934 case 'object':
2935 startPortlet ("<a href='${root}?page=objects'>Objects</a>");
2936 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2937 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>barcode</th></tr>';
2938 foreach ($what as $obj)
2939 {
2940 echo "<tr class=row_${order}><td><a href=\"${root}?page=object&object_id=${obj['id']}\">${obj['dname']}</a></td>";
2941 echo "<td>${obj['label']}</td>";
2942 echo "<td>${obj['asset_no']}</td>";
2943 echo "<td>${obj['barcode']}</td></tr>";
2944 $order = $nextorder[$order];
2945 }
2946 echo '</table>';
2947 finishPortlet();
2948 break;
2949 case 'ipv4network':
2950 startPortlet ("<a href='${root}?page=ipv4space'>IPv4 networks</a>");
2951 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2952 echo '<tr><th>network</th><th>name/tags</th></tr>';
2953 foreach ($what as $net)
2954 {
2955 $prefixtags = loadIPv4PrefixTags ($net['id']);
2956 echo "<tr class=row_${order} valign=top><td class=tdleft><a href='${root}?page=iprange&id=${net['id']}'>${net['ip']}";
2957 echo '/' . $net['mask'] . '</a></td>';
2958 echo "<td class=tdleft>${net['name']}";
2959 if (count ($prefixtags))
2960 {
2961 echo "<br>";
2962 echo serializeTags ($prefixtags, "${root}?page=ipv4space&tab=default&");
2963 }
2964 echo "</td></tr>";
2965 $order = $nextorder[$order];
2966 }
2967 echo '</table>';
2968 finishPortlet();
2969 break;
2970 case 'ipv4addressbydescr':
2971 startPortlet ('IPv4 addresses');
2972 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2973 // FIXME: address, parent network, routers (if extended view is enabled)
2974 echo '<tr><th>Address</th><th>Descritpion</th></tr>';
2975 foreach ($what as $addr)
2976 {
2977 echo "<tr class=row_${order}><td class=tdleft>";
2978 $parentnet = getIPv4AddressNetworkId ($addr['ip']);
2979 if ($parentnet !== NULL)
2980 echo "<a href='${root}?page=iprange&id=${parentnet}&hl_ipv4_addr=${addr['ip']}'>${addr['ip']}</a></td>";
2981 else
2982 echo "<a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
2983 echo "<td class=tdleft>${addr['name']}</td></tr>";
2984 $order = $nextorder[$order];
2985 }
2986 echo '</table>';
2987 finishPortlet();
2988 break;
2989 case 'ipv4rspool':
2990 startPortlet ("<a href='${root}?page=ipv4rsplist'>RS pools</a>");
2991 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2992 foreach ($what as $rspool)
2993 {
2994 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=ipv4rsp&pool_id=${rspool['pool_id']}'>";
2995 echo buildRSPoolName ($rspool);
2996 echo "</a></td></tr>";
2997 $order = $nextorder[$order];
2998 }
2999 echo '</table>';
3000 finishPortlet();
3001 break;
3002 case 'ipv4vs':
3003 startPortlet ("<a href='${root}?page=ipv4vslist'>Virtual services</a>");
3004 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3005 echo '<tr><th>VS</th><th>Descritpion</th></tr>';
3006 foreach ($what as $vs)
3007 {
3008 echo "<tr class=row_${order}><td class=tdleft><a href='${root}?page=ipv4vs&vs_id=${vs['id']}'>";
3009 echo buildVServiceName ($vs);
3010 echo "</a></td><td class=tdleft>${vs['name']}</td></tr>";
3011 $order = $nextorder[$order];
3012 }
3013 echo '</table>';
3014 finishPortlet();
3015 break;
3016 case 'user':
3017 startPortlet ("<a href='${root}?page=userlist'>Users</a>");
3018 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3019 echo '<tr><th>username</th><th>realname</th></tr>';