Roman Kagan
2016-Apr-14 09:01 UTC
[Libguestfs] [PATCH v3] v2v: add support for virtio-scsi
Virtio-SCSI offers a number of advantages over virtio-blk, in
particular, it supports SCSI UNMAP (aka trim) which is crucial for
keeping the virtual drive from wasting host disk space.
This patch adds support for virtio-scsi as the virtual disk connection
type both on input and on output of v2v.
Virtio-blk remains the default, so for now virtio-scsi-based guests can
only be produced in --in-place mode.
Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
---
v3:
- resend off a proper branch
v2:
- corrected OVF and glance output
- stopped abusing debug stringifier to obtain linux module name
- droped unneeded braces
v2v/OVF.ml | 4 +++-
v2v/convert_linux.ml | 20 ++++++++++++++------
v2v/input_libvirtxml.ml | 32 ++++++++++++++++++++------------
v2v/output_glance.ml | 5 +++++
v2v/test-v2v-print-source.sh | 2 +-
v2v/types.ml | 9 ++++++---
v2v/types.mli | 11 ++++-------
v2v/v2v.ml | 13 ++++++++-----
v2v/windows_virtio.ml | 30 ++++++++++++++++++++++++------
9 files changed, 85 insertions(+), 41 deletions(-)
diff --git a/v2v/OVF.ml b/v2v/OVF.ml
index f8afc8c..87ce561 100644
--- a/v2v/OVF.ml
+++ b/v2v/OVF.ml
@@ -454,7 +454,9 @@ and add_disks targets guestcaps output_alloc sd_uuid
image_uuids vol_uuids ovf "ovf:format",
"http://en.wikipedia.org/wiki/Byte"; (* wtf? *)
"ovf:disk-interface",
(match guestcaps.gcaps_block_bus with
- | Virtio_blk -> "VirtIO" | IDE -> "IDE");
+ | Virtio_blk -> "VirtIO"
+ | Virtio_SCSI -> "VirtIO_SCSI"
+ | IDE -> "IDE");
"ovf:disk-type", "System"; (* RHBZ#744538 *)
"ovf:boot", if is_boot_drive then "True" else
"False";
] in
diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml
index 0a2e439..04b7739 100644
--- a/v2v/convert_linux.ml
+++ b/v2v/convert_linux.ml
@@ -803,8 +803,9 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect
source rcaps * major number of vdX block devices. If we change it,
RHEL 3
* KVM guests won't boot.
*)
- [ "virtio"; "virtio_ring";
"virtio_blk"; "virtio_net";
- "virtio_pci" ]
+ List.filter (fun m -> List.mem m kernel.ki_modules)
+ [ "virtio"; "virtio_ring";
"virtio_blk";
+ "virtio_scsi"; "virtio_net";
"virtio_pci" ]
else
[ "sym53c8xx" (* XXX why not "ide"? *) ] in
@@ -1134,7 +1135,13 @@ let rec convert ~keep_serial_console (g : G.guestfs)
inspect source rcaps (* Update 'alias scsi_hostadapter ...' *)
let paths = augeas_modprobe ". =~
regexp('scsi_hostadapter.*')" in
match block_type with
- | Virtio_blk ->
+ | Virtio_blk | Virtio_SCSI ->
+ let block_module + match block_type with
+ | Virtio_blk -> "virtio_blk"
+ | Virtio_SCSI -> "virtio_scsi"
+ | _ -> raise Not_found in
+
if paths <> [] then (
(* There's only 1 scsi controller in the converted guest.
* Convert only the first scsi_hostadapter entry to virtio
@@ -1148,14 +1155,14 @@ let rec convert ~keep_serial_console (g : G.guestfs)
inspect source rcaps List.iter (fun path -> ignore (g#aug_rm path))
(List.rev paths_to_delete);
- g#aug_set (path ^ "/modulename") "virtio_blk"
+ g#aug_set (path ^ "/modulename") block_module
) else (
(* We have to add a scsi_hostadapter. *)
let modpath = discover_modpath () in
g#aug_set (sprintf "/files%s/alias[last()+1]" modpath)
"scsi_hostadapter";
g#aug_set (sprintf "/files%s/alias[last()]/modulename"
modpath)
- "virtio_blk"
+ block_module
)
| IDE ->
(* There is no scsi controller in an IDE guest. *)
@@ -1247,6 +1254,7 @@ let rec convert ~keep_serial_console (g : G.guestfs)
inspect source rcaps let block_prefix_after_conversion match
block_type with
| Virtio_blk -> "vd"
+ | Virtio_SCSI -> "sd"
| IDE -> ide_block_prefix in
let map @@ -1255,7 +1263,7 @@ let rec convert ~keep_serial_console (g :
G.guestfs) inspect source rcaps let block_prefix_before_conversion
match disk.s_controller with
| Some Source_IDE -> ide_block_prefix
- | Some Source_SCSI -> "sd"
+ | Some Source_virtio_SCSI | Some Source_SCSI -> "sd"
| Some Source_virtio_blk -> "vd"
| None ->
(* This is basically a guess. It assumes the source used IDE. *)
diff --git a/v2v/input_libvirtxml.ml b/v2v/input_libvirtxml.ml
index 9d8963d..231931f 100644
--- a/v2v/input_libvirtxml.ml
+++ b/v2v/input_libvirtxml.ml
@@ -181,6 +181,12 @@ let parse_libvirt_xml ?conn xml None
) in
+ (* Presence of virtio-scsi controller. *)
+ let has_virtio_scsi + let obj = Xml.xpath_eval_expression xpathctx
+
"/domain/devices/controller[@model='virtio-scsi']" in
+ Xml.xpathobj_nr_nodes obj > 0 in
+
(* Non-removable disk devices. *)
let disks let get_disks, add_disk @@ -208,12 +214,13 @@ let
parse_libvirt_xml ?conn xml
let controller let target_bus = xpath_string
"target/@bus" in
- match target_bus with
- | None -> None
- | Some "ide" -> Some Source_IDE
- | Some "scsi" -> Some Source_SCSI
- | Some "virtio" -> Some Source_virtio_blk
- | Some _ -> None in
+ match target_bus, has_virtio_scsi with
+ | None, _ -> None
+ | Some "ide", _ -> Some Source_IDE
+ | Some "scsi", true -> Some Source_virtio_SCSI
+ | Some "scsi", false -> Some Source_SCSI
+ | Some "virtio", _ -> Some Source_virtio_blk
+ | Some _, _ -> None in
let format match xpath_string "driver/@type" with
@@ -297,12 +304,13 @@ let parse_libvirt_xml ?conn xml
let controller let target_bus = xpath_string
"target/@bus" in
- match target_bus with
- | None -> None
- | Some "ide" -> Some Source_IDE
- | Some "scsi" -> Some Source_SCSI
- | Some "virtio" -> Some Source_virtio_blk
- | Some _ -> None in
+ match target_bus, has_virtio_scsi with
+ | None, _ -> None
+ | Some "ide", _ -> Some Source_IDE
+ | Some "scsi", true -> Some Source_virtio_SCSI
+ | Some "scsi", false -> Some Source_SCSI
+ | Some "virtio", _ -> Some Source_virtio_blk
+ | Some _, _ -> None in
let slot let target_dev = xpath_string "target/@dev"
in
diff --git a/v2v/output_glance.ml b/v2v/output_glance.ml
index 9487f0b..106c99a 100644
--- a/v2v/output_glance.ml
+++ b/v2v/output_glance.ml
@@ -86,6 +86,7 @@ object
"hw_disk_bus",
(match guestcaps.gcaps_block_bus with
| Virtio_blk -> "virtio"
+ | Virtio_SCSI -> "scsi"
| IDE -> "ide");
"hw_vif_model",
(match guestcaps.gcaps_net_bus with
@@ -105,6 +106,10 @@ object
)
] in
let properties + match guestcaps.gcaps_block_bus with
+ | Virtio_SCSI -> ("hw_scsi_model",
"virtio-scsi") :: properties
+ | _ -> properties in
+ let properties match inspect.i_major_version,
inspect.i_minor_version with
| 0, 0 -> properties
| x, 0 -> ("os_version", string_of_int x) :: properties
diff --git a/v2v/test-v2v-print-source.sh b/v2v/test-v2v-print-source.sh
index 8af6104..789555d 100755
--- a/v2v/test-v2v-print-source.sh
+++ b/v2v/test-v2v-print-source.sh
@@ -63,7 +63,7 @@ hypervisor type: test
video: qxl
sound:
disks:
- /windows.img (raw) [virtio]
+ /windows.img (raw) [virtio-blk]
removable media:
NICs:
Network \"default\" mac: 00:11:22:33:44:55 [virtio]" ]; then
diff --git a/v2v/types.ml b/v2v/types.ml
index 821b7ec..9a23b4a 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -55,7 +55,8 @@ and source_disk = {
s_format : string option;
s_controller : s_controller option;
}
-and s_controller = Source_IDE | Source_SCSI | Source_virtio_blk
+and s_controller = Source_IDE | Source_SCSI |
+ Source_virtio_blk | Source_virtio_SCSI
and source_removable = {
s_removable_type : s_removable_type;
s_removable_controller : s_controller option;
@@ -187,7 +188,8 @@ and string_of_source_disk { s_qemu_uri = qemu_uri; s_format
= format;
and string_of_controller = function
| Source_IDE -> "ide"
| Source_SCSI -> "scsi"
- | Source_virtio_blk -> "virtio"
+ | Source_virtio_blk -> "virtio-blk"
+ | Source_virtio_SCSI -> "virtio-scsi"
and string_of_source_removable { s_removable_type = typ;
s_removable_controller = controller;
@@ -366,13 +368,14 @@ and requested_guestcaps = {
rcaps_net_bus : guestcaps_net_type option;
rcaps_video : guestcaps_video_type option;
}
-and guestcaps_block_type = Virtio_blk | IDE
+and guestcaps_block_type = Virtio_blk | Virtio_SCSI | 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"
+ | Virtio_SCSI -> "virtio-scsi"
| IDE -> "ide")
let string_of_net_type net_type (match net_type with
diff --git a/v2v/types.mli b/v2v/types.mli
index 4595a1f..dde0d29 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -65,12 +65,9 @@ and source_disk = {
}
(** A source disk. *)
-and s_controller = Source_IDE | Source_SCSI | Source_virtio_blk
-(** Source disk controller.
-
- For the purposes of this field, we can treat virtio-scsi as
- [SCSI]. However we don't support conversions from virtio in any
- case so virtio is here only to make it work for testing. *)
+and s_controller = Source_IDE | Source_SCSI |
+ Source_virtio_blk | Source_virtio_SCSI
+(** Source disk controller. *)
and source_removable = {
s_removable_type : s_removable_type; (** Type. *)
@@ -218,7 +215,7 @@ and requested_guestcaps = {
}
(** Guest capabilities after conversion. eg. Was virtio found or installed? *)
-and guestcaps_block_type = Virtio_blk | IDE
+and guestcaps_block_type = Virtio_blk | Virtio_SCSI | IDE
and guestcaps_net_type = Virtio_net | E1000 | RTL8139
and guestcaps_video_type = QXL | Cirrus
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index 4d0d525..647ae11 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -731,10 +731,11 @@ and do_convert g inspect source keep_serial_console rcaps
(* Did we manage to install virtio drivers? *)
if not (quiet ()) then (
- if guestcaps.gcaps_block_bus = Virtio_blk then
- info (f_"This guest has virtio drivers installed.")
- else
- info (f_"This guest does not have virtio drivers installed.");
+ match guestcaps.gcaps_block_bus with
+ | Virtio_blk | Virtio_SCSI ->
+ info (f_"This guest has virtio drivers installed.")
+ | _ ->
+ info (f_"This guest does not have virtio drivers installed.")
);
guestcaps
@@ -939,6 +940,7 @@ and target_bus_assignment source targets guestcaps
let t = BusSlotTarget t in
match guestcaps.gcaps_block_bus with
| Virtio_blk -> insert virtio_blk_bus i t
+ | Virtio_SCSI -> insert scsi_bus i t
| IDE -> insert ide_bus i t
) targets;
@@ -952,7 +954,7 @@ and target_bus_assignment source targets guestcaps
| None -> ide_bus (* Wild guess, but should be safe. *)
| Some Source_virtio_blk -> virtio_blk_bus
| Some Source_IDE -> ide_bus
- | Some Source_SCSI -> scsi_bus in
+ | Some Source_virtio_SCSI | Some Source_SCSI -> scsi_bus in
match r.s_removable_slot with
| None -> ignore (insert_after bus 0 (BusSlotRemovable r))
| Some desired_slot_nr ->
@@ -992,6 +994,7 @@ and rcaps_from_source source let block_type match
source_block_type with
| Some Source_virtio_blk -> Some Virtio_blk
+ | Some Source_virtio_SCSI -> Some Virtio_SCSI
| Some Source_IDE -> Some IDE
| Some t -> error (f_"source has unsupported hard disk type
'%s'")
(string_of_controller t)
diff --git a/v2v/windows_virtio.ml b/v2v/windows_virtio.ml
index 7ca4068..6b78420 100644
--- a/v2v/windows_virtio.ml
+++ b/v2v/windows_virtio.ml
@@ -35,6 +35,7 @@ let virtio_win
let scsi_class_guid = "{4D36E97B-E325-11CE-BFC1-08002BE10318}"
let viostor_pciid =
"VEN_1AF4&DEV_1001&SUBSYS_00021AF4&REV_00"
+let vioscsi_pciid =
"VEN_1AF4&DEV_1004&SUBSYS_00081AF4&REV_00"
let rec install_drivers g inspect systemroot root current_cs rcaps (* Copy
the virtio drivers to the guest. *)
@@ -43,7 +44,7 @@ let rec install_drivers g inspect systemroot root current_cs
rcaps
if not (copy_drivers g inspect driverdir) then (
match rcaps with
- | { rcaps_block_bus = Some Virtio_blk }
+ | { rcaps_block_bus = Some Virtio_blk | Some Virtio_SCSI }
| { 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")
@@ -66,19 +67,25 @@ let rec install_drivers g inspect systemroot root current_cs
rcaps (* Can we install the block driver? *)
let block : guestcaps_block_type let has_viostor = g#exists
(driverdir // "viostor.inf") in
- match rcaps.rcaps_block_bus, has_viostor with
- | Some Virtio_blk, false ->
+ let has_vioscsi = g#exists (driverdir // "vioscsi.inf") in
+ match rcaps.rcaps_block_bus, has_viostor, has_vioscsi 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 ->
+ | Some Virtio_SCSI, _, false ->
+ error (f_"there is no vioscsi (virtio SCSI passthrough) 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 ->
+ | (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
@@ -89,7 +96,18 @@ let rec install_drivers g inspect systemroot root current_cs
rcaps viostor_pciid;
Virtio_blk
- | Some IDE, _ ->
+ | Some Virtio_SCSI, _, true ->
+ (* Block driver needs tweaks to allow booting; the rest is set up by
PnP
+ * manager *)
+ let source = driverdir // "vioscsi.sys" in
+ let target = sprintf "%s/system32/drivers/vioscsi.sys"
systemroot in
+ let target = g#case_sensitive_path target in
+ g#cp source target;
+ add_guestor_to_registry g root current_cs "vioscsi"
+ vioscsi_pciid;
+ Virtio_SCSI
+
+ | Some IDE, _, _ ->
IDE in
(* Can we install the virtio-net driver? *)
--
2.5.5
Richard W.M. Jones
2016-Apr-14 09:26 UTC
Re: [Libguestfs] [PATCH v3] v2v: add support for virtio-scsi
On Thu, Apr 14, 2016 at 12:01:30PM +0300, Roman Kagan wrote:> @@ -1134,7 +1135,13 @@ let rec convert ~keep_serial_console (g : G.guestfs) inspect source rcaps > (* Update 'alias scsi_hostadapter ...' *) > let paths = augeas_modprobe ". =~ regexp('scsi_hostadapter.*')" in > match block_type with > - | Virtio_blk -> > + | Virtio_blk | Virtio_SCSI -> > + let block_module > + match block_type with > + | Virtio_blk -> "virtio_blk" > + | Virtio_SCSI -> "virtio_scsi" > + | _ -> raise Not_found inIt's a bad idea to raise Not_found unless you're going to catch it immediately. As this is an impossible condition you should use `assert false' here.> @@ -105,6 +106,10 @@ object > ) > ] in > let properties > + match guestcaps.gcaps_block_bus with > + | Virtio_SCSI -> ("hw_scsi_model", "virtio-scsi") :: properties > + | _ -> properties inSince there are only two other cases, it's better to match them explicitly, ie: | Virtio_blk | IDE -> properties in The reason for this is if we add another block type in future the compiler will error out because of the missing case, forcing us to analyze whether we need to add some other property for it.> diff --git a/v2v/v2v.ml b/v2v/v2v.ml > index 4d0d525..647ae11 100644 > --- a/v2v/v2v.ml > +++ b/v2v/v2v.ml > @@ -731,10 +731,11 @@ and do_convert g inspect source keep_serial_console rcaps > > (* Did we manage to install virtio drivers? *) > if not (quiet ()) then ( > - if guestcaps.gcaps_block_bus = Virtio_blk then > - info (f_"This guest has virtio drivers installed.") > - else > - info (f_"This guest does not have virtio drivers installed."); > + match guestcaps.gcaps_block_bus with > + | Virtio_blk | Virtio_SCSI -> > + info (f_"This guest has virtio drivers installed.") > + | _ -> > + info (f_"This guest does not have virtio drivers installed.")As above, use `| IDE ->' instead of this wildcard match, so that in future we are forced to analyze this code if we add another block type.> + | Some Virtio_SCSI, _, false -> > + error (f_"there is no vioscsi (virtio SCSI passthrough) 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.")'passthrough'? I know that the virtio SCSI driver passes SCSI commands through, but I think this might be confused with PCI / host adapter passthrough which is a completely different thing. Probably better to drop this word. ----- ACK if you make all of the changes above. 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/
Apparently Analagous Threads
- [PATCH v2] v2v: add support for virtio-scsi
- [PATCH v4] v2v: add support for virtio-scsi
- [PATCH] v2v: add support for virtio-scsi
- Re: [PATCH v2 4/4] v2v: in-place: request caps based on source config
- [PATCH 4/4] v2v: in-place: request caps based on source config