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