bf8f0710a66977efdcb3bd9e1bb3b8b0117d4958
[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['spacer']['path'] = 'pix/pixel.png';
86 $image['spacer']['width'] = 16;
87 $image['spacer']['height'] = 16;
88 $image['next']['path'] = 'pix/tango-go-next.png';
89 $image['next']['width'] = 32;
90 $image['next']['height'] = 32;
91 $image['prev']['path'] = 'pix/tango-go-previous.png';
92 $image['prev']['width'] = 32;
93 $image['prev']['height'] = 32;
94 $image['clear']['path'] = 'pix/tango-edit-clear.png';
95 $image['clear']['width'] = 16;
96 $image['clear']['height'] = 16;
97 $image['CLEAR']['path'] = 'pix/tango-edit-clear-big.png';
98 $image['CLEAR']['width'] = 32;
99 $image['CLEAR']['height'] = 32;
100 $image['save']['path'] = 'pix/tango-document-save.png';
101 $image['save']['width'] = 16;
102 $image['save']['height'] = 16;
103 $image['SAVE']['path'] = 'pix/tango-document-save-big.png';
104 $image['SAVE']['width'] = 32;
105 $image['SAVE']['height'] = 32;
106 $image['create']['path'] = 'pix/tango-document-new.png';
107 $image['create']['width'] = 16;
108 $image['create']['height'] = 16;
109 $image['CREATE']['path'] = 'pix/tango-document-new-big.png';
110 $image['CREATE']['width'] = 32;
111 $image['CREATE']['height'] = 32;
112 $image['DENIED']['path'] = 'pix/tango-dialog-error-big.png';
113 $image['DENIED']['width'] = 32;
114 $image['DENIED']['height'] = 32;
115 $image['apply']['path'] = 'pix/tango-emblem-system.png';
116 $image['apply']['width'] = 16;
117 $image['apply']['height'] = 16;
118 $image['node-collapsed']['path'] = 'pix/node-collapsed.png';
119 $image['node-collapsed']['width'] = 16;
120 $image['node-collapsed']['height'] = 16;
121 $image['node-expanded']['path'] = 'pix/node-expanded.png';
122 $image['node-expanded']['width'] = 16;
123 $image['node-expanded']['height'] = 16;
124 $image['node-expanded-static']['path'] = 'pix/node-expanded-static.png';
125 $image['node-expanded-static']['width'] = 16;
126 $image['node-expanded-static']['height'] = 16;
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&");
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&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 global $root, $pageno, $tabno;
1036 if ($object_id <= 0)
1037 {
1038 showError ('Invalid object_id', __FUNCTION__);
1039 return;
1040 }
1041 showMessageOrError();
1042 startPortlet ('Ports and interfaces');
1043 $ports = getObjectPortsAndLinks ($object_id);
1044 usort($ports, 'sortByName');
1045 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1046 echo "<tr><th>&nbsp;</th><th>Local name</th><th>Visible label</th><th>Port type</th><th>L2 address</th>";
1047 echo "<th>Rem. object</th><th>Rem. port</th><th>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
1048 foreach ($ports as $port)
1049 {
1050 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
1051 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']}'>";
1052 printImageHREF ('delete', 'Unlink and Delete this port');
1053 echo "</a></td>\n";
1054 echo "<td><input type=text name=name value='${port['name']}' size=8></td>";
1055 echo "<td><input type=text name=label value='${port['label']}' size=24></td>";
1056 echo "<td>${port['type']}</td>\n";
1057 echo "<td><input type=text name=l2address value='${port['l2address']}'></td>\n";
1058 if ($port['remote_object_id'])
1059 {
1060 echo "<td><a href='${root}?page=object&object_id=${port['remote_object_id']}'>${port['remote_object_name']}</a></td>";
1061 echo "<td>${port['remote_name']}</td>";
1062 echo "<td><a href='${root}process.php?op=unlinkPort&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=$object_id&port_name=";
1063 echo urlencode ($port['name']);
1064 echo "&remote_port_name=${port['remote_name']}&remote_object_name=${port['remote_object_name']}'>";
1065 printImageHREF ('clear', 'Unlink this port');
1066 echo "</a></td>";
1067 }
1068 elseif (!empty ($port['reservation_comment']))
1069 {
1070 echo "<td><b>Reserved;</b></td>";
1071 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
1072 echo "<td><a href='${root}process.php?op=useup&page=${pageno}&tab=${tabno}&port_id=${port['id']}&object_id=${object_id}'>";
1073 printImageHREF ('clear', 'Use up this port');
1074 echo "</a></td>";
1075 }
1076 else
1077 {
1078 echo "<td>&nbsp;</td><td>&nbsp;</td>";
1079 echo "<td>";
1080 echo "<a href='javascript:;' onclick='window.open(\"${root}link_helper.php?port=${port['id']}&type=${port['type_id']}&object_id=$object_id&port_name=";
1081 echo urlencode ($port['name']);
1082 echo "\",\"findlink\",\"height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=no, status=no, titlebar=no, toolbar=no\");'>";
1083 printImageHREF ('link', 'Link this port');
1084 echo "</a> <input type=text name=reservation_comment>";
1085 echo "</td>\n";
1086 }
1087 echo "<td>";
1088 printImageHREF ('save', 'Save changes', TRUE);
1089 echo "</td></form></tr>\n";
1090 }
1091 printOpFormIntro ('addPort');
1092 echo "<tr><td>";
1093 printImageHREF ('add', '', TRUE, 104);
1094 echo "</td><td><input type=text size=8 name=port_name tabindex=100></td>\n";
1095 echo "<td><input type=text size=24 name=port_label tabindex=101></td>";
1096 echo "<td><select name='port_type_id' tabindex=102>\n";
1097 $types = getPortTypes();
1098 $default_port_type = getConfigVar ('default_port_type');
1099 foreach ($types as $typeid => $typename)
1100 {
1101 echo "<option value='${typeid}'";
1102 if ($typeid == $default_port_type)
1103 echo " selected";
1104 echo ">${typename}</option>\n";
1105 }
1106 echo "</select></td>";
1107 echo "<td><input type=text name=port_l2address tabindex=103></td>\n";
1108 echo "<td colspan=4>&nbsp;</td></tr></form>";
1109 echo "</table><br>\n";
1110 finishPortlet();
1111
1112 startPortlet ('Add/update multiple ports');
1113 printOpFormIntro ('addMultiPorts');
1114 echo 'Format: <select name=format>';
1115 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1116 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
1117 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
1118 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
1119 echo "</select>";
1120 echo 'Default port type: ';
1121 echo "<select name=port_type>\n";
1122 foreach ($types as $typeid => $typename)
1123 {
1124 echo "<option value='${typeid}'";
1125 if ($typeid == $default_port_type)
1126 echo " selected";
1127 echo ">${typename}</option>\n";
1128 }
1129 echo "</select>";
1130 echo "<input type=submit value='Parse output'><br>\n";
1131 echo "<textarea name=input cols=100 rows=50></textarea><br>\n";
1132 echo '</form>';
1133 finishPortlet();
1134 }
1135
1136 function renderIPv4ForObject ($object_id = 0)
1137 {
1138 global $root, $pageno, $tabno, $aat;
1139 if ($object_id <= 0)
1140 {
1141 showError ('Invalid object_id', __FUNCTION__);
1142 return;
1143 }
1144 showMessageOrError();
1145 startPortlet ('Allocations');
1146 $alloclist = getObjectIPv4Allocations ($object_id);
1147 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1148 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1149 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1150 echo '<th colspan=2>network</th><th>routed by</th>';
1151 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1152 foreach ($alloclist as $dottedquad => $alloc)
1153 {
1154 $class = $alloc['addrinfo']['class'];
1155 $netid = getIPv4AddressNetworkId ($dottedquad);
1156 $netinfo = getIPv4NetworkInfo ($netid);
1157 loadIPv4AddrList ($netinfo);
1158 printOpFormIntro ('updIPv4Allocation', array ('ip' => $dottedquad));
1159 echo "<tr class='$class' valign=top><td><a href='${root}process.php?op=delIPv4Allocation&page=${pageno}&tab=${tabno}&ip=${dottedquad}&object_id=$object_id'>";
1160 printImageHREF ('delete', 'Delete this IPv4 address');
1161 echo "</a></td>";
1162 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td>";
1163 echo "<td class=tdleft><a href='${root}?page=ipaddress&ip=${dottedquad}'>${dottedquad}</a>";
1164 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1165 {
1166 if (NULL === $netid)
1167 $suffix = '/??';
1168 else
1169 echo '<small>/' . $netinfo['mask'] . '</small>';
1170 }
1171 echo '&nbsp;' . $aac[$alloc['type']];
1172 if (!empty ($alloc['addrinfo']['name']))
1173 echo '(' . niftyString ($alloc['addrinfo']['name']) . ')';
1174 echo '</td>';
1175 // FIXME: this a copy-and-paste from renderRackObject()
1176 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1177 {
1178 if (NULL === $netid)
1179 echo '<td colspan=2>?</td>';
1180 else
1181 printIPv4NetInfoTDs ($netinfo);
1182 echo "<td class='${secondclass}'>";
1183 // FIXME: These cals are really heavy, replace them with a more appropriate dedicated function.
1184 $newline = '';
1185 foreach (findRouters ($netinfo['addrlist']) as $router)
1186 {
1187 if ($router['id'] == $object_id)
1188 continue;
1189 echo $newline . $router['addr'] . ", <a href='${root}?page=object&object_id=${router['id']}&hl_ipv4_addr=${router['addr']}'>";
1190 echo (empty ($router['iface']) ? '' : $router['iface'] . '@') . $router['dname'] . '</a>';
1191 $routertags = loadRackObjectTags ($router['id']);
1192 if (count ($routertags))
1193 echo '<br><small>' . serializeTags ($routertags, "${root}?page=objects&tab=default&") . '</small>';
1194 $newline = '<br>';
1195 }
1196 echo '</td>';
1197 }
1198 echo '<td>';
1199 printSelect ($aat, 'bond_type', $alloc['type']);
1200 echo "</td><td>";
1201 $prefix = '';
1202 if ($alloc['addrinfo']['reserved'] == 'yes')
1203 {
1204 echo $prefix . '<strong>RESERVED</strong>';
1205 $prefix = '; ';
1206 }
1207 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1208 {
1209 if ($allocpeer['object_id'] == $object_id)
1210 continue;
1211 echo $prefix . "<a href='${root}?page=object&object_id=${allocpeer['object_id']}'>";
1212 if (!empty ($allocpeer['osif']))
1213 echo $allocpeer['osif'] . '@';
1214 echo $allocpeer['object_name'] . '</a>';
1215 $prefix = '; ';
1216 }
1217 echo "</td><td>";
1218 printImageHREF ('save', 'Save changes', TRUE);
1219 echo "</td></form></tr>\n";
1220 }
1221
1222 printOpFormIntro ('addIPv4Allocation');
1223 echo "<tr><td>";
1224 printImageHREF ('add', 'Allocate new address', TRUE, 99);
1225 echo "</td>";
1226 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1227 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
1228 echo "<td colspan=3>&nbsp;</td><td>";
1229 printSelect ($aat, 'bond_type');
1230 echo "</td><td colspan=2>&nbsp;</td></tr></form></table><br>\n";
1231 finishPortlet();
1232
1233 }
1234
1235 // Log structure versions:
1236 // 1: the whole structure is a list of code-message pairs
1237 // 2 and later: there's a "v" field set, which indicates the version
1238 // 2: there's a "m" list set to hold message code and optional arguments
1239 function printLog ($log)
1240 {
1241 switch (TRUE)
1242 {
1243 case !isset ($log['v']):
1244 case $log['v'] == 1:
1245 foreach ($log as $key => $record)
1246 if ($key !== 'v')
1247 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1248 break;
1249 case $log['v'] == 2:
1250 $msginfo = array
1251 (
1252 0 => array ('code' => 'success', 'format' => 'Success: %s'),
1253 1 => array ('code' => 'success', 'format' => '%u new records done, %u already existed'),
1254 2 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully added.'),
1255 3 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully deleted.'),
1256 4 => array ('code' => 'success', 'format' => 'NATv4 rule was successfully updated'),
1257 5 => array ('code' => 'success', 'format' => 'Port %s was added successfully'),
1258 6 => array ('code' => 'success', 'format' => 'Port %s was updated successfully'),
1259 7 => array ('code' => 'success', 'format' => 'Port %s was deleted successfully'),
1260 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with port %s at object %s'),
1261 9 => array ('code' => 'success', 'format' => 'Port %s was successfully unlinked from %s@%s'),
1262 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1263 11 => array ('code' => 'success', 'format' => 'Reservation removed.'),
1264 12 => array ('code' => 'success', 'format' => 'allocation updated'),
1265 13 => array ('code' => 'success', 'format' => 'allocated'),
1266 14 => array ('code' => 'success', 'format' => 'deallocated'),
1267 15 => array ('code' => 'success', 'format' => 'Reset succeeded.'),
1268 16 => array ('code' => 'success', 'format' => 'Update done'),
1269 17 => array ('code' => 'success', 'format' => 'Update(s) succeeded.'),
1270 18 => array ('code' => 'success', 'format' => 'Load balancer was successfully added'),
1271 19 => array ('code' => 'success', 'format' => 'Load balancer was successfully deleted'),
1272 20 => array ('code' => 'success', 'format' => 'Load balancer info was successfully updated'),
1273 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1274 22 => array ('code' => 'success', 'format' => 'Chained %u tags'),
1275 23 => array ('code' => 'success', 'format' => 'IPv4 prefix successfully added'),
1276 24 => array ('code' => 'success', 'format' => 'IPv4 prefix deleted'),
1277 25 => array ('code' => 'success', 'format' => 'IPv4 prefix updated'),
1278 26 => array ('code' => 'success', 'format' => '%u IP address(es) were successfully updated'),
1279 27 => array ('code' => 'success', 'format' => 'IPv4 address updated'),
1280 28 => array ('code' => 'success', 'format' => 'Virtual service was successfully created'),
1281 29 => array ('code' => 'success', 'format' => 'Virtual service was successfully deleted'),
1282 30 => array ('code' => 'success', 'format' => 'Virtual service was successfully updated'),
1283 31 => array ('code' => 'success', 'format' => 'RS pool was successfully created'),
1284 32 => array ('code' => 'success', 'format' => 'RS pool was successfully deleted'),
1285 33 => array ('code' => 'success', 'format' => 'RS pool was successfully updated'),
1286 34 => array ('code' => 'success', 'format' => 'Real server was successfully added'),
1287 35 => array ('code' => 'success', 'format' => 'Real server was successfully deleted'),
1288 36 => array ('code' => 'success', 'format' => 'Real server was successfully updated'),
1289 37 => array ('code' => 'success', 'format' => 'Successfully added %u real servers'),
1290 38 => array ('code' => 'success', 'format' => '%u real server(s) were successfully (de)activated'),
1291 39 => array ('code' => 'success', 'format' => 'User account %s updated.'),
1292 40 => array ('code' => 'success', 'format' => 'User account %s created.'),
1293 41 => array ('code' => 'success', 'format' => 'User account disabled.'),
1294 42 => array ('code' => 'success', 'format' => 'User account enabled.'),
1295 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1296 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1297 45 => array ('code' => 'success', 'format' => "Attribute '%s' created."),
1298 46 => array ('code' => 'success', 'format' => 'Rename successful.'),
1299 47 => array ('code' => 'success', 'format' => 'Attribute was deleted.'),
1300 48 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1301 49 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1302 50 => array ('code' => 'success', 'format' => 'Reduction succeeded.'),
1303 51 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1304 52 => array ('code' => 'success', 'format' => 'Supplement succeeded.'),
1305 53 => array ('code' => 'success', 'format' => 'Chapter was deleted.'),
1306 54 => array ('code' => 'success', 'format' => 'Chapter was updated.'),
1307 55 => array ('code' => 'success', 'format' => 'Chapter was added.'),
1308 56 => array ('code' => 'success', 'format' => 'Update succeeded.'),
1309 57 => array ('code' => 'success', 'format' => 'Reset complete'),
1310 58 => array ('code' => 'success', 'format' => "Successfully deleted tag ."),
1311 59 => array ('code' => 'success', 'format' => "Created tag '%s'."),
1312 60 => array ('code' => 'success', 'format' => "Updated tag '%s'."),
1313 61 => array ('code' => 'success', 'format' => 'Password changed successfully.'),
1314 62 => array ('code' => 'success', 'format' => 'gw: %s'),
1315 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
1316 64 => array ('code' => 'success', 'format' => 'Port %s@%s has been assigned to VLAN %u'),
1317 65 => array ('code' => 'success', 'format' => "Added new rack '%s'"),
1318 66 => array ('code' => 'success', 'format' => "File sent Ok via handler '%s'"),
1319 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1320 68 => array ('code' => 'success', 'format' => "Updated rack '%s'"),
1321
1322 100 => array ('code' => 'error', 'format' => 'Generic error: %s'),
1323 101 => array ('code' => 'error', 'format' => 'Port name cannot be empty'),
1324 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
1325 103 => array ('code' => 'error', 'format' => 'getHashByID() failed'),
1326 104 => array ('code' => 'error', 'format' => "Error updating user account '%s'"),
1327 105 => array ('code' => 'error', 'format' => 'Error enabling user account.'),
1328 106 => array ('code' => 'error', 'format' => 'Error disabling user account.'),
1329 107 => array ('code' => 'error', 'format' => 'Admin account cannot be disabled'),
1330 108 => array ('code' => 'error', 'format' => '%u failures and %u successfull changes.'),
1331 109 => array ('code' => 'error', 'format' => 'Update failed!'),
1332 110 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1333 111 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1334 112 => array ('code' => 'error', 'format' => 'Error adding chapter.'),
1335 113 => array ('code' => 'error', 'format' => 'Error updating chapter.'),
1336 114 => array ('code' => 'error', 'format' => 'Error deleting chapter.'),
1337 115 => array ('code' => 'error', 'format' => 'Error renaming attribute.'),
1338 116 => array ('code' => 'error', 'format' => 'Error creating attribute.'),
1339 117 => array ('code' => 'error', 'format' => 'Error deleting attribute.'),
1340 118 => array ('code' => 'error', 'format' => 'Supplement failed!'),
1341 119 => array ('code' => 'error', 'format' => 'Reduction failed!'),
1342 120 => array ('code' => 'error', 'format' => 'Reset failed!'),
1343 121 => array ('code' => 'error', 'format' => 'commitUpdateObject() failed'),
1344 122 => array ('code' => 'error', 'format' => 'One or more update(s) failed!'),
1345 123 => array ('code' => 'error', 'format' => 'Cannot process submitted data: unknown format code.'),
1346 124 => array ('code' => 'error', 'format' => 'Error removing reservation!'),
1347 125 => array ('code' => 'error', 'format' => "Update failed with error: '%s'"),
1348 126 => array ('code' => 'error', 'format' => 'addRStoRSPool() failed'),
1349 127 => array ('code' => 'error', 'format' => 'Added %u real servers and encountered %u errors'),
1350 128 => array ('code' => 'error', 'format' => 'commitDeleteRS() failed'),
1351 129 => array ('code' => 'error', 'format' => 'commitDeleteLB() failed'),
1352 130 => array ('code' => 'error', 'format' => 'commitDeleteVS() failed'),
1353 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1354 132 => array ('code' => 'error', 'format' => 'invalid protocol'),
1355 133 => array ('code' => 'error', 'format' => 'commitUpdateRS() failed'),
1356 134 => array ('code' => 'error', 'format' => 'commitUpdateLB() failed'),
1357 135 => array ('code' => 'error', 'format' => 'commitUpdateVS() failed'),
1358 136 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1359 137 => array ('code' => 'error', 'format' => 'addLBtoRSPool() failed'),
1360 138 => array ('code' => 'error', 'format' => 'commitDeleteRSPool() failed'),
1361 139 => array ('code' => 'error', 'format' => 'commitUpdateRSPool() failed'),
1362 140 => array ('code' => 'error', 'format' => 'Encountered %u errors, (de)activated %u real servers'),
1363 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u IP address(es)'),
1364 142 => array ('code' => 'error', 'format' => 'executeAutoPorts() failed'),
1365 143 => array ('code' => 'error', 'format' => 'Tried chaining %u tags, but experienced %u errors.'),
1366 144 => array ('code' => 'error', 'format' => "Error deleting tag: '%s'"),
1367 145 => array ('code' => 'error', 'format' => "Invalid tag name '%s'"),
1368 146 => array ('code' => 'error', 'format' => "Tag '%s' (or similar name) already exists"),
1369 147 => array ('code' => 'error', 'format' => "Could not create tag '%s' because of error '%s'"),
1370 148 => array ('code' => 'error', 'format' => "Could not update tag '%s' because of error '%s'"),
1371 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1372 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1373 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1374 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1375 153 => array ('code' => 'error', 'format' => 'Password change failed.'),
1376 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1377 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1378 156 => array ('code' => 'error', 'format' => 'getSwitchVLANs() failed'),
1379 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
1380 158 => array ('code' => 'error', 'format' => 'Ignoring malformed record #%u in form submit'),
1381 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1382 160 => array ('code' => 'error', 'format' => 'Invalid arguments'),
1383 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1384 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
1385 163 => array ('code' => 'error', 'format' => 'Failed to get any response from queryGateway() or the gateway died'),
1386 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
1387 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1388 166 => array ('code' => 'error', 'format' => 'gw: %s'),
1389 167 => array ('code' => 'error', 'format' => 'Could not find port %s'),
1390 168 => array ('code' => 'error', 'format' => 'Port %s is a trunk'),
1391 169 => array ('code' => 'error', 'format' => 'Failed to configure %s, connector returned code %u'),
1392 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1393 171 => array ('code' => 'error', 'format' => "Failed creating rack '%s'. Already exists in this row?"),
1394 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1395 173 => array ('code' => 'error', 'format' => "Invalid IPv4 prefix '%s'"),
1396 174 => array ('code' => 'error', 'format' => 'Bad IPv4 address'),
1397 175 => array ('code' => 'error', 'format' => 'Invalid netmask'),
1398 176 => array ('code' => 'error', 'format' => 'This network already exists'),
1399 177 => array ('code' => 'error', 'format' => 'commitUpdateRack() failed'),
1400
1401 200 => array ('code' => 'warning', 'format' => 'generic warning: %s'),
1402 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1403 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
1404 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1405 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1406 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
1407 );
1408 // Handle the arguments. Is there any better way to do it?
1409 foreach ($log['m'] as $record)
1410 {
1411 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1412 {
1413 echo '<div class=msg_neutral>(this message was lost)</div>';
1414 continue;
1415 }
1416 if (isset ($record['a']))
1417 switch (count ($record['a']))
1418 {
1419 case 1:
1420 $msgtext = sprintf
1421 (
1422 $msginfo[$record['c']]['format'],
1423 $record['a'][0]
1424 );
1425 break;
1426 case 2:
1427 $msgtext = sprintf
1428 (
1429 $msginfo[$record['c']]['format'],
1430 $record['a'][0],
1431 $record['a'][1]
1432 );
1433 break;
1434 case 3:
1435 $msgtext = sprintf
1436 (
1437 $msginfo[$record['c']]['format'],
1438 $record['a'][0],
1439 $record['a'][1],
1440 $record['a'][2]
1441 );
1442 break;
1443 case 4:
1444 default:
1445 $msgtext = sprintf
1446 (
1447 $msginfo[$record['c']]['format'],
1448 $record['a'][0],
1449 $record['a'][1],
1450 $record['a'][2],
1451 $record['a'][3]
1452 );
1453 break;
1454 }
1455 else
1456 $msgtext = $msginfo[$record['c']]['format'];
1457 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1458 }
1459 break;
1460 default:
1461 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1462 break;
1463 }
1464 }
1465
1466 /*
1467 The following conditions must be followed:
1468 1. We can mount onto free atoms only. This means: if any record for an atom
1469 already exists in RackSpace, it can't be used for mounting.
1470 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1471 and either delete them before unmounting or refuse to unmount the object.
1472 */
1473
1474 // We extensively use $_REQUEST in the function.
1475 // FIXME: move related code into ophandler
1476 function renderRackSpaceForObject ($object_id = 0)
1477 {
1478 if ($object_id <= 0)
1479 {
1480 showError ('Invalid object_id', __FUNCTION__);
1481 return;
1482 }
1483 $is_submit = isset ($_REQUEST['got_atoms']);
1484 $is_update = isset ($_REQUEST['rackmulti'][0]);
1485 $info = getObjectInfo ($object_id);
1486 if ($info == NULL)
1487 {
1488 showError ('getObjectInfo() failed', __FUNCTION__);
1489 return;
1490 }
1491 // Always process occupied racks plus racks chosen by user. First get racks with
1492 // already allocated rackspace...
1493 $workingRacksData = getResidentRacksData ($object_id);
1494 if ($workingRacksData === NULL)
1495 {
1496 print_r ($workingRacksData);
1497 showError ('getResidentRacksData() failed', __FUNCTION__);
1498 return;
1499 }
1500
1501 // ...and then add those chosen by user (if any).
1502 if ($is_update)
1503 foreach ($_REQUEST['rackmulti'] as $cand_id)
1504 {
1505 if (!isset ($workingRacksData[$cand_id]))
1506 {
1507 $rackData = getRackData ($cand_id);
1508 if ($rackData == NULL)
1509 {
1510 showError ('getRackData() failed', __FUNCTION__);
1511 return NULL;
1512 }
1513 $workingRacksData[$cand_id] = $rackData;
1514 }
1515 }
1516
1517 // Do it only once...
1518 foreach ($workingRacksData as &$rackData)
1519 applyObjectMountMask ($rackData, $object_id);
1520 // Now we workaround an old caveat: http://bugs.php.net/bug.php?id=37410
1521 unset ($rackData);
1522
1523 // Here we process form submit by trying to save all submitted info to database.
1524 if ($is_submit)
1525 {
1526 $oldMolecule = getMoleculeForObject ($object_id);
1527 $worldchanged = FALSE;
1528 $log = array();
1529 foreach ($workingRacksData as $rack_id => $rackData)
1530 {
1531 $logrecord = processGridForm ($rackData, 'F', 'T', $object_id);
1532 $log[] = $logrecord;
1533 if ($logrecord['code'] != 300)
1534 {
1535 $worldchanged = TRUE;
1536 // Reload our working copy after form processing.
1537 $rackData = getRackData ($rack_id);
1538 if ($rackData == NULL)
1539 $log[] = array ('code' => 500, 'message' => 'Working copy update failed in ', __FUNCTION__);
1540 applyObjectMountMask ($rackData, $object_id);
1541 $workingRacksData[$rack_id] = $rackData;
1542 }
1543 }
1544 if ($worldchanged)
1545 {
1546 // Log a record.
1547 $newMolecule = getMoleculeForObject ($object_id);
1548 $oc = count ($oldMolecule);
1549 $nc = count ($newMolecule);
1550 $omid = $oc ? createMolecule ($oldMolecule) : 'NULL';
1551 $nmid = $nc ? createMolecule ($newMolecule) : 'NULL';
1552 global $remote_username;
1553 $comment = empty ($_REQUEST['comment']) ? 'NULL' : "'${_REQUEST['comment']}'";
1554 $query =
1555 "insert into MountOperation(object_id, old_molecule_id, new_molecule_id, user_name, comment) " .
1556 "values (${object_id}, ${omid}, ${nmid}, '${remote_username}', ${comment})";
1557 global $dbxlink;
1558 $result = $dbxlink->query ($query);
1559 if ($result == NULL)
1560 $log[] = array ('code' => 'error', 'message' => 'SQL query failed during history logging.');
1561 else
1562 $log[] = array ('code' => 'success', 'message' => 'History logged.');
1563 }
1564 printLog ($log);
1565 }
1566
1567 // This is the time for rendering.
1568 global $root, $pageno, $tabno;
1569 echo "<form id='racks' action='${root}'>";
1570 echo "<input type=hidden name=page value='${pageno}'>\n";
1571 echo "<input type=hidden name=tab value='${tabno}'>\n";
1572 echo "<input type=hidden name=object_id value='${object_id}'>\n";
1573 // Main layout starts.
1574 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1575
1576 // Left portlet with rack list.
1577 echo "<td class=pcleft height='1%'>";
1578 startPortlet ('Racks');
1579 $allRacksData = getRacksForRow();
1580 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1581 {
1582 foreach (array_keys ($allRacksData) as $rack_id)
1583 {
1584 $rackData = getRackData ($rack_id);
1585 if ($rackData == NULL)
1586 {
1587 showError ('getRackData() failed', __FUNCTION__);
1588 return NULL;
1589 }
1590 $workingRacksData[$rack_id] = $rackData;
1591 }
1592 foreach ($workingRacksData as &$rackData)
1593 applyObjectMountMask ($rackData, $object_id);
1594 unset ($rackData);
1595 }
1596 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1597 echo "<br>";
1598 echo "<br>";
1599 finishPortlet();
1600 echo "</td>";
1601
1602 // Middle portlet with comment and submit.
1603 echo "<td class=pcleft>";
1604 startPortlet ('Comment');
1605 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1606 echo "<input type=submit value='Save' name=got_atoms>\n";
1607 echo "<br>";
1608 echo "<br>";
1609 finishPortlet();
1610 echo "</td>";
1611
1612 // Right portlet with rendered racks. If this form submit is not final, we have to
1613 // reflect the former state of the grid in current form.
1614 echo "<td class=pcright rowspan=2 height='1%'>";
1615 startPortlet ('Working copy');
1616 echo '<table border=0 cellspacing=10 align=center><tr>';
1617 foreach ($workingRacksData as $rack_id => $rackData)
1618 {
1619 // Order is important here: only original allocation is highlighted.
1620 highlightObject ($rackData, $object_id);
1621 markupAtomGrid ($rackData, 'T');
1622 // If we have a form processed, discard user input and show new database
1623 // contents.
1624 if (!$is_submit and $is_update)
1625 mergeGridFormToRack ($rackData);
1626 echo "<td valign=top>";
1627 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1628 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1629 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1630 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1631 renderAtomGrid ($rackData);
1632 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
1633 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1634 echo "</table></center>\n";
1635 echo '</td>';
1636 }
1637 echo "</tr></table>";
1638 finishPortlet();
1639 echo "</td>\n";
1640
1641 echo "</form>\n";
1642 echo "</tr></table>\n";
1643 }
1644
1645 function renderMolecule ($mdata, $object_id)
1646 {
1647 // sort data out
1648 $rackpack = array();
1649 global $loclist;
1650 foreach ($mdata as $rua)
1651 {
1652 $rack_id = $rua['rack_id'];
1653 $unit_no = $rua['unit_no'];
1654 $atom = $rua['atom'];
1655 if (!isset ($rackpack[$rack_id]))
1656 {
1657 $rackData = getRackData ($rack_id);
1658 for ($i = $rackData['height']; $i > 0; $i--)
1659 for ($locidx = 0; $locidx < 3; $locidx++)
1660 $rackData[$i][$locidx]['state'] = 'F';
1661 $rackpack[$rack_id] = $rackData;
1662 }
1663 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1664 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1665 }
1666 // now we have some racks to render
1667 foreach ($rackpack as $rackData)
1668 {
1669 markAllSpans ($rackData);
1670 echo "<table class=molecule cellspacing=0>\n";
1671 echo "<caption>${rackData['name']}</caption>\n";
1672 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1673 for ($i = $rackData['height']; $i > 0; $i--)
1674 {
1675 echo "<tr><th>$i</th>";
1676 for ($locidx = 0; $locidx < 3; $locidx++)
1677 {
1678 $state = $rackData[$i][$locidx]['state'];
1679 echo "<td class=state_${state}>&nbsp;</td>\n";
1680 }
1681 echo "</tr>\n";
1682 }
1683 echo "</table>\n";
1684 }
1685 }
1686
1687 function renderUnmountedObjectsPortlet ()
1688 {
1689 startPortlet ('Unmounted objects');
1690 $objs = getUnmountedObjects();
1691 if ($objs === NULL)
1692 {
1693 showError ('getUnmountedObjects() failed', __FUNCTION__);
1694 return;
1695 }
1696 global $root, $nextorder;
1697 $order = 'odd';
1698 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1699 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset number</th><th>Barcode</th></tr>';
1700 foreach ($objs as $obj)
1701 {
1702 echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1703 echo "<td>${obj['label']}</td>";
1704 echo "<td>${obj['asset_no']}</td>";
1705 echo "<td>${obj['barcode']}</td></tr>";
1706 $order = $nextorder[$order];
1707 }
1708 echo "</table><br>\n";
1709 finishPortlet();
1710 }
1711
1712 function renderProblematicObjectsPortlet ()
1713 {
1714 startPortlet ('Problematic objects');
1715 $objs = getProblematicObjects();
1716 if ($objs === NULL)
1717 {
1718 showError ('getProblematicObjects() failed', __FUNCTION__);
1719 return;
1720 }
1721 global $root, $nextorder;
1722 $order = 'odd';
1723 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1724 echo '<tr><th>Type</th><th>Common name</th></tr>';
1725 foreach ($objs as $obj)
1726 {
1727 echo "<tr class=row_${order}><td>${obj['objtype_name']}</td>";
1728 echo "<td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></tr>";
1729 $order = $nextorder[$order];
1730 }
1731 echo "</table><br>\n";
1732 finishPortlet();
1733 }
1734
1735 function renderObjectSpace ()
1736 {
1737 global $root, $taglist, $tagtree;
1738 echo "<table border=0 class=objectview>\n";
1739 echo "<tr><td class=pcleft width='50%'>";
1740 startPortlet ('View all by type');
1741 $groupInfo = getObjectGroupInfo();
1742 if ($groupInfo === NULL)
1743 {
1744 showError ('getObjectGroupInfo() failed', __FUNCTION__);
1745 return;
1746 }
1747 if (count ($groupInfo) == 0)
1748 echo "No objects exist in DB";
1749 else
1750 {
1751 echo '<div align=left><ul>';
1752 foreach ($groupInfo as $gi)
1753 echo "<li><a href='${root}?page=objgroup&group_id=${gi['id']}'>${gi['name']}</a> (${gi['count']})</li>";
1754 echo '</ul></div>';
1755 }
1756 finishPortlet();
1757
1758 echo '</td><td class=pcright>';
1759
1760 startPortlet ('View all by tag');
1761 if (count ($taglist) == 0)
1762 echo "No tags exist in DB";
1763 else
1764 renderTagCloud ('object');
1765 finishPortlet();
1766 echo "</td></tr></table>\n";
1767 }
1768
1769 function renderObjectGroup ()
1770 {
1771 global $root, $pageno, $tabno, $nextorder, $taglist, $tagtree;
1772 assertUIntArg ('group_id', __FUNCTION__, TRUE);
1773 $group_id = $_REQUEST['group_id'];
1774 $tagfilter = getTagFilter();
1775 $tagfilter_str = getTagFilterStr ($tagfilter);
1776 echo "<table border=0 class=objectview>\n";
1777 echo "<tr><td class=pcleft width='25%'>";
1778 startPortlet ('change type');
1779 $groupInfo = getObjectGroupInfo();
1780 if ($groupInfo === NULL)
1781 {
1782 showError ('getObjectGroupInfo() failed', __FUNCTION__);
1783 return;
1784 }
1785 if (count ($groupInfo) == 0)
1786 echo "No objects exist in DB";
1787 else
1788 {
1789 echo '<div align=left><ul>';
1790 foreach ($groupInfo as $gi)
1791 {
1792 echo "<li><a href='${root}?page=${pageno}&group_id=${gi['id']}${tagfilter_str}'>";
1793 if ($gi['id'] == $group_id)
1794 echo '<strong>';
1795 echo "${gi['name']}</a>";
1796 if ($gi['id'] == $group_id)
1797 echo '</strong>';
1798 echo " (${gi['count']})";
1799 if ($gi['id'] == $group_id)
1800 echo ' &larr;';
1801 echo "</li>";
1802 }
1803 echo '</ul></div>';
1804 }
1805 finishPortlet();
1806
1807 echo '</td><td class=pcleft>';
1808
1809 startPortlet ('Objects');
1810 $objects = getObjectList ($group_id, $tagfilter, getTFMode());
1811 if ($objects === NULL)
1812 {
1813 showError ('getObjectList() failed', __FUNCTION__);
1814 return;
1815 }
1816 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1817 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Rack</th></tr>';
1818 $order = 'odd';
1819 foreach ($objects as $obj)
1820 {
1821 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1822 $secondclass = 'tdleft port_highlight';
1823 else
1824 $secondclass = 'tdleft';
1825 echo "<tr class=row_${order}><td class='${secondclass}'><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
1826 echo "<td class='${secondclass}'>${obj['label']}</td>";
1827 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
1828 echo "<td class='${secondclass}'>${obj['barcode']}</td>";
1829 if ($obj['rack_id'])
1830 echo "<td class='${secondclass}'><a href='${root}?page=rack&rack_id=${obj['rack_id']}'>${obj['Rack_name']}</a></td>";
1831 else
1832 echo "<td class='${secondclass}'>Unmounted</td>";
1833 echo '</tr>';
1834 $order = $nextorder[$order];
1835 }
1836 echo '</table>';
1837 finishPortlet();
1838
1839 echo "</td><td class=pcright width='25%'>";
1840
1841 renderTagFilterPortlet ($tagfilter, 'object', 'group_id', $group_id);
1842 echo "</td></tr></table>\n";
1843 }
1844
1845 function renderEmptyPortsSelect ($port_id, $type_id)
1846 {
1847 $ports = getEmptyPortsOfType($type_id);
1848 usort($ports, 'sortEmptyPorts');
1849 foreach ($ports as $port)
1850 {
1851 if ($port_id == $port['Port_id'])
1852 continue;
1853 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";
1854 }
1855 }
1856
1857 function renderAllIPv4Allocations ()
1858 {
1859 $addresses = getAllIPv4Allocations();
1860 usort($addresses, 'sortObjectAddressesAndNames');
1861 foreach ($addresses as $address)
1862 {
1863 echo "<option value='${address['ip']}' onclick='getElementById(\"ip\").value=\"${address['ip']}\";'>${address['object_name']} ${address['name']} ${address['ip']}</option>\n";
1864 }
1865 }
1866
1867 // History viewer for history-enabled simple dictionaries.
1868 function renderHistory ($object_type, $object_id)
1869 {
1870 switch ($object_type)
1871 {
1872 case 'row':
1873 $query = "select ctime, user_name, name, deleted, comment from RackRowHistory where id = ${object_id} order by ctime";
1874 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>is deleted?</th><th>rack row comment</th></tr>';
1875 $extra = 4;
1876 break;
1877 case 'rack':
1878 $query =
1879 "select ctime, user_name, rh.name, rh.deleted, d.dict_value as name, rh.height, rh.comment " .
1880 "from RackHistory as rh left join Dictionary as d on rh.row_id = d.dict_key " .
1881 "natural join Chapter " .
1882 "where chapter_name = 'RackRow' and rh.id = ${object_id} order by ctime";
1883 $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>';
1884 $extra = 6;
1885 break;
1886 case 'object':
1887 $query =
1888 "select ctime, user_name, name, label, barcode, asset_no, deleted, has_problems, dict_value, comment " .
1889 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key natural join Chapter " .
1890 "where chapter_name = 'RackObjectType' and id=${object_id} order by ctime";
1891 $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>';
1892 $extra = 9;
1893 break;
1894 default:
1895 showError ("Uknown object type '${object_type}'", __FUNCTION__);
1896 return;
1897 }
1898 global $dbxlink;
1899 $result = $dbxlink->query ($query);
1900 if ($result == NULL)
1901 {
1902 showError ('SQL query failed', __FUNCTION__);
1903 return;
1904 }
1905 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1906 $order = 'odd';
1907 global $nextorder;
1908 echo $header;
1909 while ($row = $result->fetch (PDO::FETCH_NUM))
1910 {
1911 echo "<tr class=row_${order}><td>${row[0]}</td>";
1912 for ($i = 1; $i <= $extra; $i++)
1913 echo "<td>" . $row[$i] . "</td>";
1914 echo "</tr>\n";
1915 $order = $nextorder[$order];
1916 }
1917 echo "</table><br>\n";
1918 }
1919
1920 function renderRackspaceHistory ()
1921 {
1922 global $root, $nextorder, $pageno, $tabno;
1923 $order = 'odd';
1924 $history = getRackspaceHistory();
1925 // Show the last operation by default.
1926 if (isset ($_REQUEST['op_id']))
1927 $op_id = $_REQUEST['op_id'];
1928 elseif (isset ($history[0]['mo_id']))
1929 $op_id = $history[0]['mo_id'];
1930 else $op_id = NULL;
1931
1932 $omid = NULL;
1933 $nmid = NULL;
1934 $object_id = 1;
1935 if ($op_id)
1936 list ($omid, $nmid) = getOperationMolecules ($op_id);
1937
1938 // Main layout starts.
1939 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1940
1941 // Left top portlet with old allocation.
1942 echo "<tr><td class=pcleft>";
1943 startPortlet ('Old allocation');
1944 if ($omid)
1945 {
1946 $oldMolecule = getMolecule ($omid);
1947 renderMolecule ($oldMolecule, $object_id);
1948 }
1949 else
1950 echo "nothing";
1951 finishPortlet();
1952
1953 echo '</td><td class=pcright>';
1954
1955 // Right top portlet with new allocation
1956 startPortlet ('New allocation');
1957 if ($nmid)
1958 {
1959 $newMolecule = getMolecule ($nmid);
1960 renderMolecule ($newMolecule, $object_id);
1961 }
1962 else
1963 echo "nothing";
1964 finishPortlet();
1965
1966 echo '</td></tr><tr><td colspan=2>';
1967
1968 // Bottom portlet with list
1969
1970 startPortlet ('Rackspace allocation history');
1971 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
1972 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";
1973 foreach ($history as $row)
1974 {
1975 if ($row['mo_id'] == $op_id)
1976 $class = 'hl';
1977 else
1978 $class = "row_${order}";
1979 echo "<tr class=${class}><td><a href='${root}?page=${pageno}&tab=${tabno}&op_id=${row['mo_id']}'>${row['ctime']}</a></td>";
1980 echo "<td>${row['user_name']}</td>";
1981 echo "<td>${row['ro_id']}</td><td>${row['objtype_name']}</td><td>${row['name']}</td><td>${row['comment']}</td>\n";
1982 echo "</tr>\n";
1983 $order = $nextorder[$order];
1984 }
1985 echo "</table>\n";
1986 finishPortlet();
1987
1988 echo '</td></tr></table>';
1989 }
1990
1991 function renderIPv4SpaceRecords ($tree, &$tagcache, $baseurl, $level = 1)
1992 {
1993 $self = __FUNCTION__;
1994 foreach ($tree as $item)
1995 {
1996 $total = $item['addrt'];
1997 if (isset ($item['id']))
1998 {
1999 loadIPv4AddrList ($item);
2000 $used = $item['addrc'];
2001 if ($item['symbol'] == 'node-collapsed')
2002 $expandurl = "${baseurl}&eid=" . $item['id'];
2003 elseif ($item['symbol'] == 'node-expanded')
2004 $expandurl = "${baseurl}&eid=" . $item['parent_id'];
2005 else
2006 $expandurl = '';
2007 echo "<tr valign=top>";
2008 printIPv4NetInfoTDs ($item, 'tdleft', $level, $item['symbol'], $expandurl);
2009 echo "<td class=tdcenter>";
2010 renderProgressBar ($total ? $used/$total : 0);
2011 echo "<br><small>${used}/${total}</small></td>";
2012 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2013 printRoutersTD (findRouters ($item['addrlist']), $tagcache);
2014 echo "</tr>";
2015 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2016 $self ($item['kids'], $tagcache, $baseurl, $level + 1);
2017 }
2018 else
2019 {
2020 $used = 0;
2021 echo "<tr valign=top>";
2022 printIPv4NetInfoTDs ($item, 'tdleft sparenetwork', $level, $item['symbol']);
2023 echo "<td class=tdcenter>";
2024 renderProgressBar ($used/$total, 'sparenetwork');
2025 echo "<br><small>${used}/${total}</small></td>";
2026 echo "<td>&nbsp;</td></tr>";
2027 }
2028 }
2029 }
2030
2031 function renderIPv4Space ()
2032 {
2033 global $root, $pageno, $tabno;
2034 $tagfilter = getTagFilter();
2035 $netlist = getIPv4NetworkList ($tagfilter, getTFMode());
2036 $netcount = count ($netlist);
2037 $tree = prepareIPv4Tree ($netlist, isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0);
2038 unset ($netlist);
2039
2040 echo "<table border=0 class=objectview>\n";
2041 echo "<tr><td class=pcleft>";
2042 startPortlet ("networks (${netcount})");
2043 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2044 echo "<tr><th>prefix</th><th>name/tags</th><th>%% used</th>";
2045 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2046 echo "<th>routed by</th>";
2047 echo "</tr>\n";
2048 $tagcache = array();
2049 $baseurl = "${root}?page=${pageno}&tab=${tabno}" . getTagFilterStr ($tagfilter);
2050 renderIPv4SpaceRecords ($tree, $tagcache, $baseurl);
2051 echo "</table>\n";
2052 finishPortlet();
2053 echo '</td><td class=pcright>';
2054 renderTagFilterPortlet ($tagfilter, 'ipv4net');
2055 echo "</td></tr></table>\n";
2056 }
2057
2058 function renderIPv4SLB ()
2059 {
2060 global $root, $page, $nextorder;
2061
2062 startPortlet ('SLB configuration');
2063 echo "<table border=0 width='100%'><tr>";
2064 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2065 echo "<td><h3><a href='${root}?page=${pno}'>" . $page[$pno]['title'] . "</a></h3></td>";
2066 echo '</tr></table>';
2067 finishPortlet();
2068
2069 $summary = getSLBSummary();
2070 startPortlet ('SLB tactical overview');
2071 // A single id-keyed array isn't used here to preserve existing
2072 // order of LBs returned by getSLBSummary()
2073 $lblist = array();
2074 $lbdname = array();
2075 foreach ($summary as $vipdata)
2076 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2077 if (!in_array ($lb_object_id, $lblist))
2078 {
2079 $oi = getObjectInfo ($lb_object_id);
2080 $lbdname[$lb_object_id] = $oi['dname'];
2081 $lblist[] = $lb_object_id;
2082 }
2083 if (!count ($summary))
2084 echo 'none configured';
2085 else
2086 {
2087 $order = 'odd';
2088 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2089 echo "<tr><th>VS&nbsp;&darr; LB&nbsp;&rarr;</th>";
2090 foreach ($lblist as $lb_object_id)
2091 echo "<th><a href='${root}?page=object&tab=default&object_id=${lb_object_id}'>" . $lbdname[$lb_object_id] . "</a></th>";
2092 echo "</tr>\n";
2093 foreach ($summary as $vsid => $vsdata)
2094 {
2095 echo "<tr class=row_${order}><td class=tdleft><a href='$root?page=ipv4vs&tab=default&vs_id=${vsid}'>";
2096 echo buildVServiceName ($vsdata);
2097 echo '</a>';
2098 if (!empty ($vsdata['name']))
2099 echo "<br>${vsdata['name']}";
2100 echo "</td>";
2101 foreach ($lblist as $lb_object_id)
2102 {
2103 echo '<td class=tdleft>';
2104 if (!isset ($vsdata['lblist'][$lb_object_id]))
2105 echo '&nbsp;';
2106 else
2107 {
2108 echo $vsdata['lblist'][$lb_object_id]['size'];
2109 // echo " (<a href='${root}?page=ipv4rsp&pool_id=";
2110 // echo $vsdata['lblist'][$lb_object_id]['id'] . "'>";
2111 // echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2112 }
2113 echo '</td>';
2114 }
2115 echo "</tr>\n";
2116 $order = $nextorder[$order];
2117 }
2118 echo "</table>\n";
2119 }
2120 finishPortlet ();
2121 }
2122
2123 function renderIPv4SpaceEditor ()
2124 {
2125 global $root, $pageno, $tabno;
2126 showMessageOrError();
2127
2128 // IPv4 validator
2129 ?>
2130 <script type="text/javascript">
2131 function init() {
2132 document.add_new_range.range.setAttribute('match', "^\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\.\\d\\d?\\d?\\/\\d\\d?$");
2133
2134 Validate.init();
2135 }
2136 window.onload=init;
2137 </script>
2138 <?php
2139
2140 startPortlet ("Add new");
2141 echo '<table border=0 cellpadding=10 align=center>';
2142 // This form requires a name, so JavaScript validator can find it.
2143 // No printOpFormIntro() hence
2144 echo "<form method=post name='add_new_range' action='${root}process.php'>\n";
2145 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2146 echo "<input type=hidden name=page value='${pageno}'>\n";
2147 echo "<input type=hidden name=tab value='${tabno}'>\n";
2148 // tags column
2149 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2150 renderTagSelect();
2151 echo '</td>';
2152 // inputs column
2153 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=18 class='live-validate' tabindex=1></td>";
2154 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2155 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2156 echo "<tr><td colspan=2>";
2157 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2158 echo '</td></tr>';
2159 echo "</form></table><br><br>\n";
2160 finishPortlet();
2161
2162 $addrspaceList = getIPv4NetworkList();
2163 $netcount = count ($addrspaceList);
2164 if ($netcount)
2165 {
2166 startPortlet ("Manage existing (${netcount})");
2167 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2168 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>&nbsp;</th></tr>";
2169 foreach ($addrspaceList as $netinfo)
2170 {
2171 echo "<form method=post action='${root}process.php?page=${pageno}&tab=${tabno}&op=updIPv4Prefix&id=${netinfo['id']}'>";
2172 echo "<tr valign=top><td><a href='${root}process.php?op=delIPv4Prefix&page=${pageno}&tab=${tabno}&id=${netinfo['id']}'>";
2173 printImageHREF ('delete', 'Delete this IP range');
2174 echo "</a></td>\n<td class=tdleft>${netinfo['ip']}/${netinfo['mask']}</td>";
2175 echo "<td><input type=text name=name size=40 value='${netinfo['name']}'>";
2176 echo "</td><td>";
2177 printImageHREF ('save', 'Save changes', TRUE);
2178 echo "</td></tr></form>\n";
2179 }
2180 echo "</table>";
2181 finishPortlet();
2182 }
2183 }
2184
2185 function renderIPv4Network ($id)
2186 {
2187 global $root, $pageno, $tabno, $aac2;
2188 $netmaskbylen = array
2189 (
2190 32 => '255.255.255.255',
2191 31 => '255.255.255.254',
2192 30 => '255.255.255.252',
2193 29 => '255.255.255.248',
2194 28 => '255.255.255.240',
2195 27 => '255.255.255.224',
2196 26 => '255.255.255.192',
2197 25 => '255.255.255.128',
2198 24 => '255.255.255.0',
2199 23 => '255.255.254.0',
2200 22 => '255.255.252.0',
2201 21 => '255.255.248.0',
2202 20 => '255.255.240.0',
2203 19 => '255.255.224.0',
2204 18 => '255.255.192.0',
2205 17 => '255.255.128.0',
2206 16 => '255.255.0.0',
2207 15 => '255.254.0.0',
2208 14 => '255.252.0.0',
2209 13 => '255.248.0.0',
2210 12 => '255.240.0.0',
2211 11 => '255.224.0.0',
2212 10 => '255.192.0.0',
2213 9 => '255.128.0.0',
2214 8 => '255.0.0.0',
2215 7 => '254.0.0.0',
2216 6 => '252.0.0.0',
2217 5 => '248.0.0.0',
2218 4 => '240.0.0.0',
2219 3 => '224.0.0.0',
2220 2 => '192.0.0.0',
2221 1 => '128.0.0.0'
2222 );
2223 $wildcardbylen = array
2224 (
2225 32 => '0.0.0.0',
2226 31 => '0.0.0.1',
2227 30 => '0.0.0.3',
2228 29 => '0.0.0.7',
2229 28 => '0.0.0.15',
2230 27 => '0.0.0.31',
2231 26 => '0.0.0.63',
2232 25 => '0.0.0.127',
2233 24 => '0.0.0.255',
2234 23 => '0.0.1.255',
2235 22 => '0.0.3.255',
2236 21 => '0.0.7.255',
2237 20 => '0.0.15.255',
2238 19 => '0.0.31.255',
2239 18 => '0.0.63.255',
2240 17 => '0.0.127.255',
2241 16 => '0.0.255.25',
2242 15 => '0.1.255.255',
2243 14 => '0.3.255.255',
2244 13 => '0.7.255.255',
2245 12 => '0.15.255.255',
2246 11 => '0.31.255.255',
2247 10 => '0.63.255.255',
2248 9 => '0.127.255.255',
2249 8 => '0.255.255.255',
2250 7 => '1.255.255.255',
2251 6 => '3.255.255.255',
2252 5 => '7.255.255.255',
2253 4 => '15.255.255.255',
2254 3 => '31.255.255.255',
2255 2 => '63.255.255.255',
2256 1 => '127.255.255.255'
2257 );
2258 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2259 if (isset($_REQUEST['pg']))
2260 $page = $_REQUEST['pg'];
2261 else
2262 $page=0;
2263
2264 $range = getIPv4NetworkInfo ($id);
2265 loadIPv4AddrList ($range);
2266 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2267 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>${range['name']}</h2></td></tr>\n";
2268
2269 echo "<tr><td class=pcleft width='50%'>";
2270 startPortlet ('summary');
2271 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2272 $used = count ($range['addrlist']);
2273 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2274
2275 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2276 renderProgressBar ($used/$total);
2277 echo "&nbsp;${used}/${total}</td></tr>\n";
2278
2279 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2280 echo $netmaskbylen[$range['mask']];
2281 echo "</td></tr>\n";
2282
2283 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2284 echo $wildcardbylen[$range['mask']];
2285 echo "</td></tr>\n";
2286
2287 $routers = findRouters ($range['addrlist']);
2288 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers))
2289 {
2290 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2291 printRoutersTD ($routers);
2292 echo "</tr>\n";
2293 }
2294
2295 printTagTRs ("${root}?page=ipv4space&");
2296 echo "</table><br>\n";
2297 finishPortlet();
2298 echo "</td>\n";
2299
2300 echo "<td class=pcright>";
2301 startPortlet ('details');
2302 $startip = $range['ip_bin'] & $range['mask_bin'];
2303 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2304 $realstartip = $startip;
2305 $realendip = $endip;
2306 $numpages = 0;
2307 if($endip - $startip > $maxperpage)
2308 {
2309 $numpages = ($endip - $startip)/$maxperpage;
2310 $startip = $startip + $page * $maxperpage;
2311 $endip = $startip + $maxperpage-1;
2312 }
2313 echo "<center>";
2314 if ($numpages)
2315 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2316 for ($i=0; $i<$numpages; $i++)
2317 {
2318 if ($i == $page)
2319 echo "<b>$i</b> ";
2320 else
2321 echo "<a href='${root}?page=${pageno}&tab=${tabno}&id=$id&pg=$i'>$i</a> ";
2322 }
2323 echo "</center>";
2324
2325 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2326 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2327
2328
2329 for ($ip = $startip; $ip <= $endip; $ip++) :
2330 if (isset ($_REQUEST['hl_ipv4_addr']) and ip2long ($_REQUEST['hl_ipv4_addr']) == $ip)
2331 $secondstyle = 'tdleft port_highlight';
2332 else
2333 $secondstyle = 'tdleft';
2334 if (!isset ($range['addrlist'][$ip]))
2335 {
2336 echo "<tr><td class=tdleft><a href='${root}?page=ipaddress&ip=" . long2ip ($ip) . "'>" . long2ip ($ip);
2337 echo "</a></td><td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2338 continue;
2339 }
2340 $addr = $range['addrlist'][$ip];
2341 echo "<tr class='${addr['class']}'>";
2342
2343 echo "<td class=tdleft><a href='${root}?page=ipaddress&ip=${addr['ip']}'>${addr['ip']}</a></td>";
2344 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2345 $delim = '';
2346 $prologue = '';
2347 if ( $addr['reserved'] == 'yes')
2348 {
2349 echo "<strong>RESERVED</strong> ";
2350 $delim = '; ';
2351 }
2352 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2353 {
2354 echo $delim . $aac2[$ref['type']];
2355 echo "<a href='${root}?page=object&object_id=${ref['object_id']}";
2356 echo "&hl_ipv4_addr=${addr['ip']}'>";
2357 echo $ref['name'] . (empty ($ref['name']) ? '' : '@');
2358 echo "${ref['object_name']}</a>";
2359 $delim = '; ';
2360 }
2361 if ($delim != '')
2362 {
2363 $delim = '';
2364 $prologue = '<br>';
2365 }
2366 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2367 {
2368 echo $prologue;
2369 $prologue = '';
2370 echo "${delim}<a href='${root}?page=object&object_id=${ref['object_id']}'>";
2371 echo "${ref['object_name']}</a>:<a href='${root}?page=ipv4vs&vs_id=${ref['vs_id']}'>";
2372 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2373 $delim = '; ';
2374 }
2375 if ($delim != '')
2376 {
2377 $delim = '';
2378 $prologue = '<br>';
2379 }
2380 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2381 {
2382 echo $prologue;
2383 $prologue = '';
2384 echo "${delim}&rarr;${ref['rsport']}@<a href='${root}?page=ipv4rsp&pool_id=${ref['rspool_id']}'>";
2385 echo "${ref['rspool_name']}</a>";
2386 $delim = '; ';
2387 }
2388 echo "</td></tr>\n";
2389 endfor;
2390 // end of iteration
2391
2392 echo "</table>";
2393 finishPortlet();
2394 echo "</td></tr></table>\n";
2395 }
2396
2397 function renderIPv4NetworkProperties ($id)
2398 {
2399 showMessageOrError();
2400 $netdata = getIPv4NetworkInfo ($id);
2401 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
2402 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2403 printOpFormIntro ('editRange');
2404 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${netdata['name']}'></tr>";
2405 echo "<tr><td colspan=2 class=tdcenter>";
2406 printImageHREF ('SAVE', 'Save changes', TRUE);
2407 echo "</td></form></tr></table>\n";
2408 }
2409
2410 function renderIPv4Address ($dottedquad)
2411 {
2412 global $root, $aat;
2413 $address = getIPv4Address ($dottedquad);
2414 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2415 echo "<tr><td colspan=2 align=center><h1>${dottedquad}</h1></td></tr>\n";
2416 if (!empty ($address['name']))
2417 echo "<tr><td colspan=2 align=center><h2>${address['name']}</h2></td></tr>\n";
2418
2419 echo "<tr><td class=pcleft>";
2420 startPortlet ('summary');
2421 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2422 echo "<tr><th width='50%' class=tdright>Allocations:</th><td class=tdleft>" . count ($address['allocs']) . "</td></tr>\n";
2423 echo "<tr><th width='50%' class=tdright>Originated NAT connections:</th><td class=tdleft>" . count ($address['outpf']) . "</td></tr>\n";
2424 echo "<tr><th width='50%' class=tdright>Arriving NAT connections:</th><td class=tdleft>" . count ($address['inpf']) . "</td></tr>\n";
2425 echo "<tr><th width='50%' class=tdright>SLB virtual services:</th><td class=tdleft>" . count ($address['lblist']) . "</td></tr>\n";
2426 echo "<tr><th width='50%' class=tdright>SLB real servers:</th><td class=tdleft>" . count ($address['rslist']) . "</td></tr>\n";
2427 printTagTRs();
2428 echo "</table><br>\n";
2429 finishPortlet();
2430 echo "</td>\n";
2431
2432 echo "<td class=pcright>";
2433
2434 if (!empty ($address['class']))
2435 {
2436 startPortlet ('allocations');
2437 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2438 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2439 $class = $address['class'];
2440 // render all allocation records for this address the same way
2441 if ($address['reserved'] == 'yes')
2442 echo "<tr class='${class}'><td colspan=2>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td></tr>";
2443 foreach ($address['allocs'] as $bond)
2444 {
2445 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
2446 $secondclass = 'tdleft port_highlight';
2447 else
2448 $secondclass = 'tdleft';
2449 echo "<tr class='$class'><td class=tdleft><a href='${root}?page=object&object_id=${bond['object_id']}";
2450 echo "&hl_ipv4_addr=${dottedquad}'>${bond['object_name']}</td><td class='${secondclass}'>${bond['name']}</td><td class='${secondclass}'><strong>";
2451 echo $aat[$bond['type']];
2452 echo "</strong></td></tr>\n";
2453 }
2454 echo "</table><br><br>";
2455 finishPortlet();
2456 }
2457
2458 // FIXME: The returned list is structured differently, than we expect it to be. One of the sides
2459 // must be fixed.
2460 if (count ($address['lblist']))
2461 {
2462 startPortlet ('Virtual services (' . count ($address['lblist']) . ')');
2463 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2464 echo "<tr><th>VS</th><th>name</th></tr>\n";
2465 foreach ($address['lblist'] as $vsinfo)
2466 {
2467 echo "<tr><td class=tdleft><a href='${root}?page=ipv4vs&vs_id=${vsinfo['vs_id']}'>";
2468 echo buildVServiceName ($vsinfo) . "</a></td><td class=tdleft>";
2469 echo $vsinfo['name'] . "</td></tr>\n";
2470 }
2471 echo "</table><br><br>";
2472 finishPortlet();
2473 }
2474
2475 if (count ($address['rslist']))
2476 {
2477 startPortlet ('Real servers (' . count ($address['rslist']) . ')');
2478 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2479 echo "<tr><th>&nbsp;</th><th>port</th><th>RS pool</th></tr>\n";
2480 foreach ($address['rslist'] as $rsinfo)
2481 {
2482 echo "<tr><td>";
2483 if ($rsinfo['inservice'] == 'yes')
2484 printImageHREF ('inservice', 'in service');
2485 else
2486 printImageHREF ('notinservice', 'NOT in service');
2487 echo "</td><td class=tdleft>${rsinfo['rsport']}</td><td class=tdleft><a href='${root}?page=ipv4rsp&pool_id=${rsinfo['rspool_id']}'>";
2488 echo $rsinfo['rspool_name'] . "</a></td></tr>\n";
2489 }
2490 echo "</table><br><br>";
2491 finishPortlet();
2492 }
2493
2494 if (count ($address['outpf']))
2495 {
2496 startPortlet ('departing NAT rules');
2497 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2498 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2499 foreach ($address['outpf'] as $rule)
2500 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2501 echo "</table>";
2502 finishPortlet();
2503 }
2504
2505 if (count ($address['inpf']))
2506 {
2507 startPortlet ('arriving NAT rules');
2508 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
2509 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
2510 foreach ($address['inpf'] as $rule)
2511 echo "<tr><td>${rule['proto']}</td><td>${rule['localip']}:${rule['localport']}</td><td>${rule['remoteip']}:${rule['remoteport']}</td><td>${rule['description']}</td></tr>";
2512 echo "</table>";
2513 finishPortlet();
2514 }
2515
2516 echo "</td></tr>";
2517 echo "</table>\n";
2518 }
2519
2520 function renderIPv4AddressProperties ($dottedquad)
2521 {
2522 showMessageOrError();
2523 $address = getIPv4Address ($dottedquad);
2524 echo "<center><h1>$dottedquad</h1></center>\n";
2525
2526 startPortlet ('update');
2527 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
2528 printOpFormIntro ('editAddress');
2529 echo "<tr><td class='tdright'>Name:</td><td class='tdleft'><input type=text name=name size=20 value='${address['name']}'></tr>";
2530 echo "<td class='tdright'>Reserved:</td><td class='tdleft'><input type=checkbox name=reserved size=20 ";
2531 echo ($address['reserved']=='yes') ? 'checked' : '';
2532 echo "></tr><tr><td colspan=2 class='tdcenter'>";
2533 printImageHREF ('SAVE', 'Save changes', TRUE);
2534 echo "</td></form></tr></table>\n";
2535 finishPortlet();
2536 if (empty ($address['name']) and $address['reserved'] == 'no')
2537 return;
2538
2539 startPortlet ('release');
2540 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => ''));
2541 echo "<input type=submit value='release'></form>";
2542 finishPortlet();
2543 }
2544
2545 function renderIPv4AddressAllocations ($dottedquad)
2546 {
2547 showMessageOrError();
2548 global $pageno, $tabno, $root, $aat;
2549
2550 $address = getIPv4Address ($dottedquad);
2551 $class = $address['class'];
2552 echo "<center><h1>${dottedquad}</h1></center>\n";
2553 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2554 echo "<tr><th>&nbsp;</th><th>object</th><th>OS interface</th><th>allocation type</th><th>&nbsp;</th></tr>\n";
2555
2556 if ($address['reserved'] == 'yes')
2557 echo "<tr class='${class}'><td colspan=3>&nbsp;</td><td class=tdleft><strong>RESERVED</strong></td><td>&nbsp;</td></tr>";
2558 foreach ($address['allocs'] as $bond)
2559 {
2560 echo "<tr class='$class'>";
2561 printOpFormIntro ('updIPv4Allocation', array ('object_id' => $bond['object_id']));
2562 echo "<td><a href='${root}process.php?op=delIPv4Allocation&page=${pageno}&tab=${tabno}&ip=${dottedquad}&object_id=${bond['object_id']}'>";
2563 printImageHREF ('delete', 'Unallocate address');
2564 echo "</a></td>";
2565 echo "<td><a href='${root}?page=object&object_id=${bond['object_id']}&hl_ipv4_addr=${dottedquad}'>${bond['object_name']}</td>";
2566 echo "<td><input type='text' name='bond_name' value='${bond['name']}' size=10></td><td>";
2567 printSelect ($aat, 'bond_type', $bond['type']);
2568 echo "</td><td>";
2569 printImageHREF ('save', 'Save changes', TRUE);
2570 echo "</td></form></tr>\n";
2571 }
2572 printOpFormIntro ('addIPv4Allocation');
2573 echo "<td>";
2574 printImageHREF ('add', 'new allocation', TRUE);
2575 echo "</td><td><select name='object_id'>";
2576
2577 foreach (explode (',', getConfigVar ('IPV4_PERFORMERS')) as $type)
2578 foreach (getNarrowObjectList ($type) as $object)
2579 echo "<option value='${object['id']}'>${object['dname']}</option>";
2580
2581 echo "</select></td><td><input type='text' name='bond_name' value='' size=10></td><td>";
2582 printSelect ($aat, 'bond_type');
2583 echo "</td><td>&nbsp;</td></form></tr>";
2584 echo "</table><br><br>";
2585
2586 }
2587
2588 function renderNATv4ForObject ($object_id = 0)
2589 {
2590 global $pageno, $tabno, $root;
2591
2592 $info = getObjectInfo ($object_id);
2593 $forwards = getNATv4ForObject ($object_id);
2594 $alloclist = getObjectIPv4Allocations ($object_id);
2595 showMessageOrError();
2596 echo "<center><h2>locally performed NAT</h2></center>";
2597
2598 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2599 echo "<tr><th></th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Comment</th><th>&nbsp;</th></tr>\n";
2600
2601 foreach ($forwards['out'] as $pf)
2602 {
2603 $class = 'trerror';
2604 $osif = '';
2605 if (isset ($alloclist [$pf['localip']]))
2606 {
2607 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
2608 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
2609 }
2610
2611 echo "<tr class='$class'>";
2612 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}'>";
2613 printImageHREF ('delete', 'Delete NAT rule');
2614 echo "</a></td>";
2615 echo "<td>${pf['proto']}/${osif}<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}";
2616 if (!empty ($pf['local_addr_name']))
2617 echo ' (' . $pf['local_addr_name'] . ')';
2618 echo "</td>";
2619 echo "<td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2620
2621 $address = getIPv4Address ($pf['remoteip']);
2622
2623 echo "<td class='description'>";
2624 if (count ($address['allocs']))
2625 foreach ($address['allocs'] as $bond)
2626 echo "<a href='${root}?page=object&tab=default&object_id=${bond['object_id']}'>${bond['object_name']}(${bond['name']})</a> ";
2627 elseif (!empty ($pf['remote_addr_name']))
2628 echo '(' . $pf['remote_addr_name'] . ')';
2629 printOpFormIntro
2630 (
2631 'updNATv4Rule',
2632 array
2633 (
2634 'localip' => $pf['localip'],
2635 'localport' => $pf['localport'],
2636 'remoteip' => $pf['remoteip'],
2637 'remoteport' => $pf['remoteport'],
2638 'proto' => $pf['proto']
2639 )
2640 );
2641 echo "</td><td class='description'>";
2642 echo "<input type='text' name='description' value='${pf['description']}'></td><td>";
2643 printImageHREF ('save', 'Save changes', TRUE);
2644 echo "</td></form></tr>";
2645 }
2646 printOpFormIntro ('addNATv4Rule');
2647 echo "<tr align='center'><td>";
2648 printImageHREF ('add', 'Add new NAT rule', TRUE);
2649 echo '</td><td>';
2650 printSelect (array ('TCP' => 'TCP', 'UDP' => 'UDP'), 'proto');
2651 echo "<select name='localip' tabindex=1>";
2652
2653 foreach ($alloclist as $dottedquad => $alloc)
2654 {
2655 $name = empty ($alloc['addrinfo']['name']) ? '' : (' (' . niftyString ($alloc['addrinfo']['name']) . ')');
2656 $osif = empty ($alloc['osif']) ? '' : ($alloc['osif'] . ': ');
2657 echo "<option value='${dottedquad}'>${osif}${dottedquad}${name}</option>";
2658 }
2659
2660 echo "</select>:<input type='text' name='localport' size='4' tabindex=2></td>";
2661 echo "<td><input type='text' name='remoteip' id='remoteip' size='10' tabindex=3>";
2662 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\");'>";
2663 printImageHREF ('find', 'Find object');
2664 echo "</a>";
2665 echo ":<input type='text' name='remoteport' size='4' tabindex=4></td><td></td>";
2666 echo "<td colspan=1><input type='text' name='description' size='20' tabindex=5></td><td>&nbsp;</td></tr>";
2667 echo "</form>";
2668
2669 echo "</table><br><br>";
2670
2671 echo "<center><h2>arriving NAT connections</h2></center>";
2672 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
2673 echo "<tr><th></th><th>Source</th><th>Source objects</th><th>Target</th><th>Description</th></tr>\n";
2674
2675 foreach ($forwards['in'] as $pf)
2676 {
2677 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}'>";
2678 printImageHREF ('delete', 'Delete NAT rule');
2679 echo "</a></td>";
2680 echo "<td>${pf['proto']}/<a href='${root}?page=ipaddress&tab=default&ip=${pf['localip']}'>${pf['localip']}</a>:${pf['localport']}</td>";
2681 echo "<td class='description'><a href='${root}?page=object&tab=default&object_id=${pf['object_id']}'>${pf['object_name']}</a>";
2682 echo "</td><td><a href='${root}?page=ipaddress&tab=default&ip=${pf['remoteip']}'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
2683 echo "<td class='description'>${pf['description']}</td></tr>";
2684 }
2685
2686 echo "</table><br><br>";
2687 }
2688
2689 // FIXME: move related code away into ophandler(s)
2690 function renderAddMultipleObjectsForm ()
2691 {
2692 global $root, $pageno, $tabno, $nextorder;
2693
2694 $type_id = array();
2695 $global_type_id = 0;
2696 $name = array();
2697 $asset_no = array();
2698 $keepvalues1 = $keepvalues2 = FALSE;
2699 $log = array();
2700 // Look for current submit.
2701 if (isset ($_REQUEST['got_fast_data']))
2702 {
2703 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
2704 $keepvalues1 = TRUE;
2705 $max = getConfigVar ('MASSCOUNT');
2706 for ($i = 0; $i < $max; $i++)
2707 {
2708 if (!isset ($_REQUEST["${i}_object_type_id"]))
2709 {
2710 $log[] = array ('code' => 'error', 'message' => "Submitted form is invalid at line " . $i + 1);
2711 break;
2712 }
2713 assertUIntArg ("${i}_object_type_id", __FUNCTION__, TRUE);
2714 assertStringArg ("${i}_object_name", __FUNCTION__, TRUE);
2715 assertStringArg ("${i}_object_label", __FUNCTION__, TRUE);
2716 assertStringArg ("${i}_object_asset_no", __FUNCTION__, TRUE);
2717 assertStringArg ("${i}_object_barcode", __FUNCTION__, TRUE);
2718 $type_id[$i] = $_REQUEST["${i}_object_type_id"];
2719 // Save user input for possible rendering.
2720 $name[$i] = $_REQUEST["${i}_object_name"];
2721 $label[$i] = $_REQUEST["${i}_object_label"];
2722 $asset_no[$i] = $_REQUEST["${i}_object_asset_no"];
2723 $barcode[$i] = $_REQUEST["${i}_object_barcode"];
2724
2725 // It's better to skip silently, than to print a notice.
2726 if ($type_id[$i] == 0)
2727 continue;
2728 if (commitAddObject ($name[$i], $label[$i], $barcode[$i], $type_id[$i], $asset_no[$i], $taglist) === TRUE)
2729 $log[] = array ('code' => 'success', 'message' => "Added new object '${name[$i]}'");
2730 else
2731 $log[] = array ('code' => 'error', 'message' => __FUNCTION__ . ': commitAddObject() failed');
2732 }
2733 }
2734 elseif (isset ($_REQUEST['got_very_fast_data']))
2735 {
2736 $taglist = isset ($_REQUEST['taglist']) ? $_REQUEST['taglist'] : array();
2737 $keepvalues2 = TRUE;
2738 assertUIntArg ('global_type_id', __FUNCTION__, TRUE);
2739 assertStringArg ('namelist', __FUNCTION__, TRUE);
2740 $global_type_id = $_REQUEST['global_type_id'];
2741 if ($global_type_id == 0)
2742 {
2743 if (!empty ($_REQUEST['namelist']))
2744 $log[] = array ('code' => 'error', 'message' => 'Object type is not selected, check the form below');
2745 else
2746 $log[] = array ('code' => 'error', 'message' => 'Empty form has been ignored. Cheers.');
2747 }
2748 else
2749 {
2750 // The name extractor below was stolen from ophandlers.php:addMultiPorts()
2751 $names1 = explode ('\n', $_REQUEST['namelist']);
2752 $names2 = array();
2753 foreach ($names1 as $line)
2754 {
2755 $parts = explode ('\r', $line);
2756 reset ($parts);
2757 if (empty ($parts[0]))
2758 continue;
2759 else
2760 $names2[] = rtrim ($parts[0]);
2761 }
2762 foreach ($names2 as $cname)
2763 if (commitAddObject ($cname, '', '', $global_type_id, '', $taglist) === TRUE)
2764 $log[] = array ('code' => 'success', 'message' => "Added new object '${cname}'");
2765 else
2766 $log[] = array ('code' => 'error', 'message' => "Could not add '${cname}'");
2767 }
2768 }
2769 printLog ($log);
2770
2771 // Render a form for the next.
2772 $typelist = getObjectTypeList();
2773 $typelist[0] = 'select type...';
2774
2775 startPortlet ('Distinct types, same tags');
2776 $max = getConfigVar ('MASSCOUNT');
2777 echo "<form name=fastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
2778 echo '<table border=0 align=center>';
2779 echo "<tr><th>Object type</th><th>Common name</th><th>Visible label</th>";
2780 echo "<th>Asset tag</th><th>Barcode</th><th>Tags</th></tr>\n";
2781 // If a user forgot to select object type on input, we keep his
2782 // previous input in the form.
2783 for ($i = 0; $i < $max; $i++)
2784 {
2785 echo '<tr><td>';
2786 // Don't employ DEFAULT_OBJECT_TYPE to avoid creating ghost records for pre-selected empty rows.
2787 printSelect ($typelist, "${i}_object_type_id", 0);
2788 echo '</td>';
2789 echo "<td><input type=text size=30 name=${i}_object_name";
2790 if ($keepvalues1 and isset ($name[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2791 echo " value='${name[$i]}'";
2792 echo "></td>";
2793 echo "<td><input type=text size=30 name=${i}_object_label";
2794 if ($keepvalues1 and isset ($label[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2795 echo " value='${label[$i]}'";
2796 echo "></td>";
2797 echo "<td><input type=text size=20 name=${i}_object_asset_no";
2798 if ($keepvalues1 and isset ($asset_no[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2799 echo " value='${asset_no[$i]}'";
2800 echo "></td>";
2801 echo "<td><input type=text size=10 name=${i}_object_barcode";
2802 if ($keepvalues1 and isset ($barcode[$i]) and (!isset ($type_id[$i]) or $type_id[$i] == 0))
2803 echo " value='${barcode[$i]}'";
2804 echo "></td>";
2805 if ($i == 0)
2806 {
2807 echo "<td valign=top rowspan=${max}>";
2808 renderTagSelect();
2809 echo "</td>\n";
2810 }
2811 echo "</tr>\n";
2812 }
2813 echo "<tr><td class=submit colspan=5><input type=submit name=got_fast_data value='Go!'></td></tr>\n";
2814 echo "</form></table>\n";
2815 finishPortlet();
2816
2817 startPortlet ('Same type, same tags');
2818 echo "<form name=veryfastform method=post action='${root}?page=${pageno}&tab=${tabno}'>";
2819 echo "<table border=0 align=center><tr><th>names</th><th>type</th></tr>";
2820 echo "<tr><td rowspan=3><textarea name=namelist cols=40 rows=25>\n";
2821 if ($keepvalues2 and $global_type_id == 0)
2822 echo $_REQUEST['namelist'];
2823 echo "</textarea></td><td valign=top>";
2824 printSelect ($typelist, "global_type_id", getConfigVar ('DEFAULT_OBJECT_TYPE'));
2825 echo "</td></tr>";
2826 echo "<tr><th>Tags</th></tr>";
2827 echo "<tr><td valign=top>";
2828 renderTagSelect();
2829 echo "</td></tr>";
2830 echo "<tr><td colspan=2><input type=submit name=got_very_fast_data value='Go!'></td></tr></table>\n";
2831 echo "</form>\n";
2832 finishPortlet();
2833 }
2834
2835 function printGreeting ()
2836 {
2837 global $remote_username, $accounts, $root;
2838 $account = $accounts[$remote_username];
2839 $person = empty ($account['user_realname']) ? $account['user_name'] : $account['user_realname'];
2840 echo "Hello, ${person}. This is RackTables " . CODE_VERSION . ". Click <a href='${root}?logout'>here</a> to logout.";
2841 }
2842
2843 function renderSearchResults ()
2844 {
2845 global $remote_username, $root;
2846 $terms = trim ($_REQUEST['q']);
2847 if (empty ($terms))
2848 {
2849 showError ('Search string cannot be empty.', __FUNCTION__);
2850 return;
2851 }
2852 if (!permitted ('objects', 'default'))
2853 {
2854 showError ('You are not authorized for viewing information about objects.', __FUNCTION__);
2855 return;
2856 }
2857 $nhits = 0;
2858 // If we search for L2 address, we can either find one or find none.
2859 if
2860 (
2861 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
2862 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
2863 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
2864 // STP bridge ID: bridge priotity + port MAC address. Cut off first 4 chars and look for MAC address.
2865 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)
2866 )
2867 // Search for L2 address.
2868 {
2869 $terms = str_replace ('.', '', $terms);
2870 $terms = str_replace (':', '', $terms);
2871 $terms = substr ($terms, -12);
2872 $result = searchByl2address ($terms);
2873 if ($result !== NULL)
2874 {
2875 $nhits++;
2876 $lasthit = 'port';
2877 $summary['port'][] = $result;
2878 }
2879 }
2880 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))
2881 // Search for IP address.
2882 {
2883 if (NULL !== getIPv4AddressNetworkId ($terms))
2884 {
2885 $nhits++;
2886 $lasthit = 'ipv4addressbydq';
2887 $summary['ipv4addressbydq'][] = $terms;
2888 }
2889 }
2890 else
2891 // Search for objects, addresses, networks, virtual services and RS pools by their description.
2892 {
2893 $tmp = getObjectSearchResults ($terms);
2894 if (count ($tmp))
2895 {
2896 $nhits += count ($tmp);
2897 $lasthit = 'object';
2898 $summary['object'] = $tmp;
2899 }
2900 $tmp = getIPv4AddressSearchResult ($terms);
2901 if (count ($tmp))
2902 {
2903 $nhits += count ($tmp);
2904 $lasthit = 'ipv4addressbydescr';
2905 $summary['ipv4addressbydescr'] = $tmp;
2906 }
2907 $tmp = getIPv4PrefixSearchResult ($terms);
2908 if (count ($tmp))
2909 {
2910 $nhits += count ($tmp);
2911 $lasthit = 'ipv4network';
2912 $summary['ipv4network'] = $tmp;
2913 }
2914 $tmp = getIPv4RSPoolSearchResult ($terms);
2915 if (count ($tmp))
2916 {
2917 $nhits += count ($tmp);
2918 $lasthit = 'ipv4rspool';
2919 $summary['ipv4rspool'] = $tmp;
2920 }
2921 $tmp = getIPv4VServiceSearchResult ($terms);
2922 if (count ($tmp))
2923 {
2924 $nhits += count ($tmp);
2925 $lasthit = 'ipv4vs';
2926 $summary['ipv4vs'] = $tmp;
2927 }
2928 $tmp = getAccountSearchResult ($terms);
2929 if (count ($tmp))
2930 {
2931 $nhits += count ($tmp);
2932 $lasthit = 'user';
2933 $summary['user'] = $tmp;
2934 }
2935 }
2936 if ($nhits == 0)
2937 echo "<center><h2>Nothing found for '${terms}'</h2></center>";
2938 elseif ($nhits == 1)
2939 {
2940 $record = current ($summary[$lasthit]);
2941 switch ($lasthit)
2942 {
2943 case 'port':
2944 echo "<script language='Javascript'>document.location='${root}?page=object";
2945 echo "&hl_port_id=" . $record['port_id'];
2946 echo "&object_id=" . $record['object_id'] . "';//</script>";
2947 break;
2948 case 'ipv4addressbydq':
2949 $parentnet = getIPv4AddressNetworkId ($record);
2950 if ($parentnet !== NULL)
2951 echo "<script language='Javascript'>document.location='${root}?page=iprange&tab=default&id=${parentnet}&hl_ipv4_addr=${record}';//</script>";
2952 else
2953 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record}';//</script>";
2954 break;
2955 case 'ipv4addressbydescr':
2956 $parentnet = getIPv4AddressNetworkId ($record['ip']);
2957 if ($parentnet !== NULL)
2958 echo "<script language='Javascript'>document.location='${root}?page=iprange&tab=default&id=${parentnet}&hl_ipv4_addr=${record['ip']}';//</script>";
2959 else
2960 echo "<script language='Javascript'>document.location='${root}?page=ipaddress&ip=${record['ip']}';//</script>";
2961 break;
2962 case 'ipv4network':
2963 echo "<script language='Javascript'>document.location='${root}?page=iprange";
2964 echo "&id=${record['id']}";
2965 echo "';//</script>";
2966 break;
2967 case 'object':
2968 echo "<script language='Javascript'>document.location='${root}?page=object&object_id=${record['id']}';//</script>";
2969 break;
2970 case 'ipv4rspool':
2971 echo "<script language='Javascript'>document.location='${root}?page=ipv4rsp&pool_id=${record['pool_id']}';//</script>";
2972 break;
2973 case 'ipv4vs':
2974 echo "<script language='Javascript'>document.location='${root}?page=ipv4vs&vs_id=${record['id']}';//</script>";
2975 break;
2976 case 'user':
2977 echo "<script language='Javascript'>document.location='${root}?page=user&user_id=${record['user_id']}';//</script>";
2978 break;
2979 }
2980 return;
2981 }
2982 else
2983 {
2984 global $nextorder;
2985 $order = 'odd';
2986 echo "<center><h2>${nhits} result(s) found for '${terms}'</h2></center>";
2987 foreach ($summary as $where => $what)
2988 switch ($where)
2989 {
2990 case 'object':
2991 startPortlet ("<a href='${root}?page=objects'>Objects</a>");
2992 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2993 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>barcode</th></tr>';
2994 foreach ($what as $obj)
2995 {
2996 echo "<tr class=row_${order}><td><a href=\"${root}?page=object&object_id=${obj['id']}\">${obj['dname']}</a></td>";
2997 echo "<td>${obj['label']}</td>";
2998 echo "<td>${obj['asset_no']}</td>";
2999 echo "<td>${obj['barcode']}</td></tr>";
3000 $order = $nextorder[$order];
3001 }
3002 echo '</table>';
3003 finishPortlet();
3004 break;
3005 case 'ipv4network':
3006 startPortlet ("<a href='${root}?page=ipv4space'>IPv4 networks</a>");
3007 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
3008 echo '<tr><th>network</th><th>name/tags</th></tr>';
3009 foreach ($what as $netinfo)
3010 {
3011 echo "<tr class=row_${order} valign=top>";
3012 printIPv4NetInfoTDs ($netin