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