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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox