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