diff --git a/playbooks/multinode/pre.yaml b/playbooks/multinode/pre.yaml index 0988a4a68..71a65c98b 100644 --- a/playbooks/multinode/pre.yaml +++ b/playbooks/multinode/pre.yaml @@ -16,3 +16,10 @@ - name: Set up multi-node firewall include_role: name: multi-node-firewall + +- name: Configure multi-node networking switch and peer nodes + hosts: + - switch + - peers + roles: + - multi-node-bridge diff --git a/roles/multi-node-bridge/README.rst b/roles/multi-node-bridge/README.rst new file mode 100644 index 000000000..5d3bbeb6f --- /dev/null +++ b/roles/multi-node-bridge/README.rst @@ -0,0 +1,66 @@ +Configures a VXLAN virtual network overlay through an openvswitch network +bridge between a 'switch' node and 'peer' nodes. + +This allows members of the bridge to communicate with each other through the +virtual network. + +By default, this role will: + +- Install and start ``openvswitch`` +- Set up a ``br-infra`` bridge on all nodes +- Set up the connectivity between the switch and the peer with a virtual port +- Set up an ip address on the bridge interface: + +:: + + 172.24.4.1/23 # switch node + 172.41.4.2/23 # first peer + 172.41.4.3/23 # second peer + ... + +**Role requirements** + +This role requires and expects two groups to be set up in the Ansible host +inventory in order to work: + +- ``switch`` (the node acting as the switch) +- ``peers`` (nodes connected to the virtual switch ports) + +**Role variables** + +.. zuul:rolevar:: bridge_vni_offset + :default: 1000000 + + VXLAN Network Identifier offset (openvswitch key). + +.. zuul:rolevar:: bridge_mtu + :default: 1450 + + Bridge interface MTU. + +.. zuul:rolevar:: bridge_name + :default: br-infra + + Name of the bridge interface. + +.. zuul:rolevar:: bridge_configure_address + :default: true + + Whether or not to configure an IP address on the bridge interface. + +.. zuul:rolevar:: bridge_address_prefix + :default: 172.24.4 + + The IP address range prefix. + +.. zuul:rolevar:: bridge_address_offset + :default: 1 + + The IP address offset, used with ``bridge_address_prefix`` to provide the + full IP address. The initial offset defines the IP address of the switch + node in the virtual network. + +.. zuul:rolevar:: bridge_address_subnet + :default: 23 + + The IP address range CIDR/subnet. diff --git a/roles/multi-node-bridge/defaults/main.yaml b/roles/multi-node-bridge/defaults/main.yaml new file mode 100644 index 000000000..9458b50eb --- /dev/null +++ b/roles/multi-node-bridge/defaults/main.yaml @@ -0,0 +1,8 @@ +bridge_vni_offset: 1000000 +bridge_mtu: 1450 +bridge_name: br-infra + +bridge_configure_address: true +bridge_address_prefix: 172.24.4 +bridge_address_offset: 1 +bridge_address_subnet: 23 diff --git a/roles/multi-node-bridge/tasks/common.yaml b/roles/multi-node-bridge/tasks/common.yaml new file mode 100644 index 000000000..b539304f1 --- /dev/null +++ b/roles/multi-node-bridge/tasks/common.yaml @@ -0,0 +1,39 @@ +- name: Include OS-specific variables + include_vars: "{{ item }}" + with_first_found: + - "{{ ansible_distribution }}.yaml" + - "{{ ansible_os_family }}.yaml" + - "default.yaml" + +# RHEL and CentOS requires repositories provided by RDO in order to install +# openvswitch, set them up. +- name: Set-up RDO repositories + become: yes + package: + name: "{{ rdo_repository }}" + state: installed + when: + - rdo_repository is defined + - ansible_os_family == "RedHat" + register: rdo_repos + +- name: Install openvswitch + become: yes + package: + name: "{{ ovs_package }}" + state: installed + +- name: Ensure openvswitch is started + become: yes + service: + name: "{{ ovs_service }}" + state: started + enabled: yes + +# If we've installed RDO repositories for openvswitch earlier, remove them +- name: Ensure RDO repositories are removed + become: yes + package: + name: "rdo-release" + state: absent + when: rdo_repos | changed diff --git a/roles/multi-node-bridge/tasks/main.yaml b/roles/multi-node-bridge/tasks/main.yaml new file mode 100644 index 000000000..046d35e61 --- /dev/null +++ b/roles/multi-node-bridge/tasks/main.yaml @@ -0,0 +1,9 @@ +- include: common.yaml + +- include: switch.yaml + when: inventory_hostname in groups['switch'] + static: no + +- include: peer.yaml + when: inventory_hostname in groups['peers'] + static: no diff --git a/roles/multi-node-bridge/tasks/peer.yaml b/roles/multi-node-bridge/tasks/peer.yaml new file mode 100644 index 000000000..99ff0c4e8 --- /dev/null +++ b/roles/multi-node-bridge/tasks/peer.yaml @@ -0,0 +1,59 @@ +--- +# This dynamically configures a unique offset for this peer +- name: Set offset + set_fact: + offset: "{{ bridge_address_offset | int + 1 + groups['peers'].index(inventory_hostname) }}" + +- name: Add additional vni offset + set_fact: + vni: "{{ offset | int + bridge_vni_offset | int }}" + +# To make things more readable in the following tasks +- name: Alias the primary node private IP + set_fact: + switch_private_ip: "{{ hostvars[groups['switch'][0]]['nodepool']['private_ipv4'] }}" + +- name: Add port to bridge on switch node + become: yes + command: >- + ovs-vsctl --may-exist add-port {{ bridge_name }} + {{ bridge_name }}_{{ nodepool['private_ipv4'] }} + -- set interface {{ bridge_name }}_{{ nodepool['private_ipv4'] }} + type=vxlan options:remote_ip={{ nodepool['private_ipv4'] }} options:key={{ vni }} + options:local_ip={{ switch_private_ip }} + delegate_to: "{{ groups['switch'][0] }}" + +- name: Create bridge on peer node + become: yes + openvswitch_bridge: + bridge: "{{ bridge_name }}" + +- name: Set MTU on peer node bridge + become: yes + command: ip link set mtu {{ bridge_mtu }} dev {{ bridge_name }} + +- name: Add port to bridge on peer node + become: yes + command: >- + ovs-vsctl --may-exist add-port {{ bridge_name }} + {{ bridge_name }}_{{ switch_private_ip }} + -- set interface {{ bridge_name }}_{{ switch_private_ip }} + type=vxlan options:remote_ip={{ switch_private_ip }} options:key={{ vni }} + options:local_ip={{ nodepool['private_ipv4'] }} + +- when: bridge_configure_address + block: + - name: Verify if the bridge address is set + shell: ip addr show dev {{ bridge_name }} | grep -q {{ bridge_address_prefix }}.{{ offset }}/{{ bridge_address_subnet }} + register: ip_addr_var + failed_when: False + changed_when: False + + - name: Set the bridge address + become: yes + command: ip addr add {{ bridge_address_prefix }}.{{ offset }}/{{ bridge_address_subnet }} dev {{ bridge_name }} + when: ip_addr_var.rc == 1 + +- name: Bring subnode bridge interface up + become: yes + command: ip link set dev {{ bridge_name }} up diff --git a/roles/multi-node-bridge/tasks/switch.yaml b/roles/multi-node-bridge/tasks/switch.yaml new file mode 100644 index 000000000..cbf8c7d67 --- /dev/null +++ b/roles/multi-node-bridge/tasks/switch.yaml @@ -0,0 +1,25 @@ +- name: Ensure the bridge exists + become: yes + openvswitch_bridge: + bridge: "{{ bridge_name }}" + +- name: Set the bridge MTU + become: yes + command: ip link set mtu {{ bridge_mtu }} dev {{ bridge_name }} + +- when: bridge_configure_address + block: + - name: Verify if the bridge address is set + shell: ip addr show dev {{ bridge_name }} | grep -q {{ bridge_address_prefix }}.{{ bridge_address_offset }}/{{ bridge_address_subnet }} + register: ip_addr_var + failed_when: False + changed_when: False + + - name: Set the bridge address + become: yes + command: ip addr add {{ bridge_address_prefix }}.{{ bridge_address_offset }}/{{ bridge_address_subnet }} dev {{ bridge_name }} + when: ip_addr_var.rc == 1 + +- name: Bring bridge interface up + become: yes + command: ip link set dev {{ bridge_name }} up diff --git a/roles/multi-node-bridge/vars/Debian.yaml b/roles/multi-node-bridge/vars/Debian.yaml new file mode 100644 index 000000000..6aa54ded9 --- /dev/null +++ b/roles/multi-node-bridge/vars/Debian.yaml @@ -0,0 +1,3 @@ +--- +ovs_package: "openvswitch-switch" +ovs_service: "openvswitch-switch" diff --git a/roles/multi-node-bridge/vars/RedHat.yaml b/roles/multi-node-bridge/vars/RedHat.yaml new file mode 100644 index 000000000..3af450ef5 --- /dev/null +++ b/roles/multi-node-bridge/vars/RedHat.yaml @@ -0,0 +1,4 @@ +--- +ovs_package: "openvswitch" +ovs_service: "openvswitch" +rdo_repository: "https://rdoproject.org/repos/openstack-ocata/rdo-release-ocata.rpm" diff --git a/roles/multi-node-bridge/vars/Suse.yaml b/roles/multi-node-bridge/vars/Suse.yaml new file mode 100644 index 000000000..19618923f --- /dev/null +++ b/roles/multi-node-bridge/vars/Suse.yaml @@ -0,0 +1,3 @@ +--- +ovs_package: "openvswitch" +ovs_service: "openvswitch" diff --git a/roles/multi-node-bridge/vars/default.yaml b/roles/multi-node-bridge/vars/default.yaml new file mode 100644 index 000000000..e69de29bb