76 lines
2 KiB
Elixir
76 lines
2 KiB
Elixir
defmodule HAHandler.DRBD.Watcher do
|
|
# TODO: add support for SSH public keys authentication.
|
|
|
|
use GenServer
|
|
|
|
require Logger
|
|
|
|
def start_link(opts) do
|
|
GenServer.start_link(__MODULE__, opts)
|
|
end
|
|
|
|
defp connect(hostname, password) do
|
|
case :inet.gethostbyname(to_charlist(hostname), :inet6) do
|
|
{:ok, {:hostent, _name, _aliases, _addrtype, _length, [addr]}} ->
|
|
SSHEx.connect(
|
|
ip: addr,
|
|
user: 'root',
|
|
password: password,
|
|
silently_accept_hosts: true
|
|
)
|
|
err ->
|
|
err
|
|
end
|
|
end
|
|
|
|
@impl true
|
|
def init(opts) do
|
|
# Configures this worker's jobs to report in the "drbd" namespace
|
|
Appsignal.Span.set_namespace(Appsignal.Tracer.root_span(), "drbd")
|
|
|
|
state = %{
|
|
backend: nil,
|
|
last_reconnect: nil,
|
|
hostname: Keyword.get(opts, :hostname),
|
|
password: Keyword.get(opts, :password),
|
|
}
|
|
|
|
# This action will be processed once the GenServer is fully
|
|
# started/operational. This process handle connection failures by itself,
|
|
# as we don't want to crash loop into supervisor logic (which is only there
|
|
# to handle unexpected failure).
|
|
send self(), :reconnect
|
|
|
|
{:ok, state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_info(:reconnect, state = %{hostname: hostname, password: password}) do
|
|
case connect(hostname, password) do
|
|
{:ok, pid} ->
|
|
{:noreply, %{state | backend: pid}}
|
|
{:error, _err} ->
|
|
# Nothing to do, as the next request will trigger the reconnect logic
|
|
# (see :execute call).
|
|
|
|
{:noreply, state}
|
|
end
|
|
end
|
|
|
|
@impl true
|
|
def handle_call({:execute, cmd}, _from, %{backend: backend} = state) do
|
|
case SSHEx.run(backend, cmd) do
|
|
{:ok, _output, _status} = reply->
|
|
{:reply, reply, state}
|
|
{:error, :closed} = reply ->
|
|
# Asynchroneously tries to reopen the connection to the backend.
|
|
send self(), :reconnect
|
|
|
|
{:reply, reply, state}
|
|
{:error, _err} = reply ->
|
|
# Do not take action on unknown error.
|
|
{:reply, reply, state}
|
|
end
|
|
end
|
|
|
|
end
|