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