a78c470cc00345f23bd3799dada893430f15248b
[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']} 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 if ($port['iif_id'] != 1)
990 echo $port['iif_name'] . '/';
991 echo $port['oif_name'] . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
992 if ($port['remote_object_id'])
993 {
994 $remote_object = spotEntity ('object', $port['remote_object_id']);
995 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>";
996 echo "<td class=tdleft>${port['remote_name']}</td>";
997 }
998 elseif (strlen ($port['reservation_comment']))
999 {
1000 echo "<td class=tdleft><b>Reserved:</b></td>";
1001 echo "<td class='tdleft rsvtext'>${port['reservation_comment']}</td>";
1002 }
1003 else
1004 echo '<td>&nbsp;</td><td>&nbsp;</td>';
1005 echo "</tr>";
1006 }
1007 echo "</table><br>";
1008 finishPortlet();
1009 }
1010
1011 $alloclist = $info['ipv4'];
1012 if (count ($alloclist))
1013 {
1014 startPortlet ('IPv4 addresses');
1015 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1016 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1017 echo "<tr><th>OS interface</th><th>IP address</th><th>network</th><th>routed by</th><th>peers</th></tr>\n";
1018 else
1019 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
1020 $hl_ipv4_addr = '';
1021 if (isset ($_REQUEST['hl_ipv4_addr']))
1022 {
1023 assertIPv4Arg ('hl_ipv4_addr');
1024 $hl_ipv4_addr = $_REQUEST['hl_ipv4_addr'];
1025 }
1026 foreach ($alloclist as $dottedquad => $alloc)
1027 {
1028 $address_name = niftyString ($alloc['addrinfo']['name']);
1029 $class = $alloc['addrinfo']['class'];
1030 $secondclass = ($hl_ipv4_addr == $dottedquad) ? 'tdleft port_highlight' : 'tdleft';
1031 $netid = getIPv4AddressNetworkId ($dottedquad);
1032 if (NULL !== $netid)
1033 {
1034 $netinfo = spotEntity ('ipv4net', $netid);
1035 loadIPv4AddrList ($netinfo);
1036 }
1037 echo "<tr class='${class}' valign=top><td class=tdleft>${alloc['osif']}</td><td class='${secondclass}'>";
1038 if (NULL !== $netid)
1039 echo "<a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$dottedquad, 'hl_object_id'=>$object_id))."'>${dottedquad}</a>";
1040 else
1041 echo $dottedquad;
1042 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1043 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1044 echo '&nbsp;' . $aac[$alloc['type']];
1045 if (strlen ($alloc['addrinfo']['name']))
1046 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1047 echo '</td>';
1048 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1049 {
1050 if (NULL === $netid)
1051 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1052 else
1053 {
1054 echo "<td class='${secondclass}'>";
1055 renderCell ($netinfo);
1056 echo "</td>";
1057 // filter out self-allocation
1058 $other_routers = array();
1059 foreach (findRouters ($netinfo['addrlist']) as $router)
1060 if ($router['id'] != $object_id)
1061 $other_routers[] = $router;
1062 if (count ($other_routers))
1063 printRoutersTD ($other_routers);
1064 else
1065 echo "<td class='${secondclass}'>&nbsp;</td>";
1066 }
1067 }
1068 // peers
1069 echo "<td class='${secondclass}'>\n";
1070 $prefix = '';
1071 if ($alloc['addrinfo']['reserved'] == 'yes')
1072 {
1073 echo $prefix . '<strong>RESERVED</strong>';
1074 $prefix = '; ';
1075 }
1076 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1077 {
1078 if ($allocpeer['object_id'] == $object_id)
1079 continue;
1080 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1081 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
1082 echo $allocpeer['osif'] . '@';
1083 echo $allocpeer['object_name'] . '</a>';
1084 $prefix = '; ';
1085 }
1086 echo "</td></tr>\n";
1087 }
1088 echo "</table><br>\n";
1089 finishPortlet();
1090 }
1091
1092 $forwards = $info['nat4'];
1093 if (count($forwards['in']) or count($forwards['out']))
1094 {
1095 startPortlet('NATv4');
1096
1097 if (count($forwards['out']))
1098 {
1099
1100 echo "<h3>locally performed NAT</h3>";
1101
1102 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
1103 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
1104
1105 foreach ($forwards['out'] as $pf)
1106 {
1107 $class = 'trerror';
1108 $osif = '';
1109 if (isset ($alloclist [$pf['localip']]))
1110 {
1111 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
1112 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
1113 }
1114 echo "<tr class='$class'>";
1115 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>";
1116 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
1117 $address = getIPv4Address ($pf['remoteip']);
1118 echo "<td class='description'>";
1119 if (count ($address['allocs']))
1120 foreach($address['allocs'] as $bond)
1121 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
1122 elseif (strlen ($pf['remote_addr_name']))
1123 echo '(' . $pf['remote_addr_name'] . ')';
1124 echo "</td><td class='description'>${pf['description']}</td></tr>";
1125 }
1126 echo "</table><br><br>";
1127 }
1128 if (count($forwards['in']))
1129 {
1130 echo "<h3>arriving NAT connections</h3>";
1131 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
1132 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
1133 foreach ($forwards['in'] as $pf)
1134 {
1135 echo "<tr>";
1136 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
1137 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
1138 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
1139 echo "<td class='description'>${pf['description']}</td></tr>";
1140 }
1141 echo "</table><br><br>";
1142 }
1143 finishPortlet();
1144 }
1145
1146 $pools = $info['ipv4rspools'];
1147 if (count ($pools))
1148 {
1149 $order = 'odd';
1150 startPortlet ('Real server pools (' . count ($pools) . ')');
1151 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
1152 echo "<tr><th>VS</th><th>RS pool</th><th>RS</th><th>VS config</th><th>RS config</th></tr>\n";
1153 foreach ($pools as $vs_id => $info)
1154 {
1155 echo "<tr valign=top class=row_${order}><td class=tdleft>";
1156 renderCell (spotEntity ('ipv4vs', $vs_id));
1157 echo "</td><td class=tdleft>";
1158 renderCell (spotEntity ('ipv4rspool', $info['pool_id']));
1159 echo '</td><td class=tdleft>' . $info['rscount'] . '</td>';
1160 echo "<td class=slbconf>${info['vsconfig']}</td>";
1161 echo "<td class=slbconf>${info['rsconfig']}</td>";
1162 echo "</tr>\n";
1163 $order = $nextorder[$order];
1164 }
1165 echo "</table>\n";
1166 finishPortlet();
1167 }
1168 echo "</td>\n";
1169
1170 // After left column we have (surprise!) right column with rackspace portlet only.
1171 echo "<td class=pcright>";
1172 // rackspace portlet
1173 startPortlet ('rackspace allocation');
1174 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1175 renderRack ($rack_id, $object_id);
1176 echo '<br>';
1177 finishPortlet();
1178 echo "</td></tr>";
1179 echo "</table>\n";
1180 }
1181
1182 function renderRackMultiSelect ($sname, $racks, $selected)
1183 {
1184 // Transform the given flat list into a list of groups, each representing a rack row.
1185 $rdata = array();
1186 foreach ($racks as $rack)
1187 if (!isset ($rdata[$rack['row_name']]))
1188 $rdata[$rack['row_name']] = array ($rack['id'] => $rack['name']);
1189 else
1190 $rdata[$rack['row_name']][$rack['id']] = $rack['name'];
1191 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementsByName(\"updateObjectAllocation\")[0].submit()'>\n";
1192 foreach ($rdata as $optgroup => $racklist)
1193 {
1194 echo "<optgroup label='${optgroup}'>";
1195 foreach ($racklist as $rack_id => $rack_name)
1196 {
1197 echo "<option value=${rack_id}";
1198 if (!(array_search ($rack_id, $selected) === FALSE))
1199 echo ' selected';
1200 echo">${rack_name}</option>\n";
1201 }
1202 }
1203 echo "</select>\n";
1204 }
1205
1206 // This function renders a form for port edition.
1207 function renderPortsForObject ($object_id)
1208 {
1209 $prefs = getPortListPrefs();
1210 function printNewItemTR ($prefs)
1211 {
1212 printOpFormIntro ('addPort');
1213 echo "<tr><td>";
1214 printImageHREF ('add', 'add a port', TRUE);
1215 echo "</td><td><input type=text size=8 name=port_name tabindex=100></td>\n";
1216 echo "<td><input type=text name=port_label tabindex=101></td><td>";
1217 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 102), $prefs['selected']);
1218 echo "<td><input type=text name=port_l2address tabindex=103 size=18 maxlength=24></td>\n";
1219 echo "<td colspan=3>&nbsp;</td><td>";
1220 printImageHREF ('add', 'add a port', TRUE, 104);
1221 echo "</td></tr></form>";
1222 }
1223 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes' || getConfigVar('ENABLE_BULKPORT_FORM') == 'yes' )
1224 startPortlet ('Ports and interfaces');
1225 else
1226 echo '<br>';
1227 $object = spotEntity ('object', $object_id);
1228 amplifyCell ($object);
1229 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1230 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1231 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>";
1232 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1233 printOpFormIntro ('addBulkPorts');
1234 echo "<tr><td>";
1235 printImageHREF ('add', 'add ports', TRUE);
1236 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1237 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1238 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1239 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1240 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1241 echo "<td>&nbsp;</td><td>";
1242 printImageHREF ('add', 'add ports', TRUE, 110);
1243 echo "</td></tr></form>";
1244 echo "</table><br>\n";
1245 }
1246
1247 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1248 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>";
1249 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";
1250 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1251 printNewItemTR ($prefs);
1252 foreach ($object['ports'] as $port)
1253 {
1254 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
1255 echo "<tr><td><a href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id'], 'object_id'=>$object_id, 'port_name'=>$port['name']))."'>";
1256 printImageHREF ('delete', 'Unlink and Delete this port');
1257 echo "</a></td>\n";
1258 echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
1259 echo "<td><input type=text name=label value='${port['label']}'></td>";
1260 if (!$port['remote_object_id'])
1261 {
1262 echo '<td>';
1263 if ($port['iif_id'] != 1)
1264 echo '<label>' . $port['iif_name'] . ' ';
1265 printSelect (getExistingPortTypeOptions ($port['id']), array ('name' => 'port_type_id'), $port['oif_id']);
1266 if ($port['iif_id'] != 1)
1267 echo '</label>';
1268 echo '</td>';
1269 }
1270 else
1271 {
1272 echo "<input type=hidden name=port_type_id value='${port['oif_id']}'><td class=tdleft>";
1273 if ($port['iif_id'] != 1)
1274 echo $port['iif_name'] . '/';
1275 echo "${port['oif_name']}</td>\n";
1276 }
1277 // 18 is enough to fit 6-byte MAC address in its longest form,
1278 // while 24 should be Ok for WWN
1279 echo "<td><input type=text name=l2address value='${port['l2address']}' size=18 maxlength=24></td>\n";
1280 if ($port['remote_object_id'])
1281 {
1282 $remote_object = spotEntity ('object', $port['remote_object_id']);
1283 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$port['remote_object_id']))."'>${remote_object['dname']}</a></td>";
1284 echo "<td>${port['remote_name']}</td>";
1285 echo "<td class=tdcenter><a href='".
1286 makeHrefProcess(array(
1287 'op'=>'unlinkPort',
1288 'port_id'=>$port['id'],
1289 'remote_port_id' => $port['remote_id'],
1290 'object_id'=>$object_id)).
1291 "'>";
1292 printImageHREF ('cut', 'Unlink this port');
1293 echo "</a></td>";
1294 }
1295 elseif (strlen ($port['reservation_comment']))
1296 {
1297 echo "<td><b>Reserved:</b></td>";
1298 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
1299 echo "<td class=tdcenter><a href='".
1300 makeHrefProcess(array(
1301 'op'=>'useup',
1302 'port_id'=>$port['id'],
1303 'object_id'=>$object_id)).
1304 "'>";
1305 printImageHREF ('clear', 'Use up this port');
1306 echo "</a></td>";
1307 }
1308 else
1309 {
1310 //echo "<td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><a href='javascript:;'";
1311 echo "<td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><span";
1312 $helper_args = array
1313 (
1314 'port' => $port['id'],
1315 'in_rack' => 'n',
1316 );
1317 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
1318 'resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no';
1319 echo " ondblclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1320 echo "\",\"findlink\",\"${popup_args}\");'";
1321 // end of onclick=
1322 $helper_args['in_rack'] = 'y';
1323 echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1324 echo "\",\"findlink\",\"${popup_args}\");'";
1325 // end of onclick=
1326 echo '>';
1327 // end of <a>
1328 printImageHREF ('plug', 'Link this port');
1329 echo "</span>";
1330 echo " <input type=text name=reservation_comment></td>\n";
1331 }
1332 echo "<td>";
1333 printImageHREF ('save', 'Save changes', TRUE);
1334 echo "</td></form></tr>\n";
1335 }
1336 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1337 printNewItemTR ($prefs);
1338 echo "</table><br>\n";
1339 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1340 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1341 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>";
1342 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1343 printOpFormIntro ('addBulkPorts');
1344 echo "<tr><td>";
1345 printImageHREF ('add', 'add ports', TRUE);
1346 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1347 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1348 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1349 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1350 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1351 echo "<td>&nbsp;</td><td>";
1352 printImageHREF ('add', 'add ports', TRUE, 110);
1353 echo "</td></tr></form>";
1354 echo "</table><br>\n";
1355 }
1356 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes')
1357 finishPortlet();
1358 if (getConfigVar('ENABLE_MULTIPORT_FORM') != 'yes')
1359 return;
1360
1361 startPortlet ('Add/update multiple ports');
1362 printOpFormIntro ('addMultiPorts');
1363 echo 'Format: <select name=format tabindex=201>';
1364 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1365 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
1366 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
1367 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
1368 echo "</select>";
1369 echo 'Default port type: ';
1370 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type', 'tabindex' => 202), $prefs['selected']);
1371 echo "<input type=submit value='Parse output' tabindex=204><br>\n";
1372 echo "<textarea name=input cols=100 rows=50 tabindex=203></textarea><br>\n";
1373 echo '</form>';
1374 finishPortlet();
1375 }
1376
1377 function renderIPv4ForObject ($object_id)
1378 {
1379 function printNewItemTR ()
1380 {
1381 global $aat;
1382 printOpFormIntro ('addIPv4Allocation');
1383 echo "<tr><td>";
1384 printImageHREF ('add', 'allocate', TRUE);
1385 echo "</td>";
1386 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1387 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
1388 echo "<td colspan=2>&nbsp;</td><td>";
1389 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), 'regular');
1390 echo "</td><td>&nbsp;</td><td>";
1391 printImageHREF ('add', 'allocate', TRUE, 103);
1392 echo "</td></tr></form>";
1393 }
1394 $focus = spotEntity ('object', $object_id);
1395 amplifyCell ($focus);
1396 global $aat;
1397 startPortlet ('Allocations');
1398 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1399 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1400 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1401 echo '<th>network</th><th>routed by</th>';
1402 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1403
1404 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1405 printNewItemTR();
1406 foreach ($focus['ipv4'] as $dottedquad => $alloc)
1407 {
1408 $class = $alloc['addrinfo']['class'];
1409 $netid = getIPv4AddressNetworkId ($dottedquad);
1410 if (NULL !== $netid)
1411 {
1412 $netinfo = spotEntity ('ipv4net', $netid);
1413 loadIPv4AddrList ($netinfo);
1414 }
1415 printOpFormIntro ('updIPv4Allocation', array ('ip' => $dottedquad));
1416 echo "<tr class='$class' valign=top><td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$object_id))."'>";
1417 printImageHREF ('delete', 'Delete this IPv4 address');
1418 echo "</a></td>";
1419 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td><td class=tdleft>";
1420 if (NULL !== $netid)
1421 echo "<a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$dottedquad))."'>${dottedquad}</a>";
1422 else
1423 echo $dottedquad;
1424 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1425 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1426 if (strlen ($alloc['addrinfo']['name']))
1427 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1428 echo '</td>';
1429 // FIXME: this a copy-and-paste from renderRackObject()
1430 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1431 {
1432 if (NULL === $netid)
1433 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1434 else
1435 {
1436 echo '<td>';
1437 renderCell ($netinfo);
1438 echo '</td>';
1439 // filter out self-allocation
1440 $other_routers = array();
1441 foreach (findRouters ($netinfo['addrlist']) as $router)
1442 if ($router['id'] != $object_id)
1443 $other_routers[] = $router;
1444 if (count ($other_routers))
1445 printRoutersTD ($other_routers);
1446 else
1447 echo "<td>&nbsp;</td>";
1448 }
1449 }
1450 echo '<td>';
1451 printSelect ($aat, array ('name' => 'bond_type'), $alloc['type']);
1452 echo "</td><td>";
1453 $prefix = '';
1454 if ($alloc['addrinfo']['reserved'] == 'yes')
1455 {
1456 echo $prefix . '<strong>RESERVED</strong>';
1457 $prefix = '; ';
1458 }
1459 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1460 {
1461 if ($allocpeer['object_id'] == $object_id)
1462 continue;
1463 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1464 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
1465 echo $allocpeer['osif'] . '@';
1466 echo $allocpeer['object_name'] . '</a>';
1467 $prefix = '; ';
1468 }
1469 echo "</td><td>";
1470 printImageHREF ('save', 'Save changes', TRUE);
1471 echo "</td></form></tr>\n";
1472 }
1473 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1474 printNewItemTR();
1475
1476 echo "</table><br>\n";
1477 finishPortlet();
1478
1479 }
1480
1481 // Log structure versions:
1482 // 1: the whole structure is a list of code-message pairs
1483 // 2 and later: there's a "v" field set, which indicates the version
1484 // 2: there's a "m" list set to hold message code and optional arguments
1485 function showMessageOrError ()
1486 {
1487 if (!isset ($_SESSION['log']))
1488 return;
1489 $log = $_SESSION['log'];
1490 switch (TRUE)
1491 {
1492 case !isset ($log['v']):
1493 case $log['v'] == 1:
1494 foreach ($log as $key => $record)
1495 if ($key !== 'v')
1496 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1497 break;
1498 case $log['v'] == 2:
1499 $msginfo = array
1500 (
1501 // records 0~99 with success messages
1502 0 => array ('code' => 'success', 'format' => '%s'),
1503 1 => array ('code' => 'success', 'format' => '%u new records done, %u already existed'),
1504 2 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully added.'),
1505 3 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully deleted.'),
1506 4 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully updated'),
1507 5 => array ('code' => 'success', 'format' => 'Port %s was added successfully'),
1508 6 => array ('code' => 'success', 'format' => 'Port %s was updated successfully'),
1509 7 => array ('code' => 'success', 'format' => 'Port %s was deleted successfully'),
1510 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with port %s at object %s'),
1511 9 => array ('code' => 'success', 'format' => 'Port %s was successfully unlinked from %s@%s'),
1512 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1513 11 => array ('code' => 'success', 'format' => 'Reservation removed.'),
1514 12 => array ('code' => 'success', 'format' => 'allocation updated'),
1515 13 => array ('code' => 'success', 'format' => 'allocated'),
1516 14 => array ('code' => 'success', 'format' => 'deallocated'),
1517 15 => array ('code' => 'success', 'format' => 'Reset succeeded.'),
1518 16 => array ('code' => 'success', 'format' => 'Update done'),
1519 17 => array ('code' => 'success', 'format' => 'Update(s) succeeded.'),
1520 18 => array ('code' => 'success', 'format' => 'Load balancer was successfully added'),
1521 19 => array ('code' => 'success', 'format' => 'Load balancer was successfully deleted'),
1522 20 => array ('code' => 'success', 'format' => 'Load balancer info was successfully updated'),
1523 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1524 22 => array ('code' => 'success', 'format' => 'Chained %u tags'),
1525 23 => array ('code' => 'success', 'format' => 'IPv4 prefix successfully added'),
1526 24 => array ('code' => 'success', 'format' => 'IPv4 prefix deleted'),
1527 25 => array ('code' => 'success', 'format' => 'IPv4 prefix updated'),
1528 26 => array ('code' => 'success', 'format' => '%u IP address(es) were successfully updated'),
1529 27 => array ('code' => 'success', 'format' => 'IPv4 address updated'),
1530 28 => array ('code' => 'success', 'format' => 'Virtual service was successfully created'),
1531 29 => array ('code' => 'success', 'format' => 'Virtual service was successfully deleted'),
1532 30 => array ('code' => 'success', 'format' => 'Virtual service was successfully updated'),
1533 31 => array ('code' => 'success', 'format' => 'RS pool was successfully created'),
1534 32 => array ('code' => 'success', 'format' => 'RS pool was successfully deleted'),
1535 33 => array ('code' => 'success', 'format' => 'RS pool was successfully updated'),
1536 34 => array ('code' => 'success', 'format' => 'Real server was successfully added'),
1537 35 => array ('code' => 'success', 'format' => 'Real server was successfully deleted'),
1538 36 => array ('code' => 'success', 'format' => 'Real server was successfully updated'),
1539 37 => array ('code' => 'success', 'format' => 'Successfully added %u real servers'),
1540 38 => array ('code' => 'success', 'format' => '%u real server(s) were successfully (de)activated'),
1541 39 => array ('code' => 'success', 'format' => 'User account %s updated.'),
1542 40 => array ('code' => 'success', 'format' => 'User account %s created.'),
1543 41 => array ('code' => 'success', 'format' => 'uplink ports reverb queued'),
1544 // ...
1545 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1546 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1547 45 => array ('code' => 'success', 'format' => "Attribute '%s' created."),
1548 46 => array ('code' => 'success', 'format' => 'Rename successful.'),
1549 47 => array ('code' => 'success', 'format' => 'Attribute was deleted.'),
1550 48 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1551 49 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1552 50 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1553 51 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1554 52 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1555 53 => array ('code' => 'success', 'format' => 'Chapter was deleted.'),
1556 54 => array ('code' => 'success', 'format' => 'Chapter was updated.'),
1557 55 => array ('code' => 'success', 'format' => 'Chapter was added.'),
1558 56 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1559 57 => array ('code' => 'success', 'format' => 'Reset complete'),
1560 58 => array ('code' => 'success', 'format' => "Deleted tag '%s'."),
1561 59 => array ('code' => 'success', 'format' => "Created tag '%s'."),
1562 60 => array ('code' => 'success', 'format' => "Updated tag '%s'."),
1563 61 => array ('code' => 'success', 'format' => 'Password changed successfully.'),
1564 62 => array ('code' => 'success', 'format' => 'gw: %s'),
1565 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
1566 64 => array ('code' => 'success', 'format' => 'Port %s@%s has been assigned to VLAN %u'),
1567 65 => array ('code' => 'success', 'format' => "Added new rack '%s'"),
1568 66 => array ('code' => 'success', 'format' => "File sent Ok via handler '%s'"),
1569 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1570 68 => array ('code' => 'success', 'format' => "Updated rack '%s'"),
1571 69 => array ('code' => 'success', 'format' => 'File "%s" was added successfully'),
1572 70 => array ('code' => 'success', 'format' => 'File "%s" was updated successfully'),
1573 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
1574 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
1575 73 => array ('code' => 'success', 'format' => 'File "%s" was deleted successfully'),
1576 74 => array ('code' => 'success', 'format' => 'Row "%s" was added successfully'),
1577 75 => array ('code' => 'success', 'format' => 'Row "%s" was updated successfully'),
1578 76 => array ('code' => 'success', 'format' => 'Object "%s" was deleted successfully'),
1579 77 => array ('code' => 'success', 'format' => 'Row "%s" was deleted successfully'),
1580 78 => array ('code' => 'success', 'format' => 'File "%s" saved Ok'),
1581 79 => array ('code' => 'success', 'format' => 'Rack "%s" was deleted successfully'),
1582 80 => array ('code' => 'success', 'format' => "Added new object '%s'"),
1583 81 => array ('code' => 'success', 'format' => "SNMP: completed '%s' work"),
1584 82 => array ('code' => 'success', 'format' => "Bulk port creation was successful. %u ports created, %u failed"),
1585 // records 100~199 with fatal error messages
1586 100 => array ('code' => 'error', 'format' => '%s'),
1587 101 => array ('code' => 'error', 'format' => 'Port name cannot be empty'),
1588 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
1589 103 => array ('code' => 'error', 'format' => 'User not found!'),
1590 104 => array ('code' => 'error', 'format' => "Error updating user account '%s'"),
1591 // ...
1592 // ...
1593 // ...
1594 // ...
1595 109 => array ('code' => 'error', 'format' => 'Update failed!'),
1596 110 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1597 111 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1598 112 => array ('code' => 'error', 'format' => 'Error adding chapter.'),
1599 113 => array ('code' => 'error', 'format' => 'Error updating chapter.'),
1600 114 => array ('code' => 'error', 'format' => 'Error deleting chapter.'),
1601 115 => array ('code' => 'error', 'format' => 'Error renaming attribute.'),
1602 116 => array ('code' => 'error', 'format' => 'Error creating attribute.'),
1603 117 => array ('code' => 'error', 'format' => 'Error deleting attribute.'),
1604 118 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1605 119 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1606 120 => array ('code' => 'error', 'format' => 'Reset failed!'),
1607 121 => array ('code' => 'error', 'format' => 'commitUpdateObject() failed'),
1608 122 => array ('code' => 'error', 'format' => 'One or more update(s) failed!'),
1609 123 => array ('code' => 'error', 'format' => 'Cannot process submitted data: unknown format code.'),
1610 124 => array ('code' => 'error', 'format' => 'Error removing reservation!'),
1611 125 => array ('code' => 'error', 'format' => "Update failed with error: '%s'"),
1612 126 => array ('code' => 'error', 'format' => 'addRStoRSPool() failed'),
1613 127 => array ('code' => 'error', 'format' => 'Added %u real servers and encountered %u errors'),
1614 128 => array ('code' => 'error', 'format' => 'commitDeleteRS() failed'),
1615 129 => array ('code' => 'error', 'format' => 'commitDeleteLB() failed'),
1616 130 => array ('code' => 'error', 'format' => 'commitDeleteVS() failed'),
1617 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1618 132 => array ('code' => 'error', 'format' => 'invalid protocol'),
1619 133 => array ('code' => 'error', 'format' => 'commitUpdateRS() failed'),
1620 134 => array ('code' => 'error', 'format' => 'commitUpdateLB() failed'),
1621 135 => array ('code' => 'error', 'format' => 'commitUpdateVS() failed'),
1622 136 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1623 137 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1624 138 => array ('code' => 'error', 'format' => 'commitDeleteRSPool() failed'),
1625 139 => array ('code' => 'error', 'format' => 'commitUpdateRSPool() failed'),
1626 140 => array ('code' => 'error', 'format' => 'Encountered %u errors, (de)activated %u real servers'),
1627 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u record(s)'),
1628 142 => array ('code' => 'error', 'format' => 'executeAutoPorts() failed'),
1629 143 => array ('code' => 'error', 'format' => 'Tried chaining %u tags, but experienced %u errors.'),
1630 144 => array ('code' => 'error', 'format' => "Error deleting tag: '%s'"),
1631 145 => array ('code' => 'error', 'format' => "Invalid tag name '%s'"),
1632 // ...
1633 147 => array ('code' => 'error', 'format' => "Could not create tag '%s': %s"),
1634 148 => array ('code' => 'error', 'format' => "Could not update tag '%s': %s"),
1635 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1636 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1637 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1638 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1639 153 => array ('code' => 'error', 'format' => 'Password change failed.'),
1640 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1641 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1642 156 => array ('code' => 'error', 'format' => 'getSwitchVLANs() failed'),
1643 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
1644 158 => array ('code' => 'error', 'format' => 'Ignoring malformed record #%u in form submit'),
1645 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1646 160 => array ('code' => 'error', 'format' => 'Invalid arguments'),
1647 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1648 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
1649 163 => array ('code' => 'error', 'format' => 'Failed to get any response from queryGateway() or the gateway died'),
1650 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
1651 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1652 166 => array ('code' => 'error', 'format' => 'gw: %s'),
1653 167 => array ('code' => 'error', 'format' => 'Could not find port %s'),
1654 168 => array ('code' => 'error', 'format' => 'Port %s is a trunk'),
1655 169 => array ('code' => 'error', 'format' => 'Failed to configure %s, connector returned code %u'),
1656 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1657 171 => array ('code' => 'error', 'format' => "Failed creating rack '%s'. Already exists in this row?"),
1658 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1659 173 => array ('code' => 'error', 'format' => "Invalid IPv4 prefix '%s'"),
1660 174 => array ('code' => 'error', 'format' => 'Bad IPv4 address'),
1661 175 => array ('code' => 'error', 'format' => 'Invalid netmask'),
1662 176 => array ('code' => 'error', 'format' => 'This network already exists'),
1663 177 => array ('code' => 'error', 'format' => 'commitUpdateRack() failed'),
1664 178 => array ('code' => 'error', 'format' => 'file not found'),
1665 179 => array ('code' => 'error', 'format' => 'Expired form has been declined.'),
1666 180 => array ('code' => 'error', 'format' => 'Error saving file, all changes lost!'),
1667 181 => array ('code' => 'error', 'format' => "file uploads not allowed, change 'file_uploads' parameter in php.ini"),
1668 182 => array ('code' => 'error', 'format' => 'SQL query failed: %s'),
1669 183 => array ('code' => 'error', 'format' => "Tag id '%s' does not exist."),
1670 184 => array ('code' => 'error', 'format' => 'Submitted form is invalid at line %u'),
1671 185 => array ('code' => 'error', 'format' => "Failed to add object '%s'"),
1672 186 => array ('code' => 'error', 'format' => 'Incomplete form has been ignored. Cheers.'),
1673 187 => array ('code' => 'error', 'format' => "Internal error in function '%s'"),
1674 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1675 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
1676 190 => array ('code' => 'error', 'format' => "Invalid VLAN ID '%s'"),
1677 191 => array ('code' => 'error', 'format' => "deploy was blocked due to conflicting configuration versions"),
1678 192 => array ('code' => 'error', 'format' => "You have to supply all the information for the bulk port function to be successful."),
1679
1680 // records 200~299 with warnings
1681 200 => array ('code' => 'warning', 'format' => '%s'),
1682 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1683 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
1684 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1685 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1686 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
1687 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
1688 207 => array ('code' => 'warning', 'format' => 'Ignored empty request'),
1689
1690 // records 300~399 with notices
1691 300 => array ('code' => 'neutral', 'format' => '%s'),
1692
1693 );
1694 // Handle the arguments. Is there any better way to do it?
1695 foreach ($log['m'] as $record)
1696 {
1697 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1698 {
1699 echo '<div class=msg_neutral>(this message was lost)</div>';
1700 continue;
1701 }
1702 if (isset ($record['a']))
1703 switch (count ($record['a']))
1704 {
1705 case 1:
1706 $msgtext = sprintf
1707 (
1708 $msginfo[$record['c']]['format'],
1709 $record['a'][0]
1710 );
1711 break;
1712 case 2:
1713 $msgtext = sprintf
1714 (
1715 $msginfo[$record['c']]['format'],
1716 $record['a'][0],
1717 $record['a'][1]
1718 );
1719 break;
1720 case 3:
1721 $msgtext = sprintf
1722 (
1723 $msginfo[$record['c']]['format'],
1724 $record['a'][0],
1725 $record['a'][1],
1726 $record['a'][2]
1727 );
1728 break;
1729 case 4:
1730 default:
1731 $msgtext = sprintf
1732 (
1733 $msginfo[$record['c']]['format'],
1734 $record['a'][0],
1735 $record['a'][1],
1736 $record['a'][2],
1737 $record['a'][3]
1738 );
1739 break;
1740 }
1741 else
1742 $msgtext = $msginfo[$record['c']]['format'];
1743 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1744 }
1745 break;
1746 default:
1747 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1748 break;
1749 }
1750 unset($_SESSION['log']);
1751 }
1752
1753 /*
1754 The following conditions must be followed:
1755 1. We can mount onto free atoms only. This means: if any record for an atom
1756 already exists in RackSpace, it can't be used for mounting.
1757 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1758 and either delete them before unmounting or refuse to unmount the object.
1759 */
1760
1761 // We extensively use $_REQUEST in the function.
1762 function renderRackSpaceForObject ($object_id)
1763 {
1764 $is_update = isset ($_REQUEST['rackmulti'][0]);
1765 $info = spotEntity ('object', $object_id);
1766 // Always process occupied racks plus racks chosen by user. First get racks with
1767 // already allocated rackspace...
1768 if (NULL === ($workingRacksData = getResidentRacksData ($object_id)))
1769 die; // some error already shown
1770
1771 // ...and then add those chosen by user (if any).
1772 if (isset($_REQUEST['rackmulti']))
1773 foreach ($_REQUEST['rackmulti'] as $cand_id)
1774 {
1775 if (!isset ($workingRacksData[$cand_id]))
1776 {
1777 $rackData = spotEntity ('rack', $cand_id);
1778 amplifyCell ($rackData);
1779 $workingRacksData[$cand_id] = $rackData;
1780 }
1781 }
1782
1783 printOpFormIntro ('updateObjectAllocation');
1784
1785 // Do it only once...
1786 foreach ($workingRacksData as $rackId => &$rackData)
1787 {
1788 applyObjectMountMask ($rackData, $object_id);
1789 echo "<input type=\"hidden\" name=\"rackmulti[]\" value=\"$rackId\">";
1790 }
1791 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1792 unset ($rackData);
1793
1794 // This is the time for rendering.
1795
1796 // Main layout starts.
1797 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1798
1799 // Left portlet with rack list.
1800 echo "<td class=pcleft height='1%'>";
1801 startPortlet ('Racks');
1802 $allRacksData = listCells ('rack');
1803 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1804 {
1805 foreach ($allRacksData as $rack)
1806 {
1807 amplifyCell ($rack);
1808 $workingRacksData[$rack['id']] = $rack;
1809 }
1810 foreach ($workingRacksData as &$rackData)
1811 applyObjectMountMask ($rackData, $object_id);
1812 unset ($rackData);
1813 }
1814 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1815 echo "<br>";
1816 echo "<br>";
1817 finishPortlet();
1818 echo "</td>";
1819
1820 // Middle portlet with comment and submit.
1821 echo "<td class=pcleft>";
1822 startPortlet ('Comment');
1823 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1824 echo "<input type=submit value='Save' name=got_atoms>\n";
1825 echo "<br>";
1826 echo "<br>";
1827 finishPortlet();
1828 echo "</td>";
1829
1830 // Right portlet with rendered racks. If this form submit is not final, we have to
1831 // reflect the former state of the grid in current form.
1832 echo "<td class=pcright rowspan=2 height='1%'>";
1833 startPortlet ('Working copy');
1834 echo '<table border=0 cellspacing=10 align=center><tr>';
1835 foreach ($workingRacksData as $rack_id => $rackData)
1836 {
1837 // Order is important here: only original allocation is highlighted.
1838 highlightObject ($rackData, $object_id);
1839 markupAtomGrid ($rackData, 'T');
1840 // If we have a form processed, discard user input and show new database
1841 // contents.
1842 if ($is_update)
1843 mergeGridFormToRack ($rackData);
1844 echo "<td valign=top>";
1845 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1846 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1847 echo "<tr><th width='10%'>&nbsp;</th>";
1848 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1849 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1850 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1851 renderAtomGrid ($rackData);
1852 echo "<tr><th width='10%'>&nbsp;</th>";
1853 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1854 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1855 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1856 echo "</table></center>\n";
1857 echo '</td>';
1858 }
1859 echo "</tr></table>";
1860 finishPortlet();
1861 echo "</td>\n";
1862
1863
1864 echo "</form>\n";
1865 echo "</tr></table>\n";
1866 }
1867
1868 function renderMolecule ($mdata, $object_id)
1869 {
1870 // sort data out
1871 $rackpack = array();
1872 global $loclist;
1873 foreach ($mdata as $rua)
1874 {
1875 $rack_id = $rua['rack_id'];
1876 $unit_no = $rua['unit_no'];
1877 $atom = $rua['atom'];
1878 if (!isset ($rackpack[$rack_id]))
1879 {
1880 $rackData = spotEntity ('rack', $rack_id);
1881 amplifyCell ($rackData);
1882 for ($i = $rackData['height']; $i > 0; $i--)
1883 for ($locidx = 0; $locidx < 3; $locidx++)
1884 $rackData[$i][$locidx]['state'] = 'F';
1885 $rackpack[$rack_id] = $rackData;
1886 }
1887 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1888 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1889 }
1890 // now we have some racks to render
1891 foreach ($rackpack as $rackData)
1892 {
1893 markAllSpans ($rackData);
1894 echo "<table class=molecule cellspacing=0>\n";
1895 echo "<caption>${rackData['name']}</caption>\n";
1896 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1897 for ($i = $rackData['height']; $i > 0; $i--)
1898 {
1899 echo "<tr><th>$i</th>";
1900 for ($locidx = 0; $locidx < 3; $locidx++)
1901 {
1902 $state = $rackData[$i][$locidx]['state'];
1903 echo "<td class=state_${state}>&nbsp;</td>\n";
1904 }
1905 echo "</tr>\n";
1906 }
1907 echo "</table>\n";
1908 }
1909 }
1910
1911 function renderDepot ()
1912 {
1913 global $pageno, $nextorder;
1914 $cellfilter = getCellFilter();
1915 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
1916
1917 echo "<table border=0 class=objectview>\n";
1918 echo "<tr><td class=pcleft>";
1919
1920 startPortlet ('Objects (' . count ($objects) . ')');
1921 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1922 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Row/Rack</th></tr>';
1923 $order = 'odd';
1924 foreach ($objects as $obj)
1925 {
1926 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1927 $secondclass = 'tdleft port_highlight';
1928 else
1929 $secondclass = 'tdleft';
1930 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>";
1931 if (count ($obj['etags']))
1932 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
1933 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
1934 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
1935 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
1936 if ($obj['rack_id'])
1937 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>";
1938 else
1939 echo "<td class='${secondclass}'>Unmounted</td>";
1940 echo '</tr>';
1941 $order = $nextorder[$order];
1942 }
1943 echo '</table>';
1944 finishPortlet();
1945
1946 echo "</td><td class=pcright width='25%'>";
1947
1948 renderCellFilterPortlet ($cellfilter, 'object');
1949 echo "</td></tr></table>\n";
1950 }
1951
1952 // History viewer for history-enabled simple dictionaries.
1953 function renderHistory ($object_type, $object_id)
1954 {
1955 switch ($object_type)
1956 {
1957 case 'row':
1958 $query = "select ctime, user_name, name, comment from RackRowHistory where id = ${object_id} order by ctime";
1959 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>rack row comment</th></tr>';
1960 $extra = 3;
1961 break;
1962 case 'rack':
1963 $query =
1964 "select ctime, user_name, rh.name, rr.name as name, rh.height, rh.comment " .
1965 "from RackHistory as rh left join RackRow as rr on rh.row_id = rr.id " .
1966 "where rh.id = ${object_id} order by ctime";
1967 $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>';
1968 $extra = 5;
1969 break;
1970 case 'object':
1971 $query =
1972 "select ctime, user_name, RackObjectHistory.name as name, label, barcode, asset_no, has_problems, dict_value, comment " .
1973 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key join Chapter on Dictionary.chapter_id = Chapter.id " .
1974 "where Chapter.name = 'RackObjectType' and RackObjectHistory.id=${object_id} order by ctime";
1975 $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>';
1976 $extra = 8;
1977 break;
1978 default:
1979 throw new RealmNotFoundException($object_type);
1980 }
1981 global $dbxlink;
1982 $result = $dbxlink->query ($query);
1983 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1984 $order = 'odd';
1985 global $nextorder;
1986 echo $header;
1987 while ($row = $result->fetch (PDO::FETCH_NUM))
1988 {
1989 echo "<tr class=row_${order}><td>${row[0]}</td>";
1990 for ($i = 1; $i <= $extra; $i++)
1991 echo "<td>" . $row[$i] . "</td>";
1992 echo "</tr>\n";
1993 $order = $nextorder[$order];
1994 }
1995 echo "</table><br>\n";
1996 }
1997
1998 function renderRackspaceHistory ()
1999 {
2000 global $nextorder, $pageno, $tabno;
2001 $order = 'odd';
2002 $history = getRackspaceHistory();
2003 // Show the last operation by default.
2004 if (isset ($_REQUEST['op_id']))
2005 $op_id = $_REQUEST['op_id'];
2006 elseif (isset ($history[0]['mo_id']))
2007 $op_id = $history[0]['mo_id'];
2008 else $op_id = NULL;
2009
2010 $omid = NULL;
2011 $nmid = NULL;
2012 $object_id = 1;
2013 if ($op_id)
2014 list ($omid, $nmid) = getOperationMolecules ($op_id);
2015
2016 // Main layout starts.
2017 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2018
2019 // Left top portlet with old allocation.
2020 echo "<tr><td class=pcleft>";
2021 startPortlet ('Old allocation');
2022 if ($omid)
2023 {
2024 $oldMolecule = getMolecule ($omid);
2025 renderMolecule ($oldMolecule, $object_id);
2026 }
2027 else
2028 echo "nothing";
2029 finishPortlet();
2030
2031 echo '</td><td class=pcright>';
2032
2033 // Right top portlet with new allocation
2034 startPortlet ('New allocation');
2035 if ($nmid)
2036 {
2037 $newMolecule = getMolecule ($nmid);
2038 renderMolecule ($newMolecule, $object_id);
2039 }
2040 else
2041 echo "nothing";
2042 finishPortlet();
2043
2044 echo '</td></tr><tr><td colspan=2>';
2045
2046 // Bottom portlet with list
2047
2048 startPortlet ('Rackspace allocation history');
2049 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
2050 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
2051 foreach ($history as $row)
2052 {
2053 if ($row['mo_id'] == $op_id)
2054 $class = 'hl';
2055 else
2056 $class = "row_${order}";
2057 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
2058 echo "<td>${row['user_name']}</td><td>";
2059 renderCell (spotEntity ('object', $row['ro_id']));
2060 echo "</td><td>${row['comment']}</td>\n";
2061 echo "</tr>\n";
2062 $order = $nextorder[$order];
2063 }
2064 echo "</table>\n";
2065 finishPortlet();
2066
2067 echo '</td></tr></table>';
2068 }
2069
2070 function renderIPv4SpaceRecords ($tree, $baseurl, $target = 0, $level = 1)
2071 {
2072 $self = __FUNCTION__;
2073 static $vdomlist = NULL;
2074 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2075 $vdomlist = getVLANDomainList();
2076 foreach ($tree as $item)
2077 {
2078 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2079 loadIPv4AddrList ($item); // necessary to compute router list and address counter
2080 else
2081 {
2082 $item['addrlist'] = array();
2083 $item['addrc'] = 0;
2084 }
2085 $used = $item['addrc'];
2086 $maxdirect = $item['addrt'];
2087 $maxtotal = binInvMaskFromDec ($item['mask']) + 1;
2088 if (isset ($item['id']))
2089 {
2090 if ($item['symbol'] == 'node-collapsed')
2091 $expandurl = "${baseurl}&eid=" . $item['id'] . "#netid" . $item['id'];
2092 elseif ($item['symbol'] == 'node-expanded')
2093 $expandurl = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#netid${item['parent_id']}" : '');
2094 else
2095 $expandurl = '';
2096 echo "<tr valign=top>";
2097 printIPv4NetInfoTDs ($item, 'tdleft', $level, $item['symbol'], $expandurl);
2098 echo "<td class=tdcenter>";
2099 if ($target == $item['id'])
2100 echo "<a name=netid${target}></a>";
2101 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2102 {
2103 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2104 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small>';
2105 }
2106 else
2107 echo "<small>${maxdirect}</small>";
2108 echo "</td>";
2109 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2110 {
2111 echo '<td class=tdleft>';
2112 if (count ($item['8021q']))
2113 {
2114 echo '<ul>';
2115 foreach ($item['8021q'] as $binding)
2116 {
2117 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
2118 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']]['description'], 15) . '</a></li>';
2119 }
2120 echo '</ul>';
2121 }
2122 echo '</td>';
2123 }
2124 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2125 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
2126 echo "</tr>";
2127 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2128 $self ($item['kids'], $baseurl, $target, $level + 1);
2129 }
2130 else
2131 {
2132 echo "<tr valign=top>";
2133 printIPv4NetInfoTDs ($item, 'tdleft sparenetwork', $level, $item['symbol']);
2134 echo "<td class=tdcenter>";
2135 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2136 {
2137 renderProgressBar ($used/$maxtotal, 'sparenetwork');
2138 echo "<br><small>${used}/${maxtotal}</small>";
2139 }
2140 else
2141 echo "<small>${maxtotal}</small>";
2142 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2143 echo '</td><td>&nbsp;</td>';
2144 echo "</td><td>&nbsp;</td></tr>";
2145 }
2146 }
2147 }
2148
2149 function renderIPv4Space ()
2150 {
2151 global $pageno, $tabno;
2152 $cellfilter = getCellFilter();
2153 $netlist = filterCellList (listCells ('ipv4net'), $cellfilter['expression']);
2154 array_walk ($netlist, 'amplifyCell');
2155
2156 $netcount = count ($netlist);
2157 // expand request can take either natural values or "ALL". Zero means no expanding.
2158 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2159 $tree = prepareIPv4Tree ($netlist, $eid);
2160
2161 echo "<table border=0 class=objectview>\n";
2162 echo "<tr><td class=pcleft>";
2163 startPortlet ("networks (${netcount})");
2164 echo '<h4>';
2165 if ($eid === 0)
2166 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2167 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2168 $cellfilter['urlextra'] . "'>expand all</a>)";
2169 elseif ($eid === 'ALL')
2170 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2171 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2172 else
2173 {
2174 $netinfo = spotEntity ('ipv4net', $eid);
2175 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2176 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2177 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2178 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2179 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2180 }
2181 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2182 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2183 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2184 echo '<th>VLAN</th>';
2185 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2186 echo "<th>routed by</th>";
2187 echo "</tr>\n";
2188 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2189 renderIPv4SpaceRecords ($tree, $baseurl, $eid);
2190 echo "</table>\n";
2191 finishPortlet();
2192 echo '</td><td class=pcright>';
2193 renderCellFilterPortlet ($cellfilter, 'ipv4net');
2194 echo "</td></tr></table>\n";
2195 }
2196
2197 function renderIPv4SLB ()
2198 {
2199 global $page, $nextorder;
2200
2201 startPortlet ('SLB configuration');
2202 echo "<table border=0 width='100%'><tr>";
2203 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2204 echo "<td><h3><a href='".makeHref(array('page'=>$pno))."'>" . $page[$pno]['title'] . "</a></h3></td>";
2205 echo '</tr></table>';
2206 finishPortlet();
2207
2208 $summary = getSLBSummary();
2209 startPortlet ('SLB tactical overview');
2210 // A single id-keyed array isn't used here to preserve existing
2211 // order of LBs returned by getSLBSummary()
2212 $lblist = array();
2213 $lbdname = array();
2214 foreach ($summary as $vipdata)
2215 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2216 if (!in_array ($lb_object_id, $lblist))
2217 {
2218 $oi = spotEntity ('object', $lb_object_id);
2219 $lbdname[$lb_object_id] = $oi['dname'];
2220 $lblist[] = $lb_object_id;
2221 }
2222 if (!count ($summary))
2223 echo 'none configured';
2224 else
2225 {
2226 $order = 'odd';
2227 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2228 echo "<tr valign=top><td>&nbsp;</td>";
2229 foreach ($lblist as $lb_object_id)
2230 {
2231 #echo "<th><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$lb_object_id))."'>" . $lbdname[$lb_object_id] . "</a></th>";
2232 echo '<td>';
2233 renderLBCell ($lb_object_id);
2234 echo '</td>';
2235 }
2236 echo "</tr>\n";
2237 foreach ($summary as $vsid => $vsdata)
2238 {
2239 echo "<tr class=row_${order}><td class=tdleft>";
2240 renderCell (spotEntity ('ipv4vs', $vsid));
2241 echo "</td>";
2242 foreach ($lblist as $lb_object_id)
2243 {
2244 echo '<td class=tdleft>';
2245 if (!isset ($vsdata['lblist'][$lb_object_id]))
2246 echo '&nbsp;';
2247 else
2248 {
2249 echo $vsdata['lblist'][$lb_object_id]['size'];
2250 // echo " (<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$vsdata['lblist'][$lb_object_id]['id'])). "'>";
2251 // echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2252 }
2253 echo '</td>';
2254 }
2255 echo "</tr>\n";
2256 $order = $nextorder[$order];
2257 }
2258 echo "</table>\n";
2259 }
2260 finishPortlet ();
2261 }
2262
2263 function renderIPv4SpaceEditor ()
2264 {
2265 // IPv4 validator
2266 ?>
2267 <script type="text/javascript">
2268 function init() {
2269 document.add_new_range.range.setAttribute('match', "^\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\/\\d\\d?$");
2270
2271 Validate.init();
2272 }
2273 window.onload=init;
2274 </script>
2275 <?php
2276
2277 function printNewItemTR ()
2278 {
2279 startPortlet ('Add new');
2280 echo '<table border=0 cellpadding=10 align=center>';
2281 // This form requires a name, so JavaScript validator can find it.
2282 // No printOpFormIntro() hence
2283 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2284 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2285 // tags column
2286 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2287 renderNewEntityTags ('ipv4net');
2288 echo '</td>';
2289 // inputs column
2290 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2291 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>";
2292 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2293 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2294 echo "<tr><td colspan=2>";
2295 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2296 echo '</td></tr>';
2297 echo "</form></table><br><br>\n";
2298 finishPortlet();
2299 }
2300
2301 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2302 printNewItemTR();
2303 if (count ($addrspaceList = listCells ('ipv4net')))
2304 {
2305 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2306 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2307 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
2308 array_walk ($addrspaceList, 'amplifyCell');
2309 $tree = prepareIPv4Tree ($addrspaceList, 'ALL');
2310 // this is only called for having "trace" set
2311 treeFromList ($addrspaceList);
2312 foreach ($addrspaceList as $netinfo)
2313 {
2314 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2315 // now we have all subnets listed in netinfo
2316 loadIPv4AddrList ($netinfo);
2317 $used = $netinfo['addrc'];
2318 $maxdirect = $netinfo['addrt'];
2319 $maxtotal = binInvMaskFromDec ($netinfo['mask']) + 1;
2320 echo "<tr valign=top><td>";
2321 if (getConfigVar ('IPV4_JAYWALK') == 'yes')
2322 {
2323 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2324 printImageHREF ('destroy', 'Delete this prefix');
2325 echo "</a>";
2326 }
2327 else // only render clickable image for empty networks
2328 {
2329 if (count ($netinfo['addrlist']))
2330 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2331 else
2332 {
2333 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2334 printImageHREF ('destroy', 'Delete this prefix');
2335 echo "</a>";
2336 }
2337
2338 }
2339 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv4net', 'id' => $netinfo['id'])) . '">';
2340 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
2341 echo '<td class=tdleft>' . htmlspecialchars ($netinfo['name']) . '</td><td>';
2342 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2343 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small></td>';
2344 echo '</tr>';
2345 }
2346 echo "</table>";
2347 finishPortlet();
2348 }
2349 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2350 printNewItemTR();
2351 }
2352
2353 function renderIPv4Network ($id)
2354 {
2355 global $pageno, $tabno, $aac2, $netmaskbylen, $wildcardbylen;
2356 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2357 if (isset($_REQUEST['pg']))
2358 $page = $_REQUEST['pg'];
2359 else
2360 $page=0;
2361
2362 $range = spotEntity ('ipv4net', $id);
2363 amplifyCell ($range);
2364 loadIPv4AddrList ($range);
2365 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2366 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2367 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2368
2369 echo "<tr><td class=pcleft width='50%'>";
2370 startPortlet ('summary');
2371 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2372 $used = count ($range['addrlist']);
2373 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2374
2375 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2376 renderProgressBar ($used/$total);
2377 echo "&nbsp;${used}/${total}</td></tr>\n";
2378
2379 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2380 {
2381 // Build a backtrace from all parent networks.
2382 $clen = $range['mask'];
2383 $backtrace = array();
2384 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2385 {
2386 $upperinfo = spotEntity ('ipv4net', $upperid);
2387 $clen = $upperinfo['mask'];
2388 $backtrace[] = $upperinfo;
2389 }
2390 $arrows = count ($backtrace);
2391 foreach (array_reverse ($backtrace) as $ainfo)
2392 {
2393 echo "<tr><th width='50%' class=tdright>";
2394 for ($i = 0; $i < $arrows; $i++)
2395 echo '&uarr;';
2396 $arrows--;
2397 echo "</th><td class=tdleft>";
2398 renderCell ($ainfo);
2399 echo "</td></tr>";
2400 }
2401 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
2402 echo "<td class=tdleft>";
2403 renderCell ($range);
2404 echo "</td></tr>";
2405 // FIXME: get and display nested networks
2406 // $theitem = pickLeaf ($ipv4tree, $id);
2407 }
2408
2409 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2410 echo $netmaskbylen[$range['mask']];
2411 echo "</td></tr>\n";
2412
2413 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2414 printf ('0x%08X', binMaskFromDec ($range['mask']));
2415 echo "</td></tr>\n";
2416
2417 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2418 echo $wildcardbylen[$range['mask']];
2419 echo "</td></tr>\n";
2420
2421 foreach ($range['8021q'] as $item)
2422 {
2423 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
2424 echo '<tr><th width="50%" class=tdright>VLAN:</th><td class=tdleft><a href="';
2425 echo makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">';
2426 echo formatVLANName ($vlaninfo, 'markup long');
2427 echo '</a></td></tr>';
2428 }
2429 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
2430 {
2431 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2432 printRoutersTD ($routers);
2433 echo "</tr>\n";
2434 }
2435
2436 printTagTRs ($range, makeHref(array('page'=>'ipv4space', 'tab'=>'default'))."&");
2437 echo "</table><br>\n";
2438 finishPortlet();
2439
2440 if (strlen ($range['comment']))
2441 {
2442 startPortlet ('Comment');
2443 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2444 finishPortlet ();
2445 }
2446
2447 renderFilesPortlet ('ipv4net', $id);
2448 echo "</td>\n";
2449
2450 echo "<td class=pcright>";
2451 startPortlet ('details');
2452 $startip = $range['ip_bin'] & $range['mask_bin'];
2453 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2454 $realstartip = $startip;
2455 $realendip = $endip;
2456 $numpages = 0;
2457 if($endip - $startip > $maxperpage)
2458 {
2459 $numpages = ($endip - $startip)/$maxperpage;
2460 $startip = $startip + $page * $maxperpage;
2461 $endip = $startip + $maxperpage-1;
2462 }
2463 echo "<center>";
2464 if ($numpages)
2465 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2466 for ($i=0; $i<$numpages; $i++)
2467 {
2468 if ($i == $page)
2469 echo "<b>$i</b> ";
2470 else
2471 echo "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'id'=>$id, 'pg'=>$i))."'>$i</a> ";
2472 }
2473 echo "</center>";
2474
2475 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2476 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2477
2478
2479 for ($ip = $startip; $ip <= $endip; $ip++) :
2480 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2481 $secondstyle = 'tdleft port_highlight';
2482 else
2483 $secondstyle = 'tdleft';
2484 if (!isset ($range['addrlist'][$ip]))
2485 {
2486 echo "<tr><td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>ip_long2quad($ip)))."'>" . ip_long2quad($ip);
2487 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2488 continue;
2489 }
2490 $addr = $range['addrlist'][$ip];
2491 echo "<tr class='${addr['class']}'>";
2492
2493 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
2494 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2495 $delim = '';
2496 $prologue = '';
2497 if ( $addr['reserved'] == 'yes')
2498 {
2499 echo "<strong>RESERVED</strong> ";
2500 $delim = '; ';
2501 }
2502 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2503 {
2504 echo $delim . $aac2[$ref['type']];
2505 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'hl_ipv4_addr'=>$addr['ip']))."'>";
2506 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
2507 echo "${ref['object_name']}</a>";
2508 $delim = '; ';
2509 }
2510 if ($delim != '')
2511 {
2512 $delim = '';
2513 $prologue = '<br>';
2514 }
2515 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2516 {
2517 echo $prologue;
2518 $prologue = '';
2519 echo "${delim}<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id']))."'>";
2520 echo "${ref['object_name']}</a>:<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$ref['vs_id']))."'>";
2521 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2522 $delim = '; ';
2523 }
2524 if ($delim != '')
2525 {
2526 $delim = '';
2527 $prologue = '<br>';
2528 }
2529 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2530 {
2531 echo $prologue;
2532 $prologue = '';
2533 echo "${delim}&rarr;${ref['rsport']}@<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$ref['rspool_id']))."'>";
2534 echo "${ref['rspool_name']}</a>";
2535 $delim = '; ';
2536 }
2537 echo "</td></tr>\n";
2538 endfor;
2539 // end of iteration
2540
2541 echo "</table>";
2542 finishPortlet();
2543 echo "</td></tr></table>\n";
2544 }
2545
2546 function renderIPv4NetworkProperties ($id)
2547 {
2548 $netdata = spotEntity ('ipv4net', $id);
2549 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
2550 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2551 printOpFormIntro ('editRange');
2552 echo '<tr><td class=tdright><label for=nameinput>Name:</label></td>';
2553 echo "<td class=tdleft><input type=text name=name id=nameinput size=80 maxlength=255 value='";
2554 echo htmlspecialchars ($netdata['name'], ENT_QUOTES, 'UTF-8') . "'></tr>";
2555 echo '<tr><td class=tdright><label for=commentinput>Comment:</label></td>';
2556 echo "<td class=tdleft><textarea name=comment id=commentinput cols=80 rows=25>\n";
2557 echo htmlspecialchars ($netdata['comment'], ENT_QUOTES, 'UTF-8') . "</textarea></tr>";
2558 echo "<tr><td colspan=2 class=tdcenter>";
2559 printImageHREF ('SAVE', 'Save changes', TRUE);
2560 echo "</td></form></tr></table>\n";
2561 }
2562
2563 function renderIPv4Address ($dottedquad)
2564 {
2565 global $aat, $nextorder;
2566 $address = getIPv4Address ($dottedquad);
2567 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2568 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2569
2570 echo "<tr><td class=pcleft>";
2571 startPortlet ('summary');
2572 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2573 if (strlen ($address['name']))
2574 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${address['name']}</td></tr>";
2575 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
2576 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2577 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2578 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
2579 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2580 echo "</table><br>\n";
2581 finishPortlet();
2582 echo "</td>\n";
2583
2584 echo "<td class=pcright>";
2585
2586 if (isset ($address['class']))
2587 {
2588 startPortlet ('allocations');
2589 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2590 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2591 $class = $address['class'];
2592 // render all allocation records for this address the same way
2593 if ($address['reserved'] == 'yes')
2594 echo "<tr class='${class}'><td colspan=2>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td></tr>";
2595 foreach ($address['allocs'] as $bond)
2596 {
2597 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2598 $secondclass = 'tdleft port_highlight';
2599 else
2600 $secondclass = 'tdleft';
2601 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>";
2602 echo $aat[$bond['type']];
2603 echo "</strong></td></tr>\n";
2604 }
2605 echo "</table><br><br>";
2606 finishPortlet();
2607 }
2608
2609 // FIXME: The returned list is structured differently, than we expect it to be. One of the sides
2610 // must be fixed.
2611 if (count ($address['lblist']))
2612 {
2613 startPortlet ('Virtual services (' . count ($address['lblist']) . ')');
2614 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2615 echo "<tr><th>VS</th><th>LB</th></tr>\n";
2616 $order = 'odd';
2617 foreach ($address['lblist'] as $vsinfo)
2618 {
2619 echo "<tr valign=top class=row_${order}><td class=tdleft>";
2620 renderCell (spotEntity ('ipv4vs', $vsinfo['vs_id']));
2621 echo "</td><td class=tdleft>";
2622 renderLBCell ($vsinfo['object_id']);
2623 echo "</td></tr>";
2624 $order = $nextorder[$order];
2625 }
2626 echo "</table><br><br>";
2627 finishPortlet();
2628 }
2629
2630 if (count ($address['rslist']))
2631 {
2632 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2633 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2634 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
2635 foreach ($address['rslist'] as $rsinfo)
2636 {
2637 echo "<tr><td>";
2638 if ($rsinfo['inservice'] == 'yes')
2639 printImageHREF ('inservice', 'in service');
2640 else
2641 printImageHREF ('notinservice', 'NOT in service');
2642 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$rsinfo['rspool_id']))."'>";
2643 echo $rsinfo['rspool_name'] . "</a></td></tr>\n";
2644 }
2645 echo "</table><br><br>";
2646 finishPortlet();
2647 }
2648
2649 if (count ($address['outpf']))
2650 {
2651 startPortlet ('departing NAT rules');
2652 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2653 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2654 foreach ($address['outpf'] as $rule)
2655 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2656 echo "</table>";
2657 finishPortlet();
2658 }
2659
2660 if (count ($address['inpf']))
2661 {
2662 startPortlet ('arriving NAT rules');
2663 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2664 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2665 foreach ($address['inpf'] as $rule)
2666 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2667 echo "</table>";
2668 finishPortlet();
2669 }
2670
2671 echo "</td></tr>";
2672 echo "</table>\n";
2673 }
2674
2675 function renderIPv4AddressProperties ($dottedquad)
2676 {
2677 $address = getIPv4Address ($dottedquad);
2678 echo "<center><h1>$dottedquad</h1></center>\n";
2679
2680 startPortlet ('update');
2681 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2682 printOpFormIntro ('editAddress');
2683 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2684 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2685 echo ($address['reserved']=='yes') ? 'checked' : '';
2686 echo "></tr><tr><td class=tdleft>";
2687 printImageHREF ('SAVE', 'Save changes', TRUE);
2688 echo "</td></form><td class=tdright>";
2689 if (!strlen ($address['name']) and $address['reserved'] == 'no')
2690 printImageHREF ('CLEAR gray');
2691 else
2692 {
2693 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2694 printImageHREF ('CLEAR', 'Release', TRUE);
2695 echo "</form>";
2696 }
2697 echo "</td></tr></table>\n";
2698 finishPortlet();
2699 }
2700
2701 function renderIPv4AddressAllocations ($dottedquad)
2702 {
2703 function printNewItemTR ()
2704 {
2705 global $aat;
2706 printOpFormIntro ('addIPv4Allocation');
2707 echo "<tr><td>";
2708 printImageHREF ('add', 'allocate', TRUE);
2709 echo "</td><td>";
2710 printSelect (getNarrowObjectList ('IPV4OBJ_LISTSRC'), array ('name' => 'object_id', 'tabindex' => 100, 'id' => 'object_id'), Null, true);
2711 echo "</td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
2712 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102, 'regular'));
2713 echo "</td><td>";
2714 printImageHREF ('add', 'allocate', TRUE, 103);
2715 echo "</td></form></tr>";
2716 }
2717 global $aat;
2718
2719 $address = getIPv4Address ($dottedquad);
2720
2721 echo "<center><h1>${dottedquad}</h1></center>\n";
2722 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2723 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
2724
2725 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2726 printNewItemTR();
2727 if (isset ($address['class']))
2728 {
2729 $class = $address['class'];
2730 if ($address['reserved'] == 'yes')
2731 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2732 foreach ($address['allocs'] as $bond)
2733 {
2734 echo "<tr class='$class'>";
2735 printOpFormIntro ('updIPv4Allocation', array ('object_id' => $bond['object_id']));
2736 echo "<td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$bond['object_id']))."'>";
2737 printImageHREF ('delete', 'Unallocate address');
2738 echo "</a></td>";
2739 echo "<td><a href='".makeHref(array('page'=>'object', 'object_id'=>$bond['object_id'], 'hl_ipv4_addr'=>$dottedquad))."'>${bond['object_name']}</td>";
2740 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
2741 printSelect ($aat, array ('name' => 'bond_type'), $bond['type']);
2742 echo "</td><td>";
2743 printImageHREF ('save', 'Save changes', TRUE);
2744 echo "</td></form></tr>\n";
2745 }
2746 }
2747 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2748 printNewItemTR();
2749 echo "</table><br><br>";
2750 }
2751
2752 function renderNATv4ForObject ($object_id)
2753 {
2754 function printNewItemTR ($alloclist)
2755 {
2756 printOpFormIntro ('addNATv4Rule');
2757 echo "<tr align='center'><td>";
2758 printImageHREF ('add', 'Add new NAT rule', TRUE);
2759 echo '</td><td>';
2760 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), array ('name' => 'proto'));
2761 echo "<select name='localip' tabindex=1>";
2762
2763 foreach ($alloclist as $dottedquad => $alloc)
2764 {
2765 $name = (!isset ($alloc['addrinfo']['name']) or !strlen ($alloc['addrinfo']['name'])) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2766 $osif = (!isset ($alloc['osif']) or !strlen ($alloc['osif'])) ? '' : ($alloc['osif'] . ': ');
2767 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
2768 }
2769
2770 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2771 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2772 echo "<a href='javascript:;' onclick='window.open(\"" . makeHrefForHelper ('inet4list');
2773 echo "\", \"findobjectip\", \"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
2774 printImageHREF ('find', 'Find object');
2775 echo "</a>";
2776 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2777 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
2778 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
2779 echo "</td></tr></form>";
2780 }
2781
2782 $focus = spotEntity ('object', $object_id);
2783 amplifyCell ($focus);
2784 echo "<center><h2>locally performed NAT</h2></center>";
2785
2786 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2787 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
2788
2789 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2790 printNewItemTR ($focus['ipv4']);
2791 foreach ($focus['nat4']['out'] as $pf)
2792 {
2793 $class = 'trerror';
2794 $osif = '';
2795 if (isset ($focus['ipv4'][$pf['localip']]))
2796 {
2797 $class = $focus['ipv4'][$pf['localip']]['addrinfo']['class'];
2798 $osif = $focus['ipv4&apos