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