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