r4348 remove all instances of formatTimestamp()
[racktables] / wwwroot / inc / interface.php
1 <?php
2 /*
3 *
4 * This file contains frontend functions for RackTables.
5 *
6 */
7
8 require_once 'ajax-interface.php';
9
10 // Interface function's special.
11 $nextorder['odd'] = 'even';
12 $nextorder['even'] = 'odd';
13
14 // address allocation type
15 $aat = array
16 (
17 'regular' => 'Connected',
18 'virtual' => 'Loopback',
19 'shared' => 'Shared',
20 'router' => 'Router',
21 );
22 // address allocation code, IPv4 addresses and objects view
23 $aac = array
24 (
25 'regular' => '',
26 'virtual' => '<strong>L</strong>',
27 'shared' => '<strong>S</strong>',
28 'router' => '<strong>R</strong>',
29 );
30 // address allocation code, IPv4 networks view
31 $aac2 = array
32 (
33 'regular' => '',
34 'virtual' => '<strong>L:</strong>',
35 'shared' => '<strong>S:</strong>',
36 'router' => '<strong>R:</strong>',
37 );
38
39 $vtdecoder = array
40 (
41 'ondemand' => '',
42 'compulsory' => 'P',
43 # 'alien' => 'NT',
44 );
45
46 $vtoptions = array
47 (
48 'ondemand' => 'auto',
49 'compulsory' => 'permanent',
50 # 'alien' => 'never touch',
51 );
52
53 // This may be populated later onsite, report rendering function will use it.
54 // See the $systemreport for structure.
55 $localreports = array();
56
57 $CodePressMap = array
58 (
59 'sql' => 'sql',
60 'php' => 'php',
61 'html' => 'html',
62 'css' => 'css',
63 'js' => 'javascript',
64 );
65
66 $attrtypes = array
67 (
68 'uint' => '[U] unsigned integer',
69 'float' => '[F] floating point',
70 'string' => '[S] string',
71 'dict' => '[D] dictionary record'
72 );
73
74 function renderInterfaceHTML ($pageno, $tabno, $payload)
75 {
76 ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
77 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
78 <head><title><?php echo getTitle ($pageno); ?></title>
79 <?php printPageHeaders(); ?>
80 </head>
81 <body>
82 <table border=0 cellpadding=0 cellspacing=0 width="100%" height="100%" class="maintable">
83 <tr class="mainheader"><td>
84 <table width="100%" cellspacing="0" cellpadding="2" border="0">
85 <tr>
86 <td valign=top><a href="http://racktables.org/"><?php printImageHREF ('logo'); ?></a></td>
87 <td valign=top><div class=greeting><?php printGreeting(); ?></div></td>
88 </tr>
89 </table>
90 </td></tr>
91 <tr><td class="menubar">
92 <table border="0" width="100%" cellpadding="3" cellspacing="0">
93 <tr><?php showPathAndSearch ($pageno); ?></tr>
94 </table>
95 </td></tr>
96 <tr><td><?php showTabs ($pageno, $tabno); ?></td></tr>
97 <tr><td><?php showMessageOrError(); ?></td></tr>
98 <tr><td><?php echo $payload; ?></td></tr>
99 </table>
100 </body>
101 </html>
102 <?php
103 }
104
105 // Main menu.
106 function renderIndexItem ($ypageno) {
107 global $page;
108 if (permitted($ypageno)) {
109 $title = isset ($page[$ypageno]['title']) ? $page[$ypageno]['title'] : dynamic_title_decoder ($ypageno);
110 if (is_array ($title))
111 $title = $title['name'];
112 print " <td>\n";
113 print " <h1><a href='".makeHref(array('page'=>$ypageno))."'>".$title."<br>\n";
114 printImageHREF ($ypageno);
115 print "</a></h1>\n";
116 print " </td>\n";
117 } else {
118 print " <td>&nbsp;</td>\n";
119 }
120 }
121
122 function renderIndex ()
123 {
124 global $indexlayout;
125 ?>
126 <table border=0 cellpadding=0 cellspacing=0 width='100%'>
127 <tr>
128 <td>
129 <div style='text-align: center; margin: 10px; '>
130 <table width='100%' cellspacing=0 cellpadding=20 class=mainmenu border=0>
131 <?php
132 foreach ($indexlayout as $row)
133 {
134 echo '<tr>';
135 foreach ($row as $column)
136 if ($column === NULL)
137 echo '<td>&nbsp;</td>';
138 else
139 renderIndexItem ($column);
140 echo '</tr>';
141 }
142 ?>
143 </table>
144 </div>
145 </td>
146 </tr>
147 </table>
148 <?php
149 }
150
151 function renderRackspace ()
152 {
153 $found_racks = array();
154 $rows = array();
155 $cellfilter = getCellFilter();
156 $rackCount = 0;
157 foreach (getRackRows() as $row_id => $row_name) {
158 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
159 $found_racks = array_merge($found_racks, $rackList);
160 $rows[] = array(
161 'row_id' => $row_id,
162 'row_name' => $row_name,
163 'racks' => $rackList
164 );
165 $rackCount += count($rackList);
166 }
167
168 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
169 renderCellFilterPortlet ($cellfilter, 'rack', $found_racks);
170 echo '</td><td class=pcright>';
171
172 if (! renderEmptyResults($cellfilter, 'racks', $rackCount))
173 {
174 echo '<table border=0 cellpadding=10 cellpadding=1>';
175 // generate thumb gallery
176 global $nextorder;
177 $rackwidth = getRackImageWidth();
178 // Zero value effectively disables the limit.
179 $maxPerRow = getConfigVar ('RACKS_PER_ROW');
180 $order = 'odd';
181 foreach ($rows as $row)
182 {
183 $row_id = $row['row_id'];
184 $row_name = $row['row_name'];
185 $rackList = $row['racks'];
186
187 if (!count ($rackList) and count ($cellfilter['expression']))
188 continue;
189 $rackListIdx = 0;
190 echo "<tr class=row_${order}><th class=tdleft>";
191 echo "<a href='".makeHref(array('page'=>'row', 'row_id'=>$row_id))."${cellfilter['urlextra']}'>";
192 echo "${row_name}</a></th><td><table border=0 cellspacing=5><tr>";
193 if (!count ($rackList))
194 echo "<td>(empty row)</td>";
195 else
196 foreach ($rackList as $rack)
197 {
198 if ($rackListIdx > 0 and $maxPerRow > 0 and $rackListIdx % $maxPerRow == 0)
199 {
200 echo '</tr></table></tr>';
201 echo "<tr class=row_${order}><th class=tdleft>${row_name} (continued)";
202 echo "</th><td><table border=0 cellspacing=5><tr>";
203 }
204 echo "<td align=center><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
205 echo "<img border=0 width=${rackwidth} height=";
206 echo getRackImageHeight ($rack['height']);
207 echo " title='${rack['height']} units'";
208 echo "src='?module=image&img=minirack&rack_id=${rack['id']}'>";
209 echo "<br>${rack['name']}</a></td>";
210 $rackListIdx++;
211 }
212 $order = $nextorder[$order];
213 echo "</tr></table></tr>\n";
214 }
215 echo "</table>\n";
216 }
217 echo "</td></tr></table>\n";
218 }
219
220 function renderRackspaceRowEditor ()
221 {
222 function printNewItemTR ()
223 {
224 printOpFormIntro ('addRow');
225 echo "<tr><td>";
226 printImageHREF ('create', 'Add new row', TRUE);
227 echo "</td><td><input type=text name=name tabindex=100></td><td>";
228 printImageHREF ('create', 'Add new row', TRUE, 101);
229 echo "</td></tr></form>";
230 }
231 startPortlet ('Rows');
232 echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
233 echo "<tr><th>&nbsp;</th><th>Name</th><th>&nbsp;</th></tr>\n";
234 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
235 printNewItemTR();
236 foreach (getRackRows() as $row_id => $row_name)
237 {
238 echo "<tr><td>";
239 if ($rc = count (listCells ('rack', $row_id)))
240 printImageHREF ('nodestroy', "${rc} rack(s) here");
241 else
242 {
243 echo "<a href=\"".makeHrefProcess(array('op'=>'delete', 'row_id'=>$row_id))."\">";
244 printImageHREF ('destroy', 'Delete row');
245 echo "</a>";
246 }
247 printOpFormIntro ('updateRow', array ('row_id' => $row_id));
248 echo "</td><td><input type=text name=name value='${row_name}'></td><td>";
249 printImageHREF ('save', 'Save changes', TRUE);
250 echo "</form></td></tr>\n";
251 }
252 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
253 printNewItemTR();
254 echo "</table><br>\n";
255 finishPortlet();
256 }
257
258 function renderRow ($row_id)
259 {
260 $rowInfo = getRackRowInfo ($row_id);
261 $cellfilter = getCellFilter();
262 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
263 // Main layout starts.
264 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
265
266 // Left portlet with row information.
267 echo "<tr><td class=pcleft>";
268 startPortlet ($rowInfo['name']);
269 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
270 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
271 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
272 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
273 renderProgressBar (getRSUforRackRow ($rackList));
274 echo "</td></tr>\n";
275 echo "</table><br>\n";
276 finishPortlet();
277 renderCellFilterPortlet ($cellfilter, 'rack', $rackList, 'row_id', $row_id);
278
279 echo "</td><td class=pcright>";
280
281 global $nextorder;
282 $rackwidth = getRackImageWidth() * getConfigVar ('ROW_SCALE');
283 // Maximum number of racks per row is proportionally less, but at least 1.
284 $maxPerRow = max (floor (getConfigVar ('RACKS_PER_ROW') / getConfigVar ('ROW_SCALE')), 1);
285 $rackListIdx = 0;
286 $order = 'odd';
287 startPortlet ('Racks');
288 echo "<table border=0 cellspacing=5 align='center'><tr>";
289 foreach ($rackList as $rack)
290 {
291 if ($rackListIdx % $maxPerRow == 0)
292 {
293 if ($rackListIdx > 0)
294 echo '</tr>';
295 echo '<tr>';
296 }
297 echo "<td align=center class=row_${order}><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
298 echo "<img border=0 width=${rackwidth} height=" . (getRackImageHeight ($rack['height']) * getConfigVar ('ROW_SCALE'));
299 echo " title='${rack['height']} units'";
300 echo "src='?module=image&img=minirack&rack_id=${rack['id']}'>";
301 echo "<br>${rack['name']}</a></td>";
302 $order = $nextorder[$order];
303 $rackListIdx++;
304 }
305 echo "</tr></table>\n";
306 finishPortlet();
307 echo "</td></tr></table>";
308 }
309
310 // This function renders rack as HTML table.
311 function renderRack ($rack_id, $hl_obj_id = 0)
312 {
313 $rackData = spotEntity ('rack', $rack_id);
314 amplifyCell ($rackData);
315 markAllSpans ($rackData);
316 if ($hl_obj_id > 0)
317 highlightObject ($rackData, $hl_obj_id);
318 markupObjectProblems ($rackData);
319 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
320 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
321 echo "<center><table border=0><tr valign=middle>";
322 echo "<td><h2><a href='".makeHref(array('page'=>'row', 'row_id'=>$rackData['row_id']))."'>${rackData['row_name']}</a> :</h2></td>";
323 // FIXME: use 'bypass'?
324 if ($prev_id != NULL)
325 {
326 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$prev_id))."'>";
327 printImageHREF ('prev', 'previous rack');
328 echo "</a></td>";
329 }
330 echo "<td><h2><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rackData['id']))."'>${rackData['name']}</a></h2></td>";
331 if ($next_id != NULL)
332 {
333 echo "<td><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$next_id))."'>";
334 printImageHREF ('next', 'next rack');
335 echo "</a></td>";
336 }
337 echo "</h2></td></tr></table>\n";
338 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
339 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
340 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
341 addAtomCSS();
342 for ($i = $rackData['height']; $i > 0; $i--)
343 {
344 echo "<tr><th>${i}</th>";
345 for ($locidx = 0; $locidx < 3; $locidx++)
346 {
347 if (isset ($rackData[$i][$locidx]['skipped']))
348 continue;
349 $state = $rackData[$i][$locidx]['state'];
350 echo "<td class='atom state_${state}";
351 if (isset ($rackData[$i][$locidx]['hl']))
352 echo $rackData[$i][$locidx]['hl'];
353 echo "'";
354 if (isset ($rackData[$i][$locidx]['colspan']))
355 echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
356 if (isset ($rackData[$i][$locidx]['rowspan']))
357 echo ' rowspan=' . $rackData[$i][$locidx]['rowspan'];
358 echo ">";
359 switch ($state)
360 {
361 case 'T':
362 $objectData = spotEntity ('object', $rackData[$i][$locidx]['object_id']);
363 if (strlen ($objectData['asset_no']))
364 $prefix = "<div title='${objectData['asset_no']}";
365 else
366 $prefix = "<div title='no asset tag";
367 // Don't tell about label, if it matches common name.
368 $body = '';
369 if ($objectData['name'] != $objectData['label'] and strlen ($objectData['label']))
370 $body = ", visible label is \"${objectData['label']}\"";
371 // Display list of child objects, if any
372 $objectChildren = getEntityRelatives ('children', 'object', $objectData['id']);
373 if (count($objectChildren) > 0)
374 {
375 foreach ($objectChildren as $child)
376 $childNames[] = $child['name'];
377 natsort($childNames);
378 $suffix = sprintf(", contains %s'>", implode(', ', $childNames));
379 }
380 else
381 $suffix = "'>";
382 echo $prefix . $body . $suffix;
383 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$objectData['id']))."'>${objectData['dname']}</a></div>";
384 break;
385 case 'A':
386 echo '<div title="This rackspace does not exist">&nbsp;</div>';
387 break;
388 case 'F':
389 echo '<div title="Free rackspace">&nbsp;</div>';
390 break;
391 case 'U':
392 echo '<div title="Problematic rackspace, you CAN\'T mount here">&nbsp;</div>';
393 break;
394 default:
395 echo '<div title="No data">&nbsp;</div>';
396 break;
397 }
398 echo '</td>';
399 }
400 echo "</tr>\n";
401 }
402 echo "</table></center>\n";
403 }
404
405 function renderNewRackForm ($row_id)
406 {
407 startPortlet ('Add one');
408 printOpFormIntro ('addRack', array ('got_data' => 'TRUE'));
409 echo '<table border=0 align=center>';
410 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
411 if ($defh == 0)
412 $defh = '';
413 echo "<tr><th class=tdright>Rack name (*):</th><td class=tdleft><input type=text name=rack_name tabindex=1></td>";
414 echo "<td rowspan=4>Assign tags:<br>";
415 renderNewEntityTags ('rack');
416 echo "</td></tr>\n";
417 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";
418 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment tabindex=3></td></tr>\n";
419 echo "<tr><td class=submit colspan=2>";
420 printImageHREF ('CREATE', 'Add', TRUE);
421 echo "</td></tr></table></form>";
422 finishPortlet();
423
424 startPortlet ('Add many');
425 printOpFormIntro ('addRack', array ('got_mdata' => 'TRUE'));
426 echo '<table border=0 align=center>';
427 $defh = getConfigVar ('DEFAULT_RACK_HEIGHT');
428 if ($defh == 0)
429 $defh = '';
430 echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=rack_height2 value='${defh}'></td>";
431 echo "<td rowspan=3 valign=top>Assign tags:<br>";
432 renderNewEntityTags ('rack');
433 echo "</td></tr>\n";
434 echo "<tr><th class=tdright>Rack names (*):</th><td class=tdleft><textarea name=rack_names cols=40 rows=25></textarea></td></tr>\n";
435 echo "<tr><td class=submit colspan=2>";
436 printImageHREF ('CREATE', 'Add', TRUE);
437 echo '</form></table>';
438 finishPortlet();
439 }
440
441 function renderEditObjectForm ($object_id)
442 {
443 global $pageno, $virtual_obj_types;
444 $object = spotEntity ('object', $object_id);
445 startPortlet ();
446 printOpFormIntro ('update');
447
448 // static attributes
449 echo '<table border=0 cellspacing=0 cellpadding=3 align=center>';
450 echo "<tr><td>&nbsp;</td><th colspan=2><h2>Attributes</h2></th></tr>";
451 // baseline info
452 echo "<tr><td>&nbsp;</td><th class=tdright>Common name:</th><td class=tdleft><input type=text name=object_name value='${object['name']}'></td></tr>\n";
453 if (in_array($object['objtype_id'], $virtual_obj_types))
454 {
455 echo "<input type=hidden name=object_label value=''>\n";
456 echo "<input type=hidden name=object_asset_no value=''>\n";
457 }
458 else
459 {
460 echo "<tr><td>&nbsp;</td><th class=tdright>Visible label:</th><td class=tdleft><input type=text name=object_label value='${object['label']}'></td></tr>\n";
461 echo "<tr><td>&nbsp;</td><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=object_asset_no value='${object['asset_no']}'></td></tr>\n";
462 }
463 // parent selection
464 if (rackObjectTypeMayHaveParent ($object['objtype_id']))
465 {
466 $parents = getEntityRelatives ('parents', 'object', $object_id);
467 foreach ($parents as $link_id => $parent_details)
468 {
469 if (!isset($label))
470 $label = count($parents) > 1 ? 'Containers:' : 'Container:';
471 echo "<tr><td>&nbsp;</td>";
472 echo "<th class=tdright>${label}</th><td class=tdleft>";
473 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$parent_details['entity_id']))."'>${parent_details['name']}</a>";
474 echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
475 echo "<a href='".
476 makeHrefProcess(array(
477 'op'=>'unlinkEntities',
478 'link_id'=>$link_id,
479 'object_id'=>$object_id,
480 'page='=>'object',
481 'tab'=>'edit')).
482 "'>";
483 printImageHREF ('cut', 'Unlink container');
484 echo "</a>";
485 echo "</td></tr>\n";
486 $label = '&nbsp;';
487 }
488 echo "<tr><td>&nbsp;</td>";
489 echo "<th class=tdright>Select container:</th><td class=tdleft>";
490 echo "<span";
491 $helper_args = array ('object_id' => $object_id);
492 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
493 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
494 echo " onclick='window.open(\"" . makeHrefForHelper ('objlist', $helper_args);
495 echo "\",\"findlink\",\"${popup_args}\");'>";
496 printImageHREF ('attach', 'Select a container');
497 echo "</span></td></tr>\n";
498 }
499 // optional attributes
500 $values = getAttrValues ($object_id);
501 echo '<input type=hidden name=num_attrs value=' . count($values) . ">\n";
502 if (count($values) > 0)
503 {
504 $i = 0;
505 foreach ($values as $record)
506 {
507 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
508 echo '<tr><td>';
509 if (strlen ($record['value']))
510 {
511 echo "<a href='".makeHrefProcess(array('op'=>'clearSticker', 'object_id'=>$object_id, 'attr_id'=>$record['id']))."'>";
512 printImageHREF ('clear', 'Clear value');
513 echo '</a>';
514 }
515 else
516 echo '&nbsp;';
517 echo '</td>';
518 echo "<th class=sticker>${record['name']}:</th><td class=tdleft>";
519 switch ($record['type'])
520 {
521 case 'uint':
522 case 'float':
523 case 'string':
524 echo "<input type=text name=${i}_value value='${record['value']}'>";
525 break;
526 case 'dict':
527 $chapter = readChapter ($record['chapter_id'], 'o');
528 $chapter[0] = '-- NOT SET --';
529 $chapter = cookOptgroups ($chapter, $object['objtype_id'], $record['key']);
530 printNiftySelect ($chapter, array ('name' => "${i}_value"), $record['key']);
531 break;
532 }
533 echo "</td></tr>\n";
534 $i++;
535 }
536 }
537 echo "<tr><td>&nbsp;</td><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
538 if ($object['has_problems'] == 'yes')
539 echo ' checked';
540 echo "></td></tr>\n";
541 echo "<tr><td>&nbsp;</td><th class=tdright>Actions:</th><td class=tdleft>";
542 echo "<a href='".
543 makeHrefProcess(array('op'=>'deleteObject', 'page'=>'depot', 'tab'=>'addmore', 'object_id'=>$object_id)).
544 "' onclick=\"javascript:return confirm('Are you sure you want to delete the object?')\">" . getImageHREF ('destroy', 'Delete object') . "</a>";
545 echo "&nbsp;";
546 echo "<a href='".
547 makeHrefProcess(array ('op'=>'resetObject', 'page' => 'object', 'tab' => 'edit', 'object_id' => $object_id)).
548 "' onclick=\"javascript:return confirm('Are you sure you want to reset most of object properties?')\">" . getImageHREF ('clear', 'Reset (cleanup) object') . "</a>";
549 echo "</td></tr>\n";
550 echo "<tr><td colspan=3><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
551
552 echo "<tr><th class=submit colspan=3>";
553 printImageHREF ('SAVE', 'Save changes', TRUE);
554 echo "</form></th></tr></table>\n";
555 finishPortlet();
556
557 echo '<table border=0 width=100%><tr><td>';
558 startPortlet ('history');
559 renderHistory ($pageno, $object_id);
560 finishPortlet();
561 echo '</td></tr></table>';
562 }
563
564 // This is a clone of renderEditObjectForm().
565 function renderEditRackForm ($rack_id)
566 {
567 global $pageno;
568 $rack = spotEntity ('rack', $rack_id);
569 amplifyCell ($rack);
570
571 startPortlet ('Rack attributes');
572 printOpFormIntro ('updateRack');
573 echo '<table border=0 align=center>';
574 echo "<tr><th class=tdright>Rack row:</th><td class=tdleft>";
575 printSelect (getRackRows(), array ('name' => 'rack_row_id'), $rack['row_id']);
576 echo "</td></tr>\n";
577 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=rack_name value='${rack['name']}'></td></tr>\n";
578 echo "<tr><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=rack_height value='${rack['height']}'></td></tr>\n";
579 echo "<tr><th class=tdright>Comment:</th><td class=tdleft><input type=text name=rack_comment value='${rack['comment']}'></td></tr>\n";
580 if (count ($rack['mountedObjects']) == 0)
581 {
582 echo "<tr><th class=tdright>Actions:</th><td class=tdleft><a href='".
583 makeHrefProcess(array('op'=>'deleteRack', 'rack_id'=>$rack_id)).
584 "' onclick=\"javascript:return confirm('Are you sure you want to delete the rack?')\">Delete rack</a></td></tr>\n";
585 }
586 echo "<tr><td class=submit colspan=2>";
587 printImageHREF ('SAVE', 'Save changes', TRUE);
588 echo "</td></tr>\n";
589 echo '</form></table><br>';
590 finishPortlet();
591
592 startPortlet ('History');
593 renderHistory ($pageno, $rack_id);
594 finishPortlet();
595 }
596
597 // used by renderGridForm() and renderRackPage()
598 function renderRackInfoPortlet ($rackData)
599 {
600 startPortlet ('summary');
601 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
602 echo "<tr><th width='50%' class=tdright>Rack row:</th><td class=tdleft>${rackData['row_name']}</td></tr>\n";
603 echo "<tr><th width='50%' class=tdright>Name:</th><td class=tdleft>${rackData['name']}</td></tr>\n";
604 echo "<tr><th width='50%' class=tdright>Height:</th><td class=tdleft>${rackData['height']}</td></tr>\n";
605 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
606 renderProgressBar (getRSUforRack ($rackData));
607 echo "</td></tr>\n";
608 echo "<tr><th width='50%' class=tdright>Objects:</th><td class=tdleft>";
609 echo count ($rackData['mountedObjects']);
610 echo "</td></tr>\n";
611 printTagTRs ($rackData, makeHref(array('page'=>'rackspace', 'tab'=>'default'))."&");
612 if (strlen ($rackData['comment']))
613 echo "<tr><th width='50%' class=tdright>Comment:</th><td class=tdleft>${rackData['comment']}</td></tr>\n";
614 echo '</table>';
615 finishPortlet();
616 }
617
618 // This is a universal editor of rack design/waste.
619 // FIXME: switch to using printOpFormIntro()
620 function renderGridForm ($rack_id, $filter, $header, $submit, $state1, $state2)
621 {
622 $rackData = spotEntity ('rack', $rack_id);
623 amplifyCell ($rackData);
624 $filter ($rackData);
625 markupObjectProblems ($rackData);
626
627 // Render the result whatever it is.
628 // Main layout.
629 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
630 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
631
632 // Left column with information portlet.
633 echo "<tr><td class=pcleft height='1%' width='50%'>";
634 renderRackInfoPortlet ($rackData);
635 echo "</td>\n";
636 echo "<td class=pcright>";
637
638 // Grid form.
639 startPortlet ($header);
640 addJS ('js/racktables.js');
641 echo "<center>\n";
642 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
643 echo "<tr><th width='10%'>&nbsp;</th>";
644 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
645 echo "<th width='50%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
646 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
647 printOpFormIntro ('updateRack');
648 markupAtomGrid ($rackData, $state2);
649 renderAtomGrid ($rackData);
650 echo "</table></center>\n";
651 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
652 finishPortlet();
653 echo "</td></tr></table>\n";
654 }
655
656 function renderRackDesign ($rack_id)
657 {
658 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
659 }
660
661 function renderRackProblems ($rack_id)
662 {
663 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
664 }
665
666 function startPortlet ($title = '')
667 {
668 echo "<div class=portlet><h2>${title}</h2>";
669 }
670
671 function finishPortlet ()
672 {
673 echo "</div>\n";
674 }
675
676 function renderRackObject ($object_id)
677 {
678 global $nextorder, $aac, $virtual_obj_types;
679 $info = spotEntity ('object', $object_id);
680 // FIXME: employ amplifyCell() instead of calling loader functions directly
681 amplifyCell ($info);
682 // Main layout starts.
683 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
684 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
685 // left column with uknown number of portlets
686 echo "<tr><td class=pcleft>";
687 startPortlet ('summary');
688 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
689 if (strlen ($info['name']))
690 echo "<tr><th width='50%' class=tdright>Common name:</th><td class=tdleft>${info['name']}</td></tr>\n";
691 // FIXME: don't call spotEntity() each time, do it once in the beginning.
692 elseif (considerConfiguredConstraint ($info, 'NAMEWARN_LISTSRC'))
693 echo "<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>\n";
694 echo "<tr><th width='50%' class=tdright>Object type:</th><td class=tdleft><a href='";
695 echo makeHref (array (
696 'page' => 'depot',
697 'tab' => 'default',
698 'cfe' => '{$typeid_' . $info['objtype_id'] . '}'
699 ));
700 echo "'>" . decodeObjectType ($info['objtype_id'], 'o') . '</a></td></tr>';
701 if (strlen ($info['asset_no']))
702 echo "<tr><th width='50%' class=tdright>Asset tag:</th><td class=tdleft>${info['asset_no']}</td></tr>\n";
703 // FIXME: ditto
704 elseif (considerConfiguredConstraint ($info, 'ASSETWARN_LISTSRC'))
705 echo "<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>\n";
706 if (strlen ($info['label']))
707 echo "<tr><th width='50%' class=tdright>Visible label:</th><td class=tdleft>${info['label']}</td></tr>\n";
708 if ($parents = getEntityRelatives ('parents', 'object', $object_id))
709 {
710 foreach ($parents as $parent)
711 {
712 if (!isset($label))
713 $label = count($parents) > 1 ? 'Containers:' : 'Container:';
714 echo "<tr><th width='50%' class=tdright>${label}</th><td class=tdleft>";
715 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$parent['entity_id']))."'>${parent['name']}</a>";
716 echo "</td></tr>\n";
717 $label = '&nbsp;';
718 }
719 unset ($label);
720 }
721 if ($children = getEntityRelatives ('children', 'object', $object_id))
722 {
723 foreach ($children as $child)
724 {
725 if (!isset($label))
726 $label = 'Contains:';
727 echo "<tr><th width='50%' class=tdright>${label}</th><td class=tdleft>";
728 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$child['entity_id']))."'>${child['name']}</a>";
729 echo "</td></tr>\n";
730 $label = '&nbsp;';
731 }
732 }
733 if ($info['has_problems'] == 'yes')
734 echo "<tr><td colspan=2 class=msg_error>Has problems</td></tr>\n";
735 foreach (getAttrValues ($object_id) as $record)
736 if (strlen ($record['value']))
737 {
738 echo "<tr><th width='50%' class=sticker>${record['name']}:</th><td class=sticker>" .
739 formatAttributeValue ($record) .
740 "</td></tr>\n";
741 }
742 printTagTRs
743 (
744 $info,
745 makeHref
746 (
747 array
748 (
749 'page'=>'depot',
750 'tab'=>'default',
751 'andor' => 'and',
752 'cfe' => '{$typeid_' . $info['objtype_id'] . '}',
753 )
754 )."&"
755 );
756 echo "</table><br>\n";
757 finishPortlet();
758
759 if (strlen ($info['comment']))
760 {
761 startPortlet ('Comment');
762 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
763 finishPortlet ();
764 }
765
766 if (count ($logrecords = getLogRecordsForObject ($_REQUEST['object_id'])))
767 {
768 startPortlet ('log records');
769 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='100%'>";
770 $order = 'odd';
771 foreach (getLogRecordsForObject ($_REQUEST['object_id']) as $row)
772 {
773 echo "<tr class=row_${order} valign=top>";
774 echo '<td class=tdleft>' . $row['date'] . '<br>' . $row['user'] . '</td>';
775 echo '<td class="slbconf rsvtext">' . string_insert_hrefs (htmlspecialchars ($row['content'], ENT_NOQUOTES)) . '</td>';
776 echo '</tr>';
777 $order = $nextorder[$order];
778 }
779 echo '</table>';
780 finishPortlet();
781 }
782
783 switchportInfoJS ($object_id); // load JS code to make portnames interactive
784 renderFilesPortlet ('object', $object_id);
785
786 if (count ($info['ports']))
787 {
788 startPortlet ('ports and links');
789 $hl_port_id = 0;
790 if (isset ($_REQUEST['hl_port_id']))
791 {
792 assertUIntArg ('hl_port_id');
793 $hl_port_id = $_REQUEST['hl_port_id'];
794 addAutoScrollScript ("port-$hl_port_id");
795 }
796 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>";
797 echo '<tr><th class=tdleft>Local name</th><th class=tdleft>Visible label</th>';
798 echo '<th class=tdleft>Interface</th><th class=tdleft>L2 address</th>';
799 echo '<th class=tdcenter colspan=2>Remote object and port</th>';
800 echo '<th class=tdleft>Cable ID</th></tr>';
801 foreach ($info['ports'] as $port)
802 {
803 echo '<tr';
804 if ($hl_port_id == $port['id'])
805 echo ' class=port_highlight';
806 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
807 echo "><td class='tdleft' NOWRAP><a name='port-${port['id']}' class='interactive-portname nolink $a_class'>${port['name']}</a></td>";
808 echo "<td class=tdleft>${port['label']}</td>";
809 echo "<td class=tdleft>" . formatPortIIFOIF ($port) . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
810 if ($port['remote_object_id'])
811 {
812 $remote_object = spotEntity ('object', $port['remote_object_id']);
813 echo "<td class=tdleft><a href='".makeHref(array('page'=>'object', 'object_id'=>$port['remote_object_id'], 'hl_port_id'=>$port['remote_id']))."'>${remote_object['dname']}</a></td>";
814 echo "<td class=tdleft>${port['remote_name']}</td>";
815 echo "<td class='tdleft rsvtext'>${port['cableid']}</td>";
816 }
817 elseif (strlen ($port['reservation_comment']))
818 {
819 echo "<td class=tdleft><b>Reserved:</b></td>";
820 echo "<td class='tdleft rsvtext'>${port['reservation_comment']}</td><td>&nbsp;</td>";
821 }
822 else
823 echo '<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>';
824 echo "</tr>";
825 }
826 echo "</table><br>";
827 finishPortlet();
828 }
829
830 if (count ($info['ipv4']) + count ($info['ipv6']))
831 {
832 startPortlet ('IP addresses');
833 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
834 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
835 echo "<tr><th>OS interface</th><th>IP address</th><th>network</th><th>routed by</th><th>peers</th></tr>\n";
836 else
837 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
838 $hl_ip_addr = '';
839 if (isset ($_REQUEST['hl_ipv6_addr']))
840 {
841 if ($hl_ipv6 = assertIPv6Arg ('hl_ipv6_addr'))
842 $hl_ip_addr = $hl_ipv6->format();
843 }
844 elseif (isset ($_REQUEST['hl_ipv4_addr']))
845 $hl_ip_addr = $_REQUEST['hl_ipv4_addr'];
846 if ($hl_ip_addr)
847 addAutoScrollScript ("ip-$hl_ip_addr");
848
849 // group IP allocations by interface name instead of address family
850 $allocs_by_iface = array();
851 foreach (array ('ipv4', 'ipv6') as $ip_v)
852 foreach ($info[$ip_v] as $dottedquad => $alloc)
853 $allocs_by_iface[$alloc['osif']][$dottedquad] = $alloc;
854
855 // sort allocs array by portnames
856 foreach (sortPortList ($allocs_by_iface) as $iface_name => $alloclist)
857 {
858 $is_first_row = TRUE;
859 foreach ($alloclist as $dottedquad => $alloc)
860 {
861 if ($alloc['addrinfo']['version'] == 6)
862 {
863 $addr_page_name = 'ipv6address';
864 $ipv6_address = new IPv6Address ($dottedquad);
865 $dottedquad = $ipv6_address->format();
866 if ($netid = getIPv6AddressNetworkId ($ipv6_address))
867 {
868 $netinfo = spotEntity ('ipv6net', $netid);
869 loadIPv6AddrList ($netinfo);
870 }
871 }
872 else
873 {
874 $addr_page_name = 'ipaddress';
875 if ($netid = getIPv4AddressNetworkId ($dottedquad))
876 {
877 $netinfo = spotEntity ('ipv4net', $netid);
878 loadIPv4AddrList ($netinfo);
879 }
880 }
881 $address_name = niftyString ($alloc['addrinfo']['name']);
882 $class = $alloc['addrinfo']['class'];
883 $secondclass = ($hl_ip_addr == $dottedquad) ? 'tdleft port_highlight' : 'tdleft';
884 echo "<tr class='${class}' valign=top>";
885
886 // display iface name (common cell for both address families)
887 if ($is_first_row)
888 {
889 $rowspan = count ($alloclist) > 1 ? 'rowspan="' . count ($alloclist) . '"' : '';
890 echo "<td class=tdleft $rowspan>$iface_name</td>";
891 $is_first_row = FALSE;
892 }
893 echo "<td class='${secondclass}'>";
894 if (NULL !== $netid)
895 echo "<a name='ip-$dottedquad' href='index.php?page=$addr_page_name&hl_object_id=$object_id&ip=$dottedquad'>${dottedquad}</a>";
896 else
897 echo $dottedquad;
898 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
899 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
900 echo '&nbsp;' . $aac[$alloc['type']];
901 if (strlen ($alloc['addrinfo']['name']))
902 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
903 echo '</td>';
904 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
905 {
906 if (NULL === $netid)
907 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
908 else
909 {
910 echo "<td class='${secondclass}'>";
911 renderCell ($netinfo);
912 echo "</td>";
913 // filter out self-allocation
914 $other_routers = array();
915 foreach (findRouters ($netinfo['addrlist']) as $router)
916 if ($router['id'] != $object_id)
917 $other_routers[] = $router;
918 if (count ($other_routers))
919 printRoutersTD ($other_routers);
920 else
921 echo "<td class='${secondclass}'>&nbsp;</td>";
922 }
923 }
924 // peers
925 echo "<td class='${secondclass}'>\n";
926 $prefix = '';
927 if ($alloc['addrinfo']['reserved'] == 'yes')
928 {
929 echo $prefix . '<strong>RESERVED</strong>';
930 $prefix = '; ';
931 }
932 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
933 {
934 if ($allocpeer['object_id'] == $object_id)
935 continue;
936 echo $prefix . "<a href='" . makeHref (array ('page' => 'object', 'object_id' => $allocpeer['object_id'])) . "'>";
937 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
938 echo $allocpeer['osif'] . '@';
939 echo $allocpeer['object_name'] . '</a>';
940 $prefix = '; ';
941 }
942 echo "</td></tr>\n";
943 }
944 }
945 echo "</table><br>\n";
946 finishPortlet();
947 }
948
949 $forwards = $info['nat4'];
950 if (count($forwards['in']) or count($forwards['out']))
951 {
952 startPortlet('NATv4');
953
954 if (count($forwards['out']))
955 {
956
957 echo "<h3>locally performed NAT</h3>";
958
959 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
960 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
961
962 foreach ($forwards['out'] as $pf)
963 {
964 $class = 'trerror';
965 $osif = '';
966 if (isset ($alloclist [$pf['localip']]))
967 {
968 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
969 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
970 }
971 echo "<tr class='$class'>";
972 echo "<td>${pf['proto']}</td><td class=tdleft>${osif}<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
973 echo "<td class=tdleft><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
974 $address = getIPv4Address ($pf['remoteip']);
975 echo "<td class='description'>";
976 if (count ($address['allocs']))
977 foreach($address['allocs'] as $bond)
978 echo "<a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$bond['object_id']))."'>${bond['object_name']}(${bond['name']})</a> ";
979 elseif (strlen ($pf['remote_addr_name']))
980 echo '(' . $pf['remote_addr_name'] . ')';
981 echo "</td><td class='description'>${pf['description']}</td></tr>";
982 }
983 echo "</table><br><br>";
984 }
985 if (count($forwards['in']))
986 {
987 echo "<h3>arriving NAT connections</h3>";
988 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
989 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
990 foreach ($forwards['in'] as $pf)
991 {
992 echo "<tr>";
993 echo "<td>${pf['proto']}/<a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['localip']))."'>${pf['localip']}</a>:${pf['localport']}</td>";
994 echo "<td class='description'><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$pf['object_id']))."'>${pf['object_name']}</a>";
995 echo "</td><td><a href='".makeHref(array('page'=>'ipaddress', 'tab'=>'default', 'ip'=>$pf['remoteip']))."'>${pf['remoteip']}</a>:${pf['remoteport']}</td>";
996 echo "<td class='description'>${pf['description']}</td></tr>";
997 }
998 echo "</table><br><br>";
999 }
1000 finishPortlet();
1001 }
1002
1003 $pools = $info['ipv4rspools'];
1004 if (count ($pools))
1005 {
1006 $order = 'odd';
1007 startPortlet ('Real server pools (' . count ($pools) . ')');
1008 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable>\n";
1009 echo "<tr><th>VS</th><th>RS pool</th><th>RS</th><th>VS config</th><th>RS config</th><th>Prio</th></tr>\n";
1010 foreach ($pools as $vs_id => $vs_info)
1011 {
1012 echo "<tr valign=top class=row_${order}><td class=tdleft>";
1013 renderCell (spotEntity ('ipv4vs', $vs_id));
1014 echo "</td><td class=tdleft>";
1015 renderCell (spotEntity ('ipv4rspool', $vs_info['pool_id']));
1016 echo '</td><td class=tdleft>' . $vs_info['rscount'] . '</td>';
1017 echo "<td class=slbconf>${vs_info['vsconfig']}</td>";
1018 echo "<td class=slbconf>${vs_info['rsconfig']}</td>";
1019 echo "<td class=slbconf>${vs_info['prio']}</td>";
1020 echo "</tr>\n";
1021 $order = $nextorder[$order];
1022 }
1023 echo "</table>\n";
1024 finishPortlet();
1025 }
1026 echo "</td>\n";
1027
1028 // After left column we have (surprise!) right column with rackspace portlet only.
1029 echo "<td class=pcright>";
1030 if (!in_array($info['objtype_id'], $virtual_obj_types))
1031 {
1032 // rackspace portlet
1033 startPortlet ('rackspace allocation');
1034 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1035 renderRack ($rack_id, $object_id);
1036 echo '<br>';
1037 finishPortlet();
1038 }
1039 echo "</td></tr>";
1040 echo "</table>\n";
1041 }
1042
1043 function renderRackMultiSelect ($sname, $racks, $selected)
1044 {
1045 // Transform the given flat list into a list of groups, each representing a rack row.
1046 $rdata = array();
1047 foreach ($racks as $rack)
1048 if (!isset ($rdata[$rack['row_name']]))
1049 $rdata[$rack['row_name']] = array ($rack['id'] => $rack['name']);
1050 else
1051 $rdata[$rack['row_name']][$rack['id']] = $rack['name'];
1052 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementsByName(\"updateObjectAllocation\")[0].submit()'>\n";
1053 foreach ($rdata as $optgroup => $racklist)
1054 {
1055 echo "<optgroup label='${optgroup}'>";
1056 foreach ($racklist as $rack_id => $rack_name)
1057 {
1058 echo "<option value=${rack_id}";
1059 if (!(array_search ($rack_id, $selected) === FALSE))
1060 echo ' selected';
1061 echo">${rack_name}</option>\n";
1062 }
1063 }
1064 echo "</select>\n";
1065 }
1066
1067 // This function renders a form for port edition.
1068 function renderPortsForObject ($object_id)
1069 {
1070 $prefs = getPortListPrefs();
1071 function printNewItemTR ($prefs)
1072 {
1073 printOpFormIntro ('addPort');
1074 echo "<tr><td>";
1075 printImageHREF ('add', 'add a port', TRUE);
1076 echo "</td><td class='tdleft'><input type=text size=8 name=port_name tabindex=100></td>\n";
1077 echo "<td><input type=text name=port_label tabindex=101></td><td>";
1078 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 102), $prefs['selected']);
1079 echo "<td><input type=text name=port_l2address tabindex=103 size=18 maxlength=24></td>\n";
1080 echo "<td colspan=3>&nbsp;</td><td>";
1081 printImageHREF ('add', 'add a port', TRUE, 104);
1082 echo "</td></tr></form>";
1083 }
1084 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes' || getConfigVar('ENABLE_BULKPORT_FORM') == 'yes' )
1085 startPortlet ('Ports and interfaces');
1086 else
1087 echo '<br>';
1088 $object = spotEntity ('object', $object_id);
1089 amplifyCell ($object);
1090 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1091 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1092 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>Start Number</th>";
1093 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1094 printOpFormIntro ('addBulkPorts');
1095 echo "<tr><td>";
1096 printImageHREF ('add', 'add ports', TRUE);
1097 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1098 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1099 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1100 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1101 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1102 echo "<td>&nbsp;</td><td>";
1103 printImageHREF ('add', 'add ports', TRUE, 110);
1104 echo "</td></tr></form>";
1105 echo "</table><br>\n";
1106 }
1107
1108 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1109 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>L2 address</th>";
1110 echo "<th class=tdcenter colspan=2>Cable, Remote object and port</th><th class=tdcenter>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
1111 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1112 printNewItemTR ($prefs);
1113
1114 // clear ports link
1115 echo "<a href='".
1116 makeHrefProcess(array ('op'=>'deleteAll', 'page' => 'object', 'tab' => 'ports', 'object_id' => $object_id)).
1117 "' onclick=\"javascript:return confirm('Are you sure you want to delete all existing ports?')\">" . getImageHREF ('clear', 'Clear port list') . " Clear port list</a>";
1118
1119 if (isset ($_REQUEST['hl_port_id']))
1120 {
1121 assertUIntArg ('hl_port_id');
1122 $hl_port_id = intval ($_REQUEST['hl_port_id']);
1123 addAutoScrollScript ("port-$hl_port_id");
1124 }
1125 switchportInfoJS ($object_id); // load JS code to make portnames interactive
1126 foreach ($object['ports'] as $port)
1127 {
1128 $tr_class = isset ($hl_port_id) && $hl_port_id == $port['id'] ? 'class="port_highlight"' : '';
1129 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
1130 echo "<tr $tr_class><td><a name='port-${port['id']}' href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id'], 'object_id'=>$object_id))."'>";
1131 printImageHREF ('delete', 'Unlink and Delete this port');
1132 echo "</a></td>\n";
1133 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
1134 echo "<td class='tdleft' NOWRAP><input type=text name=name class='interactive-portname $a_class' value='${port['name']}' size=8></td>";
1135 echo "<td><input type=text name=label value='${port['label']}'></td>";
1136 if (!$port['remote_object_id'])
1137 {
1138 echo '<td>';
1139 if ($port['iif_id'] != 1)
1140 echo '<label>' . $port['iif_name'] . ' ';
1141 printSelect (getExistingPortTypeOptions ($port['id']), array ('name' => 'port_type_id'), $port['oif_id']);
1142 if ($port['iif_id'] != 1)
1143 echo '</label>';
1144 echo '</td>';
1145 }
1146 else
1147 {
1148 echo "<input type=hidden name=port_type_id value='${port['oif_id']}'><td class=tdleft>";
1149 echo formatPortIIFOIF ($port) . '</td>';
1150 }
1151 // 18 is enough to fit 6-byte MAC address in its longest form,
1152 // while 24 should be Ok for WWN
1153 echo "<td><input type=text name=l2address value='${port['l2address']}' size=18 maxlength=24></td>\n";
1154 if ($port['remote_object_id'])
1155 {
1156 $remote_object = spotEntity ('object', $port['remote_object_id']);
1157 echo "<td>${port['cableid']}&nbsp;<a href='".makeHref(array('page'=>'object', 'object_id'=>$port['remote_object_id']))."'>${remote_object['dname']}</a></td>";
1158 echo "<td>${port['remote_name']}<input type=hidden name=reservation_comment value=''></td>";
1159 echo "<td class=tdcenter><a href='".
1160 makeHrefProcess(array(
1161 'op'=>'unlinkPort',
1162 'port_id'=>$port['id'],
1163 'object_id'=>$object_id)).
1164 "'>";
1165 printImageHREF ('cut', 'Unlink this port');
1166 echo "</a></td>";
1167 }
1168 elseif (strlen ($port['reservation_comment']))
1169 {
1170 echo "<td><b>Reserved:</b></td>";
1171 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
1172 echo "<td class=tdcenter><a href='".
1173 makeHrefProcess(array(
1174 'op'=>'useup',
1175 'port_id'=>$port['id'],
1176 'object_id'=>$object_id)).
1177 "'>";
1178 printImageHREF ('clear', 'Use up this port');
1179 echo "</a></td>";
1180 }
1181 else
1182 {
1183 //echo "<td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><a href='javascript:;'";
1184 echo "<td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><span";
1185 $helper_args = array
1186 (
1187 'port' => $port['id'],
1188 'in_rack' => 'n',
1189 );
1190 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
1191 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
1192 echo " ondblclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1193 echo "\",\"findlink\",\"${popup_args}\");'";
1194 // end of onclick=
1195 $helper_args['in_rack'] = 'y';
1196 echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1197 echo "\",\"findlink\",\"${popup_args}\");'";
1198 // end of onclick=
1199 echo '>';
1200 // end of <a>
1201 printImageHREF ('plug', 'Link this port');
1202 echo "</span>";
1203 echo " <input type=text name=reservation_comment></td>\n";
1204 }
1205 echo "<td>";
1206 printImageHREF ('save', 'Save changes', TRUE);
1207 echo "</td></form></tr>\n";
1208 }
1209 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1210 printNewItemTR ($prefs);
1211 echo "</table><br>\n";
1212 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1213 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1214 echo "<tr><th>&nbsp;</th><th class=tdleft>Local name</th><th class=tdleft>Visible label</th><th class=tdleft>Interface</th><th class=tdleft>Start Number</th>";
1215 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1216 printOpFormIntro ('addBulkPorts');
1217 echo "<tr><td>";
1218 printImageHREF ('add', 'add ports', TRUE);
1219 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1220 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1221 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1222 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1223 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1224 echo "<td>&nbsp;</td><td>";
1225 printImageHREF ('add', 'add ports', TRUE, 110);
1226 echo "</td></tr></form>";
1227 echo "</table><br>\n";
1228 }
1229 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes')
1230 finishPortlet();
1231 if (getConfigVar('ENABLE_MULTIPORT_FORM') != 'yes')
1232 return;
1233
1234 startPortlet ('Add/update multiple ports');
1235 printOpFormIntro ('addMultiPorts');
1236 echo 'Format: <select name=format tabindex=201>';
1237 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1238 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
1239 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
1240 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
1241 echo "</select>";
1242 echo 'Default port type: ';
1243 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type', 'tabindex' => 202), $prefs['selected']);
1244 echo "<input type=submit value='Parse output' tabindex=204><br>\n";
1245 echo "<textarea name=input cols=100 rows=50 tabindex=203></textarea><br>\n";
1246 echo '</form>';
1247 finishPortlet();
1248 }
1249
1250 function renderIPv4ForObject ($object_id)
1251 {
1252 function printNewItemTR ()
1253 {
1254 global $aat;
1255 printOpFormIntro ('addIPv4Allocation');
1256 echo "<tr><td>";
1257 printImageHREF ('add', 'allocate', TRUE);
1258 echo "</td>";
1259 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1260 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
1261 echo "<td colspan=2>&nbsp;</td><td>";
1262 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), 'regular');
1263 echo "</td><td>&nbsp;</td><td>";
1264 printImageHREF ('add', 'allocate', TRUE, 103);
1265 echo "</td></tr></form>";
1266 }
1267 $focus = spotEntity ('object', $object_id);
1268 amplifyCell ($focus);
1269 global $aat;
1270 startPortlet ('Allocations');
1271 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1272 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1273 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1274 echo '<th>network</th><th>routed by</th>';
1275 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1276
1277 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1278 printNewItemTR();
1279 foreach ($focus['ipv4'] as $dottedquad => $alloc)
1280 {
1281 $class = $alloc['addrinfo']['class'];
1282 $netid = getIPv4AddressNetworkId ($dottedquad);
1283 if (NULL !== $netid)
1284 {
1285 $netinfo = spotEntity ('ipv4net', $netid);
1286 loadIPv4AddrList ($netinfo);
1287 }
1288 printOpFormIntro ('updIPv4Allocation', array ('ip' => $dottedquad));
1289 echo "<tr class='$class' valign=top><td><a href='".makeHrefProcess(array('op'=>'delIPv4Allocation', 'ip'=>$dottedquad, 'object_id'=>$object_id))."'>";
1290 printImageHREF ('delete', 'Delete this IPv4 address');
1291 echo "</a></td>";
1292 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td><td class=tdleft>";
1293 if (NULL !== $netid)
1294 echo "<a href='".makeHref(array('page'=>'ipaddress', 'ip'=>$dottedquad))."'>${dottedquad}</a>";
1295 else
1296 echo $dottedquad;
1297 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1298 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1299 if (strlen ($alloc['addrinfo']['name']))
1300 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1301 echo '</td>';
1302 // FIXME: this a copy-and-paste from renderRackObject()
1303 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1304 {
1305 if (NULL === $netid)
1306 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1307 else
1308 {
1309 echo '<td>';
1310 renderCell ($netinfo);
1311 echo '</td>';
1312 // filter out self-allocation
1313 $other_routers = array();
1314 foreach (findRouters ($netinfo['addrlist']) as $router)
1315 if ($router['id'] != $object_id)
1316 $other_routers[] = $router;
1317 if (count ($other_routers))
1318 printRoutersTD ($other_routers);
1319 else
1320 echo "<td>&nbsp;</td>";
1321 }
1322 }
1323 echo '<td>';
1324 printSelect ($aat, array ('name' => 'bond_type'), $alloc['type']);
1325 echo "</td><td>";
1326 $prefix = '';
1327 if ($alloc['addrinfo']['reserved'] == 'yes')
1328 {
1329 echo $prefix . '<strong>RESERVED</strong>';
1330 $prefix = '; ';
1331 }
1332 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1333 {
1334 if ($allocpeer['object_id'] == $object_id)
1335 continue;
1336 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1337 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
1338 echo $allocpeer['osif'] . '@';
1339 echo $allocpeer['object_name'] . '</a>';
1340 $prefix = '; ';
1341 }
1342 echo "</td><td>";
1343 printImageHREF ('save', 'Save changes', TRUE);
1344 echo "</td></form></tr>\n";
1345 }
1346 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1347 printNewItemTR();
1348
1349 echo "</table><br>\n";
1350 finishPortlet();
1351
1352 }
1353
1354 function renderIPv6ForObject ($object_id)
1355 {
1356 function printNewItemTR ()
1357 {
1358 global $aat;
1359 printOpFormIntro ('addIPv6Allocation');
1360 echo "<tr><td>";
1361 printImageHREF ('add', 'allocate', TRUE);
1362 echo "</td>";
1363 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n";
1364 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n";
1365 echo "<td colspan=2>&nbsp;</td><td>";
1366 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), 'regular');
1367 echo "</td><td>&nbsp;</td><td>";
1368 printImageHREF ('add', 'allocate', TRUE, 103);
1369 echo "</td></tr></form>";
1370 }
1371 $focus = spotEntity ('object', $object_id);
1372 amplifyCell ($focus);
1373 global $aat;
1374 startPortlet ('Allocations');
1375 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1376 echo '<tr><th>&nbsp;</th><th>OS interface</th><th>IP address</th>';
1377 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1378 echo '<th>network</th><th>routed by</th>';
1379 echo '<th>type</th><th>misc</th><th>&nbsp</th></tr>';
1380
1381 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
1382 printNewItemTR();
1383 foreach ($focus['ipv6'] as $bin_str => $alloc)
1384 {
1385 $ipv6 = new IPv6Address ($bin_str);
1386 $dottedquad = $ipv6->format();
1387 $class = $alloc['addrinfo']['class'];
1388 $netid = getIPv6AddressNetworkId ($ipv6);
1389 if (NULL !== $netid)
1390 {
1391 $netinfo = spotEntity ('ipv6net', $netid);
1392 loadIPv6AddrList ($netinfo);
1393 }
1394 printOpFormIntro ('updIPv6Allocation', array ('ip' => $dottedquad));
1395 echo "<tr class='$class' valign=top><td><a href='".makeHrefProcess(array('op'=>'delIPv6Allocation', 'ip'=>$dottedquad, 'object_id'=>$object_id))."'>";
1396 printImageHREF ('delete', 'Delete this IPv6 address');
1397 echo "</a></td>";
1398 echo "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10></td><td class=tdleft>";
1399 if (NULL !== $netid)
1400 echo "<a href='index.php?page=ipv6address&ip=$dottedquad'>$dottedquad</a>";
1401 else
1402 echo $dottedquad;
1403 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
1404 echo '<small>/' . (NULL === $netid ? '??' : $netinfo['mask']) . '</small>';
1405 if (strlen ($alloc['addrinfo']['name']))
1406 echo ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
1407 echo '</td>';
1408 // FIXME: this a copy-and-paste from renderRackObject()
1409 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1410 {
1411 if (NULL === $netid)
1412 echo '<td class=sparenetwork>N/A</td><td class=sparenetwork>N/A</td>';
1413 else
1414 {
1415 echo '<td>';
1416 renderCell ($netinfo);
1417 echo '</td>';
1418 // filter out self-allocation
1419 $other_routers = array();
1420 foreach (findRouters ($netinfo['addrlist']) as $router)
1421 if ($router['id'] != $object_id)
1422 $other_routers[] = $router;
1423 if (count ($other_routers))
1424 printRoutersTD ($other_routers);
1425 else
1426 echo "<td>&nbsp;</td>";
1427 }
1428 }
1429 echo '<td>';
1430 printSelect ($aat, array ('name' => 'bond_type'), $alloc['type']);
1431 echo "</td><td>";
1432 $prefix = '';
1433 if ($alloc['addrinfo']['reserved'] == 'yes')
1434 {
1435 echo $prefix . '<strong>RESERVED</strong>';
1436 $prefix = '; ';
1437 }
1438 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
1439 {
1440 if ($allocpeer['object_id'] == $object_id)
1441 continue;
1442 echo $prefix . "<a href='".makeHref(array('page'=>'object', 'object_id'=>$allocpeer['object_id']))."'>";
1443 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
1444 echo $allocpeer['osif'] . '@';
1445 echo $allocpeer['object_name'] . '</a>';
1446 $prefix = '; ';
1447 }
1448 echo "</td><td>";
1449 printImageHREF ('save', 'Save changes', TRUE);
1450 echo "</td></form></tr>\n";
1451 }
1452 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
1453 printNewItemTR();
1454
1455 echo "</table><br>\n";
1456 finishPortlet();
1457
1458 }
1459
1460 // This function is deprecated. Do not rely on its internals,
1461 // it will probably be removed in the next major relese.
1462 // Use new showError, showWarning, showSuccess functions.
1463 // Log structure versions:
1464 // 1: the whole structure is a list of code-message pairs
1465 // 2 and later: there's a "v" field set, which indicates the version
1466 // 2: there's a "m" list set to hold message code and optional arguments
1467 function showMessageOrError ()
1468 {
1469 if (!isset ($_SESSION['log']))
1470 return;
1471 $log = $_SESSION['log'];
1472 switch (TRUE)
1473 {
1474 case !isset ($log['v']):
1475 case $log['v'] == 1:
1476 foreach ($log as $key => $record)
1477 if ($key !== 'v')
1478 echo "<div class=msg_${record['code']}>${record['message']}</div>";
1479 break;
1480 case $log['v'] == 2:
1481 $msginfo = array
1482 (
1483 // records 0~99 with success messages
1484 0 => array ('code' => 'success', 'format' => '%s'),
1485 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with port %s at object %s'),
1486 5 => array ('code' => 'success', 'format' => 'added record "%s" successfully'),
1487 6 => array ('code' => 'success', 'format' => 'updated record "%s" successfully'),
1488 7 => array ('code' => 'success', 'format' => 'deleted record "%s" successfully'),
1489 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1490 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1491 26 => array ('code' => 'success', 'format' => 'updated %u record(s) successfully'),
1492 37 => array ('code' => 'success', 'format' => 'added %u records successfully'),
1493 41 => array ('code' => 'success', 'format' => 'uplink ports reverb queued'),
1494 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1495 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1496 48 => array ('code' => 'success', 'format' => 'added a record successfully'),
1497 49 => array ('code' => 'success', 'format' => 'deleted a record successfully'),
1498 51 => array ('code' => 'success', 'format' => 'updated a record successfully'),
1499 57 => array ('code' => 'success', 'format' => 'Reset complete'),
1500 62 => array ('code' => 'success', 'format' => 'gw: %s'),
1501 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
1502 64 => array ('code' => 'success', 'format' => 'Port %s@%s has been assigned to VLAN %u'),
1503 66 => array ('code' => 'success', 'format' => "File sent Ok via handler '%s'"),
1504 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1505 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
1506 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
1507 81 => array ('code' => 'success', 'format' => "SNMP: completed '%s' work"),
1508 82 => array ('code' => 'success', 'format' => "Bulk port creation was successful. %u ports created, %u failed"),
1509 87 => array ('code' => 'success', 'format' => '802.1Q recalculate: %d ports changed on %d switches'),
1510 // records 100~199 with fatal error messages
1511 100 => array ('code' => 'error', 'format' => '%s'),
1512 102 => array ('code' => 'error', 'format' => "Error creating user account '%s'"),
1513 104 => array ('code' => 'error', 'format' => "failed updating record '%s'"),
1514 107 => array ('code' => 'error', 'format' => 'Assertion failed: %s'),
1515 108 => array ('code' => 'error', 'format' => 'Database error: %s'),
1516 109 => array ('code' => 'error', 'format' => 'failed updating a record'),
1517 110 => array ('code' => 'error', 'format' => 'failed adding a record'),
1518 111 => array ('code' => 'error', 'format' => 'failed deleting a record'),
1519 120 => array ('code' => 'error', 'format' => 'Reset failed!'),
1520 127 => array ('code' => 'error', 'format' => 'Added %u real servers and encountered %u errors'),
1521 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1522 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u record(s)'),
1523 143 => array ('code' => 'error', 'format' => 'Tried chaining %u tags, but experienced %u errors.'),
1524 144 => array ('code' => 'error', 'format' => "Error deleting tag: '%s'"),
1525 147 => array ('code' => 'error', 'format' => 'failed adding record "%s"'),
1526 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1527 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1528 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1529 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1530 153 => array ('code' => 'error', 'format' => 'Password change failed.'),
1531 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1532 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1533 157 => array ('code' => 'error', 'format' => 'operation not permitted'),
1534 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1535 160 => array ('code' => 'error', 'format' => 'Invalid arguments'),
1536 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1537 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
1538 164 => array ('code' => 'error', 'format' => 'Gateway failure: %s.'),
1539 165 => array ('code' => 'error', 'format' => 'Gateway failure: malformed reply.'),
1540 166 => array ('code' => 'error', 'format' => 'gw: %s'),
1541 167 => array ('code' => 'error', 'format' => 'Could not find port %s'),
1542 168 => array ('code' => 'error', 'format' => 'Port %s is a trunk'),
1543 169 => array ('code' => 'error', 'format' => 'Failed to configure %s, connector returned code %u'),
1544 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1545 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1546 179 => array ('code' => 'error', 'format' => 'Expired form has been declined.'),
1547 184 => array ('code' => 'error', 'format' => 'Submitted form is invalid at line %u'),
1548 186 => array ('code' => 'error', 'format' => 'Incomplete form has been ignored. Cheers.'),
1549 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1550 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
1551 190 => array ('code' => 'error', 'format' => "Invalid VLAN ID '%s'"),
1552 191 => array ('code' => 'error', 'format' => "deploy was blocked due to conflicting configuration versions"),
1553
1554 // records 200~299 with warnings
1555 200 => array ('code' => 'warning', 'format' => '%s'),
1556 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
1557 202 => array ('code' => 'warning', 'format' => 'gw: %s'),
1558 203 => array ('code' => 'warning', 'format' => 'Port %s seems to be the first in VLAN %u at this switch.'),
1559 204 => array ('code' => 'warning', 'format' => 'Check uplink/downlink configuration for proper operation.'),
1560 205 => array ('code' => 'warning', 'format' => '%u change request(s) have been ignored'),
1561 206 => array ('code' => 'warning', 'format' => 'Rack is not empty'),
1562 207 => array ('code' => 'warning', 'format' => 'Ignored empty request'),
1563
1564 // records 300~399 with notices
1565 300 => array ('code' => 'neutral', 'format' => '%s'),
1566
1567 );
1568 // Handle the arguments. Is there any better way to do it?
1569 foreach ($log['m'] as $record)
1570 {
1571 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1572 {
1573 echo '<div class=msg_neutral>(this message was lost)</div>';
1574 continue;
1575 }
1576 if (isset ($record['a']))
1577 switch (count ($record['a']))
1578 {
1579 case 1:
1580 $msgtext = sprintf
1581 (
1582 $msginfo[$record['c']]['format'],
1583 $record['a'][0]
1584 );
1585 break;
1586 case 2:
1587 $msgtext = sprintf
1588 (
1589 $msginfo[$record['c']]['format'],
1590 $record['a'][0],
1591 $record['a'][1]
1592 );
1593 break;
1594 case 3:
1595 $msgtext = sprintf
1596 (
1597 $msginfo[$record['c']]['format'],
1598 $record['a'][0],
1599 $record['a'][1],
1600 $record['a'][2]
1601 );
1602 break;
1603 case 4:
1604 default:
1605 $msgtext = sprintf
1606 (
1607 $msginfo[$record['c']]['format'],
1608 $record['a'][0],
1609 $record['a'][1],
1610 $record['a'][2],
1611 $record['a'][3]
1612 );
1613 break;
1614 }
1615 else
1616 $msgtext = $msginfo[$record['c']]['format'];
1617 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
1618 }
1619 break;
1620 default:
1621 echo '<div class=msg_error>' . __FUNCTION__ . ': internal error</div>';
1622 break;
1623 }
1624 clearMessages();
1625 }
1626
1627 // renders two tables: port link status and learned MAC list
1628 function renderPortsInfo($object_id)
1629 {
1630 global $nextorder;
1631 echo "<table width='100%'><tr>";
1632
1633 if (permitted (NULL, NULL, 'get_link_status'))
1634 {
1635 try
1636 {
1637 $linkStatus = gwRetrieveDeviceConfig ($object_id, 'getportstatus');
1638 }
1639 catch (RackTablesError $e) {}
1640 if (! empty ($linkStatus))
1641 {
1642 echo "<td valign='top' width='50%'>";
1643 startPortlet('Link status');
1644 echo "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>Port<th>Link status<th>Link info</tr>";
1645 $order = 'even';
1646 foreach ($linkStatus as $pn => $link)
1647 {
1648 echo "<tr class='row_$order'>";
1649 $order = $nextorder[$order];
1650 echo '<td>' . $pn;
1651 echo '<td>' . $link['status'];
1652 $info = '';
1653 if (isset ($link['speed']))
1654 $info .= $link['speed'];
1655 if (isset ($link['duplex']))
1656 {
1657 if (! empty ($info))
1658 $info .= ', ';
1659 $info .= $link['duplex'];
1660 }
1661 echo '<td>' . $info;
1662 echo '</tr>';
1663 }
1664 echo "</table></td>";
1665 finishPortlet();
1666 }
1667 }
1668
1669 try
1670 {
1671 $macList = sortPortList (gwRetrieveDeviceConfig ($object_id, 'getmaclist'));
1672 }
1673 catch (RackTablesError $e) {}
1674 if (! empty ($macList))
1675 {
1676 echo "<td valign='top' width='50%'>";
1677 $rendered_macs = '';
1678 $mac_count = 0;
1679 $rendered_macs .= "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>MAC<th>Vlan<th>Port</tr>";
1680 $order = 'even';
1681 foreach ($macList as $pn => $list)
1682 {
1683 $order = $nextorder[$order];
1684 foreach ($list as $item)
1685 {
1686 ++$mac_count;
1687 $rendered_macs .= "<tr class='row_$order'>";
1688 $rendered_macs .= '<td style="font-family: monospace">' . $item['mac'];
1689 $rendered_macs .= '<td>' . $item['vid'];
1690 $rendered_macs .= '<td>' . $pn;
1691 $rendered_macs .= '</tr>';
1692 }
1693 }
1694 $rendered_macs .= "</table></td>";
1695
1696 startPortlet("Learned MACs ($mac_count)");
1697 echo $rendered_macs;
1698 finishPortlet();
1699 }
1700
1701 echo "</td></tr></table>";
1702 }
1703
1704 /*
1705 The following conditions must be met:
1706 1. We can mount onto free atoms only. This means: if any record for an atom
1707 already exists in RackSpace, it can't be used for mounting.
1708 2. We can't unmount from 'W' atoms. Operator should review appropriate comments
1709 and either delete them before unmounting or refuse to unmount the object.
1710 */
1711 function renderRackSpaceForObject ($object_id)
1712 {
1713 // Always process occupied racks plus racks chosen by user. First get racks with
1714 // already allocated rackspace...
1715 $workingRacksData = getResidentRacksData ($object_id);
1716 // ...and then add those chosen by user (if any).
1717 if (isset($_REQUEST['rackmulti']))
1718 foreach ($_REQUEST['rackmulti'] as $cand_id)
1719 if (!isset ($workingRacksData[$cand_id]))
1720 {
1721 $rackData = spotEntity ('rack', $cand_id);
1722 amplifyCell ($rackData);
1723 $workingRacksData[$cand_id] = $rackData;
1724 }
1725
1726 // Main layout starts.
1727 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
1728
1729 // Left portlet with rack list.
1730 echo "<td class=pcleft height='1%'>";
1731 startPortlet ('Racks');
1732 $allRacksData = listCells ('rack');
1733
1734 // filter rack list to match only racks having common tags with the object (reducing $allRacksData)
1735 if (! isset ($_REQUEST['show_all_racks']) and getConfigVar ('FILTER_RACKLIST_BY_TAGS') == 'yes')
1736 {
1737 $matching_racks = array();
1738 $object = spotEntity ('object', $object_id);
1739 $matched_tags = array();
1740 foreach ($allRacksData as $rack)
1741 foreach ($object['etags'] as $tag)
1742 if (tagOnChain ($tag, $rack['etags']) or tagOnChain ($tag, $rack['itags']))
1743 {
1744 $matching_racks[$rack['id']] = $rack;
1745 $matched_tags[$tag['id']] = $tag;
1746 break;
1747 }
1748 // add current object's racks even if they dont match filter
1749 foreach ($workingRacksData as $rack_id => $rack)
1750 if (! isset ($matching_racks[$rack_id]))
1751 $matching_racks[$rack_id] = $rack;
1752 // if matching racks found, and rack list is reduced, show 'show all' link
1753 if (count ($matching_racks) and count ($matching_racks) != count ($allRacksData))
1754 {
1755 $filter_text = '';
1756 foreach ($matched_tags as $tag)
1757 $filter_text .= (empty ($filter_text) ? '' : ' or ') . '{' . $tag['tag'] . '}';
1758 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
1759 $href_show_all .= htmlspecialchars('&show_all_racks=1');
1760 echo "(filtered by <span class='filter-text'>$filter_text</span>, <a href='$href_show_all'>show all</a>)<p>";
1761 $allRacksData = $matching_racks;
1762 }
1763 }
1764
1765 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
1766 foreach ($allRacksData as $rack)
1767 if (!array_key_exists ($rack['id'], $workingRacksData))
1768 {
1769 amplifyCell ($rack);
1770 $workingRacksData[$rack['id']] = $rack;
1771 }
1772 foreach (array_keys ($workingRacksData) as $rackId)
1773 applyObjectMountMask ($workingRacksData[$rackId], $object_id);
1774 printOpFormIntro ('updateObjectAllocation');
1775 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
1776 echo "<br><br>";
1777 finishPortlet();
1778 echo "</td>";
1779
1780 // Middle portlet with comment and submit.
1781 echo "<td class=pcleft>";
1782 startPortlet ('Comment');
1783 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
1784 echo "<input type=submit value='Save' name=got_atoms>\n";
1785 echo "<br><br>";
1786 finishPortlet();
1787 echo "</td>";
1788
1789 // Right portlet with rendered racks. If this form submit is not final, we have to
1790 // reflect the former state of the grid in current form.
1791 echo "<td class=pcright rowspan=2 height='1%'>";
1792 startPortlet ('Working copy');
1793 addJS ('js/racktables.js');
1794 echo '<table border=0 cellspacing=10 align=center><tr>';
1795 foreach ($workingRacksData as $rack_id => $rackData)
1796 {
1797 // Order is important here: only original allocation is highlighted.
1798 highlightObject ($rackData, $object_id);
1799 markupAtomGrid ($rackData, 'T');
1800 // If we have a form processed, discard user input and show new database
1801 // contents.
1802 if (isset ($_REQUEST['rackmulti'][0])) // is an update
1803 mergeGridFormToRack ($rackData);
1804 echo "<td valign=top>";
1805 echo "<center>\n<h2>${rackData['name']}</h2>\n";
1806 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
1807 echo "<tr><th width='10%'>&nbsp;</th>";
1808 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1809 echo "<th width='50%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1810 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1811 renderAtomGrid ($rackData);
1812 echo "<tr><th width='10%'>&nbsp;</th>";
1813 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1814 echo "<th width='50%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1815 echo "<th width='20%'><a href='javascript:;' oncontextmenu=\"blockToggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']}); return false;\" onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
1816 echo "</table></center>\n";
1817 echo '</td>';
1818 }
1819 echo "</tr></table>";
1820 finishPortlet();
1821 echo "</td>\n";
1822
1823 echo "</form>\n";
1824 echo "</tr></table>\n";
1825 }
1826
1827 function renderMolecule ($mdata, $object_id)
1828 {
1829 // sort data out
1830 $rackpack = array();
1831 global $loclist;
1832 foreach ($mdata as $rua)
1833 {
1834 $rack_id = $rua['rack_id'];
1835 $unit_no = $rua['unit_no'];
1836 $atom = $rua['atom'];
1837 if (!isset ($rackpack[$rack_id]))
1838 {
1839 $rackData = spotEntity ('rack', $rack_id);
1840 amplifyCell ($rackData);
1841 for ($i = $rackData['height']; $i > 0; $i--)
1842 for ($locidx = 0; $locidx < 3; $locidx++)
1843 $rackData[$i][$locidx]['state'] = 'F';
1844 $rackpack[$rack_id] = $rackData;
1845 }
1846 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
1847 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
1848 }
1849 // now we have some racks to render
1850 addAtomCSS();
1851 foreach ($rackpack as $rackData)
1852 {
1853 markAllSpans ($rackData);
1854 echo "<table class=molecule cellspacing=0>\n";
1855 echo "<caption>${rackData['name']}</caption>\n";
1856 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
1857 for ($i = $rackData['height']; $i > 0; $i--)
1858 {
1859 echo "<tr><th>$i</th>";
1860 for ($locidx = 0; $locidx < 3; $locidx++)
1861 {
1862 $state = $rackData[$i][$locidx]['state'];
1863 echo "<td class='atom state_${state}'>&nbsp;</td>\n";
1864 }
1865 echo "</tr>\n";
1866 }
1867 echo "</table>\n";
1868 }
1869 }
1870
1871 function renderDepot ()
1872 {
1873 global $pageno, $nextorder;
1874 $cellfilter = getCellFilter();
1875 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
1876
1877 echo "<table border=0 class=objectview>\n";
1878 echo "<tr><td class=pcleft>";
1879
1880 if (! renderEmptyResults ($cellfilter, 'objects', count($objects)))
1881 {
1882 if (count($objects) > 0)
1883 {
1884 startPortlet ('Objects (' . count ($objects) . ')');
1885 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1886 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Row/Rack</th></tr>';
1887 $order = 'odd';
1888 foreach ($objects as $obj)
1889 {
1890 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $obj['id'])
1891 $secondclass = 'tdleft port_highlight';
1892 else
1893 $secondclass = 'tdleft';
1894 echo "<tr class=row_${order} valign=top><td class='${secondclass}'><a href='".makeHref(array('page'=>'object', 'object_id'=>$obj['id']))."'><strong>${obj['dname']}</strong></a>";
1895 if (count ($obj['etags']))
1896 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
1897 echo "</td><td class='${secondclass}'>${obj['label']}</td>";
1898 echo "<td class='${secondclass}'>${obj['asset_no']}</td>";
1899 if ($obj['rack_id'])
1900 echo "<td class='${secondclass}'><a href='".makeHref(array('page'=>'row', 'row_id'=>$obj['row_id']))."'>${obj['Row_name']}</a>/<a href='".makeHref(array('page'=>'rack', 'rack_id'=>$obj['rack_id']))."'>${obj['Rack_name']}</a></td>";
1901 else
1902 echo "<td class='${secondclass}'>Unmounted</td>";
1903 echo '</tr>';
1904 $order = $nextorder[$order];
1905 }
1906 echo '</table>';
1907 finishPortlet();
1908 }
1909 else
1910 echo '<h2>No objects exist</h2>';
1911 }
1912
1913 echo "</td><td class=pcright width='25%'>";
1914
1915 renderCellFilterPortlet ($cellfilter, 'object', $objects);
1916 echo "</td></tr></table>\n";
1917 }
1918
1919 // This function returns TRUE if the result set is too big to be rendered, and no filter is set.
1920 // In this case it renders the describing message instead.
1921 function renderEmptyResults($cellfilter, $entities_name, $count = NULL)
1922 {
1923 if (!$cellfilter['is_empty'])
1924 return FALSE;
1925 if (isset ($_REQUEST['show_all_objects']))
1926 return FALSE;
1927 $max = intval(getConfigVar('MAX_UNFILTERED_ENTITIES'));
1928 if (0 == $max || $count <= $max)
1929 return FALSE;
1930
1931 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
1932 $href_show_all .= htmlspecialchars('&show_all_objects=1');
1933 $suffix = isset ($count) ? " ($count)" : '';
1934 echo <<<END
1935 <p>Please set a filter to display the corresponging $entities_name.
1936 <br><a href="$href_show_all">Show all $entities_name$suffix</a>
1937 END;
1938 return TRUE;
1939 }
1940
1941 // History viewer for history-enabled simple dictionaries.
1942 function renderHistory ($object_type, $object_id)
1943 {
1944 switch ($object_type)
1945 {
1946 case 'row':
1947 $query = "select ctime, user_name, name, comment from RackRowHistory where id = ? order by ctime";
1948 $header = '<tr><th>change time</th><th>author</th><th>rack row name</th><th>rack row comment</th></tr>';
1949 $extra = 3;
1950 break;
1951 case 'rack':
1952 $query =
1953 "select ctime, user_name, rh.name, rr.name as name, rh.height, rh.comment " .
1954 "from RackHistory as rh left join RackRow as rr on rh.row_id = rr.id " .
1955 "where rh.id = ? order by ctime";
1956 $header = '<tr><th>change time</th><th>author</th><th>rack name</th><th>rack row name</th><th>rack height</th><th>rack comment</th></tr>';
1957 $extra = 5;
1958 break;
1959 case 'object':
1960 $query =
1961 "select ctime, user_name, RackObjectHistory.name as name, label, asset_no, has_problems, dict_value, comment " .
1962 "from RackObjectHistory inner join Dictionary on objtype_id = dict_key join Chapter on Dictionary.chapter_id = Chapter.id " .
1963 "where Chapter.name = 'RackObjectType' and RackObjectHistory.id=? order by ctime";
1964 $header = '<tr><th>change time</th><th>author</th><th>common name</th><th>visible label</th><th>asset no</th><th>has problems?</th><th>object type</th><th>comment</th></tr>';
1965 $extra = 7;
1966 break;
1967 default:
1968 throw new InvalidArgException ('object_type', $object_type);
1969 }
1970 $result = usePreparedSelectBlade ($query, array ($object_id));
1971 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
1972 $order = 'odd';
1973 global $nextorder;
1974 echo $header;
1975 while ($row = $result->fetch (PDO::FETCH_NUM))
1976 {
1977 echo "<tr class=row_${order}><td>${row[0]}</td>";
1978 for ($i = 1; $i <= $extra; $i++)
1979 echo "<td>" . $row[$i] . "</td>";
1980 echo "</tr>\n";
1981 $order = $nextorder[$order];
1982 }
1983 echo "</table><br>\n";
1984 }
1985
1986 function renderRackspaceHistory ()
1987 {
1988 global $nextorder, $pageno, $tabno;
1989 $order = 'odd';
1990 $history = getRackspaceHistory();
1991 // Show the last operation by default.
1992 if (isset ($_REQUEST['op_id']))
1993 $op_id = $_REQUEST['op_id'];
1994 elseif (isset ($history[0]['mo_id']))
1995 $op_id = $history[0]['mo_id'];
1996 else $op_id = NULL;
1997
1998 $omid = NULL;
1999 $nmid = NULL;
2000 $object_id = 1;
2001 if ($op_id)
2002 list ($omid, $nmid) = getOperationMolecules ($op_id);
2003
2004 // Main layout starts.
2005 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2006
2007 // Left top portlet with old allocation.
2008 echo "<tr><td class=pcleft>";
2009 startPortlet ('Old allocation');
2010 if ($omid)
2011 {
2012 $oldMolecule = getMolecule ($omid);
2013 renderMolecule ($oldMolecule, $object_id);
2014 }
2015 else
2016 echo "nothing";
2017 finishPortlet();
2018
2019 echo '</td><td class=pcright>';
2020
2021 // Right top portlet with new allocation
2022 startPortlet ('New allocation');
2023 if ($nmid)
2024 {
2025 $newMolecule = getMolecule ($nmid);
2026 renderMolecule ($newMolecule, $object_id);
2027 }
2028 else
2029 echo "nothing";
2030 finishPortlet();
2031
2032 echo '</td></tr><tr><td colspan=2>';
2033
2034 // Bottom portlet with list
2035
2036 startPortlet ('Rackspace allocation history');
2037 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
2038 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
2039 foreach ($history as $row)
2040 {
2041 if ($row['mo_id'] == $op_id)
2042 $class = 'hl';
2043 else
2044 $class = "row_${order}";
2045 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
2046 echo "<td>${row['user_name']}</td><td>";
2047 renderCell (spotEntity ('object', $row['ro_id']));
2048 echo '</td><td>' . niftyString ($row['comment'], 0) . '</td></tr>';
2049 $order = $nextorder[$order];
2050 }
2051 echo "</table>\n";
2052 finishPortlet();
2053
2054 echo '</td></tr></table>';
2055 }
2056
2057 function renderIPv4SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
2058 {
2059 $self = __FUNCTION__;
2060 static $vdomlist = NULL;
2061 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2062 $vdomlist = getVLANDomainOptions();
2063
2064 // scroll page to the highlighted item
2065 if ($target && isset ($_REQUEST['hl_net']))
2066 addAutoScrollScript ("net-$target");
2067
2068 foreach ($tree as $item)
2069 {
2070 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2071 loadIPv4AddrList ($item); // necessary to compute router list and address counter
2072 else
2073 {
2074 $item['addrlist'] = array();
2075 $item['addrc'] = 0;
2076 }
2077 $used = $item['addrc'];
2078 $maxdirect = $item['addrt'];
2079 $maxtotal = binInvMaskFromDec ($item['mask']) + 1;
2080 if (isset ($item['id']))
2081 {
2082 $decor = array ('indent' => $level);
2083 if ($item['symbol'] == 'node-collapsed')
2084 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
2085 elseif ($item['symbol'] == 'node-expanded')
2086 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}" : '');
2087 echo "<tr valign=top>";
2088 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
2089 $decor['tdclass'] = 'port_highlight';
2090 printIPNetInfoTDs ($item, $decor);
2091 echo "<td class=tdcenter>";
2092 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2093 {
2094 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2095 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small>';
2096 }
2097 else
2098 echo "<small>${maxdirect}</small>";
2099 echo "</td>";
2100 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2101 {
2102 echo '<td class=tdleft>';
2103 if (count ($item['8021q']))
2104 {
2105 echo '<ul>';
2106 foreach ($item['8021q'] as $binding)
2107 {
2108 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
2109 // FIXME: would formatVLANName() do this?
2110 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
2111 }
2112 echo '</ul>';
2113 }
2114 echo '</td>';
2115 }
2116 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2117 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
2118 echo "</tr>";
2119 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2120 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
2121 }
2122 else
2123 {
2124 echo "<tr valign=top>";
2125 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
2126 echo "<td class=tdcenter>";
2127 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2128 {
2129 renderProgressBar ($used/$maxtotal, 'sparenetwork');
2130 echo "<br><small>${used}/${maxtotal}</small>";
2131 }
2132 else
2133 echo "<small>${maxtotal}</small>";
2134 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2135 echo '</td><td>&nbsp;</td>';
2136 echo "</td><td>&nbsp;</td></tr>";
2137 }
2138 }
2139 }
2140
2141 function renderIPv6SpaceRecords ($tree, $baseurl, $target = 0, $knight, $level = 1)
2142 {
2143 $self = __FUNCTION__;
2144 static $vdomlist = NULL;
2145 if ($vdomlist == NULL and getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2146 $vdomlist = getVLANDomainOptions();
2147
2148 // scroll page to the highlighted item
2149 if ($target && isset ($_REQUEST['hl_net']))
2150 addAutoScrollScript ("net-$target");
2151
2152 foreach ($tree as $item)
2153 {
2154 if (getConfigVar ('IPV4_TREE_SHOW_USAGE') == 'yes')
2155 loadIPv6AddrList ($item); // necessary to compute router list and address counter
2156 else
2157 {
2158 $item['addrlist'] = array();
2159 $item['addrc'] = 0;
2160 }
2161 if (isset ($item['id']))
2162 {
2163 $decor = array ('indent' => $level);
2164 if ($item['symbol'] == 'node-collapsed')
2165 $decor['symbolurl'] = "${baseurl}&eid=" . $item['id'];
2166 elseif ($item['symbol'] == 'node-expanded')
2167 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}#net6id${item['parent_id']}" : '');
2168 echo "<tr valign=top>";
2169 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
2170 $decor['tdclass'] .= ' port_highlight';
2171 printIPNetInfoTDs ($item, $decor);
2172 echo "<td class=tdcenter>";
2173 // show net usage
2174 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2175 echo "</td>";
2176 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2177 {
2178 echo '<td class=tdleft>';
2179 if (count ($item['8021q']))
2180 {
2181 echo '<ul>';
2182 foreach ($item['8021q'] as $binding)
2183 {
2184 echo '<li><a href="' . makeHref (array ('page' => 'vlan', 'vlan_ck' => $binding['domain_id'] . '-' . $binding['vlan_id'])) . '">';
2185 // FIXME: would formatVLANName() do this?
2186 echo $binding['vlan_id'] . '@' . niftyString ($vdomlist[$binding['domain_id']], 15) . '</a></li>';
2187 }
2188 echo '</ul>';
2189 }
2190 echo '</td>';
2191 }
2192 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2193 printRoutersTD (findRouters ($item['addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
2194 echo "</tr>";
2195 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
2196 $self ($item['kids'], $baseurl, $target, $knight, $level + 1);
2197 }
2198 /* do not display spare networks
2199 else
2200 { // display spare networks
2201 echo "<tr valign=top>";
2202 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
2203 echo "<td class=tdcenter>";
2204 echo formatIPv6NetUsage ($item['addrc'], $item['mask']);
2205 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2206 echo '</td><td>&nbsp;</td>';
2207 echo "</td><td>&nbsp;</td></tr>";
2208 }*/
2209 }
2210 }
2211
2212 // if $used is NULL, returns only human-formatted mask.
2213 // Otherwise returns "$used in/of " . human-formatted-mask
2214 function formatIPv6NetUsage ($used, $mask)
2215 {
2216 $prefixes = array
2217 (
2218 0 => '',
2219 3 => 'k',
2220 6 => 'M',
2221 9 => 'G',
2222 12 => 'T',
2223 15 => 'P',
2224 18 => 'E',
2225 21 => 'Z',
2226 24 => 'Y',
2227 );
2228
2229 if ($mask <= 64)
2230 {
2231 $what = '/64 net';
2232 $preposition = 'in';
2233 $mask += 64;
2234 }
2235 else
2236 {
2237 $what = 'IP';
2238 $preposition = 'of';
2239 }
2240 $what .= (0 == $mask % 64 ? '' : 's');
2241 $addrc = isset ($used) ? "$used $preposition " : '';
2242
2243 $dec_order = intval ((128 - $mask) / 10) * 3;
2244 $mult = isset ($prefixes[$dec_order]) ? $prefixes[$dec_order] : '??';
2245
2246 $cnt = 1 << ((128 - $mask) % 10);
2247 if ($cnt == 1 && $mult == '')
2248 $cnt = 'single';
2249
2250 return "<small>${addrc}${cnt}${mult} ${what}</small>";
2251 }
2252
2253 function renderIPv4Space ()
2254 {
2255 global $pageno, $tabno;
2256 $cellfilter = getCellFilter();
2257 $netlist = listCells ('ipv4net');
2258 $allcount = count ($netlist);
2259 $netlist = filterCellList ($netlist, $cellfilter['expression']);
2260 array_walk ($netlist, 'amplifyCell');
2261
2262 $netcount = count ($netlist);
2263 // expand request can take either natural values or "ALL". Zero means no expanding.
2264 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2265 $tree = prepareIPv4Tree ($netlist, $eid);
2266
2267 echo "<table border=0 class=objectview>\n";
2268 echo "<tr><td class=pcleft>";
2269 if (! renderEmptyResults($cellfilter, 'IPv4 nets', count($tree)))
2270 {
2271 startPortlet ("networks (${netcount})");
2272 echo '<h4>';
2273 if ($eid === 0)
2274 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2275 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2276 $cellfilter['urlextra'] . "'>expand all</a>)";
2277 elseif ($eid === 'ALL')
2278 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2279 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2280 else
2281 {
2282 $netinfo = spotEntity ('ipv4net', $eid);
2283 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2284 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2285 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2286 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2287 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2288 }
2289 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2290 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2291 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2292 echo '<th>VLAN</th>';
2293 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2294 echo "<th>routed by</th>";
2295 echo "</tr>\n";
2296 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2297 renderIPv4SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2298 echo "</table>\n";
2299 finishPortlet();
2300 }
2301
2302 echo '</td><td class=pcright>';
2303 renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
2304 echo "</td></tr></table>\n";
2305 }
2306
2307 function renderIPv6Space ()
2308 {
2309 global $pageno, $tabno;
2310 $cellfilter = getCellFilter();
2311 $netlist = listCells ('ipv6net');
2312 $allcount = count ($netlist);
2313 $netlist = filterCellList ($netlist, $cellfilter['expression']);
2314 array_walk ($netlist, 'amplifyCell');
2315
2316 $netcount = count ($netlist);
2317 // expand request can take either natural values or "ALL". Zero means no expanding.
2318 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
2319 $tree = prepareIPv6Tree ($netlist, $eid);
2320
2321 echo "<table border=0 class=objectview>\n";
2322 echo "<tr><td class=pcleft>";
2323 if (! renderEmptyResults($cellfilter, 'IPv6 nets', count($tree)))
2324 {
2325 startPortlet ("networks (${netcount})");
2326 echo '<h4>';
2327 if ($eid === 0)
2328 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') .
2329 " (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2330 $cellfilter['urlextra'] . "'>expand all</a>)";
2331 elseif ($eid === 'ALL')
2332 echo "expanding all (<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2333 $cellfilter['urlextra'] . "'>auto-collapse</a>)";
2334 else
2335 {
2336 $netinfo = spotEntity ('ipv6net', $eid);
2337 echo "expanding ${netinfo['ip']}/${netinfo['mask']} (<a href='" .
2338 makeHref (array ('page' => $pageno, 'tab' => $tabno)) .
2339 $cellfilter['urlextra'] . "'>auto-collapse</a> / <a href='" .
2340 makeHref (array ('page' => $pageno, 'tab' => $tabno, 'eid' => 'ALL')) .
2341 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>)";
2342 }
2343 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2344 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
2345 if (getConfigVar ('IPV4_TREE_SHOW_VLAN') == 'yes')
2346 echo '<th>VLAN</th>';
2347 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2348 echo "<th>routed by</th>";
2349 echo "</tr>\n";
2350 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
2351 renderIPv6SpaceRecords ($tree, $baseurl, $eid, $netcount == $allcount and getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
2352 echo "</table>\n";
2353 finishPortlet();
2354 }
2355
2356 echo '</td><td class=pcright>';
2357 renderCellFilterPortlet ($cellfilter, 'ipv6net', $netlist);
2358 echo "</td></tr></table>\n";
2359 }
2360
2361 function renderSLBDefConfig()
2362 {
2363 $defaults = getSLBDefaults ();
2364 startPortlet ('SLB default configs');
2365 echo '<table cellspacing=0 cellpadding=5 align=center>';
2366 printOpFormIntro ('save');
2367 echo '<tr><th class=tdright>VS config</th><td colspan=2><textarea tabindex=103 name=vsconfig rows=10 cols=80>' . htmlspecialchars($defaults['vs']) . '</textarea></td>';
2368 echo '<td rowspan=2>';
2369 printImageHREF ('SAVE', 'Save changes', TRUE);
2370 echo '</td></tr>';
2371 echo '<tr><th class=tdright>RS config</th><td colspan=2><textarea tabindex=104 name=rsconfig rows=10 cols=80>' . htmlspecialchars($defaults['rs']) . '</textarea></td></tr>';
2372 echo '</form></table>';
2373 finishPortlet();
2374 }
2375
2376 function renderIPv4SLB ()
2377 {
2378 global $page, $nextorder;
2379
2380 startPortlet ('SLB configuration');
2381 echo "<table border=0 width='100%'><tr>";
2382 foreach (array ('ipv4vslist', 'ipv4rsplist', 'rservers', 'lbs') as $pno)
2383 echo "<td><h3><a href='".makeHref(array('page'=>$pno))."'>" . $page[$pno]['title'] . "</a></h3></td>";
2384 echo '</tr></table>';
2385 finishPortlet();
2386
2387 $summary = getSLBSummary();
2388 startPortlet ('SLB tactical overview');
2389 // A single id-keyed array isn't used here to preserve existing
2390 // order of LBs returned by getSLBSummary()
2391 $lblist = array();
2392 $lbdname = array();
2393 foreach ($summary as $vipdata)
2394 foreach (array_keys ($vipdata['lblist']) as $lb_object_id)
2395 if (!in_array ($lb_object_id, $lblist))
2396 {
2397 $oi = spotEntity ('object', $lb_object_id);
2398 $lbdname[$lb_object_id] = $oi['dname'];
2399 $lblist[] = $lb_object_id;
2400 }
2401 if (!count ($summary))
2402 echo 'none configured';
2403 else
2404 {
2405 $order = 'odd';
2406 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2407 echo "<tr valign=top><td>&nbsp;</td>";
2408 foreach ($lblist as $lb_object_id)
2409 {
2410 #echo "<th><a href='".makeHref(array('page'=>'object', 'tab'=>'default', 'object_id'=>$lb_object_id))."'>" . $lbdname[$lb_object_id] . "</a></th>";
2411 echo '<td>';
2412 renderLBCell ($lb_object_id);
2413 echo '</td>';
2414 }
2415 echo "</tr>\n";
2416 foreach ($summary as $vsid => $vsdata)
2417 {
2418 echo "<tr class=row_${order}><td class=tdleft>";
2419 renderCell (spotEntity ('ipv4vs', $vsid));
2420 echo "</td>";
2421 foreach ($lblist as $lb_object_id)
2422 {
2423 echo '<td class=tdleft>';
2424 if (!isset ($vsdata['lblist'][$lb_object_id]))
2425 echo '&nbsp;';
2426 else
2427 {
2428 echo $vsdata['lblist'][$lb_object_id]['size'];
2429 // echo " (<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$vsdata['lblist'][$lb_object_id]['id'])). "'>";
2430 // echo $vsdata['lblist'][$lb_object_id]['name'] . '</a>)';
2431 }
2432 echo '</td>';
2433 }
2434 echo "</tr>\n";
2435 $order = $nextorder[$order];
2436 }
2437 echo "</table>\n";
2438 }
2439 finishPortlet ();
2440 }
2441
2442 function renderIPv4SpaceEditor ()
2443 {
2444 // IPv4 validator
2445 addJs ('js/live_validation.js');
2446 $regexp = addslashes ('^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$');
2447 addJs (<<<END
2448 $(document).ready(function () {
2449 document.add_new_range.range.setAttribute('match', '$regexp');
2450 Validate.init();
2451 });
2452 END
2453 , TRUE);
2454
2455 function printNewItemTR ()
2456 {
2457 startPortlet ('Add new');
2458 echo '<table border=0 cellpadding=10 align=center>';
2459 // This form requires a name, so JavaScript validator can find it.
2460 // No printOpFormIntro() hence
2461 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2462 echo "<input type=hidden name=op value=addIPv4Prefix>\n";
2463 // tags column
2464 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2465 renderNewEntityTags ('ipv4net');
2466 echo '</td>';
2467 // inputs column
2468 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2469 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=18 class='live-validate' tabindex=1 value='${prefix_value}'></td>";
2470 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2471 echo "<tr><th class=tdright>connected network</th><td class=tdleft><input type=checkbox name='is_bcast' tabindex=3></td></tr>";
2472 echo "<tr><td colspan=2>";
2473 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2474 echo '</td></tr>';
2475 echo "</form></table><br><br>\n";
2476 finishPortlet();
2477 }
2478
2479 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2480 printNewItemTR();
2481 if (count ($addrspaceList = listCells ('ipv4net')))
2482 {
2483 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2484 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2485 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
2486 array_walk ($addrspaceList, 'amplifyCell');
2487 $tree = prepareIPv4Tree ($addrspaceList, 'ALL');
2488 // this is only called for having "trace" set
2489 treeFromList ($addrspaceList);
2490 foreach ($addrspaceList as $netinfo)
2491 {
2492 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2493 // now we have all subnets listed in netinfo
2494 loadIPv4AddrList ($netinfo);
2495 $used = $netinfo['addrc'];
2496 $maxdirect = $netinfo['addrt'];
2497 $maxtotal = binInvMaskFromDec ($netinfo['mask']) + 1;
2498 echo "<tr valign=top><td>";
2499 if (count ($netinfo['addrlist']) && getConfigVar ('IPV4_JAYWALK') == 'no')
2500 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2501 else
2502 {
2503 echo "<a href='".makeHrefProcess(array('op'=>'delIPv4Prefix', 'id'=>$netinfo['id']))."'>";
2504 printImageHREF ('destroy', 'Delete this prefix');
2505 echo "</a>";
2506 }
2507 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv4net', 'id' => $netinfo['id'])) . '">';
2508 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
2509 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2510 if (count ($netinfo['etags']))
2511 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2512 echo '</td><td>';
2513 renderProgressBar ($maxdirect ? $used/$maxdirect : 0);
2514 echo "<br><small>${used}/${maxdirect}" . ($maxdirect == $maxtotal ? '' : "/${maxtotal}") . '</small></td>';
2515 echo '</tr>';
2516 }
2517 echo "</table>";
2518 finishPortlet();
2519 }
2520 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2521 printNewItemTR();
2522 }
2523
2524 function renderIPv6SpaceEditor ()
2525 {
2526 // IPv6 validator
2527 addJs ('js/live_validation.js');
2528 $regexp = addslashes ('^[a-fA-F0-9:]*:[a-fA-F0-9:\.]*/\d{1,3}$');
2529 addJs (<<<END
2530 $(document).ready(function () {
2531 document.add_new_range.range.setAttribute('match', '$regexp');
2532 Validate.init();
2533 });
2534 END
2535 , TRUE);
2536
2537 function printNewItemTR ()
2538 {
2539 startPortlet ('Add new');
2540 echo '<table border=0 cellpadding=10 align=center>';
2541 // This form requires a name, so JavaScript validator can find it.
2542 // No printOpFormIntro() hence
2543 echo "<form method=post name='add_new_range' action='".makeHrefProcess()."'>\n";
2544 echo "<input type=hidden name=op value=addIPv6Prefix>\n";
2545 // tags column
2546 echo '<tr><td rowspan=4><h3>assign tags</h3>';
2547 renderNewEntityTags ('ipv4net');
2548 echo '</td>';
2549 // inputs column
2550 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2551 echo "<th class=tdright>prefix</th><td class=tdleft><input type=text name='range' size=36 class='live-validate' tabindex=1 value='${prefix_value}'></td>";
2552 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=2></td></tr>";
2553 echo "<tr><td colspan=2>";
2554 printImageHREF ('CREATE', 'Add a new network', TRUE, 4);
2555 echo '</td></tr>';
2556 echo "</form></table><br><br>\n";
2557 finishPortlet();
2558 }
2559
2560 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
2561 printNewItemTR();
2562 if (count ($addrspaceList = listCells ('ipv6net')))
2563 {
2564 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2565 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2566 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
2567 array_walk ($addrspaceList, 'amplifyCell');
2568 $tree = prepareIPv6Tree ($addrspaceList, 'ALL');
2569 // this is only called for having "trace" set
2570 treeFromList ($addrspaceList);
2571 foreach ($addrspaceList as $netinfo)
2572 {
2573 $netinfo = peekNode ($tree, $netinfo['trace'], $netinfo['id']);
2574 // now we have all subnets listed in netinfo
2575 loadIPv6AddrList ($netinfo);
2576 echo "<tr valign=top><td>";
2577 if (count ($netinfo['addrlist']) && getConfigVar ('IPV4_JAYWALK') == 'no')
2578 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2579 else
2580 {
2581 echo "<a href='".makeHrefProcess (array ('op' => 'delIPv6Prefix', 'id' => $netinfo['id'])) . "'>";
2582 printImageHREF ('destroy', 'Delete this prefix');
2583 echo "</a>";
2584 }
2585 echo '</td><td class=tdleft><a href="' . makeHref (array ('page' => 'ipv6net', 'id' => $netinfo['id'])) . '">';
2586 echo "${netinfo['ip']}/${netinfo['mask']}</a></td>";
2587 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2588 if (count ($netinfo['etags']))
2589 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2590 echo '</td><td>';
2591 echo formatIPv6NetUsage ($netinfo['addrc'], $netinfo['mask']);
2592 echo '</tr>';
2593 }
2594 echo "</table>";
2595 finishPortlet();
2596 }
2597 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
2598 printNewItemTR();
2599 }
2600
2601 function renderIPv4Network ($id)
2602 {
2603 global $pageno, $tabno, $aac2, $netmaskbylen, $wildcardbylen;
2604
2605 $range = spotEntity ('ipv4net', $id);
2606 amplifyCell ($range);
2607 loadIPv4AddrList ($range);
2608 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2609 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2610 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2611
2612 echo "<tr><td class=pcleft width='50%'>";
2613 startPortlet ('summary');
2614 $total = ($range['ip_bin'] | $range['mask_bin_inv']) - ($range['ip_bin'] & $range['mask_bin']) + 1;
2615 $used = count ($range['addrlist']);
2616 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2617
2618 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2619 renderProgressBar ($used/$total);
2620 echo "&nbsp;${used}/${total}</td></tr>\n";
2621
2622 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2623 {
2624 // Build a backtrace from all parent networks.
2625 $clen = $range['mask'];
2626 $backtrace = array();
2627 while (NULL !== ($upperid = getIPv4AddressNetworkId ($range['ip'], $clen)))
2628 {
2629 $upperinfo = spotEntity ('ipv4net', $upperid);
2630 $clen = $upperinfo['mask'];
2631 $backtrace[] = $upperinfo;
2632 }
2633 $arrows = count ($backtrace);
2634 foreach (array_reverse ($backtrace) as $ainfo)
2635 {
2636 echo "<tr><th width='50%' class=tdright>";
2637 for ($i = 0; $i < $arrows; $i++)
2638 echo '&uarr;';
2639 $arrows--;
2640 echo "</th><td class=tdleft>";
2641 renderCell ($ainfo);
2642 echo "</td></tr>";
2643 }
2644 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
2645 echo "<td class=tdleft>";
2646 renderCell ($range);
2647 echo "</td></tr>";
2648 // FIXME: get and display nested networks
2649 // $theitem = pickLeaf ($ipv4tree, $id);
2650 }
2651
2652 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2653 echo $netmaskbylen[$range['mask']];
2654 echo "</td></tr>\n";
2655
2656 echo "<tr><th width='50%' class=tdright>Netmask:</th><td class=tdleft>";
2657 printf ('0x%08X', binMaskFromDec ($range['mask']));
2658 echo "</td></tr>\n";
2659
2660 echo "<tr><th width='50%' class=tdright>Wildcard bits:</th><td class=tdleft>";
2661 echo $wildcardbylen[$range['mask']];
2662 echo "</td></tr>\n";
2663
2664 foreach ($range['8021q'] as $item)
2665 {
2666 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
2667 echo '<tr><th width="50%" class=tdright>VLAN:</th><td class=tdleft><a href="';
2668 echo makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">';
2669 echo formatVLANName ($vlaninfo, 'markup long');
2670 echo '</a></td></tr>';
2671 }
2672 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
2673 {
2674 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2675 printRoutersTD ($routers);
2676 echo "</tr>\n";
2677 }
2678
2679 printTagTRs ($range, makeHref(array('page'=>'ipv4space', 'tab'=>'default'))."&");
2680 echo "</table><br>\n";
2681 finishPortlet();
2682
2683 if (strlen ($range['comment']))
2684 {
2685 startPortlet ('Comment');
2686 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2687 finishPortlet ();
2688 }
2689
2690 renderFilesPortlet ('ipv4net', $id);
2691 echo "</td>\n";
2692
2693 echo "<td class=pcright>";
2694 startPortlet ('details');
2695 $startip = $range['ip_bin'] & $range['mask_bin'];
2696 $endip = $range['ip_bin'] | $range['mask_bin_inv'];
2697 $realstartip = $startip;
2698 $realendip = $endip;
2699
2700 if (isset ($_REQUEST['hl_ipv4_addr']))
2701 {
2702 $hl_ip = ip2long ($_REQUEST['hl_ipv4_addr']);
2703 $hl_dottedquad = ip_long2quad ($hl_ip);
2704 addAutoScrollScript ("ip-$hl_dottedquad"); // scroll page to highlighted ip
2705 }
2706
2707 // pager
2708 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2709 $address_count = $endip - $startip + 1;
2710 $page = 0;
2711 if ($address_count > $maxperpage && $maxperpage > 0)
2712 {
2713 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? intval (($hl_ip - $startip) / $maxperpage) : 0);
2714 if ($numpages = ceil ($address_count / $maxperpage))
2715 {
2716 echo "<center>";
2717 echo '<h3>' . long2ip ($startip) . ' ~ ' . long2ip ($endip) . '</h3>';
2718 for ($i = 0; $i < $numpages; $i++)
2719 if ($i == $page)
2720 echo "<b>$i</b> ";
2721 else
2722 echo "<a href='".makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $id, 'pg' => $i)) . "'>$i</a> ";
2723 echo "</center>";
2724 }
2725 $startip = $startip + $page * $maxperpage;
2726 $endip = min ($startip + $maxperpage - 1, $endip);
2727 }
2728
2729 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
2730 echo "<tr><th>Address</th><th>Name</th><th>Allocation</th></tr>\n";
2731
2732 for ($ip = $startip; $ip <= $endip; $ip++) :
2733 $dottedquad = ip_long2quad($ip);
2734 $secondstyle = 'tdleft' . (isset ($hl_ip) && $hl_ip == $ip ? ' port_highlight' : '');
2735 if (!isset ($range['addrlist'][$ip]))
2736 {
2737 echo "<tr><td class=tdleft><a name='ip-$dottedquad' href='" . makeHref(array('page'=>'ipaddress', 'ip' => $dottedquad)) . "'>$dottedquad</a></td>";
2738 echo "<td class='${secondstyle}'>&nbsp;</td><td class='${secondstyle}'>&nbsp;</td></tr>\n";
2739 continue;
2740 }
2741 $addr = $range['addrlist'][$ip];
2742 echo "<tr class='${addr['class']}'>";
2743
2744 echo "<td class=tdleft><a name='ip-$dottedquad' href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
2745 echo "<td class='${secondstyle}'>${addr['name']}</td><td class='${secondstyle}'>";
2746 $delim = '';
2747 $prologue = '';
2748 if ( $addr['reserved'] == 'yes')
2749 {
2750 echo "<strong>RESERVED</strong> ";
2751 $delim = '; ';
2752 }
2753 foreach ($range['addrlist'][$ip]['allocs'] as $ref)
2754 {
2755 echo $delim . $aac2[$ref['type']];
2756 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'hl_ipv4_addr'=>$addr['ip']))."'>";
2757 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
2758 echo "${ref['object_name']}</a>";
2759 $delim = '; ';
2760 }
2761 if ($delim != '')
2762 {
2763 $delim = '';
2764 $prologue = '<br>';
2765 }
2766 foreach ($range['addrlist'][$ip]['lblist'] as $ref)
2767 {
2768 echo $prologue;
2769 $prologue = '';
2770 echo "${delim}<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id']))."'>";
2771 echo "${ref['object_name']}</a>:<a href='".makeHref(array('page'=>'ipv4vs', 'vs_id'=>$ref['vs_id']))."'>";
2772 echo "${ref['vport']}/${ref['proto']}</a>&rarr;";
2773 $delim = '; ';
2774 }
2775 if ($delim != '')
2776 {
2777 $delim = '';
2778 $prologue = '<br>';
2779 }
2780 foreach ($range['addrlist'][$ip]['rslist'] as $ref)
2781 {
2782 echo $prologue;
2783 $prologue = '';
2784 echo "${delim}&rarr;${ref['rsport']}@<a href='".makeHref(array('page'=>'ipv4rspool', 'pool_id'=>$ref['rspool_id']))."'>";
2785 echo "${ref['rspool_name']}</a>";
2786 $delim = '; ';
2787 }
2788 echo "</td></tr>\n";
2789 endfor;
2790 // end of iteration
2791
2792 echo "</table>";
2793 finishPortlet();
2794 echo "</td></tr></table>\n";
2795 }
2796
2797 // based on renderIPv4Network
2798 function renderIPv6Network ($id)
2799 {
2800 $range = spotEntity ('ipv6net', $id);
2801 amplifyCell ($range);
2802 loadIPv6AddrList ($range);
2803 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2804 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2805 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2806
2807 echo "<tr><td class=pcleft width='50%'>";
2808 startPortlet ('summary');
2809 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
2810 echo "<tr><th width='50%' class=tdright>%% used:</th><td class=tdleft>";
2811 echo "&nbsp;" . formatIPv6NetUsage (count ($range['addrlist']), $range['mask']) . "</td></tr>\n";
2812
2813 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
2814 {
2815 // Build a backtrace from all parent networks.
2816 $backtrace = array();
2817 $current = $range;
2818 while ($current['parent_id'])
2819 {
2820 $current = spotEntity ('ipv6net', $current['parent_id']);
2821 $backtrace[] = $current;
2822 }
2823 $arrows = count ($backtrace);
2824 foreach (array_reverse ($backtrace) as $ainfo)
2825 {
2826 echo "<tr><th width='50%' class=tdright>";
2827 for ($i = 0; $i < $arrows; $i++)
2828 echo '&uarr;';
2829 $arrows--;
2830 echo "</th><td class=tdleft>";
2831 renderCell ($ainfo);
2832 echo "</td></tr>";
2833 }
2834 echo "<tr><th width='50%' class=tdright>&rarr;</th>";
2835 echo "<td class=tdleft>";
2836 renderCell ($range);
2837 echo "</td></tr>";
2838 // FIXME: get and display nested networks
2839 }
2840
2841 foreach ($range['8021q'] as $item)
2842 {
2843 $vlaninfo = getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id']);
2844 echo '<tr><th width="50%" class=tdright>VLAN:</th><td class=tdleft><a href="';
2845 echo makeHref (array ('page' => 'vlan', 'vlan_ck' => $vlaninfo['vlan_ck'])) . '">';
2846 echo formatVLANName ($vlaninfo, 'markup long');
2847 echo '</a></td></tr>';
2848 }
2849 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
2850 {
2851 echo "<tr><th width='50%' class=tdright>Routed by:</th>";
2852 printRoutersTD ($routers);
2853 echo "</tr>\n";
2854 }
2855
2856 printTagTRs ($range, makeHref (array ('page' => 'ipv6space', 'tab' => 'default')) . "&");
2857 echo "</table><br>\n";
2858 finishPortlet();
2859
2860 if (strlen ($range['comment']))
2861 {
2862 startPortlet ('Comment');
2863 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2864 finishPortlet ();
2865 }
2866
2867 renderFilesPortlet ('ipv6net', $id);
2868 echo "</td>\n";
2869
2870 // render address list
2871 echo "<td class=pcright>";
2872 startPortlet ('details');
2873 renderIPv6NetworkAddresses ($range);
2874 finishPortlet();
2875 echo "</td></tr></table>\n";
2876 }
2877
2878 // Used solely by renderSeparator
2879 function renderEmptyIPv6 ($ip, $hl_ip)
2880 {
2881 $class = 'tdleft';
2882 if (isset ($hl_ip) && $ip == $hl_ip)
2883 $class .= ' port_highlight';
2884 $fmt = $ip->format();
2885 echo "<tr><td class=tdleft><a name='ip-$fmt' href='" . makeHref (array ('page' => 'ipv6address', 'ip' => $fmt)) . "'>" . $fmt;
2886 echo "</a></td><td class='${class}'>&nbsp;&