This commit is contained in:
Nicolargo 2014-10-27 15:46:57 +01:00
parent 0ad3fcdbfd
commit 7d5dca88c7

View File

@ -0,0 +1,149 @@
# -*- 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 autodiscover Glances server (thk to the ZeroConf protocol)."""
# Import system libs
import socket
try:
from zeroconf import ServiceBrowser, ServiceInfo, Zeroconf
zeroconf_tag = True
except ImportError:
zeroconf_tag = False
# Import Glances libs
from glances.core.glances_globals import appname, version, logger
# Global var
zeroconf_type = "_%s._tcp." % appname
class AutoDiscovered(object):
"""Class to manage the auto discovered servers dict"""
def __init__(self):
# server_dict is a dict of dict
# key: ip:port
# value: {'cpu': 3, 'mem': 34 ...}
self._server_dict = {}
def get_servers_list(self):
"""Return the current server list (dict of dict)"""
return self._server_dict
def add_server(self, name, ip, port):
"""Add a new server to the dict"""
self._server_dict[name] = {'ip': ip, 'port': port}
logger.debug("Servers list: %s" % self._server_dict)
def remove_server(self, name):
"""Remove a server from the dict"""
del(self._server_dict[name])
logger.debug("Servers list: %s" % self._server_dict)
class GlancesAutoDiscoverListener(object):
"""Zeroconf listener for Glances server"""
def __init__(self):
# Create an instance of the servers list
self.servers = AutoDiscovered()
def get_servers_list(self):
"""Return the current server list (dict of dict)"""
return self.servers.get_servers_list()
def addService(self, zeroconf, srv_type, srv_name):
"""Method called when a new Zeroconf client is detected
Return True if the zeroconf client is a Glances server
Note: the return code will never be used
"""
if srv_type != zeroconf_type:
return False
info = zeroconf.getServiceInfo(srv_type, srv_name)
if info:
new_server_ip = socket.inet_ntoa(info.getAddress())
new_server_port = info.getPort()
# !!! Only for dev
# new_server_name = info.getServer()
prop = info.getProperties()
if prop:
logger.debug("Zeroconf properties are %s" % prop)
# Add server to the global dict
self.servers.add_server(srv_name, new_server_ip, new_server_port)
logger.info("New Glances server detected (%s from %s:%s)" % (srv_name, new_server_ip, new_server_port))
else:
logger.warning("New Glances server detected, but Zeroconf info failed to be grabbed")
return True
def removeService(self, zeroconf, srv_type, srv_name):
# Remove the server from the list
self.servers.remove_server(srv_name)
logger.info("Glances server %s removed from the autodetect list" % srv_name)
class GlancesAutoDiscoverServer(object):
"""Implementation of the Zeroconf protocol (server side for the Glances client)"""
def __init__(self, args=None):
if zeroconf_tag:
logger.info("Init autodiscover mode (Zeroconf protocol)")
self.zeroconf = Zeroconf()
self.listener = GlancesAutoDiscoverListener()
self.browser = ServiceBrowser(self.zeroconf, zeroconf_type, self.listener)
else:
logger.error("Can not start autodiscover mode (Zeroconf lib is not installed)")
def get_servers_list(self):
"""Return the current server list (dict of dict)"""
if zeroconf_tag:
return self.listener.get_servers_list()
else:
return {}
def close(self):
if zeroconf_tag:
self.zeroconf.close()
class GlancesAutoDiscoverClient(object):
"""Implementation of the Zeroconf protocol (client side for the Glances server)"""
def __init__(self, hostname, args=None):
if zeroconf_tag:
logger.info("Announce the Glances server on the local area network")
self.zeroconf = Zeroconf()
self.info = ServiceInfo(zeroconf_type,
hostname + '.' + zeroconf_type,
address=socket.inet_aton(args.bind_address),
port=args.port,
weight=0,
priority=0,
properties={},
server=hostname)
self.zeroconf.registerService(self.info)
else:
logger.error("Can not announce Glances server on the network (Zeroconf lib is not installed)")
def close(self):
if zeroconf_tag:
self.zeroconf.unregisterService(self.info)
self.zeroconf.close()