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