Roman Kagan
2016-Mar-11 13:54 UTC
[Libguestfs] [PATCH v3 0/5] v2v: more control over device types
The decision on which device type to use for disks, network and video cards on output used to be taken deep inside the converting functions. This is not always desirable. In particular, there are scenarios when this decision is made before the convertion takes place. E.g. in in-place mode, the decisions are taken and the output VM configuration is created outside of v2v tool. This patchset adds support for such scenarios. Specifically, - the input configuration parsers are taught to extract network and video device models in addition to storage controllers - the converting functions are taught to take the requested device types into consideration - the main routine in in-place mode takes the relevant data from the input VM and passes it to the converter The copying mode may eventually also profit from this patchset by taking command-line options for controlling device types, but this isn't included here. --- v3: - assume that source config in --in-place mode can't have more than one storage, network, and video types - add patch to better explain --in-place v2: - add catch-all string-valued variants for source network and video adapter models - use match instead of mixing match and if Roman Kagan (5): v2v: collect source network and video adapter types v2v: introduce requested guestcaps type v2v: take requested caps into account when converting v2v: in-place: request caps based on source config v2v: better explain --in-place test-data/phony-guests/guests.xml.in | 8 ++++ v2v/convert_linux.ml | 49 ++++++++++++++----- v2v/convert_windows.ml | 4 +- v2v/input_disk.ml | 2 + v2v/input_libvirtxml.ml | 27 +++++++++++ v2v/input_ova.ml | 2 + v2v/modules_list.ml | 3 +- v2v/modules_list.mli | 3 +- v2v/test-v2v-i-ova-formats.expected | 1 + v2v/test-v2v-i-ova-gz.expected | 1 + v2v/test-v2v-i-ova-two-disks.expected | 1 + v2v/test-v2v-print-source.sh | 4 +- v2v/types.ml | 77 +++++++++++++++++++++++++----- v2v/types.mli | 21 ++++++++- v2v/v2v.ml | 66 ++++++++++++++++++++++++-- v2v/virt-v2v.pod | 3 +- v2v/windows_virtio.ml | 89 ++++++++++++++++++++++++++--------- v2v/windows_virtio.mli | 6 +++ 18 files changed, 310 insertions(+), 57 deletions(-) -- 2.5.0
Roman Kagan
2016-Mar-11 13:54 UTC
[Libguestfs] [PATCH v3 1/5] v2v: collect source network and video adapter types
Those will be useful when making decisions about what configuration to set on output. The data is also included in --print-source so the tests are adjusted accordingly. Signed-off-by: Roman Kagan <rkagan@virtuozzo.com> --- Notes: v2: - add catch-all string-valued variants for source network and video adapter models test-data/phony-guests/guests.xml.in | 8 ++++++++ v2v/input_disk.ml | 2 ++ v2v/input_libvirtxml.ml | 27 +++++++++++++++++++++++++++ v2v/input_ova.ml | 2 ++ v2v/test-v2v-i-ova-formats.expected | 1 + v2v/test-v2v-i-ova-gz.expected | 1 + v2v/test-v2v-i-ova-two-disks.expected | 1 + v2v/test-v2v-print-source.sh | 4 +++- v2v/types.ml | 30 ++++++++++++++++++++++++++++-- v2v/types.mli | 9 +++++++++ 10 files changed, 82 insertions(+), 3 deletions(-) diff --git a/test-data/phony-guests/guests.xml.in b/test-data/phony-guests/guests.xml.in index 8f7ac81..9c7c989 100644 --- a/test-data/phony-guests/guests.xml.in +++ b/test-data/phony-guests/guests.xml.in @@ -276,6 +276,14 @@ <source file='@abs_builddir@/windows.img'/> <target dev='vda' bus='virtio'/> </disk> + <interface type='network'> + <mac address='00:11:22:33:44:55'/> + <source network='default'/> + <model type='virtio'/> + </interface> + <video> + <model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1'/> + </video> </devices> </domain> diff --git a/v2v/input_disk.ml b/v2v/input_disk.ml index 1cb6713..17ad61d 100644 --- a/v2v/input_disk.ml +++ b/v2v/input_disk.ml @@ -75,6 +75,7 @@ class input_disk input_format disk = object (* Give the guest a simple generic network interface. *) let network = { s_mac = None; + s_nic_model = None; s_vnet = "default"; s_vnet_orig = "default"; s_vnet_type = Network } in @@ -89,6 +90,7 @@ class input_disk input_format disk = object s_display Some { s_display_type = Window; s_keymap = None; s_password = None; s_listen = LNone; s_port = None }; + s_video = None; s_sound = None; s_disks = [disk]; s_removables = []; diff --git a/v2v/input_libvirtxml.ml b/v2v/input_libvirtxml.ml index 3537011..9d8963d 100644 --- a/v2v/input_libvirtxml.ml +++ b/v2v/input_libvirtxml.ml @@ -140,6 +140,23 @@ let parse_libvirt_xml ?conn xml None ) in + (* Video adapter. *) + let video + let obj = Xml.xpath_eval_expression xpathctx "/domain/devices/video" in + let nr_nodes = Xml.xpathobj_nr_nodes obj in + if nr_nodes < 1 then None + else ( + (* Ignore everything except the first <video> device. *) + let node = Xml.xpathobj_node obj 0 in + + Xml.xpathctx_set_current_context xpathctx node; + match xpath_string "model/@type" with + | None -> None + | Some "qxl" | Some "virtio" -> Some Source_QXL + | Some "cirrus" | Some "vga" -> Some Source_Cirrus + | Some model -> Some (Source_other_video model) + ) in + (* Sound card. *) let sound let obj = Xml.xpath_eval_expression xpathctx "/domain/devices/sound" in @@ -329,6 +346,14 @@ let parse_libvirt_xml ?conn xml | Some "00:00:00:00:00:00" (* thanks, VMware *) -> None | Some mac -> Some mac in + let model + match xpath_string "model/@type" with + | None -> None + | Some "virtio" -> Some Source_virtio_net + | Some "e1000" -> Some Source_e1000 + | Some "rtl8139" -> Some Source_rtl8139 + | Some model -> Some (Source_other_nic model) in + let vnet_type match xpath_string "@type" with | Some "network" -> Some Network @@ -340,6 +365,7 @@ let parse_libvirt_xml ?conn xml let add_nic vnet let nic = { s_mac = mac; + s_nic_model = model; s_vnet = vnet; s_vnet_orig = vnet; s_vnet_type = vnet_type @@ -366,6 +392,7 @@ let parse_libvirt_xml ?conn xml s_features = features; s_firmware = UnknownFirmware; (* XXX until RHBZ#1217444 is fixed *) s_display = display; + s_video = video; s_sound = sound; s_disks = []; s_removables = removables; diff --git a/v2v/input_ova.ml b/v2v/input_ova.ml index c8c6b94..db0588d 100644 --- a/v2v/input_ova.ml +++ b/v2v/input_ova.ml @@ -350,6 +350,7 @@ object xpath_string_default "rasd:ElementName/text()" (sprintf"eth%d" i) in let nic = { s_mac = None; + s_nic_model = None; s_vnet = vnet; s_vnet_orig = vnet; s_vnet_type = Network; @@ -366,6 +367,7 @@ object s_features = []; (* XXX *) s_firmware = firmware; s_display = None; (* XXX *) + s_video = None; s_sound = None; s_disks = disks; s_removables = removables; diff --git a/v2v/test-v2v-i-ova-formats.expected b/v2v/test-v2v-i-ova-formats.expected index c83e5dd..7049aee 100644 --- a/v2v/test-v2v-i-ova-formats.expected +++ b/v2v/test-v2v-i-ova-formats.expected @@ -7,6 +7,7 @@ hypervisor type: vmware CPU features: firmware: uefi display: + video: sound: disks: disk1.vmdk (vmdk) [scsi] diff --git a/v2v/test-v2v-i-ova-gz.expected b/v2v/test-v2v-i-ova-gz.expected index be6cde3..50ba746 100644 --- a/v2v/test-v2v-i-ova-gz.expected +++ b/v2v/test-v2v-i-ova-gz.expected @@ -7,6 +7,7 @@ hypervisor type: vmware CPU features: firmware: bios display: + video: sound: disks: .vmdk (vmdk) [scsi] diff --git a/v2v/test-v2v-i-ova-two-disks.expected b/v2v/test-v2v-i-ova-two-disks.expected index dcbd43e..cc850a7 100644 --- a/v2v/test-v2v-i-ova-two-disks.expected +++ b/v2v/test-v2v-i-ova-two-disks.expected @@ -7,6 +7,7 @@ hypervisor type: vmware CPU features: firmware: bios display: + video: sound: disks: disk1.vmdk (vmdk) [scsi] diff --git a/v2v/test-v2v-print-source.sh b/v2v/test-v2v-print-source.sh index 8dd0145..8af6104 100755 --- a/v2v/test-v2v-print-source.sh +++ b/v2v/test-v2v-print-source.sh @@ -60,11 +60,13 @@ hypervisor type: test CPU features: firmware: unknown display: + video: qxl sound: disks: /windows.img (raw) [virtio] removable media: -NICs:" ]; then +NICs: + Network \"default\" mac: 00:11:22:33:44:55 [virtio]" ]; then echo "$0: unexpected output from test:" cat $d/output.orig exit 1 diff --git a/v2v/types.ml b/v2v/types.ml index a9d28e0..a082c37 100644 --- a/v2v/types.ml +++ b/v2v/types.ml @@ -32,6 +32,7 @@ type source = { s_features : string list; s_firmware : source_firmware; s_display : source_display option; + s_video : source_video option; s_sound : source_sound option; s_disks : source_disk list; s_removables : source_removable list; @@ -63,10 +64,13 @@ and source_removable = { and s_removable_type = CDROM | Floppy and source_nic = { s_mac : string option; + s_nic_model : s_nic_model option; s_vnet : string; s_vnet_orig : string; s_vnet_type : vnet_type; } +and s_nic_model = Source_other_nic of string | + Source_rtl8139 | Source_e1000 | Source_virtio_net and vnet_type = Bridge | Network and source_display = { s_display_type : s_display_type; @@ -81,6 +85,9 @@ and s_display_listen | LAddress of string | LNetwork of string +and source_video = Source_other_video of string | + Source_Cirrus | Source_QXL + and source_sound = { s_sound_model : source_sound_model; } @@ -95,6 +102,7 @@ hypervisor type: %s CPU features: %s firmware: %s display: %s + video: %s sound: %s disks: %s @@ -112,6 +120,9 @@ NICs: (match s.s_display with | None -> "" | Some display -> string_of_source_display display) + (match s.s_video with + | None -> "" + | Some video -> string_of_source_video video) (match s.s_sound with | None -> "" | Some sound -> string_of_source_sound sound) @@ -188,13 +199,23 @@ and string_of_source_removable { s_removable_type = typ; | Some controller -> " [" ^ string_of_controller controller ^ "]") (match i with None -> "" | Some i -> sprintf " in slot %d" i) -and string_of_source_nic { s_mac = mac; s_vnet = vnet; s_vnet_type = typ } - sprintf "\t%s \"%s\"%s" +and string_of_source_nic { s_mac = mac; s_nic_model = model; s_vnet = vnet; + s_vnet_type = typ } + sprintf "\t%s \"%s\"%s%s" (match typ with Bridge -> "Bridge" | Network -> "Network") vnet (match mac with | None -> "" | Some mac -> " mac: " ^ mac) + (match model with + | None -> "" + | Some model -> " [" ^ string_of_nic_model model ^ "]") + +and string_of_nic_model = function + | Source_virtio_net -> "virtio" + | Source_e1000 -> "e1000" + | Source_rtl8139 -> "rtl8139" + | Source_other_nic model -> model and string_of_source_display { s_display_type = typ; s_keymap = keymap; s_password = password; @@ -209,6 +230,11 @@ and string_of_source_display { s_display_type = typ; | LNetwork n -> sprintf " listening on network %s" n ) +and string_of_source_video = function + | Source_QXL -> "qxl" + | Source_Cirrus -> "cirrus" + | Source_other_video video -> video + and string_of_source_sound { s_sound_model = model } string_of_source_sound_model model diff --git a/v2v/types.mli b/v2v/types.mli index f482a92..f58028f 100644 --- a/v2v/types.mli +++ b/v2v/types.mli @@ -29,6 +29,7 @@ type source = { s_features : string list; (** Machine features. *) s_firmware : source_firmware; (** Firmware (BIOS or EFI). *) s_display : source_display option; (** Guest display. *) + s_video : source_video option; (** Video adapter. *) s_sound : source_sound option; (** Sound card. *) s_disks : source_disk list; (** Disk images. *) s_removables : source_removable list; (** CDROMs etc. *) @@ -82,10 +83,14 @@ and s_removable_type = CDROM | Floppy and source_nic = { s_mac : string option; (** MAC address. *) + s_nic_model : s_nic_model option; (** Network adapter model. *) s_vnet : string; (** Source network name. *) s_vnet_orig : string; (** Original network (if we map it). *) s_vnet_type : vnet_type; (** Source network type. *) } +(** Network adapter models. *) +and s_nic_model = Source_other_nic of string | + Source_rtl8139 | Source_e1000 | Source_virtio_net (** Network interfaces. *) and vnet_type = Bridge | Network @@ -103,6 +108,10 @@ and s_display_listen | LAddress of string (** Listen address. *) | LNetwork of string (** Listen network. *) +(** Video adapter model. *) +and source_video = Source_other_video of string | + Source_Cirrus | Source_QXL + and source_sound = { s_sound_model : source_sound_model; (** Sound model. *) } -- 2.5.0
Roman Kagan
2016-Mar-11 13:54 UTC
[Libguestfs] [PATCH v3 2/5] v2v: introduce requested guestcaps type
Introduce a type to contain the guestcaps that are to be put in effect in the converted VM: options of the block type, net type, and video. It'll be populated by the caller and passed into convert function to affect its choice of devices and drivers. Signed-off-by: Roman Kagan <rkagan@virtuozzo.com> --- v2v/types.ml | 47 +++++++++++++++++++++++++++++++++++++---------- v2v/types.mli | 8 ++++++++ 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/v2v/types.ml b/v2v/types.ml index a082c37..821b7ec 100644 --- a/v2v/types.ml +++ b/v2v/types.ml @@ -361,10 +361,29 @@ type guestcaps = { gcaps_arch : string; gcaps_acpi : bool; } +and requested_guestcaps = { + rcaps_block_bus : guestcaps_block_type option; + rcaps_net_bus : guestcaps_net_type option; + rcaps_video : guestcaps_video_type option; +} and guestcaps_block_type = Virtio_blk | IDE and guestcaps_net_type = Virtio_net | E1000 | RTL8139 and guestcaps_video_type = QXL | Cirrus +let string_of_block_type block_type + (match block_type with + | Virtio_blk -> "virtio-blk" + | IDE -> "ide") +let string_of_net_type net_type + (match net_type with + | Virtio_net -> "virtio-net" + | E1000 -> "e1000" + | RTL8139 -> "rtl8139") +let string_of_video video + (match video with + | QXL -> "qxl" + | Cirrus -> "cirrus") + let string_of_guestcaps gcaps sprintf "\ gcaps_block_bus = %s @@ -372,19 +391,27 @@ gcaps_net_bus = %s gcaps_video = %s gcaps_arch = %s gcaps_acpi = %b -" (match gcaps.gcaps_block_bus with - | Virtio_blk -> "virtio" - | IDE -> "ide") - (match gcaps.gcaps_net_bus with - | Virtio_net -> "virtio-net" - | E1000 -> "e1000" - | RTL8139 -> "rtl8139") - (match gcaps.gcaps_video with - | QXL -> "qxl" - | Cirrus -> "cirrus") +" (string_of_block_type gcaps.gcaps_block_bus) + (string_of_net_type gcaps.gcaps_net_bus) + (string_of_video gcaps.gcaps_video) gcaps.gcaps_arch gcaps.gcaps_acpi +let string_of_requested_guestcaps rcaps + sprintf "\ +rcaps_block_bus = %s +rcaps_net_bus = %s +rcaps_video = %s +" (match rcaps.rcaps_block_bus with + | None -> "unspecified" + | Some block_type -> (string_of_block_type block_type)) + (match rcaps.rcaps_net_bus with + | None -> "unspecified" + | Some net_type -> (string_of_net_type net_type)) + (match rcaps.rcaps_video with + | None -> "unspecified" + | Some video -> (string_of_video video)) + type target_buses = { target_virtio_blk_bus : target_bus_slot array; target_ide_bus : target_bus_slot array; diff --git a/v2v/types.mli b/v2v/types.mli index f58028f..0e40668 100644 --- a/v2v/types.mli +++ b/v2v/types.mli @@ -207,6 +207,13 @@ type guestcaps = { gcaps_arch : string; (** Architecture that KVM must emulate. *) gcaps_acpi : bool; (** True if guest supports acpi. *) } +and requested_guestcaps = { + rcaps_block_bus : guestcaps_block_type option; + rcaps_net_bus : guestcaps_net_type option; + rcaps_video : guestcaps_video_type option; + (** Requested guest capabilities, to allow the caller to affect converter + choices *) +} (** Guest capabilities after conversion. eg. Was virtio found or installed? *) and guestcaps_block_type = Virtio_blk | IDE @@ -214,6 +221,7 @@ and guestcaps_net_type = Virtio_net | E1000 | RTL8139 and guestcaps_video_type = QXL | Cirrus val string_of_guestcaps : guestcaps -> string +val string_of_requested_guestcaps : requested_guestcaps -> string type target_buses = { target_virtio_blk_bus : target_bus_slot array; -- 2.5.0
Roman Kagan
2016-Mar-11 13:54 UTC
[Libguestfs] [PATCH v3 3/5] v2v: take requested caps into account when converting
Give the caller certain control over what kind of interface to use for virtual disks, network and video cards upon conversion. For that, make convert functions accept additional rcaps parameter containing an object with optional capabilities similar to the ones produced on output, with None indicating that the decision is left to the convert function itself. To facilicate review, this patch unconditionally passes rcaps with no preferences; populating it with more sensible values is done in a followup patch. Signed-off-by: Roman Kagan <rkagan@virtuozzo.com> --- Notes: v2: - use match instead of mixing match and if v2v/convert_linux.ml | 49 +++++++++++++++++++-------- v2v/convert_windows.ml | 4 +-- v2v/modules_list.ml | 3 +- v2v/modules_list.mli | 3 +- v2v/v2v.ml | 13 ++++++-- v2v/windows_virtio.ml | 89 +++++++++++++++++++++++++++++++++++++------------- v2v/windows_virtio.mli | 6 ++++ 7 files changed, 125 insertions(+), 42 deletions(-) diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml index 74fd835..0a2e439 100644 --- a/v2v/convert_linux.ml +++ b/v2v/convert_linux.ml @@ -59,7 +59,7 @@ let string_of_kernel_info ki ki.ki_supports_virtio ki.ki_is_xen_kernel ki.ki_is_debug (* The conversion function. *) -let rec convert ~keep_serial_console (g : G.guestfs) inspect source +let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps (*----------------------------------------------------------------------*) (* Inspect the guest first. We already did some basic inspection in * the common v2v.ml code, but that has to deal with generic guests @@ -1115,19 +1115,26 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source warning (f_"The display driver was updated to '%s', but X11 does not seem to be installed in the guest. X may not function correctly.") video_driver - and configure_kernel_modules virtio + and configure_kernel_modules block_type net_type (* This function modifies modules.conf (and its various aliases). *) (* Update 'alias eth0 ...'. *) let paths = augeas_modprobe ". =~ regexp('eth[0-9]+')" in - let net_device = if virtio then "virtio_net" else "e1000" in + let net_device + match net_type with + | Virtio_net -> "virtio_net" + | E1000 -> "e1000" + | RTL8139 -> "rtl8139cp" + in + List.iter ( fun path -> g#aug_set (path ^ "/modulename") net_device ) paths; (* Update 'alias scsi_hostadapter ...' *) let paths = augeas_modprobe ". =~ regexp('scsi_hostadapter.*')" in - if virtio then ( + match block_type with + | Virtio_blk -> if paths <> [] then ( (* There's only 1 scsi controller in the converted guest. * Convert only the first scsi_hostadapter entry to virtio @@ -1150,10 +1157,10 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source g#aug_set (sprintf "/files%s/alias[last()]/modulename" modpath) "virtio_blk" ) - ) else (* not virtio *) ( + | IDE -> (* There is no scsi controller in an IDE guest. *) List.iter (fun path -> ignore (g#aug_rm path)) (List.rev paths) - ); + ; (* Display a warning about any leftover Xen modules which we * haven't converted. These are likely to cause an error when @@ -1215,7 +1222,7 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source !modpath - and remap_block_devices virtio + and remap_block_devices block_type (* This function's job is to iterate over boot configuration * files, replacing "hda" with "vda" or whatever is appropriate. * This is mostly applicable to old guests, since newer OSes use @@ -1238,7 +1245,9 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source (* All modern distros use libata: *) "sd" in let block_prefix_after_conversion - if virtio then "vd" else ide_block_prefix in + match block_type with + | Virtio_blk -> "vd" + | IDE -> ide_block_prefix in let map mapi ( @@ -1411,15 +1420,29 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source let acpi = supports_acpi () in - let video = get_display_driver () in + let video + match rcaps.rcaps_video with + | None -> get_display_driver () + | Some video -> video in + + let block_type + match rcaps.rcaps_block_bus with + | None -> if virtio then Virtio_blk else IDE + | Some block_type -> block_type in + + let net_type + match rcaps.rcaps_net_bus with + | None -> if virtio then Virtio_net else E1000 + | Some net_type -> net_type in + configure_display_driver video; - remap_block_devices virtio; - configure_kernel_modules virtio; + remap_block_devices block_type; + configure_kernel_modules block_type net_type; rebuild_initrd kernel; let guestcaps = { - gcaps_block_bus = if virtio then Virtio_blk else IDE; - gcaps_net_bus = if virtio then Virtio_net else E1000; + gcaps_block_bus = block_type; + gcaps_net_bus = net_type; gcaps_video = video; gcaps_arch = Utils.kvm_arch inspect.i_arch; gcaps_acpi = acpi; diff --git a/v2v/convert_windows.ml b/v2v/convert_windows.ml index f6f0911..5daae6c 100644 --- a/v2v/convert_windows.ml +++ b/v2v/convert_windows.ml @@ -37,7 +37,7 @@ module G = Guestfs * time the Windows VM is booted on KVM. *) -let convert ~keep_serial_console (g : G.guestfs) inspect source +let convert ~keep_serial_console (g : G.guestfs) inspect source rcaps (* Get the data directory. *) let virt_tools_data_dir try Sys.getenv "VIRT_TOOLS_DATA_DIR" @@ -283,7 +283,7 @@ if errorlevel 3010 exit /b 0 disable_services root current_cs; disable_autoreboot root current_cs; Windows_virtio.install_drivers g inspect systemroot - root current_cs + root current_cs rcaps and disable_services root current_cs (* Disable miscellaneous services. *) diff --git a/v2v/modules_list.ml b/v2v/modules_list.ml index ec964c1..fd7b2ff 100644 --- a/v2v/modules_list.ml +++ b/v2v/modules_list.ml @@ -29,7 +29,8 @@ and output_modules () = List.sort compare !output_modules type conversion_fn keep_serial_console:bool -> - Guestfs.guestfs -> Types.inspect -> Types.source -> Types.guestcaps + Guestfs.guestfs -> Types.inspect -> Types.source -> + Types.requested_guestcaps -> Types.guestcaps let convert_modules = ref [] diff --git a/v2v/modules_list.mli b/v2v/modules_list.mli index 967a319..0560832 100644 --- a/v2v/modules_list.mli +++ b/v2v/modules_list.mli @@ -32,7 +32,8 @@ val output_modules : unit -> string list type conversion_fn keep_serial_console:bool -> - Guestfs.guestfs -> Types.inspect -> Types.source -> Types.guestcaps + Guestfs.guestfs -> Types.inspect -> Types.source -> + Types.requested_guestcaps -> Types.guestcaps val register_convert_module : (Types.inspect -> bool) -> string -> conversion_fn -> unit (** [register_convert_module inspect_fn name fn] registers a diff --git a/v2v/v2v.ml b/v2v/v2v.ml index 5082e9a..c828e48 100644 --- a/v2v/v2v.ml +++ b/v2v/v2v.ml @@ -82,7 +82,12 @@ let rec main () ); let keep_serial_console = output#keep_serial_console in - let guestcaps = do_convert g inspect source keep_serial_console in + let rcaps = { + rcaps_block_bus = None; + rcaps_net_bus = None; + rcaps_video = None; + } in + let guestcaps = do_convert g inspect source keep_serial_console rcaps in g#umount_all (); @@ -699,7 +704,7 @@ and check_target_free_space mpstats source targets output output#check_target_free_space source targets -and do_convert g inspect source keep_serial_console +and do_convert g inspect source keep_serial_console rcaps (* Conversion. *) (match inspect.i_product_name with | "unknown" -> @@ -714,7 +719,9 @@ and do_convert g inspect source keep_serial_console error (f_"virt-v2v is unable to convert this guest type (%s/%s)") inspect.i_type inspect.i_distro in if verbose () then printf "picked conversion module %s\n%!" conversion_name; - let guestcaps = convert ~keep_serial_console g inspect source in + if verbose () then printf "requested caps: %s%!" + (string_of_requested_guestcaps rcaps); + let guestcaps = convert ~keep_serial_console g inspect source rcaps in if verbose () then printf "%s%!" (string_of_guestcaps guestcaps); (* Did we manage to install virtio drivers? *) diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml index e63f39e..f538b36 100644 --- a/v2v/windows_virtio.ml +++ b/v2v/windows_virtio.ml @@ -33,57 +33,102 @@ let virtio_win with Not_found -> Guestfs_config.datadir // "virtio-win" -let rec install_drivers g inspect systemroot root current_cs +let rec install_drivers g inspect systemroot root current_cs rcaps (* Copy the virtio drivers to the guest. *) let driverdir = sprintf "%s/Drivers/VirtIO" systemroot in g#mkdir_p driverdir; if not (copy_drivers g inspect driverdir) then ( - warning (f_"there are no virtio drivers available for this version of Windows (%d.%d %s %s). virt-v2v looks for drivers in %s\n\nThe guest will be configured to use slower emulated devices.") + match rcaps with + | { rcaps_block_bus = Some Virtio_blk } + | { rcaps_net_bus = Some Virtio_net } + | { rcaps_video = Some QXL } -> + error (f_"there are no virtio drivers available for this version of Windows (%d.%d %s %s). virt-v2v looks for drivers in %s") inspect.i_major_version inspect.i_minor_version inspect.i_arch - inspect.i_product_variant virtio_win; - ( IDE, RTL8139, Cirrus ) + inspect.i_product_variant virtio_win + + | { rcaps_block_bus = (Some IDE | None); + rcaps_net_bus = ((Some E1000 | Some RTL8139 | None) as net_type); + rcaps_video = (Some Cirrus | None) } -> + warning (f_"there are no virtio drivers available for this version of Windows (%d.%d %s %s). virt-v2v looks for drivers in %s\n\nThe guest will be configured to use slower emulated devices.") + inspect.i_major_version inspect.i_minor_version inspect.i_arch + inspect.i_product_variant virtio_win; + let net_type + match net_type with + | Some model -> model + | None -> RTL8139 in + (IDE, net_type, Cirrus) ) else ( (* Can we install the block driver? *) let block : guestcaps_block_type - let source = driverdir // "viostor.sys" in - if g#exists source then ( + let has_viostor = g#exists (driverdir // "viostor.inf") in + match rcaps.rcaps_block_bus, has_viostor with + | Some Virtio_blk, false -> + error (f_"there is no viostor (virtio block device) driver for this version of Windows (%d.%d %s). virt-v2v looks for this driver in %s\n\nThe guest will be configured to use a slower emulated device.") + inspect.i_major_version inspect.i_minor_version + inspect.i_arch virtio_win + + | None, false -> + warning (f_"there is no viostor (virtio block device) driver for this version of Windows (%d.%d %s). virt-v2v looks for this driver in %s\n\nThe guest will be configured to use a slower emulated device.") + inspect.i_major_version inspect.i_minor_version + inspect.i_arch virtio_win; + IDE + + | (Some Virtio_blk | None), true -> + (* Block driver needs tweaks to allow booting; the rest is set up by PnP + * manager *) + let source = driverdir // "viostor.sys" in let target = sprintf "%s/system32/drivers/viostor.sys" systemroot in let target = g#case_sensitive_path target in g#cp source target; add_viostor_to_registry g inspect root current_cs; Virtio_blk - ) else ( - warning (f_"there is no viostor (virtio block device) driver for this version of Windows (%d.%d %s). virt-v2v looks for this driver in %s\n\nThe guest will be configured to use a slower emulated device.") - inspect.i_major_version inspect.i_minor_version - inspect.i_arch virtio_win; - IDE - ) in + + | Some IDE, _ -> + IDE in (* Can we install the virtio-net driver? *) let net : guestcaps_net_type - if not (g#exists (driverdir // "netkvm.inf")) then ( + let has_netkvm = g#exists (driverdir // "netkvm.inf") in + match rcaps.rcaps_net_bus, has_netkvm with + | Some Virtio_net, false -> + error (f_"there is no virtio network driver for this version of Windows (%d.%d %s). virt-v2v looks for this driver in %s") + inspect.i_major_version inspect.i_minor_version + inspect.i_arch virtio_win + + | None, false -> warning (f_"there is no virtio network driver for this version of Windows (%d.%d %s). virt-v2v looks for this driver in %s\n\nThe guest will be configured to use a slower emulated device.") inspect.i_major_version inspect.i_minor_version inspect.i_arch virtio_win; RTL8139 - ) - else - (* It will be installed at firstboot. *) - Virtio_net in + + | (Some Virtio_net | None), true -> + Virtio_net + + | Some net_type, _ -> + net_type in (* Can we install the QXL driver? *) let video : guestcaps_video_type - if not (g#exists (driverdir // "qxl.inf")) then ( + let has_qxl = g#exists (driverdir // "qxl.inf") in + match rcaps.rcaps_video, has_qxl with + | Some QXL, false -> + error (f_"there is no QXL driver for this version of Windows (%d.%d %s). virt-v2v looks for this driver in %s") + inspect.i_major_version inspect.i_minor_version + inspect.i_arch virtio_win + + | None, false -> warning (f_"there is no QXL driver for this version of Windows (%d.%d %s). virt-v2v looks for this driver in %s\n\nThe guest will be configured to use a basic VGA display driver.") inspect.i_major_version inspect.i_minor_version inspect.i_arch virtio_win; Cirrus - ) - else - (* It will be installed at firstboot. *) - QXL in + + | (Some QXL | None), true -> + QXL + + | Some Cirrus, _ -> + Cirrus in (block, net, video) ) diff --git a/v2v/windows_virtio.mli b/v2v/windows_virtio.mli index 2046fae..86dbaf6 100644 --- a/v2v/windows_virtio.mli +++ b/v2v/windows_virtio.mli @@ -20,6 +20,7 @@ val install_drivers : Guestfs.guestfs -> Types.inspect -> string -> int64 -> string -> + Types.requested_guestcaps -> Types.guestcaps_block_type * Types.guestcaps_net_type * Types.guestcaps_video_type (** [install_drivers g inspect systemroot root current_cs] installs virtio drivers from the driver directory or driver @@ -30,6 +31,11 @@ val install_drivers when this function is called). [current_cs] is the name of the [CurrentControlSet] (eg. ["ControlSet001"]). + [rcaps] is the set of guest "capabilities" requested by the caller. This + may include the type of the block driver, network driver, and video driver. + install_drivers will adjust its choices based on that information, and + abort if the requested driver wasn't found. + This returns the tuple [(block_driver, net_driver, video_driver)] reflecting what devices are now required by the guest, either virtio devices if we managed to install those, or legacy devices -- 2.5.0
Roman Kagan
2016-Mar-11 13:54 UTC
[Libguestfs] [PATCH v3 4/5] v2v: in-place: request caps based on source config
In in-place mode, the decisions on which interfaces to use are made and the source VM 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 VM configuration is used to populate requested caps object which is then passed to the convert routine. It's assumed that the configuration has exactly one type of storage devices and no more than one type of network and video adapters; anything else is rejected. Signed-off-by: Roman Kagan <rkagan@virtuozzo.com> --- Notes: v3: - assume that source config in --in-place mode can't have more than one storage, network, and video types v2: - accept catch-all variants of source net and video as no preference v2v/types.mli | 4 +++- v2v/v2v.ml | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/v2v/types.mli b/v2v/types.mli index 0e40668..4595a1f 100644 --- a/v2v/types.mli +++ b/v2v/types.mli @@ -120,8 +120,10 @@ and source_sound_model val string_of_source : source -> string val string_of_source_disk : source_disk -> string - +val string_of_controller : s_controller -> string +val string_of_nic_model : s_nic_model -> string val string_of_source_sound_model : source_sound_model -> string +val string_of_source_video : source_video -> string val string_of_source_hypervisor : source_hypervisor -> string val source_hypervisor_of_string : string -> source_hypervisor diff --git a/v2v/v2v.ml b/v2v/v2v.ml index c828e48..9bf0afe 100644 --- a/v2v/v2v.ml +++ b/v2v/v2v.ml @@ -82,11 +82,16 @@ 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 _ -> + { + 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 +979,52 @@ 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. *) + + let source_block_types + List.map (fun sd -> sd.s_controller) source.s_disks in + let source_block_type + match List.sort_uniq compare source_block_types with + | [] -> error (f_"source has no hard disks!") + | [t] -> t + | _ -> error (f_"source has multiple hard disk types!") in + let block_type + match source_block_type with + | Some Source_virtio_blk -> Some Virtio_blk + | Some Source_IDE -> Some IDE + | Some t -> error (f_"source has unsupported hard disk type '%s'") + (string_of_controller t) + | None -> error (f_"source has unrecognized hard disk type") in + + let source_net_types + List.map (fun nic -> nic.s_nic_model) source.s_nics in + let source_net_type + match List.sort_uniq compare source_net_types with + | [] -> None + | [t] -> t + | _ -> error (f_"source has multiple network adapter model!") in + let net_type + match source_net_type with + | Some Source_virtio_net -> Some Virtio_net + | Some Source_e1000 -> Some E1000 + | Some Source_rtl8139 -> Some RTL8139 + | Some t -> error (f_"source has unsupported network adapter model '%s'") + (string_of_nic_model t) + | None -> None in + + let video + match source.s_video with + | Some Source_QXL -> Some QXL + | Some Source_Cirrus -> Some Cirrus + | Some t -> error (f_"source has unsupported video adapter model '%s'") + (string_of_source_video t) + | None -> None in + + { + rcaps_block_bus = block_type; + rcaps_net_bus = net_type; + rcaps_video = video; + } + let () = run_main_and_handle_errors main -- 2.5.0
Roman Kagan
2016-Mar-11 13:54 UTC
[Libguestfs] [PATCH v3 5/5] v2v: better explain --in-place
It seems that the documentation for --in-place mode of v2v wasn't clear enough, so try to explain it better. Signed-off-by: Roman Kagan <rkagan@virtuozzo.com> --- v2v/virt-v2v.pod | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod index 14da764..e7b9558 100644 --- a/v2v/virt-v2v.pod +++ b/v2v/virt-v2v.pod @@ -348,7 +348,8 @@ format in the metadata. Do not create an output virtual machine in the target hypervisor. Instead, adjust the guest OS in the source VM to run in the input -hypervisor. +hypervisor (which is also the target one in this case) on the virtual +hardware defined in the VM configuration. This mode is meant for integration with other toolsets, which take the responsibility of converting the VM configuration, providing for -- 2.5.0
Richard W.M. Jones
2016-Mar-18 09:08 UTC
Re: [Libguestfs] [PATCH v3 5/5] v2v: better explain --in-place
On Fri, Mar 11, 2016 at 04:54:49PM +0300, Roman Kagan wrote:> It seems that the documentation for --in-place mode of v2v wasn't clear > enough, so try to explain it better. > > Signed-off-by: Roman Kagan <rkagan@virtuozzo.com> > --- > v2v/virt-v2v.pod | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/v2v/virt-v2v.pod b/v2v/virt-v2v.pod > index 14da764..e7b9558 100644 > --- a/v2v/virt-v2v.pod > +++ b/v2v/virt-v2v.pod > @@ -348,7 +348,8 @@ format in the metadata. > > Do not create an output virtual machine in the target hypervisor. > Instead, adjust the guest OS in the source VM to run in the input > -hypervisor. > +hypervisor (which is also the target one in this case) on the virtual > +hardware defined in the VM configuration. > > This mode is meant for integration with other toolsets, which take the > responsibility of converting the VM configuration, providing forThis is not nearly enough documentation. We should probably have an "IN PLACE" subsection in the manual which explains exactly what is going on. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 100 libraries supported. http://fedoraproject.org/wiki/MinGW
Reasonably Related Threads
- [PATCH 0/4] v2v: more control over device types
- [PATCH v2 0/4] v2v: more control over device types
- [PATCH v4 0/5] v2v: more control over device types
- Re: [PATCH 3/4] v2v: take requested caps into account when converting
- Re: [PATCH v2 4/4] v2v: in-place: request caps based on source config