r4593 linkPorts(): suppress empty string value for cable ID
[racktables] / wwwroot / inc / popup.php
CommitLineData
38ee0db8 1<?php
cd3775e9
DO
2
3// Return a list of rack IDs, which are P or less positions
4// far from the given rack in its row.
5function getProximateRacks ($rack_id, $proximity = 0)
6{
7 $rack = spotEntity ('rack', $rack_id);
8 $rackList = listCells ('rack', $rack['row_id']);
9 doubleLink ($rackList);
10 $ret = array ($rack_id);
11 $todo = $proximity;
12 $cur_item = $rackList[$rack_id];
13 while ($todo and array_key_exists ('prev_key', $cur_item))
14 {
15 $cur_item = $rackList[$cur_item['prev_key']];
16 $ret[] = $cur_item['id'];
17 $todo--;
18 }
19 $todo = $proximity;
20 $cur_item = $rackList[$rack_id];
21 while ($todo and array_key_exists ('next_key', $cur_item))
22 {
23 $cur_item = $rackList[$cur_item['next_key']];
24 $ret[] = $cur_item['id'];
25 $todo--;
26 }
27 return $ret;
28}
29
2030a7f2 30function findSparePorts ($port_info, $filter)
cd3775e9 31{
2030a7f2
AA
32 $qparams = array ();
33 $query = "SELECT p.id, p.object_id, p.name, p.reservation_comment, o.name as object_name FROM Port p INNER JOIN Object o ON o.id = p.object_id ";
34 // porttype filter (non-strict match)
35 $query .= "INNER JOIN (SELECT type2 as type FROM PortCompat INNER JOIN PortInterfaceCompat ON type1 = oif_id WHERE ";
36 if ($port_info['iif_id'] == 1)
37 $query .= "oif_id = ? ";
38 else
39 $query .= "iif_id IN (SELECT DISTINCT iif_id FROM PortInterfaceCompat WHERE oif_id = ? AND iif_id <> 1) ";
40 $query .= ') as sub1 USING (type)';
41 $qparams[] = $port_info['oif_id'];
42 // self and linked ports filter
43 $query .= "WHERE p.id <> ? " .
44 "AND p.id NOT IN (SELECT porta FROM Link) " .
45 "AND p.id NOT IN (SELECT portb FROM Link) ";
46 $qparams[] = $port_info['id'];
47 // rack filter
48 if (! empty ($filter['racks']))
49 {
50 $query .= 'AND p.object_id IN (SELECT DISTINCT object_id FROM RackSpace WHERE rack_id IN (' .
51 questionMarks (count ($filter['racks'])) . ')) ';
52 $qparams = array_merge ($qparams, $filter['racks']);
53 }
54 // objectname filter
55 if (! empty ($filter['objects']))
cd3775e9 56 {
2030a7f2
AA
57 $query .= 'AND o.name like ? ';
58 $qparams[] = '%' . $filter['objects'] . '%';
cd3775e9 59 }
2030a7f2
AA
60 // portname filter
61 if (! empty ($filter['ports']))
62 {
63 $query .= 'AND p.name LIKE ? ';
64 $qparams[] = '%' . $filter['ports'] . '%';
65 }
66 // ordering
67 $query .= ' ORDER BY p.object_id, p.name';
68
69 $ret = array();
70 $result = usePreparedSelectBlade ($query, $qparams);
71 while ($row = $result->fetch (PDO::FETCH_ASSOC))
72 $ret[$row['id']] = $row['object_name'] .
73 ' -- ' . $row['name'] .
74 (! empty ($row['reservation_comment']) ? ' -- ' . $row['reservation_comment'] : '');
75
24089ff9 76 natsort($ret);
cd3775e9
DO
77 return $ret;
78}
79
0682218d
AD
80// Return a list of all objects which are possible parents
81// Special case for VMs and VM Virtual Switches
82// - only select Servers with the Hypervisor attribute set to Yes
9b8174d7 83function findObjectParentCandidates ($object_id)
0682218d
AD
84{
85 $object = spotEntity ('object', $object_id);
86 $args = array ($object['objtype_id'], $object_id, $object_id);
87
9b8174d7
AD
88 $query = "SELECT O.id, O.name FROM Object O ";
89 $query .= "LEFT JOIN ObjectParentCompat OPC ON O.objtype_id = OPC.parent_objtype_id ";
0682218d 90 $query .= "WHERE OPC.child_objtype_id = ? ";
9b8174d7 91 $query .= "AND O.id != ? ";
0682218d 92 // exclude existing parents
9b8174d7 93 $query .= "AND O.id NOT IN (SELECT parent_entity_id FROM EntityLink WHERE parent_entity_type = 'object' AND child_entity_type = 'object' AND child_entity_id = ?) ";
0682218d
AD
94 if ($object['objtype_id'] == 1504 || $object['objtype_id'] == 1507)
95 {
96 array_push($args, $object['objtype_id'], $object_id, $object_id);
97 $query .= "AND OPC.parent_objtype_id != 4 ";
98 $query .= "UNION ";
9b8174d7
AD
99 $query .= "SELECT O.id, O.name FROM Object O ";
100 $query .= "LEFT JOIN ObjectParentCompat OPC ON O.objtype_id = OPC.parent_objtype_id ";
101 $query .= "LEFT JOIN AttributeValue AV ON O.id = AV.object_id ";
0682218d 102 $query .= "WHERE OPC.child_objtype_id = ? ";
9b8174d7
AD
103 $query .= "AND (O.objtype_id = 4 AND AV.attr_id = 26 AND AV.uint_value = 1501) ";
104 $query .= "AND O.id != ? ";
0682218d 105 // exclude existing parents
9b8174d7 106 $query .= "AND O.id NOT IN (SELECT parent_entity_id FROM EntityLink WHERE parent_entity_type = 'object' AND child_entity_type = 'object' AND child_entity_id = ?) ";
0682218d
AD
107 }
108 $query .= "ORDER BY 2";
109
110 $result = usePreparedSelectBlade ($query, $args);
111 $ret = array();
112 while ($row = $result->fetch (PDO::FETCH_ASSOC))
113 $ret[$row['id']] = $row['name'];
114 return $ret;
115}
116
9a15394d
DO
117function sortObjectAddressesAndNames ($a, $b)
118{
119 $objname_cmp = sortTokenize($a['object_name'], $b['object_name']);
120 if ($objname_cmp == 0)
121 {
122 $name_a = (isset ($a['port_name'])) ? $a['port_name'] : '';
123 $name_b = (isset ($b['port_name'])) ? $b['port_name'] : '';
124 $objname_cmp = sortTokenize($name_a, $name_b);
125 if ($objname_cmp == 0)
126 sortTokenize($a['ip'], $b['ip']);
127 return $objname_cmp;
128 }
129 return $objname_cmp;
130}
131
2030a7f2
AA
132function renderPopupObjectSelector()
133{
134 $object_id = getBypassValue();
135 echo '<div style="background-color: #f0f0f0; border: 1px solid #3c78b5; padding: 10px; height: 100%; text-align: center; margin: 5px;">';
136 echo '<h2>Choose a container:</h2>';
137 echo '<form action="javascript:;">';
138 $parents = findObjectParentCandidates($object_id);
139 printSelect ($parents, array ('name' => 'parents', 'size' => getConfigVar ('MAXSELSIZE')));
140 echo '<br>';
141 echo "<input type=submit value='Proceed' onclick='".
142 "if (getElementById(\"parents\").value != \"\") {".
143 " opener.location=\"?module=redirect&page=object&tab=edit&op=linkEntities&object_id=${object_id}&child_entity_type=object&child_entity_id=${object_id}&parent_entity_type=object&parent_entity_id=\"+getElementById(\"parents\").value; ".
144 " window.close();}'>";
145 echo '</form></div>';
146}
147
148function handlePopupPortLink()
149{
150 assertUIntArg ('port');
151 assertUIntArg ('remote_port');
152 assertStringArg ('cable', TRUE);
153 $port_info = getPortInfo ($_REQUEST['port']);
154 $remote_port_info = getPortInfo ($_REQUEST['remote_port']);
155 $POIFC = getPortOIFCompat();
156 if (isset ($_REQUEST['port_type']) and isset ($_REQUEST['remote_port_type']))
157 {
158 $type_local = $_REQUEST['port_type'];
159 $type_remote = $_REQUEST['remote_port_type'];
160 }
161 else
162 {
163 $type_local = $port_info['oif_id'];
164 $type_remote = $remote_port_info['oif_id'];
165 }
166 $matches = FALSE;
167 $js_table = '';
168 foreach ($POIFC as $pair)
169 if ($pair['type1'] == $type_local && $pair['type2'] == $type_remote)
170 {
171 $matches = TRUE;
172 break;
173 }
174 else
175 $js_table .= "POIFC['${pair['type1']}-${pair['type2']}'] = 1;\n";
176
177 if ($matches)
178 {
179 if ($port_info['oif_id'] != $type_local)
180 commitUpdatePortOIF ($port_info['id'], $type_local);
181 if ($remote_port_info['oif_id'] != $type_remote)
182 commitUpdatePortOIF ($remote_port_info['id'], $type_remote);
183 linkPorts ($port_info['id'], $remote_port_info['id'], $_REQUEST['cable']);
184 showOneLiner
185 (
186 8,
187 array
188 (
189 formatPortLink ($port_info['id'], $port_info['name'], NULL, NULL),
190 formatPort ($remote_port_info),
191 )
192 );
193 addJS (<<<END
194window.opener.location.reload(true);
195window.close();
196END
197 , TRUE);
198 }
199 else
200 {
201 // JS code to display port compatibility hint
202 addJS (<<<END
203POIFC = {};
204$js_table
205$(document).ready(function () {
206 $('select.porttype').change(onPortTypeChange);
207 onPortTypeChange();
208});
209function onPortTypeChange() {
210 var key = $('*[name=port_type]')[0].value + '-' + $('*[name=remote_port_type]')[0].value;
211 if (POIFC[key] == 1)
212 {
213 $('#hint-not-compat').hide();
214 $('#hint-compat').show();
215 }
216 else
217 {
218 $('#hint-compat').hide();
219 $('#hint-not-compat').show();
220 }
221}
222END
223 , TRUE);
224 addCSS (<<<END
225.compat-hint {
226 display: none;
227 font-size: 125%;
228}
229.compat-hint#hint-compat {
230 color: green;
231}
232.compat-hint#hint-not-compat {
233 color: #804040;
234}
235END
236 , TRUE);
237 // render port type editor form
238 echo '<form method=GET>';
239 echo '<input type=hidden name="module" value="popup">';
240 echo '<input type=hidden name="helper" value="portlist">';
241 echo '<input type=hidden name="port" value="' . $port_info['id'] . '">';
242 echo '<input type=hidden name="remote_port" value="' . $remote_port_info['id'] . '">';
243 echo '<input type=hidden name="cable" value="' . htmlspecialchars ($_REQUEST['cable'], ENT_QUOTES) . '">';
244 echo '<p>The ports you have selected are not compatible. Please select a compatible transceiver pair.';
245 echo '<p>';
246 echo formatPort ($port_info) . ' ';
247 if ($port_info['iif_id'] == 1)
248 {
249 echo formatPortIIFOIF ($port_info);
250 echo '<input type=hidden name="port_type" value="' . $port_info['oif_id'] . '">';
251 }
252 else
253 {
254 echo '<label>' . $port_info['iif_name'] . ' ';
255 printSelect (getExistingPortTypeOptions ($port_info['id']), array ('class' => 'porttype', 'name' => 'port_type'), $type_local);
256 echo '</label>';
257 }
258 echo ' &mdash; ';
259 if ($remote_port_info['iif_id'] == 1)
260 {
261 echo formatPortIIFOIF ($remote_port_info);
262 echo '<input type=hidden name="remote_port_type" value="' . $remote_port_info['oif_id'] . '">';
263 }
264 else
265 {
266 echo '<label>' . $remote_port_info['iif_name'] . ' ';
267 printSelect (getExistingPortTypeOptions ($remote_port_info['id']), array ('class' => 'porttype', 'name' => 'remote_port_type'), $type_remote);
268 echo '</label>';
269 }
270 echo ' ' . formatPort ($remote_port_info);
271 echo '<p class="compat-hint" id="hint-not-compat">&#10005; Not compatible port types</p>';
272 echo '<p class="compat-hint" id="hint-compat">&#10004; Compatible port types</p>';
273 echo '<p><input type=submit name="do_link" value="Link">';
274 }
275}
276
277function renderPopupPortSelector()
278{
279 assertUIntArg ('port');
280 $port_id = $_REQUEST['port'];
281 $port_info = getPortInfo ($port_id);
282 $in_rack = isset ($_REQUEST['in_rack']);
283
284 // fill port filter structure
285 $filter = array
286 (
287 'racks' => array(),
288 'objects' => '',
289 'ports' => '',
290 );
291 if (isset ($_REQUEST['filter-obj']))
292 $filter['objects'] = $_REQUEST['filter-obj'];
293 if (isset ($_REQUEST['filter-port']))
294 $filter['ports'] = $_REQUEST['filter-port'];
295 if ($in_rack)
296 {
297 $object = spotEntity ('object', $port_info['object_id']);
298 if ($object['rack_id'])
299 $filter['racks'] = getProximateRacks ($object['rack_id'], getConfigVar ('PROXIMITY_RANGE'));
300 }
301 $spare_ports = findSparePorts ($port_info, $filter);
302
303 // display search form
304 echo 'Link ' . formatPort ($port_info) . ' to...';
305 echo '<form method=GET>';
306 startPortlet ('Port list filter');
307 echo '<input type=hidden name="module" value="popup">';
308 echo '<input type=hidden name="helper" value="portlist">';
309 echo '<input type=hidden name="port" value="' . $port_id . '">';
310 echo '<table align="center" valign="bottom"><tr>';
311 echo '<td class="tdleft"><label>Object name:<br><input type=text size=8 name="filter-obj" value="' . htmlspecialchars ($filter['objects'], ENT_QUOTES) . '"></label></td>';
312 echo '<td class="tdleft"><label>Port name:<br><input type=text size=6 name="filter-port" value="' . htmlspecialchars ($filter['ports'], ENT_QUOTES) . '"></label></td>';
313 echo '<td class="tdleft" valign="bottom"><label><input type=checkbox name="in_rack"' . ($in_rack ? ' checked' : '') . '>Same rack</label></td>';
314 echo '<td valign="bottom"><input type=submit value="show ports"></td>';
315 echo '</tr></table>';
316 finishPortlet();
317
318 // display results
319 startPortlet ('Compatible spare ports');
320 if (empty ($spare_ports))
321 echo '(nothing found)';
322 else
323 {
324 echo getSelect ($spare_ports, array ('name' => 'remote_port', 'size' => getConfigVar ('MAXSELSIZE')), NULL, FALSE);
325 echo "<p>Cable ID: <input type=text id=cable name=cable>";
326 echo "<p><input type='submit' value='Link' name='do_link'>";
327 }
328 finishPortlet();
329 echo '</form>';
330}
331
332function renderPopupIPv4Selector()
333{
334 echo '<div style="background-color: #f0f0f0; border: 1px solid #3c78b5; padding: 10px; height: 100%; text-align: center; margin: 5px;">';
335 echo '<h2>Choose a port:</h2><br><br>';
336 echo '<form action="javascript:;">';
337 echo '<input type=hidden id=ip>';
338 echo '<select size=' . getConfigVar ('MAXSELSIZE') . ' id=addresses>';
339 $addresses = getAllIPv4Allocations();
340 usort ($addresses, 'sortObjectAddressesAndNames');
341 foreach ($addresses as $address)
342 echo "<option value='${address['ip']}' onclick='getElementById(\"ip\").value=\"${address['ip']}\";'>" .
343 "${address['object_name']} ${address['name']} ${address['ip']}</option>\n";
344 echo '</select><br><br>';
345 echo "<input type=submit value='Proceed' onclick='".
346 "if (getElementById(\"ip\")!=\"\") {".
347 " opener.document.getElementById(\"remoteip\").value=getElementById(\"ip\").value;".
348 " window.close();}'>";
349 echo '</form></div>';
350}
351
e0ce8064
DO
352function renderPopupHTML()
353{
354 global $pageno, $tabno;
878512c6 355header ('Content-Type: text/html; charset=UTF-8');
e0ce8064 356?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
39106006 357<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" style="height: 100%;">
b325120a 358<?php
0cc24e9a 359 assertStringArg ('helper');
2030a7f2 360 $text = '';
39106006
DO
361 switch ($_REQUEST['helper'])
362 {
0682218d
AD
363 case 'objlist':
364 $pageno = 'object';
365 $tabno = 'default';
366 fixContext();
3ec33017 367 assertPermission();
2030a7f2 368 $text .= getOutputOf ('renderPopupObjectSelector');
0682218d 369 break;
39106006 370 case 'portlist':
026a79ee
DO
371 $pageno = 'depot';
372 $tabno = 'default';
4dc8e857 373 fixContext();
3ec33017 374 assertPermission();
2030a7f2
AA
375 $text .= '<div style="background-color: #f0f0f0; border: 1px solid #3c78b5; padding: 10px; height: 100%; text-align: center; margin: 5px;">';
376 if (isset ($_REQUEST['do_link']))
377 $text .= getOutputOf ('handlePopupPortLink');
378 else
379 $text .= getOutputOf ('renderPopupPortSelector');
380 $text .= '</div>';
39106006
DO
381 break;
382 case 'inet4list':
4dc8e857
DO
383 $pageno = 'ipv4space';
384 $tabno = 'default';
385 fixContext();
3ec33017 386 assertPermission();
2030a7f2 387 $text .= getOutputOf ('renderPopupIPv4Selector');
39106006
DO
388 break;
389 default:
d6b0c986 390 throw new InvalidRequestArgException ('helper', $_REQUEST['helper']);
39106006 391 }
2030a7f2
AA
392 echo '<head><title>RackTables pop-up</title>';
393 printPageHeaders();
394 echo '</head>';
395 echo '<body style="height: 100%;">' . $text . '</body>';
e673ee24 396?>
e673ee24 397</html>
0cc24e9a 398<?php
0cc24e9a
DY
399}
400?>