heat_template_version: wallaby description: > OpenStack containerized Ovn Controller agent. parameters: RootStackName: description: The name of the stack/plan. type: string EndpointMap: default: {} description: Mapping of service endpoint -> protocol. Typically set via parameter_defaults in the resource registry. type: json ServiceNetMap: default: {} description: Mapping of service_name -> network name. Typically set via parameter_defaults in the resource registry. Use parameter_merge_strategies to merge it with the defaults. type: json ServiceData: default: {} description: Dictionary packing service data type: json ContainerOvnControllerImage: description: image type: string tags: - role_specific ContainerOvnControllerConfigImage: description: The container image to use for the ovn_controller config_volume type: string tags: - role_specific RoleName: default: '' description: Role name on which the service is applied type: string RoleParameters: default: {} description: Parameters specific to the role type: json DeployIdentifier: default: '' type: string description: > Setting this to a unique value will re-run any deployment tasks which perform configuration on a Heat stack-update. OVNSouthboundServerPort: description: Port of the Southbound DB Server type: number default: 6642 NeutronBridgeMappings: description: > The OVS logical->physical bridge mappings to use. See the Neutron documentation for details. Defaults to mapping br-ex - the external bridge on hosts - to a physical name 'datacentre' which can be used to create provider networks (and we use this for the default floating network) - if changing this either use different post-install network scripts or be sure to keep 'datacentre' as a mapping network name. type: comma_delimited_list default: "datacentre:br-ex" tags: - role_specific EnableVLANTransparency: default: false description: > If True, then allow plugins that support it to create VLAN transparent networks. type: boolean OVNEncapType: description: > Type of encapsulation used in OVN. It can be "geneve" or "vxlan". type: string default: "geneve" constraints: - allowed_values: ["geneve", "vxlan"] OVNIntegrationBridge: description: > Name of the OVS bridge to use as integration bridge by OVN Controller. type: string default: "br-int" OVNMetadataEnabled: description: Whether Metadata Service has to be enabled type: boolean default: true OVNAvailabilityZone: description: The az options to configure in ovs db. eg. ['az-0', 'az-1', 'az-2'] type: comma_delimited_list default: [] tags: - role_specific OVNCMSOptions: description: The CMS options to configure in ovs db type: string default: "" tags: - role_specific OvsHwOffload: default: false description: | Enable OVS Hardware Offload. This feature supported from OVS 2.8.0 type: boolean tags: - role_specific OVNRemoteProbeInterval: description: Probe interval in ms type: number default: 60000 EnableInternalTLS: type: boolean default: false InternalTLSCAFile: default: '/etc/ipa/ca.crt' type: string description: Specifies the default CA cert to use if TLS is used for services in the internal network. OVNOpenflowProbeInterval: description: > The inactivity probe interval of the OpenFlow connection to the OpenvSwitch integration bridge, in seconds. type: number default: 60 CertificateKeySize: type: string default: '2048' description: Specifies the private key size used when creating the certificate. ContainerOvnCertificateKeySize: type: string default: '' description: Override the private key size used when creating the certificate for this service OVNContainerCpusetCpus: description: > Limit the specific CPUs or cores a container can use. It can be specified as a single core (ex. 0), as a comma-separated list (ex. 0,1), as a range (ex. 0-3) or a combination if previous methods (ex 0-3,7,11-15). The selected cores should be isolated from guests and hypervisor in order to obtain best possible performance. type: string default: '' tags: - role_specific OVNStaticBridgeMacMappings: type: json default: {} description: | Static OVN Bridge MAC address mappings. Unique OVN bridge mac addresses is dynamically allocated by creating neutron ports. When neutron isn't available, for instance in the standalone deployment, use this parameter to provide static OVN bridge mac addresses. For example: controller-0: datacenter: 00:00:5E:00:53:00 provider: 00:00:5E:00:53:01 compute-0: datacenter: 00:00:5E:00:54:00 provider: 00:00:5E:00:54:01 tags: - role_specific AuthCloudName: description: Entry in clouds.yaml to use for authentication type: string default: "" OVNControllerUpdateTimeout: description: > During update, how long we wait for the container to be updated, in seconds. type: number default: 600 conditions: auth_cloud_name_set: not: {equals: [{get_param: AuthCloudName}, ""]} ovn_cpu_set: or: - not: {equals: [{get_param: OVNContainerCpusetCpus}, '']} - not: {equals: [{get_param: [RoleParameters, OVNContainerCpusetCpus]}, '' ]} key_size_override_set: not: {equals: [{get_param: ContainerOvnCertificateKeySize}, '']} az_ovn_unset: {equals: [{get_param: OVNAvailabilityZone}, []]} resources: ContainersCommon: type: ../containers-common.yaml # Merging role-specific parameters (RoleParameters) with the default parameters. # RoleParameters will have the precedence over the default parameters. RoleParametersValue: type: OS::Heat::Value properties: type: json value: map_replace: - map_replace: - ovn::controller::ovn_bridge_mappings: NeutronBridgeMappings ovn::controller::ovn_cms_options: if: - az_ovn_unset - OVNCMSOptions - list_join: - '' - - OVNCMSOptions - ",availability-zones=" - {get_param: OVNAvailabilityZone} vswitch::ovs::enable_hw_offload: OvsHwOffload container_cpuset_cpus: OVNContainerCpusetCpus ContainerOvnControllerImage: ContainerOvnControllerImage ContainerOvnControllerConfigImage: ContainerOvnControllerConfigImage - values: {get_param: [RoleParameters]} - values: NeutronBridgeMappings: {get_param: NeutronBridgeMappings} OVNCMSOptions: {get_param: OVNCMSOptions} OvsHwOffload: {get_param: OvsHwOffload} OVNContainerCpusetCpus: {get_param: OVNContainerCpusetCpus} ContainerOvnControllerImage: {get_param: ContainerOvnControllerImage} ContainerOvnControllerConfigImage: {get_param: ContainerOvnControllerConfigImage} OVNBridgeMappingsValue: type: OS::Heat::Value properties: type: json value: map_replace: - map_replace: - ovn_bridge_mappings: NeutronBridgeMappings ovn_static_bridge_mac_mappings: OVNStaticBridgeMacMappings - values: {get_param: [RoleParameters]} - values: NeutronBridgeMappings: {get_param: NeutronBridgeMappings} OVNStaticBridgeMacMappings: {get_param: OVNStaticBridgeMacMappings} outputs: role_data: description: Role data for the Ovn Controller agent. value: service_name: ovn_controller firewall_rules: '118 neutron vxlan networks': proto: 'udp' dport: 4789 '119 neutron geneve networks': proto: 'udp' dport: 6081 '120 neutron geneve networks no conntrack': proto: 'udp' dport: 6081 table: 'raw' chain: 'OUTPUT' jump: 'NOTRACK' action: 'append' state: [] '121 neutron geneve networks no conntrack': proto: 'udp' dport: 6081 table: 'raw' chain: 'PREROUTING' jump: 'NOTRACK' action: 'append' state: [] config_settings: map_merge: - get_attr: [RoleParametersValue, value] - ovn::southbound::port: {get_param: OVNSouthboundServerPort} ovn::controller::ovn_encap_ip: str_replace: template: "%{lookup('$NETWORK')}" params: $NETWORK: {get_param: [ServiceNetMap, NeutronTenantNetwork]} ovn::controller::ovn_encap_type: {get_param: OVNEncapType} ovn::controller::ovn_bridge: {get_param: OVNIntegrationBridge} ovn::controller::hostname: "%{lookup('fqdn_canonical')}" ovn::controller::ovn_remote_probe_interval: {get_param: OVNRemoteProbeInterval} ovn::controller::ovn_openflow_probe_interval: {get_param: OVNOpenflowProbeInterval} nova::compute::force_config_drive: {get_param: OVNMetadataEnabled} ovn::controller::ovn_monitor_all: true tripleo::profile::base::neutron::agents::ovn::protocol: if: - {get_param: EnableInternalTLS} - 'ssl' vswitch::ovs::vlan_limit: if: - {get_param: EnableVLANTransparency} - 0 service_config_settings: {} # BEGIN DOCKER SETTINGS puppet_config: puppet_tags: vs_config,exec config_volume: ovn_controller step_config: | include tripleo::profile::base::neutron::agents::ovn config_image: {get_attr: [RoleParametersValue, value, ContainerOvnControllerConfigImage]} # We need to mount /run for puppet_config step. This is because # puppet-vswitch runs the commands "ovs-vsctl set open_vswitch . external_ids:..." # to configure the required parameters in ovs db which will be read # by ovn-controller. And ovs-vsctl talks to the ovsdb-server (hosting conf.db) # on the unix domain socket - /run/openvswitch/db.sock volumes: - /lib/modules:/lib/modules:ro - /run/openvswitch:/run/openvswitch:shared,z # Needed for creating module load files - /etc/sysconfig/modules:/etc/sysconfig/modules kolla_config: /var/lib/kolla/config_files/ovn_controller.json: command: list_join: - ' ' - - /usr/bin/ovn-controller --pidfile --log-file unix:/run/openvswitch/db.sock - if: - {get_param: EnableInternalTLS} - list_join: - ' ' - - -p /etc/pki/tls/private/ovn_controller.key -c /etc/pki/tls/certs/ovn_controller.crt -C - {get_param: InternalTLSCAFile} permissions: - path: /var/log/openvswitch owner: root:root recurse: true - path: /var/log/ovn owner: root:root recurse: true metadata_settings: if: - {get_param: EnableInternalTLS} - - service: ovn_controller network: {get_param: [ServiceNetMap, OvnDbsNetwork]} type: node docker_config: step_4: configure_cms_options: start_order: 0 detach: false net: host privileged: true user: root command: ['/bin/bash', '-c', 'CMS_OPTS=$(hiera ovn::controller::ovn_cms_options -c /etc/puppet/hiera.yaml); if [ X"$CMS_OPTS" != X ]; then ovs-vsctl set open . external_ids:ovn-cms-options=$CMS_OPTS;else ovs-vsctl remove open . external_ids ovn-cms-options; fi'] image: &ovn_controller_image {get_attr: [RoleParametersValue, value, ContainerOvnControllerImage]} volumes: list_concat: - {get_attr: [ContainersCommon, volumes]} - - /lib/modules:/lib/modules:ro - /run/openvswitch:/run/openvswitch:shared,z environment: TRIPLEO_DEPLOY_IDENTIFIER: {get_param: DeployIdentifier} ovn_controller: map_merge: - start_order: 1 image: *ovn_controller_image net: host privileged: true user: root restart: always depends_on: - openvswitch.service - if: - ovn_cpu_set - cpuset_cpus: {get_attr: [RoleParametersValue, value, container_cpuset_cpus]} - healthcheck: test: list_join: - ' ' - - '/openstack/healthcheck' - yaql: expression: str($.data.port) data: port: {get_param: OVNSouthboundServerPort} volumes: list_concat: - - /var/lib/kolla/config_files/ovn_controller.json:/var/lib/kolla/config_files/config.json:ro - /lib/modules:/lib/modules:ro # TODO(numans): This is temporary. Mount /run/openvswitch once # openvswitch systemd script is fixed to not delete /run/openvswitch # folder in the host when openvswitch service is stopped. - /run:/run - /var/lib/openvswitch/ovn:/run/ovn:shared,z - /var/log/containers/openvswitch:/var/log/openvswitch:z - /var/log/containers/openvswitch:/var/log/ovn:z - if: - {get_param: EnableInternalTLS} - - list_join: - ':' - - {get_param: InternalTLSCAFile} - {get_param: InternalTLSCAFile} - 'ro' - /etc/pki/tls/certs/ovn_controller.crt:/etc/pki/tls/certs/ovn_controller.crt - /etc/pki/tls/private/ovn_controller.key:/etc/pki/tls/private/ovn_controller.key environment: KOLLA_CONFIG_STRATEGY: COPY_ALWAYS deploy_steps_tasks: - name: Certificate generation when: - step|int == 1 - enable_internal_tls block: - include_role: name: linux-system-roles.certificate vars: certificate_requests: - name: ovn_controller dns: str_replace: template: "{{fqdn_$NETWORK}}" params: $NETWORK: {get_param: [ServiceNetMap, OvnDbsNetwork]} principal: str_replace: template: "ovn_controller/{{fqdn_$NETWORK}}@{{idm_realm}}" params: $NETWORK: {get_param: [ServiceNetMap, OvnDbsNetwork]} key_size: if: - key_size_override_set - {get_param: ContainerOvnCertificateKeySize} - {get_param: CertificateKeySize} ca: ipa host_prep_tasks: - name: create persistent directories file: path: "{{ item.path }}" state: directory setype: "{{ item.setype }}" mode: "{{ item.mode|default(omit) }}" with_items: - { 'path': /var/log/containers/openvswitch, 'setype': container_file_t, 'mode': '0750' } - { 'path': /var/lib/openvswitch/ovn, 'setype': container_file_t } - name: enable virt_sandbox_use_netlink for healthcheck seboolean: name: virt_sandbox_use_netlink persistent: true state: true when: - ansible_facts.selinux is defined - ansible_facts.selinux.status == "enabled" - name: Copy in cleanup script copy: content: {get_file: ../neutron/neutron-cleanup} dest: '/usr/libexec/neutron-cleanup' force: true mode: '0755' - name: Copy in cleanup service copy: content: {get_file: ../neutron/neutron-cleanup.service} dest: '/usr/lib/systemd/system/neutron-cleanup.service' force: true - name: Enabling the cleanup service service: name: neutron-cleanup enabled: true external_deploy_tasks: - when: - step|int == 0 name: ovn_controller_external_deploy_init block: - name: str_replace: template: create ovn mac address for $ROLE_NAME role nodes params: $ROLE_NAME: {get_param: RoleName} tripleo_ovn_mac_addresses: playbook_dir: "{{ playbook_dir }}" stack_name: {get_param: RootStackName} role_name: {get_param: RoleName} server_resource_names: str_replace: template: '{{ groups["$ROLE_NAME"] }}' params: $ROLE_NAME: {get_param: RoleName} ovn_bridge_mappings: {get_attr: [OVNBridgeMappingsValue, value, ovn_bridge_mappings]} ovn_static_bridge_mac_mappings: {get_attr: [OVNBridgeMappingsValue, value, ovn_static_bridge_mac_mappings]} external_update_tasks: - name: OVN Container image used debug: msg: "ovn container will be using {{ image }}" vars: image: {get_param: ContainerOvnControllerConfigImage} when: step|int == 1 tags: ovn - name: Update ovn_controller. when: step|int == 1 tags: ovn become: true loop: "{{ groups['ovn_controller'] }}" delegate_to: "{{ item }}" async: {get_param: OVNControllerUpdateTimeout} poll: 0 register: ovn_controller_update ignore_errors: true tripleo_container_manage: config_dir: "/var/lib/tripleo-config/container-startup-config/step_4" config_patterns: 'ovn_controller.json' config_id: - 'tripleo_step4' container_cli: "{{ container_cli }}" log_path: "{{ container_log_stdout_path }}" debug: "{{ enable_debug | bool }}" config_overrides: ovn_controller: image: {get_param: ContainerOvnControllerConfigImage} - name: Was the ovn_controller successful. when: - step|int == 1 - "'results' in ovn_controller_update" tags: ovn become: true delegate_to: "{{ async_result_item.item }}" async_status: jid: "{{ async_result_item.ansible_job_id }}" loop: "{{ovn_controller_update.results }}" loop_control: loop_var: "async_result_item" register: async_poll_results until: async_poll_results.finished retries: {get_param: OVNControllerUpdateTimeout} upgrade_tasks: [] scale_tasks: - when: - step|int == 1 - container_cli == 'podman' tags: down become: true environment: OS_CLOUD: if: - auth_cloud_name_set - {get_param: AuthCloudName} - {get_param: RootStackName} block: # Some tasks are running from the Undercloud which has # the OpenStack clients installed. - name: Get neutron agents ID command: openstack network agent list --column ID --column Host --column Binary --format yaml register: neutron_agents_result delegate_to: "{{ groups['Undercloud'] | first }}" check_mode: false changed_when: false - name: Filter only current host set_fact: neutron_agents: "{{ neutron_agents_result.stdout | from_yaml | selectattr('Host', 'match', ansible_facts['fqdn'] ~ '.*') | list }}" delegate_to: "{{ groups['Undercloud'] | first }}" check_mode: false - name: Deleting OVN agents block: - name: Stop OVN containers loop: - tripleo_ovn_controller - tripleo_ovn_metadata_agent service: name: "{{ item }}" state: stopped enabled: false become: true register: stop_containers failed_when: "('msg' in stop_containers and 'Could not find the requested service' not in stop_containers.msg) or ('rc' in stop_containers and stop_containers.rc != 0)" - name: Delete neutron agents loop: "{{ neutron_agents }}" loop_control: loop_var: agent label: "{{ agent.Host }}/{{ agent.Binary }}" command: openstack network agent delete {{ agent.ID }} delegate_to: "{{ groups['Undercloud'] | first }}" check_mode: false