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