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