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