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