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