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