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