[PATCH 2/3] Add support for detecting btrfs default subvolume.
David Lehman
dlehman at redhat.com
Mon Nov 18 15:07:09 UTC 2013
On Fri, 2013-11-15 at 17:28 -0800, Brian C. Lane wrote:
> On Fri, Nov 15, 2013 at 08:32:01AM -0600, David Lehman wrote:
> > ---
> > blivet/devicelibs/btrfs.py | 16 ++++++++++++++++
> > blivet/devices.py | 31 +++++++++++++++++++++++++++++--
> > blivet/devicetree.py | 3 +++
> > 3 files changed, 48 insertions(+), 2 deletions(-)
> >
> > diff --git a/blivet/devicelibs/btrfs.py b/blivet/devicelibs/btrfs.py
> > index eba27f7..1661f53 100644
> > --- a/blivet/devicelibs/btrfs.py
> > +++ b/blivet/devicelibs/btrfs.py
> > @@ -32,6 +32,8 @@ _ = lambda x: gettext.ldgettext("blivet", x)
> > import logging
> > log = logging.getLogger("blivet")
> >
> > +main_volume_id = 5
> > +
>
> This should be all caps.
Yes -- will fix locally and include a comment.
>
> > def btrfs(args, capture=False):
> > if capture:
> > exec_func = util.capture_output
> > @@ -113,3 +115,17 @@ def list_subvolumes(mountpoint):
> > "path": group[2]})
> >
> > return vols
> > +
> > +def get_default_subvolume(mountpoint):
> > + if not os.path.ismount(mountpoint):
> > + raise ValueError("volume not mounted")
> > +
> > + args = ["subvol", "get-default", mountpoint]
> > + buf = btrfs(args, capture=True)
> > + m = re.match(r'ID (\d+) .*', buf)
> > + try:
> > + default = int(m.groups()[0])
> > + except IndexError:
> > + raise BTRFSError("failed to get default subvolume from %s" % mountpoint)
>
> The match may fail and m could be None which will give you an
> AttributeError
The match should never fail, but if it finds a way we should fail with a
BTRFSError and not an AttributeError, so I'll change it locally.
>
> > +
> > + return default
> > diff --git a/blivet/devices.py b/blivet/devices.py
> > index 725a917..6c8acd3 100644
> > --- a/blivet/devices.py
> > +++ b/blivet/devices.py
> > @@ -4351,7 +4351,7 @@ class BTRFSDevice(StorageDevice):
> >
> > class BTRFSVolumeDevice(BTRFSDevice):
> > _type = "btrfs volume"
> > - vol_id = 5
> > + vol_id = btrfs.main_volume_id
>
> why do this instead of just referring to btrfs.MAIN_VOLUME_ID where
> needed?
Because subvolumes also have a vol_id attribute, so this provides a
consistent interface for all btrfs "devices" in this regard.
>
> >
> > def __init__(self, *args, **kwargs):
> > self.dataLevel = kwargs.pop("dataLevel", None)
> > @@ -4379,7 +4379,7 @@ class BTRFSVolumeDevice(BTRFSDevice):
> > label=label,
> > volUUID=self.uuid,
> > device=self.path,
> > - mountopts="subvolid=" + self.vol_id)
> > + mountopts="subvolid=%d" % self.vol_id)
> > self.originalFormat = copy.copy(self.format)
> >
> > def _setFormat(self, format):
> > @@ -4487,6 +4487,8 @@ class BTRFSVolumeDevice(BTRFSDevice):
> > subvols = btrfs.list_subvolumes(self.originalFormat._mountpoint)
> > except BTRFSError as e:
> > log.debug("failed to list subvolumes: %s" % e)
> > + else:
> > + self._getDefaultSubVolumeID()
> > finally:
> > self._undo_temp_mount()
> >
> > @@ -4503,6 +4505,31 @@ class BTRFSVolumeDevice(BTRFSDevice):
> > def removeSubVolume(self, name):
> > raise NotImplementedError()
> >
> > + def _getDefaultSubVolumeID(self):
> > + subvolid = None
> > + try:
> > + subvolid = btrfs.get_default_subvolume(self.originalFormat._mountpoint)
> > + except BTRFSError as e:
> > + log.debug("failed to get default subvolume id: %s" % e)
> > +
> > + self.defaultSubVolumeID = subvolid
> > +
> > + @property
> > + def defaultSubVolume(self):
> > + default = None
> > + if self.defaultSubVolumeID is None:
> > + return None
> > +
> > + if self.defaultSubVolumeID == btrfs.main_volume_id:
> > + return self
> > +
> > + for sv in self.subvolumes:
> > + if sv.vol_id == self.defaultSubVolumeID:
>
> How is vol_id different from btrfs.main_volume_id? I must be missing
> something here.
vol_id will be different for each "device", including the main volume.
More information about the anaconda-patches
mailing list