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