feat: 添加详细日志,修复关机API
This commit is contained in:
66
src/api.rs
66
src/api.rs
@@ -39,36 +39,63 @@ impl ProxmoxClient {
|
|||||||
|
|
||||||
pub async fn get_vm_status(&self, node: &str, vm_id: u32) -> Result<String, String> {
|
pub async fn get_vm_status(&self, node: &str, vm_id: u32) -> Result<String, String> {
|
||||||
let url = format!("{}/nodes/{}/qemu/{}/status/current", self.base_url, node, vm_id);
|
let url = format!("{}/nodes/{}/qemu/{}/status/current", self.base_url, node, vm_id);
|
||||||
|
println!("[API] 获取状态: GET {}", url);
|
||||||
|
|
||||||
let resp = self.client
|
let resp = self.client
|
||||||
.get(&url)
|
.get(&url)
|
||||||
.header("Authorization", self.auth_header())
|
.header("Authorization", self.auth_header())
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| {
|
||||||
|
let err = format!("网络错误: {}", e);
|
||||||
|
println!("[API] {}", err);
|
||||||
|
err
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
if !status.is_success() {
|
||||||
|
let body = resp.text().await.unwrap_or_default();
|
||||||
|
println!("[API] HTTP错误 {}: {}", status, body);
|
||||||
|
return Err(format!("HTTP {}: {}", status, body));
|
||||||
|
}
|
||||||
|
|
||||||
let data: ApiResponse<VmStatus> = resp.json().await.map_err(|e| e.to_string())?;
|
let data: ApiResponse<VmStatus> = resp.json().await.map_err(|e| e.to_string())?;
|
||||||
Ok(data.data.map(|d| d.status).unwrap_or_else(|| "unknown".to_string()))
|
let result = data.data.map(|d| d.status).unwrap_or_else(|| "unknown".to_string());
|
||||||
|
println!("[API] VM状态: {}", result);
|
||||||
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start_vm(&self, node: &str, vm_id: u32) -> Result<(), String> {
|
pub async fn start_vm(&self, node: &str, vm_id: u32) -> Result<(), String> {
|
||||||
let url = format!("{}/nodes/{}/qemu/{}/status/start", self.base_url, node, vm_id);
|
let url = format!("{}/nodes/{}/qemu/{}/status/start", self.base_url, node, vm_id);
|
||||||
self.client
|
let resp = self.client
|
||||||
.post(&url)
|
.post(&url)
|
||||||
.header("Authorization", self.auth_header())
|
.header("Authorization", self.auth_header())
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| format!("网络错误: {}", e))?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
if !status.is_success() {
|
||||||
|
let body = resp.text().await.unwrap_or_default();
|
||||||
|
return Err(format!("HTTP {}: {}", status, body));
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn stop_vm(&self, node: &str, vm_id: u32) -> Result<(), String> {
|
pub async fn stop_vm(&self, node: &str, vm_id: u32) -> Result<(), String> {
|
||||||
let url = format!("{}/nodes/{}/qemu/{}/status/stop", self.base_url, node, vm_id);
|
let url = format!("{}/nodes/{}/qemu/{}/status/stop", self.base_url, node, vm_id);
|
||||||
self.client
|
let resp = self.client
|
||||||
.post(&url)
|
.post(&url)
|
||||||
.header("Authorization", self.auth_header())
|
.header("Authorization", self.auth_header())
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| format!("网络错误: {}", e))?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
if !status.is_success() {
|
||||||
|
let body = resp.text().await.unwrap_or_default();
|
||||||
|
return Err(format!("HTTP {}: {}", status, body));
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,15 +105,32 @@ impl ProxmoxClient {
|
|||||||
self.start_vm(node, vm_id).await
|
self.start_vm(node, vm_id).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn shutdown_node(&self, node: &str) -> Result<(), String> {
|
pub async fn shutdown_node(&self, node: &str) -> Result<String, String> {
|
||||||
let url = format!("{}/nodes/{}/status", self.base_url, node);
|
let url = format!("{}/nodes/{}/status", self.base_url, node);
|
||||||
self.client
|
println!("[API] 关机请求: POST {}", url);
|
||||||
|
println!("[API] Headers: Authorization={}", self.auth_header());
|
||||||
|
|
||||||
|
let resp = self.client
|
||||||
.post(&url)
|
.post(&url)
|
||||||
.header("Authorization", self.auth_header())
|
.header("Authorization", self.auth_header())
|
||||||
.json(&serde_json::json!({"command": "shutdown"}))
|
.header("Content-Type", "application/json")
|
||||||
|
.json(&serde_json::json!({"action": "shutdown"}))
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| {
|
||||||
Ok(())
|
let err = format!("网络错误: {}", e);
|
||||||
|
println!("[API] {}", err);
|
||||||
|
err
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let status = resp.status();
|
||||||
|
let body = resp.text().await.unwrap_or_default();
|
||||||
|
println!("[API] 响应状态: {}", status);
|
||||||
|
println!("[API] 响应内容: {}", body);
|
||||||
|
|
||||||
|
if !status.is_success() {
|
||||||
|
return Err(format!("HTTP {}: {}", status, body));
|
||||||
|
}
|
||||||
|
Ok(body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
20
src/gui.rs
20
src/gui.rs
@@ -333,19 +333,27 @@ impl eframe::App for App {
|
|||||||
let client = client_shutdown.clone();
|
let client = client_shutdown.clone();
|
||||||
let node = node_shutdown.clone();
|
let node = node_shutdown.clone();
|
||||||
let state = state_shutdown.clone();
|
let state = state_shutdown.clone();
|
||||||
st.add_log("正在执行关机流程...");
|
st.add_log("开始执行关机流程...");
|
||||||
st.add_log("1. 停止所有虚拟机...");
|
st.add_log(&format!("节点: {}", node));
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
let _ = rt.block_on(async {
|
rt.block_on(async {
|
||||||
let client = client.lock().unwrap();
|
let client = client.lock().unwrap();
|
||||||
if let Some(c) = client.as_ref() {
|
if let Some(c) = client.as_ref() {
|
||||||
c.shutdown_node(&node).await.ok();
|
match c.shutdown_node(&node).await {
|
||||||
|
Ok(response) => {
|
||||||
|
state.write().unwrap().add_log("✓ 关机命令发送成功");
|
||||||
|
state.write().unwrap().add_log(&format!("响应: {}", response));
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
state.write().unwrap().add_log(&format!("✗ 关机失败: {}", e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.write().unwrap().add_log("✗ 未连接到服务器");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
state.write().unwrap().add_log("2. 正在关闭 Proxmox 主机...");
|
|
||||||
state.write().unwrap().add_log("关机命令已发送");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user