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