diff --git a/ocaml/idl/datamodel_errors.ml b/ocaml/idl/datamodel_errors.ml index fed2f830db1..33c0cd2e39e 100644 --- a/ocaml/idl/datamodel_errors.ml +++ b/ocaml/idl/datamodel_errors.ml @@ -2010,6 +2010,12 @@ let _ = error Api_errors.too_many_groups [] ~doc:"VM can only belong to one group." () ; + error Api_errors.ssh_start_failed ["host"] ~doc:"Failed to start ssh service." + () ; + + error Api_errors.ssh_stop_failed ["host"] ~doc:"Failed to stop ssh service." + () ; + message (fst Api_messages.ha_pool_overcommitted) ~doc: diff --git a/ocaml/idl/datamodel_host.ml b/ocaml/idl/datamodel_host.ml index 78b68a35722..bbb1d9e5aff 100644 --- a/ocaml/idl/datamodel_host.ml +++ b/ocaml/idl/datamodel_host.ml @@ -2338,6 +2338,28 @@ let emergency_clear_mandatory_guidance = ~doc:"Clear the pending mandatory guidance on this host" ~allowed_roles:_R_LOCAL_ROOT_ONLY () +let ssh_start = + call ~name:"ssh_start" + ~doc: + "Start and enable ssh service on the host. It will call 'systemctl start \ + sshd' only if the sshd is not running. It will also call 'systemctl \ + enable sshd' only if the sshd is not enabled. A new joined host in the \ + pool or an ejected host from the pool would keep the original status." + ~lifecycle:[] + ~params:[(Ref _host, "self", "The host")] + ~allowed_roles:_R_POOL_ADMIN () + +let ssh_stop = + call ~name:"ssh_stop" + ~doc: + "Stop and disable ssh service on the host. It will call 'systemctl stop \ + sshd' only if the sshd is running. It will also call 'systemctl disable \ + sshd' only if the sshd is enabled. A new joined host in the pool or an \ + ejected host from the pool would keep the original status." + ~lifecycle:[] + ~params:[(Ref _host, "self", "The host")] + ~allowed_roles:_R_POOL_ADMIN () + let latest_synced_updates_applied_state = Enum ( "latest_synced_updates_applied_state" @@ -2494,6 +2516,8 @@ let t = ; set_https_only ; apply_recommended_guidances ; emergency_clear_mandatory_guidance + ; ssh_start + ; ssh_stop ] ~contents: ([ diff --git a/ocaml/xapi-cli-server/cli_frontend.ml b/ocaml/xapi-cli-server/cli_frontend.ml index 3de231f3cad..4ad8f9adb59 100644 --- a/ocaml/xapi-cli-server/cli_frontend.ml +++ b/ocaml/xapi-cli-server/cli_frontend.ml @@ -1048,6 +1048,34 @@ let rec cmdtable_data : (string * cmd_spec) list = ; flags= [Host_selectors] } ) + ; ( "host-ssh-start" + , { + reqd= [] + ; optn= [] + ; help= + "Start and enable ssh service on the host. It will call 'systemctl \ + start sshd' only if the sshd is not running. It will also call \ + 'systemctl enable sshd' only if the sshd is not enabled. A new \ + joined host in the pool or an ejected host from the pool would keep \ + the original status." + ; implementation= No_fd Cli_operations.host_ssh_start + ; flags= [Host_selectors] + } + ) + ; ( "host-ssh-stop" + , { + reqd= [] + ; optn= [] + ; help= + "Stop and disable ssh service on the host. It will call 'systemctl \ + stop sshd' only if the sshd is running. It will also call \ + 'systemctl disable sshd' only if the sshd is enabled. A new joined \ + host in the pool or an ejected host from the pool would keep the \ + original status." + ; implementation= No_fd Cli_operations.host_ssh_stop + ; flags= [Host_selectors] + } + ) ; ( "host-emergency-clear-mandatory-guidance" , { reqd= [] diff --git a/ocaml/xapi-cli-server/cli_operations.ml b/ocaml/xapi-cli-server/cli_operations.ml index 1e8ba0f3b37..49192361f5f 100644 --- a/ocaml/xapi-cli-server/cli_operations.ml +++ b/ocaml/xapi-cli-server/cli_operations.ml @@ -7729,6 +7729,26 @@ let host_apply_updates _printer rpc session_id params = params ["hash"] ) +let host_ssh_start _printer rpc session_id params = + ignore + (do_host_op rpc session_id + (fun _ host -> + let host = host.getref () in + Client.Host.ssh_start ~rpc ~session_id ~self:host + ) + params [] + ) + +let host_ssh_stop _printer rpc session_id params = + ignore + (do_host_op rpc session_id + (fun _ host -> + let host = host.getref () in + Client.Host.ssh_stop ~rpc ~session_id ~self:host + ) + params [] + ) + module SDN_controller = struct let introduce printer rpc session_id params = let port = diff --git a/ocaml/xapi-consts/api_errors.ml b/ocaml/xapi-consts/api_errors.ml index 54bdd6f6660..d2518bdcb95 100644 --- a/ocaml/xapi-consts/api_errors.ml +++ b/ocaml/xapi-consts/api_errors.ml @@ -1403,3 +1403,7 @@ let telemetry_next_collection_too_late = let illegal_in_fips_mode = add_error "ILLEGAL_IN_FIPS_MODE" let too_many_groups = add_error "TOO_MANY_GROUPS" + +let ssh_start_failed = add_error "SSH_START_FAILED" + +let ssh_stop_failed = add_error "SSH_STOP_FAILED" diff --git a/ocaml/xapi/message_forwarding.ml b/ocaml/xapi/message_forwarding.ml index 63b27076a1a..4771a8af6b3 100644 --- a/ocaml/xapi/message_forwarding.ml +++ b/ocaml/xapi/message_forwarding.ml @@ -4154,6 +4154,20 @@ functor let emergency_clear_mandatory_guidance ~__context = info "Host.emergency_clear_mandatory_guidance" ; Local.Host.emergency_clear_mandatory_guidance ~__context + + let ssh_start ~__context ~self = + info "%s: host = '%s'" __FUNCTION__ (host_uuid ~__context self) ; + let local_fn = Local.Host.ssh_start ~self in + do_op_on ~local_fn ~__context ~host:self (fun session_id rpc -> + Client.Host.ssh_start ~rpc ~session_id ~self + ) + + let ssh_stop ~__context ~self = + info "%s: host = '%s'" __FUNCTION__ (host_uuid ~__context self) ; + let local_fn = Local.Host.ssh_stop ~self in + do_op_on ~local_fn ~__context ~host:self (fun session_id rpc -> + Client.Host.ssh_stop ~rpc ~session_id ~self + ) end module Host_crashdump = struct diff --git a/ocaml/xapi/xapi_host.ml b/ocaml/xapi/xapi_host.ml index cd6ae3a7d35..4394d88a3da 100644 --- a/ocaml/xapi/xapi_host.ml +++ b/ocaml/xapi/xapi_host.ml @@ -3127,3 +3127,22 @@ let emergency_clear_mandatory_guidance ~__context = info "%s: %s is cleared" __FUNCTION__ s ) ; Db.Host.set_pending_guidances ~__context ~self ~value:[] + +let ssh_start ~__context ~self = + try + Xapi_systemctl.enable ~wait_until_success:false "sshd" ; + Xapi_systemctl.start ~wait_until_success:false "sshd" + with _ -> + raise + (Api_errors.Server_error + (Api_errors.ssh_start_failed, [Ref.string_of self]) + ) + +let ssh_stop ~__context ~self = + try + Xapi_systemctl.disable ~wait_until_success:false "sshd" ; + Xapi_systemctl.stop ~wait_until_success:false "sshd" + with _ -> + raise + (Api_errors.Server_error (Api_errors.ssh_stop_failed, [Ref.string_of self]) + ) diff --git a/ocaml/xapi/xapi_host.mli b/ocaml/xapi/xapi_host.mli index f8fe73f8379..83728f39898 100644 --- a/ocaml/xapi/xapi_host.mli +++ b/ocaml/xapi/xapi_host.mli @@ -561,3 +561,7 @@ val set_https_only : __context:Context.t -> self:API.ref_host -> value:bool -> unit val emergency_clear_mandatory_guidance : __context:Context.t -> unit + +val ssh_start : __context:Context.t -> self:API.ref_host -> unit + +val ssh_stop : __context:Context.t -> self:API.ref_host -> unit