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