public inbox for pdm-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Dominik Csapak <d.csapak@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [pdm-devel] [RFC PATCH datacenter-manager 1/3] server: pve api: add new bulkstart api call
Date: Wed, 29 Jan 2025 11:51:40 +0100	[thread overview]
Message-ID: <20250129105142.1291843-2-d.csapak@proxmox.com> (raw)
In-Reply-To: <20250129105142.1291843-1-d.csapak@proxmox.com>

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@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



_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel


  reply	other threads:[~2025-01-29 10:51 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-29 10:51 [pdm-devel] [RFC PATCH datacenter-manager 0/3] implement bulk start Dominik Csapak
2025-01-29 10:51 ` Dominik Csapak [this message]
2025-01-29 10:51 ` [pdm-devel] [RFC PATCH datacenter-manager 2/3] pdm-client: add bulk_start method Dominik Csapak
2025-01-29 10:51 ` [pdm-devel] [RFC PATCH datacenter-manager 3/3] ui: pve tree: add bulk start action Dominik Csapak
2025-01-29 18:48 ` [pdm-devel] [RFC PATCH datacenter-manager 0/3] implement bulk start Thomas Lamprecht
2025-01-30  8:14   ` Dominik Csapak
2025-01-30 16:15     ` Thomas Lamprecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250129105142.1291843-2-d.csapak@proxmox.com \
    --to=d.csapak@proxmox.com \
    --cc=pdm-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal