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