提交 a340a5e5 编写于 作者: N nicolargo

Finalize New Ports Scanner plugin (issue#734)

上级 3b5e1144
......@@ -38,6 +38,13 @@ Bugs corrected:
* On Windows, Glances try to display unexisting Load stats (issue #871)
* 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
=============
......
......@@ -181,29 +181,31 @@ mem_critical=90
[ports]
# Ports scanner plugin configuration
# Interval in second between scan
# Interval in second between two scans
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
# 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
# Define the scan list
# host (name or IP) is mandatory
# port (TCP port number) is optional (if not set, use ICMP)
# description is optional (if not set, define to host:port)
port_1_host=192.168.0.1
port_1_port=80
port_1_description=Home Box
port_2_host=www.free.fr
port_2_description=My ISP
port_3_host=www.google.com
port_3_description=Internet ICMP
port_4_host=www.google.com
port_4_description=Internet Web
port_4_port=80
port_5_host=blog.nicolargo.com
port_5_description=My blog
port_5_port=80
# Define the scan list (1 < x < 255)
# port_x_host (name or IP) is mandatory
# port_x_port (TCP port number) is optional (if not set, use ICMP)
# 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_port=80
#port_1_description=Home Box
#port_1_timeout=1
#port_2_host=www.free.fr
#port_2_description=My ISP
#port_3_host=www.google.com
#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
##############################################################################
# Client/server
......
......@@ -17,20 +17,28 @@ The list should be define in the ``[ports]`` section of the Glances configuratio
[ports]
# Ports scanner plugin configuration
# Interval in second between scan
# Interval in second between two scans
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
# 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
# Define the scan list
# host (name or IP) is mandatory
# port (TCP port number) is optional (if not set, use ICMP)
# description is optional (if not set, define to host:port)
# Define the scan list (1 < x < 255)
# port_x_host (name or IP) is mandatory
# port_x_port (TCP port number) is optional (if not set, use ICMP)
# 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_port=80
port_1_description=Home Box
port_1_timeout=1
port_2_host=www.free.fr
port_2_description=My ISP
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):
def exit(self):
"""Overwrite the exit method to close threads"""
logger.debug("Stop the Docker plugin")
for t in itervalues(self.thread_list):
t.stop()
# Call the father class
super(Plugin, self).exit()
def get_key(self):
"""Return the key of the list."""
......
......@@ -24,6 +24,7 @@ import subprocess
import threading
import socket
import types
import time
from glances.globals import WINDOWS
from glances.ports_list import GlancesPortsList
......@@ -51,6 +52,16 @@ class Plugin(GlancesPlugin):
# Init global Timer
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
def update(self):
"""Update the ports list."""
......@@ -59,14 +70,20 @@ class Plugin(GlancesPlugin):
return {}
if self.input_method == 'local':
# Only refresh every refresh seconds (define in the configuration file)
if self.timer_ports.finished():
# Only refresh:
# * 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
thread = threading.Thread(target=self._port_scan_all, args=(self.stats,))
thread.start()
self._thread = ThreadScanner(self.stats)
self._thread.start()
# Restart timer
if len(self.stats) > 0:
self.timer_ports = Timer(int(self.stats[0]['refresh']))
self.timer_ports = Timer(self.stats[0]['refresh'])
else:
self.timer_ports = Timer(0)
else:
......@@ -80,9 +97,12 @@ class Plugin(GlancesPlugin):
if port['status'] is None:
return 'CAREFUL'
if port['status'] == 0:
elif port['status'] == 0:
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'
......@@ -125,6 +145,59 @@ class Plugin(GlancesPlugin):
"""Scan all host/port of the given stats"""
for p in stats:
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):
"""Scan the port structure (dict) and update the status key"""
......@@ -162,7 +235,6 @@ class Plugin(GlancesPlugin):
except Exception as 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
def _port_scan_tcp(self, port):
......@@ -171,7 +243,7 @@ class Plugin(GlancesPlugin):
# Create and configure the scanning socket
try:
socket.setdefaulttimeout(int(port['timeout']))
socket.setdefaulttimeout(port['timeout'])
_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except Exception as e:
logger.debug("{0}: Error while creating scanning socket".format(self.plugin_name))
......
......@@ -61,8 +61,8 @@ class GlancesPortsList(object):
else:
logger.debug("Start reading the [%s] section in the configuration file" % self._section)
refresh = config.get_value(self._section, 'refresh', default=self._default_refresh)
timeout = config.get_value(self._section, 'timeout', default=self._default_timeout)
refresh = int(config.get_value(self._section, 'refresh', default=self._default_refresh))
timeout = int(config.get_value(self._section, 'timeout', default=self._default_timeout))
# Add default gateway on top of the ports_list lits
default_gateway = config.get_value(self._section, 'port_default_gateway', default='False')
......@@ -75,6 +75,7 @@ class GlancesPortsList(object):
new_port['refresh'] = refresh
new_port['timeout'] = timeout
new_port['status'] = None
new_port['rtt_warning'] = None
logger.debug("Add default gateway %s to the static list" % (new_port['host']))
ports_list.append(new_port)
......@@ -105,9 +106,17 @@ class GlancesPortsList(object):
new_port['refresh'] = refresh
# Timeout in second
new_port['timeout'] = config.get_value(self._section,
'%stimeout' % postfix,
default=timeout)
new_port['timeout'] = int(config.get_value(self._section,
'%stimeout' % postfix,
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
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.
先完成此消息的编辑!
想要评论请 注册