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