[Libguestfs] [PATCH v2 4/4] v2v: in-place: request caps based on source config
Richard W.M. Jones
rjones at redhat.com
Mon Feb 22 15:04:57 UTC 2016
On Sat, Feb 20, 2016 at 11:26:10AM +0300, Roman Kagan wrote:
> In in-place mode, the decisions on which interfaces to use are made and
> the source configuration is created by the outside entity. So in that
> case v2v needs to look it up in the source configuraion, and try to
> follow.
>
> For that, the source configuration is used to populate requested caps
> object which is then passed to the convert routine.
>
> Signed-off-by: Roman Kagan <rkagan at virtuozzo.com>
> ---
>
> Notes:
> v2:
> - accept catch-all variants of source net and video as no preference
>
> v2v/types.mli | 6 +++---
> v2v/v2v.ml | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
> 2 files changed, 53 insertions(+), 8 deletions(-)
>
> diff --git a/v2v/types.mli b/v2v/types.mli
> index 0e40668..fbd45cf 100644
> --- a/v2v/types.mli
> +++ b/v2v/types.mli
> @@ -66,7 +66,7 @@ and source_disk = {
> (** A source disk. *)
>
> and s_controller = Source_IDE | Source_SCSI | Source_virtio_blk
> -(** Source disk controller.
> +(** Source disk controller (in ascending order of preference).
>
> For the purposes of this field, we can treat virtio-scsi as
> [SCSI]. However we don't support conversions from virtio in any
> @@ -88,7 +88,7 @@ and source_nic = {
> s_vnet_orig : string; (** Original network (if we map it). *)
> s_vnet_type : vnet_type; (** Source network type. *)
> }
> -(** Network adapter models. *)
> +(** Network adapter models (in ascending order of preference). *)
> and s_nic_model = Source_other_nic of string |
> Source_rtl8139 | Source_e1000 | Source_virtio_net
> (** Network interfaces. *)
> @@ -108,7 +108,7 @@ and s_display_listen =
> | LAddress of string (** Listen address. *)
> | LNetwork of string (** Listen network. *)
>
> -(** Video adapter model. *)
> +(** Video adapter model (in ascending order of preference). *)
> and source_video = Source_other_video of string |
> Source_Cirrus | Source_QXL
>
> diff --git a/v2v/v2v.ml b/v2v/v2v.ml
> index c828e48..608150f 100644
> --- a/v2v/v2v.ml
> +++ b/v2v/v2v.ml
> @@ -82,11 +82,17 @@ let rec main () =
> );
>
> let keep_serial_console = output#keep_serial_console in
> - let rcaps = {
> - rcaps_block_bus = None;
> - rcaps_net_bus = None;
> - rcaps_video = None;
> - } in
> + let rcaps =
> + match conversion_mode with
> + | Copying (_, _) ->
You can just write this:
| Copying _ ->
> + {
> + rcaps_block_bus = None;
> + rcaps_net_bus = None;
> + rcaps_video = None;
> + }
> + | In_place ->
> + rcaps_from_source source
> + in
> let guestcaps = do_convert g inspect source keep_serial_console rcaps in
>
> g#umount_all ();
> @@ -974,4 +980,43 @@ and preserve_overlays overlays src_name =
> printf (f_"Overlay saved as %s [--debug-overlays]\n") saved_filename
> ) overlays
>
> +and rcaps_from_source source =
> + (* Request guest caps based on source configuration. *)
> +
> + (* rely on s_controller enum being in ascending preference order, and None
> + * being smaller than Some anything *)
> + let best_block_type =
> + List.fold_left max None
> + (List.map (fun sd -> sd.s_controller) source.s_disks) in
> + let block_type =
> + match best_block_type with
> + | Some Source_virtio_blk -> Some Virtio_blk
> + | Some Source_SCSI -> None
> + | Some Source_IDE -> Some IDE
> + | None -> None in
> +
> + (* rely on s_nic_model enum being in ascending preference order, and None
> + * being smaller than Some anything *)
> + let best_net_type =
> + List.fold_left max None
> + (List.map (fun nic -> nic.s_nic_model) source.s_nics) in
> + let net_type =
> + match best_net_type with
> + | Some Source_virtio_net -> Some Virtio_net
> + | Some Source_e1000 -> Some E1000
> + | Some Source_rtl8139 -> Some RTL8139
> + | Some Source_other_nic _ | None -> None in
> +
> + let video =
> + match source.s_video with
> + | Some Source_QXL -> Some QXL
> + | Some Source_Cirrus -> Some Cirrus
> + | Some Source_other_video _ | None -> None in
> +
> + {
> + rcaps_block_bus = block_type;
> + rcaps_net_bus = net_type;
> + rcaps_video = video;
> + }
> +
> let () = run_main_and_handle_errors main
It's a bit surprising, because I thought that you'd want to pass in
the requested preferences on the command line?
About the specific issue of ordering, although what you've written
works, you could find a few surprises. eg:
$ rlwrap ocaml
OCaml version 4.02.3
# type t = A | B | C ;;
type t = A | B | C
# A < C ;;
- : bool = true
# A < B ;;
- : bool = true
# B < C ;;
- : bool = true
but ...
# type t = A | B of int | C ;;
type t = A | B of int | C
# A < C ;;
- : bool = true
# A < B 3 ;;
- : bool = true
# B 3 < C ;;
- : bool = false
This happens because adding a parameter to an enum changes the
internal representation.
So the code as written could stop working with innocuous changes to
the declared types, or even in a future version of OCaml, because it
depends on internals of the OCaml representation.
IMHO it's safer to make the ordering you want explicit. So:
let precedence_of_s_controller_option = function
| None -> 0 (* worst *)
| Some Source_IDE -> 1
| Some Source_SCSI -> 2
| Some Source_virtio_blk -> 3 (* best *)
and then you can have a function that finds the best "something" in a
list of "somethings", using a polymorphic precedence function to
compare the best:
let rec find_best precedence = function
| [] -> None, 0
| x :: xs ->
let precedence_of_x = precedence x
and best_in_xs, precedence_of_xs = find_best precedence xs in
if precedence_of_x > precedence_of_xs then
x, precedence_of_x
else
best_in_xs, precedence_of_xs
This function has type:
val find_best : ('a option -> int) -> 'a option list -> 'a option * int
(Note it returns a pair: the best choice and also the precedence
integer of that choice).
The code to find the best block_type or net_type falls out fairly easily:
let block_type =
let sctrls = List.map (fun sd -> sd.s_controller) source.s_disks in
let best, _ = find_best precedence_of_s_controller_option sctrls in
match best with
| Some Source_virtio_blk -> Some Virtio_blk
| Some Source_SCSI -> None
| Some Source_IDE -> Some IDE
| None -> None in
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-df lists disk usage of guests without needing to install any
software inside the virtual machine. Supports Linux and Windows.
http://people.redhat.com/~rjones/virt-df/
More information about the Libguestfs
mailing list