68 lines
2.1 KiB
Rust
68 lines
2.1 KiB
Rust
|
use std::time::Duration;
|
||
|
use proxmox_api::nodes::node::lxc::vmid::migrate;
|
||
|
use proxmox_api::nodes::node::tasks::upid;
|
||
|
use sea_orm::{ActiveModelTrait, EntityTrait, IntoActiveModel, Set};
|
||
|
use tokio::time::sleep;
|
||
|
use crate::api::entity::nodes;
|
||
|
use crate::api::entity::nodes::P5xError;
|
||
|
use crate::api::services::Services;
|
||
|
|
||
|
pub async fn migrate_node(
|
||
|
svc: &Services<'_>,
|
||
|
node: nodes::Model,
|
||
|
to_host: &str,
|
||
|
) -> Result<nodes::Model, P5xError> {
|
||
|
// Ask the PVE API to start migrating the node
|
||
|
let params = migrate::PostParams::new(to_host.to_string());
|
||
|
let upid = svc.pve_node(&node.pve_host)
|
||
|
.map_err(P5xError::ServiceError)?
|
||
|
.lxc()
|
||
|
.vmid(node.vm_id())
|
||
|
.migrate()
|
||
|
.post(params)
|
||
|
.map_err(P5xError::PveError)?;
|
||
|
|
||
|
// Wait for the UPID to finish
|
||
|
wait_upid(svc, &node.pve_host, &upid).await?;
|
||
|
|
||
|
// Persist the node
|
||
|
let mut node = node.into_active_model();
|
||
|
node.pve_host = Set(to_host.to_string());
|
||
|
let node = node.save(svc.db).await.map_err(P5xError::DbErr)?;
|
||
|
|
||
|
nodes::Entity::find_by_id(node.id.unwrap())
|
||
|
.one(svc.db)
|
||
|
.await
|
||
|
.map_err(P5xError::DbErr)?
|
||
|
.ok_or(P5xError::BadPostcondition("Could not look up node after persisting"))
|
||
|
}
|
||
|
|
||
|
pub async fn wait_upid(svc: &Services<'_>, node: &str, upid: &str) -> Result<(), P5xError> {
|
||
|
info!("Waiting for UPID {upid} on node {node}");
|
||
|
let pve = svc.pve_node(node)
|
||
|
.map_err(P5xError::ServiceError)?;
|
||
|
|
||
|
loop {
|
||
|
let status = pve.tasks()
|
||
|
.upid(upid)
|
||
|
.status()
|
||
|
.get()
|
||
|
.map_err(P5xError::PveError)?;
|
||
|
|
||
|
if status.status == upid::status::Status::Running {
|
||
|
sleep(Duration::from_secs(1)).await;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if let Some(s) = status.exitstatus {
|
||
|
if s == "OK" {
|
||
|
info!("UPID {upid} on node {node} finished");
|
||
|
return Ok(());
|
||
|
}
|
||
|
|
||
|
error!("UPID {upid} on node {node} failed");
|
||
|
return Err(P5xError::UpidFailed(node.to_string(), upid.to_string()));
|
||
|
}
|
||
|
}
|
||
|
}
|