diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/conf_mode/bcast_relay.py | 135 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-pseudo-ethernet.py | 11 |
2 files changed, 41 insertions, 105 deletions
diff --git a/src/conf_mode/bcast_relay.py b/src/conf_mode/bcast_relay.py index 5c7294296..a3e141a00 100755 --- a/src/conf_mode/bcast_relay.py +++ b/src/conf_mode/bcast_relay.py @@ -15,151 +15,84 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -import fnmatch +from glob import glob +from netifaces import interfaces from sys import exit -from copy import deepcopy from vyos.config import Config -from vyos import ConfigError from vyos.util import call from vyos.template import render - +from vyos import ConfigError from vyos import airbag airbag.enable() -config_file = r'/etc/default/udp-broadcast-relay' - -default_config_data = { - 'disabled': False, - 'instances': [] -} +config_file_base = r'/etc/default/udp-broadcast-relay' def get_config(): - relay = deepcopy(default_config_data) conf = Config() base = ['service', 'broadcast-relay'] - if not conf.exists(base): - return None - else: - conf.set_level(base) - - # Service can be disabled by user - if conf.exists('disable'): - relay['disabled'] = True - return relay - - # Parse configuration of each individual instance - if conf.exists('id'): - for id in conf.list_nodes('id'): - conf.set_level(base + ['id', id]) - config = { - 'id': id, - 'disabled': False, - 'address': '', - 'description': '', - 'interfaces': [], - 'port': '' - } - - # Check if individual broadcast relay service is disabled - if conf.exists(['disable']): - config['disabled'] = True - - # Source IP of forwarded packets, if empty original senders address is used - if conf.exists(['address']): - config['address'] = conf.return_value(['address']) - - # A description for each individual broadcast relay service - if conf.exists(['description']): - config['description'] = conf.return_value(['description']) - - # UDP port to listen on for broadcast frames - if conf.exists(['port']): - config['port'] = conf.return_value(['port']) - - # Network interfaces to listen on for broadcast frames to be relayed - if conf.exists(['interface']): - config['interfaces'] = conf.return_values(['interface']) - - relay['instances'].append(config) - + relay = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True) return relay def verify(relay): - if relay is None: - return None - - if relay['disabled']: + if not relay or 'disabled' in relay: return None - for r in relay['instances']: + for instance, config in relay.get('id', {}).items(): # we don't have to check this instance when it's disabled - if r['disabled']: + if 'disabled' in config: continue # we certainly require a UDP port to listen to - if not r['port']: - raise ConfigError('UDP broadcast relay "{0}" requires a port number'.format(r['id'])) + if 'port' not in config: + raise ConfigError(f'Port number mandatory for udp broadcast relay "{instance}"') + # if only oone interface is given it's a string -> move to list + if isinstance(config.get('interface', []), str): + config['interface'] = [ config['interface'] ] # Relaying data without two interface is kinda senseless ... - if len(r['interfaces']) < 2: - raise ConfigError('UDP broadcast relay "id {0}" requires at least 2 interfaces'.format(r['id'])) + if len(config.get('interface', [])) < 2: + raise ConfigError('At least two interfaces are required for udp broadcast relay "{instance}"') - return None + for interface in config.get('interface', []): + if interface not in interfaces(): + raise ConfigError('Interface "{interface}" does not exist!') + return None def generate(relay): - if relay is None: + if not relay or 'disabled' in relay: return None - config_dir = os.path.dirname(config_file) - config_filename = os.path.basename(config_file) - active_configs = [] - - for config in fnmatch.filter(os.listdir(config_dir), config_filename + '*'): - # determine prefix length to identify service instance - prefix_len = len(config_filename) - active_configs.append(config[prefix_len:]) - - # sort our list - active_configs.sort() + for config in glob(config_file_base + '*'): + os.remove(config) - # delete old configuration files - for id in active_configs[:]: - if os.path.exists(config_file + id): - os.unlink(config_file + id) - - # If the service is disabled, we can bail out here - if relay['disabled']: - print('Warning: UDP broadcast relay service will be deactivated because it is disabled') - return None - - for r in relay['instances']: - # Skip writing instance config when it's disabled - if r['disabled']: + for instance, config in relay.get('id').items(): + # we don't have to check this instance when it's disabled + if 'disabled' in config: continue - # configuration filename contains instance id - file = config_file + str(r['id']) - render(file, 'bcast-relay/udp-broadcast-relay.tmpl', r) + config['instance'] = instance + render(config_file_base + instance, 'bcast-relay/udp-broadcast-relay.tmpl', config) return None def apply(relay): # first stop all running services - call('systemctl stop udp-broadcast-relay@{1..99}.service') + call('systemctl stop udp-broadcast-relay@*.service') - if (relay is None) or relay['disabled']: + if not relay or 'disable' in relay: return None # start only required service instances - for r in relay['instances']: - # Don't start individual instance when it's disabled - if r['disabled']: + for instance, config in relay.get('id').items(): + # we don't have to check this instance when it's disabled + if 'disabled' in config: continue - call('systemctl start udp-broadcast-relay@{0}.service'.format(r['id'])) + + call(f'systemctl start udp-broadcast-relay@{instance}.service') return None diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py index 70710e97c..fb8237bee 100755 --- a/src/conf_mode/interfaces-pseudo-ethernet.py +++ b/src/conf_mode/interfaces-pseudo-ethernet.py @@ -36,7 +36,7 @@ default_config_data = { 'ip_arp_cache_tmo': 30, 'ip_proxy_arp_pvlan': 0, 'source_interface': '', - 'source_interface_changed': False, + 'recreating_required': False, 'mode': 'private', 'vif_s': {}, 'vif_s_remove': [], @@ -79,11 +79,14 @@ def get_config(): peth['source_interface'] = conf.return_value(['source-interface']) tmp = conf.return_effective_value(['source-interface']) if tmp != peth['source_interface']: - peth['source_interface_changed'] = True + peth['recreating_required'] = True # MACvlan mode if conf.exists(['mode']): peth['mode'] = conf.return_value(['mode']) + tmp = conf.return_effective_value(['mode']) + if tmp != peth['mode']: + peth['recreating_required'] = True add_to_dict(conf, disabled, peth, 'vif', 'vif') add_to_dict(conf, disabled, peth, 'vif-s', 'vif_s') @@ -139,10 +142,10 @@ def apply(peth): return None # Check if MACVLAN interface already exists. Parameters like the underlaying - # source-interface device can not be changed on the fly and the interface + # source-interface device or mode can not be changed on the fly and the interface # needs to be recreated from the bottom. if peth['intf'] in interfaces(): - if peth['source_interface_changed']: + if peth['recreating_required']: MACVLANIf(peth['intf']).remove() # MACVLAN interface needs to be created on-block instead of passing a ton |