added reset, enable and disable rescue mode functionality

This commit is contained in:
Maxime Van Hees 2025-07-15 14:46:05 +02:00
parent 92e8ac6d16
commit 9dfb10cca6
5 changed files with 138 additions and 57 deletions

View File

@ -21,6 +21,7 @@ try {
print("Server is offline.");
}
// --- REBOOT ---
// To reboot the server, uncomment the following lines:
// print("\nAttempting to reboot the server...");
// try {
@ -29,6 +30,26 @@ try {
// } catch(e) {
// print(`Error during reboot: ${e}`);
// }
// --- ENABLE RESCUE MODE ---
// To enable rescue mode, uncomment the following lines:
// print("\nEnabling rescue mode...");
// try {
// let root_password = first_server.enable_rescue_mode(client);
// print(`Rescue mode enabled. Root password: ${root_password}`);
// } catch(e) {
// print(`Error enabling rescue mode: ${e}`);
// }
// --- DISABLE RESCUE MODE ---
// To disable rescue mode, uncomment the following lines:
// print("\nDisabling rescue mode...");
// try {
// first_server.disable_rescue_mode(client);
// print("Rescue mode disabled.");
// } catch(e) {
// print(`Error disabling rescue mode: ${e}`);
// }
}
} catch (e) {
print(`An error occurred: ${e}`);

View File

@ -1,5 +1,4 @@
use crate::hetzner_api::{HetznerClient, WrappedServer};
use crate::ping::ping_server;
use std::net::IpAddr;
use std::sync::mpsc::{Receiver, Sender};
use tokio::runtime::Builder;
@ -10,7 +9,9 @@ pub enum Request {
GetServerStatus(HetznerClient, i64),
GetServer(HetznerClient, i64),
RebootServer(HetznerClient, i64),
PingServer(IpAddr),
ResetServer(HetznerClient, i64),
EnableRescueMode(HetznerClient, i64),
DisableRescueMode(HetznerClient, i64),
}
pub enum Response {
@ -18,7 +19,9 @@ pub enum Response {
GetServerStatus(Result<String, String>),
GetServer(Result<WrappedServer, String>),
RebootServer(Result<(), String>),
PingServer(Result<bool, String>),
ResetServer(Result<(), String>),
EnableRescueMode(Result<String, String>),
DisableRescueMode(Result<(), String>),
}
pub fn run_worker(
@ -49,9 +52,17 @@ pub fn run_worker(
let result = rt.block_on(client.reboot_server(server_id)).map_err(|e| e.to_string());
Response::RebootServer(result)
}
Request::PingServer(ip) => {
let result = ping_server(ip).map_err(|e| e.to_string());
Response::PingServer(result)
Request::ResetServer(client, server_id) => {
let result = rt.block_on(client.reset_server(server_id)).map_err(|e| e.to_string());
Response::ResetServer(result)
}
Request::EnableRescueMode(client, server_id) => {
let result = rt.block_on(client.enable_rescue_mode_for_server(server_id)).map_err(|e| e.to_string());
Response::EnableRescueMode(result)
}
Request::DisableRescueMode(client, server_id) => {
let result = rt.block_on(client.disable_rescue_mode_for_server(server_id)).map_err(|e| e.to_string());
Response::DisableRescueMode(result)
}
};
reply_tx.send(response).expect("Failed to send response");

View File

@ -1,5 +1,5 @@
use hcloud::apis::{configuration::Configuration, servers_api::{self, ListServersParams}};
use hcloud::models::Server;
use hcloud::apis::{configuration::Configuration, servers_api::{self, ListServersParams, ResetServerParams, EnableRescueModeForServerParams, DisableRescueModeForServerParams}};
use hcloud::models::{Server, EnableRescueModeForServerRequest};
#[derive(Debug, Clone)]
pub struct HetznerClient {
@ -88,4 +88,31 @@ impl HetznerClient {
servers_api::soft_reboot_server(&self.configuration, params).await?;
Ok(())
}
}
pub async fn reset_server(&self, server_id: i64) -> Result<(), Box<dyn std::error::Error>> {
let params = ResetServerParams {
id: server_id,
};
servers_api::reset_server(&self.configuration, params).await?;
Ok(())
}
pub async fn enable_rescue_mode_for_server(&self, server_id: i64) -> Result<String, Box<dyn std::error::Error>> {
let params = EnableRescueModeForServerParams {
id: server_id,
enable_rescue_mode_for_server_request: Some(EnableRescueModeForServerRequest {
ssh_keys: None,
r#type: Some(hcloud::models::enable_rescue_mode_for_server_request::Type::Linux64),
}),
};
let response = servers_api::enable_rescue_mode_for_server(&self.configuration, params).await?;
Ok(response.root_password.expect("Unable to fetch root_password from enabling rescue mode for server response"))
}
pub async fn disable_rescue_mode_for_server(&self, server_id: i64) -> Result<(), Box<dyn std::error::Error>> {
let params = DisableRescueModeForServerParams {
id: server_id,
};
servers_api::disable_rescue_mode_for_server(&self.configuration, params).await?;
Ok(())
}
}

View File

@ -1,16 +0,0 @@
use std::net::IpAddr;
use std::time::Duration;
pub fn ping_server(ip: IpAddr) -> Result<bool, Box<dyn std::error::Error>> {
match ping::new(ip)
.socket_type(ping::SocketType::DGRAM)
.timeout(Duration::from_secs(2))
.send()
{
Ok(_) => Ok(true),
Err(e) => {
eprintln!("Ping error: {}", e);
Ok(false)
}
}
}

View File

@ -27,8 +27,12 @@ pub fn register_hetzner_api(
let get_server_rx = reply_rx.clone();
let reboot_server_tx = command_tx.clone();
let reboot_server_rx = reply_rx.clone();
let ping_server_tx = command_tx.clone();
let ping_server_rx = reply_rx.clone();
let reset_server_tx = command_tx.clone();
let reset_server_rx = reply_rx.clone();
let enable_rescue_mode_tx = command_tx.clone();
let enable_rescue_mode_rx = reply_rx.clone();
let disable_rescue_mode_tx = command_tx.clone();
let disable_rescue_mode_rx = reply_rx.clone();
engine
.register_fn(
@ -133,7 +137,28 @@ pub fn register_hetzner_api(
}
},
)
.register_iterator::<Vec<WrappedServer>>()
.register_fn(
"reset",
move |server: &mut WrappedServer,
client: HetznerClient|
-> Result<(), Box<EvalAltResult>> {
reset_server_tx
.send(Request::ResetServer(client, server.0.id))
.map_err(|e| e.to_string())?;
let response = reset_server_rx
.lock()
.unwrap()
.recv()
.map_err(|e| e.to_string())?;
match response {
Response::ResetServer(result) => result.map_err(|e| e.into()),
_ => Err("Unexpected response".into()),
}
},
)
.register_iterator::<Vec<WrappedServer>>()
.register_fn("len", |list: &mut Vec<WrappedServer>| list.len() as i64)
.register_indexer_get(|list: &mut Vec<WrappedServer>, index: i64| list[index as usize].clone())
.register_fn(
@ -158,35 +183,6 @@ pub fn register_hetzner_api(
Ok(table.to_string())
},
)
.register_fn(
"ping",
move |server: &mut WrappedServer| -> Result<bool, Box<EvalAltResult>> {
ping_server_tx
.send(Request::PingServer(
server
.0
.public_net
.ipv4
.clone()
.unwrap()
.ip
.parse()
.unwrap(),
))
.map_err(|e| e.to_string())?;
let response = ping_server_rx
.lock()
.unwrap()
.recv()
.map_err(|e| e.to_string())?;
match response {
Response::PingServer(result) => result.map_err(|e| e.into()),
_ => Err("Unexpected response".into()),
}
},
)
.register_fn(
"show_details",
|server: &mut WrappedServer| -> Result<String, Box<EvalAltResult>> {
@ -238,4 +234,46 @@ pub fn register_hetzner_api(
Ok(table.to_string())
},
);
engine.register_fn(
"enable_rescue_mode",
move |server: &mut WrappedServer,
client: HetznerClient|
-> Result<String, Box<EvalAltResult>> {
enable_rescue_mode_tx
.send(Request::EnableRescueMode(client, server.0.id))
.map_err(|e| e.to_string())?;
let response = enable_rescue_mode_rx
.lock()
.unwrap()
.recv()
.map_err(|e| e.to_string())?;
match response {
Response::EnableRescueMode(result) => result.map_err(|e| e.into()),
_ => Err("Unexpected response".into()),
}
},
)
.register_fn(
"disable_rescue_mode",
move |server: &mut WrappedServer,
client: HetznerClient|
-> Result<(), Box<EvalAltResult>> {
disable_rescue_mode_tx
.send(Request::DisableRescueMode(client, server.0.id))
.map_err(|e| e.to_string())?;
let response = disable_rescue_mode_rx
.lock()
.unwrap()
.recv()
.map_err(|e| e.to_string())?;
match response {
Response::DisableRescueMode(result) => result.map_err(|e| e.into()),
_ => Err("Unexpected response".into()),
}
},
);
}