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