diff --git a/addons/address.py b/addons/address.py index 3a04ed6..7c0c826 100644 --- a/addons/address.py +++ b/addons/address.py @@ -29,18 +29,18 @@ class address(moduleBase): 'attrs': { 'address' : {'help' : 'ipv4 or ipv6 addresses', - 'validvals' : [IPv4Network, IPv6Network], + 'validvals' : ['', ''], 'multiline' : True, 'example' : ['address 10.0.12.3/24', 'address 2000:1000:1000:1000:3::5/128']}, 'netmask' : {'help': 'netmask', - 'validvals' : [IPv4Address, ], + 'validvals' : ['', ], 'example' : ['netmask 255.255.255.0'], 'compat' : True}, 'broadcast' : {'help': 'broadcast address', - 'validvals' : [IPv4Address, ], + 'validvals' : ['', ], 'example' : ['broadcast 10.0.1.255']}, 'scope' : {'help': 'scope', @@ -53,7 +53,7 @@ class address(moduleBase): 'preferred-lifetime 10']}, 'gateway' : {'help': 'default gateway', - 'validvals' : [IPv4Address, IPv6Address], + 'validvals' : ['', ''], 'example' : ['gateway 255.255.255.0']}, 'mtu' : { 'help': 'interface mtu', @@ -80,7 +80,7 @@ class address(moduleBase): 'clagd-vxlan-anycast-ip' : { 'help' : 'Anycast local IP address for ' + 'dual connected VxLANs', - 'validvals' : [IPv4Address, ], + 'validvals' : ['', ], 'example' : ['clagd-vxlan-anycast-ip 36.0.0.11']}}} def __init__(self, *args, **kargs): diff --git a/addons/addressvirtual.py b/addons/addressvirtual.py index a994a7f..71efbe2 100644 --- a/addons/addressvirtual.py +++ b/addons/addressvirtual.py @@ -25,8 +25,8 @@ class addressvirtual(moduleBase): 'every mac ip address-virtual line', 'attrs' : { 'address-virtual' : - { 'help' : 'bridge router virtual mac and ip', - 'validvals' : [('', IPv4Network), ], + { 'help' : 'bridge router virtual mac and ips', + 'validvals' : ['',], 'example' : ['address-virtual 00:11:22:33:44:01 11.0.1.1/24 11.0.1.2/24']} }} diff --git a/addons/bond.py b/addons/bond.py index 35fa52f..5fb3a45 100644 --- a/addons/bond.py +++ b/addons/bond.py @@ -80,12 +80,14 @@ class bond(moduleBase): 'bond-ad-sys-mac-addr': {'help' : '802.3ad system mac address', 'default' : '00:00:00:00:00:00', + 'validvals': ['', ], 'example' : ['bond-ad-sys-mac-addr 00:00:00:00:00:00'], 'deprecated' : True, 'new-attribute' : 'bond-ad-actor-system'}, 'bond-ad-actor-system': {'help' : '802.3ad system mac address', 'default' : '00:00:00:00:00:00', + 'validvals': ['', ], 'example' : ['bond-ad-actor-system 00:00:00:00:00:00'],}, 'bond-lacp-bypass-allow': {'help' : 'allow lacp bypass', @@ -96,6 +98,7 @@ class bond(moduleBase): {'help' : 'bond slaves', 'required' : True, 'multivalue' : True, + 'validvals': [''], 'example' : ['bond-slaves swp1 swp2', 'bond-slaves glob swp1-2', 'bond-slaves regex (swp[1|2)']}}} @@ -188,20 +191,6 @@ class bond(moduleBase): ifname=ifaceobj.name, attr=attrname) if attrval: - msg = ('%s: invalid value %s for attr %s.' - %(ifaceobj.name, attrval, attrname)) - optiondict = self.get_mod_attr(attrname) - if not optiondict: - return None - validvals = optiondict.get('validvals') - if validvals and attrval not in validvals: - raise Exception(msg + ' Valid values are %s' %str(validvals)) - validrange = optiondict.get('validrange') - if validrange: - if (int(attrval) < int(validrange[0]) or - int(attrval) > int(validrange[1])): - raise Exception(msg + ' Valid range is [%s,%s]' - %(validrange[0], validrange[1])) if attrname == 'bond-mode': attrval = bond._get_readable_bond_mode(attrval) if attrval == '802.3ad': diff --git a/addons/bridge.py b/addons/bridge.py index 8242afe..d07cd9f 100644 --- a/addons/bridge.py +++ b/addons/bridge.py @@ -42,6 +42,7 @@ class bridge(moduleBase): {'help' : 'bridge ports', 'multivalue' : True, 'required' : True, + 'validvals': [''], 'example' : ['bridge-ports swp1.100 swp2.100 swp3.100', 'bridge-ports glob swp1-3.100', 'bridge-ports regex (swp[1|2|3].100)']}, @@ -85,12 +86,14 @@ class bridge(moduleBase): 'default' : '20'}, 'bridge-pathcosts' : { 'help' : 'bridge set port path costs', + 'validvals': [''], 'validrange' : ['0', '65535'], 'example' : ['under the bridge: bridge-pathcosts swp1=100 swp2=100', 'under the port (recommended): bridge-pathcosts 100'], 'default' : '100'}, 'bridge-portprios' : { 'help' : 'bridge port prios', + 'validvals': [''], 'validrange' : ['0', '65535'], 'example' : ['under the bridge: bridge-portprios swp1=32 swp2=32', 'under the port (recommended): bridge-portprios 32'], @@ -173,12 +176,13 @@ class bridge(moduleBase): 'example' : ['bridge-mcqv4src 100=172.16.100.1 101=172.16.101.1']}, 'bridge-portmcrouter' : { 'help' : 'set port multicast routers', - 'validvals' : ['yes', 'no', '0', '1'], + 'validvals' : [''], 'default' : 'yes', 'example' : ['under the bridge: bridge-portmcrouter swp1=yes swp2=yes', 'under the port (recommended): bridge-portmcrouter yes']}, 'bridge-portmcfl' : { 'help' : 'port multicast fast leave.', + 'validvals': [''], 'validrange' : ['0', '65535'], 'default' : '0', 'example' : ['under the bridge: bridge-portmcfl swp1=0 swp2=0', @@ -193,6 +197,7 @@ class bridge(moduleBase): 'regex or \"all\" on bridge_ports,' + 'as it wouldnt work.', 'default' : '0', + 'validvals': [''], 'example' : ['bridge-waitport 4 swp1 swp2']}, 'bridge-maxwait' : { 'help' : 'forces to time seconds the maximum time ' + @@ -210,6 +215,7 @@ class bridge(moduleBase): 'If specified under the bridge the ports ' + 'inherit it unless overridden by a ' + 'bridge-vids attribute under the port', + 'validvals': [''], 'example' : ['bridge-vids 4000', 'bridge-vids 2000 2200-3000']}, 'bridge-pvid' : diff --git a/addons/bridgevlan.py b/addons/bridgevlan.py index 80245cc..ef3cd02 100644 --- a/addons/bridgevlan.py +++ b/addons/bridgevlan.py @@ -25,7 +25,7 @@ class bridgevlan(moduleBase): 'bridge-igmp-querier-src' : { 'help' : 'bridge igmp querier src. Must be ' + 'specified under the vlan interface', - 'validvals' : [IPv4Address, ], + 'validvals' : ['', ], 'example' : ['bridge-igmp-querier-src 172.16.101.1']}}} def __init__(self, *args, **kargs): diff --git a/addons/mstpctl.py b/addons/mstpctl.py index cd37784..8cafb20 100644 --- a/addons/mstpctl.py +++ b/addons/mstpctl.py @@ -30,7 +30,7 @@ class mstpctl(moduleBase): 'new-attribute': 'bridge-ports'}, 'mstpctl-stp' : {'help': 'bridge stp yes/no', - 'validvals' : ['yes', 'no'], + 'validvals' : ['yes', 'no', 'on', 'off'], 'compat' : True, 'default' : 'no', 'deprecated': True, @@ -79,6 +79,7 @@ class mstpctl(moduleBase): 'example' : ['mstpctl-forcevers rstp']}, 'mstpctl-portpathcost' : { 'help' : 'bridge port path cost', + 'validvals': [''], 'validrange' : ['0', '65535'], 'default' : '0', 'jsonAttr' : 'adminExtPortCost', @@ -89,7 +90,7 @@ class mstpctl(moduleBase): { 'help' : 'bridge port p2p detection mode', 'default' : 'auto', 'jsonAttr' : 'adminPointToPoint', - 'validvals' : ['yes', 'no', 'auto'], + 'validvals' : [''], 'required' : False, 'example' : ['under the bridge: mstpctl-portp2p swp1=yes swp2=no', 'under the port (recommended): mstpctl-portp2p yes']}, @@ -98,7 +99,7 @@ class mstpctl(moduleBase): 'enable/disable port ability to take root role of the port', 'default' : 'no', 'jsonAttr' : 'restrictedRole', - 'validvals' : ['yes', 'no'], + 'validvals' : [''], 'required' : False, 'example' : ['under the bridge: mstpctl-portrestrrole swp1=yes swp2=no', 'under the port (recommended): mstpctl-portrestrrole yes']}, @@ -107,7 +108,7 @@ class mstpctl(moduleBase): 'enable/disable port ability to propagate received topology change notification of the port', 'default' : 'no', 'jsonAttr' : 'restrictedTcn', - 'validvals' : ['yes', 'no'], + 'validvals' : [''], 'required' : False, 'example' : ['under the bridge: mstpctl-portrestrtcn swp1=yes swp2=no', 'under the port (recommended): mstpctl-portrestrtcn yes']}, @@ -116,7 +117,7 @@ class mstpctl(moduleBase): 'enable/disable bpduguard', 'default' : 'no', 'jsonAttr' : 'bpduGuardPort', - 'validvals' : ['yes', 'no'], + 'validvals' : [''], 'required' : False, 'example' : ['under the bridge: mstpctl-bpduguard swp1=yes swp2=no', 'under the port (recommended): mstpctl-bpduguard yes']}, @@ -124,6 +125,7 @@ class mstpctl(moduleBase): { 'help' : 'port priority for MSTI instance', 'default' : '128', + 'validvals': [''], 'validrange' : ['0', '240'], 'required' : False, 'example' : ['under the bridge: mstpctl-treeportprio swp1=128 swp2=128', @@ -136,7 +138,7 @@ class mstpctl(moduleBase): 'example' : ['mstpctl-hello 2']}, 'mstpctl-portnetwork' : { 'help' : 'enable/disable bridge assurance capability for a port', - 'validvals' : ['yes', 'no'], + 'validvals' : [''], 'default' : 'no', 'jsonAttr' : 'networkPort', 'required' : False, @@ -144,7 +146,7 @@ class mstpctl(moduleBase): 'under the port (recommended): mstpctl-portnetwork yes']}, 'mstpctl-portadminedge' : { 'help' : 'enable/disable initial edge state of the port', - 'validvals' : ['yes', 'no'], + 'validvals' : [''], 'default' : 'no', 'jsonAttr' : 'adminEdgePort', 'required' : False, @@ -152,7 +154,7 @@ class mstpctl(moduleBase): 'under the port (recommended): mstpctl-portadminedge yes']}, 'mstpctl-portautoedge' : { 'help' : 'enable/disable auto transition to/from edge state of the port', - 'validvals' : ['yes', 'no'], + 'validvals' : [''], 'default' : 'yes', 'jsonAttr' : 'autoEdgePort', 'required' : False, @@ -166,7 +168,7 @@ class mstpctl(moduleBase): { 'help' : 'enable/disable bpdu filter on a port. ' + 'syntax varies when defined under a bridge ' + 'vs under a port', - 'validvals' : ['yes', 'no'], + 'validvals' : [''], 'jsonAttr' : 'bpduFilterPort', 'default' : 'no', 'required' : False, diff --git a/addons/vlan.py b/addons/vlan.py index ea4e68e..111d432 100644 --- a/addons/vlan.py +++ b/addons/vlan.py @@ -25,7 +25,7 @@ class vlan(moduleBase): 'attrs' : { 'vlan-raw-device' : {'help' : 'vlan raw device', - 'validvals' : ['' ,]}, + 'validvals': ['']}, 'vlan-id' : {'help' : 'vlan id', 'validrange' : ['0', '4096']}}} diff --git a/addons/vrf.py b/addons/vrf.py index fab769b..343f5b9 100644 --- a/addons/vrf.py +++ b/addons/vrf.py @@ -34,9 +34,11 @@ class vrf(moduleBase): 'creating a vrf device. ' + 'Table id is either \'auto\' or '+ '\'valid routing table id\'', + 'validvals': ['', ''], 'example': ['vrf-table auto', 'vrf-table 1001']}, 'vrf': {'help' : 'vrf the interface is part of.', + 'validvals': [''], 'example': ['vrf blue']}}} iproute2_vrf_filename = '/etc/iproute2/rt_tables.d/ifupdown2_vrf_map.conf' diff --git a/addons/vrrpd.py b/addons/vrrpd.py index 575e992..6d1ee7d 100644 --- a/addons/vrrpd.py +++ b/addons/vrrpd.py @@ -35,7 +35,7 @@ class vrrpd(moduleBase): 'example' : ['vrrp-priority 20']}, 'vrrp-virtual-ip' : {'help': 'set vrrp virtual ip', - 'validvals' : [IPv4Address, ], + 'validvals' : ['', ], 'example' : ['vrrp-virtual-ip 10.0.1.254']}}} def __init__(self, *args, **kargs): diff --git a/addons/vxlan.py b/addons/vxlan.py index 4bc1dfc..059b50b 100644 --- a/addons/vxlan.py +++ b/addons/vxlan.py @@ -22,15 +22,15 @@ class vxlan(moduleBase): 'example': ['vxlan-id 100']}, 'vxlan-local-tunnelip' : {'help' : 'vxlan local tunnel ip', - 'validvals' : [IPv4Address, ], + 'validvals' : ['', ''], 'example': ['vxlan-local-tunnelip 172.16.20.103']}, 'vxlan-svcnodeip' : {'help' : 'vxlan id', - 'validvals' : [IPv4Address, ], + 'validvals' : ['', ''], 'example': ['vxlan-svcnodeip 172.16.22.125']}, 'vxlan-remoteip' : {'help' : 'vxlan remote ip', - 'validvals' : [IPv4Address, ], + 'validvals' : ['', ''], 'example': ['vxlan-remoteip 172.16.22.127']}, 'vxlan-learning' : {'help' : 'vxlan learning yes/no', diff --git a/ifupdown/ifupdownmain.py b/ifupdown/ifupdownmain.py index 18231a0..0691a56 100644 --- a/ifupdown/ifupdownmain.py +++ b/ifupdown/ifupdownmain.py @@ -27,6 +27,8 @@ from graph import * from exceptions import * from sets import Set +from ipaddr import IPNetwork, IPv4Network, IPv6Network, IPAddress, IPv4Address, IPv6Address + """ .. module:: ifupdownmain :synopsis: main module for ifupdown package @@ -270,6 +272,30 @@ class ifupdownMain(ifupdownBase): # This makes config available to addon modules ifupdownConfig.config = self.config + self.validate_keywords = { + '': self._keyword_mac, + '': self._keyword_text, + '': self._keyword_ipv4, + '': self._keyword_ipv6, + '': self._keyword_auto, + '': self._keyword_ipaddr, + '': self._keyword_number, + '': self._keyword_interface, + '': self._keyword_ipv4_vrf_text, + '': self._keyword_number_ipv4_list, + '': self._keyword_interface_list, + '': self._keyword_ipv4_prefixlen, + '': self._keyword_ipv6_prefixlen, + '': self._keyword_ipaddr_prefixlen, + '': self._keyword_number_range_list, + '': self._keyword_interface_range_list, + '': self._keyword_mac_ipaddr_prefixlen_list, + '': self._keyword_number_interface_list, + '': self._keyword_interface_yes_no_list, + '': self._keyword_interface_yes_no_0_1_list, + '': self._keyword_interface_yes_no_auto_list, + } + def link_master_slave_ignore_error(self, errorstr): # If link master slave flag is set, # there may be cases where the lowerdev may not be @@ -722,15 +748,357 @@ class ifupdownMain(ifupdownBase): ifaceobj.flags |= ifaceobj.OLDEST_SIBLING self.ifaceobjdict[ifaceobj.name].append(ifaceobj) + def _keyword_text(self, value, validrange=None): + return isinstance(value, str) and len(value) > 0 + + def _keyword_mac(self, value, validrange=None): + if value.strip().startswith('ether'): + value = value.strip()[6:] + return re.match('[0-9a-f]{1,2}([-:])[0-9a-f]{1,2}(\\1[0-9a-f]{1,2}){4}$', + value.lower()) + + def _keyword_check_list(self, _list, obj, limit=None): + try: + if limit and limit > 0: + for i in xrange(0, limit): + obj(_list[i]) + return len(_list) == limit + else: + for elem in _list: + obj(elem) + return True + except Exception as e: + self.logger.debug('keyword: check list: %s' % str(e)) + return False + + def _keyword_ipv4(self, value, validrange=None): + return self._keyword_check_list(value.split(), IPv4Address, limit=1) + + def _keyword_ipv4_prefixlen(self, value, validrange=None): + return self._keyword_check_list(value.split(), IPv4Network, limit=1) + + def _keyword_ipv6(self, value, validrange=None): + return self._keyword_check_list(value.split(), IPv6Address, limit=1) + + def _keyword_ipv6_prefixlen(self, value, validrange=None): + return self._keyword_check_list(value.split(), IPv6Network, limit=1) + + def _keyword_ipaddr(self, value, validrange=None): + return self._keyword_check_list(value.split(), IPAddress, limit=1) + + def _keyword_ipaddr_prefixlen(self, value, validrange=None): + return self._keyword_check_list(value.split(), IPNetwork, limit=1) + + def _keyword_mac_ipaddr_prefixlen_list(self, value, validrange=None): + """ + [ ...] + ex: address-virtual 00:11:22:33:44:01 11.0.1.1/24 11.0.1.2/24 + """ + try: + res = value.split() + if len(res) < 2: + return False + if not self._keyword_mac(res[0]): + return False + for ip in res[1:]: + if not self._keyword_ipaddr_prefixlen(ip): + return False + return True + except Exception as e: + self.logger.debug('keyword: mac ipaddr prefixlen: %s' % str(e)) + return False + + def _keyword_number_ipv4_list(self, value, validrange=None): + """ + = [= ...] + ex: bridge-mcqv4src 100=172.16.100.1 101=172.16.101.1 + """ + try: + elements = value.split(' ') + if not elements: + return False + for elem in elements: + v = elem.split('=') + int(v[0]) + IPv4Address(v[1]) + return True + except Exception as e: + self.logger.debug('keyword: number ipv4: %s' % str(e)) + return False + + def _keyword_interface(self, ifacename, validrange=None): + return self.get_ifaceobjs(ifacename) + + def _keyword_ipv4_vrf_text(self, value, validrange=None): + """ + "vrf" + ex: clagd-backup-ip 10.10.10.42 vrf blue + """ + values = value.split() + size = len(values) + + if size > 3 or size < 1: + return False + try: + IPv4Address(values[0]) + if size > 1: + if values[1] != 'vrf': + return False + if size > 2: + if not self._keyword_text(values[2]): + return False + return True + except Exception as e: + self.logger.debug('keyword: ipv4 vrf text: %s' % str(e)) + return False + + def _keyword_interface_list_with_value(self, value, validvals): + values = value.split() + try: + if len(values) == 1: + if values[0] in validvals: + return True + for v in values: + iface_value = v.split('=') + size = len(iface_value) + if size != 2: + if iface_value[0] == 'glob' or iface_value[0] == 'regex': + continue + return False + if not iface_value[1] in validvals: + return False + return True + except Exception as e: + self.logger.debug('keyword: interface list with value: %s' % str(e)) + return False + + def _keyword_interface_yes_no_list(self, value, validrange=None): + """ + | ( = [= ...] ) + ex: mstpctl-portrestrrole swp1=yes swp2=no + """ + return self._keyword_interface_list_with_value(value, ['yes', 'no']) + + def _keyword_interface_yes_no_auto_list(self, value, validrange=None): + """ + | + ( = [= ...] ) + ex: mstpctl-portp2p swp1=yes swp2=no swp3=auto + """ + return self._keyword_interface_list_with_value(value, + ['yes', 'no', 'auto']) + + def _keyword_interface_yes_no_0_1_list(self, value, validrange=None): + """ + | + ( = [= ...] ) + ex: bridge-portmcrouter swp1=yes swp2=yes swp3=1 + """ + return self._keyword_interface_list_with_value(value, + ['yes', 'no', '1', '0']) + + def _keyword_interface_range_list(self, value, validrange): + """ + | ( = [ =number> ...] ) + ex: mstpctl-portpathcost swp1=0 swp2=1 + """ + values = value.split() + try: + if len(values) == 1: + try: + n = int(values[0]) + if n < int(validrange[0]) or n > int( + validrange[1]): + raise invalidValueError('value of out range "%s":' + ' valid attribute range: %s' + % (values[0], + '-'.join(validrange))) + return True + except invalidValueError as e: + raise e + except Exception as e: + self.logger.debug('keyword: interface range list: %s' + % str(e)) + return False + for v in values: + iface_value = v.split('=') + size = len(iface_value) + if size != 2: + return False + number = int(iface_value[1]) + if number < int(validrange[0]) or number > int( + validrange[1]): + raise invalidValueError( + 'value of out range "%s" for iface "%s":' + ' valid attribute range: %s' + % (iface_value[1], + iface_value[0], + '-'.join(validrange))) + return True + except invalidValueError as e: + raise e + except Exception as e: + self.logger.debug('keyword: interface range list: %s' % str(e)) + return False + + def _keyword_interface_list(self, value, validrange=None): + """ + [glob|regex] [ [glob|regex] ...] + ex: bridge-ports swp1 swp2 glob swp3-5.100 regex (swp[6|7|8].100) + """ + interface_list = value.split() + size = len(interface_list) + i = 0 + while i < size: + if interface_list[i] == 'glob' or interface_list[i] == 'regex': + i += 1 + else: + if not self._keyword_interface(interface_list[i]): + return False + i += 1 + return True + + def _keyword_number_range_list(self, value, validrange=None): + """ + [-] + ex: bridge-vids 42 100-200 + """ + number_list = value.split() + try: + i = 0 + while i < len(number_list): + if '-' in number_list[i]: + range = number_list[i].split('-') + a = int(range[0]) + b = int(range[1]) + if a > b: + return False + else: + int(number_list[i]) + i += 1 + return True + except Exception as e: + self.logger.debug('keyword: number range list: %s' % str(e)) + return False + + def _keyword_number_interface_list(self, value, validrange=None): + """ + [... [ ... ]] + bridge-waitport 42 swp1 swp2 swp3 9 swp4 + """ + interface_list = value.split() + if not interface_list: + return False + try: + int(interface_list[0]) + prev = True + for elem in interface_list[1:]: + try: + int(elem) + if prev: + return False + prev = True + except: + prev = False + return not prev + except Exception as e: + self.logger.debug('keyword: number interface list: %s' % str(e)) + return False + + def _keyword_auto(self, value, validrange=None): + return value == 'auto' + + def _keyword_number(self, value, validrange=None): + try: + int(value) + return True + except Exception as e: + self.logger.debug('keyword: number: %s' % str(e)) + return False + + def _is_keyword(self, value): + if isinstance(value, tuple): + return True + keyword_found = value in self.validate_keywords + if value.startswith('<') and value.endswith('>') and not keyword_found: + raise Exception('%s: invalid keyword, please make sure to use' + ' a valid keyword see `ifquery -s`' % value) + return keyword_found + + def _check_validvals_value(self, attrname, value, validvals, validrange): + if validvals and value not in validvals: + is_valid = False + for keyword in validvals: + if self._is_keyword(keyword): + if validrange: + if self.validate_keywords[keyword](value, validrange): + return {'result': True} + else: + if self.validate_keywords[keyword](value): + return {'result': True} + if not is_valid: + return { + 'result': False, + 'message': 'invalid value "%s": valid attribute values: %s' + % (value, validvals) + } + elif validrange: + if len(validrange) != 2: + raise Exception('%s: invalid range in addon configuration' + % '-'.join(validrange)) + _value = int(value) + if _value < int(validrange[0]) or _value > int(validrange[1]): + return { + 'result': False, + 'message': 'value of out range "%s": ' + 'valid attribute range: %s' + % (value, '-'.join(validrange)) + } + return {'result': True} + + def _check_validvals(self, ifacename, module_name, attrs): + ifaceobj = self.get_ifaceobjs(ifacename) + if not ifaceobj: + return + success = True + for attrname, attrvalue in ifaceobj[0].config.items(): + try: + attrname_dict = attrs.get(attrname, {}) + validvals = attrname_dict.get('validvals', []) + validrange = attrname_dict.get('validrange', []) + for value in attrvalue: + res = self._check_validvals_value(attrname, + value, + validvals, + validrange) + if not res['result']: + self.logger.warn('%s: %s: %s' % + (ifacename, attrname, res['message'])) + success = False + except Exception as e: + self.logger.warn('addon \'%s\': %s: %s' % (module_name, + attrname, + str(e))) + success = False + return success + def _module_syntax_check(self, filtered_ifacenames): + result = True for ifacename in filtered_ifacenames: for module in self.modules.values(): try: - if hasattr(module, 'syntax_check') \ - and callable(module.syntax_check): - module.syntax_check(self.get_ifaceobjs(ifacename)) + if hasattr(module, '_modinfo'): + if not self._check_validvals(ifacename, + module.__class__.__name__, + module._modinfo.get('attrs', {})): + result = False + if hasattr(module, 'syntax_check') and callable(module.syntax_check): + if not module.syntax_check(self.get_ifaceobjs(ifacename)): + result = False except Exception, e: - pass #self.logger.warn('%s: %s' % (ifacename, str(e))) + self.logger.warn('%s: %s' % (ifacename, str(e))) + result = False + return result def _iface_configattr_syntax_checker(self, attrname, attrval): for m, mdict in self.module_attrs.items(): @@ -1160,7 +1528,8 @@ class ifupdownMain(ifupdownBase): # return here because we want to make sure most # errors above are caught and reported. if syntaxcheck: - self._module_syntax_check(filtered_ifacenames) + if not self._module_syntax_check(filtered_ifacenames): + raise Exception() if not iface_read_ret: raise Exception() elif self._any_iface_errors(filtered_ifacenames): @@ -1366,7 +1735,8 @@ class ifupdownMain(ifupdownBase): # return here because we want to make sure most # errors above are caught and reported. if syntaxcheck: - self._module_syntax_check(interfaces_to_up) + if not self._module_syntax_check(interfaces_to_up): + raise Exception() if not iface_read_ret: raise Exception() elif self._any_iface_errors(interfaces_to_up): @@ -1449,7 +1819,8 @@ class ifupdownMain(ifupdownBase): # return here because we want to make sure most # errors above are caught and reported. if syntaxcheck: - self._module_syntax_check(new_filtered_ifacenames) + if not self._module_syntax_check(new_filtered_ifacenames): + raise Exception() if not iface_read_ret: raise Exception() elif self._any_iface_errors(new_filtered_ifacenames):