sailesh1993 / rpms / cloud-init

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