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