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