stages: add org.osbuild.erofs

Erofs is "a lightweight read-only file system"[1]. Imagine squashfs, but with
faster reads.

This commit adds support for creating it. The new stage is heavily inspired by
the squashfs one. I've decided to add all features of mkfs.erofs that looked
useful: All compression types and most of extended options (excluding the
compatibility ones, we can always add them later).

[1]: https://en.wikipedia.org/wiki/EROFS
This commit is contained in:
Ondřej Budai 2023-09-01 13:06:11 +02:00 committed by Simon de Vlieger
parent 286b785af7
commit a2ea0b2265

101
stages/org.osbuild.erofs Executable file
View file

@ -0,0 +1,101 @@
#!/usr/bin/python3
"""
Create a file containing an erofs filesystem named `filename`.
See https://en.wikipedia.org/wiki/EROFS for details about the
filesystem.
Buildhost commands used: `mkfs.erofs`
"""
import os
import subprocess
import sys
import osbuild.api
SCHEMA_2 = """
"options": {
"additionalProperties": false,
"required": ["filename"],
"properties": {
"filename": {
"description": "Filename for the output",
"type": "string"
},
"compression": {
"type": "object",
"additionalProperties": false,
"required": ["method"],
"properties": {
"method": {
"description": "Compression method",
"enum": ["lz4", "lz4hc", "lzma"]
},
"level": {
"description": "Compression level. Note that different methods support different levels. See mkfs.erofs(1) for more details",
"type": "number"
}
}
},
"options": {
"description": "Extended options for the filesystem, see mkfs.erofs(1)",
"type": "array",
"minItems": 1,
"items:": {
"enum": [
"all-fragments",
"dedupe",
"force-inode-compact",
"force-inode-extended",
"force-inode-blockmap",
"force-chunk-indexes",
"fragments",
"noinline_data",
"ztailpacking"
]
}
}
}
},
"inputs": {
"type": "object",
"additionalProperties": false,
"required": ["tree"],
"properties": {
"tree": {
"type": "object",
"additionalProperties": true
}
}
}
"""
def main(inputs, output_dir, options):
source = inputs["tree"]["path"]
filename = options["filename"].lstrip("/")
compression = options.get("compression")
target = os.path.join(output_dir, filename)
cmd = ["mkfs.erofs", target, source]
if compression:
method = compression["method"]
if compression.get("level"):
method += f",{compression['level']}"
cmd += ["-z", method]
if options:
cmd += ["-E", ",".join(options)]
subprocess.run(cmd, check=True)
return 0
if __name__ == '__main__':
args = osbuild.api.arguments()
r = main(args["inputs"], args["tree"], args["options"])
sys.exit(r)