mirror of
https://github.com/nicolargo/glances.git
synced 2024-12-29 04:04:03 +03:00
Structure and file for the SNMP client
This commit is contained in:
parent
037ec87c53
commit
879ec5eb58
@ -45,6 +45,9 @@ class GlancesClient():
|
||||
self.args = args
|
||||
self.config = config
|
||||
|
||||
# Client mode:
|
||||
self.set_mode()
|
||||
|
||||
# Build the URI
|
||||
if args.password != "":
|
||||
uri = 'http://%s:%s@%s:%d' % (args.username, args.password, args.bind_address, args.port)
|
||||
@ -58,24 +61,46 @@ class GlancesClient():
|
||||
print(_("Error: Couldn't create socket {0}: {1}").format(uri, err))
|
||||
sys.exit(2)
|
||||
|
||||
def set_mode(self, mode='glances'):
|
||||
"""
|
||||
Set the client mode
|
||||
- 'glances' = Glances server (default)
|
||||
- 'snmp' = SNMP (fallback)
|
||||
"""
|
||||
self.mode = mode
|
||||
return self.mode
|
||||
|
||||
def get_mode(self):
|
||||
"""
|
||||
Return the client mode
|
||||
- 'glances' = Glances server (default)
|
||||
- 'snmp' = SNMP (fallback)
|
||||
"""
|
||||
return self.mode
|
||||
|
||||
def login(self):
|
||||
"""
|
||||
Logon to the server
|
||||
"""
|
||||
|
||||
ret = True
|
||||
|
||||
# First of all, trying to connect to a Glances server
|
||||
try:
|
||||
client_version = self.client.init()
|
||||
except socket.error as err:
|
||||
print(_("Error: Connection to server failed: {0}").format(err))
|
||||
sys.exit(2)
|
||||
print(_("Error: Connection to {0} server failed").format(self.get_mode()))
|
||||
# Fallback to SNMP
|
||||
self.set_mode('snmp')
|
||||
except ProtocolError as err:
|
||||
# Others errors
|
||||
if str(err).find(" 401 ") > 0:
|
||||
print(_("Error: Connection to server failed: Bad password"))
|
||||
else:
|
||||
print(_("Error: Connection to server failed: {0}").format(err))
|
||||
sys.exit(2)
|
||||
|
||||
# Test if client and server are "compatible"
|
||||
if __version__[:3] == client_version[:3]:
|
||||
if self.get_mode() == 'glances' and __version__[:3] == client_version[:3]:
|
||||
# Init stats
|
||||
self.stats = GlancesStatsClient()
|
||||
self.stats.set_plugins(json.loads(self.client.getAllPlugins()))
|
||||
@ -86,12 +111,43 @@ class GlancesClient():
|
||||
|
||||
# Init screen
|
||||
self.screen = glancesCurses(args=self.args)
|
||||
|
||||
# Debug
|
||||
# print "Server version: {0}\nClient version: {1}\n".format(__version__, client_version)
|
||||
return True
|
||||
|
||||
ret = True
|
||||
else:
|
||||
return False
|
||||
ret = False
|
||||
|
||||
# Then fallback to SNMP if needed
|
||||
if self.get_mode() == 'snmp':
|
||||
from glances.core.glances_snmp import GlancesSNMPClient
|
||||
|
||||
# Test if SNMP is available on the server side
|
||||
clientsnmp = GlancesSNMPClient()
|
||||
try:
|
||||
# !!! Simple request with system name
|
||||
# !!! Had to have a standard method to check SNMP server
|
||||
clientsnmp.get_by_oid("1.3.6.1.2.1.1.5.0")
|
||||
except:
|
||||
print(_("Error: Connection to {0} server failed").format(self.get_mode()))
|
||||
sys.exit(2)
|
||||
|
||||
from glances.core.glances_stats import GlancesStatsClientSNMP
|
||||
|
||||
print(_("Fallback to {0}").format(self.get_mode()))
|
||||
|
||||
# Init stats
|
||||
self.stats = GlancesStatsClientSNMP()
|
||||
|
||||
# Load limits from the configuration file
|
||||
# Each client can choose its owns limits
|
||||
self.stats.load_limits(self.config)
|
||||
|
||||
# Init screen
|
||||
self.screen = glancesCurses(args=self.args)
|
||||
|
||||
return True
|
||||
|
||||
# Return result
|
||||
return ret
|
||||
|
||||
def update(self):
|
||||
"""
|
||||
@ -101,6 +157,22 @@ class GlancesClient():
|
||||
- Disconnected: Connection NOK
|
||||
"""
|
||||
# Update the stats
|
||||
if self.get_mode() == 'glances':
|
||||
return self.update_glances()
|
||||
elif self.get_mode() == 'snmp':
|
||||
return self.update_snmp()
|
||||
else:
|
||||
print(_("Error: Unknown server mode ({0})").format(self.get_mode()))
|
||||
sys.exit(2)
|
||||
|
||||
def update_glances(self):
|
||||
"""
|
||||
Get stats from Glances server
|
||||
Return the client/server connection status:
|
||||
- Connected: Connection OK
|
||||
- Disconnected: Connection NOK
|
||||
"""
|
||||
# Update the stats
|
||||
try:
|
||||
server_stats = json.loads(self.client.getAll())
|
||||
server_stats['monitor'] = json.loads(self.client.getAllMonitored())
|
||||
@ -112,6 +184,23 @@ class GlancesClient():
|
||||
self.stats.update(server_stats)
|
||||
return "Connected"
|
||||
|
||||
def update_snmp(self):
|
||||
"""
|
||||
Get stats from SNMP server
|
||||
Return the client/server connection status:
|
||||
- Connected: Connection OK
|
||||
- Disconnected: Connection NOK
|
||||
"""
|
||||
# Update the stats
|
||||
try:
|
||||
self.stats.update()
|
||||
except socket.error as e:
|
||||
# Client can not get SNMP server stats
|
||||
return "Disconnected"
|
||||
else:
|
||||
# Grab success
|
||||
return "Connected"
|
||||
|
||||
def serve_forever(self):
|
||||
"""
|
||||
Main client loop
|
||||
@ -122,9 +211,12 @@ class GlancesClient():
|
||||
|
||||
# Update the screen
|
||||
self.screen.update(self.stats, cs_status=cs_status)
|
||||
# print self.stats
|
||||
# print self.stats.getAll()
|
||||
|
||||
def end(self):
|
||||
"""
|
||||
End of the client session
|
||||
"""
|
||||
self.screen.end()
|
||||
|
57
glances/core/glances_snmp.py
Normal file
57
glances/core/glances_snmp.py
Normal file
@ -0,0 +1,57 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of Glances.
|
||||
#
|
||||
# Copyright (C) 2014 Nicolargo <nicolas@nicolargo.com>
|
||||
#
|
||||
# Glances is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Glances is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
import sys
|
||||
|
||||
try:
|
||||
from pysnmp.entity.rfc3413.oneliner import cmdgen
|
||||
except ImportError, e:
|
||||
print("Error importing PySNMP lib: %s" % e)
|
||||
print("Install using pip: # pip install pysnmp")
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
class GlancesSNMPClient(object):
|
||||
""" SNMP client class (based on PySNMP) """
|
||||
|
||||
def __init__(self, host = "localhost",
|
||||
port = 161,
|
||||
community = "public",
|
||||
version = "SNMPv2-MIB"):
|
||||
super(GlancesSNMPClient, self).__init__()
|
||||
self.cmdGen = cmdgen.CommandGenerator()
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.community = community
|
||||
self.version = version
|
||||
|
||||
def __result__(self, errorIndication, errorStatus, errorIndex, varBinds):
|
||||
ret = {}
|
||||
if not (errorIndication or errorStatus):
|
||||
for name, val in varBinds:
|
||||
ret[name.prettyPrint()] = val.prettyPrint()
|
||||
return ret
|
||||
|
||||
def get_by_oid(self, *oid):
|
||||
errorIndication, errorStatus, errorIndex, varBinds = self.cmdGen.getCmd(
|
||||
cmdgen.CommunityData(self.community),
|
||||
cmdgen.UdpTransportTarget((self.host, self.port)),
|
||||
*oid
|
||||
)
|
||||
return self.__result__(errorIndication, errorStatus, errorIndex, varBinds)
|
@ -87,6 +87,12 @@ class GlancesStats(object):
|
||||
plugname = os.path.basename(plug)[len(header):-3].lower()
|
||||
self._plugins[plugname] = m.Plugin()
|
||||
|
||||
def getAllPlugins(self):
|
||||
"""
|
||||
Return the plugins list
|
||||
"""
|
||||
return [p for p in self._plugins]
|
||||
|
||||
def load_limits(self, config=None):
|
||||
"""
|
||||
Load the stats limits
|
||||
@ -109,7 +115,7 @@ class GlancesStats(object):
|
||||
# print "DEBUG: Update %s stats" % p
|
||||
self._plugins[p].update()
|
||||
else:
|
||||
# For client mode
|
||||
# For Glances client mode
|
||||
# Update plugin stats with items sent by the server
|
||||
for p in input_stats:
|
||||
self._plugins[p].set_stats(input_stats[p])
|
||||
@ -118,6 +124,12 @@ class GlancesStats(object):
|
||||
# Update the stats
|
||||
self.__update__(input_stats)
|
||||
|
||||
def getAll(self):
|
||||
"""
|
||||
Return all the stats
|
||||
"""
|
||||
return [ self._plugins[p].get_raw() for p in self._plugins ]
|
||||
|
||||
def get_plugin_list(self):
|
||||
# Return the plugin list
|
||||
self._plugins
|
||||
@ -202,3 +214,27 @@ class GlancesStatsClient(GlancesStats):
|
||||
# generate self._plugins_list["xxx"] = ...
|
||||
# print "DEBUG: Init %s plugin" % plug
|
||||
self._plugins[plug] = m.Plugin()
|
||||
|
||||
|
||||
class GlancesStatsClientSNMP(GlancesStats):
|
||||
"""
|
||||
This class store, update and give stats for the SNMP client
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# Init the plugin list dict
|
||||
self._plugins = collections.defaultdict(dict)
|
||||
|
||||
# Load plugins
|
||||
self.load_plugins()
|
||||
|
||||
def update(self):
|
||||
"""
|
||||
Update the stats using SNMP
|
||||
"""
|
||||
|
||||
# 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()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user