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