[PATCH v2 0/4] launch: libvirt: Use qemu-bridge-helper to implement a full network (RHBZ#1148012).
qemu in SLIRP mode offers DHCP services to the appliance. We don't use them, but use a fixed IP address intead. This changes the appliance to get its IP address using DHCP. Note: This is only used when the network is enabled. dhclient is somewhat slower, but the penalty (a few seconds) is only paid for network users. We could consider using the faster systemd dhcp client instead. --- appliance/init | 9 +++------ appliance/packagelist.in | 1 + 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/appliance/init b/appliance/init index 6d62338..d688a52 100755 --- a/appliance/init +++ b/appliance/init @@ -79,12 +79,9 @@ hwclock -u -s ip addr add 127.0.0.1/8 brd + dev lo scope host ip link set dev lo up -ip addr add 169.254.2.10/16 brd + dev eth0 scope global -ip link set dev eth0 up - -ip route add default via 169.254.2.2 - -echo nameserver 169.254.2.3 > /etc/resolv.conf +if grep -sq guestfs_network=1 /proc/cmdline; then + dhclient +fi # Scan for MDs. mdadm -As --auto=yes --run diff --git a/appliance/packagelist.in b/appliance/packagelist.in index 276b4c2..4e93eaf 100644 --- a/appliance/packagelist.in +++ b/appliance/packagelist.in @@ -210,6 +210,7 @@ binutils bzip2 coreutils cpio +dhclient diffutils dosfstools e2fsprogs -- 2.0.4
On Thu, Oct 02, Richard W.M. Jones wrote:
+if grep -sq guestfs_network=1 /proc/cmdline; then + dhclient +fi
dhclient will be missing at least in openSUSE. Not an issue now, does the script fail if the command fails to execute due to ENOENT? Olaf
On Thu, Oct 02, 2014 at 01:43:46PM +0200, Olaf Hering wrote:
On Thu, Oct 02, Richard W.M. Jones wrote:
+if grep -sq guestfs_network=1 /proc/cmdline; then + dhclient +fi
dhclient will be missing at least in openSUSE. Not an issue now, does the script fail if the command fails to execute due to ENOENT?
The script won't fail, but the network won't work. What's the alternative on SuSE? Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-builder quickly builds VMs from scratch http://libguestfs.org/virt-builder.1.html
On Thu, Oct 02, Richard W.M. Jones wrote:
The script won't fail, but the network won't work. What's the alternative on SuSE?
I think that would be dhcpcd, which is also used by NetworkManager. Olaf
On Thu, Oct 02, 2014 at 01:53:45PM +0200, Olaf Hering wrote:
On Thu, Oct 02, Richard W.M. Jones wrote:
The script won't fail, but the network won't work. What's the alternative on SuSE?
I think that would be dhcpcd, which is also used by NetworkManager.
As a client? Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://people.redhat.com/~rjones/virt-top
On Thu, Oct 02, 2014 at 01:53:45PM +0200, Olaf Hering wrote:
On Thu, Oct 02, Richard W.M. Jones wrote:
The script won't fail, but the network won't work. What's the alternative on SuSE?
I think that would be dhcpcd, which is also used by NetworkManager.
Ah so it is ... Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com libguestfs lets you edit virtual machines. Supports shell scripting, bindings from many languages. http://libguestfs.org
On Thu, Oct 02, 2014 at 01:53:45PM +0200, Olaf Hering wrote:
On Thu, Oct 02, Richard W.M. Jones wrote:
The script won't fail, but the network won't work. What's the alternative on SuSE?
I think that would be dhcpcd, which is also used by NetworkManager.
It turns out we don't package dhcpcd in Fedora. If we did the following, would it work? if grep -sq guestfs_network=1 /proc/cmdline; then if dhclient --version >/dev/null 2>&1; then dhclient else dhcpcd fi fi It seems as if it would, from reading the dhcpcd man page .. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://people.redhat.com/~rjones/virt-top
On Thu, Oct 02, 2014 at 02:10:27PM +0200, Olaf Hering wrote:
On Thu, Oct 02, Richard W.M. Jones wrote:
It seems as if it would, from reading the dhcpcd man page ..
Looks like the syntax is 'dhcpcd <interface>'.
I haven't tried it of course, but it looks from the man page like dhcpcd will try to configure all interfaces if no interface is specified. It would be a great help if you could confirm this. I'm mainly worried that we won't know how interfaces are named, although the old code assumed eth0 and appeared to work until now. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://people.redhat.com/~rjones/virt-top
On Thu, Oct 02, Richard W.M. Jones wrote:
I'm mainly worried that we won't know how interfaces are named, although the old code assumed eth0 and appeared to work until now.
Yes. And if the appliance is booted with net.ifnames=0, or whatever keeps systemd out of the picture, the name will be predictable. Olaf
On Thu, Oct 02, Olaf Hering wrote:
On Thu, Oct 02, Richard W.M. Jones wrote:
The script won't fail, but the network won't work. What's the alternative on SuSE? I think that would be dhcpcd, which is also used by NetworkManager.
Scratch that. At least in SLED12 dhclient comes from dhcp-client.rpm. Olaf
On Thursday 02 October 2014 12:39:56 Richard W.M. Jones wrote:
qemu in SLIRP mode offers DHCP services to the appliance. We don't use them, but use a fixed IP address intead. This changes the appliance to get its IP address using DHCP.
Note: This is only used when the network is enabled. dhclient is somewhat slower, but the penalty (a few seconds) is only paid for network users. We could consider using the faster systemd dhcp client instead. --- appliance/init | 9 +++------ appliance/packagelist.in | 1 + 2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/appliance/init b/appliance/init index 6d62338..d688a52 100755 --- a/appliance/init +++ b/appliance/init @@ -79,12 +79,9 @@ hwclock -u -s ip addr add 127.0.0.1/8 brd + dev lo scope host ip link set dev lo up
-ip addr add 169.254.2.10/16 brd + dev eth0 scope global -ip link set dev eth0 up - -ip route add default via 169.254.2.2 - -echo nameserver 169.254.2.3 > /etc/resolv.conf +if grep -sq guestfs_network=1 /proc/cmdline; then + dhclient +fi
When I tried v1 of this patch, with direct backend I still needed the manual filling of /etc/resolv.conf, otherwise it was not able to resolve names.
diff --git a/appliance/packagelist.in b/appliance/packagelist.in index 276b4c2..4e93eaf 100644 --- a/appliance/packagelist.in +++ b/appliance/packagelist.in @@ -210,6 +210,7 @@ binutils bzip2 coreutils cpio +dhclient diffutils dosfstools e2fsprogs
This should be moved to the REDHAT section, as this package name differs between distributions: - REDHAT: dhclient - DEBIAN: isc-dhcp-client - ARCHLINUX: dhclient -- Pino Toscano
When using the libvirt backend, don't use the SLIRP. Use qemu-bridge-helper via libvirt to give us a full network connection. One consequence of this is that 'ping' works in 'virt-builder --run-command'. A less useful consequence is that the host firewall will prevent connections on non-standard ports to the host. So you can't (eg) connect to a rsync daemon on the host listening on an arbitrary port, which worked before. The default bridge is 'virbr0', but you can override this by setting LIBGUESTFS_BACKEND_SETTINGS=network_bridge=<some_bridge> Note: this does not fix virt-rescue (since it overrides the default backend and uses 'direct' for various reasons). --- src/guestfs.pod | 10 ++++++++++ src/launch-libvirt.c | 44 +++++++++++++++++++++++--------------------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/guestfs.pod b/src/guestfs.pod index e4f9b54..f133fee 100644 --- a/src/guestfs.pod +++ b/src/guestfs.pod @@ -1519,6 +1519,16 @@ On Fedora, install C<kernel-debuginfo> for the C<vmlinux> file (containing symbols). Make sure the symbols precisely match the kernel being used. +=head3 network_bridge + +The libvirt backend supports: + + export LIBGUESTFS_BACKEND_SETTINGS=network_bridge=virbrX + +This allows you to override the bridge that is connected to when the +network is enabled. The default is C<virbr0>. See also +L</guestfs_set_network>. + =head2 ATTACHING TO RUNNING DAEMONS I<Note (1):> This is B<highly experimental> and has a tendency to eat diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c index 706ae38..f8f818a 100644 --- a/src/launch-libvirt.c +++ b/src/launch-libvirt.c @@ -105,6 +105,7 @@ struct backend_libvirt_data { char *selinux_label; char *selinux_imagelabel; bool selinux_norelabel_disks; + char *network_bridge; char name[DOMAIN_NAME_LEN]; /* random name */ bool is_kvm; /* false = qemu, true = kvm (from capabilities)*/ unsigned long qemu_version; /* qemu version (from libvirt) */ @@ -325,6 +326,12 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri) guestfs_get_backend_setting (g, "internal_libvirt_imagelabel"); data->selinux_norelabel_disks = guestfs___get_backend_setting_bool (g, "internal_libvirt_norelabel_disks"); + if (g->enable_network) { + data->network_bridge = + guestfs_get_backend_setting (g, "network_bridge"); + if (!data->network_bridge) + data->network_bridge = safe_strdup (g, "virbr0"); + } guestfs_pop_error_handler (g); /* Locate and/or build the appliance. */ @@ -1236,6 +1243,19 @@ construct_libvirt_xml_devices (guestfs_h *g, } end_element (); } end_element (); + /* Connect to libvirt bridge (see: RHBZ#1148012). */ + if (g->enable_network) { + start_element ("interface") { + attribute ("type", "bridge"); + start_element ("source") { + attribute ("bridge", params->data->network_bridge); + } end_element (); + start_element ("model") { + attribute ("type", "virtio"); + } end_element (); + } end_element (); + } + } end_element (); /* </devices> */ return 0; @@ -1617,27 +1637,6 @@ construct_libvirt_xml_qemu_cmdline (guestfs_h *g, attribute ("value", tmpdir); } end_element (); - /* Workaround because libvirt user networking cannot specify "net=" - * parameter. - */ - if (g->enable_network) { - start_element ("qemu:arg") { - attribute ("value", "-netdev"); - } end_element (); - - start_element ("qemu:arg") { - attribute ("value", "user,id=usernet,net=169.254.0.0/16"); - } end_element (); - - start_element ("qemu:arg") { - attribute ("value", "-device"); - } end_element (); - - start_element ("qemu:arg") { - attribute ("value", VIRTIO_NET ",netdev=usernet"); - } end_element (); - } - /* The qemu command line arguments requested by the caller. */ for (hp = g->hv_params; hp; hp = hp->next) { start_element ("qemu:arg") { @@ -1707,6 +1706,9 @@ shutdown_libvirt (guestfs_h *g, void *datav, int check_for_errors) free (data->selinux_imagelabel); data->selinux_imagelabel = NULL; + free (data->network_bridge); + data->network_bridge = NULL; + return ret; } -- 2.0.4
This are commented out (still) so this change does nothing. --- appliance/init | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/appliance/init b/appliance/init index d688a52..b1e7184 100755 --- a/appliance/init +++ b/appliance/init @@ -110,8 +110,7 @@ if grep -sq guestfs_verbose=1 /proc/cmdline; then date echo -n "clocksource: " cat /sys/devices/system/clocksource/clocksource0/current_clocksource - #ping -n -v -c 5 10.0.2.2 - #ping -n -v -c 5 10.0.2.4 + #ping -n -v -c 5 8.8.8.8 echo -n "uptime: "; cat /proc/uptime fi -- 2.0.4
It would work, except if you have a host firewall which will block inbound connections on virbr0 to non-standard ports. --- tests/rsync/test-rsync.sh | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/tests/rsync/test-rsync.sh b/tests/rsync/test-rsync.sh index 793d59d..53fcab8 100755 --- a/tests/rsync/test-rsync.sh +++ b/tests/rsync/test-rsync.sh @@ -33,10 +33,33 @@ if ! rsync --help >/dev/null 2>&1; then exit 77 fi -if [ "$(guestfish get-backend)" = "uml" ]; then - echo "$0: skipping test because networking is not available in the UML backend" - exit 77 -fi +# Get host IP address. XXX Bit of a hack. +backend="$(guestfish get-backend)" +case "$backend" in + direct) + ip=169.254.2.2 + listen_address=localhost + ;; + libvirt|libvirt:*) + # This would work, except that the host firewall is effective + # on virbr0, and that is likely to block the non-standard port + # number that we listen on. +# ip="$(ip -4 -o address show virbr0 | +# awk '{print $4}' | +# awk -F/ '{print $1}')" +# listen_address="$ip" + echo "$0: skipping test because host firewall will probably prevent this test from working" + exit 77 + ;; + uml) + echo "$0: skipping test because networking is not available in the UML backend" + exit 77 + ;; + *) + echo "$0: don't know how to get IP address of backend $backend" + exit 77 + ;; +esac # If rsync is not available, bail. if ! guestfish -a /dev/null run : available rsync; then @@ -56,7 +79,7 @@ port="$(awk 'BEGIN{srand(); print 65000+int(500*rand())}' </dev/null)" # Write an rsync daemon config file. cat > rsyncd.conf <<EOF -address = localhost +address = $listen_address port = $port pid file = $pwd/rsyncd.pid [src] @@ -80,8 +103,6 @@ function cleanup () } trap cleanup INT TERM QUIT EXIT -# XXX -ip=169.254.2.2 user="$(id -un)" guestfish --network -N test-rsync.img=fs -m /dev/sda1 <<EOF -- 2.0.4
participants (3)
-
Olaf Hering -
Pino Toscano -
Richard W.M. Jones