Skip to content

Commit

Permalink
Merge c4c5c78 into 53404c7
Browse files Browse the repository at this point in the history
  • Loading branch information
edwintorok committed Jun 8, 2018
2 parents 53404c7 + c4c5c78 commit d3782de
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 28 deletions.
4 changes: 3 additions & 1 deletion ocaml/idl/datamodel_errors.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1143,7 +1143,9 @@ let _ =
error Api_errors.cluster_host_not_joined [ "cluster_host" ]
~doc:"Cluster_host operation failed as the cluster_host has not joined the cluster." ();
error Api_errors.cluster_host_is_last ["cluster_host"]
~doc:"The last cluster host cannot be destroyed. Destroy the cluster instead" ()
~doc:"The last cluster host cannot be destroyed. Destroy the cluster instead" ();
error Api_errors.no_cluster_hosts_reachable ["cluster"]
~doc:"No other cluster host was reachable when joining" ()



Expand Down
1 change: 1 addition & 0 deletions ocaml/xapi-consts/api_errors.ml
Original file line number Diff line number Diff line change
Expand Up @@ -616,3 +616,4 @@ let cluster_stack_in_use = "CLUSTER_STACK_IN_USE"
let invalid_cluster_stack = "INVALID_CLUSTER_STACK"
let pif_not_attached_to_host = "PIF_NOT_ATTACHED_TO_HOST"
let cluster_host_not_joined = "CLUSTER_HOST_NOT_JOINED"
let no_cluster_hosts_reachable = "NO_CLUSTER_HOSTS_REACHABLE"
12 changes: 9 additions & 3 deletions ocaml/xapi/helpers.ml
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,16 @@ let get_pool ~__context = List.hd (Db.Pool.get_all ~__context)
let get_master ~__context =
Db.Pool.get_master ~__context ~self:(get_pool ~__context)

let get_management_iface_is_connected ~__context =
let get_iface_is_connected ~__context iface =
let dbg = Context.string_of_task __context in
Net.Bridge.get_physical_interfaces dbg (Xapi_inventory.lookup Xapi_inventory._management_interface)
|> List.exists (fun name -> Net.Interface.is_connected dbg name)
Net.Bridge.get_physical_interfaces dbg iface
|> List.exists (fun name ->
debug "Checking interface %s" name;
Net.Interface.is_connected dbg name)

let get_management_iface_is_connected ~__context =
Xapi_inventory.lookup Xapi_inventory._management_interface
|> get_iface_is_connected ~__context

let get_primary_ip_addr ~__context iface primary_address_type =
if iface = "" then
Expand Down
15 changes: 11 additions & 4 deletions ocaml/xapi/xapi_cluster_host.ml
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,18 @@ let join_internal ~__context ~self =
let cluster = Db.Cluster_host.get_cluster ~__context ~self in
let cluster_token = Db.Cluster.get_cluster_token ~__context ~self:cluster in
let ip = ip_of_pif (pIF, Db.PIF.get_record ~__context ~self:pIF) in
let ip_list = List.map (fun self ->
let p_ref = Db.Cluster_host.get_PIF ~__context ~self in
let p_rec = Db.PIF.get_record ~__context ~self:p_ref in
ip_of_pif (p_ref,p_rec)
let ip_list = Xapi_stdext_std.Listext.List.filter_map (fun self ->
let p_ref = Db.Cluster_host.get_PIF ~__context ~self in
let p_rec = Db.PIF.get_record ~__context ~self:p_ref in
(* parallel join: some hosts may not have an IP yet *)
try
let other_ip = ip_of_pif (p_ref,p_rec) in
if other_ip <> ip then Some other_ip
else None
with _ -> None
) (Db.Cluster.get_cluster_hosts ~__context ~self:cluster) in
if ip_list = [] then
raise Api_errors.(Server_error (no_cluster_hosts_reachable, [Ref.string_of cluster]));

debug "Enabling clusterd and joining cluster_host %s" (Ref.string_of self);
Xapi_clustering.Daemon.enable ~__context;
Expand Down
42 changes: 22 additions & 20 deletions ocaml/xapi/xapi_mgmt_iface.ml
Original file line number Diff line number Diff line change
Expand Up @@ -160,31 +160,33 @@ let rebind ~__context =
let ip_mutex = Mutex.create ()
let ip_cond = Condition.create ()

let wait_for_management_ip ~__context =
let ip = ref (match Helpers.get_management_ip_addr ~__context with Some x -> x | None -> "") in
let is_connected = ref (Helpers.get_management_iface_is_connected ~__context) in
Mutex.execute ip_mutex
(fun () -> while !ip = "" && !is_connected = false do
Condition.wait ip_cond ip_mutex;
ip := (match Helpers.get_management_ip_addr ~__context with Some x -> x | None -> "");
is_connected := (Helpers.get_management_iface_is_connected ~__context)
done);
!ip
let wait_for_ip get_ip is_connected =
let rec loop () =
let ip = get_ip () in
let connected = is_connected () in
if ip = "" || not connected then begin
debug "wait_for_ip (IP=%s, connected:%b), waiting" ip connected;
Condition.wait ip_cond ip_mutex;
loop ()
end
else ip
in
Mutex.execute ip_mutex loop

let has_carrier ~__context ~self =
let metrics = Db.PIF.get_metrics ~__context ~self in
Db.PIF_metrics.get_carrier ~__context ~self:metrics
let wait_for_management_ip ~__context =
let get_ip () = match Helpers.get_management_ip_addr ~__context with Some x -> x | None -> "" in
let is_connected () = Helpers.get_management_iface_is_connected ~__context in
wait_for_ip get_ip is_connected

(* CA-280237: Called in startup sequence after creating cluster_hosts *)
let wait_for_clustering_ip ~__context ~(self : API.ref_Cluster_host) =
let pIF = Db.Cluster_host.get_PIF ~__context ~self in
let iP = ref (Db.PIF.get_IP ~__context ~self:pIF) in
Mutex.execute ip_mutex (* Don't return until PIF is plugged AND has a valid IP *)
(fun () -> while !iP="" || not (has_carrier ~__context ~self:pIF) do
Condition.wait ip_cond ip_mutex;
iP := Db.PIF.get_IP ~__context ~self:pIF
done);
!iP
let network = Db.PIF.get_network ~__context ~self:pIF in
let interface = Db.Network.get_bridge ~__context ~self:network in
debug "Waiting for clustering IP on interface %s (%s)" interface (Ref.string_of pIF);
let get_ip () = Db.PIF.get_IP ~__context ~self:pIF in
let is_connected () = Helpers.get_iface_is_connected ~__context interface in
wait_for_ip get_ip is_connected

let on_dom0_networking_change ~__context =
debug "Checking to see if hostname or management IP has changed";
Expand Down

0 comments on commit d3782de

Please sign in to comment.