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