← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~larsks/cloud-init:bz/1542578 into cloud-init:master

 

Lars Kellogg-Stedman has proposed merging ~larsks/cloud-init:bz/1542578 into cloud-init:master.

Commit message:
cc_mounts: do not add devices to fstab that are already configured
    
do not add new entries to /etc/fstab for devices that already have an
existing fstab entry.

Resolves: rhbz#1542578


Requested reviews:
  cloud-init commiters (cloud-init-dev)

For more details, see:
https://code.launchpad.net/~larsks/cloud-init/+git/cloud-init/+merge/345113

We had a customer who was booting images in OpenStack that had a pre-configured swap partition. Cloud-init was adding a second entry for the same partition. This commit resolves the problem by parsing device names from /etc/fstab and declining to generate new entries for devices that already exist.

As with the existing code, entries with the "comment=cloudconfig" option will be removed and potentially replaced.
-- 
Your team cloud-init commiters is requested to review the proposed merge of ~larsks/cloud-init:bz/1542578 into cloud-init:master.
diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py
index f14a4fc..c0d5029 100644
--- a/cloudinit/config/cc_mounts.py
+++ b/cloudinit/config/cc_mounts.py
@@ -327,6 +327,22 @@ def handle(_name, cfg, cloud, log, _args):
 
     LOG.debug("mounts configuration is %s", cfgmnt)
 
+    fstab_lines = []
+    fstab_devs = {}
+    fstab_removed = []
+    comment = "comment=cloudconfig"
+
+    for line in util.load_file(FSTAB_PATH).splitlines():
+        try:
+            toks = WS.split(line)
+            if toks[3].find(comment) != -1:
+                fstab_removed.append(line)
+                continue
+        except Exception:
+            pass
+        fstab_devs[toks[0]] = line
+        fstab_lines.append(line)
+
     for i in range(len(cfgmnt)):
         # skip something that wasn't a list
         if not isinstance(cfgmnt[i], list):
@@ -336,12 +352,17 @@ def handle(_name, cfg, cloud, log, _args):
 
         start = str(cfgmnt[i][0])
         sanitized = sanitize_devname(start, cloud.device_name_to_device, log)
+        if sanitized != start:
+            log.debug("changed %s => %s" % (start, sanitized))
+
         if sanitized is None:
-            log.debug("Ignorming nonexistant named mount %s", start)
+            log.debug("Ignoring nonexistant named mount %s", start)
+            continue
+        elif sanitized in fstab_devs:
+            log.warn("Device %s already defined in fstab: %s",
+                     sanitized, fstab_devs[sanitized])
             continue
 
-        if sanitized != start:
-            log.debug("changed %s => %s" % (start, sanitized))
         cfgmnt[i][0] = sanitized
 
         # in case the user did not quote a field (likely fs-freq, fs_passno)
@@ -373,11 +394,17 @@ def handle(_name, cfg, cloud, log, _args):
     for defmnt in defmnts:
         start = defmnt[0]
         sanitized = sanitize_devname(start, cloud.device_name_to_device, log)
+        if sanitized != start:
+            log.debug("changed default device %s => %s" % (start, sanitized))
+
         if sanitized is None:
             log.debug("Ignoring nonexistant default named mount %s", start)
             continue
-        if sanitized != start:
-            log.debug("changed default device %s => %s" % (start, sanitized))
+        elif sanitized in fstab_devs:
+            log.warn("Device %s already defined in fstab: %s",
+                     sanitized, fstab_devs[sanitized])
+            continue
+
         defmnt[0] = sanitized
 
         cfgmnt_has = False
@@ -409,7 +436,6 @@ def handle(_name, cfg, cloud, log, _args):
         log.debug("No modifications to fstab needed.")
         return
 
-    comment = "comment=cloudconfig"
     cc_lines = []
     needswap = False
     dirs = []
@@ -422,18 +448,6 @@ def handle(_name, cfg, cloud, log, _args):
             dirs.append(line[1])
         cc_lines.append('\t'.join(line))
 
-    fstab_lines = []
-    removed = []
-    for line in util.load_file(FSTAB_PATH).splitlines():
-        try:
-            toks = WS.split(line)
-            if toks[3].find(comment) != -1:
-                removed.append(line)
-                continue
-        except Exception:
-            pass
-        fstab_lines.append(line)
-
     for d in dirs:
         try:
             util.ensure_dir(d)
@@ -441,7 +455,7 @@ def handle(_name, cfg, cloud, log, _args):
             util.logexc(log, "Failed to make '%s' config-mount", d)
 
     sadds = [WS.sub(" ", n) for n in cc_lines]
-    sdrops = [WS.sub(" ", n) for n in removed]
+    sdrops = [WS.sub(" ", n) for n in fstab_removed]
 
     sops = (["- " + drop for drop in sdrops if drop not in sadds] +
             ["+ " + add for add in sadds if add not in sdrops])

Follow ups