mirror of https://github.com/nicolargo/glances
Correct issue #414
parent
7d5dca88c7
commit
934a7479f3
|
@ -121,30 +121,34 @@ def main():
|
|||
standalone.serve_forever()
|
||||
|
||||
elif core.is_client():
|
||||
logger.info("Start client mode")
|
||||
# Import the Glances client module
|
||||
from glances.core.glances_client import GlancesClient
|
||||
|
||||
# Init the client
|
||||
client = GlancesClient(config=core.get_config(),
|
||||
args=core.get_args())
|
||||
|
||||
if core.is_client_autodiscover():
|
||||
# !!! Create a new script with the client_browser feature
|
||||
import time
|
||||
while True:
|
||||
print client.get_servers_list()
|
||||
time.sleep(3)
|
||||
logger.info("Start client mode (browser)")
|
||||
|
||||
# Import the Glances client browser module
|
||||
from glances.core.glances_client_browser import GlancesClientBrowser
|
||||
|
||||
# Init the client
|
||||
client = GlancesClientBrowser(config=core.get_config(),
|
||||
args=core.get_args())
|
||||
|
||||
else:
|
||||
logger.info("Start client mode")
|
||||
|
||||
# Import the Glances client module
|
||||
from glances.core.glances_client import GlancesClient
|
||||
|
||||
# Init the client
|
||||
client = GlancesClient(config=core.get_config(),
|
||||
args=core.get_args())
|
||||
|
||||
# Test if client and server are in the same major version
|
||||
if not client.login():
|
||||
logger.critical(
|
||||
_("The server version is not compatible with the client"))
|
||||
sys.exit(2)
|
||||
|
||||
# Start the client loop
|
||||
client.serve_forever()
|
||||
# Start the client loop
|
||||
client.serve_forever()
|
||||
|
||||
# Shutdown the client
|
||||
client.close()
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
# -*- 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/>.
|
||||
|
||||
"""Manage the Glances client browser (list of Glances server)."""
|
||||
|
||||
# Import system libs
|
||||
import time
|
||||
import json
|
||||
try:
|
||||
from xmlrpc.client import Transport, ServerProxy, ProtocolError, Fault
|
||||
except ImportError:
|
||||
# Python 2
|
||||
from xmlrpclib import Transport, ServerProxy, ProtocolError, Fault
|
||||
|
||||
# Import Glances libs
|
||||
from glances.core.glances_globals import logger
|
||||
from glances.outputs.glances_curses import GlancesCurses
|
||||
from glances.core.glances_autodiscover import GlancesAutoDiscoverServer
|
||||
|
||||
|
||||
class GlancesClientBrowser(object):
|
||||
|
||||
"""This class creates and manages the TCP client browser (servers' list)."""
|
||||
|
||||
def __init__(self, config=None, args=None):
|
||||
# Store the arg/config
|
||||
self.args = args
|
||||
self.config = config
|
||||
|
||||
# Start the autodiscover mode (Zeroconf listener)
|
||||
if self.args.autodiscover:
|
||||
self.autodiscover_server = GlancesAutoDiscoverServer()
|
||||
|
||||
# Init screen
|
||||
self.screen = GlancesCurses(args=self.args)
|
||||
|
||||
def get_servers_list(self):
|
||||
"""Return the current server list (dict of dict)"""
|
||||
if self.args.autodiscover:
|
||||
return self.autodiscover_server.get_servers_list()
|
||||
else:
|
||||
return {}
|
||||
|
||||
def serve_forever(self):
|
||||
"""Main client loop."""
|
||||
while True:
|
||||
# No need to update the server list
|
||||
# It's done by the GlancesAutoDiscoverListener class (glances_autodiscover.py)
|
||||
# For each server in the list, grab elementary stats (CPU, LOAD, MEM)
|
||||
# logger.debug(self.get_servers_list())
|
||||
try:
|
||||
iteritems = self.get_servers_list().iteritems()
|
||||
except AttributeError:
|
||||
iteritems = self.get_servers_list().items()
|
||||
for k, v in iteritems:
|
||||
s = ServerProxy('http://%s:%s' % (self.get_servers_list()[k]['ip'], self.get_servers_list()[k]['port']))
|
||||
# !!! 3 requests => high CPU consumption on the server :(
|
||||
# !!! Try a getAll ??? Optimize server ???
|
||||
self.get_servers_list()[k]['load_min5'] = json.loads(s.getLoad())['min5']
|
||||
self.get_servers_list()[k]['cpu_percent'] = 100 - json.loads(s.getCpu())['idle']
|
||||
self.get_servers_list()[k]['mem_percent'] = json.loads(s.getMem())['percent']
|
||||
|
||||
# Update the screen
|
||||
self.screen.update_browser(self.get_servers_list())
|
||||
|
||||
def end(self):
|
||||
"""End of the client session."""
|
||||
pass
|
|
@ -149,8 +149,12 @@ class GlancesProcesses(object):
|
|||
procstat['mandatory_stats'] = True
|
||||
|
||||
# Process CPU, MEM percent and name
|
||||
procstat.update(
|
||||
proc.as_dict(attrs=['cpu_percent', 'memory_percent', 'name'], ad_value=''))
|
||||
try:
|
||||
procstat.update(
|
||||
proc.as_dict(attrs=['cpu_percent', 'memory_percent', 'name'], ad_value=''))
|
||||
except psutil.NoSuchProcess:
|
||||
# Correct issue #414
|
||||
return None
|
||||
if procstat['cpu_percent'] == '' or procstat['memory_percent'] == '':
|
||||
# Do not display process if we can not get the basic
|
||||
# cpu_percent or memory_percent stats
|
||||
|
|
|
@ -176,8 +176,7 @@ class GlancesInstance(object):
|
|||
if item.startswith(header):
|
||||
try:
|
||||
# Update the stat
|
||||
# !!! All the stat are updated before one grab (not optimized)
|
||||
self.stats.update()
|
||||
self.__update__()
|
||||
# Return the attribute
|
||||
return getattr(self.stats, item)
|
||||
except Exception:
|
||||
|
|
|
@ -361,6 +361,65 @@ class GlancesCurses(object):
|
|||
"""New column in the curses interface"""
|
||||
self.column = self.next_column
|
||||
|
||||
def display_browser(self, servers_list):
|
||||
"""Display the servers list
|
||||
Return:
|
||||
True if the stats have been displayed
|
||||
False if the help have been displayed
|
||||
"""
|
||||
# Init the internal line/column for Glances Curses
|
||||
self.init_line_column()
|
||||
|
||||
# Get the current screen size
|
||||
screen_x = self.screen.getmaxyx()[1]
|
||||
screen_y = self.screen.getmaxyx()[0]
|
||||
|
||||
# Display header
|
||||
x = 0
|
||||
y = 0
|
||||
if len(servers_list) == 0:
|
||||
msg = _("No Glances server detected on your network")
|
||||
elif len(servers_list) == 1:
|
||||
msg = _("One Glances server detected on your network")
|
||||
else:
|
||||
msg = _("%d Glances servers detected on your network" % len(servers_list))
|
||||
self.term_window.addnstr(y, x,
|
||||
msg,
|
||||
screen_x - x,
|
||||
self.__colors_list['TITLE'])
|
||||
|
||||
# Display the Glances server list
|
||||
y = 2
|
||||
try:
|
||||
iteritems = servers_list.iteritems()
|
||||
except AttributeError:
|
||||
iteritems = servers_list.items()
|
||||
for k, v in iteritems:
|
||||
# Display server address:port
|
||||
msg = "%s:%s" % (servers_list[k]['ip'], servers_list[k]['port'])
|
||||
self.term_window.addnstr(y, x,
|
||||
"%21s" % msg,
|
||||
screen_x - x,
|
||||
self.__colors_list['BOLD'])
|
||||
# Display server LOAD
|
||||
self.term_window.addnstr(y, x + 24,
|
||||
"%6s" % servers_list[k]['load_min5'],
|
||||
screen_x - x,
|
||||
self.__colors_list['DEFAULT'])
|
||||
# Display server CPU%
|
||||
self.term_window.addnstr(y, x + 32,
|
||||
"%6s" % servers_list[k]['cpu_percent'],
|
||||
screen_x - x,
|
||||
self.__colors_list['DEFAULT'])
|
||||
# Display server MEM%
|
||||
self.term_window.addnstr(y, x + 40,
|
||||
"%6s" % servers_list[k]['mem_percent'],
|
||||
screen_x - x,
|
||||
self.__colors_list['DEFAULT'])
|
||||
y += 1
|
||||
|
||||
return True
|
||||
|
||||
def display(self, stats, cs_status="None"):
|
||||
"""Display stats on the screen.
|
||||
|
||||
|
@ -731,6 +790,14 @@ class GlancesCurses(object):
|
|||
self.erase()
|
||||
self.display(stats, cs_status=cs_status)
|
||||
|
||||
def flush_browser(self, servers_list):
|
||||
"""Update the servers' list screen.
|
||||
|
||||
servers_list: Dict of dict with servers stats
|
||||
"""
|
||||
self.erase()
|
||||
self.display_browser(servers_list)
|
||||
|
||||
def update(self, stats, cs_status="None"):
|
||||
"""Update the screen.
|
||||
|
||||
|
@ -755,6 +822,26 @@ class GlancesCurses(object):
|
|||
# Wait 100ms...
|
||||
curses.napms(100)
|
||||
|
||||
def update_browser(self, servers_list):
|
||||
"""Update the servers' list screen.
|
||||
|
||||
Wait for __refresh_time sec / catch key every 100 ms.
|
||||
|
||||
servers_list: Dict of dict with servers stats
|
||||
"""
|
||||
# Flush display
|
||||
self.flush_browser(servers_list)
|
||||
|
||||
# Wait
|
||||
countdown = Timer(self.__refresh_time)
|
||||
while not countdown.finished():
|
||||
# Getkey
|
||||
if self.__catch_key() > -1:
|
||||
# Redraw display
|
||||
self.flush_browser(servers_list)
|
||||
# Wait 100ms...
|
||||
curses.napms(100)
|
||||
|
||||
def get_stats_display_width(self, curse_msg, without_option=False):
|
||||
"""Return the width of the formatted curses message.
|
||||
|
||||
|
|
Loading…
Reference in New Issue