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