From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <pdm-devel-bounces@lists.proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
	by lore.proxmox.com (Postfix) with ESMTPS id 74D631FF165
	for <inbox@lore.proxmox.com>; Wed, 29 Jan 2025 11:51:49 +0100 (CET)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
	by firstgate.proxmox.com (Proxmox) with ESMTP id 810431FCB1;
	Wed, 29 Jan 2025 11:51:46 +0100 (CET)
From: Dominik Csapak <d.csapak@proxmox.com>
To: pdm-devel@lists.proxmox.com
Date: Wed, 29 Jan 2025 11:51:40 +0100
Message-Id: <20250129105142.1291843-2-d.csapak@proxmox.com>
X-Mailer: git-send-email 2.39.5
In-Reply-To: <20250129105142.1291843-1-d.csapak@proxmox.com>
References: <20250129105142.1291843-1-d.csapak@proxmox.com>
MIME-Version: 1.0
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.020 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 DMARC_MISSING             0.1 Missing DMARC policy
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to
 Validity was blocked. See
 https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more
 information.
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
Subject: [pdm-devel] [RFC PATCH datacenter-manager 1/3] server: pve api: add
 new bulkstart api call
X-BeenThere: pdm-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox Datacenter Manager development discussion
 <pdm-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pdm-devel>, 
 <mailto:pdm-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pdm-devel/>
List-Post: <mailto:pdm-devel@lists.proxmox.com>
List-Help: <mailto:pdm-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel>, 
 <mailto:pdm-devel-request@lists.proxmox.com?subject=subscribe>
Reply-To: Proxmox Datacenter Manager development discussion
 <pdm-devel@lists.proxmox.com>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: pdm-devel-bounces@lists.proxmox.com
Sender: "pdm-devel" <pdm-devel-bounces@lists.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