Skip to content

Commit

Permalink
Added library ifcfg to support FreeBSD and OSX
Browse files Browse the repository at this point in the history
  • Loading branch information
bendikro committed Sep 28, 2015
1 parent 8246aee commit f4513d2
Show file tree
Hide file tree
Showing 11 changed files with 403 additions and 27 deletions.
40 changes: 27 additions & 13 deletions ifacewatch/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# of this program with the OpenSSL library. See LICENSE for more details.
#

import platform

import deluge.common
import deluge.component as component
Expand All @@ -17,6 +18,7 @@
import ifacewatch.util.common
import ifacewatch.util.logger
from ifacewatch.ifacewatch_config import IfacewatchConfig
from ifacewatch.lib import ifcfg
from ifacewatch.lib.pyiface.iface import Interface
from ifacewatch.util.common import IfaceWatchIPChangedEvent

Expand All @@ -35,12 +37,13 @@ def __init__(self, name):
self.config = None
self.ip = None
self.log = ifacewatch.util.logger.Logger()
self.log.info("Core init", gtkui=True)
self.core = component.get("Core")
self.core.config.register_set_function("listen_interface", self.interface_changed)

def interface_changed(self, iface, ip):
component.get("EventManager").emit(IfaceWatchIPChangedEvent(ip))
def emit(ip):
component.get("EventManager").emit(IfaceWatchIPChangedEvent(ip))
emit(ip)

def enable(self, config=None):
if config is None:
Expand All @@ -52,48 +55,59 @@ def enable(self, config=None):
self.scheduler_timer()
self.check_interface()

def scheduler_timer(self):
def stop_timer(self):
if self.timer:
if self.timer.running:
self.timer.stop()
else:
self.timer = LoopingCall(self.check_interface)

def scheduler_timer(self):
self.stop_timer()
self.timer = LoopingCall(self.check_interface)

interval = int(self.config.get_config()["update_interval"])
if self.config.get_config()["active"]:
self.timer.start(interval * 6, now=True) # Multiply to get seconds
self.timer.start(interval * 60, now=True) # Multiply to get seconds
self.log.info("Scheduling watch with interval %s." %
self.config.get_config()["update_interval"], gtkui=True)
else:
self.log.info("Watch mode disabled", gtkui=True)

def disable(self):
self.config.save()
self.stop_timer()

def update(self):
pass

def check_interface(self, *args, **kwargs):
if self.config is None:
return
return True
prev_ip = self.ip
self.ip = None
iface = self.config.get_config()["interface"]

if iface.strip():
try:
iff = Interface(name=str(iface))
self.ip = iff.ip_str()
if not deluge.common.is_ip(self.ip):
for interface in ifcfg.interfaces().itervalues():
if interface["device"] == iface:
self.ip = interface["inet"]
break
if self.ip is None and platform.system() == "Linux":
iff = Interface(name=str(iface))
self.ip = iff.ip_str()
if self.ip is not None and not deluge.common.is_ip(self.ip):
self.log.info("Invalid IP returned for interface '%s': %s" % (iface, self.ip), gtkui=True)
self.ip = None
except TypeError as e:
self.log.error("TypeError: %s" % e, gtkui=True)

if self.ip is None:
return True
else:
self.ip = ""
iface = "<all>"

if self.ip is None:
return True

has_changed = prev_ip != self.ip

if prev_ip is not None and has_changed:
Expand Down Expand Up @@ -123,7 +137,7 @@ def save_config(self, config):
newstate = config["active"] != self.config.get_config()["active"]
self.config.set_config(config)
if newstate and config["active"] is True:
self.log.info("Watch mode enabled")
self.log.info("Watch mode enabled", gtkui=True)
if newiface:
self.check_interface()
if newinterval or newstate:
Expand Down
4 changes: 2 additions & 2 deletions ifacewatch/data/ifacewatch.glade
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_checkbutton_active_toggled" swapped="no"/>
<signal name="toggled" handler="on_checkbutton_active_toggled"/>
</widget>
<packing>
<property name="expand">False</property>
Expand All @@ -48,7 +48,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_button_update_iface_clicked" swapped="no"/>
<signal name="clicked" handler="on_button_update_iface_clicked"/>
</widget>
<packing>
<property name="expand">False</property>
Expand Down
17 changes: 12 additions & 5 deletions ifacewatch/gtkui/gtkui.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class GtkUI(GtkPluginBase):
def enable(self):
self.create_ui()
self.on_show_prefs() # Necessary for the first time when the plugin is installed
client.register_event_handler("IfaceWatchLogMessageEvent", self.cb_on_log_message_arrived_event)
client.register_event_handler("IfaceWatchLogMessageEvent", self.cb_on_log_message_event)
client.register_event_handler("IfaceWatchIPChangedEvent", self.cb_get_ip)

def disable(self):
Expand All @@ -42,7 +42,7 @@ def create_ui(self):
component.get("Preferences").add_page("IfaceWatch", box)
component.get("PluginManager").register_hook("on_apply_prefs", self.on_apply_prefs)
component.get("PluginManager").register_hook("on_show_prefs", self.on_show_prefs)
self.gtkui_log = GTKUILogger(self.glade.get_widget('textview_log'))
self.gtkui_log = GTKUILogger(self.glade.get_widget("textview_log"))
self.log = Logger(gtkui_logger=self.gtkui_log)

###############################
Expand All @@ -67,9 +67,9 @@ def on_apply_prefs(self):
def on_show_prefs(self):
"""Called when showing preferences window"""
client.ifacewatch.get_config().addCallback(self.cb_get_config)
client.ifacewatch.get_ip().addCallback(self.cb_get_ip)
client.ifacewatch.get_ip().addCallback(self.update_ip)

def cb_on_log_message_arrived_event(self, message):
def cb_on_log_message_event(self, message):
"""Callback function called on GtkUILogMessageEvent events"""
self.gtkui_log.gtkui_log_message(message)

Expand All @@ -83,5 +83,12 @@ def cb_get_config(self, config):
self.glade.get_widget("checkbutton_active").set_active(config['active'])

def cb_get_ip(self, ip):
self.update_ip(ip)

def update_ip(self, ip):
self.glade.get_widget("label_IP_value").set_text(ip)
component.get("Preferences").glade.get_widget("entry_interface").set_text(ip)
main_prefs = component.get("Preferences")
if hasattr(main_prefs, "glade"):
main_prefs.glade.get_widget("entry_interface").set_text(ip)
else:
main_prefs.builder.get_object("entry_interface").set_text(ip)
70 changes: 70 additions & 0 deletions ifacewatch/lib/ifcfg/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@

import platform
from . import meta
from . import parser
from . import tools
from . import exc

Log = tools.minimal_logger(__name__)

def get_parser(**kw):
"""
Detect the proper parser class, and return it instantiated.
Optional Arguments:
parser
The parser class to use instead of detecting the proper one.
distro
The distro to parse for (used for testing).
kernel
The kernel to parse for (used for testing).
ifconfig
The ifconfig (stdout) to pass to the parser (used for testing).
"""
parser = kw.get('parser', None)
ifconfig = kw.get('ifconfig', None)
if not parser:
distro = kw.get('distro', platform.system())
full_kernel = kw.get('kernel', platform.uname()[2])
kernel = '.'.join(full_kernel.split('.')[0:2])

if distro == 'Linux':
if float(kernel) < 3.3:
from .parser import Linux2Parser as LinuxParser
else:
from .parser import LinuxParser
parser = LinuxParser(ifconfig=ifconfig)
elif distro in ['Darwin', 'MacOSX']:
from .parser import MacOSXParser
parser = MacOSXParser(ifconfig=ifconfig)
elif distro in ['FreeBSD']:
from .parser import FreeBSDParser
parser = FreeBSDParser(ifconfig=ifconfig)
else:
raise exc.IfcfgParserError("Unknown distro type '%s'." % distro)

Log.debug("Distro detected as '%s'" % distro)
Log.debug("Using '%s'" % parser)
return parser

def interfaces():
"""
Return just the parsed interfaces dictionary from the proper parser.
"""
parser = get_parser()
return parser.interfaces

def default_interface():
"""
Return just the default interface device dictionary.
"""
parser = get_parser()
return parser.default_interface

10 changes: 10 additions & 0 deletions ifacewatch/lib/ifcfg/exc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

class IfcfgError(Exception):
"""Generic Ifcfg Errors."""
def __init__(self, msg):
self.msg = msg

class IfcfgParserError(IfcfgError):
"""Ifcfg Parsing Errors."""
def __init__(self, *args, **kw):
super(IfcfgParserError, self).__init__(*args, **kw)
44 changes: 44 additions & 0 deletions ifacewatch/lib/ifcfg/meta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Ifcfg core meta functionality. Barrowed from http://slumber.in/."""

class Meta(object):
"""
Model that acts as a container class for a meta attributes for a larger
class. It stuffs any kwarg it gets in it's init as an attribute of itself.
"""

def __init__(self, **kw):
self._merge(kw)

def _merge(self, dict_obj):
for key, value in dict_obj.items():
setattr(self, key, value)

class MetaMixin(object):
"""
Mixin that provides the Meta class support to add settings to instances
of slumber objects. Meta settings cannot start with a _.
"""

def __init__(self, *args, **kw):
# Get a List of all the Classes we in our MRO, find any attribute named
# Meta on them, and then merge them together in order of MRO
metas = reversed([x.Meta for x in self.__class__.mro() \
if hasattr(x, "Meta")])
final_meta = {}

# Merge the Meta classes into one dict
for meta in metas:
final_meta.update(dict([x for x in list(meta.__dict__.items()) \
if not x[0].startswith("_")]))

# Update the final Meta with any kw passed in
for key in list(final_meta.keys()):
if key in kw:
final_meta[key] = kw.pop(key)

self._meta = Meta(**final_meta)

# FIX ME: object.__init__() doesn't take params without exception
super(MetaMixin, self).__init__()
Loading

0 comments on commit f4513d2

Please sign in to comment.