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