|
|
222d62 |
From 09b873ca69821ac2a3e306da0af0437b849d1dd8 Mon Sep 17 00:00:00 2001
|
|
|
222d62 |
From: Eduardo Otubo <otubo@redhat.com>
|
|
|
222d62 |
Date: Fri, 18 Jan 2019 16:55:36 +0100
|
|
|
222d62 |
Subject: [PATCH] net: Make sysconfig renderer compatible with Network Manager.
|
|
|
222d62 |
|
|
|
222d62 |
RH-Author: Eduardo Otubo <otubo@redhat.com>
|
|
|
222d62 |
Message-id: <20190118165536.25963-1-otubo@redhat.com>
|
|
|
222d62 |
Patchwork-id: 84052
|
|
|
222d62 |
O-Subject: [RHEL-8.0 cloud-init PATCH] net: Make sysconfig renderer compatible with Network Manager.
|
|
|
222d62 |
Bugzilla: 1602784
|
|
|
222d62 |
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
|
|
222d62 |
RH-Acked-by: Mohammed Gamal <mgamal@redhat.com>
|
|
|
222d62 |
|
|
|
222d62 |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1602784
|
|
|
222d62 |
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=19877292
|
|
|
222d62 |
Tested by: upstream maintainers and me
|
|
|
222d62 |
|
|
|
222d62 |
commit 3861102fcaf47a882516d8b6daab518308eb3086
|
|
|
222d62 |
Author: Eduardo Otubo <otubo@redhat.com>
|
|
|
222d62 |
Date: Fri Jan 18 15:36:19 2019 +0000
|
|
|
222d62 |
|
|
|
222d62 |
net: Make sysconfig renderer compatible with Network Manager.
|
|
|
222d62 |
|
|
|
222d62 |
The 'sysconfig' renderer is activated if, and only if, there's ifup and
|
|
|
222d62 |
ifdown commands present in its search dictonary or the network-scripts
|
|
|
222d62 |
configuration files are found. This patch adds a check for Network-
|
|
|
222d62 |
Manager configuration file as well.
|
|
|
222d62 |
|
|
|
222d62 |
This solution is based on the use of the plugin 'ifcfg-rh' present in
|
|
|
222d62 |
Network-Manager and is designed to support Fedora 29 or other
|
|
|
222d62 |
distributions that also replaced network-scripts by Network-Manager.
|
|
|
222d62 |
|
|
|
222d62 |
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
|
|
|
222d62 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
222d62 |
---
|
|
|
222d62 |
cloudinit/net/sysconfig.py | 36 +++++++++++++++++++++++
|
|
|
222d62 |
tests/unittests/test_net.py | 71 +++++++++++++++++++++++++++++++++++++++++++++
|
|
|
222d62 |
2 files changed, 107 insertions(+)
|
|
|
222d62 |
|
|
|
222d62 |
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
|
|
|
222d62 |
index bd81832..42291aa 100644
|
|
|
222d62 |
--- a/cloudinit/net/sysconfig.py
|
|
|
222d62 |
+++ b/cloudinit/net/sysconfig.py
|
|
|
222d62 |
@@ -10,11 +10,14 @@ from cloudinit.distros.parsers import resolv_conf
|
|
|
222d62 |
from cloudinit import log as logging
|
|
|
222d62 |
from cloudinit import util
|
|
|
222d62 |
|
|
|
222d62 |
+from configobj import ConfigObj
|
|
|
222d62 |
+
|
|
|
222d62 |
from . import renderer
|
|
|
222d62 |
from .network_state import (
|
|
|
222d62 |
is_ipv6_addr, net_prefix_to_ipv4_mask, subnet_is_ipv6)
|
|
|
222d62 |
|
|
|
222d62 |
LOG = logging.getLogger(__name__)
|
|
|
222d62 |
+NM_CFG_FILE = "/etc/NetworkManager/NetworkManager.conf"
|
|
|
222d62 |
|
|
|
222d62 |
|
|
|
222d62 |
def _make_header(sep='#'):
|
|
|
222d62 |
@@ -46,6 +49,24 @@ def _quote_value(value):
|
|
|
222d62 |
return value
|
|
|
222d62 |
|
|
|
222d62 |
|
|
|
222d62 |
+def enable_ifcfg_rh(path):
|
|
|
222d62 |
+ """Add ifcfg-rh to NetworkManager.cfg plugins if main section is present"""
|
|
|
222d62 |
+ config = ConfigObj(path)
|
|
|
222d62 |
+ if 'main' in config:
|
|
|
222d62 |
+ if 'plugins' in config['main']:
|
|
|
222d62 |
+ if 'ifcfg-rh' in config['main']['plugins']:
|
|
|
222d62 |
+ return
|
|
|
222d62 |
+ else:
|
|
|
222d62 |
+ config['main']['plugins'] = []
|
|
|
222d62 |
+
|
|
|
222d62 |
+ if isinstance(config['main']['plugins'], list):
|
|
|
222d62 |
+ config['main']['plugins'].append('ifcfg-rh')
|
|
|
222d62 |
+ else:
|
|
|
222d62 |
+ config['main']['plugins'] = [config['main']['plugins'], 'ifcfg-rh']
|
|
|
222d62 |
+ config.write()
|
|
|
222d62 |
+ LOG.debug('Enabled ifcfg-rh NetworkManager plugins')
|
|
|
222d62 |
+
|
|
|
222d62 |
+
|
|
|
222d62 |
class ConfigMap(object):
|
|
|
222d62 |
"""Sysconfig like dictionary object."""
|
|
|
222d62 |
|
|
|
222d62 |
@@ -597,6 +618,8 @@ class Renderer(renderer.Renderer):
|
|
|
222d62 |
netrules_content = self._render_persistent_net(network_state)
|
|
|
222d62 |
netrules_path = util.target_path(target, self.netrules_path)
|
|
|
222d62 |
util.write_file(netrules_path, netrules_content, file_mode)
|
|
|
222d62 |
+ if available_nm(target=target):
|
|
|
222d62 |
+ enable_ifcfg_rh(util.target_path(target, path=NM_CFG_FILE))
|
|
|
222d62 |
|
|
|
222d62 |
# always write /etc/sysconfig/network configuration
|
|
|
222d62 |
sysconfig_path = util.target_path(target, "etc/sysconfig/network")
|
|
|
222d62 |
@@ -608,6 +631,13 @@ class Renderer(renderer.Renderer):
|
|
|
222d62 |
|
|
|
222d62 |
|
|
|
222d62 |
def available(target=None):
|
|
|
222d62 |
+ sysconfig = available_sysconfig(target=target)
|
|
|
222d62 |
+ nm = available_nm(target=target)
|
|
|
222d62 |
+
|
|
|
222d62 |
+ return any([nm, sysconfig])
|
|
|
222d62 |
+
|
|
|
222d62 |
+
|
|
|
222d62 |
+def available_sysconfig(target=None):
|
|
|
222d62 |
expected = ['ifup', 'ifdown']
|
|
|
222d62 |
search = ['/sbin', '/usr/sbin']
|
|
|
222d62 |
for p in expected:
|
|
|
222d62 |
@@ -623,4 +653,10 @@ def available(target=None):
|
|
|
222d62 |
return True
|
|
|
222d62 |
|
|
|
222d62 |
|
|
|
222d62 |
+def available_nm(target=None):
|
|
|
222d62 |
+ if not os.path.isfile(util.target_path(target, path=NM_CFG_FILE)):
|
|
|
222d62 |
+ return False
|
|
|
222d62 |
+ return True
|
|
|
222d62 |
+
|
|
|
222d62 |
+
|
|
|
222d62 |
# vi: ts=4 expandtab
|
|
|
222d62 |
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
|
|
|
222d62 |
index 9cf41bc..8e520f6 100644
|
|
|
222d62 |
--- a/tests/unittests/test_net.py
|
|
|
222d62 |
+++ b/tests/unittests/test_net.py
|
|
|
222d62 |
@@ -24,6 +24,7 @@ import os
|
|
|
222d62 |
import textwrap
|
|
|
222d62 |
import yaml
|
|
|
222d62 |
|
|
|
222d62 |
+
|
|
|
222d62 |
DHCP_CONTENT_1 = """
|
|
|
222d62 |
DEVICE='eth0'
|
|
|
222d62 |
PROTO='dhcp'
|
|
|
222d62 |
@@ -1542,6 +1543,7 @@ iface eth1 inet dhcp
|
|
|
222d62 |
|
|
|
222d62 |
class TestSysConfigRendering(CiTestCase):
|
|
|
222d62 |
|
|
|
222d62 |
+ nm_cfg_file = "/etc/NetworkManager/NetworkManager.conf"
|
|
|
222d62 |
scripts_dir = '/etc/sysconfig/network-scripts'
|
|
|
222d62 |
header = ('# Created by cloud-init on instance boot automatically, '
|
|
|
222d62 |
'do not edit.\n#\n')
|
|
|
222d62 |
@@ -1853,6 +1855,75 @@ iface eth0 inet dhcp
|
|
|
222d62 |
self.assertEqual(
|
|
|
222d62 |
expected, dir2dict(tmp_dir)['/etc/network/interfaces'])
|
|
|
222d62 |
|
|
|
222d62 |
+ def test_check_ifcfg_rh(self):
|
|
|
222d62 |
+ """ifcfg-rh plugin is added NetworkManager.conf if conf present."""
|
|
|
222d62 |
+ render_dir = self.tmp_dir()
|
|
|
222d62 |
+ nm_cfg = util.target_path(render_dir, path=self.nm_cfg_file)
|
|
|
222d62 |
+ util.ensure_dir(os.path.dirname(nm_cfg))
|
|
|
222d62 |
+
|
|
|
222d62 |
+ # write a template nm.conf, note plugins is a list here
|
|
|
222d62 |
+ with open(nm_cfg, 'w') as fh:
|
|
|
222d62 |
+ fh.write('# test_check_ifcfg_rh\n[main]\nplugins=foo,bar\n')
|
|
|
222d62 |
+ self.assertTrue(os.path.exists(nm_cfg))
|
|
|
222d62 |
+
|
|
|
222d62 |
+ # render and read
|
|
|
222d62 |
+ entry = NETWORK_CONFIGS['small']
|
|
|
222d62 |
+ found = self._render_and_read(network_config=yaml.load(entry['yaml']),
|
|
|
222d62 |
+ dir=render_dir)
|
|
|
222d62 |
+ self._compare_files_to_expected(entry[self.expected_name], found)
|
|
|
222d62 |
+ self._assert_headers(found)
|
|
|
222d62 |
+
|
|
|
222d62 |
+ # check ifcfg-rh is in the 'plugins' list
|
|
|
222d62 |
+ config = sysconfig.ConfigObj(nm_cfg)
|
|
|
222d62 |
+ self.assertIn('ifcfg-rh', config['main']['plugins'])
|
|
|
222d62 |
+
|
|
|
222d62 |
+ def test_check_ifcfg_rh_plugins_string(self):
|
|
|
222d62 |
+ """ifcfg-rh plugin is append when plugins is a string."""
|
|
|
222d62 |
+ render_dir = self.tmp_path("render")
|
|
|
222d62 |
+ os.makedirs(render_dir)
|
|
|
222d62 |
+ nm_cfg = util.target_path(render_dir, path=self.nm_cfg_file)
|
|
|
222d62 |
+ util.ensure_dir(os.path.dirname(nm_cfg))
|
|
|
222d62 |
+
|
|
|
222d62 |
+ # write a template nm.conf, note plugins is a value here
|
|
|
222d62 |
+ util.write_file(nm_cfg, '# test_check_ifcfg_rh\n[main]\nplugins=foo\n')
|
|
|
222d62 |
+
|
|
|
222d62 |
+ # render and read
|
|
|
222d62 |
+ entry = NETWORK_CONFIGS['small']
|
|
|
222d62 |
+ found = self._render_and_read(network_config=yaml.load(entry['yaml']),
|
|
|
222d62 |
+ dir=render_dir)
|
|
|
222d62 |
+ self._compare_files_to_expected(entry[self.expected_name], found)
|
|
|
222d62 |
+ self._assert_headers(found)
|
|
|
222d62 |
+
|
|
|
222d62 |
+ # check raw content has plugin
|
|
|
222d62 |
+ nm_file_content = util.load_file(nm_cfg)
|
|
|
222d62 |
+ self.assertIn('ifcfg-rh', nm_file_content)
|
|
|
222d62 |
+
|
|
|
222d62 |
+ # check ifcfg-rh is in the 'plugins' list
|
|
|
222d62 |
+ config = sysconfig.ConfigObj(nm_cfg)
|
|
|
222d62 |
+ self.assertIn('ifcfg-rh', config['main']['plugins'])
|
|
|
222d62 |
+
|
|
|
222d62 |
+ def test_check_ifcfg_rh_plugins_no_plugins(self):
|
|
|
222d62 |
+ """enable_ifcfg_plugin creates plugins value if missing."""
|
|
|
222d62 |
+ render_dir = self.tmp_path("render")
|
|
|
222d62 |
+ os.makedirs(render_dir)
|
|
|
222d62 |
+ nm_cfg = util.target_path(render_dir, path=self.nm_cfg_file)
|
|
|
222d62 |
+ util.ensure_dir(os.path.dirname(nm_cfg))
|
|
|
222d62 |
+
|
|
|
222d62 |
+ # write a template nm.conf, note plugins is missing
|
|
|
222d62 |
+ util.write_file(nm_cfg, '# test_check_ifcfg_rh\n[main]\n')
|
|
|
222d62 |
+ self.assertTrue(os.path.exists(nm_cfg))
|
|
|
222d62 |
+
|
|
|
222d62 |
+ # render and read
|
|
|
222d62 |
+ entry = NETWORK_CONFIGS['small']
|
|
|
222d62 |
+ found = self._render_and_read(network_config=yaml.load(entry['yaml']),
|
|
|
222d62 |
+ dir=render_dir)
|
|
|
222d62 |
+ self._compare_files_to_expected(entry[self.expected_name], found)
|
|
|
222d62 |
+ self._assert_headers(found)
|
|
|
222d62 |
+
|
|
|
222d62 |
+ # check ifcfg-rh is in the 'plugins' list
|
|
|
222d62 |
+ config = sysconfig.ConfigObj(nm_cfg)
|
|
|
222d62 |
+ self.assertIn('ifcfg-rh', config['main']['plugins'])
|
|
|
222d62 |
+
|
|
|
222d62 |
|
|
|
222d62 |
class TestNetplanNetRendering(CiTestCase):
|
|
|
222d62 |
|
|
|
222d62 |
--
|
|
|
222d62 |
1.8.3.1
|
|
|
222d62 |
|