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