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