diff --git a/lib/platform.ml b/lib/platform.ml new file mode 100644 index 000000000..aa562eb1c --- /dev/null +++ b/lib/platform.ml @@ -0,0 +1,34 @@ +(* + * Copyright (C) Citrix Systems Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; version 2.1 only. with the special + * exception on linking described in file LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + *) + + +type platformdata = (string * string) list + +let is_valid ~key ~platformdata = + (not (List.mem_assoc key platformdata)) || + (match List.assoc key platformdata |> String.lowercase with + | "true" | "1" | "false" | "0" -> true + | v -> false + ) + +let is_true ~key ~platformdata ~default = + try + match List.assoc key platformdata |> String.lowercase with + | "true" | "1" -> true + | "false" | "0" -> false + | _ -> default (* Check for validity using is_valid if required *) + with Not_found -> + default + + diff --git a/lib/platform.mli b/lib/platform.mli new file mode 100644 index 000000000..e10918577 --- /dev/null +++ b/lib/platform.mli @@ -0,0 +1,36 @@ +(* + * Copyright (C) Citrix Systems Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; version 2.1 only. with the special + * exception on linking described in file LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + *) + +(* This module defines interpretation of boolean platform values. It + * matches the interpretation implemented in XenAPI for these values. + *) + +type platformdata = (string * string) list + +(** [is_valid key platformdata] returns true if: + * 1. The key is _not_ in platformdata (absence of key is valid) or + * 2. The key is in platformdata, associated with a booleanish value *) +val is_valid: key:string -> platformdata:platformdata -> bool + +(** [is_true key platformdata default] returns true, if the platformdata + * contains a value for key that is "true" or "1". It returns false, if + * a value "0" or "false" exists. If the key doesn't exist or contains + * none of the values above, [default] is returned. + *) +val is_true: + key:string -> + platformdata:platformdata -> + default:bool -> + bool + diff --git a/lib/xenops_utils.ml b/lib/xenops_utils.ml index 61ed25d14..dcd909d27 100644 --- a/lib/xenops_utils.ml +++ b/lib/xenops_utils.ml @@ -548,6 +548,8 @@ let halted_vm = { last_start_time = 0.; shadow_multiplier_target = 1.; hvm = false; + nomigrate=false; + nested_virt=false; } let unplugged_pci = { diff --git a/xc/xenops_server_xen.ml b/xc/xenops_server_xen.ml index df154e324..bc028f9fe 100644 --- a/xc/xenops_server_xen.ml +++ b/xc/xenops_server_xen.ml @@ -84,8 +84,25 @@ module VmExtra = struct build_info: Domain.build_info option; ty: Vm.builder_info option; last_start_time: float; + nomigrate: bool; (* platform:nomigrate at boot time *) + nested_virt: bool (* platform:nested_virt at boot time *) } with rpc + let default_persistent_t = + { build_info = None + ; ty = None + ; last_start_time = 0.0 + ; nomigrate = false + ; nested_virt = false + } + + (* override rpc code generated for persistent_t. It is important that + * this code is before the declaration of type t because otherwise + * the rpc code for type t won't use it. *) + let persistent_t_of_rpc rpc = + Rpc.struct_extend rpc (rpc_of_persistent_t default_persistent_t) + |> persistent_t_of_rpc + type non_persistent_t = { create_info: Domain.create_info; vcpu_max: int; @@ -759,6 +776,8 @@ module VM = struct (* Earlier than the PV drivers update time, therefore any cached PV driver information will be kept. *) last_start_time = 0.; + nomigrate = false; + nested_virt = false } |> VmExtra.rpc_of_persistent_t |> Jsonrpc.to_string let mkints n = @@ -855,7 +874,19 @@ module VM = struct x.VmExtra.persistent, x.VmExtra.non_persistent | None -> begin debug "VM = %s; has no stored domain-level configuration, regenerating" vm.Vm.id; - let persistent = { VmExtra.build_info = None; ty = None; last_start_time = Unix.gettimeofday ()} in + let persistent = + { VmExtra.build_info = None + ; ty = None + ; last_start_time = Unix.gettimeofday () + ; nomigrate = Platform.is_true + ~key:"nomigrate" + ~platformdata:vm.Xenops_interface.Vm.platformdata + ~default:false + ; nested_virt=Platform.is_true + ~key:"nested_virt" + ~platformdata:vm.Xenops_interface.Vm.platformdata + ~default:false + } in let non_persistent = generate_non_persistent_state xc xs vm in persistent, non_persistent end in @@ -1638,6 +1669,14 @@ module VM = struct end; hvm = di.Xenctrl.hvm_guest; shadow_multiplier_target = shadow_multiplier_target; + nomigrate = begin match vme with + | None -> false + | Some x -> x.VmExtra.persistent.VmExtra.nomigrate + end; + nested_virt = begin match vme with + | None -> false + | Some x -> x.VmExtra.persistent.VmExtra.nested_virt + end } ) diff --git a/xl/xenops_server_xenlight.ml b/xl/xenops_server_xenlight.ml index ff56e4184..0266dd56f 100644 --- a/xl/xenops_server_xenlight.ml +++ b/xl/xenops_server_xenlight.ml @@ -236,6 +236,8 @@ module VmExtra = struct build_info: Domain.build_info option; ty: Vm.builder_info option; last_start_time: float; + nomigrate: bool; (* platform:nomigrate at boot time *) + nested_virt: bool (* platform:nested_virt at boot time *) } with rpc type non_persistent_t = { @@ -256,6 +258,19 @@ module VmExtra = struct persistent: persistent_t; non_persistent: non_persistent_t; } with rpc + + let default_persistent_t = + { build_info = None + ; ty = None + ; last_start_time = 0.0 + ; nomigrate = false + ; nested_virt = false + } + + (* override rpc code generated for persistent_t *) + let persistent_t_of_rpc rpc = + Rpc.struct_extend rpc (rpc_of_persistent_t default_persistent_t) + |> persistent_t_of_rpc end module DB = struct @@ -1793,6 +1808,8 @@ module VM = struct (* Earlier than the PV drivers update time, therefore any cached PV driver information will be kept. *) last_start_time = 0.; + nomigrate = false; + nested_virt = false } |> VmExtra.rpc_of_persistent_t |> Jsonrpc.to_string (* Could use fold_left to get the same value, but that would necessarily go through the whole list everytime, instead of the first n items, only. *) @@ -2087,7 +2104,19 @@ module VM = struct x.VmExtra.persistent, x.VmExtra.non_persistent | None -> begin debug "VM = %s; has no stored domain-level configuration, regenerating" vm.Vm.id; - let persistent = { VmExtra.build_info = None; ty = None; last_start_time = Unix.gettimeofday () } in + let persistent = + { VmExtra.build_info = None + ; ty = None + ; last_start_time = Unix.gettimeofday () + ; nomigrate = Platform.is_true + ~key:"nomigrate" + ~platformdata:vm.Xenops_interface.Vm.platformdata + ~default:false + ; nested_virt=Platform.is_true + ~key:"nested_virt" + ~platformdata:vm.Xenops_interface.Vm.platformdata + ~default:false + } in let non_persistent = generate_non_persistent_state xs vm in persistent, non_persistent end in @@ -2682,6 +2711,14 @@ module VM = struct end; shadow_multiplier_target = shadow_multiplier_target; hvm; + nomigrate = begin match vme with + | None -> false + | Some x -> x.VmExtra.persistent.VmExtra.nomigrate + end; + nested_virt = begin match vme with + | None -> false + | Some x -> x.VmExtra.persistent.VmExtra.nested_virt + end } )