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