osbuild: support for checkpoints during build
Add a new `--checkpoint` option, which can be provided multiple times, that indicate after which stages a the current stage of the tree should be committed to the object store; the tree id will be the treesum of the tree at that point and a reference is created with the id of the stage at the point. The argument to `--checkpoint` is the id of the stage. If not all the given checkpoints can be found the execution will be aborted.
This commit is contained in:
parent
8d98696f47
commit
6f4d286ff4
2 changed files with 32 additions and 0 deletions
|
|
@ -10,6 +10,25 @@ BOLD = "\033[1m"
|
||||||
RED = "\033[31m"
|
RED = "\033[31m"
|
||||||
|
|
||||||
|
|
||||||
|
def mark_checkpoints(pipeline, checkpoints):
|
||||||
|
points = set(checkpoints)
|
||||||
|
def mark_stage(stage):
|
||||||
|
for c in points:
|
||||||
|
if stage.id == c:
|
||||||
|
stage.checkpoint = True
|
||||||
|
points.remove(c)
|
||||||
|
return
|
||||||
|
|
||||||
|
def mark_pipeline(pl):
|
||||||
|
for stage in pl.stages:
|
||||||
|
mark_stage(stage)
|
||||||
|
if pl.build:
|
||||||
|
mark_pipeline(pl.build)
|
||||||
|
|
||||||
|
mark_pipeline(pipeline)
|
||||||
|
return points
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Build operating system images")
|
parser = argparse.ArgumentParser(description="Build operating system images")
|
||||||
parser.add_argument("pipeline_path", metavar="PIPELINE",
|
parser.add_argument("pipeline_path", metavar="PIPELINE",
|
||||||
|
|
@ -25,6 +44,8 @@ def main():
|
||||||
help="json file containing a dictionary of secrets that are passed to sources")
|
help="json file containing a dictionary of secrets that are passed to sources")
|
||||||
parser.add_argument("-l", "--libdir", metavar="DIRECTORY", type=os.path.abspath,
|
parser.add_argument("-l", "--libdir", metavar="DIRECTORY", type=os.path.abspath,
|
||||||
help="the directory containing stages, assemblers, and the osbuild library")
|
help="the directory containing stages, assemblers, and the osbuild library")
|
||||||
|
parser.add_argument("--checkpoint", metavar="CHECKPOINT", action="append", type=str, default=None,
|
||||||
|
help="stage to commit to the object store during build (can be passed multiple times)")
|
||||||
parser.add_argument("--json", action="store_true",
|
parser.add_argument("--json", action="store_true",
|
||||||
help="output results in JSON format")
|
help="output results in JSON format")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
@ -51,6 +72,14 @@ def main():
|
||||||
with open(args.secrets) as f:
|
with open(args.secrets) as f:
|
||||||
secrets = json.load(f)
|
secrets = json.load(f)
|
||||||
|
|
||||||
|
if args.checkpoint:
|
||||||
|
missed = mark_checkpoints(pipeline, args.checkpoint)
|
||||||
|
if missed:
|
||||||
|
for checkpoint in missed:
|
||||||
|
print(f"Checkpoint {BOLD}{checkpoint}{RESET} not found!")
|
||||||
|
print(f"{RESET}{BOLD}{RED}Failed{RESET}")
|
||||||
|
return 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = pipeline.run(
|
r = pipeline.run(
|
||||||
args.store,
|
args.store,
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ class Stage:
|
||||||
self.build = build
|
self.build = build
|
||||||
self.base = base
|
self.base = base
|
||||||
self.options = options
|
self.options = options
|
||||||
|
self.checkpoint = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self):
|
def id(self):
|
||||||
|
|
@ -271,6 +272,8 @@ class Pipeline:
|
||||||
var=store,
|
var=store,
|
||||||
source_options=source_options,
|
source_options=source_options,
|
||||||
secrets=secrets)
|
secrets=secrets)
|
||||||
|
if stage.checkpoint:
|
||||||
|
object_store.snapshot(tree, stage.id)
|
||||||
results["stages"].append(r.as_dict())
|
results["stages"].append(r.as_dict())
|
||||||
except BuildError as err:
|
except BuildError as err:
|
||||||
results["stages"].append(err.as_dict())
|
results["stages"].append(err.as_dict())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue