]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown2/addons/tunnel.py
addons: bridge: warn users if bridge attributes are used under non-bridge stanza
[mirror_ifupdown2.git] / ifupdown2 / addons / tunnel.py
CommitLineData
22aa65c7
MW
1#!/usr/bin/python
2#
3# Maximilian Wilhelm <max@rfc2324.org>
4# -- Mon 10 Oct 2016 10:53:13 PM CEST
5#
c3c78d97
JF
6try:
7 from ifupdown2.ifupdown.iface import *
73083400 8 from ifupdown2.ifupdown.netlink import netlink
c3c78d97 9
c3c78d97 10 from ifupdown2.ifupdownaddons.LinkUtils import LinkUtils
84ca91f1 11 from ifupdown2.ifupdownaddons.modulebase import moduleBase
c3c78d97
JF
12
13 import ifupdown2.ifupdown.ifupdownflags as ifupdownflags
84ca91f1 14except ImportError:
c3c78d97 15 from ifupdown.iface import *
73083400 16 from ifupdown.netlink import netlink
c3c78d97 17
c3c78d97 18 from ifupdownaddons.LinkUtils import LinkUtils
84ca91f1 19 from ifupdownaddons.modulebase import moduleBase
c3c78d97
JF
20
21 import ifupdown.ifupdownflags as ifupdownflags
22
73083400 23
22aa65c7
MW
24#
25# TODO: Add checks for ipip tunnels.
26#
c3c78d97 27class tunnel(moduleBase):
84ca91f1
SA
28 """
29 ifupdown2 addon module to configure tunnels
30 """
c3c78d97
JF
31 _modinfo = {
32 'mhelp': 'create/configure GRE/IPIP/SIT and GRETAP tunnel interfaces',
33 'attrs': {
73083400
JF
34 'mode': {
35 'help': 'type of tunnel as in \'ip link\' command.',
36 'validvals': ['gre', 'gretap', 'ipip', 'sit', 'vti', 'ip6gre', 'ipip6', 'ip6ip6', 'vti6'],
37 'required': True,
38 'example': ['mode gre']
c3c78d97 39 },
73083400
JF
40 'local': {
41 'help': 'IP of local tunnel endpoint',
42 'validvals': ['<ipv4>', '<ipv6>'],
43 'required': True,
44 'example': ['local 192.2.0.42']
c3c78d97
JF
45 },
46 'endpoint': {
73083400
JF
47 'help': 'IP of remote tunnel endpoint',
48 'validvals': ['<ipv4>', '<ipv6>'],
49 'required': True,
50 'example': ['endpoint 192.2.0.23']
c3c78d97
JF
51 },
52 'ttl': {
73083400
JF
53 'help': 'TTL for tunnel packets',
54 'validvals': ['<number>'],
55 'required': False,
56 'example': ['ttl 64']
c3c78d97
JF
57 },
58 'tunnel-physdev': {
73083400
JF
59 'help': 'Physical underlay device to use for tunnel packets',
60 'validvals': ['<interface>'],
61 'required': False,
62 'example': ['tunnel-physdev eth1']
c3c78d97
JF
63 },
64 }
65 }
22aa65c7 66
73083400
JF
67 def __init__(self, *args, **kargs):
68 moduleBase.__init__(self, *args, **kargs)
c3c78d97 69 self.ipcmd = None
22aa65c7 70
73083400
JF
71 @staticmethod
72 def _is_my_interface(ifaceobj):
73 return ifaceobj.addr_method == "tunnel" and ifaceobj.get_attr_value_first('mode')
22aa65c7 74
33ebe60a 75 def _check_settings(self, ifaceobj, attrs):
33ebe60a
SA
76 linkup = self.ipcmd.is_link_up(ifaceobj.name)
77 try:
78 if attrs:
79 self.ipcmd.tunnel_change(ifaceobj.name, attrs)
80 except:
81 raise
82 finally:
83 if attrs and linkup:
84 netlink.link_set_updown(ifaceobj.name, 'up')
22aa65c7 85
73083400 86 def _up(self, ifaceobj):
22aa65c7
MW
87 attr_map = {
88 # attr_name -> ip route param name
73083400
JF
89 'local': 'local',
90 'endpoint': 'remote',
91 'ttl': 'ttl',
92 'tunnel-physdev': 'dev',
22aa65c7
MW
93 }
94
c3c78d97 95 mode = ifaceobj.get_attr_value_first('mode')
22aa65c7
MW
96 attrs = {}
97
98 # Only include attributes which have been set and map ifupdown2 names
99 # to attribute names expected by iproute
c3c78d97
JF
100 for attr, iproute_attr in attr_map.items():
101 attr_val = ifaceobj.get_attr_value_first(attr)
22aa65c7
MW
102 if attr_val != None:
103 attrs[iproute_attr] = attr_val
104
84ca91f1 105 current_mode = self.ipcmd.link_cache_get([ifaceobj.name, 'kind'])
22aa65c7 106
f40c6294
SA
107 try:
108 if not self.ipcmd.link_exists(ifaceobj.name):
c3c78d97 109 self.ipcmd.tunnel_create(ifaceobj.name, mode, attrs)
73083400 110 elif current_mode and current_mode != mode and (('6' in mode and '6' not in current_mode) or ('6' not in mode and '6' in current_mode)):
f40c6294 111 # Mode changes between ipv4 and ipv6 are not possible without recreating the interface
c3c78d97
JF
112 self.ipcmd.link_delete(ifaceobj.name)
113 self.ipcmd.tunnel_create(ifaceobj.name, mode, attrs)
f40c6294
SA
114 else:
115 attrs['mode'] = mode
116 self._check_settings(ifaceobj, attrs)
117 except Exception, e:
c3c78d97 118 self.log_warn(str(e))
22aa65c7 119
73083400 120 def _down(self, ifaceobj):
c3c78d97 121 if not ifupdownflags.flags.PERFMODE and not self.ipcmd.link_exists(ifaceobj.name):
73083400 122 return
22aa65c7 123 try:
c3c78d97 124 self.ipcmd.link_delete(ifaceobj.name)
22aa65c7 125 except Exception, e:
c3c78d97 126 self.log_warn(str(e))
22aa65c7 127
60e7dc3a
SA
128 def get_dependent_ifacenames(self, ifaceobj, ifacenames_all=None):
129 if not self._is_my_interface(ifaceobj):
130 return None
73083400 131
c3c78d97 132 device = ifaceobj.get_attr_value_first('tunnel-physdev')
60e7dc3a 133 if device:
8e2f5fbe 134 return [device]
60e7dc3a
SA
135
136 return None
22aa65c7 137
73083400
JF
138 @staticmethod
139 def _query_check_n_update(ifaceobj, ifaceobjcurr, attrname, attrval, running_attrval):
c3c78d97 140 if not ifaceobj.get_attr_value_first(attrname):
22aa65c7 141 return
22aa65c7 142 if running_attrval and attrval == running_attrval:
73083400 143 ifaceobjcurr.update_config_with_status(attrname, attrval, 0)
22aa65c7 144 else:
73083400 145 ifaceobjcurr.update_config_with_status(attrname, running_attrval, 1)
22aa65c7 146
c3c78d97
JF
147 def _query_check(self, ifaceobj, ifaceobjcurr):
148 if not self.ipcmd.link_exists(ifaceobj.name):
22aa65c7
MW
149 return
150
c3c78d97 151 tunattrs = self.ipcmd.link_get_linkinfo_attrs(ifaceobj.name)
22aa65c7 152 if not tunattrs:
73083400 153 ifaceobjcurr.check_n_update_config_with_status_many(ifaceobj, self.get_mod_attrs(), -1)
22aa65c7
MW
154 return
155
c3c78d97
JF
156 for attr in self.get_mod_attrs():
157 if not ifaceobj.get_attr_value_first(attr):
22aa65c7
MW
158 continue
159
160 # Validate all interface attributes set in the config.
161 # Remote any leading 'tunnel-' prefix in front of the attr name
162 # when accessing tunattrs parsed from 'ip -d link'.
c3c78d97 163 self._query_check_n_update(ifaceobj, ifaceobjcurr, attr,
73083400
JF
164 ifaceobj.get_attr_value_first(attr),
165 tunattrs.get(attr.replace("tunnel-", "")))
22aa65c7
MW
166
167 # Operations supported by this addon (yet).
168 _run_ops = {
73083400
JF
169 'pre-up': _up,
170 'post-down': _down,
171 'query-checkcurr': _query_check
22aa65c7
MW
172 }
173
c3c78d97 174 def get_ops(self):
22aa65c7
MW
175 return self._run_ops.keys()
176
c3c78d97 177 def _init_command_handlers(self):
22aa65c7 178 if not self.ipcmd:
c3c78d97 179 self.ipcmd = LinkUtils()
22aa65c7 180
73083400 181 def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
c3c78d97 182 op_handler = self._run_ops.get(operation)
22aa65c7
MW
183 if not op_handler:
184 return
185
c3c78d97 186 if operation != 'query-running' and not self._is_my_interface(ifaceobj):
22aa65c7
MW
187 return
188
c3c78d97 189 self._init_command_handlers()
22aa65c7 190 if operation == 'query-checkcurr':
c3c78d97 191 op_handler(self, ifaceobj, query_ifaceobj)
22aa65c7 192 else:
c3c78d97 193 op_handler(self, ifaceobj)