Source code for debinterface.interfacesWriter

# -*- coding: utf-8 -*-
# Write interface
from __future__ import print_function, with_statement, absolute_import
import shutil
import os
from string import Template

from . import toolutils


[docs]class InterfacesWriter(object): """ Short lived class to write interfaces file """ # Define templetes for blocks used in /etc/network/interfaces. _auto = Template('auto $name\n') _hotplug = Template('allow-hotplug $name\n') _iface = Template('iface $name $addrFam $source\n') _cmd = Template('\t$varient $value\n') _comment = Template('# $line\n') _addressFields = [ 'address', 'network', 'netmask', 'broadcast', 'gateway', 'dns-nameservers', 'dns-search' ] _prepFields = ['pre-up', 'up', 'down', 'pre-down', 'post-down'] _bridgeFields = ['ports', 'fd', 'hello', 'maxage', 'stp', 'maxwait'] _plugins = ['hostapd', 'wpa-conf'] def __init__(self, adapters, interfaces_path, backup_path=None, header_comment=None): """ if backup_path is None => no backup """ self._adapters = adapters self._interfaces_path = interfaces_path self._backup_path = backup_path try: is_str = isinstance(header_comment, basestring) except NameError: is_str = isinstance(header_comment, str) if is_str: self._header_comment = header_comment else: self._header_comment = None @property def adapters(self): return self._adapters @adapters.setter def adapters(self, value): self._adapters = value
[docs] def write_interfaces(self): # Back up the old interfaces file. self._backup_interfaces() try: # Prepare to write the new interfaces file. with toolutils.atomic_write(self._interfaces_path) as interfaces: # Write any header comments. self._write_header_comment(interfaces) # Loop through the provided networkAdaprers and # write the new file. for adapter in self._adapters: # Get dict of details about the adapter. self._write_adapter(interfaces, adapter) self._check_interfaces(self._interfaces_path) except Exception: # Any error, let's roll back self._restore_interfaces() raise
[docs] def _check_interfaces(self, interfaces_path): """Uses ifup to check interfaces file. If it is not in the default place, each interface must be checked one by one. Args: interfaces_path (string) : the path to interfaces file Raises: ValueError : if invalid network interfaces """ ret = False output = "" if not self._adapters: return if interfaces_path == "/etc/network/interfaces": ret, output = toolutils.safe_subprocess([ "/sbin/ifup", "-a", "--no-act" ]) else: for adapter in self._adapters: ret, output = toolutils.safe_subprocess([ "/sbin/ifup", "--no-act", "--interfaces={0}".format(interfaces_path), adapter.attributes["name"] ]) if not ret: break if not ret: raise ValueError("Invalid network interfaces file " "written to disk, restoring to previous " "one : {0}".format(output))
def _write_header_comment(self, interfaces): if self._header_comment: for line in self._header_comment.split('\n'): # Check the beginning of the line for a comment field # if it does not exist, add it. if line[:2] != "# ": line = self._comment.substitute(line=line) else: # split strips the newline, add it back line = line + '\n' interfaces.write(line) # Create a blank line between comment and start of interfaces interfaces.write('\n') def _write_adapter(self, interfaces, adapter): try: adapter.validateAll() except ValueError as e: print(repr(e)) raise ifAttributes = adapter.export() self._write_auto(interfaces, adapter, ifAttributes) self._write_hotplug(interfaces, adapter, ifAttributes) self._write_addrFam(interfaces, adapter, ifAttributes) self._write_addressing(interfaces, adapter, ifAttributes) self._write_bridge(interfaces, adapter, ifAttributes) self._write_plugins(interfaces, adapter, ifAttributes) self._write_callbacks(interfaces, adapter, ifAttributes) self._write_unknown(interfaces, adapter, ifAttributes) interfaces.write("\n")
[docs] def _write_auto(self, interfaces, adapter, ifAttributes): """ Write if applicable """ try: if adapter.attributes['auto'] is True: d = dict(name=ifAttributes['name']) interfaces.write(self._auto.substitute(d)) except KeyError: pass
[docs] def _write_hotplug(self, interfaces, adapter, ifAttributes): """ Write if applicable """ try: if ifAttributes['hotplug'] is True: d = dict(name=ifAttributes['name']) interfaces.write(self._hotplug.substitute(d)) except KeyError: pass
[docs] def _write_addrFam(self, interfaces, adapter, ifAttributes): """ Construct and write the iface declaration. The addrFam clause needs a little more processing. """ # Write the source clause. # Will not error if omitted. Maybe not the best plan. try: if (not ifAttributes["name"] or not ifAttributes["addrFam"] or not ifAttributes["source"]): raise ValueError("Invalid field content") d = dict(name=ifAttributes['name'], addrFam=ifAttributes['addrFam'], source=ifAttributes['source']) interfaces.write(self._iface.substitute(d)) except KeyError: pass
def _write_addressing(self, interfaces, adapter, ifAttributes): for field in self._addressFields: try: value = ifAttributes[field] if value and value != 'None': if isinstance(value, list): d = dict(varient=field, value=" ".join(ifAttributes[field])) else: d = dict(varient=field, value=ifAttributes[field]) interfaces.write(self._cmd.substitute(d)) # Keep going if a field isn't provided. except KeyError: pass
[docs] def _write_bridge(self, interfaces, adapter, ifAttributes): """ Write the bridge information. """ for field in self._bridgeFields: try: value = ifAttributes['bridge-opts'][field] if value and value != 'None': d = dict(varient="bridge_" + field, value=value) interfaces.write(self._cmd.substitute(d)) # Keep going if a field isn't provided. except KeyError: pass
[docs] def _write_callbacks(self, interfaces, adapter, ifAttributes): """ Write the up, down, pre-up, and post-down clauses. """ for field in self._prepFields: try: for item in ifAttributes[field]: if item and item != 'None': d = dict(varient=field, value=item) interfaces.write(self._cmd.substitute(d)) except KeyError: # Keep going if a field isn't provided. pass
[docs] def _write_plugins(self, interfaces, adapter, ifAttributes): """ Write plugins options, currently hostapd. """ for field in self._plugins: try: if field in ifAttributes and ifAttributes[field] != 'None': d = dict(varient=field, value=ifAttributes[field]) interfaces.write(self._cmd.substitute(d)) # Keep going if a field isn't provided. except KeyError: pass
[docs] def _write_unknown(self, interfaces, adapter, ifAttributes): """ Write unknowns options """ try: for k, v in ifAttributes['unknown'].items(): if v: d = dict(varient=k, value=str(v)) interfaces.write(self._cmd.substitute(d)) except (KeyError, ValueError): pass
[docs] def _backup_interfaces(self): """Backup interfaces file is the file exists Returns: True/False, command output Raises: IOError : if the copy fails and the source file exists """ try: if self._backup_path: shutil.copy(self._interfaces_path, self._backup_path) except IOError as ex: # Only raise if source actually exists if os.path.exists(self._interfaces_path): raise ex
[docs] def _restore_interfaces(self): """Restore interfaces file is the file exists Returns: True/False, command output Raises: IOError : if the copy fails and the source file exists """ try: if self._backup_path: shutil.copy(self._backup_path, self._interfaces_path) except IOError as ex: # Only raise if source actually exists if os.path.exists(self._backup_path): raise ex