You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
virt-v2v/SOURCES/0019-RHEL-Remove-o-rhv-o-rh...

4729 lines
164 KiB

From c0f7a321feb08727609a160ac0c0f2c0adea68f2 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 | 31 +-
36 files changed, 5 insertions(+), 4226 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 b94fc8b5..f96fd69f 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
@@ -1287,26 +1102,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
@@ -1413,7 +1208,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 63624860..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 () =
- let version = Nbdkit.version () 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 () =
- if have_selinux then (
- let config = Nbdkit.config () in
- 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 ();
- error_unless_nbdkit_min_version ();
- error_unless_nbdkit_compiled_with_selinux ();
-
- (* 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 64a0147c..35133b08 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -201,11 +201,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
@@ -245,7 +241,7 @@ let rec main () =
s_"Map network in to out";
[ L"no-trim" ], Getopt.String ("-", no_trim_warning),
s_"Ignored for backwards compatibility";
- [ S 'o' ], Getopt.String ("kubevirt|libvirt|local|null|openstack|qemu|rhv|rhv-upload|vdsm", set_output_mode),
+ [ S 'o' ], Getopt.String ("kubevirt|libvirt|local|null|openstack|qemu", set_output_mode),
s_"Set output mode (default: libvirt)";
[ M"oa" ], Getopt.String ("sparse|preallocated", set_output_alloc),
s_"Set output allocation mode";
@@ -283,18 +279,6 @@ let rec main () =
s_"Same as -io vddk-thumbprint=thumbprint";
[ L"vddk-transports" ], Getopt.String ("transports", set_input_option_compat "vddk-transports"),
s_"Same as -io vddk-transports=transports";
- [ L"vdsm-compat" ], Getopt.String ("0.10|1.1", set_output_option_compat "vdsm-compat"),
- s_"Same as -oo vdsm-compat=0.10|1.1";
- [ L"vdsm-image-uuid" ], Getopt.String ("uuid", set_output_option_compat "vdsm-image-uuid"),
- s_"Same as -oo vdsm-image-uuid=uuid";
- [ L"vdsm-vol-uuid" ], Getopt.String ("uuid", set_output_option_compat "vdsm-vol-uuid"),
- s_"Same as -oo vdsm-vol-uuid=uuid";
- [ L"vdsm-vm-uuid" ], Getopt.String ("uuid", set_output_option_compat "vdsm-vm-uuid"),
- s_"Same as -oo vdsm-vm-uuid=uuid";
- [ L"vdsm-ovf-output" ], Getopt.String ("dir", set_output_option_compat "vdsm-ovf-output"),
- s_"Same as -oo vdsm-ovf-output=dir";
- [ L"vdsm-ovf-flavour" ], Getopt.String ("ovirt|rhvexp", set_output_option_compat "vdsm-ovf-flavour"),
- s_"Same as -oo vdsm-ovf-flavour=flavour";
[ L"vmtype" ], Getopt.String ("-", vmtype_warning),
s_"Ignored for backwards compatibility";
] in
@@ -306,9 +290,6 @@ let rec main () =
virt-v2v -ic vpx://vcenter.example.com/Datacenter/esxi -os imported esx_guest
-virt-v2v -ic vpx://vcenter.example.com/Datacenter/esxi esx_guest \
- -o rhv -os rhv.nfs:/export_domain --network ovirtmgmt
-
virt-v2v -i libvirtxml guest-domain.xml -o local -os /var/tmp
virt-v2v -i disk disk.img -o local -os /var/tmp
@@ -370,7 +351,6 @@ read the man page virt-v2v(1).
pr "vcenter-https\n";
pr "vddk\n";
pr "colours-option\n";
- pr "vdsm-compat-option\n";
pr "io/oo\n";
pr "mac-option\n";
pr "bandwidth-option\n";
@@ -386,9 +366,6 @@ read the man page virt-v2v(1).
pr "output:null\n";
pr "output:openstack\n";
pr "output:qemu\n";
- pr "output:rhv\n";
- pr "output:rhv-upload\n";
- pr "output:vdsm\n";
pr "convert:linux\n";
pr "convert:windows\n";
List.iter (pr "ovf:%s\n") Create_ovf.ovf_flavours;
@@ -473,10 +450,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;
@@ -501,7 +475,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. *)