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