]>
Commit | Line | Data |
---|---|---|
15ef32ea RP |
1 | #!/usr/bin/python |
2 | ||
3 | from ifupdown.iface import * | |
594fb088 | 4 | from ifupdown.utils import utils |
15ef32ea RP |
5 | from ifupdownaddons.modulebase import moduleBase |
6 | from ifupdownaddons.iproute2 import iproute2 | |
dae9c5de | 7 | from ifupdownaddons.systemutils import systemUtils |
2864d6f3 | 8 | from ifupdown.netlink import netlink |
c6370b56 | 9 | from ipaddr import IPv4Address |
2864d6f3 | 10 | import ifupdown.ifupdownflags as ifupdownflags |
15ef32ea | 11 | import logging |
a794fb31 | 12 | import os |
9e012f9e | 13 | from sets import Set |
15ef32ea RP |
14 | |
15 | class vxlan(moduleBase): | |
16 | _modinfo = {'mhelp' : 'vxlan module configures vxlan interfaces.', | |
17 | 'attrs' : { | |
18 | 'vxlan-id' : | |
19 | {'help' : 'vxlan id', | |
ec031459 | 20 | 'validrange' : ['1', '16777214'], |
15ef32ea RP |
21 | 'required' : True, |
22 | 'example': ['vxlan-id 100']}, | |
23 | 'vxlan-local-tunnelip' : | |
24 | {'help' : 'vxlan local tunnel ip', | |
482b2fab | 25 | 'validvals' : ['<ipv4>', '<ipv6>'], |
15ef32ea RP |
26 | 'example': ['vxlan-local-tunnelip 172.16.20.103']}, |
27 | 'vxlan-svcnodeip' : | |
28 | {'help' : 'vxlan id', | |
482b2fab | 29 | 'validvals' : ['<ipv4>', '<ipv6>'], |
15ef32ea | 30 | 'example': ['vxlan-svcnodeip 172.16.22.125']}, |
44533c72 WK |
31 | 'vxlan-remoteip' : |
32 | {'help' : 'vxlan remote ip', | |
482b2fab | 33 | 'validvals' : ['<ipv4>', '<ipv6>'], |
44533c72 | 34 | 'example': ['vxlan-remoteip 172.16.22.127']}, |
15ef32ea | 35 | 'vxlan-learning' : |
594fb088 JF |
36 | {'help' : 'vxlan learning yes/no', |
37 | 'validvals' : ['yes', 'no', 'on', 'off'], | |
38 | 'example': ['vxlan-learning no'], | |
39 | 'default': 'yes'}, | |
88a5c4c8 ST |
40 | 'vxlan-ageing' : |
41 | {'help' : 'vxlan aging timer', | |
c6370b56 | 42 | 'validrange' : ['0', '4096'], |
27f2a937 BR |
43 | 'example': ['vxlan-ageing 300'], |
44 | 'default': '300'}, | |
15ef32ea | 45 | }} |
a794fb31 | 46 | _clagd_vxlan_anycast_ip = "" |
15ef32ea RP |
47 | |
48 | def __init__(self, *args, **kargs): | |
49 | moduleBase.__init__(self, *args, **kargs) | |
50 | self.ipcmd = None | |
51 | ||
0a3bee28 | 52 | def get_dependent_ifacenames(self, ifaceobj, ifaceobjs_all=None): |
a794fb31 BR |
53 | if self._is_vxlan_device(ifaceobj): |
54 | ifaceobj.link_kind |= ifaceLinkKind.VXLAN | |
55 | elif ifaceobj.name == 'lo': | |
56 | clagd_vxlan_list = ifaceobj.get_attr_value('clagd-vxlan-anycast-ip') | |
57 | if clagd_vxlan_list: | |
58 | if len(clagd_vxlan_list) != 1: | |
59 | self.log_warn('%s: multiple clagd-vxlan-anycast-ip lines, using first one' | |
60 | % (ifaceobj.name,)) | |
61 | vxlan._clagd_vxlan_anycast_ip = clagd_vxlan_list[0] | |
0a3bee28 ST |
62 | return None |
63 | ||
15ef32ea RP |
64 | def _is_vxlan_device(self, ifaceobj): |
65 | if ifaceobj.get_attr_value_first('vxlan-id'): | |
66 | return True | |
67 | return False | |
68 | ||
32a74516 | 69 | def _vxlan_create(self, ifaceobj): |
15ef32ea RP |
70 | vxlanid = ifaceobj.get_attr_value_first('vxlan-id') |
71 | if vxlanid: | |
b653111a | 72 | anycastip = self._clagd_vxlan_anycast_ip |
32a74516 | 73 | group = ifaceobj.get_attr_value_first('vxlan-svcnodeip') |
b653111a JF |
74 | local = ifaceobj.get_attr_value_first('vxlan-local-tunnelip') |
75 | ageing = ifaceobj.get_attr_value_first('vxlan-ageing') | |
76 | learning = utils.get_onoff_bool(ifaceobj.get_attr_value_first('vxlan-learning')) | |
77 | ||
78 | if self.ipcmd.link_exists(ifaceobj.name): | |
79 | vxlanattrs = self.ipcmd.get_vxlandev_attrs(ifaceobj.name) | |
80 | # on ifreload do not overwrite anycast_ip to individual ip | |
81 | # if clagd has modified | |
82 | if vxlanattrs: | |
83 | running_localtunnelip = vxlanattrs.get('local') | |
84 | if (anycastip and running_localtunnelip and | |
85 | anycastip == running_localtunnelip): | |
86 | local = running_localtunnelip | |
32a74516 JF |
87 | |
88 | netlink.link_add_vxlan(ifaceobj.name, vxlanid, | |
b653111a JF |
89 | local=local, |
90 | learning=learning, | |
91 | ageing=ageing, | |
32a74516 JF |
92 | group=group) |
93 | ||
94 | remoteips = ifaceobj.get_attr_value('vxlan-remoteip') | |
95 | if not systemUtils.is_service_running(None, '/var/run/vxrd.pid'): | |
96 | # figure out the diff for remotes and do the bridge fdb updates | |
97 | # only if provisioned by user and not by vxrd | |
98 | cur_peers = set(self.ipcmd.get_vxlan_peers(ifaceobj.name, group)) | |
99 | if remoteips: | |
100 | new_peers = set(remoteips) | |
101 | del_list = cur_peers.difference(new_peers) | |
102 | add_list = new_peers.difference(cur_peers) | |
103 | else: | |
104 | del_list = cur_peers | |
105 | add_list = [] | |
106 | ||
107 | try: | |
108 | for addr in del_list: | |
109 | self.ipcmd.bridge_fdb_del(ifaceobj.name, | |
110 | '00:00:00:00:00:00', | |
111 | None, True, addr) | |
112 | except: | |
113 | pass | |
114 | ||
115 | try: | |
116 | for addr in add_list: | |
117 | self.ipcmd.bridge_fdb_append(ifaceobj.name, | |
118 | '00:00:00:00:00:00', | |
119 | None, True, addr) | |
120 | except: | |
121 | pass | |
122 | ||
e8b4b06d | 123 | if ifaceobj.addr_method == 'manual': |
2864d6f3 | 124 | netlink.link_set_updown(ifaceobj.name, "up") |
15ef32ea | 125 | |
32a74516 JF |
126 | def _up(self, ifaceobj): |
127 | self._vxlan_create(ifaceobj) | |
128 | ||
15ef32ea RP |
129 | def _down(self, ifaceobj): |
130 | try: | |
131 | self.ipcmd.link_delete(ifaceobj.name) | |
132 | except Exception, e: | |
133 | self.log_warn(str(e)) | |
134 | ||
f50f16fa | 135 | def _query_check_n_update(self, ifaceobj, ifaceobjcurr, attrname, attrval, |
9e012f9e | 136 | running_attrval): |
f50f16fa N |
137 | if not ifaceobj.get_attr_value_first(attrname): |
138 | return | |
9e012f9e RP |
139 | if running_attrval and attrval == running_attrval: |
140 | ifaceobjcurr.update_config_with_status(attrname, attrval, 0) | |
141 | else: | |
142 | ifaceobjcurr.update_config_with_status(attrname, running_attrval, 1) | |
143 | ||
144 | def _query_check_n_update_addresses(self, ifaceobjcurr, attrname, | |
145 | addresses, running_addresses): | |
146 | if addresses: | |
147 | for a in addresses: | |
148 | if a in running_addresses: | |
149 | ifaceobjcurr.update_config_with_status(attrname, a, 0) | |
150 | else: | |
151 | ifaceobjcurr.update_config_with_status(attrname, a, 1) | |
152 | running_addresses = Set(running_addresses).difference( | |
153 | Set(addresses)) | |
154 | [ifaceobjcurr.update_config_with_status(attrname, a, 1) | |
155 | for a in running_addresses] | |
156 | ||
15ef32ea RP |
157 | def _query_check(self, ifaceobj, ifaceobjcurr): |
158 | if not self.ipcmd.link_exists(ifaceobj.name): | |
15ef32ea | 159 | return |
15ef32ea | 160 | # Update vxlan object |
9e012f9e RP |
161 | vxlanattrs = self.ipcmd.get_vxlandev_attrs(ifaceobj.name) |
162 | if not vxlanattrs: | |
a070c90e | 163 | ifaceobjcurr.check_n_update_config_with_status_many(ifaceobj, |
9e012f9e RP |
164 | self.get_mod_attrs(), -1) |
165 | return | |
f50f16fa | 166 | self._query_check_n_update(ifaceobj, ifaceobjcurr, 'vxlan-id', |
9e012f9e RP |
167 | ifaceobj.get_attr_value_first('vxlan-id'), |
168 | vxlanattrs.get('vxlanid')) | |
169 | ||
a794fb31 BR |
170 | running_attrval = vxlanattrs.get('local') |
171 | attrval = ifaceobj.get_attr_value_first('vxlan-local-tunnelip') | |
172 | if running_attrval == self._clagd_vxlan_anycast_ip: | |
173 | # if local ip is anycast_ip, then let query_check to go through | |
174 | attrval = self._clagd_vxlan_anycast_ip | |
f50f16fa | 175 | self._query_check_n_update(ifaceobj, ifaceobjcurr, 'vxlan-local-tunnelip', |
a794fb31 | 176 | attrval, running_attrval) |
9e012f9e | 177 | |
f50f16fa | 178 | self._query_check_n_update(ifaceobj, ifaceobjcurr, 'vxlan-svcnodeip', |
c07383d1 BR |
179 | ifaceobj.get_attr_value_first('vxlan-svcnodeip'), |
180 | vxlanattrs.get('svcnode')) | |
9e012f9e | 181 | |
dae9c5de | 182 | if not systemUtils.is_service_running(None, '/var/run/vxrd.pid'): |
a794fb31 | 183 | # vxlan-remoteip config is allowed only if vxrd is not running |
8e595218 | 184 | self._query_check_n_update_addresses(ifaceobjcurr, 'vxlan-remoteip', |
a794fb31 BR |
185 | ifaceobj.get_attr_value('vxlan-remoteip'), |
186 | vxlanattrs.get('remote', [])) | |
9e012f9e RP |
187 | |
188 | learning = ifaceobj.get_attr_value_first('vxlan-learning') | |
44533c72 WK |
189 | if not learning: |
190 | learning = 'on' | |
594fb088 | 191 | |
9e012f9e | 192 | running_learning = vxlanattrs.get('learning') |
594fb088 JF |
193 | if learning == 'yes' and running_learning == 'on': |
194 | running_learning = 'yes' | |
195 | elif learning == 'no' and running_learning == 'off': | |
196 | running_learning = 'no' | |
197 | ||
9e012f9e RP |
198 | if learning == running_learning: |
199 | ifaceobjcurr.update_config_with_status('vxlan-learning', | |
200 | running_learning, 0) | |
201 | else: | |
202 | ifaceobjcurr.update_config_with_status('vxlan-learning', | |
203 | running_learning, 1) | |
27f2a937 BR |
204 | ageing = ifaceobj.get_attr_value_first('vxlan-ageing') |
205 | if not ageing: | |
206 | ageing = self.get_mod_subattr('vxlan-ageing', 'default') | |
f50f16fa | 207 | self._query_check_n_update(ifaceobj, ifaceobjcurr, 'vxlan-ageing', |
27f2a937 | 208 | ageing, vxlanattrs.get('ageing')) |
15ef32ea RP |
209 | |
210 | def _query_running(self, ifaceobjrunning): | |
9e012f9e RP |
211 | vxlanattrs = self.ipcmd.get_vxlandev_attrs(ifaceobjrunning.name) |
212 | if not vxlanattrs: | |
213 | return | |
3eee421a RP |
214 | attrval = vxlanattrs.get('vxlanid') |
215 | if attrval: | |
216 | ifaceobjrunning.update_config('vxlan-id', vxlanattrs.get('vxlanid')) | |
9e012f9e RP |
217 | attrval = vxlanattrs.get('local') |
218 | if attrval: | |
219 | ifaceobjrunning.update_config('vxlan-local-tunnelip', attrval) | |
220 | attrval = vxlanattrs.get('svcnode') | |
221 | if attrval: | |
c07383d1 | 222 | ifaceobjrunning.update_config('vxlan-svcnode', attrval) |
dae9c5de | 223 | if not systemUtils.is_service_running(None, '/var/run/vxrd.pid'): |
a794fb31 BR |
224 | # vxlan-remoteip config is allowed only if vxrd is not running |
225 | attrval = vxlanattrs.get('remote') | |
226 | if attrval: | |
227 | [ifaceobjrunning.update_config('vxlan-remoteip', a) | |
228 | for a in attrval] | |
9e012f9e RP |
229 | attrval = vxlanattrs.get('learning') |
230 | if attrval and attrval == 'on': | |
231 | ifaceobjrunning.update_config('vxlan-learning', 'on') | |
88a5c4c8 ST |
232 | attrval = vxlanattrs.get('ageing') |
233 | if attrval: | |
234 | ifaceobjrunning.update_config('vxlan-ageing', vxlanattrs.get('ageing')) | |
15ef32ea RP |
235 | |
236 | _run_ops = {'pre-up' : _up, | |
237 | 'post-down' : _down, | |
238 | 'query-checkcurr' : _query_check, | |
239 | 'query-running' : _query_running} | |
240 | ||
241 | def get_ops(self): | |
242 | return self._run_ops.keys() | |
243 | ||
244 | def _init_command_handlers(self): | |
245 | if not self.ipcmd: | |
fc5e1735 | 246 | self.ipcmd = iproute2() |
15ef32ea | 247 | |
84ca006f | 248 | def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args): |
15ef32ea RP |
249 | op_handler = self._run_ops.get(operation) |
250 | if not op_handler: | |
251 | return | |
252 | if (operation != 'query-running' and | |
253 | not self._is_vxlan_device(ifaceobj)): | |
254 | return | |
255 | self._init_command_handlers() | |
256 | if operation == 'query-checkcurr': | |
257 | op_handler(self, ifaceobj, query_ifaceobj) | |
258 | else: | |
259 | op_handler(self, ifaceobj) |