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