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