Bind-mount vfs directories for each stage

Many of the stages need it anyway.
This commit is contained in:
Lars Karlitski 2019-05-06 00:23:56 +02:00
parent 658d691174
commit f6023ed78b
4 changed files with 20 additions and 40 deletions

View file

@ -35,11 +35,13 @@ modifies a file system tree. Pipelines are defined as JSON files like this one:
}
```
`osbuild` runs each of stages in turn, somewhat isolating them into mount and
pid namespaces. It injects the `options` object with a `tree` key pointing to
the file system tree and passes that to the stage via its `stdin`. Each stage
has private `/tmp` and `/var/tmp` directories that are deleted after the stage
is run. Stages may have side effects: the `io.weldr.qcow2` stage in the above
`osbuild` runs each of the stages in turn, isolating them into mount and pid
namespaces. It injects the `options` object with a `tree` key pointing to the
file system tree and passes that to the stage via its `stdin`. Each stage has
private `/tmp` and `/var/tmp` directories that are deleted after the stage is
run. osbuild also bind-mounts `/dev`, `/proc`, and `/sys` into the tree.
Stages may have side effects: the `io.weldr.qcow2` stage in the above
example packs the tree into a `qcow2` image.
## Running

View file

@ -58,6 +58,10 @@ def main(pipeline_path, from_archive, save):
set -e
mount -t tmpfs tmpfs /tmp
mount -t tmpfs tmpfs /var/tmp
mkdir -p {tree}/dev {tree}/sys {tree}/proc
mount --bind /dev {tree}/dev
mount --bind /sys {tree}/sys
mount --bind /proc {tree}/proc
stages/{name}
"""

View file

@ -1,22 +1,11 @@
#!/usr/bin/python3
import contextlib
import json
import os
import subprocess
import sys
@contextlib.contextmanager
def mount(source, dest, *options):
os.makedirs(dest, 0o755, True)
subprocess.run(["mount", *options, source, dest], check=True)
try:
yield
finally:
subprocess.run(["umount", dest], check=True)
def main(tree, playbook):
with open("/tmp/inventory", "w") as f:
f.write(f"osbuild-tree ansible_connection=chroot ansible_host={tree} ansible_python_interpreter=/usr/bin/python3")
@ -27,9 +16,6 @@ def main(tree, playbook):
else:
json.dump(playbook, f)
with mount("/dev", f"{tree}/dev", "--bind"), \
mount("/proc", f"{tree}/proc", "--bind"), \
mount("/sys", f"{tree}/sys", "--bind"):
r = subprocess.run([
"ansible-playbook", "-v",
"--connection", "chroot",
@ -42,4 +28,3 @@ def main(tree, playbook):
if __name__ == '__main__':
options = json.load(sys.stdin)
sys.exit(main(**options))

View file

@ -1,6 +1,5 @@
#!/usr/bin/python3
import atexit
import configparser
import json
import os
@ -8,30 +7,20 @@ import subprocess
import sys
def bindmount(source, dest):
os.makedirs(source, 0o755, True)
os.makedirs(dest, 0o755, True)
subprocess.run(["mount", "--bind", source, dest], check=True)
atexit.register(lambda: subprocess.run(["umount", dest]))
def main(tree, repos, packages, releasever, cache=None):
with open("/tmp/dnf.conf", "w") as conf:
p = configparser.ConfigParser()
p.read_dict(repos)
p.write(conf)
bindmount("/proc", f"{tree}/proc")
bindmount("/sys", f"{tree}/sys")
bindmount("/dev", f"{tree}/dev")
if cache:
bindmount(cache, f"{tree}/var/cache/dnf")
if not cache:
cache = f"/tmp/dnf-cache"
cmd = [
"dnf", "-yv",
"--installroot", tree,
"--setopt", "reposdir=",
"--setopt", f"cachedir={cache}",
"--setopt", "keepcache=True",
"--setopt", "install_weak_deps=False",
"--releasever", releasever,