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