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