[Libguestfs] [PATCH FOR DISCUSSION ONLY v2] v2v: Add -o kubevirt output mode.

Richard W.M. Jones rjones at redhat.com
Tue Mar 27 16:31:22 UTC 2018


XXX
No documentation.
Only handles one disk.
Network cards?
What firmware types does kubevirt support.
---
 v2v/Makefile.am         |   2 +
 v2v/cmdline.ml          |  20 +++++++++
 v2v/output_kubevirt.ml  | 115 ++++++++++++++++++++++++++++++++++++++++++++++++
 v2v/output_kubevirt.mli |  24 ++++++++++
 v2v/utils.ml            |   4 ++
 v2v/utils.mli           |   3 ++
 6 files changed, 168 insertions(+)

diff --git a/v2v/Makefile.am b/v2v/Makefile.am
index 8ec002fd3..3fbd3ef82 100644
--- a/v2v/Makefile.am
+++ b/v2v/Makefile.am
@@ -57,6 +57,7 @@ SOURCES_MLI = \
 	modules_list.mli \
 	name_from_disk.mli \
 	output_glance.mli \
+	output_kubevirt.mli \
 	output_libvirt.mli \
 	output_local.mli \
 	output_null.mli \
@@ -115,6 +116,7 @@ SOURCES_ML = \
 	output_qemu.ml \
 	output_rhv.ml \
 	output_vdsm.ml \
+	output_kubevirt.ml \
 	inspect_source.ml \
 	target_bus_assignment.ml \
 	cmdline.ml \
diff --git a/v2v/cmdline.ml b/v2v/cmdline.ml
index eae97db83..dbe766bf1 100644
--- a/v2v/cmdline.ml
+++ b/v2v/cmdline.ml
@@ -140,6 +140,7 @@ let parse_cmdline () =
       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 := `Local
     | "null" -> output_mode := `Null
@@ -487,6 +488,25 @@ read the man page virt-v2v(1).
       Output_glance.output_glance (),
       output_format, output_alloc
 
+    | `Kubevirt ->
+      if output_conn <> None then
+        error_option_cannot_be_used_in_output_mode "kubevirt" "-oc";
+      if output_password <> None then
+        error_option_cannot_be_used_in_output_mode "kubevirt" "-op";
+      let os =
+        match 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
+      if qemu_boot then
+        error_option_cannot_be_used_in_output_mode "kubevirt" "--qemu-boot";
+      if not do_copy then
+        error_option_cannot_be_used_in_output_mode "kubevirt" "--no-copy";
+      Output_kubevirt.output_kubevirt os,
+      output_format, output_alloc
+
     | `Not_set
     | `Libvirt ->
       if output_password <> None then
diff --git a/v2v/output_kubevirt.ml b/v2v/output_kubevirt.ml
new file mode 100644
index 000000000..68935a048
--- /dev/null
+++ b/v2v/output_kubevirt.ml
@@ -0,0 +1,115 @@
+(* 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.
+ *)
+
+open Printf
+
+open Std_utils
+open Tools_utils
+open Unix_utils
+open Common_gettext.Gettext
+
+open Types
+open Utils
+
+class output_kubevirt dir = object
+  inherit output
+
+  method as_options =
+    sprintf "-o kubevirt -os %s" dir
+
+  method supported_firmware = [ TargetBIOS; TargetUEFI ] (* XXX GUESS *)
+
+  val mutable name = ""
+
+  method prepare_targets source targets =
+    (* Only one disk is supported at present. XXX *)
+    if List.length targets <> 1 then
+      error (f_"-o kubevirt: this output mode only supports a single disk");
+
+    (* Don't use the source name directly, it must be munged
+     * for DNS (RFC 1123).
+     *)
+    name <- PCRE.replace ~global:true (PCRE.compile "[_.]+") "-"
+                         source.s_name;
+
+    List.mapi (
+      fun i t ->
+        (* This is the PVC name which is generated by the
+         * script that calls virt-v2v.
+         *)
+        let target_file =
+          TargetFile (dir // sprintf "%s-disk-%d" name (i+1)) in
+        { t with target_file }
+    ) targets
+
+  method create_metadata source targets target_buses
+                         guestcaps inspect target_firmware =
+    (* Create the YAML-format metadata. *)
+    with_open_out (dir // name ^ ".yaml") (
+      fun chan ->
+        let fpf fs = fprintf chan fs in
+        fpf "apiVersion: kubevirt.io/v1alpha1\n";
+        fpf "kind: OfflineVirtualMachine\n";
+        fpf "metadata:\n";
+        fpf "  name: %s\n" (yaml_quote name);
+        fpf "domain:\n";
+        fpf "  cpu:\n";
+        fpf "    cores: %d\n" source.s_vcpu;
+        fpf "  resources:\n";
+        fpf "    requests:\n";
+        fpf "      memory: %Ld%s\n" (source.s_memory /^ 1024_L) "KiB";
+        fpf "  os:\n";
+        fpf "    osinfo: %s\n" (yaml_quote inspect.i_osinfo);
+        fpf "  devices:\n";
+        fpf "    disks:\n";
+
+        (* virt-v2v (and indeed hardware) doesn't really work this way,
+         * in that there are several buses which may have multiple disks,
+         * and we're throwing all that careful mapping away, but here we
+         * are ... XXX
+         *)
+        let disk_bus =
+          match guestcaps.gcaps_block_bus with
+          | Virtio_blk -> "virtio"
+          | Virtio_SCSI -> "scsi"
+          | IDE -> "ide" in
+
+        List.iteri (
+          fun i t ->
+            fpf "    - name: disk-%d\n" (i+1);
+            fpf "      disk:\n";
+            fpf "        bus: %s\n" disk_bus;
+            fpf "      volumeName: volume-%d\n" (i+1)
+        ) targets;
+
+        fpf "  volumes:\n";
+        List.iteri (
+          fun i t ->
+            let filename =
+              match t.target_file with
+              | TargetFile t -> Filename.basename t
+              | TargetURI _ -> assert false in
+            fpf "  - name: volume-%d\n" (i+1);
+            fpf "    persistentVolumeClaim:\n";
+            fpf "      name: %s\n" (yaml_quote filename)
+        ) targets
+    )
+end
+
+let output_kubevirt = new output_kubevirt
+let () = Modules_list.register_output_module "kubevirt"
diff --git a/v2v/output_kubevirt.mli b/v2v/output_kubevirt.mli
new file mode 100644
index 000000000..3ff0041c7
--- /dev/null
+++ b/v2v/output_kubevirt.mli
@@ -0,0 +1,24 @@
+(* 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.
+ *)
+
+(** [-o kubevirt] target. *)
+
+val output_kubevirt : string -> Types.output
+(** [output_kubevirt dir] creates and returns a new
+    {!Types.output} object specialized for writing output to
+    KubeVirt. *)
diff --git a/v2v/utils.ml b/v2v/utils.ml
index 58331207f..e23aee378 100644
--- a/v2v/utils.ml
+++ b/v2v/utils.ml
@@ -39,6 +39,10 @@ let uri_quote str =
   done;
   String.concat "" (List.rev !xs)
 
+(* YAML quoting of strings. *)
+let yaml_quote str =
+  "'" ^ String.replace str "'" "''" ^ "'"
+
 (* Map guest architecture found by inspection to the architecture
  * that KVM must emulate.  Note for x86 we assume a 64 bit hypervisor.
  *)
diff --git a/v2v/utils.mli b/v2v/utils.mli
index 4a444aaa0..c5afaf88f 100644
--- a/v2v/utils.mli
+++ b/v2v/utils.mli
@@ -21,6 +21,9 @@
 val uri_quote : string -> string
 (** Take a string and perform %xx escaping as used in some parts of URLs. *)
 
+val yaml_quote : string -> string
+(** Returns a fully quoted YAML string (including end quotes). *)
+
 val kvm_arch : string -> string
 (** Map guest architecture found by inspection to the architecture
     that KVM must emulate.  Note for x86 we assume a 64 bit hypervisor. *)
-- 
2.13.2




More information about the Libguestfs mailing list