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