commit b3942f919de167d9f186cb2401ba1181457151cf Author: Mikhail Iliasov Date: Fri Mar 27 18:14:51 2026 +0300 Initial commit: PVE Trunks Plugin Плагин добавляет поле Trunks в редактор сетевого интерфейса QEMU VM в Proxmox VE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5f76274 --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# PVE Trunks Plugin + +Добавляет поле **Trunks** в редактор сетевого интерфейса QEMU VM в веб-интерфейсе Proxmox VE. + +Proxmox уже умеет парсить и сохранять параметр `trunks`, но в UI нет поля для него — приходится редактировать конфиг VM вручную. Этот плагин это исправляет. + +## Установка + +```bash +# Скопировать на хост Proxmox +scp -r pve-trunks-plugin/ root@:/tmp/ + +# Установить +ssh root@ "bash /tmp/pve-trunks-plugin/install.sh" +``` + +После установки перезагрузить веб-интерфейс: **Ctrl+Shift+R**. + +## Удаление + +```bash +ssh root@ "bash /tmp/pve-trunks-plugin/uninstall.sh" +``` + +## Использование + +1. VM → Hardware → Network Device → Edit +2. Поставить галку **Advanced** +3. Заполнить поле **Trunks** + +### Формат + +| Значение | Описание | +|---|---| +| `100;200;300` | Пропустить VLAN 100, 200, 300 тегированными | +| `100-200` | Диапазон VLAN от 100 до 200 | +| `100;200-300;400` | Комбинация отдельных VLAN и диапазонов | + +### Примеры + +| VLAN Tag | Trunks | Результат | +|---|---|---| +| 100 | `200;300` | Native VLAN 100 (untagged), VLAN 200 и 300 тегированные | +| *(пусто)* | `100;200;300` | Без native VLAN, все три VLAN тегированные | +| *(пусто)* | *(пусто)* | Access-порт, без тегирования | + +### Пропустить все VLAN (полный транк) + +**Вариант 1** — указать диапазон: + +``` +2-4094 +``` + +Пропустит все используемые VLAN (1 обычно native/default). + +**Вариант 2** — оставить оба поля пустыми: + +Если **VLAN Tag** и **Trunks** пустые, а бридж `vlan-aware`, VM получает весь трафик без изменений. Тегирование делает гостевая ОС: + +```bash +# Внутри VM +ip link add link eth0 name eth0.100 type vlan id 100 +ip link add link eth0 name eth0.200 type vlan id 200 +``` + +> **Важно:** На хосте Proxmox у бриджа должен быть `bridge-vlan-aware yes` в `/etc/network/interfaces` для работы VLAN/trunk. + +## Совместимость + +Проверено на Proxmox VE 9.1. Должно работать на PVE 8.x+ (любая версия с поддержкой `trunks` в парсере). + +## Как работает + +Плагин использует ExtJS `override` на `PVE.qemu.NetworkInputPanel` и добавляет поле Trunks в секцию Advanced. Оригинальные файлы Proxmox не модифицируются — загружается только новый JS-файл через index template. + +## Файлы + +- `pve-trunks-plugin.js` — ExtJS override плагин +- `install.sh` — установщик +- `uninstall.sh` — удаление diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..ced34ee --- /dev/null +++ b/install.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# PVE Trunks Plugin - Installer +# Adds "Trunks" field to VM Network Device editor in Proxmox VE UI +# +# Usage: bash install.sh + +set -e + +PLUGIN_JS="pve-trunks-plugin.js" +PVE_JS_DIR="/usr/share/pve-manager/js" +INDEX_TPL="/usr/share/pve-manager/index.html.tpl" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +SCRIPT_TAG='' + +# Check running as root +if [ "$(id -u)" -ne 0 ]; then + echo "Error: run as root" + exit 1 +fi + +# Check Proxmox +if [ ! -d "$PVE_JS_DIR" ]; then + echo "Error: Proxmox VE not found ($PVE_JS_DIR missing)" + exit 1 +fi + +# Copy plugin JS +cp "$SCRIPT_DIR/$PLUGIN_JS" "$PVE_JS_DIR/$PLUGIN_JS" +echo "Installed $PVE_JS_DIR/$PLUGIN_JS" + +# Patch index template if not already patched +if ! grep -q "pve-trunks-plugin" "$INDEX_TPL"; then + # Insert before closing + sed -i "s||${SCRIPT_TAG}\n|" "$INDEX_TPL" + echo "Patched $INDEX_TPL" +else + echo "Index template already patched, skipping" +fi + +# Restart web UI +systemctl restart pveproxy +echo "Done. Reload the Proxmox web UI (Ctrl+Shift+R)." diff --git a/pve-trunks-plugin.js b/pve-trunks-plugin.js new file mode 100644 index 0000000..2ae97bf --- /dev/null +++ b/pve-trunks-plugin.js @@ -0,0 +1,59 @@ +/* + * Proxmox VE - VLAN Trunks UI Plugin + * Adds "Trunks" field to QEMU VM Network Device editor + * + * Install: place in /usr/share/pve-manager/js/ and patch index template + * See install.sh for automated installation + */ + +Ext.define('PVE.patch.QemuNetworkTrunks', { + override: 'PVE.qemu.NetworkInputPanel', + + onGetValues: function(values) { + var me = this; + + if (values.trunks) { + me.network.trunks = values.trunks; + } else { + delete me.network.trunks; + } + delete values.trunks; + + return me.callParent([values]); + }, + + initComponent: function() { + var me = this; + + me.callParent(arguments); + + // Add trunks field after MTU in advanced column + var mtuFields = me.query('[name=mtu]'); + if (mtuFields.length > 0) { + var container = mtuFields[0].ownerCt; + if (container) { + container.add({ + xtype: 'textfield', + name: 'trunks', + fieldLabel: 'Trunks', + emptyText: 'e.g. 100;200;300-400', + allowBlank: true, + regex: /^\d+(?:-\d+)?(?:;\d+(?:-\d+)?)*$/, + regexText: 'VLAN IDs separated by semicolons, e.g. 100;200;300-400', + }); + } + } + + // Handle "No network device" checkbox in wizard + var noNetworkCb = me.down('[name=nonetwork]'); + if (noNetworkCb) { + var origHandler = noNetworkCb.listeners && noNetworkCb.listeners.change; + noNetworkCb.on('change', function(cb, value) { + var trunksField = me.down('[name=trunks]'); + if (trunksField) { + trunksField.setDisabled(value); + } + }); + } + }, +}); diff --git a/uninstall.sh b/uninstall.sh new file mode 100755 index 0000000..587ebc0 --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# PVE Trunks Plugin - Uninstaller + +set -e + +PVE_JS_DIR="/usr/share/pve-manager/js" +INDEX_TPL="/usr/share/pve-manager/index.html.tpl" +PLUGIN_JS="pve-trunks-plugin.js" + +if [ "$(id -u)" -ne 0 ]; then + echo "Error: run as root" + exit 1 +fi + +# Remove plugin JS +rm -f "$PVE_JS_DIR/$PLUGIN_JS" +echo "Removed $PVE_JS_DIR/$PLUGIN_JS" + +# Remove script tag from index template +sed -i '/pve-trunks-plugin/d' "$INDEX_TPL" +echo "Cleaned $INDEX_TPL" + +systemctl restart pveproxy +echo "Done. Reload the Proxmox web UI (Ctrl+Shift+R)."