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