Change almost all the plugins to host the SNMP input plugins

This commit is contained in:
Nicolargo
2014-05-02 15:26:45 +02:00
parent 879ec5eb58
commit d2ba067f18
11 changed files with 392 additions and 195 deletions

View File

@@ -221,10 +221,13 @@ class GlancesStatsClientSNMP(GlancesStats):
This class store, update and give stats for the SNMP client
"""
def __init__(self):
def __init__(self, config=None):
# Init the plugin list dict
self._plugins = collections.defaultdict(dict)
# Init the configuration
self.config = config
# Load plugins
self.load_plugins()
@@ -236,5 +239,9 @@ class GlancesStatsClientSNMP(GlancesStats):
# For each plugins, call the update method
for p in self._plugins:
# print "DEBUG: Update %s stats using SNMP request" % p
self._plugins[p].update()
try:
self._plugins[p].update(input='snmp')
except:
# !!! try/catch only for dev
pass

View File

@@ -44,7 +44,16 @@ class Plugin(GlancesPlugin):
# Enter -1 to diplay bottom
self.line_curse = 5
def update(self):
# Init the stats
self.reset()
def reset(self):
"""
Reset/init the stats
"""
self.stats = []
def update(self, input='local'):
"""
Nothing to do here
Just return the global glances_log

View File

@@ -17,7 +17,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Glances CPU plugin
Glances DiskIO plugin
"""
import psutil
@@ -46,57 +46,71 @@ class Plugin(GlancesPlugin):
# Enter -1 to diplay bottom
self.line_curse = 3
# Init stats
self.diskio_old = []
# Init the stats
self.reset()
self.diskio_old = self.stats
def update(self):
def reset(self):
"""
Update disk IO stats
Reset/init the stats
"""
self.stats = []
def update(self, input='local'):
"""
Update disk IO stats using the input method
Input method could be: local (mandatory) or snmp (optionnal)
"""
# Grab the stat using the PsUtil disk_io_counters method
# read_count: number of reads
# write_count: number of writes
# read_bytes: number of bytes read
# write_bytes: number of bytes written
# read_time: time spent reading from disk (in milliseconds)
# write_time: time spent writing to disk (in milliseconds)
diskiocounters = psutil.disk_io_counters(perdisk=True)
# Reset stats
self.reset()
# Previous disk IO stats are stored in the diskio_old variable
diskio = []
if self.diskio_old == []:
# First call, we init the network_old var
try:
self.diskio_old = diskiocounters
except (IOError, UnboundLocalError):
pass
else:
# By storing time data we enable Rx/s and Tx/s calculations in the
# XML/RPC API, which would otherwise be overly difficult work
# for users of the API
time_since_update = getTimeSinceLastUpdate('disk')
if input == 'local':
# Update stats using the standard system lib
# Grab the stat using the PsUtil disk_io_counters method
# read_count: number of reads
# write_count: number of writes
# read_bytes: number of bytes read
# write_bytes: number of bytes written
# read_time: time spent reading from disk (in milliseconds)
# write_time: time spent writing to disk (in milliseconds)
diskiocounters = psutil.disk_io_counters(perdisk=True)
diskio_new = diskiocounters
for disk in diskio_new:
# Previous disk IO stats are stored in the diskio_old variable
if self.diskio_old == []:
# First call, we init the network_old var
try:
# Try necessary to manage dynamic disk creation/del
diskstat = {}
diskstat['time_since_update'] = time_since_update
diskstat['disk_name'] = disk
diskstat['read_bytes'] = (
diskio_new[disk].read_bytes -
self.diskio_old[disk].read_bytes)
diskstat['write_bytes'] = (
diskio_new[disk].write_bytes -
self.diskio_old[disk].write_bytes)
except KeyError:
continue
else:
diskio.append(diskstat)
self.diskio_old = diskio_new
self.diskio_old = diskiocounters
except (IOError, UnboundLocalError):
pass
else:
# By storing time data we enable Rx/s and Tx/s calculations in the
# XML/RPC API, which would otherwise be overly difficult work
# for users of the API
time_since_update = getTimeSinceLastUpdate('disk')
self.stats = diskio
diskio_new = diskiocounters
for disk in diskio_new:
try:
# Try necessary to manage dynamic disk creation/del
diskstat = {}
diskstat['time_since_update'] = time_since_update
diskstat['disk_name'] = disk
diskstat['read_bytes'] = (
diskio_new[disk].read_bytes -
self.diskio_old[disk].read_bytes)
diskstat['write_bytes'] = (
diskio_new[disk].write_bytes -
self.diskio_old[disk].write_bytes)
except KeyError:
continue
else:
self.stats.append(diskstat)
self.diskio_old = diskio_new
elif input == 'snmp':
# Update stats using SNMP
# !!! TODO
pass
return self.stats

View File

@@ -34,6 +34,12 @@ class glancesGrabFs:
"""
# Init the stats
self.reset()
def reset(self):
"""
Reset/init the stats
"""
self.fs_list = []
def __update__(self):
@@ -41,7 +47,7 @@ class glancesGrabFs:
Update the stats
"""
# Reset the list
fs_list = []
self.reset()
# Grab the stats using the PsUtil disk_partitions
# If 'all'=False return physical devices only (e.g. hard disks, cd-rom drives, USB keys)
@@ -69,10 +75,7 @@ class glancesGrabFs:
fs_current['used'] = fs_usage.used
fs_current['avail'] = fs_usage.free
fs_current['percent'] = fs_usage.percent
fs_list.append(fs_current)
# Put the stats in the global var
self.fs_list = fs_list
self.fs_list.append(fs_current)
return self.fs_list
@@ -80,7 +83,6 @@ class glancesGrabFs:
"""
Update and return the stats
"""
return self.__update__()
@@ -106,11 +108,33 @@ class Plugin(GlancesPlugin):
# Enter -1 to diplay bottom
self.line_curse = 4
def update(self):
# Init the stats
self.reset()
def reset(self):
"""
Update stats
Reset/init the stats
"""
self.stats = self.glancesgrabfs.get()
self.stats = []
def update(self, input='local'):
"""
Update the FS stats using the input method
Input method could be: local (mandatory) or snmp (optionnal)
"""
# Reset the stats
self.reset()
if input == 'local':
# Update stats using the standard system lib
self.stats = self.glancesgrabfs.get()
elif input == 'snmp':
# Update stats using SNMP
# !!! TODO
pass
return self.stats
def msg_curse(self, args=None):
"""

View File

@@ -44,46 +44,62 @@ class Plugin(GlancesPlugin):
# Enter -1 to diplay bottom
self.line_curse = 1
def update(self):
# Init the stats
self.reset()
def reset(self):
"""
Update MEM (RAM) stats
Reset/init the stats
"""
self.stats = {}
def update(self, input='local'):
"""
Update MEM (RAM) stats using the input method
Input method could be: local (mandatory) or snmp (optionnal)
"""
# Grab MEM using the PSUtil virtual_memory method
vm_stats = psutil.virtual_memory()
# Reset stats
self.reset()
# Get all the memory stats (copy/paste of the PsUtil documentation)
# total: total physical memory available.
# available: the actual amount of available memory that can be given instantly to processes that request more memory in bytes; this is calculated by summing different memory values depending on the platform (e.g. free + buffers + cached on Linux) and it is supposed to be used to monitor actual memory usage in a cross platform fashion.
# percent: the percentage usage calculated as (total - available) / total * 100.
# used: memory used, calculated differently depending on the platform and designed for informational purposes only.
# free: memory not being used at all (zeroed) that is readily available; note that this doesnt reflect the actual memory available (use available instead).
# Platform-specific fields:
# active: (UNIX): memory currently in use or very recently used, and so it is in RAM.
# inactive: (UNIX): memory that is marked as not used.
# buffers: (Linux, BSD): cache for things like file system metadata.
# cached: (Linux, BSD): cache for various things.
# wired: (BSD, OSX): memory that is marked to always stay in RAM. It is never moved to disk.
# shared: (BSD): memory that may be simultaneously accessed by multiple processes.
mem_stats = {}
for mem in ['total', 'available', 'percent', 'used', 'free',
'active', 'inactive', 'buffers', 'cached',
'wired', 'shared']:
if hasattr(vm_stats, mem):
mem_stats[mem] = getattr(vm_stats, mem)
if input == 'local':
# Update stats using the standard system lib
# Grab MEM using the PSUtil virtual_memory method
vm_stats = psutil.virtual_memory()
# Use the 'free'/htop calculation
# free=available+buffer+cached
mem_stats['free'] = mem_stats['available']
if hasattr(mem_stats, 'buffer'):
mem_stats['free'] += mem_stats['buffer']
if hasattr(mem_stats, 'cached'):
mem_stats['free'] += mem_stats['cached']
# used=total-free
mem_stats['used'] = mem_stats['total'] - mem_stats['free']
# Get all the memory stats (copy/paste of the PsUtil documentation)
# total: total physical memory available.
# available: the actual amount of available memory that can be given instantly to processes that request more memory in bytes; this is calculated by summing different memory values depending on the platform (e.g. free + buffers + cached on Linux) and it is supposed to be used to monitor actual memory usage in a cross platform fashion.
# percent: the percentage usage calculated as (total - available) / total * 100.
# used: memory used, calculated differently depending on the platform and designed for informational purposes only.
# free: memory not being used at all (zeroed) that is readily available; note that this doesnt reflect the actual memory available (use available instead).
# Platform-specific fields:
# active: (UNIX): memory currently in use or very recently used, and so it is in RAM.
# inactive: (UNIX): memory that is marked as not used.
# buffers: (Linux, BSD): cache for things like file system metadata.
# cached: (Linux, BSD): cache for various things.
# wired: (BSD, OSX): memory that is marked to always stay in RAM. It is never moved to disk.
# shared: (BSD): memory that may be simultaneously accessed by multiple processes.
self.stats = {}
for mem in ['total', 'available', 'percent', 'used', 'free',
'active', 'inactive', 'buffers', 'cached',
'wired', 'shared']:
if hasattr(vm_stats, mem):
self.stats[mem] = getattr(vm_stats, mem)
# Set the global variable to the new stats
self.stats = mem_stats
# Use the 'free'/htop calculation
# free=available+buffer+cached
self.stats['free'] = self.stats['available']
if hasattr(self.stats, 'buffer'):
self.stats['free'] += self.stats['buffer']
if hasattr(self.stats, 'cached'):
self.stats['free'] += self.stats['cached']
# used=total-free
self.stats['used'] = self.stats['total'] - self.stats['free']
elif input == 'snmp':
# Update stats using SNMP
# !!! TODO
pass
return self.stats

View File

@@ -44,29 +44,44 @@ class Plugin(GlancesPlugin):
# Enter -1 to diplay bottom
self.line_curse = 1
def update(self):
# Init the stats
self.reset()
def reset(self):
"""
Update MEM (SWAP) stats
Reset/init the stats
"""
self.stats = {}
def update(self, input='local'):
"""
Update MEM (SWAP) stats using the input method
Input method could be: local (mandatory) or snmp (optionnal)
"""
# Grab SWAP using the PSUtil swap_memory method
sm_stats = psutil.swap_memory()
# Reset stats
self.reset()
# Get all the swap stats (copy/paste of the PsUtil documentation)
# total: total swap memory in bytes
# used: used swap memory in bytes
# free: free swap memory in bytes
# percent: the percentage usage
# sin: the number of bytes the system has swapped in from disk (cumulative)
# sout: the number of bytes the system has swapped out from disk (cumulative)
swap_stats = {}
for swap in ['total', 'used', 'free', 'percent',
'sin', 'sout']:
if hasattr(sm_stats, swap):
swap_stats[swap] = getattr(sm_stats, swap)
if input == 'local':
# Update stats using the standard system lib
# Grab SWAP using the PSUtil swap_memory method
sm_stats = psutil.swap_memory()
# Set the global variable to the new stats
self.stats = swap_stats
# Get all the swap stats (copy/paste of the PsUtil documentation)
# total: total swap memory in bytes
# used: used swap memory in bytes
# free: free swap memory in bytes
# percent: the percentage usage
# sin: the number of bytes the system has swapped in from disk (cumulative)
# sout: the number of bytes the system has swapped out from disk (cumulative)
for swap in ['total', 'used', 'free', 'percent',
'sin', 'sout']:
if hasattr(sm_stats, swap):
self.stats[swap] = getattr(sm_stats, swap)
elif input == 'snmp':
# Update stats using SNMP
# !!! TODO
pass
return self.stats

View File

@@ -47,61 +47,76 @@ class Plugin(GlancesPlugin):
# Enter -1 to diplay bottom
self.line_curse = 2
# Init stats
self.network_old = []
# Init the stats
self.reset()
self.network_old = self.stats
def update(self):
def reset(self):
"""
Update network stats
Reset/init the stats
"""
self.stats = []
def update(self, input='local'):
"""
Update network stats using the input method
Input method could be: local (mandatory) or snmp (optionnal)
Stats is a list of dict (one dict per interface)
"""
# Grab network interface stat using the PsUtil net_io_counter method
try:
netiocounters = psutil.net_io_counters(pernic=True)
except UnicodeDecodeError:
self.stats = []
return self.stats
# Reset stats
self.reset()
# Previous network interface stats are stored in the network_old variable
network = []
if self.network_old == []:
# First call, we init the network_old var
if input == 'local':
# Update stats using the standard system lib
# Grab network interface stat using the PsUtil net_io_counter method
try:
self.network_old = netiocounters
except (IOError, UnboundLocalError):
pass
else:
# By storing time data we enable Rx/s and Tx/s calculations in the
# XML/RPC API, which would otherwise be overly difficult work
# for users of the API
time_since_update = getTimeSinceLastUpdate('net')
netiocounters = psutil.net_io_counters(pernic=True)
except UnicodeDecodeError:
return self.stats
# Loop over interfaces
network_new = netiocounters
for net in network_new:
# Previous network interface stats are stored in the network_old variable
self.stats = []
if self.network_old == []:
# First call, we init the network_old var
try:
# Try necessary to manage dynamic network interface
netstat = {}
netstat['time_since_update'] = time_since_update
netstat['interface_name'] = net
netstat['cumulative_rx'] = network_new[net].bytes_recv
netstat['rx'] = (network_new[net].bytes_recv -
self.network_old[net].bytes_recv)
netstat['cumulative_tx'] = network_new[net].bytes_sent
netstat['tx'] = (network_new[net].bytes_sent -
self.network_old[net].bytes_sent)
netstat['cumulative_cx'] = (netstat['cumulative_rx'] +
netstat['cumulative_tx'])
netstat['cx'] = netstat['rx'] + netstat['tx']
except KeyError:
continue
else:
network.append(netstat)
self.network_old = network_new
self.stats = network
self.network_old = netiocounters
except (IOError, UnboundLocalError):
pass
else:
# By storing time data we enable Rx/s and Tx/s calculations in the
# XML/RPC API, which would otherwise be overly difficult work
# for users of the API
time_since_update = getTimeSinceLastUpdate('net')
# Loop over interfaces
network_new = netiocounters
for net in network_new:
try:
# Try necessary to manage dynamic network interface
netstat = {}
netstat['time_since_update'] = time_since_update
netstat['interface_name'] = net
netstat['cumulative_rx'] = network_new[net].bytes_recv
netstat['rx'] = (network_new[net].bytes_recv -
self.network_old[net].bytes_recv)
netstat['cumulative_tx'] = network_new[net].bytes_sent
netstat['tx'] = (network_new[net].bytes_sent -
self.network_old[net].bytes_sent)
netstat['cumulative_cx'] = (netstat['cumulative_rx'] +
netstat['cumulative_tx'])
netstat['cx'] = netstat['rx'] + netstat['tx']
except KeyError:
continue
else:
self.stats.append(netstat)
self.network_old = network_new
elif input == 'snmp':
# Update stats using SNMP
# !!! TODO
pass
return self.stats
def msg_curse(self, args=None):

View File

@@ -43,16 +43,32 @@ class Plugin(GlancesPlugin):
# Note: 'glances_processes' is already init in the glances_processes.py script
def update(self):
def reset(self):
"""
Update processes stats
Reset/init the stats
"""
self.stats = {}
def update(self, input='local'):
"""
Update processes stats using the input method
Input method could be: local (mandatory) or snmp (optionnal)
"""
# Here, update is call for processcount AND processlist
glances_processes.update()
# Reset stats
self.reset()
# Return the processes count
self.stats = glances_processes.getcount()
if input == 'local':
# Update stats using the standard system lib
# Here, update is call for processcount AND processlist
glances_processes.update()
# Return the processes count
self.stats = glances_processes.getcount()
elif input == 'snmp':
# Update stats using SNMP
# !!! TODO
pass
return self.stats

View File

@@ -46,15 +46,30 @@ class Plugin(GlancesPlugin):
# Note: 'glances_processes' is already init in the glances_processes.py script
def update(self):
def reset(self):
"""
Update processes stats
Reset/init the stats
"""
self.stats = []
def update(self, input='local'):
"""
Update processes stats using the input method
Input method could be: local (mandatory) or snmp (optionnal)
"""
# Note: Update is done in the processcount plugin
# Reset stats
self.reset()
# Just return the processes list
self.stats = glances_processes.getlist()
if input == 'local':
# Update stats using the standard system lib
# Note: Update is done in the processcount plugin
# Just return the processes list
self.stats = glances_processes.getlist()
elif input == 'snmp':
# Update stats using SNMP
# !!! TODO
pass
return self.stats

View File

@@ -46,6 +46,13 @@ class glancesGrabSensors:
else:
self.initok = True
# Init the stats
self.reset()
def reset(self):
"""
Reset/init the stats
"""
self.sensors_list = []
def __update__(self):
@@ -53,7 +60,7 @@ class glancesGrabSensors:
Update the stats
"""
# Reset the list
self.sensors_list = []
self.reset()
# grab only temperature stats
if self.initok:
@@ -65,6 +72,8 @@ class glancesGrabSensors:
sensors_current['value'] = int(feature.get_value())
self.sensors_list.append(sensors_current)
return self.sensors_list
def get(self):
self.__update__()
return self.sensors_list
@@ -101,13 +110,35 @@ class Plugin(GlancesPlugin):
# Enter -1 to diplay bottom
self.line_curse = 5
def update(self):
# Init the stats
self.reset()
def reset(self):
"""
Update sensors stats
Reset/init the stats
"""
self.hddtemp_plugin.update()
self.stats = self.glancesgrabsensors.get()
self.stats.extend(self.hddtemp_plugin.stats)
self.stats = []
def update(self, input='local'):
"""
Update sensors stats using the input method
Input method could be: local (mandatory) or snmp (optionnal)
"""
# Reset the stats
self.reset()
if input == 'local':
# Update stats using the standard system lib
self.hddtemp_plugin.update()
self.stats = self.glancesgrabsensors.get()
self.stats.extend(self.hddtemp_plugin.stats)
elif input == 'snmp':
# Update stats using SNMP
# !!! TODO
pass
return self.stats
def msg_curse(self, args=None):
"""

View File

@@ -27,6 +27,9 @@ import platform
# Import Glances libs
from glances.plugins.glances_plugin import GlancesPlugin
# SNMP OID
snmp_oid = { 'hostname': '1.3.6.1.2.1.1.5.0',
'os_name': '1.3.6.1.2.1.1.1.0' }
class Plugin(GlancesPlugin):
"""
@@ -47,32 +50,61 @@ class Plugin(GlancesPlugin):
# Enter -1 to diplay bottom
self.line_curse = 0
def update(self):
# Init the stats
self.reset()
def reset(self):
"""
Update the host/system info
Return the stats (dict)
Reset/init the stats
"""
self.stats = {}
self.stats['os_name'] = platform.system()
self.stats['hostname'] = platform.node()
self.stats['platform'] = platform.architecture()[0]
is_archlinux = os.path.exists(os.path.join("/", "etc", "arch-release"))
if self.stats['os_name'] == "Linux":
if is_archlinux:
self.stats['linux_distro'] = "Arch Linux"
def update(self, input='local'):
"""
Update the host/system info using the input method
Input method could be: local (mandatory) or snmp (optionnal)
Return the stats (dict)
"""
# Reset stats
self.reset()
if input == 'local':
# Update stats using the standard system lib
self.stats['os_name'] = platform.system()
self.stats['hostname'] = platform.node()
self.stats['platform'] = platform.architecture()[0]
is_archlinux = os.path.exists(os.path.join("/", "etc", "arch-release"))
if self.stats['os_name'] == "Linux":
if is_archlinux:
self.stats['linux_distro'] = "Arch Linux"
else:
linux_distro = platform.linux_distribution()
self.stats['linux_distro'] = ' '.join(linux_distro[:2])
self.stats['os_version'] = platform.release()
elif self.stats['os_name'] == "FreeBSD":
self.stats['os_version'] = platform.release()
elif self.stats['os_name'] == "Darwin":
self.stats['os_version'] = platform.mac_ver()[0]
elif self.stats['os_name'] == "Windows":
os_version = platform.win32_ver()
self.stats['os_version'] = ' '.join(os_version[::2])
else:
linux_distro = platform.linux_distribution()
self.stats['linux_distro'] = ' '.join(linux_distro[:2])
self.stats['os_version'] = platform.release()
elif self.stats['os_name'] == "FreeBSD":
self.stats['os_version'] = platform.release()
elif self.stats['os_name'] == "Darwin":
self.stats['os_version'] = platform.mac_ver()[0]
elif self.stats['os_name'] == "Windows":
os_version = platform.win32_ver()
self.stats['os_version'] = ' '.join(os_version[::2])
else:
self.stats['os_version'] = ""
self.stats['os_version'] = ""
elif input == 'snmp':
# Update stats using SNMP
from glances.core.glances_snmp import GlancesSNMPClient
# Init the SNMP request
clientsnmp = GlancesSNMPClient()
# Process the SNMP request
snmpresult = clientsnmp.get_by_oid(*snmp_oid.values())
# Build the internal dict with the SNMP result
for key in snmp_oid.iterkeys():
self.stats[key] = snmpresult[snmp_oid[key]]
return self.stats
def msg_curse(self, args=None):
@@ -103,9 +135,12 @@ class Plugin(GlancesPlugin):
self.stats['os_name'],
self.stats['os_version'])
else:
msg = _(" ({0} {1} {2})").format(self.stats['os_name'],
self.stats['os_version'],
self.stats['platform'])
try:
msg = _(" ({0} {1} {2})").format(self.stats['os_name'],
self.stats['os_version'],
self.stats['platform'])
except:
msg = _(" ({0})").format(self.stats['os_name'])
ret.append(self.curse_add_line(msg, optional=True))
# Return the message with decoration