Open Kilda Java Documentation
system.py
Go to the documentation of this file.
1 # Copyright 2017 Telstra Open Source
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 #
15 
16 import collections
17 import errno
18 
19 import pyroute2
20 
21 from kilda.traffexam import context as context_module
22 from kilda.traffexam import exc
23 
24 
25 class _IpMixin(context_module.ContextConsumer):
26  def get_ipdb(self):
27  raise NotImplementedError
28 
29 
31  def get_ipdb(self):
32  return self.context.shared_registry.fetch(IPDBRoot)
33 
34 
36  def get_ipdb(self):
37  return self.context.shared_registry.fetch(NetworkNamespace)
38 
39 
40 class Abstract(context_module.ContextConsumer):
41  def __init__(self, context):
42  super().__init__(context)
43 
44  try:
45  self.create()
46  self.configure()
48  try:
49  self.configure()
51  self.release_acquire()
52  self.configure()
53 
54  def create(self):
55  raise NotImplementedError
56 
57  def configure(self):
58  pass
59 
60  def release(self):
61  raise NotImplementedError
62 
63  def release_acquire(self):
64  try:
65  self.release()
67  pass
68  self.create()
69 
70 
72  def iface_drop(self, name):
73  klass = type(self)
74  try:
75  with self.get_ipdb().interfaces[name] as iface:
76  iface.remove()
77  except OSError as e:
78  raise exc.SystemResourceError(klass, name) from e
79  except KeyError:
80  raise exc.SystemResourceNotFoundError(klass, name)
81 
82  def iface_get_info(self, name):
83  try:
84  iface = self.get_ipdb().interfaces[name].ro
85  except KeyError:
86  raise exc.SystemResourceNotFoundError(type(self), name)
87  return iface
88 
89  def iface_set_up(self, name):
90  klass = type(self)
91  try:
92  with self.get_ipdb().interfaces[name] as iface:
93  iface.up()
94  except OSError as e:
95  raise exc.SystemResourceError(klass, name) from e
96  except KeyError:
97  raise exc.SystemResourceNotFoundError(klass, name)
98 
99  def iface_drop_all_addresses(self, name):
100  klass = type(self)
101  try:
102  with self.get_ipdb().interfaces[name] as iface:
103  for addr in tuple(iface.ipaddr):
104  iface.del_ip(*addr)
105  except OSError as e:
106  raise exc.SystemResourceError(klass, name) from e
107  except KeyError:
109  klass, self.context.iface)
110 
111 
113  def release(self):
114  try:
115  ip = self.context.shared_registry.fetch(type(self), remove=True)
117  pass
118  else:
119  ip.release()
120 
121 
123  def create(self):
124  instance = pyroute2.IPDB()
125  self.context.shared_registry.add(type(self), instance)
126 
127 
129  def create(self):
130  name = self.context.make_network_namespace_name()
131  klass = type(self)
132  try:
133  pyroute2.netns.create(name)
134  except OSError as e:
135  if e.errno == errno.EEXIST:
136  raise exc.SystemResourceExistsError(klass, name)
137  raise exc.SystemResourceError(klass, name) from e
138 
139  def release(self):
140  super().release()
141 
142  name = self.context.make_network_namespace_name()
143  try:
144  pyroute2.netns.remove(name)
145  except OSError as e:
146  raise exc.SystemResourceError(type(self), name) from e
147 
148  def configure(self):
149  name = self.context.make_network_namespace_name()
150  nsip = pyroute2.IPDB(nl=pyroute2.NetNS(name))
151  self.context.shared_registry.add(type(self), nsip)
152 
153 
154 GWDescriptor = collections.namedtuple('GWDescription', ('root', 'ns'))
155 
156 
158  ns_gw_name = 'gw'
159 
160  def create(self):
161  name = self.make_name()
162  left, right = name
163  klass = type(self)
164 
165  try:
166  with self.get_ipdb().create(kind='veth', ifname=left, peer=right):
167  # don't do any extra configuration here
168  pass
169  except pyroute2.CreateException:
170  raise exc.SystemResourceExistsError(klass, name)
171  except Exception as e:
172  raise exc.SystemResourceError(klass, name) from e
173 
174  def release(self):
175  name = self.make_name()
176  left, right = name
177  self.iface_drop(left)
178 
179  def configure(self):
180  ns_name = self.context.make_network_namespace_name()
181  name = self.make_name()
182  left, right = name
183  ip = self.get_ipdb()
184  klass = type(self)
185 
186  self.iface_set_up(left)
187 
188  try:
189  with ip.interfaces[right] as iface:
190  iface.net_ns_fd = ns_name
191  except OSError as e:
192  raise exc.SystemResourceError(klass, name) from e
193  except KeyError:
194  # perhaps someone already move iface into our NS
195  pass
196 
197  nsip = self.context.shared_registry.fetch(NetworkNamespace)
198  try:
199  with nsip.interfaces[right] as iface:
200  iface.ifname = self.ns_gw_name
201  iface.up()
202  except OSError as e:
203  raise exc.SystemResourceError(klass, name) from e
204  except KeyError:
205  # perhaps someone already rename iface, check it
206  try:
207  with ip.interfaces[left].ro as iface_left:
208  with nsip.interfaces[self.ns_gw_name].ro as iface_right:
209  ok = iface_left['kind'] == iface_right['kind'] == 'veth'
210  ok = ok and iface_left['peer'] == right
211 
212  if not ok:
214  klass, name,
215  'is not a veth pair created in previous '
216  'step')
217  except KeyError as e:
218  raise exc.SystemResourceNotFoundError(klass, str(e))
219 
220  self.context.shared_registry.add(
221  klass, GWDescriptor(left, self.ns_gw_name))
222 
223  def make_name(self):
224  base = self.context.make_veth_base_name()
225  return ('.'.join((base, tail)) for tail in 'AB')
226 
227 
229  def create(self):
230  name = self.context.make_bridge_name()
231  try:
232  with self.get_ipdb().create(kind='bridge', ifname=name):
233  pass
234  except pyroute2.CreateException:
235  raise exc.SystemResourceExistsError(type(self), name)
236 
237  def release(self):
238  self.iface_drop(self.context.make_bridge_name())
239 
240  def configure(self):
241  name = self.context.make_bridge_name()
242  veth = self.context.shared_registry.fetch(VEthPair)
243 
244  need_ports = {
245  self.context.iface.index,
246  self.iface_get_info(veth.root).index}
247 
248  klass = type(self)
249  try:
250  with self.get_ipdb().interfaces[name] as iface:
251  iface.up()
252  ports = set(iface.ports)
253  for port in ports - need_ports:
254  iface.del_port(port)
255  for port in need_ports - ports:
256  iface.add_port(port)
257  except OSError as e:
258  raise exc.SystemResourceError(klass, name) from e
259  except KeyError:
261  klass, name, 'interface not found')
262 
263 
265  def create(self):
266  pass
267 
268  def release(self):
269  pass
270 
271 
272 class TargetIfaceCleanUp(RootIPDBMixin, _IfaceManager, _ConfigureMixin):
273  def configure(self):
274  self.iface_drop_all_addresses(self.context.iface.index)
275 
276 
278  def configure(self):
279  veth = self.context.shared_registry.fetch(VEthPair)
280  veth_index = self.iface_get_info(veth.root).index
281 
282  try:
283  with self.get_ipdb().interfaces[self.context.iface.index] as iface:
284  iface.add_port(veth_index)
285  except OSError as e:
286  raise exc.SystemResourceError(type(self), veth.root) from e
287  except KeyError:
289  type(self), self.context.iface.name, 'interface not found')
290 
291 
293  def configure(self):
294  self.iface_set_up(self.context.iface.index)
295 
296 
298  def configure(self):
299  self.iface_drop_all_addresses(self.context.make_bridge_name())
300 
301  veth = self.context.shared_registry.fetch(VEthPair)
302  self.iface_drop_all_addresses(veth.root)
303 
304 
306  def configure(self):
307  veth = self.context.shared_registry.fetch(VEthPair)
308 
309  self.cleanup_gateway_iface(veth)
310  self.drop_all_ifaces(veth)
311 
312  self.iface_set_up('lo')
313 
314  def cleanup_gateway_iface(self, veth):
315  self.iface_drop_all_addresses(veth.ns)
316 
317  def drop_all_ifaces(self, veth):
318  keep_iface = {
319  self.iface_get_info(veth.ns).index,
320  self.iface_get_info('lo').index}
321  keep_iface_kinds = {None, 'sit'}
322 
323  for name in tuple(self.get_ipdb().interfaces):
324  if not isinstance(name, int):
325  continue
326  if name in keep_iface:
327  continue
328  if self.iface_get_info(name).kind in keep_iface_kinds:
329  continue
330 
331  try:
332  self.iface_drop(name)
333  except pyroute2.NetlinkError as e:
334  if e.code != errno.EOPNOTSUPP:
335  raise
336 
337 
339  def configure(self):
340  self.iface_set_up(self.context.shared_registry.fetch(VEthPair).ns)
341 
342 
344  def __call__(self, name):
345  return self.iface_get_info(name)
def iface_get_info(self, name)
Definition: system.py:82
def iface_drop_all_addresses(self, name)
Definition: system.py:99
def __init__(self, context)
Definition: system.py:41