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