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