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