r3014 - getPortTypes(): sayonara
[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 printNiftySelect (cookOptgroups (readChapter (CHAP_OBJTYPE, 'o')), '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_id'], 'o');
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 "'>" . decodeObjectType ($info['objtype_id'], 'o') . '</a></td></tr>';
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) 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 $portOptions = cookOptgroups (readChapter (CHAP_PORTTYPE, 'o'));
1080 function printNewItemTR ($portOptions)
1081 {
1082 printOpFormIntro ('addPort');
1083 echo "<tr><td>";
1084 printImageHREF ('add', 'add a port', TRUE);
1085 echo "</td><td><input type=text size=8 name=port_name tabindex=100></td>\n";
1086 echo "<td><input type=text size=24 name=port_label tabindex=101></td><td>";
1087 printNiftySelect ($portOptions, 'port_type_id', getConfigVar ('default_port_type'), 102);
1088 echo "<td><input type=text name=port_l2address tabindex=103></td>\n";
1089 echo "<td colspan=3>&nbsp;</td><td>";
1090 printImageHREF ('add', 'add a port', TRUE, 104);
1091 echo "</td></tr></form>";
1092 }
1093 startPortlet ('Ports and interfaces');
1094 $ports = getObjectPortsAndLinks ($object_id);
1095 usort($ports, 'sortByName');
1096 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1097 echo "<tr><th>&nbsp;</th><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
1098 echo "<th>Rem. object</th><th>Rem. port</th><th>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
1099 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1100 printNewItemTR ($portOptions);
1101 foreach ($ports as $port)
1102 {
1103 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
1104 echo "<tr><td><a href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id'], 'object_id'=>$object_id, 'port_name'=>$port['name']))."'>";
1105 printImageHREF ('delete', 'Unlink and Delete this port');
1106 echo "</a></td>\n";
1107 echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
1108 echo "<td><input type=text name=label value='${port['label']}' size=24></td>";
1109 if (!$port['remote_object_id'])
1110 {
1111 echo "<td>";
1112 printNiftySelect ($portOptions, 'port_type_id', $port['type_id']);
1113 echo "</td>";
1114 }
1115 else
1116 {
1117 echo "<input type=hidden name=port_type_id value='${port['type_id']}'>";
1118 echo "<td class=tdleft>${port['type']}</td>\n";
1119 }
1120 echo "<td><input type=text name=l2address value='${port['l2address']}'></td>\n";
1121 if ($port['remote_object_id'])
1122 {
1123 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$port['remote_object_id']))."'>${port['remote_object_name']}</a></td>";
1124 echo "<td>${port['remote_name']}</td>";
1125 echo "<td><a href='".
1126 makeHrefProcess(array(
1127 'op'=>'unlinkPort',
1128 'port_id'=>$port['id'],
1129 'object_id'=>$object_id,
1130 'port_name'=>$port['name'],
1131 'remote_port_name'=>$port['remote_name'],
1132 'remote_object_name'=>$port['remote_object_name'])).
1133 "'>";
1134 printImageHREF ('cut', 'Unlink this port');
1135 echo "</a></td>";
1136 }
1137 elseif (strlen ($port['reservation_comment']))
1138 {
1139 echo "<td><b>Reserved;</b></td>";
1140 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
1141 echo "<td><a href='".
1142 makeHrefProcess(array(
1143 'op'=>'useup',
1144 'port_id'=>$port['id'],
1145 'object_id'=>$object_id)).
1146 "'>";
1147 printImageHREF ('clear', 'Use up this port');
1148 echo "</a></td>";
1149 }
1150 else
1151 {
1152 echo "<td>&nbsp;</td><td>&nbsp;</td>";
1153 echo "<td>";
1154 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\");'>";
1155 printImageHREF ('plug', 'Link this port');
1156 echo "</a> <input type=text name=reservation_comment>";
1157 echo "</td>\n";
1158 }
1159 echo "<td>";
1160 printImageHREF ('save', 'Save changes', TRUE);
1161 echo "</td></form></tr>\n";
1162 }
1163 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1164 printNewItemTR ($portOptions);
1165 echo "</table><br>\n";
1166 finishPortlet();
1167
1168 startPortlet ('Add/update multiple ports');
1169 printOpFormIntro ('addMultiPorts');
1170 echo 'Format: <select name=format tabindex=201>';
1171 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1172 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
1173 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
1174 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
1175 echo "</select>";
1176 echo 'Default port type: ';
1177 printNiftySelect ($portOptions, 'port_type', getConfigVar ('default_port_type'), 202);
1178 echo "<input type=submit value='Parse output' tabindex=204><br>\n";
1179 echo "<textarea name=input cols=100 rows=50 tabindex=203></textarea><br>\n";
1180 echo '</form>';
1181 finishPortlet();
1182 }
1183
1184 function renderIPv4ForObject ($object_id)
1185 {
1186 function printNewItemTR ()
1187 {
1188 global $aat;
1189 printOpFormIntro ('addIPv4Allocation');
1190 echo "<tr><td>";
1191 printImageHREF ('add', 'allocate', TRUE);
1192 echo "</td>";
1193 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1194 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
1195 echo "<td colspan=2>&nbsp;</td><td>";
1196 printSelect ($aat, 'bond_type', NULL, 102);
1197 echo "</td><td>&nbsp;</td><td>";
1198 printImageHREF ('add', 'allocate', TRUE, 103);
1199 echo "</td></tr></form>";
1200 }
1201 $focus = spotEntity ('object', $object_id);
1202 amplifyCell ($focus);
1203 global $aat;
1204 startPortlet ('Allocations');
1205 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1206 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1207 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1208 echo '<th>network</th><th>routed by</th>';
1209 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1210
1211 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1212 printNewItemTR();
1213 foreach ($focus['ipv4'] as $dottedquad => $alloc)
1214 {
1215 $class = $alloc['addrinfo']['class'];
1216 $netid = getIPv4AddressNetworkId ($dottedquad);
1217 if (NULL !== $netid)
1218 {
1219 $netinfo = spotEntity ('ipv4net', $netid);
1220 loadIPv4AddrList ($netinfo);
1221 }
1222 printOpFormIntro ('updIPv4Allocation', array ('ip' => $dottedquad));
1223 echo "<tr class='$class' valign=top><td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$object_id))."'>";
1224 printImageHREF ('delete', 'Delete this IPv4 address');
1225 echo "</a></td>";
1226 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td><td class=tdleft>";
1227 if (NULL !== $netid)
1228 echo "<a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$dottedquad))."'>${dottedquad}</a>";
1229 else
1230 echo $dottedquad;
1231 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1232 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1233 if (strlen ($alloc['addrinfo']['name']))
1234 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1235 echo '</td>';
1236 // FIXME: this a copy-and-paste from renderRackObject()
1237 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1238 {
1239 if (NULL === $netid)
1240 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1241 else
1242 {
1243 echo '<td>';
1244 renderCell ($netinfo);
1245 echo '</td>';
1246 // filter out self-allocation
1247 $other_routers = array();
1248 foreach (findRouters ($netinfo['addrlist']) as $router)
1249 if ($router['id'] != $object_id)
1250 $other_routers[] = $router;
1251 if (count ($other_routers))
1252 printRoutersTD ($other_routers);
1253 else
1254 echo "<td>&nbsp;</td>";
1255 }
1256 }
1257 echo '<td>';
1258 printSelect ($aat, 'bond_type', $alloc['type']);
1259 echo "</td><td>";
1260 $prefix = '';
1261 if ($alloc['addrinfo']['reserved'] == 'yes')
1262 {
1263 echo $prefix . '<strong>RESERVED</strong>';
1264 $prefix = '; ';
1265 }
1266 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1267 {
1268 if ($allocpeer['object_id'] == $object_id)
1269 continue;
1270 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1271 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
1272 echo $allocpeer['osif'] . '@';
1273 echo $allocpeer['object_name'] . '</a>';
1274 $prefix = '; ';
1275 }
1276 echo "</td><td>";
1277 printImageHREF ('save', 'Save changes', TRUE);
1278 echo "</td></form></tr>\n";
1279 }
1280 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1281 printNewItemTR();
1282
1283 echo "</table><br>\n";
1284 finishPortlet();
1285
1286 }
1287
1288 // Log structure versions:
1289 // 1: the whole structure is a list of code-message pairs
1290 // 2 and later: there's a "v" field set, which indicates the version
1291 // 2: there's a "m" list set to hold message code and optional arguments
1292 function showMessageOrError ()
1293 {
1294 if (!isset ($_SESSION['log']))
1295 return;
1296 $log = $_SESSION['log'];
1297 switch (TRUE)
1298 {
1299 case !isset ($log['v']):
1300 case $log['v'] == 1:
1301 foreach ($log as $key => $record)
1302 if ($key !== 'v')
1303 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1304 break;
1305 case $log['v'] == 2:
1306 $msginfo = array
1307 (
1308 // records 0~99 with success messages
1309 0 => array ('code' => 'success', 'format' => '%s'),
1310 1 => array ('code' => 'success', 'format' => '%u new records done, %u already existed'),
1311 2 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully added.'),
1312 3 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully deleted.'),
1313 4 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully updated'),
1314 5 => array ('code' => 'success', 'format' => 'Port %s was added successfully'),
1315 6 => array ('code' => 'success', 'format' => 'Port %s was updated successfully'),
1316 7 => array ('code' => 'success', 'format' => 'Port %s was deleted successfully'),
1317 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with port %s at object %s'),
1318 9 => array ('code' => 'success', 'format' => 'Port %s was successfully unlinked from %s@%s'),
1319 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1320 11 => array ('code' => 'success', 'format' => 'Reservation removed.'),
1321 12 => array ('code' => 'success', 'format' => 'allocation updated'),
1322 13 => array ('code' => 'success', 'format' => 'allocated'),
1323 14 => array ('code' => 'success', 'format' => 'deallocated'),
1324 15 => array ('code' => 'success', 'format' => 'Reset succeeded.'),
1325 16 => array ('code' => 'success', 'format' => 'Update done'),
1326 17 => array ('code' => 'success', 'format' => 'Update(s) succeeded.'),
1327 18 => array ('code' => 'success', 'format' => 'Load balancer was successfully added'),
1328 19 => array ('code' => 'success', 'format' => 'Load balancer was successfully deleted'),
1329 20 => array ('code' => 'success', 'format' => 'Load balancer info was successfully updated'),
1330 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1331 22 => array ('code' => 'success', 'format' => 'Chained %u tags'),
1332 23 => array ('code' => 'success', 'format' => 'IPv4 prefix successfully added'),
1333 24 => array ('code' => 'success', 'format' => 'IPv4 prefix deleted'),
1334 25 => array ('code' => 'success', 'format' => 'IPv4 prefix updated'),
1335 26 => array ('code' => 'success', 'format' => '%u IP address(es) were successfully updated'),
1336 27 => array ('code' => 'success', 'format' => 'IPv4 address updated'),
1337 28 => array ('code' => 'success', 'format' => 'Virtual service was successfully created'),
1338 29 => array ('code' => 'success', 'format' => 'Virtual service was successfully deleted'),
1339 30 => array ('code' => 'success', 'format' => 'Virtual service was successfully updated'),
1340 31 => array ('code' => 'success', 'format' => 'RS pool was successfully created'),
1341 32 => array ('code' => 'success', 'format' => 'RS pool was successfully deleted'),
1342 33 => array ('code' => 'success', 'format' => 'RS pool was successfully updated'),
1343 34 => array ('code' => 'success', 'format' => 'Real server was successfully added'),
1344 35 => array ('code' => 'success', 'format' => 'Real server was successfully deleted'),
1345 36 => array ('code' => 'success', 'format' => 'Real server was successfully updated'),
1346 37 => array ('code' => 'success', 'format' => 'Successfully added %u real servers'),
1347 38 => array ('code' => 'success', 'format' => '%u real server(s) were successfully (de)activated'),
1348 39 => array ('code' => 'success', 'format' => 'User account %s updated.'),
1349 40 => array ('code' => 'success', 'format' => 'User account %s created.'),
1350 // ...
1351 // ...
1352 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1353 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1354 45 => array ('code' => 'success', 'format' => "Attribute '%s' created."),
1355 46 => array ('code' => 'success', 'format' => 'Rename successful.'),
1356 47 => array ('code' => 'success', 'format' => 'Attribute was deleted.'),
1357 48 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1358 49 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1359 50 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1360 51 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1361 52 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1362 53 => array ('code' => 'success', 'format' => 'Chapter was deleted.'),
1363 54 => array ('code' => 'success', 'format' => 'Chapter was updated.'),
1364 55 => array ('code' => 'success', 'format' => 'Chapter was added.'),
1365 56 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1366 57 => array ('code' => 'success', 'format' => 'Reset complete'),
1367 58 => array ('code' => 'success', 'format' => "Deleted tag '%s'."),
1368 59 => array ('code' => 'success', 'format' => "Created tag '%s'."),
1369 60 => array ('code' => 'success', 'format' => "Updated tag '%s'."),
1370 61 => array ('code' => 'success', 'format' => 'Password changed successfully.'),
1371 62 => array ('code' => 'success', 'format' => 'gw: %s'),
1372 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
1373 64 => array ('code' => 'success', 'format' => 'Port %s@%s has been assigned to VLAN %u'),
1374 65 => array ('code' => 'success', 'format' => "Added new rack '%s'"),
1375 66 => array ('code' => 'success', 'format' => "File sent Ok via handler '%s'"),
1376 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1377 68 => array ('code' => 'success', 'format' => "Updated rack '%s'"),
1378 69 => array ('code' => 'success', 'format' => 'File "%s" was added successfully'),
1379 70 => array ('code' => 'success', 'format' => 'File "%s" was updated successfully'),
1380 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
1381 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
1382 73 => array ('code' => 'success', 'format' => 'File "%s" was deleted successfully'),
1383 74 => array ('code' => 'success', 'format' => 'Row "%s" was added successfully'),
1384 75 => array ('code' => 'success', 'format' => 'Row "%s" was updated successfully'),
1385 76 => array ('code' => 'success', 'format' => 'Object "%s" was deleted successfully'),
1386 77 => array ('code' => 'success', 'format' => 'Row "%s" was deleted successfully'),
1387 78 => array ('code' => 'success', 'format' => 'File "%s" saved Ok'),
1388 79 => array ('code' => 'success', 'format' => 'Rack "%s" was deleted successfully'),
1389 80 => array ('code' => 'success', 'format' => "Added new object '%s'"),
1390 81 => array ('code' => 'success', 'format' => "SNMP: completed '%s' work"),
1391
1392 // records 100~199 with fatal error messages
1393 100 => array ('code' => 'error', 'format' => '%s'),
1394 101 => array ('code' => 'error', 'format' => 'Port name cannot be empty'),
1395 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
1396 103 => array ('code' => 'error', 'format' => 'User not found!'),
1397 104 => array ('code' => 'error', 'format' => "Error updating user account '%s'"),
1398 // ...
1399 // ...
1400 // ...
1401 108 => array ('code' => 'error', 'format' => '%u failures and %u successfull changes.'),
1402 109 => array ('code' => 'error', 'format' => 'Update failed!'),
1403 110 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1404 111 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1405 112 => array ('code' => 'error', 'format' => 'Error adding chapter.'),
1406 113 => array ('code' => 'error', 'format' => 'Error updating chapter.'),
1407 114 => array ('code' => 'error', 'format' => 'Error deleting chapter.'),
1408 115 => array ('code' => 'error', 'format' => 'Error renaming attribute.'),
1409 116 => array ('code' => 'error', 'format' => 'Error creating attribute.'),
1410 117 => array ('code' => 'error', 'format' => 'Error deleting attribute.'),
1411 118 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1412 119 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1413 120 => array ('code' => 'error', 'format' => 'Reset failed!'),
1414 121 => array ('code' => 'error', 'format' => 'commitUpdateObject() failed'),
1415 122 => array ('code' => 'error', 'format' => 'One or more update(s) failed!'),
1416 123 => array ('code' => 'error', 'format' => 'Cannot process submitted data: unknown format code.'),
1417 124 => array ('code' => 'error', 'format' => 'Error removing reservation!'),
1418 125 => array ('code' => 'error', 'format' => "Update failed with error: '%s'"),
1419 126 => array ('code' => 'error', 'format' => 'addRStoRSPool() failed'),
1420 127 => array ('code' => 'error', 'format' => 'Added %u real servers and encountered %u errors'),
1421 128 => array ('code' => 'error', 'format' => 'commitDeleteRS() failed'),
1422 129 => array ('code' => 'error', 'format' => 'commitDeleteLB() failed'),
1423 130 => array ('code' => 'error', 'format' => 'commitDeleteVS() failed'),
1424 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1425 132 => array ('code' => 'error', 'format' => 'invalid protocol'),
1426 133 => array ('code' => 'error', 'format' => 'commitUpdateRS() failed'),
1427 134 => array ('code' => 'error', 'format' => 'commitUpdateLB() failed'),
1428 135 => array ('code' => 'error', 'format' => 'commitUpdateVS() failed'),
1429 136 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1430 137 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1431 138 => array ('code' => 'error', 'format' => 'commitDeleteRSPool() failed'),
1432 139 => array ('code' => 'error', 'format' => 'commitUpdateRSPool() failed'),
1433 140 => array ('code' => 'error', 'format' => 'Encountered %u errors, (de)activated %u real servers'),
1434 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u IP address(es)'),
1435 142 => array ('code' => 'error', 'format' => 'executeAutoPorts() failed'),
1436 143 => array ('code' => 'error', 'format' => 'Tried chaining %u tags, but experienced %u errors.'),
1437 144 => array ('code' => 'error', 'format' => "Error deleting tag: '%s'"),
1438 145 => array ('code' => 'error', 'format' => "Invalid tag name '%s'"),
1439 // ...
1440 147 => array ('code' => 'error', 'format' => "Could not create tag '%s': %s"),
1441 148 => array ('code' => 'error', 'format' => "Could not update tag '%s': %s"),
1442 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1443 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1444 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1445 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1446 153 => array ('code' => 'error', 'format' => 'Password change failed.'),
1447 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1448 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1449 156 => array ('code' => 'error', 'format' => 'getSwitchVLANs() failed'),
1450 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
1451 158 => array ('code' => 'error', 'format' => 'Ignoring malformed record #%u in form submit'),
1452 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1453 160 => array ('code' => 'error', 'format' => 'Invalid arguments'),
1454 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1455 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
1456 163 => array ('code' => 'error', 'format' => 'Failed to get any response from queryGateway() or the gateway died'),
1457 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
1458 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1459 166 => array ('code' => 'error', 'format' => 'gw: %s'),
1460 167 => array ('code' => 'error', 'format' => 'Could not find port %s'),
1461 168 => array ('code' => 'error', 'format' => 'Port %s is a trunk'),
1462 169 => array ('code' => 'error', 'format' => 'Failed to configure %s, connector returned code %u'),
1463 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1464 171 => array ('code' => 'error', 'format' => "Failed creating rack '%s'. Already exists in this row?"),
1465 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1466 173 => array ('code' => 'error', 'format' => "Invalid IPv4 prefix '%s'"),
1467 174 => array ('code' => 'error', 'format' => 'Bad IPv4 address'),
1468 175 => array ('code' => 'error', 'format' => 'Invalid netmask'),
1469 176 => array ('code' => 'error', 'format' => 'This network already exists'),
1470 177 => array ('code' => 'error', 'format' => 'commitUpdateRack() failed'),
1471 178 => array ('code' => 'error', 'format' => 'file not found'),
1472 179 => array ('code' => 'error', 'format' => 'Declining outdated text. Re-edit the file for consistency.'),
1473 180 => array ('code' => 'error', 'format' => 'Error saving file, all changes lost!'),
1474 181 => array ('code' => 'error', 'format' => "file uploads not allowed, change 'file_uploads' parameter in php.ini"),
1475 182 => array ('code' => 'error', 'format' => 'SQL query failed: %s'),
1476 183 => array ('code' => 'error', 'format' => "Tag id '%s' does not exist."),
1477 184 => array ('code' => 'error', 'format' => 'Submitted form is invalid at line %u'),
1478 185 => array ('code' => 'error', 'format' => "Failed to add object '%s'"),
1479 186 => array ('code' => 'error', 'format' => 'Incomplete form has been ignored. Cheers.'),
1480 187 => array ('code' => 'error', 'format' => "Internal error in function '%s'"),
1481 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1482 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
1483
1484 // records 200~299 with warnings
1485 200 => array ('code' => 'warning', 'format' => '%s'),
1486 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1487 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
1488 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1489 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1490 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
1491 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
1492 207 => array ('code' => 'warning', 'format' => 'Ignored empty request'),
1493
1494 );
1495 // Handle the arguments. Is there any better way to do it?
1496 foreach ($log['m'] as $record)
1497 {
1498 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1499 {
1500 echo '<div class=msg_neutral>(this message was lost)</div>';
1501 continue;
1502 }
1503 if (isset ($record['a']))
1504 switch (count ($record['a']))
1505 {
1506 case 1:
1507 $msgtext = sprintf
1508 (
1509 $msginfo[$record['c']]['format'],
1510 $record['a'][0]
1511 );
1512 break;
1513 case 2:
1514 $msgtext = sprintf
1515 (
1516 $msginfo[$record['c']]['format'],
1517 $record['a'][0],
1518 $record['a'][1]
1519 );
1520 break;
1521 case 3:
1522 $msgtext = sprintf
1523 (
1524 $msginfo[$record['c']]['format'],
1525 $record['a'][0],
1526 $record['a'][1],
1527 $record['a'][2]
1528 );
1529 break;
1530 case 4:
1531 default:
1532 $msgtext = sprintf
1533 (
1534 $msginfo[$record['c']]['format'],
1535 $record['a'][0],
1536 $record['a'][1],
1537 $record['a'][2],
1538 $record['a'][3]
1539 );
1540 break;
1541 }
1542 else
1543 $msgtext = $msginfo[$record['c']]['format'];
1544 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1545 }
1546 break;
1547 default:
1548 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1549 break;
1550 }
1551 unset($_SESSION['log']);
1552 }
1553
1554 /*
1555 The following conditions must be followed:
1556 1. We can mount onto free atoms only. This means: if any record for an atom
1557 already exists in RackSpace, it can't be used for mounting.
1558 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1559 and either delete them before unmounting or refuse to unmount the object.
1560 */
1561
1562 // We extensively use $_REQUEST in the function.
1563 function renderRackSpaceForObject ($object_id)
1564 {
1565 $is_update = isset ($_REQUEST['rackmulti'][0]);
1566 $info = spotEntity ('object', $object_id);
1567 if ($info == NULL)
1568 {
1569 showError ('Error loading data', __FUNCTION__);
1570 return;
1571 }
1572 // Always process occupied racks plus racks chosen by user. First get racks with
1573 // already allocated rackspace...
1574 if (NULL === ($workingRacksData = getResidentRacksData ($object_id)))
1575 die; // some error already shown
1576
1577 // ...and then add those chosen by user (if any).
1578 if (isset($_REQUEST['rackmulti']))
1579 foreach ($_REQUEST['rackmulti'] as $cand_id)
1580 {
1581 if (!isset ($workingRacksData[$cand_id]))
1582 {
1583 if (NULL == ($rackData = spotEntity ('rack', $cand_id)))
1584 {
1585 showError ('Rack not found', __FUNCTION__);
1586 return NULL;
1587 }
1588 amplifyCell ($rackData);
1589 $workingRacksData[$cand_id] = $rackData;
1590 }
1591 }
1592
1593 printOpFormIntro ('updateObjectAllocation');
1594
1595 // Do it only once...
1596 foreach ($workingRacksData as $rackId => &$rackData)
1597 {
1598 applyObjectMountMask ($rackData, $object_id);
1599 echo "<input type=\"hidden\" name=\"rackmulti[]\" value=\"$rackId\">";
1600 }
1601 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1602 unset ($rackData);
1603
1604 // This is the time for rendering.
1605
1606 // Main layout starts.
1607 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1608
1609 // Left portlet with rack list.
1610 echo "<td class=pcleft height='1%'>";
1611 startPortlet ('Racks');
1612 $allRacksData = listCells ('rack');
1613 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1614 {
1615 foreach ($allRacksData as $rack)
1616 {
1617 amplifyCell ($rack);
1618 $workingRacksData[$rack['id']] = $rack;
1619 }
1620 foreach ($workingRacksData as &$rackData)
1621 applyObjectMountMask ($rackData, $object_id);
1622 unset ($rackData);
1623 }
1624 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1625 echo "<br>";
1626 echo "<br>";
1627 finishPortlet();
1628 echo "</td>";
1629
1630 // Middle portlet with comment and submit.
1631 echo "<td class=pcleft>";
1632 startPortlet ('Comment');
1633 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1634 echo "<input type=submit value='Save' name=got_atoms>\n";
1635 echo "<br>";
1636 echo "<br>";
1637 finishPortlet();
1638 echo "</td>";
1639
1640 // Right portlet with rendered racks. If this form submit is not final, we have to
1641 // reflect the former state of the grid in current form.
1642 echo "<td class=pcright rowspan=2 height='1%'>";
1643 startPortlet ('Working copy');
1644 echo '<table border=0 cellspacing=10 align=center><tr>';
1645 foreach ($workingRacksData as $rack_id => $rackData)
1646 {
1647 // Order is important here: only original allocation is highlighted.
1648 highlightObject ($rackData, $object_id);
1649 markupAtomGrid ($rackData, 'T');
1650 // If we have a form processed, discard user input and show new database
1651 // contents.
1652 if ($is_update)
1653 mergeGridFormToRack ($rackData);
1654 echo "<td valign=top>";
1655 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1656 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1657 echo "<tr><th width='10%'>&nbsp;</th>";
1658 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1659 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1660 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1661 renderAtomGrid ($rackData);
1662 echo "<tr><th width='10%'>&nbsp;</th>";
1663 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1664 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1665 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1666 echo "</table></center>\n";
1667 echo '</td>';
1668 }
1669 echo "</tr></table>";
1670 finishPortlet();
1671 echo "</td>\n";
1672
1673
1674 echo "</form>\n";
1675 echo "</tr></table>\n";
1676 }
1677
1678 function renderMolecule ($mdata, $object_id)
1679 {
1680 // sort data out
1681 $rackpack = array();
1682 global $loclist;
1683 foreach ($mdata as $rua)
1684 {
1685 $rack_id = $rua['rack_id'];
1686 $unit_no = $rua['unit_no'];
1687 $atom = $rua['atom'];
1688 if (!isset ($rackpack[$rack_id]))
1689 {
1690 $rackData = spotEntity ('rack', $rack_id);
1691 amplifyCell ($rackData);
1692 for ($i = $rackData['height']; $i > 0; $i--)
1693 for ($locidx = 0; $locidx < 3; $locidx++)
1694 $rackData[$i][$locidx]['state'] = 'F';
1695 $rackpack[$rack_id] = $rackData;
1696 }
1697 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1698 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1699 }
1700 // now we have some racks to render
1701 foreach ($rackpack as $rackData)
1702 {
1703 markAllSpans ($rackData);
1704 echo "<table class=molecule cellspacing=0>\n";
1705 echo "<caption>${rackData['name']}</caption>\n";
1706 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1707 for ($i = $rackData['height']; $i > 0; $i--)
1708 {
1709 echo "<tr><th>$i</th>";
1710 for ($locidx = 0; $locidx < 3; $locidx++)
1711 {
1712 $state = $rackData[$i][$locidx]['state'];
1713 echo "<td class=state_${state}>&nbsp;</td>\n";
1714 }
1715 echo "</tr>\n";
1716 }
1717 echo "</table>\n";
1718 }
1719 }
1720
1721 function renderEmptyPortsSelect ($port_id, $type_id)
1722 {
1723 $ports = getEmptyPortsOfType($type_id);
1724 usort($ports, 'sortEmptyPorts');
1725 foreach ($ports as $port)
1726 {
1727 if ($port_id == $port['Port_id'])
1728 continue;
1729 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";
1730 }
1731 }
1732
1733 function renderDepot ()
1734 {
1735 global $pageno, $nextorder;
1736 $cellfilter = getCellFilter();
1737 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
1738
1739 echo "<table border=0 class=objectview>\n";
1740 echo "<tr><td class=pcleft>";
1741
1742 startPortlet ('Objects (' . count ($objects) . ')');
1743 if ($objects === NULL)
1744 {
1745 showError ('Fatal error retrieving object list', __FUNCTION__);
1746 return;
1747 }
1748 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1749 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Row/Rack</th></tr>';
1750 $order = 'odd';
1751 foreach ($objects as $obj)
1752 {
1753 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1754 $secondclass = 'tdleft port_highlight';
1755 else
1756 $secondclass = 'tdleft';
1757 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>";
1758 if (count ($obj['etags']))
1759 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
1760 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
1761 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
1762 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
1763 if ($obj['rack_id'])
1764 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>";
1765 else
1766 echo "<td class='${secondclass}'>Unmounted</td>";
1767 echo '</tr>';
1768 $order = $nextorder[$order];
1769 }
1770 echo '</table>';
1771 finishPortlet();
1772
1773 echo "</td><td class=pcright width='25%'>";
1774
1775 renderCellFilterPortlet ($cellfilter, 'object');
1776 echo "</td></tr></table>\n";
1777 }
1778
1779 // History viewer for history-enabled simple dictionaries.
1780 function renderHistory ($object_type, $object_id)
1781 {
1782 switch ($object_type)
1783 {
1784 case 'row':
1785 $query = "select ctime, user_name, name, comment from RackRowHistory where id = ${object_id} order by ctime";
1786 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>rack row comment</th></tr>';
1787 $extra = 3;
1788 break;
1789 case 'rack':
1790 $query =
1791 "select ctime, user_name, rh.name, rr.name as name, rh.height, rh.comment " .
1792 "from RackHistory as rh left join RackRow as rr on rh.row_id = rr.id " .
1793 "where rh.id = ${object_id} order by ctime";
1794 $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>';
1795 $extra = 5;
1796 break;
1797 case 'object':
1798 $query =
1799 "select ctime, user_name, RackObjectHistory.name as name, label, barcode, asset_no, has_problems, dict_value, comment " .
1800 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key join Chapter on Dictionary.chapter_id = Chapter.id " .
1801 "where Chapter.name = 'RackObjectType' and RackObjectHistory.id=${object_id} order by ctime";
1802 $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>';
1803 $extra = 8;
1804 break;
1805 default:
1806 showError ("Uknown object type '${object_type}'", __FUNCTION__);
1807 return;
1808 }
1809 global $dbxlink;
1810 $result = $dbxlink->query ($query);
1811 if ($result == NULL)
1812 {
1813 showError ('SQL query failed', __FUNCTION__);
1814 return;
1815 }
1816 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1817 $order = 'odd';
1818 global $nextorder;
1819 echo $header;
1820 while ($row = $result->fetch (PDO::FETCH_NUM))
1821 {
1822 echo "<tr class=row_${order}><td>${row[0]}</td>";
1823 for ($i = 1; $i <= $extra; $i++)
1824 echo "<td>" . $row[$i] . "</td>";
1825 echo "</tr>\n";
1826 $order = $nextorder[$order];
1827 }
1828 echo "</table><br>\n";
1829 }
1830
1831 function renderRackspaceHistory ()
1832 {
1833 global $nextorder, $pageno, $tabno;
1834 $order = 'odd';
1835 $history = getRackspaceHistory();
1836 // Show the last operation by default.
1837 if (isset ($_REQUEST['op_id']))
1838 $op_id = $_REQUEST['op_id'];
1839 elseif (isset ($history[0]['mo_id']))
1840 $op_id = $history[0]['mo_id'];
1841 else $op_id = NULL;
1842
1843 $omid = NULL;
1844 $nmid = NULL;
1845 $object_id = 1;
1846 if ($op_id)
1847 list ($omid, $nmid) = getOperationMolecules ($op_id);
1848
1849 // Main layout starts.
1850 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1851
1852 // Left top portlet with old allocation.
1853 echo "<tr><td class=pcleft>";
1854 startPortlet ('Old allocation');
1855 if ($omid)
1856 {
1857 $oldMolecule = getMolecule ($omid);
1858 renderMolecule ($oldMolecule, $object_id);
1859 }
1860 else
1861 echo "nothing";
1862 finishPortlet();
1863
1864 echo '</td><td class=pcright>';
1865
1866 // Right top portlet with new allocation
1867 startPortlet ('New allocation');
1868 if ($nmid)
1869 {
1870 $newMolecule = getMolecule ($nmid);
1871 renderMolecule ($newMolecule, $object_id);
1872 }
1873 else
1874 echo "nothing";
1875 finishPortlet();
1876
1877 echo '</td></tr><tr><td colspan=2>';
1878
1879 // Bottom portlet with list
1880
1881 startPortlet ('Rackspace allocation history');
1882 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1883 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
1884 foreach ($history as $row)
1885 {
1886 if ($row['mo_id'] == $op_id)
1887 $class = 'hl';
1888 else
1889 $class = "row_${order}";
1890 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
1891 echo "<td>${row['user_name']}</td><td>";
1892 renderCell (spotEntity ('object', $row['ro_id']));
1893 echo "</td><td>${row['comment']}</td>\n";
1894 echo "</tr>\n";
1895 $order = $nextorder[$order];
1896 }
1897 echo "</table>\n";
1898 finishPortlet();
1899
1900 echo '</td></tr></table>';
1901 }
1902
1903 function renderIPv4SpaceRecords ($tree, $baseurl, $target = 0, $level = 1)
1904 {
1905 $self = __FUNCTION__;
1906 foreach ($tree as $item)
1907 {
1908 $total = $item['addrt'];
1909 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
1910 {
1911 loadIPv4AddrList ($item); // necessary to compute router list and address counter
1912 $used = $item['addrc'];
1913 }
1914 else
1915 {
1916 $item['addrlist'] = array();
1917 $item['addrc'] = 0;
1918 }
1919 if (isset ($item['id']))
1920 {
1921 if ($item['symbol'] == 'node-collapsed')
1922 $expandurl = "${baseurl}&eid=" . $item['id'] . "#netid" . $item['id'];
1923 elseif ($item['symbol'] == 'node-expanded')
1924 $expandurl = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#netid${item['parent_id']}" : '');
1925 else
1926 $expandurl = '';
1927 echo "<tr valign=top>";
1928 printIPv4NetInfoTDs ($item, 'tdleft', $level, $item['symbol'], $expandurl);
1929 echo "<td class=tdcenter>";
1930 if ($target == $item['id'])
1931 echo "<a name=netid${target}></a>";
1932 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
1933 {
1934 renderProgressBar ($total ? $used/$total : 0);
1935 echo "<br><small>${used}/${total}</small>";
1936 }
1937 else
1938 echo "<small>${total}</small>";
1939 echo "</td>";
1940 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1941 printRoutersTD (findRouters ($item['addrlist']));
1942 echo "</tr>";
1943 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
1944 $self ($item['kids'], $baseurl, $target, $level + 1);
1945 }
1946 else
1947 {
1948 echo "<tr valign=top>";
1949 printIPv4NetInfoTDs ($item, 'tdleft sparenetwork', $level, $item['symbol']);
1950 echo "<td class=tdcenter>";
1951 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
1952 {
1953 renderProgressBar ($used/$total, 'sparenetwork');
1954 echo "<br><small>${used}/${total}</small>";
1955 }
1956 else
1957 echo "<small>${total}</small>";
1958 echo "</td><td>&nbsp;</td></tr>";
1959 }
1960 }
1961 }
1962
1963 function renderIPv4Space ()
1964 {
1965 global $pageno, $tabno;
1966 $cellfilter = getCellFilter();
1967 $netlist = filterCellList (listCells ('ipv4net'), $cellfilter['expression']);
1968 array_walk ($netlist, 'amplifyCell');
1969
1970 $netcount = count ($netlist);
1971 // expand request can take either natural values or "ALL". Zero means no expanding.
1972 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
1973 $tree = prepareIPv4Tree ($netlist, $eid);
1974
1975 echo "<table border=0 class=objectview>\n";
1976 echo "<tr><td class=pcleft>";
1977 startPortlet ("networks (${netcount})");
1978 echo '<h4>';
1979 if ($eid === 0)
1980 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
1981 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
1982 $cellfilter['urlextra'] . "'>expand all</a>)";
1983 elseif ($eid === 'ALL')
1984 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
1985 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
1986 else
1987 {
1988 $netinfo = spotEntity ('ipv4net', $eid);
1989 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>)";
1990 }
1991 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
1992 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
1993 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1994 echo "<th>routed by</th>";
1995 echo "</tr>\n";
1996 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
1997 renderIPv4SpaceRecords ($tree, $baseurl, $eid);
1998 echo "</table>\n";
1999 finishPortlet();
2000 echo '</td><td class=pcright>';
2001 renderCellFilterPortlet ($cellfilter, 'ipv4net');
2002 echo "</td></tr></table>\n";
2003 }
2004
2005 function renderIPv4SLB ()
2006 {
2007 global $page, $nextorder;
2008
2009 startPortlet ('SLB configuration');
2010 echo "<table border=0 width='100%'><tr>";
2011 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2012 echo "<td><h3><a href='".makeHref(array('page'=>$pno))."'>" . $page[$pno]['title'] . "</a></h3></td>";
2013 echo '</tr></table>';
2014 finishPortlet();
2015
2016 $summary = getSLBSummary();
2017 startPortlet ('SLB tactical overview');
2018 // A single id-keyed array isn't used here to preserve existing
2019 // order of LBs returned by getSLBSummary()
2020 $lblist = array();
2021 $lbdname = array();
2022 foreach ($summary as $vipdata)
2023 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2024 if (!in_array ($lb_object_id, $lblist))
2025 {
2026 $oi = spotEntity ('object', $lb_object_id);
2027 $lbdname[$lb_object_id] = $oi['dname'];
2028 $lblist[] = $lb_object_id;
2029 }
2030 if (!count ($summary))
2031 echo 'none configured';
2032 else
2033 {
2034 $order = 'odd';
2035 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2036 echo "<tr valign=top><td>&nbsp;</td>";
2037 foreach ($lblist as $lb_object_id)
2038 {
2039 #echo "<th><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$lb_object_id))."'>" . $lbdname[$lb_object_id] . "</a></th>";
2040 echo '<td>';
2041 renderLBCell ($lb_object_id);
2042 echo '</td>';
2043 }
2044 echo "</tr>\n";
2045 foreach ($summary as $vsid => $vsdata)
2046 {
2047 echo "<tr class=row_${order}><td class=tdleft>";
2048 renderCell (spotEntity ('ipv4vs', $vsid));
2049 echo "</td>";
2050 foreach ($lblist as $lb_object_id)
2051 {
2052 echo '<td class=tdleft>';
2053 if (!isset ($vsdata['lblist'][$lb_object_id]))
2054 echo '&nbsp;';
2055 else
2056 {
2057 echo $vsdata['lblist'][$lb_object_id]['size'];
2058 // echo " (<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$vsdata['lblist'][$lb_object_id]['id'])). "'>";
2059 // echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2060 }
2061 echo '</td>';
2062 }
2063 echo "</tr>\n";
2064 $order = $nextorder[$order];
2065 }
2066 echo "</table>\n";
2067 }
2068 finishPortlet ();
2069 }
2070
2071 function renderIPv4SpaceEditor ()
2072 {
2073 // IPv4 validator
2074 ?>
2075 <script type="text/javascript">
2076 function init() {
2077 document.add_new_range.range.setAttribute('match', "^\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\/\\d\\d?$");
2078
2079 Validate.init();
2080 }
2081 window.onload=init;
2082 </script>
2083 <?php
2084
2085 startPortlet ("Add new");
2086 echo '<table border=0 cellpadding=10 align=center>';
2087 // This form requires a name, so JavaScript validator can find it.
2088 // No printOpFormIntro() hence
2089 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2090 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2091 // tags column
2092 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2093 renderNewEntityTags ('ipv4net');
2094 echo '</td>';
2095 // inputs column
2096 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2097 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>";
2098 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2099 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2100 echo "<tr><td colspan=2>";
2101 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2102 echo '</td></tr>';
2103 echo "</form></table><br><br>\n";
2104 finishPortlet();
2105
2106 if (count ($addrspaceList = listCells ('ipv4net')))
2107 {
2108 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2109 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2110 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th></tr>";
2111 foreach ($addrspaceList as $netinfo)
2112 {
2113 amplifyCell ($netinfo);
2114 echo "<tr valign=top><td>";
2115 if (getConfigVar ('IPV4_JAYWALK') == 'yes')
2116 {
2117 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2118 printImageHREF ('destroy', 'Delete this prefix');
2119 echo "</a>";
2120 }
2121 else // only render clickable image for empty networks
2122 {
2123 loadIPv4AddrList ($netinfo);
2124 if (count ($netinfo['addrlist']))
2125 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2126 else
2127 {
2128 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2129 printImageHREF ('destroy', 'Delete this prefix');
2130 echo "</a>";
2131 }
2132
2133 }
2134 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv4net', 'id' => $netinfo['id'])) . '">';
2135 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
2136 echo '<td class=tdleft>' . htmlspecialchars ($netinfo['name']) . '</td></tr>';
2137 }
2138 echo "</table>";
2139 finishPortlet();
2140 }
2141 }
2142
2143 function renderIPv4Network ($id)
2144 {
2145 global $pageno, $tabno, $aac2, $netmaskbylen, $wildcardbylen;
2146 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2147 if (isset($_REQUEST['pg']))
2148 $page = $_REQUEST['pg'];
2149 else
2150 $page=0;
2151
2152 $range = spotEntity ('ipv4net', $id);
2153 loadIPv4AddrList ($range);
2154 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2155 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2156 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2157
2158 echo "<tr><td class=pcleft width='50%'>";
2159 startPortlet ('summary');
2160 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2161 $used = count ($range['addrlist']);
2162 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2163
2164 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2165 renderProgressBar ($used/$total);
2166 echo "&nbsp;${used}/${total}</td></tr>\n";
2167
2168 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2169 {
2170 // Build a backtrace from all parent networks.
2171 $clen = $range['mask'];
2172 $backtrace = array();
2173 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2174 {
2175 $upperinfo = spotEntity ('ipv4net', $upperid);
2176 $clen = $upperinfo['mask'];
2177 $backtrace[] = $upperinfo;
2178 }
2179 $arrows = count ($backtrace);
2180 foreach (array_reverse ($backtrace) as $ainfo)
2181 {
2182 echo "<tr><th width='50%' class=tdright>";
2183 for ($i = 0; $i < $arrows; $i++)
2184 echo '&uarr;';
2185 $arrows--;
2186 echo "</th><td class=tdleft>";
2187 renderCell ($ainfo);
2188 echo "</td></tr>";
2189 }
2190 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
2191 echo "<td class=tdleft>";
2192 renderCell ($range);
2193 echo "</td></tr>";
2194 // FIXME: get and display nested networks
2195 // $theitem = pickLeaf ($ipv4tree, $id);
2196 }
2197
2198 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2199 echo $netmaskbylen[$range['mask']];
2200 echo "</td></tr>\n";
2201
2202 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2203 printf ('0x%08X', binMaskFromDec ($range['mask']));
2204 echo "</td></tr>\n";
2205
2206 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2207 echo $wildcardbylen[$range['mask']];
2208 echo "</td></tr>\n";
2209
2210 $routers = findRouters ($range['addrlist']);
2211 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers))
2212 {
2213 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2214 printRoutersTD ($routers);
2215 echo "</tr>\n";
2216 }
2217
2218 printTagTRs ($range, makeHref(array('page'=>'ipv4space', 'tab'=>'default'))."&");
2219 echo "</table><br>\n";
2220 finishPortlet();
2221
2222 if (strlen ($range['comment']))
2223 {
2224 startPortlet ('Comment');
2225 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2226 finishPortlet ();
2227 }
2228
2229 renderFilesPortlet ('ipv4net', $id);
2230 echo "</td>\n";
2231
2232 echo "<td class=pcright>";
2233 startPortlet ('details');
2234 $startip = $range['ip_bin'] & $range['mask_bin'];
2235 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2236 $realstartip = $startip;
2237 $realendip = $endip;
2238 $numpages = 0;
2239 if($endip - $startip > $maxperpage)
2240 {
2241 $numpages = ($endip - $startip)/$maxperpage;
2242 $startip = $startip + $page * $maxperpage;
2243 $endip = $startip + $maxperpage-1;
2244 }
2245 echo "<center>";
2246 if ($numpages)
2247 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2248 for ($i=0; $i<$numpages; $i++)
2249 {
2250 if ($i == $page)
2251 echo "<b>$i</b> ";
2252 else
2253 echo "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'id'=>$id, 'pg'=>$i))."'>$i</a> ";
2254 }
2255 echo "</center>";
2256
2257 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2258 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2259
2260
2261 for ($ip = $startip; $ip <= $endip; $ip++) :
2262 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2263 $secondstyle = 'tdleft port_highlight';
2264 else
2265 $secondstyle = 'tdleft';
2266 if (!isset ($range['addrlist'][$ip]))
2267 {
2268 echo "<tr><td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>ip_long2quad($ip)))."'>" . ip_long2quad($ip);
2269 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2270 continue;
2271 }
2272 $addr = $range['addrlist'][$ip];
2273 echo "<tr class='${addr['class']}'>";
2274
2275 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
2276 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2277 $delim = '';
2278 $prologue = '';
2279 if ( $addr['reserved'] == 'yes')
2280 {
2281 echo "<strong>RESERVED</strong> ";
2282 $delim = '; ';
2283 }
2284 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2285 {
2286 echo $delim . $aac2[$ref['type']];
2287 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'hl_ipv4_addr'=>$addr['ip']))."'>";
2288 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
2289 echo "${ref['object_name']}</a>";
2290 $delim = '; ';
2291 }
2292 if ($delim != '')
2293 {
2294 $delim = '';
2295 $prologue = '<br>';
2296 }
2297 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2298 {
2299 echo $prologue;
2300 $prologue = '';
2301 echo "${delim}<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id']))."'>";
2302 echo "${ref['object_name']}</a>:<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$ref['vs_id']))."'>";
2303 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2304 $delim = '; ';
2305 }
2306 if ($delim != '')
2307 {
2308 $delim = '';
2309 $prologue = '<br>';
2310 }
2311 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2312 {
2313 echo $prologue;
2314 $prologue = '';
2315 echo "${delim}&rarr;${ref['rsport']}@<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$ref['rspool_id']))."'>";
2316 echo "${ref['rspool_name']}</a>";
2317 $delim = '; ';
2318 }
2319 echo "</td></tr>\n";
2320 endfor;
2321 // end of iteration
2322
2323 echo "</table>";
2324 finishPortlet();
2325 echo "</td></tr></table>\n";
2326 }
2327
2328 function renderIPv4NetworkProperties ($id)
2329 {
2330 $netdata = spotEntity ('ipv4net', $id);
2331 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
2332 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2333 printOpFormIntro ('editRange');
2334 echo '<tr><td class=tdright><label for=nameinput>Name:</label></td>';
2335 echo "<td class=tdleft><input type=text name=name id=nameinput size=80 maxlength=255 value='";
2336 echo htmlspecialchars ($netdata['name'], ENT_QUOTES, 'UTF-8') . "'></tr>";
2337 echo '<tr><td class=tdright><label for=commentinput>Comment:</label></td>';
2338 echo "<td class=tdleft><textarea name=comment id=commentinput cols=80 rows=25>\n";
2339 echo htmlspecialchars ($netdata['comment'], ENT_QUOTES, 'UTF-8') . "</textarea></tr>";
2340 echo "<tr><td colspan=2 class=tdcenter>";
2341 printImageHREF ('SAVE', 'Save changes', TRUE);
2342 echo "</td></form></tr></table>\n";
2343 }
2344
2345 function renderIPv4Address ($dottedquad)
2346 {
2347 global $aat, $nextorder;
2348 $address = getIPv4Address ($dottedquad);
2349 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2350 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2351 if (strlen ($address['name']))
2352 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
2353
2354 echo "<tr><td class=pcleft>";
2355 startPortlet ('summary');
2356 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2357 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
2358 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2359 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2360 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
2361 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2362 echo "</table><br>\n";
2363 finishPortlet();
2364 echo "</td>\n";
2365
2366 echo "<td class=pcright>";
2367
2368 if (isset ($address['class']))
2369 {
2370 startPortlet ('allocations');
2371 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2372 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2373 $class = $address['class'];
2374 // render all allocation records for this address the same way
2375 if ($address['reserved'] == 'yes')
2376 echo "<tr class='${class}'><td colspan=2>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td></tr>";
2377 foreach ($address['allocs'] as $bond)
2378 {
2379 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2380 $secondclass = 'tdleft port_highlight';
2381 else
2382 $secondclass = 'tdleft';
2383 echo "<tr class='$class'><td class=tdleft><a href='".makeHref(array('page'=>'object', 'object_id'=>$bond['object_id'], 'hl_ipv4_addr'=>$dottedquad))."'>${bond['object_name']}</td><td class='${secondclass}'>${bond['name']}</td><td class='${secondclass}'><strong>";
2384 echo $aat[$bond['type']];
2385 echo "</strong></td></tr>\n";
2386 }
2387 echo "</table><br><br>";
2388 finishPortlet();
2389 }
2390
2391 // FIXME: The returned list is structured differently, than we expect it to be. One of the sides
2392 // must be fixed.
2393 if (count ($address['lblist']))
2394 {
2395 startPortlet ('Virtual services (' . count ($address['lblist']) . ')');
2396 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2397 echo "<tr><th>VS</th><th>LB</th></tr>\n";
2398 $order = 'odd';
2399 foreach ($address['lblist'] as $vsinfo)
2400 {
2401 echo "<tr valign=top class=row_${order}><td class=tdleft>";
2402 renderCell (spotEntity ('ipv4vs', $vsinfo['vs_id']));
2403 echo "</td><td class=tdleft>";
2404 renderLBCell ($vsinfo['object_id']);
2405 echo "</td></tr>";
2406 $order = $nextorder[$order];
2407 }
2408 echo "</table><br><br>";
2409 finishPortlet();
2410 }
2411
2412 if (count ($address['rslist']))
2413 {
2414 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2415 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2416 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
2417 foreach ($address['rslist'] as $rsinfo)
2418 {
2419 echo "<tr><td>";
2420 if ($rsinfo['inservice'] == 'yes')
2421 printImageHREF ('inservice', 'in service');
2422 else
2423 printImageHREF ('notinservice', 'NOT in service');
2424 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsinfo['rspool_id']))."'>";
2425 echo $rsinfo['rspool_name'] . "</a></td></tr>\n";
2426 }
2427 echo "</table><br><br>";
2428 finishPortlet();
2429 }
2430
2431 if (count ($address['outpf']))
2432 {
2433 startPortlet ('departing NAT rules');
2434 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2435 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2436 foreach ($address['outpf'] as $rule)
2437 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2438 echo "</table>";
2439 finishPortlet();
2440 }
2441
2442 if (count ($address['inpf']))
2443 {
2444 startPortlet ('arriving NAT rules');
2445 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2446 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2447 foreach ($address['inpf'] as $rule)
2448 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2449 echo "</table>";
2450 finishPortlet();
2451 }
2452
2453 echo "</td></tr>";
2454 echo "</table>\n";
2455 }
2456
2457 function renderIPv4AddressProperties ($dottedquad)
2458 {
2459 $address = getIPv4Address ($dottedquad);
2460 echo "<center><h1>$dottedquad</h1></center>\n";
2461
2462 startPortlet ('update');
2463 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2464 printOpFormIntro ('editAddress');
2465 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2466 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2467 echo ($address['reserved']=='yes') ? 'checked' : '';
2468 echo "></tr><tr><td class=tdleft>";
2469 printImageHREF ('SAVE', 'Save changes', TRUE);
2470 echo "</td></form><td class=tdright>";
2471 if (!strlen ($address['name']) and $address['reserved'] == 'no')
2472 printImageHREF ('CLEAR gray');
2473 else
2474 {
2475 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2476 printImageHREF ('CLEAR', 'Release', TRUE);
2477 echo "</form>";
2478 }
2479 echo "</td></tr></table>\n";
2480 finishPortlet();
2481 }
2482
2483 function renderIPv4AddressAllocations ($dottedquad)
2484 {
2485 function printNewItemTR ()
2486 {
2487 global $aat;
2488 printOpFormIntro ('addIPv4Allocation');
2489 echo "<tr><td>";
2490 printImageHREF ('add', 'allocate', TRUE);
2491 echo "</td><td>";
2492 printSelect (getNarrowObjectList ('IPV4OBJ_LISTSRC'), 'object_id', NULL, 100);
2493 echo "</td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
2494 printSelect ($aat, 'bond_type', NULL, 102);
2495 echo "</td><td>";
2496 printImageHREF ('add', 'allocate', TRUE, 103);
2497 echo "</td></form></tr>";
2498 }
2499 global $aat;
2500
2501 $address = getIPv4Address ($dottedquad);
2502
2503 echo "<center><h1>${dottedquad}</h1></center>\n";
2504 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2505 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
2506
2507 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2508 printNewItemTR();
2509 if (isset ($address['class']))
2510 {
2511 $class = $address['class'];
2512 if ($address['reserved'] == 'yes')
2513 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2514 foreach ($address['allocs'] as $bond)
2515 {
2516 echo "<tr class='$class'>";
2517 printOpFormIntro ('updIPv4Allocation', array ('object_id' => $bond['object_id']));
2518 echo "<td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$bond['object_id']))."'>";
2519 printImageHREF ('delete', 'Unallocate address');
2520 echo "</a></td>";
2521 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$bond['object_id'], 'hl_ipv4_addr'=>$dottedquad))."'>${bond['object_name']}</td>";
2522 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
2523 printSelect ($aat, 'bond_type', $bond['type']);
2524 echo "</td><td>";
2525 printImageHREF ('save', 'Save changes', TRUE);
2526 echo "</td></form></tr>\n";
2527 }
2528 }
2529 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2530 printNewItemTR();
2531 echo "</table><br><br>";
2532 }
2533
2534 function renderNATv4ForObject ($object_id)
2535 {
2536 function printNewItemTR ($alloclist)
2537 {
2538 printOpFormIntro ('addNATv4Rule');
2539 echo "<tr align='center'><td>";
2540 printImageHREF ('add', 'Add new NAT rule', TRUE);
2541 echo '</td><td>';
2542 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
2543 echo "<select name='localip' tabindex=1>";
2544
2545 foreach ($alloclist as $dottedquad => $alloc)
2546 {
2547 $name = (!isset ($alloc['addrinfo']['name']) or !strlen ($alloc['addrinfo']['name'])) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2548 $osif = (!isset ($alloc['osif']) or !strlen ($alloc['osif'])) ? '' : ($alloc['osif'] . ': ');
2549 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
2550 }
2551
2552 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2553 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2554 echo "<a href='javascript:;' onclick='window.open(\"" . makeHrefForHelper ('inet4list');
2555 echo "\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
2556 printImageHREF ('find', 'Find object');
2557 echo "</a>";
2558 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2559 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
2560 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
2561 echo "</td></tr></form>";
2562 }
2563
2564 $focus = spotEntity ('object', $object_id);
2565 amplifyCell ($focus);
2566 echo "<center><h2>locally performed NAT</h2></center>";
2567
2568 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2569 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
2570
2571 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2572 printNewItemTR ($focus['ipv4']);
2573 foreach ($focus['nat4']['out'] as $pf)
2574 {
2575 $class = 'trerror';
2576 $osif = '';
2577 if (isset ($focus['ipv4'][$pf['localip']]))
2578 {
2579 $class = $focus['ipv4'][$pf['localip']]['addrinfo']['class'];
2580 $osif = $focus['ipv4'][$pf['localip']]['osif'] . ': ';
2581 }
2582
2583 echo "<tr class='$class'>";
2584 echo "<td><a href='".
2585 makeHrefProcess(array(
2586 'op'=>'delNATv4Rule',
2587 'localip'=>$pf['localip'],
2588 'localport'=>$pf['localport'],
2589 'remoteip'=>$pf['remoteip'],
2590 'remoteport'=>$pf['remoteport'],
2591 'proto'=>$pf['proto'],
2592 'object_id'=>$object_id)).
2593 "'>";
2594 printImageHREF ('delete', 'Delete NAT rule');
2595 echo "</a></td>";
2596 echo "<td>${pf['proto']}/${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}";
2597 if (strlen ($pf['local_addr_name']))
2598 echo ' (' . $pf['local_addr_name'] . ')';
2599 echo "</td>";
2600 echo "<td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2601
2602 $address = getIPv4Address ($pf['remoteip']);
2603
2604 echo "<td class='description'>";
2605 if (count ($address['allocs']))
2606 foreach ($address['allocs'] as $bond)
2607 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
2608 elseif (strlen ($pf['remote_addr_name']))
2609 echo '(' . $pf['remote_addr_name'] . ')';
2610 printOpFormIntro
2611 (
2612 'updNATv4Rule',
2613 array
2614 (
2615 'localip' => $pf['localip'],
2616 'localport' => $pf['localport'],
2617 'remoteip' => $pf['remoteip'],
2618 'remoteport' => $pf['remoteport'],
2619 'proto' => $pf['proto']
2620 )
2621 );
2622 echo "</td><td class='description'>";
2623 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2624 printImageHREF ('save', 'Save changes', TRUE);
2625 echo "</td></form></tr>";
2626 }
2627 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2628 printNewItemTR ($focus['ipv4']);
2629
2630 echo "</table><br><br>";
2631 if (!count ($focus['nat4']))
2632 return;
2633
2634 echo "<center><h2>arriving NAT connections</h2></center>";
2635 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2636 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2637
2638 foreach ($focus['nat4']['in'] as $pf)
2639 {
2640 echo "<tr><td><a href='".
2641 makeHrefProcess(array(
2642 'op'=>'delNATv4Rule',
2643 'localip'=>$pf['localip'],
2644 'localport'=>$pf['localport'],
2645 'remoteip'=>$pf['remoteip'],
2646 'remoteport'=>$pf['remoteport'],
2647 'proto'=>$pf['proto'],
2648 'object_id'=>$pf['object_id']
2649 )).
2650 "'>";
2651 printImageHREF ('delete', 'Delete NAT rule');
2652 echo "</a></td>";
2653 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
2654 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
2655 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2656 echo "<td class='description'>${pf['description']}</td></tr>";
2657 }
2658
2659 echo "</table><br><br>";
2660 }
2661
2662 function renderAddMultipleObjectsForm ()
2663 {
2664 $typelist = readChapter (CHAP_OBJTYPE, 'o');
2665 $typelist[0] = 'select type...';
2666 $typelist = cookOptgroups ($typelist);
2667 $max = getConfigVar ('MASSCOUNT');
2668 $tabindex = 100;
2669
2670 startPortlet ('Distinct types, same tags');
2671 printOpFormIntro ('addObjects');
2672 echo '<table border=0 align=center>';
2673 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
2674 echo "<th>Asset tag</th><th>Barcode</th><th>Tags</th></tr>\n";
2675 for ($i = 0; $i < $max; $i++)
2676 {
2677 echo '<tr><td>';
2678 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2679 printNiftySelect ($typelist, "${i}_object_type_id", 0, $tabindex);
2680 echo '</td>';
2681 echo "<td><input type=text size=30 name=${i}_object_name tabindex=${tabindex}></td>";
2682 echo "<td><input type=text size=30 name=${i}_object_label tabindex=${tabindex}></td>";
2683 echo "<td><input type=text size=20 name=${i}_object_asset_no tabindex=${tabindex}></td>";
2684 echo "<td><input type=text size=10 name=${i}_object_barcode tabindex=${tabindex}></td>";
2685 if ($i == 0)
2686 {
2687 echo "<td valign=top rowspan=${max}>";
2688 renderNewEntityTags ('object');
2689 echo "</td>\n";
2690 }
2691 echo "</tr>\n";
2692 $tabindex++;
2693 }
2694 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2695 echo "</form></table>\n";
2696 finishPortlet();
2697
2698 startPortlet ('Same type, same tags');
2699 printOpFormIntro ('addLotOfObjects');
2700 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2701 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
2702 echo "</textarea></td><td valign=top>";
2703 printSelect ($typelist, "global_type_id", getConfigVar ('DEFAULT_OBJECT_TYPE'));
2704 echo "</td></tr>";
2705 echo "<tr><th>Tags</th></tr>";
2706 echo "<tr><td valign=top>";
2707 renderNewEntityTags ('object');
2708 echo "</td></tr>";
2709 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2710 echo "</form>\n";
2711 finishPortlet();
2712 }
2713
2714 function printGreeting ()
2715 {
2716 global $root, $remote_username, $remote_displayname;
2717 echo "Hello, <a href='${root}?page=myaccount&tab=default'>${remote_displayname}</a>. This is RackTables " .
2718 CODE_VERSION .
2719 ". Click <a href='${root}?logout'>here</a> to logout.";
2720 }
2721
2722 function renderSearchResults ()
2723 {
2724 global $root;
2725 $terms = trim ($_REQUEST['q']);
2726 if (!strlen ($terms))
2727 {
2728 showError ('Search string cannot be empty.', __FUNCTION__);
2729 return;
2730 }
2731 if (!permitted ('depot', 'default'))
2732 {
2733 showError ('You are not authorized for viewing information about objects.', __FUNCTION__);
2734 return;
2735 }
2736 $nhits = 0;
2737 if (preg_match (RE_IP4_ADDR, $terms))
2738 // Search for IPv4 address.
2739 {
2740 if (NULL !== getIPv4AddressNetworkId ($terms))
2741 {
2742 $nhits++;
2743 $lasthit = 'ipv4addressbydq';
2744 $summary['ipv4addressbydq'][] = $terms;
2745 }
2746 }
2747 elseif (preg_match (RE_IP4_NET, $terms))
2748 // Search for IPv4 network
2749 {
2750 list ($base, $len) = explode ('/', $terms);
2751 if (NULL !== ($tmp = getIPv4AddressNetworkId ($base, $len + 1)))
2752 {
2753 $nhits++;
2754 $lasthit = 'ipv4network';
2755 $summary['ipv4network'][] = spotEntity ('ipv4net', $tmp);
2756 }
2757 }
2758 else
2759 // Search for objects, addresses, networks, virtual services and RS pools by their description.
2760 {
2761 $tmp = getObjectSearchResults ($terms);
2762 if (count ($tmp))
2763 {
2764 $nhits += count ($tmp);
2765 $lasthit = 'object';
2766 $summary['object'] = $tmp;
2767 }
2768 $tmp = getIPv4AddressSearchResult ($terms);
2769 if (count ($tmp))
2770 {
2771 $nhits += count ($tmp);
2772 $lasthit = 'ipv4addressbydescr';
2773 $summary['ipv4addressbydescr'] = $tmp;
2774 }
2775 $tmp = getIPv4PrefixSearchResult ($terms);
2776 if (count ($tmp))
2777 {
2778 $nhits += count ($tmp);
2779 $lasthit = 'ipv4network';
2780 $summary['ipv4network'] = $tmp;
2781 }
2782 $tmp = getIPv4RSPoolSearchResult ($terms);
2783 if (count ($tmp))
2784 {
2785 $nhits += count ($tmp);
2786 $lasthit = 'ipv4rspool';
2787 $summary['ipv4rspool'] = $tmp;
2788 }
2789 $tmp = getIPv4VServiceSearchResult ($terms);
2790 if (count ($tmp))
2791 {
2792 $nhits += count ($tmp);
2793 $lasthit = 'ipv4vs';
2794 $summary['ipv4vs'] = $tmp;
2795 }
2796 $tmp = getAccountSearchResult ($terms);
2797 if (count ($tmp))
2798 {
2799 $nhits += count ($tmp);
2800 $lasthit = 'user';
2801 $summary['user'] = $tmp;
2802 }
2803 $tmp = getFileSearchResult ($terms);
2804 if (count ($tmp))
2805 {
2806 $nhits += count ($tmp);
2807 $lasthit = 'file';
2808 $summary['file'] = $tmp;
2809 }
2810 $tmp = getRackSearchResult ($terms);
2811 if (count ($tmp))
2812 {
2813 $nhits += count ($tmp);
2814 $lasthit = 'rack';
2815 $summary['rack'] = $tmp;
2816 }
2817 }
2818 if ($nhits == 0)
2819 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
2820 elseif ($nhits == 1)
2821 {
2822 $record = current ($summary[$lasthit]);
2823 switch ($lasthit)
2824 {
2825 case 'ipv4addressbydq':
2826 $parentnet = getIPv4AddressNetworkId ($record);
2827 if ($parentnet !== NULL)
2828 echo "<script language='Javascript'>document.location='${root}?page=ipv4net&tab=default&id=${parentnet}&hl_ipv4_addr=${record}';//</script>";
2829 else
2830 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record}';//</script>";
2831 break;
2832 case 'ipv4addressbydescr':
2833 $parentnet = getIPv4AddressNetworkId ($record['ip']);
2834 if ($parentnet !== NULL)
2835 echo "<script language='Javascript'>document.location='${root}?page=ipv4net&tab=default&id=${parentnet}&hl_ipv4_addr=${record['ip']}';//</script>";
2836 else
2837 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record['ip']}';//</script>";
2838 break;
2839 case 'ipv4network':
2840 echo "<script language='Javascript'>document.location='${root}?page=ipv4net";
2841 echo "&id=${record['id']}";
2842 echo "';//</script>";
2843 break;
2844 case 'object':
2845 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${record['id']}';//</script>";
2846 break;
2847 case 'ipv4rspool':
2848 echo "<script language='Javascript'>document.location='${root}?page=ipv4rspool&pool_id=${r