support blades of varying sizes in the same chassis (#923)
[racktables] / wwwroot / inc / interface.php
CommitLineData
b325120a 1<?php
cddbb9fd
DO
2
3# This file is a part of RackTables, a datacenter and server room management
4# framework. See accompanying file "COPYING" for the full copyright and
5# licensing information.
6
e673ee24
DO
7/*
8*
9* This file contains frontend functions for RackTables.
10*
11*/
12
e82deb48 13require_once 'ajax-interface.php';
defd92d8 14require_once 'slb-interface.php';
65e557dd 15
9c0b0016
DO
16// Interface function's special.
17$nextorder['odd'] = 'even';
18$nextorder['even'] = 'odd';
19
52c836b1
DO
20// address allocation type
21$aat = array
22(
23 'regular' => 'Connected',
24 'virtual' => 'Loopback',
25 'shared' => 'Shared',
26 'router' => 'Router',
27);
beb9e88a 28// address allocation code, IPv4 addresses and objects view
52c836b1
DO
29$aac = array
30(
31 'regular' => '',
4318ced5
AA
32 'virtual' => '<span class="aac">L</span>',
33 'shared' => '<span class="aac">S</span>',
34 'router' => '<span class="aac">R</span>',
52c836b1 35);
beb9e88a
DO
36// address allocation code, IPv4 networks view
37$aac2 = array
38(
39 'regular' => '',
40 'virtual' => '<strong>L:</strong>',
29025f8e 41 'shared' => '<strong>S:</strong>',
beb9e88a
DO
42 'router' => '<strong>R:</strong>',
43);
52c836b1 44
0dabdc53
DO
45$vtdecoder = array
46(
47 'ondemand' => '',
54b7ced3
DO
48 'compulsory' => 'P',
49# 'alien' => 'NT',
0dabdc53
DO
50);
51
52$vtoptions = array
53(
54b7ced3
DO
54 'ondemand' => 'auto',
55 'compulsory' => 'permanent',
56# 'alien' => 'never touch',
0dabdc53
DO
57);
58
e5c4506d
DO
59// This may be populated later onsite, report rendering function will use it.
60// See the $systemreport for structure.
61$localreports = array();
d6adad3e 62
9db67d95
DO
63$CodePressMap = array
64(
65 'sql' => 'sql',
66 'php' => 'php',
cf5da67e 67 'html' => 'htmlmixed',
9db67d95
DO
68 'css' => 'css',
69 'js' => 'javascript',
70);
e5c4506d 71
8d4f7d18
DO
72$attrtypes = array
73(
74 'uint' => '[U] unsigned integer',
75 'float' => '[F] floating point',
76 'string' => '[S] string',
86ff26ae
DO
77 'dict' => '[D] dictionary record',
78 'date' => '[T] date'
8d4f7d18
DO
79);
80
a1d72d2e
AA
81$quick_links = NULL; // you can override this in your local.php, but first initialize it with getConfiguredQuickLinks()
82
83function renderQuickLinks()
84{
85 global $quick_links;
86 if (! isset ($quick_links))
87 $quick_links = getConfiguredQuickLinks();
88 echo '<ul class="qlinks">';
89 foreach ($quick_links as $link)
90 echo '<li><a href="' . $link['href'] . '">' . str_replace (' ', '&nbsp;', $link['title']) . '</a></li>';
91 echo '</ul>';
92}
93
f97df464
DO
94function renderInterfaceHTML ($pageno, $tabno, $payload)
95{
96?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
97<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
98<head><title><?php echo getTitle ($pageno); ?></title>
99<?php printPageHeaders(); ?>
100</head>
101<body>
b2937330
AA
102<div class="maintable">
103 <div class="mainheader">
104 <div style="float: right" class=greeting><a href='index.php?page=myaccount&tab=default'><?php global $remote_displayname; echo $remote_displayname ?></a> [ <a href='?logout'>logout</a> ]</div>
a1d72d2e 105 <?php echo getConfigVar ('enterprise') ?> RackTables <a href="http://racktables.org" title="Visit RackTables site"><?php echo CODE_VERSION ?></a><?php renderQuickLinks() ?>
b2937330 106 </div>
d688a63f 107 <div class="menubar"><?php showPathAndSearch ($pageno, $tabno); ?></div>
b2937330
AA
108 <div class="tabbar"><?php showTabs ($pageno, $tabno); ?></div>
109 <div class="msgbar"><?php showMessageOrError(); ?></div>
110 <div class="pagebar"><?php echo $payload; ?></div>
111</div>
f97df464
DO
112</body>
113</html>
114<?php
115}
116
e673ee24 117// Main menu.
f2168c4b
DO
118function renderIndexItem ($ypageno)
119{
120 echo (! permitted ($ypageno)) ? " <td>&nbsp;</td>\n" :
121 " <td>\n" .
122 " <h1><a href='" . makeHref (array ('page' => $ypageno)) . "'>" .
123 getPageName ($ypageno) . "<br>\n" . getImageHREF ($ypageno) .
124 "</a></h1>\n" .
125 " </td>\n";
4b680876
DO
126}
127
e673ee24
DO
128function renderIndex ()
129{
67c5c049 130 global $indexlayout;
e673ee24
DO
131?>
132<table border=0 cellpadding=0 cellspacing=0 width='100%'>
133 <tr>
134 <td>
135 <div style='text-align: center; margin: 10px; '>
a544d2c4 136 <table width='100%' cellspacing=0 cellpadding=20 class=mainmenu border=0>
4b680876 137<?php
67c5c049
DO
138foreach ($indexlayout as $row)
139{
140 echo '<tr>';
141 foreach ($row as $column)
142 if ($column === NULL)
143 echo '<td>&nbsp;</td>';
144 else
145 renderIndexItem ($column);
146 echo '</tr>';
147}
148?>
e673ee24
DO
149 </table>
150 </div>
151 </td>
152 </tr>
153</table>
b325120a 154<?php
e673ee24
DO
155}
156
f3505b35
AA
157function getRenderedAlloc ($object_id, $alloc)
158{
159 $ret = array
160 (
161 'tr_class' => '',
40c9fc94 162 'td_name_suffix' => '',
f3505b35
AA
163 'td_ip' => '',
164 'td_network' => '',
165 'td_routed_by' => '',
166 'td_peers' => '',
167 );
168 $dottedquad = $alloc['addrinfo']['ip'];
4318ced5 169 $ip_bin = $alloc['addrinfo']['ip_bin'];
f3505b35 170
4318ced5
AA
171 $hl_ip_bin = NULL;
172 if (isset ($_REQUEST['hl_ip']))
f3505b35 173 {
4318ced5
AA
174 $hl_ip_bin = ip_parse ($_REQUEST['hl_ip']);
175 addAutoScrollScript ("ip-" . $_REQUEST['hl_ip']);
f3505b35
AA
176 }
177
178 $ret['tr_class'] = $alloc['addrinfo']['class'];
4318ced5 179 if ($hl_ip_bin === $ip_bin)
5c717ce5 180 $ret['tr_class'] .= ' highlight';
dec748f6 181
68c91b9c
AA
182 // render IP change history
183 $ip_title = '';
184 $ip_class = '';
185 if (isset ($alloc['addrinfo']['last_log']))
186 {
187 $log = $alloc['addrinfo']['last_log'];
188 $ip_title = "title='" .
189 htmlspecialchars
190 (
191 $log['user'] . ', ' . formatAge ($log['time']),
192 ENT_QUOTES
193 ) . "'";
194 $ip_class = 'hover-history underline';
195 }
196
f3505b35
AA
197 // render IP address td
198 global $aac;
4318ced5
AA
199 $netinfo = spotNetworkByIP ($ip_bin);
200 $ret['td_ip'] = "<td class='tdleft'>";
201 if (isset ($netinfo))
202 {
203 $title = $dottedquad;
204 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
205 $title .= '/' . $netinfo['mask'];
68c91b9c 206 $ret['td_ip'] .= "<a name='ip-$dottedquad' class='$ip_class' $ip_title href='" .
f3505b35
AA
207 makeHref (
208 array
209 (
4318ced5 210 'page' => 'ipaddress',
f3505b35
AA
211 'hl_object_id' => $object_id,
212 'ip' => $dottedquad,
213 )
4318ced5
AA
214 ) . "'>$title</a>";
215 }
f3505b35 216 else
68c91b9c 217 $ret['td_ip'] .= "<span class='$ip_class' $ip_title>$dottedquad</span>";
4318ced5 218 $ret['td_ip'] .= $aac[$alloc['type']];
f3505b35
AA
219 if (strlen ($alloc['addrinfo']['name']))
220 $ret['td_ip'] .= ' (' . niftyString ($alloc['addrinfo']['name']) . ')';
221 $ret['td_ip'] .= '</td>';
222
223 // render network and routed_by tds
4318ced5
AA
224 $td_class = 'tdleft';
225 if (! isset ($netinfo))
f3505b35
AA
226 {
227 $ret['td_network'] = "<td class='$td_class sparenetwork'>N/A</td>";
228 $ret['td_routed_by'] = $ret['td_network'];
229 }
230 else
231 {
232 $ret['td_network'] = "<td class='$td_class'>" .
233 getOutputOf ('renderCell', $netinfo) . '</td>';
234
98350e52
AA
235 // render "routed by" td
236 if ($display_routers = (getConfigVar ('IPV4_TREE_RTR_AS_CELL') == 'none'))
237 $ret['td_routed_by'] = '';
f3505b35 238 else
98350e52
AA
239 {
240 loadIPAddrList ($netinfo);
241 $other_routers = array();
242 foreach (findRouters ($netinfo['own_addrlist']) as $router)
243 if ($router['id'] != $object_id)
244 $other_routers[] = $router;
245 if (count ($other_routers))
246 $ret['td_routed_by'] = getOutputOf ('printRoutersTD', $other_routers, $display_routers);
247 else
248 $ret['td_routed_by'] = "<td class='$td_class'>&nbsp;</td>";
249 }
f3505b35 250 }
dec748f6 251
f3505b35
AA
252 // render peers td
253 $ret['td_peers'] = "<td class='$td_class'>";
254 $prefix = '';
255 if ($alloc['addrinfo']['reserved'] == 'yes')
256 {
257 $ret['td_peers'] .= $prefix . '<strong>RESERVED</strong>';
258 $prefix = '; ';
259 }
260 foreach ($alloc['addrinfo']['allocs'] as $allocpeer)
261 {
262 if ($allocpeer['object_id'] == $object_id)
263 continue;
264 $ret['td_peers'] .= $prefix . "<a href='" . makeHref (array ('page' => 'object', 'object_id' => $allocpeer['object_id'])) . "'>";
265 if (isset ($allocpeer['osif']) and strlen ($allocpeer['osif']))
266 $ret['td_peers'] .= $allocpeer['osif'] . '@';
267 $ret['td_peers'] .= $allocpeer['object_name'] . '</a>';
268 $prefix = '; ';
269 }
270 $ret['td_peers'] .= '</td>';
271
272 return $ret;
273}
274
e1add254
AD
275function renderLocationFilterPortlet ()
276{
e1add254 277 // Recursive function used to build the location tree
2056822d 278 function renderLocationCheckbox ($subtree, $level = 0)
e1add254
AD
279 {
280 $self = __FUNCTION__;
e1add254 281
2056822d 282 foreach ($subtree as $location_id => $location)
e1add254 283 {
9f68b666 284 echo "<div class=tagbox style='text-align:left; padding-left:" . ($level * 16) . "px;'>";
2056822d 285 $checked = (in_array ($location['id'], $_SESSION['locationFilter'])) ? 'checked' : '';
9c88bba9 286 echo "<label><input type=checkbox name='location_id[]' class=${level} value='${location['id']}'${checked} onClick=checkAll(this)>${location['name']}";
9f68b666 287 echo '</label>';
2056822d 288 if ($location['kidc'])
9f68b666
AD
289 {
290 echo "<a id='lfa" . $location['id'] . "' onclick=\"expand('${location['id']}')\" href\"#\" > - </a>";
291 echo "<div id='lfd" . $location['id'] . "'>";
2056822d 292 $self ($location['kids'], $level + 1);
9f68b666
AD
293 echo '</div>';
294 }
295 echo '</div>';
e1add254
AD
296 }
297 }
298
9c88bba9
AD
299 addJS(<<<END
300function checkAll(bx) {
301 for (var tbls=document.getElementsByTagName("table"), i=tbls.length; i--;)
4e9e1b7a 302 if (tbls[i].id == "locationFilter") {
9c88bba9
AD
303 var bxs=tbls[i].getElementsByTagName("input");
304 var in_tree = false;
9f68b666 305 for (var j=0; j<bxs.length; j++) {
9c88bba9
AD
306 if(in_tree == false && bxs[j].value == bx.value)
307 in_tree = true;
308 else if(parseInt(bxs[j].className) <= parseInt(bx.className))
309 in_tree = false;
310 if (bxs[j].type=="checkbox" && in_tree == true)
311 bxs[j].checked = bx.checked;
312 }
313 }
314}
9f68b666
AD
315
316function collapseAll(bx) {
317 for (var tbls=document.getElementsByTagName("table"), i=tbls.length; i--;)
318 if (tbls[i].id == "locationFilter") {
319 var bxs=tbls[i].getElementsByTagName("div");
320 //loop through divs to hide unchecked
321 for (var j=0; j<bxs.length; j++) {
322 var is_checked = -1;
323 var in_div=bxs[j].getElementsByTagName("input");
324 //loop through input to find if any is checked
325 for (var k=0; k<in_div.length; k++) {
326 if(in_div[k].type="checkbox") {
327 if (in_div[k].checked == true) {
328 is_checked = true;
329 break;
330 }
331 else
332 is_checked = false;
333 }
334 }
335 // nothing selected and element id is lfd, collapse it
336 if (is_checked == false && !bxs[j].id.indexOf("lfd"))
337 expand(bxs[j].id.substr(3));
338 }
339 }
340}
341
342function expand(id) {
343 var divid = document.getElementById("lfd" + id);
344 var iconid = document.getElementById("lfa" + id);
345 if (divid.style.display == 'none') {
346 divid.style.display = 'block';
347 iconid.innerHTML = ' - ';
348 } else {
349 divid.style.display = 'none';
350 iconid.innerHTML = ' + ';
351 }
352}
9c88bba9
AD
353END
354 ,TRUE);
e1add254
AD
355 startPortlet ('Location filter');
356 echo <<<END
9c88bba9 357<table border=0 align=center cellspacing=0 class="tagtree" id="locationFilter">
6b816bde 358 <form method=post>
e1add254
AD
359 <input type=hidden name=page value=rackspace>
360 <input type=hidden name=tab value=default>
361 <input type=hidden name=changeLocationFilter value=true>
362END;
2056822d
AA
363
364 $locationlist = listCells ('location');
e1add254
AD
365 if (count ($locationlist))
366 {
9c88bba9
AD
367 echo "<tr><td class=tagbox style='padding-left: 0px'><label>";
368 echo "<input type=checkbox name='location' onClick=checkAll(this)> Toggle all";
9f68b666 369 echo "<img src=pix/1x1t.gif onLoad=collapseAll(this)>"; // dirty hack to collapse all when page is displayed
9c88bba9 370 echo "</label></td></tr>\n";
9f68b666 371 echo "<tr><td class=tagbox><hr>\n";
2056822d 372 renderLocationCheckbox (treeFromList ($locationlist));
9f68b666
AD
373 echo "<hr></td></tr>\n";
374 echo '<tr><td>';
e1add254
AD
375 printImageHREF ('setfilter', 'set filter', TRUE);
376 echo "</td></tr>\n";
377 }
378 else
379 {
380 echo "<tr><td class='tagbox sparenetwork'>(no locations exist)</td></tr>\n";
381 echo "<tr><td>";
382 printImageHREF ('setfilter gray');
383 echo "</td></tr>\n";
384 }
385
386 echo "</form></table>\n";
387 finishPortlet ();
388}
389
e673ee24
DO
390function renderRackspace ()
391{
e1add254
AD
392 // Handle the location filter
393 @session_start();
394 if (isset ($_REQUEST['changeLocationFilter']))
395 unset ($_SESSION['locationFilter']);
396 if (isset ($_REQUEST['location_id']))
397 $_SESSION['locationFilter'] = $_REQUEST['location_id'];
398 if (!isset ($_SESSION['locationFilter']))
dec748f6 399 $_SESSION['locationFilter'] = array_keys (listCells ('location')); // Add all locations to the filter
5d6352df 400 session_commit();
e1add254 401
95857b5c
DO
402 $found_racks = array();
403 $rows = array();
a8efc03e 404 $cellfilter = getCellFilter();
1ebbf889 405 $rackCount = 0;
e1add254
AD
406 foreach (getAllRows() as $row_id => $rowInfo)
407 {
95857b5c 408 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
e1add254
AD
409 $found_racks = array_merge ($found_racks, $rackList);
410 $rows[] = array (
411 'location_id' => $rowInfo['location_id'],
412 'location_name' => $rowInfo['location_name'],
95857b5c 413 'row_id' => $row_id,
e1add254 414 'row_name' => $rowInfo['name'],
95857b5c
DO
415 'racks' => $rackList
416 );
1ebbf889 417 $rackCount += count($rackList);
95857b5c 418 }
1ebbf889 419
95857b5c 420 echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
1ebbf889
AA
421
422 if (! renderEmptyResults($cellfilter, 'racks', $rackCount))
e673ee24 423 {
1ebbf889
AA
424 // generate thumb gallery
425 global $nextorder;
426 $rackwidth = getRackImageWidth();
427 // Zero value effectively disables the limit.
428 $maxPerRow = getConfigVar ('RACKS_PER_ROW');
429 $order = 'odd';
e1add254 430 if (count ($rows))
1ebbf889 431 {
e1add254
AD
432 echo '<table border=0 cellpadding=10 class=cooltable>';
433 echo '<tr><th class=tdleft>Location</th><th class=tdleft>Row</th><th class=tdleft>Racks</th></tr>';
434 foreach ($rows as $row)
435 {
436 $location_id = $row['location_id'];
437 $row_id = $row['row_id'];
438 $row_name = $row['row_name'];
439 $rackList = $row['racks'];
440
441 if (($location_id != '' and !in_array ($location_id, $_SESSION['locationFilter'])) or (!count ($rackList) and count ($cellfilter['expression'])))
442 continue;
443 $rackListIdx = 0;
444 echo "<tr class=row_${order}><th class=tdleft>";
c08915c7
AD
445 $locationTree = '';
446 while ($location_id)
447 {
448 $parentLocation = spotEntity ('location', $location_id);
ec459a0b 449 $locationTree = "&raquo; <a href='" .
c08915c7
AD
450 makeHref(array('page'=>'location', 'location_id'=>$parentLocation['id'])) .
451 "${cellfilter['urlextra']}'>${parentLocation['name']}</a> " .
452 $locationTree;
453 $location_id = $parentLocation['parent_id'];
454 }
455 $locationTree = substr ($locationTree, 8);
456 echo $locationTree;
e1add254
AD
457 echo "</th><th class=tdleft><a href='".makeHref(array('page'=>'row', 'row_id'=>$row_id))."${cellfilter['urlextra']}'>${row_name}</a></th>";
458 echo "<th class=tdleft><table border=0 cellspacing=5><tr>";
459 if (!count ($rackList))
460 echo "<td>(empty row)</td>";
461 else
462 foreach ($rackList as $rack)
1ebbf889 463 {
e1add254
AD
464 if ($rackListIdx > 0 and $maxPerRow > 0 and $rackListIdx % $maxPerRow == 0)
465 {
42504426 466 echo '</tr></table></th></tr>';
e1add254
AD
467 echo "<tr class=row_${order}><th class=tdleft></th><th class=tdleft>${row_name} (continued)";
468 echo "</th><th class=tdleft><table border=0 cellspacing=5><tr>";
469 }
470 echo "<td align=center valign=bottom><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
471 echo "<img border=0 width=${rackwidth} height=";
472 echo getRackImageHeight ($rack['height']);
473 echo " title='${rack['height']} units'";
474 echo "src='?module=image&img=minirack&rack_id=${rack['id']}'>";
475 echo "<br>${rack['name']}</a></td>";
476 $rackListIdx++;
1ebbf889 477 }
e1add254 478 $order = $nextorder[$order];
42504426 479 echo "</tr></table></th></tr>\n";
e1add254 480 }
42504426 481 echo "</table>\n";
1ebbf889 482 }
e1add254
AD
483 else
484 echo "<h2>No rows found</h2>\n";
e673ee24 485 }
14ad4f4a
DO
486 echo '</td><td class=pcright width="25%">';
487 renderCellFilterPortlet ($cellfilter, 'rack', $found_racks);
e1add254
AD
488 echo "<br>\n";
489 renderLocationFilterPortlet ();
489a7502 490 echo "</td></tr></table>\n";
e673ee24
DO
491}
492
2056822d 493function renderLocationRowForEditor ($subtree, $level = 0)
e1add254
AD
494{
495 $self = __FUNCTION__;
2056822d
AA
496 foreach ($subtree as $locationinfo)
497 {
498 echo "<tr><td align=left style='padding-left: " . ($locationinfo['kidc'] ? $level : ($level + 1) * 16) . "px;'>";
499 if ($locationinfo['kidc'])
500 printImageHREF ('node-expanded-static');
501 if ($locationinfo['refcnt'] > 0 || $locationinfo['kidc'] > 0)
502 printImageHREF ('nodestroy');
503 else
10f5133a 504 echo getOpLink (array ('op' => 'deleteLocation', 'location_id' => $locationinfo['id']), '', 'destroy', 'Delete location');
2056822d
AA
505 echo '</td><td class=tdleft>';
506 printOpFormIntro ('updateLocation', array ('location_id' => $locationinfo['id']));
507 $parent = isset ($locationinfo['parent_id']) ? $locationinfo['parent_id'] : 0;
508 echo getSelect
509 (
510 array ( $parent => $parent ? htmlspecialchars ($locationinfo['parent_name']) : '-- NONE --'),
511 array ('name' => 'parent_id', 'id' => 'locationid_' . $locationinfo['id'], 'class' => 'locationlist-popup'),
512 $parent,
513 FALSE
514 );
515 echo "</td><td class=tdleft>";
516 echo "<input type=text size=48 name=name value='${locationinfo['name']}'>";
517 echo '</td><td>' . getImageHREF ('save', 'Save changes', TRUE) . "</form></td></tr>\n";
518 if ($locationinfo['kidc'])
519 $self ($locationinfo['kids'], $level + 1);
520 }
e1add254
AD
521}
522
eda41675
AD
523function renderLocationSelectTree ($selected_id = NULL)
524{
525 echo '<option value=0>-- NONE --</option>';
526 foreach (treeFromList (listCells ('location')) as $location)
527 {
528 echo "<option value=${location['id']} style='font-weight: bold' ";
529 if ($location['id'] == $selected_id )
530 echo ' selected';
531 echo ">${location['name']}</option>";
532 printLocationChildrenSelectOptions ($location, 0, $selected_id);
533 }
534 echo '</select>';
535}
536
e1add254
AD
537function renderRackspaceLocationEditor ()
538{
539 addJS
540 (
541<<<END
542function locationeditor_showselectbox(e) {
543 $(this).load('index.php', {module: 'ajax', ac: 'get-location-select', locationid: this.id});
544 $(this).unbind('mousedown', locationeditor_showselectbox);
545}
546$(document).ready(function () {
547 $('select.locationlist-popup').bind('mousedown', locationeditor_showselectbox);
548});
549END
550 , TRUE
551 );
552 function printNewItemTR ()
553 {
e1add254 554 printOpFormIntro ('addLocation');
eda41675 555 echo '<tr><td>';
e1add254 556 printImageHREF ('create', 'Add new location', TRUE);
eda41675
AD
557 echo '</td><td><select name=parent_id tabindex=100>';
558 renderLocationSelectTree ();
559 echo '</td><td><input type=text size=48 name=name tabindex=101></td><td>';
e1add254
AD
560 printImageHREF ('create', 'Add new location', TRUE, 102);
561 echo "</td></tr></form>\n";
562 }
e1add254
AD
563
564 startPortlet ('Locations');
565 echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
566 echo "<tr><th>&nbsp;</th><th>Parent</th><th>Name</th><th>&nbsp;</th></tr>\n";
567 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
568 printNewItemTR();
2056822d 569
1e0f13f3
AD
570 $locations = listCells ('location');
571 renderLocationRowForEditor (treeFromList ($locations));
2056822d 572
e1add254
AD
573 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
574 printNewItemTR();
575 echo "</table><br>\n";
576 finishPortlet();
577}
578
345fd640
AD
579function renderRackspaceRowEditor ()
580{
eda41675 581 function printNewItemTR ()
345fd640
AD
582 {
583 printOpFormIntro ('addRow');
eda41675 584 echo '<tr><td>';
7be51fea 585 printImageHREF ('create', 'Add new row', TRUE);
eda41675
AD
586 echo '</td><td><select name=location_id tabindex=100>';
587 renderLocationSelectTree ();
c5762190 588 echo '</td><td><input type=text name=name tabindex=100></td><td>';
e1add254 589 printImageHREF ('create', 'Add new row', TRUE, 102);
eda41675 590 echo '</td></tr></form>';
345fd640 591 }
d732e47e 592 startPortlet ('Rows');
345fd640 593 echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
e1add254 594 echo "<tr><th>&nbsp;</th><th>Location</th><th>Name</th><th>&nbsp;</th></tr>\n";
345fd640 595 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
eda41675 596 printNewItemTR ();
e1add254 597 foreach (getAllRows() as $row_id => $rowInfo)
345fd640 598 {
eda41675 599 echo '<tr><td>';
4e9e1b7a 600 if ($rc = $rowInfo['rackc'])
6c18dd08 601 printImageHREF ('nodestroy', "${rc} rack(s) here");
7be51fea 602 else
10f5133a 603 echo getOpLink (array('op'=>'deleteRow', 'row_id'=>$row_id), '', 'destroy', 'Delete row');
c40666f5 604 printOpFormIntro ('updateRow', array ('row_id' => $row_id));
eda41675
AD
605 echo '</td><td>';
606 echo '<select name=location_id tabindex=100>';
607 renderLocationSelectTree ($rowInfo['location_id']);
c5762190 608 echo "</td><td><input type=text name=name value='${rowInfo['name']}' tabindex=100></td><td>";
7be51fea
DO
609 printImageHREF ('save', 'Save changes', TRUE);
610 echo "</form></td></tr>\n";
345fd640
AD
611 }
612 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
eda41675 613 printNewItemTR ();
345fd640
AD
614 echo "</table><br>\n";
615 finishPortlet();
616}
617
7e1db771 618function renderRow ($row_id)
e673ee24 619{
e16b666c 620 $rowInfo = getRowInfo ($row_id);
a8efc03e
DO
621 $cellfilter = getCellFilter();
622 $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
e673ee24
DO
623 // Main layout starts.
624 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
625
626 // Left portlet with row information.
627 echo "<tr><td class=pcleft>";
a8ce7234 628 startPortlet ($rowInfo['name']);
e673ee24 629 echo "<table border=0 cellspacing=0 cellpadding=3 width='100%'>\n";
58295e8c
AD
630 if ($rowInfo['location_id'])
631 echo "<tr><th width='50%' class=tdright>Location:</th><td class=tdleft>".mkA ($rowInfo['location'], 'location', $rowInfo['location_id'])."</td></tr>\n";
5af82683
DY
632 echo "<tr><th width='50%' class=tdright>Racks:</th><td class=tdleft>${rowInfo['count']}</td></tr>\n";
633 echo "<tr><th width='50%' class=tdright>Units:</th><td class=tdleft>${rowInfo['sum']}</td></tr>\n";
9b8174d7
AD
634 echo "<tr><th width='50%' class=tdright>% used:</th><td class=tdleft>";
635 renderProgressBar (getRSUforRow ($rackList));
114e50af 636 echo "</td></tr>\n";
e673ee24
DO
637 echo "</table><br>\n";
638 finishPortlet();
7f297114 639 renderCellFilterPortlet ($cellfilter, 'rack', $rackList, array ('row_id' => $row_id));
e673ee24 640
6ccfd4bd 641 renderFilesPortlet ('row',$row_id);
48325652 642 echo "</td><td class=pcright>";
e673ee24 643
4fbb5a00 644 global $nextorder;
d5157018 645 $rackwidth = getRackImageWidth() * getConfigVar ('ROW_SCALE');
f5883ec1
DO
646 // Maximum number of racks per row is proportionally less, but at least 1.
647 $maxPerRow = max (floor (getConfigVar ('RACKS_PER_ROW') / getConfigVar ('ROW_SCALE')), 1);
648 $rackListIdx = 0;
e673ee24
DO
649 $order = 'odd';
650 startPortlet ('Racks');
651 echo "<table border=0 cellspacing=5 align='center'><tr>";
64b95774 652 foreach ($rackList as $rack)
e673ee24 653 {
f5883ec1
DO
654 if ($rackListIdx % $maxPerRow == 0)
655 {
656 if ($rackListIdx > 0)
657 echo '</tr>';
658 echo '<tr>';
659 }
9b8174d7 660 $class = ($rack['has_problems'] == 'yes') ? 'error' : $order;
d69e5d6f 661 echo "<td align=center valign=bottom class=row_${class}><a href='".makeHref(array('page'=>'rack', 'rack_id'=>$rack['id']))."'>";
d5157018 662 echo "<img border=0 width=${rackwidth} height=" . (getRackImageHeight ($rack['height']) * getConfigVar ('ROW_SCALE'));
e673ee24 663 echo " title='${rack['height']} units'";
e696bef6 664 echo "src='?module=image&img=midirack&rack_id=${rack['id']}&scale=" . getConfigVar ('ROW_SCALE') . "'>";
e673ee24
DO
665 echo "<br>${rack['name']}</a></td>";
666 $order = $nextorder[$order];
f5883ec1 667 $rackListIdx++;
e673ee24
DO
668 }
669 echo "</tr></table>\n";
670 finishPortlet();
e673ee24
DO
671 echo "</td></tr></table>";
672}
673
0a7feebb 674// Used by renderRack()
84feb87b 675function printObjectDetailsForRenderRack ($object_id, $hl_obj_id = 0)
0a7feebb
AD
676{
677 $objectData = spotEntity ('object', $object_id);
678 if (strlen ($objectData['asset_no']))
679 $prefix = "<div title='${objectData['asset_no']}";
680 else
681 $prefix = "<div title='no asset tag";
682 // Don't tell about label, if it matches common name.
683 $body = '';
684 if ($objectData['name'] != $objectData['label'] and strlen ($objectData['label']))
685 $body = ", visible label is \"${objectData['label']}\"";
686 // Display list of child objects, if any
687 $objectChildren = getEntityRelatives ('children', 'object', $objectData['id']);
be28528c 688 $slotRows = $slotCols = $slotInfo = $slotData = $slotTitle = array ();
0a7feebb
AD
689 if (count($objectChildren) > 0)
690 {
691 foreach ($objectChildren as $child)
84feb87b 692 {
0a7feebb 693 $childNames[] = $child['name'];
84feb87b 694 $childData = spotEntity ('object', $child['entity_id']);
ec459a0b 695 $attrData = getAttrValues ($child['entity_id']);
be28528c
M
696 $numRows = $numCols = 1;
697 if (isset ($attrData[2])) // HW type
698 {
699 extractLayout ($attrData[2]);
700 if (isset ($attrData[2]['rows']))
701 {
702 $numRows = $attrData[2]['rows'];
703 $numCols = $attrData[2]['cols'];
704 }
705 }
05abd358 706 if (isset ($attrData['28'])) // slot number
84feb87b
AD
707 {
708 $slot = $attrData['28']['value'];
be28528c
M
709 if (preg_match ('/\d+/', $slot, $matches))
710 $slot = $matches[0];
711 $slotRows[$slot] = $numRows;
712 $slotCols[$slot] = $numCols;
84feb87b
AD
713 $slotInfo[$slot] = $child['name'];
714 $slotData[$slot] = $child['entity_id'];
715 if (strlen ($childData['asset_no']))
716 $slotTitle[$slot] = "<div title='${childData['asset_no']}";
717 else
718 $slotTitle[$slot] = "<div title='no asset tag";
719 if (strlen ($childData['label']) and $childData['label'] != $child['name'])
720 $slotTitle[$slot] .= ", visible label is \"${childData['label']}\"";
721 $slotTitle[$slot] .= "'>";
722 }
723 }
0a7feebb
AD
724 natsort($childNames);
725 $suffix = sprintf(", contains %s'>", implode(', ', $childNames));
726 }
727 else
728 $suffix = "'>";
ad3e5e7e 729 echo "${prefix}${body}${suffix}" . mkA ($objectData['dname'], 'object', $objectData['id']) . '</div>';
84feb87b
AD
730 if (in_array ($objectData['objtype_id'], array (1502,1503))) // server chassis, network chassis
731 {
732 $objAttr = getAttrValues ($objectData['id']);
733 if (isset ($objAttr[2])) // HW type
734 {
735 extractLayout ($objAttr[2]);
736 if (isset ($objAttr[2]['rows']))
737 {
738 $rows = $objAttr[2]['rows'];
739 $cols = $objAttr[2]['cols'];
740 $layout = $objAttr[2]['layout'];
741 echo "<table width='100%' border='1'>";
742 for ($r = 0; $r < $rows; $r++)
743 {
744 echo '<tr>';
745 for ($c = 0; $c < $cols; $c++)
746 {
747 $s = ($r * $cols) + $c + 1;
748 if (isset ($slotData[$s]))
749 {
be28528c 750 if ($slotData[$s] >= 0)
84feb87b 751 {
be28528c
M
752 for ($lr = 0; $lr < $slotRows[$s]; $lr++)
753 for ($lc = 0; $lc < $slotCols[$s]; $lc++)
754 {
755 $skip = ($lr * $cols) + $lc;
756 if ($skip > 0)
757 $slotData[$s + $skip] = -1;
758 }
759 echo '<td';
760 if ($slotRows[$s] > 1)
761 echo " rowspan=$slotRows[$s]";
762 if ($slotCols[$s] > 1)
763 echo " colspan=$slotCols[$s]";
764 echo " class='state_T";
765 if ($slotData[$s] == $hl_obj_id)
766 echo 'h';
767 echo "'>${slotTitle[$s]}";
768 if ($layout == 'V')
769 {
770 $tmp = substr ($slotInfo[$s], 0, 1);
771 foreach (str_split (substr ($slotInfo[$s], 1)) as $letter)
772 $tmp .= '<br>' . $letter;
773 $slotInfo[$s] = $tmp;
774 }
775 echo mkA ($slotInfo[$s], 'object', $slotData[$s]);
776 echo '</div></td>';
84feb87b 777 }
84feb87b
AD
778 }
779 else
780 echo "<td class='state_F'><div title=\"Free slot\">&nbsp;</div></td>";
781 }
782 echo '</tr>';
783 }
784 echo '</table>';
785 }
786 }
787 }
0a7feebb
AD
788}
789
e673ee24 790// This function renders rack as HTML table.
7e1db771 791function renderRack ($rack_id, $hl_obj_id = 0)
e673ee24 792{
61a1d996
DO
793 $rackData = spotEntity ('rack', $rack_id);
794 amplifyCell ($rackData);
e673ee24
DO
795 markAllSpans ($rackData);
796 if ($hl_obj_id > 0)
797 highlightObject ($rackData, $hl_obj_id);
e673ee24
DO
798 $prev_id = getPrevIDforRack ($rackData['row_id'], $rack_id);
799 $next_id = getNextIDforRack ($rackData['row_id'], $rack_id);
d48d8820 800 echo "<center><table border=0><tr valign=middle>";
ad3e5e7e 801 echo '<td><h2>' . mkA ($rackData['row_name'], 'row', $rackData['row_id']) . ' :</h2></td>';
e673ee24 802 if ($prev_id != NULL)
ad3e5e7e
DO
803 echo '<td>' . mkA (getImageHREF ('prev', 'previous rack'), 'rack', $prev_id) . '</td>';
804 echo '<td><h2>' . mkA ($rackData['name'], 'rack', $rackData['id']) . '</h2></td>';
e673ee24 805 if ($next_id != NULL)
ad3e5e7e 806 echo '<td>' . mkA (getImageHREF ('next', 'next rack'), 'rack', $next_id) . '</td>';
d48d8820 807 echo "</h2></td></tr></table>\n";
e673ee24 808 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
d08147d6
DO
809 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th>";
810 echo "<th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
e673ee24
DO
811 for ($i = $rackData['height']; $i > 0; $i--)
812 {
4dcd770e 813 echo "<tr><th>" . inverseRackUnit ($i, $rackData) . "</th>";
e673ee24
DO
814 for ($locidx = 0; $locidx < 3; $locidx++)
815 {
816 if (isset ($rackData[$i][$locidx]['skipped']))
817 continue;
818 $state = $rackData[$i][$locidx]['state'];
65e557dd 819 echo "<td class='atom state_${state}";
e673ee24
DO
820 if (isset ($rackData[$i][$locidx]['hl']))
821 echo $rackData[$i][$locidx]['hl'];
65e557dd 822 echo "'";
e673ee24
DO
823 if (isset ($rackData[$i][$locidx]['colspan']))
824 echo ' colspan=' . $rackData[$i][$locidx]['colspan'];
825 if (isset ($rackData[$i][$locidx]['rowspan']))
826 echo ' rowspan=' . $rackData[$i][$locidx]['rowspan'];
827 echo ">";
828 switch ($state)
829 {
830 case 'T':
84feb87b 831 printObjectDetailsForRenderRack ($rackData[$i][$locidx]['object_id'], $hl_obj_id);
e673ee24
DO
832 break;
833 case 'A':
834 echo '<div title="This rackspace does not exist">&nbsp;</div>';
835 break;
836 case 'F':
837 echo '<div title="Free rackspace">&nbsp;</div>';
838 break;
839 case 'U':
840 echo '<div title="Problematic rackspace, you CAN\'T mount here">&nbsp;</div>';
841 break;
842 default:
843 echo '<div title="No data">&nbsp;</div>';
844 break;
845 }
846 echo '</td>';
847 }
848 echo "</tr>\n";
849 }
0a7feebb
AD
850 echo "</table>\n";
851 // Get a list of all of objects Zero-U mounted to this rack
852 $zeroUObjects = getEntityRelatives('children', 'rack', $rack_id);
a20a4e3c
DO
853 if (count ($zeroUObjects) > 0)
854 {
0a7feebb
AD
855 echo "<br><table width='75%' class=rack border=0 cellspacing=0 cellpadding=1>\n";
856 echo "<tr><th>Zero-U:</th></tr>\n";
857 foreach ($zeroUObjects as $zeroUObject)
858 {
859 $state = ($zeroUObject['entity_id'] == $hl_obj_id) ? 'Th' : 'T';
860 echo "<tr><td class='atom state_${state}'>";
861 printObjectDetailsForRenderRack($zeroUObject['entity_id']);
862 echo "</td></tr>\n";
863 }
864 echo "</table>\n";
865 }
866 echo "</center>\n";
e673ee24
DO
867}
868
42504426
AD
869function renderRackSortForm ($row_id)
870{
2b8c5aad 871 includeJQueryUI (FALSE);
42504426
AD
872 addJS
873 (
874<<<END
875 $(document).ready(
876 function () {
877 $("#sortRacks").sortable({
878 update : function () {
879 serial = $('#sortRacks').sortable('serialize');
880 $.ajax({
881 url: 'index.php?module=ajax&ac=upd-rack-sort-order',
882 type: 'post',
883 data: serial,
884 });
885 }
886 });
887 }
888 );
889END
890 , TRUE
891 );
892
893 startPortlet ('Racks');
894 echo "<table border=0 cellspacing=0 cellpadding=5 align=center class=widetable>\n";
895 echo "<tr><th>Drag to change order</th></tr>\n";
896 echo "<tr><td><ul class='uflist' id='sortRacks'>\n";
897 foreach (getRacks($row_id) as $rack_id => $rackInfo)
898 echo "<li id=racks_${rack_id}>${rackInfo['name']}</li>\n";
899 echo "</ul></td></tr></table>\n";
900 finishPortlet();
901}
902
e673ee24
DO
903function renderNewRackForm ($row_id)
904{
9b8174d7
AD
905 $default_height = getConfigVar ('DEFAULT_RACK_HEIGHT');
906 if ($default_height == 0)
907 $default_height = '';
50b4ba85 908 startPortlet ('Add one');
f19c75d6 909 printOpFormIntro ('addRack', array ('got_data' => 'TRUE'));
e673ee24 910 echo '<table border=0 align=center>';
9b8174d7 911 echo "<tr><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=name tabindex=1></td>";
72d52730 912 echo "<td rowspan=4>Assign tags:<br>";
a26a6ccc 913 renderNewEntityTags ('rack');
72d52730 914 echo "</td></tr>\n";
9b8174d7 915 echo "<tr><th class=tdright>Height in units (required):</th><td class=tdleft><input type=text name=height1 tabindex=2 value='${default_height}'></td></tr>\n";
9b8174d7 916 echo "<tr><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=asset_no tabindex=4></td></tr>\n";
f19c75d6
DO
917 echo "<tr><td class=submit colspan=2>";
918 printImageHREF ('CREATE', 'Add', TRUE);
919 echo "</td></tr></table></form>";
406b54bd 920 finishPortlet();
406b54bd 921
50b4ba85 922 startPortlet ('Add many');
f19c75d6 923 printOpFormIntro ('addRack', array ('got_mdata' => 'TRUE'));
50b4ba85 924 echo '<table border=0 align=center>';
9b8174d7 925 echo "<tr><th class=tdright>Height in units (*):</th><td class=tdleft><input type=text name=height2 value='${default_height}'></td>";
72d52730 926 echo "<td rowspan=3 valign=top>Assign tags:<br>";
a26a6ccc 927 renderNewEntityTags ('rack');
72d52730 928 echo "</td></tr>\n";
9b8174d7 929 echo "<tr><th class=tdright>Rack names (required):</th><td class=tdleft><textarea name=names cols=40 rows=25></textarea></td></tr>\n";
f19c75d6
DO
930 echo "<tr><td class=submit colspan=2>";
931 printImageHREF ('CREATE', 'Add', TRUE);
e673ee24
DO
932 echo '</form></table>';
933 finishPortlet();
934}
935
3825c4db 936function renderEditObjectForm()
e673ee24 937{
8dc2a6c8 938 global $pageno, $virtual_obj_types;
3825c4db 939 $object_id = getBypassValue();
fb6e2f57 940 $object = spotEntity ('object', $object_id);
cdd3efe9 941 startPortlet ();
43fb6eaf 942 printOpFormIntro ('update');
cdd3efe9
AD
943
944 // static attributes
e10f583a
DO
945 echo '<table border=0 cellspacing=0 cellpadding=3 align=center>';
946 echo "<tr><td>&nbsp;</td><th colspan=2><h2>Attributes</h2></th></tr>";
3825c4db
DO
947 echo '<tr><td>&nbsp;</td><th class=tdright>Type:</th><td class=tdleft>';
948 printSelect (getObjectTypeChangeOptions ($object['id']), array ('name' => 'object_type_id'), $object['objtype_id']);
949 echo '</td></tr>';
22bb04da 950 // baseline info
e10f583a 951 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";
8dc2a6c8 952 if (in_array($object['objtype_id'], $virtual_obj_types))
0682218d
AD
953 {
954 echo "<input type=hidden name=object_label value=''>\n";
955 echo "<input type=hidden name=object_asset_no value=''>\n";
0682218d
AD
956 }
957 else
958 {
959 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";
960 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";
0682218d
AD
961 }
962 // parent selection
9b8174d7 963 if (objectTypeMayHaveParent ($object['objtype_id']))
0682218d
AD
964 {
965 $parents = getEntityRelatives ('parents', 'object', $object_id);
966 foreach ($parents as $link_id => $parent_details)
967 {
968 if (!isset($label))
969 $label = count($parents) > 1 ? 'Containers:' : 'Container:';
970 echo "<tr><td>&nbsp;</td>";
971 echo "<th class=tdright>${label}</th><td class=tdleft>";
ad3e5e7e 972 echo mkA ($parent_details['name'], 'object', $parent_details['entity_id']);
0682218d 973 echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
10f5133a 974 echo getOpLink (array('op'=>'unlinkEntities', 'link_id'=>$link_id), '', 'cut', 'Unlink container');
0682218d
AD
975 echo "</td></tr>\n";
976 $label = '&nbsp;';
977 }
978 echo "<tr><td>&nbsp;</td>";
979 echo "<th class=tdright>Select container:</th><td class=tdleft>";
980 echo "<span";
981 $helper_args = array ('object_id' => $object_id);
982 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
983 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
984 echo " onclick='window.open(\"" . makeHrefForHelper ('objlist', $helper_args);
985 echo "\",\"findlink\",\"${popup_args}\");'>";
986 printImageHREF ('attach', 'Select a container');
987 echo "</span></td></tr>\n";
988 }
cdd3efe9 989 // optional attributes
a2a7f6f6 990 $i = 0;
e673ee24 991 $values = getAttrValues ($object_id);
2b98d5a2 992 if (count($values) > 0)
e673ee24 993 {
2b98d5a2 994 foreach ($values as $record)
e673ee24 995 {
990fce2a
AA
996 if (! permitted (NULL, NULL, NULL, array (
997 array ('tag' => '$attr_' . $record['id']),
998 array ('tag' => '$any_op'),
999 )))
1000 continue;
2b98d5a2
AD
1001 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
1002 echo '<tr><td>';
59a83bd8 1003 if (strlen ($record['value']))
10f5133a 1004 echo getOpLink (array('op'=>'clearSticker', 'attr_id'=>$record['id']), '', 'clear', 'Clear value', 'need-confirmation');
2b98d5a2
AD
1005 else
1006 echo '&nbsp;';
1007 echo '</td>';
e10f583a 1008 echo "<th class=sticker>${record['name']}:</th><td class=tdleft>";
2b98d5a2
AD
1009 switch ($record['type'])
1010 {
1011 case 'uint':
1012 case 'float':
1013 case 'string':
1014 echo "<input type=text name=${i}_value value='${record['value']}'>";
1015 break;
1016 case 'dict':
7fa7047a 1017 $chapter = readChapter ($record['chapter_id'], 'o');
2b98d5a2 1018 $chapter[0] = '-- NOT SET --';
f3d274bf 1019 $chapter = cookOptgroups ($chapter, $object['objtype_id'], $record['key']);
cd3775e9 1020 printNiftySelect ($chapter, array ('name' => "${i}_value"), $record['key']);
2b98d5a2 1021 break;
86ff26ae 1022 case 'date':
2a943f85 1023 $date_value = $record['value'] ? datetimestrFromTimestamp ($record['value']) : '';
86ff26ae
DO
1024 echo "<input type=text name=${i}_value value='${date_value}'>";
1025 break;
2b98d5a2
AD
1026 }
1027 echo "</td></tr>\n";
1028 $i++;
e673ee24 1029 }
e673ee24 1030 }
a2a7f6f6 1031 echo '<input type=hidden name=num_attrs value=' . $i . ">\n";
e10f583a
DO
1032 echo "<tr><td>&nbsp;</td><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=object_has_problems";
1033 if ($object['has_problems'] == 'yes')
1034 echo ' checked';
1035 echo "></td></tr>\n";
dec748f6 1036 echo "<tr><td>&nbsp;</td><th class=tdright>Actions:</th><td class=tdleft>";
10f5133a 1037 echo getOpLink (array ('op'=>'deleteObject', 'page'=>'depot', 'tab'=>'addmore', 'object_id'=>$object_id), '' ,'destroy', 'Delete object', 'need-confirmation');
abd1e9ac 1038 echo "&nbsp;";
10f5133a 1039 echo getOpLink (array ('op'=>'resetObject'), '' ,'clear', 'Reset (cleanup) object', 'need-confirmation');
abd1e9ac 1040 echo "</td></tr>\n";
e10f583a 1041 echo "<tr><td colspan=3><b>Comment:</b><br><textarea name=object_comment rows=10 cols=80>${object['comment']}</textarea></td></tr>";
cdd3efe9 1042
e10f583a 1043 echo "<tr><th class=submit colspan=3>";
5bbbeaa2 1044 printImageHREF ('SAVE', 'Save changes', TRUE);
cdd3efe9 1045 echo "</form></th></tr></table>\n";
e673ee24 1046 finishPortlet();
e673ee24 1047
cdd3efe9 1048 echo '<table border=0 width=100%><tr><td>';
e673ee24 1049 startPortlet ('history');
9b8174d7 1050 renderObjectHistory ($object_id);
e673ee24 1051 finishPortlet();
cdd3efe9 1052 echo '</td></tr></table>';
e673ee24
DO
1053}
1054
e673ee24
DO
1055function renderEditRackForm ($rack_id)
1056{
0c2b7c4a 1057 global $pageno;
61a1d996
DO
1058 $rack = spotEntity ('rack', $rack_id);
1059 amplifyCell ($rack);
e673ee24 1060
9b8174d7 1061 startPortlet ('Attributes');
7056988c 1062 printOpFormIntro ('updateRack');
e673ee24 1063 echo '<table border=0 align=center>';
9b8174d7 1064 echo "<tr><td>&nbsp;</td><th class=tdright>Rack row:</th><td class=tdleft>";
e1add254
AD
1065 foreach (getAllRows () as $row_id => $rowInfo)
1066 $rows[$row_id] = $rowInfo['name'];
1067 natcasesort ($rows);
1068 printSelect ($rows, array ('name' => 'row_id'), $rack['row_id']);
e673ee24 1069 echo "</td></tr>\n";
9b8174d7
AD
1070 echo "<tr><td>&nbsp;</td><th class=tdright>Name (required):</th><td class=tdleft><input type=text name=name value='${rack['name']}'></td></tr>\n";
1071 echo "<tr><td>&nbsp;</td><th class=tdright>Height (required):</th><td class=tdleft><input type=text name=height value='${rack['height']}'></td></tr>\n";
9b8174d7
AD
1072 echo "<tr><td>&nbsp;</td><th class=tdright>Asset tag:</th><td class=tdleft><input type=text name=asset_no value='${rack['asset_no']}'></td></tr>\n";
1073 // optional attributes
1074 $values = getAttrValues ($rack_id);
1075 $num_attrs = count($values);
42504426 1076 $num_attrs = $num_attrs-2; // subtract for the 'height' and 'sort_order' attributes
9b8174d7
AD
1077 echo "<input type=hidden name=num_attrs value=${num_attrs}>\n";
1078 $i = 0;
1079 foreach ($values as $record)
1080 {
1081 // Skip the 'height' attribute as it's already displayed as a required field
42504426
AD
1082 // Also skip the 'sort_order' attribute
1083 if ($record['id'] == 27 or $record['id'] == 29)
9b8174d7
AD
1084 continue;
1085 echo "<input type=hidden name=${i}_attr_id value=${record['id']}>";
1086 echo '<tr><td>';
1087 if (strlen ($record['value']))
10f5133a 1088 echo getOpLink (array('op'=>'clearSticker', 'attr_id'=>$record['id']), '', 'clear', 'Clear value', 'need-confirmation');
9b8174d7
AD
1089 else
1090 echo '&nbsp;';
1091 echo '</td>';
1092 echo "<th class=sticker>${record['name']}:</th><td class=tdleft>";
1093 switch ($record['type'])
1094 {
1095 case 'uint':
1096 case 'float':
1097 case 'string':
1098 echo "<input type=text name=${i}_value value='${record['value']}'>";
1099 break;
1100 case 'dict':
1101 $chapter = readChapter ($record['chapter_id'], 'o');
1102 $chapter[0] = '-- NOT SET --';
1103 $chapter = cookOptgroups ($chapter, 1560, $record['key']);
1104 printNiftySelect ($chapter, array ('name' => "${i}_value"), $record['key']);
1105 break;
1106 }
1107 echo "</td></tr>\n";
1108 $i++;
1109 }
1110 echo "<tr><td>&nbsp;</td><th class=tdright>Has problems:</th><td class=tdleft><input type=checkbox name=has_problems";
1111 if ($rack['has_problems'] == 'yes')
1112 echo ' checked';
1113 echo "></td></tr>\n";
c495997f 1114 if ($rack['isDeletable'])
c8187437 1115 {
dec748f6 1116 echo "<tr><td>&nbsp;</td><th class=tdright>Actions:</th><td class=tdleft>";
10f5133a 1117 echo getOpLink (array ('op'=>'deleteRack'), '', 'destroy', 'Delete rack', 'need-confirmation');
9b8174d7 1118 echo "&nbsp;</td></tr>\n";
c8187437 1119 }
9b8174d7
AD
1120 echo "<tr><td colspan=3><b>Comment:</b><br><textarea name=comment rows=10 cols=80>${rack['comment']}</textarea></td></tr>";
1121 echo "<tr><td class=submit colspan=3>";
7056988c
DO
1122 printImageHREF ('SAVE', 'Save changes', TRUE);
1123 echo "</td></tr>\n";
e673ee24
DO
1124 echo '</form></table><br>';
1125 finishPortlet();
dec748f6 1126
e673ee24 1127 startPortlet ('History');
9b8174d7 1128 renderObjectHistory ($rack_id);
e673ee24
DO
1129 finishPortlet();
1130}
1131
254673dd
DO
1132// used by renderGridForm() and renderRackPage()
1133function renderRackInfoPortlet ($rackData)
1134{
646272be 1135 $summary = array();
67cfe546 1136 $summary['Rack row'] = mkA ($rackData['row_name'], 'row', $rackData['row_id']);
646272be
AA
1137 $summary['Name'] = $rackData['name'];
1138 $summary['Height'] = $rackData['height'];
9b8174d7 1139 if (strlen ($rackData['asset_no']))
646272be 1140 $summary['Asset tag'] = $rackData['asset_no'];
9b8174d7 1141 if ($rackData['has_problems'] == 'yes')
646272be 1142 $summary[] = array ('<tr><td colspan=2 class=msg_error>Has problems</td></tr>');
42504426
AD
1143 // Display populated attributes, but skip 'height' since it's already displayed above
1144 // and skip 'sort_order' because it's modified using AJAX
9b8174d7 1145 foreach (getAttrValues ($rackData['id']) as $record)
42504426 1146 if ($record['id'] != 27 && $record['id'] != 29 && strlen ($record['value']))
646272be
AA
1147 $summary['{sticker}' . $record['name']] = formatAttributeValue ($record);
1148 $summary['% used'] = getProgressBar (getRSUforRack ($rackData));
1149 $summary['Objects'] = count ($rackData['mountedObjects']);
1150 $summary['tags'] = '';
59a83bd8 1151 if (strlen ($rackData['comment']))
646272be
AA
1152 $summary['Comment'] = $rackData['comment'];
1153 renderEntitySummary ($rackData, 'summary', $summary);
254673dd
DO
1154}
1155
e673ee24 1156// This is a universal editor of rack design/waste.
7056988c 1157// FIXME: switch to using printOpFormIntro()
7e1db771 1158function renderGridForm ($rack_id, $filter, $header, $submit, $state1, $state2)
e673ee24 1159{
61a1d996
DO
1160 $rackData = spotEntity ('rack', $rack_id);
1161 amplifyCell ($rackData);
254673dd 1162 $filter ($rackData);
e673ee24 1163
e673ee24
DO
1164 // Render the result whatever it is.
1165 // Main layout.
1166 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1167 echo "<tr><td colspan=2 align=center><h1>${rackData['name']}</h1></td></tr>\n";
1168
1169 // Left column with information portlet.
1170 echo "<tr><td class=pcleft height='1%' width='50%'>";
254673dd 1171 renderRackInfoPortlet ($rackData);
e673ee24 1172 echo "</td>\n";
bb09cca0 1173 echo "<td class=pcright>";
e673ee24
DO
1174
1175 // Grid form.
1176 startPortlet ($header);
65e557dd 1177 addJS ('js/racktables.js');
e673ee24
DO
1178 echo "<center>\n";
1179 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
57c69e9c 1180 echo "<tr><th width='10%'>&nbsp;</th>";
bd0bfb76
AD
1181 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
1182 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
1183 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
4fbb5a00 1184 printOpFormIntro ('updateRack');
e673ee24
DO
1185 markupAtomGrid ($rackData, $state2);
1186 renderAtomGrid ($rackData);
1187 echo "</table></center>\n";
1188 echo "<br><input type=submit name=do_update value='${submit}'></form><br><br>\n";
1189 finishPortlet();
bb09cca0 1190 echo "</td></tr></table>\n";
e673ee24
DO
1191}
1192
1193function renderRackDesign ($rack_id)
1194{
bb09cca0 1195 renderGridForm ($rack_id, 'applyRackDesignMask', 'Rack design', 'Set rack design', 'A', 'F');
e673ee24
DO
1196}
1197
7e1db771 1198function renderRackProblems ($rack_id)
e673ee24 1199{
bb09cca0 1200 renderGridForm ($rack_id, 'applyRackProblemMask', 'Rack problems', 'Mark unusable atoms', 'F', 'U');
e673ee24
DO
1201}
1202
40c9fc94
AA
1203function renderObjectPortRow ($port, $is_highlighted)
1204{
1205 echo '<tr';
1206 if ($is_highlighted)
5c717ce5 1207 echo ' class=highlight';
40c9fc94
AA
1208 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
1209 echo "><td class='tdleft' NOWRAP><a name='port-${port['id']}' class='ancor interactive-portname nolink $a_class'>${port['name']}</a></td>";
1210 echo "<td class=tdleft>${port['label']}</td>";
1211 echo "<td class=tdleft>" . formatPortIIFOIF ($port) . "</td><td class=tdleft><tt>${port['l2address']}</tt></td>";
a7390942
AD
1212 $links = array ();
1213 if ($port['linked'] == 1)
40c9fc94 1214 {
a7390942
AD
1215 $links = $port['links'];
1216 echo '<td class=tdleft>'.formatLoggedSpan ($links[0]['last_log'], formatPortLink ($links[0]['remote_object_id'], $links[0]['remote_object_name'], $links[0]['remote_id'], NULL)).'</td>';
1217 echo '<td class=tdleft>'.formatLoggedSpan ($links[0]['last_log'], $links[0]['remote_name'], 'underline').'&nbsp;';
1218 $helper_args = array ('port' => $port['id']);
1219 $popup_args = 'height=700, width=700, location=no, menubar=no, resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
1220 echo "<span onclick='window.open(\"" . makeHrefForHelper ('traceroute', $helper_args);
1221 echo "\",\"findlink\",\"${popup_args}\");'>";
1222 printImageHREF ('find', 'Trace this port');
1223 echo '</span></td>';
1224 $editable = permitted ('object', 'ports', 'editPort')? 'editable' : '';
1225 echo "<td class=tdleft><span class='rsvtext $editable id-".$links[0]['link_id']." op-upd-reservation-cable'>".$links[0]['cableid'].'</span></td>';
1226 // display other links, if any
1227 if (count ($links) > 1)
1228 {
1229 // finish off the current row
1230 echo "</tr>\n";
1231
1232 // place each link on a new row
1233 for ($i=1; $i<count($links); $i++) {
1234 echo '<tr';
1235 if ($is_highlighted)
1236 echo ' class=highlight';
1237 echo "><td class=tdleft colspan=4>&nbsp;</td>";
1238 echo '<td class=tdleft>'.formatLoggedSpan ($links[$i]['last_log'], formatPortLink ($links[$i]['remote_object_id'], $links[$i]['remote_object_name'], $links[$i]['remote_id'], NULL)).'</td>';
1239 echo '<td class=tdleft>'.formatLoggedSpan ($links[$i]['last_log'], $links[$i]['remote_name'], 'underline').'</td>';
1240 $editable = permitted ('object', 'ports', 'editPort')? 'editable' : '';
1241 echo "<td class=tdleft><span class='rsvtext $editable id-".$links[$i]['link_id']." op-upd-reservation-cable'>".$links[$i]['cableid']."</span></td></tr>\n";
1242 }
1243 }
40c9fc94
AA
1244 }
1245 else
1246 echo implode ('', formatPortReservation ($port)) . '<td></td>';
a7390942
AD
1247 // if there are 1 or fewer links, we need to conclude the row (otherwise it would have been done already)
1248 if (count ($links) <= 1)
1249 echo "</tr>\n";
40c9fc94
AA
1250}
1251
9b8174d7 1252function renderObject ($object_id)
e673ee24 1253{
8dc2a6c8 1254 global $nextorder, $virtual_obj_types;
fb6e2f57 1255 $info = spotEntity ('object', $object_id);
94fe6370 1256 amplifyCell ($info);
e673ee24
DO
1257 // Main layout starts.
1258 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
1259 echo "<tr><td colspan=2 align=center><h1>${info['dname']}</h1></td></tr>\n";
1260 // left column with uknown number of portlets
1261 echo "<tr><td class=pcleft>";
646272be
AA
1262
1263 // display summary portlet
1264 $summary = array();
59a83bd8 1265 if (strlen ($info['name']))
646272be 1266 $summary['Common name'] = $info['name'];
94fe6370 1267 elseif (considerConfiguredConstraint ($info, 'NAMEWARN_LISTSRC'))
646272be
AA
1268 $summary[] = array ('<tr><td colspan=2 class=msg_error>Common name is missing.</td></tr>');
1269 $summary['Object type'] = '<a href="' . makeHref (array (
341fd895
DO
1270 'page' => 'depot',
1271 'tab' => 'default',
1272 'cfe' => '{$typeid_' . $info['objtype_id'] . '}'
646272be 1273 )) . '">' . decodeObjectType ($info['objtype_id'], 'o') . '</a>';
9b8174d7 1274 if (strlen ($info['label']))
646272be 1275 $summary['Visible label'] = $info['label'];
59a83bd8 1276 if (strlen ($info['asset_no']))
646272be 1277 $summary['Asset tag'] = $info['asset_no'];
d4e8ddeb 1278 elseif (considerConfiguredConstraint ($info, 'ASSETWARN_LISTSRC'))
646272be
AA
1279 $summary[] = array ('<tr><td colspan=2 class=msg_error>Asset tag is missing.</td></tr>');
1280 $parents = getEntityRelatives ('parents', 'object', $object_id);
1281 if (count ($parents))
0682218d 1282 {
646272be 1283 $fmt_parents = array();
0682218d 1284 foreach ($parents as $parent)
8023ee39
AA
1285 $fmt_parents[] = "<a href='".makeHref(array('page'=>$parent['page'], $parent['id_name'] => $parent['entity_id']))."'>${parent['name']}</a>";
1286 $summary[count($parents) > 1 ? 'Containers' : 'Container'] = implode ('<br>', $fmt_parents);
0682218d 1287 }
646272be
AA
1288 $children = getEntityRelatives ('children', 'object', $object_id);
1289 if (count ($children))
0682218d 1290 {
646272be 1291 $fmt_children = array();
0682218d 1292 foreach ($children as $child)
8023ee39 1293 $fmt_children[] = "<a href='".makeHref(array('page'=>$child['page'], $child['id_name']=>$child['entity_id']))."'>${child['name']}</a>";
dcde9835 1294 $summary['Contains'] = implode ('<br>', $fmt_children);
0682218d 1295 }
e673ee24 1296 if ($info['has_problems'] == 'yes')
646272be 1297 $summary[] = array ('<tr><td colspan=2 class=msg_error>Has problems</td></tr>');
8ad59489 1298 foreach (getAttrValues ($object_id) as $record)
4969aa31
DO
1299 if
1300 (
dec748f6 1301 strlen ($record['value']) and
4969aa31
DO
1302 permitted (NULL, NULL, NULL, array (array ('tag' => '$attr_' . $record['id'])))
1303 )
646272be 1304 $summary['{sticker}' . $record['name']] = formatAttributeValue ($record);
a2c597ea
AA
1305 $summary[] = array (getOutputOf ('printTagTRs',
1306 $info,
1307 makeHref
1308 (
1309 array
1310 (
1311 'page'=>'depot',
1312 'tab'=>'default',
1313 'andor' => 'and',
1314 'cfe' => '{$typeid_' . $info['objtype_id'] . '}',
1315 )
1316 )."&"
1317 ));
a7390942 1318 renderEntitySummary ($info, 'Summary', $summary);
e673ee24 1319
59a83bd8 1320 if (strlen ($info['comment']))
e673ee24
DO
1321 {
1322 startPortlet ('Comment');
6cc5d6cd 1323 echo '<div class=commentblock>' . string_insert_hrefs ($info['comment']) . '</div>';
e673ee24
DO
1324 finishPortlet ();
1325 }
1326
b5700329
AA
1327 $logrecords = getLogRecordsForObject ($_REQUEST['object_id']);
1328 if (count ($logrecords))
9a90adc4
DO
1329 {
1330 startPortlet ('log records');
1331 echo "<table cellspacing=0 cellpadding=5 align=center class=widetable width='100%'>";
1332 $order = 'odd';
b5700329 1333 foreach ($logrecords as $row)
9a90adc4
DO
1334 {
1335 echo "<tr class=row_${order} valign=top>";
1336 echo '<td class=tdleft>' . $row['date'] . '<br>' . $row['user'] . '</td>';
0b8d8309 1337 echo '<td class="logentry">' . string_insert_hrefs (htmlspecialchars ($row['content'], ENT_NOQUOTES)) . '</td>';
9a90adc4
DO
1338 echo '</tr>';
1339 $order = $nextorder[$order];
1340 }
1341 echo '</table>';
1342 finishPortlet();
1343 }
1344
65e557dd 1345 switchportInfoJS ($object_id); // load JS code to make portnames interactive
e1ae3fb4
AD
1346 renderFilesPortlet ('object', $object_id);
1347
9f75e165 1348 if (count ($info['ports']))
e673ee24 1349 {
a7390942 1350 startPortlet ('Ports and links');
9f75e165
DO
1351 $hl_port_id = 0;
1352 if (isset ($_REQUEST['hl_port_id']))
e673ee24 1353 {
0cc24e9a 1354 assertUIntArg ('hl_port_id');
9f75e165 1355 $hl_port_id = $_REQUEST['hl_port_id'];
65e557dd 1356 addAutoScrollScript ("port-$hl_port_id");
9f75e165 1357 }
764aa01a
AD
1358 $helper_args = array ('object_id' => $object_id);
1359 $popup_args = 'height=700, width=700, location=no, menubar=no, resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
1360 echo "<a href='javascript:;' ";
1361 echo "onclick='window.open(\"" . makeHrefForHelper ('traceroute', $helper_args);
1362 echo "\",\"findlink\",\"${popup_args}\");'>";
1363 printImageHREF ('find', 'Trace all port links');
1364 echo 'Trace all ports</a>';
a7390942 1365 echo "<table border=0 cellspacing=0 cellpadding='5' align='center' class='widetable'>";
9f75e165 1366 echo '<tr><th class=tdleft>Local name</th><th class=tdleft>Visible label</th>';
0d59a51c 1367 echo '<th class=tdleft>Interface</th><th class=tdleft>L2 address</th>';
0c7c9f8b 1368 echo '<th class=tdcenter colspan=2>Remote object and port</th>';
a7390942 1369 echo "<th class=tdleft>Cable ID</th></tr>\n";
9f75e165 1370 foreach ($info['ports'] as $port)
40c9fc94 1371 callHook ('renderObjectPortRow', $port, ($hl_port_id == $port['id']));
fd5edda8 1372 if (permitted (NULL, 'ports', 'set_reserve_comment'))
a8dc2982 1373 addJS ('js/inplace-edit.js');
9f75e165 1374 echo "</table><br>";
e673ee24
DO
1375 finishPortlet();
1376 }
85970da2 1377
21ee3351 1378 if (count ($info['ipv4']) + count ($info['ipv6']))
e673ee24 1379 {
21ee3351 1380 startPortlet ('IP addresses');
e673ee24 1381 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
f0ed1181 1382 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
0b9c98d7 1383 echo "<tr><th>OS interface</th><th>IP address</th><th>network</th><th>routed by</th><th>peers</th></tr>\n";
83fdf85f
DO
1384 else
1385 echo "<tr><th>OS interface</th><th>IP address</th><th>peers</th></tr>\n";
21ee3351
AA
1386
1387 // group IP allocations by interface name instead of address family
1388 $allocs_by_iface = array();
1389 foreach (array ('ipv4', 'ipv6') as $ip_v)
4318ced5
AA
1390 foreach ($info[$ip_v] as $ip_bin => $alloc)
1391 $allocs_by_iface[$alloc['osif']][$ip_bin] = $alloc;
dec748f6 1392
21ee3351
AA
1393 // sort allocs array by portnames
1394 foreach (sortPortList ($allocs_by_iface) as $iface_name => $alloclist)
1395 {
1396 $is_first_row = TRUE;
f3505b35 1397 foreach ($alloclist as $alloc)
b90c3907 1398 {
40c9fc94 1399 $rendered_alloc = callHook ('getRenderedAlloc', $object_id, $alloc);
f3505b35 1400 echo "<tr class='${rendered_alloc['tr_class']}' valign=top>";
21ee3351 1401
f3505b35 1402 // display iface name, same values are grouped into single cell
21ee3351
AA
1403 if ($is_first_row)
1404 {
1405 $rowspan = count ($alloclist) > 1 ? 'rowspan="' . count ($alloclist) . '"' : '';
40c9fc94 1406 echo "<td class=tdleft $rowspan>" . $iface_name . $rendered_alloc['td_name_suffix'] . "</td>";
21ee3351
AA
1407 $is_first_row = FALSE;
1408 }
f3505b35 1409 echo $rendered_alloc['td_ip'];
21ee3351 1410 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
83fdf85f 1411 {
f3505b35
AA
1412 echo $rendered_alloc['td_network'];
1413 echo $rendered_alloc['td_routed_by'];
21ee3351 1414 }
f3505b35
AA
1415 echo $rendered_alloc['td_peers'];
1416
1417 echo "</tr>\n";
b90c3907 1418 }
e673ee24
DO
1419 }
1420 echo "</table><br>\n";
1421 finishPortlet();
1422 }
1423
94fe6370 1424 $forwards = $info['nat4'];
e673ee24
DO
1425 if (count($forwards['in']) or count($forwards['out']))
1426 {
f28fbe8b 1427 startPortlet('NATv4');
e673ee24
DO
1428
1429 if (count($forwards['out']))
1430 {
1431
f28fbe8b 1432 echo "<h3>locally performed NAT</h3>";
e673ee24 1433
105a3bc8 1434 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 1435 echo "<tr><th>Proto</th><th>Match endpoint</th><th>Translate to</th><th>Target object</th><th>Rule comment</th></tr>\n";
e673ee24
DO
1436
1437 foreach ($forwards['out'] as $pf)
1438 {
2c817354
DO
1439 $class = 'trerror';
1440 $osif = '';
1441 if (isset ($alloclist [$pf['localip']]))
1442 {
1443 $class = $alloclist [$pf['localip']]['addrinfo']['class'];
1444 $osif = $alloclist [$pf['localip']]['osif'] . ': ';
1445 }
e673ee24 1446 echo "<tr class='$class'>";
7419401e
AA
1447 echo "<td>${pf['proto']}</td><td class=tdleft>${osif}" . getRenderedIPPortPair ($pf['localip'], $pf['localport']) . "</td>";
1448 echo "<td class=tdleft>" . getRenderedIPPortPair ($pf['remoteip'], $pf['remoteport']) . "</td>";
4318ced5 1449 $address = getIPAddress (ip4_parse ($pf['remoteip']));
e673ee24 1450 echo "<td class='description'>";
53ef3908
DO
1451 if (count ($address['allocs']))
1452 foreach($address['allocs'] as $bond)
ad3e5e7e 1453 echo mkA ("${bond['object_name']}(${bond['name']})", 'object', $bond['object_id']) . ' ';
59a83bd8 1454 elseif (strlen ($pf['remote_addr_name']))
f28fbe8b 1455 echo '(' . $pf['remote_addr_name'] . ')';
53ef3908 1456 echo "</td><td class='description'>${pf['description']}</td></tr>";
e673ee24
DO
1457 }
1458 echo "</table><br><br>";
1459 }
1460 if (count($forwards['in']))
1461 {
f28fbe8b 1462 echo "<h3>arriving NAT connections</h3>";
105a3bc8 1463 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center'>\n";
f28fbe8b 1464 echo "<tr><th>Matched endpoint</th><th>Source object</th><th>Translated to</th><th>Rule comment</th></tr>\n";
e673ee24
DO
1465 foreach ($forwards['in'] as $pf)
1466 {
1467 echo "<tr>";
7419401e 1468 echo "<td>${pf['proto']}/" . getRenderedIPPortPair ($pf['localip'], $pf['localport']) . "</td>";
ad3e5e7e 1469 echo '<td class="description">' . mkA ($pf['object_name'], 'object', $pf['object_id']);
7419401e 1470 echo "</td><td>" . getRenderedIPPortPair ($pf['remoteip'], $pf['remoteport']) . "</td>";
e673ee24
DO
1471 echo "<td class='description'>${pf['description']}</td></tr>";
1472 }
e673ee24
DO
1473 echo "</table><br><br>";
1474 }
1475 finishPortlet();
1476 }
1477
eacc0983 1478 renderSLBTriplets2 ($info);
defd92d8 1479 renderSLBTriplets ($info);
e673ee24
DO
1480 echo "</td>\n";
1481
7056988c 1482 // After left column we have (surprise!) right column with rackspace portlet only.
e673ee24 1483 echo "<td class=pcright>";
8dc2a6c8 1484 if (!in_array($info['objtype_id'], $virtual_obj_types))
0682218d
AD
1485 {
1486 // rackspace portlet
1487 startPortlet ('rackspace allocation');
1488 foreach (getResidentRacksData ($object_id, FALSE) as $rack_id)
1489 renderRack ($rack_id, $object_id);
1490 echo '<br>';
1491 finishPortlet();
1492 }
e673ee24
DO
1493 echo "</td></tr>";
1494 echo "</table>\n";
1495}
1496
1497function renderRackMultiSelect ($sname, $racks, $selected)
1498{
04571888
DO
1499 // Transform the given flat list into a list of groups, each representing a rack row.
1500 $rdata = array();
adf8f3b1 1501 $locations = listCells ('location');
e673ee24 1502 foreach ($racks as $rack)
d016010a 1503 {
adf8f3b1
AD
1504 // Include all parents in the location name
1505 $location_name = '';
1506 $location_id = $rack['location_id'];
1507 while(isset ($location_id))
1508 {
1509 $location_name = $locations[$location_id]['name'] . ' / ' . $location_name;
1510 $location_id = $locations[$location_id]['parent_id'];
1511 }
1512 $row_name = $location_name . $rack['row_name'];
d016010a
AD
1513 $rdata[$row_name][$rack['id']] = $rack['name'];
1514 }
4fbb5a00 1515 echo "<select name=${sname} multiple size=" . getConfigVar ('MAXSELSIZE') . " onchange='getElementsByName(\"updateObjectAllocation\")[0].submit()'>\n";
04571888 1516 foreach ($rdata as $optgroup => $racklist)
e673ee24 1517 {
04571888
DO
1518 echo "<optgroup label='${optgroup}'>";
1519 foreach ($racklist as $rack_id => $rack_name)
1520 {
1521 echo "<option value=${rack_id}";
1522 if (!(array_search ($rack_id, $selected) === FALSE))
1523 echo ' selected';
1524 echo">${rack_name}</option>\n";
1525 }
e673ee24
DO
1526 }
1527 echo "</select>\n";
1528}
1529
e673ee24 1530// This function renders a form for port edition.
7e1db771 1531function renderPortsForObject ($object_id)
e673ee24 1532{
3153a326
DO
1533 $prefs = getPortListPrefs();
1534 function printNewItemTR ($prefs)
39b4abd0
DO
1535 {
1536 printOpFormIntro ('addPort');
1537 echo "<tr><td>";
f5ff50f5 1538 printImageHREF ('add', 'add a port', TRUE);
65e557dd 1539 echo "</td><td class='tdleft'><input type=text size=8 name=port_name tabindex=100></td>\n";
a7390942 1540 echo "<td><input type=text name=port_label tabindex=101></td><td class=tdleft>";
cd3775e9
DO
1541 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 102), $prefs['selected']);
1542 echo "<td><input type=text name=port_l2address tabindex=103 size=18 maxlength=24></td>\n";
318c48a8 1543 echo "<td colspan=4>&nbsp;</td><td>";
9318d2ef
DO
1544 printImageHREF ('add', 'add a port', TRUE, 104);
1545 echo "</td></tr></form>";
39b4abd0 1546 }
a1fc539a 1547 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes' || getConfigVar('ENABLE_BULKPORT_FORM') == 'yes' )
f44fdef9
DO
1548 startPortlet ('Ports and interfaces');
1549 else
1550 echo '<br>';
9f75e165
DO
1551 $object = spotEntity ('object', $object_id);
1552 amplifyCell ($object);
a1fc539a
RF
1553 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1554 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1555 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>";
1556 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
1557 printOpFormIntro ('addBulkPorts');
1558 echo "<tr><td>";
1559 printImageHREF ('add', 'add ports', TRUE);
1560 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1561 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1562 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1563 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1564 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
a7390942 1565 echo "<td>";
a1fc539a
RF
1566 printImageHREF ('add', 'add ports', TRUE, 110);
1567 echo "</td></tr></form>";
1568 echo "</table><br>\n";
1569 }
dec748f6 1570
a7390942
AD
1571 // clear ports link
1572 echo "<a href='".
1573 makeHrefProcess(array ('op'=>'deleteAll')).
1574 "' onclick=\"javascript:return confirm('Are you sure you want to delete all existing ports?')\">" . getImageHREF ('clear', 'Clear port list') . " Clear port list</a>";
1575
1576 // link patch panels link
1577 if ($object['objtype_id'] == 9)
1578 {
1579 $helper_args = array ('object_id' => $object_id);
1580 $popup_args = 'height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
1581 echo "&nbsp;&nbsp;&nbsp;&nbsp;<a href='javascript:;' ";
1582 echo "onclick='window.open(\"" . makeHrefForHelper ('patchpanellist', $helper_args);
1583 echo "\",\"findlink\",\"${popup_args}\");'>";
1584 printImageHREF ('plug', 'Link to another patch panel');
1585 echo 'Link to another patch panel</a>';
1586 }
1587
1588 $helper_args = array ('object_id' => $object_id);
1589 $popup_args = 'height=700, width=700, location=no, menubar=no, resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
1590 echo "&nbsp;&nbsp;&nbsp;&nbsp;<a href='javascript:;' ";
1591 echo "onclick='window.open(\"" . makeHrefForHelper ('traceroute', $helper_args);
1592 echo "\",\"findlink\",\"${popup_args}\");'>";
1593 printImageHREF ('find', 'Trace all port links');
1594 echo 'Trace all ports</a>';
1595
1596 echo "<table border=0 cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
0d59a51c 1597 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>";
a7390942 1598 echo "<th class=tdleft colspan=2>Remote object and port</th><th class=tdleft>Cable ID</th><th class=tdleft>(Un)link or (un)reserve</th><th>&nbsp;</th></tr>\n";
39b4abd0 1599 if (getConfigVar ('ADDNEW_AT_TOP') == 'yes')
3153a326 1600 printNewItemTR ($prefs);
45ff9012 1601
00276508
AA
1602 if (isset ($_REQUEST['hl_port_id']))
1603 {
1604 assertUIntArg ('hl_port_id');
1605 $hl_port_id = intval ($_REQUEST['hl_port_id']);
65e557dd 1606 addAutoScrollScript ("port-$hl_port_id");
00276508 1607 }
65e557dd 1608 switchportInfoJS ($object_id); // load JS code to make portnames interactive
9f75e165 1609 foreach ($object['ports'] as $port)
e673ee24 1610 {
a7390942 1611 $links = array ();
5c717ce5 1612 $tr_class = isset ($hl_port_id) && $hl_port_id == $port['id'] ? 'class="highlight"' : '';
7056988c 1613 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
d0d40671 1614 echo "<tr $tr_class><td><a name='port-${port['id']}' href='".makeHrefProcess(array('op'=>'delPort', 'port_id'=>$port['id']))."'>";
e673ee24
DO
1615 printImageHREF ('delete', 'Unlink and Delete this port');
1616 echo "</a></td>\n";
65e557dd
AA
1617 $a_class = isEthernetPort ($port) ? 'port-menu' : '';
1618 echo "<td class='tdleft' NOWRAP><input type=text name=name class='interactive-portname $a_class' value='${port['name']}' size=8></td>";
cd3775e9 1619 echo "<td><input type=text name=label value='${port['label']}'></td>";
a7390942 1620 if ($port['linked'] == 0)
611170af 1621 {
3153a326
DO
1622 echo '<td>';
1623 if ($port['iif_id'] != 1)
1624 echo '<label>' . $port['iif_name'] . ' ';
cd3775e9 1625 printSelect (getExistingPortTypeOptions ($port['id']), array ('name' => 'port_type_id'), $port['oif_id']);
3153a326
DO
1626 if ($port['iif_id'] != 1)
1627 echo '</label>';
1628 echo '</td>';
611170af
AD
1629 }
1630 else
1631 {
045bab87 1632 echo "<input type=hidden name=port_type_id value='${port['oif_id']}'><td class=tdleft>";
e9d357e1 1633 echo formatPortIIFOIF ($port) . '</td>';
611170af 1634 }
cd3775e9
DO
1635 // 18 is enough to fit 6-byte MAC address in its longest form,
1636 // while 24 should be Ok for WWN
1637 echo "<td><input type=text name=l2address value='${port['l2address']}' size=18 maxlength=24></td>\n";
a7390942 1638 if ($port['linked'] == 1)
e673ee24 1639 {
a7390942
AD
1640 $links = $port['links'];
1641 echo "<input type=hidden name=reservation_comment value=''>";
1642 echo "<input type=hidden name=link_id value='".$links[0]['link_id']."'>";
1643 echo '<td class=tdleft>'.formatLoggedSpan ($port['last_log'], formatPortLink ($links[0]['remote_object_id'], $links[0]['remote_object_name'], $links[0]['remote_id'], NULL)).'</td>';
1644 echo '<td class=tdleft>'.formatLoggedSpan ($port['last_log'], $links[0]['remote_name'], 'underline').'&nbsp;';
1645 $helper_args = array ('port' => $port['id']);
1646 $popup_args = 'height=700, width=700, location=no, menubar=no, resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
1647 echo "<span onclick='window.open(\"" . makeHrefForHelper ('traceroute', $helper_args);
1648 echo "\",\"findlink\",\"${popup_args}\");'>";
1649 printImageHREF ('find', 'Trace this port');
1650 echo '</span></td>';
1651
1652 echo "<td><input type=text name=cable value='".$links[0]['cableid']."'></td>";
1653 echo '<td class=tdcenter><span';
1654 $helper_args = array ('port' => $port['id'], 'in_rack' => 'on');
1655 $popup_args = 'height=700, width=400, location=no, menubar=no, resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
1656 echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
1657 echo "\",\"findlink\",\"${popup_args}\");'>";
1658 printImageHREF ('plug', 'Link this port');
1659 echo "</span>&nbsp;<a href='".
1660 makeHrefProcess(array(
1661 'op'=>'unlinkPort',
1662 'link_id'=>$links[0]['link_id'],
1663 'object_id'=>$object_id)).
1664 "'>";
1665 printImageHREF ('cut', 'Unlink this port');
1666 echo '</a></td>';
1667 // display other links, if any
1668 if (count($links) > 1)
1669 {
1670 // finish off the current row
1671 echo '<td>';
1672 printImageHREF ('save', 'Save changes', TRUE);
1673 echo "</td></form></tr>\n";
1674
1675 // place each link on a new row
1676 for ($i=1; $i<count($links); $i++)
1677 {
1678 printOpFormIntro ('editPort', array ('port_id' => $port['id']));
1679 echo "<input type=hidden name=name value='".$links[$i]['remote_name']."'>";
1680 echo "<input type=hidden name=link_id value='".$links[$i]['link_id']."'>";
1681 echo "<tr $tr_class><td colspan=5>&nbsp;</td><td class=tdleft>";
1682 echo formatLoggedSpan ($links[$i]['last_log'], formatPortLink ($links[$i]['remote_object_id'], $links[$i]['remote_object_name'], $links[$i]['remote_id'], NULL));
1683 echo '</td><td class=tdleft>'.formatLoggedSpan ($links[$i]['last_log'], $links[$i]['remote_name'], 'underline').'</td>';
1684 echo "<td><input type=text name=cable value='".$links[$i]['cableid']."'></td><td class=tdcenter><a href='".
1685 makeHrefProcess(array(
1686 'op'=>'unlinkPort',
1687 'link_id'=>$links[$i]['link_id'],
1688 'object_id'=>$object_id)).
1689 "'>";
1690 printImageHREF ('cut', 'Unlink this port');
1691 echo '</a></td><td>';
1692 printImageHREF ('save', 'Save changes', TRUE);
1693 echo "</td></form></tr>\n";
1694 }
1695 }
e673ee24 1696 }
59a83bd8 1697 elseif (strlen ($port['reservation_comment']))
e673ee24 1698 {
a7390942 1699 echo "<td class=tdleft>" . formatLoggedSpan ($port['last_log'], 'Reserved:', 'strong underline') . "</td>";
e673ee24 1700 echo "<td><input type=text name=reservation_comment value='${port['reservation_comment']}'></td>";
318c48a8 1701 echo "<td></td>";
10f5133a
AA
1702 echo "<td class=tdcenter>";
1703 echo getOpLink (array('op'=>'useup', 'port_id'=>$port['id']), '', 'clear', 'Use up this port');
1704 echo "</td>";
e673ee24
DO
1705 }
1706 else
1707 {
6b1ca530 1708 $in_rack = getConfigVar ('NEAREST_RACKS_CHECKBOX');
318c48a8 1709 echo "<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td class=tdcenter><span";
cd3775e9
DO
1710 $helper_args = array
1711 (
1712 'port' => $port['id'],
6b1ca530 1713 'in_rack' => ($in_rack == "yes" ? "on" : "")
cd3775e9
DO
1714 );
1715 $popup_args = 'height=700, width=400, location=no, menubar=no, '.
9e214652 1716 'resizable=yes, scrollbars=yes, status=no, titlebar=no, toolbar=no';
cd3775e9 1717 echo " onclick='window.open(\"" . makeHrefForHelper ('portlist', $helper_args);
a7390942 1718 echo "\",\"findlink\",\"${popup_args}\");'>";
5ccd99a0 1719 printImageHREF ('plug', 'Link this port');
a7390942
AD
1720 echo "</span>&nbsp;<input type=text name=reservation_comment></td>\n";
1721 }
1722 // if there are 1 or fewer links, we need to conclude the row (otherwise it would have been done already)
1723 if (count($links) <= 1)
1724 {
1725 echo '<td>';
1726 printImageHREF ('save', 'Save changes', TRUE);
1727 echo "</td></form></tr>\n";
e673ee24 1728 }
e673ee24 1729 }
39b4abd0 1730 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes')
3153a326 1731 printNewItemTR ($prefs);
e673ee24 1732 echo "</table><br>\n";
a1fc539a
RF
1733 if (getConfigVar ('ADDNEW_AT_TOP') != 'yes' && getConfigVar('ENABLE_BULKPORT_FORM') == 'yes'){
1734 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>\n";
1735 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>";
1736 echo "<th class=tdleft>Count</th><th>&nbsp;</th></tr>\n";
dec748f6 1737 printOpFormIntro ('addBulkPorts');
a1fc539a
RF
1738 echo "<tr><td>";
1739 printImageHREF ('add', 'add ports', TRUE);
1740 echo "</td><td><input type=text size=8 name=port_name tabindex=105></td>\n";
1741 echo "<td><input type=text name=port_label tabindex=106></td><td>";
1742 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type_id', 'tabindex' => 107), $prefs['selected']);
1743 echo "<td><input type=text name=port_numbering_start tabindex=108 size=3 maxlength=3></td>\n";
1744 echo "<td><input type=text name=port_numbering_count tabindex=109 size=3 maxlength=3></td>\n";
1745 echo "<td>&nbsp;</td><td>";
1746 printImageHREF ('add', 'add ports', TRUE, 110);
1747 echo "</td></tr></form>";
1748 echo "</table><br>\n";
1749 }
f44fdef9
DO
1750 if (getConfigVar('ENABLE_MULTIPORT_FORM') == 'yes')
1751 finishPortlet();
1752 if (getConfigVar('ENABLE_MULTIPORT_FORM') != 'yes')
1753 return;
e673ee24
DO
1754
1755 startPortlet ('Add/update multiple ports');
7056988c 1756 printOpFormIntro ('addMultiPorts');
f7a3c94a 1757 echo 'Format: <select name=format tabindex=201>';
e673ee24
DO
1758 echo '<option value=c3600asy>Cisco 3600 async: sh line | inc TTY</option>';
1759 echo '<option value=fiwg selected>Foundry ServerIron/FastIron WorkGroup/Edge: sh int br</option>';
e673ee24 1760 echo '<option value=fisxii>Foundry FastIron SuperX/II4000: sh int br</option>';
351d4dbf 1761 echo '<option value=ssv1>SSV:&lt;interface name&gt; &lt;MAC address&gt;</option>';
e673ee24
DO
1762 echo "</select>";
1763 echo 'Default port type: ';
cd3775e9 1764 printNiftySelect (getNewPortTypeOptions(), array ('name' => 'port_type', 'tabindex' => 202), $prefs['selected']);
f7a3c94a
DO
1765 echo "<input type=submit value='Parse output' tabindex=204><br>\n";
1766 echo "<textarea name=input cols=100 rows=50 tabindex=203></textarea><br>\n";
e673ee24
DO
1767 echo '</form>';
1768 finishPortlet();
1769}
1770
4318ced5 1771function renderIPForObject ($object_id)
e673ee24 1772{
4318ced5 1773 function printNewItemTR ($default_type)
21ee3351
AA
1774 {
1775 global $aat;
4318ced5
AA
1776 printOpFormIntro ('add');
1777 echo "<tr><td>"; // left btn
dec748f6 1778 printImageHREF ('add', 'allocate', TRUE);
21ee3351 1779 echo "</td>";
4318ced5
AA
1780 echo "<td class=tdleft><input type='text' size='10' name='bond_name' tabindex=100></td>\n"; // if-name
1781 echo "<td class=tdleft><input type=text name='ip' tabindex=101></td>\n"; // IP
1782 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1783 echo "<td colspan=2>&nbsp;</td>"; // network, routed by
1784 echo '<td>';
1785 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102), $default_type); // type
1786 echo "</td><td>&nbsp;</td><td>"; // misc
1787 printImageHREF ('add', 'allocate', TRUE, 103); // right btn
21ee3351
AA
1788 echo "</td></tr></form>";
1789 }
21ee3351
AA
1790 global $aat;
1791 startPortlet ('Allocations');
4318ced5
AA
1792 echo "<table cellspacing=0 cellpadding='5' align='center' class='widetable'><tr>\n";
1793 echo '<th>&nbsp;</th>';
1794 echo '<th>OS interface</th>';
1795 echo '<th>IP address</th>';
21ee3351 1796 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
4318ced5
AA
1797 {
1798 echo '<th>network</th>';
1799 echo '<th>routed by</th>';
1800 }
1801 echo '<th>type</th>';
1802 echo '<th>misc</th>';
1803 echo '<th>&nbsp</th>';
1804 echo '</tr>';
21ee3351 1805
710ead7e
AA
1806 $alloc_list = ''; // most of the output is stored here
1807 $used_alloc_types = array();
4318ced5 1808 foreach (getObjectIPAllocations ($object_id) as $alloc)
21ee3351 1809 {
710ead7e
AA
1810 if (! isset ($used_alloc_types[$alloc['type']]))
1811 $used_alloc_types[$alloc['type']] = 0;
1812 $used_alloc_types[$alloc['type']]++;
1813
40c9fc94 1814 $rendered_alloc = callHook ('getRenderedAlloc', $object_id, $alloc);
4318ced5 1815 $alloc_list .= getOutputOf ('printOpFormIntro', 'upd', array ('ip' => $alloc['addrinfo']['ip']));
710ead7e 1816 $alloc_list .= "<tr class='${rendered_alloc['tr_class']}' valign=top>";
f3505b35 1817
10f5133a 1818 $alloc_list .= "<td>" . getOpLink (array ('op' => 'del', 'ip' => $alloc['addrinfo']['ip']), '', 'delete', 'Delete this IP address') . "</td>";
40c9fc94 1819 $alloc_list .= "<td class=tdleft><input type='text' name='bond_name' value='${alloc['osif']}' size=10>" . $rendered_alloc['td_name_suffix'] . "</td>";
710ead7e 1820 $alloc_list .= $rendered_alloc['td_ip'];
21ee3351
AA
1821 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes')
1822 {
710ead7e
AA
1823 $alloc_list .= $rendered_alloc['td_network'];
1824 $alloc_list .= $rendered_alloc['td_routed_by'];
21ee3351 1825 }
710ead7e
AA
1826 $alloc_list .= '<td>' . getSelect ($aat, array ('name' => 'bond_type'), $alloc['type']) . "</td>";
1827 $alloc_list .= $rendered_alloc['td_peers'];
1828 $alloc_list .= "<td>" .getImageHREF ('save', 'Save changes', TRUE) . "</td>";
f3505b35 1829
710ead7e 1830 $alloc_list .= "</form></tr>\n";
21ee3351 1831 }
710ead7e 1832 asort ($used_alloc_types, SORT_NUMERIC);
a0a5ce54 1833 $most_popular_type = empty ($used_alloc_types) ? 'regular' : array_last (array_keys ($used_alloc_types));
710ead7e
AA
1834
1835 if ($list_on_top = (getConfigVar ('ADDNEW_AT_TOP') != 'yes'))
1836 echo $alloc_list;
4318ced5 1837 printNewItemTR ($most_popular_type);
710ead7e
AA
1838 if (! $list_on_top)
1839 echo $alloc_list;
21ee3351
AA
1840
1841 echo "</table><br>\n";
1842 finishPortlet();
f3505b35
AA
1843}
1844
08408472
AA
1845// This function is deprecated. Do not rely on its internals,
1846// it will probably be removed in the next major relese.
1847// Use new showError, showWarning, showSuccess functions.
dec748f6 1848// Log array is stored in global $log_messages. Its format is simple: plain ordered array
8ab645cf 1849// with values having keys 'c' (both message code and severity) and 'a' (sprintf arguments array)
1cb6adf5 1850function showMessageOrError ()
e673ee24 1851{
a2b16202
AA
1852 global $log_messages;
1853
1854 @session_start();
1855 if (isset ($_SESSION['log']))
1856 {
1857 $log_messages = array_merge ($_SESSION['log'], $log_messages);
1858 unset ($_SESSION['log']);
1859 }
1860 session_commit();
1861
1862 if (empty ($log_messages))
1cb6adf5 1863 return;
8ab645cf
AA
1864 $msginfo = array
1865 (
dec748f6 1866// records 0~99 with success messages
8ab645cf
AA
1867 0 => array ('code' => 'success', 'format' => '%s'),
1868 5 => array ('code' => 'success', 'format' => 'added record "%s" successfully'),
1869 6 => array ('code' => 'success', 'format' => 'updated record "%s" successfully'),
1870 7 => array ('code' => 'success', 'format' => 'deleted record "%s" successfully'),
1871 8 => array ('code' => 'success', 'format' => 'Port %s successfully linked with %s'),
1872 10 => array ('code' => 'success', 'format' => 'Added %u ports, updated %u ports, encountered %u errors.'),
1873 21 => array ('code' => 'success', 'format' => 'Generation complete'),
1874 26 => array ('code' => 'success', 'format' => 'updated %u records successfully'),
1875 37 => array ('code' => 'success', 'format' => 'added %u records successfully'),
1876 38 => array ('code' => 'success', 'format' => 'removed %u records successfully'),
8ab645cf
AA
1877 43 => array ('code' => 'success', 'format' => 'Saved successfully.'),
1878 44 => array ('code' => 'success', 'format' => '%s failures and %s successfull changes.'),
1879 48 => array ('code' => 'success', 'format' => 'added a record successfully'),
1880 49 => array ('code' => 'success', 'format' => 'deleted a record successfully'),
1881 51 => array ('code' => 'success', 'format' => 'updated a record successfully'),
1882 57 => array ('code' => 'success', 'format' => 'Reset complete'),
8ab645cf 1883 63 => array ('code' => 'success', 'format' => '%u change request(s) have been processed'),
8ab645cf
AA
1884 67 => array ('code' => 'success', 'format' => "Tag rolling done, %u objects involved"),
1885 71 => array ('code' => 'success', 'format' => 'File "%s" was linked successfully'),
1886 72 => array ('code' => 'success', 'format' => 'File was unlinked successfully'),
8ab645cf
AA
1887 82 => array ('code' => 'success', 'format' => "Bulk port creation was successful. %u ports created, %u failed"),
1888 87 => array ('code' => 'success', 'format' => '802.1Q recalculate: %d ports changed on %d switches'),
8628ae44 1889// records 100~199 with fatal error messages
8ab645cf
AA
1890 100 => array ('code' => 'error', 'format' => '%s'),
1891 109 => array ('code' => 'error', 'format' => 'failed updating a record'),
8ab645cf
AA
1892 131 => array ('code' => 'error', 'format' => 'invalid format requested'),
1893 141 => array ('code' => 'error', 'format' => 'Encountered %u errors, updated %u record(s)'),
1894 149 => array ('code' => 'error', 'format' => 'Turing test failed'),
1895 150 => array ('code' => 'error', 'format' => 'Can only change password under DB authentication.'),
1896 151 => array ('code' => 'error', 'format' => 'Old password doesn\'t match.'),
1897 152 => array ('code' => 'error', 'format' => 'New passwords don\'t match.'),
1898 154 => array ('code' => 'error', 'format' => "Verification error: %s"),
1899 155 => array ('code' => 'error', 'format' => 'Save failed.'),
1900 159 => array ('code' => 'error', 'format' => 'Permission denied moving port %s from VLAN%u to VLAN%u'),
1901 161 => array ('code' => 'error', 'format' => 'Endpoint not found. Please either set FQDN attribute or assign an IP address to the object.'),
1902 162 => array ('code' => 'error', 'format' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'),
8ab645cf
AA
1903 170 => array ('code' => 'error', 'format' => 'There is no network for IP address "%s"'),
1904 172 => array ('code' => 'error', 'format' => 'Malformed request'),
1905 179 => array ('code' => 'error', 'format' => 'Expired form has been declined.'),
1906 188 => array ('code' => 'error', 'format' => "Fatal SNMP failure"),
1907 189 => array ('code' => 'error', 'format' => "Unknown OID '%s'"),
1908 191 => array ('code' => 'error', 'format' => "deploy was blocked due to conflicting configuration versions"),
f0ff4930 1909
8628ae44 1910// records 200~299 with warnings
8ab645cf
AA
1911 200 => array ('code' => 'warning', 'format' => '%s'),
1912 201 => array ('code' => 'warning', 'format' => 'nothing happened...'),
e1add254 1913 206 => array ('code' => 'warning', 'format' => '%s is not empty'),
7587edca 1914 207 => array ('code' => 'warning', 'format' => 'File upload failed, error: %s'),
57777e4a 1915
24d3182a 1916// records 300~399 with notices
8ab645cf 1917 300 => array ('code' => 'neutral', 'format' => '%s'),
24d3182a 1918
8ab645cf
AA
1919 );
1920 // Handle the arguments. Is there any better way to do it?
a2b16202 1921 foreach ($log_messages as $record)
8ab645cf
AA
1922 {
1923 if (!isset ($record['c']) or !isset ($msginfo[$record['c']]))
1924 {
41152018
AA
1925 $prefix = isset ($record['c']) ? $record['c'] . ': ' : '';
1926 echo "<div class=msg_neutral>(${prefix}this message was lost)</div>";
8ab645cf
AA
1927 continue;
1928 }
1929 if (isset ($record['a']))
1930 switch (count ($record['a']))
baf37d01 1931 {
8ab645cf
AA
1932 case 1:
1933 $msgtext = sprintf
1934 (
1935 $msginfo[$record['c']]['format'],
1936 $record['a'][0]
1937 );
1938 break;
1939 case 2:
1940 $msgtext = sprintf
1941 (
1942 $msginfo[$record['c']]['format'],
1943 $record['a'][0],
1944 $record['a'][1]
1945 );
1946 break;
1947 case 3:
1948 $msgtext = sprintf
1949 (
1950 $msginfo[$record['c']]['format'],
1951 $record['a'][0],
1952 $record['a'][1],
1953 $record['a'][2]
1954 );
1955 break;
1956 case 4:
1957 default:
1958 $msgtext = sprintf
1959 (
1960 $msginfo[$record['c']]['format'],
1961 $record['a'][0],
1962 $record['a'][1],
1963 $record['a'][2],
1964 $record['a'][3]
1965 );
1966 break;
baf37d01 1967 }
8ab645cf
AA
1968 else
1969 $msgtext = $msginfo[$record['c']]['format'];
1970 echo '<div class=msg_' . $msginfo[$record['c']]['code'] . ">${msgtext}</div>";
baf37d01 1971 }
a2b16202 1972 $log_messages = array();
e673ee24
DO
1973}
1974
65e557dd
AA
1975// renders two tables: port link status and learned MAC list
1976function renderPortsInfo($object_id)
1977{
03522bd8
AA
1978 try
1979 {
1980 if (permitted (NULL, NULL, 'get_link_status'))
1981 $linkStatus = queryDevice ($object_id, 'getportstatus');
1982 else
1983 showWarning ("You don't have permission to view ports link status");
1984
1985 if (permitted (NULL, NULL, 'get_mac_list'))
1986 $macList = sortPortList (queryDevice ($object_id, 'getmaclist'));
1987 else
1988 showWarning ("You don't have permission to view learned MAC list");
1989 }
1990 catch (RTGatewayError $e)
1991 {
1992 showError ($e->getMessage());
1993 return;
1994 }
1995
65e557dd
AA
1996 global $nextorder;
1997 echo "<table width='100%'><tr>";
03522bd8 1998 if (! empty ($linkStatus))
65e557dd 1999 {
03522bd8
AA
2000 echo "<td valign='top' width='50%'>";
2001 startPortlet('Link status');
2002 echo "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>Port<th><th>Link status<th>Link info</tr>";
2003 $order = 'even';
2004 foreach ($linkStatus as $pn => $link)
65e557dd 2005 {
03522bd8 2006 switch ($link['status'])
65e557dd 2007 {
03522bd8
AA
2008 case 'up':
2009 $img_filename = 'link-up.png';
2010 break;
2011 case 'down':
2012 $img_filename = 'link-down.png';
2013 break;
2014 case 'disabled':
2015 $img_filename = 'link-disabled.png';
2016 break;
2017 default:
2018 $img_filename = '1x1t.gif';
2019 }
9f78501e 2020
03522bd8
AA
2021 echo "<tr class='row_$order'>";
2022 $order = $nextorder[$order];
2023 echo '<td>' . $pn;
2024 echo '<td>' . '<img width=16 height=16 src="?module=chrome&uri=pix/' . $img_filename . '">';
2025 echo '<td>' . $link['status'];
2026 $info = '';
2027 if (isset ($link['speed']))
2028 $info .= $link['speed'];
2029 if (isset ($link['duplex']))
2030 {
2031 if (! empty ($info))
2032 $info .= ', ';
2033 $info .= $link['duplex'];
65e557dd 2034 }
03522bd8
AA
2035 echo '<td>' . $info;
2036 echo '</tr>';
65e557dd 2037 }
03522bd8
AA
2038 echo "</table></td>";
2039 finishPortlet();
65e557dd
AA
2040 }
2041
65e557dd
AA
2042 if (! empty ($macList))
2043 {
2044 echo "<td valign='top' width='50%'>";
2045 $rendered_macs = '';
2046 $mac_count = 0;
2047 $rendered_macs .= "<table width='80%' class='widetable' cellspacing=0 cellpadding='5px' align='center'><tr><th>MAC<th>Vlan<th>Port</tr>";
2048 $order = 'even';
2049 foreach ($macList as $pn => $list)
2050 {
2051 $order = $nextorder[$order];
2052 foreach ($list as $item)
2053 {
2054 ++$mac_count;
2055 $rendered_macs .= "<tr class='row_$order'>";
2056 $rendered_macs .= '<td style="font-family: monospace">' . $item['mac'];
2057 $rendered_macs .= '<td>' . $item['vid'];
2058 $rendered_macs .= '<td>' . $pn;
2059 $rendered_macs .= '</tr>';
2060 }
2061 }
2062 $rendered_macs .= "</table></td>";
dec748f6 2063
65e557dd
AA
2064 startPortlet("Learned MACs ($mac_count)");
2065 echo $rendered_macs;
2066 finishPortlet();
2067 }
2068
2069 echo "</td></tr></table>";
2070}
2071
e673ee24 2072/*
51c18782 2073The following conditions must be met:
e673ee24
DO
20741. We can mount onto free atoms only. This means: if any record for an atom
2075already exists in RackSpace, it can't be used for mounting.
20762. We can't unmount from 'W' atoms. Operator should review appropriate comments
2077and either delete them before unmounting or refuse to unmount the object.
2078*/
7e1db771 2079function renderRackSpaceForObject ($object_id)
e673ee24 2080{
e673ee24
DO
2081 // Always process occupied racks plus racks chosen by user. First get racks with
2082 // already allocated rackspace...
51c18782 2083 $workingRacksData = getResidentRacksData ($object_id);
e673ee24 2084 // ...and then add those chosen by user (if any).
2135fd83 2085 if (isset($_REQUEST['rackmulti']))
e673ee24 2086 foreach ($_REQUEST['rackmulti'] as $cand_id)
e673ee24
DO
2087 if (!isset ($workingRacksData[$cand_id]))
2088 {
0cc24e9a 2089 $rackData = spotEntity ('rack', $cand_id);
61a1d996 2090 amplifyCell ($rackData);
e673ee24
DO
2091 $workingRacksData[$cand_id] = $rackData;
2092 }
51690ad4 2093
0a7feebb
AD
2094 // Get a list of all of this object's parents,
2095 // then trim the list to only include parents which are racks
2096 $objectParents = getEntityRelatives('parents', 'object', $object_id);
2097 $parentRacks = array();
2098 foreach ($objectParents as $parentData)
2099 if ($parentData['entity_type'] == 'rack')
2100 $parentRacks[] = $parentData['entity_id'];
2101
e673ee24
DO
2102 // Main layout starts.
2103 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0><tr>";
2104
2105 // Left portlet with rack list.
2106 echo "<td class=pcleft height='1%'>";
2107 startPortlet ('Racks');
a8efc03e 2108 $allRacksData = listCells ('rack');
6d42599c
AA
2109
2110 // filter rack list to match only racks having common tags with the object (reducing $allRacksData)
2111 if (! isset ($_REQUEST['show_all_racks']) and getConfigVar ('FILTER_RACKLIST_BY_TAGS') == 'yes')
2112 {
2113 $matching_racks = array();
2114 $object = spotEntity ('object', $object_id);
2115 $matched_tags = array();
2116 foreach ($allRacksData as $rack)
2117 foreach ($object['etags'] as $tag)
2118 if (tagOnChain ($tag, $rack['etags']) or tagOnChain ($tag, $rack['itags']))
2119 {
2120 $matching_racks[$rack['id']] = $rack;
2121 $matched_tags[$tag['id']] = $tag;
2122 break;
2123 }
2124 // add current object's racks even if they dont match filter
2125 foreach ($workingRacksData as $rack_id => $rack)
2126 if (! isset ($matching_racks[$rack_id]))
2127 $matching_racks[$rack_id] = $rack;
2128 // if matching racks found, and rack list is reduced, show 'show all' link
2129 if (count ($matching_racks) and count ($matching_racks) != count ($allRacksData))
2130 {
2131 $filter_text = '';
2132 foreach ($matched_tags as $tag)
2133 $filter_text .= (empty ($filter_text) ? '' : ' or ') . '{' . $tag['tag'] . '}';
2134 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
2135 $href_show_all .= htmlspecialchars('&show_all_racks=1');
2136 echo "(filtered by <span class='filter-text'>$filter_text</span>, <a href='$href_show_all'>show all</a>)<p>";
2137 $allRacksData = $matching_racks;
2138 }
2139 }
2140
4b8d413e 2141 if (count ($allRacksData) <= getConfigVar ('RACK_PRESELECT_THRESHOLD'))
61a1d996 2142 foreach ($allRacksData as $rack)
51c18782
DO
2143 if (!array_key_exists ($rack['id'], $workingRacksData))
2144 {
2145 amplifyCell ($rack);
2146 $workingRacksData[$rack['id']] = $rack;
2147 }
2148 foreach (array_keys ($workingRacksData) as $rackId)
2149 applyObjectMountMask ($workingRacksData[$rackId], $object_id);
2150 printOpFormIntro ('updateObjectAllocation');
4b8d413e 2151 renderRackMultiSelect ('rackmulti[]', $allRacksData, array_keys ($workingRacksData));
51c18782 2152 echo "<br><br>";
e673ee24
DO
2153 finishPortlet();
2154 echo "</td>";
2155
2156 // Middle portlet with comment and submit.
2157 echo "<td class=pcleft>";
5c8bf2ba 2158 startPortlet ('Comment (for Rackspace History)');
e673ee24
DO
2159 echo "<textarea name=comment rows=10 cols=40></textarea><br>\n";
2160 echo "<input type=submit value='Save' name=got_atoms>\n";
51c18782 2161 echo "<br><br>";
e673ee24
DO
2162 finishPortlet();
2163 echo "</td>";
2164
2165 // Right portlet with rendered racks. If this form submit is not final, we have to
2166 // reflect the former state of the grid in current form.
2167 echo "<td class=pcright rowspan=2 height='1%'>";
2168 startPortlet ('Working copy');
65e557dd 2169 addJS ('js/racktables.js');
e673ee24
DO
2170 echo '<table border=0 cellspacing=10 align=center><tr>';
2171 foreach ($workingRacksData as $rack_id => $rackData)
2172 {
2173 // Order is important here: only original allocation is highlighted.
2174 highlightObject ($rackData, $object_id);
2175 markupAtomGrid ($rackData, 'T');
2176 // If we have a form processed, discard user input and show new database
2177 // contents.
51c18782 2178 if (isset ($_REQUEST['rackmulti'][0])) // is an update
e673ee24
DO
2179 mergeGridFormToRack ($rackData);
2180 echo "<td valign=top>";
2181 echo "<center>\n<h2>${rackData['name']}</h2>\n";
2182 echo "<table class=rack border=0 cellspacing=0 cellpadding=1>\n";
57c69e9c 2183 echo "<tr><th width='10%'>&nbsp;</th>";
bd0bfb76
AD
2184 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
2185 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
2186 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
e673ee24 2187 renderAtomGrid ($rackData);
57c69e9c 2188 echo "<tr><th width='10%'>&nbsp;</th>";
bd0bfb76
AD
2189 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '0', ${rackData['height']})\">Front</a></th>";
2190 echo "<th width='50%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '1', ${rackData['height']})\">Interior</a></th>";
2191 echo "<th width='20%'><a href='javascript:;' onclick=\"toggleColumnOfAtoms('${rack_id}', '2', ${rackData['height']})\">Back</a></th></tr>\n";
0a7feebb
AD
2192 echo "</table>\n<br>\n";
2193 // Determine zero-u checkbox status.
2194 // If form has been submitted, use form data, otherwise use DB data.
dec748f6 2195 if (isset($_REQUEST['op']))
0a7feebb
AD
2196 $checked = isset($_REQUEST['zerou_'.$rack_id]) ? 'checked' : '';
2197 else
2198 $checked = in_array($rack_id, $parentRacks) ? 'checked' : '';
d141833a 2199 echo "<label for=zerou_${rack_id}>Zero-U:</label> <input type=checkbox ${checked} name=zerou_${rack_id} id=zerou_${rack_id}>\n<br><br>\n";
bd0bfb76 2200 echo "<input type='button' onclick='uncheckAll();' value='Uncheck all'>\n";
0a7feebb 2201 echo '</center></td>';
e673ee24
DO
2202 }
2203 echo "</tr></table>";
2204 finishPortlet();
2205 echo "</td>\n";
2206
2207 echo "</form>\n";
2208 echo "</tr></table>\n";
2209}
2210
2211function renderMolecule ($mdata, $object_id)
2212{
2213 // sort data out
2214 $rackpack = array();
2215 global $loclist;
64b95774 2216 foreach ($mdata as $rua)
e673ee24
DO
2217 {
2218 $rack_id = $rua['rack_id'];
2219 $unit_no = $rua['unit_no'];
2220 $atom = $rua['atom'];
2221 if (!isset ($rackpack[$rack_id]))
2222 {
61a1d996
DO
2223 $rackData = spotEntity ('rack', $rack_id);
2224 amplifyCell ($rackData);
e673ee24
DO
2225 for ($i = $rackData['height']; $i > 0; $i--)
2226 for ($locidx = 0; $locidx < 3; $locidx++)
2227 $rackData[$i][$locidx]['state'] = 'F';
2228 $rackpack[$rack_id] = $rackData;
2229 }
2230 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['state'] = 'T';
2231 $rackpack[$rack_id][$unit_no][$loclist[$atom]]['object_id'] = $object_id;
2232 }
2233 // now we have some racks to render
64b95774 2234 foreach ($rackpack as $rackData)
e673ee24
DO
2235 {
2236 markAllSpans ($rackData);
2237 echo "<table class=molecule cellspacing=0>\n";
2238 echo "<caption>${rackData['name']}</caption>\n";
2239 echo "<tr><th width='10%'>&nbsp;</th><th width='20%'>Front</th><th width='50%'>Interior</th><th width='20%'>Back</th></tr>\n";
2240 for ($i = $rackData['height']; $i > 0; $i--)
2241 {
4dcd770e 2242 echo "<tr><th>" . inverseRackUnit ($i, $rackData) . "</th>";
e673ee24
DO
2243 for ($locidx = 0; $locidx < 3; $locidx++)
2244 {
2245 $state = $rackData[$i][$locidx]['state'];
65e557dd 2246 echo "<td class='atom state_${state}'>&nbsp;</td>\n";
e673ee24
DO
2247 }
2248 echo "</tr>\n";
2249 }
2250 echo "</table>\n";
2251 }
2252}
2253
23cdc7e9 2254function renderDepot ()
e673ee24 2255{
23cdc7e9 2256 global $pageno, $nextorder;
23cdc7e9
DO
2257 $cellfilter = getCellFilter();
2258 $objects = filterCellList (listCells ('object'), $cellfilter['expression']);
2259
2260 echo "<table border=0 class=objectview>\n";
2261 echo "<tr><td class=pcleft>";
2262
1ebbf889 2263 if (! renderEmptyResults ($cellfilter, 'objects', count($objects)))
e673ee24 2264 {
4899096d 2265 if (count($objects) > 0)
1ebbf889 2266 {
4899096d
AD
2267 startPortlet ('Objects (' . count ($objects) . ')');
2268 echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
b09a8280 2269 echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Row/Rack or Container</th></tr>';
4899096d 2270 $order = 'odd';
3f8a25d6
DO
2271 # gather IDs of all objects and fetch rackspace info in one pass
2272 $idlist = array();
2273 foreach ($objects as $obj)
2274 $idlist[] = $obj['id'];
2275 $mountinfo = getMountInfo ($idlist);
4899096d
AD
2276 foreach ($objects as $obj)
2277 {
ad3e5e7e 2278 echo "<tr class='row_${order} tdleft' valign=top><td>" . mkA ("<strong>${obj['dname']}</strong>", 'object', $obj['id']);
4899096d
AD
2279 if (count ($obj['etags']))
2280 echo '<br><small>' . serializeTags ($obj['etags'], makeHref(array('page'=>$pageno, 'tab'=>'default')) . '&') . '</small>';
4318ced5
AA
2281 echo "</td><td>${obj['label']}</td>";
2282 echo "<td>${obj['asset_no']}</td>";
3f8a25d6 2283 $places = array();
b09a8280 2284 if ($obj['container_id'])
86dad907 2285 $places[] = mkA ($obj['container_dname'], 'object', $obj['container_id']);
b09a8280 2286 elseif (! array_key_exists ($obj['id'], $mountinfo))
3f8a25d6 2287 $places[] = 'Unmounted';
4899096d 2288 else
3f8a25d6
DO
2289 foreach ($mountinfo[$obj['id']] as $mi)
2290 $places[] = mkA ($mi['row_name'], 'row', $mi['row_id']) . '/' . mkA ($mi['rack_name'], 'rack', $mi['rack_id']);
4318ced5 2291 echo "<td>" . implode (', ', $places) . '</td>';
4899096d
AD
2292 echo '</tr>';
2293 $order = $nextorder[$order];
2294 }
2295 echo '</table>';
2296 finishPortlet();
1ebbf889 2297 }
4899096d
AD
2298 else
2299 echo '<h2>No objects exist</h2>';
e673ee24 2300 }
23cdc7e9
DO
2301
2302 echo "</td><td class=pcright width='25%'>";
2303
95857b5c 2304 renderCellFilterPortlet ($cellfilter, 'object', $objects);
23cdc7e9 2305 echo "</td></tr></table>\n";
e673ee24
DO
2306}
2307
1ebbf889
AA
2308// This function returns TRUE if the result set is too big to be rendered, and no filter is set.
2309// In this case it renders the describing message instead.
2310function renderEmptyResults($cellfilter, $entities_name, $count = NULL)
2311{
2312 if (!$cellfilter['is_empty'])
2313 return FALSE;
2314 if (isset ($_REQUEST['show_all_objects']))
2315 return FALSE;
2316 $max = intval(getConfigVar('MAX_UNFILTERED_ENTITIES'));
2317 if (0 == $max || $count <= $max)
2318 return FALSE;
2319
2320 $href_show_all = trim($_SERVER['REQUEST_URI'], '&');
2321 $href_show_all .= htmlspecialchars('&show_all_objects=1');
2322 $suffix = isset ($count) ? " ($count)" : '';
2323 echo <<<END
2324<p>Please set a filter to display the corresponging $entities_name.
2325<br><a href="$href_show_all">Show all $entities_name$suffix</a>
2326END;
2327 return TRUE;
2328}
2329
e673ee24 2330// History viewer for history-enabled simple dictionaries.
9b8174d7 2331function renderObjectHistory ($object_id)
e673ee24 2332{
e673ee24
DO
2333 $order = 'odd';
2334 global $nextorder;
9b8174d7
AD
2335 echo '<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
2336 echo '<tr><th>change time</th><th>author</th><th>name</th><th>visible label</th><th>asset no</th><th>has problems?</th><th>comment</th></tr>';
2337 $result = usePreparedSelectBlade
2338 (
2339 'SELECT ctime, user_name, name, label, asset_no, has_problems, comment FROM ObjectHistory WHERE id=? ORDER BY ctime',
2340 array ($object_id)
2341 );
e673ee24
DO
2342 while ($row = $result->fetch (PDO::FETCH_NUM))
2343 {
2344 echo "<tr class=row_${order}><td>${row[0]}</td>";
9b8174d7 2345 for ($i = 1; $i <= 6; $i++)
e673ee24
DO
2346 echo "<td>" . $row[$i] . "</td>";
2347 echo "</tr>\n";
2348 $order = $nextorder[$order];
2349 }
2350 echo "</table><br>\n";
2351}
2352
2353function renderRackspaceHistory ()
2354{
4fbb5a00 2355 global $nextorder, $pageno, $tabno;
e673ee24
DO
2356 $order = 'odd';
2357 $history = getRackspaceHistory();
2358 // Show the last operation by default.
2359 if (isset ($_REQUEST['op_id']))
2360 $op_id = $_REQUEST['op_id'];
2361 elseif (isset ($history[0]['mo_id']))
2362 $op_id = $history[0]['mo_id'];
2363 else $op_id = NULL;
dec748f6 2364
e673ee24
DO
2365 $omid = NULL;
2366 $nmid = NULL;
2367 $object_id = 1;
2368 if ($op_id)
2369 list ($omid, $nmid) = getOperationMolecules ($op_id);
2370
2371 // Main layout starts.
2372 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
2373
2374 // Left top portlet with old allocation.
2375 echo "<tr><td class=pcleft>";
2376 startPortlet ('Old allocation');
2377 if ($omid)
2378 {
2379 $oldMolecule = getMolecule ($omid);
2380 renderMolecule ($oldMolecule, $object_id);
2381 }
2382 else
2383 echo "nothing";
2384 finishPortlet();
2385
2386 echo '</td><td class=pcright>';
2387
2388 // Right top portlet with new allocation
2389 startPortlet ('New allocation');
2390 if ($nmid)
2391 {
2392 $newMolecule = getMolecule ($nmid);
2393 renderMolecule ($newMolecule, $object_id);
2394 }
2395 else
2396 echo "nothing";
2397 finishPortlet();
737a3f72 2398
e673ee24 2399 echo '</td></tr><tr><td colspan=2>';
737a3f72 2400
e673ee24
DO
2401 // Bottom portlet with list
2402
2403 startPortlet ('Rackspace allocation history');
2404 echo "<table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>\n";
7fa7047a 2405 echo "<tr><th>timestamp</th><th>author</th><th>object</th><th>comment</th></tr>\n";
e673ee24
DO
2406 foreach ($history as $row)
2407 {
2408 if ($row['mo_id'] == $op_id)
2409 $class = 'hl';
2410 else
2411 $class = "row_${order}";
4fbb5a00 2412 echo "<tr class=${class}><td><a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'op_id'=>$row['mo_id']))."'>${row['ctime']}</a></td>";
7fa7047a
DO
2413 echo "<td>${row['user_name']}</td><td>";
2414 renderCell (spotEntity ('object', $row['ro_id']));
9c6222ef 2415 echo '</td><td>' . niftyString ($row['comment'], 0) . '</td></tr>';
e673ee24
DO
2416 $order = $nextorder[$order];
2417 }
2418 echo "</table>\n";
2419 finishPortlet();
737a3f72 2420
e673ee24 2421 echo '</td></tr></table>';
e673ee24
DO
2422}
2423
4318ced5 2424function renderIPSpaceRecords ($tree, $baseurl, $target = 0, $level = 1)
d65353ad
DO
2425{
2426 $self = __FUNCTION__;
4318ced5 2427 $knight = (getConfigVar ('IPV4_ENABLE_KNIGHT') == 'yes');
00276508
AA
2428
2429 // scroll page to the highlighted item
2430 if ($target && isset ($_REQUEST['hl_net']))
65e557dd 2431 addAutoScrollScript ("net-$target");
00276508 2432
d65353ad
DO
2433 foreach ($tree as $item)
2434 {
4318ced5
AA
2435 if ($display_routers = (getConfigVar ('IPV4_TREE_RTR_AS_CELL') != 'none'))
2436 loadIPAddrList ($item); // necessary to compute router list and address counter
2437
0137d53c
DO
2438 if (isset ($item['id']))
2439 {
1f54e1ba 2440 $decor = array ('indent' => $level);
fec0c8da 2441 if ($item['symbol'] == 'node-collapsed')
4318ced5 2442 $decor['symbolurl'] = "${baseurl}&eid=${item['id']}&hl_net=1";
fec0c8da 2443 elseif ($item['symbol'] == 'node-expanded')
4318ced5
AA
2444 $decor['symbolurl'] = $baseurl . ($item['parent_id'] ? "&eid=${item['parent_id']}&hl_net=1" : '');
2445 $tr_class = '';
21ee3351 2446 if ($target == $item['id'] && isset ($_REQUEST['hl_net']))
64347dcf 2447 {
5c717ce5 2448 $decor['tdclass'] = ' highlight';
4318ced5 2449 $tr_class = $decor['tdclass'];
64347dcf 2450 }
4318ced5
AA
2451 echo "<tr valign=top class=\"$tr_class\">";
2452 printIPNetInfoTDs ($item, $decor);
2453
2454 // capacity and usage
2455 echo "<td class=tdcenter>";
2456 echo getRenderedIPNetCapacity ($item);
64347dcf 2457 echo "</td>";
4318ced5
AA
2458
2459 if ($display_routers)
efd8057e 2460 printRoutersTD (findRouters ($item['own_addrlist']), getConfigVar ('IPV4_TREE_RTR_AS_CELL'));
0137d53c 2461 echo "</tr>";
fec0c8da 2462 if ($item['symbol'] == 'node-expanded' or $item['symbol'] == 'node-expanded-static')
4318ced5 2463 $self ($item['kids'], $baseurl, $target, $level + 1);
0137d53c
DO
2464 }
2465 else
2466 {
4318ced5 2467 // non-allocated (spare) IP range
0137d53c 2468 echo "<tr valign=top>";
21ee3351 2469 printIPNetInfoTDs ($item, array ('indent' => $level, 'knight' => $knight, 'tdclass' => 'sparenetwork'));
00276508 2470
4318ced5 2471 // capacity and usage
21ee3351 2472 echo "<td class=tdcenter>";
4318ced5 2473 echo getRenderedIPNetCapacity ($item);
21ee3351 2474 echo "</td>";
4318ced5
AA
2475 if ($display_routers)
2476 echo "<td></td>";
21ee3351 2477 echo "</tr>";
21ee3351 2478 }
21ee3351
AA
2479 }
2480}
2481
4318ced5 2482function renderIPSpace()
e673ee24 2483{
4fbb5a00 2484 global $pageno, $tabno;
4318ced5 2485 $realm = ($pageno == 'ipv4space' ? 'ipv4net' : 'ipv6net');
31c941ec 2486 $cellfilter = getCellFilter();
4318ced5
AA
2487 $top = NULL;
2488 $netlist = array();
2489 foreach (listCells ($realm) as $net)
2490 {
2491 if (isset ($top) and IPNetContains ($top, $net))
2492 ;
2493 elseif (! count ($cellfilter['expression']) or judgeCell ($net, $cellfilter['expression']))
2494 $top = $net;
1ebbf889 2495 else
4318ced5
AA
2496 continue;
2497 $netlist[$net['id']] = $net;
5388794d 2498 }
21ee3351
AA
2499 $netcount = count ($netlist);
2500 // expand request can take either natural values or "ALL". Zero means no expanding.
2501 $eid = isset ($_REQUEST['eid']) ? $_REQUEST['eid'] : 0;
4318ced5 2502 $tree = prepareIPTree ($netlist, $eid);
21ee3351
AA
2503
2504 echo "<table border=0 class=objectview>\n";
2505 echo "<tr><td class=pcleft>";
4318ced5 2506 if (! renderEmptyResults($cellfilter, 'IP nets', count($tree)))
21ee3351
AA
2507 {
2508 startPortlet ("networks (${netcount})");
2509 echo '<h4>';
4318ced5
AA
2510 $all = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'ALL')) .
2511 $cellfilter['urlextra'] . "'>expand&nbsp;all</a>";
2512 $none = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno, 'eid'=>'NONE')) .
2513 $cellfilter['urlextra'] . "'>collapse&nbsp;all</a>";
2514 $auto = "<a href='".makeHref(array('page'=>$pageno, 'tab'=>$tabno)) .
2515 $cellfilter['urlextra'] . "'>auto-collapse</a>";
2516
21ee3351 2517 if ($eid === 0)
4318ced5 2518 echo 'auto-collapsing at threshold ' . getConfigVar ('TREE_THRESHOLD') . " ($all / $none)";
21ee3351 2519 elseif ($eid === 'ALL')
4318ced5
AA
2520 echo "expanding all ($auto / $none)";
2521 elseif ($eid === 'NONE')
2522 echo "collapsing all ($all / $auto)";
21ee3351
AA
2523 else
2524 {
4318ced5
AA
2525 $netinfo = spotEntity ($realm, $eid);
2526 echo "expanding ${netinfo['ip']}/${netinfo['mask']} ($auto / $all / $none)";
21ee3351
AA
2527 }
2528 echo "</h4><table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2529 echo "<tr><th>prefix</th><th>name/tags</th><th>capacity</th>";
4318ced5 2530 if (getConfigVar ('IPV4_TREE_RTR_AS_CELL') != 'none')
21ee3351
AA
2531 echo "<th>routed by</th>";
2532 echo "</tr>\n";
2533 $baseurl = makeHref(array('page'=>$pageno, 'tab'=>$tabno)) . $cellfilter['urlextra'];
4318ced5 2534 renderIPSpaceRecords ($tree, $baseurl, $eid);
21ee3351
AA
2535 echo "</table>\n";
2536 finishPortlet();
2537 }
2538
2539 echo '</td><td class=pcright>';
4318ced5 2540 renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
21ee3351
AA
2541 echo "</td></tr></table>\n";
2542}
2543
4318ced5 2544function renderIPSpaceEditor()
21ee3351 2545{
4318ced5
AA
2546 global $pageno;
2547 $realm = ($pageno == 'ipv4space' ? 'ipv4net' : 'ipv6net');
2548 $net_page = $realm; // 'ipv4net', 'ipv6net'
2549 $addrspaceList = listCells ($realm);
93a49e5b
AA
2550 startPortlet ('Manage existing (' . count ($addrspaceList) . ')');
2551 if (count ($addrspaceList))
21ee3351 2552 {
21ee3351
AA
2553 echo "<table class='widetable' border=0 cellpadding=5 cellspacing=0 align='center'>\n";
2554 echo "<tr><th>&nbsp;</th><th>prefix</th><th>name</th><th>capacity</th></tr>";
21ee3351
AA
2555 foreach ($addrspaceList as $netinfo)
2556 {
21ee3351 2557 echo "<tr valign=top><td>";
93a49e5b 2558 if (! isIPNetworkEmpty ($netinfo))
21ee3351
AA
2559 printImageHREF ('nodestroy', 'There are ' . count ($netinfo['addrlist']) . ' allocations inside');
2560 else
93a49e5b 2561 echo getOpLink (array ('op' => 'del', 'id' => $netinfo['id']), '', 'destroy', 'Delete this prefix');
ad3e5e7e 2562 echo '</td><td class=tdleft>' . mkA ("${netinfo['ip']}/${netinfo['mask']}", $net_page, $netinfo['id']) . '</td>';
1f54e1ba
DO
2563 echo '<td class=tdleft>' . niftyString ($netinfo['name']);
2564 if (count ($netinfo['etags']))
2565 echo '<br><small>' . serializeTags ($netinfo['etags']) . '</small>';
2566 echo '</td><td>';
4318ced5 2567 echo getRenderedIPNetCapacity ($netinfo);
b1e39212 2568 echo '</tr>';
e673ee24 2569 }
04d619d0
DO
2570 echo "</table>";
2571 finishPortlet();
e673ee24 2572 }
93a49e5b
AA
2573}
2574
2575function renderIPNewNetForm ()
2576{
2577 global $pageno;
2578 if ($pageno == 'ipv6space')
2579 {
2580 $realm = 'ipv6net';
3495ec6e 2581 $regexp = '^[a-fA-F0-9:]*:[a-fA-F0-9:\.]*/\d{1,3}$';
93a49e5b
AA
2582 }
2583 else
2584 {
2585 $realm = 'ipv4net';
3495ec6e 2586 $regexp = '^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$';
93a49e5b
AA
2587 }
2588
2589 // IP prefix validator
10f5133a 2590 addJS ('js/live_validation.js');
93a49e5b 2591 $regexp = addslashes ($regexp);
10f5133a 2592 addJS (<<<END
93a49e5b 2593$(document).ready(function () {
10f5133a 2594 $('form#add' input[name="range"]).attr('match', '$regexp');
93a49e5b
AA
2595 Validate.init();
2596});
2597END
2598 , TRUE);
dec748f6 2599
93a49e5b
AA
2600 startPortlet ('Add new');
2601 echo '<table border=0 cellpadding=10 align=center>';
10f5133a 2602 printOpFormIntro ('add');
93a49e5b
AA
2603 // tags column
2604 echo '<tr><td rowspan=5><h3>assign tags</h3>';
2605 renderNewEntityTags ($realm);
2606 echo '</td>';
2607 // inputs column
2608 $prefix_value = empty ($_REQUEST['set-prefix']) ? '' : $_REQUEST['set-prefix'];
2609 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>";
2610 echo '<tr><th class=tdright>VLAN</th><td class=tdleft>';
2611 echo getOptionTree ('vlan_ck', getAllVLANOptions(), array ('select_class' => 'vertical', 'tabindex' => 2)) . '</td></tr>';
2612 echo "<tr><th class=tdright>name</th><td class=tdleft><input type=text name='name' size='20' tabindex=3></td></tr>";
2613 echo '<tr><td class=tdright><input type=checkbox name="is_connected" tabindex=4></td><th class=tdleft>reserve subnet-router anycast address</th></tr>';
2614 echo "<tr><td colspan=2>";
2615 printImageHREF ('CREATE', 'Add a new network', TRUE, 5);
2616 echo '</td></tr>';
2617 echo "</form></table><br><br>\n";
2618 finishPortlet();
e673ee24
DO
2619}
2620
4318ced5 2621function getRenderedIPNetBacktrace ($range)
e673ee24 2622{
4318ced5
AA
2623 if (getConfigVar ('EXT_IPV4_VIEW') != 'yes')
2624 return array();
e673ee24 2625
4318ced5
AA
2626 $v = ($range['realm'] == 'ipv4net') ? 4 : 6;
2627 $space = "ipv${v}space"; // ipv4space, ipv6space
2628 $tag = "\$ip${v}netid_"; // $ip4netid_, $ip6netid_
dec748f6 2629
4318ced5
AA
2630 $ret = array();
2631 // Build a backtrace from all parent networks.
2632 $clen = $range['mask'];
2633 $backtrace = array();
2634 $backtrace['&rarr;'] = $range;
2635 $key = '';
2636 while (NULL !== ($upperid = getIPAddressNetworkId ($range['ip_bin'], $clen)))
2637 {
2638 $upperinfo = spotEntity ($range['realm'], $upperid);
2639 $clen = $upperinfo['mask'];
2640 $key .= '&uarr;';
2641 $backtrace[$key] = $upperinfo;
2642 }
2643 foreach (array_reverse ($backtrace) as $arrow => $ainfo)
2644 {
2645 $link = '<a href="' . makeHref (array (
2646 'page' => $space,
2647 'tab' => 'default',
2648 'clear-cf' => '',
2649 'cfe' => '{' . $tag . $ainfo['id'] . '}',
2650 'hl_net' => 1,
2651 'eid' => $range['id'],
2652 )) . '" title="View IP tree with this net as root">' . $arrow . '</a>';
2653 $ret[] = array ($link, getOutputOf ('renderCell', $ainfo));
2654 }
2655 return $ret;
2656}
2657
2658function renderIPNetwork ($id)
2659{
2660 global $pageno;
2661 $realm = $pageno; // 'ipv4net', 'ipv6net'
2662 $range = spotEntity ($realm, $id);
2663 loadIPAddrList ($range);
2034d968 2664 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
99ab184f
DO
2665 echo "<tr><td colspan=2 align=center><h1>${range['ip']}/${range['mask']}</h1><h2>";
2666 echo htmlspecialchars ($range['name'], ENT_QUOTES, 'UTF-8') . "</h2></td></tr>\n";
2034d968
DO
2667
2668 echo "<tr><td class=pcleft width='50%'>";
646272be
AA
2669
2670 // render summary portlet
2671 $summary = array();
4318ced5 2672 $summary['%% used'] = getRenderedIPNetCapacity ($range);
2b6b0038 2673 $summary = getRenderedIPNetBacktrace ($range) + $summary;
4318ced5 2674 if ($realm == 'ipv4net')
001e61fa 2675 {
4318ced5
AA
2676 $summary[] = array ('Netmask:', ip4_format ($range['mask_bin']));
2677 $summary[] = array ('Netmask:', "0x" . strtoupper (implode ('', unpack ('H*', $range['mask_bin']))));
2678 $summary['Wildcard bits'] = ip4_format ( ~ $range['mask_bin']);
001e61fa 2679 }
dec748f6 2680
11e3af31
DO
2681 $reuse_domain = considerConfiguredConstraint ($range, '8021Q_MULTILINK_LISTSRC');
2682 $domainclass = array();
2683 foreach (array_count_values (reduceSubarraysToColumn ($range['8021q'], 'domain_id')) as $domain_id => $vlan_count)
2684 $domainclass[$domain_id] = $vlan_count == 1 ? '' : ($reuse_domain ? '{trwarning}' : '{trerror}');
a5f9d1ca 2685 foreach ($range['8021q'] as $item)
11e3af31 2686 $summary[] = array ($domainclass[$item['domain_id']] . 'VLAN:', formatVLANAsHyperlink (getVLANInfo ($item['domain_id'] . '-' . $item['vlan_id'])));
3a4f4023 2687 if (getConfigVar ('EXT_IPV4_VIEW') == 'yes' and count ($routers = findRouters ($range['addrlist'])))
04d619d0 2688 {
646272be
AA
2689 $summary['Routed by'] = '';
2690 foreach ($routers as $rtr)
4318ced5 2691 $summary['Routed by'] .= getOutputOf ('renderRouterCell', $rtr['ip_bin'], $rtr['iface'], spotEntity ('object', $rtr['id']));
04d619d0 2692 }
646272be
AA
2693 $summary['tags'] = '';
2694 renderEntitySummary ($range, 'summary', $summary);
e1ae3fb4 2695
99ab184f
DO
2696 if (strlen ($range['comment']))
2697 {
2698 startPortlet ('Comment');
2699 echo '<div class=commentblock>' . string_insert_hrefs (htmlspecialchars ($range['comment'], ENT_QUOTES, 'UTF-8')) . '</div>';
2700 finishPortlet ();
2701 }
2702
4318ced5 2703 renderFilesPortlet ($realm, $id);
2034d968 2704 echo "</td>\n";
e673ee24 2705
2034d968
DO
2706 echo "<td class=pcright>";
2707 startPortlet ('details');
4318ced5
AA
2708 renderIPNetworkAddresses ($range);
2709 finishPortlet();
2710 echo "</td></tr></table>\n";
2711}
e673ee24 2712
4318ced5
AA
2713// Used solely by renderSeparator
2714function renderEmptyIPv6 ($ip_bin, $hl_ip)
2715{
2716 $class = 'tdleft';
2717 if ($ip_bin === $hl_ip)
5c717ce5 2718 $class .= ' highlight';
4318ced5
AA
2719 $fmt = ip6_format ($ip_bin);
2720 echo "<tr class='$class'><td><a class='ancor' name='ip-$fmt' href='" . makeHref (array ('page' => 'ipaddress', 'ip' => $fmt)) . "'>" . $fmt;
0b8d8309
AA
2721 $editable = permitted ('ipaddress', 'properties', 'editAddress')
2722 ? 'editable'
2723 : '';
cc2fa820
AD
2724 echo "</a></td><td><span class='rsvtext $editable id-$fmt op-upd-ip-name'></span></td>";
2725 echo "<td><span class='rsvtext $editable id-$fmt op-upd-ip-comment'></span></td><td>&nbsp;</td></tr>\n";
4318ced5
AA
2726}
2727
2728// Renders empty table line to shrink empty IPv6 address ranges.
2729// If the range consists of single address, renders the address instead of empty line.
2730// Renders address $hl_ip inside the range.
2731// Used solely by renderIPv6NetworkAddresses
2732function renderSeparator ($first, $last, $hl_ip)
2733{
2734 $self = __FUNCTION__;
2735 if (strcmp ($first, $last) > 0)
2736 return;
2737 if ($first == $last)
2738 renderEmptyIPv6 ($first, $hl_ip);
2739 elseif (isset ($hl_ip) && strcmp ($hl_ip, $first) >= 0 && strcmp ($hl_ip, $last) <= 0)
2740 { // $hl_ip is inside the range $first - $last
2741 $self ($first, ip_prev ($hl_ip), $hl_ip);
2742 renderEmptyIPv6 ($hl_ip, $hl_ip);
2743 $self (ip_next ($hl_ip), $last, $hl_ip);
2744 }
2745 else
cc2fa820 2746 echo "<tr><td colspan=4 class=tdleft></td></tr>\n";
4318ced5
AA
2747}
2748
2749// calculates page number which contains given $ip (used by renderIPv6NetworkAddresses)
2750function getPageNumOfIPv6 ($list, $ip_bin, $maxperpage)
2751{
2752 if (intval ($maxperpage) <= 0 || count ($list) <= $maxperpage)
2753 return 0;
2754 $keys = array_keys ($list);
2755 for ($i = 1; $i <= count ($keys); $i++)
2756 if (strcmp ($keys[$i-1], $ip_bin) >= 0)
2757 return intval ($i / $maxperpage);
2758 return intval (count ($list) / $maxperpage);
2759}
2760
2761function renderIPNetworkAddresses ($range)
2762{
2763 switch (strlen ($range['ip_bin']))
2764 {
2765 case 4: return renderIPv4NetworkAddresses ($range);
2766 case 16: return renderIPv6NetworkAddresses ($range);
2767 default: throw new InvalidArgException ("range['ip_bin']", $range['ip_bin']);
2768 }
2769}
2770
2771function renderIPv4NetworkAddresses ($range)
2772{
2773 global $pageno, $tabno, $aac2;
2774 $startip = ip4_bin2int ($range['ip_bin']);
2775 $endip = ip4_bin2int (ip_last ($range));
2776
2777 if (isset ($_REQUEST['hl_ip']))
00276508 2778 {
4318ced5
AA
2779 $hl_ip = ip4_bin2int (ip4_parse ($_REQUEST['hl_ip']));
2780 addAutoScrollScript ('ip-' . $_REQUEST['hl_ip']); // scroll page to highlighted ip
00276508
AA
2781 }
2782
79b57b18
AA
2783 // pager
2784 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2785 $address_count = $endip - $startip + 1;
2786 $page = 0;
446c25c3 2787 $rendered_pager = '';
79b57b18
AA
2788 if ($address_count > $maxperpage && $maxperpage > 0)
2789 {
2790 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? intval (($hl_ip - $startip) / $maxperpage) : 0);
2791 if ($numpages = ceil ($address_count / $maxperpage))
2792 {
4318ced5 2793 echo '<h3>' . ip4_format (ip4_int2bin ($startip)) . ' ~ ' . ip4_format (ip4_int2bin ($endip)) . '</h3>';
79b57b18
AA
2794 for ($i = 0; $i < $numpages; $i++)
2795 if ($i == $page)
446c25c3 2796 $rendered_pager .= "<b>$i</b> ";
79b57b18 2797 else
4318ced5 2798 $rendered_pager .= "<a href='".makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $range['id'], 'pg' => $i)) . "'>$i</a> ";
79b57b18
AA
2799 }
2800 $startip = $startip + $page * $maxperpage;
2801 $endip = min ($startip + $maxperpage - 1, $endip);
2802 }
2803
446c25c3 2804 echo $rendered_pager;
beb9e88a 2805 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
cc2fa820 2806 echo "<tr><th>Address</th><th>Name</th><th>Comment</th><th>Allocation</th></tr>\n";
e673ee24 2807
4318ced5
AA
2808 markupIPAddrList ($range['addrlist']);
2809 for ($ip = $startip; $ip <= $endip; $ip++)
2810 {
2811 $ip_bin = ip4_int2bin ($ip);
2812 $dottedquad = ip4_format ($ip_bin);
5c717ce5 2813 $tr_class = (isset ($hl_ip) && $hl_ip == $ip ? 'highlight' : '');
0cd7c0f6
AA
2814 if (isset ($range['addrlist'][$ip_bin]))
2815 $addr = $range['addrlist'][$ip_bin];
2816 else
e673ee24 2817 {
4318ced5 2818 echo "<tr class='tdleft $tr_class'><td class=tdleft><a class='ancor' name='ip-$dottedquad' href='" . makeHref(array('page'=>'ipaddress', 'ip' => $dottedquad)) . "'>$dottedquad</a></td>";
0b8d8309
AA
2819 $editable = permitted ('ipaddress', 'properties', 'editAddress')
2820 ? 'editable'
2821 : '';
cc2fa820
AD
2822 echo "<td><span class='rsvtext $editable id-$dottedquad op-upd-ip-name'></span></td>";
2823 echo "<td><span class='rsvtext $editable id-$dottedquad op-upd-ip-comment'></span></td><td></td></tr>\n";
b2035dca
DO
2824 continue;
2825 }
68c91b9c
AA
2826 // render IP change history
2827 $title = '';
2828 $history_class = '';
2829 if (isset ($addr['last_log']))
2830 {
2831 $title = ' title="' . htmlspecialchars ($addr['last_log']['user'] . ', ' . formatAge ($addr['last_log']['time']) , ENT_QUOTES) . '"';
2832 $history_class = 'hover-history underline';
2833 }
4318ced5
AA
2834 $tr_class .= ' ' . $addr['class'];
2835 echo "<tr class='tdleft $tr_class'>";
2836 echo "<td><a class='ancor $history_class' $title name='ip-$dottedquad' href='".makeHref(array('page'=>'ipaddress', 'ip'=>$addr['ip']))."'>${addr['ip']}</a></td>";
0b8d8309 2837 $editable =
cc2fa820 2838 (empty ($addr['allocs']) || !empty ($addr['name']) || !empty ($addr['comment']))
0b8d8309
AA
2839 && permitted ('ipaddress', 'properties', 'editAddress')
2840 ? 'editable'
2841 : '';
cc2fa820
AD
2842 echo "<td><span class='rsvtext $editable id-$dottedquad op-upd-ip-name'>${addr['name']}</span></td>";
2843 echo "<td><span class='rsvtext $editable id-$dottedquad op-upd-ip-comment'>${addr['comment']}</span></td>";
0b8d8309 2844 echo "<td>";
b2035dca 2845 $delim = '';
b2035dca
DO
2846 if ( $addr['reserved'] == 'yes')
2847 {
2d318652 2848 echo "<strong>RESERVED</strong> ";
b2035dca
DO
2849 $delim = '; ';
2850 }
212b565a 2851 foreach ($addr['allocs'] as $ref)
b2035dca 2852 {
beb9e88a 2853 echo $delim . $aac2[$ref['type']];
4318ced5 2854 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'tab' => 'default', 'hl_ip'=>$addr['ip']))."'>";
59a83bd8 2855 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
b2035dca
DO
2856 echo "${ref['object_name']}</a>";
2857 $delim = '; ';
2858 }
2859 if ($delim != '')
e0d6e38e 2860 $delim = '<br>';
212b565a
AA
2861 foreach ($addr['vslist'] as $vs_id)
2862 {
2863 $vs = spotEntity ('ipv4vs', $vs_id);
ad3e5e7e 2864 echo $delim . mkA ("${vs['name']}:${vs['vport']}/${vs['proto']}", 'ipv4vs', $vs['id']) . '&rarr;';
212b565a
AA
2865 $delim = '<br>';
2866 }
eacc0983
AA
2867 foreach ($addr['vsglist'] as $vs_id)
2868 {
2869 $vs = spotEntity ('ipvs', $vs_id);
2870 echo $delim . mkA ($vs['name'], 'ipvs', $vs['id']) . '&rarr;';
2871 $delim = '<br>';
2872 }
212b565a
AA
2873 foreach ($addr['rsplist'] as $rsp_id)
2874 {
2875 $rsp = spotEntity ('ipv4rspool', $rsp_id);
ad3e5e7e 2876 echo "${delim}&rarr;" . mkA ($rsp['name'], 'ipv4rspool', $rsp['id']);
212b565a
AA
2877 $delim = '<br>';
2878 }
b2035dca 2879 echo "</td></tr>\n";
4318ced5 2880 }
2727c7df 2881 // end of iteration
a8dc2982
AA
2882 if (permitted (NULL, NULL, 'set_reserve_comment'))
2883 addJS ('js/inplace-edit.js');
e673ee24
DO
2884
2885 echo "</table>";
446c25c3
AA
2886 if (! empty ($rendered_pager))
2887 echo '<p>' . $rendered_pager . '</p>';
21ee3351
AA
2888}
2889
2890function renderIPv6NetworkAddresses ($netinfo)
2891{
2892 global $pageno, $tabno, $aac2;
2893 echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center' width='100%'>\n";
cc2fa820 2894 echo "<tr><th>Address</th><th>Name</th><th>Comment</th><th>Allocation</th></tr>\n";
21ee3351 2895
4318ced5
AA
2896 $hl_ip = NULL;
2897 if (isset ($_REQUEST['hl_ip']))
2898 {
2899 $hl_ip = ip6_parse ($_REQUEST['hl_ip']);
2900 addAutoScrollScript ('ip-' . ip6_format ($hl_ip));
2901 }
21ee3351 2902
21ee3351
AA
2903 $addresses = $netinfo['addrlist'];
2904 ksort ($addresses);
4318ced5 2905 markupIPAddrList ($addresses);
21ee3351
AA
2906
2907 // pager
2908 $maxperpage = getConfigVar ('IPV4_ADDRS_PER_PAGE');
2909 if (count ($addresses) > $maxperpage && $maxperpage > 0)
2910 {
2911 $page = isset ($_REQUEST['pg']) ? $_REQUEST['pg'] : (isset ($hl_ip) ? getPageNumOfIPv6 ($addresses, $hl_ip, $maxperpage) : 0);
2912 $numpages = ceil (count ($addresses) / $maxperpage);
2913 echo "<center><h3>$numpages pages:</h3>";
2914 for ($i=0; $i<$numpages; $i++)
2915 {
2916 if ($i == $page)
2917 echo "<b>$i</b> ";
2918 else
2919 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $i)) . "'>$i</a> ";
2920 }
2921 echo "</center>";
2922 }
2923
2924 $i = 0;
dec748f6 2925 $interruped = FALSE;
4318ced5
AA
2926 $prev_ip = ip_prev ($netinfo['ip_bin']);
2927 foreach ($addresses as $ip_bin => $addr)
21ee3351
AA
2928 {
2929 if (isset ($page))
2930 {
2931 ++$i;
2932 if ($i <= $maxperpage * $page)
2933 continue;
2934 elseif ($i > $maxperpage * ($page + 1))
2935 {
2936 $interruped = TRUE;
2937 break;
2938 }
2939 }
2940
4318ced5
AA
2941 if ($ip_bin != ip_next ($prev_ip))
2942 renderSeparator (ip_next ($prev_ip), ip_prev ($ip_bin), $hl_ip);
2943 $prev_ip = $ip_bin;
2944
2945 // render IP change history
2946 $title = '';
2947 $history_class = '';
2948 if (isset ($addr['last_log']))
2949 {
2950 $title = ' title="' . htmlspecialchars ($addr['last_log']['user'] . ', ' . formatAge ($addr['last_log']['time']) , ENT_QUOTES) . '"';
2951 $history_class = 'hover-history underline';
2952 }
2953
5c717ce5 2954 $tr_class = $addr['class'] . ' tdleft' . ($hl_ip === $ip_bin ? ' highlight' : '');
4318ced5
AA
2955 echo "<tr class='$tr_class'>";
2956 echo "<td><a class='ancor $history_class' $title name='ip-${addr['ip']}' href='" . makeHref (array ('page' => 'ipaddress', 'ip' => $addr['ip'])) . "'>${addr['ip']}</a></td>";
0b8d8309
AA
2957 $editable =
2958 (empty ($addr['allocs']) || !empty ($addr['name'])
2959 && permitted ('ipaddress', 'properties', 'editAddress')
2960 ? 'editable'
2961 : '');
cc2fa820
AD
2962 echo "<td><span class='rsvtext $editable id-${addr['ip']} op-upd-ip-name'>${addr['name']}</span></td>";
2963 echo "<td><span class='rsvtext $editable id-${addr['ip']} op-upd-ip-comment'>${addr['comment']}</span></td><td>";
21ee3351 2964 $delim = '';
21ee3351
AA
2965 if ( $addr['reserved'] == 'yes')
2966 {
2967 echo "<strong>RESERVED</strong> ";
2968 $delim = '; ';
2969 }
2970 foreach ($addr['allocs'] as $ref)
2971 {
2972 echo $delim . $aac2[$ref['type']];
71066ef1 2973 echo "<a href='".makeHref(array('page'=>'object', 'object_id'=>$ref['object_id'], 'tab' => 'default', 'hl_ip'=>$addr['ip']))."'>";
21ee3351
AA
2974 echo $ref['name'] . (!strlen ($ref['name']) ? '' : '@');
2975 echo "${ref['object_name']}</a>";
2976 $delim = '; ';
2977 }
2978 if ($delim != '')
71066ef1
AA
2979 $delim = '<br>';
2980 foreach ($addr['vslist'] as $vs_id)
2981 {
2982 $vs = spotEntity ('ipv4vs', $vs_id);
ad3e5e7e 2983 echo $delim . mkA ("${vs['name']}:${vs['vport']}/${vs['proto']}", 'ipv4vs', $vs['id']) . '&rarr;';
71066ef1
AA
2984 $delim = '<br>';
2985 }
eacc0983
AA
2986 foreach ($addr['vsglist'] as $vs_id)
2987 {
2988 $vs = spotEntity ('ipvs', $vs_id);
2989 echo $delim . mkA ($vs['name'], 'ipvs', $vs['id']) . '&rarr;';
2990 $delim = '<br>';
2991 }
71066ef1 2992 foreach ($addr['rsplist'] as $rsp_id)
21ee3351 2993 {
71066ef1 2994 $rsp = spotEntity ('ipv4rspool', $rsp_id);
ad3e5e7e 2995 echo "${delim}&rarr;" . mkA ($rsp['name'], 'ipv4rspool', $rsp['id']);
71066ef1 2996 $delim = '<br>';
21ee3351
AA
2997 }
2998 echo "</td></tr>\n";
2999 }
3000 if (! $interruped)
4318ced5 3001 renderSeparator (ip_next ($prev_ip), ip_last ($netinfo), $hl_ip);
21ee3351
AA
3002 if (isset ($page))
3003 { // bottom pager
3004 echo "<tr><td colspan=3>";
3005 if ($page > 0)
3006 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page - 1)) . "'><< prev</a> ";
3007 if ($page < $numpages - 1)
3008 echo "<a href='" . makeHref (array ('page' => $pageno, 'tab' => $tabno, 'id' => $netinfo['id'], 'pg' => $page + 1)) . "'>next >></a> ";
3009 echo "</td></tr>";
3010 }
3011 echo "</table>";
a8dc2982
AA
3012 if (permitted (NULL, NULL, 'set_reserve_comment'))
3013 addJS ('js/inplace-edit.js');
21ee3351
AA
3014}
3015
3016function renderIPNetworkProperties ($id)
e673ee24 3017{
21ee3351
AA
3018 global $pageno;
3019 $netdata = spotEntity ($pageno, $id);
53ef3908 3020 echo "<center><h1>${netdata['ip']}/${netdata['mask']}</h1></center>\n";
e673ee24 3021 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 3022 printOpFormIntro ('editRange');
99ab184f
DO
3023 echo '<tr><td class=tdright><label for=nameinput>Name:</label></td>';
3024 echo "<td class=tdleft><input type=text name=name id=nameinput size=80 maxlength=255 value='";
3025 echo htmlspecialchars ($netdata['name'], ENT_QUOTES, 'UTF-8') . "'></tr>";
3026 echo '<tr><td class=tdright><label for=commentinput>Comment:</label></td>';
3027 echo "<td class=tdleft><textarea name=comment id=commentinput cols=80 rows=25>\n";
3028 echo htmlspecialchars ($netdata['comment'], ENT_QUOTES, 'UTF-8') . "</textarea></tr>";
53ef3908
DO
3029 echo "<tr><td colspan=2 class=tdcenter>";
3030 printImageHREF ('SAVE', 'Save changes', TRUE);
3031 echo "</td></form></tr></table>\n";
93a49e5b
AA
3032
3033 echo '<center>';
3034 if (! isIPNetworkEmpty ($netdata))
3035 echo getOpLink (NULL, 'delete this prefix', 'nodestroy', 'There are ' . count ($netdata['addrlist']) . ' allocations inside');
3036 else
3037 echo getOpLink (array('op'=>'del','id'=>$id), 'delete this prefix', 'destroy');
3038 echo '</center>';
e673ee24
DO
3039}
3040
09a531eb 3041function renderIPAddress ($ip_bin)
e673ee24 3042{
46098972 3043 global $aat, $nextorder;
09a531eb 3044 $address = getIPAddress ($ip_bin);
68225375 3045 echo "<table border=0 class=objectview cellspacing=0 cellpadding=0>";
21ee3351 3046 echo "<tr><td colspan=2 align=center><h1>${address['ip']}</h1></td></tr>\n";
e673ee24 3047
68225375 3048 echo "<tr><td class=pcleft>";
dec748f6 3049
defd92d8 3050 $summary = array();
423c4216 3051 if (strlen ($address['name']))
cc2fa820
AD
3052 $summary['Name'] = $address['name'];
3053 if (strlen ($address['comment']))
3054 $summary['Comment'] = $address['comment'];
defd92d8
AA
3055 $summary['Reserved'] = $address['reserved'];
3056 $summary['Allocations'] = count ($address['allocs']);
4318ced5 3057 if (isset ($address['outpf']))
defd92d8 3058 $summary['Originated NAT connections'] = count ($address['outpf']);
4318ced5 3059 if (isset ($address['inpf']))
defd92d8 3060 $summary['Arriving NAT connections'] = count ($address['inpf']);
defd92d8 3061 renderEntitySummary ($address, 'summary', $summary);
dec748f6 3062
212b565a 3063 // render SLB portlet
eacc0983 3064 if (! empty ($address['vslist']) or ! empty ($address['vsglist']) or ! empty ($address['rsplist']))
212b565a
AA
3065 {
3066 startPortlet ("");
eacc0983
AA
3067 if (! empty ($address['vsglist']))
3068 {
3069 printf ("<h2>virtual service groups (%d):</h2>", count ($address['vsglist']));
3070 foreach ($address['vsglist'] as $vsg_id)
3071 renderSLBEntityCell (spotEntity ('ipvs', $vsg_id));
3072 }
3073
212b565a
AA
3074 if (! empty ($address['vslist']))
3075 {
3076 printf ("<h2>virtual services (%d):</h2>", count ($address['vslist']));
3077 foreach ($address['vslist'] as $vs_id)
3078 renderSLBEntityCell (spotEntity ('ipv4vs', $vs_id));
3079 }
3080
3081 if (! empty ($address['rsplist']))
3082 {
3083 printf ("<h2>RS pools (%d):</h2>", count ($address['rsplist']));
3084 foreach ($address['rsplist'] as $rsp_id)
3085 renderSLBEntityCell (spotEntity ('ipv4rspool', $rsp_id));
3086 }
3087 finishPortlet();
3088 }
68225375 3089 echo "</td>\n";
e673ee24 3090
68225375 3091 echo "<td class=pcright>";
defd92d8 3092 if (isset ($address['class']) and ! empty ($address['allocs']))
59bebe2b 3093 {
8e700dd1 3094 startPortlet ('allocations');
2d318652
DO
3095 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
3096 echo "<tr><th>object</th><th>OS interface</th><th>allocation type</th></tr>\n";
2d318652 3097 // render all allocation records for this address the same way
2d318652 3098 foreach ($address['allocs'] as $bond)
59bebe2b 3099 {
4318ced5 3100 $tr_class = "${address['class']} tdleft";
8e700dd1 3101 if (isset ($_REQUEST['hl_object_id']) and $_REQUEST['hl_object_id'] == $bond['object_id'])
5c717ce5 3102 $tr_class .= ' highlight';
4318ced5
AA
3103 echo "<tr class='$tr_class'>" .
3104 "<td><a href='" . makeHref (array ('page' => 'object', 'object_id' => $bond['object_id'], 'tab' => 'default', 'hl_ip' => $address['ip'])) . "'>${bond['object_name']}</td>" .
3105 "<td>${bond['name']}</td>" .
3106 "<td><strong>" . $aat[$bond['type']] . "</strong></td>" .
3107 "</tr>\n";
59bebe2b
DO
3108 }
3109 echo "</table><br><br>";
3110 finishPortlet();
3111 }
e673ee24 3112
eacc0983
AA
3113 if (! empty ($address['rsplist']))
3114 {
3115 startPortlet ("RS pools:");
3116 foreach ($address['rsplist'] as $rsp_id)
3117 {
3118 renderSLBEntityCell (spotEntity ('ipv4rspool', $rsp_id));
3119 echo '<br>';
3120 }
3121 finishPortlet();
3122 }
3123
3124 if (! empty ($address['vsglist']))
3125 foreach ($address['vsglist'] as $vsg_id)
3126 renderSLBTriplets2 (spotEntity ('ipvs', $vsg_id), FALSE, $ip_bin);
3127
3128 if (! empty ($address['vslist']))
defd92d8 3129 renderSLBTriplets ($address);
5fe1ed76 3130
7419401e
AA
3131 foreach (array ('outpf' => 'departing NAT rules', 'inpf' => 'arriving NAT rules') as $key => $title)
3132 if (! empty ($address[$key]))
3133 {
3134 startPortlet ($title);
3135 echo "<table class='widetable' cellpadding=5 cellspacing=0 border=0 align='center' width='100%'>\n";
3136 echo "<tr><th>proto</th><th>from</th><th>to</th><th>comment</th></tr>\n";
3137 foreach ($address[$key] as $rule)
3138 {
3139 echo "<tr>";
3140 echo "<td>" . $rule['proto'] . "</td>";
3141 echo "<td>" . getRenderedIPPortPair ($rule['localip'], $rule['localport']) . "</td>";
3142 echo "<td>" . getRenderedIPPortPair ($rule['remoteip'], $rule['remoteport']) . "</td>";
3143 echo "<td>" . $rule['description'] . "</td></tr>";
3144 echo "</tr>";
3145 }
3146 echo "</table>";
3147 finishPortlet();
3148 }
105a3bc8 3149
68225375
DO
3150 echo "</td></tr>";
3151 echo "</table>\n";
e673ee24
DO
3152}
3153
09a531eb 3154function renderIPAddressProperties ($ip_bin)
e673ee24 3155{
09a531eb 3156 $address = getIPAddress ($ip_bin);
21ee3351 3157 echo "<center><h1>${address['ip']}</h1></center>\n";
7056988c 3158
1fbc9fd6 3159 startPortlet ('update');
e673ee24 3160 echo "<table border=0 cellpadding=10 cellpadding=1 align='center'>\n";
7056988c 3161 printOpFormIntro ('editAddress');
0186638b
DO
3162 echo '<tr><td class=tdright><label for=id_name>Name:</label></td>';
3163 echo "<td class=tdleft><input type=text name=name id=id_name size=20 value='${address['name']}'></tr>";
cc2fa820
AD
3164 echo '<tr><td class=tdright><label for=id_comment>Comment:</label></td>';
3165 echo "<td class=tdleft><input type=text name=comment id=id_comment size=20 value='${address['comment']}'></tr>";
0186638b
DO
3166 echo '<td class=tdright><label for=id_reserved>Reserved:</label></td>';
3167 echo "<td class=tdleft><input type=checkbox name=reserved id=id_reserved size=20 ";
2d318652 3168 echo ($address['reserved']=='yes') ? 'checked' : '';
f3d274bf 3169 echo "></tr><tr><td class=tdleft>";
53ef3908 3170 printImageHREF ('SAVE', 'Save changes', TRUE);
f3d274bf 3171 echo "</td></form><td class=tdright>";
59a83bd8 3172 if (!strlen ($address['name']) and $address['reserved'] == 'no')
f3d274bf
DO
3173 printImageHREF ('CLEAR gray');
3174 else
3175 {
18a77e3c 3176 printOpFormIntro ('editAddress', array ('name' => '', 'reserved' => '', 'comment' => ''));
f3d274bf
DO
3177 printImageHREF ('CLEAR', 'Release', TRUE);
3178 echo "</form>";
3179 }
3180 echo "</td></tr></table>\n";
1fbc9fd6 3181 finishPortlet();
e673ee24
DO
3182}
3183
09a531eb 3184function renderIPAddressAllocations ($ip_bin)
e673ee24 3185{
4318ced5 3186 function printNewItemTR ()
39b4abd0
DO
3187 {
3188 global $aat;
4318ced5 3189 printOpFormIntro ('add');
39b4abd0 3190 echo "<tr><td>";
9318d2ef 3191 printImageHREF ('add', 'allocate', TRUE);
8d4f7d18 3192 echo "</td><td>";
31babb65 3193 printSelect (getNarrowObjectList ('IPV4OBJ_LISTSRC'), array ('name' => 'object_id', 'tabindex' => 100));
8d4f7d18 3194 echo "</td><td><input type=text tabindex=101 name=bond_name size=10></td><td>";
01abf1de 3195 printSelect ($aat, array ('name' => 'bond_type', 'tabindex' => 102, 'regular'));
9318d2ef 3196 echo "</td><td>";
f5ff50f5 3197 printImageHREF ('add', 'allocate', TRUE, 103);
9318d2ef 3198 echo "</td></form></tr>";
39b4abd0 3199 }
b82cce3f 3200 global $aat;
e673ee24 3201
09a531eb 3202 $address = getIPAddress ($ip_bin);