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