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