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