mirror of
https://mirror.suhoan.cn/https://github.com/EasyTier/EasyTier.git
synced 2025-12-16 14:47:25 +08:00
feat(gui): GUI add support to connect to config server (#1596)
This commit is contained in:
@@ -1154,6 +1154,7 @@ async fn run_main(cli: Cli) -> anyhow::Result<()> {
|
||||
cli.machine_id.clone(),
|
||||
cli.network_options.hostname.clone(),
|
||||
manager.clone(),
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.inspect(|_| {
|
||||
|
||||
@@ -28,6 +28,7 @@ use crate::{
|
||||
proxy::TcpProxyRpcService, stats::StatsRpcService, vpn_portal::VpnPortalRpcService,
|
||||
},
|
||||
tunnel::{tcp::TcpTunnelListener, TunnelListener},
|
||||
web_client::DefaultHooks,
|
||||
};
|
||||
|
||||
pub struct ApiRpcServer<T: TunnelListener + 'static> {
|
||||
@@ -142,7 +143,10 @@ fn register_api_rpc_service(
|
||||
);
|
||||
|
||||
registry.register(
|
||||
WebClientServiceServer::new(InstanceManageRpcService::new(instance_manager.clone())),
|
||||
WebClientServiceServer::new(InstanceManageRpcService::new(
|
||||
instance_manager.clone(),
|
||||
Arc::new(DefaultHooks),
|
||||
)),
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,16 +7,18 @@ use crate::{
|
||||
api::{config::GetConfigRequest, manage::*},
|
||||
rpc_types::{self, controller::BaseController},
|
||||
},
|
||||
web_client::WebClientHooks,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InstanceManageRpcService {
|
||||
manager: Arc<NetworkInstanceManager>,
|
||||
hooks: Arc<dyn WebClientHooks>,
|
||||
}
|
||||
|
||||
impl InstanceManageRpcService {
|
||||
pub fn new(manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
Self { manager }
|
||||
pub fn new(manager: Arc<NetworkInstanceManager>, hooks: Arc<dyn WebClientHooks>) -> Self {
|
||||
Self { manager, hooks }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +53,14 @@ impl WebClientService for InstanceManageRpcService {
|
||||
};
|
||||
|
||||
let mut control = if let Some(control) = self.manager.get_instance_config_control(&id) {
|
||||
if !req.overwrite {
|
||||
let error_msg = self
|
||||
.manager
|
||||
.get_network_info(&id)
|
||||
.await
|
||||
.and_then(|i| i.error_msg)
|
||||
.unwrap_or_default();
|
||||
|
||||
if !req.overwrite && error_msg.is_empty() {
|
||||
return Ok(resp);
|
||||
}
|
||||
if control.is_read_only() {
|
||||
@@ -96,8 +105,17 @@ impl WebClientService for InstanceManageRpcService {
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = self.hooks.pre_run_network_instance(&cfg).await {
|
||||
return Err(anyhow::anyhow!("pre-run hook failed: {}", e).into());
|
||||
}
|
||||
|
||||
self.manager.run_network_instance(cfg, true, control)?;
|
||||
println!("instance {} started", id);
|
||||
|
||||
if let Err(e) = self.hooks.post_run_network_instance(&id).await {
|
||||
tracing::warn!("post-run hook failed: {}", e);
|
||||
}
|
||||
|
||||
Ok(resp)
|
||||
}
|
||||
|
||||
@@ -173,6 +191,9 @@ impl WebClientService for InstanceManageRpcService {
|
||||
req: DeleteNetworkInstanceRequest,
|
||||
) -> Result<DeleteNetworkInstanceResponse, rpc_types::error::Error> {
|
||||
let inst_ids: HashSet<uuid::Uuid> = req.inst_ids.into_iter().map(Into::into).collect();
|
||||
|
||||
let hook_ids: Vec<uuid::Uuid> = inst_ids.iter().cloned().collect();
|
||||
|
||||
let inst_ids = self
|
||||
.manager
|
||||
.iter()
|
||||
@@ -190,6 +211,11 @@ impl WebClientService for InstanceManageRpcService {
|
||||
.collect::<Vec<_>>();
|
||||
let remain_inst_ids = self.manager.delete_network_instance(inst_ids)?;
|
||||
println!("instance {:?} retained", remain_inst_ids);
|
||||
|
||||
if let Err(e) = self.hooks.post_remove_network_instances(&hook_ids).await {
|
||||
tracing::warn!("post-remove hook failed: {}", e);
|
||||
}
|
||||
|
||||
for config_file in config_files {
|
||||
if let Err(e) = std::fs::remove_file(&config_file) {
|
||||
tracing::warn!(
|
||||
|
||||
@@ -110,11 +110,12 @@ where
|
||||
// collect networks that are disabled
|
||||
let disabled_inst_ids = self
|
||||
.get_storage()
|
||||
.list_network_configs(identify, ListNetworkProps::DisabledOnly)
|
||||
.list_network_configs(identify, ListNetworkProps::All)
|
||||
.await
|
||||
.map_err(RemoteClientError::PersistentError)?
|
||||
.iter()
|
||||
.map(|x| Into::<crate::proto::common::Uuid>::into(x.get_network_inst_id().to_string()))
|
||||
.filter(|id| !ret.inst_ids.contains(id))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(ListNetworkInstanceIdsJsonResp {
|
||||
|
||||
@@ -2,21 +2,28 @@ use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
instance_manager::NetworkInstanceManager,
|
||||
rpc_service::instance_manage::InstanceManageRpcService,
|
||||
rpc_service::instance_manage::InstanceManageRpcService, web_client::WebClientHooks,
|
||||
};
|
||||
|
||||
pub struct Controller {
|
||||
token: String,
|
||||
hostname: String,
|
||||
manager: Arc<NetworkInstanceManager>,
|
||||
hooks: Arc<dyn WebClientHooks>,
|
||||
}
|
||||
|
||||
impl Controller {
|
||||
pub fn new(token: String, hostname: String, manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
pub fn new(
|
||||
token: String,
|
||||
hostname: String,
|
||||
manager: Arc<NetworkInstanceManager>,
|
||||
hooks: Arc<dyn WebClientHooks>,
|
||||
) -> Self {
|
||||
Controller {
|
||||
token,
|
||||
hostname,
|
||||
manager,
|
||||
hooks,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +40,7 @@ impl Controller {
|
||||
}
|
||||
|
||||
pub fn get_rpc_service(&self) -> InstanceManageRpcService {
|
||||
InstanceManageRpcService::new(self.manager.clone())
|
||||
InstanceManageRpcService::new(self.manager.clone(), self.hooks.clone())
|
||||
}
|
||||
|
||||
pub(super) fn notify_manager_stopping(&self) {
|
||||
|
||||
@@ -11,15 +11,40 @@ use crate::{
|
||||
tunnel::{IpVersion, TunnelConnector},
|
||||
};
|
||||
use anyhow::{Context as _, Result};
|
||||
use async_trait::async_trait;
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[async_trait]
|
||||
pub trait WebClientHooks: Send + Sync {
|
||||
async fn pre_run_network_instance(&self, _cfg: &TomlConfigLoader) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn post_run_network_instance(&self, _id: &Uuid) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn post_remove_network_instances(&self, _ids: &[Uuid]) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DefaultHooks;
|
||||
|
||||
#[async_trait]
|
||||
impl WebClientHooks for DefaultHooks {}
|
||||
|
||||
pub mod controller;
|
||||
pub mod session;
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
pub struct WebClient {
|
||||
controller: Arc<controller::Controller>,
|
||||
tasks: ScopedTask<()>,
|
||||
manager_guard: DaemonGuard,
|
||||
connected: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl WebClient {
|
||||
@@ -28,28 +53,35 @@ impl WebClient {
|
||||
token: S,
|
||||
hostname: H,
|
||||
manager: Arc<NetworkInstanceManager>,
|
||||
hooks: Option<Arc<dyn WebClientHooks>>,
|
||||
) -> Self {
|
||||
let manager_guard = manager.register_daemon();
|
||||
let hooks = hooks.unwrap_or_else(|| Arc::new(DefaultHooks));
|
||||
let controller = Arc::new(controller::Controller::new(
|
||||
token.to_string(),
|
||||
hostname.to_string(),
|
||||
manager,
|
||||
hooks,
|
||||
));
|
||||
let connected = Arc::new(AtomicBool::new(false));
|
||||
|
||||
let controller_clone = controller.clone();
|
||||
let connected_clone = connected.clone();
|
||||
let tasks = ScopedTask::from(tokio::spawn(async move {
|
||||
Self::routine(controller_clone, Box::new(connector)).await;
|
||||
Self::routine(controller_clone, connected_clone, Box::new(connector)).await;
|
||||
}));
|
||||
|
||||
WebClient {
|
||||
controller,
|
||||
tasks,
|
||||
manager_guard,
|
||||
connected,
|
||||
}
|
||||
}
|
||||
|
||||
async fn routine(
|
||||
controller: Arc<controller::Controller>,
|
||||
connected: Arc<AtomicBool>,
|
||||
mut connector: Box<dyn TunnelConnector>,
|
||||
) {
|
||||
loop {
|
||||
@@ -65,12 +97,18 @@ impl WebClient {
|
||||
}
|
||||
};
|
||||
|
||||
connected.store(true, Ordering::Release);
|
||||
println!("Successfully connected to {:?}", conn.info());
|
||||
|
||||
let mut session = session::Session::new(conn, controller.clone());
|
||||
session.wait().await;
|
||||
connected.store(false, Ordering::Release);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_connected(&self) -> bool {
|
||||
self.connected.load(Ordering::Acquire)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run_web_client(
|
||||
@@ -78,6 +116,7 @@ pub async fn run_web_client(
|
||||
machine_id: Option<String>,
|
||||
hostname: Option<String>,
|
||||
manager: Arc<NetworkInstanceManager>,
|
||||
hooks: Option<Arc<dyn WebClientHooks>>,
|
||||
) -> Result<WebClient> {
|
||||
set_default_machine_id(machine_id);
|
||||
let config_server_url = match Url::parse(config_server_url_s) {
|
||||
@@ -87,7 +126,7 @@ pub async fn run_web_client(
|
||||
config_server_url_s
|
||||
)
|
||||
.parse()
|
||||
.unwrap(),
|
||||
.with_context(|| "failed to parse config server URL")?,
|
||||
};
|
||||
|
||||
let mut c_url = config_server_url.clone();
|
||||
@@ -122,6 +161,7 @@ pub async fn run_web_client(
|
||||
token.to_string(),
|
||||
hostname,
|
||||
manager.clone(),
|
||||
hooks,
|
||||
))
|
||||
}
|
||||
|
||||
@@ -139,6 +179,7 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
manager.clone(),
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user