From: Christoph Heiss <c.heiss@proxmox.com>
To: pdm-devel@lists.proxmox.com
Subject: [PATCH datacenter-manager 5/5] ui: auto-installer: add vlan and bond config as advanced options
Date: Mon, 2 Nov 2026 13:49:37 +0100 [thread overview]
Message-ID: <20261102124939.1023342-6-c.heiss@proxmox.com> (raw)
In-Reply-To: <20261102124939.1023342-1-c.heiss@proxmox.com>
This adds a new advanced section in the "Network" tab of the prepared
answer add/edit dialog.
With this, the user can the VLAN tag and/or bonding for newly installed
system.
Bond member selection uses udev filters, to provide a way to dynamically
select network interfaces for target systems.
Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
ui/Cargo.toml | 1 +
.../prepared_answer_add_wizard.rs | 6 +
.../prepared_answer_edit_window.rs | 5 +
.../auto_installer/prepared_answer_form.rs | 134 +++++++++++++++++-
4 files changed, 140 insertions(+), 6 deletions(-)
diff --git a/ui/Cargo.toml b/ui/Cargo.toml
index d3053802..0b00914c 100644
--- a/ui/Cargo.toml
+++ b/ui/Cargo.toml
@@ -40,6 +40,7 @@ proxmox-client = "1"
proxmox-human-byte = "1"
proxmox-installer-types = "0.3"
proxmox-login = "1"
+proxmox-network-api = "1"
proxmox-network-types = "1.1"
proxmox-schema = "5"
proxmox-subscription = { version = "1.0.1", features = ["api-types"], default-features = false }
diff --git a/ui/src/remotes/auto_installer/prepared_answer_add_wizard.rs b/ui/src/remotes/auto_installer/prepared_answer_add_wizard.rs
index 03d78be8..63f10dcf 100644
--- a/ui/src/remotes/auto_installer/prepared_answer_add_wizard.rs
+++ b/ui/src/remotes/auto_installer/prepared_answer_add_wizard.rs
@@ -72,6 +72,12 @@ impl AddAnswerWizardProperties {
dns: None,
netdev_filter: BTreeMap::new(),
netif_name_pinning_enabled: true,
+ bond_enabled: false,
+ bond_members_filter: BTreeMap::new(),
+ bond_members_filter_match: None,
+ bond_mode: None,
+ bond_hash_policy: None,
+ vlan_id: None,
// disk options
filesystem: answer::FilesystemOptions::Ext4(answer::LvmOptions::default()),
disk_mode: DiskSelectionMode::default(),
diff --git a/ui/src/remotes/auto_installer/prepared_answer_edit_window.rs b/ui/src/remotes/auto_installer/prepared_answer_edit_window.rs
index 33a9ce00..5b4108ba 100644
--- a/ui/src/remotes/auto_installer/prepared_answer_edit_window.rs
+++ b/ui/src/remotes/auto_installer/prepared_answer_edit_window.rs
@@ -157,6 +157,11 @@ async fn submit(
"post-hook-cert-fp",
"disk-filter",
"netdev-filter",
+ "bond-members-filter",
+ "bond-mode",
+ "bond-hash-policy",
+ "bond-primary-interface",
+ "vlan-id",
"target-filter",
"subscription-key",
"template-counters",
diff --git a/ui/src/remotes/auto_installer/prepared_answer_form.rs b/ui/src/remotes/auto_installer/prepared_answer_form.rs
index 0b01baf1..e24d23aa 100644
--- a/ui/src/remotes/auto_installer/prepared_answer_form.rs
+++ b/ui/src/remotes/auto_installer/prepared_answer_form.rs
@@ -18,11 +18,12 @@ use proxmox_installer_types::{
answer::{
BTRFS_COMPRESS_OPTIONS, BtrfsCompressOption, BtrfsOptions, DiskSetup,
FILESYSTEM_TYPE_OPTIONS, Filesystem, FilesystemOptions, FilesystemType, FilterMatch,
- KeyboardLayout, LvmOptions, ROOT_PASSWORD_SCHEMA, RebootMode, SUBSCRIPTION_KEY_SCHEMA,
- ZFS_CHECKSUM_OPTIONS, ZFS_COMPRESS_OPTIONS, ZfsChecksumOption, ZfsCompressOption,
- ZfsOptions, email_validate,
+ KeyboardLayout, LvmOptions, NetworkBondOptions, ROOT_PASSWORD_SCHEMA, RebootMode,
+ SUBSCRIPTION_KEY_SCHEMA, ZFS_CHECKSUM_OPTIONS, ZFS_COMPRESS_OPTIONS, ZfsChecksumOption,
+ ZfsCompressOption, ZfsOptions, email_validate,
},
};
+use proxmox_network_api::{BondXmitHashPolicy, LinuxBondMode};
use proxmox_network_types::fqdn::Fqdn;
use proxmox_schema::api_types::{CIDR_SCHEMA, IP_SCHEMA};
use proxmox_yew_comp::{KeyValueList, SchemaValidation, utils::copy_text_to_clipboard};
@@ -355,7 +356,20 @@ pub fn render_network_options_form(
.and_then(|v| v.as_bool())
.unwrap_or(true);
- InputPanel::new()
+ let bond_enabled = form_ctx
+ .read()
+ .get_field_value("bond-enabled")
+ .and_then(|v| v.as_bool())
+ .unwrap_or(!config.bond_members_filter.is_empty());
+
+ let bond_mode = form_ctx
+ .read()
+ .get_field_value("bond-mode")
+ .and_then(|v| v.as_str().and_then(|s| s.parse().ok()))
+ .or(config.bond_mode)
+ .unwrap_or(LinuxBondMode::ActiveBackup);
+
+ let panel = InputPanel::new()
.class(Flex::Fill)
.class(Overflow::Auto)
.padding(4)
@@ -451,7 +465,99 @@ pub fn render_network_options_form(
.disabled(use_dhcp_network)
.required(!use_dhcp_network),
)
- .into()
+ // Bonding and VLAN tagging are supported for both the DHCP and the static
+ // configuration, so they are independent of the 'Use DHCP' setting.
+ .with_advanced_spacer()
+ .with_advanced_field(
+ tr!("VLAN ID"),
+ Number::<u16>::new()
+ .name("vlan-id")
+ .min(2)
+ .max(4094)
+ .step(1)
+ .submit_empty(false)
+ .placeholder(tr!("Optional, 2-4094. Disabled when empty."))
+ .value(config.vlan_id.map(|v| v.to_string())),
+ )
+ .with_advanced_field(
+ tr!("Enable Bonding"),
+ Checkbox::new()
+ .name("bond-enabled")
+ .tip(tr!(
+ "Bond the member interfaces for the management network."
+ ))
+ .default(config.bond_enabled),
+ )
+ .with_field(
+ tr!("Bond Members udev Filter Mode"),
+ filter_match_combobox()
+ .name("bond-members-filter-match")
+ .value(config.bond_members_filter_match.map(|v| v.to_string()))
+ .disabled(!bond_enabled),
+ )
+ .with_advanced_field(
+ tr!("Bond Members udev Filters"),
+ KeyValueList::new()
+ .name("bond-members-filter")
+ .class(FlexFit)
+ .value(
+ config
+ .bond_members_filter
+ .iter()
+ .map(|(k, v)| (k.clone(), Value::String(v.clone())))
+ .collect(),
+ )
+ .key_label(tr!("Property Name"))
+ .value_label(tr!("Value To Match"))
+ .key_placeholder(tr!("udev Property Name, e.g. ID_MODEL"))
+ .value_renderer(render_udev_filter_value.into())
+ .submit_validate(kv_list_to_udev_filter_map_validate)
+ .submit_empty(false)
+ .disabled(!bond_enabled)
+ .required(bond_enabled),
+ )
+ .with_advanced_field(
+ tr!("Bond Mode"),
+ Combobox::new()
+ .name("bond-mode")
+ .items(Rc::new(
+ NetworkBondOptions::MODES
+ .iter()
+ .map(|mode| mode.to_string().into())
+ .collect(),
+ ))
+ .default(LinuxBondMode::ActiveBackup.to_string())
+ .value(config.bond_mode.map(|v| v.to_string()))
+ .disabled(!bond_enabled)
+ .required(bond_enabled)
+ .show_filter(false),
+ )
+ .with_advanced_field(
+ tr!("Bond Hash Policy"),
+ Combobox::new()
+ .name("bond-hash-policy")
+ .items(Rc::new(
+ NetworkBondOptions::HASH_POLICIES
+ .iter()
+ .map(|policy| policy.to_string().into())
+ .collect(),
+ ))
+ .default(BondXmitHashPolicy::Layer2.to_string())
+ .value(config.bond_hash_policy.map(|v| v.to_string()))
+ .disabled(
+ !bond_enabled
+ || !matches!(
+ bond_mode,
+ LinuxBondMode::Ieee802_3ad | LinuxBondMode::BalanceXor
+ ),
+ )
+ .show_filter(false),
+ );
+
+ // the bond and VLAN options live in the advanced section, report that to the dialog so it can
+ // offer the toggle
+ form_ctx.set_has_advanced(panel.has_advanced());
+ panel.into()
}
pub fn render_disk_setup_form(
@@ -523,7 +629,7 @@ pub fn render_disk_setup_form(
.with_spacer()
.with_field(
tr!("Disk udev Filter Mode"),
- Combobox::new()
+ filter_match_combobox()
.name("disk-filter-match")
.items(Rc::new(
[FilterMatch::Any, FilterMatch::All]
@@ -1147,6 +1253,22 @@ fn render_template_counter_value(
.into()
}
+fn filter_match_combobox() -> Combobox {
+ Combobox::new()
+ .items(Rc::new(
+ [FilterMatch::Any, FilterMatch::All]
+ .iter()
+ .map(|opt| opt.to_string().into())
+ .collect(),
+ ))
+ .render_value(|v: &AttrValue| match v.parse::<FilterMatch>() {
+ Ok(FilterMatch::Any) => tr!("Match Any Filter").into(),
+ Ok(FilterMatch::All) => tr!("Match All Filters").into(),
+ _ => v.into(),
+ })
+ .default(FilterMatch::default().to_string())
+}
+
/// Validate against a schema, but accept any value carrying a MiniJinja placeholder, as the
/// backend substitutes those before parsing the field.
fn templated_schema_validate(schema: &'static proxmox_schema::Schema) -> ValidateFn<String> {
--
2.55.0
prev parent reply other threads:[~2026-11-02 12:50 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-02 12:49 [PATCH datacenter-manager 0/5] auto-install: add support for VLAN and bond configurations Christoph Heiss
2026-11-02 12:49 ` [PATCH datacenter-manager 1/5] config: auto-install: add new options for configuring vlan and bond Christoph Heiss
2026-11-02 12:49 ` [PATCH datacenter-manager 2/5] api-types: auto-installer: " Christoph Heiss
2026-11-02 12:49 ` [PATCH datacenter-manager 3/5] api: auto-installer: wire up new vlan and bond network options Christoph Heiss
2026-11-02 12:49 ` [PATCH datacenter-manager 4/5] ui: auto-installer: use .to_string() instead of manual serde variant Christoph Heiss
2026-11-02 12:49 ` Christoph Heiss [this message]
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=20261102124939.1023342-6-c.heiss@proxmox.com \
--to=c.heiss@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.