Skip to content

Commit bc78997

Browse files
authored
Merge pull request #80 from vmware/topic/okurth/vmdk-fuse
add fuse utility
2 parents 0d3bc75 + e1ad695 commit bc78997

5 files changed

Lines changed: 412 additions & 2 deletions

File tree

.github/workflows/pytest.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
- uses: actions/checkout@v4
1010

1111
- name: install build deps
12-
run: sudo apt-get -y install zlib1g-dev
12+
run: sudo apt-get -y install zlib1g-dev libfuse3-dev fuse2fs
1313

1414
- name: build
1515
working-directory: ${{ github.workspace }}
@@ -19,6 +19,14 @@ jobs:
1919
working-directory: ${{ github.workspace }}
2020
run: sudo make install
2121

22+
- name: build-fuse
23+
working-directory: ${{ github.workspace }}
24+
run: make fuse
25+
26+
- name: install-fuse
27+
working-directory: ${{ github.workspace }}
28+
run: sudo make install-fuse
29+
2230
- name: set up python 3
2331
uses: actions/setup-python@v4
2432
with:

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@
1515

1616
DIRS := vmdk ova ova-compose ovfenv templates
1717

18-
default:: all
18+
default: all
1919

2020
install all:
2121
for x in $(DIRS); do $(MAKE) -C $$x $@; done
2222

23+
fuse install-fuse:
24+
$(MAKE) -C vmdk $@
25+
2326
clean:
2427
rm -rf build
2528

pytest/test_fuse.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Copyright (c) 2024 Broadcom, Inc. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the “License”); you may not
4+
# use this file except in compliance with the License. You may obtain a copy of
5+
# the License at:
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software distributed
10+
# under the License is distributed on an “AS IS” BASIS, without warranties or
11+
# conditions of any kind, EITHER EXPRESS OR IMPLIED. See the License for the
12+
# specific language governing permissions and limitations under the License.
13+
14+
15+
import hashlib
16+
import os
17+
import pytest
18+
import shutil
19+
import subprocess
20+
import time
21+
22+
23+
THIS_DIR = os.path.dirname(os.path.abspath(__file__))
24+
25+
VMDK_CONVERT=os.path.join(THIS_DIR, "..", "build", "vmdk", "vmdk-convert")
26+
VMDK_FUSE=os.path.join(THIS_DIR, "..", "build", "vmdk", "vmdk-fuse")
27+
if not os.path.exists(VMDK_FUSE):
28+
# skip this if we haven't built vmdk-fuse
29+
pytestmark = pytest.mark.skip
30+
31+
WORK_DIR=os.path.join(os.getcwd(), "pytest-fuse")
32+
33+
IMAGE_FILE="dummy.img"
34+
VMDK_FILE="dummy.vmdk"
35+
36+
37+
@pytest.fixture(scope='module', autouse=True)
38+
def setup_test():
39+
image_file = os.path.join(WORK_DIR, IMAGE_FILE)
40+
vmdk_file = VMDK_FILE
41+
42+
os.makedirs(WORK_DIR, exist_ok=True)
43+
44+
process = subprocess.run(["dd", "if=/dev/zero", f"of={image_file}", "bs=1024", "count=1024"], cwd=WORK_DIR)
45+
assert process.returncode == 0
46+
47+
process = subprocess.run(["mke2fs", image_file], cwd=WORK_DIR)
48+
assert process.returncode == 0
49+
50+
process = subprocess.run([VMDK_CONVERT, image_file, vmdk_file], cwd=WORK_DIR)
51+
assert process.returncode == 0
52+
53+
yield
54+
shutil.rmtree(WORK_DIR)
55+
56+
57+
def _get_hash(filename, blocksz=1024 * 1024):
58+
hash_type = "sha256"
59+
hash = hashlib.new(hash_type)
60+
with open(filename, "rb") as f:
61+
while True:
62+
buf = f.read(blocksz)
63+
if not buf:
64+
break
65+
hash.update(buf)
66+
return hash.hexdigest()
67+
68+
69+
def test_mount():
70+
image_file = os.path.join(WORK_DIR, IMAGE_FILE)
71+
vmdk_file = VMDK_FILE
72+
73+
mounted_image_path = os.path.join(WORK_DIR, "mounted.img")
74+
75+
with open(mounted_image_path, "w") as f:
76+
pass
77+
78+
hash_orig = _get_hash(image_file)
79+
80+
try:
81+
process = subprocess.run([VMDK_FUSE, f"--file={vmdk_file}", mounted_image_path], cwd=WORK_DIR)
82+
assert process.returncode == 0
83+
84+
hash_mounted = _get_hash(mounted_image_path)
85+
assert hash_mounted == hash_orig
86+
87+
finally:
88+
subprocess.run(["fusermount", "-u", mounted_image_path], cwd=WORK_DIR, check=True)
89+
assert not os.path.ismount(mounted_image_path)
90+
91+
92+
def test_mount_ext2():
93+
vmdk_file = VMDK_FILE
94+
95+
mounted_image_path = os.path.join(WORK_DIR, "mounted.img")
96+
mount_dir_path = os.path.join(WORK_DIR, "mntdir")
97+
98+
with open(mounted_image_path, "w") as f:
99+
pass
100+
101+
os.makedirs(mount_dir_path, exist_ok=True)
102+
103+
try:
104+
process = subprocess.run([VMDK_FUSE, f"--file={vmdk_file}", mounted_image_path], cwd=WORK_DIR)
105+
assert process.returncode == 0
106+
107+
process = subprocess.run(["fuse2fs", mounted_image_path, mount_dir_path])
108+
assert process.returncode == 0
109+
finally:
110+
subprocess.run(["fusermount", "-u", mount_dir_path], cwd=WORK_DIR)
111+
while os.path.ismount(mount_dir_path):
112+
time.sleep(0.1)
113+
# avoid device busy, which can happen even after checking if the unmount is complete (there should be a better way)
114+
time.sleep(0.1)
115+
subprocess.run(["fusermount", "-u", mounted_image_path], cwd=WORK_DIR)

vmdk/Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,40 @@
1414
# ================================================================================
1515

1616
SRC := flat.c sparse.c mkdisk.c
17+
SRC_FUSE := sparse.c vmdk-fuse.c
18+
1719
OUTPUTDIR := ../build/vmdk
1820
EXE := $(OUTPUTDIR)/vmdk-convert
21+
EXE_FUSE := $(OUTPUTDIR)/vmdk-fuse
1922

2023
PREFIX ?= /usr
2124

2225
CC := gcc
2326
CFLAGS := -W -Wall -O2 -g $(CFLAGS)
2427
LDFLAGS := -g -lz $(LDFLAGS)
28+
LDFLAGS_FUSE := $(LDFLAGS) $$(pkg-config fuse3 --libs)
2529

2630
OBJS := $(addprefix $(OUTPUTDIR)/, $(SRC:%.c=%.o))
31+
OBJS_FUSE := $(addprefix $(OUTPUTDIR)/, $(SRC_FUSE:%.c=%.o))
2732

2833
default: all
2934

35+
fuse: all $(EXE_FUSE)
36+
3037
all: $(EXE)
3138

3239
$(EXE): $(OBJS) $(OUTPUTDIR)
3340
$(CC) -o $@ $(OBJS) $(LDFLAGS)
3441

42+
$(EXE_FUSE): $(OBJS_FUSE) $(OUTPUTDIR)
43+
$(CC) -o $@ $(OBJS_FUSE) $(LDFLAGS_FUSE)
44+
3545
$(OUTPUTDIR)/%.o: %.c | $(OUTPUTDIR)
3646
$(CC) $(CFLAGS) -c -o $@ $<
3747

48+
$(OUTPUTDIR)/vmdk-fuse.o: vmdk-fuse.c | $(OUTPUTDIR)
49+
$(CC) $(CFLAGS) $$(pkg-config fuse3 --cflags) -c -o $@ $<
50+
3851
$(OUTPUTDIR):
3952
mkdir -p $(OUTPUTDIR)
4053

@@ -48,5 +61,8 @@ check:
4861
install:
4962
mkdir -p $(DESTDIR)/$(PREFIX)/bin && cp $(EXE) $(DESTDIR)/$(PREFIX)/bin/
5063

64+
install-fuse:
65+
mkdir -p $(DESTDIR)/$(PREFIX)/bin && cp $(EXE_FUSE) $(DESTDIR)/$(PREFIX)/bin/
66+
5167
clean:
5268
rm -rf $(OUTPUTDIR)

0 commit comments

Comments
 (0)