From 8a0740df977916fa5b23117f993cde7282a303bf Mon Sep 17 00:00:00 2001 From: Michal Nasiadka Date: Fri, 20 Dec 2019 11:35:35 +0100 Subject: [PATCH] OVN Support Implement OVN Ansible role. Implements: blueprint ovn-controller-neutron-ansible Depends-On: https://review.opendev.org/713422 Change-Id: Icd425dea85d58db49c838839d8f0b864b4a89a78 --- ansible/group_vars/all.yml | 15 ++- ansible/inventory/all-in-one | 25 +++++ ansible/inventory/multinode | 25 +++++ ansible/roles/neutron/defaults/main.yml | 40 ++++++-- ansible/roles/neutron/handlers/main.yml | 16 ++++ ansible/roles/neutron/tasks/config.yml | 18 ++++ .../roles/neutron/templates/ml2_conf.ini.j2 | 12 +++ .../neutron-ovn-metadata-agent.json.j2 | 36 ++++++++ .../neutron/templates/neutron-server.json.j2 | 2 +- .../neutron_ovn_metadata_agent.ini.j2 | 17 ++++ ansible/roles/openvswitch/defaults/main.yml | 6 ++ ansible/roles/openvswitch/tasks/deploy.yml | 2 +- ...{ensure-ovs-bridge.yml => post-config.yml} | 5 + ansible/roles/openvswitch/tasks/upgrade.yml | 2 +- ansible/roles/ovn/defaults/main.yml | 92 +++++++++++++++++++ ansible/roles/ovn/handlers/main.yml | 84 +++++++++++++++++ ansible/roles/ovn/meta/main.yml | 3 + ansible/roles/ovn/tasks/bootstrap.yml | 40 ++++++++ ansible/roles/ovn/tasks/check-containers.yml | 16 ++++ ansible/roles/ovn/tasks/check.yml | 1 + ansible/roles/ovn/tasks/config.yml | 29 ++++++ ansible/roles/ovn/tasks/deploy-containers.yml | 2 + ansible/roles/ovn/tasks/deploy.yml | 7 ++ ansible/roles/ovn/tasks/main.yml | 2 + ansible/roles/ovn/tasks/precheck.yml | 30 ++++++ ansible/roles/ovn/tasks/pull.yml | 11 +++ ansible/roles/ovn/tasks/reconfigure.yml | 2 + ansible/roles/ovn/tasks/stop.yml | 6 ++ ansible/roles/ovn/tasks/upgrade.yml | 7 ++ .../ovn/templates/ovn-controller.json.j2 | 10 ++ ansible/roles/ovn/templates/ovn-nb-db.json.j2 | 12 +++ .../roles/ovn/templates/ovn-northd.json.j2 | 10 ++ ansible/roles/ovn/templates/ovn-sb-db.json.j2 | 12 +++ ansible/site.yml | 16 ++++ doc/source/reference/networking/neutron.rst | 23 +++++ etc/kolla/globals.yml | 7 ++ .../notes/implement-ovn-80b3a73e6c8a44e7.yaml | 9 ++ tests/run.yml | 9 +- tests/templates/globals-default.j2 | 4 + tests/templates/inventory.j2 | 25 +++++ tests/test-ovn.sh | 37 ++++++++ tools/setup_gate.sh | 4 + zuul.d/base.yaml | 11 +++ zuul.d/jobs.yaml | 16 ++++ zuul.d/project.yaml | 2 + 45 files changed, 746 insertions(+), 14 deletions(-) create mode 100644 ansible/roles/neutron/templates/neutron-ovn-metadata-agent.json.j2 create mode 100644 ansible/roles/neutron/templates/neutron_ovn_metadata_agent.ini.j2 rename ansible/roles/openvswitch/tasks/{ensure-ovs-bridge.yml => post-config.yml} (64%) create mode 100644 ansible/roles/ovn/defaults/main.yml create mode 100644 ansible/roles/ovn/handlers/main.yml create mode 100644 ansible/roles/ovn/meta/main.yml create mode 100644 ansible/roles/ovn/tasks/bootstrap.yml create mode 100644 ansible/roles/ovn/tasks/check-containers.yml create mode 100644 ansible/roles/ovn/tasks/check.yml create mode 100644 ansible/roles/ovn/tasks/config.yml create mode 100644 ansible/roles/ovn/tasks/deploy-containers.yml create mode 100644 ansible/roles/ovn/tasks/deploy.yml create mode 100644 ansible/roles/ovn/tasks/main.yml create mode 100644 ansible/roles/ovn/tasks/precheck.yml create mode 100644 ansible/roles/ovn/tasks/pull.yml create mode 100644 ansible/roles/ovn/tasks/reconfigure.yml create mode 100644 ansible/roles/ovn/tasks/stop.yml create mode 100644 ansible/roles/ovn/tasks/upgrade.yml create mode 100644 ansible/roles/ovn/templates/ovn-controller.json.j2 create mode 100644 ansible/roles/ovn/templates/ovn-nb-db.json.j2 create mode 100644 ansible/roles/ovn/templates/ovn-northd.json.j2 create mode 100644 ansible/roles/ovn/templates/ovn-sb-db.json.j2 create mode 100644 releasenotes/notes/implement-ovn-80b3a73e6c8a44e7.yaml create mode 100755 tests/test-ovn.sh diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml index 148112835f..80ce203458 100644 --- a/ansible/group_vars/all.yml +++ b/ansible/group_vars/all.yml @@ -374,6 +374,11 @@ octavia_api_port: "9876" octavia_api_listen_port: "{{ octavia_api_port }}" octavia_health_manager_port: "5555" +ovn_nb_db_port: "6641" +ovn_sb_db_port: "6642" +ovn_nb_connection: "{% for host in groups['ovn-nb-db'] %}tcp:{{ 'api' | kolla_address(host) }}:{{ ovn_nb_db_port }}{% if not loop.last %},{% endif %}{% endfor %}" +ovn_sb_connection: "{% for host in groups['ovn-sb-db'] %}tcp:{{ 'api' | kolla_address(host) }}:{{ ovn_sb_db_port }}{% if not loop.last %},{% endif %}{% endfor %}" + outward_rabbitmq_port: "5674" outward_rabbitmq_management_port: "15674" outward_rabbitmq_cluster_port: "25674" @@ -634,6 +639,7 @@ enable_nova_serialconsole_proxy: "no" enable_nova_ssh: "yes" enable_octavia: "no" enable_openvswitch: "{{ enable_neutron | bool and neutron_plugin_agent != 'linuxbridge' }}" +enable_ovn: "{{ enable_neutron | bool and neutron_plugin_agent == 'ovn' }}" enable_ovs_dpdk: "no" enable_osprofiler: "no" enable_panko: "no" @@ -882,14 +888,14 @@ designate_coordination_backend: "{{ 'redis' if enable_redis|bool else 'etcd' if neutron_bgp_router_id: "1.1.1.1" neutron_bridge_name: "{{ 'br-dvs' if neutron_plugin_agent == 'vmware_dvs' else 'br-ex' }}" # Comma-separated type of enabled ml2 type drivers -neutron_type_drivers: "flat,vlan,vxlan" +neutron_type_drivers: "flat,vlan,vxlan{% if neutron_plugin_agent == 'ovn' %},geneve{% endif %}" # Comma-separated types of tenant networks (should be listed in 'neutron_type_drivers') # NOTE: for ironic this list should also contain 'flat' -neutron_tenant_network_types: "vxlan" +neutron_tenant_network_types: "{% if neutron_plugin_agent == 'ovn' %}geneve{% else %}vxlan{% endif %}" # valid values: ["dvr", "dvr_no_external"] neutron_compute_dvr_mode: "dvr" -computes_need_external_bridge: "{{ (enable_neutron_dvr | bool and neutron_compute_dvr_mode == 'dvr') or enable_neutron_provider_networks | bool }}" +computes_need_external_bridge: "{{ (enable_neutron_dvr | bool and neutron_compute_dvr_mode == 'dvr') or enable_neutron_provider_networks | bool or neutron_ovn_distributed_fip | bool }}" # Default DNS resolvers for virtual networks neutron_dnsmasq_dns_servers: "1.1.1.1,8.8.8.8,8.8.4.4" @@ -897,6 +903,9 @@ neutron_dnsmasq_dns_servers: "1.1.1.1,8.8.8.8,8.8.4.4" # Set legacy iptables to allow kernels not supporting iptables-nft neutron_legacy_iptables: "no" +# Enable distributed floating ip for OVN deployments +neutron_ovn_distributed_fip: "no" + ####################### # Nova options ####################### diff --git a/ansible/inventory/all-in-one b/ansible/inventory/all-in-one index 483bc94491..b8fe610115 100644 --- a/ansible/inventory/all-in-one +++ b/ansible/inventory/all-in-one @@ -299,6 +299,9 @@ neutron [neutron-metadata-agent:children] neutron +[neutron-ovn-metadata-agent:children] +compute + [neutron-bgp-dragent:children] neutron @@ -756,3 +759,25 @@ control [masakari-monitors:children] compute + +[ovn-controller:children] +ovn-controller-compute +ovn-controller-network + +[ovn-controller-compute:children] +compute + +[ovn-controller-network:children] +network + +[ovn-database:children] +control + +[ovn-northd:children] +ovn-database + +[ovn-nb-db:children] +ovn-database + +[ovn-sb-db:children] +ovn-database diff --git a/ansible/inventory/multinode b/ansible/inventory/multinode index 98e4f1bb18..b662c90dfd 100644 --- a/ansible/inventory/multinode +++ b/ansible/inventory/multinode @@ -318,6 +318,9 @@ neutron [neutron-metadata-agent:children] neutron +[neutron-ovn-metadata-agent:children] +compute + [neutron-bgp-dragent:children] neutron @@ -775,3 +778,25 @@ control [masakari-monitors:children] compute + +[ovn-controller:children] +ovn-controller-compute +ovn-controller-network + +[ovn-controller-compute:children] +compute + +[ovn-controller-network:children] +network + +[ovn-database:children] +control + +[ovn-northd:children] +ovn-database + +[ovn-nb-db:children] +ovn-database + +[ovn-sb-db:children] +ovn-database diff --git a/ansible/roles/neutron/defaults/main.yml b/ansible/roles/neutron/defaults/main.yml index c519892f4a..b854ea71b6 100644 --- a/ansible/roles/neutron/defaults/main.yml +++ b/ansible/roles/neutron/defaults/main.yml @@ -81,7 +81,7 @@ neutron_services: container_name: "neutron_dhcp_agent" image: "{{ neutron_dhcp_agent_image_full }}" privileged: True - enabled: "{{ neutron_plugin_agent not in [ 'vmware_nsxv', 'vmware_nsxv3' ] }}" + enabled: "{{ neutron_plugin_agent not in ['ovn', 'vmware_nsxv', 'vmware_nsxv3'] }}" group: "neutron-dhcp-agent" host_in_groups: "{{ inventory_hostname in groups['neutron-dhcp-agent'] }}" volumes: "{{ neutron_dhcp_agent_default_volumes + neutron_dhcp_agent_extra_volumes }}" @@ -90,7 +90,7 @@ neutron_services: container_name: "neutron_l3_agent" image: "{{ neutron_l3_agent_image_full }}" privileged: True - enabled: "{{ neutron_plugin_agent not in ['vmware_nsxv', 'vmware_nsxv3', 'vmware_dvs'] }}" + enabled: "{{ neutron_plugin_agent not in ['ovn', 'vmware_nsxv', 'vmware_nsxv3', 'vmware_dvs'] }}" environment: KOLLA_LEGACY_IPTABLES: "{{ neutron_legacy_iptables | bool | lower }}" host_in_groups: >- @@ -112,19 +112,27 @@ neutron_services: container_name: "neutron_metadata_agent" image: "{{ neutron_metadata_agent_image_full }}" privileged: True - enabled: "{{ neutron_plugin_agent not in [ 'vmware_nsxv', 'vmware_nsxv3' ] }}" + enabled: "{{ neutron_plugin_agent not in [ 'ovn', 'vmware_nsxv', 'vmware_nsxv3' ] }}" host_in_groups: >- {{ inventory_hostname in groups['neutron-metadata-agent'] - or (inventory_hostname in groups['compute'] and enable_neutron_dvr | bool) + or (inventory_hostname in groups['compute'] and neutron_plugin_agent == 'openvswitch' and enable_neutron_dvr | bool) }} volumes: "{{ neutron_metadata_agent_default_volumes + neutron_metadata_agent_extra_volumes }}" dimensions: "{{ neutron_metadata_agent_dimensions }}" + neutron-ovn-metadata-agent: + container_name: "neutron_ovn_metadata_agent" + image: "{{ neutron_ovn_metadata_agent_image_full }}" + privileged: True + enabled: "{{ neutron_plugin_agent == 'ovn' }}" + host_in_groups: "{{ inventory_hostname in groups['neutron-ovn-metadata-agent'] }}" + volumes: "{{ neutron_ovn_metadata_agent_default_volumes + neutron_ovn_metadata_agent_extra_volumes }}" + dimensions: "{{ neutron_ovn_metadata_agent_dimensions }}" neutron-bgp-dragent: container_name: "neutron_bgp_dragent" image: "{{ neutron_bgp_dragent_image_full }}" privileged: True - enabled: "{{ enable_neutron_bgp_dragent | bool and neutron_plugin_agent not in ['vmware_nsxv', 'vmware_nsxv3', 'vmware_dvs'] }}" + enabled: "{{ enable_neutron_bgp_dragent | bool and neutron_plugin_agent not in ['ovn', 'vmware_nsxv', 'vmware_nsxv3', 'vmware_dvs'] }}" group: "neutron-bgp-dragent" host_in_groups: "{{ inventory_hostname in groups['neutron-bgp-dragent'] }}" volumes: "{{ neutron_bgp_dragent_default_volumes + neutron_bgp_dragent_extra_volumes }}" @@ -191,6 +199,10 @@ neutron_metadata_agent_image: "{{ docker_registry ~ '/' if docker_registry else neutron_metadata_agent_tag: "{{ neutron_tag }}" neutron_metadata_agent_image_full: "{{ neutron_metadata_agent_image }}:{{ neutron_metadata_agent_tag }}" +neutron_ovn_metadata_agent_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ neutron_install_type }}-neutron-metadata-agent" +neutron_ovn_metadata_agent_tag: "{{ neutron_tag }}" +neutron_ovn_metadata_agent_image_full: "{{ neutron_ovn_metadata_agent_image }}:{{ neutron_ovn_metadata_agent_tag }}" + neutron_openvswitch_agent_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ neutron_install_type }}-neutron-openvswitch-agent" neutron_openvswitch_agent_tag: "{{ neutron_tag }}" neutron_openvswitch_agent_image_full: "{{ neutron_openvswitch_agent_image }}:{{ neutron_openvswitch_agent_tag }}" @@ -232,6 +244,7 @@ neutron_l3_agent_dimensions: "{{ neutron_agent_dimensions }}" neutron_sriov_agent_dimensions: "{{ neutron_agent_dimensions }}" neutron_linuxbridge_agent_dimensions: "{{ neutron_agent_dimensions }}" neutron_metadata_agent_dimensions: "{{ neutron_agent_dimensions }}" +neutron_ovn_metadata_agent_dimensions: "{{ neutron_agent_dimensions }}" neutron_openvswitch_agent_dimensions: "{{ neutron_agent_dimensions }}" neutron_server_dimensions: "{{ default_container_dimensions }}" neutron_bgp_dragent_dimensions: "{{ default_container_dimensions }}" @@ -273,6 +286,14 @@ neutron_metadata_agent_default_volumes: - "neutron_metadata_socket:/var/lib/neutron/kolla/" - "kolla_logs:/var/log/kolla/" - "{{ kolla_dev_repos_directory ~ '/neutron/neutron:/var/lib/kolla/venv/lib/python' ~ distro_python_version ~ '/site-packages/neutron' if neutron_dev_mode | bool else '' }}" +neutron_ovn_metadata_agent_default_volumes: + - "{{ node_config_directory }}/neutron-ovn-metadata-agent/:{{ container_config_directory }}/:ro" + - "/etc/localtime:/etc/localtime:ro" + - "neutron_metadata_socket:/var/lib/neutron/kolla/" + - "/run/openvswitch:/run/openvswitch:shared" + - "/run/netns:/run/netns:shared" + - "kolla_logs:/var/log/kolla/" + - "{{ kolla_dev_repos_directory ~ '/neutron/neutron:/var/lib/kolla/venv/lib/python' ~ distro_python_version ~ '/site-packages/neutron' if neutron_dev_mode | bool else '' }}" neutron_openvswitch_agent_default_volumes: - "{{ node_config_directory }}/neutron-openvswitch-agent/:{{ container_config_directory }}/:ro" - "/etc/localtime:/etc/localtime:ro" @@ -316,6 +337,7 @@ neutron_l3_agent_extra_volumes: "{{ neutron_extra_volumes }}" neutron_sriov_agent_extra_volumes: "{{ neutron_extra_volumes }}" neutron_linuxbridge_agent_extra_volumes: "{{ neutron_extra_volumes }}" neutron_metadata_agent_extra_volumes: "{{ neutron_extra_volumes }}" +neutron_ovn_metadata_agent_extra_volumes: "{{ neutron_extra_volumes }}" neutron_openvswitch_agent_extra_volumes: "{{ neutron_extra_volumes }}" neutron_server_extra_volumes: "{{ neutron_extra_volumes }}" neutron_bgp_dragent_extra_volumes: "{{ neutron_extra_volumes }}" @@ -359,7 +381,9 @@ mechanism_drivers: - name: "baremetal" enabled: "{{ enable_ironic_neutron_agent | bool }}" - name: "l2population" - enabled: "{{ not enable_hyperv | bool }}" + enabled: "{{ not enable_hyperv | bool or neutron_plugin_agent != 'ovn' }}" + - name: "ovn" + enabled: "{{ neutron_plugin_agent == 'ovn' }}" neutron_mechanism_drivers: "{{ mechanism_drivers | selectattr('enabled', 'equalto', true) | list }}" @@ -399,7 +423,7 @@ service_plugins: - name: "qos" enabled: "{{ enable_neutron_qos | bool }}" - name: "router" - enabled: true + enabled: "{{ neutron_plugin_agent != 'ovn' }}" - name: "segments" enabled: "{{ enable_neutron_segments | bool }}" - name: "sfc" @@ -408,6 +432,8 @@ service_plugins: enabled: "{{ enable_neutron_vpnaas | bool }}" - name: "port_forwarding" enabled: "{{ enable_neutron_port_forwarding | bool }}" + - name: "ovn-router" + enabled: "{{ neutron_plugin_agent == 'ovn' }}" neutron_service_plugins: "{{ service_plugins | selectattr('enabled', 'equalto', true) | list }}" diff --git a/ansible/roles/neutron/handlers/main.yml b/ansible/roles/neutron/handlers/main.yml index fcde345072..af364f9940 100644 --- a/ansible/roles/neutron/handlers/main.yml +++ b/ansible/roles/neutron/handlers/main.yml @@ -147,6 +147,22 @@ when: - kolla_action != "config" +- name: Restart neutron-ovn-metadata-agent container + vars: + service_name: "neutron-ovn-metadata-agent" + service: "{{ neutron_services[service_name] }}" + become: true + kolla_docker: + action: "recreate_or_restart_container" + common_options: "{{ docker_common_options }}" + name: "{{ service.container_name }}" + image: "{{ service.image }}" + volumes: "{{ service.volumes|reject('equalto', '')|list }}" + dimensions: "{{ service.dimensions }}" + privileged: "{{ service.privileged | default(False) }}" + when: + - kolla_action != "config" + - name: Restart neutron-bgp-dragent container vars: service_name: "neutron-bgp-dragent" diff --git a/ansible/roles/neutron/tasks/config.yml b/ansible/roles/neutron/tasks/config.yml index bf8b3bcb4d..889ff779b6 100644 --- a/ansible/roles/neutron/tasks/config.yml +++ b/ansible/roles/neutron/tasks/config.yml @@ -57,6 +57,7 @@ - "neutron-l3-agent" - "neutron-linuxbridge-agent" - "neutron-metadata-agent" + - "neutron-ovn-metadata-agent" - "neutron-metering-agent" - "neutron-openvswitch-agent" - "neutron-openvswitch-agent-xenapi" @@ -300,6 +301,23 @@ notify: - "Restart {{ service_name }} container" +- name: Copying over neutron_ovn_metadata_agent.ini + become: true + vars: + service_name: "neutron-ovn-metadata-agent" + neutron_ovn_metadata_agent: "{{ neutron_services[service_name] }}" + merge_configs: + sources: + - "{{ role_path }}/templates/neutron_ovn_metadata_agent.ini.j2" + - "{{ node_custom_config }}/neutron/neutron_ovn_metadata_agent.ini" + dest: "{{ node_config_directory }}/{{ service_name }}/neutron_ovn_metadata_agent.ini" + mode: "0660" + when: + - neutron_ovn_metadata_agent.enabled | bool + - neutron_ovn_metadata_agent.host_in_groups | bool + notify: + - "Restart {{ service_name }} container" + - name: Copying over metering_agent.ini become: true vars: diff --git a/ansible/roles/neutron/templates/ml2_conf.ini.j2 b/ansible/roles/neutron/templates/ml2_conf.ini.j2 index 2ea2195c39..2e1cb8096a 100644 --- a/ansible/roles/neutron/templates/ml2_conf.ini.j2 +++ b/ansible/roles/neutron/templates/ml2_conf.ini.j2 @@ -29,3 +29,15 @@ flat_networks = {% for bridge in neutron_bridge_name.split(',') %}physnet{{ loop [ml2_type_vxlan] vni_ranges = 1:1000 + +{% if neutron_plugin_agent == 'ovn' %} +[ml2_type_geneve] +vni_ranges = 1001:2000 +max_header_size = 38 + +[ovn] +ovn_nb_connection = {{ ovn_nb_connection }} +ovn_sb_connection = {{ ovn_sb_connection }} +ovn_metadata_enabled = True +enable_distributed_floating_ip = {{ neutron_ovn_distributed_fip | bool }} +{% endif %} diff --git a/ansible/roles/neutron/templates/neutron-ovn-metadata-agent.json.j2 b/ansible/roles/neutron/templates/neutron-ovn-metadata-agent.json.j2 new file mode 100644 index 0000000000..f88e66494b --- /dev/null +++ b/ansible/roles/neutron/templates/neutron-ovn-metadata-agent.json.j2 @@ -0,0 +1,36 @@ +{ + "command": "neutron-ovn-metadata-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/neutron_ovn_metadata_agent.ini", + "config_files": [ + { + "source": "{{ container_config_directory }}/neutron.conf", + "dest": "/etc/neutron/neutron.conf", + "owner": "neutron", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/neutron_ovn_metadata_agent.ini", + "dest": "/etc/neutron/neutron_ovn_metadata_agent.ini", + "owner": "neutron", + "perm": "0600" + }, + { + "source": "{{ container_config_directory }}/policy.json", + "dest": "/etc/neutron/policy.json", + "owner": "neutron", + "perm": "0600", + "optional": true + } + ], + "permissions": [ + { + "path": "/var/log/kolla/neutron", + "owner": "neutron:neutron", + "recurse": true + }, + { + "path": "/var/lib/neutron/kolla", + "owner": "neutron:neutron", + "recurse": true + } + ] +} diff --git a/ansible/roles/neutron/templates/neutron-server.json.j2 b/ansible/roles/neutron/templates/neutron-server.json.j2 index 77ea2f2dda..3a71ed1239 100644 --- a/ansible/roles/neutron/templates/neutron-server.json.j2 +++ b/ansible/roles/neutron/templates/neutron-server.json.j2 @@ -1,5 +1,5 @@ { - "command": "neutron-server --config-file /etc/neutron/neutron.conf {% if neutron_plugin_agent in ['openvswitch', 'linuxbridge'] %} --config-file /etc/neutron/plugins/ml2/ml2_conf.ini --config-file /etc/neutron/neutron_vpnaas.conf {% elif neutron_plugin_agent in ['vmware_nsxv', 'vmware_nsxv3', 'vmware_dvs'] %} --config-file /etc/neutron/plugins/vmware/nsx.ini {% endif %} --config-file /etc/neutron/fwaas_driver.ini", + "command": "neutron-server --config-file /etc/neutron/neutron.conf {% if neutron_plugin_agent in ['openvswitch', 'linuxbridge', 'ovn'] %} --config-file /etc/neutron/plugins/ml2/ml2_conf.ini --config-file /etc/neutron/neutron_vpnaas.conf {% elif neutron_plugin_agent in ['vmware_nsxv', 'vmware_nsxv3', 'vmware_dvs'] %} --config-file /etc/neutron/plugins/vmware/nsx.ini {% endif %} --config-file /etc/neutron/fwaas_driver.ini", "config_files": [ { "source": "{{ container_config_directory }}/neutron.conf", diff --git a/ansible/roles/neutron/templates/neutron_ovn_metadata_agent.ini.j2 b/ansible/roles/neutron/templates/neutron_ovn_metadata_agent.ini.j2 new file mode 100644 index 0000000000..591e8cde14 --- /dev/null +++ b/ansible/roles/neutron/templates/neutron_ovn_metadata_agent.ini.j2 @@ -0,0 +1,17 @@ +[DEFAULT] +auth_ca_cert = {{ openstack_cacert }} +nova_metadata_protocol = {{ internal_protocol }} +metadata_proxy_socket = /var/lib/neutron/kolla/metadata_proxy +nova_metadata_host = {{ nova_internal_fqdn }} +nova_metadata_port = {{ nova_metadata_port }} +metadata_proxy_shared_secret = {{ metadata_secret }} +log_file = neutron-ovn-metadata-agent.log +log_dir = /var/log/kolla/neutron + +[ovs] +ovsdb_connection = tcp:127.0.0.1:6640 + +[ovn] +ovn_nb_connection = {{ ovn_nb_connection }} +ovn_sb_connection = {{ ovn_sb_connection }} +ovn_metadata_enabled = true diff --git a/ansible/roles/openvswitch/defaults/main.yml b/ansible/roles/openvswitch/defaults/main.yml index fe2867ab5e..425a86667f 100644 --- a/ansible/roles/openvswitch/defaults/main.yml +++ b/ansible/roles/openvswitch/defaults/main.yml @@ -68,3 +68,9 @@ openvswitch_vswitchd_default_volumes: openvswitch_extra_volumes: "{{ default_extra_volumes }}" openvswitch_db_extra_volumes: "{{ openvswitch_extra_volumes }}" openvswitch_vswitchd_extra_volumes: "{{ openvswitch_extra_volumes }}" + +############# +# OpenvSwitch +############# + +openvswitch_system_id: "{{ inventory_hostname_short }}" diff --git a/ansible/roles/openvswitch/tasks/deploy.yml b/ansible/roles/openvswitch/tasks/deploy.yml index 60c9a99024..f135d8a295 100644 --- a/ansible/roles/openvswitch/tasks/deploy.yml +++ b/ansible/roles/openvswitch/tasks/deploy.yml @@ -6,4 +6,4 @@ - name: Flush Handlers meta: flush_handlers -- include_tasks: ensure-ovs-bridge.yml +- include_tasks: post-config.yml diff --git a/ansible/roles/openvswitch/tasks/ensure-ovs-bridge.yml b/ansible/roles/openvswitch/tasks/post-config.yml similarity index 64% rename from ansible/roles/openvswitch/tasks/ensure-ovs-bridge.yml rename to ansible/roles/openvswitch/tasks/post-config.yml index 55ea2e9aca..ce412b8842 100644 --- a/ansible/roles/openvswitch/tasks/ensure-ovs-bridge.yml +++ b/ansible/roles/openvswitch/tasks/post-config.yml @@ -1,4 +1,9 @@ --- +# NOTE(mnasiadka): external_ids:system-id uniquely identifies a physical system, used by OVN and other controllers +- name: Set system-id + become: true + command: docker exec openvswitch_vswitchd ovs-vsctl set Open_vSwitch . external_ids:system-id={{ openvswitch_system_id }} + - name: Ensuring OVS bridge is properly setup become: true command: docker exec openvswitch_db /usr/local/bin/kolla_ensure_openvswitch_configured {{ item.0 }} {{ item.1 }} diff --git a/ansible/roles/openvswitch/tasks/upgrade.yml b/ansible/roles/openvswitch/tasks/upgrade.yml index 110210a16b..92824f43de 100644 --- a/ansible/roles/openvswitch/tasks/upgrade.yml +++ b/ansible/roles/openvswitch/tasks/upgrade.yml @@ -4,4 +4,4 @@ - name: Flush Handlers meta: flush_handlers -- include_tasks: ensure-ovs-bridge.yml +- include_tasks: post-config.yml diff --git a/ansible/roles/ovn/defaults/main.yml b/ansible/roles/ovn/defaults/main.yml new file mode 100644 index 0000000000..58c26bb6f8 --- /dev/null +++ b/ansible/roles/ovn/defaults/main.yml @@ -0,0 +1,92 @@ +--- +project_name: "ovn" + +ovn_services: + ovn-controller: + container_name: ovn_controller + group: ovn-controller + enabled: true + image: "{{ ovn_controller_image_full }}" + volumes: "{{ ovn_controller_default_volumes + ovn_controller_extra_volumes }}" + dimensions: "{{ ovn_controller_dimensions }}" + ovn-northd: + container_name: ovn_northd + group: ovn-northd + enabled: true + image: "{{ ovn_northd_image_full }}" + volumes: "{{ ovn_northd_default_volumes + ovn_northd_extra_volumes }}" + dimensions: "{{ ovn_northd_dimensions }}" + ovn-nb-db: + container_name: ovn_nb_db + group: ovn-nb-db + enabled: true + image: "{{ ovn_nb_db_image_full }}" + volumes: "{{ ovn_nb_db_default_volumes + ovn_nb_db_extra_volumes }}" + dimensions: "{{ ovn_nb_db_dimensions }}" + ovn-sb-db: + container_name: ovn_sb_db + group: ovn-sb-db + enabled: true + image: "{{ ovn_sb_db_image_full }}" + volumes: "{{ ovn_sb_db_default_volumes + ovn_sb_db_extra_volumes }}" + dimensions: "{{ ovn_sb_db_dimensions }}" + + +#################### +# Docker +#################### +ovn_install_type: "{{ kolla_install_type }}" +ovn_tag: "{{ openstack_tag }}" + +ovn_controller_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ ovn_install_type }}-ovn-controller" +ovn_controller_tag: "{{ ovn_tag }}" +ovn_controller_image_full: "{{ ovn_controller_image }}:{{ ovn_controller_tag }}" + +ovn_northd_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ ovn_install_type }}-ovn-northd" +ovn_northd_tag: "{{ ovn_tag }}" +ovn_northd_image_full: "{{ ovn_northd_image }}:{{ ovn_northd_tag }}" + +ovn_nb_db_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ ovn_install_type }}-ovn-nb-db-server" +ovn_nb_db_tag: "{{ ovn_tag }}" +ovn_nb_db_image_full: "{{ ovn_nb_db_image }}:{{ ovn_nb_db_tag }}" + +ovn_sb_db_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ ovn_install_type }}-ovn-sb-db-server" +ovn_sb_db_tag: "{{ ovn_tag }}" +ovn_sb_db_image_full: "{{ ovn_sb_db_image }}:{{ ovn_sb_db_tag }}" + +ovn_controller_dimensions: "{{ default_container_dimensions }}" +ovn_northd_dimensions: "{{ default_container_dimensions }}" +ovn_nb_db_dimensions: "{{ default_container_dimensions }}" +ovn_sb_db_dimensions: "{{ default_container_dimensions }}" + +ovn_controller_default_volumes: + - "{{ node_config_directory }}/ovn-controller/:{{ container_config_directory }}/:ro" + - "/run/openvswitch:/run/openvswitch:shared" + - "/etc/localtime:/etc/localtime:ro" + - "kolla_logs:/var/log/kolla/" +ovn_northd_default_volumes: + - "{{ node_config_directory }}/ovn-northd/:{{ container_config_directory }}/:ro" + - "/etc/localtime:/etc/localtime:ro" + - "kolla_logs:/var/log/kolla/" +ovn_nb_db_default_volumes: + - "{{ node_config_directory }}/ovn-nb-db/:{{ container_config_directory }}/:ro" + - "/etc/localtime:/etc/localtime:ro" + - "ovn_nb_db:/var/lib/openvswitch/ovn-nb/" + - "kolla_logs:/var/log/kolla/" +ovn_sb_db_default_volumes: + - "{{ node_config_directory }}/ovn-sb-db/:{{ container_config_directory }}/:ro" + - "/etc/localtime:/etc/localtime:ro" + - "ovn_sb_db:/var/lib/openvswitch/ovn-sb/" + - "kolla_logs:/var/log/kolla/" + +ovn_extra_volumes: "{{ default_extra_volumes }}" +ovn_controller_extra_volumes: "{{ ovn_extra_volumes }}" +ovn_northd_extra_volumes: "{{ ovn_extra_volumes }}" +ovn_nb_db_extra_volumes: "{{ ovn_extra_volumes }}" +ovn_sb_db_extra_volumes: "{{ ovn_extra_volumes }}" + +##### +# OVN +##### +# Configure OVN remote probe interval time in ms +ovn_remote_probe_interval: "60000" diff --git a/ansible/roles/ovn/handlers/main.yml b/ansible/roles/ovn/handlers/main.yml new file mode 100644 index 0000000000..42263f16c7 --- /dev/null +++ b/ansible/roles/ovn/handlers/main.yml @@ -0,0 +1,84 @@ +--- +- name: Restart ovn-nb-db container + vars: + service_name: "ovn-nb-db" + service: "{{ ovn_services[service_name] }}" + become: true + kolla_docker: + action: "recreate_or_restart_container" + common_options: "{{ docker_common_options }}" + name: "{{ service.container_name }}" + image: "{{ service.image }}" + volumes: "{{ service.volumes|reject('equalto', '')|list }}" + dimensions: "{{ service.dimensions }}" + when: + - kolla_action != "config" + +- name: Restart ovn-sb-db container + vars: + service_name: "ovn-sb-db" + service: "{{ ovn_services[service_name] }}" + become: true + kolla_docker: + action: "recreate_or_restart_container" + common_options: "{{ docker_common_options }}" + name: "{{ service.container_name }}" + image: "{{ service.image }}" + volumes: "{{ service.volumes|reject('equalto', '')|list }}" + dimensions: "{{ service.dimensions }}" + when: + - kolla_action != "config" + +- name: Wait for ovn-nb-db + wait_for: + host: "{{ api_interface_address }}" + port: "{{ ovn_nb_db_port }}" + connect_timeout: 1 + timeout: 60 + register: check_ovn_nb_db_port + until: check_ovn_nb_db_port is success + retries: 10 + delay: 6 + listen: "Restart ovn-nb-db container" + +- name: Wait for ovn-sb-db + wait_for: + host: "{{ api_interface_address }}" + port: "{{ ovn_sb_db_port }}" + connect_timeout: 1 + timeout: 60 + register: check_ovn_sb_db_port + until: check_ovn_sb_db_port is success + retries: 10 + delay: 6 + listen: "Restart ovn-sb-db container" + +- name: Restart ovn-northd container + vars: + service_name: "ovn-northd" + service: "{{ ovn_services[service_name] }}" + become: true + kolla_docker: + action: "recreate_or_restart_container" + common_options: "{{ docker_common_options }}" + name: "{{ service.container_name }}" + image: "{{ service.image }}" + volumes: "{{ service.volumes|reject('equalto', '')|list }}" + dimensions: "{{ service.dimensions }}" + when: + - kolla_action != "config" + +- name: Restart ovn-controller container + vars: + service_name: "ovn-controller" + service: "{{ ovn_services[service_name] }}" + become: true + kolla_docker: + action: "recreate_or_restart_container" + common_options: "{{ docker_common_options }}" + name: "{{ service.container_name }}" + image: "{{ service.image }}" + volumes: "{{ service.volumes|reject('equalto', '')|list }}" + dimensions: "{{ service.dimensions }}" + when: + - kolla_action != "config" diff --git a/ansible/roles/ovn/meta/main.yml b/ansible/roles/ovn/meta/main.yml new file mode 100644 index 0000000000..6b4fff8fef --- /dev/null +++ b/ansible/roles/ovn/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - { role: common } diff --git a/ansible/roles/ovn/tasks/bootstrap.yml b/ansible/roles/ovn/tasks/bootstrap.yml new file mode 100644 index 0000000000..3b01f19ff7 --- /dev/null +++ b/ansible/roles/ovn/tasks/bootstrap.yml @@ -0,0 +1,40 @@ +--- +- name: Create br-int bridge on OpenvSwitch + become: true + command: > + docker exec openvswitch_vswitchd ovs-vsctl --may-exist + add-br br-int -- set Bridge br-int fail-mode=secure + when: inventory_hostname in groups['ovn-controller'] + +- name: Set OVN encapsulation settings + become: true + command: > + docker exec openvswitch_vswitchd ovs-vsctl set Open_vSwitch . + external_ids:ovn-encap-ip={{ tunnel_interface_address }} + external_ids:ovn-encap-type=geneve + external_ids:ovn-remote={{ ovn_sb_connection }} + when: inventory_hostname in groups['ovn-controller'] + +- name: Set OVN bridge mappings + vars: + ovn_mappings: "{% for bridge in neutron_bridge_name.split(',') %}physnet{{ loop.index0 + 1 }}:{{ bridge }}{% if not loop.last %},{% endif %}{% endfor %}" + become: true + command: docker exec openvswitch_vswitchd ovs-vsctl set Open_vSwitch . external_ids:ovn-bridge-mappings={{ ovn_mappings }} + when: + - inventory_hostname in groups["ovn-controller-network"] + or (inventory_hostname in groups["ovn-controller-compute"] and computes_need_external_bridge | bool) + +- name: Enable chassis as gateway + become: true + command: docker exec openvswitch_vswitchd ovs-vsctl set Open_vSwitch . external-ids:ovn-cms-options="enable-chassis-as-gw" + when: + - inventory_hostname in groups["ovn-controller-network"] + or (inventory_hostname in groups["ovn-controller-compute"] and neutron_ovn_distributed_fip | bool) + +- name: Set OVN remote probe interval + become: true + command: > + docker exec openvswitch_vswitchd ovs-vsctl set Open_vSwitch . + external_ids:ovn-remote-probe-interval={{ ovn_remote_probe_interval }} + when: + - inventory_hostname in groups["ovn-controller"] diff --git a/ansible/roles/ovn/tasks/check-containers.yml b/ansible/roles/ovn/tasks/check-containers.yml new file mode 100644 index 0000000000..fe5ac530e9 --- /dev/null +++ b/ansible/roles/ovn/tasks/check-containers.yml @@ -0,0 +1,16 @@ +--- +- name: Check ovn containers + become: true + kolla_docker: + action: "compare_container" + common_options: "{{ docker_common_options }}" + name: "{{ item.value.container_name }}" + image: "{{ item.value.image }}" + volumes: "{{ item.value.volumes|reject('equalto', '')|list }}" + dimensions: "{{ item.value.dimensions }}" + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ ovn_services }}" + notify: + - Restart {{ item.key }} container diff --git a/ansible/roles/ovn/tasks/check.yml b/ansible/roles/ovn/tasks/check.yml new file mode 100644 index 0000000000..ed97d539c0 --- /dev/null +++ b/ansible/roles/ovn/tasks/check.yml @@ -0,0 +1 @@ +--- diff --git a/ansible/roles/ovn/tasks/config.yml b/ansible/roles/ovn/tasks/config.yml new file mode 100644 index 0000000000..06216fc21f --- /dev/null +++ b/ansible/roles/ovn/tasks/config.yml @@ -0,0 +1,29 @@ +--- +- name: Ensuring config directories exist + file: + path: "{{ node_config_directory }}/{{ item.key }}" + state: "directory" + owner: "{{ config_owner_user }}" + group: "{{ config_owner_group }}" + mode: "0770" + become: true + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ ovn_services }}" + +- name: Copying over config.json files for services + template: + src: "{{ item.key }}.json.j2" + dest: "{{ node_config_directory }}/{{ item.key }}/config.json" + mode: "0660" + become: true + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ ovn_services }}" + notify: + - Restart {{ item.key }} container + +- include_tasks: check-containers.yml + when: kolla_action != "config" diff --git a/ansible/roles/ovn/tasks/deploy-containers.yml b/ansible/roles/ovn/tasks/deploy-containers.yml new file mode 100644 index 0000000000..eb24ab5c7a --- /dev/null +++ b/ansible/roles/ovn/tasks/deploy-containers.yml @@ -0,0 +1,2 @@ +--- +- import_tasks: check-containers.yml diff --git a/ansible/roles/ovn/tasks/deploy.yml b/ansible/roles/ovn/tasks/deploy.yml new file mode 100644 index 0000000000..6f6feecec0 --- /dev/null +++ b/ansible/roles/ovn/tasks/deploy.yml @@ -0,0 +1,7 @@ +--- +- include_tasks: config.yml + +- include_tasks: bootstrap.yml + +- name: Flush handlers + meta: flush_handlers diff --git a/ansible/roles/ovn/tasks/main.yml b/ansible/roles/ovn/tasks/main.yml new file mode 100644 index 0000000000..bc5d1e6257 --- /dev/null +++ b/ansible/roles/ovn/tasks/main.yml @@ -0,0 +1,2 @@ +--- +- include_tasks: "{{ kolla_action }}.yml" diff --git a/ansible/roles/ovn/tasks/precheck.yml b/ansible/roles/ovn/tasks/precheck.yml new file mode 100644 index 0000000000..77bf882816 --- /dev/null +++ b/ansible/roles/ovn/tasks/precheck.yml @@ -0,0 +1,30 @@ +--- +- name: Get container facts + become: true + kolla_container_facts: + name: + - ovn_nb_db + - ovn_sb_db + register: container_facts + +- name: Checking free port for OVN northbound db + wait_for: + host: "{{ api_interface_address }}" + port: "{{ ovn_nb_db_port }}" + connect_timeout: 1 + timeout: 1 + state: stopped + when: + - container_facts['ovn_nb_db'] is not defined + - inventory_hostname in groups['ovn-nb-db'] + +- name: Checking free port for OVN southbound db + wait_for: + host: "{{ api_interface_address }}" + port: "{{ ovn_sb_db_port }}" + connect_timeout: 1 + timeout: 1 + state: stopped + when: + - container_facts['ovn_sb_db'] is not defined + - inventory_hostname in groups['ovn-sb-db'] diff --git a/ansible/roles/ovn/tasks/pull.yml b/ansible/roles/ovn/tasks/pull.yml new file mode 100644 index 0000000000..79ae0b297d --- /dev/null +++ b/ansible/roles/ovn/tasks/pull.yml @@ -0,0 +1,11 @@ +--- +- name: Pulling OVN images + become: true + kolla_docker: + action: "pull_image" + common_options: "{{ docker_common_options }}" + image: "{{ item.value.image }}" + when: + - inventory_hostname in groups[item.value.group] + - item.value.enabled | bool + with_dict: "{{ ovn_services }}" diff --git a/ansible/roles/ovn/tasks/reconfigure.yml b/ansible/roles/ovn/tasks/reconfigure.yml new file mode 100644 index 0000000000..f670a5b78d --- /dev/null +++ b/ansible/roles/ovn/tasks/reconfigure.yml @@ -0,0 +1,2 @@ +--- +- include_tasks: deploy.yml diff --git a/ansible/roles/ovn/tasks/stop.yml b/ansible/roles/ovn/tasks/stop.yml new file mode 100644 index 0000000000..885576f7de --- /dev/null +++ b/ansible/roles/ovn/tasks/stop.yml @@ -0,0 +1,6 @@ +--- +- import_role: + role: service-stop + vars: + project_services: "{{ ovn_services }}" + service_name: "{{ project_name }}" diff --git a/ansible/roles/ovn/tasks/upgrade.yml b/ansible/roles/ovn/tasks/upgrade.yml new file mode 100644 index 0000000000..6f6feecec0 --- /dev/null +++ b/ansible/roles/ovn/tasks/upgrade.yml @@ -0,0 +1,7 @@ +--- +- include_tasks: config.yml + +- include_tasks: bootstrap.yml + +- name: Flush handlers + meta: flush_handlers diff --git a/ansible/roles/ovn/templates/ovn-controller.json.j2 b/ansible/roles/ovn/templates/ovn-controller.json.j2 new file mode 100644 index 0000000000..b2db221978 --- /dev/null +++ b/ansible/roles/ovn/templates/ovn-controller.json.j2 @@ -0,0 +1,10 @@ +{ + "command": "/usr/bin/ovn-controller --pidfile=/run/ovn/ovn-controller.pid --log-file=/var/log/kolla/openvswitch/ovn-controller.log tcp:127.0.0.1:{{ ovsdb_port }}", + "permissions": [ + { + "path": "/var/log/kolla/openvswitch", + "owner": "root:root", + "recurse": true + } + ] +} diff --git a/ansible/roles/ovn/templates/ovn-nb-db.json.j2 b/ansible/roles/ovn/templates/ovn-nb-db.json.j2 new file mode 100644 index 0000000000..5255566511 --- /dev/null +++ b/ansible/roles/ovn/templates/ovn-nb-db.json.j2 @@ -0,0 +1,12 @@ +{% set ovnctl_cmd = '/usr/share/ovn/scripts/ovn-ctl' %} + +{ + "command": "{{ ovnctl_cmd }} run_nb_ovsdb --db-nb-create-insecure-remote=yes --db-nb-addr={{ api_interface_address }} --db-nb-cluster-local-addr={{ api_interface_address }} {% if groups['ovn-nb-db'] | length > 1 and inventory_hostname != groups['ovn-nb-db'][0] %} --db-nb-cluster-remote-addr={{ 'api' | kolla_address(groups['ovn-nb-db'][0]) }} {% endif %} --db-sock=/run/ovn/ovnnb_db.sock --db-nb-pid=/run/ovn/ovnnb_db.pid --db-nb-file=/var/lib/openvswitch/ovn-nb/ovnnb.db --ovn-nb-logfile=/var/log/kolla/openvswitch/ovn-nb-db.log", + "permissions": [ + { + "path": "/var/log/kolla/openvswitch", + "owner": "root:root", + "recurse": true + } + ] +} diff --git a/ansible/roles/ovn/templates/ovn-northd.json.j2 b/ansible/roles/ovn/templates/ovn-northd.json.j2 new file mode 100644 index 0000000000..35abdbe49a --- /dev/null +++ b/ansible/roles/ovn/templates/ovn-northd.json.j2 @@ -0,0 +1,10 @@ +{ + "command": "/usr/bin/ovn-northd -vconsole:emer -vsyslog:err -vfile:info --ovnnb-db={{ ovn_nb_connection }} --ovnsb-db={{ ovn_sb_connection }} --log-file=/var/log/kolla/openvswitch/ovn-northd.log --pidfile=/run/ovn/ovn-northd.pid --unixctl=/run/ovn/ovn-northd.ctl", + "permissions": [ + { + "path": "/var/log/kolla/openvswitch", + "owner": "root:root", + "recurse": true + } + ] +} diff --git a/ansible/roles/ovn/templates/ovn-sb-db.json.j2 b/ansible/roles/ovn/templates/ovn-sb-db.json.j2 new file mode 100644 index 0000000000..5777b1f5ad --- /dev/null +++ b/ansible/roles/ovn/templates/ovn-sb-db.json.j2 @@ -0,0 +1,12 @@ +{% set ovnctl_cmd = '/usr/share/ovn/scripts/ovn-ctl' %} + +{ + "command": "{{ ovnctl_cmd }} run_sb_ovsdb --db-sb-create-insecure-remote=yes --db-sb-addr={{ api_interface_address }} --db-sb-cluster-local-addr={{ api_interface_address }} {% if groups['ovn-sb-db'] | length > 1 and inventory_hostname != groups['ovn-sb-db'][0] %} --db-sb-cluster-remote-addr={{ 'api' | kolla_address(groups['ovn-sb-db'][0]) }} {% endif %} --db-sock=/run/ovn/ovnsb_db.sock --db-sb-pid=/run/ovn/ovnsb_db.pid --db-sb-file=/var/lib/openvswitch/ovn-sb/ovnsb.db --ovn-sb-logfile=/var/log/kolla/openvswitch/ovn-sb-db.log", + "permissions": [ + { + "path": "/var/log/kolla/openvswitch", + "owner": "root:root", + "recurse": true + } + ] +} diff --git a/ansible/site.yml b/ansible/site.yml index 01e443dc23..1e425f7a47 100644 --- a/ansible/site.yml +++ b/ansible/site.yml @@ -60,6 +60,7 @@ - enable_octavia_{{ enable_octavia | bool }} - enable_openvswitch_{{ enable_openvswitch | bool }}_enable_ovs_dpdk_{{ enable_ovs_dpdk | bool }} - enable_outward_rabbitmq_{{ enable_outward_rabbitmq | bool }} + - enable_ovn_{{ enable_ovn | bool }} - enable_panko_{{ enable_panko | bool }} - enable_placement_{{ enable_placement | bool }} - enable_prometheus_{{ enable_prometheus | bool }} @@ -707,6 +708,20 @@ tags: ovs-dpdk, when: "(enable_openvswitch | bool) and (enable_ovs_dpdk | bool)"} +- name: Apply role ovn + gather_facts: false + hosts: + - ovn-controller + - ovn-nb-db + - ovn-northd + - ovn-sb-db + - '&enable_ovn_True' + serial: '{{ kolla_serial|default("0") }}' + roles: + - { role: ovn, + tags: ovn, + when: enable_ovn | bool } + - name: Apply role nova-hyperv gather_facts: false hosts: @@ -728,6 +743,7 @@ - neutron-l3-agent - ironic-neutron-agent - neutron-metadata-agent + - neutron-ovn-metadata-agent - neutron-metering-agent - compute - manila-share diff --git a/doc/source/reference/networking/neutron.rst b/doc/source/reference/networking/neutron.rst index 20af193ecd..1760f349c8 100644 --- a/doc/source/reference/networking/neutron.rst +++ b/doc/source/reference/networking/neutron.rst @@ -38,6 +38,9 @@ To use provider networks in instances you also need to set the following in ``enable_neutron_provider_networks`` ensures ``neutron_external_interface`` is used on hosts in the ``compute`` group. +OpenvSwitch (ml2/ovs) +~~~~~~~~~~~~~~~~~~~~~ + By default ``kolla-ansible`` uses ``openvswitch`` as its underlying network mechanism, you can change that using the ``neutron_plugin_agent`` variable in ``/etc/kolla/globals.yml``: @@ -57,3 +60,23 @@ to using the native OVS firewall driver by employing a configuration override [security_group] firewall_driver = openvswitch +OVN (ml2/ovn) +~~~~~~~~~~~~~ + +In order to use ``OVN`` as mechanism driver for ``neutron``, you need to set +the following: + +.. path /etc/kolla/globals.yml +.. code-block:: yaml + + neutron_plugin_agent: "ovn" + +When using OVN - Kolla-Ansible will not enable distributed floating ip +functionality (not enable external bridges on computes) by default. +To change this behaviour you need to set the following: + +.. path /etc/kolla/globals.yml +.. code-block:: yaml + + neutron_ovn_distributed_fip: "yes" + diff --git a/etc/kolla/globals.yml b/etc/kolla/globals.yml index 1d1eb4db93..663fd9d0a2 100644 --- a/etc/kolla/globals.yml +++ b/etc/kolla/globals.yml @@ -325,6 +325,7 @@ #enable_nova_ssh: "yes" #enable_octavia: "no" #enable_openvswitch: "{{ enable_neutron | bool and neutron_plugin_agent != 'linuxbridge' }}" +#enable_ovn: "{{ enable_neutron | bool and neutron_plugin_agent == 'ovn' }}" #enable_ovs_dpdk: "no" #enable_osprofiler: "no" #enable_panko: "no" @@ -518,6 +519,12 @@ # Valid options are [ none, novnc, spice, rdp ] #nova_console: "novnc" +############################## +# Neutron - networking options +############################## +# Enable distributed floating ip for OVN deployments +#neutron_ovn_distributed_fip: "no" + ################# # Hyper-V options ################# diff --git a/releasenotes/notes/implement-ovn-80b3a73e6c8a44e7.yaml b/releasenotes/notes/implement-ovn-80b3a73e6c8a44e7.yaml new file mode 100644 index 0000000000..2fd23d6d8a --- /dev/null +++ b/releasenotes/notes/implement-ovn-80b3a73e6c8a44e7.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + Implement OVN and integration with Neutron. This includes deployment of: + + * OVN databases (``ovn-sb-db`` and ``ovn-nb-db``) + * Southbound and Northbound databases connector (``ovn-northd``) + * Hypervisor components ``ovn-controller`` and + ``neutron-ovn-metadata-agent`` diff --git a/tests/run.yml b/tests/run.yml index 78eca77131..66251ca282 100644 --- a/tests/run.yml +++ b/tests/run.yml @@ -23,7 +23,7 @@ need_build_image: false build_image_tag: "change_{{ zuul.change | default('none') }}" openstack_core_enabled: "{{ openstack_core_enabled }}" - openstack_core_tested: "{{ scenario in ['core', 'ceph-ansible', 'zun', 'cells', 'swift', 'linuxbridge'] }}" + openstack_core_tested: "{{ scenario in ['core', 'ceph-ansible', 'zun', 'cells', 'swift', 'linuxbridge', 'ovn'] }}" dashboard_enabled: "{{ openstack_core_enabled }}" # TODO(mgoddard): Remove when previous_release is ussuri. playbook_python_version: "{{ '2' if is_upgrade and previous_release == 'train' and not is_centos8 else '3' }}" @@ -423,6 +423,13 @@ chdir: "{{ kolla_ansible_src_dir }}" when: scenario == "masakari" + - name: Run test-ovn.sh script + script: + cmd: test-ovn.sh + executable: /bin/bash + chdir: "{{ kolla_ansible_src_dir }}" + when: scenario == "ovn" + - name: Run test-mariadb.sh script script: cmd: test-mariadb.sh diff --git a/tests/templates/globals-default.j2 b/tests/templates/globals-default.j2 index e1217ba4b2..ff9c42881c 100644 --- a/tests/templates/globals-default.j2 +++ b/tests/templates/globals-default.j2 @@ -130,3 +130,7 @@ openstack_cacert: "/etc/pki/ca-trust/source/anchors/kolla-customca-haproxy-inter {% if scenario == 'linuxbridge' %} neutron_plugin_agent: "linuxbridge" {% endif %} + +{% if scenario == "ovn" %} +neutron_plugin_agent: "ovn" +{% endif %} diff --git a/tests/templates/inventory.j2 b/tests/templates/inventory.j2 index 6b0c01e8cd..adfaa3b7c4 100644 --- a/tests/templates/inventory.j2 +++ b/tests/templates/inventory.j2 @@ -338,6 +338,9 @@ neutron [neutron-metadata-agent:children] neutron +[neutron-ovn-metadata-agent:children] +compute + [neutron-bgp-dragent:children] neutron @@ -818,3 +821,25 @@ control [masakari-monitors:children] compute + +[ovn-controller:children] +ovn-controller-compute +ovn-controller-network + +[ovn-controller-compute:children] +compute + +[ovn-controller-network:children] +network + +[ovn-database:children] +control + +[ovn-northd:children] +ovn-database + +[ovn-nb-db:children] +ovn-database + +[ovn-sb-db:children] +ovn-database diff --git a/tests/test-ovn.sh b/tests/test-ovn.sh new file mode 100755 index 0000000000..bfb2dd99a2 --- /dev/null +++ b/tests/test-ovn.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +set -o xtrace +set -o errexit +set -o pipefail + +# Enable unbuffered output for Ansible in Jenkins. +export PYTHONUNBUFFERED=1 + +function test_ovn_logged { + # Test OVSDB cluster state + if [[ $BASE_DISTRO =~ ^(debian|ubuntu)$ ]]; then + sudo docker exec ovn_nb_db ovs-appctl -t /var/run/openvswitch/ovnnb_db.ctl cluster/status OVN_Northbound + sudo docker exec ovn_sb_db ovs-appctl -t /var/run/openvswitch/ovnsb_db.ctl cluster/status OVN_Southbound + else + sudo docker exec ovn_nb_db ovs-appctl -t /var/run/ovn/ovnnb_db.ctl cluster/status OVN_Northbound + sudo docker exec ovn_sb_db ovs-appctl -t /var/run/ovn/ovnsb_db.ctl cluster/status OVN_Southbound + fi + + # List OVN NB/SB entries + sudo docker exec ovn_northd ovn-nbctl --db "tcp:192.0.2.1:6641,tcp:192.0.2.2:6641,tcp:192.0.2.3:6641" show + sudo docker exec ovn_northd ovn-sbctl --db "tcp:192.0.2.1:6642,tcp:192.0.2.2:6642,tcp:192.0.2.3:6642" show +} + +function test_ovn { + echo "Testing OVN" + test_ovn_logged > /tmp/logs/ansible/test-ovn 2>&1 + result=$? + if [[ $result != 0 ]]; then + echo "Testing OVN failed. See ansible/test-ovn for details" + else + echo "Successfully tested OVN. See ansible/test-ovn for details" + fi + return $result +} + +test_ovn diff --git a/tools/setup_gate.sh b/tools/setup_gate.sh index 7dfae456c8..7db77d4314 100755 --- a/tools/setup_gate.sh +++ b/tools/setup_gate.sh @@ -64,6 +64,10 @@ function prepare_images { GATE_IMAGES+=",^swift" fi + if [[ $SCENARIO == "ovn" ]]; then + GATE_IMAGES+=",^ovn" + fi + if [[ $SCENARIO == "mariadb" ]]; then GATE_IMAGES="^cron,^fluentd,^haproxy,^keepalived,^kolla-toolbox,^mariadb" fi diff --git a/zuul.d/base.yaml b/zuul.d/base.yaml index 868f12743b..225a60f000 100644 --- a/zuul.d/base.yaml +++ b/zuul.d/base.yaml @@ -158,3 +158,14 @@ - ^tests/test-core-openstack.sh vars: scenario: linuxbridge + +- job: + name: kolla-ansible-ovn-base + parent: kolla-ansible-base + voting: false + files: + - ^ansible/roles/(ovn|neutron)/ + - ^tests/test-ovn.sh + - ^tests/test-core-openstack.sh + vars: + scenario: ovn diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml index 24bba6cb76..4340d094b8 100644 --- a/zuul.d/jobs.yaml +++ b/zuul.d/jobs.yaml @@ -259,3 +259,19 @@ vars: base_distro: ubuntu install_type: source + +- job: + name: kolla-ansible-centos8-source-ovn + parent: kolla-ansible-ovn-base + nodeset: kolla-ansible-centos8-multi + vars: + base_distro: centos + install_type: source + +- job: + name: kolla-ansible-ubuntu-source-ovn + parent: kolla-ansible-ovn-base + nodeset: kolla-ansible-bionic-multi + vars: + base_distro: ubuntu + install_type: source diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml index a06e55ea30..bfa83de8bd 100644 --- a/zuul.d/project.yaml +++ b/zuul.d/project.yaml @@ -38,6 +38,8 @@ - kolla-ansible-centos8-source-upgrade-ceph-ansible - kolla-ansible-ubuntu-source-upgrade-ceph-ansible - kolla-ansible-ubuntu-source-linuxbridge + - kolla-ansible-centos8-source-ovn + - kolla-ansible-ubuntu-source-ovn check-arm64: jobs: - kolla-ansible-debian-source-aarch64