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