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