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