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