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