]>
Commit | Line | Data |
---|---|---|
35681c06 | 1 | #!/usr/bin/env python3 |
84ca006f | 2 | # |
d486dd0d | 3 | # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved. |
84ca006f RP |
4 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com |
5 | # | |
6 | ||
d486dd0d | 7 | try: |
223ba5af JF |
8 | from ifupdown2.lib.addon import Addon |
9 | ||
d486dd0d JF |
10 | from ifupdown2.ifupdown.iface import * |
11 | ||
d486dd0d JF |
12 | from ifupdown2.ifupdownaddons.modulebase import moduleBase |
13 | ||
14 | import ifupdown2.ifupdown.ifupdownflags as ifupdownflags | |
15 | except ImportError: | |
223ba5af JF |
16 | from lib.addon import Addon |
17 | ||
d486dd0d JF |
18 | from ifupdown.iface import * |
19 | ||
d486dd0d JF |
20 | from ifupdownaddons.modulebase import moduleBase |
21 | ||
22 | import ifupdown.ifupdownflags as ifupdownflags | |
23 | ||
84ca006f | 24 | |
223ba5af | 25 | class bridgevlan(Addon, moduleBase): |
84ca006f RP |
26 | """ ifupdown2 addon module to configure vlan attributes on a vlan |
27 | aware bridge """ | |
28 | ||
223ba5af JF |
29 | _modinfo = { |
30 | "mhelp": "bridgevlan module configures vlan attributes on a vlan aware " | |
31 | "bridge. This module only understands vlan interface name " | |
32 | "with dot notations. eg br0.100. where br0 is the vlan aware " | |
33 | "bridge this config is for", | |
34 | "attrs": { | |
35 | "bridge-igmp-querier-src": { | |
36 | "help": "bridge igmp querier src. Must be specified under " | |
37 | "the vlan interface", | |
38 | "validvals": ["<ipv4>"], | |
39 | "example": ["bridge-igmp-querier-src 172.16.101.1"] | |
40 | } | |
41 | } | |
42 | } | |
84ca006f RP |
43 | |
44 | def __init__(self, *args, **kargs): | |
223ba5af | 45 | Addon.__init__(self) |
84ca006f | 46 | moduleBase.__init__(self, *args, **kargs) |
84ca006f | 47 | |
223ba5af JF |
48 | @staticmethod |
49 | def _is_bridge_vlan_device(ifaceobj): | |
50 | return ifaceobj.type == ifaceType.BRIDGE_VLAN | |
84ca006f | 51 | |
223ba5af JF |
52 | @staticmethod |
53 | def _get_bridge_n_vlan(ifaceobj): | |
84ca006f RP |
54 | vlist = ifaceobj.name.split('.', 1) |
55 | if len(vlist) == 2: | |
223ba5af | 56 | return vlist[0], vlist[1] |
84ca006f RP |
57 | return None |
58 | ||
223ba5af JF |
59 | @staticmethod |
60 | def _get_bridgename(ifaceobj): | |
84ca006f RP |
61 | vlist = ifaceobj.name.split('.', 1) |
62 | if len(vlist) == 2: | |
63 | return vlist[0] | |
64 | return None | |
65 | ||
66 | def get_dependent_ifacenames(self, ifaceobj, ifaceobjs_all=None): | |
67 | if not self._is_bridge_vlan_device(ifaceobj): | |
68 | return None | |
69 | return [self._get_bridgename(ifaceobj)] | |
70 | ||
71 | def _up(self, ifaceobj): | |
72 | try: | |
73 | (bridgename, vlan) = self._get_bridge_n_vlan(ifaceobj) | |
74 | vlanid = int(vlan, 10) | |
75 | except: | |
223ba5af JF |
76 | self.log_error("%s: bridge vlan interface name does not correspond " |
77 | "to format (eg. br0.100)" % ifaceobj.name, ifaceobj) | |
84ca006f RP |
78 | raise |
79 | ||
223ba5af | 80 | if not self.cache.link_exists(bridgename): |
e1601369 RP |
81 | #self.logger.warn('%s: bridge %s does not exist' %(ifaceobj.name, |
82 | # bridgename)) | |
84ca006f RP |
83 | return |
84 | ||
85 | running_mcqv4src = {} | |
fc5e1735 | 86 | if not ifupdownflags.flags.PERFMODE: |
223ba5af | 87 | running_mcqv4src = self.sysfs.bridge_get_mcqv4src(bridgename) |
84ca006f RP |
88 | if running_mcqv4src: |
89 | r_mcqv4src = running_mcqv4src.get(vlan) | |
90 | else: | |
91 | r_mcqv4src = None | |
92 | mcqv4src = ifaceobj.get_attr_value_first('bridge-igmp-querier-src') | |
93 | if not mcqv4src: | |
94 | if r_mcqv4src: | |
223ba5af | 95 | self.iproute2.bridge_del_mcqv4src(bridgename, vlanid) |
84ca006f RP |
96 | return |
97 | ||
98 | if r_mcqv4src and r_mcqv4src != mcqv4src: | |
223ba5af JF |
99 | self.iproute2.bridge_del_mcqv4src(bridgename, vlanid) |
100 | self.iproute2.bridge_set_mcqv4src(bridgename, vlanid, mcqv4src) | |
84ca006f | 101 | else: |
223ba5af | 102 | self.iproute2.bridge_set_mcqv4src(bridgename, vlanid, mcqv4src) |
84ca006f RP |
103 | |
104 | def _down(self, ifaceobj): | |
105 | try: | |
106 | (bridgename, vlan) = self._get_bridge_n_vlan(ifaceobj) | |
107 | vlanid = int(vlan, 10) | |
108 | except: | |
223ba5af JF |
109 | self.logger.warn("%s: bridge vlan interface name does not " |
110 | "correspond to format (eg. br0.100)" % ifaceobj.name) | |
84ca006f RP |
111 | raise |
112 | ||
223ba5af | 113 | if not self.cache.link_exists(bridgename): |
e1601369 RP |
114 | #self.logger.warn('%s: bridge %s does not exist' %(ifaceobj.name, |
115 | # bridgename)) | |
84ca006f | 116 | return |
84ca006f RP |
117 | mcqv4src = ifaceobj.get_attr_value_first('bridge-igmp-querier-src') |
118 | if mcqv4src: | |
223ba5af | 119 | self.iproute2.bridge_del_mcqv4src(bridgename, vlanid) |
84ca006f | 120 | |
da1eb143 RP |
121 | def _query_running_bridge_igmp_querier_src(self, ifaceobj): |
122 | (bridgename, vlanid) = ifaceobj.name.split('.') | |
223ba5af | 123 | running_mcqv4src = self.sysfs.bridge_get_mcqv4src(bridgename) |
da1eb143 | 124 | if running_mcqv4src: |
223ba5af | 125 | return running_mcqv4src.get(vlanid) |
da1eb143 RP |
126 | return None |
127 | ||
84ca006f | 128 | def _query_check(self, ifaceobj, ifaceobjcurr): |
da1eb143 RP |
129 | attrval = ifaceobj.get_attr_value_first('bridge-igmp-querier-src') |
130 | if attrval: | |
131 | running_mcq = self._query_running_bridge_igmp_querier_src(ifaceobj) | |
132 | if not running_mcq or running_mcq != attrval: | |
133 | ifaceobjcurr.update_config_with_status( | |
134 | 'bridge-igmp-querier-src', running_mcq, 1) | |
135 | else: | |
136 | ifaceobjcurr.update_config_with_status( | |
137 | 'bridge-igmp-querier-src', attrval, 0) | |
16d854b4 | 138 | ifaceobjcurr.status = ifaceStatus.SUCCESS |
84ca006f RP |
139 | return |
140 | ||
d486dd0d JF |
141 | def syntax_check(self, ifaceobj, ifaceobj_getfunc): |
142 | ret = True | |
143 | bvlan_intf = self._is_bridge_vlan_device(ifaceobj) | |
223ba5af JF |
144 | if (ifaceobj.get_attr_value_first('bridge-igmp-querier-src') and not bvlan_intf): |
145 | self.logger.error('%s: bridge-igmp-querier-src only allowed under vlan stanza' % ifaceobj.name) | |
d486dd0d JF |
146 | ret = False |
147 | return ret | |
148 | ||
223ba5af JF |
149 | _run_ops = { |
150 | "pre-up": _up, | |
151 | "post-down": _down, | |
152 | "query-checkcurr": _query_check, | |
153 | } | |
84ca006f RP |
154 | |
155 | def get_ops(self): | |
156 | """ returns list of ops supported by this module """ | |
3b01ed76 | 157 | return list(self._run_ops.keys()) |
84ca006f | 158 | |
84ca006f RP |
159 | def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args): |
160 | """ run vlan configuration on the interface object passed as argument | |
161 | ||
162 | Args: | |
163 | **ifaceobj** (object): iface object | |
164 | ||
165 | **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr', | |
166 | 'query-running' | |
167 | Kwargs: | |
168 | **query_ifaceobj** (object): query check ifaceobject. This is only | |
169 | valid when op is 'query-checkcurr'. It is an object same as | |
170 | ifaceobj, but contains running attribute values and its config | |
171 | status. The modules can use it to return queried running state | |
172 | of interfaces. status is success if the running state is same | |
173 | as user required state in ifaceobj. error otherwise. | |
174 | """ | |
175 | op_handler = self._run_ops.get(operation) | |
176 | if not op_handler: | |
177 | return | |
223ba5af | 178 | if (operation != 'query-running' and not self._is_bridge_vlan_device(ifaceobj)): |
d486dd0d JF |
179 | # most common problem is people specify BRIDGE_VLAN |
180 | # attribute on a bridge or a vlan device, which | |
181 | # is incorrect. So, catch them here and warn before | |
182 | # giving up processing the interface | |
223ba5af JF |
183 | if (ifaceobj.link_kind & ifaceLinkKind.BRIDGE or ifaceobj.link_kind & ifaceLinkKind.VLAN) \ |
184 | and not self.syntax_check(ifaceobj, None): | |
d486dd0d | 185 | ifaceobj.status = ifaceStatus.ERROR |
84ca006f | 186 | return |
84ca006f RP |
187 | if operation == 'query-checkcurr': |
188 | op_handler(self, ifaceobj, query_ifaceobj) | |
189 | else: | |
190 | op_handler(self, ifaceobj) |