Skip to content

Commit 46a66c3

Browse files
committed
CP-54034: Expose expected_votes in Cluster object
The `expected_votes` field in corosync represents the number of hosts that is expected by the cluster stack. In the context of corosync, this is the same as the number of hosts as in the corosync.conf file*. This is a useful field to expose to the user so that they can see how many nodes actually are expected. We also have `Cluster_host` object, which represents xapi's view of what nodes should be in the cluster, but that might not be identical to corosync's view, especially when a host is disabled, but is still left in the list of Cluster_host objects. Although one could argue that we could infer this `expected_votes` field from the number of enabled Cluster_hosts, it might still be useful to get this information directly from corosync. *: there are ways in corosync to make one host cast multiple votes, but that feature is not used. Signed-off-by: Vincent Liu <[email protected]>
1 parent 187d61e commit 46a66c3

11 files changed

+22
-6
lines changed

ocaml/idl/datamodel_cluster.ml

+3
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ let t =
219219
; field ~qualifier:DynamicRO ~lifecycle:[] ~ty:Int "live_hosts"
220220
~default_value:(Some (VInt 0L))
221221
"Current number of live hosts, according to the cluster stack"
222+
; field ~qualifier:DynamicRO ~lifecycle:[] ~ty:Int "expected_hosts"
223+
~default_value:(Some (VInt 0L))
224+
"Total number of hosts expected by the cluster stack"
222225
]
223226
@ allowed_and_current_operations cluster_operation
224227
@ [

ocaml/idl/datamodel_common.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ open Datamodel_roles
1010
to leave a gap for potential hotfixes needing to increment the schema version.*)
1111
let schema_major_vsn = 5
1212

13-
let schema_minor_vsn = 788
13+
let schema_minor_vsn = 789
1414

1515
(* Historical schema versions just in case this is useful later *)
1616
let rio_schema_major_vsn = 5

ocaml/idl/datamodel_lifecycle.ml

+2
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ let prototyped_of_field = function
7777
Some "24.3.0"
7878
| "Cluster_host", "live" ->
7979
Some "24.3.0"
80+
| "Cluster", "expected_hosts" ->
81+
Some "25.16.0-next"
8082
| "Cluster", "live_hosts" ->
8183
Some "24.3.0"
8284
| "Cluster", "quorum" ->

ocaml/idl/schematest.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ let hash x = Digest.string x |> Digest.to_hex
33
(* BEWARE: if this changes, check that schema has been bumped accordingly in
44
ocaml/idl/datamodel_common.ml, usually schema_minor_vsn *)
55

6-
let last_known_schema_hash = "0cf3458af211661024fca9c1d0ab34ab"
6+
let last_known_schema_hash = "2f80cd8fbfd0eedab4dfe345565bcb64"
77

88
let current_schema_hash : string =
99
let open Datamodel_types in

ocaml/tests/common/test_common.ml

+3-2
Original file line numberDiff line numberDiff line change
@@ -626,12 +626,13 @@ let make_cluster_and_cluster_host ~__context ?(ref = Ref.make ())
626626
?(token_timeout = Constants.default_token_timeout_s)
627627
?(token_timeout_coefficient = Constants.default_token_timeout_coefficient_s)
628628
?(cluster_config = []) ?(other_config = []) ?(host = Ref.null)
629-
?(is_quorate = false) ?(quorum = 0L) ?(live_hosts = 0L) () =
629+
?(is_quorate = false) ?(quorum = 0L) ?(live_hosts = 0L)
630+
?(expected_hosts = 0L) () =
630631
Db.Cluster.create ~__context ~ref ~uuid ~cluster_token ~pending_forget:[]
631632
~cluster_stack ~cluster_stack_version ~allowed_operations
632633
~current_operations ~pool_auto_join ~token_timeout
633634
~token_timeout_coefficient ~cluster_config ~other_config ~is_quorate ~quorum
634-
~live_hosts ;
635+
~live_hosts ~expected_hosts ;
635636
let cluster_host_ref =
636637
make_cluster_host ~__context ~cluster:ref ~host ~pIF ()
637638
in

ocaml/tests/test_cluster.ml

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ let test_clusterd_rpc ~__context call =
6969
; num_times_booted= 1
7070
; is_quorate= true
7171
; total_votes= 1
72+
; expected_votes= 1
7273
; quorum= 1
7374
; quorum_members= Some [me]
7475
; is_running= true

ocaml/tests/test_cluster_host.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ let create_cluster ~__context pool_auto_join =
2424
~token_timeout_coefficient:Constants.default_token_timeout_coefficient_s
2525
~allowed_operations:[] ~current_operations:[] ~pool_auto_join
2626
~cluster_config:[] ~other_config:[] ~pending_forget:[] ~is_quorate:false
27-
~quorum:0L ~live_hosts:0L ;
27+
~quorum:0L ~live_hosts:0L ~expected_hosts:0L ;
2828
cluster_ref
2929

3030
let check_cluster_option =

ocaml/xapi-cli-server/records.ml

+3
Original file line numberDiff line numberDiff line change
@@ -5132,6 +5132,9 @@ let cluster_record rpc session_id cluster =
51325132
; make_field ~name:"live-hosts"
51335133
~get:(fun () -> Int64.to_string (x ()).API.cluster_live_hosts)
51345134
()
5135+
; make_field ~name:"expected-hosts"
5136+
~get:(fun () -> Int64.to_string (x ()).API.cluster_expected_hosts)
5137+
()
51355138
]
51365139
}
51375140

ocaml/xapi-idl/cluster/cluster_interface.ml

+4
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ type optional_path = string option [@@deriving rpcty]
159159
type quorum_info = {
160160
is_quorate: bool
161161
; total_votes: int
162+
(* number of nodes that the cluster stack thinks are currently in the cluster *)
163+
; expected_votes: int
164+
(* number of nodes that the cluster stack is expecting to be in the cluster *)
162165
; quorum: int (** number of nodes required to form a quorum *)
163166
; quorum_members: all_members option
164167
}
@@ -179,6 +182,7 @@ type diagnostics = {
179182
; is_quorate: bool
180183
; is_running: bool
181184
; total_votes: int
185+
; expected_votes: int
182186
; quorum: int
183187
; quorum_members: all_members option
184188
; startup_finished: bool

ocaml/xapi/xapi_cluster.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ let create ~__context ~pIF ~cluster_stack ~pool_auto_join ~token_timeout
9696
~pending_forget:[] ~pool_auto_join ~token_timeout
9797
~token_timeout_coefficient ~current_operations:[]
9898
~allowed_operations:[] ~cluster_config:[] ~other_config:[]
99-
~is_quorate:false ~quorum:0L ~live_hosts:0L ;
99+
~is_quorate:false ~quorum:0L ~live_hosts:0L ~expected_hosts:0L ;
100100
Db.Cluster_host.create ~__context ~ref:cluster_host_ref
101101
~uuid:cluster_host_uuid ~cluster:cluster_ref ~host ~enabled:true
102102
~pIF ~current_operations:[] ~allowed_operations:[] ~other_config:[]

ocaml/xapi/xapi_clustering.ml

+2
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,8 @@ module Watcher = struct
516516
Db.Cluster.set_quorum ~__context ~self:cluster
517517
~value:(Int64.of_int diag.quorum) ;
518518
Db.Cluster.set_live_hosts ~__context ~self:cluster
519+
~value:(Int64.of_int diag.total_votes) ;
520+
Db.Cluster.set_expected_hosts ~__context ~self:cluster
519521
~value:(Int64.of_int diag.total_votes)
520522
| Error (InternalError message) | Error (Unix_error message) ->
521523
warn "%s Cannot query diagnostics due to %s, not performing update"

0 commit comments

Comments
 (0)