Compare commits
No commits in common. 'c9' and 'c8-stream-rhel' have entirely different histories.
c9
...
c8-stream-
@ -1,2 +1,5 @@
|
|||||||
|
SOURCES/RHEV-Application-Provisioning-Tool.exe_4.43-5
|
||||||
SOURCES/libguestfs.keyring
|
SOURCES/libguestfs.keyring
|
||||||
SOURCES/virt-v2v-2.4.0.tar.gz
|
SOURCES/rhsrvany-fd659e77cdd9da484fdc9dcbe0605c62ec26fa30.tar.gz
|
||||||
|
SOURCES/rhsrvany.exe
|
||||||
|
SOURCES/virt-v2v-1.42.0.tar.gz
|
||||||
|
@ -1,2 +1,5 @@
|
|||||||
|
130adbc011dc0af736465b813c2b22a600c128c1 SOURCES/RHEV-Application-Provisioning-Tool.exe_4.43-5
|
||||||
1bbc40f501a7fef9eef2a39b701a71aee2fea7c4 SOURCES/libguestfs.keyring
|
1bbc40f501a7fef9eef2a39b701a71aee2fea7c4 SOURCES/libguestfs.keyring
|
||||||
52029cc7c3f9e05ec9685995ad86955154d7b28e SOURCES/virt-v2v-2.4.0.tar.gz
|
136ff75deb496e48eb448bc4ae156f3911464a90 SOURCES/rhsrvany-fd659e77cdd9da484fdc9dcbe0605c62ec26fa30.tar.gz
|
||||||
|
2bd96e478fc004cd323b5bd754c856641877dac6 SOURCES/rhsrvany.exe
|
||||||
|
bdbdc7cca87735af64f7e99c050ead24fa92aa7d SOURCES/virt-v2v-1.42.0.tar.gz
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
From 2ab37349cf37d0ffdb9929ca24c2a024600a4848 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pino Toscano <ptoscano@redhat.com>
|
||||||
|
Date: Thu, 21 May 2020 13:32:21 +0200
|
||||||
|
Subject: [PATCH] libvirt: make use of libvirt's default auth handler
|
||||||
|
(RHBZ#1838425)
|
||||||
|
|
||||||
|
Use the default libvirt authentication handler as base for ours,
|
||||||
|
overriding it with our callback only in case we have a password to
|
||||||
|
supply.
|
||||||
|
|
||||||
|
(cherry picked from commit ce66cac50179baf2fb8b404f7eba49048c7819b0)
|
||||||
|
---
|
||||||
|
v2v/libvirt_utils.ml | 12 ++++++++----
|
||||||
|
1 file changed, 8 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/libvirt_utils.ml b/v2v/libvirt_utils.ml
|
||||||
|
index 7df17b29..4d0b8639 100644
|
||||||
|
--- a/v2v/libvirt_utils.ml
|
||||||
|
+++ b/v2v/libvirt_utils.ml
|
||||||
|
@@ -33,10 +33,14 @@ let auth_for_password_file ?password_file () =
|
||||||
|
) creds
|
||||||
|
in
|
||||||
|
|
||||||
|
- {
|
||||||
|
- Libvirt.Connect.credtype = [ Libvirt.Connect.CredentialPassphrase ];
|
||||||
|
- cb = auth_fn;
|
||||||
|
- }
|
||||||
|
+ let base_auth = Libvirt.Connect.get_auth_default () in
|
||||||
|
+
|
||||||
|
+ if password_file = None then
|
||||||
|
+ base_auth
|
||||||
|
+ else
|
||||||
|
+ { base_auth with
|
||||||
|
+ cb = auth_fn;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
let get_domain conn name =
|
||||||
|
let dom =
|
@ -1,39 +0,0 @@
|
|||||||
From af68f253d1a11c4abaa30ae348ee3855cdec74e9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Thu, 11 Jan 2024 15:33:08 +0000
|
|
||||||
Subject: [PATCH] virt-v2v: -i vmx: Remove scp -T option
|
|
||||||
|
|
||||||
This reverts the following commit:
|
|
||||||
|
|
||||||
commit d265639c2ab31418cfdbdedd0cc3e68cf290d834
|
|
||||||
Author: Richard W.M. Jones <rjones@redhat.com>
|
|
||||||
Date: Thu Jul 25 14:52:42 2019 +0100
|
|
||||||
|
|
||||||
v2v: -i vmx: Use scp -T option if available to unbreak scp (RHBZ#1733168).
|
|
||||||
|
|
||||||
See also the referenced bug:
|
|
||||||
https://bugzilla.redhat.com/show_bug.cgi?id=1733168
|
|
||||||
|
|
||||||
My rationale for removing this option is that since we now require
|
|
||||||
OpenSSH 8.8 we must be using sftp for file transfer so we no longer
|
|
||||||
need to defeat the check for correct expansion of wildcards. That
|
|
||||||
check was only relevant for OpenSSH <= 8.7 using the old scp protocol.
|
|
||||||
|
|
||||||
Reverts: commit d265639c2ab31418cfdbdedd0cc3e68cf290d834
|
|
||||||
---
|
|
||||||
input/parse_domain_from_vmx.ml | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/input/parse_domain_from_vmx.ml b/input/parse_domain_from_vmx.ml
|
|
||||||
index 2e75e785..f24990f8 100644
|
|
||||||
--- a/input/parse_domain_from_vmx.ml
|
|
||||||
+++ b/input/parse_domain_from_vmx.ml
|
|
||||||
@@ -68,7 +68,7 @@ let scp_from_remote_to_temporary uri tmpdir filename =
|
|
||||||
let localfile = tmpdir // filename in
|
|
||||||
|
|
||||||
let cmd =
|
|
||||||
- sprintf "scp -T%s%s %s%s:%s %s"
|
|
||||||
+ sprintf "scp%s%s %s%s:%s %s"
|
|
||||||
(if verbose () then "" else " -q")
|
|
||||||
(match port_of_uri uri with
|
|
||||||
| None -> ""
|
|
@ -1,48 +0,0 @@
|
|||||||
From 60d4a517e43f0715fb9dc4f87cbd2f5c88ab662a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Weblate Translation Memory
|
|
||||||
<noreply-mt-weblate-translation-memory@weblate.org>
|
|
||||||
Date: Mon, 15 Jan 2024 14:37:13 +0100
|
|
||||||
Subject: [PATCH] Translated using Weblate (Polish)
|
|
||||||
|
|
||||||
Currently translated at 7.2% (35 of 481 strings)
|
|
||||||
|
|
||||||
Translation: libguestfs/virt-v2v-master
|
|
||||||
Translate-URL: https://translate.fedoraproject.org/projects/libguestfs/virt-v2v-master/pl/
|
|
||||||
---
|
|
||||||
po/pl.po | 9 +++++----
|
|
||||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/po/pl.po b/po/pl.po
|
|
||||||
index d4bee25f..e3a5b11d 100644
|
|
||||||
--- a/po/pl.po
|
|
||||||
+++ b/po/pl.po
|
|
||||||
@@ -14,8 +14,9 @@ msgstr ""
|
|
||||||
"Report-Msgid-Bugs-To: https://bugzilla.redhat.com/enter_bug."
|
|
||||||
"cgi?component=libguestfs&product=Virtualization+Tools\n"
|
|
||||||
"POT-Creation-Date: 2023-11-02 11:07+0000\n"
|
|
||||||
-"PO-Revision-Date: 2023-11-26 21:01+0000\n"
|
|
||||||
-"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
|
|
||||||
+"PO-Revision-Date: 2024-01-15 13:36+0000\n"
|
|
||||||
+"Last-Translator: Weblate Translation Memory <noreply-mt-weblate-translation-"
|
|
||||||
+"memory@weblate.org>\n"
|
|
||||||
"Language-Team: Polish <https://translate.fedoraproject.org/projects/"
|
|
||||||
"libguestfs/virt-v2v-master/pl/>\n"
|
|
||||||
"Language: pl\n"
|
|
||||||
@@ -24,7 +25,7 @@ msgstr ""
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
|
||||||
"|| n%100>=20) ? 1 : 2;\n"
|
|
||||||
-"X-Generator: Weblate 5.2.1\n"
|
|
||||||
+"X-Generator: Weblate 5.3.1\n"
|
|
||||||
|
|
||||||
#: input/input_ova.ml:136 common/mltools/tools_utils.ml:235
|
|
||||||
msgid "%s"
|
|
||||||
@@ -735,7 +736,7 @@ msgstr ""
|
|
||||||
#. common/mlcustomize/customize_cmdline.ml:245
|
|
||||||
#: common/mlcustomize/customize_cmdline.ml:453
|
|
||||||
msgid "PATH"
|
|
||||||
-msgstr ""
|
|
||||||
+msgstr "ŚCIEŻKA"
|
|
||||||
|
|
||||||
#: common/mlcustomize/customize_cmdline.ml:191
|
|
||||||
msgid "PERMISSIONS:FILE"
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,94 @@
|
|||||||
|
From 939d57ef4d5bcfa31e9b98104822962b89572481 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 19 May 2020 14:40:01 +0100
|
||||||
|
Subject: [PATCH] v2v: -o libvirt: Remove cache=none (RHBZ#1837453).
|
||||||
|
|
||||||
|
Traditionally if you did live migration (KVM to KVM), you had to
|
||||||
|
ensure that cache=none was set on all disks of the guest up front.
|
||||||
|
This was because of quirks in how NFS works (I think the close-to-open
|
||||||
|
consistency and the fact that during live migration both qemus have
|
||||||
|
the file open), and we had to assume the worst case that a guest might
|
||||||
|
be backed by NFS.
|
||||||
|
|
||||||
|
Because of this when virt-v2v converts a guest to run on KVM using
|
||||||
|
libvirt it sets cache=none.
|
||||||
|
|
||||||
|
This is not necessary with modern qemu. If qemu supports the
|
||||||
|
drop-cache property of the file block driver, which libvirt will
|
||||||
|
automatically detect for us, then libvirt live migration is able to
|
||||||
|
tell qemu to drop cached data at the right time even if the backing is
|
||||||
|
NFS.
|
||||||
|
|
||||||
|
It also had a significant performance impact. In some synthetic
|
||||||
|
benchmarks it could show 2 or 3 times slower performance.
|
||||||
|
|
||||||
|
Thanks: Ming Xie, Peter Krempa.
|
||||||
|
(cherry picked from commit 9720f45e0cd9283739fd2a67c19e66912489dfc7)
|
||||||
|
---
|
||||||
|
docs/virt-v2v-output-local.pod | 2 +-
|
||||||
|
tests/test-v2v-cdrom.expected | 2 +-
|
||||||
|
tests/test-v2v-floppy.expected | 2 +-
|
||||||
|
tests/test-v2v-i-ova.xml | 2 +-
|
||||||
|
v2v/create_libvirt_xml.ml | 1 -
|
||||||
|
5 files changed, 4 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/docs/virt-v2v-output-local.pod b/docs/virt-v2v-output-local.pod
|
||||||
|
index 38df007d..a5f155cb 100644
|
||||||
|
--- a/docs/virt-v2v-output-local.pod
|
||||||
|
+++ b/docs/virt-v2v-output-local.pod
|
||||||
|
@@ -127,7 +127,7 @@ Edit F</var/tmp/NAME.xml> to change F</var/tmp/NAME-sda> to the pool
|
||||||
|
name. In other words, locate the following bit of XML:
|
||||||
|
|
||||||
|
<disk type='file' device='disk'>
|
||||||
|
- <driver name='qemu' type='raw' cache='none' />
|
||||||
|
+ <driver name='qemu' type='raw' />
|
||||||
|
<source file='/var/tmp/NAME-sda' />
|
||||||
|
<target dev='hda' bus='ide' />
|
||||||
|
</disk>
|
||||||
|
diff --git a/tests/test-v2v-cdrom.expected b/tests/test-v2v-cdrom.expected
|
||||||
|
index e18ea6f2..34d2bf59 100644
|
||||||
|
--- a/tests/test-v2v-cdrom.expected
|
||||||
|
+++ b/tests/test-v2v-cdrom.expected
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
<disk type='file' device='disk'>
|
||||||
|
- <driver name='qemu' type='raw' cache='none'/>
|
||||||
|
+ <driver name='qemu' type='raw'/>
|
||||||
|
<target dev='vda' bus='virtio'/>
|
||||||
|
</disk>
|
||||||
|
<disk device='cdrom' type='file'>
|
||||||
|
diff --git a/tests/test-v2v-floppy.expected b/tests/test-v2v-floppy.expected
|
||||||
|
index dd74ed94..a718c21f 100644
|
||||||
|
--- a/tests/test-v2v-floppy.expected
|
||||||
|
+++ b/tests/test-v2v-floppy.expected
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
<disk type='file' device='disk'>
|
||||||
|
- <driver name='qemu' type='raw' cache='none'/>
|
||||||
|
+ <driver name='qemu' type='raw'/>
|
||||||
|
<target dev='vda' bus='virtio'/>
|
||||||
|
</disk>
|
||||||
|
<disk device='floppy' type='file'>
|
||||||
|
diff --git a/tests/test-v2v-i-ova.xml b/tests/test-v2v-i-ova.xml
|
||||||
|
index 7c198283..e26f4f83 100644
|
||||||
|
--- a/tests/test-v2v-i-ova.xml
|
||||||
|
+++ b/tests/test-v2v-i-ova.xml
|
||||||
|
@@ -22,7 +22,7 @@
|
||||||
|
<on_crash>restart</on_crash>
|
||||||
|
<devices>
|
||||||
|
<disk type='file' device='disk'>
|
||||||
|
- <driver name='qemu' type='raw' cache='none'/>
|
||||||
|
+ <driver name='qemu' type='raw'/>
|
||||||
|
<source file='TestOva-sda'/>
|
||||||
|
<target dev='vda' bus='virtio'/>
|
||||||
|
</disk>
|
||||||
|
diff --git a/v2v/create_libvirt_xml.ml b/v2v/create_libvirt_xml.ml
|
||||||
|
index 05553c4f..5a1fba0f 100644
|
||||||
|
--- a/v2v/create_libvirt_xml.ml
|
||||||
|
+++ b/v2v/create_libvirt_xml.ml
|
||||||
|
@@ -336,7 +336,6 @@ let create_libvirt_xml ?pool source targets target_buses guestcaps
|
||||||
|
e "driver" [
|
||||||
|
"name", "qemu";
|
||||||
|
"type", t.target_format;
|
||||||
|
- "cache", "none"
|
||||||
|
] [];
|
||||||
|
(match pool with
|
||||||
|
| None ->
|
@ -1,301 +0,0 @@
|
|||||||
From cddd07669d18a5a848f82dbde27b84ef405ef9fa Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Mon, 15 Jan 2024 14:24:35 +0000
|
|
||||||
Subject: [PATCH] virt-v2v: -i vmx: Refactor ssh/scp code into a new module
|
|
||||||
|
|
||||||
This is a straight refactor of the existing code that handles ssh/scp
|
|
||||||
into a new module. In this commit I just copy the code around without
|
|
||||||
doing any cleanup; cleanup will follow in subsequent commits.
|
|
||||||
|
|
||||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
|
||||||
---
|
|
||||||
input/Makefile.am | 6 ++-
|
|
||||||
input/input_vmx.ml | 8 ++--
|
|
||||||
input/parse_domain_from_vmx.ml | 60 ++-----------------------
|
|
||||||
input/parse_domain_from_vmx.mli | 6 ---
|
|
||||||
input/ssh.ml | 78 +++++++++++++++++++++++++++++++++
|
|
||||||
input/ssh.mli | 34 ++++++++++++++
|
|
||||||
6 files changed, 123 insertions(+), 69 deletions(-)
|
|
||||||
create mode 100644 input/ssh.ml
|
|
||||||
create mode 100644 input/ssh.mli
|
|
||||||
|
|
||||||
diff --git a/input/Makefile.am b/input/Makefile.am
|
|
||||||
index de016d60..4153f878 100644
|
|
||||||
--- a/input/Makefile.am
|
|
||||||
+++ b/input/Makefile.am
|
|
||||||
@@ -39,6 +39,7 @@ SOURCES_MLI = \
|
|
||||||
parse_domain_from_vmx.mli \
|
|
||||||
parse_libvirt_xml.mli \
|
|
||||||
parse_vmx.mli \
|
|
||||||
+ ssh.mli \
|
|
||||||
vCenter.mli
|
|
||||||
|
|
||||||
SOURCES_ML = \
|
|
||||||
@@ -46,11 +47,12 @@ SOURCES_ML = \
|
|
||||||
parse_libvirt_xml.ml \
|
|
||||||
OVF.ml \
|
|
||||||
OVA.ml \
|
|
||||||
- parse_vmx.ml \
|
|
||||||
- parse_domain_from_vmx.ml \
|
|
||||||
nbdkit_curl.ml \
|
|
||||||
nbdkit_ssh.ml \
|
|
||||||
nbdkit_vddk.ml \
|
|
||||||
+ ssh.ml \
|
|
||||||
+ parse_vmx.ml \
|
|
||||||
+ parse_domain_from_vmx.ml \
|
|
||||||
vCenter.ml \
|
|
||||||
input.ml \
|
|
||||||
input_disk.ml \
|
|
||||||
diff --git a/input/input_vmx.ml b/input/input_vmx.ml
|
|
||||||
index eed8a433..bd20420c 100644
|
|
||||||
--- a/input/input_vmx.ml
|
|
||||||
+++ b/input/input_vmx.ml
|
|
||||||
@@ -79,21 +79,21 @@ module VMX = struct
|
|
||||||
let socket = sprintf "%s/in%d" dir i in
|
|
||||||
On_exit.unlink socket;
|
|
||||||
|
|
||||||
- let vmx_path = path_of_uri uri in
|
|
||||||
+ let vmx_path = Ssh.path_of_uri uri in
|
|
||||||
let abs_path = absolute_path_from_other_file vmx_path filename in
|
|
||||||
let flat_vmdk = PCRE.replace (PCRE.compile "\\.vmdk$")
|
|
||||||
"-flat.vmdk" abs_path in
|
|
||||||
|
|
||||||
(* RHBZ#1774386 *)
|
|
||||||
- if not (remote_file_exists uri flat_vmdk) then
|
|
||||||
+ if not (Ssh.remote_file_exists uri flat_vmdk) then
|
|
||||||
error (f_"This transport does not support guests with snapshots. \
|
|
||||||
Either collapse the snapshots for this guest and try \
|
|
||||||
the conversion again, or use one of the alternate \
|
|
||||||
conversion methods described in \
|
|
||||||
virt-v2v-input-vmware(1) section \"NOTES\".");
|
|
||||||
|
|
||||||
- let server = server_of_uri uri in
|
|
||||||
- let port = Option.map string_of_int (port_of_uri uri) in
|
|
||||||
+ let server = Ssh.server_of_uri uri in
|
|
||||||
+ let port = Option.map string_of_int (Ssh.port_of_uri uri) in
|
|
||||||
let user = uri.Xml.uri_user in
|
|
||||||
let password =
|
|
||||||
match options.input_password with
|
|
||||||
diff --git a/input/parse_domain_from_vmx.ml b/input/parse_domain_from_vmx.ml
|
|
||||||
index f24990f8..8cf5893c 100644
|
|
||||||
--- a/input/parse_domain_from_vmx.ml
|
|
||||||
+++ b/input/parse_domain_from_vmx.ml
|
|
||||||
@@ -51,61 +51,6 @@ let vmx_source_of_arg input_transport arg =
|
|
||||||
error (f_"vmx URI path component looks incorrect");
|
|
||||||
SSH uri
|
|
||||||
|
|
||||||
-(* Return various fields from the URI. The checks in vmx_source_of_arg
|
|
||||||
- * should ensure that none of these assertions fail.
|
|
||||||
- *)
|
|
||||||
-let port_of_uri { Xml.uri_port } =
|
|
||||||
- match uri_port with i when i <= 0 -> None | i -> Some i
|
|
||||||
-let server_of_uri { Xml.uri_server } =
|
|
||||||
- match uri_server with None -> assert false | Some s -> s
|
|
||||||
-let path_of_uri { Xml.uri_path } =
|
|
||||||
- match uri_path with None -> assert false | Some p -> p
|
|
||||||
-
|
|
||||||
-(* 'scp' a remote file into a temporary local file, returning the path
|
|
||||||
- * of the temporary local file.
|
|
||||||
- *)
|
|
||||||
-let scp_from_remote_to_temporary uri tmpdir filename =
|
|
||||||
- let localfile = tmpdir // filename in
|
|
||||||
-
|
|
||||||
- let cmd =
|
|
||||||
- sprintf "scp%s%s %s%s:%s %s"
|
|
||||||
- (if verbose () then "" else " -q")
|
|
||||||
- (match port_of_uri uri with
|
|
||||||
- | None -> ""
|
|
||||||
- | Some port -> sprintf " -P %d" port)
|
|
||||||
- (match uri.Xml.uri_user with
|
|
||||||
- | None -> ""
|
|
||||||
- | Some user -> quote user ^ "@")
|
|
||||||
- (quote (server_of_uri uri))
|
|
||||||
- (quote (path_of_uri uri))
|
|
||||||
- (quote localfile) in
|
|
||||||
- if verbose () then
|
|
||||||
- eprintf "%s\n%!" cmd;
|
|
||||||
- if Sys.command cmd <> 0 then
|
|
||||||
- error (f_"could not copy the VMX file from the remote server, \
|
|
||||||
- see earlier error messages");
|
|
||||||
- localfile
|
|
||||||
-
|
|
||||||
-(* Test if [path] exists on the remote server. *)
|
|
||||||
-let remote_file_exists uri path =
|
|
||||||
- let cmd =
|
|
||||||
- sprintf "ssh%s %s%s test -f %s"
|
|
||||||
- (match port_of_uri uri with
|
|
||||||
- | None -> ""
|
|
||||||
- | Some port -> sprintf " -p %d" port)
|
|
||||||
- (match uri.Xml.uri_user with
|
|
||||||
- | None -> ""
|
|
||||||
- | Some user -> quote user ^ "@")
|
|
||||||
- (quote (server_of_uri uri))
|
|
||||||
- (* Double quoting is necessary for 'ssh', first to protect
|
|
||||||
- * from the local shell, second to protect from the remote
|
|
||||||
- * shell. https://github.com/libguestfs/virt-v2v/issues/35#issuecomment-1741730963
|
|
||||||
- *)
|
|
||||||
- (quote (quote path)) in
|
|
||||||
- if verbose () then
|
|
||||||
- eprintf "%s\n%!" cmd;
|
|
||||||
- Sys.command cmd = 0
|
|
||||||
-
|
|
||||||
let rec find_disks vmx vmx_source =
|
|
||||||
(* Set the s_disk_id field to an incrementing number. *)
|
|
||||||
List.mapi
|
|
||||||
@@ -390,7 +335,8 @@ let parse_domain_from_vmx vmx_source =
|
|
||||||
match vmx_source with
|
|
||||||
| File filename -> Parse_vmx.parse_file filename
|
|
||||||
| SSH uri ->
|
|
||||||
- let filename = scp_from_remote_to_temporary uri tmpdir "source.vmx" in
|
|
||||||
+ let filename = Ssh.scp_from_remote_to_temporary uri tmpdir
|
|
||||||
+ "source.vmx" in
|
|
||||||
Parse_vmx.parse_file filename in
|
|
||||||
|
|
||||||
let name =
|
|
||||||
@@ -400,7 +346,7 @@ let parse_domain_from_vmx vmx_source =
|
|
||||||
warning (f_"no displayName key found in VMX file");
|
|
||||||
match vmx_source with
|
|
||||||
| File filename -> name_from_disk filename
|
|
||||||
- | SSH uri -> name_from_disk (path_of_uri uri) in
|
|
||||||
+ | SSH uri -> name_from_disk (Ssh.path_of_uri uri) in
|
|
||||||
|
|
||||||
let genid =
|
|
||||||
(* See: https://lists.nongnu.org/archive/html/qemu-devel/2018-07/msg02019.html *)
|
|
||||||
diff --git a/input/parse_domain_from_vmx.mli b/input/parse_domain_from_vmx.mli
|
|
||||||
index e354b32e..42f8100e 100644
|
|
||||||
--- a/input/parse_domain_from_vmx.mli
|
|
||||||
+++ b/input/parse_domain_from_vmx.mli
|
|
||||||
@@ -22,9 +22,3 @@ type vmx_source =
|
|
||||||
|
|
||||||
val vmx_source_of_arg : [`SSH] option -> string -> vmx_source
|
|
||||||
val parse_domain_from_vmx : vmx_source -> Types.source * string list
|
|
||||||
-
|
|
||||||
-(* XXX Exporting these is a hack. *)
|
|
||||||
-val path_of_uri : Xml.uri -> string
|
|
||||||
-val server_of_uri : Xml.uri -> string
|
|
||||||
-val port_of_uri : Xml.uri -> int option
|
|
||||||
-val remote_file_exists : Xml.uri -> string -> bool
|
|
||||||
diff --git a/input/ssh.ml b/input/ssh.ml
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..5e689d29
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/input/ssh.ml
|
|
||||||
@@ -0,0 +1,78 @@
|
|
||||||
+(* virt-v2v
|
|
||||||
+ * Copyright (C) 2009-2024 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.
|
|
||||||
+ *)
|
|
||||||
+
|
|
||||||
+open Std_utils
|
|
||||||
+open Tools_utils
|
|
||||||
+open Common_gettext.Gettext
|
|
||||||
+
|
|
||||||
+open Printf
|
|
||||||
+
|
|
||||||
+(* Return various fields from the URI. The checks in vmx_source_of_arg
|
|
||||||
+ * should ensure that none of these assertions fail.
|
|
||||||
+ *)
|
|
||||||
+let port_of_uri { Xml.uri_port } =
|
|
||||||
+ match uri_port with i when i <= 0 -> None | i -> Some i
|
|
||||||
+let server_of_uri { Xml.uri_server } =
|
|
||||||
+ match uri_server with None -> assert false | Some s -> s
|
|
||||||
+let path_of_uri { Xml.uri_path } =
|
|
||||||
+ match uri_path with None -> assert false | Some p -> p
|
|
||||||
+
|
|
||||||
+(* 'scp' a remote file into a temporary local file, returning the path
|
|
||||||
+ * of the temporary local file.
|
|
||||||
+ *)
|
|
||||||
+let scp_from_remote_to_temporary uri tmpdir filename =
|
|
||||||
+ let localfile = tmpdir // filename in
|
|
||||||
+
|
|
||||||
+ let cmd =
|
|
||||||
+ sprintf "scp%s%s %s%s:%s %s"
|
|
||||||
+ (if verbose () then "" else " -q")
|
|
||||||
+ (match port_of_uri uri with
|
|
||||||
+ | None -> ""
|
|
||||||
+ | Some port -> sprintf " -P %d" port)
|
|
||||||
+ (match uri.Xml.uri_user with
|
|
||||||
+ | None -> ""
|
|
||||||
+ | Some user -> quote user ^ "@")
|
|
||||||
+ (quote (server_of_uri uri))
|
|
||||||
+ (quote (path_of_uri uri))
|
|
||||||
+ (quote localfile) in
|
|
||||||
+ if verbose () then
|
|
||||||
+ eprintf "%s\n%!" cmd;
|
|
||||||
+ if Sys.command cmd <> 0 then
|
|
||||||
+ error (f_"could not copy the VMX file from the remote server, \
|
|
||||||
+ see earlier error messages");
|
|
||||||
+ localfile
|
|
||||||
+
|
|
||||||
+(* Test if [path] exists on the remote server. *)
|
|
||||||
+let remote_file_exists uri path =
|
|
||||||
+ let cmd =
|
|
||||||
+ sprintf "ssh%s %s%s test -f %s"
|
|
||||||
+ (match port_of_uri uri with
|
|
||||||
+ | None -> ""
|
|
||||||
+ | Some port -> sprintf " -p %d" port)
|
|
||||||
+ (match uri.Xml.uri_user with
|
|
||||||
+ | None -> ""
|
|
||||||
+ | Some user -> quote user ^ "@")
|
|
||||||
+ (quote (server_of_uri uri))
|
|
||||||
+ (* Double quoting is necessary for 'ssh', first to protect
|
|
||||||
+ * from the local shell, second to protect from the remote
|
|
||||||
+ * shell. https://github.com/libguestfs/virt-v2v/issues/35#issuecomment-1741730963
|
|
||||||
+ *)
|
|
||||||
+ (quote (quote path)) in
|
|
||||||
+ if verbose () then
|
|
||||||
+ eprintf "%s\n%!" cmd;
|
|
||||||
+ Sys.command cmd = 0
|
|
||||||
diff --git a/input/ssh.mli b/input/ssh.mli
|
|
||||||
new file mode 100644
|
|
||||||
index 00000000..e9a1a6a8
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/input/ssh.mli
|
|
||||||
@@ -0,0 +1,34 @@
|
|
||||||
+(* virt-v2v
|
|
||||||
+ * Copyright (C) 2009-2024 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.
|
|
||||||
+ *)
|
|
||||||
+
|
|
||||||
+(** Wrappers for finding and downloading remote files over ssh. *)
|
|
||||||
+
|
|
||||||
+val path_of_uri : Xml.uri -> string
|
|
||||||
+val server_of_uri : Xml.uri -> string
|
|
||||||
+val port_of_uri : Xml.uri -> int option
|
|
||||||
+
|
|
||||||
+(** [remote_file_exists ssh_uri path] checks that [path] exists
|
|
||||||
+ on the remote server [ssh_uri] (note any path inside [ssh_uri]
|
|
||||||
+ is ignored). *)
|
|
||||||
+val remote_file_exists : Xml.uri -> string -> bool
|
|
||||||
+
|
|
||||||
+(** [scp_from_remote_to_temporary ssh_uri tmpdir filename]
|
|
||||||
+ uses scp to copy the single remote file at [ssh_uri] to
|
|
||||||
+ the local file called [tmpdir/filename]. It returns the
|
|
||||||
+ final path [tmpdir/filename]. *)
|
|
||||||
+val scp_from_remote_to_temporary : Xml.uri -> string -> string -> string
|
|
@ -0,0 +1,48 @@
|
|||||||
|
From f3ea9ceb1c3c9741d4f62d0c1d23b7c94634353a Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Thu, 28 May 2020 11:40:45 +0100
|
||||||
|
Subject: [PATCH] v2v: Remove extraneous '=' when setting bandwidth
|
||||||
|
(RHBZ#1841096).
|
||||||
|
|
||||||
|
Commit c3a54d6aed6dfc65f9ffa59976bb8d20044c03a8 ("v2v: Add standalone
|
||||||
|
nbdkit module.") was supposed to be a simple refactoring but it broke
|
||||||
|
the --bandwidth and --bandwidth-file options (amongst other things).
|
||||||
|
|
||||||
|
Because of an extra '=' character which was accidentally left over, it
|
||||||
|
would add an extra character in the nbdkit-rate-filter command line.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
virt-v2v .. --bandwidth 200M
|
||||||
|
|
||||||
|
would invoke:
|
||||||
|
|
||||||
|
nbdkit .. --filter rate rate==200M
|
||||||
|
|
||||||
|
which causes a parse error. The --bandwidth-file option does not
|
||||||
|
invoke a parse error but does not work, for similar reasons.
|
||||||
|
|
||||||
|
Thanks: Ming Xie
|
||||||
|
(cherry picked from commit a89a084b2d0f6d40716c1d34969f6c49ea28e9b3)
|
||||||
|
---
|
||||||
|
v2v/nbdkit_sources.ml | 6 +++---
|
||||||
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/nbdkit_sources.ml b/v2v/nbdkit_sources.ml
|
||||||
|
index 979c3773..402dfd0e 100644
|
||||||
|
--- a/v2v/nbdkit_sources.ml
|
||||||
|
+++ b/v2v/nbdkit_sources.ml
|
||||||
|
@@ -118,11 +118,11 @@ let common_create ?bandwidth ?extra_debug ?extra_env plugin_name plugin_args =
|
||||||
|
let args =
|
||||||
|
match bandwidth with
|
||||||
|
| StaticBandwidth rate ->
|
||||||
|
- [ "rate=", rate ]
|
||||||
|
+ [ "rate", rate ]
|
||||||
|
| DynamicBandwidth (None, filename) ->
|
||||||
|
- [ "rate-file=", filename ]
|
||||||
|
+ [ "rate-file", filename ]
|
||||||
|
| DynamicBandwidth (Some rate, filename) ->
|
||||||
|
- [ "rate=", rate; "rate-file=", filename ] in
|
||||||
|
+ [ "rate", rate; "rate-file", filename ] in
|
||||||
|
cmd, args
|
||||||
|
)
|
||||||
|
else cmd, [] in
|
@ -1,84 +0,0 @@
|
|||||||
From a0b22af28782a485cc2241dce55b8f435d8aaefc Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Mon, 15 Jan 2024 14:35:57 +0000
|
|
||||||
Subject: [PATCH] virt-v2v: -i vmx: Simplify scp wrapper
|
|
||||||
|
|
||||||
The existing 'scp_from_remote_to_temporary' wrapper around scp was
|
|
||||||
pretty weird (I think from much patching without refactoring).
|
|
||||||
Simplify it so it no longer generates the output filename, and rename
|
|
||||||
it accordingly to 'download_file' (as we will soon remove the need for
|
|
||||||
and dependency on 'scp').
|
|
||||||
|
|
||||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
|
||||||
---
|
|
||||||
input/parse_domain_from_vmx.ml | 4 ++--
|
|
||||||
input/ssh.ml | 13 ++++---------
|
|
||||||
input/ssh.mli | 7 +++----
|
|
||||||
3 files changed, 9 insertions(+), 15 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/input/parse_domain_from_vmx.ml b/input/parse_domain_from_vmx.ml
|
|
||||||
index 8cf5893c..e6500da6 100644
|
|
||||||
--- a/input/parse_domain_from_vmx.ml
|
|
||||||
+++ b/input/parse_domain_from_vmx.ml
|
|
||||||
@@ -335,8 +335,8 @@ let parse_domain_from_vmx vmx_source =
|
|
||||||
match vmx_source with
|
|
||||||
| File filename -> Parse_vmx.parse_file filename
|
|
||||||
| SSH uri ->
|
|
||||||
- let filename = Ssh.scp_from_remote_to_temporary uri tmpdir
|
|
||||||
- "source.vmx" in
|
|
||||||
+ let filename = tmpdir // "source.vmx" in
|
|
||||||
+ Ssh.download_file uri filename;
|
|
||||||
Parse_vmx.parse_file filename in
|
|
||||||
|
|
||||||
let name =
|
|
||||||
diff --git a/input/ssh.ml b/input/ssh.ml
|
|
||||||
index 5e689d29..63ffeb12 100644
|
|
||||||
--- a/input/ssh.ml
|
|
||||||
+++ b/input/ssh.ml
|
|
||||||
@@ -32,12 +32,8 @@ let server_of_uri { Xml.uri_server } =
|
|
||||||
let path_of_uri { Xml.uri_path } =
|
|
||||||
match uri_path with None -> assert false | Some p -> p
|
|
||||||
|
|
||||||
-(* 'scp' a remote file into a temporary local file, returning the path
|
|
||||||
- * of the temporary local file.
|
|
||||||
- *)
|
|
||||||
-let scp_from_remote_to_temporary uri tmpdir filename =
|
|
||||||
- let localfile = tmpdir // filename in
|
|
||||||
-
|
|
||||||
+(* 'scp' a remote file into a local file. *)
|
|
||||||
+let download_file uri output =
|
|
||||||
let cmd =
|
|
||||||
sprintf "scp%s%s %s%s:%s %s"
|
|
||||||
(if verbose () then "" else " -q")
|
|
||||||
@@ -49,13 +45,12 @@ let scp_from_remote_to_temporary uri tmpdir filename =
|
|
||||||
| Some user -> quote user ^ "@")
|
|
||||||
(quote (server_of_uri uri))
|
|
||||||
(quote (path_of_uri uri))
|
|
||||||
- (quote localfile) in
|
|
||||||
+ (quote output) in
|
|
||||||
if verbose () then
|
|
||||||
eprintf "%s\n%!" cmd;
|
|
||||||
if Sys.command cmd <> 0 then
|
|
||||||
error (f_"could not copy the VMX file from the remote server, \
|
|
||||||
- see earlier error messages");
|
|
||||||
- localfile
|
|
||||||
+ see earlier error messages")
|
|
||||||
|
|
||||||
(* Test if [path] exists on the remote server. *)
|
|
||||||
let remote_file_exists uri path =
|
|
||||||
diff --git a/input/ssh.mli b/input/ssh.mli
|
|
||||||
index e9a1a6a8..62e78bd3 100644
|
|
||||||
--- a/input/ssh.mli
|
|
||||||
+++ b/input/ssh.mli
|
|
||||||
@@ -27,8 +27,7 @@ val port_of_uri : Xml.uri -> int option
|
|
||||||
is ignored). *)
|
|
||||||
val remote_file_exists : Xml.uri -> string -> bool
|
|
||||||
|
|
||||||
-(** [scp_from_remote_to_temporary ssh_uri tmpdir filename]
|
|
||||||
+(** [download_file ssh_uri output]
|
|
||||||
uses scp to copy the single remote file at [ssh_uri] to
|
|
||||||
- the local file called [tmpdir/filename]. It returns the
|
|
||||||
- final path [tmpdir/filename]. *)
|
|
||||||
-val scp_from_remote_to_temporary : Xml.uri -> string -> string -> string
|
|
||||||
+ the local file called [output]. *)
|
|
||||||
+val download_file : Xml.uri -> string -> unit
|
|
@ -0,0 +1,46 @@
|
|||||||
|
From 4e0b3de57486613c8f28ef7726df728cccd7624b Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Thu, 28 May 2020 10:59:57 +0100
|
||||||
|
Subject: [PATCH] v2v: -it vddk: Don't use nbdkit readahead filter with VDDK
|
||||||
|
(RHBZ#1832805).
|
||||||
|
|
||||||
|
This filter deliberately tries to coalesce reads into larger requests.
|
||||||
|
Unfortunately VMware has low limits on the size of requests it can
|
||||||
|
serve to a VDDK client and the larger requests would break with errors
|
||||||
|
like this:
|
||||||
|
|
||||||
|
nbdkit: vddk[3]: error: [NFC ERROR] NfcFssrvrProcessErrorMsg: received NFC error 5 from server: Failed to allocate the requested 33554456 bytes
|
||||||
|
|
||||||
|
We already increase the maximum request size by changing the
|
||||||
|
configuration on the VMware server, but it's not sufficient for VDDK
|
||||||
|
with the readahead filter.
|
||||||
|
|
||||||
|
As readahead is only an optimization, the simplest solution is to
|
||||||
|
disable this filter when we're using nbdkit-vddk-plugin.
|
||||||
|
|
||||||
|
Thanks: Ming Xie
|
||||||
|
(cherry picked from commit 1438174488f111fa24420758ba3bf0218dc9ee2a)
|
||||||
|
---
|
||||||
|
v2v/nbdkit_sources.ml | 8 ++++++--
|
||||||
|
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/nbdkit_sources.ml b/v2v/nbdkit_sources.ml
|
||||||
|
index 402dfd0e..bfda91a7 100644
|
||||||
|
--- a/v2v/nbdkit_sources.ml
|
||||||
|
+++ b/v2v/nbdkit_sources.ml
|
||||||
|
@@ -97,9 +97,13 @@ let common_create ?bandwidth ?extra_debug ?extra_env plugin_name plugin_args =
|
||||||
|
let cmd = Nbdkit.add_filter_if_available cmd "retry" in
|
||||||
|
|
||||||
|
(* Adding the readahead filter is always a win for our access
|
||||||
|
- * patterns. However if it doesn't exist don't worry.
|
||||||
|
+ * patterns. If it doesn't exist don't worry. However it
|
||||||
|
+ * breaks VMware servers (RHBZ#1832805).
|
||||||
|
*)
|
||||||
|
- let cmd = Nbdkit.add_filter_if_available cmd "readahead" in
|
||||||
|
+ let cmd =
|
||||||
|
+ if plugin_name <> "vddk" then
|
||||||
|
+ Nbdkit.add_filter_if_available cmd "readahead"
|
||||||
|
+ else cmd in
|
||||||
|
|
||||||
|
(* Caching extents speeds up qemu-img, especially its consecutive
|
||||||
|
* block_status requests with req_one=1.
|
@ -0,0 +1,113 @@
|
|||||||
|
From bcb9f50eee4050e72a532a0b805531dc72105a4f Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Mon, 1 Jun 2020 17:18:59 +0100
|
||||||
|
Subject: [PATCH] v2v: nbdkit: Handle password= parameter in common_create.
|
||||||
|
|
||||||
|
Just refactoring.
|
||||||
|
|
||||||
|
(cherry picked from commit 36c008009a601634ec1c1fbc4f619b21988f075c)
|
||||||
|
---
|
||||||
|
v2v/nbdkit_sources.ml | 42 +++++++++++++++++++-----------------------
|
||||||
|
1 file changed, 19 insertions(+), 23 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/nbdkit_sources.ml b/v2v/nbdkit_sources.ml
|
||||||
|
index bfda91a7..47832011 100644
|
||||||
|
--- a/v2v/nbdkit_sources.ml
|
||||||
|
+++ b/v2v/nbdkit_sources.ml
|
||||||
|
@@ -58,7 +58,8 @@ let error_unless_nbdkit_compiled_with_selinux config =
|
||||||
|
error (f_"nbdkit was compiled without SELinux support. You will have to recompile nbdkit with libselinux-devel installed, or else set SELinux to Permissive mode while doing the conversion.")
|
||||||
|
)
|
||||||
|
|
||||||
|
-let common_create ?bandwidth ?extra_debug ?extra_env plugin_name plugin_args =
|
||||||
|
+let common_create ?bandwidth ?extra_debug ?extra_env password
|
||||||
|
+ plugin_name plugin_args =
|
||||||
|
error_unless_nbdkit_working ();
|
||||||
|
let config = Nbdkit.config () in
|
||||||
|
error_unless_nbdkit_min_version config;
|
||||||
|
@@ -136,6 +137,15 @@ let common_create ?bandwidth ?extra_debug ?extra_env plugin_name plugin_args =
|
||||||
|
List.fold_left (fun cmd (k, v) -> Nbdkit.add_arg cmd k v)
|
||||||
|
cmd (plugin_args @ rate_args) in
|
||||||
|
|
||||||
|
+ (* Handle the password parameter specially. *)
|
||||||
|
+ let cmd =
|
||||||
|
+ match password with
|
||||||
|
+ | NoPassword -> cmd
|
||||||
|
+ | AskForPassword ->
|
||||||
|
+ Nbdkit.add_arg cmd "password" "-"
|
||||||
|
+ | PasswordFile password_file ->
|
||||||
|
+ Nbdkit.add_arg cmd "password" ("+" ^ password_file) in
|
||||||
|
+
|
||||||
|
cmd
|
||||||
|
|
||||||
|
(* VDDK libraries are located under lib32/ or lib64/ relative to the
|
||||||
|
@@ -223,20 +233,16 @@ See also the virt-v2v-input-vmware(1) manual.") libNN
|
||||||
|
let get_args () = List.rev !args in
|
||||||
|
add_arg, get_args in
|
||||||
|
|
||||||
|
- let password_param =
|
||||||
|
- match password_file with
|
||||||
|
- | None ->
|
||||||
|
- (* nbdkit asks for the password interactively *)
|
||||||
|
- "password", "-"
|
||||||
|
- | Some password_file ->
|
||||||
|
- (* nbdkit reads the password from the file *)
|
||||||
|
- "password", "+" ^ password_file in
|
||||||
|
add_arg ("server", server);
|
||||||
|
add_arg ("user", user);
|
||||||
|
- add_arg password_param;
|
||||||
|
add_arg ("vm", sprintf "moref=%s" moref);
|
||||||
|
add_arg ("file", path);
|
||||||
|
|
||||||
|
+ let password =
|
||||||
|
+ match password_file with
|
||||||
|
+ | None -> AskForPassword
|
||||||
|
+ | Some password_file -> PasswordFile password_file in
|
||||||
|
+
|
||||||
|
(* The passthrough parameters. *)
|
||||||
|
Option.may (fun s -> add_arg ("config", s)) config;
|
||||||
|
Option.may (fun s -> add_arg ("cookie", s)) cookie;
|
||||||
|
@@ -251,7 +257,7 @@ See also the virt-v2v-input-vmware(1) manual.") libNN
|
||||||
|
let debug_flag =
|
||||||
|
if version >= (1, 17, 10) then Some ("vddk.datapath", "0") else None in
|
||||||
|
|
||||||
|
- common_create ?bandwidth ?extra_debug:debug_flag ?extra_env:env
|
||||||
|
+ common_create ?bandwidth ?extra_debug:debug_flag ?extra_env:env password
|
||||||
|
"vddk" (get_args ())
|
||||||
|
|
||||||
|
(* Create an nbdkit module specialized for reading from SSH sources. *)
|
||||||
|
@@ -267,14 +273,9 @@ let create_ssh ?bandwidth ~password ?port ~server ?user path =
|
||||||
|
add_arg ("host", server);
|
||||||
|
Option.may (fun s -> add_arg ("port", s)) port;
|
||||||
|
Option.may (fun s -> add_arg ("user", s)) user;
|
||||||
|
- (match password with
|
||||||
|
- | NoPassword -> ()
|
||||||
|
- | AskForPassword -> add_arg ("password", "-")
|
||||||
|
- | PasswordFile password_file -> add_arg ("password", "+" ^ password_file)
|
||||||
|
- );
|
||||||
|
add_arg ("path", path);
|
||||||
|
|
||||||
|
- common_create ?bandwidth "ssh" (get_args ())
|
||||||
|
+ common_create ?bandwidth password "ssh" (get_args ())
|
||||||
|
|
||||||
|
(* Create an nbdkit module specialized for reading from Curl sources. *)
|
||||||
|
let create_curl ?bandwidth ?cookie ~password ?(sslverify=true) ?user url =
|
||||||
|
@@ -287,18 +288,13 @@ let create_curl ?bandwidth ?cookie ~password ?(sslverify=true) ?user url =
|
||||||
|
add_arg, get_args in
|
||||||
|
|
||||||
|
Option.may (fun s -> add_arg ("user", s)) user;
|
||||||
|
- (match password with
|
||||||
|
- | NoPassword -> ()
|
||||||
|
- | AskForPassword -> add_arg ("password", "-")
|
||||||
|
- | PasswordFile password_file -> add_arg ("password", "+" ^ password_file)
|
||||||
|
- );
|
||||||
|
(* https://bugzilla.redhat.com/show_bug.cgi?id=1146007#c10 *)
|
||||||
|
add_arg ("timeout", "2000");
|
||||||
|
Option.may (fun s -> add_arg ("cookie", s)) cookie;
|
||||||
|
if not sslverify then add_arg ("sslverify", "false");
|
||||||
|
add_arg ("url", url);
|
||||||
|
|
||||||
|
- common_create ?bandwidth "curl" (get_args ())
|
||||||
|
+ common_create ?bandwidth password "curl" (get_args ())
|
||||||
|
|
||||||
|
let run cmd =
|
||||||
|
let sock, _ = Nbdkit.run_unix cmd in
|
@ -1,205 +0,0 @@
|
|||||||
From 40730615d2f691bc72777b4cb7356e2177edc1e1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Mon, 15 Jan 2024 14:48:56 +0000
|
|
||||||
Subject: [PATCH] virt-v2v: -i vmx: Remove dependency of ssh.ml on Xml.uri
|
|
||||||
|
|
||||||
Xml.uri is a convenient way to pass the multiple ssh fields to
|
|
||||||
virt-v2v and is still used internally by the -i vmx code. However
|
|
||||||
don't leak this awkward implementation into the new ssh.ml module.
|
|
||||||
|
|
||||||
Like Nbdkit_ssh, we'll only deal with the explicit (password, port,
|
|
||||||
server, user, path) fields separately.
|
|
||||||
|
|
||||||
Note after this refactoring:
|
|
||||||
|
|
||||||
- The new Ssh module interface looks broadly similar to the
|
|
||||||
Nbdkit_ssh interface.
|
|
||||||
|
|
||||||
- vmx_source_of_arg assertions are no longer required inside the new
|
|
||||||
Ssh module, which was a mild layering violation before.
|
|
||||||
|
|
||||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
|
||||||
---
|
|
||||||
input/input_vmx.ml | 21 ++++++++++++++++-----
|
|
||||||
input/parse_domain_from_vmx.ml | 22 +++++++++++++++++++---
|
|
||||||
input/ssh.ml | 32 +++++++++++---------------------
|
|
||||||
input/ssh.mli | 21 ++++++++++-----------
|
|
||||||
4 files changed, 56 insertions(+), 40 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/input/input_vmx.ml b/input/input_vmx.ml
|
|
||||||
index b9cce10f..b3426fa2 100644
|
|
||||||
--- a/input/input_vmx.ml
|
|
||||||
+++ b/input/input_vmx.ml
|
|
||||||
@@ -83,22 +83,33 @@ module VMX = struct
|
|
||||||
let socket = sprintf "%s/in%d" dir i in
|
|
||||||
On_exit.unlink socket;
|
|
||||||
|
|
||||||
- let vmx_path = Ssh.path_of_uri uri in
|
|
||||||
+ let vmx_path =
|
|
||||||
+ match uri.uri_path with
|
|
||||||
+ | None -> assert false (* checked by vmx_source_of_arg *)
|
|
||||||
+ | Some path -> path in
|
|
||||||
let abs_path = absolute_path_from_other_file vmx_path filename in
|
|
||||||
let flat_vmdk = PCRE.replace (PCRE.compile "\\.vmdk$")
|
|
||||||
"-flat.vmdk" abs_path in
|
|
||||||
|
|
||||||
+ let server =
|
|
||||||
+ match uri.uri_server with
|
|
||||||
+ | None -> assert false (* checked by vmx_source_of_arg *)
|
|
||||||
+ | Some server -> server in
|
|
||||||
+ let port =
|
|
||||||
+ match uri.uri_port with
|
|
||||||
+ | i when i <= 0 -> None
|
|
||||||
+ | i -> Some (string_of_int i) in
|
|
||||||
+ let user = uri.Xml.uri_user in
|
|
||||||
+
|
|
||||||
(* RHBZ#1774386 *)
|
|
||||||
- if not (Ssh.remote_file_exists uri flat_vmdk) then
|
|
||||||
+ if not (Ssh.remote_file_exists ~password ?port ~server ?user
|
|
||||||
+ flat_vmdk) then
|
|
||||||
error (f_"This transport does not support guests with snapshots. \
|
|
||||||
Either collapse the snapshots for this guest and try \
|
|
||||||
the conversion again, or use one of the alternate \
|
|
||||||
conversion methods described in \
|
|
||||||
virt-v2v-input-vmware(1) section \"NOTES\".");
|
|
||||||
|
|
||||||
- let server = Ssh.server_of_uri uri in
|
|
||||||
- let port = Option.map string_of_int (Ssh.port_of_uri uri) in
|
|
||||||
- let user = uri.Xml.uri_user in
|
|
||||||
let cor = dir // "convert" in
|
|
||||||
let bandwidth = options.bandwidth in
|
|
||||||
let nbdkit = Nbdkit_ssh.create_ssh ?bandwidth ~cor ~password
|
|
||||||
diff --git a/input/parse_domain_from_vmx.ml b/input/parse_domain_from_vmx.ml
|
|
||||||
index 0719738c..99c86b1a 100644
|
|
||||||
--- a/input/parse_domain_from_vmx.ml
|
|
||||||
+++ b/input/parse_domain_from_vmx.ml
|
|
||||||
@@ -334,9 +334,22 @@ let parse_domain_from_vmx vmx_source =
|
|
||||||
let vmx =
|
|
||||||
match vmx_source with
|
|
||||||
| File filename -> Parse_vmx.parse_file filename
|
|
||||||
- | SSH (_, uri) ->
|
|
||||||
+ | SSH (password, uri) ->
|
|
||||||
+ let server =
|
|
||||||
+ match uri.uri_server with
|
|
||||||
+ | None -> assert false (* checked by vmx_source_of_arg *)
|
|
||||||
+ | Some server -> server in
|
|
||||||
+ let port =
|
|
||||||
+ match uri.uri_port with
|
|
||||||
+ | i when i <= 0 -> None
|
|
||||||
+ | i -> Some (string_of_int i) in
|
|
||||||
+ let user = uri.Xml.uri_user in
|
|
||||||
+ let path =
|
|
||||||
+ match uri.uri_path with
|
|
||||||
+ | None -> assert false (* checked by vmx_source_of_arg *)
|
|
||||||
+ | Some path -> path in
|
|
||||||
let filename = tmpdir // "source.vmx" in
|
|
||||||
- Ssh.download_file uri filename;
|
|
||||||
+ Ssh.download_file ~password ?port ~server ?user path filename;
|
|
||||||
Parse_vmx.parse_file filename in
|
|
||||||
|
|
||||||
let name =
|
|
||||||
@@ -346,7 +359,10 @@ let parse_domain_from_vmx vmx_source =
|
|
||||||
warning (f_"no displayName key found in VMX file");
|
|
||||||
match vmx_source with
|
|
||||||
| File filename -> name_from_disk filename
|
|
||||||
- | SSH (_, uri) -> name_from_disk (Ssh.path_of_uri uri) in
|
|
||||||
+ | SSH (_, uri) ->
|
|
||||||
+ match uri.uri_path with
|
|
||||||
+ | None -> assert false (* checked by vmx_source_of_arg *)
|
|
||||||
+ | Some path -> name_from_disk path in
|
|
||||||
|
|
||||||
let genid =
|
|
||||||
(* See: https://lists.nongnu.org/archive/html/qemu-devel/2018-07/msg02019.html *)
|
|
||||||
diff --git a/input/ssh.ml b/input/ssh.ml
|
|
||||||
index 63ffeb12..127e818c 100644
|
|
||||||
--- a/input/ssh.ml
|
|
||||||
+++ b/input/ssh.ml
|
|
||||||
@@ -22,29 +22,19 @@ open Common_gettext.Gettext
|
|
||||||
|
|
||||||
open Printf
|
|
||||||
|
|
||||||
-(* Return various fields from the URI. The checks in vmx_source_of_arg
|
|
||||||
- * should ensure that none of these assertions fail.
|
|
||||||
- *)
|
|
||||||
-let port_of_uri { Xml.uri_port } =
|
|
||||||
- match uri_port with i when i <= 0 -> None | i -> Some i
|
|
||||||
-let server_of_uri { Xml.uri_server } =
|
|
||||||
- match uri_server with None -> assert false | Some s -> s
|
|
||||||
-let path_of_uri { Xml.uri_path } =
|
|
||||||
- match uri_path with None -> assert false | Some p -> p
|
|
||||||
-
|
|
||||||
(* 'scp' a remote file into a local file. *)
|
|
||||||
-let download_file uri output =
|
|
||||||
+let download_file ~password:_ ?port ~server ?user path output =
|
|
||||||
let cmd =
|
|
||||||
sprintf "scp%s%s %s%s:%s %s"
|
|
||||||
(if verbose () then "" else " -q")
|
|
||||||
- (match port_of_uri uri with
|
|
||||||
+ (match port with
|
|
||||||
| None -> ""
|
|
||||||
- | Some port -> sprintf " -P %d" port)
|
|
||||||
- (match uri.Xml.uri_user with
|
|
||||||
+ | Some port -> sprintf " -P %s" port)
|
|
||||||
+ (match user with
|
|
||||||
| None -> ""
|
|
||||||
| Some user -> quote user ^ "@")
|
|
||||||
- (quote (server_of_uri uri))
|
|
||||||
- (quote (path_of_uri uri))
|
|
||||||
+ (quote server)
|
|
||||||
+ (quote path)
|
|
||||||
(quote output) in
|
|
||||||
if verbose () then
|
|
||||||
eprintf "%s\n%!" cmd;
|
|
||||||
@@ -53,16 +43,16 @@ let download_file uri output =
|
|
||||||
see earlier error messages")
|
|
||||||
|
|
||||||
(* Test if [path] exists on the remote server. *)
|
|
||||||
-let remote_file_exists uri path =
|
|
||||||
+let remote_file_exists ~password:_ ?port ~server ?user path =
|
|
||||||
let cmd =
|
|
||||||
sprintf "ssh%s %s%s test -f %s"
|
|
||||||
- (match port_of_uri uri with
|
|
||||||
+ (match port with
|
|
||||||
| None -> ""
|
|
||||||
- | Some port -> sprintf " -p %d" port)
|
|
||||||
- (match uri.Xml.uri_user with
|
|
||||||
+ | Some port -> sprintf " -p %s" port)
|
|
||||||
+ (match user with
|
|
||||||
| None -> ""
|
|
||||||
| Some user -> quote user ^ "@")
|
|
||||||
- (quote (server_of_uri uri))
|
|
||||||
+ (quote server)
|
|
||||||
(* Double quoting is necessary for 'ssh', first to protect
|
|
||||||
* from the local shell, second to protect from the remote
|
|
||||||
* shell. https://github.com/libguestfs/virt-v2v/issues/35#issuecomment-1741730963
|
|
||||||
diff --git a/input/ssh.mli b/input/ssh.mli
|
|
||||||
index 62e78bd3..1f39cd1b 100644
|
|
||||||
--- a/input/ssh.mli
|
|
||||||
+++ b/input/ssh.mli
|
|
||||||
@@ -18,16 +18,15 @@
|
|
||||||
|
|
||||||
(** Wrappers for finding and downloading remote files over ssh. *)
|
|
||||||
|
|
||||||
-val path_of_uri : Xml.uri -> string
|
|
||||||
-val server_of_uri : Xml.uri -> string
|
|
||||||
-val port_of_uri : Xml.uri -> int option
|
|
||||||
+(** [remote_file_exists password ?port server ?user path]
|
|
||||||
+ checks that [path] exists on the remote server. *)
|
|
||||||
+val remote_file_exists : password:Nbdkit_ssh.password ->
|
|
||||||
+ ?port:string -> server:string -> ?user:string ->
|
|
||||||
+ string -> bool
|
|
||||||
|
|
||||||
-(** [remote_file_exists ssh_uri path] checks that [path] exists
|
|
||||||
- on the remote server [ssh_uri] (note any path inside [ssh_uri]
|
|
||||||
- is ignored). *)
|
|
||||||
-val remote_file_exists : Xml.uri -> string -> bool
|
|
||||||
-
|
|
||||||
-(** [download_file ssh_uri output]
|
|
||||||
- uses scp to copy the single remote file at [ssh_uri] to
|
|
||||||
+(** [download_file password ?port server ?user path output]
|
|
||||||
+ uses scp to copy the single remote file at [path] to
|
|
||||||
the local file called [output]. *)
|
|
||||||
-val download_file : Xml.uri -> string -> unit
|
|
||||||
+val download_file : password:Nbdkit_ssh.password ->
|
|
||||||
+ ?port:string -> server:string -> ?user:string -> string ->
|
|
||||||
+ string -> unit
|
|
@ -1,55 +0,0 @@
|
|||||||
From 72c9734050f0235c80ff7d685282a57836a70bd5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Mon, 15 Jan 2024 16:21:34 +0000
|
|
||||||
Subject: [PATCH] input/nbdkit_ssh: Make retry filter optional
|
|
||||||
|
|
||||||
This filter retries a request on failure. Add a flag to make this
|
|
||||||
filter optional, but default to using it if available (so there's no
|
|
||||||
change to default behaviour).
|
|
||||||
|
|
||||||
The reason we want to make this optional is that the next commit will
|
|
||||||
want to use nbdkit-ssh-plugin to probe to see if a remote file is
|
|
||||||
present, and we don't want to retry that probe on failure.
|
|
||||||
|
|
||||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
|
||||||
---
|
|
||||||
input/nbdkit_ssh.ml | 6 ++++--
|
|
||||||
input/nbdkit_ssh.mli | 1 +
|
|
||||||
2 files changed, 5 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/input/nbdkit_ssh.ml b/input/nbdkit_ssh.ml
|
|
||||||
index 3f6da9b6..3b72d3ad 100644
|
|
||||||
--- a/input/nbdkit_ssh.ml
|
|
||||||
+++ b/input/nbdkit_ssh.ml
|
|
||||||
@@ -44,7 +44,8 @@ let error_unless_nbdkit_min_version config =
|
|
||||||
error_unless_nbdkit_version_ge config nbdkit_min_version
|
|
||||||
|
|
||||||
(* Create an nbdkit module specialized for reading from SSH sources. *)
|
|
||||||
-let create_ssh ?bandwidth ?cor ~password ?port ~server ?user path =
|
|
||||||
+let create_ssh ?bandwidth ?cor ?(retry=true)
|
|
||||||
+ ~password ?port ~server ?user path =
|
|
||||||
if not (Nbdkit.is_installed ()) then
|
|
||||||
error (f_"nbdkit is not installed or not working");
|
|
||||||
|
|
||||||
@@ -67,7 +68,8 @@ let create_ssh ?bandwidth ?cor ~password ?port ~server ?user path =
|
|
||||||
(* Retry filter (if it exists) can be used to get around brief
|
|
||||||
* interruptions in service. It must be closest to the plugin.
|
|
||||||
*)
|
|
||||||
- Nbdkit.add_filter_if_available cmd "retry";
|
|
||||||
+ if retry then
|
|
||||||
+ Nbdkit.add_filter_if_available cmd "retry";
|
|
||||||
|
|
||||||
(* Caching extents speeds up qemu-img, especially its consecutive
|
|
||||||
* block_status requests with req_one=1.
|
|
||||||
diff --git a/input/nbdkit_ssh.mli b/input/nbdkit_ssh.mli
|
|
||||||
index bc798c5a..daa20bb2 100644
|
|
||||||
--- a/input/nbdkit_ssh.mli
|
|
||||||
+++ b/input/nbdkit_ssh.mli
|
|
||||||
@@ -25,6 +25,7 @@ type password =
|
|
||||||
|
|
||||||
val create_ssh : ?bandwidth:Types.bandwidth ->
|
|
||||||
?cor:string ->
|
|
||||||
+ ?retry:bool ->
|
|
||||||
password:password ->
|
|
||||||
?port:string ->
|
|
||||||
server:string ->
|
|
@ -0,0 +1,54 @@
|
|||||||
|
From 89ab50eb404664ac3522294f2f46a1c904a28abd Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Mon, 1 Jun 2020 17:35:58 +0100
|
||||||
|
Subject: [PATCH] v2v: nbdkit: Don't use password=- parameter (RHBZ#1842440).
|
||||||
|
|
||||||
|
This was broken with all nbdkit plugins, some in more ways than others.
|
||||||
|
|
||||||
|
Because we start nbdkit in the background and wait 30 seconds for it
|
||||||
|
to start running, the user had only 30 seconds to type in a password
|
||||||
|
before we timed out the process. In addition with the VDDK plugin
|
||||||
|
password=- had been broken ever since we changed the plugin to use a
|
||||||
|
reexec
|
||||||
|
(https://www.redhat.com/archives/libguestfs/2020-June/msg00012.html).
|
||||||
|
|
||||||
|
The solution is to read the password ourselves and pass it to nbdkit
|
||||||
|
as a private file.
|
||||||
|
|
||||||
|
(cherry picked from commit 16b551c77c88219a2f68e2fc37daf2dc4d88e4ed)
|
||||||
|
---
|
||||||
|
v2v/nbdkit_sources.ml | 21 ++++++++++++++++++++-
|
||||||
|
1 file changed, 20 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/nbdkit_sources.ml b/v2v/nbdkit_sources.ml
|
||||||
|
index 47832011..f5e91911 100644
|
||||||
|
--- a/v2v/nbdkit_sources.ml
|
||||||
|
+++ b/v2v/nbdkit_sources.ml
|
||||||
|
@@ -142,7 +142,26 @@ let common_create ?bandwidth ?extra_debug ?extra_env password
|
||||||
|
match password with
|
||||||
|
| NoPassword -> cmd
|
||||||
|
| AskForPassword ->
|
||||||
|
- Nbdkit.add_arg cmd "password" "-"
|
||||||
|
+ (* Because we will start nbdkit in the background and then wait
|
||||||
|
+ * for 30 seconds for it to start up, we cannot use the
|
||||||
|
+ * password=- feature of nbdkit to read the password
|
||||||
|
+ * interactively (since in the words of the movie the user has
|
||||||
|
+ * only "30 seconds to comply"). In any case this feature broke
|
||||||
|
+ * in the VDDK plugin in nbdkit 1.18 and 1.20. So in the
|
||||||
|
+ * AskForPassword case we read the password here.
|
||||||
|
+ *)
|
||||||
|
+ printf "password: ";
|
||||||
|
+ let open Unix in
|
||||||
|
+ let orig = tcgetattr stdin in
|
||||||
|
+ let tios = { orig with c_echo = false } in
|
||||||
|
+ tcsetattr stdin TCSAFLUSH tios; (* Disable echo. *)
|
||||||
|
+ let password = read_line () in
|
||||||
|
+ tcsetattr stdin TCSAFLUSH orig; (* Restore echo. *)
|
||||||
|
+ printf "\n";
|
||||||
|
+ let password_file = Filename.temp_file "v2vnbdkit" ".txt" in
|
||||||
|
+ unlink_on_exit password_file;
|
||||||
|
+ with_open_out password_file (fun chan -> output_string chan password);
|
||||||
|
+ Nbdkit.add_arg cmd "password" ("+" ^ password_file)
|
||||||
|
| PasswordFile password_file ->
|
||||||
|
Nbdkit.add_arg cmd "password" ("+" ^ password_file) in
|
||||||
|
|
@ -0,0 +1,41 @@
|
|||||||
|
From a8f3d2b2e87aead9f6a1db66dccebb6239ddf004 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pino Toscano <ptoscano@redhat.com>
|
||||||
|
Date: Fri, 19 Jun 2020 17:57:36 +0200
|
||||||
|
Subject: [PATCH] libosinfo: declare autocleanup funcs with libosinfo < 1.8.0
|
||||||
|
|
||||||
|
libosinfo 1.8.0 declares them automatically for all of its classes, so
|
||||||
|
there is no need to declare ours. This requires fixing the definition of
|
||||||
|
the IS_LIBOSINFO_VERSION macro to wrap its body in brackets.
|
||||||
|
|
||||||
|
While in the process, simplify the workaround for a related bug by
|
||||||
|
removing a now-useless check.
|
||||||
|
|
||||||
|
(cherry picked from commit c1caf7132000a4560c3e20c2753978e8dd10036a)
|
||||||
|
---
|
||||||
|
v2v/libosinfo-c.c | 8 +++++++-
|
||||||
|
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/libosinfo-c.c b/v2v/libosinfo-c.c
|
||||||
|
index 1ab6bb4d..497840c2 100644
|
||||||
|
--- a/v2v/libosinfo-c.c
|
||||||
|
+++ b/v2v/libosinfo-c.c
|
||||||
|
@@ -40,12 +40,18 @@
|
||||||
|
#define V2V_LIBOSINFO_VERSION_HEX \
|
||||||
|
MAKE_VERSION_HEX(OSINFO_MAJOR_VERSION, OSINFO_MINOR_VERSION, OSINFO_MICRO_VERSION)
|
||||||
|
#define IS_LIBOSINFO_VERSION(maj, min, mic) \
|
||||||
|
- V2V_LIBOSINFO_VERSION_HEX >= MAKE_VERSION_HEX(maj, min, mic)
|
||||||
|
+ (V2V_LIBOSINFO_VERSION_HEX >= MAKE_VERSION_HEX(maj, min, mic))
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * libosinfo 1.8.0 provides auto-cleanup functions for all its classes,
|
||||||
|
+ * so avoid declaring our own.
|
||||||
|
+ */
|
||||||
|
+#if !IS_LIBOSINFO_VERSION(1, 8, 0)
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoFilter, g_object_unref)
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoLoader, g_object_unref)
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoList, g_object_unref)
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OsinfoOsList, g_object_unref)
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
typedef OsinfoDb *OsinfoDb_t;
|
||||||
|
typedef OsinfoOs *OsinfoOs_t;
|
@ -1,167 +0,0 @@
|
|||||||
From fb72e059863a60503b6011b8590c25c3a010a58f Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Mon, 15 Jan 2024 15:38:30 +0000
|
|
||||||
Subject: [PATCH] virt-v2v: -i vmx: Replace external ssh/scp with
|
|
||||||
nbdkit-ssh-plugin
|
|
||||||
|
|
||||||
If you use a -i vmx ssh filename containing '*' then it will expand
|
|
||||||
the glob at the remote side. New scp is weird and silently creates a
|
|
||||||
directory on the local side. For example suppose there's a remote
|
|
||||||
file literally called "/tmp/test*" (ie. the '*' is part of the
|
|
||||||
filename) and you thought you could copy that to local using:
|
|
||||||
|
|
||||||
scp 'remote:/tmp/test*' '/tmp/test*'
|
|
||||||
|
|
||||||
scp treats the first parameter (only) as a wildcard and if there are
|
|
||||||
multiple files matching the wildcard /tmp/test*, will create a local
|
|
||||||
directory literally called "/tmp/test*/" and put the files into it.
|
|
||||||
Who expected any of that?
|
|
||||||
|
|
||||||
You might think that double quoting (as we used to use) might work,
|
|
||||||
but that breaks with spaces and quotes. I guess scp is using
|
|
||||||
different code paths internally for glob versus everything else.
|
|
||||||
|
|
||||||
The only way to really make this work is to stop using scp entirely
|
|
||||||
and just use sftp directly. The easiest way to use sftp is to use
|
|
||||||
nbdkit-ssh-plugin. We already depend on nbdkit-ssh-plugin, nbdcopy
|
|
||||||
and nbdinfo for other parts of virt-v2v, so might as well use the
|
|
||||||
whole lot here.
|
|
||||||
|
|
||||||
One advantage of this change is that now the -ip (input password)
|
|
||||||
parameter actually works in -i vmx -it ssh mode.
|
|
||||||
|
|
||||||
Other approaches that would have been possible:
|
|
||||||
|
|
||||||
- Use the OCaml NBD library instead of nbdcopy/nbdinfo
|
|
||||||
|
|
||||||
- Use 'nbdkit -U - ssh --run ...'
|
|
||||||
|
|
||||||
- Direct binding to libssh.
|
|
||||||
|
|
||||||
See also commit e2af12ba69c4463bb73d30db63290a887cdd41eb
|
|
||||||
("input: -i vmx: Remove support for openssh scp < 8.8")
|
|
||||||
|
|
||||||
See also commit 22c5b98ab78c734b478c26e14ee62e2a065aaa0c
|
|
||||||
("-it ssh: Double quote ssh command which tests remote file exists")
|
|
||||||
|
|
||||||
See also https://unix.stackexchange.com/a/587710
|
|
||||||
|
|
||||||
Reported-by: Ming Xie
|
|
||||||
Fixes: https://issues.redhat.com/browse/RHEL-21365
|
|
||||||
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
|
||||||
---
|
|
||||||
input/ssh.ml | 70 +++++++++++++++++++++++++--------------------------
|
|
||||||
input/ssh.mli | 7 ++++--
|
|
||||||
2 files changed, 40 insertions(+), 37 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/input/ssh.ml b/input/ssh.ml
|
|
||||||
index 127e818c..71ebbf2a 100644
|
|
||||||
--- a/input/ssh.ml
|
|
||||||
+++ b/input/ssh.ml
|
|
||||||
@@ -18,46 +18,46 @@
|
|
||||||
|
|
||||||
open Std_utils
|
|
||||||
open Tools_utils
|
|
||||||
+open Unix_utils
|
|
||||||
open Common_gettext.Gettext
|
|
||||||
|
|
||||||
open Printf
|
|
||||||
|
|
||||||
-(* 'scp' a remote file into a local file. *)
|
|
||||||
-let download_file ~password:_ ?port ~server ?user path output =
|
|
||||||
- let cmd =
|
|
||||||
- sprintf "scp%s%s %s%s:%s %s"
|
|
||||||
- (if verbose () then "" else " -q")
|
|
||||||
- (match port with
|
|
||||||
- | None -> ""
|
|
||||||
- | Some port -> sprintf " -P %s" port)
|
|
||||||
- (match user with
|
|
||||||
- | None -> ""
|
|
||||||
- | Some user -> quote user ^ "@")
|
|
||||||
- (quote server)
|
|
||||||
- (quote path)
|
|
||||||
- (quote output) in
|
|
||||||
- if verbose () then
|
|
||||||
- eprintf "%s\n%!" cmd;
|
|
||||||
- if Sys.command cmd <> 0 then
|
|
||||||
+let start_nbdkit ~password ?port ~server ?user path =
|
|
||||||
+ (* Create a random location for the socket used to talk to nbdkit. *)
|
|
||||||
+ let sockdir = Mkdtemp.temp_dir "v2vssh." in
|
|
||||||
+ On_exit.rm_rf sockdir;
|
|
||||||
+ let id = unique () in
|
|
||||||
+ let socket = sockdir // sprintf "nbdkit%d.sock" id in
|
|
||||||
+
|
|
||||||
+ (* Note: Disabling the retry filter helps in the missing file case,
|
|
||||||
+ * otherwise nbdkit takes ages to time out. We're not expecting that
|
|
||||||
+ * the VMX file is large, so using this filter isn't necessary.
|
|
||||||
+ *)
|
|
||||||
+ let nbdkit =
|
|
||||||
+ Nbdkit_ssh.create_ssh ~retry:false ~password ~server ?port ?user path in
|
|
||||||
+ Nbdkit.set_readonly nbdkit true;
|
|
||||||
+ let _, pid = Nbdkit.run_unix socket nbdkit in
|
|
||||||
+ On_exit.kill pid;
|
|
||||||
+
|
|
||||||
+ (* Return the URI of nbdkit. *)
|
|
||||||
+ "nbd+unix://?socket=" ^ socket
|
|
||||||
+
|
|
||||||
+(* Download a remote file into a local file. *)
|
|
||||||
+let download_file ~password ?port ~server ?user path output =
|
|
||||||
+ let uri = start_nbdkit ~password ?port ~server ?user path in
|
|
||||||
+
|
|
||||||
+ let cmd = [ "nbdcopy"; uri; output ] in
|
|
||||||
+ if run_command cmd <> 0 then
|
|
||||||
error (f_"could not copy the VMX file from the remote server, \
|
|
||||||
see earlier error messages")
|
|
||||||
|
|
||||||
(* Test if [path] exists on the remote server. *)
|
|
||||||
-let remote_file_exists ~password:_ ?port ~server ?user path =
|
|
||||||
- let cmd =
|
|
||||||
- sprintf "ssh%s %s%s test -f %s"
|
|
||||||
- (match port with
|
|
||||||
- | None -> ""
|
|
||||||
- | Some port -> sprintf " -p %s" port)
|
|
||||||
- (match user with
|
|
||||||
- | None -> ""
|
|
||||||
- | Some user -> quote user ^ "@")
|
|
||||||
- (quote server)
|
|
||||||
- (* Double quoting is necessary for 'ssh', first to protect
|
|
||||||
- * from the local shell, second to protect from the remote
|
|
||||||
- * shell. https://github.com/libguestfs/virt-v2v/issues/35#issuecomment-1741730963
|
|
||||||
- *)
|
|
||||||
- (quote (quote path)) in
|
|
||||||
- if verbose () then
|
|
||||||
- eprintf "%s\n%!" cmd;
|
|
||||||
- Sys.command cmd = 0
|
|
||||||
+let remote_file_exists ~password ?port ~server ?user path =
|
|
||||||
+ let uri = start_nbdkit ~password ?port ~server ?user path in
|
|
||||||
+
|
|
||||||
+ (* Testing for remote size using nbdinfo should be sufficient to
|
|
||||||
+ * prove the remote file exists.
|
|
||||||
+ *)
|
|
||||||
+ let cmd = [ "nbdinfo"; "--size"; uri ] in
|
|
||||||
+ run_command cmd = 0
|
|
||||||
diff --git a/input/ssh.mli b/input/ssh.mli
|
|
||||||
index 1f39cd1b..40843024 100644
|
|
||||||
--- a/input/ssh.mli
|
|
||||||
+++ b/input/ssh.mli
|
|
||||||
@@ -16,7 +16,10 @@
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*)
|
|
||||||
|
|
||||||
-(** Wrappers for finding and downloading remote files over ssh. *)
|
|
||||||
+(** Wrappers for finding and downloading remote files over ssh.
|
|
||||||
+
|
|
||||||
+ Internally this uses nbdkit-ssh-plugin (which uses sftp) as
|
|
||||||
+ that is much more predictable than running external ssh / scp. *)
|
|
||||||
|
|
||||||
(** [remote_file_exists password ?port server ?user path]
|
|
||||||
checks that [path] exists on the remote server. *)
|
|
||||||
@@ -25,7 +28,7 @@ val remote_file_exists : password:Nbdkit_ssh.password ->
|
|
||||||
string -> bool
|
|
||||||
|
|
||||||
(** [download_file password ?port server ?user path output]
|
|
||||||
- uses scp to copy the single remote file at [path] to
|
|
||||||
+ downloads the single remote file at [path] to
|
|
||||||
the local file called [output]. *)
|
|
||||||
val download_file : password:Nbdkit_ssh.password ->
|
|
||||||
?port:string -> server:string -> ?user:string -> string ->
|
|
@ -0,0 +1,57 @@
|
|||||||
|
From 6aec975c07d60a2518d3f16ee91db1d03a704882 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Thu, 30 Jul 2020 14:01:48 +0100
|
||||||
|
Subject: [PATCH] v2v: Use common documentation for --keys-from-stdin.
|
||||||
|
|
||||||
|
(cherry picked from commit 3f9b5f26398694a8a496eae85525e3be5c4b9cca)
|
||||||
|
---
|
||||||
|
common | 2 +-
|
||||||
|
docs/virt-v2v.pod | 11 ++++-------
|
||||||
|
2 files changed, 5 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
Submodule common be42b0b8..5ea1baec:
|
||||||
|
diff --git a/common/options/Makefile.am b/common/options/Makefile.am
|
||||||
|
index b38fedc7..f7ea7493 100644
|
||||||
|
--- a/common/options/Makefile.am
|
||||||
|
+++ b/common/options/Makefile.am
|
||||||
|
@@ -19,6 +19,7 @@ include $(top_srcdir)/subdir-rules.mk
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
key-option.pod \
|
||||||
|
+ keys-from-stdin-option.pod \
|
||||||
|
blocksize-option.pod
|
||||||
|
|
||||||
|
# liboptions.la contains guestfish code which is used in other
|
||||||
|
diff --git a/common/options/keys-from-stdin-option.pod b/common/options/keys-from-stdin-option.pod
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..03c5339b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/common/options/keys-from-stdin-option.pod
|
||||||
|
@@ -0,0 +1,4 @@
|
||||||
|
+=item B<--keys-from-stdin>
|
||||||
|
+
|
||||||
|
+Read key or passphrase parameters from stdin. The default is
|
||||||
|
+to try to read passphrases from the user by opening F</dev/tty>.
|
||||||
|
diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
|
||||||
|
index a00fa8af..74934eb4 100644
|
||||||
|
--- a/docs/virt-v2v.pod
|
||||||
|
+++ b/docs/virt-v2v.pod
|
||||||
|
@@ -382,14 +382,11 @@ through VDDK.
|
||||||
|
|
||||||
|
__INCLUDE:key-option.pod__
|
||||||
|
|
||||||
|
-=item B<--keys-from-stdin>
|
||||||
|
+__INCLUDE:keys-from-stdin-option.pod__
|
||||||
|
|
||||||
|
-Read key or passphrase parameters from stdin. The default is
|
||||||
|
-to try to read passphrases from the user by opening F</dev/tty>.
|
||||||
|
-
|
||||||
|
-Note this options only applies to keys and passphrases for encrypted
|
||||||
|
-devices and partitions, not for passwords used to connect to remote
|
||||||
|
-servers.
|
||||||
|
+Note I<--keys-from-stdin> only applies to keys and passphrases for
|
||||||
|
+encrypted devices and partitions, not for passwords used to connect to
|
||||||
|
+remote servers.
|
||||||
|
|
||||||
|
=item B<--mac> aa:bb:cc:dd:ee:ffB<:network:>out
|
||||||
|
|
@ -0,0 +1,23 @@
|
|||||||
|
From 37ae5e04bd5f95c0c8a462dc6ef3fbdcfff4af75 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Thu, 30 Jul 2020 14:10:18 +0100
|
||||||
|
Subject: [PATCH] docs: Multiple keys must be supplied one per line
|
||||||
|
(RHBZ#1858765).
|
||||||
|
|
||||||
|
(cherry picked from commit 7ba65d14c0139dcf7fec45d33cee67c0f6737dd2)
|
||||||
|
---
|
||||||
|
common | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
Submodule common 5ea1baec..9338df5e:
|
||||||
|
diff --git a/common/options/keys-from-stdin-option.pod b/common/options/keys-from-stdin-option.pod
|
||||||
|
index 03c5339b..83790394 100644
|
||||||
|
--- a/common/options/keys-from-stdin-option.pod
|
||||||
|
+++ b/common/options/keys-from-stdin-option.pod
|
||||||
|
@@ -2,3 +2,6 @@
|
||||||
|
|
||||||
|
Read key or passphrase parameters from stdin. The default is
|
||||||
|
to try to read passphrases from the user by opening F</dev/tty>.
|
||||||
|
+
|
||||||
|
+If there are multiple encrypted devices then you may need to supply
|
||||||
|
+multiple keys on stdin, one per line.
|
@ -1,104 +0,0 @@
|
|||||||
From 4f0758a95a4b32a5c837cf86d2fa4442d3e136ec Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Tue, 16 Jan 2024 10:31:50 +0000
|
|
||||||
Subject: [PATCH] input/ssh: Rearrange parameters specifying ssh server
|
|
||||||
|
|
||||||
---
|
|
||||||
input/nbdkit_ssh.ml | 2 +-
|
|
||||||
input/nbdkit_ssh.mli | 4 ++--
|
|
||||||
input/ssh.ml | 10 +++++-----
|
|
||||||
input/ssh.mli | 13 +++++++------
|
|
||||||
4 files changed, 15 insertions(+), 14 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/input/nbdkit_ssh.ml b/input/nbdkit_ssh.ml
|
|
||||||
index bc96df13..ae93e4e8 100644
|
|
||||||
--- a/input/nbdkit_ssh.ml
|
|
||||||
+++ b/input/nbdkit_ssh.ml
|
|
||||||
@@ -44,7 +44,7 @@ let error_unless_nbdkit_min_version config =
|
|
||||||
|
|
||||||
(* Create an nbdkit module specialized for reading from SSH sources. *)
|
|
||||||
let create_ssh ?bandwidth ?cor ?(retry=true)
|
|
||||||
- ?password ?port ~server ?user path =
|
|
||||||
+ ~server ?port ?user ?password path =
|
|
||||||
if not (Nbdkit.is_installed ()) then
|
|
||||||
error (f_"nbdkit is not installed or not working");
|
|
||||||
|
|
||||||
diff --git a/input/nbdkit_ssh.mli b/input/nbdkit_ssh.mli
|
|
||||||
index 8ea8dea4..c26f539a 100644
|
|
||||||
--- a/input/nbdkit_ssh.mli
|
|
||||||
+++ b/input/nbdkit_ssh.mli
|
|
||||||
@@ -25,10 +25,10 @@ type password = (** Use [None] for no password *)
|
|
||||||
val create_ssh : ?bandwidth:Types.bandwidth ->
|
|
||||||
?cor:string ->
|
|
||||||
?retry:bool ->
|
|
||||||
- ?password:password ->
|
|
||||||
- ?port:string ->
|
|
||||||
server:string ->
|
|
||||||
+ ?port:string ->
|
|
||||||
?user:string ->
|
|
||||||
+ ?password:password ->
|
|
||||||
string -> Nbdkit.cmd
|
|
||||||
(** Create a nbdkit object using the SSH plugin. The required
|
|
||||||
string parameter is the remote path.
|
|
||||||
diff --git a/input/ssh.ml b/input/ssh.ml
|
|
||||||
index 10c61bbf..d3b6dc0c 100644
|
|
||||||
--- a/input/ssh.ml
|
|
||||||
+++ b/input/ssh.ml
|
|
||||||
@@ -23,7 +23,7 @@ open Common_gettext.Gettext
|
|
||||||
|
|
||||||
open Printf
|
|
||||||
|
|
||||||
-let start_nbdkit ?password ?port ~server ?user path =
|
|
||||||
+let start_nbdkit ~server ?port ?user ?password path =
|
|
||||||
(* Create a random location for the socket used to talk to nbdkit. *)
|
|
||||||
let sockdir = Mkdtemp.temp_dir "v2vssh." in
|
|
||||||
On_exit.rm_rf sockdir;
|
|
||||||
@@ -44,8 +44,8 @@ let start_nbdkit ?password ?port ~server ?user path =
|
|
||||||
"nbd+unix://?socket=" ^ socket
|
|
||||||
|
|
||||||
(* Download a remote file into a local file. *)
|
|
||||||
-let download_file ?password ?port ~server ?user path output =
|
|
||||||
- let uri = start_nbdkit ?password ?port ~server ?user path in
|
|
||||||
+let download_file ~server ?port ?user ?password path output =
|
|
||||||
+ let uri = start_nbdkit ~server ?port ?user ?password path in
|
|
||||||
|
|
||||||
let cmd = [ "nbdcopy"; uri; output ] in
|
|
||||||
if run_command cmd <> 0 then
|
|
||||||
@@ -53,8 +53,8 @@ let download_file ?password ?port ~server ?user path output =
|
|
||||||
see earlier error messages")
|
|
||||||
|
|
||||||
(* Test if [path] exists on the remote server. *)
|
|
||||||
-let remote_file_exists ?password ?port ~server ?user path =
|
|
||||||
- let uri = start_nbdkit ?password ?port ~server ?user path in
|
|
||||||
+let remote_file_exists ~server ?port ?user ?password path =
|
|
||||||
+ let uri = start_nbdkit ~server ?port ?user ?password path in
|
|
||||||
|
|
||||||
(* Testing for remote size using nbdinfo should be sufficient to
|
|
||||||
* prove the remote file exists.
|
|
||||||
diff --git a/input/ssh.mli b/input/ssh.mli
|
|
||||||
index 6d9f1370..ebce46ff 100644
|
|
||||||
--- a/input/ssh.mli
|
|
||||||
+++ b/input/ssh.mli
|
|
||||||
@@ -21,15 +21,16 @@
|
|
||||||
Internally this uses nbdkit-ssh-plugin (which uses sftp) as
|
|
||||||
that is much more predictable than running external ssh / scp. *)
|
|
||||||
|
|
||||||
-(** [remote_file_exists ?password ?port server ?user path]
|
|
||||||
+(** [remote_file_exists server ?port ?user ?password path]
|
|
||||||
checks that [path] exists on the remote server. *)
|
|
||||||
-val remote_file_exists : ?password:Nbdkit_ssh.password ->
|
|
||||||
- ?port:string -> server:string -> ?user:string ->
|
|
||||||
+val remote_file_exists : server:string -> ?port:string ->
|
|
||||||
+ ?user:string -> ?password:Nbdkit_ssh.password ->
|
|
||||||
string -> bool
|
|
||||||
|
|
||||||
-(** [download_file ?password ?port server ?user path output]
|
|
||||||
+(** [download_file server ?port ?user ?password path output]
|
|
||||||
downloads the single remote file at [path] to
|
|
||||||
the local file called [output]. *)
|
|
||||||
-val download_file : ?password:Nbdkit_ssh.password ->
|
|
||||||
- ?port:string -> server:string -> ?user:string -> string ->
|
|
||||||
+val download_file : server:string -> ?port:string ->
|
|
||||||
+ ?user:string -> ?password:Nbdkit_ssh.password ->
|
|
||||||
+ string ->
|
|
||||||
string -> unit
|
|
@ -1,54 +0,0 @@
|
|||||||
From 67fcf66904c7f1f6da858eba35e95dad670427c0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Wed, 17 Jan 2024 14:16:10 +0000
|
|
||||||
Subject: [PATCH] docs: Remove paragraph about -ip passwords and ssh/scp
|
|
||||||
|
|
||||||
The documentation suggested (correctly) that the -ip option did not
|
|
||||||
cover all cases where we make an ssh connection to either VMware or
|
|
||||||
Xen. However with the recent change where we use nbdkit-ssh-plugin in
|
|
||||||
preference to ssh/scp (commit fb72e05986, "virt-v2v: -i vmx: Replace
|
|
||||||
external ssh/scp with nbdkit-ssh-plugin") this should no longer be
|
|
||||||
true for VMware. And I don't think it was true for Xen for a while.
|
|
||||||
|
|
||||||
Therefore remove this paragraph in the documentation (in two places).
|
|
||||||
|
|
||||||
See-also: https://bugzilla.redhat.com/show_bug.cgi?id=1854275
|
|
||||||
See-also: https://lists.libguestfs.org/archives/list/guestfs@lists.libguestfs.org/thread/CKBEYJHUZWLDUUDWAJM2JU6QIKZGTD6F/
|
|
||||||
Suggested-by: Laszlo Ersek
|
|
||||||
---
|
|
||||||
docs/virt-v2v-input-vmware.pod | 5 -----
|
|
||||||
docs/virt-v2v-input-xen.pod | 5 -----
|
|
||||||
2 files changed, 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/docs/virt-v2v-input-vmware.pod b/docs/virt-v2v-input-vmware.pod
|
|
||||||
index 48849f88..fe59222a 100644
|
|
||||||
--- a/docs/virt-v2v-input-vmware.pod
|
|
||||||
+++ b/docs/virt-v2v-input-vmware.pod
|
|
||||||
@@ -155,11 +155,6 @@ virt-v2v server to the ESXi hypervisor. For example:
|
|
||||||
$ ssh root@esxi.example.com
|
|
||||||
[ logs straight into the shell, no password is requested ]
|
|
||||||
|
|
||||||
-Note that support for non-interactive authentication via the I<-ip>
|
|
||||||
-option is incomplete. Some operations remain that still require the
|
|
||||||
-user to enter the password manually. Therefore ssh-agent is recommended
|
|
||||||
-over the I<-ip> option. See L<https://bugzilla.redhat.com/1854275>.
|
|
||||||
-
|
|
||||||
=head3 VMX: Construct the SSH URI
|
|
||||||
|
|
||||||
When using the SSH input transport you must specify a remote
|
|
||||||
diff --git a/docs/virt-v2v-input-xen.pod b/docs/virt-v2v-input-xen.pod
|
|
||||||
index 4a0544f8..38dc8f7b 100644
|
|
||||||
--- a/docs/virt-v2v-input-xen.pod
|
|
||||||
+++ b/docs/virt-v2v-input-xen.pod
|
|
||||||
@@ -32,11 +32,6 @@ server to the Xen host. For example:
|
|
||||||
$ ssh root@xen.example.com
|
|
||||||
[ logs straight into the shell, no password is requested ]
|
|
||||||
|
|
||||||
-Note that support for non-interactive authentication via the I<-ip>
|
|
||||||
-option is incomplete. Some operations remain that still require the
|
|
||||||
-user to enter the password manually. Therefore ssh-agent is recommended
|
|
||||||
-over the I<-ip> option. See L<https://bugzilla.redhat.com/1854275>.
|
|
||||||
-
|
|
||||||
With some modern ssh implementations, legacy crypto algorithms required
|
|
||||||
to interoperate with RHEL 5 sshd are disabled. To enable them, you may
|
|
||||||
need to add the following C<Host> stanza to your F<~/.ssh/config>:
|
|
@ -1,62 +0,0 @@
|
|||||||
From 970d7123c2025bc148870f4bc6fa75fa9e95905f Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Thu, 18 Jan 2024 17:22:26 +0000
|
|
||||||
Subject: [PATCH] input/ssh: Use nbdinfo --can connect (instead of --size)
|
|
||||||
|
|
||||||
nbdinfo --size prints the size on stdout, causing it to appear in
|
|
||||||
virt-v2v output. Using --can connect instead is silent.
|
|
||||||
|
|
||||||
Note that nbdinfo --can connect was added in libnbd 1.9.2 (Jul 2021)
|
|
||||||
and our previous minimum version of libnbd was 1.9.3 so we're OK.
|
|
||||||
However since neither of these was a stable version I also updated the
|
|
||||||
minimum libnbd requirement to 1.10 (Sep 2021), and added a proper
|
|
||||||
check in ./configure
|
|
||||||
|
|
||||||
Fixes: commit fb72e059863a60503b6011b8590c25c3a010a58f
|
|
||||||
---
|
|
||||||
README | 2 +-
|
|
||||||
input/ssh.ml | 4 ++--
|
|
||||||
m4/guestfs-libraries.m4 | 2 +-
|
|
||||||
3 files changed, 4 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/README b/README
|
|
||||||
index 5810f77d..f94bd6de 100644
|
|
||||||
--- a/README
|
|
||||||
+++ b/README
|
|
||||||
@@ -51,7 +51,7 @@ REQUIREMENTS
|
|
||||||
|
|
||||||
* OCaml bindings for libvirt (https://gitlab.com/libvirt/libvirt-ocaml)
|
|
||||||
|
|
||||||
-* libnbd >= 1.9.3 (https://gitlab.com/nbdkit/libnbd)
|
|
||||||
+* libnbd >= 1.10 (https://gitlab.com/nbdkit/libnbd)
|
|
||||||
|
|
||||||
* OCaml bindings for libnbd
|
|
||||||
|
|
||||||
diff --git a/input/ssh.ml b/input/ssh.ml
|
|
||||||
index d3b6dc0c..e35a2b5a 100644
|
|
||||||
--- a/input/ssh.ml
|
|
||||||
+++ b/input/ssh.ml
|
|
||||||
@@ -56,8 +56,8 @@ let download_file ~server ?port ?user ?password path output =
|
|
||||||
let remote_file_exists ~server ?port ?user ?password path =
|
|
||||||
let uri = start_nbdkit ~server ?port ?user ?password path in
|
|
||||||
|
|
||||||
- (* Testing for remote size using nbdinfo should be sufficient to
|
|
||||||
+ (* Testing that we can connect to the nbdkit server is enough to
|
|
||||||
* prove the remote file exists.
|
|
||||||
*)
|
|
||||||
- let cmd = [ "nbdinfo"; "--size"; uri ] in
|
|
||||||
+ let cmd = [ "nbdinfo"; "--can"; "connect"; uri ] in
|
|
||||||
run_command cmd = 0
|
|
||||||
diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4
|
|
||||||
index 33b5100e..6789a2cb 100644
|
|
||||||
--- a/m4/guestfs-libraries.m4
|
|
||||||
+++ b/m4/guestfs-libraries.m4
|
|
||||||
@@ -21,7 +21,7 @@ dnl Of course we need libguestfs.
|
|
||||||
PKG_CHECK_MODULES([LIBGUESTFS], [libguestfs >= 1.44])
|
|
||||||
|
|
||||||
dnl And libnbd.
|
|
||||||
-PKG_CHECK_MODULES([LIBNBD], [libnbd])
|
|
||||||
+PKG_CHECK_MODULES([LIBNBD], [libnbd >= 1.10])
|
|
||||||
|
|
||||||
dnl Test if it's GNU or XSI strerror_r.
|
|
||||||
AC_FUNC_STRERROR_R
|
|
@ -0,0 +1,30 @@
|
|||||||
|
From 207552533f0b4ed2e2d570a827a85a44d4248b78 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pino Toscano <ptoscano@redhat.com>
|
||||||
|
Date: Mon, 17 Aug 2020 09:17:51 +0200
|
||||||
|
Subject: [PATCH] libvirt: read password file outside libvirt auth callback
|
||||||
|
|
||||||
|
This way errors that occur while reading the password file are properly
|
||||||
|
propagated, instead of being reported as errors of the libvirt
|
||||||
|
authentication callback.
|
||||||
|
|
||||||
|
Reported by: Ming Xie.
|
||||||
|
|
||||||
|
(cherry picked from commit 76f9f3a0603f33c85d681fe13e24516331c6aea7)
|
||||||
|
---
|
||||||
|
v2v/libvirt_utils.ml | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/libvirt_utils.ml b/v2v/libvirt_utils.ml
|
||||||
|
index 4d0b8639..1a24b049 100644
|
||||||
|
--- a/v2v/libvirt_utils.ml
|
||||||
|
+++ b/v2v/libvirt_utils.ml
|
||||||
|
@@ -24,8 +24,8 @@ open Common_gettext.Gettext
|
||||||
|
module. *)
|
||||||
|
|
||||||
|
let auth_for_password_file ?password_file () =
|
||||||
|
+ let password = Option.map read_first_line_from_file password_file in
|
||||||
|
let auth_fn creds =
|
||||||
|
- let password = Option.map read_first_line_from_file password_file in
|
||||||
|
List.map (
|
||||||
|
function
|
||||||
|
| { Libvirt.Connect.typ = Libvirt.Connect.CredentialPassphrase } -> password
|
@ -1,43 +0,0 @@
|
|||||||
From aafcd0d11453d8d58a32e66285f12ec3ba3440de Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Thu, 18 Jan 2024 17:32:01 +0000
|
|
||||||
Subject: [PATCH] build: Document that nbdinfo and nbdcopy are required, and
|
|
||||||
check
|
|
||||||
|
|
||||||
Update README to document that these tools have been needed (ever
|
|
||||||
since virt-v2v 2.0), and update ./configure to check it.
|
|
||||||
---
|
|
||||||
README | 2 ++
|
|
||||||
m4/guestfs-progs.m4 | 6 ++++++
|
|
||||||
2 files changed, 8 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/README b/README
|
|
||||||
index f94bd6de..4354754f 100644
|
|
||||||
--- a/README
|
|
||||||
+++ b/README
|
|
||||||
@@ -53,6 +53,8 @@ REQUIREMENTS
|
|
||||||
|
|
||||||
* libnbd >= 1.10 (https://gitlab.com/nbdkit/libnbd)
|
|
||||||
|
|
||||||
+* The 'nbdinfo' and 'nbdcopy' programs from libnbd.
|
|
||||||
+
|
|
||||||
* OCaml bindings for libnbd
|
|
||||||
|
|
||||||
* nbdkit >= 1.27.4 (https://gitlab.com/nbdkit/nbdkit)
|
|
||||||
diff --git a/m4/guestfs-progs.m4 b/m4/guestfs-progs.m4
|
|
||||||
index 7c5f0d81..ae5094ce 100644
|
|
||||||
--- a/m4/guestfs-progs.m4
|
|
||||||
+++ b/m4/guestfs-progs.m4
|
|
||||||
@@ -59,6 +59,12 @@ AM_CONDITIONAL([HAVE_ZIP],[test "x$ZIP" != "xno"])
|
|
||||||
AC_PATH_PROGS([UNZIP],[unzip],[no])
|
|
||||||
AC_DEFINE_UNQUOTED([UNZIP],["$UNZIP"],[Name of unzip program.])
|
|
||||||
|
|
||||||
+dnl nbdinfo, nbdcopy, required by virt-v2v
|
|
||||||
+AC_CHECK_PROG([NBDINFO], [nbdinfo], [nbdinfo], [no])
|
|
||||||
+AC_CHECK_PROG([NBDCOPY], [nbdcopy], [nbdcopy], [no])
|
|
||||||
+AS_IF([test "x$NBDINFO" = "xno" || test "x$NBDCOPY" = "xno"],
|
|
||||||
+ [AC_MSG_ERROR([nbdinfo and nbdcopy (from libnbd) must be installed])])
|
|
||||||
+
|
|
||||||
dnl Check for valgrind
|
|
||||||
AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind],[no])
|
|
||||||
AS_IF([test "x$VALGRIND" != "xno"],[
|
|
@ -1,18 +1,18 @@
|
|||||||
From 6cee48bde007be6c8242c9e1a3b83bc153c566d9 Mon Sep 17 00:00:00 2001
|
From ff5ae6613f5b344371cd8523a022af08fa6f191b Mon Sep 17 00:00:00 2001
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
Date: Fri, 24 Apr 2015 09:45:41 -0400
|
Date: Fri, 24 Apr 2015 09:45:41 -0400
|
||||||
Subject: [PATCH] RHEL: Fix list of supported sound cards to match RHEL qemu
|
Subject: [PATCH] RHEL 8: Fix list of supported sound cards to match RHEL qemu
|
||||||
(RHBZ#1176493).
|
(RHBZ#1176493).
|
||||||
|
|
||||||
---
|
---
|
||||||
lib/utils.ml | 5 +++--
|
v2v/utils.ml | 5 +++--
|
||||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
diff --git a/lib/utils.ml b/lib/utils.ml
|
diff --git a/v2v/utils.ml b/v2v/utils.ml
|
||||||
index 19c5ba91..7b3aa2e2 100644
|
index ccbb9d68..c2940582 100644
|
||||||
--- a/lib/utils.ml
|
--- a/v2v/utils.ml
|
||||||
+++ b/lib/utils.ml
|
+++ b/v2v/utils.ml
|
||||||
@@ -60,13 +60,14 @@ let kvm_arch = function
|
@@ -55,13 +55,14 @@ let kvm_arch = function
|
||||||
(* Does qemu support the given sound card? *)
|
(* Does qemu support the given sound card? *)
|
||||||
let qemu_supports_sound_card = function
|
let qemu_supports_sound_card = function
|
||||||
| Types.AC97
|
| Types.AC97
|
@ -0,0 +1,23 @@
|
|||||||
|
From ca9e31a9ae2e9cf5df5c65955ad746ee9f8d560b Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Thu, 2 Mar 2017 14:21:37 +0100
|
||||||
|
Subject: [PATCH] RHEL 8: v2v: -i disk: force VNC as display (RHBZ#1372671)
|
||||||
|
|
||||||
|
The SDL output mode is not supported in RHEL 8's qemu-kvm.
|
||||||
|
---
|
||||||
|
v2v/input_disk.ml | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/input_disk.ml b/v2v/input_disk.ml
|
||||||
|
index d146e84c..4e403003 100644
|
||||||
|
--- a/v2v/input_disk.ml
|
||||||
|
+++ b/v2v/input_disk.ml
|
||||||
|
@@ -89,7 +89,7 @@ class input_disk input_format disk = object
|
||||||
|
s_features = [ "acpi"; "apic"; "pae" ];
|
||||||
|
s_firmware = UnknownFirmware; (* causes virt-v2v to autodetect *)
|
||||||
|
s_display =
|
||||||
|
- Some { s_display_type = Window; s_keymap = None; s_password = None;
|
||||||
|
+ Some { s_display_type = VNC; s_keymap = None; s_password = None;
|
||||||
|
s_listen = LNoListen; s_port = None };
|
||||||
|
s_video = None;
|
||||||
|
s_sound = None;
|
@ -1,23 +0,0 @@
|
|||||||
From 8b2bb3c153b44634fb3f93aae1c0c40655213506 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Thu, 2 Mar 2017 14:21:37 +0100
|
|
||||||
Subject: [PATCH] RHEL: v2v: -i disk: force VNC as display (RHBZ#1372671)
|
|
||||||
|
|
||||||
The SDL output mode is not supported in RHEL's qemu-kvm.
|
|
||||||
---
|
|
||||||
input/input_disk.ml | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/input/input_disk.ml b/input/input_disk.ml
|
|
||||||
index 279250fe..c6b819c0 100644
|
|
||||||
--- a/input/input_disk.ml
|
|
||||||
+++ b/input/input_disk.ml
|
|
||||||
@@ -77,7 +77,7 @@ module Disk = struct
|
|
||||||
s_features = [ "acpi"; "apic"; "pae" ];
|
|
||||||
s_firmware = UnknownFirmware; (* causes virt-v2v to autodetect *)
|
|
||||||
s_display =
|
|
||||||
- Some { s_display_type = Window; s_keymap = None; s_password = None;
|
|
||||||
+ Some { s_display_type = VNC; s_keymap = None; s_password = None;
|
|
||||||
s_listen = LNoListen; s_port = None };
|
|
||||||
s_sound = None;
|
|
||||||
s_disks = s_disks;
|
|
@ -1,18 +1,18 @@
|
|||||||
From 28e3b929b94e213bc24fa27c58215fe8ccdb9ba1 Mon Sep 17 00:00:00 2001
|
From 959c084383b259ff54a247b4fdda3254e3f335db Mon Sep 17 00:00:00 2001
|
||||||
From: Pino Toscano <ptoscano@redhat.com>
|
From: Pino Toscano <ptoscano@redhat.com>
|
||||||
Date: Wed, 8 Mar 2017 11:03:40 +0100
|
Date: Wed, 8 Mar 2017 11:03:40 +0100
|
||||||
Subject: [PATCH] RHEL: v2v: do not mention SUSE Xen hosts (RHBZ#1430203)
|
Subject: [PATCH] RHEL 8: v2v: do not mention SUSE Xen hosts (RHBZ#1430203)
|
||||||
|
|
||||||
They are not supported in RHEL.
|
They are not supported in RHEL 8.
|
||||||
---
|
---
|
||||||
docs/virt-v2v-input-xen.pod | 2 +-
|
docs/virt-v2v-input-xen.pod | 2 +-
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/docs/virt-v2v-input-xen.pod b/docs/virt-v2v-input-xen.pod
|
diff --git a/docs/virt-v2v-input-xen.pod b/docs/virt-v2v-input-xen.pod
|
||||||
index 38dc8f7b..05c4e3f5 100644
|
index 3b3cf0f0..32da2848 100644
|
||||||
--- a/docs/virt-v2v-input-xen.pod
|
--- a/docs/virt-v2v-input-xen.pod
|
||||||
+++ b/docs/virt-v2v-input-xen.pod
|
+++ b/docs/virt-v2v-input-xen.pod
|
||||||
@@ -11,7 +11,7 @@ virt-v2v-input-xen - Using virt-v2v to convert guests from Xen
|
@@ -12,7 +12,7 @@ virt-v2v-input-xen - Using virt-v2v to convert guests from Xen
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
This page documents how to use L<virt-v2v(1)> to convert guests from
|
This page documents how to use L<virt-v2v(1)> to convert guests from
|
@ -0,0 +1,24 @@
|
|||||||
|
From ca86a08fe00a56a21d239cb6d1ca6dc9f8ff28fa Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pino Toscano <ptoscano@redhat.com>
|
||||||
|
Date: Sun, 16 Dec 2018 16:42:46 +0100
|
||||||
|
Subject: [PATCH] RHEL 8: use platform-python
|
||||||
|
|
||||||
|
Use the stable platform-python provided in BaseOS, instead of relying on
|
||||||
|
some arbitrary version installed by the user.
|
||||||
|
---
|
||||||
|
v2v/python_script.ml | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/python_script.ml b/v2v/python_script.ml
|
||||||
|
index 33c5e9a2..b1ea8f9d 100644
|
||||||
|
--- a/v2v/python_script.ml
|
||||||
|
+++ b/v2v/python_script.ml
|
||||||
|
@@ -24,7 +24,7 @@ open Unix_utils
|
||||||
|
|
||||||
|
open Common_gettext.Gettext
|
||||||
|
|
||||||
|
-let python = "python3" (* Defined by PEP 394 *)
|
||||||
|
+let python = "/usr/libexec/platform-python"
|
||||||
|
|
||||||
|
type script = {
|
||||||
|
tmpdir : string; (* Temporary directory. *)
|
@ -0,0 +1,385 @@
|
|||||||
|
From 186c237ac1cb6f6830cfe2d08dfdcfdbdffab264 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Mon, 6 Apr 2020 10:19:12 +0100
|
||||||
|
Subject: [PATCH] v2v: Allow large temporary directory to be set on a global
|
||||||
|
basis.
|
||||||
|
|
||||||
|
Previously we placed large files in g#get_cachedir () (usually
|
||||||
|
/var/tmp). However the problem is this ties the libguestfs appliance
|
||||||
|
and the virt-v2v overlay files to the same location.
|
||||||
|
|
||||||
|
When virt-v2v is run in a container, or any other situation where
|
||||||
|
local storage is limited, it's helpful to be able to put the overlay
|
||||||
|
files on an externally mounted PVC, which might be using NFS and
|
||||||
|
shared between containers. But putting the libguestfs appliance on
|
||||||
|
NFS in a shared location is certainly not recommended.
|
||||||
|
|
||||||
|
This allows the two locations to be set separately:
|
||||||
|
|
||||||
|
VIRT_V2V_TMPDIR - location of large temporary files, can use NFS
|
||||||
|
and may be shared
|
||||||
|
|
||||||
|
LIBGUESTFS_CACHEDIR - location of libguestfs appliance
|
||||||
|
|
||||||
|
Another motivation for this patch is to allow more reliable cleanup of
|
||||||
|
large temporary files by an external process, as described in the
|
||||||
|
updated documentation.
|
||||||
|
|
||||||
|
Small temporary files are placed in $TMPDIR (usually /tmp). I cleaned
|
||||||
|
up some existing code which used /var/tmp for small temporaries.
|
||||||
|
|
||||||
|
(cherry picked from commit 717b808bc5cb632778973eb000600e87eaf5c31a)
|
||||||
|
---
|
||||||
|
docs/virt-v2v.pod | 27 +++++++++++++++++++--------
|
||||||
|
v2v/input_ova.ml | 4 ++--
|
||||||
|
v2v/input_vmx.ml | 3 +--
|
||||||
|
v2v/output_glance.ml | 3 +--
|
||||||
|
v2v/output_null.ml | 3 +--
|
||||||
|
v2v/output_rhv_upload.ml | 29 ++++++++++++++++-------------
|
||||||
|
v2v/parse_ova.ml | 6 ++----
|
||||||
|
v2v/python_script.ml | 12 +++---------
|
||||||
|
v2v/python_script.mli | 5 +----
|
||||||
|
v2v/utils.ml | 6 +++++-
|
||||||
|
v2v/utils.mli | 5 +++++
|
||||||
|
v2v/v2v.ml | 14 ++++++--------
|
||||||
|
12 files changed, 62 insertions(+), 55 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
|
||||||
|
index 6f9f323e..af69d633 100644
|
||||||
|
--- a/docs/virt-v2v.pod
|
||||||
|
+++ b/docs/virt-v2v.pod
|
||||||
|
@@ -1172,8 +1172,8 @@ possible.
|
||||||
|
=head3 Disk space
|
||||||
|
|
||||||
|
Virt-v2v places potentially large temporary files in
|
||||||
|
-C<$LIBGUESTFS_CACHEDIR> (which is F</var/tmp> if you don't set it).
|
||||||
|
-Using tmpfs is a bad idea.
|
||||||
|
+C<$VIRT_V2V_TMPDIR> (usually F</var/tmp>, see also
|
||||||
|
+L</ENVIRONMENT VARIBLES> below). Using tmpfs is a bad idea.
|
||||||
|
|
||||||
|
For each guest disk, an overlay is stored temporarily. This stores
|
||||||
|
the changes made during conversion, and is used as a cache. The
|
||||||
|
@@ -1186,12 +1186,12 @@ and output methods may use disk space, as outlined in the table below.
|
||||||
|
=item I<-i ova>
|
||||||
|
|
||||||
|
This temporarily places a full copy of the uncompressed source disks
|
||||||
|
-in C<$LIBGUESTFS_CACHEDIR> (or F</var/tmp>).
|
||||||
|
+in C<$VIRT_V2V_TMPDIR> (or F</var/tmp>).
|
||||||
|
|
||||||
|
=item I<-o glance>
|
||||||
|
|
||||||
|
This temporarily places a full copy of the output disks in
|
||||||
|
-C<$LIBGUESTFS_CACHEDIR> (or F</var/tmp>).
|
||||||
|
+C<$VIRT_V2V_TMPDIR> (or F</var/tmp>).
|
||||||
|
|
||||||
|
=item I<-o local>
|
||||||
|
|
||||||
|
@@ -1311,7 +1311,7 @@ have at least 100 available inodes.
|
||||||
|
=head3 Minimum free space check in the host
|
||||||
|
|
||||||
|
You must have sufficient free space in the host directory used to
|
||||||
|
-store temporary overlays. To find out
|
||||||
|
+store large temporary overlays. To find out
|
||||||
|
which directory this is, use:
|
||||||
|
|
||||||
|
$ df -h "`guestfish get-cachedir`"
|
||||||
|
@@ -1319,9 +1319,12 @@ which directory this is, use:
|
||||||
|
/dev/mapper/root 50G 40G 6.8G 86% /
|
||||||
|
|
||||||
|
and look under the C<Avail> column. Virt-v2v will refuse to do the
|
||||||
|
-conversion at all unless at least 1GB is available there.
|
||||||
|
+conversion at all unless at least 1GB is available there. You can
|
||||||
|
+change the directory that virt-v2v uses by setting
|
||||||
|
+C<$VIRT_V2V_TMPDIR>.
|
||||||
|
|
||||||
|
-See also L</Resource requirements> above.
|
||||||
|
+See also L</Resource requirements> above and L</ENVIRONMENT VARIABLES>
|
||||||
|
+below.
|
||||||
|
|
||||||
|
=head2 Running virt-v2v as root or non-root
|
||||||
|
|
||||||
|
@@ -1496,10 +1499,18 @@ conversion.
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
+=item C<VIRT_V2V_TMPDIR>
|
||||||
|
+
|
||||||
|
=item C<LIBGUESTFS_CACHEDIR>
|
||||||
|
|
||||||
|
Location of the temporary directory used for the potentially large
|
||||||
|
-temporary overlay file. If not set, F</var/tmp> is used.
|
||||||
|
+temporary overlay file. If neither environment variable is set then
|
||||||
|
+F</var/tmp> is used.
|
||||||
|
+
|
||||||
|
+To reliably ensure large temporary files are cleaned up (for example
|
||||||
|
+in case virt-v2v crashes) you should create a randomly named directory
|
||||||
|
+under F</var/tmp>, set C<VIRT_V2V_TMPDIR> to point to this directory,
|
||||||
|
+then when virt-v2v exits remove the directory.
|
||||||
|
|
||||||
|
See the L</Disk space> section above.
|
||||||
|
|
||||||
|
diff --git a/v2v/input_ova.ml b/v2v/input_ova.ml
|
||||||
|
index 5d3bece1..d78a5ce8 100644
|
||||||
|
--- a/v2v/input_ova.ml
|
||||||
|
+++ b/v2v/input_ova.ml
|
||||||
|
@@ -132,8 +132,8 @@ class input_ova ova = object
|
||||||
|
(* The spec allows the file to be gzip-compressed, in
|
||||||
|
* which case we must uncompress it into a temporary.
|
||||||
|
*)
|
||||||
|
- let temp_dir = (open_guestfs ())#get_cachedir () in
|
||||||
|
- let new_filename = Filename.temp_file ~temp_dir "ova" ".vmdk" in
|
||||||
|
+ let new_filename =
|
||||||
|
+ Filename.temp_file ~temp_dir:Utils.large_tmpdir "ova" ".vmdk" in
|
||||||
|
unlink_on_exit new_filename;
|
||||||
|
let cmd =
|
||||||
|
sprintf "zcat %s > %s" (quote filename) (quote new_filename) in
|
||||||
|
diff --git a/v2v/input_vmx.ml b/v2v/input_vmx.ml
|
||||||
|
index f1d143e9..7a7647e5 100644
|
||||||
|
--- a/v2v/input_vmx.ml
|
||||||
|
+++ b/v2v/input_vmx.ml
|
||||||
|
@@ -389,8 +389,7 @@ and find_nics vmx =
|
||||||
|
|
||||||
|
class input_vmx input_password input_transport arg =
|
||||||
|
let tmpdir =
|
||||||
|
- let base_dir = (open_guestfs ())#get_cachedir () in
|
||||||
|
- let t = Mkdtemp.temp_dir ~base_dir "vmx." in
|
||||||
|
+ let t = Mkdtemp.temp_dir "vmx." in
|
||||||
|
rmdir_on_exit t;
|
||||||
|
t in
|
||||||
|
object
|
||||||
|
diff --git a/v2v/output_glance.ml b/v2v/output_glance.ml
|
||||||
|
index 0a9e9181..e8facd0a 100644
|
||||||
|
--- a/v2v/output_glance.ml
|
||||||
|
+++ b/v2v/output_glance.ml
|
||||||
|
@@ -33,8 +33,7 @@ class output_glance () =
|
||||||
|
* to write to a temporary file. XXX
|
||||||
|
*)
|
||||||
|
let tmpdir =
|
||||||
|
- let base_dir = (open_guestfs ())#get_cachedir () in
|
||||||
|
- let t = Mkdtemp.temp_dir ~base_dir "glance." in
|
||||||
|
+ let t = Mkdtemp.temp_dir ~base_dir:large_tmpdir "glance." in
|
||||||
|
rmdir_on_exit t;
|
||||||
|
t in
|
||||||
|
object
|
||||||
|
diff --git a/v2v/output_null.ml b/v2v/output_null.ml
|
||||||
|
index 3528da50..edb749ea 100644
|
||||||
|
--- a/v2v/output_null.ml
|
||||||
|
+++ b/v2v/output_null.ml
|
||||||
|
@@ -75,8 +75,7 @@ class output_null =
|
||||||
|
* the null-co device w/ a JSON URL.
|
||||||
|
*)
|
||||||
|
let tmpdir =
|
||||||
|
- let base_dir = (open_guestfs ())#get_cachedir () in
|
||||||
|
- let t = Mkdtemp.temp_dir ~base_dir "null." in
|
||||||
|
+ let t = Mkdtemp.temp_dir ~base_dir:large_tmpdir "null." in
|
||||||
|
rmdir_on_exit t;
|
||||||
|
t in
|
||||||
|
object
|
||||||
|
diff --git a/v2v/output_rhv_upload.ml b/v2v/output_rhv_upload.ml
|
||||||
|
index 81896e53..913992d9 100644
|
||||||
|
--- a/v2v/output_rhv_upload.ml
|
||||||
|
+++ b/v2v/output_rhv_upload.ml
|
||||||
|
@@ -148,25 +148,28 @@ class output_rhv_upload output_alloc output_conn
|
||||||
|
rhv_options =
|
||||||
|
(* Create a temporary directory which will be deleted on exit. *)
|
||||||
|
let tmpdir =
|
||||||
|
- let base_dir = (open_guestfs ())#get_cachedir () in
|
||||||
|
- let t = Mkdtemp.temp_dir ~base_dir "rhvupload." in
|
||||||
|
+ let t = Mkdtemp.temp_dir "rhvupload." in
|
||||||
|
rmdir_on_exit t;
|
||||||
|
t in
|
||||||
|
|
||||||
|
let diskid_file_of_id id = tmpdir // sprintf "diskid.%d" id in
|
||||||
|
|
||||||
|
(* Create Python scripts for precheck, vmcheck, plugin and create VM. *)
|
||||||
|
- let py_create = Python_script.create ~tmpdir in
|
||||||
|
- let precheck_script = py_create ~name:"rhv-upload-precheck.py"
|
||||||
|
- Output_rhv_upload_precheck_source.code in
|
||||||
|
- let vmcheck_script = py_create ~name:"rhv-upload-vmcheck.py"
|
||||||
|
- Output_rhv_upload_vmcheck_source.code in
|
||||||
|
- let plugin_script = py_create ~name:"rhv-upload-plugin.py"
|
||||||
|
- Output_rhv_upload_plugin_source.code in
|
||||||
|
- let createvm_script = py_create ~name:"rhv-upload-createvm.py"
|
||||||
|
- Output_rhv_upload_createvm_source.code in
|
||||||
|
- let deletedisks_script = py_create ~name:"rhv-upload-deletedisks.py"
|
||||||
|
- Output_rhv_upload_deletedisks_source.code in
|
||||||
|
+ let precheck_script =
|
||||||
|
+ Python_script.create ~name:"rhv-upload-precheck.py"
|
||||||
|
+ Output_rhv_upload_precheck_source.code in
|
||||||
|
+ let vmcheck_script =
|
||||||
|
+ Python_script.create ~name:"rhv-upload-vmcheck.py"
|
||||||
|
+ Output_rhv_upload_vmcheck_source.code in
|
||||||
|
+ let plugin_script =
|
||||||
|
+ Python_script.create ~name:"rhv-upload-plugin.py"
|
||||||
|
+ Output_rhv_upload_plugin_source.code in
|
||||||
|
+ let createvm_script =
|
||||||
|
+ Python_script.create ~name:"rhv-upload-createvm.py"
|
||||||
|
+ Output_rhv_upload_createvm_source.code in
|
||||||
|
+ let deletedisks_script =
|
||||||
|
+ Python_script.create ~name:"rhv-upload-deletedisks.py"
|
||||||
|
+ Output_rhv_upload_deletedisks_source.code in
|
||||||
|
|
||||||
|
(* JSON parameters which are invariant between disks. *)
|
||||||
|
let json_params = [
|
||||||
|
diff --git a/v2v/parse_ova.ml b/v2v/parse_ova.ml
|
||||||
|
index 0b939ac4..568ac5fa 100644
|
||||||
|
--- a/v2v/parse_ova.ml
|
||||||
|
+++ b/v2v/parse_ova.ml
|
||||||
|
@@ -71,8 +71,7 @@ let rec parse_ova ova =
|
||||||
|
if is_directory ova then ova, Directory
|
||||||
|
else (
|
||||||
|
let tmpdir =
|
||||||
|
- let base_dir = (open_guestfs ())#get_cachedir () in
|
||||||
|
- let t = Mkdtemp.temp_dir ~base_dir "ova." in
|
||||||
|
+ let t = Mkdtemp.temp_dir ~base_dir:large_tmpdir "ova." in
|
||||||
|
rmdir_on_exit t;
|
||||||
|
t in
|
||||||
|
|
||||||
|
@@ -221,8 +220,7 @@ and uncompress_head format file =
|
||||||
|
*)
|
||||||
|
and uncompressed_type format file =
|
||||||
|
let head, headlen = uncompress_head format file in
|
||||||
|
- let tmpfile, chan =
|
||||||
|
- Filename.open_temp_file "ova.file." "" in
|
||||||
|
+ let tmpfile, chan = Filename.open_temp_file "ova.file." "" in
|
||||||
|
output chan head 0 headlen;
|
||||||
|
close_out chan;
|
||||||
|
let ret = detect_file_type tmpfile in
|
||||||
|
diff --git a/v2v/python_script.ml b/v2v/python_script.ml
|
||||||
|
index b1ea8f9d..212c8e1b 100644
|
||||||
|
--- a/v2v/python_script.ml
|
||||||
|
+++ b/v2v/python_script.ml
|
||||||
|
@@ -31,15 +31,9 @@ type script = {
|
||||||
|
path : string; (* Path to script. *)
|
||||||
|
}
|
||||||
|
|
||||||
|
-let create ?(name = "script.py") ?tmpdir code =
|
||||||
|
- let tmpdir =
|
||||||
|
- match tmpdir with
|
||||||
|
- | None ->
|
||||||
|
- let base_dir = (open_guestfs ())#get_cachedir () in
|
||||||
|
- let t = Mkdtemp.temp_dir ~base_dir "v2v." in
|
||||||
|
- rmdir_on_exit t;
|
||||||
|
- t
|
||||||
|
- | Some dir -> dir in
|
||||||
|
+let create ?(name = "script.py") code =
|
||||||
|
+ let tmpdir = Mkdtemp.temp_dir "v2v." in
|
||||||
|
+ rmdir_on_exit tmpdir;
|
||||||
|
let path = tmpdir // name in
|
||||||
|
with_open_out path (fun chan -> output_string chan code);
|
||||||
|
{ tmpdir; path }
|
||||||
|
diff --git a/v2v/python_script.mli b/v2v/python_script.mli
|
||||||
|
index 6bf77e34..fdf73514 100644
|
||||||
|
--- a/v2v/python_script.mli
|
||||||
|
+++ b/v2v/python_script.mli
|
||||||
|
@@ -20,14 +20,11 @@
|
||||||
|
|
||||||
|
type script
|
||||||
|
|
||||||
|
-val create : ?name:string -> ?tmpdir:string -> string -> script
|
||||||
|
+val create : ?name:string -> string -> script
|
||||||
|
(** Create a Python script object.
|
||||||
|
|
||||||
|
The optional parameter [?name] is a hint for the name of the script.
|
||||||
|
|
||||||
|
- The optional parameter [?tmpdir] is the temporary directory to use
|
||||||
|
- (instead of creating a new one).
|
||||||
|
-
|
||||||
|
The parameter is the Python code. Usually this is
|
||||||
|
[Some_source.code] where [some_source.ml] is generated from
|
||||||
|
the Python file by [v2v/embed.sh] (see also [v2v/Makefile.am]). *)
|
||||||
|
diff --git a/v2v/utils.ml b/v2v/utils.ml
|
||||||
|
index c2940582..a6c359f0 100644
|
||||||
|
--- a/v2v/utils.ml
|
||||||
|
+++ b/v2v/utils.ml
|
||||||
|
@@ -24,6 +24,10 @@ open Std_utils
|
||||||
|
open Tools_utils
|
||||||
|
open Common_gettext.Gettext
|
||||||
|
|
||||||
|
+let large_tmpdir =
|
||||||
|
+ try Sys.getenv "VIRT_V2V_TMPDIR"
|
||||||
|
+ with Not_found -> (open_guestfs ())#get_cachedir ()
|
||||||
|
+
|
||||||
|
(* Is SELinux enabled and enforcing on the host? *)
|
||||||
|
let have_selinux =
|
||||||
|
0 = Sys.command "getenforce 2>/dev/null | grep -isq Enforcing"
|
||||||
|
@@ -114,6 +118,7 @@ let qemu_img_supports_offset_and_size () =
|
||||||
|
* file that has an offset and size.
|
||||||
|
*)
|
||||||
|
let tmp = Filename.temp_file "v2vqemuimgtst" ".img" in
|
||||||
|
+ unlink_on_exit tmp;
|
||||||
|
Unix.truncate tmp 1024;
|
||||||
|
|
||||||
|
let json = [
|
||||||
|
@@ -133,7 +138,6 @@ let qemu_img_supports_offset_and_size () =
|
||||||
|
(if verbose () then "" else " 2>&1") in
|
||||||
|
debug "%s" cmd;
|
||||||
|
let r = 0 = Sys.command cmd in
|
||||||
|
- Unix.unlink tmp;
|
||||||
|
debug "qemu-img supports \"offset\" and \"size\" in json URLs: %b" r;
|
||||||
|
r
|
||||||
|
|
||||||
|
diff --git a/v2v/utils.mli b/v2v/utils.mli
|
||||||
|
index 937e2b9b..d86ca507 100644
|
||||||
|
--- a/v2v/utils.mli
|
||||||
|
+++ b/v2v/utils.mli
|
||||||
|
@@ -18,6 +18,11 @@
|
||||||
|
|
||||||
|
(** Utilities used in virt-v2v only. *)
|
||||||
|
|
||||||
|
+val large_tmpdir : string
|
||||||
|
+(** [VIRT_V2V_TMPDIR] or [/var/tmp]. Create all large temporary files
|
||||||
|
+ such as overlays in this directory. Small temporary files can
|
||||||
|
+ use the default behaviour eg. of {!Filename.temp_file} *)
|
||||||
|
+
|
||||||
|
val have_selinux : bool
|
||||||
|
(** True if SELinux is enabled and enforcing on the host. *)
|
||||||
|
|
||||||
|
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
|
||||||
|
index 73edff2c..a58ff433 100644
|
||||||
|
--- a/v2v/v2v.ml
|
||||||
|
+++ b/v2v/v2v.ml
|
||||||
|
@@ -264,8 +264,6 @@ and set_source_networks_and_bridges cmdline source =
|
||||||
|
let nics = List.map (Networks.map cmdline.network_map) source.s_nics in
|
||||||
|
{ source with s_nics = nics }
|
||||||
|
|
||||||
|
-and overlay_dir = (open_guestfs ())#get_cachedir ()
|
||||||
|
-
|
||||||
|
(* Conversion can fail or hang if there is insufficient free space in
|
||||||
|
* the temporary directory used to store overlays on the host
|
||||||
|
* (RHBZ#1316479). Although only a few hundred MB is actually
|
||||||
|
@@ -273,12 +271,12 @@ and overlay_dir = (open_guestfs ())#get_cachedir ()
|
||||||
|
* guestfs appliance which is also stored here.
|
||||||
|
*)
|
||||||
|
and check_host_free_space () =
|
||||||
|
- let free_space = StatVFS.free_space (StatVFS.statvfs overlay_dir) in
|
||||||
|
- debug "check_host_free_space: overlay_dir=%s free_space=%Ld"
|
||||||
|
- overlay_dir free_space;
|
||||||
|
+ let free_space = StatVFS.free_space (StatVFS.statvfs large_tmpdir) in
|
||||||
|
+ debug "check_host_free_space: large_tmpdir=%s free_space=%Ld"
|
||||||
|
+ large_tmpdir free_space;
|
||||||
|
if free_space < 1_073_741_824L then
|
||||||
|
error (f_"insufficient free space in the conversion server temporary directory %s (%s).\n\nEither free up space in that directory, or set the LIBGUESTFS_CACHEDIR environment variable to point to another directory with more than 1GB of free space.\n\nSee also the virt-v2v(1) manual, section \"Minimum free space check in the host\".")
|
||||||
|
- overlay_dir (human_size free_space)
|
||||||
|
+ large_tmpdir (human_size free_space)
|
||||||
|
|
||||||
|
(* Create a qcow2 v3 overlay to protect the source image(s). *)
|
||||||
|
and create_overlays source_disks =
|
||||||
|
@@ -286,7 +284,7 @@ and create_overlays source_disks =
|
||||||
|
List.mapi (
|
||||||
|
fun i ({ s_qemu_uri = qemu_uri; s_format = format } as source) ->
|
||||||
|
let overlay_file =
|
||||||
|
- Filename.temp_file ~temp_dir:overlay_dir "v2vovl" ".qcow2" in
|
||||||
|
+ Filename.temp_file ~temp_dir:large_tmpdir "v2vovl" ".qcow2" in
|
||||||
|
unlink_on_exit overlay_file;
|
||||||
|
|
||||||
|
(* There is a specific reason to use the newer qcow2 variant:
|
||||||
|
@@ -823,7 +821,7 @@ and preserve_overlays overlays src_name =
|
||||||
|
List.iter (
|
||||||
|
fun ov ->
|
||||||
|
let saved_filename =
|
||||||
|
- sprintf "%s/%s-%s.qcow2" overlay_dir src_name ov.ov_sd in
|
||||||
|
+ sprintf "%s/%s-%s.qcow2" large_tmpdir src_name ov.ov_sd in
|
||||||
|
rename ov.ov_overlay_file saved_filename;
|
||||||
|
info (f_"Overlay saved as %s [--debug-overlays]") saved_filename
|
||||||
|
) overlays
|
@ -1,22 +0,0 @@
|
|||||||
From d9c11fcfdf832f9d3d35855e7e7458efc1908515 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Tue, 5 Jul 2022 11:58:09 +0100
|
|
||||||
Subject: [PATCH] RHEL 9: tests: Remove btrfs test
|
|
||||||
|
|
||||||
RHEL does not have btrfs so this test always fails.
|
|
||||||
---
|
|
||||||
tests/Makefile.am | 1 -
|
|
||||||
1 file changed, 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
|
||||||
index 5169e2a6..a1c61f8f 100644
|
|
||||||
--- a/tests/Makefile.am
|
|
||||||
+++ b/tests/Makefile.am
|
|
||||||
@@ -98,7 +98,6 @@ TESTS = \
|
|
||||||
test-v2v-sound.sh \
|
|
||||||
test-v2v-virtio-win-iso.sh \
|
|
||||||
test-v2v-fedora-conversion.sh \
|
|
||||||
- test-v2v-fedora-btrfs-conversion.sh \
|
|
||||||
test-v2v-fedora-luks-on-lvm-conversion.sh \
|
|
||||||
test-v2v-fedora-lvm-on-luks-conversion.sh \
|
|
||||||
test-v2v-fedora-md-conversion.sh \
|
|
@ -0,0 +1,31 @@
|
|||||||
|
From 82d56820db4f05711b125daf46a4777e99dbdf87 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 25 Aug 2020 08:23:52 +0100
|
||||||
|
Subject: [PATCH] v2v: -o openstack: Allow guests to be converted to UEFI
|
||||||
|
(RHBZ#1872094).
|
||||||
|
|
||||||
|
Since this output method was written the code has always been capable
|
||||||
|
of adding the hw_firmware_type = uefi image property, and this
|
||||||
|
property has been supported since at least OpenStack 12 which is years
|
||||||
|
old.
|
||||||
|
|
||||||
|
Interestingly now all of the output modes support both BIOS and UEFI.
|
||||||
|
|
||||||
|
(cherry picked from commit 5fa65a13fbbaab03cb558d0c776c17227433f1b3)
|
||||||
|
---
|
||||||
|
v2v/output_openstack.ml | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/output_openstack.ml b/v2v/output_openstack.ml
|
||||||
|
index 179b0edf..fdc04b02 100644
|
||||||
|
--- a/v2v/output_openstack.ml
|
||||||
|
+++ b/v2v/output_openstack.ml
|
||||||
|
@@ -390,7 +390,7 @@ object
|
||||||
|
| None -> ""
|
||||||
|
| Some op -> " -op " ^ op)
|
||||||
|
|
||||||
|
- method supported_firmware = [ TargetBIOS ]
|
||||||
|
+ method supported_firmware = [ TargetBIOS; TargetUEFI ]
|
||||||
|
|
||||||
|
(* List of Cinder volume IDs. *)
|
||||||
|
val mutable volume_ids = []
|
@ -0,0 +1,41 @@
|
|||||||
|
From 358122c089d1e4df014a6821365341d3220ab6e6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 19 Jan 2021 11:26:23 +0000
|
||||||
|
Subject: [PATCH] v2v: Fix spelling mistake in uninstall function name.
|
||||||
|
|
||||||
|
Fixes: commit 53847717fa1d0ffc2a174275badf486eb1ed6fae
|
||||||
|
(cherry picked from commit 3515c9f617271bec89962ba8a2b8c690e6df4c99)
|
||||||
|
---
|
||||||
|
v2v/convert_windows.ml | 6 +++---
|
||||||
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
|
||||||
|
index ba26949f..f2f7b95c 100644
|
||||||
|
--- a/v2v/convert_windows.ml
|
||||||
|
+++ b/v2v/convert_windows.ml
|
||||||
|
@@ -135,7 +135,7 @@ let convert (g : G.guestfs) inspect _ output rcaps static_ips =
|
||||||
|
(* Locate and retrieve all the uninstallation commands for installed
|
||||||
|
* applications.
|
||||||
|
*)
|
||||||
|
- let unistallation_commands pretty_name matchfn extra_uninstall_string =
|
||||||
|
+ let uninstallation_commands pretty_name matchfn extra_uninstall_string =
|
||||||
|
let uninsts = ref [] in
|
||||||
|
|
||||||
|
Registry.with_hive_readonly g inspect.i_windows_software_hive
|
||||||
|
@@ -198,14 +198,14 @@ let convert (g : G.guestfs) inspect _ output rcaps static_ips =
|
||||||
|
*)
|
||||||
|
let extra_uninstall_string =
|
||||||
|
Some "PREVENT_REBOOT=Yes LAUNCHED_BY_SETUP_EXE=Yes" in
|
||||||
|
- unistallation_commands "Parallels Tools" matchfn extra_uninstall_string in
|
||||||
|
+ uninstallation_commands "Parallels Tools" matchfn extra_uninstall_string in
|
||||||
|
|
||||||
|
(* Locate and retrieve all uninstallation commands for VMware Tools. *)
|
||||||
|
let vmwaretools_uninst =
|
||||||
|
let matchfn s =
|
||||||
|
String.find s "VMware Tools" != -1
|
||||||
|
in
|
||||||
|
- unistallation_commands "VMware Tools" matchfn None in
|
||||||
|
+ uninstallation_commands "VMware Tools" matchfn None in
|
||||||
|
|
||||||
|
(*----------------------------------------------------------------------*)
|
||||||
|
(* Perform the conversion of the Windows guest. *)
|
@ -1,68 +0,0 @@
|
|||||||
From 88e4e0213f5dc9e60720f6a84edf36bffbea723e Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Thu, 16 May 2024 12:32:00 +0100
|
|
||||||
Subject: [PATCH] Update common submodule
|
|
||||||
|
|
||||||
Pulls in these commits, but they are not thought to be relevant to
|
|
||||||
virt-v2v.
|
|
||||||
|
|
||||||
Ben Brown (1):
|
|
||||||
Initialise bar->fp as NULL
|
|
||||||
|
|
||||||
Richard W.M. Jones (2):
|
|
||||||
mlcustomize: Update virt-customize generated files
|
|
||||||
options: Allow nbd+unix:// URIs
|
|
||||||
|
|
||||||
(cherry picked from commit 6513fcbec9a10652cb8b5690936e7265e9c8851c)
|
|
||||||
---
|
|
||||||
common | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
Submodule common 0dba002c..93a7f3af:
|
|
||||||
diff --git a/common/mlcustomize/customize_cmdline.ml b/common/mlcustomize/customize_cmdline.ml
|
|
||||||
index 245d9960..48ee3344 100644
|
|
||||||
--- a/common/mlcustomize/customize_cmdline.ml
|
|
||||||
+++ b/common/mlcustomize/customize_cmdline.ml
|
|
||||||
@@ -157,7 +157,7 @@ let rec argspec () =
|
|
||||||
let len = String.length arg in
|
|
||||||
String.sub arg 0 i, String.sub arg (i+1) (len-(i+1))
|
|
||||||
and split_string_triplet option_name arg =
|
|
||||||
- match String.nsplit ~max:3 "," arg with
|
|
||||||
+ match String.nsplit ~max:3 ":" arg with
|
|
||||||
| [a; b; c] -> a, b, c
|
|
||||||
| _ ->
|
|
||||||
error (f_"invalid format for '--%s' parameter, see the man page")
|
|
||||||
diff --git a/common/options/uri.c b/common/options/uri.c
|
|
||||||
index 84d393c1..9180d6a2 100644
|
|
||||||
--- a/common/options/uri.c
|
|
||||||
+++ b/common/options/uri.c
|
|
||||||
@@ -99,7 +99,7 @@ is_uri (const char *arg)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (p--; p >= arg; p--) {
|
|
||||||
- if (!c_islower (*p))
|
|
||||||
+ if (! (c_islower (*p) || *p == '+'))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -148,7 +148,10 @@ parse (const char *arg, char **path_ret, char **protocol_ret,
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
- *protocol_ret = strdup (uri->scheme);
|
|
||||||
+ if (STREQ (uri->scheme, "nbd+unix"))
|
|
||||||
+ *protocol_ret = strdup ("nbd");
|
|
||||||
+ else
|
|
||||||
+ *protocol_ret = strdup (uri->scheme);
|
|
||||||
if (*protocol_ret == NULL) {
|
|
||||||
perror ("strdup: protocol");
|
|
||||||
return -1;
|
|
||||||
@@ -194,7 +197,7 @@ parse (const char *arg, char **path_ret, char **protocol_ret,
|
|
||||||
if (path && path[0] == '/' &&
|
|
||||||
(STREQ (uri->scheme, "gluster") ||
|
|
||||||
STREQ (uri->scheme, "iscsi") ||
|
|
||||||
- STREQ (uri->scheme, "nbd") ||
|
|
||||||
+ STRPREFIX (uri->scheme, "nbd") ||
|
|
||||||
STREQ (uri->scheme, "rbd") ||
|
|
||||||
STREQ (uri->scheme, "sheepdog")))
|
|
||||||
path++;
|
|
@ -0,0 +1,59 @@
|
|||||||
|
From 2bf5fc815d53e581398e787ae96444c438945ab3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 19 Jan 2021 12:17:49 +0000
|
||||||
|
Subject: [PATCH] v2v: Replace broken VMware Tools uninstall command msiexec /i
|
||||||
|
with /x.
|
||||||
|
|
||||||
|
Fixes: https://bugzilla.redhat.com/1917760
|
||||||
|
Thanks: Chetan Nagarkar
|
||||||
|
(cherry picked from commit f7496b0a7e76a06bda8d7ec1aba36741f8cb295c)
|
||||||
|
---
|
||||||
|
v2v/convert_windows.ml | 15 ++++++++++++---
|
||||||
|
1 file changed, 12 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
|
||||||
|
index 84db742f..44cef5ed 100644
|
||||||
|
--- a/v2v/convert_windows.ml
|
||||||
|
+++ b/v2v/convert_windows.ml
|
||||||
|
@@ -135,7 +135,7 @@ let convert (g : G.guestfs) inspect _ output rcaps static_ips =
|
||||||
|
(* Locate and retrieve all the uninstallation commands for installed
|
||||||
|
* applications.
|
||||||
|
*)
|
||||||
|
- let uninstallation_commands pretty_name matchfn extra_uninstall_params =
|
||||||
|
+ let uninstallation_commands pretty_name matchfn modfn extra_uninstall_params =
|
||||||
|
let path = ["Microsoft"; "Windows"; "CurrentVersion"; "Uninstall"] in
|
||||||
|
let uninstval = "UninstallString" in
|
||||||
|
let ret = ref [] in
|
||||||
|
@@ -155,6 +155,7 @@ let convert (g : G.guestfs) inspect _ output rcaps static_ips =
|
||||||
|
let valueh = g#hivex_node_get_value uninstnode uninstval in
|
||||||
|
if valueh <> 0L then (
|
||||||
|
let reg_cmd = g#hivex_value_string valueh in
|
||||||
|
+ let reg_cmd = modfn reg_cmd in
|
||||||
|
let cmd =
|
||||||
|
sprintf "%s /quiet /norestart /l*v+ \"%%~dpn0.log\" REBOOT=ReallySuppress REMOVE=ALL %s"
|
||||||
|
reg_cmd extra_uninstall_params in
|
||||||
|
@@ -183,14 +184,22 @@ let convert (g : G.guestfs) inspect _ output rcaps static_ips =
|
||||||
|
*)
|
||||||
|
let extra_uninstall_params =
|
||||||
|
"PREVENT_REBOOT=Yes LAUNCHED_BY_SETUP_EXE=Yes" in
|
||||||
|
- uninstallation_commands "Parallels Tools" matchfn extra_uninstall_params in
|
||||||
|
+ uninstallation_commands "Parallels Tools" matchfn identity
|
||||||
|
+ extra_uninstall_params in
|
||||||
|
|
||||||
|
(* Locate and retrieve all uninstallation commands for VMware Tools. *)
|
||||||
|
let vmwaretools_uninst =
|
||||||
|
let matchfn s =
|
||||||
|
String.find s "VMware Tools" != -1
|
||||||
|
in
|
||||||
|
- uninstallation_commands "VMware Tools" matchfn "" in
|
||||||
|
+ (* VMware Tools writes the install command (MsiExec /I) into the
|
||||||
|
+ * UninstallString key in the registry, rather than the uninstall
|
||||||
|
+ * command. Try to spot this and rewrite. (RHBZ#1917760).
|
||||||
|
+ *)
|
||||||
|
+ let re1 = PCRE.compile ~caseless:true "msiexec" in
|
||||||
|
+ let re2 = PCRE.compile ~caseless:true "/i" in
|
||||||
|
+ let msifn s = if PCRE.matches re1 s then PCRE.replace re2 "/x" s else s in
|
||||||
|
+ uninstallation_commands "VMware Tools" matchfn msifn "" in
|
||||||
|
|
||||||
|
(*----------------------------------------------------------------------*)
|
||||||
|
(* Perform the conversion of the Windows guest. *)
|
@ -0,0 +1,447 @@
|
|||||||
|
From 9292a4637e8f4d534f4dde70e8e5451f61ad0162 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 19 Jan 2021 14:22:33 +0000
|
||||||
|
Subject: [PATCH] Update common/ submodule to latest upstream.
|
||||||
|
|
||||||
|
Only for RHEL AV 8.4.0, allowing this branch to be compiled
|
||||||
|
from git with libguestfs 1.44.
|
||||||
|
---
|
||||||
|
common | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
Submodule common 9338df5e...be09523d:
|
||||||
|
diff --git a/common/mlcustomize/SELinux_relabel.ml b/common/mlcustomize/SELinux_relabel.ml
|
||||||
|
index 44995df6..5ecf7bd7 100644
|
||||||
|
--- a/common/mlcustomize/SELinux_relabel.ml
|
||||||
|
+++ b/common/mlcustomize/SELinux_relabel.ml
|
||||||
|
@@ -28,65 +28,80 @@ module G = Guestfs
|
||||||
|
let array_find a l =
|
||||||
|
List.mem a (Array.to_list l)
|
||||||
|
|
||||||
|
-let relabel (g : G.guestfs) =
|
||||||
|
- (* Is the guest using SELinux? *)
|
||||||
|
- if g#is_file ~followsymlinks:true "/usr/sbin/load_policy" &&
|
||||||
|
- g#is_file ~followsymlinks:true "/etc/selinux/config" then (
|
||||||
|
- (* Is setfiles / SELinux relabelling functionality available? *)
|
||||||
|
- if g#feature_available [| "selinuxrelabel" |] then (
|
||||||
|
- (* Use Augeas to parse /etc/selinux/config. *)
|
||||||
|
- g#aug_init "/" (16+32) (* AUG_SAVE_NOOP | AUG_NO_LOAD *);
|
||||||
|
- (* See: https://bugzilla.redhat.com/show_bug.cgi?id=975412#c0 *)
|
||||||
|
- ignore (g#aug_rm "/augeas/load/*[\"/etc/selinux/config/\" !~ regexp('^') + glob(incl) + regexp('/.*')]");
|
||||||
|
- g#aug_load ();
|
||||||
|
- debug_augeas_errors g;
|
||||||
|
-
|
||||||
|
- (* Get the SELinux policy name, eg. "targeted", "minimum".
|
||||||
|
- * Use "targeted" if not specified, just like libselinux does.
|
||||||
|
- *)
|
||||||
|
- let policy =
|
||||||
|
- let config_path = "/files/etc/selinux/config" in
|
||||||
|
- let selinuxtype_path = config_path ^ "/SELINUXTYPE" in
|
||||||
|
- let keys = g#aug_ls config_path in
|
||||||
|
- if array_find selinuxtype_path keys then
|
||||||
|
- g#aug_get selinuxtype_path
|
||||||
|
- else
|
||||||
|
- "targeted" in
|
||||||
|
-
|
||||||
|
- g#aug_close ();
|
||||||
|
-
|
||||||
|
- (* Get the spec file name. *)
|
||||||
|
- let specfile =
|
||||||
|
- sprintf "/etc/selinux/%s/contexts/files/file_contexts" policy in
|
||||||
|
-
|
||||||
|
- (* RHEL 6.2 - 6.5 had a malformed specfile that contained the
|
||||||
|
- * invalid regular expression "/var/run/spice-vdagentd.\pid"
|
||||||
|
- * (instead of "\.p"). This stops setfiles from working on
|
||||||
|
- * the guest.
|
||||||
|
- *
|
||||||
|
- * Because an SELinux relabel writes all over the filesystem,
|
||||||
|
- * it seems reasonable to fix this problem in the specfile
|
||||||
|
- * at the same time. (RHBZ#1374232)
|
||||||
|
- *)
|
||||||
|
- if g#grep ~fixed:true "vdagentd.\\pid" specfile <> [||] then (
|
||||||
|
- debug "fixing invalid regular expression in %s" specfile;
|
||||||
|
- let old_specfile = specfile ^ "~" in
|
||||||
|
- g#mv specfile old_specfile;
|
||||||
|
- let content = g#read_file old_specfile in
|
||||||
|
- let content =
|
||||||
|
- String.replace content "vdagentd.\\pid" "vdagentd\\.pid" in
|
||||||
|
- g#write specfile content;
|
||||||
|
- g#copy_attributes ~all:true old_specfile specfile
|
||||||
|
- );
|
||||||
|
-
|
||||||
|
- (* Relabel everything. *)
|
||||||
|
- g#selinux_relabel ~force:true specfile "/";
|
||||||
|
-
|
||||||
|
- (* If that worked, we don't need to autorelabel. *)
|
||||||
|
+let rec relabel (g : G.guestfs) =
|
||||||
|
+ (* Is the guest using SELinux? (Otherwise this is a no-op). *)
|
||||||
|
+ if is_selinux_guest g then (
|
||||||
|
+ try
|
||||||
|
+ use_setfiles g;
|
||||||
|
+ (* That worked, so we don't need to autorelabel. *)
|
||||||
|
g#rm_f "/.autorelabel"
|
||||||
|
- )
|
||||||
|
- else (
|
||||||
|
- (* SELinux guest, but not SELinux host. Fallback to this. *)
|
||||||
|
+ with Failure _ ->
|
||||||
|
+ (* This is the fallback in case something in the setfiles
|
||||||
|
+ * method didn't work. That includes the case where a non-SELinux
|
||||||
|
+ * host is processing an SELinux guest, and other things.
|
||||||
|
+ *)
|
||||||
|
g#touch "/.autorelabel"
|
||||||
|
- )
|
||||||
|
)
|
||||||
|
+
|
||||||
|
+and is_selinux_guest g =
|
||||||
|
+ g#is_file ~followsymlinks:true "/usr/sbin/load_policy" &&
|
||||||
|
+ g#is_file ~followsymlinks:true "/etc/selinux/config"
|
||||||
|
+
|
||||||
|
+and use_setfiles g =
|
||||||
|
+ (* Is setfiles / SELinux relabelling functionality available? *)
|
||||||
|
+ if not (g#feature_available [| "selinuxrelabel" |]) then
|
||||||
|
+ failwith "no selinux relabel feature";
|
||||||
|
+
|
||||||
|
+ (* Use Augeas to parse /etc/selinux/config. *)
|
||||||
|
+ g#aug_init "/" (16+32) (* AUG_SAVE_NOOP | AUG_NO_LOAD *);
|
||||||
|
+ (* See: https://bugzilla.redhat.com/show_bug.cgi?id=975412#c0 *)
|
||||||
|
+ ignore (g#aug_rm "/augeas/load/*[\"/etc/selinux/config/\" !~ regexp('^') + glob(incl) + regexp('/.*')]");
|
||||||
|
+ g#aug_load ();
|
||||||
|
+ debug_augeas_errors g;
|
||||||
|
+
|
||||||
|
+ (* Get the SELinux policy name, eg. "targeted", "minimum".
|
||||||
|
+ * Use "targeted" if not specified, just like libselinux does.
|
||||||
|
+ *)
|
||||||
|
+ let policy =
|
||||||
|
+ let config_path = "/files/etc/selinux/config" in
|
||||||
|
+ let selinuxtype_path = config_path ^ "/SELINUXTYPE" in
|
||||||
|
+ let keys = g#aug_ls config_path in
|
||||||
|
+ if array_find selinuxtype_path keys then
|
||||||
|
+ g#aug_get selinuxtype_path
|
||||||
|
+ else
|
||||||
|
+ "targeted" in
|
||||||
|
+
|
||||||
|
+ g#aug_close ();
|
||||||
|
+
|
||||||
|
+ (* Get the spec file name. *)
|
||||||
|
+ let specfile =
|
||||||
|
+ sprintf "/etc/selinux/%s/contexts/files/file_contexts" policy in
|
||||||
|
+
|
||||||
|
+ (* If the spec file doesn't exist then fall back to using
|
||||||
|
+ * autorelabel (RHBZ#1828952).
|
||||||
|
+ *)
|
||||||
|
+ if not (g#is_file ~followsymlinks:true specfile) then
|
||||||
|
+ failwith "no spec file";
|
||||||
|
+
|
||||||
|
+ (* RHEL 6.2 - 6.5 had a malformed specfile that contained the
|
||||||
|
+ * invalid regular expression "/var/run/spice-vdagentd.\pid"
|
||||||
|
+ * (instead of "\.p"). This stops setfiles from working on
|
||||||
|
+ * the guest.
|
||||||
|
+ *
|
||||||
|
+ * Because an SELinux relabel writes all over the filesystem,
|
||||||
|
+ * it seems reasonable to fix this problem in the specfile
|
||||||
|
+ * at the same time. (RHBZ#1374232)
|
||||||
|
+ *)
|
||||||
|
+ if g#grep ~fixed:true "vdagentd.\\pid" specfile <> [||] then (
|
||||||
|
+ debug "fixing invalid regular expression in %s" specfile;
|
||||||
|
+ let old_specfile = specfile ^ "~" in
|
||||||
|
+ g#mv specfile old_specfile;
|
||||||
|
+ let content = g#read_file old_specfile in
|
||||||
|
+ let content =
|
||||||
|
+ String.replace content "vdagentd.\\pid" "vdagentd\\.pid" in
|
||||||
|
+ g#write specfile content;
|
||||||
|
+ g#copy_attributes ~all:true old_specfile specfile
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ (* Relabel everything. *)
|
||||||
|
+ g#selinux_relabel ~force:true specfile "/"
|
||||||
|
diff --git a/common/mltools/Makefile.am b/common/mltools/Makefile.am
|
||||||
|
index 3b4172db..aea2dce9 100644
|
||||||
|
--- a/common/mltools/Makefile.am
|
||||||
|
+++ b/common/mltools/Makefile.am
|
||||||
|
@@ -95,6 +95,7 @@ libmltools_a_CPPFLAGS = \
|
||||||
|
-I$(shell $(OCAMLC) -where) \
|
||||||
|
-I$(top_srcdir)/common/utils \
|
||||||
|
-I$(top_srcdir)/lib \
|
||||||
|
+ $(INCLUDE_DIRECTORY) \
|
||||||
|
-I$(top_srcdir)/common/options \
|
||||||
|
-I$(top_srcdir)/common/mlgettext \
|
||||||
|
-I$(top_srcdir)/common/mlpcre \
|
||||||
|
diff --git a/common/mltools/tools_utils.ml b/common/mltools/tools_utils.ml
|
||||||
|
index 12718022..d54ec581 100644
|
||||||
|
--- a/common/mltools/tools_utils.ml
|
||||||
|
+++ b/common/mltools/tools_utils.ml
|
||||||
|
@@ -679,3 +679,53 @@ let with_timeout op timeout ?(sleep = 2) fn =
|
||||||
|
loop ()
|
||||||
|
in
|
||||||
|
loop ()
|
||||||
|
+
|
||||||
|
+let run_in_guest_command g root ?logfile ?incompatible_fn cmd =
|
||||||
|
+ (* Is the host_cpu compatible with the guest arch? ie. Can we
|
||||||
|
+ * run commands in this guest?
|
||||||
|
+ *)
|
||||||
|
+ let guest_arch = g#inspect_get_arch root in
|
||||||
|
+ let guest_arch_compatible = guest_arch_compatible guest_arch in
|
||||||
|
+ if not guest_arch_compatible then (
|
||||||
|
+ match incompatible_fn with
|
||||||
|
+ | None -> ()
|
||||||
|
+ | Some fn -> fn ()
|
||||||
|
+ )
|
||||||
|
+ else (
|
||||||
|
+ (* Add a prologue to the scripts:
|
||||||
|
+ * - Pass environment variables through from the host.
|
||||||
|
+ * - Optionally send stdout and stderr to a log file so we capture
|
||||||
|
+ * all output in error messages.
|
||||||
|
+ * - Use setarch when running x86_64 host + i686 guest.
|
||||||
|
+ *)
|
||||||
|
+ let env_vars =
|
||||||
|
+ List.filter_map (
|
||||||
|
+ fun name ->
|
||||||
|
+ try Some (sprintf "export %s=%s" name (quote (Sys.getenv name)))
|
||||||
|
+ with Not_found -> None
|
||||||
|
+ ) [ "http_proxy"; "https_proxy"; "ftp_proxy"; "no_proxy" ] in
|
||||||
|
+ let env_vars = String.concat "\n" env_vars ^ "\n" in
|
||||||
|
+
|
||||||
|
+ let cmd =
|
||||||
|
+ match Guestfs_config.host_cpu, guest_arch with
|
||||||
|
+ | "x86_64", ("i386"|"i486"|"i586"|"i686") ->
|
||||||
|
+ sprintf "setarch i686 <<\"__EOCMD\"
|
||||||
|
+%s
|
||||||
|
+__EOCMD
|
||||||
|
+" cmd
|
||||||
|
+ | _ -> cmd in
|
||||||
|
+
|
||||||
|
+ let logfile_redirect =
|
||||||
|
+ match logfile with
|
||||||
|
+ | None -> ""
|
||||||
|
+ | Some logfile -> sprintf "exec >>%s 2>&1" (quote logfile) in
|
||||||
|
+
|
||||||
|
+ let cmd = sprintf "\
|
||||||
|
+%s
|
||||||
|
+%s
|
||||||
|
+%s
|
||||||
|
+" (logfile_redirect) env_vars cmd in
|
||||||
|
+
|
||||||
|
+ debug "running command:\n%s" cmd;
|
||||||
|
+ ignore (g#sh cmd)
|
||||||
|
+ )
|
||||||
|
diff --git a/common/mltools/tools_utils.mli b/common/mltools/tools_utils.mli
|
||||||
|
index ab70f583..1d1ac8a8 100644
|
||||||
|
--- a/common/mltools/tools_utils.mli
|
||||||
|
+++ b/common/mltools/tools_utils.mli
|
||||||
|
@@ -195,9 +195,8 @@ val is_btrfs_subvolume : Guestfs.guestfs -> string -> bool
|
||||||
|
(** Checks if a filesystem is a btrfs subvolume. *)
|
||||||
|
|
||||||
|
val inspect_decrypt : Guestfs.guestfs -> key_store -> unit
|
||||||
|
-(** Simple implementation of decryption: look for any [crypto_LUKS]
|
||||||
|
- partitions and decrypt them, then rescan for VGs. This only works
|
||||||
|
- for Fedora whole-disk encryption. *)
|
||||||
|
+(** Simple implementation of decryption: look for any encrypted
|
||||||
|
+ partitions and decrypt them, then rescan for VGs. *)
|
||||||
|
|
||||||
|
val with_timeout : string -> int -> ?sleep:int -> (unit -> 'a option) -> 'a
|
||||||
|
(** [with_timeout op timeout ?sleep fn] implements a timeout loop.
|
||||||
|
@@ -212,3 +211,13 @@ val with_timeout : string -> int -> ?sleep:int -> (unit -> 'a option) -> 'a
|
||||||
|
calls {!error} and the program exits. The error message will
|
||||||
|
contain the diagnostic string [op] to identify the operation
|
||||||
|
which timed out. *)
|
||||||
|
+
|
||||||
|
+val run_in_guest_command : Guestfs.guestfs -> string -> ?logfile:string -> ?incompatible_fn:(unit -> unit) -> string -> unit
|
||||||
|
+(** [run_in_guest_command g root ?incompatible_archs_fn cmd]
|
||||||
|
+ runs a command in the guest, which is already mounted for the
|
||||||
|
+ specified [root]. The command is run directly in case the
|
||||||
|
+ architecture of the host and the guest are compatible, optionally
|
||||||
|
+ calling [?incompatible_fn] in case they are not.
|
||||||
|
+
|
||||||
|
+ [?logfile] is an optional file in the guest to where redirect
|
||||||
|
+ stdout and stderr of the command. *)
|
||||||
|
diff --git a/common/mlutils/unix_utils-c.c b/common/mlutils/unix_utils-c.c
|
||||||
|
index 33099611..8acf0395 100644
|
||||||
|
--- a/common/mlutils/unix_utils-c.c
|
||||||
|
+++ b/common/mlutils/unix_utils-c.c
|
||||||
|
@@ -77,6 +77,7 @@ extern value guestfs_int_mllib_mkdtemp (value val_pattern);
|
||||||
|
extern value guestfs_int_mllib_realpath (value pathv);
|
||||||
|
extern value guestfs_int_mllib_statvfs_statvfs (value pathv);
|
||||||
|
extern value guestfs_int_mllib_statvfs_is_network_filesystem (value pathv);
|
||||||
|
+extern value guestfs_int_mllib_sysconf_nr_processors_online (value unitv);
|
||||||
|
|
||||||
|
/* NB: This is a "noalloc" call. */
|
||||||
|
value
|
||||||
|
@@ -368,3 +369,17 @@ guestfs_int_mllib_statvfs_is_network_filesystem (value pathv)
|
||||||
|
return Val_bool (0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+/* NB: This is a "noalloc" call. */
|
||||||
|
+value
|
||||||
|
+guestfs_int_mllib_sysconf_nr_processors_online (value unitv)
|
||||||
|
+{
|
||||||
|
+#ifdef _SC_NPROCESSORS_ONLN
|
||||||
|
+ long n;
|
||||||
|
+
|
||||||
|
+ n = sysconf (_SC_NPROCESSORS_ONLN);
|
||||||
|
+ if (n > 0) return Val_int (n);
|
||||||
|
+#endif
|
||||||
|
+ /* Return a safe value so that callers don't need to deal with errors. */
|
||||||
|
+ return Val_int (1);
|
||||||
|
+}
|
||||||
|
diff --git a/common/mlutils/unix_utils.ml b/common/mlutils/unix_utils.ml
|
||||||
|
index 52eb824d..2bdda12a 100644
|
||||||
|
--- a/common/mlutils/unix_utils.ml
|
||||||
|
+++ b/common/mlutils/unix_utils.ml
|
||||||
|
@@ -84,3 +84,8 @@ module StatVFS = struct
|
||||||
|
external is_network_filesystem : string -> bool =
|
||||||
|
"guestfs_int_mllib_statvfs_is_network_filesystem" "noalloc"
|
||||||
|
end
|
||||||
|
+
|
||||||
|
+module Sysconf = struct
|
||||||
|
+ external nr_processors_online : unit -> int =
|
||||||
|
+ "guestfs_int_mllib_sysconf_nr_processors_online" "noalloc"
|
||||||
|
+end
|
||||||
|
diff --git a/common/mlutils/unix_utils.mli b/common/mlutils/unix_utils.mli
|
||||||
|
index 4fcea4a3..aead4df2 100644
|
||||||
|
--- a/common/mlutils/unix_utils.mli
|
||||||
|
+++ b/common/mlutils/unix_utils.mli
|
||||||
|
@@ -121,3 +121,12 @@ module StatVFS : sig
|
||||||
|
(** [is_network_filesystem path] returns true if [path] is located on
|
||||||
|
a network filesystem such as NFS or CIFS. *)
|
||||||
|
end
|
||||||
|
+
|
||||||
|
+module Sysconf : sig
|
||||||
|
+ val nr_processors_online : unit -> int
|
||||||
|
+ (** [nr_processors_online ()] returns the number of processors
|
||||||
|
+ currently online, from [sysconf (_SC_NPROCESSORS_ONLN)].
|
||||||
|
+
|
||||||
|
+ Note this never fails. In case we cannot get the number of
|
||||||
|
+ cores it returns 1. *)
|
||||||
|
+end
|
||||||
|
diff --git a/common/options/Makefile.am b/common/options/Makefile.am
|
||||||
|
index f7ea7493..162d143b 100644
|
||||||
|
--- a/common/options/Makefile.am
|
||||||
|
+++ b/common/options/Makefile.am
|
||||||
|
@@ -41,8 +41,9 @@ liboptions_la_SOURCES = \
|
||||||
|
liboptions_la_CPPFLAGS = \
|
||||||
|
-DGUESTFS_NO_DEPRECATED=1 \
|
||||||
|
-I$(top_srcdir)/common/utils -I$(top_builddir)/common/utils \
|
||||||
|
+ -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \
|
||||||
|
-I$(top_srcdir)/lib -I$(top_builddir)/lib \
|
||||||
|
- -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib
|
||||||
|
+ $(INCLUDE_DIRECTORY)
|
||||||
|
liboptions_la_CFLAGS = \
|
||||||
|
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
|
||||||
|
$(LIBCONFIG_CFLAGS) \
|
||||||
|
diff --git a/common/options/decrypt.c b/common/options/decrypt.c
|
||||||
|
index 683cf5ed..434b7d58 100644
|
||||||
|
--- a/common/options/decrypt.c
|
||||||
|
+++ b/common/options/decrypt.c
|
||||||
|
@@ -25,6 +25,7 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include <error.h>
|
||||||
|
@@ -38,18 +39,18 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a LUKS map name from the partition name,
|
||||||
|
- * eg. C<"/dev/vda2" =E<gt> "luksvda2">
|
||||||
|
+ * eg. C<"/dev/vda2" =E<gt> "cryptvda2">
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
make_mapname (const char *device, char *mapname, size_t len)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
- if (len < 5)
|
||||||
|
+ if (len < 6)
|
||||||
|
abort ();
|
||||||
|
- strcpy (mapname, "luks");
|
||||||
|
- mapname += 4;
|
||||||
|
- len -= 4;
|
||||||
|
+ strcpy (mapname, "crypt");
|
||||||
|
+ mapname += 5;
|
||||||
|
+ len -= 5;
|
||||||
|
|
||||||
|
if (STRPREFIX (device, "/dev/"))
|
||||||
|
i = 5;
|
||||||
|
@@ -65,10 +66,8 @@ make_mapname (const char *device, char *mapname, size_t len)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
- * Simple implementation of decryption: look for any C<crypto_LUKS>
|
||||||
|
- * partitions and decrypt them, then rescan for VGs. This only works
|
||||||
|
- * for Fedora whole-disk encryption. WIP to make this work for other
|
||||||
|
- * encryption schemes.
|
||||||
|
+ * Simple implementation of decryption: look for any encrypted
|
||||||
|
+ * partitions and decrypt them, then rescan for VGs.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
inspect_do_decrypt (guestfs_h *g, struct key_store *ks)
|
||||||
|
@@ -82,12 +81,21 @@ inspect_do_decrypt (guestfs_h *g, struct key_store *ks)
|
||||||
|
|
||||||
|
for (i = 0; partitions[i] != NULL; ++i) {
|
||||||
|
CLEANUP_FREE char *type = guestfs_vfs_type (g, partitions[i]);
|
||||||
|
- if (type && STREQ (type, "crypto_LUKS")) {
|
||||||
|
+ if (type &&
|
||||||
|
+ (STREQ (type, "crypto_LUKS") || STREQ (type, "BitLocker"))) {
|
||||||
|
+ bool is_bitlocker = STREQ (type, "BitLocker");
|
||||||
|
char mapname[32];
|
||||||
|
make_mapname (partitions[i], mapname, sizeof mapname);
|
||||||
|
|
||||||
|
#ifdef GUESTFS_HAVE_LUKS_UUID
|
||||||
|
- CLEANUP_FREE char *uuid = guestfs_luks_uuid (g, partitions[i]);
|
||||||
|
+ CLEANUP_FREE char *uuid = NULL;
|
||||||
|
+
|
||||||
|
+ /* This fails for Windows BitLocker disks because cryptsetup
|
||||||
|
+ * luksUUID cannot read a UUID (unclear if this is a limitation
|
||||||
|
+ * of the format or cryptsetup).
|
||||||
|
+ */
|
||||||
|
+ if (!is_bitlocker)
|
||||||
|
+ uuid = guestfs_luks_uuid (g, partitions[i]);
|
||||||
|
#else
|
||||||
|
const char *uuid = NULL;
|
||||||
|
#endif
|
||||||
|
@@ -97,11 +105,15 @@ inspect_do_decrypt (guestfs_h *g, struct key_store *ks)
|
||||||
|
|
||||||
|
/* Try each key in turn. */
|
||||||
|
for (j = 0; keys[j] != NULL; ++j) {
|
||||||
|
- /* XXX Should we call guestfs_luks_open_ro if readonly flag
|
||||||
|
+ /* XXX Should we set GUESTFS_CRYPTSETUP_OPEN_READONLY if readonly
|
||||||
|
* is set? This might break 'mount_ro'.
|
||||||
|
*/
|
||||||
|
guestfs_push_error_handler (g, NULL, NULL);
|
||||||
|
+#ifdef GUESTFS_HAVE_CRYPTSETUP_OPEN
|
||||||
|
+ r = guestfs_cryptsetup_open (g, partitions[i], keys[j], mapname, -1);
|
||||||
|
+#else
|
||||||
|
r = guestfs_luks_open (g, partitions[i], keys[j], mapname);
|
||||||
|
+#endif
|
||||||
|
guestfs_pop_error_handler (g);
|
||||||
|
if (r == 0)
|
||||||
|
goto opened;
|
||||||
|
diff --git a/common/options/uri.c b/common/options/uri.c
|
||||||
|
index ac36bccb..6b696fc2 100644
|
||||||
|
--- a/common/options/uri.c
|
||||||
|
+++ b/common/options/uri.c
|
||||||
|
@@ -194,6 +194,7 @@ parse (const char *arg, char **path_ret, char **protocol_ret,
|
||||||
|
if (path && path[0] == '/' &&
|
||||||
|
(STREQ (uri->scheme, "gluster") ||
|
||||||
|
STREQ (uri->scheme, "iscsi") ||
|
||||||
|
+ STREQ (uri->scheme, "nbd") ||
|
||||||
|
STREQ (uri->scheme, "rbd") ||
|
||||||
|
STREQ (uri->scheme, "sheepdog")))
|
||||||
|
path++;
|
||||||
|
diff --git a/common/utils/guestfs-stringlists-utils.h b/common/utils/guestfs-stringlists-utils.h
|
||||||
|
index 0bac1587..ade3b6f3 100644
|
||||||
|
--- a/common/utils/guestfs-stringlists-utils.h
|
||||||
|
+++ b/common/utils/guestfs-stringlists-utils.h
|
||||||
|
@@ -21,7 +21,8 @@
|
||||||
|
|
||||||
|
/* stringlists-utils.c */
|
||||||
|
extern void guestfs_int_free_string_list (char **);
|
||||||
|
-extern size_t guestfs_int_count_strings (char *const *);
|
||||||
|
+extern size_t guestfs_int_count_strings (char *const *)
|
||||||
|
+ __attribute__((__nonnull__ (1)));
|
||||||
|
extern char *guestfs_int_concat_strings (char *const *);
|
||||||
|
extern char **guestfs_int_copy_string_list (char *const *);
|
||||||
|
extern char *guestfs_int_join_strings (const char *sep, char *const *);
|
@ -1,109 +0,0 @@
|
|||||||
From 006bdf2599f4d56e0612192291b846b384675e96 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Thu, 25 Jul 2024 09:08:41 +0100
|
|
||||||
Subject: [PATCH] Update common submodule
|
|
||||||
|
|
||||||
This pulls in the commits below which simplify the installation of
|
|
||||||
Qemu Guest Agent on Windows.
|
|
||||||
|
|
||||||
Richard W.M. Jones (4):
|
|
||||||
mlcustomize: firstboot: Use Linux path for Powershell script path
|
|
||||||
mlcustomize: firstboot: Use powershell.exe instead of path
|
|
||||||
mlcustomize: firstboot: Use Powershell -NoProfile flag
|
|
||||||
mlcustomize: Revert delay installation of qemu-ga MSI
|
|
||||||
|
|
||||||
Fixes: https://issues.redhat.com/browse/RHEL-49761
|
|
||||||
(cherry picked from commit 4ba18d2d6d1155db7cd83641a650477c0a13dbec)
|
|
||||||
---
|
|
||||||
common | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
Submodule common 830cbdcf..5d1f5b84:
|
|
||||||
diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml
|
|
||||||
index 5dc01234..4b9b910b 100644
|
|
||||||
--- a/common/mlcustomize/firstboot.ml
|
|
||||||
+++ b/common/mlcustomize/firstboot.ml
|
|
||||||
@@ -387,16 +387,10 @@ let add_firstboot_powershell g root ?prio name code =
|
|
||||||
(* Create the temporary directory to put the Powershell file. *)
|
|
||||||
let tempdir = sprintf "%s/Temp" windows_systemroot in
|
|
||||||
g#mkdir_p tempdir;
|
|
||||||
+ let ps_path = sprintf "%s/%s" tempdir name in
|
|
||||||
let code = String.concat "\r\n" code ^ "\r\n" in
|
|
||||||
- g#write (sprintf "%s/%s" tempdir name) code;
|
|
||||||
+ g#write ps_path code;
|
|
||||||
|
|
||||||
- (* Powershell interpreter. Should we check this exists? XXX *)
|
|
||||||
- let ps_exe =
|
|
||||||
- windows_systemroot ^
|
|
||||||
- "\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" in
|
|
||||||
-
|
|
||||||
- (* Windows path to the Powershell script. *)
|
|
||||||
- let ps_path = windows_systemroot ^ "\\Temp\\" ^ name in
|
|
||||||
-
|
|
||||||
- let fb = sprintf "%s -ExecutionPolicy ByPass -file %s" ps_exe ps_path in
|
|
||||||
+ let fb = sprintf "powershell.exe -ExecutionPolicy ByPass -NoProfile -file %s"
|
|
||||||
+ ps_path in
|
|
||||||
add_firstboot_script g root ?prio name fb
|
|
||||||
diff --git a/common/mlcustomize/inject_virtio_win.ml b/common/mlcustomize/inject_virtio_win.ml
|
|
||||||
index 4e0ed0e0..eee93669 100644
|
|
||||||
--- a/common/mlcustomize/inject_virtio_win.ml
|
|
||||||
+++ b/common/mlcustomize/inject_virtio_win.ml
|
|
||||||
@@ -575,40 +575,28 @@ and copy_from_libosinfo { g; i_osinfo; i_arch } destdir =
|
|
||||||
) driver.Libosinfo.files
|
|
||||||
with Not_found -> []
|
|
||||||
|
|
||||||
+(* Install qemu-ga. [files] is the non-empty list of possible qemu-ga
|
|
||||||
+ * installers we detected.
|
|
||||||
+ *)
|
|
||||||
and configure_qemu_ga t files =
|
|
||||||
+ let script = ref [] in
|
|
||||||
+ let add = List.push_back script in
|
|
||||||
+
|
|
||||||
+ add "# Virt-v2v script which installs QEMU Guest Agent";
|
|
||||||
+ add "";
|
|
||||||
+ add "# Uncomment this line for lots of debug output.";
|
|
||||||
+ add "# Set-PSDebug -Trace 2";
|
|
||||||
+ add "";
|
|
||||||
+ add "Write-Host Installing QEMU Guest Agent";
|
|
||||||
+ add "";
|
|
||||||
+ add "# Run qemu-ga installers";
|
|
||||||
List.iter (
|
|
||||||
fun msi_path ->
|
|
||||||
- (* Windows is a trashfire.
|
|
||||||
- * https://stackoverflow.com/a/18730884
|
|
||||||
- * https://bugzilla.redhat.com/show_bug.cgi?id=1895323
|
|
||||||
- *)
|
|
||||||
- let psh_script = ref [] in
|
|
||||||
- let add = List.push_back psh_script in
|
|
||||||
+ add (sprintf "C:\\%s /norestart /qn /l+*vx C:\\%s.log"
|
|
||||||
+ msi_path msi_path)
|
|
||||||
+ ) files;
|
|
||||||
|
|
||||||
- add "# Uncomment this line for lots of debug output.";
|
|
||||||
- add "# Set-PSDebug -Trace 2";
|
|
||||||
- add "";
|
|
||||||
- add "Write-Host Removing any previously scheduled qemu-ga installation";
|
|
||||||
- add "schtasks.exe /Delete /TN Firstboot-qemu-ga /F";
|
|
||||||
- add "";
|
|
||||||
- add (sprintf
|
|
||||||
- "Write-Host Scheduling delayed installation of qemu-ga from %s"
|
|
||||||
- msi_path);
|
|
||||||
- add "$d = (get-date).AddSeconds(120)";
|
|
||||||
- add "$dtfinfo = [System.Globalization.DateTimeFormatInfo]::CurrentInfo";
|
|
||||||
- add "$sdp = $dtfinfo.ShortDatePattern";
|
|
||||||
- add "$sdp = $sdp -replace 'y+', 'yyyy'";
|
|
||||||
- add "$sdp = $sdp -replace 'M+', 'MM'";
|
|
||||||
- add "$sdp = $sdp -replace 'd+', 'dd'";
|
|
||||||
- add "schtasks.exe /Create /SC ONCE `";
|
|
||||||
- add " /ST $d.ToString('HH:mm') /SD $d.ToString($sdp) `";
|
|
||||||
- add " /RU SYSTEM /TN Firstboot-qemu-ga `";
|
|
||||||
- add (sprintf " /TR \"C:\\%s /forcerestart /qn /l+*vx C:\\%s.log\""
|
|
||||||
- msi_path msi_path);
|
|
||||||
-
|
|
||||||
- Firstboot.add_firstboot_powershell t.g t.root
|
|
||||||
- (sprintf "install-%s.ps1" msi_path) !psh_script;
|
|
||||||
- ) files
|
|
||||||
+ Firstboot.add_firstboot_powershell t.g t.root "install-qemu-ga.ps1" !script
|
|
||||||
|
|
||||||
and configure_blnsvr t blnsvr =
|
|
||||||
let cmd = sprintf "\
|
|
@ -1,124 +0,0 @@
|
|||||||
From 22691e516898b0d54ad4100c9f04beb1e70f9dc0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Sun, 28 Jul 2024 14:49:42 +0100
|
|
||||||
Subject: [PATCH] v2v: --mac: Allow gw and len fields to be empty
|
|
||||||
|
|
||||||
Even if these appear in the middle of the list, allow them to be
|
|
||||||
empty. For example this is now permitted whereas previously it was an
|
|
||||||
error:
|
|
||||||
|
|
||||||
virt-v2v --mac <MAC>:ip:<ADDR>,,,nameserver
|
|
||||||
|
|
||||||
Reported-by: Arik Hadas
|
|
||||||
(cherry picked from commit 159fda411d2f75b087106e7293d273ae142c9fbe)
|
|
||||||
---
|
|
||||||
in-place/in_place.ml | 12 +++++++-----
|
|
||||||
inspector/inspector.ml | 12 +++++++-----
|
|
||||||
v2v/v2v.ml | 12 +++++++-----
|
|
||||||
3 files changed, 21 insertions(+), 15 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/in-place/in_place.ml b/in-place/in_place.ml
|
|
||||||
index 2049db16..a61d9795 100644
|
|
||||||
--- a/in-place/in_place.ml
|
|
||||||
+++ b/in-place/in_place.ml
|
|
||||||
@@ -90,10 +90,10 @@ let rec main () =
|
|
||||||
| "ip" ->
|
|
||||||
(match String.nsplit "," out with
|
|
||||||
| [] -> error (f_"invalid --mac ip option")
|
|
||||||
- | [ip] -> add_static_ip mac ip None None []
|
|
||||||
- | [ip; gw] -> add_static_ip mac ip (Some gw) None []
|
|
||||||
+ | [ip] -> add_static_ip mac ip "" "" []
|
|
||||||
+ | [ip; gw] -> add_static_ip mac ip gw "" []
|
|
||||||
| ip :: gw :: len :: nameservers ->
|
|
||||||
- add_static_ip mac ip (Some gw) (Some len) nameservers
|
|
||||||
+ add_static_ip mac ip gw len nameservers
|
|
||||||
)
|
|
||||||
| _ -> assert false
|
|
||||||
and add_static_ip if_mac_addr if_ip_address if_default_gateway
|
|
||||||
@@ -108,12 +108,14 @@ let rec main () =
|
|
||||||
an IP address") what addr
|
|
||||||
in
|
|
||||||
error_unless_ip_addr "ipaddr" if_ip_address;
|
|
||||||
+ let if_default_gateway =
|
|
||||||
+ match if_default_gateway with "" -> None | gw -> Some gw in
|
|
||||||
Option.iter (error_unless_ip_addr "gw") if_default_gateway;
|
|
||||||
List.iter (error_unless_ip_addr "nameserver") if_nameservers;
|
|
||||||
let if_prefix_length =
|
|
||||||
match if_prefix_length_str with
|
|
||||||
- | None -> None
|
|
||||||
- | Some len ->
|
|
||||||
+ | "" -> None
|
|
||||||
+ | len ->
|
|
||||||
let len =
|
|
||||||
try int_of_string len with
|
|
||||||
| Failure _ -> error (f_"cannot parse --mac ip prefix length \
|
|
||||||
diff --git a/inspector/inspector.ml b/inspector/inspector.ml
|
|
||||||
index 02d1a0e7..417b31c5 100644
|
|
||||||
--- a/inspector/inspector.ml
|
|
||||||
+++ b/inspector/inspector.ml
|
|
||||||
@@ -97,10 +97,10 @@ let rec main () =
|
|
||||||
| "ip" ->
|
|
||||||
(match String.nsplit "," out with
|
|
||||||
| [] -> error (f_"invalid --mac ip option")
|
|
||||||
- | [ip] -> add_static_ip mac ip None None []
|
|
||||||
- | [ip; gw] -> add_static_ip mac ip (Some gw) None []
|
|
||||||
+ | [ip] -> add_static_ip mac ip "" "" []
|
|
||||||
+ | [ip; gw] -> add_static_ip mac ip gw "" []
|
|
||||||
| ip :: gw :: len :: nameservers ->
|
|
||||||
- add_static_ip mac ip (Some gw) (Some len) nameservers
|
|
||||||
+ add_static_ip mac ip gw len nameservers
|
|
||||||
)
|
|
||||||
| _ -> assert false
|
|
||||||
and add_static_ip if_mac_addr if_ip_address if_default_gateway
|
|
||||||
@@ -115,12 +115,14 @@ let rec main () =
|
|
||||||
is an IP address") what addr
|
|
||||||
in
|
|
||||||
error_unless_ip_addr "ipaddr" if_ip_address;
|
|
||||||
+ let if_default_gateway =
|
|
||||||
+ match if_default_gateway with "" -> None | gw -> Some gw in
|
|
||||||
Option.iter (error_unless_ip_addr "gw") if_default_gateway;
|
|
||||||
List.iter (error_unless_ip_addr "nameserver") if_nameservers;
|
|
||||||
let if_prefix_length =
|
|
||||||
match if_prefix_length_str with
|
|
||||||
- | None -> None
|
|
||||||
- | Some len ->
|
|
||||||
+ | "" -> None
|
|
||||||
+ | len ->
|
|
||||||
let len =
|
|
||||||
try int_of_string len with
|
|
||||||
| Failure _ -> error (f_"cannot parse --mac ip prefix \
|
|
||||||
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
|
|
||||||
index 89c08fc5..6d9e3792 100644
|
|
||||||
--- a/v2v/v2v.ml
|
|
||||||
+++ b/v2v/v2v.ml
|
|
||||||
@@ -109,10 +109,10 @@ let rec main () =
|
|
||||||
| "ip" ->
|
|
||||||
(match String.nsplit "," out with
|
|
||||||
| [] -> error (f_"invalid --mac ip option")
|
|
||||||
- | [ip] -> add_static_ip mac ip None None []
|
|
||||||
- | [ip; gw] -> add_static_ip mac ip (Some gw) None []
|
|
||||||
+ | [ip] -> add_static_ip mac ip "" "" []
|
|
||||||
+ | [ip; gw] -> add_static_ip mac ip gw "" []
|
|
||||||
| ip :: gw :: len :: nameservers ->
|
|
||||||
- add_static_ip mac ip (Some gw) (Some len) nameservers
|
|
||||||
+ add_static_ip mac ip gw len nameservers
|
|
||||||
)
|
|
||||||
| _ -> assert false
|
|
||||||
and add_static_ip if_mac_addr if_ip_address if_default_gateway
|
|
||||||
@@ -127,12 +127,14 @@ let rec main () =
|
|
||||||
is an IP address") what addr
|
|
||||||
in
|
|
||||||
error_unless_ip_addr "ipaddr" if_ip_address;
|
|
||||||
+ let if_default_gateway =
|
|
||||||
+ match if_default_gateway with "" -> None | gw -> Some gw in
|
|
||||||
Option.iter (error_unless_ip_addr "gw") if_default_gateway;
|
|
||||||
List.iter (error_unless_ip_addr "nameserver") if_nameservers;
|
|
||||||
let if_prefix_length =
|
|
||||||
match if_prefix_length_str with
|
|
||||||
- | None -> None
|
|
||||||
- | Some len ->
|
|
||||||
+ | "" -> None
|
|
||||||
+ | len ->
|
|
||||||
let len =
|
|
||||||
try int_of_string len with
|
|
||||||
| Failure _ -> error (f_"cannot parse --mac ip prefix length field \
|
|
@ -0,0 +1,80 @@
|
|||||||
|
From 987ddcd2ad7546212d3afed52b56f27a664624d6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nir Soffer <nsoffer@redhat.com>
|
||||||
|
Date: Thu, 21 Jan 2021 03:40:00 +0200
|
||||||
|
Subject: [PATCH] v2v: rhv-upload-plugin: Defer imageio connection
|
||||||
|
|
||||||
|
When using vddk input with certain vmware version, qemu-img may spend
|
||||||
|
lot of time getting source image extents. If getting image extents takes
|
||||||
|
more than 60 seconds, imageio server closes the idle connection, and the
|
||||||
|
transfer will fail on the first write with:
|
||||||
|
|
||||||
|
nbdkit: python[1]: error: /var/tmp/rhvupload.0OKqWA/rhv-upload-plugin.py: pwrite: error:
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/var/tmp/rhvupload.0OKqWA/rhv-upload-plugin.py", line 94, in wrapper
|
||||||
|
return func(h, *args)
|
||||||
|
File "/var/tmp/rhvupload.0OKqWA/rhv-upload-plugin.py", line 230, in pwrite
|
||||||
|
r = http.getresponse()
|
||||||
|
File "/usr/lib64/python3.6/http/client.py", line 1361, in getresponse
|
||||||
|
response.begin()
|
||||||
|
File "/usr/lib64/python3.6/http/client.py", line 311, in begin
|
||||||
|
version, status, reason = self._read_status()
|
||||||
|
File "/usr/lib64/python3.6/http/client.py", line 280, in _read_status
|
||||||
|
raise RemoteDisconnected("Remote end closed connection without"
|
||||||
|
http.client.RemoteDisconnected: Remote end closed connection without response
|
||||||
|
|
||||||
|
This happens only when not using unix socket, for example when running
|
||||||
|
on non-ovirt host, or ovirt host from another data center, or when using
|
||||||
|
-oo rhv_direct=false
|
||||||
|
|
||||||
|
When using unix socket, we close the initial HTTPSConnection, and
|
||||||
|
created a new UnixHTTPConnection. This connection is not connected to
|
||||||
|
the server yet. When qemu-img tries to access the server, the connection
|
||||||
|
is connected automatically.
|
||||||
|
|
||||||
|
Fix the issue by closing the initial connection used to get server
|
||||||
|
options and initialize the handle, and storing a closed connection in
|
||||||
|
the handle.
|
||||||
|
|
||||||
|
Here is the flow with this change:
|
||||||
|
|
||||||
|
1. Create HTTPSConnection for getting server options
|
||||||
|
2. Close the connection[1]
|
||||||
|
3. If using unix socket, create UnixHTTPConnection.
|
||||||
|
4. Store the connection in the handle.
|
||||||
|
5. When qemu-img try to write/zero, the connection is reconnects
|
||||||
|
automatically to imageio server[2]
|
||||||
|
|
||||||
|
Tested by adding a 300 milliseconds delay in nbdkit file plugin. Due to
|
||||||
|
the way qemu-img works, this cause more than 2 minutes delay after
|
||||||
|
open() but before the first pwrite(). Without this change, the import
|
||||||
|
fails consistently when using rhv_direct=false.
|
||||||
|
|
||||||
|
[1] https://github.com/python/cpython/blob/34df10a9a16b38d54421eeeaf73ec89828563be7/Lib/http/client.py#L958
|
||||||
|
[2] https://github.com/python/cpython/blob/34df10a9a16b38d54421eeeaf73ec89828563be7/Lib/http/client.py#L972
|
||||||
|
|
||||||
|
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
|
||||||
|
(cherry picked from commit 1d5fc257765c444644e5bfc6525e86ff201755f0)
|
||||||
|
---
|
||||||
|
v2v/rhv-upload-plugin.py | 9 +++++++++
|
||||||
|
1 file changed, 9 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py
|
||||||
|
index 471102da..7cd6dea6 100644
|
||||||
|
--- a/v2v/rhv-upload-plugin.py
|
||||||
|
+++ b/v2v/rhv-upload-plugin.py
|
||||||
|
@@ -117,6 +117,15 @@ def open(readonly):
|
||||||
|
destination_url = parse_transfer_url(transfer)
|
||||||
|
http = create_http(destination_url)
|
||||||
|
options = get_options(http, destination_url)
|
||||||
|
+
|
||||||
|
+ # Close the initial connection to imageio server. When qemu-img will
|
||||||
|
+ # try to access the server, HTTPConnection will reconnect
|
||||||
|
+ # automatically. If we keep this connection idle and qemu-img is too
|
||||||
|
+ # slow getting image extents, imageio server may close the connection,
|
||||||
|
+ # and the import will fail on the first write.
|
||||||
|
+ # See https://bugzilla.redhat.com/1916176.
|
||||||
|
+ http.close()
|
||||||
|
+
|
||||||
|
http = optimize_http(http, host, options)
|
||||||
|
except:
|
||||||
|
cancel_transfer(connection, transfer)
|
@ -1,29 +0,0 @@
|
|||||||
From 48c49139b94b1081c6392ab3b14fbb72c024f18d Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Wed, 31 Jul 2024 10:09:50 +0100
|
|
||||||
Subject: [PATCH] docs: Note that --mac len field is now optional
|
|
||||||
|
|
||||||
Reported-by: Ming Xie
|
|
||||||
Updates: commit 159fda411d2f75b087106e7293d273ae142c9fbe
|
|
||||||
(cherry picked from commit 7800049c5612e6ffb30be7f8862d147d82976ae8)
|
|
||||||
---
|
|
||||||
docs/virt-v2v.pod | 6 +++---
|
|
||||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
|
|
||||||
index 021ac897..c173563b 100644
|
|
||||||
--- a/docs/virt-v2v.pod
|
|
||||||
+++ b/docs/virt-v2v.pod
|
|
||||||
@@ -372,9 +372,9 @@ Force a particular interface (controlled by its MAC address) to have a
|
|
||||||
static IP address after boot.
|
|
||||||
|
|
||||||
The fields in the parameter are: C<ipaddr> is the IP address. C<gw>
|
|
||||||
-is the optional gateway IP address. C<len> is the subnet mask length
|
|
||||||
-(an integer). The final parameters are zero or more nameserver IP
|
|
||||||
-addresses.
|
|
||||||
+is the optional gateway IP address. C<len> is the optional subnet
|
|
||||||
+mask length (an integer). The final parameters are zero or more
|
|
||||||
+nameserver IP addresses.
|
|
||||||
|
|
||||||
This option can be supplied zero or more times.
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
|||||||
|
From 88429f56491ed0e5b3f5f91e6e352fa1251484bc Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Mon, 30 Nov 2020 08:55:34 +0000
|
||||||
|
Subject: [PATCH] v2v: windows: Fix schtasks /SD parameter.
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Thanks: Dinesh Herath, Tomáš Golembiovský, Bryan Kinney, Mark Zealey
|
||||||
|
|
||||||
|
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1895323
|
||||||
|
(cherry picked from commit b65711c9293415f671d35d0e2f9b55a74343da45)
|
||||||
|
---
|
||||||
|
v2v/convert_windows.ml | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
|
||||||
|
index 44cef5ed..4d844e2d 100644
|
||||||
|
--- a/v2v/convert_windows.ml
|
||||||
|
+++ b/v2v/convert_windows.ml
|
||||||
|
@@ -422,11 +422,12 @@ popd
|
||||||
|
and configure_qemu_ga files =
|
||||||
|
List.iter (
|
||||||
|
fun msi_path ->
|
||||||
|
+ (* Windows is a trashfire. https://stackoverflow.com/a/18730884 *)
|
||||||
|
let fb_script = sprintf "\
|
||||||
|
echo Removing any previously scheduled qemu-ga installation
|
||||||
|
schtasks.exe /Delete /TN Firstboot-qemu-ga /F
|
||||||
|
echo Scheduling delayed installation of qemu-ga from %s
|
||||||
|
-powershell.exe -command \"$d = (get-date).AddSeconds(120); schtasks.exe /Create /SC ONCE /ST $d.ToString('HH:mm') /SD $d.ToString('MM/dd/yyyy') /RU SYSTEM /TN Firstboot-qemu-ga /TR \\\"C:\\%s /forcerestart /qn /l+*vx C:\\%s.log\\\"\"
|
||||||
|
+powershell.exe -command \"$d = (get-date).AddSeconds(120); $FormatHack = ($([System.Globalization.DateTimeFormatInfo]::CurrentInfo.ShortDatePattern) -replace 'M+/', 'MM/') -replace 'd+/', 'dd/'; schtasks.exe /Create /SC ONCE /ST $d.ToString('HH:mm') /SD $d.ToString($FormatHack) /RU SYSTEM /TN Firstboot-qemu-ga /TR \\\"C:\\%s /forcerestart /qn /l+*vx C:\\%s.log\\\"\"
|
||||||
|
"
|
||||||
|
msi_path msi_path msi_path in
|
||||||
|
Firstboot.add_firstboot_script g inspect.i_root
|
@ -1,240 +0,0 @@
|
|||||||
From bebc18c317a46cc99f50d1f6932c81df4e7da1fb Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Thu, 1 Aug 2024 09:01:47 +0100
|
|
||||||
Subject: [PATCH] convert: More robust qemu-ga installation, change paths
|
|
||||||
|
|
||||||
Add a commit from the common submodule to attempt to make qemu-ga
|
|
||||||
installation more robust on Windows.
|
|
||||||
|
|
||||||
Rename network configuration Powershell script from "v2vnetcf" to
|
|
||||||
"network-configuration". I also dropped the ".ps1" extension as the
|
|
||||||
modified Firstboot.add_firstboot_powershell function now adds this.
|
|
||||||
|
|
||||||
Update the common submodule to get these changes:
|
|
||||||
|
|
||||||
Richard W.M. Jones (3):
|
|
||||||
mlcustomize: Use Start-Process -Wait to run qemu-ga installer
|
|
||||||
mlcustomize: Add Firstboot.firstboot_dir function
|
|
||||||
mlcustomize: Place powershell scripts into <firstboot_dir>\Temp
|
|
||||||
|
|
||||||
(cherry picked from commit c57ec4fd5d4942d2320aec4a6b01977dabb87f83)
|
|
||||||
---
|
|
||||||
common | 2 +-
|
|
||||||
convert/convert_windows.ml | 4 ++--
|
|
||||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
Submodule common 5d1f5b84..d489469f:
|
|
||||||
diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml
|
|
||||||
index 4b9b910b..3bbba714 100644
|
|
||||||
--- a/common/mlcustomize/firstboot.ml
|
|
||||||
+++ b/common/mlcustomize/firstboot.ml
|
|
||||||
@@ -239,7 +239,22 @@ WantedBy=%s
|
|
||||||
end
|
|
||||||
|
|
||||||
module Windows = struct
|
|
||||||
- let rec install_service (g : Guestfs.guestfs) root =
|
|
||||||
+ (* Create and return the firstboot directory. *)
|
|
||||||
+ let create_firstboot_dir (g : Guestfs.guestfs) =
|
|
||||||
+ let rec loop firstboot_dir firstboot_dir_win = function
|
|
||||||
+ | [] -> firstboot_dir, firstboot_dir_win
|
|
||||||
+ | dir :: path ->
|
|
||||||
+ let firstboot_dir =
|
|
||||||
+ if firstboot_dir = "" then "/" ^ dir else firstboot_dir // dir in
|
|
||||||
+ let firstboot_dir_win = firstboot_dir_win ^ "\\" ^ dir in
|
|
||||||
+ let firstboot_dir = g#case_sensitive_path firstboot_dir in
|
|
||||||
+ g#mkdir_p firstboot_dir;
|
|
||||||
+ loop firstboot_dir firstboot_dir_win path
|
|
||||||
+ in
|
|
||||||
+ loop "" "C:" ["Program Files"; "Guestfs"; "Firstboot"]
|
|
||||||
+
|
|
||||||
+ let rec install_service (g : Guestfs.guestfs) root
|
|
||||||
+ firstboot_dir firstboot_dir_win =
|
|
||||||
(* Either rhsrvany.exe or pvvxsvc.exe must exist.
|
|
||||||
*
|
|
||||||
* (Check also that it's not a dangling symlink but a real file).
|
|
||||||
@@ -254,20 +269,7 @@ module Windows = struct
|
|
||||||
error (f_"One of rhsrvany.exe or pvvxsvc.exe is missing in %s. One of them is required in order to install Windows firstboot scripts. You can get one by building rhsrvany (https://github.com/rwmjones/rhsrvany)")
|
|
||||||
(virt_tools_data_dir ()) in
|
|
||||||
|
|
||||||
- (* Create a directory for firstboot files in the guest. *)
|
|
||||||
- let firstboot_dir, firstboot_dir_win =
|
|
||||||
- let rec loop firstboot_dir firstboot_dir_win = function
|
|
||||||
- | [] -> firstboot_dir, firstboot_dir_win
|
|
||||||
- | dir :: path ->
|
|
||||||
- let firstboot_dir =
|
|
||||||
- if firstboot_dir = "" then "/" ^ dir else firstboot_dir // dir in
|
|
||||||
- let firstboot_dir_win = firstboot_dir_win ^ "\\" ^ dir in
|
|
||||||
- let firstboot_dir = g#case_sensitive_path firstboot_dir in
|
|
||||||
- g#mkdir_p firstboot_dir;
|
|
||||||
- loop firstboot_dir firstboot_dir_win path
|
|
||||||
- in
|
|
||||||
- loop "" "C:" ["Program Files"; "Guestfs"; "Firstboot"] in
|
|
||||||
-
|
|
||||||
+ (* Create a directory for firstboot scripts in the guest. *)
|
|
||||||
g#mkdir_p (firstboot_dir // "scripts");
|
|
||||||
|
|
||||||
(* Copy pvvxsvc or rhsrvany to the guest. *)
|
|
||||||
@@ -339,11 +341,25 @@ echo uninstalling firstboot service
|
|
||||||
"PWD", REG_SZ firstboot_dir_win ];
|
|
||||||
] in
|
|
||||||
reg_import reg regedits
|
|
||||||
- );
|
|
||||||
-
|
|
||||||
- firstboot_dir
|
|
||||||
+ )
|
|
||||||
end
|
|
||||||
|
|
||||||
+let firstboot_dir (g : Guestfs.guestfs) root =
|
|
||||||
+ let typ = g#inspect_get_type root in
|
|
||||||
+
|
|
||||||
+ match typ with
|
|
||||||
+ | "linux" ->
|
|
||||||
+ let dir = Linux.firstboot_dir in
|
|
||||||
+ g#mkdir_p dir;
|
|
||||||
+ dir, None
|
|
||||||
+
|
|
||||||
+ | "windows" ->
|
|
||||||
+ let dir, dir_win = Windows.create_firstboot_dir g in
|
|
||||||
+ dir, Some dir_win
|
|
||||||
+
|
|
||||||
+ | _ ->
|
|
||||||
+ error (f_"guest type %s is not supported") typ
|
|
||||||
+
|
|
||||||
let script_count = ref 0
|
|
||||||
|
|
||||||
let add_firstboot_script (g : Guestfs.guestfs) root ?(prio = 5000) name
|
|
||||||
@@ -363,7 +379,8 @@ let add_firstboot_script (g : Guestfs.guestfs) root ?(prio = 5000) name
|
|
||||||
g#chmod 0o755 filename
|
|
||||||
|
|
||||||
| "windows", _ ->
|
|
||||||
- let firstboot_dir = Windows.install_service g root in
|
|
||||||
+ let firstboot_dir, firstboot_dir_win = Windows.create_firstboot_dir g in
|
|
||||||
+ Windows.install_service g root firstboot_dir firstboot_dir_win;
|
|
||||||
let filename = firstboot_dir // "scripts" // filename ^ ".bat" in
|
|
||||||
g#write filename (String.unix2dos content)
|
|
||||||
|
|
||||||
@@ -382,15 +399,18 @@ let add_firstboot_powershell g root ?prio name code =
|
|
||||||
*)
|
|
||||||
assert (g#inspect_get_type root = "windows");
|
|
||||||
|
|
||||||
- let windows_systemroot = g#inspect_get_windows_systemroot root in
|
|
||||||
-
|
|
||||||
- (* Create the temporary directory to put the Powershell file. *)
|
|
||||||
- let tempdir = sprintf "%s/Temp" windows_systemroot in
|
|
||||||
+ (* Place the Powershell script into firstboot_dir/Temp *)
|
|
||||||
+ let firstboot_dir, firstboot_dir_win = Windows.create_firstboot_dir g in
|
|
||||||
+ let tempdir = sprintf "%s/Temp" firstboot_dir in
|
|
||||||
g#mkdir_p tempdir;
|
|
||||||
- let ps_path = sprintf "%s/%s" tempdir name in
|
|
||||||
+
|
|
||||||
+ let ps_path = sprintf "%s/%s.ps1" tempdir name in
|
|
||||||
+ let ps_path_win = sprintf "%s\\Temp\\%s.ps1" firstboot_dir_win name in
|
|
||||||
let code = String.concat "\r\n" code ^ "\r\n" in
|
|
||||||
g#write ps_path code;
|
|
||||||
|
|
||||||
- let fb = sprintf "powershell.exe -ExecutionPolicy ByPass -NoProfile -file %s"
|
|
||||||
- ps_path in
|
|
||||||
+ (* Create a regular firstboot bat that just invokes powershell *)
|
|
||||||
+ let fb =
|
|
||||||
+ sprintf "powershell.exe -ExecutionPolicy ByPass -NoProfile -file \"%s\""
|
|
||||||
+ ps_path_win in
|
|
||||||
add_firstboot_script g root ?prio name fb
|
|
||||||
diff --git a/common/mlcustomize/firstboot.mli b/common/mlcustomize/firstboot.mli
|
|
||||||
index 8231af65..34ff0690 100644
|
|
||||||
--- a/common/mlcustomize/firstboot.mli
|
|
||||||
+++ b/common/mlcustomize/firstboot.mli
|
|
||||||
@@ -16,6 +16,23 @@
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*)
|
|
||||||
|
|
||||||
+val firstboot_dir : Guestfs.guestfs -> string -> string * string option
|
|
||||||
+(** [firstboot_dir g root]
|
|
||||||
+ returns the path of the firstboot directory, creating it in
|
|
||||||
+ the guest if necessary.
|
|
||||||
+
|
|
||||||
+ This returns the name of the directory as a guestfs path, and
|
|
||||||
+ optionally the name as a Windows path (only for Windows guests).
|
|
||||||
+
|
|
||||||
+ For Linux this could be [/usr/lib/virt-sysprep, None]
|
|
||||||
+
|
|
||||||
+ For Windows this could be ["/Program Files/Guestfs/Firstboot",
|
|
||||||
+ Some "C:\Program Files\Guestfs\Firstboot"]
|
|
||||||
+
|
|
||||||
+ Additional files that are used during firstboot can be placed
|
|
||||||
+ in this directory, but be careful not to conflict with files
|
|
||||||
+ and scripts added by the firstboot process itself. *)
|
|
||||||
+
|
|
||||||
val add_firstboot_script : Guestfs.guestfs -> string -> ?prio:int -> string ->
|
|
||||||
string -> unit
|
|
||||||
(** [add_firstboot_script g root prio name content] adds a firstboot
|
|
||||||
diff --git a/common/mlcustomize/inject_virtio_win.ml b/common/mlcustomize/inject_virtio_win.ml
|
|
||||||
index eee93669..b04a3b38 100644
|
|
||||||
--- a/common/mlcustomize/inject_virtio_win.ml
|
|
||||||
+++ b/common/mlcustomize/inject_virtio_win.ml
|
|
||||||
@@ -592,11 +592,11 @@ and configure_qemu_ga t files =
|
|
||||||
add "# Run qemu-ga installers";
|
|
||||||
List.iter (
|
|
||||||
fun msi_path ->
|
|
||||||
- add (sprintf "C:\\%s /norestart /qn /l+*vx C:\\%s.log"
|
|
||||||
+ add (sprintf "Start-Process -Wait -FilePath \"C:\\%s\" -ArgumentList \"/norestart\",\"/qn\",\"/l+*vx\",\"C:\\%s.log\""
|
|
||||||
msi_path msi_path)
|
|
||||||
) files;
|
|
||||||
|
|
||||||
- Firstboot.add_firstboot_powershell t.g t.root "install-qemu-ga.ps1" !script
|
|
||||||
+ Firstboot.add_firstboot_powershell t.g t.root "install-qemu-ga" !script
|
|
||||||
|
|
||||||
and configure_blnsvr t blnsvr =
|
|
||||||
let cmd = sprintf "\
|
|
||||||
diff --git a/common/mldrivers/linux_kernels.ml b/common/mldrivers/linux_kernels.ml
|
|
||||||
index 23ff76a5..e0b6b8a0 100644
|
|
||||||
--- a/common/mldrivers/linux_kernels.ml
|
|
||||||
+++ b/common/mldrivers/linux_kernels.ml
|
|
||||||
@@ -102,7 +102,7 @@ let detect_kernels (g : G.guestfs) root bootloader apps =
|
|
||||||
) apps in
|
|
||||||
if verbose () then (
|
|
||||||
let names = List.map (fun { G.app2_name = name } -> name) kernel_pkgs in
|
|
||||||
- eprintf "candidate kernel packages in this guest: %s%!\n"
|
|
||||||
+ eprintf "info: candidate kernel packages in this guest: %s%!\n"
|
|
||||||
(String.concat " " names)
|
|
||||||
);
|
|
||||||
List.filter_map (
|
|
||||||
@@ -306,7 +306,7 @@ let detect_kernels (g : G.guestfs) root bootloader apps =
|
|
||||||
) kernel_pkgs in
|
|
||||||
|
|
||||||
if verbose () then (
|
|
||||||
- eprintf "installed kernel packages in this guest:\n";
|
|
||||||
+ eprintf "info: installed kernel packages in this guest:\n";
|
|
||||||
List.iter (print_kernel_info stderr "\t") installed_kernels;
|
|
||||||
flush stderr
|
|
||||||
);
|
|
||||||
@@ -343,7 +343,7 @@ let detect_kernels (g : G.guestfs) root bootloader apps =
|
|
||||||
) vmlinuzes in
|
|
||||||
|
|
||||||
if verbose () then (
|
|
||||||
- eprintf "kernels offered by the bootloader in this guest (first in list is default):\n";
|
|
||||||
+ eprintf "info: kernels offered by the bootloader in this guest (first in list is default):\n";
|
|
||||||
List.iter (print_kernel_info stderr "\t") bootloader_kernels;
|
|
||||||
flush stderr
|
|
||||||
);
|
|
||||||
diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml
|
|
||||||
index 34cf341b..2ff60bad 100644
|
|
||||||
--- a/convert/convert_windows.ml
|
|
||||||
+++ b/convert/convert_windows.ml
|
|
||||||
@@ -391,7 +391,7 @@ let convert (g : G.guestfs) _ inspect i_firmware block_driver _ static_ips =
|
|
||||||
%systemroot%\\Sysnative\\PnPutil -i -a \
|
|
||||||
%systemroot%\\Drivers\\Virtio\\*.inf" in
|
|
||||||
|
|
||||||
- (* Set priority higher than that of "v2vnetcf.ps1" firstboot script. *)
|
|
||||||
+ (* Set priority higher than that of "network-configure" firstboot script. *)
|
|
||||||
Firstboot.add_firstboot_script g inspect.i_root ~prio:2000
|
|
||||||
"pnputil install drivers" fb_script;
|
|
||||||
|
|
||||||
@@ -668,7 +668,7 @@ let convert (g : G.guestfs) _ inspect i_firmware block_driver _ static_ips =
|
|
||||||
* Powershell script which runs at boot.
|
|
||||||
*)
|
|
||||||
if static_ips <> [] then (
|
|
||||||
- let psh_filename = "v2vnetcf.ps1" in
|
|
||||||
+ let psh_filename = "network-configure" in
|
|
||||||
let psh = ref [] in
|
|
||||||
let add = List.push_back psh in
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
From b04361528b04dc39368c1d90760e50fad63baa9f Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Thu, 3 Dec 2020 10:14:08 +0000
|
||||||
|
Subject: [PATCH] v2v: Turn pnp_wait.exe warning into a debug message.
|
||||||
|
|
||||||
|
We've used virt-v2v for years in RHEL without pnp_wait and it's never
|
||||||
|
been an issue. We don't need a warning here.
|
||||||
|
|
||||||
|
Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1903960
|
||||||
|
(cherry picked from commit 834bea6931b49dc4b14ebe04fd0e0884290bfb78)
|
||||||
|
---
|
||||||
|
v2v/convert_windows.ml | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
|
||||||
|
index 4d844e2d..33fbd410 100644
|
||||||
|
--- a/v2v/convert_windows.ml
|
||||||
|
+++ b/v2v/convert_windows.ml
|
||||||
|
@@ -267,8 +267,8 @@ let convert (g : G.guestfs) inspect _ output rcaps static_ips =
|
||||||
|
if Sys.file_exists tool_path then
|
||||||
|
configure_wait_pnp tool_path
|
||||||
|
else
|
||||||
|
- warning (f_"%s is missing. Firstboot scripts may conflict with PnP.")
|
||||||
|
- tool_path;
|
||||||
|
+ debug (f_"%s is missing. Firstboot scripts may conflict with PnP.")
|
||||||
|
+ tool_path;
|
||||||
|
|
||||||
|
(* Install RHEV-APT only if appropriate for the output hypervisor. *)
|
||||||
|
if output#install_rhev_apt then (
|
@ -0,0 +1,24 @@
|
|||||||
|
From 6fb69c6239902cd4462b6c28bc82118cbf9643f2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 25 Aug 2020 08:27:42 +0100
|
||||||
|
Subject: [PATCH] docs: UEFI guest conversion to -o openstack is supported
|
||||||
|
(RHBZ#1872100).
|
||||||
|
|
||||||
|
(cherry picked from commit db4e673df51d1235a040dc4a4782268743523e5a)
|
||||||
|
---
|
||||||
|
docs/virt-v2v-support.pod | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/docs/virt-v2v-support.pod b/docs/virt-v2v-support.pod
|
||||||
|
index a5150907..1ffc0f9d 100644
|
||||||
|
--- a/docs/virt-v2v-support.pod
|
||||||
|
+++ b/docs/virt-v2v-support.pod
|
||||||
|
@@ -38,7 +38,7 @@ hypervisor, else you will have to adjust paths in the metadata.
|
||||||
|
|
||||||
|
=item UEFI on OpenStack
|
||||||
|
|
||||||
|
-Not supported.
|
||||||
|
+Supported since virt-v2v E<ge> 1.43.2.
|
||||||
|
|
||||||
|
=item UEFI on oVirt or RHV
|
||||||
|
|
@ -1,46 +0,0 @@
|
|||||||
From 696060ba5e89da4d60a7ee1187c8cfd298d50031 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Mon, 5 Aug 2024 10:08:34 +0100
|
|
||||||
Subject: [PATCH] docs: Add a note about removal of VMware Tools on Windows
|
|
||||||
|
|
||||||
We use VMware's recommended method for removal, but we know from
|
|
||||||
experience that this rarely works. The alternate method being
|
|
||||||
proposed involves making very invasive changes to the Registry and
|
|
||||||
filesystem, which are inappropriate for virt-v2v to do and highly
|
|
||||||
risky. Therefore simply document this, with notes for the virt-v2v
|
|
||||||
user if they want to try the risky method.
|
|
||||||
|
|
||||||
Fixes: https://issues.redhat.com/browse/RHEL-51169
|
|
||||||
Thanks: Yan Vugenfirer
|
|
||||||
Reported-by: Ming Xie
|
|
||||||
(cherry picked from commit c952f310c902e438a8b0b5240a4b486b698bede8)
|
|
||||||
---
|
|
||||||
docs/virt-v2v.pod | 15 +++++++++++++++
|
|
||||||
1 file changed, 15 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
|
|
||||||
index c173563b..6df9d88b 100644
|
|
||||||
--- a/docs/virt-v2v.pod
|
|
||||||
+++ b/docs/virt-v2v.pod
|
|
||||||
@@ -1248,6 +1248,21 @@ B<N.B.> Take care not to interrupt the automatic driver installation
|
|
||||||
process when logging in to the guest for the first time, as this may
|
|
||||||
prevent the guest from subsequently booting correctly.
|
|
||||||
|
|
||||||
+=head3 Removing VMware Tools from Windows guests
|
|
||||||
+
|
|
||||||
+Virt-v2v attempts to remove VMware Tools. For Windows guests this is
|
|
||||||
+supposed to happen during the first boot after conversion.
|
|
||||||
+
|
|
||||||
+We use VMware's recommended uninstallation method as that is the
|
|
||||||
+safest choice. However our experience has shown that this method
|
|
||||||
+usually fails. If so, VMware Tools must be removed by some other
|
|
||||||
+method.
|
|
||||||
+
|
|
||||||
+One possible method is described here:
|
|
||||||
+L<https://gist.github.com/broestls/f872872a00acee2fca02017160840624>
|
|
||||||
+You should carefully check this script since it makes very invasive
|
|
||||||
+changes to the Windows Registry and filesystem.
|
|
||||||
+
|
|
||||||
=head2 Free space for conversion
|
|
||||||
|
|
||||||
=head3 Free space in the guest
|
|
@ -0,0 +1,44 @@
|
|||||||
|
From 8a57af71779e274d31fe7f87a75bc937a59575db Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 27 Apr 2021 16:12:12 +0100
|
||||||
|
Subject: [PATCH] docs: -o openstack: Clarify name of file containing OpenStack
|
||||||
|
auth
|
||||||
|
|
||||||
|
In particular, don't use "stackrc" since you will likely be connecting
|
||||||
|
to the undercloud.
|
||||||
|
|
||||||
|
Thanks: Ming Xie
|
||||||
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1871754
|
||||||
|
(cherry picked from commit 61b4b5cc2f64e7a642ea03681f36829dbe665825)
|
||||||
|
---
|
||||||
|
docs/virt-v2v-output-openstack.pod | 10 ++++++----
|
||||||
|
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/docs/virt-v2v-output-openstack.pod b/docs/virt-v2v-output-openstack.pod
|
||||||
|
index 78623d97..f5a3abad 100644
|
||||||
|
--- a/docs/virt-v2v-output-openstack.pod
|
||||||
|
+++ b/docs/virt-v2v-output-openstack.pod
|
||||||
|
@@ -89,8 +89,8 @@ endpoints. You will need to either set up your C<$OS_*> environment
|
||||||
|
variables or use output options on the virt-v2v command line to
|
||||||
|
authenticate with OpenStack.
|
||||||
|
|
||||||
|
-Normally there is a file called something like C<stackrc>,
|
||||||
|
-C<overcloudrc> etc which you can simply C<source> to set everything up.
|
||||||
|
+Normally there is a file called C<overcloudrc> or C<keystonerc_admin>
|
||||||
|
+which you can simply C<source> to set everything up.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
@@ -179,8 +179,10 @@ To output to OpenStack Glance, use the I<-o glance> option.
|
||||||
|
|
||||||
|
This runs the L<glance(1)> CLI program which must be installed on the
|
||||||
|
virt-v2v conversion host. For authentication to work, you will need
|
||||||
|
-to set C<OS_*> environment variables. In most cases you can do this
|
||||||
|
-by sourcing a file called something like F<keystonerc_admin>.
|
||||||
|
+to set C<OS_*> environment variables.
|
||||||
|
+
|
||||||
|
+Normally there is a file called C<overcloudrc> or C<keystonerc_admin>
|
||||||
|
+which you can simply C<source> to set everything up.
|
||||||
|
|
||||||
|
Virt-v2v adds metadata for the guest to Glance, describing such things
|
||||||
|
as the guest operating system and what drivers it requires. The
|
@ -1,27 +0,0 @@
|
|||||||
From 03249203b25d946358e73d0e418805f293bb43bb Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Mon, 5 Aug 2024 10:18:31 +0100
|
|
||||||
Subject: [PATCH] Update common submodule
|
|
||||||
|
|
||||||
Richard W.M. Jones (1):
|
|
||||||
mlcustomize: Write qemu-ga log file name to log.txt
|
|
||||||
|
|
||||||
(cherry picked from commit 7bc9b115baba6df2969451cd6907e2d7543ef22d)
|
|
||||||
---
|
|
||||||
common | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
Submodule common 04116678..7b84a370:
|
|
||||||
diff --git a/common/mlcustomize/inject_virtio_win.ml b/common/mlcustomize/inject_virtio_win.ml
|
|
||||||
index 2981bff5..afec1e45 100644
|
|
||||||
--- a/common/mlcustomize/inject_virtio_win.ml
|
|
||||||
+++ b/common/mlcustomize/inject_virtio_win.ml
|
|
||||||
@@ -606,6 +606,8 @@ and configure_qemu_ga t tempdir_win files =
|
|
||||||
add "# Run qemu-ga installers";
|
|
||||||
List.iter (
|
|
||||||
fun msi ->
|
|
||||||
+ add (sprintf "Write-Host \"Writing log to %s\\%s.log\""
|
|
||||||
+ tempdir_win msi);
|
|
||||||
(* [`] is an escape char for quotes *)
|
|
||||||
add (sprintf "Start-Process -Wait -FilePath \"%s\\%s\" -ArgumentList \"/norestart\",\"/qn\",\"/l+*vx\",\"`\"%s\\%s.log`\"\""
|
|
||||||
tempdir_win msi tempdir_win msi)
|
|
@ -0,0 +1,149 @@
|
|||||||
|
From 704e86cb3bd4ddc3b7c207967f0413b4637be1f3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 1 Sep 2020 14:44:17 +0100
|
||||||
|
Subject: [PATCH] v2v: Allow output to block devices (RHBZ#1868690).
|
||||||
|
|
||||||
|
We previously implicitly supported writing to block devices instead of
|
||||||
|
local files, but there were several problems:
|
||||||
|
|
||||||
|
* Block devices could be deleted, especially if virt-v2v failed during
|
||||||
|
a conversion.
|
||||||
|
|
||||||
|
* Block devices could be overwritten by a file with the same name,
|
||||||
|
although I believe this is just an observed consequence of the
|
||||||
|
previous point, or at least I was not able to reproduce this until
|
||||||
|
virt-v2v failed for another reason and then I noticed that because
|
||||||
|
the block device was deleted, the next run overwrote it with a file.
|
||||||
|
|
||||||
|
* It was not documented anywhere how to do it.
|
||||||
|
|
||||||
|
This commit makes the small code change needed to allow virt-v2v to
|
||||||
|
write to a block device, only for existing outputs which write to
|
||||||
|
local files (ie. using TargetFile). Also it avoids deleting block
|
||||||
|
devices accidentally on failure.
|
||||||
|
|
||||||
|
Note this commit intentionally does not prevent you from writing qcow2
|
||||||
|
to a block device. RHV uses this so it is a thing that people do.
|
||||||
|
|
||||||
|
(cherry picked from commit 9a5974fa3bc038e5e5dbb9605a6db77d06e7bf77)
|
||||||
|
---
|
||||||
|
docs/virt-v2v.pod | 33 ++++++++++++++++++++++++++++++
|
||||||
|
v2v/v2v.ml | 51 ++++++++++++++++++++++++++++-------------------
|
||||||
|
2 files changed, 63 insertions(+), 21 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
|
||||||
|
index af69d633..50b0bc8e 100644
|
||||||
|
--- a/docs/virt-v2v.pod
|
||||||
|
+++ b/docs/virt-v2v.pod
|
||||||
|
@@ -1378,8 +1378,41 @@ require either a special user and/or for you to source a script that
|
||||||
|
sets authentication environment variables. Consult the Glance
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
+=item Writing to block devices
|
||||||
|
+
|
||||||
|
+This normally requires root. See the next section.
|
||||||
|
+
|
||||||
|
=back
|
||||||
|
|
||||||
|
+=head2 Writing to block devices
|
||||||
|
+
|
||||||
|
+Some output modes write to local files. In general these modes also
|
||||||
|
+let you write to block devices, but before you run virt-v2v you may
|
||||||
|
+have to arrange for symbolic links to the desired block devices in the
|
||||||
|
+output directory.
|
||||||
|
+
|
||||||
|
+For example if using I<-o local -os /dir> then virt-v2v would normally
|
||||||
|
+create files called:
|
||||||
|
+
|
||||||
|
+ /dir/name-sda # first disk
|
||||||
|
+ /dir/name-sdb # second disk
|
||||||
|
+ ...
|
||||||
|
+ /dir/name.xml # metadata
|
||||||
|
+
|
||||||
|
+If you wish the disks to be written to block devices then you would
|
||||||
|
+need to create F</dir/I<name>-sda> (etc) as symlinks to the block
|
||||||
|
+devices:
|
||||||
|
+
|
||||||
|
+ # lvcreate -L 10G -n VolumeForDiskA VG
|
||||||
|
+ # lvcreate -L 6G -n VolumeForDiskB VG
|
||||||
|
+ # ln -sf /dev/VG/VolumeForDiskA /dir/name-sda
|
||||||
|
+ # ln -sf /dev/VG/VolumeForDiskB /dir/name-sdb
|
||||||
|
+
|
||||||
|
+Note that you must precreate the correct number of block devices of
|
||||||
|
+the correct size. Typically I<-of raw> has to be used too, but other
|
||||||
|
+formats such as qcow2 can be useful occasionally so virt-v2v does not
|
||||||
|
+force you to use raw on block devices.
|
||||||
|
+
|
||||||
|
=head2 Minimal XML for -i libvirtxml option
|
||||||
|
|
||||||
|
When using the I<-i libvirtxml> option, you have to supply some
|
||||||
|
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
|
||||||
|
index a58ff433..1f8d0138 100644
|
||||||
|
--- a/v2v/v2v.ml
|
||||||
|
+++ b/v2v/v2v.ml
|
||||||
|
@@ -681,7 +681,10 @@ and copy_targets cmdline targets input output =
|
||||||
|
fun t ->
|
||||||
|
match t.target_file with
|
||||||
|
| TargetURI _ -> ()
|
||||||
|
- | TargetFile s -> try unlink s with _ -> ()
|
||||||
|
+ | TargetFile filename ->
|
||||||
|
+ if not (is_block_device filename) then (
|
||||||
|
+ try unlink filename with _ -> ()
|
||||||
|
+ )
|
||||||
|
) targets
|
||||||
|
)
|
||||||
|
);
|
||||||
|
@@ -711,27 +714,33 @@ and copy_targets cmdline targets input output =
|
||||||
|
|
||||||
|
(match t.target_file with
|
||||||
|
| TargetFile filename ->
|
||||||
|
- (* It turns out that libguestfs's disk creation code is
|
||||||
|
- * considerably more flexible and easier to use than
|
||||||
|
- * qemu-img, so create the disk explicitly using libguestfs
|
||||||
|
- * then pass the 'qemu-img convert -n' option so qemu reuses
|
||||||
|
- * the disk.
|
||||||
|
- *
|
||||||
|
- * Also we allow the output mode to actually create the disk
|
||||||
|
- * image. This lets the output mode set ownership and
|
||||||
|
- * permissions correctly if required.
|
||||||
|
+ (* As a special case, allow output to a block device or
|
||||||
|
+ * symlink to a block device. In this case we don't
|
||||||
|
+ * create/overwrite the block device. (RHBZ#1868690).
|
||||||
|
*)
|
||||||
|
- (* What output preallocation mode should we use? *)
|
||||||
|
- let preallocation =
|
||||||
|
- match t.target_format, cmdline.output_alloc with
|
||||||
|
- | ("raw"|"qcow2"), Sparse -> Some "sparse"
|
||||||
|
- | ("raw"|"qcow2"), Preallocated -> Some "full"
|
||||||
|
- | _ -> None (* ignore -oa flag for other formats *) in
|
||||||
|
- let compat =
|
||||||
|
- match t.target_format with "qcow2" -> Some "1.1" | _ -> None in
|
||||||
|
- output#disk_create filename t.target_format
|
||||||
|
- t.target_overlay.ov_virtual_size
|
||||||
|
- ?preallocation ?compat
|
||||||
|
+ if not (is_block_device filename) then (
|
||||||
|
+ (* It turns out that libguestfs's disk creation code is
|
||||||
|
+ * considerably more flexible and easier to use than
|
||||||
|
+ * qemu-img, so create the disk explicitly using libguestfs
|
||||||
|
+ * then pass the 'qemu-img convert -n' option so qemu reuses
|
||||||
|
+ * the disk.
|
||||||
|
+ *
|
||||||
|
+ * Also we allow the output mode to actually create the disk
|
||||||
|
+ * image. This lets the output mode set ownership and
|
||||||
|
+ * permissions correctly if required.
|
||||||
|
+ *)
|
||||||
|
+ (* What output preallocation mode should we use? *)
|
||||||
|
+ let preallocation =
|
||||||
|
+ match t.target_format, cmdline.output_alloc with
|
||||||
|
+ | ("raw"|"qcow2"), Sparse -> Some "sparse"
|
||||||
|
+ | ("raw"|"qcow2"), Preallocated -> Some "full"
|
||||||
|
+ | _ -> None (* ignore -oa flag for other formats *) in
|
||||||
|
+ let compat =
|
||||||
|
+ match t.target_format with "qcow2" -> Some "1.1" | _ -> None in
|
||||||
|
+ output#disk_create filename t.target_format
|
||||||
|
+ t.target_overlay.ov_virtual_size
|
||||||
|
+ ?preallocation ?compat
|
||||||
|
+ )
|
||||||
|
|
||||||
|
| TargetURI _ ->
|
||||||
|
(* XXX For the moment we assume that qemu URI outputs
|
@ -1,80 +0,0 @@
|
|||||||
From a6b8794cd8b90b7f100964ff8534eb24a1b32d4b Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Thu, 8 Aug 2024 10:40:24 +0100
|
|
||||||
Subject: [PATCH] Pull in a fix to make Windows firstboot more reliable.
|
|
||||||
|
|
||||||
Update the common submodule to get:
|
|
||||||
|
|
||||||
Richard W.M. Jones (2):
|
|
||||||
mlcustomize: Add some comments to firstboot batch file
|
|
||||||
mlcustomize: Reboot Windows between each firstboot script
|
|
||||||
|
|
||||||
Document that Windows may now reboot several times after conversion.
|
|
||||||
|
|
||||||
(cherry picked from commit 50f005f8b7034916588855c15b10a0195bf54b23)
|
|
||||||
---
|
|
||||||
common | 2 +-
|
|
||||||
docs/virt-v2v.pod | 9 ++++++---
|
|
||||||
2 files changed, 7 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
Submodule common 7b84a370..a7883967:
|
|
||||||
diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml
|
|
||||||
index 3bbba714..52e76401 100644
|
|
||||||
--- a/common/mlcustomize/firstboot.ml
|
|
||||||
+++ b/common/mlcustomize/firstboot.ml
|
|
||||||
@@ -278,6 +278,9 @@ module Windows = struct
|
|
||||||
(* Write a firstboot.bat control script which just runs the other
|
|
||||||
* scripts in the directory. Note we need to use CRLF line endings
|
|
||||||
* in this script.
|
|
||||||
+ *
|
|
||||||
+ * XXX It would be better to use powershell here. For some ideas see
|
|
||||||
+ * https://github.com/HCK-CI/HLK-Setup-Scripts/
|
|
||||||
*)
|
|
||||||
let firstboot_script = sprintf "\
|
|
||||||
@echo off
|
|
||||||
@@ -299,6 +302,7 @@ if not exist \"%%scripts_done%%\" (
|
|
||||||
mkdir \"%%scripts_done%%\"
|
|
||||||
)
|
|
||||||
|
|
||||||
+:: Pick the next script to run.
|
|
||||||
for %%%%f in (\"%%scripts%%\"\\*.bat) do (
|
|
||||||
echo running \"%%%%f\"
|
|
||||||
move \"%%%%f\" \"%%scripts_done%%\"
|
|
||||||
@@ -307,8 +311,17 @@ for %%%%f in (\"%%scripts%%\"\\*.bat) do (
|
|
||||||
set elvl=!errorlevel!
|
|
||||||
echo .... exit code !elvl!
|
|
||||||
popd
|
|
||||||
+
|
|
||||||
+ :: Reboot the computer. This is necessary to free any locked
|
|
||||||
+ :: files which may prevent later scripts from running.
|
|
||||||
+ shutdown /r /t 0 /y
|
|
||||||
+
|
|
||||||
+ :: Exit the script (in case shutdown returns before rebooting).
|
|
||||||
+ :: On next boot, the whole firstboot service will be called again.
|
|
||||||
+ exit /b
|
|
||||||
)
|
|
||||||
|
|
||||||
+:: Fallthrough here if there are no scripts.
|
|
||||||
echo uninstalling firstboot service
|
|
||||||
\"%%firstboot%%\\%s\" -s firstboot uninstall
|
|
||||||
" firstboot_dir_win srvany in
|
|
||||||
diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
|
|
||||||
index 6df9d88b..7912c6b1 100644
|
|
||||||
--- a/docs/virt-v2v.pod
|
|
||||||
+++ b/docs/virt-v2v.pod
|
|
||||||
@@ -1244,9 +1244,12 @@ The guest will be bootable after the offline conversion stage, but
|
|
||||||
will not yet have all necessary drivers installed to work correctly.
|
|
||||||
These will be installed automatically the first time the guest boots.
|
|
||||||
|
|
||||||
-B<N.B.> Take care not to interrupt the automatic driver installation
|
|
||||||
-process when logging in to the guest for the first time, as this may
|
|
||||||
-prevent the guest from subsequently booting correctly.
|
|
||||||
+B<N.B.> Windows may reboot 4 or more times the first time after
|
|
||||||
+conversion. This is required to install the required drivers, guest
|
|
||||||
+agents, remove VMware Tools, and configure the network. Take care not
|
|
||||||
+to interrupt the automatic driver installation process when logging in
|
|
||||||
+to the guest for the first time, as this may prevent the guest from
|
|
||||||
+subsequently booting correctly.
|
|
||||||
|
|
||||||
=head3 Removing VMware Tools from Windows guests
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
|||||||
|
From e12604349587b67b3b4c3d0b7b1779999460a93d Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Fri, 19 Jun 2020 13:43:47 +0100
|
||||||
|
Subject: [PATCH] v2v: Disable readahead for VMware curl sources too
|
||||||
|
(RHBZ#1848862).
|
||||||
|
|
||||||
|
This appears to be the cause of timeouts during the conversion step
|
||||||
|
where VMware VCenter server's Tomcat HTTPS server stops responding to
|
||||||
|
requests (or rather, responds only with 503 errors). The server later
|
||||||
|
recovers and in fact because of the retry filter the conversion
|
||||||
|
usually succeeds, but I found that we can avoid the problem by
|
||||||
|
disabling readahead.
|
||||||
|
|
||||||
|
(cherry picked from commit 9f4940068022d4e7abdfea6617b73a2b206f19aa)
|
||||||
|
---
|
||||||
|
v2v/nbdkit_sources.ml | 8 ++++----
|
||||||
|
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/nbdkit_sources.ml b/v2v/nbdkit_sources.ml
|
||||||
|
index f5e91911..7c177e35 100644
|
||||||
|
--- a/v2v/nbdkit_sources.ml
|
||||||
|
+++ b/v2v/nbdkit_sources.ml
|
||||||
|
@@ -99,12 +99,12 @@ let common_create ?bandwidth ?extra_debug ?extra_env password
|
||||||
|
|
||||||
|
(* Adding the readahead filter is always a win for our access
|
||||||
|
* patterns. If it doesn't exist don't worry. However it
|
||||||
|
- * breaks VMware servers (RHBZ#1832805).
|
||||||
|
+ * breaks VMware servers (RHBZ#1832805, RHBZ#1848862).
|
||||||
|
*)
|
||||||
|
let cmd =
|
||||||
|
- if plugin_name <> "vddk" then
|
||||||
|
- Nbdkit.add_filter_if_available cmd "readahead"
|
||||||
|
- else cmd in
|
||||||
|
+ match plugin_name with
|
||||||
|
+ | "vddk" | "curl" -> cmd
|
||||||
|
+ | _ -> Nbdkit.add_filter_if_available cmd "readahead" in
|
||||||
|
|
||||||
|
(* Caching extents speeds up qemu-img, especially its consecutive
|
||||||
|
* block_status requests with req_one=1.
|
@ -1,31 +0,0 @@
|
|||||||
From 8bcdddcaa612feb05c4ae5033bf9440b046ef63e Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Thu, 8 Aug 2024 10:56:16 +0100
|
|
||||||
Subject: [PATCH] docs: Restate position on removal of VMware Tools
|
|
||||||
|
|
||||||
With the "reboot after every step" change made in the previous commit,
|
|
||||||
it seems removal of VMware Tools is now more reliable. Update the
|
|
||||||
notes about this.
|
|
||||||
|
|
||||||
Updates: commit c952f310c902e438a8b0b5240a4b486b698bede8
|
|
||||||
(cherry picked from commit e9c0d63b22bcb4c31cfaac00fc1271713c8bd3b3)
|
|
||||||
---
|
|
||||||
docs/virt-v2v.pod | 5 ++---
|
|
||||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
|
|
||||||
index 7912c6b1..50285cad 100644
|
|
||||||
--- a/docs/virt-v2v.pod
|
|
||||||
+++ b/docs/virt-v2v.pod
|
|
||||||
@@ -1257,9 +1257,8 @@ Virt-v2v attempts to remove VMware Tools. For Windows guests this is
|
|
||||||
supposed to happen during the first boot after conversion.
|
|
||||||
|
|
||||||
We use VMware's recommended uninstallation method as that is the
|
|
||||||
-safest choice. However our experience has shown that this method
|
|
||||||
-usually fails. If so, VMware Tools must be removed by some other
|
|
||||||
-method.
|
|
||||||
+safest choice. If this fails, VMware Tools must be manually removed
|
|
||||||
+by some other method.
|
|
||||||
|
|
||||||
One possible method is described here:
|
|
||||||
L<https://gist.github.com/broestls/f872872a00acee2fca02017160840624>
|
|
@ -1,25 +0,0 @@
|
|||||||
From 919e2fdf65377bc2496a696cb10eac3881324611 Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Tue, 9 Jul 2024 11:30:09 +0100
|
|
||||||
Subject: [PATCH] RHEL: Add warning about virt-v2v-in-place not being supported
|
|
||||||
|
|
||||||
Fixes: https://issues.redhat.com/browse/RHEL-40903
|
|
||||||
(cherry picked from commit 1dec94e52974e45fd3962dcbd51882fde7e9c306)
|
|
||||||
---
|
|
||||||
in-place/in_place.ml | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/in-place/in_place.ml b/in-place/in_place.ml
|
|
||||||
index a61d9795..d55f49a0 100644
|
|
||||||
--- a/in-place/in_place.ml
|
|
||||||
+++ b/in-place/in_place.ml
|
|
||||||
@@ -197,6 +197,9 @@ read the man page virt-v2v-in-place(1).
|
|
||||||
let opthandle = create_standard_options argspec ~anon_fun ~key_opts:true ~machine_readable:true usage_msg in
|
|
||||||
Getopt.parse opthandle.getopt;
|
|
||||||
|
|
||||||
+ warning "virt-v2v-in-place is NOT SUPPORTED for command line use. \
|
|
||||||
+ It is almost always better to use virt-v2v instead of this tool.";
|
|
||||||
+
|
|
||||||
(* Print the version, easier than asking users to tell us. *)
|
|
||||||
debug "%s: %s %s (%s)"
|
|
||||||
prog Config.package_name Config.package_version_full
|
|
@ -1,93 +0,0 @@
|
|||||||
From c36ec998cc50124300ae0b31ef844b193b2db00f Mon Sep 17 00:00:00 2001
|
|
||||||
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
||||||
Date: Tue, 27 Aug 2024 12:36:41 +0100
|
|
||||||
Subject: [PATCH] convert: windows: Online all virtio disks at first boot
|
|
||||||
|
|
||||||
Windows 2022 (and possibly earlier versions back to around 2019) will
|
|
||||||
force offline any non-boot disks which change bus, apparently as a
|
|
||||||
security mitigation. The effect of this is that although the system
|
|
||||||
drive (C:) is present after conversion, other drives may seem to
|
|
||||||
disappear.
|
|
||||||
|
|
||||||
Running a Powershell script to bring all disks online seems risky.
|
|
||||||
The compromise is to bring online only virtio disks at first boot.
|
|
||||||
|
|
||||||
To further reduce risk, we only do this if there are non-system disks
|
|
||||||
(ie. > 1 disks in total), and only if we installed virtio drivers.
|
|
||||||
|
|
||||||
Fixes: https://issues.redhat.com/browse/RHEL-55763
|
|
||||||
Fixes: https://issues.redhat.com/browse/RHEL-55837
|
|
||||||
Related: https://issues.redhat.com/browse/MTV-1299
|
|
||||||
Related: https://bugzilla.redhat.com/show_bug.cgi?id=1662286
|
|
||||||
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
|
|
||||||
Thanks: Martin Necas
|
|
||||||
Acked-by: Martin Necas
|
|
||||||
(cherry picked from commit cb56f6f94dc153051515fc7aa0d9ca646f5e2340)
|
|
||||||
---
|
|
||||||
convert/convert_windows.ml | 39 +++++++++++++++++++++++++++++++++++++-
|
|
||||||
1 file changed, 38 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml
|
|
||||||
index 2ff60bad..28f81e23 100644
|
|
||||||
--- a/convert/convert_windows.ml
|
|
||||||
+++ b/convert/convert_windows.ml
|
|
||||||
@@ -38,7 +38,8 @@ module G = Guestfs
|
|
||||||
* time the Windows VM is booted on KVM.
|
|
||||||
*)
|
|
||||||
|
|
||||||
-let convert (g : G.guestfs) _ inspect i_firmware block_driver _ static_ips =
|
|
||||||
+let convert (g : G.guestfs) source inspect i_firmware
|
|
||||||
+ block_driver _ static_ips =
|
|
||||||
(*----------------------------------------------------------------------*)
|
|
||||||
(* Inspect the Windows guest. *)
|
|
||||||
|
|
||||||
@@ -272,6 +273,8 @@ let convert (g : G.guestfs) _ inspect i_firmware block_driver _ static_ips =
|
|
||||||
Registry.with_hive_write g inspect.i_windows_software_hive
|
|
||||||
update_software_hive;
|
|
||||||
|
|
||||||
+ configure_online_disks block_driver;
|
|
||||||
+
|
|
||||||
configure_network_interfaces net_driver;
|
|
||||||
|
|
||||||
fix_ntfs_heads ();
|
|
||||||
@@ -662,6 +665,40 @@ let convert (g : G.guestfs) _ inspect i_firmware block_driver _ static_ips =
|
|
||||||
warning (f_"could not find registry key \
|
|
||||||
HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion")
|
|
||||||
|
|
||||||
+ and configure_online_disks block_driver =
|
|
||||||
+ (* If there are > 1 disks, run a script which will force Windows
|
|
||||||
+ * to bring them all online. Windows 2022 will offline non-boot disks
|
|
||||||
+ * where the bus changes as some sort of "security" mitigation.
|
|
||||||
+ * https://issues.redhat.com/browse/RHEL-55837
|
|
||||||
+ * https://issues.redhat.com/browse/MTV-1299
|
|
||||||
+ * https://bugzilla.redhat.com/show_bug.cgi?id=1662286
|
|
||||||
+ *)
|
|
||||||
+ let virtio_installed =
|
|
||||||
+ match block_driver with
|
|
||||||
+ | Inject_virtio_win.Virtio_blk | Virtio_SCSI -> true
|
|
||||||
+ | IDE -> false in
|
|
||||||
+ let more_than_one_disk = List.length source.s_disks > 1 in
|
|
||||||
+
|
|
||||||
+ if virtio_installed && more_than_one_disk then (
|
|
||||||
+ let psh_filename = "online-disks" in
|
|
||||||
+ let psh = ref [] in
|
|
||||||
+ let add = List.push_back psh in
|
|
||||||
+
|
|
||||||
+ add "# Uncomment this line for lots of debug output.";
|
|
||||||
+ add "# Set-PSDebug -Trace 1";
|
|
||||||
+ add "";
|
|
||||||
+ add "Write-Host \"Online all virtio disks\"";
|
|
||||||
+ add "";
|
|
||||||
+ add "Get-Disk | Where { $_.FriendlyName -like '*VirtIO*' } | % {";
|
|
||||||
+ add " Write-Host (' - ' + $_.Number + ': ' + $_.FriendlyName + '(' + [math]::Round($_.Size/1GB,2) + 'GB)')";
|
|
||||||
+ add " $_ | Set-Disk -IsOffline $false";
|
|
||||||
+ add " $_ | Set-Disk -IsReadOnly $false";
|
|
||||||
+ add "}";
|
|
||||||
+
|
|
||||||
+ (* Install the Powershell script to run late at firstboot. *)
|
|
||||||
+ Firstboot.add_firstboot_powershell g inspect.i_root psh_filename !psh
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
and configure_network_interfaces net_driver =
|
|
||||||
(* If we were asked to force network interfaces to have particular
|
|
||||||
* static IP addresses then it is done here by installing a
|
|
@ -0,0 +1,27 @@
|
|||||||
|
From 575cb719ceb56d5f1812b6580f3a181bd95f5030 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 27 Apr 2021 17:29:42 +0100
|
||||||
|
Subject: [PATCH] v2v: windows: Allow qxldod.inf as synonym for qxl.inf
|
||||||
|
|
||||||
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1926102
|
||||||
|
Thanks: Xiaodai Wang, Ming Xie
|
||||||
|
(cherry picked from commit 11d1f3cd6878ae7713e589194f97526f744dc090)
|
||||||
|
---
|
||||||
|
v2v/windows_virtio.ml | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml
|
||||||
|
index 4e00cd61..b8256bad 100644
|
||||||
|
--- a/v2v/windows_virtio.ml
|
||||||
|
+++ b/v2v/windows_virtio.ml
|
||||||
|
@@ -155,7 +155,9 @@ let rec install_drivers ((g, _) as reg) inspect rcaps =
|
||||||
|
|
||||||
|
(* Can we install the QXL driver? *)
|
||||||
|
let video : guestcaps_video_type =
|
||||||
|
- let has_qxl = g#exists (driverdir // "qxl.inf") in
|
||||||
|
+ let has_qxl =
|
||||||
|
+ g#exists (driverdir // "qxl.inf") ||
|
||||||
|
+ g#exists (driverdir // "qxldod.inf") in
|
||||||
|
match rcaps.rcaps_video, has_qxl with
|
||||||
|
| Some QXL, false ->
|
||||||
|
error (f_"there is no QXL driver for this version of Windows (%d.%d %s). virt-v2v looks for this driver in %s")
|
@ -0,0 +1,25 @@
|
|||||||
|
From e8d3beabfba4b309296569e84b275724e3cd9709 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 30 Jun 2021 16:18:20 +0100
|
||||||
|
Subject: [PATCH] RHEL 8: docs: Fix version of virt-v2v which added UEFI for
|
||||||
|
OpenStack
|
||||||
|
|
||||||
|
Reported-by: Tingting Zheng
|
||||||
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1872100#c7
|
||||||
|
---
|
||||||
|
docs/virt-v2v-support.pod | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/docs/virt-v2v-support.pod b/docs/virt-v2v-support.pod
|
||||||
|
index 1ffc0f9d..a9bfffab 100644
|
||||||
|
--- a/docs/virt-v2v-support.pod
|
||||||
|
+++ b/docs/virt-v2v-support.pod
|
||||||
|
@@ -38,7 +38,7 @@ hypervisor, else you will have to adjust paths in the metadata.
|
||||||
|
|
||||||
|
=item UEFI on OpenStack
|
||||||
|
|
||||||
|
-Supported since virt-v2v E<ge> 1.43.2.
|
||||||
|
+Supported since virt-v2v E<ge> 1.42.0-7.
|
||||||
|
|
||||||
|
=item UEFI on oVirt or RHV
|
||||||
|
|
@ -0,0 +1,57 @@
|
|||||||
|
From 906e087d6c57d4c1f24ecb60f98a6c98f75881a7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Thu, 20 May 2021 09:10:20 +0100
|
||||||
|
Subject: [PATCH] v2v: Increase Linux minimum root filesystem to 100 MB
|
||||||
|
|
||||||
|
Ming Xie created a RHEL 8.3 guest which required around 70 MB free in
|
||||||
|
order to recreate the initramfs (temporary space used by the pigz
|
||||||
|
step). Increase the minimum space required to 100 MB, the same as for
|
||||||
|
Windows.
|
||||||
|
|
||||||
|
Seealso commit dfcf60c916a986a352938b432231a36558a3bc05.
|
||||||
|
|
||||||
|
Reported-by: Ming Xie
|
||||||
|
Fixes: https://bugzilla.redhat.com/1764569#c16
|
||||||
|
(cherry picked from commit e82ff27c3bea5ce2cc3b7d1ce8d775989fc7e5a5)
|
||||||
|
---
|
||||||
|
docs/virt-v2v.pod | 2 +-
|
||||||
|
v2v/v2v.ml | 12 +++++-------
|
||||||
|
2 files changed, 6 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
|
||||||
|
index 4016c724..4ecce369 100644
|
||||||
|
--- a/docs/virt-v2v.pod
|
||||||
|
+++ b/docs/virt-v2v.pod
|
||||||
|
@@ -1290,7 +1290,7 @@ to perform the conversion. Currently it checks:
|
||||||
|
|
||||||
|
=item Linux root filesystem
|
||||||
|
|
||||||
|
-Minimum free space: 20 MB
|
||||||
|
+Minimum free space: 100 MB
|
||||||
|
|
||||||
|
=item Linux F</boot>
|
||||||
|
|
||||||
|
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
|
||||||
|
index bde51885..8af86687 100644
|
||||||
|
--- a/v2v/v2v.ml
|
||||||
|
+++ b/v2v/v2v.ml
|
||||||
|
@@ -389,14 +389,12 @@ and check_guest_free_space inspect mpstats =
|
||||||
|
* typical size of 20-30MB. Hence:
|
||||||
|
*)
|
||||||
|
| "/boot" | "/" when not has_boot && not is_windows -> 50
|
||||||
|
- (* We may install some packages, and they would usually go
|
||||||
|
- * on the root filesystem.
|
||||||
|
+ (* Both Linux and Windows require installation of files,
|
||||||
|
+ * device drivers and guest agents.
|
||||||
|
+ * https://bugzilla.redhat.com/1949147
|
||||||
|
+ * https://bugzilla.redhat.com/1764569#c16
|
||||||
|
*)
|
||||||
|
- | "/" when not is_windows -> 20
|
||||||
|
- (* Windows requires copying in many device drivers and possibly
|
||||||
|
- * guest agents, so we need more space. (RHBZ#1949147).
|
||||||
|
- *)
|
||||||
|
- | "/" (* when is_windows *) -> 100
|
||||||
|
+ | "/" -> 100
|
||||||
|
(* For everything else, just make sure there is some free space. *)
|
||||||
|
| _ -> 10
|
||||||
|
in
|
@ -0,0 +1,176 @@
|
|||||||
|
From 419aa23f0c6338b01b644094c3af2c024470e9b2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nir Soffer <nsoffer@redhat.com>
|
||||||
|
Date: Sat, 10 Jul 2021 02:35:27 +0300
|
||||||
|
Subject: [PATCH] v2v: rhv-upload-plugin: Fix waiting for finalize
|
||||||
|
|
||||||
|
Waiting for image transfer finalize is complex. In the past we tried to
|
||||||
|
simplify the process by waiting on the disk status, but turns out that
|
||||||
|
due to the way oVirt lock the disk, this is not reliable.
|
||||||
|
|
||||||
|
These is finalize success flow:
|
||||||
|
|
||||||
|
1. User asks to finalize the transfer
|
||||||
|
2. oVirt sets transfer phase to FINALIZING_SUCCESS
|
||||||
|
3. oVirt finalizes the transfer
|
||||||
|
4. oVirt sets disk status to OK
|
||||||
|
5. oVirt unlocks the disk and changes transfer phase to FINISHED_SUCCESS
|
||||||
|
6. oVirt removes the transfer
|
||||||
|
|
||||||
|
In oVirt logs we can see that disk status changes to OK about 3 seconds
|
||||||
|
before the disk is actually unlocked. This is a very old problem that is
|
||||||
|
unlikely to be fixed.
|
||||||
|
|
||||||
|
The only way to wait for transfer completion is to poll the transfer
|
||||||
|
phase, but oVirt makes this hard by removing the transfer shortly after
|
||||||
|
it completes, so we may not be able to get the FINISHED_SUCCESS phase.
|
||||||
|
If the transfer was removed before we got one of the final phases, we
|
||||||
|
need to check the disk status to understand the result of transfer.
|
||||||
|
|
||||||
|
oVirt 4.4.7 made polling transfer phase easier by keeping the transfer
|
||||||
|
after completion, but we need to support older versions so we must have
|
||||||
|
generic code that work with any version.
|
||||||
|
|
||||||
|
To make debugging easier, we log the transfer phase during polling. Here
|
||||||
|
is a typical transfer log when finalizing transfer:
|
||||||
|
|
||||||
|
finalizing transfer 59e545f3-db1f-4a6b-90b1-80ac66572faa
|
||||||
|
transfer 59e545f3-db1f-4a6b-90b1-80ac66572faa is finalizing_success
|
||||||
|
transfer 59e545f3-db1f-4a6b-90b1-80ac66572faa is finalizing_success
|
||||||
|
transfer 59e545f3-db1f-4a6b-90b1-80ac66572faa is finalizing_success
|
||||||
|
transfer 59e545f3-db1f-4a6b-90b1-80ac66572faa is finalizing_success
|
||||||
|
transfer 59e545f3-db1f-4a6b-90b1-80ac66572faa is finished_success
|
||||||
|
transfer 59e545f3-db1f-4a6b-90b1-80ac66572faa finalized in 5.153 seconds
|
||||||
|
|
||||||
|
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
|
||||||
|
Fixes: https://bugzilla.redhat.com/1976024
|
||||||
|
(cherry picked from commit 79702b28329d15a7485801ed7e915d486fcc0cf4)
|
||||||
|
---
|
||||||
|
v2v/rhv-upload-plugin.py | 98 ++++++++++++++++++++++++++++------------
|
||||||
|
1 file changed, 69 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/rhv-upload-plugin.py b/v2v/rhv-upload-plugin.py
|
||||||
|
index 7cd6dea6..61ade1a8 100644
|
||||||
|
--- a/v2v/rhv-upload-plugin.py
|
||||||
|
+++ b/v2v/rhv-upload-plugin.py
|
||||||
|
@@ -601,17 +601,29 @@ def finalize_transfer(connection, transfer, disk_id):
|
||||||
|
"""
|
||||||
|
Finalize a transfer, making the transfer disk available.
|
||||||
|
|
||||||
|
- If finalizing succeeds, transfer's phase will change to FINISHED_SUCCESS
|
||||||
|
- and the transer's disk status will change to OK. On errors, the transfer's
|
||||||
|
- phase will change to FINISHED_FAILURE and the disk status will change to
|
||||||
|
- ILLEGAL and it will be removed. In both cases the transfer entity will be
|
||||||
|
- removed shortly after.
|
||||||
|
+ If finalizing succeeds, the transfer's disk status will change to OK
|
||||||
|
+ and transfer's phase will change to FINISHED_SUCCESS. Unfortunately,
|
||||||
|
+ the disk status is modified before the transfer finishes, and oVirt
|
||||||
|
+ may still hold a lock on the disk at this point.
|
||||||
|
|
||||||
|
- If oVirt fails to finalize the transfer, transfer's phase will change to
|
||||||
|
- PAUSED_SYSTEM. In this case the disk's status will change to ILLEGAL and it
|
||||||
|
- will not be removed.
|
||||||
|
+ The only way to make sure that the disk is unlocked, is to wait
|
||||||
|
+ until the transfer phase switches FINISHED_SUCCESS. Unfortunately
|
||||||
|
+ oVirt makes this hard to use because the transfer is removed shortly
|
||||||
|
+ after switching the phase to the final phase. However if the
|
||||||
|
+ transfer was removed, we can be sure that the disk is not locked,
|
||||||
|
+ since oVirt releases the locks before removing the transfer.
|
||||||
|
|
||||||
|
- For simplicity, we track only disk's status changes.
|
||||||
|
+ On errors, the transfer's phase will change to FINISHED_FAILURE and
|
||||||
|
+ the disk status will change to ILLEGAL and it will be removed. Again
|
||||||
|
+ the transfer will be removed shortly after that.
|
||||||
|
+
|
||||||
|
+ If oVirt fails to finalize the transfer, transfer's phase will
|
||||||
|
+ change to PAUSED_SYSTEM. In this case the disk's status will change
|
||||||
|
+ to ILLEGAL and it will not be removed.
|
||||||
|
+
|
||||||
|
+ oVirt 4.4.7 made waiting for transfer easier by keeping transfers
|
||||||
|
+ after they complete, but we must support older versions so we have
|
||||||
|
+ generic code that work with any version.
|
||||||
|
|
||||||
|
For more info see:
|
||||||
|
- http://ovirt.github.io/ovirt-engine-api-model/4.4/#services/image_transfer
|
||||||
|
@@ -626,34 +638,62 @@ def finalize_transfer(connection, transfer, disk_id):
|
||||||
|
|
||||||
|
transfer_service.finalize()
|
||||||
|
|
||||||
|
- disk_service = (connection.system_service()
|
||||||
|
- .disks_service()
|
||||||
|
- .disk_service(disk_id))
|
||||||
|
-
|
||||||
|
while True:
|
||||||
|
time.sleep(1)
|
||||||
|
try:
|
||||||
|
- disk = disk_service.get()
|
||||||
|
+ transfer = transfer_service.get()
|
||||||
|
except sdk.NotFoundError:
|
||||||
|
- # Disk verification failed and the system removed the disk.
|
||||||
|
- raise RuntimeError(
|
||||||
|
- "transfer %s failed: disk %s was removed"
|
||||||
|
- % (transfer.id, disk_id))
|
||||||
|
+ # Transfer was removed (ovirt < 4.4.7). We need to check the
|
||||||
|
+ # disk status to understand if the transfer was successful.
|
||||||
|
+ # Due to the way oVirt does locking, we know that the disk
|
||||||
|
+ # is unlocked at this point so we can check only once.
|
||||||
|
|
||||||
|
- if disk.status == types.DiskStatus.ILLEGAL:
|
||||||
|
- # Disk verification failed or transfer was paused by the system.
|
||||||
|
- raise RuntimeError(
|
||||||
|
- "transfer %s failed: disk is ILLEGAL" % transfer.id)
|
||||||
|
+ debug("transfer %s was removed, checking disk %s status"
|
||||||
|
+ % (transfer.id, disk_id))
|
||||||
|
+
|
||||||
|
+ disk_service = (connection.system_service()
|
||||||
|
+ .disks_service()
|
||||||
|
+ .disk_service(disk_id))
|
||||||
|
|
||||||
|
- if disk.status == types.DiskStatus.OK:
|
||||||
|
- debug("transfer %s finalized in %.3f seconds"
|
||||||
|
- % (transfer.id, time.time() - start))
|
||||||
|
- break
|
||||||
|
+ try:
|
||||||
|
+ disk = disk_service.get()
|
||||||
|
+ except sdk.NotFoundError:
|
||||||
|
+ raise RuntimeError(
|
||||||
|
+ "transfer %s failed: disk %s was removed"
|
||||||
|
+ % (transfer.id, disk_id))
|
||||||
|
+
|
||||||
|
+ debug("disk %s is %s" % (disk_id, disk.status))
|
||||||
|
+
|
||||||
|
+ if disk.status == types.DiskStatus.OK:
|
||||||
|
+ break
|
||||||
|
|
||||||
|
- if time.time() > start + timeout:
|
||||||
|
raise RuntimeError(
|
||||||
|
- "timed out waiting for transfer %s to finalize"
|
||||||
|
- % transfer.id)
|
||||||
|
+ "transfer %s failed: disk is %s" % (transfer.id, disk.status))
|
||||||
|
+ else:
|
||||||
|
+ # Transfer exists, check if it reached one of the final
|
||||||
|
+ # phases, or we timed out.
|
||||||
|
+
|
||||||
|
+ debug("transfer %s is %s" % (transfer.id, transfer.phase))
|
||||||
|
+
|
||||||
|
+ if transfer.phase == types.ImageTransferPhase.FINISHED_SUCCESS:
|
||||||
|
+ break
|
||||||
|
+
|
||||||
|
+ if transfer.phase == types.ImageTransferPhase.FINISHED_FAILURE:
|
||||||
|
+ raise RuntimeError(
|
||||||
|
+ "transfer %s has failed" % (transfer.id,))
|
||||||
|
+
|
||||||
|
+ if transfer.phase == types.ImageTransferPhase.PAUSED_SYSTEM:
|
||||||
|
+ raise RuntimeError(
|
||||||
|
+ "transfer %s was paused by system" % (transfer.id,))
|
||||||
|
+
|
||||||
|
+ if time.time() > start + timeout:
|
||||||
|
+ raise RuntimeError(
|
||||||
|
+ "timed out waiting for transfer %s to finalize, "
|
||||||
|
+ "transfer is %s"
|
||||||
|
+ % (transfer.id, transfer.phase))
|
||||||
|
+
|
||||||
|
+ debug("transfer %s finalized in %.3f seconds"
|
||||||
|
+ % (transfer.id, time.time() - start))
|
||||||
|
|
||||||
|
|
||||||
|
def transfer_supports_format():
|
@ -0,0 +1,77 @@
|
|||||||
|
From 72f50e52515369ef8decda9493422d6235f5b365 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 18 Aug 2021 11:00:12 +0100
|
||||||
|
Subject: [PATCH] v2v: windows: Do not fix NTFS heads in Windows Vista and
|
||||||
|
later
|
||||||
|
|
||||||
|
Setting/adjusting the number of drive heads in the NTFS header is only
|
||||||
|
necessary for ancient versions of Windows. Modern versions ignore
|
||||||
|
this. In addition this operation broke when we added BitLocker
|
||||||
|
support. Only do this for ancient Windows 2000/XP and skip it for
|
||||||
|
everything else.
|
||||||
|
|
||||||
|
Reported-by: Ming Xie
|
||||||
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1994984
|
||||||
|
(cherry picked from commit 0a394c5c2f802098c9e481b4bacee7821e5dd0ae)
|
||||||
|
---
|
||||||
|
v2v/convert_windows.ml | 44 ++++++++++++++++++++++--------------------
|
||||||
|
1 file changed, 23 insertions(+), 21 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
|
||||||
|
index 33fbd410..13de10cb 100644
|
||||||
|
--- a/v2v/convert_windows.ml
|
||||||
|
+++ b/v2v/convert_windows.ml
|
||||||
|
@@ -730,30 +730,32 @@ if errorlevel 3010 exit /b 0
|
||||||
|
however, as this is specific to Windows 2003 it lists location
|
||||||
|
0x1A as unused.
|
||||||
|
*)
|
||||||
|
- let rootpart = inspect.i_root in
|
||||||
|
+ if inspect.i_major_version < 6 (* is Windows 2000/XP *) then (
|
||||||
|
+ let rootpart = inspect.i_root in
|
||||||
|
|
||||||
|
- (* Ignore if the rootpart is something like /dev/sda. RHBZ#1276540. *)
|
||||||
|
- if not (g#is_whole_device rootpart) then (
|
||||||
|
- (* Check that the root device contains NTFS magic. *)
|
||||||
|
- let magic = g#pread_device rootpart 8 3L in
|
||||||
|
- if magic = "NTFS " then (
|
||||||
|
- (* Get the size of the whole disk containing the root partition. *)
|
||||||
|
- let rootdev = g#part_to_dev rootpart in (* eg. /dev/sda *)
|
||||||
|
- let size = g#blockdev_getsize64 rootdev in
|
||||||
|
+ (* Ignore if the rootpart is something like /dev/sda. RHBZ#1276540. *)
|
||||||
|
+ if not (g#is_whole_device rootpart) then (
|
||||||
|
+ (* Check that the root device contains NTFS magic. *)
|
||||||
|
+ let magic = g#pread_device rootpart 8 3L in
|
||||||
|
+ if magic = "NTFS " then (
|
||||||
|
+ (* Get the size of the whole disk containing the root partition. *)
|
||||||
|
+ let rootdev = g#part_to_dev rootpart in (* eg. /dev/sda *)
|
||||||
|
+ let size = g#blockdev_getsize64 rootdev in
|
||||||
|
|
||||||
|
- let heads = (* refer to the table above *)
|
||||||
|
- if size < 2114445312L then 0x40
|
||||||
|
- else if size < 4228374780L then 0x80
|
||||||
|
- else 0xff in
|
||||||
|
+ let heads = (* refer to the table above *)
|
||||||
|
+ if size < 2114445312L then 0x40
|
||||||
|
+ else if size < 4228374780L then 0x80
|
||||||
|
+ else 0xff in
|
||||||
|
|
||||||
|
- (* Update NTFS's idea of the number of heads. This is an
|
||||||
|
- * unsigned 16 bit little-endian integer, offset 0x1a from the
|
||||||
|
- * beginning of the partition.
|
||||||
|
- *)
|
||||||
|
- let b = Bytes.create 2 in
|
||||||
|
- Bytes.unsafe_set b 0 (Char.chr heads);
|
||||||
|
- Bytes.unsafe_set b 1 '\000';
|
||||||
|
- ignore (g#pwrite_device rootpart (Bytes.to_string b) 0x1a_L)
|
||||||
|
+ (* Update NTFS's idea of the number of heads. This is an
|
||||||
|
+ * unsigned 16 bit little-endian integer, offset 0x1a from the
|
||||||
|
+ * beginning of the partition.
|
||||||
|
+ *)
|
||||||
|
+ let b = Bytes.create 2 in
|
||||||
|
+ Bytes.unsafe_set b 0 (Char.chr heads);
|
||||||
|
+ Bytes.unsafe_set b 1 '\000';
|
||||||
|
+ ignore (g#pwrite_device rootpart (Bytes.to_string b) 0x1a_L)
|
||||||
|
+ )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,272 @@
|
|||||||
|
From cc9a507e2372b5b6408964f9c31a3bd526aabf7c Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 23 Sep 2020 09:56:27 +0100
|
||||||
|
Subject: [PATCH] v2v: vcenter: Implement cookie scripts.
|
||||||
|
|
||||||
|
For conversions[*] which take longer than 30 minutes it can happen
|
||||||
|
that the HTTPS authorization cookie that we fetched from VMware when
|
||||||
|
we first connect expires. This can especially happen when there are
|
||||||
|
multiple disks, because we may not "touch" (therefore autorenew) the
|
||||||
|
second disk while we are doing the long conversion. This can lead to
|
||||||
|
failures, some of which are silent: again if there are multiple disks,
|
||||||
|
fstrim of the non-system disks can fail silently resulting in the copy
|
||||||
|
step taking a very long time.
|
||||||
|
|
||||||
|
The solution to this is to use the new nbdkit-curl-plugin
|
||||||
|
cookie-script feature which allows nbdkit to automatically renew the
|
||||||
|
cookie as required.
|
||||||
|
|
||||||
|
During the conversion or copying steps you may see the cookie being
|
||||||
|
autorenewed:
|
||||||
|
|
||||||
|
nbdkit: curl[3]: debug: curl: running cookie-script
|
||||||
|
nbdkit: curl[3]: debug: cookie-script returned cookies
|
||||||
|
|
||||||
|
This removes the ?user and ?password parameters from Nbdkit_sources.-
|
||||||
|
create_curl because they are no longer needed after this change.
|
||||||
|
Note for future: if we need to add them back, we must prevent both
|
||||||
|
user and cookie_script parameters from being used at the same time,
|
||||||
|
because simply having the user parameter will try basic
|
||||||
|
authentication, overriding the cookie, which will either fail (no
|
||||||
|
password) or run very slowly.
|
||||||
|
|
||||||
|
This change requires nbdkit >= 1.22 which is checked at runtime only
|
||||||
|
if this feature is used.
|
||||||
|
|
||||||
|
[*] Note here I mean conversions not the total runtime of virt-v2v.
|
||||||
|
When doing the copy the cookie does not expire because it is
|
||||||
|
continuously auto-renewed by VMware as we continuously access the disk
|
||||||
|
(this works differently from systems like Docker where the cookie is
|
||||||
|
only valid from the absolute time when it is first created). This
|
||||||
|
change also implements the cookie-script logic for copying.
|
||||||
|
|
||||||
|
(cherry picked from commit 2b9a11743b74ef3716b66a7e395108a26382e331)
|
||||||
|
|
||||||
|
Notes for cherry pick to RHEL 8.6:
|
||||||
|
|
||||||
|
We no longer need the session_cookie field inside virt-v2v since it is
|
||||||
|
replaced by the cookie script. However it is still needed by
|
||||||
|
virt-v2v-copy-to-local. (This utility is removed upstream and in RHEL
|
||||||
|
9, but we need to keep it around at least for appearances in RHEL 8.)
|
||||||
|
|
||||||
|
So when cherry picking I had to retain the get_session_cookie function
|
||||||
|
which required also keeping fetch_headers_and_url as it was (not
|
||||||
|
dropping headers).
|
||||||
|
---
|
||||||
|
v2v/nbdkit_sources.ml | 34 ++++++++++++-----
|
||||||
|
v2v/nbdkit_sources.mli | 5 +--
|
||||||
|
v2v/parse_libvirt_xml.ml | 3 +-
|
||||||
|
v2v/vCenter.ml | 80 +++++++++++++++++++++++++++++++---------
|
||||||
|
4 files changed, 90 insertions(+), 32 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/nbdkit_sources.ml b/v2v/nbdkit_sources.ml
|
||||||
|
index 7c177e35..16af5f5c 100644
|
||||||
|
--- a/v2v/nbdkit_sources.ml
|
||||||
|
+++ b/v2v/nbdkit_sources.ml
|
||||||
|
@@ -26,7 +26,6 @@ open Types
|
||||||
|
open Utils
|
||||||
|
|
||||||
|
let nbdkit_min_version = (1, 12, 0)
|
||||||
|
-let nbdkit_min_version_string = "1.12.0"
|
||||||
|
|
||||||
|
type password =
|
||||||
|
| NoPassword (* no password option at all *)
|
||||||
|
@@ -38,11 +37,16 @@ let error_unless_nbdkit_working () =
|
||||||
|
if not (Nbdkit.is_installed ()) then
|
||||||
|
error (f_"nbdkit is not installed or not working")
|
||||||
|
|
||||||
|
-let error_unless_nbdkit_min_version config =
|
||||||
|
+let error_unless_nbdkit_version_ge config min_version =
|
||||||
|
let version = Nbdkit.version config in
|
||||||
|
- if version < nbdkit_min_version then
|
||||||
|
- error (f_"nbdkit is too old. nbdkit >= %s is required.")
|
||||||
|
- nbdkit_min_version_string
|
||||||
|
+ if version < min_version then (
|
||||||
|
+ let min_major, min_minor, min_release = min_version in
|
||||||
|
+ error (f_"nbdkit is too old. nbdkit >= %d.%d.%d is required.")
|
||||||
|
+ min_major min_minor min_release
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+let error_unless_nbdkit_min_version config =
|
||||||
|
+ error_unless_nbdkit_version_ge config nbdkit_min_version
|
||||||
|
|
||||||
|
let error_unless_nbdkit_plugin_exists plugin =
|
||||||
|
if not (Nbdkit.probe_plugin plugin) then
|
||||||
|
@@ -297,23 +301,35 @@ let create_ssh ?bandwidth ~password ?port ~server ?user path =
|
||||||
|
common_create ?bandwidth password "ssh" (get_args ())
|
||||||
|
|
||||||
|
(* Create an nbdkit module specialized for reading from Curl sources. *)
|
||||||
|
-let create_curl ?bandwidth ?cookie ~password ?(sslverify=true) ?user url =
|
||||||
|
+let create_curl ?bandwidth ?cookie_script ?cookie_script_renew
|
||||||
|
+ ?(sslverify=true) url =
|
||||||
|
error_unless_nbdkit_plugin_exists "curl";
|
||||||
|
|
||||||
|
+ (* The cookie* parameters require nbdkit 1.22, so check that early. *)
|
||||||
|
+ if cookie_script <> None || cookie_script_renew <> None then (
|
||||||
|
+ let config = Nbdkit.config () in
|
||||||
|
+ error_unless_nbdkit_version_ge config (1, 22, 0)
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
let add_arg, get_args =
|
||||||
|
let args = ref [] in
|
||||||
|
let add_arg (k, v) = List.push_front (k, v) args in
|
||||||
|
let get_args () = List.rev !args in
|
||||||
|
add_arg, get_args in
|
||||||
|
|
||||||
|
- Option.may (fun s -> add_arg ("user", s)) user;
|
||||||
|
(* https://bugzilla.redhat.com/show_bug.cgi?id=1146007#c10 *)
|
||||||
|
add_arg ("timeout", "2000");
|
||||||
|
- Option.may (fun s -> add_arg ("cookie", s)) cookie;
|
||||||
|
+ Option.may (fun s -> add_arg ("cookie-script", s)) cookie_script;
|
||||||
|
+ Option.may (fun i -> add_arg ("cookie-script-renew", string_of_int i))
|
||||||
|
+ cookie_script_renew;
|
||||||
|
if not sslverify then add_arg ("sslverify", "false");
|
||||||
|
add_arg ("url", url);
|
||||||
|
|
||||||
|
- common_create ?bandwidth password "curl" (get_args ())
|
||||||
|
+ (* For lots of extra debugging, uncomment one or both lines. *)
|
||||||
|
+ (*add_arg ("--debug", "curl.verbose=1");*)
|
||||||
|
+ (*add_arg ("--debug", "curl.scripts=1");*)
|
||||||
|
+
|
||||||
|
+ common_create ?bandwidth NoPassword "curl" (get_args ())
|
||||||
|
|
||||||
|
let run cmd =
|
||||||
|
let sock, _ = Nbdkit.run_unix cmd in
|
||||||
|
diff --git a/v2v/nbdkit_sources.mli b/v2v/nbdkit_sources.mli
|
||||||
|
index 94810ea6..922642df 100644
|
||||||
|
--- a/v2v/nbdkit_sources.mli
|
||||||
|
+++ b/v2v/nbdkit_sources.mli
|
||||||
|
@@ -60,10 +60,9 @@ val create_ssh : ?bandwidth:Types.bandwidth ->
|
||||||
|
Note this doesn't run nbdkit yet, it just creates the object. *)
|
||||||
|
|
||||||
|
val create_curl : ?bandwidth:Types.bandwidth ->
|
||||||
|
- ?cookie:string ->
|
||||||
|
- password:password ->
|
||||||
|
+ ?cookie_script:string ->
|
||||||
|
+ ?cookie_script_renew:int ->
|
||||||
|
?sslverify:bool ->
|
||||||
|
- ?user:string ->
|
||||||
|
string -> Nbdkit.cmd
|
||||||
|
(** Create a nbdkit object using the Curl plugin. The required
|
||||||
|
string parameter is the URL.
|
||||||
|
diff --git a/v2v/parse_libvirt_xml.ml b/v2v/parse_libvirt_xml.ml
|
||||||
|
index 0b136839..fffc5a24 100644
|
||||||
|
--- a/v2v/parse_libvirt_xml.ml
|
||||||
|
+++ b/v2v/parse_libvirt_xml.ml
|
||||||
|
@@ -319,8 +319,7 @@ let parse_libvirt_xml ?bandwidth ?conn xml =
|
||||||
|
| _, Some port ->
|
||||||
|
invalid_arg "invalid port number in libvirt XML" in
|
||||||
|
sprintf "%s://%s%s%s" driver host port (uri_quote path) in
|
||||||
|
- let nbdkit = Nbdkit_sources.create_curl ?bandwidth ~password:NoPassword
|
||||||
|
- url in
|
||||||
|
+ let nbdkit = Nbdkit_sources.create_curl ?bandwidth url in
|
||||||
|
let qemu_uri = Nbdkit_sources.run nbdkit in
|
||||||
|
add_disk qemu_uri format controller P_dont_rewrite
|
||||||
|
| Some protocol, _, _ ->
|
||||||
|
diff --git a/v2v/vCenter.ml b/v2v/vCenter.ml
|
||||||
|
index 4c128b0c..ead03364 100644
|
||||||
|
--- a/v2v/vCenter.ml
|
||||||
|
+++ b/v2v/vCenter.ml
|
||||||
|
@@ -46,11 +46,12 @@ let rec map_source ?bandwidth ?password_file dcPath uri server path =
|
||||||
|
(* XXX only works if the query string is not URI-quoted *)
|
||||||
|
String.find query "no_verify=1" = -1 in
|
||||||
|
|
||||||
|
+ (* Check the URL exists and authentication info is correct. *)
|
||||||
|
let https_url =
|
||||||
|
let https_url = get_https_url dcPath uri server path in
|
||||||
|
- (* Check the URL exists. *)
|
||||||
|
- let status, _, _ =
|
||||||
|
+ let status, _, dump_response =
|
||||||
|
fetch_headers_from_url password_file uri sslverify https_url in
|
||||||
|
+
|
||||||
|
(* If a disk is actually a snapshot image it will have '-00000n'
|
||||||
|
* appended to its name, e.g.:
|
||||||
|
* [yellow:storage1] RHEL4-X/RHEL4-X-000003.vmdk
|
||||||
|
@@ -58,28 +59,71 @@ let rec map_source ?bandwidth ?password_file dcPath uri server path =
|
||||||
|
* a 404 and the vmdk name looks like it might be a snapshot, try
|
||||||
|
* again without the snapshot suffix.
|
||||||
|
*)
|
||||||
|
- if status = "404" && PCRE.matches snapshot_re path then (
|
||||||
|
- let path = PCRE.sub 1 ^ PCRE.sub 2 in
|
||||||
|
- get_https_url dcPath uri server path
|
||||||
|
- )
|
||||||
|
- else
|
||||||
|
- (* Note that other non-200 status errors will be handled
|
||||||
|
- * in get_session_cookie below, so we don't have to worry
|
||||||
|
- * about them here.
|
||||||
|
- *)
|
||||||
|
- https_url in
|
||||||
|
+ let https_url, status, dump_response =
|
||||||
|
+ if status = "404" && PCRE.matches snapshot_re path then (
|
||||||
|
+ let path = PCRE.sub 1 ^ PCRE.sub 2 in
|
||||||
|
+ let https_url = get_https_url dcPath uri server path in
|
||||||
|
+ let status, _, dump_response =
|
||||||
|
+ fetch_headers_from_url password_file uri sslverify https_url in
|
||||||
|
+ https_url, status, dump_response
|
||||||
|
+ )
|
||||||
|
+ else (https_url, status, dump_response) in
|
||||||
|
+
|
||||||
|
+ if status = "401" then (
|
||||||
|
+ dump_response stderr;
|
||||||
|
+ if uri.uri_user <> None then
|
||||||
|
+ error (f_"vcenter: incorrect username or password")
|
||||||
|
+ else
|
||||||
|
+ error (f_"vcenter: incorrect username or password. You might need to specify the username in the URI like this: [vpx|esx|..]://USERNAME@[etc]")
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ if status = "404" then (
|
||||||
|
+ dump_response stderr;
|
||||||
|
+ error (f_"vcenter: URL not found: %s") https_url
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ if status <> "200" then (
|
||||||
|
+ dump_response stderr;
|
||||||
|
+ error (f_"vcenter: invalid response from server: %s") status
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ https_url in
|
||||||
|
|
||||||
|
let session_cookie =
|
||||||
|
get_session_cookie password_file uri sslverify https_url in
|
||||||
|
|
||||||
|
- let password =
|
||||||
|
- match password_file with
|
||||||
|
- | None -> Nbdkit_sources.NoPassword
|
||||||
|
- | Some password_file -> Nbdkit_sources.PasswordFile password_file in
|
||||||
|
+ (* Write a cookie script to retrieve the session cookie.
|
||||||
|
+ * See nbdkit-curl-plugin(1) "Example: VMware ESXi cookies"
|
||||||
|
+ *)
|
||||||
|
+ let cookie_script, chan =
|
||||||
|
+ Filename.open_temp_file ~perms:0o700 "v2vcs" ".sh" in
|
||||||
|
+ unlink_on_exit cookie_script;
|
||||||
|
+ let fpf fs = fprintf chan fs in
|
||||||
|
+ fpf "#!/bin/sh -\n";
|
||||||
|
+ fpf "\n";
|
||||||
|
+ fpf "curl --head -s";
|
||||||
|
+ if not sslverify then fpf " --insecure";
|
||||||
|
+ (match uri.uri_user, password_file with
|
||||||
|
+ | None, None -> ()
|
||||||
|
+ | Some user, None -> fpf " -u %s" (quote user)
|
||||||
|
+ | None, Some password_file ->
|
||||||
|
+ fpf " -u \"$LOGNAME\":\"$(cat %s)\"" (quote password_file)
|
||||||
|
+ | Some user, Some password_file ->
|
||||||
|
+ fpf " -u %s:\"$(cat %s)\"" (quote user) (quote password_file)
|
||||||
|
+ );
|
||||||
|
+ fpf " %s" (quote https_url);
|
||||||
|
+ fpf " |\n";
|
||||||
|
+ fpf "\tsed -ne %s\n" (quote "{ s/^Set-Cookie: \\([^;]*\\);.*/\\1/ip }");
|
||||||
|
+ close_out chan;
|
||||||
|
+
|
||||||
|
+ (* VMware authentication expires after 30 minutes so we must renew
|
||||||
|
+ * after < 30 minutes.
|
||||||
|
+ *)
|
||||||
|
+ let cookie_script_renew = 25*60 in
|
||||||
|
|
||||||
|
let nbdkit =
|
||||||
|
- Nbdkit_sources.create_curl ?bandwidth ?cookie:session_cookie ~password ~sslverify
|
||||||
|
- ?user:uri.uri_user https_url in
|
||||||
|
+ Nbdkit_sources.create_curl ?bandwidth ~cookie_script ~cookie_script_renew
|
||||||
|
+ ~sslverify https_url in
|
||||||
|
let qemu_uri = Nbdkit_sources.run nbdkit in
|
||||||
|
|
||||||
|
(* Return the struct. *)
|
@ -0,0 +1,41 @@
|
|||||||
|
From 84cb43440a2ad143eb7474a028b1b1549cb8c0f1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Fri, 12 Nov 2021 08:47:55 +0000
|
||||||
|
Subject: [PATCH] convert/convert_windows.ml: Handle date formats with dots
|
||||||
|
instead of /
|
||||||
|
|
||||||
|
If the ShortDatePattern is yy.M.d (as can happen for US locale) we may
|
||||||
|
not always reformat the date for schtasks.exe correctly. For
|
||||||
|
explanation and testing see:
|
||||||
|
|
||||||
|
https://bugzilla.redhat.com/show_bug.cgi?id=1895323#c46 (- #c50)
|
||||||
|
|
||||||
|
Thanks: Xiaodai Wang for suggesting the fix and testing it
|
||||||
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1895323
|
||||||
|
(cherry picked from commit d9dc6c42ae64ba92993dbd9477f003ba73fcfa2f)
|
||||||
|
---
|
||||||
|
v2v/convert_windows.ml | 7 +++++--
|
||||||
|
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml
|
||||||
|
index 13de10cb..6c7440aa 100644
|
||||||
|
--- a/v2v/convert_windows.ml
|
||||||
|
+++ b/v2v/convert_windows.ml
|
||||||
|
@@ -422,12 +422,15 @@ popd
|
||||||
|
and configure_qemu_ga files =
|
||||||
|
List.iter (
|
||||||
|
fun msi_path ->
|
||||||
|
- (* Windows is a trashfire. https://stackoverflow.com/a/18730884 *)
|
||||||
|
+ (* Windows is a trashfire.
|
||||||
|
+ * https://stackoverflow.com/a/18730884
|
||||||
|
+ * https://bugzilla.redhat.com/show_bug.cgi?id=1895323
|
||||||
|
+ *)
|
||||||
|
let fb_script = sprintf "\
|
||||||
|
echo Removing any previously scheduled qemu-ga installation
|
||||||
|
schtasks.exe /Delete /TN Firstboot-qemu-ga /F
|
||||||
|
echo Scheduling delayed installation of qemu-ga from %s
|
||||||
|
-powershell.exe -command \"$d = (get-date).AddSeconds(120); $FormatHack = ($([System.Globalization.DateTimeFormatInfo]::CurrentInfo.ShortDatePattern) -replace 'M+/', 'MM/') -replace 'd+/', 'dd/'; schtasks.exe /Create /SC ONCE /ST $d.ToString('HH:mm') /SD $d.ToString($FormatHack) /RU SYSTEM /TN Firstboot-qemu-ga /TR \\\"C:\\%s /forcerestart /qn /l+*vx C:\\%s.log\\\"\"
|
||||||
|
+powershell.exe -command \"$d = (get-date).AddSeconds(120); $FormatHack = (($([System.Globalization.DateTimeFormatInfo]::CurrentInfo.ShortDatePattern) -replace 'y+', 'yyyy') -replace 'M+', 'MM') -replace 'd+', 'dd'; schtasks.exe /Create /SC ONCE /ST $d.ToString('HH:mm') /SD $d.ToString($FormatHack) /RU SYSTEM /TN Firstboot-qemu-ga /TR \\\"C:\\%s /forcerestart /qn /l+*vx C:\\%s.log\\\"\"
|
||||||
|
"
|
||||||
|
msi_path msi_path msi_path in
|
||||||
|
Firstboot.add_firstboot_script g inspect.i_root
|
@ -0,0 +1,41 @@
|
|||||||
|
From 992af0707ad54d39ec707da6daa6c4ca7c3fc69a Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 24 Nov 2021 11:23:38 +0000
|
||||||
|
Subject: [PATCH] v2v: Cope with libvirt vpx/esx driver which does not set
|
||||||
|
format
|
||||||
|
|
||||||
|
See discussion in this bug:
|
||||||
|
https://bugzilla.redhat.com/show_bug.cgi?id=2026199
|
||||||
|
|
||||||
|
Fixes: commit 40cfe6da0861ca6360f670e254c71ed923a0402f
|
||||||
|
(cherry picked from commit 59dc3293a9b4fdf11da8571c50e3e5badbb511c2)
|
||||||
|
---
|
||||||
|
v2v/parse_libvirt_xml.ml | 8 ++++++--
|
||||||
|
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/parse_libvirt_xml.ml b/v2v/parse_libvirt_xml.ml
|
||||||
|
index 27e08135..e65fbf4a 100644
|
||||||
|
--- a/v2v/parse_libvirt_xml.ml
|
||||||
|
+++ b/v2v/parse_libvirt_xml.ml
|
||||||
|
@@ -273,7 +273,11 @@ let parse_libvirt_xml ?bandwidth ?conn xml =
|
||||||
|
| Some "aio" -> "raw" (* Xen wierdness *)
|
||||||
|
| Some format -> format
|
||||||
|
| None ->
|
||||||
|
- error (f_"<disk><driver type=\"format\"> attribute is missing from the libvirt XML") in
|
||||||
|
+ (* Some libvirt drivers don't set the format. Typically
|
||||||
|
+ * this is the vpx/esx driver (see RHBZ#2026199). We
|
||||||
|
+ * can assume "raw", as it will be overwritten later.
|
||||||
|
+ *)
|
||||||
|
+ "raw" in
|
||||||
|
|
||||||
|
(* The <disk type='...'> attribute may be 'block', 'file',
|
||||||
|
* 'network' or 'volume'. We ignore any other types.
|
||||||
|
@@ -344,7 +348,7 @@ let parse_libvirt_xml ?bandwidth ?conn xml =
|
||||||
|
match xpath_string "/volume/target/format/@type" with
|
||||||
|
| Some format -> format
|
||||||
|
| None ->
|
||||||
|
- error (f_"<volume><target>.<format type=\"format\"> attribute is missing from the libvirt XML of volume %s") vol in
|
||||||
|
+ error (f_"<volume><target><format type=\"format\"> attribute is missing from the libvirt XML of volume %s") vol in
|
||||||
|
|
||||||
|
(match xpath_string "/volume/@type" with
|
||||||
|
| None | Some "file" ->
|
@ -0,0 +1,179 @@
|
|||||||
|
From 8036ab4bc8f37030fcaceda14678cb14dbbed547 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= <tgolembi@redhat.com>
|
||||||
|
Date: Wed, 20 Apr 2022 17:14:26 +0200
|
||||||
|
Subject: [PATCH] -o rhv-upload: wait for VM creation task
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
oVirt API call for VM creation finishes before the VM is actually
|
||||||
|
created. Entities may be still locked after virt-v2v terminates and if
|
||||||
|
user tries to perform (scripted) actions after virt-v2v those operations
|
||||||
|
may fail. To prevent this it is useful to monitor the task and wait for
|
||||||
|
the completion. This will also help to prevent some corner case
|
||||||
|
scenarios (that would be difficult to debug) when the VM creation job
|
||||||
|
fails after virt-v2v already termintates with success.
|
||||||
|
|
||||||
|
Thanks: Nir Soffer
|
||||||
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1985827
|
||||||
|
Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com>
|
||||||
|
Reviewed-by: Arik Hadas <ahadas@redhat.com>
|
||||||
|
Reviewed-by: Nir Soffer <nsoffer@redhat.com>
|
||||||
|
(cherry picked from commit 291edb363e841e1c555954a070def671a651cfab)
|
||||||
|
---
|
||||||
|
.../ovirtsdk4/__init__.py | 10 +++-
|
||||||
|
.../ovirtsdk4/types.py | 19 +++++++
|
||||||
|
v2v/rhv-upload-createvm.py | 57 ++++++++++++++++++-
|
||||||
|
3 files changed, 84 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py
|
||||||
|
index abb7050c..ba0649cb 100644
|
||||||
|
--- a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py
|
||||||
|
+++ b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py
|
||||||
|
@@ -63,6 +63,9 @@ class SystemService(object):
|
||||||
|
def disks_service(self):
|
||||||
|
return DisksService()
|
||||||
|
|
||||||
|
+ def jobs_service(self):
|
||||||
|
+ return JobsService()
|
||||||
|
+
|
||||||
|
def image_transfers_service(self):
|
||||||
|
return ImageTransfersService()
|
||||||
|
|
||||||
|
@@ -108,6 +111,11 @@ class DisksService(object):
|
||||||
|
return DiskService(disk_id)
|
||||||
|
|
||||||
|
|
||||||
|
+class JobsService(object):
|
||||||
|
+ def list(self, search=None):
|
||||||
|
+ return [types.Job()]
|
||||||
|
+
|
||||||
|
+
|
||||||
|
class ImageTransferService(object):
|
||||||
|
def __init__(self):
|
||||||
|
self._finalized = False
|
||||||
|
@@ -139,7 +147,7 @@ class StorageDomainsService(object):
|
||||||
|
|
||||||
|
|
||||||
|
class VmsService(object):
|
||||||
|
- def add(self, vm):
|
||||||
|
+ def add(self, vm, query=None):
|
||||||
|
return vm
|
||||||
|
|
||||||
|
def list(self, search=None):
|
||||||
|
diff --git a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py
|
||||||
|
index 732887aa..8e734756 100644
|
||||||
|
--- a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py
|
||||||
|
+++ b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py
|
||||||
|
@@ -138,6 +138,25 @@ class Initialization(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
+class JobStatus(Enum):
|
||||||
|
+ ABORTED = "aborted"
|
||||||
|
+ FAILED = "failed"
|
||||||
|
+ FINISHED = "finished"
|
||||||
|
+ STARTED = "started"
|
||||||
|
+ UNKNOWN = "unknown"
|
||||||
|
+
|
||||||
|
+ def __init__(self, image):
|
||||||
|
+ self._image = image
|
||||||
|
+
|
||||||
|
+ def __str__(self):
|
||||||
|
+ return self._image
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class Job(object):
|
||||||
|
+ description = "Fake job"
|
||||||
|
+ status = JobStatus.FINISHED
|
||||||
|
+
|
||||||
|
+
|
||||||
|
class StorageDomain(object):
|
||||||
|
def __init__(self, name=None):
|
||||||
|
pass
|
||||||
|
diff --git a/v2v/rhv-upload-createvm.py b/v2v/rhv-upload-createvm.py
|
||||||
|
index 50bb7e34..8887c52b 100644
|
||||||
|
--- a/v2v/rhv-upload-createvm.py
|
||||||
|
+++ b/v2v/rhv-upload-createvm.py
|
||||||
|
@@ -19,12 +19,54 @@
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
+import time
|
||||||
|
+import uuid
|
||||||
|
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
import ovirtsdk4 as sdk
|
||||||
|
import ovirtsdk4.types as types
|
||||||
|
|
||||||
|
+
|
||||||
|
+def debug(s):
|
||||||
|
+ if params['verbose']:
|
||||||
|
+ print(s, file=sys.stderr)
|
||||||
|
+ sys.stderr.flush()
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def jobs_completed(system_service, correlation_id):
|
||||||
|
+ jobs_service = system_service.jobs_service()
|
||||||
|
+
|
||||||
|
+ try:
|
||||||
|
+ jobs = jobs_service.list(
|
||||||
|
+ search="correlation_id=%s" % correlation_id)
|
||||||
|
+ except sdk.Error as e:
|
||||||
|
+ debug(
|
||||||
|
+ "Error searching for jobs with correlation id %s: %s" %
|
||||||
|
+ (correlation_id, e))
|
||||||
|
+ # We don't know, assume that jobs did not complete yet.
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+ # STARTED is the only "in progress" status, anything else means the job
|
||||||
|
+ # has already terminated.
|
||||||
|
+ if all(job.status != types.JobStatus.STARTED for job in jobs):
|
||||||
|
+ failed_jobs = [(job.description, str(job.status))
|
||||||
|
+ for job in jobs
|
||||||
|
+ if job.status != types.JobStatus.FINISHED]
|
||||||
|
+ if failed_jobs:
|
||||||
|
+ raise RuntimeError(
|
||||||
|
+ "Failed to create a VM! Failed jobs: %r" % failed_jobs)
|
||||||
|
+ return True
|
||||||
|
+ else:
|
||||||
|
+ running_jobs = [(job.description, str(job.status)) for job in jobs]
|
||||||
|
+ debug("Some jobs with correlation id %s are running: %s" %
|
||||||
|
+ (correlation_id, running_jobs))
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+# Seconds to wait for the VM import job to complete in oVirt.
|
||||||
|
+timeout = 3 * 60
|
||||||
|
+
|
||||||
|
# Parameters are passed in via a JSON doc from the OCaml code.
|
||||||
|
# Because this Python code ships embedded inside virt-v2v there
|
||||||
|
# is no formal API here.
|
||||||
|
@@ -67,6 +109,7 @@ system_service = connection.system_service()
|
||||||
|
cluster = system_service.clusters_service().cluster_service(params['rhv_cluster_uuid'])
|
||||||
|
cluster = cluster.get()
|
||||||
|
|
||||||
|
+correlation_id = str(uuid.uuid4())
|
||||||
|
vms_service = system_service.vms_service()
|
||||||
|
vm = vms_service.add(
|
||||||
|
types.Vm(
|
||||||
|
@@ -77,5 +120,17 @@ vm = vms_service.add(
|
||||||
|
data=ovf,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
- )
|
||||||
|
+ ),
|
||||||
|
+ query={'correlation_id': correlation_id},
|
||||||
|
)
|
||||||
|
+
|
||||||
|
+# Wait for the import job to finish.
|
||||||
|
+endt = time.monotonic() + timeout
|
||||||
|
+while True:
|
||||||
|
+ time.sleep(10)
|
||||||
|
+ if jobs_completed(system_service, correlation_id):
|
||||||
|
+ break
|
||||||
|
+ if time.monotonic() > endt:
|
||||||
|
+ raise RuntimeError(
|
||||||
|
+ "Timed out waiting for VM creation!"
|
||||||
|
+ " Jobs still running for correlation id %s" % correlation_id)
|
@ -0,0 +1,93 @@
|
|||||||
|
From 7748be2af952898c9c38d02e9a539c71cbfbb56b Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 25 May 2021 10:13:00 +0100
|
||||||
|
Subject: [PATCH] tests: Add test of -i ova from a directory.
|
||||||
|
|
||||||
|
This was not tested previously.
|
||||||
|
|
||||||
|
(cherry picked from commit a00ce662cb33c33706a013ff98ff89244cd14667)
|
||||||
|
---
|
||||||
|
tests/Makefile.am | 2 ++
|
||||||
|
tests/test-v2v-i-ova-directory.sh | 53 +++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 55 insertions(+)
|
||||||
|
create mode 100755 tests/test-v2v-i-ova-directory.sh
|
||||||
|
|
||||||
|
diff --git a/tests/Makefile.am b/tests/Makefile.am
|
||||||
|
index eee4e1af..e4b907fe 100644
|
||||||
|
--- a/tests/Makefile.am
|
||||||
|
+++ b/tests/Makefile.am
|
||||||
|
@@ -58,6 +58,7 @@ TESTS = \
|
||||||
|
test-v2v-copy-to-local.sh \
|
||||||
|
test-v2v-i-ova-bad-sha1.sh \
|
||||||
|
test-v2v-i-ova-bad-sha256.sh \
|
||||||
|
+ test-v2v-i-ova-directory.sh \
|
||||||
|
test-v2v-i-ova-formats.sh \
|
||||||
|
test-v2v-i-ova-good-checksums.sh \
|
||||||
|
test-v2v-i-ova-gz.sh \
|
||||||
|
@@ -185,6 +186,7 @@ EXTRA_DIST += \
|
||||||
|
test-v2v-i-ova-bad-sha1.sh \
|
||||||
|
test-v2v-i-ova-bad-sha256.sh \
|
||||||
|
test-v2v-i-ova-checksums.ovf \
|
||||||
|
+ test-v2v-i-ova-directory.sh \
|
||||||
|
test-v2v-i-ova-formats.expected \
|
||||||
|
test-v2v-i-ova-formats.ovf \
|
||||||
|
test-v2v-i-ova-formats.sh \
|
||||||
|
diff --git a/tests/test-v2v-i-ova-directory.sh b/tests/test-v2v-i-ova-directory.sh
|
||||||
|
new file mode 100755
|
||||||
|
index 00000000..7c593139
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/test-v2v-i-ova-directory.sh
|
||||||
|
@@ -0,0 +1,53 @@
|
||||||
|
+#!/bin/bash -
|
||||||
|
+# libguestfs virt-v2v test script
|
||||||
|
+# Copyright (C) 2014-2021 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 -i ova option with a directory.
|
||||||
|
+
|
||||||
|
+set -e
|
||||||
|
+
|
||||||
|
+$TEST_FUNCTIONS
|
||||||
|
+skip_if_skipped
|
||||||
|
+skip_if_backend uml
|
||||||
|
+skip_unless_phony_guest windows.img
|
||||||
|
+
|
||||||
|
+skip_unless_libvirt_minimum_version 3 1 0
|
||||||
|
+
|
||||||
|
+export VIRT_TOOLS_DATA_DIR="$top_srcdir/test-data/fake-virt-tools"
|
||||||
|
+export VIRTIO_WIN="$top_srcdir/test-data/fake-virtio-win"
|
||||||
|
+
|
||||||
|
+d=test-v2v-i-ova-directory.d
|
||||||
|
+rm -rf $d
|
||||||
|
+mkdir $d
|
||||||
|
+
|
||||||
|
+vmdk=test-ova.vmdk
|
||||||
|
+ovf=test-v2v-i-ova.ovf
|
||||||
|
+mf=test-ova.mf
|
||||||
|
+
|
||||||
|
+qemu-img convert $top_builddir/test-data/phony-guests/windows.img \
|
||||||
|
+ -O vmdk $d/$vmdk
|
||||||
|
+cp "$srcdir/$ovf" $d/$ovf
|
||||||
|
+sha1=`do_sha1 $d/$ovf`
|
||||||
|
+echo "SHA1($ovf)= $sha1" > $d/$mf
|
||||||
|
+sha256=`do_sha256 $d/$vmdk`
|
||||||
|
+echo "SHA256($vmdk)= $sha256" >> $d/$mf
|
||||||
|
+
|
||||||
|
+$VG virt-v2v --debug-gc \
|
||||||
|
+ -i ova $d \
|
||||||
|
+ -o null
|
||||||
|
+
|
||||||
|
+rm -rf $d
|
@ -0,0 +1,63 @@
|
|||||||
|
From 9e52e90cf8d570516d4098584c263c9d8b76c447 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Tue, 25 May 2021 10:27:53 +0100
|
||||||
|
Subject: [PATCH] v2v: -i ova: Fix parsing if OVA directory name has a trailing
|
||||||
|
"/"
|
||||||
|
|
||||||
|
If you use an OVA directory with a trailing "/" in the name, virt-v2v
|
||||||
|
would fail with:
|
||||||
|
|
||||||
|
virt-v2v: error: internal error: assertion failed at parse_ova.ml, line 273, char 15
|
||||||
|
|
||||||
|
The fix for this is to knock off the trailing "/" if present.
|
||||||
|
|
||||||
|
Reported-by: Xiaodai Wang
|
||||||
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1964324
|
||||||
|
(cherry picked from commit f8428f5eaaff6dedc54a40138f760298a7a3a965)
|
||||||
|
---
|
||||||
|
v2v/parse_ova.ml | 18 +++++++++++++++++-
|
||||||
|
1 file changed, 17 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/parse_ova.ml b/v2v/parse_ova.ml
|
||||||
|
index 568ac5fa..fc413d2a 100644
|
||||||
|
--- a/v2v/parse_ova.ml
|
||||||
|
+++ b/v2v/parse_ova.ml
|
||||||
|
@@ -57,6 +57,13 @@ and ova_type =
|
||||||
|
*)
|
||||||
|
| TarOptimized of string (* tarball *)
|
||||||
|
|
||||||
|
+let string_of_t { orig_ova; top_dir; ova_type } =
|
||||||
|
+ sprintf "orig_ova = %s, top_dir = %s, ova_type = %s"
|
||||||
|
+ orig_ova top_dir
|
||||||
|
+ (match ova_type with
|
||||||
|
+ | Directory -> "Directory"
|
||||||
|
+ | TarOptimized tarball -> "TarOptimized " ^ tarball)
|
||||||
|
+
|
||||||
|
type file_ref =
|
||||||
|
| LocalFile of string
|
||||||
|
| TarFile of string * string
|
||||||
|
@@ -122,6 +129,13 @@ let rec parse_ova ova =
|
||||||
|
(* Exploded path must be absolute (RHBZ#1155121). *)
|
||||||
|
let top_dir = absolute_path top_dir in
|
||||||
|
|
||||||
|
+ (* top_dir must not end with / except if it == "/" (which is
|
||||||
|
+ * likely not what you want). (RHBZ#1964324)
|
||||||
|
+ *)
|
||||||
|
+ let top_dir =
|
||||||
|
+ if top_dir = "/" || not (String.is_suffix top_dir "/") then top_dir
|
||||||
|
+ else String.sub top_dir 0 (String.length top_dir - 1) in
|
||||||
|
+
|
||||||
|
(* If virt-v2v is running as root, and the backend is libvirt, then
|
||||||
|
* we have to chmod the directory to 0755 and files to 0644
|
||||||
|
* so it is readable by qemu.qemu. This is libvirt bug RHBZ#890291.
|
||||||
|
@@ -136,7 +150,9 @@ let rec parse_ova ova =
|
||||||
|
ignore (run_command cmd)
|
||||||
|
);
|
||||||
|
|
||||||
|
- { orig_ova = ova; top_dir; ova_type }
|
||||||
|
+ let ova = { orig_ova = ova; top_dir; ova_type } in
|
||||||
|
+ debug "ova: %s" (string_of_t ova);
|
||||||
|
+ ova
|
||||||
|
|
||||||
|
(* Return true if [libvirt] supports ["json:"] pseudo-URLs and accepts the
|
||||||
|
* ["raw"] driver. Function also returns true if [libvirt] backend is not
|
@ -0,0 +1,95 @@
|
|||||||
|
From 87e5404d20ec54d16d22a7bb8f06ea91076c91f7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Wed, 25 May 2022 16:47:04 +0100
|
||||||
|
Subject: [PATCH] convert: If listing RPM applications fails, rebuild DB and
|
||||||
|
retry
|
||||||
|
|
||||||
|
In libguestfs before commit 488245ed6c ("daemon: rpm: Check return
|
||||||
|
values from librpm calls") we didn't bother to check the return values
|
||||||
|
from any librpm calls. In some cases where the RPM database is
|
||||||
|
faulty, this caused us to return a zero-length array of applications
|
||||||
|
(but no error indication). Libguestfs has subsequently been fixed so
|
||||||
|
now it returns an error if the RPM database is corrupt.
|
||||||
|
|
||||||
|
This commit changes virt-v2v behaviour so that if either
|
||||||
|
guestfs_inspect_list_applications2 returns a zero-length list (ie. old
|
||||||
|
libguestfs) or it throws an error (new libguestfs) then we attempt to
|
||||||
|
rebuild the RPM database and retry the operation. Rebuilding the
|
||||||
|
database can recover from some but not all RPM DB corruption.
|
||||||
|
|
||||||
|
See-also: https://bugzilla.redhat.com/show_bug.cgi?id=2089623#c12
|
||||||
|
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2089623
|
||||||
|
Reported-by: Xiaodai Wang
|
||||||
|
Reported-by: Ming Xie
|
||||||
|
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
|
||||||
|
(cherry picked from commit 31bf5db25bcfd8a9f5a48cc0523abae28861de9a)
|
||||||
|
---
|
||||||
|
v2v/inspect_source.ml | 34 ++++++++++++++++++++++++++++++++--
|
||||||
|
1 file changed, 32 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/v2v/inspect_source.ml b/v2v/inspect_source.ml
|
||||||
|
index b8a3c8ad..554fde1d 100644
|
||||||
|
--- a/v2v/inspect_source.ml
|
||||||
|
+++ b/v2v/inspect_source.ml
|
||||||
|
@@ -34,6 +34,7 @@ let rec inspect_source root_choice g =
|
||||||
|
reject_if_not_installed_image g root;
|
||||||
|
|
||||||
|
let typ = g#inspect_get_type root in
|
||||||
|
+ let package_format = g#inspect_get_package_format root in
|
||||||
|
|
||||||
|
(* Mount up the filesystems. *)
|
||||||
|
let mps = g#inspect_get_mountpoints root in
|
||||||
|
@@ -71,7 +72,7 @@ let rec inspect_source root_choice g =
|
||||||
|
) mps;
|
||||||
|
|
||||||
|
(* Get list of applications/packages installed. *)
|
||||||
|
- let apps = g#inspect_list_applications2 root in
|
||||||
|
+ let apps = list_applications g root package_format in
|
||||||
|
let apps = Array.to_list apps in
|
||||||
|
|
||||||
|
(* A map of app2_name -> application2, for easier lookups. Note
|
||||||
|
@@ -106,7 +107,7 @@ let rec inspect_source root_choice g =
|
||||||
|
i_arch = g#inspect_get_arch root;
|
||||||
|
i_major_version = g#inspect_get_major_version root;
|
||||||
|
i_minor_version = g#inspect_get_minor_version root;
|
||||||
|
- i_package_format = g#inspect_get_package_format root;
|
||||||
|
+ i_package_format = package_format;
|
||||||
|
i_package_management = g#inspect_get_package_management root;
|
||||||
|
i_product_name = g#inspect_get_product_name root;
|
||||||
|
i_product_variant = g#inspect_get_product_variant root;
|
||||||
|
@@ -186,6 +187,35 @@ and reject_if_not_installed_image g root =
|
||||||
|
if fmt <> "installed" then
|
||||||
|
error (f_"libguestfs thinks this is not an installed operating system (it might be, for example, an installer disk or live CD). If this is wrong, it is probably a bug in libguestfs. root=%s fmt=%s") root fmt
|
||||||
|
|
||||||
|
+(* Wrapper around g#inspect_list_applications2 which, for RPM
|
||||||
|
+ * guests, on failure tries to rebuild the RPM database before
|
||||||
|
+ * repeating the operation.
|
||||||
|
+ *)
|
||||||
|
+and list_applications g root = function
|
||||||
|
+ | "rpm" ->
|
||||||
|
+ (* RPM guest.
|
||||||
|
+ *
|
||||||
|
+ * In libguestfs before commit 488245ed6c ("daemon: rpm: Check
|
||||||
|
+ * return values from librpm calls"), a corrupt RPM database
|
||||||
|
+ * would return an empty array here with no exception. Hence
|
||||||
|
+ * the check below which turns empty array => exception. In
|
||||||
|
+ * libguestfs after that commit, inspect_list_applications2
|
||||||
|
+ * will raise an exception if it detects a corrupt RPM database.
|
||||||
|
+ *)
|
||||||
|
+ (try
|
||||||
|
+ let apps = g#inspect_list_applications2 root in
|
||||||
|
+ if apps = [||] then raise (G.Error "no applications returned");
|
||||||
|
+ apps
|
||||||
|
+ with G.Error msg ->
|
||||||
|
+ debug "%s" msg;
|
||||||
|
+ debug "rebuilding RPM database and retrying ...";
|
||||||
|
+ ignore (g#sh "rpmdb --rebuilddb");
|
||||||
|
+ g#inspect_list_applications2 root
|
||||||
|
+ )
|
||||||
|
+ | _ ->
|
||||||
|
+ (* Non-RPM guest, just do it. *)
|
||||||
|
+ g#inspect_list_applications2 root
|
||||||
|
+
|
||||||
|
(* See if this guest could use UEFI to boot. It should use GPT and
|
||||||
|
* it should have an EFI System Partition (ESP).
|
||||||
|
*
|
@ -0,0 +1,50 @@
|
|||||||
|
From 5852b85eaa174dfb87ce7a03b9f70e2bffac4ca4 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Laszlo Ersek <lersek@redhat.com>
|
||||||
|
Date: Wed, 29 Jun 2022 15:44:27 +0200
|
||||||
|
Subject: [PATCH] update common submodule for CVE-2022-2211 fix
|
||||||
|
|
||||||
|
$ git shortlog 9e990f3e4530..35467027f657
|
||||||
|
|
||||||
|
Laszlo Ersek (1):
|
||||||
|
options: fix buffer overflow in get_keys() [CVE-2022-2211]
|
||||||
|
|
||||||
|
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
|
||||||
|
(cherry picked from commit 795d5dfcef77fc54fec4d237bda28571454a6d4e)
|
||||||
|
---
|
||||||
|
common | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
Submodule common be09523d..1174b443:
|
||||||
|
diff --git a/common/options/keys.c b/common/options/keys.c
|
||||||
|
index 798315c2..d27a7123 100644
|
||||||
|
--- a/common/options/keys.c
|
||||||
|
+++ b/common/options/keys.c
|
||||||
|
@@ -128,17 +128,23 @@ read_first_line_from_file (const char *filename)
|
||||||
|
char **
|
||||||
|
get_keys (struct key_store *ks, const char *device, const char *uuid)
|
||||||
|
{
|
||||||
|
- size_t i, j, len;
|
||||||
|
+ size_t i, j, nmemb;
|
||||||
|
char **r;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
/* We know the returned list must have at least one element and not
|
||||||
|
* more than ks->nr_keys.
|
||||||
|
*/
|
||||||
|
- len = 1;
|
||||||
|
- if (ks)
|
||||||
|
- len = MIN (1, ks->nr_keys);
|
||||||
|
- r = calloc (len+1, sizeof (char *));
|
||||||
|
+ nmemb = 1;
|
||||||
|
+ if (ks && ks->nr_keys > nmemb)
|
||||||
|
+ nmemb = ks->nr_keys;
|
||||||
|
+
|
||||||
|
+ /* make room for the terminating NULL */
|
||||||
|
+ if (nmemb == (size_t)-1)
|
||||||
|
+ error (EXIT_FAILURE, 0, _("size_t overflow"));
|
||||||
|
+ nmemb++;
|
||||||
|
+
|
||||||
|
+ r = calloc (nmemb, sizeof (char *));
|
||||||
|
if (r == NULL)
|
||||||
|
error (EXIT_FAILURE, errno, "calloc");
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
From 217a74ad09bad781ee9efd5599f4323bdf9e3cff Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Mon, 3 Apr 2023 09:41:37 +0100
|
||||||
|
Subject: [PATCH] RHEL 8: If setfiles fails fall back to autorelabel
|
||||||
|
|
||||||
|
SFDC case 03473932, RHEL 8 only.
|
||||||
|
|
||||||
|
See discussion in private email thread "Customer case requiring our
|
||||||
|
assistance" in 2023.
|
||||||
|
---
|
||||||
|
common | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
Submodule common 1174b443..c4841a70:
|
||||||
|
diff --git a/common/mlcustomize/SELinux_relabel.ml b/common/mlcustomize/SELinux_relabel.ml
|
||||||
|
index 5ecf7bd7..f0630db1 100644
|
||||||
|
--- a/common/mlcustomize/SELinux_relabel.ml
|
||||||
|
+++ b/common/mlcustomize/SELinux_relabel.ml
|
||||||
|
@@ -35,11 +35,12 @@ let rec relabel (g : G.guestfs) =
|
||||||
|
use_setfiles g;
|
||||||
|
(* That worked, so we don't need to autorelabel. *)
|
||||||
|
g#rm_f "/.autorelabel"
|
||||||
|
- with Failure _ ->
|
||||||
|
+ with Failure _
|
||||||
|
(* This is the fallback in case something in the setfiles
|
||||||
|
* method didn't work. That includes the case where a non-SELinux
|
||||||
|
* host is processing an SELinux guest, and other things.
|
||||||
|
*)
|
||||||
|
+ | Guestfs.Error _ -> (* this is for SFDC case 03473932 in RHEL 8 only *)
|
||||||
|
g#touch "/.autorelabel"
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,18 @@
|
|||||||
|
Source Offer
|
||||||
|
|
||||||
|
A complete machine-readable copy of the source code corresponding to
|
||||||
|
portions of the accompanying package is available upon request. This
|
||||||
|
offer is valid to anyone in receipt of this information and shall
|
||||||
|
expire three years following the date of the final distribution of
|
||||||
|
this package by Red Hat, Inc.
|
||||||
|
|
||||||
|
To obtain such source code, send a check or money order in the amount
|
||||||
|
of US$10.00 to:
|
||||||
|
|
||||||
|
General Counsel
|
||||||
|
Red Hat, Inc.
|
||||||
|
100 East Davie Street
|
||||||
|
Raleigh, NC 27601 USA
|
||||||
|
|
||||||
|
Please specify the name, version and release of the package for which
|
||||||
|
you are requesting corresponding source code.
|
@ -0,0 +1,17 @@
|
|||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iQJFBAABCAAvFiEE93dPsa0HSn6Mh2fqkXOPc+G3aKAFAl6YQ9QRHHJpY2hAYW5u
|
||||||
|
ZXhpYS5vcmcACgkQkXOPc+G3aKAgTBAAiT/ojN14i0NRzpuGSb7I9oupzclVqic8
|
||||||
|
c5NIXH8TGYLY9tVMYSsr+uyWu8Qk2lsqV6knXeqbBKot/682v2AlYn6ZpG+cl8tm
|
||||||
|
ZKjVSwMwLVdAvV5zTaggEO/Xs8WbtSkmTk184s62804qlc+mv0ngFTGZomKjH4o1
|
||||||
|
tHgJnegeR/lppeBnIuhAC/hWo6SyhPul8UnDg3rnByWOX7Qs3p4lY9y5hHv2pQfK
|
||||||
|
ezXLDYBBAtQ3oe3p8jh3SCe7GLxxX8oxDCn6l8K7AK4czRMLJ/iykS/iE+E1bazM
|
||||||
|
V7rUItPfK3MhrWThlekn4u5tOclCDKbK75Hgkb2qjeK9Ctad80boXnNEnIv0UWFr
|
||||||
|
SaqCKmJrOtohn2oR/aUmTXm2u09jy+nQTRhvqy/2TNTdExCa1A6n7r0EcEJQMQPX
|
||||||
|
DK34+cbn3J+/+BA9kyH2a2/pTwJBaCk4PCXyrxWAkHyLUt9HZwmtPXUeBhq/iMIf
|
||||||
|
QZSo/LgXTTNEpsFx5K3xuvy6Ps/IaImeI8xdU2wl252/HN4wY3roZOBNflbTCF2m
|
||||||
|
aXFXf6bReZmO9HJg5674zCYkB0N8nSPMaHmv7EWyK7sEMKCUuYnWMiEBHtIZA+dW
|
||||||
|
Qp3IdoODkjciwVzJL2E7RhA2GNvwnkay4WYqb0mjAPVktVTnhla7S1hSD8SM6Fs7
|
||||||
|
sVAPrKAFidk=
|
||||||
|
=l3OH
|
||||||
|
-----END PGP SIGNATURE-----
|
@ -1,17 +0,0 @@
|
|||||||
-----BEGIN PGP SIGNATURE-----
|
|
||||||
|
|
||||||
iQJFBAABCAAvFiEE93dPsa0HSn6Mh2fqkXOPc+G3aKAFAmWW5kYRHHJpY2hAYW5u
|
|
||||||
ZXhpYS5vcmcACgkQkXOPc+G3aKBddxAAvM08lmWH0IlpLwKX06TwnVERt8fXD++p
|
|
||||||
bjRrfj2mOoayoN/B1oE61laCdZgCzPtN6MC/aW94LITaGJWHi7YYqdgdRgL1NqeC
|
|
||||||
n0tu8t14XsCT1xTIOa1ndb018+a5ppIcOnmGAj4naM5uA50rgRwChdSOTP/H10+J
|
|
||||||
93M2rvvak8aVdeWEhnMJyqWG2mFJ0YselJ+cMu66XFBkK7wg4UwCzzJ4Blqb1Igd
|
|
||||||
W/wctLDLqPVAxI85P/2p2dt+N4vzOnT/jr+dFxXOJg99E6iwa3qPCdzGHmszjhyC
|
|
||||||
uNhq/pWMt5tSk34IwYduyk1b9mlx9dCQsyREwrVomsdZD+XrUZHhrGrlcVJDfT07
|
|
||||||
2DCkVnGAoH0DRmz3t69KJS9U1JgzkaTDNaezkLlIZ7VZOdaC5nK74efnN0yinBkJ
|
|
||||||
9GhmR0qbk4/QVKeNWSftu4Rd9OUtRSaEMH0kO/S42vl3fW59u+ZGMEz26Ar4x/q7
|
|
||||||
jLx3vKfduJbpvberc3kQ2p9jQbUjlyFOTtnTAf84ckyIkvEMwpEhlyfchctPji/K
|
|
||||||
IaJ4Yd0KnKiLg/GH9Eon79cadAV2hzvYb2FZYI1RcrbRH+nZvGLgSbvHobqESERT
|
|
||||||
hBBXrAhaazRdxbOVqwMV9d+lq4llzUJJMOVCsK/PLnigrl5OCLQNQ2IVBbPv8WFD
|
|
||||||
VMg/9mGiUj0=
|
|
||||||
=lbFv
|
|
||||||
-----END PGP SIGNATURE-----
|
|
Loading…
Reference in new issue