r1214 + switchvlans gateway has learned to list MAC addresses from 2900 swithes
[racktables] / inc / gateways.php
CommitLineData
d33645ff
DO
1<?
2/*
3*
4* This file contains gateway functions for RackTables.
5* A gateway is an external executable, which provides
6* read-only or read-write access to some external entities.
7* Each gateway accepts its own list of command-line args
8* and then reads its stdin for requests. Each request consists
9* of one line and results in exactly one line of reply.
10* The replies must have the following syntax:
11* OK<space>any text up to the end of the line
12* ERR<space>any text up to the end of the line
13*
14*/
15
16
17// This function launches specified gateway with specified
18// command-line arguments and feeds it with the commands stored
19// in the second arg as array.
20// The answers are stored in another array, which is returned
21// by this function. In the case when a gateway cannot be found,
22// finishes prematurely or exits with non-zero return code,
23// a single-item array is returned with the only "ERR" record,
24// which explains the reason.
2da7c9b0 25function queryGateway ($gwname, $questions)
d33645ff
DO
26{
27 $execpath = "./gateways/{$gwname}/main";
d33645ff
DO
28 $dspec = array
29 (
30 0 => array ("pipe", "r"),
31 1 => array ("pipe", "w"),
32 2 => array ("file", "/dev/null", "a")
33 );
34 $pipes = array();
2da7c9b0 35 $gateway = proc_open ($execpath, $dspec, $pipes);
d33645ff
DO
36 if (!is_resource ($gateway))
37 return array ('ERR proc_open() failed in queryGateway()');
38
39// Dialogue starts. Send all questions.
40 foreach ($questions as $q)
41 fwrite ($pipes[0], "$q\n");
42 fclose ($pipes[0]);
43
44// Fetch replies.
2da7c9b0 45 $answers = array ();
d33645ff
DO
46 while (!feof($pipes[1]))
47 {
48 $a = fgets ($pipes[1]);
49 if (empty ($a))
50 continue;
075aeb88
DO
51 // Somehow I got a space appended at the end. Kick it.
52 $answers[] = trim ($a);
d33645ff
DO
53 }
54 fclose($pipes[1]);
55
56 $retval = proc_close ($gateway);
57 if ($retval != 0)
58 return array ("ERR gateway '${gwname}' returned ${retval}");
59 return $answers;
60}
61
0a1b1268
DO
62// This functions returns an array for VLAN list, and an array for port list (both
63// form another array themselves).
64// The ports in the latter array are marked with either VLAN ID or 'trunk'.
65// We don't sort the port list, as the gateway is believed to have done this already
66// (or at least the underlying switch software ought to). This is important, as the
67// port info is transferred to/from form not by names, but by numbers.
68function getSwitchVLANs ($object_id = 0)
69{
70 global $remote_username;
71 if ($object_id <= 0)
72 {
73 showError ('Invalid object_id in getSwitchVLANs()');
74 return;
75 }
76 $objectInfo = getObjectInfo ($object_id);
77 $endpoints = findAllEndpoints ($object_id, $objectInfo['name']);
78 if (count ($endpoints) == 0)
79 {
80 showError ('Can\'t find any mean to reach current object. Please either set FQDN attribute or assign an IP address to the object.');
81 return NULL;
82 }
83 if (count ($endpoints) > 1)
84 {
85 showError ('More than one IP address is assigned to this object, please configure FQDN attribute.');
86 return NULL;
87 }
88 $hwtype = $swtype = 'unknown';
89 foreach (getAttrValues ($object_id) as $record)
90 {
91 if ($record['name'] == 'SW type' && !empty ($record['value']))
92 $swtype = str_replace (' ', '+', $record['value']);
93 if ($record['name'] == 'HW type' && !empty ($record['value']))
94 $hwtype = str_replace (' ', '+', $record['value']);
95 }
96 $data = queryGateway
97 (
98 'switchvlans',
99 array ("connect ${endpoints[0]} $hwtype $swtype ${remote_username}", 'listvlans', 'listports')
100 );
101 if ($data == NULL)
102 {
103 showError ('Failed to get any response from queryGateway() or the gateway died');
104 return NULL;
105 }
106 if (strpos ($data[0], 'OK!') !== 0)
107 {
108 showError ("Gateway failure: returned code ${data[0]}.");
109 return NULL;
110 }
111 if (count ($data) != 3)
112 {
113 showError ("Gateway failure: mailformed reply.");
114 return NULL;
115 }
116 // Now we have VLAN list in $data[1] and port list in $data[2]. Let's sort this out.
117 $tmp = array_unique (explode (';', substr ($data[1], strlen ('OK!'))));
118 if (count ($tmp) == 0)
119 {
120 showError ("Gateway succeeded, but returned no VLAN records.");
121 return NULL;
122 }
123 $vlanlist = array();
124 foreach ($tmp as $record)
125 {
126 list ($vlanid, $vlandescr) = explode ('=', $record);
127 $vlanlist[$vlanid] = $vlandescr;
128 }
129 $portlist = array();
0a73c02f 130 foreach (explode (';', substr ($data[2], strlen ('OK!'))) as $pair)
0a1b1268 131 {
0a73c02f
DO
132 list ($portname, $pair2) = explode ('=', $pair);
133 list ($status, $vlanid) = explode (',', $pair2);
134 $portlist[] = array ('portname' => $portname, 'status' => $status, 'vlanid' => $vlanid);
0a1b1268
DO
135 }
136 if (count ($portlist) == 0)
137 {
138 showError ("Gateway succeeded, but returned no port records.");
139 return NULL;
140 }
141 return array ($vlanlist, $portlist);
142}
143
144function setSwitchVLANs ($object_id = 0, $setcmd)
145{
146 global $remote_username;
147 $log = array();
148 if ($object_id <= 0)
149 return array (array ('code' => 'error', 'message' => 'Invalid object_id in setSwitchVLANs()'));
150 $objectInfo = getObjectInfo ($object_id);
151 $endpoints = findAllEndpoints ($object_id, $objectInfo['name']);
152 if (count ($endpoints) == 0)
153 return array (array ('code' => 'error', 'message' => 'Can\'t find any mean to reach current object. Please either set FQDN attribute or assign an IP address to the object.'));
154 if (count ($endpoints) > 1)
155 return array (array ('code' => 'error', 'message' => 'More than one IP address is assigned to this object, please configure FQDN attribute.'));
156 $hwtype = $swtype = 'unknown';
157 foreach (getAttrValues ($object_id) as $record)
158 {
159 if ($record['name'] == 'SW type' && !empty ($record['value']))
160 $swtype = strtr ($record['value'], ' ', '+');
161 if ($record['name'] == 'HW type' && !empty ($record['value']))
162 $hwtype = strtr ($record['value'], ' ', '+');
163 }
164 $data = queryGateway
165 (
166 'switchvlans',
167 array ("connect ${endpoints[0]} $hwtype $swtype ${remote_username}", $setcmd)
168 );
169 if ($data == NULL)
170 return array (array ('code' => 'error', 'message' => 'Failed to get any response from queryGateway() or the gateway died'));
171 if (strpos ($data[0], 'OK!') !== 0)
172 return array (array ('code' => 'error', 'message' => "Gateway failure: returned code ${data[0]}."));
173 if (count ($data) != 2)
174 return array (array ('code' => 'error', 'message' => 'Gateway failure: mailformed reply.'));
175 // Finally we can parse the response into message array.
176 $ret = array();
177 foreach (split (';', substr ($data[1], strlen ('OK!'))) as $text)
178 {
179 if (strpos ($text, 'I!') === 0)
180 $code = 'success';
181 elseif (strpos ($text, 'W!') === 0)
182 $code = 'warning';
183 else // All improperly formatted messages must be treated as error conditions.
184 $code = 'error';
185 $ret[] = array ('code' => $code, 'message' => substr ($text, 2));
186 }
187 return $ret;
188}
189
d33645ff 190?>