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