]>
git.proxmox.com Git - mirror_ifupdown2.git/blob - ifupdown2/addons/openvswitch_port.py
394ed663f034e2eea60f3eaf830d5c824960f74a
3 # Copyright 2020 Alexandre Derumier <aderumier@odiso.com>
4 # Author: Alexandre Derumier, aderumier@odiso.com
8 from ifupdown2
.lib
.addon
import Addon
10 from ifupdown2
.ifupdown
.iface
import *
11 from ifupdown2
.ifupdown
.utils
import utils
12 from ifupdown2
.ifupdownaddons
.modulebase
import moduleBase
13 from ifupdown2
.ifupdown
.exceptions
import moduleNotSupported
14 import ifupdown2
.ifupdown
.ifupdownflags
as ifupdownflags
17 from lib
.addon
import Addon
19 from ifupdown
.iface
import *
20 from ifupdown
.utils
import utils
21 from ifupdownaddons
.modulebase
import moduleBase
22 from ifupdown
.exceptions
import moduleNotSupported
23 import ifupdown
.ifupdownflags
as ifupdownflags
30 class openvswitch_port(Addon
, moduleBase
):
31 """ ifupdown2 addon module to configure openvswitch ports """
34 'mhelp': 'openvswitch module configure openvswitch ports',
37 'help': 'Interfaces to be part of this ovs bridge',
41 'help': 'ovs interface type',
42 'validvals': ['OVSPort', 'OVSIntPort', 'OVSBond', 'OVSTunnel', 'OVSPatchPort'],
44 'example': ['ovs-type OVSPort'],
47 'help': 'This option lets you add extra arguments to a ovs-vsctl command',
49 'example': ['ovs_options bond_mode=balance-tcp lacp=active tag=100']
52 'help': 'This option lets you run additional ovs-vsctl commands,' +
53 'separated by "--" (double dash). Variables can be part of the "ovs_extra"' +
54 'option. You can provide all the standard environmental variables' +
55 'described in the interfaces(5) man page. You can also pass shell' +
56 'commands.extra args',
58 'example': ['ovs_extra set interface ${IFACE} external-ids:iface-id=$(hostname -s)']
61 'help': 'Interfaces to be part of this ovs bond',
62 'validvals': ['<interface-list>'],
66 'help': 'For "OVSTunnel" interfaces, the type of the tunnel',
68 'example': ['ovs-tunnel-type gre'],
70 'ovs-tunnel-options': {
71 'help': 'For "OVSTunnel" interfaces, this field should be ' +
72 'used to specify the tunnel options like remote_ip, key, etc.',
74 'example': ['ovs-tunnel-options options:remote_ip=182.168.1.2 options:key=1'],
77 'help': 'ovs patch peer',
79 'example': ['ovs-patch-peer patch0'],
82 'help': 'mtu of the ovs interface',
84 'example': ['ovs-mtu 9000'],
89 def __init__ (self
, *args
, **kargs
):
90 moduleBase
.__init
__ (self
, *args
, **kargs
)
92 if not os
.path
.exists('/usr/bin/ovs-vsctl'):
93 raise moduleNotSupported('module init failed: no /usr/bin/ovs-vsctl found')
95 def _is_ovs_port (self
, ifaceobj
):
96 ovstype
= ifaceobj
.get_attr_value_first ('ovs-type')
97 ovsbridge
= ifaceobj
.get_attr_value_first ('ovs-bridge')
98 if ovstype
and ovsbridge
:
102 def _get_bond_ifaces (self
, ifaceobj
):
103 ovs_bonds
= ifaceobj
.get_attr_value_first ('ovs-bonds')
105 return sorted (ovs_bonds
.split ())
108 def _ovs_vsctl(self
, ifaceobj
, cmdlist
):
112 os
.environ
['IFACE'] = ifaceobj
.name
if ifaceobj
.name
else ''
113 os
.environ
['LOGICAL'] = ifaceobj
.name
if ifaceobj
.name
else ''
114 os
.environ
['METHOD'] = ifaceobj
.addr_method
if ifaceobj
.addr_method
else ''
115 os
.environ
['ADDRFAM'] = ','.join(ifaceobj
.addr_family
) if ifaceobj
.addr_family
else ''
117 finalcmd
= "/usr/bin/ovs-vsctl"
120 finalcmd
= finalcmd
+ " -- " + cmd
123 self
.logger
.debug ("Running %s" % (finalcmd
))
124 utils
.exec_user_command(finalcmd
)
125 except subprocess
.CalledProcessError
as c
:
126 raise Exception ("Command \"%s failed: %s" % (finalcmd
, c
.output
))
127 except Exception as e
:
128 raise Exception ("%s" % e
)
130 def _addport (self
, ifaceobj
):
131 iface
= ifaceobj
.name
132 ovsbridge
= ifaceobj
.get_attr_value_first ('ovs-bridge')
133 ovsoptions
= ifaceobj
.get_attr_value_first ('ovs-options')
134 ovstype
= ifaceobj
.get_attr_value_first ('ovs-type')
135 ovsbonds
= ifaceobj
.get_attr_value_first ('ovs-bonds')
136 ovsextra
= ifaceobj
.get_attr_value('ovs-extra')
140 if ovstype
== 'OVSBond':
142 raise Exception ("missing ovs-bonds option")
143 cmd
= "--may-exist --fake-iface add-bond %s %s %s"%(ovsbridge
, iface
, ovsbonds
)
146 cmd
= "--may-exist add-port %s %s"%(ovsbridge
, iface
)
150 #clear old ports options
151 cmd
= "--if-exists clear port %s bond_active_slave bond_mode cvlans external_ids lacp mac other_config qos tag trunks vlan_mode"%(iface)
154 #clear old interface options
155 cmd
= "--if-exists clear interface %s mtu_request external-ids other_config options"%(iface)
159 cmd
= "set Port %s %s" %(iface
, ovsoptions
)
163 if ovstype
== 'OVSIntPort':
164 cmd
= "set Interface %s type=internal"%(iface)
167 if ovstype
== 'OVSTunnel':
168 ovstunneltype
= ifaceobj
.get_attr_value_first ('ovs-tunnel-type')
169 if ovstunneltype
is None:
170 raise Exception ("missing ovs-tunnel-type option")
171 ovstunneloptions
= ifaceobj
.get_attr_value_first('ovs-tunnel-options')
172 if ovstunneloptions
is None:
173 raise Exception ("missing ovs-tunnel-options option")
174 cmd
= "set Interface %s type=%s %s"%(iface
, ovstunneltype
, ovstunneloptions
)
177 if ovstype
== 'OVSPatchPort':
178 ovspatchpeer
= ifaceobj
.get_attr_value_first ('ovs-patch-peer')
179 if ovspatchpeer
is None:
180 raise Exception ("missing ovs-patch-peer")
181 cmd
= "set Interface %s type=patch options:peer=%s"%(iface
, ovspatchpeer
)
185 ovsmtu
= ifaceobj
.get_attr_value_first ('ovs-mtu')
186 ovsbonds_list
= self
._get
_bond
_ifaces
(ifaceobj
)
187 if ovsmtu
is not None:
188 #we can't set mtu on bond fake interface, we apply it on slaves interfaces
189 if ovstype
== 'OVSBond' and ovsbonds_list
is not None:
190 for slave
in ovsbonds_list
:
191 cmd
= "set Interface %s mtu_request=%s"%(slave
,ovsmtu
)
195 cmd
= "set Interface %s mtu_request=%s"%(iface
,ovsmtu
)
199 if ovsextra
is not None:
200 cmd_list
.extend(ovsextra
)
202 self
._ovs
_vsctl
(ifaceobj
, cmd_list
)
204 def _delport (self
, ifaceobj
):
205 iface
= ifaceobj
.name
206 ovsbridge
= ifaceobj
.get_attr_value_first ('ovs-bridge')
207 cmd
= "--if-exists del-port %s %s"%(ovsbridge
, iface
)
209 self
._ovs
_vsctl
(ifaceobj
, [cmd
])
211 def get_dependent_ifacenames (self
, ifaceobj
, ifaceobjs_all
=None):
213 if not self
._is
_ovs
_port
(ifaceobj
):
216 ovsbridge
= ifaceobj
.get_attr_value_first ('ovs-bridge')
219 def _up (self
, ifaceobj
):
221 self
._addport
(ifaceobj
)
223 def _down (self
, ifaceobj
):
224 if not ifupdownflags
.flags
.PERFMODE
and not self
.cache
.link_exists (ifaceobj
.name
):
227 self
._delport
(ifaceobj
)
229 def _query_check (self
, ifaceobj
, ifaceobjcurr
):
230 if not self
.cache
.link_exists (ifaceobj
.name
):
237 'query-checkcurr': _query_check
241 """ returns list of ops supported by this module """
242 return self
._run
_ops
.keys ()
244 def run (self
, ifaceobj
, operation
, query_ifaceobj
= None, **extra_args
):
245 """ run Openvswitch port configuration on the interface object passed as argument
248 **ifaceobj** (object): iface object
250 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
253 **query_ifaceobj** (object): query check ifaceobject. This is only
254 valid when op is 'query-checkcurr'. It is an object same as
255 ifaceobj, but contains running attribute values and its config
256 status. The modules can use it to return queried running state
257 of interfaces. status is success if the running state is same
258 as user required state in ifaceobj. error otherwise.
260 op_handler
= self
._run
_ops
.get (operation
)
264 if (operation
!= 'query-running' and not self
._is
_ovs
_port
(ifaceobj
)):
267 if operation
== 'query-checkcurr':
268 op_handler (self
, ifaceobj
, query_ifaceobj
)
270 op_handler (self
, ifaceobj
)