[pdm-devel] [RFC PATCH datacenter-manager 1/3] server: pve api: add new bulkstart api call
Dominik Csapak
d.csapak at proxmox.com
Wed Jan 29 11:51:40 CET 2025
similar to the 'bulkstart' of pve itself, but implemented here, since we
can do it across the cluster, and are not bound to one specific node.
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
server/src/api/pve/mod.rs | 98 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 97 insertions(+), 1 deletion(-)
diff --git a/server/src/api/pve/mod.rs b/server/src/api/pve/mod.rs
index 2cefbb4..7dc7a34 100644
--- a/server/src/api/pve/mod.rs
+++ b/server/src/api/pve/mod.rs
@@ -1,10 +1,12 @@
//! Manage PVE instances.
+use std::collections::HashMap;
use std::sync::Arc;
use anyhow::{bail, format_err, Error};
use proxmox_access_control::CachedUserInfo;
+use proxmox_rest_server::WorkerTask;
use proxmox_router::{
http_bail, http_err, list_subdirs_api_method, Permission, Router, RpcEnvironment, SubdirMap,
};
@@ -17,7 +19,7 @@ use pdm_api_types::remotes::{NodeUrl, Remote, RemoteType, REMOTE_ID_SCHEMA};
use pdm_api_types::resource::PveResource;
use pdm_api_types::{
Authid, RemoteUpid, HOST_OPTIONAL_PORT_FORMAT, PRIV_RESOURCE_AUDIT, PRIV_RESOURCE_DELETE,
- PRIV_SYS_MODIFY,
+ PRIV_RESOURCE_MANAGE, PRIV_SYS_MODIFY, UPID, VMID_SCHEMA,
};
use pve_api_types::client::PveClient;
@@ -57,6 +59,7 @@ const MAIN_ROUTER: Router = Router::new()
#[sortable]
const REMOTE_SUBDIRS: SubdirMap = &sorted!([
+ ("bulk-start", &Router::new().post(&API_METHOD_BULK_START)),
("lxc", &lxc::ROUTER),
("nodes", &NODES_ROUTER),
("qemu", &qemu::ROUTER),
@@ -427,3 +430,96 @@ pub async fn list_realm_remote_pve(
Ok(list)
}
+
+#[api(
+ input: {
+ properties: {
+ remote: { schema: REMOTE_ID_SCHEMA },
+ "vmid-list": {
+ type: Array,
+ description: "A list of vmids to start",
+ items: {
+ schema: VMID_SCHEMA,
+ },
+ },
+ },
+ },
+ returns: { type: UPID },
+ access: {
+ permission: &Permission::Privilege(&["resource", "{remote}"], PRIV_RESOURCE_MANAGE, false),
+ },
+)]
+/// Start a remote qemu vm.
+pub async fn bulk_start(
+ remote: String,
+ vmid_list: Vec<u32>,
+ rpcenv: &mut dyn RpcEnvironment,
+) -> Result<UPID, Error> {
+ let (remotes, _) = pdm_config::remotes::config()?;
+
+ let pve = connect_to_remote(&remotes, &remote)?;
+
+ let auth_id = rpcenv.get_auth_id().unwrap();
+
+ let upid = WorkerTask::spawn("qmbulkstart", None, auth_id, false, |_| async move {
+ let resources = pve.cluster_resources(Some(ClusterResourceKind::Vm)).await?;
+
+ let mut map = HashMap::new();
+
+ for res in resources {
+ match res.ty {
+ ClusterResourceType::Qemu => {
+ map.insert(res.vmid.unwrap(), (res.node, res.ty));
+ }
+ ClusterResourceType::Lxc => {
+ map.insert(res.vmid.unwrap(), (res.node, res.ty));
+ }
+ _ => {}
+ }
+ }
+
+ for vmid in vmid_list {
+ // TODO:
+ // * get boot order/delay?
+ // * wait for start task to finish?
+ // * how to handle errors?
+ // * check privileges for each vmid
+
+ let (node, vmtype) = if let Some((node, vmtype)) = map.get(&vmid) {
+ match node {
+ Some(node) => (node, vmtype),
+ None => bail!("vm without node"),
+ }
+ } else {
+ bail!("no such vmid");
+ };
+
+ log::info!("Start VM {vmid} on {node}");
+ let res = match vmtype {
+ ClusterResourceType::Qemu => {
+ pve.start_qemu_async(node, vmid, Default::default()).await
+ }
+ ClusterResourceType::Lxc => {
+ pve.start_lxc_async(node, vmid, Default::default()).await
+ }
+ _ => bail!("invalid vm type"),
+ };
+
+ match res {
+ Ok(upid) => {
+ log::info!("Started Task: {upid}");
+
+ // track the remote upids
+ let _ = new_remote_upid(remote.clone(), upid);
+ }
+ Err(err) => {
+ log::error!("Starting failed: {err}");
+ }
+ }
+ }
+
+ Ok(())
+ })?;
+
+ upid.parse()
+}
--
2.39.5
More information about the pdm-devel
mailing list