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