sailesh1993 / rpms / cloud-init

Forked from rpms/cloud-init 10 months ago
Clone
c1c26e
From 2604984fc44dde89dac847de9f95011713d448ff Mon Sep 17 00:00:00 2001
c1c26e
From: Eduardo Otubo <otubo@redhat.com>
c1c26e
Date: Wed, 29 May 2019 13:41:49 +0200
c1c26e
Subject: [PATCH 5/5] cc_mounts: check if mount -a on no-change fstab path
c1c26e
c1c26e
RH-Author: Eduardo Otubo <otubo@redhat.com>
c1c26e
Message-id: <20190529134149.842-6-otubo@redhat.com>
c1c26e
Patchwork-id: 88269
c1c26e
O-Subject: [RHEL-8.0.1/RHEL-8.1.0 cloud-init PATCHv2 5/5] cc_mounts: check if mount -a on no-change fstab path
c1c26e
Bugzilla: 1691986
c1c26e
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
c1c26e
RH-Acked-by: Cathy Avery <cavery@redhat.com>
c1c26e
c1c26e
From: "Jason Zions (MSFT)" <jasonzio@microsoft.com>
c1c26e
commit acc25d8d7d603313059ac35b4253b504efc560a9
c1c26e
Author: Jason Zions (MSFT) <jasonzio@microsoft.com>
c1c26e
Date:   Wed May 8 22:47:07 2019 +0000
c1c26e
c1c26e
    cc_mounts: check if mount -a on no-change fstab path
c1c26e
c1c26e
    Under some circumstances, cc_disk_setup may reformat volumes which
c1c26e
    already appear in /etc/fstab (e.g. Azure ephemeral drive is reformatted
c1c26e
    from NTFS to ext4 after service-heal). Normally, cc_mounts only calls
c1c26e
    mount -a if it altered /etc/fstab. With this change cc_mounts will read
c1c26e
    /proc/mounts and verify if configured mounts are already mounted and if
c1c26e
    not raise flag to request a mount -a.  This handles the case where no
c1c26e
    changes to fstab occur but a mount -a is required due to change in
c1c26e
    underlying device which prevented the .mount unit from running until
c1c26e
    after disk was reformatted.
c1c26e
c1c26e
    LP: #1825596
c1c26e
c1c26e
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
c1c26e
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
c1c26e
---
c1c26e
 cloudinit/config/cc_mounts.py                      | 11 ++++++++
c1c26e
 .../unittests/test_handler/test_handler_mounts.py  | 30 +++++++++++++++++++++-
c1c26e
 2 files changed, 40 insertions(+), 1 deletion(-)
c1c26e
c1c26e
diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py
c1c26e
index 339baba..123ffb8 100644
c1c26e
--- a/cloudinit/config/cc_mounts.py
c1c26e
+++ b/cloudinit/config/cc_mounts.py
c1c26e
@@ -439,6 +439,7 @@ def handle(_name, cfg, cloud, log, _args):
c1c26e
 
c1c26e
     cc_lines = []
c1c26e
     needswap = False
c1c26e
+    need_mount_all = False
c1c26e
     dirs = []
c1c26e
     for line in actlist:
c1c26e
         # write 'comment' in the fs_mntops, entry,  claiming this
c1c26e
@@ -449,11 +450,18 @@ def handle(_name, cfg, cloud, log, _args):
c1c26e
             dirs.append(line[1])
c1c26e
         cc_lines.append('\t'.join(line))
c1c26e
 
c1c26e
+    mount_points = [v['mountpoint'] for k, v in util.mounts().items()
c1c26e
+                    if 'mountpoint' in v]
c1c26e
     for d in dirs:
c1c26e
         try:
c1c26e
             util.ensure_dir(d)
c1c26e
         except Exception:
c1c26e
             util.logexc(log, "Failed to make '%s' config-mount", d)
c1c26e
+        # dirs is list of directories on which a volume should be mounted.
c1c26e
+        # If any of them does not already show up in the list of current
c1c26e
+        # mount points, we will definitely need to do mount -a.
c1c26e
+        if not need_mount_all and d not in mount_points:
c1c26e
+            need_mount_all = True
c1c26e
 
c1c26e
     sadds = [WS.sub(" ", n) for n in cc_lines]
c1c26e
     sdrops = [WS.sub(" ", n) for n in fstab_removed]
c1c26e
@@ -473,6 +481,9 @@ def handle(_name, cfg, cloud, log, _args):
c1c26e
         log.debug("No changes to /etc/fstab made.")
c1c26e
     else:
c1c26e
         log.debug("Changes to fstab: %s", sops)
c1c26e
+        need_mount_all = True
c1c26e
+
c1c26e
+    if need_mount_all:
c1c26e
         activate_cmds.append(["mount", "-a"])
c1c26e
         if uses_systemd:
c1c26e
             activate_cmds.append(["systemctl", "daemon-reload"])
c1c26e
diff --git a/tests/unittests/test_handler/test_handler_mounts.py b/tests/unittests/test_handler/test_handler_mounts.py
c1c26e
index 8fea6c2..0fb160b 100644
c1c26e
--- a/tests/unittests/test_handler/test_handler_mounts.py
c1c26e
+++ b/tests/unittests/test_handler/test_handler_mounts.py
c1c26e
@@ -154,7 +154,15 @@ class TestFstabHandling(test_helpers.FilesystemMockingTestCase):
c1c26e
                        return_value=True)
c1c26e
 
c1c26e
         self.add_patch('cloudinit.config.cc_mounts.util.subp',
c1c26e
-                       'mock_util_subp')
c1c26e
+                       'm_util_subp')
c1c26e
+
c1c26e
+        self.add_patch('cloudinit.config.cc_mounts.util.mounts',
c1c26e
+                       'mock_util_mounts',
c1c26e
+                       return_value={
c1c26e
+                           '/dev/sda1': {'fstype': 'ext4',
c1c26e
+                                         'mountpoint': '/',
c1c26e
+                                         'opts': 'rw,relatime,discard'
c1c26e
+                                         }})
c1c26e
 
c1c26e
         self.mock_cloud = mock.Mock()
c1c26e
         self.mock_log = mock.Mock()
c1c26e
@@ -230,4 +238,24 @@ class TestFstabHandling(test_helpers.FilesystemMockingTestCase):
c1c26e
             fstab_new_content = fd.read()
c1c26e
             self.assertEqual(fstab_expected_content, fstab_new_content)
c1c26e
 
c1c26e
+    def test_no_change_fstab_sets_needs_mount_all(self):
c1c26e
+        '''verify unchanged fstab entries are mounted if not call mount -a'''
c1c26e
+        fstab_original_content = (
c1c26e
+            'LABEL=cloudimg-rootfs / ext4 defaults 0 0\n'
c1c26e
+            'LABEL=UEFI /boot/efi vfat defaults 0 0\n'
c1c26e
+            '/dev/vdb /mnt auto defaults,noexec,comment=cloudconfig 0 2\n'
c1c26e
+        )
c1c26e
+        fstab_expected_content = fstab_original_content
c1c26e
+        cc = {'mounts': [
c1c26e
+                 ['/dev/vdb', '/mnt', 'auto', 'defaults,noexec']]}
c1c26e
+        with open(cc_mounts.FSTAB_PATH, 'w') as fd:
c1c26e
+            fd.write(fstab_original_content)
c1c26e
+        with open(cc_mounts.FSTAB_PATH, 'r') as fd:
c1c26e
+            fstab_new_content = fd.read()
c1c26e
+            self.assertEqual(fstab_expected_content, fstab_new_content)
c1c26e
+        cc_mounts.handle(None, cc, self.mock_cloud, self.mock_log, [])
c1c26e
+        self.m_util_subp.assert_has_calls([
c1c26e
+            mock.call(['mount', '-a']),
c1c26e
+            mock.call(['systemctl', 'daemon-reload'])])
c1c26e
+
c1c26e
 # vi: ts=4 expandtab
c1c26e
-- 
c1c26e
1.8.3.1
c1c26e