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