1
0
mirror of https://github.com/systemd/systemd synced 2024-07-05 17:39:42 +00:00

vmspawn: add nic configuration

This commit is contained in:
Sam Leonard 2023-11-10 17:32:25 +00:00
parent 88af28d170
commit 75331bedeb
No known key found for this signature in database
GPG Key ID: 96850F0978CE78F0
4 changed files with 100 additions and 22 deletions

View File

@ -176,6 +176,31 @@
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry>
<varlistentry>
<term><option>-n</option></term>
<term><option>--network-tap</option></term>
<listitem>
<para>Create a TAP device to network with the virtual machine.</para>
<para>
Note: root privileges are required to use TAP networking.
Additionally requires a correctly setup
<citerefentry><refentrytitle>systemd-networkd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
to be running on the host to ensure the host interface is correctly configured.
The relevant <literal>.network</literal> file can be found at <filename>/usr/lib/systemd/network/80-vm-vt.network</filename>.
</para>
<xi:include href="version-info.xml" xpointer="v255"/>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--network-user-mode</option></term>
<listitem><para>Use user mode networking with QEMU.</para>
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--firmware=</option><replaceable>PATH</replaceable></term>

View File

@ -20,6 +20,7 @@
#include "siphash24.h"
#include "socket-util.h"
#include "sort-util.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "vmspawn-util.h"
@ -35,6 +36,8 @@ OvmfConfig* ovmf_config_free(OvmfConfig *config) {
return mfree(config);
}
DEFINE_STRING_TABLE_LOOKUP(qemu_network_stack, QemuNetworkStack);
int qemu_check_kvm_support(void) {
if (access("/dev/kvm", F_OK) >= 0)
return true;

View File

@ -45,6 +45,23 @@ static inline const char *ovmf_config_vars_format(const OvmfConfig *c) {
OvmfConfig* ovmf_config_free(OvmfConfig *ovmf_config);
DEFINE_TRIVIAL_CLEANUP_FUNC(OvmfConfig*, ovmf_config_free);
typedef enum QemuNetworkStack {
QEMU_NET_TAP,
QEMU_NET_USER,
QEMU_NET_NONE,
_QEMU_NET_MAX,
_QEMU_NET_INVALID = -EINVAL,
} QemuNetworkStack;
static const char* const qemu_network_stack_table[_QEMU_NET_MAX] = {
[QEMU_NET_TAP] = "tap",
[QEMU_NET_USER] = "user",
[QEMU_NET_NONE] = "none",
};
const char* qemu_network_stack_to_string(QemuNetworkStack type) _const_;
QemuNetworkStack qemu_network_stack_from_string(const char *s) _pure_;
int qemu_check_kvm_support(void);
int qemu_check_vsock_support(void);
int list_ovmf_config(char ***ret);

View File

@ -61,6 +61,7 @@ static int arg_tpm = -1;
static char *arg_linux = NULL;
static char *arg_initrd = NULL;
static bool arg_qemu_gui = false;
static QemuNetworkStack arg_network_stack = QEMU_NET_NONE;
static int arg_secure_boot = -1;
static MachineCredentialContext arg_credentials = {};
static SettingsMask arg_settings_mask = 0;
@ -109,6 +110,8 @@ static int help(void) {
" --linux=PATH Specify the linux kernel for direct kernel boot\n"
" --initrd=PATH Specify the initrd for direct kernel boot\n"
" --qemu-gui Start QEMU in graphical mode\n"
" -n --network-tap Create a TAP device for networking with QEMU.\n"
" --network-user-mode Use user mode networking with QEMU.\n"
" --secure-boot=BOOL Configure whether to search for firmware which\n"
" supports Secure Boot\n"
" --firmware=PATH|list Select firmware definition file (or list available)\n"
@ -145,6 +148,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_LINUX,
ARG_INITRD,
ARG_QEMU_GUI,
ARG_NETWORK_USER_MODE,
ARG_SECURE_BOOT,
ARG_SET_CREDENTIAL,
ARG_LOAD_CREDENTIAL,
@ -152,25 +156,27 @@ static int parse_argv(int argc, char *argv[]) {
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "quiet", no_argument, NULL, 'q' },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "image", required_argument, NULL, 'i' },
{ "machine", required_argument, NULL, 'M' },
{ "qemu-smp", required_argument, NULL, ARG_QEMU_SMP },
{ "qemu-mem", required_argument, NULL, ARG_QEMU_MEM },
{ "qemu-kvm", required_argument, NULL, ARG_QEMU_KVM },
{ "qemu-vsock", required_argument, NULL, ARG_QEMU_VSOCK },
{ "vsock-cid", required_argument, NULL, ARG_VSOCK_CID },
{ "tpm", required_argument, NULL, ARG_TPM },
{ "linux", required_argument, NULL, ARG_LINUX },
{ "initrd", required_argument, NULL, ARG_INITRD },
{ "qemu-gui", no_argument, NULL, ARG_QEMU_GUI },
{ "secure-boot", required_argument, NULL, ARG_SECURE_BOOT },
{ "set-credential", required_argument, NULL, ARG_SET_CREDENTIAL },
{ "load-credential", required_argument, NULL, ARG_LOAD_CREDENTIAL },
{ "firmware", required_argument, NULL, ARG_FIRMWARE },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "quiet", no_argument, NULL, 'q' },
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
{ "image", required_argument, NULL, 'i' },
{ "machine", required_argument, NULL, 'M' },
{ "qemu-smp", required_argument, NULL, ARG_QEMU_SMP },
{ "qemu-mem", required_argument, NULL, ARG_QEMU_MEM },
{ "qemu-kvm", required_argument, NULL, ARG_QEMU_KVM },
{ "qemu-vsock", required_argument, NULL, ARG_QEMU_VSOCK },
{ "vsock-cid", required_argument, NULL, ARG_VSOCK_CID },
{ "tpm", required_argument, NULL, ARG_TPM },
{ "linux", required_argument, NULL, ARG_LINUX },
{ "initrd", required_argument, NULL, ARG_INITRD },
{ "qemu-gui", no_argument, NULL, ARG_QEMU_GUI },
{ "network-tap", no_argument, NULL, 'n' },
{ "network-user-mode", no_argument, NULL, ARG_NETWORK_USER_MODE },
{ "secure-boot", required_argument, NULL, ARG_SECURE_BOOT },
{ "set-credential", required_argument, NULL, ARG_SET_CREDENTIAL },
{ "load-credential", required_argument, NULL, ARG_LOAD_CREDENTIAL },
{ "firmware", required_argument, NULL, ARG_FIRMWARE },
{}
};
@ -180,7 +186,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argv);
optind = 0;
while ((c = getopt_long(argc, argv, "+hi:M:q", options, NULL)) >= 0)
while ((c = getopt_long(argc, argv, "+hi:M:nq", options, NULL)) >= 0)
switch (c) {
case 'h':
return help();
@ -281,6 +287,14 @@ static int parse_argv(int argc, char *argv[]) {
arg_qemu_gui = true;
break;
case 'n':
arg_network_stack = QEMU_NET_TAP;
break;
case ARG_NETWORK_USER_MODE:
arg_network_stack = QEMU_NET_USER;
break;
case ARG_SECURE_BOOT:
r = parse_tristate(optarg, &arg_secure_boot);
if (r < 0)
@ -702,8 +716,7 @@ static int run_virtual_machine(void) {
"-smp", arg_qemu_smp ?: "1",
"-m", mem,
"-object", "rng-random,filename=/dev/urandom,id=rng0",
"-device", "virtio-rng-pci,rng=rng0,id=rng-device0",
"-nic", "user,model=virtio-net-pci"
"-device", "virtio-rng-pci,rng=rng0,id=rng-device0"
);
if (!cmdline)
return log_oom();
@ -722,6 +735,15 @@ static int run_virtual_machine(void) {
}
}
if (arg_network_stack == QEMU_NET_TAP)
r = strv_extend_many(&cmdline, "-nic", "tap,script=no,model=virtio-net-pci");
else if (arg_network_stack == QEMU_NET_USER)
r = strv_extend_many(&cmdline, "-nic", "user,model=virtio-net-pci");
else
r = strv_extend_many(&cmdline, "-nic", "none");
if (r < 0)
return log_oom();
bool use_vsock = arg_qemu_vsock > 0 && ARCHITECTURE_SUPPORTS_SMBIOS;
if (arg_qemu_vsock < 0) {
r = qemu_check_vsock_support();
@ -1062,6 +1084,13 @@ static int determine_names(void) {
return 0;
}
static int verify_arguments(void) {
if (arg_network_stack == QEMU_NET_TAP && !arg_privileged)
return log_error_errno(SYNTHETIC_ERRNO(EPERM), "--network-tap requires root privileges, refusing.");
return 0;
}
static int run(int argc, char *argv[]) {
int r;
@ -1077,6 +1106,10 @@ static int run(int argc, char *argv[]) {
if (r < 0)
return r;
r = verify_arguments();
if (r < 0)
return r;
if (!arg_quiet) {
_cleanup_free_ char *u = NULL;
(void) terminal_urlify_path(arg_image, arg_image, &u);