Commit graph

188 commits

Author SHA1 Message Date
Michael Vogt
67fabadbd4 osbuild: drop + when doing QEMU_LOG=unimp
This commit drops the `QEMU_LOG=+unimp` and replaces it with
`QEMU_LOG=unimp`. The `+` format does not work and we found
this in https://github.com/osbuild/bootc-image-builder/pull/963#issuecomment-3001154460
2025-06-27 11:37:38 +02:00
Michael Vogt
f52aeb0676 osbuild: add experimental flag debug-qemu-user
This commit adds support for more debug for `qemu-user` options.
When settings:
```
$ sudo IMAGE_BUILDER_EXPERIMENAL=debug-qemu-user bootc-image-builder ...
```
extra debug will be printed. This hopefully helps to track down
the root cause of
https://github.com/podman-desktop/extension-bootc/issues/1475
2025-04-03 10:49:06 +02:00
Michael Vogt
154abafae8 osbuild: tweak build() to be mypy clean
This commit tweaks build() to be mypy clean without the need to
call assert. This drops the map() and instead we use the existing
dict-like access of the manifest to get the pipeline. In practise
this should not happen but lets be prepared.

Note that a small tweak for the error is needed to make it clear
what is happening.

Thanks to Simon for raising this.
2025-01-14 14:33:28 +01:00
Michael Vogt
d6aca23709 osbuild: make {Build,Download}Result as_dict() explicit
This commit makes the returns of the of {Build,Download}Result.as_dict()
explicit. Ideally this would just be a dataclass and dataclass.asdict()
but because we need to support python3.6 this is not possible today.
2025-01-14 14:33:28 +01:00
Michael Vogt
c27c32be0e osbuild: add result error reporting for sources
This commit adds error reporting from source download errors
to the monitor. It reuses the `BuildResult` for symmetry but
we probably want to refactor this a bit to make source handling
a bit more similar to stages.
2025-01-14 14:33:28 +01:00
Michael Vogt
5ba7cadd8b monitor: include build_result in jsonseq monitor streaming
In order to avoid having to rely on the output of `osbuild --json`
when using `--progress=JSONSeqMonitor` the monitor needs to include
the `osbuild.pipeline.BuildResult` for each individual stage.

This commit adds those to the montior.
2025-01-14 14:33:28 +01:00
Michael Vogt
2cb57f0ed8 osbuild: describe the result Manifest.build() and Stage.run()
This commit adds mypy annotations and a docstring to make it
easier to trace the result value of an osbuild run.
2025-01-14 14:33:28 +01:00
Tomáš Hozza
7f86ccc7fc Fix pylint issue R1737: use-yield-from
Fix:
osbuild/pipeline.py:101:12: R1737: Use 'yield from' directly instead of yielding each element one by one (use-yield-from)

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
2024-11-25 10:09:18 +01:00
Simon de Vlieger
8429acf7e3 test: metadata in describe
Michael Vogt pointed out that testcases start failing when we describe
the new format. Let's add a test case and fix the describe to include
the metadata.

Metadata is freeform in the `Manifest` instance but it is stored on it
during loading (at which time its properties are validated) and returned
as-is on describe.

Signed-off-by: Simon de Vlieger <supakeen@redhat.com>
2024-10-29 08:24:33 +01:00
Michael Vogt
0abdfb9041 jsoncomm: transparently handle huge messages via fds
The existing jsoncomm is a work of beautiy. For very big arguments
however the used `SOCK_SEQPACKET` hits the limitations of the
kernel network buffer size (see also [0]). This lead to various
workarounds in #824,#1331,#1836 where parts of the request are
encoded as part of the json method call and parts are done via
a side-channel via fd-passing.

This commit changes the code so that the fd channel is automatically
and transparently created and the workarounds are removed. A test
is added that ensures that very big messages can be passed.

[0] https://github.com/osbuild/osbuild/pull/1833
2024-09-17 19:27:03 +02:00
Michael Vogt
77a61da760 osbuild: drop libdir from download() methods
The libdir is passed down for sources but it is never used in
any of our sources. As this is confusing and we want to eventually
support multiple libdirs remove this code.

It looks like the libdir for soruces was added a long time ago in 8423da3
but there is no indication if/how it is/was supposed to get used and
AFACT from going over the git history it was very used.

SourceService:dispatch() never sends "libdir" to the actual sources,
so it is not an even technically an API break.
2024-08-26 19:58:55 +02:00
Michael Vogt
f214c69a98 osbuild: add workaround to integrate sources into progress reporting
This commit is somewhat poor, sorry for that. It mostly adds
workaround so that the osbuild sources can emit some progress
reporting as well. Without that the user experience is rather poor
and there is a long delay before any sort of progress can be
reported (even before the normal stages run).

With it the user experience is still not good but slightly better,
i.e. the progress monitor will report that the sources have
started downloading and curl will generated some log output. No
real progress unfortunately (sources subprogress will jump from
zero to 100%).
2024-03-12 16:44:12 +01:00
Michael Vogt
83e66839bc monitor: log start/stop of stages and pipelines too
Generate log messages with origin "org.osbuild.main" when
pipelines/stages start and finish. This way a higher level
frontend can display high level progress coming from this
origin and filter out e.g. stages based log messages (that
are usually quite technical as they are just stdout/stderr
from the stages).
2024-03-12 16:44:12 +01:00
Dusty Mabe
83a14886d3 add --break for requesting a debug shell
Similar to rd.break for dracut this allows a user to specify:

- --break or --break=*
    - to get a shell before each stage is run
- --break=stage.name
    - to get a shell each time the stage with that name is run
    - example: --break=org.osbuild.copy
- --break=stage.id
    - to get a shell each time the stage with that ID is run
    - get the ID for the stages for your manifest by running
      osbuild on the manifest with --inspect
    - example: --break=dc6e3a66fef3ebe7c815eb24d348215b9e5e2ed0cd808c15ebbe85fc73181a86

and get a bash shell where they can inspect the environment to debug
and develop OSBuild stages.
2024-01-10 08:39:27 -08:00
Dusty Mabe
ce8408a9c6 mounts: support mounting partitions
This allows us to map in a whole disk as a loopback device with parition
scanning rather than slicing up the disk and creating several loopback
devices. Something like this:

```
      - type: org.osbuild.copy
        inputs:
          tree:
            type: org.osbuild.tree
            origin: org.osbuild.pipeline
            references:
              - name:tree
        options:
          paths:
            - from: input://tree/
              to: mount://root/
        devices:
          efi:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              start:
                mpp-format-int: '{image.layout[''EFI-SYSTEM''].start}'
              size:
                mpp-format-int: '{image.layout[''EFI-SYSTEM''].size}'
          boot:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              start:
                mpp-format-int: '{image.layout[''boot''].start}'
              size:
                mpp-format-int: '{image.layout[''boot''].size}'
          root:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              start:
                mpp-format-int: '{image.layout[''root''].start}'
              size:
                mpp-format-int: '{image.layout[''root''].size}'
        mounts:
          - name: root
            type: org.osbuild.xfs
            source: root
            target: /
          - name: boot
            type: org.osbuild.ext4
            source: boot
            target: /boot
          - name: efi
            type: org.osbuild.fat
            source: efi
            target: /boot/efi
```

now becomes a little more simple:

```
      - type: org.osbuild.copy
        inputs:
          tree:
            type: org.osbuild.tree
            origin: org.osbuild.pipeline
            references:
              - name:tree
        options:
          paths:
            - from: input://tree/
              to: mount://root/
        devices:
          disk:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              partscan: true
        mounts:
          - name: root
            type: org.osbuild.xfs
            source: disk
            partition:
              mpp-format-int: '{image.layout[''root''].partnum}'
            target: /
          - name: boot
            type: org.osbuild.ext4
            source: disk
            partition:
              mpp-format-int: '{image.layout[''boot''].partnum}'
            target: /boot
          - name: efi
            type: org.osbuild.fat
            source: disk
            partition:
              mpp-format-int: '{image.layout[''EFI-SYSTEM''].partnum}'
            target: /boot/efi
```

Fixes https://github.com/osbuild/osbuild/issues/1495
2023-12-22 10:18:29 -05:00
Simon de Vlieger
427e82e0c0 osbuild: --checkpoint can now use globs
When developing or rebuilding manifests a lot it is common to want to
checkpoint everything to the store. It seems we all have small shell
scripts hanging around for this.

Let `--checkpoint` take a shell-like glob such as `--checkpoint="*"` to
checkpoint everything.

Note that there's a behavioral change here; previously `osbuild
--checkpoint=a` would error if that specific checkpoint wasn't found.
Now `osbuild` will only error if nothing was selected by the passed
globs.
2023-08-04 19:59:11 +02:00
Simon de Vlieger
d60690ce46 tox: add tox
`tox` is a standard testing tool for Python projects, this allows you to
test locally with all your installed Python version with the following
command:

`tox -m test -p all`

To run the tests in parallel for all supported Python versions.

To run linters or type analysis:

```
tox -m lint -p all
tox -m type -p all
```

This commit *also* disables the `import-error` warning from `pylint`,
not all Python versions have the system-installed Python libraries
available and they can't be fetched from PyPI.

Some linters have been added and the general order linters run in has
been changed. This allows for quicker test failure when running
`tox -m lint`. As a consequence the `test_pylint` test has been removed
as it's role can now be fulfilled by `tox`.

Other assorted linter fixes due to newer versions:
- use a str.join method (`consider-using-join`)
- fix various (newer) mypy and pylint issues
- comments starting with `#` and no space due to `autopep8`

This also changes our CI to use the new `tox` setup and on top of that
pins the versions of linters used. This might move into separate
requirements.txt files later on to allow for easier updating of those
dependencies.
2023-08-01 15:01:13 +02:00
Ondřej Budai
c90b587dcc inputs: Move arguments for InputService.map to a temporary file
Prior this commit, the arguments for the input service were passed inline.
However, jsoncomm uses the SOCK_SEQPACKET socket type underneath that has
a fixed maximum packet size. On my system, it's 212960 bytes. Unfortunately,
that's not enough for big inputs (e.g. when building packages with a lot
of rpms).

This commit moves all arguments to a temporary file. Then, just a file
descriptor is sent. Thus, we are now able to send arbitrarily sized args
for inputs, making osbuild work even for large image builds.
2023-06-27 10:56:10 +02:00
Christian Kellner
6c0183da21 pipeline: set source_epoch for tree
This will lead to all mtimes that are newer than the creation time
of `tree` being clamped to `source_epoch`, if that was specified
for the pipeline. Specifically it means that all files that were
created during the build will be clamped to it. This should make
builds more reproducible.
2022-12-15 13:10:35 +00:00
Christian Kellner
809c9e7828 pipeline,api: write metadata directly
Instead of transmitting stage metadata over a socket and then
writing it via `Object.meta.write`, use the latter and bind
mount the corresponding file into the stage so it can directly
be written to from the stage. Change `api.metadata` to do so,
which means that this change is transparent for the stages.
2022-12-09 12:03:40 +01:00
Christian Kellner
8b638562d1 pipeline: remove metadata from BuildResult
The metadata field became unused with the previous commit, which
uses `Object.meta` to read the metadata.
2022-12-09 12:03:40 +01:00
Christian Kellner
1205de0abb objectstore: integrate metadata object
Integrate the new `Metadata` object as `meta` property on `Object`.
Use it to actually store metadata after a successful stage run.
A new class `PathAdapter` is introduce which is in turned used to
expose the base path of `Object` as `os.PathLike` so it can be
passed as path to `Metadata`. The advantage is that any changes
to the base path in `Object` will automatically be picked up by
`Metadata`; the prominent, and currently only, case where this is
happening in `Object` is `store_tree`.
2022-12-09 12:03:40 +01:00
Christian Kellner
f8ca0cf4bc objectstore: direct path i/o for Object
The `Object.{read,write}` methods were introduced to implement
copy on write support. Calling `write` would trigger the copy,
if the object had a `base`. Additionally, a level of indirection
was introduced via bind mounts, which allowed to hide the actual
path of the object in the store and make sure that `read` really
returned a read-only path.
Support for copy-on-write was recently removed[1], and thus the
need for the `read` and `write` methods. We lose the benefits
of the indirection, but they are not really needed: the path to
the object is not really hidden since one can always use the
`resolve_ref` method to obtain the actual store object path.
The read only property of build trees is ensured via read only
bind mounts in the build root.
Instead of using `read` and `write`, `Object` now gained a new
`tree` property that is the path to the objects tree and also
is implementing `__fspath__` and so behaves like an `os.PathLike`
object and can thus transparently be used in many places, like
e.g. `os.path.join` or `pathlib.Path`.

[1] 5346025031
2022-11-21 17:26:53 +01:00
Christian Kellner
28b8252a04 objectstore: implicit clone based on object ids
If the object's id does not match with the one supplied for the
commit, we create a clone. Otherwise we store the tree.
The code path is arranged in a way that we always go through
`Object.store_tree` so we always call `Object.finalize` as a
prepration for the future, where we might actually do something
meaningful in the finalizer, like reset the *times or count the
tree size.
2022-11-16 11:09:44 +01:00
Christian Kellner
5346025031 objectstore: remove copy on write from object
Remove copy-on-write support from `objectstore.Object`. The main
reason for introducing copy-on-write was to save an additional
copy in the non DAG-pipeline model[1]. With the introduction of
the latter and the explicit `--export` option, we can achieve the
same result without the complexity of copy-on-write semantics.

[1] See commit 39213b7, part of 3b7c87d5..42a365d1 changeset.
2022-11-16 11:09:44 +01:00
Christian Kellner
3e8d2c21dc pipeline: opt out of copy-on-write for objects
When committing an object to the store, clone it if the current
stage is not the latests stage, i.e. `todo` has still entries.
This is the second step of the removal of copy-on-write support
in `Object`.
2022-11-16 11:09:44 +01:00
Christian Kellner
5bdc8d030c osbuild: auto-detect best available runner
Use the new `Index.detect_runner` method that will give us the best
available runner for a requested one. To do so a new `pipeline.Runner`
class is introduced that stores the `meta.RunnerInfo` class for the
specific runner and the original name that was requested.
In the manifest loading and describing functions of the formats, use
`Index.detect_runner` to get the `RunnerInfo` for a requested runner
and then wrap it in a `pipeline.Runner` object, which is then passed
to the `Manifest.add_pipeline` method.
See also commit "meta: ability to auto-detect runner".
Adjust all test.
2022-10-11 12:49:16 +02:00
Christian Kellner
ebf967ad1f pipeline: reformat line for readability
The line got too long.
2022-10-11 12:49:16 +02:00
Simon de Vlieger
ea6085fae6 osbuild: run isort on all files 2022-09-12 13:32:51 +02:00
Christian Kellner
ba218f781d pipeline: include mounts in stage checksum
When calculating the checksum of the stage, the mount options were
not included. This was maybe deliberate, because if the mounts of
a stage change, it is very likely that previous stages change too.
But the introduction of non-device mounts, like ostree.deployment,
have changed the setting, since the content of the tree will be
different if that mount is applied or not. And even for the device
based mounts it will change the tree if e.g. a device is mounted
at at different path but otherwise is formatted with the very same
options. In the worst case we miss a few cache hits due to changes
in the mount setup that don't lead to tree changes, but that will
rarely happen in practice.
2022-08-23 19:29:33 +01:00
Christian Kellner
f05078f66e global: fix PEP-8 formatting
This patch was generated by running `autopep8 --diff` on the
source tree and then applying the diff.
2022-08-05 09:41:05 +02:00
Simon de Vlieger
3fd864e5a9 osbuild: fix optional-types
Optional types were provided in places but were not always correct. Add
mypy checking and fix those that fail(ed).
2022-07-13 17:31:37 +02:00
Christian Kellner
7eb58ea348 inputs: introduce new input manager class
Introduce a new class to manage inputs, `InputManger` and move the
code to map inputs from the `Input` here. The main insight of why
the logic should be place here is that certain information is needed
to map inputs, independently of specific type: the path to the input
directory, `root`, the store API, `storeapi` and the service manager
instance to start the actual service. Instead of passing all this
information again and again to the `Input` class, we now have a
specialized (service) manager class for inputs that has all the
needed information all the time.
2022-06-25 02:21:17 +02:00
Christian Kellner
2d78a0bbea pipeline: separate object creation from access
Check for existing checkpoint in `Pipeline.build_stages` by trying to
get the object, instead of just checking for its existence. Later, if
no checkpoints were found, i.e. `tree` is `None`, create a new object.
This avoids mixing of new object creation and object access.
2022-06-21 15:08:32 +02:00
Christian Kellner
458e2063c9 pipeline: use deque to track stages to be built
Instead of iterating over the stages via indices, iterate over the
stages directly. To be able to do so, collect the stages that need
to be built in a deque and then drain it from the other end.
2022-06-21 15:08:32 +02:00
Christian Kellner
d70a8d6419 pipeline: always invoke monitor.finish
Also invoke `monitor.finish` when the pipeline failed to built.
There is no need to not invoke it in that case. This also will
allow us to print some information in the monitor in tha case.
2022-06-21 15:08:32 +02:00
Christian Kellner
9cb9a0d817 pipeline: simplify short circuit code
Since neither a build tree, nor the actual tree is returned from
`build_stages` the short circuit code that checks if the tree is
already present in the store, can be moved before the build tree
retrival. As a result, the short-circuit check in `Pipeline.run`
is now redundant. It was there to make sure that if we have the
tree associated with a pipeline, its build pipeline would also
not be needed. With the short-circuit now happening before the
access of the build pipeline in `build_stages` this is ensured.
2022-06-21 15:08:32 +02:00
Christian Kellner
bd28a29b85 pipeline: do not return tree from build_stages
In the previous data model the build pipelines were nested inside
the pipeline and thus we would recurse in `build_stages`. The
tree that was built was returned and potentially became the build
tree for the pipeline that invoked `build_stages`. In the new
model of a direct acyclic graph of pipelines the build tree can
be any previously built pipeline and we just get it via the store,
which now keeps track of all previously built pipelines even if
there are not committed to it. Thus there is no need to return
the trees from `build_stages` anymore.
Adjust the short code that does the short circuit check to use
`ObjectStore.contains` instead of `ObjectStore.get` since we
do not need to object anymore.
2022-06-21 15:08:32 +02:00
Christian Kellner
ba6c07f406 pipeline: remove build_tree return value
The pipeline data model used to have an assembler optionally
associated with the pipeline; therefore we had to return the
build tree used to to build the stages since the same build
tree also needed to be used from the assembler. In the "new"
model (first introduced in version 27), the assembler got
replaced by another "normal" pipeline. Since then, there is
no need to return the build tree anymore. Remove it.
2022-06-21 15:08:32 +02:00
Christian Kellner
3ab2ddd481 pipeline, fmt: use build result object internally
Instead of serializing the `BuildResult` to a dict in `build_stages`,
we keep the object and then only serialize it in the corresponding
formatting code. This doubles down on the separation between the
internal data structures and the external representation of them. It
was partially already done in the v2 format which hand-picked which
elements of the BuildResult it would return for each stage.
2022-06-14 00:15:51 +01:00
Christian Kellner
d235e4c26a pipeline: remove options from build result
Remove the stage options from the `BuildResult` object. They were
only serialized in the case of version 1 and not actually used by
Composer for anything. Use of v1 manifests should very limted now
anyway.
2022-06-14 00:15:51 +01:00
Christian Kellner
b57376d160 pipeline: drop CAP_MAC_ADMIN by default
Drop `CAP_MAC_ADMIN` from the default capabilities which is needed
to write and read(!) unknown SELinux labels. Adjust the stages
that need to read or write SELinux labels accordingly.
2022-04-27 23:05:11 +01:00
Christian Kellner
0c8f5c7ef0 pipeline: drop CAP_{NET_ADMIN,SYS_PTRACE} caps
Drop CAP_{NET_ADMIN,SYS_PTRACE} from the default capabilities which
are only needed to run bwrap from inside a stage which is done by
the `ostree.commit` and `ostree.preptree` stages, so retain them
directly there.
2022-04-27 23:05:11 +01:00
Christian Kellner
d14e5f3ee8 meta: ability to specify capabilities for stages
Add new stage metadata `CAPABILITIES` where stages can request
additional capabilities that are not in the default set.
Currently this is not used by any stage since the default set
contains the sum of all needed capabilities.
2022-04-27 23:05:11 +01:00
Christian Kellner
bdcc9ea218 pipeline: retain minimal required capabilities
Drop all capabilities that are not required by any of the stages.
N.B. at least one stage (`ostree.preptree`) itself executes bwrap
itself, which in turn needs `CAP_SYS_PTRACE` and `CAP_NET_ADMIN`.
2022-04-27 23:05:11 +01:00
Alexander Larsson
d57eeb38b9 Pass source-epoch to stages only if set
The client side does meta.get("source-epoch", default), but for
this to work we need to have the key unset if not specified,
but currently we set it to None.

Also, make sure the check for "not None" is explicit, because
we do consider a value of `0` to be a valid source-epoch.
2022-02-09 09:58:49 +01:00
Alexander Larsson
0ab4a6d401 Pipeline: Pass down the source-epoch to stages via the meta key
This can be used by stages that wish to support more reproducible
builds.
2022-02-09 09:58:49 +01:00
Alexander Larsson
b31c91d671 v2: Add source-epoch key in pipeline declaration and pass to buildroot
If this is set it is passed down to all stages and set as
SOURCE_DATE_EPOCH in the buildroot environment. This implements
the spec at:
  https://reproducible-builds.org/docs/source-date-epoch/
2022-02-09 09:58:49 +01:00
Christian Kellner
73dd612cad pipeline: fix small whitespace issue
David, where are you? Gotta do all those myself now.
2021-12-07 09:47:01 +00:00
Christian Kellner
70634d7578 pipeline: rename stage_timeout in Stage.run
Rename the `stage_timeout` paramter for the `Stage.run` method to
just `timeout`. It is clear from the context that this is the
stage timeout now.
2021-12-07 09:47:01 +00:00