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