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