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