Improve IP plugin to display public IP address #646

This commit is contained in:
nicolargo 2016-04-02 15:38:32 +02:00
parent cfbb1e3fc3
commit 33d01bf586
5 changed files with 68 additions and 2 deletions

1
NEWS
View File

@ -7,6 +7,7 @@ Version 2.7
Enhancements and new features:
* Improve IP plugin to display public IP address (issue #646)
* CPU additionnal stats monitoring: Context switch, Interrupts... (issue #810)
* [Folders] Differentiate permission issue and non-existence of a directory (issue #828)
* [Web UI] add cpu name in quicklook plugin (issue #825)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -6,7 +6,7 @@ Header
.. image:: ../_static/header.png
The header shows the hostname, OS name, release version, platform
architecture and system uptime (on the upper right corner).
architecture IP addresses (private and public) and system uptime.
Additionally, on GNU/Linux, it also shows the kernel version.
In client mode, the server connection status is also displayed.

View File

@ -31,6 +31,8 @@ if PY3:
from configparser import ConfigParser, NoOptionError, NoSectionError
from xmlrpc.client import Fault, ProtocolError, ServerProxy, Transport
from xmlrpc.server import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
from urllib.request import urlopen
from urllib.error import URLError
input = input
range = range
@ -79,6 +81,7 @@ else:
from ConfigParser import SafeConfigParser as ConfigParser, NoOptionError, NoSectionError
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
from xmlrpclib import Fault, ProtocolError, ServerProxy, Transport
from urllib2 import urlopen, URLError
input = raw_input
range = xrange

View File

@ -19,9 +19,14 @@
"""IP plugin."""
from glances.compat import iterkeys
import Queue
import threading
from json import load
from glances.compat import iterkeys, urlopen, URLError
from glances.globals import BSD
from glances.logger import logger
from glances.timer import Timer
from glances.plugins.glances_plugin import GlancesPlugin
# XXX *BSDs: Segmentation fault (core dumped)
@ -35,6 +40,16 @@ if not BSD:
else:
netifaces_tag = False
# List of online services to retreive public IP address
# List of tuple (url, json, key)
# - url: URL of the Web site
# - json: service return a JSON (True) or string (False)
# - key: key of the IP addresse in the JSON structure
urls = [('http://ip.42.pl/raw', False, None),
('http://httpbin.org/ip', True, 'origin'),
('http://jsonip.com', True, 'ip'),
('https://api.ipify.org/?format=json', True, 'ip')]
class Plugin(GlancesPlugin):
@ -50,6 +65,9 @@ class Plugin(GlancesPlugin):
# We want to display the stat in the curse interface
self.display_curse = True
# Get the public IP address once
self.public_address = PublicIpAddress().get()
# Init the stats
self.reset()
@ -78,6 +96,8 @@ class Plugin(GlancesPlugin):
self.stats['mask'] = netifaces.ifaddresses(default_gw[1])[netifaces.AF_INET][0]['netmask']
self.stats['mask_cidr'] = self.ip_to_cidr(self.stats['mask'])
self.stats['gateway'] = netifaces.gateways()['default'][netifaces.AF_INET][0]
# !!! SHOULD be done once, not on each refresh
self.stats['public_address'] = self.public_address
except (KeyError, AttributeError) as e:
logger.debug("Cannot grab IP information: {0}".format(e))
elif self.input_method == 'snmp':
@ -115,6 +135,11 @@ class Plugin(GlancesPlugin):
ret.append(self.curse_add_line(msg, 'TITLE'))
msg = '{0:}/{1}'.format(self.stats['address'], self.stats['mask_cidr'])
ret.append(self.curse_add_line(msg))
if self.stats['public_address'] is not None:
msg = ' Pub '
ret.append(self.curse_add_line(msg, 'TITLE'))
msg = '{0:}'.format(self.stats['public_address'])
ret.append(self.curse_add_line(msg))
return ret
@ -125,3 +150,40 @@ class Plugin(GlancesPlugin):
Example: '255.255.255.0' will return 24
"""
return sum([int(x) << 8 for x in ip.split('.')]) // 8128
class PublicIpAddress(object):
"""Get public IP address from online services"""
def __init__(self, timeout=2):
self.timeout = timeout
def get(self):
"""Get the first public IP address returned by one of the online services"""
q = Queue.Queue()
for u, j, k in urls:
t = threading.Thread(target=self._get_ip_public, args=(q, u, j, k))
t.daemon = True
t.start()
t = Timer(self.timeout)
ip = None
while not t.finished() and ip is None:
if q.qsize() > 0:
ip = q.get()
return ip
def _get_ip_public(self, queue, url, json=False, key=None):
"""Request the url service and put the result in the queue"""
try:
u = urlopen(url, timeout=self.timeout)
except URLError:
queue.put(None)
else:
# Request depend on service
if not json:
queue.put(u.read())
else:
queue.put(load(u)[key])