提交 a340a5e5 编写于 作者: N nicolargo

Finalize New Ports Scanner plugin (issue#734)

上级 3b5e1144
...@@ -38,6 +38,13 @@ Bugs corrected: ...@@ -38,6 +38,13 @@ Bugs corrected:
* On Windows, Glances try to display unexisting Load stats (issue #871) * On Windows, Glances try to display unexisting Load stats (issue #871)
* Top 3 processes are back in the alert summary * Top 3 processes are back in the alert summary
Version 2.6.2
=============
Bugs corrected:
* Crash with Docker 1.11 (issue #848)
Version 2.6.1 Version 2.6.1
============= =============
......
...@@ -181,29 +181,31 @@ mem_critical=90 ...@@ -181,29 +181,31 @@ mem_critical=90
[ports] [ports]
# Ports scanner plugin configuration # Ports scanner plugin configuration
# Interval in second between scan # Interval in second between two scans
refresh=30 refresh=30
# Set the default timeout for a scan (can be overwrite in the scan list) # Set the default timeout (in second) for a scan (can be overwrite in the scan list)
timeout=3 timeout=3
# If True, add the default gateway on top of the scan list # If port_default_gateway is True, add the default gateway on top of the scan list
port_default_gateway=True port_default_gateway=True
# Define the scan list # Define the scan list (1 < x < 255)
# host (name or IP) is mandatory # port_x_host (name or IP) is mandatory
# port (TCP port number) is optional (if not set, use ICMP) # port_x_port (TCP port number) is optional (if not set, use ICMP)
# description is optional (if not set, define to host:port) # port_x_description is optional (if not set, define to host:port)
port_1_host=192.168.0.1 # port_x_timeout is optional and overwrite the default timeout value
port_1_port=80 # port_x_rtt_warning is optional and defines the warning threshold in ms
port_1_description=Home Box #port_1_host=192.168.0.1
port_2_host=www.free.fr #port_1_port=80
port_2_description=My ISP #port_1_description=Home Box
port_3_host=www.google.com #port_1_timeout=1
port_3_description=Internet ICMP #port_2_host=www.free.fr
port_4_host=www.google.com #port_2_description=My ISP
port_4_description=Internet Web #port_3_host=www.google.com
port_4_port=80 #port_3_description=Internet ICMP
port_5_host=blog.nicolargo.com #port_3_rtt_warning=1000
port_5_description=My blog #port_4_host=www.google.com
port_5_port=80 #port_4_description=Internet Web
#port_4_port=80
#port_4_rtt_warning=1000
############################################################################## ##############################################################################
# Client/server # Client/server
......
...@@ -17,20 +17,28 @@ The list should be define in the ``[ports]`` section of the Glances configuratio ...@@ -17,20 +17,28 @@ The list should be define in the ``[ports]`` section of the Glances configuratio
[ports] [ports]
# Ports scanner plugin configuration # Ports scanner plugin configuration
# Interval in second between scan # Interval in second between two scans
refresh=30 refresh=30
# Set the default timeout for a scan (can be overwrite in the scan list) # Set the default timeout (in second) for a scan (can be overwrite in the scan list)
timeout=3 timeout=3
# If True, add the default gateway on top of the scan list # If port_default_gateway is True, add the default gateway on top of the scan list
port_default_gateway=True port_default_gateway=True
# Define the scan list # Define the scan list (1 < x < 255)
# host (name or IP) is mandatory # port_x_host (name or IP) is mandatory
# port (TCP port number) is optional (if not set, use ICMP) # port_x_port (TCP port number) is optional (if not set, use ICMP)
# description is optional (if not set, define to host:port) # port_x_description is optional (if not set, define to host:port)
# port_x_timeout is optional and overwrite the default timeout value
# port_x_rtt_warning is optional and defines the warning threshold in ms
port_1_host=192.168.0.1 port_1_host=192.168.0.1
port_1_port=80 port_1_port=80
port_1_description=Home Box port_1_description=Home Box
port_1_timeout=1
port_2_host=www.free.fr port_2_host=www.free.fr
port_2_description=My ISP port_2_description=My ISP
port_3_host=www.google.com port_3_host=www.google.com
port_3_description=Internet port_3_description=Internet ICMP
port_3_rtt_warning=1000
port_4_host=www.google.com
port_4_description=Internet Web
port_4_port=80
port_4_rtt_warning=1000
...@@ -68,9 +68,10 @@ class Plugin(GlancesPlugin): ...@@ -68,9 +68,10 @@ class Plugin(GlancesPlugin):
def exit(self): def exit(self):
"""Overwrite the exit method to close threads""" """Overwrite the exit method to close threads"""
logger.debug("Stop the Docker plugin")
for t in itervalues(self.thread_list): for t in itervalues(self.thread_list):
t.stop() t.stop()
# Call the father class
super(Plugin, self).exit()
def get_key(self): def get_key(self):
"""Return the key of the list.""" """Return the key of the list."""
......
...@@ -24,6 +24,7 @@ import subprocess ...@@ -24,6 +24,7 @@ import subprocess
import threading import threading
import socket import socket
import types import types
import time
from glances.globals import WINDOWS from glances.globals import WINDOWS
from glances.ports_list import GlancesPortsList from glances.ports_list import GlancesPortsList
...@@ -51,6 +52,16 @@ class Plugin(GlancesPlugin): ...@@ -51,6 +52,16 @@ class Plugin(GlancesPlugin):
# Init global Timer # Init global Timer
self.timer_ports = Timer(0) self.timer_ports = Timer(0)
# Global Thread running all the scans
self._thread = None
def exit(self):
"""Overwrite the exit method to close threads"""
if self._thread is not None:
self._thread.stop()
# Call the father class
super(Plugin, self).exit()
@GlancesPlugin._log_result_decorator @GlancesPlugin._log_result_decorator
def update(self): def update(self):
"""Update the ports list.""" """Update the ports list."""
...@@ -59,14 +70,20 @@ class Plugin(GlancesPlugin): ...@@ -59,14 +70,20 @@ class Plugin(GlancesPlugin):
return {} return {}
if self.input_method == 'local': if self.input_method == 'local':
# Only refresh every refresh seconds (define in the configuration file) # Only refresh:
if self.timer_ports.finished(): # * if there is not other scanning thread
# * every refresh seconds (define in the configuration file)
if self._thread is None:
thread_is_running = False
else:
thread_is_running = self._thread.isAlive()
if self.timer_ports.finished() and not thread_is_running:
# Run ports scanner # Run ports scanner
thread = threading.Thread(target=self._port_scan_all, args=(self.stats,)) self._thread = ThreadScanner(self.stats)
thread.start() self._thread.start()
# Restart timer # Restart timer
if len(self.stats) > 0: if len(self.stats) > 0:
self.timer_ports = Timer(int(self.stats[0]['refresh'])) self.timer_ports = Timer(self.stats[0]['refresh'])
else: else:
self.timer_ports = Timer(0) self.timer_ports = Timer(0)
else: else:
...@@ -80,9 +97,12 @@ class Plugin(GlancesPlugin): ...@@ -80,9 +97,12 @@ class Plugin(GlancesPlugin):
if port['status'] is None: if port['status'] is None:
return 'CAREFUL' return 'CAREFUL'
elif port['status'] == 0:
if port['status'] == 0:
return 'CRITICAL' return 'CRITICAL'
elif isinstance(port['status'], (float, int)) and \
port['rtt_warning'] is not None and \
port['status'] > port['rtt_warning']:
return 'WARNING'
return 'OK' return 'OK'
...@@ -125,6 +145,59 @@ class Plugin(GlancesPlugin): ...@@ -125,6 +145,59 @@ class Plugin(GlancesPlugin):
"""Scan all host/port of the given stats""" """Scan all host/port of the given stats"""
for p in stats: for p in stats:
self._port_scan(p) self._port_scan(p)
# Had to wait between two scans
# If not, result are not ok
time.sleep(1)
class ThreadScanner(threading.Thread):
"""
Specific thread for the port scanner.
stats is a list of dict
"""
def __init__(self, stats):
"""Init the class"""
logger.debug("ports plugin - Create thread for scan list {}".format(stats))
super(ThreadScanner, self).__init__()
# Event needed to stop properly the thread
self._stopper = threading.Event()
# The class return the stats as a list of dict
self._stats = stats
# Is part of Ports plugin
self.plugin_name = "ports"
def run(self):
"""Function called to grab stats.
Infinite loop, should be stopped by calling the stop() method"""
for p in self._stats:
self._port_scan(p)
if self.stopped():
break
# Had to wait between two scans
# If not, result are not ok
time.sleep(1)
@property
def stats(self):
"""Stats getter"""
return self._stats
@stats.setter
def stats(self, value):
"""Stats setter"""
self._stats = value
def stop(self, timeout=None):
"""Stop the thread"""
logger.debug("ports plugin - Close thread for scan list {}".format(self._stats))
self._stopper.set()
def stopped(self):
"""Return True is the thread is stopped"""
return self._stopper.isSet()
def _port_scan(self, port): def _port_scan(self, port):
"""Scan the port structure (dict) and update the status key""" """Scan the port structure (dict) and update the status key"""
...@@ -162,7 +235,6 @@ class Plugin(GlancesPlugin): ...@@ -162,7 +235,6 @@ class Plugin(GlancesPlugin):
except Exception as e: except Exception as e:
logger.debug("{0}: Error while pinging host ({2})".format(self.plugin_name, port['host'], e)) logger.debug("{0}: Error while pinging host ({2})".format(self.plugin_name, port['host'], e))
logger.info("Ping {} ({}) in {} second".format(port['host'], self._resolv_name(port['host']), port['status']))
return ret return ret
def _port_scan_tcp(self, port): def _port_scan_tcp(self, port):
...@@ -171,7 +243,7 @@ class Plugin(GlancesPlugin): ...@@ -171,7 +243,7 @@ class Plugin(GlancesPlugin):
# Create and configure the scanning socket # Create and configure the scanning socket
try: try:
socket.setdefaulttimeout(int(port['timeout'])) socket.setdefaulttimeout(port['timeout'])
_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except Exception as e: except Exception as e:
logger.debug("{0}: Error while creating scanning socket".format(self.plugin_name)) logger.debug("{0}: Error while creating scanning socket".format(self.plugin_name))
......
...@@ -61,8 +61,8 @@ class GlancesPortsList(object): ...@@ -61,8 +61,8 @@ class GlancesPortsList(object):
else: else:
logger.debug("Start reading the [%s] section in the configuration file" % self._section) logger.debug("Start reading the [%s] section in the configuration file" % self._section)
refresh = config.get_value(self._section, 'refresh', default=self._default_refresh) refresh = int(config.get_value(self._section, 'refresh', default=self._default_refresh))
timeout = config.get_value(self._section, 'timeout', default=self._default_timeout) timeout = int(config.get_value(self._section, 'timeout', default=self._default_timeout))
# Add default gateway on top of the ports_list lits # Add default gateway on top of the ports_list lits
default_gateway = config.get_value(self._section, 'port_default_gateway', default='False') default_gateway = config.get_value(self._section, 'port_default_gateway', default='False')
...@@ -75,6 +75,7 @@ class GlancesPortsList(object): ...@@ -75,6 +75,7 @@ class GlancesPortsList(object):
new_port['refresh'] = refresh new_port['refresh'] = refresh
new_port['timeout'] = timeout new_port['timeout'] = timeout
new_port['status'] = None new_port['status'] = None
new_port['rtt_warning'] = None
logger.debug("Add default gateway %s to the static list" % (new_port['host'])) logger.debug("Add default gateway %s to the static list" % (new_port['host']))
ports_list.append(new_port) ports_list.append(new_port)
...@@ -105,9 +106,17 @@ class GlancesPortsList(object): ...@@ -105,9 +106,17 @@ class GlancesPortsList(object):
new_port['refresh'] = refresh new_port['refresh'] = refresh
# Timeout in second # Timeout in second
new_port['timeout'] = config.get_value(self._section, new_port['timeout'] = int(config.get_value(self._section,
'%stimeout' % postfix, '%stimeout' % postfix,
default=timeout) default=timeout))
# RTT warning
new_port['rtt_warning'] = config.get_value(self._section,
'%srtt_warning' % postfix,
default=None)
if new_port['rtt_warning'] is not None:
# Convert to second
new_port['rtt_warning'] = int(new_port['rtt_warning']) / 1000.0
# Add the server to the list # Add the server to the list
logger.debug("Add port %s:%s to the static list" % (new_port['host'], new_port['port'])) logger.debug("Add port %s:%s to the static list" % (new_port['host'], new_port['port']))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册