[lnst] Machine, NetTestController: ordered interface configuration
by Jiří Pírko
commit 73d7ea7b3df2f82af22fd743e6187e8d027bc774
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Thu Feb 6 13:39:18 2014 +0100
Machine, NetTestController: ordered interface configuration
This commit completes the master/slave hierarchy of machine interfaces
and adds a new method get_ordered_interfaces to the Machine class that
returns the machines interfaces in order of slaves before masters. The
interfaces are then configured in this order and after all devices are
configured they are set UP in the same order. The reverse ordering is
used in the Machine class when deconfiguring devices.
Interface information sent to the slave will also contain the id of the
master interface or None. This will be used by the NmConfig classes to
activate master connections.
This is required for both NM and iproute2 to work properly.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Controller/Machine.py | 49 +++++++++++++++++++++++++++++++--
lnst/Controller/NetTestController.py | 8 ++++-
2 files changed, 52 insertions(+), 5 deletions(-)
---
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index 4342ef1..78ba622 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -112,6 +112,29 @@ class Machine(object):
msg = "Interface '%s' not found on machine '%s'" % (if_id, self._id)
raise MachineError(msg)
+ def get_ordered_interfaces(self):
+ ordered_list = list(self._interfaces)
+ change = True
+ while change:
+ change = False
+ swap = False
+ ind1 = 0
+ ind2 = 0
+ for i in ordered_list:
+ master = i.get_master()
+ if master != None:
+ ind1 = ordered_list.index(i)
+ ind2 = ordered_list.index(master)
+ if ind1 > ind2:
+ swap = True
+ break
+ if swap:
+ change = True
+ tmp = ordered_list[ind1]
+ ordered_list[ind1] = ordered_list[ind2]
+ ordered_list[ind2] = tmp
+ return ordered_list
+
def _rpc_call(self, method_name, *args):
data = {"type": "command", "method_name": method_name, "args": args}
@@ -167,12 +190,15 @@ class Machine(object):
if not self._msg_dispatcher.get_connection(self._id):
return
+ ordered_ifaces = self.get_ordered_interfaces()
try:
self._rpc_call("kill_cmds")
if deconfigure:
- for iface in reversed(self._interfaces):
+ ordered_ifaces.reverse()
+ for iface in ordered_ifaces:
iface.deconfigure()
+ for iface in ordered_ifaces:
iface.cleanup()
self._rpc_call("bye")
@@ -180,7 +206,7 @@ class Machine(object):
#cleanup is only meaningful on dynamic interfaces, and should
#always be called when deconfiguration happens- especially
#when something on the slave breaks during deconfiguration
- for iface in reversed(self._interfaces):
+ for iface in ordered_ifaces:
if not isinstance(iface, VirtualInterface):
continue
iface.cleanup()
@@ -360,6 +386,8 @@ class Interface(object):
self._addresses = []
self._options = []
+ self._master = None
+
def get_id(self):
return self._id
@@ -396,8 +424,19 @@ class Interface(object):
def set_option(self, name, value):
self._options.append((name, value))
+ def set_master(self, master):
+ if self._master != None:
+ msg = "Interface %s already has a master." % self._master.get_id()
+ raise MachineError(msg)
+ else:
+ self._master = master
+
+ def get_master(self):
+ return self._master
+
def add_slave(self, iface):
self._slaves[iface.get_id()] = iface
+ iface.set_master(self)
def set_slave_option(self, slave_id, name, value):
if slave_id not in self._slave_options:
@@ -420,7 +459,11 @@ class Interface(object):
config = {"hwaddr": self._hwaddr, "type": self._type,
"addresses": self._addresses, "slaves": self._slaves.keys(),
"options": self._options,
- "slave_options": self._slave_options}
+ "slave_options": self._slave_options,
+ "master": None}
+
+ if self._master != None:
+ config["master"] = self._master.get_id()
return config
diff --git a/lnst/Controller/NetTestController.py b/lnst/Controller/NetTestController.py
index c646b51..6e0954f 100644
--- a/lnst/Controller/NetTestController.py
+++ b/lnst/Controller/NetTestController.py
@@ -175,6 +175,12 @@ class NetTestController:
for iface_xml_data in machine_xml_data["interfaces"]:
self._prepare_interface(m_id, iface_xml_data)
+ ifaces = machines[m_id].get_ordered_interfaces()
+ for iface in ifaces:
+ iface.configure()
+ for iface in ifaces:
+ iface.up()
+
def _prepare_provisioning(self):
mreq = self._get_machine_requirements()
sp = self._slave_pool
@@ -236,8 +242,6 @@ class NetTestController:
for opt in iface_xml_data["options"]:
iface.set_option(opt["name"], opt["value"])
- iface.configure()
-
def _prepare_tasks(self):
self._tasks = []
for task_data in self._recipe["tasks"]:
10 years, 2 months
[lnst] Machine: use the new slave interface
by Jiří Pírko
commit 842e5a55daff5aafbf4ad8c81297aaa0444a6cb3
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Thu Feb 6 13:39:17 2014 +0100
Machine: use the new slave interface
Interface initialization and configuration now reflects the recent
changes to the slave implementation. The important points are:
* Static and Virtual interfaces are initialized by creating an id to
* device mapping on the slave
* Soft devices are initialized by calling the create_soft_interface
* slave method.
* Configuration no longer means setting the device up as well... this
* will be done separately in a different order due to how NetworkManager
* works.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Controller/Machine.py | 55 +++++++++++++++++++++++++++----------------
1 files changed, 34 insertions(+), 21 deletions(-)
---
diff --git a/lnst/Controller/Machine.py b/lnst/Controller/Machine.py
index 1c77f38..4342ef1 100644
--- a/lnst/Controller/Machine.py
+++ b/lnst/Controller/Machine.py
@@ -421,26 +421,25 @@ class Interface(object):
"addresses": self._addresses, "slaves": self._slaves.keys(),
"options": self._options,
"slave_options": self._slave_options}
- if self._type == "eth":
- config["phys_id"] = self.get_id()
+
return config
+ def up(self):
+ self._machine._rpc_call("set_device_up", self._id)
+
def down(self):
- self._machine._rpc_call("set_device_down", self._hwaddr)
+ self._machine._rpc_call("set_device_down", self._id)
def initialize(self):
- phys_devs = self._machine._rpc_call("get_devices_by_hwaddr",
- self._hwaddr)
- if len(phys_devs) == 1:
- self.set_devname(phys_devs[0]["name"])
- elif len(phys_devs) < 1:
+ phys_dev = self._machine._rpc_call("map_if_by_hwaddr",
+ self._id, self._hwaddr)
+
+ if phys_dev != None:
+ self.set_devname(phys_dev["name"])
+ else:
msg = "Device %s not found on machine %s" \
% (self.get_id(), self._machine.get_id())
raise MachineError(msg)
- elif len(phys_devs) > 1:
- msg = "Multiple interfaces with same address %s on machine %s" \
- % (self._hwaddr, self._machine.get_id())
- raise MachineError(msg)
self.down()
@@ -461,20 +460,12 @@ class Interface(object):
self._get_config())
self._configured = True
- if_info = self._machine._rpc_call("get_interface_info", self.get_id())
- if "name" in if_info:
- self.set_devname(if_info["name"])
-
- if "hwaddr" in if_info:
- self.set_hwaddr(if_info["hwaddr"])
-
def deconfigure(self):
if not self._configured:
return
self._machine._rpc_call("deconfigure_interface", self.get_id())
self._configured = False
- sleep(1)
class StaticInterface(Interface):
""" Static interface
@@ -583,6 +574,22 @@ class SoftInterface(Interface):
def initialize(self):
pass
+ def configure(self):
+ if self._configured:
+ msg = "Unable to configure interface %s on machine %s. " \
+ "It has been configured already." % (self.get_id(),
+ self._machine.get_id())
+ raise MachineError(msg)
+
+ logging.info("Configuring interface %s on machine %s", self.get_id(),
+ self._machine.get_id())
+
+ dev_name = self._machine._rpc_call("create_soft_interface", self._id,
+ self._get_config())
+ self.set_devname(dev_name)
+ self._configured = True
+
+
class UnusedInterface(Interface):
""" Unused interface for this test
@@ -599,10 +606,16 @@ class UnusedInterface(Interface):
super(UnusedInterface, self).__init__(machine, if_id, if_type)
def initialize(self):
- self.down()
+ self._machine._rpc_call('set_unmapped_device_down', self._hwaddr)
def configure(self):
pass
def deconfigure(self):
pass
+
+ def up(self):
+ pass
+
+ def down(self):
+ pass
10 years, 2 months
[lnst] NetTestSlave: InterfaceManager integration
by Jiří Pírko
commit f3563365efb9fae416d19bb8c16ffd7d216b07ca
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Thu Feb 6 13:39:16 2014 +0100
NetTestSlave: InterfaceManager integration
This commit reimplements the NetTestSlave module to use the new
InterfaceManager module instead of the old NetConfig one.
This includes:
* Netlink handling is done in the InterfaceManager class where it makes
* sense
* Device configuration is delegated to the InterfaceManager, the
* SlaveMethods class reflects this by adding methods such as
* map_if_by_hwaddr that can be used by the controller to map interface
* ids to the specific slave interface.
* Or the new create_soft_interface method that will be used to
* initialize soft interfaces.
* Packet capture now uses the interface provided by the
* InterfaceManager, packet captures are run on every controller mapped
* device.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Slave/NetTestSlave.py | 152 +++++++++++++++++++-------------------------
1 files changed, 65 insertions(+), 87 deletions(-)
---
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index d334449..f81a23a 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -37,7 +37,7 @@ from lnst.Common.ConnectionHandler import recv_data, send_data
from lnst.Common.ConnectionHandler import ConnectionHandler
from lnst.Common.Config import lnst_config
from lnst.Common.NetTestCommand import NetTestCommandConfig
-from pyroute2 import IPRSocket
+from lnst.Slave.InterfaceManager import InterfaceManager
DefaultRPCPort = 9999
@@ -45,9 +45,9 @@ class SlaveMethods:
'''
Exported xmlrpc methods
'''
- def __init__(self, command_context, log_ctl):
+ def __init__(self, command_context, log_ctl, if_manager):
self._packet_captures = {}
- self._netconfig = NetConfig()
+ self._if_manager = if_manager
self._command_context = command_context
self._log_ctl = log_ctl
@@ -94,6 +94,7 @@ class SlaveMethods:
self._cache.del_old_entries()
self.reset_file_transfers()
self._remove_capture_files()
+ self._if_manager.clear_if_mapping()
self._ctl_clean_exit = True
return "bye"
@@ -102,18 +103,20 @@ class SlaveMethods:
self._command_context.cleanup()
return "Commands killed"
- def get_devices_by_hwaddr(self, hwaddr):
- name_scan = scan_netdevs()
- netdevs = []
+ def map_if_by_hwaddr(self, if_id, hwaddr):
+ devices = self._if_manager.get_devices()
- for entry in name_scan:
- if entry["hwaddr"] == normalize_hwaddr(hwaddr):
- netdevs.append(entry)
+ entry = None
+ for dev in devices:
+ if dev.get_hwaddr() == hwaddr:
+ entry = {"name": dev.get_name(),
+ "hwaddr": dev.get_hwaddr()}
+ self._if_manager.map_if(if_id, dev.get_if_index())
- return netdevs
+ return entry
def get_devices_by_devname(self, devname):
- name_scan = scan_netdevs()
+ name_scan = self._if_manager.get_devices()
netdevs = []
for entry in name_scan:
@@ -122,91 +125,77 @@ class SlaveMethods:
return netdevs
- def set_device_down(self, hwaddr):
- devs = self.get_devices_by_hwaddr(hwaddr)
-
- for dev in devs:
- if is_nm_managed_by_name(dev["name"]):
- bus = dbus.SystemBus()
- nm_obj = bus.get_object("org.freedesktop.NetworkManager",
- "/org/freedesktop/NetworkManager")
- nm_if = dbus.Interface(nm_obj, "org.freedesktop.NetworkManager")
- dev_obj_path = nm_if.GetDeviceByIpIface(dev["name"])
- dev_obj = bus.get_object("org.freedesktop.NetworkManager",
- dev_obj_path)
- dev_props = dbus.Interface(dev_obj,
- "org.freedesktop.DBus.Properties")
- if dev_props.Get("org.freedesktop.NetworkManager.Device",
- "ActiveConnection") != "/":
- dev_if = dbus.Interface(dev_obj,
- "org.freedesktop.NetworkManager.Device")
- logging.debug("Disconnecting device %s: %s" %
- (dev["name"], dev_obj_path))
- dev_if.Disconnect()
- else:
- exec_cmd("ip link set %s down" % dev["name"])
-
+ def get_devices_by_hwaddr(self, hwaddr):
+ devices = self._if_manager.get_devices()
+ matched = []
+ for dev in devices:
+ if dev.get_hwaddr() == hwaddr:
+ entry = {"name": dev.get_name(),
+ "hwaddr": dev.get_hwaddr()}
+ matched.append(entry)
+
+ return matched
+
+ def set_device_up(self, if_id):
+ dev = self._if_manager.get_mapped_device(if_id)
+ dev.up()
return True
- def get_interface_info(self, if_id):
- if_config = self._netconfig.get_interface_config(if_id)
- info = {}
-
- if "name" in if_config and if_config["name"] != None:
- info["name"] = if_config["name"]
- else:
- devs = self.get_devices_by_hwaddr(if_config["hwaddr"])
- info["name"] = devs[0]["name"]
-
- if "hwaddr" in if_config and if_config["hwaddr"] != None:
- info["hwaddr"] = if_config["hwaddr"]
- else:
- devs = self.get_devices_by_devname(if_config["name"])
- info["hwaddr"] = devs[0]["hwaddr"]
+ def set_device_down(self, if_id):
+ dev = self._if_manager.get_mapped_device(if_id)
+ dev.down()
+ return True
- return info
+ def set_unmapped_device_down(self, hwaddr):
+ dev = self._if_manager.get_device_by_hwaddr(hwaddr)
+ dev.down()
+ return True
def configure_interface(self, if_id, config):
- self._netconfig.add_interface_config(if_id, config)
- self._netconfig.configure(if_id)
+ device = self._if_manager.get_mapped_device(if_id)
+ device.set_configuration(config)
+ device.configure()
return True
+ def create_soft_interface(self, if_id, config):
+ return self._if_manager.create_device_from_config(if_id, config)
+
def deconfigure_interface(self, if_id):
- self._netconfig.deconfigure(if_id)
- self._netconfig.remove_interface_config(if_id)
+ device = self._if_manager.get_mapped_device(if_id)
+ device.clear_configuration()
return True
- def netconfig_dump(self):
- return self._netconfig.dump_config().items()
-
def start_packet_capture(self, filt):
- netconfig = self._netconfig.dump_config()
-
files = {}
- for dev_id, dev_spec in netconfig.iteritems():
+ for if_id, dev in self._if_manager.get_mapped_devices().iteritems():
+ dev_name = dev.get_name()
+
df_handle = NamedTemporaryFile(delete=False)
dump_file = df_handle.name
df_handle.close()
- files[dev_id] = dump_file
+ files[if_id] = dump_file
pcap = PacketCapture()
- pcap.set_interface(dev_spec["name"])
+ pcap.set_interface(dev_name)
pcap.set_output_file(dump_file)
pcap.set_filter(filt)
pcap.start()
- self._packet_captures[dev_id] = pcap
+ self._packet_captures[if_id] = pcap
self._capture_files = files
return files
def stop_packet_capture(self):
- netconfig = self._netconfig.dump_config()
- for dev_id in netconfig.keys():
- pcap = self._packet_captures[dev_id]
+ if self._packet_captures == None:
+ return True
+
+ for if_index, pcap in self._packet_captures.iteritems():
pcap.stop()
+ self._packet_captures.clear()
+
return True
def _remove_capture_files(self):
@@ -273,8 +262,8 @@ class SlaveMethods:
def machine_cleanup(self):
logging.info("Performing machine cleanup.")
self._command_context.cleanup()
- self._netconfig.deconfigure_all()
- self._netconfig.cleanup()
+ self._if_manager.deconfigure_all()
+ self._if_manager.clear_if_mapping()
self._cache.del_old_entries()
self.restore_system_config()
return True
@@ -436,21 +425,21 @@ class NetTestSlave:
die_when_parent_die()
self._cmd_context = NetTestCommandContext()
- self._methods = SlaveMethods(self._cmd_context, log_ctl)
+ self._if_manager = InterfaceManager()
+ self._methods = SlaveMethods(self._cmd_context, log_ctl,
+ self._if_manager)
+ self._server_handler = ServerHandler(("", port))
self.register_die_signal(signal.SIGHUP)
self.register_die_signal(signal.SIGINT)
self.register_die_signal(signal.SIGTERM)
- self._server_handler = ServerHandler(("", port))
-
self._finished = False
self._log_ctl = log_ctl
- self._nl_socket = IPRSocket()
- self._nl_socket.bind()
- self._server_handler.add_connection('netlink', self._nl_socket)
+ self._server_handler.add_connection('netlink',
+ self._if_manager.get_nl_socket())
def run(self):
while not self._finished:
@@ -527,18 +516,7 @@ class NetTestSlave:
self._server_handler.send_data_to_ctl(msg)
self._cmd_context.del_cmd(cmd)
elif msg["type"] == "netlink":
- for sub_msg in msg["data"]:
- if sub_msg["event"] == "RTM_NEWLINK":
- response = dict()
- response["type"] = "if_update"
- response["if_index"] = sub_msg["index"]
- msg_attrs = sub_msg["attrs"]
- for name, value in msg_attrs:
- if name == "IFLA_IFNAME":
- response["devname"] = value
- elif name == "IFLA_ADDRESS":
- response["hwaddr"] = value
- self._server_handler.send_data_to_ctl(response)
+ self._if_manager.handle_netlink_msgs(msg["data"])
else:
raise Exception("Recieved unknown command")
10 years, 2 months
[PATCH 0/8] slave network configuration reimplementation
by Ondrej Lichtner
From: Ondrej Lichtner <olichtne(a)redhat.com>
The following patch series reimplements the slave network configuration in order
to make it more maintainable and extensible. This will also allow us to add a
few new features that we wanted for some time, for example sending updates about
IP addresses to the controller.
I've tested this on Fedora 20 and RHEL 7 machines and all the old functionality
should be there. From the few tests I did on RHEL 6.5 machines there might be a
few problems, I will analyze these in the future.
Ondrej Lichtner (8):
ConnectionHandler: retrieve ALL messages from connections
NetTestSlave: handle ctl messages last
InterfaceManager module created
NetConfigDevice: InterfaceManager integration
NmConfigDevice: InterfaceManager integration
NetTestSlave: InterfaceManager integration
Machine: use the new slave interface
Machine, NetTestController: ordered interface configuration
lnst/Common/ConnectionHandler.py | 39 ++-
lnst/Controller/Machine.py | 104 +++++--
lnst/Controller/NetTestController.py | 8 +-
lnst/Slave/InterfaceManager.py | 250 ++++++++++++++++
lnst/Slave/NetConfigDevice.py | 176 +++++------
lnst/Slave/NetTestSlave.py | 164 +++++------
lnst/Slave/NmConfigDevice.py | 553 +++++++++++++++++------------------
7 files changed, 805 insertions(+), 489 deletions(-)
create mode 100644 lnst/Slave/InterfaceManager.py
--
1.8.5.3
10 years, 2 months
[lnst] NmConfigDevice: InterfaceManager integration
by Jiří Pírko
commit e5129cf354b803ceb1930f11044283e82d77f68e
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Thu Feb 6 13:39:15 2014 +0100
NmConfigDevice: InterfaceManager integration
The NmConfigDevice module now supports the new InterfaceManager module
instead of the old NetConfig way. I also refactored certain variable
names so that they make more sense and are consistent with the rest of
the code.
In addition to this the NetworkManager code needed reimplementing in
some places to work with the new program flow of device configuration
and to support more use cases. The most important part of this is that
configuration of master interfaces (e.g. bonding or team) doesn't also
configure the slave interfaces. Instead it changes finds their
ConfigDevice object and changes it's configuration so that the device
is enslaved on activation.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Slave/NmConfigDevice.py | 553 +++++++++++++++++++++---------------------
1 files changed, 273 insertions(+), 280 deletions(-)
---
diff --git a/lnst/Slave/NmConfigDevice.py b/lnst/Slave/NmConfigDevice.py
index 396dea8..40f4b70 100644
--- a/lnst/Slave/NmConfigDevice.py
+++ b/lnst/Slave/NmConfigDevice.py
@@ -87,32 +87,45 @@ class NmConfigDeviceGeneric(object):
_wait_for = None
- def __init__(self, netdev, config):
- self._netdev = netdev
- self._config = config
+ def __init__(self, dev_config, if_manager):
+ self._dev_config = dev_config
+ self._if_manager = if_manager
self._bus = dbus.SystemBus()
self._nm_obj = self._bus.get_object(NM_BUS, OBJ_PRE)
self._nm_if = dbus.Interface(self._nm_obj, IF_PRE)
+ self._connection = None
+ self._connection_added = False
+ self._con_obj_path = None
+ self._acon_obj_path = None
+
def configure(self):
pass
def deconfigure(self):
pass
- def slave_add(self, slaveid):
+ def slave_add(self, slave_id):
pass
- def slave_del(self, slaveid):
+ def slave_del(self, slave_id):
pass
def up(self):
- netdev = self._netdev
- self._nm_activate_connection(netdev)
+ if not self._connection_added:
+ self._nm_add_connection()
+ if self._connection_added:
+ #NM would automatically activate the master connection, however
+ #we want to have the record of which active connection that is
+ if self._dev_config["master"] != None:
+ master_id = self._dev_config["master"]
+ master_dev = self._if_manager.get_mapped_device(master_id)
+ master_dev.up()
+ self._nm_activate_connection()
def down(self):
- netdev = self._netdev
- self._nm_deactivate_connection(netdev)
+ if self._connection_added:
+ self._nm_deactivate_connection()
@classmethod
def type_init(self):
@@ -123,8 +136,8 @@ class NmConfigDeviceGeneric(object):
pass
@classmethod
- def is_nm_managed(cls, netdev, config):
- return is_nm_managed_by_name(netdev["name"])
+ def is_nm_managed(cls, dev_config, if_manager):
+ return is_nm_managed_by_name(dev_config["name"])
def _wait_for_state(self, new_state, old_state, reason):
self._device_state = new_state
@@ -137,9 +150,9 @@ class NmConfigDeviceGeneric(object):
break
time.sleep(1)
- def _convert_hwaddr(self, netdev):
- if "hwaddr" in netdev:
- hwaddr = netdev["hwaddr"]
+ def _convert_hwaddr(self, dev_config):
+ if "hwaddr" in dev_config:
+ hwaddr = dev_config["hwaddr"]
else:
return None
@@ -191,79 +204,116 @@ class NmConfigDeviceGeneric(object):
return (s_ipv4, s_ipv6)
- def _nm_add_connection(self, connection):
- bus = self._bus
- settings_obj = bus.get_object(NM_BUS, OBJ_PRE + "/Settings")
- settings_if = dbus.Interface(settings_obj, IF_PRE + ".Settings")
- con_obj_path = settings_if.AddConnection(connection)
- logging.debug("Added NM connection: %s" % con_obj_path)
- return con_obj_path
+ def _nm_add_connection(self):
+ #NM will succesfully add this connection but is unable to activate it...
+ if self._connection["ipv4"]["method"] == "disabled" and\
+ self._connection["ipv6"]["method"] == "ignore" and\
+ "master" not in self._connection["connection"] and\
+ self._connection["connection"]["type"] == "802-3-ethernet":
+ return
- def _nm_rm_connection(self, con_obj_path):
- bus = self._bus
- con_obj = bus.get_object(NM_BUS, con_obj_path)
- con_if = dbus.Interface(con_obj, IF_PRE + ".Settings.Connection")
- con_if.Delete()
- logging.debug("Removed NM connection: %s" % con_obj_path)
-
- def _nm_activate_connection(self, netdev):
- if "acon_obj_path" in netdev and netdev["acon_obj_path"] != "" or\
- "con_obj_path" not in netdev:
+ if not self._connection_added:
+ bus = self._bus
+ settings_obj = bus.get_object(NM_BUS, OBJ_PRE + "/Settings")
+ settings_if = dbus.Interface(settings_obj, IF_PRE + ".Settings")
+ self._con_obj_path = settings_if.AddConnection(self._connection)
+ self._connection_added = True
+ logging.debug("Added NM connection: %s" % self._con_obj_path)
+
+ def _nm_rm_connection(self):
+ if self._connection_added:
+ bus = self._bus
+ con_obj = bus.get_object(NM_BUS, self._con_obj_path)
+ con_if = dbus.Interface(con_obj, IF_PRE + ".Settings.Connection")
+ con_if.Delete()
+ logging.debug("Removed NM connection: %s" % self._con_obj_path)
+ self._connection_added = False
+ self._con_obj_path = None
+
+ def _nm_update_connection(self):
+ if self._connection_added:
+ bus = self._bus
+ con_obj = bus.get_object(NM_BUS, self._con_obj_path)
+ con_if = dbus.Interface(con_obj, IF_PRE + ".Settings.Connection")
+ con_if.Update(self._connection)
+ logging.debug("Updated NM connection: %s" % self._con_obj_path)
+
+ def _nm_activate_connection(self):
+ config = self._dev_config
+ if self._acon_obj_path != None or\
+ self._con_obj_path == None:
return
else:
logging.info("Activating connection on interface %s"
- % netdev["name"])
+ % config["name"])
bus = self._bus
nm_if = self._nm_if
try:
- device_obj_path = nm_if.GetDeviceByIpIface(netdev["name"])
+ device_obj_path = nm_if.GetDeviceByIpIface(config["name"])
except:
device_obj_path = "/"
- netdev["acon_obj_path"] = nm_if.ActivateConnection(
- netdev["con_obj_path"],
+ self._acon_obj_path = nm_if.ActivateConnection(
+ self._con_obj_path,
device_obj_path, "/")
logging.debug("Device object path: %s" % device_obj_path)
- logging.debug("Connection object path: %s" % netdev["con_obj_path"])
+ logging.debug("Connection object path: %s" % self._con_obj_path)
logging.debug("Active connection object path: %s"
- % netdev["acon_obj_path"])
+ % self._acon_obj_path)
- act_con = bus.get_object(NM_BUS, netdev["acon_obj_path"])
+ act_con = bus.get_object(NM_BUS, self._acon_obj_path)
act_con_props = dbus.Interface(act_con,
"org.freedesktop.DBus.Properties")
self._poll_loop(act_con_props.Get,
_ACON_ACTIVATED,
IF_PRE + ".Connection.Active", "State")
- def _nm_deactivate_connection(self, netdev):
- if "acon_obj_path" not in netdev or netdev["acon_obj_path"] == "":
+ def _nm_deactivate_connection(self):
+ config = self._dev_config
+ if self._acon_obj_path == None:
return
else:
logging.info("Deactivating connection on device %s"
- % netdev["name"])
+ % config["name"])
logging.debug("Active connection object path: %s"
- % netdev["acon_obj_path"])
- self._nm_if.DeactivateConnection(netdev["acon_obj_path"])
- netdev["acon_obj_path"] = ""
+ % self._acon_obj_path)
+ self._nm_if.DeactivateConnection(self._acon_obj_path)
+ self._acon_obj_path = None
+
+ def nm_enslave(self, slave_type, master_uuid, slave_conf):
+ self._connection["connection"]["slave_type"] = slave_type
+ self._connection["connection"]["master"] = master_uuid
+ self._connection.update(slave_conf)
+
+ self._nm_update_connection()
+
+ def nm_free(self):
+ if "slave_type" in self._connection["connection"]:
+ del self._connection["connection"]["slave_type"]
+ if "master" in self._connection["connection"]:
+ del self._connection["connection"]["master"]
+
+ self._nm_update_connection()
class NmConfigDeviceEth(NmConfigDeviceGeneric):
@classmethod
- def is_nm_managed(cls, netdev, config):
- managed = super(NmConfigDeviceEth, cls).is_nm_managed(netdev, config)
- if _dev_exists(netdev["hwaddr"]):
+ def is_nm_managed(cls, dev_config, if_manager):
+ managed = super(NmConfigDeviceEth, cls).is_nm_managed(dev_config,
+ if_manager)
+ if _dev_exists(dev_config["hwaddr"]):
return managed
else:
return False
def up(self):
- netdev = self._netdev
+ config = self._dev_config
bus = self._bus
nm_if = self._nm_if
- device_obj_path = nm_if.GetDeviceByIpIface(netdev["name"])
+ device_obj_path = nm_if.GetDeviceByIpIface(config["name"])
dev = bus.get_object(NM_BUS, device_obj_path)
dev_props = dbus.Interface(dev, "org.freedesktop.DBus.Properties")
@@ -271,26 +321,25 @@ class NmConfigDeviceEth(NmConfigDeviceGeneric):
state = dev_props.Get(IF_PRE + ".Device", "State")
if state == _DEV_UNAVAILABLE:
logging.info("Resetting interface so NM manages it.")
- exec_cmd("ip link set %s down" % netdev["name"])
- exec_cmd("ip link set %s up" % netdev["name"])
+ exec_cmd("ip link set %s down" % config["name"])
+ exec_cmd("ip link set %s up" % config["name"])
self._poll_loop(dev_props.Get,
_DEV_DISCONNECTED,
IF_PRE + ".Device", "State")
+ else:
+ exec_cmd("ip link set %s up" % config["name"])
super(NmConfigDeviceEth, self).up()
def configure(self):
- netdev = self._netdev
- exec_cmd("ethtool -A %s rx off tx off" % netdev["name"], die_on_err=False, log_outputs=False)
+ config = self._dev_config
+ exec_cmd("ethtool -A %s rx off tx off" % config["name"],
+ die_on_err=False, log_outputs=False)
- hw_addr = self._convert_hwaddr(netdev)
+ hw_addr = self._convert_hwaddr(config)
- s_ipv4, s_ipv6 = self._nm_make_ip_settings(netdev["addresses"])
-
- #TODO is this correct?? NM sets ipv4 to automatic if both are disabled
- if s_ipv4["method"] == "disabled" and s_ipv6["method"] == "ignore":
- return
+ s_ipv4, s_ipv6 = self._nm_make_ip_settings(config["addresses"])
s_eth = dbus.Dictionary({'mac-address': hw_addr}, signature='sv')
s_con = dbus.Dictionary({
@@ -305,31 +354,31 @@ class NmConfigDeviceEth(NmConfigDeviceGeneric):
'ipv4': s_ipv4,
'ipv6': s_ipv6}, signature='sa{sv}')
- netdev["con_obj_path"] = self._nm_add_connection(connection)
+ self._connection = connection
+ self._nm_add_connection()
def deconfigure(self):
- netdev = self._netdev
- if "con_obj_path" in netdev and netdev["con_obj_path"] != "":
- self._nm_rm_connection(netdev["con_obj_path"])
- netdev["con_obj_path"] = ""
+ if self._con_obj_path != None:
+ self._nm_rm_connection()
class NmConfigDeviceBond(NmConfigDeviceGeneric):
_modulename = "bonding"
_moduleparams = "max_bonds=0"
@classmethod
- def is_nm_managed(cls, netdev, config):
- if _dev_exists(netdev["hwaddr"]):
- managed = super(NmConfigDeviceBond, cls).is_nm_managed(netdev,
- config)
+ def is_nm_managed(cls, dev_config, if_manager):
+ if _dev_exists(dev_config["hwaddr"]):
+ managed = super(NmConfigDeviceBond, cls).is_nm_managed(dev_config,
+ if_manager)
else:
- slave_id = get_slaves(netdev)[1]
- netdev = config[slave_id]
- managed = is_nm_managed(netdev, config)
-
- for slave in get_slaves(netdev):
- netdev = config[slave]
- if is_nm_managed(netdev, config) != managed:
+ slave_dev = if_manager.get_mapped_device(get_slaves(dev_config)[0])
+ slave_config = slave_dev.get_conf_dict()
+ managed = is_nm_managed(slave_config, if_manager)
+
+ for slave_id in get_slaves(dev_config):
+ slave_dev = if_manager.get_mapped_device(slave_id)
+ slave_config = slave_dev.get_conf_dict()
+ if is_nm_managed(slave_config, if_manager) != managed:
msg = "Mixing NM managed and not managed devices in a "\
"master-slave relationship is not allowed!"
raise Exception(msg)
@@ -339,28 +388,25 @@ class NmConfigDeviceBond(NmConfigDeviceGeneric):
def up(self):
super(NmConfigDeviceBond, self).up()
- for slave in get_slaves(self._netdev):
- netdev = self._config[slave]
- self._nm_activate_connection(netdev)
-
def down(self):
- for slave in get_slaves(self._netdev):
- netdev = self._config[slave]
- self._nm_deactivate_connection(netdev)
+ for slave_id in get_slaves(self._dev_config):
+ slave_dev = self._if_manager.get_mapped_device(slave_id)
+ slave_dev.down()
super(NmConfigDeviceBond, self).down()
def _setup_options(self):
- if not "options" in self._netdev:
+ if not "options" in self._dev_config:
return dbus.Dictionary({}, signature="ss")
options = {}
- for option, value in self._netdev["options"]:
+ for option, value in self._dev_config["options"]:
if option == "primary":
'''
"primary" option is not direct value but it's
index of netdevice. So take the appropriate name from config
'''
- value = self._config[int(value)]["name"]
+ slave_dev = self._if_manager.get_mapped_device(int(value))
+ value = slave_dev.get_name()
options[option] = value
if options:
return dbus.Dictionary(options, signature="ss")
@@ -368,26 +414,26 @@ class NmConfigDeviceBond(NmConfigDeviceGeneric):
return None
def _add_bond(self):
- netdev = self._netdev
- netdev["master_uuid"] = str(uuid.uuid4())
+ config = self._dev_config
+ config["master_uuid"] = str(uuid.uuid4())
s_bond_con = dbus.Dictionary({
'type': 'bond',
'autoconnect': dbus.Boolean(False),
- 'uuid': netdev["master_uuid"],
- 'id': netdev["name"]+"_con"})
+ 'uuid': config["master_uuid"],
+ 'id': config["name"]+"_con"})
options = self._setup_options()
if options:
s_bond = dbus.Dictionary({
- 'interface-name': netdev["name"],
+ 'interface-name': config["name"],
'options': options})
else:
s_bond = dbus.Dictionary({
- 'interface-name': netdev["name"]})
+ 'interface-name': config["name"]})
- s_ipv4, s_ipv6 = self._nm_make_ip_settings(netdev["addresses"])
+ s_ipv4, s_ipv6 = self._nm_make_ip_settings(config["addresses"])
connection = dbus.Dictionary({
'bond': s_bond,
@@ -395,53 +441,32 @@ class NmConfigDeviceBond(NmConfigDeviceGeneric):
'ipv6': s_ipv6,
'connection': s_bond_con})
- netdev["con_obj_path"] = self._nm_add_connection(connection)
+ self._connection = connection
+ self._nm_add_connection()
def _rm_bond(self):
- netdev = self._netdev
- if netdev["con_obj_path"] != "":
- self._nm_rm_connection(netdev["con_obj_path"])
- netdev["con_obj_path"] = ""
+ if self._con_obj_path != None:
+ self._nm_rm_connection()
#older versions of NM don't know how to remove soft devices...
if get_nm_version() < "0.9.9":
try:
bond_masters = "/sys/class/net/bonding_masters"
- exec_cmd('echo "-%s" > %s' % (netdev["name"], bond_masters))
+ exec_cmd('echo "-%s" > %s' % (config["name"], bond_masters))
except:
pass
def _add_slaves(self):
- for slave in get_slaves(self._netdev):
- netdev = self._config[slave]
- slave_name = netdev["name"]
-
- hw_addr = self._convert_hwaddr(netdev)
-
- s_eth = dbus.Dictionary({
- 'duplex': dbus.Array('full', 's'),
- 'mac-address': hw_addr})
-
- s_slave_con = dbus.Dictionary({
- 'type': '802-3-ethernet',
- 'autoconnect': dbus.Boolean(False),
- 'uuid': str(uuid.uuid4()),
- 'id': 'slave_con',
- 'master': self._netdev["master_uuid"],
- 'slave-type': 'bond'})
-
- slave_con = dbus.Dictionary({
- '802-3-ethernet': s_eth,
- 'connection': s_slave_con})
-
- netdev["con_obj_path"] = self._nm_add_connection(slave_con)
+ for slave_id in get_slaves(self._dev_config):
+ slave_dev = self._if_manager.get_mapped_device(slave_id)
+ slave_config = slave_dev.get_configuration()
+ slave_config.nm_enslave("bond", self._dev_config["master_uuid"], {})
def _rm_slaves(self):
- for slave in get_slaves(self._netdev):
- netdev = self._config[slave]
- if netdev["con_obj_path"] != "":
- self._nm_rm_connection(netdev["con_obj_path"])
- netdev["con_obj_path"] = ""
+ for slave_id in get_slaves(self._dev_config):
+ slave_dev = self._if_manager.get_mapped_device(slave_id)
+ slave_config = slave_dev.get_configuration()
+ slave_config.nm_free()
def configure(self):
self._add_bond()
@@ -455,18 +480,19 @@ class NmConfigDeviceBridge(NmConfigDeviceGeneric):
_modulename = "bridge"
@classmethod
- def is_nm_managed(cls, netdev, config):
- if _dev_exists(netdev["hwaddr"]):
- managed = super(NmConfigDeviceBridge, cls).is_nm_managed(netdev,
- config)
+ def is_nm_managed(cls, dev_config, if_manager):
+ if _dev_exists(dev_config["hwaddr"]):
+ managed = super(NmConfigDeviceBridge, cls).is_nm_managed(dev_config,
+ if_manager)
else:
- slave_id = get_slaves(netdev)[1]
- netdev = config[slave_id]
- managed = is_nm_managed(netdev, config)
-
- for slave in get_slaves(netdev):
- netdev = config[slave]
- if is_nm_managed(netdev, config) != managed:
+ slave_dev = if_manager.get_mapped_device(get_slaves(dev_config)[0])
+ slave_config = slave_dev.get_conf_dict()
+ managed = is_nm_managed(slave_config, if_manager)
+
+ for slave_id in get_slaves(dev_config):
+ slave_dev = if_manager.get_mapped_device(slave_id)
+ slave_config = slave_dev.get_conf_dict()
+ if is_nm_managed(slave_config, if_manager) != managed:
msg = "Mixing NM managed and not managed devices in a "\
"master-slave relationship is not allowed!"
raise Exception(msg)
@@ -476,32 +502,28 @@ class NmConfigDeviceBridge(NmConfigDeviceGeneric):
def up(self):
super(NmConfigDeviceBridge, self).up()
- for slave in get_slaves(self._netdev):
- netdev = self._config[slave]
- self._nm_activate_connection(netdev)
-
def down(self):
- for slave in get_slaves(self._netdev):
- netdev = self._config[slave]
- self._nm_deactivate_connection(netdev)
+ for slave_id in get_slaves(self._dev_config):
+ slave_dev = self._if_manager.get_mapped_device(slave_id)
+ slave_dev.down()
super(NmConfigDeviceBridge, self).down()
def _add_bridge(self):
- netdev = self._netdev
- netdev["master_uuid"] = str(uuid.uuid4())
+ config = self._dev_config
+ config["master_uuid"] = str(uuid.uuid4())
s_bridge_con = dbus.Dictionary({
'type': 'bridge',
'autoconnect': dbus.Boolean(False),
- 'uuid': netdev["master_uuid"],
- 'id': netdev["name"]+"_con"})
+ 'uuid': config["master_uuid"],
+ 'id': config["name"]+"_con"})
s_bridge = dbus.Dictionary({
- 'interface-name': netdev["name"],
+ 'interface-name': config["name"],
'stp': dbus.Boolean(False)})
- s_ipv4, s_ipv6 = self._nm_make_ip_settings(netdev["addresses"])
+ s_ipv4, s_ipv6 = self._nm_make_ip_settings(config["addresses"])
connection = dbus.Dictionary({
'bridge': s_bridge,
@@ -509,59 +531,38 @@ class NmConfigDeviceBridge(NmConfigDeviceGeneric):
'ipv6': s_ipv6,
'connection': s_bridge_con})
- netdev["con_obj_path"] = self._nm_add_connection(connection)
+ self._connection = connection
+ self._nm_add_connection()
def _rm_bridge(self):
- netdev = self._netdev
- if netdev["con_obj_path"] != "":
- self._nm_rm_connection(netdev["con_obj_path"])
- netdev["con_obj_path"] = ""
+ if self._con_obj_path != None:
+ self._nm_rm_connection()
#older versions of NM don't know how to remove soft devices...
if get_nm_version() < "0.9.9":
try:
- exec_cmd("ip link set %s down" % netdev["name"])
- exec_cmd("brctl delbr %s " % netdev["name"])
+ exec_cmd("ip link set %s down" % config["name"])
+ exec_cmd("brctl delbr %s " % config["name"])
except:
pass
- def _add_slave(self, slave):
- netdev = self._config[slave]
- slave_name = netdev["name"]
-
- hw_addr = self._convert_hwaddr(netdev)
-
- s_eth = dbus.Dictionary({
- 'duplex': dbus.Array('full', 's'),
- 'mac-address': hw_addr})
-
- s_slave_con = dbus.Dictionary({
- 'type': '802-3-ethernet',
- 'autoconnect': dbus.Boolean(False),
- 'uuid': str(uuid.uuid4()),
- 'id': 'slave_con',
- 'master': self._netdev["master_uuid"],
- 'slave-type': 'bridge'})
-
- slave_con = dbus.Dictionary({
- '802-3-ethernet': s_eth,
- 'connection': s_slave_con})
-
- netdev["con_obj_path"] = self._nm_add_connection(slave_con)
+ def _add_slave(self, slave_id):
+ slave_dev = self._if_manager.get_mapped_device(slave_id)
+ slave_config = slave_dev.get_configuration()
+ slave_config.nm_enslave("bridge", self._dev_config["master_uuid"], {})
- def _rm_slave(self, slave):
- netdev = self._config[slave]
- if netdev["con_obj_path"] != "":
- self._nm_rm_connection(netdev["con_obj_path"])
- netdev["con_obj_path"] = ""
+ def _rm_slave(self, slave_id):
+ slave_dev = self._if_manager.get_mapped_device(slave_id)
+ slave_config = slave_dev.get_configuration()
+ slave_config.nm_free()
def _add_slaves(self):
- for slaveid in get_slaves(self._netdev):
- self._add_slave(slaveid)
+ for slave_id in get_slaves(self._dev_config):
+ self._add_slave(slave_id)
def _rm_slaves(self):
- for slaveid in get_slaves(self._netdev):
- self._rm_slave(slaveid)
+ for slave_id in get_slaves(self._dev_config):
+ self._rm_slave(slave_id)
def configure(self):
self._add_bridge()
@@ -571,21 +572,22 @@ class NmConfigDeviceBridge(NmConfigDeviceGeneric):
self._rm_slaves()
self._rm_bridge()
- def slave_add(self, slaveid):
- self._add_slave(slaveid)
+ def slave_add(self, slave_id):
+ self._add_slave(slave_id)
- def slave_del(self, slaveid):
- self._rm_slave(slaveid)
+ def slave_del(self, slave_id):
+ self._rm_slave(slave_id)
class NmConfigDeviceMacvlan(NmConfigDeviceGeneric):
#Not supported by NetworkManager yet
@classmethod
- def is_nm_managed(cls, netdev, config):
+ def is_nm_managed(cls, dev_config, if_manager):
managed = False
- for slave in get_slaves(netdev):
- slave_netdev = config[slave]
- if is_nm_managed(slave_netdev, config) != managed:
+ for slave_id in get_slaves(dev_config):
+ slave_dev = if_manager.get_mapped_device(slave_id)
+ slave_config = slave_dev.get_conf_dict()
+ if is_nm_managed(slave_config, if_manager) != managed:
msg = "Mixing NM managed and not managed devices in a "\
"master-slave relationship is not allowed!"
raise Exception(msg)
@@ -596,18 +598,19 @@ class NmConfigDeviceVlan(NmConfigDeviceGeneric):
_modulename = "8021q"
@classmethod
- def is_nm_managed(cls, netdev, config):
- if _dev_exists(netdev["hwaddr"]):
- managed = super(NmConfigDeviceVlan, cls).is_nm_managed(netdev,
- config)
+ def is_nm_managed(cls, dev_config, if_manager):
+ if _dev_exists(dev_config["hwaddr"]):
+ managed = super(NmConfigDeviceVlan, cls).is_nm_managed(dev_config,
+ if_manager)
else:
- slave_id = get_slaves(netdev)[0]
- netdev = config[slave_id]
- managed = is_nm_managed(netdev, config)
-
- for slave in get_slaves(netdev):
- slave_netdev = config[slave]
- if is_nm_managed(slave_netdev, config) != managed:
+ slave_dev = if_manager.get_mapped_device(get_slaves(dev_config)[0])
+ slave_config = slave_dev.get_conf_dict()
+ managed = is_nm_managed(slave_config, if_manager)
+
+ for slave_id in get_slaves(dev_config):
+ slave_dev = if_manager.get_mapped_device(slave_id)
+ slave_config = slave_dev.get_conf_dict()
+ if is_nm_managed(slave_config, if_manager) != managed:
msg = "Mixing NM managed and not managed devices in a "\
"master-slave relationship is not allowed!"
raise Exception(msg)
@@ -623,14 +626,16 @@ class NmConfigDeviceVlan(NmConfigDeviceGeneric):
return False
def _get_vlan_info(self):
- netdev = self._netdev;
- realdev_index = get_slaves(netdev)[0]
- realdev = self._config[realdev_index]["name"]
- dev_name = netdev["name"]
- vlan_tci = int(get_option(netdev, "vlan_tci"))
- return dev_name, realdev, vlan_tci
+ config = self._dev_config;
+ realdev = self._if_manager.get_mapped_device(get_slaves(config)[0])
+ realdev_name = realdev.get_name()
+ dev_name = config["name"]
+ vlan_tci = int(get_option(config, "vlan_tci"))
+ return dev_name, realdev_name, vlan_tci
def configure(self):
+ config = self._dev_config
+
dev_name, realdev, vlan_tci = self._get_vlan_info()
s_vlan_con = dbus.Dictionary({
@@ -644,7 +649,7 @@ class NmConfigDeviceVlan(NmConfigDeviceGeneric):
'parent': realdev,
'id': dbus.UInt32(vlan_tci)}, signature="sv")
- s_ipv4, s_ipv6 = self._nm_make_ip_settings(self._netdev["addresses"])
+ s_ipv4, s_ipv6 = self._nm_make_ip_settings(config["addresses"])
connection = dbus.Dictionary({
'vlan': s_vlan,
@@ -652,13 +657,12 @@ class NmConfigDeviceVlan(NmConfigDeviceGeneric):
'ipv6': s_ipv6,
'connection': s_vlan_con})
- self._netdev["con_obj_path"] = self._nm_add_connection(connection)
+ self._connection = connection
+ self._nm_add_connection()
def deconfigure(self):
- netdev = self._netdev
- if "con_obj_path" in netdev and netdev["con_obj_path"] != "":
- self._nm_rm_connection(netdev["con_obj_path"])
- netdev["con_obj_path"] = ""
+ if self._con_obj_path != None:
+ self._nm_rm_connection()
#older versions of NM don't know how to remove soft devices...
#and lnst will break when multiple devices with the same mac exist
@@ -672,23 +676,31 @@ class NmConfigDeviceVlan(NmConfigDeviceGeneric):
except:
pass
+ def up(self):
+ realdev_id = get_slaves(self._dev_config)[0]
+ realdev = self._if_manager.get_mapped_device(realdev_id)
+ realdev.up()
+
+ super(NmConfigDeviceVlan, self).up()
+
class NmConfigDeviceTeam(NmConfigDeviceGeneric):
@classmethod
- def is_nm_managed(cls, netdev, config):
- if _dev_exists(netdev["hwaddr"]):
- managed = super(NmConfigDeviceTeam, cls).is_nm_managed(netdev,
- config)
+ def is_nm_managed(cls, dev_config, if_manager):
+ if _dev_exists(dev_config["hwaddr"]):
+ managed = super(NmConfigDeviceTeam, cls).is_nm_managed(dev_config,
+ if_manager)
else:
if get_nm_version() < "0.9.9":
managed = False
else:
- slave_id = get_slaves(netdev)[0]
- netdev = config[slave_id]
- managed = is_nm_managed(netdev, config)
-
- for slave in get_slaves(netdev):
- netdev = config[slave]
- if is_nm_managed(netdev, config) != managed:
+ slave_dev = if_manager.get_mapped_device(get_slaves(dev_config)[0])
+ slave_config = slave_dev.get_conf_dict()
+ managed = is_nm_managed(slave_config, if_manager)
+
+ for slave_id in get_slaves(dev_config):
+ slave_dev = if_manager.get_mapped_device(slave_id)
+ slave_config = slave_dev.get_conf_dict()
+ if is_nm_managed(slave_config, if_manager) != managed:
msg = "Mixing NM managed and not managed devices in a "\
"master-slave relationship is not allowed!"
raise Exception(msg)
@@ -698,34 +710,30 @@ class NmConfigDeviceTeam(NmConfigDeviceGeneric):
def up(self):
super(NmConfigDeviceTeam, self).up()
- for slave in get_slaves(self._netdev):
- netdev = self._config[slave]
- self._nm_activate_connection(netdev)
-
def down(self):
- for slave in get_slaves(self._netdev):
- netdev = self._config[slave]
- self._nm_deactivate_connection(netdev)
+ for slave_id in get_slaves(self._dev_config):
+ slave_dev = self._if_manager.get_mapped_device(slave_id)
+ slave_dev.down()
super(NmConfigDeviceTeam, self).down()
def _add_team(self):
- netdev = self._netdev
- netdev["master_uuid"] = str(uuid.uuid4())
+ config = self._dev_config
+ config["master_uuid"] = str(uuid.uuid4())
s_team_con = dbus.Dictionary({
'type': 'team',
'autoconnect': dbus.Boolean(False),
- 'uuid': netdev["master_uuid"],
- 'id': netdev["name"]+"_con"})
+ 'uuid': config["master_uuid"],
+ 'id': config["name"]+"_con"})
- teamd_config = get_option(self._netdev, "teamd_config")
+ teamd_config = get_option(config, "teamd_config")
s_team = dbus.Dictionary({
- 'interface-name': netdev["name"],
+ 'interface-name': config["name"],
'config': teamd_config})
- s_ipv4, s_ipv6 = self._nm_make_ip_settings(netdev["addresses"])
+ s_ipv4, s_ipv6 = self._nm_make_ip_settings(config["addresses"])
connection = dbus.Dictionary({
'team': s_team,
@@ -733,53 +741,37 @@ class NmConfigDeviceTeam(NmConfigDeviceGeneric):
'ipv6': s_ipv6,
'connection': s_team_con})
- netdev["con_obj_path"] = self._nm_add_connection(connection)
+ self._connection = connection
+ self._nm_add_connection()
def _rm_team(self):
- netdev = self._netdev
- if netdev["con_obj_path"] != "":
- self._nm_rm_connection(netdev["con_obj_path"])
- netdev["con_obj_path"] = ""
+ if self._con_obj_path != None:
+ self._nm_rm_connection()
def _add_slaves(self):
- for slave in get_slaves(self._netdev):
- netdev = self._config[slave]
- slave_name = netdev["name"]
-
- hw_addr = self._convert_hwaddr(netdev)
-
- teamd_port_config = get_slave_option(self._netdev,
- slave, "teamd_port_config")
-
- s_eth = dbus.Dictionary({
- 'duplex': dbus.Array('full', 's'),
- 'mac-address': hw_addr})
+ for slave_id in get_slaves(self._dev_config):
+ slave_dev = self._if_manager.get_mapped_device(slave_id)
+ slave_config = slave_dev.get_configuration()
- s_slave_con = dbus.Dictionary({
- 'type': '802-3-ethernet',
- 'autoconnect': dbus.Boolean(False),
- 'uuid': str(uuid.uuid4()),
- 'id': 'slave_con',
- 'master': self._netdev["master_uuid"],
- 'slave-type': 'team'})
+ teamd_port_config = get_slave_option(self._dev_config,
+ slave_id,
+ "teamd_port_config")
- slave_con = dbus.Dictionary({
- '802-3-ethernet': s_eth,
- 'connection': s_slave_con})
+ slave_con = dbus.Dictionary()
if teamd_port_config != None:
s_port_cfg = dbus.Dictionary({
'config': teamd_port_config})
slave_con['team-port'] = s_port_cfg
- netdev["con_obj_path"] = self._nm_add_connection(slave_con)
+ slave_config.nm_enslave("team", self._dev_config["master_uuid"],
+ slave_con)
def _rm_slaves(self):
- for slave in get_slaves(self._netdev):
- netdev = self._config[slave]
- if netdev["con_obj_path"] != "":
- self._nm_rm_connection(netdev["con_obj_path"])
- netdev["con_obj_path"] = ""
+ for slave_id in get_slaves(self._dev_config):
+ slave_dev = self._if_manager.get_mapped_device(slave_id)
+ slave_config = slave_dev.get_configuration()
+ slave_config.nm_free()
def configure(self):
self._add_team()
@@ -798,5 +790,6 @@ type_class_mapping = {
"team": NmConfigDeviceTeam
}
-def is_nm_managed(netdev, config):
- return type_class_mapping[netdev["type"]].is_nm_managed(netdev, config)
+def is_nm_managed(dev_config, if_manager):
+ return type_class_mapping[dev_config["type"]].is_nm_managed(dev_config,
+ if_manager)
10 years, 2 months
[lnst] NetConfigDevice: InterfaceManager integration
by Jiří Pírko
commit e0c01e127245cffabc3ada7d408e8e03920c6920
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Thu Feb 6 13:39:14 2014 +0100
NetConfigDevice: InterfaceManager integration
The NetConfigDevice module now supports the new InterfaceManager module
instead of the old NetConfig way. I also refactored certain variable
names so that they make more sense and are consistent with the rest of
the code.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Slave/NetConfigDevice.py | 176 ++++++++++++++++++++++-------------------
1 files changed, 94 insertions(+), 82 deletions(-)
---
diff --git a/lnst/Slave/NetConfigDevice.py b/lnst/Slave/NetConfigDevice.py
index 0c71fc7..997f22d 100644
--- a/lnst/Slave/NetConfigDevice.py
+++ b/lnst/Slave/NetConfigDevice.py
@@ -23,7 +23,7 @@ from lnst.Common.Utils import check_process_running
from lnst.Common.Config import lnst_config
-class NetConfigDeviceGeneric:
+class NetConfigDeviceGeneric(object):
'''
Generic class for device manipulation all type classes should
extend this one.
@@ -33,9 +33,10 @@ class NetConfigDeviceGeneric:
_moduleparams = ""
_cleanupcmd = ""
- def __init__(self, netdev, config):
- self._netdev = netdev
- self._config = config
+ def __init__(self, dev_config, if_manager):
+ self._dev_config = dev_config
+ self._if_manager = if_manager
+ self.type_init()
def configure(self):
pass
@@ -43,25 +44,25 @@ class NetConfigDeviceGeneric:
def deconfigure(self):
pass
- def slave_add(self, slaveid):
+ def slave_add(self, slave_id):
pass
- def slave_del(self, slaveid):
+ def slave_del(self, slave_id):
pass
def up(self):
- netdev = self._netdev
- if "addresses" in netdev:
- for address in netdev["addresses"]:
- exec_cmd("ip addr add %s dev %s" % (address, netdev["name"]))
- exec_cmd("ip link set %s up" % netdev["name"])
+ config = self._dev_config
+ if "addresses" in config:
+ for address in config["addresses"]:
+ exec_cmd("ip addr add %s dev %s" % (address, config["name"]))
+ exec_cmd("ip link set %s up" % config["name"])
def down(self):
- netdev = self._netdev
- if "addresses" in netdev:
- for address in netdev["addresses"]:
- exec_cmd("ip addr del %s dev %s" % (address, netdev["name"]))
- exec_cmd("ip link set %s down" % netdev["name"])
+ config = self._dev_config
+ if "addresses" in config:
+ for address in config["addresses"]:
+ exec_cmd("ip addr del %s dev %s" % (address, config["name"]))
+ exec_cmd("ip link set %s down" % config["name"])
@classmethod
def type_init(self):
@@ -75,9 +76,9 @@ class NetConfigDeviceGeneric:
class NetConfigDeviceEth(NetConfigDeviceGeneric):
def configure(self):
- netdev = self._netdev
- exec_cmd("ip addr flush %s" % netdev["name"])
- exec_cmd("ethtool -A %s rx off tx off" % netdev["name"], die_on_err=False, log_outputs=False)
+ config = self._dev_config
+ exec_cmd("ip addr flush %s" % config["name"])
+ exec_cmd("ethtool -A %s rx off tx off" % config["name"], die_on_err=False, log_outputs=False)
class NetConfigDeviceBond(NetConfigDeviceGeneric):
_modulename = "bonding"
@@ -85,33 +86,35 @@ class NetConfigDeviceBond(NetConfigDeviceGeneric):
def _add_rm_bond(self, mark):
bond_masters = "/sys/class/net/bonding_masters"
- exec_cmd('echo "%s%s" > %s' % (mark, self._netdev["name"],
+ exec_cmd('echo "%s%s" > %s' % (mark, self._dev_config["name"],
bond_masters))
def _get_bond_dir(self):
- return "/sys/class/net/%s/bonding" % self._netdev["name"]
+ return "/sys/class/net/%s/bonding" % self._dev_config["name"]
def _setup_options(self):
- if not "options" in self._netdev:
+ if not "options" in self._dev_config:
return
- options = self._netdev["options"]
+ options = self._dev_config["options"]
for option, value in options:
if option == "primary":
'''
"primary" option is not direct value but it's
index of netdevice. So take the appropriate name from config
'''
- value = self._config[int(value)]["name"]
+ slave_dev = self._if_manager.get_mapped_device(int(value))
+ value = slave_dev.get_name()
exec_cmd('echo "%s" > %s/%s' % (value,
self._get_bond_dir(),
option))
def _add_rm_slaves(self, mark):
- for slave in get_slaves(self._netdev):
- slavenetdev = self._config[slave]
- slave_name = slavenetdev["name"]
+ for slave_id in get_slaves(self._dev_config):
+ slave_dev = self._if_manager.get_mapped_device(slave_id)
+ slave_conf = slave_dev.get_conf_dict()
+ slave_name = slave_dev.get_name()
if (mark == "+"):
- NetConfigDevice(slavenetdev, self._config).down()
+ slave_dev.down()
exec_cmd('echo "%s%s" > %s/slaves' % (mark, slave_name,
self._get_bond_dir()))
@@ -128,16 +131,16 @@ class NetConfigDeviceBridge(NetConfigDeviceGeneric):
_modulename = "bridge"
def _add_rm_bridge(self, prefix):
- exec_cmd("brctl %sbr %s " % (prefix, self._netdev["name"]))
+ exec_cmd("brctl %sbr %s " % (prefix, self._dev_conf["name"]))
- def _add_rm_port(self, prefix, slaveid):
- port_name = self._config[slaveid]["name"]
- exec_cmd("brctl %sif %s %s" % (prefix, self._netdev["name"],
+ def _add_rm_port(self, prefix, slave_if_index):
+ port_name = self._if_manager.get_mapped_device(slave_id).get_name()
+ exec_cmd("brctl %sif %s %s" % (prefix, self._dev_conf["name"],
port_name))
def _add_rm_ports(self, prefix):
- for slaveid in get_slaves(self._netdev):
- self._add_rm_port(prefix, slaveid)
+ for slave_id in get_slaves(self._dev_conf):
+ self._add_rm_port(prefix, slave_id)
def configure(self):
self._add_rm_bridge("add")
@@ -147,31 +150,31 @@ class NetConfigDeviceBridge(NetConfigDeviceGeneric):
self._add_rm_ports("del")
self._add_rm_bridge("del")
- def slave_add(self, slaveid):
- self._add_rm_port("add", slaveid)
+ def slave_add(self, slave_id):
+ self._add_rm_port("add", slave_id)
- def slave_del(self, slaveid):
- self._add_rm_port("del", slaveid)
+ def slave_del(self, slave_id):
+ self._add_rm_port("del", slave_id)
class NetConfigDeviceMacvlan(NetConfigDeviceGeneric):
_modulename = "macvlan"
def configure(self):
- netdev = self._netdev;
- realdev_index = netdev["slaves"][0]
- realdev = self._config[realdev_index]["name"]
- dev_name = netdev["name"]
+ config = self._dev_config;
+ realdev_id = config["slaves"][0]
+ realdev_name = self._if_manager.get_mapped_device(realdev_id).get_name()
+ dev_name = config["name"]
- if "hwaddr" in netdev:
- hwaddr = " address %s" % netdev["hwaddr"]
+ if "hwaddr" in config:
+ hwaddr = " address %s" % config["hwaddr"]
else:
hwaddr = ""
exec_cmd("ip link add link %s %s%s type macvlan"
- % (realdev, dev_name, hwaddr))
+ % (realdev_name, dev_name, hwaddr))
def deconfigure(self):
- dev_name = self._netdev["name"]
+ dev_name = self._dev_config["name"]
exec_cmd("ip link del %s" % dev_name)
class NetConfigDeviceVlan(NetConfigDeviceGeneric):
@@ -186,24 +189,24 @@ class NetConfigDeviceVlan(NetConfigDeviceGeneric):
return False
def _get_vlan_info(self):
- netdev = self._netdev;
- realdev_index = get_slaves(netdev)[0]
- realdev = self._config[realdev_index]["name"]
- dev_name = netdev["name"]
- vlan_tci = int(get_option(netdev, "vlan_tci"))
- return dev_name, realdev, vlan_tci
+ config = self._dev_config;
+ realdev_id = get_slaves(config)[0]
+ realdev_name = self._if_manager.get_mapped_device(realdev_id).get_name()
+ dev_name = config["name"]
+ vlan_tci = int(get_option(config, "vlan_tci"))
+ return dev_name, realdev_name, vlan_tci
def configure(self):
- dev_name, realdev, vlan_tci = self._get_vlan_info()
+ dev_name, realdev_name, vlan_tci = self._get_vlan_info()
if self._check_ip_link_add():
exec_cmd("ip link add link %s %s type vlan id %d"
- % (realdev, dev_name, vlan_tci))
+ % (realdev_name, dev_name, vlan_tci))
else:
- if not re.match(r'^%s.%d$' % (realdev, vlan_tci), dev_name):
+ if not re.match(r'^%s.%d$' % (realdev_name, vlan_tci), dev_name):
logging.error("Since using old vlan manipulation interface, "
"devname \"%s\" cannot be used" % dev_name)
raise Exception("Bad vlan device name")
- exec_cmd("vconfig add %s %d" % (realdev, vlan_tci))
+ exec_cmd("vconfig add %s %d" % (realdev_name, vlan_tci))
def deconfigure(self):
dev_name = self._get_vlan_info()[0]
@@ -212,6 +215,13 @@ class NetConfigDeviceVlan(NetConfigDeviceGeneric):
else:
exec_cmd("vconfig rem %s" % dev_name)
+ def up(self):
+ parent_id = get_slaves(self._dev_config)[0]
+ parent_dev = self._if_manager.get_mapped_device(parent_id)
+ exec_cmd("ip link set %s up" % parent_dev.get_name())
+
+ super(NetConfigDeviceVlan, self).up()
+
def prepare_json_str(json_str):
if not json_str:
return ""
@@ -225,60 +235,62 @@ class NetConfigDeviceTeam(NetConfigDeviceGeneric):
_cleanupcmd = "killall -q teamd"
def _should_enable_dbus(self):
- dbus_disabled = get_option(self._netdev, "dbus_disabled")
+ dbus_disabled = get_option(self._dev_config, "dbus_disabled")
if not dbus_disabled or bool_it(dbus_disabled):
return True
return False
def _ports_down(self):
- for slave_id in get_slaves(self._netdev):
- port_netdev = self._config[slave_id]
- NetConfigDevice(port_netdev, self._config).down()
+ for slave_id in get_slaves(self._dev_config):
+ port_dev = self._if_manager.get_mapped_device(slave_id)
+ port_dev.down()
def _ports_up(self):
- for slave_id in get_slaves(self._netdev):
- port_netdev = self._config[slave_id]
- NetConfigDevice(port_netdev, self._config).up()
+ for slave_id in get_slaves(self._dev_config):
+ port_dev = self._if_manager.get_mapped_device(slave_id)
+ port_dev.up()
def configure(self):
self._ports_down()
- teamd_config = get_option(self._netdev, "teamd_config")
+ teamd_config = get_option(self._dev_config, "teamd_config")
teamd_config = prepare_json_str(teamd_config)
- dev_name = self._netdev["name"]
+ dev_name = self._dev_config["name"]
dbus_option = " -D" if self._should_enable_dbus() else ""
exec_cmd("teamd -r -d -c \"%s\" -t %s %s" % (teamd_config, dev_name, dbus_option))
- for slave_id in get_slaves(self._netdev):
+ for slave_id in get_slaves(self._dev_config):
self.slave_add(slave_id)
self._ports_up()
def deconfigure(self):
- for slave_id in get_slaves(self._netdev):
+ for slave_id in get_slaves(self._dev_config):
self.slave_del(slave_id)
- dev_name = self._netdev["name"]
+ dev_name = self._dev_config["name"]
exec_cmd("teamd -k -t %s" % dev_name)
- def slave_add(self, slaveid):
- dev_name = self._netdev["name"]
- port_netdev = self._config[slaveid]
- port_name = port_netdev["name"]
- teamd_port_config = get_slave_option(self._netdev,
- slaveid, "teamd_port_config")
+ def slave_add(self, slave_id):
+ dev_name = self._dev_config["name"]
+ port_dev = self._if_manager.get_mapped_device(slave_id)
+ port_name = port_dev.get_name()
+ teamd_port_config = get_slave_option(self._dev_config,
+ slave_id,
+ "teamd_port_config")
dbus_option = "-D" if self._should_enable_dbus() else ""
if teamd_port_config:
teamd_port_config = prepare_json_str(teamd_port_config)
exec_cmd("teamdctl %s %s port config update %s \"%s\"" % (dbus_option, dev_name, port_name, teamd_port_config))
- NetConfigDevice(port_netdev, self._config).down()
+ port_dev.down()
exec_cmd("teamdctl %s %s port add %s" % (dbus_option, dev_name, port_name))
- def slave_del(self, slaveid):
- dev_name = self._netdev["name"]
- port_name = self._config[slaveid]["name"]
+ def slave_del(self, slave_id):
+ dev_name = self._dev_config["name"]
+ port_dev = self._if_manager.get_mapped_device(slave_id)
+ port_name = port_dev.get_name()
dbus_option = "-D" if self._should_enable_dbus() else ""
exec_cmd("teamdctl %s %s port remove %s" % (dbus_option, dev_name, port_name))
@@ -291,14 +303,14 @@ type_class_mapping = {
"team": NetConfigDeviceTeam
}
-def NetConfigDevice(netdev, config):
+def NetConfigDevice(dev_config, if_manager):
'''
Class dispatcher
'''
- if is_nm_managed(netdev, config):
- return nm_type_class_mapping[netdev["type"]](netdev, config)
+ if is_nm_managed(dev_config, if_manager):
+ return nm_type_class_mapping[dev_config["type"]](dev_config, if_manager)
else:
- return type_class_mapping[netdev["type"]](netdev, config)
+ return type_class_mapping[dev_config["type"]](dev_config, if_manager)
def NetConfigDeviceType(netdev, config):
'''
10 years, 2 months
[lnst] InterfaceManager module created
by Jiří Pírko
commit 41f17704e8d4024e6b4d0faa0664a9a4ed1b0600
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Thu Feb 6 13:39:13 2014 +0100
InterfaceManager module created
The module contains two classes:
InterfaceManager
- will represent the device database of the slave machine
- handles creation of soft devices, name assignment included
- handles netlink messages by updating the database
- provides access to local devices by kernel ifindex of the device
(used for unique identification on the machine)
- contains controller id to slave device mapping - created on
controller interface initialization by the HWADDR specified in the
controllers pool files. The controller therefore only needs to
know the id of the device and the slave will translate that to the
specific device.
Device
- will represent a device record in the InterfaceManager database
- provides a configuration interface that will use the *ConfigDevice
objects.
- will provide an interface to accessing the most common device
attributes (such as IP address)
- supports updates based on netlink messages and will be able to
send update messages to the controller if any attributes are
changed
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Slave/InterfaceManager.py | 250 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 250 insertions(+), 0 deletions(-)
---
diff --git a/lnst/Slave/InterfaceManager.py b/lnst/Slave/InterfaceManager.py
new file mode 100644
index 0000000..bc5793d
--- /dev/null
+++ b/lnst/Slave/InterfaceManager.py
@@ -0,0 +1,250 @@
+"""
+This module defines the InterfaceManager class that contains a database of
+the available devices, handles netlink messages updating these devices and
+provides an interface for creating software interfaces from config objects.
+
+Copyright 2014 Red Hat, Inc.
+Licensed under the GNU General Public License, version 2 as
+published by the Free Software Foundation; see COPYING for details.
+"""
+
+__author__ = """
+olichtne(a)redhat.com (Ondrej Lichtner)
+"""
+
+import logging
+from lnst.Slave.NetConfigDevice import NetConfigDevice
+from lnst.Slave.NetConfigCommon import get_option
+from lnst.Common.NetUtils import normalize_hwaddr
+from lnst.Common.NetUtils import scan_netdevs
+from lnst.Common.ExecCmd import exec_cmd
+from pyroute2 import IPRSocket
+from pyroute2.netlink.iproute import RTM_NEWLINK
+from pyroute2.netlink.iproute import RTM_DELLINK
+
+class IfMgrError(Exception):
+ pass
+
+class InterfaceManager(object):
+ def __init__(self):
+ self._devices = {}
+ self._id_mapping = {} #id from the ctl to device
+
+ self._nl_socket = IPRSocket()
+ self._nl_socket.bind()
+
+ self._rescan_devices()
+
+ def map_if(self, if_id, if_index):
+ if if_id in self._id_mapping:
+ raise IfMgrError("Interface already mapped.")
+ elif if_index not in self._devices:
+ raise IfMgrError("No interface with index %s found." % if_index)
+
+ self._id_mapping[if_id] = self._devices[if_index]
+ return
+
+ def clear_if_mapping(self):
+ self._id_mapping = {}
+
+ def get_nl_socket(self):
+ return self._nl_socket
+
+ def _rescan_devices(self):
+ devs = scan_netdevs()
+ for dev in devs:
+ if dev['index'] not in self._devices:
+ device = Device(self)
+ device.init_netlink(dev['netlink_msg'])
+
+ self._devices[dev['index']] = device
+
+ def handle_netlink_msgs(self, msgs):
+ for msg in msgs:
+ self._handle_netlink_msg(msg)
+
+ def _handle_netlink_msg(self, msg):
+ if msg['header']['type'] == RTM_NEWLINK:
+ if msg['index'] in self._devices:
+ self._devices[msg['index']].update_netlink(msg)
+ else:
+ dev = None
+ for d in self._id_mapping.values():
+ d_cfg = d.get_conf_dict()
+ if d.get_if_index() == None and\
+ d_cfg["name"] == msg.get_attr("IFLA_IFNAME"):
+ dev = d
+ break
+ if dev == None:
+ dev = Device(self)
+ dev.init_netlink(msg)
+ self._devices[msg['index']] = dev
+ elif msg['header']['type'] == RTM_DELLINK:
+ if msg['index'] in self._devices:
+ del self._devices[msg['index']]
+ else:
+ return
+
+ def get_mapped_device(self, if_id):
+ if if_id in self._id_mapping:
+ return self._id_mapping[if_id]
+ else:
+ raise IfMgrError("No device with id %s mapped." % if_id)
+
+ def get_mapped_devices(self):
+ return self._id_mapping
+
+ def get_device(self, if_index):
+ if if_index in self._devices:
+ return self._devices[if_index]
+ else:
+ return None
+
+ def get_devices(self):
+ return self._devices.values()
+
+ def get_device_by_hwaddr(self, hwaddr):
+ for dev in self._devices.values():
+ if dev.get_hwaddr() == hwaddr:
+ return dev
+ return None
+
+ def deconfigure_all(self):
+ for dev in self._devices.itervalues():
+ dev.clear_configuration()
+
+ def create_device_from_config(self, if_id, config):
+ if config["type"] == "eth":
+ raise IfMgrError("Ethernet devices can't be created.")
+
+ config["name"] = self.assign_name(config)
+
+ device = Device(self)
+ device.set_configuration(config)
+ device.configure()
+
+ self._id_mapping[if_id] = device
+ return config["name"]
+
+ def _is_name_used(self, name):
+ for device in self._devices.itervalues():
+ if name == device.get_name():
+ return True
+ return False
+
+ def _assign_name_generic(self, prefix):
+ index = 0
+ while (self._is_name_used(prefix + str(index))):
+ index += 1
+ return prefix + str(index)
+
+ def assign_name(self, config):
+ if "name" in config:
+ return config["name"]
+ dev_type = config["type"]
+ if dev_type == "eth":
+ if (not "hwaddr" in config or
+ "name" in config):
+ return
+ hwaddr = normalize_hwaddr(netdev["hwaddr"])
+ for dev in self._devices:
+ if dev.get_hwaddr() == hwaddr:
+ return dev.get_name()
+ elif dev_type == "bond":
+ return self._assign_name_generic("t_bond")
+ elif dev_type == "bridge":
+ return self._assign_name_generic("t_br")
+ elif dev_type == "macvlan":
+ return self._assign_name_generic("t_macvlan")
+ elif dev_type == "team":
+ return self._assign_name_generic("t_team")
+ elif dev_type == "vlan":
+ netdev_name = self.get_mapped_device(config["slaves"][0]).get_name()
+ vlan_tci = get_option(config, "vlan_tci")
+ prefix = "%s.%s_" % (netdev_name, vlan_tci)
+ return self._assign_name_generic(prefix)
+
+class Device(object):
+ def __init__(self, if_manager):
+ self._configured = False
+
+ self._if_index = None
+ self._hwaddr = None
+ self._name = None
+ self._conf = None
+ self._conf_dict = None
+ self._ip = None
+ self._state = None
+
+ self._if_manager = if_manager
+
+ def init_netlink(self, nl_msg):
+ self._if_index = nl_msg['index']
+ self._hwaddr = normalize_hwaddr(nl_msg.get_attr("IFLA_ADDRESS"))
+ self._name = nl_msg.get_attr("IFLA_IFNAME")
+ self._state = nl_msg.get_attr("IFLA_OPERSTATE")
+ self._ip = None #TODO
+
+ def update_netlink(self, nl_msg):
+ if self._if_index == nl_msg['index']:
+ self._hwaddr = normalize_hwaddr(nl_msg.get_attr("IFLA_ADDRESS"))
+ self._name = nl_msg.get_attr("IFLA_IFNAME")
+ self._ip = None #TODO
+ #send update msg
+
+ def get_if_index(self):
+ return self._if_index
+
+ def get_hwaddr(self):
+ return self._hwaddr
+
+ def get_name(self):
+ return self._name
+
+ def get_ip_conf(self):
+ return self._ip
+
+ def is_configured(self):
+ return self._configured
+
+ def get_conf_dict(self):
+ return self._conf_dict
+
+ def set_configuration(self, conf):
+ self.clear_configuration()
+ if "name" not in conf or conf["name"] == None:
+ conf["name"] = self._name
+ self._conf_dict = conf
+ self._conf = NetConfigDevice(conf, self._if_manager)
+
+ def get_configuration(self):
+ return self._conf
+
+ def clear_configuration(self):
+ if self._conf != None:
+ self.down()
+ self.deconfigure()
+ self._conf = None
+ self._conf_dict = None
+
+ def configure(self):
+ if self._conf != None and not self._configured:
+ self._conf.configure()
+ self._configured = True
+
+ def deconfigure(self):
+ if self._conf != None and self._configured:
+ self._conf.deconfigure()
+ self._configured = False
+
+ def up(self):
+ if self._conf != None:
+ self._conf.up()
+ else:
+ exec_cmd("ip link set %s up" % self._name)
+
+ def down(self):
+ if self._conf != None:
+ self._conf.down()
+ else:
+ exec_cmd("ip link set %s down" % self._name)
10 years, 2 months
[lnst] NetTestSlave: handle ctl messages last
by Jiří Pírko
commit cfe927a9bfdaec46ad4f17a161c51971c1bb7861
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Thu Feb 6 13:39:12 2014 +0100
NetTestSlave: handle ctl messages last
The get_messages method of the ServerHandler class will now return
messages sorted so that messages from the controller are last. This
presents a kind of optimization resulting in updates taking place before
the controller calls a method.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Slave/NetTestSlave.py | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
---
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index 0cd6185..d334449 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -392,6 +392,18 @@ class ServerHandler(object):
def get_messages(self):
messages = self._connection_handler.check_connections()
+
+ #push ctl messages to the end of message queue, this ensures that
+ #update messages are handled first
+ ctl_msgs = []
+ non_ctl_msgs = []
+ for msg in messages:
+ if msg[0] == self._c_socket[1]:
+ ctl_msgs.append(msg)
+ else:
+ non_ctl_msgs.append(msg)
+ messages = non_ctl_msgs + ctl_msgs
+
addr = self._c_socket[1]
if self._connection_handler.get_connection(addr) == None:
logging.info("Lost controller connection.")
10 years, 2 months
[lnst] ConnectionHandler: retrieve ALL messages from connections
by Jiří Pírko
commit bbda90f30ff3cdc0e00695a0b925c5833206bc13
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Thu Feb 6 13:39:11 2014 +0100
ConnectionHandler: retrieve ALL messages from connections
The check_connections method only recieved one message per file
descriptor. This wasn't a problem because the other messages would be
retrieved in the next iteration. However this way we will be able to
order the recieved messages, so that messages from the controller can be
handled last, after all recieved updates (e.g. netlink).
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Common/ConnectionHandler.py | 39 ++++++++++++++++++++++++-------------
1 files changed, 25 insertions(+), 14 deletions(-)
---
diff --git a/lnst/Common/ConnectionHandler.py b/lnst/Common/ConnectionHandler.py
index c0a43fa..04eef86 100644
--- a/lnst/Common/ConnectionHandler.py
+++ b/lnst/Common/ConnectionHandler.py
@@ -76,22 +76,33 @@ class ConnectionHandler(object):
except select.error:
return []
for f in rl:
- try:
- data = recv_data(f)
-
- if data == "":
+ f_ready = True
+ while f_ready:
+ try:
+ data = recv_data(f)
+
+ if data == "":
+ f.close()
+ self.remove_connection(f)
+ f_ready = False
+ else:
+ id = self.get_connection_id(f)
+ requests.append((id, data))
+
+ #poll the file descriptor if there is another message
+ rll, _, _ = select.select([f], [], [], 0)
+ if rll == []:
+ f_ready = False
+
+ except socket.error:
+ f_ready = False
+ f.close()
+ self.remove_connection(f)
+ except EOFError:
+ f_ready = False
f.close()
self.remove_connection(f)
- else:
- id = self.get_connection_id(f)
- requests.append((id, data))
-
- except socket.error:
- f.close()
- self.remove_connection(f)
- except EOFError:
- f.close()
- self.remove_connection(f)
+
return requests
def get_connection(self, id):
10 years, 2 months
[lnst] NetTestSlave: fix ctl_clean_exit typos
by Jiří Pírko
commit 7f365cc7115cca8586659ceba142d2e7496e29f4
Author: Ondrej Lichtner <olichtne(a)redhat.com>
Date: Thu Feb 6 13:31:47 2014 +0100
NetTestSlave: fix ctl_clean_exit typos
The internal variable ctl_clean_exit in the SlaveMethods class was
incorrectly used a few types, python didn't pick this up because of it's
dynamic nature... This however caused that the cleanup didn't work
properly. This commit fixes that.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Slave/NetTestSlave.py | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
---
diff --git a/lnst/Slave/NetTestSlave.py b/lnst/Slave/NetTestSlave.py
index f8dad2b..0cd6185 100644
--- a/lnst/Slave/NetTestSlave.py
+++ b/lnst/Slave/NetTestSlave.py
@@ -61,12 +61,12 @@ class SlaveMethods:
self._resource_table = {}
- self.ctl_clean_exit = True
+ self._ctl_clean_exit = True
def hello(self, recipe_path):
- if not self.ctl_clean_exit:
- self._methods.machine_cleanup()
- self._methods.ctl_clean_exit = True
+ if not self._ctl_clean_exit:
+ self.machine_cleanup()
+ self._ctl_clean_exit = True
logging.info("Recieved a controller connection.")
self.clear_resource_table()
@@ -94,7 +94,7 @@ class SlaveMethods:
self._cache.del_old_entries()
self.reset_file_transfers()
self._remove_capture_files()
- self.ctl_clean_exit = True
+ self._ctl_clean_exit = True
return "bye"
def kill_cmds(self):
10 years, 2 months