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