mirror of
https://github.com/nicolargo/glances.git
synced 2024-12-23 09:11:49 +03:00
Init plugins structure
This commit is contained in:
parent
36e91f1686
commit
8da175d5fa
@ -9,17 +9,19 @@ __init__.py Global module init
|
||||
__main__.py Entry point for module
|
||||
core/
|
||||
glances_core.py Main script to rule them up...
|
||||
glances_globals.py Share variables uppon modules
|
||||
glances_config.py Manage configuration file
|
||||
glances_timer.py Manage timer
|
||||
glances_stats.py Inteface to grab stats
|
||||
glances_client.py Glances client
|
||||
glances_config.py Script to manage configuration file
|
||||
glances_server.py Glances_server
|
||||
plugins/
|
||||
glances_plugins.py Main class for others plugins
|
||||
glances_cpu.py Grab CPU stats
|
||||
glances_load.py Grab LOAD stats
|
||||
glances_mem.py Grab MEM (both RAM and SWAP) stats
|
||||
glances_plugins.py "Father class" for others plugins
|
||||
glances_cpu.py Manage CPU stats
|
||||
glances_load.py Manage LOAD stats
|
||||
glances_mem.py Manage MEM (both RAM and SWAP) stats
|
||||
...
|
||||
outputs/
|
||||
glances_api.py The API interface
|
||||
glances_curse.py The Curse (console) interface
|
||||
glances_csv.py The CSV interface
|
||||
glances_html.py The HTML interface
|
||||
|
@ -21,5 +21,41 @@
|
||||
from .core.glances_core import GlancesCore
|
||||
|
||||
def main(argv=None):
|
||||
glances_instance = GlancesCore()
|
||||
glances_instance.start()
|
||||
# Create the Glances core instance
|
||||
core = GlancesCore()
|
||||
|
||||
# Glances can be ran in standalone, client or server mode
|
||||
if (core.is_standalone()):
|
||||
# !!!
|
||||
print "Standalone mode"
|
||||
elif (core.is_client()):
|
||||
# !!!
|
||||
print "Client mode"
|
||||
elif (core.is_server()):
|
||||
# Import the Glances server module
|
||||
from .core.glances_server import GlancesServer
|
||||
|
||||
# Init the server
|
||||
server = GlancesServer(bind_address=core.bind_ip,
|
||||
bind_port=int(core.server_port),
|
||||
cached_time=core.cached_time)
|
||||
print(_("Glances server is running on") + " %s:%s" % (core.bind_ip, core.server_port))
|
||||
|
||||
# Set the server login/password (if -P/--password tag)
|
||||
if (core.password != ""):
|
||||
server.add_user(core.username, core.password)
|
||||
|
||||
# Init stats
|
||||
# !!! Uncomment
|
||||
# stats = GlancesStatsServer()
|
||||
# stats.update({})
|
||||
|
||||
# Shutdown the server
|
||||
# !!! How to close the server with CTRL-C
|
||||
# !!! Call core.end() with parameters ?
|
||||
server.server_close()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
143
glances/core/glances_config.py
Normal file
143
glances/core/glances_config.py
Normal file
@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Glances - An eye on your system
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
__appname__ = 'glances'
|
||||
|
||||
from ..core.glances_globals import *
|
||||
|
||||
# Import system libs
|
||||
import os
|
||||
try:
|
||||
# Python 2
|
||||
from ConfigParser import RawConfigParser
|
||||
from ConfigParser import NoOptionError
|
||||
except ImportError:
|
||||
# Python 3
|
||||
from configparser import RawConfigParser
|
||||
from configparser import NoOptionError
|
||||
|
||||
|
||||
class Config:
|
||||
"""
|
||||
This class is used to access/read config file, if it exists
|
||||
|
||||
:param location: the custom path to search for config file
|
||||
:type location: str or None
|
||||
"""
|
||||
|
||||
def __init__(self, location=None):
|
||||
self.location = location
|
||||
self.filename = 'glances.conf'
|
||||
|
||||
self.parser = RawConfigParser()
|
||||
self.load()
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
Load a config file from the list of paths, if it exists
|
||||
"""
|
||||
for path in self.get_paths_list():
|
||||
if (os.path.isfile(path) and os.path.getsize(path) > 0):
|
||||
try:
|
||||
if (sys.version_info >= (3, 2)):
|
||||
self.parser.read(path, encoding='utf-8')
|
||||
else:
|
||||
self.parser.read(path)
|
||||
except UnicodeDecodeError as e:
|
||||
print(_("Error decoding config file '%s': %s") % (path, e))
|
||||
sys.exit(1)
|
||||
break
|
||||
|
||||
def get_paths_list(self):
|
||||
"""
|
||||
Get a list of config file paths, taking into account of the OS,
|
||||
priority and location.
|
||||
|
||||
* running from source: /path/to/glances/conf
|
||||
* Linux: ~/.config/glances, /etc/glances
|
||||
* BSD: ~/.config/glances, /usr/local/etc/glances
|
||||
* Mac: ~/Library/Application Support/glances, /usr/local/etc/glances
|
||||
* Windows: %APPDATA%\glances
|
||||
|
||||
The config file will be searched in the following order of priority:
|
||||
* /path/to/file (via -C flag)
|
||||
* /path/to/glances/conf
|
||||
* user's home directory (per-user settings)
|
||||
* {/usr/local,}/etc directory (system-wide settings)
|
||||
"""
|
||||
paths = []
|
||||
conf_path = os.path.realpath(os.path.join(work_path, '..', 'conf'))
|
||||
|
||||
if self.location is not None:
|
||||
paths.append(self.location)
|
||||
|
||||
if os.path.exists(conf_path):
|
||||
paths.append(os.path.join(conf_path, self.filename))
|
||||
|
||||
if is_Linux or is_BSD:
|
||||
paths.append(os.path.join(
|
||||
os.environ.get('XDG_CONFIG_HOME') or os.path.expanduser('~/.config'),
|
||||
__appname__, self.filename))
|
||||
elif is_Mac:
|
||||
paths.append(os.path.join(
|
||||
os.path.expanduser('~/Library/Application Support/'),
|
||||
__appname__, self.filename))
|
||||
elif is_Windows:
|
||||
paths.append(os.path.join(
|
||||
os.environ.get('APPDATA'), __appname__, self.filename))
|
||||
|
||||
if is_Linux:
|
||||
paths.append(os.path.join('/etc', __appname__, self.filename))
|
||||
elif is_BSD:
|
||||
paths.append(os.path.join(
|
||||
sys.prefix, 'etc', __appname__, self.filename))
|
||||
elif is_Mac:
|
||||
paths.append(os.path.join(
|
||||
sys_prefix, 'etc', __appname__, self.filename))
|
||||
|
||||
return paths
|
||||
|
||||
def has_section(self, section):
|
||||
"""
|
||||
Return info about the existence of a section
|
||||
"""
|
||||
return self.parser.has_section(section)
|
||||
|
||||
def get_option(self, section, option):
|
||||
"""
|
||||
Get the float value of an option, if it exists
|
||||
"""
|
||||
try:
|
||||
value = self.parser.getfloat(section, option)
|
||||
except NoOptionError:
|
||||
return
|
||||
else:
|
||||
return value
|
||||
|
||||
def get_raw_option(self, section, option):
|
||||
"""
|
||||
Get the raw value of an option, if it exists
|
||||
"""
|
||||
try:
|
||||
value = self.parser.get(section, option)
|
||||
except NoOptionError:
|
||||
return
|
||||
else:
|
||||
return value
|
@ -18,42 +18,26 @@
|
||||
# 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 informations
|
||||
__appname__ = 'glances'
|
||||
__version__ = "2.0_Alpha"
|
||||
__author__ = "Nicolas Hennion <nicolas@nicolargo.com>"
|
||||
__license__ = "LGPL"
|
||||
|
||||
# Import system libs
|
||||
import sys
|
||||
import os
|
||||
import gettext
|
||||
import locale
|
||||
import signal
|
||||
import argparse
|
||||
|
||||
# path definitions
|
||||
work_path = os.path.realpath(os.path.dirname(__file__))
|
||||
appname_path = os.path.split(sys.argv[0])[0]
|
||||
sys_prefix = os.path.realpath(os.path.dirname(appname_path))
|
||||
|
||||
# i18n
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
gettext_domain = __appname__
|
||||
# get locale directory
|
||||
i18n_path = os.path.realpath(os.path.join(work_path, '..', 'i18n'))
|
||||
sys_i18n_path = os.path.join(sys_prefix, 'share', 'locale')
|
||||
if os.path.exists(i18n_path):
|
||||
locale_dir = i18n_path
|
||||
elif os.path.exists(sys_i18n_path):
|
||||
locale_dir = sys_i18n_path
|
||||
else:
|
||||
locale_dir = None
|
||||
gettext.install(gettext_domain, locale_dir)
|
||||
|
||||
# Operating system flag
|
||||
# Note: Somes libs depends of OS
|
||||
is_BSD = sys.platform.find('bsd') != -1
|
||||
is_Linux = sys.platform.startswith('linux')
|
||||
is_Mac = sys.platform.startswith('darwin')
|
||||
is_Windows = sys.platform.startswith('win')
|
||||
# Import Glances libs
|
||||
# !!! Todo: rename class
|
||||
# GlancesExemple
|
||||
from ..core.glances_globals import *
|
||||
from ..core.glances_config import Config
|
||||
from ..core.glances_limits import glancesLimits
|
||||
from ..core.glances_monitor_list import monitorList
|
||||
from ..core.glances_stats import GlancesStats, GlancesStatsServer
|
||||
|
||||
# Import PSUtil
|
||||
# !!! Is it mandatory for client ?
|
||||
@ -125,6 +109,7 @@ class GlancesCore(object):
|
||||
# Default stats' refresh time is 3 seconds
|
||||
refresh_time = 3
|
||||
# Set the default cache lifetime to 1 second (only for server)
|
||||
# !!! Todo: configuration from the command line
|
||||
cached_time = 1
|
||||
# Default network bitrate is display in bit per second
|
||||
network_bytepersec_tag = False
|
||||
@ -160,16 +145,74 @@ class GlancesCore(object):
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.parser = argparse.ArgumentParser(
|
||||
prog=__appname__,
|
||||
description='Glances, an eye on your system.')
|
||||
# Init and manage command line arguments
|
||||
self.init_arg()
|
||||
self.parse_arg()
|
||||
|
||||
# Read the configuration file
|
||||
if (self.conf_file_tag):
|
||||
self.config = Config(self.conf_file)
|
||||
else:
|
||||
self.config = Config()
|
||||
|
||||
# Init the limits
|
||||
self.limits = glancesLimits(self.config)
|
||||
|
||||
# Init the monitoring list
|
||||
self.monitors = monitorList(self.config)
|
||||
|
||||
# Init stats
|
||||
stats = GlancesStatsServer()
|
||||
|
||||
# Catch the CTRL-C signal
|
||||
signal.signal(signal.SIGINT, self.__signal_handler)
|
||||
|
||||
|
||||
def __signal_handler(self, signal, frame):
|
||||
self.end()
|
||||
|
||||
|
||||
def end(self):
|
||||
"""
|
||||
Stop the Glances core and exit
|
||||
"""
|
||||
|
||||
if (self.is_standalone()):
|
||||
# Stop the classical CLI loop
|
||||
# !!! Uncomment
|
||||
# screen.end()
|
||||
pass
|
||||
elif (self.is_client()):
|
||||
# Stop the client loop
|
||||
#~ client.client_quit()
|
||||
pass
|
||||
elif (self.is_server()):
|
||||
# Stop the server loop
|
||||
# !!! Uncomment
|
||||
# server.server_close()
|
||||
pass
|
||||
|
||||
# !!! Uncomment
|
||||
# if (self.csv_tag):
|
||||
# csvoutput.exit()
|
||||
|
||||
# !! Todo for htmloutput too
|
||||
# The exit should generate a new HTML page
|
||||
# to inform the user that data are not refreshed anymore
|
||||
|
||||
# The end...
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def init_arg(self):
|
||||
"""
|
||||
Init all the command line arguments
|
||||
"""
|
||||
|
||||
self.parser = argparse.ArgumentParser(
|
||||
prog=__appname__,
|
||||
description='Glances, an eye on your system.')
|
||||
|
||||
# Version
|
||||
self.parser.add_argument('-v', '--version',
|
||||
action='version',
|
||||
@ -250,12 +293,11 @@ class GlancesCore(object):
|
||||
choices=self.output_list)
|
||||
# Define output type flag to False (default is no output)
|
||||
for o in self.output_list:
|
||||
setattr(self, o+"_tag", False)
|
||||
setattr(self, o + "_tag", False)
|
||||
# Output file/folder
|
||||
self.parser.add_argument('-f', '--file',
|
||||
help=_('set the html output folder or csv file'))
|
||||
|
||||
|
||||
def parse_arg(self):
|
||||
"""
|
||||
Parse command line argument
|
||||
@ -264,6 +306,7 @@ class GlancesCore(object):
|
||||
args = self.parser.parse_args()
|
||||
|
||||
# Change global variables regarding to user args
|
||||
# !!! To be refactor to use directly the args list in the code
|
||||
if (args.time is not None): self.refresh_time = args.time
|
||||
self.network_bytepersec_tag = args.byte
|
||||
self.diskio_tag = args.disable_diskio
|
||||
@ -300,7 +343,7 @@ class GlancesCore(object):
|
||||
output_folder = args.file
|
||||
|
||||
# !!! Debug
|
||||
print args
|
||||
# print args
|
||||
|
||||
def get_password(self, description='', confirm=False):
|
||||
"""
|
||||
@ -323,10 +366,21 @@ class GlancesCore(object):
|
||||
sys.stdout.write(_("[Warning] Passwords did not match, please try again...\n"))
|
||||
return self.get_password(description=description, confirm=confirm)
|
||||
|
||||
def start(self):
|
||||
def is_standalone(self):
|
||||
"""
|
||||
Start the instance
|
||||
It is the 'real' main function for Glances
|
||||
Return True if Glances is running in standalone mode
|
||||
"""
|
||||
return not self.client_tag and not self.server_tag
|
||||
|
||||
def is_client(self):
|
||||
"""
|
||||
Return True if Glances is running in client mode
|
||||
"""
|
||||
return self.client_tag and not self.server_tag
|
||||
|
||||
def is_server(self):
|
||||
"""
|
||||
Return True if Glances is running in sserver mode
|
||||
"""
|
||||
return not self.client_tag and self.server_tag
|
||||
|
||||
self.parse_arg()
|
||||
|
51
glances/core/glances_globals.py
Normal file
51
glances/core/glances_globals.py
Normal file
@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Glances - An eye on your system
|
||||
#
|
||||
# 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 system libs
|
||||
import sys
|
||||
import os
|
||||
import gettext
|
||||
import locale
|
||||
|
||||
# Path definitions
|
||||
work_path = os.path.realpath(os.path.dirname(__file__))
|
||||
appname_path = os.path.split(sys.argv[0])[0]
|
||||
sys_prefix = os.path.realpath(os.path.dirname(appname_path))
|
||||
|
||||
# Operating system flag
|
||||
# Note: Somes libs depends of OS
|
||||
is_BSD = sys.platform.find('bsd') != -1
|
||||
is_Linux = sys.platform.startswith('linux')
|
||||
is_Mac = sys.platform.startswith('darwin')
|
||||
is_Windows = sys.platform.startswith('win')
|
||||
|
||||
# i18n
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
gettext_domain = 'glances'
|
||||
# get locale directory
|
||||
i18n_path = os.path.realpath(os.path.join(work_path, '..', 'i18n'))
|
||||
sys_i18n_path = os.path.join(sys_prefix, 'share', 'locale')
|
||||
if os.path.exists(i18n_path):
|
||||
locale_dir = i18n_path
|
||||
elif os.path.exists(sys_i18n_path):
|
||||
locale_dir = sys_i18n_path
|
||||
else:
|
||||
locale_dir = None
|
||||
gettext.install(gettext_domain, locale_dir)
|
270
glances/core/glances_limits.py
Normal file
270
glances/core/glances_limits.py
Normal file
@ -0,0 +1,270 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Glances - An eye on your system
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
class glancesLimits:
|
||||
"""
|
||||
Manage limits for each stats. A limit can be:
|
||||
* a set of careful, warning and critical values
|
||||
* a filter (for example: hide some network interfaces)
|
||||
|
||||
The limit list is stored in an hash table:
|
||||
__limits_list[STAT] = [CAREFUL, WARNING, CRITICAL]
|
||||
|
||||
STD is for defaults limits (CPU/MEM/SWAP/FS)
|
||||
CPU_IOWAIT limits (iowait in %)
|
||||
CPU_STEAL limits (steal in %)
|
||||
LOAD is for LOAD limits (5 min/15 min)
|
||||
TEMP is for sensors limits (temperature in °C)
|
||||
HDDTEMP is for hddtemp limits (temperature in °C)
|
||||
FS is for partitions space limits
|
||||
IODISK_HIDE is a list of disk (name) to hide
|
||||
NETWORK_HIDE is a list of network interface (name) to hide
|
||||
"""
|
||||
__limits_list = {'STD': [50, 70, 90],
|
||||
'CPU_USER': [50, 70, 90],
|
||||
'CPU_SYSTEM': [50, 70, 90],
|
||||
'CPU_IOWAIT': [40, 60, 80],
|
||||
'CPU_STEAL': [10, 15, 20],
|
||||
'LOAD': [0.7, 1.0, 5.0],
|
||||
'MEM': [50, 70, 90],
|
||||
'SWAP': [50, 70, 90],
|
||||
'TEMP': [60, 70, 80],
|
||||
'HDDTEMP': [45, 52, 60],
|
||||
'FS': [50, 70, 90],
|
||||
'PROCESS_CPU': [50, 70, 90],
|
||||
'PROCESS_MEM': [50, 70, 90],
|
||||
'IODISK_HIDE': [],
|
||||
'NETWORK_HIDE': []}
|
||||
|
||||
def __init__(self, config):
|
||||
"""
|
||||
Init the limits with: default values and configuration file
|
||||
"""
|
||||
|
||||
self.config = config
|
||||
|
||||
# Test if the configuration file has a limits section
|
||||
if config.has_section('global'):
|
||||
# Read STD limits
|
||||
self.__setLimits('STD', 'global', 'careful')
|
||||
self.__setLimits('STD', 'global', 'warning')
|
||||
self.__setLimits('STD', 'global', 'critical')
|
||||
if config.has_section('cpu'):
|
||||
# Read CPU limits
|
||||
self.__setLimits('CPU_USER', 'cpu', 'user_careful')
|
||||
self.__setLimits('CPU_USER', 'cpu', 'user_warning')
|
||||
self.__setLimits('CPU_USER', 'cpu', 'user_critical')
|
||||
self.__setLimits('CPU_SYSTEM', 'cpu', 'system_careful')
|
||||
self.__setLimits('CPU_SYSTEM', 'cpu', 'system_warning')
|
||||
self.__setLimits('CPU_SYSTEM', 'cpu', 'system_critical')
|
||||
self.__setLimits('CPU_IOWAIT', 'cpu', 'iowait_careful')
|
||||
self.__setLimits('CPU_IOWAIT', 'cpu', 'iowait_warning')
|
||||
self.__setLimits('CPU_IOWAIT', 'cpu', 'iowait_critical')
|
||||
self.__setLimits('CPU_STEAL', 'cpu', 'steal_careful')
|
||||
self.__setLimits('CPU_STEAL', 'cpu', 'steal_warning')
|
||||
self.__setLimits('CPU_STEAL', 'cpu', 'steal_critical')
|
||||
if config.has_section('load'):
|
||||
# Read LOAD limits
|
||||
self.__setLimits('LOAD', 'load', 'careful')
|
||||
self.__setLimits('LOAD', 'load', 'warning')
|
||||
self.__setLimits('LOAD', 'load', 'critical')
|
||||
if config.has_section('memory'):
|
||||
# Read MEM limits
|
||||
self.__setLimits('MEM', 'memory', 'careful')
|
||||
self.__setLimits('MEM', 'memory', 'warning')
|
||||
self.__setLimits('MEM', 'memory', 'critical')
|
||||
if config.has_section('swap'):
|
||||
# Read MEM limits
|
||||
self.__setLimits('SWAP', 'swap', 'careful')
|
||||
self.__setLimits('SWAP', 'swap', 'warning')
|
||||
self.__setLimits('SWAP', 'swap', 'critical')
|
||||
if config.has_section('temperature'):
|
||||
# Read TEMP limits
|
||||
self.__setLimits('TEMP', 'temperature', 'careful')
|
||||
self.__setLimits('TEMP', 'temperature', 'warning')
|
||||
self.__setLimits('TEMP', 'temperature', 'critical')
|
||||
if config.has_section('hddtemperature'):
|
||||
# Read HDDTEMP limits
|
||||
self.__setLimits('HDDTEMP', 'hddtemperature', 'careful')
|
||||
self.__setLimits('HDDTEMP', 'hddtemperature', 'warning')
|
||||
self.__setLimits('HDDTEMP', 'hddtemperature', 'critical')
|
||||
if config.has_section('filesystem'):
|
||||
# Read FS limits
|
||||
self.__setLimits('FS', 'filesystem', 'careful')
|
||||
self.__setLimits('FS', 'filesystem', 'warning')
|
||||
self.__setLimits('FS', 'filesystem', 'critical')
|
||||
if config.has_section('process'):
|
||||
# Process limits
|
||||
self.__setLimits('PROCESS_CPU', 'process', 'cpu_careful')
|
||||
self.__setLimits('PROCESS_CPU', 'process', 'cpu_warning')
|
||||
self.__setLimits('PROCESS_CPU', 'process', 'cpu_critical')
|
||||
self.__setLimits('PROCESS_MEM', 'process', 'mem_careful')
|
||||
self.__setLimits('PROCESS_MEM', 'process', 'mem_warning')
|
||||
self.__setLimits('PROCESS_MEM', 'process', 'mem_critical')
|
||||
if config.has_section('iodisk'):
|
||||
# Hidden disks' list
|
||||
self.__setHidden('IODISK_HIDE', 'iodisk', 'hide')
|
||||
if config.has_section('network'):
|
||||
# Network interfaces' list
|
||||
self.__setHidden('NETWORK_HIDE', 'network', 'hide')
|
||||
|
||||
def __setHidden(self, stat, section, alert='hide'):
|
||||
"""
|
||||
stat: 'IODISK', 'NETWORK'
|
||||
section: 'iodisk', 'network'
|
||||
alert: 'hide'
|
||||
"""
|
||||
value = self.config.get_raw_option(section, alert)
|
||||
|
||||
# print("%s / %s = %s -> %s" % (section, alert, value, stat))
|
||||
if (value is not None):
|
||||
self.__limits_list[stat] = value.split(",")
|
||||
|
||||
def __setLimits(self, stat, section, alert):
|
||||
"""
|
||||
stat: 'CPU', 'LOAD', 'MEM', 'SWAP', 'TEMP', etc.
|
||||
section: 'cpu', 'load', 'memory', 'swap', 'temperature', etc.
|
||||
alert: 'careful', 'warning', 'critical'
|
||||
"""
|
||||
value = self.config.get_option(section, alert)
|
||||
|
||||
# print("%s / %s = %s -> %s" % (section, alert, value, stat))
|
||||
if alert.endswith('careful'):
|
||||
self.__limits_list[stat][0] = value
|
||||
elif alert.endswith('warning'):
|
||||
self.__limits_list[stat][1] = value
|
||||
elif alert.endswith('critical'):
|
||||
self.__limits_list[stat][2] = value
|
||||
|
||||
def setAll(self, newlimits):
|
||||
self.__limits_list = newlimits
|
||||
return True
|
||||
|
||||
def getAll(self):
|
||||
return self.__limits_list
|
||||
|
||||
def getHide(self, stat):
|
||||
try:
|
||||
self.__limits_list[stat]
|
||||
except KeyError:
|
||||
return []
|
||||
else:
|
||||
return self.__limits_list[stat]
|
||||
|
||||
def getCareful(self, stat):
|
||||
return self.__limits_list[stat][0]
|
||||
|
||||
def getWarning(self, stat):
|
||||
return self.__limits_list[stat][1]
|
||||
|
||||
def getCritical(self, stat):
|
||||
return self.__limits_list[stat][2]
|
||||
|
||||
# TO BE DELETED AFTER THE HTML output refactoring
|
||||
def getSTDCareful(self):
|
||||
return self.getCareful('STD')
|
||||
|
||||
def getSTDWarning(self):
|
||||
return self.getWarning('STD')
|
||||
|
||||
def getSTDCritical(self):
|
||||
return self.getCritical('STD')
|
||||
# /TO BE DELETED AFTER THE HTML output refactoring
|
||||
|
||||
def getCPUCareful(self, stat):
|
||||
return self.getCareful('CPU_' + stat.upper())
|
||||
|
||||
def getCPUWarning(self, stat):
|
||||
return self.getWarning('CPU_' + stat.upper())
|
||||
|
||||
def getCPUCritical(self, stat):
|
||||
return self.getCritical('CPU_' + stat.upper())
|
||||
|
||||
def getLOADCareful(self, core=1):
|
||||
return self.getCareful('LOAD') * core
|
||||
|
||||
def getLOADWarning(self, core=1):
|
||||
return self.getWarning('LOAD') * core
|
||||
|
||||
def getLOADCritical(self, core=1):
|
||||
return self.getCritical('LOAD') * core
|
||||
|
||||
def getMEMCareful(self):
|
||||
return self.getCareful('MEM')
|
||||
|
||||
def getMEMWarning(self):
|
||||
return self.getWarning('MEM')
|
||||
|
||||
def getMEMCritical(self):
|
||||
return self.getCritical('MEM')
|
||||
|
||||
def getSWAPCareful(self):
|
||||
return self.getCareful('SWAP')
|
||||
|
||||
def getSWAPWarning(self):
|
||||
return self.getWarning('SWAP')
|
||||
|
||||
def getSWAPCritical(self):
|
||||
return self.getCritical('SWAP')
|
||||
|
||||
def getTEMPCareful(self):
|
||||
return self.getCareful('TEMP')
|
||||
|
||||
def getTEMPWarning(self):
|
||||
return self.getWarning('TEMP')
|
||||
|
||||
def getTEMPCritical(self):
|
||||
return self.getCritical('TEMP')
|
||||
|
||||
def getHDDTEMPCareful(self):
|
||||
return self.getCareful('HDDTEMP')
|
||||
|
||||
def getHDDTEMPWarning(self):
|
||||
return self.getWarning('HDDTEMP')
|
||||
|
||||
def getHDDTEMPCritical(self):
|
||||
return self.getCritical('HDDTEMP')
|
||||
|
||||
def getFSCareful(self):
|
||||
return self.getCareful('FS')
|
||||
|
||||
def getFSWarning(self):
|
||||
return self.getWarning('FS')
|
||||
|
||||
def getFSCritical(self):
|
||||
return self.getCritical('FS')
|
||||
|
||||
def getProcessCareful(self, stat='', core=1):
|
||||
if stat.upper() != 'CPU':
|
||||
# Use core only for CPU
|
||||
core = 1
|
||||
return self.getCareful('PROCESS_' + stat.upper()) * core
|
||||
|
||||
def getProcessWarning(self, stat='', core=1):
|
||||
if stat.upper() != 'CPU':
|
||||
# Use core only for CPU
|
||||
core = 1
|
||||
return self.getWarning('PROCESS_' + stat.upper()) * core
|
||||
|
||||
def getProcessCritical(self, stat='', core=1):
|
||||
if stat.upper() != 'CPU':
|
||||
# Use core only for CPU
|
||||
core = 1
|
||||
return self.getCritical('PROCESS_' + stat.upper()) * core
|
135
glances/core/glances_monitor_list.py
Normal file
135
glances/core/glances_monitor_list.py
Normal file
@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Glances - An eye on your system
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
class monitorList:
|
||||
"""
|
||||
This class describes the optionnal monitored processes list
|
||||
A list of 'important' processes to monitor.
|
||||
|
||||
The list (Python list) is composed of items (Python dict)
|
||||
An item is defined (Dict keys'):
|
||||
* description: Description of the processes (max 16 chars)
|
||||
* regex: regular expression of the processes to monitor
|
||||
* command: (optional) shell command for extended stat
|
||||
* countmin: (optional) minimal number of processes
|
||||
* countmax: (optional) maximum number of processes
|
||||
"""
|
||||
# Maximum number of items in the list
|
||||
__monitor_list_max_size = 10
|
||||
# The list
|
||||
__monitor_list = []
|
||||
|
||||
def __init__(self, config):
|
||||
"""
|
||||
Init the monitoring list from the configuration file
|
||||
"""
|
||||
|
||||
if config.has_section('monitor'):
|
||||
# Process monitoring list
|
||||
self.__setMonitorList('monitor', 'list')
|
||||
|
||||
def __setMonitorList(self, section, key):
|
||||
"""
|
||||
Init the monitored processes list
|
||||
The list is defined in the Glances configuration file
|
||||
"""
|
||||
for l in range(1, self.__monitor_list_max_size + 1):
|
||||
value = {}
|
||||
key = "list_" + str(l) + "_"
|
||||
try:
|
||||
description = config.get_raw_option(section, key + "description")
|
||||
regex = config.get_raw_option(section, key + "regex")
|
||||
command = config.get_raw_option(section, key + "command")
|
||||
countmin = config.get_raw_option(section, key + "countmin")
|
||||
countmax = config.get_raw_option(section, key + "countmax")
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
if description is not None and regex is not None:
|
||||
# Build the new item
|
||||
value["description"] = description
|
||||
value["regex"] = regex
|
||||
value["command"] = command
|
||||
value["countmin"] = countmin
|
||||
value["countmax"] = countmax
|
||||
# Add the item to the list
|
||||
self.__monitor_list.append(value)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__monitor_list)
|
||||
|
||||
def __repr__(self):
|
||||
return self.__monitor_list
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.__monitor_list[item]
|
||||
|
||||
def __len__(self):
|
||||
return len(self.__monitor_list)
|
||||
|
||||
def __get__(self, item, key):
|
||||
"""
|
||||
Meta function to return key value of item
|
||||
None if not defined or item > len(list)
|
||||
"""
|
||||
if item < len(self.__monitor_list):
|
||||
try:
|
||||
return self.__monitor_list[item][key]
|
||||
except Exception:
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
|
||||
def getAll(self):
|
||||
return self.__monitor_list
|
||||
|
||||
def setAll(self, newlist):
|
||||
self.__monitor_list = newlist
|
||||
|
||||
def description(self, item):
|
||||
"""
|
||||
Return the description of the item number (item)
|
||||
"""
|
||||
return self.__get__(item, "description")
|
||||
|
||||
def regex(self, item):
|
||||
"""
|
||||
Return the regular expression of the item number (item)
|
||||
"""
|
||||
return self.__get__(item, "regex")
|
||||
|
||||
def command(self, item):
|
||||
"""
|
||||
Return the stats command of the item number (item)
|
||||
"""
|
||||
return self.__get__(item, "command")
|
||||
|
||||
def countmin(self, item):
|
||||
"""
|
||||
Return the minimum number of processes of the item number (item)
|
||||
"""
|
||||
return self.__get__(item, "countmin")
|
||||
|
||||
def countmax(self, item):
|
||||
"""
|
||||
Return the maximum number of processes of the item number (item)
|
||||
"""
|
||||
return self.__get__(item, "countmax")
|
||||
|
288
glances/core/glances_server.py
Normal file
288
glances/core/glances_server.py
Normal file
@ -0,0 +1,288 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Glances - An eye on your system
|
||||
#
|
||||
# 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 system libs
|
||||
import sys
|
||||
import socket
|
||||
|
||||
from ..core.glances_timer import Timer
|
||||
|
||||
try:
|
||||
# Python 2
|
||||
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
|
||||
from SimpleXMLRPCServer import SimpleXMLRPCServer
|
||||
except ImportError:
|
||||
# Python 3
|
||||
from xmlrpc.server import SimpleXMLRPCRequestHandler
|
||||
from xmlrpc.server import SimpleXMLRPCServer
|
||||
|
||||
try:
|
||||
# Python 2
|
||||
from xmlrpclib import ServerProxy, ProtocolError
|
||||
except ImportError:
|
||||
# Python 3
|
||||
from xmlrpc.client import ServerProxy, ProtocolError
|
||||
|
||||
|
||||
class GlancesXMLRPCHandler(SimpleXMLRPCRequestHandler):
|
||||
"""
|
||||
Main XMLRPC handler
|
||||
"""
|
||||
rpc_paths = ('/RPC2', )
|
||||
|
||||
def end_headers(self):
|
||||
# Hack to add a specific header
|
||||
# Thk to: https://gist.github.com/rca/4063325
|
||||
self.send_my_headers()
|
||||
SimpleXMLRPCRequestHandler.end_headers(self)
|
||||
|
||||
def send_my_headers(self):
|
||||
# Specific header is here (solved the issue #227)
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
|
||||
def authenticate(self, headers):
|
||||
# auth = headers.get('Authorization')
|
||||
try:
|
||||
(basic, _, encoded) = headers.get('Authorization').partition(' ')
|
||||
except Exception:
|
||||
# Client did not ask for authentidaction
|
||||
# If server need it then exit
|
||||
return not self.server.isAuth
|
||||
else:
|
||||
# Client authentication
|
||||
(basic, _, encoded) = headers.get('Authorization').partition(' ')
|
||||
assert basic == 'Basic', 'Only basic authentication supported'
|
||||
# Encoded portion of the header is a string
|
||||
# Need to convert to bytestring
|
||||
encodedByteString = encoded.encode()
|
||||
# Decode Base64 byte String to a decoded Byte String
|
||||
decodedBytes = b64decode(encodedByteString)
|
||||
# Convert from byte string to a regular String
|
||||
decodedString = decodedBytes.decode()
|
||||
# Get the username and password from the string
|
||||
(username, _, password) = decodedString.partition(':')
|
||||
# Check that username and password match internal global dictionary
|
||||
return self.check_user(username, password)
|
||||
|
||||
def check_user(self, username, password):
|
||||
# Check username and password in the dictionnary
|
||||
if username in self.server.user_dict:
|
||||
if self.server.user_dict[username] == md5(password).hexdigest():
|
||||
return True
|
||||
return False
|
||||
|
||||
def parse_request(self):
|
||||
if SimpleXMLRPCRequestHandler.parse_request(self):
|
||||
# Next we authenticate
|
||||
if self.authenticate(self.headers):
|
||||
return True
|
||||
else:
|
||||
# if authentication fails, tell the client
|
||||
self.send_error(401, 'Authentication failed')
|
||||
return False
|
||||
|
||||
def log_message(self, format, *args):
|
||||
# No message displayed on the server side
|
||||
pass
|
||||
|
||||
|
||||
class GlancesXMLRPCServer(SimpleXMLRPCServer):
|
||||
"""
|
||||
Init a SimpleXMLRPCServer instance (IPv6-ready)
|
||||
"""
|
||||
|
||||
def __init__(self, bind_address, bind_port=61209,
|
||||
requestHandler=GlancesXMLRPCHandler):
|
||||
|
||||
try:
|
||||
self.address_family = socket.getaddrinfo(bind_address, bind_port)[0][0]
|
||||
except socket.error as e:
|
||||
print(_("Couldn't open socket: %s") % e)
|
||||
sys.exit(1)
|
||||
|
||||
SimpleXMLRPCServer.__init__(self, (bind_address, bind_port),
|
||||
requestHandler)
|
||||
|
||||
|
||||
class GlancesInstance():
|
||||
"""
|
||||
All the methods of this class are published as XML RPC methods
|
||||
"""
|
||||
|
||||
def __init__(self, cached_time=1):
|
||||
# cached_time is the minimum time interval between stats updates
|
||||
# i.e. XML/RPC calls will not retrieve updated info until the time
|
||||
# since last update is passed (will retrieve old cached info instead)
|
||||
self.timer = Timer(0)
|
||||
self.cached_time = cached_time
|
||||
|
||||
def __update__(self):
|
||||
# Never update more than 1 time per cached_time
|
||||
if self.timer.finished():
|
||||
stats.update()
|
||||
self.timer = Timer(self.cached_time)
|
||||
|
||||
def init(self):
|
||||
# Return the Glances version
|
||||
return __version__
|
||||
|
||||
def getAll(self):
|
||||
# Update and return all the stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getAll())
|
||||
|
||||
def getAllLimits(self):
|
||||
# Return all the limits
|
||||
return json.dumps(limits.getAll())
|
||||
|
||||
def getAllMonitored(self):
|
||||
# Return the processes monitored list
|
||||
return json.dumps(monitors.getAll())
|
||||
|
||||
def getSystem(self):
|
||||
# Return operating system info
|
||||
# No need to update...
|
||||
#~ self.__update__()
|
||||
return json.dumps(stats.getSystem())
|
||||
|
||||
def getCore(self):
|
||||
# Update and return number of Core
|
||||
self.__update__()
|
||||
return json.dumps(stats.getCore())
|
||||
|
||||
def getCpu(self):
|
||||
# Update and return CPU stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getCpu())
|
||||
|
||||
def getLoad(self):
|
||||
# Update and return LOAD stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getLoad())
|
||||
|
||||
def getMem(self):
|
||||
# Update and return MEM stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getMem())
|
||||
|
||||
def getMemSwap(self):
|
||||
# Update and return MEMSWAP stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getMemSwap())
|
||||
|
||||
def getSensors(self):
|
||||
# Update and return SENSORS stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getSensors())
|
||||
|
||||
def getHDDTemp(self):
|
||||
# Update and return HDDTEMP stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getHDDTemp())
|
||||
|
||||
def getNetwork(self):
|
||||
# Update and return NET stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getNetwork())
|
||||
|
||||
def getDiskIO(self):
|
||||
# Update and return DISK IO stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getDiskIO())
|
||||
|
||||
def getFs(self):
|
||||
# Update and return FS stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getFs())
|
||||
|
||||
def getProcessCount(self):
|
||||
# Update and return ProcessCount stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getProcessCount())
|
||||
|
||||
def getProcessList(self):
|
||||
# Update and return ProcessList stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getProcessList())
|
||||
|
||||
def getBatPercent(self):
|
||||
# Update and return total batteries percent stats
|
||||
self.__update__()
|
||||
return json.dumps(stats.getBatPercent())
|
||||
|
||||
def getNow(self):
|
||||
# Update and return current date/hour
|
||||
self.__update__()
|
||||
return json.dumps(stats.getNow().strftime(_("%Y-%m-%d %H:%M:%S")))
|
||||
|
||||
def getUptime(self):
|
||||
# Update and return system uptime
|
||||
self.__update__()
|
||||
return json.dumps(stats.getUptime().strftime(_("%Y-%m-%d %H:%M:%S")))
|
||||
|
||||
def __getTimeSinceLastUpdate(self, IOType):
|
||||
assert(IOType in ['net', 'disk', 'process_disk'])
|
||||
return getTimeSinceLastUpdate(IOType)
|
||||
|
||||
def getNetTimeSinceLastUpdate(self):
|
||||
return getTimeSinceLastUpdate('net')
|
||||
|
||||
def getDiskTimeSinceLastUpdate(self):
|
||||
return getTimeSinceLastUpdate('net')
|
||||
|
||||
def getProcessDiskTimeSinceLastUpdate(self):
|
||||
return getTimeSinceLastUpdate('process_disk')
|
||||
|
||||
|
||||
class GlancesServer():
|
||||
"""
|
||||
This class creates and manages the TCP client
|
||||
"""
|
||||
|
||||
def __init__(self, bind_address="0.0.0.0", bind_port=61209,
|
||||
requestHandler=GlancesXMLRPCHandler, cached_time=1):
|
||||
# Init the XML RPC server
|
||||
try:
|
||||
self.server = GlancesXMLRPCServer(bind_address, bind_port, requestHandler)
|
||||
except Exception, err:
|
||||
print(_("Error: Can not start Glances server (%s)") % err)
|
||||
sys.exit(2)
|
||||
|
||||
# The users dict
|
||||
# username / MD5 password couple
|
||||
# By default, no auth is needed
|
||||
self.server.user_dict = {}
|
||||
self.server.isAuth = False
|
||||
# Register functions
|
||||
self.server.register_introspection_functions()
|
||||
self.server.register_instance(GlancesInstance(cached_time))
|
||||
|
||||
def add_user(self, username, password):
|
||||
"""
|
||||
Add an user to the dictionnary
|
||||
"""
|
||||
self.server.user_dict[username] = md5(password).hexdigest()
|
||||
self.server.isAuth = True
|
||||
|
||||
def serve_forever(self):
|
||||
self.server.serve_forever()
|
||||
|
||||
def server_close(self):
|
||||
self.server.server_close()
|
44
glances/core/glances_timer.py
Normal file
44
glances/core/glances_timer.py
Normal file
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Glances - An eye on your system
|
||||
#
|
||||
# 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 time
|
||||
|
||||
class Timer:
|
||||
"""
|
||||
The timer class
|
||||
A simple chrono
|
||||
"""
|
||||
|
||||
def __init__(self, duration):
|
||||
self.duration = duration
|
||||
self.start()
|
||||
|
||||
def start(self):
|
||||
self.target = time.time() + self.duration
|
||||
|
||||
def reset(self):
|
||||
self.start()
|
||||
|
||||
def set(self, duration):
|
||||
self.duration = duration
|
||||
|
||||
def finished(self):
|
||||
return time.time() > self.target
|
||||
|
@ -18,9 +18,10 @@
|
||||
# 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/>.
|
||||
|
||||
from ..plugins.glances_plugin import GlancesPlugin
|
||||
# from ..plugins.glances_plugin import GlancesPlugin
|
||||
from glances_plugin import GlancesPlugin
|
||||
|
||||
class CpuPlugin(GlancesPlugin):
|
||||
class Plugin(GlancesPlugin):
|
||||
"""
|
||||
Glances' Cpu Plugin
|
||||
|
||||
|
43
glances/plugins/glances_host.py
Normal file
43
glances/plugins/glances_host.py
Normal file
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Glances - An eye on your system
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
# from ..plugins.glances_plugin import GlancesPlugin
|
||||
from glances_plugin import GlancesPlugin
|
||||
|
||||
class Plugin(GlancesPlugin):
|
||||
"""
|
||||
Glances' Host Plugin
|
||||
|
||||
stats is a ?
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
GlancesPlugin.__init__(self)
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
# !!! Example
|
||||
self.stats = { 'os': 'linux' }
|
||||
|
||||
def __str__(self):
|
||||
ret = "Host\n"
|
||||
for k in self.stats:
|
||||
ret += "{0} {1}\n".format(k, self.stats[k])
|
||||
return ret
|
Loading…
Reference in New Issue
Block a user