Files
libguestfs/v2v/output_vdsm.ml
Tomáš Golembiovský 285014b290 v2v: vdsm: add --vdsm-fixed-ovf option
Add option for -o vdsm that enables output of the modified OVF. oVirt
engine should already be able to consume the OVF, but let's not take any
chances and enable it only by command line argument. It can be made
default later when it receives proper testing.

Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com>
2018-02-22 15:06:13 +00:00

193 lines
7.0 KiB
OCaml
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(* virt-v2v
* Copyright (C) 2009-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.
*)
open Std_utils
open Tools_utils
open Common_gettext.Gettext
open Unix
open Printf
open Types
open Utils
type vdsm_params = {
image_uuids : string list;
vol_uuids : string list;
vm_uuid : string;
ovf_output : string;
compat : string;
ovf_flavour : Create_ovf.ovf_flavour;
}
class output_vdsm os vdsm_params output_alloc =
object
inherit output
method as_options =
sprintf "-o vdsm -os %s%s%s --vdsm-vm-uuid %s --vdsm-ovf-output %s%s%s" os
(String.concat ""
(List.map (sprintf " --vdsm-image-uuid %s") vdsm_params.image_uuids))
(String.concat ""
(List.map (sprintf " --vdsm-vol-uuid %s") vdsm_params.vol_uuids))
vdsm_params.vm_uuid
vdsm_params.ovf_output
(match vdsm_params.compat with
| "0.10" -> "" (* currently this is the default, so don't print it *)
| s -> sprintf " --vdsm-compat=%s" s)
(match vdsm_params.ovf_flavour with
| Create_ovf.OVirt -> "--vdsm-ovf-flavour=ovf"
(* currently this is the default, so don't print it *)
| Create_ovf.RHVExportStorageDomain -> "")
method supported_firmware = [ TargetBIOS ]
(* RHV doesn't support serial consoles. This causes the conversion
* step to remove it.
*)
method keep_serial_console = false
(* rhev-apt.exe will be installed (if available). *)
method install_rhev_apt = true
(* Data Domain mountpoint. *)
val mutable dd_mp = ""
val mutable dd_uuid = ""
(* This is called early on in the conversion and lets us choose the
* name of the target files that eventually get written by the main
* code.
*
* 'os' is the output storage domain (-os /rhv/data/<data center>/<data domain>)
* this is already mounted path.
*
* Note it's good to fail here (early) if there are any problems, since
* the next time we are called (in {!create_metadata}) we have already
* done the conversion and copy, and the user won't thank us for
* displaying errors there.
*)
method prepare_targets _ targets =
if List.length vdsm_params.image_uuids <> List.length targets ||
List.length vdsm_params.vol_uuids <> List.length targets then
error (f_"the number of --vdsm-image-uuid and --vdsm-vol-uuid parameters passed on the command line has to match the number of guest disk images (for this guest: %d)")
(List.length targets);
let mp, uuid =
let fields = String.nsplit "/" os 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")
os in
dd_mp <- mp;
dd_uuid <- uuid;
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
) vdsm_params.image_uuids;
(* Note that VDSM has to create this directory too. *)
if not (is_directory vdsm_params.ovf_output) then
error (f_"OVF (metadata) directory (%s) does not exist or is not a directory")
vdsm_params.ovf_output;
debug "VDSM: OVF (metadata) directory: %s" vdsm_params.ovf_output;
(* The final directory structure should look like this:
* /<MP>/<ESD_UUID>/images/
* <IMAGE_UUID_1>/<VOL_UUID_1> # first disk (gen'd by main code)
* <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 targets =
List.map (
fun ({ target_overlay = ov } as t, image_uuid, vol_uuid) ->
let ov_sd = ov.ov_sd in
let target_file = images_dir // image_uuid // vol_uuid in
debug "VDSM: will export %s to %s" ov_sd target_file;
{ t with target_file = TargetFile target_file }
) (List.combine3 targets vdsm_params.image_uuids vdsm_params.vol_uuids) in
(* Generate the .meta files associated with each volume. *)
let metas =
Create_ovf.create_meta_files output_alloc dd_uuid
vdsm_params.image_uuids targets in
List.iter (
fun ({ target_file }, meta) ->
let target_file =
match target_file with
| TargetFile s -> s
| TargetURI _ -> assert false in
let meta_filename = target_file ^ ".meta" in
with_open_out meta_filename (fun chan -> output_string chan meta)
) (List.combine targets metas);
(* Return the list of targets. *)
targets
method disk_create ?backingfile ?backingformat ?preallocation ?compat
?clustersize path format size =
let g = open_guestfs ~identifier:"vdsm_disk_create" () in
(* For qcow2, override v2v-supplied compat option, because RHEL 6
* nodes cannot handle qcow2 v3 (RHBZ#1145582, RHBZ#1400205).
*)
let compat =
if format <> "qcow2" then compat else Some vdsm_params.compat in
g#disk_create ?backingfile ?backingformat ?preallocation ?compat
?clustersize path format size
(* This is called after conversion to write the OVF metadata. *)
method create_metadata source targets _ guestcaps inspect target_firmware =
(* See #supported_firmware above. *)
assert (target_firmware = TargetBIOS);
(* Create the metadata. *)
let ovf = Create_ovf.create_ovf source targets guestcaps inspect
output_alloc dd_uuid
vdsm_params.image_uuids
vdsm_params.vol_uuids
vdsm_params.vm_uuid
vdsm_params.ovf_flavour in
(* Write it to the metadata file. *)
let file = vdsm_params.ovf_output // vdsm_params.vm_uuid ^ ".ovf" in
with_open_out file (fun chan -> DOM.doc_to_chan chan ovf)
end
let output_vdsm = new output_vdsm
let () = Modules_list.register_output_module "vdsm"