Skip to content

Commit b3a3000

Browse files
committed
CP-53478: Implement SSH enabeld timeout API for Dom0 SSH control
Implemented XAPI APIs: - `host.set_ssh_enabled_timeout` - `pool.set_ssh_enabled_timeout` These APIs allow XAPI to configure timeout for SSH service. `host.enable_ssh` now also supports enabling the SSH service with a ssh_enabled_timeout Signed-off-by: Lunfan Zhang <[email protected]>
1 parent 778fb57 commit b3a3000

File tree

4 files changed

+126
-14
lines changed

4 files changed

+126
-14
lines changed

ocaml/idl/datamodel_errors.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,6 +2040,9 @@ let _ =
20402040
error Api_errors.disable_ssh_partially_failed ["hosts"]
20412041
~doc:"Some of hosts failed to disable SSH access." () ;
20422042

2043+
error Api_errors.set_ssh_timeout_partially_failed ["hosts"]
2044+
~doc:"Some hosts failed to set SSH timeout." () ;
2045+
20432046
error Api_errors.set_console_timeout_partially_failed ["hosts"]
20442047
~doc:"Some hosts failed to set console timeout." () ;
20452048

ocaml/xapi-consts/api_errors.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,6 +1420,9 @@ let enable_ssh_partially_failed = add_error "ENABLE_SSH_PARTIALLY_FAILED"
14201420

14211421
let disable_ssh_partially_failed = add_error "DISABLE_SSH_PARTIALLY_FAILED"
14221422

1423+
let set_ssh_timeout_partially_failed =
1424+
add_error "SET_SSH_TIMEOUT_PARTIALLY_FAILED"
1425+
14231426
let set_console_timeout_partially_failed =
14241427
add_error "SET_CONSOLE_TIMEOUT_PARTIALLY_FAILED"
14251428

ocaml/xapi/xapi_host.ml

Lines changed: 112 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3114,27 +3114,126 @@ let emergency_clear_mandatory_guidance ~__context =
31143114
) ;
31153115
Db.Host.set_pending_guidances ~__context ~self ~value:[]
31163116

3117+
let get_disable_ssh_task_name ~__context ~self =
3118+
let host_uuid = Db.Host.get_uuid ~__context ~self in
3119+
Printf.sprintf "disable_ssh_for_host_%s" host_uuid
3120+
3121+
let remove_disable_ssh_job ~__context ~self =
3122+
let task_name = get_disable_ssh_task_name ~__context ~self in
3123+
Xapi_stdext_threads_scheduler.Scheduler.remove_from_queue task_name
3124+
3125+
let schedule_disable_ssh_job ~__context ~self ~timeout =
3126+
let host_uuid = Db.Host.get_uuid ~__context ~self in
3127+
let task_name = get_disable_ssh_task_name ~__context ~self in
3128+
let expiry_time =
3129+
match
3130+
Ptime.add_span (Ptime_clock.now ())
3131+
(Ptime.Span.of_int_s (Int64.to_int timeout))
3132+
with
3133+
| None ->
3134+
error "Invalid SSH timeout: %Ld" timeout ;
3135+
raise
3136+
(Api_errors.Server_error
3137+
( Api_errors.invalid_value
3138+
, ["ssh_enabled_timeout"; Int64.to_string timeout]
3139+
)
3140+
)
3141+
| Some t ->
3142+
Ptime.to_float_s t |> Date.of_unix_time
3143+
in
3144+
3145+
debug "Scheduling SSH disable job for host %s with timeout %Ld seconds"
3146+
host_uuid timeout ;
3147+
3148+
(* Remove any existing job first *)
3149+
remove_disable_ssh_job ~__context ~self ;
3150+
3151+
Xapi_stdext_threads_scheduler.Scheduler.add_to_queue task_name
3152+
Xapi_stdext_threads_scheduler.Scheduler.OneShot (Int64.to_float timeout)
3153+
(fun () ->
3154+
try
3155+
Xapi_systemctl.disable ~wait_until_success:false "sshd" ;
3156+
Xapi_systemctl.stop ~wait_until_success:false "sshd" ;
3157+
Db.Host.set_ssh_enabled ~__context ~self ~value:false ;
3158+
debug "Successfully disabled SSH for host %s" host_uuid
3159+
with e ->
3160+
error "Failed to disable SSH for host %s: %s" host_uuid
3161+
(Printexc.to_string e)
3162+
) ;
3163+
3164+
Db.Host.set_ssh_expiry ~__context ~self ~value:expiry_time
3165+
31173166
let enable_ssh ~__context ~self =
31183167
try
3168+
debug "Enabling SSH for host %s" (Db.Host.get_uuid ~__context ~self) ;
3169+
31193170
Xapi_systemctl.enable ~wait_until_success:false "sshd" ;
3120-
Xapi_systemctl.start ~wait_until_success:false "sshd"
3121-
with _ ->
3122-
raise
3123-
(Api_errors.Server_error
3124-
(Api_errors.enable_ssh_failed, [Ref.string_of self])
3125-
)
3171+
Xapi_systemctl.start ~wait_until_success:false "sshd" ;
3172+
3173+
let timeout = Db.Host.get_ssh_enabled_timeout ~__context ~self in
3174+
( match timeout with
3175+
| 0L ->
3176+
remove_disable_ssh_job ~__context ~self
3177+
| t ->
3178+
schedule_disable_ssh_job ~__context ~self ~timeout:t
3179+
) ;
3180+
3181+
Db.Host.set_ssh_enabled ~__context ~self ~value:true
3182+
with e ->
3183+
error "Failed to enable SSH on host %s: %s" (Ref.string_of self)
3184+
(Printexc.to_string e) ;
3185+
Helpers.internal_error "Failed to enable SSH: %s" (Printexc.to_string e)
31263186

31273187
let disable_ssh ~__context ~self =
31283188
try
3189+
debug "Disabling SSH for host %s" (Db.Host.get_uuid ~__context ~self) ;
3190+
3191+
remove_disable_ssh_job ~__context ~self ;
3192+
31293193
Xapi_systemctl.disable ~wait_until_success:false "sshd" ;
3130-
Xapi_systemctl.stop ~wait_until_success:false "sshd"
3131-
with _ ->
3132-
raise
3133-
(Api_errors.Server_error
3134-
(Api_errors.disable_ssh_failed, [Ref.string_of self])
3135-
)
3194+
Xapi_systemctl.stop ~wait_until_success:false "sshd" ;
3195+
Db.Host.set_ssh_enabled ~__context ~self ~value:false ;
3196+
3197+
let expiry_time =
3198+
Ptime_clock.now () |> Ptime.to_float_s |> Date.of_unix_time
3199+
in
3200+
Db.Host.set_ssh_expiry ~__context ~self ~value:expiry_time
3201+
with e ->
3202+
error "Failed to disable SSH on host %s: %s" (Ref.string_of self)
3203+
(Printexc.to_string e) ;
3204+
Helpers.internal_error "Failed to disable SSH: %s" (Printexc.to_string e)
31363205

3137-
let set_ssh_enabled_timeout ~__context ~self:_ ~value:_ = ()
3206+
let set_ssh_enabled_timeout ~__context ~self ~value =
3207+
let validate_timeout value =
3208+
(* the max timeout is two days: 172800L = 2*24*60*60 *)
3209+
if value < 0L || value > 172800L then
3210+
raise
3211+
(Api_errors.Server_error
3212+
( Api_errors.invalid_value
3213+
, [
3214+
"ssh_enabled_timeout"
3215+
; Int64.to_string value
3216+
; "must be between 0 and 2*24*60*60 seconds"
3217+
]
3218+
)
3219+
)
3220+
in
3221+
validate_timeout value ;
3222+
debug "Setting SSH timeout for host %s to %Ld seconds"
3223+
(Db.Host.get_uuid ~__context ~self)
3224+
value ;
3225+
Db.Host.set_ssh_enabled_timeout ~__context ~self ~value ;
3226+
match Db.Host.get_ssh_enabled ~__context ~self with
3227+
| false ->
3228+
()
3229+
| true -> (
3230+
match value with
3231+
| 0L ->
3232+
remove_disable_ssh_job ~__context ~self ;
3233+
Db.Host.set_ssh_expiry ~__context ~self ~value:Date.epoch
3234+
| t ->
3235+
schedule_disable_ssh_job ~__context ~self ~timeout:t
3236+
)
31383237

31393238
let set_console_idle_timeout ~__context ~self ~value =
31403239
let validate_timeout = function

ocaml/xapi/xapi_pool.ml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4004,6 +4004,13 @@ module Ssh = struct
40044004
operate ~__context ~action:Client.Host.disable_ssh
40054005
~error:Api_errors.disable_ssh_partially_failed
40064006

4007+
let set_enabled_timeout ~__context ~self:_ ~value =
4008+
operate ~__context
4009+
~action:(fun ~rpc ~session_id ~self ->
4010+
Client.Host.set_ssh_enabled_timeout ~rpc ~session_id ~self ~value
4011+
)
4012+
~error:Api_errors.set_ssh_timeout_partially_failed
4013+
40074014
let set_console_timeout ~__context ~self:_ ~value =
40084015
operate ~__context
40094016
~action:(fun ~rpc ~session_id ~self ->
@@ -4016,6 +4023,6 @@ let enable_ssh = Ssh.enable
40164023

40174024
let disable_ssh = Ssh.disable
40184025

4019-
let set_ssh_enabled_timeout ~__context ~self:_ ~value:_ = ()
4026+
let set_ssh_enabled_timeout = Ssh.set_enabled_timeout
40204027

40214028
let set_console_idle_timeout = Ssh.set_console_timeout

0 commit comments

Comments
 (0)