r1762 + introduce TagTree and RackObjectTags tables
[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;
b39e7545
DO
3057 $image['spacer']['path'] = 'pix/pixel.png';
3058 $image['spacer']['width'] = 16;
3059 $image['spacer']['height'] = 16;
e673ee24
DO
3060 if (!isset ($image[$tag]))
3061 $tag = 'error';
3062 $img = $image[$tag];
a5ae8c2a
DO
3063 if ($do_input == TRUE)
3064 echo
3065 "<input type=image name=submit " .
3066 "src='${root}${img['path']}' " .
3067 "border=0 " .
3068 ($tabindex ? '' : "tabindex=${tabindex}") .
3069 ">";
3070 else
3071 echo
3072 "<img " .
3073 "src='${root}${img['path']}' " .
3074 "width=${img['width']} " .
3075 "height=${img['height']} " .
3076 "border=0 " .
3077 (empty ($title) ? '' : "title='${title}'") .
3078 ">";
e673ee24
DO
3079}
3080
3081// This function returns URL for favourite icon.
3082function getFaviconURL ()
3083{
46100c70
DO
3084 global $root;
3085 return $root . 'pix/racktables.ico';
e673ee24
DO
3086}
3087
3088function renderReportSummary ()
3089{
da95280e
DO
3090 echo "<table width='100%'>\n";
3091 echo "<tr><td class=pcleft>\n";
08b4cb24 3092 startPortlet ("Dictionary/objects stats");
da95280e
DO
3093 echo "<table>\n";
3094 foreach (getDictStats() as $header => $data)
7e233246 3095 echo "<tr><th class=tdright>${header}:</th><td class=tdleft>${data}</td></tr>\n";
8948cd63
DO
3096 echo "</table>\n";
3097 finishPortlet();
3098 startPortlet ('IPv4 stats');
3099 echo "<table>\n";
3100 foreach (getIPv4Stats() as $header => $data)
3101 echo "<tr><th class=tdright>${header}:</th><td class=tdleft>${data}</td></tr>\n";
3102 echo "</table>\n";
3103 finishPortlet();
3104 startPortlet ('Rackspace stats');
3105 echo "<table>\n";
3106 foreach (getRackspaceStats() as $header => $data)
3107 echo "<tr><th class=tdright>${header}:</th><td class=tdleft>${data}</td></tr>\n";
da95280e
DO
3108 echo "</table>\n";
3109 finishPortlet();
3110
3111 echo "</td><td class=pcright>\n";
3112
c461c579
DO
3113 startPortlet ("Here be dragons");
3114 dragon();
3115 dragon();
3116 dragon();
3117 echo 'ASCII art &copy; Daniel C. Au';
3118 finishPortlet();
da95280e
DO
3119 echo "</td></tr>\n";
3120 echo "</table>\n";
c461c579
DO
3121}
3122
3123function dragon ()
3124{
3125?>
3126<div class=dragon><pre><font color="#00ff33">
3127 \||/
3128 | <font color="#ff0000">@</font>___oo
3129 /\ /\ / (__<font color=yellow>,,,,</font>|
3130 ) /^\) ^\/ _)
3131 ) /^\/ _)
3132 ) _ / / _)
3133 /\ )/\/ || | )_)
3134 &lt; &gt; |(<font color=white>,,</font>) )__)
3135 || / \)___)\
3136 | \____( )___) )___
3137 \______(_______<font color=white>;;;</font> __<font color=white>;;;</font>
3138
3139</font></pre></div>
3140<?php
e673ee24
DO
3141}
3142
3143function renderUIConfig ()
3144{
4fe32e78
DY
3145 global $configCache, $nextorder;
3146 showMessageOrError();
0a1b1268 3147 startPortlet ('Current configuration');
c461c579
DO
3148 echo '<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center width="50%">';
3149 echo '<tr><th class=tdleft>Option</th><th class=tdleft>Value</th></tr>';
4fe32e78 3150 $order = 'odd';
0a1b1268 3151 foreach ($configCache as $v)
4fe32e78 3152 {
c461c579
DO
3153 if ($v['is_hidden'] != 'no')
3154 continue;
3155 echo "<tr class=row_${order}>";
3156 echo "<td class=tdright>${v['description']}</td>\n";
3157 echo "<td class=tdleft>${v['varvalue']}</td></tr>";
3158 $order = $nextorder[$order];
4fe32e78 3159 }
0a1b1268
DO
3160 echo "</table>\n";
3161 finishPortlet();
7865c525
DO
3162}
3163
4fe32e78
DY
3164function renderUIConfigEditForm ()
3165{
c461c579 3166 global $root, $pageno, $tabno, $configCache;
4fe32e78
DY
3167 showMessageOrError();
3168 startPortlet ('Current configuration');
c461c579
DO
3169 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='50%'>\n";
3170 echo "<tr><th class=tdleft>Option</th>";
3171 echo "<th class=tdleft>Value</th></tr>";
4fe32e78
DY
3172 echo "<form action='${root}process.php'>";
3173 echo "<input type=hidden name=op value='upd'>";
c461c579
DO
3174 echo "<input type=hidden name=page value='${pageno}'>\n";
3175 echo "<input type=hidden name=tab value='${tabno}'>\n";
4fe32e78
DY
3176
3177 $i = 0;
3178 foreach ($configCache as $v)
3179 {
c461c579
DO
3180 if ($v['is_hidden'] != 'no')
3181 continue;
3182 echo "<input type=hidden name=${i}_varname value='${v['varname']}'>";
3183 echo "<tr><td class=tdright>${v['description']}</td>";
3184 echo "<td class=tdleft><input type=text name=${i}_varvalue value='${v['varvalue']}' size=24></td>";
3185 echo "</tr>\n";
3186 $i++;
4fe32e78
DY
3187 }
3188 echo "<input type=hidden name=num_vars value=${i}>\n";
c461c579 3189 echo "<tr><td colspan=2><input type=submit value='Save changes'></td></tr>";
4fe32e78
DY
3190 echo "</form>";
3191 finishPortlet();
3192}
3193
7865c525
DO
3194// This function queries the gateway about current VLAN configuration and
3195// renders a form suitable for submit. Ah, and it does submit processing as well.
111b4a67
DO
3196function renderVLANMembership ($object_id = 0)
3197{
fc8d0004 3198 global $root, $pageno, $tabno, $remote_username;
111b4a67
DO
3199 if ($object_id <= 0)
3200 {
591ff2c4 3201 showError ('Invalid object_id', __FUNCTION__);
111b4a67
DO
3202 return;
3203 }
7865c525
DO
3204
3205 // Handle probable pending submit.
3206 if (isset ($_REQUEST['portcount']))
111b4a67 3207 {
7865c525
DO
3208 $data = getSwitchVLANs ($object_id);
3209 if ($data === NULL)
2da7c9b0 3210 {
591ff2c4 3211 showError ('getSwitchVLANs() failed during submit processing', __FUNCTION__);
fc8d0004
DO
3212 return;
3213 }
7865c525
DO
3214 list ($vlanlist, $portlist) = $data;
3215 // Here we just build up 1 set command for the gateway with all of the ports
3216 // included. The gateway is expected to filter unnecessary changes silently
3217 // and to provide a list of responses with either error or success message
3218 // for each of the rest.
3219 assertUIntArg ('portcount');
3220 $nports = $_REQUEST['portcount'];
3221 $prefix = 'set ';
3222 $log = array();
3223 $setcmd = '';
3224 for ($i = 0; $i < $nports; $i++)
3225 if
3226 (
3227 !isset ($_REQUEST['portname_' . $i]) ||
3228 !isset ($_REQUEST['vlanid_' . $i]) ||
3229 $_REQUEST['portname_' . $i] != $portlist[$i]['portname']
3230 )
cd40a2a0 3231 $log[] = array ('code' => 'error', 'message' => "Ignoring malformed record #${i} in form submit");
7865c525
DO
3232 elseif
3233 (
3234 $_REQUEST['vlanid_' . $i] == $portlist[$i]['vlanid'] ||
3235 $portlist[$i]['vlaind'] == 'TRUNK'
3236 )
3237 continue;
3238 else
3239 {
3240 $setcmd .= $prefix . $_REQUEST['portname_' . $i] . '=' . $_REQUEST['vlanid_' . $i];
3241 $prefix = ';';
3242 }
3243 printLog ($log);
3244 // Feed the gateway and interpret its (non)response.
3245 if ($setcmd != '')
3246 printLog (setSwitchVLANs ($object_id, $setcmd));
3247 }
3248
3249 // Reload and render.
3250 $data = getSwitchVLANs ($object_id);
3251 if ($data === NULL)
3252 return;
18cb9495 3253 list ($vlanlist, $portlist, $maclist) = $data;
d28ea105 3254
a684aa6f 3255 echo '<table border=0 width="100%"><tr><td colspan=3>';
d28ea105 3256
2b9e0abd 3257 startPortlet ('Current status');
18cb9495 3258 echo "<table class=widetable cellspacing=3 cellpadding=5 align=center width='100%'><tr>";
7865c525
DO
3259 echo "<form method=post>";
3260 echo "<input type=hidden name=page value='${pageno}'>";
3261 echo "<input type=hidden name=tab value='${tabno}'>";
3262 echo "<input type=hidden name=object_id value=${object_id}>";
0d591525
DO
3263 $portcount = count ($portlist);
3264 echo "<input type=hidden name=portcount value=" . $portcount . ">\n";
7865c525 3265 $portno = 0;
9c0b0016 3266 $ports_per_row = getConfigVar ('PORTS_PER_ROW');
7865c525
DO
3267 foreach ($portlist as $port)
3268 {
3269 // Don't let wide forms break our fancy pages.
9c0b0016 3270 if ($portno % $ports_per_row == 0)
fc8d0004 3271 {
7865c525
DO
3272 if ($portno > 0)
3273 echo "</tr>\n";
0d591525 3274 echo "<tr><th>" . ($portno + 1) . "-" . ($portno + $ports_per_row > $portcount ? $portcount : $portno + $ports_per_row) . "</th>";
fc8d0004 3275 }
18cb9495
DO
3276 echo '<td class=port_';
3277 if ($port['status'] == 'notconnect')
3278 echo 'notconnect';
2b9e0abd
DO
3279 elseif ($port['status'] == 'disabled')
3280 echo 'disabled';
18cb9495
DO
3281 elseif ($port['status'] != 'connected')
3282 echo 'unknown';
3283 elseif (!isset ($maclist[$port['portname']]))
3284 echo 'connected_none';
3285 else
3286 {
3287 $maccount = 0;
3288 foreach ($maclist[$port['portname']] as $vlanid => $addrs)
3289 $maccount += count ($addrs);
3290 if ($maccount == 1)
3291 echo 'connected_single';
3292 else
3293 echo 'connected_multi';
3294 }
3295 echo '>' . $port['portname'] . '<br>';
7865c525
DO
3296 echo "<input type=hidden name=portname_${portno} value=" . $port['portname'] . '>';
3297 if ($port['vlanid'] == 'trunk')
fc8d0004 3298 {
7865c525
DO
3299 echo "<input type=hidden name=vlanid_${portno} value='trunk'>";
3300 echo "<select disabled multiple='multiple' size=1><option>TRUNK</option></select>";
fc8d0004 3301 }
7865c525 3302 else
fc8d0004 3303 {
7865c525 3304 echo "<select name=vlanid_${portno}>";
8c7a0e37
DO
3305 // A port may belong to a VLAN, which is absent from the VLAN table, this is normal.
3306 // We must be able to render its SELECT properly at least.
3307 $in_table = FALSE;
d28ea105 3308 foreach ($vlanlist as $v => $d)
fc8d0004 3309 {
7865c525
DO
3310 echo "<option value=${v}";
3311 if ($v == $port['vlanid'])
8c7a0e37 3312 {
7865c525 3313 echo ' selected';
8c7a0e37
DO
3314 $in_table = TRUE;
3315 }
3316 echo ">${v}</option>\n";
fc8d0004 3317 }
8c7a0e37
DO
3318 if (!$in_table)
3319 echo "<option value=${port['vlanid']} selected>${port['vlanid']}</option>\n";
7865c525 3320 echo "</select>";
fc8d0004 3321 }
7865c525
DO
3322 $portno++;
3323 echo "</td>";
111b4a67 3324 }
9c0b0016 3325 echo "</tr><tr><td colspan=" . ($ports_per_row + 1) . "><input type=submit value='Save changes'></form></td></tr></table>";
7865c525 3326 finishPortlet();
d28ea105 3327
a684aa6f
DO
3328 echo '</td></tr><tr><td class=pcleft>';
3329 startPortlet ('VLAN table');
3330 echo '<table class=cooltable cellspacing=0 cellpadding=5 align=center width="100%">';
3331 echo "<tr><th>ID</th><th>Description</th></tr>";
3332 $order = 'even';
3333 global $nextorder;
3334 foreach ($vlanlist as $id => $descr)
3335 {
3336 echo "<tr class=row_${order}><td class=tdright>${id}</td><td class=tdleft>${descr}</td></tr>";
3337 $order = $nextorder[$order];
3338 }
3339 echo '</table>';
3340 finishPortlet();
3341
3342 echo '</td><td class=pcright>';
3343
3344 startPortlet ('Color legend');
3345 echo '<table>';
3346 echo "<tr><th>port state</th><th>color code</th></tr>";
3347 echo "<tr><td>not connected</td><td class=port_notconnect>SAMPLE</td></tr>";
3348 echo "<tr><td>disabled</td><td class=port_disabled>SAMPLE</td></tr>";
3349 echo "<tr><td>unknown</td><td class=port_unknown>SAMPLE</td></tr>";
3350 echo "<tr><td>connected with none MAC addresses active</td><td class=port_connected_none>SAMPLE</td></tr>";
3351 echo "<tr><td>connected with 1 MAC addresses active</td><td class=port_connected_single>SAMPLE</td></tr>";
3352 echo "<tr><td>connected with 1+ MAC addresses active</td><td class=port_connected_multi>SAMPLE</td></tr>";
3353 echo '</table>';
3354 finishPortlet();
3355
3356 echo '</td><td class=pcright>';
3357
18cb9495
DO
3358 if (count ($maclist))
3359 {
3360 startPortlet ('MAC address table');
3361 echo '<table border=0 class=cooltable align=center cellspacing=0 cellpadding=5>';
3362 echo "<tr><th>Port</th><th>VLAN ID</th><th>MAC address</th></tr>\n";
3363 $order = 'even';
3364 foreach ($maclist as $portname => $portdata)
3365 foreach ($portdata as $vlanid => $addrgroup)
3366 foreach ($addrgroup as $addr)
3367 {
818a43a2
DO
3368 echo "<tr class=row_${order}><td class=tdleft>$portname</td><td class=tdleft>$vlanid</td>";
3369 echo "<td class=tdleft>$addr</td></tr>\n";
18cb9495
DO
3370 $order = $nextorder[$order];
3371 }
3372 echo '</table>';
3373 finishPortlet();
3374 }
3375
18cb9495
DO
3376 // End of main table.
3377 echo '</td></tr></table>';
111b4a67
DO
3378}
3379
9c67f713
DO
3380// This snippet either renders a form inviting the user to start SNMP query
3381// on the current device or displays the result of the scan.
3382function renderSNMPPortFinder ($object_id = 0)
3383{
3384 global $root, $pageno, $tabno, $remote_username;
3385 if ($object_id <= 0)
3386 {
591ff2c4 3387 showError ('Invalid object_id', __FUNCTION__);
9c67f713
DO
3388 return;
3389 }
dd9afc41 3390// FIXME: check if SNMP PHP extension is available!
9c67f713
DO
3391 if (isset ($_REQUEST['do_scan']))
3392 {
dd9afc41 3393 $log = array();
1c4d54d4
DO
3394// IDs: http://cisco.com/en/US/products/sw/cscowork/ps2064/products_device_support_table09186a0080803bb4.html
3395// 2960: http://www.cisco.com/en/US/products/ps6406/prod_models_comparison.html
65813f73 3396// 2970: http://cisco.com/en/US/products/hw/switches/ps5206/products_qanda_item09186a00801b1750.shtml
563196e8 3397// 3500XL: http://cisco.com/en/US/products/hw/switches/ps637/products_eol_models.html
1c4d54d4 3398// 3560: http://cisco.com/en/US/products/hw/switches/ps5528/products_data_sheet09186a00801f3d7f.html
563196e8 3399// 3750: http://cisco.com/en/US/products/hw/switches/ps5023/products_data_sheet09186a008016136f.html
137b7a50 3400 $ciscomodel[283] = 'WS-C6509-E (9-slot system)';
818e40c7
DO
3401// FIXME: hwtype hardcoded value will become invalid after the Dictionary table transformation
3402// in 0.14.7 version. Either the values will have to be adjusted as well or we have to switch
3403// to value lookup (not reliable).
64d5f2b4 3404 $hwtype[283] = 148;
dd9afc41
DO
3405# $ciscomodel[694] = 'WS-C2960-24TC-L (24 Ethernet 10/100 ports and 2 dual-purpose uplinks)';
3406# $ciscomodel[695] = 'WS-C2960-48TC-L (48 Ethernet 10/100 ports and 2 dual-purpose uplinks)';
3407 $ciscomodel[696] = 'WS-C2960G-24TC-L (20 Ethernet 10/100/1000 ports and 4 dual-purpose uplinks)';
64d5f2b4 3408 $hwtype[696] = 167;
dd9afc41 3409 $ciscomodel[697] = 'WS-C2960G-48TC-L (44 Ethernet 10/100/1000 ports and 4 dual-purpose uplinks)';
64d5f2b4 3410 $hwtype[697] = 166;
dd9afc41
DO
3411# $ciscomodel[716] = 'WS-C2960-24TT-L (24 Ethernet 10/100 ports and 2 10/100/1000 uplinks)';
3412# $ciscomodel[717] = 'WS-C2960-48TT-L (48 Ethernet 10/100 ports and 2 10/100/1000 uplinks)';
65813f73 3413 $ciscomodel[527] = 'WS-C2970G-24T (24 Ethernet 10/100/1000 ports)';
64d5f2b4 3414 $hwtype[527] = 210;
65813f73
DO
3415 $ciscomodel[561] = 'WS-C2970G-24TS (24 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
3416 $hwtype[561] = 115;
137b7a50 3417# $ciscomodel[633] = 'WS-C3560-24TS (24 Ethernet 10/100 ports and 2 10/100/1000 SFP uplinks)';
64d5f2b4 3418# $hwtype[633] = 169;
137b7a50 3419 $ciscomodel[634] = 'WS-C3560-48TS (48 Ethernet 10/100 ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3420 $hwtype[634] = 170;
137b7a50 3421# $ciscomodel[563] = 'WS-C3560-24PS (24 Ethernet 10/100 POE ports and 2 10/100/1000 SFP uplinks)';
64d5f2b4 3422# $hwtype[563] = 171;
137b7a50 3423 $ciscomodel[564] = 'WS-C3560-48PS (48 Ethernet 10/100 POE ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3424 $hwtype[564] = 172;
1c4d54d4 3425 $ciscomodel[614] = 'WS-C3560G-24PS (24 Ethernet 10/100/1000 POE ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3426 $hwtype[614] = 175;
1c4d54d4 3427 $ciscomodel[615] = 'WS-C3560G-24TS (24 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3428 $hwtype[615] = 173;
1c4d54d4 3429 $ciscomodel[616] = 'WS-C3560G-48PS (48 Ethernet 10/100/1000 POE ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3430 $hwtype[616] = 176;
1c4d54d4 3431 $ciscomodel[617] = 'WS-C3560G-48TS (48 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3432 $hwtype[617] = 174;
7a9f3034 3433 $ciscomodel[58] = 'WS-C4503 (3-slot system)';
64d5f2b4 3434 $hwtype[58] = 145;
7a9f3034 3435 $ciscomodel[503] = '4503 (3-slot system)';
64d5f2b4 3436 $hwtype[503] = 145;
7a9f3034 3437 $ciscomodel[59] = 'WS-C4506 (6-slot system)';
64d5f2b4 3438 $hwtype[59] = 156;
7a9f3034 3439 $ciscomodel[502] = '4506 (6-slot system)';
64d5f2b4 3440 $hwtype[502] = 156;
3d61d4ca 3441 $ciscomodel[626] = 'WS-C4948 (48 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)';
64d5f2b4 3442 $hwtype[626] = 147;
563196e8 3443 $ciscomodel[659] = 'WS-C4948-10GE (48 Ethernet 10/100/1000 ports and 2 10Gb X2 uplinks)';
64d5f2b4 3444 $hwtype[659] = 377;
dd9afc41
DO
3445 assertStringArg ('community');
3446 $community = $_REQUEST['community'];
3447 $objectInfo = getObjectInfo ($object_id);
3448 $endpoints = findAllEndpoints ($object_id, $objectInfo['name']);
64db81c8 3449 $sysName = substr (snmpget ($endpoints[0], $community, 'sysName.0'), strlen ('STRING: '));
dd9afc41
DO
3450 $sysDescr = snmpget ($endpoints[0], $community, 'sysDescr.0');
3451 // Strip the object type, it's always string here.
3452 $sysDescr = substr ($sysDescr, strlen ('STRING: '));
1c4d54d4 3453 if (strpos ($sysDescr, 'Cisco IOS Software') === 0 or strpos ($sysDescr, 'Cisco Internetwork Operating System Software') === 0)
dd9afc41 3454 $log[] = array ('code' => 'success', 'message' => 'Seems to be a Cisco box');
818e40c7
DO
3455 else
3456 {
3457 $log[] = array ('code' => 'error', 'message' => 'No idea how to handle ' . $sysDescr);
3458 printLog ($log);
3459 return;
3460 }
3461
3462 // It's a Cisco. Go on.
3463 $attrs = getAttrValues ($object_id);
3464 // Only fill in attribute values, if they are not set.
3465 // FIXME: this is hardcoded
3466
64db81c8
DO
3467 if (empty ($attrs[3]['value']) && !empty ($sysName)) // FQDN
3468 {
3469 $error = commitUpdateAttrValue ($object_id, 3, $sysName);
3470 if ($error == TRUE)
3471 $log[] = array ('code' => 'success', 'message' => 'FQDN set to ' . $sysName);
3472 else
3473 $log[] = array ('code' => 'error', 'message' => 'Failed settig FQDN: ' . $error);
3474 }
3475
818e40c7
DO
3476 if (empty ($attrs[5]['value'])) // SW version
3477 {
3478 $IOSversion = ereg_replace ('^.*, Version ([^ ]+), .*$', '\\1', $sysDescr);
3479 $error = commitUpdateAttrValue ($object_id, 5, $IOSversion);
3480 if ($error == TRUE)
3481 $log[] = array ('code' => 'success', 'message' => 'SW version set to ' . $IOSversion);
3482 else
3483 $log[] = array ('code' => 'error', 'message' => 'Failed settig SW version: ' . $error);
3484 }
3485
20204509
DO
3486 if (empty ($attrs[4]['value'])) // switch OS type
3487 switch (substr ($IOSversion, 0, 4))
3488 {
3489 case '12.2':
3490 $error = commitUpdateAttrValue ($object_id, 4, 252);
3491 break;
3492 case '12.1':
d3239110 3493 $error = commitUpdateAttrValue ($object_id, 4, 251);
20204509
DO
3494 break;
3495 case '12.0':
d3239110 3496 $error = commitUpdateAttrValue ($object_id, 4, 244);
20204509
DO
3497 break;
3498 }
3499 if ($error == TRUE)
3500 $log[] = array ('code' => 'success', 'message' => 'Switch OS type set to Cisco IOS ' . substr ($IOSversion, 0, 4));
3501 else
3502 $log[] = array ('code' => 'error', 'message' => 'Failed settig Switch OS type');
818e40c7 3503
dd9afc41
DO
3504 $sysObjectID = snmpget ($endpoints[0], $community, 'sysObjectID.0');
3505 // Transform OID
3506 $sysObjectID = substr ($sysObjectID, strlen ('OID: SNMPv2-SMI::enterprises.9.1.'));
3507 if (!isset ($ciscomodel[$sysObjectID]))
3508 {
3509 $log[] = array ('code' => 'error', 'message' => 'Could not guess exact HW model!');
3510 printLog ($log);
3511 return;
3512 }
3513 $log[] = array ('code' => 'success', 'message' => 'HW is ' . $ciscomodel[$sysObjectID]);
818e40c7
DO
3514 if (empty ($attrs[2]['value']) and isset ($hwtype[$sysObjectID])) // switch HW type
3515 {
3516 $error = commitUpdateAttrValue ($object_id, 2, $hwtype[$sysObjectID]);
3517 if ($error == TRUE)
3d61d4ca 3518 $log[] = array ('code' => 'success', 'message' => 'HW type updated Ok');
818e40c7
DO
3519 else
3520 $log[] = array ('code' => 'error', 'message' => 'Failed settig HW type: ' . $error);
3521 }
dd9afc41
DO
3522 // Now fetch ifType, ifDescr and ifPhysAddr and let model-specific code sort the data out.
3523 $ifType = snmpwalkoid ($endpoints[0], $community, 'ifType');
3524 $ifDescr = snmpwalkoid ($endpoints[0], $community, 'ifdescr');
3525 $ifPhysAddress = snmpwalkoid ($endpoints[0], $community, 'ifPhysAddress');
3526 // Combine 3 tables into 1...
3527 $ifList1 = array();
3528 foreach ($ifType as $key => $val)
3529 {
3530 list ($dummy, $ifIndex) = explode ('.', $key);
3531 list ($dummy, $type) = explode (' ', $val);
3532 $ifList1[$ifIndex]['type'] = $type;
3533 }
3534 foreach ($ifDescr as $key => $val)
3535 {
3536 list ($dummy, $ifIndex) = explode ('.', $key);
3537 list ($dummy, $descr) = explode (' ', $val);
3538 $ifList1[$ifIndex]['descr'] = trim ($descr, '"');
3539 }
3540 foreach ($ifPhysAddress as $key => $val)
3541 {
3542 list ($dummy, $ifIndex) = explode ('.', $key);
3543 list ($dummy, $addr) = explode (':', $val);
3544 $addr = str_replace (' ', '', $addr);
3545 $ifList1[$ifIndex]['phyad'] = $addr;
3546 }
3547 // ...and then reverse it inside out to make description the key.
3548 $ifList2 = array();
3549 foreach ($ifList1 as $ifIndex => $data)
3550 {
3551 $ifList2[$data['descr']]['type'] = $data['type'];
3552 $ifList2[$data['descr']]['phyad'] = $data['phyad'];
3553 $ifList2[$data['descr']]['idx'] = $ifIndex;
3554 }
dd9afc41
DO
3555 $newports = 0;
3556 // Now we can directly pick necessary ports from the table accordingly
3557 // to our known hardware model.
3558 switch ($sysObjectID)
3559 {
3560 // FIXME: chassis edge switches often share a common naming scheme, so
3561 // the sequences below have to be generalized. Let's have some duplicated
3562 // code for the time being, as this is the first implementation ever.
3563 case '697': // WS-C2960G-48TC-L
3564 // 44 copper ports: 1X, 2X, 3X...
3565 // 4 combo ports: 45, 46, 47, 48. Don't list SFP connectors atm, as it's not
3566 // clear how to fit them into current Ports table structure.
3567 for ($i = 1; $i <= 48; $i++)
3568 {
3569 $label = ($i >= 45) ? "${i}" : "${i}X";
64d5f2b4 3570 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
dd9afc41
DO
3571 if ($error == '')
3572 $newports++;
3573 else
3574 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3575 }
3576 break;
3577 case '696': // WS-C2960G-24TC-L
3578 // Quite similar to the above.
3579 for ($i = 1; $i <= 24; $i++)
3580 {
3581 $label = ($i >= 21) ? "${i}" : "${i}X";
64d5f2b4 3582 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
dd9afc41
DO
3583 if ($error == '')
3584 $newports++;
3585 else
3586 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3587 }
3588 break;
137b7a50
DO
3589 case '564': // WS-C3560-48PS
3590 case '634': // WS-C3560-48TS
3591 for ($i = 1; $i <= 48; $i++)
3592 {
3593 $label = "${i}X";
64d5f2b4 3594 $error = commitAddPort ($object_id, 'fa0/' . $i, 19, $label, $ifList2["FastEthernet0/${i}"]['phyad']);
137b7a50
DO
3595 if ($error == '')
3596 $newports++;
3597 else
3598 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3599 }
3600 for ($i = 1; $i <= 4; $i++)
3601 {
3602 $label = "${i}";
64d5f2b4 3603 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
137b7a50
DO
3604 if ($error == '')
3605 $newports++;
3606 else
3607 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3608 }
3609 break;
1c4d54d4
DO
3610 case '614': // WS-C3560G-24PS
3611 case '615': // WS-C3560G-24TS
65813f73
DO
3612 case '527': // WS-C2970G-24T
3613 case '561': // WS-C2970G-24TS
1c4d54d4
DO
3614 for ($i = 1; $i <= 24; $i++)
3615 {
3616 $label = "${i}X";
64d5f2b4 3617 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
1c4d54d4
DO
3618 if ($error == '')
3619 $newports++;
3620 else
3621 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3622 }
3623 break;
3624 case '616': // WS-C3560G-48PS
3625 case '617': // WS-C3560G-48TS
cdc8ff71
DO
3626 for ($i = 1; $i <= 48; $i++)
3627 {
3628 $label = "${i}X";
3629 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
3630 if ($error == '')
3631 $newports++;
3632 else
3633 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
3634 }
3635 break;
3d61d4ca
DO
3636 case '626': // WS-C4948
3637 case '659': // WS-C4948-10GE
1c4d54d4
DO
3638 for ($i = 1; $i <= 48; $i++)