فهرست منبع

Add support for mounting LVM volumes defined in /etc/fstab during OSMount.

Nashwan Azhari 7 سال پیش
والد
کامیت
e01fe86812
1فایلهای تغییر یافته به همراه49 افزوده شده و 11 حذف شده
  1. 49 11
      coriolis/osmorphing/osmount/base.py

+ 49 - 11
coriolis/osmorphing/osmount/base.py

@@ -2,9 +2,10 @@
 # All Rights Reserved.
 # All Rights Reserved.
 
 
 import abc
 import abc
+import base64
+import json
 import os
 import os
 import re
 import re
-import base64
 
 
 from oslo_log import log as logging
 from oslo_log import log as logging
 import paramiko
 import paramiko
@@ -120,8 +121,36 @@ class BaseLinuxOSMountTools(BaseSSHOSMountTools):
                 vg_names.append(m.groups()[0])
                 vg_names.append(m.groups()[0])
         return vg_names
         return vg_names
 
 
+    def _get_lv_paths(self):
+        """ Returns list with paths of available LVM volumes. """
+        lvm_paths = []
+        out = json.loads(
+            self._exec_cmd(
+                "sudo lvs -o lv_path,lv_name --report-format json").decode())
+        LOG.debug("Decoded `lvs` output data: %s", out)
+
+        reports = out.get("report", [])
+        if not reports:
+            return []
+
+        if len(reports) > 1:
+            LOG.warn("Multiple LVM reports found: %s", reports)
+        report = reports[0]
+
+        for i, lvm in enumerate(report.get("lv", [])):
+            lvm_name = lvm.get("lv_name", str(i))
+            lvm_path = lvm.get("lv_path")
+            if not lvm_path:
+                LOG.warn("No path for lvm volume '%s'", lvm_name)
+            else:
+                lvm_paths.append(lvm_path)
+
+        LOG.debug("Found LVM device paths: %s", lvm_paths)
+        return lvm_paths
+
     def _check_mount_fstab_partitions(
     def _check_mount_fstab_partitions(
-            self, os_root_dir, skip_mounts=["/"], skip_filesystems=["swap"]):
+            self, os_root_dir, skip_mounts=["/"], skip_filesystems=["swap"],
+            mountable_lvm_devs=None):
         """ Reads the contents of /etc/fstab from the VM's root directory and
         """ Reads the contents of /etc/fstab from the VM's root directory and
         tries to mount all clearly identified (by UUID or path) filesystems.
         tries to mount all clearly identified (by UUID or path) filesystems.
         Returns the list of the new directories which were mounted.
         Returns the list of the new directories which were mounted.
@@ -129,6 +158,8 @@ class BaseLinuxOSMountTools(BaseSSHOSMountTools):
         chroot) to not try to mount.
         chroot) to not try to mount.
         param: skip_filesystems: list(str()): list of filesystem types to skip
         param: skip_filesystems: list(str()): list of filesystem types to skip
         mounting entirely
         mounting entirely
+        param: mountable_lvm_devs: list(str()): list of LVM device paths which
+        exist and are mountable should they appear in /etc/fstab
         """
         """
         new_mountpoints = []
         new_mountpoints = []
         etc_fstab_path = os.path.join(os_root_dir, "etc/fstab")
         etc_fstab_path = os.path.join(os_root_dir, "etc/fstab")
@@ -179,16 +210,20 @@ class BaseLinuxOSMountTools(BaseSSHOSMountTools):
             "%(char)s{4}-%(char)s{12}") % {"char": uuid_char_regex}
             "%(char)s{4}-%(char)s{12}") % {"char": uuid_char_regex}
         fs_uuid_entry_regex = "^(UUID=%s)$" % fs_uuid_regex
         fs_uuid_entry_regex = "^(UUID=%s)$" % fs_uuid_regex
         by_uuid_entry_regex = "^(/dev/disk/by-uuid/%s)$" % fs_uuid_regex
         by_uuid_entry_regex = "^(/dev/disk/by-uuid/%s)$" % fs_uuid_regex
+        if not mountable_lvm_devs:
+            mountable_lvm_devs = []
         for (mountpoint, details) in mounts.items():
         for (mountpoint, details) in mounts.items():
             device = details['device']
             device = details['device']
             if (re.match(fs_uuid_entry_regex, device) is None and
             if (re.match(fs_uuid_entry_regex, device) is None and
                     re.match(by_uuid_entry_regex, device) is None):
                     re.match(by_uuid_entry_regex, device) is None):
-                LOG.warn(
-                    "Found fstab entry for dir %s which references device %s. "
-                    "Only devices references by UUID= or /dev/disk/by-uuid "
-                    "are supported. Skipping mounting directory." % (
-                        mountpoint, device))
-                continue
+                if device not in mountable_lvm_devs:
+                    LOG.warn(
+                        "Found fstab entry for dir %s which references device "
+                        "%s. Only LVM volumes or devices referenced by UUID=* "
+                        "or /dev/disk/by-uuid/* notation are supported. "
+                        "Skipping mounting directory." % (
+                            mountpoint, device))
+                    continue
             elif mountpoint in skip_mounts:
             elif mountpoint in skip_mounts:
                 LOG.debug(
                 LOG.debug(
                     "Skipping undesired mount: %s: %s", device, details)
                     "Skipping undesired mount: %s: %s", device, details)
@@ -230,6 +265,7 @@ class BaseLinuxOSMountTools(BaseSSHOSMountTools):
             colls = line.split()
             colls = line.split()
             if colls[0].startswith("/dev"):
             if colls[0].startswith("/dev"):
                 ret.append(colls[0])
                 ret.append(colls[0])
+        LOG.debug("Currently mounted devices: %s", ret)
         return ret
         return ret
 
 
     def _get_mount_destinations(self):
     def _get_mount_destinations(self):
@@ -264,7 +300,7 @@ class BaseLinuxOSMountTools(BaseSSHOSMountTools):
 
 
     def mount_os(self):
     def mount_os(self):
         dev_paths = []
         dev_paths = []
-        mouted_devs = self._get_mounted_devices()
+        mounted_devs = self._get_mounted_devices()
 
 
         volume_devs = self._get_volume_block_devices()
         volume_devs = self._get_volume_block_devices()
         for volume_dev in volume_devs:
         for volume_dev in volume_devs:
@@ -290,7 +326,7 @@ class BaseLinuxOSMountTools(BaseSSHOSMountTools):
 
 
         dev_paths_to_mount = []
         dev_paths_to_mount = []
         for dev_path in dev_paths:
         for dev_path in dev_paths:
-            if dev_path in mouted_devs:
+            if dev_path in mounted_devs:
                 # this device is already mounted. Skip it, as it most likely
                 # this device is already mounted. Skip it, as it most likely
                 # means this device belongs to the worker VM.
                 # means this device belongs to the worker VM.
                 continue
                 continue
@@ -348,7 +384,9 @@ class BaseLinuxOSMountTools(BaseSSHOSMountTools):
                 'sudo mount %s "%s/boot"' % (
                 'sudo mount %s "%s/boot"' % (
                     os_boot_device, os_root_dir))
                     os_boot_device, os_root_dir))
 
 
-        self._check_mount_fstab_partitions(os_root_dir)
+        lvm_devs = list(set(self._get_lv_paths()) - set(mounted_devs))
+        self._check_mount_fstab_partitions(
+            os_root_dir, mountable_lvm_devs=lvm_devs)
 
 
         for dir in set(dirs).intersection(['proc', 'sys', 'dev', 'run']):
         for dir in set(dirs).intersection(['proc', 'sys', 'dev', 'run']):
             mount_dir = os.path.join(os_root_dir, dir)
             mount_dir = os.path.join(os_root_dir, dir)