r2960 - maintenance->trunk sync of changeset:2953
[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
1480 // records 200~299 with warnings
1481 200 => array ('code' => 'warning', 'format' => '%s'),
1482 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1483 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
1484 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1485 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1486 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
1487 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
1488 207 => array ('code' => 'warning', 'format' => 'Ignored empty request'),
1489
1490 );
1491 // Handle the arguments. Is there any better way to do it?
1492 foreach ($log['m'] as $record)
1493 {
1494 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1495 {
1496 echo '<div class=msg_neutral>(this message was lost)</div>';
1497 continue;
1498 }
1499 if (isset ($record['a']))
1500 switch (count ($record['a']))
1501 {
1502 case 1:
1503 $msgtext = sprintf
1504 (
1505 $msginfo[$record['c']]['format'],
1506 $record['a'][0]
1507 );
1508 break;
1509 case 2:
1510 $msgtext = sprintf
1511 (
1512 $msginfo[$record['c']]['format'],
1513 $record['a'][0],
1514 $record['a'][1]
1515 );
1516 break;
1517 case 3:
1518 $msgtext = sprintf
1519 (
1520 $msginfo[$record['c']]['format'],
1521 $record['a'][0],
1522 $record['a'][1],
1523 $record['a'][2]
1524 );
1525 break;
1526 case 4:
1527 default:
1528 $msgtext = sprintf
1529 (
1530 $msginfo[$record['c']]['format'],
1531 $record['a'][0],
1532 $record['a'][1],
1533 $record['a'][2],
1534 $record['a'][3]
1535 );
1536 break;
1537 }
1538 else
1539 $msgtext = $msginfo[$record['c']]['format'];
1540 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1541 }
1542 break;
1543 default:
1544 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1545 break;
1546 }
1547 unset($_SESSION['log']);
1548 }
1549
1550 /*
1551 The following conditions must be followed:
1552 1. We can mount onto free atoms only. This means: if any record for an atom
1553 already exists in RackSpace, it can't be used for mounting.
1554 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1555 and either delete them before unmounting or refuse to unmount the object.
1556 */
1557
1558 // We extensively use $_REQUEST in the function.
1559 function renderRackSpaceForObject ($object_id)
1560 {
1561 $is_update = isset ($_REQUEST['rackmulti'][0]);
1562 $info = spotEntity ('object', $object_id);
1563 if ($info == NULL)
1564 {
1565 showError ('Error loading data', __FUNCTION__);
1566 return;
1567 }
1568 // Always process occupied racks plus racks chosen by user. First get racks with
1569 // already allocated rackspace...
1570 if (NULL === ($workingRacksData = getResidentRacksData ($object_id)))
1571 die; // some error already shown
1572
1573 // ...and then add those chosen by user (if any).
1574 if (isset($_REQUEST['rackmulti']))
1575 foreach ($_REQUEST['rackmulti'] as $cand_id)
1576 {
1577 if (!isset ($workingRacksData[$cand_id]))
1578 {
1579 if (NULL == ($rackData = spotEntity ('rack', $cand_id)))
1580 {
1581 showError ('Rack not found', __FUNCTION__);
1582 return NULL;
1583 }
1584 amplifyCell ($rackData);
1585 $workingRacksData[$cand_id] = $rackData;
1586 }
1587 }
1588
1589 printOpFormIntro ('updateObjectAllocation');
1590
1591 // Do it only once...
1592 foreach ($workingRacksData as $rackId => &$rackData)
1593 {
1594 applyObjectMountMask ($rackData, $object_id);
1595 echo "<input type=\"hidden\" name=\"rackmulti[]\" value=\"$rackId\">";
1596 }
1597 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1598 unset ($rackData);
1599
1600 // This is the time for rendering.
1601
1602 // Main layout starts.
1603 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1604
1605 // Left portlet with rack list.
1606 echo "<td class=pcleft height='1%'>";
1607 startPortlet ('Racks');
1608 $allRacksData = listCells ('rack');
1609 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1610 {
1611 foreach ($allRacksData as $rack)
1612 {
1613 amplifyCell ($rack);
1614 $workingRacksData[$rack_id] = $rack;
1615 }
1616 foreach ($workingRacksData as &$rackData)
1617 applyObjectMountMask ($rackData, $object_id);
1618 unset ($rackData);
1619 }
1620 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1621 echo "<br>";
1622 echo "<br>";
1623 finishPortlet();
1624 echo "</td>";
1625
1626 // Middle portlet with comment and submit.
1627 echo "<td class=pcleft>";
1628 startPortlet ('Comment');
1629 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1630 echo "<input type=submit value='Save' name=got_atoms>\n";
1631 echo "<br>";
1632 echo "<br>";
1633 finishPortlet();
1634 echo "</td>";
1635
1636 // Right portlet with rendered racks. If this form submit is not final, we have to
1637 // reflect the former state of the grid in current form.
1638 echo "<td class=pcright rowspan=2 height='1%'>";
1639 startPortlet ('Working copy');
1640 echo '<table border=0 cellspacing=10 align=center><tr>';
1641 foreach ($workingRacksData as $rack_id => $rackData)
1642 {
1643 // Order is important here: only original allocation is highlighted.
1644 highlightObject ($rackData, $object_id);
1645 markupAtomGrid ($rackData, 'T');
1646 // If we have a form processed, discard user input and show new database
1647 // contents.
1648 if ($is_update)
1649 mergeGridFormToRack ($rackData);
1650 echo "<td valign=top>";
1651 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1652 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1653 echo "<tr><th width='10%'>&nbsp;</th>";
1654 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1655 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1656 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1657 renderAtomGrid ($rackData);
1658 echo "<tr><th width='10%'>&nbsp;</th>";
1659 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1660 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1661 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1662 echo "</table></center>\n";
1663 echo '</td>';
1664 }
1665 echo "</tr></table>";
1666 finishPortlet();
1667 echo "</td>\n";
1668
1669
1670 echo "</form>\n";
1671 echo "</tr></table>\n";
1672 }
1673
1674 function renderMolecule ($mdata, $object_id)
1675 {
1676 // sort data out
1677 $rackpack = array();
1678 global $loclist;
1679 foreach ($mdata as $rua)
1680 {
1681 $rack_id = $rua['rack_id'];
1682 $unit_no = $rua['unit_no'];
1683 $atom = $rua['atom'];
1684 if (!isset ($rackpack[$rack_id]))
1685 {
1686 $rackData = spotEntity ('rack', $rack_id);
1687 amplifyCell ($rackData);
1688 for ($i = $rackData['height']; $i > 0; $i--)
1689 for ($locidx = 0; $locidx < 3; $locidx++)
1690 $rackData[$i][$locidx]['state'] = 'F';
1691 $rackpack[$rack_id] = $rackData;
1692 }
1693 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1694 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1695 }
1696 // now we have some racks to render
1697 foreach ($rackpack as $rackData)
1698 {
1699 markAllSpans ($rackData);
1700 echo "<table class=molecule cellspacing=0>\n";
1701 echo "<caption>${rackData['name']}</caption>\n";
1702 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1703 for ($i = $rackData['height']; $i > 0; $i--)
1704 {
1705 echo "<tr><th>$i</th>";
1706 for ($locidx = 0; $locidx < 3; $locidx++)
1707 {
1708 $state = $rackData[$i][$locidx]['state'];
1709 echo "<td class=state_${state}>&nbsp;</td>\n";
1710 }
1711 echo "</tr>\n";
1712 }
1713 echo "</table>\n";
1714 }
1715 }
1716
1717 function renderEmptyPortsSelect ($port_id, $type_id)
1718 {
1719 $ports = getEmptyPortsOfType($type_id);
1720 usort($ports, 'sortEmptyPorts');
1721 foreach ($ports as $port)
1722 {
1723 if ($port_id == $port['Port_id'])
1724 continue;
1725 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";
1726 }
1727 }
1728
1729 function renderDepot ()
1730 {
1731 global $pageno, $nextorder;
1732 $cellfilter = getCellFilter();
1733 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
1734
1735 echo "<table border=0 class=objectview>\n";
1736 echo "<tr><td class=pcleft>";
1737
1738 startPortlet ('Objects (' . count ($objects) . ')');
1739 if ($objects === NULL)
1740 {
1741 showError ('Fatal error retrieving object list', __FUNCTION__);
1742 return;
1743 }
1744 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1745 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Row/Rack</th></tr>';
1746 $order = 'odd';
1747 foreach ($objects as $obj)
1748 {
1749 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1750 $secondclass = 'tdleft port_highlight';
1751 else
1752 $secondclass = 'tdleft';
1753 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>";
1754 if (count ($obj['etags']))
1755 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
1756 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
1757 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
1758 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
1759 if ($obj['rack_id'])
1760 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>";
1761 else
1762 echo "<td class='${secondclass}'>Unmounted</td>";
1763 echo '</tr>';
1764 $order = $nextorder[$order];
1765 }
1766 echo '</table>';
1767 finishPortlet();
1768
1769 echo "</td><td class=pcright width='25%'>";
1770
1771 renderCellFilterPortlet ($cellfilter, 'object');
1772 echo "</td></tr></table>\n";
1773 }
1774
1775 // History viewer for history-enabled simple dictionaries.
1776 function renderHistory ($object_type, $object_id)
1777 {
1778 switch ($object_type)
1779 {
1780 case 'row':
1781 $query = "select ctime, user_name, name, comment from RackRowHistory where id = ${object_id} order by ctime";
1782 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>rack row comment</th></tr>';
1783 $extra = 3;
1784 break;
1785 case 'rack':
1786 $query =
1787 "select ctime, user_name, rh.name, rr.name as name, rh.height, rh.comment " .
1788 "from RackHistory as rh left join RackRow as rr on rh.row_id = rr.id " .
1789 "where rh.id = ${object_id} order by ctime";
1790 $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>';
1791 $extra = 5;
1792 break;
1793 case 'object':
1794 $query =
1795 "select ctime, user_name, RackObjectHistory.name as name, label, barcode, asset_no, has_problems, dict_value, comment " .
1796 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key join Chapter on Dictionary.chapter_id = Chapter.id " .
1797 "where Chapter.name = 'RackObjectType' and RackObjectHistory.id=${object_id} order by ctime";
1798 $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>';
1799 $extra = 8;
1800 break;
1801 default:
1802 showError ("Uknown object type '${object_type}'", __FUNCTION__);
1803 return;
1804 }
1805 global $dbxlink;
1806 $result = $dbxlink->query ($query);
1807 if ($result == NULL)
1808 {
1809 showError ('SQL query failed', __FUNCTION__);
1810 return;
1811 }
1812 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1813 $order = 'odd';
1814 global $nextorder;
1815 echo $header;
1816 while ($row = $result->fetch (PDO::FETCH_NUM))
1817 {
1818 echo "<tr class=row_${order}><td>${row[0]}</td>";
1819 for ($i = 1; $i <= $extra; $i++)
1820 echo "<td>" . $row[$i] . "</td>";
1821 echo "</tr>\n";
1822 $order = $nextorder[$order];
1823 }
1824 echo "</table><br>\n";
1825 }
1826
1827 function renderRackspaceHistory ()
1828 {
1829 global $nextorder, $pageno, $tabno;
1830 $order = 'odd';
1831 $history = getRackspaceHistory();
1832 // Show the last operation by default.
1833 if (isset ($_REQUEST['op_id']))
1834 $op_id = $_REQUEST['op_id'];
1835 elseif (isset ($history[0]['mo_id']))
1836 $op_id = $history[0]['mo_id'];
1837 else $op_id = NULL;
1838
1839 $omid = NULL;
1840 $nmid = NULL;
1841 $object_id = 1;
1842 if ($op_id)
1843 list ($omid, $nmid) = getOperationMolecules ($op_id);
1844
1845 // Main layout starts.
1846 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1847
1848 // Left top portlet with old allocation.
1849 echo "<tr><td class=pcleft>";
1850 startPortlet ('Old allocation');
1851 if ($omid)
1852 {
1853 $oldMolecule = getMolecule ($omid);
1854 renderMolecule ($oldMolecule, $object_id);
1855 }
1856 else
1857 echo "nothing";
1858 finishPortlet();
1859
1860 echo '</td><td class=pcright>';
1861
1862 // Right top portlet with new allocation
1863 startPortlet ('New allocation');
1864 if ($nmid)
1865 {
1866 $newMolecule = getMolecule ($nmid);
1867 renderMolecule ($newMolecule, $object_id);
1868 }
1869 else
1870 echo "nothing";
1871 finishPortlet();
1872
1873 echo '</td></tr><tr><td colspan=2>';
1874
1875 // Bottom portlet with list
1876
1877 startPortlet ('Rackspace allocation history');
1878 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1879 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";
1880 foreach ($history as $row)
1881 {
1882 if ($row['mo_id'] == $op_id)
1883 $class = 'hl';
1884 else
1885 $class = "row_${order}";
1886 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
1887 echo "<td>${row['user_name']}</td>";
1888 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
1889 echo "</tr>\n";
1890 $order = $nextorder[$order];
1891 }
1892 echo "</table>\n";
1893 finishPortlet();
1894
1895 echo '</td></tr></table>';
1896 }
1897
1898 function renderIPv4SpaceRecords ($tree, $baseurl, $target = 0, $level = 1)
1899 {
1900 $self = __FUNCTION__;
1901 foreach ($tree as $item)
1902 {
1903 $total = $item['addrt'];
1904 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
1905 {
1906 loadIPv4AddrList ($item); // necessary to compute router list and address counter
1907 $used = $item['addrc'];
1908 }
1909 else
1910 {
1911 $item['addrlist'] = array();
1912 $item['addrc'] = 0;
1913 }
1914 if (isset ($item['id']))
1915 {
1916 if ($item['symbol'] == 'node-collapsed')
1917 $expandurl = "${baseurl}&eid=" . $item['id'] . "#netid" . $item['id'];
1918 elseif ($item['symbol'] == 'node-expanded')
1919 $expandurl = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#netid${item['parent_id']}" : '');
1920 else
1921 $expandurl = '';
1922 echo "<tr valign=top>";
1923 printIPv4NetInfoTDs ($item, 'tdleft', $level, $item['symbol'], $expandurl);
1924 echo "<td class=tdcenter>";
1925 if ($target == $item['id'])
1926 echo "<a name=netid${target}></a>";
1927 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
1928 {
1929 renderProgressBar ($total ? $used/$total : 0);
1930 echo "<br><small>${used}/${total}</small>";
1931 }
1932 else
1933 echo "<small>${total}</small>";
1934 echo "</td>";
1935 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1936 printRoutersTD (findRouters ($item['addrlist']));
1937 echo "</tr>";
1938 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
1939 $self ($item['kids'], $baseurl, $target, $level + 1);
1940 }
1941 else
1942 {
1943 echo "<tr valign=top>";
1944 printIPv4NetInfoTDs ($item, 'tdleft sparenetwork', $level, $item['symbol']);
1945 echo "<td class=tdcenter>";
1946 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
1947 {
1948 renderProgressBar ($used/$total, 'sparenetwork');
1949 echo "<br><small>${used}/${total}</small>";
1950 }
1951 else
1952 echo "<small>${total}</small>";
1953 echo "</td><td>&nbsp;</td></tr>";
1954 }
1955 }
1956 }
1957
1958 function renderIPv4Space ()
1959 {
1960 global $pageno, $tabno;
1961 $cellfilter = getCellFilter();
1962 $netlist = filterCellList (listCells ('ipv4net'), $cellfilter['expression']);
1963 array_walk ($netlist, 'amplifyCell');
1964
1965 $netcount = count ($netlist);
1966 // expand request can take either natural values or "ALL". Zero means no expanding.
1967 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
1968 $tree = prepareIPv4Tree ($netlist, $eid);
1969
1970 echo "<table border=0 class=objectview>\n";
1971 echo "<tr><td class=pcleft>";
1972 startPortlet ("networks (${netcount})");
1973 echo '<h4>';
1974 if ($eid === 0)
1975 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
1976 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
1977 $cellfilter['urlextra'] . "'>expand all</a>)";
1978 elseif ($eid === 'ALL')
1979 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
1980 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
1981 else
1982 {
1983 $netinfo = spotEntity ('ipv4net', $eid);
1984 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>)";
1985 }
1986 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
1987 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
1988 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1989 echo "<th>routed by</th>";
1990 echo "</tr>\n";
1991 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
1992 renderIPv4SpaceRecords ($tree, $baseurl, $eid);
1993 echo "</table>\n";
1994 finishPortlet();
1995 echo '</td><td class=pcright>';
1996 renderCellFilterPortlet ($cellfilter, 'ipv4net');
1997 echo "</td></tr></table>\n";
1998 }
1999
2000 function renderIPv4SLB ()
2001 {
2002 global $page, $nextorder;
2003
2004 startPortlet ('SLB configuration');
2005 echo "<table border=0 width='100%'><tr>";
2006 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2007 echo "<td><h3><a href='".makeHref(array('page'=>$pno))."'>" . $page[$pno]['title'] . "</a></h3></td>";
2008 echo '</tr></table>';
2009 finishPortlet();
2010
2011 $summary = getSLBSummary();
2012 startPortlet ('SLB tactical overview');
2013 // A single id-keyed array isn't used here to preserve existing
2014 // order of LBs returned by getSLBSummary()
2015 $lblist = array();
2016 $lbdname = array();
2017 foreach ($summary as $vipdata)
2018 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2019 if (!in_array ($lb_object_id, $lblist))
2020 {
2021 $oi = spotEntity ('object', $lb_object_id);
2022 $lbdname[$lb_object_id] = $oi['dname'];
2023 $lblist[] = $lb_object_id;
2024 }
2025 if (!count ($summary))
2026 echo 'none configured';
2027 else
2028 {
2029 $order = 'odd';
2030 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2031 echo "<tr valign=top><td>&nbsp;</td>";
2032 foreach ($lblist as $lb_object_id)
2033 {
2034 #echo "<th><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$lb_object_id))."'>" . $lbdname[$lb_object_id] . "</a></th>";
2035 echo '<td>';
2036 renderLBCell ($lb_object_id);
2037 echo '</td>';
2038 }
2039 echo "</tr>\n";
2040 foreach ($summary as $vsid => $vsdata)
2041 {
2042 echo "<tr class=row_${order}><td class=tdleft>";
2043 renderCell (spotEntity ('ipv4vs', $vsid));
2044 echo "</td>";
2045 foreach ($lblist as $lb_object_id)
2046 {
2047 echo '<td class=tdleft>';
2048 if (!isset ($vsdata['lblist'][$lb_object_id]))
2049 echo '&nbsp;';
2050 else
2051 {
2052 echo $vsdata['lblist'][$lb_object_id]['size'];
2053 // echo " (<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$vsdata['lblist'][$lb_object_id]['id'])). "'>";
2054 // echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2055 }
2056 echo '</td>';
2057 }
2058 echo "</tr>\n";
2059 $order = $nextorder[$order];
2060 }
2061 echo "</table>\n";
2062 }
2063 finishPortlet ();
2064 }
2065
2066 function renderIPv4SpaceEditor ()
2067 {
2068 // IPv4 validator
2069 ?>
2070 <script type="text/javascript">
2071 function init() {
2072 document.add_new_range.range.setAttribute('match', "^\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\/\\d\\d?$");
2073
2074 Validate.init();
2075 }
2076 window.onload=init;
2077 </script>
2078 <?php
2079
2080 startPortlet ("Add new");
2081 echo '<table border=0 cellpadding=10 align=center>';
2082 // This form requires a name, so JavaScript validator can find it.
2083 // No printOpFormIntro() hence
2084 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2085 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2086 // tags column
2087 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2088 renderNewEntityTags ('ipv4net');
2089 echo '</td>';
2090 // inputs column
2091 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2092 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>";
2093 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2094 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2095 echo "<tr><td colspan=2>";
2096 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2097 echo '</td></tr>';
2098 echo "</form></table><br><br>\n";
2099 finishPortlet();
2100
2101 $addrspaceList = listCells ('ipv4net');
2102 array_walk ($addrspaceList, 'amplifyCell');
2103 if (count ($addrspaceList))
2104 {
2105 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2106 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2107 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>&nbsp;</th></tr>";
2108 foreach ($addrspaceList as $netinfo)
2109 {
2110 echo "<form method=post action='".makeHrefProcess(array('op'=>'updIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2111 echo "<tr valign=top><td>";
2112 if (getConfigVar ('IPV4_JAYWALK') == 'yes')
2113 {
2114 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2115 printImageHREF ('destroy', 'Delete this prefix');
2116 echo "</a>";
2117 }
2118 else // only render clickable image for empty networks
2119 {
2120 $netdata = spotEntity ('ipv4net', $netinfo['id']);
2121 loadIPv4AddrList ($netdata);
2122 if (count ($netdata['addrlist']))
2123 printImageHREF ('nodestroy', 'There are ' . count ($netdata['addrlist']) . ' allocations inside');
2124 else
2125 {
2126 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2127 printImageHREF ('destroy', 'Delete this prefix');
2128 echo "</a>";
2129 }
2130
2131 }
2132 echo "</td>\n<td class=tdleft>${netinfo['ip']}/${netinfo['mask']}</td>";
2133 echo "<td><input type=text name=name size=40 value='${netinfo['name']}'>";
2134 echo "</td><td>";
2135 printImageHREF ('save', 'Save changes', TRUE);
2136 echo "</td></tr></form>\n";
2137 }
2138 echo "</table>";
2139 finishPortlet();
2140 }
2141 }
2142
2143 function renderIPv4Network ($id)
2144 {
2145 global $pageno, $tabno, $aac2, $netmaskbylen, $wildcardbylen;
2146 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2147 if (isset($_REQUEST['pg']))
2148 $page = $_REQUEST['pg'];
2149 else
2150 $page=0;
2151
2152 $range = spotEntity ('ipv4net', $id);
2153 loadIPv4AddrList ($range);
2154 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2155 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2156 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2157
2158 echo "<tr><td class=pcleft width='50%'>";
2159 startPortlet ('summary');
2160 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2161 $used = count ($range['addrlist']);
2162 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2163
2164 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2165 renderProgressBar ($used/$total);
2166 echo "&nbsp;${used}/${total}</td></tr>\n";
2167
2168 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2169 {
2170 // Build a backtrace from all parent networks.
2171 $clen = $range['mask'];
2172 $backtrace = array();
2173 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2174 {
2175 $upperinfo = spotEntity ('ipv4net', $upperid);
2176 $clen = $upperinfo['mask'];
2177 $backtrace[] = $upperinfo;
2178 }
2179 $arrows = count ($backtrace);
2180 foreach (array_reverse ($backtrace) as $ainfo)
2181 {
2182 echo "<tr><th width='50%' class=tdright>";
2183 for ($i = 0; $i < $arrows; $i++)
2184 echo '&uarr;';
2185 $arrows--;
2186 echo "</th><td class=tdleft>";
2187 renderCell ($ainfo);
2188 echo "</td></tr>";
2189 }
2190 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
2191 echo "<td class=tdleft>";
2192 renderCell ($range);
2193 echo "</td></tr>";
2194 // FIXME: get and display nested networks
2195 // $theitem = pickLeaf ($ipv4tree, $id);
2196 }
2197
2198 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2199 echo $netmaskbylen[$range['mask']];
2200 echo "</td></tr>\n";
2201
2202 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2203 printf ('0x%08X', binMaskFromDec ($range['mask']));
2204 echo "</td></tr>\n";
2205
2206 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2207 echo $wildcardbylen[$range['mask']];
2208 echo "</td></tr>\n";
2209
2210 $routers = findRouters ($range['addrlist']);
2211 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers))
2212 {
2213 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2214 printRoutersTD ($routers);
2215 echo "</tr>\n";
2216 }
2217
2218 printTagTRs ($range, makeHref(array('page'=>'ipv4space', 'tab'=>'default'))."&");
2219 echo "</table><br>\n";
2220 finishPortlet();
2221
2222 if (strlen ($range['comment']))
2223 {
2224 startPortlet ('Comment');
2225 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2226 finishPortlet ();
2227 }
2228
2229 renderFilesPortlet ('ipv4net', $id);
2230 echo "</td>\n";
2231
2232 echo "<td class=pcright>";
2233 startPortlet ('details');
2234 $startip = $range['ip_bin'] & $range['mask_bin'];
2235 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2236 $realstartip = $startip;
2237 $realendip = $endip;
2238 $numpages = 0;
2239 if($endip - $startip > $maxperpage)
2240 {
2241 $numpages = ($endip - $startip)/$maxperpage;
2242 $startip = $startip + $page * $maxperpage;
2243 $endip = $startip + $maxperpage-1;
2244 }
2245 echo "<center>";
2246 if ($numpages)
2247 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2248 for ($i=0; $i<$numpages; $i++)
2249 {
2250 if ($i == $page)
2251 echo "<b>$i</b> ";
2252 else
2253 echo "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'id'=>$id, 'pg'=>$i))."'>$i</a> ";
2254 }
2255 echo "</center>";
2256
2257 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2258 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2259
2260
2261 for ($ip = $startip; $ip <= $endip; $ip++) :
2262 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2263 $secondstyle = 'tdleft port_highlight';
2264 else
2265 $secondstyle = 'tdleft';
2266 if (!isset ($range['addrlist'][$ip]))
2267 {
2268 echo "<tr><td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>ip_long2quad($ip)))."'>" . ip_long2quad($ip);
2269 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2270 continue;
2271 }
2272 $addr = $range['addrlist'][$ip];
2273 echo "<tr class='${addr['class']}'>";
2274
2275 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
2276 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2277 $delim = '';
2278 $prologue = '';
2279 if ( $addr['reserved'] == 'yes')
2280 {
2281 echo "<strong>RESERVED</strong> ";
2282 $delim = '; ';
2283 }
2284 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2285 {
2286 echo $delim . $aac2[$ref['type']];
2287 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'hl_ipv4_addr'=>$addr['ip']))."'>";
2288 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
2289 echo "${ref['object_name']}</a>";
2290 $delim = '; ';
2291 }
2292 if ($delim != '')
2293 {
2294 $delim = '';
2295 $prologue = '<br>';
2296 }
2297 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2298 {
2299 echo $prologue;
2300 $prologue = '';
2301 echo "${delim}<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id']))."'>";
2302 echo "${ref['object_name']}</a>:<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$ref['vs_id']))."'>";
2303 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2304 $delim = '; ';
2305 }
2306 if ($delim != '')
2307 {
2308 $delim = '';
2309 $prologue = '<br>';
2310 }
2311 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2312 {
2313 echo $prologue;
2314 $prologue = '';
2315 echo "${delim}&rarr;${ref['rsport']}@<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$ref['rspool_id']))."'>";
2316 echo "${ref['rspool_name']}</a>";
2317 $delim = '; ';
2318 }
2319 echo "</td></tr>\n";
2320 endfor;
2321 // end of iteration
2322
2323 echo "</table>";
2324 finishPortlet();
2325 echo "</td></tr></table>\n";
2326 }
2327
2328 function renderIPv4NetworkProperties ($id)
2329 {
2330 $netdata = spotEntity ('ipv4net', $id);
2331 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
2332 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2333 printOpFormIntro ('editRange');
2334 echo '<tr><td class=tdright><label for=nameinput>Name:</label></td>';
2335 echo "<td class=tdleft><input type=text name=name id=nameinput size=80 maxlength=255 value='";
2336 echo htmlspecialchars ($netdata['name'], ENT_QUOTES, 'UTF-8') . "'></tr>";
2337 echo '<tr><td class=tdright><label for=commentinput>Comment:</label></td>';
2338 echo "<td class=tdleft><textarea name=comment id=commentinput cols=80 rows=25>\n";
2339 echo htmlspecialchars ($netdata['comment'], ENT_QUOTES, 'UTF-8') . "</textarea></tr>";
2340 echo "<tr><td colspan=2 class=tdcenter>";
2341 printImageHREF ('SAVE', 'Save changes', TRUE);
2342 echo "</td></form></tr></table>\n";
2343 }
2344
2345 function renderIPv4Address ($dottedquad)
2346 {
2347 global $aat, $nextorder;
2348 $address = getIPv4Address ($dottedquad);
2349 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2350 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2351 if (strlen ($address['name']))
2352 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
2353
2354 echo "<tr><td class=pcleft>";
2355 startPortlet ('summary');
2356 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2357 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
2358 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2359 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2360 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
2361 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2362 echo "</table><br>\n";
2363 finishPortlet();
2364 echo "</td>\n";
2365
2366 echo "<td class=pcright>";
2367
2368 if (isset ($address['class']))
2369 {
2370 startPortlet ('allocations');
2371 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2372 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2373 $class = $address['class'];
2374 // render all allocation records for this address the same way
2375 if ($address['reserved'] == 'yes')
2376 echo "<tr class='${class}'><td colspan=2>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td></tr>";
2377 foreach ($address['allocs'] as $bond)
2378 {
2379 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2380 $secondclass = 'tdleft port_highlight';
2381 else
2382 $secondclass = 'tdleft';
2383 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>";
2384 echo $aat[$bond['type']];
2385 echo "</strong></td></tr>\n";
2386 }
2387 echo "</table><br><br>";
2388 finishPortlet();
2389 }
2390
2391 // FIXME: The returned list is structured differently, than we expect it to be. One of the sides
2392 // must be fixed.
2393 if (count ($address['lblist']))
2394 {
2395 startPortlet ('Virtual services (' . count ($address['lblist']) . ')');
2396 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2397 echo "<tr><th>VS</th><th>LB</th></tr>\n";
2398 $order = 'odd';
2399 foreach ($address['lblist'] as $vsinfo)
2400 {
2401 echo "<tr valign=top class=row_${order}><td class=tdleft>";
2402 renderCell (spotEntity ('ipv4vs', $vsinfo['vs_id']));
2403 echo "</td><td class=tdleft>";
2404 renderLBCell ($vsinfo['object_id']);
2405 echo "</td></tr>";
2406 $order = $nextorder[$order];
2407 }
2408 echo "</table><br><br>";
2409 finishPortlet();
2410 }
2411
2412 if (count ($address['rslist']))
2413 {
2414 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2415 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2416 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
2417 foreach ($address['rslist'] as $rsinfo)
2418 {
2419 echo "<tr><td>";
2420 if ($rsinfo['inservice'] == 'yes')
2421 printImageHREF ('inservice', 'in service');
2422 else
2423 printImageHREF ('notinservice', 'NOT in service');
2424 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsinfo['rspool_id']))."'>";
2425 echo $rsinfo['rspool_name'] . "</a></td></tr>\n";
2426 }
2427 echo "</table><br><br>";
2428 finishPortlet();
2429 }
2430
2431 if (count ($address['outpf']))
2432 {
2433 startPortlet ('departing NAT rules');
2434 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2435 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2436 foreach ($address['outpf'] as $rule)
2437 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2438 echo "</table>";
2439 finishPortlet();
2440 }
2441
2442 if (count ($address['inpf']))
2443 {
2444 startPortlet ('arriving NAT rules');
2445 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2446 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2447 foreach ($address['inpf'] as $rule)
2448 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2449 echo "</table>";
2450 finishPortlet();
2451 }
2452
2453 echo "</td></tr>";
2454 echo "</table>\n";
2455 }
2456
2457 function renderIPv4AddressProperties ($dottedquad)
2458 {
2459 $address = getIPv4Address ($dottedquad);
2460 echo "<center><h1>$dottedquad</h1></center>\n";
2461
2462 startPortlet ('update');
2463 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2464 printOpFormIntro ('editAddress');
2465 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2466 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2467 echo ($address['reserved']=='yes') ? 'checked' : '';
2468 echo "></tr><tr><td class=tdleft>";
2469 printImageHREF ('SAVE', 'Save changes', TRUE);
2470 echo "</td></form><td class=tdright>";
2471 if (!strlen ($address['name']) and $address['reserved'] == 'no')
2472 printImageHREF ('CLEAR gray');
2473 else
2474 {
2475 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2476 printImageHREF ('CLEAR', 'Release', TRUE);
2477 echo "</form>";
2478 }
2479 echo "</td></tr></table>\n";
2480 finishPortlet();
2481 }
2482
2483 function renderIPv4AddressAllocations ($dottedquad)
2484 {
2485 function printNewItemTR ()
2486 {
2487 global $aat;
2488 printOpFormIntro ('addIPv4Allocation');
2489 echo "<tr><td>";
2490 printImageHREF ('add', 'allocate', TRUE);
2491 echo "</td><td>";
2492 printSelect (getNarrowObjectList ('IPV4OBJ_LISTSRC'), 'object_id', NULL, 100);
2493 echo "</td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
2494 printSelect ($aat, 'bond_type', NULL, 102);
2495 echo "</td><td>";
2496 printImageHREF ('add', 'allocate', TRUE, 103);
2497 echo "</td></form></tr>";
2498 }
2499 global $aat;
2500
2501 $address = getIPv4Address ($dottedquad);
2502
2503 echo "<center><h1>${dottedquad}</h1></center>\n";
2504 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2505 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
2506
2507 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2508 printNewItemTR();
2509 if (isset ($address['class']))
2510 {
2511 $class = $address['class'];
2512 if ($address['reserved'] == 'yes')
2513 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2514 foreach ($address['allocs'] as $bond)
2515 {
2516 echo "<tr class='$class'>";
2517 printOpFormIntro ('updIPv4Allocation', array ('object_id' => $bond['object_id']));
2518 echo "<td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$bond['object_id']))."'>";
2519 printImageHREF ('delete', 'Unallocate address');
2520 echo "</a></td>";
2521 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$bond['object_id'], 'hl_ipv4_addr'=>$dottedquad))."'>${bond['object_name']}</td>";
2522 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
2523 printSelect ($aat, 'bond_type', $bond['type']);
2524 echo "</td><td>";
2525 printImageHREF ('save', 'Save changes', TRUE);
2526 echo "</td></form></tr>\n";
2527 }
2528 }
2529 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2530 printNewItemTR();
2531 echo "</table><br><br>";
2532 }
2533
2534 function renderNATv4ForObject ($object_id)
2535 {
2536 function printNewItemTR ($alloclist)
2537 {
2538 printOpFormIntro ('addNATv4Rule');
2539 echo "<tr align='center'><td>";
2540 printImageHREF ('add', 'Add new NAT rule', TRUE);
2541 echo '</td><td>';
2542 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
2543 echo "<select name='localip' tabindex=1>";
2544
2545 foreach ($alloclist as $dottedquad => $alloc)
2546 {
2547 $name = (!isset ($alloc['addrinfo']['name']) or !strlen ($alloc['addrinfo']['name'])) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2548 $osif = (!isset ($alloc['osif']) or !strlen ($alloc['osif'])) ? '' : ($alloc['osif'] . ': ');
2549 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
2550 }
2551
2552 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2553 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2554 echo "<a href='javascript:;' onclick='window.open(\"" . makeHrefForHelper ('inet4list');
2555 echo "\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
2556 printImageHREF ('find', 'Find object');
2557 echo "</a>";
2558 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2559 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
2560 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
2561 echo "</td></tr></form>";
2562 }
2563
2564 $focus = spotEntity ('object', $object_id);
2565 amplifyCell ($focus);
2566 echo "<center><h2>locally performed NAT</h2></center>";
2567
2568 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2569 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
2570
2571 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2572 printNewItemTR ($focus['ipv4']);
2573 foreach ($focus['nat4']['out'] as $pf)
2574 {
2575 $class = 'trerror';
2576 $osif = '';
2577 if (isset ($focus['ipv4'][$pf['localip']]))
2578 {
2579 $class = $focus['ipv4'][$pf['localip']]['addrinfo']['class'];
2580 $osif = $focus['ipv4'][$pf['localip']]['osif'] . ': ';
2581 }
2582
2583 echo "<tr class='$class'>";
2584 echo "<td><a href='".
2585 makeHrefProcess(array(
2586 'op'=>'delNATv4Rule',
2587 'localip'=>$pf['localip'],
2588 'localport'=>$pf['localport'],
2589 'remoteip'=>$pf['remoteip'],
2590 'remoteport'=>$pf['remoteport'],
2591 'proto'=>$pf['proto'],
2592 'object_id'=>$object_id)).
2593 "'>";
2594 printImageHREF ('delete', 'Delete NAT rule');
2595 echo "</a></td>";
2596 echo "<td>${pf['proto']}/${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}";
2597 if (strlen ($pf['local_addr_name']))
2598 echo ' (' . $pf['local_addr_name'] . ')';
2599 echo "</td>";
2600 echo "<td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2601
2602 $address = getIPv4Address ($pf['remoteip']);
2603
2604 echo "<td class='description'>";
2605 if (count ($address['allocs']))
2606 foreach ($address['allocs'] as $bond)
2607 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
2608 elseif (strlen ($pf['remote_addr_name']))
2609 echo '(' . $pf['remote_addr_name'] . ')';
2610 printOpFormIntro
2611 (
2612 'updNATv4Rule',
2613 array
2614 (
2615 'localip' => $pf['localip'],
2616 'localport' => $pf['localport'],
2617 'remoteip' => $pf['remoteip'],
2618 'remoteport' => $pf['remoteport'],
2619 'proto' => $pf['proto']
2620 )
2621 );
2622 echo "</td><td class='description'>";
2623 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2624 printImageHREF ('save', 'Save changes', TRUE);
2625 echo "</td></form></tr>";
2626 }
2627 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2628 printNewItemTR ($focus['ipv4']);
2629
2630 echo "</table><br><br>";
2631 if (!count ($focus['nat4']))
2632 return;
2633
2634 echo "<center><h2>arriving NAT connections</h2></center>";
2635 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2636 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2637
2638 foreach ($focus['nat4']['in'] as $pf)
2639 {
2640 echo "<tr><td><a href='".
2641 makeHrefProcess(array(
2642 'op'=>'delNATv4Rule',
2643 'localip'=>$pf['localip'],
2644 'localport'=>$pf['localport'],
2645 'remoteip'=>$pf['remoteip'],
2646 'remoteport'=>$pf['remoteport'],
2647 'proto'=>$pf['proto'],
2648 'object_id'=>$pf['object_id']
2649 )).
2650 "'>";
2651 printImageHREF ('delete', 'Delete NAT rule');
2652 echo "</a></td>";
2653 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
2654 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
2655 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2656 echo "<td class='description'>${pf['description']}</td></tr>";
2657 }
2658
2659 echo "</table><br><br>";
2660 }
2661
2662 function renderAddMultipleObjectsForm ()
2663 {
2664 $typelist = getObjectTypeList();
2665 $typelist[0] = 'select type...';
2666 $max = getConfigVar ('MASSCOUNT');
2667 $tabindex = 100;
2668
2669 startPortlet ('Distinct types, same tags');
2670 printOpFormIntro ('addObjects');
2671 echo '<table border=0 align=center>';
2672 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
2673 echo "<th>Asset tag</th><th>Barcode</th><th>Tags</th></tr>\n";
2674 for ($i = 0; $i < $max; $i++)
2675 {
2676 echo '<tr><td>';
2677 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2678 printSelect ($typelist, "${i}_object_type_id", 0, $tabindex);
2679 echo '</td>';
2680 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
2681 echo "<td><input type=text size=30 name=${i}_object_label tabindex=${tabindex}></td>";
2682 echo "<td><input type=text size=20 name=${i}_object_asset_no tabindex=${tabindex}></td>";
2683 echo "<td><input type=text size=10 name=${i}_object_barcode tabindex=${tabindex}></td>";
2684 if ($i == 0)
2685 {
2686 echo "<td valign=top rowspan=${max}>";
2687 renderNewEntityTags ('object');
2688 echo "</td>\n";
2689 }
2690 echo "</tr>\n";
2691 $tabindex++;
2692 }
2693 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2694 echo "</form></table>\n";
2695 finishPortlet();
2696
2697 startPortlet ('Same type, same tags');
2698 printOpFormIntro ('addLotOfObjects');
2699 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2700 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
2701 echo "</textarea></td><td valign=top>";
2702 printSelect ($typelist, "global_type_id", getConfigVar ('DEFAULT_OBJECT_TYPE'));
2703 echo "</td></tr>";
2704 echo "<tr><th>Tags</th></tr>";
2705 echo "<tr><td valign=top>";
2706 renderNewEntityTags ('object');
2707 echo "</td></tr>";
2708 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2709 echo "</form>\n";
2710 finishPortlet();
2711 }
2712
2713 function printGreeting ()
2714 {
2715 global $root, $remote_username, $remote_displayname;
2716 echo "Hello, <a href='${root}?page=myaccount&tab=default'>${remote_displayname}</a>. This is RackTables " .
2717 CODE_VERSION .
2718 ". Click <a href='${root}?logout'>here</a> to logout.";
2719 }
2720
2721 function renderSearchResults ()
2722 {
2723 global $root;
2724 $terms = trim ($_REQUEST['q']);
2725 if (!strlen ($terms))
2726 {
2727 showError ('Search string cannot be empty.', __FUNCTION__);
2728 return;
2729 }
2730 if (!permitted ('depot', 'default'))
2731 {
2732 showError ('You are not authorized for viewing information about objects.', __FUNCTION__);
2733 return;
2734 }
2735 $nhits = 0;
2736 if (preg_match (RE_IP4_ADDR, $terms))
2737 // Search for IPv4 address.
2738 {
2739 if (NULL !== getIPv4AddressNetworkId ($terms))
2740 {
2741 $nhits++;
2742 $lasthit = 'ipv4addressbydq';
2743 $summary['ipv4addressbydq'][] = $terms;
2744 }
2745 }
2746 elseif (preg_match (RE_IP4_NET, $terms))
2747 // Search for IPv4 network
2748 {
2749 list ($base, $len) = explode ('/', $terms);
2750 if (NULL !== ($tmp = getIPv4AddressNetworkId ($base, $len + 1)))
2751 {
2752 $nhits++;
2753 $lasthit = 'ipv4network';
2754 $summary['ipv4network'][] = spotEntity ('ipv4net', $tmp);
2755 }
2756 }
2757 else
2758 // Search for objects, addresses, networks, virtual services and RS pools by their description.
2759 {
2760 $tmp = getObjectSearchResults ($terms);
2761 if (count ($tmp))
2762 {
2763 $nhits += count ($tmp);
2764 $lasthit = 'object';
2765 $summary['object'] = $tmp;
2766 }
2767 $tmp = getIPv4AddressSearchResult ($terms);
2768 if (count ($tmp))
2769 {
2770 $nhits += count ($tmp);
2771 $lasthit = 'ipv4addressbydescr';
2772 $summary['ipv4addressbydescr'] = $tmp;
2773 }
2774 $tmp = getIPv4PrefixSearchResult ($terms);
2775 if (count ($tmp))
2776 {
2777 $nhits += count ($tmp);
2778 $lasthit = 'ipv4network';
2779 $summary['ipv4network'] = $tmp;
2780 }
2781 $tmp = getIPv4RSPoolSearchResult ($terms);
2782 if (count ($tmp))
2783 {
2784 $nhits += count ($tmp);
2785 $lasthit = 'ipv4rspool';
2786 $summary['ipv4rspool'] = $tmp;
2787 }
2788 $tmp = getIPv4VServiceSearchResult ($terms);
2789 if (count ($tmp))
2790 {
2791 $nhits += count ($tmp);
2792 $lasthit = 'ipv4vs';
2793 $summary['ipv4vs'] = $tmp;
2794 }
2795 $tmp = getAccountSearchResult ($terms);
2796 if (count ($tmp))
2797 {
2798 $nhits += count ($tmp);
2799 $lasthit = 'user';
2800 $summary['user'] = $tmp;
2801 }
2802 $tmp = getFileSearchResult ($terms);
2803 if (count ($tmp))
2804 {
2805 $nhits += count ($tmp);
2806 $lasthit = 'file';
2807 $summary['file'] = $tmp;
2808 }
2809 $tmp = getRackSearchResult ($terms);
2810 if (count ($tmp))
2811 {
2812 $nhits += count ($tmp);
2813 $lasthit = 'rack';
2814 $summary['rack'] = $tmp;
2815 }
2816 }
2817 if ($nhits == 0)
2818 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
2819 elseif ($nhits == 1)
2820 {
2821 $record = current ($summary[$lasthit]);
2822 switch ($lasthit)
2823 {
2824 case 'ipv4addressbydq':
2825 $parentnet = getIPv4AddressNetworkId ($record);
2826 if ($parentnet !== NULL)
2827 echo "<script language='Javascript'>document.location='${root}?page=ipv4net&tab=default&id=${parentnet}&hl_ipv4_addr=${record}';//</script>";
2828 else
2829 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record}';//</script>";
2830 break;
2831 case 'ipv4addressbydescr':
2832 $parentnet = getIPv4AddressNetworkId ($record['ip']);
2833 if ($parentnet !== NULL)
2834 echo "<script language='Javascript'>document.location='${root}?page=ipv4net&tab=default&id=${parentnet}&hl_ipv4_addr=${record['ip']}';//</script>";
2835 else
2836 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record['ip']}';//</script>";
2837 break;
2838 case 'ipv4network':
2839 echo "<script language='Javascript'>document.location='${root}?page=ipv4net";
2840 echo "&id=${record['id']}";
2841 echo "';//</script>";
2842 break;
2843 case 'object':
2844 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${record['id']}';//</script>";
2845 break;
2846 case 'ipv4rspool':
2847 echo "<script language='Javascript'>document.location='${root}?page=ipv4rspool&pool_id=${record['id']}';//</script>";
2848 break;
2849 case 'ipv4vs':
2850 echo "<script language='Javascript'>document.location='${root}?page=ipv4vs&vs_id=${record['id']}';//</script>";
2851 break;
2852 case 'user':
2853 echo "<script language='Javascript'>document.location='${root}?page=user&user_id=${record['user_id']}';//</script>";
2854