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