r2241 - fix meaningless warning about 'class' index
[racktables] / inc / snmp.php
CommitLineData
2ffd5a2a
DO
1<?php
2
3function doSNMPmining ($object_id, $community)
4{
7056988c 5 // FIXME: switch to message log version 2
2ffd5a2a
DO
6 $log = array();
7// IDs: http://cisco.com/en/US/products/sw/cscowork/ps2064/products_device_support_table09186a0080803bb4.html
8// 2950: http://www.cisco.com/en/US/products/hw/switches/ps628/prod_models_home.html
9// 2960: http://www.cisco.com/en/US/products/ps6406/prod_models_comparison.html
10// 2970: http://cisco.com/en/US/products/hw/switches/ps5206/products_qanda_item09186a00801b1750.shtml
11// 3500XL: http://cisco.com/en/US/products/hw/switches/ps637/products_eol_models.html
12// 3560: http://cisco.com/en/US/products/hw/switches/ps5528/products_data_sheet09186a00801f3d7f.html
13// 3750: http://cisco.com/en/US/products/hw/switches/ps5023/products_data_sheet09186a008016136f.html
14
389e01ee 15 // Cisco sysObjectID to model (not product number, i.e. image code is missing) decoder
2ffd5a2a
DO
16 $ciscomodel = array
17 (
18 283 => 'WS-C6509-E (9-slot system)',
19# 694 => 'WS-C2960-24TC-L (24 Ethernet 10/100 ports and 2 dual-purpose uplinks)',
20# 695 => 'WS-C2960-48TC-L (48 Ethernet 10/100 ports and 2 dual-purpose uplinks)',
21 696 => 'WS-C2960G-24TC-L (20 Ethernet 10/100/1000 ports and 4 dual-purpose uplinks)',
22 697 => 'WS-C2960G-48TC-L (44 Ethernet 10/100/1000 ports and 4 dual-purpose uplinks)',
069c186f
DO
23 716 => 'WS-C2960-24TT-L (24 Ethernet 10/100 ports and 2 10/100/1000 uplinks)',
24 717 => 'WS-C2960-48TT-L (48 Ethernet 10/100 ports and 2 10/100/1000 uplinks)',
2ffd5a2a
DO
25 527 => 'WS-C2970G-24T (24 Ethernet 10/100/1000 ports)',
26 561 => 'WS-C2970G-24TS (24 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)',
27 633 => 'WS-C3560-24TS (24 Ethernet 10/100 ports and 2 10/100/1000 SFP uplinks)',
28 634 => 'WS-C3560-48TS (48 Ethernet 10/100 ports and 4 10/100/1000 SFP uplinks)',
29 563 => 'WS-C3560-24PS (24 Ethernet 10/100 POE ports and 2 10/100/1000 SFP uplinks)',
30 564 => 'WS-C3560-48PS (48 Ethernet 10/100 POE ports and 4 10/100/1000 SFP uplinks)',
069c186f 31 516 => 'WS-C3750-48PS (48 Ethernet 10/100 POE ports and 4 10/100/1000 SFP uplinks)',
2ffd5a2a
DO
32 614 => 'WS-C3560G-24PS (24 Ethernet 10/100/1000 POE ports and 4 10/100/1000 SFP uplinks)',
33 615 => 'WS-C3560G-24TS (24 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)',
34 616 => 'WS-C3560G-48PS (48 Ethernet 10/100/1000 POE ports and 4 10/100/1000 SFP uplinks)',
35 617 => 'WS-C3560G-48TS (48 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)',
36 58 => 'WS-C4503 (3-slot system)',
37 503 => '4503 (3-slot system)',
38 59 => 'WS-C4506 (6-slot system)',
39 502 => '4506 (6-slot system)',
40 626 => 'WS-C4948 (48 Ethernet 10/100/1000 ports and 4 10/100/1000 SFP uplinks)',
41 659 => 'WS-C4948-10GE (48 Ethernet 10/100/1000 ports and 2 10Gb X2 uplinks)',
3ec29bf4
DO
42 428 => 'WS-C2950G-24 (24 Ethernet 10/100 ports and 2 1000 GBIC uplinks)',
43 429 => 'WS-C2950G-48 (48 Ethernet 10/100 ports and 2 1000 GBIC uplinks)',
389e01ee 44 559 => 'WS-C2950T-48 (48 Ethernet 10/100 ports and 2 10/100/1000 uplinks)',
2ffd5a2a 45 );
389e01ee 46 // Cisco sysObjectID to Dictionary dict_key map
2ffd5a2a
DO
47 $hwtype = array
48 (
49 283 => 148,
50 696 => 167,
51 697 => 166,
52 527 => 210,
53 561 => 115,
54 633 => 169,
55 634 => 170,
56 563 => 171,
57 564 => 172,
58 614 => 175,
59 615 => 173,
60 616 => 176,
61 617 => 174,
62 58 => 145,
63 503 => 145,
64 59 => 156,
65 502 => 156,
66 626 => 147,
3ec29bf4
DO
67 659 => 377,
68 428 => 389,
69 429 => 390,
389e01ee 70 559 => 387,
069c186f
DO
71 516 => 179,
72 716 => 164,
73 717 => 162,
2ffd5a2a
DO
74 );
75
76 $objectInfo = getObjectInfo ($object_id);
77 $endpoints = findAllEndpoints ($object_id, $objectInfo['name']);
78 $sysName = substr (snmpget ($endpoints[0], $community, 'sysName.0'), strlen ('STRING: '));
79 $sysDescr = snmpget ($endpoints[0], $community, 'sysDescr.0');
80 $sysChassi = snmpget ($endpoints[0], $community, '1.3.6.1.4.1.9.3.6.3.0');
81 // Strip the object type, it's always string here.
82 $sysDescr = substr ($sysDescr, strlen ('STRING: '));
3ec29bf4 83 $IOSversion = ereg_replace ('^.*, Version ([^ ]+), .*$', '\\1', $sysDescr);
2ffd5a2a
DO
84 $sysChassi = str_replace ('"', '', substr ($sysChassi, strlen ('STRING: ')));
85 if (strpos ($sysDescr, 'Cisco IOS Software') === 0 or strpos ($sysDescr, 'Cisco Internetwork Operating System Software') === 0)
86 $log[] = array ('code' => 'success', 'message' => 'Seems to be a Cisco box');
87 else
88 {
89 $log[] = array ('code' => 'error', 'message' => 'No idea how to handle ' . $sysDescr);
3ec29bf4 90 return $log;
2ffd5a2a
DO
91 }
92
93 // It's a Cisco box. Go on.
94 $attrs = getAttrValues ($object_id);
95 // Only fill in attribute values, if they are not set.
96 // FIXME: this is hardcoded
97
98 if (empty ($attrs[3]['value']) && !empty ($sysName)) // FQDN
99 {
100 $error = commitUpdateAttrValue ($object_id, 3, $sysName);
101 if ($error == TRUE)
102 $log[] = array ('code' => 'success', 'message' => 'FQDN set to ' . $sysName);
103 else
104 $log[] = array ('code' => 'error', 'message' => 'Failed settig FQDN: ' . $error);
105 }
106
3ec29bf4 107 if (empty ($attrs[5]['value']) and strlen ($IOSversion) > 0) // SW version
2ffd5a2a 108 {
2ffd5a2a
DO
109 $error = commitUpdateAttrValue ($object_id, 5, $IOSversion);
110 if ($error == TRUE)
111 $log[] = array ('code' => 'success', 'message' => 'SW version set to ' . $IOSversion);
112 else
113 $log[] = array ('code' => 'error', 'message' => 'Failed settig SW version: ' . $error);
114 }
115
116 if (empty ($attrs[1]['value']) and strlen ($sysChassi) > 0) // OEM Serial #1
117 {
118 $error = commitUpdateAttrValue ($object_id, 1, $sysChassi);
119 if ($error == TRUE)
120 $log[] = array ('code' => 'success', 'message' => 'OEM S/N 1 set to ' . $sysChassi);
121 else
122 $log[] = array ('code' => 'error', 'message' => 'Failed settig OEM S/N 1: ' . $error);
123 }
124
125 if (empty ($attrs[4]['value'])) // switch OS type
3ec29bf4 126 {
2ffd5a2a
DO
127 switch (substr ($IOSversion, 0, 4))
128 {
129 case '12.2':
130 $error = commitUpdateAttrValue ($object_id, 4, 252);
131 break;
132 case '12.1':
133 $error = commitUpdateAttrValue ($object_id, 4, 251);
134 break;
135 case '12.0':
136 $error = commitUpdateAttrValue ($object_id, 4, 244);
137 break;
3ec29bf4
DO
138 default:
139 $log[] = array ('code' => 'error', 'message' => "Unknown IOS version ${IOSversion}");
140 $error = TRUE;
141 break;
2ffd5a2a 142 }
3ec29bf4
DO
143 if ($error == TRUE)
144 $log[] = array ('code' => 'success', 'message' => 'Switch OS type set to Cisco IOS ' . substr ($IOSversion, 0, 4));
145 else
146 $log[] = array ('code' => 'error', 'message' => 'Failed setting Switch OS type');
147 }
2ffd5a2a
DO
148
149 $sysObjectID = snmpget ($endpoints[0], $community, 'sysObjectID.0');
150 // Transform OID
151 $sysObjectID = substr ($sysObjectID, strlen ('OID: SNMPv2-SMI::enterprises.9.1.'));
152 if (!isset ($ciscomodel[$sysObjectID]))
153 {
154 $log[] = array ('code' => 'error', 'message' => 'Could not guess exact HW model!');
3ec29bf4 155 return $log;
2ffd5a2a
DO
156 }
157 $log[] = array ('code' => 'success', 'message' => 'HW is ' . $ciscomodel[$sysObjectID]);
158 if (empty ($attrs[2]['value']) and isset ($hwtype[$sysObjectID])) // switch HW type
159 {
160 $error = commitUpdateAttrValue ($object_id, 2, $hwtype[$sysObjectID]);
161 if ($error == TRUE)
162 $log[] = array ('code' => 'success', 'message' => 'HW type updated Ok');
163 else
164 $log[] = array ('code' => 'error', 'message' => 'Failed settig HW type: ' . $error);
165 }
166 // Now fetch ifType, ifDescr and ifPhysAddr and let model-specific code sort the data out.
167 $ifType = snmpwalkoid ($endpoints[0], $community, 'ifType');
168 $ifDescr = snmpwalkoid ($endpoints[0], $community, 'ifdescr');
169 $ifPhysAddress = snmpwalkoid ($endpoints[0], $community, 'ifPhysAddress');
170 // Combine 3 tables into 1...
171 $ifList1 = array();
172 foreach ($ifType as $key => $val)
173 {
174 list ($dummy, $ifIndex) = explode ('.', $key);
175 list ($dummy, $type) = explode (' ', $val);
176 $ifList1[$ifIndex]['type'] = $type;
177 }
178 foreach ($ifDescr as $key => $val)
179 {
180 list ($dummy, $ifIndex) = explode ('.', $key);
181 list ($dummy, $descr) = explode (' ', $val);
182 $ifList1[$ifIndex]['descr'] = trim ($descr, '"');
183 }
184 foreach ($ifPhysAddress as $key => $val)
185 {
5fc57c5b 186 $val = trim ($val);
2ffd5a2a 187 list ($dummy, $ifIndex) = explode ('.', $key);
5fc57c5b
DO
188 // NET-SNMP may return MAC addresses in one of two (?) formats depending on
189 // DISPLAY-HINT internal database. The best we can do about it is to accept both.
190 // Bug originally reported by Walery Wysotsky against openSUSE 11.0.
191 if (preg_match ('/^string: /i', $val)) // STRING: x:yy:z:xx:y:zz
192 {
193 list ($dummy, $val) = explode (' ', $val);
194 $addrbytes = explode (':', $val);
195 foreach ($addrbytes as $bidx => $bytestr)
196 if (strlen ($bytestr) == 1)
197 $addrbytes[$bidx] = '0' . $bytestr;
198 }
199 elseif (preg_match ('/^hex-string: /i', $val)) // Hex-STRING: xx yy zz xx yy zz
200 $addrbytes = explode (' ', substr ($val, -17));
201 else
202 continue; // martian format
203 $ifList1[$ifIndex]['phyad'] = implode ('', $addrbytes);
2ffd5a2a
DO
204 }
205 // ...and then reverse it inside out to make description the key.
206 $ifList2 = array();
207 foreach ($ifList1 as $ifIndex => $data)
208 {
209 $ifList2[$data['descr']]['type'] = $data['type'];
210 $ifList2[$data['descr']]['phyad'] = $data['phyad'];
211 $ifList2[$data['descr']]['idx'] = $ifIndex;
212 }
213 $newports = 0;
214 // Now we can directly pick necessary ports from the table accordingly
215 // to our known hardware model.
216 switch ($sysObjectID)
217 {
218 // FIXME: chassis edge switches often share a common naming scheme, so
219 // the sequences below have to be generalized. Let's have some duplicated
220 // code for the time being, as this is the first implementation ever.
221 case '697': // WS-C2960G-48TC-L
222 // 44 copper ports: 1X, 2X, 3X...
223 // 4 combo ports: 45, 46, 47, 48. Don't list SFP connectors atm, as it's not
224 // clear how to fit them into current Ports table structure.
225 for ($i = 1; $i <= 48; $i++)
226 {
227 $label = ($i >= 45) ? "${i}" : "${i}X";
228 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
229 if ($error == '')
230 $newports++;
231 else
232 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
233 }
234 break;
235 case '696': // WS-C2960G-24TC-L
236 // Quite similar to the above.
237 for ($i = 1; $i <= 24; $i++)
238 {
239 $label = ($i >= 21) ? "${i}" : "${i}X";
240 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
241 if ($error == '')
242 $newports++;
243 else
244 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
245 }
246 break;
069c186f 247 case '716': // WS-C2960-24TT-L
2ffd5a2a
DO
248 case '563': // WS-C3560-24PS
249 case '633': // WS-C3560-24TS
3ec29bf4 250 case '428': // WS-C2950G-24
2ffd5a2a
DO
251 for ($i = 1; $i <= 24; $i++)
252 {
253 $label = "${i}X";
254 $error = commitAddPort ($object_id, 'fa0/' . $i, 19, $label, $ifList2["FastEthernet0/${i}"]['phyad']);
255 if ($error == '')
256 $newports++;
257 else
258 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
259 }
260 for ($i = 1; $i <= 2; $i++)
261 {
262 $label = "${i}";
263 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
264 if ($error == '')
265 $newports++;
266 else
267 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
268 }
269 break;
069c186f 270 case '717': // WS-C2960-48TT-L
3ec29bf4 271 case '429': // WS-C2950G-48
389e01ee 272 case '559': // WS-C2950T-48
3ec29bf4
DO
273 for ($i = 1; $i <= 48; $i++)
274 {
275 $label = "${i}X";
276 $error = commitAddPort ($object_id, 'fa0/' . $i, 19, $label, $ifList2["FastEthernet0/${i}"]['phyad']);
277 if ($error == '')
278 $newports++;
279 else
280 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
281 }
282 for ($i = 1; $i <= 2; $i++)
283 {
284 $label = "${i}";
285 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
286 if ($error == '')
287 $newports++;
288 else
289 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
290 }
291 break;
069c186f
DO
292 case '516': // WS-C3750-48PS
293 for ($i = 1; $i <= 48; $i++)
294 {
295 $label = "${i}X";
296 $error = commitAddPort ($object_id, 'fa1/0/' . $i, 19, $label, $ifList2["FastEthernet1/0/${i}"]['phyad']);
297 if ($error == '')
298 $newports++;
299 else
300 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
301 }
302 for ($i = 1; $i <= 4; $i++)
303 {
304 $label = "${i}";
305 $error = commitAddPort ($object_id, 'gi1/0/' . $i, 24, $label, $ifList2["GigabitEthernet1/0/${i}"]['phyad']);
306 if ($error == '')
307 $newports++;
308 else
309 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
310 }
311 break;
2ffd5a2a
DO
312 case '564': // WS-C3560-48PS
313 case '634': // WS-C3560-48TS
314 for ($i = 1; $i <= 48; $i++)
315 {
316 $label = "${i}X";
317 $error = commitAddPort ($object_id, 'fa0/' . $i, 19, $label, $ifList2["FastEthernet0/${i}"]['phyad']);
318 if ($error == '')
319 $newports++;
320 else
321 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
322 }
323 for ($i = 1; $i <= 4; $i++)
324 {
325 $label = "${i}";
326 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
327 if ($error == '')
328 $newports++;
329 else
330 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
331 }
332 break;
333 case '614': // WS-C3560G-24PS
334 case '615': // WS-C3560G-24TS
335 case '527': // WS-C2970G-24T
336 case '561': // WS-C2970G-24TS
2ffd5a2a
DO
337 for ($i = 1; $i <= 24; $i++)
338 {
339 $label = "${i}X";
340 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
341 if ($error == '')
342 $newports++;
343 else
344 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
345 }
346 break;
347 case '616': // WS-C3560G-48PS
348 case '617': // WS-C3560G-48TS
2ffd5a2a
DO
349 for ($i = 1; $i <= 48; $i++)
350 {
351 $label = "${i}X";
352 $error = commitAddPort ($object_id, 'gi0/' . $i, 24, $label, $ifList2["GigabitEthernet0/${i}"]['phyad']);
353 if ($error == '')
354 $newports++;
355 else
356 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
357 }
358 break;
359 case '626': // WS-C4948
360 case '659': // WS-C4948-10GE
361 for ($i = 1; $i <= 48; $i++)
362 {
363 $label = "${i}X";
364 $error = commitAddPort ($object_id, 'gi1/' . $i, 24, $label, $ifList2["GigabitEthernet1/${i}"]['phyad']);
365 if ($error == '')
366 $newports++;
367 else
368 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $label . ': ' . $error);
369 }
370 break;
371 // For modular devices we don't iterate over all possible port names,
372 // but use the first list to pick everything that looks legitimate
373 // for this hardware. It would be correct to fetch the list of modules
374 // installed to generate lists of ports, but who is going to implement
375 // this?
376 case '503': // 4503
377 case '58': // WS-C4503
378 case '502': // 4506
379 case '59': // WS-C4506
380 case '283': // WS-C6509-E
381 foreach ($ifList1 as $port)
382 {
383 if ($port['type'] != 'ethernet-csmacd(6)')
384 continue;
385 // Copper Fa/Gi harvesting is relatively simple, while 10Gig ports can
386 // have random samples of transciever units.
387 if (strpos ($port['descr'], 'FastEthernet') === 0) // Fa
388 {
389 $prefix = 'fa';
390 $ptype = 19; // RJ-45/100Base-TX
391 list ($slotno, $portno) = explode ('/', substr ($port['descr'], strlen ('FastEthernet')));
392 }
393 elseif (strpos ($port['descr'], 'GigabitEthernet') === 0) // Gi
394 {
395 $prefix = 'gi';
396 $ptype = 24; // RJ-45/1000Base-T
397 list ($slotno, $portno) = explode ('/', substr ($port['descr'], strlen ('GigabitEthernet')));
398 }
399 else continue;
400 $label = "slot ${slotno} port ${portno}";
401 $pname = "${prefix}${slotno}/${portno}";
402 $error = commitAddPort ($object_id, $pname, $ptype, $label, $port['phyad']);
403 if ($error == '')
404 $newports++;
405 else
406 $log[] = array ('code' => 'error', 'message' => 'Failed to add port ' . $pname . ': ' . $error);
407 }
408 break;
409 default:
410 showError ("Unexpected sysObjectID '${sysObjectID}'", __FUNCTION__);
411 }
412 $error = commitAddPort ($object_id, 'con0', 29, 'console', '');
413 if ($error == '')
414 $newports++;
415 else
416 $log[] = array ('code' => 'error', 'message' => 'Failed to add console port : ' . $error);
417 if ($newports > 0)
418 $log[] = array ('code' => 'success', 'message' => "Added ${newports} new ports");
419 return $log;
420}
421
422?>