diff --git a/netjsonconfig/backends/openwrt/converters/__init__.py b/netjsonconfig/backends/openwrt/converters/__init__.py index 5993c2b83..69dee0808 100644 --- a/netjsonconfig/backends/openwrt/converters/__init__.py +++ b/netjsonconfig/backends/openwrt/converters/__init__.py @@ -2,6 +2,7 @@ from .general import General from .interfaces import Interfaces from .led import Led +from .mwan3 import Mwan3 from .ntp import Ntp from .openvpn import OpenVpn from .radios import Radios @@ -24,4 +25,5 @@ 'Switch', 'WireguardPeers', 'Wireless', + 'Mwan3', ] diff --git a/netjsonconfig/backends/openwrt/converters/mwan3.py b/netjsonconfig/backends/openwrt/converters/mwan3.py new file mode 100644 index 000000000..a3b0278cb --- /dev/null +++ b/netjsonconfig/backends/openwrt/converters/mwan3.py @@ -0,0 +1,45 @@ +from collections import OrderedDict + +from ..schema import schema +from .base import OpenWrtConverter + + +class Mwan3(OpenWrtConverter): + netjson_key = 'mwan3' + intermediate_key = 'mwan3' + _uci_types = ['interface'] + _schema = schema['properties']['mwan3'] + + def to_intermediate_loop(self, block, result, index=None): + interfaces = self.__intermediate_interfaces(block.pop('interfaces', {})) + result.setdefault('mwan3', []) + result['mwan3'] = interfaces + return result + + def __intermediate_interfaces(self, interfaces): + """ + converts NetJSON interface to + UCI intermediate data structure + """ + result = [] + for interface in interfaces: + resultdict = OrderedDict( + ( + ('.name', self._get_uci_name(interface.pop('name'))), + ('.type', 'interface'), + ) + ) + resultdict.update(interface) + result.append(resultdict) + return result + + def to_netjson_loop(self, block, result, index): + result['mwan3'] = self.__netjson_mwan3(block) + return result + + def __netjson_mwan3(self, mwan3): + del mwan3['.type'] + _name = mwan3.pop('.name') + if _name != 'mwan3': + mwan3['id'] = _name + return self.type_cast(mwan3) diff --git a/netjsonconfig/backends/openwrt/openwrt.py b/netjsonconfig/backends/openwrt/openwrt.py index 1f156e00b..2e1650b56 100644 --- a/netjsonconfig/backends/openwrt/openwrt.py +++ b/netjsonconfig/backends/openwrt/openwrt.py @@ -25,6 +25,7 @@ class OpenWrt(BaseBackend): converters.Wireless, converters.OpenVpn, converters.WireguardPeers, + converters.Mwan3, converters.Default, ] parser = OpenWrtParser diff --git a/netjsonconfig/backends/openwrt/schema.py b/netjsonconfig/backends/openwrt/schema.py index bf2ffd9d4..5e4c23beb 100644 --- a/netjsonconfig/backends/openwrt/schema.py +++ b/netjsonconfig/backends/openwrt/schema.py @@ -928,6 +928,197 @@ }, }, }, + "mwan3": { + "type": "object", + "title": "Mwan3", + "additionalProperties": True, + "propertyOrder": 11, + "properties": { + "interfaces": { + "type": "array", + "title": "Interfaces", + "propertyOrder": 1, + "items": { + "type": "object", + "title": "Interface", + "additionalProperties": True, + "required": [ + "name", + "track_ip", + ], + "properties": { + "name": { + "type": "string", + "title": "Name", + "description": "the OpenWrt interface name", + "propertyOrder": 1, + }, + "enabled": { + "type": "boolean", + "title": "Enabled", + "description": "specifies wether mwan3 should run on this interface", + "default": False, + "format": "checkbox", + "propertyOrder": 2, + }, + "track_method": { + "type": "string", + "title": "Tracking method", + "description": "Tracking method for mwan3track", + "enum": ["ping", "arping", "httping", "nping-*"], + "default": "ping", + "propertyOrder": 3, + }, + "track_ip": { + "title": "Tracking IPs", + "description": "List of IPs to ping to test the interface. If this list " + "is empty then the interface is always considered up", + "type": "array", + "uniqueItems": True, + "additionalItems": True, + "items": { + "type": "string", + "title": "ipv4 address", + "minLength": 7, + "maxLength": 15, + "format": "ipv4", + }, + "propertyOrder": 4, + }, + "reliability": { + "type": "integer", + "title": "Reliability", + "description": "Number of track_ip hosts that must reply for the test to" + " be considered successful. Ensure there are at least this" + " many track_ip hosts defined or the interface will always" + " be considered down", + "default": 1, + "propertyOrder": 5, + }, + "count": { + "type": "integer", + "title": "Count", + "description": "Number of checks to send to each host with each test", + "default": 1, + "propertyOrder": 6, + }, + "timeout": { + "type": "integer", + "title": "Timeout", + "description": "Number of seconds to wait for an echo-reply after an " + "echo-request", + "default": 4, + "propertyOrder": 7, + }, + "interval": { + "type": "integer", + "title": "Interval", + "description": "Number of seconds between each test", + "default": 10, + "propertyOrder": 8, + }, + "failure_interval": { + "type": "integer", + "title": "Failure interval", + "description": "Number of seconds between each test during teardown on " + "failure detection", + "propertyOrder": 9, + }, + "recovery_interval": { + "type": "integer", + "title": "Recovery interval", + "description": "Number of seconds between each test during tearup on " + "recovery detection", + "propertyOrder": 10, + }, + "keep_failure_interval": { + "type": "boolean", + "title": "Keep failure interval", + "description": "In the event of an error, keep the number of seconds " + "between each test during teardown (failure detection)", + "default": False, + "format": "checkbox", + "propertyOrder": 11, + }, + "up": { + "type": "integer", + "title": "Up", + "description": "Number of successful tests to consider link as alive", + "default": 5, + "propertyOrder": 12, + }, + "down": { + "type": "integer", + "title": "Down", + "description": "Number of failed tests to consider link as dead", + "default": 5, + "propertyOrder": 13, + }, + "family": { + "type": "string", + "title": "Family", + "description": "", + "enum": [ + "ipv4", + "ipv6", + ], + "default": "ipv4", + "propertyOrder": 14, + }, + "max_ttl": { + "type": "integer", + "title": "Time to live", + "description": "Time to live (TTL) or hop limit. Only valid if tracking " + "method is ping.", + "default": 60, + "propertyOrder": 15, + }, + "initial_state": { + "type": "string", + "title": "Initial state", + "description": "If the value is offline, then traffic goes via this " + "interface only if mwan3track checked the connection " + "first. If the value is online, then the mwan3track " + "test is not waited for. The interface is marked as " + "online at once.", + "enum": [ + "online", + "offline", + ], + "default": "online", + "propertyOrder": 16, + }, + "size": { + "type": "integer", + "title": "Size", + "description": "Size of ping packets to use in bytes. Only valid if " + "tracking method is ping.", + "default": 56, + "propertyOrder": 17, + }, + "flush_conntrack": { + "title": "Flush connection tracking", + "description": "specifies upon which events the connections table should" + " be flushed", + "type": "array", + "uniqueItems": True, + "additionalItems": True, + "items": { + "type": "string", + "enum": [ + "ifup", + "ifdown", + "connected", + "disconnected", + ], + }, + "propertyOrder": 18, + }, + }, + }, + } + }, + }, }, }, )