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