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