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