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