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