debian-forge/mounts/org.osbuild.ostree.deployment
Christian Kellner 8b5fe600c1 mounts: add new ostree.deployment service
Create a new OSTree deployment mount service that will set up bind
mounts inside the tree very much as it is done by OSTree in early
boot. This allows any stage to transparently work with OSTree
deployments.
2021-10-30 15:32:44 +01:00

122 lines
2.9 KiB
Python
Executable file

#!/usr/bin/python3
"""
OSTree deployment mount service
This mount service will setup all needed bind mounts so
that a given `tree` will look like an active OSTree
deployment, very much as OSTree does during early boot.
More specifically it will:
- setup the sysroot bindmount to the deployment
- setup the shared var directory
- bind the boot directory into the deployment
Host commands used: mount
"""
import os
import sys
import subprocess
from typing import Dict
from osbuild import mounts
from osbuild.util import ostree
SCHEMA_2 = """
"additionalProperties": false,
"required": ["name", "type"],
"properties": {
"name": { "type": "string" },
"type": { "type": "string" },
"options": {
"type": "object",
"required": ["deployment"],
"properties": {
"deployment": {
"type": "object",
"additionalProperties": false,
"required": ["osname", "ref"],
"properties": {
"osname": {
"description": "Name of the stateroot to be used in the deployment",
"type": "string"
},
"ref": {
"description": "OStree ref to create and use for deployment",
"type": "string"
},
"serial": {
"description": "The deployment serial (usually '0')",
"type": "number",
"default": 0
}
}
}
}
}
}
"""
class OSTreeDeploymentMount(mounts.MountService):
@staticmethod
def bind_mount(source, target):
subprocess.run([
"mount", "--bind", "--make-private", source, target,
], check=True)
def mount(self, args: Dict):
tree = args["tree"]
options = args["options"]
deployment = options["deployment"]
osname = deployment["osname"]
ref = deployment["ref"]
serial = deployment.get("serial", 0)
root = ostree.deployment_path(tree, osname, ref, serial)
print(f"Deployment root at '{os.path.relpath(root, tree)}'")
var = os.path.join(tree, "ostree", "deploy", osname, "var")
boot = os.path.join(tree, "boot")
self.mountpoint = root
self.bind_mount(root, root) # prepare to move it later
self.bind_mount(tree, os.path.join(root, "sysroot"))
self.bind_mount(var, os.path.join(root, "var"))
self.bind_mount(boot, os.path.join(root, "boot"))
subprocess.run([
"mount", "--move", root, tree,
], check=True)
self.mountpoint = tree
self.check = True
return None
def umount(self):
if not self.mountpoint:
return
subprocess.run(["sync", "-f", self.mountpoint],
check=self.check)
subprocess.run(["umount", "-R", self.mountpoint],
check=self.check)
self.mountpoint = None
def main():
service = OSTreeDeploymentMount.from_args(sys.argv[1:])
service.main()
if __name__ == '__main__':
main()