From: Hannes Laimer <h.laimer@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve-manager 2/2] ui: sdn: ipam: allow picking the nic instead of typing its MAC
Date: Wed, 19 Aug 2026 14:44:07 +0200 [thread overview]
Message-ID: <20260819124407.856577-3-h.laimer@proxmox.com> (raw)
In-Reply-To: <20260819124407.856577-1-h.laimer@proxmox.com>
Instead of hand-copying a MAC from the guest's hardware panel, take a
guest and one of its NICs on the assignments's VNet, and fill the MAC in
from there.
Setting a MAC without a guest stays possible, so this is purely a UX
improvement. We could also restrict this, so our IPAM only manages IPs
of guests in our SDN.
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
www/manager6/sdn/IpamEdit.js | 112 ++++++++++++++++++++++++++++++++++-
1 file changed, 109 insertions(+), 3 deletions(-)
diff --git a/www/manager6/sdn/IpamEdit.js b/www/manager6/sdn/IpamEdit.js
index cdefe436..aeb21b2b 100644
--- a/www/manager6/sdn/IpamEdit.js
+++ b/www/manager6/sdn/IpamEdit.js
@@ -16,18 +16,48 @@ Ext.define('PVE.sdn.IpamEditInputPanel', {
items: [
{
- xtype: 'pmxDisplayEditField',
name: 'vmid',
- fieldLabel: 'VMID',
+ fieldLabel: gettext('Guest'),
+ allowBlank: true,
+ notFoundIsValid: true,
+ emptyText: Proxmox.Utils.NoneText,
+ cbind: {
+ xtype: (get) => (get('isCreate') ? 'vmComboSelector' : 'displayfield'),
+ },
+ listeners: {
+ change: 'onGuestChange',
+ },
+ },
+ {
+ xtype: 'combobox',
+ reference: 'netid',
+ fieldLabel: gettext('Network Device'),
+ emptyText: gettext('Select a guest first'),
+ submitValue: false,
allowBlank: false,
editable: false,
+ disabled: true,
+ queryMode: 'local',
+ valueField: 'netid',
+ displayField: 'netid',
+ listConfig: {
+ itemTpl: '{netid} <i>{mac:htmlEncode}</i>',
+ },
+ store: {
+ fields: ['netid', 'mac'],
+ data: [],
+ },
cbind: {
- hidden: '{isCreate}',
+ hidden: '{!isCreate}',
+ },
+ listeners: {
+ select: 'onDeviceSelect',
},
},
{
xtype: 'pmxDisplayEditField',
name: 'mac',
+ reference: 'mac',
fieldLabel: 'MAC',
allowBlank: false,
cbind: {
@@ -58,11 +88,87 @@ Ext.define('PVE.sdn.IpamEdit', {
return `${url}/${values.vnet}/ips`;
},
+ controller: {
+ xclass: 'Ext.app.ViewController',
+
+ onGuestChange: function (f, vmid) {
+ if (!this.getView().isCreate) {
+ return;
+ }
+ this.setGuest(vmid ? f.getSelection() : undefined);
+ },
+
+ onDeviceSelect: function (f, record) {
+ this.lookup('mac').setValue(record?.data.mac ?? '');
+ },
+
+ setGuest: function (record) {
+ let me = this;
+ let view = me.getView();
+
+ let selector = me.lookup('netid');
+ let mac = me.lookup('mac');
+
+ selector.clearValue();
+ selector.getStore().removeAll();
+ selector.setDisabled(!record);
+
+ mac.setValue('');
+ mac.setEditable(!record);
+
+ if (!record) {
+ selector.setEmptyText(gettext('Select a guest first'));
+ return;
+ }
+
+ Proxmox.Utils.API2Request({
+ url: `/nodes/${record.data.node}/${record.data.type}/${record.data.vmid}/config`,
+ method: 'GET',
+ failure: (response) => Ext.Msg.alert(gettext('Error'), response.htmlStatus),
+ success: function ({ result }) {
+ if (selector.destroyed) {
+ return;
+ }
+
+ let vnet = view.extraRequestParams?.vnet;
+ let nics = [];
+
+ for (const [key, value] of Object.entries(result.data)) {
+ if (!key.match(/^net\d+$/)) {
+ continue;
+ }
+
+ let net =
+ record.data.type === 'qemu'
+ ? PVE.Parser.parseQemuNetwork(key, value)
+ : PVE.Parser.parseLxcNetwork(value);
+
+ let mac = net?.macaddr ?? net?.hwaddr;
+ if (!mac || net.bridge !== vnet) {
+ continue;
+ }
+
+ nics.push({ netid: key, mac });
+ }
+
+ selector.getStore().setData(nics);
+ selector.setEmptyText(
+ nics.length
+ ? gettext('Select a network device')
+ : Ext.String.format(gettext('No network device on {0}'), vnet),
+ );
+ },
+ });
+ },
+ },
+
initComponent: function () {
var me = this;
me.method = me.isCreate ? 'POST' : 'PUT';
+ me.defaultFocus = me.isCreate ? 'textfield[name=mac]' : 'textfield[name=ip]';
+
let ipanel = Ext.create('PVE.sdn.IpamEditInputPanel', {
isCreate: me.isCreate,
});
--
2.47.3
prev parent reply other threads:[~2026-08-19 12:44 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-19 12:44 [PATCH manager/network 0/2] sdn: add guest/nic selectors to IPAM create window Hannes Laimer
2026-08-19 12:44 ` [PATCH pve-network 1/2] api: sdn: ipam: add optional vmid to POST endpoint Hannes Laimer
2026-08-19 12:44 ` Hannes Laimer [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=20260819124407.856577-3-h.laimer@proxmox.com \
--to=h.laimer@proxmox.com \
--cc=pve-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