diff options
| author | Christian Poessinger <christian@poessinger.com> | 2020-07-19 10:51:00 +0200 | 
|---|---|---|
| committer | Christian Poessinger <christian@poessinger.com> | 2020-07-19 10:51:00 +0200 | 
| commit | dadb09fd14046720e7898c3cbad8c5def408db9d (patch) | |
| tree | aefae9962f7fdfe2969ab7483f64a1a6dbc90b4f /src | |
| parent | daa810f81ce03cc0f51dfd810507d4b2c9ec0428 (diff) | |
| download | vyos-1x-dadb09fd14046720e7898c3cbad8c5def408db9d.tar.gz vyos-1x-dadb09fd14046720e7898c3cbad8c5def408db9d.zip | |
broadcast-relay: T2712: migrate to get_config_dict()
Add additional verify() stage to check that the relaying interface actually
exists on the system.
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/bcast_relay.py | 135 | 
1 files changed, 34 insertions, 101 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 | 
