mirror of
https://github.com/nicolargo/glances.git
synced 2024-12-29 20:21:35 +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.args = args
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
|
# Client mode:
|
||||||
|
self.set_mode()
|
||||||
|
|
||||||
# Build the URI
|
# Build the URI
|
||||||
if args.password != "":
|
if args.password != "":
|
||||||
uri = 'http://%s:%s@%s:%d' % (args.username, args.password, args.bind_address, args.port)
|
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))
|
print(_("Error: Couldn't create socket {0}: {1}").format(uri, err))
|
||||||
sys.exit(2)
|
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):
|
def login(self):
|
||||||
"""
|
"""
|
||||||
Logon to the server
|
Logon to the server
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
ret = True
|
||||||
|
|
||||||
|
# First of all, trying to connect to a Glances server
|
||||||
try:
|
try:
|
||||||
client_version = self.client.init()
|
client_version = self.client.init()
|
||||||
except socket.error as err:
|
except socket.error as err:
|
||||||
print(_("Error: Connection to server failed: {0}").format(err))
|
print(_("Error: Connection to {0} server failed").format(self.get_mode()))
|
||||||
sys.exit(2)
|
# Fallback to SNMP
|
||||||
|
self.set_mode('snmp')
|
||||||
except ProtocolError as err:
|
except ProtocolError as err:
|
||||||
|
# Others errors
|
||||||
if str(err).find(" 401 ") > 0:
|
if str(err).find(" 401 ") > 0:
|
||||||
print(_("Error: Connection to server failed: Bad password"))
|
print(_("Error: Connection to server failed: Bad password"))
|
||||||
else:
|
else:
|
||||||
print(_("Error: Connection to server failed: {0}").format(err))
|
print(_("Error: Connection to server failed: {0}").format(err))
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
# Test if client and server are "compatible"
|
if self.get_mode() == 'glances' and __version__[:3] == client_version[:3]:
|
||||||
if __version__[:3] == client_version[:3]:
|
|
||||||
# Init stats
|
# Init stats
|
||||||
self.stats = GlancesStatsClient()
|
self.stats = GlancesStatsClient()
|
||||||
self.stats.set_plugins(json.loads(self.client.getAllPlugins()))
|
self.stats.set_plugins(json.loads(self.client.getAllPlugins()))
|
||||||
@ -86,12 +111,43 @@ class GlancesClient():
|
|||||||
|
|
||||||
# Init screen
|
# Init screen
|
||||||
self.screen = glancesCurses(args=self.args)
|
self.screen = glancesCurses(args=self.args)
|
||||||
|
|
||||||
# Debug
|
ret = True
|
||||||
# print "Server version: {0}\nClient version: {1}\n".format(__version__, client_version)
|
|
||||||
return True
|
|
||||||
else:
|
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):
|
def update(self):
|
||||||
"""
|
"""
|
||||||
@ -101,6 +157,22 @@ class GlancesClient():
|
|||||||
- Disconnected: Connection NOK
|
- Disconnected: Connection NOK
|
||||||
"""
|
"""
|
||||||
# Update the stats
|
# 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:
|
try:
|
||||||
server_stats = json.loads(self.client.getAll())
|
server_stats = json.loads(self.client.getAll())
|
||||||
server_stats['monitor'] = json.loads(self.client.getAllMonitored())
|
server_stats['monitor'] = json.loads(self.client.getAllMonitored())
|
||||||
@ -112,6 +184,23 @@ class GlancesClient():
|
|||||||
self.stats.update(server_stats)
|
self.stats.update(server_stats)
|
||||||
return "Connected"
|
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):
|
def serve_forever(self):
|
||||||
"""
|
"""
|
||||||
Main client loop
|
Main client loop
|
||||||
@ -122,9 +211,12 @@ class GlancesClient():
|
|||||||
|
|
||||||
# Update the screen
|
# Update the screen
|
||||||
self.screen.update(self.stats, cs_status=cs_status)
|
self.screen.update(self.stats, cs_status=cs_status)
|
||||||
|
# print self.stats
|
||||||
|
# print self.stats.getAll()
|
||||||
|
|
||||||
def end(self):
|
def end(self):
|
||||||
"""
|
"""
|
||||||
End of the client session
|
End of the client session
|
||||||
"""
|
"""
|
||||||
self.screen.end()
|
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()
|
plugname = os.path.basename(plug)[len(header):-3].lower()
|
||||||
self._plugins[plugname] = m.Plugin()
|
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):
|
def load_limits(self, config=None):
|
||||||
"""
|
"""
|
||||||
Load the stats limits
|
Load the stats limits
|
||||||
@ -109,7 +115,7 @@ class GlancesStats(object):
|
|||||||
# print "DEBUG: Update %s stats" % p
|
# print "DEBUG: Update %s stats" % p
|
||||||
self._plugins[p].update()
|
self._plugins[p].update()
|
||||||
else:
|
else:
|
||||||
# For client mode
|
# For Glances client mode
|
||||||
# Update plugin stats with items sent by the server
|
# Update plugin stats with items sent by the server
|
||||||
for p in input_stats:
|
for p in input_stats:
|
||||||
self._plugins[p].set_stats(input_stats[p])
|
self._plugins[p].set_stats(input_stats[p])
|
||||||
@ -118,6 +124,12 @@ class GlancesStats(object):
|
|||||||
# Update the stats
|
# Update the stats
|
||||||
self.__update__(input_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):
|
def get_plugin_list(self):
|
||||||
# Return the plugin list
|
# Return the plugin list
|
||||||
self._plugins
|
self._plugins
|
||||||
@ -202,3 +214,27 @@ class GlancesStatsClient(GlancesStats):
|
|||||||
# generate self._plugins_list["xxx"] = ...
|
# generate self._plugins_list["xxx"] = ...
|
||||||
# print "DEBUG: Init %s plugin" % plug
|
# print "DEBUG: Init %s plugin" % plug
|
||||||
self._plugins[plug] = m.Plugin()
|
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