Commit graph

3495 commits

Author SHA1 Message Date
Christian Kellner
51a396e3f1 disk: implement Entity interface
Implement the base type of the new entity system, i.e. `Entity`,
for all relevant components:
 - PartitionTable
 - Partition
 - Filesystem

Co-Authored-By: Achilleas Koutsou <achilleas@koutsou.net>
2022-02-22 19:23:41 +00:00
Christian Kellner
37e6fa8b95 disk: add entity-based interfaces and types
Add a generic entity data model that can be used to navigate and operate
on any specific disk image layout. Since the latter allows for arbitrary
nesting of different container types, such as LUKS2, LVM2, and with file
systems that can have sub-volumes, the entity model is very generic.

Co-Authored-By: Achilleas Koutsou <achilleas@koutsou.net>
2022-02-22 19:23:41 +00:00
Achilleas Koutsou
22b8b671a8 disk: move Partition and methods to separate file
Split up disk.go into smaller more manageable pieces: finish
by moving `Partition` to its own file.

Co-Authored-By: Christian Kellner <christian@kellner.me>
2022-02-22 19:23:41 +00:00
Achilleas Koutsou
53795c3dad disk: move Filesystem and methods to separate file
Split up disk.go into smaller more managable pieces: continue
with moving `Filesystem` to its own file.

Co-Authored-By: Christian Kellner <christian@kellner.me>
2022-02-22 19:23:41 +00:00
Achilleas Koutsou
e7827b4b97 disk: move PartitionTable and methods to separate file
Split up disk.go into smaller more managable pieces: start with
extracting `PartitionTable` and all its methods to a new file.

Co-Authored-By: Christian Kellner <christian@kellner.me>
2022-02-22 19:23:41 +00:00
Christian Kellner
dec5a3850c disk: use bytes instead of sectors in all code
Use bytes internally everywhere and convert to sectors only when writing
the options for the stages.

Changed the AlignUp() method to not do the alignment if the input is
already aligned.  This changes the behaviour when the size is 0, but
that's not a realistic use case.  Updated unit tests to match.

Manifests are unaffected.

Co-Authored-By: Christian Kellner <christian@kellner.me>
2022-02-22 19:23:41 +00:00
Christian Kellner
abaadf95ed disk: dynamically calculate header & footer
Instead of just reserving a fixed amount of sectors for the
partition header and footer, calculate the size of the
header and footer dynamically when the layout is GPT.
2022-02-22 19:23:41 +00:00
Christian Kellner
b65ef74cb2 disk: honour maximum number of partitions
Return an error if the maximum numbers of partitions has been
reached and thus creating further partitions would result in
errors.
Currently we limit MBR partition types to 4 as we dont support
logical partitions and GPT layouts to 128. According to the
UEFI specificatio (2.8) a minimum of 16384 bytes are reserved
for the partition entries array. Each entry is 128 bytes wide
thus resulting in at least 128 entries; we choose this to be
the maximum as well for now.
2022-02-22 19:23:41 +00:00
Christian Kellner
2ee3fd31a1 distro: define PartitionType method on ImageType
This is needed so that we can do different things depending on the 
given layout; this will be used in tests for now only. Only GPT
allows for arbitrary number of partitions and once we assert this
in code we will need to adjust the tests accordingly.

NB: This method might be removed again in the future, once generic
LVM support is added everywhere and the ability to differentiate 
between MBR and GPT layouts is not needed anymore.
2022-02-22 19:23:41 +00:00
Christian Kellner
c64e3149aa distro/*: handle image size internally
Do not rely on `distro.imageOptions` having any size information,
i.e. `Size` being `0`. Instead use `imageType.Size()` and the
information in the blueprint customization to calculate the size.
This makes the individual distro definitions idenpendent of the
API entry points that currently calculate the size, e.g.:
  internal/cloudapi/v1/v1.go:PostCompose line 184
  internal/cloudapi/v2/v2.go:PostCompose line 197
  internal/kojiapi/server.go:PostCompose line 135
  internal/weldr/api.go:composeHandler line 2289
2022-02-22 19:23:41 +00:00
Christian Kellner
1dbd2bc364 disk: use new alignment helper to align partitions
Align partitions during their re-layout. Specifically, we align the
first partition which removes the need for the hard coded magic
number of 2048, which represents the proper alignment for a grain
size of 1MB given a sector size of 512 (our setup).

NB: Since all our partitions should sizes that are themselves
aligned, i.e. evenly dividable by the default grain (1MB) this
will not actually change any manifest.
2022-02-22 19:23:41 +00:00
Christian Kellner
930633c249 disk: add alignment helper
Add a utility method that can be used to align data to the next "grain"
which is currently defined as 1 MiB -- the default used by sfdisk.

Add corresponding tests.
2022-02-22 19:23:41 +00:00
Christian Kellner
b7abef54e8 disk: calculate padding for secondary GPT header
Instead of hard coding a padding of 100 sectors for all layouts, i.e.
MBR and GTP, adjust the needed space depending on the layout: for MBR 
we don't need to reserve any space at all since it does not have a 
secondary header. For GTP we reserve 33 sectors, as indicated in the
UEFI specific, which allows for the header itself and up to 128 entries.
To not modify the layout of already released distributions, like RHEL
8.4 and 8.5, a new member called `ExtraPadding` is added to `Partition
Table` and then used in the corresponding layouts to preserve the
existing padding of 100.
2022-02-22 19:23:41 +00:00
Christian Kellner
b3c769ae02 disk: grow root partition while re-layouting
Instead of growing the root partition in `CreatePartitionTable` do it
as part of `updatePartitionStartPointOffsets`.
2022-02-22 19:23:41 +00:00
Christian Kellner
16ad1211c3 disk: ensure there is enough space for all parts
The old calculation was wrong since it compared sectors and bytes.
2022-02-22 19:23:41 +00:00
Christian Kellner
6db5a7d6a8 disk: fix order of expected size in test
The method assert.GreaterOrEqual(t, a, b) asserts that a >= b,
but the arguments were (expected, actual), which is the wrong
way around since we want to assure that the actual size is at
least the expected size, i.e. actual >= expected and thus the
argument should be (actual, expected).

The partition table size (pt.Size) is in sectors while our checks and
customizations are in bytes, so we need to convert when comparing.

Co-Authored-By: Achilleas Koutsou <achilleas@koutsou.net>
2022-02-22 19:23:41 +00:00
Christian Kellner
b6cece8b28 disk: ability to grow existing partitions
Apply the minimum size specified in the file system customizations 
also to existing partitions. Specifically, this now allows to set
a minimum size also for the root partition.
2022-02-22 19:23:41 +00:00
Christian Kellner
97754a2c99 disk: add EnsureSize helper
Ensure the partition has at least the given size. Will do nothing
if the partition is already larger. Returns if the size changed.
2022-02-22 19:23:41 +00:00
Christian Kellner
e7dbe60622 disk: add find partition for mountpoint helper 2022-02-22 19:23:41 +00:00
Christian Kellner
9746a87609 disk: move createFilesystem to disk.go
Move the `createFilesystem` method over the `disk.go` and make it
a public method of `PartitionTable`.
2022-02-22 19:23:41 +00:00
Christian Kellner
7e4097fb6f disk: sector size can now be per partition table
Allow the sector size to be specified on the partition table level by
introducing a new `SectorSize` field. Modify the conversion helpers
to use that new field with a fallback to default sector size in case
the field is `0`.
2022-02-22 19:23:41 +00:00
Christian Kellner
aa2825d296 disk: use BytesToSectors in customization.go
Use the newly introduced conversion helper to convert between bytes
and sectors.
2022-02-22 19:23:41 +00:00
Christian Kellner
f5592bd14a disk: add bytes ↔ sectors conversion helper
Add simple helper methods that convert between bytes and sectors. This
is a method of `PartitionTable`, since the sector size can in theory
be per partition table and this prepares for that case.
2022-02-22 19:23:41 +00:00
Christian Kellner
115c864f93 disk: define the default sector size constant
Move the `sectorSize` constant, defined in `customizations.go`
to `disk.go` as `DefaultSectorSize`. Rename current usages of
the former to the latter.
2022-02-22 19:23:41 +00:00
Christian Kellner
199463547e disk: CreatePartitionTable can return errors now
Modify the signature of `CreatePartitionTable` so that it is
possible to return errors from the function. This is not yet
used, but will be in the near future. Change all call sites
accordingly: in most cases we can just bubble up the error.
2022-02-22 19:23:41 +00:00
Christian Kellner
4086bf8dbc disk: add more docs for fields
Complete the docs for fields of `PartitionTable` and `Partition`.
2022-02-22 19:23:41 +00:00
Christian Kellner
d9ef268809 disk: use GenerateUUIDs in CreatePartitionTable
Instead of generating the UUIDs directly when new partitions are
created and separately for the boot and root partition, use the
new `PartitionTable.GenerateUUIDs` method to generate all UUIDs
that are missing in one go. Since this changes the order in
which the uuids are generated the test manifests UUIDs changed
and needed to be updated:
I used to following patch to get the updated manifests:

--- a/internal/distro/distro_test_common/distro_test_common.go
+++ b/internal/distro/distro_test_common/distro_test_common.go
@@ -105,6 +105,12 @@ func TestDistro_Manifest(t *testing.T, pipelinePath string, prefix string, regis
                                require.NoError(t, err)

                                diff := cmp.Diff(expected, actual)
+                               if diff != "" {
+                                       tt.Manifest = got
+                                       data, _ := json.MarshalIndent(tt, "", "  ")
+                                       path := filepath.Join("/tmp", filepath.Base(fileName))
+                                       _ = ioutil.WriteFile(path, data, 0644)
+                               }
                                require.Emptyf(t, diff, "Distro: %s\nArch: %s\nImage type: %s\nTest case file: %s\n", d.Name(), arch.Name(), imageType.Name(), fileName)
                        }
                })

And the following fish snippet to update the existing ones, using the
jq and sponge utilities:

for file in /tmp/rhel_85-*.json
  set filename (basename $file)
  jq -s '.[0].manifest = .[1].manifest | .[0]' test/data/manifests/$filename /tmp/$filename | sponge test/data/manifests/$filename
end
2022-02-22 19:23:41 +00:00
Christian Kellner
58112e7152 disk: add GenerateUUIDs helper
Add a new helper to `PartitionTable` that generates all necessary
uuids for uuid fields that are empty but should not. These are
the file system uuids and, in case of a GPT layout, partition ids.
2022-02-22 19:23:41 +00:00
Christian Kellner
3e72e5aa1d disk: pass basePartitionTable as pointer
Pass the `basePartitionTable` argument of `CreatePartitionTable`.
Now that we clone the partition table at the beginning of the
method there is no need to pass a copy of the partition table.
2022-02-22 19:23:41 +00:00
Christian Kellner
2280a55e71 distro: use PartitionTable.ContainsMountpoint
Use the new helper instead of re-defining it in the distro tests.
2022-02-22 19:23:41 +00:00
Christian Kellner
4f474f1661 disk: introduce ContainsMountpoint helper
Simple wrapper around FindFilesystemForMountpoint that will
return a boolean if a filesystem with the given mountpoint
is defined in the partition table.
2022-02-22 19:23:41 +00:00
Christian Kellner
37d912529c disk: add ForEachFilesystem helper
Add helper that iterates over all filesystems in the partition
table and calls the callback on each one.
Add simple checks for it as well.
2022-02-22 19:23:41 +00:00
Christian Kellner
74f6c59c93 disk: remove RootPartitionIndex
This method was only used by `updateRootPartition` which got
removed as well so this method is unused now.
2022-02-22 19:23:41 +00:00
Christian Kellner
fb7f92aa95 disk: clone partition table before modifying it
The partition table is modified `CreatePartitionTable`, which is
not a problem for the table itself since it is currently passed
by value. However, all shallow copies share the same file system
pointers and `CreatePartitionTable` will modify those as well.
As there is a data race where two concurrent thread modify the
content of the Fileystem object at the same time before writing
the uuids out to the manifest via the stage options and thus the
resulting manifest would be broken.
Therefore we use the new `Clone` methods to make a dee@ copy of
the `PartitionTable` object in the `CreatePartitionTable` method;
This will allow us to pass the `basePartitionTable` object by val
and also return the resulting `PartitionTable` as a pointer.
2022-02-22 19:23:41 +00:00
Christian Kellner
d7df6b3d5c disk: add Clone helpers
Add `Clone` methods to Filesystem and PartitionTable. This can be
used to create a new PartitionTable that should be modified based
on the original.
2022-02-22 19:23:41 +00:00
Christian Kellner
34781214cf disk: methods of Filesystem take it by ref
Convert all methods of `Filesystem` to pass it by reference
not by value.
2022-02-22 19:23:41 +00:00
Christian Kellner
5bf4892077 disk: use pointer receiver for PartitionTable
The `PartitionTable` object contains an array of `Partitions`, which
is shared among all shallow copies of `PartitionTable` instances, as
when it is used via a value receiver in method calls. The individual
objects are thus not fully isolated since modifications of array
elements, or in some cases modifications to the array itself, are
shared and visible between all shallow `PartitionTable` copies. Thus
use a pointer receiver for all methods of `PartitionTable` to make
it explicit that modifications will affect other objects.
2022-02-22 19:23:41 +00:00
Christian Kellner
d415d57f95 disk: create{Partition -> Filesystem}
What this function is actually doing is to create a filesystem,
together with a new partition; for LVM that filesystem could
also be created on a new logical volume though.
2022-02-22 19:23:41 +00:00
Christian Kellner
5693045916 disk: createPartition now appends also it
It makes sense that the function that creates the partition also
adds it to the partition table.
2022-02-22 19:23:41 +00:00
Christian Kellner
147e0c966b disk: remove updateRootPartition
The previous commit made sure that `PartitionTable.RootPartition`
is indeed returning the pointer partition object inside the array
of the `PartitionTable`. Thus changes to the returned object will
now directly affect the object and thus there is no need to call
`PartitionTable.updateRootPartition` anymore.
2022-02-22 19:23:41 +00:00
Christian Kellner
6333d54091 disk: return the correct ptr from RootPartition
When we iterate over the partitions to find the root partition,
we are getting the partition by value so even if we return a
pointer to that then, it is actually a pointer duplicated object.
Return the pointer to the actual partition object instead.
2022-02-22 19:23:41 +00:00
Christian Kellner
c8efc7d282 disk: create file system accessors and use those
In various places we are interested in the root and boot file-
systems. Currently those were accessed via by retrieving the
partition that contain them and the accessing the filesystem
member. Add accessors to `PartitionTable` that directly return
the needed filesystem. This will help if the file system is
stored inside a container like LVM or LUKS instead of directly
on a partition.
2022-02-22 19:23:41 +00:00
Sanne Raymaekers
d589317dcb internal/cloudapi: Log error in manifest job 2022-02-22 14:06:05 +01:00
Djebran Lezzoum
d8fdb03373 dnf-json: Add repo_id to dump package.
The dump function will be used to search packages and as we are implementing third party repositories, adding the repo_id of the package will allow us to identify the package repository used.
2022-02-21 15:46:53 +01:00
Sanne Raymaekers
c4ecbea510 internal/cloud: Allow aws creds from defaults
Defaults according to https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config:
Defaults to a chain of credential providers to search for credentials in
environment variables, shared credential file, and EC2 Instance Roles.

If nothing is specified fall back to whatever instance role.
2022-02-21 15:43:53 +01:00
Ondřej Budai
17e809b5f7 worker: use default transport instead of "blank" one
This allows us to use the default behaviour of http.DefaultTransport
to honor HTTP_PROXY.

Signed-off-by: Ondřej Budai <ondrej@budai.cz>
2022-02-21 14:46:49 +01:00
Jakub Rusz
f0f80bd930 ci: update terraform SHA
This brings AWS internal subnet balancing which allows to double our CI
runners in AWS.
2022-02-21 12:21:13 +01:00
Jakub Rusz
f9fb593da3 ci: large runners for some ostree tests
The longer running ostree tests (all except ostree.sh) benefit from
running on large runners because of their long runtime. Changing all to
large runners. Should not be a problem with our increased Openstack
quota.
2022-02-21 12:02:55 +01:00
Tom Gundersen
bb486bcccb cloudapi/v2/compose: don't overwrite customizations struct
The customizations struct contains different kinds of customizations,
such as users and filesystems. If both filesystems and users are
configured, the current code overwrites the user configuration.

Change this by unconditionally allocating the customizations struct
when creating the empty blueprint, and ammending it for each
customization we find.

This means that the customizations will be non-nil, also when it is
empty, which was not the case in the past. This should not change
the behavior of the code.
2022-02-19 11:13:55 +00:00
Tom Gundersen
351d06aecf tests/cases/api.sh: make /var at least 256MB
We (mistakenly) don't enforce a minimum size for /var,
so setting it to 1024 (1kB) causes the image build to fail.

CI does not expose this in a helpful way at the moment,
so this is a bit tricky to debug.

Also skip customizations for the AWS.S3 upload type. Not all the
image types with this upload type support filesystem customizations
and that's as expected. We could make a more fine-grained test in
the future, but testing with a coulpe of targets should be
sufficient.
2022-02-19 11:13:55 +00:00