Commit graph

59 commits

Author SHA1 Message Date
Christian Kellner
f67a649805 assembler/qemu: support partition names (gpt)
The GPT (GUID Partition Table) standard for partition layout supports
giving partition a name in the Partition object as well as in the
option for the qemu stage when specifying the partition layout.
2019-12-18 20:45:54 +01:00
Christian Kellner
1ea04d803f assembler/qemu: mkfs_for_type → Filesystem.make_at
Make mkfs_for_type a member of Filesystem (as 'make').
2019-12-18 20:45:54 +01:00
Christian Kellner
dc25fb3e42 assembler/qemu: helper to root fs partition
Introduce a method on the PartitionTable that returns the partition
containing the root filesystem. NB: this does not have to be the
first partition (which could be the EFI partition, or something
else), so we have to iterate through the partitions until we find
it.
2019-12-18 20:45:54 +01:00
Christian Kellner
5ee68aef30 assembler/qemu: Partition{Table} & Filesystem objs
Instead of having dictionaries representing the partition table,
partitions and filesystems together with some functions operating
on them, have proper python objects with methods. In the future
these objects could be extract and properly tested as well.
2019-12-18 20:45:54 +01:00
Christian Kellner
c77313079b assembler/qemu: add filesystem label support
Add a (optional) property call `label` to the `filesystem` object to
support labeling the filesystem. Add the label for the ESP to both
UEFI examples.
2019-12-12 17:25:47 +01:00
Christian Kellner
accef40124 assembler/qemu: support ESP partitions
Add mkfs_vfat and hook it up into the generic mkfs_for_type()
dispatcher function. Install grub2 to the MBR only if the partition
table is of type "MBR".
2019-12-12 17:25:47 +01:00
Christian Kellner
5eb4ceff2f assembler/qemu: support generic partition layouts
Introduce two new assembler options `pttype` and `partitions` to
allow fine grained control over how the partition table is created.
The first one controls the partition type, either `mbr` (default,
when the key is missing) or `gpt`; if specified the `partitions`
key must contain a list of objects describing the individual
partitions (`start`, `size`, `type`) together with a `filesystem`
object describing the filesystem (`type`, `uuid`, `mountpoint`) to
be created on that partition.
In the case the `pttype` option is missing, the legacy mode is used
where `root_fs_uuid` and `root_fs_type` need to be specified.
2019-12-12 17:25:47 +01:00
Christian Kellner
9688859acf assembler/qemu: install_grub uses partitions
Use the newly available partition information in the install_grub2
method: detect which module to use for the root filesystem and
assert the second stage fits between the MBR and the first partition.
2019-12-12 17:25:47 +01:00
Christian Kellner
9863b5ad10 assembler/qemu: refactor fs creation & mounting
Introduce a generic mkfs_for_type() function that will dispatch
to the correct mkfs function depending on the type. Additionally
refactor the partition creation and mounting code to handle more
than one partition.
2019-12-12 17:25:47 +01:00
Christian Kellner
9b9c604ab7 assembler/qemu: refactor partition table code
Part of the refactoring to support uefi/gpt: the method that creates
the partition table now returns an array of dictionaries corresponding
to the individual partitions that have been created together with the
information for the filesystem that this partition should end up with.
2019-12-12 17:25:47 +01:00
Christian Kellner
b85e8ea673 assembler/qemu: refactor to prepare for uefi/gpt
Prepare the stage for uefi/gpt support by extracting the code that
installs GRUB and creates the partitions into its own functions.
Should not have any effect on the actual data written to the image.
2019-12-12 17:25:47 +01:00
Lars Karlitski
e590dee93b assemblers/tar: fix compression
Commit 283281f broke compression by appending the argument last to the
tar command line. It needs to appear before the file.

Fix that and add a test.

[teg: add minor fix]
2019-12-10 12:07:08 +01:00
Lars Karlitski
2a1f49c8fa assemblers/qemu: add raw.xz format
Amazon images are sometimes delivered as `raw.xz` format.

Use compression level of `-0`, which seems to be what Red Hat is using
for cloud images.
2019-11-28 00:51:16 +01:00
Lars Karlitski
40cd95dbf3 assemblers/qemu: clarify extra_args 2019-11-28 00:51:16 +01:00
Lars Karlitski
8c02636bae assemblers/rawfs: add support for xfs
This introduces the `root_fs_type` option on the org.osbuild.rawfs
assembler. It only accepts "ext4" and "xfs" values right now and
defaults to "ext4" to preserve backwards compatibility.
2019-11-24 15:12:23 +01:00
Lars Karlitski
2437bb6196 assemblers/qemu: add support for xfs
This introduces the `root_fs_type` option on the org.osbuild.qemu
assembler. It only accepts "ext4" and "xfs" values right now and
defaults to "ext4" to preserve backwards compatibility.
2019-11-24 15:12:23 +01:00
Martin Sehnoutka
a253aedbc2 remove the resize, leave only vpc support and options 2019-11-23 19:35:19 +01:00
Martin Sehnoutka
459a25bba7 Support for vpc format in qemu assembler (fixes #164) 2019-11-23 19:35:19 +01:00
Will Woods
6164b38fb9 Add STAGE_DESC, STAGE_INFO, and STAGE_OPTS to stages
This commit adds semi-structured documentation to all osbuild stages and
assemblers. The variables added work like this:

* STAGE_DESC: Short description of the stage.
* STAGE_INFO: Longer documentation of the stage, including expected
              behavior, required binaries, etc.
* STAGE_OPTS: A JSON Schema describing the stage's expected/allowed
              options. (see https://json-schema.org/ for details)

It also has a little unittest to check stageinfo - specifically:

1. All (executable) stages in stages/* and assemblers/ must define strings named
   STAGE_DESC, STAGE_INFO, and STAGE_OPTS
2. The contents of STAGE_OPTS must be valid JSON (if you put '{' '}'
   around it)
3. STAGE_OPTS, if non-empty, should have a "properties" object
4. if STAGE_OPTS lists "required" properties, those need to be present
   in the "properties" object.

The test is *not* included in .travis.yml because I'm not sure we want
to fail the build for this, but it's still helpful as a lint-style
check.
2019-11-13 21:47:03 +01:00
Tom Gundersen
2457635bac assemblers/qemu: simplify mkfs
Rather than relying on the offset parameter, simply run mkfs on the
loopback device which is anyway being set up. This also allows us
not to specify the size explicitly.

Before this patch mkfs would complain (uneccesarily) about the
backing file containing a partition table. This is a false positive
as the partition table is in the region of the file before the
passed offset.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-10-16 13:44:01 +02:00
Tom Gundersen
ea4a6d135e assembler/qemu/grub: don't search for the root partition
We know the root partition we want, as we are setting it up. There
is no need to search for it by filesystem UUID. This simplifies the
setup and means the level 1.5 bootloader is always the same, and
not dependent on an embedded UUID.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-10-13 12:08:08 +02:00
Lars Karlitski
2819d07296 test: test qemu assembler
Similar to the existing test, but uses qemu-nbd to mount the generated
image.

Using unittest.TestCase.subTest() for now, which means that the tests
aren't very independent. I think this is fine in this case, because
we're testing images independently from each other, reusing the base
tree in the store.
2019-10-10 18:08:58 +02:00
Lars Karlitski
eab8cbff5e assemblers/qemu: don't try to compress raw or vdi formats
qemu-img convert fails when passing `-c` to vdi or raw outputs.
2019-10-10 18:08:58 +02:00
Lars Karlitski
9fbe80722b assemblers: add org.osbuild.rawfs
This assembler outputs an image file which only contains the file
system.
2019-10-07 10:10:51 +02:00
Lars Karlitski
cb2f383601 remoteloop: make LoopClient.device a context manager 2019-10-07 10:10:51 +02:00
Lars Karlitski
0dd60b3abf remoteloop: pass filename to create_device
This makes LoopClient simpler to use in the common case.
2019-10-07 10:10:51 +02:00
Lars Karlitski
3d3ffda5d8 remoteloop: don't close a socket it didn't open
Closing the socket is the responsibility of whoever opened it.

Fix this in the only user (qemu assembler) by using socket() in a `with`
block, which closes the socket on exit.
2019-10-07 10:10:51 +02:00
Tom Gundersen
72c3157162 assemblers/qemu: replace grub2-install
Background:

grub2 works in three stages:
 - The first stage is found in the first 440 bytes of the master
   boot record, and its only purpose is to load and execute the
   second stage. This stage is static, and just copied from the rpm
   without modification.
 - The second stage is found in the gap between the MBR and the
   first partition, and may be up to 31kB in size. This stage is
   specific to the host and must contain the instructions for
   finding the right file system and subdirectory for the grub2
   config and modules on the host, as well as the modules needed
   to do this.
 - The third stage is found in the `normal` module, which loads
   grub2.conf, which in turn may load more modules and perform
   arbitrary instructions.

Problem:

grub2-install is responsible for installing all these stages on the
target image. This goes against our design, as modifications outside
the filesystem should happen in the assembler, but modifications to
the filesystem should happen in a stage. In particular, we don't
want the contents of the image to differ in any way from the output
tree that is stored in our content store (the output of our last
stage). This causes a practical problem at the moment, as our
selinux stage is ran before the assembler, and as such the grub
modules do not get selinux labels applied.

It turns out that we could split grub2-install in two as we want,
by passing `--no-bootsector` to it to install only the modules,
and copy/genereta the two first stages as files under /boot and
then run `grub2-bios-setup` to write the stages from /boot into
the image where they belong.

Regrettably, this does not work as both `grub2-install` and
`grub2-bios-setup` introspect the system and block devices they
are being run on to generate the right configuration. This is not
what we want, as we would like to specifcy the config explicitly
and run them independently of the target image. The specific bug
we get in both cases is that the canonical path containing our
object store cannot be found.

Before osbuild this was not a problem, as other installers would
instal and assemble everything directly in the target image as a
loopback device. Something we explicitly do not want to do.

Solution:

This patch essentially reimplements grub2-install, or rather the
parts of it that we need. One change in behavior from the upstream
tool is that we no longer write the level one and level two boot
loaders to /boot before moving them into place, but just write them
directly where they belong (so they do not end up on the
filesystem).

The parts that copy files into /boot are now in the grub2 installer
and the parts that write the level one/two bootloaders are in the
qemu assembler.

This achieves a few principles I think we should always adher to:
 - never run tools from the target image (no chroot)
 - don't read/copy files from the target image that was written
   by other stages. We already try to avoid sharing state, and
   by treating the image as write-only, we avoid accidentally
   sharing state through the target tree.

Based-on-suggestions-from: Javier Martinez Canillas <javierm@redhat.com>
With-god-like-debugging-and-fixes-by: Lars Karlitski <lubreni@redhat.com>
Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-10-02 15:10:37 +02:00
Tom Gundersen
816d111779 assemblers/qemu/loop: open backing file O_DIRECT
This should improve performance and save memory as we don't need two
page caches.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-10-02 15:10:37 +02:00
Tom Gundersen
f470c3f3a3 assemblers/qemu: fix the partition UUID in the pipeline
Otherwise, sfdik would pick one at random. We want our images to be
reproducible to the extent possible, so we must move all randomness
out of the assemblers when we can.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-10-02 15:10:37 +02:00
Tom Gundersen
34098bf6c6 assembler: rename qcow2 to qemu and add support for more formats
Opt in to supporting the most common ones, if we want to support more
we can add support as the need arises.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-09-29 19:05:55 +02:00
Ondřej Budai
283281f047 assemblers/tar: Allow creating tar archive without any compression
In tests we often use tar assembler as final stage. This means we
compress the image tree and decompress it right away. For this purposes
it is nice to have option to not have any compression. Actually,
this could very drastically improve CI running time.

A better option would be not to use tar at all and instead let osbuild
just dump the resulting tree. However, we felt this behaviour needs
more discussion and we need a fix asap.
2019-09-10 14:55:40 +02:00
Ondřej Budai
f78db47a0e assembler/qcow2: Move temporary image out of /tmp
Directory /tmp is hosted on tmpfs. Therefore the image size could be
limited by memory size. By moving the image to /var/tmp we assure that
the file is hosted on disk allowing us to build bigger images or build
images on memory-constrained machines (e.g. CI).
2019-09-07 08:23:03 +02:00
Lars Karlitski
2c73187046 assemblers/qcow2: Pass size explicitly
Don't try to guess how much room the filesystem will take up. In
practice, most people will want to specify a size anyway, depending on
their use case.

As is typical for osbuild, there are no convenience features for the
pipeline (it's not meant to be written manually). `size` must be given
in bytes and it must be a multiple of 512.
2019-09-01 23:04:25 +02:00
Lars Karlitski
358ef27f9f assemblers/qcow2: Don't create extra level of tmp
Assemblers are always run in their own, clean environment and can be
sure that there's only one instance of themselves running. Remove the
extra layer of temporary directory and use static names.
2019-09-01 23:04:25 +02:00
Tom Gundersen
53fe311bcd assembler/qcow2: copy the tree into the target image
We used to let mkfs.ext4 initialize the filesystem for us, but it
turns out that the metadata attributes of the root directory were
not being initialized from the source tree. In particular, this
meant that the SELinu labels were left as unconfined_t, rather
than root_t, which would not allow us to boot in enforcing mode.

An alternative approach might be to fixup the root inode manually,
while still doing the rest using mkfs.ext4, but let's leave that
for the future if it turns out to be worth it.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-08-26 09:25:42 +03:00
Tom Gundersen
fa7a5b985e travis: add an osbuild test
Actually test the tools. This simply runs a noop stage followed by
a noop assembler.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-07-31 01:34:31 +02:00
Lars Karlitski
2e0981f1ab qcow2: remove partition_table_id
It's not necessary to specify it.
2019-07-29 12:39:10 +02:00
Lars Karlitski
f4862457a3 rename io.weldr to org.osbuild (#39) 2019-07-26 09:40:55 +02:00
Tom Gundersen
a17ecd0fca stages/assemblers: symlink the osbulid python library
This way the assemblers/stages are valid in isolation, even without
osbulid installed system-wide. This would be needed to have this work
when --libdir is not the system-wide one, as the library would
otherwise not be in sys.path.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-07-25 21:28:23 +02:00
Tom Gundersen
7274847711 Assembler: no longer mount devtmpfs in the container
Move the only assembler that relied on this to use LoopClient instead.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-07-19 00:51:12 +02:00
Tom Gundersen
40dfee9855 assemblers/qcow2: don't rely on partition loopback devices
Create a loopback device for the raw partiton, rather than relying on
the partition devices the kernel puts in /dev. This requires us to
specify the part_msdos module directly as grub2-install now seems
unable to detect the partition table type.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-07-19 00:51:12 +02:00
Martin Sehnoutka
70aeaec9ed drop unused partition_table_id option completely 2019-07-17 13:08:22 +02:00
Martin Sehnoutka
f04cb3836f fix warnings generated by pylint 2019-07-17 13:08:22 +02:00
Sehny
36f20b3e48 make the compression algorithm explicit 2019-07-16 10:25:42 +02:00
Martin Sehnoutka
7a9925ec99 tar: derive compression algorithm from the file name 2019-07-15 14:52:48 +02:00
Tom Gundersen
7ea901928d assembler/qcow2: only require loopback for grub2
Create and instantiate the ext4 filesystem directly on the device, without
ever mounting it. This means that only grub2 now requires loopback devices
to function properly.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-07-11 15:01:44 +02:00
Lars Karlitski
e9fb1ded15 assemblers: resurrect io.weldr.targz
This was dropped in cebed27cd. However, a tar of a tree is useful in its
own right as an output format.
2019-07-08 14:22:56 +02:00
Tom Gundersen
cebed27cd9 osbuild: drop the concept of an input_dir
This removes the possibility of passing in arbitrary input data. We
now restrict ourselves to explicitly specified files/directories or
a base tree given by its pipeline id.

This drops the tar/tree stages/assemblers, as the tree/untree ones
are implicit in osbuild, and if we wish to also support compressed
trees, then we should add that to osbuild core as an option.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-07-03 13:11:37 +02:00
Tom Gundersen
0252f42305 assemblers/loop_dev: take the size and optionally the offset as arguments
By default the whole image file is attechd to the loopback device, but
we want to only attach a slice, namely individual partitions.

This is a noop, just adds the parameters to the helpers.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-07-01 22:18:05 +02:00