From: Ondrej Lichtner <olichtne(a)redhat.com>
This commit adds a function is_nm_managed_by_name which checks if the
device with a specified name is managed by NM. When the device doesn't
exist it assumes that NM manages it as it's probably a soft device that
will be created.
Additionaly a class method is_nm_managed was added to the NmConfigDevice
class hierarchy that uses the new function and returns if the specified
device and potentially it's group of slaves is managed by NM and in case
of a conflict an Exception can be raised.
Lastly a function is_nm_managed has been added that just calls the
class method is_nm_managed from the approriate class.
Signed-off-by: Ondrej Lichtner <olichtne(a)redhat.com>
---
lnst/Slave/NmConfigDevice.py | 101 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 99 insertions(+), 2 deletions(-)
diff --git a/lnst/Slave/NmConfigDevice.py b/lnst/Slave/NmConfigDevice.py
index e7d6418..5168aff 100644
--- a/lnst/Slave/NmConfigDevice.py
+++ b/lnst/Slave/NmConfigDevice.py
@@ -21,6 +21,7 @@ import time
from lnst.Common.ExecCmd import exec_cmd
from lnst.Slave.NetConfigCommon import get_slaves, get_option, get_slave_option
from lnst.Common.Utils import kmod_in_use, bool_it
+from lnst.Common.NetUtils import scan_netdevs
NM_BUS = "org.freedesktop.NetworkManager"
OBJ_PRE = "/org/freedesktop/NetworkManager"
@@ -31,6 +32,25 @@ _ACON_ACTIVATED = 2
_DEV_UNAVAILABLE = 20
_DEV_DISCONNECTED = 30
+def is_nm_managed_by_name(dev_name):
+ if not check_process_running("NetworkManager"):
+ return False
+
+ bus = dbus.SystemBus()
+ nm_obj = bus.get_object(NM_BUS, OBJ_PRE)
+ nm_if = dbus.Interface(nm_obj, IF_PRE)
+ try:
+ device_obj_path = nm_if.GetDeviceByIpIface(dev_name)
+ except:
+ #There is a higher possibility that if the interface doesn't exist
+ #it's a software interface that can be created by NM so we say that it's
+ #managed and check existance of physical interfaces sepparately
+ return True
+
+ dev = bus.get_object(NM_BUS, device_obj_path)
+ dev_props = dbus.Interface(dev, "org.freedesktop.DBus.Properties")
+ return dev_props.Get(IF_PRE + ".Device", "Managed")
+
class NmConfigDeviceGeneric(object):
'''
Generic class for device manipulation all type classes should
@@ -81,6 +101,10 @@ class NmConfigDeviceGeneric(object):
def type_cleanup(self):
pass
+ @classmethod
+ def is_nm_managed(cls, netdev, config):
+ return is_nm_managed_by_name(netdev["name"])
+
def _wait_for_state(self, new_state, old_state, reason):
self._device_state = new_state
if self._device_state == self._wait_for:
@@ -204,6 +228,15 @@ class NmConfigDeviceGeneric(object):
netdev["acon_obj_path"] = ""
class NmConfigDeviceEth(NmConfigDeviceGeneric):
+ @classmethod
+ def is_nm_managed(cls, netdev, config):
+ managed = super(NmConfigDeviceEth, cls).is_nm_managed(netdev, config)
+ devnames = scan_netdevs()
+ for dev in devnames:
+ if dev["hwaddr"] == netdev["hwaddr"]:
+ return managed
+ return False
+
def up(self):
netdev = self._netdev
@@ -264,6 +297,19 @@ class NmConfigDeviceBond(NmConfigDeviceGeneric):
_modulename = "bonding"
_moduleparams = "max_bonds=0"
+ @classmethod
+ def is_nm_managed(cls, netdev, config):
+ managed = super(NmConfigDeviceBond, cls).is_nm_managed(netdev, config)
+
+ for slave in get_slaves(netdev):
+ netdev = config[slave]
+ if is_nm_managed(netdev, config) != managed:
+ msg = "Mixing NM managed and not managed devices in a "\
+ "master-slave relationship is not allowed!"
+ raise Exception(msg)
+
+ return managed
+
def up(self):
super(NmConfigDeviceBond, self).up()
@@ -378,6 +424,19 @@ class NmConfigDeviceBond(NmConfigDeviceGeneric):
class NmConfigDeviceBridge(NmConfigDeviceGeneric):
_modulename = "bridge"
+ @classmethod
+ def is_nm_managed(cls, netdev, config):
+ managed = super(NmConfigDeviceBridge, cls).is_nm_managed(netdev, config)
+
+ for slave in get_slaves(netdev):
+ netdev = config[slave]
+ if is_nm_managed(netdev, config) != managed:
+ msg = "Mixing NM managed and not managed devices in a "\
+ "master-slave relationship is not allowed!"
+ raise Exception(msg)
+
+ return managed
+
def up(self):
super(NmConfigDeviceBridge, self).up()
@@ -480,11 +539,35 @@ class NmConfigDeviceBridge(NmConfigDeviceGeneric):
class NmConfigDeviceMacvlan(NmConfigDeviceGeneric):
#Not supported by NetworkManager yet
- pass
+ @classmethod
+ def is_nm_managed(cls, netdev, config):
+ managed = False
+
+ for slave in get_slaves(netdev):
+ slave_netdev = config[slave]
+ if is_nm_managed(slave_netdev, config) != managed:
+ msg = "Mixing NM managed and not managed devices in a "\
+ "master-slave relationship is not allowed!"
+ raise Exception(msg)
+
+ return managed
class NmConfigDeviceVlan(NmConfigDeviceGeneric):
_modulename = "8021q"
+ @classmethod
+ def is_nm_managed(cls, netdev, config):
+ managed = super(NmConfigDeviceVlan, cls).is_nm_managed(netdev, config)
+
+ for slave in get_slaves(netdev):
+ slave_netdev = config[slave]
+ if is_nm_managed(slave_netdev, config) != managed:
+ msg = "Mixing NM managed and not managed devices in a "\
+ "master-slave relationship is not allowed!"
+ raise Exception(msg)
+
+ return managed
+
def _check_ip_link_add(self):
output = exec_cmd("ip link help", die_on_err=False,
log_outputs=False)[1]
@@ -541,7 +624,18 @@ class NmConfigDeviceVlan(NmConfigDeviceGeneric):
class NmConfigDeviceTeam(NmConfigDeviceGeneric):
#Not supported by NetworkManager yet
- pass
+ @classmethod
+ def is_nm_managed(cls, netdev, config):
+ managed = False
+
+ for slave in get_slaves(netdev):
+ slave_netdev = config[slave]
+ if is_nm_managed(slave_netdev, config) != managed:
+ msg = "Mixing NM managed and not managed devices in a "\
+ "master-slave relationship is not allowed!"
+ raise Exception(msg)
+
+ return managed
type_class_mapping = {
"eth": NmConfigDeviceEth,
@@ -551,3 +645,6 @@ type_class_mapping = {
"vlan": NmConfigDeviceVlan,
"team": NmConfigDeviceTeam
}
+
+def is_nm_managed(netdev, config):
+ return type_class_mapping[netdev["type"]].is_nm_managed(netdev, config)
--
1.8.3.1