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