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