#!/usr/bin/python import gobject import gtk import pango import gc import os from stat import * import datetime import getopt import sys import traceback # for address import socket import fcntl import struct import time import signal import Queue import textwrap # localization import gettext try: gettext.install("net_monitor") except IOError: _ = str from net_monitor import Monitor ifaces = {} HISTOGRAM_SIZE=50 # borrowed from gnome-network-monitor 0.9.1 (gnetworkmonitor.sourceforge.net) class LoadGraph: """ This class is able do display a nicely formatted graph if interface bandwidth load. """ # we don't want to allow the window to shrink below this height padding = { "left" : 50, "right" : 10, "top" : 10, "bottom" : 10 } colors = ( "bg", "bg_outer", "in", "out" ) def __init__(self, widget, hist, size, min_height=70, axes_text=_("Bytes"), draw_both=True, max=None, draw_legend = True, legend1=_("Upload"), legend2=_("Download")): """ widget => GtkDrawingArea we paint into hist => a list of integers containing the hist of incoming traffic width, height => initial size of the GtkDrawingArea widget """ # set the minimum height of the widget widget.set_size_request(-1, min_height) # the object holding the history and its size self.__hist = hist self.__size = size # strings holding 0, middle and max values for displayed graph self.__str_min = "0" self.__str_mid = "" # gets computed later self.__str_max = "" # gets computer later # axes descriptions self.axes_text = axes_text self.draw_legend = draw_legend self.legend1 = legend1 self.legend2 = legend2 # are we drawing both values? self.draw_both = draw_both # minimum and maximum values self.min = min self.max = max # size of the GtkDrawingArea self.__rect = self.__inner = gtk.gdk.Rectangle() self.maxval = 0 # maximum value in the history self.__mesh_x = self.__mesh_y = 0 # distance in pixels between items self.__get_max() self.__on_size(widget.get_allocation()) # save reference to the widget we paint into self.__widget = widget # lists holding bandwidth history mapped to actual coordinates self.__in = list() self.__out = list() self.__colors = dict() self.set_color(bg=(0, 0, 0), fg_in=(255, 0, 0), fg_out=(0, 255, 0)) self.__context = None def __set_context_color(self, con, col_tuple): """ Cleaner might be to extend the context class, but who cares? """ con.set_source_rgb(col_tuple[0], col_tuple[1], col_tuple[2]) def __draw(self): """ Strokes the rectangles and draws the curves """ if (self.__context == None): return # stroke the outer rectangle self.__context.rectangle(0, 0, self.__rect.width, self.__rect.height) self.__set_context_color(self.__context, self.__colors["bg"]) self.__context.fill_preserve() self.__context.stroke() # stroke the inner rectangle self.__context.rectangle(self.__inner.x, self.__inner.y, self.__inner.width, self.__inner.height) self.__set_context_color(self.__context, self.__colors["bg"]) self.__context.fill_preserve() self.__context.stroke() # stroke the quad around self.__context.move_to(self.__inner.x, self.__inner.y + self.__inner.height) self.__context.line_to(self.__inner.x, self.__inner.y) self.__context.line_to(self.__inner.x + self.__inner.width - self.__mesh_x, self.__inner.y) self.__context.line_to(self.__inner.x + self.__inner.width - self.__mesh_x, self.__inner.y + self.__inner.height) self.__set_context_color(self.__context, (255, 255, 255)) self.__context.stroke() # draw the actual bandwidth curves self.__draw_bw(self.__in, self.__colors["fg_in"]) if self.draw_both: self.__draw_bw(self.__out, self.__colors["fg_out"]) # draw legend if self.draw_legend: self.__draw_legend(self.__inner.y + 15, self.legend1, self.__colors["fg_in"]) if self.draw_both: self.__draw_legend(self.__inner.y + 25, self.legend2, self.__colors["fg_out"]) # draw minimum, middle and max numbers self.__draw_num(self.__inner.height + self.__inner.y, self.__str_min, (255, 255, 255)) self.__draw_num(self.__rect.height/2, self.__str_mid, (255, 255, 255)) self.__draw_num(self.__inner.y, self.__str_max, (255, 255, 255)) def __draw_num(self, ypos, num, color): """ The leftmost column is used to draw info about maximum, minimum and average bw """ self.__set_context_color(self.__context, color) self.__context.move_to(5, ypos) self.__context.show_text(num) self.__context.stroke() def __draw_legend(self, ypos, text, color): """ The rightmost column is used to draw graph legend """ text_length = self.__context.text_extents(text)[2] self.__context.move_to(self.__inner.x + self.__inner.width - text_length - 20, ypos) self.__context.show_text(text) self.__set_context_color(self.__context, color) self.__context.stroke() def __draw_bw(self, bw_list, color): """ Draws a curve from points stored in bw_list in color """ self.__context.move_to(self.__inner.x, self.__inner.y + self.__inner.height) self.__set_context_color(self.__context, color) x = self.__inner.x + self.__mesh_x for i in bw_list[1:]: self.__context.line_to(x, i) x += self.__mesh_x self.__context.stroke() def __convert_one_hist(self, hist): """ Maps values from one history object to real coordinates of the drawing area """ converted = list() if self.__mesh_y == 0: return [self.__inner.height + self.__inner.y] * len(hist) for item in hist: converted.append((self.__inner.height - int(item / self.__mesh_y)) + self.__inner.y) return converted def __convert_points(self): """ The bandwidth history object has the bandwidth stored as bytes. This method converts the bytes into actual coordiantes of the rectangle displayed """ # compute the aspect ratio self.__mesh_x = float(self.__inner.width) / float(self.__size) self.__mesh_y = float(self.maxval) / float(self.__inner.height) self.__in = self.__convert_one_hist(self.__hist["in"]) self.__out = self.__convert_one_hist(self.__hist["out"]) def __get_max(self): """ Finds the maximum value in both incoming and outgoing queue """ if self.max != None: self.maxval = self.max else: if self.__hist["in"]: maxin = max(self.__hist["in"]) else: maxin = 0 if self.__hist["out"]: maxout = max(self.__hist["out"]) else: maxout = 0 self.maxval = max(maxin, maxout) def __text_size(self): """ Computes the size of the text and thus the left border """ val = self.maxval if val == 0 and self.maxval != 0: val = self.maxval self.__str_max = "%d %s" % (val, self.axes_text) if val != val/2: self.__str_mid = "%d %s" % (val/2, self.axes_text) else: self.__str_mid = "" LoadGraph.padding["left"] = self.__context.text_extents(self.__str_max)[2] + 10 def __on_size(self, rect): """ rect => a rectangle holding the size of the widget """ self.__rect = rect self.__inner.x = LoadGraph.padding["left"] self.__inner.y = LoadGraph.padding["top"] self.__inner.width = rect.width - LoadGraph.padding["right"] - self.__inner.x self.__inner.height = rect.height - LoadGraph.padding["bottom"] - self.__inner.y self.__convert_points() def on_expose(self, widget, event): """ A signal handler that is called every time we need to redraw the widget """ self.__context = widget.window.cairo_create() self.__get_max() self.__text_size() self.__on_size(widget.get_allocation()) self.__draw() return False def set_history(self, hist): """ Called typically on change of interface displayed """ self.__hist = hist self.__convert_points() def update(self): """ Redraws the area """ alloc = self.__widget.get_allocation() self.__widget.queue_draw_area(0, 0, alloc.width, alloc.height) def change_colors(self, col_in = None, col_out = None): """ Sets the colors to draw the curves with """ if ( col_in ) : self.__colors["fg_in"] = col_in if ( col_out ) : self.__colors["fg_out"] = col_out def set_color(self, *args, **kwargs): """ Sets the colors of the graph """ for key, value in kwargs.items(): self.__colors[key] = value class MonitorGui: # icon pattern - icons are pulled from drakx-net ICON_PATTERN="/usr/share/libDrakX/pixmaps/%s-16.png" ICON_CONNECTED="/usr/share/libDrakX/pixmaps/connected.png" (COLUMN_PROTO, COLUMN_LOC_ADDR, COLUMN_LOC_PORT, COLUMN_REM_ADDR, COLUMN_REM_PORT, COLUMN_STATUS) = range(6) def __init__(self, default_iface=None): self.window = gtk.Window() self.window.set_title(_("Network monitor")) self.window.set_default_size(640, 440) self.window.connect('delete-event', lambda *w: gtk.main_quit()) self.main_vbox = gtk.VBox() self.window.add(self.main_vbox) # notebook self.notebook = gtk.Notebook() self.main_vbox.pack_start(self.notebook) #self.notebook.connect('switch-page', self.show_net_status) # monitor self.monitor = Monitor() self.ifaces = self.monitor.readnet() 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() net=self.monitor.readnet() select_page=0 for iface in sorted_ifaces: device_exists, data_in, data_out = self.monitor.get_traffic(iface,net) self.ifaces[iface] = {'data_in': 0, 'data_out': 0, 'total_in': 0, 'total_out': 0, 'widget_in': None, 'widget_out': None, 'widget_speed_in': None, 'widget_speed_out': None, 'graph': None, 'histogram': [], 'address': "", } iface_stat, iface_label = self.build_iface_stat(iface) cur_page = self.notebook.append_page(iface_stat, iface_label) if default_iface and iface == default_iface: select_page = cur_page if self.monitor.has_network_accounting(iface): self.enabled_ifaces.append(iface) # finally, we have tabs for network connections network_stat_label, network_stat, self.connections = self.build_network_stat() # refresh current connections self.refresh_connections(None) cur_page = self.notebook.append_page(network_stat, network_stat_label) # global statusbar self.statusbar = gtk.Statusbar() self.context_id = self.statusbar.get_context_id("Statusbar") self.main_vbox.pack_start(self.statusbar, False, False, padding=1) # add initial message self.statusbar.push(self.context_id, _("Please wait..")) # configure timer self.signals = Queue.Queue() gobject.timeout_add_seconds(1, self.update) self.window.show_all() # do we have to select a default interface? if select_page: self.notebook.set_current_page(select_page) def update_tray_info(self): """Updates tray information""" dns_servers = self.monitor.get_dns() if dns_servers: dns_message = ", ".join(dns_servers) else: dns_message = _("Not found") # routes routes, default_routes = self.monitor.get_routes() if default_routes: gw_message = ", ".join(["%s (%s)" % (gw, iface) for gw, iface in default_routes]) else: gw_message = _("Not found") tray_message = _("Default routes: %s; DNS: %s") % (gw_message, dns_message) self.statusbar.pop(self.context_id) self.statusbar.push(self.context_id, tray_message) 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() self.update_tray_info() for iface in self.ifaces: status = self.monitor.get_status(iface) old_data_in = self.ifaces[iface]['data_in'] old_data_out = self.ifaces[iface]['data_out'] total_in = self.ifaces[iface]['total_in'] total_out = self.ifaces[iface]['total_out'] device_exists, data_in, data_out = self.monitor.get_traffic(iface, net) # is it a wireless interface? if iface in self.wireless_ifaces: essid = self.monitor.wifi_get_essid(iface) mode = self.monitor.wifi_get_mode(iface) bitrate = self.monitor.wifi_get_bitrate(iface) ap = self.monitor.wifi_get_ap(iface) link = wifi_stats.get(iface, 0) # calculate link quality if "max_quality" in self.ifaces[iface]: max_quality = self.ifaces[iface]["max_quality"] if max_quality != 0: quality = link * 100.0 / max_quality else: quality = 0 else: quality = 0 else: essid = None mode = None bitrate = None ap = None quality = 0 # is it the first measure? if old_data_in == 0 and old_data_out == 0: old_data_in = data_in old_data_out = data_out # check if device exists if not device_exists: old_data_in = data_in old_data_out = data_out # check total download diff_in = data_in - old_data_in diff_out = data_out - old_data_out # checking for 32bits overflow if diff_in < 0: diff_in += 2**32 if diff_out < 0: diff_out += 2**32 total_in += diff_in total_out += diff_out # speed speed_in = diff_in / interval speed_out = diff_out / interval # update saved values self.ifaces[iface]['data_in'] = data_in self.ifaces[iface]['data_out'] = data_out self.ifaces[iface]['total_in'] = total_in self.ifaces[iface]['total_out'] = total_out # updating graphs for histogram, graph, value_in, value_out in [ ('histogram', 'graph', speed_in, speed_out), ('link_histogram', 'link_graph', quality, quality) ]: if histogram not in self.ifaces[iface] or graph not in self.ifaces[iface]: # skip invalid graphs continue # calculating histogram hist_in = self.ifaces[iface][histogram]['in'] hist_out = self.ifaces[iface][histogram]['out'] if hist_in: histo_in = reduce(lambda x, y: x+y, hist_in) / len(hist_in) else: histo_in = 0 if hist_out: histo_out = reduce(lambda x, y: x+y, hist_out) / len(hist_in) else: histo_out = 0 hist_in.append(value_in) if len(hist_in) > HISTOGRAM_SIZE: del hist_in[0] hist_out.append(value_out) if len(hist_out) > HISTOGRAM_SIZE: del hist_out[0] graph = self.ifaces[iface][graph] graph.update() # calculate average network traffic hist_in = self.ifaces[iface]['histogram']['in'] hist_out = self.ifaces[iface]['histogram']['out'] if hist_out: 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)), ('widget_out', self.monitor.format_size(total_out)), ('widget_speed_in', self.monitor.format_size(speed_in, "/s")), ('widget_speed_out', self.monitor.format_size(speed_out, "/s")), ('widget_ip_address', ip), ('widget_status', status), ('widget_hw_address', mac), ('widget_essid', essid), ('widget_mode', mode), ('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? if value.__class__ == tuple: pretty_size, pretty_bytes = value if pretty_size == pretty_bytes: value = pretty_size else: value = "%s (%s)" % (pretty_size, pretty_bytes) self.ifaces[iface][widget].set_text(str(value)) gobject.timeout_add_seconds(interval, self.update) def show_statistics_dialog(self, widget, iface): """Shows statistics dialog""" dialog = gtk.Dialog(_("Network statistics for %s") % iface, self.window, 0, (gtk.STOCK_OK, gtk.RESPONSE_OK) ) # statistics vbox stats_vbox = dialog.vbox if self.monitor.has_network_accounting(iface): # graph graph_vnstat = gtk.Image() pixbuf = self.load_graph_from_vnstat(iface, type="summary") graph_vnstat.set_from_pixbuf(pixbuf) stats_vbox.pack_start(graph_vnstat) # buttons frame = gtk.Frame(_("Network traffic statistics for %s") % iface) stats_vbox.add(frame) vbox = gtk.VBox() frame.add(vbox) # summary button = gtk.RadioButton(None, _("Summary")) button.connect('toggled', self.update_stat_iface, (iface, graph_vnstat, "summary")) vbox.pack_start(button, False, False) # summary button = gtk.RadioButton(button, _("Hourly traffic")) button.connect('toggled', self.update_stat_iface, (iface, graph_vnstat, "hourly")) vbox.pack_start(button, False, False) # summary button = gtk.RadioButton(button, _("Daily traffic")) button.connect('toggled', self.update_stat_iface, (iface, graph_vnstat, "daily")) vbox.pack_start(button, False, False) # summary button = gtk.RadioButton(button, _("Monthly traffic")) button.connect('toggled', self.update_stat_iface, (iface, graph_vnstat, "monthly")) vbox.pack_start(button, False, False) # summary button = gtk.RadioButton(button, _("Top 10 traffic days")) button.connect('toggled', self.update_stat_iface, (iface, graph_vnstat, "top")) vbox.pack_start(button, False, False) else: label = gtk.Label(_("Network accounting was not enabled on interface %s.\nPlease enable network accounting on the interface in order to view traffic statistics and restart your network connection to start collecting traffic statistics.")) stats_vbox.add(label) stats_vbox.show_all() ret = dialog.run() dialog.destroy() def refresh_connections(self, widget): """Updates connections""" lstore = self.connections lstore.clear() for proto in ["tcp", "udp"]: connections = self.monitor.get_connections(proto=proto) for loc_addr, loc_port, rem_addr, rem_port, status in connections: iter = lstore.append() lstore.set(iter, self.COLUMN_PROTO, proto, self.COLUMN_LOC_ADDR, loc_addr, self.COLUMN_LOC_PORT, loc_port, self.COLUMN_REM_ADDR, rem_addr, self.COLUMN_REM_PORT, rem_port, self.COLUMN_STATUS, status) def build_network_stat(self): """Builds graphical view for connections""" vbox = gtk.VBox() sw = gtk.ScrolledWindow() sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) sw.set_shadow_type(gtk.SHADOW_ETCHED_IN) lstore = gtk.ListStore( gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_STRING ) treeview = gtk.TreeView(lstore) treeview.set_rules_hint(True) treeview.set_search_column(self.COLUMN_LOC_ADDR) # treeview.connect('row-activated', self.expand_domain, lstore) # now building columns for c, descr in [ (self.COLUMN_PROTO, _("Protocol")), (self.COLUMN_LOC_ADDR, _("Local address")), (self.COLUMN_LOC_PORT, _("Local port")), (self.COLUMN_REM_ADDR, _("Remote address")), (self.COLUMN_REM_PORT, _("Remote port")), (self.COLUMN_STATUS, _("Connection status")) ]: renderer = gtk.CellRendererText() column = gtk.TreeViewColumn(descr, renderer, text=c) column.set_sort_column_id(c) column.set_resizable(True) column.set_expand(True) treeview.append_column(column) sw.add(treeview) # build tab label widget = gtk.HBox() try: icon = gtk.Image() pixbuf = gtk.gdk.pixbuf_new_from_file(self.ICON_CONNECTED) icon.set_from_pixbuf(pixbuf) widget.pack_start(icon) except: traceback.print_exc() widget.pack_start(gtk.Label(_("connections"))) widget.show_all() vbox.pack_start(sw) button = gtk.Button(_("Refresh")) button.connect('clicked', self.refresh_connections) vbox.pack_start(button, False, False) return widget, vbox, lstore def build_iface_stat(self, iface): """Builds graphical view for interface""" traf_vbox = gtk.VBox(spacing=5) # graph draw = gtk.DrawingArea() traf_vbox.pack_start(draw) histogram = {"in": [], "out": []} graph = LoadGraph(draw, histogram, HISTOGRAM_SIZE) draw.connect('expose_event', graph.on_expose) self.ifaces[iface]['graph'] = graph self.ifaces[iface]['histogram'] = histogram # configuring callbacks sizegroup1 = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) sizegroup2 = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) sizegroup3 = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) sizegroup4 = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) # traffic frame = gtk.Frame(_("Traffic statistics")) traf_vbox.pack_start(frame, False, False) table = gtk.Table(2, 2, False) frame.add(table) cur_row = 0 total_in_h, total_in = self.build_value_pair(sizegroup1, _("Downloaded:"), value_sizegroup=sizegroup2) self.ifaces[iface]["widget_in"] = total_in total_out_h, total_out = self.build_value_pair(sizegroup3, _("Uploaded:"), value_sizegroup=sizegroup4) self.ifaces[iface]["widget_out"] = total_out # speed speed_in_h, speed_in = self.build_value_pair(sizegroup1, _("Download speed:"), value_sizegroup=sizegroup2) self.ifaces[iface]["widget_speed_in"] = speed_in speed_out_h, speed_out = self.build_value_pair(sizegroup3, _("Upload speed:"), value_sizegroup=sizegroup4) self.ifaces[iface]["widget_speed_out"] = speed_out # pack items into table for items in [ [total_in_h, total_out_h], [speed_in_h, speed_out_h], ]: self.__add_row(table, cur_row, items) cur_row += 1 frame_global = gtk.Frame(_("Interface settings")) traf_vbox.pack_start(frame_global, False, False) table = gtk.Table(2, 2, False) frame_global.add(table) cur_row = 0 # interface iface_h, iface_p = self.build_value_pair(sizegroup1, _("Network interface:"), iface, value_sizegroup=sizegroup2) iface_s, iface_status = self.build_value_pair(sizegroup1, _("Device status:"), value_sizegroup=sizegroup2) self.ifaces[iface]["widget_status"] = iface_status iface_addr_s, iface_addr = self.build_value_pair(sizegroup3, _("IP Address:"), value_sizegroup=sizegroup4) self.ifaces[iface]["widget_ip_address"] = iface_addr iface_mac_s, iface_mac = self.build_value_pair(sizegroup3, _("Hardware address:"), value_sizegroup=sizegroup4) self.ifaces[iface]["widget_hw_address"] = iface_mac # pack items into table for items in [ [iface_h, iface_addr_s], [iface_s, iface_mac_s], ]: self.__add_row(table, cur_row, items) cur_row += 1 # wireless statistics if iface in self.wireless_ifaces: # essid essid_h, essid = self.build_value_pair(sizegroup1, _("Wireless ESSID:"), value_sizegroup=sizegroup2) self.ifaces[iface]["widget_essid"] = essid # mode mode_h, mode = self.build_value_pair(sizegroup3, _("Wireless mode:"), value_sizegroup=sizegroup4) self.ifaces[iface]["widget_mode"] = mode # bitrate bitrate_h, bitrate = self.build_value_pair(sizegroup1, _("Connection speed:"), value_sizegroup=sizegroup2) self.ifaces[iface]["widget_bitrate"] = bitrate # AP ap_h, ap = self.build_value_pair(sizegroup3, _("Access point or cell:"), value_sizegroup=sizegroup4) self.ifaces[iface]["widget_ap"] = ap # caching quality values self.ifaces[iface]["max_quality"] = self.monitor.wifi_get_max_quality(iface) # link quality info quality_h, quality = self.build_value_pair(sizegroup1, _("Link quality:"), value_sizegroup=sizegroup2) self.ifaces[iface]["quality"] = quality # link quality graph draw = gtk.DrawingArea() histogram = {"in": [], "out": []} graph = LoadGraph(draw, histogram, HISTOGRAM_SIZE, min_height=40, axes_text="%", draw_both=False, max=100, draw_legend=False) draw.connect('expose_event', graph.on_expose) self.ifaces[iface]['link_graph'] = graph self.ifaces[iface]['link_histogram'] = histogram # pack everything into table for items in [ [essid_h, mode_h], [bitrate_h, ap_h], [quality_h, draw], ]: self.__add_row(table, cur_row, items) cur_row += 1 # statistics button frame_accounting = gtk.Frame(_("Traffic accounting")) vbox = gtk.VBox() frame_accounting.add(vbox) if self.monitor.has_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) 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")))) vbox.pack_start(label, False, False) traf_vbox.pack_start(frame_accounting, False, False) # building notebook label icons traf_label = gtk.HBox(False, 2) if iface in self.wireless_ifaces: # wifi self.__load_interface_icon(traf_label, 'wireless') elif iface[:3] == 'ppp': # modem or peer-to-peer connection self.__load_interface_icon(traf_label, 'potsmodem') elif iface[:3] == 'eth': # ethernet self.__load_interface_icon(traf_label, 'ethernet') elif iface[:3] == 'pan': # ethernet self.__load_interface_icon(traf_label, 'bluetooth') traf_label.pack_start(gtk.Label(iface)) traf_label.show_all() return traf_vbox, traf_label def __load_interface_icon(self, widget, icon_title): """Loads interface icon""" try: icon = gtk.Image() pixbuf = gtk.gdk.pixbuf_new_from_file(self.ICON_PATTERN % icon_title) icon.set_from_pixbuf(pixbuf) widget.pack_start(icon) except: traceback.print_exc() def __add_row(self, table, row, items, markup=False, wrap=False): cur_pos = 1 for item in items: table.attach(item, cur_pos - 1, cur_pos, row, row + 1, gtk.EXPAND | gtk.FILL, 0, 0, 0) cur_pos += 1 def build_widget_pair(self, container, w1, w2): """Puts two widgets side-by-side""" # finding left and right vboxes from container vbox_left, vbox_right = container vbox_left.pack_start(w1, False, False) vbox_right.pack_start(w2, False, False) def build_value_pair(self, sizegroup, text, value_text=None, value_sizegroup=None): """Builds a value pair""" hbox = gtk.HBox(spacing=10) name = gtk.Label(text) name.set_property("xalign", 0.0) hbox.pack_start(name, False, False) value = gtk.Label(value_text) value.set_property("xalign", 0.0) hbox.pack_start(value, False, False) if sizegroup: sizegroup.add_widget(name) if value_sizegroup: value_sizegroup.add_widget(value) return hbox, value def update_stat_iface(self, widget, data): """Updates graphic statistics""" iface, graph, type = data pixbuf = self.load_graph_from_vnstat(iface, type) graph.set_from_pixbuf(pixbuf) def load_graph_from_vnstat(self, iface, type="hourly"): """Loads graph from vnstat. Right now uses vnstati to do all the dirty job""" # load image from data if type == "hourly": param="-h" elif type == "monthly": param="-m" elif type == "daily": param="-d" elif type == "top": param="-t" elif type == "summary": param="-s" else: # show summary if parameter is unknown print "Unknown parameter %s, showing summary.." % type param="-s" data = os.popen("vnstati %s -o - -i %s" % (param, iface)).read() loader = gtk.gdk.PixbufLoader() loader.write(data) loader.close() 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""" print """net_monitor: Mandriva network monitoring tool. Arguments to net_monitor: -h, --help displays this helpful message. -i, --defaultintf start monitoring the specified interface """ # }}} if __name__ == "__main__": # default monitoring interface iface = None # parse command line try: opt, args = getopt.getopt(sys.argv[1:], 'hi:', ['help', 'defaultintf=']) except getopt.error: usage() sys.exit(1) for o in opt: if o[0] == '-h' or o[0] == '--help': usage() sys.exit(0) 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()