virt-v2v/0012-RHEL-Remove-o-rhv-o-rhv-upload-and-o-vdsm-modes.patch
Richard W.M. Jones c9793c46cd New upstream development version 2.5.5
resolves: RHEL-46869

(cherry picked from commit 4ca1dbba4b7aba2b9eb4fc93a7a740922524e958)
2024-07-11 12:52:08 +01:00

4673 lines
161 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From e22fef42bd60cfe68320dcebc8c6520cff401e17 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 8 Jul 2024 09:56:54 +0100
Subject: [PATCH] RHEL: Remove -o rhv, -o rhv-upload and -o vdsm modes
Fixes: https://issues.redhat.com/browse/RHEL-36712
---
docs/Makefile.am | 14 -
docs/virt-v2v-output-rhv.pod | 232 --------
docs/virt-v2v.pod | 208 +------
output/Makefile.am | 54 +-
output/output_rhv.ml | 317 -----------
output/output_rhv.mli | 21 -
output/output_rhv_upload.ml | 520 -----------------
output/output_rhv_upload.mli | 21 -
output/output_rhv_upload_cancel_source.mli | 19 -
output/output_rhv_upload_createvm_source.mli | 19 -
output/output_rhv_upload_finalize_source.mli | 19 -
output/output_rhv_upload_plugin_source.mli | 19 -
output/output_rhv_upload_precheck_source.mli | 19 -
output/output_rhv_upload_transfer_source.mli | 19 -
output/output_rhv_upload_vmcheck_source.mli | 19 -
output/output_vdsm.ml | 237 --------
output/output_vdsm.mli | 21 -
output/rhv-upload-cancel.py | 96 ----
output/rhv-upload-createvm.py | 137 -----
output/rhv-upload-finalize.py | 174 ------
output/rhv-upload-plugin.py | 525 ------------------
output/rhv-upload-precheck.py | 135 -----
output/rhv-upload-transfer.py | 298 ----------
output/rhv-upload-vmcheck.py | 72 ---
tests/Makefile.am | 15 -
tests/test-v2v-o-rhv-upload-module/imageio.py | 71 ---
.../ovirtsdk4/__init__.py | 150 -----
.../ovirtsdk4/types.py | 184 ------
tests/test-v2v-o-rhv-upload-oo-query.sh | 41 --
tests/test-v2v-o-rhv-upload.sh | 74 ---
tests/test-v2v-o-rhv.ovf.expected | 113 ----
tests/test-v2v-o-rhv.sh | 87 ---
tests/test-v2v-o-vdsm-oo-query.sh | 41 --
tests/test-v2v-o-vdsm-options.ovf.expected | 113 ----
tests/test-v2v-o-vdsm-options.sh | 96 ----
v2v/v2v.ml | 10 +-
36 files changed, 4 insertions(+), 4206 deletions(-)
delete mode 100644 docs/virt-v2v-output-rhv.pod
delete mode 100644 output/output_rhv.ml
delete mode 100644 output/output_rhv.mli
delete mode 100644 output/output_rhv_upload.ml
delete mode 100644 output/output_rhv_upload.mli
delete mode 100644 output/output_rhv_upload_cancel_source.mli
delete mode 100644 output/output_rhv_upload_createvm_source.mli
delete mode 100644 output/output_rhv_upload_finalize_source.mli
delete mode 100644 output/output_rhv_upload_plugin_source.mli
delete mode 100644 output/output_rhv_upload_precheck_source.mli
delete mode 100644 output/output_rhv_upload_transfer_source.mli
delete mode 100644 output/output_rhv_upload_vmcheck_source.mli
delete mode 100644 output/output_vdsm.ml
delete mode 100644 output/output_vdsm.mli
delete mode 100644 output/rhv-upload-cancel.py
delete mode 100644 output/rhv-upload-createvm.py
delete mode 100644 output/rhv-upload-finalize.py
delete mode 100644 output/rhv-upload-plugin.py
delete mode 100644 output/rhv-upload-precheck.py
delete mode 100644 output/rhv-upload-transfer.py
delete mode 100644 output/rhv-upload-vmcheck.py
delete mode 100755 tests/test-v2v-o-rhv-upload-module/imageio.py
delete mode 100644 tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py
delete mode 100644 tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py
delete mode 100755 tests/test-v2v-o-rhv-upload-oo-query.sh
delete mode 100755 tests/test-v2v-o-rhv-upload.sh
delete mode 100644 tests/test-v2v-o-rhv.ovf.expected
delete mode 100755 tests/test-v2v-o-rhv.sh
delete mode 100755 tests/test-v2v-o-vdsm-oo-query.sh
delete mode 100644 tests/test-v2v-o-vdsm-options.ovf.expected
delete mode 100755 tests/test-v2v-o-vdsm-options.sh
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 214cfc24..2cbe9397 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -26,7 +26,6 @@ EXTRA_DIST = \
virt-v2v-inspector.pod \
virt-v2v-output-local.pod \
virt-v2v-output-openstack.pod \
- virt-v2v-output-rhv.pod \
virt-v2v-release-notes-1.42.pod \
virt-v2v-release-notes-2.0.pod \
virt-v2v-release-notes-2.2.pod \
@@ -44,7 +43,6 @@ man_MANS = \
virt-v2v-inspector.1 \
virt-v2v-output-local.1 \
virt-v2v-output-openstack.1 \
- virt-v2v-output-rhv.1 \
virt-v2v-release-notes-1.42.1 \
virt-v2v-release-notes-2.0.1 \
virt-v2v-release-notes-2.2.1 \
@@ -59,7 +57,6 @@ noinst_DATA = \
$(top_builddir)/website/virt-v2v-inspector.1.html \
$(top_builddir)/website/virt-v2v-output-local.1.html \
$(top_builddir)/website/virt-v2v-output-openstack.1.html \
- $(top_builddir)/website/virt-v2v-output-rhv.1.html \
$(top_builddir)/website/virt-v2v-release-notes-1.42.1.html \
$(top_builddir)/website/virt-v2v-release-notes-2.0.1.html \
$(top_builddir)/website/virt-v2v-release-notes-2.2.1.html \
@@ -146,17 +143,6 @@ stamp-virt-v2v-output-openstack.pod: virt-v2v-output-openstack.pod
$<
touch $@
-virt-v2v-output-rhv.1 $(top_builddir)/website/virt-v2v-output-rhv.1.html: stamp-virt-v2v-output-rhv.pod
-
-stamp-virt-v2v-output-rhv.pod: virt-v2v-output-rhv.pod
- $(PODWRAPPER) \
- --man virt-v2v-output-rhv.1 \
- --html $(top_builddir)/website/virt-v2v-output-rhv.1.html \
- --license GPLv2+ \
- --warning safe \
- $<
- touch $@
-
virt-v2v-release-notes-1.42.1 $(top_builddir)/website/virt-v2v-release-notes-1.42.1.html: stamp-virt-v2v-release-notes-1.42.pod
stamp-virt-v2v-release-notes-1.42.pod: virt-v2v-release-notes-1.42.pod
diff --git a/docs/virt-v2v-output-rhv.pod b/docs/virt-v2v-output-rhv.pod
deleted file mode 100644
index 2ce697f4..00000000
--- a/docs/virt-v2v-output-rhv.pod
+++ /dev/null
@@ -1,232 +0,0 @@
-=head1 NAME
-
-virt-v2v-output-rhv - Using virt-v2v to convert guests to oVirt or RHV
-
-=head1 SYNOPSIS
-
- virt-v2v [-i* options] -o rhv-upload [-oc ENGINE_URL] -os STORAGE
- [-op PASSWORD] [-of raw]
- [-oo rhv-cafile=FILE]
- [-oo rhv-cluster=CLUSTER]
- [-oo rhv-proxy]
- [-oo rhv-disk-uuid=UUID ...]
- [-oo rhv-verifypeer]
-
- virt-v2v [-i* options] -o rhv -os [esd:/path|/path]
-
- virt-v2v [-i* options] -o vdsm
- [-oo vdsm-image-uuid=UUID]
- [-oo vdsm-vol-uuid=UUID]
- [-oo vdsm-vm-uuid=UUID]
- [-oo vdsm-ovf-output=DIR]
-
-=head1 DESCRIPTION
-
-This page documents how to use L<virt-v2v(1)> to convert guests to an
-oVirt or RHV management instance. There are three output modes that
-you can select, but only I<-o rhv-upload> should be used normally, the
-other two are deprecated:
-
-=over 4
-
-=item B<-o rhv-upload> B<-os> STORAGE
-
-Full description: L</OUTPUT TO RHV>
-
-This is the modern method for uploading to oVirt/RHV via the REST API.
-It requires oVirt/RHV E<ge> 4.2.
-
-=item B<-o rhv> B<-os> esd:/path
-
-=item B<-o rhv> B<-os> /path
-
-Full description: L</OUTPUT TO EXPORT STORAGE DOMAIN>
-
-This is the old method for uploading to oVirt/RHV via the
-Export Storage Domain (ESD). The ESD can either be accessed
-over NFS (using the I<-os esd:/path> form) or if you have
-already NFS-mounted it somewhere specify the path to the mountpoint
-as I<-os /path>.
-
-The Export Storage Domain was deprecated in oVirt 4, and so we expect
-that this method will stop working at some point in the future.
-
-=item B<-o vdsm>
-
-This is the old method used internally by the RHV-M user interface.
-It is never intended to be used directly by end users.
-
-=back
-
-=head1 OUTPUT TO RHV
-
-This new method to upload guests to oVirt or RHV directly via the REST
-API requires oVirt/RHV E<ge> 4.2.
-
-You need to specify I<-o rhv-upload> as well as the following extra
-parameters:
-
-=over 4
-
-=item I<-oc> C<https://ovirt-engine.example.com/ovirt-engine/api>
-
-The URL of the REST API which is usually the server name with
-C</ovirt-engine/api> appended, but might be different if you installed
-oVirt Engine on a different path.
-
-You can optionally add a username and port number to the URL. If the
-username is not specified then virt-v2v defaults to using
-C<admin@internal> which is the typical superuser account for oVirt
-instances.
-
-=item I<-of raw>
-
-Currently you must use I<-of raw> and you cannot use I<-oa preallocated>.
-
-These restrictions will be loosened in a future version.
-
-=item I<-op> F<password-file>
-
-A file containing a password to be used when connecting to the oVirt
-engine. Note the file should contain the whole password, B<without
-any trailing newline>, and for security the file should have mode
-C<0600> so that others cannot read it.
-
-=item I<-os> C<ovirt-data>
-
-The storage domain.
-
-=item I<-oo rhv-cafile=>F<ca.pem>
-
-The F<ca.pem> file (Certificate Authority), copied from
-F</etc/pki/ovirt-engine/ca.pem> on the oVirt engine.
-
-If I<-oo rhv-verifypeer> is enabled then this option can
-be used to control which CA is used to verify the clients
-identity. If this option is not used then the systems
-global trust store is used.
-
-=item I<-oo rhv-cluster=>C<CLUSTERNAME>
-
-Set the RHV Cluster Name. If not given it uses C<Default>.
-
-=item I<-oo rhv-disk-uuid=>C<UUID>
-
-This option can used to manually specify UUIDs for the disks when
-creating the virtual machine. If not specified, the oVirt engine will
-generate random UUIDs for the disks. Please note that:
-
-=over 4
-
-=item *
-
-you B<must> pass as many I<-oo rhv-disk-uuid=UUID> options as the
-amount of disks in the guest
-
-=item *
-
-the specified UUIDs must not conflict with the UUIDs of existing disks
-
-=back
-
-=item I<-oo rhv-proxy>
-
-Proxy the upload through oVirt Engine. This is slower than uploading
-directly to the oVirt node but may be necessary if you do not have
-direct network access to the nodes.
-
-=item I<-oo rhv-verifypeer>
-
-Verify the oVirt/RHV servers identity by checking the servers
-certificate against the Certificate Authority.
-
-=back
-
-=head1 OUTPUT TO EXPORT STORAGE DOMAIN
-
-This section only applies to the I<-o rhv> output mode. If you use
-virt-v2v from the RHV-M user interface, then behind the scenes the
-import is managed by VDSM using the I<-o vdsm> output mode (which end
-users should not try to use directly).
-
-You have to specify I<-o rhv> and an I<-os> option that points to the
-RHV-M Export Storage Domain. You can either specify the NFS server
-and mountpoint, eg. S<C<-os rhv-storage:/rhv/export>>, or you can
-mount that first and point to the directory where it is mounted,
-eg. S<C<-os /tmp/mnt>>. Be careful not to point to the Data Storage
-Domain by accident as that will not work.
-
-On successful completion virt-v2v will have written the new guest to
-the Export Storage Domain, but it will not yet be ready to run. It
-must be imported into RHV using the UI before it can be used.
-
-In RHV E<ge> 2.2 this is done from the Storage tab. Select the
-export domain the guest was written to. A pane will appear underneath
-the storage domain list displaying several tabs, one of which is "VM
-Import". The converted guest will be listed here. Select the
-appropriate guest an click "Import". See the RHV documentation for
-additional details.
-
-If you export several guests, then you can import them all at the same
-time through the UI.
-
-=head2 Testing RHV conversions
-
-If you do not have an oVirt or RHV instance to test against, then you
-can test conversions by creating a directory structure which looks
-enough like a RHV-M Export Storage Domain to trick virt-v2v:
-
- uuid=`uuidgen`
- mkdir /tmp/rhv
- mkdir /tmp/rhv/$uuid
- mkdir /tmp/rhv/$uuid/images
- mkdir /tmp/rhv/$uuid/master
- mkdir /tmp/rhv/$uuid/master/vms
- touch /tmp/rhv/$uuid/dom_md
- virt-v2v [...] -o rhv -os /tmp/rhv
-
-=head2 Debugging RHV-M import failures
-
-When you export to the RHV-M Export Storage Domain, and then import
-that guest through the RHV-M UI, you may encounter an import failure.
-Diagnosing these failures is infuriatingly difficult as the UI
-generally hides the true reason for the failure.
-
-There are several log files of interest:
-
-=over 4
-
-=item F</var/log/vdsm/import/>
-
-In oVirt E<ge> 4.1.0, VDSM preserves the virt-v2v log file for
-30 days in this directory.
-
-This directory is found on the host which performed the conversion.
-The host can be selected in the import dialog, or can be found under
-the C<Events> tab in oVirt administration.
-
-=item F</var/log/vdsm/vdsm.log>
-
-As above, this file is present on the host which performed the
-conversion. It contains detailed error messages from low-level
-operations executed by VDSM, and is useful if the error was not caused
-by virt-v2v, but by VDSM.
-
-=item F</var/log/ovirt-engine/engine.log>
-
-This log file is stored on the RHV-M server. It contains more detail
-for any errors caused by the oVirt GUI.
-
-=back
-
-=head1 SEE ALSO
-
-L<virt-v2v(1)>.
-
-=head1 AUTHOR
-
-Richard W.M. Jones
-
-=head1 COPYRIGHT
-
-Copyright (C) 2009-2020 Red Hat Inc.
diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
index 59843d35..4dac1203 100644
--- a/docs/virt-v2v.pod
+++ b/docs/virt-v2v.pod
@@ -13,7 +13,7 @@ virt-v2v - Convert a guest to use KVM
Virt-v2v converts a single guest from a foreign hypervisor to run on
KVM. It can read Linux and Windows guests running on VMware,
Hyper-V and some other hypervisors, and convert them to KVM managed by
-libvirt, OpenStack, oVirt, Red Hat Virtualisation (RHV) or several
+libvirt, OpenStack or several
other targets. It can modify the guest to make it bootable on KVM and
install virtio drivers so it will run quickly.
@@ -45,8 +45,6 @@ L<virt-v2v-input-vmware(1)> — Input from VMware.
L<virt-v2v-output-local(1)> — Output to local files or local libvirt.
-L<virt-v2v-output-rhv(1)> — Output to oVirt or RHV.
-
L<virt-v2v-output-openstack(1)> — Output to OpenStack.
L<virt-v2v-release-notes-1.42(1)> — Release notes for 1.42 release.
@@ -74,21 +72,6 @@ disks to F</var/lib/libvirt/images>.
For more information see L<virt-v2v-input-vmware(1)>.
-=head2 Convert from VMware to RHV/oVirt
-
-This is the same as the previous example, except you want to send the
-guest to a RHV Data Domain using the RHV REST API. Guest network
-interface(s) are connected to the target network called C<ovirtmgmt>.
-
- virt-v2v -ic vpx://vcenter.example.com/Datacenter/esxi vmware_guest \
- -o rhv-upload -oc https://ovirt-engine.example.com/ovirt-engine/api \
- -os ovirt-data -op /tmp/ovirt-admin-password -of raw \
- -oo rhv-cafile=/tmp/ca.pem --bridge ovirtmgmt
-
-In this case the host running virt-v2v acts as a B<conversion server>.
-
-For more information see L<virt-v2v-output-rhv(1)>.
-
=head2 Convert from ESXi hypervisor over SSH to local libvirt
You have an ESXi hypervisor called C<esxi.example.com> with SSH access
@@ -468,14 +451,6 @@ no metadata is written.
Set the output method to OpenStack. See L<virt-v2v-output-openstack(1)>.
-=item B<-o> B<ovirt>
-
-This is the same as I<-o rhv>.
-
-=item B<-o> B<ovirt-upload>
-
-This is the same as I<-o rhv-upload>.
-
=item B<-o> B<qemu>
Set the output method to I<qemu>.
@@ -484,40 +459,6 @@ This is similar to I<-o local>, except that a shell script is written
which you can use to boot the guest in qemu. The converted disks and
shell script are written to the directory specified by I<-os>.
-=item B<-o> B<rhev>
-
-This is the same as I<-o rhv>.
-
-=item B<-o> B<rhv>
-
-Set the output method to I<rhv>.
-
-The converted guest is written to a RHV Export Storage Domain. The
-I<-os> parameter must also be used to specify the location of the
-Export Storage Domain. Note this does not actually import the guest
-into RHV. You have to do that manually later using the UI.
-
-See L<virt-v2v-output-rhv(1)>.
-
-=item B<-o> B<rhv-upload>
-
-Set the output method to I<rhv-upload>.
-
-The converted guest is written directly to a RHV Data Domain.
-This is a faster method than I<-o rhv>, but requires oVirt
-or RHV E<ge> 4.2.
-
-See L<virt-v2v-output-rhv(1)>.
-
-=item B<-o> B<vdsm>
-
-Set the output method to I<vdsm>.
-
-This mode is similar to I<-o rhv>, but the full path to the
-data domain must be given:
-F</rhv/data-center/E<lt>data-center-uuidE<gt>/E<lt>data-domain-uuidE<gt>>.
-This mode is only used when virt-v2v runs under VDSM control.
-
=item B<-oa> B<sparse>
=item B<-oa> B<preallocated>
@@ -580,117 +521,11 @@ For I<-o openstack> (L<virt-v2v-output-openstack(1)>) only, set optional
OpenStack authentication. For example I<-oo os-username=>NAME is
equivalent to C<openstack --os-username=NAME>.
-=item B<-oo rhv-cafile=>F<ca.pem>
-
-For I<-o rhv-upload> (L<virt-v2v-output-rhv(1)>) only, the F<ca.pem> file
-(Certificate Authority), copied from F</etc/pki/ovirt-engine/ca.pem>
-on the oVirt engine.
-
-=item B<-oo rhv-cluster=>C<CLUSTERNAME>
-
-For I<-o rhv-upload> (L<virt-v2v-output-rhv(1)>) only, set the RHV Cluster
-Name. If not given it uses C<Default>.
-
-=item B<-oo rhv-proxy>
-
-For I<-o rhv-upload> (L<virt-v2v-output-rhv(1)>) only, proxy the
-upload through oVirt Engine. This is slower than uploading directly
-to the oVirt node but may be necessary if you do not have direct
-network access to the nodes.
-
-=item B<-oo rhv-verifypeer>
-
-For I<-o rhv-upload> (L<virt-v2v-output-rhv(1)>) only, verify the oVirt/RHV
-servers identity by checking the servers certificate against the
-Certificate Authority.
-
=item B<-oo server-id=>C<NAME|UUID>
For I<-o openstack> (L<virt-v2v-output-openstack(1)>) only, set the name
of the conversion appliance where virt-v2v is running.
-=item B<-oo vdsm-compat=0.10>
-
-=item B<-oo vdsm-compat=1.1>
-
-If I<-o vdsm> and the output format is qcow2, then we add the qcow2
-I<compat=0.10> option to the output file for compatibility with RHEL 6
-(see L<https://bugzilla.redhat.com/1145582>).
-
-If I<-oo vdsm-compat=1.1> is used then modern qcow2 (I<compat=1.1>)
-files are generated instead.
-
-Currently I<-oo vdsm-compat=0.10> is the default, but this will change
-to I<-oo vdsm-compat=1.1> in a future version of virt-v2v (when we can
-assume that everyone is using a modern version of qemu).
-
-B<Note this option only affects I<-o vdsm> output>. All other output
-modes (including I<-o rhv>) generate modern qcow2 I<compat=1.1>
-files, always.
-
-If this option is available, then C<vdsm-compat-option> will appear in
-the I<--machine-readable> output.
-
-=item B<-oo vdsm-image-uuid=>UUID
-
-=item B<-oo vdsm-vol-uuid=>UUID
-
-=item B<-oo vdsm-vm-uuid=>UUID
-
-=item B<-oo vdsm-ovf-output=>DIR
-
-Normally the RHV output mode chooses random UUIDs for the target
-guest. However VDSM needs to control the UUIDs and passes these
-parameters when virt-v2v runs under VDSM control. The parameters
-control:
-
-=over 4
-
-=item *
-
-the image directory of each guest disk (I<-oo vdsm-image-uuid>) (this
-option is passed once for each guest disk)
-
-=item *
-
-UUIDs for each guest disk (I<-oo vdsm-vol-uuid>) (this option
-is passed once for each guest disk)
-
-=item *
-
-the OVF file name (I<-oo vdsm-vm-uuid>).
-
-=item *
-
-the OVF output directory (default current directory) (I<-oo vdsm-ovf-output>).
-
-=back
-
-The format of UUIDs is: C<12345678-1234-1234-1234-123456789abc> (each
-hex digit can be C<0-9> or C<a-f>), conforming to S<OSF DCE 1.1>.
-
-These options can only be used with I<-o vdsm>.
-
-=item B<-oo vdsm-ovf-flavour=>flavour
-
-This option controls the format of the OVF generated at the end of conversion.
-Currently there are two possible flavours:
-
-=over 4
-
-=item rhvexp
-
-The OVF format used in RHV export storage domain.
-
-=item ovirt
-
-The OVF format understood by oVirt REST API.
-
-=back
-
-For backward compatibility the default is I<rhvexp>, but this may change in
-the future.
-
=item B<-op> file
Supply a file containing a password to be used when connecting to the
@@ -708,28 +543,8 @@ For I<-o libvirt>, this is a libvirt directory pool
For I<-o local> and I<-o qemu>, this is a directory name.
The directory must exist.
-For I<-o rhv-upload>, this is the name of the destination Storage
-Domain.
-
For I<-o openstack>, this is the optional Cinder volume type.
-For I<-o rhv>, this can be an NFS path of the Export Storage Domain
-of the form C<E<lt>hostE<gt>:E<lt>pathE<gt>>, eg:
-
- rhv-storage.example.com:/rhv/export
-
-The NFS export must be mountable and writable by the user and host
-running virt-v2v, since the virt-v2v program has to actually mount it
-when it runs. So you probably have to run virt-v2v as C<root>.
-
-B<Or:> You can mount the Export Storage Domain yourself, and point
-I<-os> to the mountpoint. Note that virt-v2v will still need to write
-to this remote directory, so virt-v2v will still need to run as
-C<root>.
-
-You will get an error if virt-v2v is unable to mount/write to the
-Export Storage Domain.
-
=item B<--print-source>
Print information about the source guest and stop. This option is
@@ -1270,26 +1085,6 @@ require either root or a special user:
=over 4
-=item Mounting the Export Storage Domain
-
-When using I<-o rhv -os server:/esd> virt-v2v has to have sufficient
-privileges to NFS mount the Export Storage Domain from C<server>.
-
-You can avoid needing root here by mounting it yourself before running
-virt-v2v, and passing I<-os /mountpoint> instead, but first of all
-read the next S<section ...>
-
-=item Writing to the Export Storage Domain as 36:36
-
-RHV-M cannot read files and directories from the Export Storage
-Domain unless they have UID:GID 36:36. You will see VM import
-problems if the UID:GID is not correct.
-
-When you run virt-v2v I<-o rhv> as root, virt-v2v attempts to create
-files and directories with the correct ownership. If you run virt-v2v
-as non-root, it will probably still work, but you will need to
-manually change ownership after virt-v2v has finished.
-
=item Writing to libvirt
When using I<-o libvirt>, you may need to run virt-v2v as root so that
@@ -1396,7 +1191,6 @@ virt-v2v binary. Typical output looks like this:
virt-v2v
libguestfs-rewrite
colours-option
- vdsm-compat-option
input:disk
[...]
output:local
diff --git a/output/Makefile.am b/output/Makefile.am
index 9663acb1..d53a2280 100644
--- a/output/Makefile.am
+++ b/output/Makefile.am
@@ -17,14 +17,7 @@
include $(top_srcdir)/subdir-rules.mk
-BUILT_SOURCES = \
- output_rhv_upload_cancel_source.ml \
- output_rhv_upload_createvm_source.ml \
- output_rhv_upload_finalize_source.ml \
- output_rhv_upload_plugin_source.ml \
- output_rhv_upload_precheck_source.ml \
- output_rhv_upload_transfer_source.ml \
- output_rhv_upload_vmcheck_source.ml
+BUILT_SOURCES =
EXTRA_DIST = \
$(SOURCES_MLI) \
@@ -32,13 +25,6 @@ EXTRA_DIST = \
$(SOURCES_C) \
$(BUILT_SOURCES) \
embed.sh \
- rhv-upload-cancel.py \
- rhv-upload-createvm.py \
- rhv-upload-finalize.py \
- rhv-upload-plugin.py \
- rhv-upload-precheck.py \
- rhv-upload-transfer.py \
- rhv-upload-vmcheck.py \
test-v2v-python-syntax.sh
SOURCES_MLI = \
@@ -54,16 +40,6 @@ SOURCES_MLI = \
output_null.mli \
output_openstack.mli \
output_qemu.mli \
- output_rhv.mli \
- output_rhv_upload.mli \
- output_vdsm.mli \
- output_rhv_upload_cancel_source.mli \
- output_rhv_upload_createvm_source.mli \
- output_rhv_upload_finalize_source.mli \
- output_rhv_upload_plugin_source.mli \
- output_rhv_upload_precheck_source.mli \
- output_rhv_upload_transfer_source.mli \
- output_rhv_upload_vmcheck_source.mli \
python_script.mli \
qemuopts.mli
@@ -74,13 +50,6 @@ SOURCES_ML = \
create_kubevirt_yaml.ml \
qemuopts.ml \
openstack_image_properties.ml \
- output_rhv_upload_cancel_source.ml \
- output_rhv_upload_createvm_source.ml \
- output_rhv_upload_finalize_source.ml \
- output_rhv_upload_plugin_source.ml \
- output_rhv_upload_precheck_source.ml \
- output_rhv_upload_transfer_source.ml \
- output_rhv_upload_vmcheck_source.ml \
output.ml \
output_disk.ml \
output_glance.ml \
@@ -88,30 +57,11 @@ SOURCES_ML = \
output_libvirt.ml \
output_null.ml \
output_openstack.ml \
- output_qemu.ml \
- output_rhv.ml \
- output_rhv_upload.ml \
- output_vdsm.ml
+ output_qemu.ml
SOURCES_C = \
qemuopts-c.c
-# These files are generated and contain *.py embedded as an OCaml string.
-output_rhv_upload_cancel_source.ml: $(srcdir)/rhv-upload-cancel.py
- $(srcdir)/embed.sh code $^ $@
-output_rhv_upload_createvm_source.ml: $(srcdir)/rhv-upload-createvm.py
- $(srcdir)/embed.sh code $^ $@
-output_rhv_upload_finalize_source.ml: $(srcdir)/rhv-upload-finalize.py
- $(srcdir)/embed.sh code $^ $@
-output_rhv_upload_plugin_source.ml: $(srcdir)/rhv-upload-plugin.py
- $(srcdir)/embed.sh code $^ $@
-output_rhv_upload_precheck_source.ml: $(srcdir)/rhv-upload-precheck.py
- $(srcdir)/embed.sh code $^ $@
-output_rhv_upload_transfer_source.ml: $(srcdir)/rhv-upload-transfer.py
- $(srcdir)/embed.sh code $^ $@
-output_rhv_upload_vmcheck_source.ml: $(srcdir)/rhv-upload-vmcheck.py
- $(srcdir)/embed.sh code $^ $@
-
# We pretend that we're building a C library. automake handles the
# compilation of the C sources for us. At the end we take the C
# objects and OCaml objects and link them into the OCaml library.
diff --git a/output/output_rhv.ml b/output/output_rhv.ml
deleted file mode 100644
index 13c2d8dc..00000000
--- a/output/output_rhv.ml
+++ /dev/null
@@ -1,317 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2009-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.
- *)
-
-open Printf
-open Unix
-
-open Std_utils
-open Tools_utils
-open Unix_utils
-open Common_gettext.Gettext
-
-open Types
-open Utils
-
-open Output
-
-module RHV = struct
- type poptions = Types.output_allocation * string * string * string
-
- type t = string * string * string * string list * string list * int64 list
-
- let to_string options = "-o rhv"
-
- let query_output_options () =
- printf (f_"No output options can be used in this mode.\n")
-
- let parse_options options source =
- if options.output_options <> [] then
- error (f_"no -oo (output options) are allowed here");
- if options.output_password <> None then
- error_option_cannot_be_used_in_output_mode "rhv" "-op";
-
- (* -os must be set, but at this point we cannot check it. *)
- let output_storage =
- match options.output_storage with
- | None -> error (f_"-o rhv: -os option was not specified")
- | Some d -> d in
-
- let output_name = Option.value ~default:source.s_name options.output_name in
-
- (options.output_alloc, options.output_format, output_name, output_storage)
-
- let rec setup dir options source =
- error_if_disk_count_gt dir 23;
- let disks = get_disks dir in
- let output_alloc, output_format, output_name, output_storage = options in
-
- (* UID:GID required for files and directories when writing to ESD. *)
- let uid = 36 and gid = 36 in
-
- (* Create a UID-switching handle. If we're not root, create a dummy
- * one because we cannot switch UIDs.
- *)
- let running_as_root = geteuid () = 0 in
- let changeuid_t =
- if running_as_root then
- Changeuid.create ~uid ~gid ()
- else
- Changeuid.create () in
-
- let esd_mp, esd_uuid =
- mount_and_check_storage_domain (s_"Export Storage Domain")
- output_storage in
- debug "RHV: ESD mountpoint: %s\nRHV: ESD UUID: %s" esd_mp esd_uuid;
-
- (* See if we can write files as UID:GID 36:36. *)
- let () =
- let testfile = esd_mp // esd_uuid // String.random8 () in
- Changeuid.make_file changeuid_t testfile "";
- let stat = stat testfile in
- Changeuid.unlink changeuid_t testfile;
- let actual_uid = stat.st_uid and actual_gid = stat.st_gid in
- debug "RHV: actual UID:GID of new files is %d:%d" actual_uid actual_gid;
- if uid <> actual_uid || gid <> actual_gid then (
- if running_as_root then
- warning (f_"cannot write files to the NFS server as %d:%d, \
- even though we appear to be running as root. This \
- probably means the NFS client or idmapd is not \
- configured properly.\n\nYou will have to chown \
- the files that virt-v2v creates after the run, \
- otherwise RHV-M will not be able to import the VM.")
- uid gid
- else
- warning (f_"cannot write files to the NFS server as %d:%d. \
- You might want to stop virt-v2v (^C) and rerun it \
- as root.") uid gid
- ) in
-
- (* Create unique UUIDs for everything *)
- let vm_uuid = uuidgen () in
- (* Generate random image and volume UUIDs for each target disk. *)
- let image_uuids = List.map (fun _ -> uuidgen ()) disks in
- let vol_uuids = List.map (fun _ -> uuidgen ()) disks in
-
- (* We need to create the target image director(ies) so there's a place
- * for the main program to copy the images to. However if image
- * conversion fails for any reason then we delete this directory.
- *)
- let images_dir = esd_mp // esd_uuid // "images" in
- List.iter (
- fun image_uuid ->
- let d = images_dir // image_uuid in
- Changeuid.mkdir changeuid_t d 0o755
- ) image_uuids;
- On_exit.f (
- fun () ->
- (* virt-v2v writes v2vdir/done on success only. *)
- let success = Sys.file_exists (dir // "done") in
- if not success then (
- List.iter (
- fun image_uuid ->
- let d = images_dir // image_uuid in
- let cmd = sprintf "rm -rf %s" (quote d) in
- Changeuid.command changeuid_t cmd
- ) image_uuids
- )
- );
-
- (* The final directory structure should look like this:
- * /<MP>/<ESD_UUID>/images/
- * <IMAGE_UUID_1>/<VOL_UUID_1> # first disk
- * <IMAGE_UUID_1>/<VOL_UUID_1>.meta # first disk
- * <IMAGE_UUID_2>/<VOL_UUID_2> # second disk
- * <IMAGE_UUID_2>/<VOL_UUID_2>.meta # second disk
- * <IMAGE_UUID_3>/<VOL_UUID_3> # etc
- * <IMAGE_UUID_3>/<VOL_UUID_3>.meta #
- *)
-
- (* Generate the randomly named target files (just the names).
- * The main code is what generates the files themselves.
- *)
- let filenames =
- List.map (
- fun (image_uuid, vol_uuid) ->
- let filename = images_dir // image_uuid // vol_uuid in
- debug "RHV: disk: %s" filename;
- filename
- ) (List.combine image_uuids vol_uuids) in
-
- (* Generate the .meta file associated with each volume. *)
- let sizes = List.map snd disks in
- let metas =
- Create_ovf.create_meta_files output_alloc output_format
- esd_uuid image_uuids sizes in
- List.iter (
- fun (filename, meta) ->
- let meta_filename = filename ^ ".meta" in
- Changeuid.make_file changeuid_t meta_filename meta
- ) (List.combine filenames metas);
-
- (* Set up the NBD servers. *)
- List.iter (
- fun ((i, size), filename) ->
- let socket = sprintf "%s/out%d" dir i in
- On_exit.unlink socket;
-
- (* Create the actual output disk. *)
- let changeuid f =
- Changeuid.func changeuid_t (
- fun () ->
- (* Run the command to create the file. *)
- f ();
- (* Make the file sufficiently writable so that possibly root, or
- * root squashed nbdkit will definitely be able to open it.
- * An example of how root squashing nonsense makes everyone
- * less secure.
- *)
- chmod filename 0o666
- )
- in
-
- (* We have to wait for the NBD server to exit rather than just
- * killing it, otherwise it races with unmounting. See:
- * https://bugzilla.redhat.com/show_bug.cgi?id=1953286#c26
- *)
- let on_exit_kill = Output.KillAndWait in
-
- output_to_local_file ~changeuid ~on_exit_kill
- output_alloc output_format filename size socket
- ) (List.combine disks filenames);
-
- (* Save parameters since we need them during finalization. *)
- let t = esd_mp, esd_uuid, vm_uuid, image_uuids, vol_uuids, sizes in
- t
-
- and mount_and_check_storage_domain domain_class os =
- (* The user can either specify -os nfs:/export, or a local directory
- * which is assumed to be the already-mounted NFS export.
- *)
- match String.split ":/" os with
- | mp, "" -> (* Already mounted directory. *)
- check_storage_domain domain_class os mp
- | server, export ->
- let export = "/" ^ export in
-
- (* Create a mountpoint. Default mode is too restrictive for us
- * when we need to write into the directory as 36:36.
- *)
- let mp = Mkdtemp.temp_dir "v2v." in
- chmod mp 0o755;
-
- (* Try mounting it. *)
- let cmd = [ "mount"; sprintf "%s:%s" server export; mp ] in
- if run_command cmd <> 0 then
- error (f_"mount command failed, see earlier errors.\n\nThis probably \
- means you didn't specify the right %s path [-os %s], or \
- else you need to rerun virt-v2v as root.") domain_class os;
-
- (* Make sure it is unmounted at exit, as late as possible (prio=9999) *)
- On_exit.f ~prio:9999 (
- fun () ->
- let cmd = [ "umount"; mp ] in
- ignore (run_command cmd);
- try rmdir mp with _ -> ()
- );
-
- check_storage_domain domain_class os mp
-
- and check_storage_domain domain_class os mp =
- (* Typical SD mountpoint looks like this:
- * $ ls /tmp/mnt
- * 39b6af0e-1d64-40c2-97e4-4f094f1919c7 __DIRECT_IO_TEST__ lost+found
- * $ ls /tmp/mnt/39b6af0e-1d64-40c2-97e4-4f094f1919c7
- * dom_md images master
- * We expect exactly one of those magic UUIDs.
- *)
- let entries =
- try Sys.readdir mp
- with Sys_error msg ->
- error (f_"could not read the %s specified by the '-os %s' \
- parameter on the command line. Is it really an \
- OVirt or RHV-M %s? The original error is: %s")
- domain_class os domain_class msg in
- let entries = Array.to_list entries in
- let uuids = List.filter (
- fun entry ->
- String.length entry = 36 &&
- entry.[8] = '-' && entry.[13] = '-' && entry.[18] = '-' &&
- entry.[23] = '-'
- ) entries in
- let uuid =
- match uuids with
- | [uuid] -> uuid
- | [] ->
- error (f_"there are no UUIDs in the %s (%s). Is it really an \
- OVirt or RHV-M %s?") domain_class os domain_class
- | _::_ ->
- error (f_"there are multiple UUIDs in the %s (%s). This is \
- unexpected, and may be a bug in virt-v2v or OVirt.")
- domain_class os in
-
- (* Check that the domain has been attached to a Data Center by
- * checking that the master/vms directory exists.
- *)
- let () =
- let master_vms_dir = mp // uuid // "master" // "vms" in
- if not (is_directory master_vms_dir) then
- error (f_"%s does not exist or is not a directory.\n\nMost likely \
- cause: Either the %s (%s) has not been attached to any \
- Data Center, or the path %s is not an %s at all.\n\n\
- You have to attach the %s to a Data Center using the \
- RHV-M / OVirt user interface first.\n\nIf you dont \
- know what the %s mount point should be then you can \
- also find this out through the RHV-M user interface.")
- master_vms_dir domain_class os os
- domain_class domain_class domain_class in
-
- (* Looks good, so return the SD mountpoint and UUID. *)
- (mp, uuid)
-
- let finalize dir options t source inspect target_meta =
- let output_alloc, output_format, output_name, output_storage = options in
- let esd_mp, esd_uuid, vm_uuid, image_uuids, vol_uuids, sizes = t in
-
- (* UID:GID required for files and directories when writing to ESD. *)
- let uid = 36 and gid = 36 in
-
- (* Create a UID-switching handle. If we're not root, create a dummy
- * one because we cannot switch UIDs.
- *)
- let running_as_root = geteuid () = 0 in
- let changeuid_t =
- if running_as_root then
- Changeuid.create ~uid ~gid ()
- else
- Changeuid.create () in
-
- (* Create the metadata. *)
- let ovf =
- Create_ovf.create_ovf source inspect target_meta sizes
- output_alloc output_format output_name esd_uuid image_uuids vol_uuids
- ~need_actual_sizes:true dir vm_uuid
- Create_ovf.RHVExportStorageDomain in
-
- (* Write it to the metadata file. *)
- let dir = esd_mp // esd_uuid // "master" // "vms" // vm_uuid in
- Changeuid.mkdir changeuid_t dir 0o755;
- let file = dir // vm_uuid ^ ".ovf" in
- Changeuid.output changeuid_t file (fun chan -> DOM.doc_to_chan chan ovf)
-
- let request_size = None
-end
diff --git a/output/output_rhv.mli b/output/output_rhv.mli
deleted file mode 100644
index 08f3f2d0..00000000
--- a/output/output_rhv.mli
+++ /dev/null
@@ -1,21 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2009-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.
- *)
-
-(** [-o rhv] output mode. *)
-
-module RHV : Output.OUTPUT
diff --git a/output/output_rhv_upload.ml b/output/output_rhv_upload.ml
deleted file mode 100644
index d6fde169..00000000
--- a/output/output_rhv_upload.ml
+++ /dev/null
@@ -1,520 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2009-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.
- *)
-
-open Printf
-open Unix
-
-open Std_utils
-open Tools_utils
-open Common_gettext.Gettext
-
-open Types
-open Utils
-
-open Output
-
-module RHVUpload = struct
- type poptions = string * string * string * string * string *
- string option * string option * bool * bool *
- string list option
-
- type t = int64 list * string list * string list *
- Python_script.script * Python_script.script *
- JSON.field list * string option * string option *
- string option * string * int list ref
-
- let to_string options =
- "-o rhv-upload" ^
- (match options.output_conn with
- | Some oc -> " -oc " ^ oc
- | None -> "") ^
- (match options.output_storage with
- | Some os -> " -os " ^ os
- | None -> "")
-
- let query_output_options () =
- printf (f_"Output options (-oo) which can be used with -o rhv-upload:
-
- -oo rhv-cafile=CA.PEM Set ca.pem certificate bundle filename.
- -oo rhv-cluster=CLUSTERNAME Set RHV cluster name.
- -oo rhv-proxy Connect via oVirt Engine proxy (default: false).
- -oo rhv-verifypeer[=true|false] Verify server identity (default: false).
-
-You can override the UUIDs of the disks, instead of using autogenerated UUIDs
-after their uploads (if you do, you must supply one for each disk):
-
- -oo rhv-disk-uuid=UUID Disk UUID
-")
-
- let rec parse_options options source =
- let output_conn =
- match options.output_conn with
- | None ->
- error (f_"-o rhv-upload: use -oc to point to the oVirt \
- or RHV server REST API URL, which is usually \
- https://servername/ovirt-engine/api")
- | Some oc -> oc in
- (* In theory we could make the password optional in future. *)
- let output_password =
- match options.output_password with
- | None ->
- error (f_"-o rhv-upload: output password file was not specified, \
- use -op to point to a file which contains the password \
- used to connect to the oVirt or RHV server")
- | Some op -> op in
- let output_storage =
- match options.output_storage with
- | None ->
- error (f_"-o rhv-upload: output storage was not specified, use -os");
- | Some os -> os in
-
- let rhv_cafile = ref None in
- let rhv_cluster = ref None in
- let rhv_direct = ref true in
- let rhv_verifypeer = ref false in
- let rhv_disk_uuids = ref None in
-
- List.iter (
- function
- | "rhv-cafile", v ->
- if !rhv_cafile <> None then
- error (f_"-o rhv-upload: -oo rhv-cafile set more than once");
- rhv_cafile := Some v
- | "rhv-cluster", v ->
- if !rhv_cluster <> None then
- error (f_"-o rhv-upload: -oo rhv-cluster set more than once");
- rhv_cluster := Some v
- | "rhv-direct", "" -> rhv_direct := true
- | "rhv-direct", v -> rhv_direct := bool_of_string v
- | "rhv-proxy", "" -> rhv_direct := false
- | "rhv-proxy", v -> rhv_direct := not (bool_of_string v)
- | "rhv-verifypeer", "" -> rhv_verifypeer := true
- | "rhv-verifypeer", v -> rhv_verifypeer := bool_of_string v
- | "rhv-disk-uuid", v ->
- if not (is_nonnil_uuid v) then
- error (f_"-o rhv-upload: invalid UUID for -oo rhv-disk-uuid");
- rhv_disk_uuids := Some (v :: (Option.value ~default:[] !rhv_disk_uuids))
- | k, _ ->
- error (f_"-o rhv-upload: unknown output option -oo %s") k
- ) options.output_options;
-
- let rhv_cafile = !rhv_cafile in
- let rhv_cluster = !rhv_cluster in
- let rhv_direct = !rhv_direct in
- let rhv_verifypeer = !rhv_verifypeer in
- let rhv_disk_uuids = Option.map List.rev !rhv_disk_uuids in
-
- let output_name = Option.value ~default:source.s_name options.output_name in
-
- (output_conn, options.output_format,
- output_password, output_name, output_storage,
- rhv_cafile, rhv_cluster, rhv_direct,
- rhv_verifypeer, rhv_disk_uuids)
-
- and is_nonnil_uuid uuid =
- let nil_uuid = "00000000-0000-0000-0000-000000000000" in
- let rex_uuid = lazy (
- let hex = "[a-fA-F0-9]" in
- let str = sprintf "^%s{8}-%s{4}-%s{4}-%s{4}-%s{12}$"
- hex hex hex hex hex in
- PCRE.compile str
- ) in
- if uuid = nil_uuid then false
- else PCRE.matches (Lazy.force rex_uuid) uuid
-
- let rec setup dir options source =
- error_if_disk_count_gt dir 23;
- let disks = get_disks dir in
- let output_conn, output_format,
- output_password, output_name, output_storage,
- rhv_cafile, rhv_cluster, rhv_direct,
- rhv_verifypeer, rhv_disk_uuids = options in
-
- (* We need nbdkit >= 1.22 for API_VERSION 2 and parallel threading model
- * in the python plugin.
- *)
- let nbdkit_min_version = (1, 22, 0) in
- let nbdkit_min_version_string = "1.22.0" in
-
- (* Check that the 'ovirtsdk4' Python module is available. *)
- let error_unless_ovirtsdk4_module_available () =
- let res = run_command [ Python_script.python; "-c";
- "import ovirtsdk4" ] in
- if res <> 0 then
- error (f_"the Python module ovirtsdk4 could not be loaded, \
- is it installed? See previous messages for problems.")
- in
-
- (* Check that nbdkit is available and new enough. *)
- let error_unless_nbdkit_working () =
- if not (Nbdkit.is_installed ()) then
- error (f_"nbdkit is not installed or not working. It is required \
- to use -o rhv-upload. See the virt-v2v-output-rhv(1) \
- manual.")
- in
-
- let error_unless_nbdkit_min_version config =
- let version = Nbdkit.version config in
- if version < nbdkit_min_version then
- error (f_"nbdkit is not new enough, you need to upgrade to nbdkit ≥ %s")
- nbdkit_min_version_string
- in
-
- (* Check that the python3 plugin is installed and working
- * and can load the plugin script.
- *)
- let error_unless_nbdkit_python_plugin_working plugin_script =
- let cmd = sprintf "nbdkit python %s --dump-plugin >/dev/null"
- (quote (Python_script.path plugin_script)) in
- debug "%s" cmd;
- if Sys.command cmd <> 0 then
- error (f_"nbdkit python plugin is not installed or not working. \
- It is required if you want to use -o rhv-upload.
-
-See also the virt-v2v-output-rhv(1) manual.");
- in
-
- (* Check that nbdkit was compiled with SELinux support (for the
- * --selinux-label option).
- *)
- let error_unless_nbdkit_compiled_with_selinux config =
- if have_selinux then (
- let selinux = try List.assoc "selinux" config with Not_found -> "no" in
- if selinux = "no" then
- 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.")
- )
- in
-
- Python_script.error_unless_python_interpreter_found ();
- error_unless_ovirtsdk4_module_available ();
- error_unless_nbdkit_working ();
- let config = Nbdkit.config () in
- error_unless_nbdkit_min_version config;
- error_unless_nbdkit_compiled_with_selinux config;
-
- (* Python code. *)
- 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 transfer_script =
- Python_script.create ~name:"rhv-upload-transfer.py"
- Output_rhv_upload_transfer_source.code in
- let finalize_script =
- Python_script.create ~name:"rhv-upload-finalize.py"
- Output_rhv_upload_finalize_source.code in
- let cancel_script =
- Python_script.create ~name:"rhv-upload-cancel.py"
- Output_rhv_upload_cancel_source.code in
- let createvm_script =
- Python_script.create ~name:"rhv-upload-createvm.py"
- Output_rhv_upload_createvm_source.code in
-
- error_unless_nbdkit_python_plugin_working plugin_script;
-
- (* JSON parameters which are invariant between disks. *)
- let json_params = [
- "verbose", JSON.Bool (verbose ());
-
- "output_conn", JSON.String output_conn;
- "output_password", JSON.String output_password;
- "output_storage", JSON.String output_storage;
- "rhv_cafile", json_optstring rhv_cafile;
- "rhv_cluster", JSON.String (Option.value ~default:"Default" rhv_cluster);
- "rhv_direct", JSON.Bool rhv_direct;
-
- (* The 'Insecure' flag seems to be a number with various possible
- * meanings, however we just set it to True/False.
- *
- * https://github.com/oVirt/ovirt-engine-sdk/blob/19aa7070b80e60a4cfd910448287aecf9083acbe/sdk/lib/ovirtsdk4/__init__.py#L395
- *)
- "insecure", JSON.Bool (not rhv_verifypeer);
- ] in
-
- (* nbdkit command line which is invariant between disks. *)
- let cmd = Nbdkit.create "python" in
- Nbdkit.add_arg cmd "script" (Python_script.path plugin_script);
-
- (* Match number of parallel coroutines in qemu-img *)
- Nbdkit.set_threads cmd 8;
-
- (* Python code prechecks. *)
- let json_params = match rhv_disk_uuids with
- | None -> json_params
- | Some uuids ->
- let ids = List.map (fun uuid -> JSON.String uuid) uuids in
- ("rhv_disk_uuids", JSON.List ids) :: json_params
- in
- let precheck_json = dir // "v2vprecheck.json" in
- let fd = Unix.openfile precheck_json [O_WRONLY; O_CREAT; O_TRUNC] 0o600 in
- if Python_script.run_command ~stdout_fd:fd
- precheck_script json_params [] <> 0 then
- error (f_"failed server prechecks, see earlier errors");
- if verbose () then
- debug "precheck output before parsing: %s"
- (read_whole_file precheck_json);
- let json = JSON_parser.json_parser_tree_parse_file precheck_json in
- debug "precheck output parsed as: %s"
- (JSON.string_of_doc ~fmt:JSON.Indented ["", json]);
- let rhv_storagedomain_uuid =
- Some (JSON_parser.object_get_string "rhv_storagedomain_uuid" json) in
- let rhv_cluster_uuid =
- Some (JSON_parser.object_get_string "rhv_cluster_uuid" json) in
- let rhv_cluster_cpu_architecture =
- Some (JSON_parser.object_get_string "rhv_cluster_cpu_architecture" json) in
-
- (* If the disk UUIDs were not provided, then generate them.
- * This is simpler than letting RHV generate them and trying
- * to read them back from RHV.
- *)
- let disk_uuids =
- match rhv_disk_uuids with
- | Some uuids ->
- let nr_disks = List.length disks in
- if List.length uuids <> nr_disks then
- error (f_"the number of -oo rhv-disk-uuid parameters passed on \
- the command line has to match the number of guest \
- disk images (for this guest: %d)") nr_disks;
- uuids
- | None -> List.map (fun _ -> uuidgen ()) disks in
-
- (* This will accumulate the list of transfer IDs from the transfer
- * script.
- *)
- let transfer_ids = ref [] in
-
- let rhv_cluster_name =
- match List.assoc "rhv_cluster" json_params with
- | JSON.String s -> s
- | _ -> assert false in
-
- let json_params =
- ("output_name", JSON.String output_name) :: json_params in
-
- (* Check that the VM does not exist. This can't run in #precheck because
- * we need to know the name of the virtual machine.
- *)
- if Python_script.run_command vmcheck_script json_params [] <> 0 then
- error (f_"failed vmchecks, see earlier errors");
-
- (* Cancel the transfer and delete disks.
- *
- * This ignores errors since the only time we are doing this is on
- * the failure path.
- *)
- let cancel transfer_ids disk_uuids =
- let ids = List.map (fun id -> JSON.String id) transfer_ids in
- let json_params = ("transfer_ids", JSON.List ids) :: json_params in
- let ids = List.map (fun uuid -> JSON.String uuid) disk_uuids in
- let json_params = ("disk_uuids", JSON.List ids) :: json_params in
- ignore (Python_script.run_command cancel_script json_params [])
- in
-
- (* Set up an at-exit handler to perform some cleanups.
- * - Kill nbdkit PIDs (only before finalization).
- * - Delete the orphan disks (only on conversion failure).
- *)
- let nbdkit_pids = ref [] in
- On_exit.f (
- fun () ->
- (* Kill the nbdkit PIDs. *)
- List.iter (
- fun pid ->
- try kill pid Sys.sigterm
- with exn -> debug "%s" (Printexc.to_string exn)
- ) !nbdkit_pids;
- nbdkit_pids := [];
-
- (* virt-v2v writes v2vdir/done on success only. *)
- let success = Sys.file_exists (dir // "done") in
- if not success then (
- if disk_uuids <> [] then
- cancel !transfer_ids disk_uuids
- )
- );
-
- (* Create an nbdkit instance for each disk and set the
- * target URI to point to the NBD socket.
- *)
- List.iter (
- fun ((i, size), uuid) ->
- let socket = sprintf "%s/out%d" dir i in
- On_exit.unlink socket;
-
- let disk_name = sprintf "%s-%03d" output_name i in
- let json_params =
- ("disk_name", JSON.String disk_name) :: json_params in
-
- let disk_format =
- match output_format with
- | "raw" as fmt -> fmt
- | "qcow2" as fmt -> fmt
- | _ ->
- error (f_"rhv-upload: -of %s: Only output format raw or qcow2 \
- is supported. If the input is in a different format \
- then force one of these output formats by adding \
- either -of raw or -of qcow2 on the command line.")
- output_format in
- let json_params =
- ("disk_format", JSON.String disk_format) :: json_params in
-
- let json_params =
- ("disk_size", JSON.Int size) :: json_params in
-
- let json_params =
- ("disk_uuid", JSON.String uuid) :: json_params in
-
- (* Write the JSON parameters to a file. *)
- let json_param_file = dir // sprintf "out.params%d.json" i in
- with_open_out
- json_param_file
- (fun chan -> output_string chan (JSON.string_of_doc json_params));
-
- (* Start the transfer. *)
- let transfer_json = dir // sprintf "v2vtransfer%d.json" i in
- let fd =
- Unix.openfile transfer_json [O_WRONLY; O_CREAT; O_TRUNC] 0o600 in
- if Python_script.run_command ~stdout_fd:fd
- transfer_script json_params [] <> 0 then
- error (f_"failed to start transfer, see earlier errors");
- if verbose () then
- debug "transfer output before parsing: %s"
- (read_whole_file transfer_json);
- let json = JSON_parser.json_parser_tree_parse_file transfer_json in
- debug "transfer output parsed as: %s"
- (JSON.string_of_doc ~fmt:JSON.Indented ["", json]);
- let destination_url =
- JSON_parser.object_get_string "destination_url" json in
- let transfer_id =
- JSON_parser.object_get_string "transfer_id" json in
- List.push_back transfer_ids transfer_id;
- let is_ovirt_host =
- JSON_parser.object_get_bool "is_ovirt_host" json in
-
- (* Create the nbdkit instance. *)
- Nbdkit.add_arg cmd "size" (Int64.to_string size);
- Nbdkit.add_arg cmd "url" destination_url;
- Option.iter (Nbdkit.add_arg cmd "cafile") rhv_cafile;
- if not rhv_verifypeer then
- Nbdkit.add_arg cmd "insecure" "true";
- if is_ovirt_host then
- Nbdkit.add_arg cmd "is_ovirt_host" "true";
- let _, pid = Nbdkit.run_unix socket cmd in
- List.push_front pid nbdkit_pids
- ) (List.combine disks disk_uuids);
-
- (* Stash some data we will need during finalization. *)
- let disk_sizes = List.map snd disks in
- let t = (disk_sizes : int64 list), disk_uuids, !transfer_ids,
- finalize_script, createvm_script, json_params,
- rhv_storagedomain_uuid, rhv_cluster_uuid,
- rhv_cluster_cpu_architecture, rhv_cluster_name, nbdkit_pids in
- t
-
- and json_optstring = function
- | Some s -> JSON.String s
- | None -> JSON.Null
-
- let finalize dir options t source inspect target_meta =
- let output_conn, output_format,
- output_password, output_name, output_storage,
- rhv_cafile, rhv_cluster, rhv_direct,
- rhv_verifypeer, rhv_disk_uuids = options in
- let disk_sizes, disk_uuids, transfer_ids,
- finalize_script, createvm_script, json_params,
- rhv_storagedomain_uuid, rhv_cluster_uuid,
- rhv_cluster_cpu_architecture, rhv_cluster_name,
- nbdkit_pids = t in
-
- (* Check the cluster CPU arch matches what we derived about the
- * guest during conversion.
- *)
- (match rhv_cluster_cpu_architecture with
- | None -> assert false
- | Some arch ->
- if arch <> target_meta.guestcaps.gcaps_arch then
- error (f_"the cluster %s does not support the architecture %s \
- but %s")
- rhv_cluster_name target_meta.guestcaps.gcaps_arch arch
- );
-
- (* We must kill all our nbdkit instances before finalizing the
- * transfer. See:
- * https://listman.redhat.com/archives/libguestfs/2022-February/msg00111.html
- *
- * We want to fail here if the kill fails because nbdkit
- * died already, as that would be unexpected.
- *)
- let () =
- let pids = !nbdkit_pids in
- List.iter (fun pid -> kill pid Sys.sigterm) pids;
- List.iter (fun pid -> ignore (waitpid [] pid)) pids;
- nbdkit_pids := [] (* Don't kill them again in the On_exit handler. *) in
-
- (* Finalize all the transfers. *)
- let json_params =
- let ids = List.map (fun id -> JSON.String id) transfer_ids in
- let json_params = ("transfer_ids", JSON.List ids) :: json_params in
- let ids = List.map (fun uuid -> JSON.String uuid) disk_uuids in
- let json_params = ("disk_uuids", JSON.List ids) :: json_params in
- json_params in
- if Python_script.run_command finalize_script json_params [] <> 0 then
- error (f_"failed to finalize the transfers, see earlier errors");
-
- (* The storage domain UUID. *)
- let sd_uuid =
- match rhv_storagedomain_uuid with
- | None -> assert false
- | Some uuid -> uuid in
-
- (* The volume and VM UUIDs are made up. *)
- let vol_uuids = List.map (fun _ -> uuidgen ()) disk_sizes
- and vm_uuid = uuidgen () in
-
- (* Create the metadata. *)
- let ovf =
- Create_ovf.create_ovf source inspect target_meta disk_sizes
- Sparse output_format output_name
- sd_uuid disk_uuids vol_uuids dir vm_uuid OVirt in
- let ovf = DOM.doc_to_string ovf in
-
- let json_params =
- match rhv_cluster_uuid with
- | None -> assert false
- | Some uuid -> ("rhv_cluster_uuid", JSON.String uuid) :: json_params in
-
- let ovf_file = dir // "vm.ovf" in
- with_open_out ovf_file (fun chan -> output_string chan ovf);
- if Python_script.run_command createvm_script json_params [ovf_file] <> 0
- then
- error (f_"failed to create virtual machine, see earlier errors")
-
- (* The imageio server has high overhead per request. Using 4 MiB
- * request size is 1.8x times faster compared with nbdcopy default
- * request size (256k).
- *)
- let request_size = Some (4*1024*1024)
-end
diff --git a/output/output_rhv_upload.mli b/output/output_rhv_upload.mli
deleted file mode 100644
index 35457596..00000000
--- a/output/output_rhv_upload.mli
+++ /dev/null
@@ -1,21 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2009-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.
- *)
-
-(** [-o rhv-upload] output mode. *)
-
-module RHVUpload : Output.OUTPUT
diff --git a/output/output_rhv_upload_cancel_source.mli b/output/output_rhv_upload_cancel_source.mli
deleted file mode 100644
index aa33bc54..00000000
--- a/output/output_rhv_upload_cancel_source.mli
+++ /dev/null
@@ -1,19 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2019 Red Hat Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *)
-
-val code : string
diff --git a/output/output_rhv_upload_createvm_source.mli b/output/output_rhv_upload_createvm_source.mli
deleted file mode 100644
index c1bafa15..00000000
--- a/output/output_rhv_upload_createvm_source.mli
+++ /dev/null
@@ -1,19 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2018 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.
- *)
-
-val code : string
diff --git a/output/output_rhv_upload_finalize_source.mli b/output/output_rhv_upload_finalize_source.mli
deleted file mode 100644
index aa33bc54..00000000
--- a/output/output_rhv_upload_finalize_source.mli
+++ /dev/null
@@ -1,19 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2019 Red Hat Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *)
-
-val code : string
diff --git a/output/output_rhv_upload_plugin_source.mli b/output/output_rhv_upload_plugin_source.mli
deleted file mode 100644
index c1bafa15..00000000
--- a/output/output_rhv_upload_plugin_source.mli
+++ /dev/null
@@ -1,19 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2018 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.
- *)
-
-val code : string
diff --git a/output/output_rhv_upload_precheck_source.mli b/output/output_rhv_upload_precheck_source.mli
deleted file mode 100644
index aa33bc54..00000000
--- a/output/output_rhv_upload_precheck_source.mli
+++ /dev/null
@@ -1,19 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2019 Red Hat Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *)
-
-val code : string
diff --git a/output/output_rhv_upload_transfer_source.mli b/output/output_rhv_upload_transfer_source.mli
deleted file mode 100644
index aa33bc54..00000000
--- a/output/output_rhv_upload_transfer_source.mli
+++ /dev/null
@@ -1,19 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2019 Red Hat Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *)
-
-val code : string
diff --git a/output/output_rhv_upload_vmcheck_source.mli b/output/output_rhv_upload_vmcheck_source.mli
deleted file mode 100644
index c1bafa15..00000000
--- a/output/output_rhv_upload_vmcheck_source.mli
+++ /dev/null
@@ -1,19 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2018 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.
- *)
-
-val code : string
diff --git a/output/output_vdsm.ml b/output/output_vdsm.ml
deleted file mode 100644
index 3052fb9c..00000000
--- a/output/output_vdsm.ml
+++ /dev/null
@@ -1,237 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2009-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.
- *)
-
-open Printf
-open Unix
-
-open Std_utils
-open Tools_utils
-open Common_gettext.Gettext
-
-open Types
-open Utils
-
-open Output
-
-module VDSM = struct
- type poptions = Types.output_allocation * string * string * string *
- string list * string list * string * string *
- string * Create_ovf.ovf_flavour
-
- type t = string * string * int64 list
-
- let to_string options = "-o vdsm"
-
- let query_output_options () =
- let ovf_flavours_str = String.concat "|" Create_ovf.ovf_flavours in
-
- printf (f_"Output options (-oo) which can be used with -o vdsm:
-
- -oo vdsm-compat=0.10|1.1 Write qcow2 with compat=0.10|1.1
- (default: 0.10)
- -oo vdsm-vm-uuid=UUID VM UUID (required)
- -oo vdsm-ovf-output=DIR OVF metadata directory (required)
- -oo vdsm-ovf-flavour=%s
- Set the type of generated OVF (default: rhvexp)
-
-For each disk you must supply one of each of these options:
-
- -oo vdsm-image-uuid=UUID Image directory UUID
- -oo vdsm-vol-uuid=UUID Disk volume UUID
-") ovf_flavours_str
-
- let parse_options options source =
- if options.output_password <> None then
- error_option_cannot_be_used_in_output_mode "vdsm" "-op";
-
- let vm_uuid = ref None in
- let ovf_output = ref None in (* default "." *)
- let compat = ref "0.10" in
- let ovf_flavour = ref Create_ovf.RHVExportStorageDomain in
- let image_uuids = ref [] in
- let vol_uuids = ref [] in
-
- List.iter (
- function
- | "vdsm-compat", "0.10" -> compat := "0.10"
- | "vdsm-compat", "1.1" -> compat := "1.1"
- | "vdsm-compat", v ->
- error (f_"-o vdsm: unknown vdsm-compat level %s") v
- | "vdsm-vm-uuid", v ->
- if !vm_uuid <> None then
- error (f_"-o vdsm: -oo vdsm-vm-uuid set more than once");
- vm_uuid := Some v;
- | "vdsm-ovf-output", v ->
- if !ovf_output <> None then
- error (f_"-o vdsm: -oo vdsm-ovf-output set more than once");
- ovf_output := Some v;
- | "vdsm-ovf-flavour", v ->
- ovf_flavour := Create_ovf.ovf_flavour_of_string v
- | "vdsm-image-uuid", v ->
- List.push_front v image_uuids
- | "vdsm-vol-uuid", v ->
- List.push_front v vol_uuids
- | k, _ ->
- error (f_"-o vdsm: unknown output option -oo %s") k
- ) options.output_options;
-
- let compat = !compat in
- let image_uuids = List.rev !image_uuids in
- let vol_uuids = List.rev !vol_uuids in
- if image_uuids = [] || vol_uuids = [] then
- error (f_"-o vdsm: either -oo vdsm-vol-uuid or \
- -oo vdsm-vm-uuid was not specified");
- let vm_uuid =
- match !vm_uuid with
- | None ->
- error (f_"-o vdsm: -oo vdsm-image-uuid was not specified")
- | Some uuid -> uuid in
- let ovf_output = Option.value ~default:"." !ovf_output in
- let ovf_flavour = !ovf_flavour in
-
- (* -os must be set, but at this point we cannot check it. *)
- let output_storage =
- match options.output_storage with
- | None -> error (f_"-o vdsm: -os option was not specified")
- | Some d when not (is_directory d) ->
- error (f_"-os %s: output directory does not exist \
- or is not a directory") d
- | Some d -> d in
-
- let output_name = Option.value ~default:source.s_name options.output_name in
-
- (options.output_alloc, options.output_format,
- output_name, output_storage,
- image_uuids, vol_uuids, vm_uuid, ovf_output,
- compat, ovf_flavour)
-
- let setup dir options source =
- error_if_disk_count_gt dir 23;
- let disks = get_disks dir in
- let output_alloc, output_format,
- output_name, output_storage,
- image_uuids, vol_uuids, vm_uuid, ovf_output,
- compat, ovf_flavour = options in
-
- if List.length image_uuids <> List.length disks ||
- List.length vol_uuids <> List.length disks then
- error (f_"the number of -oo vdsm-image-uuid and -oo vdsm-vol-uuid \
- parameters passed on the command line has to match the \
- number of guest disk images (for this guest: %d)")
- (List.length disks);
-
- let dd_mp, dd_uuid =
- let fields =
- String.nsplit "/" output_storage in (* ... "data-center" "UUID" *)
- let fields = List.rev fields in (* "UUID" "data-center" ... *)
- let fields = List.dropwhile ((=) "") fields in
- match fields with
- | uuid :: rest when String.length uuid = 36 ->
- let mp = String.concat "/" (List.rev rest) in
- mp, uuid
- | _ ->
- error (f_"vdsm: invalid -os parameter \
- does not contain a valid UUID: %s")
- output_storage in
-
- debug "VDSM: DD mountpoint: %s\nVDSM: DD UUID: %s" dd_mp dd_uuid;
-
- (* Note that VDSM has to create all these directories. *)
- let images_dir = dd_mp // dd_uuid // "images" in
- List.iter (
- fun image_uuid ->
- let d = images_dir // image_uuid in
- if not (is_directory d) then
- error (f_"image directory (%s) does not exist or is not a directory")
- d
- ) image_uuids;
-
- (* Note that VDSM has to create this directory too. *)
- if not (is_directory ovf_output) then
- error (f_"OVF (metadata) directory (%s) does not exist or \
- is not a directory")
- ovf_output;
-
- debug "VDSM: OVF (metadata) directory: %s" ovf_output;
-
- (* The final directory structure should look like this:
- * /<MP>/<ESD_UUID>/images/
- * <IMAGE_UUID_1>/<VOL_UUID_1> # first disk
- * <IMAGE_UUID_1>/<VOL_UUID_1>.meta # first disk
- * <IMAGE_UUID_2>/<VOL_UUID_2> # second disk
- * <IMAGE_UUID_2>/<VOL_UUID_2>.meta # second disk
- * <IMAGE_UUID_3>/<VOL_UUID_3> # etc
- * <IMAGE_UUID_3>/<VOL_UUID_3>.meta #
- *)
-
- (* Create the target filenames. *)
- let filenames =
- List.map (
- fun (image_uuid, vol_uuid) ->
- let filename = images_dir // image_uuid // vol_uuid in
- debug "VDSM: disk: %s" filename;
- filename
- ) (List.combine image_uuids vol_uuids) in
-
- (* Generate the .meta files associated with each volume. *)
- let sizes = List.map snd disks in
- let metas =
- Create_ovf.create_meta_files output_alloc output_format
- dd_uuid image_uuids sizes in
- List.iter (
- fun (filename, meta) ->
- let meta_filename = filename ^ ".meta" in
- with_open_out meta_filename (fun chan -> output_string chan meta)
- ) (List.combine filenames metas);
-
- (* Set up the NBD servers. *)
- List.iter (
- fun ((i, size), filename) ->
- let socket = sprintf "%s/out%d" dir i in
- On_exit.unlink socket;
-
- (* Create the actual output disk. *)
- output_to_local_file output_alloc output_format filename size socket
- ) (List.combine disks filenames);
-
- (* Save parameters since we need them during finalization. *)
- let t = dd_mp, dd_uuid, sizes in
- t
-
- let finalize dir options t source inspect target_meta =
- let output_alloc, output_format,
- output_name, output_storage,
- image_uuids, vol_uuids, vm_uuid, ovf_output,
- compat, ovf_flavour = options in
- let dd_mp, dd_uuid, sizes = t in
-
- (* Create the metadata. *)
- let ovf = Create_ovf.create_ovf source inspect target_meta sizes
- output_alloc output_format output_name dd_uuid
- image_uuids
- vol_uuids
- dir
- vm_uuid
- ovf_flavour in
-
- (* Write it to the metadata file. *)
- let file = ovf_output // vm_uuid ^ ".ovf" in
- with_open_out file (fun chan -> DOM.doc_to_chan chan ovf)
-
- let request_size = None
-end
diff --git a/output/output_vdsm.mli b/output/output_vdsm.mli
deleted file mode 100644
index 2260d7e6..00000000
--- a/output/output_vdsm.mli
+++ /dev/null
@@ -1,21 +0,0 @@
-(* virt-v2v
- * Copyright (C) 2009-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.
- *)
-
-(** [-o vdsm] output mode. *)
-
-module VDSM : Output.OUTPUT
diff --git a/output/rhv-upload-cancel.py b/output/rhv-upload-cancel.py
deleted file mode 100644
index b36e1904..00000000
--- a/output/rhv-upload-cancel.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# -*- python -*-
-# oVirt or RHV upload cancel used by virt-v2v -o rhv-upload
-# Copyright (C) 2019-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.
-
-import json
-import logging
-import sys
-from contextlib import closing
-from urllib.parse import urlparse, urlunparse
-
-import ovirtsdk4 as sdk
-import ovirtsdk4.types as types
-
-
-def debug(s):
- if params['verbose']:
- print(s, file=sys.stderr)
- sys.stderr.flush()
-
-
-# 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.
-params = None
-
-if len(sys.argv) != 2:
- raise RuntimeError("incorrect number of parameters")
-
-# Parameters are passed in via a JSON document.
-with open(sys.argv[1], 'r') as fp:
- params = json.load(fp)
-
-# What is passed in is a password file, read the actual password.
-with open(params['output_password'], 'r') as fp:
- output_password = fp.read()
-output_password = output_password.rstrip()
-
-# Parse out the username from the output_conn URL.
-parsed = urlparse(params['output_conn'])
-username = parsed.username or "admin@internal"
-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname
-
-# Connect to the server.
-connection = sdk.Connection(
- url=urlunparse(parsed._replace(netloc=netloc)),
- username=username,
- password=output_password,
- ca_file=params['rhv_cafile'],
- log=logging.getLogger(),
- insecure=params['insecure'],
-)
-
-with closing(connection):
- system_service = connection.system_service()
- image_transfers_service = system_service.image_transfers_service()
-
- # Try to cancel the transfers. This should delete the associated disk.
- for id in params['transfer_ids']:
- try:
- transfer_service = \
- image_transfers_service.image_transfer_service(id)
- transfer_service.cancel()
- except sdk.NotFoundError:
- debug("unexpected error: transfer id %s not found" % id)
- except Exception:
- if params['verbose']:
- traceback.print_exc()
-
- disks_service = system_service.disks_service()
-
- # In case we didn't associate a disk with a transfer and as a last
- # resort, delete the disk too.
- for uuid in params['disk_uuids']:
- try:
- disk_service = disks_service.disk_service(uuid)
- disk_service.remove()
- except (sdk.NotFoundError, sdk.Error):
- # We expect these exceptions so ignore them.
- pass
- except Exception:
- if params['verbose']:
- traceback.print_exc()
diff --git a/output/rhv-upload-createvm.py b/output/rhv-upload-createvm.py
deleted file mode 100644
index 9af2c167..00000000
--- a/output/rhv-upload-createvm.py
+++ /dev/null
@@ -1,137 +0,0 @@
-# -*- python -*-
-# oVirt or RHV upload create VM used by virt-v2v -o rhv-upload
-# Copyright (C) 2018 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.
-
-import json
-import logging
-import sys
-import time
-import uuid
-
-from urllib.parse import urlparse, urlunparse
-
-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.
-params = None
-ovf = None # OVF file
-
-if len(sys.argv) != 3:
- raise RuntimeError("incorrect number of parameters")
-
-# Parameters are passed in via a JSON document.
-with open(sys.argv[1], 'r') as fp:
- params = json.load(fp)
-
-# What is passed in is a password file, read the actual password.
-with open(params['output_password'], 'r') as fp:
- output_password = fp.read()
-output_password = output_password.rstrip()
-
-# Read the OVF document.
-with open(sys.argv[2], 'r') as fp:
- ovf = fp.read()
-
-# Parse out the username from the output_conn URL.
-parsed = urlparse(params['output_conn'])
-username = parsed.username or "admin@internal"
-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname
-
-# Connect to the server.
-connection = sdk.Connection(
- url=urlunparse(parsed._replace(netloc=netloc)),
- username=username,
- password=output_password,
- ca_file=params['rhv_cafile'],
- log=logging.getLogger(),
- insecure=params['insecure'],
-)
-
-system_service = connection.system_service()
-
-# Get the cluster.
-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(
- cluster=cluster,
- initialization=types.Initialization(
- configuration=types.Configuration(
- type=types.ConfigurationType.OVA,
- 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)
diff --git a/output/rhv-upload-finalize.py b/output/rhv-upload-finalize.py
deleted file mode 100644
index 12fd39ec..00000000
--- a/output/rhv-upload-finalize.py
+++ /dev/null
@@ -1,174 +0,0 @@
-# -*- python -*-
-# oVirt or RHV upload finalize used by virt-v2v -o rhv-upload
-# Copyright (C) 2018-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.
-
-import json
-import logging
-import sys
-import time
-from urllib.parse import urlparse, urlunparse
-
-import ovirtsdk4 as sdk
-import ovirtsdk4.types as types
-
-# Timeout to wait for oVirt disks to change status, or the transfer
-# object to finish initializing [seconds].
-timeout = 5 * 60
-
-
-def debug(s):
- if params['verbose']:
- print(s, file=sys.stderr)
- sys.stderr.flush()
-
-
-def finalize_transfer(connection, transfer_id, disk_id):
- """
- Finalize a transfer, making the transfer disk available.
-
- 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.
-
- 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.
-
- 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
- - http://ovirt.github.io/ovirt-engine-sdk/master/types.m.html#ovirtsdk4.types.ImageTransfer
- """
- debug("finalizing transfer %s" % transfer_id)
- transfer_service = (connection.system_service()
- .image_transfers_service()
- .image_transfer_service(transfer_id))
-
- start = time.monotonic()
-
- transfer_service.finalize()
-
- while True:
- time.sleep(1)
- try:
- transfer = transfer_service.get()
- except sdk.NotFoundError:
- # 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.
-
- debug("transfer %s was removed, checking disk %s status"
- % (transfer_id, disk_id))
-
- disk_service = (connection.system_service()
- .disks_service()
- .disk_service(disk_id))
-
- 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
-
- raise RuntimeError(
- "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.monotonic() > 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.monotonic() - start))
-
-
-# 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.
-params = None
-
-if len(sys.argv) != 2:
- raise RuntimeError("incorrect number of parameters")
-
-# Parameters are passed in via a JSON document.
-with open(sys.argv[1], 'r') as fp:
- params = json.load(fp)
-
-# What is passed in is a password file, read the actual password.
-with open(params['output_password'], 'r') as fp:
- output_password = fp.read()
-output_password = output_password.rstrip()
-
-# Parse out the username from the output_conn URL.
-parsed = urlparse(params['output_conn'])
-username = parsed.username or "admin@internal"
-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname
-
-# Connect to the server.
-connection = sdk.Connection(
- url=urlunparse(parsed._replace(netloc=netloc)),
- username=username,
- password=output_password,
- ca_file=params['rhv_cafile'],
- log=logging.getLogger(),
- insecure=params['insecure'],
-)
-
-# Finalize all the transfers.
-for (transfer_id, disk_id) in zip(params['transfer_ids'], params['disk_uuids']):
- finalize_transfer(connection, transfer_id, disk_id)
-
-connection.close()
diff --git a/output/rhv-upload-plugin.py b/output/rhv-upload-plugin.py
deleted file mode 100644
index 8bc79a4a..00000000
--- a/output/rhv-upload-plugin.py
+++ /dev/null
@@ -1,525 +0,0 @@
-# -*- python -*-
-# oVirt or RHV upload nbdkit plugin used by virt-v2v -o rhv-upload
-# Copyright (C) 2018-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.
-
-import json
-import queue
-import socket
-import ssl
-import threading
-import time
-
-from contextlib import contextmanager
-from http.client import HTTPSConnection, HTTPConnection
-from urllib.parse import urlparse
-
-import nbdkit
-
-# Using version 2 supporting the buffer protocol for better performance.
-API_VERSION = 2
-
-# Maximum number of connection to imageio server. Based on testing with imageio
-# client, this give best performance.
-MAX_CONNECTIONS = 4
-
-# Maximum idle time allowed for imageio connections.
-IDLE_TIMEOUT = 30
-
-# Required parameters.
-size = None
-url = None
-
-# Optional parameters.
-cafile = None
-insecure = False
-is_ovirt_host = False
-
-# List of options read from imageio server.
-options = None
-
-# Pool of HTTP connections.
-pool = None
-
-# Set when plugin is cleaning up.
-done = threading.Event()
-
-# Set when periodic flush request fails.
-pool_error = None
-
-
-# Parse parameters.
-def config(key, value):
- global cafile, url, is_ovirt_host, insecure, size
-
- if key == "cafile":
- cafile = value
- elif key == "insecure":
- insecure = value.lower() in ['true', '1']
- elif key == "is_ovirt_host":
- is_ovirt_host = value.lower() in ['true', '1']
- elif key == "size":
- size = int(value)
- elif key == "url":
- url = urlparse(value)
- else:
- raise RuntimeError("unknown configuration key '%s'" % key)
-
-
-def config_complete():
- # These parameters are required.
- if url is None:
- raise RuntimeError("url parameter was not set")
- if size is None:
- raise RuntimeError("size parameter was not set")
-
-
-def after_fork():
- global options, pool
-
- http = create_http(url)
- options = get_options(http, url)
- http.close()
-
- nbdkit.debug("imageio features: flush=%(can_flush)r "
- "zero=%(can_zero)r unix_socket=%(unix_socket)r "
- "max_readers=%(max_readers)r max_writers=%(max_writers)r"
- % options)
-
- pool = create_http_pool(url, options)
-
- t = threading.Thread(target=pool_keeper, name="poolkeeper")
- t.daemon = True
- t.start()
-
-
-# This function is not actually defined before nbdkit 1.28, but it
-# doesn't particularly matter if we don't close the pool because
-# clients should call flush().
-def cleanup():
- nbdkit.debug("cleaning up")
- done.set()
- close_http_pool(pool)
-
-
-def thread_model():
- """
- Using parallel model to speed up transfer with multiple connections to
- imageio server.
- """
- return nbdkit.THREAD_MODEL_PARALLEL
-
-
-def open(readonly):
- return 1
-
-
-def can_trim(h):
- return False
-
-
-def can_flush(h):
- return options['can_flush']
-
-
-def can_fua(h):
- # imageio flush feature is is compatible with NBD_CMD_FLAG_FUA.
- return options['can_flush']
-
-
-def can_multi_conn(h):
- # We can always handle multiple connections, and the number of NBD
- # connections is independent of the number of HTTP clients in the
- # pool.
- return True
-
-
-def get_size(h):
- return size
-
-
-# Any unexpected HTTP response status from the server will end up calling this
-# function which logs the full error, and raises a RuntimeError exception.
-def request_failed(r, msg):
- status = r.status
- reason = r.reason
- try:
- body = r.read()
- except EnvironmentError as e:
- body = "(Unable to read response body: %s)" % e
-
- # Log the full error if we're verbose.
- nbdkit.debug("unexpected response from imageio server:")
- nbdkit.debug(msg)
- nbdkit.debug("%d: %s" % (status, reason))
- nbdkit.debug(body)
-
- # Only a short error is included in the exception.
- raise RuntimeError("%s: %d %s: %r" % (msg, status, reason, body[:200]))
-
-
-# For documentation see:
-# https://github.com/oVirt/ovirt-imageio/blob/master/docs/random-io.md
-# For examples of working code to read/write from the server, see:
-# https://github.com/oVirt/ovirt-imageio/blob/master/daemon/test/server_test.py
-def pread(h, buf, offset, flags):
- count = len(buf)
- headers = {"Range": "bytes=%d-%d" % (offset, offset + count - 1)}
-
- with http_context(pool) as http:
- http.request("GET", url.path, headers=headers)
-
- r = http.getresponse()
- # 206 = HTTP Partial Content.
- if r.status != 206:
- request_failed(r,
- "could not read sector offset %d size %d" %
- (offset, count))
-
- content_length = int(r.getheader("content-length"))
- if content_length != count:
- # Should never happen.
- request_failed(r,
- "unexpected Content-Length offset %d size %d got %d" %
- (offset, count, content_length))
-
- with memoryview(buf) as view:
- got = 0
- while got < count:
- n = r.readinto(view[got:])
- if n == 0:
- request_failed(r,
- "short read offset %d size %d got %d" %
- (offset, count, got))
- got += n
-
-
-def pwrite(h, buf, offset, flags):
- count = len(buf)
-
- flush = "y" if (options['can_flush'] and (flags & nbdkit.FLAG_FUA)) else "n"
-
- with http_context(pool) as http:
- http.putrequest("PUT", url.path + "?flush=" + flush)
- # The oVirt server only uses the first part of the range, and the
- # content-length.
- http.putheader("Content-Range", "bytes %d-%d/*" %
- (offset, offset + count - 1))
- http.putheader("Content-Length", str(count))
- http.endheaders()
-
- try:
- http.send(buf)
- except BrokenPipeError:
- pass
-
- r = http.getresponse()
- if r.status != 200:
- request_failed(r,
- "could not write sector offset %d size %d" %
- (offset, count))
-
- r.read()
-
-
-def zero(h, count, offset, flags):
- # Unlike the trim and flush calls, there is no 'can_zero' method
- # so nbdkit could call this even if the server doesn't support
- # zeroing. If this is the case we must emulate.
- if not options['can_zero']:
- emulate_zero(h, count, offset, flags)
- return
-
- flush = bool(options['can_flush'] and (flags & nbdkit.FLAG_FUA))
-
- # Construct the JSON request for zeroing.
- buf = json.dumps({'op': "zero",
- 'offset': offset,
- 'size': count,
- 'flush': flush}).encode()
-
- headers = {"Content-Type": "application/json",
- "Content-Length": str(len(buf))}
-
- with http_context(pool) as http:
- http.request("PATCH", url.path, body=buf, headers=headers)
-
- r = http.getresponse()
- if r.status != 200:
- request_failed(r,
- "could not zero sector offset %d size %d" %
- (offset, count))
-
- r.read()
-
-
-def emulate_zero(h, count, offset, flags):
- flush = "y" if (options['can_flush'] and (flags & nbdkit.FLAG_FUA)) else "n"
-
- with http_context(pool) as http:
- http.putrequest("PUT", url.path + "?flush=" + flush)
- http.putheader("Content-Range",
- "bytes %d-%d/*" % (offset, offset + count - 1))
- http.putheader("Content-Length", str(count))
- http.endheaders()
-
- try:
- buf = bytearray(128 * 1024)
- while count > len(buf):
- http.send(buf)
- count -= len(buf)
- http.send(memoryview(buf)[:count])
- except BrokenPipeError:
- pass
-
- r = http.getresponse()
- if r.status != 200:
- request_failed(r,
- "could not write zeroes offset %d size %d" %
- (offset, count))
-
- r.read()
-
-
-def flush(h, flags):
- if pool_error:
- raise pool_error
-
- # Wait until all inflight requests are completed, and send a flush
- # request for all imageio connections.
- locked = []
-
- # Lock the pool by taking all connections out.
- while len(locked) < pool.maxsize:
- locked.append(pool.get())
-
- try:
- for item in locked:
- send_flush(item.http)
- item.last_used = time.monotonic()
- finally:
- # Unlock the pool by puting the connection back.
- for item in locked:
- pool.put(item)
-
-
-def send_flush(http):
- # Construct the JSON request for flushing.
- buf = json.dumps({'op': "flush"}).encode()
-
- headers = {"Content-Type": "application/json",
- "Content-Length": str(len(buf))}
-
- http.request("PATCH", url.path, body=buf, headers=headers)
-
- r = http.getresponse()
- if r.status != 200:
- request_failed(r, "could not flush")
-
- r.read()
-
-
-# Modify http.client.HTTPConnection to work over a Unix domain socket.
-# Derived from uhttplib written by Erik van Zijst under an MIT license.
-# (https://pypi.org/project/uhttplib/)
-# Ported to Python 3 by Irit Goihman.
-class UnixHTTPConnection(HTTPConnection):
- def __init__(self, path, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
- self.path = path
- HTTPConnection.__init__(self, "localhost", timeout=timeout)
-
- def connect(self):
- self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
- if self.timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
- self.sock.settimeout(timeout)
- self.sock.connect(self.path)
-
-
-class PoolItem:
-
- def __init__(self, http):
- self.http = http
- self.last_used = None
-
-
-# Connection pool.
-def create_http_pool(url, options):
- count = min(options["max_readers"],
- options["max_writers"],
- MAX_CONNECTIONS)
-
- nbdkit.debug("creating http pool connections=%d" % count)
-
- unix_socket = options["unix_socket"] if is_ovirt_host else None
-
- pool = queue.Queue(count)
-
- for i in range(count):
- http = create_http(url, unix_socket=unix_socket)
- pool.put(PoolItem(http))
-
- return pool
-
-
-def pool_keeper():
- """
- Thread flushing idle connections, keeping them alive.
-
- If a connection does not send any request for 60 seconds, imageio
- server closes the connection. Recovering from closed connection is
- hard and unsafe, so this thread ensure that connections never
- becomes idle by sending a flush request if the connection is idle
- for too much time.
-
- In normal conditions, all connections are busy most of the time, so
- the keeper will find no idle connections. If there short delays in
- nbdcopy, the keeper will find some idle connections, but will
- quickly return them back to the pool. In the pathological case when
- nbdcopy is blocked for 3 minutes on vddk input, the keeper will send
- a flush request on all connections every ~30 seconds, until nbdcopy
- starts communicating again.
- """
- global pool_error
-
- nbdkit.debug("poolkeeper: started")
-
- while not done.wait(IDLE_TIMEOUT / 2):
- idle = []
-
- while True:
- try:
- idle.append(pool.get_nowait())
- except queue.Empty:
- break
-
- if idle:
- now = time.monotonic()
- for item in idle:
- if item.last_used and now - item.last_used > IDLE_TIMEOUT:
- nbdkit.debug("poolkeeper: flushing idle connection")
- try:
- send_flush(item.http)
- item.last_used = now
- except Exception as e:
- # We will report this error on the next request.
- pool_error = e
- item.last_used = None
-
- pool.put(item)
-
- nbdkit.debug("poolkeeper: stopped")
-
-
-@contextmanager
-def http_context(pool):
- """
- Context manager yielding an imageio http connection from the pool. Blocks
- until a connection is available.
- """
- if pool_error:
- raise pool_error
-
- item = pool.get()
- try:
- yield item.http
- finally:
- item.last_used = time.monotonic()
- pool.put(item)
-
-
-def close_http_pool(pool):
- """
- Wait until all inflight requests are done, close all connections and remove
- them from the pool.
-
- No request can be served by the pool after this call.
- """
- nbdkit.debug("closing http pool")
-
- locked = []
-
- while len(locked) < pool.maxsize:
- locked.append(pool.get())
-
- for item in locked:
- item.http.close()
-
-
-def create_http(url, unix_socket=None):
- """
- Create http connection for transfer url.
-
- Returns HTTPConnection.
- """
- if unix_socket:
- nbdkit.debug("creating unix http connection socket=%r" % unix_socket)
- try:
- return UnixHTTPConnection(unix_socket)
- except Exception as e:
- # Very unlikely, but we can recover by using https.
- nbdkit.debug("cannot create unix socket connection: %s" % e)
-
- if url.scheme == "https":
- context = \
- ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH,
- cafile=cafile)
- if insecure:
- context.check_hostname = False
- context.verify_mode = ssl.CERT_NONE
-
- nbdkit.debug("creating https connection host=%s port=%s" %
- (url.hostname, url.port))
- return HTTPSConnection(url.hostname, url.port, context=context)
- elif url.scheme == "http":
- nbdkit.debug("creating http connection host=%s port=%s" %
- (url.hostname, url.port))
- return HTTPConnection(url.hostname, url.port)
- else:
- raise RuntimeError("unknown URL scheme (%s)" % url.scheme)
-
-
-def get_options(http, url):
- """
- Send OPTIONS request to imageio server and return options dict.
- """
- http.request("OPTIONS", url.path)
- r = http.getresponse()
- data = r.read()
-
- if r.status == 200:
- j = json.loads(data)
- features = j["features"]
- return {
- "can_flush": "flush" in features,
- "can_zero": "zero" in features,
- "unix_socket": j.get('unix_socket'),
- "max_readers": j.get("max_readers", 1),
- "max_writers": j.get("max_writers", 1),
- }
-
- elif r.status == 405 or r.status == 204:
- # Old imageio servers returned either 405 Method Not Allowed or
- # 204 No Content (with an empty body).
- return {
- "can_flush": False,
- "can_zero": False,
- "unix_socket": None,
- "max_readers": 1,
- "max_writers": 1,
- }
- else:
- raise RuntimeError("could not use OPTIONS request: %d: %s" %
- (r.status, r.reason))
diff --git a/output/rhv-upload-precheck.py b/output/rhv-upload-precheck.py
deleted file mode 100644
index 0bbb738d..00000000
--- a/output/rhv-upload-precheck.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# -*- python -*-
-# oVirt or RHV pre-upload checks used by virt-v2v -o rhv-upload
-# Copyright (C) 2018-2020 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.
-
-import json
-import logging
-import re
-import sys
-
-from urllib.parse import urlparse, urlunparse
-
-import ovirtsdk4 as sdk
-import ovirtsdk4.types as types
-
-# 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.
-params = None
-
-if len(sys.argv) != 2:
- raise RuntimeError("incorrect number of parameters")
-
-# Parameters are passed in via a JSON document.
-with open(sys.argv[1], 'r') as fp:
- params = json.load(fp)
-
-# What is passed in is a password file, read the actual password.
-with open(params['output_password'], 'r') as fp:
- output_password = fp.read()
-output_password = output_password.rstrip()
-
-# Parse out the username from the output_conn URL.
-parsed = urlparse(params['output_conn'])
-username = parsed.username or "admin@internal"
-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname
-
-# Check the storage domain name is valid
-# (https://bugzilla.redhat.com/show_bug.cgi?id=1986386#c1)
-# Also this means it cannot contain spaces or glob symbols, so
-# the search below is valid.
-output_storage = params['output_storage']
-if not re.match('^[-a-zA-Z0-9_]+$', output_storage):
- raise RuntimeError("The storage domain (-os) parameter %s is not valid" %
- output_storage)
-
-# Connect to the server.
-connection = sdk.Connection(
- url=urlunparse(parsed._replace(netloc=netloc)),
- username=username,
- password=output_password,
- ca_file=params['rhv_cafile'],
- log=logging.getLogger(),
- insecure=params['insecure'],
-)
-
-system_service = connection.system_service()
-
-# Check whether there is a datacenter for the specified storage.
-data_centers = system_service.data_centers_service().list(
- search='storage.name=%s' % output_storage,
- case_sensitive=True,
-)
-if len(data_centers) == 0:
- storage_domains = system_service.storage_domains_service().list(
- search='name=%s' % output_storage,
- case_sensitive=True,
- )
- if len(storage_domains) == 0:
- # The storage domain does not even exist.
- raise RuntimeError("The storage domain %s does not exist" %
- output_storage)
-
- # The storage domain is not attached to a datacenter
- # (shouldn't happen, would fail on disk creation).
- raise RuntimeError("The storage domain %s is not attached to a DC" %
- output_storage)
-datacenter = data_centers[0]
-
-# Get the storage domain.
-storage_domains = connection.follow_link(datacenter.storage_domains)
-try:
- storage_domain = [sd for sd in storage_domains
- if sd.name == output_storage][0]
-except IndexError:
- raise RuntimeError("The storage domain %s does not exist" %
- output_storage)
-
-# Get the cluster.
-clusters = connection.follow_link(datacenter.clusters)
-clusters = [cluster for cluster in clusters if cluster.name == params['rhv_cluster']]
-if len(clusters) == 0:
- raise RuntimeError("The cluster %s is not part of the DC %s, "
- "where the storage domain %s is" %
- (params['rhv_cluster'], datacenter.name,
- output_storage))
-cluster = clusters[0]
-cpu = cluster.cpu
-if cpu.architecture == types.Architecture.UNDEFINED:
- raise RuntimeError("The cluster %s has an unknown architecture" %
- (params['rhv_cluster']))
-
-# Find if any disk already exists with specified UUID.
-# Only used with -oo rhv-disk-uuid. It is assumed that the
-# random UUIDs that we generate are unlikely to conflict.
-disks_service = system_service.disks_service()
-
-for uuid in params.get('rhv_disk_uuids', []):
- try:
- disk_service = disks_service.disk_service(uuid).get()
- raise RuntimeError("Disk with the UUID '%s' already exists" % uuid)
- except sdk.NotFoundError:
- pass
-
-# Otherwise everything is OK, print a JSON with the results.
-results = {
- "rhv_storagedomain_uuid": storage_domain.id,
- "rhv_cluster_uuid": cluster.id,
- "rhv_cluster_cpu_architecture": cpu.architecture.value,
-}
-
-json.dump(results, sys.stdout)
diff --git a/output/rhv-upload-transfer.py b/output/rhv-upload-transfer.py
deleted file mode 100644
index ed96153b..00000000
--- a/output/rhv-upload-transfer.py
+++ /dev/null
@@ -1,298 +0,0 @@
-# -*- python -*-
-# oVirt or RHV upload start transfer used by virt-v2v -o rhv-upload
-# Copyright (C) 2018-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.
-
-import inspect
-import json
-import logging
-import sys
-import time
-from contextlib import closing
-from urllib.parse import urlparse, urlunparse
-
-import ovirtsdk4 as sdk
-import ovirtsdk4.types as types
-
-# Timeout to wait for oVirt disks to change status, or the transfer
-# object to finish initializing [seconds].
-timeout = 5 * 60
-
-
-def debug(s):
- if params['verbose']:
- print(s, file=sys.stderr)
- sys.stderr.flush()
-
-
-def find_host(connection):
- """Return the current host object or None."""
- try:
- with open("/etc/vdsm/vdsm.id") as f:
- vdsm_id = f.readline().strip()
- except FileNotFoundError:
- # Expected condition when running on non-oVirt host.
- debug("not an oVirt host, using non-oVirt host")
- return None
- except Exception as e:
- # Unexpected but we can degrade to remote transfer.
- debug(f"warning: cannot read host id, using non-oVirt host: {e}")
- return None
-
- debug("hw_id = %r" % vdsm_id)
-
- system_service = connection.system_service()
- storage_name = params['output_storage']
- data_centers = system_service.data_centers_service().list(
- search='storage.name=%s' % storage_name,
- case_sensitive=True,
- )
- if len(data_centers) == 0:
- # The storage domain is not attached to a datacenter
- # (shouldn't happen, would fail on disk creation).
- debug("storange domain (%s) is not attached to a DC" % storage_name)
- return None
-
- datacenter = data_centers[0]
- debug("datacenter = %s" % datacenter.name)
-
- hosts_service = system_service.hosts_service()
- hosts = hosts_service.list(
- search="hw_id=%s and datacenter=%s and status=Up"
- % (vdsm_id, datacenter.name),
- case_sensitive=True,
- )
- if len(hosts) == 0:
- # Couldn't find a host that's fulfilling the following criteria:
- # - 'hw_id' equals to 'vdsm_id'
- # - Its status is 'Up'
- # - Belongs to the storage domain's datacenter
- debug("cannot find a running host with hw_id=%r, "
- "that belongs to datacenter '%s', "
- "using any host" % (vdsm_id, datacenter.name))
- return None
-
- host = hosts[0]
- debug("host.id = %r" % host.id)
-
- return types.Host(id=host.id)
-
-
-def create_disk(connection):
- """
- Create a new disk for the transfer and wait until the disk is ready.
-
- Returns disk object.
- """
- system_service = connection.system_service()
- disks_service = system_service.disks_service()
-
- if params['disk_format'] == "raw":
- disk_format = types.DiskFormat.RAW
- else:
- disk_format = types.DiskFormat.COW
-
- disk = disks_service.add(
- disk=types.Disk(
- id=params['disk_uuid'],
- name=params['disk_name'],
- description="Uploaded by virt-v2v",
- format=disk_format,
- # XXX For qcow2 disk on block storage, we should use the estimated
- # size, based on qemu-img measure of the overlay.
- initial_size=params['disk_size'],
- provisioned_size=params['disk_size'],
- # Handling this properly will be complex, see:
- # https://www.redhat.com/archives/libguestfs/2018-March/msg00177.html
- sparse=True,
- storage_domains=[
- types.StorageDomain(
- name=params['output_storage'],
- )
- ],
- )
- )
-
- debug("disk.id = %r" % disk.id)
-
- # Wait till the disk moved from LOCKED state to OK state, as the transfer
- # can't start if the disk is locked.
-
- disk_service = disks_service.disk_service(disk.id)
- endt = time.monotonic() + timeout
- while True:
- time.sleep(1)
- disk = disk_service.get()
- if disk.status == types.DiskStatus.OK:
- break
- if time.monotonic() > endt:
- raise RuntimeError(
- "timed out waiting for disk %s to become unlocked" % disk.id)
-
- return disk
-
-
-def create_transfer(connection, disk, host):
- """
- Create image transfer and wait until the transfer is ready.
-
- Returns a transfer object.
- """
- system_service = connection.system_service()
- transfers_service = system_service.image_transfers_service()
-
- extra = {}
- if transfer_supports_format():
- extra["format"] = types.DiskFormat.RAW
-
- transfer = transfers_service.add(
- types.ImageTransfer(
- disk=types.Disk(id=disk.id),
- host=host,
- inactivity_timeout=3600,
- **extra,
- )
- )
-
- # At this point the transfer owns the disk and will delete the disk if the
- # transfer is canceled, or if finalizing the transfer fails.
-
- debug("transfer.id = %r" % transfer.id)
-
- # Get a reference to the created transfer service.
- transfer_service = transfers_service.image_transfer_service(transfer.id)
-
- # Wait until transfer's phase change from INITIALIZING to TRANSFERRING. On
- # errors transfer's phase can change to PAUSED_SYSTEM or FINISHED_FAILURE.
- # If the transfer was paused, we need to cancel it to remove the disk,
- # otherwise the system will remove the disk and transfer shortly after.
-
- endt = time.monotonic() + timeout
- while True:
- time.sleep(1)
- try:
- transfer = transfer_service.get()
- except sdk.NotFoundError:
- # The system has removed the disk and the transfer.
- raise RuntimeError("transfer %s was removed" % transfer.id)
-
- if transfer.phase == types.ImageTransferPhase.FINISHED_FAILURE:
- # The system will remove the disk and the transfer soon.
- raise RuntimeError(
- "transfer %s has failed" % transfer.id)
-
- if transfer.phase == types.ImageTransferPhase.PAUSED_SYSTEM:
- transfer_service.cancel()
- raise RuntimeError(
- "transfer %s was paused by system" % transfer.id)
-
- if transfer.phase == types.ImageTransferPhase.TRANSFERRING:
- break
-
- if transfer.phase != types.ImageTransferPhase.INITIALIZING:
- transfer_service.cancel()
- raise RuntimeError(
- "unexpected transfer %s phase %s"
- % (transfer.id, transfer.phase))
-
- if time.monotonic() > endt:
- transfer_service.cancel()
- raise RuntimeError(
- "timed out waiting for transfer %s" % transfer.id)
-
- return transfer
-
-
-def transfer_supports_format():
- """
- Return True if transfer supports the "format" argument, enabing the NBD
- bakend on imageio side, which allows uploading to qcow2 images.
-
- This feature was added in ovirt 4.3. We assume that the SDK version matches
- engine version.
- """
- sig = inspect.signature(types.ImageTransfer)
- return "format" in sig.parameters
-
-
-def get_transfer_url(transfer):
- """
- Returns the transfer url, preferring direct transfer if possible.
- """
- if params['rhv_direct']:
- if transfer.transfer_url is None:
- raise RuntimeError("direct upload to host not supported, "
- "requires ovirt-engine >= 4.2 and only works "
- "when virt-v2v is run within the oVirt/RHV "
- "environment, eg. on an oVirt node.")
- return transfer.transfer_url
- else:
- return transfer.proxy_url
-
-
-# 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.
-params = None
-
-if len(sys.argv) != 2:
- raise RuntimeError("incorrect number of parameters")
-
-# Parameters are passed in via a JSON document.
-with open(sys.argv[1], 'r') as fp:
- data = fp.read()
-
-try:
- params = json.loads(data)
-except ValueError as e:
- raise RuntimeError(f"Cannot parse params {data!r}: {e}").with_traceback(
- e.__traceback__
- ) from None
-
-# What is passed in is a password file, read the actual password.
-with open(params['output_password'], 'r') as fp:
- output_password = fp.read()
-output_password = output_password.rstrip()
-
-# Parse out the username from the output_conn URL.
-parsed = urlparse(params['output_conn'])
-username = parsed.username or "admin@internal"
-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname
-
-connection = sdk.Connection(
- url=urlunparse(parsed._replace(netloc=netloc)),
- username=username,
- password=output_password,
- ca_file=params['rhv_cafile'],
- log=logging.getLogger(),
- insecure=params['insecure'],
-)
-
-with closing(connection):
- # Use the local host if possible.
- host = find_host(connection) if params['rhv_direct'] else None
- disk = create_disk(connection)
-
- transfer = create_transfer(connection, disk, host)
- destination_url = get_transfer_url(transfer)
-
-# Send the destination URL, transfer ID, and host flag back to OCaml code.
-results = {
- "transfer_id": transfer.id,
- "destination_url": destination_url,
- "is_ovirt_host": host is not None,
-}
-json.dump(results, sys.stdout)
diff --git a/output/rhv-upload-vmcheck.py b/output/rhv-upload-vmcheck.py
deleted file mode 100644
index cd500574..00000000
--- a/output/rhv-upload-vmcheck.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# -*- python -*-
-# oVirt or RHV VM existence check used by virt-v2v -o rhv-upload
-# Copyright (C) 2018-2020 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.
-
-import json
-import logging
-import sys
-
-from urllib.parse import urlparse, urlunparse
-
-import ovirtsdk4 as sdk
-import ovirtsdk4.types as types
-
-# 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.
-params = None
-
-if len(sys.argv) != 2:
- raise RuntimeError("incorrect number of parameters")
-
-# Parameters are passed in via a JSON document.
-with open(sys.argv[1], 'r') as fp:
- params = json.load(fp)
-
-# What is passed in is a password file, read the actual password.
-with open(params['output_password'], 'r') as fp:
- output_password = fp.read()
-output_password = output_password.rstrip()
-
-# Parse out the username from the output_conn URL.
-parsed = urlparse(params['output_conn'])
-username = parsed.username or "admin@internal"
-netloc = f"{parsed.hostname:parsed.port}" if parsed.port else parsed.hostname
-
-# Connect to the server.
-connection = sdk.Connection(
- url=urlunparse(parsed._replace(netloc=netloc)),
- username=username,
- password=output_password,
- ca_file=params['rhv_cafile'],
- log=logging.getLogger(),
- insecure=params['insecure'],
-)
-
-system_service = connection.system_service()
-
-# Find if a virtual machine already exists with that name.
-vms_service = system_service.vms_service()
-vms = vms_service.list(
- search=("name=%s" % params['output_name']),
-)
-if len(vms) > 0:
- vm = vms[0]
- raise RuntimeError("VM already exists with name %s, id %s" %
- (params['output_name'], vm.id))
-
-# Otherwise everything is OK, exit with no error.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 1ec1a702..955d08a0 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -70,8 +70,6 @@ TESTS = \
test-v2v-i-ova-two-disks.sh \
test-v2v-i-vmx.sh \
test-v2v-it-vddk-io-query.sh \
- test-v2v-o-rhv-upload-oo-query.sh \
- test-v2v-o-vdsm-oo-query.sh \
test-v2v-bad-networks-and-bridges.sh \
test-v2v-cdrom.sh \
test-v2v-floppy.sh \
@@ -89,9 +87,6 @@ TESTS = \
test-v2v-o-null.sh \
test-v2v-o-openstack.sh \
test-v2v-o-qemu.sh \
- test-v2v-o-rhv.sh \
- test-v2v-o-rhv-upload.sh \
- test-v2v-o-vdsm-options.sh \
test-v2v-oa-option-qcow2.sh \
test-v2v-oa-option-raw.sh \
test-v2v-of-option.sh \
@@ -256,16 +251,6 @@ EXTRA_DIST += \
test-v2v-o-null.sh \
test-v2v-o-openstack.sh \
test-v2v-o-qemu.sh \
- test-v2v-o-rhv.ovf.expected \
- test-v2v-o-rhv.sh \
- test-v2v-o-rhv-upload.sh \
- test-v2v-o-rhv-upload-module/imageio.py \
- test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py \
- test-v2v-o-rhv-upload-module/ovirtsdk4/types.py \
- test-v2v-o-rhv-upload-oo-query.sh \
- test-v2v-o-vdsm-oo-query.sh \
- test-v2v-o-vdsm-options.ovf.expected \
- test-v2v-o-vdsm-options.sh \
test-v2v-oa-option-qcow2.sh \
test-v2v-oa-option-raw.sh \
test-v2v-of-option.sh \
diff --git a/tests/test-v2v-o-rhv-upload-module/imageio.py b/tests/test-v2v-o-rhv-upload-module/imageio.py
deleted file mode 100755
index b9a491d7..00000000
--- a/tests/test-v2v-o-rhv-upload-module/imageio.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python3
-# -*- python -*-
-# Copyright (C) 2018-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.
-
-# Fake imageio web server used as a test harness.
-# See v2v/test-v2v-o-rhv-upload.sh
-
-import sys
-import threading
-from http.server import HTTPServer, BaseHTTPRequestHandler
-
-class RequestHandler(BaseHTTPRequestHandler):
- protocol_version = 'HTTP/1.1'
-
- def do_OPTIONS(self):
- self.discard_request()
-
- # Advertize only flush and zero support.
- content = b'''{ "features": [ "flush", "zero" ] }'''
- length = len(content)
-
- self.send_response(200)
- self.send_header("Content-type", "application/json; charset=UTF-8")
- self.send_header("Content-Length", length)
- self.end_headers()
- self.wfile.write(content)
-
- # eg. zero request. Just ignore it.
- def do_PATCH(self):
- self.discard_request()
- self.send_response(200)
- self.send_header("Content-Length", "0")
- self.end_headers()
-
- # Flush request. Ignore it.
- def do_PUT(self):
- self.discard_request()
- self.send_response(200)
- self.send_header("Content-Length", "0")
- self.end_headers()
-
- def discard_request(self):
- length = self.headers.get('Content-Length')
- if length:
- length = int(length)
- content = self.rfile.read(length)
-
-server_address = ("", 0)
-# XXX This should test HTTPS, not HTTP, because we are testing a
-# different path through the main code.
-httpd = HTTPServer(server_address, RequestHandler)
-imageio_port = httpd.server_address[1]
-
-print("port: %d" % imageio_port)
-sys.stdout.flush()
-
-httpd.serve_forever()
diff --git a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py
deleted file mode 100644
index e33d0714..00000000
--- a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# -*- python -*-
-# Copyright (C) 2018 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.
-
-# Fake ovirtsdk4 module used as a test harness.
-# See v2v/test-v2v-o-rhv-upload.sh
-
-class Error(Exception):
- pass
-
-
-class NotFoundError(Error):
- pass
-
-
-class Connection(object):
- def __init__(
- self,
- url=None,
- username=None,
- password=None,
- ca_file=None,
- log=None,
- insecure=False,
- debug=True,
- ):
- pass
-
- def close(self):
- pass
-
- def follow_link(self, objs):
- return objs
-
- def system_service(self):
- return SystemService()
-
-
-class SystemService(object):
- def clusters_service(self):
- return ClustersService()
-
- def data_centers_service(self):
- return DataCentersService()
-
- def disks_service(self):
- return DisksService()
-
- def jobs_service(self):
- return JobsService()
-
- def image_transfers_service(self):
- return ImageTransfersService()
-
- def storage_domains_service(self):
- return StorageDomainsService()
-
- def vms_service(self):
- return VmsService()
-
-
-class ClusterService(object):
- def get(self):
- return types.Cluster()
-
-
-class ClustersService(object):
- def cluster_service(self, id):
- return ClusterService()
-
-
-class DataCentersService(object):
- def list(self, search=None, case_sensitive=False):
- return [types.DataCenter()]
-
-
-class DiskService(object):
- def __init__(self, disk_id):
- self._disk_id = disk_id
-
- def get(self):
- return types.Disk(id=self._disk_id)
-
- def remove(self):
- pass
-
-
-class DisksService(object):
- def add(self, disk=None):
- disk.id = "756d81b0-d5c0-41bc-9bbe-b343c3fa3490"
- return disk
-
- def disk_service(self, disk_id):
- return DiskService(disk_id)
-
-
-class JobsService(object):
- def list(self, search=None):
- return [types.Job()]
-
-
-class ImageTransferService(object):
- def __init__(self):
- self._finalized = False
-
- def cancel(self):
- pass
-
- def get(self):
- if self._finalized:
- raise NotFoundError
- else:
- return types.ImageTransfer()
-
- def finalize(self):
- self._finalized = True
-
-
-class ImageTransfersService(object):
- def add(self, transfer):
- return transfer
-
- def image_transfer_service(self, id):
- return ImageTransferService()
-
-
-class StorageDomainsService(object):
- def list(self, search=None, case_sensitive=False):
- return [StorageDomain()]
-
-
-class VmsService(object):
- def add(self, vm, query=None):
- return vm
-
- def list(self, search=None):
- return []
diff --git a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py
deleted file mode 100644
index 38d89573..00000000
--- a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py
+++ /dev/null
@@ -1,184 +0,0 @@
-# -*- python -*-
-# Copyright (C) 2018 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.
-
-# Fake ovirtsdk4 module used as a test harness.
-# See v2v/test-v2v-o-rhv-upload.sh
-
-import os
-from enum import Enum
-
-imageio_port = os.getenv("IMAGEIO_PORT")
-assert imageio_port is not None
-
-
-class Architecture(Enum):
- UNDEFINED = "undefined"
- X86_64 = "x86_64"
-
- def __init__(self, arch):
- self._arch = arch
-
- def __str__(self):
- return self._arch
-
-
-class Cpu(object):
- architecture = Architecture.X86_64
-
-
-class Cluster(object):
- id = "2e97537b-a783-4706-af9e-75cb2e032dcd"
- name = "Default"
- cpu = Cpu()
-
-
-class Configuration(object):
- def __init__(self, type=None, data=None):
- pass
-
-
-class ConfigurationType(Enum):
- OVA = 'ova'
- OVF = 'ovf'
-
- def __init__(self, image):
- self._image = image
-
- def __str__(self):
- return self._image
-
-
-class DiskFormat(Enum):
- COW = "cow"
- RAW = "raw"
-
- def __init__(self, image):
- self._image = image
-
- def __str__(self):
- return self._image
-
-
-class DiskStatus(Enum):
- ILLEGAL = "illegal"
- LOCKED = "locked"
- OK = "ok"
-
- def __init__(self, image):
- self._image = image
-
- def __str__(self):
- return self._image
-
-
-class Disk(object):
- def __init__(
- self,
- id=None,
- name=None,
- description=None,
- format=None,
- initial_size=None,
- provisioned_size=None,
- sparse=False,
- storage_domains=None
- ):
- self.id = id
-
- status = DiskStatus.OK
-
-
-class ImageTransferPhase(Enum):
- CANCELLED = 'cancelled'
- FINALIZING_FAILURE = 'finalizing_failure'
- FINALIZING_SUCCESS = 'finalizing_success'
- FINISHED_FAILURE = 'finished_failure'
- FINISHED_SUCCESS = 'finished_success'
- INITIALIZING = 'initializing'
- PAUSED_SYSTEM = 'paused_system'
- PAUSED_USER = 'paused_user'
- RESUMING = 'resuming'
- TRANSFERRING = 'transferring'
- UNKNOWN = 'unknown'
-
- def __init__(self, image):
- self._image = image
-
- def __str__(self):
- return self._image
-
-
-class ImageTransfer(object):
- def __init__(
- self,
- disk=None,
- host=None,
- inactivity_timeout=None,
- ):
- pass
-
- id = "e26ac8ab-7090-4d5e-95ad-e707b511a359"
- phase = ImageTransferPhase.TRANSFERRING
- transfer_url = "http://localhost:" + imageio_port + "/"
-
-
-class Initialization(object):
- def __init__(self, configuration):
- 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
-
- id = "ba87af68-b630-4211-a73a-694c1a689405"
- name = "Storage"
-
-
-class Vm(object):
- def __init__(
- self,
- cluster=None,
- initialization=None
- ):
- pass
-
-
-class DataCenter(object):
- id = "31d8c73b-554b-4958-bb04-9ce97f0849e1"
- name = "DC"
- storage_domains = [StorageDomain()]
- clusters = [Cluster()]
diff --git a/tests/test-v2v-o-rhv-upload-oo-query.sh b/tests/test-v2v-o-rhv-upload-oo-query.sh
deleted file mode 100755
index 5ef56b90..00000000
--- a/tests/test-v2v-o-rhv-upload-oo-query.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash -
-# libguestfs virt-v2v test script
-# Copyright (C) 2018 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 -oo "?" option.
-
-set -e
-
-source ./functions.sh
-set -e
-set -x
-
-skip_if_skipped
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win"
-
-f=test-v2v-o-rhv-upload-oo-query.actual
-rm -f $f
-
-$VG virt-v2v --debug-gc \
- -o rhv-upload -oo "?" > $f
-
-grep -- "-oo rhv-cafile" $f
-grep -- "-oo rhv-verifypeer" $f
-
-rm $f
diff --git a/tests/test-v2v-o-rhv-upload.sh b/tests/test-v2v-o-rhv-upload.sh
deleted file mode 100755
index 15d5d028..00000000
--- a/tests/test-v2v-o-rhv-upload.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/bin/bash -
-# libguestfs virt-v2v test script
-# Copyright (C) 2018 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 -o rhv-upload.
-#
-# These uses a test harness (see
-# tests/test-v2v-o-rhv-upload-module/ovirtsdk4) to fake responses from
-# oVirt.
-
-set -e
-set -x
-
-source ./functions.sh
-set -e
-set -x
-
-skip_if_skipped
-requires python3 --version
-requires nbdkit $VIRT_V2V_NBDKIT_PYTHON_PLUGIN --version
-requires test -f ../test-data/phony-guests/windows.img
-
-libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
-f=../test-data/phony-guests/windows.img
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win"
-export PYTHONPATH=$srcdir/test-v2v-o-rhv-upload-module:$PYTHONPATH
-
-# Run the imageio process and get the port number.
-log=test-v2v-o-rhv-upload.webserver.log
-rm -f $log
-cleanup_fn rm -f $log
-$srcdir/test-v2v-o-rhv-upload-module/imageio.py >$log 2>&1 &
-pid=$!
-cleanup_fn kill $pid
-export IMAGEIO_PORT=
-for i in {1..5}; do
- IMAGEIO_PORT=$( grep "^port:" $log | awk '{print $2}' )
- if [ -n "$IMAGEIO_PORT" ]; then break; fi
- sleep 3
-done
-if [ ! -n "$IMAGEIO_PORT" ]; then
- echo "$0: imageio process did not start up"
- cat $log
- exit 1
-fi
-echo IMAGEIO_PORT=$IMAGEIO_PORT
-
-# Run virt-v2v -o rhv-upload.
-#
-# The fake ovirtsdk4 module doesn't care about most of the options
-# like -oc, -oo rhv-cafile, -op etc. Any values may be used.
-$VG virt-v2v --debug-gc -v -x \
- -i libvirt -ic "$libvirt_uri" windows \
- -o rhv-upload \
- -oc https://example.com/ovirt-engine/api \
- -oo rhv-cafile=/dev/null \
- -op /dev/null \
- -os Storage
diff --git a/tests/test-v2v-o-rhv.ovf.expected b/tests/test-v2v-o-rhv.ovf.expected
deleted file mode 100644
index 25e492fd..00000000
--- a/tests/test-v2v-o-rhv.ovf.expected
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<ovf:Envelope xmlns:rasd='http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData' xmlns:vssd='http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ovf='http://schemas.dmtf.org/ovf/envelope/1/' xmlns:ovirt='http://www.ovirt.org/ovf' ovf:version='0.9'>
- <!-- generated by virt-v2v -->
- <References>
- <File ovf:href='#DISK_ID#/#VOL_ID#' ovf:id='#VOL_ID#' ovf:description='generated by virt-v2v' ovf:size='#SIZE#'/>
- </References>
- <Section xsi:type='ovf:NetworkSection_Type'>
- <Info>List of networks</Info>
- <Network ovf:name='default'/>
- </Section>
- <Section xsi:type='ovf:DiskSection_Type'>
- <Info>List of Virtual Disks</Info>
- <Disk ovf:diskId='#VOL_ID#' ovf:size='1' ovf:capacity='536870912' ovf:fileRef='#DISK_ID#/#VOL_ID#' ovf:parentRef='' ovf:vm_snapshot_id='#UUID#' ovf:volume-format='RAW' ovf:volume-type='Sparse' ovf:format='http://en.wikipedia.org/wiki/Byte' ovf:disk-interface='VirtIO' ovf:disk-type='System' ovf:boot='True' ovf:actual_size='1'/>
- </Section>
- <Content ovf:id='out' xsi:type='ovf:VirtualSystem_Type'>
- <Name>windows</Name>
- <TemplateId>00000000-0000-0000-0000-000000000000</TemplateId>
- <TemplateName>Blank</TemplateName>
- <Description>generated by virt-v2v</Description>
- <Domain/>
- <CreationDate>#DATE#</CreationDate>
- <IsInitilized>True</IsInitilized>
- <IsAutoSuspend>False</IsAutoSuspend>
- <TimeZone/>
- <IsStateless>False</IsStateless>
- <VmType>0</VmType>
- <DefaultDisplayType>2</DefaultDisplayType>
- <BiosType>1</BiosType>
- <Section ovf:id='#VM_ID#' ovf:required='false' xsi:type='ovf:OperatingSystemSection_Type'>
- <Info>Microsoft Windows 7 Phony Edition</Info>
- <Description>Windows7</Description>
- </Section>
- <Section xsi:type='ovf:VirtualHardwareSection_Type'>
- <Info>1 CPU, 1024 Memory</Info>
- <Item>
- <rasd:Caption>1 virtual cpu</rasd:Caption>
- <rasd:Description>Number of virtual CPU</rasd:Description>
- <rasd:InstanceId>1</rasd:InstanceId>
- <rasd:ResourceType>3</rasd:ResourceType>
- <rasd:num_of_sockets>1</rasd:num_of_sockets>
- <rasd:cpu_per_socket>1</rasd:cpu_per_socket>
- </Item>
- <Item>
- <rasd:Caption>1024 MB of memory</rasd:Caption>
- <rasd:Description>Memory Size</rasd:Description>
- <rasd:InstanceId>2</rasd:InstanceId>
- <rasd:ResourceType>4</rasd:ResourceType>
- <rasd:AllocationUnits>MegaBytes</rasd:AllocationUnits>
- <rasd:VirtualQuantity>1024</rasd:VirtualQuantity>
- </Item>
- <Item>
- <rasd:Caption>USB Controller</rasd:Caption>
- <rasd:InstanceId>3</rasd:InstanceId>
- <rasd:ResourceType>23</rasd:ResourceType>
- <rasd:UsbPolicy>Disabled</rasd:UsbPolicy>
- </Item>
- <Item>
- <rasd:Caption>Graphical Controller</rasd:Caption>
- <rasd:InstanceId>#UUID#</rasd:InstanceId>
- <rasd:ResourceType>20</rasd:ResourceType>
- <Type>video</Type>
- <rasd:VirtualQuantity>1</rasd:VirtualQuantity>
- <Device>vga</Device>
- </Item>
- <Item>
- <rasd:Caption>RNG Device</rasd:Caption>
- <rasd:InstanceId>#UUID#</rasd:InstanceId>
- <rasd:ResourceType>0</rasd:ResourceType>
- <Type>rng</Type>
- <Device>virtio</Device>
- <SpecParams>
- <source>urandom</source>
- </SpecParams>
- </Item>
- <Item>
- <rasd:Caption>Memory Ballooning Device</rasd:Caption>
- <rasd:InstanceId>#UUID#</rasd:InstanceId>
- <rasd:ResourceType>0</rasd:ResourceType>
- <Type>balloon</Type>
- <Device>memballoon</Device>
- <SpecParams>
- <model>virtio</model>
- </SpecParams>
- </Item>
- <Item>
- <rasd:Caption>Drive 1</rasd:Caption>
- <rasd:InstanceId>#VOL_ID#</rasd:InstanceId>
- <rasd:ResourceType>17</rasd:ResourceType>
- <Type>disk</Type>
- <rasd:HostResource>#DISK_ID#/#VOL_ID#</rasd:HostResource>
- <rasd:Parent>00000000-0000-0000-0000-000000000000</rasd:Parent>
- <rasd:Template>00000000-0000-0000-0000-000000000000</rasd:Template>
- <rasd:ApplicationList/>
- <rasd:StorageId>12345678-1234-1234-1234-123456789abc</rasd:StorageId>
- <rasd:StoragePoolId>00000000-0000-0000-0000-000000000000</rasd:StoragePoolId>
- <rasd:CreationDate>#DATE#</rasd:CreationDate>
- <rasd:LastModified>#DATE#</rasd:LastModified>
- <rasd:last_modified_date>#DATE#</rasd:last_modified_date>
- <BootOrder>1</BootOrder>
- </Item>
- <Item>
- <rasd:InstanceId>#UUID#</rasd:InstanceId>
- <rasd:Caption>Ethernet adapter on default</rasd:Caption>
- <rasd:ResourceType>10</rasd:ResourceType>
- <rasd:ResourceSubType>3</rasd:ResourceSubType>
- <Type>interface</Type>
- <rasd:Connection>default</rasd:Connection>
- <rasd:Name>eth0</rasd:Name>
- <rasd:MACAddress>00:11:22:33:44:55</rasd:MACAddress>
- </Item>
- </Section>
- </Content>
-</ovf:Envelope>
diff --git a/tests/test-v2v-o-rhv.sh b/tests/test-v2v-o-rhv.sh
deleted file mode 100755
index e6ec7c61..00000000
--- a/tests/test-v2v-o-rhv.sh
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/bin/bash -
-# libguestfs virt-v2v test script
-# Copyright (C) 2014 Red Hat Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-# Test -o rhv.
-
-set -e
-
-source ./functions.sh
-set -e
-set -x
-
-skip_if_skipped
-requires test -f ../test-data/phony-guests/windows.img
-
-libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
-f=../test-data/phony-guests/windows.img
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win"
-
-d=test-v2v-o-rhv.d
-rm -rf $d
-cleanup_fn rm -r $d
-mkdir $d
-
-# Create a dummy Export Storage Domain.
-mkdir $d/12345678-1234-1234-1234-123456789abc
-mkdir $d/12345678-1234-1234-1234-123456789abc/images
-mkdir $d/12345678-1234-1234-1234-123456789abc/master
-mkdir $d/12345678-1234-1234-1234-123456789abc/master/vms
-
-# $VG - XXX Disabled because the forking used to write files in -o rhv
-# mode confuses valgrind.
-virt-v2v --debug-gc -v -x \
- -i libvirt -ic "$libvirt_uri" windows \
- -o rhv -os $d
-
-# Test the OVF metadata was created.
-test -f $d/12345678-1234-1234-1234-123456789abc/master/vms/*/*.ovf
-
-pushd $d/12345678-1234-1234-1234-123456789abc/images/*
-
-# Test the disk .meta was created.
-test -f *.meta
-
-# Test the disk file was created.
-vol=`basename *.meta .meta`
-test -f $vol
-
-popd
-
-# Compare resulting OVF
-VM_ID=$(basename $(ls -1d $d/12345678-1234-1234-1234-123456789abc/master/vms/*))
-DISK_ID=$(basename $(ls -1d $d/12345678-1234-1234-1234-123456789abc/images/*))
-VOL_ID=$(basename $(ls -1d $d/12345678-1234-1234-1234-123456789abc/images/$DISK_ID/*.meta) .meta)
-OVF=$(ls -1d $d/12345678-1234-1234-1234-123456789abc/master/vms/$VM_ID/$VM_ID.ovf)
-
-RE_UUID='\<[0-9a-fA-F]\{8\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{12\}\>'
-
-# Filter variable strings
-sed -i \
- -e "s/$DISK_ID/#DISK_ID#/g" \
- -e "s/$VM_ID/#VM_ID#/g" \
- -e "s/$VOL_ID/#VOL_ID#/g" \
- -e "s/\(<File.*ovf:size='\)[^']*/\1#SIZE#/g" \
- -e 's/\(\<generated by virt-v2v\) [^ <'"'\""']*/\1/' \
- -e 's/<rasd:InstanceId>'"$RE_UUID"'</<rasd:InstanceId>#UUID#</' \
- -e 's/<\(rasd:\)\?\(CreationDate\|LastModified\|last_modified_date\)>[^<]*</<\1\2>#DATE#</' \
- -e 's/\<ovf:vm_snapshot_id='"'$RE_UUID'/ovf:vm_snapshot_id='#UUID#'/g" \
- "$OVF"
-
-diff -u "$srcdir/test-v2v-o-rhv.ovf.expected" "$OVF"
diff --git a/tests/test-v2v-o-vdsm-oo-query.sh b/tests/test-v2v-o-vdsm-oo-query.sh
deleted file mode 100755
index 7d4cae4e..00000000
--- a/tests/test-v2v-o-vdsm-oo-query.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash -
-# libguestfs virt-v2v test script
-# Copyright (C) 2018 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 -oo "?" option.
-
-set -e
-
-source ./functions.sh
-set -e
-set -x
-
-skip_if_skipped
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win"
-
-f=test-v2v-o-vdsm-oo-query.actual
-rm -f $f
-
-$VG virt-v2v --debug-gc \
- -o vdsm -oo "?" > $f
-
-grep -- "-oo vdsm-compat" $f
-grep -- "-oo vdsm-image-uuid" $f
-
-rm $f
diff --git a/tests/test-v2v-o-vdsm-options.ovf.expected b/tests/test-v2v-o-vdsm-options.ovf.expected
deleted file mode 100644
index 23ca180f..00000000
--- a/tests/test-v2v-o-vdsm-options.ovf.expected
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<ovf:Envelope xmlns:rasd='http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData' xmlns:vssd='http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ovf='http://schemas.dmtf.org/ovf/envelope/1/' xmlns:ovirt='http://www.ovirt.org/ovf' ovf:version='0.9'>
- <!-- generated by virt-v2v -->
- <References>
- <File ovf:href='VOL' ovf:id='VOL' ovf:description='generated by virt-v2v'/>
- </References>
- <NetworkSection>
- <Info>List of networks</Info>
- <Network ovf:name='default'/>
- </NetworkSection>
- <DiskSection>
- <Info>List of Virtual Disks</Info>
- <Disk ovf:diskId='IMAGE' ovf:size='1' ovf:capacity='536870912' ovf:fileRef='VOL' ovf:parentRef='' ovf:vm_snapshot_id='#UUID#' ovf:volume-format='COW' ovf:volume-type='Sparse' ovf:format='http://en.wikipedia.org/wiki/Byte' ovf:disk-interface='VirtIO' ovf:disk-type='System' ovf:boot='True'/>
- </DiskSection>
- <VirtualSystem ovf:id='VM'>
- <Name>windows</Name>
- <TemplateId>00000000-0000-0000-0000-000000000000</TemplateId>
- <TemplateName>Blank</TemplateName>
- <Description>generated by virt-v2v</Description>
- <Domain/>
- <CreationDate>#DATE#</CreationDate>
- <IsInitilized>True</IsInitilized>
- <IsAutoSuspend>False</IsAutoSuspend>
- <TimeZone/>
- <IsStateless>False</IsStateless>
- <VmType>0</VmType>
- <DefaultDisplayType>2</DefaultDisplayType>
- <BiosType>1</BiosType>
- <OperatingSystemSection ovf:id='VM' ovf:required='false' ovirt:id='11'>
- <Info>Microsoft Windows 7 Phony Edition</Info>
- <Description>Windows7</Description>
- </OperatingSystemSection>
- <VirtualHardwareSection>
- <Info>1 CPU, 1024 Memory</Info>
- <Item>
- <rasd:Caption>1 virtual cpu</rasd:Caption>
- <rasd:Description>Number of virtual CPU</rasd:Description>
- <rasd:InstanceId>1</rasd:InstanceId>
- <rasd:ResourceType>3</rasd:ResourceType>
- <rasd:num_of_sockets>1</rasd:num_of_sockets>
- <rasd:cpu_per_socket>1</rasd:cpu_per_socket>
- </Item>
- <Item>
- <rasd:Caption>1024 MB of memory</rasd:Caption>
- <rasd:Description>Memory Size</rasd:Description>
- <rasd:InstanceId>2</rasd:InstanceId>
- <rasd:ResourceType>4</rasd:ResourceType>
- <rasd:AllocationUnits>MegaBytes</rasd:AllocationUnits>
- <rasd:VirtualQuantity>1024</rasd:VirtualQuantity>
- </Item>
- <Item>
- <rasd:Caption>USB Controller</rasd:Caption>
- <rasd:InstanceId>3</rasd:InstanceId>
- <rasd:ResourceType>23</rasd:ResourceType>
- <rasd:UsbPolicy>Disabled</rasd:UsbPolicy>
- </Item>
- <Item>
- <rasd:Caption>Graphical Controller</rasd:Caption>
- <rasd:InstanceId>#UUID#</rasd:InstanceId>
- <rasd:ResourceType>32768</rasd:ResourceType>
- <Type>video</Type>
- <rasd:VirtualQuantity>1</rasd:VirtualQuantity>
- <Device>vga</Device>
- </Item>
- <Item>
- <rasd:Caption>RNG Device</rasd:Caption>
- <rasd:InstanceId>#UUID#</rasd:InstanceId>
- <rasd:ResourceType>0</rasd:ResourceType>
- <Type>rng</Type>
- <Device>virtio</Device>
- <SpecParams>
- <source>urandom</source>
- </SpecParams>
- </Item>
- <Item>
- <rasd:Caption>Memory Ballooning Device</rasd:Caption>
- <rasd:InstanceId>#UUID#</rasd:InstanceId>
- <rasd:ResourceType>0</rasd:ResourceType>
- <Type>balloon</Type>
- <Device>memballoon</Device>
- <SpecParams>
- <model>virtio</model>
- </SpecParams>
- </Item>
- <Item>
- <rasd:Caption>Drive 1</rasd:Caption>
- <rasd:InstanceId>VOL</rasd:InstanceId>
- <rasd:ResourceType>17</rasd:ResourceType>
- <Type>disk</Type>
- <rasd:HostResource>VOL</rasd:HostResource>
- <rasd:Parent>00000000-0000-0000-0000-000000000000</rasd:Parent>
- <rasd:Template>00000000-0000-0000-0000-000000000000</rasd:Template>
- <rasd:ApplicationList/>
- <rasd:StorageId>12345678-1234-1234-1234-123456789abc</rasd:StorageId>
- <rasd:StoragePoolId>00000000-0000-0000-0000-000000000000</rasd:StoragePoolId>
- <rasd:CreationDate>#DATE#</rasd:CreationDate>
- <rasd:LastModified>#DATE#</rasd:LastModified>
- <rasd:last_modified_date>#DATE#</rasd:last_modified_date>
- <BootOrder>1</BootOrder>
- </Item>
- <Item>
- <rasd:InstanceId>#UUID#</rasd:InstanceId>
- <rasd:Caption>Ethernet adapter on default</rasd:Caption>
- <rasd:ResourceType>10</rasd:ResourceType>
- <rasd:ResourceSubType>3</rasd:ResourceSubType>
- <Type>interface</Type>
- <rasd:Connection>default</rasd:Connection>
- <rasd:Name>eth0</rasd:Name>
- <rasd:MACAddress>00:11:22:33:44:55</rasd:MACAddress>
- </Item>
- </VirtualHardwareSection>
- </VirtualSystem>
-</ovf:Envelope>
diff --git a/tests/test-v2v-o-vdsm-options.sh b/tests/test-v2v-o-vdsm-options.sh
deleted file mode 100755
index e8f8c538..00000000
--- a/tests/test-v2v-o-vdsm-options.sh
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/bash -
-# libguestfs virt-v2v test script
-# Copyright (C) 2014-2020 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 -o vdsm options -oo vdsm-*-uuid
-
-set -e
-set -x
-
-source ./functions.sh
-set -e
-set -x
-
-skip_if_skipped
-requires test -f ../test-data/phony-guests/windows.img
-
-libvirt_uri="test://$abs_top_builddir/test-data/phony-guests/guests.xml"
-f=../test-data/phony-guests/windows.img
-
-export VIRT_TOOLS_DATA_DIR="$srcdir/../test-data/fake-virt-tools"
-export VIRTIO_WIN="$srcdir/../test-data/fake-virtio-win"
-
-d=test-v2v-o-vdsm-options.d
-rm -rf $d
-cleanup_fn rm -r $d
-mkdir $d
-
-# Create a dummy Export Storage Domain.
-mkdir $d/12345678-1234-1234-1234-123456789abc
-mkdir $d/12345678-1234-1234-1234-123456789abc/images
-mkdir $d/12345678-1234-1234-1234-123456789abc/images/IMAGE
-mkdir $d/12345678-1234-1234-1234-123456789abc/master
-mkdir $d/12345678-1234-1234-1234-123456789abc/master/vms
-mkdir $d/12345678-1234-1234-1234-123456789abc/master/vms/VM
-
-# The -oo vdsm-*-uuid options don't actually check that the
-# parameter is a UUID, which is useful here.
-
-$VG virt-v2v --debug-gc \
- -i libvirt -ic "$libvirt_uri" windows \
- -o vdsm -os $d/12345678-1234-1234-1234-123456789abc \
- -of qcow2 \
- -oo vdsm-image-uuid=IMAGE \
- -oo vdsm-vol-uuid=VOL \
- -oo vdsm-vm-uuid=VM \
- -oo vdsm-ovf-output=$d/12345678-1234-1234-1234-123456789abc/master/vms/VM \
- -oo vdsm-compat=1.1 \
- -oo vdsm-ovf-flavour=ovirt
-
-# Test the OVF metadata was created.
-test -f $d/12345678-1234-1234-1234-123456789abc/master/vms/VM/VM.ovf
-
-pushd $d/12345678-1234-1234-1234-123456789abc/images/IMAGE
-
-# Test the disk .meta was created.
-test -f VOL.meta
-
-# Test the disk file was created.
-test -f VOL
-
-# Test that a qcow2 file with compat=1.1 was generated.
-test "$(guestfish disk-format VOL)" = "qcow2"
-qemu-img info VOL | grep 'compat: 1.1'
-
-popd
-
-# Compare resulting OVF
-OVF="$d/12345678-1234-1234-1234-123456789abc/master/vms/VM/VM.ovf"
-
-RE_UUID='\<[0-9a-fA-F]\{8\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{4\}-[0-9a-fA-F]\{12\}\>'
-
-# Filter variable strings
-sed -i \
- -e "s/\(<File.*ovf:size='\)[^']*/\1#SIZE#/g" \
- -e 's/\(\<generated by virt-v2v\) [^ <'"'\""']*/\1/' \
- -e 's/<rasd:InstanceId>'"$RE_UUID"'</<rasd:InstanceId>#UUID#</' \
- -e 's/<\(rasd:\)\?\(CreationDate\|LastModified\|last_modified_date\)>[^<]*</<\1\2>#DATE#</' \
- -e 's/\<ovf:vm_snapshot_id='"'$RE_UUID'/ovf:vm_snapshot_id='#UUID#'/g" \
- "$OVF"
-
-diff -u "$srcdir/test-v2v-o-vdsm-options.ovf.expected" \
- "$OVF"
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index fb1ee64d..447bc598 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -199,11 +199,7 @@ let rec main () =
| "disk" | "local" -> output_mode := `Disk
| "null" -> output_mode := `Null
| "openstack" | "osp" | "rhosp" -> output_mode := `Openstack
- | "ovirt" | "rhv" | "rhev" -> output_mode := `RHV
- | "ovirt-upload" | "ovirt_upload" | "rhv-upload" | "rhv_upload" ->
- output_mode := `RHV_Upload
| "qemu" -> output_mode := `QEmu
- | "vdsm" -> output_mode := `VDSM
| s ->
error (f_"unknown -o option: %s") s
in
@@ -471,10 +467,7 @@ read the man page virt-v2v(1).
| `Null -> (module Output_null.Null)
| `QEmu -> (module Output_qemu.QEMU)
| `Kubevirt -> (module Output_kubevirt.Kubevirt)
- | `Openstack -> (module Output_openstack.Openstack)
- | `RHV_Upload -> (module Output_rhv_upload.RHVUpload)
- | `RHV -> (module Output_rhv.RHV)
- | `VDSM -> (module Output_vdsm.VDSM) in
+ | `Openstack -> (module Output_openstack.Openstack) in
let output_options = {
Output.output_alloc = output_alloc;
@@ -499,7 +492,6 @@ read the man page virt-v2v(1).
*)
let remove_serial_console =
match output_mode with
- | `RHV | `VDSM -> true
| _ -> false in
(* Get the conversion options. *)