This commit adds a new -o kubevirt mode. You can specify where to
place the disks and metadata (guest.yaml) file using -os. Also
allocation mode (-oa) and disk format (-of) may be set. For example:
$ virt-v2v -i disk guest.img -o kubevirt -os /var/tmp
will generate /var/tmp/guest.yaml and /var/tmp/guest-sda
This is not finalized since undoubtedly the way the disks are handled
will have to be changed in future.
---
docs/virt-v2v.pod | 18 +++++
output/Makefile.am | 4 +
output/create_kubevirt_yaml.ml | 128 ++++++++++++++++++++++++++++++++
output/create_kubevirt_yaml.mli | 27 +++++++
output/output_kubevirt.ml | 96 ++++++++++++++++++++++++
output/output_kubevirt.mli | 21 ++++++
v2v/v2v.ml | 5 +-
7 files changed, 298 insertions(+), 1 deletion(-)
diff --git a/docs/virt-v2v.pod b/docs/virt-v2v.pod
index d627734b0d..7041a0d69d 100644
--- a/docs/virt-v2v.pod
+++ b/docs/virt-v2v.pod
@@ -429,6 +429,24 @@ instead.
Set the output method to OpenStack Glance. In this mode the converted
guest is uploaded to Glance. See L<virt-v2v-output-openstack(1)>.
+=item B<-o> B<kubevirt>
+
+Set the output method to I<kubevirt>.
+
+In this mode, the converted guest is written to a local directory
+specified by I<-os /dir> (the directory must exist). The converted
+guest’s disks are written to:
+
+ /dir/name-sda
+ /dir/name-sdb
+ [etc]
+
+and guest metadata is created in the associated YAML file:
+
+ /dir/name.yaml
+
+where C<name> is the guest name.
+
=item B<-o> B<libvirt>
Set the output method to I<libvirt>. This is the default.
diff --git a/output/Makefile.am b/output/Makefile.am
index dd488549db..7a13a99217 100644
--- a/output/Makefile.am
+++ b/output/Makefile.am
@@ -44,10 +44,12 @@ EXTRA_DIST = \
SOURCES_MLI = \
changeuid.mli \
create_libvirt_xml.mli \
+ create_kubevirt_yaml.mli \
openstack_image_properties.mli \
output.mli \
output_disk.mli \
output_glance.mli \
+ output_kubevirt.mli \
output_libvirt.mli \
output_null.mli \
output_openstack.mli \
@@ -69,6 +71,7 @@ SOURCES_ML = \
changeuid.ml \
python_script.ml \
create_libvirt_xml.ml \
+ create_kubevirt_yaml.ml \
qemuopts.ml \
openstack_image_properties.ml \
output_rhv_upload_cancel_source.ml \
@@ -81,6 +84,7 @@ SOURCES_ML = \
output.ml \
output_disk.ml \
output_glance.ml \
+ output_kubevirt.ml \
output_libvirt.ml \
output_null.ml \
output_openstack.ml \
diff --git a/output/create_kubevirt_yaml.ml b/output/create_kubevirt_yaml.ml
new file mode 100644
index 0000000000..205e9be38a
--- /dev/null
+++ b/output/create_kubevirt_yaml.ml
@@ -0,0 +1,128 @@
+(* virt-v2v
+ * Copyright (C) 2009-2022 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 Std_utils
+open Tools_utils
+open Common_gettext.Gettext
+
+open Types
+open Utils
+open YAML
+
+let create_kubevirt_yaml source inspect
+ { guestcaps; target_buses; target_firmware; target_nics }
+ outdisk_name output_format output_name =
+ (* The body of the YAML contains various sections attached to
+ * a tree. We fill in these sections first.
+ *)
+ let metadata = ref [] in
+ let devices = ref [] in
+ let disks = ref [] in
+ let resources = ref [] in
+ let volumes = ref [] in
+
+ (* The guest name. *)
+ List.push_back metadata ("name", String output_name);
+
+ (* The one Windows example I have includes this clock section, and
+ * the other non-Windows examples do not. I'm not certain this
+ * is correct. XXX
+ *)
+ if inspect.i_type = "windows" then (
+ List.push_back resources (
+ "clock", Assoc [
+ "timer", Assoc [
+ "hpet", Assoc [ "present", Bool false ];
+ "hyperv", List [];
+ "pit", Assoc [ "tickPolicy", String "delay" ];
+ "rtc", Assoc [ "tickPolicy", String "catchup" ];
+ ];
+ "utc", List []
+ ]
+ )
+ );
+
+ (* XXX genid *)
+
+ (* Memory. *)
+ let memory_str = sprintf "%LdMi" (source.s_memory /^ 1024_L /^ 1024_L) in
+ List.push_back resources ("requests", Assoc ["memory", String
memory_str]);
+
+ (* # vCPUs. XXX vendor, model, topology *)
+ List.push_back resources ("cpu", Assoc ["cores", Int
source.s_vcpu]);
+
+ (* Machine features. *)
+ let features = List.map (fun name -> name, List []) source.s_features in
+ List.push_back resources ("features", Assoc features);
+
+ (* XXX firmware, display, sound *)
+
+ (* XXX guestcaps: rng, balloon, vsock, virtio 1.0 *)
+
+ (* We're using local ("host") disks here which is not realistic. *)
+ Array.iter (
+ function
+ | BusSlotEmpty ->
+ (* XXX How to place devices on the bus? *) ()
+ | BusSlotDisk d ->
+ let disk_id = sprintf "disk-%d" d.s_disk_id in
+ let disk = Assoc [
+ "disk", Assoc ["bus", String "virtio"];
+ "name", String disk_id
+ ] in
+ List.push_back disks disk;
+ let vol = Assoc [
+ "hostDisk", Assoc [
+ "path", String (outdisk_name d.s_disk_id);
+ "type", String "Disk";
+ ];
+ "name", String disk_id
+ ] in
+ List.push_back volumes vol
+ | BusSlotRemovable _ ->
+ (* XXX removables *) ()
+ ) target_buses.target_virtio_blk_bus;
+
+ (* XXX ide, scsi, floppy, NICs *)
+
+ (* Create the final document. *)
+ if !disks <> [] then
+ List.push_back devices ("disks", List !disks);
+ let domain = ref [] in
+ if !devices <> [] then
+ List.push_back domain ("devices", Assoc !devices);
+ List.push_back domain ("resources", Assoc !resources);
+
+ let spec = ref [] in
+ List.push_back spec ("domain", Assoc !domain);
+ if !volumes <> [] then
+ List.push_back spec ("volumes", List !volumes);
+ List.push_back spec ("terminationGracePeriodSeconds", Int 0);
+
+ let body = [
+ "#", String generated_by;
+ "apiVersion", String "kubevirt.io/v1";
+ "kind", String "VirtualMachineInstance";
+ "metadata", Assoc !metadata;
+ "spec", Assoc !spec;
+ ] in
+
+ (* Return the YAML document. *)
+ Doc (Assoc body)
diff --git a/output/create_kubevirt_yaml.mli b/output/create_kubevirt_yaml.mli
new file mode 100644
index 0000000000..2d7eec1cc5
--- /dev/null
+++ b/output/create_kubevirt_yaml.mli
@@ -0,0 +1,27 @@
+(* virt-v2v
+ * Copyright (C) 2009-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.
+ *)
+
+(** Create kubevirt YAML for -o kubevirt *)
+
+val create_kubevirt_yaml : Types.source ->
+ Types.inspect -> Types.target_meta ->
+ (int -> string) -> string -> string ->
+ YAML.doc
+(** [create_kubevirt_yaml source inspect target_meta
+ target_features outdisk_map output_format output_name]
+ creates the Kubevirt machine description YAML document. *)
diff --git a/output/output_kubevirt.ml b/output/output_kubevirt.ml
new file mode 100644
index 0000000000..63ee8197c0
--- /dev/null
+++ b/output/output_kubevirt.ml
@@ -0,0 +1,96 @@
+(* virt-v2v
+ * Copyright (C) 2009-2022 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
+open Create_kubevirt_yaml
+
+module Kubevirt = struct
+ type poptions = output_allocation * string * string * string
+
+ type t = unit
+
+ let to_string options =
+ "-o kubevirt" ^
+ match options.output_storage with
+ | Some os -> " -os " ^ os
+ | None -> ""
+
+ 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 "local" "-op";
+
+ (* -os must be set to a directory. *)
+ let output_storage =
+ match options.output_storage with
+ | None ->
+ error (f_"-o kubevirt: output directory was not specified, use '-os
/dir'")
+ | 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.default source.s_name options.output_name in
+
+ options.output_alloc, options.output_format, output_name, output_storage
+
+ let setup dir options source =
+ let disks = get_disks dir in
+ let output_alloc, output_format, output_name, output_storage = options in
+
+ List.iter (
+ fun (i, size) ->
+ let socket = sprintf "%s/out%d" dir i in
+ On_exit.unlink socket;
+
+ (* Create the actual output disk. *)
+ let outdisk = disk_path output_storage output_name i in
+ output_to_local_file output_alloc output_format outdisk size socket
+ ) disks
+
+ let finalize dir options () source inspect target_meta =
+ let output_alloc, output_format, output_name, output_storage = options in
+
+ let doc = create_kubevirt_yaml source inspect target_meta
+ (disk_path output_storage output_name)
+ output_format output_name in
+
+ let file = output_storage // output_name ^ ".yaml" in
+ with_open_out file (fun chan -> YAML.doc_to_chan chan doc);
+
+ if verbose () then (
+ eprintf "resulting kubevirt YAML:\n";
+ YAML.doc_to_chan Stdlib.stderr doc;
+ eprintf "\n%!";
+ )
+
+ let request_size = None
+end
diff --git a/output/output_kubevirt.mli b/output/output_kubevirt.mli
new file mode 100644
index 0000000000..a34aa33a5b
--- /dev/null
+++ b/output/output_kubevirt.mli
@@ -0,0 +1,21 @@
+(* virt-v2v
+ * Copyright (C) 2009-2022 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 kubevirt] output mode. *)
+
+module Kubevirt : Output.OUTPUT
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index 6df82cfce9..fcf5e2d4d0 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -193,6 +193,7 @@ let rec main () =
error (f_"%s option used more than once on the command line")
"-o";
match mode with
| "glance" -> output_mode := `Glance
+ | "kubevirt" -> output_mode := `Kubevirt
| "libvirt" -> output_mode := `Libvirt
| "disk" | "local" -> output_mode := `Disk
| "null" -> output_mode := `Null
@@ -249,7 +250,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
("glance|libvirt|local|null|openstack|qemu|rhv|rhv-upload|vdsm",
set_output_mode),
+ [ S 'o' ], Getopt.String
("glance|kubevirt|libvirt|local|null|openstack|qemu|rhv|rhv-upload|vdsm",
set_output_mode),
s_"Set output mode (default: libvirt)";
[ M"oa" ], Getopt.String ("sparse|preallocated",
set_output_alloc),
s_"Set output allocation mode";
@@ -389,6 +390,7 @@ read the man page virt-v2v(1).
pr "input:ova\n";
pr "input:vmx\n";
pr "output:glance\n";
+ pr "output:kubevirt\n";
pr "output:libvirt\n";
pr "output:local\n";
pr "output:null\n";
@@ -482,6 +484,7 @@ read the man page virt-v2v(1).
| `Null -> (module Output_null.Null)
| `QEmu -> (module Output_qemu.QEMU)
| `Glance -> (module Output_glance.Glance)
+ | `Kubevirt -> (module Output_kubevirt.Kubevirt)
| `Openstack -> (module Output_openstack.Openstack)
| `RHV_Upload -> (module Output_rhv_upload.RHVUpload)
| `RHV -> (module Output_rhv.RHV)
--
2.35.1