4 * This file contains frontend functions for RackTables.
8 // Interface function's special.
9 $nextorder['odd'] = 'even';
10 $nextorder['even'] = 'odd';
13 function renderIndex ()
17 <table border
=0 cellpadding
=0 cellspacing
=0 width
='100%'>
20 <div style
='text-align: center; margin: 10px; '>
21 <table width
='100%' cellspacing
=0 cellpadding
=30 class=mainmenu border
=0>
24 <h1
><a href
='<?php echo $root; ?>?page=rackspace'>Rackspace
<br
>
25 <?php
printImageHREF ('rackspace'); ?
></a
></h1
>
28 <h1
><a href
='<?php echo $root; ?>?page=objects'>Objects
<br
>
29 <?php
printImageHREF ('objects'); ?
></a
></h1
>
32 <h1
><a href
='<?php echo $root; ?>?page=ipv4space'>IPv4 space
<br
>
33 <?php
printImageHREF ('ipv4space'); ?
></a
></h1
>
37 <table width
='100%' cellspacing
=0 cellpadding
=30 class=mainmenu border
=0>
40 <h1
><a href
='<?php echo $root; ?>?page=config'>Configuration
<br
>
41 <?php
printImageHREF ('config'); ?
></a
></h1
>
44 <h1
><a href
='<?php echo $root; ?>?page=reports'>Reports
<br
>
45 <?php
printImageHREF ('reports'); ?
></a
></h1
>
48 <h1
><a href
='<?php echo $root; ?>?page=help'>Help
<br
>
49 <?php
printImageHREF ('help'); ?
></a
></h1
>
60 function renderRackspace ()
63 <table border
=0 cellpadding
=10 cellpadding
=1>
65 // generate thumb gallery
66 $rackrowList = getRackRowInfo();
67 global $root, $nextorder;
68 $rackwidth = getConfigVar ('rtwidth_0') +
getConfigVar ('rtwidth_1') +
getConfigVar ('rtwidth_2');
70 foreach ($rackrowList as $rackrow)
72 echo "<tr class=row_${order}><th><a href='${root}?page=row&row_id=${rackrow['dict_key']}'>${rackrow['dict_value']}</a></th>";
73 $rackList = getRacksForRow ($rackrow['dict_key']);
74 echo "<td><table border=0 cellspacing=5><tr>";
75 foreach ($rackList as $dummy => $rack)
77 echo "<td align=center><a href='${root}?page=rack&rack_id=${rack['id']}'>";
78 echo "<img border=0 width=${rackwidth} height=";
79 echo 3 +
3 +
$rack['height'] * 2;
80 echo " title='${rack['height']} units'";
81 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
82 echo "<br>${rack['name']}</a></td>";
84 echo "</tr></table></tr>\n";
85 $order = $nextorder[$order];
90 function renderRow ($row_id)
94 showError ('Invalid row_id', __FUNCTION__
);
97 if (($rowInfo = getRackRowInfo ($row_id)) == NULL)
99 showError ('getRackRowInfo() failed', __FUNCTION__
);
102 $rackList = getRacksForRow ($row_id);
103 // Main layout starts.
104 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
106 // Left portlet with row information.
107 echo "<tr><td class=pcleft>";
108 startPortlet ($rowInfo['dict_value']);
109 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
110 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
111 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
112 echo "<tr><th width='50%' class=tdright>Utilization:</th><td class=tdleft>";
113 renderProgressBar (getRSUforRackRow ($rackList));
115 echo "</table><br>\n";
118 echo "</td><td class=pcright>";
120 global $root, $nextorder;
121 $rackwidth = getConfigVar ('rtwidth_0') +
getConfigVar ('rtwidth_1') +
getConfigVar ('rtwidth_2');
123 startPortlet ('Racks');
124 echo "<table border=0 cellspacing=5 align='center'><tr>";
125 foreach ($rackList as $dummy => $rack)
127 echo "<td align=center class=row_${order}><a href='${root}?page=rack&rack_id=${rack['id']}'>";
128 echo "<img border=0 width=" . $rackwidth * getConfigVar ('ROW_SCALE') . " height=";
129 echo (3 +
3 +
$rack['height'] * 2) * getConfigVar ('ROW_SCALE');
130 echo " title='${rack['height']} units'";
131 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
132 echo "<br>${rack['name']}</a></td>";
133 $order = $nextorder[$order];
135 echo "</tr></table>\n";
138 echo "</td></tr></table>";
141 function showError ($info = '', $funcname = 'N/A')
144 echo "<div class=msg_error>An error has occured in function [${funcname}]. ";
146 echo 'No additional information is available.';
148 echo "Additional information:<br><p>\n<pre>\n${info}\n</pre></p>";
149 echo "Go back or try starting from <a href='${root}'>index page</a>.<br></div>\n";
152 // This function renders rack as HTML table.
153 function renderRack ($rack_id = 0, $hl_obj_id = 0)
157 showError ('Invalid rack_id', __FUNCTION__
);
160 if (($rackData = getRackData ($rack_id)) == NULL)
162 showError ('getRackData() failed', __FUNCTION__
);
165 global $root, $pageno, $tabno;
166 markAllSpans ($rackData);
168 highlightObject ($rackData, $hl_obj_id);
169 markupObjectProblems ($rackData);
170 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
171 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
172 echo "<center>\n<h2><a href='${root}?page=row&row_id=${rackData['row_id']}'>${rackData['row_name']}</a> :";
173 // FIXME: use 'bypass'?
174 if ($prev_id != NULL)
175 echo " <a href='${root}?page=rack&rack_id=${prev_id}'>< < <</a>";
176 echo " <a href='${root}?page=rack&rack_id=${rackData['id']}'>${rackData['name']}</a>";
177 if ($next_id != NULL)
178 echo " <a href='${root}?page=rack&rack_id=${next_id}'>> > ></a>";
180 if ($rackData['left_is_front'] == 'yes')
181 $markup = array ('left' => 'Front', 'right' => 'Back');
183 $markup = array ('left' => 'Back', 'right' => 'Front');
184 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
185 echo "<tr><th width='10%'> </th><th width='20%'>${markup['left']}</th>";
186 echo "<th width='50%'>Interior</th><th width='20%'>${markup['right']}</th></tr>\n";
187 for ($i = $rackData['height']; $i > 0; $i--)
189 echo '<tr><th>' . ($rackData['bottom_is_unit1'] == 'yes' ?
$i : $rackData['height'] - $i +
1) . '</th>';
190 for ($locidx = 0; $locidx < 3; $locidx++
)
192 if (isset ($rackData[$i][$locidx]['skipped']))
194 $state = $rackData[$i][$locidx]['state'];
195 echo "<td class=state_${state}";
196 if (isset ($rackData[$i][$locidx]['hl']))
197 echo $rackData[$i][$locidx]['hl'];
198 if (isset ($rackData[$i][$locidx]['colspan']))
199 echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
200 if (isset ($rackData[$i][$locidx]['rowspan']))
201 echo ' rowspan=' . $rackData[$i][$locidx]['rowspan'];
206 $objectData = getObjectInfo ($rackData[$i][$locidx]['object_id']);
207 if (!empty ($objectData['asset_no']))
208 $prefix = "<div title='${objectData['asset_no']}";
210 $prefix = "<div title='no asset tag";
211 // Don't tell about label, if it matches common name.
212 if ($objectData['name'] != $objectData['label'] and !empty ($objectData['label']))
213 $suffix = ", visible label is \"${objectData['label']}\"'>";
216 echo $prefix . $suffix;
217 echo "<a href='${root}?page=object&object_id=${objectData['id']}'>${objectData['dname']}</a></div>";
220 echo '<div title="This rackspace does not exist"> </div>';
223 echo '<div title="Free rackspace"> </div>';
226 echo '<div title="Problematic rackspace, you CAN\'T mount here"> </div>';
229 echo '<div title="No data"> </div>';
236 echo "</table></center>\n";
239 function renderNewObjectForm ()
241 global $pageno, $tabno;
243 // Look for current submit.
244 if (isset ($_REQUEST['got_data']))
247 assertUIntArg ('object_type_id');
248 assertStringArg ('object_name', TRUE);
249 assertStringArg ('object_label', TRUE);
250 assertStringArg ('object_barcode', TRUE);
251 assertStringArg ('object_asset_no', TRUE);
252 $type_id = $_REQUEST['object_type_id'];
253 $name = $_REQUEST['object_name'];
254 $label = $_REQUEST['object_label'];
255 $asset_no = $_REQUEST['object_asset_no'];
256 $barcode = $_REQUEST['object_barcode'];
258 if (commitAddObject ($name, $label, $barcode, $type_id, $asset_no) === TRUE)
259 $log[] = array ('code' => 'success', 'message' => "Added new object '${name}'");
261 $log[] = array ('code' => 'error', 'message' => __FUNCTION__
. ': commitAddObject() failed');
265 // Render a form for the next.
266 startPortlet ('Object attributes');
268 echo "<input type=hidden name=page value=${pageno}>";
269 echo "<input type=hidden name=tab value=${tabno}>";
270 echo '<table border=0 align=center>';
271 echo "<tr><th class=tdright>Type:</th><td class=tdleft>";
272 printSelect (getObjectTypeList(), 'object_type_id');
274 echo "<tr><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name></td></tr>\n";
275 echo "<tr><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label></td></tr>\n";
276 echo "<tr><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=object_asset_no></td></tr>\n";
277 echo "<tr><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode></td></tr>\n";
278 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Create'></td></tr>\n";
279 echo '</form></table>';
283 function renderNewRackForm ($row_id)
285 global $pageno, $tabno;
287 // Look for current submit.
288 if (isset ($_REQUEST['got_data']))
291 assertStringArg ('rack_name');
292 assertUIntArg ('rack_height');
293 assertStringArg ('rack_comment', TRUE);
294 $name = $_REQUEST['rack_name'];
295 $height = $_REQUEST['rack_height'];
296 $comment = $_REQUEST['rack_comment'];
298 if (commitAddRack ($name, $height, $row_id, $comment) === TRUE)
299 $log[] = array ('code' => 'success', 'message' => "Added new rack '${name}'");
301 $log[] = array ('code' => 'error', 'message' => __FUNCTION__
. 'commitAddRack() failed');
305 // Render a form for the next.
306 startPortlet ('Rack attributes');
308 echo "<input type=hidden name=page value=${pageno}>";
309 echo "<input type=hidden name=tab value=${tabno}>";
310 echo "<input type=hidden name=row_id value=${row_id}>";
311 echo '<table border=0 align=center>';
312 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
315 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name tabindex=1></td></tr>\n";
316 echo "<tr><th class=tdright>Height in units (required):</th><td class=tdleft><input type=text name=rack_height tabindex=2 value='${defh}'></td></tr>\n";
317 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
318 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Create'></td></tr>\n";
319 echo '</form></table>';
323 function renderEditObjectForm ($object_id)
325 showMessageOrError();
327 if (isset ($_REQUEST['got_data']))
330 // object_id is already verified by page handler
331 assertUIntArg ('object_type_id');
332 assertStringArg ('object_name', TRUE);
333 assertStringArg ('object_label', TRUE);
334 assertStringArg ('object_barcode', TRUE);
335 assertStringArg ('object_asset_no', TRUE);
336 $type_id = $_REQUEST['object_type_id'];
337 if (isset ($_REQUEST['object_has_problems']) and $_REQUEST['object_has_problems'] == 'on')
338 $has_problems = 'yes';
340 $has_problems = 'no';
341 $name = $_REQUEST['object_name'];
342 $label = $_REQUEST['object_label'];
343 $barcode = $_REQUEST['object_barcode'];
344 $asset_no = $_REQUEST['object_asset_no'];
345 $comment = $_REQUEST['object_comment'];
347 if (commitUpdateObject ($object_id, $name, $label, $barcode, $type_id, $has_problems, $asset_no, $comment) === TRUE)
348 $log[] = array ('code' => 'success', 'message' => "Updated object '${name}'");
350 $log[] = array ('code' => 'error', 'message' => __FUNCTION__
. ': commitUpdateObject() failed');
351 // Invalidate thumb cache of all racks objects could occupy.
352 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
353 resetThumbCache ($rack_id);
357 global $pageno, $tabno;
358 $object = getObjectInfo ($object_id);
361 showError ('getObjectInfo() failed', __FUNCTION__
);
365 // Render a form for the next submit;
366 echo '<table border=0 width=100%><tr>';
368 echo '<td class=pcleft>';
369 startPortlet ('Static attributes');
371 echo "<input type=hidden name=page value=${pageno}>";
372 echo "<input type=hidden name=tab value=${tabno}>";
373 echo "<input type=hidden name=object_id value=${object_id}>";
374 echo '<table border=0 align=center>';
375 echo "<tr><th class=tdright>Type:</th><td class=tdleft>";
376 printSelect (getObjectTypeList(), 'object_type_id', $object['objtype_id']);
378 // Common attributes.
379 echo "<tr><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name value='${object['name']}'></td></tr>\n";
380 echo "<tr><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label value='${object['label']}'></td></tr>\n";
381 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";
382 echo "<tr><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode value='${object['barcode']}'></td></tr>\n";
383 echo "<tr><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
384 if ($object['has_problems'] == 'yes')
386 echo "></td></tr>\n";
387 echo "<tr><td colspan=2><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
388 echo "<tr><th class=submit colspan=2><input type=submit name=got_data value='Update'></td></tr>\n";
389 echo '</form></table><br>';
393 // Optional attributes.
394 echo '<td class=pcright>';
395 startPortlet ('Optional attributes');
396 $values = getAttrValues ($object_id);
398 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
399 echo "<tr><th> </th><th>Attribute</th><th>Value</th><th> </th></tr>\n";
400 echo "<form method=post action='${root}process.php'>\n";
401 echo "<input type=hidden name=page value=${pageno}>\n";
402 echo "<input type=hidden name=tab value=${tabno}>\n";
403 echo "<input type=hidden name=op value=upd>\n";
404 echo "<input type=hidden name=object_id value=${object_id}>\n";
405 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
408 foreach ($values as $record)
410 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
411 echo "<tr><td><a href=${root}process.php?page=${pageno}&tab=${tabno}&op=del&object_id=${object_id}&attr_id=${record['id']}>";
412 printImageHREF ('delete', 'Delete value');
414 echo "<td class=tdright>${record['name']}:</td><td class=tdleft>";
415 switch ($record['type'])
420 echo "<input type=text name=${i}_value value='${record['value']}'>";
423 $chapter = readChapter ($record['chapter_name']);
424 $chapter[0] = '-- NOT SET --';
425 printSelect ($chapter, "${i}_value", $record['key']);
431 echo "<tr><td colspan=3><input type=submit value='Update'></td></tr>\n";
439 echo '<td colspan=2>';
440 startPortlet ('history');
441 renderHistory ($pageno, $object_id);
445 echo '</tr></table>';
448 // This is a clone of renderEditObjectForm().
449 function renderEditRackForm ($rack_id)
452 if (isset ($_REQUEST['got_data']))
455 assertUIntArg ('rack_row_id');
456 assertUIntArg ('rack_height');
457 assertStringArg ('rack_name');
458 assertStringArg ('rack_comment', TRUE);
459 $row_id = $_REQUEST['rack_row_id'];
460 $height = $_REQUEST['rack_height'];
461 $name = $_REQUEST['rack_name'];
462 $comment = $_REQUEST['rack_comment'];
464 if (commitUpdateRack ($rack_id, $name, $height, $row_id, $comment) === TRUE)
465 $log[] = array ('code' => 'success', 'message' => "Updated rack '${name}'");
467 $log[] = array ('code' => 'error', 'message' => __FUNCTION__
. ': commitUpdateRack() failed');
468 resetThumbCache ($rack_id);
472 global $pageno, $tabno;
473 $rack = getRackData ($rack_id);
476 showError ('getRackData() failed', __FUNCTION__
);
480 // Render a form for the next.
481 startPortlet ('Rack attributes');
483 echo "<input type=hidden name=page value=${pageno}>";
484 echo "<input type=hidden name=tab value=${tabno}>";
485 echo "<input type=hidden name=rack_id value=${rack_id}>";
486 echo '<table border=0 align=center>';
487 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
488 printSelect (readChapter ('RackRow'), 'rack_row_id', $rack['row_id']);
490 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
491 echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
492 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
493 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Update'></td></tr>\n";
494 echo '</form></table><br>';
497 startPortlet ('History');
498 renderHistory ($pageno, $rack_id);
502 // This is a helper for creators and editors.
503 function printSelect ($rowList, $select_name, $selected_id = 1)
505 echo "<select name=${select_name}>";
506 foreach ($rowList as $dict_key => $dict_value)
508 echo "<option value=${dict_key}";
509 if ($dict_key == $selected_id)
511 echo ">${dict_value}</option>";
516 // This is a universal editor of rack design/waste.
517 function renderGridForm ($rack_id = 0, $filter, $header, $submit, $state1, $state2)
521 showError ('Invalid rack_id', __FUNCTION__
);
524 if (($rackData = getRackData ($rack_id)) == NULL)
526 showError ('getRackData() failed', __FUNCTION__
);
530 global $root, $pageno, $tabno;
532 markupObjectProblems ($rackData);
534 // Process form submit.
535 if (isset ($_REQUEST['do_update']))
537 $log[] = processGridForm ($rackData, $state1, $state2);
541 // Render the result whatever it is.
543 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
544 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
546 // Left column with information portlet.
547 echo "<tr><td class=pcleft height='1%' width='50%'>";
548 startPortlet ('Rack information');
549 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
550 echo "<tr><th width='50%' class=tdright>Rack name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
551 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
552 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
553 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
558 echo "<td class=pcright>";
561 startPortlet ($header);
563 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
564 echo "<tr><th width='10%'> </th><th width='20%'>Front</th>";
565 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
566 echo "<form action='${root}?'>\n";
567 echo "<input type=hidden name=page value=${pageno}>\n";
568 echo "<input type=hidden name=tab value=${tabno}>\n";
569 echo "<input type=hidden name=rack_id value=${rack_id}>\n";
570 markupAtomGrid ($rackData, $state2);
571 renderAtomGrid ($rackData);
572 echo "</table></center>\n";
573 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
575 echo "</td></tr></table>\n";
578 function renderRackDesign ($rack_id)
580 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
583 function renderRackProblems ($rack_id = 0)
585 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
588 function startPortlet ($title = '')
590 echo "<div class=portlet><h2>${title}</h2>";
593 function finishPortlet ()
598 function printRefsOfType ($refs, $type, $eq)
602 foreach ($refs as $ref)
604 if ($eq($ref['type'], $type))
606 if ($gotone) echo ', ';
607 echo "<a href='${root}?page=object&object_id=${ref['object_id']}'>";
608 if (!empty ($ref['name']))
609 echo $ref['name'] . '@';
610 echo "${ref['object_name']}</a>";
616 function renderRackObject ($object_id = 0)
621 showError ('Invalid object_id', __FUNCTION__
);
624 $info = getObjectInfo ($object_id);
627 showError ('getObjectInfo() failed', __FUNCTION__
);
630 // Main layout starts.
631 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
632 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
633 // left column with uknown number of portlets
634 echo "<tr><td class=pcleft>";
635 startPortlet ('Object information');
636 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
637 if (!empty ($info['name']))
638 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
639 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('NAMEFUL_OBJTYPES'))))
640 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
641 echo "<tr><th width='50%' class=tdright>Object type:</th><td class=tdleft>${info['objtype_name']}</td></tr>\n";
642 if (!empty ($info['asset_no']))
643 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
644 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('REQUIRE_ASSET_TAG_FOR'))))
645 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
646 if (!empty ($info['label']))
647 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
648 if (!empty ($info['barcode']))
649 echo "<tr><th width='50%' class=tdright>Barcode:</th><td class=tdleft>${info['barcode']}</td></tr>\n";
650 if ($info['has_problems'] == 'yes')
651 echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
652 foreach (getAttrValues ($object_id) as $record)
653 if (!empty ($record['value']))
654 echo "<tr><th width='50%' class=opt_attr_th>${record['name']}:</th><td class=tdleft>${record['a_value']}</td></tr>\n";
655 echo "</table><br>\n";
658 if (!empty ($info['comment']))
660 startPortlet ('Comment');
661 echo '<div class=commentblock>' . $info['comment'] . '</div>';
665 $ports = getObjectPortsAndLinks ($object_id);
668 startPortlet ('Ports and links');
669 usort($ports, 'sortByName');
673 if (isset ($_REQUEST['hl_port_id']))
675 assertUIntArg ('hl_port_id');
676 $hl_port_id = $_REQUEST['hl_port_id'];
678 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
679 echo "<tr><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
680 echo "<th>Rem. Object</th><th>Rem. port</th></tr>\n";
681 foreach ($ports as $port)
684 if ($hl_port_id == $port['id'])
685 echo ' class=port_highlight';
686 echo "><td>${port['name']}</td><td>${port['label']}</td><td>${port['type']}</td>";
687 echo "<td>${port['l2address']}</td>";
688 if ($port['remote_object_id'])
690 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}'>${port['remote_object_name']}</a></td>";
691 echo "<td>${port['remote_name']}</td>";
693 elseif (!empty ($port['reservation_comment']))
695 echo "<td><b>Reserved;</b></td>";
696 echo "<td>${port['reservation_comment']}</td>";
699 echo '<td> </td><td> </td>';
702 echo "</table><br>\n";
706 $addresses = getObjectAddresses ($object_id);
707 usort($addresses, 'sortAddresses');
708 if (count ($addresses))
710 startPortlet ('IPv4 addresses');
711 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
712 echo "<tr><th>Interface name</th><th>IP Address</th><th>Description</th><th>Misc</th></tr>\n";
713 foreach ($addresses as $addr)
715 if (strlen($addr['address_name'])>40)
716 $address_name = substr($addr['address_name'],0,38).'...';
718 $address_name = $addr['address_name'];
720 $virtnum = countRefsOfType($addr['references'], 'virtual', 'eq');
721 $sharednum = countRefsOfType($addr['references'], 'shared', 'eq');
722 $regnum = countRefsOfType($addr['references'], 'regular', 'eq');
723 $notvirtnum = countRefsOfType($addr['references'], 'virtual', 'neq');
725 if ($addr['address_reserved']=='yes')
727 elseif ($addr['type']!='virtual' && $regnum>0)
729 elseif ($addr['type']=='regular' && $sharednum>0)
734 echo "<tr class='$class'><td>${addr['name']}</td><td><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td><td class='description'>$address_name</td><td>\n";
736 if ($addr['address_reserved']=='yes')
737 echo "<b>Reserved;</b> ";
739 if ($addr['type'] == 'virtual')
745 printRefsOfType($addr['references'], 'virtual', 'neq');
748 elseif ($addr['type'] == 'shared')
754 printRefsOfType($addr['references'], 'shared', 'eq');
760 printRefsOfType($addr['references'], 'virtual', 'eq');
765 echo " Collisions: ";
766 printRefsOfType($addr['references'], 'regular', 'eq');
775 printRefsOfType($addr['references'], 'virtual', 'eq');
780 echo " Collisions: ";
781 printRefsOfType($addr['references'], 'virtual', 'neq');
787 echo "</table><br>\n";
791 $forwards = getObjectForwards ($object_id);
792 if (count($forwards['in']) or count($forwards['out']))
794 startPortlet('NATv4');
796 if (count($forwards['out']))
799 echo "<h3>locally performed NAT</h3>";
801 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
802 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
804 foreach ($forwards['out'] as $pf)
808 foreach ($addresses as $addr)
809 if ($addr['ip'] == $pf['localip'])
816 echo "<tr class='$class'>";
818 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>";
820 echo "<td class=tdleft><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
822 $address=getIPAddress($pf['remoteip']);
824 echo "<td class='description'>";
825 if (count ($address['bonds']))
826 foreach($address['bonds'] as $bond)
827 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
828 elseif (!empty ($pf['remote_addr_name']))
829 echo '(' . $pf['remote_addr_name'] . ')';
831 echo "</td><td class='description'>${pf['description']}</td>";
835 echo "</table><br><br>";
837 if (count($forwards['in']))
839 echo "<h3>arriving NAT connections</h3>";
841 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
842 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
844 foreach ($forwards['in'] as $pf)
847 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
849 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
851 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
852 echo "<td class='description'>${pf['description']}</td></tr>";
855 echo "</table><br><br>";
860 $pools = getRSPoolsForObject ($object_id);
863 startPortlet ('Real server pools');
864 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
865 echo "<tr><th>VS</th><th>RS pool</th><th>real servers</th></tr>\n";
866 foreach ($pools as $vs_id => $info)
868 echo "<tr><td class=tdleft><a href='${root}?page=vservice&id=${vs_id}'>";
869 echo buildVServiceName ($info);
871 if (!empty ($info['name']))
872 echo " (${info['name']})";
873 echo "</td><td class=tdleft><a href='${root}?page=rspool&id=${info['pool_id']}'>";
874 echo (empty ($info['pool_name']) ?
'ANONYMOUS' : $info['pool_name']);
875 echo '</a></td><td class=tdleft>' . $info['rscount'] . '</td>';
883 // After left column we have (surprise!) right column with rackspace portled only.
884 echo "<td class=pcright>";
886 startPortlet ('Rackspace allocation');
887 // FIXME: now we call getRackData() twice
888 $racks = getResidentRacksData ($object_id);
889 foreach ($racks as $rackData)
890 renderRack ($rackData['id'], $object_id);
897 function renderRackMultiSelect ($sname, $racks, $selected)
899 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementById(\"racks\").submit()'>\n";
900 foreach ($racks as $rack)
902 echo "<option value=${rack['id']}";
903 if (!(array_search ($rack['id'], $selected) === FALSE))
905 echo">${rack['row_name']}: ${rack['name']}</option>\n";
910 function showMessageOrError ()
912 if (isset($_REQUEST['message']))
913 echo "<div class=msg_success>${_REQUEST['message']}</div>";
914 if (isset($_REQUEST['error']))
915 echo "<div class=msg_error>${_REQUEST['error']}</div>";
918 // This function renders a form for port edition.
919 function renderPortsForObject ($object_id = 0)
921 global $root, $pageno, $tabno;
924 showError ('Invalid object_id', __FUNCTION__
);
927 showMessageOrError();
928 startPortlet ('Ports and interfaces');
929 $ports = getObjectPortsAndLinks ($object_id);
930 usort($ports, 'sortByName');
931 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
932 echo "<tr><th> </th><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
933 echo "<th>Rem. object</th><th>Rem. port</th><th>(Un)link or (un)reserve</th><th> </th></tr>\n";
934 foreach ($ports as $port)
936 echo "<form action='${root}process.php'>";
937 echo "<input type=hidden name=op value=editPort>";
938 echo "<input type=hidden name=page value='${pageno}'>\n";
939 echo "<input type=hidden name=tab value='${tabno}'>\n";
940 echo "<input type=hidden name=port_id value='${port['id']}'>";
941 echo "<input type=hidden name=object_id value='$object_id'>\n";
942 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']}'>";
943 printImageHREF ('delete', 'Unlink and Delete this port');
945 echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
946 echo "<td><input type=text name=label value='${port['label']}' size=24></td>";
947 echo "<td>${port['type']}</td>\n";
948 echo "<td><input type=text name=l2address value='${port['l2address']}'></td>\n";
949 if ($port['remote_object_id'])
951 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}'>${port['remote_object_name']}</a></td>";
952 echo "<td>${port['remote_name']}</td>";
953 echo "<td><a href='${root}process.php?op=unlinkPort&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=$object_id&port_name=";
954 echo urlencode ($port['name']);
955 echo "&remote_port_name=${port['remote_name']}&remote_object_name=${port['remote_object_name']}'>";
956 printImageHREF ('unlink', 'Unlink this port');
959 elseif (!empty ($port['reservation_comment']))
961 echo "<td><b>Reserved;</b></td>";
962 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
963 echo "<td><a href='${root}process.php?op=useup&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=${object_id}'>";
964 printImageHREF ('useup', 'Use up this port');
969 echo "<td> </td><td> </td>";
971 echo "<a href='javascript:;' onclick='window.open(\"${root}link_helper.php?port=${port['id']}&type=${port['type_id']}&object_id=$object_id&port_name=";
972 echo urlencode ($port['name']);
973 echo "\",\"findlink\",\"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
974 printImageHREF ('link', 'Link this port');
975 echo "</a> <input type=text name=reservation_comment>";
978 echo "<td><input type='submit' value='OK'></td>";
979 echo "</form></tr>\n";
981 echo "<form action='${root}process.php'><tr>";
982 echo "<td colspan=2><input type=text size=10 name=port_name tabindex=100></td>\n";
983 echo "<td><input type=text size=24 name=port_label tabindex=101></td>";
984 echo "<input type=hidden name=op value=addPort>\n";
985 echo "<input type=hidden name=object_id value='${object_id}'>\n";
986 echo "<input type=hidden name=page value='${pageno}'>\n";
987 echo "<input type=hidden name=tab value='${tabno}'>\n";
988 echo "<td><select name='port_type_id' tabindex=102>\n";
989 $types = getPortTypes();
990 $default_port_type = getConfigVar ('default_port_type');
991 foreach ($types as $typeid => $typename)
993 echo "<option value='${typeid}'";
994 if ($typeid == $default_port_type)
996 echo ">${typename}</option>\n";
998 echo "</select></td>";
999 echo "<td><input type=text name=port_l2address tabindex=103></td>\n";
1000 echo "<td colspan=4><input type='submit' value='Add a new port' tabindex=104></td></tr></form>";
1001 echo "</table><br>\n";
1004 startPortlet ('Add/update multiple ports');
1005 echo "<form action=${root}process.php method=post>";
1006 echo "<input type=hidden name=page value='${pageno}'>\n";
1007 echo "<input type=hidden name=tab value='${tabno}'>\n";
1008 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1009 echo "<input type=hidden name=op value=addMultiPorts>";
1010 echo 'Format: <select name=format>';
1011 echo '<option value=c2900 disabled>Cisco 2900 series: sh int eth</option>';
1012 echo '<option value=c3600eth disabled>Cisco 3600 ethernet: sh arp | inc -</option>';
1013 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1014 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
1015 echo '<option value=fiedge disabled>Foundry FastIron Edge: sh int br</option>';
1016 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
1018 echo 'Default port type: ';
1019 echo "<select name=port_type>\n";
1020 foreach ($types as $typeid => $typename)
1022 echo "<option value='${typeid}'";
1023 if ($typeid == $default_port_type)
1025 echo ">${typename}</option>\n";
1028 echo "<input type=submit value='Parse output'><br>\n";
1029 echo "<textarea name=input cols=100 rows=50></textarea><br>\n";
1034 function renderNetworkForObject ($object_id=0)
1036 global $root, $pageno, $tabno;
1037 if ($object_id <= 0)
1039 showError ('Invalid object_id', __FUNCTION__
);
1042 showMessageOrError();
1043 startPortlet ('Network Addresses');
1044 $addresses = getObjectAddresses ($object_id);
1045 usort($addresses, 'sortAddresses');
1046 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1047 echo "<tr><th> </th><th>Interface name</th><th>IP Address</th><th>Description</th><th>Type</th><th>Misc</th><th> </th></tr>\n";
1048 foreach ($addresses as $addr)
1050 if (strlen($addr['address_name'])>40)
1051 $address_name = substr($addr['address_name'],0,38).'...';
1053 $address_name = $addr['address_name'];
1055 $virtnum = countRefsOfType($addr['references'], 'virtual', 'eq');
1056 $sharednum = countRefsOfType($addr['references'], 'shared', 'eq');
1057 $regnum = countRefsOfType($addr['references'], 'regular', 'eq');
1058 $notvirtnum = countRefsOfType($addr['references'], 'virtual', 'neq');
1060 if ($addr['address_reserved']=='yes')
1062 elseif ($addr['type']!='virtual' && $regnum>0)
1064 elseif ($addr['type']=='regular' && $sharednum>0)
1069 echo "<form action='process.php'>";
1070 echo "<input type=hidden name=page value='${pageno}'>\n";
1071 echo "<input type=hidden name=tab value='${tabno}'>\n";
1072 echo "<input type=hidden name=op value=editAddressFromObject>";
1073 echo "<input type=hidden name=object_id value='$object_id'>";
1074 echo "<input type=hidden name=ip value='${addr['ip']}'>";
1075 echo "<tr class='$class'><td><a href='process.php?op=delAddrFObj&page=${pageno}&tab=${tabno}&ip=${addr['ip']}&object_id=$object_id'>";
1076 printImageHREF ('delete', 'Delete this IPv4 address');
1078 echo "<td><input type='text' name='bond_name' value='${addr['name']}' size=10></td>";
1079 echo "<td><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
1080 echo "<td class='description'>$address_name</td>\n";
1081 echo "<td><select name='bond_type'>";
1082 foreach (array('regular'=>'Regular', 'virtual'=>'Virtual', 'shared'=>'Shared') as $n => $v)
1084 echo "<option value='$n'";
1085 if ($addr['type'] == $n)
1087 echo ">$v</option>";
1090 if ($addr['address_reserved']=='yes')
1091 echo "<b>Reserved</b>; ";
1093 if ($addr['type'] == 'virtual')
1095 if ($notvirtnum > 0)
1098 printRefsOfType($addr['references'], 'virtual', 'neq');
1101 elseif ($addr['type'] == 'shared')
1106 printRefsOfType($addr['references'], 'shared', 'eq');
1112 printRefsOfType($addr['references'], 'virtual', 'eq');
1117 echo " Collisions: ";
1118 printRefsOfType($addr['references'], 'regular', 'eq');
1127 printRefsOfType($addr['references'], 'virtual', 'eq');
1130 if ($notvirtnum > 0)
1132 echo " Collisions: ";
1133 printRefsOfType($addr['references'], 'virtual', 'neq');
1137 echo "</td><td><input type=submit value='OK'></td></form></tr>\n";
1141 echo "<form action='${root}process.php'><tr><td colspan=2><input type='text' size='10' name='name' tabindex=100></td>\n";
1142 echo "<input type=hidden name=page value='${pageno}'>\n";
1143 echo "<input type=hidden name=tab value='${tabno}'>\n";
1144 echo "<input type=hidden name=op value=addAddrFObj>\n";
1145 echo "<input type=hidden name=object_id value='$object_id'>\n";
1147 echo "<td><input type=text name='ip' tabindex=101>\n";
1148 echo "</td><td><select name='type' tabindex=102>";
1149 echo "<option value='regular'>Regular</option>";
1150 echo "<option value='virtual'>Virtual</option>";
1151 echo "<option value='shared'>Shared</option>";
1153 echo "</td><td colspan=3><input type='submit' value='Add a new interface' tabindex=103></td></tr></form>";
1154 echo "</table><br>\n";
1159 function printLog ($log)
1161 foreach ($log as $record)
1162 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1166 The following conditions must be followed:
1167 1. We can mount onto free atoms only. This means: if any record for an atom
1168 already exists in RackSpace, it can't be used for mounting.
1169 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1170 and either delete them before unmounting or refuse to unmount the object.
1173 // We extensively use $_REQUEST in the function.
1174 function renderRackSpaceForObject ($object_id = 0)
1176 if ($object_id <= 0)
1178 showError ('Invalid object_id', __FUNCTION__
);
1181 $is_submit = isset ($_REQUEST['got_atoms']);
1182 $is_update = isset ($_REQUEST['rackmulti'][0]);
1183 $info = getObjectInfo ($object_id);
1186 showError ('getObjectInfo() failed', __FUNCTION__
);
1189 // Always process occupied racks plus racks chosen by user. First get racks with
1190 // already allocated rackspace...
1191 $workingRacksData = getResidentRacksData ($object_id);
1192 if ($workingRacksData === NULL)
1194 print_r ($workingRacksData);
1195 showError ('getResidentRacksData() failed', __FUNCTION__
);
1199 // ...and then add those chosen by user (if any).
1201 foreach ($_REQUEST['rackmulti'] as $cand_id)
1203 if (!isset ($workingRacksData[$cand_id]))
1205 $rackData = getRackData ($cand_id);
1206 if ($rackData == NULL)
1208 showError ('getRackData() failed', __FUNCTION__
);
1211 $workingRacksData[$cand_id] = $rackData;
1215 // Do it only once...
1216 foreach ($workingRacksData as &$rackData)
1217 applyObjectMountMask ($rackData, $object_id);
1218 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1221 // Here we process form submit by trying to save all submitted info to database.
1224 $oldMolecule = getMoleculeForObject ($object_id);
1225 $worldchanged = FALSE;
1227 foreach ($workingRacksData as $rack_id => $rackData)
1229 $logrecord = processGridForm ($rackData, 'F', 'T', $object_id);
1230 $log[] = $logrecord;
1231 if ($logrecord['code'] != 300)
1233 $worldchanged = TRUE;
1234 // Reload our working copy after form processing.
1235 $rackData = getRackData ($rack_id);
1236 if ($rackData == NULL)
1237 $log[] = array ('code' => 500, 'message' => 'Working copy update failed in ', __FUNCTION__
);
1238 applyObjectMountMask ($rackData, $object_id);
1239 $workingRacksData[$rack_id] = $rackData;
1245 $newMolecule = getMoleculeForObject ($object_id);
1246 $oc = count ($oldMolecule);
1247 $nc = count ($newMolecule);
1248 $omid = $oc ?
createMolecule ($oldMolecule) : 'NULL';
1249 $nmid = $nc ?
createMolecule ($newMolecule) : 'NULL';
1250 global $remote_username;
1251 $comment = empty ($_REQUEST['comment']) ?
'NULL' : "'${_REQUEST['comment']}'";
1253 "insert into MountOperation(object_id, old_molecule_id, new_molecule_id, user_name, comment) " .
1254 "values (${object_id}, ${omid}, ${nmid}, '${remote_username}', ${comment})";
1256 $result = $dbxlink->query ($query);
1257 if ($result == NULL)
1258 $log[] = array ('code' => 'error', 'message' => 'SQL query failed during history logging.');
1260 $log[] = array ('code' => 'success', 'message' => 'History logged.');
1265 // This is the time for rendering.
1266 global $root, $pageno, $tabno;
1267 echo "<form id='racks' action='${root}'>";
1268 echo "<input type=hidden name=page value='${pageno}'>\n";
1269 echo "<input type=hidden name=tab value='${tabno}'>\n";
1270 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1271 // Main layout starts.
1272 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1274 // Left portlet with rack list.
1275 echo "<td class=pcleft height='1%'>";
1276 startPortlet ('Racks');
1277 $allRacksData = getRacksForRow();
1278 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1284 // Middle portlet with comment and submit.
1285 echo "<td class=pcleft>";
1286 startPortlet ('Comment');
1287 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1288 echo "<input type=submit value='Save' name=got_atoms>\n";
1294 // Right portlet with rendered racks. If this form submit is not final, we have to
1295 // reflect the former state of the grid in current form.
1296 echo "<td class=pcright rowspan=2 height='1%'>";
1297 startPortlet ('Working copy');
1298 echo '<table border=0 cellspacing=10 align=center><tr>';
1299 foreach ($workingRacksData as $rack_id => $rackData)
1301 // Order is important here: only original allocation is highlighted.
1302 highlightObject ($rackData, $object_id);
1303 markupAtomGrid ($rackData, 'T');
1304 // If we have a form processed, discard user input and show new database
1306 if (!$is_submit and $is_update)
1307 mergeGridFormToRack ($rackData);
1308 echo "<td valign=top>";
1309 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1310 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1311 echo "<tr><th width='10%'> </th><th width='20%'>Front</th>";
1312 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1313 renderAtomGrid ($rackData);
1314 echo "<tr><th width='10%'> </th><th width='20%'>Front</th>";
1315 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1316 echo "</table></center>\n";
1319 echo "</tr></table>";
1324 echo "</tr></table>\n";
1327 function renderMolecule ($mdata, $object_id)
1330 $rackpack = array();
1332 foreach ($mdata as $dummy => $rua)
1334 $rack_id = $rua['rack_id'];
1335 $unit_no = $rua['unit_no'];
1336 $atom = $rua['atom'];
1337 if (!isset ($rackpack[$rack_id]))
1339 $rackData = getRackData ($rack_id);
1340 for ($i = $rackData['height']; $i > 0; $i--)
1341 for ($locidx = 0; $locidx < 3; $locidx++
)
1342 $rackData[$i][$locidx]['state'] = 'F';
1343 $rackpack[$rack_id] = $rackData;
1345 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1346 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1348 // now we have some racks to render
1349 foreach ($rackpack as $dummy => $rackData)
1351 markAllSpans ($rackData);
1352 echo "<table class=molecule cellspacing=0>\n";
1353 echo "<caption>${rackData['name']}</caption>\n";
1354 echo "<tr><th width='10%'> </th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1355 for ($i = $rackData['height']; $i > 0; $i--)
1357 echo "<tr><th>$i</th>";
1358 for ($locidx = 0; $locidx < 3; $locidx++
)
1360 $state = $rackData[$i][$locidx]['state'];
1361 echo "<td class=state_${state}> </td>\n";
1369 function renderUnmountedObjectsPortlet ()
1371 startPortlet ('Unmounted objects');
1372 $objs = getUnmountedObjects();
1375 showError ('getUnmountedObjects() failed', __FUNCTION__
);
1378 global $root, $nextorder;
1380 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1381 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset number</th><th>Barcode</th></tr>';
1382 foreach ($objs as $obj)
1384 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1385 echo "<td>${obj['label']}</td>";
1386 echo "<td>${obj['asset_no']}</td>";
1387 echo "<td>${obj['barcode']}</td></tr>";
1388 $order = $nextorder[$order];
1390 echo "</table><br>\n";
1394 function renderProblematicObjectsPortlet ()
1396 startPortlet ('Problematic objects');
1397 $objs = getProblematicObjects();
1400 showError ('getProblematicObjects() failed', __FUNCTION__
);
1403 global $root, $nextorder;
1405 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1406 echo '<tr><th>Type</th><th>Common name</th></tr>';
1407 foreach ($objs as $obj)
1409 echo "<tr class=row_${order}><td>${obj['objtype_name']}</td>";
1410 echo "<td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></tr>";
1411 $order = $nextorder[$order];
1413 echo "</table><br>\n";
1417 function renderObjectGroupSummary ()
1420 $summary = getObjectGroupInfo();
1421 if ($summary === NULL)
1423 showError ('getObjectGroupInfo() failed', __FUNCTION__
);
1426 echo "<table border=0 class=objectview>\n";
1427 echo "<tr><td class=pcleft width='25%'>";
1429 startPortlet ('Summary');
1430 foreach ($summary as $gi)
1432 echo "<a href='${root}?page=objgroup&group_id=${gi['id']}'><b>${gi['name']}</b></a> <i>(${gi['count']})</i><br>";
1436 echo '</td><td class=pcright>';
1437 renderUnmountedObjectsPortlet();
1438 echo '</td><td class=pcright>';
1439 renderProblematicObjectsPortlet();
1440 echo "</td></tr></table>\n";
1443 function renderObjectGroup ($group_id = 0)
1446 $summary = getObjectGroupInfo();
1447 if ($summary == NULL)
1449 showError ('getObjectGroupInfo() failed', __FUNCTION__
);
1452 $objects = getObjectList ($group_id);
1453 if ($objects === NULL)
1455 showError ('getObjectList() failed', __FUNCTION__
);
1458 echo "<table border=0 class=objectview>\n";
1459 echo "<tr><td class=pcleft width='25%'>";
1461 startPortlet ('All objects');
1462 foreach ($summary as $gi)
1464 echo "<a href='${root}?page=objgroup&group_id=${gi['id']}'><b>${gi['name']}</b></a> <i>(${gi['count']})</i><br>";
1468 echo '</td><td class=pcright>';
1470 startPortlet ('Object group');
1471 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1472 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Rack</th></tr>';
1475 foreach ($objects as $obj)
1477 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1478 echo "<td>${obj['label']}</td>";
1479 echo "<td>${obj['asset_no']}</td>";
1480 echo "<td>${obj['barcode']}</td>";
1481 if ($obj['rack_id'])
1482 echo "<td><a href='${root}?page=rack&rack_id=${obj['rack_id']}'>${obj['Rack_name']}</a></td>";
1484 echo '<td>Unmounted</td>';
1486 $order = $nextorder[$order];
1491 echo "</td></tr></table>";
1494 function renderEmptyPortsSelect ($port_id, $type_id)
1496 $ports = getEmptyPortsOfType($type_id);
1497 usort($ports, 'sortEmptyPorts');
1498 foreach ($ports as $port)
1500 if ($port_id == $port['Port_id'])
1502 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";
1506 function renderObjectAddressesAndNames ()
1508 $addresses = getObjectAddressesAndNames();
1509 usort($addresses, 'sortObjectAddressesAndNames');
1510 foreach ($addresses as $address)
1512 echo "<option value='${address['ip']}' onclick='getElementById(\"ip\").value=\"${address['ip']}\";'>${address['object_name']} ${address['name']} ${address['ip']}</option>\n";
1516 // History viewer for history-enabled simple dictionaries.
1517 function renderHistory ($object_type, $object_id)
1519 switch ($object_type)
1522 $query = "select ctime, user_name, name, deleted, comment from RackRowHistory where id = ${object_id} order by ctime";
1523 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>is deleted?</th><th>rack row comment</th></tr>';
1528 "select ctime, user_name, rh.name, rh.deleted, d.dict_value as name, rh.height, rh.comment " .
1529 "from RackHistory as rh left join Dictionary as d on rh.row_id = d.dict_key " .
1530 "natural join Chapter " .
1531 "where chapter_name = 'RackRow' and rh.id = ${object_id} order by ctime";
1532 $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>';
1537 "select ctime, user_name, name, label, barcode, asset_no, deleted, has_problems, dict_value, comment " .
1538 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key natural join Chapter " .
1539 "where chapter_name = 'RackObjectType' and id=${object_id} order by ctime";
1540 $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>';
1544 showError ("Uknown object type '${object_type}'", __FUNCTION__
);
1548 $result = $dbxlink->query ($query);
1549 if ($result == NULL)
1551 showError ('SQL query failed', __FUNCTION__
);
1554 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1558 while ($row = $result->fetch (PDO
::FETCH_NUM
))
1560 echo "<tr class=row_${order}><td>${row[0]}</td>";
1561 for ($i = 1; $i <= $extra; $i++
)
1562 echo "<td>" . $row[$i] . "</td>";
1564 $order = $nextorder[$order];
1566 echo "</table><br>\n";
1569 function renderRackspaceHistory ()
1571 global $root, $nextorder, $pageno, $tabno;
1573 $history = getRackspaceHistory();
1574 // Show the last operation by default.
1575 if (isset ($_REQUEST['op_id']))
1576 $op_id = $_REQUEST['op_id'];
1577 elseif (isset ($history[0]['mo_id']))
1578 $op_id = $history[0]['mo_id'];
1585 list ($omid, $nmid) = getOperationMolecules ($op_id);
1587 // Main layout starts.
1588 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1590 // Left top portlet with old allocation.
1591 echo "<tr><td class=pcleft>";
1592 startPortlet ('Old allocation');
1595 $oldMolecule = getMolecule ($omid);
1596 renderMolecule ($oldMolecule, $object_id);
1602 echo '</td><td class=pcright>';
1604 // Right top portlet with new allocation
1605 startPortlet ('New allocation');
1608 $newMolecule = getMolecule ($nmid);
1609 renderMolecule ($newMolecule, $object_id);
1615 echo '</td></tr><tr><td colspan=2>';
1617 // Bottom portlet with list
1619 startPortlet ('Rackspace allocation history');
1620 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1621 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";
1622 foreach ($history as $row)
1624 if ($row['mo_id'] == $op_id)
1627 $class = "row_${order}";
1628 echo "<tr class=${class}><td><a href='${root}?page=${pageno}&tab=${tabno}&op_id=${row['mo_id']}'>${row['ctime']}</a></td>";
1629 echo "<td>${row['user_name']}</td>";
1630 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
1632 $order = $nextorder[$order];
1637 echo '</td></tr></table>';
1641 function renderAddressspace ()
1643 global $root, $page;
1644 echo '<table border=0 class=objectview cellspacing=0 cellpadding=0><tr><td class=pcleft>';
1646 startPortlet ('Subnets');
1647 echo "<table class='widetable' border=0 cellpadding=10 cellspacing=0 align='center'>\n";
1648 $addrspaceList = getAddressspaceList();
1649 echo "<tr><th>Subnet</th><th>Name</th><th>Utilization</th></tr>";
1650 foreach ($addrspaceList as $iprange)
1652 $range = getIPRange ($iprange['id']);
1653 $total = ($iprange['ip_bin'] |
$iprange['mask_bin_inv']) - ($iprange['ip_bin'] & $iprange['mask_bin']) +
1;
1654 $used = count ($range['addrlist']);
1655 echo "<tr><td class=tdleft><a href='${root}?page=iprange&id=${iprange['id']}'>${iprange['ip']}/${iprange['mask']}</a></td>";
1656 echo "<td class=tdleft>${iprange['name']}</td><td class=tdleft>";
1657 renderProgressBar ($used/$total);
1658 echo " ${used}/${total}</td></tr>";
1663 echo "</td>\n<td class=pcright>";
1665 startPortlet ('SLB configuration');
1666 echo "<table border=0 width='100%'><tr>";
1667 foreach (array ('vservices', 'rspools', 'rservers', 'lbs') as $pno)
1668 echo "<td><h3><a href='${root}?page=${pno}'>" . $page[$pno]['title'] . "</a></h3></td>";
1669 echo '</tr></table>';
1672 $summary = getSLBSummary();
1673 startPortlet ('SLB tactical overview');
1674 // A single id-keyed array isn't used here to preserve existing
1675 // order of LBs returned by getSLBSummary()
1678 foreach ($summary as $vipdata)
1679 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
1680 if (!in_array ($lb_object_id, $lblist))
1682 $oi = getObjectInfo ($lb_object_id);
1683 $lbdname[$lb_object_id] = $oi['dname'];
1684 $lblist[] = $lb_object_id;
1686 if (!count ($summary))
1687 echo 'none configured';
1690 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
1691 echo "<tr><th>VS ↓ LB →</th>";
1692 foreach ($lblist as $lb_object_id)
1693 echo "<th><a href='${root}?page=object&tab=default&object_id=${lb_object_id}'>" . $lbdname[$lb_object_id] . "</a></th>";
1695 foreach ($summary as $vsid => $vsdata)
1697 echo "<tr><td class=tdleft><a href='$root?page=vservice&tab=default&id=${vsid}'>";
1698 echo buildVServiceName ($vsdata);
1700 if (!empty ($vsdata['name']))
1701 echo " (${vsdata['name']})";
1703 foreach ($lblist as $lb_object_id)
1705 echo '<td class=tdleft>';
1706 if (!isset ($vsdata['lblist'][$lb_object_id]))
1710 echo $vsdata['lblist'][$lb_object_id]['size'];
1711 echo " (<a href='${root}?page=rspool&id=";
1712 echo $vsdata['lblist'][$lb_object_id]['id'] . "'>";
1713 echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
1723 echo '</td></tr></table>';
1726 function renderAddNewRange ()
1728 global $root, $pageno, $tabno;
1729 showMessageOrError();
1731 echo "<center><h2>Add New</h2></center>\n";
1732 echo "<table class='widetable' border=0 cellpadding=10 align='center'>\n";
1733 echo "<tr><th>Address range</th><th>Name</th><th>C>*</th><th> </th></tr>\n";
1734 echo "<form name='add_new_range' action='process.php'>\n";
1735 echo "<input type=hidden name=op value=addRange>\n";
1736 echo "<input type=hidden name=page value='${pageno}'>\n";
1737 echo "<input type=hidden name=tab value='${tabno}'>\n";
1738 echo "<tr><td class='tdcenter'><input type=text name='range' size=18 class='live-validate' tabindex=1></td>\n";
1739 echo "<td class='tdcenter'><input type=text name='name' size='20' tabindex=2></td>\n";
1740 echo "<td class='tdcenter'><input type=checkbox name='is_bcast' tabindex=3 checked></td>\n";
1741 echo "<td class='tdcenter'><input type=submit value='Add a new range' tabindex=4></td></tr>\n";
1742 echo "</form></table><br><br>\n";
1744 echo "<center><h2>Manage Existing</h2></center>\n";
1745 echo "<table class='widetable' border=0 cellpadding=10 align='center'>\n";
1746 $addrspaceList = getAddressspaceList();
1747 echo "<tr><th> </th><th>Address range</th><th>Name</th><th>Utilization</th></tr>";
1748 foreach ($addrspaceList as $iprange)
1750 $range = getIPRange($iprange['id']);
1751 $usedips = count ($range['addrlist']);
1752 $totalips = ($iprange['ip_bin'] |
$iprange['mask_bin_inv']) - ($iprange['ip_bin'] & $iprange['mask_bin']) +
1;
1756 echo "<td><a href='process.php?op=delRange&page=${pageno}&tab=${tabno}&id=${iprange['id']}'>";
1757 printImageHREF ('delete', 'Delete this IP range');
1761 echo "<td> </td>";
1762 echo "<td><a href='${root}?page=iprange&id=${iprange['id']}'>${iprange['ip']}/${iprange['mask']}</a></td><td>${iprange['name']}</td><td class=tdleft>";
1763 renderProgressBar ($usedips / $totalips);
1764 echo " ${usedips}/${totalips}";
1770 function renderIPRange ()
1773 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
1774 $id = $_REQUEST['id'];
1775 if (isset($_REQUEST['pg']))
1776 $page = $_REQUEST['pg'];
1780 $range = getIPRange($id);
1781 echo "<center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></center>\n";
1783 $startip = $range['ip_bin'] & $range['mask_bin'];
1784 $endip = $range['ip_bin'] |
$range['mask_bin_inv'];
1785 $realstartip = $startip;
1786 $realendip = $endip;
1788 if($endip - $startip > $maxperpage)
1790 $numpages = ($endip - $startip)/$maxperpage;
1791 $startip = $startip +
$page * $maxperpage;
1792 $endip = $startip +
$maxperpage-1;
1796 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
1797 for ($i=0; $i<$numpages; $i++
)
1802 echo "<a href='${root}?page=iprange&id=$id&pg=$i'>$i</a> ";
1806 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center'>\n";
1807 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
1810 for($ip = $startip; $ip<=$endip; $ip++
)
1812 if (isset ($range['addrlist'][$ip]))
1814 $numshared = countRefsOfType($range['addrlist'][$ip]['references'], 'shared', 'eq');
1815 $numreg = countRefsOfType($range['addrlist'][$ip]['references'], 'regular', 'eq');
1816 $numvirt = countRefsOfType($range['addrlist'][$ip]['references'], 'virtual', 'eq');
1818 $addr = $range['addrlist'][$ip];
1819 if ( ($numshared > 0 && $numreg > 0) ||
$numreg > 1 )
1820 echo "<tr class='trwarning'>";
1821 elseif ( $addr['reserved'] == 'yes' and $numshared+
$numreg+
$numvirt > 0)
1822 echo "<tr class='trwarning'>";
1823 elseif ( $addr['reserved'] == 'yes')
1824 echo "<tr class='trbusy'>";
1825 elseif ( $numshared > 0 ||
$numreg > 0)
1826 echo "<tr class='trbusy'>";
1830 echo "<td><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td><td>${addr['name']}</td><td>";
1831 if ( $addr['reserved'] == 'yes')
1832 echo "<b>Reserved;</b> ";
1833 foreach ($range['addrlist'][$ip]['references'] as $ref)
1835 echo "<a href='${root}?page=object&object_id=${ref['object_id']}'>";
1836 echo $ref['name'] . (empty ($ref['name']) ?
'' : '@');
1837 echo "${ref['object_name']}</a>; ";
1839 echo "</td></tr>\n";
1843 echo "<tr><td><a href='${root}?page=ipaddress&ip=".long2ip($ip)."'>".long2ip($ip)."</a></td><td> </td><td> </td></tr>\n";
1851 function renderIPRangeProperties ()
1853 global $pageno, $tabno;
1854 $id = $_REQUEST['id'];
1855 showMessageOrError();
1856 $range = getIPRange($id);
1857 echo "<center><h1>${range['ip']}/${range['mask']}</h1></center>\n";
1858 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
1859 echo "<form action='process.php'><input type=hidden name=op value=editRange>";
1860 echo "<input type=hidden name=page value='${pageno}'>\n";
1861 echo "<input type=hidden name=tab value='${tabno}'>\n";
1862 echo "<input type=hidden name=id value='${id}'>";
1863 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>";
1868 function renderIPAddress ()
1871 $ip = $_REQUEST['ip'];
1872 $address = getIPAddress($ip);
1873 echo "<center><h1>$ip</h1>";
1874 if ($address['exists'] == 1)
1875 echo "<h2>${address['name']}</h2>";
1878 // echo "<table width='100%' cesspadding=5 cellspacing=0 border=0 align='center'>";
1879 // echo "<tr valign='top'><td>";
1881 startPortlet ('Address assignment');
1882 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
1883 echo "<tr><th>Object name</th><th>Interface name</th><th>Interface type</th></tr>\n";
1885 $numshared = countRefsOfType($address['bonds'], 'shared', 'eq');
1886 $numreg = countRefsOfType($address['bonds'], 'regular', 'eq');
1887 $numvirt = countRefsOfType($address['bonds'], 'virtual', 'eq');
1890 if ( ($numshared > 0 && $numreg > 0) ||
$numreg > 1 )
1892 elseif ( $address['reserved'] == 'yes' and $numshared+
$numreg+
$numvirt > 0)
1899 if ($address['reserved'] == 'yes')
1900 echo "<tr class='$class'><td colspan='3'><b>RESERVED</b></td></tr>";
1901 foreach ($address['bonds'] as $bond)
1903 echo "<tr class='$class'><td><a href='${root}?page=object&object_id=${bond['object_id']}'>${bond['object_name']}</td><td>${bond['name']}</td><td><b>";
1904 switch ($bond['type'])
1916 echo "</b></td></tr>\n";
1918 echo "</table><br><br>";
1921 // echo "</td><td>";
1922 // echo "</td></tr></table>";
1925 function renderIPAddressProperties ()
1927 global $pageno, $tabno;
1928 $ip = $_REQUEST['ip'];
1929 showMessageOrError();
1930 $address = getIPAddress($ip);
1931 echo "<center><h1>$ip</h1></center>\n";
1932 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
1933 echo "<form action='process.php'><input type=hidden name=op value=editAddress>";
1934 echo "<input type=hidden name=page value='${pageno}'>\n";
1935 echo "<input type=hidden name=tab value='${tabno}'>\n";
1936 echo "<input type=hidden name=ip value='${ip}'>";
1937 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='".($address['exists']==1?
$address['name']:'')."'></tr>";
1938 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ".($address['exists']==1?
(($address['reserved']=='yes')?
'checked':''):'')."></tr>";
1939 echo "<tr><td colspan=2 class='tdcenter'><input type=submit value='Update address'></td></form></tr>";
1944 function renderIPAddressAssignment ()
1946 global $pageno, $tabno, $root;
1947 $ip = $_REQUEST['ip'];
1948 $address = getIPAddress($ip);
1950 showMessageOrError();
1951 echo "<center><h1>$ip</h1></center>\n";
1954 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
1955 echo "<tr><th> </th><th>Object name</th><th>Interface name</th><th>Interface type</th><th> </th></tr>\n";
1957 $numshared = countRefsOfType($address['bonds'], 'shared', 'eq');
1958 $numreg = countRefsOfType($address['bonds'], 'regular', 'eq');
1959 $numvirt = countRefsOfType($address['bonds'], 'virtual', 'eq');
1962 if ( ($numshared > 0 && $numreg > 0) ||
$numreg > 1 )
1964 elseif ( $address['reserved'] == 'yes' and $numshared+
$numreg+
$numvirt > 0)
1971 if ($address['reserved'] == 'yes')
1972 echo "<tr class='$class'><td colspan='5'><b>RESERVED</b></td></tr>";
1973 foreach ($address['bonds'] as $bond)
1975 echo "<tr class='$class'><form action='process.php'>";
1976 echo "<input type=hidden name=op value='editBondForAddress'>";
1977 echo "<input type=hidden name=page value='${pageno}'>";
1978 echo "<input type=hidden name=tab value='${tabno}'>";
1979 echo "<input type=hidden name=ip value='$ip'>";
1980 echo "<input type=hidden name=object_id value='${bond['object_id']}'>";
1981 echo "<td><a href='process.php?op=delIpAssignment&page=${pageno}&tab=${tabno}&ip=$ip&object_id=${bond['object_id']}'>";
1982 printImageHREF ('delete', 'Unallocate address');
1984 echo "<td><a href='${root}?page=object&object_id=${bond['object_id']}'>${bond['object_name']}</td>";
1985 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td>";
1986 echo "<td><select name='bond_type'>";
1987 switch ($bond['type'])
1990 echo "<option value='regular'>Regular</option>";
1991 echo "<option value='virtual' selected>Virtual</option>";
1992 echo "<option value='shared'>Shared</option>";
1995 echo "<option value='regular'>Regular</option>";
1996 echo "<option value='virtual'>Virtual</option>";
1997 echo "<option value='shared' selected>Shared</option>";
2000 echo "<option value='regular' selected>Regular</option>";
2001 echo "<option value='virtual'>Virtual</option>";
2002 echo "<option value='shared'>Shared</option>";
2005 echo "</select></td><td><input type='submit' value='OK'></td></form></tr>\n";
2007 echo "<form action='process.php'><input type='hidden' name='op' value='bindObjectToIp'>";
2008 echo "<input type=hidden name=page value='${pageno}'>\n";
2009 echo "<input type=hidden name=tab value='${tabno}'>\n";
2010 echo "<input type='hidden' name='ip' value='$ip'>";
2011 echo "<td colspan=2><select name='object_id'>";
2013 foreach (explode (',', getConfigVar ('IPV4_PERFORMERS')) as $type)
2014 foreach (getObjectList ($type) as $object)
2015 echo "<option value='${object['id']}'>${object['dname']}</option>";
2017 echo "</select></td><td><input type='text' name='bond_name' value='' size=10></td>";
2018 echo "<td><select name='bond_type'><option value='regular'>Regular</option><option value='virtual'>Virtual</option><option value='shared'>Shared</option></select></td>";
2019 echo "<td><input type='submit' value='Assign address'></td></form></tr>";
2020 echo "</table><br><br>";
2024 function renderIPAddressPortForwarding ($object_id=0)
2026 global $pageno, $tabno, $root;
2028 $info = getObjectInfo ($object_id);
2029 $forwards = getObjectForwards ($object_id);
2030 $addresses = getObjectAddresses ($object_id);
2031 showMessageOrError();
2032 echo "<center><h2>locally performed NAT</h2></center>";
2034 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
2035 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th></tr>\n";
2037 foreach ($forwards['out'] as $pf)
2041 foreach ($addresses as $addr)
2042 if ($addr['ip'] == $pf['localip'])
2045 $name = $addr['name'];
2049 echo "<tr class='$class'>";
2050 echo "<td><a href='process.php?op=delPortForwarding&localip=${pf['localip']}&localport=${pf['localport']}&remoteip=${pf['remoteip']}&remoteport=${pf['remoteport']}&proto=${pf['proto_bin']}&object_id=$object_id&page=${pageno}&tab=${tabno}'><img src='${root}/pix/delete_s.gif' title='Delete port forwarding' border=0 width=16 height=16></a></td>";
2051 echo "<td>${pf['proto']}/${name}: <a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}";
2052 if (!empty ($pf['local_addr_name']))
2053 echo ' (' . $pf['local_addr_name'] . ')';
2055 echo "<td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2057 $address=getIPAddress($pf['remoteip']);
2059 echo "<td class='description'>";
2060 if (count ($address['bonds']))
2061 foreach($address['bonds'] as $bond)
2062 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
2063 elseif (!empty ($pf['remote_addr_name']))
2064 echo '(' . $pf['remote_addr_name'] . ')';
2065 echo "</td><form action='process.php'><input type='hidden' name='op' value='updPortForwarding'><input type=hidden name=page value='${pageno}'><input type=hidden name=tab value='${tabno}'><input type='hidden' name='object_id' value='$object_id'><input type='hidden' name='localip' value='${pf['localip']}'><input type='hidden' name='localport' value='${pf['localport']}'><input type='hidden' name='remoteip' value='${pf['remoteip']}'><input type='hidden' name='remoteport' value='${pf['remoteport']}'><input type='hidden' name='proto' value='${pf['proto_bin']}'><td class='description'><input type='text' name='description' value='${pf['description']}'> <input type='submit' value='OK'></td></form>";
2068 echo "<form action='process.php'><input type='hidden' name='op' value='forwardPorts'>";
2069 echo "<input type='hidden' name='object_id' value='$object_id'>";
2070 echo "<input type=hidden name=page value='${pageno}'>\n";
2071 echo "<input type=hidden name=tab value='${tabno}'>\n";
2072 echo "<tr align='center'><td colspan=2>";
2073 printSelect (readChapter ('Protocols'), 'proto');
2074 echo "<select name='localip' tabindex=1>";
2076 foreach ($addresses as $addr)
2077 echo "<option value='${addr['ip']}'>" . (empty ($addr['name']) ?
'' : "${addr['name']}: ") .
2078 "${addr['ip']}" . (empty ($addr['address_name']) ?
'' : " (${addr['address_name']})") . "</option>";
2080 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2081 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2082 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\");'><img src='${root}/pix/find.png' title='Find object' border=0 height=16 width=16></a>";
2083 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2084 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5> <input type='submit' value='Create Forwarding' tabindex=6></td></tr>";
2087 echo "</table><br><br>";
2090 echo "<center><h2>arriving NAT connections</h2></center>";
2091 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
2092 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2094 foreach ($forwards['in'] as $pf)
2098 echo "<td><a href='process.php?op=delPortForwarding&localip=${pf['localip']}&localport=${pf['localport']}&remoteip=${pf['remoteip']}&remoteport=${pf['remoteport']}&proto=${pf['proto_bin']}&object_id=${pf['object_id']}&page=${pageno}&tab=${tabno}'><img src='${root}/pix/delete_s.gif' title='Delete port forwarding' border=0 width=16 height=16></a></td>";
2099 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
2100 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
2101 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2102 echo "<td class='description'>${pf['description']}</td></tr>";
2105 // echo "<form action='process.php'><input type='hidden' name='op' value='forwardPorts'>";
2106 // echo "<input type='hidden' name='object_id' value='$object_id'>";
2107 // echo "<input type=hidden name=page value='${pageno}'>\n";
2108 // echo "<input type=hidden name=tab value='${tabno}'>\n";
2109 // echo "<tr align='center'><td colspan=2><select name='proto'><option value='1'>TCP</option><option value='2'>UDP</option><input type='text' name='localip' size='10'>:<input type='text' name='localport' size='4'></td><td><select name='localip'>";
2110 // foreach ($addresses as $addr)
2111 // echo "<option value='${addr['ip']}'>${addr['ip']}</option>";
2113 // echo "</select>:<input type='text' name='remoteport' size='4'></td><td><input type='text' name='description' size='20'></td><td><input type='submit' value='Create Forwarding'></td></tr>";
2115 echo "</table><br><br>";
2121 function renderAddMultipleObjectsForm ()
2123 global $pageno, $tabno, $nextorder;
2126 $global_type_id = 0;
2128 $asset_no = array();
2129 $keepvalues = FALSE;
2131 // Look for current submit.
2132 if (isset ($_REQUEST['got_fast_data']))
2135 $max = getConfigVar ('MASSCOUNT');
2136 for ($i = 0; $i < $max; $i++
)
2138 if (!isset ($_REQUEST["${i}_object_type_id"]))
2140 $log[] = array ('code' => 'error', 'message' => "Submitted form is invalid at line " . $i +
1);
2143 assertUIntArg ("${i}_object_type_id", TRUE);
2144 assertStringArg ("${i}_object_name", TRUE);
2145 assertStringArg ("${i}_object_label", TRUE);
2146 assertStringArg ("${i}_object_asset_no", TRUE);
2147 assertStringArg ("${i}_object_barcode", TRUE);
2148 $type_id[$i] = $_REQUEST["${i}_object_type_id"];
2149 // Save user input for possible rendering.
2150 $name[$i] = $_REQUEST["${i}_object_name"];
2151 $label[$i] = $_REQUEST["${i}_object_label"];
2152 $asset_no[$i] = $_REQUEST["${i}_object_asset_no"];
2153 $barcode[$i] = $_REQUEST["${i}_object_barcode"];
2155 // It's better to skip silently than printing a notice.
2156 if ($type_id[$i] == 0)
2158 if (commitAddObject ($name[$i], $label[$i], $barcode[$i], $type_id[$i], $asset_no[$i]) === TRUE)
2159 $log[] = array ('code' => 'success', 'message' => "Added new object '${name[$i]}'");
2161 $log[] = array ('code' => 'error', 'message' => __FUNCTION__
. ': commitAddObject() failed');
2164 elseif (isset ($_REQUEST['got_very_fast_data']))
2167 assertUIntArg ('global_type_id', TRUE);
2168 assertStringArg ('namelist', TRUE);
2169 $global_type_id = $_REQUEST['global_type_id'];
2170 if ($global_type_id == 0)
2172 if (!empty ($_REQUEST['namelist']))
2173 $log[] = array ('code' => 'error', 'message' => 'Object type is not selected, check the form below');
2175 $log[] = array ('code' => 'error', 'message' => 'Empty form has been ignored. Cheers.');
2179 // The name extractor below was stolen from ophandlers.php:addMultiPorts()
2180 $names1 = explode ('\n', $_REQUEST['namelist']);
2182 foreach ($names1 as $line)
2184 $parts = explode ('\r', $line);
2186 if (empty ($parts[0]))
2189 $names2[] = rtrim ($parts[0]);
2191 foreach ($names2 as $cname)
2192 if (commitAddObject ($cname, '', '', $global_type_id, '') === TRUE)
2193 $log[] = array ('code' => 'success', 'message' => "Added new object '${cname}'");
2195 $log[] = array ('code' => 'error', 'message' => "Could not add '${cname}'");
2200 // Render a form for the next.
2201 $typelist = getObjectTypeList();
2202 $typelist[0] = 'select type...';
2204 startPortlet ('Fast way');
2206 echo "<input type=hidden name=page value=${pageno}>";
2207 echo "<input type=hidden name=tab value=${tabno}>";
2208 echo '<table border=0 align=center>';
2209 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th></tr>\n";
2210 // If a user forgot to select object type on input, we keep his
2211 // previous input in the form.
2212 $max = getConfigVar ('MASSCOUNT');
2213 for ($i = 0; $i < $max; $i++
)
2216 printSelect ($typelist, "${i}_object_type_id", 0);
2218 echo "<td><input type=text size=30 name=${i}_object_name";
2219 if ($keepvalues and $type_id[$i] == 0)
2220 echo " value='${name[$i]}'";
2222 echo "<td><input type=text size=30 name=${i}_object_label";
2223 if ($keepvalues and $type_id[$i] == 0)
2224 echo " value='${label[$i]}'";
2226 echo "<td><input type=text size=20 name=${i}_object_asset_no";
2227 if ($keepvalues and $type_id[$i] == 0)
2228 echo " value='${asset_no[$i]}'";
2230 echo "<td><input type=text size=10 name=${i}_object_barcode";
2231 if ($keepvalues and $type_id[$i] == 0)
2232 echo " value='${barcode[$i]}'";
2236 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Create'></td></tr>\n";
2237 echo "</form></table>\n";
2240 startPortlet ('Very fast way');
2242 echo "<input type=hidden name=page value=${pageno}>";
2243 echo "<input type=hidden name=tab value=${tabno}>";
2244 echo 'For each line shown below create an object of type ';
2245 printSelect ($typelist, "global_type_id", 0);
2246 echo " <input type=submit name=got_very_fast_data value='Go!'><br>\n";
2247 echo "<textarea name=namelist cols=40 rows=25>\n";
2248 if ($keepvalues and $global_type_id == 0)
2249 echo $_REQUEST['namelist'];
2250 echo "</textarea></form>\n";
2254 function printGreeting ()
2256 global $remote_username, $accounts, $root;
2257 $account = $accounts[$remote_username];
2258 echo "Hello, ${account['user_realname']}. This is RackTables " . CODE_VERSION
. ". Click <a href='${root}?logout'>here</a> to logout.";
2261 function renderSearchResults ()
2263 global $remote_username, $root;
2264 $terms = trim ($_REQUEST['q']);
2267 showError ('Search string cannot be empty.', __FUNCTION__
);
2270 if (!authorized ($remote_username, 'object', 'default'))
2272 showError ('You are not authorized for viewing information about objects.', __FUNCTION__
);
2275 // If we search for L2 address, we can either find one or find none.
2278 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
2279 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
2280 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)
2282 // Search for L2 address.
2284 $result = searchByl2address ($terms);
2285 if ($result !== NULL)
2287 echo "<script language='Javascript'>document.location='${root}?page=object";
2288 echo "&hl_port_id=${result['port_id']}";
2289 echo "&object_id=${result['object_id']}';//</script>";
2292 echo "L2 address '${terms}' not found!";
2294 elseif (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))
2295 // STP bridge ID: bridge priotity + port MAC address. Cut off first 4 chars and look for MAC address.
2297 $terms = substr ($terms, 4);
2298 $result = searchByl2address ($terms);
2299 if ($result !== NULL)
2301 echo "<script language='Javascript'>document.location='${root}?page=object";
2302 echo "&hl_port_id=${result['port_id']}";
2303 echo "&object_id=${result['object_id']}';//</script>";
2306 echo "L2 address '${terms}' not found!";
2308 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))
2309 // Search for IP address.
2311 $result = getRangeByIp ($terms);
2312 if ($result !== NULL)
2314 echo "<script language='Javascript'>document.location='${root}?page=ipaddress";
2315 echo "&ip=${terms}";
2316 echo "';//</script>";
2319 echo "IP address '${terms}' not found!";
2323 // Search for objects.
2325 $objects = getSearchResults ($terms);
2326 if (count ($objects) == 1)
2328 $obj = current ($objects);
2329 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${obj['id']}';//</script>";
2331 elseif (count ($objects) > 1)
2333 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2334 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>barcode</th></tr>';
2337 foreach ($objects as $obj)
2339 echo "<tr class=row_${order}><td><a href=\"${root}?page=object&object_id=${obj['id']}\">${obj['dname']}</a></td>";
2340 echo "<td>${obj['label']}</td>";
2341 echo "<td>${obj['asset_no']}</td>";
2342 echo "<td>${obj['barcode']}</td></tr>";
2343 $order = $nextorder[$order];
2348 echo "Object '${terms}' not found!";
2352 // This function prints a table of checkboxes to aid the user in toggling mount atoms
2353 // from one state to another. The first argument is rack data as
2354 // produced by getRackData(), the second is the value used for the 'unckecked' state
2355 // and the third is the value used for 'checked' state.
2357 // for mounting an object: printAtomGrid ($data, 'F', 'T')
2358 // for changing rack design: printAtomGrid ($data, 'A', 'F')
2359 // for adding rack problem: printAtomGrid ($data, 'F', 'U')
2360 // for adding object problem: printAtomGrid ($data, 'T', 'W')
2362 function renderAtomGrid ($data)
2364 $rack_id = $data['id'];
2365 for ($unit_no = $data['height']; $unit_no > 0; $unit_no--)
2367 echo "<tr><th>${unit_no}</th>";
2368 for ($locidx = 0; $locidx < 3; $locidx++
)
2370 $state = $data[$unit_no][$locidx]['state'];
2371 echo "<td class=state_${state}";
2372 if (isset ($data[$unit_no][$locidx]['hl']))
2373 echo $data[$unit_no][$locidx]['hl'];
2375 if (!($data[$unit_no][$locidx]['enabled'] === TRUE))
2376 echo '<input type=checkbox disabled>';
2378 echo "<input type=checkbox" . $data[$unit_no][$locidx]['checked'] . " name=atom_${rack_id}_${unit_no}_${locidx}>";
2385 function renderPermissions ()
2387 startPortlet ('User permissions');
2388 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2389 echo "<tr><th>Username</th><th>Page</th><th>Tab</th><th>Access</th></tr>";
2390 global $perms, $nextorder;
2392 foreach ($perms as $username => $pages)
2393 foreach ($pages as $page => $tabs)
2394 foreach ($tabs as $tab => $access)
2396 echo "<tr class=row_${order}><td class=tdleft>$username</td><td>$page</td><td>$tab</td><td>$access</td></tr>\n";
2397 $order = $nextorder[$order];
2403 function renderAccounts ()
2405 global $nextorder, $accounts;
2406 startPortlet ('User accounts');
2407 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2408 echo "<tr><th class=tdleft>Username</th><th class=tdleft>Real name</th></tr>";
2410 foreach ($accounts as $user)
2412 echo "<tr class=row_${order}><td class=tdleft>${user['user_name']}</td><td class=tdleft>${user['user_realname']}</td></li>";
2413 $order = $nextorder[$order];
2419 function renderAccountsEditForm ()
2421 global $root, $pageno, $tabno, $accounts;
2422 startPortlet ('User accounts');
2423 showMessageOrError();
2424 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2425 echo "<tr><th>op</th><th>Username</th><th>Real name</th><th>Password</th><th> </th></tr>\n";
2426 foreach ($accounts as $account)
2428 echo "<form action='${root}process.php'>";
2429 echo "<input type=hidden name=op value=updateAccount>";
2430 echo "<input type=hidden name=page value='${pageno}'>\n";
2431 echo "<input type=hidden name=tab value='${tabno}'>\n";
2432 echo "<input type=hidden name=id value='${account['user_id']}'><tr>";
2434 if ($account['user_enabled'] == 'yes' && $account['user_id'] != 1)
2436 echo "<a href='${root}process.php?op=disableAccount&page=${pageno}&tab=${tabno}&id=${account['user_id']}'>";
2437 printImageHREF ('blockuser', 'disable account');
2440 if ($account['user_enabled'] == 'no' && $account['user_id'] != 1)
2442 echo "<a href='${root}process.php?op=enableAccount&page=${pageno}&tab=${tabno}&id=${account['user_id']}'>";
2443 printImageHREF ('unblockuser', 'enable account');
2446 // Otherwise skip icon.
2448 echo "<td><input type=text name=username value='${account['user_name']}' size=16></td>";
2449 echo "<td><input type=text name=realname value='${account['user_realname']}' size=24></td>";
2450 echo "<td><input type=password name=password value='${account['user_password_hash']}' size=64></td>";
2451 echo "<td><input type='submit' value='OK'></td>";
2452 echo "</form></tr>\n";
2454 echo "<form action='${root}process.php' method=post><tr>";
2455 echo "<input type=hidden name=op value=createAccount>\n";
2456 echo "<input type=hidden name=page value='${pageno}'>\n";
2457 echo "<input type=hidden name=tab value='${tabno}'>\n";
2458 echo "<td colspan=2><input type=text size=16 name=username tabindex=100></td>\n";
2459 echo "<td><input type=text size=24 name=realname tabindex=101></td>";
2460 echo "<td><input type=password size=64 name=password tabindex=102></td>";
2461 echo "<td colspan=4><input type=submit value='Create account' tabindex=103></td></tr></form>";
2462 echo "</table><br>\n";
2466 function printChildrenAsOptions ($root, $depth = 0)
2468 echo "<option value=${root['title']}>";
2471 for ($i = 0; $i < $depth; $i++
)
2473 echo $root['title'];
2475 foreach ($root['kids'] as $kid)
2476 printChildrenAsOptions ($kid, $depth +
1);
2479 // 1. Find all parentless pages.
2480 // 2. For each of them recursively find all children.
2481 // 3. Output the tree with recursion tree display.
2482 function printPagesTree ()
2486 foreach ($page as $ctitle => $cpage)
2487 if (!isset ($cpage['parent']))
2489 $croot['title'] = $ctitle;
2490 $croot['kids'] = getAllChildPages ($ctitle);
2491 printChildrenAsOptions ($croot);
2496 function renderPermissionsEditForm ()
2498 global $root, $pageno, $tabno, $perms, $accounts;
2499 startPortlet ('User permissions');
2500 showMessageOrError();
2501 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
2502 echo "<tr><th> </th><th>Username</th><th>Page</th><th>Tab</th><th>Access</th></tr>\n";
2503 foreach ($perms as $username => $pages)
2504 foreach ($pages as $access_page => $tabs)
2505 foreach ($tabs as $access_tab => $access)
2508 if ($username != '%')
2509 $userid = $accounts[$username]['user_id'];
2512 echo "<a href='${root}process.php?op=revoke&page=${pageno}&tab=${tabno}&access_userid=${userid}&access_page=${access_page}&access_tab=${access_tab}'>";
2513 printImageHREF ('revoke', 'Revoke permission');
2515 echo "<td>${username}</td>";
2516 echo "<td>${access_page}</td>";
2517 echo "<td>${access_tab}</td>";
2518 echo "<td>${access}</td>";
2521 echo "<form action='${root}process.php' method=post><tr>";
2522 echo "<input type=hidden name=op value=grant>\n";
2523 echo "<input type=hidden name=page value='${pageno}'>\n";
2524 echo "<input type=hidden name=tab value='${tabno}'>\n";
2525 // FIXME: border=0 doesn't work here for unknown reason
2527 printImageHREF ('grant', '', TRUE, 103);
2529 echo "<td><select name=access_userid>";
2530 echo "<option value=0>ANY</option>";
2531 foreach ($accounts as $account)
2532 echo "<option value=${account['user_id']}>${account['user_name']}</option>";
2533 echo "</select></td>\n";
2534 echo "<td><select name=access_page>";
2535 echo "<option value='%'>ANY</option>";
2537 echo "</select></td>";
2538 echo "<td><input type=text size=16 name=access_tab tabindex=102 value=default></td>";
2539 echo "<td><input type=radio name=access_value value=no checked>no <input type=radio name=access_value value=yes>yes</td>";
2540 echo "</tr></form>";
2541 echo "</table><br>\n";
2545 function renderPortMap ($editable = FALSE)
2547 global $nextorder, $root, $pageno, $tabno;
2548 showMessageOrError();
2549 startPortlet ("Port compatibility map");
2550 $ptlist = getPortTypes();
2551 $pclist = getPortCompat();
2552 $pctable = buildPortCompatMatrixFromList ($ptlist, $pclist);
2555 echo "<form method=post action='${root}process.php'>";
2556 echo "<input type=hidden name=page value='${pageno}'>";
2557 echo "<input type=hidden name=tab value='${tabno}'>";
2558 echo "<input type=hidden name=op value=save>";
2560 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2561 echo "<tr><th class=vert_th> </th>";
2562 foreach ($ptlist as $name2)
2563 echo "<th>to ${name2}</th>";
2565 // Make a copy to have an independent array pointer.
2568 foreach ($ptlistY as $type1 => $name1)
2570 echo "<tr class=row_${order}><th class=vert_th style='border-bottom: 0px;'>from $name1</th>";
2571 foreach ($ptlist as $type2 => $name2)
2573 echo '<td><input type=checkbox' . ($editable ?
" name=atom_${type1}_${type2}" : ' disabled');
2574 echo ($pctable[$type1][$type2] ?
' checked' : '') . '></td>';
2577 $order = $nextorder[$order];
2579 echo '</table><br>';
2582 echo "<input type=submit value='Save changes'>";
2588 function renderConfigMainpage ()
2590 global $pageno, $root;
2591 $children = getDirectChildPages ($pageno);
2593 // FIXME: assume all config kids to have static titles at the moment,
2594 // but use some proper abstract function later.
2595 foreach ($children as $cpageno => $child)
2596 echo "<li><a href='${root}?page=${cpageno}'>" . $child['title'] . "</li>\n";
2601 function renderRackPage ($rack_id)
2605 showError ('Invalid rack_id', __FUNCTION__
);
2608 if (($rackData = getRackData ($rack_id)) == NULL)
2610 showError ('getRackData() failed', __FUNCTION__
);
2613 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
2615 // Left column with information.
2616 echo "<td class=pcleft>";
2617 startPortlet ('Rack information');
2618 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2619 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
2620 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
2621 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
2622 echo "<tr><th width='50%' class=tdright>Utilization:</th><td class=tdleft>";
2623 renderProgressBar (getRSUforRack ($rackData));
2624 echo "</td></tr>\n";
2625 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
2626 echo getObjectCount ($rackData);
2627 echo "</td></tr>\n";
2628 if (!empty ($rackData['comment']))
2629 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
2634 // Right column with rendered rack.
2636 startPortlet ('Rack diagram');
2637 renderRack ($rack_id);
2641 echo '</tr></table>';
2644 function renderDictionary ()
2648 echo "<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2649 foreach ($dict as $chapter_no => $chapter)
2652 echo "<tr><th>Chapter</th><th>refs</th><th>Word</th></tr>\n";
2653 $wc = count ($chapter['word']);
2654 echo "<tr class=row_${order}><td class=tdleft" . ($wc ?
" rowspan = ${wc}" : '');
2655 echo "><div title='number=${chapter_no}'>${chapter['name']} (${wc} records)</div></td>";
2657 echo "<td colspan=2>none</td>";
2661 foreach ($chapter['word'] as $key => $value)
2664 echo "<tr class=row_${order}>";
2666 $chap_start = FALSE;
2667 echo '<td>' . ($chapter['refcnt'][$key] ?
$chapter['refcnt'][$key] : ' ') . '</td>';
2668 echo "<td><div title='key=${key}'>${value}</div></td></tr>\n";
2669 $order = $nextorder[$order];
2676 function renderDictionaryEditor ()
2678 global $root, $pageno, $tabno, $nextorder;
2680 showMessageOrError();
2681 echo "<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2682 foreach ($dict as $chapter_no => $chapter)
2685 echo "<tr><th>Chapter</th><th>refs</th><th>Word</th><th> </th></tr>\n";
2686 $wc = count ($chapter['word']);
2687 // One extra span for the new record per each chapter block.
2688 echo "<tr class=row_${order}><td class=tdleft" . ($wc ?
' rowspan = ' . ($wc +
1) : '');
2689 echo "><div title='number=${chapter_no}'>${chapter['name']} (${wc} records)</div></td>";
2690 echo "<form action='${root}process.php' method=post>";
2691 echo "<input type=hidden name=page value='${pageno}'>";
2692 echo "<input type=hidden name=tab value='${tabno}'>";
2693 echo "<input type=hidden name=op value=add>";
2694 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2695 echo "<td> </td>";
2696 echo "<td class=tdright><input type=text name=dict_value size=32></td>";
2697 echo "<td><input type=submit value='Add new'></td>";
2698 echo '</tr></form>';
2699 foreach ($chapter['word'] as $key => $value)
2701 echo "<form action='${root}process.php' method=post>";
2702 echo "<input type=hidden name=page value='${pageno}'>";
2703 echo "<input type=hidden name=tab value='${tabno}'>";
2704 echo "<input type=hidden name=op value='upd'>";
2705 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2706 echo "<input type=hidden name=dict_key value='${key}'>";
2707 echo "<tr class=row_${order}><td>";
2708 // Prevent deleting words currently used somewhere.
2709 if ($chapter['refcnt'][$key])
2710 echo $chapter['refcnt'][$key];
2713 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}&dict_key=${key}'>";
2714 printImageHREF ('delete', 'Delete word');
2718 echo "<td class=tdright><input type=text name=dict_value size=32 value='${value}'></td>";
2719 echo "<td><input type=submit value=OK></td>";
2720 echo "</tr></form>\n";
2721 $order = $nextorder[$order];
2722 } // foreach ($chapter['word']
2727 // We don't allow to rename/delete a sticky chapter and we don't allow
2728 // to delete a non-empty chapter.
2729 function renderChaptersEditor ()
2731 global $root, $pageno, $tabno;
2732 showMessageOrError();
2734 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2735 echo '<tr><th> </th><th>Chapter name</th><th>Words</th><th> </th></tr>';
2736 foreach ($dict as $chapter)
2738 $wordcount = count ($chapter['word']);
2739 $sticky = $chapter['sticky'];
2740 echo "<form action='${root}process.php' method=post>";
2741 echo "<input type=hidden name=page value='${pageno}'>";
2742 echo "<input type=hidden name=tab value='${tabno}'>";
2743 echo "<input type=hidden name=op value=upd>";
2744 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2747 if ($sticky or $wordcount > 0)
2751 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}'>";
2752 printImageHREF ('delete', 'Remove chapter');
2756 echo "<td><input type=text name=chapter_name value='${chapter['name']}'" . ($sticky ?
' disabled' : '') . "></td>";
2757 echo "<td class=tdleft>${wordcount}</td><td>";
2761 echo "<input type=submit value='OK'>";
2765 echo "<form action='${root}process.php' method=post>";
2766 echo "<input type=hidden name=page value='${pageno}'>";
2767 echo "<input type=hidden name=tab value='${tabno}'>";
2768 echo "<input type=hidden name=op value=add>";
2770 printImageHREF ('add', '', TRUE);
2771 echo "</td><td colspan=3><input type=text name=chapter_name></td>";
2777 function renderAttributes ()
2780 $attrMap = getAttrMap();
2781 startPortlet ('Optional attributes');
2782 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2783 echo "<tr><th class=tdleft>Attribute name</th><th class=tdleft>Attribute type</th><th class=tdleft>Applies to</th></tr>";
2785 foreach ($attrMap as $attr)
2787 echo "<tr class=row_${order}>";
2788 echo "<td class=tdleft>${attr['name']}</td>";
2789 echo "<td class=tdleft>${attr['type']}</td>";
2790 echo '<td class=tdleft>';
2791 if (count ($attr['application']) == 0)
2794 foreach ($attr['application'] as $app)
2795 if ($attr['type'] == 'dict')
2796 echo "${app['objtype_name']} (values from '${app['chapter_name']}')<br>";
2798 echo "${app['objtype_name']}<br>";
2801 $order = $nextorder[$order];
2803 echo "</table><br>\n";
2807 function renderEditAttributesForm ()
2809 global $root, $pageno, $tabno;
2810 $attrMap = getAttrMap();
2811 showMessageOrError();
2812 startPortlet ('Optional attributes');
2813 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2814 echo '<tr><th> </th><th>Name</th><th>Type</th><th> </th></tr>';
2815 foreach ($attrMap as $attr)
2817 echo "<form action='${root}process.php' method=post>";
2818 echo "<input type=hidden name=page value='${pageno}'>";
2819 echo "<input type=hidden name=tab value='${tabno}'>";
2820 echo "<input type=hidden name=op value=upd>";
2821 echo "<input type=hidden name=attr_id value='${attr['id']}'>";
2823 echo "<td><a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&attr_id=${attr['id']}'>";
2824 printImageHREF ('delete', 'Remove attribute');
2826 echo "<td><input type=text name=attr_name value='${attr['name']}'></td>";
2827 echo "<td>${attr['type']}</td>";
2828 echo "<td><input type=submit value='OK'></td>";
2832 echo "<form action='${root}process.php' method=post>";
2833 echo "<input type=hidden name=page value='${pageno}'>";
2834 echo "<input type=hidden name=tab value='${tabno}'>";
2835 echo "<input type=hidden name=op value=add>";
2837 printImageHREF ('add', '', TRUE);
2838 echo "</td><td><input type=text name=attr_name></td>";
2839 echo '<td><select name=attr_type>';
2840 echo '<option value=uint>uint</option>';
2841 echo '<option value=float>float</option>';
2842 echo '<option value=string>string</option>';
2843 echo '<option value=dict>dict</option>';
2844 echo '</select></td>';
2851 function renderEditAttrMapForm ()
2853 global $root, $pageno, $tabno;
2854 $attrMap = getAttrMap();
2855 showMessageOrError();
2856 startPortlet ('Attribute map');
2857 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2858 echo '<tr><th> </th><th>Attribute name</th><th>Object type</th><th>Dictionary chapter</th></tr>';
2859 foreach ($attrMap as $attr)
2861 if (count ($attr['application']) == 0)
2863 foreach ($attr['application'] as $app)
2867 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&";
2868 echo "attr_id=${attr['id']}&objtype_id=${app['objtype_id']}'>";
2869 printImageHREF ('delete', 'Remove mapping');
2872 echo "<td>${attr['name']}</td>";
2873 echo "<td>${app['objtype_name']}</td>";
2875 if ($attr['type'] == 'dict')
2876 echo "${app['chapter_name']}";
2879 echo "</td></tr>\n";
2882 echo "<form action='${root}process.php' method=post>";
2883 echo "<input type=hidden name=page value='${pageno}'>";
2884 echo "<input type=hidden name=tab value='${tabno}'>";
2885 echo "<input type=hidden name=op value=add>";
2887 printImageHREF ('add', '', TRUE);
2888 echo "</td><td><select name=attr_id>";
2889 $shortType['uint'] = 'U';
2890 $shortType['float'] = 'F';
2891 $shortType['string'] = 'S';
2892 $shortType['dict'] = 'D';
2893 foreach ($attrMap as $attr)
2894 echo "<option value=${attr['id']}>[" . $shortType[$attr['type']] . "] ${attr['name']}</option>";
2895 echo "</select></td>";
2897 printSelect (getObjectTypeList(), 'objtype_id');
2900 echo '<td><select name=chapter_no>';
2901 foreach ($dict as $chapter)
2902 if (!$chapter['sticky'])
2903 echo "<option value='${chapter['no']}'>${chapter['name']}</option>";
2904 echo '</select></td>';
2911 function printImageHREF ($tag, $title = '', $do_input = FALSE, $tabindex = 0)
2914 $image['error']['path'] = 'pix/error.png';
2915 $image['error']['width'] = 76;
2916 $image['error']['height'] = 17;
2917 $image['logo']['path'] = 'pix/defaultlogo.png';
2918 $image['logo']['width'] = 210;
2919 $image['logo']['height'] = 40;
2920 $image['rackspace']['path'] = 'pix/racks.png';
2921 $image['rackspace']['width'] = 218;
2922 $image['rackspace']['height'] = 200;
2923 $image['objects']['path'] = 'pix/server.png';
2924 $image['objects']['width'] = 218;
2925 $image['objects']['height'] = 200;
2926 $image['ipv4space']['path'] = 'pix/addressspace.png';
2927 $image['ipv4space']['width'] = 218;
2928 $image['ipv4space']['height'] = 200;
2929 $image['config']['path'] = 'pix/configuration.png';
2930 $image['config']['width'] = 218;
2931 $image['config']['height'] = 200;
2932 $image['reports']['path'] = 'pix/report.png';
2933 $image['reports']['width'] = 218;
2934 $image['reports']['height'] = 200;
2935 $image['help']['path'] = 'pix/help.png';
2936 $image['help']['width'] = 218;
2937 $image['help']['height'] = 200;
2938 $image['reserve']['path'] = 'pix/stop.png';
2939 $image['reserve']['width'] = 16;
2940 $image['reserve']['height'] = 16;
2941 $image['useup']['path'] = 'pix/go.png';
2942 $image['useup']['width'] = 16;
2943 $image['useup']['height'] = 16;
2944 $image['blockuser'] = $image['reserve'];
2945 $image['unblockuser'] = $image['useup'];
2946 $image['link']['path'] = 'pix/link.png';
2947 $image['link']['width'] = 24;
2948 $image['link']['height'] = 24;
2949 $image['unlink']['path'] = 'pix/unlink.png';
2950 $image['unlink']['width'] = 24;
2951 $image['unlink']['height'] = 24;
2952 $image['add']['path'] = 'pix/greenplus.png';
2953 $image['add']['width'] = 16;
2954 $image['add']['height'] = 16;
2955 $image['delete']['path'] = 'pix/delete_s.gif';
2956 $image['delete']['width'] = 16;
2957 $image['delete']['height'] = 16;
2958 $image['grant'] = $image['add'];
2959 $image['revoke'] = $image['delete'];
2960 $image['helphint']['path'] = 'pix/helphint.png';
2961 $image['helphint']['width'] = 24;
2962 $image['helphint']['height'] = 24;
2963 if (!isset ($image[$tag]))
2965 $img = $image[$tag];
2966 if ($do_input == TRUE)
2968 "<input type=image name=submit " .
2969 "src='${root}${img['path']}' " .
2971 ($tabindex ?
'' : "tabindex=${tabindex}") .
2976 "src='${root}${img['path']}' " .
2977 "width=${img['width']} " .
2978 "height=${img['height']} " .
2980 (empty ($title) ?
'' : "title='${title}'") .
2984 // This function returns URL for favourite icon.
2985 function getFaviconURL ()
2988 return $root . 'pix/racktables.ico';
2991 function renderReportSummary ()
2993 echo "<table width='100%'>\n";
2994 echo "<tr><td class=pcleft>\n";
2995 startPortlet ("Dictionary/objects stats");
2997 foreach (getDictStats() as $header => $data)
2999 echo "<tr><th>${header}:</th><td>${data}</td></tr>\n";
3004 echo "</td><td class=pcright>\n";
3006 startPortlet ("Here be dragons");
3010 echo 'ASCII art © Daniel C. Au';
3012 echo "</td></tr>\n";
3019 <div
class=dragon
><pre
><font color
="#00ff33">
3021 |
<font color
="#ff0000">@</font
>___oo
3022 /\
/\
/ (__
<font color
=yellow
>,,,,</font
>|
3027 <
; >
; |
(<font color
=white
>,,</font
>) )__
)
3030 \
______(_______
<font color
=white
>;;;</font
> __
<font color
=white
>;;;</font
>
3036 function renderUIConfig ()
3038 global $configCache, $nextorder;
3039 showMessageOrError();
3040 startPortlet ('Current configuration');
3041 echo '<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center width="50%">';
3042 echo '<tr><th class=tdleft>Option</th><th class=tdleft>Value</th></tr>';
3044 foreach ($configCache as $v)
3046 if ($v['is_hidden'] != 'no')
3048 echo "<tr class=row_${order}>";
3049 echo "<td class=tdright>${v['description']}</td>\n";
3050 echo "<td class=tdleft>${v['varvalue']}</td></tr>";
3051 $order = $nextorder[$order];
3057 function renderUIConfigEditForm ()
3059 global $root, $pageno, $tabno, $configCache;
3060 showMessageOrError();
3061 startPortlet ('Current configuration');
3062 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='50%'>\n";
3063 echo "<tr><th class=tdleft>Option</th>";
3064 echo "<th class=tdleft>Value</th></tr>";
3065 echo "<form action='${root}process.php'>";
3066 echo "<input type=hidden name=op value='upd'>";
3067 echo "<input type=hidden name=page value='${pageno}'>\n";
3068 echo "<input type=hidden name=tab value='${tabno}'>\n";
3071 foreach ($configCache as $v)
3073 if ($v['is_hidden'] != 'no')
3075 echo "<input type=hidden name=${i}_varname value='${v['varname']}'>";
3076 echo "<tr><td class=tdright>${v['description']}</td>";
3077 echo "<td class=tdleft><input type=text name=${i}_varvalue value='${v['varvalue']}' size=24></td>";
3081 echo "<input type=hidden name=num_vars value=${i}>\n";
3082 echo "<tr><td colspan=2><input type=submit value='Save changes'></td></tr>";
3087 // This function queries the gateway about current VLAN configuration and
3088 // renders a form suitable for submit. Ah, and it does submit processing as well.
3089 function renderVLANMembership ($object_id = 0)
3091 global $root, $pageno, $tabno, $remote_username;
3092 if ($object_id <= 0)
3094 showError ('Invalid object_id', __FUNCTION__
);
3098 // Handle probable pending submit.
3099 if (isset ($_REQUEST['portcount']))
3101 $data = getSwitchVLANs ($object_id);
3104 showError ('getSwitchVLANs() failed during submit processing', __FUNCTION__
);
3107 list ($vlanlist, $portlist) = $data;
3108 // Here we just build up 1 set command for the gateway with all of the ports
3109 // included. The gateway is expected to filter unnecessary changes silently
3110 // and to provide a list of responses with either error or success message
3111 // for each of the rest.
3112 assertUIntArg ('portcount');
3113 $nports = $_REQUEST['portcount'];
3117 for ($i = 0; $i < $nports; $i++
)
3120 !isset ($_REQUEST['portname_' . $i]) ||
3121 !isset ($_REQUEST['vlanid_' . $i]) ||
3122 $_REQUEST['portname_' . $i] != $portlist[$i]['portname']
3124 $log[] = array ('code' => 'error', 'message' => "Ignoring mailformed record #${i} in form submit");
3127 $_REQUEST['vlanid_' . $i] == $portlist[$i]['vlanid'] ||
3128 $portlist[$i]['vlaind'] == 'TRUNK'
3133 $setcmd .= $prefix . $_REQUEST['portname_' . $i] . '=' . $_REQUEST['vlanid_' . $i];
3137 // Feed the gateway and interpret its (non)response.
3139 printLog (setSwitchVLANs ($object_id, $setcmd));
3142 // Reload and render.
3143 $data = getSwitchVLANs ($object_id);
3146 list ($vlanlist, $portlist, $maclist) = $data;
3148 echo '<table border=0 width="100%"><tr><td colspan=3>';
3150 startPortlet ('Current status');
3151 echo "<table class=widetable cellspacing=3 cellpadding=5 align=center width='100%'><tr>";
3152 echo "<form method=post>";
3153 echo "<input type=hidden name=page value='${pageno}'>";
3154 echo "<input type=hidden name=tab value='${tabno}'>";
3155 echo "<input type=hidden name=object_id value=${object_id}>";
3156 $portcount = count ($portlist);
3157 echo "<input type=hidden name=portcount value=" . $portcount . ">\n";
3159 $ports_per_row = getConfigVar ('PORTS_PER_ROW');
3160 foreach ($portlist as $port)
3162 // Don't let wide forms break our fancy pages.
3163 if ($portno %
$ports_per_row == 0)
3167 echo "<tr><th>" . ($portno +
1) . "-" . ($portno +
$ports_per_row > $portcount ?
$portcount : $portno +
$ports_per_row) . "</th>";
3169 echo '<td class=port_';
3170 if ($port['status'] == 'notconnect')
3172 elseif ($port['status'] == 'disabled')
3174 elseif ($port['status'] != 'connected')
3176 elseif (!isset ($maclist[$port['portname']]))
3177 echo 'connected_none';
3181 foreach ($maclist[$port['portname']] as $vlanid => $addrs)
3182 $maccount +
= count ($addrs);
3184 echo 'connected_single';
3186 echo 'connected_multi';
3188 echo '>' . $port['portname'] . '<br>';
3189 echo "<input type=hidden name=portname_${portno} value=" . $port['portname'] . '>';
3190 if ($port['vlanid'] == 'trunk')
3192 echo "<input type=hidden name=vlanid_${portno} value='trunk'>";
3193 echo "<select disabled multiple='multiple' size=1><option>TRUNK</option></select>";
3197 echo "<select name=vlanid_${portno}>";
3198 // A port may belong to a VLAN, which is absent from the VLAN table, this is normal.
3199 // We must be able to render its SELECT properly at least.
3201 foreach ($vlanlist as $v => $d)
3203 echo "<option value=${v}";
3204 if ($v == $port['vlanid'])
3209 echo ">${v}</option>\n";
3212 echo "<option value=${port['vlanid']} selected>${port['vlanid']}</option>\n";
3218 echo "</tr><tr><td colspan=" . ($ports_per_row +
1) . "><input type=submit value='Save changes'></form></td></tr></table>";
3221 echo '</td></tr><tr><td class=pcleft>';
3222 startPortlet ('VLAN table');
3223 echo '<table class=cooltable cellspacing=0 cellpadding=5 align=center width="100%">';
3224 echo "<tr><th>ID</th><th>Description</th></tr>";
3227 foreach ($vlanlist as $id => $descr)
3229 echo "<tr class=row_${order}><td class=tdright>${id}</td><td class=tdleft>${descr}</td></tr>";
3230 $order = $nextorder[$order];
3235 echo '</td><td class=pcright>';
3237 startPortlet ('Color legend');
3239 echo "<tr><th>port state</th><th>color code</th></tr>";
3240 echo "<tr><td>not connected</td><td class=port_notconnect>SAMPLE</td></tr>";
3241 echo "<tr><td>disabled</td><td class=port_disabled>SAMPLE</td></tr>";
3242 echo "<tr><td>unknown</td><td class=port_unknown>SAMPLE</td></tr>";
3243 echo "<tr><td>connected with none MAC addresses active</td><td class=port_connected_none>SAMPLE</td></tr>";
3244 echo "<tr><td>connected with 1 MAC addresses active</td><td class=port_connected_single>SAMPLE</td></tr>";
3245 echo "<tr><td>connected with 1+ MAC addresses active</td><td class=port_connected_multi>SAMPLE</td></tr>";
3249 echo '</td><td class=pcright>';
3251 if (count ($maclist))
3253 startPortlet ('MAC address table');
3254 echo '<table border=0 class=cooltable align=center cellspacing=0 cellpadding=5>';
3255 echo "<tr><th>Port</th><th>VLAN ID</th><th>MAC address</th></tr>\n";
3257 foreach ($maclist as $portname => $portdata)