From 92dd96726dd638593ab0794ab9b66cfb33b2ac67 Mon Sep 17 00:00:00 2001
From: Christian Poessinger <christian@poessinger.com>
Date: Tue, 21 Jul 2020 22:00:12 +0200
Subject: geneve: ifconfig: T2653: move to get_config_dict()

The current VyOS CLI parser code written in Python contains a ton of duplicates
which I can also hold myself accountable for - or maybe mainly me - depends on
the angle of judge.
---
 src/conf_mode/interfaces-geneve.py | 128 +++++++------------------------------
 1 file changed, 23 insertions(+), 105 deletions(-)

diff --git a/src/conf_mode/interfaces-geneve.py b/src/conf_mode/interfaces-geneve.py
index 31f6eb6b5..868ab5ccf 100755
--- a/src/conf_mode/interfaces-geneve.py
+++ b/src/conf_mode/interfaces-geneve.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-# Copyright (C) 2019 VyOS maintainers and contributors
+# Copyright (C) 2019-2020 VyOS maintainers and contributors
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 or later as
@@ -21,102 +21,44 @@ from copy import deepcopy
 from netifaces import interfaces
 
 from vyos.config import Config
+from vyos.configdict import get_interface_dict
+from vyos.configverify import verify_address
+from vyos.configverify import verify_bridge_delete
 from vyos.ifconfig import GeneveIf
-from vyos.validate import is_member
 from vyos import ConfigError
 
 from vyos import airbag
 airbag.enable()
 
-default_config_data = {
-    'address': [],
-    'deleted': False,
-    'description': '',
-    'disable': False,
-    'intf': '',
-    'ip_arp_cache_tmo': 30,
-    'ip_proxy_arp': 0,
-    'is_bridge_member': False,
-    'mtu': 1500,
-    'remote': '',
-    'vni': ''
-}
-
 def get_config():
-    geneve = deepcopy(default_config_data)
+    """
+    Retrive CLI config as dictionary. Dictionary can never be empty, as at least the
+    interface name will be added or a deleted flag
+    """
     conf = Config()
+    base = ['interfaces', 'geneve']
 
     # determine tagNode instance
     if 'VYOS_TAGNODE_VALUE' not in os.environ:
         raise ConfigError('Interface (VYOS_TAGNODE_VALUE) not specified')
 
-    geneve['intf'] = os.environ['VYOS_TAGNODE_VALUE']
-
-    # check if interface is member if a bridge
-    geneve['is_bridge_member'] = is_member(conf, geneve['intf'], 'bridge')
-
-    # Check if interface has been removed
-    if not conf.exists('interfaces geneve ' + geneve['intf']):
-        geneve['deleted'] = True
-        return geneve
-
-    # set new configuration level
-    conf.set_level('interfaces geneve ' + geneve['intf'])
-
-    # retrieve configured interface addresses
-    if conf.exists('address'):
-        geneve['address'] = conf.return_values('address')
-
-    # retrieve interface description
-    if conf.exists('description'):
-        geneve['description'] = conf.return_value('description')
-
-    # Disable this interface
-    if conf.exists('disable'):
-        geneve['disable'] = True
-
-    # ARP cache entry timeout in seconds
-    if conf.exists('ip arp-cache-timeout'):
-        geneve['ip_arp_cache_tmo'] = int(conf.return_value('ip arp-cache-timeout'))
-
-    # Enable proxy-arp on this interface
-    if conf.exists('ip enable-proxy-arp'):
-        geneve['ip_proxy_arp'] = 1
-
-    # Maximum Transmission Unit (MTU)
-    if conf.exists('mtu'):
-        geneve['mtu'] = int(conf.return_value('mtu'))
-
-    # Remote address of GENEVE tunnel
-    if conf.exists('remote'):
-        geneve['remote'] = conf.return_value('remote')
-
-    # Virtual Network Identifier
-    if conf.exists('vni'):
-        geneve['vni'] = conf.return_value('vni')
+    ifname = os.environ['VYOS_TAGNODE_VALUE']
+    geneve = get_interface_dict(conf, base, ifname)
 
     return geneve
 
-
 def verify(geneve):
-    if geneve['deleted']:
-        if geneve['is_bridge_member']:
-            raise ConfigError((
-                f'Cannot delete interface "{geneve["intf"]}" as it is a '
-                f'member of bridge "{geneve["is_bridge_member"]}"!'))
-
+    if 'deleted' in geneve:
+        verify_bridge_delete(geneve)
         return None
 
-    if geneve['is_bridge_member'] and geneve['address']:
-        raise ConfigError((
-            f'Cannot assign address to interface "{geneve["intf"]}" '
-            f'as it is a member of bridge "{geneve["is_bridge_member"]}"!'))
+    verify_address(geneve)
 
-    if not geneve['remote']:
-        raise ConfigError('GENEVE remote must be configured')
+    if 'remote' not in geneve:
+        raise ConfigError('Remote side must be configured')
 
-    if not geneve['vni']:
-        raise ConfigError('GENEVE VNI must be configured')
+    if 'vni' not in geneve:
+        raise ConfigError('VNI must be configured')
 
     return None
 
@@ -127,13 +69,13 @@ def generate(geneve):
 
 def apply(geneve):
     # Check if GENEVE interface already exists
-    if geneve['intf'] in interfaces():
-        g = GeneveIf(geneve['intf'])
+    if geneve['ifname'] in interfaces():
+        g = GeneveIf(geneve['ifname'])
         # GENEVE is super picky and the tunnel always needs to be recreated,
         # thus we can simply always delete it first.
         g.remove()
 
-    if not geneve['deleted']:
+    if 'deleted' not in geneve:
         # GENEVE interface needs to be created on-block
         # instead of passing a ton of arguments, I just use a dict
         # that is managed by vyos.ifconfig
@@ -144,32 +86,8 @@ def apply(geneve):
         conf['remote'] = geneve['remote']
 
         # Finally create the new interface
-        g = GeneveIf(geneve['intf'], **conf)
-        # update interface description used e.g. by SNMP
-        g.set_alias(geneve['description'])
-        # Maximum Transfer Unit (MTU)
-        g.set_mtu(geneve['mtu'])
-
-        # configure ARP cache timeout in milliseconds
-        g.set_arp_cache_tmo(geneve['ip_arp_cache_tmo'])
-        # Enable proxy-arp on this interface
-        g.set_proxy_arp(geneve['ip_proxy_arp'])
-
-        # Configure interface address(es) - no need to implicitly delete the
-        # old addresses as they have already been removed by deleting the
-        # interface above
-        for addr in geneve['address']:
-            g.add_addr(addr)
-
-        # As the GENEVE interface is always disabled first when changing
-        # parameters we will only re-enable the interface if it is not
-        # administratively disabled
-        if not geneve['disable']:
-            g.set_admin_state('up')
-
-        # re-add ourselves to any bridge we might have fallen out of
-        if geneve['is_bridge_member']:
-            g.add_to_bridge(geneve['is_bridge_member'])
+        g = GeneveIf(geneve['ifname'], **conf)
+        g.update(geneve)
 
     return None
 
-- 
cgit v1.2.3