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