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