From 0845cc57b2dfaab366b4a8a81371dc6ac52b32ca Mon Sep 17 00:00:00 2001 From: Peter Keresztes Schmidt Date: Sat, 11 Sep 2021 22:26:08 +0200 Subject: [PATCH] networkinterfaces: support source-directory statement ifupdown supports the "source-directory" statement that include the content of the specified directory. See [1] for details. Implement the statement to improve compatibility with ifupdown. Fixes #191 [1] https://manpages.debian.org/buster/ifupdown/interfaces.5.en.html --- ifupdown2/ifupdown/networkinterfaces.py | 42 +++++++++++++++++++------ 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/ifupdown2/ifupdown/networkinterfaces.py b/ifupdown2/ifupdown/networkinterfaces.py index c16a3c3..ce47e8d 100644 --- a/ifupdown2/ifupdown/networkinterfaces.py +++ b/ifupdown2/ifupdown/networkinterfaces.py @@ -7,11 +7,12 @@ # ifupdown network interfaces file parser # -import re +import collections import copy import glob import logging -import collections +import os +import re try: from ifupdown2.ifupdown.iface import * @@ -176,6 +177,21 @@ class networkInterfaces(): 'unable to read source line') return 0 + def process_source_directory(self, lines, cur_idx, lineno): + self.logger.debug('processing source-directory line ..\'%s\'' % lines[cur_idx]) + sourced_directory = re.split(self._ws_split_regex, lines[cur_idx], 2)[1] + if sourced_directory: + folders = glob.glob(sourced_directory) + for folder in folders: + filenames = [file for file in os.listdir(folder) if re.match(r'^[a-zA-Z0-9_-]+$', file)] + + for f in filenames: + self.read_file(os.path.join(folder, f)) + else: + self._parse_error(self._currentfile, lineno, + 'unable to read source-directory line') + return 0 + def process_auto(self, lines, cur_idx, lineno): auto_ifaces = re.split(self._ws_split_regex, lines[cur_idx])[1:] if not auto_ifaces: @@ -388,11 +404,14 @@ class networkInterfaces(): return lines_consumed # Return next index - network_elems = { 'source' : process_source, - 'allow' : process_allow, - 'auto' : process_auto, - 'iface' : process_iface, - 'vlan' : process_vlan} + network_elems = { + 'source': process_source, + 'source-directory': process_source_directory, + 'allow': process_allow, + 'auto': process_auto, + 'iface': process_iface, + 'vlan': process_vlan + } def _is_keyword(self, str): # The additional split here is for allow- keyword @@ -401,9 +420,12 @@ class networkInterfaces(): return 1 return 0 - def _get_keyword_func(self, str): - tmp_str = str.split('-')[0] - return self.network_elems.get(tmp_str) + def _get_keyword_func(self, str_): + tmp_str = str_.split('-')[0] + if tmp_str == "allow": + return self.network_elems.get(tmp_str) + else: + return self.network_elems.get(str_) def get_allow_classes_for_iface(self, ifacename): classes = [] -- 2.39.5