]> git.proxmox.com Git - mirror_ifupdown2.git/blame - addons/vxlan.py
attribute syntax check using validvals/validrange and keywords
[mirror_ifupdown2.git] / addons / vxlan.py
CommitLineData
15ef32ea
RP
1#!/usr/bin/python
2
3from ifupdown.iface import *
594fb088 4from ifupdown.utils import utils
15ef32ea
RP
5from ifupdownaddons.modulebase import moduleBase
6from ifupdownaddons.iproute2 import iproute2
dae9c5de 7from ifupdownaddons.systemutils import systemUtils
2864d6f3 8from ifupdown.netlink import netlink
c6370b56 9from ipaddr import IPv4Address
2864d6f3 10import ifupdown.ifupdownflags as ifupdownflags
15ef32ea 11import logging
a794fb31 12import os
9e012f9e 13from sets import Set
15ef32ea
RP
14
15class 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)