It's not really useful because it's at the wrong place, after a stage has torn down all mounts. It also makes the code more complex for too little benefit.
68 lines
2.6 KiB
Python
Executable file
68 lines
2.6 KiB
Python
Executable file
#!/usr/bin/python3
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import osbuild
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
RESET = "\033[0m"
|
|
BOLD = "\033[1m"
|
|
RED = "\033[31m"
|
|
|
|
|
|
def run_interactive(pipeline_path, input_dir, output_dir):
|
|
with open(pipeline_path) as f:
|
|
pipeline = json.load(f)
|
|
|
|
with osbuild.BuildRoot("/run/osbuild") as buildroot:
|
|
for i, stage in enumerate(pipeline["stages"], start=1):
|
|
name = stage["name"]
|
|
options = stage.get("options", {})
|
|
print()
|
|
print(f"{RESET}{BOLD}{i}. {name}{RESET} " + json.dumps(options or {}, indent=2))
|
|
print("Inspect with:")
|
|
print(f"\t# nsenter -a --wd=/root -t `machinectl show {buildroot.machine_name} -p Leader --value`")
|
|
print()
|
|
buildroot.run_stage(name, options, input_dir)
|
|
|
|
assembler = pipeline.get("assembler")
|
|
if assembler:
|
|
name = assembler["name"]
|
|
options = assembler.get("options", {})
|
|
print()
|
|
print(f"{RESET}{BOLD}Assembling: {name}{RESET} " + json.dumps(options or {}, indent=2))
|
|
print("Inspect with:")
|
|
print(f"\t# nsenter -a --wd=/root -t `machinectl show {buildroot.machine_name} -p Leader --value`")
|
|
print()
|
|
buildroot.run_assembler(name, options, output_dir)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Build operating system images")
|
|
parser.add_argument("pipeline_path", metavar="PIPELINE",
|
|
help="json file containing the pipeline that should be built")
|
|
parser.add_argument("--input", dest="input_dir", metavar="DIRECTORY", type=os.path.abspath,
|
|
help="provide the contents of DIRECTORY to the first stage")
|
|
parser.add_argument("--output", dest="output_dir", metavar="DIRECTORY", type=os.path.abspath,
|
|
help="provide the empty DIRECTORY as output argument to the last stage")
|
|
args = parser.parse_args()
|
|
|
|
os.makedirs("/run/osbuild", exist_ok=True)
|
|
|
|
if args.output_dir and os.path.exists(args.output_dir) and len(os.listdir(args.output_dir)) != 0:
|
|
print("Error: output directory is not empty", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
try:
|
|
run_interactive(args.pipeline_path, args.input_dir, args.output_dir)
|
|
except KeyboardInterrupt:
|
|
print()
|
|
print(f"{RESET}{BOLD}{RED}Aborted{RESET}")
|
|
sys.exit(130)
|
|
except osbuild.StageFailed as error:
|
|
print()
|
|
print(f"{RESET}{BOLD}{RED}{error.stage} failed with code {error.returncode}{RESET}")
|
|
sys.exit(1)
|