r2370 make 'Delete object' link available only on Object->Properties page
[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><th class=tdright>Actions:</th><td class=tdleft><a href='${root}process.php?op=deleteObject&page=objects&tab=default&object_id=${object_id}&name=${object['name']}' onclick=\"javascript:return confirm('Are you sure you want to delete the object?')\">Delete object</a></td></tr>\n";
519 echo "<tr><td colspan=2><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
520 echo '</table>';
521
522 echo '</td><td class=pcright>';
523
524 // optional attributes
525 $values = getAttrValues ($object_id);
526 if (count($values) > 0)
527 {
528 echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
529 echo "<tr><th colspan=3><h2>Optional attributes</h2></th></tr>";
530 echo "<tr><th>&nbsp;</th><th>Attribute</th><th>Value</th></tr>\n";
531 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
532 $i = 0;
533 foreach ($values as $record)
534 {
535 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
536 echo '<tr><td>';
537 if (!empty ($record['value']))
538 {
539 echo "<a href='${root}process.php?page=${pageno}&tab=${tabno}&op=clearSticker&object_id=${object_id}&attr_id=${record['id']}'>";
540 printImageHREF ('clear', 'Clear value');
541 echo '</a>';
542 }
543 else
544 echo '&nbsp;';
545 echo '</td>';
546 echo "<td class=tdright>${record['name']}:</td><td class=tdleft>";
547 switch ($record['type'])
548 {
549 case 'uint':
550 case 'float':
551 case 'string':
552 echo "<input type=text name=${i}_value value='${record['value']}'>";
553 break;
554 case 'dict':
555 $chapter = readChapter ($record['chapter_name']);
556 $chapter[0] = '-- NOT SET --';
557 printSelect ($chapter, "${i}_value", $record['key']);
558 break;
559 }
560 echo "</td></tr>\n";
561 $i++;
562 }
563 echo "</table>";
564 }
565 echo "</td></tr>\n";
566
567 echo "<tr><th class=submit colspan=2>";
568 printImageHREF ('SAVE', 'Save changes', TRUE);
569 echo "</form></th></tr></table>\n";
570 finishPortlet();
571
572 echo '<table border=0 width=100%><tr><td>';
573 startPortlet ('history');
574 renderHistory ($pageno, $object_id);
575 finishPortlet();
576 echo '</td></tr></table>';
577 }
578
579 // This is a clone of renderEditObjectForm().
580 function renderEditRackForm ($rack_id)
581 {
582 showMessageOrError();
583 global $pageno;
584 $rack = getRackData ($rack_id);
585 if ($rack == NULL)
586 {
587 showError ('getRackData() failed', __FUNCTION__);
588 return;
589 }
590
591 startPortlet ('Rack attributes');
592 printOpFormIntro ('updateRack');
593 echo '<table border=0 align=center>';
594 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
595 printSelect (readChapter ('RackRow'), 'rack_row_id', $rack['row_id']);
596 echo "</td></tr>\n";
597 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
598 echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
599 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
600 echo "<tr><td class=submit colspan=2>";
601 printImageHREF ('SAVE', 'Save changes', TRUE);
602 echo "</td></tr>\n";
603 echo '</form></table><br>';
604 finishPortlet();
605
606 startPortlet ('History');
607 renderHistory ($pageno, $rack_id);
608 finishPortlet();
609 }
610
611 // This is a helper for creators and editors.
612 function printSelect ($rowList, $select_name, $selected_id = NULL, $tabindex = NULL)
613 {
614 // First collect all data for OPTGROUPs, then ouput it and dump
615 // the rest of records as is.
616 $optgroup = array();
617 $other = array();
618 foreach ($rowList as $dict_key => $dict_value)
619 {
620 if (strpos ($dict_value, '%GSKIP%') !== FALSE)
621 {
622 $tmp = explode ('%GSKIP%', $dict_value, 2);
623 $optgroup[$tmp[0]][$dict_key] = $tmp[1];
624 }
625 elseif (strpos ($dict_value, '%GPASS%') !== FALSE)
626 {
627 $tmp = explode ('%GPASS%', $dict_value, 2);
628 $optgroup[$tmp[0]][$dict_key] = $tmp[1];
629 }
630 else
631 $other[$dict_key] = $dict_value;
632 }
633 echo "<select name=${select_name}" . ($tabindex ? " tabindex=${tabindex}" : '') . '>';
634 if (!count ($optgroup))
635 {
636 foreach ($other as $dict_key => $dict_value)
637 {
638 echo "<option value=${dict_key}";
639 if ($dict_key == $selected_id)
640 echo ' selected';
641 echo ">${dict_value}</option>";
642 }
643 }
644 else
645 {
646 foreach ($optgroup as $groupname => $groupdata)
647 {
648 echo "<optgroup label='${groupname}'>";
649 foreach ($groupdata as $dict_key => $dict_value)
650 {
651 echo "<option value=${dict_key}";
652 if ($dict_key == $selected_id)
653 echo ' selected';
654 echo ">${dict_value}</option>";
655 }
656 echo "</optgroup>\n";
657 }
658 if (count ($other))
659 {
660 echo "<optgroup label='other'>\n";
661 foreach ($other as $dict_key => $dict_value)
662 {
663 echo "<option value=${dict_key}";
664 if ($dict_key == $selected_id)
665 echo ' selected';
666 echo ">${dict_value}</option>";
667 }
668 echo "</optgroup>\n";
669 }
670 }
671 echo "</select>";
672 }
673
674 // used by renderGridForm() and renderRackPage()
675 function renderRackInfoPortlet ($rackData)
676 {
677 global $root;
678 startPortlet ('summary');
679 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
680 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
681 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
682 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
683 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
684 renderProgressBar (getRSUforRack ($rackData));
685 echo "</td></tr>\n";
686 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
687 echo count (stuffInRackspace ($rackData));
688 echo "</td></tr>\n";
689 printTagTRs ("${root}?page=rackspace&tab=default&");
690 if (!empty ($rackData['comment']))
691 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
692 echo '</table>';
693 finishPortlet();
694 }
695
696 // This is a universal editor of rack design/waste.
697 // FIXME: switch to using printOpFormIntro()
698 function renderGridForm ($rack_id = 0, $filter, $header, $submit, $state1, $state2)
699 {
700 if ($rack_id == 0)
701 {
702 showError ('Invalid rack_id', __FUNCTION__);
703 return;
704 }
705 if (($rackData = getRackData ($rack_id)) == NULL)
706 {
707 showError ('getRackData() failed', __FUNCTION__);
708 return;
709 }
710
711 global $root, $pageno, $tabno;
712 $filter ($rackData);
713 markupObjectProblems ($rackData);
714
715 // Process form submit.
716 if (isset ($_REQUEST['do_update']))
717 {
718 $log[] = processGridForm ($rackData, $state1, $state2);
719 printLog ($log);
720 $rackData = getRackData ($rack_id);
721 $filter ($rackData);
722 markupObjectProblems ($rackData);
723 }
724
725 // Render the result whatever it is.
726 // Main layout.
727 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
728 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
729
730 // Left column with information portlet.
731 echo "<tr><td class=pcleft height='1%' width='50%'>";
732 renderRackInfoPortlet ($rackData);
733 echo "</td>\n";
734 echo "<td class=pcright>";
735
736 // Grid form.
737 startPortlet ($header);
738 echo "<center>\n";
739 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
740 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
741 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
742 echo "<form method=post action='${root}?'>\n";
743 echo "<input type=hidden name=page value=${pageno}>\n";
744 echo "<input type=hidden name=tab value=${tabno}>\n";
745 echo "<input type=hidden name=rack_id value=${rack_id}>\n";
746 markupAtomGrid ($rackData, $state2);
747 renderAtomGrid ($rackData);
748 echo "</table></center>\n";
749 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
750 finishPortlet();
751 echo "</td></tr></table>\n";
752 }
753
754 function renderRackDesign ($rack_id)
755 {
756 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
757 }
758
759 function renderRackProblems ($rack_id = 0)
760 {
761 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
762 }
763
764 function startPortlet ($title = '')
765 {
766 echo "<div class=portlet><h2>${title}</h2>";
767 }
768
769 function finishPortlet ()
770 {
771 echo "</div>\n";
772 }
773
774 function printRefsOfType ($refs, $type, $eq)
775 {
776 global $root;
777 $gotone=0;
778 foreach ($refs as $ref)
779 {
780 if ($eq($ref['type'], $type))
781 {
782 if ($gotone) echo ', ';
783 echo "<a href='${root}?page=object&object_id=${ref['object_id']}'>";
784 if (!empty ($ref['name']))
785 echo $ref['name'] . '@';
786 echo "${ref['object_name']}</a>";
787 $gotone=1;
788 }
789 }
790 }
791
792 function renderRackObject ($object_id = 0)
793 {
794 global $root, $nextorder, $aac;
795 if ($object_id <= 0)
796 {
797 showError ('Invalid object_id', __FUNCTION__);
798 return;
799 }
800 $info = getObjectInfo ($object_id);
801 if ($info == NULL)
802 {
803 showError ('getObjectInfo() failed', __FUNCTION__);
804 return;
805 }
806 // Main layout starts.
807 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
808 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
809 // left column with uknown number of portlets
810 echo "<tr><td class=pcleft>";
811 startPortlet ('summary');
812 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
813 if (!empty ($info['name']))
814 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
815 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('NAMEFUL_OBJTYPES'))))
816 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
817 echo "<tr><th width='50%' class=tdright>Object type:</th>";
818 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";
819 if (!empty ($info['asset_no']))
820 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
821 elseif (in_array ($info['objtype_id'], explode (',', getConfigVar ('REQUIRE_ASSET_TAG_FOR'))))
822 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
823 if (!empty ($info['label']))
824 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
825 if (!empty ($info['barcode']))
826 echo "<tr><th width='50%' class=tdright>Barcode:</th><td class=tdleft>${info['barcode']}</td></tr>\n";
827 if ($info['has_problems'] == 'yes')
828 echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
829 foreach (getAttrValues ($object_id, TRUE) as $record)
830 if (!empty ($record['value']))
831 echo "<tr><th width='50%' class=tdright><span class=sticker>${record['name']}</span>:</th><td class=tdleft>${record['a_value']}</td></tr>\n";
832 printTagTRs ("${root}?page=objgroup&tab=default&group_id=${info['objtype_id']}&");
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></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 '</tr>';
1920 $order = $nextorder[$order];
1921 }
1922 echo '</table>';
1923 finishPortlet();
1924
1925 echo "</td><td class=pcright width='25%'>";
1926
1927 renderTagFilterPortlet ($tagfilter, 'object', 'group_id', $group_id);
1928 echo "</td></tr></table>\n";
1929 }
1930
1931 function renderEmptyPortsSelect ($port_id, $type_id)
1932 {
1933 $ports = getEmptyPortsOfType($type_id);
1934 usort($ports, 'sortEmptyPorts');
1935 foreach ($ports as $port)
1936 {
1937 if ($port_id == $port['Port_id'])
1938 continue;
1939 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";
1940 }
1941 }
1942
1943 function renderAllIPv4Allocations ()
1944 {
1945 $addresses = getAllIPv4Allocations();
1946 usort($addresses, 'sortObjectAddressesAndNames');
1947 foreach ($addresses as $address)
1948 {
1949 echo "<option value='${address['ip']}' onclick='getElementById(\"ip\").value=\"${address['ip']}\";'>${address['object_name']} ${address['name']} ${address['ip']}</option>\n";
1950 }
1951 }
1952
1953 // History viewer for history-enabled simple dictionaries.
1954 function renderHistory ($object_type, $object_id)
1955 {
1956 switch ($object_type)
1957 {
1958 case 'row':
1959 $query = "select ctime, user_name, name, deleted, comment from RackRowHistory where id = ${object_id} order by ctime";
1960 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>is deleted?</th><th>rack row comment</th></tr>';
1961 $extra = 4;
1962 break;
1963 case 'rack':
1964 $query =
1965 "select ctime, user_name, rh.name, rh.deleted, d.dict_value as name, rh.height, rh.comment " .
1966 "from RackHistory as rh left join Dictionary as d on rh.row_id = d.dict_key " .
1967 "natural join Chapter " .
1968 "where chapter_name = 'RackRow' and rh.id = ${object_id} order by ctime";
1969 $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>';
1970 $extra = 6;
1971 break;
1972 case 'object':
1973 $query =
1974 "select ctime, user_name, name, label, barcode, asset_no, deleted, has_problems, dict_value, comment " .
1975 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key natural join Chapter " .
1976 "where chapter_name = 'RackObjectType' and id=${object_id} order by ctime";
1977 $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>';
1978 $extra = 9;
1979 break;
1980 default:
1981 showError ("Uknown object type '${object_type}'", __FUNCTION__);
1982 return;
1983 }
1984 global $dbxlink;
1985 $result = $dbxlink->query ($query);
1986 if ($result == NULL)
1987 {
1988 showError ('SQL query failed', __FUNCTION__);
1989 return;
1990 }
1991 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1992 $order = 'odd';
1993 global $nextorder;
1994 echo $header;
1995 while ($row = $result->fetch (PDO::FETCH_NUM))
1996 {
1997 echo "<tr class=row_${order}><td>${row[0]}</td>";
1998 for ($i = 1; $i <= $extra; $i++)
1999 echo "<td>" . $row[$i] . "</td>";
2000 echo "</tr>\n";
2001 $order = $nextorder[$order];
2002 }
2003 echo "</table><br>\n";
2004 }
2005
2006 function renderRackspaceHistory ()
2007 {
2008 global $root, $nextorder, $pageno, $tabno;
2009 $order = 'odd';
2010 $history = getRackspaceHistory();
2011 // Show the last operation by default.
2012 if (isset ($_REQUEST['op_id']))
2013 $op_id = $_REQUEST['op_id'];
2014 elseif (isset ($history[0]['mo_id']))
2015 $op_id = $history[0]['mo_id'];
2016 else $op_id = NULL;
2017
2018 $omid = NULL;
2019 $nmid = NULL;
2020 $object_id = 1;
2021 if ($op_id)
2022 list ($omid, $nmid) = getOperationMolecules ($op_id);
2023
2024 // Main layout starts.
2025 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2026
2027 // Left top portlet with old allocation.
2028 echo "<tr><td class=pcleft>";
2029 startPortlet ('Old allocation');
2030 if ($omid)
2031 {
2032 $oldMolecule = getMolecule ($omid);
2033 renderMolecule ($oldMolecule, $object_id);
2034 }
2035 else
2036 echo "nothing";
2037 finishPortlet();
2038
2039 echo '</td><td class=pcright>';
2040
2041 // Right top portlet with new allocation
2042 startPortlet ('New allocation');
2043 if ($nmid)
2044 {
2045 $newMolecule = getMolecule ($nmid);
2046 renderMolecule ($newMolecule, $object_id);
2047 }
2048 else
2049 echo "nothing";
2050 finishPortlet();
2051
2052 echo '</td></tr><tr><td colspan=2>';
2053
2054 // Bottom portlet with list
2055
2056 startPortlet ('Rackspace allocation history');
2057 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
2058 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";
2059 foreach ($history as $row)
2060 {
2061 if ($row['mo_id'] == $op_id)
2062 $class = 'hl';
2063 else
2064 $class = "row_${order}";
2065 echo "<tr class=${class}><td><a href='${root}?page=${pageno}&tab=${tabno}&op_id=${row['mo_id']}'>${row['ctime']}</a></td>";
2066 echo "<td>${row['user_name']}</td>";
2067 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
2068 echo "</tr>\n";
2069 $order = $nextorder[$order];
2070 }
2071 echo "</table>\n";
2072 finishPortlet();
2073
2074 echo '</td></tr></table>';
2075 }
2076
2077 function renderIPv4SpaceRecords ($tree, &$tagcache, $baseurl, $target = 0, $level = 1)
2078 {
2079 $self = __FUNCTION__;
2080 foreach ($tree as $item)
2081 {
2082 $total = $item['addrt'];
2083 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2084 {
2085 loadIPv4AddrList ($item); // necessary to compute router list and address counter
2086 $used = $item['addrc'];
2087 }
2088 else
2089 {
2090 $item['addrlist'] = array();
2091 $item['addrc'] = 0;
2092 }
2093 if (isset ($item['id']))
2094 {
2095 if ($item['symbol'] == 'node-collapsed')
2096 $expandurl = "${baseurl}&eid=" . $item['id'] . "#netid" . $item['id'];
2097 elseif ($item['symbol'] == 'node-expanded')
2098 $expandurl = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#netid${item['parent_id']}" : '');
2099 else
2100 $expandurl = '';
2101 echo "<tr valign=top>";
2102 printIPv4NetInfoTDs ($item, 'tdleft', $level, $item['symbol'], $expandurl);
2103 echo "<td class=tdcenter>";
2104 if ($target == $item['id'])
2105 echo "<a name=netid${target}></a>";
2106 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2107 {
2108 renderProgressBar ($total ? $used/$total : 0);
2109 echo "<br><small>${used}/${total}</small>";
2110 }
2111 else
2112 echo "<small>${total}</small>";
2113 echo "</td>";
2114 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2115 printRoutersTD (findRouters ($item['addrlist']), $tagcache);
2116 echo "</tr>";
2117 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2118 $self ($item['kids'], $tagcache, $baseurl, $target, $level + 1);
2119 }
2120 else
2121 {
2122 echo "<tr valign=top>";
2123 printIPv4NetInfoTDs ($item, 'tdleft sparenetwork', $level, $item['symbol']);
2124 echo "<td class=tdcenter>";
2125 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2126 {
2127 renderProgressBar ($used/$total, 'sparenetwork');
2128 echo "<br><small>${used}/${total}</small>";
2129 }
2130 else
2131 echo "<small>${total}</small>";
2132 echo "</td><td>&nbsp;</td></tr>";
2133 }
2134 }
2135 }
2136
2137 function renderIPv4Space ()
2138 {
2139 global $root, $pageno, $tabno;
2140 $tagfilter = getTagFilter();
2141 $netlist = getIPv4NetworkList ($tagfilter, getTFMode());
2142 $netcount = count ($netlist);
2143 // expand request can take either natural values or "ALL". Zero means no expanding.
2144 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2145 $tree = prepareIPv4Tree ($netlist, $eid);
2146
2147 echo "<table border=0 class=objectview>\n";
2148 echo "<tr><td class=pcleft>";
2149 startPortlet ("networks (${netcount})");
2150 echo '<h4>';
2151 if ($eid === 0)
2152 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') . " (<a href='${root}?page=${pageno}&tab=${tabno}&eid=ALL'>expand all</a>)";
2153 elseif ($eid === 'ALL')
2154 echo "expanding all (<a href='${root}?page=${pageno}&tab=${tabno}'>auto-collapse</a>)";
2155 else
2156 {
2157 $netinfo = getIPv4NetworkInfo ($eid);
2158 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>)";
2159 }
2160 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2161 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2162 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2163 echo "<th>routed by</th>";
2164 echo "</tr>\n";
2165 $tagcache = array();
2166 $baseurl = "${root}?page=${pageno}&tab=${tabno}" . getTagFilterStr ($tagfilter);
2167 renderIPv4SpaceRecords ($tree, $tagcache, $baseurl, $eid);
2168 echo "</table>\n";
2169 finishPortlet();
2170 echo '</td><td class=pcright>';
2171 renderTagFilterPortlet ($tagfilter, 'ipv4net');
2172 echo "</td></tr></table>\n";
2173 }
2174
2175 function renderIPv4SLB ()
2176 {
2177 global $root, $page, $nextorder;
2178
2179 startPortlet ('SLB configuration');
2180 echo "<table border=0 width='100%'><tr>";
2181 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2182 echo "<td><h3><a href='${root}?page=${pno}'>" . $page[$pno]['title'] . "</a></h3></td>";
2183 echo '</tr></table>';
2184 finishPortlet();
2185
2186 $summary = getSLBSummary();
2187 startPortlet ('SLB tactical overview');
2188 // A single id-keyed array isn't used here to preserve existing
2189 // order of LBs returned by getSLBSummary()
2190 $lblist = array();
2191 $lbdname = array();
2192 foreach ($summary as $vipdata)
2193 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2194 if (!in_array ($lb_object_id, $lblist))
2195 {
2196 $oi = getObjectInfo ($lb_object_id);
2197 $lbdname[$lb_object_id] = $oi['dname'];
2198 $lblist[] = $lb_object_id;
2199 }
2200 if (!count ($summary))
2201 echo 'none configured';
2202 else
2203 {
2204 $order = 'odd';
2205 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2206 echo "<tr valign=top><td>&nbsp;</td>";
2207 foreach ($lblist as $lb_object_id)
2208 {
2209 #echo "<th><a href='${root}?page=object&tab=default&object_id=${lb_object_id}'>" . $lbdname[$lb_object_id] . "</a></th>";
2210 echo '<td>';
2211 renderLBCell ($lb_object_id);
2212 echo '</td>';
2213 }
2214 echo "</tr>\n";
2215 foreach ($summary as $vsid => $vsdata)
2216 {
2217 echo "<tr class=row_${order}><td class=tdleft>";
2218 renderVSCell ($vsid);
2219 echo "</td>";
2220 foreach ($lblist as $lb_object_id)
2221 {
2222 echo '<td class=tdleft>';
2223 if (!isset ($vsdata['lblist'][$lb_object_id]))
2224 echo '&nbsp;';
2225 else
2226 {
2227 echo $vsdata['lblist'][$lb_object_id]['size'];
2228 // echo " (<a href='${root}?page=ipv4rspool&pool_id=";
2229 // echo $vsdata['lblist'][$lb_object_id]['id'] . "'>";
2230 // echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2231 }
2232 echo '</td>';
2233 }
2234 echo "</tr>\n";
2235 $order = $nextorder[$order];
2236 }
2237 echo "</table>\n";
2238 }
2239 finishPortlet ();
2240 }
2241
2242 function renderIPv4SpaceEditor ()
2243 {
2244 global $root, $pageno, $tabno;
2245 showMessageOrError();
2246
2247 // IPv4 validator
2248 ?>
2249 <script type="text/javascript">
2250 function init() {
2251 document.add_new_range.range.setAttribute('match', "^\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\/\\d\\d?$");
2252
2253 Validate.init();
2254 }
2255 window.onload=init;
2256 </script>
2257 <?php
2258
2259 startPortlet ("Add new");
2260 echo '<table border=0 cellpadding=10 align=center>';
2261 // This form requires a name, so JavaScript validator can find it.
2262 // No printOpFormIntro() hence
2263 echo "<form method=post name='add_new_range' action='${root}process.php'>\n";
2264 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2265 echo "<input type=hidden name=page value='${pageno}'>\n";
2266 echo "<input type=hidden name=tab value='${tabno}'>\n";
2267 // tags column
2268 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2269 renderTagSelect();
2270 echo '</td>';
2271 // inputs column
2272 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=18 class='live-validate' tabindex=1></td>";
2273 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2274 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2275 echo "<tr><td colspan=2>";
2276 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2277 echo '</td></tr>';
2278 echo "</form></table><br><br>\n";
2279 finishPortlet();
2280
2281 $addrspaceList = getIPv4NetworkList();
2282 $netcount = count ($addrspaceList);
2283 if ($netcount)
2284 {
2285 startPortlet ("Manage existing (${netcount})");
2286 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2287 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>&nbsp;</th></tr>";
2288 foreach ($addrspaceList as $netinfo)
2289 {
2290 echo "<form method=post action='${root}process.php?page=${pageno}&tab=${tabno}&op=updIPv4Prefix&id=${netinfo['id']}'>";
2291 echo "<tr valign=top><td><a href='${root}process.php?op=delIPv4Prefix&page=${pageno}&tab=${tabno}&id=${netinfo['id']}'>";
2292 printImageHREF ('delete', 'Delete this IP range');
2293 echo "</a></td>\n<td class=tdleft>${netinfo['ip']}/${netinfo['mask']}</td>";
2294 echo "<td><input type=text name=name size=40 value='${netinfo['name']}'>";
2295 echo "</td><td>";
2296 printImageHREF ('save', 'Save changes', TRUE);
2297 echo "</td></tr></form>\n";
2298 }
2299 echo "</table>";
2300 finishPortlet();
2301 }
2302 }
2303
2304 function renderIPv4Network ($id)
2305 {
2306 global $root, $pageno, $tabno, $aac2;
2307 $netmaskbylen = array
2308 (
2309 32 => '255.255.255.255',
2310 31 => '255.255.255.254',
2311 30 => '255.255.255.252',
2312 29 => '255.255.255.248',
2313 28 => '255.255.255.240',
2314 27 => '255.255.255.224',
2315 26 => '255.255.255.192',
2316 25 => '255.255.255.128',
2317 24 => '255.255.255.0',
2318 23 => '255.255.254.0',
2319 22 => '255.255.252.0',
2320 21 => '255.255.248.0',
2321 20 => '255.255.240.0',
2322 19 => '255.255.224.0',
2323 18 => '255.255.192.0',
2324 17 => '255.255.128.0',
2325 16 => '255.255.0.0',
2326 15 => '255.254.0.0',
2327 14 => '255.252.0.0',
2328 13 => '255.248.0.0',
2329 12 => '255.240.0.0',
2330 11 => '255.224.0.0',
2331 10 => '255.192.0.0',
2332 9 => '255.128.0.0',
2333 8 => '255.0.0.0',
2334 7 => '254.0.0.0',
2335 6 => '252.0.0.0',
2336 5 => '248.0.0.0',
2337 4 => '240.0.0.0',
2338 3 => '224.0.0.0',
2339 2 => '192.0.0.0',
2340 1 => '128.0.0.0'
2341 );
2342 $wildcardbylen = array
2343 (
2344 32 => '0.0.0.0',
2345 31 => '0.0.0.1',
2346 30 => '0.0.0.3',
2347 29 => '0.0.0.7',
2348 28 => '0.0.0.15',
2349 27 => '0.0.0.31',
2350 26 => '0.0.0.63',
2351 25 => '0.0.0.127',
2352 24 => '0.0.0.255',
2353 23 => '0.0.1.255',
2354 22 => '0.0.3.255',
2355 21 => '0.0.7.255',
2356 20 => '0.0.15.255',
2357 19 => '0.0.31.255',
2358 18 => '0.0.63.255',
2359 17 => '0.0.127.255',
2360 16 => '0.0.255.25',
2361 15 => '0.1.255.255',
2362 14 => '0.3.255.255',
2363 13 => '0.7.255.255',
2364 12 => '0.15.255.255',
2365 11 => '0.31.255.255',
2366 10 => '0.63.255.255',
2367 9 => '0.127.255.255',
2368 8 => '0.255.255.255',
2369 7 => '1.255.255.255',
2370 6 => '3.255.255.255',
2371 5 => '7.255.255.255',
2372 4 => '15.255.255.255',
2373 3 => '31.255.255.255',
2374 2 => '63.255.255.255',
2375 1 => '127.255.255.255'
2376 );
2377 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2378 if (isset($_REQUEST['pg']))
2379 $page = $_REQUEST['pg'];
2380 else
2381 $page=0;
2382
2383 $range = getIPv4NetworkInfo ($id);
2384 loadIPv4AddrList ($range);
2385 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2386 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></td></tr>\n";
2387
2388 echo "<tr><td class=pcleft width='50%'>";
2389 startPortlet ('summary');
2390 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2391 $used = count ($range['addrlist']);
2392 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2393
2394 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2395 renderProgressBar ($used/$total);
2396 echo "&nbsp;${used}/${total}</td></tr>\n";
2397
2398 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2399 {
2400 // Build a backtrace from all parent networks.
2401 $clen = $range['mask'];
2402 $backtrace = array();
2403 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2404 {
2405 $upperinfo = getIPv4NetworkInfo ($upperid);
2406 $clen = $upperinfo['mask'];
2407 $backtrace[] = $upperid;
2408 }
2409 $arrows = count ($backtrace);
2410 foreach (array_reverse ($backtrace) as $ancestorid)
2411 {
2412 $ainfo = getIPv4NetworkInfo ($ancestorid);
2413 echo "<tr><th width='50%' class=tdright>";
2414 for ($i = 0; $i < $arrows; $i++)
2415 echo '&uarr;';
2416 $arrows--;
2417 echo "</th><td class=tdleft><a href='${root}?page=${pageno}&tab=${tabno}&id=${ainfo['id']}'>${ainfo['ip']}/${ainfo['mask']}</a></td></tr>";
2418 }
2419 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
2420 echo "<td class=tdleft>${range['ip']}/${range['mask']}</td></tr>";
2421 // FIXME: get and display nested networks
2422 // $theitem = pickLeaf ($ipv4tree, $id);
2423 }
2424
2425 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2426 echo $netmaskbylen[$range['mask']];
2427 echo "</td></tr>\n";
2428
2429 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2430 printf ('0x%08X', binMaskFromDec ($range['mask']));
2431 echo "</td></tr>\n";
2432
2433 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2434 echo $wildcardbylen[$range['mask']];
2435 echo "</td></tr>\n";
2436
2437 $routers = findRouters ($range['addrlist']);
2438 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers))
2439 {
2440 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2441 printRoutersTD ($routers);
2442 echo "</tr>\n";
2443 }
2444
2445 printTagTRs ("${root}?page=ipv4space&tab=default&");
2446 echo "</table><br>\n";
2447 finishPortlet();
2448
2449 renderFilesPortlet ('ipv4net', $id);
2450 echo "</td>\n";
2451
2452 echo "<td class=pcright>";
2453 startPortlet ('details');
2454 $startip = $range['ip_bin'] & $range['mask_bin'];
2455 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2456 $realstartip = $startip;
2457 $realendip = $endip;
2458 $numpages = 0;
2459 if($endip - $startip > $maxperpage)
2460 {
2461 $numpages = ($endip - $startip)/$maxperpage;
2462 $startip = $startip + $page * $maxperpage;
2463 $endip = $startip + $maxperpage-1;
2464 }
2465 echo "<center>";
2466 if ($numpages)
2467 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2468 for ($i=0; $i<$numpages; $i++)
2469 {
2470 if ($i == $page)
2471 echo "<b>$i</b> ";
2472 else
2473 echo "<a href='${root}?page=${pageno}&tab=${tabno}&id=$id&pg=$i'>$i</a> ";
2474 }
2475 echo "</center>";
2476
2477 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2478 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2479
2480
2481 for ($ip = $startip; $ip <= $endip; $ip++) :
2482 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2483 $secondstyle = 'tdleft port_highlight';
2484 else
2485 $secondstyle = 'tdleft';
2486 if (!isset ($range['addrlist'][$ip]))
2487 {
2488 echo "<tr><td class=tdleft><a href='${root}?page=ipaddress&ip=" . long2ip ($ip) . "'>" . long2ip ($ip);
2489 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2490 continue;
2491 }
2492 $addr = $range['addrlist'][$ip];
2493 echo "<tr class='${addr['class']}'>";
2494
2495 echo "<td class=tdleft><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
2496 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2497 $delim = '';
2498 $prologue = '';
2499 if ( $addr['reserved'] == 'yes')
2500 {
2501 echo "<strong>RESERVED</strong> ";
2502 $delim = '; ';
2503 }
2504 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2505 {
2506 echo $delim . $aac2[$ref['type']];
2507 echo "<a href='${root}?page=object&object_id=${ref['object_id']}";
2508 echo "&hl_ipv4_addr=${addr['ip']}'>";
2509 echo $ref['name'] . (empty ($ref['name']) ? '' : '@');
2510 echo "${ref['object_name']}</a>";
2511 $delim = '; ';
2512 }
2513 if ($delim != '')
2514 {
2515 $delim = '';
2516 $prologue = '<br>';
2517 }
2518 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2519 {
2520 echo $prologue;
2521 $prologue = '';
2522 echo "${delim}<a href='${root}?page=object&object_id=${ref['object_id']}'>";
2523 echo "${ref['object_name']}</a>:<a href='${root}?page=ipv4vs&vs_id=${ref['vs_id']}'>";
2524 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2525 $delim = '; ';
2526 }
2527 if ($delim != '')
2528 {
2529 $delim = '';
2530 $prologue = '<br>';
2531 }
2532 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2533 {
2534 echo $prologue;
2535 $prologue = '';
2536 echo "${delim}&rarr;${ref['rsport']}@<a href='${root}?page=ipv4rspool&pool_id=${ref['rspool_id']}'>";
2537 echo "${ref['rspool_name']}</a>";
2538 $delim = '; ';
2539 }
2540 echo "</td></tr>\n";
2541 endfor;
2542 // end of iteration
2543
2544 echo "</table>";
2545 finishPortlet();
2546 echo "</td></tr></table>\n";
2547 }
2548
2549 function renderIPv4NetworkProperties ($id)
2550 {
2551 showMessageOrError();
2552 $netdata = getIPv4NetworkInfo ($id);
2553 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
2554 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2555 printOpFormIntro ('editRange');
2556 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${netdata['name']}'></tr>";
2557 echo "<tr><td colspan=2 class=tdcenter>";
2558 printImageHREF ('SAVE', 'Save changes', TRUE);
2559 echo "</td></form></tr></table>\n";
2560 }
2561
2562 function renderIPv4Address ($dottedquad)
2563 {
2564 global $root, $aat;
2565 $address = getIPv4Address ($dottedquad);
2566 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2567 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2568 if (!empty ($address['name']))
2569 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
2570
2571 echo "<tr><td class=pcleft>";
2572 startPortlet ('summary');
2573 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2574 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
2575 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2576 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2577 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
2578 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2579 printTagTRs();
2580 echo "</table><br>\n";
2581 finishPortlet();
2582 echo "</td>\n";
2583
2584 echo "<td class=pcright>";
2585
2586 if (isset ($address['class']))
2587 {
2588 startPortlet ('allocations');
2589 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2590 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2591 $class = $address['class'];
2592 // render all allocation records for this address the same way
2593 if ($address['reserved'] == 'yes')
2594 echo "<tr class='${class}'><td colspan=2>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td></tr>";
2595 foreach ($address['allocs'] as $bond)
2596 {
2597 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2598 $secondclass = 'tdleft port_highlight';
2599 else
2600 $secondclass = 'tdleft';
2601 echo "<tr class='$class'><td class=tdleft><a href='${root}?page=object&object_id=${bond['object_id']}";
2602 echo "&hl_ipv4_addr=${dottedquad}'>${bond['object_name']}</td><td class='${secondclass}'>${bond['name']}</td><td class='${secondclass}'><strong>";
2603 echo $aat[$bond['type']];
2604 echo "</strong></td></tr>\n";
2605 }
2606 echo "</table><br><br>";
2607 finishPortlet();
2608 }
2609
2610 // FIXME: The returned list is structured differently, than we expect it to be. One of the sides
2611 // must be fixed.
2612 if (count ($address['lblist']))
2613 {
2614 startPortlet ('Virtual services (' . count ($address['lblist']) . ')');
2615 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2616 echo "<tr><th>VS</th><th>name</th></tr>\n";
2617 foreach ($address['lblist'] as $vsinfo)
2618 {
2619 echo "<tr><td class=tdleft><a href='${root}?page=ipv4vs&vs_id=${vsinfo['vs_id']}'>";
2620 echo buildVServiceName ($vsinfo) . "</a></td><td class=tdleft>";
2621 echo $vsinfo['name'] . "</td></tr>\n";
2622 }
2623 echo "</table><br><br>";
2624 finishPortlet();
2625 }
2626
2627 if (count ($address['rslist']))
2628 {
2629 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2630 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2631 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
2632 foreach ($address['rslist'] as $rsinfo)
2633 {
2634 echo "<tr><td>";
2635 if ($rsinfo['inservice'] == 'yes')
2636 printImageHREF ('inservice', 'in service');
2637 else
2638 printImageHREF ('notinservice', 'NOT in service');
2639 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='${root}?page=ipv4rspool&pool_id=${rsinfo['rspool_id']}'>";
2640 echo $rsinfo['rspool_name'] . "</a></td></tr>\n";
2641 }
2642 echo "</table><br><br>";
2643 finishPortlet();
2644 }
2645
2646 if (count ($address['outpf']))
2647 {
2648 startPortlet ('departing NAT rules');
2649 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2650 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2651 foreach ($address['outpf'] as $rule)
2652 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2653 echo "</table>";
2654 finishPortlet();
2655 }
2656
2657 if (count ($address['inpf']))
2658 {
2659 startPortlet ('arriving NAT rules');
2660 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2661 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2662 foreach ($address['inpf'] as $rule)
2663 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2664 echo "</table>";
2665 finishPortlet();
2666 }
2667
2668 echo "</td></tr>";
2669 echo "</table>\n";
2670 }
2671
2672 function renderIPv4AddressProperties ($dottedquad)
2673 {
2674 showMessageOrError();
2675 $address = getIPv4Address ($dottedquad);
2676 echo "<center><h1>$dottedquad</h1></center>\n";
2677
2678 startPortlet ('update');
2679 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2680 printOpFormIntro ('editAddress');
2681 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2682 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2683 echo ($address['reserved']=='yes') ? 'checked' : '';
2684 echo "></tr><tr><td colspan=2 class='tdcenter'>";
2685 printImageHREF ('SAVE', 'Save changes', TRUE);
2686 echo "</td></form></tr></table>\n";
2687 finishPortlet();
2688 if (empty ($address['name']) and $address['reserved'] == 'no')
2689 return;
2690
2691 startPortlet ('release');
2692 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2693 echo "<input type=submit value='release'></form>";
2694 finishPortlet();
2695 }
2696
2697 function renderIPv4AddressAllocations ($dottedquad)
2698 {
2699 showMessageOrError();
2700 function printNewItemTR ()
2701 {
2702 global $aat;
2703 printOpFormIntro ('addIPv4Allocation');
2704 echo "<tr><td>";
2705 printImageHREF ('add', 'allocate', TRUE);
2706 echo "</td><td><select name='object_id' tabindex=100>";
2707
2708 foreach (explode (',', getConfigVar ('IPV4_PERFORMERS')) as $type)
2709 foreach (getNarrowObjectList ($type) as $object)
2710 echo "<option value='${object['id']}'>${object['dname']}</option>";
2711
2712 echo "</select></td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
2713 printSelect ($aat, 'bond_type', NULL, 102);
2714 echo "</td><td>";
2715 printImageHREF ('add', 'allocate', TRUE, 103);
2716 echo "</td></form></tr>";
2717 }
2718 global $pageno, $tabno, $root, $aat;
2719
2720 $address = getIPv4Address ($dottedquad);
2721
2722 echo "<center><h1>${dottedquad}</h1></center>\n";
2723 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2724 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
2725
2726 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2727 printNewItemTR();
2728 if (isset ($address['class']))
2729 {
2730 $class = $address['class'];
2731 if ($address['reserved'] == 'yes')
2732 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2733 foreach ($address['allocs'] as $bond)
2734 {
2735 echo "<tr class='$class'>";
2736 printOpFormIntro ('updIPv4Allocation', array ('object_id' => $bond['object_id']));
2737 echo "<td><a href='${root}process.php?op=delIPv4Allocation&page=${pageno}&tab=${tabno}&ip=${dottedquad}&object_id=${bond['object_id']}'>";
2738 printImageHREF ('delete', 'Unallocate address');
2739 echo "</a></td>";
2740 echo "<td><a href='${root}?page=object&object_id=${bond['object_id']}&hl_ipv4_addr=${dottedquad}'>${bond['object_name']}</td>";
2741 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
2742 printSelect ($aat, 'bond_type', $bond['type']);
2743 echo "</td><td>";
2744 printImageHREF ('save', 'Save changes', TRUE);
2745 echo "</td></form></tr>\n";
2746 }
2747 }
2748 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2749 printNewItemTR();
2750 echo "</table><br><br>";
2751 }
2752
2753 function renderNATv4ForObject ($object_id = 0)
2754 {
2755 function printNewItemTR ($alloclist)
2756 {
2757 global $root;
2758 printOpFormIntro ('addNATv4Rule');
2759 echo "<tr align='center'><td>";
2760 printImageHREF ('add', 'Add new NAT rule', TRUE);
2761 echo '</td><td>';
2762 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
2763 echo "<select name='localip' tabindex=1>";
2764
2765 foreach ($alloclist as $dottedquad => $alloc)
2766 {
2767 $name = empty ($alloc['addrinfo']['name']) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2768 $osif = empty ($alloc['osif']) ? '' : ($alloc['osif'] . ': ');
2769 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
2770 }
2771
2772 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2773 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2774 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\");'>";
2775 printImageHREF ('find', 'Find object');
2776 echo "</a>";
2777 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2778 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>";
2779 printImageHREF ('add', 'Add new NAT rule', TRUE, 6);
2780 echo "</td></tr></form>";
2781 }
2782 global $pageno, $tabno, $root;
2783
2784 $info = getObjectInfo ($object_id);
2785 $forwards = getNATv4ForObject ($object_id);
2786 $alloclist = getObjectIPv4Allocations ($object_id);
2787 showMessageOrError();
2788 echo "<center><h2>locally performed NAT</h2></center>";
2789
2790 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2791 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
2792
2793 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2794 printNewItemTR ($alloclist);
2795 foreach ($forwards['out'] as $pf)
2796 {
2797 $class = 'trerror';
2798 $osif = '';
2799 if (isset ($alloclist [$pf['localip']]))
2800 {
2801 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
2802 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
2803 }
2804
2805 echo "<tr class='$class'>";
2806 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}'>";
2807 printImageHREF ('delete', 'Delete NAT rule');
2808 echo "</a></td>";
2809 echo "<td>${pf['proto']}/${osif}<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}";
2810 if (!empty ($pf['local_addr_name']))
2811 echo ' (' . $pf['local_addr_name'] . ')';
2812 echo "</td>";
2813 echo "<td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2814
2815 $address = getIPv4Address ($pf['remoteip']);
2816
2817 echo "<td class='description'>";
2818 if (count ($address['allocs']))
2819 foreach ($address['allocs'] as $bond)
2820 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
2821 elseif (!empty ($pf['remote_addr_name']))
2822 echo '(' . $pf['remote_addr_name'] . ')';
2823 printOpFormIntro
2824 (
2825 'updNATv4Rule',
2826 array
2827 (
2828 'localip' => $pf['localip'],
2829 'localport' => $pf['localport'],
2830 'remoteip' => $pf['remoteip'],
2831 'remoteport' => $pf['remoteport'],
2832 'proto' => $pf['proto']
2833 )
2834 );
2835 echo "</td><td class='description'>";
2836 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2837 printImageHREF ('save', 'Save changes', TRUE);
2838 echo "</td></form></tr>";
2839 }
2840 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2841 printNewItemTR ($alloclist);
2842
2843 echo "</table><br><br>";
2844
2845 echo "<center><h2>arriving NAT connections</h2></center>";
2846 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2847 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2848
2849 foreach ($forwards['in'] as $pf)
2850 {
2851 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}'>";
2852 printImageHREF ('delete', 'Delete NAT rule');
2853 echo "</a></td>";
2854 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
2855 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
2856 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2857 echo "<td class='description'>${pf['description']}</td></tr>";
2858 }
2859
2860 echo "</table><br><br>";
2861 }
2862
2863 // FIXME: move related code away into ophandler(s)
2864 function renderAddMultipleObjectsForm ()
2865 {
2866 global $root, $pageno, $tabno, $nextorder;
2867
2868 $type_id = array();
2869 $global_type_id = 0;
2870 $name = array();
2871 $asset_no = array();
2872 $keepvalues1 = $keepvalues2 = FALSE;
2873 $log = array();
2874 // Look for current submit.
2875 if (isset ($_REQUEST['got_fast_data']))
2876 {
2877 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
2878 $keepvalues1 = TRUE;
2879 $max = getConfigVar ('MASSCOUNT');
2880 for ($i = 0; $i < $max; $i++)
2881 {
2882 if (!isset ($_REQUEST["${i}_object_type_id"]))
2883 {
2884 $log[] = array ('code' => 'error', 'message' => "Submitted form is invalid at line " . $i + 1);
2885 break;
2886 }
2887 assertUIntArg ("${i}_object_type_id", __FUNCTION__, TRUE);
2888 assertStringArg ("${i}_object_name", __FUNCTION__, TRUE);
2889 assertStringArg ("${i}_object_label", __FUNCTION__, TRUE);
2890 assertStringArg ("${i}_object_asset_no", __FUNCTION__, TRUE);
2891 assertStringArg ("${i}_object_barcode", __FUNCTION__, TRUE);
2892 $type_id[$i] = $_REQUEST["${i}_object_type_id"];
2893 // Save user input for possible rendering.
2894 $name[$i] = $_REQUEST["${i}_object_name"];
2895 $label[$i] = $_REQUEST["${i}_object_label"];
2896 $asset_no[$i] = $_REQUEST["${i}_object_asset_no"];
2897 $barcode[$i] = $_REQUEST["${i}_object_barcode"];
2898
2899 // It's better to skip silently, than to print a notice.
2900 if ($type_id[$i] == 0)
2901 continue;
2902 if (commitAddObject ($name[$i], $label[$i], $barcode[$i], $type_id[$i], $asset_no[$i], $taglist) === TRUE)
2903 $log[] = array ('code' => 'success', 'message' => "Added new object '${name[$i]}'");
2904 else
2905 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitAddObject() failed');
2906 }
2907 }
2908 elseif (isset ($_REQUEST['got_very_fast_data']))
2909 {
2910 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
2911 $keepvalues2 = TRUE;
2912 assertUIntArg ('global_type_id', __FUNCTION__, TRUE);
2913 assertStringArg ('namelist', __FUNCTION__, TRUE);
2914 $global_type_id = $_REQUEST['global_type_id'];
2915 if ($global_type_id == 0)
2916 {
2917 if (!empty ($_REQUEST['namelist']))
2918 $log[] = array ('code' => 'error', 'message' => 'Object type is not selected, check the form below');
2919 else
2920 $log[] = array ('code' => 'error', 'message' => 'Empty form has been ignored. Cheers.');
2921 }
2922 else
2923 {
2924 // The name extractor below was stolen from ophandlers.php:addMultiPorts()
2925 $names1 = explode ('\n', $_REQUEST['namelist']);
2926 $names2 = array();
2927 foreach ($names1 as $line)
2928 {
2929 $parts = explode ('\r', $line);
2930 reset ($parts);
2931 if (empty ($parts[0]))
2932 continue;
2933 else
2934 $names2[] = rtrim ($parts[0]);
2935 }
2936 foreach ($names2 as $cname)
2937 if (commitAddObject ($cname, '', '', $global_type_id, '', $taglist) === TRUE)
2938 $log[] = array ('code' => 'success', 'message' => "Added new object '${cname}'");
2939 else
2940 $log[] = array ('code' => 'error', 'message' => "Could not add '${cname}'");
2941 }
2942 }
2943 printLog ($log);
2944
2945 // Render a form for the next.
2946 $typelist = getObjectTypeList();
2947 $typelist[0] = 'select type...';
2948
2949 startPortlet ('Distinct types, same tags');
2950 $max = getConfigVar ('MASSCOUNT');
2951 echo "<form name=fastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
2952 echo '<table border=0 align=center>';
2953 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
2954 echo "<th>Asset tag</th><th>Barcode</th><th>Tags</th></tr>\n";
2955 // If a user forgot to select object type on input, we keep his
2956 // previous input in the form.
2957 for ($i = 0; $i < $max; $i++)
2958 {
2959 echo '<tr><td>';
2960 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2961 printSelect ($typelist, "${i}_object_type_id", 0);
2962 echo '</td>';
2963 echo "<td><input type=text size=30 name=${i}_object_name";
2964 if ($keepvalues1 and isset ($name[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2965 echo " value='${name[$i]}'";
2966 echo "></td>";
2967 echo "<td><input type=text size=30 name=${i}_object_label";
2968 if ($keepvalues1 and isset ($label[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2969 echo " value='${label[$i]}'";
2970 echo "></td>";
2971 echo "<td><input type=text size=20 name=${i}_object_asset_no";
2972 if ($keepvalues1 and isset ($asset_no[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2973 echo " value='${asset_no[$i]}'";
2974 echo "></td>";
2975 echo "<td><input type=text size=10 name=${i}_object_barcode";
2976 if ($keepvalues1 and isset ($barcode[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2977 echo " value='${barcode[$i]}'";
2978 echo "></td>";
2979 if ($i == 0)
2980 {
2981 echo "<td valign=top rowspan=${max}>";
2982 renderTagSelect();
2983 echo "</td>\n";
2984 }
2985 echo "</tr>\n";
2986 }
2987 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2988 echo "</form></table>\n";
2989 finishPortlet();
2990
2991 startPortlet ('Same type, same tags');
2992 echo "<form name=veryfastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
2993 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2994 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";