Skip to content

Commit

Permalink
inputs: new input type org.osbuild.containers-storage
Browse files Browse the repository at this point in the history
An input that pairs with the org.osbuild.containers-storage source. It
makes the host container storage available to a stage and a container ID
for the stage to use.

Unlike all the other input types, this input does not refer to static
objects in the osbuild sources store but a dynamically mounted container
store that depends on the host storage configuration and the
availability of specific containers in that store.

Co-authored-by: Achilleas Koutsou <[email protected]>
Co-authored-by: Gianluca Zuccarelli <[email protected]>
  • Loading branch information
2 people authored and ondrejbudai committed Feb 21, 2024
1 parent ac45c29 commit 591341d
Showing 1 changed file with 145 additions and 0 deletions.
145 changes: 145 additions & 0 deletions inputs/org.osbuild.containers-storage
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#!/usr/bin/python3
"""Inputs for container images from the host storage
This is an input that pairs with the org.osbuild.containers-storage
source. It makes the host container storage available to a stage
and a container ID for the stage to use.
Unlike all the other input types, this does not refer to static
objects in the osbuild sources store but a dynamically mounted
container store that depends on the availability of the
resource (the specific container) on the host.
"""

import os
import sys

from osbuild import inputs
from osbuild.util import containers
from osbuild.util.mnt import MountGuard

SCHEMA = r"""
"definitions": {
"source-options": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"description": "The name to use for the image"
}
}
},
"source-object-ref": {
"type": "object",
"additionalProperties": false,
"minProperties": 1,
"patternProperties": {
".*": {
"$ref": "#/definitions/source-options"
}
}
},
"source-array-ref": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": ["id"],
"properties": {
"id": {
"type": "string"
},
"options": {
"$ref": "#/definitions/source-options"
}
}
}
},
"source-origin": {
"type": "string",
"description": "When the origin of the input is a source",
"enum": ["org.osbuild.source"]
}
},
"additionalProperties": false,
"required": ["type", "origin", "references"],
"properties": {
"type": {
"enum": ["org.osbuild.containers-storage"]
},
"origin": {
"description": "The org.osbuild.source origin case",
"$ref": "#/definitions/source-origin"
},
"references": {
"description": "Container image id",
"oneOf": [
{"$ref": "#/definitions/source-array-ref"},
{"$ref": "#/definitions/source-object-ref"}
]
}
}
"""


class ContainersInput(inputs.InputService):

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.mg = MountGuard()
self.storage_conf = None

def map_storage_ref(self, _source, ref, target):
# we only want to read the host once and only for inputs that
# require it. If we do this for all inputs, reading the host
# may cause unexpected errors.
if self.storage_conf is None:
self.storage_conf = containers.get_host_storage()

source = self.storage_conf["storage"]["graphroot"]
dest = os.path.join(target, "storage")

# bind mount the input directory to the destination
os.makedirs(dest, exist_ok=True)
self.mg.mount(source, dest)

return ref, "containers-storage"

def map(self, store, origin, refs, target, _options):
images = {}

for ref, data in refs.items():
source = "org.osbuild.containers-storage"
ref, container_format = self.map_storage_ref(source, ref, target)

images[ref] = {
"format": container_format,
"name": data["name"]
}
images[ref]["name"] = data["name"]

if container_format == "containers-storage" and self.storage_conf is not None:
images[ref]["storage"] = self.storage_conf["storage"]

reply = {
"path": target,
"data": {
"archives": images
}
}

return reply

def unmap(self):
self.mg.umount()


def main():
service = ContainersInput.from_args(sys.argv[1:])
service.main()


if __name__ == '__main__':
main()

0 comments on commit 591341d

Please sign in to comment.