aodh/ceilometer/hardware/inspector/snmp.py
Igor Degtiarov 92a08daa31 Fix H904 violations and re-enable gating
H904 got stricter in hacking 0.9, so fix new violations and
re-enable gating.

Change-Id: I7a3e9006cfb756da4893b9c0a6139a2e70c9aaf4
2014-07-01 13:37:21 +03:00

199 lines
8.0 KiB
Python

#
# Copyright 2014 ZHAW SoE
#
# Authors: Lucas Graf <graflu0@students.zhaw.ch>
# Toni Zehnder <zehndton@students.zhaw.ch>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Inspector for collecting data over SNMP"""
from pysnmp.entity.rfc3413.oneliner import cmdgen
from six.moves.urllib import parse as urlparse
from ceilometer.hardware.inspector import base
class SNMPException(Exception):
pass
def parse_snmp_return(ret):
"""Check the return value of snmp operations
:param ret: a tuple of (errorIndication, errorStatus, errorIndex, data)
returned by pysnmp
:return: a tuple of (err, data)
err: True if error found, or False if no error found
data: a string of error description if error found, or the
actual return data of the snmp operation
"""
err = True
(errIndication, errStatus, errIdx, varBinds) = ret
if errIndication:
data = errIndication
elif errStatus:
data = "%s at %s" % (errStatus.prettyPrint(),
errIdx and varBinds[int(errIdx) - 1] or "?")
else:
err = False
data = varBinds
return (err, data)
class SNMPInspector(base.Inspector):
# CPU OIDs
_cpu_1_min_load_oid = "1.3.6.1.4.1.2021.10.1.3.1"
_cpu_5_min_load_oid = "1.3.6.1.4.1.2021.10.1.3.2"
_cpu_15_min_load_oid = "1.3.6.1.4.1.2021.10.1.3.3"
# Memory OIDs
_memory_total_oid = "1.3.6.1.4.1.2021.4.5.0"
_memory_used_oid = "1.3.6.1.4.1.2021.4.6.0"
# Disk OIDs
_disk_index_oid = "1.3.6.1.4.1.2021.9.1.1"
_disk_path_oid = "1.3.6.1.4.1.2021.9.1.2"
_disk_device_oid = "1.3.6.1.4.1.2021.9.1.3"
_disk_size_oid = "1.3.6.1.4.1.2021.9.1.6"
_disk_used_oid = "1.3.6.1.4.1.2021.9.1.8"
# Network Interface OIDs
_interface_index_oid = "1.3.6.1.2.1.2.2.1.1"
_interface_name_oid = "1.3.6.1.2.1.2.2.1.2"
_interface_speed_oid = "1.3.6.1.2.1.2.2.1.5"
_interface_mac_oid = "1.3.6.1.2.1.2.2.1.6"
_interface_ip_oid = "1.3.6.1.2.1.4.20.1.2"
_interface_received_oid = "1.3.6.1.2.1.2.2.1.10"
_interface_transmitted_oid = "1.3.6.1.2.1.2.2.1.16"
_interface_error_oid = "1.3.6.1.2.1.2.2.1.20"
# Default port and security name
_port = 161
_security_name = 'public'
def __init__(self):
super(SNMPInspector, self).__init__()
self._cmdGen = cmdgen.CommandGenerator()
def _get_or_walk_oid(self, oid, host, get=True):
if get:
func = self._cmdGen.getCmd
ret_func = lambda x: x[0][1]
else:
func = self._cmdGen.nextCmd
ret_func = lambda x: x
ret = func(cmdgen.CommunityData(self._get_security_name(host)),
cmdgen.UdpTransportTarget((host.hostname,
host.port or self._port)),
oid)
(error, data) = parse_snmp_return(ret)
if error:
raise SNMPException("An error occurred, oid %(oid)s, "
"host %(host)s, %(err)s" %
dict(oid=oid, host=host.hostname, err=data))
else:
return ret_func(data)
def _get_value_from_oid(self, oid, host):
return self._get_or_walk_oid(oid, host, True)
def _walk_oid(self, oid, host):
return self._get_or_walk_oid(oid, host, False)
def inspect_cpu(self, host):
# get 1 minute load
cpu_1_min_load = (
str(self._get_value_from_oid(self._cpu_1_min_load_oid, host)))
# get 5 minute load
cpu_5_min_load = (
str(self._get_value_from_oid(self._cpu_5_min_load_oid, host)))
# get 15 minute load
cpu_15_min_load = (
str(self._get_value_from_oid(self._cpu_15_min_load_oid, host)))
yield base.CPUStats(cpu_1_min=float(cpu_1_min_load),
cpu_5_min=float(cpu_5_min_load),
cpu_15_min=float(cpu_15_min_load))
def inspect_memory(self, host):
# get total memory
total = self._get_value_from_oid(self._memory_total_oid, host)
# get used memory
used = self._get_value_from_oid(self._memory_used_oid, host)
yield base.MemoryStats(total=int(total), used=int(used))
def inspect_disk(self, host):
disks = self._walk_oid(self._disk_index_oid, host)
for disk in disks:
for object_name, value in disk:
path_oid = "%s.%s" % (self._disk_path_oid, str(value))
path = self._get_value_from_oid(path_oid, host)
device_oid = "%s.%s" % (self._disk_device_oid, str(value))
device = self._get_value_from_oid(device_oid, host)
size_oid = "%s.%s" % (self._disk_size_oid, str(value))
size = self._get_value_from_oid(size_oid, host)
used_oid = "%s.%s" % (self._disk_used_oid, str(value))
used = self._get_value_from_oid(used_oid, host)
disk = base.Disk(device=str(device),
path=str(path))
stats = base.DiskStats(size=int(size),
used=int(used))
yield (disk, stats)
def inspect_network(self, host):
net_interfaces = self._walk_oid(self._interface_index_oid, host)
for interface in net_interfaces:
for object_name, value in interface:
ip = self._get_ip_for_interface(host, value)
name_oid = "%s.%s" % (self._interface_name_oid,
str(value))
name = self._get_value_from_oid(name_oid, host)
mac_oid = "%s.%s" % (self._interface_mac_oid,
str(value))
mac = self._get_value_from_oid(mac_oid, host)
speed_oid = "%s.%s" % (self._interface_speed_oid,
str(value))
# bits/s to byte/s
speed = self._get_value_from_oid(speed_oid, host) / 8
rx_oid = "%s.%s" % (self._interface_received_oid,
str(value))
rx_bytes = self._get_value_from_oid(rx_oid, host)
tx_oid = "%s.%s" % (self._interface_transmitted_oid,
str(value))
tx_bytes = self._get_value_from_oid(tx_oid, host)
error_oid = "%s.%s" % (self._interface_error_oid,
str(value))
error = self._get_value_from_oid(error_oid, host)
adapted_mac = mac.prettyPrint().replace('0x', '')
interface = base.Interface(name=str(name),
mac=adapted_mac,
ip=str(ip),
speed=int(speed))
stats = base.InterfaceStats(rx_bytes=int(rx_bytes),
tx_bytes=int(tx_bytes),
error=int(error))
yield (interface, stats)
def _get_security_name(self, host):
options = urlparse.parse_qs(host.query)
return options.get('security_name', [self._security_name])[-1]
def _get_ip_for_interface(self, host, interface_id):
ip_addresses = self._walk_oid(self._interface_ip_oid, host)
for ip in ip_addresses:
for name, value in ip:
if value == interface_id:
return str(name).replace(self._interface_ip_oid + ".", "")