Conversion will set "gcaps_default_cpu" to true iff the guest OS is
capable of running on QEMU's default VCPU model.
This capability will only matter for the QEMU and libvirt output modules,
where, in case the capability is false *and* the source hypervisor does
not specify a VCPU model, we'll have to manually present the guest OS with
a VCPU that looks as close as possible to a physical CPU. (In that case,
we'll specify host-passthrough.)
The management applications targeted by the RHV and OpenStack output
modules have their own explicit VCPU defaults, overriding the QEMU default
model even in case the source hypervisor does not specify a VCPU model;
those modules will ignore this capability therefore.
Bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=2076013
Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
---
lib/types.mli | 14 ++++++++++++++
convert/convert_linux.ml | 1 +
convert/convert_windows.ml | 1 +
lib/types.ml | 3 +++
4 files changed, 19 insertions(+)
diff --git a/lib/types.mli b/lib/types.mli
index 37238cd75519..87544a0c59eb 100644
--- a/lib/types.mli
+++ b/lib/types.mli
@@ -251,52 +251,66 @@ val string_of_target_firmware : target_firmware -> string
(** {2 Target NICs} *)
type target_nics = source_nic list
(** {2 Guest capabilities} *)
type guestcaps = {
gcaps_block_bus : guestcaps_block_type;
gcaps_net_bus : guestcaps_net_type;
(** Best block device and network device guest can access. These are
determined during conversion by inspecting the guest (and in some cases
conversion can actually enhance these by installing drivers). Thus this
is not known until after conversion. *)
gcaps_virtio_rng : bool; (** Guest supports virtio-rng. *)
gcaps_virtio_balloon : bool; (** Guest supports virtio balloon. *)
gcaps_isa_pvpanic : bool; (** Guest supports ISA pvpanic device. *)
gcaps_virtio_socket : bool; (** Guest supports virtio socket. *)
gcaps_machine : guestcaps_machine; (** Machine model. *)
gcaps_arch : string; (** Architecture that KVM must emulate. *)
gcaps_acpi : bool; (** True if guest supports acpi. *)
gcaps_virtio_1_0 : bool;
(** The guest supports the virtio devices that it does at the virtio-1.0
protocol level. *)
+
+ gcaps_default_cpu : bool;
+ (** True iff the guest OS is capable of running on QEMU's default VCPU model.
+
+ This capability only matters for the QEMU and libvirt output modules,
+ where, in case the capability is false *and* the source hypervisor does
+ not specify a VCPU model, we must manually present the guest OS with a
+ VCPU that looks as close as possible to a physical CPU. (In that case, we
+ specify host-passthrough.)
+
+ The management applications targeted by the RHV and OpenStack output
+ modules have their own explicit VCPU defaults, overriding the QEMU default
+ model even in case the source hypervisor does not specify a VCPU model;
+ those modules ignore this capability therefore. Refer to RHBZ#2076013. *)
}
(** Guest capabilities after conversion. eg. Was virtio found or installed? *)
and guestcaps_block_type = Virtio_blk | IDE
and guestcaps_net_type = Virtio_net | E1000 | RTL8139
and guestcaps_machine = I440FX | Q35 | Virt
val string_of_guestcaps : guestcaps -> string
(** {2 Guest buses} *)
type target_buses = {
target_virtio_blk_bus : target_bus_slot array;
target_ide_bus : target_bus_slot array;
target_scsi_bus : target_bus_slot array;
target_floppy_bus : target_bus_slot array;
}
(** Mapping of fixed and removable disks to buses.
As shown in the diagram below, there are (currently) four buses
attached to the target VM. Each contains a chain of fixed or
removable disks. Slots can also be empty.
We try to assign disks to the same slot number as they would
occupy on the source, although that is not always possible.
diff --git a/convert/convert_linux.ml b/convert/convert_linux.ml
index c2bbce03637f..93b3922cac60 100644
--- a/convert/convert_linux.ml
+++ b/convert/convert_linux.ml
@@ -151,52 +151,53 @@ let convert (g : G.guestfs) source inspect keep_serial_console _ =
if major <= 4 then I440FX else Q35
| ("sles"|"suse-based"|"opensuse"), major
->
if major < 10 then I440FX else Q35
|
("debian"|"ubuntu"|"linuxmint"|"kalilinux"), major
->
if major < 4 then I440FX else Q35
(* reasonable default for all modern Linux kernels *)
| _, _ -> Q35
), true
)
| _ -> Virt, true
in
(* Return guest capabilities from the convert () function. *)
let guestcaps = {
gcaps_block_bus = block_type;
gcaps_net_bus = net_type;
gcaps_virtio_rng = kernel.ki_supports_virtio_rng;
gcaps_virtio_balloon = kernel.ki_supports_virtio_balloon;
gcaps_isa_pvpanic = kernel.ki_supports_isa_pvpanic;
gcaps_virtio_socket = kernel.ki_supports_virtio_socket;
gcaps_machine = machine;
gcaps_arch = Utils.kvm_arch inspect.i_arch;
gcaps_acpi = acpi;
gcaps_virtio_1_0 = virtio_1_0;
+ gcaps_default_cpu = true;
} in
guestcaps
and augeas_grub_configuration () =
if bootloader#set_augeas_configuration () then
Linux.augeas_reload g
and unconfigure_xen () =
(* Remove kmod-xenpv-* (RHEL 3). *)
let xenmods =
List.filter_map (
fun { G.app2_name = name } ->
if name = "kmod-xenpv" || String.is_prefix name
"kmod-xenpv-" then
Some name
else
None
) inspect.i_apps in
Linux.remove g inspect xenmods;
(* Undo related nastiness if kmod-xenpv was installed. *)
if xenmods <> [] then (
(* kmod-xenpv modules may have been manually copied to other kernels.
* Hunt them down and destroy them.
*)
let dirs = g#find "/lib/modules" in
diff --git a/convert/convert_windows.ml b/convert/convert_windows.ml
index b53312a9aba4..34a5044dd338 100644
--- a/convert/convert_windows.ml
+++ b/convert/convert_windows.ml
@@ -282,52 +282,53 @@ let convert (g : G.guestfs) _ inspect _ static_ips =
Libosinfo_utils.os_support_of_osinfo_device_list
(devices @ best_drv_devs) in
(if q35 then Q35 else I440FX), vio10
with
| Not_found ->
(* Pivot on the year 2007. Any Windows version from earlier than
* 2007 should use i440fx, anything 2007 or newer should use q35.
* Luckily this coincides almost exactly with the release of NT 6.
*)
(if inspect.i_major_version < 6 then I440FX else Q35), true
)
| _ -> Virt, true
in
(* Return guest capabilities from the convert () function. *)
let guestcaps = {
gcaps_block_bus = block_driver;
gcaps_net_bus = net_driver;
gcaps_virtio_rng = virtio_rng_supported;
gcaps_virtio_balloon = virtio_ballon_supported;
gcaps_isa_pvpanic = isa_pvpanic_supported;
gcaps_virtio_socket = virtio_socket_supported;
gcaps_machine = machine;
gcaps_arch = Utils.kvm_arch inspect.i_arch;
gcaps_acpi = true;
gcaps_virtio_1_0 = virtio_1_0;
+ gcaps_default_cpu = true;
} in
guestcaps
and configure_firstboot () =
(* Note that pnp_wait.exe must be the first firstboot script as it
* suppresses PnP for all following scripts.
*)
let tool_path = virt_tools_data_dir () // "pnp_wait.exe" in
if Sys.file_exists tool_path then
configure_wait_pnp tool_path
else
debug (f_"%s is missing. Firstboot scripts may conflict with PnP.")
tool_path;
(* Install VMDP unconditionally, if available, but don't
* warn about it if not.
*)
let tool_path = virt_tools_data_dir () // "vmdp.exe" in
if Sys.file_exists tool_path then
configure_vmdp tool_path;
(* Install QEMU Guest Agent unconditionally and warn if missing *)
let qemu_ga_files = Windows_virtio.copy_qemu_ga g inspect in
if qemu_ga_files <> [] then
configure_qemu_ga qemu_ga_files
diff --git a/lib/types.ml b/lib/types.ml
index 92ed0e52513d..7ffb868b1fbf 100644
--- a/lib/types.ml
+++ b/lib/types.ml
@@ -383,92 +383,95 @@ let string_of_target t =
target format: %s
"
(match t.target_file with
| TargetFile s -> "[file] " ^ s
| TargetURI s -> "[qemu] " ^ s)
t.target_format
type target_firmware = TargetBIOS | TargetUEFI
let string_of_target_firmware = function
| TargetBIOS -> "bios"
| TargetUEFI -> "uefi"
type target_nics = source_nic list
type guestcaps = {
gcaps_block_bus : guestcaps_block_type;
gcaps_net_bus : guestcaps_net_type;
gcaps_virtio_rng : bool;
gcaps_virtio_balloon : bool;
gcaps_isa_pvpanic : bool;
gcaps_virtio_socket : bool;
gcaps_machine : guestcaps_machine;
gcaps_arch : string;
gcaps_acpi : bool;
gcaps_virtio_1_0 : bool;
+ gcaps_default_cpu : bool;
}
and guestcaps_block_type = Virtio_blk | IDE
and guestcaps_net_type = Virtio_net | E1000 | RTL8139
and guestcaps_machine = I440FX | Q35 | Virt
let string_of_block_type = function
| Virtio_blk -> "virtio-blk"
| IDE -> "ide"
let string_of_net_type = function
| Virtio_net -> "virtio-net"
| E1000 -> "e1000"
| RTL8139 -> "rtl8139"
let string_of_machine = function
| I440FX -> "i440fx"
| Q35 -> "q35"
| Virt -> "virt"
let string_of_guestcaps gcaps =
sprintf "\
gcaps_block_bus = %s\n\
gcaps_net_bus = %s\n\
gcaps_virtio_rng = %b\n\
gcaps_virtio_balloon = %b\n\
gcaps_isa_pvpanic = %b\n\
gcaps_virtio_socket = %b\n\
gcaps_machine = %s\n\
gcaps_arch = %s\n\
gcaps_acpi = %b\n\
gcaps_virtio_1_0 = %b\n\
+ gcaps_default_cpu = %b\n\
"
(string_of_block_type gcaps.gcaps_block_bus)
(string_of_net_type gcaps.gcaps_net_bus)
gcaps.gcaps_virtio_rng
gcaps.gcaps_virtio_balloon
gcaps.gcaps_isa_pvpanic
gcaps.gcaps_virtio_socket
(string_of_machine gcaps.gcaps_machine)
gcaps.gcaps_arch
gcaps.gcaps_acpi
gcaps.gcaps_virtio_1_0
+ gcaps.gcaps_default_cpu
type target_buses = {
target_virtio_blk_bus : target_bus_slot array;
target_ide_bus : target_bus_slot array;
target_scsi_bus : target_bus_slot array;
target_floppy_bus : target_bus_slot array;
}
and target_bus_slot =
| BusSlotEmpty
| BusSlotDisk of source_disk
| BusSlotRemovable of source_removable
let string_of_target_bus_slots bus_name slots =
let slots =
Array.mapi (
fun slot_nr slot ->
sprintf "%s slot %d:\n" bus_name slot_nr ^
(match slot with
| BusSlotEmpty -> "\t(slot empty)\n"
| BusSlotDisk d -> string_of_source_disk d
| BusSlotRemovable r -> string_of_source_removable r ^ "\n"
)
) slots in
String.concat "" (Array.to_list slots)
--
2.19.1.3.g30247aa5d201