feat(bootstrap): accept extra_addresses on network interfaces
This commit is contained in:
@@ -213,7 +213,7 @@ Uniform package content source, family-resolved. `source: ''` defaults to `dvd`
|
||||
| `dns.search` | list | `[]` | Search domains (must be a YAML list) |
|
||||
| `interfaces` | list | `[]` | Multi-NIC config (overrides flat fields above) |
|
||||
|
||||
When `interfaces` is empty, the flat fields (`bridge`, `ip`, `prefix`, `gateway`, `vlan`) are auto-wrapped into a single-entry list. When `interfaces` is set, it takes precedence. Each entry supports: `name`, `bridge` (required), `vlan`, `ip`, `prefix`, `gateway`.
|
||||
When `interfaces` is empty, the flat fields (`bridge`, `ip`, `prefix`, `gateway`, `vlan`) are auto-wrapped into a single-entry list. When `interfaces` is set, it takes precedence. Each entry supports: `name`, `bridge` (required), `vlan`, `ip`, `prefix`, `gateway`, and `extra_addresses`: further IPv4 CIDRs (`192.0.2.10/24`) on the same NIC beside `ip`, written by every network backend. Proxmox `ipconfigN` carries one address per NIC, so on Proxmox the extras arrive with the installed network config, not cloud-init.
|
||||
|
||||
#### `system.users`
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ interface-name=en*;eth*;
|
||||
{% set search_list = configuration_dns_search %}
|
||||
{% if iface.ip | default('') | string | length %}
|
||||
address1={{ iface.ip }}/{{ iface.prefix }}{{ (',' ~ iface.gateway) if (iface.gateway | default('') | string | length) else '' }}
|
||||
{% for address in iface.extra_addresses | default([]) %}
|
||||
address{{ loop.index + 1 }}={{ address }}
|
||||
{% endfor %}
|
||||
method=manual
|
||||
{% else %}
|
||||
method=auto
|
||||
|
||||
@@ -16,6 +16,11 @@ iface {{ ifname }} inet static
|
||||
{% if loop.index0 == 0 and configuration_dns_search %}
|
||||
dns-search {{ configuration_dns_search | join(' ') }}
|
||||
{% endif %}
|
||||
{# One stanza per extra address: classic ifupdown takes one address per stanza, ifupdown2 merges them. #}
|
||||
{% for address in iface.extra_addresses | default([]) %}
|
||||
iface {{ ifname }} inet static
|
||||
address {{ address }}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
iface {{ ifname }} inet dhcp
|
||||
{% endif %}
|
||||
|
||||
@@ -9,6 +9,9 @@ network:
|
||||
{% if iface.ip | default('') | string | length %}
|
||||
addresses:
|
||||
- {{ iface.ip }}/{{ iface.prefix }}
|
||||
{% for address in iface.extra_addresses | default([]) %}
|
||||
- {{ address }}
|
||||
{% endfor %}
|
||||
{% if iface.gateway | default('') | string | length %}
|
||||
routes:
|
||||
- to: default
|
||||
|
||||
@@ -11,6 +11,9 @@ Type=ether
|
||||
[Network]
|
||||
{% if iface.ip | default('') | string | length %}
|
||||
Address={{ iface.ip }}/{{ iface.prefix }}
|
||||
{% for address in iface.extra_addresses | default([]) %}
|
||||
Address={{ address }}
|
||||
{% endfor %}
|
||||
{% if iface.gateway | default('') | string | length %}
|
||||
Gateway={{ iface.gateway }}
|
||||
{% endif %}
|
||||
|
||||
@@ -467,6 +467,21 @@
|
||||
loop_control:
|
||||
label: "{{ item | to_json }}"
|
||||
|
||||
# A string here would iterate into one address per character in every network renderer.
|
||||
- name: Validate network interfaces extra_addresses
|
||||
when: item.extra_addresses is defined
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- item.extra_addresses is not string
|
||||
- item.extra_addresses is iterable
|
||||
- item.ip | default('') | string | length > 0
|
||||
- item.extra_addresses | reject('match', '^(\\d{1,3}\\.){3}\\d{1,3}/\\d{1,2}$') | list | length == 0
|
||||
fail_msg: "system.network.interfaces[].extra_addresses must be a list of IPv4 CIDRs (192.0.2.10/24) on an entry that also sets 'ip'."
|
||||
quiet: true
|
||||
loop: "{{ system_cfg.network.interfaces | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item | to_json }}"
|
||||
|
||||
- name: Validate hostname format
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
|
||||
@@ -12,6 +12,9 @@ network:
|
||||
{% if has_static %}
|
||||
addresses:
|
||||
- "{{ iface.ip }}/{{ iface.prefix }}"
|
||||
{% for address in iface.extra_addresses | default([]) %}
|
||||
- "{{ address }}"
|
||||
{% endfor %}
|
||||
{% if iface.gateway | default('') | string | length %}
|
||||
routes:
|
||||
- to: default
|
||||
|
||||
Reference in New Issue
Block a user