[PATCH] Handle the incompleteness of a VG.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



---
 storage/devicelibs/lvm.py |   44 ++++++++++++++++++++++++++
 storage/devicetree.py     |   76 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 119 insertions(+), 1 deletions(-)

diff --git a/storage/devicelibs/lvm.py b/storage/devicelibs/lvm.py
index 0faee10..28c3f9e 100644
--- a/storage/devicelibs/lvm.py
+++ b/storage/devicelibs/lvm.py
@@ -171,6 +171,34 @@ def pvinfo(device):
 
     return info
 
+def pvcomplete(device):
+    """ Check validity of lvm structure with Physical Volume device.
+
+    LVM metadata is stored in all the PVs that compose a VG.  This means that
+    there might be "valid" VGs with missing PVs.  This function detects this
+    LVM behavior.
+
+    Returs True if all the PVs are known to LVM and currently present in system.
+    False otherwise.
+    """
+    # Its better not to filter any devices here.
+    args = ["pvs"] + \
+            ["--noheadings"] + \
+            ["-o", "pv_name"]
+
+    rc = iutil.execWithCapture("lvm", args,
+                                stderr = "/dev/tty5")
+
+    rc = rc.strip("\n").split("\n")
+    # We don't check for error because what we are looking for *is* an error.
+    # We search for the "unknown device" string that will tell us
+    # if this PV is part of an incomplete VG.
+    for name in rc:
+        if name.strip(" ") == "unknown device":
+            return False
+
+    return True
+
 def vgcreate(vg_name, pv_list, pe_size):
     argv = ["vgcreate"]
     if pe_size:
@@ -221,6 +249,22 @@ def vgreduce(vg_name, pv_list):
     if rc:
         raise LVMError("vgreduce failed for %s" % vg_name)
 
+def vgreduce_rm(vg_name):
+    """ Reduce a VG with the --removemissing options.
+
+    We use this when we don't know the PVs that we are to reduce.
+    """
+    # We should not filter this command because we want lvm to consider all pvs
+    args = ["vgreduce", "--removemissing", vg_name]
+    rc = iutil.execWithRedirect("lvm", args,
+                                stdout = "/dev/tty5",
+                                stderr = "/dev/tty5",
+                                searchPath=1)
+
+    if rc:
+        raise LVMError("vgreduce failed for %s" % vg_name)
+
+
 def vginfo(vg_name):
     buf = iutil.execWithCapture("lvm",
                 ["vgs", "--noheadings", "--nosuffix", "--units", "m", "-o", 
diff --git a/storage/devicetree.py b/storage/devicetree.py
index ccc925a..0d469f1 100644
--- a/storage/devicetree.py
+++ b/storage/devicetree.py
@@ -135,6 +135,34 @@ def questionInitializeDisk(intf=None, name=None):
             retVal = True
     return retVal
 
+def questionClobberIncompleteVG(intf=None, pv_name=None, vg_name=None):
+    retVal = False # The less destructive default
+    if not intf or not pv_name:
+        pass
+    else:
+        if vg_name is not None:
+            message_part = _("%s, that is an incomplete" % vg_name)
+        else:
+            message_part = _("an unknown")
+
+        message = _("Error processing drive %s.\n"
+                    "It seems that %s is part of %s Volume Group. "
+                    "You can reinitialize %s, loosing all data or ignore "
+                    "it, preserving its contents.") % (pv_name, pv_name,
+                            message_part, pv_name)
+
+        rc = intf.messageWindow(_("Warning"),
+                message,
+                type="custom",
+                custom_buttons = [ _("_Ignore drive"),
+                                   _("_Re-initialize drive") ],
+                custom_icon="question")
+        if rc == 0:
+            pass
+        else:
+            retVal = True # thie means clobber.
+    return retVal
+
 class DeviceTree(object):
     """ A quasi-tree that represents the devices in the system.
 
@@ -1030,16 +1058,62 @@ class DeviceTree(object):
                             self.ignoredDisks.append(device.name)
                             rs.deactivate()
             elif format.type == "lvmpv":
+                import pdb; pdb.set_trace()
                 # lookup/create the VG and LVs
                 try:
                     vg_name = udev_device_get_vg_name(info)
                 except KeyError:
-                    # no vg name means no vg -- we're done with this pv
+                    # This means that there is LVM metadata in device but not
+                    # enough to identify the vg name.
+                    # There is no need to call lvm.pvcomplete as we already know
+                    # that it is incomplete.
+                    if questionClobberIncompleteVG(intf = self.intf,
+                            pv_name = device.path):
+                        try:
+                            lvm.pvremove(device.path)
+                        except:
+                            # We ignore because we expect an certain error.
+                            # LVM complains that it cannot find uuids
+                            # FIXME: This fails if some other error ocurrs.
+                            pass
+                        # Give the device the a default format
+                        for arg in ["vgName", "vgUuid", "peStarg"]:
+                            if kwargs.has_key(arg):
+                                del kwargs[arg]
+                        device.format = formats.getFormat(None)
+
+                    else:
+                        self.ignoredDisks.append(device.name)
                     return
 
+
                 vg_device = self.getDeviceByName(vg_name)
                 if vg_device:
                     vg_device._addDevice(device)
+
+                elif not lvm.pvcomplete(device.path):
+                    # PVs usually have VG data, that does not mean that the VG
+                    # is valid.  Here, check to see if all the vg components are
+                    # here.  If not, give the user the possibility to ignore or
+                    # initialize this device.
+                    if questionClobberIncompleteVG(intf = self.intf,
+                            pv_name = device.path,
+                            vg_name = vg_name):
+                        lvm.vgreduce_rm(vg_name) #reduce with --removemissing
+                        lvm.vgremove(vg_name) # now we can remove
+                        lvm.pvremove(device.path) # finally remove the PV
+
+                        # Give the device the a default format
+                        for arg in ["vgName", "vgUuid", "peStarg"]:
+                            if kwargs.has_key(arg):
+                                del kwargs[arg]
+                        device.format = formats.getFormat(None)
+
+                    else:
+                        self.ignoredDisks.append(device.name)
+
+                    return
+
                 else:
                     try:
                         vg_uuid = udev_device_get_vg_uuid(info)
-- 
1.6.0.6

_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list

[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux