mirror of
https://github.com/systemd/systemd
synced 2024-10-06 16:21:34 +00:00
repart: make it easy to generate DDIs
This adds --make-ddi=confext, --make-ddi=sysext, --make-ddi=portable, to make it really easiy to generate DDIs of the specified class. It it's ultimately just a fancy wrapper around some defaults and in particular --definitions=. This makes it very easy to generate a confext: $ systemd-repart -C --private-key=privkey.pem --certificate=cert.crt -s mytree/ mytree.confext.raw
This commit is contained in:
parent
607343a1ac
commit
a121b331e3
|
@ -516,6 +516,47 @@
|
|||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--make-ddi=</option><replaceable>TYPE</replaceable></term>
|
||||
|
||||
<listitem><para>Takes one of <literal>sysext</literal>, <literal>confext</literal> or
|
||||
<literal>portable</literal>. Generates a Discoverable Disk Image (DDI) for a system extension
|
||||
(sysext, see
|
||||
<citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
for details), configuration extension (confext) or <ulink
|
||||
url="https://systemd.io/PORTABLE_SERVICES">portable service</ulink>. The generated image will consist
|
||||
of a signed Verity <literal>erofs</literal> file system as root partition. In this mode of operation
|
||||
the partition definitions in <filename>/usr/lib/repart.d/*.conf</filename> and related directories
|
||||
are not read, and <option>--definitions=</option> is not supported, as appropriate definitions for
|
||||
the selected DDI class will be chosen automatically.</para>
|
||||
|
||||
<para>Must be used in conjunction with <option>--copy-source=</option> to specify the file hierarchy
|
||||
to populate the DDI with. The specified directory should contain an <filename>etc/</filename>
|
||||
subdirectory if <literal>confext</literal> is selected. If <literal>sysext</literal> is selected it
|
||||
should contain either a <filename>usr/</filename> or <filename>opt/</filename> directory, or both. If
|
||||
<literal>portable</literal> is used a full OS file hierarchy can be provided.</para>
|
||||
|
||||
<para>This option implies <option>--empty=create</option>, <option>--size=auto</option> and
|
||||
<option>--seed=random</option> (the latter two can be overriden).</para>
|
||||
|
||||
<para>The private key and certificate for signing the DDI must be specified via the
|
||||
<option>--private-key=</option> and <option>--certificate=</option> switches.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-S</option></term>
|
||||
<term><option>-C</option></term>
|
||||
<term><option>-P</option></term>
|
||||
|
||||
<listitem><para>Shortcuts for <option>--make-ddi=sysext</option>,
|
||||
<option>--make-ddi=confext</option>, <option>--make-ddi=portable</option>,
|
||||
respectively.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
<xi:include href="standard-options.xml" xpointer="version" />
|
||||
<xi:include href="standard-options.xml" xpointer="no-pager" />
|
||||
|
@ -530,13 +571,41 @@
|
|||
<para>On success, 0 is returned, a non-zero failure code otherwise.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Example</title>
|
||||
|
||||
<example>
|
||||
<title>Generate a configuration extension image</title>
|
||||
|
||||
<para>The following creates a configuration extension DDI (confext) for an
|
||||
<filename>/etc/motd</filename> update.</para>
|
||||
|
||||
<programlisting>mkdir tree tree/etc tree/etc/extension-release.d
|
||||
echo "Hello World" > tree/etc/motd
|
||||
cat > tree/etc/extension-release.d/extension-release.my-motd <<EOF
|
||||
ID=fedora
|
||||
VERSION_ID=38
|
||||
IMAGE_ID=my-motd
|
||||
IMAGE_VERSION=7
|
||||
EOF
|
||||
systemd-repart -C --private-key=privkey.pem --certificate=cert.crt -s tree/ /var/lib/confexts/my-motd.confext.raw
|
||||
systemd-confext refresh</programlisting>
|
||||
|
||||
<para>The DDI generated that way may be applied to the system with
|
||||
<citerefentry><refentrytitle>systemd-confext</refentrytitle><manvolnum>1</manvolnum></citerefentry>.</para>
|
||||
</example>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para>
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>repart.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
<citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>portablectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd-sysext</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ systemdstatedir = localstatedir / 'lib/systemd'
|
|||
catalogstatedir = systemdstatedir / 'catalog'
|
||||
randomseeddir = localstatedir / 'lib/systemd'
|
||||
profiledir = libexecdir / 'portable' / 'profile'
|
||||
repartdefinitionsdir = libexecdir / 'repart/definitions'
|
||||
ntpservicelistdir = prefixdir / 'lib/systemd/ntp-units.d'
|
||||
credstoredir = prefixdir / 'lib/credstore'
|
||||
|
||||
|
|
15
src/partition/definitions/confext.repart.d/10-root.conf
Normal file
15
src/partition/definitions/confext.repart.d/10-root.conf
Normal file
|
@ -0,0 +1,15 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Partition]
|
||||
Type=root
|
||||
Format=erofs
|
||||
CopyFiles=/etc/
|
||||
Verity=data
|
||||
VerityMatchKey=root
|
|
@ -0,0 +1,13 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Partition]
|
||||
Type=root-verity
|
||||
Verity=hash
|
||||
VerityMatchKey=root
|
|
@ -0,0 +1,13 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Partition]
|
||||
Type=root-verity-sig
|
||||
Verity=signature
|
||||
VerityMatchKey=root
|
15
src/partition/definitions/portable.repart.d/10-root.conf
Normal file
15
src/partition/definitions/portable.repart.d/10-root.conf
Normal file
|
@ -0,0 +1,15 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Partition]
|
||||
Type=root
|
||||
Format=erofs
|
||||
CopyFiles=/
|
||||
Verity=data
|
||||
VerityMatchKey=root
|
|
@ -0,0 +1,13 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Partition]
|
||||
Type=root-verity
|
||||
Verity=hash
|
||||
VerityMatchKey=root
|
|
@ -0,0 +1,13 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Partition]
|
||||
Type=root-verity-sig
|
||||
Verity=signature
|
||||
VerityMatchKey=root
|
15
src/partition/definitions/sysext.repart.d/10-root.conf
Normal file
15
src/partition/definitions/sysext.repart.d/10-root.conf
Normal file
|
@ -0,0 +1,15 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Partition]
|
||||
Type=root
|
||||
Format=erofs
|
||||
CopyFiles=/usr/ /opt/
|
||||
Verity=data
|
||||
VerityMatchKey=root
|
|
@ -0,0 +1,13 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Partition]
|
||||
Type=root-verity
|
||||
Verity=hash
|
||||
VerityMatchKey=root
|
|
@ -0,0 +1,13 @@
|
|||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
[Partition]
|
||||
Type=root-verity-sig
|
||||
Verity=signature
|
||||
VerityMatchKey=root
|
|
@ -48,3 +48,15 @@ executables += [
|
|||
'install' : have_standalone_binaries,
|
||||
},
|
||||
]
|
||||
|
||||
if conf.get('ENABLE_REPART') == 1
|
||||
install_data('definitions/confext.repart.d/10-root.conf', install_dir : repartdefinitionsdir / 'confext.repart.d')
|
||||
install_data('definitions/confext.repart.d/20-root-verity.conf', install_dir : repartdefinitionsdir / 'confext.repart.d')
|
||||
install_data('definitions/confext.repart.d/30-root-verity-sig.conf', install_dir : repartdefinitionsdir / 'confext.repart.d')
|
||||
install_data('definitions/portable.repart.d/10-root.conf', install_dir : repartdefinitionsdir / 'portable.repart.d')
|
||||
install_data('definitions/portable.repart.d/20-root-verity.conf', install_dir : repartdefinitionsdir / 'portable.repart.d')
|
||||
install_data('definitions/portable.repart.d/30-root-verity-sig.conf', install_dir : repartdefinitionsdir / 'portable.repart.d')
|
||||
install_data('definitions/sysext.repart.d/10-root.conf', install_dir : repartdefinitionsdir / 'sysext.repart.d')
|
||||
install_data('definitions/sysext.repart.d/20-root-verity.conf', install_dir : repartdefinitionsdir / 'sysext.repart.d')
|
||||
install_data('definitions/sysext.repart.d/30-root-verity-sig.conf', install_dir : repartdefinitionsdir / 'sysext.repart.d')
|
||||
endif
|
||||
|
|
|
@ -163,6 +163,7 @@ static Architecture arg_architecture = _ARCHITECTURE_INVALID;
|
|||
static int arg_offline = -1;
|
||||
static char **arg_copy_from = NULL;
|
||||
static char *arg_copy_source = NULL;
|
||||
static char *arg_make_ddi = NULL;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
|
||||
|
@ -177,6 +178,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_filter_partitions, freep);
|
|||
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_copy_from, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_copy_source, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_make_ddi, freep);
|
||||
|
||||
typedef struct FreeArea FreeArea;
|
||||
|
||||
|
@ -6376,6 +6378,9 @@ static int help(void) {
|
|||
" --offline=BOOL Whether to build the image offline\n"
|
||||
" -s --copy-source=PATH Specify the primary source tree to copy files from\n"
|
||||
" --copy-from=IMAGE Copy partitions from the given image(s)\n"
|
||||
" -S --make-ddi=sysext Make a system extension DDI\n"
|
||||
" -C --make-ddi=confext Make a configuration extension DDI\n"
|
||||
" -P --make-ddi=portable Make a portable service DDI\n"
|
||||
"\nSee the %s for details.\n",
|
||||
program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
|
@ -6420,7 +6425,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
ARG_ARCHITECTURE,
|
||||
ARG_OFFLINE,
|
||||
ARG_COPY_FROM,
|
||||
ARG_COPY_SOURCE,
|
||||
ARG_MAKE_DDI,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
|
@ -6457,6 +6462,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
{ "offline", required_argument, NULL, ARG_OFFLINE },
|
||||
{ "copy-from", required_argument, NULL, ARG_COPY_FROM },
|
||||
{ "copy-source", required_argument, NULL, 's' },
|
||||
{ "make-ddi", required_argument, NULL, ARG_MAKE_DDI },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -6465,7 +6471,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hs:", options, NULL)) >= 0)
|
||||
while ((c = getopt_long(argc, argv, "hs:SCP", options, NULL)) >= 0)
|
||||
|
||||
switch (c) {
|
||||
|
||||
|
@ -6796,6 +6802,33 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
return r;
|
||||
break;
|
||||
|
||||
case ARG_MAKE_DDI:
|
||||
if (!filename_is_valid(optarg))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid DDI type: %s", optarg);
|
||||
|
||||
r = free_and_strdup_warn(&arg_make_ddi, optarg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
r = free_and_strdup_warn(&arg_make_ddi, "sysext");
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
r = free_and_strdup_warn(&arg_make_ddi, "confext");
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
r = free_and_strdup_warn(&arg_make_ddi, "portable");
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -6807,6 +6840,38 @@ static int parse_argv(int argc, char *argv[]) {
|
|||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Expected at most one argument, the path to the block device.");
|
||||
|
||||
if (arg_make_ddi) {
|
||||
if (arg_definitions)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Combination of --make-ddi= and --definitions= is not supported.");
|
||||
if (!IN_SET(arg_empty, EMPTY_UNSET, EMPTY_CREATE))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Combination of --make-ddi= and --empty=%s is not supported.",
|
||||
arg_empty == EMPTY_REFUSE ? "refuse" :
|
||||
arg_empty == EMPTY_ALLOW ? "allow" :
|
||||
arg_empty == EMPTY_REQUIRE ? "require" : "force");
|
||||
|
||||
/* Imply automatic sizing in DDI mode */
|
||||
if (arg_size == UINT64_MAX)
|
||||
arg_size_auto = true;
|
||||
|
||||
if (!arg_copy_source)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No --copy-source= specified, refusing.");
|
||||
|
||||
r = dir_is_empty(arg_copy_source, /* ignore_hidden_or_backup= */ false);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine if '%s' is empty: %m", arg_copy_source);
|
||||
if (r > 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Source directory '%s' is empty, refusing to create empty image.", arg_copy_source);
|
||||
|
||||
if (sd_id128_is_null(arg_seed) && !arg_randomize) {
|
||||
/* We don't want that /etc/machine-id leaks into any image built this way, hence
|
||||
* let's randomize the seed if not specified explicitly */
|
||||
log_notice("No seed value specified, randomizing generated UUIDs, resulting image will not be reproducible.");
|
||||
arg_randomize = true;
|
||||
}
|
||||
|
||||
arg_empty = EMPTY_CREATE;
|
||||
}
|
||||
|
||||
if (arg_empty == EMPTY_UNSET) /* default to refuse mode, if not otherwise specified */
|
||||
arg_empty = EMPTY_REFUSE;
|
||||
|
||||
|
@ -7371,7 +7436,22 @@ static int run(int argc, char *argv[]) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
strv_uniq(arg_definitions);
|
||||
if (arg_make_ddi) {
|
||||
_cleanup_free_ char *d = NULL, *dp = NULL;
|
||||
assert(!arg_definitions);
|
||||
|
||||
d = strjoin(arg_make_ddi, ".repart.d/");
|
||||
if (!d)
|
||||
return log_oom();
|
||||
|
||||
r = search_and_access(d, F_OK, arg_root, CONF_PATHS_USR_STRV("systemd/repart/definitions"), &dp);
|
||||
if (r < 0)
|
||||
return log_error_errno(errno, "DDI type '%s' is not defined: %m", arg_make_ddi);
|
||||
|
||||
if (strv_consume(&arg_definitions, TAKE_PTR(dp)) < 0)
|
||||
return log_oom();
|
||||
} else
|
||||
strv_uniq(arg_definitions);
|
||||
|
||||
r = context_read_definitions(context);
|
||||
if (r < 0)
|
||||
|
|
Loading…
Reference in a new issue