Pino Toscano
2019-Sep-10 14:35 UTC
[Libguestfs] [PATCH 0/2] Remove virt-p2v from libguestfs
Now that virt-p2v has its own repository [1] and releases [2], it is time to remove it from libguestfs. [1] https://github.com/libguestfs/virt-p2v [2] http://download.libguestfs.org/virt-p2v/ Pino Toscano (2): Remove virt-p2v Remove remaining virt-p2v bits .gitignore | 4 - Makefile.am | 7 +- bash/Makefile.am | 4 - bash/virt-alignment-scan | 18 - common/miniexpect/Makefile.am | 51 - common/miniexpect/README | 31 - common/miniexpect/miniexpect.c | 489 ---- common/miniexpect/miniexpect.h | 110 - common/miniexpect/miniexpect.pod | 496 ---- configure.ac | 18 +- contrib/README | 3 - docs/C_SOURCE_FILES | 2 - docs/guestfs-building.pod | 55 +- docs/guestfs-hacking.pod | 83 - generator/authors.ml | 9 - generator/authors.mli | 1 - generator/main.ml | 2 - installcheck.sh.in | 3 - m4/guestfs-v2v.m4 | 52 +- p2v/.gitignore | 49 - p2v/Makefile.am | 376 --- p2v/contrib/aux-scripts/do-build.sh | 196 -- p2v/contrib/build-p2v-iso.sh | 155 -- ...BLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch | 54 - ...-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch | 34 - p2v/contrib/test-p2v-iso.sh | 63 - p2v/conversion.c | 668 ----- p2v/cpuid.c | 222 -- p2v/dependencies.m4 | 181 -- p2v/generate-p2v-authors.pl | 54 - p2v/generate-p2v-config.pl | 915 ------- p2v/gui-gtk2-compat.h | 117 - p2v/gui-gtk3-compat.h | 140 - p2v/gui.c | 2295 ----------------- p2v/inhibit.c | 154 -- p2v/issue | 16 - p2v/kernel-cmdline.c | 196 -- p2v/kernel.c | 158 -- p2v/kiwi-config.sh | 73 - p2v/kiwi-config.xml.in | 92 - p2v/launch-virt-p2v | 51 - p2v/main.c | 583 ----- p2v/nbd.c | 840 ------ p2v/p2v.h | 136 - p2v/p2v.ks.in | 193 -- p2v/p2v.service | 38 - p2v/physical-xml.c | 304 --- p2v/rtc.c | 165 -- p2v/ssh.c | 1203 --------- p2v/test-virt-p2v-cmdline.sh | 53 - p2v/test-virt-p2v-docs.sh | 24 - p2v/test-virt-p2v-nbdkit.sh | 59 - p2v/test-virt-p2v-pxe.sh | 96 - p2v/test-virt-p2v-pxe.sshd_config.in | 43 - p2v/test-virt-p2v-scp.sh | 62 - p2v/test-virt-p2v-ssh.sh | 61 - p2v/test-virt-p2v.sh | 57 - p2v/utils.c | 256 -- p2v/virt-p2v-make-disk.in | 267 -- p2v/virt-p2v-make-disk.pod | 218 -- p2v/virt-p2v-make-kickstart.in | 241 -- p2v/virt-p2v-make-kickstart.pod | 339 --- p2v/virt-p2v-make-kiwi.in | 233 -- p2v/virt-p2v-make-kiwi.pod | 184 -- p2v/virt-p2v.pod | 757 ------ p2v/whole-file.c | 95 - po-docs/language.mk | 3 - po-docs/podfiles | 6 - po/POTFILES | 1 - run.in | 7 - 70 files changed, 6 insertions(+), 14215 deletions(-) delete mode 100644 common/miniexpect/Makefile.am delete mode 100644 common/miniexpect/README delete mode 100644 common/miniexpect/miniexpect.c delete mode 100644 common/miniexpect/miniexpect.h delete mode 100644 common/miniexpect/miniexpect.pod delete mode 100644 p2v/.gitignore delete mode 100644 p2v/Makefile.am delete mode 100644 p2v/contrib/aux-scripts/do-build.sh delete mode 100755 p2v/contrib/build-p2v-iso.sh delete mode 100644 p2v/contrib/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch delete mode 100644 p2v/contrib/patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch delete mode 100755 p2v/contrib/test-p2v-iso.sh delete mode 100644 p2v/conversion.c delete mode 100644 p2v/cpuid.c delete mode 100644 p2v/dependencies.m4 delete mode 100755 p2v/generate-p2v-authors.pl delete mode 100755 p2v/generate-p2v-config.pl delete mode 100644 p2v/gui-gtk2-compat.h delete mode 100644 p2v/gui-gtk3-compat.h delete mode 100644 p2v/gui.c delete mode 100644 p2v/inhibit.c delete mode 100644 p2v/issue delete mode 100644 p2v/kernel-cmdline.c delete mode 100644 p2v/kernel.c delete mode 100755 p2v/kiwi-config.sh delete mode 100644 p2v/kiwi-config.xml.in delete mode 100755 p2v/launch-virt-p2v delete mode 100644 p2v/main.c delete mode 100644 p2v/nbd.c delete mode 100644 p2v/p2v.h delete mode 100644 p2v/p2v.ks.in delete mode 100644 p2v/p2v.service delete mode 100644 p2v/physical-xml.c delete mode 100644 p2v/rtc.c delete mode 100644 p2v/ssh.c delete mode 100755 p2v/test-virt-p2v-cmdline.sh delete mode 100755 p2v/test-virt-p2v-docs.sh delete mode 100755 p2v/test-virt-p2v-nbdkit.sh delete mode 100755 p2v/test-virt-p2v-pxe.sh delete mode 100644 p2v/test-virt-p2v-pxe.sshd_config.in delete mode 100755 p2v/test-virt-p2v-scp.sh delete mode 100755 p2v/test-virt-p2v-ssh.sh delete mode 100755 p2v/test-virt-p2v.sh delete mode 100644 p2v/utils.c delete mode 100644 p2v/virt-p2v-make-disk.in delete mode 100644 p2v/virt-p2v-make-disk.pod delete mode 100644 p2v/virt-p2v-make-kickstart.in delete mode 100644 p2v/virt-p2v-make-kickstart.pod delete mode 100644 p2v/virt-p2v-make-kiwi.in delete mode 100644 p2v/virt-p2v-make-kiwi.pod delete mode 100644 p2v/virt-p2v.pod delete mode 100644 p2v/whole-file.c -- 2.21.0
This removes only the tool itself, and all the bits strictly needed to not break the build. This is now available as separate tool in its own repository: https://github.com/libguestfs/virt-p2v --- Makefile.am | 3 - configure.ac | 13 - generator/main.ml | 2 - installcheck.sh.in | 3 - p2v/.gitignore | 49 - p2v/Makefile.am | 376 --- p2v/contrib/aux-scripts/do-build.sh | 196 -- p2v/contrib/build-p2v-iso.sh | 155 -- ...BLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch | 54 - ...-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch | 34 - p2v/contrib/test-p2v-iso.sh | 63 - p2v/conversion.c | 668 ----- p2v/cpuid.c | 222 -- p2v/dependencies.m4 | 181 -- p2v/generate-p2v-authors.pl | 54 - p2v/generate-p2v-config.pl | 915 ------- p2v/gui-gtk2-compat.h | 117 - p2v/gui-gtk3-compat.h | 140 - p2v/gui.c | 2295 ----------------- p2v/inhibit.c | 154 -- p2v/issue | 16 - p2v/kernel-cmdline.c | 196 -- p2v/kernel.c | 158 -- p2v/kiwi-config.sh | 73 - p2v/kiwi-config.xml.in | 92 - p2v/launch-virt-p2v | 51 - p2v/main.c | 583 ----- p2v/nbd.c | 840 ------ p2v/p2v.h | 136 - p2v/p2v.ks.in | 193 -- p2v/p2v.service | 38 - p2v/physical-xml.c | 304 --- p2v/rtc.c | 165 -- p2v/ssh.c | 1203 --------- p2v/test-virt-p2v-cmdline.sh | 53 - p2v/test-virt-p2v-docs.sh | 24 - p2v/test-virt-p2v-nbdkit.sh | 59 - p2v/test-virt-p2v-pxe.sh | 96 - p2v/test-virt-p2v-pxe.sshd_config.in | 43 - p2v/test-virt-p2v-scp.sh | 62 - p2v/test-virt-p2v-ssh.sh | 61 - p2v/test-virt-p2v.sh | 57 - p2v/utils.c | 256 -- p2v/virt-p2v-make-disk.in | 267 -- p2v/virt-p2v-make-disk.pod | 218 -- p2v/virt-p2v-make-kickstart.in | 241 -- p2v/virt-p2v-make-kickstart.pod | 339 --- p2v/virt-p2v-make-kiwi.in | 233 -- p2v/virt-p2v-make-kiwi.pod | 184 -- p2v/virt-p2v.pod | 757 ------ p2v/whole-file.c | 95 - po-docs/language.mk | 3 - po-docs/podfiles | 5 - 53 files changed, 12795 deletions(-) delete mode 100644 p2v/.gitignore delete mode 100644 p2v/Makefile.am delete mode 100644 p2v/contrib/aux-scripts/do-build.sh delete mode 100755 p2v/contrib/build-p2v-iso.sh delete mode 100644 p2v/contrib/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch delete mode 100644 p2v/contrib/patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch delete mode 100755 p2v/contrib/test-p2v-iso.sh delete mode 100644 p2v/conversion.c delete mode 100644 p2v/cpuid.c delete mode 100644 p2v/dependencies.m4 delete mode 100755 p2v/generate-p2v-authors.pl delete mode 100755 p2v/generate-p2v-config.pl delete mode 100644 p2v/gui-gtk2-compat.h delete mode 100644 p2v/gui-gtk3-compat.h delete mode 100644 p2v/gui.c delete mode 100644 p2v/inhibit.c delete mode 100644 p2v/issue delete mode 100644 p2v/kernel-cmdline.c delete mode 100644 p2v/kernel.c delete mode 100755 p2v/kiwi-config.sh delete mode 100644 p2v/kiwi-config.xml.in delete mode 100755 p2v/launch-virt-p2v delete mode 100644 p2v/main.c delete mode 100644 p2v/nbd.c delete mode 100644 p2v/p2v.h delete mode 100644 p2v/p2v.ks.in delete mode 100644 p2v/p2v.service delete mode 100644 p2v/physical-xml.c delete mode 100644 p2v/rtc.c delete mode 100644 p2v/ssh.c delete mode 100755 p2v/test-virt-p2v-cmdline.sh delete mode 100755 p2v/test-virt-p2v-docs.sh delete mode 100755 p2v/test-virt-p2v-nbdkit.sh delete mode 100755 p2v/test-virt-p2v-pxe.sh delete mode 100644 p2v/test-virt-p2v-pxe.sshd_config.in delete mode 100755 p2v/test-virt-p2v-scp.sh delete mode 100755 p2v/test-virt-p2v-ssh.sh delete mode 100755 p2v/test-virt-p2v.sh delete mode 100644 p2v/utils.c delete mode 100644 p2v/virt-p2v-make-disk.in delete mode 100644 p2v/virt-p2v-make-disk.pod delete mode 100644 p2v/virt-p2v-make-kickstart.in delete mode 100644 p2v/virt-p2v-make-kickstart.pod delete mode 100644 p2v/virt-p2v-make-kiwi.in delete mode 100644 p2v/virt-p2v-make-kiwi.pod delete mode 100644 p2v/virt-p2v.pod delete mode 100644 p2v/whole-file.c diff --git a/Makefile.am b/Makefile.am index 5d12cc2be..1b7c98319 100644 --- a/Makefile.am +++ b/Makefile.am @@ -110,9 +110,6 @@ SUBDIRS += fish # virt-tools in C. SUBDIRS += align cat diff df edit format inspector make-fs rescue -if HAVE_P2V -SUBDIRS += common/miniexpect p2v -endif # bash-completion SUBDIRS += bash diff --git a/configure.ac b/configure.ac index 095ee96da..93fe063b4 100644 --- a/configure.ac +++ b/configure.ac @@ -213,12 +213,6 @@ AC_CONFIG_FILES([ocaml-dep.sh], [chmod +x,-w ocaml-dep.sh]) AC_CONFIG_FILES([ocaml-link.sh], [chmod +x,-w ocaml-link.sh]) -AC_CONFIG_FILES([p2v/virt-p2v-make-disk], - [chmod +x,-w p2v/virt-p2v-make-disk]) -AC_CONFIG_FILES([p2v/virt-p2v-make-kickstart], - [chmod +x,-w p2v/virt-p2v-make-kickstart]) -AC_CONFIG_FILES([p2v/virt-p2v-make-kiwi], - [chmod +x,-w p2v/virt-p2v-make-kiwi]) AC_CONFIG_FILES([php/extension/php-for-tests.sh], [chmod +x,-w php/extension/php-for-tests.sh]) AC_CONFIG_FILES([pick-guests.pl], @@ -298,7 +292,6 @@ AC_CONFIG_FILES([Makefile ocaml/META ocaml/Makefile ocaml/examples/Makefile - p2v/Makefile perl/Build.PL perl/Makefile perl/examples/Makefile @@ -381,10 +374,6 @@ AC_CONFIG_FILES([Makefile v2v/test-harness/META website/index.html]) -if test "x$HAVE_P2V_TRUE" = "x"; then - AC_CONFIG_COMMANDS([p2v/p2v-config.h], [${ac_srcdir}/p2v/generate-p2v-config.pl --file=p2v-config.h --output=p2v/p2v-config.h]) -fi - AC_OUTPUT dnl Produce summary. @@ -403,8 +392,6 @@ echo "FUSE filesystem ..................... $enable_fuse" echo "Default backend ..................... $DEFAULT_BACKEND" AS_ECHO_N(["GNU gettext for i18n ................ "]) if test "x$HAVE_GNU_GETTEXT_TRUE" = "x"; then echo "yes"; else echo "no"; fi -AS_ECHO_N(["virt-p2v ............................ "]) -if test "x$HAVE_P2V_TRUE" = "x"; then echo "yes"; else echo "no"; fi AS_ECHO_N(["OCaml bindings ...................... "]) if test "x$HAVE_OCAML_TRUE" = "x"; then echo "yes"; else echo "no"; fi AS_ECHO_N(["OCaml-based virt tools .............. "]) diff --git a/generator/main.ml b/generator/main.ml index 80000b1e3..eff417536 100644 --- a/generator/main.ml +++ b/generator/main.ml @@ -75,8 +75,6 @@ Run it from the top source directory using the command output_to "AUTHORS" Authors.generate_authors; - output_to "p2v/AUTHORS" - Authors.generate_p2v_authors; output_to "common/errnostring/errnostring-gperf.gperf" Errnostring.generate_errnostring_gperf; diff --git a/installcheck.sh.in b/installcheck.sh.in index a4829cda6..ed744cc60 100644 --- a/installcheck.sh.in +++ b/installcheck.sh.in @@ -61,9 +61,6 @@ cp @bindir@/virt-get-kernel get-kernel/ cp @bindir@/virt-inspector inspector/ cp @bindir@/virt-ls cat/ cp @bindir@/virt-make-fs make-fs/ -cp @libdir@/virt-p2v/virt-p2v.xz p2v/ -unxz -fk p2v/virt-p2v.xz -chmod +x p2v/virt-p2v cp @bindir@/virt-rescue rescue/ cp @bindir@/virt-resize resize/ cp @bindir@/virt-sparsify sparsify/ diff --git a/p2v/.gitignore b/p2v/.gitignore deleted file mode 100644 index 22ac25aed..000000000 --- a/p2v/.gitignore +++ /dev/null @@ -1,49 +0,0 @@ -*~ -*.log -*.o -*.trs -.deps -.libs -Makefile -Makefile.in - -/about-authors.c -/AUTHORS -/blank-part.img -/config.c -/dependencies.archlinux -/dependencies.debian -/dependencies.redhat -/dependencies.suse -/fedora.img -/kernel-config.c -/p2v-config.h -/stamp-test-virt-p2v-pxe-data-files -/stamp-test-virt-p2v-pxe-hostkey -/stamp-test-virt-p2v-pxe-kernel -/stamp-test-virt-p2v-pxe-userkey -/stamp-virt-p2v.pod -/stamp-virt-p2v-make-disk.pod -/stamp-virt-p2v-make-kickstart.pod -/stamp-virt-p2v-make-kiwi.pod -/test-virt-p2v-pxe.authorized_keys -/test-virt-p2v-pxe.id_rsa -/test-virt-p2v-pxe.id_rsa.pub -/test-virt-p2v-pxe.img -/test-virt-p2v-pxe.initramfs -/test-virt-p2v-pxe.sshd_config -/test-virt-p2v-pxe.ssh_host_rsa_key -/test-virt-p2v-pxe.ssh_host_rsa_key.pub -/test-virt-p2v-pxe.vmlinuz -/virt-p2v -/virt-p2v.1 -/virt-p2v.i686 -/virt-p2v.img -/virt-p2v-kernel-config.pod -/virt-p2v-make-disk -/virt-p2v-make-disk.1 -/virt-p2v-make-kickstart -/virt-p2v-make-kickstart.1 -/virt-p2v-make-kiwi -/virt-p2v-make-kiwi.1 -/virt-p2v.xz diff --git a/p2v/Makefile.am b/p2v/Makefile.am deleted file mode 100644 index 59846aeba..000000000 --- a/p2v/Makefile.am +++ /dev/null @@ -1,376 +0,0 @@ -# libguestfs virt-p2v -# Copyright (C) 2009-2019 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. - -include $(top_srcdir)/subdir-rules.mk - -generator_built = \ - AUTHORS - -BUILT_SOURCES = \ - $(generator_built) - -EXTRA_DIST = \ - .gitignore \ - $(BUILT_SOURCES) \ - $(TESTS) $(APPLIANCE_TESTS) $(SLOW_TESTS) \ - contrib/aux-scripts/do-build.sh \ - contrib/build-p2v-iso.sh \ - contrib/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch \ - contrib/patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch \ - contrib/test-p2v-iso.sh \ - dependencies.m4 \ - generate-p2v-authors.pl \ - generate-p2v-config.pl \ - issue \ - kiwi-config.sh \ - kiwi-config.xml.in \ - launch-virt-p2v \ - p2v.ks.in \ - p2v.service \ - test-virt-p2v-docs.sh \ - test-virt-p2v-pxe.sshd_config.in \ - test-virt-p2v-scp.sh \ - test-virt-p2v-ssh.sh \ - virt-p2v.pod \ - virt-p2v-make-disk.in \ - virt-p2v-make-disk.pod \ - virt-p2v-make-kickstart.in \ - virt-p2v-make-kickstart.pod \ - virt-p2v-make-kiwi.in \ - virt-p2v-make-kiwi.pod - -# Don't clean ssh_host_rsa_key{,.pub} or id_rsa{,.pub} since those -# consume system entropy to regenerate. -CLEANFILES += \ - $(dependencies_files) \ - $(generated_sources) \ - $(PHYSICAL_MACHINE) $(BLANK_DISK) \ - about-authors.c \ - stamp-test-virt-p2v-pxe-data-files \ - stamp-test-virt-p2v-pxe-kernel \ - test-virt-p2v-pxe.authorized_keys \ - test-virt-p2v-pxe.img \ - test-virt-p2v-pxe.vmlinuz \ - test-virt-p2v-pxe.initramfs \ - test-virt-p2v-pxe.sshd_config \ - virt-p2v.img \ - virt-p2v-kernel-config.pod \ - virt-p2v.xz - -# Although virt-p2v is a regular binary, it is not usually installed -# in /usr/bin since it only functions when contained in an ISO or PXE -# image which is used to boot the physical machine (since otherwise -# virt-p2v would not be able to get a consistent snapshot of the -# physical disks). Also we don't want the naked binary to appear on -# the host, which would cause various Gtk dependencies to be pulled -# in, so it must be compressed. -virtp2vlibdir = $(libdir)/virt-p2v -virtp2vlib_DATA = virt-p2v.xz - -virt-p2v.xz: virt-p2v - rm -f $@ $@-t - xz --best --keep --stdout $< > $@-t - mv $@-t $@ - -noinst_PROGRAMS = virt-p2v - -virt_p2v_SOURCES = \ - conversion.c \ - cpuid.c \ - gui.c \ - gui-gtk2-compat.h \ - gui-gtk3-compat.h \ - inhibit.c \ - kernel.c \ - kernel-cmdline.c \ - main.c \ - nbd.c \ - p2v.h \ - p2v-config.h \ - physical-xml.c \ - rtc.c \ - ssh.c \ - utils.c \ - whole-file.c - -generated_sources = \ - config.c \ - kernel-config.c \ - p2v-config.h - -nodist_virt_p2v_SOURCES = \ - $(generated_sources) \ - about-authors.c - -virt_p2v_CPPFLAGS = \ - -DLOCALEBASEDIR=\""$(datadir)/locale"\" \ - -DGTK_DISABLE_DEPRECATED \ - -I$(top_srcdir)/common/utils -I$(top_builddir)/common/utils \ - -I$(top_srcdir)/lib -I$(top_builddir)/lib \ - -I$(top_srcdir)/common/miniexpect -I$(top_builddir)/common/miniexpect \ - -I$(srcdir)/../gnulib/lib -I../gnulib/lib - -virt_p2v_CFLAGS = \ - -pthread \ - $(WARN_CFLAGS) $(WERROR_CFLAGS) \ - $(PCRE_CFLAGS) \ - $(LIBXML2_CFLAGS) \ - $(GTK_CFLAGS) \ - $(DBUS_CFLAGS) - -virt_p2v_LDADD = \ - $(top_builddir)/common/utils/libutils.la \ - $(top_builddir)/common/miniexpect/libminiexpect.la \ - $(PCRE_LIBS) \ - $(LIBXML2_LIBS) \ - $(GTK_LIBS) \ - $(DBUS_LIBS) \ - ../gnulib/lib/libgnu.la \ - -lm - -$(generated_sources) virt-p2v-kernel-config.pod: $(srcdir)/generate-p2v-config.pl - $(AM_V_GEN)rm -f $@ $@-t && $(PERL) $(<) --file=$@ --output=$@-t && mv $@-t $@ - -about-authors.c: $(srcdir)/generate-p2v-authors.pl $(srcdir)/AUTHORS - $(AM_V_GEN)rm -f $@ $@-t && $(PERL) $(<) $(srcdir)/AUTHORS > $@-t && mv $@-t $@ - -# Scripts to build the disk image, USB key, or kickstart. -bin_SCRIPTS = virt-p2v-make-disk virt-p2v-make-kickstart virt-p2v-make-kiwi - -dependencies_files = \ - dependencies.archlinux \ - dependencies.debian \ - dependencies.redhat \ - dependencies.suse - -$(dependencies_files): dependencies.m4 ../config.status - define=`echo $@ | $(SED) 's/dependencies.//;y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`; \ - m4 -D$$define=1 -DGTK_VERSION=$(GTK_VERSION) $< > $@-t - mv $@-t $@ - -# Support files needed by the virt-p2v-make-* scripts. -virtp2vdatadir = $(datadir)/virt-p2v - -virtp2vdata_DATA = \ - $(dependencies_files) \ - issue \ - kiwi-config.sh \ - kiwi-config.xml.in \ - launch-virt-p2v \ - p2v.ks.in \ - p2v.service - -# Manual pages and HTML files for the website. -man_MANS = \ - virt-p2v.1 \ - virt-p2v-make-disk.1 \ - virt-p2v-make-kickstart.1 \ - virt-p2v-make-kiwi.1 - -noinst_DATA = \ - $(top_builddir)/website/virt-p2v.1.html \ - $(top_builddir)/website/virt-p2v-make-disk.1.html \ - $(top_builddir)/website/virt-p2v-make-kickstart.1.html \ - $(top_builddir)/website/virt-p2v-make-kiwi.1.html - -virt-p2v.1 $(top_builddir)/website/virt-p2v.1.html: stamp-virt-p2v.pod - -stamp-virt-p2v.pod: virt-p2v.pod virt-p2v-kernel-config.pod - $(PODWRAPPER) \ - --man virt-p2v.1 \ - --html $(top_builddir)/website/virt-p2v.1.html \ - --insert virt-p2v-kernel-config.pod:__KERNEL_CONFIG__ \ - --license GPLv2+ \ - --warning safe \ - $< - touch $@ - -virt-p2v-make-disk.1 $(top_builddir)/website/virt-p2v-make-disk.1.html: stamp-virt-p2v-make-disk.pod - -stamp-virt-p2v-make-disk.pod: virt-p2v-make-disk.pod - $(PODWRAPPER) \ - --man virt-p2v-make-disk.1 \ - --html $(top_builddir)/website/virt-p2v-make-disk.1.html \ - --license GPLv2+ \ - --warning safe \ - $< - touch $@ - -virt-p2v-make-kickstart.1 $(top_builddir)/website/virt-p2v-make-kickstart.1.html: stamp-virt-p2v-make-kickstart.pod - -stamp-virt-p2v-make-kickstart.pod: virt-p2v-make-kickstart.pod - $(PODWRAPPER) \ - --man virt-p2v-make-kickstart.1 \ - --html $(top_builddir)/website/virt-p2v-make-kickstart.1.html \ - --license GPLv2+ \ - --warning safe \ - $< - touch $@ - -virt-p2v-make-kiwi.1 $(top_builddir)/website/virt-p2v-make-kiwi.1.html: stamp-virt-p2v-make-kiwi.pod - -stamp-virt-p2v-make-kiwi.pod: virt-p2v-make-kiwi.pod - $(PODWRAPPER) \ - --man virt-p2v-make-kiwi.1 \ - --html $(top_builddir)/website/virt-p2v-make-kiwi.1.html \ - --license GPLv2+ \ - --warning safe \ - $< - touch $@ - -# Run virt-p2v locally either directly or in a VM. -# See guestfs-hacking(1) section "Running virt-p2v" - -PHYSICAL_MACHINE = $(abs_builddir)/fedora.img -BLANK_DISK = blank-part.img - -check_DATA = \ - $(PHYSICAL_MACHINE) \ - $(BLANK_DISK) - -run-virt-p2v-directly: $(PHYSICAL_MACHINE) - $(top_builddir)/run virt-p2v --test-disk=$(PHYSICAL_MACHINE) - -run-virt-p2v-in-a-vm: virt-p2v.img $(PHYSICAL_MACHINE) - $(QEMU) \ - -M pc,accel=kvm:tcg \ - -cpu host \ - -m 1024 \ - -drive id=hd0,file=$(PHYSICAL_MACHINE),format=raw,if=ide \ - -device piix3-usb-uhci \ - -drive id=usb0,file=$<,format=raw,snapshot=on,if=none \ - -device usb-storage,bootindex=1,drive=usb0 \ - -boot menu=on \ - -netdev user,id=net0,net=169.254.0.0/16 \ - -device virtio-net-pci,netdev=net0 \ - -netdev user,id=net1 \ - -device rtl8139,netdev=net1 \ - -netdev user,id=net2 \ - -device e1000,netdev=net2 \ - $(QEMU_OPTIONS) \ - & - -run-virt-p2v-non-gui-conversion: stamp-test-virt-p2v-pxe-data-files - SLOW=1 $(top_builddir)/run ./test-virt-p2v-pxe.sh - -$(PHYSICAL_MACHINE): - $(top_builddir)/run virt-builder --format raw -o $@ fedora-30 - -$(BLANK_DISK): - $(top_builddir)/run guestfish -N $@=part exit - -virt-p2v.img: \ - dependencies.m4 \ - issue \ - launch-virt-p2v \ - p2v.service \ - virt-p2v \ - virt-p2v-make-disk - $(top_builddir)/run virt-p2v-make-disk -o $@ - -# Tests. - -TESTS_ENVIRONMENT = $(top_builddir)/run --test - -TESTS = \ - test-virt-p2v-cmdline.sh \ - test-virt-p2v-docs.sh - -APPLIANCE_TESTS = \ - test-virt-p2v.sh \ - test-virt-p2v-nbdkit.sh - -if ENABLE_APPLIANCE -TESTS += \ - $(APPLIANCE_TESTS) \ - $(SLOW_TESTS) -endif ENABLE_APPLIANCE - -check-valgrind: - make VG="@VG@" check - -SLOW_TESTS = \ - test-virt-p2v-pxe.sh - -check-slow: stamp-test-virt-p2v-pxe-data-files - $(MAKE) check TESTS="$(SLOW_TESTS)" SLOW=1 - -stamp-test-virt-p2v-pxe-data-files: \ - test-virt-p2v-pxe.authorized_keys \ - test-virt-p2v-pxe.img \ - test-virt-p2v-pxe.vmlinuz test-virt-p2v-pxe.initramfs \ - test-virt-p2v-pxe.sshd_config \ - test-virt-p2v-pxe.ssh_host_rsa_key \ - test-virt-p2v-pxe.ssh_host_rsa_key.pub \ - test-virt-p2v-pxe.id_rsa test-virt-p2v-pxe.id_rsa.pub - touch $@ - -test-virt-p2v-pxe.img: \ - dependencies.m4 \ - issue \ - launch-virt-p2v \ - p2v.service \ - test-virt-p2v-pxe.id_rsa \ - virt-p2v \ - virt-p2v-make-disk - $(top_builddir)/run virt-p2v-make-disk \ - --inject-ssh-identity=test-virt-p2v-pxe.id_rsa \ - -o $@-t - mv $@-t $@ - -test-virt-p2v-pxe.vmlinuz test-virt-p2v-pxe.initramfs: stamp-test-virt-p2v-pxe-kernel - -stamp-test-virt-p2v-pxe-kernel: test-virt-p2v-pxe.img - rm -f $@ vmlinuz initramfs test-virt-p2v-pxe.vmlinuz test-virt-p2v-pxe.initramfs - $(top_builddir)/run virt-get-kernel --unversioned-names -a $< - mv vmlinuz test-virt-p2v-pxe.vmlinuz - mv initramfs test-virt-p2v-pxe.initramfs - touch $@ - -test-virt-p2v-pxe.sshd_config: test-virt-p2v-pxe.sshd_config.in - rm -f $@ $@-t - @AWK@ \ - -v "abs_builddir=$(abs_builddir)" \ - '{ \ - gsub (/__RANDOM_PORT__/, 10000 + int (1000 * rand())); \ - gsub (/__abs_builddir__/, abs_builddir); \ - print; \ - }' < $< > $@-t - chmod 0444 $@-t - mv $@-t $@ - -test-virt-p2v-pxe.authorized_keys: test-virt-p2v-pxe.id_rsa.pub $(top_builddir)/run - rm -f $@ $@-t - $(top_builddir)/run sh -c 'echo -n environment=\"PATH=$$PATH\",environment=\"LD_LIBRARY_PATH=$(abs_top_builddir)/lib/.libs\",environment=\"LIBGUESTFS_PATH=$(abs_top_builddir)/appliance\",environment=\"LIBGUESTFS_CACHEDIR=$(abs_top_builddir)/tmp\"\ ' > $@-t - cat $< >> $@-t - mv $@-t $@ - -test-virt-p2v-pxe.ssh_host_rsa_key test-virt-p2v-pxe.ssh_host_rsa_key.pub: stamp-test-virt-p2v-pxe-hostkey - -stamp-test-virt-p2v-pxe-hostkey: - rm -f test-virt-p2v-pxe.ssh_host_rsa_key - rm -f test-virt-p2v-pxe.ssh_host_rsa_key.pub - ssh-keygen -t rsa -f test-virt-p2v-pxe.ssh_host_rsa_key -N '' - touch $@ - -test-virt-p2v-pxe.id_rsa test-virt-p2v-pxe.id_rsa.pub: stamp-test-virt-p2v-pxe-userkey - -stamp-test-virt-p2v-pxe-userkey: - rm -f test-virt-p2v-pxe.id_rsa - rm -f test-virt-p2v-pxe.id_rsa.pub - ssh-keygen -t rsa -f test-virt-p2v-pxe.id_rsa -N '' - touch $@ diff --git a/p2v/contrib/aux-scripts/do-build.sh b/p2v/contrib/aux-scripts/do-build.sh deleted file mode 100644 index dd6424bb4..000000000 --- a/p2v/contrib/aux-scripts/do-build.sh +++ /dev/null @@ -1,196 +0,0 @@ -#!/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 JANSSON_CFLAGS=-D_GNU_SOURCE - export JANSSON_LIBS=-ljansson - # 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 JANSSON_CFLAGS=-D_GNU_SOURCE - export JANSSON_LIBS=-ljansson - ;; -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 <<EOF | gzip -cd > /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 <<EOF | gzip -cd >' $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/p2v/contrib/build-p2v-iso.sh b/p2v/contrib/build-p2v-iso.sh deleted file mode 100755 index 2c6bd105b..000000000 --- a/p2v/contrib/build-p2v-iso.sh +++ /dev/null @@ -1,155 +0,0 @@ -#!/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 -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" - pkgs="$pkgs,jansson-devel" - ;; - 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" - pkgs="$pkgs,jansson-devel" - ;; -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 -no-user-config -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/p2v/contrib/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch b/p2v/contrib/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch deleted file mode 100644 index a4efb38bf..000000000 --- a/p2v/contrib/patches/0001-RHEL-5-ONLY-DISABLE-AUTOMATIC-REMOTE-PORT-ALLOCATION.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 28dd464c8e78f241622d142671a61a75bf5d758e Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" <rjones@redhat.com> -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/p2v/contrib/patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch b/p2v/contrib/patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch deleted file mode 100644 index d0bc2cfc9..000000000 --- a/p2v/contrib/patches/0002-RHEL-5-ONLY-QEMU-NBD-1.4-HAS-NO-f-OPTION.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 3ccd25c981431426038d7952f5b0b86118d92c23 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" <rjones@redhat.com> -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/p2v/contrib/test-p2v-iso.sh b/p2v/contrib/test-p2v-iso.sh deleted file mode 100755 index ff6453b79..000000000 --- a/p2v/contrib/test-p2v-iso.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/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 -no-user-config -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 diff --git a/p2v/conversion.c b/p2v/conversion.c deleted file mode 100644 index 7dd201a0d..000000000 --- a/p2v/conversion.c +++ /dev/null @@ -1,668 +0,0 @@ -/* virt-p2v - * Copyright (C) 2009-2019 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 file manages the p2v conversion. - * - * The conversion is actually done by L<virt-v2v(1)> running on the - * remote conversion server. This file manages running the remote - * command and provides callbacks for displaying the output. - * - * When virt-p2v operates in GUI mode, this code runs in a separate - * thread. When virt-p2v operates in kernel mode, this runs - * synchronously in the main thread. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <fcntl.h> -#include <inttypes.h> -#include <unistd.h> -#include <time.h> -#include <errno.h> -#include <error.h> -#include <locale.h> -#include <libintl.h> -#include <netdb.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> - -#include <pthread.h> - -#include "ignore-value.h" -#include "getprogname.h" - -#include "miniexpect.h" -#include "p2v.h" - -static void cleanup_data_conns (struct data_conn *data_conns, size_t nr); -static void generate_name (struct config *, const char *filename); -static void generate_wrapper_script (struct config *, const char *remote_dir, const char *filename); -static void generate_system_data (const char *dmesg_file, const char *lscpu_file, const char *lspci_file, const char *lsscsi_file, const char *lsusb_file); -static void generate_p2v_version_file (const char *p2v_version_file); -static void print_quoted (FILE *fp, const char *s); - -static char *conversion_error; - -static void set_conversion_error (const char *fs, ...) - __attribute__((format(printf,1,2))); - -static void -set_conversion_error (const char *fs, ...) -{ - va_list args; - char *msg; - int len; - - va_start (args, fs); - len = vasprintf (&msg, fs, args); - va_end (args); - - if (len < 0) - error (EXIT_FAILURE, errno, - "vasprintf (original error format string: %s)", fs); - - free (conversion_error); - conversion_error = msg; -} - -const char * -get_conversion_error (void) -{ - return conversion_error; -} - -static pthread_mutex_t running_mutex = PTHREAD_MUTEX_INITIALIZER; -static int running = 0; -static pthread_mutex_t cancel_requested_mutex = PTHREAD_MUTEX_INITIALIZER; -static int cancel_requested = 0; -static mexp_h *control_h = NULL; - -static int -is_running (void) -{ - int r; - pthread_mutex_lock (&running_mutex); - r = running; - pthread_mutex_unlock (&running_mutex); - return r; -} - -static void -set_running (int r) -{ - pthread_mutex_lock (&running_mutex); - running = r; - pthread_mutex_unlock (&running_mutex); -} - -static int -is_cancel_requested (void) -{ - int r; - pthread_mutex_lock (&cancel_requested_mutex); - r = cancel_requested; - pthread_mutex_unlock (&cancel_requested_mutex); - return r; -} - -static void -set_cancel_requested (int r) -{ - pthread_mutex_lock (&cancel_requested_mutex); - cancel_requested = r; - - /* Send ^C to the remote so that virt-v2v "knows" the connection has - * been cancelled. mexp_send_interrupt is a single write(2) call. - */ - if (r && control_h) - ignore_value (mexp_send_interrupt (control_h)); - - pthread_mutex_unlock (&cancel_requested_mutex); -} - -static void -set_control_h (mexp_h *new_h) -{ - pthread_mutex_lock (&cancel_requested_mutex); - control_h = new_h; - pthread_mutex_unlock (&cancel_requested_mutex); -} - -#pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn" -int -start_conversion (struct config *config, - void (*notify_ui) (int type, const char *data)) -{ - int ret = -1; - int status; - size_t i, len; - const size_t nr_disks = guestfs_int_count_strings (config->disks); - time_t now; - struct tm tm; - CLEANUP_FREE struct data_conn *data_conns = NULL; - CLEANUP_FREE char *remote_dir = NULL; - char tmpdir[] = "/tmp/p2v.XXXXXX"; - char name_file[] = "/tmp/p2v.XXXXXX/name"; - char physical_xml_file[] = "/tmp/p2v.XXXXXX/physical.xml"; - char wrapper_script[] = "/tmp/p2v.XXXXXX/virt-v2v-wrapper.sh"; - char dmesg_file[] = "/tmp/p2v.XXXXXX/dmesg"; - char lscpu_file[] = "/tmp/p2v.XXXXXX/lscpu"; - char lspci_file[] = "/tmp/p2v.XXXXXX/lspci"; - char lsscsi_file[] = "/tmp/p2v.XXXXXX/lsscsi"; - char lsusb_file[] = "/tmp/p2v.XXXXXX/lsusb"; - char p2v_version_file[] = "/tmp/p2v.XXXXXX/p2v-version"; - int inhibit_fd = -1; - -#if DEBUG_STDERR - print_config (config, stderr); - fprintf (stderr, "\n"); -#endif - - set_control_h (NULL); - set_running (1); - set_cancel_requested (0); - - inhibit_fd = inhibit_power_saving (); -#ifdef DEBUG_STDERR - if (inhibit_fd == -1) - fprintf (stderr, "warning: virt-p2v cannot inhibit power saving during conversion.\n"); -#endif - - data_conns = malloc (sizeof (struct data_conn) * nr_disks); - if (data_conns == NULL) - error (EXIT_FAILURE, errno, "malloc"); - - for (i = 0; config->disks[i] != NULL; ++i) { - data_conns[i].h = NULL; - data_conns[i].nbd_pid = 0; - data_conns[i].nbd_remote_port = -1; - } - - /* Start the data connections and NBD server processes, one per disk. */ - for (i = 0; config->disks[i] != NULL; ++i) { - const char *nbd_local_ipaddr; - int nbd_local_port; - CLEANUP_FREE char *device = NULL; - - if (config->disks[i][0] == '/') { - device = strdup (config->disks[i]); - if (!device) { - perror ("strdup"); - cleanup_data_conns (data_conns, nr_disks); - exit (EXIT_FAILURE); - } - } - else if (asprintf (&device, "/dev/%s", config->disks[i]) == -1) { - perror ("asprintf"); - cleanup_data_conns (data_conns, nr_disks); - exit (EXIT_FAILURE); - } - - if (notify_ui) { - CLEANUP_FREE char *msg; - if (asprintf (&msg, - _("Starting local NBD server for %s ..."), - config->disks[i]) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - notify_ui (NOTIFY_STATUS, msg); - } - - /* Start NBD server listening on the given port number. */ - data_conns[i].nbd_pid - start_nbd_server (&nbd_local_ipaddr, &nbd_local_port, device); - if (data_conns[i].nbd_pid == 0) { - set_conversion_error ("NBD server error: %s", get_nbd_error ()); - goto out; - } - - /* Wait for NBD server to start up and listen. */ - if (wait_for_nbd_server_to_start (nbd_local_ipaddr, nbd_local_port) == -1) { - set_conversion_error ("NBD server error: %s", get_nbd_error ()); - goto out; - } - - if (notify_ui) { - CLEANUP_FREE char *msg; - if (asprintf (&msg, - _("Opening data connection for %s ..."), - config->disks[i]) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - notify_ui (NOTIFY_STATUS, msg); - } - - /* Open the SSH data connection, with reverse port forwarding - * back to the NBD server. - */ - data_conns[i].h = open_data_connection (config, - nbd_local_ipaddr, nbd_local_port, - &data_conns[i].nbd_remote_port); - if (data_conns[i].h == NULL) { - const char *err = get_ssh_error (); - - set_conversion_error ("could not open data connection over SSH to the conversion server: %s", err); - goto out; - } - -#if DEBUG_STDERR - fprintf (stderr, - "%s: data connection for %s: SSH remote port %d, local port %s:%d\n", - getprogname (), device, - data_conns[i].nbd_remote_port, - nbd_local_ipaddr, nbd_local_port); -#endif - } - - /* Create a remote directory name which will be used for libvirt - * XML, log files and other stuff. We don't delete this directory - * after the run because (a) it's useful for debugging and (b) it - * only contains small files. - * - * NB: This path MUST NOT require shell quoting. - */ - time (&now); - gmtime_r (&now, &tm); - if (asprintf (&remote_dir, - "/tmp/virt-p2v-%04d%02d%02d-XXXXXXXX", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday) == -1) { - perror ("asprintf"); - cleanup_data_conns (data_conns, nr_disks); - exit (EXIT_FAILURE); - } - len = strlen (remote_dir); - guestfs_int_random_string (&remote_dir[len-8], 8); - if (notify_ui) - notify_ui (NOTIFY_LOG_DIR, remote_dir); - - /* Generate the local temporary directory. */ - if (mkdtemp (tmpdir) == NULL) { - perror ("mkdtemp"); - cleanup_data_conns (data_conns, nr_disks); - exit (EXIT_FAILURE); - } - memcpy (name_file, tmpdir, strlen (tmpdir)); - memcpy (physical_xml_file, tmpdir, strlen (tmpdir)); - memcpy (wrapper_script, tmpdir, strlen (tmpdir)); - memcpy (dmesg_file, tmpdir, strlen (tmpdir)); - memcpy (lscpu_file, tmpdir, strlen (tmpdir)); - memcpy (lspci_file, tmpdir, strlen (tmpdir)); - memcpy (lsscsi_file, tmpdir, strlen (tmpdir)); - memcpy (lsusb_file, tmpdir, strlen (tmpdir)); - memcpy (p2v_version_file, tmpdir, strlen (tmpdir)); - - /* Generate the static files. */ - generate_name (config, name_file); - generate_physical_xml (config, data_conns, physical_xml_file); - generate_wrapper_script (config, remote_dir, wrapper_script); - generate_system_data (dmesg_file, - lscpu_file, lspci_file, lsscsi_file, lsusb_file); - generate_p2v_version_file (p2v_version_file); - - /* Open the control connection. This also creates remote_dir. */ - if (notify_ui) - notify_ui (NOTIFY_STATUS, _("Setting up the control connection ...")); - - set_control_h (start_remote_connection (config, remote_dir)); - if (control_h == NULL) { - set_conversion_error ("could not open control connection over SSH to the conversion server: %s", - get_ssh_error ()); - goto out; - } - - /* Copy the static files to the remote dir. */ - - /* These three files must not fail, so check for errors here. */ - if (scp_file (config, remote_dir, - name_file, physical_xml_file, wrapper_script, NULL) == -1) { - set_conversion_error ("scp: %s: %s", - remote_dir, get_ssh_error ()); - goto out; - } - - /* It's not essential that these files are copied, so ignore errors. */ - ignore_value (scp_file (config, remote_dir, - dmesg_file, lscpu_file, lspci_file, lsscsi_file, - lsusb_file, p2v_version_file, NULL)); - - /* Do the conversion. This runs until virt-v2v exits. */ - if (notify_ui) - notify_ui (NOTIFY_STATUS, _("Doing conversion ...")); - - if (mexp_printf (control_h, - /* To simplify things in the wrapper script, it - * writes virt-v2v's exit status to - * /remote_dir/status, and here we read that and - * exit the ssh shell with the same status. - */ - "%s/virt-v2v-wrapper.sh; " - "exit $(< %s/status)\n", - remote_dir, remote_dir) == -1) { - set_conversion_error ("mexp_printf: virt-v2v: %m"); - goto out; - } - - /* Read output from the virt-v2v process and echo it through the - * notify function, until virt-v2v closes the connection. - */ - while (!is_cancel_requested ()) { - char buf[257]; - ssize_t r; - - r = read (mexp_get_fd (control_h), buf, sizeof buf - 1); - if (r == -1) { - /* See comment about this in miniexpect.c. */ - if (errno == EIO) - break; /* EOF */ - set_conversion_error ("read: %m"); - goto out; - } - if (r == 0) - break; /* EOF */ - buf[r] = '\0'; - if (notify_ui) - notify_ui (NOTIFY_REMOTE_MESSAGE, buf); - } - - if (is_cancel_requested ()) { - set_conversion_error ("cancelled by user"); - if (notify_ui) - notify_ui (NOTIFY_STATUS, _("Conversion cancelled by user.")); - goto out; - } - - if (notify_ui) - notify_ui (NOTIFY_STATUS, _("Control connection closed by remote.")); - - ret = 0; - out: - if (control_h) { - mexp_h *h = control_h; - set_control_h (NULL); - status = mexp_close (h); - - if (status == -1) { - set_conversion_error ("mexp_close: %m"); - ret = -1; - } - else if (ret == 0 && - WIFEXITED (status) && - WEXITSTATUS (status) != 0) { - set_conversion_error ("virt-v2v exited with status %d", - WEXITSTATUS (status)); - ret = -1; - } - } - cleanup_data_conns (data_conns, nr_disks); - - if (inhibit_fd >= 0) - close (inhibit_fd); - - set_running (0); - - return ret; -} - -int -conversion_is_running (void) -{ - return is_running (); -} - -void -cancel_conversion (void) -{ - set_cancel_requested (1); -} - -static void -cleanup_data_conns (struct data_conn *data_conns, size_t nr) -{ - size_t i; - - for (i = 0; i < nr; ++i) { - if (data_conns[i].h != NULL) { - /* Because there is no SSH prompt (ssh -N), the only way to kill - * these ssh connections is to send a signal. Just closing the - * pipe doesn't do anything. - */ - kill (mexp_get_pid (data_conns[i].h), SIGHUP); - mexp_close (data_conns[i].h); - } - - if (data_conns[i].nbd_pid > 0) { - /* Kill NBD process and clean up. */ - kill (data_conns[i].nbd_pid, SIGTERM); - waitpid (data_conns[i].nbd_pid, NULL, 0); - } - } -} - -/** - * Write the guest name into C<filename>. - */ -static void -generate_name (struct config *config, const char *filename) -{ - FILE *fp; - - fp = fopen (filename, "w"); - if (fp == NULL) - error (EXIT_FAILURE, errno, "fopen: %s", filename); - fprintf (fp, "%s\n", config->guestname); - fclose (fp); -} - -/** - * Construct the virt-v2v wrapper script. - * - * This will be sent to the remote server, and is easier than trying - * to "type" a long and complex single command line into the ssh - * connection when we start the conversion. - */ -static void -generate_wrapper_script (struct config *config, const char *remote_dir, - const char *filename) -{ - FILE *fp; - - fp = fopen (filename, "w"); - if (fp == NULL) - error (EXIT_FAILURE, errno, "fopen: %s", filename); - - fprintf (fp, "#!/bin/bash -\n"); - fprintf (fp, "\n"); - - fprintf (fp, "cd %s\n", remote_dir); - fprintf (fp, "\n"); - - /* The virt-v2v command, as a shell function called "v2v". */ - fprintf (fp, "v2v ()\n"); - fprintf (fp, "{\n"); - if (config->auth.sudo) - fprintf (fp, "sudo -n "); - fprintf (fp, "virt-v2v -v -x"); - if (feature_colours_option) - fprintf (fp, " --colours"); - fprintf (fp, " -i libvirtxml"); - - if (config->output.type) { /* -o */ - fprintf (fp, " -o "); - print_quoted (fp, config->output.type); - } - - switch (config->output.allocation) { /* -oa */ - case OUTPUT_ALLOCATION_NONE: - /* nothing */ - break; - case OUTPUT_ALLOCATION_SPARSE: - fprintf (fp, " -oa sparse"); - break; - case OUTPUT_ALLOCATION_PREALLOCATED: - fprintf (fp, " -oa preallocated"); - break; - default: - abort (); - } - - if (config->output.format) { /* -of */ - fprintf (fp, " -of "); - print_quoted (fp, config->output.format); - } - - if (config->output.storage) { /* -os */ - fprintf (fp, " -os "); - print_quoted (fp, config->output.storage); - } - - fprintf (fp, " --root first"); - fprintf (fp, " physical.xml"); - fprintf (fp, " </dev/null"); /* no stdin */ - fprintf (fp, "\n"); - fprintf (fp, - "# Save the exit code of virt-v2v into the 'status' file.\n"); - fprintf (fp, "echo $? > status\n"); - fprintf (fp, "}\n"); - fprintf (fp, "\n"); - - fprintf (fp, - "# Write a pre-emptive error status, in case the virt-v2v\n" - "# command doesn't get to run at all. This will be\n" - "# overwritten with the true exit code when virt-v2v runs.\n"); - fprintf (fp, "echo 99 > status\n"); - fprintf (fp, "\n"); - - fprintf (fp, "log=virt-v2v-conversion-log.txt\n"); - fprintf (fp, "rm -f $log\n"); - fprintf (fp, "\n"); - - fprintf (fp, - "# Log the environment where virt-v2v will run.\n"); - fprintf (fp, "printenv > environment\n"); - fprintf (fp, "\n"); - - fprintf (fp, - "# Log the version of virt-v2v (for information only).\n"); - if (config->auth.sudo) - fprintf (fp, "sudo -n "); - fprintf (fp, "virt-v2v --version > v2v-version\n"); - fprintf (fp, "\n"); - - fprintf (fp, - "# Run virt-v2v. Send stdout back to virt-p2v. Send stdout\n" - "# and stderr (debugging info) to the log file.\n"); - fprintf (fp, "v2v 2>> $log | tee -a $log\n"); - fprintf (fp, "\n"); - - fprintf (fp, - "# If virt-v2v failed then the error message (sent to stderr)\n" - "# will not be seen in virt-p2v. Send the last few lines of\n" - "# the log back to virt-p2v in this case.\n"); - fprintf (fp, - "if [ \"$(< status)\" -ne 0 ]; then\n" - " echo\n" - " echo\n" - " echo\n" - " echo -ne '\\e[1;31m'\n" - " echo '***' virt-v2v command failed '***'\n" - " echo\n" - " echo The full log is available on the conversion server in:\n" - " echo ' ' %s/$log\n" - " echo Only the last 50 lines are shown below.\n" - " echo -ne '\\e[0m'\n" - " echo\n" - " echo\n" - " echo\n" - " tail -50 $log\n" - "fi\n", - remote_dir); - - fprintf (fp, "\n"); - fprintf (fp, "# EOF\n"); - fclose (fp); - - if (chmod (filename, 0755) == -1) - error (EXIT_FAILURE, errno, "chmod: %s", filename); -} - -/** - * Print a shell-quoted string on C<fp>. - */ -static void -print_quoted (FILE *fp, const char *s) -{ - fprintf (fp, "\""); - while (*s) { - if (*s == '$' || *s == '`' || *s == '\\' || *s == '"') - fprintf (fp, "\\"); - fprintf (fp, "%c", *s); - ++s; - } - fprintf (fp, "\""); -} - -/** - * Collect data about the system running virt-p2v such as the dmesg - * output and lists of PCI devices. This is useful for diagnosis when - * things go wrong. - * - * If any command fails, this is non-fatal. - */ -static void -generate_system_data (const char *dmesg_file, - const char *lscpu_file, - const char *lspci_file, - const char *lsscsi_file, - const char *lsusb_file) -{ - CLEANUP_FREE char *cmd = NULL; - - if (asprintf (&cmd, - "dmesg >%s 2>&1; " - "lscpu >%s 2>&1; " - "lspci -vvv >%s 2>&1; " - "lsscsi -v >%s 2>&1; " - "lsusb -v >%s 2>&1", - dmesg_file, lscpu_file, lspci_file, lsscsi_file, lsusb_file) - == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - ignore_value (system (cmd)); -} - -/** - * Generate a file containing the version of virt-p2v. - * - * The version of virt-v2v is contained in the conversion log. - */ -static void -generate_p2v_version_file (const char *p2v_version_file) -{ - FILE *fp = fopen (p2v_version_file, "w"); - if (fp == NULL) { - perror (p2v_version_file); - return; /* non-fatal */ - } - fprintf (fp, "%s %s\n", - getprogname (), PACKAGE_VERSION_FULL); - fclose (fp); -} diff --git a/p2v/cpuid.c b/p2v/cpuid.c deleted file mode 100644 index ef3574deb..000000000 --- a/p2v/cpuid.c +++ /dev/null @@ -1,222 +0,0 @@ -/* virt-p2v - * Copyright (C) 2009-2019 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. - */ - -/** - * Find CPU vendor, topology and some CPU flags. - * - * lscpu (from util-linux) provides CPU vendor, topology and flags. - * - * ACPI can be read by seeing if F</sys/firmware/acpi> exists. - * - * CPU model is essentially impossible to get without using libvirt, - * but we cannot use libvirt for the reasons outlined in this message: - * https://www.redhat.com/archives/libvirt-users/2017-March/msg00071.html - * - * Note that #vCPUs and amount of RAM is handled by F<main.c>. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include <error.h> -#include <libintl.h> - -#include "c-ctype.h" -#include "getprogname.h" -#include "ignore-value.h" - -#include "p2v.h" - -static void -free_cpu_config (struct cpu_config *cpu) -{ - if (cpu->vendor) - free (cpu->vendor); - if (cpu->model) - free (cpu->model); - memset (cpu, 0, sizeof *cpu); -} - -/** - * Get the output of lscpu as a list of (key, value) pairs (as a - * flattened list of strings). - */ -static char ** -get_lscpu (void) -{ - const char *cmd; - CLEANUP_PCLOSE FILE *fp = NULL; - CLEANUP_FREE char *line = NULL; - ssize_t len; - size_t buflen = 0; - char **ret = NULL; - size_t ret_size = 0; - - cmd = "lscpu"; - - fp = popen (cmd, "re"); - if (fp == NULL) { - perror (cmd); - return NULL; - } - - ret = malloc (sizeof (char *)); - if (ret == NULL) error (EXIT_FAILURE, errno, "malloc"); - ret[0] = NULL; - - while (errno = 0, (len = getline (&line, &buflen, fp)) != -1) { - char *p; - char *key, *value; - - if (len > 0 && line[len-1] == '\n') - line[len-1] = '\0'; - - /* Split the line at the first ':' character. */ - p = strchr (line, ':'); - if (p == NULL) - continue; - - *p = '\0'; - key = strdup (line); - /* Skip leading whitespace in the value. */ - for (++p; *p && c_isspace (*p); ++p) - ; - value = strdup (p); - - /* Add key and value to the list, and trailing NULL pointer. */ - ret_size += 2; - ret = realloc (ret, (ret_size + 1) * sizeof (char *)); - if (ret == NULL) error (EXIT_FAILURE, errno, "realloc"); - ret[ret_size-2] = key; - ret[ret_size-1] = value; - ret[ret_size] = NULL; - } - - if (errno) { - perror (cmd); - guestfs_int_free_string_list (ret); - return NULL; - } - - return ret; -} - -/** - * Read a single field from lscpu output. - * - * If the field does not exist, returns C<NULL>. - */ -static const char * -get_field (char **lscpu, const char *key) -{ - size_t i; - - for (i = 0; lscpu[i] != NULL; i += 2) { - if (STREQ (lscpu[i], key)) - return lscpu[i+1]; - } - - return NULL; -} - -/** - * Read the CPU vendor from lscpu output. - */ -static void -get_vendor (char **lscpu, struct cpu_config *cpu) -{ - const char *vendor = get_field (lscpu, "Vendor ID"); - - if (vendor) { - /* Note this mapping comes from /usr/share/libvirt/cpu_map.xml */ - if (STREQ (vendor, "GenuineIntel")) - cpu->vendor = strdup ("Intel"); - else if (STREQ (vendor, "AuthenticAMD")) - cpu->vendor = strdup ("AMD"); - /* Currently aarch64 lscpu has no Vendor ID XXX. */ - } -} - -/** - * Read the CPU topology from lscpu output. - */ -static void -get_topology (char **lscpu, struct cpu_config *cpu) -{ - const char *v; - - v = get_field (lscpu, "Socket(s)"); - if (v) - ignore_value (sscanf (v, "%u", &cpu->sockets)); - v = get_field (lscpu, "Core(s) per socket"); - if (v) - ignore_value (sscanf (v, "%u", &cpu->cores)); - v = get_field (lscpu, "Thread(s) per core"); - if (v) - ignore_value (sscanf (v, "%u", &cpu->threads)); -} - -/** - * Read some important flags from lscpu output. - */ -static void -get_flags (char **lscpu, struct cpu_config *cpu) -{ - const char *flags; - - flags = get_field (lscpu, "Flags"); - if (flags) { - cpu->apic = strstr (flags, " apic ") != NULL; - cpu->pae = strstr (flags, " pae ") != NULL; - - /* aarch64 /proc/cpuinfo has a "Features" field, but lscpu does - * not expose it. However aarch64 Features does not contain any - * of the interesting flags above. - */ - } -} - -/** - * Find out if the system uses ACPI. - */ -static void -get_acpi (struct cpu_config *cpu) -{ - cpu->acpi = access ("/sys/firmware/acpi", F_OK) == 0; -} - -void -get_cpu_config (struct cpu_config *cpu) -{ - CLEANUP_FREE_STRING_LIST char **lscpu = NULL; - - free_cpu_config (cpu); - - lscpu = get_lscpu (); - if (lscpu != NULL) { - get_vendor (lscpu, cpu); - get_topology (lscpu, cpu); - get_flags (lscpu, cpu); - } - - get_acpi (cpu); -} diff --git a/p2v/dependencies.m4 b/p2v/dependencies.m4 deleted file mode 100644 index 40b3786cb..000000000 --- a/p2v/dependencies.m4 +++ /dev/null @@ -1,181 +0,0 @@ -dnl This is the list of distro packages which are required by -dnl virt-p2v. -dnl -dnl This file is processed by m4 with only one of the following -dnl symbols defined (depending on the target distro): -dnl -dnl REDHAT=1 Fedora, RHEL, CentOS, SL and workalikes -dnl DEBIAN=1 Debian and Ubuntu -dnl ARCHLINUX=1 Arch Linux -dnl SUSE=1 SUSE, OpenSUSE -dnl OPENMANDRIVA=1 OpenMandriva -dnl -dnl NB 1: Must be one package name per line. Blank lines are ignored. -dnl -dnl NB 2: This works differently from appliance/packagelist.in -dnl because we don't care about the current DISTRO (the one on -dnl which libguestfs is being compiled), since we can "cross-build" -dnl the virt-p2v ISO to any other Linux distro. -dnl -dnl NB 3: libguestfs is not a dependency of virt-p2v. libguestfs -dnl only runs on the virt-v2v conversion server. - -ifelse(REDHAT,1, - dnl Used by the virt-p2v binary. - pcre - libxml2 - gtk`'GTK_VERSION - dbus-libs - - dnl Run as external programs by the p2v binary. - /usr/bin/ssh - /usr/bin/qemu-nbd - which - - dnl Generally useful tools to use within xterm - vim-minimal - - dnl Useful disk and diagnostic utilities. - iscsi-initiator-utils - - dnl X11 environment - /usr/bin/xinit - /usr/bin/Xorg - xorg-x11-drivers - xorg-x11-fonts-Type1 - dejavu-sans-fonts - dejavu-sans-mono-fonts - mesa-dri-drivers - metacity - - NetworkManager - nm-connection-editor - network-manager-applet - dnl dbus is required by nm-applet, but not a dependency in Fedora - dbus-x11 - dnl sysadmins prefer ifconfig - net-tools - - dnl RHBZ#1157679 - @hardware-support -) - -ifelse(DEBIAN,1, - libpcre3 - libxml2 - ifelse(GTK_VERSION,2,libgtk`'GTK_VERSION`'.0-0,libgtk-`'GTK_VERSION`'-0) - libdbus-1-3 - openssh-client - qemu-utils - debianutils - vim-tiny - open-iscsi - xorg - xserver-xorg-video-all - fonts-dejavu - metacity - network-manager - network-manager-gnome - dbus-x11 - net-tools -) - -ifelse(ARCHLINUX,1, - pcre - libxml2 - gtk`'GTK_VERSION - dbus - openssh - qemu - which - vim-tiny - open-iscsi - xorg-xinit - xorg-server - xf86-video-* - ttf-dejavu - metacity - NetworkManager - nm-connection-editor - network-manager-applet - dbus-x11 - net-tools -) - -ifelse(SUSE,1, - pcre - libxml2 - gtk`'GTK_VERSION - libdbus-1-3 - qemu-tools - openssh - dnl /usr/bin/which is in util-linux on SUSE - vim - open-iscsi - xinit - xorg-x11-server - xf86-video-* - dejavu-fonts - NetworkManager - xf86-input-* - icewm-lite - dbus-1-x11 - yast2-network - libyui-qt - SuSEfirewall2 -) - -ifelse(OPENMANDRIVA,1, - dnl Used by the virt-p2v binary. - pcre - libxml2 - gtk`'GTK_VERSION - dbus-libs - - dnl Run as external programs by the p2v binary. - /usr/bin/ssh - /usr/bin/qemu-nbd - which - - dnl Generally useful tools to use within xterm - vim-enhanced - - dnl X11 environment - /usr/bin/xinit - /usr/bin/Xorg - xorg-x11-drivers - xorg-x11-fonts-Type1 - dejavu-sans-fonts - dejavu-sans-mono-fonts - mesa-dri-drivers - kwin_x11 - - NetworkManager - nm-connection-editor - network-manager-applet - dnl dbus is required by nm-applet, but not a dependency in Fedora - dbus-x11 - dnl sysadmins prefer ifconfig - net-tools -) - -dnl Run as external programs by the p2v binary. -curl -ethtool -gawk -lsscsi -pciutils -usbutils -util-linux -xterm - -dnl Generally useful tools to use within xterm -less - -dnl The hwdata package contains PCI IDs, used by virt-p2v to display -dnl network vendor information (RHBZ#855059). -hwdata - -dnl Useful disk and diagnostic utilities. -hdparm -smartmontools diff --git a/p2v/generate-p2v-authors.pl b/p2v/generate-p2v-authors.pl deleted file mode 100755 index 18a825bd7..000000000 --- a/p2v/generate-p2v-authors.pl +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env perl -# Copyright (C) 2019 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. - -use strict; -use warnings; - -# Clean up the program name. -my $progname = $0; -$progname =~ s{.*/}{}; - -my $filename = shift or die "$progname: missing filename"; - -open(my $fh, '<', $filename) or die "Unable to open file '$filename': $!"; - -print <<"EOF"; -/* libguestfs generated file - * WARNING: THIS FILE IS GENERATED FROM THE FOLLOWING FILES: - * $filename - * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. - */ - -#include <config.h> - -#include "p2v.h" - -/* Authors involved with virt-v2v and virt-p2v directly. */ -const char *authors[] = { -EOF - -while (<$fh>) { - chomp $_; - printf " \"%s\",\n", $_; -} - -print <<"EOF"; - NULL -}; -EOF - -close($fh); diff --git a/p2v/generate-p2v-config.pl b/p2v/generate-p2v-config.pl deleted file mode 100755 index 01387e04b..000000000 --- a/p2v/generate-p2v-config.pl +++ /dev/null @@ -1,915 +0,0 @@ -#!/usr/bin/env perl -# Copyright (C) 2019 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. - -use strict; -use warnings; - -use Class::Struct; -use Getopt::Long; -use List::Util qw(any); - -struct ConfigSection => -{ - name => '$', - elements => '@', -}; - -struct ConfigString => -{ - name => '$', -}; - -struct ConfigInt => -{ - name => '$', - value => '$', -}; - -struct ConfigBool => -{ - name => '$', -}; - -struct ConfigUInt64 => -{ - name => '$', -}; - -struct ConfigUnsigned => -{ - name => '$', -}; - -struct ConfigEnum => -{ - name => '$', - enum => '$', -}; - -struct ConfigStringList => -{ - name => '$', -}; - -struct manual_entry => -{ - shortopt => '$', - description => '$', -}; - -# Enums. -my @enums = ( - ["basis", ( - ["BASIS_UNKNOWN", "unknown", "RTC could not be read"], - ["BASIS_UTC", "utc", "RTC is either UTC or an offset from UTC"], - ["BASIS_LOCALTIME", "localtime", "RTC is localtime"], - )], - ["output_allocation", ( - ["OUTPUT_ALLOCATION_NONE", "none", "output allocation not set"], - ["OUTPUT_ALLOCATION_SPARSE", "sparse", "sparse"], - ["OUTPUT_ALLOCATION_PREALLOCATED", "preallocated", "preallocated"], - )], -); - -# Configuration fields. -my @fields = [ - ConfigSection->new( - name => 'remote', - elements => [ - ConfigString->new(name => 'server'), - ConfigInt->new(name => 'port', value => 22), - ], - ), - ConfigSection->new( - name => 'auth', - elements => [ - ConfigString->new(name => 'username'), - ConfigString->new(name => 'password'), - ConfigSection->new( - name => 'identity', - elements => [ - ConfigString->new(name => 'url'), - ConfigString->new(name => 'file'), - ConfigBool->new(name => 'file_needs_update'), - ], - ), - ConfigBool->new(name => 'sudo'), - ], - ), - ConfigString->new(name => 'guestname'), - ConfigInt->new(name => 'vcpus', value => 0), - ConfigUInt64->new(name => 'memory'), - ConfigSection->new( - name => 'cpu', - elements => [ - ConfigString->new(name => 'vendor'), - ConfigString->new(name => 'model'), - ConfigUnsigned->new(name => 'sockets'), - ConfigUnsigned->new(name => 'cores'), - ConfigUnsigned->new(name => 'threads'), - ConfigBool->new(name => 'acpi'), - ConfigBool->new(name => 'apic'), - ConfigBool->new(name => 'pae'), - ], - ), - ConfigSection->new( - name => 'rtc', - elements => [ - ConfigEnum->new(name => 'basis', enum => 'basis'), - ConfigInt->new(name => 'offset', value => 0), - ], - ), - ConfigStringList->new(name => 'disks'), - ConfigStringList->new(name => 'removable'), - ConfigStringList->new(name => 'interfaces'), - ConfigStringList->new(name => 'network_map'), - ConfigSection->new( - name => 'output', - elements => [ - ConfigString->new(name => 'type'), - ConfigEnum->new(name => 'allocation', enum => 'output_allocation'), - ConfigString->new(name => 'connection'), - ConfigString->new(name => 'format'), - ConfigString->new(name => 'storage'), - ], - ), -]; - -# Some /proc/cmdline p2v.* options were renamed when we introduced -# the generator. This map creates backwards compatibility mappings -# for these. -my @cmdline_aliases = ( - ["p2v.remote.server", "p2v.server"], - ["p2v.remote.port", "p2v.port"], - ["p2v.auth.username", "p2v.username"], - ["p2v.auth.password", "p2v.password"], - ["p2v.auth.identity.url", "p2v.identity"], - ["p2v.auth.sudo", "p2v.sudo"], - ["p2v.guestname", "p2v.name"], - ["p2v.network_map", "p2v.network"], - ["p2v.output.type", "p2v.o"], - ["p2v.output.allocation", "p2v.oa"], - ["p2v.output.connection", "p2v.oc"], - ["p2v.output.format", "p2v.of"], - ["p2v.output.storage", "p2v.os"], -); - -# Some config entries are not exposed on the kernel command line. -my @cmdline_ignore = ( - "p2v.auth.identity.file", - "p2v.auth.identity.file_needs_update", -); - -# Man page snippets for each kernel command line setting. -my %cmdline_manual = ( - "p2v.remote.server" => manual_entry->new( - shortopt => "SERVER", - description => " -The name or IP address of the conversion server. - -This is always required if you are using the kernel configuration -method. If virt-p2v does not find this on the kernel command line -then it switches to the GUI (interactive) configuration method.", - ), - "p2v.remote.port" => manual_entry->new( - shortopt => "PORT", - description => " -The SSH port number on the conversion server (default: C<22>).", - ), - "p2v.auth.username" => manual_entry->new( - shortopt => "USERNAME", - description => " -The SSH username that we log in as on the conversion server -(default: C<root>).", - ), - "p2v.auth.password" => manual_entry->new( - shortopt => "PASSWORD", - description => " -The SSH password that we use to log in to the conversion server. - -The default is to try with no password. If this fails then virt-p2v -will ask the user to type the password (probably several times during -conversion). - -This setting is ignored if C<p2v.auth.identity.url> is present.", - ), - "p2v.auth.identity.url" => manual_entry->new( - shortopt => "URL", - description => " -Provide a URL pointing to an SSH identity (private key) file. The URL -is interpreted by L<curl(1)> so any URL that curl supports can be used -here, including C<https://> and C<file://>. For more information on -using SSH identities, see L</SSH IDENTITIES> below. - -If C<p2v.auth.identity.url> is present, it overrides C<p2v.auth.password>. -There is no fallback.", - ), - "p2v.auth.sudo" => manual_entry->new( - shortopt => "", # ignored for booleans - description => " -Use C<p2v.sudo> to tell virt-p2v to use L<sudo(8)> to gain root -privileges on the conversion server after logging in as a non-root -user (default: do not use sudo).", - ), - "p2v.guestname" => manual_entry->new( - shortopt => "GUESTNAME", - description => " -The name of the guest that is created. The default is to try to -derive a name from the physical machine’s hostname (if possible) else -use a randomly generated name.", - ), - "p2v.vcpus" => manual_entry->new( - shortopt => "N", - description => " -The number of virtual CPUs to give to the guest. The default is to -use the same as the number of physical CPUs.", - ), - "p2v.memory" => manual_entry->new( - shortopt => "n(M|G)", - description => " -The size of the guest memory. You must specify the unit such as -megabytes or gigabytes by using for example C<p2v.memory=1024M> or -C<p2v.memory=1G>. - -The default is to use the same amount of RAM as on the physical -machine.", - ), - "p2v.cpu.vendor" => manual_entry->new( - shortopt => "VENDOR", - description => " -The vCPU vendor, eg. \"Intel\" or \"AMD\". The default is to use -the same CPU vendor as the physical machine.", - ), - "p2v.cpu.model" => manual_entry->new( - shortopt => "MODEL", - description => " -The vCPU model, eg. \"IvyBridge\". The default is to use the same -CPU model as the physical machine.", - ), - "p2v.cpu.sockets" => manual_entry->new( - shortopt => "N", - description => " -Number of vCPU sockets to use. The default is to use the same as the -physical machine.", - ), - "p2v.cpu.cores" => manual_entry->new( - shortopt => "N", - description => " -Number of vCPU cores to use. The default is to use the same as the -physical machine.", - ), - "p2v.cpu.threads" => manual_entry->new( - shortopt => "N", - description => " -Number of vCPU hyperthreads to use. The default is to use the same -as the physical machine.", - ), - "p2v.cpu.acpi" => manual_entry->new( - shortopt => "", # ignored for booleans - description => " -Whether to enable ACPI in the remote virtual machine. The default is -to use the same as the physical machine.", - ), - "p2v.cpu.apic" => manual_entry->new( - shortopt => "", # ignored for booleans - description => " -Whether to enable APIC in the remote virtual machine. The default is -to use the same as the physical machine.", - ), - "p2v.cpu.pae" => manual_entry->new( - shortopt => "", # ignored for booleans - description => " -Whether to enable PAE in the remote virtual machine. The default is -to use the same as the physical machine.", - ), - "p2v.rtc.basis" => manual_entry->new( - shortopt => "", # ignored for enums - description => " -Set the basis of the Real Time Clock in the virtual machine. The -default is to try to detect this setting from the physical machine.", - ), - "p2v.rtc.offset" => manual_entry->new( - shortopt => "[+|-]HOURS", - description => " -The offset of the Real Time Clock from UTC. The default is to try -to detect this setting from the physical machine.", - ), - "p2v.disks" => manual_entry->new( - shortopt => "sda,sdb,...", - description => " -A list of physical hard disks to convert, for example: - - p2v.disks=sda,sdc - -The default is to convert all local hard disks that are found.", - ), - "p2v.removable" => manual_entry->new( - shortopt => "sra,srb,...", - description => " -A list of removable media to convert. The default is to create -virtual removable devices for every physical removable device found. -Note that the content of removable media is never copied over.", - ), - "p2v.interfaces" => manual_entry->new( - shortopt => "em1,...", - description => " -A list of network interfaces to convert. The default is to create -virtual network interfaces for every physical network interface found.", - ), - "p2v.network_map" => manual_entry->new( - shortopt => "interface:target,...", - description => " -Controls how network interfaces are connected to virtual networks on -the target hypervisor. The default is to connect all network -interfaces to the target C<default> network. - -You give a comma-separated list of C<interface:target> pairs, plus -optionally a default target. For example: - - p2v.network=em1:ovirtmgmt - -maps interface C<em1> to target network C<ovirtmgmt>. - - p2v.network=em1:ovirtmgmt,em2:management,other - -maps interface C<em1> to C<ovirtmgmt>, and C<em2> to C<management>, -and any other interface that is found to C<other>.", - ), - "p2v.output.type" => manual_entry->new( - shortopt => "(libvirt|local|...)", - description => " -Set the output mode. This is the same as the virt-v2v I<-o> option. -See L<virt-v2v(1)/OPTIONS>. - -If not specified, the default is C<local>, and the converted guest is -written to F</var/tmp>.", - ), - "p2v.output.allocation" => manual_entry->new( - shortopt => "", # ignored for enums - description => " -Set the output allocation mode. This is the same as the virt-v2v -I<-oa> option. See L<virt-v2v(1)/OPTIONS>.", - ), - "p2v.output.connection" => manual_entry->new( - shortopt => "URI", - description => " -Set the output connection libvirt URI. This is the same as the -virt-v2v I<-oc> option. See L<virt-v2v(1)/OPTIONS> and -L<http://libvirt.org/uri.html>", - ), - "p2v.output.format" => manual_entry->new( - shortopt => "(raw|qcow2|...)", - description => " -Set the output format. This is the same as the virt-v2v I<-of> -option. See L<virt-v2v(1)/OPTIONS>.", - ), - "p2v.output.storage" => manual_entry->new( - shortopt => "STORAGE", - description => " -Set the output storage. This is the same as the virt-v2v I<-os> -option. See L<virt-v2v(1)/OPTIONS>. - -If not specified, the default is F</var/tmp> (on the conversion server).", - ), -); - -# Clean up the program name. -my $progname = $0; -$progname =~ s{.*/}{}; - -my $filename; -my $output; - -GetOptions( - 'file=s' => \$filename, - 'output=s' => \$output, - 'help' => sub { pod2usage(1); }, -) or pod2usage(2); -die "$progname: Option --file not specified.\n" unless $filename; -# die "$progname: Option --output not specified.\n" unless $output; - -sub print_generated_header { - my $fh = shift; - print $fh <<"EOF"; -/* libguestfs generated file - * WARNING: THIS FILE IS GENERATED FROM THE FOLLOWING FILES: - * $filename - * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST. - */ - -EOF -} - -sub generate_config_struct { - my ($fh, $name, $fields) = @_; - # If there are any ConfigSection (sub-structs) in any of the - # fields then output those first. - foreach my $field (@$fields) { - if (ref($field) eq 'ConfigSection') { - generate_config_struct($fh, $field->name . "_config", $field->elements); - } - } - - # Now generate this struct. - print $fh "struct $name {\n"; - foreach my $field (@$fields) { - my $type = ref($field); - if ($type eq 'ConfigSection') { - printf $fh " struct %s_config %s;\n", $field->name, $field->name; - } elsif ($type eq 'ConfigString') { - printf $fh " char *%s;\n", $field->name; - } elsif ($type eq 'ConfigInt') { - printf $fh " int %s;\n", $field->name; - } elsif ($type eq 'ConfigBool') { - printf $fh " bool %s;\n", $field->name; - } elsif ($type eq 'ConfigUInt64') { - printf $fh " uint64_t %s;\n", $field->name; - } elsif ($type eq 'ConfigUnsigned') { - printf $fh " unsigned %s;\n", $field->name; - } elsif ($type eq 'ConfigEnum') { - printf $fh " enum %s %s;\n", $field->enum, $field->name; - } elsif ($type eq 'ConfigStringList') { - printf $fh " char **%s;\n", $field->name; - } - } - print $fh "};\n"; - print $fh "\n" -} - -sub generate_p2v_config_h { - my $fh = shift; - print_generated_header($fh); - print $fh <<"EOF"; -#ifndef GUESTFS_P2V_CONFIG_H -#define GUESTFS_P2V_CONFIG_H - -#include <stdbool.h> -#include <stdint.h> - -EOF - - # Generate enums. - foreach my $enum (@enums) { - my $name = shift @$enum; - print $fh "enum $name {\n"; - foreach my $items (@$enum) { - my ($n, $foo, $comment) = @$items; - printf $fh " %-25s /* %s */\n", ($n . ","), $comment; - } - print $fh "};\n"; - print $fh "\n" - } - - # Generate struct config. - generate_config_struct($fh, "config", @fields); - - print $fh <<'EOF'; -extern struct config *new_config (void); -extern struct config *copy_config (struct config *); -extern void free_config (struct config *); -extern void print_config (struct config *, FILE *); - -#endif /* GUESTFS_P2V_CONFIG_H */ -EOF -} - -sub generate_field_initialization { - my ($fh, $v, $fields) = @_; - foreach my $field (@$fields) { - my $type = ref($field); - if ($type eq 'ConfigSection') { - my $lv = $v . $field->name . '.'; - generate_field_initialization($fh, $lv, $field->elements); - } elsif ($type eq 'ConfigInt') { - if ($field->value > 0) { - printf $fh " %s%s = %d;\n", $v, $field->name, $field->value; - } - } - } -} - -sub generate_field_copy { - my ($fh, $v, $fields) = @_; - foreach my $field (@$fields) { - my $type = ref($field); - if ($type eq 'ConfigSection') { - my $lv = $v . $field->name . '.'; - generate_field_copy($fh, $lv, $field->elements); - } elsif ($type eq 'ConfigString') { - printf $fh " if (%s%s) {\n", $v, $field->name; - printf $fh " %s%s = strdup (%s%s);\n", $v, $field->name, $v, $field->name; - printf $fh " if (%s%s == NULL)\n", $v, $field->name; - printf $fh " error (EXIT_FAILURE, errno, \"strdup: %%s\", \"%s\");\n", $field->name; - printf $fh " }\n"; - } elsif ($type eq 'ConfigStringList') { - printf $fh " if (%s%s) {\n", $v, $field->name; - printf $fh " %s%s = guestfs_int_copy_string_list (%s%s);\n", $v, $field->name, $v, $field->name; - printf $fh " if (%s%s == NULL)\n", $v, $field->name; - printf $fh " error (EXIT_FAILURE, errno, \"copy string list: %%s\", \"%s\");\n", $field->name; - printf $fh " }\n"; - } - } -} - -sub generate_field_free { - my ($fh, $v, $fields) = @_; - foreach my $field (@$fields) { - my $type = ref($field); - if ($type eq 'ConfigSection') { - my $lv = $v . $field->name . '.'; - generate_field_free($fh, $lv, $field->elements); - } elsif ($type eq 'ConfigString') { - printf $fh " free (%s%s);\n", $v, $field->name; - } elsif ($type eq 'ConfigStringList') { - printf $fh " guestfs_int_free_string_list (%s%s);\n", $v, $field->name; - } - } -} - -sub generate_field_print { - my ($fh, $prefix, $v, $fields) = @_; - foreach my $field (@$fields) { - my $type = ref($field); - my $printable_name = defined($prefix) - ? $prefix . '.' . $field->name - : $field->name; - if ($type eq 'ConfigSection') { - my $lv = $v . $field->name . '.'; - generate_field_print($fh, $printable_name, $lv, $field->elements); - } elsif ($type eq 'ConfigString') { - print $fh " fprintf (fp, \"%-20s %s\\n\",\n"; - printf $fh " \"%s\", %s%s ? %s%s : \"(none)\");\n", - $printable_name, $v, $field->name, $v, $field->name; - } elsif ($type eq 'ConfigInt') { - print $fh " fprintf (fp, \"%-20s %d\\n\",\n"; - printf $fh " \"%s\", %s%s);\n", $printable_name, $v, $field->name; - } elsif ($type eq 'ConfigBool') { - print $fh " fprintf (fp, \"%-20s %s\\n\",\n"; - printf $fh " \"%s\", %s%s ? \"true\" : \"false\");\n", - $printable_name, $v, $field->name; - } elsif ($type eq 'ConfigUInt64') { - print $fh " fprintf (fp, \"%-20s %\" PRIu64 \"\\n\",\n"; - printf $fh " \"%s\", %s%s);\n", $printable_name, $v, $field->name; - } elsif ($type eq 'ConfigUnsigned') { - print $fh " fprintf (fp, \"%-20s %u\\n\",\n"; - printf $fh " \"%s\", %s%s);\n", $printable_name, $v, $field->name; - } elsif ($type eq 'ConfigEnum') { - printf $fh " fprintf (fp, \"%%-20s \", \"%s\");\n", $printable_name; - printf $fh " print_%s (%s%s, fp);\n", $field->enum, $v, $field->name; - print $fh " fprintf (fp, \"\\n\");\n"; - } elsif ($type eq 'ConfigStringList') { - printf $fh " fprintf (fp, \"%%-20s\", \"%s\");\n", $printable_name; - printf $fh " if (%s%s) {\n", $v, $field->name; - printf $fh " for (i = 0; %s%s[i] != NULL; ++i)\n", $v, $field->name; - printf $fh " fprintf (fp, \" %%s\", %s%s[i]);\n", $v, $field->name; - print $fh " }\n"; - print $fh " else\n"; - print $fh " fprintf (fp, \" (none)\\n\");\n"; - print $fh " fprintf (fp, \"\\n\");\n"; - } - } -} - -sub generate_p2v_config_c { - my $fh = shift; - print_generated_header($fh); - print $fh <<"EOF"; -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdint.h> -#include <stdbool.h> -#include <inttypes.h> -#include <errno.h> -#include <error.h> - -#include "p2v.h" -#include "p2v-config.h" - -/** - * Allocate a new config struct. - */ -struct config * -new_config (void) -{ - struct config *c; - - c = calloc (1, sizeof *c); - if (c == NULL) - error (EXIT_FAILURE, errno, "calloc"); - -EOF - - generate_field_initialization($fh, "c->", @fields); - - print $fh <<"EOF"; - - return c; -} - -/** - * Copy a config struct. - */ -struct config * -copy_config (struct config *old) -{ - struct config *c = new_config (); - - memcpy (c, old, sizeof *c); - - /* Need to deep copy strings and string lists. */ -EOF - - generate_field_copy($fh, "c->", @fields); - - print $fh <<"EOF"; - - return c; -} - -/** - * Free a config struct. - */ -void -free_config (struct config *c) -{ - if (c == NULL) - return; - -EOF - - generate_field_free($fh, "c->", @fields); - - print $fh <<"EOF"; -} - -EOF - - foreach my $enum (@enums) { - my $name = shift @$enum; - print $fh "static void\n"; - printf $fh "print_%s (enum %s v, FILE *fp)\n", $name, $name; - print $fh "{\n"; - printf $fh " switch (v) {\n"; - foreach my $items (@$enum) { - my ($n, $cmdline, $foo) = @$items; - printf $fh " case %s:\n", $n; - printf $fh " fprintf (fp, \"%s\");\n", $cmdline; - print $fh " break;\n"; - } - print $fh " }\n"; - print $fh "}\n"; - print $fh "\n" - } - - print $fh <<"EOF"; -/** - * Print the conversion parameters and other important information. - */ -void -print_config (struct config *c, FILE *fp) -{ - size_t i; - - fprintf (fp, \"%-20s %s\\n\", \"local version\", PACKAGE_VERSION_FULL); - fprintf (fp, \"%-20s %s\\n\", \"remote version\", - v2v_version ? v2v_version : \"unknown\"); -EOF - - generate_field_print($fh, undef, "c->", @fields); - - print $fh <<"EOF"; -} -EOF -} - -sub find_alias { - my $name = shift; - foreach my $alias (@cmdline_aliases) { - if ($name eq @$alias[0]) { - return @$alias[1]; - } - } - return; -} - -sub find_enum { - my $name = shift; - foreach my $enum (@enums) { - my $n = shift @$enum; - if ($n eq $name) { - return @$enum; - } - } - return; -} - -sub generate_field_config { - my ($fh, $prefix, $v, $fields) = @_; - - foreach my $field (@$fields) { - my $type = ref($field); - if ($type eq 'ConfigSection') { - my $lprefix = $prefix . '.' . $field->name; - my $lv = $v . $field->name . '.'; - generate_field_config($fh, $lprefix, $lv, $field->elements); - } else { - my $key = $prefix . '.' . $field->name; - - if (not (any { $_ eq $key } @cmdline_ignore)) { - # Is there an alias for this field? - my $alias = find_alias($key); - - printf $fh " if ((p = get_cmdline_key (cmdline, \"%s\")) != NULL", $key; - if (defined($alias)) { - print $fh " ||\n"; - printf $fh " (p = get_cmdline_key (cmdline, \"%s\")) != NULL", $alias; - } - print $fh ") {\n"; - - # Parse the field. - if ($type eq 'ConfigString') { - printf $fh " free (%s%s);\n", $v, $field->name; - printf $fh " %s%s = strdup (p);\n", $v, $field->name; - printf $fh " if (%s%s == NULL)\n", $v, $field->name; - print $fh " error (EXIT_FAILURE, errno, \"strdup\");\n"; - } elsif ($type eq 'ConfigInt') { - printf $fh " if (sscanf (p, \"%%d\", &%s%s) != 1)\n", $v, $field->name; - print $fh " error (EXIT_FAILURE, errno,\n"; - print $fh " \"cannot parse %s=%s from the kernel command line\",\n"; - printf $fh " \"%s\", p);\n", $key; - } elsif ($type eq 'ConfigBool') { - printf $fh " %s%s = guestfs_int_is_true (p) || STREQ (p, \"\");\n", $v, $field->name; - } elsif ($type eq 'ConfigUInt64') { - print $fh " xerr = xstrtoull (p, NULL, 0, &ull, \"0kKMGTPEZY\");\n"; - print $fh " if (xerr != LONGINT_OK)\n"; - print $fh " error (EXIT_FAILURE, 0,\n"; - print $fh " \"cannot parse %s=%s from the kernel command line\",\n"; - printf $fh " \"%s\", p);\n", $key; - printf $fh " %s%s = ull;\n", $v, $field->name; - } elsif ($type eq 'ConfigUnsigned') { - printf $fh " if (sscanf (p, \"%%u\", &%s%s) != 1)\n", $v, $field->name; - print $fh " error (EXIT_FAILURE, errno,\n"; - print $fh " \"cannot parse %s=%s from the kernel command line\",\n"; - printf $fh " \"%s\", p);\n", $key; - } elsif ($type eq 'ConfigEnum') { - my @enum_choices = find_enum($field->enum) or die "cannot find ConfigEnum $field->enum"; - printf $fh " "; - foreach my $items (@enum_choices) { - my ($n, $cmdline, $foo) = @$items; - printf $fh "if (STREQ (p, \"%s\"))\n", $cmdline; - printf $fh " %s%s = %s;\n", $v, $field->name, $n; - print $fh " else "; - } - print $fh "{\n"; - print $fh " error (EXIT_FAILURE, 0,\n"; - print $fh " \"invalid value %s=%s from the kernel command line\",\n"; - printf $fh " \"%s\", p);\n", $key; - print $fh " }\n"; - } elsif ($type eq 'ConfigStringList') { - printf $fh " guestfs_int_free_string_list (%s%s);\n", $v, $field->name; - printf $fh " %s%s = guestfs_int_split_string (',', p);\n", $v, $field->name; - printf $fh " if (%s%s == NULL)\n", $v, $field->name; - print $fh " error (EXIT_FAILURE, errno, \"strdup\");\n"; - } - - print $fh " }\n"; - print $fh "\n"; - } - } - } -} - -sub generate_p2v_kernel_config_c { - my $fh = shift; - print_generated_header($fh); - print $fh <<"EOF"; -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <inttypes.h> -#include <unistd.h> -#include <errno.h> -#include <error.h> - -#include "xstrtol.h" - -#include "p2v.h" -#include "p2v-config.h" - -/** - * Read the kernel command line and parse out any C<p2v.*> fields that - * we understand into the config struct. - */ -void -update_config_from_kernel_cmdline (struct config *c, char **cmdline) -{ - const char *p; - strtol_error xerr; - unsigned long long ull; - -EOF - - generate_field_config($fh, "p2v", "c->", @fields); - - print $fh <<"EOF"; - if (c->auth.identity.url != NULL) - c->auth.identity.file_needs_update = 1; - - /* Undocumented command line parameter used for testing command line - * parsing. - */ - p = get_cmdline_key (cmdline, "p2v.dump_config_and_exit"); - if (p) { - print_config (c, stdout); - exit (EXIT_SUCCESS); - } -} -EOF -} - -sub generate_field_config_pod { - my ($fh, $prefix, $fields) = @_; - - foreach my $field (@$fields) { - my $type = ref($field); - if ($type eq 'ConfigSection') { - my $lprefix = $prefix . '.' . $field->name; - generate_field_config_pod($fh, $lprefix, $field->elements); - } else { - my $key = $prefix . '.' . $field->name; - - if (not (any { $_ eq $key } @cmdline_ignore)) { - # Is there an alias for this field? - my $manual_entry = $cmdline_manual{$key} or die "missing manual entry for $key"; - - # For booleans there is no shortopt field. For enums - # we generate it. - my $shortopt; - if ($type eq 'ConfigBool') { - die "non-empty shortopt for $field->name" if $manual_entry->shortopt ne ''; - $shortopt = ''; - } elsif ($type eq 'ConfigEnum') { - die "non-empty shortopt for $field->name" if $manual_entry->shortopt ne ''; - my @enum_choices = find_enum($field->enum) or die "cannot find ConfigEnum $field->enum"; - $shortopt = "=(" . join('|', map { $_->[1] } @enum_choices) . ")"; - } else { - $shortopt = "=" . $manual_entry->shortopt; - } - - # The description must not end with \n - die "description of $key must not end with \\n" if $manual_entry->description =~ /\n\z/; - - # Is there an alias for this field? - my $alias = find_alias($key); - printf $fh "=item B<%s%s>\n\n", $key, $shortopt; - if (defined($alias)) { - printf $fh "=item B<%s%s>\n\n", $alias, $shortopt; - } - - printf $fh "%s\n\n", $manual_entry->description; - } - } - } -} - -sub write_to { - my $fn = shift; - if (defined($output)) { - open(my $fh, '>', $output) or die "Could not open file '$output': $!"; - $fn->($fh, @_); - close($fh); - } else { - $fn->(*STDOUT, @_); - } -} - -if ($filename eq 'config.c') { - write_to(\&generate_p2v_config_c); -} elsif ($filename eq 'kernel-config.c') { - write_to(\&generate_p2v_kernel_config_c); -} elsif ($filename eq 'p2v-config.h') { - write_to(\&generate_p2v_config_h); -} elsif ($filename eq 'virt-p2v-kernel-config.pod') { - write_to(\&generate_field_config_pod, "p2v", @fields); -} else { - die "$progname: unrecognized output file '$filename'\n"; -} diff --git a/p2v/gui-gtk2-compat.h b/p2v/gui-gtk2-compat.h deleted file mode 100644 index 65569ddbe..000000000 --- a/p2v/gui-gtk2-compat.h +++ /dev/null @@ -1,117 +0,0 @@ -/* virt-p2v - * Copyright (C) 2009-2019 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. - */ - -/* Backwards compatibility for ancient RHEL 5 Gtk 2.10. */ -#ifndef GTK_COMBO_BOX_TEXT -#define GTK_COMBO_BOX_TEXT GTK_COMBO_BOX -#define gtk_combo_box_text_new() gtk_combo_box_new_text() -#define gtk_combo_box_text_append_text(combo, text) \ - gtk_combo_box_append_text((combo), (text)) -#define gtk_combo_box_text_get_active_text(combo) \ - gtk_combo_box_get_active_text((combo)) -#endif - -#if !GTK_CHECK_VERSION(2,12,0) /* gtk < 2.12 */ -#define gtk_widget_set_tooltip_markup(widget, text) /* nothing */ -#endif - -#if !GTK_CHECK_VERSION(2,14,0) /* gtk < 2.14 */ -#define gtk_dialog_get_content_area(dlg) ((dlg)->vbox) -#endif - -#if !GTK_CHECK_VERSION(2,18,0) /* gtk < 2.18 */ -static void -gtk_cell_renderer_set_alignment (GtkCellRenderer *cell, - gfloat xalign, gfloat yalign) -{ - if ((xalign != cell->xalign) || (yalign != cell->yalign)) { - g_object_freeze_notify (G_OBJECT (cell)); - - if (xalign != cell->xalign) { - cell->xalign = xalign; - g_object_notify (G_OBJECT (cell), "xalign"); - } - - if (yalign != cell->yalign) { - cell->yalign = yalign; - g_object_notify (G_OBJECT (cell), "yalign"); - } - - g_object_thaw_notify (G_OBJECT (cell)); - } -} -#endif - -#if !GTK_CHECK_VERSION(2,20,0) /* gtk < 2.20 */ -typedef struct _ResponseData ResponseData; - -struct _ResponseData -{ - gint response_id; -}; - -static void -response_data_free (gpointer data) -{ - g_slice_free (ResponseData, data); -} - -static ResponseData * -get_response_data (GtkWidget *widget, gboolean create) -{ - ResponseData *ad = g_object_get_data (G_OBJECT (widget), - "gtk-dialog-response-data"); - - if (ad == NULL && create) { - ad = g_slice_new (ResponseData); - - g_object_set_data_full (G_OBJECT (widget), - g_intern_static_string ("gtk-dialog-response-data"), - ad, - response_data_free); - } - - return ad; -} - -static GtkWidget * -gtk_dialog_get_widget_for_response (GtkDialog *dialog, gint response_id) -{ - GList *children; - GList *tmp_list; - - children = gtk_container_get_children (GTK_CONTAINER (dialog->action_area)); - - tmp_list = children; - while (tmp_list != NULL) { - GtkWidget *widget = tmp_list->data; - ResponseData *rd = get_response_data (widget, FALSE); - - if (rd && rd->response_id == response_id) { - g_list_free (children); - return widget; - } - - tmp_list = tmp_list->next; - } - - g_list_free (children); - - return NULL; -} -#endif /* gtk < 2.20 */ diff --git a/p2v/gui-gtk3-compat.h b/p2v/gui-gtk3-compat.h deleted file mode 100644 index 212c3af28..000000000 --- a/p2v/gui-gtk3-compat.h +++ /dev/null @@ -1,140 +0,0 @@ -/* virt-p2v - * Copyright (C) 2009-2019 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. - */ - -/* Backwards compatibility for some deprecated functions in Gtk 3. */ -#if !GTK_CHECK_VERSION(3,2,0) /* gtk < 3.2 */ -static gboolean -gdk_event_get_button (const GdkEvent *event, guint *button) -{ - if (event->type != GDK_BUTTON_PRESS) - return FALSE; - - *button = ((const GdkEventButton *) event)->button; - return TRUE; -} -#endif - -#if GTK_CHECK_VERSION(3,2,0) /* gtk >= 3.2 */ -#define hbox_new(box, homogeneous, spacing) \ - do { \ - (box) = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, spacing); \ - if (homogeneous) \ - gtk_box_set_homogeneous (GTK_BOX (box), TRUE); \ - } while (0) -#define vbox_new(box, homogeneous, spacing) \ - do { \ - (box) = gtk_box_new (GTK_ORIENTATION_VERTICAL, spacing); \ - if (homogeneous) \ - gtk_box_set_homogeneous (GTK_BOX (box), TRUE); \ - } while (0) -#else /* gtk < 3.2 */ -#define hbox_new(box, homogeneous, spacing) \ - (box) = gtk_hbox_new ((homogeneous), (spacing)) -#define vbox_new(box, homogeneous, spacing) \ - (box) = gtk_vbox_new ((homogeneous), (spacing)) -#endif - -#if GTK_CHECK_VERSION(3,4,0) /* gtk >= 3.4 */ -/* Copy this enum from GtkTable, as when building without deprecated - * functions this is not automatically pulled in. - */ -typedef enum -{ - GTK_EXPAND = 1 << 0, - GTK_SHRINK = 1 << 1, - GTK_FILL = 1 << 2 -} GtkAttachOptions; -/* GtkGrid is sufficiently similar to GtkTable that we can just - * redefine these functions. - */ -#define table_new(grid, rows, columns) \ - (grid) = gtk_grid_new () -#define table_attach(grid, child, left, right, top, bottom, xoptions, yoptions, xpadding, ypadding) \ - do { \ - if (((xoptions) & GTK_EXPAND) != 0) \ - gtk_widget_set_hexpand ((child), TRUE); \ - if (((xoptions) & GTK_FILL) != 0) \ - gtk_widget_set_halign ((child), GTK_ALIGN_FILL); \ - if (((yoptions) & GTK_EXPAND) != 0) \ - gtk_widget_set_vexpand ((child), TRUE); \ - if (((yoptions) & GTK_FILL) != 0) \ - gtk_widget_set_valign ((child), GTK_ALIGN_FILL); \ - set_padding ((child), (xpadding), (ypadding)); \ - gtk_grid_attach (GTK_GRID (grid), (child), \ - (left), (top), (right)-(left), (bottom)-(top)); \ - } while (0) -#else -#define table_new(table, rows, columns) \ - (table) = gtk_table_new ((rows), (columns), FALSE) -#define table_attach(table, child, left, right,top, bottom, xoptions, yoptions, xpadding, ypadding) \ - gtk_table_attach (GTK_TABLE (table), (child), \ - (left), (right), (top), (bottom), \ - (xoptions), (yoptions), (xpadding), (ypadding)) -#endif - -#if GTK_CHECK_VERSION(3,8,0) /* gtk >= 3.8 */ -#define scrolled_window_add_with_viewport(container, child) \ - gtk_container_add (GTK_CONTAINER (container), child) -#else -#define scrolled_window_add_with_viewport(container, child) \ - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (container), child) -#endif - -#if !GTK_CHECK_VERSION(3,10,0) /* gtk < 3.10 */ -#define gdk_event_get_event_type(event) ((event)->type) -#endif - -#if GTK_CHECK_VERSION(3,10,0) /* gtk >= 3.10 */ -#undef GTK_STOCK_DIALOG_WARNING -#define GTK_STOCK_DIALOG_WARNING "dialog-warning" -#define gtk_image_new_from_stock gtk_image_new_from_icon_name -#endif - -#if GTK_CHECK_VERSION(3,14,0) /* gtk >= 3.14 */ -#define set_padding(widget, xpad, ypad) \ - do { \ - if ((xpad) != 0) { \ - gtk_widget_set_margin_start ((widget), (xpad)); \ - gtk_widget_set_margin_end ((widget), (xpad)); \ - } \ - if ((ypad) != 0) { \ - gtk_widget_set_margin_top ((widget), (ypad)); \ - gtk_widget_set_margin_bottom ((widget), (ypad)); \ - } \ - } while (0) -#define set_alignment(widget, xalign, yalign) \ - do { \ - if ((xalign) == 0.) \ - gtk_widget_set_halign ((widget), GTK_ALIGN_START); \ - else if ((xalign) == 1.) \ - gtk_widget_set_halign ((widget), GTK_ALIGN_END); \ - else \ - gtk_widget_set_halign ((widget), GTK_ALIGN_CENTER); \ - if ((yalign) == 0.) \ - gtk_widget_set_valign ((widget), GTK_ALIGN_START); \ - else if ((xalign) == 1.) \ - gtk_widget_set_valign ((widget), GTK_ALIGN_END); \ - else \ - gtk_widget_set_valign ((widget), GTK_ALIGN_CENTER); \ - } while (0) -#else /* gtk < 3.14 */ -#define set_padding(widget, xpad, ypad) \ - gtk_misc_set_padding(GTK_MISC(widget),(xpad),(ypad)) -#define set_alignment(widget, xalign, yalign) \ - gtk_misc_set_alignment(GTK_MISC(widget),(xalign),(yalign)) -#endif diff --git a/p2v/gui.c b/p2v/gui.c deleted file mode 100644 index 32c56dda7..000000000 --- a/p2v/gui.c +++ /dev/null @@ -1,2295 +0,0 @@ -/* virt-p2v - * Copyright (C) 2009-2019 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 file implements almost all of the virt-p2v graphical user - * interface (GUI). - * - * The GUI has three main dialogs: - * - * =over 4 - * - * =item Connection dialog - * - * The connection dialog is the one shown initially. It asks the user - * to type in the login details for the remote conversion server and - * invites the user to test the ssh connection. - * - * =item Conversion dialog - * - * The conversion dialog asks for information about the target VM - * (eg. the number of vCPUs required), and about what to convert - * (eg. which network interfaces should be copied and which should be - * ignored). - * - * =item Running dialog - * - * The running dialog is displayed when the P2V process is underway. - * It mainly displays the virt-v2v debug messages. - * - * =back - * - * Note that the other major dialog (C<"Configure network ...">) is - * handled entirely by NetworkManager's L<nm-connection-editor(1)> - * program and has nothing to do with this code. - * - * This file is written in a kind of "pseudo-Gtk" which is backwards - * compatible from Gtk 2.10 (RHEL 5) through at least Gtk 3.22. This - * is done using a few macros to implement old C<gtk_*> functions or - * map them to newer functions. Supporting ancient Gtk is important - * because we want to provide a virt-p2v binary that can run on very - * old kernels, to support 32 bit and proprietary SCSI drivers. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <inttypes.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <error.h> -#include <locale.h> -#include <assert.h> -#include <libintl.h> - -#include <pthread.h> - -/* errors in <gtk.h> */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#if defined(__GNUC__) && __GNUC__ >= 6 /* gcc >= 6 */ -#pragma GCC diagnostic ignored "-Wshift-overflow" -#endif -#include <gtk/gtk.h> -#pragma GCC diagnostic pop - -#include "ignore-value.h" -#include "getprogname.h" - -#include "p2v.h" - -/* See note about "pseudo-Gtk" above. */ -#include "gui-gtk2-compat.h" -#include "gui-gtk3-compat.h" - -/* Maximum vCPUs and guest memory that we will allow users to set. - * These limits come from - * https://access.redhat.com/articles/rhel-kvm-limits - */ -#define MAX_SUPPORTED_VCPUS 160 -#define MAX_SUPPORTED_MEMORY_MB (UINT64_C (4000 * 1024)) - -#if GLIB_CHECK_VERSION(2,32,0) && GTK_CHECK_VERSION(3,12,0) /* glib >= 2.32 && gtk >= 3.12 */ -#define USE_POPOVERS -#endif - -static void create_connection_dialog (struct config *); -static void create_conversion_dialog (struct config *); -static void create_running_dialog (void); -static void show_connection_dialog (void); -static void show_conversion_dialog (void); -static void show_running_dialog (void); - -static void set_info_label (void); - -/* The connection dialog. */ -static GtkWidget *conn_dlg, - *server_entry, *port_entry, - *username_entry, *password_entry, *identity_entry, *sudo_button, - *spinner_hbox, -#ifdef GTK_SPINNER - *spinner, -#endif - *spinner_message, *next_button; - -/* The conversion dialog. */ -static GtkWidget *conv_dlg, - *guestname_entry, *vcpus_entry, *memory_entry, - *vcpus_warning, *memory_warning, *target_warning_label, - *o_combo, *oc_entry, *os_entry, *of_entry, *oa_combo, - *info_label, - *disks_list, *removable_list, *interfaces_list, - *start_button; - -/* The running dialog which is displayed when virt-v2v is running. */ -static GtkWidget *run_dlg, - *v2v_output_sw, *v2v_output, *log_label, *status_label, - *cancel_button, *shutdown_button; - -/* Colour tags used in the v2v_output GtkTextBuffer. */ -static GtkTextTag *v2v_output_tags[16]; - -#if !GTK_CHECK_VERSION(3,0,0) /* gtk < 3 */ -/* The license of virt-p2v, for the About dialog. */ -static const char gplv2plus[] - "This program is free software; you can redistribute it and/or modify\n" - "it under the terms of the GNU General Public License as published by\n" - "the Free Software Foundation; either version 2 of the License, or\n" - "(at your option) any later version.\n" - "\n" - "This program is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "GNU General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU General Public License\n" - "along with this program; if not, write to the Free Software\n" - "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n"; -#endif - -/** - * The entry point from the main program. - * - * Note that C<gtk_init> etc have already been called in C<main>. - */ -void -gui_conversion (struct config *config) -{ - /* Create the dialogs. */ - create_connection_dialog (config); - create_conversion_dialog (config); - create_running_dialog (); - - /* Start by displaying the connection dialog. */ - show_connection_dialog (); - - gtk_main (); -} - -/*----------------------------------------------------------------------*/ -/* Connection dialog. */ - -static void username_changed_callback (GtkWidget *w, gpointer data); -static void password_or_identity_changed_callback (GtkWidget *w, gpointer data); -static void test_connection_clicked (GtkWidget *w, gpointer data); -static void *test_connection_thread (void *data); -static gboolean start_spinner (gpointer user_data); -static gboolean stop_spinner (gpointer user_data); -static gboolean test_connection_error (gpointer user_data); -static gboolean test_connection_ok (gpointer user_data); -static void configure_network_button_clicked (GtkWidget *w, gpointer data); -static void xterm_button_clicked (GtkWidget *w, gpointer data); -static void about_button_clicked (GtkWidget *w, gpointer data); -static void connection_next_clicked (GtkWidget *w, gpointer data); -static void repopulate_output_combo (struct config *config); - -/** - * Create the connection dialog. - * - * This creates the dialog, but it is not displayed. See - * C<show_connection_dialog>. - */ -static void -create_connection_dialog (struct config *config) -{ - GtkWidget *intro, *table; - GtkWidget *server_label; - GtkWidget *server_hbox; - GtkWidget *port_colon_label; - GtkWidget *username_label; - GtkWidget *password_label; - GtkWidget *identity_label; - GtkWidget *test_hbox, *test; - GtkWidget *about; - GtkWidget *configure_network; - GtkWidget *xterm; - char port_str[64]; - - conn_dlg = gtk_dialog_new (); - gtk_window_set_title (GTK_WINDOW (conn_dlg), getprogname ()); - gtk_window_set_resizable (GTK_WINDOW (conn_dlg), FALSE); - - /* The main dialog area. */ - intro = gtk_label_new (_("Connect to a virt-v2v conversion server over SSH:")); - gtk_label_set_line_wrap (GTK_LABEL (intro), TRUE); - set_padding (intro, 10, 10); - - table_new (table, 5, 2); - server_label = gtk_label_new_with_mnemonic (_("Conversion _server:")); - table_attach (table, server_label, - 0, 1, 0, 1, GTK_FILL, GTK_FILL, 4, 4); - set_alignment (server_label, 1., 0.5); - - hbox_new (server_hbox, FALSE, 4); - server_entry = gtk_entry_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (server_label), server_entry); - if (config->remote.server != NULL) - gtk_entry_set_text (GTK_ENTRY (server_entry), config->remote.server); - port_colon_label = gtk_label_new (":"); - port_entry = gtk_entry_new (); - gtk_entry_set_width_chars (GTK_ENTRY (port_entry), 6); - snprintf (port_str, sizeof port_str, "%d", config->remote.port); - gtk_entry_set_text (GTK_ENTRY (port_entry), port_str); - gtk_box_pack_start (GTK_BOX (server_hbox), server_entry, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (server_hbox), port_colon_label, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (server_hbox), port_entry, FALSE, FALSE, 0); - table_attach (table, server_hbox, - 1, 2, 0, 1, GTK_EXPAND|GTK_FILL, GTK_FILL, 4, 4); - - username_label = gtk_label_new_with_mnemonic (_("_User name:")); - table_attach (table, username_label, - 0, 1, 1, 2, GTK_FILL, GTK_FILL, 4, 4); - set_alignment (username_label, 1., 0.5); - username_entry = gtk_entry_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (username_label), username_entry); - if (config->auth.username != NULL) - gtk_entry_set_text (GTK_ENTRY (username_entry), config->auth.username); - else - gtk_entry_set_text (GTK_ENTRY (username_entry), "root"); - table_attach (table, username_entry, - 1, 2, 1, 2, GTK_EXPAND|GTK_FILL, GTK_FILL, 4, 4); - - password_label = gtk_label_new_with_mnemonic (_("_Password:")); - table_attach (table, password_label, - 0, 1, 2, 3, GTK_FILL, GTK_FILL, 4, 4); - set_alignment (password_label, 1., 0.5); - password_entry = gtk_entry_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (password_label), password_entry); - gtk_entry_set_visibility (GTK_ENTRY (password_entry), FALSE); -#ifdef GTK_INPUT_PURPOSE_PASSWORD - gtk_entry_set_input_purpose (GTK_ENTRY (password_entry), - GTK_INPUT_PURPOSE_PASSWORD); -#endif - if (config->auth.password != NULL) - gtk_entry_set_text (GTK_ENTRY (password_entry), config->auth.password); - table_attach (table, password_entry, - 1, 2, 2, 3, GTK_EXPAND|GTK_FILL, GTK_FILL, 4, 4); - - identity_label = gtk_label_new_with_mnemonic (_("SSH _Identity URL:")); - table_attach (table, identity_label, - 0, 1, 3, 4, GTK_FILL, GTK_FILL, 4, 4); - set_alignment (identity_label, 1., 0.5); - identity_entry = gtk_entry_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (identity_label), identity_entry); - if (config->auth.identity.url != NULL) - gtk_entry_set_text (GTK_ENTRY (identity_entry), config->auth.identity.url); - table_attach (table, identity_entry, - 1, 2, 3, 4, GTK_EXPAND|GTK_FILL, GTK_FILL, 4, 4); - - sudo_button - gtk_check_button_new_with_mnemonic (_("Use su_do when running virt-v2v")); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sudo_button), - config->auth.sudo); - table_attach (table, sudo_button, - 1, 2, 4, 5, GTK_FILL, GTK_FILL, 4, 4); - - hbox_new (test_hbox, FALSE, 0); - test = gtk_button_new_with_mnemonic (_("_Test connection")); - gtk_box_pack_start (GTK_BOX (test_hbox), test, TRUE, FALSE, 0); - - hbox_new (spinner_hbox, FALSE, 10); -#ifdef GTK_SPINNER - spinner = gtk_spinner_new (); - gtk_box_pack_start (GTK_BOX (spinner_hbox), spinner, FALSE, FALSE, 0); -#endif - spinner_message = gtk_label_new (NULL); - gtk_label_set_line_wrap (GTK_LABEL (spinner_message), TRUE); - set_padding (spinner_message, 10, 10); - gtk_box_pack_start (GTK_BOX (spinner_hbox), spinner_message, TRUE, TRUE, 0); - - gtk_box_pack_start - (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (conn_dlg))), - intro, TRUE, TRUE, 0); - gtk_box_pack_start - (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (conn_dlg))), - table, TRUE, TRUE, 0); - gtk_box_pack_start - (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (conn_dlg))), - test_hbox, FALSE, FALSE, 0); - gtk_box_pack_start - (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (conn_dlg))), - spinner_hbox, TRUE, TRUE, 0); - - /* Buttons. */ - gtk_dialog_add_buttons (GTK_DIALOG (conn_dlg), - _("_Configure network ..."), 1, - _("_XTerm ..."), 2, - _("_About virt-p2v " PACKAGE_VERSION " ..."), 3, - _("_Next"), 4, - NULL); - - next_button = gtk_dialog_get_widget_for_response (GTK_DIALOG (conn_dlg), 4); - gtk_widget_set_sensitive (next_button, FALSE); - - configure_network - gtk_dialog_get_widget_for_response (GTK_DIALOG (conn_dlg), 1); - xterm = gtk_dialog_get_widget_for_response (GTK_DIALOG (conn_dlg), 2); - about = gtk_dialog_get_widget_for_response (GTK_DIALOG (conn_dlg), 3); - - /* Signals. */ - g_signal_connect_swapped (G_OBJECT (conn_dlg), "destroy", - G_CALLBACK (gtk_main_quit), NULL); - g_signal_connect (G_OBJECT (test), "clicked", - G_CALLBACK (test_connection_clicked), config); - g_signal_connect (G_OBJECT (configure_network), "clicked", - G_CALLBACK (configure_network_button_clicked), NULL); - g_signal_connect (G_OBJECT (xterm), "clicked", - G_CALLBACK (xterm_button_clicked), NULL); - g_signal_connect (G_OBJECT (about), "clicked", - G_CALLBACK (about_button_clicked), NULL); - g_signal_connect (G_OBJECT (next_button), "clicked", - G_CALLBACK (connection_next_clicked), NULL); - g_signal_connect (G_OBJECT (username_entry), "changed", - G_CALLBACK (username_changed_callback), NULL); - g_signal_connect (G_OBJECT (password_entry), "changed", - G_CALLBACK (password_or_identity_changed_callback), NULL); - g_signal_connect (G_OBJECT (identity_entry), "changed", - G_CALLBACK (password_or_identity_changed_callback), NULL); - - /* Call this signal to initialize the sensitivity of the sudo - * button correctly. - */ - username_changed_callback (NULL, NULL); -} - -/** - * If the username is "root", disable the sudo button. - */ -static void -username_changed_callback (GtkWidget *w, gpointer data) -{ - const char *str; - int username_is_root; - int sudo_is_set; - - str = gtk_entry_get_text (GTK_ENTRY (username_entry)); - username_is_root = str != NULL && STREQ (str, "root"); - sudo_is_set = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (sudo_button)); - - /* The sudo button is sensitive if: - * - The username is not "root", or - * - The button is not already checked (to allow the user to uncheck it) - */ - gtk_widget_set_sensitive (sudo_button, !username_is_root || sudo_is_set); -} - -/** - * The password or SSH identity URL entries are mutually exclusive, so - * if one contains text then disable the other. This function is - * called when the "changed" signal is received on either. - */ -static void -password_or_identity_changed_callback (GtkWidget *w, gpointer data) -{ - const char *str; - int password_set; - int identity_set; - - str = gtk_entry_get_text (GTK_ENTRY (password_entry)); - password_set = str != NULL && STRNEQ (str, ""); - str = gtk_entry_get_text (GTK_ENTRY (identity_entry)); - identity_set = str != NULL && STRNEQ (str, ""); - - if (!password_set && !identity_set) { - gtk_widget_set_sensitive (password_entry, TRUE); - gtk_widget_set_sensitive (identity_entry, TRUE); - } - else if (identity_set) - gtk_widget_set_sensitive (password_entry, FALSE); - else if (password_set) - gtk_widget_set_sensitive (identity_entry, FALSE); -} - -/** - * Hide all other dialogs and show the connection dialog. - */ -static void -show_connection_dialog (void) -{ - /* Hide the other dialogs. */ - gtk_widget_hide (conv_dlg); - gtk_widget_hide (run_dlg); - - /* Show everything except the spinner. */ - gtk_widget_show_all (conn_dlg); - gtk_widget_hide (spinner_hbox); -} - -/** - * Callback from the C<Test connection> button. - * - * This initiates a background thread which actually does the ssh to - * the conversion server and the rest of the testing (see - * C<test_connection_thread>). - */ -static void -test_connection_clicked (GtkWidget *w, gpointer data) -{ - struct config *config = data; - const gchar *port_str; - const gchar *identity_str; - size_t errors = 0; - struct config *copy; - int err; - pthread_t tid; - pthread_attr_t attr; - - gtk_label_set_text (GTK_LABEL (spinner_message), ""); - gtk_widget_show_all (spinner_hbox); -#ifdef GTK_SPINNER - gtk_widget_hide (spinner); -#endif - - /* Get the fields from the various widgets. */ - free (config->remote.server); - config->remote.server = strdup (gtk_entry_get_text (GTK_ENTRY (server_entry))); - if (STREQ (config->remote.server, "")) { - gtk_label_set_text (GTK_LABEL (spinner_message), - _("error: No conversion server given.")); - gtk_widget_grab_focus (server_entry); - errors++; - } - port_str = gtk_entry_get_text (GTK_ENTRY (port_entry)); - if (sscanf (port_str, "%d", &config->remote.port) != 1 || - config->remote.port <= 0 || config->remote.port >= 65536) { - gtk_label_set_text (GTK_LABEL (spinner_message), - _("error: Invalid port number. If in doubt, use \"22\".")); - gtk_widget_grab_focus (port_entry); - errors++; - } - free (config->auth.username); - config->auth.username = strdup (gtk_entry_get_text (GTK_ENTRY (username_entry))); - if (STREQ (config->auth.username, "")) { - gtk_label_set_text (GTK_LABEL (spinner_message), - _("error: No user name. If in doubt, use \"root\".")); - gtk_widget_grab_focus (username_entry); - errors++; - } - free (config->auth.password); - config->auth.password = strdup (gtk_entry_get_text (GTK_ENTRY (password_entry))); - - free (config->auth.identity.url); - identity_str = gtk_entry_get_text (GTK_ENTRY (identity_entry)); - if (identity_str && STRNEQ (identity_str, "")) - config->auth.identity.url = strdup (identity_str); - else - config->auth.identity.url = NULL; - config->auth.identity.file_needs_update = 1; - - config->auth.sudo = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (sudo_button)); - - if (errors) - return; - - /* Give the testing thread its own copy of the config in case we - * update the config in the main thread. - */ - copy = copy_config (config); - - /* No errors so far, so test the connection in a background thread. */ - pthread_attr_init (&attr); - pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); - err = pthread_create (&tid, &attr, test_connection_thread, copy); - if (err != 0) - error (EXIT_FAILURE, err, "pthread_create"); - pthread_attr_destroy (&attr); -} - -/** - * Run C<test_connection> (in a detached background thread). Once it - * finishes stop the spinner and set the spinner message - * appropriately. If the test is successful then we enable the - * C<Next> button. If unsuccessful, an error is shown in the - * connection dialog. - */ -static void * -test_connection_thread (void *data) -{ - struct config *copy = data; - int r; - - g_idle_add (start_spinner, NULL); - - wait_network_online (copy); - r = test_connection (copy); - free_config (copy); - - g_idle_add (stop_spinner, NULL); - - if (r == -1) - g_idle_add (test_connection_error, NULL); - else - g_idle_add (test_connection_ok, NULL); - - /* Thread is detached anyway, so no one is waiting for the status. */ - return NULL; -} - -/** - * Idle task called from C<test_connection_thread> (but run on the - * main thread) to start the spinner in the connection dialog. - */ -static gboolean -start_spinner (gpointer user_data) -{ - gtk_label_set_text (GTK_LABEL (spinner_message), - _("Testing the connection to the conversion server ...")); -#ifdef GTK_SPINNER - gtk_widget_show (spinner); - gtk_spinner_start (GTK_SPINNER (spinner)); -#endif - return FALSE; -} - -/** - * Idle task called from C<test_connection_thread> (but run on the - * main thread) to stop the spinner in the connection dialog. - */ -static gboolean -stop_spinner (gpointer user_data) -{ -#ifdef GTK_SPINNER - gtk_spinner_stop (GTK_SPINNER (spinner)); - gtk_widget_hide (spinner); -#endif - return FALSE; -} - -/** - * Idle task called from C<test_connection_thread> (but run on the - * main thread) when there is an error. Display the error message and - * disable the C<Next> button so the user is forced to correct it. - */ -static gboolean -test_connection_error (gpointer user_data) -{ - const char *err = get_ssh_error (); - - gtk_label_set_text (GTK_LABEL (spinner_message), err); - /* Disable the Next button. */ - gtk_widget_set_sensitive (next_button, FALSE); - - return FALSE; -} - -/** - * Idle task called from C<test_connection_thread> (but run on the - * main thread) when the connection test was successful. - */ -static gboolean -test_connection_ok (gpointer user_data) -{ - gtk_label_set_text - (GTK_LABEL (spinner_message), - _("Connected to the conversion server.\n" - "Press the \"Next\" button to configure the conversion process.")); - - /* Enable the Next button. */ - gtk_widget_set_sensitive (next_button, TRUE); - gtk_widget_grab_focus (next_button); - - /* Update the information in the conversion dialog. */ - set_info_label (); - - return FALSE; -} - -/** - * Callback from the C<Configure network ...> button. This dialog is - * handled entirely by an external program which is part of - * NetworkManager. - */ -static void -configure_network_button_clicked (GtkWidget *w, gpointer data) -{ - if (access ("/sbin/yast2", X_OK) >= 0) - ignore_value (system ("yast2 lan &")); - else - ignore_value (system ("nm-connection-editor &")); -} - -/** - * Callback from the C<XTerm ...> button. - */ -static void -xterm_button_clicked (GtkWidget *w, gpointer data) -{ - ignore_value (system ("xterm &")); -} - -/** - * Callback from the C<About virt-p2v ...> button. - * - * See also F<p2v/about-authors.c> and F<p2v/about-license.c>. - */ -static void -about_button_clicked (GtkWidget *w, gpointer data) -{ - GtkWidget *dialog; - GtkWidget *parent = conn_dlg; - - dialog = gtk_about_dialog_new (); - - g_object_set (G_OBJECT (dialog), - "program-name", getprogname (), - "version", PACKAGE_VERSION_FULL " (" host_cpu ")", - "copyright", "\u00A9 2009-2019 Red Hat Inc.", - "comments", - _("Virtualize a physical machine to run on KVM"), -#if GTK_CHECK_VERSION(3,0,0) /* gtk >= 3 */ - "license-type", GTK_LICENSE_GPL_2_0, -#else - "license", gplv2plus, -#endif - "website", "http://libguestfs.org/", - "authors", authors, - NULL); - - gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); - gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent)); - gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); - - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); -} - -/** - * Callback when the connection dialog C<Next> button has been - * clicked. - */ -static void -connection_next_clicked (GtkWidget *w, gpointer data) -{ - /* Switch to the conversion dialog. */ - show_conversion_dialog (); -} - -/*----------------------------------------------------------------------*/ -/* Conversion dialog. */ - -static void populate_disks (GtkTreeView *disks_list); -static void populate_removable (GtkTreeView *removable_list); -static void populate_interfaces (GtkTreeView *interfaces_list); -static void toggled (GtkCellRendererToggle *cell, gchar *path_str, gpointer data); -static void network_edited_callback (GtkCellRendererToggle *cell, gchar *path_str, gchar *new_text, gpointer data); -static gboolean maybe_identify_click (GtkWidget *interfaces_list, GdkEventButton *event, gpointer data); -static void set_disks_from_ui (struct config *); -static void set_removable_from_ui (struct config *); -static void set_interfaces_from_ui (struct config *); -static void conversion_back_clicked (GtkWidget *w, gpointer data); -static void start_conversion_clicked (GtkWidget *w, gpointer data); -static void vcpus_or_memory_check_callback (GtkWidget *w, gpointer data); -static void notify_ui_callback (int type, const char *data); -static int get_vcpus_from_conv_dlg (void); -static uint64_t get_memory_from_conv_dlg (void); - -enum { - DISKS_COL_CONVERT = 0, - DISKS_COL_DEVICE, - NUM_DISKS_COLS, -}; - -enum { - REMOVABLE_COL_CONVERT = 0, - REMOVABLE_COL_DEVICE, - NUM_REMOVABLE_COLS, -}; - -enum { - INTERFACES_COL_CONVERT = 0, - INTERFACES_COL_DEVICE, - INTERFACES_COL_NETWORK, - NUM_INTERFACES_COLS, -}; - -/** - * Create the conversion dialog. - * - * This creates the dialog, but it is not displayed. See - * C<show_conversion_dialog>. - */ -static void -create_conversion_dialog (struct config *config) -{ - GtkWidget *back; - GtkWidget *hbox, *left_vbox, *right_vbox; - GtkWidget *target_frame, *target_vbox, *target_tbl; - GtkWidget *guestname_label, *vcpus_label, *memory_label; - GtkWidget *output_frame, *output_vbox, *output_tbl; - GtkWidget *o_label, *oa_label, *oc_label, *of_label, *os_label; - GtkWidget *info_frame; - GtkWidget *disks_frame, *disks_sw; - GtkWidget *removable_frame, *removable_sw; - GtkWidget *interfaces_frame, *interfaces_sw; - char vcpus_str[64]; - char memory_str[64]; - - conv_dlg = gtk_dialog_new (); - gtk_window_set_title (GTK_WINDOW (conv_dlg), getprogname ()); - gtk_window_set_resizable (GTK_WINDOW (conv_dlg), FALSE); - /* XXX It would be nice not to have to set this explicitly, but - * if we don't then Gtk chooses a very small window. - */ - gtk_widget_set_size_request (conv_dlg, 900, 600); - - /* The main dialog area. */ - hbox_new (hbox, TRUE, 1); - vbox_new (left_vbox, FALSE, 1); - vbox_new (right_vbox, TRUE, 1); - - /* The left column: target properties and output options. */ - target_frame = gtk_frame_new (_("Target properties")); - gtk_container_set_border_width (GTK_CONTAINER (target_frame), 4); - - vbox_new (target_vbox, FALSE, 1); - - table_new (target_tbl, 3, 3); - guestname_label = gtk_label_new_with_mnemonic (_("_Name:")); - table_attach (target_tbl, guestname_label, - 0, 1, 0, 1, GTK_FILL, GTK_FILL, 1, 1); - set_alignment (guestname_label, 1., 0.5); - guestname_entry = gtk_entry_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (guestname_label), guestname_entry); - if (config->guestname != NULL) - gtk_entry_set_text (GTK_ENTRY (guestname_entry), config->guestname); - table_attach (target_tbl, guestname_entry, - 1, 2, 0, 1, GTK_FILL, GTK_FILL, 1, 1); - - vcpus_label = gtk_label_new_with_mnemonic (_("# _vCPUs:")); - table_attach (target_tbl, vcpus_label, - 0, 1, 1, 2, GTK_FILL, GTK_FILL, 1, 1); - set_alignment (vcpus_label, 1., 0.5); - vcpus_entry = gtk_entry_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (vcpus_label), vcpus_entry); - snprintf (vcpus_str, sizeof vcpus_str, "%d", config->vcpus); - gtk_entry_set_text (GTK_ENTRY (vcpus_entry), vcpus_str); - table_attach (target_tbl, vcpus_entry, - 1, 2, 1, 2, GTK_FILL, GTK_FILL, 1, 1); - vcpus_warning = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, - GTK_ICON_SIZE_BUTTON); - table_attach (target_tbl, vcpus_warning, - 2, 3, 1, 2, 0, 0, 1, 1); - - memory_label = gtk_label_new_with_mnemonic (_("_Memory (MB):")); - table_attach (target_tbl, memory_label, - 0, 1, 2, 3, GTK_FILL, GTK_FILL, 1, 1); - set_alignment (memory_label, 1., 0.5); - memory_entry = gtk_entry_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (memory_label), memory_entry); - snprintf (memory_str, sizeof memory_str, "%" PRIu64, - config->memory / 1024 / 1024); - gtk_entry_set_text (GTK_ENTRY (memory_entry), memory_str); - table_attach (target_tbl, memory_entry, - 1, 2, 2, 3, GTK_FILL, GTK_FILL, 1, 1); - memory_warning = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, - GTK_ICON_SIZE_BUTTON); - table_attach (target_tbl, memory_warning, - 2, 3, 2, 3, 0, 0, 1, 1); - - gtk_box_pack_start (GTK_BOX (target_vbox), target_tbl, TRUE, TRUE, 0); - - target_warning_label = gtk_label_new (""); - gtk_label_set_line_wrap (GTK_LABEL (target_warning_label), TRUE); - gtk_label_set_line_wrap_mode (GTK_LABEL (target_warning_label), - PANGO_WRAP_WORD); - gtk_widget_set_size_request (target_warning_label, -1, 7 * 16); - gtk_box_pack_end (GTK_BOX (target_vbox), target_warning_label, TRUE, TRUE, 0); - - gtk_container_add (GTK_CONTAINER (target_frame), target_vbox); - - output_frame = gtk_frame_new (_("Virt-v2v output options")); - gtk_container_set_border_width (GTK_CONTAINER (output_frame), 4); - - vbox_new (output_vbox, FALSE, 1); - - table_new (output_tbl, 5, 2); - o_label = gtk_label_new_with_mnemonic (_("Output _to (-o):")); - table_attach (output_tbl, o_label, - 0, 1, 0, 1, GTK_FILL, GTK_FILL, 1, 1); - set_alignment (o_label, 1., 0.5); - o_combo = gtk_combo_box_text_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (o_label), o_combo); - gtk_widget_set_tooltip_markup (o_combo, _("<b>libvirt</b> means send the converted guest to libvirt-managed KVM on the conversion server. <b>local</b> means put it in a directory on the conversion server. <b>rhv</b> means write it to RHV-M/oVirt. <b>glance</b> means write it to OpenStack Glance. See the virt-v2v(1) manual page for more information about output options.")); - repopulate_output_combo (config); - table_attach (output_tbl, o_combo, - 1, 2, 0, 1, GTK_FILL, GTK_FILL, 1, 1); - - oc_label = gtk_label_new_with_mnemonic (_("_Output conn. (-oc):")); - table_attach (output_tbl, oc_label, - 0, 1, 1, 2, GTK_FILL, GTK_FILL, 1, 1); - set_alignment (oc_label, 1., 0.5); - oc_entry = gtk_entry_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (oc_label), oc_entry); - gtk_widget_set_tooltip_markup (oc_entry, _("For <b>libvirt</b> only, the libvirt connection URI, or leave blank to add the guest to the default libvirt instance on the conversion server. For others, leave this field blank.")); - if (config->output.connection != NULL) - gtk_entry_set_text (GTK_ENTRY (oc_entry), config->output.connection); - table_attach (output_tbl, oc_entry, - 1, 2, 1, 2, GTK_FILL, GTK_FILL, 1, 1); - - os_label = gtk_label_new_with_mnemonic (_("Output _storage (-os):")); - table_attach (output_tbl, os_label, - 0, 1, 2, 3, GTK_FILL, GTK_FILL, 1, 1); - set_alignment (os_label, 1., 0.5); - os_entry = gtk_entry_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (os_label), os_entry); - gtk_widget_set_tooltip_markup (os_entry, _("For <b>local</b>, put the directory name on the conversion server. For <b>rhv</b>, put the Export Storage Domain (server:/mountpoint). For others, leave this field blank.")); - if (config->output.storage != NULL) - gtk_entry_set_text (GTK_ENTRY (os_entry), config->output.storage); - table_attach (output_tbl, os_entry, - 1, 2, 2, 3, GTK_FILL, GTK_FILL, 1, 1); - - of_label = gtk_label_new_with_mnemonic (_("Output _format (-of):")); - table_attach (output_tbl, of_label, - 0, 1, 3, 4, GTK_FILL, GTK_FILL, 1, 1); - set_alignment (of_label, 1., 0.5); - of_entry = gtk_entry_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (of_label), of_entry); - gtk_widget_set_tooltip_markup (of_entry, _("The output disk format, typically <b>raw</b> or <b>qcow2</b>. If blank, defaults to <b>raw</b>.")); - if (config->output.format != NULL) - gtk_entry_set_text (GTK_ENTRY (of_entry), config->output.format); - table_attach (output_tbl, of_entry, - 1, 2, 3, 4, GTK_FILL, GTK_FILL, 1, 1); - - oa_label = gtk_label_new_with_mnemonic (_("Output _allocation (-oa):")); - table_attach (output_tbl, oa_label, - 0, 1, 4, 5, GTK_FILL, GTK_FILL, 1, 1); - set_alignment (oa_label, 1., 0.5); - oa_combo = gtk_combo_box_text_new (); - gtk_label_set_mnemonic_widget (GTK_LABEL (oa_label), oa_combo); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (oa_combo), - "sparse"); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (oa_combo), - "preallocated"); - switch (config->output.allocation) { - case OUTPUT_ALLOCATION_PREALLOCATED: - gtk_combo_box_set_active (GTK_COMBO_BOX (oa_combo), 1); - break; - default: - gtk_combo_box_set_active (GTK_COMBO_BOX (oa_combo), 0); - break; - } - table_attach (output_tbl, oa_combo, - 1, 2, 4, 5, GTK_FILL, GTK_FILL, 1, 1); - - gtk_box_pack_start (GTK_BOX (output_vbox), output_tbl, TRUE, TRUE, 0); - gtk_container_add (GTK_CONTAINER (output_frame), output_vbox); - - info_frame = gtk_frame_new (_("Information")); - gtk_container_set_border_width (GTK_CONTAINER (info_frame), 4); - info_label = gtk_label_new (NULL); - set_alignment (info_label, 0.1, 0.5); - set_info_label (); - gtk_container_add (GTK_CONTAINER (info_frame), info_label); - - /* The right column: select devices to be converted. */ - disks_frame = gtk_frame_new (_("Fixed hard disks")); - gtk_container_set_border_width (GTK_CONTAINER (disks_frame), 4); - disks_sw = gtk_scrolled_window_new (NULL, NULL); - gtk_container_set_border_width (GTK_CONTAINER (disks_sw), 8); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (disks_sw), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - disks_list = gtk_tree_view_new (); - populate_disks (GTK_TREE_VIEW (disks_list)); - scrolled_window_add_with_viewport (disks_sw, disks_list); - gtk_container_add (GTK_CONTAINER (disks_frame), disks_sw); - - removable_frame = gtk_frame_new (_("Removable media")); - gtk_container_set_border_width (GTK_CONTAINER (removable_frame), 4); - removable_sw = gtk_scrolled_window_new (NULL, NULL); - gtk_container_set_border_width (GTK_CONTAINER (removable_sw), 8); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (removable_sw), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - removable_list = gtk_tree_view_new (); - populate_removable (GTK_TREE_VIEW (removable_list)); - scrolled_window_add_with_viewport (removable_sw, removable_list); - gtk_container_add (GTK_CONTAINER (removable_frame), removable_sw); - - interfaces_frame = gtk_frame_new (_("Network interfaces")); - gtk_container_set_border_width (GTK_CONTAINER (interfaces_frame), 4); - interfaces_sw = gtk_scrolled_window_new (NULL, NULL); - gtk_container_set_border_width (GTK_CONTAINER (interfaces_sw), 8); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (interfaces_sw), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - interfaces_list = gtk_tree_view_new (); - /* See maybe_identify_click below for what we're doing. */ - g_signal_connect (interfaces_list, "button-press-event", - G_CALLBACK (maybe_identify_click), NULL); - gtk_widget_set_tooltip_markup (interfaces_list, _("Left click on an interface name to flash the light on the physical interface.")); - populate_interfaces (GTK_TREE_VIEW (interfaces_list)); - scrolled_window_add_with_viewport (interfaces_sw, interfaces_list); - gtk_container_add (GTK_CONTAINER (interfaces_frame), interfaces_sw); - - /* Pack the top level dialog. */ - gtk_box_pack_start (GTK_BOX (left_vbox), target_frame, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (left_vbox), output_frame, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (left_vbox), info_frame, TRUE, TRUE, 0); - - gtk_box_pack_start (GTK_BOX (right_vbox), disks_frame, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (right_vbox), removable_frame, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (right_vbox), interfaces_frame, TRUE, TRUE, 0); - - gtk_box_pack_start (GTK_BOX (hbox), left_vbox, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (hbox), right_vbox, TRUE, TRUE, 0); - gtk_box_pack_start - (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (conv_dlg))), - hbox, TRUE, TRUE, 0); - - /* Buttons. */ - gtk_dialog_add_buttons (GTK_DIALOG (conv_dlg), - _("_Back"), 1, - _("Start _conversion"), 2, - NULL); - back = gtk_dialog_get_widget_for_response (GTK_DIALOG (conv_dlg), 1); - start_button = gtk_dialog_get_widget_for_response (GTK_DIALOG (conv_dlg), 2); - - /* Signals. */ - g_signal_connect_swapped (G_OBJECT (conv_dlg), "destroy", - G_CALLBACK (gtk_main_quit), NULL); - g_signal_connect (G_OBJECT (back), "clicked", - G_CALLBACK (conversion_back_clicked), NULL); - g_signal_connect (G_OBJECT (start_button), "clicked", - G_CALLBACK (start_conversion_clicked), config); - g_signal_connect (G_OBJECT (vcpus_entry), "changed", - G_CALLBACK (vcpus_or_memory_check_callback), NULL); - g_signal_connect (G_OBJECT (memory_entry), "changed", - G_CALLBACK (vcpus_or_memory_check_callback), NULL); -} - -/** - * Hide all other dialogs and show the conversion dialog. - */ -static void -show_conversion_dialog (void) -{ - /* Hide the other dialogs. */ - gtk_widget_hide (conn_dlg); - gtk_widget_hide (run_dlg); - - /* Show the conversion dialog. */ - gtk_widget_show_all (conv_dlg); - gtk_widget_hide (vcpus_warning); - gtk_widget_hide (memory_warning); - - /* output_drivers may have been updated, so repopulate o_combo. */ - repopulate_output_combo (NULL); -} - -/** - * Update the C<Information> section in the conversion dialog. - * - * Note that C<v2v_version> (the remote virt-v2v version) is read from - * the remote virt-v2v in the C<test_connection> function. - */ -static void -set_info_label (void) -{ - CLEANUP_FREE char *text; - int r; - - if (!v2v_version) - r = asprintf (&text, _("virt-p2v (client):\n%s"), PACKAGE_VERSION); - else - r = asprintf (&text, - _("virt-p2v (client):\n" - "%s\n" - "virt-v2v (conversion server):\n" - "%s"), - PACKAGE_VERSION_FULL, v2v_version); - if (r == -1) { - perror ("asprintf"); - return; - } - - gtk_label_set_text (GTK_LABEL (info_label), text); -} - -/** - * Repopulate the list of output drivers in the C<Output to (-o)> - * combo. The list of drivers is read from the remote virt-v2v - * instance in C<test_connection>. - */ -static void -repopulate_output_combo (struct config *config) -{ - GtkTreeModel *model; - CLEANUP_FREE char *output; - size_t i; - - /* Which driver is currently selected? */ - if (config && config->output.type) - output = strdup (config->output.type); - else - output = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (o_combo)); - - /* Remove existing rows in o_combo. */ - model = gtk_combo_box_get_model (GTK_COMBO_BOX (o_combo)); - gtk_list_store_clear (GTK_LIST_STORE (model)); - - /* List of output_drivers from virt-v2v not read yet, so present - * a standard set of drivers. - */ - if (output_drivers == NULL) { - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (o_combo), "libvirt"); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (o_combo), "local"); - /* Use rhev instead of rhv here so we can work with old virt-v2v. */ - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (o_combo), "rhev"); - if (output == NULL || STREQ (output, "libvirt")) - gtk_combo_box_set_active (GTK_COMBO_BOX (o_combo), 0); - else if (STREQ (output, "local")) - gtk_combo_box_set_active (GTK_COMBO_BOX (o_combo), 1); - else if (STREQ (output, "rhev")) - gtk_combo_box_set_active (GTK_COMBO_BOX (o_combo), 2); - } - /* List of -o options read from remote virt-v2v --machine-readable. */ - else { - for (i = 0; output_drivers[i] != NULL; ++i) - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (o_combo), - output_drivers[i]); - if (output) { - for (i = 0; output_drivers[i] != NULL; ++i) - if (STREQ (output, output_drivers[i])) - gtk_combo_box_set_active (GTK_COMBO_BOX (o_combo), i); - } - else - gtk_combo_box_set_active (GTK_COMBO_BOX (o_combo), 0); - } -} - -/** - * Populate the C<Fixed hard disks> treeview. - */ -static void -populate_disks (GtkTreeView *disks_list) -{ - GtkListStore *disks_store; - GtkCellRenderer *disks_col_convert, *disks_col_device; - GtkTreeIter iter; - size_t i; - - disks_store = gtk_list_store_new (NUM_DISKS_COLS, - G_TYPE_BOOLEAN, G_TYPE_STRING); - if (all_disks != NULL) { - for (i = 0; all_disks[i] != NULL; ++i) { - uint64_t size; - CLEANUP_FREE char *size_gb = NULL; - CLEANUP_FREE char *model = NULL; - CLEANUP_FREE char *serial = NULL; - CLEANUP_FREE char *device_descr = NULL; - - if (all_disks[i][0] != '/') { /* not using --test-disk */ - size = get_blockdev_size (all_disks[i]); - if (asprintf (&size_gb, "%" PRIu64 "G", size) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - model = get_blockdev_model (all_disks[i]); - serial = get_blockdev_serial (all_disks[i]); - } - - if (asprintf (&device_descr, - "<b>%s</b>\n" - "<small>" - "%s %s\n" - "%s%s" - "</small>", - all_disks[i], - size_gb ? size_gb : "", model ? model : "", - serial ? "s/n " : "", serial ? serial : "") == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - gtk_list_store_append (disks_store, &iter); - gtk_list_store_set (disks_store, &iter, - DISKS_COL_CONVERT, TRUE, - DISKS_COL_DEVICE, device_descr, - -1); - } - } - gtk_tree_view_set_model (disks_list, - GTK_TREE_MODEL (disks_store)); - gtk_tree_view_set_headers_visible (disks_list, TRUE); - disks_col_convert = gtk_cell_renderer_toggle_new (); - gtk_tree_view_insert_column_with_attributes (disks_list, - -1, - _("Convert"), - disks_col_convert, - "active", DISKS_COL_CONVERT, - NULL); - gtk_cell_renderer_set_alignment (disks_col_convert, 0.5, 0.0); - disks_col_device = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (disks_list, - -1, - _("Device"), - disks_col_device, - "markup", DISKS_COL_DEVICE, - NULL); - gtk_cell_renderer_set_alignment (disks_col_device, 0.0, 0.0); - - g_signal_connect (disks_col_convert, "toggled", - G_CALLBACK (toggled), disks_store); -} - -/** - * Populate the C<Removable media> treeview. - */ -static void -populate_removable (GtkTreeView *removable_list) -{ - GtkListStore *removable_store; - GtkCellRenderer *removable_col_convert, *removable_col_device; - GtkTreeIter iter; - size_t i; - - removable_store = gtk_list_store_new (NUM_REMOVABLE_COLS, - G_TYPE_BOOLEAN, G_TYPE_STRING); - if (all_removable != NULL) { - for (i = 0; all_removable[i] != NULL; ++i) { - CLEANUP_FREE char *device_descr = NULL; - - if (asprintf (&device_descr, "<b>%s</b>\n", all_removable[i]) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - gtk_list_store_append (removable_store, &iter); - gtk_list_store_set (removable_store, &iter, - REMOVABLE_COL_CONVERT, TRUE, - REMOVABLE_COL_DEVICE, device_descr, - -1); - } - } - gtk_tree_view_set_model (removable_list, - GTK_TREE_MODEL (removable_store)); - gtk_tree_view_set_headers_visible (removable_list, TRUE); - removable_col_convert = gtk_cell_renderer_toggle_new (); - gtk_tree_view_insert_column_with_attributes (removable_list, - -1, - _("Convert"), - removable_col_convert, - "active", REMOVABLE_COL_CONVERT, - NULL); - gtk_cell_renderer_set_alignment (removable_col_convert, 0.5, 0.0); - removable_col_device = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (removable_list, - -1, - _("Device"), - removable_col_device, - "markup", REMOVABLE_COL_DEVICE, - NULL); - gtk_cell_renderer_set_alignment (removable_col_device, 0.0, 0.0); - - g_signal_connect (removable_col_convert, "toggled", - G_CALLBACK (toggled), removable_store); -} - -/** - * Populate the C<Network interfaces> treeview. - */ -static void -populate_interfaces (GtkTreeView *interfaces_list) -{ - GtkListStore *interfaces_store; - GtkCellRenderer *interfaces_col_convert, *interfaces_col_device, - *interfaces_col_network; - GtkTreeIter iter; - size_t i; - - interfaces_store = gtk_list_store_new (NUM_INTERFACES_COLS, - G_TYPE_BOOLEAN, G_TYPE_STRING, - G_TYPE_STRING); - if (all_interfaces) { - for (i = 0; all_interfaces[i] != NULL; ++i) { - const char *if_name = all_interfaces[i]; - CLEANUP_FREE char *device_descr = NULL; - CLEANUP_FREE char *if_addr = get_if_addr (if_name); - CLEANUP_FREE char *if_vendor = get_if_vendor (if_name, 40); - - if (asprintf (&device_descr, - "<b>%s</b>\n" - "<small>" - "%s\n" - "%s" - "</small>\n" - "<small><u><span foreground=\"blue\">Identify interface</span></u></small>", - if_name, - if_addr ? : _("Unknown"), - if_vendor ? : _("Unknown")) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - gtk_list_store_append (interfaces_store, &iter); - gtk_list_store_set (interfaces_store, &iter, - /* Only convert the first interface. As - * they are sorted, this is usually the - * physical interface. - */ - INTERFACES_COL_CONVERT, i == 0, - INTERFACES_COL_DEVICE, device_descr, - INTERFACES_COL_NETWORK, "default", - -1); - } - } - gtk_tree_view_set_model (interfaces_list, - GTK_TREE_MODEL (interfaces_store)); - gtk_tree_view_set_headers_visible (interfaces_list, TRUE); - interfaces_col_convert = gtk_cell_renderer_toggle_new (); - gtk_tree_view_insert_column_with_attributes (interfaces_list, - -1, - _("Convert"), - interfaces_col_convert, - "active", INTERFACES_COL_CONVERT, - NULL); - gtk_cell_renderer_set_alignment (interfaces_col_convert, 0.5, 0.0); - interfaces_col_device = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (interfaces_list, - -1, - _("Device"), - interfaces_col_device, - "markup", INTERFACES_COL_DEVICE, - NULL); - gtk_cell_renderer_set_alignment (interfaces_col_device, 0.0, 0.0); - interfaces_col_network = gtk_cell_renderer_text_new (); - gtk_tree_view_insert_column_with_attributes (interfaces_list, - -1, - _("Connect to virtual network"), - interfaces_col_network, - "text", INTERFACES_COL_NETWORK, - NULL); - gtk_cell_renderer_set_alignment (interfaces_col_network, 0.0, 0.0); - - g_signal_connect (interfaces_col_convert, "toggled", - G_CALLBACK (toggled), interfaces_store); - - g_object_set (interfaces_col_network, "editable", TRUE, NULL); - g_signal_connect (interfaces_col_network, "edited", - G_CALLBACK (network_edited_callback), interfaces_store); -} - -static void -toggled (GtkCellRendererToggle *cell, gchar *path_str, gpointer data) -{ - GtkTreeModel *model = data; - GtkTreePath *path = gtk_tree_path_new_from_string (path_str); - GtkTreeIter iter; - gboolean v; - - gtk_tree_model_get_iter (model, &iter, path); - gtk_tree_model_get (model, &iter, 0 /* CONVERT */, &v, -1); - v ^= 1; - gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0 /* CONVERT */, v, -1); - gtk_tree_path_free (path); -} - -static void -network_edited_callback (GtkCellRendererToggle *cell, gchar *path_str, - gchar *new_text, gpointer data) -{ - GtkTreeModel *model = data; - GtkTreePath *path; - GtkTreeIter iter; - - if (new_text == NULL || STREQ (new_text, "")) - return; - - path = gtk_tree_path_new_from_string (path_str); - - gtk_tree_model_get_iter (model, &iter, path); - gtk_list_store_set (GTK_LIST_STORE (model), &iter, - INTERFACES_COL_NETWORK, new_text, -1); - gtk_tree_path_free (path); -} - -/** - * When the user clicks on the interface name on the list of - * interfaces, we want to run C<ethtool --identify>, which usually - * makes some lights flash on the physical interface. - * - * We cannot catch clicks on the cell itself, so we have to go via a - * more obscure route. See L<http://stackoverflow.com/a/27207433> and - * L<https://en.wikibooks.org/wiki/GTK%2B_By_Example/Tree_View/Events> - */ -static gboolean -maybe_identify_click (GtkWidget *interfaces_list, GdkEventButton *event, - gpointer data) -{ - gboolean ret = FALSE; /* Did we handle this event? */ - guint button; - - /* Single left click only. */ - if (gdk_event_get_event_type ((const GdkEvent *) event) == GDK_BUTTON_PRESS && - gdk_event_get_button ((const GdkEvent *) event, &button) && - button == 1) { - GtkTreePath *path; - GtkTreeViewColumn *column; - gdouble event_x, event_y; - - if (gdk_event_get_coords ((const GdkEvent *) event, &event_x, &event_y) - && gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (interfaces_list), - event_x, event_y, - &path, &column, NULL, NULL)) { - GList *cols; - gint column_index; - - /* Get column index. */ - cols = gtk_tree_view_get_columns (GTK_TREE_VIEW (interfaces_list)); - column_index = g_list_index (cols, (gpointer) column); - g_list_free (cols); - - if (column_index == INTERFACES_COL_DEVICE) { - const gint *indices; - gint row_index; - const char *if_name; - char *cmd; - - /* Get the row index. */ - indices = gtk_tree_path_get_indices (path); - row_index = indices[0]; - - /* And the interface name. */ - if_name = all_interfaces[row_index]; - - /* Issue the ethtool command in the background. */ - if (asprintf (&cmd, "ethtool --identify '%s' 10 &", if_name) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - printf ("%s\n", cmd); - ignore_value (system (cmd)); - - free (cmd); - - ret = TRUE; /* We handled this event. */ - } - - gtk_tree_path_free (path); - } - } - - return ret; -} - -static void -set_from_ui_generic (char **all, char ***ret, GtkTreeView *list) -{ - GtkTreeModel *model; - GtkTreeIter iter; - gboolean b, v; - size_t i, j; - - if (all == NULL) { - guestfs_int_free_string_list (*ret); - *ret = NULL; - return; - } - - model = gtk_tree_view_get_model (list); - - guestfs_int_free_string_list (*ret); - *ret = malloc ((1 + guestfs_int_count_strings (all)) * sizeof (char *)); - if (*ret == NULL) - error (EXIT_FAILURE, errno, "malloc"); - i = j = 0; - - b = gtk_tree_model_get_iter_first (model, &iter); - while (b) { - gtk_tree_model_get (model, &iter, 0 /* CONVERT */, &v, -1); - if (v) { - assert (all[i] != NULL); - (*ret)[j++] = strdup (all[i]); - } - b = gtk_tree_model_iter_next (model, &iter); - ++i; - } - - (*ret)[j] = NULL; -} - -static void -set_disks_from_ui (struct config *config) -{ - set_from_ui_generic (all_disks, &config->disks, - GTK_TREE_VIEW (disks_list)); -} - -static void -set_removable_from_ui (struct config *config) -{ - set_from_ui_generic (all_removable, &config->removable, - GTK_TREE_VIEW (removable_list)); -} - -static void -set_interfaces_from_ui (struct config *config) -{ - set_from_ui_generic (all_interfaces, &config->interfaces, - GTK_TREE_VIEW (interfaces_list)); -} - -static void -set_network_map_from_ui (struct config *config) -{ - GtkTreeView *list; - GtkTreeModel *model; - GtkTreeIter iter; - gboolean b; - const char *s; - size_t i, j; - - if (all_interfaces == NULL) { - guestfs_int_free_string_list (config->network_map); - config->network_map = NULL; - return; - } - - list = GTK_TREE_VIEW (interfaces_list); - model = gtk_tree_view_get_model (list); - - guestfs_int_free_string_list (config->network_map); - config->network_map - malloc ((1 + guestfs_int_count_strings (all_interfaces)) - * sizeof (char *)); - if (config->network_map == NULL) - error (EXIT_FAILURE, errno, "malloc"); - i = j = 0; - - b = gtk_tree_model_get_iter_first (model, &iter); - while (b) { - gtk_tree_model_get (model, &iter, INTERFACES_COL_NETWORK, &s, -1); - if (s) { - assert (all_interfaces[i] != NULL); - if (asprintf (&config->network_map[j], "%s:%s", - all_interfaces[i], s) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - ++j; - } - b = gtk_tree_model_iter_next (model, &iter); - ++i; - } - - config->network_map[j] = NULL; -} - -/** - * The conversion dialog C<Back> button has been clicked. - */ -static void -conversion_back_clicked (GtkWidget *w, gpointer data) -{ - /* Switch to the connection dialog. */ - show_connection_dialog (); - - /* Better disable the Next button so the user is forced to - * do "Test connection" again. - */ - gtk_widget_set_sensitive (next_button, FALSE); -} - -static char *concat_warning (char *warning, const char *fs, ...) - __attribute__((format (printf,2,3))); - -static char * -concat_warning (char *warning, const char *fs, ...) -{ - va_list args; - char *msg; - size_t len, len2; - int r; - - if (warning == NULL) { - warning = strdup (""); - if (warning == NULL) - malloc_fail: - error (EXIT_FAILURE, errno, "malloc"); - } - - len = strlen (warning); - if (len > 0 && warning[len-1] != '\n' && fs[0] != '\n') { - warning = concat_warning (warning, "\n"); - len = strlen (warning); - } - - va_start (args, fs); - r = vasprintf (&msg, fs, args); - va_end (args); - if (r == -1) goto malloc_fail; - - len2 = strlen (msg); - warning = realloc (warning, len + len2 + 1); - if (warning == NULL) goto malloc_fail; - memcpy (&warning[len], msg, len2 + 1); - free (msg); - - return warning; -} - -/** - * Display a warning if the vCPUs or memory is outside the supported - * range (L<https://bugzilla.redhat.com/823758>). - */ -static void -vcpus_or_memory_check_callback (GtkWidget *w, gpointer data) -{ - int vcpus; - uint64_t memory; - CLEANUP_FREE char *warning = NULL; - - vcpus = get_vcpus_from_conv_dlg (); - memory = get_memory_from_conv_dlg (); - - if (vcpus > MAX_SUPPORTED_VCPUS) { - gtk_widget_show (vcpus_warning); - - warning = concat_warning (warning, - _("Number of virtual CPUs is larger than what is supported for KVM (max: %d)."), - MAX_SUPPORTED_VCPUS); - } - else - gtk_widget_hide (vcpus_warning); - - if (memory > MAX_SUPPORTED_MEMORY_MB * 1024 * 1024) { - gtk_widget_show (memory_warning); - - warning = concat_warning (warning, - _("Memory size is larger than what is supported for KVM (max: %" PRIu64 ")."), - MAX_SUPPORTED_MEMORY_MB); - } - else - gtk_widget_hide (memory_warning); - - if (warning != NULL) { - warning = concat_warning (warning, - _("If you ignore this warning, conversion can still succeed, but the guest may not work or may not be supported on the target.")); - gtk_label_set_text (GTK_LABEL (target_warning_label), warning); - } - else - gtk_label_set_text (GTK_LABEL (target_warning_label), ""); -} - -static int -get_vcpus_from_conv_dlg (void) -{ - const char *str; - int i; - - str = gtk_entry_get_text (GTK_ENTRY (vcpus_entry)); - if (sscanf (str, "%d", &i) == 1 && i > 0) - return i; - else - return 1; -} - -static uint64_t -get_memory_from_conv_dlg (void) -{ - const char *str; - uint64_t i; - - str = gtk_entry_get_text (GTK_ENTRY (memory_entry)); - if (sscanf (str, "%" SCNu64, &i) == 1 && i >= 256) - return i * 1024 * 1024; - else - return UINT64_C (1024) * 1024 * 1024; -} - -/*----------------------------------------------------------------------*/ -/* Running dialog. */ - -static gboolean set_log_dir (gpointer remote_dir); -static gboolean set_status (gpointer msg); -static gboolean add_v2v_output (gpointer msg); -static void *start_conversion_thread (void *data); -static gboolean conversion_error (gpointer user_data); -static gboolean conversion_finished (gpointer user_data); -static void cancel_conversion_dialog (GtkWidget *w, gpointer data); -#ifdef USE_POPOVERS -static void activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data); -#else -static void shutdown_button_clicked (GtkToolButton *w, gpointer data); -#endif -static void shutdown_clicked (GtkWidget *w, gpointer data); -static void reboot_clicked (GtkWidget *w, gpointer data); -static gboolean close_running_dialog (GtkWidget *w, GdkEvent *event, gpointer data); - -#ifdef USE_POPOVERS -static const GActionEntry shutdown_actions[] = { - { "shutdown", activate_action, NULL, NULL, NULL }, - { "reboot", activate_action, NULL, NULL, NULL }, -}; -#endif - -/** - * Create the running dialog. - * - * This creates the dialog, but it is not displayed. See - * C<show_running_dialog>. - */ -static void -create_running_dialog (void) -{ - size_t i; - static const char *tags[16] - { "black", "maroon", "green", "olive", "navy", "purple", "teal", "silver", - "gray", "red", "lime", "yellow", "blue", "fuchsia", "cyan", "white" }; - GtkTextBuffer *buf; -#ifdef USE_POPOVERS - GMenu *shutdown_menu; - GSimpleActionGroup *shutdown_group; -#else - GtkWidget *shutdown_menu; - GtkWidget *shutdown_menu_item; - GtkWidget *reboot_menu_item; -#endif - - run_dlg = gtk_dialog_new (); - gtk_window_set_title (GTK_WINDOW (run_dlg), getprogname ()); - gtk_window_set_resizable (GTK_WINDOW (run_dlg), FALSE); - - /* The main dialog area. */ - v2v_output_sw = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (v2v_output_sw), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_widget_set_size_request (v2v_output_sw, 700, 400); - - v2v_output = gtk_text_view_new (); - gtk_text_view_set_editable (GTK_TEXT_VIEW (v2v_output), FALSE); - gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (v2v_output), GTK_WRAP_CHAR); - - buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (v2v_output)); - for (i = 0; i < 16; ++i) { - CLEANUP_FREE char *tag_name; - - if (asprintf (&tag_name, "tag_%s", tags[i]) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - v2v_output_tags[i] - gtk_text_buffer_create_tag (buf, tag_name, "foreground", tags[i], NULL); - } - -#if GTK_CHECK_VERSION(3,16,0) /* gtk >= 3.16 */ - /* XXX This only sets the "CSS" style. It's not clear how to set - * the particular font. However (by accident) this does at least - * set the widget to use a monospace font. - */ - GtkStyleContext *context = gtk_widget_get_style_context (v2v_output); - gtk_style_context_add_class (context, "monospace"); -#else - PangoFontDescription *font; - font = pango_font_description_from_string ("Monospace 11"); -#if GTK_CHECK_VERSION(3,0,0) /* gtk >= 3 */ - gtk_widget_override_font (v2v_output, font); -#else - gtk_widget_modify_font (v2v_output, font); -#endif - pango_font_description_free (font); -#endif - - log_label = gtk_label_new (NULL); - set_alignment (log_label, 0., 0.5); - set_padding (log_label, 10, 10); - set_log_dir (NULL); - status_label = gtk_label_new (NULL); - set_alignment (status_label, 0., 0.5); - set_padding (status_label, 10, 10); - - gtk_container_add (GTK_CONTAINER (v2v_output_sw), v2v_output); - - gtk_box_pack_start - (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (run_dlg))), - v2v_output_sw, TRUE, TRUE, 0); - gtk_box_pack_start - (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (run_dlg))), - log_label, TRUE, TRUE, 0); - gtk_box_pack_start - (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (run_dlg))), - status_label, TRUE, TRUE, 0); - - /* Shutdown popup menu. */ -#ifdef USE_POPOVERS - shutdown_menu = g_menu_new (); - g_menu_append (shutdown_menu, _("_Shutdown"), "shutdown.shutdown"); - g_menu_append (shutdown_menu, _("_Reboot"), "shutdown.reboot"); - - shutdown_group = g_simple_action_group_new (); - g_action_map_add_action_entries (G_ACTION_MAP (shutdown_group), - shutdown_actions, - G_N_ELEMENTS (shutdown_actions), NULL); -#else - shutdown_menu = gtk_menu_new (); - shutdown_menu_item = gtk_menu_item_new_with_mnemonic (_("_Shutdown")); - gtk_menu_shell_append (GTK_MENU_SHELL (shutdown_menu), shutdown_menu_item); - gtk_widget_show (shutdown_menu_item); - reboot_menu_item = gtk_menu_item_new_with_mnemonic (_("_Reboot")); - gtk_menu_shell_append (GTK_MENU_SHELL (shutdown_menu), reboot_menu_item); - gtk_widget_show (reboot_menu_item); -#endif - - /* Buttons. */ - gtk_dialog_add_buttons (GTK_DIALOG (run_dlg), - _("_Cancel conversion ..."), 1, - NULL); - cancel_button = gtk_dialog_get_widget_for_response (GTK_DIALOG (run_dlg), 1); - gtk_widget_set_sensitive (cancel_button, FALSE); -#ifdef USE_POPOVERS - shutdown_button = gtk_menu_button_new (); - gtk_button_set_use_underline (GTK_BUTTON (shutdown_button), TRUE); - gtk_button_set_label (GTK_BUTTON (shutdown_button), _("_Shutdown ...")); - gtk_button_set_always_show_image (GTK_BUTTON (shutdown_button), TRUE); - gtk_widget_insert_action_group (shutdown_button, "shutdown", - G_ACTION_GROUP (shutdown_group)); - gtk_menu_button_set_use_popover (GTK_MENU_BUTTON (shutdown_button), TRUE); - gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (shutdown_button), - G_MENU_MODEL (shutdown_menu)); -#else - shutdown_button = GTK_WIDGET (gtk_menu_tool_button_new (NULL, - _("_Shutdown ..."))); - gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (shutdown_button), TRUE); - gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (shutdown_button), - shutdown_menu); -#endif - gtk_widget_set_sensitive (shutdown_button, FALSE); - gtk_dialog_add_action_widget (GTK_DIALOG (run_dlg), shutdown_button, 2); - - /* Signals. */ - g_signal_connect_swapped (G_OBJECT (run_dlg), "delete_event", - G_CALLBACK (close_running_dialog), NULL); - g_signal_connect_swapped (G_OBJECT (run_dlg), "destroy", - G_CALLBACK (gtk_main_quit), NULL); - g_signal_connect (G_OBJECT (cancel_button), "clicked", - G_CALLBACK (cancel_conversion_dialog), NULL); -#ifndef USE_POPOVERS - g_signal_connect (G_OBJECT (shutdown_button), "clicked", - G_CALLBACK (shutdown_button_clicked), shutdown_menu); - g_signal_connect (G_OBJECT (shutdown_menu_item), "activate", - G_CALLBACK (shutdown_clicked), NULL); - g_signal_connect (G_OBJECT (reboot_menu_item), "activate", - G_CALLBACK (reboot_clicked), NULL); -#endif -} - -/** - * Hide all other dialogs and show the running dialog. - */ -static void -show_running_dialog (void) -{ - /* Hide the other dialogs. */ - gtk_widget_hide (conn_dlg); - gtk_widget_hide (conv_dlg); - - /* Show the running dialog. */ - gtk_widget_show_all (run_dlg); - gtk_widget_set_sensitive (cancel_button, TRUE); - if (is_iso_environment) - gtk_widget_set_sensitive (shutdown_button, FALSE); -} - -/** - * Display the remote log directory in the running dialog. - * - * If this isn't called from the main thread, then you must only - * call it via an idle task (C<g_idle_add>). - * - * B<NB:> This frees the remote_dir (C<user_data> pointer) which was - * strdup'd in C<notify_ui_callback>. - */ -static gboolean -set_log_dir (gpointer user_data) -{ - CLEANUP_FREE const char *remote_dir = user_data; - CLEANUP_FREE char *msg; - - if (asprintf (&msg, - _("Debug information and log files " - "are saved to this directory " - "on the conversion server:\n" - "%s"), - remote_dir ? remote_dir : "") == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - gtk_label_set_text (GTK_LABEL (log_label), msg); - - return FALSE; -} - -/** - * Display the conversion status in the running dialog. - * - * If this isn't called from the main thread, then you must only - * call it via an idle task (C<g_idle_add>). - * - * B<NB:> This frees the message (C<user_data> pointer) which was - * strdup'd in C<notify_ui_callback>. - */ -static gboolean -set_status (gpointer user_data) -{ - CLEANUP_FREE const char *msg = user_data; - - gtk_label_set_text (GTK_LABEL (status_label), msg); - - return FALSE; -} - -/** - * Append output from the virt-v2v process to the buffer, and scroll - * to ensure it is visible. - * - * This function is able to parse ANSI colour sequences and more. - * - * If this isn't called from the main thread, then you must only - * call it via an idle task (C<g_idle_add>). - * - * B<NB:> This frees the message (C<user_data> pointer) which was - * strdup'd in C<notify_ui_callback>. - */ -static gboolean -add_v2v_output (gpointer user_data) -{ - CLEANUP_FREE const char *msg = user_data; - const char *p; - static size_t linelen = 0; - static enum { - state_normal, - state_escape1, /* seen ESC, expecting [ */ - state_escape2, /* seen ESC [, expecting 0 or 1 */ - state_escape3, /* seen ESC [ 0/1, expecting ; or m */ - state_escape4, /* seen ESC [ 0/1 ;, expecting 3 */ - state_escape5, /* seen ESC [ 0/1 ; 3, expecting 1/2/4/5 */ - state_escape6, /* seen ESC [ 0/1 ; 3 1/2/5/5, expecting m */ - state_cr, /* seen CR */ - state_truncating, /* truncating line until next \n */ - } state = state_normal; - static int colour = 0; - static GtkTextTag *tag = NULL; - GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (v2v_output)); - GtkTextIter iter, iter2; - const char *dots = " [...]"; - - for (p = msg; *p != '\0'; ++p) { - char c = *p; - - switch (state) { - case state_normal: - if (c == '\r') /* Start of possible CRLF sequence. */ - state = state_cr; - else if (c == '\x1b') { /* Start of an escape sequence. */ - state = state_escape1; - colour = 0; - } - else if (c != '\n' && linelen >= 256) { - /* Gtk2 (in ~ Fedora 23) has a regression where it takes much - * longer to display long lines, to the point where the - * virt-p2v UI would still be slowly displaying kernel modules - * while the conversion had finished. For this reason, - * arbitrarily truncate very long lines. - */ - gtk_text_buffer_get_end_iter (buf, &iter); - gtk_text_buffer_insert_with_tags (buf, &iter, - dots, strlen (dots), tag, NULL); - state = state_truncating; - colour = 0; - tag = NULL; - } - else { /* Treat everything else as a normal char. */ - if (c != '\n') linelen++; else linelen = 0; - gtk_text_buffer_get_end_iter (buf, &iter); - gtk_text_buffer_insert_with_tags (buf, &iter, &c, 1, tag, NULL); - } - break; - - case state_escape1: - if (c == '[') - state = state_escape2; - else - state = state_normal; - break; - - case state_escape2: - if (c == '0') - state = state_escape3; - else if (c == '1') { - state = state_escape3; - colour += 8; - } - else - state = state_normal; - break; - - case state_escape3: - if (c == ';') - state = state_escape4; - else if (c == 'm') { - tag = NULL; /* restore text colour */ - state = state_normal; - } - else - state = state_normal; - break; - - case state_escape4: - if (c == '3') - state = state_escape5; - else - state = state_normal; - break; - - case state_escape5: - if (c >= '0' && c <= '7') { - state = state_escape6; - colour += c - '0'; - } - else - state = state_normal; - break; - - case state_escape6: - if (c == 'm') { - assert (colour >= 0 && colour <= 15); - tag = v2v_output_tags[colour]; /* set colour tag */ - } - state = state_normal; - break; - - case state_cr: - if (c == '\n') - /* Process CRLF as single a newline character. */ - p--; - else { /* Delete current (== last) line. */ - linelen = 0; - gtk_text_buffer_get_end_iter (buf, &iter); - iter2 = iter; - gtk_text_iter_set_line_offset (&iter, 0); - /* Delete from iter..iter2 */ - gtk_text_buffer_delete (buf, &iter, &iter2); - } - state = state_normal; - break; - - case state_truncating: - if (c == '\n') { - p--; - state = state_normal; - } - break; - } /* switch (state) */ - } /* for */ - - /* Scroll to the end of the buffer. */ - gtk_text_buffer_get_end_iter (buf, &iter); - gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (v2v_output), &iter, - 0, FALSE, 0., 1.); - - return FALSE; -} - -/** - * Callback when the C<Start conversion> button is clicked. - */ -static void -start_conversion_clicked (GtkWidget *w, gpointer data) -{ - struct config *config = data; - const char *str; - char *str2; - GtkWidget *dlg; - struct config *copy; - int err; - pthread_t tid; - pthread_attr_t attr; - - /* Unpack dialog fields and check them. */ - free (config->guestname); - config->guestname = strdup (gtk_entry_get_text (GTK_ENTRY (guestname_entry))); - - if (STREQ (config->guestname, "")) { - dlg = gtk_message_dialog_new (GTK_WINDOW (conv_dlg), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("The guest \"Name\" field is empty.")); - gtk_window_set_title (GTK_WINDOW (dlg), _("Error")); - gtk_dialog_run (GTK_DIALOG (dlg)); - gtk_widget_destroy (dlg); - gtk_widget_grab_focus (guestname_entry); - return; - } - - config->vcpus = get_vcpus_from_conv_dlg (); - config->memory = get_memory_from_conv_dlg (); - - /* Get the list of disks to be converted. */ - set_disks_from_ui (config); - - /* The list of disks must be non-empty. */ - if (config->disks == NULL || guestfs_int_count_strings (config->disks) == 0) { - dlg = gtk_message_dialog_new (GTK_WINDOW (conv_dlg), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("No disks were selected for conversion.\n" - "At least one fixed hard disk must be selected.\n")); - gtk_window_set_title (GTK_WINDOW (dlg), _("Error")); - gtk_dialog_run (GTK_DIALOG (dlg)); - gtk_widget_destroy (dlg); - return; - } - - /* List of removable media and network interfaces. */ - set_removable_from_ui (config); - set_interfaces_from_ui (config); - set_network_map_from_ui (config); - - /* Output selection. */ - free (config->output.type); - config->output.type - gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (o_combo)); - - config->output.allocation = OUTPUT_ALLOCATION_NONE; - str2 = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (oa_combo)); - if (str2) { - if (STREQ (str2, "sparse")) - config->output.allocation = OUTPUT_ALLOCATION_SPARSE; - else if (STREQ (str2, "preallocated")) - config->output.allocation = OUTPUT_ALLOCATION_PREALLOCATED; - free (str2); - } - - free (config->output.connection); - str = gtk_entry_get_text (GTK_ENTRY (oc_entry)); - if (str && STRNEQ (str, "")) - config->output.connection = strdup (str); - else - config->output.connection = NULL; - - free (config->output.format); - str = gtk_entry_get_text (GTK_ENTRY (of_entry)); - if (str && STRNEQ (str, "")) - config->output.format = strdup (str); - else - config->output.format = NULL; - - free (config->output.storage); - str = gtk_entry_get_text (GTK_ENTRY (os_entry)); - if (str && STRNEQ (str, "")) - config->output.storage = strdup (str); - else - config->output.storage = NULL; - - /* Display the UI for conversion. */ - show_running_dialog (); - - /* Do the conversion, in a background thread. */ - - /* Give the conversion (background) thread its own copy of the - * config in case we update the config in the main thread. - */ - copy = copy_config (config); - - pthread_attr_init (&attr); - pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); - err = pthread_create (&tid, &attr, start_conversion_thread, copy); - if (err != 0) - error (EXIT_FAILURE, err, "pthread_create"); - pthread_attr_destroy (&attr); -} - -/** - * This is the background thread which performs the conversion. - */ -static void * -start_conversion_thread (void *data) -{ - struct config *copy = data; - int r; - - r = start_conversion (copy, notify_ui_callback); - free_config (copy); - - if (r == -1) - g_idle_add (conversion_error, NULL); - else - g_idle_add (conversion_finished, NULL); - - /* Thread is detached anyway, so no one is waiting for the status. */ - return NULL; -} - -/** - * Idle task called from C<start_conversion_thread> (but run on the - * main thread) when there was an error during the conversion. - */ -static gboolean -conversion_error (gpointer user_data) -{ - const char *err = get_conversion_error (); - GtkWidget *dlg; - - dlg = gtk_message_dialog_new (GTK_WINDOW (run_dlg), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("Conversion failed: %s"), err); - gtk_window_set_title (GTK_WINDOW (dlg), _("Conversion failed")); - gtk_dialog_run (GTK_DIALOG (dlg)); - gtk_widget_destroy (dlg); - - /* Disable the cancel button. */ - gtk_widget_set_sensitive (cancel_button, FALSE); - - /* Enable the shutdown button. */ - if (is_iso_environment) - gtk_widget_set_sensitive (shutdown_button, TRUE); - - return FALSE; -} - -/** - * Idle task called from C<start_conversion_thread> (but run on the - * main thread) when the conversion completed without errors. - */ -static gboolean -conversion_finished (gpointer user_data) -{ - GtkWidget *dlg; - - dlg = gtk_message_dialog_new (GTK_WINDOW (run_dlg), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_OK, - _("The conversion was successful.")); - gtk_window_set_title (GTK_WINDOW (dlg), _("Conversion was successful")); - gtk_dialog_run (GTK_DIALOG (dlg)); - gtk_widget_destroy (dlg); - - /* Disable the cancel button. */ - gtk_widget_set_sensitive (cancel_button, FALSE); - - /* Enable the shutdown button. */ - if (is_iso_environment) - gtk_widget_set_sensitive (shutdown_button, TRUE); - - return FALSE; -} - -/** - * This is called from F<conversion.c>:C<start_conversion> - * when there is a status change or a log message. - */ -static void -notify_ui_callback (int type, const char *data) -{ - /* Because we call the functions as idle callbacks which run - * in the main thread some time later, we must duplicate the - * 'data' parameter (which is always a \0-terminated string). - * - * This is freed by the idle task function. - */ - char *copy = strdup (data); - - switch (type) { - case NOTIFY_LOG_DIR: - g_idle_add (set_log_dir, (gpointer) copy); - break; - - case NOTIFY_REMOTE_MESSAGE: - g_idle_add (add_v2v_output, (gpointer) copy); - break; - - case NOTIFY_STATUS: - g_idle_add (set_status, (gpointer) copy); - break; - - default: - fprintf (stderr, - "%s: unknown message during conversion: type=%d data=%s\n", - getprogname (), type, data); - free (copy); - } -} - -static gboolean -close_running_dialog (GtkWidget *w, GdkEvent *event, gpointer data) -{ - /* This function is called if the user tries to close the running - * dialog. This is the same as cancelling the conversion. - */ - if (conversion_is_running ()) { - cancel_conversion (); - return TRUE; - } - else - /* Conversion is not running, so this will delete the dialog. */ - return FALSE; -} - -/** - * This is called when the user clicks on the "Cancel conversion" - * button. Since conversions can run for a long time, and cancelling - * the conversion is non-recoverable, this function displays a - * confirmation dialog before cancelling the conversion. - */ -static void -cancel_conversion_dialog (GtkWidget *w, gpointer data) -{ - GtkWidget *dlg; - - if (!conversion_is_running ()) - return; - - dlg = gtk_message_dialog_new (GTK_WINDOW (run_dlg), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_YES_NO, - _("Really cancel the conversion? " - "To convert this machine you will need to " - "re-run the conversion from the beginning.")); - gtk_window_set_title (GTK_WINDOW (dlg), _("Cancel the conversion")); - if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_YES) - /* This makes start_conversion return an error (eventually). */ - cancel_conversion (); - - gtk_widget_destroy (dlg); -} - -#ifdef USE_POPOVERS -static void -activate_action (GSimpleAction *action, GVariant *parameter, gpointer user_data) -{ - const char *action_name = g_action_get_name (G_ACTION (action)); - if (STREQ (action_name, "shutdown")) - shutdown_clicked (NULL, user_data); - else if (STREQ (action_name, "reboot")) - reboot_clicked (NULL, user_data); -} -#else -static void -shutdown_button_clicked (GtkToolButton *w, gpointer data) -{ - GtkMenu *menu = data; - - gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 1, - gtk_get_current_event_time ()); -} -#endif - -static void -shutdown_clicked (GtkWidget *w, gpointer data) -{ - if (!is_iso_environment) - return; - - sync (); - sleep (2); - ignore_value (system ("/sbin/poweroff")); -} - -static void -reboot_clicked (GtkWidget *w, gpointer data) -{ - if (!is_iso_environment) - return; - - sync (); - sleep (2); - ignore_value (system ("/sbin/reboot")); -} diff --git a/p2v/inhibit.c b/p2v/inhibit.c deleted file mode 100644 index 7615d65f9..000000000 --- a/p2v/inhibit.c +++ /dev/null @@ -1,154 +0,0 @@ -/* virt-p2v - * Copyright (C) 2016 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 file is used to inhibit power saving, sleep, suspend etc during - * the conversion. - * - * The method it uses is to send a D-Bus message to logind, as - * described here: - * - * https://www.freedesktop.org/wiki/Software/systemd/inhibit/ - * - * If virt-p2v is compiled without D-Bus support then this does nothing. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#if defined(HAVE_DBUS) -#include <dbus/dbus.h> -#endif - -#include "p2v.h" - -/** - * Inhibit all forms of power saving. A file descriptor is returned, - * and when the file descriptor is closed the inhibit is stopped. - * - * If the function returns C<-1> then C<Inhibit> operation could not - * be performed (eg. if we are compiled without D-Bus support, or there - * is some error contacting logind). This is not usually fatal from - * the point of view of the caller, conversion can continue. - */ -int -inhibit_power_saving (void) -{ -#if defined(HAVE_DBUS) && defined(DBUS_TYPE_UNIX_FD) - DBusError err; - DBusConnection *conn = NULL; - DBusMessage *msg = NULL; - DBusMessageIter args; - DBusPendingCall *pending = NULL; - const char *what = "shutdown:sleep:idle"; - const char *who = "virt-p2v"; - const char *why = "virt-p2v conversion is running"; - const char *mode = "block"; - int fd = -1; - - dbus_error_init (&err); - - conn = dbus_bus_get (DBUS_BUS_SYSTEM, &err); - if (dbus_error_is_set (&err)) { - fprintf (stderr, "inhibit_power_saving: dbus: cannot connect to system bus: %s\n", err.message); - goto out; - } - if (conn == NULL) - goto out; - - msg = dbus_message_new_method_call ("org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "Inhibit"); - if (msg == NULL) { - fprintf (stderr, "inhibit_power_saving: dbus: cannot create message\n"); - goto out; - } - - dbus_message_iter_init_append (msg, &args); - if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &what) || - !dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &who) || - !dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &why) || - !dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &mode)) { - fprintf (stderr, "inhibit_power_saving: dbus: cannot add message arguments\n"); - goto out; - } - - if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) { - fprintf (stderr, "inhibit_power_saving: dbus: cannot send Inhibit message to logind\n"); - goto out; - } - if (pending == NULL) - goto out; - dbus_connection_flush (conn); - - dbus_message_unref (msg); - msg = NULL; - - dbus_pending_call_block (pending); - msg = dbus_pending_call_steal_reply (pending); - if (msg == NULL) { - fprintf (stderr, "inhibit_power_saving: dbus: could not read message reply\n"); - goto out; - } - - dbus_pending_call_unref (pending); - pending = NULL; - - if (!dbus_message_iter_init (msg, &args)) { - fprintf (stderr, "inhibit_power_saving: dbus: message reply has no return value\n"); - goto out; - } - - if (dbus_message_iter_get_arg_type (&args) != DBUS_TYPE_UNIX_FD) { - fprintf (stderr, "inhibit_power_saving: dbus: message reply is not a file descriptor\n"); - goto out; - } - - dbus_message_iter_get_basic (&args, &fd); - -#ifdef DEBUG_STDERR - fprintf (stderr, "inhibit_power_saving: dbus: Inhibit() call returned file descriptor %d\n", fd); -#endif - -out: - if (pending != NULL) - dbus_pending_call_unref (pending); - if (msg != NULL) - dbus_message_unref (msg); - - /* This is the system bus connection, so unref-ing it does not - * actually close it. - */ - if (conn != NULL) - dbus_connection_unref (conn); - - dbus_error_free (&err); - - return fd; - -#else /* !dbus */ -#ifdef DEBUG_STDERR - fprintf (stderr, "warning: virt-p2v compiled without D-Bus support.\n"); -#endif - return -1; -#endif -} diff --git a/p2v/issue b/p2v/issue deleted file mode 100644 index 9896b6b75..000000000 --- a/p2v/issue +++ /dev/null @@ -1,16 +0,0 @@ -virt-p2v - Convert a physical machine to use KVM. - -*** -The root password is "p2v" (without quotes). - -To see the status of virt-p2v, do: - - systemctl status p2v -l - -Virt-p2v may take some time to start up. If virt-p2v is not running -after a few minutes, you can start it by typing: - - launch-virt-p2v - -*** - diff --git a/p2v/kernel-cmdline.c b/p2v/kernel-cmdline.c deleted file mode 100644 index c53b9783b..000000000 --- a/p2v/kernel-cmdline.c +++ /dev/null @@ -1,196 +0,0 @@ -/* virt-p2v - * Copyright (C) 2015 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. - */ - -/** - * Mini library to read and parse C</proc/cmdline>. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <error.h> - -#include "getprogname.h" - -#include "p2v.h" - -static void -add_null (char ***argv, size_t *lenp) -{ - (*lenp)++; - *argv = realloc (*argv, *lenp * sizeof (char *)); - if (*argv == NULL) - error (EXIT_FAILURE, errno, "realloc"); - (*argv)[(*lenp)-1] = NULL; -} - -static void -add_string (char ***argv, size_t *lenp, const char *str, size_t len) -{ - add_null (argv, lenp); - (*argv)[(*lenp)-1] = strndup (str, len); - if ((*argv)[(*lenp)-1] == NULL) - error (EXIT_FAILURE, errno, "strndup"); -} - -/** - * Read and parse C</proc/cmdline>. - * - * We only support double quoting, consistent with the Linux - * documentation. - * L<https://www.kernel.org/doc/Documentation/kernel-parameters.txt> - * - * systemd supports single and double quoting and single character - * escaping, but we don't support all that. - * - * Returns a list of key, value pairs, terminated by C<NULL>. - */ -char ** -parse_cmdline_string (const char *cmdline) -{ - char **ret = NULL; - size_t len = 0; - const char *p, *key = NULL, *value = NULL; - enum { - KEY_START = 0, - KEY, - VALUE_START, - VALUE, - VALUE_QUOTED - } state = 0; - - for (p = cmdline; *p; p++) { - switch (state) { - case KEY_START: /* looking for the start of a key */ - if (*p == ' ') continue; - key = p; - state = KEY; - break; - - case KEY: /* reading key */ - if (*p == ' ') { - add_string (&ret, &len, key, p-key); - add_string (&ret, &len, "", 0); - state = KEY_START; - } - else if (*p == '=') { - add_string (&ret, &len, key, p-key); - state = VALUE_START; - } - break; - - case VALUE_START: /* looking for the start of a value */ - if (*p == ' ') { - add_string (&ret, &len, "", 0); - state = KEY_START; - } - else if (*p == '"') { - value = p+1; - state = VALUE_QUOTED; - } - else { - value = p; - state = VALUE; - } - break; - - case VALUE: /* reading unquoted value */ - if (*p == ' ') { - add_string (&ret, &len, value, p-value); - state = KEY_START; - } - break; - - case VALUE_QUOTED: /* reading quoted value */ - if (*p == '"') { - add_string (&ret, &len, value, p-value); - state = KEY_START; - } - break; - } - } - - switch (state) { - case KEY_START: break; - case KEY: /* key followed by end of string */ - add_string (&ret, &len, key, p-key); - add_string (&ret, &len, "", 0); - break; - case VALUE_START: /* key= followed by end of string */ - add_string (&ret, &len, "", 0); - break; - case VALUE: /* key=value followed by end of string */ - add_string (&ret, &len, value, p-value); - break; - case VALUE_QUOTED: /* unterminated key="value" */ - fprintf (stderr, "%s: warning: unterminated quoted string on kernel command line\n", - getprogname ()); - add_string (&ret, &len, value, p-value); - } - - add_null (&ret, &len); - - return ret; -} - -char ** -parse_proc_cmdline (void) -{ - CLEANUP_FCLOSE FILE *fp = NULL; - CLEANUP_FREE char *cmdline = NULL; - size_t len = 0; - - fp = fopen ("/proc/cmdline", "re"); - if (fp == NULL) { - perror ("/proc/cmdline"); - return NULL; - } - - if (getline (&cmdline, &len, fp) == -1) { - perror ("getline"); - return NULL; - } - - /* 'len' is not the length of the string, but the length of the - * buffer. We need to chomp the string. - */ - len = strlen (cmdline); - - if (len >= 1 && cmdline[len-1] == '\n') - cmdline[len-1] = '\0'; - - return parse_cmdline_string (cmdline); -} - -const char * -get_cmdline_key (char **argv, const char *key) -{ - size_t i; - - for (i = 0; argv[i] != NULL; i += 2) { - if (STREQ (argv[i], key)) - return argv[i+1]; - } - - /* Not found. */ - return NULL; -} diff --git a/p2v/kernel.c b/p2v/kernel.c deleted file mode 100644 index e9a0630ae..000000000 --- a/p2v/kernel.c +++ /dev/null @@ -1,158 +0,0 @@ -/* virt-p2v - * Copyright (C) 2009-2019 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. - */ - -/** - * Kernel-driven, non-interactive configuration of virt-p2v. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <inttypes.h> -#include <unistd.h> -#include <errno.h> -#include <error.h> -#include <assert.h> -#include <locale.h> -#include <libintl.h> -#include <sys/types.h> -#include <sys/wait.h> - -#include "getprogname.h" - -#include "p2v.h" - -static void notify_ui_callback (int type, const char *data); -static void run_command (const char *stage, const char *command); - -/* Perform conversion using the kernel method. */ -void -kernel_conversion (struct config *config, char **cmdline, int cmdline_source) -{ - const char *p; - - /* Pre-conversion command. */ - p = get_cmdline_key (cmdline, "p2v.pre"); - if (p) - run_command ("p2v.pre", p); - - /* Connect to and interrogate virt-v2v on the conversion server. */ - p = get_cmdline_key (cmdline, "p2v.skip_test_connection"); - if (!p) { - wait_network_online (config); - if (test_connection (config) == -1) { - const char *err = get_ssh_error (); - - error (EXIT_FAILURE, 0, - "error opening control connection to %s:%d: %s", - config->remote.server, config->remote.port, err); - } - } - - /* Some disks must have been specified for conversion. */ - if (config->disks == NULL || guestfs_int_count_strings (config->disks) == 0) - error (EXIT_FAILURE, 0, - "no non-removable disks were discovered on this machine.\n" - "virt-p2v looked in /sys/block and in p2v.disks on the kernel command line.\n" - "This is a fatal error and virt-p2v cannot continue."); - - /* Perform the conversion in text mode. */ - if (start_conversion (config, notify_ui_callback) == -1) { - const char *err = get_conversion_error (); - - fprintf (stderr, "%s: error during conversion: %s\n", - getprogname (), err); - - p = get_cmdline_key (cmdline, "p2v.fail"); - if (p) - run_command ("p2v.fail", p); - - exit (EXIT_FAILURE); - } - - ansi_green (stdout); - printf ("Conversion finished successfully."); - ansi_restore (stdout); - putchar ('\n'); - - p = get_cmdline_key (cmdline, "p2v.post"); - if (!p) { - if (geteuid () == 0 && cmdline_source == CMDLINE_SOURCE_PROC_CMDLINE) - p = "poweroff"; - } - if (p) - run_command ("p2v.post", p); -} - -static void -notify_ui_callback (int type, const char *data) -{ - switch (type) { - case NOTIFY_LOG_DIR: - ansi_magenta (stdout); - printf ("%s: remote log directory location: ", getprogname ()); - ansi_red (stdout); - fputs (data, stdout); - ansi_restore (stdout); - putchar ('\n'); - break; - - case NOTIFY_REMOTE_MESSAGE: - printf ("%s", data); - break; - - case NOTIFY_STATUS: - ansi_magenta (stdout); - printf ("%s: %s", getprogname (), data); - ansi_restore (stdout); - putchar ('\n'); - break; - - default: - ansi_red (stdout); - printf ("%s: unknown message during conversion: type=%d data=%s", - getprogname (), type, data); - ansi_restore (stdout); - putchar ('\n'); - } - - fflush (stdout); -} - -static void -run_command (const char *stage, const char *command) -{ - int r; - - if (STREQ (command, "")) - return; - -#if DEBUG_STDERR - fprintf (stderr, "%s\n", command); - fflush (stderr); -#endif - - r = system (command); - if (r == -1) - error (EXIT_FAILURE, errno, "system: %s", command); - if ((WIFEXITED (r) && WEXITSTATUS (r) != 0) || !WIFEXITED (r)) - error (EXIT_FAILURE, 0, - "%s: unexpected failure of external command", stage); -} diff --git a/p2v/kiwi-config.sh b/p2v/kiwi-config.sh deleted file mode 100755 index b24fd3bad..000000000 --- a/p2v/kiwi-config.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash -#===============-# FILE : config.sh -#---------------- -# PROJECT : OpenSuSE KIWI Image System -# COPYRIGHT : (c) 2006 SUSE LINUX Products GmbH. All rights reserved -# : -# AUTHOR : Marcus Schaefer <ms@suse.de> -#=====================================-# Functions... -#-------------------------------------- -test -f /.kconfig && . /.kconfig -test -f /.profile && . /.profile - -#=====================================-# Greeting... -#-------------------------------------- -echo "Configure image: [$kiwi_iname]..." - -#=====================================-# Mount system filesystems -#-------------------------------------- -baseMount - -#=====================================-# Setup baseproduct link -#-------------------------------------- -suseSetupProduct - -#=====================================-# Add missing gpg keys to rpm -#-------------------------------------- -suseImportBuildKey - -#=====================================-# Activate services -#-------------------------------------- -suseInsertService p2v - -#=====================================-# Setup default target, multi-user -#-------------------------------------- -baseSetRunlevel 3 - -#=========================================-# remove package docs -#------------------------------------------ -rm -rf /usr/share/doc/packages/* -rm -rf /usr/share/doc/manual/* -rm -rf /opt/kde* - -# Update the default getty target to login automatically as root without -# prompting for a password -sed -i 's/^ExecStart=\(.*\)/ExecStart=\1 -a root/' \ - /usr/lib/systemd/system/getty@.service - -# Reserve tty1 as a getty so we can document it clearly -echo ReserveVT=1 >> /etc/systemd/logind.conf - -sed -i 's/^ROOT_USES_LANG=.*$/ROOT_USES_LANG="yes"/' \ - /etc/sysconfig/language - -#=====================================-# SuSEconfig -#-------------------------------------- -suseConfig - -#=====================================-# Umount kernel filesystems -#-------------------------------------- -baseCleanMount - -exit 0 diff --git a/p2v/kiwi-config.xml.in b/p2v/kiwi-config.xml.in deleted file mode 100644 index 680076b20..000000000 --- a/p2v/kiwi-config.xml.in +++ /dev/null @@ -1,92 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<image schemaversion="6.2" name="p2v-__KIWI_BOOT__" displayname="p2v___PACKAGE_VERSION_____KIWI_BOOT__"> - <description type="system"> - <author>Marcus Schäfer</author> - <contact>ms@suse.com</contact> - <specification>P2V __PACKAGE_VERSION__</specification> - </description> - <profiles> - <profile name="vmxFlavour" description="VMX with default kernel" import="true"/> - <profile name="netboot" description="compressed rootfs image for pxe"/> - </profiles> - <preferences> - <type image="iso" primary="true" boot="isoboot/suse-__KIWI_BOOT__" flags="overlay" hybrid="true" firmware="uefi" kernelcmdline="splash"/> - <version>__PACKAGE_VERSION__</version> - <packagemanager>zypper</packagemanager> - <locale>en_US</locale> - <keytable>us.map.gz</keytable> - <hwclock>utc</hwclock> - <bootloader-theme>__BRANDING__</bootloader-theme> - <bootsplash-theme>__BRANDING__</bootsplash-theme> - <rpm-excludedocs>true</rpm-excludedocs> - <rpm-check-signatures>false</rpm-check-signatures> - </preferences> - <preferences profiles="netboot"> - <type image="pxe" filesystem="overlayfs" boot="netboot/suse-__KIWI_BOOT__"> - <pxedeploy server="192.168.100.2" blocksize="4096"> - <partitions device="/dev/sda"> - <partition type="swap" number="1" size="5"/> - <partition type="L" number="2" size="image" mountpoint="/" target="true"/> - <partition type="L" number="3" target="false"/> - </partitions> - <union ro="/dev/sda2" rw="/dev/sda3" type="overlayfs"/> - </pxedeploy> - </type> - </preferences> - <preferences profiles="vmxFlavour"> - <type image="vmx" filesystem="ext3" boot="vmxboot/suse-__KIWI_BOOT__" format="vmdk" bootloader="grub2" firmware="uefi" kernelcmdline="splash" bootpartition="false"> - <systemdisk name="systemVG"/> - <machine memory="512" guestOS="suse" HWversion="4"> - <vmdisk id="0" controller="ide"/> - <vmnic driver="e1000" interface="0" mode="bridged"/> - </machine> - </type> - </preferences> - <users group="root"> - <user password="p2v" pwdformat="plain" home="/root" name="root"/> - </users> - <!--__REPOS__--> - <packages type="image" patternType="onlyRequired"> - <package name="__BASE_PATTERN__"/> - <package name="plymouth-branding-__BRANDING__" bootinclude="true"/> - <package name="grub2-branding-__BRANDING__" bootinclude="true"/> - <package name="iputils"/> - <package name="grub2"/> - <package name="grub2-x86_64-efi"/> - <package name="syslinux"/> - <package name="lvm2"/> - <package name="plymouth"/> - <package name="fontconfig"/> - <package name="fonts-config"/> - <package name="tar"/> - <package name="systemd"/> - <package name="systemd-sysvinit"/> - <package name="dracut"/> - <package name="wicked"/> - <package name="iproute2"/> - <package name="sudo"/> - <package name="dhcp-client"/> - <package name="which"/> - <!-- virt-p2v dependencies from dependencies.suse --> -<!--__DEPENDENCIES__--> - </packages> - <packages type="iso"> - <package name="gfxboot-branding-__BRANDING__" bootinclude="true" bootdelete="true"/> - </packages> - <packages type="image" profiles="vmxFlavour"> - <package name="kernel-default" replaces="kernel-xen"/> - <package name="kernel-default" replaces="xen-kmp-default"/> - <package name="kernel-default" replaces="xen-libs"/> - <package name="kernel-default" replaces="xen-tools"/> - <package name="kernel-default" replaces="xen"/> - <package name="gfxboot-branding-__BRANDING__" bootinclude="true" bootdelete="true"/> - </packages> - <packages type="bootstrap"> - <package name="udev"/> - <package name="filesystem"/> - <package name="glibc-locale"/> - <package name="cracklib-dict-full"/> - <package name="ca-certificates"/> - <package name="__RELEASE_PKG__"/> - </packages> -</image> diff --git a/p2v/launch-virt-p2v b/p2v/launch-virt-p2v deleted file mode 100755 index 925aa6d6a..000000000 --- a/p2v/launch-virt-p2v +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash - -# (C) Copyright 2014-2019 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., 675 Mass Ave, Cambridge, MA 02139, USA. - -# This normally runs from systemd which deals with logging. - -# Are we running in GUI or non-GUI mode? This is controlled by the -# presence of "p2v.server" on the kernel command line. -cmdline=$(</proc/cmdline) -if [[ $cmdline == *p2v.server=* ]]; then - # Non-GUI mode, don't run X. Just run virt-p2v directly. - exec /usr/bin/virt-p2v --iso --colours - -else - # GUI mode. Run xinit to start X. To save one script, we invoke - # self again to run the window manager and virt-p2v. - if [ "$1" = "run" ]; then - cd / - - ID- if test -f /etc/os-release; then - . /etc/os-release - fi - - case "$ID" in - sles|opensuse) - # not all versions of SLE / openSUSE ship metacity and nm-applet - icewm & - ;; - *) - metacity & - nm-applet & - esac - exec /usr/bin/virt-p2v --iso --colours - else - xinit "$0" run - fi -fi diff --git a/p2v/main.c b/p2v/main.c deleted file mode 100644 index 424bccfb3..000000000 --- a/p2v/main.c +++ /dev/null @@ -1,583 +0,0 @@ -/* virt-p2v - * Copyright (C) 2009-2019 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. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <inttypes.h> -#include <unistd.h> -#include <getopt.h> -#include <fcntl.h> -#include <errno.h> -#include <error.h> -#include <dirent.h> -#include <locale.h> -#include <libintl.h> -#include <sys/types.h> -#include <sys/stat.h> - -#if MAJOR_IN_MKDEV -#include <sys/mkdev.h> -#elif MAJOR_IN_SYSMACROS -#include <sys/sysmacros.h> -/* else it's in sys/types.h, included above */ -#endif - -/* errors in <gtk.h> */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#if defined(__GNUC__) && __GNUC__ >= 6 /* gcc >= 6 */ -#pragma GCC diagnostic ignored "-Wshift-overflow" -#endif -#include <gtk/gtk.h> -#pragma GCC diagnostic pop - -#include "ignore-value.h" -#include "getprogname.h" -#include "p2v.h" - -char **all_disks; -char **all_removable; -char **all_interfaces; -int is_iso_environment = 0; -int feature_colours_option = 0; -int force_colour = 0; -static const char *test_disk = NULL; - -static void udevadm_settle (void); -static void set_config_defaults (struct config *config); -static void find_all_disks (void); -static void find_all_interfaces (void); - -enum { HELP_OPTION = CHAR_MAX + 1 }; -static const char options[] = "Vv"; -static const struct option long_options[] = { - { "help", 0, 0, HELP_OPTION }, - { "cmdline", 1, 0, 0 }, - { "color", 0, 0, 0 }, - { "colors", 0, 0, 0 }, - { "colour", 0, 0, 0 }, - { "colours", 0, 0, 0 }, - { "iso", 0, 0, 0 }, - { "nbd", 1, 0, 0 }, - { "long-options", 0, 0, 0 }, - { "short-options", 0, 0, 0 }, - { "test-disk", 1, 0, 0 }, - { "verbose", 0, 0, 'v' }, - { "version", 0, 0, 'V' }, - { 0, 0, 0, 0 } -}; - -static void __attribute__((noreturn)) -usage (int status) -{ - if (status != EXIT_SUCCESS) - fprintf (stderr, _("Try ‘%s --help’ for more information.\n"), - getprogname ()); - else { - printf (_("%s: Convert a physical machine to use KVM\n" - "Copyright (C) 2009-2019 Red Hat Inc.\n" - "Usage:\n" - " %s [--options]\n" - "Options:\n" - " --help Display brief help\n" - " --cmdline=CMDLINE Used to debug command line parsing\n" - " --colors|--colours Use ANSI colour sequences even if not tty\n" - " --iso Running in the ISO environment\n" - " --nbd=qemu-nbd,nbdkit Search order for NBD servers\n" - " --test-disk=DISK.IMG For testing, use disk as /dev/sda\n" - " -v|--verbose Verbose messages\n" - " -V|--version Display version and exit\n" - "For more information, see the manpage %s(1).\n"), - getprogname (), getprogname (), - getprogname ()); - } - exit (status); -} - -/* XXX Copied from fish/options.c. */ -static void -display_short_options (const char *format) -{ - while (*format) { - if (*format != ':') - printf ("-%c\n", *format); - ++format; - } - exit (EXIT_SUCCESS); -} - -static void -display_long_options (const struct option *long_options) -{ - while (long_options->name) { - if (STRNEQ (long_options->name, "long-options") && STRNEQ (long_options->name, "short-options")) - printf ("--%s\n", long_options->name); - long_options++; - } - exit (EXIT_SUCCESS); -} - -int -main (int argc, char *argv[]) -{ - gboolean gui_possible; - int c; - int option_index; - char **cmdline = NULL; - int cmdline_source = 0; - struct config *config = new_config (); - - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEBASEDIR); - textdomain (PACKAGE); - - /* We may use random(3) in this program. */ - srandom (time (NULL) + getpid ()); - - /* There is some raciness between slow devices being discovered by - * the kernel and udev and virt-p2v running. This is a partial - * workaround, but a real fix involves handling hotplug events - * (possible in GUI mode, not easy in kernel mode). - */ - udevadm_settle (); - - gui_possible = gtk_init_check (&argc, &argv); - - for (;;) { - c = getopt_long (argc, argv, options, long_options, &option_index); - if (c == -1) break; - - switch (c) { - case 0: /* options which are long only */ - if (STREQ (long_options[option_index].name, "long-options")) { - display_long_options (long_options); - } - else if (STREQ (long_options[option_index].name, "short-options")) { - display_short_options (options); - } - else if (STREQ (long_options[option_index].name, "cmdline")) { - cmdline = parse_cmdline_string (optarg); - cmdline_source = CMDLINE_SOURCE_COMMAND_LINE; - } - else if (STREQ (long_options[option_index].name, "color") || - STREQ (long_options[option_index].name, "colour") || - STREQ (long_options[option_index].name, "colors") || - STREQ (long_options[option_index].name, "colours")) { - force_colour = 1; - } - else if (STREQ (long_options[option_index].name, "iso")) { - is_iso_environment = 1; - } - else if (STREQ (long_options[option_index].name, "nbd")) { - set_nbd_option (optarg); /* in nbd.c */ - } - else if (STREQ (long_options[option_index].name, "test-disk")) { - if (test_disk != NULL) - error (EXIT_FAILURE, 0, - _("only a single --test-disk option can be used")); - if (optarg[0] != '/') - error (EXIT_FAILURE, 0, - _("--test-disk must be an absolute path")); - test_disk = optarg; - } - else - error (EXIT_FAILURE, 0, - _("unknown long option: %s (%d)"), - long_options[option_index].name, option_index); - break; - - case 'v': - /* This option does nothing since 1.33.41. Verbose is always - * enabled. - */ - break; - - case 'V': - printf ("%s %s\n", getprogname (), PACKAGE_VERSION_FULL); - exit (EXIT_SUCCESS); - - case HELP_OPTION: - usage (EXIT_SUCCESS); - - default: - usage (EXIT_FAILURE); - } - } - - if (optind != argc) { - fprintf (stderr, _("%s: unused arguments on the command line\n"), - getprogname ()); - usage (EXIT_FAILURE); - } - - test_nbd_servers (); - - set_config_defaults (config); - - /* Parse /proc/cmdline (if it exists) or use the --cmdline parameter - * to initialize the configuration. This allows defaults to be pass - * using the kernel command line, with additional GUI configuration - * later. - */ - if (cmdline == NULL) { - cmdline = parse_proc_cmdline (); - if (cmdline != NULL) - cmdline_source = CMDLINE_SOURCE_PROC_CMDLINE; - } - - if (cmdline) - update_config_from_kernel_cmdline (config, cmdline); - - /* If p2v.server exists, then we use the non-interactive kernel - * conversion. Otherwise we run the GUI. - */ - if (config->remote.server != NULL) - kernel_conversion (config, cmdline, cmdline_source); - else { - if (!gui_possible) - error (EXIT_FAILURE, 0, - _("gtk_init_check returned false, indicating that\n" - "a GUI is not possible on this host. Check X11, $DISPLAY etc.")); - gui_conversion (config); - } - - guestfs_int_free_string_list (cmdline); - free_config (config); - - exit (EXIT_SUCCESS); -} - -static void -udevadm_settle (void) -{ - ignore_value (system ("udevadm settle")); -} - -static void -set_config_defaults (struct config *config) -{ - long i; - char hostname[257]; - - /* Default guest name is derived from the source hostname. If we - * assume that the p2v ISO gets its IP address and hostname from - * DHCP, then there is at better than average chance that - * gethostname will return the real hostname here. It's better than - * trying to fish around in the guest filesystem anyway. - */ - if (gethostname (hostname, sizeof hostname) == -1) { - perror ("gethostname"); - /* Generate a simple random name. */ - if (guestfs_int_random_string (hostname, 8) == -1) - error (EXIT_FAILURE, errno, "guestfs_int_random_string"); - } else { - char *p; - - /* If the hostname is an FQDN, truncate before the first dot. */ - p = strchr (hostname, '.'); - if (p && p > hostname) - *p = '\0'; - } - config->guestname = strdup (hostname); - - /* Defaults for #vcpus and memory are taken from the physical machine. */ - i = sysconf (_SC_NPROCESSORS_ONLN); - if (i == -1) { - perror ("sysconf: _SC_NPROCESSORS_ONLN"); - config->vcpus = 1; - } - else if (i == 0) - config->vcpus = 1; - else - config->vcpus = i; - - i = sysconf (_SC_PHYS_PAGES); - if (i == -1) { - perror ("sysconf: _SC_PHYS_PAGES"); - config->memory = 1024 * 1024 * 1024; - } - else - config->memory = i; - - i = sysconf (_SC_PAGESIZE); - if (i == -1) { - perror ("sysconf: _SC_PAGESIZE"); - config->memory *= 4096; - } - else - config->memory *= i; - - /* Round up the default memory to a power of 2, since the kernel - * memory is not included in the total physical pages returned - * above. - * http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 - */ - config->memory--; - config->memory |= config->memory >> 1; - config->memory |= config->memory >> 2; - config->memory |= config->memory >> 4; - config->memory |= config->memory >> 8; - config->memory |= config->memory >> 16; - config->memory |= config->memory >> 32; - config->memory++; - - get_cpu_config (&config->cpu); - get_rtc_config (&config->rtc); - - /* Find all block devices in the system. */ - if (!test_disk) - find_all_disks (); - else { - /* For testing and debugging purposes, you can use - * --test-disk=/path/to/disk.img - */ - all_disks = malloc (2 * sizeof (char *)); - if (all_disks == NULL) - error (EXIT_FAILURE, errno, "realloc"); - all_disks[0] = strdup (test_disk); - if (all_disks[0] == NULL) - error (EXIT_FAILURE, errno, "strdup"); - all_disks[1] = NULL; - } - if (all_disks) - config->disks = guestfs_int_copy_string_list (all_disks); - - /* Find all removable devices in the system. */ - if (all_removable) - config->removable = guestfs_int_copy_string_list (all_removable); - - /* Find all network interfaces in the system. */ - find_all_interfaces (); - if (all_interfaces) - config->interfaces = guestfs_int_copy_string_list (all_interfaces); - - /* Default output drops the guest onto /var/tmp on the conversion - * server, a hopefully safe default. - */ - config->output.type = strdup ("local"); - config->output.storage = strdup ("/var/tmp"); -} - -static int -compare (const void *vp1, const void *vp2) -{ - char * const *p1 = (char * const *) vp1; - char * const *p2 = (char * const *) vp2; - return strcmp (*p1, *p2); -} - -/** - * Get parent device of a partition. - * - * Returns C<0> if no parent device could be found. - */ -static dev_t -partition_parent (dev_t part_dev) -{ - CLEANUP_FCLOSE FILE *fp = NULL; - CLEANUP_FREE char *path = NULL, *content = NULL; - size_t len = 0; - unsigned parent_major, parent_minor; - - if (asprintf (&path, "/sys/dev/block/%ju:%ju/../dev", - (uintmax_t) major (part_dev), - (uintmax_t) minor (part_dev)) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - fp = fopen (path, "r"); - if (fp == NULL) - return 0; - - if (getline (&content, &len, fp) == -1) - error (EXIT_FAILURE, errno, "getline"); - - if (sscanf (content, "%u:%u", &parent_major, &parent_minor) != 2) - return 0; - - return makedev (parent_major, parent_minor); -} - -/** - * Return true if the named device (eg. C<dev == "sda">) contains the - * root filesystem. C<root_device> is the major:minor of the root - * filesystem (eg. C<8:1> if the root filesystem was F</dev/sda1>). - * - * This doesn't work for LVs and so on. However we only really care - * if this test works on the P2V ISO where the root device is a - * regular partition. - */ -static int -device_contains (const char *dev, dev_t root_device) -{ - struct stat statbuf; - CLEANUP_FREE char *dev_name = NULL; - dev_t root_device_parent; - - if (asprintf (&dev_name, "/dev/%s", dev) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - if (stat (dev_name, &statbuf) == -1) - return 0; - - /* See if dev is the root_device. */ - if (statbuf.st_rdev == root_device) - return 1; - - /* See if dev is the parent device of the root_device. */ - root_device_parent = partition_parent (root_device); - if (root_device_parent == 0) - return 0; - if (statbuf.st_rdev == root_device_parent) - return 1; - - return 0; -} - -/** - * Enumerate all disks in F</sys/block> and add them to the global - * C<all_disks> and C<all_removable> arrays. - */ -static void -find_all_disks (void) -{ - DIR *dir; - struct dirent *d; - size_t nr_disks = 0, nr_removable = 0; - dev_t root_device = 0; - struct stat statbuf; - - if (stat ("/", &statbuf) == 0) - root_device = statbuf.st_dev; - - /* The default list of disks is everything in /sys/block which - * matches the common patterns for disk names. - */ - dir = opendir ("/sys/block"); - if (!dir) - error (EXIT_FAILURE, errno, "opendir"); - - for (;;) { - errno = 0; - d = readdir (dir); - if (!d) break; - - if (STRPREFIX (d->d_name, "cciss!") || - STRPREFIX (d->d_name, "hd") || - STRPREFIX (d->d_name, "sd") || - STRPREFIX (d->d_name, "ubd") || - STRPREFIX (d->d_name, "vd")) { - char *p; - - /* Skip the device containing the root filesystem. */ - if (device_contains (d->d_name, root_device)) - continue; - - nr_disks++; - all_disks = realloc (all_disks, sizeof (char *) * (nr_disks + 1)); - if (!all_disks) - error (EXIT_FAILURE, errno, "realloc"); - - all_disks[nr_disks-1] = strdup (d->d_name); - - /* cciss device /dev/cciss/c0d0 will be /sys/block/cciss!c0d0 */ - p = strchr (all_disks[nr_disks-1], '!'); - if (p) *p = '/'; - - all_disks[nr_disks] = NULL; - } - else if (STRPREFIX (d->d_name, "sr")) { - nr_removable++; - all_removable = realloc (all_removable, - sizeof (char *) * (nr_removable + 1)); - if (!all_removable) - error (EXIT_FAILURE, errno, "realloc"); - all_removable[nr_removable-1] = strdup (d->d_name); - all_removable[nr_removable] = NULL; - } - } - - /* Check readdir didn't fail */ - if (errno != 0) - error (EXIT_FAILURE, errno, "readdir: %s", "/sys/block"); - - /* Close the directory handle */ - if (closedir (dir) == -1) - error (EXIT_FAILURE, errno, "closedir: %s", "/sys/block"); - - if (all_disks) - qsort (all_disks, nr_disks, sizeof (char *), compare); - if (all_removable) - qsort (all_removable, nr_removable, sizeof (char *), compare); -} - -/** - * Enumerate all network interfaces in F</sys/class/net> and add them - * to the global C<all_interfaces> array. - */ -static void -find_all_interfaces (void) -{ - DIR *dir; - struct dirent *d; - size_t nr_interfaces = 0; - - /* The default list of network interfaces is everything in - * /sys/class/net which matches some common patterns. - */ - dir = opendir ("/sys/class/net"); - if (!dir) - error (EXIT_FAILURE, errno, "opendir: %s", "/sys/class/net"); - - for (;;) { - errno = 0; - d = readdir (dir); - if (!d) break; - - /* For systemd predictable names, see: - * http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-net_id.c#n20 - * biosdevname is also a possibility here. - * Ignore PPP, SLIP, WWAN, bridges, etc. - */ - if (STRPREFIX (d->d_name, "em") || - STRPREFIX (d->d_name, "en") || - STRPREFIX (d->d_name, "eth") || - STRPREFIX (d->d_name, "wl")) { - nr_interfaces++; - all_interfaces - realloc (all_interfaces, sizeof (char *) * (nr_interfaces + 1)); - if (!all_interfaces) - error (EXIT_FAILURE, errno, "realloc"); - all_interfaces[nr_interfaces-1] = strdup (d->d_name); - all_interfaces[nr_interfaces] = NULL; - } - } - - /* Check readdir didn't fail */ - if (errno != 0) - error (EXIT_FAILURE, errno, "readdir: %s", "/sys/class/net"); - - /* Close the directory handle */ - if (closedir (dir) == -1) - error (EXIT_FAILURE, errno, "closedir: %s", "/sys/class/net"); - - if (all_interfaces) - qsort (all_interfaces, nr_interfaces, sizeof (char *), compare); -} diff --git a/p2v/nbd.c b/p2v/nbd.c deleted file mode 100644 index 8b80803da..000000000 --- a/p2v/nbd.c +++ /dev/null @@ -1,840 +0,0 @@ -/* virt-p2v - * Copyright (C) 2009-2019 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 file handles the virt-p2v I<--nbd> command line option - * and running either L<qemu-nbd(8)> or L<nbdkit(1)>. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <inttypes.h> -#include <fcntl.h> -#include <unistd.h> -#include <time.h> -#include <netdb.h> -#include <errno.h> -#include <error.h> -#include <libintl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <assert.h> - -#include "getprogname.h" - -#include "p2v.h" - -/* How long to wait for the NBD server to start (seconds). */ -#define WAIT_NBD_TIMEOUT 10 - -/* The local port that the NBD server listens on (incremented for - * each server which is started). - */ -static int nbd_local_port; - -/* List of servers specified by the --nbd option. */ -enum nbd_server { - /* 0 is reserved for "end of list" */ - QEMU_NBD = 1, - QEMU_NBD_NO_SA = 2, - NBDKIT = 3, - NBDKIT_NO_SA = 4, -}; -static enum nbd_server *cmdline_servers = NULL; - -static const char * -nbd_server_string (enum nbd_server s) -{ - const char *ret = NULL; - - switch (s) { - case QEMU_NBD: ret = "qemu-nbd"; break; - case QEMU_NBD_NO_SA: ret = "qemu-nbd-no-sa"; break; - case NBDKIT: ret = "nbdkit"; break; - case NBDKIT_NO_SA: ret = "nbdkit-no-sa"; break; - } - - if (ret == NULL) - abort (); - - return ret; -} - -/* If no --nbd option is passed, we use this standard list instead. - * Must match the documentation in virt-p2v(1). - */ -static const enum nbd_server standard_servers[] - { QEMU_NBD, QEMU_NBD_NO_SA, NBDKIT, NBDKIT_NO_SA, 0 }; - -/* After testing the list of servers passed by the user, this is - * server we decide to use. - */ -static enum nbd_server use_server; - -static pid_t start_qemu_nbd (const char *device, const char *ipaddr, int port, int *fds, size_t nr_fds); -static pid_t start_nbdkit (const char *device, const char *ipaddr, int port, int *fds, size_t nr_fds); -static int get_local_port (void); -static int open_listening_socket (const char *ipaddr, int **fds, size_t *nr_fds); -static int bind_tcpip_socket (const char *ipaddr, const char *port, int **fds, size_t *nr_fds); -static int connect_with_source_port (const char *hostname, int dest_port, int source_port); -static int bind_source_port (int sockfd, int family, int source_port); - -static char *nbd_error; - -static void set_nbd_error (const char *fs, ...) - __attribute__((format(printf,1,2))); - -static void -set_nbd_error (const char *fs, ...) -{ - va_list args; - char *msg; - int len; - - va_start (args, fs); - len = vasprintf (&msg, fs, args); - va_end (args); - - if (len < 0) - error (EXIT_FAILURE, errno, - "vasprintf (original error format string: %s)", fs); - - free (nbd_error); - nbd_error = msg; -} - -const char * -get_nbd_error (void) -{ - return nbd_error; -} - -/** - * The main program calls this to set the I<--nbd> option. - */ -void -set_nbd_option (const char *opt) -{ - size_t i, len; - CLEANUP_FREE_STRING_LIST char **strs = NULL; - - if (cmdline_servers != NULL) - error (EXIT_FAILURE, 0, _("--nbd option appears multiple times")); - - strs = guestfs_int_split_string (',', opt); - - if (strs == NULL) - error (EXIT_FAILURE, errno, _("malloc")); - - len = guestfs_int_count_strings (strs); - if (len == 0) - error (EXIT_FAILURE, 0, _("--nbd option cannot be empty")); - - cmdline_servers = malloc (sizeof (enum nbd_server) * (len + 1)); - if (cmdline_servers == NULL) - error (EXIT_FAILURE, errno, _("malloc")); - - for (i = 0; strs[i] != NULL; ++i) { - if (STREQ (strs[i], "qemu-nbd") || STREQ (strs[i], "qemu")) - cmdline_servers[i] = QEMU_NBD; - else if (STREQ (strs[i], "qemu-nbd-no-sa") || STREQ (strs[i], "qemu-no-sa")) - cmdline_servers[i] = QEMU_NBD_NO_SA; - else if (STREQ (strs[i], "nbdkit")) - cmdline_servers[i] = NBDKIT; - else if (STREQ (strs[i], "nbdkit-no-sa")) - cmdline_servers[i] = NBDKIT_NO_SA; - else - error (EXIT_FAILURE, 0, _("--nbd: unknown server: %s"), strs[i]); - } - - assert (i == len); - cmdline_servers[i] = 0; /* marks the end of the list */ -} - -/** - * Test the I<--nbd> option (or built-in default list) to see which - * servers are actually installed and appear to be working. - * - * Set the C<use_server> global accordingly. - */ -void -test_nbd_servers (void) -{ - size_t i; - int r; - const enum nbd_server *servers; - - /* Initialize nbd_local_port. */ - if (is_iso_environment) - /* The p2v ISO should allow us to open up just about any port, so - * we can fix a port number in that case. Using a predictable - * port number in this case should avoid rare errors if the port - * colides with another (ie. it'll either always fail or never - * fail). - */ - nbd_local_port = 50123; - else - /* When testing on the local machine, choose a random port. */ - nbd_local_port = 50000 + (random () % 10000); - - if (cmdline_servers != NULL) - servers = cmdline_servers; - else - servers = standard_servers; - - use_server = 0; - - for (i = 0; servers[i] != 0; ++i) { -#if DEBUG_STDERR - fprintf (stderr, "checking for %s ...\n", nbd_server_string (servers[i])); -#endif - - switch (servers[i]) { - case QEMU_NBD: /* with socket activation */ - r = system ("qemu-nbd --version" -#ifndef DEBUG_STDERR - " >/dev/null 2>&1" -#endif - " && grep -sq LISTEN_PID `which qemu-nbd`" - ); - if (r == 0) { - use_server = servers[i]; - goto finish; - } - break; - - case QEMU_NBD_NO_SA: - r = system ("qemu-nbd --version" -#ifndef DEBUG_STDERR - " >/dev/null 2>&1" -#endif - ); - if (r == 0) { - use_server = servers[i]; - goto finish; - } - break; - - case NBDKIT: /* with socket activation */ - r = system ("nbdkit file --version" -#ifndef DEBUG_STDERR - " >/dev/null 2>&1" -#endif - " && grep -sq LISTEN_PID `which nbdkit`" - ); - if (r == 0) { - use_server = servers[i]; - goto finish; - } - break; - - case NBDKIT_NO_SA: - r = system ("nbdkit file --version" -#ifndef DEBUG_STDERR - " >/dev/null 2>&1" -#endif - ); - if (r == 0) { - use_server = servers[i]; - goto finish; - } - break; - - default: - abort (); - } - } - - finish: - if (use_server == 0) { - fprintf (stderr, - _("%s: no working NBD server was found, cannot continue.\n" - "Please check the --nbd option in the virt-p2v(1) man page.\n"), - getprogname ()); - exit (EXIT_FAILURE); - } - - /* Release memory used by the --nbd option. */ - free (cmdline_servers); - cmdline_servers = NULL; - -#if DEBUG_STDERR - fprintf (stderr, "picked %s\n", nbd_server_string (use_server)); -#endif -} - -/** - * Start the NBD server. - * - * We previously tested all NBD servers (see C<test_nbd_servers>) and - * hopefully found one which will work. - * - * Returns the process ID (E<gt> 0) or C<0> if there is an error. - */ -pid_t -start_nbd_server (const char **ipaddr, int *port, const char *device) -{ - int *fds = NULL; - size_t i, nr_fds; - pid_t pid; - - switch (use_server) { - case QEMU_NBD: /* qemu-nbd with socket activation */ - /* Ideally we would bind this socket to "localhost", but that - * requires two listening FDs, and qemu-nbd currently cannot - * support socket activation with two FDs. So we only bind to the - * IPv4 address. - */ - *ipaddr = "127.0.0.1"; - *port = open_listening_socket (*ipaddr, &fds, &nr_fds); - if (*port == -1) return -1; - pid = start_qemu_nbd (device, *ipaddr, *port, fds, nr_fds); - for (i = 0; i < nr_fds; ++i) - close (fds[i]); - free (fds); - return pid; - - case QEMU_NBD_NO_SA: /* qemu-nbd without socket activation */ - *ipaddr = "localhost"; - *port = get_local_port (); - if (*port == -1) return -1; - return start_qemu_nbd (device, *ipaddr, *port, NULL, 0); - - case NBDKIT: /* nbdkit with socket activation */ - *ipaddr = "localhost"; - *port = open_listening_socket (*ipaddr, &fds, &nr_fds); - if (*port == -1) return -1; - pid = start_nbdkit (device, *ipaddr, *port, fds, nr_fds); - for (i = 0; i < nr_fds; ++i) - close (fds[i]); - free (fds); - return pid; - - case NBDKIT_NO_SA: /* nbdkit without socket activation */ - *ipaddr = "localhost"; - *port = get_local_port (); - if (*port == -1) return -1; - return start_nbdkit (device, *ipaddr, *port, NULL, 0); - } - - abort (); -} - -#define FIRST_SOCKET_ACTIVATION_FD 3 - -/** - * Set up file descriptors and environment variables for - * socket activation. - * - * Note this function runs in the child between fork and exec. - */ -static inline void -socket_activation (int *fds, size_t nr_fds) -{ - size_t i; - char nr_fds_str[16]; - char pid_str[16]; - - if (fds == NULL) return; - - for (i = 0; i < nr_fds; ++i) { - int fd = FIRST_SOCKET_ACTIVATION_FD + i; - if (fds[i] != fd) { - dup2 (fds[i], fd); - close (fds[i]); - } - } - - snprintf (nr_fds_str, sizeof nr_fds_str, "%zu", nr_fds); - setenv ("LISTEN_FDS", nr_fds_str, 1); - snprintf (pid_str, sizeof pid_str, "%d", (int) getpid ()); - setenv ("LISTEN_PID", pid_str, 1); -} - -/** - * Start a local L<qemu-nbd(1)> process. - * - * If we are using socket activation, C<fds> and C<nr_fds> will - * contain the locally pre-opened file descriptors for this. - * Otherwise if C<fds == NULL> we pass the port number. - * - * Returns the process ID (E<gt> 0) or C<0> if there is an error. - */ -static pid_t -start_qemu_nbd (const char *device, - const char *ipaddr, int port, int *fds, size_t nr_fds) -{ - pid_t pid; - char port_str[64]; - -#if DEBUG_STDERR - fprintf (stderr, "starting qemu-nbd for %s on %s:%d%s\n", - device, ipaddr, port, - fds == NULL ? "" : " using socket activation"); -#endif - - snprintf (port_str, sizeof port_str, "%d", port); - - pid = fork (); - if (pid == -1) { - set_nbd_error ("fork: %m"); - return 0; - } - - if (pid == 0) { /* Child. */ - close (0); - if (open ("/dev/null", O_RDONLY) == -1) { - perror ("open: /dev/null"); - _exit (EXIT_FAILURE); - } - - if (fds == NULL) { /* without socket activation */ - execlp ("qemu-nbd", - "qemu-nbd", - "-r", /* readonly (vital!) */ - "-p", port_str, /* listening port */ - "-t", /* persistent */ - "-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 */ - NULL); - perror ("qemu-nbd"); - _exit (EXIT_FAILURE); - } - else { /* socket activation */ - socket_activation (fds, nr_fds); - - execlp ("qemu-nbd", - "qemu-nbd", - "-r", /* readonly (vital!) */ - "-t", /* persistent */ - "-f", "raw", /* force raw format */ - "--cache=unsafe", /* use unsafe caching for speed */ - device, /* a device like /dev/sda */ - NULL); - perror ("qemu-nbd"); - _exit (EXIT_FAILURE); - } - } - - /* Parent. */ - return pid; -} - -/** - * Start a local L<nbdkit(1)> process using the - * L<nbdkit-file-plugin(1)>. - * - * If we are using socket activation, C<fds> and C<nr_fds> will - * contain the locally pre-opened file descriptors for this. - * Otherwise if C<fds == NULL> we pass the port number. - * - * Returns the process ID (E<gt> 0) or C<0> if there is an error. - */ -static pid_t -start_nbdkit (const char *device, - const char *ipaddr, int port, int *fds, size_t nr_fds) -{ - pid_t pid; - char port_str[64]; - CLEANUP_FREE char *file_str = NULL; - -#if DEBUG_STDERR - fprintf (stderr, "starting nbdkit for %s on %s:%d%s\n", - device, ipaddr, port, - fds == NULL ? "" : " using socket activation"); -#endif - - snprintf (port_str, sizeof port_str, "%d", port); - - if (asprintf (&file_str, "file=%s", device) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - pid = fork (); - if (pid == -1) { - set_nbd_error ("fork: %m"); - return 0; - } - - if (pid == 0) { /* Child. */ - close (0); - if (open ("/dev/null", O_RDONLY) == -1) { - perror ("open: /dev/null"); - _exit (EXIT_FAILURE); - } - - if (fds == NULL) { /* without socket activation */ - execlp ("nbdkit", - "nbdkit", - "-r", /* readonly (vital!) */ - "-p", port_str, /* listening port */ - "-i", ipaddr, /* listen only on loopback interface */ - "-f", /* don't fork */ - "file", /* file plugin */ - file_str, /* a device like file=/dev/sda */ - NULL); - perror ("nbdkit"); - _exit (EXIT_FAILURE); - } - else { /* socket activation */ - socket_activation (fds, nr_fds); - - execlp ("nbdkit", - "nbdkit", - "-r", /* readonly (vital!) */ - "-f", /* don't fork */ - "file", /* file plugin */ - file_str, /* a device like file=/dev/sda */ - NULL); - perror ("nbdkit"); - _exit (EXIT_FAILURE); - } - } - - /* Parent. */ - return pid; -} - -/** - * This is used when we are starting an NBD server that does not - * support socket activation. We have to pass the '-p' option to - * the NBD server, but there's no good way to choose a free port, - * so we have to just guess. - * - * Returns the port number on success or C<-1> on error. - */ -static int -get_local_port (void) -{ - int port = nbd_local_port; - nbd_local_port++; - return port; -} - -/** - * This is used when we are starting an NBD server which supports - * socket activation. We can open a listening socket on an unused - * local port and return it. - * - * Returns the port number on success or C<-1> on error. - * - * The file descriptor(s) bound are returned in the array *fds, *nr_fds. - * The caller must free the array. - */ -static int -open_listening_socket (const char *ipaddr, int **fds, size_t *nr_fds) -{ - int port; - char port_str[16]; - - /* This just ensures we don't try the port we previously bound to. */ - port = nbd_local_port; - - /* Search for a free port. */ - for (; port < 60000; ++port) { - snprintf (port_str, sizeof port_str, "%d", port); - if (bind_tcpip_socket (ipaddr, port_str, fds, nr_fds) == 0) { - /* See above. */ - nbd_local_port = port + 1; - return port; - } - } - - set_nbd_error ("cannot find a free local port"); - return -1; -} - -static int -bind_tcpip_socket (const char *ipaddr, const char *port, - int **fds_rtn, size_t *nr_fds_rtn) -{ - struct addrinfo *ai = NULL; - struct addrinfo hints; - struct addrinfo *a; - int err; - int *fds = NULL; - size_t nr_fds; - int addr_in_use = 0; - - memset (&hints, 0, sizeof hints); - hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; - hints.ai_socktype = SOCK_STREAM; - - err = getaddrinfo (ipaddr, port, &hints, &ai); - if (err != 0) { -#if DEBUG_STDERR - fprintf (stderr, "%s: getaddrinfo: %s: %s: %s", - getprogname (), ipaddr ? ipaddr : "<any>", port, - gai_strerror (err)); -#endif - return -1; - } - - nr_fds = 0; - - for (a = ai; a != NULL; a = a->ai_next) { - int sock, opt; - - sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol); - if (sock == -1) - error (EXIT_FAILURE, errno, "socket"); - - opt = 1; - if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt) == -1) - perror ("setsockopt: SO_REUSEADDR"); - -#ifdef IPV6_V6ONLY - if (a->ai_family == PF_INET6) { - if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof opt) == -1) - perror ("setsockopt: IPv6 only"); - } -#endif - - if (bind (sock, a->ai_addr, a->ai_addrlen) == -1) { - if (errno == EADDRINUSE) { - addr_in_use = 1; - close (sock); - continue; - } - perror ("bind"); - close (sock); - continue; - } - - if (listen (sock, SOMAXCONN) == -1) { - perror ("listen"); - close (sock); - continue; - } - - nr_fds++; - fds = realloc (fds, sizeof (int) * nr_fds); - if (!fds) - error (EXIT_FAILURE, errno, "realloc"); - fds[nr_fds-1] = sock; - } - - freeaddrinfo (ai); - - if (nr_fds == 0 && addr_in_use) { -#if DEBUG_STDERR - fprintf (stderr, "%s: unable to bind to %s:%s: %s\n", - getprogname (), ipaddr ? ipaddr : "<any>", port, - strerror (EADDRINUSE)); -#endif - return -1; - } - -#if DEBUG_STDERR - fprintf (stderr, "%s: bound to IP address %s:%s (%zu socket(s))\n", - getprogname (), ipaddr ? ipaddr : "<any>", port, nr_fds); -#endif - - *fds_rtn = fds; - *nr_fds_rtn = nr_fds; - return 0; -} - -/** - * Wait for a local NBD server to start and be listening for - * connections. - */ -int -wait_for_nbd_server_to_start (const char *ipaddr, int port) -{ - int sockfd = -1; - int result = -1; - time_t start_t, now_t; - struct timespec half_sec = { .tv_sec = 0, .tv_nsec = 500000000 }; - struct timeval timeout = { .tv_usec = 0 }; - char magic[8]; /* NBDMAGIC */ - size_t bytes_read = 0; - ssize_t recvd; - - time (&start_t); - - for (;;) { - time (&now_t); - - if (now_t - start_t >= WAIT_NBD_TIMEOUT) { - set_nbd_error ("timed out waiting for NBD server to start"); - goto cleanup; - } - - /* Source port for probing NBD server should be one greater than - * port. It's not guaranteed to always bind to this port, but it - * will hint the kernel to start there and try incrementally - * higher ports if needed. This avoids the case where the kernel - * selects port as our source port, and we immediately connect to - * ourself. See: - * https://bugzilla.redhat.com/show_bug.cgi?id=1167774#c9 - */ - sockfd = connect_with_source_port (ipaddr, port, port+1); - if (sockfd >= 0) - break; - - nanosleep (&half_sec, NULL); - } - - time (&now_t); - timeout.tv_sec = (start_t + WAIT_NBD_TIMEOUT) - now_t; - if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout) == -1) { - set_nbd_error ("waiting for NBD server to start: " - "setsockopt(SO_RCVTIMEO): %m"); - goto cleanup; - } - - do { - recvd = recv (sockfd, magic, sizeof magic - bytes_read, 0); - - if (recvd == -1) { - set_nbd_error ("waiting for NBD server to start: recv: %m"); - goto cleanup; - } - - bytes_read += recvd; - } while (bytes_read < sizeof magic); - - if (memcmp (magic, "NBDMAGIC", sizeof magic) != 0) { - set_nbd_error ("waiting for NBD server to start: " - "'NBDMAGIC' was not received from NBD server"); - goto cleanup; - } - - result = 0; - cleanup: - if (sockfd >= 0) - close (sockfd); - - return result; -} - -/** - * Connect to C<hostname:dest_port>, resolving the address using - * L<getaddrinfo(3)>. - * - * This also sets the source port of the connection to the first free - * port number E<ge> C<source_port>. - * - * This may involve multiple connections - to IPv4 and IPv6 for - * instance. - */ -static int -connect_with_source_port (const char *hostname, int dest_port, int source_port) -{ - struct addrinfo hints; - struct addrinfo *results, *rp; - char dest_port_str[16]; - int r, sockfd = -1; - int reuseaddr = 1; - - snprintf (dest_port_str, sizeof dest_port_str, "%d", dest_port); - - memset (&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; /* allow IPv4 or IPv6 */ - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_NUMERICSERV; /* numeric dest port number */ - hints.ai_protocol = 0; /* any protocol */ - - r = getaddrinfo (hostname, dest_port_str, &hints, &results); - if (r != 0) { - set_nbd_error ("getaddrinfo: %s/%s: %s", - hostname, dest_port_str, gai_strerror (r)); - return -1; - } - - for (rp = results; rp != NULL; rp = rp->ai_next) { - sockfd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (sockfd == -1) - continue; - - /* If we run p2v repeatedly (say, running the tests in a loop), - * there's a decent chance we'll end up trying to bind() to a port - * that is in TIME_WAIT from a prior run. Handle that gracefully - * with SO_REUSEADDR. - */ - if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, - &reuseaddr, sizeof reuseaddr) == -1) - perror ("warning: setsockopt"); - - /* Need to bind the source port. */ - if (bind_source_port (sockfd, rp->ai_family, source_port) == -1) { - close (sockfd); - sockfd = -1; - continue; - } - - /* Connect. */ - if (connect (sockfd, rp->ai_addr, rp->ai_addrlen) == -1) { - set_nbd_error ("waiting for NBD server to start: " - "connect to %s/%s: %m", - hostname, dest_port_str); - close (sockfd); - sockfd = -1; - continue; - } - - break; - } - - freeaddrinfo (results); - return sockfd; -} - -static int -bind_source_port (int sockfd, int family, int source_port) -{ - struct addrinfo hints; - struct addrinfo *results, *rp; - char source_port_str[16]; - int r; - - snprintf (source_port_str, sizeof source_port_str, "%d", source_port); - - memset (&hints, 0, sizeof (hints)); - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* numeric port number */ - hints.ai_protocol = 0; /* any protocol */ - - r = getaddrinfo ("localhost", source_port_str, &hints, &results); - if (r != 0) { - set_nbd_error ("getaddrinfo (bind): localhost/%s: %s", - source_port_str, gai_strerror (r)); - return -1; - } - - for (rp = results; rp != NULL; rp = rp->ai_next) { - if (bind (sockfd, rp->ai_addr, rp->ai_addrlen) == 0) - goto bound; - } - - set_nbd_error ("waiting for NBD server to start: " - "bind to source port %d: %m", - source_port); - freeaddrinfo (results); - return -1; - - bound: - freeaddrinfo (results); - return 0; -} diff --git a/p2v/p2v.h b/p2v/p2v.h deleted file mode 100644 index 66c245eda..000000000 --- a/p2v/p2v.h +++ /dev/null @@ -1,136 +0,0 @@ -/* virt-p2v - * Copyright (C) 2009-2019 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. - */ - -#ifndef P2V_H -#define P2V_H - -#include <stdio.h> -#include <stdbool.h> - -/* Send various debug information to stderr. Harmless and useful, so - * can be left enabled in production builds. - */ -#define DEBUG_STDERR 1 - -#include "miniexpect.h" -#include "p2v-config.h" - -#include "guestfs-utils.h" - -/* All disks / removable media / network interfaces discovered - * when the program started. Do not change these. - */ -extern char **all_disks; -extern char **all_removable; -extern char **all_interfaces; - -/* True if running inside the virt-p2v ISO environment. Various - * dangerous functions such as the "Reboot" button are disabled if - * this is false. - */ -extern int is_iso_environment; - -/* True if virt-v2v supports the --colours option. */ -extern int feature_colours_option; - -/* virt-p2v --colours option (used by ansi_* macros). */ -extern int force_colour; - -/* cpuid.c */ -extern void get_cpu_config (struct cpu_config *); - -/* rtc.c */ -extern void get_rtc_config (struct rtc_config *); - -/* kernel-cmdline.c */ -extern char **parse_cmdline_string (const char *cmdline); -extern char **parse_proc_cmdline (void); -extern const char *get_cmdline_key (char **cmdline, const char *key); - -#define CMDLINE_SOURCE_COMMAND_LINE 1 /* --cmdline */ -#define CMDLINE_SOURCE_PROC_CMDLINE 2 /* /proc/cmdline */ - -/* kernel-config.c */ -extern void update_config_from_kernel_cmdline (struct config *config, char **cmdline); - -/* kernel.c */ -extern void kernel_conversion (struct config *, char **cmdline, int cmdline_source); - -/* gui.c */ -extern void gui_conversion (struct config *); - -/* conversion.c */ -struct data_conn { /* Data per NBD connection / physical disk. */ - mexp_h *h; /* miniexpect handle to ssh */ - pid_t nbd_pid; /* NBD server PID */ - int nbd_remote_port; /* remote NBD port on conversion server */ -}; - -extern int start_conversion (struct config *, void (*notify_ui) (int type, const char *data)); -#define NOTIFY_LOG_DIR 1 /* location of remote log directory */ -#define NOTIFY_REMOTE_MESSAGE 2 /* log message from remote virt-v2v */ -#define NOTIFY_STATUS 3 /* stage in conversion process */ -extern const char *get_conversion_error (void); -extern void cancel_conversion (void); -extern int conversion_is_running (void); - -/* physical-xml.c */ -extern void generate_physical_xml (struct config *, struct data_conn *, const char *filename); - -/* inhibit.c */ -extern int inhibit_power_saving (void); - -/* ssh.c */ -extern int test_connection (struct config *); -extern mexp_h *open_data_connection (struct config *, const char *local_ipaddr, int local_port, int *remote_port); -extern mexp_h *start_remote_connection (struct config *, const char *remote_dir); -extern const char *get_ssh_error (void); -extern int scp_file (struct config *config, const char *target, const char *local, ...) __attribute__((sentinel)); - -/* nbd.c */ -extern void set_nbd_option (const char *opt); -extern void test_nbd_servers (void); -extern pid_t start_nbd_server (const char **ipaddr, int *port, const char *device); -extern int wait_for_nbd_server_to_start (const char *ipaddr, int port); -const char *get_nbd_error (void); - -/* utils.c */ -extern uint64_t get_blockdev_size (const char *dev); -extern char *get_blockdev_model (const char *dev); -extern char *get_blockdev_serial (const char *dev); -extern char *get_if_addr (const char *if_name); -extern char *get_if_vendor (const char *if_name, int truncate); -extern void wait_network_online (const struct config *); - -/* whole-file.c */ -extern int read_whole_file (const char *filename, char **data_r, size_t *size_r); - -/* virt-v2v version and features (read from remote). */ -extern char *v2v_version; - -/* input and output drivers (read from remote). */ -extern char **input_drivers; -extern char **output_drivers; - -/* about-authors.c */ -extern const char *authors[]; -extern const char *qa[]; -extern const char *documenters[]; -extern const char *others[]; - -#endif /* P2V_H */ diff --git a/p2v/p2v.ks.in b/p2v/p2v.ks.in deleted file mode 100644 index 32f3665f0..000000000 --- a/p2v/p2v.ks.in +++ /dev/null @@ -1,193 +0,0 @@ -# Kickstart file for creating the virt-p2v ISO. -# (C) Copyright 2014-2019 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., 675 Mass Ave, Cambridge, MA 02139, USA. - -# Generated by virt-p2v-make-kickstart __PACKAGE_VERSION_FULL__ - -lang en_US.UTF-8 -keyboard us -timezone --utc GMT - -rootpw --plaintext p2v - -selinux --enforcing -firewall --enabled - -# Make sure that systemd doesn't rename the network device. We have -# to tell Anaconda we're using eth0, *and* we have to pass -# net.ifnames=0 on the kernel command line. -network --bootproto=dhcp --device=eth0 -bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH net.ifnames=0" - -zerombr -clearpart --all --initlabel -part / --size 3000 --fstype ext4 - -reboot - -# Repository lines: -__REPOS__ - -# Packages to install in the ISO. For dependencies, see -# p2v/Makefile.am. Note that libguestfs is NOT required by virt-p2v. - -%packages - -@core - -# rpm must be installed, else you'll hit RHBZ#1089566. -rpm - -# Note you must have a kernel, else the boot menu won't work: -kernel - -# This is required in order for RHEL to set the root password. -passwd - -# RHEL needs this in order to get networking. -NetworkManager - -# Required to run firewall --enabled kickstart command: -firewalld - -# Needed by post script to unpack the blobs. -/usr/bin/base64 -/usr/bin/gzip - -# Work around https://bugzilla.redhat.com/show_bug.cgi?id=1182362 -tar - -# https://bugzilla.redhat.com/show_bug.cgi?id=1168223 -dracut-live - -# The dependencies of virt-p2v. -__DEPENDENCIES__ - -# Extra packages requested by the user via the virt-p2v-make-kickstart -# --install option (if any). -__EXTRA_PACKAGES__ - -%end - -# Post-install configuration. - -%post - -# Base64-decoding of SSH Identity. - -base64 -d -i > /var/tmp/id_rsa << EOF -__BASE64_SSH_IDENTITY__ -EOF -if test -s /var/tmp/id_rsa; then - chmod 0600 /var/tmp/id_rsa -else - rm /var/tmp/id_rsa -fi - -# Base64-decoding of /etc/issue - -base64 -d -i > /etc/issue << EOF -__BASE64_ISSUE__ -EOF - -cp /etc/issue /etc/issue.net - -# Base64-decoding of launch-virt-p2v - -base64 -d -i > /usr/bin/launch-virt-p2v <<EOF -__BASE64_LAUNCH_VIRT_P2V__ -EOF - -chmod 0755 /usr/bin/launch-virt-p2v - -# Base64-decoding of p2v.service unit file - -base64 -d -i > /etc/systemd/system/p2v.service <<EOF -__BASE64_P2V_SERVICE__ -EOF - -# Base64-decoding of virt-p2v binary -# md5(virt-p2v) = __MD5SUM_VIRT_P2V__ - -base64 -d -i <<EOF | gzip -cd > /usr/bin/virt-p2v -__BASE64_VIRT_P2V__ -EOF - -chmod 0755 /usr/bin/virt-p2v - -# Update the default getty target to login automatically as root without -# prompting for a password -sed -i 's/^ExecStart=\(.*\)/ExecStart=\1 -a root/' \ - /usr/lib/systemd/system/getty@.service - -# Reserve tty1 as a getty so we can document it clearly -echo ReserveVT=1 >> /etc/systemd/logind.conf - -# Force text mode -systemctl set-default multi-user.target - -# Start p2v service -systemctl enable p2v.service - -# Disable ssh service (RHBZ#1248678) -systemctl disable sshd.service - -%end - -%post --nochroot - -PRODUCT='Virt P2V' -PRODUCT_SHORT='virt-p2v' -PACKAGE='__PACKAGE_NAME__' -VERSION='__PACKAGE_VERSION__' - -echo "Customizing boot menu" -sed -i -e ' -# Put product information at the top of the file -1 { - i '"say $PRODUCT $VERSION"' - i '"menu title $PRODUCT_SHORT $VERSION"' -} - -# Remove any existing menu title -/^menu title .*/d - -# Set the default timeout to 60 seconds -s/^timeout .*/timeout 600/ -' $LIVE_ROOT/isolinux/isolinux.cfg - -# store image version info in the ISO -cat > $LIVE_ROOT/isolinux/version <<EOF -PRODUCT='$PRODUCT' -PRODUCT_SHORT='${PRODUCT_SHORT}' -#PRODUCT_CODE=$PRODUCT_CODE -#RECIPE_SHA256=$RECIPE_SHA256 -#RECIPE_RPM=$RECIPE_RPM -PACKAGE=$PACKAGE -VERSION=$VERSION -EOF - -# overwrite user visible banners with the image versioning info -cat > $INSTALL_ROOT/etc/$PACKAGE-release <<EOF -$PRODUCT release $VERSION -EOF - -# replace initramfs if regenerated -if [ -f "$INSTALL_ROOT/initrd0.img" ]; then - mv -v "$INSTALL_ROOT/initrd0.img" "$LIVE_ROOT/isolinux/initrd0.img" -fi - -%end diff --git a/p2v/p2v.service b/p2v/p2v.service deleted file mode 100644 index 7096eb175..000000000 --- a/p2v/p2v.service +++ /dev/null @@ -1,38 +0,0 @@ -# libguestfs virt-p2v ISO -# Copyright (C) 2009-2019 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. - -# NB: This cannot be called "virt-p2v.service" because on Fedora the -# virt- prefix will cause it to get the wrong SELinux label. - -[Unit] -Description=p2v service -# For the GUI, we cannot necessarily wait for the network to come -# online, since that may require the "Configure Network" dialog. For -# the command line, we would like the network to be online, but we -# test that within virt-p2v itself. Therefore use network.target -# here, not network-online.target. -After=network.target - -[Service] -Type=oneshot -ExecStart=/usr/bin/launch-virt-p2v -RemainAfterExit=yes -StandardOutput=journal+console -StandardError=inherit - -[Install] -WantedBy=multi-user.target diff --git a/p2v/physical-xml.c b/p2v/physical-xml.c deleted file mode 100644 index 08f443014..000000000 --- a/p2v/physical-xml.c +++ /dev/null @@ -1,304 +0,0 @@ -/* virt-p2v - * Copyright (C) 2009-2019 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. - */ - -/** - * Create the F<physical.xml> file, which is a piece of phony libvirt - * XML used to communicate the metadata of the physical machine to - * virt-v2v. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <stdarg.h> -#include <string.h> -#include <inttypes.h> -#include <errno.h> -#include <error.h> - -#include <libxml/xmlwriter.h> - -#include <glib.h> - -#include "getprogname.h" - -#include "libxml2-writer-macros.h" - -#include "p2v.h" - -/* This macro is used by the macros in "libxml2-writer-macros.h" - * when an error occurs. - */ -#define xml_error(fn) \ - error (EXIT_FAILURE, errno, \ - "%s:%d: error constructing XML near call to \"%s\"", \ - __FILE__, __LINE__, (fn)); - -static const char *map_interface_to_network (struct config *, const char *interface); - -/** - * Write the libvirt XML for this physical machine. - * - * Note this is not actually input for libvirt. It's input for - * virt-v2v on the conversion server. Virt-v2v will (if necessary) - * generate the final libvirt XML. - */ -void -generate_physical_xml (struct config *config, struct data_conn *data_conns, - const char *filename) -{ - uint64_t memkb; - CLEANUP_XMLFREETEXTWRITER xmlTextWriterPtr xo = NULL; - size_t i; - - xo = xmlNewTextWriterFilename (filename, 0); - if (xo == NULL) - error (EXIT_FAILURE, errno, "xmlNewTextWriterFilename"); - - if (xmlTextWriterSetIndent (xo, 1) == -1 || - xmlTextWriterSetIndentString (xo, BAD_CAST " ") == -1) - error (EXIT_FAILURE, errno, "could not set XML indent"); - if (xmlTextWriterStartDocument (xo, NULL, NULL, NULL) == -1) - error (EXIT_FAILURE, errno, "xmlTextWriterStartDocument"); - - memkb = config->memory / 1024; - - comment (" %s %s ", getprogname (), PACKAGE_VERSION_FULL); - - comment - (" NOTE!\n" - "\n" - " This libvirt XML is generated by the virt-p2v front end, in\n" - " order to communicate with the backend virt-v2v process running\n" - " on the conversion server. It is a minimal description of the\n" - " physical machine. If the target of the conversion is libvirt,\n" - " then virt-v2v will generate the real target libvirt XML, which\n" - " has only a little to do with the XML in this file.\n" - "\n" - " TL;DR: Don't try to load this XML into libvirt. "); - - start_element ("domain") { - attribute ("type", "physical"); - - single_element ("name", config->guestname); - - start_element ("memory") { - attribute ("unit", "KiB"); - string_format ("%" PRIu64, memkb); - } end_element (); - - start_element ("currentMemory") { - attribute ("unit", "KiB"); - string_format ("%" PRIu64, memkb); - } end_element (); - - single_element_format ("vcpu", "%d", config->vcpus); - - if (config->cpu.vendor || config->cpu.model || - config->cpu.sockets || config->cpu.cores || config->cpu.threads) { - /* https://libvirt.org/formatdomain.html#elementsCPU */ - start_element ("cpu") { - attribute ("match", "minimum"); - if (config->cpu.vendor) - single_element ("vendor", config->cpu.vendor); - if (config->cpu.model) { - start_element ("model") { - attribute ("fallback", "allow"); - string (config->cpu.model); - } end_element (); - } - if (config->cpu.sockets || config->cpu.cores || config->cpu.threads) { - start_element ("topology") { - if (config->cpu.sockets) - attribute_format ("sockets", "%u", config->cpu.sockets); - if (config->cpu.cores) - attribute_format ("cores", "%u", config->cpu.cores); - if (config->cpu.threads) - attribute_format ("threads", "%u", config->cpu.threads); - } end_element (); - } - } end_element (); - } - - switch (config->rtc.basis) { - case BASIS_UNKNOWN: - /* Don't emit any <clock> element. */ - break; - case BASIS_UTC: - start_element ("clock") { - if (config->rtc.offset == 0) - attribute ("offset", "utc"); - else { - attribute ("offset", "variable"); - attribute ("basis", "utc"); - attribute_format ("adjustment", "%d", config->rtc.offset); - } - } end_element (); - break; - case BASIS_LOCALTIME: - start_element ("clock") { - attribute ("offset", "localtime"); - /* config->rtc.offset is always 0 in this case */ - } end_element (); - break; - } - - start_element ("os") { - start_element ("type") { - attribute ("arch", host_cpu); - string ("hvm"); - } end_element (); - } end_element (); - - start_element ("features") { - if (config->cpu.acpi) empty_element ("acpi"); - if (config->cpu.apic) empty_element ("apic"); - if (config->cpu.pae) empty_element ("pae"); - } end_element (); - - start_element ("devices") { - - for (i = 0; config->disks[i] != NULL; ++i) { - char target_dev[64]; - - if (config->disks[i][0] == '/') { - target_sd: - memcpy (target_dev, "sd", 2); - guestfs_int_drive_name (i, &target_dev[2]); - } else { - if (strlen (config->disks[i]) <= sizeof (target_dev) - 1) - strcpy (target_dev, config->disks[i]); - else - goto target_sd; - } - - start_element ("disk") { - attribute ("type", "network"); - attribute ("device", "disk"); - start_element ("driver") { - attribute ("name", "qemu"); - attribute ("type", "raw"); - } end_element (); - start_element ("source") { - attribute ("protocol", "nbd"); - start_element ("host") { - attribute ("name", "localhost"); - attribute_format ("port", "%d", data_conns[i].nbd_remote_port); - } end_element (); - } end_element (); - start_element ("target") { - attribute ("dev", target_dev); - /* XXX Need to set bus to "ide" or "scsi" here. */ - } end_element (); - } end_element (); - } - - if (config->removable) { - for (i = 0; config->removable[i] != NULL; ++i) { - start_element ("disk") { - attribute ("type", "network"); - attribute ("device", "cdrom"); - start_element ("driver") { - attribute ("name", "qemu"); - attribute ("type", "raw"); - } end_element (); - start_element ("target") { - attribute ("dev", config->removable[i]); - } end_element (); - } end_element (); - } - } - - if (config->interfaces) { - for (i = 0; config->interfaces[i] != NULL; ++i) { - const char *target_network; - CLEANUP_FREE char *mac_filename = NULL; - CLEANUP_FREE char *mac = NULL; - - target_network - map_interface_to_network (config, config->interfaces[i]); - - if (asprintf (&mac_filename, "/sys/class/net/%s/address", - config->interfaces[i]) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - if (g_file_get_contents (mac_filename, &mac, NULL, NULL)) { - const size_t len = strlen (mac); - - if (len > 0 && mac[len-1] == '\n') - mac[len-1] = '\0'; - } - - start_element ("interface") { - attribute ("type", "network"); - start_element ("source") { - attribute ("network", target_network); - } end_element (); - start_element ("target") { - attribute ("dev", config->interfaces[i]); - } end_element (); - if (mac) { - start_element ("mac") { - attribute ("address", mac); - } end_element (); - } - } end_element (); - } - } - - } end_element (); /* </devices> */ - - } end_element (); /* </domain> */ - - if (xmlTextWriterEndDocument (xo) == -1) - error (EXIT_FAILURE, errno, "xmlTextWriterEndDocument"); -} - -/** - * Using C<config-E<gt>network_map>, map the interface to a target - * network name. If no map is found, return C<default>. See - * L<virt-p2v(1)> documentation of C<"p2v.network"> for how the - * network map works. - * - * Note this returns a static string which is only valid as long as - * C<config-E<gt>network_map> is not freed. - */ -static const char * -map_interface_to_network (struct config *config, const char *interface) -{ - size_t i, len; - - if (config->network_map == NULL) - return "default"; - - for (i = 0; config->network_map[i] != NULL; ++i) { - /* The default map maps everything. */ - if (strchr (config->network_map[i], ':') == NULL) - return config->network_map[i]; - - /* interface: ? */ - len = strlen (interface); - if (STRPREFIX (config->network_map[i], interface) && - config->network_map[i][len] == ':') - return &config->network_map[i][len+1]; - } - - /* No mapping found. */ - return "default"; -} diff --git a/p2v/rtc.c b/p2v/rtc.c deleted file mode 100644 index 28884fcc0..000000000 --- a/p2v/rtc.c +++ /dev/null @@ -1,165 +0,0 @@ -/* virt-p2v - * 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. - */ - -/** - * Try to calculate Real Time Clock (RTC) offset from UTC in seconds. - * For example if the RTC is 1 hour ahead of UTC, this will return - * C<3600>. This is stored in C<config-E<gt>rtc_offset>. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <fcntl.h> -#include <errno.h> -#include <libintl.h> -#include <time.h> -#include <sys/ioctl.h> - -#include <math.h> - -#ifdef HAVE_LINUX_RTC_H -#include <linux/rtc.h> -#endif - -#include "getprogname.h" -#include "ignore-value.h" - -#include "p2v.h" - -#ifndef HAVE_LINUX_RTC_H -void -get_rtc_config (struct rtc_config *rtc) -{ - fprintf (stderr, "%s: RTC: compiled without support for /dev/rtc\n", - getprogname ()); - - rtc->offset = 0; - rtc->basis = BASIS_UTC; -} - -#else /* HAVE_LINUX_RTC_H */ - -/** - * Return RTC offset from UTC in seconds, positive numbers meaning - * that the RTC is running ahead of UTC. - * - * In the error case, C<rtcE<gt>offset> is updated with 0 and - * C<rtcE<gt>basis> is set to C<BASIS_UNKNOWN>. - */ -void -get_rtc_config (struct rtc_config *rtc) -{ - int fd; - struct rtc_time rtm; - struct tm tm; - time_t rtc_time; - time_t system_time; - double rf; - - rtc->basis = BASIS_UNKNOWN; - rtc->offset = 0; - - fd = open ("/dev/rtc", O_RDONLY); - if (fd == -1) { - perror ("/dev/rtc"); - return; - } - - if (ioctl (fd, RTC_RD_TIME, &rtm) == -1) { - perror ("ioctl: RTC_RD_TIME"); - close (fd); - return; - } - - close (fd); - -#ifdef DEBUG_STDERR - fprintf (stderr, "%s: RTC: %04d-%02d-%02d %02d:%02d:%02d\n", - getprogname (), - rtm.tm_year + 1900, rtm.tm_mon + 1, rtm.tm_mday, - rtm.tm_hour, rtm.tm_min, rtm.tm_sec); -#endif - - /* Convert this to seconds since the epoch. */ - tm.tm_sec = rtm.tm_sec; - tm.tm_min = rtm.tm_min; - tm.tm_hour = rtm.tm_hour; - tm.tm_mday = rtm.tm_mday; - tm.tm_mon = rtm.tm_mon; - tm.tm_year = rtm.tm_year; - tm.tm_isdst = 0; /* Ignore DST when calculating. */ - rtc_time = timegm (&tm); - if (rtc_time == -1) - return; /* Not representable as a Unix time. */ - - /* Get system time in UTC. */ - system_time = time (NULL); - - /* Calculate the difference, rounded to the nearest 15 minutes. */ - rf = rtc_time - system_time; - -#ifdef DEBUG_STDERR - fprintf (stderr, "%s: RTC: %ld system time: %ld difference: %g\n", - getprogname (), - (long) rtc_time, (long) system_time, rf); -#endif - - rf /= 15*60; - rf = round (rf); - rf *= 15*60; - - /* If it's obviously out of range then print an error and return. */ - if (rf < -12*60*60 || rf > 14*60*60) { - fprintf (stderr, - "%s: RTC: offset of RTC from UTC is out of range (%g).\n", - getprogname (), rf); - return; - } - - rtc->offset = (int) rf; - -#ifdef DEBUG_STDERR - fprintf (stderr, "%s: RTC: offset of RTC from UTC = %d secs\n", - getprogname (), rtc->offset); -#endif - - /* Is the hardware clock set to localtime? - * - * Unfortunately it's not possible to distinguish between UTC and - * localtime in timezones that lie along the Greenwich Meridian - * (obviously including the UK), when daylight savings time is not - * in effect. In that case, prefer UTC. - */ - localtime_r (&system_time, &tm); - if (tm.tm_gmtoff != 0 && tm.tm_gmtoff != rtc->offset) - rtc->basis = BASIS_UTC; - else { - rtc->basis = BASIS_LOCALTIME; - rtc->offset = 0; -#ifdef DEBUG_STDERR - fprintf (stderr, "%s: RTC time is localtime\n", getprogname ()); -#endif - } - - return; -} - -#endif /* HAVE_LINUX_RTC_H */ diff --git a/p2v/ssh.c b/p2v/ssh.c deleted file mode 100644 index c8528033d..000000000 --- a/p2v/ssh.c +++ /dev/null @@ -1,1203 +0,0 @@ -/* virt-p2v - * Copyright (C) 2009-2019 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 file handles the ssh connections to the conversion server. - * - * virt-p2v will open several connections over the lifetime of - * the conversion process. - * - * In C<test_connection>, it will first open a connection (to check it - * is possible) and query virt-v2v on the server to ensure it exists, - * it is the right version, and so on. This connection is then - * closed, because in the GUI case we don't want to deal with keeping - * it alive in case the administrator has set up an autologout. - * - * Once we start conversion, we will open a control connection to send - * the libvirt configuration data and to start up virt-v2v, and we - * will open up one data connection per local hard disk. The data - * connection(s) have a reverse port forward to the local NBD server - * which is serving the content of that hard disk. The remote port - * for each data connection is assigned by ssh. See - * C<open_data_connection> and C<start_remote_conversion>. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <inttypes.h> -#include <unistd.h> -#include <errno.h> -#include <error.h> -#include <locale.h> -#include <assert.h> -#include <libintl.h> -#include <sys/types.h> -#include <sys/wait.h> - -#include "ignore-value.h" -#include "getprogname.h" - -#include "miniexpect.h" -#include "p2v.h" - -#define SSH_TIMEOUT 60 /* seconds */ - -char *v2v_version = NULL; -char **input_drivers = NULL; -char **output_drivers = NULL; - -static char *ssh_error; - -static void set_ssh_error (const char *fs, ...) - __attribute__((format(printf,1,2))); - -static void -set_ssh_error (const char *fs, ...) -{ - va_list args; - char *msg; - int len; - - va_start (args, fs); - len = vasprintf (&msg, fs, args); - va_end (args); - - if (len < 0) - error (EXIT_FAILURE, errno, - "vasprintf (original error format string: %s)", fs); - - free (ssh_error); - ssh_error = msg; -} - -const char * -get_ssh_error (void) -{ - return ssh_error; -} - -/* Like set_ssh_error, but for errors that aren't supposed to happen. */ -#define set_ssh_internal_error(fs, ...) \ - set_ssh_error ("%s:%d: internal error: " fs, __FILE__, __LINE__, \ - ##__VA_ARGS__) -#define set_ssh_mexp_error(fn) \ - set_ssh_internal_error ("%s: %m", fn) -#define set_ssh_pcre_error() \ - set_ssh_internal_error ("pcre error: %d\n", mexp_get_pcre_error (h)) - -#define set_ssh_unexpected_eof(fs, ...) \ - set_ssh_error ("remote server closed the connection unexpectedly, " \ - "waiting for: " fs, ##__VA_ARGS__) -#define set_ssh_unexpected_timeout(fs, ...) \ - set_ssh_error ("remote server timed out unexpectedly, " \ - "waiting for: " fs, ##__VA_ARGS__) - -static void compile_regexps (void) __attribute__((constructor)); -static void free_regexps (void) __attribute__((destructor)); - -static pcre *password_re; -static pcre *ssh_message_re; -static pcre *sudo_password_re; -static pcre *prompt_re; -static pcre *version_re; -static pcre *feature_libguestfs_rewrite_re; -static pcre *feature_colours_option_re; -static pcre *feature_input_re; -static pcre *feature_output_re; -static pcre *portfwd_re; - -static void -compile_regexps (void) -{ - const char *err; - int offset; - int p; - - /* These regexps are always used for partial matching. In pcre < 8 - * there were limitations on the regexps possible for partial - * matching, so fail if that is true here. In pcre >= 8, all - * regexps can be used in a partial match. - */ -#ifdef PCRE_INFO_OKPARTIAL -#define CHECK_PARTIAL_OK(pattern, re) \ - do { \ - pcre_fullinfo ((re), NULL, PCRE_INFO_OKPARTIAL, &p); \ - if (p != 1) { \ - fprintf (stderr, "%s: %s:%d: internal error: pattern '%s' cannot be used for partial matching\n", \ - getprogname (), \ - __FILE__, __LINE__, (pattern)); \ - abort (); \ - } \ - } while (0) -#else -#define CHECK_PARTIAL_OK(pattern, re) /* skip check */ -#endif - -#define COMPILE(re,pattern,options) \ - do { \ - re = pcre_compile ((pattern), (options), &err, &offset, NULL); \ - if (re == NULL) { \ - ignore_value (write (2, err, strlen (err))); \ - abort (); \ - } \ - CHECK_PARTIAL_OK ((pattern), re); \ - } while (0) - - COMPILE (password_re, "password:", 0); - /* Note that (?:.)* is required in order to work around a problem - * with partial matching and PCRE in RHEL 5. - */ - COMPILE (ssh_message_re, "(ssh: (?:.)*)", 0); - COMPILE (sudo_password_re, "sudo: a password is required", 0); - /* The magic synchronization strings all match this expression. See - * start_ssh function below. - */ - COMPILE (prompt_re, - "###((?:[0123456789abcdefghijklmnopqrstuvwxyz]){8})### ", 0); - /* Note that (?:.)* is required in order to work around a problem - * with partial matching and PCRE in RHEL 5. - */ - COMPILE (version_re, - "virt-v2v ([1-9](?:.)*)", - 0); - COMPILE (feature_libguestfs_rewrite_re, "libguestfs-rewrite", 0); - COMPILE (feature_colours_option_re, "colours-option", 0); - /* The input and output regexps must match the same pattern in - * v2v/modules_list.ml. - */ - COMPILE (feature_input_re, "input:((?:[-\\w])+)", 0); - COMPILE (feature_output_re, "output:((?:[-\\w])+)", 0); - COMPILE (portfwd_re, "Allocated port ((?:\\d)+) for remote forward", 0); -} - -static void -free_regexps (void) -{ - pcre_free (password_re); - pcre_free (ssh_message_re); - pcre_free (sudo_password_re); - pcre_free (prompt_re); - pcre_free (version_re); - pcre_free (feature_libguestfs_rewrite_re); - pcre_free (feature_colours_option_re); - pcre_free (feature_input_re); - pcre_free (feature_output_re); - pcre_free (portfwd_re); -} - -/** - * Download URL to local file using the external 'curl' command. - */ -static int -curl_download (const char *url, const char *local_file) -{ - char curl_config_file[] = "/tmp/curl.XXXXXX"; - char error_file[] = "/tmp/curlerr.XXXXXX"; - CLEANUP_FREE char *error_message = NULL; - int fd, r; - size_t i, len; - FILE *fp; - CLEANUP_FREE char *curl_cmd = NULL; - - fd = mkstemp (error_file); - if (fd == -1) - error (EXIT_FAILURE, errno, "mkstemp: %s", error_file); - close (fd); - - /* Use a secure curl config file because escaping is easier. */ - fd = mkstemp (curl_config_file); - if (fd == -1) - error (EXIT_FAILURE, errno, "mkstemp: %s", curl_config_file); - fp = fdopen (fd, "w"); - if (fp == NULL) - error (EXIT_FAILURE, errno, "fdopen: %s", curl_config_file); - fprintf (fp, "url = \""); - len = strlen (url); - for (i = 0; i < len; ++i) { - switch (url[i]) { - case '\\': fprintf (fp, "\\\\"); break; - case '"': fprintf (fp, "\\\""); break; - case '\t': fprintf (fp, "\\t"); break; - case '\n': fprintf (fp, "\\n"); break; - case '\r': fprintf (fp, "\\r"); break; - case '\v': fprintf (fp, "\\v"); break; - default: fputc (url[i], fp); - } - } - fprintf (fp, "\"\n"); - fclose (fp); - - /* Run curl to download the URL to a file. */ - if (asprintf (&curl_cmd, "curl -f -s -S -o %s -K %s 2>%s", - local_file, curl_config_file, error_file) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - r = system (curl_cmd); - /* unlink (curl_config_file); - useful for debugging */ - if (r == -1) - error (EXIT_FAILURE, errno, "system: %s", curl_cmd); - - /* Did curl subprocess fail? */ - if (WIFEXITED (r) && WEXITSTATUS (r) != 0) { - if (read_whole_file (error_file, &error_message, NULL) == 0) - set_ssh_error ("%s: %s", url, error_message); - else - set_ssh_error ("%s: curl error %d", url, WEXITSTATUS (r)); - unlink (error_file); - return -1; - } - else if (!WIFEXITED (r)) { - set_ssh_internal_error ("curl subprocess got a signal (%d)", r); - unlink (error_file); - return -1; - } - - unlink (error_file); - return 0; -} - -/** - * Re-cache the C<config-E<gt>identity.url> if needed. - */ -static int -cache_ssh_identity (struct config *config) -{ - int fd; - - /* If it doesn't need downloading, return. */ - if (config->auth.identity.url == NULL || - !config->auth.identity.file_needs_update) - return 0; - - /* Generate a random filename. */ - free (config->auth.identity.file); - config->auth.identity.file = strdup ("/tmp/id.XXXXXX"); - if (config->auth.identity.file == NULL) - error (EXIT_FAILURE, errno, "strdup"); - fd = mkstemp (config->auth.identity.file); - if (fd == -1) - error (EXIT_FAILURE, errno, "mkstemp"); - close (fd); - - /* Curl download URL to file. */ - if (curl_download (config->auth.identity.url, config->auth.identity.file) == -1) { - free (config->auth.identity.file); - config->auth.identity.file = NULL; - config->auth.identity.file_needs_update = 1; - return -1; - } - - return 0; -} - -/* GCC complains about the argv array in the next function which it - * thinks might grow to an unbounded size. Since we control - * extra_args, this is not in fact a problem. - */ -#if defined(__GNUC__) && GUESTFS_GCC_VERSION >= 40800 /* gcc >= 4.8.0 */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstack-usage=" -#endif - -/** - * Start ssh subprocess with the standard arguments and possibly some - * optional arguments. Also handles authentication. - */ -static mexp_h * -start_ssh (unsigned spawn_flags, struct config *config, - char **extra_args, int wait_prompt) -{ - size_t i = 0; - const size_t MAX_ARGS - 64 + (extra_args != NULL ? guestfs_int_count_strings (extra_args) : 0); - const char *argv[MAX_ARGS]; - char port_str[64]; - char connect_timeout_str[128]; - mexp_h *h; - const int ovecsize = 12; - int ovector[ovecsize]; - int saved_timeout; - int using_password_auth; - size_t count; - - if (cache_ssh_identity (config) == -1) - return NULL; - - /* Are we using password or identity authentication? */ - using_password_auth = config->auth.identity.file == NULL; - - ADD_ARG (argv, i, "ssh"); - ADD_ARG (argv, i, "-p"); /* Port. */ - snprintf (port_str, sizeof port_str, "%d", config->remote.port); - ADD_ARG (argv, i, port_str); - ADD_ARG (argv, i, "-l"); /* Username. */ - ADD_ARG (argv, i, config->auth.username ? config->auth.username : "root"); - ADD_ARG (argv, i, "-o"); /* Host key will always be novel. */ - ADD_ARG (argv, i, "StrictHostKeyChecking=no"); - ADD_ARG (argv, i, "-o"); /* ConnectTimeout */ - snprintf (connect_timeout_str, sizeof connect_timeout_str, - "ConnectTimeout=%d", SSH_TIMEOUT); - ADD_ARG (argv, i, connect_timeout_str); - ADD_ARG (argv, i, "-o"); /* Send ping packets every 5 mins to sshd. */ - ADD_ARG (argv, i, "ServerAliveInterval=300"); - ADD_ARG (argv, i, "-o"); - ADD_ARG (argv, i, "ServerAliveCountMax=6"); - if (using_password_auth) { - /* Only use password authentication. */ - ADD_ARG (argv, i, "-o"); - ADD_ARG (argv, i, "PreferredAuthentications=keyboard-interactive,password"); - } - else { - /* Use identity file (private key). */ - ADD_ARG (argv, i, "-o"); - ADD_ARG (argv, i, "PreferredAuthentications=publickey"); - ADD_ARG (argv, i, "-i"); - ADD_ARG (argv, i, config->auth.identity.file); - } - if (extra_args != NULL) { - for (size_t j = 0; extra_args[j] != NULL; ++j) - ADD_ARG (argv, i, extra_args[j]); - } - ADD_ARG (argv, i, config->remote.server); /* Conversion server. */ - ADD_ARG (argv, i, NULL); - -#if DEBUG_STDERR - fputs ("ssh command: ", stderr); - for (i = 0; argv[i] != NULL; ++i) { - if (i > 0) fputc (' ', stderr); - fputs (argv[i], stderr); - } - fputc ('\n', stderr); -#endif - - /* Create the miniexpect handle. */ - h = mexp_spawnvf (spawn_flags, "ssh", (char **) argv); - if (h == NULL) { - set_ssh_internal_error ("ssh: mexp_spawnvf: %m"); - return NULL; - } -#if DEBUG_STDERR - mexp_set_debug_file (h, stderr); -#endif - - /* We want the ssh ConnectTimeout to be less than the miniexpect - * timeout, so that if the server is completely unresponsive we - * still see the error from ssh, not a timeout from miniexpect. The - * obvious solution to this is to set ConnectTimeout (above) and to - * set the miniexpect timeout to be a little bit larger. - */ - mexp_set_timeout (h, SSH_TIMEOUT + 20); - - if (using_password_auth && - config->auth.password && strlen (config->auth.password) > 0) { - CLEANUP_FREE char *ssh_message = NULL; - - /* Wait for the password prompt. */ - wait_password_again: - switch (mexp_expect (h, - (mexp_regexp[]) { - { 100, .re = password_re }, - { 101, .re = ssh_message_re }, - { 0 } - }, ovector, ovecsize)) { - case 100: /* Got password prompt. */ - if (mexp_printf_password (h, "%s", config->auth.password) == -1 || - mexp_printf (h, "\n") == -1) { - set_ssh_mexp_error ("mexp_printf"); - mexp_close (h); - return NULL; - } - break; - - case 101: - free (ssh_message); - ssh_message = strndup (&h->buffer[ovector[2]], ovector[3]-ovector[2]); - goto wait_password_again; - - case MEXP_EOF: - /* This is where we get to if the user enters an incorrect or - * impossible hostname or port number. Hopefully ssh printed an - * error message, and we picked it up and put it in - * 'ssh_message' in case 101 above. If not we have to print a - * generic error instead. - */ - if (ssh_message) - set_ssh_error ("%s", ssh_message); - else - set_ssh_error ("ssh closed the connection without printing an error."); - mexp_close (h); - return NULL; - - case MEXP_TIMEOUT: - set_ssh_unexpected_timeout ("password prompt"); - mexp_close (h); - return NULL; - - case MEXP_ERROR: - set_ssh_mexp_error ("mexp_expect"); - mexp_close (h); - return NULL; - - case MEXP_PCRE_ERROR: - set_ssh_pcre_error (); - mexp_close (h); - return NULL; - } - } - - if (!wait_prompt) - return h; - - /* Ensure we are running bash, set environment variables, and - * synchronize with the command prompt and set it to a known - * string. There are multiple issues being solved here: - * - * We cannot control the initial shell prompt. It would involve - * changing the remote SSH configuration (AcceptEnv). However what - * we can do is to repeatedly send 'export PS1=<magic>' commands - * until we synchronize with the remote shell. - * - * Since we parse error messages, we must set LANG=C. - * - * We don't know if the user is using a Bourne-like shell (eg sh, - * bash) or csh/tcsh. Setting environment variables works - * differently. - * - * We don't know how command line editing is set up - * (https://bugzilla.redhat.com/1314244#c9). - */ - if (mexp_printf (h, "exec bash --noediting --noprofile\n") == -1) { - set_ssh_mexp_error ("mexp_printf"); - mexp_close (h); - return NULL; - } - - saved_timeout = mexp_get_timeout_ms (h); - mexp_set_timeout (h, 2); - - for (count = 0; count < 30; ++count) { - char magic[9]; - const char *matched; - int r; - - if (guestfs_int_random_string (magic, 8) == -1) { - set_ssh_internal_error ("random_string: %m"); - mexp_close (h); - return NULL; - } - - /* The purpose of the '' inside the string is to ensure we don't - * mistake the command echo for the prompt. - */ - if (mexp_printf (h, "export LANG=C PS1='###''%s''### '\n", magic) == -1) { - set_ssh_mexp_error ("mexp_printf"); - mexp_close (h); - return NULL; - } - - /* Wait for the prompt. */ - wait_again: - switch (mexp_expect (h, - (mexp_regexp[]) { - { 100, .re = password_re }, - { 101, .re = prompt_re }, - { 0 } - }, ovector, ovecsize)) { - case 100: /* Got password prompt unexpectedly. */ - set_ssh_error ("Login failed. Probably the username and/or password is wrong."); - mexp_close (h); - return NULL; - - case 101: - /* Got a prompt. However it might be an earlier prompt. If it - * doesn't match the PS1 string we sent, then repeat the expect. - */ - r = pcre_get_substring (h->buffer, ovector, - mexp_get_pcre_error (h), 1, &matched); - if (r < 0) - error (EXIT_FAILURE, 0, "pcre error reading substring (%d)", r); - r = STREQ (magic, matched); - pcre_free_substring (matched); - if (!r) - goto wait_again; - goto got_prompt; - - case MEXP_EOF: - set_ssh_unexpected_eof ("the command prompt"); - mexp_close (h); - return NULL; - - case MEXP_TIMEOUT: - /* Timeout here is not an error, since ssh may "eat" commands that - * we send before the shell at the other end is ready. Just loop. - */ - break; - - case MEXP_ERROR: - set_ssh_mexp_error ("mexp_expect"); - mexp_close (h); - return NULL; - - case MEXP_PCRE_ERROR: - set_ssh_pcre_error (); - mexp_close (h); - return NULL; - } - } - - set_ssh_error ("Failed to synchronize with remote shell after 60 seconds."); - mexp_close (h); - return NULL; - - got_prompt: - mexp_set_timeout_ms (h, saved_timeout); - - return h; -} - -#if defined(__GNUC__) && GUESTFS_GCC_VERSION >= 40800 /* gcc >= 4.8.0 */ -#pragma GCC diagnostic pop -#endif - -/** - * Upload file(s) to remote using L<scp(1)>. - * - * Note that the target (directory or file) comes before the list of - * local files, because the list of local files is a varargs list. - * - * This is a simplified version of L</start_ssh> above. - */ -int -scp_file (struct config *config, const char *target, const char *local, ...) -{ - size_t i = 0; - va_list args; - const size_t MAX_ARGS = 64; - const char *argv[MAX_ARGS]; - char port_str[64]; - char connect_timeout_str[128]; - CLEANUP_FREE char *remote = NULL; - mexp_h *h; - const int ovecsize = 12; - int ovector[ovecsize]; - int using_password_auth; - - if (cache_ssh_identity (config) == -1) - return -1; - - /* Are we using password or identity authentication? */ - using_password_auth = config->auth.identity.file == NULL; - - ADD_ARG (argv, i, "scp"); - ADD_ARG (argv, i, "-P"); /* Port. */ - snprintf (port_str, sizeof port_str, "%d", config->remote.port); - ADD_ARG (argv, i, port_str); - ADD_ARG (argv, i, "-o"); /* Host key will always be novel. */ - ADD_ARG (argv, i, "StrictHostKeyChecking=no"); - ADD_ARG (argv, i, "-o"); /* ConnectTimeout */ - snprintf (connect_timeout_str, sizeof connect_timeout_str, - "ConnectTimeout=%d", SSH_TIMEOUT); - ADD_ARG (argv, i, connect_timeout_str); - if (using_password_auth) { - /* Only use password authentication. */ - ADD_ARG (argv, i, "-o"); - ADD_ARG (argv, i, "PreferredAuthentications=keyboard-interactive,password"); - } - else { - /* Use identity file (private key). */ - ADD_ARG (argv, i, "-o"); - ADD_ARG (argv, i, "PreferredAuthentications=publickey"); - ADD_ARG (argv, i, "-i"); - ADD_ARG (argv, i, config->auth.identity.file); - } - - /* Source files or directories. - * Strictly speaking this could abort() if the list of files is - * too long, but that never happens in virt-p2v. XXX - */ - va_start (args, local); - do ADD_ARG (argv, i, local); - while ((local = va_arg (args, const char *)) != NULL); - va_end (args); - - /* The target file or directory. We need to rewrite this as - * "username@server:target". - */ - if (asprintf (&remote, "%s@%s:%s", - config->auth.username ? config->auth.username : "root", - config->remote.server, target) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - ADD_ARG (argv, i, remote); - - ADD_ARG (argv, i, NULL); - -#if DEBUG_STDERR - fputs ("scp command: ", stderr); - for (i = 0; argv[i] != NULL; ++i) { - if (i > 0) fputc (' ', stderr); - fputs (argv[i], stderr); - } - fputc ('\n', stderr); -#endif - - /* Create the miniexpect handle. */ - h = mexp_spawnv ("scp", (char **) argv); - if (h == NULL) { - set_ssh_internal_error ("scp: mexp_spawnv: %m"); - return -1; - } -#if DEBUG_STDERR - mexp_set_debug_file (h, stderr); -#endif - - /* We want the ssh ConnectTimeout to be less than the miniexpect - * timeout, so that if the server is completely unresponsive we - * still see the error from ssh, not a timeout from miniexpect. The - * obvious solution to this is to set ConnectTimeout (above) and to - * set the miniexpect timeout to be a little bit larger. - */ - mexp_set_timeout (h, SSH_TIMEOUT + 20); - - if (using_password_auth && - config->auth.password && strlen (config->auth.password) > 0) { - CLEANUP_FREE char *ssh_message = NULL; - - /* Wait for the password prompt. */ - wait_password_again: - switch (mexp_expect (h, - (mexp_regexp[]) { - { 100, .re = password_re }, - { 101, .re = ssh_message_re }, - { 0 } - }, ovector, ovecsize)) { - case 100: /* Got password prompt. */ - if (mexp_printf_password (h, "%s", config->auth.password) == -1 || - mexp_printf (h, "\n") == -1) { - set_ssh_mexp_error ("mexp_printf"); - mexp_close (h); - return -1; - } - break; - - case 101: - free (ssh_message); - ssh_message = strndup (&h->buffer[ovector[2]], ovector[3]-ovector[2]); - goto wait_password_again; - - case MEXP_EOF: - /* This is where we get to if the user enters an incorrect or - * impossible hostname or port number. Hopefully scp printed an - * error message, and we picked it up and put it in - * 'ssh_message' in case 101 above. If not we have to print a - * generic error instead. - */ - if (ssh_message) - set_ssh_error ("%s", ssh_message); - else - set_ssh_error ("scp closed the connection without printing an error."); - mexp_close (h); - return -1; - - case MEXP_TIMEOUT: - set_ssh_unexpected_timeout ("password prompt"); - mexp_close (h); - return -1; - - case MEXP_ERROR: - set_ssh_mexp_error ("mexp_expect"); - mexp_close (h); - return -1; - - case MEXP_PCRE_ERROR: - set_ssh_pcre_error (); - mexp_close (h); - return -1; - } - } - - /* Wait for the scp subprocess to finish. */ - switch (mexp_expect (h, NULL, NULL, 0)) { - case MEXP_EOF: - break; - - case MEXP_TIMEOUT: - set_ssh_unexpected_timeout ("copying (scp) file"); - mexp_close (h); - return -1; - - case MEXP_ERROR: - set_ssh_mexp_error ("mexp_expect"); - mexp_close (h); - return -1; - - case MEXP_PCRE_ERROR: - set_ssh_pcre_error (); - mexp_close (h); - return -1; - } - - if (mexp_close (h) == -1) { - set_ssh_internal_error ("scp: mexp_close: %m"); - return -1; - } - - return 0; -} - -static void add_input_driver (const char *name, size_t len); -static void add_output_driver (const char *name, size_t len); -static int compatible_version (const char *v2v_version); - -#pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn" /* WTF? */ -int -test_connection (struct config *config) -{ - mexp_h *h; - CLEANUP_FREE char *major_str = NULL, *minor_str = NULL, *release_str = NULL; - int feature_libguestfs_rewrite = 0; - int status; - const int ovecsize = 12; - int ovector[ovecsize]; - - h = start_ssh (0, config, NULL, 1); - if (h == NULL) - return -1; - - /* Clear any previous version information since we may be connecting - * to a different server. - */ - free (v2v_version); - v2v_version = NULL; - - /* Send 'virt-v2v --version' command and hope we get back a version string. - * Note old virt-v2v did not understand -V option. - */ - if (mexp_printf (h, - "%svirt-v2v --version\n", - config->auth.sudo ? "sudo -n " : "") == -1) { - set_ssh_mexp_error ("mexp_printf"); - mexp_close (h); - return -1; - } - - for (;;) { - switch (mexp_expect (h, - (mexp_regexp[]) { - { 100, .re = version_re }, - { 101, .re = sudo_password_re }, - { 102, .re = prompt_re }, - { 0 } - }, ovector, ovecsize)) { - case 100: /* Got version string. */ - free (v2v_version); - v2v_version = strndup (&h->buffer[ovector[2]], ovector[3]-ovector[2]); -#if DEBUG_STDERR - fprintf (stderr, "%s: remote virt-v2v version: %s\n", - getprogname (), v2v_version); -#endif - break; - - case 101: - set_ssh_error ("sudo for user \"%s\" requires a password. Edit /etc/sudoers on the conversion server to ensure the \"NOPASSWD:\" option is set for this user.", - config->auth.username); - mexp_close (h); - return -1; - - case 102: /* Got the prompt. */ - goto end_of_version; - - case MEXP_EOF: - set_ssh_unexpected_eof ("\"virt-v2v --version\" output"); - mexp_close (h); - return -1; - - case MEXP_TIMEOUT: - set_ssh_unexpected_timeout ("\"virt-v2v --version\" output"); - mexp_close (h); - return -1; - - case MEXP_ERROR: - set_ssh_mexp_error ("mexp_expect"); - mexp_close (h); - return -1; - - case MEXP_PCRE_ERROR: - set_ssh_pcre_error (); - mexp_close (h); - return -1; - } - } - end_of_version: - - /* Got the prompt but no version number. */ - if (v2v_version == NULL) { - set_ssh_error ("virt-v2v is not installed on the conversion server, " - "or it might be a too old version."); - mexp_close (h); - return -1; - } - - /* Check the version of virt-v2v is compatible with virt-p2v. */ - if (!compatible_version (v2v_version)) { - mexp_close (h); - return -1; - } - - /* Clear any previous driver information since we may be connecting - * to a different server. - */ - guestfs_int_free_string_list (input_drivers); - guestfs_int_free_string_list (output_drivers); - input_drivers = output_drivers = NULL; - - /* Get virt-v2v features. See: v2v/cmdline.ml */ - if (mexp_printf (h, "%svirt-v2v --machine-readable\n", - config->auth.sudo ? "sudo -n " : "") == -1) { - set_ssh_mexp_error ("mexp_printf"); - mexp_close (h); - return -1; - } - - for (;;) { - switch (mexp_expect (h, - (mexp_regexp[]) { - { 100, .re = feature_libguestfs_rewrite_re }, - { 101, .re = feature_colours_option_re }, - { 102, .re = feature_input_re }, - { 103, .re = feature_output_re }, - { 104, .re = prompt_re }, - { 0 } - }, ovector, ovecsize)) { - case 100: /* libguestfs-rewrite. */ - feature_libguestfs_rewrite = 1; - break; - - case 101: /* virt-v2v supports --colours option */ -#if DEBUG_STDERR - fprintf (stderr, "%s: remote virt-v2v supports --colours option\n", - getprogname ()); -#endif - feature_colours_option = 1; - break; - - case 102: - /* input:<driver-name> corresponds to an -i option in virt-v2v. */ - add_input_driver (&h->buffer[ovector[2]], - (size_t) (ovector[3]-ovector[2])); - break; - - case 103: - /* output:<driver-name> corresponds to an -o option in virt-v2v. */ - add_output_driver (&h->buffer[ovector[2]], - (size_t) (ovector[3]-ovector[2])); - break; - - case 104: /* Got prompt, so end of output. */ - goto end_of_machine_readable; - - case MEXP_EOF: - set_ssh_unexpected_eof ("\"virt-v2v --machine-readable\" output"); - mexp_close (h); - return -1; - - case MEXP_TIMEOUT: - set_ssh_unexpected_timeout ("\"virt-v2v --machine-readable\" output"); - mexp_close (h); - return -1; - - case MEXP_ERROR: - set_ssh_mexp_error ("mexp_expect"); - mexp_close (h); - return -1; - - case MEXP_PCRE_ERROR: - set_ssh_pcre_error (); - mexp_close (h); - return -1; - } - } - end_of_machine_readable: - - if (!feature_libguestfs_rewrite) { - set_ssh_error ("Invalid output of \"virt-v2v --machine-readable\" command."); - mexp_close (h); - return -1; - } - - /* Test finished, shut down ssh. */ - if (mexp_printf (h, "exit\n") == -1) { - set_ssh_mexp_error ("mexp_printf"); - mexp_close (h); - return -1; - } - - switch (mexp_expect (h, NULL, NULL, 0)) { - case MEXP_EOF: - break; - - case MEXP_TIMEOUT: - set_ssh_unexpected_timeout ("end of ssh session"); - mexp_close (h); - return -1; - - case MEXP_ERROR: - set_ssh_mexp_error ("mexp_expect"); - mexp_close (h); - return -1; - - case MEXP_PCRE_ERROR: - set_ssh_pcre_error (); - mexp_close (h); - return -1; - } - - status = mexp_close (h); - if (status == -1) { - set_ssh_internal_error ("mexp_close: %m"); - return -1; - } - if (WIFSIGNALED (status) && WTERMSIG (status) == SIGHUP) - return 0; /* not an error */ - if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) { - set_ssh_internal_error ("unexpected close status from ssh subprocess (%d)", - status); - return -1; - } - return 0; -} - -static void -add_option (const char *type, char ***drivers, const char *name, size_t len) -{ - size_t n; - - if (*drivers == NULL) - n = 0; - else - n = guestfs_int_count_strings (*drivers); - - n++; - - *drivers = realloc (*drivers, (n+1) * sizeof (char *)); - if (*drivers == NULL) - error (EXIT_FAILURE, errno, "malloc"); - - (*drivers)[n-1] = strndup (name, len); - if ((*drivers)[n-1] == NULL) - error (EXIT_FAILURE, errno, "strndup"); - (*drivers)[n] = NULL; - -#if DEBUG_STDERR - fprintf (stderr, "%s: remote virt-v2v supports %s driver %s\n", - getprogname (), type, (*drivers)[n-1]); -#endif -} - -static void -add_input_driver (const char *name, size_t len) -{ - add_option ("input", &input_drivers, name, len); -} - -static void -add_output_driver (const char *name, size_t len) -{ - /* Ignore the 'vdsm' driver, since that should only be used by VDSM. */ - if (len != 4 || memcmp (name, "vdsm", 4) != 0) - add_option ("output", &output_drivers, name, len); -} - -static int -compatible_version (const char *v2v_version) -{ - unsigned v2v_minor; - - /* The major version must always be 1. */ - if (!STRPREFIX (v2v_version, "1.")) { - set_ssh_error ("virt-v2v major version is not 1 (\"%s\"), " - "this version of virt-p2v is not compatible.", - v2v_version); - return 0; - } - - /* The version of virt-v2v must be >= 1.28, just to make sure - * someone isn't (a) using one of the experimental 1.27 releases - * that we published during development, nor (b) using old virt-v2v. - * We should remain compatible with any virt-v2v after 1.28. - */ - if (sscanf (v2v_version, "1.%u", &v2v_minor) != 1) { - set_ssh_internal_error ("cannot parse virt-v2v version string (\"%s\")", - v2v_version); - return 0; - } - - if (v2v_minor < 28) { - set_ssh_error ("virt-v2v version is < 1.28 (\"%s\"), " - "you must upgrade to virt-v2v >= 1.28 on " - "the conversion server.", v2v_version); - return 0; - } - - return 1; /* compatible */ -} - -mexp_h * -open_data_connection (struct config *config, - const char *local_ipaddr, int local_port, - int *remote_port) -{ - mexp_h *h; - char remote_arg[32]; - const char *extra_args[] = { - "-R", remote_arg, - "-N", - NULL - }; - CLEANUP_FREE char *port_str = NULL; - const int ovecsize = 12; - int ovector[ovecsize]; - - snprintf (remote_arg, sizeof remote_arg, "0:%s:%d", local_ipaddr, local_port); - - h = start_ssh (0, config, (char **) extra_args, 0); - if (h == NULL) - return NULL; - - switch (mexp_expect (h, - (mexp_regexp[]) { - { 100, .re = portfwd_re }, - { 0 } - }, ovector, ovecsize)) { - case 100: /* Ephemeral port. */ - port_str = strndup (&h->buffer[ovector[2]], ovector[3]-ovector[2]); - if (port_str == NULL) { - set_ssh_internal_error ("strndup: %m"); - mexp_close (h); - return NULL; - } - if (sscanf (port_str, "%d", remote_port) != 1) { - set_ssh_internal_error ("cannot extract the port number from '%s'", - port_str); - mexp_close (h); - return NULL; - } - break; - - case MEXP_EOF: - set_ssh_unexpected_eof ("\"ssh -R\" output"); - mexp_close (h); - return NULL; - - case MEXP_TIMEOUT: - set_ssh_unexpected_timeout ("\"ssh -R\" output"); - mexp_close (h); - return NULL; - - case MEXP_ERROR: - set_ssh_mexp_error ("mexp_expect"); - mexp_close (h); - return NULL; - - case MEXP_PCRE_ERROR: - set_ssh_pcre_error (); - mexp_close (h); - return NULL; - } - - return h; -} - -/* Wait for the prompt. */ -static int -wait_for_prompt (mexp_h *h) -{ - const int ovecsize = 12; - int ovector[ovecsize]; - - switch (mexp_expect (h, - (mexp_regexp[]) { - { 100, .re = prompt_re }, - { 0 } - }, ovector, ovecsize)) { - case 100: /* Got the prompt. */ - return 0; - - case MEXP_EOF: - set_ssh_unexpected_eof ("command prompt"); - return -1; - - case MEXP_TIMEOUT: - set_ssh_unexpected_timeout ("command prompt"); - return -1; - - case MEXP_ERROR: - set_ssh_mexp_error ("mexp_expect"); - return -1; - - case MEXP_PCRE_ERROR: - set_ssh_pcre_error (); - return -1; - } - - return 0; -} - -mexp_h * -start_remote_connection (struct config *config, const char *remote_dir) -{ - mexp_h *h; - - /* This connection is opened in cooked mode so that we can send ^C - * if the conversion needs to be cancelled. However that also means - * we must be careful not to accidentally send any control - * characters over this connection at other times. - */ - h = start_ssh (MEXP_SPAWN_COOKED_MODE, config, NULL, 1); - if (h == NULL) - return NULL; - - /* Create the remote directory. */ - if (mexp_printf (h, "mkdir %s\n", remote_dir) == -1) { - set_ssh_mexp_error ("mexp_printf"); - goto error; - } - - if (wait_for_prompt (h) == -1) - goto error; - - /* It's simplest to create the remote 'time' file by running the date - * command, as that won't send any special control characters. - */ - if (mexp_printf (h, "date > %s/time\n", remote_dir) == -1) { - set_ssh_mexp_error ("mexp_printf"); - goto error; - } - - if (wait_for_prompt (h) == -1) - goto error; - - return h; - - error: - mexp_close (h); - return NULL; -} diff --git a/p2v/test-virt-p2v-cmdline.sh b/p2v/test-virt-p2v-cmdline.sh deleted file mode 100755 index 2fbca1eb5..000000000 --- a/p2v/test-virt-p2v-cmdline.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash - -# libguestfs virt-p2v test script -# Copyright (C) 2015 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. - -# Test virt-p2v command line parsing in non-GUI mode. - -set -e - -$TEST_FUNCTIONS -skip_if_skipped - -out=test-virt-p2v-cmdline.out -rm -f $out - -# The Linux kernel command line. -$VG virt-p2v --cmdline='p2v.server=localhost p2v.port=123 p2v.username=user p2v.password=secret p2v.skip_test_connection p2v.name=test p2v.vcpus=4 p2v.memory=1G p2v.disks=sda,sdb,sdc p2v.removable=sdd p2v.interfaces=eth0,eth1 p2v.o=local p2v.oa=sparse p2v.oc=qemu:///session p2v.of=raw p2v.os=/var/tmp p2v.network=em1:wired,other p2v.dump_config_and_exit' > $out - -# For debugging purposes. -cat $out - -# Check the output contains what we expect. -grep "^remote\.server.*localhost" $out -grep "^remote\.port.*123" $out -grep "^auth\.username.*user" $out -grep "^auth\.sudo.*false" $out -grep "^guestname.*test" $out -grep "^vcpus.*4" $out -grep "^memory.*"$((1024*1024*1024)) $out -grep "^disks.*sda sdb sdc" $out -grep "^removable.*sdd" $out -grep "^interfaces.*eth0 eth1" $out -grep "^network_map.*em1:wired other" $out -grep "^output\.type.*local" $out -grep "^output\.allocation.*sparse" $out -grep "^output\.connection.*qemu:///session" $out -grep "^output\.format.*raw" $out -grep "^output\.storage.*/var/tmp" $out - -rm $out diff --git a/p2v/test-virt-p2v-docs.sh b/p2v/test-virt-p2v-docs.sh deleted file mode 100755 index d4942de4e..000000000 --- a/p2v/test-virt-p2v-docs.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# libguestfs -# Copyright (C) 2016 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. - -set -e - -$TEST_FUNCTIONS -skip_if_skipped - -$top_srcdir/podcheck.pl $srcdir/virt-p2v.pod virt-p2v diff --git a/p2v/test-virt-p2v-nbdkit.sh b/p2v/test-virt-p2v-nbdkit.sh deleted file mode 100755 index cf7a416bc..000000000 --- a/p2v/test-virt-p2v-nbdkit.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash - -# libguestfs virt-p2v test script -# Copyright (C) 2014-2019 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. - -# Test virt-p2v in non-GUI mode using nbdkit instead of qemu-nbd. - -set -e - -$TEST_FUNCTIONS -skip_if_skipped -skip_if_backend uml -skip_unless nbdkit file --version -skip_unless test -f fedora.img -skip_unless test -f blank-part.img - -f1="$abs_builddir/fedora.img" -f2="$abs_builddir/blank-part.img" - -d=test-virt-p2v-nbdkit.d -rm -rf $d -mkdir $d - -# We don't want the program under test to run real 'ssh' or 'scp'. -# They won't work. Therefore create dummy 'ssh' and 'scp' binaries. -pushd $d -ln -sf "$abs_srcdir/test-virt-p2v-ssh.sh" ssh -ln -sf "$abs_srcdir/test-virt-p2v-scp.sh" scp -popd -export PATH=$d:$PATH - -# Note that the PATH already contains the local virt-p2v & virt-v2v -# binaries under test (because of the ./run script). - -# The Linux kernel command line. -cmdline="p2v.server=localhost p2v.name=fedora p2v.disks=$f1,$f2 p2v.o=local p2v.os=$(pwd)/$d p2v.network=em1:wired,other p2v.post=" - -# Only use nbdkit, disable qemu-nbd. -$VG virt-p2v --cmdline="$cmdline" --nbd=nbdkit,nbdkit-no-sa - -# Test the libvirt XML metadata and a disk was created. -test -f $d/fedora.xml -test -f $d/fedora-sda -test -f $d/fedora-sdb - -rm -r $d diff --git a/p2v/test-virt-p2v-pxe.sh b/p2v/test-virt-p2v-pxe.sh deleted file mode 100755 index bad41886e..000000000 --- a/p2v/test-virt-p2v-pxe.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/bash - -# libguestfs virt-p2v test script -# Copyright (C) 2014-2019 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. - -# Test virt-p2v in non-GUI mode with something resembling the -# PXE boot code path. This tests: -# * virt-p2v-make-disk -# * systemd p2v.service -# * launch-virt-p2v -# * networking -# * virt-p2v in kernel command-line mode - -set -e - -$TEST_FUNCTIONS -slow_test -skip_if_skipped -skip_if_backend uml -skip_unless_arch x86_64 - -qemu=qemu-system-x86_64 -skip_unless $qemu -help - -img="test-virt-p2v-pxe.img" -if ! test -f $img; then - echo "$0: test skipped because $img was not created" - exit 77 -fi - -skip_unless test -f fedora.img -f="$abs_builddir/fedora.img" - -d=test-virt-p2v-pxe.d -rm -rf $d -mkdir $d - -# Start the ssh server. Kill it if the script exits for any reason. -# Note you must use an absolute path to exec sshd. -`which sshd` -f test-virt-p2v-pxe.sshd_config -D -e & -sshd_pid=$! -cleanup () -{ - kill $sshd_pid -} -trap cleanup INT QUIT TERM EXIT ERR - -# Get the randomly assigned sshd port number. -port="$(grep ^Port test-virt-p2v-pxe.sshd_config | awk '{print $2}')" - -# Connect as the local user. -username="$(id -un)" - -# Output storage path. -os="$(cd $d; pwd)" - -# The Linux kernel command line. -cmdline="root=/dev/sda4 ro console=ttyS0 printk.time=1 p2v.server=10.0.2.2 p2v.port=$port p2v.username=$username p2v.identity=file:///var/tmp/id_rsa p2v.name=fedora p2v.o=local p2v.os=$os" - -# Run virt-p2v inside qemu. -$qemu \ - -no-user-config \ - -display none \ - -machine accel=kvm:tcg \ - -m 2048 \ - -kernel test-virt-p2v-pxe.vmlinuz \ - -initrd test-virt-p2v-pxe.initramfs \ - -append "$cmdline" \ - -boot c \ - -device virtio-scsi-pci,id=scsi \ - -drive file=$img,format=raw,snapshot=on,if=none,index=0,id=hd0 \ - -device scsi-hd,drive=hd0 \ - -drive file=$f,format=raw,snapshot=on,if=none,index=1,id=hd1 \ - -device scsi-hd,drive=hd1 \ - -netdev user,id=usernet \ - -device virtio-net-pci,netdev=usernet \ - -serial stdio - -# Test the libvirt XML metadata and a disk was created. -test -f $d/fedora.xml -test -f $d/fedora-sda - -rm -r $d diff --git a/p2v/test-virt-p2v-pxe.sshd_config.in b/p2v/test-virt-p2v-pxe.sshd_config.in deleted file mode 100644 index d6ce5789c..000000000 --- a/p2v/test-virt-p2v-pxe.sshd_config.in +++ /dev/null @@ -1,43 +0,0 @@ -# libguestfs virt-p2v test script -# Copyright (C) 2014-2019 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. - -# Minimal sshd_config used by test-virt-p2v-pxe.ssh when it runs -# a captive sshd. -# -# This file is processed by awk. See p2v/Makefile.am. - -# Choose a random high port number. -Port __RANDOM_PORT__ - -# Only allow connections from loopback. -ListenAddress [::1] -ListenAddress 127.0.0.1 - -# Privilege separation breaks non-root usage of sshd. -UsePrivilegeSeparation no - -# Use local files instead of inaccessible global configuration. -PidFile __abs_builddir__/test-virt-p2v-pxe.sshd.pid -HostKey __abs_builddir__/test-virt-p2v-pxe.ssh_host_rsa_key - -AuthorizedKeysFile __abs_builddir__/test-virt-p2v-pxe.authorized_keys - -# Don't check file permissions. -StrictModes no - -# Allow the environment to be set in the authorized_keys file above. -PermitUserEnvironment yes diff --git a/p2v/test-virt-p2v-scp.sh b/p2v/test-virt-p2v-scp.sh deleted file mode 100755 index 53f9781fc..000000000 --- a/p2v/test-virt-p2v-scp.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -# Copyright (C) 2014-2019 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 is an scp substitute used by test-virt-p2v.sh. - -TEMP=`getopt \ - -o 'o:P:' \ - -- "$@"` -if [ $? != 0 ]; then - echo "$0: problem parsing the command line arguments" - exit 1 -fi -eval set -- "$TEMP" - -while true ; do - case "$1" in - # Regular arguments that we can just ignore. - -o|-P) - shift 2 - ;; - - --) - shift - break - ;; - *) - echo "$0: internal error ($1)" - exit 1 - ;; - esac -done - -# Hopefully there are >= two arguments left, the source (local) -# file(s) and a remote file of the form user@server:remote. -if [ $# -lt 2 ]; then - echo "$0: incorrect number of arguments found:" "$@" - exit 1 -fi - -# https://stackoverflow.com/questions/1853946/getting-the-last-argument-passed-to-a-shell-script/1854031#1854031 -remote="${@: -1}" -# https://stackoverflow.com/questions/20398499/remove-last-argument-from-argument-list-of-shell-script-bash/26163980#26163980 -set -- "${@:1:$(($#-1))}" - -remote="$(echo $remote | awk -F: '{print $2}')" - -# Use the copy command. -exec cp "$@" "$remote" diff --git a/p2v/test-virt-p2v-ssh.sh b/p2v/test-virt-p2v-ssh.sh deleted file mode 100755 index 79dc883c3..000000000 --- a/p2v/test-virt-p2v-ssh.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -# Copyright (C) 2014 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 is an ssh substitute used by test-virt-p2v.sh. - -TEMP=`getopt \ - -o 'l:No:p:R:' \ - -- "$@"` -if [ $? != 0 ]; then - echo "$0: problem parsing the command line arguments" - exit 1 -fi -eval set -- "$TEMP" - -while true ; do - case "$1" in - # Regular arguments that we can just ignore. - -N) - shift - ;; - -l|-o|-p) - shift 2 - ;; - - # ssh -R 0:localhost:<port> (port forwarding). Don't actually - # port forward, just return the original port number here so that - # the conversion process connects directly to qemu-nbd. - -R) - arg="$2" - port="$(echo $arg | awk -F: '{print $3}')" - echo "Allocated port" $port "for remote forward" - shift 2 - ;; - - --) - shift - break - ;; - *) - echo "$0: internal error ($1)" - exit 1 - ;; - esac -done - -# Now run the interactive shell. -exec bash diff --git a/p2v/test-virt-p2v.sh b/p2v/test-virt-p2v.sh deleted file mode 100755 index a6b07274e..000000000 --- a/p2v/test-virt-p2v.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -# libguestfs virt-p2v test script -# Copyright (C) 2014 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. - -# Test virt-p2v in non-GUI mode. - -set -e - -$TEST_FUNCTIONS -skip_if_skipped -skip_if_backend uml -skip_unless test -f fedora.img -skip_unless test -f blank-part.img - -f1="$abs_builddir/fedora.img" -f2="$abs_builddir/blank-part.img" - -d=test-virt-p2v.d -rm -rf $d -mkdir $d - -# We don't want the program under test to run real 'ssh' or 'scp'. -# They won't work. Therefore create dummy 'ssh' and 'scp' binaries. -pushd $d -ln -sf "$abs_srcdir/test-virt-p2v-ssh.sh" ssh -ln -sf "$abs_srcdir/test-virt-p2v-scp.sh" scp -popd -export PATH=$d:$PATH - -# Note that the PATH already contains the local virt-p2v & virt-v2v -# binaries under test (because of the ./run script). - -# The Linux kernel command line. -cmdline="p2v.server=localhost p2v.name=fedora p2v.disks=$f1,$f2 p2v.o=local p2v.os=$(pwd)/$d p2v.network=em1:wired,other p2v.post=" - -$VG virt-p2v --cmdline="$cmdline" - -# Test the libvirt XML metadata and a disk was created. -test -f $d/fedora.xml -test -f $d/fedora-sda -test -f $d/fedora-sdb - -rm -r $d diff --git a/p2v/utils.c b/p2v/utils.c deleted file mode 100644 index 4b5e72390..000000000 --- a/p2v/utils.c +++ /dev/null @@ -1,256 +0,0 @@ -/* virt-p2v - * Copyright (C) 2015 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. - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <inttypes.h> -#include <string.h> -#include <ctype.h> -#include <unistd.h> -#include <errno.h> -#include <error.h> -#include <locale.h> -#include <libintl.h> - -#include "ignore-value.h" - -#include "p2v.h" - -#define CHOMP(line,len) \ - do { \ - if ((len) > 0 && (line)[(len)-1] == '\n') { \ - (line)[(len)-1] = '\0'; \ - len--; \ - } \ - } while (0) - -/** - * Return size of a block device, from F</sys/block/I<dev>/size>. - * - * This function always succeeds, or else exits (since we expect - * C<dev> to always be valid and the C<size> file to always exist). - */ -uint64_t -get_blockdev_size (const char *dev) -{ - CLEANUP_FCLOSE FILE *fp = NULL; - CLEANUP_FREE char *path = NULL; - CLEANUP_FREE char *size_str = NULL; - size_t len; - uint64_t size; - - if (asprintf (&path, "/sys/block/%s/size", dev) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - - fp = fopen (path, "r"); - if (fp == NULL) - error (EXIT_FAILURE, errno, "fopen: %s", path); - if (getline (&size_str, &len, fp) == -1) - error (EXIT_FAILURE, errno, "getline: %s", path); - - if (sscanf (size_str, "%" SCNu64, &size) != 1) - error (EXIT_FAILURE, 0, "cannot parse %s: %s", path, size_str); - - size /= 2*1024*1024; /* size from kernel is given in sectors? */ - return size; -} - -/** - * Return model of a block device, from F</sys/block/I<dev>/device/model>. - * - * Returns C<NULL> if the file was not found. The caller must - * free the returned string. - */ -char * -get_blockdev_model (const char *dev) -{ - CLEANUP_FCLOSE FILE *fp = NULL; - CLEANUP_FREE char *path = NULL; - char *model = NULL; - size_t len = 0; - ssize_t n; - - if (asprintf (&path, "/sys/block/%s/device/model", dev) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - fp = fopen (path, "r"); - if (fp == NULL) { - perror (path); - return NULL; - } - if ((n = getline (&model, &len, fp)) == -1) { - perror (path); - free (model); - return NULL; - } - CHOMP (model, n); - return model; -} - -/** - * Return the serial number of a block device. - * - * This is found using the lsblk command. - * - * Returns C<NULL> if we could not get the serial number. The caller - * must free the returned string. - */ -char * -get_blockdev_serial (const char *dev) -{ - CLEANUP_PCLOSE FILE *fp = NULL; - CLEANUP_FREE char *cmd = NULL; - char *serial = NULL; - size_t len = 0; - ssize_t n; - - if (asprintf (&cmd, "lsblk -o serial /dev/%s --nodeps --noheadings", - dev) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - fp = popen (cmd, "r"); - if (fp == NULL) { - perror (cmd); - return NULL; - } - if ((n = getline (&serial, &len, fp)) == -1) { - perror (cmd); - free (serial); - return NULL; - } - CHOMP (serial, n); - return serial; -} - -/** - * Return contents of F</sys/class/net/I<if_name>/address> (if found). - */ -char * -get_if_addr (const char *if_name) -{ - CLEANUP_FCLOSE FILE *fp = NULL; - CLEANUP_FREE char *path = NULL; - char *content = NULL; - size_t len = 0; - ssize_t n; - - if (asprintf (&path, "/sys/class/net/%s/address", if_name) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - fp = fopen (path, "r"); - if (fp == NULL) - return NULL; - if ((n = getline (&content, &len, fp)) == -1) { - perror (path); - free (content); - return NULL; - } - CHOMP (content, n); - return content; -} - -/** - * Return contents of F</sys/class/net/I<if_name>/device/vendor> (if - * found), mapped to the PCI vendor. See: - * L<http://pjwelsh.blogspot.co.uk/2011/11/howto-get-network-card-vendor-device-or.html> - */ -char * -get_if_vendor (const char *if_name, int truncate) -{ - CLEANUP_FCLOSE FILE *fp = NULL; - CLEANUP_FREE char *path = NULL; - char *line = NULL; - size_t len = 0; - ssize_t n; - char vendor[5]; - - if (asprintf (&path, "/sys/class/net/%s/device/vendor", if_name) == -1) - error (EXIT_FAILURE, errno, "asprintf"); - fp = fopen (path, "r"); - if (fp == NULL) { - perror (path); - return NULL; - } - if ((n = getline (&line, &len, fp)) == -1) { - perror (path); - free (line); - return NULL; - } - - /* Vendor is (always?) a 16 bit quantity (as defined by PCI), - * something like "0x8086" (for Intel Corp). - */ - CHOMP (line, n); - if (line[0] != '0' || line[1] != 'x' || strlen (&line[2]) != 4) { - free (line); - return NULL; - } - - strcpy (vendor, &line[2]); - - fclose (fp); - fp = fopen ("/usr/share/hwdata/pci.ids", "r"); - if (fp == NULL) { - perror ("/usr/share/hwdata/pci.ids"); - free (line); - return NULL; - } - while ((n = getline (&line, &len, fp)) != -1) { - CHOMP (line, n); - if (STRPREFIX (line, vendor)) { - /* Find the start of the name after the vendor ID and whitespace. */ - size_t i = 4; - n -= 4; - - while (n > 0 && isspace (line[i])) { - i++; - n--; - } - - memmove (&line[0], &line[i], n+1 /* copy trailing \0 */); - - /* Truncate? */ - if (truncate > 0 && n > truncate) - line[n] = '\0'; - - return line; - } - } - - free (line); - return NULL; -} - -/* XXX We could make this configurable. */ -#define NETWORK_ONLINE_COMMAND "nm-online -t 30" - -/** - * Wait for the network to come online, but don't error out if that - * fails. The caller will call C<test_connection> immediately after - * this which will fail if the network didn't come online. - */ -void -wait_network_online (const struct config *config) -{ -#ifdef DEBUG_STDERR - fprintf (stderr, "waiting for the network to come online ...\n"); - fprintf (stderr, "%s\n", NETWORK_ONLINE_COMMAND); - fflush (stderr); -#endif - - ignore_value (system (NETWORK_ONLINE_COMMAND)); -} diff --git a/p2v/virt-p2v-make-disk.in b/p2v/virt-p2v-make-disk.in deleted file mode 100644 index 4cf8f5661..000000000 --- a/p2v/virt-p2v-make-disk.in +++ /dev/null @@ -1,267 +0,0 @@ -#!/bin/bash - -# @configure_input@ -# virt-p2v-make-disk -# Copyright (C) 2014-2019 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. - -unset CDPATH - -program="virt-p2v-make-disk" -version="@PACKAGE_VERSION@" - -if [ -n "$VIRT_P2V_DATA_DIR" ]; then - datadir="$VIRT_P2V_DATA_DIR" - libdir="$VIRT_P2V_DATA_DIR" -else - datadir="@datadir@/virt-p2v" - libdir="@libdir@/virt-p2v" -fi - -# Parse the command line arguments. -shortopts=o:vV -longopts=arch:,help,short-options,inject-ssh-identity:,install:,long-options,no-warn-if-partition,output:,verbose,version -TEMP=`getopt \ - -o "$shortopts" \ - --long "$longopts" \ - -n $program -- "$@"` -if [ $? != 0 ]; then - echo "$program: problem parsing the command line arguments" - exit 1 -fi -eval set -- "$TEMP" - -output-upload-verbose-declare -a passthru - -usage () -{ - echo "Usage:" - echo " $program [--options] -o /dev/sdX [os-version]" - echo - echo "Read $program(1) man page for more information." - exit $1 -} - -while true; do - case "$1" in - --arch) - arch="$2" - shift 2;; - --inject-ssh-identity) - upload="--upload $2:/var/tmp/id_rsa" - shift 2;; - -o|--output) - output="$2" - shift 2;; - -v|--verbose) - set +x - verbose=1 - shift;; - - # virt-builder parameters that are passed through. - --install) - passthru[${#passthru[*]}]="$1" - passthru[${#passthru[*]}]="$2" - shift 2;; - - --no-warn-if-partition) - passthru[${#passthru[*]}]="$1" - shift;; - - # help etc. - --help) - usage 0;; - -V|--version) - echo "$program $version" - exit 0;; - --short-options) - echo -n "$shortopts" | - @SED@ -e 's/://g' -e 's/\(.\)/-\1\n/g' - exit 0;; - --long-options) - echo "$longopts" | - @SED@ -e 's/,/\n/g' -e 's/:$//mg' -e 's/\(.*\)/--\1/mg' | - grep -v -E -- "--(short|long)-options" - exit 0;; - --) - shift - break;; - *) - echo "internal error ($1)" - exit 1;; - esac -done - -if [ -z "$output" ]; then - echo "$program: You must set the -o (--output) option." - exit 1 -fi - -if [ $# -gt 1 ]; then - echo "$program: Too many parameters. See $program(1)." - exit 1 -fi - -if [ $# -eq 1 ]; then - osversion="$1" -else - # If osversion was not set, then we must guess a good value - # based on the host distro. - if test -f /etc/os-release; then - osversion="`. /etc/os-release && echo ${ID}-${VERSION_ID}`" - fi - if [ "x$osversion" = "x" ]; then - echo "$program: unable to guess a suitable os-version." - echo "You must supply one on the command line and output of 'virt-builder -l'." - echo "See $program(1) for further details." - exit 1 - fi -fi - -if [ -n "$arch" ]; then - arch_option="--arch $arch" - virt_p2v_xz_binary="$libdir/virt-p2v.$arch.xz" -else - virt_p2v_xz_binary="$libdir/virt-p2v.xz" -fi - -if [ ! -f "$virt_p2v_xz_binary" ]; then - echo "$program: cannot find $virt_p2v_xz_binary" - if [ -n "$arch" ]; then - echo "You used the '--arch' option, so it’s likely that you will need to build" - echo "a virt-p2v.$arch binary yourself." - echo "See guestfs-building(1) section BUILDING i686 32 BIT VIRT-P2V for help." - fi - exit 1 -fi - -# Create a temporary directory and clean it up when we finish. -tmpdir="$(mktemp -d)" -cleanup () -{ - rm -rf $tmpdir -} -trap cleanup INT QUIT TERM EXIT ERR - -# Uncompress the virt-p2v binary into tmpdir. -virt_p2v_binary="$tmpdir/virt-p2v" -xzcat "$virt_p2v_xz_binary" > "$virt_p2v_binary" - -# Variations depending on the target distro. The main difference -# is in the list of distro packages we add to the base appliance. -case "$osversion" in - centos-*|fedora-*|rhel-*|scientificlinux-*|oraclelinux-*) - depsfile="$datadir/dependencies.redhat" - cat > $tmpdir/p2v.conf <<'EOF' -add_drivers+=" usb-storage " -EOF - cat > $tmpdir/post-install <<'EOF' -#!/bin/bash -# Rebuild the initramfs. -latest_version="$(cd /lib/modules; ls -1vr | head -1)" -dracut -v -f --kver $latest_version -EOF - # Double quotes because we want $tmpdir to be expanded: - extra_args=" - --selinux-relabel - --upload $tmpdir/p2v.conf:/etc/dracut.conf.d/ - --run $tmpdir/post-install - " - ;; - debian-*|ubuntu-*) - depsfile="$datadir/dependencies.debian" - cat > $tmpdir/policy-rc.d <<'EOF' -#!/bin/sh -# Avoid running daemons during the upgrade/installation -exit 101 -EOF - chmod +x $tmpdir/policy-rc.d - # Double quotes because we want $tmpdir to be expanded: - preinstall_args=" - --upload $tmpdir/policy-rc.d:/usr/sbin/policy-rc.d - " - final_args=" - --delete /usr/sbin/policy-rc.d - " - ;; - archlinux-*) - depsfile="$datadir/dependencies.archlinux" - ;; - opensuse-*|suse-*) - depsfile="$datadir/dependencies.suse" - ;; - *) - echo "$program: internal error: could not work out the Linux distro from '$osversion'" - exit 1 -esac - -# Virt-builder requires the dependencies to be comma-separated with -# no spaces. The $depsfile is one dependency per line. -if [ ! -f "$depsfile" ]; then - echo "$program: cannot find dependencies file ($depsfile)" - exit 1 -fi -install-while read line; do - if [ -n "$line" ]; then - if [ -z "$install" ]; then - install="$line" - else - install="$install,$line" - fi - fi -done < $depsfile - -# Add -v -x if we're in verbose mode. -if [ "x$verbose" = "x1" ]; then - verbose_option="-v -x" -fi - -# Run virt-builder. Note we controversially assume systemd here. We -# could provide a sysvinit fallback if required. -virt-builder "$osversion" \ - $verbose_option \ - --output "$output" \ - $arch_option \ - $preinstall_args \ - --update \ - --install "$install" \ - --root-password password:p2v \ - --upload "$datadir"/issue:/etc/issue \ - --upload "$datadir"/issue:/etc/issue.net \ - --mkdir /usr/bin \ - --upload "$virt_p2v_binary":/usr/bin/virt-p2v \ - --chmod 0755:/usr/bin/virt-p2v \ - --upload "$datadir"/launch-virt-p2v:/usr/bin/ \ - --chmod 0755:/usr/bin/launch-virt-p2v \ - --upload "$datadir"/p2v.service:/etc/systemd/system/ \ - --mkdir /etc/systemd/system/multi-user.target.wants \ - --link /etc/systemd/system/p2v.service:/etc/systemd/system/multi-user.target.wants/p2v.service \ - --edit '/lib/systemd/system/getty@.service: - s/^ExecStart=(.*)/ExecStart=$1 -a root/ - ' \ - --edit '/etc/systemd/logind.conf: - s/^[Login]/[Login]\nReserveVT=1\n/ - ' \ - $upload \ - $extra_args \ - "${passthru[@]}" \ - $final_args - -# We have to do this so the cleanup() handler runs. -exit $? diff --git a/p2v/virt-p2v-make-disk.pod b/p2v/virt-p2v-make-disk.pod deleted file mode 100644 index 05b8a3d9e..000000000 --- a/p2v/virt-p2v-make-disk.pod +++ /dev/null @@ -1,218 +0,0 @@ -=head1 NAME - -virt-p2v-make-disk - Build the virt-p2v disk using virt-builder - -=head1 SYNOPSIS - - virt-p2v-make-disk -o /dev/sdX [os-version] - -=head1 DESCRIPTION - -L<virt-p2v(1)> converts a physical machine to run virtualized on KVM, -managed by libvirt, OpenStack, oVirt, Red Hat Enterprise -Virtualisation (RHEV), or one of the other targets supported by -L<virt-v2v(1)>. - -virt-p2v-make-disk is a script which creates a bootable disk image or -USB key containing virt-p2v. It uses L<virt-builder(1)> to do this, -and is just a small shell script around virt-builder. - -The required I<-o> parameter specifies where the output should go, for -example to a USB key (eg. C<-o /dev/sdX>) or to a file. If you pass a -device name, then B<the existing contents of the device will be erased>. - -=head2 C<os-version> parameter - -The optional C<os-version> parameter is the base Linux distro to use -for the operating system on the ISO. If you don't set this parameter, -the script tries to choose a suitable default for you. Most users -should I<not> use the C<os-version> parameter. - -The base OS selected for virt-p2v is not related in any way to the OS -of the physical machine that you are trying to convert. - -To list possible C<os-version> combinations, do: - - virt-builder -l - -=head1 EXAMPLES - -Write a virt-p2v bootable USB key on F</dev/sdX> (any existing content -on F</dev/sdX> is erased): - - virt-p2v-make-disk -o /dev/sdX - -Write a virt-p2v bootable virtual disk image, and boot it under qemu: - - virt-p2v-make-disk -o /var/tmp/p2v.img - qemu-kvm -m 1024 -boot c \ - -drive file=/var/tmp/p2v.img,if=virtio,index=0 \ - -drive file=/var/tmp/guest.img,if=virtio,index=1 - -where F</var/tmp/guest.img> would be the disk image of some guest that -you want to convert (for testing only). - -=head1 ADDING EXTRA PACKAGES - -You can install extra packages using the I<--install> option. This -can be useful for making a more fully-featured virt-p2v disk with -extra tools for debugging and troubleshooting. Give a list of -packages, separated by commas. For example: - - virt-p2v-make-disk -o /var/tmp/p2v.img --install tcpdump,traceroute - -=head1 ADDING AN SSH IDENTITY - -You can inject an SSH identity (private key) file to the image using -the I<--inject-ssh-identity> option. - -First create a key pair. It must have an empty passphrase: - - ssh-keygen -t rsa -N '' -f id_rsa - -This creates a private key (C<id_rsa>) and a public key -(C<id_rsa.pub>) pair. The public key should be appended to the -C<authorized_keys> file on the virt-v2v conversion server (usually to -C</root/.ssh/authorized_keys>). - -The private key should be injected into the disk image and then -discarded: - - virt-p2v-make-disk [...] --inject-ssh-identity id_rsa - rm id_rsa - -When booting virt-p2v, specify the URL of the injected file like this: - - │ User name: [root_____________________________] │ - │ │ - │ Password: [ <leave this field blank> ] │ - │ │ - │ SSH Identity URL: [file:///var/tmp/id_rsa___________] │ - -or if using the kernel command line, add: - - p2v.identity=file:///var/tmp/id_rsa - -For more information, see L<virt-p2v(1)/SSH IDENTITIES>. - -=head1 32 BIT VIRT-P2V - -For improved compatibility with older hardware, virt-p2v-make-disk has -an I<--arch> option. The most useful setting (on x86-64 hosts) is -I<--arch i686>, which builds a 32 bit virt-p2v environment that will -work on older hardware. 32 bit virt-p2v can convert 64 bit physical -machines and can interoperate with 64 bit virt-v2v and 64 bit -hypervisors. - -This option requires that you have built F<virt-p2v.$arch> (ie. -usually F<virt-p2v.i686>) by some means, and that you install it next -to the ordinary F<virt-p2v> binary (eg. in F<$libdir/virt-p2v/> or -C<$VIRT_V2V_DATA_DIR>). This is outside the scope of this manual -page, but you can find some tips in -L<guestfs-building(1)/BUILDING i686 32 BIT VIRT-P2V>. - -=head1 OPTIONS - -=over 4 - -=item B<--help> - -Display help. - -=item B<--arch> ARCH - -Set the architecture of the virt-p2v ISO. See L</32 BIT VIRT-P2V> above. - -If this option is not supplied, then the default is to use the same -architecture as the host that is running virt-p2v-make-disk. - -=item B<--inject-ssh-identity> id_rsa - -Add an SSH identity (private key) file into the image. -See L</ADDING AN SSH IDENTITY> above. - -=item B<--install> pkg,pkg,... - -Add extra packages to the image. -See L</ADDING EXTRA PACKAGES> above. - -=item B<--no-warn-if-partition> - -Normally you should not write to a partition on a USB drive (ie. don’t -use S<C<-o /dev/sdX1>>, use S<C<-o /dev/sdX>> to make a bootable USB -drive). If you do this, virt-builder prints a warning. This option -suppresses that warning. - -=item B<-o> OUTPUT - -=item B<--output> OUTPUT - -Write output to C<OUTPUT>, which can be a local file or block device. -B<The existing contents of the device will be erased>. - -=item B<-v> - -=item B<--verbose> - -Enable verbose output. Use this if you need to debug problems with -the script or if you are filing a bug. - -=item B<-V> - -=item B<--version> - -Display version number and exit. - -=back - -=head1 FILES - -=over 4 - -=item F<$libdir/virt-p2v/virt-p2v.xz> - -The L<virt-p2v(1)> binary which is copied into the bootable disk -image. - -The location of the binary can be changed by setting the -C<VIRT_P2V_DATA_DIR> environment variable. - -=item F<$datadir/virt-p2v/issue> - -=item F<$datadir/virt-p2v/launch-virt-p2v.in> - -=item F<$datadir/virt-p2v/p2v.service> - -Various data files that are copied into the bootable disk image. - -The location of these files can be changed by setting the -C<VIRT_P2V_DATA_DIR> environment variable. - -=back - -=head1 ENVIRONMENT VARIABLES - -=over 4 - -=item C<VIRT_P2V_DATA_DIR> - -The directory where virt-p2v-make-disk looks for data files (see -L</FILES> above). If not set, a compiled-in location is used. - -=back - -=head1 SEE ALSO - -L<virt-p2v(1)>, -L<virt-p2v-make-kickstart(1)>, -L<virt-p2v-make-kiwi(1)>, -L<virt-v2v(1)>, -L<http://libguestfs.org/>. - -=head1 AUTHORS - -Richard W.M. Jones L<http://people.redhat.com/~rjones/> - -=head1 COPYRIGHT - -Copyright (C) 2009-2019 Red Hat Inc. diff --git a/p2v/virt-p2v-make-kickstart.in b/p2v/virt-p2v-make-kickstart.in deleted file mode 100644 index 97610cdd1..000000000 --- a/p2v/virt-p2v-make-kickstart.in +++ /dev/null @@ -1,241 +0,0 @@ -#!/bin/bash - -# @configure_input@ -# virt-p2v-make-kickstart -# Copyright (C) 2014-2019 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. - -unset CDPATH - -program="virt-p2v-make-kickstart" -version="@PACKAGE_VERSION@" - -# Parse the command line arguments. -shortopts=o:vV -longopts=help,inject-ssh-identity:,install:,long-options,output:,proxy:,short-options,verbose,version -TEMP=`getopt \ - -o "$shortopts" \ - --long "$longopts" \ - -n $program -- "$@"` -if [ $? != 0 ]; then - echo "$program: problem parsing the command line arguments" - exit 1 -fi -eval set -- "$TEMP" - -usage () -{ - echo "Usage:" - echo " $program [--options] [-o p2v.ks] [--proxy=http://...] repo [repo...]" - echo - echo "Read $program(1) man page for more information." - exit $1 -} - -extra_packages-output=p2v.ks -proxy-ssh_identity-verbose- -while true; do - case "$1" in - --inject-ssh-identity) - ssh_identity="$2" - shift 2;; - --install) - extra_packages="${extra_packages:+${extra_packages},}$2" - shift 2;; - -o|--output) - output="$2" - shift 2;; - --proxy) - proxy="--proxy=$2" - shift 2;; - --repo) - repo="$2" - shift 2;; - -v|--verbose) - set +x - verbose=1 - shift;; - - # help etc. - --help) - usage 0;; - -V|--version) - echo "$program $version" - exit 0;; - --short-options) - echo -n "$shortopts" | - @SED@ -e 's/://g' -e 's/\(.\)/-\1\n/g' - exit 0;; - --long-options) - echo "$longopts" | - @SED@ -e 's/,/\n/g' -e 's/:$//mg' -e 's/\(.*\)/--\1/mg' | - grep -v -E -- "--(short|long)-options" - exit 0;; - --) - shift - break;; - *) - echo "internal error ($1)" - exit 1;; - esac -done - -if [ $# -lt 1 ]; then - echo "$program: Missing repo(s). See $program(1)." - exit 1 -fi - -set -e - -if [ -n "$VIRT_P2V_DATA_DIR" ]; then - datadir="$VIRT_P2V_DATA_DIR" - libdir="$VIRT_P2V_DATA_DIR" -else - datadir="@datadir@/virt-p2v" - libdir="@libdir@/virt-p2v" -fi - -# Base64-encode the files that we need to embed into the kickstart. -base64_issue="$(base64 $datadir/issue)" -base64_launch_virt_p2v="$(base64 $datadir/launch-virt-p2v)" -base64_p2v_service="$(base64 $datadir/p2v.service)" -if [ -n "$ssh_identity" ]; then - base64_ssh_identity="$(base64 $ssh_identity)" -else - base64_ssh_identity-fi - -# virt-p2v binary is too large unless we strip it and recompress it. -tmpfile="$(mktemp -u)" -xzcat $libdir/virt-p2v.xz > $tmpfile -md5sum_virt_p2v="$(md5sum $tmpfile | @AWK@ '{print $1}')" -strip --strip-all $tmpfile -gzip -9 $tmpfile -base64_virt_p2v="$(base64 $tmpfile.gz)" -rm $tmpfile.gz - -# Repositories. -repos-i=0 -for repo in "$@"; do - case "$repo" in - fedora) - repos="$repos -repo --name=fedora --mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=fedora-\$releasever\\\\&arch=\$basearch $proxy -" - ;; - rawhide) - repos="$repos -repo --name=rawhide --mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=rawhide\\\\&arch=\$basearch $proxy -" - ;; - koji) - repos="$repos -repo --name=koji --baseurl=http://koji.fedoraproject.org/repos/rawhide/latest/\$basearch/ $proxy -" - ;; - rhel-5.*) - minor=$( echo "$repo" | sed 's/rhel-[0-9]*\.\([0-9]*\)/\1/' ) - arch=`uname -m | sed 's/i[3456]86/i386/g'` - baseurl=http://download.devel.redhat.com/released/RHEL-5-Server/U$minor/$arch/os/Server/ - # Neither $basearch nor --proxy work in RHEL 5 kickstarts. - repos="$repos -repo --name=rhel5_${minor}_server --baseurl=$baseurl -" - ;; - rhel-6.*) - minor=$( echo "$repo" | sed 's/rhel-[0-9]*\.\([0-9]*\)/\1/' ) - baseurl=http://download.devel.redhat.com/released/RHEL-6/6.$minor - # '$basearch' cannot be used in kickstart, so: - arch=`uname -m` - repos="$repos -repo --name=rhel6_${minor}_server --baseurl=$baseurl/Server/$arch/os $proxy -repo --name=rhel6_${minor}_server_optional --baseurl=$baseurl/Server/optional/$arch/os $proxy -" - ;; - rhel-7.*) - minor=$( echo "$repo" | sed 's/rhel-[0-9]*\.\([0-9]*\)/\1/' ) - baseurl=http://download.devel.redhat.com/released/RHEL-7/7.$minor - # '$basearch' cannot be used in kickstart, so: - arch=`uname -m` - repos="$repos -repo --name=rhel7_${minor}_server --baseurl=$baseurl/Server/$arch/os $proxy -repo --name=rhel7_${minor}_server_optional --baseurl=$baseurl/Server-optional/$arch/os $proxy -" - ;; - *) - # A custom repo is just a URL. - ((i++)) ||: - repos="$repos -repo --name=custom$i --baseurl=$repo $proxy -" - ;; - esac -done - -# Dependencies. Since kickstart is Red Hat-specific, only include -# dependencies.redhat here. -depsfile="$datadir/dependencies.redhat" -if [ ! -f "$depsfile" ]; then - echo "$0: cannot find dependencies file ($depsfile)" - exit 1 -fi -dependencies-while read line; do - if [ -n "$line" ]; then - if [ -z "$dependencies" ]; then - dependencies="$line" - else - dependencies="$dependencies -$line" - fi - fi -done < $depsfile - -# Now generate the final kickstart, substituting as necessary. -# AWK FTW! -@AWK@ \ - -v "base64_issue=$base64_issue" \ - -v "base64_launch_virt_p2v=$base64_launch_virt_p2v" \ - -v "base64_p2v_service=$base64_p2v_service" \ - -v "base64_ssh_identity=$base64_ssh_identity" \ - -v "base64_virt_p2v=$base64_virt_p2v" \ - -v "dependencies=$dependencies" \ - -v "extra_packages=$extra_packages" \ - -v "md5sum_virt_p2v=$md5sum_virt_p2v" \ - -v "repos=$repos" \ - '{ - gsub (/__PACKAGE_NAME__/, "@PACKAGE_NAME@"); - gsub (/__PACKAGE_VERSION__/, "@PACKAGE_VERSION@"); - gsub (/__PACKAGE_VERSION_FULL__/, "@PACKAGE_VERSION_FULL@"); - gsub (/__BASE64_ISSUE__/, base64_issue); - gsub (/__BASE64_LAUNCH_VIRT_P2V__/, base64_launch_virt_p2v); - gsub (/__BASE64_P2V_SERVICE__/, base64_p2v_service); - gsub (/__BASE64_SSH_IDENTITY__/, base64_ssh_identity); - gsub (/__BASE64_VIRT_P2V__/, base64_virt_p2v); - gsub (/__DEPENDENCIES__/, dependencies); - gsub (/__EXTRA_PACKAGES__/, gensub (/,/, "\n", "g", extra_packages)); - gsub (/__MD5SUM_VIRT_P2V__/, md5sum_virt_p2v); - gsub (/__REPOS__/, repos); - print; - }' \ - $datadir/p2v.ks.in > $output-t -mv $output-t $output - -echo "Kickstart file written to $output" diff --git a/p2v/virt-p2v-make-kickstart.pod b/p2v/virt-p2v-make-kickstart.pod deleted file mode 100644 index f4abdf8d7..000000000 --- a/p2v/virt-p2v-make-kickstart.pod +++ /dev/null @@ -1,339 +0,0 @@ -=head1 NAME - -virt-p2v-make-kickstart - Build the virt-p2v kickstart - -=head1 SYNOPSIS - - virt-p2v-make-kickstart [-o p2v.ks] [--proxy=http://...] repo [repo...] - -=head1 DESCRIPTION - -L<virt-p2v(1)> converts a physical machine to run virtualized on KVM, -managed by libvirt, OpenStack, oVirt, Red Hat Enterprise -Virtualisation (RHEV), or one of the other targets supported by -L<virt-v2v(1)>. - -Kickstart is a format used by Red Hat-derived distributions (such as -Fedora, Red Hat Enterprise Linux, CentOS, Scientific Linux, and -others) to describe how to make live CDs, install the distro, make -"Spins" and so on. It is driven by a kickstart file. - -virt-p2v-make-kickstart builds a kickstart file which can be used to -build a bootable P2V ISO, live CD, USB key, or PXE image. This tool -only builds the kickstart file, but this manual page describes some of -the ways you can use the kickstart file. - -=head1 BUILDING THE KICKSTART FILE - -Using virt-p2v-make-kickstart is very simple: - - virt-p2v-make-kickstart fedora - -will build a kickstart file for Fedora. The kickstart file will be -called F<p2v.ks> and located in the current directory. - -The parameters are a list of one or more repositories. Some built-in -repositories are available: C<fedora>, C<rawhide>, C<koji> or -C<rhel-VERSION> (eg. C<rhel-7.1>). You can also use a URL as a -parameter to point to a repository, for example: - - virt-p2v-make-kickstart https://dl.fedoraproject.org/pub/fedora/linux/releases/21/Everything/x86_64/os/ - -To control the name of the output file, use the I<-o> parameter. To -tell kickstart to use a proxy server or web cache to download files, -use the I<--proxy> parameter. - -=head1 BUILDING A LIVE CD / ISO - -Once you have the kickstart file, you can use L<livecd-creator(8)> -to make a live CD: - - sudo livecd-creator p2v.ks - -Before running this note that you should probably run -C<livecd-creator> in a disposable virtual machine for these reasons: - -=over 4 - -=item * - -You have to disable SELinux when running the tool. - -=item * - -This tool has to be run as root, and has some nasty failure modes. - -=item * - -You can only create the exact same Live CD distro as the host -distro. Cross-builds will fail in strange ways (eg. RHBZ#1092327). - -=back - -=head1 BUILDING A FEDORA SPIN USING KOJI - -This requires C<spin-livecd> permissions on Koji, which are not given -out usually, even to Fedora packagers. However assuming you have been -given these permissions (or have your own Koji instance, I guess), -then you can do: - - koji spin-livecd [--scratch] virt-p2v 1.XX.YY rawhide x86_64 p2v.ks - -=over 4 - -=item * - -Add the C<--scratch> option to do a scratch build (recommended for -testing). - -=item * - -C<1.XX.YY> should match the libguestfs version - -=item * - -Instead of C<rawhide> you can use any Koji target. - -=back - -=head1 BUILDING A BOOTABLE USB KEY - -Use the L<livecd-iso-to-disk(8)> program to convert the ISO created -above to a USB key: - - sudo livecd-iso-to-disk livecd-p2v.iso /dev/sdX - -=head1 BUILDING A PXE BOOT IMAGE - -Use the C<livecd-iso-to-pxeboot> program to convert the ISO created -above to a PXE boot image. - - sudo livecd-iso-to-pxeboot livecd-p2v.iso - -This creates a C<tftpboot> subdirectory under the current directory -containing the files required to PXE boot virt-p2v: - - $ ls -1R tftpboot/ - tftpboot/: - initrd0.img - pxelinux.0 - pxelinux.cfg/ - vmlinuz0 - - tftpboot/pxelinux.cfg: - default - -=head1 32 OR 64 BIT VIRT-P2V? - -Virt-p2v can convert any 32 or 64 bit guest, regardless of whether -virt-p2v itself is built as a 32 or 64 bit binary. The only -restriction is that 64 bit virt-p2v cannot run on 32 bit hardware. - -Old virt-p2v 0.9 was always built as a 32 bit (i686) ISO. This meant -that the CD could be booted on any 32- or 64-bit i686 or x86-64 -hardware, and could convert any guest. The old virt-p2v ISO shipped -by Red Hat was based on Red Hat Enterprise Linux (RHEL) 6. - -Since RHEL 7 dropped support for 32 bit machines, current virt-p2v on -RHEL can only be built for 64 bit. It cannot run on old 32 bit only -hardware. - -Fedora virt-p2v ISOs are generally built for 32 bit, so like the old -RHEL 6-based virt-p2v 0.9 they can boot on any hardware. - -=head1 TESTING VIRT-P2V USING QEMU - -=head2 TESTING THE P2V ISO USING QEMU - -You can use qemu to test-boot the P2V ISO: - - qemu-kvm -m 1024 -hda /tmp/guest.img -cdrom /tmp/livecd-p2v.iso -boot d - -Note that C<-hda> is the (virtual) system that you want to convert -(for test purposes). It could be any guest type supported by -L<virt-v2v(1)>, including Windows or Red Hat Enterprise Linux. - -=head2 TESTING PXE SUPPORT USING QEMU - -=over 4 - -=item * - -Unpack the tftpboot directory into F</tmp> (so it appears as -F</tmp/tftpboot>). - -=item * - -Copy F<pxelinux.0> and F<ldlinux.c32> from syslinux (usually from -F</usr/share/syslinux>) into F</tmp/tftpboot>. - -=item * - -Adjust the C<APPEND> line in F</tmp/tftpboot/pxelinux.cfg/default> if -required. See L<virt-p2v(1)/KERNEL COMMAND LINE CONFIGURATION>. - -=item * - -Run qemu like this so that it acts as a TFTP and BOOTP server, -emulating a netboot: - - qemu-kvm \ - -m 4096 -hda /tmp/guest.img \ - -boot n \ - -netdev user,id=unet,tftp=/tmp/tftpboot,bootfile=/pxelinux.0 \ - -device virtio-net-pci,netdev=unet \ - -serial stdio - -Note that this requires considerably more memory because the PXE image -is loaded into memory. Also that qemu’s TFTP server is very slow and -the virt-p2v PXE image is very large, so it can appear to "hang" after -pxelinux starts up. - -=back - -=head1 ADDING EXTRA PACKAGES - -You can install extra packages using the I<--install> option. This -can be useful for making a more fully-featured virt-p2v disk with -extra tools for debugging and troubleshooting. Give a list of -packages, separated by commas. For example: - - virt-p2v-make-kickstart [...] --install tcpdump,traceroute - -=head1 ADDING AN SSH IDENTITY - -You can inject an SSH identity (private key) file to the kickstart and -hence into the ISO using the I<--inject-ssh-identity> option. Note -that you I<cannot> inject a key once the ISO has been built. - -First create a key pair. It must have an empty passphrase: - - ssh-keygen -t rsa -N '' -f id_rsa - -This creates a private key (C<id_rsa>) and a public key -(C<id_rsa.pub>) pair. The public key should be appended to the -C<authorized_keys> file on the virt-v2v conversion server (usually to -C</root/.ssh/authorized_keys>). - -The private key should be added to the kickstart file and then -discarded: - - virt-p2v-make-kickstart [...] --inject-ssh-identity id_rsa - rm id_rsa - -The ISO can then be built from the kickstart in the usual way (see -above), and it will contain the embedded SSH identity -(F</var/tmp/id_rsa>). - -When booting virt-p2v, specify the URL of the injected file like this: - - │ User name: [root_____________________________] │ - │ │ - │ Password: [ <leave this field blank> ] │ - │ │ - │ SSH Identity URL: [file:///var/tmp/id_rsa___________] │ - -or if using the kernel command line, add: - - p2v.identity=file:///var/tmp/id_rsa - -For more information, see L<virt-p2v(1)/SSH IDENTITIES>. - -=head1 OPTIONS - -=over 4 - -=item B<--help> - -Display help. - -=item B<--inject-ssh-identity> id_rsa - -Add an SSH identity (private key) file into the kickstart. -See L</ADDING AN SSH IDENTITY> above. - -=item B<--install> pkg,pkg,... - -Add extra packages to the kickstart C<%packages> section. -See L</ADDING EXTRA PACKAGES> above. - -=item B<-o> OUTPUT - -=item B<--output> OUTPUT - -Write kickstart to C<OUTPUT>. If not specified, the default is -F<p2v.ks> in the current directory. - -=item B<--proxy> URL - -Tell the kickstart to use a proxy server or web cache for downloads. - -=item B<-v> - -=item B<--verbose> - -Enable verbose output. Use this if you need to debug problems with -the script or if you are filing a bug. - -=item B<-V> - -=item B<--version> - -Display version number and exit. - -=back - -=head1 FILES - -=over 4 - -=item F<$libdir/virt-p2v/virt-p2v.xz> - -The L<virt-p2v(1)> binary which is copied into the kickstart file. - -The location of the binary can be changed by setting the -C<VIRT_P2V_DATA_DIR> environment variable. - -=item F<$datadir/virt-p2v/issue> - -=item F<$datadir/virt-p2v/launch-virt-p2v.in> - -=item F<$datadir/virt-p2v/p2v.ks.in> - -=item F<$datadir/virt-p2v/p2v.service> - -Various data files that are used to make the kickstart. - -The location of these files can be changed by setting the -C<VIRT_P2V_DATA_DIR> environment variable. - -=back - -=head1 ENVIRONMENT VARIABLES - -=over 4 - -=item C<VIRT_P2V_DATA_DIR> - -The directory where virt-p2v-make-kickstart looks for data files and -the virt-p2v binary (see L</FILES> above). If not set, a compiled-in -location is used. - -=back - -=head1 SEE ALSO - -L<virt-p2v(1)>, -L<virt-p2v-make-disk(1)>, -L<virt-v2v(1)>, -L<livecd-creator(8)>, -L<livecd-iso-to-disk(8)>, -L<http://libguestfs.org/>. - -=head1 AUTHORS - -Richard W.M. Jones L<http://people.redhat.com/~rjones/> - -=head1 COPYRIGHT - -Copyright (C) 2009-2019 Red Hat Inc. diff --git a/p2v/virt-p2v-make-kiwi.in b/p2v/virt-p2v-make-kiwi.in deleted file mode 100644 index 405b629de..000000000 --- a/p2v/virt-p2v-make-kiwi.in +++ /dev/null @@ -1,233 +0,0 @@ -#!/bin/bash - -# @configure_input@ -# virt-p2v-make-kiwi -# Copyright (C) 2016 SUSE. -# -# 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. - -unset CDPATH - -program="virt-p2v-make-kiwi" -version="@PACKAGE_VERSION@" - -# Parse the command line arguments. -shortopts=o:V -longopts=help,inject-ssh-identity:,long-options,output:,short-options,version -TEMP=`getopt \ - -o "$shortopts" \ - --long "$longopts" \ - -n $program -- "$@"` -if [ $? != 0 ]; then - echo "$program: problem parsing the command line arguments" - exit 1 -fi -eval set -- "$TEMP" - -usage () -{ - echo "Usage:" - echo " $program [--options] [-o kiwi-folder]" - echo - echo "Read $program(1) man page for more information." - exit $1 -} - -output=p2v.kiwi -ssh_identity- -while true; do - case "$1" in - --inject-ssh-identity) - ssh_identity="$2" - shift 2;; - -o|--output) - output="$2" - shift 2;; - - # help etc. - --help) - usage 0;; - -V|--version) - echo "$program $version" - exit 0;; - --short-options) - echo -n "$shortopts" | - @SED@ -e 's/://g' -e 's/\(.\)/-\1\n/g' - exit 0;; - --long-options) - echo "$longopts" | - @SED@ -e 's/,/\n/g' -e 's/:$//mg' -e 's/\(.*\)/--\1/mg' | - grep -v -E -- "--(short|long)-options" - exit 0;; - --) - shift - break;; - *) - echo "internal error ($1)" - exit 1;; - esac -done - -set -e - -if [ -n "$VIRT_P2V_DATA_DIR" ]; then - datadir="$VIRT_P2V_DATA_DIR" - libdir="$VIRT_P2V_DATA_DIR" -else - datadir="@datadir@/virt-p2v" - libdir="@libdir@/virt-p2v" -fi - -# Dependencies. Since kiwi is SUSE-specific, only include -# dependencies.suse here. -depsfile="$datadir/dependencies.suse" -if [ ! -f "$depsfile" ]; then - echo "$0: cannot find dependencies file ($depsfile)" - exit 1 -fi -dependencies-while read line; do - if [ -n "$line" ]; then - depname=$(echo $line | awk '{gsub(/ /, "", $0); print}') - pkg=" <package name=\"$depname\"/>" - if [ -z "$dependencies" ]; then - dependencies="$pkg" - else - dependencies="$dependencies -$pkg" - fi - fi -done < $depsfile - -# Compute the distro-dependent pieces for kiwi -branding-release_pkg-base_pattern-kiwi_boot-repos-. /etc/os-release -case "$NAME" in - SLES) - branding="SLE" - release_pkg="sles-release" - base_pattern="patterns-sles-Minimal" - case "$VERSION_ID" in - 12) - kiwi_boot="SLES12" - repos="http://download.suse.de/ibs/SUSE:/SLE-12:/Update/standard - http://download.suse.de/ibs/SUSE:/SLE-12:/GA/standard" - ;; - 12.1) - kiwi_boot="SLES12" - repos="http://download.suse.de/ibs/SUSE:/SLE-12-SP1:/Update/standard - http://download.suse.de/ibs/SUSE:/SLE-12-SP1:/GA/standard - http://download.suse.de/ibs/SUSE:/SLE-12:/Update/standard - http://download.suse.de/ibs/SUSE:/SLE-12:/GA/standard" - ;; - *) - echo "Unsupported distribution $NAME $VERSION_ID" - exit 1;; - esac;; - openSUSE*) - branding="openSUSE" - release_pkg="openSUSE-release" - base_pattern="patterns-openSUSE-base" - case "$VERSION" in - 13.1\ *) - kiwi_boot="13.1" - repos="obs://13.1/repo/oss" - ;; - 13.2\ *) - kiwi_boot="13.2" - repos="obs://13.2/repo/oss" - ;; - 42.1) - kiwi_boot="leap42.1" - repos="obs://leap/42.1/repo/oss" - ;; - *\ \(Tumbleweed\)) - kiwi_boot="leap42.1" - repos="obs://openSUSE:Factory/standard" - ;; - *) - echo "Unsupported distribution $NAME $VERSION_ID" - exit 1;; - esac;; - *) - echo "Unsupported distribution $NAME $VERSION" - exit 1;; -esac - -# Compute the repos -repos_xml-for repo in $repos; do - repos_xml=" <repository type=\"rpm-md\">\n <source path=\"$repo\"/>\n </repository>\n$repos_xml" -done - -mkdir $output -cp $datadir/kiwi-config.sh $output/config.sh - -mkdir -p $output/root/etc/sysconfig/network -cat >$output/root/etc/sysconfig/network/ifcfg-eth0 << EOF -BOOTPROTO='dhcp' -MTU='' -REMOTE_IPADDR='' -STARTMODE='onboot' -EOF - -mkdir -p $output/root/etc/systemd/system -cp $datadir/p2v.service $output/root/etc/systemd/system - -mkdir -p $output/root/etc/udev/rules.d -cat >$output/root/etc/udev/rules.d/70-persistent-net.rules <<EOF -SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="?*", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="?*", NAME="eth0" -EOF - -cp $datadir/issue $output/root/etc/issue - -mkdir -p $output/root/usr/bin -cp $datadir/launch-virt-p2v $output/root/usr/bin -xzcat $libdir/virt-p2v.xz > $output/root/usr/bin/virt-p2v - -if test "z$ssh_identity" != "z"; then - mkdir -p $output/root/var/tmp - cp $ssh_identity $output/root/var/tmp/id_rsa - chmod 0600 $output/root/var/tmp/id_rsa -fi - -# Now generate the final kiwi config, substituting as necessary. -@AWK@ \ - -v "dependencies=$dependencies" \ - -v "md5sum_virt_p2v=$md5sum_virt_p2v" \ - -v "branding=$branding" \ - -v "release_pkg=$release_pkg" \ - -v "base_pattern=$base_pattern" \ - -v "kiwi_boot=$kiwi_boot" \ - -v "repos=$repos_xml" \ - '{ - gsub (/__PACKAGE_NAME__/, "@PACKAGE_NAME@"); - gsub (/__PACKAGE_VERSION__/, "@PACKAGE_VERSION@"); - gsub (/__PACKAGE_VERSION_FULL__/, "@PACKAGE_VERSION_FULL@"); - gsub (/<!--__DEPENDENCIES__-->/, dependencies); - gsub (/__BRANDING__/, branding); - gsub (/__RELEASE_PKG__/, release_pkg); - gsub (/__BASE_PATTERN__/, base_pattern); - gsub (/__KIWI_BOOT__/, kiwi_boot); - gsub (/<!--__REPOS__-->/, repos); - print; - }' \ - $datadir/kiwi-config.xml.in > $output/config.xml - -echo "kiwi config folder written to $output" diff --git a/p2v/virt-p2v-make-kiwi.pod b/p2v/virt-p2v-make-kiwi.pod deleted file mode 100644 index d879d9774..000000000 --- a/p2v/virt-p2v-make-kiwi.pod +++ /dev/null @@ -1,184 +0,0 @@ -=head1 NAME - -virt-p2v-make-kiwi - Build the virt-p2v kiwi configuration - -=head1 SYNOPSIS - - virt-p2v-make-kiwi [--inject-ssh-identity path] [-o kiwi-folder] - -=head1 DESCRIPTION - -L<virt-p2v(1)> converts a physical machine to run virtualized on KVM, -managed by libvirt, OpenStack, oVirt, Red Hat Enterprise -Virtualisation (RHEV), or one of the other targets supported by -L<virt-v2v(1)>. - -Kiwi is a tool used mainly by SUSE Linux Enterprise and openSUSE to -build live CDs, make appliances and so on. It is driven by a few files -including an xml description of the machine. - -virt-p2v-make-kiwi builds a folder containing all the pieces needed for -kiwi to build a bootable P2V live CD ISO, USB key, or PXE image. This tool -only builds the kiwi configuration, but this manual page describes some of -the ways you can use the kiwi configuration. - -=head1 BUILDING THE KIWI CONFIGURATION - -Using virt-p2v-make-kiwi is very simple: - - virt-p2v-make-kiwi - -will build a kiwi configuration based on the current machine’s distribution. - -To control the name of the output folder, use the I<-o> parameter. - -=head1 BUILDING A LIVE CD / ISO - -Once you have the kiwi configuration folder, you can use L<kiwi(1)> to make a -live CD: - - sudo kiwi --build p2v.kiwi -d build --type iso - -Before running this, you may have to tweak the C<config.xml> file -to change the locale and keyboard mapping to the one you need. - -If running on a SUSE Linux Entreprise Server, add the path to your packages repositories -using the C<--ignore-repos> and C<--add-repo> kiwi parameters. - -The generated ISO image will be placed in the C<build> folder. - -=head1 BUILDING A BOOTABLE USB KEY - -Use the L<dd(1)> program to write the ISO created above to a USB key: - - sudo dd if=path/to/p2v.iso of=/dev/sdX - -=head1 BUILDING A PXE BOOT IMAGE - -To create a PXE boot image, run kiwi in such a way: - - sudo kiwi --build $PWD/p2v.kiwi -d build --add-profile netboot --type pxe - -For more details on how to use the generated image, report to the kiwi documentation -on PXE images: L<https://doc.opensuse.org/projects/kiwi/doc/#chap.pxe> - -=head1 ADDING AN SSH IDENTITY - -You can inject an SSH identity (private key) file to the kiwi config and -hence into the ISO using the I<--inject-ssh-identity> option. Note -that you I<cannot> inject a key once the ISO has been built. - -First create a key pair. It must have an empty passphrase: - - ssh-keygen -t rsa -N '' -f id_rsa - -This creates a private key (C<id_rsa>) and a public key -(C<id_rsa.pub>) pair. The public key should be appended to the -C<authorized_keys> file on the virt-v2v conversion server (usually to -C</root/.ssh/authorized_keys>). - -The private key should be added to the kiwi config and then -discarded: - - virt-p2v-make-kiwi [...] --inject-ssh-identity id_rsa - rm id_rsa - -The ISO can then be built from the kickstart in the usual way (see -above), and it will contain the embedded SSH identity -(F</var/tmp/id_rsa>). - -When booting virt-p2v, specify the URL of the injected file like this: - - │ User name: [root_____________________________] │ - │ │ - │ Password: [ <leave this field blank> ] │ - │ │ - │ SSH Identity URL: [file:///var/tmp/id_rsa___________] │ - -or if using the kernel command line, add: - - p2v.identity=file:///var/tmp/id_rsa - -For more information, see L<virt-p2v(1)/SSH IDENTITIES>. - -=head1 OPTIONS - -=over 4 - -=item B<--help> - -Display help. - -=item B<--inject-ssh-identity> id_rsa - -Add an SSH identity (private key) file into the kickstart. -See L</ADDING AN SSH IDENTITY> above. - -=item B<-o> OUTPUT - -=item B<--output> OUTPUT - -Write kiwi configuration to the C<OUTPUT> folder. If not specified, the default is -F<p2v.kiwi> in the current directory. - -=item B<-V> - -=item B<--version> - -Display version number and exit. - -=back - -=head1 FILES - -=over 4 - -=item F<$libdir/virt-p2v/virt-p2v.xz> - -The L<virt-p2v(1)> binary which is copied into the kiwi configuration. - -The location of the binary can be changed by setting the -C<VIRT_P2V_DATA_DIR> environment variable. - -=item F<$datadir/virt-p2v/issue> - -=item F<$datadir/virt-p2v/launch-virt-p2v.in> - -=item F<$datadir/virt-p2v/kiwi> - -=item F<$datadir/virt-p2v/p2v.service> - -Various data files that are used to make the kiwi appliance. - -The location of these files can be changed by setting the -C<VIRT_P2V_DATA_DIR> environment variable. - -=back - -=head1 ENVIRONMENT VARIABLES - -=over 4 - -=item C<VIRT_P2V_DATA_DIR> - -The directory where virt-p2v-make-kiwi looks for data files and -the virt-p2v binary (see L</FILES> above). If not set, a compiled-in -location is used. - -=back - -=head1 SEE ALSO - -L<virt-p2v(1)>, -L<virt-p2v-make-disk(1)>, -L<virt-v2v(1)>, -L<kiwi(1)>, -L<http://libguestfs.org/>. - -=head1 AUTHORS - -Cédric Bosdonnat - -=head1 COPYRIGHT - -Copyright (C) 2016 SUSE Ltd. diff --git a/p2v/virt-p2v.pod b/p2v/virt-p2v.pod deleted file mode 100644 index 758021134..000000000 --- a/p2v/virt-p2v.pod +++ /dev/null @@ -1,757 +0,0 @@ -=head1 NAME - -virt-p2v - Convert a physical machine to use KVM - -=head1 SYNOPSIS - - virt-p2v - - virt-p2v.iso - -=head1 DESCRIPTION - -Virt-p2v converts a physical machine to run virtualized on KVM, -managed by libvirt, OpenStack, oVirt, Red Hat Virtualisation (RHV), or -one of the other targets supported by L<virt-v2v(1)>. - -Normally you don’t run the virt-p2v program directly. Instead you -have to boot the physical machine using the bootable CD-ROM, ISO or -PXE image. This bootable image contains the virt-p2v binary and runs -it automatically. Booting from a CD-ROM/etc is required because the -disks which are being converted must be quiescent. It is not safe to -try to convert a running physical machine where other programs may be -modifying the disk content at the same time. - -This manual page documents running the virt-p2v program. To create -the bootable image you should look at L<virt-p2v-make-disk(1)> or -L<virt-p2v-make-kickstart(1)>. - -=head1 NETWORK SETUP - -Virt-p2v runs on the physical machine which you want to convert. It -has to talk to another server called the "conversion server" which -must have L<virt-v2v(1)> installed on it. It always talks to the -conversion server over SSH: - - ┌──────────────┐ ┌─────────────────┐ - │ virt-p2v │ │ virt-v2v │ - │ (physical │ ssh connection │ (conversion │ - │ server) ╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍▶ server) │ - └──────────────┘ └─────────────────┘ - -The virt-v2v program on the conversion server does the actual -conversion (physical to virtual, and virtual to virtual conversions -are sufficiently similar that we use the same program to do both). - -The SSH connection is always initiated from the physical server. All -data is transferred over the SSH connection. In terms of firewall and -network configuration, you only need to ensure that the physical -server has access to a port (usually TCP port 22) on the conversion -server. Note that the physical machine may reconnect several times -during the conversion process. - -The reverse port forwarding feature of ssh (ie. C<ssh -R>) is required -by virt-p2v, and it will not work if this is disabled on the -conversion server. (C<AllowTcpForwarding> must be C<yes> in the -L<sshd_config(5)> file on the conversion server). - -The scp (secure copy) feature of ssh is required by virt-p2v so it can -send over small files (this is I<not> the method by which disks are -copied). - -The conversion server does not need to be a physical machine. It -could be a virtual machine, as long as it has sufficient memory and -disk space to do the conversion, and as long as the physical machine -can connect directly to its SSH port. (See also -L<virt-v2v(1)/Resource requirements>). - -Because all of the data on the physical server’s hard drive(s) has to -be copied over the network, the speed of conversion is largely -determined by the speed of the network between the two machines. - -=head1 GUI INTERACTIVE CONFIGURATION - -When you start virt-p2v, you'll see a graphical configuration dialog -that walks you through connection to the conversion server, asks for -the password, which local hard disks you want to convert, and other -things like the name of the guest to create and the number of virtual -CPUs to give it. - -=head2 SSH CONFIGURATION DIALOG - -When virt-p2v starts up in GUI mode, the first dialog looks like this: - - ┌─────────────────────────────────────────────────────────────┐ - │ virt-p2v │ - │ │ - │ Conversion server: [____________________________] : [22___] │ - │ │ - │ User name: [root__________________________________] │ - │ │ - │ Password: [______________________________________] │ - │ │ - │ SSH Identity URL: [______________________________________] │ - │ │ - -In the fields above, you must enter the details of the conversion -server: the hostname, SSH port number, remote user name, and either -the password or SSH identity (private key) URL. The conversion server -must have an up to date version of virt-v2v. - -Normally you must log in to the conversion server as root, but if you -check the following box: - - │ │ - │ [ ] Use sudo when running virt-v2v │ - │ │ - -then you can log in as another user, and virt-p2v will use the -L<sudo(8)> command to elevate privileges to root. Note that -sudo must not require a password. - -It is also possible to run virt-v2v on the conversion server entirely -as non-root, but output modes may be limited. Consult the -L<virt-v2v(1)> manual page for details. - -At the bottom of the dialog are these buttons: - - │ │ - │ [ Test connection ] │ - │ │ - │ [ Configure network ] [ XTerm ] [ About virt-p2v ] [ Next ] │ - │ │ - └─────────────────────────────────────────────────────────────┘ - -You must press the C<Test connection> button first to test the SSH -connection to the conversion server. If that is successful (ie. you -have supplied the correct server name, user name, password, etc., and -a suitable version of virt-v2v is available remotely) then press the -C<Next> button to move to the next dialog. - -You can use the C<Configure network> button if you need to assign a -static IP address to the physical machine, or use Wifi, bonding or -other network features. - -The C<XTerm> button opens a shell which can be used for diagnostics, -manual network configuration, and so on. - -=head2 DISK AND NETWORK CONFIGURATION DIALOG - -The second configuration dialog lets you configure the details of -conversion, including what to convert and where to send the guest. - -In the left hand column, starting at the top, the target properties -let you select the name of the guest (ie. after conversion) and how -many virtual CPUs and how much RAM to give it. The defaults come from -the physical machine, and you can usually leave them unchanged: - - ┌─────────────────────────────────────── ─ ─ ─ ─ - │ Target properties: - │ - │ Name: [hostname______________] - │ - │ # vCPUs: [4_____________________] - │ - │ Memory (MB): [16384_________________] - │ - -The second panel on the left controls the virt-v2v output options. To -understand these options it is a really good idea to read the -L<virt-v2v(1)> manual page. You can leave the options at the default -to create a guest as a disk image plus libvirt XML file located in -F</var/tmp> on the conversion host. This is a good idea if you are a -first-time virt-p2v user. - - │ - │ Virt-v2v output options: - │ - │ Output to (-o): [local ▼] - │ - │ Output conn. (-oc): [___________________] - │ - │ Output storage (-os): [/var/tmp___________] - │ - │ Output format (-of): [___________________] - │ - │ Output allocation (-oa): [sparse ▼] - │ - -All output options and paths are relative to the conversion server -(I<not> to the physical server). - -Finally in the left hand column is an information box giving the -version of virt-p2v (on the physical server) and virt-v2v (on the -conversion server). You should supply this information when reporting -bugs. - -In the right hand column are three panels which control what hard -disks, removable media devices, and network interfaces, will be -created in the output guest. Normally leaving these at the default -settings is fine. - - ─ ─ ───────────────────────────────────────┐ - Fixed hard disks │ - │ - Convert Device │ - [✔] sda │ - 1024G HITACHI │ - s/n 12345 │ - [✔] sdb │ - 119G HITACHI │ - s/n 12346 │ - │ - -Normally you would want to convert all hard disks. If you want -virt-p2v to completely ignore a local hard disk, uncheck it. The hard -disk that contains the operating system must be selected. If a hard -disk is part of a RAID array or LVM volume group (VG), then either all -hard disks in that array/VG must be selected, or none of them. - - │ - Removable media │ - │ - Convert Device │ - [✔] sr0 │ - │ - -If the physical machine has CD or DVD drives, then you can use the -Removable media panel to create corresponding drives on the guest -after conversion. Note that any data CDs/DVDs which are mounted in -the drives are I<not> copied over. - - │ - Network interfaces │ - │ - Convert Device Connect to ... | - [✔] em1 [default_____________] │ - [ ] wlp3s0 [default_____________] │ - │ - -In the Network interfaces panel, select the network interfaces that -should be created in the guest after conversion. You can also connect -these to target hypervisor networks (for further information about -this feature, see L<virt-v2v(1)/Networks and bridges>). - -On supported hardware, left-clicking on the device name (eg. C<em1>) -causes a light to start flashing on the physical interface, allowing -the interface to be identified by the operator. - -When you are ready to begin the conversion, press the -C<Start conversion> button: - - │ - [ Back ] [ Start conversion ] │ - │ - ─ ─ ───────────────────────────────────────┘ - -=head2 CONVERSION RUNNING DIALOG - -When conversion is running you will see this dialog: - - ┌────────────────────────────────────────────────────────┐ - │ virt-p2v │ - │ │ - │ ┌──────────────────────────────────────────────────┐ │ - │ │ ▲│ │ - │ │ │ │ - │ │ │ │ - ∼ ∼ ∼ ∼ - │ │ │ │ - │ │ │ │ - │ │ ▼│ │ - │ └──────────────────────────────────────────────────┘ │ - │ │ - │ Log files ... to /tmp/virt-p2v-xxx │ - │ │ - │ Doing conversion ... │ - │ │ - │ [ Cancel conversion ] │ - │ │ - └────────────────────────────────────────────────────────┘ - -In the main scrolling area you will see messages from the virt-v2v -process. - -Below the main area, virt-p2v shows you the location of the directory -on the conversion server that contains log files and other debugging -information. Below that is the current status and a button for -cancelling conversion. - -Once conversion has finished, you should shut down the physical -machine. If conversion is successful, you should never reboot it. - -=head1 KERNEL COMMAND LINE CONFIGURATION - -If you don’t want to configure things using the graphical UI, an -alternative is to configure through the kernel command line. This is -especially convenient if you are converting a lot of physical machines -which are booted using PXE. - -Where exactly you set command line arguments depends on your PXE -implementation, but for pxelinux you put them in the C<APPEND> field -in the F<pxelinux.cfg> file. For example: - - DEFAULT p2v - TIMEOUT 20 - PROMPT 0 - LABEL p2v - KERNEL vmlinuz0 - APPEND initrd=initrd0.img [....] p2v.server=conv.example.com p2v.password=secret p2v.o=libvirt - -You have to set some or all of the following command line arguments: - -=over 4 - -__KERNEL_CONFIG__ - -=item B<p2v.pre=COMMAND> - -=item B<p2v.pre="COMMAND ARG ..."> - -Select a pre-conversion command to run. Any command or script can be -specified here. If the command contains spaces, you must quote the -whole command with double quotes. The default is not to run any -command. - -=item B<p2v.post=poweroff> - -=item B<p2v.post=reboot> - -=item B<p2v.post=COMMAND> - -=item B<p2v.post="COMMAND ARG ..."> - -Select a post-conversion command to run if conversion is successful. -This can be any command or script. If the command contains spaces, -you must quote the whole command with double quotes. - -I<If> virt-p2v is running as root, I<and> the command line was set -from F</proc/cmdline> (not I<--cmdline>), then the default is to run -the L<poweroff(8)> command. Otherwise the default is not to run any -command. - -=item B<p2v.fail=COMMAND> - -=item B<p2v.fail="COMMAND ARG ..."> - -Select a post-conversion command to run if conversion fails. Any -command or script can be specified here. If the command contains -spaces, you must quote the whole command with double quotes. The -default is not to run any command. - -=item B<ip=dhcp> - -Use DHCP for configuring the network interface (this is the default). - -=begin comment - -=item B<ip=ADDR:GATEWAY:NETMASK> - -Set up a static IPv4 network configuration. - -=end comment - -=back - -=head1 SSH IDENTITIES - -As a somewhat more secure alternative to password authentication, you -can use an SSH identity (private key) for authentication. - -First create a key pair. It must have an empty passphrase: - - ssh-keygen -t rsa -N '' -f id_rsa - -This creates a private key (C<id_rsa>) and a public key -(C<id_rsa.pub>) pair. - -The public key should be appended to the C<authorized_keys> file on -the virt-v2v conversion server (usually to -C</root/.ssh/authorized_keys>). - -For distributing the private key, there are four scenarios from least -secure to most secure: - -=over 4 - -=item 1. - -Not using SSH identities at all, ie. password authentication. - -Anyone who can sniff the PXE boot parameters from the network or -observe the password some other way can log in to the virt-v2v -conversion server. - -=item 2. - -SSH identity embedded in the virt-p2v ISO or disk image. In the GUI, use: - - │ Password: [ <leave this field blank> ] │ - │ │ - │ SSH Identity URL: [file:///var/tmp/id_rsa_____________] │ - -or on the kernel command line: - - p2v.identity=file:///var/tmp/id_rsa - -The SSH private key can still be sniffed from the network if using -standard PXE. - -=item 3. - -SSH identity downloaded from a website. In the GUI, use: - - │ Password: [ <leave this field blank> ] │ - │ │ - │ SSH Identity URL: [https://internal.example.com/id_rsa] │ - -or on the kernel command line: - - p2v.identity=https://internal.example.com/id_rsa - -Anyone could still download the private key and use it to log in to -the virt-v2v conversion server, but you could provide some extra -security by configuring the web server to only allow connections from -P2V machines. - -Note that L<ssh-keygen(1)> creates the C<id_rsa> (private key) file -with mode 0600. If you simply copy the file to a webserver, the -webserver will not serve it. It will reply with "403 Forbidden" -errors. You will need to change the mode of the file to make it -publicly readable, for example by using: - - chmod 0644 id_rsa - -=item 4. - -SSH identity embedded in the virt-p2v ISO or disk image (like 2.), -I<and> use of secure PXE, PXE over separate physical network, or -sneakernet to distribute virt-p2v to the physical machine. - -=back - -Both L<virt-p2v-make-disk(1)> and L<virt-p2v-make-kickstart(1)> have -the same option I<--inject-ssh-identity> for injecting the private key -into the virt-p2v disk image / ISO. See also the following manual -sections: - -L<virt-p2v-make-disk(1)/ADDING AN SSH IDENTITY> - -L<virt-p2v-make-kickstart(1)/ADDING AN SSH IDENTITY> - -=head1 COMMON PROBLEMS - -=head2 Timeouts - -As described below (see L</HOW VIRT-P2V WORKS>) virt-p2v makes several -long-lived ssh connections to the conversion server. If these -connections time out then virt-p2v will fail. - -To test if a timeout might be causing problems, open an XTerm on the -virt-p2v machine, C<ssh root@I<conversion-server>>, and leave it for -at least an hour. If the session disconnects without you doing -anything, then there is a timeout which you should turn off. - -Timeouts happen because: - -=over 4 - -=item C<TIMEOUT> or C<TMOUT> environment variable - -Check if one of these environment variables is set in the root shell -on the conversion server. - -=item sshd C<ClientAlive*> setting - -Check for C<ClientAlive*> settings in C</etc/ssh/sshd_config> on the -conversion server. - -=item Firewall or NAT settings - -Check if there is a firewall or NAT box between virt-p2v and the -conversion server, and if this firewall drops idle connections after a -too-short time. - -virt-p2v E<ge> 1.36 attempts to work around firewall timeouts by -sending ssh keepalive messages every 5 minutes. - -=back - -=head1 OPTIONS - -=over 4 - -=item B<--help> - -Display help. - -=item B<--cmdline=CMDLINE> - -This is used for debugging. Instead of parsing the kernel command line -from F</proc/cmdline>, parse the string parameter C<CMDLINE>. - -=item B<--colors> - -=item B<--colours> - -Use ANSI colour sequences to colourize messages. This is the default -when the output is a tty. If the output of the program is redirected -to a file, ANSI colour sequences are disabled unless you use this -option. - -=item B<--iso> - -This flag is passed to virt-p2v when it is launched inside the -virt-p2v ISO environment, ie. when it is running on a real physical -machine (and thus not when testing). It enables various dangerous -features such as the Shutdown popup button. - -=item B<--nbd=server[,server...]> - -Select which NBD server is used. By default the following servers are -checked and the first one found is used: -I<--nbd=qemu-nbd,qemu-nbd-no-sa,nbdkit,nbdkit-no-sa> - -=over 4 - -=item B<qemu-nbd> - -Use qemu-nbd. - -=item B<qemu-nbd-no-sa> - -Use qemu-nbd, but disable socket activation. - -=item B<nbdkit> - -Use nbdkit with the file plugin (see: L<nbdkit-file-plugin(1)>). - -=item B<nbdkit-no-sa> - -Use nbdkit, but disable socket activation - -=back - -The C<*-no-sa> variants allow virt-p2v to fall back to older versions -of qemu-nbd and nbdkit which did not support -L<socket activation|http://0pointer.de/blog/projects/socket-activation.html>. - -=item B<--test-disk=/PATH/TO/DISK.IMG> - -For testing or debugging purposes, replace F</dev/sda> with a local -file. You must use an absolute path. - -=item B<-v> - -=item B<--verbose> - -In libguestfs E<ge> 1.33.41, debugging is always enabled on the -conversion server, and this option does nothing. - -=item B<-V> - -=item B<--version> - -Display version number and exit. - -=back - -=head1 HOW VIRT-P2V WORKS - -B<Note this section is not normative.> We may change how virt-p2v -works at any time in the future. - -As described above, virt-p2v runs on a physical machine, interrogates -the user or the kernel command line for configuration, and then -establishes one or more ssh connections to the virt-v2v conversion -server. The ssh connections are interactive shell sessions to the -remote host, but the commands sent are generated entirely by virt-p2v -itself, not by the user. For data transfer, virt-p2v will use the -reverse port forward feature of ssh (ie. C<ssh -R>). - -It will first make one or more test connections, which are used to -query the remote version of virt-v2v and its features. The test -connections are closed before conversion begins. - - ┌──────────────┐ ┌─────────────────┐ - │ virt-p2v │ │ virt-v2v │ - │ (physical │ control connection │ (conversion │ - │ server) ╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍▶ server) │ - └──────────────┘ └─────────────────┘ - -Once virt-p2v is ready to start conversion, it will open a single ssh -control connection. It first sends a mkdir command to create a -temporary directory on the conversion server. The directory name is -randomly chosen and is displayed in the GUI. It has the form: - - /tmp/virt-p2v-YYYYMMDD-XXXXXXXX - -where C<YYYYMMDD> is the current date, and the ‘X’s are random -characters. - -Into this directory are written various files which include: - -=over 4 - -=item F<dmesg> - -=item F<lscpu> - -=item F<lspci> - -=item F<lsscsi> - -=item F<lsusb> - -I<(before conversion)> - -The output of the corresponding commands (ie L<dmesg(1)>, L<lscpu(1)> -etc) on the physical machine. - -The dmesg output is useful for detecting problems such as missing -device drivers or firmware on the virt-p2v ISO. The others are useful -for debugging novel hardware configurations. - -=item F<environment> - -I<(before conversion)> - -The content of the environment where L<virt-v2v(1)> will run. - -=item F<name> - -I<(before conversion)> - -The name (usually the hostname) of the physical machine. - -=item F<physical.xml> - -I<(before conversion)> - -Libvirt XML describing the physical machine. It is used to pass data -about the physical source host to L<virt-v2v(1)> via the I<-i libvirtxml> -option. - -Note this is not "real" libvirt XML (and must B<never> be loaded into -libvirt, which would reject it anyhow). Also it is not the same as -the libvirt XML which virt-v2v generates in certain output modes. - -=item F<p2v-version> - -=item F<v2v-version> - -I<(before conversion)> - -The versions of virt-p2v and virt-v2v respectively. - -=item F<status> - -I<(after conversion)> - -The final status of the conversion. C<0> if the conversion was -successful. Non-zero if the conversion failed. - -=item F<time> - -I<(before conversion)> - -The start date/time of conversion. - -=item F<virt-v2v-conversion-log.txt> - -I<(during/after conversion)> - -The conversion log. This is just the output of the virt-v2v command -on the conversion server. If conversion fails, you should examine -this log file, and you may be asked to supply the B<complete>, -B<unedited> log file in any bug reports or support tickets. - -=item F<virt-v2v-wrapper.sh> - -I<(before conversion)> - -This is the wrapper script which is used when running virt-v2v. For -interest only, do not attempt to run this script yourself. - -=back - -Before conversion actually begins, virt-p2v then makes one or more -further ssh connections to the server for data transfer. - -The transfer protocol used currently is NBD (Network Block Device), -which is proxied over ssh. The NBD server is L<qemu-nbd(1)> by -default but others can be selected using the I<--nbd> command line -option. - -There is one ssh connection per physical hard disk on the source -machine (the common case — a single hard disk — is shown below): - - ┌──────────────┐ ┌─────────────────┐ - │ virt-p2v │ │ virt-v2v │ - │ (physical │ control connection │ (conversion │ - │ server) ╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍▶ server) │ - │ │ │ │ - │ │ data connection │ │ - │ ╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍▶ │ - │qemu-nbd ← ─┘ │ │└─ ← NBD │ - │/dev/sda │ │ requests │ - ∼ ∼ ∼ ∼ - └──────────────┘ └─────────────────┘ - -Although the ssh data connection is originated from the physical -server and terminates on the conversion server, in fact NBD requests -flow in the opposite direction. This is because the reverse port -forward feature of ssh (C<ssh -R>) is used to open a port on the -loopback interface of the conversion server which is proxied back by -ssh to the NBD server running on the physical machine. The effect is -that virt-v2v via libguestfs can open nbd connections which directly -read the hard disk(s) of the physical server. - -Two layers of protection are used to ensure that there are no writes -to the hard disks: Firstly, the qemu-nbd I<-r> (readonly) option is -used. Secondly libguestfs creates an overlay on top of the NBD -connection which stores writes in a temporary file on the conversion -file. - -The long S<C<virt-v2v -i libvirtxml physical.xml ...>> command is -wrapped inside a wrapper script and uploaded to the conversion server. -The final step is to run this wrapper script, in turn running the -virt-v2v command. The virt-v2v command references the F<physical.xml> -file (see above), which in turn references the NBD listening port(s) -of the data connection(s). - -Output from the virt-v2v command (messages, debugging etc) is saved -both in the log file on the conversion server. Only informational -messages are sent back over the control connection to be displayed in -the graphical UI. - -=head1 SEE ALSO - -L<virt-p2v-make-disk(1)>, -L<virt-p2v-make-kickstart(1)>, -L<virt-p2v-make-kiwi(1)>, -L<virt-v2v(1)>, -L<qemu-nbd(1)>, -L<nbdkit(1)>, L<nbdkit-file-plugin(1)>, -L<ssh(1)>, -L<sshd(8)>, -L<sshd_config(5)>, -L<http://libguestfs.org/>. - -=head1 AUTHORS - -Matthew Booth - -John Eckersberg - -Richard W.M. Jones L<http://people.redhat.com/~rjones/> - -Mike Latimer - -Pino Toscano - -Tingting Zheng - -=head1 COPYRIGHT - -Copyright (C) 2009-2019 Red Hat Inc. diff --git a/p2v/whole-file.c b/p2v/whole-file.c deleted file mode 100644 index 63597e0c0..000000000 --- a/p2v/whole-file.c +++ /dev/null @@ -1,95 +0,0 @@ -/* libguestfs - * Copyright (C) 2011-2019 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <libintl.h> - -#include "p2v.h" - -/** - * Read the whole file into a memory buffer and return it. The file - * should be a regular, local, trusted file. - */ -int -read_whole_file (const char *filename, char **data_r, size_t *size_r) -{ - int fd; - char *data; - off_t size; - off_t n; - ssize_t r; - struct stat statbuf; - - fd = open (filename, O_RDONLY|O_CLOEXEC); - if (fd == -1) { - fprintf (stderr, "open: %s: %m\n", filename); - return -1; - } - - if (fstat (fd, &statbuf) == -1) { - fprintf (stderr, "stat: %s: %m\n", filename); - close (fd); - return -1; - } - - size = statbuf.st_size; - data = malloc (size + 1); - if (data == NULL) { - perror ("malloc"); - return -1; - } - - n = 0; - while (n < size) { - r = read (fd, &data[n], size - n); - if (r == -1) { - fprintf (stderr, "read: %s: %m\n", filename); - free (data); - close (fd); - return -1; - } - if (r == 0) { - fprintf (stderr, "read: %s: unexpected end of file\n", filename); - free (data); - close (fd); - return -1; - } - n += r; - } - - if (close (fd) == -1) { - fprintf (stderr, "close: %s: %m\n", filename); - free (data); - return -1; - } - - /* For convenience of callers, \0-terminate the data. */ - data[size] = '\0'; - - *data_r = data; - if (size_r != NULL) - *size_r = size; - - return 0; -} diff --git a/po-docs/language.mk b/po-docs/language.mk index b50d053e6..e3d669cdf 100644 --- a/po-docs/language.mk +++ b/po-docs/language.mk @@ -71,9 +71,6 @@ MANPAGES = \ virt-log.1 \ virt-ls.1 \ virt-make-fs.1 \ - virt-p2v.1 \ - virt-p2v-make-disk.1 \ - virt-p2v-make-kickstart.1 \ virt-rescue.1 \ virt-resize.1 \ virt-sparsify.1 \ diff --git a/po-docs/podfiles b/po-docs/podfiles index 119e75ad0..7d90267a1 100644 --- a/po-docs/podfiles +++ b/po-docs/podfiles @@ -53,11 +53,6 @@ ../lua/examples/guestfs-lua.pod ../make-fs/virt-make-fs.pod ../ocaml/examples/guestfs-ocaml.pod -../p2v/virt-p2v-kernel-config.pod -../p2v/virt-p2v-make-disk.pod -../p2v/virt-p2v-make-kickstart.pod -../p2v/virt-p2v-make-kiwi.pod -../p2v/virt-p2v.pod ../perl/examples/guestfs-perl.pod ../python/examples/guestfs-python.pod ../rescue/virt-rescue.pod -- 2.21.0
Pino Toscano
2019-Sep-10 14:35 UTC
[Libguestfs] [PATCH 2/2] Remove remaining virt-p2v bits
Remove (almost) all the remaining bits related to virt-p2v. --- .gitignore | 4 - Makefile.am | 4 +- bash/Makefile.am | 4 - bash/virt-alignment-scan | 18 -- common/miniexpect/Makefile.am | 51 ---- common/miniexpect/README | 31 -- common/miniexpect/miniexpect.c | 489 ------------------------------ common/miniexpect/miniexpect.h | 110 ------- common/miniexpect/miniexpect.pod | 496 ------------------------------- configure.ac | 5 +- contrib/README | 3 - docs/C_SOURCE_FILES | 2 - docs/guestfs-building.pod | 55 +--- docs/guestfs-hacking.pod | 83 ------ generator/authors.ml | 9 - generator/authors.mli | 1 - m4/guestfs-v2v.m4 | 52 +--- po-docs/podfiles | 1 - po/POTFILES | 1 - run.in | 7 - 20 files changed, 6 insertions(+), 1420 deletions(-) delete mode 100644 common/miniexpect/Makefile.am delete mode 100644 common/miniexpect/README delete mode 100644 common/miniexpect/miniexpect.c delete mode 100644 common/miniexpect/miniexpect.h delete mode 100644 common/miniexpect/miniexpect.pod diff --git a/.gitignore b/.gitignore index ff45d9d73..d10f30fd4 100644 --- a/.gitignore +++ b/.gitignore @@ -64,9 +64,6 @@ Makefile.in /bash/virt-inspector /bash/virt-log /bash/virt-ls -/bash/virt-p2v-make-disk -/bash/virt-p2v-make-kickstart -/bash/virt-p2v-make-kiwi /bash/virt-resize /bash/virt-sysprep /bash/virt-sparsify @@ -129,7 +126,6 @@ Makefile.in /common/errnostring/errnostring-gperf.c /common/errnostring/errnostring-gperf.gperf /common/errnostring/errnostring.h -/common/miniexpect/miniexpect.3 /common/mlaugeas/.depend /common/mlgettext/.depend /common/mlgettext/common_gettext.ml diff --git a/Makefile.am b/Makefile.am index 1b7c98319..1cc21961a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -328,7 +328,7 @@ ChangeLog: configure.ac docs/C_SOURCE_FILES: configure.ac rm -f $@ $@-t find $(DIST_SUBDIRS) -name '*.[ch]' | \ - grep -v -E '^(builder/index-parse\.|builder/index-scan\.|common/mllibvirt/libvirt_c\.c|examples/|gnulib/|gobject/|java/com_redhat_et_libguestfs|perl/|p2v/|php/extension/config\.h|ruby/ext/guestfs/extconf\.h|tests/|test-data/)' | \ + grep -v -E '^(builder/index-parse\.|builder/index-scan\.|common/mllibvirt/libvirt_c\.c|examples/|gnulib/|gobject/|java/com_redhat_et_libguestfs|perl/|php/extension/config\.h|ruby/ext/guestfs/extconf\.h|tests/|test-data/)' | \ grep -v -E '/(guestfs|rc)_protocol\.' | \ grep -v -E '.*/errnostring\.' | \ grep -v -E '.*-gperf\.' | \ @@ -340,7 +340,7 @@ po/POTFILES: configure.ac rm -f $@ $@-t cd $(srcdir); \ find $(DIST_SUBDIRS) -name '*.c' -o -name '*.pl' -o -name '*.pm' | \ - grep -v -E '^(examples|gnulib|perl/(blib|examples)|p2v|po-docs|tests|test-data)/' | \ + grep -v -E '^(examples|gnulib|perl/(blib|examples)|po-docs|tests|test-data)/' | \ grep -v -E '/((guestfs|rc)_protocol\.c)$$' | \ grep -v -E '^python/utils\.c$$' | \ grep -v -E '^perl/lib/Sys/Guestfs\.c$$' | \ diff --git a/bash/Makefile.am b/bash/Makefile.am index 4f595cd04..61b37deba 100644 --- a/bash/Makefile.am +++ b/bash/Makefile.am @@ -44,9 +44,6 @@ symlinks = \ virt-inspector \ virt-log \ virt-ls \ - virt-p2v-make-disk \ - virt-p2v-make-kickstart \ - virt-p2v-make-kiwi \ virt-resize \ virt-sparsify \ virt-sysprep \ @@ -79,7 +76,6 @@ guestunmount \ virt-builder virt-cat virt-customize virt-df virt-dib virt-diff \ virt-edit virt-filesystems virt-format virt-get-kernel virt-inspector \ virt-log virt-ls \ -virt-p2v-make-disk virt-p2v-make-kickstart virt-p2v-make-kiwi \ virt-resize virt-sparsify virt-sysprep \ virt-tail: rm -f $@ diff --git a/bash/virt-alignment-scan b/bash/virt-alignment-scan index 1014677f6..3d4c114e9 100644 --- a/bash/virt-alignment-scan +++ b/bash/virt-alignment-scan @@ -169,24 +169,6 @@ _virt_ls () } && complete -o default -F _virt_ls virt-ls -_virt_p2v_make_disk () -{ - _guestfs_virttools "virt-p2v-make-disk" 1 -} && -complete -o default -F _virt_p2v_make_disk virt-p2v-make-disk - -_virt_p2v_make_kickstart () -{ - _guestfs_virttools "virt-p2v-make-kickstart" 1 -} && -complete -o default -F _virt_p2v_make_kickstart virt-p2v-make-kickstart - -_virt_p2v_make_kiwi () -{ - _guestfs_virttools "virt-p2v-make-kiwi" 1 -} && -complete -o default -F _virt_p2v_make_kiwi virt-p2v-make-kiwi - _virt_resize () { _guestfs_virttools "virt-resize" 0 diff --git a/common/miniexpect/Makefile.am b/common/miniexpect/Makefile.am deleted file mode 100644 index f223b8d79..000000000 --- a/common/miniexpect/Makefile.am +++ /dev/null @@ -1,51 +0,0 @@ -# libguestfs virt-p2v -# Copyright (C) 2009-2019 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 directory contains a copy of the miniexpect library from -# http://git.annexia.org/?p=miniexpect.git;a=summary -# This is used in virt-p2v. - -include $(top_srcdir)/subdir-rules.mk - -EXTRA_DIST = \ - miniexpect.pod \ - README - -noinst_LTLIBRARIES = libminiexpect.la - -libminiexpect_la_SOURCES = \ - miniexpect.c \ - miniexpect.h -libminiexpect_la_CFLAGS = \ - $(WARN_CFLAGS) $(WERROR_CFLAGS) \ - $(PCRE_CFLAGS) -libminiexpect_la_LIBADD = \ - $(PCRE_LIBS) - -# It should be noinst_MANS but that doesn't work. -noinst_DATA = miniexpect.3 - -# podwrapper cannot parse this page because it's not in the POD format -# expected by libguestfs. Just use pod2man, but don't fail if we -# can't generate it. -miniexpect.3: miniexpect.pod - rm -f $@ $@-t - -pod2man --utf8 --stderr \ - --center=miniexpect --release=miniexpect --name=miniexpect \ - --section=3 \ - $< $@-t - mv $@-t $@ || touch $@ diff --git a/common/miniexpect/README b/common/miniexpect/README deleted file mode 100644 index f1f5a9532..000000000 --- a/common/miniexpect/README +++ /dev/null @@ -1,31 +0,0 @@ -miniexpect is a very simple expect-like library for C. - -It has a saner interface than libexpect, and doesn't depend on Tcl. -It is also thread safe, const-correct and uses modern C standards. - -It is standalone, except that it requires the PCRE (Perl Compatible -Regular Expressions) library from http://www.pcre.org/. The PCRE -dependency is fundamental because we want to offer the most powerful -regular expression syntax to match on, but more importantly because -PCRE has a convenient way to detect partial matches which made this -library very simple to implement. - -License -------- - -The library was written by Richard W.M. Jones <rjones@redhat.com> -and is licensed under the Library GPL (LGPL) version 2 or above. - -Source is available from: http://git.annexia.org/?p=miniexpect.git;a=summary - -Using the library ------------------ - -If you wanted to copy the library into your own code (instead of -linking to it as a dependency), you only need to copy the two files: -miniexpect.h, miniexpect.c. - -The API is documented in the manual page (miniexpect.pod / miniexpect.3). - -For examples of how to use the API in reality, see the examples and -tests in the source directory. diff --git a/common/miniexpect/miniexpect.c b/common/miniexpect/miniexpect.c deleted file mode 100644 index 7debc0238..000000000 --- a/common/miniexpect/miniexpect.c +++ /dev/null @@ -1,489 +0,0 @@ -/* miniexpect - * Copyright (C) 2014 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <ctype.h> -#include <fcntl.h> -#include <unistd.h> -#include <signal.h> -#include <poll.h> -#include <errno.h> -#include <termios.h> -#include <time.h> -#include <assert.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/time.h> - -#include <pcre.h> - -/* RHEL 6 pcre did not define PCRE_PARTIAL_SOFT. However PCRE_PARTIAL - * is a synonym so use that. - */ -#ifndef PCRE_PARTIAL_SOFT -#define PCRE_PARTIAL_SOFT PCRE_PARTIAL -#endif - -#include "miniexpect.h" - -static void debug_buffer (FILE *, const char *); - -static mexp_h * -create_handle (void) -{ - mexp_h *h = malloc (sizeof *h); - if (h == NULL) - return NULL; - - /* Initialize the fields to default values. */ - h->fd = -1; - h->pid = 0; - h->timeout = 60000; - h->read_size = 1024; - h->pcre_error = 0; - h->buffer = NULL; - h->len = h->alloc = 0; - h->next_match = -1; - h->debug_fp = NULL; - h->user1 = h->user2 = h->user3 = NULL; - - return h; -} - -static void -clear_buffer (mexp_h *h) -{ - free (h->buffer); - h->buffer = NULL; - h->alloc = h->len = 0; - h->next_match = -1; -} - -int -mexp_close (mexp_h *h) -{ - int status = 0; - - free (h->buffer); - - if (h->fd >= 0) - close (h->fd); - if (h->pid > 0) { - if (waitpid (h->pid, &status, 0) == -1) - return -1; - } - - free (h); - - return status; -} - -mexp_h * -mexp_spawnlf (unsigned flags, const char *file, const char *arg, ...) -{ - char **argv, **new_argv; - size_t i; - va_list args; - mexp_h *h; - - argv = malloc (sizeof (char *)); - if (argv == NULL) - return NULL; - argv[0] = (char *) arg; - - va_start (args, arg); - for (i = 1; arg != NULL; ++i) { - arg = va_arg (args, const char *); - new_argv = realloc (argv, sizeof (char *) * (i+1)); - if (new_argv == NULL) { - free (argv); - va_end (args); - return NULL; - } - argv = new_argv; - argv[i] = (char *) arg; - } - - h = mexp_spawnvf (flags, file, argv); - free (argv); - va_end (args); - return h; -} - -mexp_h * -mexp_spawnvf (unsigned flags, const char *file, char **argv) -{ - mexp_h *h = NULL; - int fd = -1; - int err; - char slave[1024]; - pid_t pid = 0; - - fd = posix_openpt (O_RDWR|O_NOCTTY); - if (fd == -1) - goto error; - - if (grantpt (fd) == -1) - goto error; - - if (unlockpt (fd) == -1) - goto error; - - /* Get the slave pty name now, but don't open it in the parent. */ - if (ptsname_r (fd, slave, sizeof slave) != 0) - goto error; - - /* Create the handle last before we fork. */ - h = create_handle (); - if (h == NULL) - goto error; - - pid = fork (); - if (pid == -1) - goto error; - - if (pid == 0) { /* Child. */ - int slave_fd; - - if (!(flags & MEXP_SPAWN_KEEP_SIGNALS)) { - struct sigaction sa; - int i; - - /* Remove all signal handlers. See the justification here: - * https://www.redhat.com/archives/libvir-list/2008-August/msg00303.html - * We don't mask signal handlers yet, so this isn't completely - * race-free, but better than not doing it at all. - */ - memset (&sa, 0, sizeof sa); - sa.sa_handler = SIG_DFL; - sa.sa_flags = 0; - sigemptyset (&sa.sa_mask); - for (i = 1; i < NSIG; ++i) - sigaction (i, &sa, NULL); - } - - setsid (); - - /* Open the slave side of the pty. We must do this in the child - * after setsid so it becomes our controlling tty. - */ - slave_fd = open (slave, O_RDWR); - if (slave_fd == -1) - goto error; - - if (!(flags & MEXP_SPAWN_COOKED_MODE)) { - struct termios termios; - - /* Set raw mode. */ - tcgetattr (slave_fd, &termios); - cfmakeraw (&termios); - tcsetattr (slave_fd, TCSANOW, &termios); - } - - /* Set up stdin, stdout, stderr to point to the pty. */ - dup2 (slave_fd, 0); - dup2 (slave_fd, 1); - dup2 (slave_fd, 2); - close (slave_fd); - - /* Close the master side of the pty - do this late to avoid a - * kernel bug, see sshpass source code. - */ - close (fd); - - if (!(flags & MEXP_SPAWN_KEEP_FDS)) { - int i, max_fd; - - /* Close all other file descriptors. This ensures that we don't - * hold open (eg) pipes from the parent process. - */ - max_fd = sysconf (_SC_OPEN_MAX); - if (max_fd == -1) - max_fd = 1024; - if (max_fd > 65536) - max_fd = 65536; /* bound the amount of work we do here */ - for (i = 3; i < max_fd; ++i) - close (i); - } - - /* Run the subprocess. */ - execvp (file, argv); - perror (file); - _exit (EXIT_FAILURE); - } - - /* Parent. */ - - h->fd = fd; - h->pid = pid; - return h; - - error: - err = errno; - if (fd >= 0) - close (fd); - if (pid > 0) - waitpid (pid, NULL, 0); - if (h != NULL) - mexp_close (h); - errno = err; - return NULL; -} - -enum mexp_status -mexp_expect (mexp_h *h, const mexp_regexp *regexps, int *ovector, int ovecsize) -{ - time_t start_t, now_t; - int timeout; - struct pollfd pfds[1]; - int r; - ssize_t rs; - - time (&start_t); - - if (h->next_match == -1) { - /* Fully clear the buffer, then read. */ - clear_buffer (h); - } else { - /* See the comment in the manual about h->next_match. We have - * some data remaining in the buffer, so begin by matching that. - */ - memmove (&h->buffer[0], &h->buffer[h->next_match], h->len - h->next_match); - h->len -= h->next_match; - h->buffer[h->len] = '\0'; - h->next_match = -1; - goto try_match; - } - - for (;;) { - /* If we've got a timeout then work out how many seconds are left. - * Timeout == 0 is not particularly well-defined, but it probably - * means "return immediately if there's no data to be read". - */ - if (h->timeout >= 0) { - time (&now_t); - timeout = h->timeout - ((now_t - start_t) * 1000); - if (timeout < 0) - timeout = 0; - } - else - timeout = 0; - - pfds[0].fd = h->fd; - pfds[0].events = POLLIN; - pfds[0].revents = 0; - r = poll (pfds, 1, timeout); - if (h->debug_fp) - fprintf (h->debug_fp, "DEBUG: poll returned %d\n", r); - if (r == -1) - return MEXP_ERROR; - - if (r == 0) - return MEXP_TIMEOUT; - - /* Otherwise we expect there is something to read from the file - * descriptor. - */ - if (h->alloc - h->len <= h->read_size) { - char *new_buffer; - /* +1 here allows us to store \0 after the data read */ - new_buffer = realloc (h->buffer, h->alloc + h->read_size + 1); - if (new_buffer == NULL) - return MEXP_ERROR; - h->buffer = new_buffer; - h->alloc += h->read_size; - } - rs = read (h->fd, h->buffer + h->len, h->read_size); - if (h->debug_fp) - fprintf (h->debug_fp, "DEBUG: read returned %zd\n", rs); - if (rs == -1) { - /* Annoyingly on Linux (I'm fairly sure this is a bug) if the - * writer closes the connection, the entire pty is destroyed, - * and read returns -1 / EIO. Handle that special case here. - */ - if (errno == EIO) - return MEXP_EOF; - return MEXP_ERROR; - } - if (rs == 0) - return MEXP_EOF; - - /* We read something. */ - h->len += rs; - h->buffer[h->len] = '\0'; - if (h->debug_fp) { - fprintf (h->debug_fp, "DEBUG: read %zd bytes from pty\n", rs); - fprintf (h->debug_fp, "DEBUG: buffer content: "); - debug_buffer (h->debug_fp, h->buffer); - fprintf (h->debug_fp, "\n"); - } - - try_match: - /* See if there is a full or partial match against any regexp. */ - if (regexps) { - size_t i; - int can_clear_buffer = 1; - - assert (h->buffer != NULL); - - for (i = 0; regexps[i].r > 0; ++i) { - const int options = regexps[i].options | PCRE_PARTIAL_SOFT; - - r = pcre_exec (regexps[i].re, regexps[i].extra, - h->buffer, (int)h->len, 0, - options, - ovector, ovecsize); - h->pcre_error = r; - - if (r >= 0) { - /* A full match. */ - if (ovector != NULL && ovecsize >= 1 && ovector[1] >= 0) - h->next_match = ovector[1]; - else - h->next_match = -1; - return regexps[i].r; - } - - else if (r == PCRE_ERROR_NOMATCH) { - /* No match at all. */ - /* (nothing here) */ - } - - else if (r == PCRE_ERROR_PARTIAL) { - /* Partial match. Keep the buffer and keep reading. */ - can_clear_buffer = 0; - } - - else { - /* An actual PCRE error. */ - return MEXP_PCRE_ERROR; - } - } - - /* If none of the regular expressions matched (not partially) - * then we can clear the buffer. This is an optimization. - */ - if (can_clear_buffer) - clear_buffer (h); - - } /* if (regexps) */ - } -} - -static int mexp_vprintf (mexp_h *h, int password, const char *fs, va_list args) - __attribute__((format(printf,3,0))); - -static int -mexp_vprintf (mexp_h *h, int password, const char *fs, va_list args) -{ - char *msg; - int len; - size_t n; - ssize_t r; - char *p; - - len = vasprintf (&msg, fs, args); - - if (len < 0) - return -1; - - if (h->debug_fp) { - if (!password) { - fprintf (h->debug_fp, "DEBUG: writing: "); - debug_buffer (h->debug_fp, msg); - fprintf (h->debug_fp, "\n"); - } - else - fprintf (h->debug_fp, "DEBUG: writing the password\n"); - } - - n = len; - p = msg; - while (n > 0) { - r = write (h->fd, p, n); - if (r == -1) { - free (msg); - return -1; - } - n -= r; - p += r; - } - - free (msg); - return len; -} - -int -mexp_printf (mexp_h *h, const char *fs, ...) -{ - int r; - va_list args; - - va_start (args, fs); - r = mexp_vprintf (h, 0, fs, args); - va_end (args); - return r; -} - -int -mexp_printf_password (mexp_h *h, const char *fs, ...) -{ - int r; - va_list args; - - va_start (args, fs); - r = mexp_vprintf (h, 1, fs, args); - va_end (args); - return r; -} - -int -mexp_send_interrupt (mexp_h *h) -{ - return write (h->fd, "\003", 1); -} - -/* Print escaped buffer to fp. */ -static void -debug_buffer (FILE *fp, const char *buf) -{ - while (*buf) { - if (isprint (*buf)) - fputc (*buf, fp); - else { - switch (*buf) { - case '\0': fputs ("\\0", fp); break; - case '\a': fputs ("\\a", fp); break; - case '\b': fputs ("\\b", fp); break; - case '\f': fputs ("\\f", fp); break; - case '\n': fputs ("\\n", fp); break; - case '\r': fputs ("\\r", fp); break; - case '\t': fputs ("\\t", fp); break; - case '\v': fputs ("\\v", fp); break; - default: - fprintf (fp, "\\x%x", (unsigned char) *buf); - } - } - buf++; - } -} diff --git a/common/miniexpect/miniexpect.h b/common/miniexpect/miniexpect.h deleted file mode 100644 index 14d823650..000000000 --- a/common/miniexpect/miniexpect.h +++ /dev/null @@ -1,110 +0,0 @@ -/* miniexpect - * Copyright (C) 2014 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* ** NOTE ** All API documentation is in the manual page. - * - * To read the manual page from the source directory, do: - * man ./miniexpect.3 - * If you have installed miniexpect, do: - * man 3 miniexpect - * - * The source for the manual page is miniexpect.pod. - */ - -#ifndef MINIEXPECT_H_ -#define MINIEXPECT_H_ - -#include <stdio.h> -#include <unistd.h> - -#include <pcre.h> - -/* This handle is created per subprocess that is spawned. */ -struct mexp_h { - int fd; - pid_t pid; - int timeout; - char *buffer; - size_t len; - size_t alloc; - ssize_t next_match; - size_t read_size; - int pcre_error; - FILE *debug_fp; - void *user1; - void *user2; - void *user3; -}; -typedef struct mexp_h mexp_h; - -/* Methods to access (some) fields in the handle. */ -#define mexp_get_fd(h) ((h)->fd) -#define mexp_get_pid(h) ((h)->pid) -#define mexp_get_timeout_ms(h) ((h)->timeout) -#define mexp_set_timeout_ms(h, ms) ((h)->timeout = (ms)) -/* If secs == -1, then this sets h->timeout to -1000, but the main - * code handles this since it only checks for h->timeout < 0. - */ -#define mexp_set_timeout(h, secs) ((h)->timeout = 1000 * (secs)) -#define mexp_get_read_size(h) ((h)->read_size) -#define mexp_set_read_size(h, size) ((h)->read_size = (size)) -#define mexp_get_pcre_error(h) ((h)->pcre_error) -#define mexp_set_debug_file(h, fp) ((h)->debug_fp = (fp)) -#define mexp_get_debug_file(h) ((h)->debug_fp) - -/* Spawn a subprocess. */ -extern mexp_h *mexp_spawnvf (unsigned flags, const char *file, char **argv); -extern mexp_h *mexp_spawnlf (unsigned flags, const char *file, const char *arg, ...); -#define mexp_spawnv(file,argv) mexp_spawnvf (0, (file), (argv)) -#define mexp_spawnl(file,...) mexp_spawnlf (0, (file), __VA_ARGS__) - -#define MEXP_SPAWN_KEEP_SIGNALS 1 -#define MEXP_SPAWN_KEEP_FDS 2 -#define MEXP_SPAWN_COOKED_MODE 4 -#define MEXP_SPAWN_RAW_MODE 0 - -/* Close the handle. */ -extern int mexp_close (mexp_h *h); - -/* Expect. */ -struct mexp_regexp { - int r; - const pcre *re; - const pcre_extra *extra; - int options; -}; -typedef struct mexp_regexp mexp_regexp; - -enum mexp_status { - MEXP_EOF = 0, - MEXP_ERROR = -1, - MEXP_PCRE_ERROR = -2, - MEXP_TIMEOUT = -3, -}; - -extern int mexp_expect (mexp_h *h, const mexp_regexp *regexps, - int *ovector, int ovecsize); - -/* Sending commands, keypresses. */ -extern int mexp_printf (mexp_h *h, const char *fs, ...) - __attribute__((format(printf,2,3))); -extern int mexp_printf_password (mexp_h *h, const char *fs, ...) - __attribute__((format(printf,2,3))); -extern int mexp_send_interrupt (mexp_h *h); - -#endif /* MINIEXPECT_H_ */ diff --git a/common/miniexpect/miniexpect.pod b/common/miniexpect/miniexpect.pod deleted file mode 100644 index fe769791c..000000000 --- a/common/miniexpect/miniexpect.pod +++ /dev/null @@ -1,496 +0,0 @@ -=encoding utf8 - -=head1 NAME - -miniexpect - A very simple expect library for C. - -=head1 SYNOPSIS - - #include <errno.h> - #include <sys/wait.h> - #include <pcre.h> - #include <miniexpect.h> - - mexp_h *h; - h = mexp_spawnl ("ssh", "ssh", "host", NULL); - switch (mexp_expect (h, regexps, ovector, ovecsize)) { - ... - } - mexp_close (h); - - cc prog.c -o prog -lminiexpect -lpcre - -=head1 DESCRIPTION - -Miniexpect is a very simple expect-like library for C. Expect is a -way to control an external program that wants to be run interactively. - -Miniexpect has a saner interface than libexpect, and doesn't depend on -Tcl. It is also thread safe, const-correct and uses modern C -standards. - -Miniexpect is a standalone library, except for a single dependency: it -requires the PCRE (Perl Compatible Regular Expressions) library from -L<http://www.pcre.org/>. The PCRE dependency is fundamental because -we want to offer the most powerful regular expression syntax to match -on, but more importantly because PCRE has a convenient way to detect -partial matches which made this library very simple to implement. - -This manual page documents the API. Examples of how to use the API -can be found in the source directory. - -=head1 CONCEPTS - -Miniexpect lets you start up an external program, control it (by -sending commands to it), and close it down gracefully. Two things -make this different from other APIs like L<popen(3)> and L<system(3)>: -Firstly miniexpect creates a pseudoterminal (pty). Secondly -miniexpect lets you match the output of the program using regular -expressions. Both of these are handy for controlling interactive -programs that might (for example) ask for passwords, but you can use -miniexpect on just about any external program. - -You can control multiple programs at the same time. - -=head1 SPAWNING THE SUBPROCESS - -There are four calls for creating a subprocess: - -B<mexp_h *mexp_spawnl (const char *file, const char *arg, ...);> - -This creates a subprocess running the external program C<file> (the -current C<$PATH> is searched unless you give an absolute path). -C<arg, ...> are the arguments to the program. You should terminate -the list of arguments with C<NULL>. Usually the first argument should -be the name of the program. - -The return value is a handle (see next section). - -If there was an error running the subprocess, C<NULL> is returned and -the error is available in C<errno>. - -For example, to run an ssh subprocess you could do: - - h = mexp_spawnl ("ssh", "ssh", "-l", "root", "host", NULL); - -or to run a particular ssh binary: - - h = mexp_spawnl ("/usr/local/bin/ssh", "ssh", "-l", "root", "host", NULL); - -An alternative to C<mexp_spawnl> is: - -B<mexp_h *mexp_spawnv (const char *file, char **argv);> - -This is the same as C<mexp_spawnl> except that you pass the arguments -in a NULL-terminated array. - -There are also two versions of the above calls which take flags: - -B<mexp_h *mexp_spawnlf (unsigned flags, const char *file, const char *arg, ...);> - -B<mexp_h *mexp_spawnvf (unsigned flags, const char *file, char **argv);> - -The flags may contain the following values, logically ORed together: - -=over 4 - -=item B<MEXP_SPAWN_KEEP_SIGNALS> - -Do not reset signal handlers to C<SIG_DFL> in the subprocess. - -=item B<MEXP_SPAWN_KEEP_FDS> - -Do not close file descriptors E<ge> 3 in the subprocess. - -=item B<MEXP_SPAWN_COOKED_MODE> or B<MEXP_SPAWN_RAW_MODE> - -Configure the pty in cooked mode or raw mode. Raw mode is the -default. - -=back - -=head1 HANDLES - -After spawning a subprocess, you get back a handle which is a pointer -to a struct: - - struct mexp_h; - typedef struct mexp_h mexp_h; - -Various methods can be used on the handle: - -B<int mexp_get_fd (mexp_h *h);> - -Return the file descriptor of the pty of the subprocess. You can read -and write to this if you want, although convenience functions are also -provided (see below). - -B<pid_t mexp_get_pid (mexp_h *h);> - -Return the process ID of the subprocess. You can send it signals if -you want. - -B<int mexp_get_timeout_ms (mexp_h *h);> - -B<void mexp_set_timeout_ms (mexp_h *h, int millisecs);> - -B<void mexp_set_timeout (mexp_h *h, int secs);> - -Get or set the timeout used by C<mexp_expect> [see below]. The -resolution is milliseconds (1/1000th of a second). Set this before -calling C<mexp_expect>. Passing -1 to either of the C<set_> methods -means no timeout. The default setting is 60000 milliseconds (60 -seconds). - -B<size_t mexp_get_read_size (mexp *h);> - -B<void mexp_set_read_size (mexp *h, size_t read_size);> - -Get or set the natural size (in bytes) for reads from the subprocess. -The default is 1024. Most callers will not need to change this. - -B<int mexp_get_pcre_error (mexp *h);> - -When C<mexp_expect> [see below] calls the PCRE function -L<pcre_exec(3)>, it stashes the return value in the C<pcre_error> -field in the handle, and that field is returned by this method. - -There are two uses for this: - -=over 4 - -=item 1. - -If C<mexp_expect> returns C<MEXP_PCRE_ERROR>, then the actual PCRE -error code returned by L<pcre_exec(3)> is available by calling this -method. For a list of PCRE error codes, see L<pcreapi(3)>. - -=item 2. - -A more unusual use is if you ever need to get the captured substrings -from your regular expression (calling L<pcre_get_substring(3)>). The -third parameter of that function (C<stringcount>) is the value -returned by L<pcre_exec(3)>, and so you can call it like this: - - pcre_get_substring (h->buffer, ovector, - mexp_get_pcre_error (h), 1, &matched); - -=back - -B<void mexp_set_debug_file (mexp *h, FILE *fp);> - -B<FILE *mexp_get_debug_file (mexp *h);> - -Set or get the debug file of the handle. To enable debugging, pass a -non-C<NULL> file handle, eg. C<stderr>. To disable debugging, pass -C<NULL>. Debugging messages are printed on the file handle. - -Note that all output and input gets printed, including passwords. To -prevent passwords from being printed, modify your code to call -C<mexp_printf_password> instead of C<mexp_printf>. - -The following fields in the handle do not have methods, but can be -accessed directly instead: - - char *buffer; - size_t len; - size_t alloc; - -If C<mexp_expect> returns a match then these variables contain the -read buffer. Note this buffer does not contain the full input from -the process, but it will contain at least the part matched by the -regular expression (and maybe some more). C<buffer> is the read -buffer and C<len> is the number of bytes of data in the buffer. - - ssize_t next_match; - -If C<mexp_expect> returns a match, then C<next_match> points to the -first byte in the buffer I<after> the fully matched expression. (It -may be C<-1> which means it is invalid). The next time that -C<mexp_expect> is called, it will start by consuming the data -C<buffer[next_match...len-1]>. Callers may also need to read from -that point in the buffer before calling L<read(2)> on the file -descriptor. Callers may also set this, for example setting it to -C<-1> in order to ignore the remainder of the buffer. In most cases -callers can ignore this field, and C<mexp_expect> will just do the -right thing when called repeatedly. - - void *user1; - void *user2; - void *user3; - -Opaque pointers for use by the caller. The library will not touch -these. - -=head1 CLOSING THE HANDLE - -To close the handle and clean up the subprocess, call: - -B<int mexp_close (mexp_h *h);> - -This returns the status code from the subprocess. This is in the form -of a L<waitpid(2)>/L<system(3)> status so you have to use the macros -C<WIFEXITED>, C<WEXITSTATUS>, C<WIFSIGNALED>, C<WTERMSIG> etc defined -in C<E<lt>sys/wait.hE<gt>> to parse it. - -If there was a system call error, then C<-1> is returned. The error -will be in C<errno>. - -Notes: - -=over 4 - -=item * - -Even in error cases, the handle is always closed and its memory is -freed by this call. - -=item * - -It is normal for the kernel to send SIGHUP to the subprocess. - -If the subprocess doesn't catch the SIGHUP, then it will die -with status: - - WIFSIGNALED (status) && WTERMSIG (status) == SIGHUP - -This case should not necessarily be considered an error. - -=back - -This is how code should check for and print errors from C<mexp_close>: - - status = mexp_close (h); - if (status == -1) { - perror ("mexp_close"); - return -1; - } - if (WIFSIGNALED (status) && WTERMSIG (status) == SIGHUP) - goto ignore; /* not an error */ - if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) - /* You could use the W* macros to print a better error message. */ - fprintf (stderr, "error: subprocess failed, status = %d", status); - return -1; - } - ignore: - /* no error case */ - -=head1 EXPECT FUNCTION - -Miniexpect contains a powerful regular expression matching function -based on L<pcre(3)>: - -B<int mexp_expect (mexp_h *h, const mexp_regexp *regexps, -int *ovector, int ovecsize);> - -The output of the subprocess is matched against the list of PCRE -regular expressions in C<regexps>. C<regexps> is a list of regular -expression structures: - - struct mexp_regexp { - int r; - const pcre *re; - const pcre_extra *extra; - int options; - }; - typedef struct mexp_regexp mexp_regexp; - -C<r> is the integer code returned from C<mexp_expect> if this regular -expression matches. It B<must> be E<gt> 0. C<r == 0> indicates the -end of the list of regular expressions. C<re> is the compiled regular -expression. - -Possible return values are: - -=over 4 - -=item C<MEXP_TIMEOUT> - -No input matched before the timeout (C<h-E<gt>timeout>) was -reached. - -=item C<MEXP_EOF> - -The subprocess closed the connection. - -=item C<MEXP_ERROR> - -There was a system call error (eg. from the read call). The error is -returned in C<errno>. - -=item C<MEXP_PCRE_ERROR> - -There was a C<pcre_exec> error. C<h-E<gt>pcre_error> is set to the -error code. See L<pcreapi(3)> for a list of the C<PCRE_*> error codes -and what they mean. - -=item C<r> E<gt> 0 - -If any regexp matches, the associated integer code (C<regexps[].r>) -is returned. - -=back - -Notes: - -=over 4 - -=item * - -C<regexps> may be NULL or an empty list, which means we don't match -against a regular expression. This is useful if you just want to wait -for EOF or timeout. - -=item * - -C<regexps[].re>, C<regexps[].extra>, C<regexps[].options>, C<ovector> -and C<ovecsize> are passed through to the L<pcre_exec(3)> function. - -=item * - -If multiple regular expressions are passed, then they are checked in -turn and the I<first> regular expression that matches is returned -I<even if the match happens later in the input than another regular -expression>. - -For example if the input is C<"hello world"> and you pass the two -regular expressions: - - regexps[0].re = world - regexps[1].re = hello - -then the first regular expression (C<"world">) may match and the -C<"hello"> part of the input may be ignored. - -In some cases this can even lead to unpredictable matching. In the -case above, if we only happened to read C<"hello wor">, then the -second regular expression (C<"hello">) I<would> match. - -If this is a concern, combine your regular expressions into a single -one, eg. C<(hello)|(world)>. - -=back - -=head2 mexp_expect example - -It is easier to understand C<mexp_expect> by considering a simple -example. - -In this example we are waiting for ssh to either send us a password -prompt, or (if no password was required) a command prompt, and based -on the output we will either send back a password or a command. - -The unusual C<(mexp_regexp[]){...}> syntax is called a "compound -literal" and is available in C99. If you need to use an older -compiler, you can just use a local variable instead. - - mexp_h *h; - char *errptr; - int offset; - pcre *password_re, *prompt_re; - const int ovecsize = 12; - int ovector[ovecsize]; - - password_re = pcre_compile ("assword", 0, &errptr, &offset, NULL); - prompt_re = pcre_compile ("[$#] ", 0, &errptr, &offset, NULL); - - switch (mexp_expect (h, - (mexp_regexp[]) { - { 100, .re = password_re }, - { 101, .re = prompt_re }, - { 0 }, - }, ovector, ovecsize)) { - case 100: - /* here you would send a password */ - break; - case 101: - /* here you would send a command */ - break; - case MEXP_EOF: - fprintf (stderr, "error: ssh closed the connection unexpectedly\n"); - exit (EXIT_FAILURE); - case MEXP_TIMEOUT: - fprintf (stderr, "error: timeout before reaching the prompt\n"); - exit (EXIT_FAILURE); - case MEXP_ERROR: - perror ("mexp_expect"); - exit (EXIT_FAILURE); - case MEXP_PCRE_ERROR: - fprintf (stderr, "error: PCRE error: %d\n", h->pcre_error); - exit (EXIT_FAILURE); - } - -=head1 SENDING COMMANDS TO THE SUBPROCESS - -You can write to the subprocess simply by writing to C<h-E<gt>fd>. -However we also provide a convenience function: - -B<int mexp_printf (mexp_h *h, const char *fs, ...);> - -B<int mexp_printf_password (mexp_h *h, const char *fs, ...);> - -This returns the number of bytes, if the whole message was written OK. -If there was an error, -1 is returned and the error is available in -C<errno>. - -Notes: - -=over 4 - -=item * - -C<mexp_printf> will not do a partial write. If it cannot write all -the data, then it will return an error. - -=item * - -This function does not write a newline automatically. If you want to -send a command followed by a newline you have to do something like: - - mexp_printf (h, "exit\n"); - -=item * - -C<mexp_printf_password> works identically to C<mexp_printf> except -that the output is I<not> sent to the debugging file if debugging is -enabled. As the name suggests, use this for passwords so that they -don't appear in debugging output. - -=back - -B<int mexp_send_interrupt (mexp_h *h);> - -Send the interrupt character (C<^C>, Ctrl-C, C<\003>). This is like -pressing C<^C> - the subprocess (or remote process, if using C<ssh>) -is gracefully killed. - -Note this only works if the pty is in cooked mode -(ie. C<MEXP_SPAWN_COOKED_MODE> was passed to C<mexp_spawnlf> or -C<mexp_spawnvf>). In raw mode, all characters are passed through -without any special interpretation. - -=head1 SOURCE - -Source is available from: -L<http://git.annexia.org/?p=miniexpect.git;a=summary> - -=head1 SEE ALSO - -L<pcre(3)>, -L<pcre_exec(3)>, -L<pcreapi(3)>, -L<waitpid(2)>, -L<system(3)>. - -=head1 AUTHORS - -Richard W.M. Jones (C<rjones at redhat dot com>) - -=head1 LICENSE - -The library is released under the Library GPL (LGPL) version 2 or at -your option any later version. - -=head1 COPYRIGHT - -Copyright (C) 2014 Red Hat Inc. diff --git a/configure.ac b/configure.ac index 93fe063b4..729713099 100644 --- a/configure.ac +++ b/configure.ac @@ -166,8 +166,8 @@ m4_include([m4/guestfs-rust.m4]) HEADING([Checking for Vala]) VAPIGEN_CHECK -dnl virt-v2v, virt-p2v. -HEADING([Checking the virt-v2v and virt-p2v dependencies]) +dnl virt-v2v. +HEADING([Checking the virt-v2v dependencies]) m4_include([m4/guestfs-v2v.m4]) dnl Bash completion. @@ -236,7 +236,6 @@ AC_CONFIG_FILES([Makefile cat/Makefile common/errnostring/Makefile common/edit/Makefile - common/miniexpect/Makefile common/mlaugeas/Makefile common/mlgettext/Makefile common/mllibvirt/Makefile diff --git a/contrib/README b/contrib/README index 811f005c6..fb359f9e3 100644 --- a/contrib/README +++ b/contrib/README @@ -18,9 +18,6 @@ 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/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES index 855223d44..a6a5838c4 100644 --- a/docs/C_SOURCE_FILES +++ b/docs/C_SOURCE_FILES @@ -12,8 +12,6 @@ cat/ls.c cat/tail.c common/edit/file-edit.c common/edit/file-edit.h -common/miniexpect/miniexpect.c -common/miniexpect/miniexpect.h common/mlaugeas/augeas-c.c common/mlgettext/dummy.c common/mllibvirt/libvirt_c_epilogue.c diff --git a/docs/guestfs-building.pod b/docs/guestfs-building.pod index 94ec079a5..441fe0937 100644 --- a/docs/guestfs-building.pod +++ b/docs/guestfs-building.pod @@ -76,7 +76,7 @@ I<Required>. =item qemu-img E<ge> 1.3.0 -I<Required>. Virt-p2v and virt-v2v requires qemu-img E<ge> 2.2.0. +I<Required>. Virt-v2v requires qemu-img E<ge> 2.2.0. =item kernel E<ge> 2.6.34 @@ -272,10 +272,6 @@ Optional. Used only for testing. Optional. qemu-nbd is used for testing. -L<virt-p2v(1)> requires either qemu-nbd or nbdkit, but these only need -to be present on the virt-p2v ISO, they do not need to be installed at -compile time. - =item uml_mkcow Optional. For the L<UML backend|guestfs(3)/BACKEND>. @@ -293,27 +289,6 @@ Optional. Used by virt-builder for checking digital signatures. Optional. If available, virt-builder will use this library for fast, parallel uncompression of templates. -=item Gtk E<ge> 2.24, or 3 - -Optional. - -Used by the virt-p2v graphical user interface. - -Either Gtk 2 or Gtk 3 can be used. If you want to select a specific -version of Gtk, use S<C<./configure --with-gtk=2>> or -S<C<./configure --with-gtk=3>>. - -=item D-Bus - -Optional. - -If the D-Bus low level C API is available, virt-p2v can send a D-Bus -message to logind to inhibit power saving (sleep, suspend, etc) during -P2V conversions. - -If this API is not available at build time, then very long conversions -might be interrupted if the physical machine goes to sleep. - =item zip =item unzip @@ -688,11 +663,6 @@ indicate this is I<not> a distro build. Compile libguestfs without libvirt support, even if libvirt development libraries are installed. -=item B<--with-gtk=2> - -This option forces virt-p2v to be built against Gtk 2, which is -currently the most widely tested configuration. - =item B<--with-qemu=">bin1 bin2 ...B<"> Provide an alternate qemu binary (or list of binaries). This can be @@ -843,29 +813,6 @@ The sources and spec files for RHEL versions of libguestfs are available on L<https://git.centos.org/project/rpms>, and see also L<https://wiki.centos.org/Sources>. -=head1 BUILDING i686 32 BIT VIRT-P2V - -I<(This section only applies on the x86-64 architecture.)> - -Building a 32 bit virt-p2v (i686) binary improves compatibility with -older hardware. See L<virt-p2v-make-disk(1)> for details. Although -virt-p2v is a simple Gtk application, it is not especially easy to -build just virt-p2v as a 32 bit application on a 64 bit host. Usually -the simplest way is to use a 32 bit chroot or even a 32 bit virtual -machine to build libguestfs. - -On Fedora you can use the L<mock(1)> tool. For example: - - fedpkg mockbuild --root fedora-23-i386 - -This will result in a F<virt-v2v-*.i686.rpm> file which can be -unpacked to extract the 32 bit virt-p2v binary. - -The binary may be compressed to either F<p2v/virt-p2v.i686.xz>, or -F<$libdir/virt-p2v/virt-p2v.i686.xz> or -F<$VIRT_P2V_DATA_DIR/virt-p2v.i686.xz> as appropriate. This enables -the L<virt-p2v-make-disk(1)> I<--arch> option. - =head1 SEE ALSO L<guestfs(3)>, diff --git a/docs/guestfs-hacking.pod b/docs/guestfs-hacking.pod index ff8b955af..2efa7a9a7 100644 --- a/docs/guestfs-hacking.pod +++ b/docs/guestfs-hacking.pod @@ -94,12 +94,6 @@ The communication protocol used between the library and the daemon running inside the appliance has to encode errnos as strings, which is handled by this library. -=item F<common/miniexpect> - -A copy of the miniexpect library from -L<http://git.annexia.org/?p=miniexpect.git;a=summary>. This is used -in virt-p2v. - =item F<common/mlaugeas> Bindings for the Augeas library. These come from the ocaml-augeas @@ -267,11 +261,6 @@ M4 macros used by autoconf. See L</THE BUILD SYSTEM>. L<virt-make-fs(1)> command and documentation. -=item F<p2v> - -L<virt-p2v(1)> command, documentation and scripts for building the -virt-p2v ISO or disk image. - =item F<po> Translations of simple gettext strings. @@ -986,78 +975,6 @@ Every other file in this directory is a support module / library of some sort. Some code is written in C, especially where we want to use an external C library such as libxml2. -=head2 VIRT-P2V - -Virt-p2v is a front end on virt-v2v. ie. All it does is act as a GUI -front end, and it calls out to virt-v2v to perform the actual -conversion. Therefore most of the C code in the F<p2v/> subdirectory -is Gtk (GUI) code, or supporting code for talking to the remote -conversion server. There is no special support for physical machines -in virt-v2v. They are converted in the same way as foreign VMs. - -=head3 Running virt-p2v - -You can run the F<p2v/virt-p2v> binary directly, but it will try to -convert your machine’s real F</dev/sda> which is unlikely to work -well. However virt-p2v also has a test mode in which you can supply a -test disk: - - make -C p2v run-virt-p2v-directly - -This is a wrapper around the L<virt-p2v(1)> I<--test-disk> option. -You can control the "physical machine" disk by setting -C<PHYSICAL_MACHINE> to point to a disk image. - -A more realistic test is to run virt-p2v inside a VM on the local -machine. To do that, do: - - make -C p2v run-virt-p2v-in-a-vm - -This also runs qemu with the "physical machine" disk (which you can -set by setting C<PHYSICAL_MACHINE>), a virtual CD, and a variety of -network cards for testing. You can change the qemu binary and add -extra qemu options by setting C<QEMU> and/or C<QEMU_OPTIONS> on the -make commandline. - -A third way to run virt-p2v simulates fairly accurately the program -being downloaded over PXE and then doing an automatic conversion of -the source physical machine (the non-GUI path -- see next section -below): - - make -C p2v run-virt-p2v-non-gui-conversion - -=head3 Understanding the virt-p2v code - -I<See also:> L<virt-p2v(1)/HOW VIRT-P2V WORKS> - -There are two paths through the code, GUI or non-GUI (parsing the -kernel command line): - - main.c ──────┬─────▶ gui.c ──────┬─────▶ conversion.c - │ │ - │ │ - └────▶ kernel.c ────┘ - -but both paths call back to the F<conversion.c> function -C<start_conversion> to run the remote virt-v2v. - -The main task of F<gui.c>/F<kernel.c> is to populate the virt-v2v -configuration (F<config.c>). - -During conversion, we need to establish ssh connections, and that is -done using two libraries: - - conversion.c ──────▶ ssh.c ──────▶ miniexpect.c - -where F<ssh.c> is responsible for managing ssh connections overall, -and F<miniexpect.c> implements "expect-like" functionality for talking -interactively to the remote virt-v2v conversion server. - -(Note that miniexpect is a separate library with its own upstream, so -if you patch miniexpect.c, then please make sure the changes get -reflected in miniexpect’s upstream too: -F<http://git.annexia.org/?p=miniexpect.git;a=summary>) - =head1 MAINTAINER TASKS =head2 MAINTAINER MAKEFILE TARGETS diff --git a/generator/authors.ml b/generator/authors.ml index 3c8ee1de3..2d91f9d35 100644 --- a/generator/authors.ml +++ b/generator/authors.ml @@ -134,12 +134,3 @@ let authors = [ let generate_authors () List.iter (fun (name, _, _) -> pr "%s\n" name) authors - -let generate_p2v_authors () - let p2v_authors - List.filter_map ( - fun (name, _, roles) -> - if List.mem V2V_and_P2V roles then Some name - else None - ) authors in - List.iter (pr "%s\n") p2v_authors diff --git a/generator/authors.mli b/generator/authors.mli index 834bcb811..3009995d4 100644 --- a/generator/authors.mli +++ b/generator/authors.mli @@ -23,4 +23,3 @@ val authors : (string * string list * role list) list (** List of authors, their aliases, and their roles. *) val generate_authors : unit -> unit -val generate_p2v_authors : unit -> unit diff --git a/m4/guestfs-v2v.m4 b/m4/guestfs-v2v.m4 index 59d502f10..b14c364e2 100644 --- a/m4/guestfs-v2v.m4 +++ b/m4/guestfs-v2v.m4 @@ -15,7 +15,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -dnl Virt-v2v and virt-p2v. +dnl Virt-v2v. dnl nbdkit python plugin. AC_MSG_CHECKING([for the nbdkit python plugin name]) @@ -26,53 +26,3 @@ AC_ARG_WITH([virt-v2v-nbdkit-python-plugin], [VIRT_V2V_NBDKIT_PYTHON_PLUGIN=python]) AC_MSG_RESULT([$VIRT_V2V_NBDKIT_PYTHON_PLUGIN]) AC_SUBST([VIRT_V2V_NBDKIT_PYTHON_PLUGIN]) - -dnl Check for Gtk 2 or 3 library, used by virt-p2v. -AC_MSG_CHECKING([for --with-gtk option]) -AC_ARG_WITH([gtk], - [AS_HELP_STRING([--with-gtk=2|3|check|no], - [prefer Gtk version 2 or 3. @<:@default=check@:>@])], - [with_gtk="$withval" - AC_MSG_RESULT([$withval])], - [with_gtk="check" - AC_MSG_RESULT([not set, will check for installed Gtk])] -) - -if test "x$with_gtk" = "x3"; then - PKG_CHECK_MODULES([GTK], [gtk+-3.0], [ - GTK_VERSION=3 - ]) -elif test "x$with_gtk" = "x2"; then - PKG_CHECK_MODULES([GTK], [gtk+-2.0], [ - GTK_VERSION=2 - ], []) -elif test "x$with_gtk" = "xcheck"; then - PKG_CHECK_MODULES([GTK], [gtk+-3.0], [ - GTK_VERSION=3 - ], [ - PKG_CHECK_MODULES([GTK], [gtk+-2.0], [ - GTK_VERSION=2 - ], [:]) - ]) -fi - -dnl D-Bus is an optional dependency of virt-p2v. -PKG_CHECK_MODULES([DBUS], [dbus-1], [ - AC_SUBST([DBUS_CFLAGS]) - AC_SUBST([DBUS_LIBS]) - AC_DEFINE([HAVE_DBUS],[1],[D-Bus found at compile time.]) -],[ - AC_MSG_WARN([D-Bus not found, virt-p2v will not be able to inhibit power saving during P2V conversions]) -]) - -dnl Can we build virt-p2v? -AC_MSG_CHECKING([if we can build virt-p2v]) -if test "x$GTK_LIBS" != "x"; then - AC_MSG_RESULT([yes, with Gtk $GTK_VERSION]) - AC_SUBST([GTK_CFLAGS]) - AC_SUBST([GTK_LIBS]) - AC_SUBST([GTK_VERSION]) -else - AC_MSG_RESULT([no]) -fi -AM_CONDITIONAL([HAVE_P2V], [test "x$GTK_LIBS" != "x"]) diff --git a/po-docs/podfiles b/po-docs/podfiles index 7d90267a1..b0deb00df 100644 --- a/po-docs/podfiles +++ b/po-docs/podfiles @@ -8,7 +8,6 @@ ../cat/virt-log.pod ../cat/virt-ls.pod ../cat/virt-tail.pod -../common/miniexpect/miniexpect.pod ../customize/customize-options.pod ../customize/customize-synopsis.pod ../customize/virt-customize.pod diff --git a/po/POTFILES b/po/POTFILES index 2a41a26c8..2409ef72a 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -14,7 +14,6 @@ cat/tail.c common/edit/file-edit.c common/errnostring/errnostring-gperf.c common/errnostring/errnostring.c -common/miniexpect/miniexpect.c common/mlaugeas/augeas-c.c common/mlgettext/dummy.c common/mllibvirt/generator.pl diff --git a/run.in b/run.in index f484f1b76..7e4963cdf 100755 --- a/run.in +++ b/run.in @@ -98,7 +98,6 @@ prepend PATH "$b/fuse" prepend PATH "$b/get-kernel" prepend PATH "$b/inspector" prepend PATH "$b/make-fs" -prepend PATH "$b/p2v" prepend PATH "$b/rescue" prepend PATH "$b/resize" prepend PATH "$b/sparsify" @@ -125,12 +124,6 @@ if [ -z "$XDG_CONFIG_DIRS" ]; then export XDG_CONFIG_DIRS fi -# virt-p2v-make-* data directory. -if [ -z "$VIRT_P2V_DATA_DIR" ]; then - VIRT_P2V_DATA_DIR="$b/p2v" - export VIRT_P2V_DATA_DIR -fi - # For Perl. prepend PERL5LIB "$b/perl/blib/arch" prepend PERL5LIB "$b/perl/blib/lib" -- 2.21.0
Richard W.M. Jones
2019-Sep-10 15:41 UTC
Re: [Libguestfs] [PATCH 0/2] Remove virt-p2v from libguestfs
ACK series, thanks. 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