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