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