heat_template_version: wallaby description: > OpenStack containerized OVN DBs service in cluster mode parameters: ContainerOvnNbDbImage: description: image type: string tags: - role_specific ContainerOvnSbDbImage: description: image type: string tags: - role_specific ContainerOvnNorthdImage: description: image type: string tags: - role_specific ContainerNeutronApiImage: description: image type: string tags: - role_specific ContainerOvnMetadataImage: description: image type: string tags: - role_specific EndpointMap: default: {} description: Mapping of service endpoint -> protocol. Typically set via parameter_defaults in the resource registry. type: json ServiceData: default: {} description: Dictionary packing service data type: json ServiceNetMap: default: {} description: Mapping of service_name -> network name. Typically set via parameter_defaults in the resource registry. This mapping overrides those in ServiceNetMapDefaults. type: json RoleName: default: '' description: Role name on which the service is applied type: string RoleParameters: default: {} description: Parameters specific to the role type: json OVNOvsdbProbeInterval: description: Probe interval in ms for the OVSDB session type: number default: 60000 OVNNorthboundServerPort: description: Port of the OVN Northbound DB server type: number default: 6641 OVNSouthboundServerPort: description: Port of the OVN Southbound DB server type: number default: 6642 OVNNorthboundClusterPort: description: Cluster port of the OVN Northbound DB server type: number default: 6643 OVNSouthboundClusterPort: description: Cluster port of the OVN Southbound DB server type: number default: 6644 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. CertificateKeySize: type: string default: '2048' description: Specifies the private key size used when creating the certificate. OvnDBSCertificateKeySize: type: string default: '' description: Override the private key size used when creating the certificate for this service conditions: key_size_override_unset: {equals: [{get_param: OvnDBSCertificateKeySize}, '']} is_ipv6: equals: - {get_param: [ServiceData, net_ip_version_map, {get_param: [ServiceNetMap, OvnDbsNetwork]}]} - 6 resources: ContainersCommon: type: ../containers-common.yaml RoleParametersValue: type: OS::Heat::Value properties: type: json value: map_replace: - map_replace: - ContainerOvnNbDbImage: ContainerOvnNbDbImage ContainerOvnSbDbImage: ContainerOvnSbDbImage ContainerOvnNorthdImage: ContainerOvnNorthdImage ContainerNeutronApiImage: ContainerNeutronApiImage ContainerOvnMetadataImage: ContainerOvnMetadataImage - values: {get_param: [RoleParameters]} - values: ContainerOvnNbDbImage: {get_param: ContainerOvnNbDbImage} ContainerOvnSbDbImage: {get_param: ContainerOvnSbDbImage} ContainerOvnNorthdImage: {get_param: ContainerOvnNorthdImage} ContainerNeutronApiImage: {get_param: ContainerNeutronApiImage} ContainerOvnMetadataImage: {get_param: ContainerOvnMetadataImage} outputs: role_data: description: Role data for the OVN multi-active cluster role. value: service_name: ovn_dbs firewall_rules: map_merge: repeat: for_each: <%net_cidr%>: get_param: - ServiceData - net_cidr_map - {get_param: [ServiceNetMap, OvnDbsNetwork]} template: '121 OVN DB server and cluster ports for <%net_cidr%>': proto: 'tcp' source: <%net_cidr%> dport: - {get_param: OVNNorthboundServerPort} - {get_param: OVNSouthboundServerPort} - {get_param: OVNNorthboundClusterPort} - {get_param: OVNSouthboundClusterPort} kolla_config: /var/lib/kolla/config_files/ovn_cluster_north_db_server.json: command: bash -c $* -- eval source /etc/sysconfig/ovn_cluster; exec /usr/local/bin/start-nb-db-server ${OVN_NB_DB_OPTS} config_files: &ovn_dbs_kolla_config_files - source: "/var/lib/kolla/config_files/src/*" dest: "/" merge: true preserve_properties: true - source: "/var/lib/kolla/config_files/src-tls/*" dest: "/" merge: true preserve_properties: true optional: true permissions: &ovn_dbs_kolla_permissions - path: /var/log/openvswitch owner: root:root recurse: true - path: /var/log/ovn owner: root:root recurse: true /var/lib/kolla/config_files/ovn_cluster_south_db_server.json: command: bash -c $* -- eval source /etc/sysconfig/ovn_cluster; exec /usr/local/bin/start-sb-db-server ${OVN_SB_DB_OPTS} config_files: *ovn_dbs_kolla_config_files permissions: *ovn_dbs_kolla_permissions /var/lib/kolla/config_files/ovn_cluster_northd.json: command: bash -c $* -- eval source /etc/sysconfig/ovn_cluster; exec /usr/bin/ovn-northd ${OVN_NORTHD_OPTS} config_files: *ovn_dbs_kolla_config_files permissions: *ovn_dbs_kolla_permissions docker_config: step_0: ovn_cluster_north_db_server: start_order: 0 image: {get_attr: [RoleParametersValue, value, ContainerOvnNbDbImage]} net: host privileged: false restart: always volumes: list_concat: - {get_attr: [ContainersCommon, volumes]} - - /var/lib/kolla/config_files/ovn_cluster_north_db_server.json:/var/lib/kolla/config_files/config.json:ro - /lib/modules:/lib/modules:ro - /var/lib/openvswitch/ovn:/var/lib/openvswitch:shared,z - /var/lib/openvswitch/ovn:/run/openvswitch:shared,z - /var/log/containers/openvswitch:/var/log/openvswitch:z - /var/lib/openvswitch/ovn:/var/lib/ovn:shared,z - /var/lib/openvswitch/ovn:/etc/openvswitch:shared,z - /var/lib/openvswitch/ovn:/etc/ovn:shared,z - /var/lib/openvswitch/ovn:/run/ovn:shared,z - /var/log/containers/openvswitch:/var/log/ovn:z - /var/lib/config-data/ansible-generated/ovn:/var/lib/kolla/config_files/src:ro - if: - {get_param: EnableInternalTLS} - - /etc/pki/tls/private/ovn_dbs.key:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/ovn_dbs.key:ro - /etc/pki/tls/certs/ovn_dbs.crt:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/ovn_dbs.crt:ro - null environment: KOLLA_CONFIG_STRATEGY: COPY_ALWAYS ovn_cluster_south_db_server: start_order: 0 image: {get_attr: [RoleParametersValue, value, ContainerOvnSbDbImage]} net: host privileged: false restart: always volumes: list_concat: - {get_attr: [ContainersCommon, volumes]} - - /var/lib/kolla/config_files/ovn_cluster_south_db_server.json:/var/lib/kolla/config_files/config.json:ro - /lib/modules:/lib/modules:ro - /var/lib/openvswitch/ovn:/var/lib/openvswitch:shared,z - /var/lib/openvswitch/ovn:/run/openvswitch:shared,z - /var/log/containers/openvswitch:/var/log/openvswitch:z - /var/lib/openvswitch/ovn:/var/lib/ovn:shared,z - /var/lib/openvswitch/ovn:/etc/openvswitch:shared,z - /var/lib/openvswitch/ovn:/etc/ovn:shared,z - /var/lib/openvswitch/ovn:/run/ovn:shared,z - /var/log/containers/openvswitch:/var/log/ovn:z - /var/lib/config-data/ansible-generated/ovn:/var/lib/kolla/config_files/src:ro - if: - {get_param: EnableInternalTLS} - - /etc/pki/tls/private/ovn_dbs.key:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/ovn_dbs.key:ro - /etc/pki/tls/certs/ovn_dbs.crt:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/ovn_dbs.crt:ro - null environment: KOLLA_CONFIG_STRATEGY: COPY_ALWAYS ovn_cluster_northd: start_order: 2 image: {get_attr: [RoleParametersValue, value, ContainerOvnNorthdImage]} net: host privileged: false restart: always healthcheck: test: /openstack/healthcheck volumes: list_concat: - {get_attr: [ContainersCommon, volumes]} - - /var/lib/kolla/config_files/ovn_cluster_northd.json:/var/lib/kolla/config_files/config.json:ro - /lib/modules:/lib/modules:ro - /var/lib/openvswitch/ovn:/run/openvswitch:shared,z - /var/log/containers/openvswitch:/var/log/openvswitch:z - /var/lib/openvswitch/ovn:/run/ovn:shared,z - /var/log/containers/openvswitch:/var/log/ovn:z - /var/lib/config-data/ansible-generated/ovn:/var/lib/kolla/config_files/src:ro - if: - {get_param: EnableInternalTLS} - - /etc/pki/tls/private/ovn_dbs.key:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/ovn_dbs.key:ro - /etc/pki/tls/certs/ovn_dbs.crt:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/ovn_dbs.crt:ro - null environment: KOLLA_CONFIG_STRATEGY: COPY_ALWAYS global_config_settings: ovn_db_clustered: true metadata_settings: if: - {get_param: EnableInternalTLS} - - service: ovn_dbs network: {get_param: [ServiceNetMap, OvnDbsNetwork]} type: node - null host_prep_tasks: - name: create persistent directories file: path: "{{ item.path }}" state: directory setype: "{{ item.setype }}" mode: "{{ item.mode|default(omit) }}" loop: - { 'path': /var/log/containers/openvswitch, 'setype': container_file_t, 'mode': '0750' } - { 'path': /var/lib/openvswitch/ovn, 'setype': container_file_t } deploy_steps_tasks: - name: set is_ovn_dbs_bootstrap_node fact set_fact: is_ovn_dbs_bootstrap_node={{ovn_dbs_short_bootstrap_node_name|lower == ansible_facts['hostname']|lower}} when: - step|int == 1 - name: Populate ansible service facts so we can check for pacemaker service ansible.builtin.service_facts: when: - is_ovn_dbs_bootstrap_node | bool - step|int == 1 - name: Remove OVNDBs from Pacemaker when: - step|int == 1 - is_ovn_dbs_bootstrap_node | bool - "ansible_facts['services']['pacemaker.service']['state'] | default('unknown') == 'running'" block: - name: Fetch ovn-dbs-bundle shell: | pcs status |grep ovn-dbs-bundle ||true register: ovn_dbs - name: Fetch ovn VIP shell: | pcs constraint config |grep "with ovn-dbs-bundle" |awk '{print $1}' register: ovn_vip - name: Remove OVNDBs from pacemaker pacemaker_resource: resource: ovn-dbs-bundle state: delete when: ovn_dbs.stdout |length > 0 - name: Remove OVNDBs VIP from pacemaker pacemaker_resource: resource: "{{ ovn_vip.stdout }}" state: delete when: ovn_vip.stdout |length > 0 - name: Clean up pacemaker remote nodes cache shell: | pcs cluster node clear ovn-dbs-bundle-0 pcs cluster node clear ovn-dbs-bundle-1 pcs cluster node clear ovn-dbs-bundle-2 crm_attribute --name OVN_REPL_INFO --delete - name: Remove pacemaker attributes shell: | pcs node attribute "{{ item }}" ovn-dbs-role= || true loop: "{{ ovn_dbs_short_node_names }}" - name: Prepare OVN cluster when: step|int == 1 block: - name: Certificate generation when: enable_internal_tls | bool block: - include_role: name: linux-system-roles.certificate vars: certificate_requests: - name: ovn_dbs dns: str_replace: template: "{{fqdn_$NETWORK}}" params: $NETWORK: {get_param: [ServiceNetMap, OvnDbsNetwork]} principal: str_replace: template: "ovn_dbs/{{fqdn_$NETWORK}}@{{idm_realm}}" params: $NETWORK: {get_param: [ServiceNetMap, OvnDbsNetwork]} key_size: if: - key_size_override_unset - {get_param: CertificateKeySize} - {get_param: OvnDBSCertificateKeySize} ca: ipa - block: &configure_ovn_db_northd - name: Configure OVN DBs and northd include_role: name: tripleo_ovn_cluster vars: tripleo_ovn_cluster_dbs_protocol: "{{ enable_internal_tls | ternary('ssl', 'tcp', 'tcp') }}" tripleo_ovn_cluster_network: {get_param: [ServiceNetMap, OvnDbsNetwork]} tripleo_ovn_cluster_nb_db_port: {get_param: OVNNorthboundServerPort} tripleo_ovn_cluster_sb_db_port: {get_param: OVNSouthboundServerPort} tripleo_ovn_cluster_nb_local_port: {get_param: OVNNorthboundClusterPort} tripleo_ovn_cluster_nb_remote_port: {get_param: OVNNorthboundClusterPort} tripleo_ovn_cluster_sb_local_port: {get_param: OVNSouthboundClusterPort} tripleo_ovn_cluster_sb_remote_port: {get_param: OVNSouthboundClusterPort} tripleo_ovn_cluster_northd_ssl_ca_cert: {get_param: InternalTLSCAFile} tripleo_ovn_cluster_sb_ssl_ca_cert: {get_param: InternalTLSCAFile} tripleo_ovn_cluster_nb_ssl_ca_cert: {get_param: InternalTLSCAFile} - name: Start OVN DBs and northd containers (bootstrap node) when: - step|int == 3 - is_ovn_dbs_bootstrap_node | bool block: &ovn_dbs_start_containers - block: &ovn_dbs_containers - name: Start OVN container include_role: name: tripleo_container_manage vars: tripleo_container_manage_config: "/var/lib/tripleo-config/container-startup-config/step_0" tripleo_container_manage_config_id: "{{ ovn_container }}" tripleo_container_manage_config_patterns: "{{ ovn_container }}.json" loop: - ovn_cluster_north_db_server - ovn_cluster_south_db_server - ovn_cluster_northd loop_control: loop_var: ovn_container - name: Set NB connection become: yes shell: | podman exec ovn_cluster_north_db_server bash -c "ovn-nbctl --no-leader-only --inactivity-probe={{ tripleo_ovn_cluster_probe_interval }} set-connection p{{ tripleo_ovn_cluster_dbs_protocol }}:{{ tripleo_ovn_cluster_nb_db_port }}:{{ tripleo_ovn_cluster_dbs_addr }}" register: nb_result retries: 20 delay: 5 until: nb_result.rc == 0 when: - is_ovn_dbs_bootstrap_node | bool vars: tripleo_ovn_cluster_network: {get_param: [ServiceNetMap, OvnDbsNetwork]} tripleo_ovn_cluster_nb_db_port: {get_param: OVNNorthboundServerPort} tripleo_ovn_cluster_dbs_protocol: "{{ enable_internal_tls | ternary('ssl', 'tcp', 'tcp') }}" tripleo_ovn_cluster_dbs_addr: if: - is_ipv6 - "[::]" - "0.0.0.0" tripleo_ovn_cluster_probe_interval: {get_param: OVNOvsdbProbeInterval} - name: Set SB connection become: yes shell: | podman exec ovn_cluster_south_db_server bash -c "ovn-sbctl --no-leader-only --inactivity-probe={{ tripleo_ovn_cluster_probe_interval }} set-connection p{{ tripleo_ovn_cluster_dbs_protocol }}:{{ tripleo_ovn_cluster_sb_db_port }}:{{ tripleo_ovn_cluster_dbs_addr }}" register: sb_result retries: 20 delay: 5 until: sb_result.rc == 0 when: - is_ovn_dbs_bootstrap_node | bool vars: tripleo_ovn_cluster_network: {get_param: [ServiceNetMap, OvnDbsNetwork]} tripleo_ovn_cluster_sb_db_port: {get_param: OVNSouthboundServerPort} tripleo_ovn_cluster_dbs_protocol: "{{ enable_internal_tls | ternary('ssl', 'tcp', 'tcp') }}" tripleo_ovn_cluster_dbs_addr: if: - is_ipv6 - "[::]" - "0.0.0.0" tripleo_ovn_cluster_probe_interval: {get_param: OVNOvsdbProbeInterval} - name: Start OVN DBs and northd containers (non-bootstrap nodes) when: - step|int == 4 - not is_ovn_dbs_bootstrap_node | bool block: *ovn_dbs_start_containers external_update_tasks: - name: Run ovndbs update tags: - ovn - ovn_image when: step|int == 2 block: - name: Get OVN_Northbound cluster leader become: yes shell: | podman exec -u root ovn_cluster_north_db_server ovs-appctl -t /var/run/ovn/ovnnb_db.ctl cluster/status OVN_Northbound | grep 'Leader: ' register: ovn_nb_dbs_cluster_leader loop: "{{groups['ovn_dbs'] | difference(groups['excluded_overcloud']) }}" delegate_to: "{{ item }}" - set_fact: ovn_nb_leader: "{{ ovn_nb_dbs_cluster_leader| json_query(\"results[?contains(stdout,'Leader: self')].item\") }}" - name: Graceful stop OVN NB leader container delegate_to: "{{ ovn_nb_leader[0] }}" become: true shell: | podman exec -u root ovn_cluster_north_db_server ovs-appctl -t /var/run/ovn/ovnnb_db.ctl exit - name: Start OVN NB leader container delegate_to: "{{ ovn_nb_leader[0] }}" become: true tripleo_container_manage: config_dir: "/var/lib/tripleo-config/container-startup-config/step_0" config_id: - 'ovn_cluster_north_db_server' config_patterns: "*ovn_cluster_north_db_server.json" config_overrides: ".*ovn_cluster_north_db_server": image: {get_param: ContainerOvnNbDbImage} name: "ovn_cluster_north_db_server" - name: Get OVN_Southbound cluster leader become: yes shell: | sudo podman exec -u root ovn_cluster_south_db_server ovs-appctl -t /var/run/ovn/ovnsb_db.ctl cluster/status OVN_Southbound | grep 'Leader: ' register: ovn_sb_dbs_cluster_leader loop: "{{groups['ovn_dbs'] | difference(groups['excluded_overcloud']) }}" delegate_to: "{{ item }}" - set_fact: ovn_sb_leader: "{{ ovn_sb_dbs_cluster_leader | json_query(\"results[?contains(stdout,'Leader: self')].item\") }}" - name: Graceful stop OVN SB leader container delegate_to: "{{ ovn_sb_leader[0] }}" become: true shell: | sudo podman exec -u root ovn_cluster_south_db_server ovs-appctl -t /var/run/ovn/ovnsb_db.ctl exit - name: Start OVN SB leader container delegate_to: "{{ ovn_sb_leader[0] }}" become: true tripleo_container_manage: config_dir: "/var/lib/tripleo-config/container-startup-config/step_0" config_id: - 'ovn_cluster_south_db_server' config_patterns: "*ovn_cluster_south_db_server.json" config_overrides: ".*ovn_cluster_south_db_server": image: {get_param: ContainerOvnSbDbImage} name: "ovn_cluster_south_db_server" - name: Loop on OVN_Northbound cluster for leader election become: yes shell: | podman exec -u root ovn_cluster_north_db_server ovs-appctl -t /var/run/ovn/ovnnb_db.ctl cluster/status OVN_Northbound | grep 'Leader: ' register: wait_leader delegate_to: "{{ groups['ovn_dbs'] | difference(groups['excluded_overcloud']) | difference(ovn_nb_leader[0]) | first }}" failed_when: "'Leader: unknown' in wait_leader.stdout or wait_leader.stderr != ''" until: "'Leader: unknown' not in wait_leader.stdout and wait_leader.stderr == ''" retries: 10 delay: 5 - name: Loop on OVN_Southbound cluster for leader election become: yes shell: | podman exec -u root ovn_cluster_south_db_server ovs-appctl -t /var/run/ovn/ovnsb_db.ctl cluster/status OVN_Southbound | grep 'Leader: ' register: wait_leader delegate_to: "{{ groups['ovn_dbs'] | difference(groups['excluded_overcloud']) | difference(ovn_nb_leader[0]) | first }}" failed_when: "'Leader: unknown' in wait_leader.stdout or wait_leader.stderr != ''" until: "'Leader: unknown' not in wait_leader.stdout and wait_leader.stderr == ''" retries: 10 delay: 5 - name: Pause for 30 seconds to ensure ovn db leader knows it was elected and clients reconnect wait_for: timeout: 30 - name: Get OVN_Northbound cluster new leader become: yes shell: | podman exec -u root ovn_cluster_north_db_server ovs-appctl -t /var/run/ovn/ovnnb_db.ctl cluster/status OVN_Northbound | grep 'Leader: ' register: ovn_nb_dbs_cluster_leader_new loop: "{{groups['ovn_dbs'] | difference(groups['excluded_overcloud']) }}" until: "'Leader: unknown' not in ovn_nb_dbs_cluster_leader_new.stdout" retries: 10 delay: 5 delegate_to: "{{ item }}" - set_fact: ovn_nb_leader_new: "{{ ovn_nb_dbs_cluster_leader_new| json_query(\"results[?contains(stdout,'Leader: self')].item\") }}" - name: Get OVN_Southbound cluster new leader become: yes shell: | sudo podman exec -u root ovn_cluster_south_db_server ovs-appctl -t /var/run/ovn/ovnsb_db.ctl cluster/status OVN_Southbound | grep 'Leader: ' register: ovn_sb_dbs_cluster_leader_new loop: "{{groups['ovn_dbs'] | difference(groups['excluded_overcloud']) }}" until: "'Leader: unknown' not in ovn_sb_dbs_cluster_leader_new.stdout" retries: 10 delay: 5 delegate_to: "{{ item }}" - set_fact: ovn_sb_leader_new: "{{ ovn_sb_dbs_cluster_leader_new | json_query(\"results[?contains(stdout,'Leader: self')].item\") }}" - name: Start OVN NB containers (non-leader nodes) delegate_to: "{{ item }}" become: true tripleo_container_manage: config_dir: "/var/lib/tripleo-config/container-startup-config/step_0" config_id: - 'ovn_cluster_north_db_server' config_patterns: "*ovn_cluster_north_db_server.json" config_overrides: ".*ovn_cluster_north_db_server": image: {get_param: ContainerOvnNbDbImage} name: "ovn_cluster_north_db_server" loop: "{{groups['ovn_dbs'] | difference(groups['excluded_overcloud']) | difference(ovn_nb_leader[0])| difference(ovn_nb_leader_new[0])}}" # pause for 15 seconds to give time to dbs and clients to recover between restarts loop_control: pause: 15 - name: Start OVN SB containers (non-leader nodes) delegate_to: "{{ item }}" become: true tripleo_container_manage: config_dir: "/var/lib/tripleo-config/container-startup-config/step_0" config_id: - 'ovn_cluster_south_db_server' config_patterns: "*ovn_cluster_south_db_server.json" config_overrides: ".*ovn_cluster_south_db_server": image: {get_param: ContainerOvnSbDbImage} name: "ovn_cluster_south_db_server" loop: "{{groups['ovn_dbs'] | difference(groups['excluded_overcloud']) | difference(ovn_sb_leader[0])| difference(ovn_sb_leader_new[0])}}" # pause for 15 seconds to give time to dbs and clients to recover between restarts loop_control: pause: 15 - name: Pause for 50 seconds before restarting new leaders of OVN wait_for: timeout: 50 - name: Graceful stop OVN NB new-leader container delegate_to: "{{ ovn_nb_leader_new[0] }}" become: true shell: | podman exec -u root ovn_cluster_north_db_server ovs-appctl -t /var/run/ovn/ovnnb_db.ctl exit when: ovn_nb_leader_new[0] != ovn_nb_leader[0] - name: Start OVN NB containers (new-leader nodes) delegate_to: "{{ ovn_nb_leader_new[0] }}" become: true tripleo_container_manage: config_dir: "/var/lib/tripleo-config/container-startup-config/step_0" config_id: - 'ovn_cluster_north_db_server' config_patterns: "*ovn_cluster_north_db_server.json" config_overrides: ".*ovn_cluster_north_db_server": image: {get_param: ContainerOvnNbDbImage} name: "ovn_cluster_north_db_server" when: ovn_nb_leader_new[0] != ovn_nb_leader[0] - name: Graceful stop OVN SB new-leader container delegate_to: "{{ ovn_sb_leader_new[0] }}" become: true shell: | sudo podman exec -u root ovn_cluster_south_db_server ovs-appctl -t /var/run/ovn/ovnsb_db.ctl exit when: ovn_sb_leader_new[0] != ovn_sb_leader[0] - name: Start OVN SB containers (new-leader nodes) delegate_to: "{{ ovn_sb_leader_new[0] }}" become: true tripleo_container_manage: config_dir: "/var/lib/tripleo-config/container-startup-config/step_0" config_id: - 'ovn_cluster_south_db_server' config_patterns: "*ovn_cluster_south_db_server.json" config_overrides: ".*ovn_cluster_south_db_server": image: {get_param: ContainerOvnSbDbImage} name: "ovn_cluster_south_db_server" when: ovn_sb_leader_new[0] != ovn_sb_leader[0] - name: Start OVN northd container delegate_to: "{{ item }}" become: true tripleo_container_manage: config_dir: "/var/lib/tripleo-config/container-startup-config/step_0" config_id: - 'ovn_cluster_northd' config_patterns: "*ovn_cluster_northd.json" config_overrides: ".*ovn_cluster_northd": image: {get_param: ContainerOvnNorthdImage} name: "ovn_cluster_northd" loop: "{{groups['ovn_dbs'] | difference(groups['excluded_overcloud'])}}" # pause for 15 seconds to give time to dbs and clients to recover between restarts loop_control: pause: 15 update_tasks: - name: Configure OVN cluster during update when: step|int == 4 block: *configure_ovn_db_northd - name: Update OVN cluster containers when: step|int == 4 block: *ovn_dbs_containers