From 005c49353a6a71954e6a975a43989ded1786022a Mon Sep 17 00:00:00 2001 From: Ahmed Abdelhalim Date: Fri, 3 Jul 2026 21:32:24 +0200 Subject: Refactor pve and add pve-network role to configure the pve network --- configure.yml | 1 + host_vars/pve.local.yml | Bin 737 -> 822 bytes host_vars/pve.local.yml.example | 8 +++-- molecule/proxmox/converge.yml | 1 + roles/pve-network/defaults/main.yml | 2 ++ roles/pve-network/handlers/main.yml | 16 +++++++++ roles/pve-network/meta/argument_specs.yml | 32 ++++++++++++++++++ roles/pve-network/meta/main.yml | 13 ++++++++ roles/pve-network/tasks/main.yml | 36 +++++++++++++++++++++ .../pve-network/templates/ethernet.nmconnection.j2 | 16 +++++++++ roles/pve-network/templates/vmbr0.nmconnection.j2 | 29 +++++++++++++++++ roles/pve/defaults/main.yml | 2 ++ roles/pve/meta/argument_specs.yml | 8 +++++ roles/pve/tasks/main.yml | 20 +++++------- 14 files changed, 170 insertions(+), 14 deletions(-) create mode 100644 roles/pve-network/defaults/main.yml create mode 100644 roles/pve-network/handlers/main.yml create mode 100644 roles/pve-network/meta/argument_specs.yml create mode 100644 roles/pve-network/meta/main.yml create mode 100644 roles/pve-network/tasks/main.yml create mode 100644 roles/pve-network/templates/ethernet.nmconnection.j2 create mode 100644 roles/pve-network/templates/vmbr0.nmconnection.j2 diff --git a/configure.yml b/configure.yml index db599780..466103c0 100644 --- a/configure.yml +++ b/configure.yml @@ -103,6 +103,7 @@ - pve.local roles: - role: "pve" + - role: "pve-network" - role: "locales" - role: "timezone" - role: "bash" diff --git a/host_vars/pve.local.yml b/host_vars/pve.local.yml index ce9097fc..a0465c97 100644 Binary files a/host_vars/pve.local.yml and b/host_vars/pve.local.yml differ diff --git a/host_vars/pve.local.yml.example b/host_vars/pve.local.yml.example index def72e3b..f804ba67 100644 --- a/host_vars/pve.local.yml.example +++ b/host_vars/pve.local.yml.example @@ -9,10 +9,14 @@ network_ipv4_address: "10.0.0.253" network_ipv4_gateway: "10.0.0.254" network_ipv4_dns: "10.0.0.254" -restic_version: "0.19.0" +pve_network_interface: "enp0s25" pve_admin_user: "admin" pve_admin_password: "changeme" +pve_lvm_device: "/dev/sda4" +pve_lvm_vg_name: "pve" + +restic_version: "0.19.0" -ethtool_wol_interface: "eth0" +ethtool_wol_interface: "enp0s25" ethtool_lid_ac_action: "ignore" diff --git a/molecule/proxmox/converge.yml b/molecule/proxmox/converge.yml index c383777a..46ae7f76 100644 --- a/molecule/proxmox/converge.yml +++ b/molecule/proxmox/converge.yml @@ -49,6 +49,7 @@ ansible_facts: "{{ ansible_facts | combine({'is_chroot': false}) }}" roles: - role: "pve" + - role: "pve-network" - role: "locales" - role: "timezone" - role: "bash" diff --git a/roles/pve-network/defaults/main.yml b/roles/pve-network/defaults/main.yml new file mode 100644 index 00000000..f56c943e --- /dev/null +++ b/roles/pve-network/defaults/main.yml @@ -0,0 +1,2 @@ +--- +pve_network_interface: "eth0" diff --git a/roles/pve-network/handlers/main.yml b/roles/pve-network/handlers/main.yml new file mode 100644 index 00000000..7a4ce4c0 --- /dev/null +++ b/roles/pve-network/handlers/main.yml @@ -0,0 +1,16 @@ +--- +- name: "Restart NetworkManager" + become: true + ansible.builtin.systemd_service: + name: "NetworkManager" + state: "restarted" + async: 10 + poll: 0 + +- name: "Restart pveproxy" + become: true + ansible.builtin.systemd_service: + name: "pveproxy" + state: "restarted" + tags: + - "molecule-notest" diff --git a/roles/pve-network/meta/argument_specs.yml b/roles/pve-network/meta/argument_specs.yml new file mode 100644 index 00000000..6f93a13b --- /dev/null +++ b/roles/pve-network/meta/argument_specs.yml @@ -0,0 +1,32 @@ +--- +argument_specs: + main: + options: + pve_network_interface: + type: "str" + description: "Physical ethernet interface to add as bridge port" + default: "enp0s25" + network_ipv4_address: + type: "str" + description: "Static IPv4 address for vmbr0" + required: true + network_ipv4_prefix: + type: "int" + description: "IPv4 prefix length" + default: 24 + network_ipv4_gateway: + type: "str" + description: "IPv4 default gateway" + required: true + network_ipv4_dns: + type: "str" + description: "IPv4 DNS server" + network_ipv6_address: + type: "str" + description: "Static IPv6 address for vmbr0 (optional)" + network_ipv6_gateway: + type: "str" + description: "IPv6 default gateway (required if network_ipv6_address is set)" + network_ipv6_dns: + type: "str" + description: "IPv6 DNS server" diff --git a/roles/pve-network/meta/main.yml b/roles/pve-network/meta/main.yml new file mode 100644 index 00000000..e7c9c044 --- /dev/null +++ b/roles/pve-network/meta/main.yml @@ -0,0 +1,13 @@ +--- +dependencies: + - role: "network" + - role: "pve" +galaxy_info: + author: "a14m" + description: "Configure vmbr0 bridge on Proxmox VE via NetworkManager" + license: "MIT" + min_ansible_version: "2.18" + platforms: + - name: "Debian" + versions: + - "bookworm" diff --git a/roles/pve-network/tasks/main.yml b/roles/pve-network/tasks/main.yml new file mode 100644 index 00000000..dcaf0638 --- /dev/null +++ b/roles/pve-network/tasks/main.yml @@ -0,0 +1,36 @@ +--- +- name: "Set management IP in /etc/hosts for PVE cert generation" + become: true + ansible.builtin.lineinfile: + path: "/etc/hosts" + regexp: "^{{ network_ipv4_address }}" + line: "{{ network_ipv4_address }} {{ ansible_facts['hostname'] }}" + state: present + notify: "Restart pveproxy" + tags: + - "molecule-notest" + +- name: "Deploy bridge master connection" + become: true + ansible.builtin.template: + src: "vmbr0.nmconnection.j2" + dest: "/etc/NetworkManager/system-connections/vmbr0.nmconnection" + owner: "root" + group: "root" + mode: "0600" + notify: "Restart NetworkManager" + +- name: "Override ethernet connection as bridge port" + become: true + ansible.builtin.template: + src: "ethernet.nmconnection.j2" + dest: "/etc/NetworkManager/system-connections/ethernet.nmconnection" + owner: "root" + group: "root" + mode: "0600" + notify: "Restart NetworkManager" + +- name: "Wait for connection to recover after bridge reconfiguration" + ansible.builtin.wait_for_connection: + delay: 5 + timeout: 30 diff --git a/roles/pve-network/templates/ethernet.nmconnection.j2 b/roles/pve-network/templates/ethernet.nmconnection.j2 new file mode 100644 index 00000000..2aaa85b0 --- /dev/null +++ b/roles/pve-network/templates/ethernet.nmconnection.j2 @@ -0,0 +1,16 @@ +[connection] +id={{ pve_network_interface }}-bridge-port +type=ethernet +interface-name={{ pve_network_interface }} +autoconnect=true +controller=vmbr0 +port-type=bridge + +[ethernet] +cloned-mac-address=permanent + +[ipv4] +method=disabled + +[ipv6] +method=disabled diff --git a/roles/pve-network/templates/vmbr0.nmconnection.j2 b/roles/pve-network/templates/vmbr0.nmconnection.j2 new file mode 100644 index 00000000..013acd6a --- /dev/null +++ b/roles/pve-network/templates/vmbr0.nmconnection.j2 @@ -0,0 +1,29 @@ +[connection] +id=vmbr0 +type=bridge +interface-name=vmbr0 +autoconnect=true + +[bridge] +stp=false + +[ipv4] +method=manual +addresses={{ network_ipv4_address }}/{{ network_ipv4_prefix | default(24) }} +gateway={{ network_ipv4_gateway }} +{% if network_ipv4_dns is defined %} +dns={{ network_ipv4_dns }} +{% endif %} + +[ipv6] +addr-gen-mode=default +{% if network_ipv6_address is defined %} +method=manual +addresses={{ network_ipv6_address }} +gateway={{ network_ipv6_gateway }} +{% if network_ipv6_dns is defined %} +dns={{ network_ipv6_dns }} +{% endif %} +{% else %} +method=disabled +{% endif %} diff --git a/roles/pve/defaults/main.yml b/roles/pve/defaults/main.yml index c9047655..c2bca151 100644 --- a/roles/pve/defaults/main.yml +++ b/roles/pve/defaults/main.yml @@ -2,3 +2,5 @@ pve_repo: "no-subscription" pve_admin_user: "admin" pve_admin_password: "changeme" +pve_lvm_device: "/dev/sda4" +pve_lvm_vg_name: "pve" diff --git a/roles/pve/meta/argument_specs.yml b/roles/pve/meta/argument_specs.yml index 195ca146..ab9f22c6 100644 --- a/roles/pve/meta/argument_specs.yml +++ b/roles/pve/meta/argument_specs.yml @@ -17,3 +17,11 @@ argument_specs: type: "str" description: "PVE realm admin password" default: "changeme" + pve_lvm_device: + type: "str" + description: "Block device for PVE LVM volume group (e.g. /dev/sda4)" + default: "/dev/sda4" + pve_lvm_vg_name: + type: "str" + description: "LVM volume group name — PVE auto-detects VG named 'pve' as local-lvm storage" + default: "pve" diff --git a/roles/pve/tasks/main.yml b/roles/pve/tasks/main.yml index 39998cb7..7a314325 100644 --- a/roles/pve/tasks/main.yml +++ b/roles/pve/tasks/main.yml @@ -34,18 +34,6 @@ tags: - molecule-notest -- name: "Set management IP in /etc/hosts for PVE cert generation" - become: true - ansible.builtin.lineinfile: - path: "/etc/hosts" - regexp: "^{{ network_ipv4_address }}" - line: "{{ network_ipv4_address }} {{ ansible_facts['hostname'] }}" - state: present - notify: "Restart pveproxy" - tags: - # Since container doesn't have network ip address, skipping this test - - "molecule-notest" - - name: "Create PVE admin user" become: true ansible.builtin.command: @@ -73,6 +61,14 @@ tags: - "molecule-notest" +- name: "Create LVM volume group for PVE storage" + become: true + ansible.builtin.command: + cmd: "vgcreate {{ pve_lvm_vg_name }} {{ pve_lvm_device }}" + creates: "/dev/{{ pve_lvm_vg_name }}" + tags: + - "molecule-notest" + - name: "Enable and start Proxmox VE services" become: true ansible.builtin.systemd_service: -- cgit v1.2.3