osbuild/util: hoist ostree code into util/ostree
Prep for sharing with other stages later.
This commit is contained in:
parent
34d3471fdd
commit
4e99e80c4a
9 changed files with 57 additions and 120 deletions
|
|
@ -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"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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__':
|
||||||
|
|
|
||||||
|
|
@ -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__':
|
||||||
|
|
|
||||||
|
|
@ -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__':
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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__':
|
||||||
|
|
|
||||||
|
|
@ -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__':
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue