# HG changeset patch # User Rob Hoes Add CPUID features whitelisting foor Pool.join. This allows the user to exclude CPUID features from the Pool.join checks by setting a mask in Pool.other_config:cpuid_feature_mask. When comparing the CPUID features of the pool and the joining host for equality, this mask is applied before the comparison. The format is the same as the format of the feature field in Host.cpu_info. The default is "ffffff7f-ffffffff-ffffffff-ffffffff", which defines the EST feature, bit 7 of the base ecx flags, as "don't care". Signed-off-by: Rob Hoes diff -r e7fc4836cce5 ocaml/xapi/dbsync_master.ml --- a/ocaml/xapi/dbsync_master.ml Wed Mar 17 11:07:36 2010 +0000 +++ b/ocaml/xapi/dbsync_master.ml Fri Mar 19 09:59:15 2010 +0000 @@ -59,6 +59,15 @@ let set_master_pool_reference ~__context = let pool = List.hd (Db.Pool.get_all ~__context) in Db.Pool.set_master ~__context ~self:pool ~value:(Helpers.get_localhost ~__context) + +let set_pool_defaults ~__context = + (* If Pool.other_config has no cpuid_feature_mask_key yet, fill in the default. *) + let pool = List.hd (Db.Pool.get_all ~__context) in + let other_config = Db.Pool.get_other_config ~__context ~self:pool in + if not (List.mem_assoc Xapi_globs.cpuid_feature_mask_key other_config) then + Db.Pool.add_to_other_config ~__context ~self:pool + ~key:Xapi_globs.cpuid_feature_mask_key + ~value:Xapi_globs.cpuid_default_feature_mask (** Look at all running VMs, examine their consoles and regenerate the console URLs. This catches the case where the IP address changes but the URLs still point to the wrong @@ -223,6 +232,7 @@ set_master_pool_reference ~__context; set_master_ip ~__context; set_master_live ~__context; + set_pool_defaults ~__context; (* CA-15449: when we restore from backup we end up with Hosts being forgotten and VMs marked as running with dangling resident_on references. We delete the control domains diff -r e7fc4836cce5 ocaml/xapi/xapi_globs.ml --- a/ocaml/xapi/xapi_globs.ml Wed Mar 17 11:07:36 2010 +0000 +++ b/ocaml/xapi/xapi_globs.ml Fri Mar 19 09:59:15 2010 +0000 @@ -603,3 +603,12 @@ let permanent_master_failure_retry_timeout = 5. *. 60. (* 5 minutes *) +(** {2 CPUID feature masking} *) + +(** Pool.other_config key to hold the user-defined feature mask, used to + * override the feature equality checks at a Pool.join. *) +let cpuid_feature_mask_key = "cpuid_feature_mask" + +(** Default feature mask: EST (base_ecx.7) is ignored. *) +let cpuid_default_feature_mask = "ffffff7f-ffffffff-ffffffff-ffffffff" + diff -r e7fc4836cce5 ocaml/xapi/xapi_pool.ml --- a/ocaml/xapi/xapi_pool.ml Wed Mar 17 11:07:36 2010 +0000 +++ b/ocaml/xapi/xapi_pool.ml Fri Mar 19 09:59:15 2010 +0000 @@ -37,7 +37,7 @@ let get_master ~rpc ~session_id = let pool = List.hd (Client.Pool.get_all rpc session_id) in Client.Pool.get_master rpc session_id pool - + (* Pre-join asserts *) let pre_join_checks ~__context ~rpc ~session_id ~force = (* I cannot join a Pool if I have HA already enabled on me *) @@ -178,9 +178,6 @@ let my_software_compare = get_software_version_fields my_software_version in let master_software_compare = get_software_version_fields master_software_version in - - if my_software_compare <> master_software_compare then - raise (Api_errors.Server_error(Api_errors.pool_hosts_not_homogeneous,["software version differs"])); debug "Pool pre-join Software homogeneity check:"; debug "Slave software:"; @@ -188,25 +185,51 @@ debug "Master software:"; print_software_version master_software_compare; + if my_software_compare <> master_software_compare then + raise (Api_errors.Server_error(Api_errors.pool_hosts_not_homogeneous,["software version differs"])); + (* Check CPUs *) let master_cpu_info = master.API.host_cpu_info in let my_cpu_info = Db.Host.get_cpu_info ~__context ~self:me in - + let pool_other_config = + let pool = List.hd (Client.Pool.get_all rpc session_id) in + Client.Pool.get_other_config rpc session_id pool + in + let mask = + try + let features = List.assoc Xapi_globs.cpuid_feature_mask_key pool_other_config in + Some (Cpuid.string_to_features features) + with _ -> None + in let get_comparable_fields cpu_info = - List.assoc "vendor" cpu_info, List.assoc "features" cpu_info in + List.assoc "vendor" cpu_info, + let features = List.assoc "features" cpu_info in + match mask with + | None -> features + | Some mask -> + let features = Cpuid.string_to_features features in + let relevant_features = Cpuid.mask_features features mask in + Cpuid.features_to_string relevant_features + in let my_cpus_compare = get_comparable_fields my_cpu_info in let master_cpus_compare = get_comparable_fields master_cpu_info in - let print_cpu (vendor, features) = debug "%s, %s" vendor features in + let print_cpu cpu = debug "%s, %s" + (List.assoc "vendor" cpu) (List.assoc "features" cpu) in debug "Pool pre-join CPU homogeneity check:"; - debug "Slave cpus:"; - print_cpu my_cpus_compare; - debug "Master cpus:"; - print_cpu master_cpus_compare; + debug "Slave CPUs:"; + print_cpu my_cpu_info; + debug "Master CPUs:"; + print_cpu master_cpu_info; + begin match mask with + | Some mask -> + debug "User-defined feature mask on pool: %s" (Cpuid.features_to_string mask) + | None -> () + end; if my_cpus_compare <> master_cpus_compare then - raise (Api_errors.Server_error(Api_errors.pool_hosts_not_homogeneous,["cpus differ"])) in + raise (Api_errors.Server_error(Api_errors.pool_hosts_not_homogeneous,["CPUs differ"])) in let assert_not_joining_myself () = let master = get_master rpc session_id in