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