]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown2/addons/vlan.py
Fixed new file addition breakage with 0b762139
[mirror_ifupdown2.git] / ifupdown2 / addons / vlan.py
CommitLineData
f82758bf
RP
1#!/usr/bin/python
2#
3# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6
7from ifupdown.iface import *
8from ifupdownaddons.modulebase import moduleBase
9from ifupdownaddons.iproute2 import iproute2
10import ifupdown.rtnetlink_api as rtnetlink_api
11import logging
12import re
13
14class vlan(moduleBase):
15 """ ifupdown2 addon module to configure vlans """
16
17 _modinfo = {'mhelp' : 'vlan module configures vlan interfaces.' +
18 'This module understands vlan interfaces with dot ' +
19 'notations. eg swp1.100. Vlan interfaces with any ' +
20 'other names need to have raw device and vlan id ' +
21 'attributes',
22 'attrs' : {
23 'vlan-raw-device' :
24 {'help' : 'vlan raw device'},
25 'vlan-id' :
26 {'help' : 'vlan id'}}}
27
28
29 def __init__(self, *args, **kargs):
30 moduleBase.__init__(self, *args, **kargs)
31 self.ipcmd = None
32 self._bridge_vids_query_cache = {}
33 self._resv_vlan_range = self._get_reserved_vlan_range()
34 self.logger.debug('%s: using reserved vlan range %s'
35 %(self.__class__.__name__, str(self._resv_vlan_range)))
36
37 def _is_vlan_device(self, ifaceobj):
38 vlan_raw_device = ifaceobj.get_attr_value_first('vlan-raw-device')
39 if vlan_raw_device:
40 return True
41 elif '.' in ifaceobj.name:
42 return True
43 return False
44
45 def _get_vlan_id(self, ifaceobj):
46 """ Derives vlanid from iface name
47
48 Example:
49 Returns 1 for ifname vlan0001 returns 1
50 Returns 1 for ifname vlan1
51 Returns 1 for ifname eth0.1
52
53 Returns -1 if vlan id cannot be determined
54 """
55 vid_str = ifaceobj.get_attr_value_first('vlan-id')
56 try:
57 if vid_str: return int(vid_str)
58 except:
59 return -1
60
61 if '.' in ifaceobj.name:
62 vid_str = ifaceobj.name.split('.', 1)[1]
63 elif ifaceobj.name.startswith('vlan'):
64 vid_str = ifaceobj.name[4:]
65 else:
66 return -1
67 try:
68 vid = int(vid_str)
69 except:
70 return -1
71 return vid
72
73 def _is_vlan_by_name(self, ifacename):
74 return '.' in ifacename
75
76 def _get_vlan_raw_device_from_ifacename(self, ifacename):
77 """ Returns vlan raw device from ifname
78 Example:
79 Returns eth0 for ifname eth0.100
80
81 Returns None if vlan raw device name cannot
82 be determined
83 """
84 vlist = ifacename.split('.', 1)
85 if len(vlist) == 2:
86 return vlist[0]
87 return None
88
89 def _get_vlan_raw_device(self, ifaceobj):
90 vlan_raw_device = ifaceobj.get_attr_value_first('vlan-raw-device')
91 if vlan_raw_device:
92 return vlan_raw_device
93 return self._get_vlan_raw_device_from_ifacename(ifaceobj.name)
94
95 def get_dependent_ifacenames(self, ifaceobj, ifaceobjs_all=None):
96 if not self._is_vlan_device(ifaceobj):
97 return None
4fc71247 98 ifaceobj.link_kind |= ifaceLinkKind.VLAN
f82758bf
RP
99 return [self._get_vlan_raw_device(ifaceobj)]
100
101 def _bridge_vid_add_del(self, ifaceobj, bridgename, vlanid,
102 add=True):
103 """ If the lower device is a vlan aware bridge, add/del the vlanid
104 to the bridge """
105 if self.ipcmd.bridge_is_vlan_aware(bridgename):
106 if add:
107 rtnetlink_api.rtnl_api.bridge_vlan(add=True, dev=bridgename,
108 vid=vlanid, master=False)
109 else:
110 rtnetlink_api.rtnl_api.bridge_vlan(add=False, dev=bridgename,
111 vid=vlanid, master=False)
112
113 def _bridge_vid_check(self, ifaceobj, ifaceobjcurr, bridgename, vlanid):
114 """ If the lower device is a vlan aware bridge, check if the vlanid
115 is configured on the bridge """
116 if not self.ipcmd.bridge_is_vlan_aware(bridgename):
117 return
118 vids = self._bridge_vids_query_cache.get(bridgename)
119 if vids == None:
120 vids = self.ipcmd.bridge_port_vids_get(bridgename)
121 self._bridge_vids_query_cache[bridgename] = vids
122 if not vids or vlanid not in vids:
123 ifaceobjcurr.status = ifaceStatus.ERROR
124 ifaceobjcurr.status_str = 'bridge vid error'
125
126 def _up(self, ifaceobj):
127 vlanid = self._get_vlan_id(ifaceobj)
128 if vlanid == -1:
129 raise Exception('could not determine vlanid')
130 if self._handle_reserved_vlan(vlanid, ifaceobj.name):
131 return
132 vlanrawdevice = self._get_vlan_raw_device(ifaceobj)
133 if not vlanrawdevice:
134 raise Exception('could not determine vlan raw device')
135 if not self.PERFMODE:
136 if not self.ipcmd.link_exists(vlanrawdevice):
137 raise Exception('rawdevice %s not present' %vlanrawdevice)
138 if self.ipcmd.link_exists(ifaceobj.name):
139 self._bridge_vid_add_del(ifaceobj, vlanrawdevice, vlanid)
140 return
141 rtnetlink_api.rtnl_api.create_vlan(vlanrawdevice,
142 ifaceobj.name, vlanid)
143 self._bridge_vid_add_del(ifaceobj, vlanrawdevice, vlanid)
144 if ifaceobj.addr_method == 'manual':
145 rtnetlink_api.rtnl_api.link_set(ifaceobj.name, "up")
146
147 def _down(self, ifaceobj):
148 vlanid = self._get_vlan_id(ifaceobj)
149 if vlanid == -1:
150 raise Exception('could not determine vlanid')
151 vlanrawdevice = self._get_vlan_raw_device(ifaceobj)
152 if not vlanrawdevice:
153 raise Exception('could not determine vlan raw device')
154 if not self.PERFMODE and not self.ipcmd.link_exists(ifaceobj.name):
155 return
156 try:
157 self.ipcmd.link_delete(ifaceobj.name)
158 self._bridge_vid_add_del(ifaceobj, vlanrawdevice, vlanid, add=False)
159 except Exception, e:
160 self.log_warn(str(e))
161
162 def _query_check(self, ifaceobj, ifaceobjcurr):
163 if not self.ipcmd.link_exists(ifaceobj.name):
164 return
165 if not '.' in ifaceobj.name:
166 # if vlan name is not in the dot format, check its running state
167 (vlanrawdev, vlanid) = self.ipcmd.get_vlandev_attrs(ifaceobj.name)
168 if vlanrawdev != ifaceobj.get_attr_value_first('vlan-raw-device'):
169 ifaceobjcurr.update_config_with_status('vlan-raw-device',
170 vlanrawdev, 1)
171 else:
172 ifaceobjcurr.update_config_with_status('vlan-raw-device',
173 vlanrawdev, 0)
174 if vlanid != ifaceobj.get_attr_value_first('vlan-id'):
175 ifaceobjcurr.update_config_with_status('vlan-id', vlanid, 1)
176 else:
177 ifaceobjcurr.update_config_with_status('vlan-id',
178 vlanid, 0)
179 self._bridge_vid_check(ifaceobj, ifaceobjcurr, vlanrawdev, vlanid)
180
181 def _query_running(self, ifaceobjrunning):
182 if not self.ipcmd.link_exists(ifaceobjrunning.name):
183 return
184 if not self.ipcmd.get_vlandev_attrs(ifaceobjrunning.name):
185 return
186 # If vlan name is not in the dot format, get the
187 # vlan dev and vlan id
188 if not '.' in ifaceobjrunning.name:
189 (vlanrawdev, vlanid) = self.ipcmd.get_vlandev_attrs(ifaceobjrunning.name)
190 ifaceobjrunning.update_config_dict({(k, v) for k, v in
191 {'vlan-raw-device' : vlanrawdev,
192 'vlan-id' : vlanid}.items()
193 if v})
194
195 _run_ops = {'pre-up' : _up,
196 'post-down' : _down,
197 'query-checkcurr' : _query_check,
198 'query-running' : _query_running}
199
200 def get_ops(self):
201 """ returns list of ops supported by this module """
202 return self._run_ops.keys()
203
204 def _init_command_handlers(self):
205 if not self.ipcmd:
206 self.ipcmd = iproute2(**self.get_flags())
207
208
209 def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
210 """ run vlan configuration on the interface object passed as argument
211
212 Args:
213 **ifaceobj** (object): iface object
214
215 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
216 'query-running'
217 Kwargs:
218 **query_ifaceobj** (object): query check ifaceobject. This is only
219 valid when op is 'query-checkcurr'. It is an object same as
220 ifaceobj, but contains running attribute values and its config
221 status. The modules can use it to return queried running state
222 of interfaces. status is success if the running state is same
223 as user required state in ifaceobj. error otherwise.
224 """
225 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
226 return
227 op_handler = self._run_ops.get(operation)
228 if not op_handler:
229 return
230 if (operation != 'query-running' and
231 not self._is_vlan_device(ifaceobj)):
232 return
233 self._init_command_handlers()
234 if operation == 'query-checkcurr':
235 op_handler(self, ifaceobj, query_ifaceobj)
236 else:
237 op_handler(self, ifaceobj)