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