r1512 + implement LB management for RS pools
[racktables] / inc / interface.php
CommitLineData
b325120a 1<?php
e673ee24
DO
2/*
3*
4* This file contains frontend functions for RackTables.
5*
6*/
7
9c0b0016
DO
8// Interface function's special.
9$nextorder['odd'] = 'even';
10$nextorder['even'] = 'odd';
11
e673ee24
DO
12// Main menu.
13function 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>
b325120a
DO
24 <h1><a href='<?php echo $root; ?>?page=rackspace'>Rackspace<br>
25 <?php printImageHREF ('rackspace'); ?></a></h1>
e673ee24
DO
26 </td>
27 <td>
b325120a
DO
28 <h1><a href='<?php echo $root; ?>?page=objects'>Objects<br>
29 <?php printImageHREF ('objects'); ?></a></h1>
e673ee24
DO
30 </td>
31 <td>
b325120a
DO
32 <h1><a href='<?php echo $root; ?>?page=ipv4space'>IPv4 space<br>
33 <?php printImageHREF ('ipv4space'); ?></a></h1>
e673ee24
DO
34 </td>
35 </tr>
36 </table>
37 <table width='100%' cellspacing=0 cellpadding=30 class=mainmenu border=0>
38 <tr>
39 <td>
b325120a
DO
40 <h1><a href='<?php echo $root; ?>?page=config'>Configuration<br>
41 <?php printImageHREF ('config'); ?></a></h1>
e673ee24
DO
42 </td>
43 <td>
da95280e 44 <h1><a href='<?php echo $root; ?>?page=reports'>Reports<br>
b325120a 45 <?php printImageHREF ('reports'); ?></a></h1>
e673ee24 46 </td>
ae545907 47 <td>
b325120a
DO
48 <h1><a href='<?php echo $root; ?>?page=help'>Help<br>
49 <?php printImageHREF ('help'); ?></a></h1>
ae545907 50 </td>
e673ee24
DO
51 </tr>
52 </table>
53 </div>
54 </td>
55 </tr>
56</table>
b325120a 57<?php
e673ee24
DO
58}
59
60function renderRackspace ()
61{
62?>
63 <table border=0 cellpadding=10 cellpadding=1>
b325120a 64<?php
e673ee24
DO
65 // generate thumb gallery
66 $rackrowList = getRackRowInfo();
9c0b0016
DO
67 global $root, $nextorder;
68 $rackwidth = getConfigVar ('rtwidth_0') + getConfigVar ('rtwidth_1') + getConfigVar ('rtwidth_2');
e673ee24
DO
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'";
d2ec5490 81 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
e673ee24
DO
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
90function renderRow ($row_id)
91{
92 if ($row_id == 0)
93 {
39a6338a 94 showError ('Invalid row_id', __FUNCTION__);
e673ee24
DO
95 return;
96 }
97 if (($rowInfo = getRackRowInfo ($row_id)) == NULL)
98 {
39a6338a 99 showError ('getRackRowInfo() failed', __FUNCTION__);
e673ee24
DO
100 return;
101 }
114e50af 102 $rackList = getRacksForRow ($row_id);
e673ee24
DO
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>";
51a2330f 108 startPortlet ($rowInfo['dict_value']);
e673ee24 109 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
e673ee24
DO
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";
114e50af
DO
112 echo "<tr><th width='50%' class=tdright>Utilization:</th><td class=tdleft>";
113 renderProgressBar (getRSUforRackRow ($rackList));
114 echo "</td></tr>\n";
e673ee24
DO
115 echo "</table><br>\n";
116 finishPortlet();
117
118 echo "</td><td class=pcright>";
119
9c0b0016
DO
120 global $root, $nextorder;
121 $rackwidth = getConfigVar ('rtwidth_0') + getConfigVar ('rtwidth_1') + getConfigVar ('rtwidth_2');
e673ee24
DO
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']}'>";
9c0b0016
DO
128 echo "<img border=0 width=" . $rackwidth * getConfigVar ('ROW_SCALE') . " height=";
129 echo (3 + 3 + $rack['height'] * 2) * getConfigVar ('ROW_SCALE');
e673ee24 130 echo " title='${rack['height']} units'";
d2ec5490 131 echo "src='render_image.php?img=minirack&rack_id=${rack['id']}'>";
e673ee24
DO
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
39a6338a 141function showError ($info = '', $funcname = 'N/A')
e673ee24
DO
142{
143 global $root;
b1cae282 144 echo "<div class=msg_error>An error has occured in function [${funcname}]. ";
e673ee24
DO
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.
153function renderRack ($rack_id = 0, $hl_obj_id = 0)
154{
155 if ($rack_id == 0)
156 {
39a6338a 157 showError ('Invalid rack_id', __FUNCTION__);
e673ee24
DO
158 return;
159 }
160 if (($rackData = getRackData ($rack_id)) == NULL)
161 {
39a6338a 162 showError ('getRackData() failed', __FUNCTION__);
e673ee24
DO
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";
1c81a02c
DO
180 if ($rackData['left_is_front'] == 'yes')
181 $markup = array ('left' => 'Front', 'right' => 'Back');
182 else
183 $markup = array ('left' => 'Back', 'right' => 'Front');
e673ee24 184 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
9ddfe309
DO
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";
e673ee24
DO
187 for ($i = $rackData['height']; $i > 0; $i--)
188 {
9ddfe309 189 echo '<tr><th>' . ($rackData['bottom_is_unit1'] == 'yes' ? $i : $rackData['height'] - $i + 1) . '</th>';
e673ee24
DO
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
239function 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
4d2e93f2 261 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitAddObject() failed');
e673ee24
DO
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 printSelect (getObjectTypeList(), 'object_type_id');
273 echo "</td></tr>\n";
274 echo "<tr><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name></td></tr>\n";
275 echo "<tr><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label></td></tr>\n";
276 echo "<tr><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=object_asset_no></td></tr>\n";
277 echo "<tr><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode></td></tr>\n";
278 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Create'></td></tr>\n";
279 echo '</form></table>';
280 finishPortlet();
281}
282
283function renderNewRackForm ($row_id)
284{
285 global $pageno, $tabno;
286
287 // Look for current submit.
288 if (isset ($_REQUEST['got_data']))
289 {
290 $log = array();
291 assertStringArg ('rack_name');
292 assertUIntArg ('rack_height');
293 assertStringArg ('rack_comment', TRUE);
294 $name = $_REQUEST['rack_name'];
295 $height = $_REQUEST['rack_height'];
296 $comment = $_REQUEST['rack_comment'];
297
298 if (commitAddRack ($name, $height, $row_id, $comment) === TRUE)
299 $log[] = array ('code' => 'success', 'message' => "Added new rack '${name}'");
300 else
4d2e93f2 301 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . 'commitAddRack() failed');
e673ee24
DO
302 printLog ($log);
303 }
304
305 // Render a form for the next.
306 startPortlet ('Rack attributes');
307 echo '<form>';
308 echo "<input type=hidden name=page value=${pageno}>";
309 echo "<input type=hidden name=tab value=${tabno}>";
310 echo "<input type=hidden name=row_id value=${row_id}>";
311 echo '<table border=0 align=center>';
b901bf1f
DO
312 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
313 if ($defh == 0)
314 $defh = '';
a7bc8321 315 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name tabindex=1></td></tr>\n";
b901bf1f 316 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";
4134b5c0 317 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
e673ee24
DO
318 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Create'></td></tr>\n";
319 echo '</form></table>';
320 finishPortlet();
321}
322
323function renderEditObjectForm ($object_id)
324{
325 showMessageOrError();
326 // Handle submit.
327 if (isset ($_REQUEST['got_data']))
328 {
329 $log = array();
330 // object_id is already verified by page handler
331 assertUIntArg ('object_type_id');
332 assertStringArg ('object_name', TRUE);
333 assertStringArg ('object_label', TRUE);
334 assertStringArg ('object_barcode', TRUE);
335 assertStringArg ('object_asset_no', TRUE);
336 $type_id = $_REQUEST['object_type_id'];
337 if (isset ($_REQUEST['object_has_problems']) and $_REQUEST['object_has_problems'] == 'on')
338 $has_problems = 'yes';
339 else
340 $has_problems = 'no';
341 $name = $_REQUEST['object_name'];
342 $label = $_REQUEST['object_label'];
343 $barcode = $_REQUEST['object_barcode'];
344 $asset_no = $_REQUEST['object_asset_no'];
345 $comment = $_REQUEST['object_comment'];
346
347 if (commitUpdateObject ($object_id, $name, $label, $barcode, $type_id, $has_problems, $asset_no, $comment) === TRUE)
348 $log[] = array ('code' => 'success', 'message' => "Updated object '${name}'");
349 else
4d2e93f2 350 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitUpdateObject() failed');
c7fe33be
DO
351 // Invalidate thumb cache of all racks objects could occupy.
352 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
353 resetThumbCache ($rack_id);
e673ee24
DO
354 printLog ($log);
355 }
356
357 global $pageno, $tabno;
358 $object = getObjectInfo ($object_id);
359 if ($object == NULL)
360 {
39a6338a 361 showError ('getObjectInfo() failed', __FUNCTION__);
e673ee24
DO
362 return;
363 }
364
365 // Render a form for the next submit;
366 echo '<table border=0 width=100%><tr>';
367
368 echo '<td class=pcleft>';
369 startPortlet ('Static attributes');
370 echo '<form>';
371 echo "<input type=hidden name=page value=${pageno}>";
372 echo "<input type=hidden name=tab value=${tabno}>";
373 echo "<input type=hidden name=object_id value=${object_id}>";
374 echo '<table border=0 align=center>';
375 echo "<tr><th class=tdright>Type:</th><td class=tdleft>";
376 printSelect (getObjectTypeList(), 'object_type_id', $object['objtype_id']);
377 echo "</td></tr>\n";
378 // Common attributes.
379 echo "<tr><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name value='${object['name']}'></td></tr>\n";
380 echo "<tr><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label value='${object['label']}'></td></tr>\n";
381 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";
382 echo "<tr><th class=tdright>Barcode:</th><td class=tdleft><input type=text name=object_barcode value='${object['barcode']}'></td></tr>\n";
383 echo "<tr><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
384 if ($object['has_problems'] == 'yes')
385 echo ' checked';
386 echo "></td></tr>\n";
387 echo "<tr><td colspan=2><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
388 echo "<tr><th class=submit colspan=2><input type=submit name=got_data value='Update'></td></tr>\n";
389 echo '</form></table><br>';
390 finishPortlet();
391 echo '</td>';
392
393 // Optional attributes.
394 echo '<td class=pcright>';
395 startPortlet ('Optional attributes');
396 $values = getAttrValues ($object_id);
397 global $root;
398 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
399 echo "<tr><th>&nbsp;</th><th>Attribute</th><th>Value</th><th>&nbsp;</th></tr>\n";
0dfb8a2a
DO
400 echo "<form method=post action='${root}process.php'>\n";
401 echo "<input type=hidden name=page value=${pageno}>\n";
402 echo "<input type=hidden name=tab value=${tabno}>\n";
403 echo "<input type=hidden name=op value=upd>\n";
404 echo "<input type=hidden name=object_id value=${object_id}>\n";
405 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
406
407 $i = 0;
e673ee24
DO
408 foreach ($values as $record)
409 {
0dfb8a2a 410 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
e673ee24
DO
411 echo "<tr><td><a href=${root}process.php?page=${pageno}&tab=${tabno}&op=del&object_id=${object_id}&attr_id=${record['id']}>";
412 printImageHREF ('delete', 'Delete value');
413 echo "</a></td>";
414 echo "<td class=tdright>${record['name']}:</td><td class=tdleft>";
415 switch ($record['type'])
416 {
417 case 'uint':
418 case 'float':
419 case 'string':
0dfb8a2a 420 echo "<input type=text name=${i}_value value='${record['value']}'>";
e673ee24
DO
421 break;
422 case 'dict':
423 $chapter = readChapter ($record['chapter_name']);
4c330a14 424 $chapter[0] = '-- NOT SET --';
0dfb8a2a 425 printSelect ($chapter, "${i}_value", $record['key']);
e673ee24
DO
426 break;
427 }
0dfb8a2a
DO
428 echo "</td></tr>\n";
429 $i++;
e673ee24 430 }
0dfb8a2a
DO
431 echo "<tr><td colspan=3><input type=submit value='Update'></td></tr>\n";
432 echo "</form>";
e673ee24
DO
433 echo "</table>\n";
434 finishPortlet();
435 echo '</td>';
436
437 echo '</tr><tr>';
438
439 echo '<td colspan=2>';
440 startPortlet ('history');
441 renderHistory ($pageno, $object_id);
442 finishPortlet();
443 echo '</td>';
444
445 echo '</tr></table>';
446}
447
448// This is a clone of renderEditObjectForm().
449function renderEditRackForm ($rack_id)
450{
451 // Handle submit.
452 if (isset ($_REQUEST['got_data']))
453 {
454 $log = array();
455 assertUIntArg ('rack_row_id');
456 assertUIntArg ('rack_height');
457 assertStringArg ('rack_name');
458 assertStringArg ('rack_comment', TRUE);
459 $row_id = $_REQUEST['rack_row_id'];
460 $height = $_REQUEST['rack_height'];
461 $name = $_REQUEST['rack_name'];
462 $comment = $_REQUEST['rack_comment'];
463
464 if (commitUpdateRack ($rack_id, $name, $height, $row_id, $comment) === TRUE)
465 $log[] = array ('code' => 'success', 'message' => "Updated rack '${name}'");
466 else
4d2e93f2 467 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitUpdateRack() failed');
c7fe33be 468 resetThumbCache ($rack_id);
e673ee24
DO
469 printLog ($log);
470 }
471
472 global $pageno, $tabno;
473 $rack = getRackData ($rack_id);
474 if ($rack == NULL)
475 {
39a6338a 476 showError ('getRackData() failed', __FUNCTION__);
e673ee24
DO
477 return;
478 }
479
480 // Render a form for the next.
481 startPortlet ('Rack attributes');
482 echo '<form>';
483 echo "<input type=hidden name=page value=${pageno}>";
484 echo "<input type=hidden name=tab value=${tabno}>";
485 echo "<input type=hidden name=rack_id value=${rack_id}>";
486 echo '<table border=0 align=center>';
487 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
4c330a14 488 printSelect (readChapter ('RackRow'), 'rack_row_id', $rack['row_id']);
e673ee24
DO
489 echo "</td></tr>\n";
490 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
491 echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
492 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
493 echo "<tr><td class=submit colspan=2><input type=submit name=got_data value='Update'></td></tr>\n";
494 echo '</form></table><br>';
495 finishPortlet();
496
497 startPortlet ('History');
498 renderHistory ($pageno, $rack_id);
499 finishPortlet();
500}
501
502// This is a helper for creators and editors.
503function printSelect ($rowList, $select_name, $selected_id = 1)
504{
505 echo "<select name=${select_name}>";
4c330a14 506 foreach ($rowList as $dict_key => $dict_value)
e673ee24 507 {
4c330a14
DO
508 echo "<option value=${dict_key}";
509 if ($dict_key == $selected_id)
e673ee24 510 echo ' selected';
4c330a14 511 echo ">${dict_value}</option>";
e673ee24
DO
512 }
513 echo "</select>";
514}
515
516// This is a universal editor of rack design/waste.
bb09cca0 517function renderGridForm ($rack_id = 0, $filter, $header, $submit, $state1, $state2)
e673ee24
DO
518{
519 if ($rack_id == 0)
520 {
591ff2c4 521 showError ('Invalid rack_id', __FUNCTION__);
e673ee24
DO
522 return;
523 }
524 if (($rackData = getRackData ($rack_id)) == NULL)
525 {
591ff2c4 526 showError ('getRackData() failed', __FUNCTION__);
e673ee24
DO
527 return;
528 }
529
530 global $root, $pageno, $tabno;
531 $filter($rackData);
532 markupObjectProblems ($rackData);
533
534 // Process form submit.
535 if (isset ($_REQUEST['do_update']))
536 {
537 $log[] = processGridForm ($rackData, $state1, $state2);
538 printLog($log);
539 }
540
541 // Render the result whatever it is.
542 // Main layout.
543 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
544 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
545
546 // Left column with information portlet.
547 echo "<tr><td class=pcleft height='1%' width='50%'>";
548 startPortlet ('Rack information');
549 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
550 echo "<tr><th width='50%' class=tdright>Rack name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
551 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
552 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
553 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
554 echo "</table>\n";
555 finishPortlet();
556
557 echo "</td>\n";
bb09cca0 558 echo "<td class=pcright>";
e673ee24
DO
559
560 // Grid form.
561 startPortlet ($header);
562 echo "<center>\n";
563 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
564 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
565 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
566 echo "<form action='${root}?'>\n";
567 echo "<input type=hidden name=page value=${pageno}>\n";
568 echo "<input type=hidden name=tab value=${tabno}>\n";
569 echo "<input type=hidden name=rack_id value=${rack_id}>\n";
570 markupAtomGrid ($rackData, $state2);
571 renderAtomGrid ($rackData);
572 echo "</table></center>\n";
573 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
574 finishPortlet();
bb09cca0 575 echo "</td></tr></table>\n";
e673ee24
DO
576}
577
578function renderRackDesign ($rack_id)
579{
bb09cca0 580 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
e673ee24
DO
581}
582
583function renderRackProblems ($rack_id = 0)
584{
bb09cca0 585 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
e673ee24
DO
586}
587
588function startPortlet ($title = '')
589{
590 echo "<div class=portlet><h2>${title}</h2>";
591}
592
593function finishPortlet ()
594{
595 echo "</div>\n";
596}
597
598function printRefsOfType ($refs, $type, $eq)
599{
600 global $root;
601 $gotone=0;
602 foreach ($refs as $ref)
603 {
604 if ($eq($ref['type'], $type))
605 {
606 if ($gotone) echo ', ';
4b2bf583
DO
607 echo "<a href='${root}?page=object&object_id=${ref['object_id']}'>";
608 if (!empty ($ref['name']))
609 echo $ref['name'] . '@';
610 echo "${ref['object_name']}</a>";
e673ee24
DO
611 $gotone=1;
612 }
613 }
614}
615
616function renderRackObject ($object_id = 0)
617{
618 global $root;
619 if ($object_id <= 0)
620 {
591ff2c4 621 showError ('Invalid object_id', __FUNCTION__);
e673ee24
DO
622 return;
623 }
624 $info = getObjectInfo ($object_id);
625 if ($info == NULL)
626 {
591ff2c4 627 showError ('getObjectInfo() failed', __FUNCTION__);
e673ee24
DO
628 return;
629 }
630 // Main layout starts.
631 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
632 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
633 // left column with uknown number of portlets
634 echo "<tr><td class=pcleft>";
635 startPortlet ('Object information');
636 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
637 if (!empty ($info['name']))
638 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
9c0b0016 639 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('NAMEFUL_OBJTYPES'))))
a0ec6295 640 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
e673ee24
DO
641 echo "<tr><th width='50%' class=tdright>Object type:</th><td class=tdleft>${info['objtype_name']}</td></tr>\n";
642 if (!empty ($info['asset_no']))
643 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
a6305acc 644 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('REQUIRE_ASSET_TAG_FOR'))))
a0ec6295 645 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
e673ee24
DO
646 if (!empty ($info['label']))
647 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
648 if (!empty ($info['barcode']))
649 echo "<tr><th width='50%' class=tdright>Barcode:</th><td class=tdleft>${info['barcode']}</td></tr>\n";
650 if ($info['has_problems'] == 'yes')
651 echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
652 foreach (getAttrValues ($object_id) as $record)
653 if (!empty ($record['value']))
50a954f6 654 echo "<tr><th width='50%' class=opt_attr_th>${record['name']}:</th><td class=tdleft>${record['a_value']}</td></tr>\n";
e673ee24
DO
655 echo "</table><br>\n";
656 finishPortlet();
657
658 if (!empty ($info['comment']))
659 {
660 startPortlet ('Comment');
661 echo '<div class=commentblock>' . $info['comment'] . '</div>';
662 finishPortlet ();
663 }
664
665 $ports = getObjectPortsAndLinks ($object_id);
666 if (count ($ports))
667 {
668 startPortlet ('Ports and links');
669 usort($ports, 'sortByName');
670 if ($ports)
671 {
672 $hl_port_id = 0;
673 if (isset ($_REQUEST['hl_port_id']))
674 {
675 assertUIntArg ('hl_port_id');
676 $hl_port_id = $_REQUEST['hl_port_id'];
677 }
678 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
679 echo "<tr><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
680 echo "<th>Rem. Object</th><th>Rem. port</th></tr>\n";
681 foreach ($ports as $port)
682 {
683 echo '<tr';
684 if ($hl_port_id == $port['id'])
685 echo ' class=port_highlight';
686 echo "><td>${port['name']}</td><td>${port['label']}</td><td>${port['type']}</td>";
687 echo "<td>${port['l2address']}</td>";
688 if ($port['remote_object_id'])
689 {
690 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}'>${port['remote_object_name']}</a></td>";
691 echo "<td>${port['remote_name']}</td>";
692 }
693 elseif (!empty ($port['reservation_comment']))
694 {
695 echo "<td><b>Reserved;</b></td>";
696 echo "<td>${port['reservation_comment']}</td>";
697 }
698 else
699 echo '<td>&nbsp;</td><td>&nbsp;</td>';
700 echo "</tr>\n";
701 }
702 echo "</table><br>\n";
703 }
704 finishPortlet();
705 }
706 $addresses = getObjectAddresses ($object_id);
707 usort($addresses, 'sortAddresses');
708 if (count ($addresses))
709 {
f28fbe8b 710 startPortlet ('IPv4 addresses');
e673ee24
DO
711 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
712 echo "<tr><th>Interface name</th><th>IP Address</th><th>Description</th><th>Misc</th></tr>\n";
713 foreach ($addresses as $addr)
714 {
715 if (strlen($addr['address_name'])>40)
716 $address_name = substr($addr['address_name'],0,38).'...';
717 else
718 $address_name = $addr['address_name'];
719
720 $virtnum = countRefsOfType($addr['references'], 'virtual', 'eq');
721 $sharednum = countRefsOfType($addr['references'], 'shared', 'eq');
722 $regnum = countRefsOfType($addr['references'], 'regular', 'eq');
723 $notvirtnum = countRefsOfType($addr['references'], 'virtual', 'neq');
724
725 if ($addr['address_reserved']=='yes')
726 $class='trwarning';
727 elseif ($addr['type']!='virtual' && $regnum>0)
728 $class='trwarning';
729 elseif ($addr['type']=='regular' && $sharednum>0)
730 $class='trwarning';
731 else
732 $class='';
733
734 echo "<tr class='$class'><td>${addr['name']}</td><td><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td><td class='description'>$address_name</td><td>\n";
735
736 if ($addr['address_reserved']=='yes')
737 echo "<b>Reserved;</b> ";
738
739 if ($addr['type'] == 'virtual')
740 {
741 echo "<b>V</b>";
742 if ($notvirtnum > 0)
743 {
744 echo " Owners: ";
745 printRefsOfType($addr['references'], 'virtual', 'neq');
746 }
747 }
748 elseif ($addr['type'] == 'shared')
749 {
750 echo "<b>S</b>";
751 if ($sharednum > 0)
752 {
753 echo " Peers: ";
754 printRefsOfType($addr['references'], 'shared', 'eq');
755 echo ";";
756 }
757 if ($virtnum > 0)
758 {
759 echo " Virtuals: ";
760 printRefsOfType($addr['references'], 'virtual', 'eq');
761 echo ";";
762 }
763 if ($regnum > 0)
764 {
765 echo " Collisions: ";
766 printRefsOfType($addr['references'], 'regular', 'eq');
767 }
768
769 }
770 else
771 {
772 if ($virtnum > 0)
773 {
774 echo " Virtuals: ";
775 printRefsOfType($addr['references'], 'virtual', 'eq');
776 echo ";";
777 }
778 if ($notvirtnum > 0)
779 {
780 echo " Collisions: ";
781 printRefsOfType($addr['references'], 'virtual', 'neq');
782 }
783 }
784
785 echo "</td></tr>\n";
786 }
787 echo "</table><br>\n";
788 finishPortlet();
789 }
790
791 $forwards = getObjectForwards ($object_id);
792 if (count($forwards['in']) or count($forwards['out']))
793 {
f28fbe8b 794 startPortlet('NATv4');
e673ee24
DO
795
796 if (count($forwards['out']))
797 {
798
f28fbe8b 799 echo "<h3>locally performed NAT</h3>";
e673ee24
DO
800
801 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 802 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
e673ee24
DO
803
804 foreach ($forwards['out'] as $pf)
805 {
806 $class='trwarning';
807 $name='';
808 foreach ($addresses as $addr)
809 if ($addr['ip'] == $pf['localip'])
810 {
811 $class='';
812 $name=$addr['name'];
813 break;
814 }
815
816 echo "<tr class='$class'>";
817
f28fbe8b 818 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>";
e673ee24 819
f28fbe8b 820 echo "<td class=tdleft><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
e673ee24
DO
821
822 $address=getIPAddress($pf['remoteip']);
823
824 echo "<td class='description'>";
f28fbe8b
DO
825 if (count ($address['bonds']))
826 foreach($address['bonds'] as $bond)
827 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
828 elseif (!empty ($pf['remote_addr_name']))
829 echo '(' . $pf['remote_addr_name'] . ')';
e673ee24
DO
830
831 echo "</td><td class='description'>${pf['description']}</td>";
832
833 echo "</tr>";
834 }
835 echo "</table><br><br>";
836 }
837 if (count($forwards['in']))
838 {
f28fbe8b 839 echo "<h3>arriving NAT connections</h3>";
e673ee24
DO
840
841 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 842 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
e673ee24
DO
843
844 foreach ($forwards['in'] as $pf)
845 {
846 echo "<tr>";
847 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
848
849 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
850
851 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
852 echo "<td class='description'>${pf['description']}</td></tr>";
853 }
854
855 echo "</table><br><br>";
856 }
857 finishPortlet();
858 }
859
860 echo "</td>\n";
861
862 // After left column we have (surprise!) right column with rackspace portled only.
863 echo "<td class=pcright>";
864 // rackspace portlet
865 startPortlet ('Rackspace allocation');
866 // FIXME: now we call getRackData() twice
867 $racks = getResidentRacksData ($object_id);
868 foreach ($racks as $rackData)
869 renderRack ($rackData['id'], $object_id);
870 echo '<br>';
871 finishPortlet();
872 echo "</td></tr>";
873 echo "</table>\n";
874}
875
876function renderRackMultiSelect ($sname, $racks, $selected)
877{
9c0b0016 878 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementById(\"racks\").submit()'>\n";
e673ee24
DO
879 foreach ($racks as $rack)
880 {
881 echo "<option value=${rack['id']}";
882 if (!(array_search ($rack['id'], $selected) === FALSE))
883 echo ' selected';
6a3a37b2 884 echo">${rack['row_name']}: ${rack['name']}</option>\n";
e673ee24
DO
885 }
886 echo "</select>\n";
887}
888
889function showMessageOrError ()
890{
891 if (isset($_REQUEST['message']))
892 echo "<div class=msg_success>${_REQUEST['message']}</div>";
893 if (isset($_REQUEST['error']))
894 echo "<div class=msg_error>${_REQUEST['error']}</div>";
895}
896
897// This function renders a form for port edition.
898function renderPortsForObject ($object_id = 0)
899{
900 global $root, $pageno, $tabno;
901 if ($object_id <= 0)
902 {
591ff2c4 903 showError ('Invalid object_id', __FUNCTION__);
e673ee24
DO
904 return;
905 }
906 showMessageOrError();
907 startPortlet ('Ports and interfaces');
908 $ports = getObjectPortsAndLinks ($object_id);
909 usort($ports, 'sortByName');
910 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
911 echo "<tr><th>&nbsp;</th><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
912 echo "<th>Rem. object</th><th>Rem. port</th><th>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
913 foreach ($ports as $port)
914 {
915 echo "<form action='${root}process.php'>";
916 echo "<input type=hidden name=op value=editPort>";
917 echo "<input type=hidden name=page value='${pageno}'>\n";
918 echo "<input type=hidden name=tab value='${tabno}'>\n";
919 echo "<input type=hidden name=port_id value='${port['id']}'>";
920 echo "<input type=hidden name=object_id value='$object_id'>\n";
921 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']}'>";
922 printImageHREF ('delete', 'Unlink and Delete this port');
923 echo "</a></td>\n";
924 echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
925 echo "<td><input type=text name=label value='${port['label']}' size=24></td>";
926 echo "<td>${port['type']}</td>\n";
927 echo "<td><input type=text name=l2address value='${port['l2address']}'></td>\n";
928 if ($port['remote_object_id'])
929 {
930 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}'>${port['remote_object_name']}</a></td>";
931 echo "<td>${port['remote_name']}</td>";
932 echo "<td><a href='${root}process.php?op=unlinkPort&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=$object_id&port_name=";
933 echo urlencode ($port['name']);
934 echo "&remote_port_name=${port['remote_name']}&remote_object_name=${port['remote_object_name']}'>";
935 printImageHREF ('unlink', 'Unlink this port');
936 echo "</a></td>";
937 }
938 elseif (!empty ($port['reservation_comment']))
939 {
940 echo "<td><b>Reserved;</b></td>";
941 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
942 echo "<td><a href='${root}process.php?op=useup&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=${object_id}'>";
943 printImageHREF ('useup', 'Use up this port');
944 echo "</a></td>";
945 }
946 else
947 {
948 echo "<td>&nbsp;</td><td>&nbsp;</td>";
949 echo "<td>";
950 echo "<a href='javascript:;' onclick='window.open(\"${root}link_helper.php?port=${port['id']}&type=${port['type_id']}&object_id=$object_id&port_name=";
951 echo urlencode ($port['name']);
952 echo "\",\"findlink\",\"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
953 printImageHREF ('link', 'Link this port');
954 echo "</a> <input type=text name=reservation_comment>";
955 echo "</td>\n";
956 }
957 echo "<td><input type='submit' value='OK'></td>";
958 echo "</form></tr>\n";
959 }
960 echo "<form action='${root}process.php'><tr>";
961 echo "<td colspan=2><input type=text size=10 name=port_name tabindex=100></td>\n";
962 echo "<td><input type=text size=24 name=port_label tabindex=101></td>";
963 echo "<input type=hidden name=op value=addPort>\n";
964 echo "<input type=hidden name=object_id value='${object_id}'>\n";
965 echo "<input type=hidden name=page value='${pageno}'>\n";
966 echo "<input type=hidden name=tab value='${tabno}'>\n";
967 echo "<td><select name='port_type_id' tabindex=102>\n";
968 $types = getPortTypes();
9c0b0016 969 $default_port_type = getConfigVar ('default_port_type');
e673ee24
DO
970 foreach ($types as $typeid => $typename)
971 {
972 echo "<option value='${typeid}'";
973 if ($typeid == $default_port_type)
974 echo " selected";
975 echo ">${typename}</option>\n";
976 }
977 echo "</select></td>";
978 echo "<td><input type=text name=port_l2address tabindex=103></td>\n";
979 echo "<td colspan=4><input type='submit' value='Add a new port' tabindex=104></td></tr></form>";
980 echo "</table><br>\n";
981 finishPortlet();
982
983 startPortlet ('Add/update multiple ports');
984 echo "<form action=${root}process.php method=post>";
985 echo "<input type=hidden name=page value='${pageno}'>\n";
986 echo "<input type=hidden name=tab value='${tabno}'>\n";
987 echo "<input type=hidden name=object_id value='${object_id}'>\n";
988 echo "<input type=hidden name=op value=addMultiPorts>";
989 echo 'Format: <select name=format>';
990 echo '<option value=c2900 disabled>Cisco 2900 series: sh int eth</option>';
991 echo '<option value=c3600eth disabled>Cisco 3600 ethernet: sh arp | inc -</option>';
992 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
993 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
994 echo '<option value=fiedge disabled>Foundry FastIron Edge: sh int br</option>';
995 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
996 echo "</select>";
997 echo 'Default port type: ';
998 echo "<select name=port_type>\n";
999 foreach ($types as $typeid => $typename)
1000 {
1001 echo "<option value='${typeid}'";
1002 if ($typeid == $default_port_type)
1003 echo " selected";
1004 echo ">${typename}</option>\n";
1005 }
1006 echo "</select>";
1007 echo "<input type=submit value='Parse output'><br>\n";
1008 echo "<textarea name=input cols=100 rows=50></textarea><br>\n";
1009 echo '</form>';
1010 finishPortlet();
1011}
1012
1013function renderNetworkForObject ($object_id=0)
1014{
1015 global $root, $pageno, $tabno;
1016 if ($object_id <= 0)
1017 {
591ff2c4 1018 showError ('Invalid object_id', __FUNCTION__);
e673ee24
DO
1019 return;
1020 }
1021 showMessageOrError();
1022 startPortlet ('Network Addresses');
1023 $addresses = getObjectAddresses ($object_id);
1024 usort($addresses, 'sortAddresses');
1025 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1026 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";
1027 foreach ($addresses as $addr)
1028 {
1029 if (strlen($addr['address_name'])>40)
1030 $address_name = substr($addr['address_name'],0,38).'...';
1031 else
1032 $address_name = $addr['address_name'];
1033
1034 $virtnum = countRefsOfType($addr['references'], 'virtual', 'eq');
1035 $sharednum = countRefsOfType($addr['references'], 'shared', 'eq');
1036 $regnum = countRefsOfType($addr['references'], 'regular', 'eq');
1037 $notvirtnum = countRefsOfType($addr['references'], 'virtual', 'neq');
1038
1039 if ($addr['address_reserved']=='yes')
1040 $class='trwarning';
1041 elseif ($addr['type']!='virtual' && $regnum>0)
1042 $class='trwarning';
1043 elseif ($addr['type']=='regular' && $sharednum>0)
1044 $class='trwarning';
1045 else
1046 $class='';
1047
1048 echo "<form action='process.php'>";
1049 echo "<input type=hidden name=page value='${pageno}'>\n";
1050 echo "<input type=hidden name=tab value='${tabno}'>\n";
1051 echo "<input type=hidden name=op value=editAddressFromObject>";
1052 echo "<input type=hidden name=object_id value='$object_id'>";
1053 echo "<input type=hidden name=ip value='${addr['ip']}'>";
1054 echo "<tr class='$class'><td><a href='process.php?op=delAddrFObj&page=${pageno}&tab=${tabno}&ip=${addr['ip']}&object_id=$object_id'>";
1055 printImageHREF ('delete', 'Delete this IPv4 address');
1056 echo "</a></td>";
1057 echo "<td><input type='text' name='bond_name' value='${addr['name']}' size=10></td>";
1058 echo "<td><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
1059 echo "<td class='description'>$address_name</td>\n";
1060 echo "<td><select name='bond_type'>";
1061 foreach (array('regular'=>'Regular', 'virtual'=>'Virtual', 'shared'=>'Shared') as $n => $v)
1062 {
1063 echo "<option value='$n'";
1064 if ($addr['type'] == $n)
1065 echo " selected";
1066 echo ">$v</option>";
1067 }
1068 echo "</td><td>";
1069 if ($addr['address_reserved']=='yes')
1070 echo "<b>Reserved</b>; ";
1071
1072 if ($addr['type'] == 'virtual')
1073 {
1074 if ($notvirtnum > 0)
1075 {
1076 echo " Owners: ";
1077 printRefsOfType($addr['references'], 'virtual', 'neq');
1078 }
1079 }
1080 elseif ($addr['type'] == 'shared')
1081 {
1082 if ($sharednum > 0)
1083 {
1084 echo " Peers: ";
1085 printRefsOfType($addr['references'], 'shared', 'eq');
1086 echo ";";
1087 }
1088 if ($virtnum > 0)
1089 {
1090 echo " Virtuals: ";
1091 printRefsOfType($addr['references'], 'virtual', 'eq');
1092 echo ";";
1093 }
1094 if ($regnum > 0)
1095 {
1096 echo " Collisions: ";
1097 printRefsOfType($addr['references'], 'regular', 'eq');
1098 }
1099
1100 }
1101 else
1102 {
1103 if ($virtnum > 0)
1104 {
1105 echo " Virtuals: ";
1106 printRefsOfType($addr['references'], 'virtual', 'eq');
1107 echo ";";
1108 }
1109 if ($notvirtnum > 0)
1110 {
1111 echo " Collisions: ";
1112 printRefsOfType($addr['references'], 'virtual', 'neq');
1113 }
1114 }
1115
1116 echo "</td><td><input type=submit value='OK'></td></form></tr>\n";
1117 }
1118
1119
1120 echo "<form action='${root}process.php'><tr><td colspan=2><input type='text' size='10' name='name' tabindex=100></td>\n";
1121 echo "<input type=hidden name=page value='${pageno}'>\n";
1122 echo "<input type=hidden name=tab value='${tabno}'>\n";
1123 echo "<input type=hidden name=op value=addAddrFObj>\n";
1124 echo "<input type=hidden name=object_id value='$object_id'>\n";
1125
1126 echo "<td><input type=text name='ip' tabindex=101>\n";
1127 echo "</td><td><select name='type' tabindex=102>";
1128 echo "<option value='regular'>Regular</option>";
1129 echo "<option value='virtual'>Virtual</option>";
1130 echo "<option value='shared'>Shared</option>";
1131 echo "</select>";
1132 echo "</td><td colspan=3><input type='submit' value='Add a new interface' tabindex=103></td></tr></form>";
1133 echo "</table><br>\n";
1134 finishPortlet();
1135
1136}
1137
1138function printLog ($log)
1139{
1140 foreach ($log as $record)
1141 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1142}
1143
1144/*
1145The following conditions must be followed:
11461. We can mount onto free atoms only. This means: if any record for an atom
1147already exists in RackSpace, it can't be used for mounting.
11482. We can't unmount from 'W' atoms. Operator should review appropriate comments
1149and either delete them before unmounting or refuse to unmount the object.
1150*/
1151
1152// We extensively use $_REQUEST in the function.
1153function renderRackSpaceForObject ($object_id = 0)
1154{
1155 if ($object_id <= 0)
1156 {
591ff2c4 1157 showError ('Invalid object_id', __FUNCTION__);
e673ee24
DO
1158 return;
1159 }
1160 $is_submit = isset ($_REQUEST['got_atoms']);
1161 $is_update = isset ($_REQUEST['rackmulti'][0]);
1162 $info = getObjectInfo ($object_id);
1163 if ($info == NULL)
1164 {
591ff2c4 1165 showError ('getObjectInfo() failed', __FUNCTION__);
e673ee24
DO
1166 return;
1167 }
1168 // Always process occupied racks plus racks chosen by user. First get racks with
1169 // already allocated rackspace...
1170 $workingRacksData = getResidentRacksData ($object_id);
1171 if ($workingRacksData === NULL)
1172 {
1173 print_r ($workingRacksData);
591ff2c4 1174 showError ('getResidentRacksData() failed', __FUNCTION__);
e673ee24
DO
1175 return;
1176 }
1177
1178 // ...and then add those chosen by user (if any).
1179 if ($is_update)
1180 foreach ($_REQUEST['rackmulti'] as $cand_id)
1181 {
1182 if (!isset ($workingRacksData[$cand_id]))
1183 {
1184 $rackData = getRackData ($cand_id);
1185 if ($rackData == NULL)
1186 {
591ff2c4 1187 showError ('getRackData() failed', __FUNCTION__);
e673ee24
DO
1188 return NULL;
1189 }
1190 $workingRacksData[$cand_id] = $rackData;
1191 }
1192 }
1193
1194 // Do it only once...
1195 foreach ($workingRacksData as &$rackData)
1196 applyObjectMountMask ($rackData, $object_id);
1197 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1198 unset ($rackData);
1199
1200 // Here we process form submit by trying to save all submitted info to database.
1201 if ($is_submit)
1202 {
1203 $oldMolecule = getMoleculeForObject ($object_id);
1204 $worldchanged = FALSE;
1205 $log = array();
1206 foreach ($workingRacksData as $rack_id => $rackData)
1207 {
1208 $logrecord = processGridForm ($rackData, 'F', 'T', $object_id);
1209 $log[] = $logrecord;
1210 if ($logrecord['code'] != 300)
1211 {
1212 $worldchanged = TRUE;
1213 // Reload our working copy after form processing.
1214 $rackData = getRackData ($rack_id);
1215 if ($rackData == NULL)
4d2e93f2 1216 $log[] = array ('code' => 500, 'message' => 'Working copy update failed in ', __FUNCTION__);
e673ee24
DO
1217 applyObjectMountMask ($rackData, $object_id);
1218 $workingRacksData[$rack_id] = $rackData;
1219 }
1220 }
1221 if ($worldchanged)
1222 {
1223 // Log a record.
1224 $newMolecule = getMoleculeForObject ($object_id);
1225 $oc = count ($oldMolecule);
1226 $nc = count ($newMolecule);
1227 $omid = $oc ? createMolecule ($oldMolecule) : 'NULL';
1228 $nmid = $nc ? createMolecule ($newMolecule) : 'NULL';
1229 global $remote_username;
1230 $comment = empty ($_REQUEST['comment']) ? 'NULL' : "'${_REQUEST['comment']}'";
1231 $query =
1232 "insert into MountOperation(object_id, old_molecule_id, new_molecule_id, user_name, comment) " .
1233 "values (${object_id}, ${omid}, ${nmid}, '${remote_username}', ${comment})";
1234 global $dbxlink;
1235 $result = $dbxlink->query ($query);
1236 if ($result == NULL)
1237 $log[] = array ('code' => 'error', 'message' => 'SQL query failed during history logging.');
1238 else
1239 $log[] = array ('code' => 'success', 'message' => 'History logged.');
1240 }
1241 printLog ($log);
1242 }
1243
1244 // This is the time for rendering.
1245 global $root, $pageno, $tabno;
1246 echo "<form id='racks' action='${root}'>";
1247 echo "<input type=hidden name=page value='${pageno}'>\n";
1248 echo "<input type=hidden name=tab value='${tabno}'>\n";
1249 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1250 // Main layout starts.
1251 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1252
1253 // Left portlet with rack list.
1254 echo "<td class=pcleft height='1%'>";
1255 startPortlet ('Racks');
1256 $allRacksData = getRacksForRow();
1257 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1258 echo "<br>";
1259 echo "<br>";
1260 finishPortlet();
1261 echo "</td>";
1262
1263 // Middle portlet with comment and submit.
1264 echo "<td class=pcleft>";
1265 startPortlet ('Comment');
1266 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1267 echo "<input type=submit value='Save' name=got_atoms>\n";
1268 echo "<br>";
1269 echo "<br>";
1270 finishPortlet();
1271 echo "</td>";
1272
1273 // Right portlet with rendered racks. If this form submit is not final, we have to
1274 // reflect the former state of the grid in current form.
1275 echo "<td class=pcright rowspan=2 height='1%'>";
1276 startPortlet ('Working copy');
1277 echo '<table border=0 cellspacing=10 align=center><tr>';
1278 foreach ($workingRacksData as $rack_id => $rackData)
1279 {
1280 // Order is important here: only original allocation is highlighted.
1281 highlightObject ($rackData, $object_id);
1282 markupAtomGrid ($rackData, 'T');
1283 // If we have a form processed, discard user input and show new database
1284 // contents.
1285 if (!$is_submit and $is_update)
1286 mergeGridFormToRack ($rackData);
1287 echo "<td valign=top>";
1288 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1289 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1290 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1291 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1292 renderAtomGrid ($rackData);
9b7468b7
DO
1293 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1294 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
e673ee24
DO
1295 echo "</table></center>\n";
1296 echo '</td>';
1297 }
1298 echo "</tr></table>";
1299 finishPortlet();
1300 echo "</td>\n";
1301
1302 echo "</form>\n";
1303 echo "</tr></table>\n";
1304}
1305
1306function renderMolecule ($mdata, $object_id)
1307{
1308 // sort data out
1309 $rackpack = array();
1310 global $loclist;
1311 foreach ($mdata as $dummy => $rua)
1312 {
1313 $rack_id = $rua['rack_id'];
1314 $unit_no = $rua['unit_no'];
1315 $atom = $rua['atom'];
1316 if (!isset ($rackpack[$rack_id]))
1317 {
1318 $rackData = getRackData ($rack_id);
1319 for ($i = $rackData['height']; $i > 0; $i--)
1320 for ($locidx = 0; $locidx < 3; $locidx++)
1321 $rackData[$i][$locidx]['state'] = 'F';
1322 $rackpack[$rack_id] = $rackData;
1323 }
1324 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1325 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1326 }
1327 // now we have some racks to render
1328 foreach ($rackpack as $dummy => $rackData)
1329 {
1330 markAllSpans ($rackData);
1331 echo "<table class=molecule cellspacing=0>\n";
1332 echo "<caption>${rackData['name']}</caption>\n";
1333 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1334 for ($i = $rackData['height']; $i > 0; $i--)
1335 {
1336 echo "<tr><th>$i</th>";
1337 for ($locidx = 0; $locidx < 3; $locidx++)
1338 {
1339 $state = $rackData[$i][$locidx]['state'];
1340 echo "<td class=state_${state}>&nbsp;</td>\n";
1341 }
1342 echo "</tr>\n";
1343 }
1344 echo "</table>\n";
1345 }
1346}
1347
1348function renderUnmountedObjectsPortlet ()
1349{
1350 startPortlet ('Unmounted objects');
1351 $objs = getUnmountedObjects();
1352 if ($objs === NULL)
1353 {
591ff2c4 1354 showError ('getUnmountedObjects() failed', __FUNCTION__);
e673ee24
DO
1355 return;
1356 }
1357 global $root, $nextorder;
1358 $order = 'odd';
1359 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
18d94c29 1360 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset number</th><th>Barcode</th></tr>';
e673ee24
DO
1361 foreach ($objs as $obj)
1362 {
1363 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1364 echo "<td>${obj['label']}</td>";
18d94c29
DO
1365 echo "<td>${obj['asset_no']}</td>";
1366 echo "<td>${obj['barcode']}</td></tr>";
e673ee24
DO
1367 $order = $nextorder[$order];
1368 }
1369 echo "</table><br>\n";
1370 finishPortlet();
1371}
1372
1373function renderProblematicObjectsPortlet ()
1374{
1375 startPortlet ('Problematic objects');
1376 $objs = getProblematicObjects();
1377 if ($objs === NULL)
1378 {
591ff2c4 1379 showError ('getProblematicObjects() failed', __FUNCTION__);
e673ee24
DO
1380 return;
1381 }
1382 global $root, $nextorder;
1383 $order = 'odd';
1384 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1385 echo '<tr><th>Type</th><th>Common name</th></tr>';
1386 foreach ($objs as $obj)
1387 {
1388 echo "<tr class=row_${order}><td>${obj['objtype_name']}</td>";
1389 echo "<td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></tr>";
1390 $order = $nextorder[$order];
1391 }
1392 echo "</table><br>\n";
1393 finishPortlet();
1394}
1395
1396function renderObjectGroupSummary ()
1397{
1398 global $root;
1399 $summary = getObjectGroupInfo();
1400 if ($summary === NULL)
1401 {
591ff2c4 1402 showError ('getObjectGroupInfo() failed', __FUNCTION__);
e673ee24
DO
1403 return;
1404 }
1405 echo "<table border=0 class=objectview>\n";
1406 echo "<tr><td class=pcleft width='25%'>";
1407
1408 startPortlet ('Summary');
1409 foreach ($summary as $gi)
1410 {
1411 echo "<a href='${root}?page=objgroup&group_id=${gi['id']}'><b>${gi['name']}</b></a> <i>(${gi['count']})</i><br>";
1412 }
1413 finishPortlet();
1414
1415 echo '</td><td class=pcright>';
1416 renderUnmountedObjectsPortlet();
1417 echo '</td><td class=pcright>';
1418 renderProblematicObjectsPortlet();
1419 echo "</td></tr></table>\n";
1420}
1421
1422function renderObjectGroup ($group_id = 0)
1423{
1424 global $root;
1425 $summary = getObjectGroupInfo();
1426 if ($summary == NULL)
1427 {
591ff2c4 1428 showError ('getObjectGroupInfo() failed', __FUNCTION__);
e673ee24
DO
1429 return;
1430 }
1431 $objects = getObjectList ($group_id);
1432 if ($objects === NULL)
1433 {
591ff2c4 1434 showError ('getObjectList() failed', __FUNCTION__);
e673ee24
DO
1435 return;
1436 }
1437 echo "<table border=0 class=objectview>\n";
1438 echo "<tr><td class=pcleft width='25%'>";
1439
1440 startPortlet ('All objects');
1441 foreach ($summary as $gi)
1442 {
1443 echo "<a href='${root}?page=objgroup&group_id=${gi['id']}'><b>${gi['name']}</b></a> <i>(${gi['count']})</i><br>";
1444 }
1445 finishPortlet();
1446
1447 echo '</td><td class=pcright>';
1448
1449 startPortlet ('Object group');
1450 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
18d94c29 1451 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Rack</th></tr>';
e673ee24
DO
1452 $order = 'odd';
1453 global $nextorder;
1454 foreach ($objects as $obj)
1455 {
1456 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1457 echo "<td>${obj['label']}</td>";
1458 echo "<td>${obj['asset_no']}</td>";
18d94c29 1459 echo "<td>${obj['barcode']}</td>";
e673ee24
DO
1460 if ($obj['rack_id'])
1461 echo "<td><a href='${root}?page=rack&rack_id=${obj['rack_id']}'>${obj['Rack_name']}</a></td>";
1462 else
1463 echo '<td>Unmounted</td>';
1464 echo '</tr>';
1465 $order = $nextorder[$order];
1466 }
1467 echo '</table>';
1468 finishPortlet();
1469
1470 echo "</td></tr></table>";
1471}
1472
1473function renderEmptyPortsSelect ($port_id, $type_id)
1474{
1475 $ports = getEmptyPortsOfType($type_id);
1476 usort($ports, 'sortEmptyPorts');
1477 foreach ($ports as $port)
1478 {
1479 if ($port_id == $port['Port_id'])
1480 continue;
1481 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";
1482 }
1483}
1484
1485function renderObjectAddressesAndNames ()
1486{
1487 $addresses = getObjectAddressesAndNames();
1488 usort($addresses, 'sortObjectAddressesAndNames');
1489 foreach ($addresses as $address)
1490 {
1491 echo "<option value='${address['ip']}' onclick='getElementById(\"ip\").value=\"${address['ip']}\";'>${address['object_name']} ${address['name']} ${address['ip']}</option>\n";
1492 }
1493}
1494
1495// History viewer for history-enabled simple dictionaries.
1496function renderHistory ($object_type, $object_id)
1497{
1498 switch ($object_type)
1499 {
1500 case 'row':
1501 $query = "select ctime, user_name, name, deleted, comment from RackRowHistory where id = ${object_id} order by ctime";
1502 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>is deleted?</th><th>rack row comment</th></tr>';
1503 $extra = 4;
1504 break;
1505 case 'rack':
1506 $query =
1507 "select ctime, user_name, rh.name, rh.deleted, d.dict_value as name, rh.height, rh.comment " .
1508 "from RackHistory as rh left join Dictionary as d on rh.row_id = d.dict_key " .
1509 "natural join Chapter " .
1510 "where chapter_name = 'RackRow' and rh.id = ${object_id} order by ctime";
1511 $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>';
1512 $extra = 6;
1513 break;
1514 case 'object':
1515 $query =
1516 "select ctime, user_name, name, label, barcode, asset_no, deleted, has_problems, dict_value, comment " .
1517 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key natural join Chapter " .
1518 "where chapter_name = 'RackObjectType' and id=${object_id} order by ctime";
1519 $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>';
1520 $extra = 9;
1521 break;
1522 default:
591ff2c4 1523 showError ("Uknown object type '${object_type}'", __FUNCTION__);
e673ee24
DO
1524 return;
1525 }
1526 global $dbxlink;
1527 $result = $dbxlink->query ($query);
1528 if ($result == NULL)
1529 {
591ff2c4 1530 showError ('SQL query failed', __FUNCTION__);
e673ee24
DO
1531 return;
1532 }
1533 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1534 $order = 'odd';
1535 global $nextorder;
1536 echo $header;
1537 while ($row = $result->fetch (PDO::FETCH_NUM))
1538 {
1539 echo "<tr class=row_${order}><td>${row[0]}</td>";
1540 for ($i = 1; $i <= $extra; $i++)
1541 echo "<td>" . $row[$i] . "</td>";
1542 echo "</tr>\n";
1543 $order = $nextorder[$order];
1544 }
1545 echo "</table><br>\n";
1546}
1547
1548function renderRackspaceHistory ()
1549{
1550 global $root, $nextorder, $pageno, $tabno;
1551 $order = 'odd';
1552 $history = getRackspaceHistory();
1553 // Show the last operation by default.
1554 if (isset ($_REQUEST['op_id']))
1555 $op_id = $_REQUEST['op_id'];
1556 elseif (isset ($history[0]['mo_id']))
1557 $op_id = $history[0]['mo_id'];
1558 else $op_id = NULL;
1559
1560 $omid = NULL;
1561 $nmid = NULL;
1562 $object_id = 1;
1563 if ($op_id)
1564 list ($omid, $nmid) = getOperationMolecules ($op_id);
1565
1566 // Main layout starts.
1567 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1568
1569 // Left top portlet with old allocation.
1570 echo "<tr><td class=pcleft>";
1571 startPortlet ('Old allocation');
1572 if ($omid)
1573 {
1574 $oldMolecule = getMolecule ($omid);
1575 renderMolecule ($oldMolecule, $object_id);
1576 }
1577 else
1578 echo "nothing";
1579 finishPortlet();
1580
1581 echo '</td><td class=pcright>';
1582
1583 // Right top portlet with new allocation
1584 startPortlet ('New allocation');
1585 if ($nmid)
1586 {
1587 $newMolecule = getMolecule ($nmid);
1588 renderMolecule ($newMolecule, $object_id);
1589 }
1590 else
1591 echo "nothing";
1592 finishPortlet();
1593
1594 echo '</td></tr><tr><td colspan=2>';
1595
1596 // Bottom portlet with list
1597
1598 startPortlet ('Rackspace allocation history');
1599 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1600 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";
1601 foreach ($history as $row)
1602 {
1603 if ($row['mo_id'] == $op_id)
1604 $class = 'hl';
1605 else
1606 $class = "row_${order}";
1607 echo "<tr class=${class}><td><a href='${root}?page=${pageno}&tab=${tabno}&op_id=${row['mo_id']}'>${row['ctime']}</a></td>";
1608 echo "<td>${row['user_name']}</td>";
1609 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
1610 echo "</tr>\n";
1611 $order = $nextorder[$order];
1612 }
1613 echo "</table>\n";
1614 finishPortlet();
1615
1616 echo '</td></tr></table>';
1617
1618}
1619
1620function renderAddressspace ()
1621{
b3c50e6c 1622 global $root, $page;
a7fe7729
DO
1623 echo '<table border=0 class=objectview cellspacing=0 cellpadding=0><tr><td class=pcleft>';
1624
1625 startPortlet ('Subnets');
e673ee24
DO
1626 echo "<table class='widetable' border=0 cellpadding=10 cellspacing=0 align='center'>\n";
1627 $addrspaceList = getAddressspaceList();
119f2ad2 1628 echo "<tr><th>Subnet</th><th>Name</th><th>Utilization</th></tr>";
e673ee24
DO
1629 foreach ($addrspaceList as $iprange)
1630 {
119f2ad2
DO
1631 $range = getIPRange ($iprange['id']);
1632 $total = ($iprange['ip_bin'] | $iprange['mask_bin_inv']) - ($iprange['ip_bin'] & $iprange['mask_bin']) + 1;
1633 $used = count ($range['addrlist']);
1634 echo "<tr><td class=tdleft><a href='${root}?page=iprange&id=${iprange['id']}'>${iprange['ip']}/${iprange['mask']}</a></td>";
1635 echo "<td class=tdleft>${iprange['name']}</td><td class=tdleft>";
1636 renderProgressBar ($used/$total);
1637 echo " ${used}/${total}</td></tr>";
e673ee24
DO
1638 }
1639 echo "</table>\n";
a7fe7729
DO
1640 finishPortlet();
1641
1642 echo "</td>\n<td class=pcright>";
1643
b3c50e6c
DO
1644 startPortlet ('SLB details');
1645 echo "<table border=0 width='100%'><tr>";
1646 foreach (array ('vservices', 'rspools', 'rservers', 'lbs') as $pno)
e57dca7f 1647 echo "<td><h3><a href='${root}?page=${pno}'>" . $page[$pno]['title'] . "</a></h3></td>";
b3c50e6c
DO
1648 echo '</tr></table>';
1649 finishPortlet();
1650
1651 startPortlet ('current SLB setup');
c3bdc503 1652 $summary = getSLBSummary();
4cadac8f
DO
1653#echo '<pre>';
1654#print_r ($summary);
1655#echo '</pre>';
1656 // A single id-keyed array isn't used here to preserve existing
1657 // order of LBs returned by getSLBSummary()
c3bdc503
DO
1658 $lblist = array();
1659 $lbdname = array();
4cadac8f 1660 foreach ($summary as $vipdata)
da04825a 1661 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
c3bdc503
DO
1662 if (!in_array ($lb_object_id, $lblist))
1663 {
1664 $oi = getObjectInfo ($lb_object_id);
1665 $lbdname[$lb_object_id] = $oi['dname'];
1666 $lblist[] = $lb_object_id;
1667 }
1668 if (!count ($summary))
1669 echo 'none configured';
1670 else
1671 {
1672 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
13bffb29 1673 echo "<tr><th>VIP</th><th>Name</th>";
c3bdc503 1674 foreach ($lblist as $lb_object_id)
71b8bda1 1675 echo "<th><a href='${root}?page=object&tab=default&object_id=${lb_object_id}'>" . $lbdname[$lb_object_id] . "</a></th>";
c3bdc503 1676 echo "</tr>\n";
4cadac8f
DO
1677 foreach ($summary as $vsid => $vsdata)
1678 {
b3c50e6c 1679 echo "<tr><td class=tdleft><a href='$root?page=vservice&tab=default&id=${vsid}'>";
8d790216 1680 echo buildVServiceName ($vsdata);
b3c50e6c 1681 echo "</td><td>${vsdata['name']}</td>";
4cadac8f 1682 foreach ($lblist as $lb_object_id)
da04825a
DO
1683 {
1684 echo '<td>';
2b4eee17 1685 if (!isset ($vsdata['lblist'][$lb_object_id]))
da04825a
DO
1686 echo '&nbsp;';
1687 else
1688 foreach ($vsdata['lblist'][$lb_object_id] as $pool_id => $pool_info)
71b8bda1
DO
1689 {
1690 echo $pool_info['size'] . "@(<a href='${root}?page=rspool&id=${pool_id}'>";
2b4eee17 1691 echo $pool_info['name'] . '</a>)';
71b8bda1 1692 }
da04825a
DO
1693 echo '</td>';
1694 }
1695 echo "</tr>\n";
4cadac8f 1696 }
c3bdc503
DO
1697 echo "</table>\n";
1698 }
a7fe7729
DO
1699 finishPortlet ();
1700
1701 echo '</td></tr></table>';
e673ee24
DO
1702}
1703
1704function renderAddNewRange ()
1705{
1706 global $root, $pageno, $tabno;
1707 showMessageOrError();
2a201216 1708
a7fe7729 1709 echo "<center><h2>Add New</h2></center>\n";
2a201216 1710 echo "<table class='widetable' border=0 cellpadding=10 align='center'>\n";
2dee289e 1711 echo "<tr><th>Address range</th><th>Name</th><th>C&gt;*</th><th>&nbsp;</th></tr>\n";
2a201216
DY
1712 echo "<form name='add_new_range' action='process.php'>\n";
1713 echo "<input type=hidden name=op value=addRange>\n";
1714 echo "<input type=hidden name=page value='${pageno}'>\n";
1715 echo "<input type=hidden name=tab value='${tabno}'>\n";
7059c1d2
DO
1716 echo "<tr><td class='tdcenter'><input type=text name='range' size=18 class='live-validate' tabindex=1></td>\n";
1717 echo "<td class='tdcenter'><input type=text name='name' size='20' tabindex=2></td>\n";
1718 echo "<td class='tdcenter'><input type=checkbox name='is_bcast' tabindex=3 checked></td>\n";
1719 echo "<td class='tdcenter'><input type=submit value='Add a new range' tabindex=4></td></tr>\n";
2a201216
DY
1720 echo "</form></table><br><br>\n";
1721
a7fe7729 1722 echo "<center><h2>Manage Existing</h2></center>\n";
2a201216 1723 echo "<table class='widetable' border=0 cellpadding=10 align='center'>\n";
e673ee24
DO
1724 $addrspaceList = getAddressspaceList();
1725 echo "<tr><th>&nbsp;</th><th>Address range</th><th>Name</th><th>Total/used addresses</th></tr>";
1726 foreach ($addrspaceList as $iprange)
1727 {
1728 $range = getIPRange($iprange['id']);
dc462202 1729 $usedips = count ($range['addrlist']);
e673ee24
DO
1730 echo "<tr>";
1731 if ($usedips == 0)
1732 {
1733 echo "<td><a href='process.php?op=delRange&page=${pageno}&tab=${tabno}&id=${iprange['id']}'>";
1734 printImageHREF ('delete', 'Delete this IP range');
1735 echo "</a></td>\n";
1736 }
1737 else
1738 echo "<td>&nbsp</td>";
1739 echo "<td><a href='${root}?page=iprange&id=${iprange['id']}'>${iprange['ip']}/${iprange['mask']}</a></td><td>${iprange['name']}</td><td>";
1740 echo ($iprange['ip_bin'] | $iprange['mask_bin_inv']) - ($iprange['ip_bin'] & $iprange['mask_bin'])+1;
1741 echo "/";
1742 echo $usedips;
2a201216 1743 #echo "</td></tr></table>";
e673ee24
DO
1744 echo "</td></tr>";
1745 }
e673ee24
DO
1746}
1747
1748function renderIPRange ()
1749{
1750 global $root;
b901bf1f 1751 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
e673ee24
DO
1752 $id = $_REQUEST['id'];
1753 if (isset($_REQUEST['pg']))
1754 $page = $_REQUEST['pg'];
1755 else
1756 $page=0;
1757
e673ee24
DO
1758 $range = getIPRange($id);
1759 echo "<center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></center>\n";
1760
e673ee24
DO
1761 $startip = $range['ip_bin'] & $range['mask_bin'];
1762 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
1763 $realstartip = $startip;
1764 $realendip = $endip;
1765 $numpages = 0;
1766 if($endip - $startip > $maxperpage)
1767 {
e673ee24
DO
1768 $numpages = ($endip - $startip)/$maxperpage;
1769 $startip = $startip + $page * $maxperpage;
1770 $endip = $startip + $maxperpage-1;
1771 }
1772 echo "<center>";
b901bf1f
DO
1773 if ($numpages)
1774 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
e673ee24
DO
1775 for ($i=0; $i<$numpages; $i++)
1776 {
1777 if ($i == $page)
1778 echo "<b>$i</b> ";
1779 else
1780 echo "<a href='${root}?page=iprange&id=$id&pg=$i'>$i</a> ";
1781 }
1782 echo "</center>";
1783
1784 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center'>\n";
1785 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
1786
1787
1788 for($ip = $startip; $ip<=$endip; $ip++)
1789 {
dcee8072 1790 if (isset ($range['addrlist'][$ip]))
e673ee24
DO
1791 {
1792 $numshared = countRefsOfType($range['addrlist'][$ip]['references'], 'shared', 'eq');
1793 $numreg = countRefsOfType($range['addrlist'][$ip]['references'], 'regular', 'eq');
1794 $numvirt = countRefsOfType($range['addrlist'][$ip]['references'], 'virtual', 'eq');
1795
1796 $addr = $range['addrlist'][$ip];
1797 if ( ($numshared > 0 && $numreg > 0) || $numreg > 1 )
1798 echo "<tr class='trwarning'>";
1799 elseif ( $addr['reserved'] == 'yes' and $numshared+$numreg+$numvirt > 0)
1800 echo "<tr class='trwarning'>";
1801 elseif ( $addr['reserved'] == 'yes')
1802 echo "<tr class='trbusy'>";
1803 elseif ( $numshared > 0 || $numreg > 0)
1804 echo "<tr class='trbusy'>";
1805 else
1806 echo "<tr>";
1807
1808 echo "<td><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td><td>${addr['name']}</td><td>";
1809 if ( $addr['reserved'] == 'yes')
1810 echo "<b>Reserved;</b> ";
1811 foreach ($range['addrlist'][$ip]['references'] as $ref)
1812 {
db88e2de
DO
1813 echo "<a href='${root}?page=object&object_id=${ref['object_id']}'>";
1814 echo $ref['name'] . (empty ($ref['name']) ? '' : '@');
1815 echo "${ref['object_name']}</a>; ";
e673ee24
DO
1816 }
1817 echo "</td></tr>\n";
1818 }
1819 else
1820 {
1821 echo "<tr><td><a href='${root}?page=ipaddress&ip=".long2ip($ip)."'>".long2ip($ip)."</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>\n";
1822 }
1823 }
1824
1825 echo "</table>";
1826
1827}
1828
1829function renderIPRangeProperties ()
1830{
1831 global $pageno, $tabno;
1832 $id = $_REQUEST['id'];
1833 showMessageOrError();
1834 $range = getIPRange($id);
1835 echo "<center><h1>${range['ip']}/${range['mask']}</h1></center>\n";
1836 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
1837 echo "<form action='process.php'><input type=hidden name=op value=editRange>";
1838 echo "<input type=hidden name=page value='${pageno}'>\n";
1839 echo "<input type=hidden name=tab value='${tabno}'>\n";
1840 echo "<input type=hidden name=id value='${id}'>";
1841 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>";
1842 echo "</table>\n";
1843
1844}
1845
1846function renderIPAddress ()
1847{
1848 global $root;
1849 $ip = $_REQUEST['ip'];
1850 $address = getIPAddress($ip);
1851 echo "<center><h1>$ip</h1>";
1852 if ($address['exists'] == 1)
1853 echo "<h2>${address['name']}</h2>";
1854 echo "</center>\n";
1855
1856// echo "<table width='100%' cesspadding=5 cellspacing=0 border=0 align='center'>";
1857// echo "<tr valign='top'><td>";
1858
1859 startPortlet ('Address assignment');
1860 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
1861 echo "<tr><th>Object name</th><th>Interface name</th><th>Interface type</th></tr>\n";
1862
1863 $numshared = countRefsOfType($address['bonds'], 'shared', 'eq');
1864 $numreg = countRefsOfType($address['bonds'], 'regular', 'eq');
1865 $numvirt = countRefsOfType($address['bonds'], 'virtual', 'eq');
1866
1867
1868 if ( ($numshared > 0 && $numreg > 0) || $numreg > 1 )
1869 $class='trwarning';
1870 elseif ( $address['reserved'] == 'yes' and $numshared+$numreg+$numvirt > 0)
1871 $class='trwarning';
1872 else
1873 $class='';
1874
1875
1876
1877 if ($address['reserved'] == 'yes')
1878 echo "<tr class='$class'><td colspan='3'><b>RESERVED</b></td></tr>";
1879 foreach ($address['bonds'] as $bond)
1880 {
1881 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>";
1882 switch ($bond['type'])
1883 {
1884 case 'virtual':
1885 echo "Virtual";
1886 break;
1887 case 'shared':
1888 echo "Shared";
1889 break;
1890 case 'regular':
1891 echo "Regular";
1892 break;
1893 }
1894 echo "</b></td></tr>\n";
1895 }
1896 echo "</table><br><br>";
1897 finishPortlet();
1898
1899// echo "</td><td>";
1900// echo "</td></tr></table>";
1901}
1902
1903function renderIPAddressProperties ()
1904{
1905 global $pageno, $tabno;
1906 $ip = $_REQUEST['ip'];
1907 showMessageOrError();
1908 $address = getIPAddress($ip);
1909 echo "<center><h1>$ip</h1></center>\n";
1910 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
1911 echo "<form action='process.php'><input type=hidden name=op value=editAddress>";
1912 echo "<input type=hidden name=page value='${pageno}'>\n";
1913 echo "<input type=hidden name=tab value='${tabno}'>\n";
1914 echo "<input type=hidden name=ip value='${ip}'>";
1915 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='".($address['exists']==1?$address['name']:'')."'></tr>";
1916 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ".($address['exists']==1?(($address['reserved']=='yes')?'checked':''):'')."></tr>";
1917 echo "<tr><td colspan=2 class='tdcenter'><input type=submit value='Update address'></td></form></tr>";
1918 echo "</table>\n";
1919
1920}
1921
1922function renderIPAddressAssignment ()
1923{
1924 global $pageno, $tabno, $root;
1925 $ip = $_REQUEST['ip'];
1926 $address = getIPAddress($ip);
1927
1928 showMessageOrError();
1929 echo "<center><h1>$ip</h1></center>\n";
1930
1931
1932 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
1933 echo "<tr><th>&nbsp;</th><th>Object name</th><th>Interface name</th><th>Interface type</th><th>&nbsp;</th></tr>\n";
1934
1935 $numshared = countRefsOfType($address['bonds'], 'shared', 'eq');
1936 $numreg = countRefsOfType($address['bonds'], 'regular', 'eq');
1937 $numvirt = countRefsOfType($address['bonds'], 'virtual', 'eq');
1938
1939
1940 if ( ($numshared > 0 && $numreg > 0) || $numreg > 1 )
1941 $class='trwarning';
1942 elseif ( $address['reserved'] == 'yes' and $numshared+$numreg+$numvirt > 0)
1943 $class='trwarning';
1944 else
1945 $class='';
1946
1947
1948
1949 if ($address['reserved'] == 'yes')
1950 echo "<tr class='$class'><td colspan='5'><b>RESERVED</b></td></tr>";
1951 foreach ($address['bonds'] as $bond)
1952 {
1953 echo "<tr class='$class'><form action='process.php'>";
1954 echo "<input type=hidden name=op value='editBondForAddress'>";
1955 echo "<input type=hidden name=page value='${pageno}'>";
1956 echo "<input type=hidden name=tab value='${tabno}'>";
1957 echo "<input type=hidden name=ip value='$ip'>";
1958 echo "<input type=hidden name=object_id value='${bond['object_id']}'>";
1959 echo "<td><a href='process.php?op=delIpAssignment&page=${pageno}&tab=${tabno}&ip=$ip&object_id=${bond['object_id']}'>";
1960 printImageHREF ('delete', 'Unallocate address');
1961 echo "</a></td>";
1962 echo "<td><a href='${root}?page=object&object_id=${bond['object_id']}'>${bond['object_name']}</td>";
1963 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td>";
1964 echo "<td><select name='bond_type'>";
1965 switch ($bond['type'])
1966 {
1967 case 'virtual':
1968 echo "<option value='regular'>Regular</option>";
1969 echo "<option value='virtual' selected>Virtual</option>";
1970 echo "<option value='shared'>Shared</option>";
1971 break;
1972 case 'shared':
1973 echo "<option value='regular'>Regular</option>";
1974 echo "<option value='virtual'>Virtual</option>";
1975 echo "<option value='shared' selected>Shared</option>";
1976 break;
1977 case 'regular':
1978 echo "<option value='regular' selected>Regular</option>";
1979 echo "<option value='virtual'>Virtual</option>";
1980 echo "<option value='shared'>Shared</option>";
1981 break;
1982 }
1983 echo "</select></td><td><input type='submit' value='OK'></td></form></tr>\n";
1984 }
1985 echo "<form action='process.php'><input type='hidden' name='op' value='bindObjectToIp'>";
1986 echo "<input type=hidden name=page value='${pageno}'>\n";
1987 echo "<input type=hidden name=tab value='${tabno}'>\n";
1988 echo "<input type='hidden' name='ip' value='$ip'>";
1989 echo "<td colspan=2><select name='object_id'>";
1990
1991 foreach (array(1, 4, 7, 8, 12, 14) as $type)
1992 {
1993 //get all Balck Boxes, Servers, Routers, Switches, UPS, Modems
1994 $objects = getObjectList($type);
1995 foreach ($objects as $object)
1996 echo "<option value='${object['id']}'>${object['dname']}</option>";
1997 }
1998
1999 echo "</select></td><td><input type='text' name='bond_name' value='' size=10></td>";
2000 echo "<td><select name='bond_type'><option value='regular'>Regular</option><option value='virtual'>Virtual</option><option value='shared'>Shared</option></select></td>";
2001 echo "<td><input type='submit' value='Assign address'></td></form></tr>";
2002 echo "</table><br><br>";
2003
2004}
2005
2006function renderIPAddressPortForwarding ($object_id=0)
2007{
2008 global $pageno, $tabno, $root;
2009
2010 $info = getObjectInfo ($object_id);
2011 $forwards = getObjectForwards ($object_id);
2012 $addresses = getObjectAddresses ($object_id);
2013 showMessageOrError();
f28fbe8b 2014 echo "<center><h2>locally performed NAT</h2></center>";
e673ee24
DO
2015
2016 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 2017 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th></tr>\n";
e673ee24
DO
2018
2019 foreach ($forwards['out'] as $pf)
2020 {
2021 $class='trwarning';
2022 $name='';
2023 foreach ($addresses as $addr)
2024 if ($addr['ip'] == $pf['localip'])
2025 {
2026 $class='';
2027 $name = $addr['name'];
2028 break;
2029 }
2030
2031 echo "<tr class='$class'>";
2032 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}'><img src='${root}/pix/delete_s.gif' title='Delete port forwarding' border=0 width=16 height=16></a></td>";
f28fbe8b
DO
2033 echo "<td>${pf['proto']}/${name}: <a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}";
2034 if (!empty ($pf['local_addr_name']))
2035 echo ' (' . $pf['local_addr_name'] . ')';
2036 echo "</td>";
e673ee24
DO
2037 echo "<td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2038
2039 $address=getIPAddress($pf['remoteip']);
2040
2041 echo "<td class='description'>";
f28fbe8b
DO
2042 if (count ($address['bonds']))
2043 foreach($address['bonds'] as $bond)
2044 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
2045 elseif (!empty ($pf['remote_addr_name']))
2046 echo '(' . $pf['remote_addr_name'] . ')';
e673ee24
DO
2047 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>";
2048 echo "</tr>";
2049 }
2050 echo "<form action='process.php'><input type='hidden' name='op' value='forwardPorts'>";
2051 echo "<input type='hidden' name='object_id' value='$object_id'>";
2052 echo "<input type=hidden name=page value='${pageno}'>\n";
2053 echo "<input type=hidden name=tab value='${tabno}'>\n";
436605a7
DO
2054 echo "<tr align='center'><td colspan=2>";
2055 printSelect (readChapter ('Protocols'), 'proto');
52c3543f 2056 echo "<select name='localip' tabindex=1>";
e673ee24
DO
2057
2058 foreach ($addresses as $addr)
09992c16
DO
2059 echo "<option value='${addr['ip']}'>" . (empty ($addr['name']) ? '' : "${addr['name']}: ") .
2060 "${addr['ip']}" . (empty ($addr['address_name']) ? '' : " (${addr['address_name']})") . "</option>";
e673ee24 2061
52c3543f
DO
2062 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2063 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
e673ee24 2064 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\");'><img src='${root}/pix/find.png' title='Find object' border=0 height=16 width=16></a>";
52c3543f
DO
2065 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2066 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5> <input type='submit' value='Create Forwarding' tabindex=6></td></tr>";
e673ee24
DO
2067 echo "</form>";
2068
2069 echo "</table><br><br>";
2070
2071
f28fbe8b 2072 echo "<center><h2>arriving NAT connections</h2></center>";
e673ee24
DO
2073 echo "<table class='widetable' cesspadding=5 cellspacing=0 border=0 align='center'>\n";
2074 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2075
2076 foreach ($forwards['in'] as $pf)
2077 {
2078 echo "<tr>";
2079
2080 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}'><img src='${root}/pix/delete_s.gif' title='Delete port forwarding' border=0 width=16 height=16></a></td>";
2081 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
2082 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
2083 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2084 echo "<td class='description'>${pf['description']}</td></tr>";
2085 }
2086
2087// echo "<form action='process.php'><input type='hidden' name='op' value='forwardPorts'>";
2088// echo "<input type='hidden' name='object_id' value='$object_id'>";
2089// echo "<input type=hidden name=page value='${pageno}'>\n";
2090// echo "<input type=hidden name=tab value='${tabno}'>\n";
2091// 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'>";
2092// foreach ($addresses as $addr)
2093// echo "<option value='${addr['ip']}'>${addr['ip']}</option>";
2094//
2095// 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>";
2096// echo "</form>";
2097 echo "</table><br><br>";
2098
2099
2100}
2101
2102
2103function renderAddMultipleObjectsForm ()
2104{
2105 global $pageno, $tabno, $nextorder;
2106
2107 $type_id = array();
7f791d1d 2108 $global_type_id = 0;
e673ee24
DO
2109 $name = array();
2110 $asset_no = array();
2111 $keepvalues = FALSE;
7f791d1d 2112 $log = array();
e673ee24 2113 // Look for current submit.
7f791d1d 2114 if (isset ($_REQUEST['got_fast_data']))
e673ee24
DO
2115 {
2116 $keepvalues = TRUE;
9c0b0016
DO
2117 $max = getConfigVar ('MASSCOUNT');
2118 for ($i = 0; $i < $max; $i++)
e673ee24
DO
2119 {
2120 if (!isset ($_REQUEST["${i}_object_type_id"]))
2121 {
2122 $log[] = array ('code' => 'error', 'message' => "Submitted form is invalid at line " . $i + 1);
2123 break;
2124 }
2125 assertUIntArg ("${i}_object_type_id", TRUE);
2126 assertStringArg ("${i}_object_name", TRUE);
2127 assertStringArg ("${i}_object_label", TRUE);
2128 assertStringArg ("${i}_object_asset_no", TRUE);
2129 assertStringArg ("${i}_object_barcode", TRUE);
2130 $type_id[$i] = $_REQUEST["${i}_object_type_id"];
2131 // Save user input for possible rendering.
2132 $name[$i] = $_REQUEST["${i}_object_name"];
2133 $label[$i] = $_REQUEST["${i}_object_label"];
2134 $asset_no[$i] = $_REQUEST["${i}_object_asset_no"];
2135 $barcode[$i] = $_REQUEST["${i}_object_barcode"];
2136
2137 // It's better to skip silently than printing a notice.
2138 if ($type_id[$i] == 0)
2139 continue;
2140 if (commitAddObject ($name[$i], $label[$i], $barcode[$i], $type_id[$i], $asset_no[$i]) === TRUE)
2141 $log[] = array ('code' => 'success', 'message' => "Added new object '${name[$i]}'");
2142 else
4d2e93f2 2143 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitAddObject() failed');
e673ee24 2144 }
e673ee24 2145 }
7f791d1d
DO
2146 elseif (isset ($_REQUEST['got_very_fast_data']))
2147 {
2148 $keepvalues = TRUE;
2149 assertUIntArg ('global_type_id', TRUE);
2150 assertStringArg ('namelist', TRUE);
2151 $global_type_id = $_REQUEST['global_type_id'];
2152 if ($global_type_id == 0)
2153 {
2154 if (!empty ($_REQUEST['namelist']))
2155 $log[] = array ('code' => 'error', 'message' => 'Object type is not selected, check the form below');
2156 else
2157 $log[] = array ('code' => 'error', 'message' => 'Empty form has been ignored. Cheers.');
2158 }
2159 else
2160 {
2161 // The name extractor below was stolen from ophandlers.php:addMultiPorts()
2162 $names1 = explode ('\n', $_REQUEST['namelist']);
2163 $names2 = array();
2164 foreach ($names1 as $line)
2165 {
2166 $parts = explode ('\r', $line);
2167 reset ($parts);
2168 if (empty ($parts[0]))
2169 continue;
2170 else
2171 $names2[] = rtrim ($parts[0]);
2172 }
2173 foreach ($names2 as $cname)
2174 if (commitAddObject ($cname, '', '', $global_type_id, '') === TRUE)
2175 $log[] = array ('code' => 'success', 'message' => "Added new object '${cname}'");
2176 else
2177 $log[] = array ('code' => 'error', 'message' => "Could not add '${cname}'");
2178 }
2179 }
2180 printLog ($log);
e673ee24
DO
2181
2182 // Render a form for the next.
2183 $typelist = getObjectTypeList();
4c330a14 2184 $typelist[0] = 'select type...';
7f791d1d
DO
2185
2186 startPortlet ('Fast way');
e673ee24
DO
2187 echo '<form>';
2188 echo "<input type=hidden name=page value=${pageno}>";
2189 echo "<input type=hidden name=tab value=${tabno}>";
2190 echo '<table border=0 align=center>';
2191 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th></tr>\n";
7f791d1d 2192 // If a user forgot to select object type on input, we keep his
e673ee24 2193 // previous input in the form.
9c0b0016
DO
2194 $max = getConfigVar ('MASSCOUNT');
2195 for ($i = 0; $i < $max; $i++)
e673ee24 2196 {
7f791d1d 2197 echo '<tr><td>';
e673ee24
DO
2198 printSelect ($typelist, "${i}_object_type_id", 0);
2199 echo '</td>';
2200 echo "<td><input type=text size=30 name=${i}_object_name";
2201 if ($keepvalues and $type_id[$i] == 0)
2202 echo " value='${name[$i]}'";
2203 echo "></td>";
2204 echo "<td><input type=text size=30 name=${i}_object_label";
2205 if ($keepvalues and $type_id[$i] == 0)
2206 echo " value='${label[$i]}'";
2207 echo "></td>";
2208 echo "<td><input type=text size=20 name=${i}_object_asset_no";
2209 if ($keepvalues and $type_id[$i] == 0)
2210 echo " value='${asset_no[$i]}'";
2211 echo "></td>";
2212 echo "<td><input type=text size=10 name=${i}_object_barcode";
2213 if ($keepvalues and $type_id[$i] == 0)
2214 echo " value='${barcode[$i]}'";
2215 echo "></td>";
2216 echo "</tr>\n";
e673ee24 2217 }
7f791d1d 2218 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Create'></td></tr>\n";
e673ee24
DO
2219 echo "</form></table>\n";
2220 finishPortlet();
7f791d1d
DO
2221
2222 startPortlet ('Very fast way');
2223 echo '<form>';
2224 echo "<input type=hidden name=page value=${pageno}>";
2225 echo "<input type=hidden name=tab value=${tabno}>";
2226 echo 'For each line shown below create an object of type ';
2227 printSelect ($typelist, "global_type_id", 0);
2228 echo " <input type=submit name=got_very_fast_data value='Go!'><br>\n";
2229 echo "<textarea name=namelist cols=40 rows=25>\n";
2230 if ($keepvalues and $global_type_id == 0)
2231 echo $_REQUEST['namelist'];
2232 echo "</textarea></form>\n";
2233 finishPortlet();
e673ee24
DO
2234}
2235
2236function printGreeting ()
2237{
59cd003e 2238 global $remote_username, $accounts, $root;
e673ee24 2239 $account = $accounts[$remote_username];
4eb5efb7 2240 echo "Hello, ${account['user_realname']}. This is RackTables " . CODE_VERSION . ". Click <a href='${root}?logout'>here</a> to logout.";
e673ee24
DO
2241}
2242
2243function renderSearchResults ()
2244{
2245 global $remote_username, $root;
2246 $terms = trim ($_REQUEST['q']);
2247 if (empty ($terms))
2248 {
591ff2c4 2249 showError ('Search string cannot be empty.', __FUNCTION__);
e673ee24
DO
2250 return;
2251 }
2252 if (!authorized ($remote_username, 'object', 'default'))
2253 {
591ff2c4 2254 showError ('You are not authorized for viewing information about objects.', __FUNCTION__);
e673ee24
DO
2255 return;
2256 }
2257 // If we search for L2 address, we can either find one or find none.
2258 if
2259 (
2260 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
2261 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
2262 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)
2263 )
2264 // Search for L2 address.
2265 {
2266 $result = searchByl2address ($terms);
2267 if ($result !== NULL)
2268 {
2269 echo "<script language='Javascript'>document.location='${root}?page=object";
2270 echo "&hl_port_id=${result['port_id']}";
2271 echo "&object_id=${result['object_id']}';//</script>";
2272 }
2273 else
2274 echo "L2 address '${terms}' not found!";
2275 }
2276 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))
2277 // STP bridge ID: bridge priotity + port MAC address. Cut off first 4 chars and look for MAC address.
2278 {
2279 $terms = substr ($terms, 4);
2280 $result = searchByl2address ($terms);
2281 if ($result !== NULL)
2282 {
2283 echo "<script language='Javascript'>document.location='${root}?page=object";
2284 echo "&hl_port_id=${result['port_id']}";
2285 echo "&object_id=${result['object_id']}';//</script>";
2286 }
2287 else
2288 echo "L2 address '${terms}' not found!";
2289 }
2290 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))
2291 // Search for IP address.
2292 {
2293 $result = getRangeByIp ($terms);
2294 if ($result !== NULL)
2295 {
2296 echo "<script language='Javascript'>document.location='${root}?page=ipaddress";
2297 echo "&ip=${terms}";
2298 echo "';//</script>";
2299 }
2300 else
2301 echo "IP address '${terms}' not found!";
2302 return;
2303 }
2304 else
2305 // Search for objects.
2306 {
2307 $objects = getSearchResults ($terms);
2308 if (count ($objects) == 1)
2309 {
2310 $obj = current ($objects);
2311 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${obj['id']}';//</script>";
2312 }
2313 elseif (count ($objects) > 1)
2314 {
2315 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2316 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>barcode</th></tr>';
2317 $order = 'odd';
2318 global $nextorder;
2319 foreach ($objects as $obj)
2320 {
2321 echo "<tr class=row_${order}><td><a href=\"${root}?page=object&object_id=${obj['id']}\">${obj['dname']}</a></td>";
2322 echo "<td>${obj['label']}</td>";
2323 echo "<td>${obj['asset_no']}</td>";
2324 echo "<td>${obj['barcode']}</td></tr>";
2325 $order = $nextorder[$order];
2326 }
2327 echo '</table>';
2328 }
2329 else
2330 echo "Object '${terms}' not found!";
2331 }
2332}
2333
2334// This function prints a table of checkboxes to aid the user in toggling mount atoms
2335// from one state to another. The first argument is rack data as
2336// produced by getRackData(), the second is the value used for the 'unckecked' state
2337// and the third is the value used for 'checked' state.
2338// Usage contexts:
2339// for mounting an object: printAtomGrid ($data, 'F', 'T')
2340// for changing rack design: printAtomGrid ($data, 'A', 'F')
2341// for adding rack problem: printAtomGrid ($data, 'F', 'U')
2342// for adding object problem: printAtomGrid ($data, 'T', 'W')
2343
2344function renderAtomGrid ($data)
2345{
2346 $rack_id = $data['id'];
2347 for ($unit_no = $data['height']; $unit_no > 0; $unit_no--)
2348 {
2349 echo "<tr><th>${unit_no}</th>";
2350 for ($locidx = 0; $locidx < 3; $locidx++)
2351 {
2352 $state = $data[$unit_no][$locidx]['state'];
2353 echo "<td class=state_${state}";
2354 if (isset ($data[$unit_no][$locidx]['hl']))
2355 echo $data[$unit_no][$locidx]['hl'];
2356 echo ">";
2357 if (!($data[$unit_no][$locidx]['enabled'] === TRUE))
2358 echo '<input type=checkbox disabled>';
2359 else
2360 echo "<input type=checkbox" . $data[$unit_no][$locidx]['checked'] . " name=atom_${rack_id}_${unit_no}_${locidx}>";
2361 echo '</td>';
2362 }
2363 echo "</tr>\n";
2364 }
2365}
2366
2367function renderPermissions ()
2368{
2369 startPortlet ('User permissions');
2370 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2371 echo "<tr><th>Username</th><th>Page</th><th>Tab</th><th>Access</th></tr>";
2372 global $perms, $nextorder;
2373 $order = 'odd';
2374 foreach ($perms as $username => $pages)
2375 foreach ($pages as $page => $tabs)
2376 foreach ($tabs as $tab => $access)
2377 {
2378 echo "<tr class=row_${order}><td class=tdleft>$username</td><td>$page</td><td>$tab</td><td>$access</td></tr>\n";
2379 $order = $nextorder[$order];
2380 }
2381 echo "</table>\n";
2382 finishPortlet();
2383}
2384
2385function renderAccounts ()
2386{
2387 global $nextorder, $accounts;
2388 startPortlet ('User accounts');
2389 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2390 echo "<tr><th class=tdleft>Username</th><th class=tdleft>Real name</th></tr>";
2391 $order = 'odd';
2392 foreach ($accounts as $user)
2393 {
2394 echo "<tr class=row_${order}><td class=tdleft>${user['user_name']}</td><td class=tdleft>${user['user_realname']}</td></li>";
2395 $order = $nextorder[$order];
2396 }
2397 echo '</table>';
2398 finishPortlet();
2399}
2400
2401function renderAccountsEditForm ()
2402{
2403 global $root, $pageno, $tabno, $accounts;
2404 startPortlet ('User accounts');
2405 showMessageOrError();
2406 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2407 echo "<tr><th>op</th><th>Username</th><th>Real name</th><th>Password</th><th>&nbsp;</th></tr>\n";
2408 foreach ($accounts as $account)
2409 {
2410 echo "<form action='${root}process.php'>";
2411 echo "<input type=hidden name=op value=updateAccount>";
2412 echo "<input type=hidden name=page value='${pageno}'>\n";
2413 echo "<input type=hidden name=tab value='${tabno}'>\n";
2414 echo "<input type=hidden name=id value='${account['user_id']}'><tr>";
2415 echo "<td>";
2416 if ($account['user_enabled'] == 'yes' && $account['user_id'] != 1)
2417 {
2418 echo "<a href='${root}process.php?op=disableAccount&page=${pageno}&tab=${tabno}&id=${account['user_id']}'>";
2419 printImageHREF ('blockuser', 'disable account');
2420 echo "</a>\n";
2421 }
2422 if ($account['user_enabled'] == 'no' && $account['user_id'] != 1)
2423 {
2424 echo "<a href='${root}process.php?op=enableAccount&page=${pageno}&tab=${tabno}&id=${account['user_id']}'>";
2425 printImageHREF ('unblockuser', 'enable account');
2426 echo "</a>\n";
2427 }
2428 // Otherwise skip icon.
2429 echo "</td>";
2430 echo "<td><input type=text name=username value='${account['user_name']}' size=16></td>";
2431 echo "<td><input type=text name=realname value='${account['user_realname']}' size=24></td>";
2432 echo "<td><input type=password name=password value='${account['user_password_hash']}' size=64></td>";
2433 echo "<td><input type='submit' value='OK'></td>";
2434 echo "</form></tr>\n";
2435 }
2436 echo "<form action='${root}process.php' method=post><tr>";
2437 echo "<input type=hidden name=op value=createAccount>\n";
2438 echo "<input type=hidden name=page value='${pageno}'>\n";
2439 echo "<input type=hidden name=tab value='${tabno}'>\n";
2440 echo "<td colspan=2><input type=text size=16 name=username tabindex=100></td>\n";
2441 echo "<td><input type=text size=24 name=realname tabindex=101></td>";
2442 echo "<td><input type=password size=64 name=password tabindex=102></td>";
2443 echo "<td colspan=4><input type=submit value='Create account' tabindex=103></td></tr></form>";
2444 echo "</table><br>\n";
2445 finishPortlet();
2446}
2447
2448function printChildrenAsOptions ($root, $depth = 0)
2449{
2450 echo "<option value=${root['title']}>";
2451 if ($depth == 0)
2452 echo '* ';
2453 for ($i = 0; $i < $depth; $i++)
2454 echo '-- ';
2455 echo $root['title'];
2456 echo "</option>\n";
2457 foreach ($root['kids'] as $kid)
2458 printChildrenAsOptions ($kid, $depth + 1);
2459}
2460
2461// 1. Find all parentless pages.
2462// 2. For each of them recursively find all children.
2463// 3. Output the tree with recursion tree display.
2464function printPagesTree ()
2465{
2466 global $page;
2467 echo '<pre>';
2468 foreach ($page as $ctitle => $cpage)
2469 if (!isset ($cpage['parent']))
2470 {
2471 $croot['title'] = $ctitle;
2472 $croot['kids'] = getAllChildPages ($ctitle);
2473 printChildrenAsOptions ($croot);
2474 }
2475 echo '</pre>';
2476}
2477
2478function renderPermissionsEditForm ()
2479{
2480 global $root, $pageno, $tabno, $perms, $accounts;
2481 startPortlet ('User permissions');
2482 showMessageOrError();
2483 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
2484 echo "<tr><th>&nbsp;</th><th>Username</th><th>Page</th><th>Tab</th><th>Access</th></tr>\n";
2485 foreach ($perms as $username => $pages)
2486 foreach ($pages as $access_page => $tabs)
2487 foreach ($tabs as $access_tab => $access)
2488 {
2489 echo "<td>";
2490 if ($username != '%')
2491 $userid = $accounts[$username]['user_id'];
2492 else
2493 $userid = 0;
2494 echo "<a href='${root}process.php?op=revoke&page=${pageno}&tab=${tabno}&access_userid=${userid}&access_page=${access_page}&access_tab=${access_tab}'>";
2495 printImageHREF ('revoke', 'Revoke permission');
2496 echo "</a></td>";
2497 echo "<td>${username}</td>";
2498 echo "<td>${access_page}</td>";
2499 echo "<td>${access_tab}</td>";
2500 echo "<td>${access}</td>";
2501 echo "</tr>\n";
2502 }
2503 echo "<form action='${root}process.php' method=post><tr>";
2504 echo "<input type=hidden name=op value=grant>\n";
2505 echo "<input type=hidden name=page value='${pageno}'>\n";
2506 echo "<input type=hidden name=tab value='${tabno}'>\n";
2507 // FIXME: border=0 doesn't work here for unknown reason
2508 echo "<td>";
a5ae8c2a 2509 printImageHREF ('grant', '', TRUE, 103);
e673ee24
DO
2510 echo "</td>";
2511 echo "<td><select name=access_userid>";
2512 echo "<option value=0>ANY</option>";
2513 foreach ($accounts as $account)
2514 echo "<option value=${account['user_id']}>${account['user_name']}</option>";
2515 echo "</select></td>\n";
2516 echo "<td><select name=access_page>";
2517 echo "<option value='%'>ANY</option>";
2518 printPagesTree();
2519 echo "</select></td>";
2520 echo "<td><input type=text size=16 name=access_tab tabindex=102 value=default></td>";
2521 echo "<td><input type=radio name=access_value value=no checked>no <input type=radio name=access_value value=yes>yes</td>";
2522 echo "</tr></form>";
2523 echo "</table><br>\n";
2524 finishPortlet();
2525}
2526
e673ee24
DO
2527function renderPortMap ($editable = FALSE)
2528{
2529 global $nextorder, $root, $pageno, $tabno;
2530 showMessageOrError();
2531 startPortlet ("Port compatibility map");
2532 $ptlist = getPortTypes();
2533 $pclist = getPortCompat();
2534 $pctable = buildPortCompatMatrixFromList ($ptlist, $pclist);
2535 if ($editable)
2536 {
2537 echo "<form method=post action='${root}process.php'>";
2538 echo "<input type=hidden name=page value='${pageno}'>";
2539 echo "<input type=hidden name=tab value='${tabno}'>";
2540 echo "<input type=hidden name=op value=save>";
2541 }
2542 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2543 echo "<tr><th class=vert_th>&nbsp;</th>";
2544 foreach ($ptlist as $name2)
2545 echo "<th>to ${name2}</th>";
2546 echo "</tr>";
2547 // Make a copy to have an independent array pointer.
2548 $ptlistY = $ptlist;
2549 $order = 'odd';
2550 foreach ($ptlistY as $type1 => $name1)
2551 {
2552 echo "<tr class=row_${order}><th class=vert_th style='border-bottom: 0px;'>from $name1</th>";
2553 foreach ($ptlist as $type2 => $name2)
2554 {
2555 echo '<td><input type=checkbox' . ($editable ? " name=atom_${type1}_${type2}" : ' disabled');
2556 echo ($pctable[$type1][$type2] ? ' checked' : '') . '></td>';
2557 }
2558 echo "</tr>\n";
2559 $order = $nextorder[$order];
2560 }
2561 echo '</table><br>';
2562 if ($editable)
2563 {
2564 echo "<input type=submit value='Save changes'>";
2565 echo "</form>";
2566 }
2567 finishPortlet();
2568}
2569
2570function renderConfigMainpage ()
2571{
2572 global $pageno, $root;
2573 $children = getDirectChildPages ($pageno);
2574 echo '<ul>';
27ef67da
DO
2575 // FIXME: assume all config kids to have static titles at the moment,
2576 // but use some proper abstract function later.
e673ee24 2577 foreach ($children as $cpageno => $child)
27ef67da 2578 echo "<li><a href='${root}?page=${cpageno}'>" . $child['title'] . "</li>\n";
e673ee24
DO
2579 echo '';
2580 echo '</ul>';
2581}
2582
2583function renderRackPage ($rack_id)
2584{
2585 if ($rack_id == 0)
2586 {
591ff2c4 2587 showError ('Invalid rack_id', __FUNCTION__);
e673ee24
DO
2588 return;
2589 }
2590 if (($rackData = getRackData ($rack_id)) == NULL)
2591 {
591ff2c4 2592 showError ('getRackData() failed', __FUNCTION__);
e673ee24
DO
2593 return;
2594 }
2595 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
2596
2597 // Left column with information.
2598 echo "<td class=pcleft>";
2599 startPortlet ('Rack information');
2600 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2601 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
2602 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
2603 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
8a1b387d 2604 echo "<tr><th width='50%' class=tdright>Utilization:</th><td class=tdleft>";
11df133a 2605 renderProgressBar (getRSUforRack ($rackData));
8a1b387d 2606 echo "</td></tr>\n";
f1a0477d
DO
2607 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
2608 echo getObjectCount ($rackData);
2609 echo "</td></tr>\n";
e673ee24
DO
2610 if (!empty ($rackData['comment']))
2611 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
2612 echo '</table>';
2613 finishPortlet();
2614 echo '</td>';
2615
2616 // Right column with rendered rack.
2617 echo '<td>';
2618 startPortlet ('Rack diagram');
2619 renderRack ($rack_id);
2620 finishPortlet();
2621 echo '</td>';
2622
2623 echo '</tr></table>';
2624}
2625
2626function renderDictionary ()
2627{
2628 global $nextorder;
2629 $dict = getDict();
aa28ebdf 2630 echo "<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
aa28ebdf
DO
2631 foreach ($dict as $chapter_no => $chapter)
2632 {
a22ec5b4 2633 $order = 'odd';
aa28ebdf
DO
2634 echo "<tr><th>Chapter</th><th>[refcnt]</th><th>Word</th></tr>\n";
2635 $wc = count ($chapter['word']);
2636 echo "<tr class=row_${order}><td class=tdleft" . ($wc ? " rowspan = ${wc}" : '');
2637 echo "><div title='number=${chapter_no}'>${chapter['name']} (${wc} records)</div></td>";
2638 if (!$wc)
2639 echo "<td colspan=2>none</td>";
2640 else
e673ee24 2641 {
aa28ebdf
DO
2642 $chap_start = TRUE;
2643 foreach ($chapter['word'] as $key => $value)
2644 {
2645 if (!$chap_start)
2646 echo "<tr class=row_${order}>";
2647 else
2648 $chap_start = FALSE;
a22ec5b4 2649 echo "<td>&nbsp;</td><td><div title='key=${key}'>${value}</div></td></tr>\n";
aa28ebdf
DO
2650 $order = $nextorder[$order];
2651 }
e673ee24 2652 }
e673ee24 2653 }
aa28ebdf 2654 echo "</table>\n";
e673ee24
DO
2655}
2656
2657function renderDictionaryEditor ()
2658{
2659 global $root, $pageno, $tabno;
2660 showMessageOrError();
2661 $dict = getDict();
2662 echo "<table border=0><tr>";
2663 foreach ($dict as $chapter)
2664 {
2665 echo "<td class=pcleft>";
2666 startPortlet ($chapter['name'] . ' (' . count ($chapter['word']) . ')');
2667 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2668 foreach ($chapter['word'] as $key => $value)
2669 {
2670 echo "<form action='${root}process.php' method=post>";
2671 echo "<input type=hidden name=page value='${pageno}'>";
2672 echo "<input type=hidden name=tab value='${tabno}'>";
2673 echo "<input type=hidden name=op value='upd'>";
2674 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2675 echo "<input type=hidden name=dict_key value='${key}'>";
2676 echo '<tr>';
2677 echo "<td><a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}&dict_key=${key}'>";
2678 printImageHREF ('delete', 'Delete word');
2679 echo "</a></td>";
2680 echo "<td class=tdright><input type=text name=dict_value size=32 value='${value}'></td>";
2681 echo "<td><input type=submit value=OK></td>";
2682 echo '</tr></form>';
2683 }
2684 echo "<form action='${root}process.php' method=post>";
2685 echo "<input type=hidden name=page value='${pageno}'>";
2686 echo "<input type=hidden name=tab value='${tabno}'>";
2687 echo "<input type=hidden name=op value=add>";
2688 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2689 echo '<tr>';
2690 echo "<td>&nbsp;</td>";
2691 echo "<td class=tdright><input type=text name=dict_value size=32></td>";
2692 echo "<td><input type=submit value=OK></td>";
2693 echo '</tr></form>';
2694 echo "</table>";
2695 finishPortlet();
2696 echo "</td>";
2697 }
2698 echo "</tr></table>";
2699}
2700
2701// We don't allow to rename/delete a sticky chapter and we don't allow
2702// to delete a non-empty chapter.
2703function renderChaptersEditor ()
2704{
2705 global $root, $pageno, $tabno;
2706 showMessageOrError();
2707 $dict = getDict();
2708 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2709 echo '<tr><th>&nbsp;</th><th>Chapter name</th><th>Words</th><th>&nbsp;</th></tr>';
2710 foreach ($dict as $chapter)
2711 {
2712 $wordcount = count ($chapter['word']);
2713 $sticky = $chapter['sticky'];
2714 echo "<form action='${root}process.php' method=post>";
2715 echo "<input type=hidden name=page value='${pageno}'>";
2716 echo "<input type=hidden name=tab value='${tabno}'>";
2717 echo "<input type=hidden name=op value=upd>";
2718 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2719 echo '<tr>';
2720 echo '<td>';
2721 if ($sticky or $wordcount > 0)
2722 echo '&nbsp;';
2723 else
2724 {
2725 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}'>";
2726 printImageHREF ('delete', 'Remove chapter');
2727 echo "</a>";
2728 }
2729 echo '</td>';
2730 echo "<td><input type=text name=chapter_name value='${chapter['name']}'" . ($sticky ? ' disabled' : '') . "></td>";
2731 echo "<td class=tdleft>${wordcount}</td><td>";
2732 if ($sticky)
2733 echo '&nbsp;';
2734 else
2735 echo "<input type=submit value='OK'>";
2736 echo '</td></tr>';
2737 echo '</form>';
2738 }
2739 echo "<form action='${root}process.php' method=post>";
2740 echo "<input type=hidden name=page value='${pageno}'>";
2741 echo "<input type=hidden name=tab value='${tabno}'>";
2742 echo "<input type=hidden name=op value=add>";
2743 echo '<tr><td>';
a5ae8c2a 2744 printImageHREF ('add', '', TRUE);
e673ee24
DO
2745 echo "</td><td colspan=3><input type=text name=chapter_name></td>";
2746 echo '</tr>';
2747 echo '</form>';
2748 echo "</table>\n";
2749}
2750
2751function renderAttributes ()
2752{
2753 global $nextorder;
2754 $attrMap = getAttrMap();
2755 startPortlet ('Optional attributes');
2756 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2757 echo "<tr><th class=tdleft>Attribute name</th><th class=tdleft>Attribute type</th><th class=tdleft>Applies to</th></tr>";
2758 $order = 'odd';
2759 foreach ($attrMap as $attr)
2760 {
2761 echo "<tr class=row_${order}>";
2762 echo "<td class=tdleft>${attr['name']}</td>";
2763 echo "<td class=tdleft>${attr['type']}</td>";
2764 echo '<td class=tdleft>';
2765 if (count ($attr['application']) == 0)
2766 echo '&nbsp;';
2767 else
2768 foreach ($attr['application'] as $app)
2769 if ($attr['type'] == 'dict')
2770 echo "${app['objtype_name']} (values from '${app['chapter_name']}')<br>";
2771 else
2772 echo "${app['objtype_name']}<br>";
2773 echo '</td>';
2774 echo "</tr>\n";
2775 $order = $nextorder[$order];
2776 }
2777 echo "</table><br>\n";
2778 finishPortlet();
2779}
2780
2781function renderEditAttributesForm ()
2782{
2783 global $root, $pageno, $tabno;
2784 $attrMap = getAttrMap();
2785 showMessageOrError();
2786 startPortlet ('Optional attributes');
2787 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2788 echo '<tr><th>&nbsp;</th><th>Name</th><th>Type</th><th>&nbsp;</th></tr>';
2789 foreach ($attrMap as $attr)
2790 {
2791 echo "<form action='${root}process.php' method=post>";
2792 echo "<input type=hidden name=page value='${pageno}'>";
2793 echo "<input type=hidden name=tab value='${tabno}'>";
2794 echo "<input type=hidden name=op value=upd>";
2795 echo "<input type=hidden name=attr_id value='${attr['id']}'>";
2796 echo '<tr>';
2797 echo "<td><a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&attr_id=${attr['id']}'>";
2798 printImageHREF ('delete', 'Remove attribute');
2799 echo '</a></td>';
2800 echo "<td><input type=text name=attr_name value='${attr['name']}'></td>";
2801 echo "<td>${attr['type']}</td>";
2802 echo "<td><input type=submit value='OK'></td>";
2803 echo '</tr>';
2804 echo '</form>';
2805 }
2806 echo "<form action='${root}process.php' method=post>";
2807 echo "<input type=hidden name=page value='${pageno}'>";
2808 echo "<input type=hidden name=tab value='${tabno}'>";
2809 echo "<input type=hidden name=op value=add>";
2810 echo '<tr><td>';
a5ae8c2a 2811 printImageHREF ('add', '', TRUE);
e673ee24
DO
2812 echo "</td><td><input type=text name=attr_name></td>";
2813 echo '<td><select name=attr_type>';
2814 echo '<option value=uint>uint</option>';
2815 echo '<option value=float>float</option>';
2816 echo '<option value=string>string</option>';
2817 echo '<option value=dict>dict</option>';
2818 echo '</select></td>';
2819 echo '</tr>';
2820 echo '</form>';
2821 echo "</table>\n";
2822 finishPortlet();
2823}
2824
2825function renderEditAttrMapForm ()
2826{
2827 global $root, $pageno, $tabno;
2828 $attrMap = getAttrMap();
2829 showMessageOrError();
2830 startPortlet ('Attribute map');
2831 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2832 echo '<tr><th>&nbsp;</th><th>Attribute name</th><th>Object type</th><th>Dictionary chapter</th></tr>';
2833 foreach ($attrMap as $attr)
2834 {
2835 if (count ($attr['application']) == 0)
2836 continue;
2837 foreach ($attr['application'] as $app)
2838 {
2839 echo '<tr>';
2840 echo '<td>';
2841 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&";
2842 echo "attr_id=${attr['id']}&objtype_id=${app['objtype_id']}'>";
2843 printImageHREF ('delete', 'Remove mapping');
2844 echo "</a>";
2845 echo '</td>';
2846 echo "<td>${attr['name']}</td>";
2847 echo "<td>${app['objtype_name']}</td>";
2848 echo "<td>";
2849 if ($attr['type'] == 'dict')
2850 echo "${app['chapter_name']}";
2851 else
2852 echo '&nbsp;';
2853 echo "</td></tr>\n";
2854 }
2855 }
2856 echo "<form action='${root}process.php' method=post>";
2857 echo "<input type=hidden name=page value='${pageno}'>";
2858 echo "<input type=hidden name=tab value='${tabno}'>";
2859 echo "<input type=hidden name=op value=add>";
2860 echo '<tr><td>';
a5ae8c2a 2861 printImageHREF ('add', '', TRUE);
e673ee24
DO
2862 echo "</td><td><select name=attr_id>";
2863 $shortType['uint'] = 'U';
2864 $shortType['float'] = 'F';
2865 $shortType['string'] = 'S';
2866 $shortType['dict'] = 'D';
2867 foreach ($attrMap as $attr)
2868 echo "<option value=${attr['id']}>[" . $shortType[$attr['type']] . "] ${attr['name']}</option>";
2869 echo "</select></td>";
2870 echo '<td>';
2871 printSelect (getObjectTypeList(), 'objtype_id');
2872 echo '</td>';
2873 $dict = getDict();
2874 echo '<td><select name=chapter_no>';
2875 foreach ($dict as $chapter)
2876 if (!$chapter['sticky'])
2877 echo "<option value='${chapter['no']}'>${chapter['name']}</option>";
2878 echo '</select></td>';
2879 echo '</tr>';
2880 echo '</form>';
2881 echo "</table>\n";
2882 finishPortlet();
2883}
2884
a5ae8c2a 2885function printImageHREF ($tag, $title = '', $do_input = FALSE, $tabindex = 0)
e673ee24 2886{
a5ae8c2a
DO
2887 global $root;
2888 $image['error']['path'] = 'pix/error.png';
2889 $image['error']['width'] = 76;
2890 $image['error']['height'] = 17;
a5ae8c2a
DO
2891 $image['logo']['path'] = 'pix/defaultlogo.png';
2892 $image['logo']['width'] = 210;
2893 $image['logo']['height'] = 40;
2894 $image['rackspace']['path'] = 'pix/racks.png';
2895 $image['rackspace']['width'] = 218;
2896 $image['rackspace']['height'] = 200;
2897 $image['objects']['path'] = 'pix/server.png';
2898 $image['objects']['width'] = 218;
2899 $image['objects']['height'] = 200;
2900 $image['ipv4space']['path'] = 'pix/addressspace.png';
2901 $image['ipv4space']['width'] = 218;
2902 $image['ipv4space']['height'] = 200;
2903 $image['config']['path'] = 'pix/configuration.png';
2904 $image['config']['width'] = 218;
2905 $image['config']['height'] = 200;
2906 $image['reports']['path'] = 'pix/report.png';
2907 $image['reports']['width'] = 218;
2908 $image['reports']['height'] = 200;
2909 $image['help']['path'] = 'pix/help.png';
2910 $image['help']['width'] = 218;
2911 $image['help']['height'] = 200;
2912 $image['reserve']['path'] = 'pix/stop.png';
2913 $image['reserve']['width'] = 16;
2914 $image['reserve']['height'] = 16;
2915 $image['useup']['path'] = 'pix/go.png';
2916 $image['useup']['width'] = 16;
2917 $image['useup']['height'] = 16;
2918 $image['blockuser'] = $image['reserve'];
2919 $image['unblockuser'] = $image['useup'];
2920 $image['link']['path'] = 'pix/link.png';
2921 $image['link']['width'] = 24;
2922 $image['link']['height'] = 24;
2923 $image['unlink']['path'] = 'pix/unlink.png';
2924 $image['unlink']['width'] = 24;
2925 $image['unlink']['height'] = 24;
2926 $image['add']['path'] = 'pix/greenplus.png';
2927 $image['add']['width'] = 16;
2928 $image['add']['height'] = 16;
2929 $image['delete']['path'] = 'pix/delete_s.gif';
2930 $image['delete']['width'] = 16;
2931 $image['delete']['height'] = 16;
2932 $image['grant'] = $image['add'];
2933 $image['revoke'] = $image['delete'];
2934 $image['helphint']['path'] = 'pix/helphint.png';
2935 $image['helphint']['width'] = 24;
2936 $image['helphint']['height'] = 24;
e673ee24
DO
2937 if (!isset ($image[$tag]))
2938 $tag = 'error';
2939 $img = $image[$tag];
a5ae8c2a
DO
2940 if ($do_input == TRUE)
2941 echo
2942 "<input type=image name=submit " .
2943 "src='${root}${img['path']}' " .
2944 "border=0 " .
2945 ($tabindex ? '' : "tabindex=${tabindex}") .
2946 ">";
2947 else
2948 echo
2949 "<img " .
2950 "src='${root}${img['path']}' " .
2951 "width=${img['width']} " .
2952 "height=${img['height']} " .
2953 "border=0 " .
2954 (empty ($title) ? '' : "title='${title}'") .
2955 ">";
e673ee24
DO
2956}
2957
2958// This function returns URL for favourite icon.
2959function getFaviconURL ()
2960{
46100c70
DO
2961 global $root;
2962 return $root . 'pix/racktables.ico';
e673ee24
DO
2963}
2964
2965function renderReportSummary ()
2966{
da95280e
DO
2967 echo "<table width='100%'>\n";
2968 echo "<tr><td class=pcleft>\n";
08b4cb24 2969 startPortlet ("Dictionary/objects stats");
da95280e
DO
2970 echo "<table>\n";
2971 foreach (getDictStats() as $header => $data)
2972 {
2973 echo "<tr><th>${header}:</th><td>${data}</td></tr>\n";
2974 }
2975 echo "</table>\n";
2976 finishPortlet();
2977
2978 echo "</td><td class=pcright>\n";
2979
c461c579
DO
2980 startPortlet ("Here be dragons");
2981 dragon();
2982 dragon();
2983 dragon();
2984 echo 'ASCII art &copy; Daniel C. Au';
2985 finishPortlet();
da95280e
DO
2986 echo "</td></tr>\n";
2987 echo "</table>\n";
c461c579
DO
2988}
2989
2990function dragon ()
2991{
2992?>
2993<div class=dragon><pre><font color="#00ff33">
2994 \||/
2995 | <font color="#ff0000">@</font>___oo
2996 /\ /\ / (__<font color=yellow>,,,,</font>|
2997 ) /^\) ^\/ _)
2998 ) /^\/ _)
2999 ) _ / / _)
3000 /\ )/\/ || | )_)
3001 &lt; &gt; |(<font color=white>,,</font>) )__)
3002 || / \)___)\
3003 | \____( )___) )___
3004 \______(_______<font color=white>;;;</font> __<font color=white>;;;</font>
3005
3006</font></pre></div>
3007<?php
e673ee24
DO
3008}
3009
3010function renderUIConfig ()
3011{
4fe32e78
DY
3012 global $configCache, $nextorder;
3013 showMessageOrError();
0a1b1268 3014 startPortlet ('Current configuration');
c461c579
DO
3015 echo '<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center width="50%">';
3016 echo '<tr><th class=tdleft>Option</th><th class=tdleft>Value</th></tr>';
4fe32e78 3017 $order = 'odd';
0a1b1268 3018 foreach ($configCache as $v)
4fe32e78 3019 {
c461c579
DO
3020 if ($v['is_hidden'] != 'no')
3021 continue;
3022 echo "<tr class=row_${order}>";
3023 echo "<td class=tdright>${v['description']}</td>\n";
3024 echo "<td class=tdleft>${v['varvalue']}</td></tr>";
3025 $order = $nextorder[$order];
4fe32e78 3026 }
0a1b1268
DO
3027 echo "</table>\n";
3028 finishPortlet();
7865c525
DO
3029}
3030
4fe32e78
DY
3031function renderUIConfigEditForm ()
3032{
c461c579 3033 global $root, $pageno, $tabno, $configCache;
4fe32e78
DY
3034 showMessageOrError();
3035 startPortlet ('Current configuration');
c461c579
DO
3036 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='50%'>\n";
3037 echo "<tr><th class=tdleft>Option</th>";
3038 echo "<th class=tdleft>Value</th></tr>";
4fe32e78
DY
3039 echo "<form action='${root}process.php'>";
3040 echo "<input type=hidden name=op value='upd'>";
c461c579
DO
3041 echo "<input type=hidden name=page value='${pageno}'>\n";
3042 echo "<input type=hidden name=tab value='${tabno}'>\n";
4fe32e78
DY
3043
3044 $i = 0;
3045 foreach ($configCache as $v)
3046 {
c461c579
DO
3047 if ($v['is_hidden'] != 'no')
3048 continue;
3049 echo "<input type=hidden name=${i}_varname value='${v['varname']}'>";
3050 echo "<tr><td class=tdright>${v['description']}</td>";
3051 echo "<td class=tdleft><input type=text name=${i}_varvalue value='${v['varvalue']}' size=24></td>";
3052 echo "</tr>\n";
3053 $i++;
4fe32e78
DY
3054 }
3055 echo "<input type=hidden name=num_vars value=${i}>\n";
c461c579 3056 echo "<tr><td colspan=2><input type=submit value='Save changes'></td></tr>";
4fe32e78
DY
3057 echo "</form>";
3058 finishPortlet();
3059}
3060
7865c525
DO
3061// This function queries the gateway about current VLAN configuration and
3062// renders a form suitable for submit. Ah, and it does submit processing as well.
111b4a67
DO
3063function renderVLANMembership ($object_id = 0)
3064{
fc8d0004 3065 global $root, $pageno, $tabno, $remote_username;
111b4a67
DO
3066 if ($object_id <= 0)
3067 {
591ff2c4 3068 showError ('Invalid object_id', __FUNCTION__);
111b4a67
DO
3069 return;
3070 }
7865c525
DO
3071
3072 // Handle probable pending submit.
3073 if (isset ($_REQUEST['portcount']))
111b4a67 3074 {
7865c525
DO
3075 $data = getSwitchVLANs ($object_id);
3076 if ($data === NULL)
2da7c9b0 3077 {
591ff2c4 3078 showError ('getSwitchVLANs() failed during submit processing', __FUNCTION__);
fc8d0004
DO
3079 return;
3080 }
7865c525
DO
3081 list ($vlanlist, $portlist) = $data;
3082 // Here we just build up 1 set command for the gateway with all of the ports
3083 // included. The gateway is expected to filter unnecessary changes silently
3084 // and to provide a list of responses with either error or success message
3085 // for each of the rest.
3086 assertUIntArg ('portcount');
3087 $nports = $_REQUEST['portcount'];
3088 $prefix = 'set ';
3089 $log = array();
3090 $setcmd = '';
3091 for ($i = 0; $i < $nports; $i++)
3092 if
3093 (
3094 !isset ($_REQUEST['portname_' . $i]) ||
3095 !isset ($_REQUEST['vlanid_' . $i]) ||
3096 $_REQUEST['portname_' . $i] != $portlist[$i]['portname']
3097 )
3098 $log[] = array ('code' => 'error', 'message' => "Ignoring mailformed record #${i} in form submit");
3099 elseif
3100 (
3101 $_REQUEST['vlanid_' . $i] == $portlist[$i]['vlanid'] ||
3102 $portlist[$i]['vlaind'] == 'TRUNK'
3103 )
3104 continue;
3105 else
3106 {
3107 $setcmd .= $prefix . $_REQUEST['portname_' . $i] . '=' . $_REQUEST['vlanid_' . $i];
3108 $prefix = ';';
3109 }
3110 printLog ($log);
3111 // Feed the gateway and interpret its (non)response.
3112 if ($setcmd != '')
3113 printLog (setSwitchVLANs ($object_id, $setcmd));
3114 }
3115
3116 // Reload and render.
3117 $data = getSwitchVLANs ($object_id);
3118 if ($data === NULL)
3119 return;
18cb9495 3120 list ($vlanlist, $portlist, $maclist) = $data;
d28ea105 3121
a684aa6f 3122 echo '<table border=0 width="100%"><tr><td colspan=3>';
d28ea105 3123
2b9e0abd 3124 startPortlet ('Current status');
18cb9495 3125 echo "<table class=widetable cellspacing=3 cellpadding=5 align=center width='100%'><tr>";
7865c525
DO
3126 echo "<form method=post>";
3127 echo "<input type=hidden name=page value='${pageno}'>";
3128 echo "<input type=hidden name=tab value='${tabno}'>";
3129 echo "<input type=hidden name=object_id value=${object_id}>";
0d591525
DO
3130 $portcount = count ($portlist);
3131 echo "<input type=hidden name=portcount value=" . $portcount . ">\n";
7865c525 3132 $portno = 0;
9c0b0016 3133 $ports_per_row = getConfigVar ('PORTS_PER_ROW');
7865c525
DO
3134 foreach ($portlist as $port)
3135 {
3136 // Don't let wide forms break our fancy pages.
9c0b0016 3137 if ($portno % $ports_per_row == 0)
fc8d0004 3138 {
7865c525
DO
3139 if ($portno > 0)
3140 echo "</tr>\n";
0d591525 3141 echo "<tr><th>" . ($portno + 1) . "-" . ($portno + $ports_per_row > $portcount ? $portcount : $portno + $ports_per_row) . "</th>";
fc8d0004 3142 }
18cb9495
DO
3143 echo '<td class=port_';
3144 if ($port['status'] == 'notconnect')
3145 echo 'notconnect';
2b9e0abd
DO
3146 elseif ($port['status'] == 'disabled')
3147 echo 'disabled';
18cb9495
DO
3148 elseif ($port['status'] != 'connected')
3149 echo 'unknown';
3150 elseif (!isset ($maclist[$port['portname']]))
3151 echo 'connected_none';
3152 else
3153 {
3154 $maccount = 0;
3155 foreach ($maclist[$port['portname']] as $vlanid => $addrs)
3156 $maccount += count ($addrs);
3157 if ($maccount == 1)
3158 echo 'connected_single';
3159 else
3160 echo 'connected_multi';
3161 }
3162 echo '>' . $port['portname'] . '<br>';
7865c525
DO
3163 echo "<input type=hidden name=portname_${portno} value=" . $port['portname'] . '>';
3164 if ($port['vlanid'] == 'trunk')
fc8d0004 3165 {
7865c525
DO
3166 echo "<input type=hidden name=vlanid_${portno} value='trunk'>";
3167 echo "<select disabled multiple='multiple' size=1><option>TRUNK</option></select>";
fc8d0004 3168 }
7865c525 3169 else
fc8d0004 3170 {
7865c525 3171 echo "<select name=vlanid_${portno}>";
8c7a0e37
DO
3172 // A port may belong to a VLAN, which is absent from the VLAN table, this is normal.
3173 // We must be able to render its SELECT properly at least.
3174 $in_table = FALSE;
d28ea105 3175 foreach ($vlanlist as $v => $d)
fc8d0004 3176 {
7865c525
DO
3177 echo "<option value=${v}";
3178 if ($v == $port['vlanid'])
8c7a0e37 3179 {
7865c525 3180 echo ' selected';
8c7a0e37
DO
3181 $in_table = TRUE;
3182 }
3183 echo ">${v}</option>\n";
fc8d0004 3184 }
8c7a0e37
DO
3185 if (!$in_table)
3186 echo "<option value=${port['vlanid']} selected>${port['vlanid']}</option>\n";
7865c525 3187 echo "</select>";
fc8d0004 3188 }
7865c525
DO
3189 $portno++;
3190 echo "</td>";
111b4a67 3191 }
9c0b0016 3192 echo "</tr><tr><td colspan=" . ($ports_per_row + 1) . "><input type=submit value='Save changes'></form></td></tr></table>";
7865c525 3193 finishPortlet();
d28ea105 3194
a684aa6f
DO
3195 echo '</td></tr><tr><td class=pcleft>';
3196 startPortlet ('VLAN table');
3197 echo '<table class=cooltable cellspacing=0 cellpadding=5 align=center width="100%">';
3198 echo "<tr><th>ID</th><th>Description</th></tr>";
3199 $order = 'even';
3200 global $nextorder;
3201 foreach ($vlanlist as $id => $descr)
3202 {
3203 echo "<tr class=row_${order}><td class=tdright>${id}</td><td class=tdleft>${descr}</td></tr>";
3204 $order = $nextorder[$order];
3205 }
3206 echo '</table>';
3207 finishPortlet();
3208
3209 echo '</td><td class=pcright>';
3210
3211 startPortlet ('Color legend');
3212 echo '<table>';
3213 echo "<tr><th>port state</th><th>color code</th></tr>";
3214 echo "<tr><td>not connected</td><td class=port_notconnect>SAMPLE</td></tr>";
3215 echo "<tr><td>disabled</td><td class=port_disabled>SAMPLE</td></tr>";
3216 echo "<tr><td>unknown</td><td class=port_unknown>SAMPLE</td></tr>";
3217 echo "<tr><td>connected with none MAC addresses active</td><td class=port_connected_none>SAMPLE</td></tr>";
3218 echo "<tr><td>connected with 1 MAC addresses active</td><td class=port_connected_single>SAMPLE</td></tr>";
3219 echo "<tr><td>connected with 1+ MAC addresses active</td><td class=port_connected_multi>SAMPLE</td></tr>";
3220 echo '</table>';
3221 finishPortlet();
3222
3223 echo '</td><td class=pcright>';
3224
18cb9495
DO
3225 if (count ($maclist))
3226 {
3227 startPortlet ('MAC address table');
3228 echo '<table border=0 class=cooltable align=center cellspacing=0 cellpadding=5>';
3229 echo "<tr><th>Port</th><th>VLAN ID</th><th>MAC address</th></tr>\n";
3230 $order = 'even';
3231 foreach ($maclist as $portname => $portdata)
3232 foreach ($portdata as $vlanid => $addrgroup)
3233 foreach ($addrgroup as $addr)
3234 {
3235 echo "<tr class=row_${order}><td>$portname</td><td>$vlanid</td><td>$addr</td></tr>\n";
3236 $order = $nextorder[$order];
3237 }
3238 echo '</table>';
3239 finishPortlet();
3240 }
3241
18cb9495
DO
3242 // End of main table.
3243 echo '</td></tr></table>';
111b4a67
DO
3244}
3245
9c67f713
DO
3246// This snippet either renders a form inviting the user to start SNMP query
3247// on the current device or displays the result of the scan.
3248function renderSNMPPortFinder ($object_id = 0)
3249{
3250 global $root, $pageno, $tabno, $remote_username;
3251 if ($object_id <= 0)
3252 {
591ff2c4 3253 showError ('Invalid object_id', __FUNCTION__);
9c67f713
DO
3254 return;
3255 }
dd9afc41 3256// FIXME: check if SNMP PHP extension is available!
9c67f713
DO
3257 if (isset ($_REQUEST['do_scan']))
3258 {
dd9afc41 3259 $log = array();
1c4d54d4
DO
3260// IDs: http://cisco.com/en/US/products/sw/cscowork/ps2064/products_device_support_table09186a0080803bb4.html
3261// 2960: http://www.cisco.com/en/US/products/ps6406/prod_models_comparison.html
65813f73 3262// 2970: http://cisco.com/en/US/products/hw/switches/ps5206/products_qanda_item09186a00801b1750.shtml
563196e8 3263// 3500XL: http://cisco.com/en/US/products/hw/switches/ps637/products_eol_models.html
1c4d54d4 3264// 3560: http://cisco.com/en/US/products/hw/switches/ps5528/products_data_sheet09186a00801f3d7f.html
563196e8 3265// 3750: http://cisco.com/en/US/products/hw/switches/ps5023/products_data_sheet09186a008016136f.html
137b7a50 3266 $ciscomodel[283] = 'WS-C6509-E (9-slot system)';
818e40c7
DO
3267// FIXME: hwtype hardcoded value will become invalid after the Dictionary table transformation
3268// in 0.14.7 version. Either the values will have to be adjusted as well or we have to switch
3269// to value lookup (not reliable).
64d5f2b4 3270 $hwtype[283] = 148;
dd9afc41
DO
3271# $ciscomodel[694] = 'WS-C2960-24TC-L (24 Ethernet 10/100 ports and 2 dual-purpose uplinks)';
3272# $ciscomodel[695] = 'WS-C2960-48TC-L (48 Ethernet 10/100 ports and 2 dual-purpose uplinks)';
3273 $ciscomodel[696] = 'WS-C2960G-24TC-L (20 Ethernet 10/100/1000 ports and 4 dual-purpose uplinks)';
64d5f2b4 3274 $hwtype[696] = 167;
dd9afc41 3275 $ciscomodel[697] = 'WS-C2960G-48TC-L (44 Ethernet 10/100/1000 ports and 4 dual-purpose uplinks)';
64d5f2b4 3276 $hwtype[697] = 166;
dd9afc41
DO
3277# $ciscomodel[716] = 'WS-C2960-24TT-L (24 Ethernet 10/100 ports and 2 10/100/1000 uplinks)';
3278# $ciscomodel[717] = 'WS-C2960-48TT-L (48 Ethernet 10/100 ports and 2 10/100/1000 uplinks)';
65813f73 3279 $ciscomodel[527] = 'WS-C2970G-24T (24 Ethernet 10/100/1000 ports)';
64d5f2b4 3280 $hwtype[527] = 210;
65813f73
DO
3281 $ciscomodel[561] = 'WS-C2970G-24TS (24 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
3282 $hwtype[561] = 115;
137b7a50 3283# $ciscomodel[633] = 'WS-C3560-24TS (24 Ethernet 10/100 ports and 2 10/100/1000 SFP uplinks)';
64d5f2b4 3284# $hwtype[633] = 169;
137b7a50 3285 $ciscomodel[634] = 'WS-C3560-48TS (48 Ethernet 10/100 ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3286 $hwtype[634] = 170;
137b7a50 3287# $ciscomodel[563] = 'WS-C3560-24PS (24 Ethernet 10/100 POE ports and 2 10/100/1000 SFP uplinks)';
64d5f2b4 3288# $hwtype[563] = 171;
137b7a50 3289 $ciscomodel[564] = 'WS-C3560-48PS (48 Ethernet 10/100 POE ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3290 $hwtype[564] = 172;
1c4d54d4 3291 $ciscomodel[614] = 'WS-C3560G-24PS (24 Ethernet 10/100/1000 POE ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3292 $hwtype[614] = 175;
1c4d54d4 3293 $ciscomodel[615] = 'WS-C3560G-24TS (24 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3294 $hwtype[615] = 173;
1c4d54d4 3295 $ciscomodel[616] = 'WS-C3560G-48PS (48 Ethernet 10/100/1000 POE ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3296 $hwtype[616] = 176;
1c4d54d4 3297 $ciscomodel[617] = 'WS-C3560G-48TS (48 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3298 $hwtype[617] = 174;
7a9f3034 3299 $ciscomodel[58] = 'WS-C4503 (3-slot system)';
64d5f2b4 3300 $hwtype[58] = 145;
7a9f3034 3301 $ciscomodel[503] = '4503 (3-slot system)';
64d5f2b4 3302 $hwtype[503] = 145;
7a9f3034 3303 $ciscomodel[59] = 'WS-C4506 (6-slot system)';
64d5f2b4 3304 $hwtype[59] = 156;
7a9f3034 3305 $ciscomodel[502] = '4506 (6-slot system)';
64d5f2b4 3306 $hwtype[502] = 156;
3d61d4ca 3307 $ciscomodel[626] = 'WS-C4948 (48 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3308 $hwtype[626] = 147;
563196e8 3309 $ciscomodel[659] = 'WS-C4948-10GE (48 Ethernet 10/100/1000 ports and 2 10Gb X2 uplinks)';
64d5f2b4 3310 $hwtype[659] = 377;
dd9afc41
DO
3311 assertStringArg ('community');
3312 $community = $_REQUEST['community'];
3313 $objectInfo = getObjectInfo ($object_id);
3314 $endpoints = findAllEndpoints ($object_id, $objectInfo['name']);
3315 $sysDescr = snmpget ($endpoints[0], $community, 'sysDescr.0');
3316 // Strip the object type, it's always string here.
3317 $sysDescr = substr ($sysDescr, strlen ('STRING: '));
1c4d54d4 3318 if (strpos ($sysDescr, 'Cisco IOS Software') === 0 or strpos ($sysDescr, 'Cisco Internetwork Operating System Software') === 0)
dd9afc41 3319 $log[] = array ('code' => 'success', 'message' => 'Seems to be a Cisco box');
818e40c7
DO
3320 else
3321 {
3322 $log[] = array ('code' => 'error', 'message' => 'No idea how to handle ' . $sysDescr);
3323 printLog ($log);
3324 return;
3325 }
3326
3327 // It's a Cisco. Go on.
3328 $attrs = getAttrValues ($object_id);
3329 // Only fill in attribute values, if they are not set.
3330 // FIXME: this is hardcoded
3331
3332 if (empty ($attrs[5]['value'])) // SW version
3333 {
3334 $IOSversion = ereg_replace ('^.*, Version ([^ ]+), .*$', '\\1', $sysDescr);
3335 $error = commitUpdateAttrValue ($object_id, 5, $IOSversion);
3336 if ($error == TRUE)
3337 $log[] = array ('code' => 'success', 'message' => 'SW version set to ' . $IOSversion);
3338 else
3339 $log[] = array ('code' => 'error', 'message' => 'Failed settig SW version: ' . $error);
3340 }
3341
3342 if (empty ($attrs[4]['value']) and substr ($IOSversion, 0, 4) == '12.2') // switch OS type
3343 {
64d5f2b4 3344 $error = commitUpdateAttrValue ($object_id, 4, 252);
818e40c7
DO
3345 if ($error == TRUE)
3346 $log[] = array ('code' => 'success', 'message' => 'Switch OS type set to Cisco IOS 12.2');
3347 else
3348 $log[] = array ('code' => 'error', 'message' => 'Failed settig Switch OS type: ' . $error);
3349 }
3350
dd9afc41
DO
3351 $sysObjectID = snmpget ($endpoints[0], $community, 'sysObjectID.0');
3352 // Transform OID
3353 $sysObjectID = substr ($sysObjectID, strlen ('OID: SNMPv2-SMI::enterprises.9.1.'));
3354 if (!isset ($ciscomodel[$sysObjectID]))
3355 {
3356 $log[] = array ('code' => 'error', 'message' => 'Could not guess exact HW model!');
3357 printLog ($log);
3358 return;
3359 }
3360 $log[] = array ('code' => 'success', 'message' => 'HW is ' . $ciscomodel[$sysObjectID]);
818e40c7
DO
3361 if (empty ($attrs[2]['value']) and isset ($hwtype[$sysObjectID])) // switch HW type
3362 {
3363 $error = commitUpdateAttrValue ($object_id, 2, $hwtype[$sysObjectID]);
3364 if ($error == TRUE)
3d61d4ca 3365 $log[] = array ('code' => 'success', 'message' => 'HW type updated Ok');
818e40c7
DO
3366 else
3367 $log[] = array ('code' => 'error', 'message' => 'Failed settig HW type: ' . $error);
3368 }
dd9afc41
DO
3369 // Now fetch ifType, ifDescr and ifPhysAddr and let model-specific code sort the data out.
3370 $ifType = snmpwalkoid ($endpoints[0], $community, 'ifType');
3371 $ifDescr = snmpwalkoid ($endpoints[0], $community, 'ifdescr');
3372 $ifPhysAddress = snmpwalkoid ($endpoints[0], $community, 'ifPhysAddress');
3373 // Combine 3 tables into 1...
3374 $ifList1 = array();
3375 foreach ($ifType as $key => $val)
3376 {
3377 list ($dummy, $ifIndex) = explode ('.', $key);
3378 list ($dummy, $type) = explode (' ', $val);
3379 $ifList1[$ifIndex]['type'] = $type;
3380 }
3381 foreach ($ifDescr as $key => $val)
3382 {
3383 list ($dummy, $ifIndex) = explode ('.', $key);
3384 list ($dummy, $descr) = explode (' ', $val);
3385 $ifList1[$ifIndex]['descr'] = trim ($descr, '"');
3386 }
3387 foreach ($ifPhysAddress as $key => $val)
3388 {
3389 list ($dummy, $ifIndex) = explode ('.', $key);
3390 list ($dummy, $addr) = explode (':', $val);
3391 $addr = str_replace (' ', '', $addr);
3392 $ifList1[$ifIndex]['phyad'] = $addr;
3393 }
3394 // ...and then reverse it inside out to make description the key.
3395 $ifList2 = array();
3396 foreach ($ifList1 as $ifIndex => $data)
3397 {
3398 $ifList2[$data['descr']]['type'] = $data['type'];
3399 $ifList2[$data['descr']]['phyad'] = $data['phyad'];
3400 $ifList2[$data['descr']]['idx'] = $ifIndex;
3401 }
dd9afc41
DO
3402 $newports = 0;
3403 // Now we can directly pick necessary ports from the table accordingly
3404 // to our known hardware model.
3405 switch ($sysObjectID)
3406 {
3407 // FIXME: chassis edge switches often share a common naming scheme, so
3408 // the sequences below have to be generalized. Let's have some duplicated
3409 // code for the time being, as this is the first implementation ever.
3410 case '697': // WS-C2960G-48TC-L
3411 // 44 copper ports: 1X, 2X, 3X...
3412 // 4 combo ports: 45, 46, 47, 48. Don't list SFP connectors atm, as it's not
3413 // clear how to fit them into current Ports table structure.
3414 for ($i = 1; $i <= 48; $i++)
3415 {
3416 $label = ($i >= 45) ? "${i}" : "${i}X";
64d5f2b4 3417 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
dd9afc41
DO
3418 if ($error == '')
3419 $newports++;
3420 else
3421 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3422 }
3423 break;
3424 case '696': // WS-C2960G-24TC-L
3425 // Quite similar to the above.
3426 for ($i = 1; $i <= 24; $i++)
3427 {
3428 $label = ($i >= 21) ? "${i}" : "${i}X";
64d5f2b4 3429 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
dd9afc41
DO
3430 if ($error == '')
3431 $newports++;
3432 else
3433 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3434 }
3435 break;
137b7a50
DO
3436 case '564': // WS-C3560-48PS
3437 case '634': // WS-C3560-48TS
3438 for ($i = 1; $i <= 48; $i++)
3439 {
3440 $label = "${i}X";
64d5f2b4 3441 $error = commitAddPort ($object_id, 'fa0/' . $i, 19, $label, $ifList2["FastEthernet0/${i}"]['phyad']);
137b7a50
DO
3442 if ($error == '')
3443 $newports++;
3444 else
3445 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3446 }
3447 for ($i = 1; $i <= 4; $i++)
3448 {
3449 $label = "${i}";
64d5f2b4 3450 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
137b7a50
DO
3451 if ($error == '')
3452 $newports++;
3453 else
3454 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3455 }
3456 break;
1c4d54d4
DO
3457 case '614': // WS-C3560G-24PS
3458 case '615': // WS-C3560G-24TS
65813f73
DO
3459 case '527': // WS-C2970G-24T
3460 case '561': // WS-C2970G-24TS
1c4d54d4
DO
3461 for ($i = 1; $i <= 24; $i++)
3462 {
3463 $label = "${i}X";
64d5f2b4 3464 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
1c4d54d4
DO
3465 if ($error == '')
3466 $newports++;
3467 else
3468 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3469 }
3470 break;
3471 case '616': // WS-C3560G-48PS
3472 case '617': // WS-C3560G-48TS
cdc8ff71
DO
3473 for ($i = 1; $i <= 48; $i++)
3474 {
3475 $label = "${i}X";
3476 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
3477 if ($error == '')
3478 $newports++;
3479 else
3480 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3481 }
3482 break;
3d61d4ca
DO
3483 case '626': // WS-C4948
3484 case '659': // WS-C4948-10GE
1c4d54d4
DO
3485 for ($i = 1; $i <= 48; $i++)
3486 {
3487 $label = "${i}X";
cdc8ff71 3488 $error = commitAddPort ($object_id, 'gi1/' . $i, 24, $label, $ifList2["GigabitEthernet1/${i}"]['phyad']);
1c4d54d4
DO
3489 if ($error == '')
3490 $newports++;
3491 else
3492 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3493 }
3494 break;
137b7a50
DO
3495 // For modular devices we don't iterate over all possible port names,
3496 // but use the first list to pick everything that looks legitimate
3497 // for this hardware. It would be correct to fetch the list of modules
3498 // installed to generate lists of ports, but who is going to implement
3499 // this?
7a9f3034
DO
3500 case '503': // 4503
3501 case '58': // WS-C4503
3502 case '502': // 4506
3503 case '59': // WS-C4506
137b7a50
DO
3504 case '283': // WS-C6509-E
3505 foreach ($ifList1 as $port)
3506 {
3507 if ($port['type'] != 'ethernet-csmacd(6)')
3508 continue;
3509 // Copper Fa/Gi harvesting is relatively simple, while 10Gig ports can
3510 // have random samples of transciever units.
3511 if (strpos ($port['descr'], 'FastEthernet') === 0) // Fa
3512 {
3513 $prefix = 'fa';
64d5f2b4 3514 $ptype = 19; // RJ-45/100Base-TX
137b7a50
DO
3515 list ($slotno, $portno) = explode ('/', substr ($port['descr'], strlen ('FastEthernet')));
3516 }
3517 elseif (strpos ($port['descr'], 'GigabitEthernet') === 0) // Gi
3518 {
3519 $prefix = 'gi';
64d5f2b4 3520 $ptype = 24; // RJ-45/1000Base-T
137b7a50
DO
3521 list ($slotno, $portno) = explode ('/', substr ($port['descr'], strlen ('GigabitEthernet')));
3522 }
3523 else continue;
3524 $label = "slot ${slotno} port ${portno}";
3525 $pname = "${prefix}${slotno}/${portno}";
3526 $error = commitAddPort ($object_id, $pname, $ptype, $label, $port['phyad']);
3527 if ($error == '')
3528 $newports++;
3529 else
3530 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $pname . ': ' . $error);
3531 }
3532 break;
dd9afc41 3533 default:
591ff2c4 3534 showError ("Unexpected sysObjectID '${sysObjectID}'", __FUNCTION__);
dd9afc41 3535 }
64d5f2b4 3536 $error = commitAddPort ($object_id, 'con0', 29, 'console', '');
b8f2fed1
DO
3537 if ($error == '')
3538 $newports++;
3539 else
3540 $log[] = array ('code' => 'error', 'message' => 'Failed to add console port : ' . $error);
dd9afc41
DO
3541 if ($newports > 0)
3542 $log[] = array ('code' => 'success', 'message' => "Added ${newports} new ports");
3543 printLog ($log);
9c67f713
DO
3544 return;
3545 }
dd9afc41
DO
3546 echo "<form method=post>\n";
3547 echo "<input type=hidden name=pageno value='${pageno}'>\n";
3548 echo "<input type=hidden name=tabno value='${pageno}'>\n";
3549?>
3550<p align=center>
3551This switch has no ports listed, that's why you see this form. If you supply SNMP community,
3552I can try atomatic data harvesting on the switch. As soon as at least one relevant port is found,
3553this tab will not be seen any more. Good luck.<br>
3554<input type=text name=community value='public'>
3555<input type=submit name='do_scan' value='Go!'>
3556</p>
b325120a 3557<?php
9c67f713
DO
3558}
3559
b07f617c
DO
3560function renderUIResetForm()
3561{
8dedc926 3562 global $root, $pageno, $tabno;
b07f617c
DO
3563 echo "<form method=post action='${root}process.php'>";
3564 echo "<input type=hidden name=page value=${pageno}>";
3565 echo "<input type=hidden name=tab value=${tabno}>";
3566 echo "<input type=hidden name=op value=go>";
3567 echo "This button will reset user interface configuration to its defaults (except organization name): ";
3568 echo "<input type=submit value='proceed'>";
3569 echo "</form>";
3570}
3571
9b0cf84f
DO
3572function renderFirstRowForm ()
3573{
3574 global $root, $pageno, $tabno;
80c37f85
DO
3575 echo "<form action='${root}process.php'>\n";
3576 echo "<input type=hidden name=page value=dict>\n";
3577 echo "<input type=hidden name=tab value=edit>\n";
3578 echo "<input type=hidden name=op value=add>\n";
3579 echo "<input type=hidden name=chapter_no value=3>\n";
9b0cf84f
DO
3580?>
3581<p align=center>
3582Your rackspace seems to be empty, and this form will create your first rack row,
3583just fill in the name. All the subsequent rack rows will have to be added from the
3584Dictionary edit page in Configuration section.
3585<br>
80c37f85
DO
3586<input type=text name=dict_value value='my server room'>
3587<input type=submit value='OK'>
9b0cf84f
DO
3588</p>
3589<?php
3590}
3591
fb355164 3592function renderLVSConfig ($object_id = 0)
3ee1252b 3593{
fb355164
DO
3594 if ($object_id <= 0)
3595 {
591ff2c4 3596 showError ('Invalid object_id', __FUNCTION__);
fb355164
DO
3597 return;
3598 }
3599 $natrules = getObjectForwards ($object_id);
3600 $lvsconfig = array();
3601 foreach ($natrules['out'] as $rule)
3602 {
3603 $lvsconfig [$rule['localip']] ['description'] = $rule['local_addr_name'];
3604 $lvsconfig [$rule['localip']] [$rule['proto']] [$rule['localport']] ['rs'] [] = array
3605 (
3606 'address' => $rule['remoteip'],
3607 'port' => $rule['remoteport'],
3608 'description' => $rule['remote_addr_name']
3609 );
3610 }
3611 echo '<pre>';
3612 foreach ($lvsconfig as $vip => $vipdata)
3613 foreach (readChapter ('Protocols') as $proto)
3614 {
3615 if (!isset ($vipdata[$proto]))
3616 continue;
3617 foreach ($vipdata[$proto] as $vport => $vportdata)
3618 {
5e19e15c 3619 echo '# auto-VIP: ' . (empty ($vipdata['description']) ? 'NO NAME' : $vipdata['description']) . "\n";
fb355164
DO
3620 echo "virtual_server ${vip} ${vport}\n";
3621 foreach ($vportdata['rs'] as $rs)
04d1707b
DO
3622 {
3623 if (!empty ($rs['description']))
3624 echo "\t# " . $rs['description'] . "\n";
fb355164 3625 echo "\treal_server ${rs['address']} ${rs['port']} {\n\t}\n";
04d1707b 3626 }
fb355164
DO
3627 echo "}\n\n";
3628 }
3629 }
3630 echo '</pre>';
3ee1252b
DO
3631}
3632
060ba26e 3633function renderVirtualService ($vsid = 0)
13bffb29 3634{
b3c50e6c 3635 global $root, $nextorder;
060ba26e
DO
3636 if ($vsid <= 0)
3637 {
3638 showError ('Invalid vsid', __FUNCTION__);
3639 return;
3640 }
3641 $vsinfo = getVServiceInfo ($vsid);
c85b85b5
DO
3642 echo '<table border=0 class=objectview cellspacing=0 cellpadding=0>';
3643 if (!empty ($vsinfo['name']))
3644 echo "<tr><td colspan=2 align=center><h1>${vsinfo['name']}</h1></td></tr>\n";
3645 echo '<tr>';
3646
3647 echo '<td class=pcleft>';
3648 startPortlet ('Frontend');
3649 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
3650 if (!empty ($vsinfo['name']))
3651 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${vsinfo['name']}</td></tr>\n";
3652 echo "<tr><th width='50%' class=tdright>Protocol:</th><td class=tdleft>${vsinfo['proto']}</td></tr>\n";
85f96f3f 3653 echo "<tr><th width='50%' class=tdright>Virtual IP address:</th><td class=tdleft><a href='${root}?page=ipaddress&tab=default&ip=${vsinfo['vip']}'>${vsinfo['vip']}</a></td></tr>\n";
c85b85b5 3654 echo "<tr><th width='50%' class=tdright>Virtual port:</th><td class=tdleft>${vsinfo['vport']}</td></tr>\n";
2b4eee17
DO
3655 if (!empty ($vsinfo['vsconfig']))
3656 {
3657 echo "<tr><th width='50%' class=tdright>VS configuration:</th><td class=tdleft>&nbsp;</td></tr>\n";
3658 echo "<tr><td class=tdleft colspan=2><pre>${vsinfo['vsconfig']}</pre></td></tr>\n";
3659 }
3660 if (!empty ($vsinfo['rsconfig']))
3661 {
3662 echo "<tr><th width='50%' class=tdright>RS configuration:</th><td class=tdleft>&nbsp;</td></tr>\n";
3663 echo "<tr><td class=tdleft colspan=2><pre>${vsinfo['rsconfig']}</pre></td></tr>\n";
3664 }
c85b85b5
DO
3665 echo "</table>\n";
3666 finishPortlet ();
3667 echo '</td>';
3668
2b4eee17 3669 echo '<td class=pcright>';
c85b85b5 3670 startPortlet ('Backend');
b3c50e6c 3671 echo "<table cellspacing=0 cellpadding=5 align=center border=0>\n";
2b4eee17 3672 echo "<tr><th>real server pool</th><th>load balancers</th></tr>\n";
b3c50e6c 3673 $order = 'odd';
2b4eee17
DO
3674 foreach ($vsinfo['rspool'] as $pool_id => $poolInfo)
3675 {
b3c50e6c 3676 echo "<tr class=row_${order}><td class=tdleft>";
2b4eee17
DO
3677 // Pool info
3678 echo '<table width=100%>';
3679 echo "<tr><td colspan=2><a href='${root}?page=rspool&id=${pool_id}'>";
3680 if (!empty ($poolInfo['name']))
3681 echo $poolInfo['name'];
3682 else
3683 echo 'ANONYMOUS';
3684 echo "</a></td></tr>";
3685 if (!empty ($poolInfo['vsconfig']))
3686 echo "<tr><th>VS config</th><td><pre>${poolInfo['vsconfig']}</pre></td></tr>";
3687 if (!empty ($poolInfo['rsconfig']))
3688 echo "<tr><th>RS config</th><td><pre>${poolInfo['rsconfig']}</pre></td></tr>";
3689 echo '</table>';
3690 echo '</td><td>';
3691 // LB list
3692 if (!count ($poolInfo['lblist']))
3693 echo 'none';
3694 else
3695 {
3696 echo '<table width=100%>';
3697 foreach ($poolInfo['lblist'] as $object_id => $lbInfo)
3698 {
3699 // FIXME: dname should be cached
3700 $oi = getObjectInfo ($object_id);
3701 echo "<tr><td colspan=2><a href='${root}?page=object&object_id=${object_id}'>";
3702 echo $oi['dname'] . '</a></td></tr>';
3703 if (!empty ($lbInfo['vsconfig']))
3704 echo "<tr><th>VS config</th><td><pre>${lbInfo['vsconfig']}</pre></td></tr>";
3705 if (!empty ($lbInfo['rsconfig']))
3706 echo "<tr><th>RS config</th><td><pre>${lbInfo['rsconfig']}</pre></td></tr>";
3707 }
3708 echo '</table>';
3709 }
3710 echo "</td></tr>\n";
e57dca7f 3711 $order = $nextorder[$order];
c85b85b5
DO
3712 }
3713 echo "</table>\n";
3714 finishPortlet ();
3715 echo '</td>';