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