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