Skip to content

Commit cf5be62

Browse files
committed
host.disable: Add auto_enabled parameter for persistency
Currently a manually disabled host will be re-enabled on toolstack restarts and host reboots, which will provoke VM migrations in an HA cluster. If maintenance requires many restarts, that could be painful. To allow for keeping a host persistently disabled across toolstack restarts and host reboots, add a new localdb flag "host_auto_enable" (set through the parameter on Host.disable). This coexists with the internal flag of host_disabled_until_reboot, which is only set on host poweroff internally and cannot be controlled by the user directly. With host_auto_enable set to false, xapi will not re-enable a host on its own no matter what: toolstack restarts, host reboots, calls to consider_enabling_host (triggered by PBD plugs etc.) will have no effect. Only a manual call to Host.enable will re-enable the host. Expose the new parameter in the CLI. Also fix up the comment in xapi_host_helpers.mli. Signed-off-by: Andrii Sultanov <[email protected]>
1 parent 6c16a2f commit cf5be62

12 files changed

+114
-31
lines changed

ocaml/idl/datamodel_common.ml

Lines changed: 1 addition & 1 deletion
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 = 789
13+
let schema_minor_vsn = 790
1414

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

ocaml/idl/datamodel_errors.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,11 @@ let _ =
648648
"The specified server is disabled and cannot be re-enabled until after \
649649
it has rebooted."
650650
() ;
651+
error Api_errors.host_disabled_indefinitely ["host"]
652+
~doc:
653+
"The specified server is disabled and can only be re-enabled manually \
654+
with Host.enable."
655+
() ;
651656
error Api_errors.no_hosts_available []
652657
~doc:"There were no servers available to complete the specified operation."
653658
() ;

ocaml/idl/datamodel_host.ml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,12 +625,37 @@ let disable =
625625
, "Puts the host into a state in which no new VMs can be started. \
626626
Currently active VMs on the host continue to execute."
627627
)
628+
; ( Changed
629+
, "25.31.0"
630+
, "Added auto_enable option to allow persisting the state across \
631+
toolstack restarts and host reboots."
632+
)
628633
]
629634
~name:"disable"
630635
~doc:
631636
"Puts the host into a state in which no new VMs can be started. \
632637
Currently active VMs on the host continue to execute."
633-
~params:[(Ref _host, "host", "The Host to disable")]
638+
~versioned_params:
639+
[
640+
{
641+
param_type= Ref _host
642+
; param_name= "host"
643+
; param_doc= "The Host to disable"
644+
; param_release= rio_release
645+
; param_default= None
646+
}
647+
; {
648+
param_type= Bool
649+
; param_name= "auto_enable"
650+
; param_doc=
651+
"If true (default), the host will be re-enabled after a toolstack \
652+
restart automatically. If false, the host will be disabled \
653+
indefinitely, across toolstack restarts and host reboots, until \
654+
re-enabled explicitly with Host.enable."
655+
; param_release= numbered_release "25.31.0"
656+
; param_default= Some (VBool true)
657+
}
658+
]
634659
~allowed_roles:(_R_POOL_OP ++ _R_CLIENT_CERT)
635660
()
636661

ocaml/xapi-cli-server/cli_frontend.ml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -579,8 +579,10 @@ let rec cmdtable_data : (string * cmd_spec) list =
579579
; ( "host-disable"
580580
, {
581581
reqd= []
582-
; optn= []
583-
; help= "Disable the XE host."
582+
; optn= ["auto-enable"]
583+
; help=
584+
"Disable the XE host. Setting auto-enable=false will keep the host \
585+
persistently disabled until manually re-enabled with Host.enable."
584586
; implementation= No_fd Cli_operations.host_disable
585587
; flags= [Host_selectors]
586588
}
@@ -4049,7 +4051,7 @@ let rio_help printer minimal cmd =
40494051
in
40504052
let help =
40514053
Printf.sprintf
4052-
{|Usage:
4054+
{|Usage:
40534055
%s <command>
40544056
[ -s <server> ] XenServer host
40554057
[ -p <port> ] XenServer port number
@@ -4061,7 +4063,7 @@ let rio_help printer minimal cmd =
40614063
[ --traceparent <value> ] Distributed tracing context
40624064
[ <other arguments> ... ] Command-specific options
40634065

4064-
To get help on a specific command:
4066+
To get help on a specific command:
40654067
%s help <command>
40664068

40674069
|}

ocaml/xapi-cli-server/cli_operations.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2240,6 +2240,9 @@ let print_assert_exception e =
22402240
"VM requires access to SR: " ^ Cli_util.ref_convert (get_arg 2 params)
22412241
| Api_errors.Server_error (code, _) when code = Api_errors.host_disabled ->
22422242
"Host disabled (use 'xe host-enable' to re-enable)"
2243+
| Api_errors.Server_error (code, _)
2244+
when code = Api_errors.host_disabled_indefinitely ->
2245+
"Host disabled indefinitely (use 'xe host-enable' to re-enable)"
22432246
| Api_errors.Server_error (code, _) when code = Api_errors.host_not_live ->
22442247
"Host down"
22452248
| Api_errors.Server_error (code, _)
@@ -6565,12 +6568,14 @@ let bond_set_mode _printer rpc session_id params =
65656568
Client.Bond.set_mode ~rpc ~session_id ~self:bond ~value:mode
65666569

65676570
let host_disable _printer rpc session_id params =
6571+
let auto_enable = get_bool_param ~default:true params "auto-enable" in
65686572
ignore
65696573
(do_host_op rpc session_id
65706574
(fun _ host ->
65716575
Client.Host.disable ~rpc ~session_id ~host:(host.getref ())
6576+
~auto_enable
65726577
)
6573-
params []
6578+
params ["auto-enable"]
65746579
)
65756580

65766581
let host_sync_data _printer rpc session_id params =

ocaml/xapi-consts/api_errors.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ let host_disabled = add_error "HOST_DISABLED"
113113

114114
let host_disabled_until_reboot = add_error "HOST_DISABLED_UNTIL_REBOOT"
115115

116+
let host_disabled_indefinitely = add_error "HOST_DISABLED_INDEFINITELY"
117+
116118
let host_not_disabled = add_error "HOST_NOT_DISABLED"
117119

118120
let host_not_live = add_error "HOST_NOT_LIVE"

ocaml/xapi-consts/constants.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,11 @@ let master_scripts = "master_scripts"
233233
This will prevent anyone from re-enabling the host and starting VMs on it during shutdown. *)
234234
let host_disabled_until_reboot = "host_disabled_until_reboot"
235235

236+
(* This flag is set to false when the host is forcibly disabled in a
237+
persistent way - it will not be re-enabled on startup (even after reboots)
238+
until manually directed by the user *)
239+
let host_auto_enable = "host_auto_enable"
240+
236241
(* Set when shutting down and rebooting. If we come up and finds no new crashdump and HA is enabled,
237242
we assume the host was fenced. *)
238243
let host_restarted_cleanly = "host_restarted_cleanly"

ocaml/xapi/message_forwarding.ml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3345,13 +3345,15 @@ functor
33453345
(host_uuid ~__context host) ;
33463346
Local.Host.get_management_interface ~__context ~host
33473347

3348-
let disable ~__context ~host =
3349-
info "Host.disable: host = '%s'" (host_uuid ~__context host) ;
3348+
let disable ~__context ~host ~auto_enable =
3349+
info "Host.disable: host = '%s', auto_enable = '%b'"
3350+
(host_uuid ~__context host)
3351+
auto_enable ;
33503352
(* Block call if this would break our VM restart plan *)
33513353
Xapi_ha_vm_failover.assert_host_disable_preserves_ha_plan ~__context
33523354
host ;
3353-
let local_fn = Local.Host.disable ~host in
3354-
let remote_fn = Client.Host.disable ~host in
3355+
let local_fn = Local.Host.disable ~host ~auto_enable in
3356+
let remote_fn = Client.Host.disable ~host ~auto_enable in
33553357
do_op_on ~local_fn ~__context ~host ~remote_fn ;
33563358
Xapi_host_helpers.update_allowed_operations ~__context ~self:host
33573359

ocaml/xapi/xapi_host.ml

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ let set_power_on_mode ~__context ~self ~power_on_mode ~power_on_config =
7474
+ HA is enabled and this host has broken storage or networking which would cause protected VMs
7575
to become non-agile
7676
*)
77-
let assert_safe_to_reenable ~__context ~self =
77+
let assert_safe_to_reenable ~__context ~self ~user_request =
7878
assert_startup_complete () ;
7979
Repository_helpers.assert_no_host_pending_mandatory_guidance ~__context
8080
~host:self ;
@@ -87,6 +87,14 @@ let assert_safe_to_reenable ~__context ~self =
8787
(Api_errors.Server_error
8888
(Api_errors.host_disabled_until_reboot, [Ref.string_of self])
8989
) ;
90+
let host_auto_enable =
91+
try bool_of_string (Localdb.get Constants.host_auto_enable) with _ -> true
92+
in
93+
if (not host_auto_enable) && not user_request then
94+
raise
95+
(Api_errors.Server_error
96+
(Api_errors.host_disabled_indefinitely, [Ref.string_of self])
97+
) ;
9098
if Db.Pool.get_ha_enabled ~__context ~self:(Helpers.get_pool ~__context) then (
9199
let pbds = Db.Host.get_PBDs ~__context ~self in
92100
let unplugged_pbds =
@@ -799,20 +807,23 @@ let shutdown_agent ~__context =
799807
~reason:Xapi_hooks.reason__clean_shutdown ;
800808
Xapi_fuse.light_fuse_and_dont_restart ~fuse_length:1. ()
801809

802-
let disable ~__context ~host =
810+
let disable ~__context ~host ~auto_enable =
803811
if Db.Host.get_enabled ~__context ~self:host then (
804812
info
805813
"Host.enabled: setting host %s (%s) to disabled because of user request"
806814
(Ref.string_of host)
807815
(Db.Host.get_hostname ~__context ~self:host) ;
808816
Db.Host.set_enabled ~__context ~self:host ~value:false ;
809-
Xapi_host_helpers.user_requested_host_disable := true
817+
Xapi_host_helpers.user_requested_host_disable := true ;
818+
if not auto_enable then
819+
Localdb.put Constants.host_auto_enable "false"
810820
)
811821

812822
let enable ~__context ~host =
813823
if not (Db.Host.get_enabled ~__context ~self:host) then (
814-
assert_safe_to_reenable ~__context ~self:host ;
824+
assert_safe_to_reenable ~__context ~self:host ~user_request:true ;
815825
Xapi_host_helpers.user_requested_host_disable := false ;
826+
Localdb.put Constants.host_auto_enable "true" ;
816827
info "Host.enabled: setting host %s (%s) to enabled because of user request"
817828
(Ref.string_of host)
818829
(Db.Host.get_hostname ~__context ~self:host) ;
@@ -3087,7 +3098,7 @@ let apply_updates ~__context ~self ~hash =
30873098
if Db.Pool.get_ha_enabled ~__context ~self:pool then
30883099
raise Api_errors.(Server_error (ha_is_enabled, [])) ;
30893100
if Db.Host.get_enabled ~__context ~self then (
3090-
disable ~__context ~host:self ;
3101+
disable ~__context ~host:self ~auto_enable:true ;
30913102
Xapi_host_helpers.update_allowed_operations ~__context ~self
30923103
) ;
30933104
Xapi_host_helpers.with_host_operation ~__context ~self

ocaml/xapi/xapi_host.mli

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ val restart_agent : __context:'a -> host:'b -> unit
7979

8080
val shutdown_agent : __context:Context.t -> unit
8181

82-
val disable : __context:Context.t -> host:[`host] Ref.t -> unit
82+
val disable :
83+
__context:Context.t -> host:[`host] Ref.t -> auto_enable:bool -> unit
8384

8485
val enable : __context:Context.t -> host:[`host] Ref.t -> unit
8586

0 commit comments

Comments
 (0)