* [pdm-devel] [PATCH datacenter-manager v2 1/4] pdm-client: add cluster status method
2025-01-14 11:21 [pdm-devel] [PATCH datacenter-manager v2 0/4] remote migration: make target endpoint selectable Dominik Csapak
@ 2025-01-14 11:21 ` Dominik Csapak
2025-01-14 11:21 ` [pdm-devel] [PATCH datacenter-manager v2 2/4] pdm-client: add target-endpoint parameter to remote migration methods Dominik Csapak
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2025-01-14 11:21 UTC (permalink / raw)
To: pdm-devel
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
lib/pdm-client/src/lib.rs | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/lib/pdm-client/src/lib.rs b/lib/pdm-client/src/lib.rs
index 14e6fc8..4ef560e 100644
--- a/lib/pdm-client/src/lib.rs
+++ b/lib/pdm-client/src/lib.rs
@@ -52,6 +52,8 @@ pub mod types {
};
pub use pve_api_types::ListRealm;
+
+ pub use pve_api_types::ClusterNodeStatus;
}
pub struct PdmClient<T: HttpApiClient>(pub T);
@@ -347,6 +349,16 @@ impl<T: HttpApiClient> PdmClient<T> {
Ok(self.0.get(&query).await?.expect_json()?.data)
}
+ pub async fn pve_cluster_status(
+ &self,
+ remote: &str,
+ target_endpoint: Option<&str>,
+ ) -> Result<Vec<ClusterNodeStatus>, Error> {
+ let mut query = format!("/api2/extjs/pve/remotes/{remote}/cluster-status");
+ add_query_arg(&mut query, &mut '?', "target-endpoint", &target_endpoint);
+ Ok(self.0.get(&query).await?.expect_json()?.data)
+ }
+
pub async fn pve_list_qemu(
&self,
remote: &str,
--
2.39.5
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pdm-devel] [PATCH datacenter-manager v2 2/4] pdm-client: add target-endpoint parameter to remote migration methods
2025-01-14 11:21 [pdm-devel] [PATCH datacenter-manager v2 0/4] remote migration: make target endpoint selectable Dominik Csapak
2025-01-14 11:21 ` [pdm-devel] [PATCH datacenter-manager v2 1/4] pdm-client: add cluster status method Dominik Csapak
@ 2025-01-14 11:21 ` Dominik Csapak
2025-01-14 11:21 ` [pdm-devel] [PATCH datacenter-manager v2 3/4] ui: widget: add remote endpoint selector Dominik Csapak
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2025-01-14 11:21 UTC (permalink / raw)
To: pdm-devel
and set it to None for all users for now
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
changes from v1:
* fix cli code to set that parameter to None
* also fix UI code in one go so the repo state is compileable
cli/client/src/pve.rs | 4 ++--
lib/pdm-client/src/lib.rs | 8 ++++++++
ui/src/widget/migrate_window.rs | 2 ++
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/cli/client/src/pve.rs b/cli/client/src/pve.rs
index c355293..1b12403 100644
--- a/cli/client/src/pve.rs
+++ b/cli/client/src/pve.rs
@@ -618,7 +618,7 @@ async fn remote_migrate_qemu(
let client = client()?;
let upid = client
- .pve_qemu_remote_migrate(&remote, node.as_deref(), vmid, target, params)
+ .pve_qemu_remote_migrate(&remote, node.as_deref(), vmid, target, None, params)
.await?;
println!("upid: {upid}");
let status = client.pve_wait_for_task(&upid).await?;
@@ -996,7 +996,7 @@ async fn remote_migrate_lxc(
let client = client()?;
let upid = client
- .pve_lxc_remote_migrate(&remote, node.as_deref(), vmid, target, params)
+ .pve_lxc_remote_migrate(&remote, node.as_deref(), vmid, target, None, params)
.await?;
println!("upid: {upid}");
let status = client.pve_wait_for_task(&upid).await?;
diff --git a/lib/pdm-client/src/lib.rs b/lib/pdm-client/src/lib.rs
index 4ef560e..1253ded 100644
--- a/lib/pdm-client/src/lib.rs
+++ b/lib/pdm-client/src/lib.rs
@@ -488,6 +488,7 @@ impl<T: HttpApiClient> PdmClient<T> {
node: Option<&str>,
vmid: u32,
target: String,
+ target_endpoint: Option<&str>,
params: RemoteMigrateQemu,
) -> Result<RemoteUpid, Error> {
let path = format!("/api2/extjs/pve/remotes/{remote}/qemu/{vmid}/remote-migrate");
@@ -496,6 +497,9 @@ impl<T: HttpApiClient> PdmClient<T> {
if let Some(node) = node {
request["node"] = node.into();
}
+ if let Some(target_endpoint) = target_endpoint {
+ request["target-endpoint"] = target_endpoint.into();
+ }
Ok(self.0.post(&path, &request).await?.expect_json()?.data)
}
@@ -581,6 +585,7 @@ impl<T: HttpApiClient> PdmClient<T> {
node: Option<&str>,
vmid: u32,
target: String,
+ target_endpoint: Option<&str>,
params: RemoteMigrateLxc,
) -> Result<RemoteUpid, Error> {
let path = format!("/api2/extjs/pve/remotes/{remote}/lxc/{vmid}/remote-migrate");
@@ -589,6 +594,9 @@ impl<T: HttpApiClient> PdmClient<T> {
if let Some(node) = node {
request["node"] = node.into();
}
+ if let Some(target_endpoint) = target_endpoint {
+ request["target-endpoint"] = target_endpoint.into();
+ }
Ok(self.0.post(&path, &request).await?.expect_json()?.data)
}
diff --git a/ui/src/widget/migrate_window.rs b/ui/src/widget/migrate_window.rs
index c87cf9a..42b4e95 100644
--- a/ui/src/widget/migrate_window.rs
+++ b/ui/src/widget/migrate_window.rs
@@ -174,6 +174,7 @@ impl PdmMigrateWindow {
None,
guest_info.vmid,
target_remote.to_string(),
+ None,
migrate_opts,
)
.await?
@@ -218,6 +219,7 @@ impl PdmMigrateWindow {
None,
guest_info.vmid,
target_remote.to_string(),
+ None,
migrate_opts,
)
.await?
--
2.39.5
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pdm-devel] [PATCH datacenter-manager v2 3/4] ui: widget: add remote endpoint selector
2025-01-14 11:21 [pdm-devel] [PATCH datacenter-manager v2 0/4] remote migration: make target endpoint selectable Dominik Csapak
2025-01-14 11:21 ` [pdm-devel] [PATCH datacenter-manager v2 1/4] pdm-client: add cluster status method Dominik Csapak
2025-01-14 11:21 ` [pdm-devel] [PATCH datacenter-manager v2 2/4] pdm-client: add target-endpoint parameter to remote migration methods Dominik Csapak
@ 2025-01-14 11:21 ` Dominik Csapak
2025-01-14 11:21 ` [pdm-devel] [PATCH datacenter-manager v2 4/4] ui: migrate: make target endpoint selectable for remote migration Dominik Csapak
2025-01-14 13:25 ` [pdm-devel] applied: [PATCH datacenter-manager v2 0/4] remote migration: make target endpoint selectable Dietmar Maurer
4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2025-01-14 11:21 UTC (permalink / raw)
To: pdm-devel
this is a widget to select a specific endpoint, showing the hostname as
the value. This can be useful in situations where we wan to explicitly
select an endpoint, e.g. remote migration.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
changes from v1:
* fix typo in commit message
ui/src/widget/mod.rs | 2 +
ui/src/widget/remote_endpoint_selector.rs | 103 ++++++++++++++++++++++
2 files changed, 105 insertions(+)
create mode 100644 ui/src/widget/remote_endpoint_selector.rs
diff --git a/ui/src/widget/mod.rs b/ui/src/widget/mod.rs
index b885d1b..ee9e799 100644
--- a/ui/src/widget/mod.rs
+++ b/ui/src/widget/mod.rs
@@ -21,3 +21,5 @@ pub use search_box::SearchBox;
mod remote_selector;
pub use remote_selector::RemoteSelector;
+
+mod remote_endpoint_selector;
diff --git a/ui/src/widget/remote_endpoint_selector.rs b/ui/src/widget/remote_endpoint_selector.rs
new file mode 100644
index 0000000..779d98c
--- /dev/null
+++ b/ui/src/widget/remote_endpoint_selector.rs
@@ -0,0 +1,103 @@
+use std::rc::Rc;
+
+use wasm_bindgen::UnwrapThrowExt;
+use yew::{
+ html::{IntoEventCallback, IntoPropValue},
+ AttrValue, Callback, Component, Properties,
+};
+
+use pwt::{
+ props::{FieldBuilder, WidgetBuilder},
+ widget::form::Combobox,
+};
+use pwt_macros::{builder, widget};
+
+use crate::RemoteList;
+
+#[widget(comp=PdmEndpointSelector, @input)]
+#[derive(Clone, Properties, PartialEq)]
+#[builder]
+pub struct EndpointSelector {
+ /// The default value
+ #[builder(IntoPropValue, into_prop_value)]
+ #[prop_or_default]
+ pub default: Option<AttrValue>,
+
+ /// Change callback
+ #[builder_cb(IntoEventCallback, into_event_callback, String)]
+ #[prop_or_default]
+ pub on_change: Option<Callback<String>>,
+
+ /// The remote to list Endpoints from
+ #[builder(IntoPropValue, into_prop_value)]
+ #[prop_or_default]
+ pub remote: AttrValue,
+}
+
+impl EndpointSelector {
+ pub fn new(remote: AttrValue) -> Self {
+ yew::props!(Self { remote })
+ }
+}
+
+pub struct PdmEndpointSelector {
+ endpoints: Rc<Vec<AttrValue>>,
+}
+
+impl PdmEndpointSelector {
+ fn update_endpoint_list(&mut self, ctx: &yew::Context<Self>) {
+ let (remotes, _): (RemoteList, _) = ctx
+ .link()
+ .context(ctx.link().callback(|_| ()))
+ .unwrap_throw();
+
+ let remote_id = ctx.props().remote.as_str();
+
+ for remote in remotes.iter() {
+ if remote.id != remote_id {
+ continue;
+ }
+
+ let endpoints = remote
+ .nodes
+ .iter()
+ .map(|endpoint| AttrValue::from(endpoint.hostname.clone()))
+ .collect();
+ self.endpoints = Rc::new(endpoints);
+ break;
+ }
+ }
+}
+
+impl Component for PdmEndpointSelector {
+ type Message = ();
+ type Properties = EndpointSelector;
+
+ fn create(ctx: &yew::Context<Self>) -> Self {
+ let mut this = Self {
+ endpoints: Rc::new(Vec::new()),
+ };
+
+ this.update_endpoint_list(ctx);
+ this
+ }
+
+ fn changed(&mut self, ctx: &yew::Context<Self>, old_props: &Self::Properties) -> bool {
+ if ctx.props().remote != old_props.remote {
+ log::info!("{} {}", ctx.props().remote, old_props.remote);
+ self.update_endpoint_list(ctx);
+ }
+ true
+ }
+
+ fn view(&self, ctx: &yew::Context<Self>) -> yew::Html {
+ let props = ctx.props();
+ Combobox::new()
+ .with_std_props(&props.std_props)
+ .with_input_props(&props.input_props)
+ .on_change(props.on_change.clone())
+ .default(props.default.clone())
+ .items(self.endpoints.clone())
+ .into()
+ }
+}
--
2.39.5
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pdm-devel] [PATCH datacenter-manager v2 4/4] ui: migrate: make target endpoint selectable for remote migration
2025-01-14 11:21 [pdm-devel] [PATCH datacenter-manager v2 0/4] remote migration: make target endpoint selectable Dominik Csapak
` (2 preceding siblings ...)
2025-01-14 11:21 ` [pdm-devel] [PATCH datacenter-manager v2 3/4] ui: widget: add remote endpoint selector Dominik Csapak
@ 2025-01-14 11:21 ` Dominik Csapak
2025-01-14 13:25 ` [pdm-devel] applied: [PATCH datacenter-manager v2 0/4] remote migration: make target endpoint selectable Dietmar Maurer
4 siblings, 0 replies; 6+ messages in thread
From: Dominik Csapak @ 2025-01-14 11:21 UTC (permalink / raw)
To: pdm-devel
by showing a target endpoint selector instead of a target node one when
it's a remote migration.
For the user to be able to select the target storage/network properly,
we have to query the nodename for the target and update the
storage/network selectors.
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
changes from v1:
* adapt to changes from pdm-client patch (basic rebase)
ui/src/widget/migrate_window.rs | 70 +++++++++++++++++++++++++++++++--
1 file changed, 66 insertions(+), 4 deletions(-)
diff --git a/ui/src/widget/migrate_window.rs b/ui/src/widget/migrate_window.rs
index 42b4e95..7214ff4 100644
--- a/ui/src/widget/migrate_window.rs
+++ b/ui/src/widget/migrate_window.rs
@@ -23,6 +23,7 @@ use pdm_client::{MigrateLxc, MigrateQemu, RemoteMigrateLxc, RemoteMigrateQemu};
use crate::pve::GuestInfo;
use crate::pve::GuestType;
+use super::remote_endpoint_selector::EndpointSelector;
use super::{
PveMigrateMap, PveNetworkSelector, PveNodeSelector, PveStorageSelector, RemoteSelector,
};
@@ -62,6 +63,8 @@ impl MigrateWindow {
pub enum Msg {
RemoteChange(String),
+ EndpointChange(String),
+ NodenameResult(Result<String, proxmox_client::Error>),
Result(RemoteUpid),
LoadPreconditions(Option<AttrValue>),
PreconditionResult(Result<QemuMigratePreconditions, proxmox_client::Error>),
@@ -71,9 +74,29 @@ pub struct PdmMigrateWindow {
target_remote: AttrValue,
_async_pool: AsyncPool,
preconditions: Option<QemuMigratePreconditions>,
+ target_node: Option<AttrValue>,
}
impl PdmMigrateWindow {
+ async fn get_nodename(
+ remote: AttrValue,
+ target_endpoint: AttrValue,
+ ) -> Result<String, proxmox_client::Error> {
+ let status_list = crate::pdm_client()
+ .pve_cluster_status(&remote, Some(&target_endpoint))
+ .await?;
+
+ for status in status_list {
+ if status.local.unwrap_or(false) {
+ return Ok(status.name);
+ }
+ }
+
+ Err(proxmox_client::Error::Other(
+ "could not find local nodename",
+ ))
+ }
+
async fn load_preconditions(
remote: String,
guest_info: GuestInfo,
@@ -132,6 +155,7 @@ impl PdmMigrateWindow {
let target_remote = value["remote"].as_str().unwrap_or_default();
let upid = if target_remote != remote {
+ let target_endpoint = value.get("target-endpoint").and_then(|e| e.as_str());
match guest_info.guest_type {
crate::pve::GuestType::Qemu => {
let mut migrate_opts = RemoteMigrateQemu::new()
@@ -174,7 +198,7 @@ impl PdmMigrateWindow {
None,
guest_info.vmid,
target_remote.to_string(),
- None,
+ target_endpoint,
migrate_opts,
)
.await?
@@ -219,7 +243,7 @@ impl PdmMigrateWindow {
None,
guest_info.vmid,
target_remote.to_string(),
- None,
+ target_endpoint,
migrate_opts,
)
.await?
@@ -268,10 +292,12 @@ impl PdmMigrateWindow {
source_remote: AttrValue,
guest_info: GuestInfo,
preconditions: Option<QemuMigratePreconditions>,
+ target_node: Option<AttrValue>,
) -> Html {
let same_remote = target_remote == source_remote;
if !same_remote {
- form_ctx.write().set_field_value("node", "".into());
+ let node = target_node.unwrap_or_default().to_string();
+ form_ctx.write().set_field_value("node", node.into());
}
let detail_mode = form_ctx.read().get_field_checked("detailed-mode");
let mut uses_local_disks = false;
@@ -338,13 +364,27 @@ impl PdmMigrateWindow {
tr!("Mode"),
DisplayField::new("").name("migrate-mode").key("mode"),
)
- .with_right_field(
+ .with_field_and_options(
+ pwt::widget::FieldPosition::Right,
+ false,
+ !same_remote,
tr!("Target Node"),
PveNodeSelector::new(target_remote.clone())
.name("node")
.required(same_remote)
.on_change(link.callback(Msg::LoadPreconditions))
.disabled(!same_remote),
+ )
+ .with_field_and_options(
+ pwt::widget::FieldPosition::Right,
+ false,
+ same_remote,
+ tr!("Target Endpoint"),
+ EndpointSelector::new(target_remote.clone())
+ .placeholder(tr!("Automatic"))
+ .name("target-endpoint")
+ .on_change(link.callback(Msg::EndpointChange))
+ .disabled(same_remote),
);
if !same_remote || uses_local_disks || uses_local_resources {
@@ -462,6 +502,7 @@ impl Component for PdmMigrateWindow {
target_remote: ctx.props().remote.clone(),
_async_pool: AsyncPool::new(),
preconditions: None,
+ target_node: None,
}
}
@@ -503,6 +544,25 @@ impl Component for PdmMigrateWindow {
}
true
}
+ Msg::EndpointChange(endpoint) => {
+ let remote = self.target_remote.clone();
+ self._async_pool
+ .send_future(ctx.link().clone(), async move {
+ let res = Self::get_nodename(remote, endpoint.into()).await;
+ Msg::NodenameResult(res)
+ });
+ false
+ }
+ Msg::NodenameResult(result) => match result {
+ Ok(nodename) => {
+ self.target_node = Some(nodename.into());
+ true
+ }
+ Err(err) => {
+ log::error!("could not extract nodename from endpoint: {err}");
+ false
+ }
+ },
}
}
@@ -527,6 +587,7 @@ impl Component for PdmMigrateWindow {
let source_remote = ctx.props().remote.clone();
let link = ctx.link().clone();
let preconditions = self.preconditions.clone();
+ let target_node = self.target_node.clone();
move |form| {
Self::input_panel(
&link,
@@ -535,6 +596,7 @@ impl Component for PdmMigrateWindow {
source_remote.clone(),
guest_info,
preconditions.clone(),
+ target_node.clone(),
)
}
})
--
2.39.5
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pdm-devel] applied: [PATCH datacenter-manager v2 0/4] remote migration: make target endpoint selectable
2025-01-14 11:21 [pdm-devel] [PATCH datacenter-manager v2 0/4] remote migration: make target endpoint selectable Dominik Csapak
` (3 preceding siblings ...)
2025-01-14 11:21 ` [pdm-devel] [PATCH datacenter-manager v2 4/4] ui: migrate: make target endpoint selectable for remote migration Dominik Csapak
@ 2025-01-14 13:25 ` Dietmar Maurer
4 siblings, 0 replies; 6+ messages in thread
From: Dietmar Maurer @ 2025-01-14 13:25 UTC (permalink / raw)
To: Proxmox Datacenter Manager development discussion, Dominik Csapak
applied
_______________________________________________
pdm-devel mailing list
pdm-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pdm-devel
^ permalink raw reply [flat|nested] 6+ messages in thread