Compare commits

...

11 Commits

Author SHA1 Message Date
Ivan Kruglov aca5078ec5
Merge b1e226539e into 2e5b0412f9 2024-11-21 00:11:57 +00:00
Luca Boccassi 2e5b0412f9
network: update state files before replying bus method (#35255)
Follow-up for 2b07a3211b.

Fixes the failure found in
https://autopkgtest.ubuntu.com/results/autopkgtest-noble-upstream-systemd-ci-systemd-ci/noble/amd64/s/systemd-upstream/20241115_182040_92382@/log.gz
. Relevant logs:
```
Nov 16 02:48:36 systemd-networkd[2706]: veth99: Reconfiguring with /run/systemd/network/25-dhcp-client-ipv6-only.network.
Nov 16 02:48:36 systemd-networkd[2706]: veth99: NDISC: Started IPv6 Router Solicitation client
Nov 16 02:48:36 systemd-networkd[2706]: veth99: IPv6 Router Discovery is configured and started.
Nov 16 02:48:36 systemd-networkd[2706]: veth99: NDISC: Sent Router Solicitation, next solicitation in 3s
Nov 16 02:48:36 systemd-networkd[2706]: veth99: NDISC: Received Router Advertisement from fe80::1034:56ff:fe78:9abd: flags=0xc0(managed, other), preference=medium, lifetime=30min
Nov 16 02:48:36 systemd-networkd[2706]: veth99: NDISC: Invoking callback for 'router' event.
Nov 16 02:48:36 systemd-networkd[2706]: veth99: link_check_ready(): dynamic addressing protocols are enabled but none of them finished yet.
Nov 16 02:48:36 systemd-networkd[2706]: veth99: DHCPv6 client: Starting in Solicit mode
Nov 16 02:48:36 systemd-networkd[2706]: veth99: DHCPv6 client: State changed: stopped -> solicitation
Nov 16 02:48:36 systemd-networkd[2706]: veth99: Acquiring DHCPv6 lease on NDisc request
Nov 16 02:48:36 systemd-networkd[2706]: veth99: DHCPv6 client: Sent Solicit
Nov 16 02:48:36 systemd-networkd[2706]: veth99: DHCPv6 client: Next retransmission in 1s
Nov 16 02:48:37 systemd-networkd[2706]: veth99: DHCPv6 client: Sent Solicit
Nov 16 02:48:37 systemd-networkd[2706]: veth99: DHCPv6 client: Next retransmission in 1s
Nov 16 02:48:39 systemd-networkd[2706]: veth99: NDISC: Received Neighbor Advertisement from fe80::1034:56ff:fe78:9abd: Router=yes, Solicited=yes, Override=no
Nov 16 02:48:39 systemd-networkd[2706]: veth99: NDISC: Invoking callback for 'neighbor' event.
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 client: Processed Reply message
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 client: T1 expires in 50s
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 client: T2 expires in 55s
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 client: Valid lifetime expires in 2min
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 client: State changed: solicitation -> bound
Nov 16 02:48:39 systemd-networkd[2706]: veth99: DHCPv6 address 2600::15/128 (valid for 1min 59s, preferred for 1min 59s)
Nov 16 02:48:41 systemd-networkd[2706]: veth99: Received updated DHCPv6 address (configured): 2600::15/128 (valid for 1min 58s, preferred for 1min 58s), flags: no-prefixroute, scope: global
Nov 16 02:48:41 systemd-networkd[2706]: veth99: DHCPv6 addresses and routes set.
Nov 16 02:48:41 systemd-networkd[2706]: veth99: link_check_ready(): IPv4LL:no DHCPv4:no DHCPv6:yes DHCP-PD:no NDisc:no
Nov 16 02:48:41 systemd-networkd[2706]: veth99: State changed: configuring -> configured
```
The interface veth99 entered the configured state after 5 seconds, but
at the same time, the `wait_online()` in the test script considered the
test failed.
The function `wait_online()` first invokes
`systemd-networkd-wait-online` with `--timeout=20`, then check setup
states of interfaces with 5 seconds timeout. So, the failure suggests
that `systemd-networkd-wait-online` finishes immediately, as the state
file was not updated when it is invoked, and thus it handles the
interface veth99 already in the configured state.
2024-11-20 23:36:35 +00:00
Martin Srebotnjak 69af4849aa po: Translated using Weblate (Slovenian)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Martin Srebotnjak <miles@filmsi.net>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/sl/
Translation: systemd/main
2024-11-21 04:17:08 +09:00
Jiri Grönroos 18d4e0be89 po: Translated using Weblate (Finnish)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Jiri Grönroos <jiri.gronroos@iki.fi>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/fi/
Translation: systemd/main
2024-11-21 04:17:08 +09:00
Dmytro Markevych 7d7b89a015 po: Translated using Weblate (Ukrainian)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Dmytro Markevych <hotr1pak@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/uk/
Translation: systemd/main
2024-11-21 04:17:08 +09:00
Léane GRASSER 8a92365f79 po: Translated using Weblate (French)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Léane GRASSER <leane.grasser@proton.me>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/fr/
Translation: systemd/main
2024-11-21 04:17:08 +09:00
Yu Watanabe 2b397d43ab test-network: actually check metric and preference
Otherwise, nexthop ID may contain e.g. 300, then
===
AssertionError: '300' unexpectedly found in
'default nhid 3860882700 via fe80::1034:56ff:fe78:9a99 proto ra metric 512 expires 1798sec pref high\n
 default nhid 2639230080 via fe80::1034:56ff:fe78:9a98 proto ra metric 2048 expires 1798sec pref low'
===
2024-11-21 03:43:35 +09:00
Yu Watanabe 9ad294efd0 network: update state files before replying bus method
Follow-up for 2b07a3211b.
2024-11-21 03:42:06 +09:00
Ivan Kruglov b1e226539e machine: tests for io.systemd.Machine.{CopyFrom, CopyTo} methods 2024-11-20 10:38:59 +01:00
Ivan Kruglov 6d077f1216 machine: introduce io.system.Machine.{CopyFrom, CopyTo} methods 2024-11-20 10:38:59 +01:00
Ivan Kruglov 997c1bba6b machine: adjust operation callback logic for varlink
This is to simplyfy varlink callback. There is no use of this logic atm.
So, no harm.
2024-11-20 10:38:59 +01:00
12 changed files with 297 additions and 52 deletions

View File

@ -3,12 +3,13 @@
# Finnish translation of systemd. # Finnish translation of systemd.
# Jan Kuparinen <copper_fin@hotmail.com>, 2021, 2022, 2023. # Jan Kuparinen <copper_fin@hotmail.com>, 2021, 2022, 2023.
# Ricky Tigg <ricky.tigg@gmail.com>, 2022, 2024. # Ricky Tigg <ricky.tigg@gmail.com>, 2022, 2024.
# Jiri Grönroos <jiri.gronroos@iki.fi>, 2024.
msgid "" msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\n" "POT-Creation-Date: 2024-11-06 14:42+0000\n"
"PO-Revision-Date: 2024-09-12 13:43+0000\n" "PO-Revision-Date: 2024-11-20 19:13+0000\n"
"Last-Translator: Ricky Tigg <ricky.tigg@gmail.com>\n" "Last-Translator: Jiri Grönroos <jiri.gronroos@iki.fi>\n"
"Language-Team: Finnish <https://translate.fedoraproject.org/projects/systemd/" "Language-Team: Finnish <https://translate.fedoraproject.org/projects/systemd/"
"main/fi/>\n" "main/fi/>\n"
"Language: fi\n" "Language: fi\n"
@ -16,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n" "Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.7.2\n" "X-Generator: Weblate 5.8.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22 #: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system" msgid "Send passphrase back to system"
@ -112,14 +113,12 @@ msgid "Authentication is required to update a user's home area."
msgstr "Todennus vaaditaan käyttäjän kotialueen päivittämiseksi." msgstr "Todennus vaaditaan käyttäjän kotialueen päivittämiseksi."
#: src/home/org.freedesktop.home1.policy:53 #: src/home/org.freedesktop.home1.policy:53
#, fuzzy
msgid "Update your home area" msgid "Update your home area"
msgstr "Päivitä kotialue" msgstr "Päivitä kotialue"
#: src/home/org.freedesktop.home1.policy:54 #: src/home/org.freedesktop.home1.policy:54
#, fuzzy
msgid "Authentication is required to update your home area." msgid "Authentication is required to update your home area."
msgstr "Todennus vaaditaan käyttäjän kotialueen päivittämiseksi." msgstr "Todennus vaaditaan kotialueen päivittämiseksi."
#: src/home/org.freedesktop.home1.policy:63 #: src/home/org.freedesktop.home1.policy:63
msgid "Resize a home area" msgid "Resize a home area"
@ -1174,14 +1173,11 @@ msgstr "Todennus vaaditaan vanhojen järjestelmäpäivitysten puhdistamiseen."
#: src/sysupdate/org.freedesktop.sysupdate1.policy:75 #: src/sysupdate/org.freedesktop.sysupdate1.policy:75
msgid "Manage optional features" msgid "Manage optional features"
msgstr "" msgstr "Hallitse valinnaisia ominaisuuksia"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76 #: src/sysupdate/org.freedesktop.sysupdate1.policy:76
#, fuzzy
msgid "Authentication is required to manage optional features" msgid "Authentication is required to manage optional features"
msgstr "" msgstr "Todennus vaaditaan valinnaisten ominaisuuksien hallintaan"
"Todennus vaaditaan aktiivisten istuntojen, käyttäjien ja paikkojen "
"hallintaan."
#: src/timedate/org.freedesktop.timedate1.policy:22 #: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time" msgid "Set system time"

View File

@ -12,7 +12,7 @@ msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\n" "POT-Creation-Date: 2024-11-06 14:42+0000\n"
"PO-Revision-Date: 2024-11-07 09:30+0000\n" "PO-Revision-Date: 2024-11-20 19:13+0000\n"
"Last-Translator: Léane GRASSER <leane.grasser@proton.me>\n" "Last-Translator: Léane GRASSER <leane.grasser@proton.me>\n"
"Language-Team: French <https://translate.fedoraproject.org/projects/systemd/" "Language-Team: French <https://translate.fedoraproject.org/projects/systemd/"
"main/fr/>\n" "main/fr/>\n"
@ -360,8 +360,8 @@ msgid ""
"Authentication is required to set the statically configured local hostname, " "Authentication is required to set the statically configured local hostname, "
"as well as the pretty hostname." "as well as the pretty hostname."
msgstr "" msgstr ""
"Une authentification est requise pour définir le nom d'hôte local de manière " "Une authentification est requise pour définir le nom d'hôte local configuré "
"statique, ainsi que le nom d'hôte familier." "de manière statique, ainsi que le nom d'hôte convivial."
#: src/hostname/org.freedesktop.hostname1.policy:41 #: src/hostname/org.freedesktop.hostname1.policy:41
msgid "Set machine information" msgid "Set machine information"

View File

@ -7,7 +7,7 @@ msgstr ""
"Project-Id-Version: systemd\n" "Project-Id-Version: systemd\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\n" "POT-Creation-Date: 2024-11-06 14:42+0000\n"
"PO-Revision-Date: 2024-08-26 19:38+0000\n" "PO-Revision-Date: 2024-11-20 19:13+0000\n"
"Last-Translator: Martin Srebotnjak <miles@filmsi.net>\n" "Last-Translator: Martin Srebotnjak <miles@filmsi.net>\n"
"Language-Team: Slovenian <https://translate.fedoraproject.org/projects/" "Language-Team: Slovenian <https://translate.fedoraproject.org/projects/"
"systemd/main/sl/>\n" "systemd/main/sl/>\n"
@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " "Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || "
"n%100==4 ? 2 : 3;\n" "n%100==4 ? 2 : 3;\n"
"X-Generator: Weblate 5.7\n" "X-Generator: Weblate 5.8.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22 #: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system" msgid "Send passphrase back to system"
@ -125,16 +125,13 @@ msgstr ""
"območja." "območja."
#: src/home/org.freedesktop.home1.policy:53 #: src/home/org.freedesktop.home1.policy:53
#, fuzzy
msgid "Update your home area" msgid "Update your home area"
msgstr "Posodobite domače območje" msgstr "Posodobite domače območje"
#: src/home/org.freedesktop.home1.policy:54 #: src/home/org.freedesktop.home1.policy:54
#, fuzzy
msgid "Authentication is required to update your home area." msgid "Authentication is required to update your home area."
msgstr "" msgstr ""
"Preverjanje pristnosti je potrebno za posodobitev uporabnikovega domačega " "Preverjanje pristnosti je potrebno za posodobitev vašega domačega območja."
"območja."
#: src/home/org.freedesktop.home1.policy:63 #: src/home/org.freedesktop.home1.policy:63
msgid "Resize a home area" msgid "Resize a home area"
@ -1234,14 +1231,12 @@ msgstr ""
#: src/sysupdate/org.freedesktop.sysupdate1.policy:75 #: src/sysupdate/org.freedesktop.sysupdate1.policy:75
msgid "Manage optional features" msgid "Manage optional features"
msgstr "" msgstr "Upravljaj dodatne funkcionalnosti"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76 #: src/sysupdate/org.freedesktop.sysupdate1.policy:76
#, fuzzy
msgid "Authentication is required to manage optional features" msgid "Authentication is required to manage optional features"
msgstr "" msgstr ""
"Preverjanje pristnosti je potrebno za upravljanje aktivnih sej, uporabnikov " "Preverjanje pristnosti je potrebno za upravljanje dodatnih funkcionalnosti."
"in delovišč."
#: src/timedate/org.freedesktop.timedate1.policy:22 #: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time" msgid "Set system time"

View File

@ -4,12 +4,13 @@
# Eugene Melnik <jeka7js@gmail.com>, 2014. # Eugene Melnik <jeka7js@gmail.com>, 2014.
# Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016, 2018. # Daniel Korostil <ted.korostiled@gmail.com>, 2014, 2016, 2018.
# Yuri Chornoivan <yurchor@ukr.net>, 2019, 2020, 2021, 2022, 2023, 2024. # Yuri Chornoivan <yurchor@ukr.net>, 2019, 2020, 2021, 2022, 2023, 2024.
# Dmytro Markevych <hotr1pak@gmail.com>, 2024.
msgid "" msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\n" "POT-Creation-Date: 2024-11-06 14:42+0000\n"
"PO-Revision-Date: 2024-08-24 10:36+0000\n" "PO-Revision-Date: 2024-11-20 19:13+0000\n"
"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n" "Last-Translator: Dmytro Markevych <hotr1pak@gmail.com>\n"
"Language-Team: Ukrainian <https://translate.fedoraproject.org/projects/" "Language-Team: Ukrainian <https://translate.fedoraproject.org/projects/"
"systemd/main/uk/>\n" "systemd/main/uk/>\n"
"Language: uk\n" "Language: uk\n"
@ -18,7 +19,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 5.7\n" "X-Generator: Weblate 5.8.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22 #: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system" msgid "Send passphrase back to system"
@ -118,14 +119,12 @@ msgid "Authentication is required to update a user's home area."
msgstr "Для оновлення домашньої теки користувача слід пройти розпізнавання." msgstr "Для оновлення домашньої теки користувача слід пройти розпізнавання."
#: src/home/org.freedesktop.home1.policy:53 #: src/home/org.freedesktop.home1.policy:53
#, fuzzy
msgid "Update your home area" msgid "Update your home area"
msgstr "Оновлення домашньої теки" msgstr "Оновіть свій домашній простір"
#: src/home/org.freedesktop.home1.policy:54 #: src/home/org.freedesktop.home1.policy:54
#, fuzzy
msgid "Authentication is required to update your home area." msgid "Authentication is required to update your home area."
msgstr "Для оновлення домашньої теки користувача слід пройти розпізнавання." msgstr "Для оновлення домашньої області потрібна автентифікація."
#: src/home/org.freedesktop.home1.policy:63 #: src/home/org.freedesktop.home1.policy:63
msgid "Resize a home area" msgid "Resize a home area"
@ -1212,14 +1211,11 @@ msgstr "Для вилучення застарілих оновлень сист
#: src/sysupdate/org.freedesktop.sysupdate1.policy:75 #: src/sysupdate/org.freedesktop.sysupdate1.policy:75
msgid "Manage optional features" msgid "Manage optional features"
msgstr "" msgstr "Керування додатковими функціями"
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76 #: src/sysupdate/org.freedesktop.sysupdate1.policy:76
#, fuzzy
msgid "Authentication is required to manage optional features" msgid "Authentication is required to manage optional features"
msgstr "" msgstr "Для керування додатковими функціями потрібна автентифікація"
"Для того, щоб керувати сеансами, користувачами і робочими місцями, слід "
"пройти розпізнавання."
#: src/timedate/org.freedesktop.timedate1.policy:22 #: src/timedate/org.freedesktop.timedate1.policy:22
msgid "Set system time" msgid "Set system time"

View File

@ -7,6 +7,7 @@
#include "sd-varlink.h" #include "sd-varlink.h"
#include "bus-polkit.h" #include "bus-polkit.h"
#include "copy.h"
#include "fd-util.h" #include "fd-util.h"
#include "hostname-util.h" #include "hostname-util.h"
#include "json-util.h" #include "json-util.h"
@ -570,3 +571,191 @@ int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_met
return sd_varlink_reply(link, v); return sd_varlink_reply(link, v);
} }
typedef struct MachineCopyParameters {
const char *name;
PidRef pidref;
char *src, *dest;
bool replace;
} MachineCopyParameters;
static void machine_copy_paramaters_done(MachineCopyParameters *p) {
assert(p);
pidref_done(&p->pidref);
free(p->src);
free(p->dest);
}
static int copy_done(Operation *operation, int ret, sd_bus_error *error) {
assert(operation);
assert(operation->link);
// TODO(ikruglov): maybe just leaving a plain errno in response?
if (ret == -EPERM || ret == -EACCES)
return sd_varlink_error(operation->link, SD_VARLINK_ERROR_PERMISSION_DENIED, NULL);
if (ERRNO_IS_NEG_NOT_SUPPORTED(ret))
return sd_varlink_error(operation->link, "io.systemd.Machine.NotSupported", NULL);
if (ret == -ENOENT)
return sd_varlink_error(operation->link, "io.systemd.Machine.NoSuchFile", NULL);
if (ret == -EEXIST)
return sd_varlink_error(operation->link, "io.systemd.Machine.FileExists", NULL);
if (ret < 0)
return sd_varlink_error_errno(operation->link, ret);
return sd_varlink_reply(operation->link, NULL);
}
int vl_method_copy_internal(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata, bool copy_from) {
static const sd_json_dispatch_field dispatch_table[] = {
VARLINK_DISPATCH_MACHINE_LOOKUP_FIELDS(MachineCopyParameters),
{ "source", SD_JSON_VARIANT_STRING, json_dispatch_path, offsetof(MachineCopyParameters, src), SD_JSON_MANDATORY },
{ "destination", SD_JSON_VARIANT_STRING, json_dispatch_path, offsetof(MachineCopyParameters, dest), 0 },
{ "replace", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(MachineCopyParameters, replace), 0 },
VARLINK_DISPATCH_POLKIT_FIELD,
{}
};
Manager *manager = ASSERT_PTR(userdata);
_cleanup_close_ int hostfd = -EBADF, mntns_fd = -EBADF;
_cleanup_close_pair_ int errno_pipe_fd[2] = EBADF_PAIR;
_cleanup_(machine_copy_paramaters_done) MachineCopyParameters p = { .pidref = PIDREF_NULL };
_cleanup_free_ char *host_basename = NULL, *container_basename = NULL;
CopyFlags copy_flags = COPY_REFLINK|COPY_MERGE|COPY_HARDLINKS;
uid_t uid_shift;
pid_t child;
int r;
assert(link);
assert(parameters);
if (manager->n_operations >= OPERATIONS_MAX)
return sd_varlink_error(link, "io.systemd.MachineImage.TooManyOperations", NULL);
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
if (r != 0)
return r;
/* There is no need for extra validation since path_is_absolute() does path_is_valid() and path_is_absolute().*/
const char *dest = p.dest ?: p.src;
const char *container_path = copy_from ? p.src : dest;
const char *host_path = copy_from ? dest : p.src;
copy_flags |= p.replace ? COPY_REPLACE : 0;
Machine *machine;
r = lookup_machine_by_name_or_pidref(link, manager, p.name, &p.pidref, &machine);
if (r == -ESRCH)
return sd_varlink_error(link, "io.systemd.Machine.NoSuchMachine", NULL);
if (r != 0)
return r;
if (machine->class != MACHINE_CONTAINER)
return sd_varlink_error(link, "io.systemd.Machine.NotSupported", NULL);
r = varlink_verify_polkit_async(
link,
manager->bus,
"org.freedesktop.machine1.manage-machines",
(const char**) STRV_MAKE("name", machine->name,
"verb", "copy",
"src", p.src,
"dest", dest),
&manager->polkit_registry);
if (r <= 0)
return r;
r = path_extract_filename(host_path, &host_basename);
if (r < 0)
return log_debug_errno(r, "Failed to extract file name of '%s' path: %m", host_path);
r = path_extract_filename(container_path, &container_basename);
if (r < 0)
return log_debug_errno(r, "Failed to extract file name of '%s' path: %m", container_path);
hostfd = open_parent(host_path, O_CLOEXEC, 0);
if (hostfd < 0)
return log_debug_errno(hostfd, "Failed to open host directory %s: %m", host_path);
r = machine_get_uid_shift(machine, &uid_shift);
if (r < 0)
return log_debug_errno(r, "Failed to get machine UID shift: %m");
r = pidref_namespace_open(&machine->leader,
/* ret_pidns_fd = */ NULL,
&mntns_fd,
/* ret_netns_fd = */ NULL,
/* ret_userns_fd = */ NULL,
/* ret_root_fd = */ NULL);
if (r < 0)
return log_debug_errno(r, "Failed to open namespace: %m");
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
return log_debug_errno(errno, "Failed to create pipe: %m");
r = namespace_fork("(sd-copyns)",
"(sd-copy)",
/* except_fds = */ NULL,
/* n_except_fds = */ 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
/* pidns_fd = */ -1,
mntns_fd,
/* netns_fd = */ -1,
/* userns_fd = */ -1,
/* root_fd = */ -1,
&child);
if (r < 0)
return log_debug_errno(r, "Failed to fork(): %m");
if (r == 0) {
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
_cleanup_close_ int containerfd = -EBADF;
containerfd = open_parent(container_path, O_CLOEXEC, 0);
if (containerfd < 0) {
log_error_errno(containerfd, "Failed to open destination directory: %m");
report_errno_and_exit(errno_pipe_fd[1], containerfd);
}
/* Run the actual copy operation. Note that when a UID shift is set we'll either clamp the UID/GID to */
/* 0 or to the actual UID shift depending on the direction we copy. If no UID shift is set we'll copy */
/* the UID/GIDs as they are. */
r = copy_from ? copy_tree_at(
containerfd,
container_basename,
hostfd,
host_basename,
uid_shift == 0 ? UID_INVALID : 0,
uid_shift == 0 ? GID_INVALID : 0,
copy_flags,
/* denylist = */ NULL,
/* subvolumes = */ NULL)
: copy_tree_at(
hostfd,
host_basename,
containerfd,
container_basename,
uid_shift == 0 ? UID_INVALID : uid_shift,
uid_shift == 0 ? GID_INVALID : uid_shift,
copy_flags,
/* denylist = */ NULL,
/* subvolumes = */ NULL);
if (r < 0)
log_error_errno(r, "Failed to copy tree: %m");
report_errno_and_exit(errno_pipe_fd[1], r);
}
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
Operation *operation;
r = operation_new_with_varlink_reply(manager, machine, child, link, errno_pipe_fd[0], &operation);
if (r < 0) {
sigkill_wait(child);
return r;
}
operation->done = copy_done;
TAKE_FD(errno_pipe_fd[0]);
return 1;
}

View File

@ -25,3 +25,4 @@ int vl_method_unregister_internal(sd_varlink *link, sd_json_variant *parameters,
int vl_method_terminate_internal(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); int vl_method_terminate_internal(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
int vl_method_kill(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); int vl_method_kill(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata); int vl_method_open(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata);
int vl_method_copy_internal(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata, bool copy_from);

View File

@ -590,6 +590,13 @@ static int vl_method_terminate(sd_varlink *link, sd_json_variant *parameters, sd
return lookup_machine_and_call_method(link, parameters, flags, userdata, vl_method_terminate_internal); return lookup_machine_and_call_method(link, parameters, flags, userdata, vl_method_terminate_internal);
} }
static int vl_method_copy_from(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
return vl_method_copy_internal(link, parameters, flags, userdata, /* copy_from = */ true);
}
static int vl_method_copy_to(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
return vl_method_copy_internal(link, parameters, flags, userdata, /* copy_from = */ false);
}
static int list_image_one_and_maybe_read_metadata(sd_varlink *link, Image *image, bool more, AcquireMetadata am) { static int list_image_one_and_maybe_read_metadata(sd_varlink *link, Image *image, bool more, AcquireMetadata am) {
int r; int r;
@ -774,6 +781,8 @@ static int manager_varlink_init_machine(Manager *m) {
"io.systemd.Machine.Terminate", vl_method_terminate, "io.systemd.Machine.Terminate", vl_method_terminate,
"io.systemd.Machine.Kill", vl_method_kill, "io.systemd.Machine.Kill", vl_method_kill,
"io.systemd.Machine.Open", vl_method_open, "io.systemd.Machine.Open", vl_method_open,
"io.systemd.Machine.CopyFrom", vl_method_copy_from,
"io.systemd.Machine.CopyTo", vl_method_copy_to,
"io.systemd.MachineImage.List", vl_method_list_images, "io.systemd.MachineImage.List", vl_method_list_images,
"io.systemd.MachineImage.Update", vl_method_update_image, "io.systemd.MachineImage.Update", vl_method_update_image,
"io.systemd.MachineImage.Clone", vl_method_clone_image, "io.systemd.MachineImage.Clone", vl_method_clone_image,

View File

@ -46,10 +46,13 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat
if (r < 0) if (r < 0)
log_debug_errno(r, "Operation failed: %m"); log_debug_errno(r, "Operation failed: %m");
/* If a completion routine (o->done) is set for this operation, call it. It sends a response, but can return an error in which case it expect us to reply.
* Otherwise, the default action is to simply return an error on failure or an empty success message on success. */
if (o->message) { if (o->message) {
/* If a completion routine (o->done) is set for this operation,
* call it. It sends a response, but can return an error in
* which case it expect us to reply. Otherwise, the default
* action is to simply return an error on failure or an empty
* success message on success. */
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
if (o->done) if (o->done)
r = o->done(o, r, &error); r = o->done(o, r, &error);
@ -68,13 +71,13 @@ static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdat
log_error_errno(r, "Failed to reply to dbus message: %m"); log_error_errno(r, "Failed to reply to dbus message: %m");
} }
} else if (o->link) { } else if (o->link) {
/* If a completion routine (o->done) is set for this operation,
* then it's completely response for sending a response */
if (o->done) if (o->done)
r = o->done(o, r, /* error = */ NULL); (void) o->done(o, r, /* error = */ NULL);
else if (r < 0)
if (r < 0)
(void) sd_varlink_error_errno(o->link, r); (void) sd_varlink_error_errno(o->link, r);
else if (!o->done) else
/* when o->done set it's responsible for sending reply in a happy-path case */
(void) sd_varlink_reply(o->link, NULL); (void) sd_varlink_reply(o->link, NULL);
} else } else
assert_not_reached(); assert_not_reached();

View File

@ -1443,6 +1443,7 @@ int link_reconfigure_impl(Link *link, LinkReconfigurationFlag flags) {
} }
typedef struct LinkReconfigurationData { typedef struct LinkReconfigurationData {
Manager *manager;
Link *link; Link *link;
LinkReconfigurationFlag flags; LinkReconfigurationFlag flags;
sd_bus_message *message; sd_bus_message *message;
@ -1473,6 +1474,12 @@ static void link_reconfiguration_data_destroy_callback(LinkReconfigurationData *
} }
if (!data->counter || *data->counter <= 0) { if (!data->counter || *data->counter <= 0) {
/* Update the state files before replying the bus method. Otherwise,
* systemd-networkd-wait-online following networkctl reload/reconfigure may read an
* outdated state file and wrongly handle an interface is already in the configured
* state. */
(void) manager_clean_all(data->manager);
r = sd_bus_reply_method_return(data->message, NULL); r = sd_bus_reply_method_return(data->message, NULL);
if (r < 0) if (r < 0)
log_warning_errno(r, "Failed to reply for DBus method, ignoring: %m"); log_warning_errno(r, "Failed to reply for DBus method, ignoring: %m");
@ -1521,6 +1528,7 @@ int link_reconfigure_full(Link *link, LinkReconfigurationFlag flags, sd_bus_mess
} }
*data = (LinkReconfigurationData) { *data = (LinkReconfigurationData) {
.manager = link->manager,
.link = link_ref(link), .link = link_ref(link),
.flags = flags, .flags = flags,
.message = sd_bus_message_ref(message), /* message may be NULL, but _ref() works fine. */ .message = sd_bus_message_ref(message), /* message may be NULL, but _ref() works fine. */

View File

@ -121,9 +121,30 @@ static SD_VARLINK_DEFINE_METHOD(
SD_VARLINK_DEFINE_OUTPUT(ptyFileDescriptor, SD_VARLINK_INT, 0), SD_VARLINK_DEFINE_OUTPUT(ptyFileDescriptor, SD_VARLINK_INT, 0),
SD_VARLINK_FIELD_COMMENT("Path to the allocated pseudo TTY"), SD_VARLINK_FIELD_COMMENT("Path to the allocated pseudo TTY"),
SD_VARLINK_DEFINE_OUTPUT(ptyPath, SD_VARLINK_STRING, 0)); SD_VARLINK_DEFINE_OUTPUT(ptyPath, SD_VARLINK_STRING, 0));
static SD_VARLINK_DEFINE_METHOD(
CopyFrom,
VARLINK_DEFINE_MACHINE_LOOKUP_AND_POLKIT_INPUT_FIELDS,
SD_VARLINK_FIELD_COMMENT("A source directory in the container"),
SD_VARLINK_DEFINE_INPUT(source, SD_VARLINK_STRING, 0),
SD_VARLINK_FIELD_COMMENT("A destination directory in the container. If null, it's equal to 'source'"),
SD_VARLINK_DEFINE_INPUT(destination, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("If true the destination will be replaced"),
SD_VARLINK_DEFINE_INPUT(replace, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_METHOD(
CopyTo,
VARLINK_DEFINE_MACHINE_LOOKUP_AND_POLKIT_INPUT_FIELDS,
SD_VARLINK_FIELD_COMMENT("A source directory on the host"),
SD_VARLINK_DEFINE_INPUT(source, SD_VARLINK_STRING, 0),
SD_VARLINK_FIELD_COMMENT("A destination directory in the container. If null, it's equal to 'source'"),
SD_VARLINK_DEFINE_INPUT(destination, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("If true the destination will be replaced"),
SD_VARLINK_DEFINE_INPUT(replace, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE));
static SD_VARLINK_DEFINE_ERROR(NoSuchMachine); static SD_VARLINK_DEFINE_ERROR(NoSuchMachine);
static SD_VARLINK_DEFINE_ERROR(MachineExists); static SD_VARLINK_DEFINE_ERROR(MachineExists);
static SD_VARLINK_DEFINE_ERROR(NoSuchFile);
static SD_VARLINK_DEFINE_ERROR(FileExists);
static SD_VARLINK_DEFINE_ERROR(NoPrivateNetworking); static SD_VARLINK_DEFINE_ERROR(NoPrivateNetworking);
static SD_VARLINK_DEFINE_ERROR(NoOSReleaseInformation); static SD_VARLINK_DEFINE_ERROR(NoOSReleaseInformation);
static SD_VARLINK_DEFINE_ERROR(NoUIDShift); static SD_VARLINK_DEFINE_ERROR(NoUIDShift);
@ -154,9 +175,17 @@ SD_VARLINK_DEFINE_INTERFACE(
&vl_type_MachineOpenMode, &vl_type_MachineOpenMode,
SD_VARLINK_SYMBOL_COMMENT("Allocates a pseudo TTY in the container in various modes"), SD_VARLINK_SYMBOL_COMMENT("Allocates a pseudo TTY in the container in various modes"),
&vl_method_Open, &vl_method_Open,
SD_VARLINK_SYMBOL_COMMENT("Copy files or directories from a container into the host"),
&vl_method_CopyFrom,
SD_VARLINK_SYMBOL_COMMENT("Copy files or directories from the host into a container"),
&vl_method_CopyTo,
SD_VARLINK_SYMBOL_COMMENT("No matching machine currently running"), SD_VARLINK_SYMBOL_COMMENT("No matching machine currently running"),
&vl_error_NoSuchMachine, &vl_error_NoSuchMachine,
&vl_error_MachineExists, &vl_error_MachineExists,
SD_VARLINK_SYMBOL_COMMENT("No such file"),
&vl_error_NoSuchFile,
SD_VARLINK_SYMBOL_COMMENT("File exists"),
&vl_error_FileExists,
SD_VARLINK_SYMBOL_COMMENT("Machine does not use private networking"), SD_VARLINK_SYMBOL_COMMENT("Machine does not use private networking"),
&vl_error_NoPrivateNetworking, &vl_error_NoPrivateNetworking,
SD_VARLINK_SYMBOL_COMMENT("Machine does not contain OS release information"), SD_VARLINK_SYMBOL_COMMENT("Machine does not contain OS release information"),

View File

@ -6406,11 +6406,11 @@ class NetworkdRATests(unittest.TestCase, Utilities):
for i in [100, 200, 300, 512, 1024, 2048]: for i in [100, 200, 300, 512, 1024, 2048]:
if i not in [metric_1, metric_2]: if i not in [metric_1, metric_2]:
self.assertNotIn(f'{i}', output) self.assertNotIn(f'metric {i} ', output)
for i in ['low', 'medium', 'high']: for i in ['low', 'medium', 'high']:
if i not in [preference_1, preference_2]: if i not in [preference_1, preference_2]:
self.assertNotIn(f'{i}', output) self.assertNotIn(f'pref {i}', output)
def test_router_preference(self): def test_router_preference(self):
copy_network_unit('25-veth-client.netdev', copy_network_unit('25-veth-client.netdev',

View File

@ -252,7 +252,7 @@ done
#################### ####################
# varlinkctl tests # # varlinkctl tests #
# ################## ####################
long_running_machine_start long_running_machine_start
@ -352,12 +352,7 @@ TS="$(date '+%H:%M:%S')"
(! varlinkctl --more call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{"acquireMetadata": "yes"}') (! varlinkctl --more call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{"acquireMetadata": "yes"}')
journalctl --sync journalctl --sync
(! journalctl -u systemd-machined.service --since="$TS" --grep 'Connection busy') (! journalctl -u systemd-machined.service --since="$TS" --grep 'Connection busy')
# terminate machines
machinectl terminate container-without-os-release machinectl terminate container-without-os-release
machinectl terminate long-running
# wait for the container being stopped, otherwise acquiring image metadata by io.systemd.MachineImage.List may fail in the below.
timeout 10 bash -c "while machinectl status long-running &>/dev/null; do sleep .5; done"
systemctl kill --signal=KILL systemd-nspawn@long-running.service || :
(ip addr show lo | grep -q 192.168.1.100) || ip address add 192.168.1.100/24 dev lo (ip addr show lo | grep -q 192.168.1.100) || ip address add 192.168.1.100/24 dev lo
(! varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{"name": ".host"}' | grep 'addresses') (! varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.List '{"name": ".host"}' | grep 'addresses')
@ -386,6 +381,30 @@ varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.Open
timeout 30 bash -c "until test -e /tmp/none-existent-file; do sleep .5; done" timeout 30 bash -c "until test -e /tmp/none-existent-file; do sleep .5; done"
grep -q "BAR" /tmp/none-existent-file grep -q "BAR" /tmp/none-existent-file
# test io.systemd.Machine.CopyTo
long_running_machine_start
rm -f /tmp/foo /var/lib/machines/long-running/root/foo
cp /etc/machine-id /tmp/foo
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.CopyTo '{"name": "long-running", "source": "/tmp/foo", "destination": "/root/foo"}'
diff /tmp/foo /var/lib/machines/long-running/root/foo
(! varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.CopyTo '{"name": "long-running", "source": "/tmp/foo", "destination": "/root/foo"}')
echo "sample-test-output" > /tmp/foo
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.CopyTo '{"name": "long-running", "source": "/tmp/foo", "destination": "/root/foo", "replace": true}'
diff /tmp/foo /var/lib/machines/long-running/root/foo
rm -f /tmp/foo /var/lib/machines/long-running/root/foo
# test io.systemd.Machine.CopyFrom
cp /etc/machine-id /var/lib/machines/long-running/foo
varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.CopyFrom '{"name": "long-running", "source": "/foo"}'
diff /var/lib/machines/long-running/foo /foo
rm -f /var/lib/machines/long-running/root/foo /foo
# Terminating machine, otherwise acquiring image metadata by io.systemd.MachineImage.List may fail in the below.
machinectl terminate long-running
timeout 10 bash -c "while machinectl status long-running &>/dev/null; do sleep .5; done"
systemctl kill --signal=KILL systemd-nspawn@long-running.service || :
# test io.systemd.MachineImage.List # test io.systemd.MachineImage.List
varlinkctl --more call /run/systemd/machine/io.systemd.MachineImage io.systemd.MachineImage.List '{}' | grep 'long-running' varlinkctl --more call /run/systemd/machine/io.systemd.MachineImage io.systemd.MachineImage.List '{}' | grep 'long-running'
varlinkctl --more call /run/systemd/machine/io.systemd.MachineImage io.systemd.MachineImage.List '{}' | grep '.host' varlinkctl --more call /run/systemd/machine/io.systemd.MachineImage io.systemd.MachineImage.List '{}' | grep '.host'