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