Commit 2cd9d91a authored by aquereil's avatar aquereil

ForeignNodeInterface and ImportedNodeInterface merged into the second. Link renamed to Switch.

parent f122489d
...@@ -4,7 +4,7 @@ import os, weakref ...@@ -4,7 +4,7 @@ import os, weakref
import netns.iproute import netns.iproute
__all__ = ['NodeInterface', 'P2PInterface', 'ImportedInterface', __all__ = ['NodeInterface', 'P2PInterface', 'ImportedInterface',
'ForeignNodeInterface', 'ImportedNodeInterface', 'Link'] 'ImportedNodeInterface', 'Switch']
class Interface(object): class Interface(object):
"""Just a base class for the *Interface classes: assign names and handle """Just a base class for the *Interface classes: assign names and handle
...@@ -39,7 +39,7 @@ class Interface(object): ...@@ -39,7 +39,7 @@ class Interface(object):
@property @property
def control(self): def control(self):
"""Associated interface in the main name space (if it exists). Only """Associated interface in the main name space (if it exists). Only
control interfaces can be put into a Link, for example.""" control interfaces can be put into a Switch, for example."""
return None return None
class NSInterface(Interface): class NSInterface(Interface):
...@@ -102,7 +102,7 @@ class NSInterface(Interface): ...@@ -102,7 +102,7 @@ class NSInterface(Interface):
class NodeInterface(NSInterface): class NodeInterface(NSInterface):
"""Class to create and handle a virtual interface inside a name space, it """Class to create and handle a virtual interface inside a name space, it
can be connected to a Link object with emulation of link can be connected to a Switch object with emulation of link
characteristics.""" characteristics."""
def __init__(self, node): def __init__(self, node):
"""Create a new interface. `node' is the name space in which this """Create a new interface. `node' is the name space in which this
...@@ -131,7 +131,7 @@ class NodeInterface(NSInterface): ...@@ -131,7 +131,7 @@ class NodeInterface(NSInterface):
class P2PInterface(NSInterface): class P2PInterface(NSInterface):
"""Class to create and handle point-to-point interfaces between name """Class to create and handle point-to-point interfaces between name
spaces, without using Link objects. Those do not allow any kind of traffic spaces, without using Switch objects. Those do not allow any kind of traffic
shaping. shaping.
As two interfaces need to be created, instead of using the class As two interfaces need to be created, instead of using the class
constructor, use the P2PInterface.create_pair() static method.""" constructor, use the P2PInterface.create_pair() static method."""
...@@ -168,45 +168,39 @@ class P2PInterface(NSInterface): ...@@ -168,45 +168,39 @@ class P2PInterface(NSInterface):
self._slave.del_if(self.index) self._slave.del_if(self.index)
self._slave = None self._slave = None
class ForeignNodeInterface(NSInterface):
"""Class to handle already existing interfaces inside a name space, usually
just the loopback device, but it can be other user-created interfaces. On
destruction, the code will try to restore the interface to the state it was
in before being imported into netns."""
def __init__(self, node, iface):
iface = node._slave.get_if_data(iface)
self._original_state = iface.copy()
super(ForeignNodeInterface, self).__init__(node, iface.index)
# FIXME: register somewhere for destruction!
def destroy(self): # override: restore as much as possible
if self._slave:
if self.index in self._slave.get_if_data():
self._slave.set_if(self._original_state)
self._slave = None
class ImportedNodeInterface(NSInterface): class ImportedNodeInterface(NSInterface):
"""Class to handle already existing interfaces that are migrated inside a """Class to handle already existing interfaces inside a name spac:
name space: real devices, tun devices, etc. On destruction, the interface real devices, tun devices, etc.
will be restored to the original name space and will try to restore the The flag 'migrate' in the constructor indicates that the interface was migrated
original state.""" inside the name space.
def __init__(self, node, iface): On destruction, the interface will be restored to the original name space and
iface = netns.iproute.get_if(iface) will try to restore the original state."""
self._original_state = iface.copy() def __init__(self, node, iface, migrate = False):
self._migrate = migrate
# Change the name to avoid clashes if self._migrate:
iface.name = self._gen_if_name() iface = node._slave.get_if_data(iface)
netns.iproute.set_if(iface) self._original_state = iface.copy()
else:
netns.iproute.change_netns(iface, node.pid) iface = netns.iproute.get_if(iface)
self._original_state = iface.copy()
# Change the name to avoid clashes
iface.name = self._gen_if_name()
netns.iproute.set_if(iface)
netns.iproute.change_netns(iface, node.pid)
super(ImportedNodeInterface, self).__init__(node, iface.index) super(ImportedNodeInterface, self).__init__(node, iface.index)
def destroy(self): # override: restore as much as possible def destroy(self): # override: restore as much as possible
if self._slave: if self._slave:
if self.index in self._slave.get_if_data(): if self.index in self._slave.get_if_data():
self._slave.change_netns(self.index, os.getpid()) if self._migrate:
# else, assume it is in the main name space self._slave.set_if(self._original_state)
netns.iproute.set_if(self._original_state) else:
self._slave.change_netns(self.index, os.getpid())
if not self._migrate:
# else, assume it is in the main name space
netns.iproute.set_if(self._original_state)
self._slave = None self._slave = None
class ExternalInterface(Interface): class ExternalInterface(Interface):
...@@ -272,7 +266,7 @@ class ImportedInterface(ExternalInterface): ...@@ -272,7 +266,7 @@ class ImportedInterface(ExternalInterface):
"""Class to handle already existing interfaces. Analogous to """Class to handle already existing interfaces. Analogous to
ImportedNodeInterface, this class only differs in that the interface is not ImportedNodeInterface, this class only differs in that the interface is not
migrated inside the name space. This kind of interfaces can only be migrated inside the name space. This kind of interfaces can only be
connected to Link objects and not assigned to a name space. On connected to Switch objects and not assigned to a name space. On
destruction, the code will try to restore the interface to the state it was destruction, the code will try to restore the interface to the state it was
in before being imported into netns.""" in before being imported into netns."""
def __init__(self, iface): def __init__(self, iface):
...@@ -286,20 +280,20 @@ class ImportedInterface(ExternalInterface): ...@@ -286,20 +280,20 @@ class ImportedInterface(ExternalInterface):
netns.iproute.set_if(self._original_state) netns.iproute.set_if(self._original_state)
self._original_state = None self._original_state = None
# Link is just another interface type # Switch is just another interface type
class Link(ExternalInterface): class Switch(ExternalInterface):
@staticmethod @staticmethod
def _gen_br_name(): def _gen_br_name():
n = Link._gen_next_id() n = Switch._gen_next_id()
# Max 15 chars # Max 15 chars
return "NETNSbr-%.4x%.3x" % (os.getpid(), n) return "NETNSbr-%.4x%.3x" % (os.getpid(), n)
def __init__(self, **args): def __init__(self, **args):
"""Creates a new Link object, which models a linux bridge device. """Creates a new Switch object, which models a linux bridge device.
Parameters are passed to the set_parameters() method after creation.""" Parameters are passed to the set_parameters() method after creation."""
iface = netns.iproute.create_bridge(self._gen_br_name()) iface = netns.iproute.create_bridge(self._gen_br_name())
super(Link, self).__init__(iface.index) super(Switch, self).__init__(iface.index)
self._parameters = {} self._parameters = {}
self._ports = weakref.WeakValueDictionary() self._ports = weakref.WeakValueDictionary()
...@@ -316,7 +310,7 @@ class Link(ExternalInterface): ...@@ -316,7 +310,7 @@ class Link(ExternalInterface):
def __setattr__(self, name, value): def __setattr__(self, name, value):
if name[0] == '_': # forbid anything that doesn't start with a _ if name[0] == '_': # forbid anything that doesn't start with a _
super(Link, self).__setattr__(name, value) super(Switch, self).__setattr__(name, value)
return return
# Set ports # Set ports
if name in ('up', 'mtu'): if name in ('up', 'mtu'):
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
import os, socket, sys, traceback, unshare, weakref import os, socket, sys, traceback, unshare, weakref
from netns.environ import * from netns.environ import *
import netns.protocol, netns.subprocess_ import netns.protocol, netns.subprocess_, netns.interface
__all__ = ['Node', 'get_nodes', 'import_if'] __all__ = ['Node', 'get_nodes', 'import_if']
...@@ -113,7 +113,7 @@ class Node(object): ...@@ -113,7 +113,7 @@ class Node(object):
ifaces = self._slave.get_if_data() ifaces = self._slave.get_if_data()
for i in ifaces: for i in ifaces:
if i not in self._interfaces: if i not in self._interfaces:
iface = netns.interface.ForeignNodeInterface( self, i) iface = netns.interface.ImportedNodeInterface(self, i, migrate = True)
self._auto_interfaces.append(iface) # keep it referenced! self._auto_interfaces.append(iface) # keep it referenced!
self._interfaces[i] = iface self._interfaces[i] = iface
# by the way, clean up _interfaces # by the way, clean up _interfaces
...@@ -189,4 +189,4 @@ def _start_child(debug, nonetns): ...@@ -189,4 +189,4 @@ def _start_child(debug, nonetns):
# NOTREACHED # NOTREACHED
get_nodes = Node.get_nodes get_nodes = Node.get_nodes
import_if = netns.interface.ImportedInterface(interface) import_if = netns.interface.ImportedInterface
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment