mirror of
https://github.com/systemd/systemd
synced 2026-03-14 17:14:49 +01:00
Compare commits
No commits in common. "5a35a6d9d44bc6ca21d6bc9d8bb20beab956da99" and "503a788332bda768fbcad485f8d51ee46f9e8c2f" have entirely different histories.
5a35a6d9d4
...
503a788332
@ -125,17 +125,6 @@
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-x</option></term>
|
||||
<term><option>--ephemeral</option></term>
|
||||
|
||||
<listitem><para>If specified, the VM is run with a temporary snapshot of its file system that is removed
|
||||
immediately when the VM terminates. Only works with <option>--image=</option> currently.
|
||||
|
||||
Note that <option>--ephemeral</option> will not work with <option>--extra-drive=</option>.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
|
||||
|
||||
@ -107,7 +107,6 @@
|
||||
#include "shift-uid.h"
|
||||
#include "signal-util.h"
|
||||
#include "siphash24.h"
|
||||
#include "snapshot-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "stdio-util.h"
|
||||
@ -5916,7 +5915,7 @@ static int do_cleanup(void) {
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
bool remove_image = false, veth_created = false;
|
||||
bool remove_directory = false, remove_image = false, veth_created = false;
|
||||
_cleanup_close_ int master = -EBADF, userns_fd = -EBADF, mount_fd = -EBADF;
|
||||
_cleanup_fdset_free_ FDSet *fds = NULL;
|
||||
int r, ret = EXIT_SUCCESS;
|
||||
@ -5924,7 +5923,6 @@ static int run(int argc, char *argv[]) {
|
||||
struct ExposeArgs expose_args = {};
|
||||
_cleanup_(release_lock_file) LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT;
|
||||
_cleanup_(rmdir_and_freep) char *rootdir = NULL;
|
||||
_cleanup_(rm_rf_subvolume_and_freep) char *snapshot_dir = NULL;
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop = NULL;
|
||||
_cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *nfnl = NULL;
|
||||
@ -6066,27 +6064,63 @@ static int run(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (arg_ephemeral) {
|
||||
_cleanup_free_ char *np = NULL;
|
||||
|
||||
r = chase_and_update(&arg_directory, 0);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = create_ephemeral_snapshot(
|
||||
arg_directory,
|
||||
arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER,
|
||||
arg_read_only,
|
||||
&tree_global_lock,
|
||||
&tree_local_lock,
|
||||
&snapshot_dir);
|
||||
/* If the specified path is a mount point we generate the new snapshot immediately
|
||||
* inside it under a random name. However if the specified is not a mount point we
|
||||
* create the new snapshot in the parent directory, just next to it. */
|
||||
r = path_is_mount_point(arg_directory);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to create ephemeral snapshot: %m");
|
||||
log_error_errno(r, "Failed to determine whether directory %s is mount point: %m", arg_directory);
|
||||
goto finish;
|
||||
}
|
||||
if (r > 0)
|
||||
r = tempfn_random_child(arg_directory, "machine.", &np);
|
||||
else
|
||||
r = tempfn_random(arg_directory, "machine.", &np);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to generate name for directory snapshot: %m");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = free_and_strdup(&arg_directory, snapshot_dir);
|
||||
/* We take an exclusive lock on this image, since it's our private, ephemeral copy
|
||||
* only owned by us and no one else. */
|
||||
r = image_path_lock(
|
||||
arg_privileged ? RUNTIME_SCOPE_SYSTEM : RUNTIME_SCOPE_USER,
|
||||
np,
|
||||
LOCK_EX|LOCK_NB,
|
||||
arg_privileged ? &tree_global_lock : NULL,
|
||||
&tree_local_lock);
|
||||
if (r < 0) {
|
||||
log_oom();
|
||||
log_error_errno(r, "Failed to lock %s: %m", np);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
{
|
||||
BLOCK_SIGNALS(SIGINT);
|
||||
r = btrfs_subvol_snapshot_at(AT_FDCWD, arg_directory, AT_FDCWD, np,
|
||||
(arg_read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) |
|
||||
BTRFS_SNAPSHOT_FALLBACK_COPY |
|
||||
BTRFS_SNAPSHOT_FALLBACK_DIRECTORY |
|
||||
BTRFS_SNAPSHOT_RECURSIVE |
|
||||
BTRFS_SNAPSHOT_QUOTA |
|
||||
BTRFS_SNAPSHOT_SIGINT);
|
||||
}
|
||||
if (r == -EINTR) {
|
||||
log_error_errno(r, "Interrupted while copying file system tree to %s, removed again.", np);
|
||||
goto finish;
|
||||
}
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to create snapshot %s from %s: %m", np, arg_directory);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
free_and_replace(arg_directory, np);
|
||||
remove_directory = true;
|
||||
} else {
|
||||
r = chase_and_update(&arg_directory, arg_template ? CHASE_NONEXISTENT : 0);
|
||||
if (r < 0)
|
||||
@ -6437,6 +6471,14 @@ finish:
|
||||
|
||||
pager_close();
|
||||
|
||||
if (remove_directory && arg_directory) {
|
||||
int k;
|
||||
|
||||
k = rm_rf(arg_directory, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
|
||||
if (k < 0)
|
||||
log_warning_errno(k, "Cannot remove '%s', ignoring: %m", arg_directory);
|
||||
}
|
||||
|
||||
if (remove_image && arg_image) {
|
||||
if (unlink(arg_image) < 0)
|
||||
log_warning_errno(errno, "Can't remove image file '%s', ignoring: %m", arg_image);
|
||||
|
||||
@ -177,7 +177,6 @@ shared_sources = files(
|
||||
'sleep-config.c',
|
||||
'smack-util.c',
|
||||
'smbios11.c',
|
||||
'snapshot-util.c',
|
||||
'socket-label.c',
|
||||
'socket-netlink.c',
|
||||
'specifier.c',
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <sys/file.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "btrfs-util.h"
|
||||
#include "discover-image.h"
|
||||
#include "log.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "snapshot-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
int create_ephemeral_snapshot(
|
||||
const char *directory,
|
||||
RuntimeScope scope,
|
||||
bool read_only,
|
||||
LockFile *tree_global_lock,
|
||||
LockFile *tree_local_lock,
|
||||
char **ret_new_path) {
|
||||
|
||||
_cleanup_free_ char *np = NULL;
|
||||
int r;
|
||||
|
||||
/* If the specified path is a mount point we generate the new snapshot immediately
|
||||
* inside it under a random name. However if the specified is not a mount point we
|
||||
* create the new snapshot in the parent directory, just next to it. */
|
||||
r = path_is_mount_point(directory);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine whether directory %s is mount point: %m", directory);
|
||||
if (r > 0)
|
||||
r = tempfn_random_child(directory, "snapshot.", &np);
|
||||
else
|
||||
r = tempfn_random(directory, "snapshot.", &np);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to generate name for directory snapshot: %m");
|
||||
|
||||
/* We take an exclusive lock on this image, since it's our private, ephemeral copy
|
||||
* only owned by us and no one else. */
|
||||
r = image_path_lock(
|
||||
scope,
|
||||
np,
|
||||
LOCK_EX|LOCK_NB,
|
||||
scope == RUNTIME_SCOPE_SYSTEM ? tree_global_lock : NULL,
|
||||
tree_local_lock);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to lock %s: %m", np);
|
||||
|
||||
{
|
||||
BLOCK_SIGNALS(SIGINT);
|
||||
r = btrfs_subvol_snapshot_at(AT_FDCWD, directory, AT_FDCWD, np,
|
||||
(read_only ? BTRFS_SNAPSHOT_READ_ONLY : 0) |
|
||||
BTRFS_SNAPSHOT_FALLBACK_COPY |
|
||||
BTRFS_SNAPSHOT_FALLBACK_DIRECTORY |
|
||||
BTRFS_SNAPSHOT_RECURSIVE |
|
||||
BTRFS_SNAPSHOT_QUOTA |
|
||||
BTRFS_SNAPSHOT_SIGINT);
|
||||
}
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create snapshot %s from %s: %m", np, directory);
|
||||
|
||||
*ret_new_path = TAKE_PTR(np);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "runtime-scope.h"
|
||||
|
||||
/* create_ephemeral_snapshot - create a snapshot of the given directory.
|
||||
*
|
||||
* It will use a btrfs snapshot when available with fallback to traditional dir copy. It will set the global
|
||||
* and local lock files based on the passed runtime scope. On success the new directory path is returned via
|
||||
* `ret_new_path`.
|
||||
*
|
||||
* The caller is responsible for the cleanup of the directory, using `_cleanup_(rm_rf_subvolume_and_freep)`
|
||||
* is recommended.
|
||||
*/
|
||||
int create_ephemeral_snapshot(
|
||||
const char *directory,
|
||||
RuntimeScope scope,
|
||||
bool read_only,
|
||||
LockFile *tree_global_lock,
|
||||
LockFile *tree_local_lock,
|
||||
char **ret_new_path);
|
||||
@ -35,7 +35,6 @@ typedef enum SettingsMask {
|
||||
SETTING_START_MODE = UINT64_C(1) << 0,
|
||||
SETTING_MACHINE_ID = UINT64_C(1) << 6,
|
||||
SETTING_BIND_MOUNTS = UINT64_C(1) << 11,
|
||||
SETTING_EPHEMERAL = UINT64_C(1) << 24,
|
||||
SETTING_DIRECTORY = UINT64_C(1) << 26,
|
||||
SETTING_CREDENTIALS = UINT64_C(1) << 30,
|
||||
_SETTING_FORCE_ENUM_WIDTH = UINT64_MAX
|
||||
|
||||
@ -62,7 +62,6 @@
|
||||
#include "random-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "signal-util.h"
|
||||
#include "snapshot-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "stdio-util.h"
|
||||
@ -146,7 +145,6 @@ static char **arg_bind_user = NULL;
|
||||
static char *arg_bind_user_shell = NULL;
|
||||
static bool arg_bind_user_shell_copy = false;
|
||||
static char **arg_bind_user_groups = NULL;
|
||||
static bool arg_ephemeral = false;
|
||||
static RuntimeScope arg_runtime_scope = _RUNTIME_SCOPE_INVALID;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_directory, freep);
|
||||
@ -192,7 +190,6 @@ static int help(void) {
|
||||
" --system Interact with system manager\n"
|
||||
"\n%3$sImage:%4$s\n"
|
||||
" -D --directory=PATH Root directory for the VM\n"
|
||||
" -x --ephemeral Run VM with snapshot of the disk or directory\n"
|
||||
" -i --image=FILE|DEVICE Root file system disk image or device for the VM\n"
|
||||
" --image-format=FORMAT Specify disk image format (raw, qcow2; default: raw)\n"
|
||||
"\n%3$sHost Configuration:%4$s\n"
|
||||
@ -330,7 +327,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||
{ "image", required_argument, NULL, 'i' },
|
||||
{ "image-format", required_argument, NULL, ARG_IMAGE_FORMAT },
|
||||
{ "ephemeral", no_argument, NULL, 'x' },
|
||||
{ "directory", required_argument, NULL, 'D' },
|
||||
{ "machine", required_argument, NULL, 'M' },
|
||||
{ "slice", required_argument, NULL, 'S' },
|
||||
@ -386,7 +382,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert(argv);
|
||||
|
||||
optind = 0;
|
||||
while ((c = getopt_long(argc, argv, "+hD:i:xM:nqs:G:S:", options, NULL)) >= 0)
|
||||
while ((c = getopt_long(argc, argv, "+hD:i:M:nqs:G:S:", options, NULL)) >= 0)
|
||||
switch (c) {
|
||||
case 'h':
|
||||
return help();
|
||||
@ -433,10 +429,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
arg_ephemeral = true;
|
||||
break;
|
||||
|
||||
case ARG_NO_PAGER:
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
@ -802,9 +794,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
if (!strv_isempty(arg_bind_user_groups) && strv_isempty(arg_bind_user))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot use --bind-user-group= without --bind-user=");
|
||||
|
||||
if (arg_ephemeral && arg_extra_drives.n_drives > 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot use --ephemeral with --extra-drive=");
|
||||
|
||||
if (argc > optind) {
|
||||
arg_kernel_cmdline_extra = strv_copy(argv + optind);
|
||||
if (!arg_kernel_cmdline_extra)
|
||||
@ -1854,8 +1843,6 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
_cleanup_(ovmf_config_freep) OvmfConfig *ovmf_config = NULL;
|
||||
_cleanup_free_ char *qemu_binary = NULL, *mem = NULL, *kernel = NULL;
|
||||
_cleanup_(rm_rf_physical_and_freep) char *ssh_private_key_path = NULL, *ssh_public_key_path = NULL;
|
||||
_cleanup_(rm_rf_subvolume_and_freep) char *snapshot_directory = NULL;
|
||||
_cleanup_(release_lock_file) LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT;
|
||||
_cleanup_close_ int notify_sock_fd = -EBADF;
|
||||
_cleanup_strv_free_ char **cmdline = NULL;
|
||||
_cleanup_free_ int *pass_fds = NULL;
|
||||
@ -2332,8 +2319,7 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
if (!escaped_image)
|
||||
return log_oom();
|
||||
|
||||
if (strv_extendf(&cmdline, "if=none,id=vmspawn,file=%s,format=%s,discard=%s,snapshot=%s",
|
||||
escaped_image, image_format_to_string(arg_image_format), on_off(arg_discard_disk), on_off(arg_ephemeral)) < 0)
|
||||
if (strv_extendf(&cmdline, "if=none,id=vmspawn,file=%s,format=%s,discard=%s", escaped_image, image_format_to_string(arg_image_format), on_off(arg_discard_disk)) < 0)
|
||||
return log_oom();
|
||||
|
||||
_cleanup_free_ char *image_fn = NULL;
|
||||
@ -2380,21 +2366,6 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
||||
if (!GREEDY_REALLOC(children, n_children + 1))
|
||||
return log_oom();
|
||||
|
||||
if (arg_ephemeral) {
|
||||
r = create_ephemeral_snapshot(arg_directory,
|
||||
arg_runtime_scope,
|
||||
/* read-only */ false,
|
||||
&tree_global_lock,
|
||||
&tree_local_lock,
|
||||
&snapshot_directory);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
arg_directory = strdup(snapshot_directory);
|
||||
if (!arg_directory)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = start_virtiofsd(
|
||||
unit,
|
||||
arg_directory,
|
||||
@ -3094,11 +3065,6 @@ static int determine_names(void) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract file name from '%s': %m", arg_directory);
|
||||
}
|
||||
/* Add a random suffix when this is an ephemeral machine, so that we can run many
|
||||
* instances at once without manually having to specify -M each time. */
|
||||
if (arg_ephemeral)
|
||||
if (strextendf(&arg_machine, "-%016" PRIx64, random_u64()) < 0)
|
||||
return log_oom();
|
||||
|
||||
hostname_cleanup(arg_machine);
|
||||
if (!hostname_is_valid(arg_machine, 0))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user