osbuild/util: hoist ostree code into util/ostree

Prep for sharing with other stages later.
This commit is contained in:
Dusty Mabe 2023-09-28 16:52:31 -04:00 committed by Simon de Vlieger
parent 34d3471fdd
commit 4e99e80c4a
9 changed files with 57 additions and 120 deletions

View file

@ -153,6 +153,25 @@ def show(repo: PathLike, checksum: str) -> str:
return msg return msg
def cli(*args, _input=None, **kwargs):
"""Thin wrapper for running the ostree CLI"""
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
print("ostree " + " ".join(args), file=sys.stderr)
subprocess.run(["ostree"] + args,
encoding="utf8",
stdout=sys.stderr,
input=_input,
check=True)
def parse_input_commits(commits):
"""Parse ostree input commits and return the repo path and refs specified"""
data = commits["data"]
refs = data["refs"]
assert refs, "Need at least one commit"
return commits["path"], data["refs"]
def deployment_path(root: PathLike, osname: str, ref: str, serial: int): def deployment_path(root: PathLike, osname: str, ref: str, serial: int):
"""Return the path to a deployment given the parameters""" """Return the path to a deployment given the parameters"""

View file

@ -11,10 +11,10 @@ See `ostree.repo-config(5)` for more information.
""" """
import os import os
import subprocess
import sys import sys
import osbuild.api import osbuild.api
from osbuild.util import ostree
SCHEMA = """ SCHEMA = """
"additionalProperties": false, "additionalProperties": false,
@ -51,28 +51,18 @@ SCHEMA = """
""" """
def ostree(*args, _input=None, **kwargs):
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
print("ostree " + " ".join(args), file=sys.stderr)
subprocess.run(["ostree"] + args,
encoding="utf8",
stdout=sys.stderr,
input=_input,
check=True)
def main(tree, options): def main(tree, options):
repo = os.path.join(tree, options["repo"].lstrip("/")) repo = os.path.join(tree, options["repo"].lstrip("/"))
sysroot_options = options["config"].get("sysroot", {}) sysroot_options = options["config"].get("sysroot", {})
bootloader = sysroot_options.get("bootloader") bootloader = sysroot_options.get("bootloader")
if bootloader: if bootloader:
ostree("config", "set", "sysroot.bootloader", bootloader, repo=repo) ostree.cli("config", "set", "sysroot.bootloader", bootloader, repo=repo)
readonly = sysroot_options.get("readonly") readonly = sysroot_options.get("readonly")
if readonly is not None: # can be False, which we would want to set if readonly is not None: # can be False, which we would want to set
ro = "true" if readonly else "false" ro = "true" if readonly else "false"
ostree("config", "set", "sysroot.readonly", ro, repo=repo) ostree.cli("config", "set", "sysroot.readonly", ro, repo=repo)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -20,10 +20,10 @@ the sysroot and the deployments. Additional kernel options can be passed via
""" """
import os import os
import subprocess
import sys import sys
import osbuild.api import osbuild.api
from osbuild.util import ostree
from osbuild.util.mnt import MountGuard from osbuild.util.mnt import MountGuard
CAPABILITIES = ["CAP_MAC_ADMIN"] CAPABILITIES = ["CAP_MAC_ADMIN"]
@ -85,16 +85,6 @@ SCHEMA_2 = """
""" """
def ostree(*args, _input=None, **kwargs):
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
print("ostree " + " ".join(args), file=sys.stderr)
subprocess.run(["ostree"] + args,
encoding="utf8",
stdout=sys.stderr,
input=_input,
check=True)
def make_fs_identifier(desc): def make_fs_identifier(desc):
for key in ["uuid", "label"]: for key in ["uuid", "label"]:
val = desc.get(key) val = desc.get(key)
@ -129,10 +119,10 @@ def main(tree, options):
path = os.path.join(tree, path) path = os.path.join(tree, path)
mounter.mount(path, path) mounter.mount(path, path)
ostree("admin", "deploy", ref, ostree.cli("admin", "deploy", ref,
*kargs, *kargs,
sysroot=tree, sysroot=tree,
os=osname) os=osname)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -10,10 +10,10 @@ See the ostree-init(1) man page for more details.
""" """
import os import os
import subprocess
import sys import sys
import osbuild.api import osbuild.api
from osbuild.util import ostree
SCHEMA = """ SCHEMA = """
"additionalProperties": false, "additionalProperties": false,
@ -41,13 +41,7 @@ def main(tree, options):
parent = os.path.dirname(repo) parent = os.path.dirname(repo)
os.makedirs(parent, exist_ok=True) os.makedirs(parent, exist_ok=True)
subprocess.run(["ostree", ostree.cli("init", "-v", mode=mode, repo=repo)
"init",
"-v",
f"--mode={mode}",
f"--repo={repo}"],
stdout=sys.stderr,
check=True)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -6,30 +6,20 @@ Creates the basic file system layout for an OSTree based system.
""" """
import subprocess
import sys import sys
import osbuild.api import osbuild.api
from osbuild.util import ostree
SCHEMA = """ SCHEMA = """
"additionalProperties": false "additionalProperties": false
""" """
def ostree(*args, _input=None, **kwargs):
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
print("ostree " + " ".join(args), file=sys.stderr)
subprocess.run(["ostree"] + args,
encoding="utf8",
stdout=sys.stderr,
input=_input,
check=True)
def main(tree): def main(tree):
ostree("admin", "init-fs", "--modern", tree, ostree.cli("admin", "init-fs", "--modern", tree,
sysroot=tree) sysroot=tree)
return 0 return 0

View file

@ -8,10 +8,10 @@ name `osname`.
[1] https://ostree.readthedocs.io/en/latest/manual/deployment/ [1] https://ostree.readthedocs.io/en/latest/manual/deployment/
""" """
import subprocess
import sys import sys
import osbuild.api import osbuild.api
from osbuild.util import ostree
SCHEMA = """ SCHEMA = """
"required": ["osname"], "required": ["osname"],
@ -24,20 +24,10 @@ SCHEMA = """
""" """
def ostree(*args, _input=None, **kwargs):
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
print("ostree " + " ".join(args), file=sys.stderr)
subprocess.run(["ostree"] + args,
encoding="utf8",
stdout=sys.stderr,
input=_input,
check=True)
def main(tree, options): def main(tree, options):
osname = options["osname"] osname = options["osname"]
ostree("admin", "os-init", osname, sysroot=tree) ostree.cli("admin", "os-init", osname, sysroot=tree)
return 0 return 0

View file

@ -17,7 +17,7 @@ import os
import sys import sys
import osbuild.api import osbuild.api
from osbuild.util.ostree import PasswdLike, SubIdsDB from osbuild.util import ostree
SCHEMA_2 = """ SCHEMA_2 = """
"options": { "options": {
@ -41,24 +41,16 @@ SUBUID_PATH = "etc/subuid"
SUBGID_PATH = "etc/subgid" SUBGID_PATH = "etc/subgid"
def parse_input(inputs):
commits = inputs["commits"]
source_root = commits["path"]
data = commits["data"]
refs = data["refs"]
assert refs, "Need at least one commit"
assert len(refs) == 1, "Only one commit is currently supported"
return source_root, refs
# pylint: disable=too-many-statements # pylint: disable=too-many-statements
def main(tree, inputs, _options): def main(tree, inputs, _options):
source_root, refs = parse_input(inputs) source_root, refs = ostree.parse_input_commits(inputs["commits"])
assert refs, "Need at least one commit"
assert len(refs) == 1, "Only one commit is currently supported"
os.makedirs(os.path.join(tree, "etc"), exist_ok=True) os.makedirs(os.path.join(tree, "etc"), exist_ok=True)
subuids = SubIdsDB() subuids = ostree.SubIdsDB()
subgids = SubIdsDB() subgids = ostree.SubIdsDB()
# Only once ref (commit) is currently supported, so this loop will run exactly once # Only once ref (commit) is currently supported, so this loop will run exactly once
for commit, data in refs.items(): for commit, data in refs.items():
@ -68,14 +60,14 @@ def main(tree, inputs, _options):
# Merge /usr/etc/passwd with /usr/lib/passwd from the checkout and store it in the buildroot # Merge /usr/etc/passwd with /usr/lib/passwd from the checkout and store it in the buildroot
# "tree" directory. Entries in /usr/etc/passwd have a precedence, but the file does not # "tree" directory. Entries in /usr/etc/passwd have a precedence, but the file does not
# necessarily exist. # necessarily exist.
passwd = PasswdLike.from_file(os.path.join(checkout_root, "usr/etc/passwd"), allow_missing_file=True) passwd = ostree.PasswdLike.from_file(os.path.join(checkout_root, "usr/etc/passwd"), allow_missing_file=True)
passwd.merge_with_file(os.path.join(checkout_root, "usr/lib/passwd"), allow_missing_file=False) passwd.merge_with_file(os.path.join(checkout_root, "usr/lib/passwd"), allow_missing_file=False)
passwd.dump_to_file(os.path.join(tree, "etc/passwd")) passwd.dump_to_file(os.path.join(tree, "etc/passwd"))
# Merge /usr/etc/group with /usr/lib/group from the checkout and store it in the buildroot # Merge /usr/etc/group with /usr/lib/group from the checkout and store it in the buildroot
# "tree" directory. Entries in /usr/etc/group have a precedence, but the file does not # "tree" directory. Entries in /usr/etc/group have a precedence, but the file does not
# necessarily exist. # necessarily exist.
passwd = PasswdLike.from_file(os.path.join(checkout_root, "usr/etc/group"), allow_missing_file=True) passwd = ostree.PasswdLike.from_file(os.path.join(checkout_root, "usr/etc/group"), allow_missing_file=True)
passwd.merge_with_file(os.path.join(checkout_root, "usr/lib/group"), allow_missing_file=False) passwd.merge_with_file(os.path.join(checkout_root, "usr/lib/group"), allow_missing_file=False)
passwd.dump_to_file(os.path.join(tree, "etc/group")) passwd.dump_to_file(os.path.join(tree, "etc/group"))

View file

@ -12,10 +12,10 @@ that to pull the commits.
import os import os
import subprocess
import sys import sys
import osbuild.api import osbuild.api
from osbuild.util import ostree
CAPABILITIES = ["CAP_MAC_ADMIN"] CAPABILITIES = ["CAP_MAC_ADMIN"]
@ -49,27 +49,9 @@ SCHEMA_2 = """
""" """
def ostree(*args, _input=None, **kwargs):
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
print("ostree " + " ".join(args), file=sys.stderr)
subprocess.run(["ostree"] + args,
encoding="utf8",
stdout=sys.stderr,
input=_input,
check=True)
def parse_input(inputs):
commits = inputs["commits"]
data = commits["data"]
refs = data["refs"]
assert refs, "Need at least one commit"
return commits["path"], data["refs"]
# pylint: disable=too-many-statements # pylint: disable=too-many-statements
def main(tree, inputs, options): def main(tree, inputs, options):
source_repo, commits = parse_input(inputs) source_repo, commits = ostree.parse_input_commits(inputs["commits"])
repo = options["repo"] repo = options["repo"]
remote = options.get("remote") remote = options.get("remote")
target = os.path.join(tree, repo.lstrip("/")) target = os.path.join(tree, repo.lstrip("/"))
@ -81,9 +63,9 @@ def main(tree, inputs, options):
if remote: if remote:
extra_args.append(f'--remote={remote}') extra_args.append(f'--remote={remote}')
ostree("pull-local", source_repo, ref, ostree.cli("pull-local", source_repo, ref,
*extra_args, *extra_args,
repo=target) repo=target)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -5,10 +5,10 @@ Configure OSTree remotes for a repository.
import os import os
import subprocess
import sys import sys
import osbuild.api import osbuild.api
from osbuild.util import ostree
SCHEMA = """ SCHEMA = """
"additionalProperties": false, "additionalProperties": false,
@ -66,16 +66,6 @@ SCHEMA = """
""" """
def ostree(*args, _input=None, **kwargs):
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
print("ostree " + " ".join(args), file=sys.stderr)
subprocess.run(["ostree"] + args,
encoding="utf8",
stdout=sys.stderr,
input=_input,
check=True)
def main(tree, options): def main(tree, options):
repo = options["repo"] repo = options["repo"]
remotes = options.get("remotes", []) remotes = options.get("remotes", [])
@ -101,17 +91,17 @@ def main(tree, options):
if contenturl: if contenturl:
extra_args.append(f"--set=contenturl={contenturl}") extra_args.append(f"--set=contenturl={contenturl}")
ostree("remote", "add", ostree.cli("remote", "add",
"--if-not-exists", "--if-not-exists",
*extra_args, *extra_args,
name, url, name, url,
*branches, *branches,
repo=target) repo=target)
for key in gpgkeys: for key in gpgkeys:
ostree("remote", "gpg-import", "--stdin", name, ostree.cli("remote", "gpg-import", "--stdin", name,
repo=target, repo=target,
_input=key) _input=key)
if __name__ == '__main__': if __name__ == '__main__':