aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/os-net-config/samples/linux_bond_networkmanager.yaml18
-rw-r--r--os_net_config/impl_ifcfg.py32
-rw-r--r--os_net_config/objects.py142
-rw-r--r--os_net_config/tests/test_impl_ifcfg.py73
4 files changed, 206 insertions, 59 deletions
diff --git a/etc/os-net-config/samples/linux_bond_networkmanager.yaml b/etc/os-net-config/samples/linux_bond_networkmanager.yaml
new file mode 100644
index 0000000..c7036c0
--- /dev/null
+++ b/etc/os-net-config/samples/linux_bond_networkmanager.yaml
@@ -0,0 +1,18 @@
+# To use NetworkManager to manage an interface, set nm_controlled=true.
+# Note that some interface types may not be supported by NetworkManager.
+network_config:
+ -
+ type: linux_bond
+ name: bond1
+ nm_controlled: true
+ use_dhcp: true
+ bonding_options: "mode=active-backup"
+ members:
+ -
+ type: interface
+ name: em1
+ nm_controlled: true
+ -
+ type: interface
+ name: em2
+ nm_controlled: true
diff --git a/os_net_config/impl_ifcfg.py b/os_net_config/impl_ifcfg.py
index 6d3c681..cf3b257 100644
--- a/os_net_config/impl_ifcfg.py
+++ b/os_net_config/impl_ifcfg.py
@@ -34,6 +34,13 @@ def ifcfg_config_path(name):
return "/etc/sysconfig/network-scripts/ifcfg-%s" % name
+def remove_ifcfg_config(ifname):
+ if re.match('[\w-]+$', ifname):
+ ifcfg_file = ifcfg_config_path(ifname)
+ if os.path.exists(ifcfg_file):
+ os.remove(ifcfg_file)
+
+
# NOTE(dprince): added here for testability
def bridge_config_path(name):
return ifcfg_config_path(name)
@@ -135,7 +142,10 @@ class IfcfgNetConfig(os_net_config.NetConfig):
data += "HOTPLUG=yes\n"
else:
data += "HOTPLUG=no\n"
- data += "NM_CONTROLLED=no\n"
+ if base_opt.nm_controlled:
+ data += "NM_CONTROLLED=yes\n"
+ else:
+ data += "NM_CONTROLLED=no\n"
if not base_opt.dns_servers and not base_opt.use_dhcp:
data += "PEERDNS=no\n"
if isinstance(base_opt, objects.Vlan):
@@ -587,6 +597,8 @@ class IfcfgNetConfig(os_net_config.NetConfig):
# Bind the dpdk interface
utils.bind_dpdk_interfaces(ifname, ovs_dpdk_port.driver, self.noop)
+ if not self.noop:
+ remove_ifcfg_config(ifname)
data = self._add_common(ovs_dpdk_port)
logger.debug('ovs dpdk port data: %s' % data)
@@ -605,6 +617,8 @@ class IfcfgNetConfig(os_net_config.NetConfig):
# checks are added at the object creation stage.
ifname = dpdk_port.members[0].name
utils.bind_dpdk_interfaces(ifname, dpdk_port.driver, self.noop)
+ if not self.noop:
+ remove_ifcfg_config(ifname)
data = self._add_common(ovs_dpdk_bond)
logger.debug('ovs dpdk bond data: %s' % data)
@@ -683,6 +697,7 @@ class IfcfgNetConfig(os_net_config.NetConfig):
nfvswitch_interfaces = [] # nfvswitch physical interfaces
nfvswitch_internal_ifaces = [] # nfvswitch internal/management ports
stop_dhclient_interfaces = []
+ ovs_needs_restart = False
for interface_name, iface_data in self.interface_data.items():
route_data = self.route_data.get(interface_name, '')
@@ -708,6 +723,11 @@ class IfcfgNetConfig(os_net_config.NetConfig):
update_files[route6_path] = route6_data
if "BOOTPROTO=dhcp" not in iface_data:
stop_dhclient_interfaces.append(interface_name)
+ # Openvswitch needs to be restarted when OVSDPDKPort or
+ # OVSDPDKBond is added
+ if "OVSDPDK" in iface_data:
+ ovs_needs_restart = True
+
else:
logger.info('No changes required for interface: %s' %
interface_name)
@@ -915,6 +935,16 @@ class IfcfgNetConfig(os_net_config.NetConfig):
for oldname, newname in self.renamed_interfaces.items():
self.ifrename(oldname, newname)
+ # DPDK initialization is done before running os-net-config, to make
+ # the DPDK ports available when enabled. DPDK Hotplug support is
+ # supported only in OvS 2.7 version. Until then, OvS needs to be
+ # restarted after adding a DPDK port. This change will be removed on
+ # migration to OvS 2.7 where DPDK Hotplug support is available.
+ if ovs_needs_restart:
+ msg = "Restart openvswitch"
+ self.execute(msg, '/usr/bin/systemctl',
+ 'restart', 'openvswitch')
+
for location, data in update_files.items():
self.write_config(location, data)
diff --git a/os_net_config/objects.py b/os_net_config/objects.py
index 741f304..7ff2750 100644
--- a/os_net_config/objects.py
+++ b/os_net_config/objects.py
@@ -181,7 +181,7 @@ class _BaseOpts(object):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
routes=None, mtu=None, primary=False, nic_mapping=None,
persist_mapping=False, defroute=True, dhclient_args=None,
- dns_servers=None):
+ dns_servers=None, nm_controlled=False):
addresses = addresses or []
routes = routes or []
dns_servers = dns_servers or []
@@ -209,6 +209,7 @@ class _BaseOpts(object):
self.defroute = defroute
self.dhclient_args = dhclient_args
self.dns_servers = dns_servers
+ self.nm_controlled = nm_controlled
self.bridge_name = None # internal
self.linux_bridge_name = None # internal
self.ivs_bridge_name = None # internal
@@ -244,6 +245,7 @@ class _BaseOpts(object):
mtu = json.get('mtu', None)
dhclient_args = json.get('dhclient_args')
dns_servers = json.get('dns_servers')
+ nm_controlled = json.get('nm_controlled')
primary = strutils.bool_from_string(str(json.get('primary', False)))
addresses = []
routes = []
@@ -274,11 +276,11 @@ class _BaseOpts(object):
if include_primary:
return (use_dhcp, use_dhcpv6, addresses, routes, mtu, primary,
nic_mapping, persist_mapping, defroute, dhclient_args,
- dns_servers)
+ dns_servers, nm_controlled)
else:
return (use_dhcp, use_dhcpv6, addresses, routes, mtu,
nic_mapping, persist_mapping, defroute, dhclient_args,
- dns_servers)
+ dns_servers, nm_controlled)
class Interface(_BaseOpts):
@@ -287,14 +289,16 @@ class Interface(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
routes=None, mtu=None, primary=False, nic_mapping=None,
persist_mapping=False, defroute=True, dhclient_args=None,
- dns_servers=None, ethtool_opts=None, hotplug=False):
+ dns_servers=None, nm_controlled=False, ethtool_opts=None,
+ hotplug=False):
addresses = addresses or []
routes = routes or []
dns_servers = dns_servers or []
super(Interface, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, primary, nic_mapping,
persist_mapping, defroute,
- dhclient_args, dns_servers)
+ dhclient_args, dns_servers,
+ nm_controlled)
self.ethtool_opts = ethtool_opts
self.hotplug = hotplug
@@ -318,7 +322,7 @@ class Vlan(_BaseOpts):
def __init__(self, device, vlan_id, use_dhcp=False, use_dhcpv6=False,
addresses=None, routes=None, mtu=None, primary=False,
nic_mapping=None, persist_mapping=False, defroute=True,
- dhclient_args=None, dns_servers=None):
+ dhclient_args=None, dns_servers=None, nm_controlled=False):
addresses = addresses or []
routes = routes or []
dns_servers = dns_servers or []
@@ -326,7 +330,7 @@ class Vlan(_BaseOpts):
super(Vlan, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, primary, nic_mapping,
persist_mapping, defroute, dhclient_args,
- dns_servers)
+ dns_servers, nm_controlled)
self.vlan_id = int(vlan_id)
mapped_nic_names = _mapped_nics(nic_mapping)
@@ -350,7 +354,7 @@ class IvsInterface(_BaseOpts):
def __init__(self, vlan_id, name='ivs', use_dhcp=False, use_dhcpv6=False,
addresses=None, routes=None, mtu=1500, primary=False,
nic_mapping=None, persist_mapping=False, defroute=True,
- dhclient_args=None, dns_servers=None):
+ dhclient_args=None, dns_servers=None, nm_controlled=False):
addresses = addresses or []
routes = routes or []
dns_servers = dns_servers or []
@@ -359,7 +363,7 @@ class IvsInterface(_BaseOpts):
addresses, routes, mtu, primary,
nic_mapping, persist_mapping,
defroute, dhclient_args,
- dns_servers)
+ dns_servers, nm_controlled)
self.vlan_id = int(vlan_id)
@staticmethod
@@ -376,7 +380,8 @@ class NfvswitchInternal(_BaseOpts):
def __init__(self, vlan_id, name='nfvswitch', use_dhcp=False,
use_dhcpv6=False, addresses=None, routes=None, mtu=1500,
primary=False, nic_mapping=None, persist_mapping=False,
- defroute=True, dhclient_args=None, dns_servers=None):
+ defroute=True, dhclient_args=None, dns_servers=None,
+ nm_controlled=False):
addresses = addresses or []
routes = routes or []
dns_servers = dns_servers or []
@@ -385,7 +390,8 @@ class NfvswitchInternal(_BaseOpts):
use_dhcpv6, addresses, routes,
mtu, primary, nic_mapping,
persist_mapping, defroute,
- dhclient_args, dns_servers)
+ dhclient_args, dns_servers,
+ nm_controlled)
self.vlan_id = int(vlan_id)
@staticmethod
@@ -403,7 +409,7 @@ class OvsBridge(_BaseOpts):
routes=None, mtu=None, members=None, ovs_options=None,
ovs_extra=None, nic_mapping=None, persist_mapping=False,
defroute=True, dhclient_args=None, dns_servers=None,
- fail_mode=None):
+ nm_controlled=False, fail_mode=None):
addresses = addresses or []
routes = routes or []
members = members or []
@@ -411,7 +417,8 @@ class OvsBridge(_BaseOpts):
super(OvsBridge, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, False, nic_mapping,
persist_mapping, defroute,
- dhclient_args, dns_servers)
+ dhclient_args, dns_servers,
+ nm_controlled)
self.members = members
self.ovs_options = ovs_options
ovs_extra = ovs_extra or []
@@ -436,7 +443,8 @@ class OvsBridge(_BaseOpts):
name = _get_required_field(json, 'name', 'OvsBridge')
(use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
persist_mapping, defroute,
- dhclient_args, dns_servers) = _BaseOpts.base_opts_from_json(
+ dhclient_args, dns_servers,
+ nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
ovs_options = json.get('ovs_options')
ovs_extra = json.get('ovs_extra')
@@ -459,7 +467,7 @@ class OvsBridge(_BaseOpts):
ovs_extra=ovs_extra, nic_mapping=nic_mapping,
persist_mapping=persist_mapping, defroute=defroute,
dhclient_args=dhclient_args, dns_servers=dns_servers,
- fail_mode=fail_mode)
+ nm_controlled=nm_controlled, fail_mode=fail_mode)
class OvsUserBridge(_BaseOpts):
@@ -469,12 +477,12 @@ class OvsUserBridge(_BaseOpts):
routes=None, mtu=None, members=None, ovs_options=None,
ovs_extra=None, nic_mapping=None, persist_mapping=False,
defroute=True, dhclient_args=None, dns_servers=None,
- fail_mode=None):
+ nm_controlled=False, fail_mode=None):
super(OvsUserBridge, self).__init__(name, use_dhcp, use_dhcpv6,
addresses, routes, mtu, False,
nic_mapping, persist_mapping,
defroute, dhclient_args,
- dns_servers)
+ dns_servers, nm_controlled)
self.members = members or []
self.ovs_options = ovs_options
ovs_extra = ovs_extra or []
@@ -501,7 +509,8 @@ class OvsUserBridge(_BaseOpts):
name = _get_required_field(json, 'name', 'OvsUserBridge')
(use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
persist_mapping, defroute,
- dhclient_args, dns_servers) = _BaseOpts.base_opts_from_json(
+ dhclient_args, dns_servers,
+ nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
ovs_options = json.get('ovs_options')
ovs_extra = json.get('ovs_extra')
@@ -524,7 +533,8 @@ class OvsUserBridge(_BaseOpts):
ovs_extra=ovs_extra, nic_mapping=nic_mapping,
persist_mapping=persist_mapping,
defroute=defroute, dhclient_args=dhclient_args,
- dns_servers=dns_servers, fail_mode=fail_mode)
+ dns_servers=dns_servers,
+ nm_controlled=nm_controlled, fail_mode=fail_mode)
class LinuxBridge(_BaseOpts):
@@ -533,7 +543,7 @@ class LinuxBridge(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
routes=None, mtu=None, members=None, nic_mapping=None,
persist_mapping=False, defroute=True, dhclient_args=None,
- dns_servers=None):
+ dns_servers=None, nm_controlled=False):
addresses = addresses or []
routes = routes or []
members = members or []
@@ -541,7 +551,8 @@ class LinuxBridge(_BaseOpts):
super(LinuxBridge, self).__init__(name, use_dhcp, use_dhcpv6,
addresses, routes, mtu, False,
nic_mapping, persist_mapping,
- defroute, dhclient_args, dns_servers)
+ defroute, dhclient_args, dns_servers,
+ nm_controlled)
self.members = members
for member in self.members:
member.linux_bridge_name = name
@@ -560,7 +571,7 @@ class LinuxBridge(_BaseOpts):
name = _get_required_field(json, 'name', 'LinuxBridge')
(use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
persist_mapping, defroute, dhclient_args,
- dns_servers) = _BaseOpts.base_opts_from_json(
+ dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
members = []
@@ -579,7 +590,8 @@ class LinuxBridge(_BaseOpts):
members=members, nic_mapping=nic_mapping,
persist_mapping=persist_mapping, defroute=defroute,
dhclient_args=dhclient_args,
- dns_servers=dns_servers)
+ dns_servers=dns_servers,
+ nm_controlled=nm_controlled)
class IvsBridge(_BaseOpts):
@@ -598,7 +610,7 @@ class IvsBridge(_BaseOpts):
def __init__(self, name='ivs', use_dhcp=False, use_dhcpv6=False,
addresses=None, routes=None, mtu=1500, members=None,
nic_mapping=None, persist_mapping=False, defroute=True,
- dhclient_args=None, dns_servers=None):
+ dhclient_args=None, dns_servers=None, nm_controlled=False):
addresses = addresses or []
routes = routes or []
members = members or []
@@ -606,7 +618,8 @@ class IvsBridge(_BaseOpts):
super(IvsBridge, self).__init__(name, use_dhcp, use_dhcpv6,
addresses, routes, mtu, False,
nic_mapping, persist_mapping,
- defroute, dhclient_args, dns_servers)
+ defroute, dhclient_args, dns_servers,
+ nm_controlled)
self.members = members
for member in self.members:
if isinstance(member, OvsBond) or isinstance(member, LinuxBond):
@@ -621,7 +634,7 @@ class IvsBridge(_BaseOpts):
name = 'ivs'
(use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
persist_mapping, defroute, dhclient_args,
- dns_servers) = _BaseOpts.base_opts_from_json(
+ dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
members = []
@@ -640,7 +653,7 @@ class IvsBridge(_BaseOpts):
members=members, nic_mapping=nic_mapping,
persist_mapping=persist_mapping, defroute=defroute,
dhclient_args=dhclient_args,
- dns_servers=dns_servers)
+ dns_servers=dns_servers, nm_controlled=nm_controlled)
class NfvswitchBridge(_BaseOpts):
@@ -654,7 +667,8 @@ class NfvswitchBridge(_BaseOpts):
def __init__(self, name='nfvswitch', use_dhcp=False, use_dhcpv6=False,
addresses=None, routes=None, mtu=1500, members=None,
nic_mapping=None, persist_mapping=False, defroute=True,
- dhclient_args=None, dns_servers=None, options=""):
+ dhclient_args=None, dns_servers=None, nm_controlled=False,
+ options=""):
addresses = addresses or []
routes = routes or []
members = members or []
@@ -663,7 +677,7 @@ class NfvswitchBridge(_BaseOpts):
addresses, routes, mtu, False,
nic_mapping, persist_mapping,
defroute, dhclient_args,
- dns_servers)
+ dns_servers, nm_controlled)
self.options = options
self.members = members
for member in self.members:
@@ -679,7 +693,7 @@ class NfvswitchBridge(_BaseOpts):
name = 'nfvswitch'
(use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
persist_mapping, defroute, dhclient_args,
- dns_servers) = _BaseOpts.base_opts_from_json(
+ dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
# members
@@ -703,7 +717,8 @@ class NfvswitchBridge(_BaseOpts):
members=members, nic_mapping=nic_mapping,
persist_mapping=persist_mapping,
defroute=defroute, dhclient_args=dhclient_args,
- dns_servers=dns_servers, options=options)
+ dns_servers=dns_servers,
+ nm_controlled=nm_controlled, options=options)
class LinuxTeam(_BaseOpts):
@@ -712,7 +727,8 @@ class LinuxTeam(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
routes=None, mtu=None, primary=False, members=None,
bonding_options=None, nic_mapping=None, persist_mapping=False,
- defroute=True, dhclient_args=None, dns_servers=None):
+ defroute=True, dhclient_args=None, dns_servers=None,
+ nm_controlled=False):
addresses = addresses or []
routes = routes or []
members = members or []
@@ -720,7 +736,8 @@ class LinuxTeam(_BaseOpts):
super(LinuxTeam, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, primary, nic_mapping,
persist_mapping, defroute,
- dhclient_args, dns_servers)
+ dhclient_args, dns_servers,
+ nm_controlled)
self.members = members
self.bonding_options = bonding_options
for member in self.members:
@@ -739,7 +756,7 @@ class LinuxTeam(_BaseOpts):
name = _get_required_field(json, 'name', 'LinuxTeam')
(use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
persist_mapping, defroute, dhclient_args,
- dns_servers) = _BaseOpts.base_opts_from_json(
+ dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
bonding_options = json.get('bonding_options')
members = []
@@ -759,7 +776,8 @@ class LinuxTeam(_BaseOpts):
members=members, bonding_options=bonding_options,
nic_mapping=nic_mapping,
persist_mapping=persist_mapping, defroute=defroute,
- dhclient_args=dhclient_args, dns_servers=dns_servers)
+ dhclient_args=dhclient_args, dns_servers=dns_servers,
+ nm_controlled=nm_controlled)
class LinuxBond(_BaseOpts):
@@ -768,7 +786,8 @@ class LinuxBond(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
routes=None, mtu=None, primary=False, members=None,
bonding_options=None, nic_mapping=None, persist_mapping=False,
- defroute=True, dhclient_args=None, dns_servers=None):
+ defroute=True, dhclient_args=None, dns_servers=None,
+ nm_controlled=False):
addresses = addresses or []
routes = routes or []
members = members or []
@@ -776,7 +795,8 @@ class LinuxBond(_BaseOpts):
super(LinuxBond, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, primary, nic_mapping,
persist_mapping, defroute,
- dhclient_args, dns_servers)
+ dhclient_args, dns_servers,
+ nm_controlled)
self.members = members
self.bonding_options = bonding_options
for member in self.members:
@@ -795,7 +815,7 @@ class LinuxBond(_BaseOpts):
name = _get_required_field(json, 'name', 'LinuxBond')
(use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
persist_mapping, defroute, dhclient_args,
- dns_servers) = _BaseOpts.base_opts_from_json(
+ dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
bonding_options = json.get('bonding_options')
members = []
@@ -815,7 +835,8 @@ class LinuxBond(_BaseOpts):
members=members, bonding_options=bonding_options,
nic_mapping=nic_mapping,
persist_mapping=persist_mapping, defroute=defroute,
- dhclient_args=dhclient_args, dns_servers=dns_servers)
+ dhclient_args=dhclient_args, dns_servers=dns_servers,
+ nm_controlled=nm_controlled)
class OvsBond(_BaseOpts):
@@ -825,7 +846,7 @@ class OvsBond(_BaseOpts):
routes=None, mtu=None, primary=False, members=None,
ovs_options=None, ovs_extra=None, nic_mapping=None,
persist_mapping=False, defroute=True, dhclient_args=None,
- dns_servers=None):
+ dns_servers=None, nm_controlled=False):
addresses = addresses or []
routes = routes or []
members = members or []
@@ -833,7 +854,7 @@ class OvsBond(_BaseOpts):
super(OvsBond, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, primary, nic_mapping,
persist_mapping, defroute, dhclient_args,
- dns_servers)
+ dns_servers, nm_controlled)
self.members = members
self.ovs_options = ovs_options
self.ovs_extra = format_ovs_extra(self, ovs_extra)
@@ -856,7 +877,7 @@ class OvsBond(_BaseOpts):
name = _get_required_field(json, 'name', 'OvsBond')
(use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
persist_mapping, defroute, dhclient_args,
- dns_servers) = _BaseOpts.base_opts_from_json(
+ dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
ovs_options = json.get('ovs_options')
ovs_extra = json.get('ovs_extra', [])
@@ -877,7 +898,8 @@ class OvsBond(_BaseOpts):
members=members, ovs_options=ovs_options,
ovs_extra=ovs_extra, nic_mapping=nic_mapping,
persist_mapping=persist_mapping, defroute=defroute,
- dhclient_args=dhclient_args, dns_servers=dns_servers)
+ dhclient_args=dhclient_args, dns_servers=dns_servers,
+ nm_controlled=nm_controlled)
class OvsTunnel(_BaseOpts):
@@ -886,15 +908,16 @@ class OvsTunnel(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
routes=None, mtu=None, primary=False, nic_mapping=None,
persist_mapping=False, defroute=True, dhclient_args=None,
- dns_servers=None, tunnel_type=None, ovs_options=None,
- ovs_extra=None):
+ dns_servers=None, nm_controlled=False, tunnel_type=None,
+ ovs_options=None, ovs_extra=None):
addresses = addresses or []
routes = routes or []
dns_servers = dns_servers or []
super(OvsTunnel, self).__init__(name, use_dhcp, use_dhcpv6, addresses,
routes, mtu, primary, nic_mapping,
persist_mapping, defroute,
- dhclient_args, dns_servers)
+ dhclient_args, dns_servers,
+ nm_controlled)
self.tunnel_type = tunnel_type
self.ovs_options = ovs_options or []
self.ovs_extra = format_ovs_extra(self, ovs_extra)
@@ -917,8 +940,8 @@ class OvsPatchPort(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
routes=None, mtu=None, primary=False, nic_mapping=None,
persist_mapping=False, defroute=True, dhclient_args=None,
- dns_servers=None, bridge_name=None, peer=None,
- ovs_options=None, ovs_extra=None):
+ dns_servers=None, nm_controlled=False, bridge_name=None,
+ peer=None, ovs_options=None, ovs_extra=None):
addresses = addresses or []
routes = routes or []
dns_servers = dns_servers or []
@@ -926,7 +949,7 @@ class OvsPatchPort(_BaseOpts):
addresses, routes, mtu, primary,
nic_mapping, persist_mapping,
defroute, dhclient_args,
- dns_servers)
+ dns_servers, nm_controlled)
self.bridge_name = bridge_name
self.peer = peer
self.ovs_options = ovs_options or []
@@ -951,14 +974,15 @@ class IbInterface(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
routes=None, mtu=None, primary=False, nic_mapping=None,
persist_mapping=False, defroute=True, dhclient_args=None,
- dns_servers=None, ethtool_opts=None):
+ dns_servers=None, nm_controlled=False, ethtool_opts=None):
addresses = addresses or []
routes = routes or []
dns_servers = dns_servers or []
super(IbInterface, self).__init__(name, use_dhcp, use_dhcpv6,
addresses, routes, mtu, primary,
nic_mapping, persist_mapping,
- defroute, dhclient_args, dns_servers)
+ defroute, dhclient_args, dns_servers,
+ nm_controlled)
self.ethtool_opts = ethtool_opts
@staticmethod
@@ -975,14 +999,14 @@ class OvsDpdkPort(_BaseOpts):
def __init__(self, name, use_dhcp=False, use_dhcpv6=False, addresses=None,
routes=None, mtu=None, primary=False, nic_mapping=None,
persist_mapping=False, defroute=True, dhclient_args=None,
- dns_servers=None, members=None, driver='vfio-pci',
- ovs_options=None, ovs_extra=None):
+ dns_servers=None, nm_controlled=False, members=None,
+ driver='vfio-pci', ovs_options=None, ovs_extra=None):
super(OvsDpdkPort, self).__init__(name, use_dhcp, use_dhcpv6,
addresses, routes, mtu, primary,
nic_mapping, persist_mapping,
defroute, dhclient_args,
- dns_servers)
+ dns_servers, nm_controlled)
self.members = members or []
self.ovs_options = ovs_options or []
self.ovs_extra = format_ovs_extra(self, ovs_extra)
@@ -1035,11 +1059,12 @@ class OvsDpdkBond(_BaseOpts):
routes=None, mtu=None, primary=False, members=None,
ovs_options=None, ovs_extra=None, nic_mapping=None,
persist_mapping=False, defroute=True, dhclient_args=None,
- dns_servers=None):
+ dns_servers=None, nm_controlled=False):
super(OvsDpdkBond, self).__init__(name, use_dhcp, use_dhcpv6,
addresses, routes, mtu, primary,
nic_mapping, persist_mapping,
- defroute, dhclient_args, dns_servers)
+ defroute, dhclient_args, dns_servers,
+ nm_controlled)
self.members = members or []
self.ovs_options = ovs_options
self.ovs_extra = format_ovs_extra(self, ovs_extra)
@@ -1063,7 +1088,7 @@ class OvsDpdkBond(_BaseOpts):
name = _get_required_field(json, 'name', 'OvsDpdkBond')
(use_dhcp, use_dhcpv6, addresses, routes, mtu, nic_mapping,
persist_mapping, defroute, dhclient_args,
- dns_servers) = _BaseOpts.base_opts_from_json(
+ dns_servers, nm_controlled) = _BaseOpts.base_opts_from_json(
json, include_primary=False)
ovs_options = json.get('ovs_options')
ovs_extra = json.get('ovs_extra', [])
@@ -1090,4 +1115,5 @@ class OvsDpdkBond(_BaseOpts):
ovs_extra=ovs_extra, nic_mapping=nic_mapping,
persist_mapping=persist_mapping,
defroute=defroute, dhclient_args=dhclient_args,
- dns_servers=dns_servers)
+ dns_servers=dns_servers,
+ nm_controlled=nm_controlled)
diff --git a/os_net_config/tests/test_impl_ifcfg.py b/os_net_config/tests/test_impl_ifcfg.py
index 9621b8c..82ca116 100644
--- a/os_net_config/tests/test_impl_ifcfg.py
+++ b/os_net_config/tests/test_impl_ifcfg.py
@@ -20,6 +20,7 @@ import tempfile
from oslo_concurrency import processutils
from os_net_config import impl_ifcfg
+from os_net_config import NetConfig
from os_net_config import objects
from os_net_config.tests import base
from os_net_config import utils
@@ -33,6 +34,14 @@ NM_CONTROLLED=no
PEERDNS=no
"""
+_BASE_IFCFG_NETWORKMANAGER = """# This file is autogenerated by os-net-config
+DEVICE=em1
+ONBOOT=yes
+HOTPLUG=no
+NM_CONTROLLED=yes
+PEERDNS=no
+"""
+
_HOTPLUG = """# This file is autogenerated by os-net-config
DEVICE=em1
ONBOOT=yes
@@ -152,6 +161,19 @@ OVSBOOTPROTO=dhcp
OVSDHCPINTERFACES="em1"
"""
+_NM_CONTROLLED_INTERFACE = _BASE_IFCFG_NETWORKMANAGER + """MASTER=bond1
+SLAVE=yes
+BOOTPROTO=none
+"""
+
+_NM_CONTROLLED_BOND = """# This file is autogenerated by os-net-config
+DEVICE=bond1
+ONBOOT=yes
+HOTPLUG=no
+NM_CONTROLLED=yes
+PEERDNS=no
+"""
+
_OVS_BRIDGE_DHCP_STANDALONE = _OVS_BRIDGE_DHCP + \
"OVS_EXTRA=\"set bridge br-ctlplane fail_mode=standalone\"\n"
@@ -844,6 +866,20 @@ DNS2=5.6.7.8
"""
self.assertEqual(em1_config, self.get_interface_config('em1'))
+ def test_nm_controlled(self):
+ interface1 = objects.Interface('em1', nm_controlled=True)
+ interface2 = objects.Interface('em2', nm_controlled=True)
+ bond = objects.LinuxBond('bond1', nm_controlled=True,
+ members=[interface1, interface2])
+ self.provider.add_linux_bond(bond)
+ self.provider.add_interface(interface1)
+ self.provider.add_interface(interface2)
+
+ ifcfg_data = self.get_interface_config('em1')
+ self.assertEqual(_NM_CONTROLLED_INTERFACE, ifcfg_data)
+ bond_data = self.get_linux_bond_config('bond1')
+ self.assertEqual(_NM_CONTROLLED_BOND, bond_data)
+
def test_network_ovs_dpdk_bridge_and_port(self):
nic_mapping = {'nic1': 'eth0', 'nic2': 'eth1', 'nic3': 'eth2'}
self.stubbed_mapped_nics = nic_mapping
@@ -923,6 +959,7 @@ class TestIfcfgNetConfigApply(base.TestCase):
def setUp(self):
super(TestIfcfgNetConfigApply, self).setUp()
self.temp_ifcfg_file = tempfile.NamedTemporaryFile()
+ self.temp_bond_file = tempfile.NamedTemporaryFile()
self.temp_route_file = tempfile.NamedTemporaryFile()
self.temp_route6_file = tempfile.NamedTemporaryFile()
self.temp_bridge_file = tempfile.NamedTemporaryFile()
@@ -935,6 +972,13 @@ class TestIfcfgNetConfigApply(base.TestCase):
return self.temp_ifcfg_file.name
self.stubs.Set(impl_ifcfg, 'ifcfg_config_path', test_ifcfg_path)
+ def test_remove_ifcfg_config(name):
+ ifcfg_file = self.temp_ifcfg_file.name
+ if os.path.exists(ifcfg_file):
+ os.remove(ifcfg_file)
+ self.stubs.Set(impl_ifcfg, 'remove_ifcfg_config',
+ test_remove_ifcfg_config)
+
def test_routes_path(name):
return self.temp_route_file.name
self.stubs.Set(impl_ifcfg, 'route_config_path', test_routes_path)
@@ -1157,3 +1201,32 @@ class TestIfcfgNetConfigApply(base.TestCase):
self.provider.apply(cleanup=True)
self.assertTrue(os.path.exists(tmp_lo_file))
os.remove(tmp_lo_file)
+
+ def test_ovs_restart_called(self):
+ interface = objects.Interface('em1')
+ dpdk_port = objects.OvsDpdkPort('dpdk0', members=[interface])
+ execute_strings = []
+
+ def test_execute(*args, **kwargs):
+ execute_strings.append(args[1])
+ pass
+ self.stubs.Set(NetConfig, 'execute', test_execute)
+
+ self.provider.noop = True
+ self.provider.add_ovs_dpdk_port(dpdk_port)
+ self.provider.apply()
+ self.assertIn('Restart openvswitch', execute_strings)
+
+ def test_ovs_restart_not_called(self):
+ interface = objects.Interface('em1')
+ execute_strings = []
+
+ def test_execute(*args, **kwargs):
+ execute_strings.append(args[1])
+ pass
+ self.stubs.Set(NetConfig, 'execute', test_execute)
+
+ self.provider.noop = True
+ self.provider.add_interface(interface)
+ self.provider.apply()
+ self.assertNotIn('Restart openvswitch', execute_strings)