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