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