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