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