Commit Graph

35059 Commits

Author SHA1 Message Date
Peter Krempa
3ad5d7b2bb qemuBuildHostdevSCSIAttachPrepare: Use "effective node" mode for getting blockdev props
The resulting properties are identical, as the hostdev backend code
doesn't set any of the extra properties.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-11-02 15:32:08 +01:00
Peter Krempa
ec936526c2 qemuBlockStorageSourceGetBackendProps: Introduce QEMU_BLOCK_STORAGE_SOURCE_BACKEND_PROPS_EFFECTIVE_NODE
Introduce a mode where the protocol layer -blockdev will be formatted
so that it can be used as the effective node (used to access data from
the device). For this new mode we'll use
qemuBlockStorageSourceAddBlockdevCommonProps.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-11-02 15:31:51 +01:00
Peter Krempa
80494dfb74 qemu: block: Use qemuBlockStorageSourceAddBlockdevCommonProps for storage slice
Use the new helper in qemuBlockStorageSourceGetBlockdevStorageSliceProps
to format the common bits.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-11-02 15:31:40 +01:00
Peter Krempa
ce153ef2ad qemu: block: Add helper to add common properties for -blockdev configuration
The new helper replaces qemuBlockStorageSourceGetBlockdevFormatCommonProps
and the two inline instances generating the common properties for a
blockdev layer.

The new helper is to be used for both the format layer and the storage
backing layer, thus a new parameter 'effective' switches between the
modes.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-11-02 15:31:29 +01:00
Peter Krempa
84df50dc87 qemuBlockStorageSourceGetBackendProps: Unify ordering of fields
Use the same ordering of the relevant fields as we do for the format
layer -blockdev so that later they can be refactored without test
fallout.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-11-02 15:31:10 +01:00
Peter Krempa
a175dfc487 virDomainDiskGetDetectZeroesMode: Return proper type
Change the return value type to 'virDomainDiskGetDetectZeroes'.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-11-02 15:24:10 +01:00
Peter Krempa
16e57a98d0 qemuBlockStorageSourceGetBackendProps: Unify cases for '!onlytarget' and '!legacy'
At this point only a single code path (for formatting -drive for legacy
SD cards) uses the 'legacy' output and that code path doesn't populate
the node name. Thus we can unify the code block and simplify the JSON
formatters.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-11-02 15:24:09 +01:00
Andrea Bolognani
ca4cb3d7dc src: Remove duplicated VIR_REQUIRE_FLAG_GOTO() call
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-11-02 11:02:18 +01:00
Daniel P. Berrangé
e7facdca25 logging: lockdown the systemd service configuration
The 'systemd-analyze security' command looks at the unit file
configuration and reports on any settings which increase the
attack surface for the daemon. Since most systemd units are
fairly minimalist, this is generally informing us about settings
that we never put any thought into using before.

In its current configuration it reports

  # systemd-analyze security virtlogd.service
  ...snip...
  → Overall exposure level for virtlogd.service: 9.6 UNSAFE 😨

which is pretty terrible as a score.

If we apply all of the recommendations that appear possible
without (knowingly) breaking functionality it reports:

  # systemd-analyze security virtlogd.service
  ...snip...
  → Overall exposure level for virtlogd.service: 2.2 OK 🙂

which is a pretty decent improvement.

Some of the settings we would like to enable require a systemd
version that is newer than that available in our oldest distro
target - RHEL-8 at v239.

NB, RestrictSUIDSGID is technically newer than 239, but RHEL-8
backported it, and other distros we target have it by default.

Remaining recommendations are

✗ CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER)

  We block FOWNER/IPC_OWNER, but can't block the two DAC
  capabilities. Historically apps/users might point QEMU
  to log files in $HOME, pre-created with their own user
  ID.

✗ IPAddressDeny=

  Not required since RestrictAddressFamilies blocks IP
  usage. Ignoring this avoids the overhead of creating
  a traffic filter than will never be used.

✗ NoNewPrivileges=

  Highly desirable, but cannot enable it yet, because it
  will block the ability to transition to the virtlogd_t
  SELinux domain during execve. The SELinux policy needs
  fixing to permit this transition under NNP first.

✗ PrivateTmp=

  There is a decent chance people have VMs configured
  with a serial port logfile pointing at /tmp. We would
  cause a regression to use private /tmp for logging

✗ PrivateUsers=

  This would put virtlogd inside a user namespace where
  its root is in fact unprivileged. Same problem as the
  User= setting below

✗ ProcSubset=

  Libraries we link to might read certain non-PID related
  files from /proc

✗ ProtectClock=

  Requires v245

✗ ProtectHome=

  Same problem as PrivateTmp=. There's a decent chance
  that someone has a VM configured to write a logfile
  to /home

✗ ProtectHostname=

  Requires v241

✗ ProtectKernelLogs

  Requires v244

✗ ProtectProc

  Requires v247

✗ ProtectSystem=

  We only set it to 'full', as 'strict' is not viable for
  our required usage

✗ RootDirectory=/RootImage=

  We are not capable of running inside a custom chroot
  given needs to write log files to arbitrary places

✗ RestrictAddressFamilies=~AF_UNIX

  We need AF_UNIX to communicate with other libvirt daemons

✗ SystemCallFilter=~@resources

  We link to libvirt.so which links to libnuma.so which has
  a constructor that calls set_mempolicy. This is highly
  undesirable todo during a constructor.

✗ User=/DynamicUser=

  This is highly desirable, but we currently read/write
  logs as root, and directories we're told to write into
  could be anywhere. So using a non-root user would have
  a major risk of regressions for applications and also
  have upgrade implications

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2023-11-01 11:34:06 +00:00
Daniel P. Berrangé
012e70c923 src: update log/error messages pointing to old mailing list addr
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2023-10-31 10:04:25 +00:00
Peter Krempa
9ca910488c qemu: Setup host side of VDPA device for block copy
Setup the VDPA bits of the appropriate part of the image chain for block
copy.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-27 15:04:20 +02:00
Peter Krempa
98dd641e86 qemu: hotplug: Setup host side of VDPA device for disk hotplug
The code which opens the VDPA device and prepares it for FD passing was
not called in the hotplug code path, preventing hotplug of VDPA disks
with:

 error: internal error: argument key 'path' must not have null value

Use the new helper qemuProcessPrepareHostStorageDisk to setup the VDPA
definition.

Closes: https://gitlab.com/libvirt/libvirt/-/issues/539
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-27 15:04:20 +02:00
Peter Krempa
61baeb1152 qemu: process: Extract host setup of disk device into helpers
Currently the code sets up only VDPA backends but will be used later in
hotplug code too.

This patch also uses normal forward iteration in the loop in
qemuProcessPrepareHostStorage as we don't need to remove disks from the
disk list at that point.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-27 15:04:20 +02:00
Andrea Bolognani
4242a94816 meson: Rename build_tests -> tests_enabled
Given that this variable now controls not just whether C tests
are built, but also whether any test at all is executed, the new
name is more appropriate.

Update the description for the corresponding meson option
accordingly.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
2023-10-26 11:31:25 +02:00
Andrea Bolognani
87f14badd0 meson: Disable all tests when tests are disabled
Currently, passing -Dtests=disabled only disables a subset of
tests: those that are written in C and thus require compilation.
Other tests, such as the syntax-check ones and those that are
implemented as scripts, are always enabled.

There's a potentially dangerous consequence of this behavior:
when tests are disabled, 'meson test' will succeed as if they
had been enabled. No indication of this will be shown, so the
user will likely make the reasonable assumption that everything
is fine when in fact the significantly reduced coverage might
be hiding failures.

To solve this issues, disable *all* tests when asked to do so,
and inject an intentionally failing test to ensure that 'meson
test' doesn't succeed.

Best viewed with 'git show -w'.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
2023-10-26 11:31:24 +02:00
Peter Krempa
e60c3057cc qemuBlockStorageSourceGetBlockdevGetCacheProps: Return the cache object rather than appending it
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-26 09:02:23 +02:00
Peter Krempa
4cf223962a qemuDomainDiskCachemodeFlags: Simplify usage
Return whether a relevant cachemode was presented rather than returning
an error, so that callers can be simplified. Use the proper enum type as
argument rather than typecasting in the switch statement.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-26 09:02:23 +02:00
Peter Krempa
91661eb19f virStorageSource: Use proper type for shadow copies of iomode/cachemode/discard/detect_zeroes
The aforementioned fields in virStorageSource struct are copies of the
disk properties, but were not converted to the proper type yet.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-26 09:02:23 +02:00
Peter Krempa
5ac61e7c15 conf: Move definition of some disk type enums to a common header
Certain disk config fields are mirrored between the disk and storage
source definitions, but the proper types are not available for use in
the virStorageSource definition. Move them so they can be used properly.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-26 09:02:23 +02:00
Peter Krempa
01e35b452b qemuBlockStorageSourceGetBackendProps: Remove unnecessary indent for non-nbdkit code path
Formatting of the 'nbdkit' driven backend breaks out of the switch
statement so we don't need to have an unnecessary block and indentation
level for the case when nbdkit is not in use.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-26 09:02:23 +02:00
Peter Krempa
d38f32cb4e qemuBuildDriveSourceStr: Absorb only use of qemuDiskSourceGetProps
'qemuBuildDriveSourceStr' used to build the legacy -drive commandline
for SD cards is the only user of qemuDiskSourceGetProps. Move the helper
directly inline.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-26 09:02:23 +02:00
Peter Krempa
682db64417 qemu: migration: No longer avoid 'auto-read-only' option for migration
The 'auto-read-only' blockdev option is available in all supported qemu
versions so we can remove the migration hack which disabled it.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-26 09:02:23 +02:00
Andrea Bolognani
d3bdfa0911 systemd: Tweak service definitions
Use a consistent style everywhere.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-25 12:19:32 +02:00
Andrea Bolognani
e73b0a1209 systemd: Make service_extra_in/socket_extra_in required
We want at least one file to always be present, so that it can
serve as a pointer for users. Ensure that this is the case by
unconditionally using the value of the respective keys.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-25 12:19:32 +02:00
Andrea Bolognani
95e6615cd2 systemd: Set service_extra_in/socket_extra_in everywhere
It's somewhat confusing that some of the services have a
corresponding foo.service.extra.in and foo.socket.extra.in, some
have just one of the two, and some have neither.

In order to make things more approachable, make sure that both
files exists for each service.

In most cases the extra units are currently unused, so they will
just contain a comment briefly explaining their purpose and
pointing users to meson.build, where they can find more
information. The same comment is also added to the top of
extra units that already have some contents in them for
consistency.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-25 12:19:32 +02:00
Andrea Bolognani
28b85e0374 systemd: Introduce systemd_service_oomscoreadjust_extra_in
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-25 12:19:28 +02:00
Andrea Bolognani
5c83da1dfd systemd: Introduce systemd_service_limitmemlock_extra_in
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-25 12:19:26 +02:00
Andrea Bolognani
13de087237 systemd: Introduce systemd_service_tasksmax_extra_in
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-25 12:19:24 +02:00
Andrea Bolognani
3b16a13f14 systemd: Introduce systemd_service_limitnofile_extra_in
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-25 12:19:21 +02:00
Andrea Bolognani
c8ae549cd5 systemd: Accept multiple files for service_extra_in/socket_extra_in
Now that the underlying script is able to merge an arbitrary
number of units into the base template, expose this possibility
in the build system.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-25 11:42:19 +02:00
Andrea Bolognani
9b26834305 systemd: libvirtd doesn't need @sockprefix@
It uses custom templates which already hardcode the correct
value.

Signed-off-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-25 11:42:19 +02:00
Praveen K Paladugu
6be0d1a0d3 ch: support serial and console devices in parallel
Starting v18, cloud-hypervisor supports serial and console devices in
parallel. Drop related check based on ch version.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-20 13:21:17 +02:00
Praveen K Paladugu
2c1f34a2bb ch: use payload api to send kernel details
Starting with v28.0 cloud-hypervisor requires the use of "payload" api to pass
kernel, initramfs and cmdline options. Extend ch driver to use the new
api based on ch version.

Signed-off-by: Praveen K Paladugu <prapal@linux.microsoft.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-20 13:21:14 +02:00
Narayana Murty N
9df1e7d814 util:hostcpu: Report physical address size based on Architecture
The function virHostCPUGetPhysAddrSize was introduced with commit be1b7d5b18
fails on architectures other than x86 and SuperH. The commit 8417c1394c
fixed the issue only for s390 but the problem is still seen on other
architectures like ppc which does not report Physical address size in their
cpuinfo output.

command:
systemctl restart libvirtd.service
Output :
<snip>
dnsmasq[2377]: read /var/lib/libvirt/dnsmasq/default.addnhosts - 0
addresses
dnsmasq-dhcp[2377]: read /var/lib/libvirt/dnsmasq/default.hostsfile
libvirtd[3163]: libvirt version: 9.8.0
libvirtd[3163]: hostname: xxxxxxxxxx
libvirtd[3163]: internal error: Missing or invalid CPU address size in
/proc/cpuinfo
 libvirtd.service: Deactivated successfully.
 </snip>

This patch fixes this issue by returning the size=0 for architectures
other than x86 and SuperH.

Signed-off-by: Narayana Murty N <nnmlinux@linux.ibm.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-20 12:46:47 +02:00
Dmitry Frolov
8ff149516f lxc: fix lxcContainerMountAllFS() DEREF_BEFORE_CHECK
vmDef->fss[i]->src->path may be NULL,
so check is needed before passing it to VIR_DEBUG.
Also removed checking vmDef->fss[i]->src for NULL, since it may not be NULL.

Fixes: 57487085dc ("lxc: don't try to reference NULL when mounting filesystems")

Signed-off-by: Dmitry Frolov <frolov@swemel.ru>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-20 12:17:56 +02:00
Fima Shevrin
bc06cfa1cd qemu: Send event on persistent config modification
Currently, libvirt doesn't send events when devices are attached,
detached or updated. Thus, any services that listen to events are
unaware of the change to persistent config.

Signed-off-by: Fima Shevrin <efim.shevrin@virtuozzo.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-20 12:12:17 +02:00
Sergey Mironov
a97b428208 selinux: Drop dead code in virSecuritySELinuxSetImageLabelInternal()
Considering that at the virSecuritySELinuxSetFilecon() function can only
return 0 or -1 and so does the virSecuritySELinuxFSetFilecon(), the check
for '1' at the end of virSecuritySELinuxSetImageLabelInternal() is
effectively a dead code. Drop it.

Co-developed-by: sdl.qemu <sdl.qemu@linuxtesting.org>
Signed-off-by: Sergey Mironov <mironov@fintech.ru>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
2023-10-20 10:44:38 +02:00
Peter Krempa
11839c8cc1 conf: Rename 'nodeformat' field of virStorageSource to 'nodenameformat'
While the name itself doesn't matter, this rename is done to prove that
all places using 'nodeformat' were converted to the appropriate
accessors.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:18 +02:00
Peter Krempa
e0e834a55d qemu: driver: Use 'format' nodename accessors for disk resize
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:17 +02:00
Peter Krempa
8848362196 qemu: migration: Use 'format' nodename accessors in dirty bitmap migration
The persistent bitmaps are stored in the format layer, using 'effective'
bitmap name is the most reasonable approach in this case.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:17 +02:00
Peter Krempa
032edf2f11 qemu: Convert migration setup code to use 'format' layer node name accessors
The blockjob, NBD export and setup of the cookie data all care about the
effective nodename.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:17 +02:00
Peter Krempa
1baf16fe04 qemu: command: Use 'format' nodename accessors for 'pflash' backend setup
The frontend device needs to access the blocks directly so it cares
about the effective nodename.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:17 +02:00
Peter Krempa
abab5130f8 qemu: Use 'format' nodename accessors for block dirty bitmap operations
In most cases the bitmap operations are relevant only on qcow2 images
thus the 'format' layer will be present. Although in certain specific
cases temporary bitmaps can be created on top of other images as well,
thus we use the 'effective' bitmap name in all cases for bitmap
operations.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:17 +02:00
Peter Krempa
ac6cd5869a qemu: driver: Convert disk stats code to use 'format' nodename accessors
I case of statistics we're interested in the statistics of the effective
bitmap whatever it happens to be.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:17 +02:00
Peter Krempa
6eb41dff95 qemu: Convert disk backend setup code to use 'format' nodename accessors
The disk backend setup code is concerned only about the effective
nodename. Doing this conversion will also simplify further changes
needed to drop the 'raw' layer in cases when it's not really needed.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:17 +02:00
Peter Krempa
c888784a24 qemu: domain: Use 'format' layer node name accessors for nodename setup code
The code setting the nodenames needs to use the 'true' nodename of the
format layer.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:17 +02:00
Peter Krempa
67600bd00d qemu: block: Use 'format' nodename accessors in '-blockdev' setup code
Convert the main -blockdev JSON object setup code to use the new
accessors. In these we use mainly the real 'format' layer node name.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:17 +02:00
Peter Krempa
90fc8ef2a3 qemu: blockjob: Use 'format' nodename accessors for job naming
Use the effective nodename for naming the job as we use that one now.
It doesn't matter too much which one we pick, because it's used just for
the name of the job, which we preserve in the status XML.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:17 +02:00
Peter Krempa
47bd985ebb qemu: backup: Use format nodename accessors
Both modified cases in this patch require the effective nodename as they
deal with the data being backed up.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:16 +02:00
Peter Krempa
11567c1e50 qemuBlockStorageSourceGetFormatProps: Use new frontend name accessor
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
2023-10-17 14:16:16 +02:00