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

_______________________________________________
Libguestfs mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to