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