mirror of
https://github.com/nicolargo/glances.git
synced 2025-01-01 14:04:50 +03:00
Browser first public version !
This commit is contained in:
parent
891827ace4
commit
af62415923
@ -151,7 +151,7 @@ def main():
|
||||
client.serve_forever()
|
||||
|
||||
# Shutdown the client
|
||||
client.close()
|
||||
client.end()
|
||||
|
||||
elif core.is_server():
|
||||
logger.info("Start server mode")
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
# Import system libs
|
||||
import socket
|
||||
import time
|
||||
try:
|
||||
import netifaces
|
||||
netifaces_tag = True
|
||||
@ -55,9 +54,14 @@ class AutoDiscovered(object):
|
||||
|
||||
def add_server(self, name, ip, port):
|
||||
"""Add a new server to the list"""
|
||||
new_server = {'key': name, 'name': name.split(':')[0], 'ip': ip, 'port': port}
|
||||
new_server = {'key': name, # Zeroconf name with both hostname and port
|
||||
'name': name.split(':')[0], # Short name
|
||||
'ip': ip, # IP address seen by the client
|
||||
'port': port, # TCP port
|
||||
}
|
||||
self._server_list.append(new_server)
|
||||
logger.debug("Servers list: %s" % self._server_list)
|
||||
logger.debug("Updated servers list (%s servers): %s" %
|
||||
(len(self._server_list), self._server_list))
|
||||
|
||||
def remove_server(self, name):
|
||||
"""Remove a server from the dict"""
|
||||
@ -66,9 +70,11 @@ class AutoDiscovered(object):
|
||||
try:
|
||||
self._server_list.remove(i)
|
||||
logger.debug("Remove server %s from the list" % name)
|
||||
logger.debug("Updated servers list: %s" % self._server_list)
|
||||
logger.debug("Updated servers list (%s servers): %s" % (
|
||||
len(self._server_list), self._server_list))
|
||||
except ValueError:
|
||||
logger.error("Can not remove server %s from the list" % name)
|
||||
logger.error(
|
||||
"Can not remove server %s from the list" % name)
|
||||
|
||||
|
||||
class GlancesAutoDiscoverListener(object):
|
||||
@ -90,7 +96,8 @@ class GlancesAutoDiscoverListener(object):
|
||||
"""
|
||||
if srv_type != zeroconf_type:
|
||||
return False
|
||||
logger.debug("Check new Zeroconf server: %s / %s" % (srv_type, srv_name))
|
||||
logger.debug("Check new Zeroconf server: %s / %s" %
|
||||
(srv_type, srv_name))
|
||||
info = zeroconf.getServiceInfo(srv_type, srv_name)
|
||||
if info:
|
||||
new_server_ip = socket.inet_ntoa(info.getAddress())
|
||||
@ -145,21 +152,23 @@ class GlancesAutoDiscoverClient(object):
|
||||
|
||||
def __init__(self, hostname, args=None):
|
||||
if netifaces_tag:
|
||||
# !!! TO BE REFACTOR
|
||||
try:
|
||||
zeroconf_bind_address = netifaces.ifaddresses(netifaces.interfaces()[1])[netifaces.AF_INET][0]['addr']
|
||||
zeroconf_bind_address = netifaces.ifaddresses(
|
||||
netifaces.interfaces()[1])[netifaces.AF_INET][0]['addr']
|
||||
except:
|
||||
zeroconf_bind_address = args.bind_address
|
||||
print("Announce the Glances server on the local area network (using %s IP address)" % zeroconf_bind_address)
|
||||
# /!!!
|
||||
print("Announce the Glances server on the local area network (using %s IP address)" %
|
||||
zeroconf_bind_address)
|
||||
|
||||
if zeroconf_tag:
|
||||
logger.info(
|
||||
"Announce the Glances server on the local area network (using %s IP address)" % zeroconf_bind_address)
|
||||
self.zeroconf = Zeroconf()
|
||||
self.info = ServiceInfo(zeroconf_type,
|
||||
hostname+':'+str(args.port)+'.'+zeroconf_type,
|
||||
address=socket.inet_aton(zeroconf_bind_address),
|
||||
hostname + ':' +
|
||||
str(args.port) + '.' + zeroconf_type,
|
||||
address=socket.inet_aton(
|
||||
zeroconf_bind_address),
|
||||
port=args.port,
|
||||
weight=0,
|
||||
priority=0,
|
||||
|
@ -78,20 +78,9 @@ class GlancesClient(object):
|
||||
try:
|
||||
self.client = ServerProxy(uri, transport=transport)
|
||||
except Exception as e:
|
||||
logger.error("Couldn't create socket {0}: {1}".format(uri, e))
|
||||
logger.error("Client couldn't create socket {0}: {1}".format(uri, e))
|
||||
sys.exit(2)
|
||||
|
||||
# Start the autodiscover mode (Zeroconf listener)
|
||||
if self.args.autodiscover:
|
||||
self.autodiscover_server = GlancesAutoDiscoverServer()
|
||||
|
||||
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 set_mode(self, mode='glances'):
|
||||
"""Set the client mode.
|
||||
|
||||
@ -175,7 +164,7 @@ class GlancesClient(object):
|
||||
return self.update_snmp()
|
||||
else:
|
||||
self.end()
|
||||
logger.critical("Unknown server mode: {0}").format(self.get_mode())
|
||||
logger.critical(_("Unknown server mode: {0}").format(self.get_mode()))
|
||||
sys.exit(2)
|
||||
|
||||
def update_glances(self):
|
||||
@ -217,14 +206,19 @@ class GlancesClient(object):
|
||||
# Grab success
|
||||
return "SNMP"
|
||||
|
||||
def serve_forever(self):
|
||||
def serve_forever(self, return_to_browser=False):
|
||||
"""Main client loop."""
|
||||
while True:
|
||||
|
||||
exitkey = False
|
||||
|
||||
while True and not exitkey:
|
||||
# Update the stats
|
||||
cs_status = self.update()
|
||||
|
||||
# Update the screen
|
||||
self.screen.update(self.stats, cs_status=cs_status)
|
||||
exitkey = self.screen.update(self.stats,
|
||||
cs_status=cs_status,
|
||||
return_to_browser=return_to_browser)
|
||||
|
||||
def end(self):
|
||||
"""End of the client session."""
|
||||
|
@ -32,7 +32,7 @@ except ImportError:
|
||||
from glances.core.glances_globals import logger
|
||||
from glances.outputs.glances_curses import GlancesCursesBrowser
|
||||
from glances.core.glances_autodiscover import GlancesAutoDiscoverServer
|
||||
from glances.core.glances_client import GlancesClientTransport
|
||||
from glances.core.glances_client import GlancesClientTransport, GlancesClient
|
||||
|
||||
|
||||
class GlancesClientBrowser(object):
|
||||
@ -52,7 +52,7 @@ class GlancesClientBrowser(object):
|
||||
self.screen = GlancesCursesBrowser(args=self.args)
|
||||
|
||||
def get_servers_list(self):
|
||||
"""Return the current server list (dict of dict)"""
|
||||
"""Return the current server list (list of dict)"""
|
||||
if self.args.autodiscover:
|
||||
return self.autodiscover_server.get_servers_list()
|
||||
else:
|
||||
@ -78,26 +78,60 @@ class GlancesClientBrowser(object):
|
||||
try:
|
||||
s = ServerProxy(uri, t)
|
||||
except Exception as e:
|
||||
logger.warning("Couldn't create socket {0}: {1}".format(uri, e))
|
||||
logger.warning(
|
||||
"Client browser couldn't create socket {0}: {1}".format(uri, e))
|
||||
else:
|
||||
try:
|
||||
# LOAD
|
||||
v['load_min5'] = json.loads(s.getLoad())['min5']
|
||||
# CPU%
|
||||
v['cpu_percent'] = 100 - json.loads(s.getCpu())['idle']
|
||||
v['cpu_percent'] = 100 - \
|
||||
json.loads(s.getCpu())['idle']
|
||||
# MEM%
|
||||
v['mem_percent'] = json.loads(s.getMem())['percent']
|
||||
v['mem_percent'] = json.loads(
|
||||
s.getMem())['percent']
|
||||
# OS (Human Readable name)
|
||||
v['hr_name'] = json.loads(s.getSystem())['hr_name']
|
||||
except (socket.error, Fault, KeyError) as e:
|
||||
logger.warning("Can not grab stats form {0}: {1}".format(uri, e))
|
||||
logger.warning(
|
||||
"Can not grab stats form {0}: {1}".format(uri, e))
|
||||
# List can change size during iteration...
|
||||
except RuntimeError:
|
||||
logger.debug("Server list dictionnary change inside the loop (wait next update)")
|
||||
logger.debug(
|
||||
"Server list dictionnary change inside the loop (wait next update)")
|
||||
|
||||
# Update the screen
|
||||
self.screen.update(self.get_servers_list())
|
||||
# Update the screen (list or Glances client)
|
||||
if self.screen.get_active() is None:
|
||||
# Display the Glances browser
|
||||
self.screen.update(self.get_servers_list())
|
||||
else:
|
||||
# Display the Glance client on the selected server
|
||||
logger.info("Connect Glances client to the %s server" %
|
||||
self.get_servers_list()[self.screen.get_active()]['key'])
|
||||
|
||||
# Init the client
|
||||
args_server = self.args
|
||||
|
||||
# Overwrite connection setting
|
||||
args_server.client = self.get_servers_list(
|
||||
)[self.screen.get_active()]['ip']
|
||||
args_server.port = self.get_servers_list()[self.screen.get_active()][
|
||||
'port']
|
||||
client = GlancesClient(config=self.config,
|
||||
args=args_server)
|
||||
|
||||
# Test if client and server are in the same major version
|
||||
if not client.login():
|
||||
logger.error(
|
||||
"The server version is not compatible with the client")
|
||||
|
||||
# Start the client loop
|
||||
client.serve_forever(return_to_browser=True)
|
||||
|
||||
logger.debug("Disconnect Glances client from the %s server" %
|
||||
self.get_servers_list()[self.screen.get_active()]['key'])
|
||||
self.screen.set_active(None)
|
||||
|
||||
def end(self):
|
||||
"""End of the client session."""
|
||||
pass
|
||||
"""End of the client browser session."""
|
||||
self.screen.end()
|
||||
|
@ -19,8 +19,6 @@
|
||||
|
||||
"""Curses interface class."""
|
||||
|
||||
# !!! TODO: split GlancesCurses for client and client_browser
|
||||
|
||||
# Import system lib
|
||||
import sys
|
||||
|
||||
@ -218,7 +216,7 @@ class _GlancesCurses(object):
|
||||
keycode[1] = window.getch()
|
||||
|
||||
if keycode != [-1, -1]:
|
||||
logger.debug("Keypressed ! Code: %s" % keycode)
|
||||
logger.debug("Keypressed (code: %s)" % keycode)
|
||||
|
||||
if keycode[0] == 27 and keycode[1] != -1:
|
||||
# Do not escape on specials keys
|
||||
@ -226,16 +224,19 @@ class _GlancesCurses(object):
|
||||
else:
|
||||
return keycode[0]
|
||||
|
||||
def __catch_key(self):
|
||||
def __catch_key(self, return_to_browser=False):
|
||||
# Catch the pressed key
|
||||
self.pressedkey = self.get_key(self.term_window)
|
||||
|
||||
# Actions...
|
||||
if self.pressedkey == ord('\x1b') or self.pressedkey == ord('q'):
|
||||
# 'ESC'|'q' > Quit
|
||||
self.end()
|
||||
logger.info("Stop Glances")
|
||||
sys.exit(0)
|
||||
if return_to_browser:
|
||||
logger.info("Stop Glances client and return to the browser")
|
||||
else:
|
||||
self.end()
|
||||
logger.info("Stop Glances")
|
||||
sys.exit(0)
|
||||
elif self.pressedkey == 10:
|
||||
# 'ENTER' > Edit the process filter
|
||||
self.edit_filter = not self.edit_filter
|
||||
@ -736,30 +737,44 @@ class _GlancesCurses(object):
|
||||
self.erase()
|
||||
self.display(stats, cs_status=cs_status)
|
||||
|
||||
def update(self, stats, cs_status="None"):
|
||||
def update(self, stats, cs_status="None", return_to_browser=False):
|
||||
"""Update the screen.
|
||||
|
||||
Wait for __refresh_time sec / catch key every 100 ms.
|
||||
|
||||
INPUT
|
||||
stats: Stats database to display
|
||||
cs_status:
|
||||
"None": standalone or server mode
|
||||
"Connected": Client is connected to the server
|
||||
"Disconnected": Client is disconnected from the server
|
||||
return_to_browser:
|
||||
True: Do not exist, return to the browser list
|
||||
False: Exit and return to the shell
|
||||
|
||||
OUPUT
|
||||
True: Exit key has been pressed
|
||||
False: Others cases...
|
||||
"""
|
||||
# Flush display
|
||||
self.flush(stats, cs_status=cs_status)
|
||||
|
||||
# Wait
|
||||
exitkey = False
|
||||
countdown = Timer(self.__refresh_time)
|
||||
while not countdown.finished():
|
||||
while not countdown.finished() and not exitkey:
|
||||
# Getkey
|
||||
if self.__catch_key() > -1:
|
||||
pressedkey = self.__catch_key(return_to_browser=return_to_browser)
|
||||
# Is it an exit key ?
|
||||
exitkey = (pressedkey == ord('\x1b') or pressedkey == ord('q'))
|
||||
if not exitkey and pressedkey > -1:
|
||||
# Redraw display
|
||||
self.flush(stats, cs_status=cs_status)
|
||||
# Wait 100ms...
|
||||
curses.napms(100)
|
||||
|
||||
return exitkey
|
||||
|
||||
def get_stats_display_width(self, curse_msg, without_option=False):
|
||||
"""Return the width of the formatted curses message.
|
||||
|
||||
@ -813,12 +828,24 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
# Init the cursor position for the client browser
|
||||
self.cursor_init()
|
||||
|
||||
# Active Glances server number
|
||||
self.set_active()
|
||||
|
||||
def set_active(self, index=None):
|
||||
"""Set the active server or None if no server selected"""
|
||||
self.active_server = index
|
||||
return self.active_server
|
||||
|
||||
def get_active(self):
|
||||
"""Return the active server (the one display in front) or None if it is the browser list"""
|
||||
return self.active_server
|
||||
|
||||
def cursor_init(self):
|
||||
"""Init the cursor position to the top of the list"""
|
||||
return self.cursor_set(0)
|
||||
|
||||
def cursor_set(self, pos):
|
||||
"""Set the cursor position andd return it"""
|
||||
"""Set the cursor position and return it"""
|
||||
self.cursor_position = pos
|
||||
return self.cursor_position
|
||||
|
||||
@ -851,7 +878,7 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
elif self.pressedkey == 10:
|
||||
# 'ENTER' > Run Glances on the selected server
|
||||
logger.debug("Server number %s selected" % (self.cursor_get() + 1))
|
||||
self.run_client(servers_list[self.cursor_get()])
|
||||
self.set_active(self.cursor_get())
|
||||
elif self.pressedkey == 259:
|
||||
# 'UP' > Up in the server list
|
||||
logger
|
||||
@ -863,11 +890,6 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
# Return the key code
|
||||
return self.pressedkey
|
||||
|
||||
def run_client(self, server):
|
||||
"""Run the Glances client to the given server"""
|
||||
|
||||
logger.debug("Run Glances client on %s" % server)
|
||||
|
||||
def update(self, servers_list):
|
||||
"""Update the servers' list screen.
|
||||
|
||||
@ -879,15 +901,21 @@ class GlancesCursesBrowser(_GlancesCurses):
|
||||
self.flush(servers_list)
|
||||
|
||||
# Wait
|
||||
exitkey = False
|
||||
countdown = Timer(self.__refresh_time)
|
||||
while not countdown.finished():
|
||||
while not countdown.finished() and not exitkey:
|
||||
# Getkey
|
||||
if self.__catch_key(servers_list) > -1:
|
||||
pressedkey = self.__catch_key(servers_list)
|
||||
# Is it an exit or select server key ?
|
||||
exitkey = (pressedkey == ord('\x1b') or pressedkey == ord('q') or pressedkey == 10)
|
||||
if not exitkey and pressedkey > -1:
|
||||
# Redraw display
|
||||
self.flush(servers_list)
|
||||
# Wait 100ms...
|
||||
curses.napms(100)
|
||||
|
||||
return self.get_active()
|
||||
|
||||
def flush(self, servers_list):
|
||||
"""Update the servers' list screen.
|
||||
servers_list: List of dict with servers stats
|
||||
|
Loading…
Reference in New Issue
Block a user