Commit | Line | Data |
---|---|---|
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 | 25 | function 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. | |
68 | function 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 | ||
144 | function 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 | ?> |