From 92e6795b249b4282eb2028b981de731bf9913417 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Mon, 1 Mar 2010 18:21:33 -0300 Subject: implement connection uptime monitoring --- scripts/netmonitor_down | 2 +- scripts/netmonitor_up | 2 +- src/monitor.py | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ src/net_monitor | 37 +++++++++++++++++++++++--- 4 files changed, 106 insertions(+), 5 deletions(-) diff --git a/scripts/netmonitor_down b/scripts/netmonitor_down index 6ce6064..8782ef7 100755 --- a/scripts/netmonitor_down +++ b/scripts/netmonitor_down @@ -6,6 +6,6 @@ if [ -r /etc/sysconfig/network-scripts/ifcfg-$1 ]; then . /etc/sysconfig/network-scripts/ifcfg-$1 if [ "a$ACCOUNTING" = "ayes" ]; then - echo $1:DOWN:$(date +%s) >> /var/log/net_monitor + echo $1:DOWN:$(date +%s) >> /var/log/net_monitor.log fi fi diff --git a/scripts/netmonitor_up b/scripts/netmonitor_up index a0cba3f..4012bf2 100755 --- a/scripts/netmonitor_up +++ b/scripts/netmonitor_up @@ -6,6 +6,6 @@ if [ -r /etc/sysconfig/network-scripts/ifcfg-$1 ]; then . /etc/sysconfig/network-scripts/ifcfg-$1 if [ "a$ACCOUNTING" = "ayes" ]; then - echo $1:UP:$(date +%s) >> /var/log/net_monitor + echo $1:UP:$(date +%s) >> /var/log/net_monitor.log fi fi diff --git a/src/monitor.py b/src/monitor.py index 72408b3..a7e7f76 100644 --- a/src/monitor.py +++ b/src/monitor.py @@ -7,6 +7,7 @@ import fcntl import struct import traceback import array +import time # native library implements a few bits import _native @@ -15,6 +16,9 @@ import _native class Monitor: # based on http://svn.pardus.org.tr/pardus/tags/pardus-1.0/system/base/wireless-tools/comar/link.py + # network uptime log file + LOGFILE="/var/log/net_monitor.log" + # wireless IOCTL constants SIOCGIWMODE = 0x8B07 # get operation mode SIOCGIWRATE = 0x8B21 # get default bit rate @@ -31,6 +35,7 @@ class Monitor: def __init__(self): self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.net = {} + self.uptime_log = {} def ioctl(self, func, params): return fcntl.ioctl(self.sock.fileno(), func, params) @@ -231,3 +236,68 @@ class Monitor: pass return routes, default_routes + def load_uptime_log(self): + """Loads network uptime log, handled by /etc/sysconfig/network-scripts/if{up,down}.d/netprofile*""" + self.uptime_log = {} + if not os.access(self.LOGFILE, os.F_OK): + # no log file + return + with open(self.LOGFILE) as fd: + data = fd.readlines() + + for l in data: + dev, status, secs = l.strip().split(":") + secs = int(secs) + if dev not in self.uptime_log: + self.uptime_log[dev] = {"uptime": None, "log": []} + self.uptime_log[dev]["log"].append((secs, status)) + + # now reload the last uptime data + for i in self.uptime_log: + self.calc_uptime(i) + + def calc_uptime(self, iface): + """Calculates uptime data for an interface""" + if iface not in self.uptime_log: + self.uptime_log[iface]["uptime"] = -1 + return + # ok, interface is there, calculate last uptime status + last_up=0 + last_down=0 + for s, status in self.uptime_log[iface]["log"]: + if status == "UP": + last_up = s + elif status == "DOWN": + last_down = s + + # now get the uptime + # is the device up and running? + if not last_up: + self.uptime_log[iface]["uptime"] = -1 + return + + # was the interface disconnected? + if last_down > last_up: + self.uptime_log[iface]["uptime"] = 0 + return + + # ok, we are up and running, lets get the uptime + self.uptime_log[iface]["uptime"] = last_up + + def get_uptime(self, iface): + """Determines interface uptime""" + if iface not in self.uptime_log: + return _("Unknown") + uptime = self.uptime_log[iface]["uptime"] + if uptime < 0: + return _("Unknown") + elif uptime == 0: + # device is offline + return _("Device is offline") + else: + curtime = int(time.time()) + uptime = curtime - uptime + mins = uptime / 60.0 + hours = mins / 60.0 + secs = uptime % 60 + return _("%d hours, %d minutes, %d seconds") % (hours, mins, secs) diff --git a/src/net_monitor b/src/net_monitor index 44dacf7..45a94ad 100755 --- a/src/net_monitor +++ b/src/net_monitor @@ -18,6 +18,8 @@ import fcntl import struct import time +import signal +import Queue import textwrap @@ -295,6 +297,9 @@ class MonitorGui: self.enabled_ifaces = [] self.wireless_ifaces = filter(self.monitor.has_wireless, self.ifaces.keys()) + # load uptime log + self.monitor.load_uptime_log() + sorted_ifaces = self.ifaces.keys() sorted_ifaces.sort() @@ -330,6 +335,7 @@ class MonitorGui: self.statusbar.push(self.context_id, _("Please wait..")) # configure timer + self.signals = Queue.Queue() gobject.timeout_add(1000, self.update) self.window.show_all() @@ -357,6 +363,8 @@ class MonitorGui: def update(self, interval=1): """Updates traffic counters (interval is in seconds)""" + # check for pending signals + self.check_signals() # TODO: move it to Monitor()? net=self.monitor.readnet() wifi_stats = self.monitor.wireless_stats() @@ -446,6 +454,8 @@ class MonitorGui: histo_out = reduce(lambda x, y: x+y, hist_out) / len(hist_in) else: histo_out = 0 + # get the uptime + uptime = self.monitor.get_uptime(iface) # update widgets ip, mac = self.monitor.get_address(iface) for widget, value in [('widget_in', self.monitor.format_size(total_in)), @@ -460,6 +470,7 @@ class MonitorGui: ('widget_bitrate', bitrate), ('widget_ap', ap), ('quality', "%d%%" % quality), + ('widget_uptime', uptime), ]: if widget in self.ifaces[iface]: # is it absolute value or pretty-formatted number? @@ -591,7 +602,7 @@ class MonitorGui: # pack items into table for items in [ [iface_h, iface_addr_s], - [iface_s, iface_mac_s] + [iface_s, iface_mac_s], ]: self.__add_row(table, cur_row, items) cur_row += 1 @@ -637,13 +648,20 @@ class MonitorGui: cur_row += 1 # statistics button + frame_accounting = gtk.Frame(_("Traffic accounting")) + vbox = gtk.VBox() + frame_accounting.add(vbox) if self.check_network_accounting(iface): + iface_u, iface_uptime = self.build_value_pair(sizegroup1, _("Connection time:")) + self.ifaces[iface]["widget_uptime"] = iface_uptime + vbox.pack_start(iface_u, False, False) button = gtk.Button(_("Show detailed network statistics")) button.connect('clicked', self.show_statistics_dialog, iface) - traf_vbox.pack_start(button, False, False) + vbox.pack_start(button, False, False) else: label = gtk.Label("\n".join(textwrap.wrap(_("Network accounting is not enabled for this interface. Please enable it in Mandriva network center in order to view detailed traffic statistics")))) - traf_vbox.pack_start(label, False, False) + vbox.pack_start(label, False, False) + traf_vbox.pack_start(frame_accounting, False, False) # building notebook label icons traf_label = gtk.HBox(False, 2) @@ -733,6 +751,18 @@ class MonitorGui: pixbuf = loader.get_pixbuf() return pixbuf + def check_signals(self): + """Checks for received signals""" + if not self.signals.empty(): + s = self.signals.get() + if s == signal.SIGHUP: + # reload network configuration + self.monitor.load_uptime_log() + + def queue_update(self, s): + """Queue update for network devices""" + self.signals.put(s) + # {{{ usage def usage(): """Prints help message""" @@ -760,4 +790,5 @@ if __name__ == "__main__": elif o[0] == '-i' or o[0] == '--defaultintf': iface = o[1] monitor = MonitorGui(default_iface=iface) + signal.signal(signal.SIGHUP, lambda s, f: monitor.queue_update(s)) gtk.main() -- cgit v1.2.1