Merge "CI: Refactor VXLAN overlay setup"
This commit is contained in:
commit
8829c5aa72
72
roles/multi-node-managed-addressing/tasks/main.yml
Normal file
72
roles/multi-node-managed-addressing/tasks/main.yml
Normal file
@ -0,0 +1,72 @@
|
||||
---
|
||||
# Not all variables have sensible defaults, let's ensure these are set.
|
||||
- name: Ensure mandatory variables are defined
|
||||
assert:
|
||||
that:
|
||||
- managed_interface_name is defined
|
||||
- managed_network_prefix is defined
|
||||
- managed_network_prefix_length is defined
|
||||
- managed_network_address_family is defined
|
||||
|
||||
- name: Set managed interface facts
|
||||
set_fact:
|
||||
managed_interface_address: "{{ managed_network_prefix }}{{ groups['all'].index(inventory_hostname) + 1 }}"
|
||||
|
||||
- name: Add IPv4 address for managed network
|
||||
become: true
|
||||
vars:
|
||||
managed_network_cidr: "{{ managed_interface_address }}/{{ managed_network_prefix_length }}"
|
||||
# NOTE(yoctozepto): we have to compute and explicitly set the broadcast address,
|
||||
# otherwise bifrost fails its pre-bootstrap sanity checks due to missing
|
||||
# broadcast address as ansible picks up scope ('global') as the interface's
|
||||
# broadcast address which fails checks logic
|
||||
managed_network_broadcast_address: "{{ managed_network_cidr | ipaddr('broadcast') }}"
|
||||
command: ip address add {{ managed_network_cidr }} broadcast {{ managed_network_broadcast_address }} dev {{ managed_interface_name }}
|
||||
when: managed_network_address_family == 'ipv4'
|
||||
|
||||
# NOTE(yoctozepto): IPv6 has no broadcast address, let's not create confusion by setting it
|
||||
- name: Add IPv6 address for managed network
|
||||
become: true
|
||||
command: ip address add {{ managed_interface_address }}/{{ managed_network_prefix_length }} dev {{ managed_interface_name }}
|
||||
when: managed_network_address_family == 'ipv6'
|
||||
|
||||
- name: Accept traffic on the managed network (IN)
|
||||
become: true
|
||||
iptables:
|
||||
state: present
|
||||
action: insert
|
||||
chain: INPUT
|
||||
ip_version: "{{ managed_network_address_family }}"
|
||||
in_interface: "{{ managed_interface_name }}"
|
||||
jump: ACCEPT
|
||||
|
||||
# NOTE(yoctozepto): the default policy is ACCEPT but it is nicer to get statistics
|
||||
- name: Accept traffic on the managed network (OUT)
|
||||
become: true
|
||||
iptables:
|
||||
state: present
|
||||
action: insert
|
||||
chain: OUTPUT
|
||||
ip_version: "{{ managed_network_address_family }}"
|
||||
out_interface: "{{ managed_interface_name }}"
|
||||
jump: ACCEPT
|
||||
|
||||
# NOTE(yoctozepto): IPv6 DAD may delay proper address assignment
|
||||
# this task will wait until DAD is done and addresses are no longer tentative
|
||||
# we assign addresses uniquely so DAD can only move it to preferred
|
||||
# hence we only check whether it's no longer tentative
|
||||
- name: Ensure IPv6 addresses on the managed interface are no longer tentative
|
||||
become: true
|
||||
command: ip -o address show tentative dev {{ managed_interface_name }}
|
||||
register: tentative_addresses
|
||||
until: tentative_addresses.stdout == ''
|
||||
retries: 30
|
||||
delay: 2
|
||||
when:
|
||||
- managed_network_address_family == 'ipv6'
|
||||
|
||||
- name: Ping across the managed network
|
||||
vars:
|
||||
ping_command: "{{ 'ping' if managed_network_address_family == 'ipv4' else 'ping6' }}"
|
||||
command: "{{ ping_command }} -c1 {{ hostvars[item].managed_interface_address }}"
|
||||
with_inventory_hostnames: all
|
5
roles/multi-node-vxlan-overlay/defaults/main.yml
Normal file
5
roles/multi-node-vxlan-overlay/defaults/main.yml
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
# NOTE(yoctozepto): CI VXLAN overlay must use a different port than
|
||||
# neutron-openvswitch-agent which defaults to 4789.
|
||||
# Hence using port 4790 by default.
|
||||
vxlan_dstport: 4790
|
50
roles/multi-node-vxlan-overlay/tasks/main.yml
Normal file
50
roles/multi-node-vxlan-overlay/tasks/main.yml
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
# Not all variables have sensible defaults, let's ensure these are set.
|
||||
- name: Ensure mandatory variables are defined
|
||||
assert:
|
||||
that:
|
||||
- vxlan_interface_name is defined
|
||||
- vxlan_vni is defined
|
||||
|
||||
# We have had cases where the nodepool private IP address is not assigned,
|
||||
# which causes hard to diagnose errors later on. Catch it early.
|
||||
- name: Assert that the nodepool private IPv4 address is assigned
|
||||
assert:
|
||||
that: nodepool.private_ipv4 in ansible_all_ipv4_addresses
|
||||
fail_msg: >-
|
||||
The nodepool private IP address {{ nodepool.private_ipv4 }} is not assigned
|
||||
|
||||
- name: Set VXLAN interface facts
|
||||
set_fact:
|
||||
tunnel_local_address: "{{ nodepool.private_ipv4 }}"
|
||||
|
||||
- name: Create VXLAN interface
|
||||
become: true
|
||||
command: ip link add {{ vxlan_interface_name }} type vxlan id {{ vxlan_vni }} local {{ tunnel_local_address }} dstport {{ vxlan_dstport }}
|
||||
|
||||
- name: Set VXLAN interface MTU
|
||||
become: true
|
||||
vars:
|
||||
# Find the parent interface
|
||||
parent_interface: >-
|
||||
{{ ansible_interfaces |
|
||||
map('extract', ansible_facts) |
|
||||
selectattr('ipv4.address', 'defined') |
|
||||
selectattr('ipv4.address', 'equalto', tunnel_local_address) |
|
||||
first }}
|
||||
# Allow 50 bytes overhead for VXLAN headers.
|
||||
mtu: "{{ parent_interface.mtu | int - 50 }}"
|
||||
command: ip link set {{ vxlan_interface_name }} mtu {{ mtu }}
|
||||
|
||||
# emulate BUM by multiplicating traffic to unicast targets
|
||||
- name: Add fdb entries for BUM traffic
|
||||
become: true
|
||||
vars:
|
||||
dest_ip: "{{ hostvars[item].tunnel_local_address }}"
|
||||
command: bridge fdb append 00:00:00:00:00:00 dev {{ vxlan_interface_name }} dst {{ dest_ip }}
|
||||
with_inventory_hostnames: all
|
||||
when: item != inventory_hostname
|
||||
|
||||
- name: Bring VXLAN interface up
|
||||
become: true
|
||||
command: ip link set {{ vxlan_interface_name }} up
|
119
tests/pre.yml
119
tests/pre.yml
@ -6,20 +6,22 @@
|
||||
roles:
|
||||
- bindep
|
||||
- multi-node-firewall
|
||||
- role: multi-node-vxlan-overlay
|
||||
vars:
|
||||
vxlan_interface_name: "{{ api_interface_name }}"
|
||||
vxlan_vni: 10001
|
||||
- role: multi-node-managed-addressing
|
||||
vars:
|
||||
managed_interface_name: "{{ api_interface_name }}"
|
||||
managed_network_prefix: "{{ api_network_prefix }}"
|
||||
managed_network_prefix_length: "{{ api_network_prefix_length }}"
|
||||
managed_network_address_family: "{{ address_family }}"
|
||||
tasks:
|
||||
# TODO(mnasiadka): Remove once infra merges virtualenv fixes
|
||||
- name: Upgrade virtualenv package
|
||||
command: python3 -m pip install -U virtualenv
|
||||
become: True
|
||||
|
||||
# We have had cases where the nodepool private IP address is not assigned,
|
||||
# which causes hard to diagnose errors later on. Catch it early.
|
||||
- name: Assert that the nodepool private IPv4 address is assigned
|
||||
assert:
|
||||
that: nodepool.private_ipv4 in ansible_all_ipv4_addresses
|
||||
fail_msg: >-
|
||||
The nodepool private IP address {{ nodepool.private_ipv4 }} is not assigned
|
||||
|
||||
- name: Install dbus for debian system
|
||||
apt: name=dbus
|
||||
when:
|
||||
@ -48,107 +50,6 @@
|
||||
name: "{{ inventory_hostname }}"
|
||||
become: true
|
||||
|
||||
# NOTE(yoctozepto): start VXLAN interface config
|
||||
|
||||
- name: Set VXLAN interface facts
|
||||
set_fact:
|
||||
api_interface_address: "{{ api_network_prefix }}{{ groups['all'].index(inventory_hostname) + 1 }}"
|
||||
api_interface_tunnel_vni: 10001
|
||||
tunnel_local_address: "{{ nodepool.private_ipv4 }}"
|
||||
|
||||
# NOTE(yoctozepto): CI VXLAN must use a different port than neutron-openvswitch-agent
|
||||
# which defaults to 4789 (the default is used in CI)
|
||||
# hence using port 4790
|
||||
- name: Create VXLAN interface
|
||||
become: true
|
||||
command: ip link add {{ api_interface_name }} type vxlan id {{ api_interface_tunnel_vni }} local {{ tunnel_local_address }} dstport 4790
|
||||
|
||||
- name: Set VXLAN interface MTU
|
||||
become: true
|
||||
vars:
|
||||
# Find the parent interface
|
||||
parent_interface: >-
|
||||
{{ ansible_interfaces |
|
||||
map('extract', ansible_facts) |
|
||||
selectattr('ipv4.address', 'defined') |
|
||||
selectattr('ipv4.address', 'equalto', tunnel_local_address) |
|
||||
first }}
|
||||
# Allow 50 bytes overhead for VXLAN headers.
|
||||
mtu: "{{ parent_interface.mtu | int - 50 }}"
|
||||
command: ip link set {{ api_interface_name }} mtu {{ mtu }}
|
||||
|
||||
# emulate BUM by multiplicating traffic to unicast targets
|
||||
- name: Add fdb entries for BUM traffic
|
||||
become: true
|
||||
vars:
|
||||
dest_ip: "{{ hostvars[item].tunnel_local_address }}"
|
||||
command: bridge fdb append 00:00:00:00:00:00 dev {{ api_interface_name }} dst {{ dest_ip }}
|
||||
with_inventory_hostnames: all
|
||||
when: item != inventory_hostname
|
||||
|
||||
- name: Add IPv4 address for VXLAN network
|
||||
become: true
|
||||
vars:
|
||||
api_network_cidr: "{{ api_interface_address }}/{{ api_network_prefix_length }}"
|
||||
# NOTE(yoctozepto): we have to compute and explicitly set the broadcast address,
|
||||
# otherwise bifrost fails its pre-bootstrap sanity checks due to missing
|
||||
# broadcast address as ansible picks up scope ('global') as the interface's
|
||||
# broadcast address which fails checks logic
|
||||
api_network_broadcast_address: "{{ api_network_cidr | ipaddr('broadcast') }}"
|
||||
command: ip address add {{ api_network_cidr }} broadcast {{ api_network_broadcast_address }} dev {{ api_interface_name }}
|
||||
when: address_family == 'ipv4'
|
||||
|
||||
# NOTE(yoctozepto): IPv6 has no broadcast address, let's not create confusion by setting it
|
||||
- name: Add IPv6 address for VXLAN network
|
||||
become: true
|
||||
command: ip address add {{ api_interface_address }}/{{ api_network_prefix_length }} dev {{ api_interface_name }}
|
||||
when: address_family == 'ipv6'
|
||||
|
||||
- name: Accept traffic on the VXLAN network (IN)
|
||||
become: true
|
||||
iptables:
|
||||
state: present
|
||||
action: insert
|
||||
chain: INPUT
|
||||
ip_version: "{{ address_family }}"
|
||||
in_interface: "{{ api_interface_name }}"
|
||||
jump: ACCEPT
|
||||
|
||||
# NOTE(yoctozepto): the default policy is ACCEPT but it is nicer to get statistics
|
||||
- name: Accept traffic on the VXLAN network (OUT)
|
||||
become: true
|
||||
iptables:
|
||||
state: present
|
||||
action: insert
|
||||
chain: OUTPUT
|
||||
ip_version: "{{ address_family }}"
|
||||
out_interface: "{{ api_interface_name }}"
|
||||
jump: ACCEPT
|
||||
|
||||
- name: Bring VXLAN interface up
|
||||
become: true
|
||||
command: ip link set {{ api_interface_name }} up
|
||||
|
||||
# NOTE(yoctozepto): IPv6 DAD may delay proper address assignment
|
||||
# this task will wait until DAD is done and addresses are no longer tentative
|
||||
# we assign addresses uniquely so DAD can only move it to preferred
|
||||
# hence we only check whether it's no longer tentative
|
||||
- name: Ensure IPv6 addresses on VXLAN are no longer tentative
|
||||
become: true
|
||||
command: ip -o address show tentative dev {{ api_interface_name }}
|
||||
register: tentative_addresses
|
||||
until: tentative_addresses.stdout == ''
|
||||
retries: 30
|
||||
delay: 2
|
||||
when:
|
||||
- address_family == 'ipv6'
|
||||
|
||||
- name: Ping across VXLAN
|
||||
vars:
|
||||
ping_command: "{{ 'ping' if address_family == 'ipv4' else 'ping6' }}"
|
||||
command: "{{ ping_command }} -c1 {{ hostvars[item].api_interface_address }}"
|
||||
with_inventory_hostnames: all
|
||||
|
||||
# NOTE(yoctozepto): CentOS 7 image uses myhostname plugin for NSS
|
||||
# which creates issues with IPv6-only deployment by providing
|
||||
# an IPv4 address for the current hostname (affects rabbitmq)
|
||||
|
Loading…
Reference in New Issue
Block a user