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