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