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