summaryrefslogtreecommitdiffstats
path: root/glances/glances.py
diff options
context:
space:
mode:
Diffstat (limited to 'glances/glances.py')
-rwxr-xr-xglances/glances.py2066
1 files changed, 2066 insertions, 0 deletions
diff --git a/glances/glances.py b/glances/glances.py
new file mode 100755
index 00000000..4d005c03
--- /dev/null
+++ b/glances/glances.py
@@ -0,0 +1,2066 @@
+#!/usr/bin/env python
+#
+# Glances is a simple textual monitoring tool
+#
+# Pre-requisites: Python 2.6+ and PsUtil 0.4.0+ (for full functions)
+#
+# Copyright (C) Nicolargo 2012 <nicolas@nicolargo.com>
+#
+# 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 __future__ import generators
+
+__appname__ = 'glances'
+__version__ = "1.4"
+__author__ = "Nicolas Hennion <nicolas@nicolargo.com>"
+__licence__ = "LGPL"
+
+# Libraries
+#==========
+
+import os
+import sys
+import platform
+import getopt
+import signal
+import time
+from datetime import datetime, timedelta
+import gettext
+
+# International
+#==============
+
+gettext.install(__appname__)
+
+# Test methods
+#=============
+
+try:
+ import curses
+ import curses.panel
+except ImportError:
+ print _('Curses module not found. Glances cannot start.')
+ print _('Glances requires at least Python 2.6 or higher.')
+ print
+ sys.exit(1)
+
+try:
+ import psutil
+except ImportError:
+ print _('PsUtil module not found. Glances cannot start.')
+ print
+ print _('On Ubuntu 12.04 or higher:')
+ print _('$ sudo apt-get install python-psutil')
+ print
+ print _('To install PsUtil using pip (as root):')
+ print _('# pip install psutil')
+ print
+ sys.exit(1)
+
+try:
+ # get_cpu_percent method only available with PsUtil 0.2.0+
+ psutil.Process(os.getpid()).get_cpu_percent(interval=0)
+except Exception:
+ psutil_get_cpu_percent_tag = False
+else:
+ psutil_get_cpu_percent_tag = True
+
+try:
+ # (phy|virt)mem_usage methods only available with PsUtil 0.3.0+
+ psutil.phymem_usage()
+ psutil.virtmem_usage()
+except Exception:
+ psutil_mem_usage_tag = False
+else:
+ psutil_mem_usage_tag = True
+
+try:
+ # disk_(partitions|usage) methods only available with PsUtil 0.3.0+
+ psutil.disk_partitions()
+ psutil.disk_usage('/')
+except Exception:
+ psutil_fs_usage_tag = False
+else:
+ psutil_fs_usage_tag = True
+
+try:
+ # disk_io_counters method only available with PsUtil 0.4.0+
+ psutil.disk_io_counters()
+except Exception:
+ psutil_disk_io_tag = False
+else:
+ psutil_disk_io_tag = True
+
+try:
+ # network_io_counters method only available with PsUtil 0.4.0+
+ psutil.network_io_counters()
+except Exception:
+ psutil_network_io_tag = False
+else:
+ psutil_network_io_tag = True
+
+try:
+ # HTML output
+ import jinja2
+except ImportError:
+ jinja_tag = False
+else:
+ jinja_tag = True
+
+try:
+ # CSV output
+ import csv
+except ImportError:
+ csvlib_tag = False
+else:
+ csvlib_tag = True
+
+
+# Classes
+#========
+
+class Timer:
+ """
+ The timer class
+ """
+
+ def __init__(self, duration):
+ self.started(duration)
+
+ def started(self, duration):
+ self.target = time.time() + duration
+
+ def finished(self):
+ return time.time() > self.target
+
+
+class glancesLimits:
+ """
+ Manage the limit OK,CAREFUL,WARNING,CRITICAL for each stats
+ """
+
+ # The limit list is stored in an hash table:
+ # limits_list[STAT] = [CAREFUL, WARNING, CRITICAL]
+ # Exemple:
+ # limits_list['STD'] = [50, 70, 90]
+
+ #_______________________________CAREFUL WARNING CRITICAL
+ __limits_list = {'STD': [50, 70, 90],
+ 'LOAD': [0.7, 1.0, 5.0]}
+
+ def __init__(self, careful=50, warning=70, critical=90):
+ self.__limits_list['STD'] = [careful, warning, critical]
+
+ def getSTDCareful(self):
+ return self.__limits_list['STD'][0]
+
+ def getSTDWarning(self):
+ return self.__limits_list['STD'][1]
+
+ def getSTDCritical(self):
+ return self.__limits_list['STD'][2]
+
+ def getLOADCareful(self, core=1):
+ return self.__limits_list['LOAD'][0] * core
+
+ def getLOADWarning(self, core=1):
+ return self.__limits_list['LOAD'][1] * core
+
+ def getLOADCritical(self, core=1):
+ return self.__limits_list['LOAD'][2] * core
+
+
+class glancesLogs:
+ """
+ The main class to manage logs inside the Glances software
+ Logs is a list of list:
+ [["begin", "end", "WARNING|CRITICAL", "CPU|LOAD|MEM",
+ MAX, AVG, MIN, SUM, COUNT],...]
+ """
+
+ def __init__(self):
+ """
+ Init the logs classe
+ """
+ # Maximum size of the logs list
+ self.logs_max = 10
+
+ # Init the logs list
+ self.logs_list = []
+
+ def get(self):
+ """
+ Return the logs list (RAW)
+ """
+ return self.logs_list
+
+ def len(self):
+ """
+ Return the number of item in the log list
+ """
+ return self.logs_list.__len__()
+
+ def __itemexist__(self, item_type):
+ """
+ An item exist in the list if:
+ * end is < 0
+ * item_type is matching
+ """
+ for i in xrange(self.len()):
+ if (self.logs_list[i][1] < 0 and
+ self.logs_list[i][3] == item_type):
+ return i
+ return -1
+
+ def add(self, item_state, item_type, item_value):
+ """
+ item_state = "OK|CAREFUL|WARNING|CRITICAL"
+ item_type = "CPU|LOAD|MEM"
+ item_value = value
+ Item is defined by:
+ ["begin", "end", "WARNING|CRITICAL", "CPU|LOAD|MEM",
+ MAX, AVG, MIN, SUM, COUNT]
+ If item is a 'new one':
+ Add the new item at the beginning of the logs list
+ Else:
+ Update the existing item
+ """
+ item_index = self.__itemexist__(item_type)
+ if item_index < 0:
+ # Item did not exist, add if WARNING or CRITICAL
+ if (item_state == "WARNING" or
+ item_state == "CRITICAL"):
+ # Time is stored in Epoch format
+ # Epoch -> DMYHMS = datetime.fromtimestamp(epoch)
+ item = []
+ item.append(time.mktime(datetime.now().timetuple()))
+ item.append(-1)
+ item.append(item_state) # STATE: WARNING|CRITICAL
+ item.append(item_type) # TYPE: CPU, LOAD, MEM...
+ item.append(item_value) # MAX
+ item.append(item_value) # AVG
+ item.append(item_value) # MIN
+ item.append(item_value) # SUM
+ item.append(1) # COUNT
+ self.logs_list.insert(0, item)
+ if self.len() > self.logs_max:
+ self.logs_list.pop()
+ else:
+ # Item exist, update
+ if (item_state == "OK" or
+ item_state == "CAREFUL"):
+ # Close the item
+ self.logs_list[item_index][1] = time.mktime(
+ datetime.now().timetuple())
+ else:
+ # Update the item
+ # State
+ if item_state == "CRITICAL":
+ self.logs_list[item_index][2] = item_state
+ # Value
+ if item_value > self.logs_list[item_index][4]:
+ # MAX
+ self.logs_list[item_index][4] = item_value
+ elif item_value < self.logs_list[item_index][6]:
+ # MIN
+ self.logs_list[item_index][6] = item_value
+ # AVG
+ self.logs_list[item_index][7] += item_value
+ self.logs_list[item_index][8] += 1
+ self.logs_list[item_index][5] = (
+ self.logs_list[item_index][7] /
+ self.logs_list[item_index][8])
+
+ return self.len()
+
+
+class glancesGrabFs:
+ """
+ Get FS stats
+ """
+
+ def __init__(self):
+ """
+ Init FS stats
+ """
+
+ # Ignore the following FS name
+ self.ignore_fsname = ('', 'none', 'gvfs-fuse-daemon', 'fusectl',
+ 'cgroup')
+
+ # Ignore the following FS type
+ self.ignore_fstype = ('binfmt_misc', 'devpts', 'iso9660', 'none',
+ 'proc', 'sysfs', 'usbfs', 'rootfs', 'autofs',
+ 'devtmpfs')
+
+ def __update__(self):
+ """
+ Update the stats
+ """
+
+ # Reset the list
+ self.fs_list = []
+
+ # Open the current mounted FS
+ fs_stat = psutil.disk_partitions(True)
+ for fs in xrange(len(fs_stat)):
+ fs_current = {}
+ fs_current['device_name'] = fs_stat[fs].device
+ if fs_current['device_name'] in self.ignore_fsname:
+ continue
+ fs_current['fs_type'] = fs_stat[fs].fstype
+ if fs_current['fs_type'] in self.ignore_fstype:
+ continue
+ fs_current['mnt_point'] = fs_stat[fs].mountpoint
+ try:
+ fs_usage = psutil.disk_usage(fs_current['mnt_point'])
+ except Exception:
+ continue
+ fs_current['size'] = fs_usage.total
+ fs_current['used'] = fs_usage.used
+ fs_current['avail'] = fs_usage.free
+ self.fs_list.append(fs_current)
+
+ def get(self):
+ self.__update__()
+ return self.fs_list
+
+
+class glancesStats:
+ """
+ This class store, update and give stats
+ """
+
+ def __init__(self):
+ """
+ Init the stats
+ """
+
+ # Init the fs stats
+ try:
+ self.glancesgrabfs = glancesGrabFs()
+ except Exception:
+ self.glancesgrabfs = {}
+
+ # Process list refresh
+ self.process_list_refresh = True
+
+ def __update__(self):
+ """
+ Update the stats
+ """
+
+ # Host and OS informations
+ self.host = {}
+ self.host['os_name'] = platform.system()
+ self.host['hostname'] = platform.node()
+ self.host['platform'] = platform.architecture()[0]
+
+ # check if it's Arch Linux
+ is_archlinux = os.path.exists(os.path.join("/", "etc", "arch-release"))
+
+ try:
+ if self.host['os_name'] == "Linux":
+ if is_archlinux:
+ self.host['linux_distro'] = "Arch Linux"
+ else:
+ linux_distro = platform.linux_distribution()
+ self.host['linux_distro'] = " ".join(linux_distro[:2])
+ self.host['os_version'] = platform.release()
+ elif self.host['os_name'] == "FreeBSD":
+ self.host['os_version'] = platform.release()
+ elif self.host['os_name'] == "Darwin":
+ self.host['os_version'] = platform.mac_ver()[0]
+ elif self.host['os_name'] == "Windows":
+ os_version = platform.win32_ver()
+ self.host['os_version'] = " ".join(os_version[::2])
+ else:
+ self.host['os_version'] = ""
+ except Exception:
+ self.host['os_version'] = ""
+
+ # CPU
+ percent = 0
+ try:
+ self.cputime_old
+ except Exception:
+ self.cputime_old = psutil.cpu_times()
+ self.cputime_total_old = (self.cputime_old.user +
+ self.cputime_old.system +
+ self.cputime_old.idle)
+ # Only available on some OS
+ try:
+ self.cputime_total_old += self.cputime_old.nice
+ except Exception:
+ pass
+ try:
+ self.cputime_total_old += self.cputime_old.iowait
+ except Exception:
+ pass
+ try:
+ self.cputime_total_old += self.cputime_old.irq
+ except Exception:
+ pass
+ try:
+ self.cputime_total_old += self.cputime_old.softirq
+ except Exception:
+ pass
+ self.cpu = {}
+ else:
+ try:
+ self.cputime_new = psutil.cpu_times()
+ self.cputime_total_new = (self.cputime_new.user +
+ self.cputime_new.system +
+ self.cputime_new.idle)
+ # Only available on some OS
+ try:
+ self.cputime_total_new += self.cputime_new.nice
+ except Exception:
+ pass
+ try:
+ self.cputime_total_new += self.cputime_new.iowait
+ except Exception:
+ pass
+ try:
+ self.cputime_total_new += self.cputime_new.irq
+ except Exception:
+ pass
+ try:
+ self.cputime_total_new += self.cputime_new.softirq
+ except Exception:
+ pass
+ percent = 100 / (self.cputime_total_new -
+ self.cputime_total_old)
+ self.cpu = {'kernel':
+ (self.cputime_new.system -
+ self.cputime_old.system) * percent,
+ 'user':
+ (self.cputime_new.user -
+ self.cputime_old.user) * percent,
+ 'idle':
+ (self.cputime_new.idle -
+ self.cputime_old.idle) * percent,
+ 'nice':
+ (self.cputime_new.nice -
+ self.cputime_old.nice) * percent}
+ self.cputime_old = self.cputime_new
+ self.cputime_total_old = self.cputime_total_new
+ except Exception:
+ self.cpu = {}
+
+ # LOAD
+ try:
+ getload = os.getloadavg()
+ self.load = {'min1': getload[0],
+ 'min5': getload[1],
+ 'min15': getload[2]}
+ except Exception:
+ self.load = {}
+
+ # MEM
+ try:
+ # Only for Linux
+ cachemem = psutil.cached_phymem() + psutil.phymem_buffers()
+ except Exception:
+ cachemem = 0
+
+ try:
+ phymem = psutil.phymem_usage()
+ self.mem = {'cache': cachemem,
+ 'total': phymem.total,
+ 'used': phymem.used,
+ 'free': phymem.free,
+ 'percent': phymem.percent}
+ except Exception:
+ self.mem = {}
+
+ try:
+ virtmem = psutil.virtmem_usage()
+ self.memswap = {'total': virtmem.total,
+ 'used': virtmem.used,
+ 'free': virtmem.free,
+ 'percent': virtmem.percent}
+ except Exception:
+ self.memswap = {}
+
+ # NET
+ if psutil_network_io_tag:
+ self.network = []
+ try:
+ self.network_old
+ except Exception:
+ if psutil_network_io_tag:
+ self.network_old = psutil.network_io_counters(True)
+ else:
+ try:
+ self.network_new = psutil.network_io_counters(True)
+ except Exception:
+ pass
+ else:
+ for net in self.network_new:
+ try:
+ netstat = {}
+ netstat['interface_name'] = net
+ netstat['rx'] = (self.network_new[net].bytes_recv -
+ self.network_old[net].bytes_recv)
+ netstat['tx'] = (self.network_new[net].bytes_sent -
+ self.network_old[net].bytes_sent)
+ except Exception:
+ continue
+ else:
+ self.network.append(netstat)
+ self.network_old = self.network_new
+
+ # DISK I/O
+ if psutil_disk_io_tag:
+ self.diskio = []
+ try:
+ self.diskio_old
+ except Exception:
+ if psutil_disk_io_tag:
+ self.diskio_old = psutil.disk_io_counters(True)
+ else:
+ try:
+ self.diskio_new = psutil.disk_io_counters(True)
+ except Exception:
+ pass
+ else:
+ for disk in self.diskio_new:
+ try:
+ diskstat = {}
+ diskstat['disk_name'] = disk
+ diskstat['read_bytes'] = (
+ self.diskio_new[disk].read_bytes -
+ self.diskio_old[disk].read_bytes)
+ diskstat['write_bytes'] = (
+ self.diskio_new[disk].write_bytes -
+ self.diskio_old[disk].write_bytes)
+ except Exception:
+ continue
+ else:
+ self.diskio.append(diskstat)
+ self.diskio_old = self.diskio_new
+
+ # FILE SYSTEM
+ if psutil_fs_usage_tag:
+ try:
+ self.fs = self.glancesgrabfs.get()
+ except Exception:
+ self.fs = {}
+
+ # PROCESS
+ # Initialiation of the running processes list
+ # Data are refreshed every two cycle (refresh_time * 2)
+ if self.process_list_refresh:
+ self.process_first_grab = False
+ try:
+ self.process_all
+ except Exception:
+ self.process_all = [proc for proc in psutil.process_iter()]
+ self.process_first_grab = True
+ self.process = []
+ self.processcount = {'total': 0, 'running': 0, 'sleeping': 0}
+ # Manage new processes
+ process_new = [proc.pid for proc in self.process_all]
+ for proc in psutil.process_iter():
+ if proc.pid not in process_new:
+ self.process_all.append(proc)
+ # Grab stats from process list
+ for proc in self.process_all[:]:
+ try:
+ if not proc.is_running():
+ try:
+ self.process_all.remove(proc)
+ except Exception:
+ pass
+ except psutil.error.NoSuchProcess:
+ try:
+ self.process_all.remove(proc)
+ except Exception:
+ pass
+ else:
+ # Global stats
+ try:
+ self.processcount[str(proc.status)] += 1
+ except psutil.error.NoSuchProcess:
+ # Process non longer exist
+ pass
+ except KeyError:
+ # Key did not exist, create it
+ self.processcount[str(proc.status)] = 1
+ finally:
+ self.processcount['total'] += 1
+ # Per process stats
+ try:
+ procstat = {}
+ procstat['proc_size'] = proc.get_memory_info().vms
+ procstat['proc_resident'] = proc.get_memory_info().rss
+ if psutil_get_cpu_percent_tag:
+ procstat['cpu_percent'] = \
+ proc.get_cpu_percent(interval=0)
+ procstat['mem_percent'] = proc.get_memory_percent()
+ procstat['pid'] = proc.pid
+ procstat['uid'] = proc.username
+ try:
+ # Deprecated in PsUtil 0.5.0
+ procstat['nice'] = proc.nice
+ except:
+ # Specific for PsUtil 0.5.0
+ procstat['nice'] = proc.get_nice()
+ procstat['status'] = str(proc.status)[:1].upper()
+ procstat['proc_time'] = proc.get_cpu_times()
+ procstat['proc_name'] = proc.name
+ procstat['proc_cmdline'] = " ".join(proc.cmdline)
+ self.process.append(procstat)
+ except Exception:
+ pass
+
+ # If it is the first grab then empty process list
+ if self.process_first_grab:
+ self.process = []
+
+ self.process_list_refresh = not self.process_list_refresh
+
+ # Get the current date/time
+ self.now = datetime.now()
+
+ # Get the number of core (CPU) (Used to display load alerts)
+ self.core_number = psutil.NUM_CPUS
+
+ def update(self):
+ # Update the stats
+ self.__update__()
+
+ def getHost(self):
+ return self.host
+
+ def getSystem(self):
+ return self.host
+
+ def getCpu(self):
+ return self.cpu
+
+ def getCore(self):
+ return self.core_number
+
+ def getLoad(self):
+ return self.load
+
+ def getMem(self):
+ return self.mem
+
+ def getMemSwap(self):
+ return self.memswap
+
+ def getNetwork(self):
+ if psutil_network_io_tag:
+ return sorted(self.network,
+ key=lambda network: network['interface_name'])
+ else:
+ return 0
+
+ def getDiskIO(self):
+ if psutil_disk_io_tag:
+ return sorted(self.diskio, key=lambda diskio: diskio['disk_name'])
+ else:
+ return 0
+
+ def getFs(self):
+ if psutil_fs_usage_tag:
+ return sorted(self.fs, key=lambda fs: fs['mnt_point'])
+ else:
+ return 0
+
+ def getProcessCount(self):
+ return self.processcount
+
+ def getProcessList(self, sortedby='auto'):
+ """
+ Return the sorted process list
+ """
+
+ sortedReverse = True
+ if sortedby == 'auto':
+ if psutil_get_cpu_percent_tag:
+ sortedby = 'cpu_percent'
+ else:
+ sortedby = 'mem_percent'
+ # Auto selection
+ # If global MEM > 70% sort by MEM usage
+ # else sort by CPU usage
+ real_used_phymem = self.mem['used'] - self.mem['cache']
+ try:
+ memtotal = (real_used_phymem * 100) / self.mem['total']
+ except Exception:
+ pass
+ else:
+ if memtotal > limits.getSTDWarning():
+ sortedby = 'mem_percent'
+ elif sortedby == 'proc_name':
+ sortedReverse = False
+
+ return sorted(self.process, key=lambda process: process[sortedby],
+ reverse=sortedReverse)
+
+ def getNow(self):
+ return self.now
+
+
+class glancesScreen:
+ """
+ This class manage the screen (display and key pressed)
+ """
+
+ # By default the process list is automatically sorted
+ # If global CPU > WANRING => Sorted by CPU usage
+ # If global used MEM > WARINING => Sorted by MEM usage
+ __process_sortedby = 'auto'
+
+ def __init__(self, refresh_time=1):
+ # Global information to display
+ self.__version = __version__
+
+ # Init windows positions
+ self.term_w = 80
+ self.term_h = 24
+ self.system_x = 0
+ self.system_y = 0
+ self.cpu_x = 0
+ self.cpu_y = 2
+ self.load_x = 19
+ self.load_y = 2
+ self.mem_x = 39
+ self.mem_y = 2
+ self.network_x = 0
+ self.network_y = 7
+ self.diskio_x = 0
+ self.diskio_y = -1
+ self.fs_x = 0
+ self.fs_y = -1
+ self.process_x = 29
+ self.process_y = 7
+ self.log_x = 0
+ self.log_y = -1
+ self.help_x = 0
+ self.help_y = 0
+ self.now_x = 79
+ self.now_y = 3
+ self.caption_x = 0
+ self.caption_y = 3
+
+ # Init the curses screen
+ self.screen = curses.initscr()
+ if not self.screen:
+ print _("Error: Cannot init the curses library.\n")
+
+ curses.start_color()
+ if hasattr(curses, 'use_default_colors'):
+ try:
+ curses.use_default_colors()
+ except Exception:
+ pass
+ if hasattr(curses, 'noecho'):
+ try:
+ curses.noecho()
+ except Exception:
+ pass
+ if hasattr(curses, 'cbreak'):
+ try:
+ curses.cbreak()
+ except Exception:
+ pass
+ if hasattr(curses, 'curs_set'):
+ try:
+ curses.curs_set(0)
+ except Exception:
+ pass
+
+ # Init colors
+ self.hascolors = False
+ if curses.has_colors() and curses.COLOR_PAIRS > 8:
+ self.hascolors = True
+ # FG color, BG color
+ curses.init_pair(1, curses.COLOR_WHITE, -1)
+ curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_RED)
+ curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_GREEN)
+ curses.init_pair(4, curses.COLOR_WHITE, curses.COLOR_BLUE)
+ curses.init_pair(5, curses.COLOR_WHITE, curses.COLOR_MAGENTA)
+ curses.init_pair(6, curses.COLOR_RED, -1)
+ curses.init_pair(7, curses.COLOR_GREEN, -1)
+ curses.init_pair(8, curses.COLOR_BLUE, -1)
+ curses.init_pair(9, curses.COLOR_MAGENTA, -1)
+ else:
+ self.hascolors = False
+
+ self.title_color = curses.A_BOLD | curses.A_UNDERLINE
+ self.help_color = curses.A_BOLD
+ if self.hascolors:
+ # Colors text styles
+ self.no_color = curses.color_pair(1)
+ self.default_color = curses.color_pair(3) | curses.A_BOLD
+ self.ifCAREFUL_color = curses.color_pair(4) | curses.A_BOLD
+ self.ifWARNING_color = curses.color_pair(5) | curses.A_BOLD
+ self.ifCRITICAL_color = curses.color_pair(2) | curses.A_BOLD
+ self.default_color2 = curses.color_pair(7) | curses.A_BOLD
+ self.ifCAREFUL_color2 = curses.color_pair(8) | curses.A_BOLD
+ self.ifWARNING_color2 = curses.color_pair(9) | curses.A_BOLD
+ self.ifCRITICAL_color2 = curses.color_pair(6) | curses.A_BOLD
+ else:
+ # B&W text styles
+ self.no_color = curses.A_NORMAL
+ self.default_color = curses.A_NORMAL
+ self.ifCAREFUL_color = curses.A_UNDERLINE
+ self.ifWARNING_color = curses.A_BOLD
+ self.ifCRITICAL_color = curses.A_REVERSE
+ self.default_color2 = curses.A_NORMAL
+ self.ifCAREFUL_color2 = curses.A_UNDERLINE
+ self.ifWARNING_color2 = curses.A_BOLD
+ self.ifCRITICAL_color2 = curses.A_REVERSE
+
+ # Define the colors list (hash table) for logged stats
+ self.__colors_list = {
+ # CAREFUL WARNING CRITICAL
+ 'DEFAULT': self.no_color,
+ 'OK': self.default_color,
+ 'CAREFUL': self.ifCAREFUL_color,
+ 'WARNING': self.ifWARNING_color,
+ 'CRITICAL': self.ifCRITICAL_color
+ }
+
+ # Define the colors list (hash table) for non logged stats
+ self.__colors_list2 = {
+ # CAREFUL WARNING CRITICAL
+ 'DEFAULT': self.no_color,
+ 'OK': self.default_color2,
+ 'CAREFUL': self.ifCAREFUL_color2,
+ 'WARNING': self.ifWARNING_color2,
+ 'CRITICAL': self.ifCRITICAL_color2
+ }
+
+ # What are we going to display
+ self.network_tag = psutil_network_io_tag
+ self.diskio_tag = psutil_disk_io_tag
+ self.fs_tag = psutil_fs_usage_tag
+ self.log_tag = True
+ self.help_tag = False
+
+ # Init main window
+ self.term_window = self.screen.subwin(0, 0)
+
+ # Init refresh time
+ self.__refresh_time = refresh_time
+
+ # Catch key pressed with non blocking mode
+ self.term_window.keypad(1)
+ self.term_window.nodelay(1)
+ self.pressedkey = -1
+
+ def setProcessSortedBy(self, sorted):
+ self.__process_sortedautoflag = False
+ self.__process_sortedby = sorted
+
+ def getProcessSortedBy(self):
+ return self.__process_sortedby
+
+ def __autoUnit(self, val):
+ """
+ Convert val to string and concatenate the good unit
+ Exemples:
+ 960 -> 960
+ 142948 -> 143K
+ 560745673 -> 561M
+ ...
+ """
+ symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
+ prefix = {
+ 'Y': 1208925819614629174706176L,
+ 'Z': 1180591620717411303424L,
+ 'E': 1152921504606846976L,
+ 'P': 1125899906842624L,
+ 'T': 1099511627776L,
+ 'G': 1073741824,
+ 'M': 1048576,
+ 'K': 1024
+ }
+
+ for key in reversed(symbols):
+ if val >= prefix[key]:
+ value = float(val) / prefix[key]
+ if key == "M" or key == "K":
+ return "{0:.0f}{1}".format(value, key)
+ else:
+ return "{0:.1f}{1}".format(value, key)
+
+ return "{!s}".format(val)
+
+ def __getAlert(self, current=0, max=100):
+ # If current < CAREFUL of max then alert = OK
+ # If current > CAREFUL of max then alert = CAREFUL
+ # If current > WARNING of max then alert = WARNING
+ # If current > CRITICAL of max then alert = CRITICAL
+ try:
+ (current * 100) / max
+ except ZeroDivisionError:
+ return 'DEFAULT'
+
+ variable = (current * 100) / max
+
+ if variable > limits.getSTDCritical():
+ return 'CRITICAL'
+ elif variable > limits.getSTDWarning():
+ return 'WARNING'
+ elif variable > limits.getSTDCareful():
+ return 'CAREFUL'
+
+ return 'OK'
+
+ def __getColor(self, current=0, max=100):
+ """
+ Return colors for logged stats
+ """
+ return self.__colors_list[self.__getAlert(current, max)]
+
+ def __getColor2(self, current=0, max=100):
+ """
+ Return colors for non logged stats
+ """
+ return self.__colors_list2[self.__getAlert(current, max)]
+
+ def __getCpuAlert(self, current=0, max=100):
+ return self.__getAlert(current, max)
+
+ def __getCpuColor(self, current=0, max=100):
+ return self.__getColor(current, max)
+
+ def __getLoadAlert(self, current=0, core=1):
+ # If current < CAREFUL*core of max then alert = OK
+ # If current > CAREFUL*core of max then alert = CAREFUL
+ # If current > WARNING*core of max then alert = WARNING
+ # If current > CRITICAL*core of max then alert = CRITICAL
+
+ if current > limits.getLOADCritical(core):
+ return 'CRITICAL'
+ elif current > limits.getLOADWarning(core):
+ return 'WARNING'
+ elif current > limits.getLOADCareful(core):
+ return 'CAREFUL'
+
+ return 'OK'
+
+ def __getLoadColor(self, current=0, core=1):
+ return self.__colors_list[self.__getLoadAlert(current, core)]
+
+ def __getMemAlert(self, current=0, max=100):
+ return self.__getAlert(current, max)
+
+ def __getMemColor(self, current=0, max=100):
+ return self.__getColor(current, max)
+
+ def __getNetColor(self, current=0, max=100):
+ return self.__getColor2(current, max)
+