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