From c9d65696c2596e6b92e40fab4df4eb8948e8ddb3 Mon Sep 17 00:00:00 2001
From: David Lehman <dlehman@redhat.com>
Date: Fri, 26 Aug 2011 18:39:50 -0500
Subject: [PATCH 01/12] Add backend module for operating on btrfs volumes.

---
 pyanaconda/storage/devicelibs/btrfs.py |  118 ++++++++++++++++++++++++++++++++
 1 files changed, 118 insertions(+), 0 deletions(-)
 create mode 100644 pyanaconda/storage/devicelibs/btrfs.py

diff --git a/pyanaconda/storage/devicelibs/btrfs.py b/pyanaconda/storage/devicelibs/btrfs.py
new file mode 100644
index 0000000..3fe1218
--- /dev/null
+++ b/pyanaconda/storage/devicelibs/btrfs.py
@@ -0,0 +1,118 @@
+#
+# btrfs.py
+# btrfs functions
+#
+# Copyright (C) 2011  Red Hat, Inc.  All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): David Lehman <dlehman@redhat.com>
+#
+
+import os
+import re
+
+from pyanaconda import iutil
+from ..errors import *
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+import logging
+log = logging.getLogger("storage")
+
+def btrfs(args, progress=None, capture=False):
+    kwargs = {}
+    kwargs["stderr"] = "/dev/tty5"
+    if capture:
+        # execWithCapture can't take a progress window so it gets ignored
+        exec_func = iutil.execWithCapture
+    else:
+        exec_func = iutil.execWithPulseProgress
+        kwargs["stdout"] = "/dev/tty5"
+        kwargs["progress"] = progress
+
+    ret = exec_func("btrfs", args, **kwargs)
+    if not capture and ret.rc:
+        raise BTRFSError(ret.stderr)
+
+    return ret
+
+def create_volume(devices, label=None, data=None, metadata=None, progress=None):
+    """ For now, data and metadata must be strings mkfs.btrfs understands. """
+    if not devices:
+        raise ValueError("no devices specified")
+    elif any([not os.path.exists(d) for d in devices]):
+        raise ValueError("one or more specified devices not present")
+
+    args = []
+    if data:
+        args.append("--data=%s" % data)
+
+    if metadata:
+        args.append("--metadata=%s" % metadata)
+
+    if label:
+        args.append("--label=%s" % label)
+
+    args.extend(devices)
+
+    ret = iutil.execWithPulseProgress("mkfs.btrfs", args,
+                                      stdout="/dev/tty5", stderr="/dev/tty5",
+                                      progress=progress)
+    if ret.rc:
+        raise BTRFSError(ret.stderr)
+
+    return ret
+
+# destroy is handled using wipefs
+
+# add device
+
+# remove device
+
+def create_subvolume(mountpoint, name, progress=None):
+    if not os.path.ismount(mountpoint):
+        raise ValueError("volume not mounted")
+
+    path = os.path.normpath("%s/%s" % (mountpoint, name))
+    args = ["subvol", "create", path]
+    return btrfs(args, progress=progress)
+
+def delete_subvolume(mountpoint, name, progress=None):
+    if not os.path.ismount(mountpoint):
+        raise ValueError("volume not mounted")
+
+    path = os.path.normpath("%s/%s" % (mountpoint, name))
+    args = ["subvol", "delete", path]
+    return btrfs(args, progress=progress)
+
+def create_snapshot(source, dest):
+    pass
+
+def scan_device(path):
+    return btrfs(["device", "scan", path])
+
+# get a list of subvolumes from a mounted btrfs filesystem
+def list_subvolumes(mountpoint):
+    if not os.path.ismount(mountpoint):
+        raise ValueError("volume not mounted")
+
+    args = ["subvol", "list", mountpoint]
+    buf = btrfs(args, capture=True)
+    vols = []
+    for group in re.findall(r'ID (\d+) top level (\d+) path (.+)\n', buf):
+        vols.append({"id": int(group[0]), "path": group[2]})
+
+    return vols
-- 
1.7.3.4

