Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows PV auto-update feature support #2197

Merged
merged 9 commits into from
Apr 7, 2015
5 changes: 5 additions & 0 deletions ocaml/client_records/records.ml
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,8 @@ let vm_record rpc session_id vm =
~get:(fun () -> Int64.to_string (x ()).API.vM_version) ();
make_field ~name:"generation-id"
~get:(fun () -> (x ()).API.vM_generation_id) ();
make_field ~name:"hardware-platform-version"
~get:(fun () -> Int64.to_string (x ()).API.vM_hardware_platform_version) ();
]}

let host_crashdump_record rpc session_id host =
Expand Down Expand Up @@ -1049,6 +1051,9 @@ let host_record rpc session_id host =
~get_map:(fun () -> (x ()).API.host_guest_VCPUs_params)
~add_to_map:(fun k v -> Client.Host.add_to_guest_VCPUs_params rpc session_id host k v)
~remove_from_map:(fun k -> Client.Host.remove_from_guest_VCPUs_params rpc session_id host k) ();
make_field ~name:"virtual-hardware-platform-versions"
~get:(fun () -> String.concat "; " (List.map Int64.to_string (x ()).API.host_virtual_hardware_platform_versions))
~get_set:(fun () -> List.map Int64.to_string (x ()).API.host_virtual_hardware_platform_versions) ();
]}

let vdi_record rpc session_id vdi =
Expand Down
1 change: 1 addition & 0 deletions ocaml/idl/api_errors.ml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ let vm_requires_gpu = "VM_REQUIRES_GPU"
let vm_requires_vgpu = "VM_REQUIRES_VGPU"
let vm_requires_iommu = "VM_REQUIRES_IOMMU"
let vm_host_incompatible_version = "VM_HOST_INCOMPATIBLE_VERSION"
let vm_host_incompatible_virtual_hardware_platform_version = "VM_HOST_INCOMPATIBLE_VIRTUAL_HARDWARE_PLATFORM_VERSION"
let vm_has_pci_attached = "VM_HAS_PCI_ATTACHED"
let vm_has_vgpu = "VM_HAS_VGPU"
let host_cannot_attach_network = "HOST_CANNOT_ATTACH_NETWORK"
Expand Down
9 changes: 7 additions & 2 deletions ocaml/idl/datamodel.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ open Datamodel_types
(* IMPORTANT: Please bump schema vsn if you change/add/remove a _field_.
You do not have to bump vsn if you change/add/remove a message *)
let schema_major_vsn = 5
let schema_minor_vsn = 83
let schema_minor_vsn = 84

(* Historical schema versions just in case this is useful later *)
let rio_schema_major_vsn = 5
Expand Down Expand Up @@ -64,7 +64,7 @@ let creedence_release_schema_major_vsn = 5
let creedence_release_schema_minor_vsn = 72

let cream_release_schema_major_vsn = 5
let cream_release_schema_minor_vsn = 72
let cream_release_schema_minor_vsn = 73

let dundee_release_schema_major_vsn = 5
let dundee_release_schema_minor_vsn = 83
Expand Down Expand Up @@ -889,6 +889,8 @@ let _ =
~doc:"You attempted to run a VM on a host which doesn't have I/O virtualization (IOMMU/VT-d) enabled, which is needed by the VM." ();
error Api_errors.vm_host_incompatible_version ["host"; "vm"]
~doc:"This VM operation cannot be performed on an older-versioned host during an upgrade." ();
error Api_errors.vm_host_incompatible_virtual_hardware_platform_version ["host"; "host_versions"; "vm"; "vm_version"]
~doc:"You attempted to run a VM on a host that cannot provide the VM's required Virtual Hardware Platform version." ();
error Api_errors.vm_has_pci_attached ["vm"]
~doc:"This operation could not be performed, because the VM has one or more PCI devices passed through." ();
error Api_errors.vm_has_vgpu ["vm"]
Expand Down Expand Up @@ -1691,6 +1693,7 @@ let vm_assert_can_boot_here = call
Api_errors.host_not_enough_free_memory;
Api_errors.vm_requires_sr;
Api_errors.vm_host_incompatible_version;
Api_errors.vm_host_incompatible_virtual_hardware_platform_version;
]
~doc_tags:[Memory]
()
Expand Down Expand Up @@ -4468,6 +4471,7 @@ let host =
field ~qualifier:DynamicRO ~lifecycle:[Published, rel_boston, ""] ~ty:(Set (Ref _pgpu)) "PGPUs" "List of physical GPUs in the host";
field ~qualifier:RW ~in_product_since:rel_tampa ~default_value:(Some (VMap [])) ~ty:(Map (String, String)) "guest_VCPUs_params" "VCPUs params to apply to all resident guests";
field ~qualifier:RW ~in_product_since:rel_cream ~default_value:(Some (VEnum "enabled")) ~ty:host_display "display" "indicates whether the host is configured to output its console to a physical display device";
field ~qualifier:DynamicRO ~in_product_since:rel_cream ~default_value:(Some (VSet [VInt 0L])) ~ty:(Set (Int)) "virtual_hardware_platform_versions" "The set of versions of the virtual hardware platform that the host can offer to its guests";
])
()

Expand Down Expand Up @@ -7004,6 +7008,7 @@ let vm =
field ~writer_roles:_R_VM_ADMIN ~qualifier:RW ~in_product_since:rel_boston ~default_value:(Some (VRef (Ref.string_of Ref.null))) ~ty:(Ref _sr) "suspend_SR" "The SR on which a suspend image is stored";
field ~qualifier:StaticRO ~in_product_since:rel_boston ~default_value:(Some (VInt 0L)) ~ty:Int "version" "The number of times this VM has been recovered";
field ~qualifier:StaticRO ~in_product_since:rel_clearwater ~default_value:(Some (VString "0:0")) ~ty:(String) "generation_id" "Generation ID of the VM";
field ~writer_roles:_R_VM_ADMIN ~qualifier:RW ~in_product_since:rel_cream ~default_value:(Some (VInt 0L)) ~ty:Int "hardware_platform_version" "The host virtual hardware platform version the VM can run on";
])
()

Expand Down
6 changes: 3 additions & 3 deletions ocaml/test/test_common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ let make_vm ~__context ?(name_label="name_label") ?(name_description="descriptio
?(other_config=[]) ?(xenstore_data=[]) ?(recommendations="") ?(ha_always_run=false)
?(ha_restart_priority="") ?(tags=[]) ?(blocked_operations=[]) ?(protection_policy=Ref.null)
?(is_snapshot_from_vmpp=false) ?(appliance=Ref.null) ?(start_delay=0L)
?(shutdown_delay=0L) ?(order=0L) ?(suspend_SR=Ref.null) ?(version=0L) ?(generation_id="0:0") () =
?(shutdown_delay=0L) ?(order=0L) ?(suspend_SR=Ref.null) ?(version=0L) ?(generation_id="0:0") ?(hardware_platform_version=0L) () =
Xapi_vm.create ~__context ~name_label ~name_description ~user_version ~is_a_template
~affinity ~memory_target ~memory_static_max ~memory_dynamic_max ~memory_dynamic_min
~memory_static_min ~vCPUs_params ~vCPUs_max ~vCPUs_at_startup ~actions_after_shutdown
Expand All @@ -93,12 +93,12 @@ let make_vm ~__context ?(name_label="name_label") ?(name_description="descriptio
~hVM_shadow_multiplier ~platform ~pCI_bus ~other_config ~xenstore_data ~recommendations
~ha_always_run ~ha_restart_priority ~tags ~blocked_operations ~protection_policy
~is_snapshot_from_vmpp ~appliance ~start_delay ~shutdown_delay ~order ~suspend_SR
~version ~generation_id
~version ~generation_id ~hardware_platform_version

let make_host ~__context ?(uuid=make_uuid ()) ?(name_label="host")
?(name_description="description") ?(hostname="localhost") ?(address="127.0.0.1")
?(external_auth_type="") ?(external_auth_service_name="") ?(external_auth_configuration=[])
?(license_params=[]) ?(edition="free") ?(license_server=[]) ?(local_cache_sr=Ref.null) ?(chipset_info=[]) () =
?(license_params=[]) ?(edition="free") ?(license_server=[]) ?(local_cache_sr=Ref.null) ?(chipset_info=[]) () =

Xapi_host.create ~__context ~uuid ~name_label ~name_description ~hostname ~address ~external_auth_type ~external_auth_service_name ~external_auth_configuration ~license_params ~edition ~license_server ~local_cache_sr ~chipset_info

Expand Down
3 changes: 2 additions & 1 deletion ocaml/xapi/cli_operations.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,8 @@ let vm_create printer rpc session_id params =
~order:0L
~suspend_SR:Ref.null
~version:0L
~generation_id:"" in
~generation_id:""
~hardware_platform_version:0L in
let uuid=Client.VM.get_uuid rpc session_id vm in
printer (Cli_printer.PList [uuid])

Expand Down
3 changes: 2 additions & 1 deletion ocaml/xapi/create_misc.ml
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ and create_domain_zero_record ~__context ~domain_zero_ref (host_info: host_info)
~order:0L
~suspend_SR:Ref.null
~version:0L
~generation_id:"";
~generation_id:""
~hardware_platform_version:0L;
Xapi_vm_helpers.update_memory_overhead ~__context ~vm:domain_zero_ref

and create_domain_zero_console_record_with_protocol ~__context ~domain_zero_ref ~dom0_console_protocol =
Expand Down
1 change: 1 addition & 0 deletions ocaml/xapi/dbsync_slave.ml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ let refresh_localhost_info ~__context info =
Db.Host.set_software_version ~__context ~self:host ~value:software_version;
Db.Host.set_API_version_major ~__context ~self:host ~value:Xapi_globs.api_version_major;
Db.Host.set_API_version_minor ~__context ~self:host ~value:Xapi_globs.api_version_minor;
Db.Host.set_virtual_hardware_platform_versions ~__context ~self:host ~value:Xapi_globs.host_virtual_hardware_platform_versions;
Db.Host.set_hostname ~__context ~self:host ~value:info.hostname;
let caps = try
String.split ' ' (Xenctrl.with_intf (fun xc -> Xenctrl.version_capabilities xc))
Expand Down
8 changes: 8 additions & 0 deletions ocaml/xapi/helpers.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,14 @@ let force_loopback_vbd ~__context =
let other_config = Db.Pool.get_other_config ~__context ~self:pool in
List.mem_assoc "force_loopback_vbd" other_config

let is_true ~key ~pairlist ~default =
try
match List.assoc key pairlist with
| "true" | "1" -> true
| "false" | "0" -> false
| _ -> default
with Not_found ->
default

(* We no longer care about the hash, but it's part of the API and we
can't get rid of it. Put this here so clients don't need to know
Expand Down
1 change: 1 addition & 0 deletions ocaml/xapi/import_xva.ml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ let make __context rpc session_id srid (vms, vdis) =
~suspend_SR:Ref.null
~version:0L
~generation_id:""
~hardware_platform_version:0L
in

TaskHelper.operate_on_db_task ~__context
Expand Down
31 changes: 31 additions & 0 deletions ocaml/xapi/xapi_globs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,11 @@ let default_viridian_key_value = "true"

let device_id_key_name = "device_id"

(* Key name for PCI device for Window Update control, goes in platform flags *)
let pci_pv_key_name = "pci_pv"
(* Disable if not explicitly set, including the scenario of importing, storage-motion, and host/pool upgrade *)
let default_pci_pv_key_value = false

(* machine-address-size key-name/value; goes in other-config of RHEL5.2 template *)
let machine_address_size_key_name = "machine-address-size"
let machine_address_size_key_value = "36"
Expand Down Expand Up @@ -912,6 +917,32 @@ let other_options = [

let all_options = options_of_xapi_globs_spec @ other_options

(* VIRTUAL HARDWARE PLATFORM VERSIONS *)

let pci_for_PV_support = 2L

(* This set is used as an indicator to show the virtual hardware
platform versions the current host offers to its guests *)
let host_virtual_hardware_platform_versions = [
(* Zero is the implicit version offered by hosts older than this
versioning concept, and the version implicitly required by old
guests that do not specify a version. *)
0L;

(* Version one is the version in which this versioning concept was
introduced. This Virtual Hardware Platform might not differ
significantly from the immediately preceding version zero, but
it seems prudent to introduce a way to differentiate it from
the whole history of older host versions. *)
1L;

(* Version two which is "pci_for_PV_support" will be the first virtual
hardware platform versionto offer the option of an emulated PCI
device used to trigger a guest to install or upgrade its PV tools
(originally introduced to exploit the Windows Update system). *)
pci_for_PV_support;
]

module Resources = struct

let essential_executables = [
Expand Down
4 changes: 3 additions & 1 deletion ocaml/xapi/xapi_host.ml
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ let create ~__context ~uuid ~name_label ~name_description ~hostname ~address ~ex
let metrics = Ref.make () in
make_new_metrics_object metrics;

let host_is_us = (uuid=(Helpers.get_localhost_uuid ())) in
Db.Host.create ~__context ~ref:host
~current_operations:[] ~allowed_operations:[]
~software_version:(Xapi_globs.software_version ())
Expand Down Expand Up @@ -607,10 +608,11 @@ let create ~__context ~uuid ~name_label ~name_description ~hostname ~address ~ex
~local_cache_sr
~guest_VCPUs_params:[]
~display:`enabled
~virtual_hardware_platform_versions:(if host_is_us then Xapi_globs.host_virtual_hardware_platform_versions else [0L])
;
(* If the host we're creating is us, make sure its set to live *)
Db.Host_metrics.set_last_updated ~__context ~self:metrics ~value:(Date.of_float (Unix.gettimeofday ()));
Db.Host_metrics.set_live ~__context ~self:metrics ~value:(uuid=(Helpers.get_localhost_uuid ()));
Db.Host_metrics.set_live ~__context ~self:metrics ~value:host_is_us;
host

let precheck_destroy_declare_dead ~__context ~self call =
Expand Down
2 changes: 1 addition & 1 deletion ocaml/xapi/xapi_pool.ml
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ let rec create_or_get_host_on_master __context rpc session_id (host_ref, host) :
* we need an alternative way of preserving the value of the local_cache_sr field, so it's
* been added to the constructor. *)
~local_cache_sr
~chipset_info:host.API.host_chipset_info
~chipset_info:host.API.host_chipset_info
in

(* Copy other-config into newly created host record: *)
Expand Down
9 changes: 8 additions & 1 deletion ocaml/xapi/xapi_vm.ml
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ let set_xenstore_data ~__context ~self ~value =
let start ~__context ~vm ~start_paused ~force =
let vmr = Db.VM.get_record ~__context ~self:vm in
Vgpuops.create_vgpus ~__context (vm, vmr) (Helpers.will_boot_hvm ~__context ~self:vm);

if vmr.API.vM_ha_restart_priority = Constants.ha_restart
then Db.VM.set_ha_always_run ~__context ~self:vm ~value:true;

Expand All @@ -206,6 +205,10 @@ let start ~__context ~vm ~start_paused ~force =
Db.VM.set_guest_metrics ~__context ~self:vm ~value:Ref.null;
(try Db.VM_guest_metrics.destroy ~__context ~self:vm_gm with _ -> ());

(* This makes sense here while the available versions are 0 and 1.
* If/when we introduce version 2, we must reassess this. *)
update_vm_virtual_hardware_platform_version ~__context ~vm;

(* If the VM has any vGPUs, gpumon must remain stopped until the
* VM has started. *)
match vmr.API.vM_VGPUs with
Expand All @@ -231,6 +234,7 @@ let start_on ~__context ~vm ~host ~start_paused ~force =
start ~__context ~vm ~start_paused ~force

let hard_reboot ~__context ~vm =
update_vm_virtual_hardware_platform_version ~__context ~vm;
Xapi_xenops.reboot ~__context ~self:vm None

let hard_shutdown ~__context ~vm =
Expand All @@ -250,6 +254,7 @@ let hard_shutdown ~__context ~vm =
Xapi_xenops.shutdown ~__context ~self:vm None

let clean_reboot ~__context ~vm =
update_vm_virtual_hardware_platform_version ~__context ~vm;
Xapi_xenops.reboot ~__context ~self:vm (Some !Xapi_globs.domain_shutdown_total_timeout)

let clean_shutdown_with_timeout ~__context ~vm timeout =
Expand Down Expand Up @@ -394,6 +399,7 @@ let create ~__context
~suspend_SR
~version
~generation_id
~hardware_platform_version
: API.ref_VM =
let gen_mac_seed () = Uuid.to_string (Uuid.make_uuid ()) in
(* Add random mac_seed if there isn't one specified already *)
Expand Down Expand Up @@ -446,6 +452,7 @@ let create ~__context
~suspend_SR
~version
~generation_id
~hardware_platform_version

let destroy ~__context ~self =
let parent = Db.VM.get_parent ~__context ~self in
Expand Down
3 changes: 2 additions & 1 deletion ocaml/xapi/xapi_vm.mli
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ val create :
order:int64 ->
suspend_SR:[ `SR ] Ref.t ->
version:int64 ->
generation_id:string
generation_id:string ->
hardware_platform_version:int64
-> API.ref_VM
val destroy : __context:Context.t -> self:[ `VM ] Ref.t -> unit
val clone :
Expand Down
1 change: 1 addition & 0 deletions ocaml/xapi/xapi_vm_clone.ml
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ let copy_vm_record ?(snapshot_info_record) ~__context ~vm ~disk_op ~new_name ~ne
~suspend_SR:Ref.null
~version:0L
~generation_id
~hardware_platform_version:0L
;

(* update the VM's parent field in case of snapshot. Note this must be done after "ref"
Expand Down
48 changes: 47 additions & 1 deletion ocaml/xapi/xapi_vm_helpers.ml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ open Xstringext
open Printf
open Xapi_vm_memory_constraints
open Listext
open Xenstore
open Fun
module XenAPI = Client.Client

module D=Debug.Make(struct let name="xapi" end)
open D
Expand Down Expand Up @@ -96,6 +96,7 @@ let create ~__context ~name_label ~name_description
~suspend_SR
~version
~generation_id
~hardware_platform_version
: API.ref_VM =

(* NB parameter validation is delayed until VM.start *)
Expand Down Expand Up @@ -162,6 +163,7 @@ let create ~__context ~name_label ~name_description
~suspend_SR
~version
~generation_id
~hardware_platform_version
;
Db.VM.set_power_state ~__context ~self:vm_ref ~value:`Halted;
Xapi_vm_lifecycle.update_allowed_operations ~__context ~self:vm_ref;
Expand Down Expand Up @@ -264,6 +266,31 @@ let validate_basic_parameters ~__context ~self ~snapshot:x =
~hVM_shadow_multiplier:x.API.vM_HVM_shadow_multiplier;
validate_actions_after_crash ~__context ~self ~value:x.API.vM_actions_after_crash

let assert_hardware_platform_support ~__context ~vm ~host =
let vm_hardware_platform_version = Db.VM.get_hardware_platform_version ~__context ~self:vm in
let host_virtual_hardware_platform_versions =
try
match host with
| Helpers.LocalObject host_ref ->
Db.Host.get_virtual_hardware_platform_versions ~__context ~self:host_ref
| Helpers.RemoteObject (rpc, session_id, host_ref) ->
XenAPI.Host.get_virtual_hardware_platform_versions ~rpc ~session_id ~self:host_ref
with Not_found ->
(* An old host that does not understand the concept
* has implicit support for version 0 *)
[0L]
in
if not (List.mem vm_hardware_platform_version host_virtual_hardware_platform_versions) then
let host_r = match host with
| Helpers.LocalObject host_ref -> host_ref
| Helpers.RemoteObject (rpc, session_id, host_ref) -> host_ref
in
raise (Api_errors.Server_error (
Api_errors.vm_host_incompatible_virtual_hardware_platform_version, [
Ref.string_of host_r;
"["^(String.concat "; " (List.map Int64.to_string host_virtual_hardware_platform_versions))^"]";
Ref.string_of vm;
Int64.to_string vm_hardware_platform_version]))

let assert_host_is_enabled ~__context ~host =
(* Check the host is enabled first *)
Expand Down Expand Up @@ -467,6 +494,7 @@ let assert_enough_memory_available ~__context ~self ~host ~snapshot =

(** Checks to see if a VM can boot on a particular host, throws an error if not.
* Criteria:
- The host must support the VM's required Virtual Hardware Platform version.
- The vCPU, memory, shadow multiplier, and actions-after-crash values must be valid.
- For each VBD, corresponding VDI's SR must be attached on the target host.
- For each VIF, either the Network has a PIF connecting to the target host,
Expand All @@ -491,6 +519,8 @@ let assert_can_boot_here ~__context ~self ~host ~snapshot ?(do_sr_check=true) ?(
validate_basic_parameters ~__context ~self ~snapshot;
assert_host_is_live ~__context ~host;
assert_host_is_enabled ~__context ~host;
(* Check the host can support the VM's required version of virtual hardware platform *)
assert_hardware_platform_support ~__context ~vm:self ~host:(Helpers.LocalObject host);
if do_sr_check then
assert_can_see_SRs ~__context ~self ~host;
assert_can_see_networks ~__context ~self ~host;
Expand Down Expand Up @@ -1025,3 +1055,19 @@ let vm_fresh_genid ~__context ~self =
debug "Refreshing GenID for VM %s to %s" uuid new_genid;
Db.VM.set_generation_id ~__context ~self ~value:new_genid ;
new_genid

let is_pci_pv_enabled ~platformdata =
Helpers.is_true ~key:(Xapi_globs.pci_pv_key_name) ~pairlist:platformdata ~default:(Xapi_globs.default_pci_pv_key_value)

let update_vm_virtual_hardware_platform_version ~__context ~vm =
let vm_record = Db.VM.get_record ~__context ~self:vm in
(* Deduce what we can, but the guest VM might need a higher version. *)
let visibly_required_version =
if is_pci_pv_enabled vm_record.API.vM_platform then
Xapi_globs.pci_for_PV_support
else
0L
in
let current_version = vm_record.API.vM_hardware_platform_version in
if visibly_required_version > current_version then
Db.VM.set_hardware_platform_version ~__context ~self:vm ~value:visibly_required_version
Loading