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