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