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