Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #2222 from robhoes/winup

Windows Update
  • Loading branch information...
commit de07410f28b8f6195feb465eb8470b5a47aaca08 2 parents 0f3cd03 + 548cde1
@robhoes authored
View
7 ocaml/client_records/records.ml
@@ -852,6 +852,10 @@ let vm_record rpc session_id vm =
make_field ~name:"networks"
~get:(fun () -> default nid (may (fun m -> Record_util.s2sm_to_string "; " m.API.vM_guest_metrics_networks) (xgm ()) ))
~get_map:(fun () -> default [] (may (fun m -> m.API.vM_guest_metrics_networks) (xgm ()))) ();
+ make_field ~name:"network-paths-optimized"
+ ~get:(fun () -> default nid (may (fun m -> string_of_bool m.API.vM_guest_metrics_network_paths_optimized) (xgm ()) )) ();
+ make_field ~name:"storage-paths-optimized"
+ ~get:(fun () -> default nid (may (fun m -> string_of_bool m.API.vM_guest_metrics_storage_paths_optimized) (xgm ()) )) ();
make_field ~name:"other"
~get:(fun () -> default nid (may (fun m -> Record_util.s2sm_to_string "; " m.API.vM_guest_metrics_other) (xgm ()) ))
~get_map:(fun () -> default [] (may (fun m -> m.API.vM_guest_metrics_other) (xgm()))) ();
@@ -886,6 +890,9 @@ let vm_record rpc session_id vm =
~get:(fun () -> (x ()).API.vM_generation_id) ();
make_field ~name:"hardware-platform-version"
~get:(fun () -> Int64.to_string (x ()).API.vM_hardware_platform_version) ();
+ make_field ~name:"auto-update-drivers"
+ ~get:(fun () -> string_of_bool (x ()).API.vM_auto_update_drivers)
+ ~set:(fun x -> Client.VM.set_auto_update_drivers rpc session_id vm (safe_bool_of_string "auto-update-drivers" x)) ();
]}
let host_crashdump_record rpc session_id host =
View
2  ocaml/idl/api_errors.ml
@@ -187,6 +187,7 @@ let vm_rebooted = "VM_REBOOTED"
let vm_halted = "VM_HALTED"
let vm_attached_to_more_than_one_vdi_with_timeoffset_marked_as_reset_on_boot = "VM_ATTACHED_TO_MORE_THAN_ONE_VDI_WITH_TIMEOFFSET_MARKED_AS_RESET_ON_BOOT"
let vms_failed_to_cooperate = "VMS_FAILED_TO_COOPERATE"
+let vm_pv_drivers_in_use = "VM_PV_DRIVERS_IN_USE"
let domain_exists = "DOMAIN_EXISTS"
let cannot_reset_control_domain = "CANNOT_RESET_CONTROL_DOMAIN"
let not_system_domain = "NOT_SYSTEM_DOMAIN"
@@ -195,7 +196,6 @@ let only_revert_snapshot = "REVERT_ONLY_ALLOWED_ON_SNAPSHOT"
let provision_failed_out_of_space = "PROVISION_FAILED_OUT_OF_SPACE"
let bootloader_failed = "BOOTLOADER_FAILED"
let unknown_bootloader = "UNKNOWN_BOOTLOADER"
-let operation_not_allowed = "OPERATION_NOT_ALLOWED"
let object_nolonger_exists = "OBJECT_NOLONGER_EXISTS"
let sr_attach_failed = "SR_ATTACH_FAILED"
let sr_full = "SR_FULL"
View
46 ocaml/idl/datamodel.ml
@@ -694,7 +694,8 @@ let _ =
~doc:"An error occured while saving the memory image of the specified virtual machine" ();
error Api_errors.vm_checkpoint_resume_failed [ "vm" ]
~doc:"An error occured while restoring the memory image of the specified virtual machine" ();
-
+ error Api_errors.vm_pv_drivers_in_use [ "vm" ]
+ ~doc:"VM PV drivers still in use" ();
(* VM appliance errors *)
error Api_errors.operation_partially_failed [ "operation" ]
~doc:"Some VMs belonging to the appliance threw an exception while carrying out the specified operation" ();
@@ -2389,6 +2390,25 @@ let vm_call_plugin = call
~allowed_roles:_R_VM_OP
()
+let vm_set_auto_update_drivers = call
+ ~name:"set_auto_update_drivers"
+ ~in_product_since:rel_dundee
+ ~doc:"Enable or disable PV auto update on Windows vm"
+ ~params:[Ref _vm, "self", "The vm to set auto update drivers";
+ Bool, "value", "True if the Windows Update feature is enabled on the VM; false otherwise"]
+ ~allowed_roles:_R_VM_OP
+ ~doc_tags:[Windows]
+ ()
+
+let vm_assert_can_set_auto_update_drivers = call
+ ~name:"assert_can_set_auto_update_drivers"
+ ~in_product_since:rel_dundee
+ ~doc:"Check if PV auto update can be set on Windows vm"
+ ~params:[Ref _vm, "self", "The vm to check if auto update drivers can be set";
+ Bool, "value", "True if the Windows Update feature is enabled on the VM; false otherwise"]
+ ~allowed_roles:_R_VM_OP
+ ~doc_tags:[Windows]
+ ()
(* ------------------------------------------------------------------------------------------------------------
Host Management
------------------------------------------------------------------------------------------------------------ *)
@@ -6937,6 +6957,8 @@ let vm =
vm_set_appliance;
vm_query_services;
vm_call_plugin;
+ vm_set_auto_update_drivers;
+ vm_assert_can_set_auto_update_drivers;
]
~contents:
([ uid _vm;
@@ -7013,7 +7035,8 @@ let vm =
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";
- ])
+ field ~qualifier:DynamicRO ~in_product_since:rel_dundee ~doc_tags:[Windows] ~default_value:(Some (VBool false)) ~ty:Bool "auto_update_drivers" "True if the Windows Update feature is enabled on the VM; false otherwise";
+ ])
()
let vm_memory_metrics =
@@ -7059,9 +7082,22 @@ let vm_guest_metrics =
field ~qualifier:DynamicRO ~ty:(Map(String, String)) "os_version" "version of the OS";
field ~qualifier:DynamicRO ~ty:(Map(String, String)) "PV_drivers_version"
"version of the PV drivers";
- field ~qualifier:DynamicRO ~ty:Bool ~in_oss_since:None "PV_drivers_up_to_date"
- "true if the PV drivers appear to be up to date";
-
+ field ~qualifier:DynamicRO ~ty:Bool ~in_oss_since:None
+ ~lifecycle:[
+ Published, rel_rio, "true if the PV drivers appear to be up to date";
+ Deprecated, rel_dundee, "Deprecated in favour of network_paths_optimized and storage_paths_optimized, and redefined in terms of them"
+ ]
+ "PV_drivers_up_to_date" "Logical AND of network_paths_optimized and storage_paths_optimized";
+ field ~qualifier:DynamicRO ~ty:Bool ~in_oss_since:None ~default_value:(Some (VBool false))
+ ~lifecycle:[
+ Published, rel_dundee, "Network paths are optimized with backend";
+ ]
+ "network_paths_optimized" "True if the network paths are optimized with PV driver";
+ field ~qualifier:DynamicRO ~ty:Bool ~in_oss_since:None ~default_value:(Some (VBool false))
+ ~lifecycle:[
+ Published, rel_dundee, "Storage paths are optimized with backend";
+ ]
+ "storage_paths_optimized" "True if the storage paths are optimized with PV driver";
field ~qualifier:DynamicRO ~ty:(Map(String, String))
~lifecycle:[
Published, rel_rio, "free/used/total";
View
2  ocaml/idl/datamodel_types.ml
@@ -151,7 +151,7 @@ and obj_op = Make | Delete | GetByUuid | GetByLabel | GetRecord | GetAll | GetAl
and param = {param_type:ty; param_name:string; param_doc:string; param_release: release; param_default: api_value option}
-and doc_tag = VM_lifecycle | Snapshots | Networking | Memory
+and doc_tag = VM_lifecycle | Snapshots | Networking | Memory | Windows
(** Types of RPC messages; in addition to those generated for object fields *)
and message = {
View
1  ocaml/idl/datamodel_utils.ml
@@ -526,6 +526,7 @@ let string_of_doc_tag = function
| Snapshots -> "snapshots"
| Networking -> "networking"
| Memory -> "memory"
+ | Windows -> "windows-vm"
let string_of_lifecycle_transition = function
| Prototyped -> "prototyped"
View
3  ocaml/xapi/create_misc.ml
@@ -216,7 +216,8 @@ and create_domain_zero_record ~__context ~domain_zero_ref (host_info: host_info)
~suspend_SR:Ref.null
~version:0L
~generation_id:""
- ~hardware_platform_version:0L;
+ ~hardware_platform_version:0L
+ ~auto_update_drivers:false;
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 =
View
9 ocaml/xapi/helpers.ml
@@ -1176,6 +1176,15 @@ 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
about this. *)
View
2  ocaml/xapi/import.ml
@@ -534,6 +534,8 @@ module GuestMetrics : HandlerTools = struct
~memory:gm_record.API.vM_guest_metrics_memory
~disks:gm_record.API.vM_guest_metrics_disks
~networks:gm_record.API.vM_guest_metrics_networks
+ ~network_paths_optimized:gm_record.API.vM_guest_metrics_network_paths_optimized
+ ~storage_paths_optimized:gm_record.API.vM_guest_metrics_storage_paths_optimized
~other:gm_record.API.vM_guest_metrics_other
~last_updated:gm_record.API.vM_guest_metrics_last_updated
~other_config:gm_record.API.vM_guest_metrics_other_config
View
8 ocaml/xapi/message_forwarding.ml
@@ -1314,6 +1314,14 @@ module Forward = functor(Local: Custom_actions.CUSTOM_ACTIONS) -> struct
(fun () ->
forward_vm_op ~local_fn ~__context ~vm (fun session_id rpc -> Client.VM.call_plugin rpc session_id vm plugin fn args))
+ let set_auto_update_drivers ~__context ~self ~value =
+ info "VM.set_auto_update_drivers: VM = '%s' to %b" (vm_uuid ~__context self) value;
+ Local.VM.set_auto_update_drivers ~__context ~self ~value
+
+ let assert_can_set_auto_update_drivers ~__context ~self ~value =
+ info "VM.assert_can_set_auto_update_drivers: VM = '%s' to %b " (vm_uuid ~__context self) value;
+ Local.VM.assert_can_set_auto_update_drivers ~__context ~self ~value
+
let set_xenstore_data ~__context ~self ~value =
info "VM.set_xenstore_data: VM = '%s'" (vm_uuid ~__context self);
Db.VM.set_xenstore_data ~__context ~self ~value;
View
14 ocaml/xapi/xapi_globs.ml
@@ -932,6 +932,8 @@ let all_options = options_of_xapi_globs_spec @ other_options
(* VIRTUAL HARDWARE PLATFORM VERSIONS *)
+let auto_update_drivers = 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 = [
@@ -939,17 +941,19 @@ let host_virtual_hardware_platform_versions = [
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;
- (* We anticipate that version two will be the first virtual
- hardware platform version to 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). *)
+
+ (* Version two which is "auto_update_drivers" 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). *)
+ auto_update_drivers;
]
module Resources = struct
View
71 ocaml/xapi/xapi_guest_agent.ml
@@ -55,6 +55,8 @@ let memory =
let device_id = [ "data/device_id", "device_id"]
+let extend base str = Printf.sprintf "%s/%s" base str
+
(* This function is passed the 'attr' node and a function it can use to
* find the directory listing of sub-nodes. It will return a map where the
* keys are the xenstore paths of the VM's IP addresses, and the values are
@@ -65,7 +67,6 @@ let device_id = [ "data/device_id", "device_id"]
* attr/eth0/ipv6/1/addr -> 0/ipv6/1
* *)
let networks path (list: string -> string list) =
- let extend base str = Printf.sprintf "%s/%s" base str in
(* Find all ipv6 addresses under a path. *)
let find_ipv6 path prefix = List.map
(fun str -> (extend (extend path str) "addr", extend prefix str))
@@ -97,6 +98,33 @@ let networks path (list: string -> string list) =
|> List.map (fun (path, prefix) -> find_all_ips path prefix)
|> List.concat
+(* This function is passed the "device/vif" node, a function it can use to
+ * find the directory listing of sub-nodes and a function to retrieve the value
+ * with the given path.
+ * If "state" of all VIFs are "4", the return value is true
+ * which means the network paths are optimized.
+ * Or else the return value is false.
+ *)
+let network_paths_optimized path (list: string -> string list) (lookup: string -> string option) =
+ List.fold_left (fun result vif_id ->
+ let vif_state = lookup (extend (extend path vif_id) "state") in
+ result && (vif_state = Some "4")
+ ) true (list path)
+
+(* This function is passed the "device/vbd" node, a function it can use to
+ * find the directory listing of sub-nodes and a function to retrieve the value
+ * with the given path.
+ * If "state" of all VBDs (except cdrom) are "4", the return value is true
+ * which means the storage paths are optimized.
+ * Or else the return value is false.
+ *)
+let storage_paths_optimized path (list: string -> string list) (lookup: string -> string option) =
+ List.fold_left (fun result vbd_id ->
+ let vbd_state = lookup (extend (extend path vbd_id) "state") in
+ let vbd_type = lookup (extend (extend path vbd_id) "device-type") in
+ result && (vbd_state = Some "4" || vbd_type = Some "cdrom")
+ ) true (list path)
+
(* One key is placed in the other map per control/* key in xenstore. This
catches keys like "feature-shutdown" "feature-hibernate" "feature-reboot"
"feature-sysrq" *)
@@ -110,7 +138,7 @@ let other all_control =
the results of these lookups differ *)
type m = (string * string) list
-let cache : (int, (m*m*m*m*m*m*float)) Hashtbl.t = Hashtbl.create 20
+let cache : (int, (m*m*m*m*m*m*bool*bool*bool*float)) Hashtbl.t = Hashtbl.create 20
let memory_targets : (int, int64) Hashtbl.t = Hashtbl.create 20
let dead_domains : IntSet.t ref = ref IntSet.empty
let mutex = Mutex.create ()
@@ -134,8 +162,12 @@ let all (lookup: string -> string option) (list: string -> string list) ~__conte
and networks = to_map (networks "attr" list)
and other = List.append (to_map (other all_control)) ts
and memory = to_map memory
+ and network_paths_optimized = network_paths_optimized "device/vif" list lookup
+ and storage_paths_optimized = storage_paths_optimized "device/vbd" list lookup
and last_updated = Unix.gettimeofday () in
+ let pv_drivers_up_to_date = network_paths_optimized && storage_paths_optimized in
+
(* let num = Mutex.execute mutex (fun () -> Hashtbl.fold (fun _ _ c -> 1 + c) cache 0) in
debug "Number of entries in hashtbl: %d" num; *)
@@ -154,6 +186,9 @@ let all (lookup: string -> string option) (list: string -> string list) ~__conte
other_cached,
memory_cached,
device_id_cached,
+ network_paths_optimized_cached,
+ storage_paths_optimized_cached,
+ pv_drivers_up_to_date_cached,
last_updated_cached
) = Mutex.execute mutex (fun () -> try
Hashtbl.find cache domid
@@ -167,7 +202,7 @@ let all (lookup: string -> string option) (list: string -> string list) ~__conte
dead_domains := IntSet.remove domid !dead_domains
else
dead_domains := IntSet.add domid !dead_domains;
- ([],[],[],[],[],[],0.0)) in
+ ([],[],[],[],[],[],false,false,false,0.0)) in
(* Consider the data valid IF the data/updated key exists AND the pv_drivers_version map
contains a major and minor version-- this prevents a migration mid-way through an update
@@ -187,7 +222,7 @@ let all (lookup: string -> string option) (list: string -> string list) ~__conte
then begin
(* Only if the data is valid, cache it (CA-20353) *)
- Mutex.execute mutex (fun () -> Hashtbl.replace cache domid (pv_drivers_version,os_version,networks,other,memory,device_id,last_updated));
+ Mutex.execute mutex (fun () -> Hashtbl.replace cache domid (pv_drivers_version,os_version,networks,other,memory,device_id,network_paths_optimized,storage_paths_optimized,pv_drivers_up_to_date,last_updated));
(* We update only if any actual data has changed *)
if ( pv_drivers_version_cached <> pv_drivers_version
@@ -198,7 +233,13 @@ let all (lookup: string -> string option) (list: string -> string list) ~__conte
||
other_cached <> other
||
- device_id_cached <> device_id)
+ device_id_cached <> device_id
+ ||
+ network_paths_optimized_cached <> network_paths_optimized
+ ||
+ storage_paths_optimized_cached <> storage_paths_optimized
+ ||
+ pv_drivers_up_to_date_cached <> pv_drivers_up_to_date)
(* Nb. we're ignoring the memory updates as far as the VM_guest_metrics API object is concerned. We are putting them into an RRD instead *)
(* ||
memory_cached <> memory)*)
@@ -213,7 +254,7 @@ let all (lookup: string -> string option) (list: string -> string list) ~__conte
let new_ref = Ref.make () and new_uuid = Uuid.to_string (Uuid.make_uuid ()) in
Db.VM_guest_metrics.create ~__context ~ref:new_ref ~uuid:new_uuid
~os_version:os_version ~pV_drivers_version:pv_drivers_version ~pV_drivers_up_to_date:false ~memory:[] ~disks:[] ~networks:networks ~other:other
- ~last_updated:(Date.of_float last_updated) ~other_config:[] ~live:true;
+ ~storage_paths_optimized:false ~network_paths_optimized:false ~last_updated:(Date.of_float last_updated) ~other_config:[] ~live:true;
Db.VM.set_guest_metrics ~__context ~self ~value:new_ref;
(* We've just set the thing to live, let's make sure it's not in the dead list *)
let sl xs = String.concat "; " (List.map (fun (k, v) -> k ^ ": " ^ v) xs) in
@@ -233,6 +274,15 @@ let all (lookup: string -> string option) (list: string -> string list) ~__conte
Db.VM_guest_metrics.set_other ~__context ~self:gm ~value:other;
Helpers.call_api_functions ~__context (fun rpc session_id -> Client.Client.VM.update_allowed_operations rpc session_id self);
end;
+ if(network_paths_optimized_cached <> network_paths_optimized) then begin
+ Db.VM_guest_metrics.set_network_paths_optimized ~__context ~self:gm ~value:network_paths_optimized;
+ end;
+ if(storage_paths_optimized_cached <> storage_paths_optimized) then begin
+ Db.VM_guest_metrics.set_storage_paths_optimized ~__context ~self:gm ~value:storage_paths_optimized;
+ end;
+ if(pv_drivers_up_to_date_cached <> pv_drivers_up_to_date) then begin
+ Db.VM_guest_metrics.set_PV_drivers_up_to_date ~__context ~self:gm ~value:pv_drivers_up_to_date;
+ end;
(* if(memory_cached <> memory) then
Db.VM_guest_metrics.set_memory ~__context ~self:gm ~value:memory; *)
@@ -256,7 +306,6 @@ let all (lookup: string -> string option) (list: string -> string list) ~__conte
(* Update the 'up to date' flag afterwards *)
let gmr = Db.VM_guest_metrics.get_record_internal ~__context ~self:gm in
let up_to_date = Xapi_pv_driver_version.is_up_to_date (Xapi_pv_driver_version.of_guest_metrics (Some gmr)) in
- Db.VM_guest_metrics.set_PV_drivers_up_to_date ~__context ~self:gm ~value:up_to_date;
(* CA-18034: If viridian flag isn't in there and we have current PV drivers then shove it in the metadata for next boot... *)
if up_to_date then begin
@@ -288,6 +337,9 @@ let all (lookup: string -> string option) (list: string -> string list) ~__conte
other, (* not the cached version *)
memory_cached,
device_id_cached,
+ network_paths_optimized_cached,
+ storage_paths_optimized_cached,
+ pv_drivers_up_to_date_cached,
last_updated)); (* not a cached version *)
let gm =
@@ -305,6 +357,8 @@ let all (lookup: string -> string option) (list: string -> string list) ~__conte
~disks:[]
~networks:networks_cached
~other:other
+ ~storage_paths_optimized:false
+ ~network_paths_optimized:false
~last_updated:(Date.of_float last_updated)
~other_config:[]
~live:false;
@@ -321,6 +375,9 @@ let all (lookup: string -> string option) (list: string -> string list) ~__conte
other, (* current version *)
[], (* memory *)
device_id_cached,
+ network_paths_optimized_cached,
+ storage_paths_optimized_cached,
+ pv_drivers_up_to_date_cached,
last_updated)); (* not a cached version *)
new_ref
in
View
24 ocaml/xapi/xapi_vm.ml
@@ -205,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
@@ -230,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 =
@@ -249,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 =
@@ -956,3 +962,21 @@ let import_convert ~__context ~_type ~username ~password ~sr ~remote_config =
let query_services ~__context ~self =
raise (Api_errors.Server_error(Api_errors.not_implemented, [ "query_services" ]))
+
+let assert_can_set_auto_update_drivers ~__context ~self ~value=
+ let power_state = Db.VM.get_power_state ~__context ~self in
+ if power_state <> `Halted
+ then raise (Api_errors.Server_error(Api_errors.vm_bad_power_state,
+ [Ref.string_of self; Record_util.power_to_string `Halted;
+ Record_util.power_to_string power_state]));
+
+ let vm_gm = Db.VM.get_guest_metrics ~__context ~self in
+ let network_optimized = try Db.VM_guest_metrics.get_network_paths_optimized ~__context ~self:vm_gm with _ -> false in
+ let storage_optimized = try Db.VM_guest_metrics.get_storage_paths_optimized ~__context ~self:vm_gm with _ -> false in
+ if storage_optimized || network_optimized
+ then
+ raise (Api_errors.Server_error(Api_errors.vm_pv_drivers_in_use, [ Ref.string_of self ]))
+
+let set_auto_update_drivers ~__context ~self ~value=
+ assert_can_set_auto_update_drivers ~__context ~self ~value;
+ Db.VM.set_auto_update_drivers ~__context ~self ~value
View
3  ocaml/xapi/xapi_vm.mli
@@ -250,3 +250,6 @@ val request_rdp_on : __context:Context.t -> vm:API.ref_VM -> unit
val request_rdp_off: __context:Context.t -> vm:API.ref_VM -> unit
val call_plugin : __context:Context.t -> vm:API.ref_VM -> plugin:string -> fn:string -> args:(string * string) list -> string
+
+val set_auto_update_drivers : __context:Context.t -> self:API.ref_VM -> value:bool -> unit
+val assert_can_set_auto_update_drivers : __context:Context.t -> self:API.ref_VM -> value:bool -> unit
View
3  ocaml/xapi/xapi_vm_clone.ml
@@ -335,7 +335,8 @@ 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
+ ~hardware_platform_version:all.Db_actions.vM_hardware_platform_version
+ ~auto_update_drivers:all.Db_actions.vM_auto_update_drivers
;
(* update the VM's parent field in case of snapshot. Note this must be done after "ref"
View
15 ocaml/xapi/xapi_vm_helpers.ml
@@ -164,6 +164,7 @@ let create ~__context ~name_label ~name_description
~version
~generation_id
~hardware_platform_version
+ ~auto_update_drivers:false
;
Db.VM.set_power_state ~__context ~self:vm_ref ~value:`Halted;
Xapi_vm_lifecycle.update_allowed_operations ~__context ~self:vm_ref;
@@ -936,6 +937,8 @@ let copy_guest_metrics ~__context ~vm =
~memory:all.API.vM_guest_metrics_memory
~disks:all.API.vM_guest_metrics_disks
~networks:all.API.vM_guest_metrics_networks
+ ~network_paths_optimized:all.API.vM_guest_metrics_network_paths_optimized
+ ~storage_paths_optimized:all.API.vM_guest_metrics_storage_paths_optimized
~other:all.API.vM_guest_metrics_other
~last_updated:all.API.vM_guest_metrics_last_updated
~other_config:all.API.vM_guest_metrics_other_config
@@ -1056,3 +1059,15 @@ let vm_fresh_genid ~__context ~self =
Db.VM.set_generation_id ~__context ~self ~value:new_genid ;
new_genid
+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 vm_record.API.vM_auto_update_drivers then
+ Xapi_globs.auto_update_drivers
+ 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
View
1  ocaml/xapi/xapi_xenops.ml
@@ -678,6 +678,7 @@ module MD = struct
on_reboot = on_normal_exit_behaviour vm.API.vM_actions_after_reboot;
pci_msitranslate = pci_msitranslate;
pci_power_mgmt = false;
+ auto_update_drivers = vm.API.vM_auto_update_drivers
}
Please sign in to comment.
Something went wrong with that request. Please try again.