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