Correct issue #414

pull/454/head
Nicolas Hennion 2014-10-28 08:55:25 +01:00
parent 7d5dca88c7
commit 934a7479f3
5 changed files with 197 additions and 19 deletions

View File

@ -121,7 +121,19 @@ def main():
standalone.serve_forever()
elif core.is_client():
if core.is_client_autodiscover():
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
@ -129,14 +141,6 @@ def main():
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)
else:
# Test if client and server are in the same major version
if not client.login():
logger.critical(

View File

@ -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

View File

@ -149,8 +149,12 @@ class GlancesProcesses(object):
procstat['mandatory_stats'] = True
# Process CPU, MEM percent and name
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

View File

@ -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:

View File

@ -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.