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