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