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