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