From b702ec19e859f6f3333b129a8b0a7fc278ed400f Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 8 Feb 2017 17:00:57 +0000 Subject: [PATCH] contrib: p2v: Add scripts to build and test virt-p2v ISOs with RHEL 5, 6. This adds a contrib script which can be used to build the virt-p2v ISO on top of RHEL 5 or RHEL 6, i686 (32 bit) or x86-64 (64 bit) base. There is also a script for testing the ISOs produced this way. --- .gitignore | 3 +- Makefile.am | 5 + contrib/README | 3 + contrib/p2v/aux-scripts/do-build.sh | 196 ++++++++++++++++++ contrib/p2v/build-p2v-iso.sh | 154 ++++++++++++++ ...BLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch | 54 +++++ ...-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch | 34 +++ contrib/p2v/test-p2v-iso.sh | 63 ++++++ 8 files changed, 511 insertions(+), 1 deletion(-) create mode 100644 contrib/p2v/aux-scripts/do-build.sh create mode 100755 contrib/p2v/build-p2v-iso.sh create mode 100644 contrib/p2v/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch create mode 100644 contrib/p2v/patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch create mode 100755 contrib/p2v/test-p2v-iso.sh diff --git a/.gitignore b/.gitignore index dde7a529b..0ea250831 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,6 @@ *.log *.o *.orig -*.patch *.pyc *.rej *.swp @@ -34,6 +33,8 @@ Makefile Makefile.in /.sc-* +/*.patch + /ABOUT-NLS /aclocal.m4 /align/stamp-virt-alignment-scan.pod diff --git a/Makefile.am b/Makefile.am index f3ecb8fe8..d27806717 100644 --- a/Makefile.am +++ b/Makefile.am @@ -215,6 +215,11 @@ EXTRA_DIST = \ contrib/intro/vmm-icons-t.png \ contrib/intro/vmm-icons.png \ contrib/intro/win7.xml \ + contrib/p2v/aux-scripts/do-build.sh \ + contrib/p2v/build-p2v-iso.sh \ + contrib/p2v/patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch \ + contrib/p2v/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch \ + contrib/p2v/test-p2v-iso.sh \ contrib/README \ contrib/visualize-alignment/.gitignore \ contrib/visualize-alignment/guestfish-add-mount.qtr \ diff --git a/contrib/README b/contrib/README index fb359f9e3..811f005c6 100644 --- a/contrib/README +++ b/contrib/README @@ -18,6 +18,9 @@ make-check-on-installed.pl we release them. Note that a checked out copy of the source from git is required. Read the top of the file before using. +p2v/ Hacky script to build virt-p2v ISO on top of RHEL 5/6/7, + for 32 bit (i686) and 64 bit (x86-64). + windows-icons.pl This script lets you extract all the icons from a Windows guest. We use this to locate the Windows logo in new releases diff --git a/contrib/p2v/aux-scripts/do-build.sh b/contrib/p2v/aux-scripts/do-build.sh new file mode 100644 index 000000000..5edb53d0e --- /dev/null +++ b/contrib/p2v/aux-scripts/do-build.sh @@ -0,0 +1,196 @@ +#!/bin/bash - +# Auxiliary script for building virt-p2v ISO. +# Copyright (C) 2017 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# See build-p2v-iso.sh + +set -e +set -x + +# Make sure we're in the virtual environment, and refuse to run otherwise. +if [ ! -f /var/tmp/livecd ]; then + echo "$0: do not run this script directly" + exit 1 +fi + +# If the script exits for any reason (including success) reboot. This +# in fact powers off the virtual machine because we are using +# qemu -no-reboot. +trap reboot INT QUIT TERM EXIT ERR + +cd /var/tmp + +osversion=`cat osversion` +livecd=`cat livecd` +source ./proxy +prefix=`rpm --eval '%_prefix'` +libdir=`rpm --eval '%_libdir'` +sysconfdir=`rpm --eval '%_sysconfdir'` + +# Build virt-p2v from libguestfs sources. +# We have to start from a tarball because at least RHEL 5 autotools +# isn't sufficiently new to run autoreconf. +zcat libguestfs.tar.gz | tar xf - +pushd libguestfs-* + +# Various hacks for different versions of RHEL. +case $osversion in + rhel-5.*|centos-5.*) + # This just forces configure to ignore these missing dependencies. + export LIBTINFO_CFLAGS=-D_GNU_SOURCE + export LIBTINFO_LIBS=-lncurses + export YAJL_CFLAGS=-D_GNU_SOURCE + export YAJL_LIBS=-lyajl + # Remove some unsupported flags that the configure script hard codes. + sed -i -e 's/-fno-strict-overflow//' configure + sed -i -e 's/-Wno-strict-overflow//' configure + # Apply some RHEL 5 only patches. + patch -p1 < ../patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch + patch -p1 < ../patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch + ;; + rhel-6.*|centos-6.*) + # This just forces configure to ignore these missing dependencies. + export LIBTINFO_CFLAGS=-D_GNU_SOURCE + export LIBTINFO_LIBS=-lncurses + export YAJL_CFLAGS=-D_GNU_SOURCE + export YAJL_LIBS=-lyajl + ;; +esac + +export vmchannel_test=no +./configure \ + --prefix $prefix \ + --libdir $libdir \ + --sysconfdir $sysconfdir \ + --disable-static \ + --disable-appliance \ + --disable-daemon \ + --disable-lua \ + --disable-ocaml \ + --disable-perl \ + --disable-php \ + --disable-python \ + --disable-ruby \ + --with-qemu=no +# We only need to build a handful of directories to get virt-p2v. +make -C generator +make -C gnulib/lib +make -C common/utils +make -C common/miniexpect +make -C p2v virt-p2v virt-p2v.xz dependencies.redhat +make run + +# Check virt-p2v was built and runs. +./run ./p2v/virt-p2v --version +./run ./p2v/virt-p2v-make-kickstart --version + +# Create the kickstart file. +if [ "x$http_proxy" != "x" ]; then proxy="--proxy=$http_proxy"; fi +./run ./p2v/virt-p2v-make-kickstart -o /var/tmp/p2v.ks $osversion $proxy + +popd + +# More hacks for different versions of RHEL. +case $osversion in + rhel-5.*|centos-5.*) + # RHEL 5 livecd-tools is broken with syslinux, this fixes it: + sed -i -e 's,/usr/lib/syslinux/,/usr/share/syslinux/,g'\ + /usr/lib/python2.4/site-packages/imgcreate/live.py + # livecd-tools cannot parse certain aspects of the kickstart: + sed -i \ + -e 's/--plaintext//g' \ + -e 's/^firewall.*//g' \ + -e 's/^%end.*//g' \ + p2v.ks + # Remove some packages which don't exist on RHEL 5: + sed -i \ + -e 's,^dracut-live.*,,g' \ + -e 's,^dejavu-.*,,g' \ + -e 's,^mesa-dri-drivers.*,,g' \ + -e 's,^network-manager-applet.*,,g' \ + -e 's,^nm-connection-editor.*,,g' \ + -e 's,^/usr/bin/qemu-nbd.*,,g' \ + -e '/^net-tools/a syslinux' \ + p2v.ks + # Remove systemctl lines, doesn't exist on RHEL 5. + sed -i \ + -e 's/^\(systemctl.*\)/#\1/g' \ + p2v.ks + ;; + rhel-6.*|centos-6.*) + # Remove some packages which don't exist on RHEL 6: + sed -i \ + -e 's,^dracut-live.*,,g' \ + -e 's,^firewalld.*,,g' \ + -e 's,^network-manager-applet.*,,g' \ + -e 's,^nm-connection-editor.*,,g' \ + -e 's,^/usr/bin/qemu-nbd.*,,g' \ + p2v.ks + # Remove systemctl lines, doesn't exist on RHEL 5. + sed -i \ + -e 's/^\(systemctl.*\)/#\1/g' \ + p2v.ks + ;; +esac + +# Build nbdkit +zcat nbdkit.tar.gz | tar xf - +pushd nbdkit-* +./configure \ + CFLAGS="-D_GNU_SOURCE" \ + --prefix $prefix \ + --libdir $libdir \ + --sysconfdir $sysconfdir \ + --without-liblzma +make +cp src/nbdkit .. +cp plugins/file/.libs/nbdkit-file-plugin.so .. +popd +gzip -c nbdkit > nbdkit.gz +gzip -c nbdkit-file-plugin.so > nbdkit-file-plugin.so.gz +base64 nbdkit.gz > nbdkit.gz.b64 +base64 nbdkit-file-plugin.so.gz > nbdkit-file-plugin.so.gz.b64 + +# Add nbdkit binaries to the kickstart. +echo > fragment.ks +echo '#' `md5sum nbdkit` >> fragment.ks +echo 'base64 -d -i < /usr/bin/nbdkit' >> fragment.ks +cat nbdkit.gz.b64 >> fragment.ks +echo >> fragment.ks +echo EOF >> fragment.ks +echo 'chmod 0755 /usr/bin/nbdkit' >> fragment.ks +echo >> fragment.ks + +echo '#' `md5sum nbdkit-file-plugin.so` >> fragment.ks +echo 'mkdir -p' $libdir/nbdkit/plugins >> fragment.ks +echo 'base64 -d -i <' $libdir/nbdkit/plugins/nbdkit-file-plugin.so >> fragment.ks +cat nbdkit-file-plugin.so.gz.b64 >> fragment.ks +echo >> fragment.ks +echo EOF >> fragment.ks +echo 'chmod 0755' $libdir/nbdkit/plugins/nbdkit-file-plugin.so >> fragment.ks +echo >> fragment.ks + +sed -i -e '/^chmod.*\/usr\/bin\/virt-p2v$/ r fragment.ks' p2v.ks + +# Run livecd-creator to make the live CD. The strange redirect works +# around a bug in RHEL 5's livecd-tools: "/sbin/mksquashfs: invalid +# option" is printed if the output is redirected to a file +# (https://bugs.centos.org/bug_view_page.php?bug_id=3738) +livecd-creator -c p2v.ks > `tty` 2>&1 + +# Move the live CD to the final filename. +mv livecd-*.iso $livecd diff --git a/contrib/p2v/build-p2v-iso.sh b/contrib/p2v/build-p2v-iso.sh new file mode 100755 index 000000000..c80a1b134 --- /dev/null +++ b/contrib/p2v/build-p2v-iso.sh @@ -0,0 +1,154 @@ +#!/bin/bash - +# Build virt-p2v ISO for RHEL 5/6/7. +# Copyright (C) 2017 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# This script is used to build the virt-p2v ISO on RHEL 5/6/7, +# for 32 bit (i686) and 64 bit (x86-64). +# +# This script is *not* used to build the official RHEL 7 virt-p2v ISO +# for Red Hat customers. However it is used to build alternate ISOs +# which can optionally be used by customers who need older RHEL +# (eg. for proprietary FakeRAID drivers), or have 32 bit physical +# machines that they wish to virtualize. +# +# The virt-p2v ISOs built by this script are hosted at: +# http://oirase.annexia.org/virt-p2v/ + +set -e + +usage () +{ + echo ' libguestfs and nbdkit tarballs' + echo ' (http URLs may also be used here)' + echo ' |' + echo './build-p2v-iso.sh file:///path/to/libguestfs-1.XX.YY.tar.gz \' + echo ' file:///path/to/nbdkit-1.XX.YY.tar.gz \' + echo ' rhel-5.11 i686' + echo ' | |' + echo ' | `--- architecture (i686 or x86_64)' + echo ' `---- version of RHEL (5.x or 6.x tested)' + echo + echo 'Note this downloads the libguestfs tarball from upstream, it' + echo 'does not use libguestfs from the current directory.' + echo + echo 'Minimum versions of: libguestfs = 1.35.22' + echo ' nbdkit = 1.1.13' + echo + echo 'You should run the script on a Fedora (or recent Linux) host.' + echo 'It uses virt-builder to create the RHEL environment' + exit 0 +} + +if [ $# -ne 4 ]; then + usage +fi + +tmpdir="$(mktemp -d)" +cleanup () +{ + rm -rf "$tmpdir" +} +trap cleanup INT QUIT TERM EXIT ERR + +libguestfs_tarball=$1 +nbdkit_tarball=$2 +osversion=$3 +arch=$4 + +# Get the path to the auxiliary script. +d="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +if [ ! -d "$d/aux-scripts" ]; then + echo "$0: error: cannot locate auxiliary scripts" + exit 1 +fi + +# Build the list of packages needed for the build environment. +pkgs=augeas-devel,bison,coreutils,cpio,file-devel,flex,gcc,gperf,gtk2-devel,libxml2-devel,livecd-tools,mkisofs,ncurses-devel,patch,perl-Pod-Man,perl-Pod-Simple,pcre-devel,/usr/bin/pod2text,syslinux,syslinux-extlinux,xz,xz-devel + +for f in `cat $d/../../p2v/dependencies.redhat`; do + pkgs="$pkgs,$f" +done + +# Various hacks for different versions of RHEL. +if=virtio +netdev=virtio-net-pci +pkgs="$pkgs,yajl-devel" +declare -a epel +case $osversion in + rhel-5.*|centos-5.*) + if=ide + netdev=rtl8139 + # RHEL 5 yum cannot download a package. + curl -o $tmpdir/epel-release.rpm https://dl.fedoraproject.org/pub/epel/epel-release-latest-5.noarch.rpm + epel[0]="--upload" + epel[1]="$tmpdir/epel-release.rpm:/var/tmp" + # RHEL 5 i686 template has a broken RPM DB, so rebuild it. + epel[2]="--run-command" + epel[3]="rm -f /var/lib/rpm/__db*; rpm -vv --rebuilddb" + epel[4]="--run-command" + epel[5]="yum install -y --nogpgcheck /var/tmp/epel-release.rpm" + ;; + rhel-6.*|centos-6.*) + epel[0]="--run-command" + epel[1]="yum install -y --nogpgcheck https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm" + ;; + rhel-7.*|centos-7.*) + epel[0]="--run-command" + epel[1]="yum install -y --nogpgcheck https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm" + ;; +esac + +# Download libguestfs and nbdkit sources. +curl -o $tmpdir/libguestfs.tar.gz $libguestfs_tarball +curl -o $tmpdir/nbdkit.tar.gz $nbdkit_tarball + +# Write a proxy file for the guest environment. +echo "export http_proxy=$http_proxy" >> $tmpdir/proxy +echo "export https_proxy=$https_proxy" >> $tmpdir/proxy +echo "export ftp_proxy=$ftp_proxy" >> $tmpdir/proxy + +# Build the temporary guest RHEL environment. +disk=$tmpdir/tmp-$osversion.img +livecd=virt-p2v-livecd-$osversion-$arch-`date +"%Y%m%d%H%M"`.iso +virt-builder $osversion --arch $arch \ + --size 20G --output $disk \ + "${epel[@]}" \ + --install "$pkgs" \ + --upload $tmpdir/libguestfs.tar.gz:/var/tmp \ + --upload $tmpdir/nbdkit.tar.gz:/var/tmp \ + --copy-in $d/patches:/var/tmp \ + --write /var/tmp/osversion:$osversion \ + --write /var/tmp/livecd:$livecd \ + --upload $tmpdir/proxy:/var/tmp/proxy \ + --firstboot $d/aux-scripts/do-build.sh \ + --selinux-relabel + +# Run the guest. +qemu-system-x86_64 -nodefconfig -nodefaults -nographic \ + -no-reboot \ + -machine accel=kvm:tcg \ + -cpu host \ + -m 4096 \ + -drive file=$disk,format=raw,if=$if \ + -netdev user,id=usernet,net=169.254.0.0/16 \ + -device $netdev,netdev=usernet \ + -serial stdio + +# Did we get any output from the auxiliary script? +# (This command will fail if not) +guestfish --ro -a $disk -i download /var/tmp/$livecd $livecd +ls -lh $livecd diff --git a/contrib/p2v/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch b/contrib/p2v/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch new file mode 100644 index 000000000..a4efb38bf --- /dev/null +++ b/contrib/p2v/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch @@ -0,0 +1,54 @@ +From 28dd464c8e78f241622d142671a61a75bf5d758e Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 21 Jan 2017 05:30:40 -0500 +Subject: [PATCH 1/2] RHEL 5 ONLY DISABLE AUTOMATIC REMOTE PORT ALLOCATION + +--- + p2v/ssh.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/p2v/ssh.c b/p2v/ssh.c +index 8beaf74..919f2df 100644 +--- a/p2v/ssh.c ++++ b/p2v/ssh.c +@@ -1044,16 +1044,28 @@ open_data_connection (struct config *config, + "-N", + NULL + }; ++#if 0 + CLEANUP_FREE char *port_str = NULL; + const int ovecsize = 12; + int ovector[ovecsize]; ++#endif + +- snprintf (remote_arg, sizeof remote_arg, "0:%s:%d", local_ipaddr, local_port); ++ /* RHEL 5 hack: ssh does not print the "Allocated port ..." string, ++ * so we cannot find the remotely allocated port. Instead just ++ * assign a random port and hope for the best. ++ */ ++ static int next_remote_port = 58123; ++ ++ snprintf (remote_arg, sizeof remote_arg, "%d:%s:%d", ++ next_remote_port, local_ipaddr, local_port); ++ *remote_port = next_remote_port; ++ next_remote_port++; + + h = start_ssh (0, config, (char **) extra_args, 0); + if (h == NULL) + return NULL; + ++#if 0 + switch (mexp_expect (h, + (mexp_regexp[]) { + { 100, .re = portfwd_re }, +@@ -1094,6 +1106,7 @@ open_data_connection (struct config *config, + mexp_close (h); + return NULL; + } ++#endif + + return h; + } +-- +1.8.2.3 + diff --git a/contrib/p2v/patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch b/contrib/p2v/patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch new file mode 100644 index 000000000..d0bc2cfc9 --- /dev/null +++ b/contrib/p2v/patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch @@ -0,0 +1,34 @@ +From 3ccd25c981431426038d7952f5b0b86118d92c23 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 21 Jan 2017 05:57:17 -0500 +Subject: [PATCH 2/2] RHEL 5 ONLY QEMU-NBD 1.4 HAS NO -f OPTION + +--- + p2v/nbd.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/p2v/nbd.c b/p2v/nbd.c +index b1caf2f..2232b08 100644 +--- a/p2v/nbd.c ++++ b/p2v/nbd.c +@@ -409,7 +409,7 @@ start_qemu_nbd (const char *device, + "-r", /* readonly (vital!) */ + "-p", port_str, /* listening port */ + "-t", /* persistent */ +- "-f", "raw", /* force raw format */ ++ //"-f", "raw", /* force raw format */ + "-b", ipaddr, /* listen only on loopback interface */ + "--cache=unsafe", /* use unsafe caching for speed */ + device, /* a device like /dev/sda */ +@@ -424,7 +424,7 @@ start_qemu_nbd (const char *device, + "qemu-nbd", + "-r", /* readonly (vital!) */ + "-t", /* persistent */ +- "-f", "raw", /* force raw format */ ++ //"-f", "raw", /* force raw format */ + "--cache=unsafe", /* use unsafe caching for speed */ + device, /* a device like /dev/sda */ + NULL); +-- +1.8.2.3 + diff --git a/contrib/p2v/test-p2v-iso.sh b/contrib/p2v/test-p2v-iso.sh new file mode 100755 index 000000000..cdc4a5412 --- /dev/null +++ b/contrib/p2v/test-p2v-iso.sh @@ -0,0 +1,63 @@ +#!/bin/bash - +# Test virt-p2v ISO for RHEL 5/6/7. +# Copyright (C) 2017 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# Once you have built a virt-p2v ISO (see build-p2v-iso.sh), you +# can interactively test it using this script. + +set -e + +usage () +{ + echo './test-p2v-iso.sh virt-p2v-livecd-....iso' + exit 0 +} + +if [ $# -ne 1 ]; then + usage +fi + +tmpdir="$(mktemp -d)" +cleanup () +{ + rm -rf "$tmpdir" +} +trap cleanup INT QUIT TERM EXIT ERR + +iso=$1 +if [ ! -f "$iso" ]; then + echo "$iso: file not found" + exit 1 +fi + +# Build a temporary guest to test. +disk=$tmpdir/guest.img +virt-builder rhel-6.8 --output $disk + +# Boot the guest as if running with virt-p2v ISO in the CD drive. +qemu-system-x86_64 -nodefconfig -nodefaults \ + -no-reboot \ + -machine accel=kvm:tcg \ + -cpu host \ + -m 4096 \ + -display gtk \ + -vga std \ + -drive file=$disk,format=raw,if=ide \ + -cdrom $iso \ + -netdev user,id=usernet,net=169.254.0.0/16 \ + -device rtl8139,netdev=usernet \ + -boot d