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