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