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