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