1a38c887839787e8409d03d53832f5860b0805a4
[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 if (count ($addrspaceList = listCells ('ipv4net')))
2105 {
2106 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2107 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2108 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th></tr>";
2109 foreach ($addrspaceList as $netinfo)
2110 {
2111 amplifyCell ($netinfo);
2112 echo "<tr valign=top><td>";
2113 if (getConfigVar ('IPV4_JAYWALK') == 'yes')
2114 {
2115 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2116 printImageHREF ('destroy', 'Delete this prefix');
2117 echo "</a>";
2118 }
2119 else // only render clickable image for empty networks
2120 {
2121 loadIPv4AddrList ($netinfo);
2122 if (count ($netinfo['addrlist']))
2123 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2124 else
2125 {
2126 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2127 printImageHREF ('destroy', 'Delete this prefix');
2128 echo "</a>";
2129 }
2130
2131 }
2132 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv4net', 'id' => $netinfo['id'])) . '">';
2133 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
2134 echo '<td class=tdleft>' . htmlspecialchars ($netinfo['name']) . '</td></tr>';
2135 }
2136 echo "</table>";
2137 finishPortlet();
2138 }
2139 }
2140
2141 function renderIPv4Network ($id)
2142 {
2143 global $pageno, $tabno, $aac2, $netmaskbylen, $wildcardbylen;
2144 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2145 if (isset($_REQUEST['pg']))
2146 $page = $_REQUEST['pg'];
2147 else
2148 $page=0;
2149
2150 $range = spotEntity ('ipv4net', $id);
2151 loadIPv4AddrList ($range);
2152 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2153 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2154 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2155
2156 echo "<tr><td class=pcleft width='50%'>";
2157 startPortlet ('summary');
2158 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2159 $used = count ($range['addrlist']);
2160 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2161
2162 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2163 renderProgressBar ($used/$total);
2164 echo "&nbsp;${used}/${total}</td></tr>\n";
2165
2166 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2167 {
2168 // Build a backtrace from all parent networks.
2169 $clen = $range['mask'];
2170 $backtrace = array();
2171 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2172 {
2173 $upperinfo = spotEntity ('ipv4net', $upperid);
2174 $clen = $upperinfo['mask'];
2175 $backtrace[] = $upperinfo;
2176 }
2177 $arrows = count ($backtrace);
2178 foreach (array_reverse ($backtrace) as $ainfo)
2179 {
2180 echo "<tr><th width='50%' class=tdright>";
2181 for ($i = 0; $i < $arrows; $i++)
2182 echo '&uarr;';
2183 $arrows--;
2184 echo "</th><td class=tdleft>";
2185 renderCell ($ainfo);
2186 echo "</td></tr>";
2187 }
2188 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
2189 echo "<td class=tdleft>";
2190 renderCell ($range);
2191 echo "</td></tr>";
2192 // FIXME: get and display nested networks
2193 // $theitem = pickLeaf ($ipv4tree, $id);
2194 }
2195
2196 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2197 echo $netmaskbylen[$range['mask']];
2198 echo "</td></tr>\n";
2199
2200 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2201 printf ('0x%08X', binMaskFromDec ($range['mask']));
2202 echo "</td></tr>\n";
2203
2204 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2205 echo $wildcardbylen[$range['mask']];
2206 echo "</td></tr>\n";
2207
2208 $routers = findRouters ($range['addrlist']);
2209 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers))
2210 {
2211 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2212 printRoutersTD ($routers);
2213 echo "</tr>\n";
2214 }
2215
2216 printTagTRs ($range, makeHref(array('page'=>'ipv4space', 'tab'=>'default'))."&");
2217 echo "</table><br>\n";
2218 finishPortlet();
2219
2220 if (strlen ($range['comment']))
2221 {
2222 startPortlet ('Comment');
2223 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2224 finishPortlet ();
2225 }
2226
2227 renderFilesPortlet ('ipv4net', $id);
2228 echo "</td>\n";
2229
2230 echo "<td class=pcright>";
2231 startPortlet ('details');
2232 $startip = $range['ip_bin'] & $range['mask_bin'];
2233 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2234 $realstartip = $startip;
2235 $realendip = $endip;
2236 $numpages = 0;
2237 if($endip - $startip > $maxperpage)
2238 {
2239 $numpages = ($endip - $startip)/$maxperpage;
2240 $startip = $startip + $page * $maxperpage;
2241 $endip = $startip + $maxperpage-1;
2242 }
2243 echo "<center>";
2244 if ($numpages)
2245 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2246 for ($i=0; $i<$numpages; $i++)
2247 {
2248 if ($i == $page)
2249 echo "<b>$i</b> ";
2250 else
2251 echo "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'id'=>$id, 'pg'=>$i))."'>$i</a> ";
2252 }
2253 echo "</center>";
2254
2255 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2256 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2257
2258
2259 for ($ip = $startip; $ip <= $endip; $ip++) :
2260 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2261 $secondstyle = 'tdleft port_highlight';
2262 else
2263 $secondstyle = 'tdleft';
2264 if (!isset ($range['addrlist'][$ip]))
2265 {
2266 echo "<tr><td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>ip_long2quad($ip)))."'>" . ip_long2quad($ip);
2267 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2268 continue;
2269 }
2270 $addr = $range['addrlist'][$ip];
2271 echo "<tr class='${addr['class']}'>";
2272
2273 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
2274 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2275 $delim = '';
2276 $prologue = '';
2277 if ( $addr['reserved'] == 'yes')
2278 {
2279 echo "<strong>RESERVED</strong> ";
2280 $delim = '; ';
2281 }
2282 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2283 {
2284 echo $delim . $aac2[$ref['type']];
2285 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'hl_ipv4_addr'=>$addr['ip']))."'>";
2286 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
2287 echo "${ref['object_name']}</a>";
2288 $delim = '; ';
2289 }
2290 if ($delim != '')
2291 {
2292 $delim = '';
2293 $prologue = '<br>';
2294 }
2295 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2296 {
2297 echo $prologue;
2298 $prologue = '';
2299 echo "${delim}<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id']))."'>";
2300 echo "${ref['object_name']}</a>:<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$ref['vs_id']))."'>";
2301 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2302 $delim = '; ';
2303 }
2304 if ($delim != '')
2305 {
2306 $delim = '';
2307 $prologue = '<br>';
2308 }
2309 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2310 {
2311 echo $prologue;
2312 $prologue = '';
2313 echo "${delim}&rarr;${ref['rsport']}@<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$ref['rspool_id']))."'>";
2314 echo "${ref['rspool_name']}</a>";
2315 $delim = '; ';
2316 }
2317 echo "</td></tr>\n";
2318 endfor;
2319 // end of iteration
2320
2321 echo "</table>";
2322 finishPortlet();
2323 echo "</td></tr></table>\n";
2324 }
2325
2326 function renderIPv4NetworkProperties ($id)
2327 {
2328 $netdata = spotEntity ('ipv4net', $id);
2329 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
2330 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2331 printOpFormIntro ('editRange');
2332 echo '<tr><td class=tdright><label for=nameinput>Name:</label></td>';
2333 echo "<td class=tdleft><input type=text name=name id=nameinput size=80 maxlength=255 value='";
2334 echo htmlspecialchars ($netdata['name'], ENT_QUOTES, 'UTF-8') . "'></tr>";
2335 echo '<tr><td class=tdright><label for=commentinput>Comment:</label></td>';
2336 echo "<td class=tdleft><textarea name=comment id=commentinput cols=80 rows=25>\n";
2337 echo htmlspecialchars ($netdata['comment'], ENT_QUOTES, 'UTF-8') . "</textarea></tr>";
2338 echo "<tr><td colspan=2 class=tdcenter>";
2339 printImageHREF ('SAVE', 'Save changes', TRUE);
2340 echo "</td></form></tr></table>\n";
2341 }
2342
2343 function renderIPv4Address ($dottedquad)
2344 {
2345 global $aat, $nextorder;
2346 $address = getIPv4Address ($dottedquad);
2347 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2348 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2349 if (strlen ($address['name']))
2350 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
2351
2352 echo "<tr><td class=pcleft>";
2353 startPortlet ('summary');
2354 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2355 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
2356 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2357 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2358 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
2359 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2360 echo "</table><br>\n";
2361 finishPortlet();
2362 echo "</td>\n";
2363
2364 echo "<td class=pcright>";
2365
2366 if (isset ($address['class']))
2367 {
2368 startPortlet ('allocations');
2369 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2370 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2371 $class = $address['class'];
2372 // render all allocation records for this address the same way
2373 if ($address['reserved'] == 'yes')
2374 echo "<tr class='${class}'><td colspan=2>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td></tr>";
2375 foreach ($address['allocs'] as $bond)
2376 {
2377 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2378 $secondclass = 'tdleft port_highlight';
2379 else
2380 $secondclass = 'tdleft';
2381 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>";
2382 echo $aat[$bond['type']];
2383 echo "</strong></td></tr>\n";
2384 }
2385 echo "</table><br><br>";
2386 finishPortlet();
2387 }
2388
2389 // FIXME: The returned list is structured differently, than we expect it to be. One of the sides
2390 // must be fixed.
2391 if (count ($address['lblist']))
2392 {
2393 startPortlet ('Virtual services (' . count ($address['lblist']) . ')');
2394 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2395 echo "<tr><th>VS</th><th>LB</th></tr>\n";
2396 $order = 'odd';
2397 foreach ($address['lblist'] as $vsinfo)
2398 {
2399 echo "<tr valign=top class=row_${order}><td class=tdleft>";
2400 renderCell (spotEntity ('ipv4vs', $vsinfo['vs_id']));
2401 echo "</td><td class=tdleft>";
2402 renderLBCell ($vsinfo['object_id']);
2403 echo "</td></tr>";
2404 $order = $nextorder[$order];
2405 }
2406 echo "</table><br><br>";
2407 finishPortlet();
2408 }
2409
2410 if (count ($address['rslist']))
2411 {
2412 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2413 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2414 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
2415 foreach ($address['rslist'] as $rsinfo)
2416 {
2417 echo "<tr><td>";
2418 if ($rsinfo['inservice'] == 'yes')
2419 printImageHREF ('inservice', 'in service');
2420 else
2421 printImageHREF ('notinservice', 'NOT in service');
2422 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsinfo['rspool_id']))."'>";
2423 echo $rsinfo['rspool_name'] . "</a></td></tr>\n";
2424 }
2425 echo "</table><br><br>";
2426 finishPortlet();
2427 }
2428
2429 if (count ($address['outpf']))
2430 {
2431 startPortlet ('departing NAT rules');
2432 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2433 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2434 foreach ($address['outpf'] as $rule)
2435 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2436 echo "</table>";
2437 finishPortlet();
2438 }
2439
2440 if (count ($address['inpf']))
2441 {
2442 startPortlet ('arriving NAT rules');
2443 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2444 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2445 foreach ($address['inpf'] as $rule)
2446 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2447 echo "</table>";
2448 finishPortlet();
2449 }
2450
2451 echo "</td></tr>";
2452 echo "</table>\n";
2453 }
2454
2455 function renderIPv4AddressProperties ($dottedquad)
2456 {
2457 $address = getIPv4Address ($dottedquad);
2458 echo "<center><h1>$dottedquad</h1></center>\n";
2459
2460 startPortlet ('update');
2461 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2462 printOpFormIntro ('editAddress');
2463 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2464 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2465 echo ($address['reserved']=='yes') ? 'checked' : '';
2466 echo "></tr><tr><td class=tdleft>";
2467 printImageHREF ('SAVE', 'Save changes', TRUE);
2468 echo "</td></form><td class=tdright>";
2469 if (!strlen ($address['name']) and $address['reserved'] == 'no')
2470 printImageHREF ('CLEAR gray');
2471 else
2472 {
2473 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2474 printImageHREF ('CLEAR', 'Release', TRUE);
2475 echo "</form>";
2476 }
2477 echo "</td></tr></table>\n";
2478 finishPortlet();
2479 }
2480
2481 function renderIPv4AddressAllocations ($dottedquad)
2482 {
2483 function printNewItemTR ()
2484 {
2485 global $aat;
2486 printOpFormIntro ('addIPv4Allocation');
2487 echo "<tr><td>";
2488 printImageHREF ('add', 'allocate', TRUE);
2489 echo "</td><td>";
2490 printSelect (getNarrowObjectList ('IPV4OBJ_LISTSRC'), 'object_id', NULL, 100);
2491 echo "</td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
2492 printSelect ($aat, 'bond_type', NULL, 102);
2493 echo "</td><td>";
2494 printImageHREF ('add', 'allocate', TRUE, 103);
2495 echo "</td></form></tr>";
2496 }
2497 global $aat;
2498
2499 $address = getIPv4Address ($dottedquad);
2500
2501 echo "<center><h1>${dottedquad}</h1></center>\n";
2502 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2503 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
2504
2505 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2506 printNewItemTR();
2507 if (isset ($address['class']))
2508 {
2509 $class = $address['class'];
2510 if ($address['reserved'] == 'yes')
2511 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2512 foreach ($address['allocs'] as $bond)
2513 {
2514 echo "<tr class='$class'>";
2515 printOpFormIntro ('updIPv4Allocation', array ('object_id' => $bond['object_id']));
2516 echo "<td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$bond['object_id']))."'>";
2517 printImageHREF ('delete', 'Unallocate address');
2518 echo "</a></td>";
2519 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$bond['object_id'], 'hl_ipv4_addr'=>$dottedquad))."'>${bond['object_name']}</td>";
2520 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
2521 printSelect ($aat, 'bond_type', $bond['type']);
2522 echo "</td><td>";
2523 printImageHREF ('save', 'Save changes', TRUE);
2524 echo "</td></form></tr>\n";
2525 }
2526 }
2527 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2528 printNewItemTR();
2529 echo "</table><br><br>";
2530 }
2531
2532 function renderNATv4ForObject ($object_id)
2533 {
2534 function printNewItemTR ($alloclist)
2535 {
2536 printOpFormIntro ('addNATv4Rule');
2537 echo "<tr align='center'><td>";
2538 printImageHREF ('add', 'Add new NAT rule', TRUE);
2539 echo '</td><td>';
2540 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
2541 echo "<select name='localip' tabindex=1>";
2542
2543 foreach ($alloclist as $dottedquad => $alloc)
2544 {
2545 $name = (!isset ($alloc['addrinfo']['name']) or !strlen ($alloc['addrinfo']['name'])) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2546 $osif = (!isset ($alloc['osif']) or !strlen ($alloc['osif'])) ? '' : ($alloc['osif'] . ': ');
2547 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
2548 }
2549
2550 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2551 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2552 echo "<a href='javascript:;' onclick='window.open(\"" . makeHrefForHelper ('inet4list');
2553 echo "\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
2554 printImageHREF ('find', 'Find object');
2555 echo "</a>";
2556 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2557 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
2558 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
2559 echo "</td></tr></form>";
2560 }
2561
2562 $focus = spotEntity ('object', $object_id);
2563 amplifyCell ($focus);
2564 echo "<center><h2>locally performed NAT</h2></center>";
2565
2566 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2567 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
2568
2569 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2570 printNewItemTR ($focus['ipv4']);
2571 foreach ($focus['nat4']['out'] as $pf)
2572 {
2573 $class = 'trerror';
2574 $osif = '';
2575 if (isset ($focus['ipv4'][$pf['localip']]))
2576 {
2577 $class = $focus['ipv4'][$pf['localip']]['addrinfo']['class'];
2578 $osif = $focus['ipv4'][$pf['localip']]['osif'] . ': ';
2579 }
2580
2581 echo "<tr class='$class'>";
2582 echo "<td><a href='".
2583 makeHrefProcess(array(
2584 'op'=>'delNATv4Rule',
2585 'localip'=>$pf['localip'],
2586 'localport'=>$pf['localport'],
2587 'remoteip'=>$pf['remoteip'],
2588 'remoteport'=>$pf['remoteport'],
2589 'proto'=>$pf['proto'],
2590 'object_id'=>$object_id)).
2591 "'>";
2592 printImageHREF ('delete', 'Delete NAT rule');
2593 echo "</a></td>";
2594 echo "<td>${pf['proto']}/${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}";
2595 if (strlen ($pf['local_addr_name']))
2596 echo ' (' . $pf['local_addr_name'] . ')';
2597 echo "</td>";
2598 echo "<td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2599
2600 $address = getIPv4Address ($pf['remoteip']);
2601
2602 echo "<td class='description'>";
2603 if (count ($address['allocs']))
2604 foreach ($address['allocs'] as $bond)
2605 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
2606 elseif (strlen ($pf['remote_addr_name']))
2607 echo '(' . $pf['remote_addr_name'] . ')';
2608 printOpFormIntro
2609 (
2610 'updNATv4Rule',
2611 array
2612 (
2613 'localip' => $pf['localip'],
2614 'localport' => $pf['localport'],
2615 'remoteip' => $pf['remoteip'],
2616 'remoteport' => $pf['remoteport'],
2617 'proto' => $pf['proto']
2618 )
2619 );
2620 echo "</td><td class='description'>";
2621 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2622 printImageHREF ('save', 'Save changes', TRUE);
2623 echo "</td></form></tr>";
2624 }
2625 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2626 printNewItemTR ($focus['ipv4']);
2627
2628 echo "</table><br><br>";
2629 if (!count ($focus['nat4']))
2630 return;
2631
2632 echo "<center><h2>arriving NAT connections</h2></center>";
2633 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2634 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2635
2636 foreach ($focus['nat4']['in'] as $pf)
2637 {
2638 echo "<tr><td><a href='".
2639 makeHrefProcess(array(
2640 'op'=>'delNATv4Rule',
2641 'localip'=>$pf['localip'],
2642 'localport'=>$pf['localport'],
2643 'remoteip'=>$pf['remoteip'],
2644 'remoteport'=>$pf['remoteport'],
2645 'proto'=>$pf['proto'],
2646 'object_id'=>$pf['object_id']
2647 )).
2648 "'>";
2649 printImageHREF ('delete', 'Delete NAT rule');
2650 echo "</a></td>";
2651 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
2652 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
2653 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2654 echo "<td class='description'>${pf['description']}</td></tr>";
2655 }
2656
2657 echo "</table><br><br>";
2658 }
2659
2660 function renderAddMultipleObjectsForm ()
2661 {
2662 $typelist = getObjectTypeList();
2663 $typelist[0] = 'select type...';
2664 $max = getConfigVar ('MASSCOUNT');
2665 $tabindex = 100;
2666
2667 startPortlet ('Distinct types, same tags');
2668 printOpFormIntro ('addObjects');
2669 echo '<table border=0 align=center>';
2670 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
2671 echo "<th>Asset tag</th><th>Barcode</th><th>Tags</th></tr>\n";
2672 for ($i = 0; $i < $max; $i++)
2673 {
2674 echo '<tr><td>';
2675 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2676 printSelect ($typelist, "${i}_object_type_id", 0, $tabindex);
2677 echo '</td>';
2678 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
2679 echo "<td><input type=text size=30 name=${i}_object_label tabindex=${tabindex}></td>";
2680 echo "<td><input type=text size=20 name=${i}_object_asset_no tabindex=${tabindex}></td>";
2681 echo "<td><input type=text size=10 name=${i}_object_barcode tabindex=${tabindex}></td>";
2682 if ($i == 0)
2683 {
2684 echo "<td valign=top rowspan=${max}>";
2685 renderNewEntityTags ('object');
2686 echo "</td>\n";
2687 }
2688 echo "</tr>\n";
2689 $tabindex++;
2690 }
2691 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2692 echo "</form></table>\n";
2693 finishPortlet();
2694
2695 startPortlet ('Same type, same tags');
2696 printOpFormIntro ('addLotOfObjects');
2697 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2698 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
2699 echo "</textarea></td><td valign=top>";
2700 printSelect ($typelist, "global_type_id", getConfigVar ('DEFAULT_OBJECT_TYPE'));
2701 echo "</td></tr>";
2702 echo "<tr><th>Tags</th></tr>";
2703 echo "<tr><td valign=top>";
2704 renderNewEntityTags ('object');
2705 echo "</td></tr>";
2706 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2707 echo "</form>\n";
2708 finishPortlet();
2709 }
2710
2711 function printGreeting ()
2712 {
2713 global $root, $remote_username, $remote_displayname;
2714 echo "Hello, <a href='${root}?page=myaccount&tab=default'>${remote_displayname}</a>. This is RackTables " .
2715 CODE_VERSION .
2716 ". Click <a href='${root}?logout'>here</a> to logout.";
2717 }
2718
2719 function renderSearchResults ()
2720 {
2721 global $root;
2722 $terms = trim ($_REQUEST['q']);
2723 if (!strlen ($terms))
2724 {
2725 showError ('Search string cannot be empty.', __FUNCTION__);
2726 return;
2727 }
2728 if (!permitted ('depot', 'default'))
2729 {
2730 showError ('You are not authorized for viewing information about objects.', __FUNCTION__);
2731 return;
2732 }
2733 $nhits = 0;
2734 if (preg_match (RE_IP4_ADDR, $terms))
2735 // Search for IPv4 address.
2736 {
2737 if (NULL !== getIPv4AddressNetworkId ($terms))
2738 {
2739 $nhits++;
2740 $lasthit = 'ipv4addressbydq';
2741 $summary['ipv4addressbydq'][] = $terms;
2742 }
2743 }
2744 elseif (preg_match (RE_IP4_NET, $terms))
2745 // Search for IPv4 network
2746 {
2747 list ($base, $len) = explode ('/', $terms);
2748 if (NULL !== ($tmp = getIPv4AddressNetworkId ($base, $len + 1)))
2749 {
2750 $nhits++;
2751 $lasthit = 'ipv4network';
2752 $summary['ipv4network'][] = spotEntity ('ipv4net', $tmp);
2753 }
2754 }
2755 else
2756 // Search for objects, addresses, networks, virtual services and RS pools by their description.
2757 {
2758 $tmp = getObjectSearchResults ($terms);
2759 if (count ($tmp))
2760 {
2761 $nhits += count ($tmp);
2762 $lasthit = 'object';
2763 $summary['object'] = $tmp;
2764 }
2765 $tmp = getIPv4AddressSearchResult ($terms);
2766 if (count ($tmp))
2767 {
2768 $nhits += count ($tmp);
2769 $lasthit = 'ipv4addressbydescr';
2770 $summary['ipv4addressbydescr'] = $tmp;
2771 }
2772 $tmp = getIPv4PrefixSearchResult ($terms);
2773 if (count ($tmp))
2774 {
2775 $nhits += count ($tmp);
2776 $lasthit = 'ipv4network';
2777 $summary['ipv4network'] = $tmp;
2778 }
2779 $tmp = getIPv4RSPoolSearchResult ($terms);
2780 if (count ($tmp))
2781 {
2782 $nhits += count ($tmp);
2783 $lasthit = 'ipv4rspool';
2784 $summary['ipv4rspool'] = $tmp;
2785 }
2786 $tmp = getIPv4VServiceSearchResult ($terms);
2787 if (count ($tmp))
2788 {
2789 $nhits += count ($tmp);
2790 $lasthit = 'ipv4vs';
2791 $summary['ipv4vs'] = $tmp;
2792 }
2793 $tmp = getAccountSearchResult ($terms);
2794 if (count ($tmp))
2795 {
2796 $nhits += count ($tmp);
2797 $lasthit = 'user';
2798 $summary['user'] = $tmp;
2799 }
2800 $tmp = getFileSearchResult ($terms);
2801 if (count ($tmp))
2802 {
2803 $nhits += count ($tmp);
2804 $lasthit = 'file';
2805 $summary['file'] = $tmp;
2806 }
2807 $tmp = getRackSearchResult ($terms);
2808 if (count ($tmp))
2809 {
2810 $nhits += count ($tmp);
2811 $lasthit = 'rack';
2812 $summary['rack'] = $tmp;
2813 }
2814 }
2815 if ($nhits == 0)
2816 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
2817 elseif ($nhits == 1)
2818 {
2819 $record = current ($summary[$lasthit]);
2820 switch ($lasthit)
2821 {
2822 case 'ipv4addressbydq':
2823 $parentnet = getIPv4AddressNetworkId ($record);
2824 if ($parentnet !== NULL)
2825 echo "<script language='Javascript'>document.location='${root}?page=ipv4net&tab=default&id=${parentnet}&hl_ipv4_addr=${record}';//</script>";
2826 else
2827 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record}';//</script>";
2828 break;
2829 case 'ipv4addressbydescr':
2830 $parentnet = getIPv4AddressNetworkId ($record['ip']);
2831 if ($parentnet !== NULL)
2832 echo "<script language='Javascript'>document.location='${root}?page=ipv4net&tab=default&id=${parentnet}&hl_ipv4_addr=${record['ip']}';//</script>";
2833 else
2834 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record['ip']}';//</script>";
2835 break;
2836 case 'ipv4network':
2837 echo "<script language='Javascript'>document.location='${root}?page=ipv4net";
2838 echo "&id=${record['id']}";
2839 echo "';//</script>";
2840 break;
2841 case 'object':
2842 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${record['id']}';//</script>";
2843 break;
2844 case 'ipv4rspool':
2845 echo "<script language='Javascript'>document.location='${root}?page=ipv4rspool&pool_id=${record['id']}';//</script>&