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."); print("Server is offline.");
} }
// --- REBOOT ---
// To reboot the server, uncomment the following lines: // To reboot the server, uncomment the following lines:
// print("\nAttempting to reboot the server..."); // print("\nAttempting to reboot the server...");
// try { // try {
@ -29,6 +30,26 @@ try {
// } catch(e) { // } catch(e) {
// print(`Error during reboot: ${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) { } catch (e) {
print(`An error occurred: ${e}`); print(`An error occurred: ${e}`);

View File

@ -1,5 +1,4 @@
use crate::hetzner_api::{HetznerClient, WrappedServer}; use crate::hetzner_api::{HetznerClient, WrappedServer};
use crate::ping::ping_server;
use std::net::IpAddr; use std::net::IpAddr;
use std::sync::mpsc::{Receiver, Sender}; use std::sync::mpsc::{Receiver, Sender};
use tokio::runtime::Builder; use tokio::runtime::Builder;
@ -10,7 +9,9 @@ pub enum Request {
GetServerStatus(HetznerClient, i64), GetServerStatus(HetznerClient, i64),
GetServer(HetznerClient, i64), GetServer(HetznerClient, i64),
RebootServer(HetznerClient, i64), RebootServer(HetznerClient, i64),
PingServer(IpAddr), ResetServer(HetznerClient, i64),
EnableRescueMode(HetznerClient, i64),
DisableRescueMode(HetznerClient, i64),
} }
pub enum Response { pub enum Response {
@ -18,7 +19,9 @@ pub enum Response {
GetServerStatus(Result<String, String>), GetServerStatus(Result<String, String>),
GetServer(Result<WrappedServer, String>), GetServer(Result<WrappedServer, String>),
RebootServer(Result<(), String>), RebootServer(Result<(), String>),
PingServer(Result<bool, String>), ResetServer(Result<(), String>),
EnableRescueMode(Result<String, String>),
DisableRescueMode(Result<(), String>),
} }
pub fn run_worker( 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()); let result = rt.block_on(client.reboot_server(server_id)).map_err(|e| e.to_string());
Response::RebootServer(result) Response::RebootServer(result)
} }
Request::PingServer(ip) => { Request::ResetServer(client, server_id) => {
let result = ping_server(ip).map_err(|e| e.to_string()); let result = rt.block_on(client.reset_server(server_id)).map_err(|e| e.to_string());
Response::PingServer(result) 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"); 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::apis::{configuration::Configuration, servers_api::{self, ListServersParams, ResetServerParams, EnableRescueModeForServerParams, DisableRescueModeForServerParams}};
use hcloud::models::Server; use hcloud::models::{Server, EnableRescueModeForServerRequest};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct HetznerClient { pub struct HetznerClient {
@ -88,4 +88,31 @@ impl HetznerClient {
servers_api::soft_reboot_server(&self.configuration, params).await?; servers_api::soft_reboot_server(&self.configuration, params).await?;
Ok(()) 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 get_server_rx = reply_rx.clone();
let reboot_server_tx = command_tx.clone(); let reboot_server_tx = command_tx.clone();
let reboot_server_rx = reply_rx.clone(); let reboot_server_rx = reply_rx.clone();
let ping_server_tx = command_tx.clone(); let reset_server_tx = command_tx.clone();
let ping_server_rx = reply_rx.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 engine
.register_fn( .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_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_indexer_get(|list: &mut Vec<WrappedServer>, index: i64| list[index as usize].clone())
.register_fn( .register_fn(
@ -158,35 +183,6 @@ pub fn register_hetzner_api(
Ok(table.to_string()) 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( .register_fn(
"show_details", "show_details",
|server: &mut WrappedServer| -> Result<String, Box<EvalAltResult>> { |server: &mut WrappedServer| -> Result<String, Box<EvalAltResult>> {
@ -238,4 +234,46 @@ pub fn register_hetzner_api(
Ok(table.to_string()) 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()),
}
},
);
} }