summaryrefslogtreecommitdiffstats
path: root/tools/nbdfuse.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/nbdfuse.py')
-rw-r--r--tools/nbdfuse.py63
1 files changed, 63 insertions, 0 deletions
diff --git a/tools/nbdfuse.py b/tools/nbdfuse.py
new file mode 100644
index 0000000..b7a4997
--- /dev/null
+++ b/tools/nbdfuse.py
@@ -0,0 +1,63 @@
+import logging
+import os
+import tempfile
+
+from subprocess import Popen, PIPE
+from time import sleep
+from . import log, rmdir
+
+__all__ = ["mount"]
+
+L = logging.getLogger(__name__)
+
+
+@log
+def mount(path):
+ """Mount a VMware Virtual Machine Disk (VMDK) file as a RAW image file in
+ the local filesystem with read-only support using `qemu-nbd` + `nbdfuse`.
+
+ See also:
+ https://manpages.debian.org/bullseye/qemu-utils/qemu-nbd.8.en.html
+ https://manpages.debian.org/bullseye/libnbd-bin/nbdfuse.1.en.html
+
+ Make sure you have the following packages installed:
+ $ sudo apt install qemu-utils nbdfuse
+
+ Args:
+ path (str): Path to the VMDK file.
+
+ Returns:
+ Path to the directory containing a single virtual file named `nbd`.
+ """
+ mp = tempfile.mkdtemp()
+ cmd = [
+ "nbdfuse",
+ "--readonly",
+ mp,
+ "--socket-activation",
+ "qemu-nbd",
+ "--read-only",
+ "--format=vmdk",
+ path
+ ]
+
+ try:
+ p = Popen(cmd, stdout=PIPE, stderr=PIPE, text=True)
+ except Exception as e:
+ L.error("failed to execute command %s: %r", cmd, e)
+ rmdir(mp)
+ return ""
+
+ while p.poll() is None:
+ if os.path.ismount(mp):
+ return mp
+ sleep(1)
+
+ ret = p.poll()
+ out, err = p.communicate()
+ out, err = out.strip(), err.strip()
+ L.error("retcode: %d, stdout: %s, stderr: %s", ret, out, err)
+
+ rmdir(mp)
+
+ return ""