]>
Commit | Line | Data |
---|---|---|
1aa30813 | 1 | From 4311f4deb9b95e67694c04ced13782a3608a176b Mon Sep 17 00:00:00 2001 |
bf9a532c AD |
2 | From: Alexandre Derumier <aderumier@odiso.com> |
3 | Date: Mon, 17 Feb 2020 13:32:18 +0100 | |
4 | Subject: [PATCH] add openvswitch addon | |
5 | ||
1aa30813 | 6 | Signed-off-by: Alexandre Derumier <aderumier@odiso.com> |
bf9a532c AD |
7 | --- |
8 | etc/network/ifupdown2/addons.conf | 4 + | |
1aa30813 | 9 | ifupdown2/addons/openvswitch.py | 248 ++++++++++++++++++++++++ |
bf9a532c AD |
10 | ifupdown2/addons/openvswitch_port.py | 274 +++++++++++++++++++++++++++ |
11 | ifupdown2/lib/iproute2.py | 3 + | |
12 | ifupdown2/nlmanager/nlpacket.py | 1 + | |
1aa30813 | 13 | 5 files changed, 530 insertions(+) |
bf9a532c AD |
14 | create mode 100644 ifupdown2/addons/openvswitch.py |
15 | create mode 100644 ifupdown2/addons/openvswitch_port.py | |
16 | ||
17 | diff --git a/etc/network/ifupdown2/addons.conf b/etc/network/ifupdown2/addons.conf | |
1aa30813 | 18 | index c43d377..8811cc2 100644 |
bf9a532c AD |
19 | --- a/etc/network/ifupdown2/addons.conf |
20 | +++ b/etc/network/ifupdown2/addons.conf | |
21 | @@ -1,3 +1,5 @@ | |
22 | +pre-up,openvswitch | |
23 | +pre-up,openvswitch_port | |
24 | pre-up,xfrm | |
25 | pre-up,link | |
26 | pre-up,ppp | |
1aa30813 | 27 | @@ -43,3 +45,5 @@ post-down,usercmds |
bf9a532c AD |
28 | post-down,link |
29 | post-down,tunnel | |
30 | post-down,xfrm | |
31 | +post-down,openvswitch_port | |
32 | +post-down,openvswitch | |
33 | diff --git a/ifupdown2/addons/openvswitch.py b/ifupdown2/addons/openvswitch.py | |
34 | new file mode 100644 | |
1aa30813 | 35 | index 0000000..1d4c563 |
bf9a532c AD |
36 | --- /dev/null |
37 | +++ b/ifupdown2/addons/openvswitch.py | |
1aa30813 | 38 | @@ -0,0 +1,248 @@ |
bf9a532c AD |
39 | +#!/usr/bin/python |
40 | +# | |
41 | +# Copyright 2020 Alexandre Derumier <aderumier@odiso.com> | |
42 | +# Author: Alexandre Derumier, aderumier@odiso.com | |
43 | +# | |
44 | + | |
45 | +try: | |
46 | + from ifupdown2.lib.addon import Addon | |
47 | + | |
48 | + from ifupdown2.ifupdown.iface import * | |
49 | + from ifupdown2.ifupdown.utils import utils | |
50 | + from ifupdown2.ifupdownaddons.modulebase import moduleBase | |
51 | + from ifupdown2.ifupdown.exceptions import moduleNotSupported | |
52 | + import ifupdown2.ifupdown.ifupdownflags as ifupdownflags | |
53 | + | |
54 | +except: | |
55 | + from lib.addon import Addon | |
56 | + | |
57 | + from ifupdown.iface import * | |
58 | + from ifupdown.utils import utils | |
59 | + from ifupdownaddons.modulebase import moduleBase | |
60 | + from ifupdown.exceptions import moduleNotSupported | |
61 | + import ifupdown.ifupdownflags as ifupdownflags | |
62 | + | |
63 | +import logging | |
64 | +import re | |
65 | +import subprocess | |
66 | +import os | |
67 | + | |
68 | +class openvswitch(Addon, moduleBase): | |
69 | + """ ifupdown2 addon module to configure Openvswitch bridge """ | |
70 | + | |
71 | + _modinfo = { | |
72 | + 'mhelp': 'openvswitch module configure openvswitch bridges', | |
73 | + 'attrs': { | |
74 | + 'ovs-ports': { | |
75 | + 'help': 'Interfaces to be part of this ovs bridge.', | |
76 | + 'validvals': ['<interface-list>'], | |
77 | + 'required': False, | |
78 | + }, | |
79 | + 'ovs-type': { | |
80 | + 'help': 'ovs interface type', | |
81 | + 'validvals': ['OVSBridge'], | |
82 | + 'required': True, | |
83 | + }, | |
84 | + 'ovs-mtu': { | |
85 | + 'help': 'Interface MTU (maximum transmission unit)', | |
86 | + 'validrange': ['552', '9216'], | |
87 | + 'example': ['ovs-mtu 1600'], | |
88 | + 'default': '1500' | |
89 | + }, | |
90 | + 'ovs-options': { | |
91 | + 'help': 'This option lets you add extra arguments to a ovs-vsctl command', | |
92 | + 'required': False, | |
93 | + }, | |
94 | + 'ovs-extra': { | |
95 | + 'help': 'This option lets you run additional ovs-vsctl commands,' + | |
96 | + 'separated by "--" (double dash). Variables can be part of the "ovs_extra"' + | |
97 | + 'option. You can provide all the standard environmental variables' + | |
98 | + 'described in the interfaces(5) man page. You can also pass shell' + | |
99 | + 'commands.extra args', | |
100 | + 'required': False, | |
101 | + 'example': ['ovs_extra set bridge ${IFACE} other-config:hwaddr=00:59:cf:9c:84:3a -- br-set-external-id ${IFACE} bridge-id ${IFACE}'] | |
102 | + | |
103 | + }, | |
1aa30813 AD |
104 | + 'ovs-ports-condone-regex': { |
105 | + "help": "bridge ports to ignore/condone when reloading config / removing interfaces", | |
106 | + "required": False, | |
107 | + "default": "^(tap|veth|fwln)", | |
108 | + "example": ["ovs-ports-condone-regex ^[a-zA-Z0-9]+_v[0-9]{1,4}$"] | |
109 | + }, | |
bf9a532c AD |
110 | + } |
111 | + } | |
112 | + | |
113 | + def __init__ (self, *args, **kargs): | |
114 | + moduleBase.__init__ (self, *args, **kargs) | |
115 | + Addon.__init__(self) | |
116 | + if not os.path.exists('/usr/bin/ovs-vsctl'): | |
117 | + raise moduleNotSupported('module init failed: no /usr/bin/ovs-vsctl found') | |
118 | + | |
119 | + def _is_ovs_bridge (self, ifaceobj): | |
120 | + ovstype = ifaceobj.get_attr_value_first('ovs-type') | |
121 | + if ovstype: | |
122 | + if ovstype == 'OVSBridge': | |
123 | + return True | |
124 | + else: | |
125 | + return False | |
126 | + return False | |
127 | + | |
128 | + def _get_ovs_ports (self, ifaceobj): | |
129 | + ovs_ports = ifaceobj.get_attr_value_first('ovs-ports') | |
130 | + if ovs_ports: | |
131 | + return sorted (ovs_ports.split ()) | |
132 | + return None | |
133 | + | |
134 | + def _get_running_ovs_ports (self, iface): | |
135 | + output = utils.exec_command("/usr/bin/ovs-vsctl list-ports %s" %iface) | |
136 | + if output: | |
137 | + ovs_ports = sorted(output.splitlines()) | |
138 | + return ovs_ports | |
139 | + return None | |
140 | + | |
1aa30813 AD |
141 | + def _get_ovs_port_condone_regex(self, ifaceobj, get_string = False): |
142 | + ovs_port_condone_regex = ifaceobj.get_attr_value_first('ovs-ports-condone-regex') | |
143 | + if not ovs_port_condone_regex: | |
144 | + ovs_port_condone_regex = self.get_attr_default_value('ovs-ports-condone-regex') | |
145 | + | |
146 | + if ovs_port_condone_regex: | |
147 | + if get_string: | |
148 | + return ovs_port_condone_regex | |
149 | + return re.compile (r"%s" % ovs_port_condone_regex) | |
150 | + return None | |
151 | + | |
bf9a532c AD |
152 | + def _ovs_vsctl(self, ifaceobj, cmdlist): |
153 | + | |
154 | + if cmdlist: | |
155 | + | |
156 | + os.environ['IFACE'] = ifaceobj.name if ifaceobj.name else '' | |
157 | + os.environ['LOGICAL'] = ifaceobj.name if ifaceobj.name else '' | |
158 | + os.environ['METHOD'] = ifaceobj.addr_method if ifaceobj.addr_method else '' | |
159 | + os.environ['ADDRFAM'] = ','.join(ifaceobj.addr_family) if ifaceobj.addr_family else '' | |
160 | + | |
161 | + finalcmd = "/usr/bin/ovs-vsctl" | |
162 | + | |
163 | + for cmd in cmdlist: | |
164 | + finalcmd = finalcmd + " -- " + cmd | |
165 | + | |
166 | + try: | |
167 | + self.logger.debug ("Running %s" % (finalcmd)) | |
168 | + utils.exec_user_command(finalcmd) | |
169 | + except subprocess.CalledProcessError as c: | |
170 | + raise Exception ("Command \"%s failed: %s" % (finalcmd, c.output)) | |
171 | + except Exception as e: | |
172 | + raise Exception ("%s" % e) | |
173 | + | |
174 | + def _addbridge (self, ifaceobj): | |
175 | + | |
176 | + iface = ifaceobj.name | |
177 | + ovsoptions = ifaceobj.get_attr_value_first ('ovs-options') | |
178 | + ovsextra = ifaceobj.get_attr_value('ovs-extra') | |
179 | + ovsmtu = ifaceobj.get_attr_value_first ('ovs-mtu') | |
180 | + | |
181 | + cmd_list = [] | |
182 | + | |
183 | + cmd = "--may-exist add-br %s"%(iface) | |
184 | + cmd_list.append(cmd) | |
185 | + | |
186 | + if ovsoptions: | |
187 | + cmd = "set bridge %s %s" %(iface, ovsoptions) | |
188 | + cmd_list.append(cmd) | |
189 | + | |
190 | + #update | |
191 | + if self.cache.link_exists (iface): | |
1aa30813 AD |
192 | + |
193 | + ovsportscondoneregex = self._get_ovs_port_condone_regex(ifaceobj) | |
bf9a532c AD |
194 | + # on update, delete active ports not in the new port list |
195 | + ovs_ports = self._get_ovs_ports(ifaceobj) | |
196 | + running_ovs_ports = self._get_running_ovs_ports(iface) | |
197 | + if running_ovs_ports is not None and ovs_ports is not None: | |
198 | + missingports = list(set(running_ovs_ports) - set(ovs_ports)) | |
199 | + | |
200 | + if missingports is not None: | |
201 | + for port in missingports: | |
1aa30813 AD |
202 | + if ovsportscondoneregex and ovsportscondoneregex.match(port): |
203 | + self.logger.info("%s: port %s will stay enslaved as it matches with ovs-ports-condone-regex" % (ifaceobj.name, port)) | |
204 | + continue | |
bf9a532c AD |
205 | + cmd = "--if-exists del-port %s %s"%(iface, port) |
206 | + cmd_list.append(cmd) | |
207 | + | |
208 | + #clear old bridge options | |
209 | + cmd = "--if-exists clear bridge %s auto_attach controller external-ids fail_mode flood_vlans ipfix mirrors netflow other_config protocols sflow"%(iface) | |
210 | + | |
211 | + cmd_list.append(cmd) | |
212 | + | |
213 | + #clear old interface options | |
214 | + cmd = "--if-exists clear interface %s mtu_request external-ids other_config options"%(iface) | |
215 | + cmd_list.append(cmd) | |
216 | + | |
217 | + if ovsextra is not None: | |
218 | + cmd_list.extend(ovsextra) | |
219 | + | |
220 | + if ovsmtu is not None: | |
221 | + cmd = "set Interface %s mtu_request=%s"%(iface, ovsmtu) | |
222 | + cmd_list.append(cmd) | |
223 | + | |
224 | + self._ovs_vsctl(ifaceobj, cmd_list) | |
225 | + if not self.cache.link_exists(ifaceobj.name): | |
226 | + self.iproute2.link_add_openvswitch(ifaceobj.name, "openvswitch") | |
227 | + | |
228 | + def _delbridge (self, ifaceobj): | |
229 | + | |
230 | + cmd = "del-br %s"%(ifaceobj.name) | |
231 | + self._ovs_vsctl(ifaceobj, [cmd]) | |
232 | + | |
233 | + def get_dependent_ifacenames (self, ifaceobj, ifaceobjs_all=None): | |
234 | + return None | |
235 | + | |
236 | + def _up (self, ifaceobj): | |
237 | + self._addbridge (ifaceobj) | |
238 | + | |
239 | + def _down (self, ifaceobj): | |
240 | + if not ifupdownflags.flags.PERFMODE and not self.cache.link_exists (ifaceobj.name): | |
241 | + return | |
242 | + | |
243 | + self._delbridge (ifaceobj) | |
244 | + | |
245 | + def _query_check (self, ifaceobj, ifaceobjcurr): | |
246 | + if not self.cache.link_exists (ifaceobj.name): | |
247 | + return | |
248 | + return | |
249 | + | |
250 | + _run_ops = { | |
251 | + 'pre-up': _up, | |
252 | + 'post-down': _down, | |
253 | + 'query-checkcurr': _query_check | |
254 | + } | |
255 | + | |
256 | + def get_ops (self): | |
257 | + """ returns list of ops supported by this module """ | |
258 | + return self._run_ops.keys () | |
259 | + | |
260 | + def run (self, ifaceobj, operation, query_ifaceobj = None, **extra_args): | |
261 | + """ run openvswitch configuration on the interface object passed as argument | |
262 | + | |
263 | + Args: | |
264 | + **ifaceobj** (object): iface object | |
265 | + | |
266 | + **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr', | |
267 | + 'query-running' | |
268 | + Kwargs: | |
269 | + **query_ifaceobj** (object): query check ifaceobject. This is only | |
270 | + valid when op is 'query-checkcurr'. It is an object same as | |
271 | + ifaceobj, but contains running attribute values and its config | |
272 | + status. The modules can use it to return queried running state | |
273 | + of interfaces. status is success if the running state is same | |
274 | + as user required state in ifaceobj. error otherwise. | |
275 | + """ | |
276 | + op_handler = self._run_ops.get (operation) | |
277 | + if not op_handler: | |
278 | + return | |
279 | + | |
280 | + if (operation != 'query-running' and not self._is_ovs_bridge (ifaceobj)): | |
281 | + return | |
282 | + | |
283 | + if operation == 'query-checkcurr': | |
284 | + op_handler (self, ifaceobj, query_ifaceobj) | |
285 | + else: | |
286 | + op_handler (self, ifaceobj) | |
287 | diff --git a/ifupdown2/addons/openvswitch_port.py b/ifupdown2/addons/openvswitch_port.py | |
288 | new file mode 100644 | |
289 | index 0000000..e34cc18 | |
290 | --- /dev/null | |
291 | +++ b/ifupdown2/addons/openvswitch_port.py | |
292 | @@ -0,0 +1,274 @@ | |
293 | +#!/usr/bin/python | |
294 | +# | |
295 | +# Copyright 2020 Alexandre Derumier <aderumier@odiso.com> | |
296 | +# Author: Alexandre Derumier, aderumier@odiso.com | |
297 | +# | |
298 | + | |
299 | +try: | |
300 | + from ifupdown2.lib.addon import Addon | |
301 | + | |
302 | + from ifupdown2.ifupdown.iface import * | |
303 | + from ifupdown2.ifupdown.utils import utils | |
304 | + from ifupdown2.ifupdownaddons.modulebase import moduleBase | |
305 | + from ifupdown2.ifupdown.exceptions import moduleNotSupported | |
306 | + import ifupdown2.ifupdown.ifupdownflags as ifupdownflags | |
307 | + | |
308 | +except: | |
309 | + from lib.addon import Addon | |
310 | + | |
311 | + from ifupdown.iface import * | |
312 | + from ifupdown.utils import utils | |
313 | + from ifupdownaddons.modulebase import moduleBase | |
314 | + from ifupdown.exceptions import moduleNotSupported | |
315 | + import ifupdown.ifupdownflags as ifupdownflags | |
316 | + | |
317 | +import logging | |
318 | +import re | |
319 | +import subprocess | |
320 | +import os | |
321 | + | |
322 | +class openvswitch_port(Addon, moduleBase): | |
323 | + """ ifupdown2 addon module to configure openvswitch ports """ | |
324 | + | |
325 | + _modinfo = { | |
326 | + 'mhelp': 'openvswitch module configure openvswitch ports', | |
327 | + 'attrs': { | |
328 | + 'ovs-bridge': { | |
329 | + 'help': 'Interfaces to be part of this ovs bridge', | |
330 | + 'required': True, | |
331 | + }, | |
332 | + 'ovs-type': { | |
333 | + 'help': 'ovs interface type', | |
334 | + 'validvals': ['OVSPort', 'OVSIntPort', 'OVSBond', 'OVSTunnel', 'OVSPatchPort'], | |
335 | + 'required': True, | |
336 | + 'example': ['ovs-type OVSPort'], | |
337 | + }, | |
338 | + 'ovs-options': { | |
339 | + 'help': 'This option lets you add extra arguments to a ovs-vsctl command', | |
340 | + 'required': False, | |
341 | + 'example': ['ovs_options bond_mode=balance-tcp lacp=active tag=100'] | |
342 | + }, | |
343 | + 'ovs-extra': { | |
344 | + 'help': 'This option lets you run additional ovs-vsctl commands,' + | |
345 | + 'separated by "--" (double dash). Variables can be part of the "ovs_extra"' + | |
346 | + 'option. You can provide all the standard environmental variables' + | |
347 | + 'described in the interfaces(5) man page. You can also pass shell' + | |
348 | + 'commands.extra args', | |
349 | + 'required': False, | |
350 | + 'example': ['ovs_extra set interface ${IFACE} external-ids:iface-id=$(hostname -s)'] | |
351 | + }, | |
352 | + 'ovs-bonds': { | |
353 | + 'help': 'Interfaces to be part of this ovs bond', | |
354 | + 'validvals': ['<interface-list>'], | |
355 | + 'required': False, | |
356 | + }, | |
357 | + 'ovs-tunnel-type': { | |
358 | + 'help': 'For "OVSTunnel" interfaces, the type of the tunnel', | |
359 | + 'required': False, | |
360 | + 'example': ['ovs-tunnel-type gre'], | |
361 | + }, | |
362 | + 'ovs-tunnel-options': { | |
363 | + 'help': 'For "OVSTunnel" interfaces, this field should be ' + | |
364 | + 'used to specify the tunnel options like remote_ip, key, etc.', | |
365 | + 'required': False, | |
366 | + 'example': ['ovs-tunnel-options options:remote_ip=182.168.1.2 options:key=1'], | |
367 | + }, | |
368 | + 'ovs-patch-peer': { | |
369 | + 'help': 'ovs patch peer', | |
370 | + 'required': False, | |
371 | + 'example': ['ovs-patch-peer patch0'], | |
372 | + }, | |
373 | + 'ovs-mtu': { | |
374 | + 'help': 'mtu of the ovs interface', | |
375 | + 'required': False, | |
376 | + 'example': ['ovs-mtu 9000'], | |
377 | + }, | |
378 | + } | |
379 | + } | |
380 | + | |
381 | + def __init__ (self, *args, **kargs): | |
382 | + moduleBase.__init__ (self, *args, **kargs) | |
383 | + Addon.__init__(self) | |
384 | + if not os.path.exists('/usr/bin/ovs-vsctl'): | |
385 | + raise moduleNotSupported('module init failed: no /usr/bin/ovs-vsctl found') | |
386 | + | |
387 | + def _is_ovs_port (self, ifaceobj): | |
388 | + ovstype = ifaceobj.get_attr_value_first ('ovs-type') | |
389 | + ovsbridge = ifaceobj.get_attr_value_first ('ovs-bridge') | |
390 | + if ovstype and ovsbridge: | |
391 | + return True | |
392 | + return False | |
393 | + | |
394 | + def _get_bond_ifaces (self, ifaceobj): | |
395 | + ovs_bonds = ifaceobj.get_attr_value_first ('ovs-bonds') | |
396 | + if ovs_bonds: | |
397 | + return sorted (ovs_bonds.split ()) | |
398 | + return None | |
399 | + | |
400 | + def _ovs_vsctl(self, ifaceobj, cmdlist): | |
401 | + | |
402 | + if cmdlist: | |
403 | + | |
404 | + os.environ['IFACE'] = ifaceobj.name if ifaceobj.name else '' | |
405 | + os.environ['LOGICAL'] = ifaceobj.name if ifaceobj.name else '' | |
406 | + os.environ['METHOD'] = ifaceobj.addr_method if ifaceobj.addr_method else '' | |
407 | + os.environ['ADDRFAM'] = ','.join(ifaceobj.addr_family) if ifaceobj.addr_family else '' | |
408 | + | |
409 | + finalcmd = "/usr/bin/ovs-vsctl" | |
410 | + | |
411 | + for cmd in cmdlist: | |
412 | + finalcmd = finalcmd + " -- " + cmd | |
413 | + | |
414 | + try: | |
415 | + self.logger.debug ("Running %s" % (finalcmd)) | |
416 | + utils.exec_user_command(finalcmd) | |
417 | + except subprocess.CalledProcessError as c: | |
418 | + raise Exception ("Command \"%s failed: %s" % (finalcmd, c.output)) | |
419 | + except Exception as e: | |
420 | + raise Exception ("%s" % e) | |
421 | + | |
422 | + def _addport (self, ifaceobj): | |
423 | + iface = ifaceobj.name | |
424 | + ovsbridge = ifaceobj.get_attr_value_first ('ovs-bridge') | |
425 | + ovsoptions = ifaceobj.get_attr_value_first ('ovs-options') | |
426 | + ovstype = ifaceobj.get_attr_value_first ('ovs-type') | |
427 | + ovsbonds = ifaceobj.get_attr_value_first ('ovs-bonds') | |
428 | + ovsextra = ifaceobj.get_attr_value('ovs-extra') | |
429 | + | |
430 | + cmd_list = [] | |
431 | + | |
432 | + if ovstype == 'OVSBond': | |
433 | + if ovsbonds is None: | |
434 | + raise Exception ("missing ovs-bonds option") | |
435 | + cmd = "--may-exist --fake-iface add-bond %s %s %s"%(ovsbridge, iface, ovsbonds) | |
436 | + cmd_list.append(cmd) | |
437 | + else: | |
438 | + cmd = "--may-exist add-port %s %s"%(ovsbridge, iface) | |
439 | + cmd_list.append(cmd) | |
440 | + | |
441 | + | |
442 | + #clear old ports options | |
443 | + cmd = "--if-exists clear port %s bond_active_slave bond_mode cvlans external_ids lacp mac other_config qos tag trunks vlan_mode"%(iface) | |
444 | + cmd_list.append(cmd) | |
445 | + | |
446 | + #clear old interface options | |
447 | + cmd = "--if-exists clear interface %s mtu_request external-ids other_config options"%(iface) | |
448 | + cmd_list.append(cmd) | |
449 | + | |
450 | + if ovsoptions: | |
451 | + cmd = "set Port %s %s" %(iface, ovsoptions) | |
452 | + cmd_list.append(cmd) | |
453 | + | |
454 | + | |
455 | + if ovstype == 'OVSIntPort': | |
456 | + cmd = "set Interface %s type=internal"%(iface) | |
457 | + cmd_list.append(cmd) | |
458 | + | |
459 | + if ovstype == 'OVSTunnel': | |
460 | + ovstunneltype = ifaceobj.get_attr_value_first ('ovs-tunnel-type') | |
461 | + if ovstunneltype is None: | |
462 | + raise Exception ("missing ovs-tunnel-type option") | |
463 | + ovstunneloptions = ifaceobj.get_attr_value_first('ovs-tunnel-options') | |
464 | + if ovstunneloptions is None: | |
465 | + raise Exception ("missing ovs-tunnel-options option") | |
466 | + cmd = "set Interface %s type=%s %s"%(iface, ovstunneltype, ovstunneloptions) | |
467 | + cmd_list.append(cmd) | |
468 | + | |
469 | + if ovstype == 'OVSPatchPort': | |
470 | + ovspatchpeer = ifaceobj.get_attr_value_first ('ovs-patch-peer') | |
471 | + if ovspatchpeer is None: | |
472 | + raise Exception ("missing ovs-patch-peer") | |
473 | + cmd = "set Interface %s type=patch options:peer=%s"%(iface, ovspatchpeer) | |
474 | + cmd_list.append(cmd) | |
475 | + | |
476 | + #mtu | |
477 | + ovsmtu = ifaceobj.get_attr_value_first ('ovs-mtu') | |
478 | + ovsbonds_list = self._get_bond_ifaces(ifaceobj) | |
479 | + if ovsmtu is not None: | |
480 | + #we can't set mtu on bond fake interface, we apply it on slaves interfaces | |
481 | + if ovstype == 'OVSBond' and ovsbonds_list is not None: | |
482 | + for slave in ovsbonds_list: | |
483 | + cmd = "set Interface %s mtu_request=%s"%(slave,ovsmtu) | |
484 | + cmd_list.append(cmd) | |
485 | + | |
486 | + else: | |
487 | + cmd = "set Interface %s mtu_request=%s"%(iface,ovsmtu) | |
488 | + cmd_list.append(cmd) | |
489 | + | |
490 | + #extra | |
491 | + if ovsextra is not None: | |
492 | + cmd_list.extend(ovsextra) | |
493 | + | |
494 | + self._ovs_vsctl(ifaceobj, cmd_list) | |
495 | + | |
496 | + if ovstype != 'OVSTunnel' and ovstype != 'OVSPatchPort': | |
497 | + if not self.cache.link_exists(ifaceobj.name): | |
498 | + self.iproute2.link_add_openvswitch(ifaceobj.name, "openvswitch") | |
499 | + | |
500 | + def _delport (self, ifaceobj): | |
501 | + iface = ifaceobj.name | |
502 | + ovsbridge = ifaceobj.get_attr_value_first ('ovs-bridge') | |
503 | + cmd = "--if-exists del-port %s %s"%(ovsbridge, iface) | |
504 | + | |
505 | + self._ovs_vsctl(ifaceobj, [cmd]) | |
506 | + | |
507 | + def get_dependent_ifacenames (self, ifaceobj, ifaceobjs_all=None): | |
508 | + | |
509 | + if not self._is_ovs_port (ifaceobj): | |
510 | + return None | |
511 | + | |
512 | + ovsbridge = ifaceobj.get_attr_value_first ('ovs-bridge') | |
513 | + return [ovsbridge] | |
514 | + | |
515 | + def _up (self, ifaceobj): | |
516 | + | |
517 | + self._addport (ifaceobj) | |
518 | + | |
519 | + def _down (self, ifaceobj): | |
520 | + if not ifupdownflags.flags.PERFMODE and not self.cache.link_exists (ifaceobj.name): | |
521 | + return | |
522 | + | |
523 | + self._delport (ifaceobj) | |
524 | + | |
525 | + def _query_check (self, ifaceobj, ifaceobjcurr): | |
526 | + if not self.cache.link_exists (ifaceobj.name): | |
527 | + return | |
528 | + return | |
529 | + | |
530 | + _run_ops = { | |
531 | + 'pre-up': _up, | |
532 | + 'post-down': _down, | |
533 | + 'query-checkcurr': _query_check | |
534 | + } | |
535 | + | |
536 | + def get_ops (self): | |
537 | + """ returns list of ops supported by this module """ | |
538 | + return self._run_ops.keys () | |
539 | + | |
540 | + def run (self, ifaceobj, operation, query_ifaceobj = None, **extra_args): | |
541 | + """ run Openvswitch port configuration on the interface object passed as argument | |
542 | + | |
543 | + Args: | |
544 | + **ifaceobj** (object): iface object | |
545 | + | |
546 | + **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr', | |
547 | + 'query-running' | |
548 | + Kwargs: | |
549 | + **query_ifaceobj** (object): query check ifaceobject. This is only | |
550 | + valid when op is 'query-checkcurr'. It is an object same as | |
551 | + ifaceobj, but contains running attribute values and its config | |
552 | + status. The modules can use it to return queried running state | |
553 | + of interfaces. status is success if the running state is same | |
554 | + as user required state in ifaceobj. error otherwise. | |
555 | + """ | |
556 | + op_handler = self._run_ops.get (operation) | |
557 | + if not op_handler: | |
558 | + return | |
559 | + | |
560 | + if (operation != 'query-running' and not self._is_ovs_port (ifaceobj)): | |
561 | + return | |
562 | + | |
563 | + if operation == 'query-checkcurr': | |
564 | + op_handler (self, ifaceobj, query_ifaceobj) | |
565 | + else: | |
566 | + op_handler (self, ifaceobj) | |
567 | diff --git a/ifupdown2/lib/iproute2.py b/ifupdown2/lib/iproute2.py | |
568 | index 704d120..a1223b9 100644 | |
569 | --- a/ifupdown2/lib/iproute2.py | |
570 | +++ b/ifupdown2/lib/iproute2.py | |
571 | @@ -334,6 +334,9 @@ class IPRoute2(Cache, Requirements): | |
572 | def link_add_xfrm(ifname, xfrm_name, xfrm_id): | |
573 | utils.exec_commandl(['ip', 'link', 'add', xfrm_name, 'type', 'xfrm', 'dev', ifname, 'if_id', xfrm_id]) | |
574 | ||
575 | + def link_add_openvswitch(self, ifname, kind): | |
576 | + self.__update_cache_after_link_creation(ifname, kind) | |
577 | + | |
578 | ############################################################################ | |
579 | # TUNNEL | |
580 | ############################################################################ | |
581 | diff --git a/ifupdown2/nlmanager/nlpacket.py b/ifupdown2/nlmanager/nlpacket.py | |
582 | index fcb89fb..c8a0697 100644 | |
583 | --- a/ifupdown2/nlmanager/nlpacket.py | |
584 | +++ b/ifupdown2/nlmanager/nlpacket.py | |
585 | @@ -2791,6 +2791,7 @@ class AttributeIFLA_LINKINFO(Attribute): | |
586 | "dummy", | |
587 | "bridge", | |
588 | "macvlan", | |
589 | + "openvswitch" | |
590 | ): | |
591 | self.log.debug('Unsupported IFLA_INFO_KIND %s' % kind) | |
592 | return | |
593 | -- | |
594 | 2.20.1 | |
595 |