r1726 + bugfix: update SW type attribute for IOS 12.0 and 12.1 cases
[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 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2292 printSelect ($typelist, "${i}_object_type_id", 0);
2293 echo '</td>';
2294 echo "<td><input type=text size=30 name=${i}_object_name";
2295 if ($keepvalues and $type_id[$i] == 0)
2296 echo " value='${name[$i]}'";
2297 echo "></td>";
2298 echo "<td><input type=text size=30 name=${i}_object_label";
2299 if ($keepvalues and $type_id[$i] == 0)
2300 echo " value='${label[$i]}'";
2301 echo "></td>";
2302 echo "<td><input type=text size=20 name=${i}_object_asset_no";
2303 if ($keepvalues and $type_id[$i] == 0)
2304 echo " value='${asset_no[$i]}'";
2305 echo "></td>";
2306 echo "<td><input type=text size=10 name=${i}_object_barcode";
2307 if ($keepvalues and $type_id[$i] == 0)
2308 echo " value='${barcode[$i]}'";
2309 echo "></td>";
2310 echo "</tr>\n";
2311 }
2312 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Create'></td></tr>\n";
2313 echo "</form></table>\n";
2314 finishPortlet();
2315
2316 startPortlet ('Very fast way');
2317 echo '<form>';
2318 echo "<input type=hidden name=page value=${pageno}>";
2319 echo "<input type=hidden name=tab value=${tabno}>";
2320 echo 'For each line shown below create an object of type ';
2321 printSelect ($typelist, "global_type_id", getConfigVar ('DEFAULT_OBJECT_TYPE'));
2322 echo " <input type=submit name=got_very_fast_data value='Go!'><br>\n";
2323 echo "<textarea name=namelist cols=40 rows=25>\n";
2324 if ($keepvalues and $global_type_id == 0)
2325 echo $_REQUEST['namelist'];
2326 echo "</textarea></form>\n";
2327 finishPortlet();
2328 }
2329
2330 function printGreeting ()
2331 {
2332 global $remote_username, $accounts, $root;
2333 $account = $accounts[$remote_username];
2334 echo "Hello, ${account['user_realname']}. This is RackTables " . CODE_VERSION . ". Click <a href='${root}?logout'>here</a> to logout.";
2335 }
2336
2337 function renderSearchResults ()
2338 {
2339 global $remote_username, $root;
2340 $terms = trim ($_REQUEST['q']);
2341 if (empty ($terms))
2342 {
2343 showError ('Search string cannot be empty.', __FUNCTION__);
2344 return;
2345 }
2346 if (!authorized ($remote_username, 'object', 'default'))
2347 {
2348 showError ('You are not authorized for viewing information about objects.', __FUNCTION__);
2349 return;
2350 }
2351 // If we search for L2 address, we can either find one or find none.
2352 if
2353 (
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) or
2356 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)
2357 )
2358 // Search for L2 address.
2359 {
2360 $result = searchByl2address ($terms);
2361 if ($result !== NULL)
2362 {
2363 echo "<script language='Javascript'>document.location='${root}?page=object";
2364 echo "&hl_port_id=${result['port_id']}";
2365 echo "&object_id=${result['object_id']}';//</script>";
2366 }
2367 else
2368 echo "L2 address '${terms}' not found!";
2369 }
2370 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))
2371 // STP bridge ID: bridge priotity + port MAC address. Cut off first 4 chars and look for MAC address.
2372 {
2373 $terms = substr ($terms, 4);
2374 $result = searchByl2address ($terms);
2375 if ($result !== NULL)
2376 {
2377 echo "<script language='Javascript'>document.location='${root}?page=object";
2378 echo "&hl_port_id=${result['port_id']}";
2379 echo "&object_id=${result['object_id']}';//</script>";
2380 }
2381 else
2382 echo "L2 address '${terms}' not found!";
2383 }
2384 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))
2385 // Search for IP address.
2386 {
2387 $result = getRangeByIp ($terms);
2388 if ($result !== NULL)
2389 {
2390 echo "<script language='Javascript'>document.location='${root}?page=ipaddress";
2391 echo "&ip=${terms}";
2392 echo "';//</script>";
2393 }
2394 else
2395 echo "IP address '${terms}' not found!";
2396 return;
2397 }
2398 else
2399 // Search for objects.
2400 {
2401 $objects = getSearchResults ($terms);
2402 if (count ($objects) == 1)
2403 {
2404 $obj = current ($objects);
2405 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${obj['id']}';//</script>";
2406 }
2407 elseif (count ($objects) > 1)
2408 {
2409 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2410 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>barcode</th></tr>';
2411 $order = 'odd';
2412 global $nextorder;
2413 foreach ($objects as $obj)
2414 {
2415 echo "<tr class=row_${order}><td><a href=\"${root}?page=object&object_id=${obj['id']}\">${obj['dname']}</a></td>";
2416 echo "<td>${obj['label']}</td>";
2417 echo "<td>${obj['asset_no']}</td>";
2418 echo "<td>${obj['barcode']}</td></tr>";
2419 $order = $nextorder[$order];
2420 }
2421 echo '</table>';
2422 }
2423 else
2424 echo "Object '${terms}' not found!";
2425 }
2426 }
2427
2428 // This function prints a table of checkboxes to aid the user in toggling mount atoms
2429 // from one state to another. The first argument is rack data as
2430 // produced by getRackData(), the second is the value used for the 'unckecked' state
2431 // and the third is the value used for 'checked' state.
2432 // Usage contexts:
2433 // for mounting an object: printAtomGrid ($data, 'F', 'T')
2434 // for changing rack design: printAtomGrid ($data, 'A', 'F')
2435 // for adding rack problem: printAtomGrid ($data, 'F', 'U')
2436 // for adding object problem: printAtomGrid ($data, 'T', 'W')
2437
2438 function renderAtomGrid ($data)
2439 {
2440 $rack_id = $data['id'];
2441 for ($unit_no = $data['height']; $unit_no > 0; $unit_no--)
2442 {
2443 echo "<tr><th>${unit_no}</th>";
2444 for ($locidx = 0; $locidx < 3; $locidx++)
2445 {
2446 $state = $data[$unit_no][$locidx]['state'];
2447 echo "<td class=state_${state}";
2448 if (isset ($data[$unit_no][$locidx]['hl']))
2449 echo $data[$unit_no][$locidx]['hl'];
2450 echo ">";
2451 if (!($data[$unit_no][$locidx]['enabled'] === TRUE))
2452 echo '<input type=checkbox disabled>';
2453 else
2454 echo "<input type=checkbox" . $data[$unit_no][$locidx]['checked'] . " name=atom_${rack_id}_${unit_no}_${locidx}>";
2455 echo '</td>';
2456 }
2457 echo "</tr>\n";
2458 }
2459 }
2460
2461 function renderPermissions ()
2462 {
2463 startPortlet ('User permissions');
2464 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2465 echo "<tr><th>Username</th><th>Page</th><th>Tab</th><th>Access</th></tr>";
2466 global $perms, $nextorder;
2467 $order = 'odd';
2468 foreach ($perms as $username => $pages)
2469 foreach ($pages as $page => $tabs)
2470 foreach ($tabs as $tab => $access)
2471 {
2472 echo "<tr class=row_${order}><td class=tdleft>$username</td><td>$page</td><td>$tab</td><td>$access</td></tr>\n";
2473 $order = $nextorder[$order];
2474 }
2475 echo "</table>\n";
2476 finishPortlet();
2477 }
2478
2479 function renderAccounts ()
2480 {
2481 global $nextorder, $accounts;
2482 startPortlet ('User accounts');
2483 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2484 echo "<tr><th class=tdleft>Username</th><th class=tdleft>Real name</th></tr>";
2485 $order = 'odd';
2486 foreach ($accounts as $user)
2487 {
2488 echo "<tr class=row_${order}><td class=tdleft>${user['user_name']}</td><td class=tdleft>${user['user_realname']}</td></li>";
2489 $order = $nextorder[$order];
2490 }
2491 echo '</table>';
2492 finishPortlet();
2493 }
2494
2495 function renderAccountsEditForm ()
2496 {
2497 global $root, $pageno, $tabno, $accounts;
2498 startPortlet ('User accounts');
2499 showMessageOrError();
2500 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2501 echo "<tr><th>op</th><th>Username</th><th>Real name</th><th>Password</th><th>&nbsp;</th></tr>\n";
2502 foreach ($accounts as $account)
2503 {
2504 echo "<form action='${root}process.php'>";
2505 echo "<input type=hidden name=op value=updateAccount>";
2506 echo "<input type=hidden name=page value='${pageno}'>\n";
2507 echo "<input type=hidden name=tab value='${tabno}'>\n";
2508 echo "<input type=hidden name=id value='${account['user_id']}'><tr>";
2509 echo "<td>";
2510 if ($account['user_enabled'] == 'yes' && $account['user_id'] != 1)
2511 {
2512 echo "<a href='${root}process.php?op=disableAccount&page=${pageno}&tab=${tabno}&id=${account['user_id']}'>";
2513 printImageHREF ('blockuser', 'disable account');
2514 echo "</a>\n";
2515 }
2516 if ($account['user_enabled'] == 'no' && $account['user_id'] != 1)
2517 {
2518 echo "<a href='${root}process.php?op=enableAccount&page=${pageno}&tab=${tabno}&id=${account['user_id']}'>";
2519 printImageHREF ('unblockuser', 'enable account');
2520 echo "</a>\n";
2521 }
2522 // Otherwise skip icon.
2523 echo "</td>";
2524 echo "<td><input type=text name=username value='${account['user_name']}' size=16></td>";
2525 echo "<td><input type=text name=realname value='${account['user_realname']}' size=24></td>";
2526 echo "<td><input type=password name=password value='${account['user_password_hash']}' size=64></td>";
2527 echo "<td><input type='submit' value='OK'></td>";
2528 echo "</form></tr>\n";
2529 }
2530 echo "<form action='${root}process.php' method=post><tr>";
2531 echo "<input type=hidden name=op value=createAccount>\n";
2532 echo "<input type=hidden name=page value='${pageno}'>\n";
2533 echo "<input type=hidden name=tab value='${tabno}'>\n";
2534 echo "<td colspan=2><input type=text size=16 name=username tabindex=100></td>\n";
2535 echo "<td><input type=text size=24 name=realname tabindex=101></td>";
2536 echo "<td><input type=password size=64 name=password tabindex=102></td>";
2537 echo "<td colspan=4><input type=submit value='Create account' tabindex=103></td></tr></form>";
2538 echo "</table><br>\n";
2539 finishPortlet();
2540 }
2541
2542 function printChildrenAsOptions ($root, $depth = 0)
2543 {
2544 echo "<option value=${root['title']}>";
2545 if ($depth == 0)
2546 echo '* ';
2547 for ($i = 0; $i < $depth; $i++)
2548 echo '-- ';
2549 echo $root['title'];
2550 echo "</option>\n";
2551 foreach ($root['kids'] as $kid)
2552 printChildrenAsOptions ($kid, $depth + 1);
2553 }
2554
2555 // 1. Find all parentless pages.
2556 // 2. For each of them recursively find all children.
2557 // 3. Output the tree with recursion tree display.
2558 function printPagesTree ()
2559 {
2560 global $page;
2561 echo '<pre>';
2562 foreach ($page as $ctitle => $cpage)
2563 if (!isset ($cpage['parent']))
2564 {
2565 $croot['title'] = $ctitle;
2566 $croot['kids'] = getAllChildPages ($ctitle);
2567 printChildrenAsOptions ($croot);
2568 }
2569 echo '</pre>';
2570 }
2571
2572 function renderPermissionsEditForm ()
2573 {
2574 global $root, $pageno, $tabno, $perms, $accounts;
2575 startPortlet ('User permissions');
2576 showMessageOrError();
2577 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
2578 echo "<tr><th>&nbsp;</th><th>Username</th><th>Page</th><th>Tab</th><th>Access</th></tr>\n";
2579 foreach ($perms as $username => $pages)
2580 foreach ($pages as $access_page => $tabs)
2581 foreach ($tabs as $access_tab => $access)
2582 {
2583 echo "<td>";
2584 if ($username != '%')
2585 $userid = $accounts[$username]['user_id'];
2586 else
2587 $userid = 0;
2588 echo "<a href='${root}process.php?op=revoke&page=${pageno}&tab=${tabno}&access_userid=${userid}&access_page=${access_page}&access_tab=${access_tab}'>";
2589 printImageHREF ('revoke', 'Revoke permission');
2590 echo "</a></td>";
2591 echo "<td>${username}</td>";
2592 echo "<td>${access_page}</td>";
2593 echo "<td>${access_tab}</td>";
2594 echo "<td>${access}</td>";
2595 echo "</tr>\n";
2596 }
2597 echo "<form action='${root}process.php' method=post><tr>";
2598 echo "<input type=hidden name=op value=grant>\n";
2599 echo "<input type=hidden name=page value='${pageno}'>\n";
2600 echo "<input type=hidden name=tab value='${tabno}'>\n";
2601 // FIXME: border=0 doesn't work here for unknown reason
2602 echo "<td>";
2603 printImageHREF ('grant', '', TRUE, 103);
2604 echo "</td>";
2605 echo "<td><select name=access_userid>";
2606 echo "<option value=0>ANY</option>";
2607 foreach ($accounts as $account)
2608 echo "<option value=${account['user_id']}>${account['user_name']}</option>";
2609 echo "</select></td>\n";
2610 echo "<td><select name=access_page>";
2611 echo "<option value='%'>ANY</option>";
2612 printPagesTree();
2613 echo "</select></td>";
2614 echo "<td><input type=text size=16 name=access_tab tabindex=102 value=default></td>";
2615 echo "<td><input type=radio name=access_value value=no checked>no <input type=radio name=access_value value=yes>yes</td>";
2616 echo "</tr></form>";
2617 echo "</table><br>\n";
2618 finishPortlet();
2619 }
2620
2621 function renderPortMap ($editable = FALSE)
2622 {
2623 global $nextorder, $root, $pageno, $tabno;
2624 showMessageOrError();
2625 startPortlet ("Port compatibility map");
2626 $ptlist = getPortTypes();
2627 $pclist = getPortCompat();
2628 $pctable = buildPortCompatMatrixFromList ($ptlist, $pclist);
2629 if ($editable)
2630 {
2631 echo "<form method=post action='${root}process.php'>";
2632 echo "<input type=hidden name=page value='${pageno}'>";
2633 echo "<input type=hidden name=tab value='${tabno}'>";
2634 echo "<input type=hidden name=op value=save>";
2635 }
2636 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2637 echo "<tr><th class=vert_th>&nbsp;</th>";
2638 foreach ($ptlist as $name2)
2639 echo "<th>to ${name2}</th>";
2640 echo "</tr>";
2641 // Make a copy to have an independent array pointer.
2642 $ptlistY = $ptlist;
2643 $order = 'odd';
2644 foreach ($ptlistY as $type1 => $name1)
2645 {
2646 echo "<tr class=row_${order}><th class=vert_th style='border-bottom: 0px;'>from $name1</th>";
2647 foreach ($ptlist as $type2 => $name2)
2648 {
2649 echo '<td><input type=checkbox' . ($editable ? " name=atom_${type1}_${type2}" : ' disabled');
2650 echo ($pctable[$type1][$type2] ? ' checked' : '') . '></td>';
2651 }
2652 echo "</tr>\n";
2653 $order = $nextorder[$order];
2654 }
2655 echo '</table><br>';
2656 if ($editable)
2657 {
2658 echo "<input type=submit value='Save changes'>";
2659 echo "</form>";
2660 }
2661 finishPortlet();
2662 }
2663
2664 function renderConfigMainpage ()
2665 {
2666 global $pageno, $root;
2667 $children = getDirectChildPages ($pageno);
2668 echo '<ul>';
2669 // FIXME: assume all config kids to have static titles at the moment,
2670 // but use some proper abstract function later.
2671 foreach ($children as $cpageno => $child)
2672 echo "<li><a href='${root}?page=${cpageno}'>" . $child['title'] . "</li>\n";
2673 echo '';
2674 echo '</ul>';
2675 }
2676
2677 function renderRackPage ($rack_id)
2678 {
2679 if ($rack_id == 0)
2680 {
2681 showError ('Invalid rack_id', __FUNCTION__);
2682 return;
2683 }
2684 if (($rackData = getRackData ($rack_id)) == NULL)
2685 {
2686 showError ('getRackData() failed', __FUNCTION__);
2687 return;
2688 }
2689 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
2690
2691 // Left column with information.
2692 echo "<td class=pcleft>";
2693 startPortlet ('Rack information');
2694 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2695 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
2696 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
2697 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
2698 echo "<tr><th width='50%' class=tdright>Utilization:</th><td class=tdleft>";
2699 renderProgressBar (getRSUforRack ($rackData));
2700 echo "</td></tr>\n";
2701 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
2702 echo getObjectCount ($rackData);
2703 echo "</td></tr>\n";
2704 if (!empty ($rackData['comment']))
2705 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
2706 echo '</table>';
2707 finishPortlet();
2708 echo '</td>';
2709
2710 // Right column with rendered rack.
2711 echo '<td>';
2712 startPortlet ('Rack diagram');
2713 renderRack ($rack_id);
2714 finishPortlet();
2715 echo '</td>';
2716
2717 echo '</tr></table>';
2718 }
2719
2720 function renderDictionary ()
2721 {
2722 global $nextorder;
2723 $dict = getDict();
2724 echo "<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2725 foreach ($dict as $chapter_no => $chapter)
2726 {
2727 $order = 'odd';
2728 echo "<tr><th>Chapter</th><th>refs</th><th>Word</th></tr>\n";
2729 $wc = count ($chapter['word']);
2730 echo "<tr class=row_${order}><td class=tdleft" . ($wc ? " rowspan = ${wc}" : '');
2731 echo "><div title='number=${chapter_no}'>${chapter['name']} (${wc} records)</div></td>";
2732 if (!$wc)
2733 echo "<td colspan=2>none</td>";
2734 else
2735 {
2736 $chap_start = TRUE;
2737 foreach ($chapter['word'] as $key => $value)
2738 {
2739 if (!$chap_start)
2740 echo "<tr class=row_${order}>";
2741 else
2742 $chap_start = FALSE;
2743 echo '<td>' . ($chapter['refcnt'][$key] ? $chapter['refcnt'][$key] : '&nbsp;') . '</td>';
2744 echo "<td><div title='key=${key}'>${value}</div></td></tr>\n";
2745 $order = $nextorder[$order];
2746 }
2747 }
2748 }
2749 echo "</table>\n";
2750 }
2751
2752 function renderDictionaryEditor ()
2753 {
2754 global $root, $pageno, $tabno, $nextorder;
2755 $dict = getDict();
2756 showMessageOrError();
2757 echo "<br><table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2758 foreach ($dict as $chapter_no => $chapter)
2759 {
2760 $order = 'odd';
2761 echo "<tr><th>Chapter</th><th>&nbsp;</th><th>Word</th><th>&nbsp;</th></tr>\n";
2762 $wc = count ($chapter['word']);
2763 // One extra span for the new record per each chapter block.
2764 echo "<tr class=row_${order}><td class=tdleft" . ($wc ? ' rowspan = ' . ($wc + 1) : '');
2765 echo "><div title='number=${chapter_no}'>${chapter['name']} (${wc} records)</div></td>";
2766 echo "<form action='${root}process.php' method=post>";
2767 echo "<input type=hidden name=page value='${pageno}'>";
2768 echo "<input type=hidden name=tab value='${tabno}'>";
2769 echo "<input type=hidden name=op value=add>";
2770 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2771 echo "<td>&nbsp;</td>";
2772 echo "<td class=tdright><input type=text name=dict_value size=32></td>";
2773 echo "<td><input type=submit value='Add new'></td>";
2774 echo '</tr></form>';
2775 $order = $nextorder[$order];
2776 foreach ($chapter['word'] as $key => $value)
2777 {
2778 echo "<form action='${root}process.php' method=post>";
2779 echo "<input type=hidden name=page value='${pageno}'>";
2780 echo "<input type=hidden name=tab value='${tabno}'>";
2781 echo "<input type=hidden name=op value='upd'>";
2782 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2783 echo "<input type=hidden name=dict_key value='${key}'>";
2784 echo "<tr class=row_${order}><td>";
2785 // Prevent deleting words currently used somewhere.
2786 if ($chapter['refcnt'][$key])
2787 printImageHREF ('nodelete', 'referenced ' . $chapter['refcnt'][$key] . ' time(s)');
2788 else
2789 {
2790 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}&dict_key=${key}'>";
2791 printImageHREF ('delete', 'Delete word');
2792 echo "</a>";
2793 }
2794 echo '</td>';
2795 echo "<td class=tdright><input type=text name=dict_value size=32 value='${value}'></td>";
2796 echo "<td><input type=submit value=OK></td>";
2797 echo "</tr></form>\n";
2798 $order = $nextorder[$order];
2799 } // foreach ($chapter['word']
2800 } // foreach ($dict
2801 echo "</table>\n";
2802 }
2803
2804 // We don't allow to rename/delete a sticky chapter and we don't allow
2805 // to delete a non-empty chapter.
2806 function renderChaptersEditor ()
2807 {
2808 global $root, $pageno, $tabno;
2809 showMessageOrError();
2810 $dict = getDict();
2811 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2812 echo '<tr><th>&nbsp;</th><th>Chapter name</th><th>Words</th><th>&nbsp;</th></tr>';
2813 foreach ($dict as $chapter)
2814 {
2815 $wordcount = count ($chapter['word']);
2816 $sticky = $chapter['sticky'];
2817 echo "<form action='${root}process.php' method=post>";
2818 echo "<input type=hidden name=page value='${pageno}'>";
2819 echo "<input type=hidden name=tab value='${tabno}'>";
2820 echo "<input type=hidden name=op value=upd>";
2821 echo "<input type=hidden name=chapter_no value='${chapter['no']}'>";
2822 echo '<tr>';
2823 echo '<td>';
2824 if ($sticky)
2825 printImageHREF ('nodelete', 'system chapter');
2826 elseif ($wordcount > 0)
2827 printImageHREF ('nodelete', 'contains ' . $wordcount . ' word(s)');
2828 else
2829 {
2830 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&chapter_no=${chapter['no']}'>";
2831 printImageHREF ('delete', 'Remove chapter');
2832 echo "</a>";
2833 }
2834 echo '</td>';
2835 echo "<td><input type=text name=chapter_name value='${chapter['name']}'" . ($sticky ? ' disabled' : '') . "></td>";
2836 echo "<td class=tdleft>${wordcount}</td><td>";
2837 if ($sticky)
2838 echo '&nbsp;';
2839 else
2840 echo "<input type=submit value='OK'>";
2841 echo '</td></tr>';
2842 echo '</form>';
2843 }
2844 echo "<form action='${root}process.php' method=post>";
2845 echo "<input type=hidden name=page value='${pageno}'>";
2846 echo "<input type=hidden name=tab value='${tabno}'>";
2847 echo "<input type=hidden name=op value=add>";
2848 echo '<tr><td>';
2849 printImageHREF ('add', '', TRUE);
2850 echo "</td><td colspan=3><input type=text name=chapter_name></td>";
2851 echo '</tr>';
2852 echo '</form>';
2853 echo "</table>\n";
2854 }
2855
2856 function renderAttributes ()
2857 {
2858 global $nextorder;
2859 $attrMap = getAttrMap();
2860 startPortlet ('Optional attributes');
2861 echo "<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center>\n";
2862 echo "<tr><th class=tdleft>Attribute name</th><th class=tdleft>Attribute type</th><th class=tdleft>Applies to</th></tr>";
2863 $order = 'odd';
2864 foreach ($attrMap as $attr)
2865 {
2866 echo "<tr class=row_${order}>";
2867 echo "<td class=tdleft>${attr['name']}</td>";
2868 echo "<td class=tdleft>${attr['type']}</td>";
2869 echo '<td class=tdleft>';
2870 if (count ($attr['application']) == 0)
2871 echo '&nbsp;';
2872 else
2873 foreach ($attr['application'] as $app)
2874 if ($attr['type'] == 'dict')
2875 echo "${app['objtype_name']} (values from '${app['chapter_name']}')<br>";
2876 else
2877 echo "${app['objtype_name']}<br>";
2878 echo '</td>';
2879 echo "</tr>\n";
2880 $order = $nextorder[$order];
2881 }
2882 echo "</table><br>\n";
2883 finishPortlet();
2884 }
2885
2886 function renderEditAttributesForm ()
2887 {
2888 global $root, $pageno, $tabno;
2889 $attrMap = getAttrMap();
2890 showMessageOrError();
2891 startPortlet ('Optional attributes');
2892 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2893 echo '<tr><th>&nbsp;</th><th>Name</th><th>Type</th><th>&nbsp;</th></tr>';
2894 foreach ($attrMap as $attr)
2895 {
2896 echo "<form action='${root}process.php' method=post>";
2897 echo "<input type=hidden name=page value='${pageno}'>";
2898 echo "<input type=hidden name=tab value='${tabno}'>";
2899 echo "<input type=hidden name=op value=upd>";
2900 echo "<input type=hidden name=attr_id value='${attr['id']}'>";
2901 echo '<tr>';
2902 echo "<td><a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&attr_id=${attr['id']}'>";
2903 printImageHREF ('delete', 'Remove attribute');
2904 echo '</a></td>';
2905 echo "<td><input type=text name=attr_name value='${attr['name']}'></td>";
2906 echo "<td>${attr['type']}</td>";
2907 echo "<td><input type=submit value='OK'></td>";
2908 echo '</tr>';
2909 echo '</form>';
2910 }
2911 echo "<form action='${root}process.php' method=post>";
2912 echo "<input type=hidden name=page value='${pageno}'>";
2913 echo "<input type=hidden name=tab value='${tabno}'>";
2914 echo "<input type=hidden name=op value=add>";
2915 echo '<tr><td>';
2916 printImageHREF ('add', '', TRUE);
2917 echo "</td><td><input type=text name=attr_name></td>";
2918 echo '<td><select name=attr_type>';
2919 echo '<option value=uint>uint</option>';
2920 echo '<option value=float>float</option>';
2921 echo '<option value=string>string</option>';
2922 echo '<option value=dict>dict</option>';
2923 echo '</select></td>';
2924 echo '</tr>';
2925 echo '</form>';
2926 echo "</table>\n";
2927 finishPortlet();
2928 }
2929
2930 function renderEditAttrMapForm ()
2931 {
2932 global $root, $pageno, $tabno;
2933 $attrMap = getAttrMap();
2934 showMessageOrError();
2935 startPortlet ('Attribute map');
2936 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
2937 echo '<tr><th>&nbsp;</th><th>Attribute name</th><th>Object type</th><th>Dictionary chapter</th></tr>';
2938 foreach ($attrMap as $attr)
2939 {
2940 if (count ($attr['application']) == 0)
2941 continue;
2942 foreach ($attr['application'] as $app)
2943 {
2944 echo '<tr>';
2945 echo '<td>';
2946 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=del&";
2947 echo "attr_id=${attr['id']}&objtype_id=${app['objtype_id']}'>";
2948 printImageHREF ('delete', 'Remove mapping');
2949 echo "</a>";
2950 echo '</td>';
2951 echo "<td>${attr['name']}</td>";
2952 echo "<td>${app['objtype_name']}</td>";
2953 echo "<td>";
2954 if ($attr['type'] == 'dict')
2955 echo "${app['chapter_name']}";
2956 else
2957 echo '&nbsp;';
2958 echo "</td></tr>\n";
2959 }
2960 }
2961 echo "<form action='${root}process.php' method=post>";
2962 echo "<input type=hidden name=page value='${pageno}'>";
2963 echo "<input type=hidden name=tab value='${tabno}'>";
2964 echo "<input type=hidden name=op value=add>";
2965 echo '<tr><td>';
2966 printImageHREF ('add', '', TRUE);
2967 echo "</td><td><select name=attr_id>";
2968 $shortType['uint'] = 'U';
2969 $shortType['float'] = 'F';
2970 $shortType['string'] = 'S';
2971 $shortType['dict'] = 'D';
2972 foreach ($attrMap as $attr)
2973 echo "<option value=${attr['id']}>[" . $shortType[$attr['type']] . "] ${attr['name']}</option>";
2974 echo "</select></td>";
2975 echo '<td>';
2976 printSelect (getObjectTypeList(), 'objtype_id');
2977 echo '</td>';
2978 $dict = getDict();
2979 echo '<td><select name=chapter_no>';
2980 foreach ($dict as $chapter)
2981 if (!$chapter['sticky'])
2982 echo "<option value='${chapter['no']}'>${chapter['name']}</option>";
2983 echo '</select></td>';
2984 echo '</tr>';
2985 echo '</form>';
2986 echo "</table>\n";
2987 finishPortlet();
2988 }
2989
2990 function printImageHREF ($tag, $title = '', $do_input = FALSE, $tabindex = 0)
2991 {
2992 global $root;
2993 $image['error']['path'] = 'pix/error.png';
2994 $image['error']['width'] = 76;
2995 $image['error']['height'] = 17;
2996 $image['logo']['path'] = 'pix/defaultlogo.png';
2997 $image['logo']['width'] = 210;
2998 $image['logo']['height'] = 40;
2999 $image['rackspace']['path'] = 'pix/racks.png';
3000 $image['rackspace']['width'] = 218;
3001 $image['rackspace']['height'] = 200;
3002 $image['objects']['path'] = 'pix/server.png';
3003 $image['objects']['width'] = 218;
3004 $image['objects']['height'] = 200;
3005 $image['ipv4space']['path'] = 'pix/addressspace.png';
3006 $image['ipv4space']['width'] = 218;
3007 $image['ipv4space']['height'] = 200;
3008 $image['ipv4slb']['path'] = 'pix/slb.png';
3009 $image['ipv4slb']['width'] = 218;
3010 $image['ipv4slb']['height'] = 200;
3011 $image['config']['path'] = 'pix/configuration.png';
3012 $image['config']['width'] = 218;
3013 $image['config']['height'] = 200;
3014 $image['reports']['path'] = 'pix/report.png';
3015 $image['reports']['width'] = 218;
3016 $image['reports']['height'] = 200;
3017 $image['help']['path'] = 'pix/help.png';
3018 $image['help']['width'] = 218;
3019 $image['help']['height'] = 200;
3020 $image['reserve']['path'] = 'pix/stop.png';
3021 $image['reserve']['width'] = 16;
3022 $image['reserve']['height'] = 16;
3023 $image['useup']['path'] = 'pix/go.png';
3024 $image['useup']['width'] = 16;
3025 $image['useup']['height'] = 16;
3026 $image['blockuser'] = $image['reserve'];
3027 $image['unblockuser'] = $image['useup'];
3028 $image['link']['path'] = 'pix/link.png';
3029 $image['link']['width'] = 24;
3030 $image['link']['height'] = 24;
3031 $image['unlink']['path'] = 'pix/unlink.png';
3032 $image['unlink']['width'] = 24;
3033 $image['unlink']['height'] = 24;
3034 $image['add']['path'] = 'pix/greenplus.png';
3035 $image['add']['width'] = 16;
3036 $image['add']['height'] = 16;
3037 $image['delete']['path'] = 'pix/delete_s.gif';
3038 $image['delete']['width'] = 16;
3039 $image['delete']['height'] = 16;
3040 $image['nodelete']['path'] = 'pix/delete_g.png';
3041 $image['nodelete']['width'] = 16;
3042 $image['nodelete']['height'] = 16;
3043 $image['grant'] = $image['add'];
3044 $image['revoke'] = $image['delete'];
3045 $image['helphint']['path'] = 'pix/helphint.png';
3046 $image['helphint']['width'] = 24;
3047 $image['helphint']['height'] = 24;
3048 $image['inservice']['path'] = 'pix/go.png';
3049 $image['inservice']['width'] = 16;
3050 $image['inservice']['height'] = 16;
3051 $image['notinservice']['path'] = 'pix/stop.png';
3052 $image['notinservice']['width'] = 16;
3053 $image['notinservice']['height'] = 16;
3054 $image['find']['path'] = 'pix/find.png';
3055 $image['find']['width'] = 16;
3056 $image['find']['height'] = 16;
3057 if (!isset ($image[$tag]))
3058 $tag = 'error';
3059 $img = $image[$tag];
3060 if ($do_input == TRUE)
3061 echo
3062 "<input type=image name=submit " .
3063 "src='${root}${img['path']}' " .
3064 "border=0 " .
3065 ($tabindex ? '' : "tabindex=${tabindex}") .
3066 ">";
3067 else
3068 echo
3069 "<img " .
3070 "src='${root}${img['path']}' " .
3071 "width=${img['width']} " .
3072 "height=${img['height']} " .
3073 "border=0 " .
3074 (empty ($title) ? '' : "title='${title}'") .
3075 ">";
3076 }
3077
3078 // This function returns URL for favourite icon.
3079 function getFaviconURL ()
3080 {
3081 global $root;
3082 return $root . 'pix/racktables.ico';
3083 }
3084
3085 function renderReportSummary ()
3086 {
3087 echo "<table width='100%'>\n";
3088 echo "<tr><td class=pcleft>\n";
3089 startPortlet ("Dictionary/objects stats");
3090 echo "<table>\n";
3091 foreach (getDictStats() as $header => $data)
3092 echo "<tr><th class=tdright>${header}:</th><td class=tdleft>${data}</td></tr>\n";
3093 echo "</table>\n";
3094 finishPortlet();
3095 startPortlet ('IPv4 stats');
3096 echo "<table>\n";
3097 foreach (getIPv4Stats() as $header => $data)
3098 echo "<tr><th class=tdright>${header}:</th><td class=tdleft>${data}</td></tr>\n";
3099 echo "</table>\n";
3100 finishPortlet();
3101 startPortlet ('Rackspace stats');
3102 echo "<table>\n";
3103 foreach (getRackspaceStats() as $header => $data)
3104 echo "<tr><th class=tdright>${header}:</th><td class=tdleft>${data}</td></tr>\n";
3105 echo "</table>\n";
3106 finishPortlet();
3107
3108 echo "</td><td class=pcright>\n";
3109
3110 startPortlet ("Here be dragons");
3111 dragon();
3112 dragon();
3113 dragon();
3114 echo 'ASCII art &copy; Daniel C. Au';
3115 finishPortlet();
3116 echo "</td></tr>\n";
3117 echo "</table>\n";
3118 }
3119
3120 function dragon ()
3121 {
3122 ?>
3123 <div class=dragon><pre><font color="#00ff33">
3124 \||/
3125 | <font color="#ff0000">@</font>___oo
3126 /\ /\ / (__<font color=yellow>,,,,</font>|
3127 ) /^\) ^\/ _)
3128 ) /^\/ _)
3129 ) _ / / _)
3130 /\ )/\/ || | )_)
3131 &lt; &gt; |(<font color=white>,,</font>) )__)
3132 || / \)___)\
3133 | \____( )___) )___
3134 \______(_______<font color=white>;;;</font> __<font color=white>;;;</font>
3135
3136 </font></pre></div>
3137 <?php
3138 }
3139
3140 function renderUIConfig ()
3141 {
3142 global $configCache, $nextorder;
3143 showMessageOrError();
3144 startPortlet ('Current configuration');
3145 echo '<table class=cooltable border=0 cellpadding=5 cellspacing=0 align=center width="50%">';
3146 echo '<tr><th class=tdleft>Option</th><th class=tdleft>Value</th></tr>';
3147 $order = 'odd';
3148 foreach ($configCache as $v)
3149 {
3150 if ($v['is_hidden'] != 'no')
3151 continue;
3152 echo "<tr class=row_${order}>";
3153 echo "<td class=tdright>${v['description']}</td>\n";
3154 echo "<td class=tdleft>${v['varvalue']}</td></tr>";
3155 $order = $nextorder[$order];
3156 }
3157 echo "</table>\n";
3158 finishPortlet();
3159 }
3160
3161 function renderUIConfigEditForm ()
3162 {
3163 global $root, $pageno, $tabno, $configCache;
3164 showMessageOrError();
3165 startPortlet ('Current configuration');
3166 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='50%'>\n";
3167 echo "<tr><th class=tdleft>Option</th>";
3168 echo "<th class=tdleft>Value</th></tr>";
3169 echo "<form action='${root}process.php'>";
3170 echo "<input type=hidden name=op value='upd'>";
3171 echo "<input type=hidden name=page value='${pageno}'>\n";
3172 echo "<input type=hidden name=tab value='${tabno}'>\n";
3173
3174 $i = 0;
3175 foreach ($configCache as $v)
3176 {
3177 if ($v['is_hidden'] != 'no')
3178 continue;
3179 echo "<input type=hidden name=${i}_varname value='${v['varname']}'>";
3180 echo "<tr><td class=tdright>${v['description']}</td>";
3181 echo "<td class=tdleft><input type=text name=${i}_varvalue value='${v['varvalue']}' size=24></td>";
3182 echo "</tr>\n";
3183 $i++;
3184 }
3185 echo "<input type=hidden name=num_vars value=${i}>\n";
3186 echo "<tr><td colspan=2><input type=submit value='Save changes'></td></tr>";
3187 echo "</form>";
3188 finishPortlet();
3189 }
3190
3191 // This function queries the gateway about current VLAN configuration and
3192 // renders a form suitable for submit. Ah, and it does submit processing as well.
3193 function renderVLANMembership ($object_id = 0)
3194 {
3195 global $root, $pageno, $tabno, $remote_username;
3196 if ($object_id <= 0)
3197 {
3198 showError ('Invalid object_id', __FUNCTION__);
3199 return;
3200 }
3201
3202 // Handle probable pending submit.
3203 if (isset ($_REQUEST['portcount']))
3204 {
3205 $data = getSwitchVLANs ($object_id);
3206 if ($data === NULL)
3207 {
3208 showError ('getSwitchVLANs() failed during submit processing', __FUNCTION__);
3209 return;
3210 }
3211 list ($vlanlist, $portlist) = $data;
3212 // Here we just build up 1 set command for the gateway with all of the ports
3213 // included. The gateway is expected to filter unnecessary changes silently
3214 // and to provide a list of responses with either error or success message
3215 // for each of the rest.
3216 assertUIntArg ('portcount');
3217 $nports = $_REQUEST['portcount'];
3218 $prefix = 'set ';
3219 $log = array();
3220 $setcmd = '';
3221 for ($i = 0; $i < $nports; $i++)
3222 if
3223 (
3224 !isset ($_REQUEST['portname_' . $i]) ||
3225 !isset ($_REQUEST['vlanid_' . $i]) ||
3226 $_REQUEST['portname_' . $i] != $portlist[$i]['portname']
3227 )
3228 $log[] = array ('code' => 'error', 'message' => "Ignoring malformed record #${i} in form submit");
3229 elseif
3230 (
3231 $_REQUEST['vlanid_' . $i] == $portlist[$i]['vlanid'] ||
3232 $portlist[$i]['vlaind'] == 'TRUNK'
3233 )
3234 continue;
3235 else
3236 {
3237 $setcmd .= $prefix . $_REQUEST['portname_' . $i] . '=' . $_REQUEST['vlanid_' . $i];
3238 $prefix = ';';
3239 }
3240 printLog ($log);
3241 // Feed the gateway and interpret its (non)response.