# resource_properties_data

created_at: 2026-06-13 07:32:43.352753
data:
  {"type": "json", "value": {"vhostuser_socket_group": "qemu", "nova_libvirt_opt_volumes": [], "ContainerNovaLibvirtImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ContainerNovaLibvirtConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1"}}


created_at: 2026-06-13 07:32:48.408001
data:
  {"container_puppet_apply_volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/var/lib/container-config-scripts/container_puppet_apply.sh:/container_puppet_apply.sh:ro", "/etc/puppet:/tmp/puppet-etc:ro", "/usr/share/openstack-puppet/modules:/usr/share/openstack-puppet/modules:ro"], "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro"], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-39-q3pqhi4hcssr-ContainersCommon-yjf6i7e2btpl/a89475a6-8d7a-42d9-a701-ea084aec3da9"}


created_at: 2026-06-13 07:32:48.461857
data:
  {"volumes": ["/var/log/containers/libvirt:/var/log/libvirt:shared,z"], "config_settings": {"nova::compute::libvirt::log_outputs": "1:file:/var/log/libvirt/libvirtd.log", "nova::compute::libvirt::virtlogd::log_outputs": "1:file:/var/log/libvirt/virtlogd.log", "nova::compute::libvirt::virtsecretd::log_outputs": "1:file:/var/log/libvirt/virtsecretd.log", "nova::compute::libvirt::virtnodedevd::log_outputs": "1:file:/var/log/libvirt/virtnodedevd.log", "nova::compute::libvirt::virtqemud::log_outputs": "1:file:/var/log/libvirt/virtqemud.log", "nova::compute::libvirt::virtproxyd::log_outputs": "1:file:/var/log/libvirt/virtproxyd.log", "nova::compute::libvirt::virtstoraged::log_outputs": "1:file:/var/log/libvirt/virtstoraged.log"}, "host_prep_tasks": [{"name": "create persistent directories", "file": {"path": "{{ item.path }}", "setype": "{{ item.setype }}", "state": "directory", "mode": "{{ item.mode }}"}, "with_items": [{"path": "/var/log/containers/libvirt", "setype": "container_file_t", "mode": "0750"}]}], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-39-q3pqhi4hcssr-NovaLibvirtLogging-gtzner64i72y/c12679af-a4ff-4793-b524-3e7335bcb2df"}


created_at: 2026-06-13 07:32:48.527166
data:
  {"tuple:('role_data', 'config_settings', 'nova::logging::debug')": true, "tuple:('role_data', 'config_settings')": {"nova::my_ip": "%{hiera('internal_api')}", "nova::rabbit_use_ssl": "True", "nova::keystone::service_user::send_service_user_token": true, "nova::keystone::service_user::project_name": "service", "nova::keystone::service_user::password": "ksmPDM6JveiqLvoFg56EAxny1", "nova::keystone::service_user::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::keystone::service_user::region_name": "regionOne", "nova::placement::project_name": "service", "nova::placement::password": "H4Zat7IGHRAxn3vftDX6FGvMZ", "nova::placement::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::placement::region_name": "regionOne", "nova::placement::valid_interfaces": "internal", "nova::os_region_name": "regionOne", "nova::logging::debug": true, "nova::purge_config": false, "nova::network::neutron::project_name": "service", "nova::network::neutron::username": "neutron", "nova::network::neutron::region_name": "regionOne", "nova::dhcp_domain": "", "nova::network::neutron::password": "CC70wbFRk1QjXjqZLaKBjXfHn", "nova::network::neutron::auth_url": "https://overcloud.internalapi.ooo.test:5000/v3", "nova::network::neutron::valid_interfaces": "internal", "nova::glance::valid_interfaces": "internal", "nova::rabbit_heartbeat_timeout_threshold": 60, "nova::cinder_catalog_info": "volumev3:cinderv3:internalURL", "nova::host": "%{hiera('fqdn_canonical')}", "nova::notify_on_state_change": "vm_and_task_state", "nova::notification_driver": ["noop"], "nova::notification_format": "unversioned", "nova::network::neutron::auth_type": "v3password", "nova::db::database_db_max_retries": -1, "nova::db::database_max_retries": -1, "nova::network::neutron::ovs_bridge": "br-int", "nova::compute::sync_power_state_interval": 600, "nova_is_additional_cell": false, "nova::cross_az_attach": true, "nova::cache::enabled": true, "nova::cache::tls_enabled": true, "nova::cache::backend": "dogpile.cache.pymemcache", "nova::rabbit_heartbeat_in_pthread": false, "nova::ovsdb_connection": ""}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-39-q3pqhi4hcssr-NovaBase-yypjnippbal6/aad2703e-ae95-44bf-a326-bc0fc2d954ee"}


created_at: 2026-06-13 07:32:48.576719
data:
  {"kolla_config_files": [{"source": "/var/lib/kolla/config_files/src/*", "dest": "/", "merge": true, "preserve_properties": true}, {"source": "/var/lib/kolla/config_files/src-ceph/", "dest": "/etc/ceph/", "merge": true, "preserve_properties": true}], "kolla_permissions": [{"path": "/etc/ceph/ceph.client.openstack.keyring", "owner": "nova:nova", "perm": "0600"}], "update_tasks": [{"name": "check systemd-container package present or not", "package": {"name": "systemd-container", "state": "present"}, "check_mode": true, "register": "is_systemd_container_package"}, {"name": "download systemd-container package if not present", "yum": {"name": "systemd-container", "state": "present", "download_only": true, "download_dir": "/var/tmp/"}, "when": "is_systemd_container_package.changed"}], "config_settings": {"nova::compute::libvirt::qemu::memory_backing_dir": ""}, "volumes": ["/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro"], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-39-q3pqhi4hcssr-NovaLibvirtCommon-b4zv5e2dkc6g/ae6548c7-7788-4093-95f4-7a591f317a92"}


created_at: 2026-06-13 07:32:48.582270
data:
  {"value": {"vhostuser_socket_group": "qemu", "nova_libvirt_opt_volumes": [], "ContainerNovaLibvirtImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ContainerNovaLibvirtConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1"}}


created_at: 2026-06-13 07:32:48.598442
data:
  {"tuple:('role_data', 'step_config')": null, "tuple:('role_data', 'container_config_scripts')": {"nova_libvirt_init_secret.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nset -e\n\nCEPH_INFO=($*)\n\nif [ -z \"$CEPH_INFO\" ]; then\n    echo \"error: At least one CLUSTER:CLIENT tuple must be specified\"\n    exit 1\nfi\n\necho \"------------------------------------------------\"\necho \"Initializing virsh secrets for: ${CEPH_INFO[@]}\"\n\nfor INFO in ${CEPH_INFO[@]}; do\n    IFS=: read CLUSTER CLIENT <<< $INFO\n    if [ ! -f /etc/ceph/${CLUSTER}.conf ]; then\n        echo \"Error: /etc/ceph/${CLUSTER}.conf was not found\"\n        echo \"Path to nova_libvirt_init_secret was ${CEPH_INFO}\"\n        exit 1\n    fi\n    FSID=$(awk '$1 == \"fsid\" {print $3}' /etc/ceph/${CLUSTER}.conf)\n    if [ -z \"${FSID}\" ]; then\n        echo \"Error: /etc/ceph/${CLUSTER}.conf contained an empty fsid definition\"\n        echo \"Check your ceph configuration\"\n        exit 1\n    fi\n\n    echo \"--------\"\n    echo \"Initializing the virsh secret for '$CLUSTER' cluster ($FSID) '$CLIENT' client\"\n\n    # Ensure the secret XML file exists. Puppet should have created a secret.xml\n    # file for the first cluster's secret, so detect when to use that file.\n    if grep -q $FSID /etc/nova/secret.xml; then\n        SECRET_FILE=\"/etc/nova/secret.xml\"\n        SECRET_NAME=\"client.${CLIENT} secret\"\n    else\n        SECRET_FILE=\"/etc/nova/${CLUSTER}-secret.xml\"\n        SECRET_NAME=\"${CLUSTER}.client.${CLIENT} secret\"\n    fi\n\n    if [ ! -f $SECRET_FILE ]; then\n        echo \"Creating $SECRET_FILE\"\n        cat <<EOF > $SECRET_FILE\n<secret ephemeral='no' private='no'>\n  <usage type='ceph'>\n    <name>${SECRET_NAME}</name>\n  </usage>\n  <uuid>${FSID}</uuid>\n</secret>\nEOF\n    else\n        echo \"The $SECRET_FILE file already exists\"\n    fi\n\n    # Ensure the libvirt secret is defined\n    if /usr/bin/virsh secret-list | grep -q $FSID; then\n        echo \"The virsh secret for $FSID has already been defined\"\n    else\n        /usr/bin/virsh secret-define --file $SECRET_FILE\n    fi\n\n    # Fetch the key from the keyring and ensure the secret is set\n    KEY=$(awk '$1 == \"key\" {print $3}' /etc/ceph/${CLUSTER}.client.${CLIENT}.keyring)\n    if /usr/bin/virsh secret-get-value $FSID 2>/dev/null | grep -q $KEY; then\n        echo \"The virsh secret for $FSID has already been set\"\n    else\n        /usr/bin/virsh secret-set-value --secret $FSID --base64 $KEY\n    fi\ndone\n"}}, "tuple:('role_data', 'docker_config')": {"step_2": {"nova_virtqemud_init_logs": {"image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "net": "none", "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "user": "root", "volumes": ["/var/log/containers/libvirt/swtpm:/var/log/swtpm:shared,z"], "command": ["/bin/bash", "-c", "chown -R tss:tss /var/log/swtpm"], "environment": {"TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}, "create_virtlogd_wrapper": {"start_order": 1, "detach": false, "cgroupns": "host", "net": "host", "pid": "host", "user": "root", "command": ["/container_puppet_apply.sh", "4", "file", "include ::tripleo::profile::base::nova::virtlogd_wrapper"], "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/var/lib/container-config-scripts/container_puppet_apply.sh:/container_puppet_apply.sh:ro", "/etc/puppet:/tmp/puppet-etc:ro", "/usr/share/openstack-puppet/modules:/usr/share/openstack-puppet/modules:ro", "/var/lib/container-config-scripts:/var/lib/container-config-scripts:shared,z"], "environment": {"TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}}, "step_3": {"nova_virtlogd_wrapper": {"start_order": 0, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtlogd.json:/var/lib/kolla/config_files/config.json:ro", "/var/lib/container-config-scripts/virtlogd_wrapper:/usr/local/bin/virtlogd_wrapper:ro"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}, "nova_virtsecretd": {"start_order": 1, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "pids_limit": 65536, "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "depends_on": ["tripleo_nova_virtlogd_wrapper.service"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtsecretd.json:/var/lib/kolla/config_files/config.json:ro"]}, "nova_virtnodedevd": {"start_order": 2, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "pids_limit": 65536, "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "depends_on": ["tripleo_nova_virtlogd_wrapper.service"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtnodedevd.json:/var/lib/kolla/config_files/config.json:ro"]}, "nova_virtstoraged": {"start_order": 3, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "pids_limit": 65536, "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "depends_on": ["tripleo_nova_virtlogd_wrapper.service"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtstoraged.json:/var/lib/kolla/config_files/config.json:ro"]}, "nova_virtqemud": {"start_order": 4, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "pids_limit": 65536, "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "depends_on": ["tripleo_nova_virtlogd_wrapper.service"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtqemud.json:/var/lib/kolla/config_files/config.json:ro", "/var/log/containers/libvirt/swtpm:/var/log/swtpm:z"]}, "nova_virtproxyd": {"start_order": 5, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "pids_limit": 65536, "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "depends_on": ["tripleo_nova_virtlogd_wrapper.service"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtproxyd.json:/var/lib/kolla/config_files/config.json:ro"]}}}, "tuple:('role_data', 'service_name')": "nova_libvirt", "role_data": {"service_name": "nova_libvirt", "firewall_rules": {"200 nova_libvirt": {"dport": [16514, "61152-61215", "5900-6923"]}}, "ansible_group_vars": {"tripleo_nova_libvirt_virsh_container": "nova_virtproxyd"}, "monitoring_subscription": "overcloud-nova-libvirt", "config_settings": {"nova::my_ip": "%{hiera('internal_api')}", "nova::rabbit_use_ssl": "True", "nova::keystone::service_user::send_service_user_token": true, "nova::keystone::service_user::project_name": "service", "nova::keystone::service_user::password": "ksmPDM6JveiqLvoFg56EAxny1", "nova::keystone::service_user::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::keystone::service_user::region_name": "regionOne", "nova::placement::project_name": "service", "nova::placement::password": "H4Zat7IGHRAxn3vftDX6FGvMZ", "nova::placement::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::placement::region_name": "regionOne", "nova::placement::valid_interfaces": "internal", "nova::os_region_name": "regionOne", "nova::logging::debug": true, "nova::purge_config": false, "nova::network::neutron::project_name": "service", "nova::network::neutron::username": "neutron", "nova::network::neutron::region_name": "regionOne", "nova::dhcp_domain": "", "nova::network::neutron::password": "CC70wbFRk1QjXjqZLaKBjXfHn", "nova::network::neutron::auth_url": "https://overcloud.internalapi.ooo.test:5000/v3", "nova::network::neutron::valid_interfaces": "internal", "nova::glance::valid_interfaces": "internal", "nova::rabbit_heartbeat_timeout_threshold": 60, "nova::cinder_catalog_info": "volumev3:cinderv3:internalURL", "nova::host": "%{hiera('fqdn_canonical')}", "nova::notify_on_state_change": "vm_and_task_state", "nova::notification_driver": ["noop"], "nova::notification_format": "unversioned", "nova::network::neutron::auth_type": "v3password", "nova::db::database_db_max_retries": -1, "nova::db::database_max_retries": -1, "nova::network::neutron::ovs_bridge": "br-int", "nova::compute::sync_power_state_interval": 600, "nova_is_additional_cell": false, "nova::cross_az_attach": true, "nova::cache::enabled": true, "nova::cache::tls_enabled": true, "nova::cache::backend": "dogpile.cache.pymemcache", "nova::rabbit_heartbeat_in_pthread": false, "nova::ovsdb_connection": "", "vhostuser_socket_group": "qemu", "nova_libvirt_opt_volumes": [], "ContainerNovaLibvirtImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ContainerNovaLibvirtConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "nova::compute::libvirt::log_outputs": "1:file:/var/log/libvirt/libvirtd.log", "nova::compute::libvirt::virtlogd::log_outputs": "1:file:/var/log/libvirt/virtlogd.log", "nova::compute::libvirt::virtsecretd::log_outputs": "1:file:/var/log/libvirt/virtsecretd.log", "nova::compute::libvirt::virtnodedevd::log_outputs": "1:file:/var/log/libvirt/virtnodedevd.log", "nova::compute::libvirt::virtqemud::log_outputs": "1:file:/var/log/libvirt/virtqemud.log", "nova::compute::libvirt::virtproxyd::log_outputs": "1:file:/var/log/libvirt/virtproxyd.log", "nova::compute::libvirt::virtstoraged::log_outputs": "1:file:/var/log/libvirt/virtstoraged.log", "nova::compute::libvirt::qemu::memory_backing_dir": "", "nova::compute::libvirt::manage_libvirt_services": false, "tripleo::profile::base::nova::virtlogd_wrapper::enable_wrapper": true, "tripleo::profile::base::nova::virtlogd_wrapper::virtlogd_process_wrapper": "/var/lib/container-config-scripts/virtlogd_wrapper", "tripleo::profile::base::nova::virtlogd_wrapper::virtlogd_image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "tripleo::profile::base::nova::virtlogd_wrapper::debug": true, "nova::compute::libvirt::migration_support": false, "nova::compute::rbd::libvirt_images_rbd_ceph_conf": "/etc/ceph/ceph.conf", "nova::compute::rbd::libvirt_rbd_user": "openstack", "tripleo::profile::base::nova::compute_libvirt_shared::nova_rbd_ceph_conf_path": "/var/lib/tripleo-config/ceph", "nova::compute::rbd::rbd_keyring": "client.openstack", "nova::compute::rbd::libvirt_rbd_secret_key": "AQCtBi1qAAAAABAAlMbuGDpAuKfBXDWSJGSRjw==", "nova::compute::rbd::libvirt_rbd_secret_uuid": "f72fc8e7-c471-4878-af38-3eab533fd252", "tripleo::profile::base::nova::migration::client::libvirt_enabled": true, "tripleo::profile::base::nova::migration::client::ssh_private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAtEHfMqe/CUfsijQpoJHgkGtXu7olMqGTlbiR3w/aOmycSlLy\nDRC1GFuaSXaRmZzDEoClHGQeMcc2eNzi/edgcjd0Zn9zUnCmq7wbcDYgInwnNgcw\na7jw/sCw7FgfL5rjJus0dGSwcG+aaStUsjcF0f0KwTCnMYPOBQmoDmfcLM/KXwEg\n6xPvoUeXWLmuiYUhX8Ov6/pzQ8qhjwh5QxMGSmDqkE9k+g1AHUAVCnx1H7ABfLgW\nDg5nDt+z1POuw62ttzTjIiTJkOPGzyTgPSUM8G+zcvVUeg6R0tsUj5SdIdpx6ldR\nibjRUo6d+bOyBnK/CLKaXVW0wFMUlqf5vOKEHwIDAQABAoIBAA7SJbRoB3SPZdr9\nK/kIVYL6WHXWec1+bICQcun4xzQrjvQrerxpRcKRcY+dwJ31PjLMwgaiErt8CjYI\nz18aAZuShK8SxpweKA4Rwt3IjX7YX275S1loFOSVWlasbi//V7Lw/tidGMa93l/M\nUMPwczmPSS2WPwD6uds/LoK0tm02qy9xv/1v36xGZTClKbGJm7Gr8DqRBfSrF/Xi\ncUWswxbiEfwVlLQ3KUjH8A/nqoOwDFlkmyw4I1t16Nto6fvsywSS80z2+PZUZyN1\nwcb+Kw7UiJhSiM3E58ecFKloLb0pnuO4EIDqIP3+uoOrvjM4hUHGtDpjcclz7fY8\ntzVi3OECgYEAzz+tx3/tMFbuSjivurgoXFVDDIOAZG3vWY2oeA30j22uUhfXnS4Q\npHRLfxh01avP21fb/N8dlipl/ZY97OsdMghLa8LVYKKs+dpJObiO9COXqOCgf9uH\nOuA8HUiet1vrO8x000zlVRl08jZEhHd87qcgA8jXFhzVQYkuk2aB4D8CgYEA3qjL\ndECE1S9QLmivvcRs+512yPaiXjB6EpVABiSPha2JrFh3vjWzItMb1dQEa3w12kyg\nZpVIfUvjkdaVAU0jJRTX2LivQw1Eb+TIBKTxN0bpsbzGLhZV22y5gqTqlWVtalwr\nsXoCyNMi6TJg3Dm4Jh662f2HI566+NZ5f1J0ZCECgYATYCGwCA61uTrX54rOSw9C\n6pm1HsovGXQKDEtWxf86NYfZlu8Ke9cEePbh7/hkTYbGO+WOM5HBiz8zwQsTDjwR\nhGMAtRtbyHmhdj3oTo/W1UkFedKngW+YGoSkPDjSbZ6FXa0CYCsElLexOU+Yjs84\nRJmioPEy2Qk68kdPcoLr4wKBgDedzgQhwYxGny6Yc51hHR/Ue0FDaddBIJzXrwBZ\nzYfEiykDiBV48F/4f3Fv3hLDGeiHT2GQVGUHubZJ9To3/Flc1XWK3CxRehDBAr02\nPhJioikFUDNe3N9MTyI082uRxDzW/Qr9wQhMxOGe9dbMjBTphB7DVygsk+NoHz0Q\naYZBAoGBAIcWC5mh7BK88xWwH7lTd29gBC0sMfV+4L8/NWQvnxg1omfjfJ32e5sd\n5QqKigi6MtTJwDtXO1EXLxYOjX1zc2jBRYP5NZioxZd0Bc0UvBowcSP5ib5fK4LM\nZzEajZhutEfz1KycMybzQtyzmurMKTVPoLRxIftwg9KKYK7tdeMg\n-----END RSA PRIVATE KEY-----\n", "tripleo::profile::base::nova::migration::client::ssh_port": 2022, "nova::compute::libvirt::services::libvirt_virt_type": "kvm", "nova::compute::libvirt::virt_type": "kvm", "nova::compute::libvirt::enabled_perf_events": [], "nova::compute::libvirt::qemu::configure_qemu": true, "nova::compute::libvirt::qemu::max_files": 32768, "nova::compute::libvirt::qemu::max_processes": 131072, "nova::migration::qemu::configure_qemu": true, "nova::migration::qemu::migration_port_min": 61152, "nova::migration::qemu::migration_port_max": 61215, "nova::compute::libvirt::vncserver_listen": "%{hiera('internal_api')}", "nova::compute::libvirt::log_filters": "1:libvirt 1:qemu 1:conf 1:security 3:event 3:json 3:file 3:object 1:util", "nova::compute::libvirt::virtlogd::log_filters": "1:logging 4:object 4:json 4:event 1:util", "rbd_persistent_storage": false, "rbd_disk_cachemodes": ["network=writeback"], "nova::compute::libvirt::virtsecretd::log_filters": "1:qemu 1:libvirt 4:object 4:json 4:event 1:util", "nova::compute::libvirt::virtnodedevd::log_filters": "1:qemu 1:libvirt 4:object 4:json 4:event 1:util", "nova::compute::libvirt::virtstoraged::log_filters": "1:qemu 1:libvirt 4:object 4:json 4:event 1:util", "nova::compute::libvirt::virtqemud::log_filters": "1:qemu 1:libvirt 4:object 4:json 4:event 1:util", "nova::compute::libvirt::virtproxyd::log_filters": "1:qemu 1:libvirt 4:object 4:json 4:event 1:util", "tripleo::profile::base::nova::libvirt::modular_libvirt": true, "nova::compute::libvirt::services::modular_libvirt": true, "nova::compute::libvirt::modular_libvirt": true, "nova::migration::libvirt::modular_libvirt": true, "tripleo::profile::base::nova::migration::client::libvirt_tls": true, "tripleo::profile::base::nova::libvirt::tls_password": "48uI3YGlejNdMaWws7eHabBvu", "nova::compute::libvirt::qemu::default_tls_verify": true, "nova::compute::libvirt::tls_priority": "NORMAL:-VERS-SSL3.0:-VERS-TLS-ALL:+VERS-TLS1.2", "nova::migration::libvirt::listen_address": "%{hiera('internal_api')}", "nova::migration::libvirt::live_migration_inbound_addr": "%{hiera('fqdn_internal_api')}", "nova::compute::libvirt::qemu::vnc_tls": true, "nova::compute::libvirt::qemu::vnc_tls_verify": true, "nova::compute::libvirt::qemu::nbd_tls": true, "nova::migration::libvirt::live_migration_with_native_tls": true}, "puppet_config": {"config_volume": "nova_libvirt", "puppet_tags": "libvirtd_config,virtlogd_config,virtproxyd_config,virtqemud_config,virtnodedevd_config,virtsecretd_config,virtstoraged_config,nova_config,file,libvirt_tls_password", "step_config": "include tripleo::profile::base::nova::libvirt\n", "config_image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1"}, "kolla_config": {"/var/lib/kolla/config_files/nova_virtlogd.json": {"command": "/usr/local/bin/virtlogd_wrapper", "config_files": [{"source": "/var/lib/kolla/config_files/src/*", "dest": "/", "merge": true, "preserve_properties": true}, {"source": "/var/lib/kolla/config_files/src-ceph/", "dest": "/etc/ceph/", "merge": true, "preserve_properties": true}], "permissions": [{"path": "/etc/ceph/ceph.client.openstack.keyring", "owner": "nova:nova", "perm": "0600"}]}, "/var/lib/kolla/config_files/nova_virtsecretd.json": {"command": "/usr/sbin/virtsecretd --config /etc/libvirt/virtsecretd.conf", "config_files": [{"source": "/var/lib/kolla/config_files/src/*", "dest": "/", "merge": true, "preserve_properties": true}, {"source": "/var/lib/kolla/config_files/src-ceph/", "dest": "/etc/ceph/", "merge": true, "preserve_properties": true}], "permissions": [{"path": "/etc/ceph/ceph.client.openstack.keyring", "owner": "nova:nova", "perm": "0600"}]}, "/var/lib/kolla/config_files/nova_virtnodedevd.json": {"command": "/usr/sbin/virtnodedevd --config /etc/libvirt/virtnodedevd.conf", "config_files": [{"source": "/var/lib/kolla/config_files/src/*", "dest": "/", "merge": true, "preserve_properties": true}, {"source": "/var/lib/kolla/config_files/src-ceph/", "dest": "/etc/ceph/", "merge": true, "preserve_properties": true}], "permissions": [{"path": "/etc/ceph/ceph.client.openstack.keyring", "owner": "nova:nova", "perm": "0600"}]}, "/var/lib/kolla/config_files/nova_virtstoraged.json": {"command": "/usr/sbin/virtstoraged --config /etc/libvirt/virtstoraged.conf", "config_files": [{"source": "/var/lib/kolla/config_files/src/*", "dest": "/", "merge": true, "preserve_properties": true}, {"source": "/var/lib/kolla/config_files/src-ceph/", "dest": "/etc/ceph/", "merge": true, "preserve_properties": true}], "permissions": [{"path": "/etc/ceph/ceph.client.openstack.keyring", "owner": "nova:nova", "perm": "0600"}]}, "/var/lib/kolla/config_files/nova_virtqemud.json": {"command": "/usr/sbin/virtqemud --config /etc/libvirt/virtqemud.conf", "config_files": [{"source": "/var/lib/kolla/config_files/src/*", "dest": "/", "merge": true, "preserve_properties": true}, {"source": "/var/lib/kolla/config_files/src-ceph/", "dest": "/etc/ceph/", "merge": true, "preserve_properties": true}], "permissions": [{"path": "/etc/ceph/ceph.client.openstack.keyring", "owner": "nova:nova", "perm": "0600"}]}, "/var/lib/kolla/config_files/nova_virtproxyd.json": {"command": "/usr/sbin/virtproxyd --config /etc/libvirt/virtproxyd.conf", "config_files": [{"source": "/var/lib/kolla/config_files/src/*", "dest": "/", "merge": true, "preserve_properties": true}, {"source": "/var/lib/kolla/config_files/src-ceph/", "dest": "/etc/ceph/", "merge": true, "preserve_properties": true}], "permissions": [{"path": "/etc/ceph/ceph.client.openstack.keyring", "owner": "nova:nova", "perm": "0600"}]}}, "container_config_scripts": {"nova_libvirt_init_secret.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nset -e\n\nCEPH_INFO=($*)\n\nif [ -z \"$CEPH_INFO\" ]; then\n    echo \"error: At least one CLUSTER:CLIENT tuple must be specified\"\n    exit 1\nfi\n\necho \"------------------------------------------------\"\necho \"Initializing virsh secrets for: ${CEPH_INFO[@]}\"\n\nfor INFO in ${CEPH_INFO[@]}; do\n    IFS=: read CLUSTER CLIENT <<< $INFO\n    if [ ! -f /etc/ceph/${CLUSTER}.conf ]; then\n        echo \"Error: /etc/ceph/${CLUSTER}.conf was not found\"\n        echo \"Path to nova_libvirt_init_secret was ${CEPH_INFO}\"\n        exit 1\n    fi\n    FSID=$(awk '$1 == \"fsid\" {print $3}' /etc/ceph/${CLUSTER}.conf)\n    if [ -z \"${FSID}\" ]; then\n        echo \"Error: /etc/ceph/${CLUSTER}.conf contained an empty fsid definition\"\n        echo \"Check your ceph configuration\"\n        exit 1\n    fi\n\n    echo \"--------\"\n    echo \"Initializing the virsh secret for '$CLUSTER' cluster ($FSID) '$CLIENT' client\"\n\n    # Ensure the secret XML file exists. Puppet should have created a secret.xml\n    # file for the first cluster's secret, so detect when to use that file.\n    if grep -q $FSID /etc/nova/secret.xml; then\n        SECRET_FILE=\"/etc/nova/secret.xml\"\n        SECRET_NAME=\"client.${CLIENT} secret\"\n    else\n        SECRET_FILE=\"/etc/nova/${CLUSTER}-secret.xml\"\n        SECRET_NAME=\"${CLUSTER}.client.${CLIENT} secret\"\n    fi\n\n    if [ ! -f $SECRET_FILE ]; then\n        echo \"Creating $SECRET_FILE\"\n        cat <<EOF > $SECRET_FILE\n<secret ephemeral='no' private='no'>\n  <usage type='ceph'>\n    <name>${SECRET_NAME}</name>\n  </usage>\n  <uuid>${FSID}</uuid>\n</secret>\nEOF\n    else\n        echo \"The $SECRET_FILE file already exists\"\n    fi\n\n    # Ensure the libvirt secret is defined\n    if /usr/bin/virsh secret-list | grep -q $FSID; then\n        echo \"The virsh secret for $FSID has already been defined\"\n    else\n        /usr/bin/virsh secret-define --file $SECRET_FILE\n    fi\n\n    # Fetch the key from the keyring and ensure the secret is set\n    KEY=$(awk '$1 == \"key\" {print $3}' /etc/ceph/${CLUSTER}.client.${CLIENT}.keyring)\n    if /usr/bin/virsh secret-get-value $FSID 2>/dev/null | grep -q $KEY; then\n        echo \"The virsh secret for $FSID has already been set\"\n    else\n        /usr/bin/virsh secret-set-value --secret $FSID --base64 $KEY\n    fi\ndone\n"}}, "docker_config": {"step_2": {"nova_virtqemud_init_logs": {"image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "net": "none", "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "user": "root", "volumes": ["/var/log/containers/libvirt/swtpm:/var/log/swtpm:shared,z"], "command": ["/bin/bash", "-c", "chown -R tss:tss /var/log/swtpm"], "environment": {"TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}, "create_virtlogd_wrapper": {"start_order": 1, "detach": false, "cgroupns": "host", "net": "host", "pid": "host", "user": "root", "command": ["/container_puppet_apply.sh", "4", "file", "include ::tripleo::profile::base::nova::virtlogd_wrapper"], "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/var/lib/container-config-scripts/container_puppet_apply.sh:/container_puppet_apply.sh:ro", "/etc/puppet:/tmp/puppet-etc:ro", "/usr/share/openstack-puppet/modules:/usr/share/openstack-puppet/modules:ro", "/var/lib/container-config-scripts:/var/lib/container-config-scripts:shared,z"], "environment": {"TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}}, "step_3": {"nova_virtlogd_wrapper": {"start_order": 0, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtlogd.json:/var/lib/kolla/config_files/config.json:ro", "/var/lib/container-config-scripts/virtlogd_wrapper:/usr/local/bin/virtlogd_wrapper:ro"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}, "nova_virtsecretd": {"start_order": 1, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "pids_limit": 65536, "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "depends_on": ["tripleo_nova_virtlogd_wrapper.service"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtsecretd.json:/var/lib/kolla/config_files/config.json:ro"]}, "nova_virtnodedevd": {"start_order": 2, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "pids_limit": 65536, "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "depends_on": ["tripleo_nova_virtlogd_wrapper.service"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtnodedevd.json:/var/lib/kolla/config_files/config.json:ro"]}, "nova_virtstoraged": {"start_order": 3, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "pids_limit": 65536, "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "depends_on": ["tripleo_nova_virtlogd_wrapper.service"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtstoraged.json:/var/lib/kolla/config_files/config.json:ro"]}, "nova_virtqemud": {"start_order": 4, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "pids_limit": 65536, "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "depends_on": ["tripleo_nova_virtlogd_wrapper.service"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtqemud.json:/var/lib/kolla/config_files/config.json:ro", "/var/log/containers/libvirt/swtpm:/var/log/swtpm:z"]}, "nova_virtproxyd": {"start_order": 5, "image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ulimit": ["nofile=131072", "nproc=126960"], "cgroupns": "host", "net": "host", "pid": "host", "pids_limit": 65536, "privileged": true, "security_opt": ["label=level:s0", "label=type:spc_t", "label=filetype:container_file_t"], "restart": "always", "depends_on": ["tripleo_nova_virtlogd_wrapper.service"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/libvirt:/var/log/libvirt:shared,z", "/lib/modules:/lib/modules:ro", "/dev:/dev", "/run:/run", "/sys/fs/cgroup:/sys/fs/cgroup", "/sys/fs/selinux:/sys/fs/selinux", "/etc/selinux/config:/etc/selinux/config:ro", "/etc/libvirt:/etc/libvirt:shared", "/etc/ssh/ssh_known_hosts:/etc/ssh/ssh_known_hosts:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared", "/var/lib/libvirt:/var/lib/libvirt:shared", "/var/cache/libvirt:/var/cache/libvirt:shared", "/var/lib/vhost_sockets:/var/lib/vhost_sockets", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/var/lib/tripleo-config/ceph:/var/lib/kolla/config_files/src-ceph:z", "/etc/pki/CA/cacert.pem:/etc/pki/CA/cacert.pem:ro", "/etc/pki/libvirt:/etc/pki/libvirt:ro", "/etc/pki/qemu:/etc/pki/qemu:ro", "/var/lib/kolla/config_files/nova_virtproxyd.json:/var/lib/kolla/config_files/config.json:ro"]}}}, "deploy_steps_tasks": [{"name": "Ensure recovery of containerized virtqemud", "when": "step|int == 4", "become": true, "block": [{"name": "Create virtqemud recovery script", "copy": {"dest": "/usr/libexec/recover_tripleo_nova_virtqemud.sh", "mode": "0755", "content": "#!/bin/bash\npgrep -f /sbin/virtqemud\n[ $? -eq 0 ] && exit 0\nkill -9 $(cat /run/nova_virtqemud.pid)\n"}}, {"name": "Create virtqemud recovery trigger service", "copy": {"dest": "/etc/systemd/system/tripleo_nova_virtqemud_recover.service", "mode": "0644", "content": "[Unit]\nDescription=Check and recover tripleo_nova_virtqemud\nAfter=tripleo_nova_virtqemud.service\nRequisite=tripleo_nova_virtqemud.service\n[Service]\nType=oneshot\nExecStart=bash /usr/libexec/recover_tripleo_nova_virtqemud.sh\nSyslogIdentifier=recover_tripleo_nova_virtqemud\n[Install]\nWantedBy=multi-user.target\n"}}, {"name": "Create virtqemud recovery trigger timer", "copy": {"dest": "/etc/systemd/system/tripleo_nova_virtqemud_recover.timer", "mode": "0644", "content": "[Unit]\nDescription=Check and recover tripleo_nova_virtqemud every 10m\nPartOf=tripleo_nova_virtqemud.service\n[Timer]\nOnCalendar=*:5/10\nOnActiveSec=120\nOnUnitActiveSec=60\nRandomizedDelaySec=1m\n[Install]\nWantedBy=timers.target\n"}}, {"name": "Enable virtqemud recovery trigger service", "systemd": {"name": "tripleo_nova_virtqemud_recover.service", "enabled": true, "daemon_reload": true}}, {"name": "Enable virtqemud recovery trigger timer", "systemd": {"name": "tripleo_nova_virtqemud_recover.timer", "enabled": true, "state": "restarted", "daemon_reload": true}, "register": "virtqemud_recover_timer_result"}, {"name": "Really enable virtqemud recovery trigger timer", "shell": {"cmd": "systemctl enable --now tripleo_nova_virtqemud_recover.timer"}, "when": "virtqemud_recover_timer_result.status.UnitFileState != \"enabled\""}]}, {"name": "Certificate generation", "when": "step|int == 1", "block": [{"name": "Create dirs for certificates and keys", "file": {"path": "{{ item }}", "state": "directory", "serole": "object_r", "setype": "cert_t", "seuser": "system_u"}, "with_items": ["/etc/pki/libvirt", "/etc/pki/libvirt/private", "/etc/pki/qemu"]}, {"include_role": {"name": "linux-system-roles.certificate"}, "vars": {"certificate_requests": [{"name": "libvirt-server-cert", "dns": "{{fqdn_internal_api}}", "principal": "libvirt/{{fqdn_internal_api}}@{{idm_realm}}", "run_after": "# Copy cert and key to libvirt dirs\ncp /etc/ipa/ca.crt /etc/pki/CA/cacert.pem\nchown root:root /etc/pki/CA/cacert.pem\nchmod 644 /etc/pki/CA/cacert.pem\ncp /etc/pki/tls/certs/libvirt-server-cert.crt /etc/pki/libvirt/servercert.pem\ncp /etc/pki/tls/private/libvirt-server-cert.key /etc/pki/libvirt/private/serverkey.pem\npodman exec nova_virtproxyd virt-admin server-update-tls virtproxyd || systemctl reload tripleo_nova_virtproxyd\n", "key_size": "2048", "ca": "ipa"}, {"name": "libvirt-client-cert", "dns": "{{fqdn_internal_api}}", "principal": "libvirt/{{fqdn_internal_api}}@{{idm_realm}}", "run_after": "# Copy cert and key to libvirt dirs\ncp /etc/pki/tls/certs/libvirt-client-cert.crt /etc/pki/libvirt/clientcert.pem\ncp /etc/pki/tls/private/libvirt-client-cert.key /etc/pki/libvirt/private/clientkey.pem\npodman exec nova_virtproxyd virt-admin server-update-tls virtproxyd || systemctl reload tripleo_nova_virtproxyd\n", "key_size": "2048", "ca": "ipa"}, {"name": "qemu-server-cert", "owner": "root", "group": "qemu", "dns": "{{fqdn_internal_api}}", "principal": "qemu/{{fqdn_internal_api}}@{{idm_realm}}", "run_after": "# Copy cert and key to qemu dir\ncp /etc/ipa/ca.crt /etc/pki/qemu/ca-cert.pem\nchown root:root /etc/pki/qemu/ca-cert.pem\nchmod 644 /etc/pki/qemu/ca-cert.pem\ncp -a /etc/pki/tls/certs/qemu-server-cert.crt /etc/pki/qemu/server-cert.pem\ncp -a /etc/pki/tls/private/qemu-server-cert.key /etc/pki/qemu/server-key.pem\nchgrp qemu /etc/pki/qemu/server-*\nchmod 0640 /etc/pki/qemu/server-cert.pem\nchmod 0640 /etc/pki/qemu/server-key.pem\n", "key_size": "2048", "ca": "ipa"}, {"name": "qemu-client-cert", "owner": "root", "group": "qemu", "dns": "{{fqdn_internal_api}}", "principal": "qemu/{{fqdn_internal_api}}@{{idm_realm}}", "run_after": "# Copy cert and key to qemu dir\ncp -a /etc/pki/tls/certs/qemu-client-cert.crt /etc/pki/qemu/client-cert.pem\ncp -a /etc/pki/tls/private/qemu-client-cert.key /etc/pki/qemu/client-key.pem\nchgrp qemu /etc/pki/qemu/client-*\nchmod 0640 /etc/pki/qemu/client-cert.pem\nchmod 0640 /etc/pki/qemu/client-key.pem\n", "key_size": "2048", "ca": "ipa"}]}}]}, {"name": "Set up systemd target for libvirt services", "when": "step|int == 4", "block": [{"name": "Create systemd file", "copy": {"dest": "/etc/systemd/system/tripleo_nova_libvirt.target", "mode": "0644", "owner": "root", "group": "root", "content": "[Unit]\nWants=tripleo_nova_virtsecretd.service\nWants=tripleo_nova_virtnodedevd.service\nWants=tripleo_nova_virtstoraged.service\nWants=tripleo_nova_virtproxyd.service\nWants=tripleo_nova_virtqemud.service\nAfter=tripleo_nova_virtsecretd.service\nAfter=tripleo_nova_virtnodedevd.service\nAfter=tripleo_nova_virtstoraged.service\nAfter=tripleo_nova_virtproxyd.service\nAfter=tripleo_nova_virtqemud.service\n"}, "become": true, "register": "libvirt_target_result"}, {"name": "Reload systemd", "systemd": {"name": "tripleo_nova_libvirt.target", "enabled": true, "state": "restarted", "daemon_reload": true}, "become": true, "when": "libvirt_target_result.changed"}]}], "host_prep_tasks": [{"name": "create persistent directories", "file": {"path": "{{ item.path }}", "setype": "{{ item.setype }}", "state": "directory", "mode": "{{ item.mode }}"}, "with_items": [{"path": "/var/log/containers/libvirt", "setype": "container_file_t", "mode": "0750"}]}, {"name": "create libvirt persistent data directories", "file": {"path": "{{ item.path }}", "state": "directory", "setype": "{{ item.setype | default(omit) }}", "mode": "{{ item.mode | default(omit) }}"}, "with_items": [{"path": "/etc/libvirt", "setype": "container_file_t"}, {"path": "/etc/libvirt/secrets", "setype": "container_file_t"}, {"path": "/etc/libvirt/qemu", "setype": "container_file_t"}, {"path": "/var/lib/libvirt", "setype": "container_file_t"}, {"path": "/var/cache/libvirt"}, {"path": "/var/lib/nova", "setype": "container_file_t"}, {"path": "/run/libvirt"}, {"path": "/var/log/containers/libvirt/swtpm", "setype": "container_file_t", "mode": "0770"}]}, {"name": "ensure qemu group is present on the host", "group": {"name": "qemu", "gid": 107, "state": "present"}}, {"name": "ensure qemu user is present on the host", "user": {"name": "qemu", "uid": 107, "group": "qemu", "state": "present", "shell": "/sbin/nologin", "comment": "qemu user"}}, {"name": "create directory for vhost-user sockets with qemu ownership", "file": {"path": "/var/lib/vhost_sockets", "state": "directory", "owner": "qemu", "group": "qemu", "setype": "virt_cache_t", "seuser": "system_u"}}, {"name": "ensure ceph configurations exist", "file": {"path": "/var/lib/tripleo-config/ceph", "state": "directory"}}, {"name": "check if libvirt is installed", "command": "/usr/bin/rpm -q libvirt-daemon", "failed_when": false, "register": "libvirt_installed", "check_mode": false}, {"name": "make sure libvirt services are disabled and masked", "service": {"name": "{{ item }}", "state": "stopped", "enabled": false, "masked": true, "daemon_reload": true}, "with_items": ["libvirtd.service", "virtlogd.socket"], "when": "libvirt_installed.rc == 0"}, {"name": "ensure /run/libvirt is present upon reboot", "copy": {"dest": "/etc/tmpfiles.d/run-libvirt.conf", "content": "d /run/libvirt 0755 root root - -\n"}}, {"name": "Enable os_enable_vtpm SELinux boolean for vTPM", "seboolean": {"name": "os_enable_vtpm", "persistent": true, "state": true}, "when": ["ansible_facts.selinux is defined", "ansible_facts.selinux.status == \"enabled\""]}, [{"name": "remove gnutls-qemu.config", "file": {"path": "/etc/crypto-policies/local.d/gnutls-qemu.config", "state": "absent"}, "register": "update_gnutls_config"}], {"name": "update crypto policies", "command": "update-crypto-policies", "when": "update_gnutls_config.changed"}], "metadata_settings": [{"service": "libvirt", "network": "internal_api", "type": "node"}, {"service": "qemu", "network": "internal_api", "type": "node"}, {"service": "libvirt-vnc", "network": "internal_api", "type": "node"}], "upgrade_tasks": [{"name": "Fail if we are on RHEL8 as this is monolithic libvirt deployment", "when": ["step|int == 0", "'system_upgrade' not in ansible_run_tags", "ansible_facts['distribution_major_version'] is version('8', '==')"], "fail": {"msg": "Use of the Modular Libvirt deployment on RHEL8 results in loss of workloads. Use NovaLibvirtLegacy in roles data."}}, {"name": "nova_libvirt_container_tmpfile_cleanup", "when": "step|int == 1", "block": [{"name": "Remove old tmpfiles.d config", "file": {"path": "/etc/tmpfiles.d/var-run-libvirt.conf", "state": "absent"}}]}, {"name": "Get container virtlogd image", "when": "step|int == 1", "tags": "always", "set_fact": {"virtlogd_image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1"}}, {"name": "Force pull image novalibvirt", "when": ["step|int == 1"], "containers.podman.podman_image": {"name": "{{ virtlogd_image }}", "force": true}}, {"name": "Diff OS release in container image and baremetal", "when": "step|int == 1", "shell": "diff /etc/redhat-release <(podman run {{ virtlogd_image }} cat /etc/redhat-release)\n", "args": {"executable": "/bin/bash"}, "failed_when": false, "register": "libvirt_ubi_diff"}, {"name": "Fail if UBI of the container does not match RHEL of running host", "when": ["'system_upgrade' not in ansible_run_tags", "step|int == 1", "libvirt_ubi_diff.rc == 1"], "fail": {"msg": "The host operating system versus container UBI does not match.\n{{ libvirt_ubi_diff.stdout }}\nMost likely container passed to NovaLibvirt was EL8 one.\nYou have to pass the correct container for container-image-prepare.\nIf you would continue all running workloads would get destroyed.\n"}}, {"name": "Switch virtlogd image before system upgrade", "when": "step|int == 1", "tags": ["never", "system_upgrade"], "block": [{"name": "Get running image version", "shell": "podman ps --filter name=^nova_virtlogd$ --format \"{% raw %}{{ .Image }}{% endraw %}\"\n", "register": "old_virtlogd_image"}, {"name": "Switch running image to new image in wrapper script", "shell": "set -o pipefail\nsed -i -e 's|{{ old_virtlogd_image.stdout }}|{{ virtlogd_image }}|' /var/lib/container-config-scripts/virtlogd_wrapper\n", "when": ["old_virtlogd_image.stdout != virtlogd_image", "old_virtlogd_image.stdout != ''"]}]}], "update_tasks": [{"name": "check systemd-container package present or not", "package": {"name": "systemd-container", "state": "present"}, "check_mode": true, "register": "is_systemd_container_package"}, {"name": "download systemd-container package if not present", "yum": {"name": "systemd-container", "state": "present", "download_only": true, "download_dir": "/var/tmp/"}, "when": "is_systemd_container_package.changed"}, {"name": "nova_libvirt_container_tmpfile_cleanup", "when": "step|int == 1", "block": [{"name": "Remove old tmpfiles.d config", "file": {"path": "/etc/tmpfiles.d/var-run-libvirt.conf", "state": "absent"}}]}]}, "tuple:('role_data', 'service_names')": null, "tuple:('role_data', 'config_settings')": {"nova::my_ip": "%{hiera('internal_api')}", "nova::rabbit_use_ssl": "True", "nova::keystone::service_user::send_service_user_token": true, "nova::keystone::service_user::project_name": "service", "nova::keystone::service_user::password": "ksmPDM6JveiqLvoFg56EAxny1", "nova::keystone::service_user::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::keystone::service_user::region_name": "regionOne", "nova::placement::project_name": "service", "nova::placement::password": "H4Zat7IGHRAxn3vftDX6FGvMZ", "nova::placement::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::placement::region_name": "regionOne", "nova::placement::valid_interfaces": "internal", "nova::os_region_name": "regionOne", "nova::logging::debug": true, "nova::purge_config": false, "nova::network::neutron::project_name": "service", "nova::network::neutron::username": "neutron", "nova::network::neutron::region_name": "regionOne", "nova::dhcp_domain": "", "nova::network::neutron::password": "CC70wbFRk1QjXjqZLaKBjXfHn", "nova::network::neutron::auth_url": "https://overcloud.internalapi.ooo.test:5000/v3", "nova::network::neutron::valid_interfaces": "internal", "nova::glance::valid_interfaces": "internal", "nova::rabbit_heartbeat_timeout_threshold": 60, "nova::cinder_catalog_info": "volumev3:cinderv3:internalURL", "nova::host": "%{hiera('fqdn_canonical')}", "nova::notify_on_state_change": "vm_and_task_state", "nova::notification_driver": ["noop"], "nova::notification_format": "unversioned", "nova::network::neutron::auth_type": "v3password", "nova::db::database_db_max_retries": -1, "nova::db::database_max_retries": -1, "nova::network::neutron::ovs_bridge": "br-int", "nova::compute::sync_power_state_interval": 600, "nova_is_additional_cell": false, "nova::cross_az_attach": true, "nova::cache::enabled": true, "nova::cache::tls_enabled": true, "nova::cache::backend": "dogpile.cache.pymemcache", "nova::rabbit_heartbeat_in_pthread": false, "nova::ovsdb_connection": "", "vhostuser_socket_group": "qemu", "nova_libvirt_opt_volumes": [], "ContainerNovaLibvirtImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "ContainerNovaLibvirtConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "nova::compute::libvirt::log_outputs": "1:file:/var/log/libvirt/libvirtd.log", "nova::compute::libvirt::virtlogd::log_outputs": "1:file:/var/log/libvirt/virtlogd.log", "nova::compute::libvirt::virtsecretd::log_outputs": "1:file:/var/log/libvirt/virtsecretd.log", "nova::compute::libvirt::virtnodedevd::log_outputs": "1:file:/var/log/libvirt/virtnodedevd.log", "nova::compute::libvirt::virtqemud::log_outputs": "1:file:/var/log/libvirt/virtqemud.log", "nova::compute::libvirt::virtproxyd::log_outputs": "1:file:/var/log/libvirt/virtproxyd.log", "nova::compute::libvirt::virtstoraged::log_outputs": "1:file:/var/log/libvirt/virtstoraged.log", "nova::compute::libvirt::qemu::memory_backing_dir": "", "nova::compute::libvirt::manage_libvirt_services": false, "tripleo::profile::base::nova::virtlogd_wrapper::enable_wrapper": true, "tripleo::profile::base::nova::virtlogd_wrapper::virtlogd_process_wrapper": "/var/lib/container-config-scripts/virtlogd_wrapper", "tripleo::profile::base::nova::virtlogd_wrapper::virtlogd_image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1", "tripleo::profile::base::nova::virtlogd_wrapper::debug": true, "nova::compute::libvirt::migration_support": false, "nova::compute::rbd::libvirt_images_rbd_ceph_conf": "/etc/ceph/ceph.conf", "nova::compute::rbd::libvirt_rbd_user": "openstack", "tripleo::profile::base::nova::compute_libvirt_shared::nova_rbd_ceph_conf_path": "/var/lib/tripleo-config/ceph", "nova::compute::rbd::rbd_keyring": "client.openstack", "nova::compute::rbd::libvirt_rbd_secret_key": "AQCtBi1qAAAAABAAlMbuGDpAuKfBXDWSJGSRjw==", "nova::compute::rbd::libvirt_rbd_secret_uuid": "f72fc8e7-c471-4878-af38-3eab533fd252", "tripleo::profile::base::nova::migration::client::libvirt_enabled": true, "tripleo::profile::base::nova::migration::client::ssh_private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAtEHfMqe/CUfsijQpoJHgkGtXu7olMqGTlbiR3w/aOmycSlLy\nDRC1GFuaSXaRmZzDEoClHGQeMcc2eNzi/edgcjd0Zn9zUnCmq7wbcDYgInwnNgcw\na7jw/sCw7FgfL5rjJus0dGSwcG+aaStUsjcF0f0KwTCnMYPOBQmoDmfcLM/KXwEg\n6xPvoUeXWLmuiYUhX8Ov6/pzQ8qhjwh5QxMGSmDqkE9k+g1AHUAVCnx1H7ABfLgW\nDg5nDt+z1POuw62ttzTjIiTJkOPGzyTgPSUM8G+zcvVUeg6R0tsUj5SdIdpx6ldR\nibjRUo6d+bOyBnK/CLKaXVW0wFMUlqf5vOKEHwIDAQABAoIBAA7SJbRoB3SPZdr9\nK/kIVYL6WHXWec1+bICQcun4xzQrjvQrerxpRcKRcY+dwJ31PjLMwgaiErt8CjYI\nz18aAZuShK8SxpweKA4Rwt3IjX7YX275S1loFOSVWlasbi//V7Lw/tidGMa93l/M\nUMPwczmPSS2WPwD6uds/LoK0tm02qy9xv/1v36xGZTClKbGJm7Gr8DqRBfSrF/Xi\ncUWswxbiEfwVlLQ3KUjH8A/nqoOwDFlkmyw4I1t16Nto6fvsywSS80z2+PZUZyN1\nwcb+Kw7UiJhSiM3E58ecFKloLb0pnuO4EIDqIP3+uoOrvjM4hUHGtDpjcclz7fY8\ntzVi3OECgYEAzz+tx3/tMFbuSjivurgoXFVDDIOAZG3vWY2oeA30j22uUhfXnS4Q\npHRLfxh01avP21fb/N8dlipl/ZY97OsdMghLa8LVYKKs+dpJObiO9COXqOCgf9uH\nOuA8HUiet1vrO8x000zlVRl08jZEhHd87qcgA8jXFhzVQYkuk2aB4D8CgYEA3qjL\ndECE1S9QLmivvcRs+512yPaiXjB6EpVABiSPha2JrFh3vjWzItMb1dQEa3w12kyg\nZpVIfUvjkdaVAU0jJRTX2LivQw1Eb+TIBKTxN0bpsbzGLhZV22y5gqTqlWVtalwr\nsXoCyNMi6TJg3Dm4Jh662f2HI566+NZ5f1J0ZCECgYATYCGwCA61uTrX54rOSw9C\n6pm1HsovGXQKDEtWxf86NYfZlu8Ke9cEePbh7/hkTYbGO+WOM5HBiz8zwQsTDjwR\nhGMAtRtbyHmhdj3oTo/W1UkFedKngW+YGoSkPDjSbZ6FXa0CYCsElLexOU+Yjs84\nRJmioPEy2Qk68kdPcoLr4wKBgDedzgQhwYxGny6Yc51hHR/Ue0FDaddBIJzXrwBZ\nzYfEiykDiBV48F/4f3Fv3hLDGeiHT2GQVGUHubZJ9To3/Flc1XWK3CxRehDBAr02\nPhJioikFUDNe3N9MTyI082uRxDzW/Qr9wQhMxOGe9dbMjBTphB7DVygsk+NoHz0Q\naYZBAoGBAIcWC5mh7BK88xWwH7lTd29gBC0sMfV+4L8/NWQvnxg1omfjfJ32e5sd\n5QqKigi6MtTJwDtXO1EXLxYOjX1zc2jBRYP5NZioxZd0Bc0UvBowcSP5ib5fK4LM\nZzEajZhutEfz1KycMybzQtyzmurMKTVPoLRxIftwg9KKYK7tdeMg\n-----END RSA PRIVATE KEY-----\n", "tripleo::profile::base::nova::migration::client::ssh_port": 2022, "nova::compute::libvirt::services::libvirt_virt_type": "kvm", "nova::compute::libvirt::virt_type": "kvm", "nova::compute::libvirt::enabled_perf_events": [], "nova::compute::libvirt::qemu::configure_qemu": true, "nova::compute::libvirt::qemu::max_files": 32768, "nova::compute::libvirt::qemu::max_processes": 131072, "nova::migration::qemu::configure_qemu": true, "nova::migration::qemu::migration_port_min": 61152, "nova::migration::qemu::migration_port_max": 61215, "nova::compute::libvirt::vncserver_listen": "%{hiera('internal_api')}", "nova::compute::libvirt::log_filters": "1:libvirt 1:qemu 1:conf 1:security 3:event 3:json 3:file 3:object 1:util", "nova::compute::libvirt::virtlogd::log_filters": "1:logging 4:object 4:json 4:event 1:util", "rbd_persistent_storage": false, "rbd_disk_cachemodes": ["network=writeback"], "nova::compute::libvirt::virtsecretd::log_filters": "1:qemu 1:libvirt 4:object 4:json 4:event 1:util", "nova::compute::libvirt::virtnodedevd::log_filters": "1:qemu 1:libvirt 4:object 4:json 4:event 1:util", "nova::compute::libvirt::virtstoraged::log_filters": "1:qemu 1:libvirt 4:object 4:json 4:event 1:util", "nova::compute::libvirt::virtqemud::log_filters": "1:qemu 1:libvirt 4:object 4:json 4:event 1:util", "nova::compute::libvirt::virtproxyd::log_filters": "1:qemu 1:libvirt 4:object 4:json 4:event 1:util", "tripleo::profile::base::nova::libvirt::modular_libvirt": true, "nova::compute::libvirt::services::modular_libvirt": true, "nova::compute::libvirt::modular_libvirt": true, "nova::migration::libvirt::modular_libvirt": true, "tripleo::profile::base::nova::migration::client::libvirt_tls": true, "tripleo::profile::base::nova::libvirt::tls_password": "48uI3YGlejNdMaWws7eHabBvu", "nova::compute::libvirt::qemu::default_tls_verify": true, "nova::compute::libvirt::tls_priority": "NORMAL:-VERS-SSL3.0:-VERS-TLS-ALL:+VERS-TLS1.2", "nova::migration::libvirt::listen_address": "%{hiera('internal_api')}", "nova::migration::libvirt::live_migration_inbound_addr": "%{hiera('fqdn_internal_api')}", "nova::compute::libvirt::qemu::vnc_tls": true, "nova::compute::libvirt::qemu::vnc_tls_verify": true, "nova::compute::libvirt::qemu::nbd_tls": true, "nova::migration::libvirt::live_migration_with_native_tls": true}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-39-q3pqhi4hcssr/f2a28142-5fdd-42b0-baa3-57056439e1e3"}


created_at: 2026-06-13 07:32:49.984414
data:
  {"type": "json", "value": {"ContainerNovaComputeImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-compute:17.1", "ContainerNovaLibvirtConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1"}}


created_at: 2026-06-13 07:32:50.948277
data:
  {"EndpointMap": {"AodhAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8042", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8042", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8042"}, "AodhInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8042", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8042", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8042"}, "AodhPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13042", "protocol": "https", "uri": "https://standalone.ooo.test:13042", "uri_no_suffix": "https://standalone.ooo.test:13042"}, "BarbicanAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9311", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9311", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9311"}, "BarbicanInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9311", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9311", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9311"}, "BarbicanPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13311", "protocol": "https", "uri": "https://standalone.ooo.test:13311", "uri_no_suffix": "https://standalone.ooo.test:13311"}, "CephDashboardInternal": {"host": "overcloud.ctlplane.ooo.test", "host_nobrackets": "overcloud.ctlplane.ooo.test", "port": "8444", "protocol": "https", "uri": "https://overcloud.ctlplane.ooo.test:8444", "uri_no_suffix": "https://overcloud.ctlplane.ooo.test:8444"}, "CephGrafanaInternal": {"host": "overcloud.storage.ooo.test", "host_nobrackets": "overcloud.storage.ooo.test", "port": "3100", "protocol": "https", "uri": "https://overcloud.storage.ooo.test:3100", "uri_no_suffix": "https://overcloud.storage.ooo.test:3100"}, "CephRgwAdmin": {"host": "overcloud.storage.ooo.test", "host_nobrackets": "overcloud.storage.ooo.test", "port": "8080", "protocol": "https", "uri": "https://overcloud.storage.ooo.test:8080/swift/v1/AUTH_%(project_id)s", "uri_no_suffix": "https://overcloud.storage.ooo.test:8080"}, "CephRgwInternal": {"host": "overcloud.storage.ooo.test", "host_nobrackets": "overcloud.storage.ooo.test", "port": "8080", "protocol": "https", "uri": "https://overcloud.storage.ooo.test:8080/swift/v1/AUTH_%(project_id)s", "uri_no_suffix": "https://overcloud.storage.ooo.test:8080"}, "CephRgwPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13808", "protocol": "https", "uri": "https://standalone.ooo.test:13808/swift/v1/AUTH_%(project_id)s", "uri_no_suffix": "https://standalone.ooo.test:13808"}, "CinderAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8776", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8776/v1/%(tenant_id)s", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8776"}, "CinderInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8776", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8776/v1/%(tenant_id)s", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8776"}, "CinderPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13776", "protocol": "https", "uri": "https://standalone.ooo.test:13776/v1/%(tenant_id)s", "uri_no_suffix": "https://standalone.ooo.test:13776"}, "CinderV2Admin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8776", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8776/v2/%(tenant_id)s", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8776"}, "CinderV2Internal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8776", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8776/v2/%(tenant_id)s", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8776"}, "CinderV2Public": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13776", "protocol": "https", "uri": "https://standalone.ooo.test:13776/v2/%(tenant_id)s", "uri_no_suffix": "https://standalone.ooo.test:13776"}, "CinderV3Admin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8776", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8776/v3/%(tenant_id)s", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8776"}, "CinderV3Internal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8776", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8776/v3/%(tenant_id)s", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8776"}, "CinderV3Public": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13776", "protocol": "https", "uri": "https://standalone.ooo.test:13776/v3/%(tenant_id)s", "uri_no_suffix": "https://standalone.ooo.test:13776"}, "DesignateAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9001", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9001/v2", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9001"}, "DesignateInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9001", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9001/v2", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9001"}, "DesignatePublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13001", "protocol": "https", "uri": "https://standalone.ooo.test:13001/v2", "uri_no_suffix": "https://standalone.ooo.test:13001"}, "DockerRegistryInternal": {"host": "overcloud.ctlplane.ooo.test", "host_nobrackets": "overcloud.ctlplane.ooo.test", "port": "8787", "protocol": "https", "uri": "https://overcloud.ctlplane.ooo.test:8787", "uri_no_suffix": "https://overcloud.ctlplane.ooo.test:8787"}, "GaneshaInternal": {"host": "172.21.0.2", "host_nobrackets": "172.21.0.2", "port": "2049", "protocol": "nfs", "uri": "nfs://172.21.0.2:2049", "uri_no_suffix": "nfs://172.21.0.2:2049"}, "GlanceAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9293", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9293", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9293"}, "GlanceInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9293", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9293", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9293"}, "GlancePublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13292", "protocol": "https", "uri": "https://standalone.ooo.test:13292", "uri_no_suffix": "https://standalone.ooo.test:13292"}, "GnocchiAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8041", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8041", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8041"}, "GnocchiInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8041", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8041", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8041"}, "GnocchiPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13041", "protocol": "https", "uri": "https://standalone.ooo.test:13041", "uri_no_suffix": "https://standalone.ooo.test:13041"}, "HeatAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8004", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8004/v1/%(tenant_id)s", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8004"}, "HeatInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8004", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8004/v1/%(tenant_id)s", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8004"}, "HeatPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13004", "protocol": "https", "uri": "https://standalone.ooo.test:13004/v1/%(tenant_id)s", "uri_no_suffix": "https://standalone.ooo.test:13004"}, "HeatCfnAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8000", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8000/v1", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8000"}, "HeatCfnInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8000", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8000/v1", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8000"}, "HeatCfnPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13005", "protocol": "https", "uri": "https://standalone.ooo.test:13005/v1", "uri_no_suffix": "https://standalone.ooo.test:13005"}, "HorizonPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "443", "protocol": "https", "uri": "https://standalone.ooo.test:443/dashboard", "uri_no_suffix": "https://standalone.ooo.test:443"}, "IronicAdmin": {"host": "overcloud.ctlplane.ooo.test", "host_nobrackets": "overcloud.ctlplane.ooo.test", "port": "6385", "protocol": "https", "uri": "https://overcloud.ctlplane.ooo.test:6385/v1", "uri_no_suffix": "https://overcloud.ctlplane.ooo.test:6385"}, "IronicInternal": {"host": "overcloud.ctlplane.ooo.test", "host_nobrackets": "overcloud.ctlplane.ooo.test", "port": "6385", "protocol": "https", "uri": "https://overcloud.ctlplane.ooo.test:6385/v1", "uri_no_suffix": "https://overcloud.ctlplane.ooo.test:6385"}, "IronicPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13385", "protocol": "https", "uri": "https://standalone.ooo.test:13385/v1", "uri_no_suffix": "https://standalone.ooo.test:13385"}, "IronicInspectorAdmin": {"host": "", "host_nobrackets": "", "port": "5050", "protocol": "http", "uri": "http://:5050", "uri_no_suffix": "http://:5050"}, "IronicInspectorInternal": {"host": "", "host_nobrackets": "", "port": "5050", "protocol": "http", "uri": "http://:5050", "uri_no_suffix": "http://:5050"}, "IronicInspectorPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13050", "protocol": "https", "uri": "https://standalone.ooo.test:13050", "uri_no_suffix": "https://standalone.ooo.test:13050"}, "KeystoneAdmin": {"host": "overcloud.ctlplane.ooo.test", "host_nobrackets": "overcloud.ctlplane.ooo.test", "port": "35357", "protocol": "https", "uri": "https://overcloud.ctlplane.ooo.test:35357/", "uri_no_suffix": "https://overcloud.ctlplane.ooo.test:35357"}, "KeystoneInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "5000", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:5000/", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:5000"}, "KeystonePublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13000", "protocol": "https", "uri": "https://standalone.ooo.test:13000/", "uri_no_suffix": "https://standalone.ooo.test:13000"}, "KeystoneV3Admin": {"host": "overcloud.ctlplane.ooo.test", "host_nobrackets": "overcloud.ctlplane.ooo.test", "port": "35357", "protocol": "https", "uri": "https://overcloud.ctlplane.ooo.test:35357/v3", "uri_no_suffix": "https://overcloud.ctlplane.ooo.test:35357"}, "KeystoneV3Internal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "5000", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:5000/v3", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:5000"}, "KeystoneV3Public": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13000", "protocol": "https", "uri": "https://standalone.ooo.test:13000/v3", "uri_no_suffix": "https://standalone.ooo.test:13000"}, "ManilaAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8786", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8786/v2", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8786"}, "ManilaInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8786", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8786/v2", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8786"}, "ManilaPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13786", "protocol": "https", "uri": "https://standalone.ooo.test:13786/v2", "uri_no_suffix": "https://standalone.ooo.test:13786"}, "ManilaV1Admin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8786", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8786/v1/%(tenant_id)s", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8786"}, "ManilaV1Internal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8786", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8786/v1/%(tenant_id)s", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8786"}, "ManilaV1Public": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13786", "protocol": "https", "uri": "https://standalone.ooo.test:13786/v1/%(tenant_id)s", "uri_no_suffix": "https://standalone.ooo.test:13786"}, "MetricsQdrPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "5666", "protocol": "amqp", "uri": "amqp://standalone.ooo.test:5666", "uri_no_suffix": "amqp://standalone.ooo.test:5666"}, "MysqlInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "3306", "protocol": "mysql+pymysql", "uri": "mysql+pymysql://overcloud.internalapi.ooo.test:3306", "uri_no_suffix": "mysql+pymysql://overcloud.internalapi.ooo.test:3306"}, "NeutronAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9696", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9696", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9696"}, "NeutronInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9696", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9696", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9696"}, "NeutronPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13696", "protocol": "https", "uri": "https://standalone.ooo.test:13696", "uri_no_suffix": "https://standalone.ooo.test:13696"}, "NovaAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8774", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8774/v2.1", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8774"}, "NovaInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8774", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8774/v2.1", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8774"}, "NovaPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13774", "protocol": "https", "uri": "https://standalone.ooo.test:13774/v2.1", "uri_no_suffix": "https://standalone.ooo.test:13774"}, "NovaMetadataInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8775", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8775", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8775"}, "NovaVNCProxyAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "6080", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:6080", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:6080"}, "NovaVNCProxyInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "6080", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:6080", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:6080"}, "NovaVNCProxyPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13080", "protocol": "https", "uri": "https://standalone.ooo.test:13080", "uri_no_suffix": "https://standalone.ooo.test:13080"}, "NovajoinAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9090", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9090/v1", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9090"}, "NovajoinInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9090", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9090/v1", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9090"}, "NovajoinPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13090", "protocol": "https", "uri": "https://standalone.ooo.test:13090/v1", "uri_no_suffix": "https://standalone.ooo.test:13090"}, "OctaviaAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9876", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9876", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9876"}, "OctaviaInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "9876", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:9876", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:9876"}, "OctaviaPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13876", "protocol": "https", "uri": "https://standalone.ooo.test:13876", "uri_no_suffix": "https://standalone.ooo.test:13876"}, "PlacementAdmin": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8778", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8778/placement", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8778"}, "PlacementInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8778", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8778/placement", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8778"}, "PlacementPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13778", "protocol": "https", "uri": "https://standalone.ooo.test:13778/placement", "uri_no_suffix": "https://standalone.ooo.test:13778"}, "SwiftAdmin": {"host": "overcloud.storage.ooo.test", "host_nobrackets": "overcloud.storage.ooo.test", "port": "8080", "protocol": "https", "uri": "https://overcloud.storage.ooo.test:8080", "uri_no_suffix": "https://overcloud.storage.ooo.test:8080"}, "SwiftInternal": {"host": "overcloud.storage.ooo.test", "host_nobrackets": "overcloud.storage.ooo.test", "port": "8080", "protocol": "https", "uri": "https://overcloud.storage.ooo.test:8080/v1/AUTH_%(tenant_id)s", "uri_no_suffix": "https://overcloud.storage.ooo.test:8080"}, "SwiftPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13808", "protocol": "https", "uri": "https://standalone.ooo.test:13808/v1/AUTH_%(tenant_id)s", "uri_no_suffix": "https://standalone.ooo.test:13808"}, "SwiftS3Admin": {"host": "overcloud.storage.ooo.test", "host_nobrackets": "overcloud.storage.ooo.test", "port": "8080", "protocol": "https", "uri": "https://overcloud.storage.ooo.test:8080", "uri_no_suffix": "https://overcloud.storage.ooo.test:8080"}, "SwiftS3Internal": {"host": "overcloud.storage.ooo.test", "host_nobrackets": "overcloud.storage.ooo.test", "port": "8080", "protocol": "https", "uri": "https://overcloud.storage.ooo.test:8080", "uri_no_suffix": "https://overcloud.storage.ooo.test:8080"}, "SwiftS3Public": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13808", "protocol": "https", "uri": "https://standalone.ooo.test:13808", "uri_no_suffix": "https://standalone.ooo.test:13808"}, "MysqlCellInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "3306", "protocol": "mysql+pymysql", "uri": "mysql+pymysql://overcloud.internalapi.ooo.test:3306", "uri_no_suffix": "mysql+pymysql://overcloud.internalapi.ooo.test:3306"}, "NovaVNCProxyCellPublic": {"host": "standalone.ooo.test", "host_nobrackets": "standalone.ooo.test", "port": "13080", "protocol": "https", "uri": "https://standalone.ooo.test:13080", "uri_no_suffix": "https://standalone.ooo.test:13080"}, "NovaMetadataCellInternal": {"host": "overcloud.internalapi.ooo.test", "host_nobrackets": "overcloud.internalapi.ooo.test", "port": "8775", "protocol": "https", "uri": "https://overcloud.internalapi.ooo.test:8775", "uri_no_suffix": "https://overcloud.internalapi.ooo.test:8775"}}, "ServiceNetMap": {"ApacheNetwork": "internal_api", "NeutronTenantNetwork": "tenant", "AodhApiNetwork": "internal_api", "BarbicanApiNetwork": "internal_api", "GnocchiApiNetwork": "internal_api", "MongodbNetwork": "internal_api", "CinderApiNetwork": "internal_api", "CinderIscsiNetwork": "storage", "GlanceApiNetwork": "internal_api", "GlanceApiEdgeNetwork": "internal_api", "GlanceApiInternalNetwork": "internal_api", "IronicApiNetwork": "ctlplane", "IronicNetwork": "baremetal", "IronicInspectorNetwork": "baremetal", "KeystoneAdminApiNetwork": "ctlplane", "KeystonePublicApiNetwork": "internal_api", "ManilaApiNetwork": "internal_api", "NeutronApiNetwork": "internal_api", "OctaviaApiNetwork": "internal_api", "HeatApiNetwork": "internal_api", "HeatApiCfnNetwork": "internal_api", "HeatApiCloudwatchNetwork": "internal_api", "NovaApiNetwork": "internal_api", "PlacementNetwork": "internal_api", "NovaMetadataNetwork": "internal_api", "NovaLibvirtNetwork": "internal_api", "NovajoinNetwork": "internal_api", "SwiftStorageNetwork": "storage_mgmt", "SwiftProxyNetwork": "storage", "HorizonNetwork": "internal_api", "MemcachedNetwork": "internal_api", "OsloMessagingRpcNetwork": "internal_api", "OsloMessagingNotifyNetwork": "internal_api", "RabbitmqNetwork": "internal_api", "RabbitmqManagementNetwork": "internal_api", "QdrNetwork": "internal_api", "RedisNetwork": "internal_api", "GaneshaNetwork": "external", "MysqlNetwork": "internal_api", "SnmpdNetwork": "ctlplane", "CephClusterNetwork": "storage_mgmt", "CephDashboardNetwork": "ctlplane", "CephGrafanaNetwork": "storage", "CephMonNetwork": "storage", "CephRgwNetwork": "storage", "PublicNetwork": "external", "InternalApiNetwork": "internal_api", "OpendaylightApiNetwork": "internal_api", "OvnDbsNetwork": "internal_api", "DockerRegistryNetwork": "ctlplane", "PacemakerNetwork": "internal_api", "PacemakerRemoteNetwork": "internal_api", "DesignateApiNetwork": "internal_api", "DesignateMdnsNetwork": "internal_api", "DesignateWorkerNetwork": "external", "DesignateBindNetwork": "external", "BINDNetwork": "external", "EtcdNetwork": "internal_api", "HaproxyNetwork": "ctlplane", "UnboundNetwork": "external", "StandaloneHostnameResolveNetwork": "internal_api", "StandaloneMetricsQdrNetwork": "internal_api", "NovaVncProxyNetwork": "internal_api"}, "RoleName": "Standalone", "RoleParameters": {"OVNCMSOptions": "enable-chassis-as-gw"}}


created_at: 2026-06-13 07:32:53.074774
data:
  {"volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro"], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-40-ortbfllx2iko-ContainersCommon-tfian27ocp2g/f1b37e82-c4b3-46e3-bd88-686018e39c5e"}


created_at: 2026-06-13 07:32:53.079193
data:
  {"value": {"ContainerNovaComputeImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-compute:17.1", "ContainerNovaLibvirtConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1"}}


created_at: 2026-06-13 07:32:53.122069
data:
  {"tuple:('role_data', 'step_config')": "include tripleo::profile::base::sshd", "tuple:('role_data', 'config_settings')": {"tripleo::profile::base::sshd::bannertext": "", "tripleo::profile::base::sshd::motd": "", "tripleo::profile::base::sshd::options": {"HostKey": ["/etc/ssh/ssh_host_rsa_key", "/etc/ssh/ssh_host_ecdsa_key", "/etc/ssh/ssh_host_ed25519_key"], "SyslogFacility": "AUTHPRIV", "AuthorizedKeysFile": ".ssh/authorized_keys", "ChallengeResponseAuthentication": "no", "GSSAPIAuthentication": "no", "GSSAPICleanupCredentials": "no", "UsePAM": "yes", "UseDNS": "no", "PrintMotd": "no", "X11Forwarding": "yes", "AcceptEnv": ["LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES", "LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT", "LC_IDENTIFICATION LC_ALL LANGUAGE", "XMODIFIERS"], "Subsystem": "sftp  /usr/libexec/openssh/sftp-server"}, "tripleo::profile::base::sshd::password_authentication": "yes"}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-40-ortbfllx2iko-SshdBase-pp6vypl2juol/5445752c-808e-42fd-913e-deee13473fb8"}


created_at: 2026-06-13 07:32:53.133918
data:
  {"tuple:('role_data', 'step_config')": null, "tuple:('role_data', 'container_config_scripts')": null, "tuple:('role_data', 'docker_config')": {"step_4": {"nova_migration_target": {"image": "registry.redhat.io/rhosp-rhel9/openstack-nova-compute:17.1", "net": "host", "privileged": true, "user": "root", "restart": "always", "healthcheck": {"test": "/openstack/healthcheck"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/lib/kolla/config_files/nova-migration-target.json:/var/lib/kolla/config_files/config.json:ro", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/etc/ssh:/host-ssh:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}}}, "tuple:('role_data', 'service_name')": "nova_migration_target", "role_data": {"service_name": "nova_migration_target", "firewall_rules": {"113 nova_migration_target accept libvirt subnet 172.17.0.0/24": {"source": "172.17.0.0/24", "proto": "tcp", "dport": 2022}, "113 nova_migration_target accept api subnet 172.17.0.0/24": {"source": "172.17.0.0/24", "proto": "tcp", "dport": 2022}}, "config_settings": {"tripleo::profile::base::sshd::bannertext": "", "tripleo::profile::base::sshd::motd": "", "tripleo::profile::base::sshd::options": {"HostKey": ["/etc/ssh/ssh_host_rsa_key", "/etc/ssh/ssh_host_ecdsa_key", "/etc/ssh/ssh_host_ed25519_key"], "SyslogFacility": "AUTHPRIV", "AuthorizedKeysFile": ".ssh/authorized_keys", "ChallengeResponseAuthentication": "no", "GSSAPIAuthentication": "no", "GSSAPICleanupCredentials": "no", "UsePAM": "yes", "UseDNS": "no", "PrintMotd": "no", "X11Forwarding": "yes", "AcceptEnv": ["LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES", "LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT", "LC_IDENTIFICATION LC_ALL LANGUAGE", "XMODIFIERS"], "Subsystem": "sftp  /usr/libexec/openssh/sftp-server"}, "tripleo::profile::base::sshd::password_authentication": "yes", "tripleo::profile::base::nova::migration::target::ssh_authorized_keys": ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0Qd8yp78JR+yKNCmgkeCQa1e7uiUyoZOVuJHfD9o6bJxKUvINELUYW5pJdpGZnMMSgKUcZB4xxzZ43OL952ByN3Rmf3NScKarvBtwNiAifCc2BzBruPD+wLDsWB8vmuMm6zR0ZLBwb5ppK1SyNwXR/QrBMKcxg84FCagOZ9wsz8pfASDrE++hR5dYua6JhSFfw6/r+nNDyqGPCHlDEwZKYOqQT2T6DUAdQBUKfHUfsAF8uBYODmcO37PU867Dra23NOMiJMmQ48bPJOA9JQzwb7Ny9VR6DpHS2xSPlJ0h2nHqV1GJuNFSjp35s7IGcr8IsppdVbTAUxSWp/m84oQf Generated by TripleO"], "tripleo::profile::base::nova::migration::target::ssh_localaddrs": ["%{hiera('cold_migration_ssh_inbound_addr')}", "%{hiera('live_migration_ssh_inbound_addr')}"], "live_migration_ssh_inbound_addr": "%{hiera('internal_api')}", "cold_migration_ssh_inbound_addr": "%{hiera('internal_api')}", "tripleo::profile::base::sshd::port": [22]}, "puppet_config": {"config_volume": "nova_libvirt", "step_config": "include tripleo::profile::base::sshd\ninclude tripleo::profile::base::nova::migration::target", "config_image": "registry.redhat.io/rhosp-rhel9/openstack-nova-libvirt:17.1"}, "kolla_config": {"/var/lib/kolla/config_files/nova-migration-target.json": {"command": "dumb-init --single-child -- /usr/sbin/sshd -D -p 2022", "config_files": [{"source": "/var/lib/kolla/config_files/src/*", "dest": "/", "merge": true, "preserve_properties": true}, {"source": "/host-ssh/ssh_host_*_key", "dest": "/etc/ssh/", "owner": "root", "perm": "0600"}]}}, "host_prep_tasks": [{"name": "Create libvirt persistent data directories", "file": {"path": "{{ item.path }}", "state": "directory", "setype": "{{ item.setype }}"}, "loop": [{"path": "/run/libvirt", "setype": "virt_var_run_t"}]}, {"name": "ensure /run/libvirt is present upon reboot", "copy": {"dest": "/etc/tmpfiles.d/run-libvirt.conf", "content": "d /run/libvirt 0755 root root - -\n"}}], "docker_config": {"step_4": {"nova_migration_target": {"image": "registry.redhat.io/rhosp-rhel9/openstack-nova-compute:17.1", "net": "host", "privileged": true, "user": "root", "restart": "always", "healthcheck": {"test": "/openstack/healthcheck"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/lib/kolla/config_files/nova-migration-target.json:/var/lib/kolla/config_files/config.json:ro", "/var/lib/config-data/puppet-generated/nova_libvirt:/var/lib/kolla/config_files/src:ro", "/etc/ssh:/host-ssh:ro", "/run/libvirt:/run/libvirt:shared,z", "/var/lib/nova:/var/lib/nova:shared"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}}}, "deploy_steps_tasks": [{"name": "validate nova-migration-target container state", "containers.podman.podman_container_info": {"name": "nova_migration_target"}, "register": "nova_migration_target_infos", "failed_when": ["nova_migration_target_infos.containers.0.Healthcheck.Status is defined", "'healthy' not in nova_migration_target_infos.containers.0.Healthcheck.Status"], "retries": 10, "delay": 30, "tags": ["opendev-validation", "opendev-validation-nova"], "when": ["container_cli == 'podman'", "not container_healthcheck_disabled", "step|int == 5"]}], "update_tasks": [{"name": "nova_migration_target_tmpfile_cleanup", "when": "step|int == 1", "block": [{"name": "Remove old tmpfiles.d config", "file": {"path": "/etc/tmpfiles.d/var-run-libvirt.conf", "state": "absent"}}]}], "upgrade_tasks": [{"name": "nova_migration_target_tmpfile_cleanup", "when": "step|int == 1", "block": [{"name": "Remove old tmpfiles.d config", "file": {"path": "/etc/tmpfiles.d/var-run-libvirt.conf", "state": "absent"}}]}]}, "tuple:('role_data', 'service_names')": null, "tuple:('role_data', 'config_settings')": {"tripleo::profile::base::sshd::bannertext": "", "tripleo::profile::base::sshd::motd": "", "tripleo::profile::base::sshd::options": {"HostKey": ["/etc/ssh/ssh_host_rsa_key", "/etc/ssh/ssh_host_ecdsa_key", "/etc/ssh/ssh_host_ed25519_key"], "SyslogFacility": "AUTHPRIV", "AuthorizedKeysFile": ".ssh/authorized_keys", "ChallengeResponseAuthentication": "no", "GSSAPIAuthentication": "no", "GSSAPICleanupCredentials": "no", "UsePAM": "yes", "UseDNS": "no", "PrintMotd": "no", "X11Forwarding": "yes", "AcceptEnv": ["LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES", "LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT", "LC_IDENTIFICATION LC_ALL LANGUAGE", "XMODIFIERS"], "Subsystem": "sftp  /usr/libexec/openssh/sftp-server"}, "tripleo::profile::base::sshd::password_authentication": "yes", "tripleo::profile::base::nova::migration::target::ssh_authorized_keys": ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0Qd8yp78JR+yKNCmgkeCQa1e7uiUyoZOVuJHfD9o6bJxKUvINELUYW5pJdpGZnMMSgKUcZB4xxzZ43OL952ByN3Rmf3NScKarvBtwNiAifCc2BzBruPD+wLDsWB8vmuMm6zR0ZLBwb5ppK1SyNwXR/QrBMKcxg84FCagOZ9wsz8pfASDrE++hR5dYua6JhSFfw6/r+nNDyqGPCHlDEwZKYOqQT2T6DUAdQBUKfHUfsAF8uBYODmcO37PU867Dra23NOMiJMmQ48bPJOA9JQzwb7Ny9VR6DpHS2xSPlJ0h2nHqV1GJuNFSjp35s7IGcr8IsppdVbTAUxSWp/m84oQf Generated by TripleO"], "tripleo::profile::base::nova::migration::target::ssh_localaddrs": ["%{hiera('cold_migration_ssh_inbound_addr')}", "%{hiera('live_migration_ssh_inbound_addr')}"], "live_migration_ssh_inbound_addr": "%{hiera('internal_api')}", "cold_migration_ssh_inbound_addr": "%{hiera('internal_api')}", "tripleo::profile::base::sshd::port": [22]}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-40-ortbfllx2iko/1af00285-8356-4e29-87de-752b4acfeaaa"}


created_at: 2026-06-13 07:32:54.501339
data:
  {"type": "json", "value": {"ContainerNovaVncProxyImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-novncproxy:17.1", "ContainerNovaConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-api:17.1"}}


created_at: 2026-06-13 07:32:54.532214
data:
  {"value": {"ContainerNovaVncProxyImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-novncproxy:17.1", "ContainerNovaConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-api:17.1"}}


created_at: 2026-06-13 07:32:54.608410
data:
  {"ContainerNovaImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-novncproxy:17.1", "NovaServiceName": "vncproxy"}


created_at: 2026-06-13 07:32:55.767232
data:
  {"type": "json", "value": {"ContainerNovaImage": "registry.redhat.io/rhosp-rhel9/openstack-nova-novncproxy:17.1"}}


created_at: 2026-06-13 07:32:59.609653
data:
  {"volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro"], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-41-magdhrhectw6-ContainersCommon-dwt5ccjwv5hb/3ddf0377-e8a9-4234-9095-635b912b1f93"}


created_at: 2026-06-13 07:32:59.662289
data:
  {"tuple:('role_data', 'step_config')": "include tripleo::profile::base::database::mysql::client", "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-41-magdhrhectw6-MySQLClient-4dfs25w6inf7/527d1315-4544-4613-ad84-229cfee44b3b"}


created_at: 2026-06-13 07:32:59.731743
data:
  {"tuple:('role_data', 'config_settings')": {"nova::my_ip": "%{hiera('internal_api')}", "nova::rabbit_use_ssl": "True", "nova::keystone::service_user::send_service_user_token": true, "nova::keystone::service_user::project_name": "service", "nova::keystone::service_user::password": "ksmPDM6JveiqLvoFg56EAxny1", "nova::keystone::service_user::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::keystone::service_user::region_name": "regionOne", "nova::placement::project_name": "service", "nova::placement::password": "H4Zat7IGHRAxn3vftDX6FGvMZ", "nova::placement::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::placement::region_name": "regionOne", "nova::placement::valid_interfaces": "internal", "nova::os_region_name": "regionOne", "nova::logging::debug": true, "nova::purge_config": false, "nova::network::neutron::project_name": "service", "nova::network::neutron::username": "neutron", "nova::network::neutron::region_name": "regionOne", "nova::dhcp_domain": "", "nova::network::neutron::password": "CC70wbFRk1QjXjqZLaKBjXfHn", "nova::network::neutron::auth_url": "https://overcloud.internalapi.ooo.test:5000/v3", "nova::network::neutron::valid_interfaces": "internal", "nova::glance::valid_interfaces": "internal", "nova::rabbit_heartbeat_timeout_threshold": 60, "nova::cinder_catalog_info": "volumev3:cinderv3:internalURL", "nova::host": "%{hiera('fqdn_canonical')}", "nova::notify_on_state_change": "vm_and_task_state", "nova::notification_driver": ["noop"], "nova::notification_format": "unversioned", "nova::network::neutron::auth_type": "v3password", "nova::db::database_db_max_retries": -1, "nova::db::database_max_retries": -1, "nova::network::neutron::ovs_bridge": "br-int", "nova::compute::sync_power_state_interval": 600, "nova_is_additional_cell": false, "nova::cross_az_attach": true, "nova::cache::enabled": true, "nova::cache::tls_enabled": true, "nova::cache::backend": "dogpile.cache.pymemcache", "nova::rabbit_heartbeat_in_pthread": false, "nova::ovsdb_connection": ""}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-41-magdhrhectw6-NovaBase-fevrkl4uhu2i/4f918c99-be5f-40a9-b5c6-67d5f9de6b13"}


created_at: 2026-06-13 07:32:59.760270
data:
  {"tuple:('role_data', 'config_settings')": {"nova::database_connection": "mysql+pymysql://nova:ksmPDM6JveiqLvoFg56EAxny1@overcloud.internalapi.ooo.test/nova?read_default_file=/etc/my.cnf.d/tripleo.cnf&read_default_group=tripleo"}, "tuple:('role_data', 'service_config_settings', 'mysql')": {"nova::db::mysql::password": "ksmPDM6JveiqLvoFg56EAxny1", "nova::db::mysql::user": "nova", "nova::db::mysql::host": "%", "nova::db::mysql::dbname": "nova"}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-41-magdhrhectw6-NovaDBClient-um4zaz56f3gq/bbca3cb2-5883-42d7-96f3-2aed6c817d89"}


created_at: 2026-06-13 07:32:59.876562
data:
  {"cmd_extra_args": "", "volumes": ["/var/log/containers/nova:/var/log/nova"], "config_settings": null, "host_prep_tasks": [{"name": "create persistent directories", "file": {"path": "{{ item.path }}", "setype": "{{ item.setype }}", "state": "directory", "mode": "{{ item.mode }}"}, "with_items": [{"path": "/var/log/containers/nova", "setype": "container_file_t", "mode": "0750"}]}], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-41-magdhrhectw6-NovaLogging-ejzfnuag2uk6/50b8afa1-6b2e-4cf7-b13a-f386c4ca381d"}


created_at: 2026-06-13 07:32:59.889409
data:
  {"tuple:('role_data', 'step_config')": null, "tuple:('role_data', 'container_config_scripts')": null, "tuple:('role_data', 'docker_config')": {"step_4": {"nova_vnc_proxy": {"image": "registry.redhat.io/rhosp-rhel9/openstack-nova-novncproxy:17.1", "net": "host", "privileged": false, "restart": "always", "healthcheck": {"test": "/openstack/healthcheck"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/nova:/var/log/nova", "/var/lib/kolla/config_files/nova_vnc_proxy.json:/var/lib/kolla/config_files/config.json:ro", "/var/lib/config-data/puppet-generated/nova:/var/lib/kolla/config_files/src:ro", "/etc/ipa/ca.crt:/etc/pki/CA/certs/vnc.crt:ro", "/etc/pki/tls/certs/libvirt-vnc-client-cert.crt:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/libvirt-vnc-client-cert.crt:ro", "/etc/pki/tls/private/libvirt-vnc-client-cert.key:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/libvirt-vnc-client-cert.key:ro", "/etc/pki/tls/certs/novnc-proxy.crt:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/novnc-proxy.crt:ro", "/etc/pki/tls/private/novnc-proxy.key:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/novnc-proxy.key:ro"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}}}, "tuple:('role_data', 'service_name')": "nova_vnc_proxy", "role_data": {"service_name": "nova_vnc_proxy", "firewall_rules": {"137 nova_vnc_proxy": {"dport": [6080]}}, "firewall_frontend_rules": {"100 nova_vncproxy_haproxy_frontend": {"dport": [6080]}}, "firewall_ssl_frontend_rules": {"100 nova_vncproxy_haproxy_frontend_ssl": {"dport": [13080]}}, "config_settings": {"nova::my_ip": "%{hiera('internal_api')}", "nova::rabbit_use_ssl": "True", "nova::keystone::service_user::send_service_user_token": true, "nova::keystone::service_user::project_name": "service", "nova::keystone::service_user::password": "ksmPDM6JveiqLvoFg56EAxny1", "nova::keystone::service_user::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::keystone::service_user::region_name": "regionOne", "nova::placement::project_name": "service", "nova::placement::password": "H4Zat7IGHRAxn3vftDX6FGvMZ", "nova::placement::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::placement::region_name": "regionOne", "nova::placement::valid_interfaces": "internal", "nova::os_region_name": "regionOne", "nova::logging::debug": true, "nova::purge_config": false, "nova::network::neutron::project_name": "service", "nova::network::neutron::username": "neutron", "nova::network::neutron::region_name": "regionOne", "nova::dhcp_domain": "", "nova::network::neutron::password": "CC70wbFRk1QjXjqZLaKBjXfHn", "nova::network::neutron::auth_url": "https://overcloud.internalapi.ooo.test:5000/v3", "nova::network::neutron::valid_interfaces": "internal", "nova::glance::valid_interfaces": "internal", "nova::rabbit_heartbeat_timeout_threshold": 60, "nova::cinder_catalog_info": "volumev3:cinderv3:internalURL", "nova::host": "%{hiera('fqdn_canonical')}", "nova::notify_on_state_change": "vm_and_task_state", "nova::notification_driver": ["noop"], "nova::notification_format": "unversioned", "nova::network::neutron::auth_type": "v3password", "nova::db::database_db_max_retries": -1, "nova::db::database_max_retries": -1, "nova::network::neutron::ovs_bridge": "br-int", "nova::compute::sync_power_state_interval": 600, "nova_is_additional_cell": false, "nova::cross_az_attach": true, "nova::cache::enabled": true, "nova::cache::tls_enabled": true, "nova::cache::backend": "dogpile.cache.pymemcache", "nova::rabbit_heartbeat_in_pthread": false, "nova::ovsdb_connection": "", "nova::database_connection": "mysql+pymysql://nova:ksmPDM6JveiqLvoFg56EAxny1@overcloud.internalapi.ooo.test/nova?read_default_file=/etc/my.cnf.d/tripleo.cnf&read_default_group=tripleo", "nova::vncproxy::enabled": true, "nova::vncproxy::common::vncproxy_protocol": "https", "nova::vncproxy::common::vncproxy_host": "standalone.ooo.test", "nova::vncproxy::common::vncproxy_port": "13080", "nova::vncproxy::host": "%{hiera('internal_api')}", "nova::vncproxy::allow_vencrypt": true, "nova::vncproxy::vencrypt_key": "/etc/pki/tls/private/libvirt-vnc-client-cert.key", "nova::vncproxy::vencrypt_cert": "/etc/pki/tls/certs/libvirt-vnc-client-cert.crt", "nova::vncproxy::vencrypt_ca": "/etc/pki/CA/certs/vnc.crt", "nova::ssl_only": true, "nova::console_ssl_minimum_version": "default", "nova::cert": "/etc/pki/tls/certs/novnc-proxy.crt", "nova::key": "/etc/pki/tls/private/novnc-proxy.key"}, "service_config_settings": {"rabbitmq": {"get_attr": ["NovaBase", "role_data", "service_config_settings"], "rabbitmq": null}, "mysql": {"nova::db::mysql::password": "ksmPDM6JveiqLvoFg56EAxny1", "nova::db::mysql::user": "nova", "nova::db::mysql::host": "%", "nova::db::mysql::dbname": "nova"}, "rsyslog": {"tripleo_logging_sources_nova_vnc_proxy": [{"tag": "openstack.nova.vncproxy", "file": "/var/log/containers/nova/nova-novncproxy.log"}]}}, "puppet_config": {"config_volume": "nova", "puppet_tags": "nova_config", "step_config": "include tripleo::profile::base::nova::vncproxy\ninclude tripleo::profile::base::database::mysql::client", "config_image": "registry.redhat.io/rhosp-rhel9/openstack-nova-api:17.1"}, "kolla_config": {"/var/lib/kolla/config_files/nova_vnc_proxy.json": {"command": "/usr/bin/nova-novncproxy --web /usr/share/novnc/ ", "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": [{"path": "/var/log/nova", "owner": "nova:nova", "recurse": true}, {"path": "/etc/pki/tls/certs/novnc-proxy.crt", "owner": "root:root", "perm": "0644"}, {"path": "/etc/pki/tls/private/novnc-proxy.key", "owner": "root:qemu", "perm": "0640"}, {"path": "/etc/pki/tls/certs/libvirt-vnc-client-cert.crt", "owner": "root:root", "perm": "0644"}, {"path": "/etc/pki/tls/private/libvirt-vnc-client-cert.key", "owner": "root:qemu", "perm": "0640"}]}}, "docker_config": {"step_4": {"nova_vnc_proxy": {"image": "registry.redhat.io/rhosp-rhel9/openstack-nova-novncproxy:17.1", "net": "host", "privileged": false, "restart": "always", "healthcheck": {"test": "/openstack/healthcheck"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/nova:/var/log/nova", "/var/lib/kolla/config_files/nova_vnc_proxy.json:/var/lib/kolla/config_files/config.json:ro", "/var/lib/config-data/puppet-generated/nova:/var/lib/kolla/config_files/src:ro", "/etc/ipa/ca.crt:/etc/pki/CA/certs/vnc.crt:ro", "/etc/pki/tls/certs/libvirt-vnc-client-cert.crt:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/libvirt-vnc-client-cert.crt:ro", "/etc/pki/tls/private/libvirt-vnc-client-cert.key:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/libvirt-vnc-client-cert.key:ro", "/etc/pki/tls/certs/novnc-proxy.crt:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/novnc-proxy.crt:ro", "/etc/pki/tls/private/novnc-proxy.key:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/novnc-proxy.key:ro"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}}}, "metadata_settings": [{"service": "libvirt-vnc", "network": "internal_api", "type": "node"}, {"service": "novnc-proxy", "network": "internal_api", "type": "node"}], "deploy_steps_tasks": [{"name": "validate nova-vnc-proxy container state", "containers.podman.podman_container_info": {"name": "nova_vnc_proxy"}, "register": "nova_vnc_proxy_infos", "failed_when": ["nova_vnc_proxy_infos.containers.0.Healthcheck.Status is defined", "'healthy' not in nova_vnc_proxy_infos.containers.0.Healthcheck.Status"], "retries": 10, "delay": 30, "tags": ["opendev-validation", "opendev-validation-nova"], "when": ["container_cli == 'podman'", "not container_healthcheck_disabled", "step|int == 5"]}, {"name": "Certificate generation", "when": "step|int == 1", "vars": {"cert_key_size": "2048", "nova_vnc_key_size": "", "libvirt_vnc_key_size": "", "libvirt_network": "{{ fqdn_internal_api }}"}, "block": [{"name": "Execute system role for Nova/Libvirt VNC certs", "loop": [{"name": "libvirt-vnc-client-cert", "key_size": "{{ libvirt_vnc_key_size | default(cert_key_size, true) }}", "principal": "libvirt-vnc/{{ libvirt_network }}@{{ idm_realm }}"}, {"name": "novnc-proxy", "key_size": "{{ nova_vnc_key_size | default(cert_key_size, true) }}", "principal": "novnc-proxy/{{ libvirt_network }}@{{ idm_realm }}"}], "loop_control": {"loop_var": "cert"}, "include_role": {"name": "linux-system-roles.certificate"}, "vars": {"certificate_requests": [{"name": "{{ cert.name }}", "dns": "{{ libvirt_network }}", "principal": "{{ cert.principal }}", "key_size": "{{ cert.key_size }}", "run_after": "container_name=$({{container_cli}} ps --format=\\{\\{.Names\\}\\} | grep nova_vnc_proxy)\nservice_crt=\"/etc/pki/tls/certs/{{ cert.name }}.crt\"\nservice_key=\"/etc/pki/tls/private/{{ cert.name }}.key\"\n# Copy the new cert from the mount-point to the real path\n{{container_cli}} exec -u root \"$container_name\" cp \"/var/lib/kolla/config_files/src-tls$service_crt\" \"$service_crt\"\n# Copy the new key from the mount-point to the real path\n{{container_cli}} exec -u root \"$container_name\" cp \"/var/lib/kolla/config_files/src-tls$service_key\" \"$service_key\"\n\n# Set permissions\n{{container_cli}} exec -u root \"$container_name\" chmod 0644 $service_crt\n{{container_cli}} exec -u root \"$container_name\" chmod 0640 $service_key\n{{container_cli}} exec -u root \"$container_name\" chgrp qemu $service_key\n\n# No need to trigger a reload for novnc proxy since the cert is not cached\n", "ca": "ipa"}]}}]}], "host_prep_tasks": [{"name": "create persistent directories", "file": {"path": "{{ item.path }}", "setype": "{{ item.setype }}", "state": "directory", "mode": "{{ item.mode }}"}, "with_items": [{"path": "/var/log/containers/nova", "setype": "container_file_t", "mode": "0750"}]}, {"name": "ensure qemu group is present on the host", "group": {"name": "qemu", "gid": 107, "state": "present"}}, {"name": "ensure qemu user is present on the host", "user": {"name": "qemu", "uid": 107, "group": "qemu", "state": "present", "shell": "/sbin/nologin", "comment": "qemu user"}}], "post_upgrade_tasks": [{"when": ["step|int == 3"], "become": true, "environment": {"OS_CLOUD": "standalone"}, "block": [{"name": "Get nova-consoleauth service ID", "command": "openstack compute service list --service nova-consoleauth --column ID  --column Host --format yaml", "register": "nova_compute_service_result", "check_mode": false, "run_once": true, "changed_when": false, "failed_when": false, "delegate_to": "{{ groups['Undercloud'] | first }}"}, {"name": "Deleting nova-consoleauth", "command": "openstack compute service delete {{ item.ID }}", "loop": "{{ nova_compute_service_result.stdout | from_yaml | default([]) }}", "run_once": true, "delegate_to": "{{ groups['Undercloud'] | first }}", "failed_when": false}]}], "external_upgrade_tasks": [{"when": ["step|int == 1"], "tags": ["never", "system_upgrade_transfer_data", "system_upgrade_stop_services"], "block": [{"name": "Stop nova vnc proxy container", "import_role": {"name": "tripleo_container_stop"}, "vars": {"tripleo_containers_to_stop": ["nova_vnc_proxy"], "tripleo_delegate_to": "{{ groups['nova_vnc_proxy'] | difference(groups['excluded_overcloud']) }}"}}]}]}, "tuple:('role_data', 'service_names')": null, "tuple:('role_data', 'config_settings')": {"nova::my_ip": "%{hiera('internal_api')}", "nova::rabbit_use_ssl": "True", "nova::keystone::service_user::send_service_user_token": true, "nova::keystone::service_user::project_name": "service", "nova::keystone::service_user::password": "ksmPDM6JveiqLvoFg56EAxny1", "nova::keystone::service_user::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::keystone::service_user::region_name": "regionOne", "nova::placement::project_name": "service", "nova::placement::password": "H4Zat7IGHRAxn3vftDX6FGvMZ", "nova::placement::auth_url": "https://overcloud.internalapi.ooo.test:5000", "nova::placement::region_name": "regionOne", "nova::placement::valid_interfaces": "internal", "nova::os_region_name": "regionOne", "nova::logging::debug": true, "nova::purge_config": false, "nova::network::neutron::project_name": "service", "nova::network::neutron::username": "neutron", "nova::network::neutron::region_name": "regionOne", "nova::dhcp_domain": "", "nova::network::neutron::password": "CC70wbFRk1QjXjqZLaKBjXfHn", "nova::network::neutron::auth_url": "https://overcloud.internalapi.ooo.test:5000/v3", "nova::network::neutron::valid_interfaces": "internal", "nova::glance::valid_interfaces": "internal", "nova::rabbit_heartbeat_timeout_threshold": 60, "nova::cinder_catalog_info": "volumev3:cinderv3:internalURL", "nova::host": "%{hiera('fqdn_canonical')}", "nova::notify_on_state_change": "vm_and_task_state", "nova::notification_driver": ["noop"], "nova::notification_format": "unversioned", "nova::network::neutron::auth_type": "v3password", "nova::db::database_db_max_retries": -1, "nova::db::database_max_retries": -1, "nova::network::neutron::ovs_bridge": "br-int", "nova::compute::sync_power_state_interval": 600, "nova_is_additional_cell": false, "nova::cross_az_attach": true, "nova::cache::enabled": true, "nova::cache::tls_enabled": true, "nova::cache::backend": "dogpile.cache.pymemcache", "nova::rabbit_heartbeat_in_pthread": false, "nova::ovsdb_connection": "", "nova::database_connection": "mysql+pymysql://nova:ksmPDM6JveiqLvoFg56EAxny1@overcloud.internalapi.ooo.test/nova?read_default_file=/etc/my.cnf.d/tripleo.cnf&read_default_group=tripleo", "nova::vncproxy::enabled": true, "nova::vncproxy::common::vncproxy_protocol": "https", "nova::vncproxy::common::vncproxy_host": "standalone.ooo.test", "nova::vncproxy::common::vncproxy_port": "13080", "nova::vncproxy::host": "%{hiera('internal_api')}", "nova::vncproxy::allow_vencrypt": true, "nova::vncproxy::vencrypt_key": "/etc/pki/tls/private/libvirt-vnc-client-cert.key", "nova::vncproxy::vencrypt_cert": "/etc/pki/tls/certs/libvirt-vnc-client-cert.crt", "nova::vncproxy::vencrypt_ca": "/etc/pki/CA/certs/vnc.crt", "nova::ssl_only": true, "nova::console_ssl_minimum_version": "default", "nova::cert": "/etc/pki/tls/certs/novnc-proxy.crt", "nova::key": "/etc/pki/tls/private/novnc-proxy.key"}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-41-magdhrhectw6/0440e518-dac9-4fcf-ade3-03805d1b8614"}


created_at: 2026-06-13 07:33:00.215966
data:
  {"type": "json", "value": {"ovn_bridge_mappings": ["datacentre:br-ctlplane"], "ovn_static_bridge_mac_mappings": {"standalone": {"datacentre": "fa:16:3a:00:53:00"}}}}


created_at: 2026-06-13 07:33:02.245456
data:
  {"type": "json", "value": {"ovn::controller::ovn_bridge_mappings": ["datacentre:br-ctlplane"], "ovn::controller::ovn_cms_options": "enable-chassis-as-gw", "ovn::controller::ovn_encap_tos": "0", "vswitch::ovs::enable_hw_offload": false, "container_cpuset_cpus": "", "ContainerOvnControllerImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "ContainerOvnControllerConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1"}}


created_at: 2026-06-13 07:33:03.323232
data:
  {"volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro"], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-42-inurourfbbjc-ContainersCommon-pgd5tbnoknc2/2274067c-7be4-44d3-9553-2e79ab7616e3"}


created_at: 2026-06-13 07:33:03.328323
data:
  {"value": {"ovn::controller::ovn_bridge_mappings": ["datacentre:br-ctlplane"], "ovn::controller::ovn_cms_options": "enable-chassis-as-gw", "ovn::controller::ovn_encap_tos": "0", "vswitch::ovs::enable_hw_offload": false, "container_cpuset_cpus": "", "ContainerOvnControllerImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "ContainerOvnControllerConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1"}}


created_at: 2026-06-13 07:33:03.332775
data:
  {"value": {"ovn_bridge_mappings": ["datacentre:br-ctlplane"], "ovn_static_bridge_mac_mappings": {"standalone": {"datacentre": "fa:16:3a:00:53:00"}}}}


created_at: 2026-06-13 07:33:03.347937
data:
  {"tuple:('role_data', 'step_config')": null, "tuple:('role_data', 'container_config_scripts')": null, "tuple:('role_data', '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": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/lib/modules:/lib/modules:ro", "/run/openvswitch:/run/openvswitch:shared,z"], "environment": {"TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}, "ovn_controller": {"start_order": 1, "image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "net": "host", "privileged": true, "user": "root", "restart": "always", "depends_on": ["openvswitch.service"], "healthcheck": {"test": "/openstack/healthcheck 6642"}, "volumes": ["/var/lib/kolla/config_files/ovn_controller.json:/var/lib/kolla/config_files/config.json:ro", "/lib/modules:/lib/modules:ro", "/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", "/etc/ipa/ca.crt:/etc/ipa/ca.crt: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"}}}}, "tuple:('role_data', 'service_name')": "ovn_controller", "role_data": {"service_name": "ovn_controller", "firewall_rules": {"118 neutron vxlan networks": {"proto": "udp", "dport": 4789, "state": []}, "119 neutron geneve networks": {"proto": "udp", "dport": 6081, "state": []}, "120 neutron geneve networks no conntrack": {"proto": "udp", "dport": 6081, "table": "raw", "chain": "OUTPUT", "jump": "NOTRACK", "action": "append", "state": ["INVALID"]}, "121 neutron geneve networks no conntrack": {"proto": "udp", "dport": 6081, "table": "raw", "chain": "PREROUTING", "jump": "NOTRACK", "action": "append", "state": ["INVALID"]}}, "config_settings": {"ovn::controller::ovn_bridge_mappings": ["datacentre:br-ctlplane"], "ovn::controller::ovn_cms_options": "enable-chassis-as-gw", "ovn::controller::ovn_encap_tos": "0", "vswitch::ovs::enable_hw_offload": false, "container_cpuset_cpus": "", "ContainerOvnControllerImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "ContainerOvnControllerConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "ovn::southbound::port": 6642, "ovn::controller::ovn_encap_ip": "%{hiera('tenant')}", "ovn::controller::ovn_encap_type": "geneve", "ovn::controller::ovn_bridge": "br-int", "ovn::controller::hostname": "%{hiera('fqdn_canonical')}", "ovn::controller::ovn_remote_probe_interval": 60000, "ovn::controller::ovn_openflow_probe_interval": 60, "ovn::controller::ovn_ofctrl_wait_before_clear": 8000, "ovn::controller::garp_max_timeout_sec": 0, "ovn::controller::ovn_monitor_all": true, "tripleo::profile::base::neutron::agents::ovn::protocol": "ssl"}, "service_config_settings": {}, "puppet_config": {"puppet_tags": "vs_config,exec", "config_volume": "ovn_controller", "step_config": "include tripleo::profile::base::neutron::agents::ovn\n", "config_image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "volumes": ["/lib/modules:/lib/modules:ro", "/run/openvswitch:/run/openvswitch:shared,z", "/etc/sysconfig/modules:/etc/sysconfig/modules"]}, "kolla_config": {"/var/lib/kolla/config_files/ovn_controller.json": {"command": "/usr/bin/ovn-controller --pidfile --log-file unix:/run/openvswitch/db.sock -p /etc/pki/tls/private/ovn_controller.key -c /etc/pki/tls/certs/ovn_controller.crt -C /etc/ipa/ca.crt", "permissions": [{"path": "/var/log/openvswitch", "owner": "root:root", "recurse": true}, {"path": "/var/log/ovn", "owner": "root:root", "recurse": true}]}}, "metadata_settings": [{"service": "ovn_controller", "network": "internal_api", "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": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/lib/modules:/lib/modules:ro", "/run/openvswitch:/run/openvswitch:shared,z"], "environment": {"TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}, "ovn_controller": {"start_order": 1, "image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "net": "host", "privileged": true, "user": "root", "restart": "always", "depends_on": ["openvswitch.service"], "healthcheck": {"test": "/openstack/healthcheck 6642"}, "volumes": ["/var/lib/kolla/config_files/ovn_controller.json:/var/lib/kolla/config_files/config.json:ro", "/lib/modules:/lib/modules:ro", "/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", "/etc/ipa/ca.crt:/etc/ipa/ca.crt: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": "{{fqdn_internal_api}}", "principal": "ovn_controller/{{fqdn_internal_api}}@{{idm_realm}}", "run_after": "systemctl restart tripleo_ovn_controller\n", "key_size": "2048", "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": "#!/usr/bin/bash\n# Cleanup neutron OVS bridges. To be called on startup to avoid\n# \"difficult-to-debug\" issues with partially configured resources.\n\nNEUTRON_OVS_CONF=/var/lib/config-data/puppet-generated/neutron/etc/neutron/plugins/ml2/openvswitch_agent.ini\n\nif [ -e ${NEUTRON_OVS_CONF} ];\nthen\n    INT_BRIDGE=`crudini --get ${NEUTRON_OVS_CONF} ovs integration_bridge`\n    TUN_BRIDGE=`crudini --get ${NEUTRON_OVS_CONF} ovs tunnel_bridge`\nfi\n\nfor port in `ovs-vsctl list-ports ${INT_BRIDGE:-\"br-int\"}`;\ndo\n    skip_cleanup=`ovs-vsctl --if-exists get Interface $port external_ids:skip_cleanup`\n    if ! [[ \"x$skip_cleanup\" == \"x\\\"true\\\"\" ]];\n    then\n        ovs-vsctl del-port ${INT_BRIDGE:-\"br-int\"} $port\n    fi\ndone\n\novs-vsctl --if-exists del-br ${TUN_BRIDGE:-\"br-tun\"}\n\n# Clean up trunk port bridges\nfor br in $(ovs-vsctl list-br | egrep 'tbr-[0-9a-f\\-]+'); do\n    ovs-vsctl --if-exists del-br $br\ndone\n", "dest": "/usr/libexec/neutron-cleanup", "force": true, "mode": "0755"}}, {"name": "Copy in cleanup service", "copy": {"content": "[Unit]\nDescription=Neutron cleanup on startup\nAfter=openvswitch.service network.target\nBefore=tripleo_neutron_ovs_agent.service tripleo_neutron_dhcp.service tripleo_neutron_l3_agent.service tripleo_nova_compute.service\nRefuseManualStop=yes\n\n[Service]\nType=oneshot\nExecStart=/usr/libexec/neutron-cleanup\n\n[Install]\nWantedBy=multi-user.target\n", "dest": "/usr/lib/systemd/system/neutron-cleanup.service", "force": true}}, {"name": "Enabling the cleanup service", "service": {"name": "neutron-cleanup", "enabled": true}, "when": "not (ansible_check_mode|bool)"}], "external_deploy_tasks": [{"when": ["step|int == 0"], "name": "ovn_controller_external_deploy_init", "block": [{"name": "create ovn mac address for Standalone role nodes", "tripleo_ovn_mac_addresses": {"playbook_dir": "{{ playbook_dir }}", "stack_name": "standalone", "role_name": "Standalone", "server_resource_names": "{{ groups[\"Standalone\"] }}", "ovn_bridge_mappings": ["datacentre:br-ctlplane"], "ovn_static_bridge_mac_mappings": {"standalone": {"datacentre": "fa:16:3a:00:53:00"}}}}]}], "external_update_tasks": [{"name": "Force pull image in case image name doesn't change.", "when": "step|int == 1", "tags": ["ovn", "ovn_image"], "become": true, "loop": "{{ groups['ovn_controller'] | difference(groups['excluded_overcloud']) }}", "delegate_to": "{{ item }}", "async": 600, "poll": 0, "register": "ovn_controller_image_update", "containers.podman.podman_image": {"name": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "validate_certs": false, "force": true}}, {"name": "Was the ovn_controller image pull successful.", "when": ["step|int == 1", "'results' in ovn_controller_image_update"], "tags": ["ovn", "ovn_image"], "become": true, "delegate_to": "{{ async_result_item.item }}", "async_status": {"jid": "{{ async_result_item.ansible_job_id }}"}, "loop": "{{ovn_controller_image_update.results }}", "loop_control": {"loop_var": "async_result_item"}, "register": "async_poll_results", "until": "async_poll_results.finished", "retries": 600, "delay": 1}, {"name": "OVN Container image used", "debug": {"msg": "ovn container will be using {{ image }}"}, "vars": {"image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1"}, "when": "step|int == 1", "tags": "ovn"}, {"name": "Update OVN OVS related parameters before update.", "when": ["step|int == 1"], "tags": ["ovn"], "become": true, "vars": {"timeout": 8000}, "shell": "set -e\novs-vsctl set Open_vSwitch . external_ids:ovn-ofctrl-wait-before-clear={{ timeout }}\novs-vsctl set Open_vSwitch . external_ids:ovn-monitor-all=true\novs-vsctl set Open_vSwitch . external_ids:ovn-match-northd-version=false\n", "async": 600, "poll": 0, "register": "ovs_vsctl", "loop": "{{ groups['ovn_controller'] | difference(groups['excluded_overcloud']) }}", "delegate_to": "{{ item }}"}, {"name": "Was the update of OVN OVS related parameter successful.", "when": ["step|int == 1", "'results' in ovs_vsctl"], "become": true, "tags": ["ovn"], "delegate_to": "{{ async_result_item.item }}", "async_status": {"jid": "{{ async_result_item.ansible_job_id }}"}, "loop": "{{ovs_vsctl.results }}", "loop_control": {"loop_var": "async_result_item"}, "register": "async_poll_results", "until": "async_poll_results.finished", "retries": 600, "delay": 1}, {"set_fact": {"any_ovn_host": "{{groups['ovn_controller'] | difference(groups['excluded_overcloud']) | first }}"}, "tags": "ovn", "when": "step|int == 1"}, {"name": "Find ovn_controller configs in container-startup-configs", "find": {"paths": "/var/lib/tripleo-config/container-startup-config/", "patterns": "*ovn_controller.json", "recurse": true}, "register": "ovn_cont_17_0", "delegate_to": "{{ any_ovn_host }}", "when": "(step|int == 1) and (any_ovn_host is defined) and (any_ovn_host|length > 0)", "tags": ["ovn"], "become": true}, {"name": "get directory path from the ovn_cont_17_0", "set_fact": {"ovn_config_path": "{{ ovn_cont_17_0.files.0.path | dirname }}"}, "when": "step|int == 1", "tags": "ovn"}, {"name": "Get PIDfile used by systemd on each ovn node", "when": ["step|int == 1"], "tags": ["ovn"], "become": true, "shell": "set -e\ngrep PID /etc/systemd/system/tripleo_ovn_controller.service | cut -d= -f2\n", "register": "pidfile", "loop": "{{ groups['ovn_controller'] | difference(groups['excluded_overcloud']) }}", "delegate_to": "{{ item }}"}, {"name": "Update ovn_controller.", "vars": {"config_step": "{{ ('step_4' in ovn_config_path) | ternary('4', '3')}}", "query": "results[?item == '{{item}}'].stdout"}, "when": "step|int == 1", "tags": "ovn", "become": true, "loop": "{{ groups['ovn_controller'] | difference(groups['excluded_overcloud']) }}", "delegate_to": "{{ item }}", "async": 600, "poll": 0, "register": "ovn_controller_update", "tripleo_container_manage": {"config_dir": "{{ ovn_config_path }}", "config_patterns": "*ovn_controller.json", "config_id": ["tripleo_step{{config_step}}"], "log_base_path": "{{ container_log_stdout_path }}", "debug": "{{ enable_debug | bool }}", "config_overrides": {".*ovn_controller": {"image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "conmon_pidfile": "{{ pidfile | json_query(query) | first }}", "name": "ovn_controller"}}}}, {"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": 600, "delay": 1}, {"name": "Pause for 30s to give ovn_controllers time to reconnect to dbs", "when": ["step|int == 1"], "tags": "ovn", "wait_for": {"timeout": 30}}], "upgrade_tasks": [{"name": "Fetch running ovn_controller image", "shell": "set -e\npodman inspect --format \"{{'{{'}}.ImageName{{'}}'}}\" ovn_controller\n", "register": "running_ovn_image", "when": ["step|int == 4"], "tags": ["ovn", "ovn_image"]}, {"name": "Run ovn_controller upgrade", "tags": ["ovn", "ovn_image"], "vars": {"ovn_controller_image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1"}, "when": ["step|int == 4", "running_ovn_image.stdout != ovn_controller_image"], "block": [{"name": "Force pull image in case image name doesn't change.", "when": "step|int == 4", "tags": ["ovn", "ovn_image"], "containers.podman.podman_image": {"name": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "validate_certs": false, "force": true}}, {"name": "Update OVN OVS related parameters before update.", "when": ["step|int == 4"], "tags": ["ovn"], "vars": {"timeout": 8000}, "shell": "set -e\novs-vsctl set Open_vSwitch . external_ids:ovn-ofctrl-wait-before-clear={{ timeout }}\novs-vsctl set Open_vSwitch . external_ids:ovn-monitor-all=true\novs-vsctl set Open_vSwitch . external_ids:ovn-match-northd-version=false\n"}, {"name": "Find ovn_controller configs in container-startup-configs", "find": {"paths": "/var/lib/tripleo-config/container-startup-config/", "patterns": "*ovn_controller.json", "recurse": true}, "register": "ovn_cont_17_0", "when": ["step|int == 4"], "tags": ["ovn"]}, {"name": "get directory path from the ovn_cont_17_0", "set_fact": {"ovn_config_path": "{{ ovn_cont_17_0.files.0.path | dirname }}"}, "when": "step|int == 4", "tags": "ovn"}, {"name": "Get PIDfile used by systemd on each ovn node", "when": ["step|int == 4"], "tags": ["ovn"], "shell": "set -e\ngrep PID /etc/systemd/system/tripleo_ovn_controller.service | cut -d= -f2\n", "register": "pidfile"}, {"name": "Update ovn_controller.", "vars": {"config_step": "{{ ('step_4' in ovn_config_path) | ternary('4', '3')}}"}, "when": "step|int == 4", "tags": "ovn", "tripleo_container_manage": {"config_dir": "{{ ovn_config_path }}", "config_patterns": "*ovn_controller.json", "config_id": ["tripleo_step{{config_step}}"], "log_base_path": "{{ container_log_stdout_path }}", "debug": "{{ enable_debug | bool }}", "config_overrides": {".*ovn_controller": {"image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "conmon_pidfile": "{{ pidfile.stdout }}", "name": "ovn_controller"}}}}, {"name": "Pause for 30s to give ovn_controllers time to reconnect to dbs", "when": ["step|int == 4"], "tags": "ovn", "wait_for": {"timeout": 30}}]}], "scale_tasks": [{"when": ["step|int == 1", "container_cli == 'podman'"], "tags": "down", "become": true, "environment": {"OS_CLOUD": "standalone"}, "block": [{"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}]}]}]}, "tuple:('role_data', 'service_names')": null, "tuple:('role_data', 'config_settings')": {"ovn::controller::ovn_bridge_mappings": ["datacentre:br-ctlplane"], "ovn::controller::ovn_cms_options": "enable-chassis-as-gw", "ovn::controller::ovn_encap_tos": "0", "vswitch::ovs::enable_hw_offload": false, "container_cpuset_cpus": "", "ContainerOvnControllerImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "ContainerOvnControllerConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-controller:17.1", "ovn::southbound::port": 6642, "ovn::controller::ovn_encap_ip": "%{hiera('tenant')}", "ovn::controller::ovn_encap_type": "geneve", "ovn::controller::ovn_bridge": "br-int", "ovn::controller::hostname": "%{hiera('fqdn_canonical')}", "ovn::controller::ovn_remote_probe_interval": 60000, "ovn::controller::ovn_openflow_probe_interval": 60, "ovn::controller::ovn_ofctrl_wait_before_clear": 8000, "ovn::controller::garp_max_timeout_sec": 0, "ovn::controller::ovn_monitor_all": true, "tripleo::profile::base::neutron::agents::ovn::protocol": "ssl"}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-42-inurourfbbjc/a871deed-5fba-4066-b47e-ed56d6bb8cbe"}


created_at: 2026-06-13 07:33:04.644398
data:
  {"type": "json", "value": {"ContainerOvnNbDbImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-nb-db-server:17.1", "ContainerOvnSbDbImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-sb-db-server:17.1", "ContainerOvnNorthdImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-northd:17.1", "ContainerNeutronApiImage": "registry.redhat.io/rhosp-rhel9/openstack-neutron-server:17.1", "ContainerOvnMetadataImage": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1"}}


created_at: 2026-06-13 07:33:05.793057
data:
  {"volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro"], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-43-dzwzxcc2l4si-ContainersCommon-sshgjv2fnlfr/352b58eb-c7e9-4322-9b79-9154fd74b9d5"}


created_at: 2026-06-13 07:33:05.809024
data:
  {"value": {"ContainerOvnNbDbImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-nb-db-server:17.1", "ContainerOvnSbDbImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-sb-db-server:17.1", "ContainerOvnNorthdImage": "registry.redhat.io/rhosp-rhel9/openstack-ovn-northd:17.1", "ContainerNeutronApiImage": "registry.redhat.io/rhosp-rhel9/openstack-neutron-server:17.1", "ContainerOvnMetadataImage": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1"}}


created_at: 2026-06-13 07:33:05.824871
data:
  {"tuple:('role_data', 'step_config')": null, "tuple:('role_data', 'container_config_scripts')": null, "tuple:('role_data', 'docker_config')": {"step_0": {"ovn_cluster_north_db_server": {"start_order": 0, "image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-nb-db-server:17.1", "net": "host", "privileged": false, "restart": "always", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/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", "/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"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}, "ovn_cluster_south_db_server": {"start_order": 0, "image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-sb-db-server:17.1", "net": "host", "privileged": false, "restart": "always", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/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", "/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"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}, "ovn_cluster_northd": {"start_order": 2, "image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-northd:17.1", "net": "host", "privileged": false, "restart": "always", "healthcheck": {"test": "/openstack/healthcheck"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/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", "/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"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}}}, "tuple:('role_data', 'service_name')": "ovn_dbs", "role_data": {"service_name": "ovn_dbs", "firewall_rules": {"121 OVN DB server and cluster ports for 172.17.0.0/24": {"proto": "tcp", "source": "172.17.0.0/24", "dport": [6641, 6642, 6643, 6644]}}, "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": [{"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": [{"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": [{"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": [{"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_northd.json": {"command": "bash -c $* -- eval source /etc/sysconfig/ovn_cluster; exec /usr/bin/ovn-northd ${OVN_NORTHD_OPTS}", "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": [{"path": "/var/log/openvswitch", "owner": "root:root", "recurse": true}, {"path": "/var/log/ovn", "owner": "root:root", "recurse": true}]}}, "docker_config": {"step_0": {"ovn_cluster_north_db_server": {"start_order": 0, "image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-nb-db-server:17.1", "net": "host", "privileged": false, "restart": "always", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/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", "/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"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}, "ovn_cluster_south_db_server": {"start_order": 0, "image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-sb-db-server:17.1", "net": "host", "privileged": false, "restart": "always", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/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", "/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"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}, "ovn_cluster_northd": {"start_order": 2, "image": "registry.redhat.io/rhosp-rhel9/openstack-ovn-northd:17.1", "net": "host", "privileged": false, "restart": "always", "healthcheck": {"test": "/openstack/healthcheck"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/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", "/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"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}}}, "global_config_settings": {"ovn_db_clustered": true}, "metadata_settings": [{"service": "ovn_dbs", "network": "internal_api", "type": "node"}], "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": null, "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\n", "register": "ovn_dbs"}, {"name": "Fetch ovn VIP", "shell": "pcs constraint config |grep \"with ovn-dbs-bundle\" |awk '{print $1}'\n", "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\npcs cluster node clear ovn-dbs-bundle-1\npcs cluster node clear ovn-dbs-bundle-2\ncrm_attribute --name OVN_REPL_INFO --delete\n"}, {"name": "Remove pacemaker attributes", "shell": "pcs node attribute \"{{ item }}\" ovn-dbs-role= || true\n", "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": "{{fqdn_internal_api}}", "principal": "ovn_dbs/{{fqdn_internal_api}}@{{idm_realm}}", "key_size": "2048", "ca": "ipa"}]}}]}, {"block": [{"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": "internal_api", "tripleo_ovn_cluster_nb_db_port": 6641, "tripleo_ovn_cluster_sb_db_port": 6642, "tripleo_ovn_cluster_nb_local_port": 6643, "tripleo_ovn_cluster_nb_remote_port": 6643, "tripleo_ovn_cluster_sb_local_port": 6644, "tripleo_ovn_cluster_sb_remote_port": 6644, "tripleo_ovn_cluster_northd_ssl_ca_cert": "/etc/ipa/ca.crt", "tripleo_ovn_cluster_sb_ssl_ca_cert": "/etc/ipa/ca.crt", "tripleo_ovn_cluster_nb_ssl_ca_cert": "/etc/ipa/ca.crt"}}]}]}, {"name": "Start OVN DBs and northd containers (bootstrap node)", "when": ["step|int == 3", "is_ovn_dbs_bootstrap_node | bool"], "block": [{"block": [{"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": true, "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 }}\"\n", "register": "nb_result", "retries": 20, "delay": 5, "until": "nb_result.rc == 0", "when": ["is_ovn_dbs_bootstrap_node | bool"], "vars": {"tripleo_ovn_cluster_network": "internal_api", "tripleo_ovn_cluster_nb_db_port": 6641, "tripleo_ovn_cluster_dbs_protocol": "{{ enable_internal_tls | ternary('ssl', 'tcp', 'tcp') }}", "tripleo_ovn_cluster_dbs_addr": "0.0.0.0", "tripleo_ovn_cluster_probe_interval": 60000}}, {"name": "Set SB connection", "become": true, "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 }}\"\n", "register": "sb_result", "retries": 20, "delay": 5, "until": "sb_result.rc == 0", "when": ["is_ovn_dbs_bootstrap_node | bool"], "vars": {"tripleo_ovn_cluster_network": "internal_api", "tripleo_ovn_cluster_sb_db_port": 6642, "tripleo_ovn_cluster_dbs_protocol": "{{ enable_internal_tls | ternary('ssl', 'tcp', 'tcp') }}", "tripleo_ovn_cluster_dbs_addr": "0.0.0.0", "tripleo_ovn_cluster_probe_interval": 60000}}]}, {"name": "Start OVN DBs and northd containers (non-bootstrap nodes)", "when": ["step|int == 4", "not is_ovn_dbs_bootstrap_node | bool"], "block": [{"block": [{"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": true, "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 }}\"\n", "register": "nb_result", "retries": 20, "delay": 5, "until": "nb_result.rc == 0", "when": ["is_ovn_dbs_bootstrap_node | bool"], "vars": {"tripleo_ovn_cluster_network": "internal_api", "tripleo_ovn_cluster_nb_db_port": 6641, "tripleo_ovn_cluster_dbs_protocol": "{{ enable_internal_tls | ternary('ssl', 'tcp', 'tcp') }}", "tripleo_ovn_cluster_dbs_addr": "0.0.0.0", "tripleo_ovn_cluster_probe_interval": 60000}}, {"name": "Set SB connection", "become": true, "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 }}\"\n", "register": "sb_result", "retries": 20, "delay": 5, "until": "sb_result.rc == 0", "when": ["is_ovn_dbs_bootstrap_node | bool"], "vars": {"tripleo_ovn_cluster_network": "internal_api", "tripleo_ovn_cluster_sb_db_port": 6642, "tripleo_ovn_cluster_dbs_protocol": "{{ enable_internal_tls | ternary('ssl', 'tcp', 'tcp') }}", "tripleo_ovn_cluster_dbs_addr": "0.0.0.0", "tripleo_ovn_cluster_probe_interval": 60000}}]}], "external_update_tasks": [{"name": "Run ovndbs update", "tags": ["ovn", "ovn_image"], "when": "step|int == 2", "block": [{"name": "Get OVN_Northbound cluster leader", "become": true, "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: '\n", "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\n"}, {"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": "registry.redhat.io/rhosp-rhel9/openstack-ovn-nb-db-server:17.1", "name": "ovn_cluster_north_db_server"}}}}, {"name": "Get OVN_Southbound cluster leader", "become": true, "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: '\n", "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\n"}, {"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": "registry.redhat.io/rhosp-rhel9/openstack-ovn-sb-db-server:17.1", "name": "ovn_cluster_south_db_server"}}}}, {"name": "Loop on OVN_Northbound cluster for leader election", "become": true, "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: '\n", "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": true, "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: '\n", "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": true, "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: '\n", "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": true, "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: '\n", "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": "registry.redhat.io/rhosp-rhel9/openstack-ovn-nb-db-server:17.1", "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])}}", "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": "registry.redhat.io/rhosp-rhel9/openstack-ovn-sb-db-server:17.1", "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])}}", "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\n", "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": "registry.redhat.io/rhosp-rhel9/openstack-ovn-nb-db-server:17.1", "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\n", "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": "registry.redhat.io/rhosp-rhel9/openstack-ovn-sb-db-server:17.1", "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": "registry.redhat.io/rhosp-rhel9/openstack-ovn-northd:17.1", "name": "ovn_cluster_northd"}}}, "loop": "{{groups['ovn_dbs'] | difference(groups['excluded_overcloud'])}}", "loop_control": {"pause": 15}}]}], "update_tasks": [{"name": "Configure OVN cluster during update", "when": "step|int == 4", "block": [{"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": "internal_api", "tripleo_ovn_cluster_nb_db_port": 6641, "tripleo_ovn_cluster_sb_db_port": 6642, "tripleo_ovn_cluster_nb_local_port": 6643, "tripleo_ovn_cluster_nb_remote_port": 6643, "tripleo_ovn_cluster_sb_local_port": 6644, "tripleo_ovn_cluster_sb_remote_port": 6644, "tripleo_ovn_cluster_northd_ssl_ca_cert": "/etc/ipa/ca.crt", "tripleo_ovn_cluster_sb_ssl_ca_cert": "/etc/ipa/ca.crt", "tripleo_ovn_cluster_nb_ssl_ca_cert": "/etc/ipa/ca.crt"}}]}, {"name": "Update OVN cluster containers", "when": "step|int == 4", "block": [{"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"}}]}]}, "tuple:('role_data', 'service_names')": null, "tuple:('role_data', 'config_settings')": null, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-43-dzwzxcc2l4si/705f878b-0423-4311-b34a-73303cd1c482"}


created_at: 2026-06-13 07:33:09.169547
data:
  {"type": "json", "value": {"ContainerOvnMetadataImage": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "ContainerNeutronConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-neutron-server:17.1"}}


created_at: 2026-06-13 07:33:10.276292
data:
  {"container_config_scripts": {"container_puppet_apply.sh": {"mode": "0700", "content": "#!/bin/bash\nset -eux\nSTEP=$1\nTAGS=$2\nCONFIG=$3\nEXTRA_ARGS=${4:-''}\nif [ -d /tmp/puppet-etc ]; then\n  # ignore copy failures as these may be the same file depending on docker mounts\n  cp -a /tmp/puppet-etc/* /etc/puppet || true\nfi\necho \"{\\\"step\\\": ${STEP}}\" > /etc/puppet/hieradata/docker_puppet.json\n# $::deployment_type in puppet-tripleo\nexport FACTER_deployment_type=containers\nset +e\npuppet apply $EXTRA_ARGS \\\n    --verbose \\\n    --detailed-exitcodes \\\n    --summarize \\\n    --color=false \\\n    --modulepath /etc/puppet/modules:/opt/stack/puppet-modules:/usr/share/openstack-puppet/modules \\\n    --tags $TAGS \\\n    -e \"noop_resource('package'); ${CONFIG}\"\nrc=$?\nset -e\nset +ux\nif [ $rc -eq 2 -o $rc -eq 0 ]; then\n    exit 0\nfi\nexit $rc\n"}, "pyshim.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n# Copyright 2018 Red Hat Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n#\n# Usage: pyshim.sh <script and/or arguments>\n#\n# Unfortunately THT doesn't know which version of python might be in a\n# container so we need this script to be able to try python3 or python2\n# depending on availability.  Since this is a temporary shim until we've\n# fully cut over to python3, we check for the existence of python3 first\n# before falling back to python2. This will help in the transition from\n# python2 based containers to python3.\n\nshow_usage() {\n    echo \"Usage: pyshim.sh <script and/or arguments>\"\n}\n\nif [ $# -lt 1 ]\nthen\n    show_usage\n    exit 1\nfi\n\nset -x\nif command -v python3 >/dev/null; then\n    python3 \"$@\"\nelif command -v python2 >/dev/null; then\n    python2 \"$@\"\nelif command -v python >/dev/null; then\n    python \"$@\"\nelse\n    echo \"ERROR: python is not available!\"\n    exit 1\nfi\n"}, "pacemaker_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nset -u\n\n# ./pacemaker_restart_bundle.sh mysql galera galera-bundle Master _\n# ./pacemaker_restart_bundle.sh redis redis redis-bundle Slave Master\n# ./pacemaker_restart_bundle.sh ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\nRESTART_SCRIPTS_DIR=$(dirname $0)\nTRIPLEO_SERVICE=$1\nRESOURCE_NAME=$2\nBUNDLE_NAME=$3\nWAIT_TARGET_LOCAL=$4\nWAIT_TARGET_ANYWHERE=${5:-_}\nTRIPLEO_MINOR_UPDATE=\"${TRIPLEO_MINOR_UPDATE:-false}\"\nTRIPLEO_HA_WRAPPER_RESOURCE_EXISTS=\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS:-false}\"\n\nbundle_can_be_restarted() {\n    local bundle=$1\n    # As long as the resource bundle is managed by pacemaker and is\n    # not meant to stay stopped, no matter the state of any inner\n    # pcmk_remote or ocf resource, we should restart it to give it a\n    # chance to read the new config.\n    [ \"$(crm_resource --meta -r $1 -g is-managed 2>/dev/null)\" != \"false\" ] && \\\n    [ \"$(crm_resource --meta -r $1 -g target-role 2>/dev/null)\" != \"Stopped\" ]\n}\n\nlog() {\n    local msg=$1\n    logger -t pcmkrestart \"$1\"\n}\n\nHOSTNAME=$(/bin/hostname -s)\nif [ x\"${TRIPLEO_MINOR_UPDATE,,}\" != x\"true\" ]; then\n    if [ x\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS,,}\" = x\"false\" ]; then\n        # Do not restart during initial deployment, as the resource\n        # has just been created.\n        SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n        if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n            log \"Initial deployment, skipping the restart of ${BUNDLE_NAME}\"\n\tfi\n        exit 0\n    else\n        # During a stack update, this script is called in parallel on\n        # every node the resource runs on, after the service's configs\n        # have been updated on all nodes. So we need to run pcs only\n        # once (e.g. on the service's boostrap node).\n        if bundle_can_be_restarted ${BUNDLE_NAME}; then\n            SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n            if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n                replicas_running=$(crm_resource -Q -r $BUNDLE_NAME --locate 2>&1 | wc -l)\n                if [ \"$replicas_running\" != \"0\" ]; then\n                    log \"Restarting ${BUNDLE_NAME} globally. Stopping:\"\n                    /sbin/pcs resource disable --wait=600 $BUNDLE_NAME\n                    log \"Restarting ${BUNDLE_NAME} globally. Starting:\"\n                    /sbin/pcs resource enable --wait=600 $BUNDLE_NAME\n                else\n                    log \"${BUNDLE_NAME} is not running anywhere,\" \\\n                         \"cleaning up to restart it globally if necessary\"\n                    /sbin/pcs resource cleanup $BUNDLE_NAME\n                fi\n            else\n                log \"Skipping global restart of ${BUNDLE_NAME} on ${HOSTNAME} it will be restarted by node ${SERVICE_NODEID}\"\n            fi\n\n        else\n            log \"No global restart needed for ${BUNDLE_NAME}.\"\n        fi\n    fi\nelse\n    # During a minor update workflow however, a host gets fully\n    # updated before updating the next one. So unlike stack\n    # update, at the time this script is called, the service's\n    # configs aren't updated on all nodes yet. So only restart the\n    # resource locally, where it's guaranteed that the config is\n    # up to date.\n    HOST=$(facter hostname)\n\n    if bundle_can_be_restarted ${BUNDLE_NAME}; then\n\t# if the resource is running locally, restart it\n\tif crm_resource -r $BUNDLE_NAME --locate 2>&1 | grep -w -q \"${HOST}\"; then\n            log \"Restarting ${BUNDLE_NAME} locally on '${HOST}'\"\n            /sbin/pcs resource restart $BUNDLE_NAME \"${HOST}\"\n\n\telse\n\t    # At this point, if no resource is running locally, it's\n\t    # either because a) it has failed previously, or b) because\n\t    # it's an A/P resource running elsewhere.\n\t    # By cleaning up resource, we ensure that a) it will try to\n\t    # restart, or b) it won't do anything if the resource is\n\t    # already running elsewhere.\n            log \"${BUNDLE_NAME} is currently not running on '${HOST}',\" \\\n                 \"cleaning up its state to restart it if necessary\"\n            /sbin/pcs resource cleanup $BUNDLE_NAME node=\"${HOST}\"\n\tfi\n\n\t# Wait until the resource is in the expected target state\n\t$RESTART_SCRIPTS_DIR/pacemaker_wait_bundle.sh \\\n            $RESOURCE_NAME $BUNDLE_NAME \\\n            \"$WAIT_TARGET_LOCAL\" \"$WAIT_TARGET_ANYWHERE\" \\\n\t    \"${HOST}\" 600\n    else\n        log \"No restart needed for ${BUNDLE_NAME}.\"\n    fi\nfi\n"}, "pacemaker_wait_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# ----\n# Wait for an OCF resource or a bundle to be restarted\n# ----\n# e.g.:\n# M/S OCF:      $0 galera galera-bundle Master\n# clone OCF:    $0 rabbitmq rabbitmq-bundle Started\n# A/P M/S OCF:  $0 redis redis-bundle Slave Master\n# A/P bundle:   $0 openstack-cinder-volume openstack-cinder-volume _ Started\n# clone bundle: $0 haproxy-bundle haproxy-bundle Started\n\n# design note 1:\n#  - this script is called during a minor update; it is called\n#    once per node that hosts a service replica.\n#  - the purpose of this script is to ensure that restarting the\n#    service replica locally won't disrupt the service availability\n#    for the end user. To reach that goal, the script waits until the\n#    service is restarted locally or globallu and reaches a given\n#    target state (i.e. Started, Slave or Master).\n# design note 2:\n#   - we don't want to track restart error: our only job is to ensure\n#     service restart synchronization, not service health.\n#   - In particular, we don't want to error out in case the resource\n#     cannot be restarted locally, because that would make the minor\n#     update fail, even if potentially other replicas still provide\n#     the service.\n# design note 3:\n#   - we can bail out early if we determine that the resource can't\n#     be restarted automatically by pacemaker (e.g. its \"blocked\",\n#     unmanaged or disabled).\n\nlog() {\n    local msg=$1\n    echo \"$(date -u): $1\"\n}\n\nusage() {\n    echo 2>&1 \"Usage: $0 NAME BUNDLE_NAME ROLE_LOCAL [ROLE_ANYWHERE] [HOST] [TIMEOUT]\"\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\n#\n# Utility functions to detect stuck resources\n#\n\nbundle_failures_locally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local replica_name\n    for i in $(seq 0 $last); do\n\treplica_name=${BUNDLE_NAME}-${engine}-${i}\n\tcrm_failcount -q -G -r $replica_name -N $HOST\n    done\n}\n\nbundle_failures_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    for i in $(seq 0 $last); do\n\tcrm_failcount -q -G -r ${BUNDLE_NAME}-${engine}-${i}\n    done\n}\n\nbundle_running_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    # return the number of running bundles replica, i.e. the number of\n    # docker/podman resource replicas currently running in the cluster\n    crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:heartbeat:${engine}']/node)\" -\n}\n\nocf_failures_globally() {\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local bundle_node\n    for i in $(seq 0 $last); do\n\tbundle_node=${BUNDLE_NAME}-${i}\n\tcrm_failcount -q -G -r $NAME -N $bundle_node\n    done\n}\n\ndid_resource_failed_locally() {\n    local failures\n    local running\n    local remotehost\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# if we're dealing with an ocf resource, it is running on a\n\t# pacemaker_remote rather that on the real host, and the\n\t# failcounts are thus associated to the pcmk remote. Replace\n\t# the host's name with the pcmk remote's name.\n        remotehost=$(crm_mon --as-xml | xmllint --xpath \"string(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource/node[@name='${HOST}']/../../resource[@resource_agent='${OCF}:pacemaker:remote']/@id)\" -)\n\tif [ -n \"${remotehost}\" ]; then\n\t    crm_failcount -q -G -r $NAME -N $remotehost | grep -q -w INFINITY\n\t    return $?\n\tfi\n\t# If no pcmk remote is currently running, the failcount from\n\t# the ocf resource is useless, compute the failcount from the\n\t# bundle case instead (computed below).\n    fi\n\n    # for bundles, pacemaker can run any bundle replica locally\n    # (e.g. galera-bundle-docker-{0,1,2}), and a failure happens when\n    # there are no more replica to try.\n    # That is, when _at least_ one replica failed locally, and all the\n    # others either failed or are currently running elsewhere.\n    failures=$(bundle_failures_locally $HOST | grep -c -w INFINITY)\n    running=$(bundle_running_globally)\n    test $failures -gt 0 && \\\n    test $(( $failures + $running )) -ge $BUNDLE_REPLICAS\n}\n\ndid_resource_failed_globally() {\n    local remotecount\n    local failures\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# we check the state of an ocf resource only if the\n\t# pcmkremotes are started\n        remotecount=$(crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node)\" -)\n\tif [ \"${remotecount}\" = \"0\" ]; then\n\t    # no pcmkremote is running, so check the bundle state\n\t    # instead of checking the ocf resource\n\t    # bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\t    failures=$(bundle_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\telse\n\t    # ocf resource failed if it failed to start on\n\t    # all $BUNDLE_REPLICAS bundle nodes\n\t    failures=$(ocf_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\tfi\n    else\n\t# bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\tfailures=$(bundle_failures_globally | grep -c -w INFINITY)\n\ttest $failures -eq $BUNDLE_REPLICAS\n    fi\n}\n\n\n# Input validation\n#\n\nNAME=$1\nif [ -z \"${NAME}\" ]; then\n    echo 2>&1 \"Error: argument NAME must not be empty\"\n    exit 1\nfi\n\nBUNDLE_NAME=$2\nif [ -z \"${BUNDLE_NAME}\" ]; then\n    echo 2>&1 \"Error: argument BUNDLE_NAME must not be empty\"\n    exit 1\nfi\n\nROLE_LOCAL=$3\nif [ \"${ROLE_LOCAL}\" = \"_\" ]; then\n    ROLE_LOCAL=\"\"\nfi\n\nROLE_ANYWHERE=$4\nif [ \"${ROLE_ANYWHERE}\" = \"_\" ]; then\n    ROLE_ANYWHERE=\"\"\nfi\n\nif [ -z \"${ROLE_LOCAL}\" ]; then\n    if [ -z \"${ROLE_ANYWHERE}\" ]; then\n        echo 2>&1 \"Error: either ROLE_LOCAL or ROLE_ANYWHERE must be non empty\"\n        exit 1\n    fi\nelse\n    if !(echo \"${ROLE_LOCAL}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n        echo 2>&1 \"Error: argument ROLE_LOCAL must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n        exit 1\n    fi\nfi\n\nif [ -n \"${ROLE_ANYWHERE}\" ] && !(echo \"${ROLE_ANYWHERE}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n    echo 2>&1 \"Error: argument ROLE_ANYWHERE must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n    exit 1\nfi\n\n# Ensure compatibility with pacemaker 2.1\nif pacemaker_supports_promoted; then\n    ROLE_LOCAL=$(echo \"$ROLE_LOCAL\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    ROLE_ANYWHERE=$(echo \"$ROLE_ANYWHERE\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    OCF=\"ocf\"\nelse\n    OCF=\"ocf:\"\nfi\n\nHOST=${5:-$(facter hostname)}\nTIMEOUT=${6:-600}\n\n\n# Configure the search\n# ----\n# Note: we can't use crm_resource in all searches because we can't\n# easily extract the host the OCF resources run on (crm_resource\n# returns the pcmk-remote nodes rather than the hosts)\n# So instead, we implement various searches with XPath directly.\n\nif [ \"${BUNDLE_NAME}\" != \"${NAME}\" ]; then\n# ocf resource\nlocal_resource_xpath=\"//bundle/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node[@name='${HOST}']/../../resource[@id='${NAME}']\"\nany_resource_xpath=\"//bundle//resource[@id='${NAME}']\"\nreplicas_xpath=\"//bundle/primitive[@id='${BUNDLE_NAME}']/../*[boolean(@image) and boolean(@replicas)]\"\nelse\n# bundle resource\nlocal_resource_xpath=\"//bundle[@id='${NAME}']/replica/resource/node[@name='${HOST}']/../../resource\"\nany_resource_xpath=\"//bundle[@id='${NAME}']//resource\"\nreplicas_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nfi\n\nbundle_def_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nBUNDLE_CONTAINER_ENGINE=$(cibadmin -Q | xmllint --xpath \"name(${bundle_def_xpath})\" -)\nBUNDLE_REPLICAS=$(cibadmin -Q | xmllint --xpath \"string(${bundle_def_xpath}/@replicas)\" -)\n\n\n# The wait algorithm follows a two-stage approach\n#  1. Depending on how the script is called, we first check whether\n#     the resource is restarted locally. An A/P resource may be\n#     restarted elsewhere in the cluster.\n#  2. If needed, check whether the A/P resource has restarted\n#     elsewhere. For A/P M/S resources, in case the resource is\n#     restarted as Slave locally, ensure a Master is available.\n\nsuccess=1\nbailout=1\ntimeout=$TIMEOUT\nrole=\"\"\n\n# Stage 1: local check\nif [ -n \"$ROLE_LOCAL\" ]; then\n    log \"Waiting until ${NAME} has restarted on ${HOST} and is in state ${ROLE_LOCAL}\"\n    log \"Will probe resource state with the following XPath pattern: ${local_resource_xpath}\"\n\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resource=$(crm_mon -r --as-xml | xmllint --xpath \"${local_resource_xpath}\" - 2>/dev/null)\n        role=$(echo \"${resource}\" | sed -ne 's/.*\\Wrole=\"\\([^\"]*\\)\".*/\\1/p')\n\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resource}\" | grep -q -w \"\\Wblocked=\\\"true\\\"\"; then\n            log \"${NAME} is blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_locally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif [ \"$role\" = \"$ROLE_LOCAL\" ]; then\n            success=0\n            continue\n        elif [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" = \"$ROLE_ANYWHERE\" ]; then\n            # A/P: we are restarted in the expected state\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_LOCAL} on ${HOST}\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\n# Stage 2: global check\nif [ $timeout -gt 0 ] && [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" != \"$ROLE_ANYWHERE\" ]; then\n    log \"Wait until ${NAME} is restarted anywhere in the cluster in state ${ROLE_ANYWHERE}\"\n    log \"Will probe resource state with the following XPath pattern: ${any_resource_xpath}\"\n\n    success=1\n    bailout=1\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resources=$(crm_mon -r --as-xml | xmllint --xpath \"${any_resource_xpath}\" - 2>/dev/null)\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif ! (echo \"${resources}\" | grep -q -w \"\\Wblocked=\\\"false\\\"\"); then\n            log \"${NAME} blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_globally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resources}\" | grep -q -w \"\\Wrole=\\\"${ROLE_ANYWHERE}\\\"\"; then\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_ANYWHERE} anywhere in the cluster\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\nif [ $timeout -le 0 ]; then\n    log \"Timeout reached after ${TIMEOUT}s while waiting for ${NAME} to be restarted\"\nelif [ $bailout -le 0 ]; then\n    log \"Restart monitoring for ${NAME} cancelled\"\nfi\n\nif [ $success -eq 0 ]; then\n    log \"${NAME} successfully restarted\"\nelse\n    log \"${NAME} was not restarted properly\"\nfi\n\n# Don't block minor update or stack update if the wait was unsuccessful\nexit 0\n"}, "wait-port-and-run.sh": {"mode": "0755", "content": "#!/usr/bin/bash\nset -eu\n\nHOST=$1\nPORT=$2\n\necho \"$(date -u): Checking whether we can bind to ${HOST}:${PORT}\"\nwhile (ss -Htnl src \"${HOST}\" \"sport = :${PORT}\" | grep -wq \"${PORT}\"); do\n    echo \"$(date -u): ${HOST}:${PORT} still in use, waiting...\";\n    sleep 10;\ndone\n\nshift 2\nCOMMAND=\"$*\"\nif [ -z \"${COMMAND}\" ]; then\n    COMMAND=\"true\"\nfi\nexec $COMMAND\n"}, "pacemaker_resource_lock.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nMAX_RETRIES=10\nCIB_ENOTFOUND=105\n\nusage() {\n   echo \"Set a global property in the cluster with a validity timestamp.\"\n   echo \"Usage:\"\n   echo \"   $0 --acquire <lock_name> <lock_owner> <lock_ttl_in_seconds>\"\n   echo \"   $0 --release <lock_name> <lock_owner>\"\n   echo\n}\n\nlog() {\n    echo \"$(date -u): $1\" 1>&2\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\nlock_create() {\n    local name=$1\n    local data=$2\n    # cibadmin won't overwrite a key if someone else succeeded to create it concurrently\n    cibadmin --sync-call --scope crm_config --create --xml-text \"<cluster_property_set id='${name}'><nvpair id='${name}-pair' name='${name}' value='${data}'/></cluster_property_set>\" &>/dev/null\n    return $?\n}\n\nlock_update() {\n    local name=$1\n    local expected_data=$2\n    local new_data=$3\n    # we only update the lock we expect to see, so we can't update someone else's lock\n    cibadmin --sync-call --scope crm_config --modify --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" --xml-text \"<nvpair id='${name}-pair' name='${name}' value='${new_data}'/>\" &>/dev/null\n    return $?\n}\n\nlock_delete() {\n    local name=$1\n    local expected_data=$2\n    # we only delete the lock we expect to see, so we can't delete someone else's lock\n    cibadmin --sync-call --scope crm_config --delete --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" &>/dev/null\n    return $?\n}\n\nlock_get() {\n    local lockname=$1\n    local res\n    local rc\n    res=$(cibadmin --query --scope crm_config --xpath \"//cluster_property_set/nvpair[@name='$lockname']\" 2>/dev/null)\n    rc=$?\n    if [ $rc -eq 0 ]; then\n        echo \"$res\" | sed -n 's/.*value=\"\\([^\"]*\\)\".*/\\1/p'\n    fi\n    return $rc\n}\n\nlock_owner() {\n    local lock=$1\n    echo \"$lock\" | cut -d':' -f1\n}\n\nlock_has_expired() {\n    local lock=$1\n    local expiry=$(echo \"$lock\" | cut -d':' -f2)\n    local now=$(date +%s)\n    test $now -ge $expiry\n}\n\n\n# Perform a lock action and restart if the CIB has been modified before\n# committing the lock action\ntry_action() {\n    local fun=$1\n    local lock=$2\n    local requester=$3\n    local args=${4:-}\n    local tries=$MAX_RETRIES\n    local rc=1\n    if [ \"$fun\" = \"lock_acquire\" ] || [ \"$fun\" = \"lock_release\" ]; then\n        log \"Try running $fun\"\n    else\n        return 2\n    fi\n    while [ $rc -ne 0 ]; do\n        $fun $lock $requester $args\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Operation $1 succeeded\"\n            return 0\n        elif [ $rc -eq 3 ]; then\n            # rc == 3 -> CIB changed before push\n            if [ $tries -eq 0 ]; then\n                log \"Failed to commit after $MAX_RETRIES retries. Bailing out.\"\n                return 2\n            else\n                log \"Failed to commit. Retrying operation.\"\n                tries=$(($tries - 1))\n            fi\n        elif [ $rc -eq 2 ]; then\n            # rc == 2 -> unrecoverable cib error (e.g. pacemaker down)\n            log \"Unexpected failure. Bailing out\"\n            return $rc\n        else\n            # rc == 1 -> lock error (not owner, lock doesn't exists)\n            return $rc\n        fi\n    done\n}\n\n# The lock mechanism uses cibadmin's atomic creation so cluster-wide\n# state coherency is guaranteed by pacemaker\nlock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc\n    local lock\n    local expiry\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -n \"$lock\" ]; then\n        lock_has_expired $lock\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Lock has expired, now available for being held\"\n        else\n            # lock is still held. check whether we're the owner\n            owner=$(lock_owner $lock)\n            if [ \"$owner\" = \"$requester\" ];then\n                log \"Requester already owns the lock, acquiring attempt will just reconfigure the TTL\"\n            else\n                log \"Lock is held by someone else ($owner)\"\n                return 1\n            fi\n        fi\n    else\n        log \"Lock is not held yet\"\n    fi\n\n    # prepare the lock info\n    expiry=$(($(date +%s) + $ttl))\n\n    if [ -n \"$lock\" ]; then\n        log \"Attempting to update the lock\"\n        lock_update $lockname \"$lock\" \"$requester:$expiry\"\n        rc=$?\n    else\n        log \"Attempting to acquire the lock\"\n        lock_create $lockname \"$requester:$expiry\"\n        rc=$?\n    fi\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' acquired by '$requester', valid until $(date -d @$expiry)\"\n        return 0\n    else\n        log \"CIB changed, lock cannot be acquired\"\n        return 3\n    fi\n}\n\n\n# The lock mechanism uses the CIB's num_updates tag to implement\n# a conditional store. Cluster-wide locking is guaranteed by pacemaker\nlock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n    local lock\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        log \"Lock doesn't exist. Nothing to release\"\n        return 0\n    else\n        log \"Lock exists, check whether we're the owner\"\n        owner=$(lock_owner $lock)\n        if [ \"$owner\" != \"$requester\" ];then\n            log \"Lock is held by someone else ($owner), will not unlock\"\n            return 1\n        fi\n    fi\n\n    lock_delete $lockname \"$lock\"\n    rc=$?\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' released by '$requester'\"\n        return 0\n    else\n        log \"CIB deletion error, lock cannot be released\"\n        return 3\n    fi\n}\n\n\n# Retrieve the owner of a lock from the CIB\n# this is a read-only operation, so no need to log debug info\nlock_get_owner() {\n    local lockname=$1\n    local rc\n    local lock\n    local owner\n\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        return 1\n    else\n        lock_owner $lock\n        return 0\n    fi\n}\n\n\nACTION=$1\nLOCKNAME=$2\nREQUESTER=$3\nTTL=${4:-60}\n\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nif [ $ACTION != \"--help\" ]; then\n    if [ -z \"$LOCKNAME\" ]; then\n        error \"You must specific a lock name\"\n    fi\n    if [ $ACTION != \"--owner\" ] && [ $ACTION != \"-o\" ]; then\n        if [ -z \"$REQUESTER\" ]; then\n            error \"You must specific a lock requester\"\n        fi\n    fi\nfi\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) try_action lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --release|-r) try_action lock_release $LOCKNAME $REQUESTER;;\n    --acquire-once|-A) lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --owner|-o) lock_get_owner $LOCKNAME;;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}, "pacemaker_mutex_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_restart_bundle.sh --lock mysql galera galera-bundle Master _\n# pacemaker_mutex_restart_bundle.sh --lock ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\n\nset -u\n\nusage() {\n    echo \"Restart a clustered resource in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --lock <tripleo-service> <pcmk-resource> <pcmk-bundle> <target-state-local> <target-state-cluster>\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\nACTION=$1\ncase $ACTION in\n    --help) usage; exit 0;;\n    --lock) ;;\n    *) error \"Unknown action '$ACTION'\";;\nesac\n\nTRIPLEO_SERVICE=$2\nLOCK_NAME=${TRIPLEO_SERVICE}-restart-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to restart resource $TRIPLEO_SERVICE\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\nRESOURCE_NAME=$3\nBUNDLE_NAME=$4\nWAIT_TARGET_LOCAL=$5\nWAIT_TARGET_ANYWHERE=${6:-_}\n\nif pacemaker_supports_promoted; then\n    WAIT_TARGET_LOCAL=$(echo \"$5\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    WAIT_TARGET_ANYWHERE=$(echo \"${6:-_}\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    promoted_role=\"Promoted\"\nelse\n    promoted_role=\"Master\"\nfi\n\n# The lock TTL should accomodate for the resource start/promote timeout\nif [ \"$RESOURCE_NAME\" != \"$BUNDLE_NAME\" ]; then\n    if [ \"$WAIT_TARGET_LOCAL\" = \"$promoted_role\" ] || [ \"$WAIT_TARGET_ANYWHERE\" = \"$promoted_role\" ]; then\n        rsc_op=\"promote\"\n    else\n        rsc_op=\"start\"\n    fi\n    # <op id=\"galera-promote-interval-0s\" interval=\"0s\" name=\"promote\" on-fail=\"block\" timeout=\"300s\"/>\n    PCMK_TTL=$(cibadmin -Q | xmllint -xpath \"string(//primitive[@id='${RESOURCE_NAME}']/operations/op[@name='${rsc_op}']/@timeout)\" - | sed 's/s$//')\n    LOCK_TTL=$((PCMK_TTL + 30))\nelse\n    # The podman RA's default start timeout\n    LOCK_TTL=90\nfi\n\nlog \"Acquire a ${LOCK_TTL}s restart lock for service $TRIPLEO_SERVICE before restarting it\"\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nrc=1\nwhile [ $rc -ne 0 ]; do\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire $LOCK_NAME $LOCK_OWNER $LOCK_TTL\n    rc=$?\n    if [ $rc != 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not acquire lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Could not acquire lock, retrying\"\n            sleep 10\n        fi\n    fi\ndone\n\nlog \"Restart the service $TRIPLEO_SERVICE locally\"\n# Reuse the local restart script in t-h-t (driven by env var TRIPLEO_MINOR_UPDATE)\nTRIPLEO_MINOR_UPDATE=true /var/lib/container-config-scripts/pacemaker_restart_bundle.sh $TRIPLEO_SERVICE $RESOURCE_NAME $BUNDLE_NAME $WAIT_TARGET_LOCAL $WAIT_TARGET_ANYWHERE\n\n# If we reached this point, always try to release the lock\nlog \"Release the restart lock for service $TRIPLEO_SERVICE\"\n/var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $LOCK_NAME $LOCK_OWNER\nrc=$?\nif [ $rc -ne 0 ] && [ $rc -ne 1 ]; then\n    error \"Could not release held lock (rc: $rc)\"\nfi\n"}, "pacemaker_mutex_shutdown.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_shutdown.sh --acquire\n# pacemaker_mutex_shutdown.sh --release\n\nset -u\n\nusage() {\n    echo \"Shutdown a cluster node in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --acquire # prevent other node from shutting down until we hold the lock\"\n    echo \"   $0 --release # release the lock, other node can compete for the shutdown lock\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nshutdown_lock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc=1\n    local current_owner\n    local owner_stopped\n    local owner_rc\n\n    log \"Acquiring the shutdown lock\"\n    while [ $rc -ne 0 ]; do\n        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire-once $lockname $requester $ttl\n        rc=$?\n        if [ $rc -ne 0 ]; then\n            if [ $rc -eq 2 ]; then\n                error \"Could not acquire the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n            else\n                # The lock is held by another node.\n                current_owner=$(/var/lib/container-config-scripts/pacemaker_resource_lock.sh --owner $lockname)\n                owner_rc=$?\n                if [ $owner_rc -eq 2 ]; then\n                    error \"Could not get the shutdown lock owner due to unrecoverable error (rc: $owner_rc), bailing out\"\n                fi\n                if [ $owner_rc -eq 0 ]; then\n                    # If the owner is marked as offline, that means it has shutdown and\n                    # we can clean the lock preemptively and try to acquire it.\n                    owner_stopped=$(crm_mon -1X | xmllint --xpath 'count(//nodes/node[@name=\"'${current_owner}'\" and @online=\"false\" and @unclean=\"false\"])' -)\n                    if [ \"${owner_stopped}\" = \"1\" ]; then\n                        log \"Shutdown lock held by stopped node '${current_owner}', lock can be released\"\n                        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $current_owner\n                        continue\n                    fi\n                fi\n                log \"Shutdown lock held by another node (rc: $rc), retrying\"\n                sleep 10\n            fi\n        fi\n    done\n    log \"Shutdown lock acquired\"\n    return 0\n}\n\n\n# Release the lock if we still own it. Not owning it anymore is not fatal\nshutdown_lock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n\n    log \"Releasing the shutdown lock\"\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $requester\n    rc=$?\n    if [ $rc -ne 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not release the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Shutdown lock no longer held, nothing to do\"\n        fi\n    else\n        log \"Shutdown lock released\"\n    fi\n    return 0\n}\n\n\nACTION=$1\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nLOCK_NAME=tripleo-shutdown-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to aquire the shutdown lock\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\n# We start with a very high TTL, that long enough to accomodate a cluster stop.\n# As soon as the node will get offline, the other competing node will be entitled\n# to steal the lock, so they should never wait that long in practice.\nLOCK_TTL=600\n\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) shutdown_lock_acquire ${LOCK_NAME} ${LOCK_OWNER} ${LOCK_TTL};;\n    --release|-r) shutdown_lock_release ${LOCK_NAME} ${LOCK_OWNER};;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}}, "container_puppet_apply_volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/var/lib/container-config-scripts/container_puppet_apply.sh:/container_puppet_apply.sh:ro", "/etc/puppet:/tmp/puppet-etc:ro", "/usr/share/openstack-puppet/modules:/usr/share/openstack-puppet/modules:ro"], "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro"], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-44-drbqceomkufl-ContainersCommon-s4o45z7lxxcz/4ce05ac9-1341-4b8e-8e9f-353f09351280"}


created_at: 2026-06-13 07:33:10.333515
data:
  {"tuple:('role_data', 'metadata_settings')": null, "tuple:('role_data', 'config_settings')": {"neutron::notification_driver": ["noop"], "neutron::core_plugin": "ml2", "neutron::service_plugins": ["qos", "ovn-router", "trunk", "segments", "port_forwarding", "log"], "neutron::report_interval": 300, "neutron::logging::debug": true, "neutron::purge_config": false, "neutron::allow_overlapping_ips": true, "neutron::dhcp_agent_notification": true, "neutron::dns_domain": "ooo.test", "neutron::rabbit_heartbeat_timeout_threshold": 60, "neutron::host": "%{hiera('fqdn_canonical')}", "neutron::db::database_db_max_retries": -1, "neutron::db::database_max_retries": -1, "neutron::db::sync::db_sync_timeout": 900, "neutron::global_physnet_mtu": 1500, "neutron::db::sync::extra_params": "", "neutron::vlan_transparent": false, "neutron::rabbit_heartbeat_in_pthread": false}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-44-drbqceomkufl-NeutronBase-7qdj5cmubigu/1e1ef75e-d98f-4dcf-acb1-0024f6d77f92"}


created_at: 2026-06-13 07:33:10.341054
data:
  {"value": {"ContainerOvnMetadataImage": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "ContainerNeutronConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-neutron-server:17.1"}}


created_at: 2026-06-13 07:33:10.430305
data:
  {"cmd_extra_args": "--log-file=/var/log/neutron/ovn-metadata-agent.log", "volumes": ["/var/log/containers/neutron:/var/log/neutron:z"], "config_settings": null, "host_prep_tasks": [{"name": "create persistent directories", "file": {"path": "{{ item.path }}", "state": "directory", "setype": "{{ item.setype }}", "mode": "{{ item.mode }}"}, "with_items": [{"path": "/var/log/containers/neutron", "setype": "container_file_t", "mode": "0750"}]}], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-44-drbqceomkufl-NeutronLogging-yynlqhn3stvs/861a4cb3-3adf-4509-a1de-43d8fe359e58"}


created_at: 2026-06-13 07:33:10.451361
data:
  {"tuple:('role_data', 'step_config')": null, "tuple:('role_data', 'container_config_scripts')": {"container_puppet_apply.sh": {"mode": "0700", "content": "#!/bin/bash\nset -eux\nSTEP=$1\nTAGS=$2\nCONFIG=$3\nEXTRA_ARGS=${4:-''}\nif [ -d /tmp/puppet-etc ]; then\n  # ignore copy failures as these may be the same file depending on docker mounts\n  cp -a /tmp/puppet-etc/* /etc/puppet || true\nfi\necho \"{\\\"step\\\": ${STEP}}\" > /etc/puppet/hieradata/docker_puppet.json\n# $::deployment_type in puppet-tripleo\nexport FACTER_deployment_type=containers\nset +e\npuppet apply $EXTRA_ARGS \\\n    --verbose \\\n    --detailed-exitcodes \\\n    --summarize \\\n    --color=false \\\n    --modulepath /etc/puppet/modules:/opt/stack/puppet-modules:/usr/share/openstack-puppet/modules \\\n    --tags $TAGS \\\n    -e \"noop_resource('package'); ${CONFIG}\"\nrc=$?\nset -e\nset +ux\nif [ $rc -eq 2 -o $rc -eq 0 ]; then\n    exit 0\nfi\nexit $rc\n"}, "pyshim.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n# Copyright 2018 Red Hat Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n#\n# Usage: pyshim.sh <script and/or arguments>\n#\n# Unfortunately THT doesn't know which version of python might be in a\n# container so we need this script to be able to try python3 or python2\n# depending on availability.  Since this is a temporary shim until we've\n# fully cut over to python3, we check for the existence of python3 first\n# before falling back to python2. This will help in the transition from\n# python2 based containers to python3.\n\nshow_usage() {\n    echo \"Usage: pyshim.sh <script and/or arguments>\"\n}\n\nif [ $# -lt 1 ]\nthen\n    show_usage\n    exit 1\nfi\n\nset -x\nif command -v python3 >/dev/null; then\n    python3 \"$@\"\nelif command -v python2 >/dev/null; then\n    python2 \"$@\"\nelif command -v python >/dev/null; then\n    python \"$@\"\nelse\n    echo \"ERROR: python is not available!\"\n    exit 1\nfi\n"}, "pacemaker_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nset -u\n\n# ./pacemaker_restart_bundle.sh mysql galera galera-bundle Master _\n# ./pacemaker_restart_bundle.sh redis redis redis-bundle Slave Master\n# ./pacemaker_restart_bundle.sh ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\nRESTART_SCRIPTS_DIR=$(dirname $0)\nTRIPLEO_SERVICE=$1\nRESOURCE_NAME=$2\nBUNDLE_NAME=$3\nWAIT_TARGET_LOCAL=$4\nWAIT_TARGET_ANYWHERE=${5:-_}\nTRIPLEO_MINOR_UPDATE=\"${TRIPLEO_MINOR_UPDATE:-false}\"\nTRIPLEO_HA_WRAPPER_RESOURCE_EXISTS=\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS:-false}\"\n\nbundle_can_be_restarted() {\n    local bundle=$1\n    # As long as the resource bundle is managed by pacemaker and is\n    # not meant to stay stopped, no matter the state of any inner\n    # pcmk_remote or ocf resource, we should restart it to give it a\n    # chance to read the new config.\n    [ \"$(crm_resource --meta -r $1 -g is-managed 2>/dev/null)\" != \"false\" ] && \\\n    [ \"$(crm_resource --meta -r $1 -g target-role 2>/dev/null)\" != \"Stopped\" ]\n}\n\nlog() {\n    local msg=$1\n    logger -t pcmkrestart \"$1\"\n}\n\nHOSTNAME=$(/bin/hostname -s)\nif [ x\"${TRIPLEO_MINOR_UPDATE,,}\" != x\"true\" ]; then\n    if [ x\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS,,}\" = x\"false\" ]; then\n        # Do not restart during initial deployment, as the resource\n        # has just been created.\n        SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n        if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n            log \"Initial deployment, skipping the restart of ${BUNDLE_NAME}\"\n\tfi\n        exit 0\n    else\n        # During a stack update, this script is called in parallel on\n        # every node the resource runs on, after the service's configs\n        # have been updated on all nodes. So we need to run pcs only\n        # once (e.g. on the service's boostrap node).\n        if bundle_can_be_restarted ${BUNDLE_NAME}; then\n            SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n            if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n                replicas_running=$(crm_resource -Q -r $BUNDLE_NAME --locate 2>&1 | wc -l)\n                if [ \"$replicas_running\" != \"0\" ]; then\n                    log \"Restarting ${BUNDLE_NAME} globally. Stopping:\"\n                    /sbin/pcs resource disable --wait=600 $BUNDLE_NAME\n                    log \"Restarting ${BUNDLE_NAME} globally. Starting:\"\n                    /sbin/pcs resource enable --wait=600 $BUNDLE_NAME\n                else\n                    log \"${BUNDLE_NAME} is not running anywhere,\" \\\n                         \"cleaning up to restart it globally if necessary\"\n                    /sbin/pcs resource cleanup $BUNDLE_NAME\n                fi\n            else\n                log \"Skipping global restart of ${BUNDLE_NAME} on ${HOSTNAME} it will be restarted by node ${SERVICE_NODEID}\"\n            fi\n\n        else\n            log \"No global restart needed for ${BUNDLE_NAME}.\"\n        fi\n    fi\nelse\n    # During a minor update workflow however, a host gets fully\n    # updated before updating the next one. So unlike stack\n    # update, at the time this script is called, the service's\n    # configs aren't updated on all nodes yet. So only restart the\n    # resource locally, where it's guaranteed that the config is\n    # up to date.\n    HOST=$(facter hostname)\n\n    if bundle_can_be_restarted ${BUNDLE_NAME}; then\n\t# if the resource is running locally, restart it\n\tif crm_resource -r $BUNDLE_NAME --locate 2>&1 | grep -w -q \"${HOST}\"; then\n            log \"Restarting ${BUNDLE_NAME} locally on '${HOST}'\"\n            /sbin/pcs resource restart $BUNDLE_NAME \"${HOST}\"\n\n\telse\n\t    # At this point, if no resource is running locally, it's\n\t    # either because a) it has failed previously, or b) because\n\t    # it's an A/P resource running elsewhere.\n\t    # By cleaning up resource, we ensure that a) it will try to\n\t    # restart, or b) it won't do anything if the resource is\n\t    # already running elsewhere.\n            log \"${BUNDLE_NAME} is currently not running on '${HOST}',\" \\\n                 \"cleaning up its state to restart it if necessary\"\n            /sbin/pcs resource cleanup $BUNDLE_NAME node=\"${HOST}\"\n\tfi\n\n\t# Wait until the resource is in the expected target state\n\t$RESTART_SCRIPTS_DIR/pacemaker_wait_bundle.sh \\\n            $RESOURCE_NAME $BUNDLE_NAME \\\n            \"$WAIT_TARGET_LOCAL\" \"$WAIT_TARGET_ANYWHERE\" \\\n\t    \"${HOST}\" 600\n    else\n        log \"No restart needed for ${BUNDLE_NAME}.\"\n    fi\nfi\n"}, "pacemaker_wait_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# ----\n# Wait for an OCF resource or a bundle to be restarted\n# ----\n# e.g.:\n# M/S OCF:      $0 galera galera-bundle Master\n# clone OCF:    $0 rabbitmq rabbitmq-bundle Started\n# A/P M/S OCF:  $0 redis redis-bundle Slave Master\n# A/P bundle:   $0 openstack-cinder-volume openstack-cinder-volume _ Started\n# clone bundle: $0 haproxy-bundle haproxy-bundle Started\n\n# design note 1:\n#  - this script is called during a minor update; it is called\n#    once per node that hosts a service replica.\n#  - the purpose of this script is to ensure that restarting the\n#    service replica locally won't disrupt the service availability\n#    for the end user. To reach that goal, the script waits until the\n#    service is restarted locally or globallu and reaches a given\n#    target state (i.e. Started, Slave or Master).\n# design note 2:\n#   - we don't want to track restart error: our only job is to ensure\n#     service restart synchronization, not service health.\n#   - In particular, we don't want to error out in case the resource\n#     cannot be restarted locally, because that would make the minor\n#     update fail, even if potentially other replicas still provide\n#     the service.\n# design note 3:\n#   - we can bail out early if we determine that the resource can't\n#     be restarted automatically by pacemaker (e.g. its \"blocked\",\n#     unmanaged or disabled).\n\nlog() {\n    local msg=$1\n    echo \"$(date -u): $1\"\n}\n\nusage() {\n    echo 2>&1 \"Usage: $0 NAME BUNDLE_NAME ROLE_LOCAL [ROLE_ANYWHERE] [HOST] [TIMEOUT]\"\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\n#\n# Utility functions to detect stuck resources\n#\n\nbundle_failures_locally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local replica_name\n    for i in $(seq 0 $last); do\n\treplica_name=${BUNDLE_NAME}-${engine}-${i}\n\tcrm_failcount -q -G -r $replica_name -N $HOST\n    done\n}\n\nbundle_failures_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    for i in $(seq 0 $last); do\n\tcrm_failcount -q -G -r ${BUNDLE_NAME}-${engine}-${i}\n    done\n}\n\nbundle_running_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    # return the number of running bundles replica, i.e. the number of\n    # docker/podman resource replicas currently running in the cluster\n    crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:heartbeat:${engine}']/node)\" -\n}\n\nocf_failures_globally() {\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local bundle_node\n    for i in $(seq 0 $last); do\n\tbundle_node=${BUNDLE_NAME}-${i}\n\tcrm_failcount -q -G -r $NAME -N $bundle_node\n    done\n}\n\ndid_resource_failed_locally() {\n    local failures\n    local running\n    local remotehost\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# if we're dealing with an ocf resource, it is running on a\n\t# pacemaker_remote rather that on the real host, and the\n\t# failcounts are thus associated to the pcmk remote. Replace\n\t# the host's name with the pcmk remote's name.\n        remotehost=$(crm_mon --as-xml | xmllint --xpath \"string(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource/node[@name='${HOST}']/../../resource[@resource_agent='${OCF}:pacemaker:remote']/@id)\" -)\n\tif [ -n \"${remotehost}\" ]; then\n\t    crm_failcount -q -G -r $NAME -N $remotehost | grep -q -w INFINITY\n\t    return $?\n\tfi\n\t# If no pcmk remote is currently running, the failcount from\n\t# the ocf resource is useless, compute the failcount from the\n\t# bundle case instead (computed below).\n    fi\n\n    # for bundles, pacemaker can run any bundle replica locally\n    # (e.g. galera-bundle-docker-{0,1,2}), and a failure happens when\n    # there are no more replica to try.\n    # That is, when _at least_ one replica failed locally, and all the\n    # others either failed or are currently running elsewhere.\n    failures=$(bundle_failures_locally $HOST | grep -c -w INFINITY)\n    running=$(bundle_running_globally)\n    test $failures -gt 0 && \\\n    test $(( $failures + $running )) -ge $BUNDLE_REPLICAS\n}\n\ndid_resource_failed_globally() {\n    local remotecount\n    local failures\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# we check the state of an ocf resource only if the\n\t# pcmkremotes are started\n        remotecount=$(crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node)\" -)\n\tif [ \"${remotecount}\" = \"0\" ]; then\n\t    # no pcmkremote is running, so check the bundle state\n\t    # instead of checking the ocf resource\n\t    # bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\t    failures=$(bundle_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\telse\n\t    # ocf resource failed if it failed to start on\n\t    # all $BUNDLE_REPLICAS bundle nodes\n\t    failures=$(ocf_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\tfi\n    else\n\t# bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\tfailures=$(bundle_failures_globally | grep -c -w INFINITY)\n\ttest $failures -eq $BUNDLE_REPLICAS\n    fi\n}\n\n\n# Input validation\n#\n\nNAME=$1\nif [ -z \"${NAME}\" ]; then\n    echo 2>&1 \"Error: argument NAME must not be empty\"\n    exit 1\nfi\n\nBUNDLE_NAME=$2\nif [ -z \"${BUNDLE_NAME}\" ]; then\n    echo 2>&1 \"Error: argument BUNDLE_NAME must not be empty\"\n    exit 1\nfi\n\nROLE_LOCAL=$3\nif [ \"${ROLE_LOCAL}\" = \"_\" ]; then\n    ROLE_LOCAL=\"\"\nfi\n\nROLE_ANYWHERE=$4\nif [ \"${ROLE_ANYWHERE}\" = \"_\" ]; then\n    ROLE_ANYWHERE=\"\"\nfi\n\nif [ -z \"${ROLE_LOCAL}\" ]; then\n    if [ -z \"${ROLE_ANYWHERE}\" ]; then\n        echo 2>&1 \"Error: either ROLE_LOCAL or ROLE_ANYWHERE must be non empty\"\n        exit 1\n    fi\nelse\n    if !(echo \"${ROLE_LOCAL}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n        echo 2>&1 \"Error: argument ROLE_LOCAL must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n        exit 1\n    fi\nfi\n\nif [ -n \"${ROLE_ANYWHERE}\" ] && !(echo \"${ROLE_ANYWHERE}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n    echo 2>&1 \"Error: argument ROLE_ANYWHERE must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n    exit 1\nfi\n\n# Ensure compatibility with pacemaker 2.1\nif pacemaker_supports_promoted; then\n    ROLE_LOCAL=$(echo \"$ROLE_LOCAL\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    ROLE_ANYWHERE=$(echo \"$ROLE_ANYWHERE\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    OCF=\"ocf\"\nelse\n    OCF=\"ocf:\"\nfi\n\nHOST=${5:-$(facter hostname)}\nTIMEOUT=${6:-600}\n\n\n# Configure the search\n# ----\n# Note: we can't use crm_resource in all searches because we can't\n# easily extract the host the OCF resources run on (crm_resource\n# returns the pcmk-remote nodes rather than the hosts)\n# So instead, we implement various searches with XPath directly.\n\nif [ \"${BUNDLE_NAME}\" != \"${NAME}\" ]; then\n# ocf resource\nlocal_resource_xpath=\"//bundle/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node[@name='${HOST}']/../../resource[@id='${NAME}']\"\nany_resource_xpath=\"//bundle//resource[@id='${NAME}']\"\nreplicas_xpath=\"//bundle/primitive[@id='${BUNDLE_NAME}']/../*[boolean(@image) and boolean(@replicas)]\"\nelse\n# bundle resource\nlocal_resource_xpath=\"//bundle[@id='${NAME}']/replica/resource/node[@name='${HOST}']/../../resource\"\nany_resource_xpath=\"//bundle[@id='${NAME}']//resource\"\nreplicas_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nfi\n\nbundle_def_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nBUNDLE_CONTAINER_ENGINE=$(cibadmin -Q | xmllint --xpath \"name(${bundle_def_xpath})\" -)\nBUNDLE_REPLICAS=$(cibadmin -Q | xmllint --xpath \"string(${bundle_def_xpath}/@replicas)\" -)\n\n\n# The wait algorithm follows a two-stage approach\n#  1. Depending on how the script is called, we first check whether\n#     the resource is restarted locally. An A/P resource may be\n#     restarted elsewhere in the cluster.\n#  2. If needed, check whether the A/P resource has restarted\n#     elsewhere. For A/P M/S resources, in case the resource is\n#     restarted as Slave locally, ensure a Master is available.\n\nsuccess=1\nbailout=1\ntimeout=$TIMEOUT\nrole=\"\"\n\n# Stage 1: local check\nif [ -n \"$ROLE_LOCAL\" ]; then\n    log \"Waiting until ${NAME} has restarted on ${HOST} and is in state ${ROLE_LOCAL}\"\n    log \"Will probe resource state with the following XPath pattern: ${local_resource_xpath}\"\n\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resource=$(crm_mon -r --as-xml | xmllint --xpath \"${local_resource_xpath}\" - 2>/dev/null)\n        role=$(echo \"${resource}\" | sed -ne 's/.*\\Wrole=\"\\([^\"]*\\)\".*/\\1/p')\n\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resource}\" | grep -q -w \"\\Wblocked=\\\"true\\\"\"; then\n            log \"${NAME} is blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_locally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif [ \"$role\" = \"$ROLE_LOCAL\" ]; then\n            success=0\n            continue\n        elif [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" = \"$ROLE_ANYWHERE\" ]; then\n            # A/P: we are restarted in the expected state\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_LOCAL} on ${HOST}\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\n# Stage 2: global check\nif [ $timeout -gt 0 ] && [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" != \"$ROLE_ANYWHERE\" ]; then\n    log \"Wait until ${NAME} is restarted anywhere in the cluster in state ${ROLE_ANYWHERE}\"\n    log \"Will probe resource state with the following XPath pattern: ${any_resource_xpath}\"\n\n    success=1\n    bailout=1\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resources=$(crm_mon -r --as-xml | xmllint --xpath \"${any_resource_xpath}\" - 2>/dev/null)\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif ! (echo \"${resources}\" | grep -q -w \"\\Wblocked=\\\"false\\\"\"); then\n            log \"${NAME} blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_globally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resources}\" | grep -q -w \"\\Wrole=\\\"${ROLE_ANYWHERE}\\\"\"; then\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_ANYWHERE} anywhere in the cluster\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\nif [ $timeout -le 0 ]; then\n    log \"Timeout reached after ${TIMEOUT}s while waiting for ${NAME} to be restarted\"\nelif [ $bailout -le 0 ]; then\n    log \"Restart monitoring for ${NAME} cancelled\"\nfi\n\nif [ $success -eq 0 ]; then\n    log \"${NAME} successfully restarted\"\nelse\n    log \"${NAME} was not restarted properly\"\nfi\n\n# Don't block minor update or stack update if the wait was unsuccessful\nexit 0\n"}, "wait-port-and-run.sh": {"mode": "0755", "content": "#!/usr/bin/bash\nset -eu\n\nHOST=$1\nPORT=$2\n\necho \"$(date -u): Checking whether we can bind to ${HOST}:${PORT}\"\nwhile (ss -Htnl src \"${HOST}\" \"sport = :${PORT}\" | grep -wq \"${PORT}\"); do\n    echo \"$(date -u): ${HOST}:${PORT} still in use, waiting...\";\n    sleep 10;\ndone\n\nshift 2\nCOMMAND=\"$*\"\nif [ -z \"${COMMAND}\" ]; then\n    COMMAND=\"true\"\nfi\nexec $COMMAND\n"}, "pacemaker_resource_lock.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nMAX_RETRIES=10\nCIB_ENOTFOUND=105\n\nusage() {\n   echo \"Set a global property in the cluster with a validity timestamp.\"\n   echo \"Usage:\"\n   echo \"   $0 --acquire <lock_name> <lock_owner> <lock_ttl_in_seconds>\"\n   echo \"   $0 --release <lock_name> <lock_owner>\"\n   echo\n}\n\nlog() {\n    echo \"$(date -u): $1\" 1>&2\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\nlock_create() {\n    local name=$1\n    local data=$2\n    # cibadmin won't overwrite a key if someone else succeeded to create it concurrently\n    cibadmin --sync-call --scope crm_config --create --xml-text \"<cluster_property_set id='${name}'><nvpair id='${name}-pair' name='${name}' value='${data}'/></cluster_property_set>\" &>/dev/null\n    return $?\n}\n\nlock_update() {\n    local name=$1\n    local expected_data=$2\n    local new_data=$3\n    # we only update the lock we expect to see, so we can't update someone else's lock\n    cibadmin --sync-call --scope crm_config --modify --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" --xml-text \"<nvpair id='${name}-pair' name='${name}' value='${new_data}'/>\" &>/dev/null\n    return $?\n}\n\nlock_delete() {\n    local name=$1\n    local expected_data=$2\n    # we only delete the lock we expect to see, so we can't delete someone else's lock\n    cibadmin --sync-call --scope crm_config --delete --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" &>/dev/null\n    return $?\n}\n\nlock_get() {\n    local lockname=$1\n    local res\n    local rc\n    res=$(cibadmin --query --scope crm_config --xpath \"//cluster_property_set/nvpair[@name='$lockname']\" 2>/dev/null)\n    rc=$?\n    if [ $rc -eq 0 ]; then\n        echo \"$res\" | sed -n 's/.*value=\"\\([^\"]*\\)\".*/\\1/p'\n    fi\n    return $rc\n}\n\nlock_owner() {\n    local lock=$1\n    echo \"$lock\" | cut -d':' -f1\n}\n\nlock_has_expired() {\n    local lock=$1\n    local expiry=$(echo \"$lock\" | cut -d':' -f2)\n    local now=$(date +%s)\n    test $now -ge $expiry\n}\n\n\n# Perform a lock action and restart if the CIB has been modified before\n# committing the lock action\ntry_action() {\n    local fun=$1\n    local lock=$2\n    local requester=$3\n    local args=${4:-}\n    local tries=$MAX_RETRIES\n    local rc=1\n    if [ \"$fun\" = \"lock_acquire\" ] || [ \"$fun\" = \"lock_release\" ]; then\n        log \"Try running $fun\"\n    else\n        return 2\n    fi\n    while [ $rc -ne 0 ]; do\n        $fun $lock $requester $args\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Operation $1 succeeded\"\n            return 0\n        elif [ $rc -eq 3 ]; then\n            # rc == 3 -> CIB changed before push\n            if [ $tries -eq 0 ]; then\n                log \"Failed to commit after $MAX_RETRIES retries. Bailing out.\"\n                return 2\n            else\n                log \"Failed to commit. Retrying operation.\"\n                tries=$(($tries - 1))\n            fi\n        elif [ $rc -eq 2 ]; then\n            # rc == 2 -> unrecoverable cib error (e.g. pacemaker down)\n            log \"Unexpected failure. Bailing out\"\n            return $rc\n        else\n            # rc == 1 -> lock error (not owner, lock doesn't exists)\n            return $rc\n        fi\n    done\n}\n\n# The lock mechanism uses cibadmin's atomic creation so cluster-wide\n# state coherency is guaranteed by pacemaker\nlock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc\n    local lock\n    local expiry\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -n \"$lock\" ]; then\n        lock_has_expired $lock\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Lock has expired, now available for being held\"\n        else\n            # lock is still held. check whether we're the owner\n            owner=$(lock_owner $lock)\n            if [ \"$owner\" = \"$requester\" ];then\n                log \"Requester already owns the lock, acquiring attempt will just reconfigure the TTL\"\n            else\n                log \"Lock is held by someone else ($owner)\"\n                return 1\n            fi\n        fi\n    else\n        log \"Lock is not held yet\"\n    fi\n\n    # prepare the lock info\n    expiry=$(($(date +%s) + $ttl))\n\n    if [ -n \"$lock\" ]; then\n        log \"Attempting to update the lock\"\n        lock_update $lockname \"$lock\" \"$requester:$expiry\"\n        rc=$?\n    else\n        log \"Attempting to acquire the lock\"\n        lock_create $lockname \"$requester:$expiry\"\n        rc=$?\n    fi\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' acquired by '$requester', valid until $(date -d @$expiry)\"\n        return 0\n    else\n        log \"CIB changed, lock cannot be acquired\"\n        return 3\n    fi\n}\n\n\n# The lock mechanism uses the CIB's num_updates tag to implement\n# a conditional store. Cluster-wide locking is guaranteed by pacemaker\nlock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n    local lock\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        log \"Lock doesn't exist. Nothing to release\"\n        return 0\n    else\n        log \"Lock exists, check whether we're the owner\"\n        owner=$(lock_owner $lock)\n        if [ \"$owner\" != \"$requester\" ];then\n            log \"Lock is held by someone else ($owner), will not unlock\"\n            return 1\n        fi\n    fi\n\n    lock_delete $lockname \"$lock\"\n    rc=$?\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' released by '$requester'\"\n        return 0\n    else\n        log \"CIB deletion error, lock cannot be released\"\n        return 3\n    fi\n}\n\n\n# Retrieve the owner of a lock from the CIB\n# this is a read-only operation, so no need to log debug info\nlock_get_owner() {\n    local lockname=$1\n    local rc\n    local lock\n    local owner\n\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        return 1\n    else\n        lock_owner $lock\n        return 0\n    fi\n}\n\n\nACTION=$1\nLOCKNAME=$2\nREQUESTER=$3\nTTL=${4:-60}\n\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nif [ $ACTION != \"--help\" ]; then\n    if [ -z \"$LOCKNAME\" ]; then\n        error \"You must specific a lock name\"\n    fi\n    if [ $ACTION != \"--owner\" ] && [ $ACTION != \"-o\" ]; then\n        if [ -z \"$REQUESTER\" ]; then\n            error \"You must specific a lock requester\"\n        fi\n    fi\nfi\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) try_action lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --release|-r) try_action lock_release $LOCKNAME $REQUESTER;;\n    --acquire-once|-A) lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --owner|-o) lock_get_owner $LOCKNAME;;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}, "pacemaker_mutex_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_restart_bundle.sh --lock mysql galera galera-bundle Master _\n# pacemaker_mutex_restart_bundle.sh --lock ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\n\nset -u\n\nusage() {\n    echo \"Restart a clustered resource in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --lock <tripleo-service> <pcmk-resource> <pcmk-bundle> <target-state-local> <target-state-cluster>\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\nACTION=$1\ncase $ACTION in\n    --help) usage; exit 0;;\n    --lock) ;;\n    *) error \"Unknown action '$ACTION'\";;\nesac\n\nTRIPLEO_SERVICE=$2\nLOCK_NAME=${TRIPLEO_SERVICE}-restart-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to restart resource $TRIPLEO_SERVICE\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\nRESOURCE_NAME=$3\nBUNDLE_NAME=$4\nWAIT_TARGET_LOCAL=$5\nWAIT_TARGET_ANYWHERE=${6:-_}\n\nif pacemaker_supports_promoted; then\n    WAIT_TARGET_LOCAL=$(echo \"$5\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    WAIT_TARGET_ANYWHERE=$(echo \"${6:-_}\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    promoted_role=\"Promoted\"\nelse\n    promoted_role=\"Master\"\nfi\n\n# The lock TTL should accomodate for the resource start/promote timeout\nif [ \"$RESOURCE_NAME\" != \"$BUNDLE_NAME\" ]; then\n    if [ \"$WAIT_TARGET_LOCAL\" = \"$promoted_role\" ] || [ \"$WAIT_TARGET_ANYWHERE\" = \"$promoted_role\" ]; then\n        rsc_op=\"promote\"\n    else\n        rsc_op=\"start\"\n    fi\n    # <op id=\"galera-promote-interval-0s\" interval=\"0s\" name=\"promote\" on-fail=\"block\" timeout=\"300s\"/>\n    PCMK_TTL=$(cibadmin -Q | xmllint -xpath \"string(//primitive[@id='${RESOURCE_NAME}']/operations/op[@name='${rsc_op}']/@timeout)\" - | sed 's/s$//')\n    LOCK_TTL=$((PCMK_TTL + 30))\nelse\n    # The podman RA's default start timeout\n    LOCK_TTL=90\nfi\n\nlog \"Acquire a ${LOCK_TTL}s restart lock for service $TRIPLEO_SERVICE before restarting it\"\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nrc=1\nwhile [ $rc -ne 0 ]; do\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire $LOCK_NAME $LOCK_OWNER $LOCK_TTL\n    rc=$?\n    if [ $rc != 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not acquire lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Could not acquire lock, retrying\"\n            sleep 10\n        fi\n    fi\ndone\n\nlog \"Restart the service $TRIPLEO_SERVICE locally\"\n# Reuse the local restart script in t-h-t (driven by env var TRIPLEO_MINOR_UPDATE)\nTRIPLEO_MINOR_UPDATE=true /var/lib/container-config-scripts/pacemaker_restart_bundle.sh $TRIPLEO_SERVICE $RESOURCE_NAME $BUNDLE_NAME $WAIT_TARGET_LOCAL $WAIT_TARGET_ANYWHERE\n\n# If we reached this point, always try to release the lock\nlog \"Release the restart lock for service $TRIPLEO_SERVICE\"\n/var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $LOCK_NAME $LOCK_OWNER\nrc=$?\nif [ $rc -ne 0 ] && [ $rc -ne 1 ]; then\n    error \"Could not release held lock (rc: $rc)\"\nfi\n"}, "pacemaker_mutex_shutdown.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_shutdown.sh --acquire\n# pacemaker_mutex_shutdown.sh --release\n\nset -u\n\nusage() {\n    echo \"Shutdown a cluster node in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --acquire # prevent other node from shutting down until we hold the lock\"\n    echo \"   $0 --release # release the lock, other node can compete for the shutdown lock\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nshutdown_lock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc=1\n    local current_owner\n    local owner_stopped\n    local owner_rc\n\n    log \"Acquiring the shutdown lock\"\n    while [ $rc -ne 0 ]; do\n        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire-once $lockname $requester $ttl\n        rc=$?\n        if [ $rc -ne 0 ]; then\n            if [ $rc -eq 2 ]; then\n                error \"Could not acquire the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n            else\n                # The lock is held by another node.\n                current_owner=$(/var/lib/container-config-scripts/pacemaker_resource_lock.sh --owner $lockname)\n                owner_rc=$?\n                if [ $owner_rc -eq 2 ]; then\n                    error \"Could not get the shutdown lock owner due to unrecoverable error (rc: $owner_rc), bailing out\"\n                fi\n                if [ $owner_rc -eq 0 ]; then\n                    # If the owner is marked as offline, that means it has shutdown and\n                    # we can clean the lock preemptively and try to acquire it.\n                    owner_stopped=$(crm_mon -1X | xmllint --xpath 'count(//nodes/node[@name=\"'${current_owner}'\" and @online=\"false\" and @unclean=\"false\"])' -)\n                    if [ \"${owner_stopped}\" = \"1\" ]; then\n                        log \"Shutdown lock held by stopped node '${current_owner}', lock can be released\"\n                        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $current_owner\n                        continue\n                    fi\n                fi\n                log \"Shutdown lock held by another node (rc: $rc), retrying\"\n                sleep 10\n            fi\n        fi\n    done\n    log \"Shutdown lock acquired\"\n    return 0\n}\n\n\n# Release the lock if we still own it. Not owning it anymore is not fatal\nshutdown_lock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n\n    log \"Releasing the shutdown lock\"\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $requester\n    rc=$?\n    if [ $rc -ne 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not release the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Shutdown lock no longer held, nothing to do\"\n        fi\n    else\n        log \"Shutdown lock released\"\n    fi\n    return 0\n}\n\n\nACTION=$1\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nLOCK_NAME=tripleo-shutdown-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to aquire the shutdown lock\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\n# We start with a very high TTL, that long enough to accomodate a cluster stop.\n# As soon as the node will get offline, the other competing node will be entitled\n# to steal the lock, so they should never wait that long in practice.\nLOCK_TTL=600\n\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) shutdown_lock_acquire ${LOCK_NAME} ${LOCK_OWNER} ${LOCK_TTL};;\n    --release|-r) shutdown_lock_release ${LOCK_NAME} ${LOCK_OWNER};;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}}, "tuple:('role_data', 'docker_config')": {"step_2": {"create_haproxy_wrapper": {"start_order": 1, "detach": false, "net": "host", "pid": "host", "user": "root", "command": ["/container_puppet_apply.sh", "4", "file", "include ::tripleo::profile::base::neutron::ovn_metadata_agent_wrappers"], "image": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/var/lib/container-config-scripts/container_puppet_apply.sh:/container_puppet_apply.sh:ro", "/etc/puppet:/tmp/puppet-etc:ro", "/usr/share/openstack-puppet/modules:/usr/share/openstack-puppet/modules:ro", "/run/openvswitch:/run/openvswitch:shared,z", "/var/lib/neutron:/var/lib/neutron:shared,z"]}}, "step_4": {"setup_ovs_manager": {"start_order": 0, "detach": false, "net": "host", "privileged": true, "user": "root", "command": ["/container_puppet_apply.sh", "4", "exec", "include tripleo::profile::base::neutron::ovn_metadata"], "image": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/var/lib/container-config-scripts/container_puppet_apply.sh:/container_puppet_apply.sh:ro", "/etc/puppet:/tmp/puppet-etc:ro", "/usr/share/openstack-puppet/modules:/usr/share/openstack-puppet/modules:ro", "/lib/modules:/lib/modules:ro", "/run/openvswitch:/run/openvswitch:shared,z"], "environment": {"TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}, "ovn_metadata_agent": {"start_order": 1, "image": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "net": "host", "pid": "host", "cgroupns": "host", "privileged": true, "restart": "always", "healthcheck": {"test": "/openstack/healthcheck"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/neutron:/var/log/neutron:z", "/var/lib/kolla/config_files/ovn_metadata_agent.json:/var/lib/kolla/config_files/config.json:ro", "/var/lib/config-data/puppet-generated/neutron:/var/lib/kolla/config_files/src:ro", "/lib/modules:/lib/modules:ro", "/run/openvswitch:/run/openvswitch:shared,z", "/var/lib/neutron:/var/lib/neutron:shared,z", "/run/netns:/run/netns:shared", "/var/lib/neutron/kill_scripts:/etc/neutron/kill_scripts:shared,z", "/var/lib/neutron/ovn_metadata_haproxy_wrapper:/usr/local/bin/haproxy:ro", "/etc/pki/tls/certs/ovn_metadata.crt:/etc/pki/tls/certs/ovn_metadata.crt", "/etc/pki/tls/private/ovn_metadata.key:/etc/pki/tls/private/ovn_metadata.key"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}}}, "tuple:('role_data', 'service_name')": "ovn_metadata", "role_data": {"service_name": "ovn_metadata", "monitoring_subscription": "overcloud-ovn-metadata", "config_settings": {"neutron::notification_driver": ["noop"], "neutron::core_plugin": "ml2", "neutron::service_plugins": ["qos", "ovn-router", "trunk", "segments", "port_forwarding", "log"], "neutron::report_interval": 300, "neutron::logging::debug": true, "neutron::purge_config": false, "neutron::allow_overlapping_ips": true, "neutron::dhcp_agent_notification": true, "neutron::dns_domain": "ooo.test", "neutron::rabbit_heartbeat_timeout_threshold": 60, "neutron::host": "%{hiera('fqdn_canonical')}", "neutron::db::database_db_max_retries": -1, "neutron::db::database_max_retries": -1, "neutron::db::sync::db_sync_timeout": 900, "neutron::global_physnet_mtu": 1500, "neutron::db::sync::extra_params": "", "neutron::vlan_transparent": false, "neutron::rabbit_heartbeat_in_pthread": false, "tripleo::profile::base::neutron::ovn_metadata_agent_wrappers::enable_haproxy_wrapper": true, "tripleo::profile::base::neutron::ovn_metadata_agent_wrappers::haproxy_process_wrapper": "/var/lib/neutron/ovn_metadata_haproxy_wrapper", "tripleo::profile::base::neutron::ovn_metadata_agent_wrappers::haproxy_image": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "tripleo::profile::base::neutron::ovn_metadata_agent_wrappers::debug": true, "tripleo::profile::base::neutron::container_cli": "podman", "neutron::agents::ovn_metadata::shared_secret": "bxeW2RrqpEnHixt0KeySTY5OI", "neutron::agents::ovn_metadata::auth_password": "CC70wbFRk1QjXjqZLaKBjXfHn", "neutron::agents::ovn_metadata::auth_url": "https://overcloud.internalapi.ooo.test:5000", "neutron::agents::ovn_metadata::auth_tenant": "service", "neutron::agents::ovn_metadata::metadata_host": "overcloud.internalapi.ooo.test", "neutron::agents::ovn_metadata::ovsdb_connection_timeout": 180, "neutron::agents::ovn_metadata::ovsdb_probe_interval": 60000, "neutron::agents::ovn_metadata::hwol_qos_enabled": false, "ovn::northbound::port": 6641, "ovn::southbound::port": 6642, "neutron::agents::ovn_metadata::debug": true, "neutron::agents::ovn_metadata::metadata_protocol": "https", "neutron::agents::ovn_metadata::metadata_workers": "1", "tripleo::profile::base::neutron::ovn_metadata::ovn_nb_ca_cert": "/etc/ipa/ca.crt", "tripleo::profile::base::neutron::ovn_metadata::ovn_sb_ca_cert": "/etc/ipa/ca.crt", "tripleo::profile::base::neutron::ovn_metadata::protocol": "ssl", "tripleo::profile::base::neutron::ovn_metadata::ovn_nb_certificate": "/etc/pki/tls/certs/ovn_metadata.crt", "tripleo::profile::base::neutron::ovn_metadata::ovn_nb_private_key": "/etc/pki/tls/private/ovn_metadata.key", "tripleo::profile::base::neutron::ovn_metadata::ovn_sb_certificate": "/etc/pki/tls/certs/ovn_metadata.crt", "tripleo::profile::base::neutron::ovn_metadata::ovn_sb_private_key": "/etc/pki/tls/private/ovn_metadata.key"}, "puppet_config": {"puppet_tags": "neutron_config,ovn_metadata_agent_config", "config_volume": "neutron", "step_config": "include tripleo::profile::base::neutron::ovn_metadata\n", "config_image": "registry.redhat.io/rhosp-rhel9/openstack-neutron-server:17.1", "volumes": ["/lib/modules:/lib/modules:ro", "/run/openvswitch:/run/openvswitch:shared,z"]}, "kolla_config": {"/var/lib/kolla/config_files/ovn_metadata_agent.json": {"command": "/usr/bin/networking-ovn-metadata-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/networking-ovn/networking-ovn-metadata-agent.ini --log-file=/var/log/neutron/ovn-metadata-agent.log", "config_files": [{"source": "/var/lib/kolla/config_files/src/*", "dest": "/", "merge": true, "preserve_properties": true}], "permissions": [{"path": "/var/log/neutron", "owner": "neutron:neutron", "recurse": true}, {"path": "/var/lib/neutron", "owner": "neutron:neutron", "recurse": true}, {"path": "/etc/pki/tls/certs/ovn_metadata.crt", "owner": "neutron:neutron", "optional": true, "perm": "0644"}, {"path": "/etc/pki/tls/private/ovn_metadata.key", "owner": "neutron:neutron", "optional": true, "perm": "0644"}]}}, "container_config_scripts": {"container_puppet_apply.sh": {"mode": "0700", "content": "#!/bin/bash\nset -eux\nSTEP=$1\nTAGS=$2\nCONFIG=$3\nEXTRA_ARGS=${4:-''}\nif [ -d /tmp/puppet-etc ]; then\n  # ignore copy failures as these may be the same file depending on docker mounts\n  cp -a /tmp/puppet-etc/* /etc/puppet || true\nfi\necho \"{\\\"step\\\": ${STEP}}\" > /etc/puppet/hieradata/docker_puppet.json\n# $::deployment_type in puppet-tripleo\nexport FACTER_deployment_type=containers\nset +e\npuppet apply $EXTRA_ARGS \\\n    --verbose \\\n    --detailed-exitcodes \\\n    --summarize \\\n    --color=false \\\n    --modulepath /etc/puppet/modules:/opt/stack/puppet-modules:/usr/share/openstack-puppet/modules \\\n    --tags $TAGS \\\n    -e \"noop_resource('package'); ${CONFIG}\"\nrc=$?\nset -e\nset +ux\nif [ $rc -eq 2 -o $rc -eq 0 ]; then\n    exit 0\nfi\nexit $rc\n"}, "pyshim.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n# Copyright 2018 Red Hat Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n#\n# Usage: pyshim.sh <script and/or arguments>\n#\n# Unfortunately THT doesn't know which version of python might be in a\n# container so we need this script to be able to try python3 or python2\n# depending on availability.  Since this is a temporary shim until we've\n# fully cut over to python3, we check for the existence of python3 first\n# before falling back to python2. This will help in the transition from\n# python2 based containers to python3.\n\nshow_usage() {\n    echo \"Usage: pyshim.sh <script and/or arguments>\"\n}\n\nif [ $# -lt 1 ]\nthen\n    show_usage\n    exit 1\nfi\n\nset -x\nif command -v python3 >/dev/null; then\n    python3 \"$@\"\nelif command -v python2 >/dev/null; then\n    python2 \"$@\"\nelif command -v python >/dev/null; then\n    python \"$@\"\nelse\n    echo \"ERROR: python is not available!\"\n    exit 1\nfi\n"}, "pacemaker_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nset -u\n\n# ./pacemaker_restart_bundle.sh mysql galera galera-bundle Master _\n# ./pacemaker_restart_bundle.sh redis redis redis-bundle Slave Master\n# ./pacemaker_restart_bundle.sh ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\nRESTART_SCRIPTS_DIR=$(dirname $0)\nTRIPLEO_SERVICE=$1\nRESOURCE_NAME=$2\nBUNDLE_NAME=$3\nWAIT_TARGET_LOCAL=$4\nWAIT_TARGET_ANYWHERE=${5:-_}\nTRIPLEO_MINOR_UPDATE=\"${TRIPLEO_MINOR_UPDATE:-false}\"\nTRIPLEO_HA_WRAPPER_RESOURCE_EXISTS=\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS:-false}\"\n\nbundle_can_be_restarted() {\n    local bundle=$1\n    # As long as the resource bundle is managed by pacemaker and is\n    # not meant to stay stopped, no matter the state of any inner\n    # pcmk_remote or ocf resource, we should restart it to give it a\n    # chance to read the new config.\n    [ \"$(crm_resource --meta -r $1 -g is-managed 2>/dev/null)\" != \"false\" ] && \\\n    [ \"$(crm_resource --meta -r $1 -g target-role 2>/dev/null)\" != \"Stopped\" ]\n}\n\nlog() {\n    local msg=$1\n    logger -t pcmkrestart \"$1\"\n}\n\nHOSTNAME=$(/bin/hostname -s)\nif [ x\"${TRIPLEO_MINOR_UPDATE,,}\" != x\"true\" ]; then\n    if [ x\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS,,}\" = x\"false\" ]; then\n        # Do not restart during initial deployment, as the resource\n        # has just been created.\n        SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n        if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n            log \"Initial deployment, skipping the restart of ${BUNDLE_NAME}\"\n\tfi\n        exit 0\n    else\n        # During a stack update, this script is called in parallel on\n        # every node the resource runs on, after the service's configs\n        # have been updated on all nodes. So we need to run pcs only\n        # once (e.g. on the service's boostrap node).\n        if bundle_can_be_restarted ${BUNDLE_NAME}; then\n            SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n            if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n                replicas_running=$(crm_resource -Q -r $BUNDLE_NAME --locate 2>&1 | wc -l)\n                if [ \"$replicas_running\" != \"0\" ]; then\n                    log \"Restarting ${BUNDLE_NAME} globally. Stopping:\"\n                    /sbin/pcs resource disable --wait=600 $BUNDLE_NAME\n                    log \"Restarting ${BUNDLE_NAME} globally. Starting:\"\n                    /sbin/pcs resource enable --wait=600 $BUNDLE_NAME\n                else\n                    log \"${BUNDLE_NAME} is not running anywhere,\" \\\n                         \"cleaning up to restart it globally if necessary\"\n                    /sbin/pcs resource cleanup $BUNDLE_NAME\n                fi\n            else\n                log \"Skipping global restart of ${BUNDLE_NAME} on ${HOSTNAME} it will be restarted by node ${SERVICE_NODEID}\"\n            fi\n\n        else\n            log \"No global restart needed for ${BUNDLE_NAME}.\"\n        fi\n    fi\nelse\n    # During a minor update workflow however, a host gets fully\n    # updated before updating the next one. So unlike stack\n    # update, at the time this script is called, the service's\n    # configs aren't updated on all nodes yet. So only restart the\n    # resource locally, where it's guaranteed that the config is\n    # up to date.\n    HOST=$(facter hostname)\n\n    if bundle_can_be_restarted ${BUNDLE_NAME}; then\n\t# if the resource is running locally, restart it\n\tif crm_resource -r $BUNDLE_NAME --locate 2>&1 | grep -w -q \"${HOST}\"; then\n            log \"Restarting ${BUNDLE_NAME} locally on '${HOST}'\"\n            /sbin/pcs resource restart $BUNDLE_NAME \"${HOST}\"\n\n\telse\n\t    # At this point, if no resource is running locally, it's\n\t    # either because a) it has failed previously, or b) because\n\t    # it's an A/P resource running elsewhere.\n\t    # By cleaning up resource, we ensure that a) it will try to\n\t    # restart, or b) it won't do anything if the resource is\n\t    # already running elsewhere.\n            log \"${BUNDLE_NAME} is currently not running on '${HOST}',\" \\\n                 \"cleaning up its state to restart it if necessary\"\n            /sbin/pcs resource cleanup $BUNDLE_NAME node=\"${HOST}\"\n\tfi\n\n\t# Wait until the resource is in the expected target state\n\t$RESTART_SCRIPTS_DIR/pacemaker_wait_bundle.sh \\\n            $RESOURCE_NAME $BUNDLE_NAME \\\n            \"$WAIT_TARGET_LOCAL\" \"$WAIT_TARGET_ANYWHERE\" \\\n\t    \"${HOST}\" 600\n    else\n        log \"No restart needed for ${BUNDLE_NAME}.\"\n    fi\nfi\n"}, "pacemaker_wait_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# ----\n# Wait for an OCF resource or a bundle to be restarted\n# ----\n# e.g.:\n# M/S OCF:      $0 galera galera-bundle Master\n# clone OCF:    $0 rabbitmq rabbitmq-bundle Started\n# A/P M/S OCF:  $0 redis redis-bundle Slave Master\n# A/P bundle:   $0 openstack-cinder-volume openstack-cinder-volume _ Started\n# clone bundle: $0 haproxy-bundle haproxy-bundle Started\n\n# design note 1:\n#  - this script is called during a minor update; it is called\n#    once per node that hosts a service replica.\n#  - the purpose of this script is to ensure that restarting the\n#    service replica locally won't disrupt the service availability\n#    for the end user. To reach that goal, the script waits until the\n#    service is restarted locally or globallu and reaches a given\n#    target state (i.e. Started, Slave or Master).\n# design note 2:\n#   - we don't want to track restart error: our only job is to ensure\n#     service restart synchronization, not service health.\n#   - In particular, we don't want to error out in case the resource\n#     cannot be restarted locally, because that would make the minor\n#     update fail, even if potentially other replicas still provide\n#     the service.\n# design note 3:\n#   - we can bail out early if we determine that the resource can't\n#     be restarted automatically by pacemaker (e.g. its \"blocked\",\n#     unmanaged or disabled).\n\nlog() {\n    local msg=$1\n    echo \"$(date -u): $1\"\n}\n\nusage() {\n    echo 2>&1 \"Usage: $0 NAME BUNDLE_NAME ROLE_LOCAL [ROLE_ANYWHERE] [HOST] [TIMEOUT]\"\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\n#\n# Utility functions to detect stuck resources\n#\n\nbundle_failures_locally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local replica_name\n    for i in $(seq 0 $last); do\n\treplica_name=${BUNDLE_NAME}-${engine}-${i}\n\tcrm_failcount -q -G -r $replica_name -N $HOST\n    done\n}\n\nbundle_failures_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    for i in $(seq 0 $last); do\n\tcrm_failcount -q -G -r ${BUNDLE_NAME}-${engine}-${i}\n    done\n}\n\nbundle_running_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    # return the number of running bundles replica, i.e. the number of\n    # docker/podman resource replicas currently running in the cluster\n    crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:heartbeat:${engine}']/node)\" -\n}\n\nocf_failures_globally() {\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local bundle_node\n    for i in $(seq 0 $last); do\n\tbundle_node=${BUNDLE_NAME}-${i}\n\tcrm_failcount -q -G -r $NAME -N $bundle_node\n    done\n}\n\ndid_resource_failed_locally() {\n    local failures\n    local running\n    local remotehost\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# if we're dealing with an ocf resource, it is running on a\n\t# pacemaker_remote rather that on the real host, and the\n\t# failcounts are thus associated to the pcmk remote. Replace\n\t# the host's name with the pcmk remote's name.\n        remotehost=$(crm_mon --as-xml | xmllint --xpath \"string(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource/node[@name='${HOST}']/../../resource[@resource_agent='${OCF}:pacemaker:remote']/@id)\" -)\n\tif [ -n \"${remotehost}\" ]; then\n\t    crm_failcount -q -G -r $NAME -N $remotehost | grep -q -w INFINITY\n\t    return $?\n\tfi\n\t# If no pcmk remote is currently running, the failcount from\n\t# the ocf resource is useless, compute the failcount from the\n\t# bundle case instead (computed below).\n    fi\n\n    # for bundles, pacemaker can run any bundle replica locally\n    # (e.g. galera-bundle-docker-{0,1,2}), and a failure happens when\n    # there are no more replica to try.\n    # That is, when _at least_ one replica failed locally, and all the\n    # others either failed or are currently running elsewhere.\n    failures=$(bundle_failures_locally $HOST | grep -c -w INFINITY)\n    running=$(bundle_running_globally)\n    test $failures -gt 0 && \\\n    test $(( $failures + $running )) -ge $BUNDLE_REPLICAS\n}\n\ndid_resource_failed_globally() {\n    local remotecount\n    local failures\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# we check the state of an ocf resource only if the\n\t# pcmkremotes are started\n        remotecount=$(crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node)\" -)\n\tif [ \"${remotecount}\" = \"0\" ]; then\n\t    # no pcmkremote is running, so check the bundle state\n\t    # instead of checking the ocf resource\n\t    # bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\t    failures=$(bundle_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\telse\n\t    # ocf resource failed if it failed to start on\n\t    # all $BUNDLE_REPLICAS bundle nodes\n\t    failures=$(ocf_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\tfi\n    else\n\t# bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\tfailures=$(bundle_failures_globally | grep -c -w INFINITY)\n\ttest $failures -eq $BUNDLE_REPLICAS\n    fi\n}\n\n\n# Input validation\n#\n\nNAME=$1\nif [ -z \"${NAME}\" ]; then\n    echo 2>&1 \"Error: argument NAME must not be empty\"\n    exit 1\nfi\n\nBUNDLE_NAME=$2\nif [ -z \"${BUNDLE_NAME}\" ]; then\n    echo 2>&1 \"Error: argument BUNDLE_NAME must not be empty\"\n    exit 1\nfi\n\nROLE_LOCAL=$3\nif [ \"${ROLE_LOCAL}\" = \"_\" ]; then\n    ROLE_LOCAL=\"\"\nfi\n\nROLE_ANYWHERE=$4\nif [ \"${ROLE_ANYWHERE}\" = \"_\" ]; then\n    ROLE_ANYWHERE=\"\"\nfi\n\nif [ -z \"${ROLE_LOCAL}\" ]; then\n    if [ -z \"${ROLE_ANYWHERE}\" ]; then\n        echo 2>&1 \"Error: either ROLE_LOCAL or ROLE_ANYWHERE must be non empty\"\n        exit 1\n    fi\nelse\n    if !(echo \"${ROLE_LOCAL}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n        echo 2>&1 \"Error: argument ROLE_LOCAL must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n        exit 1\n    fi\nfi\n\nif [ -n \"${ROLE_ANYWHERE}\" ] && !(echo \"${ROLE_ANYWHERE}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n    echo 2>&1 \"Error: argument ROLE_ANYWHERE must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n    exit 1\nfi\n\n# Ensure compatibility with pacemaker 2.1\nif pacemaker_supports_promoted; then\n    ROLE_LOCAL=$(echo \"$ROLE_LOCAL\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    ROLE_ANYWHERE=$(echo \"$ROLE_ANYWHERE\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    OCF=\"ocf\"\nelse\n    OCF=\"ocf:\"\nfi\n\nHOST=${5:-$(facter hostname)}\nTIMEOUT=${6:-600}\n\n\n# Configure the search\n# ----\n# Note: we can't use crm_resource in all searches because we can't\n# easily extract the host the OCF resources run on (crm_resource\n# returns the pcmk-remote nodes rather than the hosts)\n# So instead, we implement various searches with XPath directly.\n\nif [ \"${BUNDLE_NAME}\" != \"${NAME}\" ]; then\n# ocf resource\nlocal_resource_xpath=\"//bundle/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node[@name='${HOST}']/../../resource[@id='${NAME}']\"\nany_resource_xpath=\"//bundle//resource[@id='${NAME}']\"\nreplicas_xpath=\"//bundle/primitive[@id='${BUNDLE_NAME}']/../*[boolean(@image) and boolean(@replicas)]\"\nelse\n# bundle resource\nlocal_resource_xpath=\"//bundle[@id='${NAME}']/replica/resource/node[@name='${HOST}']/../../resource\"\nany_resource_xpath=\"//bundle[@id='${NAME}']//resource\"\nreplicas_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nfi\n\nbundle_def_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nBUNDLE_CONTAINER_ENGINE=$(cibadmin -Q | xmllint --xpath \"name(${bundle_def_xpath})\" -)\nBUNDLE_REPLICAS=$(cibadmin -Q | xmllint --xpath \"string(${bundle_def_xpath}/@replicas)\" -)\n\n\n# The wait algorithm follows a two-stage approach\n#  1. Depending on how the script is called, we first check whether\n#     the resource is restarted locally. An A/P resource may be\n#     restarted elsewhere in the cluster.\n#  2. If needed, check whether the A/P resource has restarted\n#     elsewhere. For A/P M/S resources, in case the resource is\n#     restarted as Slave locally, ensure a Master is available.\n\nsuccess=1\nbailout=1\ntimeout=$TIMEOUT\nrole=\"\"\n\n# Stage 1: local check\nif [ -n \"$ROLE_LOCAL\" ]; then\n    log \"Waiting until ${NAME} has restarted on ${HOST} and is in state ${ROLE_LOCAL}\"\n    log \"Will probe resource state with the following XPath pattern: ${local_resource_xpath}\"\n\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resource=$(crm_mon -r --as-xml | xmllint --xpath \"${local_resource_xpath}\" - 2>/dev/null)\n        role=$(echo \"${resource}\" | sed -ne 's/.*\\Wrole=\"\\([^\"]*\\)\".*/\\1/p')\n\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resource}\" | grep -q -w \"\\Wblocked=\\\"true\\\"\"; then\n            log \"${NAME} is blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_locally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif [ \"$role\" = \"$ROLE_LOCAL\" ]; then\n            success=0\n            continue\n        elif [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" = \"$ROLE_ANYWHERE\" ]; then\n            # A/P: we are restarted in the expected state\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_LOCAL} on ${HOST}\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\n# Stage 2: global check\nif [ $timeout -gt 0 ] && [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" != \"$ROLE_ANYWHERE\" ]; then\n    log \"Wait until ${NAME} is restarted anywhere in the cluster in state ${ROLE_ANYWHERE}\"\n    log \"Will probe resource state with the following XPath pattern: ${any_resource_xpath}\"\n\n    success=1\n    bailout=1\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resources=$(crm_mon -r --as-xml | xmllint --xpath \"${any_resource_xpath}\" - 2>/dev/null)\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif ! (echo \"${resources}\" | grep -q -w \"\\Wblocked=\\\"false\\\"\"); then\n            log \"${NAME} blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_globally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resources}\" | grep -q -w \"\\Wrole=\\\"${ROLE_ANYWHERE}\\\"\"; then\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_ANYWHERE} anywhere in the cluster\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\nif [ $timeout -le 0 ]; then\n    log \"Timeout reached after ${TIMEOUT}s while waiting for ${NAME} to be restarted\"\nelif [ $bailout -le 0 ]; then\n    log \"Restart monitoring for ${NAME} cancelled\"\nfi\n\nif [ $success -eq 0 ]; then\n    log \"${NAME} successfully restarted\"\nelse\n    log \"${NAME} was not restarted properly\"\nfi\n\n# Don't block minor update or stack update if the wait was unsuccessful\nexit 0\n"}, "wait-port-and-run.sh": {"mode": "0755", "content": "#!/usr/bin/bash\nset -eu\n\nHOST=$1\nPORT=$2\n\necho \"$(date -u): Checking whether we can bind to ${HOST}:${PORT}\"\nwhile (ss -Htnl src \"${HOST}\" \"sport = :${PORT}\" | grep -wq \"${PORT}\"); do\n    echo \"$(date -u): ${HOST}:${PORT} still in use, waiting...\";\n    sleep 10;\ndone\n\nshift 2\nCOMMAND=\"$*\"\nif [ -z \"${COMMAND}\" ]; then\n    COMMAND=\"true\"\nfi\nexec $COMMAND\n"}, "pacemaker_resource_lock.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nMAX_RETRIES=10\nCIB_ENOTFOUND=105\n\nusage() {\n   echo \"Set a global property in the cluster with a validity timestamp.\"\n   echo \"Usage:\"\n   echo \"   $0 --acquire <lock_name> <lock_owner> <lock_ttl_in_seconds>\"\n   echo \"   $0 --release <lock_name> <lock_owner>\"\n   echo\n}\n\nlog() {\n    echo \"$(date -u): $1\" 1>&2\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\nlock_create() {\n    local name=$1\n    local data=$2\n    # cibadmin won't overwrite a key if someone else succeeded to create it concurrently\n    cibadmin --sync-call --scope crm_config --create --xml-text \"<cluster_property_set id='${name}'><nvpair id='${name}-pair' name='${name}' value='${data}'/></cluster_property_set>\" &>/dev/null\n    return $?\n}\n\nlock_update() {\n    local name=$1\n    local expected_data=$2\n    local new_data=$3\n    # we only update the lock we expect to see, so we can't update someone else's lock\n    cibadmin --sync-call --scope crm_config --modify --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" --xml-text \"<nvpair id='${name}-pair' name='${name}' value='${new_data}'/>\" &>/dev/null\n    return $?\n}\n\nlock_delete() {\n    local name=$1\n    local expected_data=$2\n    # we only delete the lock we expect to see, so we can't delete someone else's lock\n    cibadmin --sync-call --scope crm_config --delete --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" &>/dev/null\n    return $?\n}\n\nlock_get() {\n    local lockname=$1\n    local res\n    local rc\n    res=$(cibadmin --query --scope crm_config --xpath \"//cluster_property_set/nvpair[@name='$lockname']\" 2>/dev/null)\n    rc=$?\n    if [ $rc -eq 0 ]; then\n        echo \"$res\" | sed -n 's/.*value=\"\\([^\"]*\\)\".*/\\1/p'\n    fi\n    return $rc\n}\n\nlock_owner() {\n    local lock=$1\n    echo \"$lock\" | cut -d':' -f1\n}\n\nlock_has_expired() {\n    local lock=$1\n    local expiry=$(echo \"$lock\" | cut -d':' -f2)\n    local now=$(date +%s)\n    test $now -ge $expiry\n}\n\n\n# Perform a lock action and restart if the CIB has been modified before\n# committing the lock action\ntry_action() {\n    local fun=$1\n    local lock=$2\n    local requester=$3\n    local args=${4:-}\n    local tries=$MAX_RETRIES\n    local rc=1\n    if [ \"$fun\" = \"lock_acquire\" ] || [ \"$fun\" = \"lock_release\" ]; then\n        log \"Try running $fun\"\n    else\n        return 2\n    fi\n    while [ $rc -ne 0 ]; do\n        $fun $lock $requester $args\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Operation $1 succeeded\"\n            return 0\n        elif [ $rc -eq 3 ]; then\n            # rc == 3 -> CIB changed before push\n            if [ $tries -eq 0 ]; then\n                log \"Failed to commit after $MAX_RETRIES retries. Bailing out.\"\n                return 2\n            else\n                log \"Failed to commit. Retrying operation.\"\n                tries=$(($tries - 1))\n            fi\n        elif [ $rc -eq 2 ]; then\n            # rc == 2 -> unrecoverable cib error (e.g. pacemaker down)\n            log \"Unexpected failure. Bailing out\"\n            return $rc\n        else\n            # rc == 1 -> lock error (not owner, lock doesn't exists)\n            return $rc\n        fi\n    done\n}\n\n# The lock mechanism uses cibadmin's atomic creation so cluster-wide\n# state coherency is guaranteed by pacemaker\nlock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc\n    local lock\n    local expiry\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -n \"$lock\" ]; then\n        lock_has_expired $lock\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Lock has expired, now available for being held\"\n        else\n            # lock is still held. check whether we're the owner\n            owner=$(lock_owner $lock)\n            if [ \"$owner\" = \"$requester\" ];then\n                log \"Requester already owns the lock, acquiring attempt will just reconfigure the TTL\"\n            else\n                log \"Lock is held by someone else ($owner)\"\n                return 1\n            fi\n        fi\n    else\n        log \"Lock is not held yet\"\n    fi\n\n    # prepare the lock info\n    expiry=$(($(date +%s) + $ttl))\n\n    if [ -n \"$lock\" ]; then\n        log \"Attempting to update the lock\"\n        lock_update $lockname \"$lock\" \"$requester:$expiry\"\n        rc=$?\n    else\n        log \"Attempting to acquire the lock\"\n        lock_create $lockname \"$requester:$expiry\"\n        rc=$?\n    fi\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' acquired by '$requester', valid until $(date -d @$expiry)\"\n        return 0\n    else\n        log \"CIB changed, lock cannot be acquired\"\n        return 3\n    fi\n}\n\n\n# The lock mechanism uses the CIB's num_updates tag to implement\n# a conditional store. Cluster-wide locking is guaranteed by pacemaker\nlock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n    local lock\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        log \"Lock doesn't exist. Nothing to release\"\n        return 0\n    else\n        log \"Lock exists, check whether we're the owner\"\n        owner=$(lock_owner $lock)\n        if [ \"$owner\" != \"$requester\" ];then\n            log \"Lock is held by someone else ($owner), will not unlock\"\n            return 1\n        fi\n    fi\n\n    lock_delete $lockname \"$lock\"\n    rc=$?\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' released by '$requester'\"\n        return 0\n    else\n        log \"CIB deletion error, lock cannot be released\"\n        return 3\n    fi\n}\n\n\n# Retrieve the owner of a lock from the CIB\n# this is a read-only operation, so no need to log debug info\nlock_get_owner() {\n    local lockname=$1\n    local rc\n    local lock\n    local owner\n\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        return 1\n    else\n        lock_owner $lock\n        return 0\n    fi\n}\n\n\nACTION=$1\nLOCKNAME=$2\nREQUESTER=$3\nTTL=${4:-60}\n\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nif [ $ACTION != \"--help\" ]; then\n    if [ -z \"$LOCKNAME\" ]; then\n        error \"You must specific a lock name\"\n    fi\n    if [ $ACTION != \"--owner\" ] && [ $ACTION != \"-o\" ]; then\n        if [ -z \"$REQUESTER\" ]; then\n            error \"You must specific a lock requester\"\n        fi\n    fi\nfi\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) try_action lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --release|-r) try_action lock_release $LOCKNAME $REQUESTER;;\n    --acquire-once|-A) lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --owner|-o) lock_get_owner $LOCKNAME;;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}, "pacemaker_mutex_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_restart_bundle.sh --lock mysql galera galera-bundle Master _\n# pacemaker_mutex_restart_bundle.sh --lock ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\n\nset -u\n\nusage() {\n    echo \"Restart a clustered resource in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --lock <tripleo-service> <pcmk-resource> <pcmk-bundle> <target-state-local> <target-state-cluster>\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\nACTION=$1\ncase $ACTION in\n    --help) usage; exit 0;;\n    --lock) ;;\n    *) error \"Unknown action '$ACTION'\";;\nesac\n\nTRIPLEO_SERVICE=$2\nLOCK_NAME=${TRIPLEO_SERVICE}-restart-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to restart resource $TRIPLEO_SERVICE\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\nRESOURCE_NAME=$3\nBUNDLE_NAME=$4\nWAIT_TARGET_LOCAL=$5\nWAIT_TARGET_ANYWHERE=${6:-_}\n\nif pacemaker_supports_promoted; then\n    WAIT_TARGET_LOCAL=$(echo \"$5\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    WAIT_TARGET_ANYWHERE=$(echo \"${6:-_}\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    promoted_role=\"Promoted\"\nelse\n    promoted_role=\"Master\"\nfi\n\n# The lock TTL should accomodate for the resource start/promote timeout\nif [ \"$RESOURCE_NAME\" != \"$BUNDLE_NAME\" ]; then\n    if [ \"$WAIT_TARGET_LOCAL\" = \"$promoted_role\" ] || [ \"$WAIT_TARGET_ANYWHERE\" = \"$promoted_role\" ]; then\n        rsc_op=\"promote\"\n    else\n        rsc_op=\"start\"\n    fi\n    # <op id=\"galera-promote-interval-0s\" interval=\"0s\" name=\"promote\" on-fail=\"block\" timeout=\"300s\"/>\n    PCMK_TTL=$(cibadmin -Q | xmllint -xpath \"string(//primitive[@id='${RESOURCE_NAME}']/operations/op[@name='${rsc_op}']/@timeout)\" - | sed 's/s$//')\n    LOCK_TTL=$((PCMK_TTL + 30))\nelse\n    # The podman RA's default start timeout\n    LOCK_TTL=90\nfi\n\nlog \"Acquire a ${LOCK_TTL}s restart lock for service $TRIPLEO_SERVICE before restarting it\"\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nrc=1\nwhile [ $rc -ne 0 ]; do\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire $LOCK_NAME $LOCK_OWNER $LOCK_TTL\n    rc=$?\n    if [ $rc != 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not acquire lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Could not acquire lock, retrying\"\n            sleep 10\n        fi\n    fi\ndone\n\nlog \"Restart the service $TRIPLEO_SERVICE locally\"\n# Reuse the local restart script in t-h-t (driven by env var TRIPLEO_MINOR_UPDATE)\nTRIPLEO_MINOR_UPDATE=true /var/lib/container-config-scripts/pacemaker_restart_bundle.sh $TRIPLEO_SERVICE $RESOURCE_NAME $BUNDLE_NAME $WAIT_TARGET_LOCAL $WAIT_TARGET_ANYWHERE\n\n# If we reached this point, always try to release the lock\nlog \"Release the restart lock for service $TRIPLEO_SERVICE\"\n/var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $LOCK_NAME $LOCK_OWNER\nrc=$?\nif [ $rc -ne 0 ] && [ $rc -ne 1 ]; then\n    error \"Could not release held lock (rc: $rc)\"\nfi\n"}, "pacemaker_mutex_shutdown.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_shutdown.sh --acquire\n# pacemaker_mutex_shutdown.sh --release\n\nset -u\n\nusage() {\n    echo \"Shutdown a cluster node in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --acquire # prevent other node from shutting down until we hold the lock\"\n    echo \"   $0 --release # release the lock, other node can compete for the shutdown lock\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nshutdown_lock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc=1\n    local current_owner\n    local owner_stopped\n    local owner_rc\n\n    log \"Acquiring the shutdown lock\"\n    while [ $rc -ne 0 ]; do\n        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire-once $lockname $requester $ttl\n        rc=$?\n        if [ $rc -ne 0 ]; then\n            if [ $rc -eq 2 ]; then\n                error \"Could not acquire the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n            else\n                # The lock is held by another node.\n                current_owner=$(/var/lib/container-config-scripts/pacemaker_resource_lock.sh --owner $lockname)\n                owner_rc=$?\n                if [ $owner_rc -eq 2 ]; then\n                    error \"Could not get the shutdown lock owner due to unrecoverable error (rc: $owner_rc), bailing out\"\n                fi\n                if [ $owner_rc -eq 0 ]; then\n                    # If the owner is marked as offline, that means it has shutdown and\n                    # we can clean the lock preemptively and try to acquire it.\n                    owner_stopped=$(crm_mon -1X | xmllint --xpath 'count(//nodes/node[@name=\"'${current_owner}'\" and @online=\"false\" and @unclean=\"false\"])' -)\n                    if [ \"${owner_stopped}\" = \"1\" ]; then\n                        log \"Shutdown lock held by stopped node '${current_owner}', lock can be released\"\n                        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $current_owner\n                        continue\n                    fi\n                fi\n                log \"Shutdown lock held by another node (rc: $rc), retrying\"\n                sleep 10\n            fi\n        fi\n    done\n    log \"Shutdown lock acquired\"\n    return 0\n}\n\n\n# Release the lock if we still own it. Not owning it anymore is not fatal\nshutdown_lock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n\n    log \"Releasing the shutdown lock\"\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $requester\n    rc=$?\n    if [ $rc -ne 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not release the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Shutdown lock no longer held, nothing to do\"\n        fi\n    else\n        log \"Shutdown lock released\"\n    fi\n    return 0\n}\n\n\nACTION=$1\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nLOCK_NAME=tripleo-shutdown-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to aquire the shutdown lock\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\n# We start with a very high TTL, that long enough to accomodate a cluster stop.\n# As soon as the node will get offline, the other competing node will be entitled\n# to steal the lock, so they should never wait that long in practice.\nLOCK_TTL=600\n\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) shutdown_lock_acquire ${LOCK_NAME} ${LOCK_OWNER} ${LOCK_TTL};;\n    --release|-r) shutdown_lock_release ${LOCK_NAME} ${LOCK_OWNER};;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}}, "docker_config": {"step_2": {"create_haproxy_wrapper": {"start_order": 1, "detach": false, "net": "host", "pid": "host", "user": "root", "command": ["/container_puppet_apply.sh", "4", "file", "include ::tripleo::profile::base::neutron::ovn_metadata_agent_wrappers"], "image": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/var/lib/container-config-scripts/container_puppet_apply.sh:/container_puppet_apply.sh:ro", "/etc/puppet:/tmp/puppet-etc:ro", "/usr/share/openstack-puppet/modules:/usr/share/openstack-puppet/modules:ro", "/run/openvswitch:/run/openvswitch:shared,z", "/var/lib/neutron:/var/lib/neutron:shared,z"]}}, "step_4": {"setup_ovs_manager": {"start_order": 0, "detach": false, "net": "host", "privileged": true, "user": "root", "command": ["/container_puppet_apply.sh", "4", "exec", "include tripleo::profile::base::neutron::ovn_metadata"], "image": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/var/lib/container-config-scripts/container_puppet_apply.sh:/container_puppet_apply.sh:ro", "/etc/puppet:/tmp/puppet-etc:ro", "/usr/share/openstack-puppet/modules:/usr/share/openstack-puppet/modules:ro", "/lib/modules:/lib/modules:ro", "/run/openvswitch:/run/openvswitch:shared,z"], "environment": {"TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}, "ovn_metadata_agent": {"start_order": 1, "image": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "net": "host", "pid": "host", "cgroupns": "host", "privileged": true, "restart": "always", "healthcheck": {"test": "/openstack/healthcheck"}, "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro", "/var/log/containers/neutron:/var/log/neutron:z", "/var/lib/kolla/config_files/ovn_metadata_agent.json:/var/lib/kolla/config_files/config.json:ro", "/var/lib/config-data/puppet-generated/neutron:/var/lib/kolla/config_files/src:ro", "/lib/modules:/lib/modules:ro", "/run/openvswitch:/run/openvswitch:shared,z", "/var/lib/neutron:/var/lib/neutron:shared,z", "/run/netns:/run/netns:shared", "/var/lib/neutron/kill_scripts:/etc/neutron/kill_scripts:shared,z", "/var/lib/neutron/ovn_metadata_haproxy_wrapper:/usr/local/bin/haproxy:ro", "/etc/pki/tls/certs/ovn_metadata.crt:/etc/pki/tls/certs/ovn_metadata.crt", "/etc/pki/tls/private/ovn_metadata.key:/etc/pki/tls/private/ovn_metadata.key"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}}}, "metadata_settings": [{"service": "ovn_metadata", "network": "internal_api", "type": "node"}], "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_metadata", "dns": "{{fqdn_internal_api}}", "principal": "ovn_metadata/{{fqdn_internal_api}}@{{idm_realm}}", "run_after": "systemctl restart tripleo_ovn_metadata_agent\n", "key_size": "2048", "ca": "ipa"}]}}]}], "host_prep_tasks": [{"name": "create persistent directories", "file": {"path": "{{ item.path }}", "state": "directory", "setype": "{{ item.setype }}", "mode": "{{ item.mode }}"}, "with_items": [{"path": "/var/log/containers/neutron", "setype": "container_file_t", "mode": "0750"}]}, {"name": "create /run/netns with temp namespace", "command": "ip netns add ns_temp", "register": "ipnetns_add_result", "failed_when": false}, {"name": "remove temp namespace", "command": "ip netns delete ns_temp", "failed_when": false, "when": ["ipnetns_add_result.rc is defined", "ipnetns_add_result.rc == 0"]}, {"name": "create /var/lib/neutron", "file": {"path": "/var/lib/neutron", "state": "directory", "setype": "container_file_t"}}, {"name": "set conditions", "set_fact": {"haproxy_wrapper_enabled": true, "debug_enabled": true, "docker_additional_sockets": ["/var/lib/openstack/docker.sock"]}}, {"name": "create kill_scripts directory within /var/lib/neutron", "file": {"state": "directory", "path": "/var/lib/neutron/kill_scripts"}}, {"name": "create haproxy kill script", "when": "haproxy_wrapper_enabled|bool", "copy": {"dest": "/var/lib/neutron/kill_scripts/haproxy-kill", "mode": 493, "content": "#!/bin/bash\n{% if debug_enabled|bool -%}\nset -x\n{% endif -%}\nadd_date() {\n  echo \"$(date) $@\"\n}\n\n# Set up script logging for debugging purpose.\n# It will be taken care of by logrotate since there is the .log\n# suffix.\nexec 3>&1 4>&2\ntrap 'exec 2>&4 1>&3' 0 1 2 3\nexec 1>>/var/log/neutron/kill-script.log 2>&1\n\nSIG=$1\nPID=$2\nNETNS=$(ip netns identify ${PID})\n\nif [ \"x${NETNS}\" == \"x\" ]; then\n  CLI=\"nsenter --all --preserve-credentials -t 1 podman\"\n  SIG=9\nelse\n  CLI=\"nsenter --net=/run/netns/${NETNS} --preserve-credentials -m -t 1 podman\"\nfi\n\nkill_container() {\n  add_date \"Killing container $1 ($2)\"\n  signal_container $1 $2 9\n}\n\nstop_container() {\n  add_date \"Stopping container $1 ($2)\"\n  $CLI stop $2\n}\n\nsignal_container() {\n  SIGNAL=$3\n  if [ -z \"$SIGNAL\" ]; then\n      SIGNAL=\"HUP\"\n  fi\n  add_date \"Sending signal '$SIGNAL' to $1 ($2)\"\n  $CLI kill --signal $SIGNAL $2\n}\n\ndelete_container() {\n  add_date \"Deleting container $1 ($2)\"\n  $CLI rm $2 || echo \"Deleting container $1 ($2) failed\"\n}\n\n\n{% raw -%}\nif [ -f /proc/$PID/cgroup ]; then\n  # Get container ID based on process cgroups\n  CT_ID=$(awk 'BEGIN {FS=\".scope|-\"} /\\/libpod-/ {if ($(NF-1)) print $(NF-1);exit}' /proc/$PID/cgroup)\n  CT_NAME=$($CLI inspect -f '{{.Name}}' $CT_ID)\n\n  case $SIG in\n    HUP)\n      signal_container $CT_NAME $CT_ID\n      ;;\n    9)\n      kill_container $CT_NAME $CT_ID\n      delete_container $CT_NAME $CT_ID\n      ;;\n    15)\n      stop_container $CT_NAME $CT_ID\n      delete_container $CT_NAME $CT_ID\n      ;;\n    *)\n      add_date \"Unknown action ${SIG} for ${CT_NAME} ${CT_ID}\"\n      exit 1\n      ;;\n  esac\n\nelse\n  add_date \"No such PID: ${PID}\"\n  exit 1\nfi\n{% endraw %}\n"}}], "upgrade_tasks": [], "external_update_tasks": [{"name": "Check if python3-openvswitch3.1 workaround is needed", "delegate_to": "{{ item }}", "become": true, "tags": ["ovn", "ovn_image"], "when": "step|int == 1", "shell": "if podman exec ovn_metadata_agent rpm -q python3-openvswitch3.1 > /dev/null ; then echo REQUIRED; else echo OK ; fi\n", "register": "metadata_python_ovs_3_1", "failed_when": false, "loop": "{{ groups['ovn_metadata'] | difference(groups['excluded_overcloud']) }}"}, {"name": "Update ovn_metadata_agents", "vars": {"hosts_to_update_metadata": "{{ metadata_python_ovs_3_1.results | selectattr('stdout', 'eq', 'REQUIRED') | map(attribute='item') | list }}"}, "tags": ["ovn", "ovn_image"], "when": ["step|int == 1", "hosts_to_update_metadata | length > 0"], "block": [{"name": "Force pull image in case image name doesn't change.", "become": true, "loop": "{{ hosts_to_update_metadata }}", "delegate_to": "{{ item }}", "async": 600, "poll": 0, "register": "ovn_metadata_image_update", "containers.podman.podman_image": {"name": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "validate_certs": false, "force": true}}, {"name": "Was the ovn_metadata_agent image pull successful.", "when": ["'results' in ovn_metadata_image_update"], "become": true, "delegate_to": "{{ async_result_item.item }}", "async_status": {"jid": "{{ async_result_item.ansible_job_id }}"}, "loop": "{{ovn_metadata_image_update.results }}", "loop_control": {"loop_var": "async_result_item"}, "register": "async_poll_results", "until": "async_poll_results.finished", "retries": 600, "delay": 1}, {"name": "Now rotate all ovn_metadata_agents", "tags": ["ovn_metadata_parallel"], "delegate_to": "{{ item }}", "become": true, "tripleo_container_manage": {"config_dir": "/var/lib/tripleo-config/container-startup-config/step_4", "config_id": ["ovn_metadata_agent"], "config_patterns": "*ovn_metadata_agent.json", "config_overrides": {".*ovn_metadata_agent": {"image": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "name": "ovn_metadata_agent"}}}, "loop": "{{ hosts_to_update_metadata }}", "async": 600, "poll": 0}]}, {"name": "Now rotate all ovn_metadata_agents", "vars": {"hosts_to_update_metadata": "{{ metadata_python_ovs_3_1.results | selectattr('stdout', 'eq', 'REQUIRED') | map(attribute='item') | list }}"}, "tags": ["never", "ovn_metadata_serial"], "when": ["step|int == 1", "hosts_to_update_metadata | length > 0"], "delegate_to": "{{ item }}", "become": true, "tripleo_container_manage": {"config_dir": "/var/lib/tripleo-config/container-startup-config/step_4", "config_id": ["ovn_metadata_agent"], "config_patterns": "*ovn_metadata_agent.json", "config_overrides": {".*ovn_metadata_agent": {"image": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "name": "ovn_metadata_agent"}}}, "loop": "{{ hosts_to_update_metadata }}", "loop_control": {"pause": 1}}]}, "tuple:('role_data', 'service_names')": null, "tuple:('role_data', 'config_settings')": {"neutron::notification_driver": ["noop"], "neutron::core_plugin": "ml2", "neutron::service_plugins": ["qos", "ovn-router", "trunk", "segments", "port_forwarding", "log"], "neutron::report_interval": 300, "neutron::logging::debug": true, "neutron::purge_config": false, "neutron::allow_overlapping_ips": true, "neutron::dhcp_agent_notification": true, "neutron::dns_domain": "ooo.test", "neutron::rabbit_heartbeat_timeout_threshold": 60, "neutron::host": "%{hiera('fqdn_canonical')}", "neutron::db::database_db_max_retries": -1, "neutron::db::database_max_retries": -1, "neutron::db::sync::db_sync_timeout": 900, "neutron::global_physnet_mtu": 1500, "neutron::db::sync::extra_params": "", "neutron::vlan_transparent": false, "neutron::rabbit_heartbeat_in_pthread": false, "tripleo::profile::base::neutron::ovn_metadata_agent_wrappers::enable_haproxy_wrapper": true, "tripleo::profile::base::neutron::ovn_metadata_agent_wrappers::haproxy_process_wrapper": "/var/lib/neutron/ovn_metadata_haproxy_wrapper", "tripleo::profile::base::neutron::ovn_metadata_agent_wrappers::haproxy_image": "registry.redhat.io/rhosp-rhel9/openstack-neutron-metadata-agent-ovn:17.1", "tripleo::profile::base::neutron::ovn_metadata_agent_wrappers::debug": true, "tripleo::profile::base::neutron::container_cli": "podman", "neutron::agents::ovn_metadata::shared_secret": "bxeW2RrqpEnHixt0KeySTY5OI", "neutron::agents::ovn_metadata::auth_password": "CC70wbFRk1QjXjqZLaKBjXfHn", "neutron::agents::ovn_metadata::auth_url": "https://overcloud.internalapi.ooo.test:5000", "neutron::agents::ovn_metadata::auth_tenant": "service", "neutron::agents::ovn_metadata::metadata_host": "overcloud.internalapi.ooo.test", "neutron::agents::ovn_metadata::ovsdb_connection_timeout": 180, "neutron::agents::ovn_metadata::ovsdb_probe_interval": 60000, "neutron::agents::ovn_metadata::hwol_qos_enabled": false, "ovn::northbound::port": 6641, "ovn::southbound::port": 6642, "neutron::agents::ovn_metadata::debug": true, "neutron::agents::ovn_metadata::metadata_protocol": "https", "neutron::agents::ovn_metadata::metadata_workers": "1", "tripleo::profile::base::neutron::ovn_metadata::ovn_nb_ca_cert": "/etc/ipa/ca.crt", "tripleo::profile::base::neutron::ovn_metadata::ovn_sb_ca_cert": "/etc/ipa/ca.crt", "tripleo::profile::base::neutron::ovn_metadata::protocol": "ssl", "tripleo::profile::base::neutron::ovn_metadata::ovn_nb_certificate": "/etc/pki/tls/certs/ovn_metadata.crt", "tripleo::profile::base::neutron::ovn_metadata::ovn_nb_private_key": "/etc/pki/tls/private/ovn_metadata.key", "tripleo::profile::base::neutron::ovn_metadata::ovn_sb_certificate": "/etc/pki/tls/certs/ovn_metadata.crt", "tripleo::profile::base::neutron::ovn_metadata::ovn_sb_private_key": "/etc/pki/tls/private/ovn_metadata.key"}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-44-drbqceomkufl/a45de98c-3911-4e55-b6a3-0b4ee7e41eda"}


created_at: 2026-06-13 07:33:11.801294
data:
  {"tuple:('role_data', 'step_config')": null, "tuple:('role_data', 'container_config_scripts')": null, "tuple:('role_data', 'docker_config')": null, "tuple:('role_data', 'service_name')": "openstack_clients", "role_data": {"service_name": "openstack_clients", "host_prep_tasks": [{"include_role": {"name": "tripleo_clients_install"}}]}, "tuple:('role_data', 'service_names')": null, "tuple:('role_data', 'config_settings')": null, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-45-xupugslikkx5/6ef66eba-72f8-4dc6-aa61-2a24bdc70ae6"}


created_at: 2026-06-13 07:33:14.168478
data:
  {"OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-46-ytoxqiaup3ux-ContainersCommon-yn673wmzk43l/84161b42-914c-476d-b9e0-7b6e04bd075c"}


created_at: 2026-06-13 07:33:14.175984
data:
  {"tuple:('role_data', 'step_config')": null, "tuple:('role_data', 'container_config_scripts')": null, "tuple:('role_data', 'docker_config')": null, "tuple:('role_data', 'service_name')": "oslo_messaging_notify", "role_data": {"service_name": "oslo_messaging_notify", "global_config_settings": {"oslo_messaging_notify_scheme": "rabbit", "oslo_messaging_notify_user_name": "guest", "oslo_messaging_notify_password": "CXYUjEO3wxDmzZtKlwuHEqtzC", "oslo_messaging_notify_use_ssl": "True", "oslo_messaging_notify_port": 5672}}, "tuple:('role_data', 'service_names')": null, "tuple:('role_data', 'config_settings')": null, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-46-ytoxqiaup3ux/a39af509-9ee3-4179-9182-bf37566d06da"}


created_at: 2026-06-13 07:33:15.526609
data:
  {"type": "json", "value": {"ContainerRabbitmqImage": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1", "ContainerRabbitmqConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1"}}


created_at: 2026-06-13 07:33:22.627041
data:
  {"container_config_scripts": {"container_puppet_apply.sh": {"mode": "0700", "content": "#!/bin/bash\nset -eux\nSTEP=$1\nTAGS=$2\nCONFIG=$3\nEXTRA_ARGS=${4:-''}\nif [ -d /tmp/puppet-etc ]; then\n  # ignore copy failures as these may be the same file depending on docker mounts\n  cp -a /tmp/puppet-etc/* /etc/puppet || true\nfi\necho \"{\\\"step\\\": ${STEP}}\" > /etc/puppet/hieradata/docker_puppet.json\n# $::deployment_type in puppet-tripleo\nexport FACTER_deployment_type=containers\nset +e\npuppet apply $EXTRA_ARGS \\\n    --verbose \\\n    --detailed-exitcodes \\\n    --summarize \\\n    --color=false \\\n    --modulepath /etc/puppet/modules:/opt/stack/puppet-modules:/usr/share/openstack-puppet/modules \\\n    --tags $TAGS \\\n    -e \"noop_resource('package'); ${CONFIG}\"\nrc=$?\nset -e\nset +ux\nif [ $rc -eq 2 -o $rc -eq 0 ]; then\n    exit 0\nfi\nexit $rc\n"}, "pyshim.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n# Copyright 2018 Red Hat Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n#\n# Usage: pyshim.sh <script and/or arguments>\n#\n# Unfortunately THT doesn't know which version of python might be in a\n# container so we need this script to be able to try python3 or python2\n# depending on availability.  Since this is a temporary shim until we've\n# fully cut over to python3, we check for the existence of python3 first\n# before falling back to python2. This will help in the transition from\n# python2 based containers to python3.\n\nshow_usage() {\n    echo \"Usage: pyshim.sh <script and/or arguments>\"\n}\n\nif [ $# -lt 1 ]\nthen\n    show_usage\n    exit 1\nfi\n\nset -x\nif command -v python3 >/dev/null; then\n    python3 \"$@\"\nelif command -v python2 >/dev/null; then\n    python2 \"$@\"\nelif command -v python >/dev/null; then\n    python \"$@\"\nelse\n    echo \"ERROR: python is not available!\"\n    exit 1\nfi\n"}, "pacemaker_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nset -u\n\n# ./pacemaker_restart_bundle.sh mysql galera galera-bundle Master _\n# ./pacemaker_restart_bundle.sh redis redis redis-bundle Slave Master\n# ./pacemaker_restart_bundle.sh ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\nRESTART_SCRIPTS_DIR=$(dirname $0)\nTRIPLEO_SERVICE=$1\nRESOURCE_NAME=$2\nBUNDLE_NAME=$3\nWAIT_TARGET_LOCAL=$4\nWAIT_TARGET_ANYWHERE=${5:-_}\nTRIPLEO_MINOR_UPDATE=\"${TRIPLEO_MINOR_UPDATE:-false}\"\nTRIPLEO_HA_WRAPPER_RESOURCE_EXISTS=\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS:-false}\"\n\nbundle_can_be_restarted() {\n    local bundle=$1\n    # As long as the resource bundle is managed by pacemaker and is\n    # not meant to stay stopped, no matter the state of any inner\n    # pcmk_remote or ocf resource, we should restart it to give it a\n    # chance to read the new config.\n    [ \"$(crm_resource --meta -r $1 -g is-managed 2>/dev/null)\" != \"false\" ] && \\\n    [ \"$(crm_resource --meta -r $1 -g target-role 2>/dev/null)\" != \"Stopped\" ]\n}\n\nlog() {\n    local msg=$1\n    logger -t pcmkrestart \"$1\"\n}\n\nHOSTNAME=$(/bin/hostname -s)\nif [ x\"${TRIPLEO_MINOR_UPDATE,,}\" != x\"true\" ]; then\n    if [ x\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS,,}\" = x\"false\" ]; then\n        # Do not restart during initial deployment, as the resource\n        # has just been created.\n        SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n        if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n            log \"Initial deployment, skipping the restart of ${BUNDLE_NAME}\"\n\tfi\n        exit 0\n    else\n        # During a stack update, this script is called in parallel on\n        # every node the resource runs on, after the service's configs\n        # have been updated on all nodes. So we need to run pcs only\n        # once (e.g. on the service's boostrap node).\n        if bundle_can_be_restarted ${BUNDLE_NAME}; then\n            SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n            if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n                replicas_running=$(crm_resource -Q -r $BUNDLE_NAME --locate 2>&1 | wc -l)\n                if [ \"$replicas_running\" != \"0\" ]; then\n                    log \"Restarting ${BUNDLE_NAME} globally. Stopping:\"\n                    /sbin/pcs resource disable --wait=600 $BUNDLE_NAME\n                    log \"Restarting ${BUNDLE_NAME} globally. Starting:\"\n                    /sbin/pcs resource enable --wait=600 $BUNDLE_NAME\n                else\n                    log \"${BUNDLE_NAME} is not running anywhere,\" \\\n                         \"cleaning up to restart it globally if necessary\"\n                    /sbin/pcs resource cleanup $BUNDLE_NAME\n                fi\n            else\n                log \"Skipping global restart of ${BUNDLE_NAME} on ${HOSTNAME} it will be restarted by node ${SERVICE_NODEID}\"\n            fi\n\n        else\n            log \"No global restart needed for ${BUNDLE_NAME}.\"\n        fi\n    fi\nelse\n    # During a minor update workflow however, a host gets fully\n    # updated before updating the next one. So unlike stack\n    # update, at the time this script is called, the service's\n    # configs aren't updated on all nodes yet. So only restart the\n    # resource locally, where it's guaranteed that the config is\n    # up to date.\n    HOST=$(facter hostname)\n\n    if bundle_can_be_restarted ${BUNDLE_NAME}; then\n\t# if the resource is running locally, restart it\n\tif crm_resource -r $BUNDLE_NAME --locate 2>&1 | grep -w -q \"${HOST}\"; then\n            log \"Restarting ${BUNDLE_NAME} locally on '${HOST}'\"\n            /sbin/pcs resource restart $BUNDLE_NAME \"${HOST}\"\n\n\telse\n\t    # At this point, if no resource is running locally, it's\n\t    # either because a) it has failed previously, or b) because\n\t    # it's an A/P resource running elsewhere.\n\t    # By cleaning up resource, we ensure that a) it will try to\n\t    # restart, or b) it won't do anything if the resource is\n\t    # already running elsewhere.\n            log \"${BUNDLE_NAME} is currently not running on '${HOST}',\" \\\n                 \"cleaning up its state to restart it if necessary\"\n            /sbin/pcs resource cleanup $BUNDLE_NAME node=\"${HOST}\"\n\tfi\n\n\t# Wait until the resource is in the expected target state\n\t$RESTART_SCRIPTS_DIR/pacemaker_wait_bundle.sh \\\n            $RESOURCE_NAME $BUNDLE_NAME \\\n            \"$WAIT_TARGET_LOCAL\" \"$WAIT_TARGET_ANYWHERE\" \\\n\t    \"${HOST}\" 600\n    else\n        log \"No restart needed for ${BUNDLE_NAME}.\"\n    fi\nfi\n"}, "pacemaker_wait_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# ----\n# Wait for an OCF resource or a bundle to be restarted\n# ----\n# e.g.:\n# M/S OCF:      $0 galera galera-bundle Master\n# clone OCF:    $0 rabbitmq rabbitmq-bundle Started\n# A/P M/S OCF:  $0 redis redis-bundle Slave Master\n# A/P bundle:   $0 openstack-cinder-volume openstack-cinder-volume _ Started\n# clone bundle: $0 haproxy-bundle haproxy-bundle Started\n\n# design note 1:\n#  - this script is called during a minor update; it is called\n#    once per node that hosts a service replica.\n#  - the purpose of this script is to ensure that restarting the\n#    service replica locally won't disrupt the service availability\n#    for the end user. To reach that goal, the script waits until the\n#    service is restarted locally or globallu and reaches a given\n#    target state (i.e. Started, Slave or Master).\n# design note 2:\n#   - we don't want to track restart error: our only job is to ensure\n#     service restart synchronization, not service health.\n#   - In particular, we don't want to error out in case the resource\n#     cannot be restarted locally, because that would make the minor\n#     update fail, even if potentially other replicas still provide\n#     the service.\n# design note 3:\n#   - we can bail out early if we determine that the resource can't\n#     be restarted automatically by pacemaker (e.g. its \"blocked\",\n#     unmanaged or disabled).\n\nlog() {\n    local msg=$1\n    echo \"$(date -u): $1\"\n}\n\nusage() {\n    echo 2>&1 \"Usage: $0 NAME BUNDLE_NAME ROLE_LOCAL [ROLE_ANYWHERE] [HOST] [TIMEOUT]\"\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\n#\n# Utility functions to detect stuck resources\n#\n\nbundle_failures_locally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local replica_name\n    for i in $(seq 0 $last); do\n\treplica_name=${BUNDLE_NAME}-${engine}-${i}\n\tcrm_failcount -q -G -r $replica_name -N $HOST\n    done\n}\n\nbundle_failures_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    for i in $(seq 0 $last); do\n\tcrm_failcount -q -G -r ${BUNDLE_NAME}-${engine}-${i}\n    done\n}\n\nbundle_running_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    # return the number of running bundles replica, i.e. the number of\n    # docker/podman resource replicas currently running in the cluster\n    crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:heartbeat:${engine}']/node)\" -\n}\n\nocf_failures_globally() {\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local bundle_node\n    for i in $(seq 0 $last); do\n\tbundle_node=${BUNDLE_NAME}-${i}\n\tcrm_failcount -q -G -r $NAME -N $bundle_node\n    done\n}\n\ndid_resource_failed_locally() {\n    local failures\n    local running\n    local remotehost\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# if we're dealing with an ocf resource, it is running on a\n\t# pacemaker_remote rather that on the real host, and the\n\t# failcounts are thus associated to the pcmk remote. Replace\n\t# the host's name with the pcmk remote's name.\n        remotehost=$(crm_mon --as-xml | xmllint --xpath \"string(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource/node[@name='${HOST}']/../../resource[@resource_agent='${OCF}:pacemaker:remote']/@id)\" -)\n\tif [ -n \"${remotehost}\" ]; then\n\t    crm_failcount -q -G -r $NAME -N $remotehost | grep -q -w INFINITY\n\t    return $?\n\tfi\n\t# If no pcmk remote is currently running, the failcount from\n\t# the ocf resource is useless, compute the failcount from the\n\t# bundle case instead (computed below).\n    fi\n\n    # for bundles, pacemaker can run any bundle replica locally\n    # (e.g. galera-bundle-docker-{0,1,2}), and a failure happens when\n    # there are no more replica to try.\n    # That is, when _at least_ one replica failed locally, and all the\n    # others either failed or are currently running elsewhere.\n    failures=$(bundle_failures_locally $HOST | grep -c -w INFINITY)\n    running=$(bundle_running_globally)\n    test $failures -gt 0 && \\\n    test $(( $failures + $running )) -ge $BUNDLE_REPLICAS\n}\n\ndid_resource_failed_globally() {\n    local remotecount\n    local failures\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# we check the state of an ocf resource only if the\n\t# pcmkremotes are started\n        remotecount=$(crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node)\" -)\n\tif [ \"${remotecount}\" = \"0\" ]; then\n\t    # no pcmkremote is running, so check the bundle state\n\t    # instead of checking the ocf resource\n\t    # bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\t    failures=$(bundle_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\telse\n\t    # ocf resource failed if it failed to start on\n\t    # all $BUNDLE_REPLICAS bundle nodes\n\t    failures=$(ocf_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\tfi\n    else\n\t# bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\tfailures=$(bundle_failures_globally | grep -c -w INFINITY)\n\ttest $failures -eq $BUNDLE_REPLICAS\n    fi\n}\n\n\n# Input validation\n#\n\nNAME=$1\nif [ -z \"${NAME}\" ]; then\n    echo 2>&1 \"Error: argument NAME must not be empty\"\n    exit 1\nfi\n\nBUNDLE_NAME=$2\nif [ -z \"${BUNDLE_NAME}\" ]; then\n    echo 2>&1 \"Error: argument BUNDLE_NAME must not be empty\"\n    exit 1\nfi\n\nROLE_LOCAL=$3\nif [ \"${ROLE_LOCAL}\" = \"_\" ]; then\n    ROLE_LOCAL=\"\"\nfi\n\nROLE_ANYWHERE=$4\nif [ \"${ROLE_ANYWHERE}\" = \"_\" ]; then\n    ROLE_ANYWHERE=\"\"\nfi\n\nif [ -z \"${ROLE_LOCAL}\" ]; then\n    if [ -z \"${ROLE_ANYWHERE}\" ]; then\n        echo 2>&1 \"Error: either ROLE_LOCAL or ROLE_ANYWHERE must be non empty\"\n        exit 1\n    fi\nelse\n    if !(echo \"${ROLE_LOCAL}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n        echo 2>&1 \"Error: argument ROLE_LOCAL must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n        exit 1\n    fi\nfi\n\nif [ -n \"${ROLE_ANYWHERE}\" ] && !(echo \"${ROLE_ANYWHERE}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n    echo 2>&1 \"Error: argument ROLE_ANYWHERE must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n    exit 1\nfi\n\n# Ensure compatibility with pacemaker 2.1\nif pacemaker_supports_promoted; then\n    ROLE_LOCAL=$(echo \"$ROLE_LOCAL\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    ROLE_ANYWHERE=$(echo \"$ROLE_ANYWHERE\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    OCF=\"ocf\"\nelse\n    OCF=\"ocf:\"\nfi\n\nHOST=${5:-$(facter hostname)}\nTIMEOUT=${6:-600}\n\n\n# Configure the search\n# ----\n# Note: we can't use crm_resource in all searches because we can't\n# easily extract the host the OCF resources run on (crm_resource\n# returns the pcmk-remote nodes rather than the hosts)\n# So instead, we implement various searches with XPath directly.\n\nif [ \"${BUNDLE_NAME}\" != \"${NAME}\" ]; then\n# ocf resource\nlocal_resource_xpath=\"//bundle/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node[@name='${HOST}']/../../resource[@id='${NAME}']\"\nany_resource_xpath=\"//bundle//resource[@id='${NAME}']\"\nreplicas_xpath=\"//bundle/primitive[@id='${BUNDLE_NAME}']/../*[boolean(@image) and boolean(@replicas)]\"\nelse\n# bundle resource\nlocal_resource_xpath=\"//bundle[@id='${NAME}']/replica/resource/node[@name='${HOST}']/../../resource\"\nany_resource_xpath=\"//bundle[@id='${NAME}']//resource\"\nreplicas_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nfi\n\nbundle_def_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nBUNDLE_CONTAINER_ENGINE=$(cibadmin -Q | xmllint --xpath \"name(${bundle_def_xpath})\" -)\nBUNDLE_REPLICAS=$(cibadmin -Q | xmllint --xpath \"string(${bundle_def_xpath}/@replicas)\" -)\n\n\n# The wait algorithm follows a two-stage approach\n#  1. Depending on how the script is called, we first check whether\n#     the resource is restarted locally. An A/P resource may be\n#     restarted elsewhere in the cluster.\n#  2. If needed, check whether the A/P resource has restarted\n#     elsewhere. For A/P M/S resources, in case the resource is\n#     restarted as Slave locally, ensure a Master is available.\n\nsuccess=1\nbailout=1\ntimeout=$TIMEOUT\nrole=\"\"\n\n# Stage 1: local check\nif [ -n \"$ROLE_LOCAL\" ]; then\n    log \"Waiting until ${NAME} has restarted on ${HOST} and is in state ${ROLE_LOCAL}\"\n    log \"Will probe resource state with the following XPath pattern: ${local_resource_xpath}\"\n\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resource=$(crm_mon -r --as-xml | xmllint --xpath \"${local_resource_xpath}\" - 2>/dev/null)\n        role=$(echo \"${resource}\" | sed -ne 's/.*\\Wrole=\"\\([^\"]*\\)\".*/\\1/p')\n\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resource}\" | grep -q -w \"\\Wblocked=\\\"true\\\"\"; then\n            log \"${NAME} is blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_locally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif [ \"$role\" = \"$ROLE_LOCAL\" ]; then\n            success=0\n            continue\n        elif [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" = \"$ROLE_ANYWHERE\" ]; then\n            # A/P: we are restarted in the expected state\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_LOCAL} on ${HOST}\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\n# Stage 2: global check\nif [ $timeout -gt 0 ] && [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" != \"$ROLE_ANYWHERE\" ]; then\n    log \"Wait until ${NAME} is restarted anywhere in the cluster in state ${ROLE_ANYWHERE}\"\n    log \"Will probe resource state with the following XPath pattern: ${any_resource_xpath}\"\n\n    success=1\n    bailout=1\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resources=$(crm_mon -r --as-xml | xmllint --xpath \"${any_resource_xpath}\" - 2>/dev/null)\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif ! (echo \"${resources}\" | grep -q -w \"\\Wblocked=\\\"false\\\"\"); then\n            log \"${NAME} blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_globally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resources}\" | grep -q -w \"\\Wrole=\\\"${ROLE_ANYWHERE}\\\"\"; then\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_ANYWHERE} anywhere in the cluster\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\nif [ $timeout -le 0 ]; then\n    log \"Timeout reached after ${TIMEOUT}s while waiting for ${NAME} to be restarted\"\nelif [ $bailout -le 0 ]; then\n    log \"Restart monitoring for ${NAME} cancelled\"\nfi\n\nif [ $success -eq 0 ]; then\n    log \"${NAME} successfully restarted\"\nelse\n    log \"${NAME} was not restarted properly\"\nfi\n\n# Don't block minor update or stack update if the wait was unsuccessful\nexit 0\n"}, "wait-port-and-run.sh": {"mode": "0755", "content": "#!/usr/bin/bash\nset -eu\n\nHOST=$1\nPORT=$2\n\necho \"$(date -u): Checking whether we can bind to ${HOST}:${PORT}\"\nwhile (ss -Htnl src \"${HOST}\" \"sport = :${PORT}\" | grep -wq \"${PORT}\"); do\n    echo \"$(date -u): ${HOST}:${PORT} still in use, waiting...\";\n    sleep 10;\ndone\n\nshift 2\nCOMMAND=\"$*\"\nif [ -z \"${COMMAND}\" ]; then\n    COMMAND=\"true\"\nfi\nexec $COMMAND\n"}, "pacemaker_resource_lock.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nMAX_RETRIES=10\nCIB_ENOTFOUND=105\n\nusage() {\n   echo \"Set a global property in the cluster with a validity timestamp.\"\n   echo \"Usage:\"\n   echo \"   $0 --acquire <lock_name> <lock_owner> <lock_ttl_in_seconds>\"\n   echo \"   $0 --release <lock_name> <lock_owner>\"\n   echo\n}\n\nlog() {\n    echo \"$(date -u): $1\" 1>&2\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\nlock_create() {\n    local name=$1\n    local data=$2\n    # cibadmin won't overwrite a key if someone else succeeded to create it concurrently\n    cibadmin --sync-call --scope crm_config --create --xml-text \"<cluster_property_set id='${name}'><nvpair id='${name}-pair' name='${name}' value='${data}'/></cluster_property_set>\" &>/dev/null\n    return $?\n}\n\nlock_update() {\n    local name=$1\n    local expected_data=$2\n    local new_data=$3\n    # we only update the lock we expect to see, so we can't update someone else's lock\n    cibadmin --sync-call --scope crm_config --modify --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" --xml-text \"<nvpair id='${name}-pair' name='${name}' value='${new_data}'/>\" &>/dev/null\n    return $?\n}\n\nlock_delete() {\n    local name=$1\n    local expected_data=$2\n    # we only delete the lock we expect to see, so we can't delete someone else's lock\n    cibadmin --sync-call --scope crm_config --delete --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" &>/dev/null\n    return $?\n}\n\nlock_get() {\n    local lockname=$1\n    local res\n    local rc\n    res=$(cibadmin --query --scope crm_config --xpath \"//cluster_property_set/nvpair[@name='$lockname']\" 2>/dev/null)\n    rc=$?\n    if [ $rc -eq 0 ]; then\n        echo \"$res\" | sed -n 's/.*value=\"\\([^\"]*\\)\".*/\\1/p'\n    fi\n    return $rc\n}\n\nlock_owner() {\n    local lock=$1\n    echo \"$lock\" | cut -d':' -f1\n}\n\nlock_has_expired() {\n    local lock=$1\n    local expiry=$(echo \"$lock\" | cut -d':' -f2)\n    local now=$(date +%s)\n    test $now -ge $expiry\n}\n\n\n# Perform a lock action and restart if the CIB has been modified before\n# committing the lock action\ntry_action() {\n    local fun=$1\n    local lock=$2\n    local requester=$3\n    local args=${4:-}\n    local tries=$MAX_RETRIES\n    local rc=1\n    if [ \"$fun\" = \"lock_acquire\" ] || [ \"$fun\" = \"lock_release\" ]; then\n        log \"Try running $fun\"\n    else\n        return 2\n    fi\n    while [ $rc -ne 0 ]; do\n        $fun $lock $requester $args\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Operation $1 succeeded\"\n            return 0\n        elif [ $rc -eq 3 ]; then\n            # rc == 3 -> CIB changed before push\n            if [ $tries -eq 0 ]; then\n                log \"Failed to commit after $MAX_RETRIES retries. Bailing out.\"\n                return 2\n            else\n                log \"Failed to commit. Retrying operation.\"\n                tries=$(($tries - 1))\n            fi\n        elif [ $rc -eq 2 ]; then\n            # rc == 2 -> unrecoverable cib error (e.g. pacemaker down)\n            log \"Unexpected failure. Bailing out\"\n            return $rc\n        else\n            # rc == 1 -> lock error (not owner, lock doesn't exists)\n            return $rc\n        fi\n    done\n}\n\n# The lock mechanism uses cibadmin's atomic creation so cluster-wide\n# state coherency is guaranteed by pacemaker\nlock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc\n    local lock\n    local expiry\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -n \"$lock\" ]; then\n        lock_has_expired $lock\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Lock has expired, now available for being held\"\n        else\n            # lock is still held. check whether we're the owner\n            owner=$(lock_owner $lock)\n            if [ \"$owner\" = \"$requester\" ];then\n                log \"Requester already owns the lock, acquiring attempt will just reconfigure the TTL\"\n            else\n                log \"Lock is held by someone else ($owner)\"\n                return 1\n            fi\n        fi\n    else\n        log \"Lock is not held yet\"\n    fi\n\n    # prepare the lock info\n    expiry=$(($(date +%s) + $ttl))\n\n    if [ -n \"$lock\" ]; then\n        log \"Attempting to update the lock\"\n        lock_update $lockname \"$lock\" \"$requester:$expiry\"\n        rc=$?\n    else\n        log \"Attempting to acquire the lock\"\n        lock_create $lockname \"$requester:$expiry\"\n        rc=$?\n    fi\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' acquired by '$requester', valid until $(date -d @$expiry)\"\n        return 0\n    else\n        log \"CIB changed, lock cannot be acquired\"\n        return 3\n    fi\n}\n\n\n# The lock mechanism uses the CIB's num_updates tag to implement\n# a conditional store. Cluster-wide locking is guaranteed by pacemaker\nlock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n    local lock\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        log \"Lock doesn't exist. Nothing to release\"\n        return 0\n    else\n        log \"Lock exists, check whether we're the owner\"\n        owner=$(lock_owner $lock)\n        if [ \"$owner\" != \"$requester\" ];then\n            log \"Lock is held by someone else ($owner), will not unlock\"\n            return 1\n        fi\n    fi\n\n    lock_delete $lockname \"$lock\"\n    rc=$?\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' released by '$requester'\"\n        return 0\n    else\n        log \"CIB deletion error, lock cannot be released\"\n        return 3\n    fi\n}\n\n\n# Retrieve the owner of a lock from the CIB\n# this is a read-only operation, so no need to log debug info\nlock_get_owner() {\n    local lockname=$1\n    local rc\n    local lock\n    local owner\n\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        return 1\n    else\n        lock_owner $lock\n        return 0\n    fi\n}\n\n\nACTION=$1\nLOCKNAME=$2\nREQUESTER=$3\nTTL=${4:-60}\n\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nif [ $ACTION != \"--help\" ]; then\n    if [ -z \"$LOCKNAME\" ]; then\n        error \"You must specific a lock name\"\n    fi\n    if [ $ACTION != \"--owner\" ] && [ $ACTION != \"-o\" ]; then\n        if [ -z \"$REQUESTER\" ]; then\n            error \"You must specific a lock requester\"\n        fi\n    fi\nfi\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) try_action lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --release|-r) try_action lock_release $LOCKNAME $REQUESTER;;\n    --acquire-once|-A) lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --owner|-o) lock_get_owner $LOCKNAME;;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}, "pacemaker_mutex_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_restart_bundle.sh --lock mysql galera galera-bundle Master _\n# pacemaker_mutex_restart_bundle.sh --lock ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\n\nset -u\n\nusage() {\n    echo \"Restart a clustered resource in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --lock <tripleo-service> <pcmk-resource> <pcmk-bundle> <target-state-local> <target-state-cluster>\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\nACTION=$1\ncase $ACTION in\n    --help) usage; exit 0;;\n    --lock) ;;\n    *) error \"Unknown action '$ACTION'\";;\nesac\n\nTRIPLEO_SERVICE=$2\nLOCK_NAME=${TRIPLEO_SERVICE}-restart-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to restart resource $TRIPLEO_SERVICE\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\nRESOURCE_NAME=$3\nBUNDLE_NAME=$4\nWAIT_TARGET_LOCAL=$5\nWAIT_TARGET_ANYWHERE=${6:-_}\n\nif pacemaker_supports_promoted; then\n    WAIT_TARGET_LOCAL=$(echo \"$5\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    WAIT_TARGET_ANYWHERE=$(echo \"${6:-_}\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    promoted_role=\"Promoted\"\nelse\n    promoted_role=\"Master\"\nfi\n\n# The lock TTL should accomodate for the resource start/promote timeout\nif [ \"$RESOURCE_NAME\" != \"$BUNDLE_NAME\" ]; then\n    if [ \"$WAIT_TARGET_LOCAL\" = \"$promoted_role\" ] || [ \"$WAIT_TARGET_ANYWHERE\" = \"$promoted_role\" ]; then\n        rsc_op=\"promote\"\n    else\n        rsc_op=\"start\"\n    fi\n    # <op id=\"galera-promote-interval-0s\" interval=\"0s\" name=\"promote\" on-fail=\"block\" timeout=\"300s\"/>\n    PCMK_TTL=$(cibadmin -Q | xmllint -xpath \"string(//primitive[@id='${RESOURCE_NAME}']/operations/op[@name='${rsc_op}']/@timeout)\" - | sed 's/s$//')\n    LOCK_TTL=$((PCMK_TTL + 30))\nelse\n    # The podman RA's default start timeout\n    LOCK_TTL=90\nfi\n\nlog \"Acquire a ${LOCK_TTL}s restart lock for service $TRIPLEO_SERVICE before restarting it\"\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nrc=1\nwhile [ $rc -ne 0 ]; do\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire $LOCK_NAME $LOCK_OWNER $LOCK_TTL\n    rc=$?\n    if [ $rc != 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not acquire lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Could not acquire lock, retrying\"\n            sleep 10\n        fi\n    fi\ndone\n\nlog \"Restart the service $TRIPLEO_SERVICE locally\"\n# Reuse the local restart script in t-h-t (driven by env var TRIPLEO_MINOR_UPDATE)\nTRIPLEO_MINOR_UPDATE=true /var/lib/container-config-scripts/pacemaker_restart_bundle.sh $TRIPLEO_SERVICE $RESOURCE_NAME $BUNDLE_NAME $WAIT_TARGET_LOCAL $WAIT_TARGET_ANYWHERE\n\n# If we reached this point, always try to release the lock\nlog \"Release the restart lock for service $TRIPLEO_SERVICE\"\n/var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $LOCK_NAME $LOCK_OWNER\nrc=$?\nif [ $rc -ne 0 ] && [ $rc -ne 1 ]; then\n    error \"Could not release held lock (rc: $rc)\"\nfi\n"}, "pacemaker_mutex_shutdown.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_shutdown.sh --acquire\n# pacemaker_mutex_shutdown.sh --release\n\nset -u\n\nusage() {\n    echo \"Shutdown a cluster node in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --acquire # prevent other node from shutting down until we hold the lock\"\n    echo \"   $0 --release # release the lock, other node can compete for the shutdown lock\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nshutdown_lock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc=1\n    local current_owner\n    local owner_stopped\n    local owner_rc\n\n    log \"Acquiring the shutdown lock\"\n    while [ $rc -ne 0 ]; do\n        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire-once $lockname $requester $ttl\n        rc=$?\n        if [ $rc -ne 0 ]; then\n            if [ $rc -eq 2 ]; then\n                error \"Could not acquire the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n            else\n                # The lock is held by another node.\n                current_owner=$(/var/lib/container-config-scripts/pacemaker_resource_lock.sh --owner $lockname)\n                owner_rc=$?\n                if [ $owner_rc -eq 2 ]; then\n                    error \"Could not get the shutdown lock owner due to unrecoverable error (rc: $owner_rc), bailing out\"\n                fi\n                if [ $owner_rc -eq 0 ]; then\n                    # If the owner is marked as offline, that means it has shutdown and\n                    # we can clean the lock preemptively and try to acquire it.\n                    owner_stopped=$(crm_mon -1X | xmllint --xpath 'count(//nodes/node[@name=\"'${current_owner}'\" and @online=\"false\" and @unclean=\"false\"])' -)\n                    if [ \"${owner_stopped}\" = \"1\" ]; then\n                        log \"Shutdown lock held by stopped node '${current_owner}', lock can be released\"\n                        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $current_owner\n                        continue\n                    fi\n                fi\n                log \"Shutdown lock held by another node (rc: $rc), retrying\"\n                sleep 10\n            fi\n        fi\n    done\n    log \"Shutdown lock acquired\"\n    return 0\n}\n\n\n# Release the lock if we still own it. Not owning it anymore is not fatal\nshutdown_lock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n\n    log \"Releasing the shutdown lock\"\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $requester\n    rc=$?\n    if [ $rc -ne 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not release the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Shutdown lock no longer held, nothing to do\"\n        fi\n    else\n        log \"Shutdown lock released\"\n    fi\n    return 0\n}\n\n\nACTION=$1\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nLOCK_NAME=tripleo-shutdown-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to aquire the shutdown lock\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\n# We start with a very high TTL, that long enough to accomodate a cluster stop.\n# As soon as the node will get offline, the other competing node will be entitled\n# to steal the lock, so they should never wait that long in practice.\nLOCK_TTL=600\n\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) shutdown_lock_acquire ${LOCK_NAME} ${LOCK_OWNER} ${LOCK_TTL};;\n    --release|-r) shutdown_lock_release ${LOCK_NAME} ${LOCK_OWNER};;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}}, "container_puppet_apply_volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/var/lib/container-config-scripts/container_puppet_apply.sh:/container_puppet_apply.sh:ro", "/etc/puppet:/tmp/puppet-etc:ro", "/usr/share/openstack-puppet/modules:/usr/share/openstack-puppet/modules:ro"], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-47-ladweh3urreb-ContainersCommon-ooudbxejpy2k/f9ff400a-5eb3-4e60-9460-48d0f39e998b"}


created_at: 2026-06-13 07:33:22.632627
data:
  {"value": {"ContainerRabbitmqImage": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1", "ContainerRabbitmqConfigImage": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1"}}


created_at: 2026-06-13 07:33:22.742430
data:
  {"volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro"], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-47-ladweh3urreb-RabbitmqBase-dz4qqscmtqjp-ContainersCommon-nfjbc36nk7pi/642513f4-8322-4078-ae8c-1a12744eda67"}


created_at: 2026-06-13 07:33:22.841846
data:
  {"volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/etc/puppet:/etc/puppet:ro"], "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-47-ladweh3urreb-RabbitmqBase-dz4qqscmtqjp-RabbitMQServiceBase-li7ecmtghoxb-ContainersCommon-sls43efyxbqh/2b435487-e24e-4749-b1fd-3feebce86c58"}


created_at: 2026-06-13 07:33:22.858378
data:
  {"tuple:('role_data', 'global_config_settings')": null, "tuple:('role_data', 'config_settings')": {"rabbitmq::file_limit": 65536, "rabbitmq::default_user": "guest", "rabbitmq::default_pass": "bWJCeSdG34AGR7rjtNWyoHK3w", "rabbit_ipv6": false, "rabbitmq::delete_guest_user": false, "rabbitmq::wipe_db_on_cookie_change": true, "rabbitmq::port": 5672, "rabbitmq::loopback_users": [], "rabbitmq::tcp_backlog": 4096, "rabbitmq::repos_ensure": false, "rabbitmq::tcp_keepalive": true, "rabbitmq_environment": {"LANG": "en_US.UTF-8", "LC_ALL": "en_US.UTF-8", "NODE_PORT": "", "NODE_IP_ADDRESS": "", "RABBITMQ_NODENAME": "rabbit@%{hiera('fqdn_internal_api')}", "RABBITMQ_USE_LONGNAME": "true", "RABBITMQ_CTL_DIST_PORT_MIN": "25673", "RABBITMQ_CTL_DIST_PORT_MAX": "25683", "export ERL_EPMD_ADDRESS": "%{hiera('rabbitmq::interface')}"}, "tripleo::profile::base::rabbitmq::additional_erl_args": "'+sbwt none +sbwtdcpu none +sbwtdio none'", "rabbitmq_kernel_variables": {"inet_dist_listen_min": "25672", "inet_dist_listen_max": "25672", "net_ticktime": 15}, "rabbitmq_config_variables": {"cluster_partition_handling": "ignore", "queue_master_locator": "<<\"min-masters\">>"}, "rabbitmq::config_additional_variables": {"lager": "[{crash_log_count, 0}, { crash_log_date, \"\"}, { crash_log_size, 0 }]"}, "rabbitmq::erlang_cookie": "mpHJWwKkkBAv6EusO06i", "rabbitmq::interface": "%{hiera('internal_api')}", "rabbitmq::nr_ha_queues": 0, "rabbitmq::ssl": true, "rabbitmq::ssl_erl_dist": true, "rabbitmq::ssl_port": 5672, "rabbitmq::ssl_depth": 1, "rabbitmq::ssl_only": true, "rabbitmq::ssl_interface": "%{hiera('internal_api')}", "tripleo::profile::base::rabbitmq::enable_internal_tls": true, "tripleo::profile::base::rabbitmq::fips_mode": false, "rabbitmq::collect_statistics_interval": 30000, "tripleo::rabbitmq::service_certificate": "/etc/pki/tls/certs/rabbitmq.crt", "tripleo::profile::base::rabbitmq::certificate_specs": {"service_certificate": "/etc/pki/tls/certs/rabbitmq.crt", "service_key": "/etc/pki/tls/private/rabbitmq.key"}, "rabbitmq::ssl_versions": ["tlsv1.2"], "rabbitmq::admin_enable": false, "rabbitmq::management_enable": true, "rabbitmq::use_config_file_for_plugins": true, "rabbitmq::management_ip_address": "127.0.0.1", "rabbitmq::management_port": 15672, "rabbitmq::config_management_variables": {"rates_mode": "none"}, "rabbitmq::ssl_cacert": "/etc/ipa/ca.crt", "rabbitmq::ssl_management_cacert": "/etc/ipa/ca.crt", "tripleo::certmonger::rabbitmq::postsave_cmd": "true"}, "tuple:('role_data', 'monitoring_subscription')": "overcloud-rabbitmq", "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-47-ladweh3urreb-RabbitmqBase-dz4qqscmtqjp-RabbitMQServiceBase-li7ecmtghoxb/a4fe7caf-3648-4d17-b138-96754c3538bd"}


created_at: 2026-06-13 07:33:22.868162
data:
  {"tuple:('role_data', '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": "rabbitmq", "dns": "{{fqdn_internal_api}}", "principal": "rabbitmq/{{fqdn_internal_api}}@{{idm_realm}}", "run_after": "container_name=$({{container_cli}} ps --format=\\{\\{.Names\\}\\} | grep -w -E 'rabbitmq(-bundle-.*-[0-9]+)?')\nservice_crt=\"/etc/pki/tls/certs/rabbitmq.crt\"\nservice_key=\"/etc/pki/tls/private/rabbitmq.key\"\nif echo \"$container_name\" | grep -q \"^rabbitmq-bundle\"; then\n  # lp#1917868: Do not use podman cp with HA containers as they get\n  # frozen temporarily and that can make pacemaker operation fail.\n  tar -c \"$service_crt\" \"$service_key\" | {{container_cli}} exec -i \"$container_name\" tar -C / -xv\n  # no need to update the mount point, because pacemaker\n  # recreates the container when it's restarted\nelse\n  # Refresh the cert at the mount-point\n  {{container_cli}} cp $service_crt \"$container_name:/var/lib/kolla/config_files/src-tls/$service_crt\"\n  # Refresh the key at the mount-point\n  {{container_cli}} cp $service_key \"$container_name:/var/lib/kolla/config_files/src-tls/$service_key\"\n  # Copy the new cert from the mount-point to the real path\n  {{container_cli}} exec -u root \"$container_name\" cp \"/var/lib/kolla/config_files/src-tls$service_crt\" \"$service_crt\"\n  # Copy the new key from the mount-point to the real path\n  {{container_cli}} exec -u root \"$container_name\" cp \"/var/lib/kolla/config_files/src-tls$service_key\" \"$service_key\"\nfi\n# Set appropriate permissions\n{{container_cli}} exec -u root \"$container_name\" chown rabbitmq:rabbitmq \"$service_crt\"\n{{container_cli}} exec -u root \"$container_name\" chown rabbitmq:rabbitmq \"$service_key\"\n# Trigger a pem cache clear in RabbitMQ to read the new certificates\n{{container_cli}} exec \"$container_name\" rabbitmqctl eval \"ssl:clear_pem_cache().\"\n", "key_size": "2048", "ca": "ipa"}]}}]}], "tuple:('role_data', 'metadata_settings')": [{"service": "rabbitmq", "network": "internal_api", "type": "node"}], "tuple:('role_data', 'service_name')": "oslo_messaging_rpc", "tuple:('role_data', 'service_config_settings')": null, "tuple:('role_data', 'global_config_settings')": {"oslo_messaging_rpc_scheme": "rabbit", "oslo_messaging_rpc_user_name": "guest", "oslo_messaging_rpc_password": "CXYUjEO3wxDmzZtKlwuHEqtzC", "oslo_messaging_rpc_use_ssl": "True", "oslo_messaging_rpc_port": 5672}, "tuple:('role_data', 'config_settings')": {"rabbitmq::file_limit": 65536, "rabbitmq::default_user": "guest", "rabbitmq::default_pass": "CXYUjEO3wxDmzZtKlwuHEqtzC", "rabbit_ipv6": false, "rabbitmq::delete_guest_user": false, "rabbitmq::wipe_db_on_cookie_change": true, "rabbitmq::port": 5672, "rabbitmq::loopback_users": [], "rabbitmq::tcp_backlog": 4096, "rabbitmq::repos_ensure": false, "rabbitmq::tcp_keepalive": true, "rabbitmq_environment": {"LANG": "en_US.UTF-8", "LC_ALL": "en_US.UTF-8", "NODE_PORT": "", "NODE_IP_ADDRESS": "", "RABBITMQ_NODENAME": "rabbit@%{hiera('fqdn_internal_api')}", "RABBITMQ_USE_LONGNAME": "true", "RABBITMQ_CTL_DIST_PORT_MIN": "25673", "RABBITMQ_CTL_DIST_PORT_MAX": "25683", "export ERL_EPMD_ADDRESS": "%{hiera('rabbitmq::interface')}"}, "tripleo::profile::base::rabbitmq::additional_erl_args": "'+sbwt none +sbwtdcpu none +sbwtdio none'", "rabbitmq_kernel_variables": {"inet_dist_listen_min": "25672", "inet_dist_listen_max": "25672", "net_ticktime": 15}, "rabbitmq_config_variables": {"cluster_partition_handling": "ignore", "queue_master_locator": "<<\"min-masters\">>"}, "rabbitmq::config_additional_variables": {"lager": "[{crash_log_count, 0}, { crash_log_date, \"\"}, { crash_log_size, 0 }]"}, "rabbitmq::erlang_cookie": "mpHJWwKkkBAv6EusO06i", "rabbitmq::interface": "%{hiera('internal_api')}", "rabbitmq::nr_ha_queues": 0, "rabbitmq::ssl": true, "rabbitmq::ssl_erl_dist": true, "rabbitmq::ssl_port": 5672, "rabbitmq::ssl_depth": 1, "rabbitmq::ssl_only": true, "rabbitmq::ssl_interface": "%{hiera('internal_api')}", "tripleo::profile::base::rabbitmq::enable_internal_tls": true, "tripleo::profile::base::rabbitmq::fips_mode": false, "rabbitmq::collect_statistics_interval": 30000, "tripleo::rabbitmq::service_certificate": "/etc/pki/tls/certs/rabbitmq.crt", "tripleo::profile::base::rabbitmq::certificate_specs": {"service_certificate": "/etc/pki/tls/certs/rabbitmq.crt", "service_key": "/etc/pki/tls/private/rabbitmq.key"}, "rabbitmq::ssl_versions": ["tlsv1.2"], "rabbitmq::admin_enable": false, "rabbitmq::management_enable": true, "rabbitmq::use_config_file_for_plugins": true, "rabbitmq::management_ip_address": "127.0.0.1", "rabbitmq::management_port": 15672, "rabbitmq::config_management_variables": {"rates_mode": "none"}, "rabbitmq::ssl_cacert": "/etc/ipa/ca.crt", "rabbitmq::ssl_management_cacert": "/etc/ipa/ca.crt", "tripleo::certmonger::rabbitmq::postsave_cmd": "true"}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-47-ladweh3urreb-RabbitmqBase-dz4qqscmtqjp/32d0a87d-8c1b-48b9-a399-6d280982a847"}


created_at: 2026-06-13 07:33:22.882995
data:
  {"tuple:('role_data', 'step_config')": null, "tuple:('role_data', 'container_config_scripts')": {"container_puppet_apply.sh": {"mode": "0700", "content": "#!/bin/bash\nset -eux\nSTEP=$1\nTAGS=$2\nCONFIG=$3\nEXTRA_ARGS=${4:-''}\nif [ -d /tmp/puppet-etc ]; then\n  # ignore copy failures as these may be the same file depending on docker mounts\n  cp -a /tmp/puppet-etc/* /etc/puppet || true\nfi\necho \"{\\\"step\\\": ${STEP}}\" > /etc/puppet/hieradata/docker_puppet.json\n# $::deployment_type in puppet-tripleo\nexport FACTER_deployment_type=containers\nset +e\npuppet apply $EXTRA_ARGS \\\n    --verbose \\\n    --detailed-exitcodes \\\n    --summarize \\\n    --color=false \\\n    --modulepath /etc/puppet/modules:/opt/stack/puppet-modules:/usr/share/openstack-puppet/modules \\\n    --tags $TAGS \\\n    -e \"noop_resource('package'); ${CONFIG}\"\nrc=$?\nset -e\nset +ux\nif [ $rc -eq 2 -o $rc -eq 0 ]; then\n    exit 0\nfi\nexit $rc\n"}, "pyshim.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n# Copyright 2018 Red Hat Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n#\n# Usage: pyshim.sh <script and/or arguments>\n#\n# Unfortunately THT doesn't know which version of python might be in a\n# container so we need this script to be able to try python3 or python2\n# depending on availability.  Since this is a temporary shim until we've\n# fully cut over to python3, we check for the existence of python3 first\n# before falling back to python2. This will help in the transition from\n# python2 based containers to python3.\n\nshow_usage() {\n    echo \"Usage: pyshim.sh <script and/or arguments>\"\n}\n\nif [ $# -lt 1 ]\nthen\n    show_usage\n    exit 1\nfi\n\nset -x\nif command -v python3 >/dev/null; then\n    python3 \"$@\"\nelif command -v python2 >/dev/null; then\n    python2 \"$@\"\nelif command -v python >/dev/null; then\n    python \"$@\"\nelse\n    echo \"ERROR: python is not available!\"\n    exit 1\nfi\n"}, "pacemaker_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nset -u\n\n# ./pacemaker_restart_bundle.sh mysql galera galera-bundle Master _\n# ./pacemaker_restart_bundle.sh redis redis redis-bundle Slave Master\n# ./pacemaker_restart_bundle.sh ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\nRESTART_SCRIPTS_DIR=$(dirname $0)\nTRIPLEO_SERVICE=$1\nRESOURCE_NAME=$2\nBUNDLE_NAME=$3\nWAIT_TARGET_LOCAL=$4\nWAIT_TARGET_ANYWHERE=${5:-_}\nTRIPLEO_MINOR_UPDATE=\"${TRIPLEO_MINOR_UPDATE:-false}\"\nTRIPLEO_HA_WRAPPER_RESOURCE_EXISTS=\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS:-false}\"\n\nbundle_can_be_restarted() {\n    local bundle=$1\n    # As long as the resource bundle is managed by pacemaker and is\n    # not meant to stay stopped, no matter the state of any inner\n    # pcmk_remote or ocf resource, we should restart it to give it a\n    # chance to read the new config.\n    [ \"$(crm_resource --meta -r $1 -g is-managed 2>/dev/null)\" != \"false\" ] && \\\n    [ \"$(crm_resource --meta -r $1 -g target-role 2>/dev/null)\" != \"Stopped\" ]\n}\n\nlog() {\n    local msg=$1\n    logger -t pcmkrestart \"$1\"\n}\n\nHOSTNAME=$(/bin/hostname -s)\nif [ x\"${TRIPLEO_MINOR_UPDATE,,}\" != x\"true\" ]; then\n    if [ x\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS,,}\" = x\"false\" ]; then\n        # Do not restart during initial deployment, as the resource\n        # has just been created.\n        SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n        if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n            log \"Initial deployment, skipping the restart of ${BUNDLE_NAME}\"\n\tfi\n        exit 0\n    else\n        # During a stack update, this script is called in parallel on\n        # every node the resource runs on, after the service's configs\n        # have been updated on all nodes. So we need to run pcs only\n        # once (e.g. on the service's boostrap node).\n        if bundle_can_be_restarted ${BUNDLE_NAME}; then\n            SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n            if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n                replicas_running=$(crm_resource -Q -r $BUNDLE_NAME --locate 2>&1 | wc -l)\n                if [ \"$replicas_running\" != \"0\" ]; then\n                    log \"Restarting ${BUNDLE_NAME} globally. Stopping:\"\n                    /sbin/pcs resource disable --wait=600 $BUNDLE_NAME\n                    log \"Restarting ${BUNDLE_NAME} globally. Starting:\"\n                    /sbin/pcs resource enable --wait=600 $BUNDLE_NAME\n                else\n                    log \"${BUNDLE_NAME} is not running anywhere,\" \\\n                         \"cleaning up to restart it globally if necessary\"\n                    /sbin/pcs resource cleanup $BUNDLE_NAME\n                fi\n            else\n                log \"Skipping global restart of ${BUNDLE_NAME} on ${HOSTNAME} it will be restarted by node ${SERVICE_NODEID}\"\n            fi\n\n        else\n            log \"No global restart needed for ${BUNDLE_NAME}.\"\n        fi\n    fi\nelse\n    # During a minor update workflow however, a host gets fully\n    # updated before updating the next one. So unlike stack\n    # update, at the time this script is called, the service's\n    # configs aren't updated on all nodes yet. So only restart the\n    # resource locally, where it's guaranteed that the config is\n    # up to date.\n    HOST=$(facter hostname)\n\n    if bundle_can_be_restarted ${BUNDLE_NAME}; then\n\t# if the resource is running locally, restart it\n\tif crm_resource -r $BUNDLE_NAME --locate 2>&1 | grep -w -q \"${HOST}\"; then\n            log \"Restarting ${BUNDLE_NAME} locally on '${HOST}'\"\n            /sbin/pcs resource restart $BUNDLE_NAME \"${HOST}\"\n\n\telse\n\t    # At this point, if no resource is running locally, it's\n\t    # either because a) it has failed previously, or b) because\n\t    # it's an A/P resource running elsewhere.\n\t    # By cleaning up resource, we ensure that a) it will try to\n\t    # restart, or b) it won't do anything if the resource is\n\t    # already running elsewhere.\n            log \"${BUNDLE_NAME} is currently not running on '${HOST}',\" \\\n                 \"cleaning up its state to restart it if necessary\"\n            /sbin/pcs resource cleanup $BUNDLE_NAME node=\"${HOST}\"\n\tfi\n\n\t# Wait until the resource is in the expected target state\n\t$RESTART_SCRIPTS_DIR/pacemaker_wait_bundle.sh \\\n            $RESOURCE_NAME $BUNDLE_NAME \\\n            \"$WAIT_TARGET_LOCAL\" \"$WAIT_TARGET_ANYWHERE\" \\\n\t    \"${HOST}\" 600\n    else\n        log \"No restart needed for ${BUNDLE_NAME}.\"\n    fi\nfi\n"}, "pacemaker_wait_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# ----\n# Wait for an OCF resource or a bundle to be restarted\n# ----\n# e.g.:\n# M/S OCF:      $0 galera galera-bundle Master\n# clone OCF:    $0 rabbitmq rabbitmq-bundle Started\n# A/P M/S OCF:  $0 redis redis-bundle Slave Master\n# A/P bundle:   $0 openstack-cinder-volume openstack-cinder-volume _ Started\n# clone bundle: $0 haproxy-bundle haproxy-bundle Started\n\n# design note 1:\n#  - this script is called during a minor update; it is called\n#    once per node that hosts a service replica.\n#  - the purpose of this script is to ensure that restarting the\n#    service replica locally won't disrupt the service availability\n#    for the end user. To reach that goal, the script waits until the\n#    service is restarted locally or globallu and reaches a given\n#    target state (i.e. Started, Slave or Master).\n# design note 2:\n#   - we don't want to track restart error: our only job is to ensure\n#     service restart synchronization, not service health.\n#   - In particular, we don't want to error out in case the resource\n#     cannot be restarted locally, because that would make the minor\n#     update fail, even if potentially other replicas still provide\n#     the service.\n# design note 3:\n#   - we can bail out early if we determine that the resource can't\n#     be restarted automatically by pacemaker (e.g. its \"blocked\",\n#     unmanaged or disabled).\n\nlog() {\n    local msg=$1\n    echo \"$(date -u): $1\"\n}\n\nusage() {\n    echo 2>&1 \"Usage: $0 NAME BUNDLE_NAME ROLE_LOCAL [ROLE_ANYWHERE] [HOST] [TIMEOUT]\"\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\n#\n# Utility functions to detect stuck resources\n#\n\nbundle_failures_locally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local replica_name\n    for i in $(seq 0 $last); do\n\treplica_name=${BUNDLE_NAME}-${engine}-${i}\n\tcrm_failcount -q -G -r $replica_name -N $HOST\n    done\n}\n\nbundle_failures_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    for i in $(seq 0 $last); do\n\tcrm_failcount -q -G -r ${BUNDLE_NAME}-${engine}-${i}\n    done\n}\n\nbundle_running_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    # return the number of running bundles replica, i.e. the number of\n    # docker/podman resource replicas currently running in the cluster\n    crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:heartbeat:${engine}']/node)\" -\n}\n\nocf_failures_globally() {\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local bundle_node\n    for i in $(seq 0 $last); do\n\tbundle_node=${BUNDLE_NAME}-${i}\n\tcrm_failcount -q -G -r $NAME -N $bundle_node\n    done\n}\n\ndid_resource_failed_locally() {\n    local failures\n    local running\n    local remotehost\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# if we're dealing with an ocf resource, it is running on a\n\t# pacemaker_remote rather that on the real host, and the\n\t# failcounts are thus associated to the pcmk remote. Replace\n\t# the host's name with the pcmk remote's name.\n        remotehost=$(crm_mon --as-xml | xmllint --xpath \"string(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource/node[@name='${HOST}']/../../resource[@resource_agent='${OCF}:pacemaker:remote']/@id)\" -)\n\tif [ -n \"${remotehost}\" ]; then\n\t    crm_failcount -q -G -r $NAME -N $remotehost | grep -q -w INFINITY\n\t    return $?\n\tfi\n\t# If no pcmk remote is currently running, the failcount from\n\t# the ocf resource is useless, compute the failcount from the\n\t# bundle case instead (computed below).\n    fi\n\n    # for bundles, pacemaker can run any bundle replica locally\n    # (e.g. galera-bundle-docker-{0,1,2}), and a failure happens when\n    # there are no more replica to try.\n    # That is, when _at least_ one replica failed locally, and all the\n    # others either failed or are currently running elsewhere.\n    failures=$(bundle_failures_locally $HOST | grep -c -w INFINITY)\n    running=$(bundle_running_globally)\n    test $failures -gt 0 && \\\n    test $(( $failures + $running )) -ge $BUNDLE_REPLICAS\n}\n\ndid_resource_failed_globally() {\n    local remotecount\n    local failures\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# we check the state of an ocf resource only if the\n\t# pcmkremotes are started\n        remotecount=$(crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node)\" -)\n\tif [ \"${remotecount}\" = \"0\" ]; then\n\t    # no pcmkremote is running, so check the bundle state\n\t    # instead of checking the ocf resource\n\t    # bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\t    failures=$(bundle_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\telse\n\t    # ocf resource failed if it failed to start on\n\t    # all $BUNDLE_REPLICAS bundle nodes\n\t    failures=$(ocf_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\tfi\n    else\n\t# bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\tfailures=$(bundle_failures_globally | grep -c -w INFINITY)\n\ttest $failures -eq $BUNDLE_REPLICAS\n    fi\n}\n\n\n# Input validation\n#\n\nNAME=$1\nif [ -z \"${NAME}\" ]; then\n    echo 2>&1 \"Error: argument NAME must not be empty\"\n    exit 1\nfi\n\nBUNDLE_NAME=$2\nif [ -z \"${BUNDLE_NAME}\" ]; then\n    echo 2>&1 \"Error: argument BUNDLE_NAME must not be empty\"\n    exit 1\nfi\n\nROLE_LOCAL=$3\nif [ \"${ROLE_LOCAL}\" = \"_\" ]; then\n    ROLE_LOCAL=\"\"\nfi\n\nROLE_ANYWHERE=$4\nif [ \"${ROLE_ANYWHERE}\" = \"_\" ]; then\n    ROLE_ANYWHERE=\"\"\nfi\n\nif [ -z \"${ROLE_LOCAL}\" ]; then\n    if [ -z \"${ROLE_ANYWHERE}\" ]; then\n        echo 2>&1 \"Error: either ROLE_LOCAL or ROLE_ANYWHERE must be non empty\"\n        exit 1\n    fi\nelse\n    if !(echo \"${ROLE_LOCAL}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n        echo 2>&1 \"Error: argument ROLE_LOCAL must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n        exit 1\n    fi\nfi\n\nif [ -n \"${ROLE_ANYWHERE}\" ] && !(echo \"${ROLE_ANYWHERE}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n    echo 2>&1 \"Error: argument ROLE_ANYWHERE must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n    exit 1\nfi\n\n# Ensure compatibility with pacemaker 2.1\nif pacemaker_supports_promoted; then\n    ROLE_LOCAL=$(echo \"$ROLE_LOCAL\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    ROLE_ANYWHERE=$(echo \"$ROLE_ANYWHERE\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    OCF=\"ocf\"\nelse\n    OCF=\"ocf:\"\nfi\n\nHOST=${5:-$(facter hostname)}\nTIMEOUT=${6:-600}\n\n\n# Configure the search\n# ----\n# Note: we can't use crm_resource in all searches because we can't\n# easily extract the host the OCF resources run on (crm_resource\n# returns the pcmk-remote nodes rather than the hosts)\n# So instead, we implement various searches with XPath directly.\n\nif [ \"${BUNDLE_NAME}\" != \"${NAME}\" ]; then\n# ocf resource\nlocal_resource_xpath=\"//bundle/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node[@name='${HOST}']/../../resource[@id='${NAME}']\"\nany_resource_xpath=\"//bundle//resource[@id='${NAME}']\"\nreplicas_xpath=\"//bundle/primitive[@id='${BUNDLE_NAME}']/../*[boolean(@image) and boolean(@replicas)]\"\nelse\n# bundle resource\nlocal_resource_xpath=\"//bundle[@id='${NAME}']/replica/resource/node[@name='${HOST}']/../../resource\"\nany_resource_xpath=\"//bundle[@id='${NAME}']//resource\"\nreplicas_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nfi\n\nbundle_def_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nBUNDLE_CONTAINER_ENGINE=$(cibadmin -Q | xmllint --xpath \"name(${bundle_def_xpath})\" -)\nBUNDLE_REPLICAS=$(cibadmin -Q | xmllint --xpath \"string(${bundle_def_xpath}/@replicas)\" -)\n\n\n# The wait algorithm follows a two-stage approach\n#  1. Depending on how the script is called, we first check whether\n#     the resource is restarted locally. An A/P resource may be\n#     restarted elsewhere in the cluster.\n#  2. If needed, check whether the A/P resource has restarted\n#     elsewhere. For A/P M/S resources, in case the resource is\n#     restarted as Slave locally, ensure a Master is available.\n\nsuccess=1\nbailout=1\ntimeout=$TIMEOUT\nrole=\"\"\n\n# Stage 1: local check\nif [ -n \"$ROLE_LOCAL\" ]; then\n    log \"Waiting until ${NAME} has restarted on ${HOST} and is in state ${ROLE_LOCAL}\"\n    log \"Will probe resource state with the following XPath pattern: ${local_resource_xpath}\"\n\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resource=$(crm_mon -r --as-xml | xmllint --xpath \"${local_resource_xpath}\" - 2>/dev/null)\n        role=$(echo \"${resource}\" | sed -ne 's/.*\\Wrole=\"\\([^\"]*\\)\".*/\\1/p')\n\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resource}\" | grep -q -w \"\\Wblocked=\\\"true\\\"\"; then\n            log \"${NAME} is blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_locally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif [ \"$role\" = \"$ROLE_LOCAL\" ]; then\n            success=0\n            continue\n        elif [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" = \"$ROLE_ANYWHERE\" ]; then\n            # A/P: we are restarted in the expected state\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_LOCAL} on ${HOST}\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\n# Stage 2: global check\nif [ $timeout -gt 0 ] && [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" != \"$ROLE_ANYWHERE\" ]; then\n    log \"Wait until ${NAME} is restarted anywhere in the cluster in state ${ROLE_ANYWHERE}\"\n    log \"Will probe resource state with the following XPath pattern: ${any_resource_xpath}\"\n\n    success=1\n    bailout=1\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resources=$(crm_mon -r --as-xml | xmllint --xpath \"${any_resource_xpath}\" - 2>/dev/null)\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif ! (echo \"${resources}\" | grep -q -w \"\\Wblocked=\\\"false\\\"\"); then\n            log \"${NAME} blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_globally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resources}\" | grep -q -w \"\\Wrole=\\\"${ROLE_ANYWHERE}\\\"\"; then\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_ANYWHERE} anywhere in the cluster\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\nif [ $timeout -le 0 ]; then\n    log \"Timeout reached after ${TIMEOUT}s while waiting for ${NAME} to be restarted\"\nelif [ $bailout -le 0 ]; then\n    log \"Restart monitoring for ${NAME} cancelled\"\nfi\n\nif [ $success -eq 0 ]; then\n    log \"${NAME} successfully restarted\"\nelse\n    log \"${NAME} was not restarted properly\"\nfi\n\n# Don't block minor update or stack update if the wait was unsuccessful\nexit 0\n"}, "wait-port-and-run.sh": {"mode": "0755", "content": "#!/usr/bin/bash\nset -eu\n\nHOST=$1\nPORT=$2\n\necho \"$(date -u): Checking whether we can bind to ${HOST}:${PORT}\"\nwhile (ss -Htnl src \"${HOST}\" \"sport = :${PORT}\" | grep -wq \"${PORT}\"); do\n    echo \"$(date -u): ${HOST}:${PORT} still in use, waiting...\";\n    sleep 10;\ndone\n\nshift 2\nCOMMAND=\"$*\"\nif [ -z \"${COMMAND}\" ]; then\n    COMMAND=\"true\"\nfi\nexec $COMMAND\n"}, "pacemaker_resource_lock.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nMAX_RETRIES=10\nCIB_ENOTFOUND=105\n\nusage() {\n   echo \"Set a global property in the cluster with a validity timestamp.\"\n   echo \"Usage:\"\n   echo \"   $0 --acquire <lock_name> <lock_owner> <lock_ttl_in_seconds>\"\n   echo \"   $0 --release <lock_name> <lock_owner>\"\n   echo\n}\n\nlog() {\n    echo \"$(date -u): $1\" 1>&2\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\nlock_create() {\n    local name=$1\n    local data=$2\n    # cibadmin won't overwrite a key if someone else succeeded to create it concurrently\n    cibadmin --sync-call --scope crm_config --create --xml-text \"<cluster_property_set id='${name}'><nvpair id='${name}-pair' name='${name}' value='${data}'/></cluster_property_set>\" &>/dev/null\n    return $?\n}\n\nlock_update() {\n    local name=$1\n    local expected_data=$2\n    local new_data=$3\n    # we only update the lock we expect to see, so we can't update someone else's lock\n    cibadmin --sync-call --scope crm_config --modify --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" --xml-text \"<nvpair id='${name}-pair' name='${name}' value='${new_data}'/>\" &>/dev/null\n    return $?\n}\n\nlock_delete() {\n    local name=$1\n    local expected_data=$2\n    # we only delete the lock we expect to see, so we can't delete someone else's lock\n    cibadmin --sync-call --scope crm_config --delete --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" &>/dev/null\n    return $?\n}\n\nlock_get() {\n    local lockname=$1\n    local res\n    local rc\n    res=$(cibadmin --query --scope crm_config --xpath \"//cluster_property_set/nvpair[@name='$lockname']\" 2>/dev/null)\n    rc=$?\n    if [ $rc -eq 0 ]; then\n        echo \"$res\" | sed -n 's/.*value=\"\\([^\"]*\\)\".*/\\1/p'\n    fi\n    return $rc\n}\n\nlock_owner() {\n    local lock=$1\n    echo \"$lock\" | cut -d':' -f1\n}\n\nlock_has_expired() {\n    local lock=$1\n    local expiry=$(echo \"$lock\" | cut -d':' -f2)\n    local now=$(date +%s)\n    test $now -ge $expiry\n}\n\n\n# Perform a lock action and restart if the CIB has been modified before\n# committing the lock action\ntry_action() {\n    local fun=$1\n    local lock=$2\n    local requester=$3\n    local args=${4:-}\n    local tries=$MAX_RETRIES\n    local rc=1\n    if [ \"$fun\" = \"lock_acquire\" ] || [ \"$fun\" = \"lock_release\" ]; then\n        log \"Try running $fun\"\n    else\n        return 2\n    fi\n    while [ $rc -ne 0 ]; do\n        $fun $lock $requester $args\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Operation $1 succeeded\"\n            return 0\n        elif [ $rc -eq 3 ]; then\n            # rc == 3 -> CIB changed before push\n            if [ $tries -eq 0 ]; then\n                log \"Failed to commit after $MAX_RETRIES retries. Bailing out.\"\n                return 2\n            else\n                log \"Failed to commit. Retrying operation.\"\n                tries=$(($tries - 1))\n            fi\n        elif [ $rc -eq 2 ]; then\n            # rc == 2 -> unrecoverable cib error (e.g. pacemaker down)\n            log \"Unexpected failure. Bailing out\"\n            return $rc\n        else\n            # rc == 1 -> lock error (not owner, lock doesn't exists)\n            return $rc\n        fi\n    done\n}\n\n# The lock mechanism uses cibadmin's atomic creation so cluster-wide\n# state coherency is guaranteed by pacemaker\nlock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc\n    local lock\n    local expiry\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -n \"$lock\" ]; then\n        lock_has_expired $lock\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Lock has expired, now available for being held\"\n        else\n            # lock is still held. check whether we're the owner\n            owner=$(lock_owner $lock)\n            if [ \"$owner\" = \"$requester\" ];then\n                log \"Requester already owns the lock, acquiring attempt will just reconfigure the TTL\"\n            else\n                log \"Lock is held by someone else ($owner)\"\n                return 1\n            fi\n        fi\n    else\n        log \"Lock is not held yet\"\n    fi\n\n    # prepare the lock info\n    expiry=$(($(date +%s) + $ttl))\n\n    if [ -n \"$lock\" ]; then\n        log \"Attempting to update the lock\"\n        lock_update $lockname \"$lock\" \"$requester:$expiry\"\n        rc=$?\n    else\n        log \"Attempting to acquire the lock\"\n        lock_create $lockname \"$requester:$expiry\"\n        rc=$?\n    fi\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' acquired by '$requester', valid until $(date -d @$expiry)\"\n        return 0\n    else\n        log \"CIB changed, lock cannot be acquired\"\n        return 3\n    fi\n}\n\n\n# The lock mechanism uses the CIB's num_updates tag to implement\n# a conditional store. Cluster-wide locking is guaranteed by pacemaker\nlock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n    local lock\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        log \"Lock doesn't exist. Nothing to release\"\n        return 0\n    else\n        log \"Lock exists, check whether we're the owner\"\n        owner=$(lock_owner $lock)\n        if [ \"$owner\" != \"$requester\" ];then\n            log \"Lock is held by someone else ($owner), will not unlock\"\n            return 1\n        fi\n    fi\n\n    lock_delete $lockname \"$lock\"\n    rc=$?\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' released by '$requester'\"\n        return 0\n    else\n        log \"CIB deletion error, lock cannot be released\"\n        return 3\n    fi\n}\n\n\n# Retrieve the owner of a lock from the CIB\n# this is a read-only operation, so no need to log debug info\nlock_get_owner() {\n    local lockname=$1\n    local rc\n    local lock\n    local owner\n\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        return 1\n    else\n        lock_owner $lock\n        return 0\n    fi\n}\n\n\nACTION=$1\nLOCKNAME=$2\nREQUESTER=$3\nTTL=${4:-60}\n\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nif [ $ACTION != \"--help\" ]; then\n    if [ -z \"$LOCKNAME\" ]; then\n        error \"You must specific a lock name\"\n    fi\n    if [ $ACTION != \"--owner\" ] && [ $ACTION != \"-o\" ]; then\n        if [ -z \"$REQUESTER\" ]; then\n            error \"You must specific a lock requester\"\n        fi\n    fi\nfi\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) try_action lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --release|-r) try_action lock_release $LOCKNAME $REQUESTER;;\n    --acquire-once|-A) lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --owner|-o) lock_get_owner $LOCKNAME;;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}, "pacemaker_mutex_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_restart_bundle.sh --lock mysql galera galera-bundle Master _\n# pacemaker_mutex_restart_bundle.sh --lock ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\n\nset -u\n\nusage() {\n    echo \"Restart a clustered resource in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --lock <tripleo-service> <pcmk-resource> <pcmk-bundle> <target-state-local> <target-state-cluster>\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\nACTION=$1\ncase $ACTION in\n    --help) usage; exit 0;;\n    --lock) ;;\n    *) error \"Unknown action '$ACTION'\";;\nesac\n\nTRIPLEO_SERVICE=$2\nLOCK_NAME=${TRIPLEO_SERVICE}-restart-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to restart resource $TRIPLEO_SERVICE\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\nRESOURCE_NAME=$3\nBUNDLE_NAME=$4\nWAIT_TARGET_LOCAL=$5\nWAIT_TARGET_ANYWHERE=${6:-_}\n\nif pacemaker_supports_promoted; then\n    WAIT_TARGET_LOCAL=$(echo \"$5\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    WAIT_TARGET_ANYWHERE=$(echo \"${6:-_}\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    promoted_role=\"Promoted\"\nelse\n    promoted_role=\"Master\"\nfi\n\n# The lock TTL should accomodate for the resource start/promote timeout\nif [ \"$RESOURCE_NAME\" != \"$BUNDLE_NAME\" ]; then\n    if [ \"$WAIT_TARGET_LOCAL\" = \"$promoted_role\" ] || [ \"$WAIT_TARGET_ANYWHERE\" = \"$promoted_role\" ]; then\n        rsc_op=\"promote\"\n    else\n        rsc_op=\"start\"\n    fi\n    # <op id=\"galera-promote-interval-0s\" interval=\"0s\" name=\"promote\" on-fail=\"block\" timeout=\"300s\"/>\n    PCMK_TTL=$(cibadmin -Q | xmllint -xpath \"string(//primitive[@id='${RESOURCE_NAME}']/operations/op[@name='${rsc_op}']/@timeout)\" - | sed 's/s$//')\n    LOCK_TTL=$((PCMK_TTL + 30))\nelse\n    # The podman RA's default start timeout\n    LOCK_TTL=90\nfi\n\nlog \"Acquire a ${LOCK_TTL}s restart lock for service $TRIPLEO_SERVICE before restarting it\"\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nrc=1\nwhile [ $rc -ne 0 ]; do\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire $LOCK_NAME $LOCK_OWNER $LOCK_TTL\n    rc=$?\n    if [ $rc != 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not acquire lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Could not acquire lock, retrying\"\n            sleep 10\n        fi\n    fi\ndone\n\nlog \"Restart the service $TRIPLEO_SERVICE locally\"\n# Reuse the local restart script in t-h-t (driven by env var TRIPLEO_MINOR_UPDATE)\nTRIPLEO_MINOR_UPDATE=true /var/lib/container-config-scripts/pacemaker_restart_bundle.sh $TRIPLEO_SERVICE $RESOURCE_NAME $BUNDLE_NAME $WAIT_TARGET_LOCAL $WAIT_TARGET_ANYWHERE\n\n# If we reached this point, always try to release the lock\nlog \"Release the restart lock for service $TRIPLEO_SERVICE\"\n/var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $LOCK_NAME $LOCK_OWNER\nrc=$?\nif [ $rc -ne 0 ] && [ $rc -ne 1 ]; then\n    error \"Could not release held lock (rc: $rc)\"\nfi\n"}, "pacemaker_mutex_shutdown.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_shutdown.sh --acquire\n# pacemaker_mutex_shutdown.sh --release\n\nset -u\n\nusage() {\n    echo \"Shutdown a cluster node in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --acquire # prevent other node from shutting down until we hold the lock\"\n    echo \"   $0 --release # release the lock, other node can compete for the shutdown lock\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nshutdown_lock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc=1\n    local current_owner\n    local owner_stopped\n    local owner_rc\n\n    log \"Acquiring the shutdown lock\"\n    while [ $rc -ne 0 ]; do\n        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire-once $lockname $requester $ttl\n        rc=$?\n        if [ $rc -ne 0 ]; then\n            if [ $rc -eq 2 ]; then\n                error \"Could not acquire the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n            else\n                # The lock is held by another node.\n                current_owner=$(/var/lib/container-config-scripts/pacemaker_resource_lock.sh --owner $lockname)\n                owner_rc=$?\n                if [ $owner_rc -eq 2 ]; then\n                    error \"Could not get the shutdown lock owner due to unrecoverable error (rc: $owner_rc), bailing out\"\n                fi\n                if [ $owner_rc -eq 0 ]; then\n                    # If the owner is marked as offline, that means it has shutdown and\n                    # we can clean the lock preemptively and try to acquire it.\n                    owner_stopped=$(crm_mon -1X | xmllint --xpath 'count(//nodes/node[@name=\"'${current_owner}'\" and @online=\"false\" and @unclean=\"false\"])' -)\n                    if [ \"${owner_stopped}\" = \"1\" ]; then\n                        log \"Shutdown lock held by stopped node '${current_owner}', lock can be released\"\n                        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $current_owner\n                        continue\n                    fi\n                fi\n                log \"Shutdown lock held by another node (rc: $rc), retrying\"\n                sleep 10\n            fi\n        fi\n    done\n    log \"Shutdown lock acquired\"\n    return 0\n}\n\n\n# Release the lock if we still own it. Not owning it anymore is not fatal\nshutdown_lock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n\n    log \"Releasing the shutdown lock\"\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $requester\n    rc=$?\n    if [ $rc -ne 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not release the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Shutdown lock no longer held, nothing to do\"\n        fi\n    else\n        log \"Shutdown lock released\"\n    fi\n    return 0\n}\n\n\nACTION=$1\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nLOCK_NAME=tripleo-shutdown-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to aquire the shutdown lock\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\n# We start with a very high TTL, that long enough to accomodate a cluster stop.\n# As soon as the node will get offline, the other competing node will be entitled\n# to steal the lock, so they should never wait that long in practice.\nLOCK_TTL=600\n\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) shutdown_lock_acquire ${LOCK_NAME} ${LOCK_OWNER} ${LOCK_TTL};;\n    --release|-r) shutdown_lock_release ${LOCK_NAME} ${LOCK_OWNER};;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}}, "tuple:('role_data', 'docker_config')": {"step_1": {"rabbitmq_bootstrap": {"start_order": 0, "image": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1", "net": "host", "privileged": false, "user": "root", "command": ["bash", "-ec", "kolla_set_configs\nif [[ -e \"/var/lib/rabbitmq/.erlang.cookie\" ]]; then rm -f /var/lib/rabbitmq/.erlang.cookie; fi\nhiera 'rabbitmq::erlang_cookie' > /var/lib/rabbitmq/.erlang.cookie\nchown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie\nchmod 400 /var/lib/rabbitmq/.erlang.cookie"], "volumes": ["/var/lib/kolla/config_files/rabbitmq.json:/var/lib/kolla/config_files/config.json:ro", "/var/lib/config-data/puppet-generated/rabbitmq:/var/lib/kolla/config_files/src:ro", "/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/var/lib/rabbitmq:/var/lib/rabbitmq:z", "/etc/puppet:/etc/puppet:ro,z"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS", "TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}}, "step_2": {"rabbitmq_wait_bundle": {"start_order": 0, "detach": false, "net": "host", "ipc": "host", "user": "root", "command": ["/container_puppet_apply.sh", "2", "file,file_line,concat,augeas,rabbitmq_policy,rabbitmq_user,rabbitmq_ready", "include tripleo::profile::pacemaker::rabbitmq_bundle", ""], "image": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/var/lib/container-config-scripts/container_puppet_apply.sh:/container_puppet_apply.sh:ro", "/etc/puppet:/tmp/puppet-etc:ro", "/usr/share/openstack-puppet/modules:/usr/share/openstack-puppet/modules:ro", "/bin/true:/bin/epmd"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS", "KOLLA_BOOTSTRAP": true, "TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}}}, "tuple:('role_data', 'service_name')": "oslo_messaging_rpc", "role_data": {"service_name": "oslo_messaging_rpc", "firewall_rules": {"109 rabbitmq-bundle": {"dport": [3122, 4369, 5672, 25672, "25673-25683"]}}, "global_config_settings": {"oslo_messaging_rpc_scheme": "rabbit", "oslo_messaging_rpc_user_name": "guest", "oslo_messaging_rpc_password": "CXYUjEO3wxDmzZtKlwuHEqtzC", "oslo_messaging_rpc_use_ssl": "True", "oslo_messaging_rpc_port": 5672}, "config_settings": {"rabbitmq::file_limit": 65536, "rabbitmq::default_user": "guest", "rabbitmq::default_pass": "CXYUjEO3wxDmzZtKlwuHEqtzC", "rabbit_ipv6": false, "rabbitmq::delete_guest_user": false, "rabbitmq::wipe_db_on_cookie_change": true, "rabbitmq::port": 5672, "rabbitmq::loopback_users": [], "rabbitmq::tcp_backlog": 4096, "rabbitmq::repos_ensure": false, "rabbitmq::tcp_keepalive": true, "rabbitmq_environment": {"LANG": "en_US.UTF-8", "LC_ALL": "en_US.UTF-8", "NODE_PORT": "", "NODE_IP_ADDRESS": "", "RABBITMQ_NODENAME": "rabbit@%{hiera('fqdn_internal_api')}", "RABBITMQ_USE_LONGNAME": "true", "RABBITMQ_CTL_DIST_PORT_MIN": "25673", "RABBITMQ_CTL_DIST_PORT_MAX": "25683", "export ERL_EPMD_ADDRESS": "%{hiera('rabbitmq::interface')}"}, "tripleo::profile::base::rabbitmq::additional_erl_args": "'+sbwt none +sbwtdcpu none +sbwtdio none'", "rabbitmq_kernel_variables": {"inet_dist_listen_min": "25672", "inet_dist_listen_max": "25672", "net_ticktime": 15}, "rabbitmq_config_variables": {"cluster_partition_handling": "ignore", "queue_master_locator": "<<\"min-masters\">>"}, "rabbitmq::config_additional_variables": {"lager": "[{crash_log_count, 0}, { crash_log_date, \"\"}, { crash_log_size, 0 }]"}, "rabbitmq::erlang_cookie": "mpHJWwKkkBAv6EusO06i", "rabbitmq::interface": "%{hiera('internal_api')}", "rabbitmq::nr_ha_queues": 0, "rabbitmq::ssl": true, "rabbitmq::ssl_erl_dist": true, "rabbitmq::ssl_port": 5672, "rabbitmq::ssl_depth": 1, "rabbitmq::ssl_only": true, "rabbitmq::ssl_interface": "%{hiera('internal_api')}", "tripleo::profile::base::rabbitmq::enable_internal_tls": true, "tripleo::profile::base::rabbitmq::fips_mode": false, "rabbitmq::collect_statistics_interval": 30000, "tripleo::rabbitmq::service_certificate": "/etc/pki/tls/certs/rabbitmq.crt", "tripleo::profile::base::rabbitmq::certificate_specs": {"service_certificate": "/etc/pki/tls/certs/rabbitmq.crt", "service_key": "/etc/pki/tls/private/rabbitmq.key"}, "rabbitmq::ssl_versions": ["tlsv1.2"], "rabbitmq::admin_enable": false, "rabbitmq::management_enable": true, "rabbitmq::use_config_file_for_plugins": true, "rabbitmq::management_ip_address": "127.0.0.1", "rabbitmq::management_port": 15672, "rabbitmq::config_management_variables": {"rates_mode": "none"}, "rabbitmq::ssl_cacert": "/etc/ipa/ca.crt", "rabbitmq::ssl_management_cacert": "/etc/ipa/ca.crt", "tripleo::certmonger::rabbitmq::postsave_cmd": "true", "rabbitmq::service_manage": false, "tripleo::profile::pacemaker::rabbitmq_bundle::rabbitmq_docker_image": "cluster.common.tag/rabbitmq:pcmklatest", "tripleo::profile::pacemaker::rabbitmq_bundle::control_port": 3122, "tripleo::profile::pacemaker::rabbitmq_bundle::container_backend": "podman", "tripleo::profile::pacemaker::rabbitmq_bundle::force_ocf": true}, "service_config_settings": null, "puppet_config": {"config_volume": "rabbitmq", "puppet_tags": "file,file_line", "step_config": "['Rabbitmq_policy', 'Rabbitmq_user'].each |String $val| { noop_resource($val) }\ninclude tripleo::profile::pacemaker::rabbitmq_bundle", "config_image": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1"}, "kolla_config": {"/var/lib/kolla/config_files/rabbitmq.json": {"command": "/usr/sbin/pacemaker_remoted", "config_files": [{"dest": "/etc/libqb/force-filesystem-sockets", "source": "/dev/null", "owner": "root", "perm": "0644"}, {"dest": "/var/log/btmp", "source": "/dev/null", "owner": "root:utmp", "perm": "0600"}, {"source": "/var/lib/kolla/config_files/src/*", "dest": "/", "merge": true, "preserve_properties": true}, {"source": "/var/lib/kolla/config_files/src-tls/*", "dest": "/", "merge": true, "optional": true, "preserve_properties": true}], "permissions": [{"path": "/var/lib/rabbitmq", "owner": "rabbitmq:rabbitmq", "recurse": true}, {"path": "/var/log/rabbitmq", "owner": "rabbitmq:rabbitmq", "recurse": true}, {"path": "/etc/pki/tls/certs/rabbitmq.crt", "owner": "rabbitmq:rabbitmq", "perm": "0600", "optional": true}, {"path": "/etc/pki/tls/private/rabbitmq.key", "owner": "rabbitmq:rabbitmq", "perm": "0600", "optional": true}]}}, "container_config_scripts": {"container_puppet_apply.sh": {"mode": "0700", "content": "#!/bin/bash\nset -eux\nSTEP=$1\nTAGS=$2\nCONFIG=$3\nEXTRA_ARGS=${4:-''}\nif [ -d /tmp/puppet-etc ]; then\n  # ignore copy failures as these may be the same file depending on docker mounts\n  cp -a /tmp/puppet-etc/* /etc/puppet || true\nfi\necho \"{\\\"step\\\": ${STEP}}\" > /etc/puppet/hieradata/docker_puppet.json\n# $::deployment_type in puppet-tripleo\nexport FACTER_deployment_type=containers\nset +e\npuppet apply $EXTRA_ARGS \\\n    --verbose \\\n    --detailed-exitcodes \\\n    --summarize \\\n    --color=false \\\n    --modulepath /etc/puppet/modules:/opt/stack/puppet-modules:/usr/share/openstack-puppet/modules \\\n    --tags $TAGS \\\n    -e \"noop_resource('package'); ${CONFIG}\"\nrc=$?\nset -e\nset +ux\nif [ $rc -eq 2 -o $rc -eq 0 ]; then\n    exit 0\nfi\nexit $rc\n"}, "pyshim.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n# Copyright 2018 Red Hat Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\n# not use this file except in compliance with the License. You may obtain\n# a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\n# License for the specific language governing permissions and limitations\n# under the License.\n#\n# Usage: pyshim.sh <script and/or arguments>\n#\n# Unfortunately THT doesn't know which version of python might be in a\n# container so we need this script to be able to try python3 or python2\n# depending on availability.  Since this is a temporary shim until we've\n# fully cut over to python3, we check for the existence of python3 first\n# before falling back to python2. This will help in the transition from\n# python2 based containers to python3.\n\nshow_usage() {\n    echo \"Usage: pyshim.sh <script and/or arguments>\"\n}\n\nif [ $# -lt 1 ]\nthen\n    show_usage\n    exit 1\nfi\n\nset -x\nif command -v python3 >/dev/null; then\n    python3 \"$@\"\nelif command -v python2 >/dev/null; then\n    python2 \"$@\"\nelif command -v python >/dev/null; then\n    python \"$@\"\nelse\n    echo \"ERROR: python is not available!\"\n    exit 1\nfi\n"}, "pacemaker_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nset -u\n\n# ./pacemaker_restart_bundle.sh mysql galera galera-bundle Master _\n# ./pacemaker_restart_bundle.sh redis redis redis-bundle Slave Master\n# ./pacemaker_restart_bundle.sh ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\nRESTART_SCRIPTS_DIR=$(dirname $0)\nTRIPLEO_SERVICE=$1\nRESOURCE_NAME=$2\nBUNDLE_NAME=$3\nWAIT_TARGET_LOCAL=$4\nWAIT_TARGET_ANYWHERE=${5:-_}\nTRIPLEO_MINOR_UPDATE=\"${TRIPLEO_MINOR_UPDATE:-false}\"\nTRIPLEO_HA_WRAPPER_RESOURCE_EXISTS=\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS:-false}\"\n\nbundle_can_be_restarted() {\n    local bundle=$1\n    # As long as the resource bundle is managed by pacemaker and is\n    # not meant to stay stopped, no matter the state of any inner\n    # pcmk_remote or ocf resource, we should restart it to give it a\n    # chance to read the new config.\n    [ \"$(crm_resource --meta -r $1 -g is-managed 2>/dev/null)\" != \"false\" ] && \\\n    [ \"$(crm_resource --meta -r $1 -g target-role 2>/dev/null)\" != \"Stopped\" ]\n}\n\nlog() {\n    local msg=$1\n    logger -t pcmkrestart \"$1\"\n}\n\nHOSTNAME=$(/bin/hostname -s)\nif [ x\"${TRIPLEO_MINOR_UPDATE,,}\" != x\"true\" ]; then\n    if [ x\"${TRIPLEO_HA_WRAPPER_RESOURCE_EXISTS,,}\" = x\"false\" ]; then\n        # Do not restart during initial deployment, as the resource\n        # has just been created.\n        SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n        if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n            log \"Initial deployment, skipping the restart of ${BUNDLE_NAME}\"\n\tfi\n        exit 0\n    else\n        # During a stack update, this script is called in parallel on\n        # every node the resource runs on, after the service's configs\n        # have been updated on all nodes. So we need to run pcs only\n        # once (e.g. on the service's boostrap node).\n        if bundle_can_be_restarted ${BUNDLE_NAME}; then\n            SERVICE_NODEID=$(/bin/hiera -c /etc/puppet/hiera.yaml \"${TRIPLEO_SERVICE}_short_bootstrap_node_name\")\n            if [[ \"${HOSTNAME,,}\" == \"${SERVICE_NODEID,,}\" ]]; then\n                replicas_running=$(crm_resource -Q -r $BUNDLE_NAME --locate 2>&1 | wc -l)\n                if [ \"$replicas_running\" != \"0\" ]; then\n                    log \"Restarting ${BUNDLE_NAME} globally. Stopping:\"\n                    /sbin/pcs resource disable --wait=600 $BUNDLE_NAME\n                    log \"Restarting ${BUNDLE_NAME} globally. Starting:\"\n                    /sbin/pcs resource enable --wait=600 $BUNDLE_NAME\n                else\n                    log \"${BUNDLE_NAME} is not running anywhere,\" \\\n                         \"cleaning up to restart it globally if necessary\"\n                    /sbin/pcs resource cleanup $BUNDLE_NAME\n                fi\n            else\n                log \"Skipping global restart of ${BUNDLE_NAME} on ${HOSTNAME} it will be restarted by node ${SERVICE_NODEID}\"\n            fi\n\n        else\n            log \"No global restart needed for ${BUNDLE_NAME}.\"\n        fi\n    fi\nelse\n    # During a minor update workflow however, a host gets fully\n    # updated before updating the next one. So unlike stack\n    # update, at the time this script is called, the service's\n    # configs aren't updated on all nodes yet. So only restart the\n    # resource locally, where it's guaranteed that the config is\n    # up to date.\n    HOST=$(facter hostname)\n\n    if bundle_can_be_restarted ${BUNDLE_NAME}; then\n\t# if the resource is running locally, restart it\n\tif crm_resource -r $BUNDLE_NAME --locate 2>&1 | grep -w -q \"${HOST}\"; then\n            log \"Restarting ${BUNDLE_NAME} locally on '${HOST}'\"\n            /sbin/pcs resource restart $BUNDLE_NAME \"${HOST}\"\n\n\telse\n\t    # At this point, if no resource is running locally, it's\n\t    # either because a) it has failed previously, or b) because\n\t    # it's an A/P resource running elsewhere.\n\t    # By cleaning up resource, we ensure that a) it will try to\n\t    # restart, or b) it won't do anything if the resource is\n\t    # already running elsewhere.\n            log \"${BUNDLE_NAME} is currently not running on '${HOST}',\" \\\n                 \"cleaning up its state to restart it if necessary\"\n            /sbin/pcs resource cleanup $BUNDLE_NAME node=\"${HOST}\"\n\tfi\n\n\t# Wait until the resource is in the expected target state\n\t$RESTART_SCRIPTS_DIR/pacemaker_wait_bundle.sh \\\n            $RESOURCE_NAME $BUNDLE_NAME \\\n            \"$WAIT_TARGET_LOCAL\" \"$WAIT_TARGET_ANYWHERE\" \\\n\t    \"${HOST}\" 600\n    else\n        log \"No restart needed for ${BUNDLE_NAME}.\"\n    fi\nfi\n"}, "pacemaker_wait_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# ----\n# Wait for an OCF resource or a bundle to be restarted\n# ----\n# e.g.:\n# M/S OCF:      $0 galera galera-bundle Master\n# clone OCF:    $0 rabbitmq rabbitmq-bundle Started\n# A/P M/S OCF:  $0 redis redis-bundle Slave Master\n# A/P bundle:   $0 openstack-cinder-volume openstack-cinder-volume _ Started\n# clone bundle: $0 haproxy-bundle haproxy-bundle Started\n\n# design note 1:\n#  - this script is called during a minor update; it is called\n#    once per node that hosts a service replica.\n#  - the purpose of this script is to ensure that restarting the\n#    service replica locally won't disrupt the service availability\n#    for the end user. To reach that goal, the script waits until the\n#    service is restarted locally or globallu and reaches a given\n#    target state (i.e. Started, Slave or Master).\n# design note 2:\n#   - we don't want to track restart error: our only job is to ensure\n#     service restart synchronization, not service health.\n#   - In particular, we don't want to error out in case the resource\n#     cannot be restarted locally, because that would make the minor\n#     update fail, even if potentially other replicas still provide\n#     the service.\n# design note 3:\n#   - we can bail out early if we determine that the resource can't\n#     be restarted automatically by pacemaker (e.g. its \"blocked\",\n#     unmanaged or disabled).\n\nlog() {\n    local msg=$1\n    echo \"$(date -u): $1\"\n}\n\nusage() {\n    echo 2>&1 \"Usage: $0 NAME BUNDLE_NAME ROLE_LOCAL [ROLE_ANYWHERE] [HOST] [TIMEOUT]\"\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\n#\n# Utility functions to detect stuck resources\n#\n\nbundle_failures_locally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local replica_name\n    for i in $(seq 0 $last); do\n\treplica_name=${BUNDLE_NAME}-${engine}-${i}\n\tcrm_failcount -q -G -r $replica_name -N $HOST\n    done\n}\n\nbundle_failures_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    for i in $(seq 0 $last); do\n\tcrm_failcount -q -G -r ${BUNDLE_NAME}-${engine}-${i}\n    done\n}\n\nbundle_running_globally() {\n    local engine=$BUNDLE_CONTAINER_ENGINE\n    # return the number of running bundles replica, i.e. the number of\n    # docker/podman resource replicas currently running in the cluster\n    crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:heartbeat:${engine}']/node)\" -\n}\n\nocf_failures_globally() {\n    local replicas=$BUNDLE_REPLICAS\n    local last=$(($replicas - 1))\n    local bundle_node\n    for i in $(seq 0 $last); do\n\tbundle_node=${BUNDLE_NAME}-${i}\n\tcrm_failcount -q -G -r $NAME -N $bundle_node\n    done\n}\n\ndid_resource_failed_locally() {\n    local failures\n    local running\n    local remotehost\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# if we're dealing with an ocf resource, it is running on a\n\t# pacemaker_remote rather that on the real host, and the\n\t# failcounts are thus associated to the pcmk remote. Replace\n\t# the host's name with the pcmk remote's name.\n        remotehost=$(crm_mon --as-xml | xmllint --xpath \"string(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource/node[@name='${HOST}']/../../resource[@resource_agent='${OCF}:pacemaker:remote']/@id)\" -)\n\tif [ -n \"${remotehost}\" ]; then\n\t    crm_failcount -q -G -r $NAME -N $remotehost | grep -q -w INFINITY\n\t    return $?\n\tfi\n\t# If no pcmk remote is currently running, the failcount from\n\t# the ocf resource is useless, compute the failcount from the\n\t# bundle case instead (computed below).\n    fi\n\n    # for bundles, pacemaker can run any bundle replica locally\n    # (e.g. galera-bundle-docker-{0,1,2}), and a failure happens when\n    # there are no more replica to try.\n    # That is, when _at least_ one replica failed locally, and all the\n    # others either failed or are currently running elsewhere.\n    failures=$(bundle_failures_locally $HOST | grep -c -w INFINITY)\n    running=$(bundle_running_globally)\n    test $failures -gt 0 && \\\n    test $(( $failures + $running )) -ge $BUNDLE_REPLICAS\n}\n\ndid_resource_failed_globally() {\n    local remotecount\n    local failures\n    if [ \"${NAME}\" != \"${BUNDLE_NAME}\" ]; then\n\t# we check the state of an ocf resource only if the\n\t# pcmkremotes are started\n        remotecount=$(crm_mon --as-xml | xmllint --xpath \"count(//resources/bundle[@id='${BUNDLE_NAME}']/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node)\" -)\n\tif [ \"${remotecount}\" = \"0\" ]; then\n\t    # no pcmkremote is running, so check the bundle state\n\t    # instead of checking the ocf resource\n\t    # bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\t    failures=$(bundle_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\telse\n\t    # ocf resource failed if it failed to start on\n\t    # all $BUNDLE_REPLICAS bundle nodes\n\t    failures=$(ocf_failures_globally | grep -c -w INFINITY)\n\t    test $failures -eq $BUNDLE_REPLICAS\n\tfi\n    else\n\t# bundle failed if all ${BUNDLE_REPLICAS} replicas failed\n\tfailures=$(bundle_failures_globally | grep -c -w INFINITY)\n\ttest $failures -eq $BUNDLE_REPLICAS\n    fi\n}\n\n\n# Input validation\n#\n\nNAME=$1\nif [ -z \"${NAME}\" ]; then\n    echo 2>&1 \"Error: argument NAME must not be empty\"\n    exit 1\nfi\n\nBUNDLE_NAME=$2\nif [ -z \"${BUNDLE_NAME}\" ]; then\n    echo 2>&1 \"Error: argument BUNDLE_NAME must not be empty\"\n    exit 1\nfi\n\nROLE_LOCAL=$3\nif [ \"${ROLE_LOCAL}\" = \"_\" ]; then\n    ROLE_LOCAL=\"\"\nfi\n\nROLE_ANYWHERE=$4\nif [ \"${ROLE_ANYWHERE}\" = \"_\" ]; then\n    ROLE_ANYWHERE=\"\"\nfi\n\nif [ -z \"${ROLE_LOCAL}\" ]; then\n    if [ -z \"${ROLE_ANYWHERE}\" ]; then\n        echo 2>&1 \"Error: either ROLE_LOCAL or ROLE_ANYWHERE must be non empty\"\n        exit 1\n    fi\nelse\n    if !(echo \"${ROLE_LOCAL}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n        echo 2>&1 \"Error: argument ROLE_LOCAL must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n        exit 1\n    fi\nfi\n\nif [ -n \"${ROLE_ANYWHERE}\" ] && !(echo \"${ROLE_ANYWHERE}\" | grep -q -x -E \"(Started|Slave|Master|Unpromoted|Promoted)\"); then\n    echo 2>&1 \"Error: argument ROLE_ANYWHERE must be either 'Started' 'Slave' 'Master' 'Unpromoted' or 'Promoted'\"\n    exit 1\nfi\n\n# Ensure compatibility with pacemaker 2.1\nif pacemaker_supports_promoted; then\n    ROLE_LOCAL=$(echo \"$ROLE_LOCAL\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    ROLE_ANYWHERE=$(echo \"$ROLE_ANYWHERE\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    OCF=\"ocf\"\nelse\n    OCF=\"ocf:\"\nfi\n\nHOST=${5:-$(facter hostname)}\nTIMEOUT=${6:-600}\n\n\n# Configure the search\n# ----\n# Note: we can't use crm_resource in all searches because we can't\n# easily extract the host the OCF resources run on (crm_resource\n# returns the pcmk-remote nodes rather than the hosts)\n# So instead, we implement various searches with XPath directly.\n\nif [ \"${BUNDLE_NAME}\" != \"${NAME}\" ]; then\n# ocf resource\nlocal_resource_xpath=\"//bundle/replica/resource[@resource_agent='${OCF}:pacemaker:remote']/node[@name='${HOST}']/../../resource[@id='${NAME}']\"\nany_resource_xpath=\"//bundle//resource[@id='${NAME}']\"\nreplicas_xpath=\"//bundle/primitive[@id='${BUNDLE_NAME}']/../*[boolean(@image) and boolean(@replicas)]\"\nelse\n# bundle resource\nlocal_resource_xpath=\"//bundle[@id='${NAME}']/replica/resource/node[@name='${HOST}']/../../resource\"\nany_resource_xpath=\"//bundle[@id='${NAME}']//resource\"\nreplicas_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nfi\n\nbundle_def_xpath=\"//bundle[@id='${BUNDLE_NAME}']/*[boolean(@image) and boolean(@replicas)]\"\nBUNDLE_CONTAINER_ENGINE=$(cibadmin -Q | xmllint --xpath \"name(${bundle_def_xpath})\" -)\nBUNDLE_REPLICAS=$(cibadmin -Q | xmllint --xpath \"string(${bundle_def_xpath}/@replicas)\" -)\n\n\n# The wait algorithm follows a two-stage approach\n#  1. Depending on how the script is called, we first check whether\n#     the resource is restarted locally. An A/P resource may be\n#     restarted elsewhere in the cluster.\n#  2. If needed, check whether the A/P resource has restarted\n#     elsewhere. For A/P M/S resources, in case the resource is\n#     restarted as Slave locally, ensure a Master is available.\n\nsuccess=1\nbailout=1\ntimeout=$TIMEOUT\nrole=\"\"\n\n# Stage 1: local check\nif [ -n \"$ROLE_LOCAL\" ]; then\n    log \"Waiting until ${NAME} has restarted on ${HOST} and is in state ${ROLE_LOCAL}\"\n    log \"Will probe resource state with the following XPath pattern: ${local_resource_xpath}\"\n\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resource=$(crm_mon -r --as-xml | xmllint --xpath \"${local_resource_xpath}\" - 2>/dev/null)\n        role=$(echo \"${resource}\" | sed -ne 's/.*\\Wrole=\"\\([^\"]*\\)\".*/\\1/p')\n\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resource}\" | grep -q -w \"\\Wblocked=\\\"true\\\"\"; then\n            log \"${NAME} is blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_locally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif [ \"$role\" = \"$ROLE_LOCAL\" ]; then\n            success=0\n            continue\n        elif [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" = \"$ROLE_ANYWHERE\" ]; then\n            # A/P: we are restarted in the expected state\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_LOCAL} on ${HOST}\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\n# Stage 2: global check\nif [ $timeout -gt 0 ] && [ -n \"$ROLE_ANYWHERE\" ] && [ \"$role\" != \"$ROLE_ANYWHERE\" ]; then\n    log \"Wait until ${NAME} is restarted anywhere in the cluster in state ${ROLE_ANYWHERE}\"\n    log \"Will probe resource state with the following XPath pattern: ${any_resource_xpath}\"\n\n    success=1\n    bailout=1\n    while [ $timeout -gt 0 ] && [ $bailout -ne 0 ] && [ $success -ne 0 ]; do\n        resources=$(crm_mon -r --as-xml | xmllint --xpath \"${any_resource_xpath}\" - 2>/dev/null)\n\tif [ \"$(crm_resource --meta -r ${NAME} -g is-managed 2>/dev/null)\" = \"false\" ]; then\n            log \"${NAME} is unmanaged, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif [ \"$(crm_resource --meta -r ${NAME} -g target-role 2>/dev/null)\" = \"Stopped\" ]; then\n            log \"${NAME} is disabled, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif ! (echo \"${resources}\" | grep -q -w \"\\Wblocked=\\\"false\\\"\"); then\n            log \"${NAME} blocked, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n\telif did_resource_failed_globally; then\n            log \"${NAME} is in failed state, will never reach target role. Bailing out\"\n            bailout=0\n            continue\n        elif echo \"${resources}\" | grep -q -w \"\\Wrole=\\\"${ROLE_ANYWHERE}\\\"\"; then\n            success=0\n            continue\n        else\n            log \"Waiting for ${NAME} to transition to role ${ROLE_ANYWHERE} anywhere in the cluster\"\n        fi\n\n        if [ $bailout -ne 0 ] && [ $success -ne 0 ]; then\n            sleep 4\n            timeout=$((timeout-4))\n        fi\n    done\nfi\n\nif [ $timeout -le 0 ]; then\n    log \"Timeout reached after ${TIMEOUT}s while waiting for ${NAME} to be restarted\"\nelif [ $bailout -le 0 ]; then\n    log \"Restart monitoring for ${NAME} cancelled\"\nfi\n\nif [ $success -eq 0 ]; then\n    log \"${NAME} successfully restarted\"\nelse\n    log \"${NAME} was not restarted properly\"\nfi\n\n# Don't block minor update or stack update if the wait was unsuccessful\nexit 0\n"}, "wait-port-and-run.sh": {"mode": "0755", "content": "#!/usr/bin/bash\nset -eu\n\nHOST=$1\nPORT=$2\n\necho \"$(date -u): Checking whether we can bind to ${HOST}:${PORT}\"\nwhile (ss -Htnl src \"${HOST}\" \"sport = :${PORT}\" | grep -wq \"${PORT}\"); do\n    echo \"$(date -u): ${HOST}:${PORT} still in use, waiting...\";\n    sleep 10;\ndone\n\nshift 2\nCOMMAND=\"$*\"\nif [ -z \"${COMMAND}\" ]; then\n    COMMAND=\"true\"\nfi\nexec $COMMAND\n"}, "pacemaker_resource_lock.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\nMAX_RETRIES=10\nCIB_ENOTFOUND=105\n\nusage() {\n   echo \"Set a global property in the cluster with a validity timestamp.\"\n   echo \"Usage:\"\n   echo \"   $0 --acquire <lock_name> <lock_owner> <lock_ttl_in_seconds>\"\n   echo \"   $0 --release <lock_name> <lock_owner>\"\n   echo\n}\n\nlog() {\n    echo \"$(date -u): $1\" 1>&2\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\nlock_create() {\n    local name=$1\n    local data=$2\n    # cibadmin won't overwrite a key if someone else succeeded to create it concurrently\n    cibadmin --sync-call --scope crm_config --create --xml-text \"<cluster_property_set id='${name}'><nvpair id='${name}-pair' name='${name}' value='${data}'/></cluster_property_set>\" &>/dev/null\n    return $?\n}\n\nlock_update() {\n    local name=$1\n    local expected_data=$2\n    local new_data=$3\n    # we only update the lock we expect to see, so we can't update someone else's lock\n    cibadmin --sync-call --scope crm_config --modify --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" --xml-text \"<nvpair id='${name}-pair' name='${name}' value='${new_data}'/>\" &>/dev/null\n    return $?\n}\n\nlock_delete() {\n    local name=$1\n    local expected_data=$2\n    # we only delete the lock we expect to see, so we can't delete someone else's lock\n    cibadmin --sync-call --scope crm_config --delete --xpath \"//cluster_property_set/nvpair[@name='${name}' and @value='${expected_data}']/..\" &>/dev/null\n    return $?\n}\n\nlock_get() {\n    local lockname=$1\n    local res\n    local rc\n    res=$(cibadmin --query --scope crm_config --xpath \"//cluster_property_set/nvpair[@name='$lockname']\" 2>/dev/null)\n    rc=$?\n    if [ $rc -eq 0 ]; then\n        echo \"$res\" | sed -n 's/.*value=\"\\([^\"]*\\)\".*/\\1/p'\n    fi\n    return $rc\n}\n\nlock_owner() {\n    local lock=$1\n    echo \"$lock\" | cut -d':' -f1\n}\n\nlock_has_expired() {\n    local lock=$1\n    local expiry=$(echo \"$lock\" | cut -d':' -f2)\n    local now=$(date +%s)\n    test $now -ge $expiry\n}\n\n\n# Perform a lock action and restart if the CIB has been modified before\n# committing the lock action\ntry_action() {\n    local fun=$1\n    local lock=$2\n    local requester=$3\n    local args=${4:-}\n    local tries=$MAX_RETRIES\n    local rc=1\n    if [ \"$fun\" = \"lock_acquire\" ] || [ \"$fun\" = \"lock_release\" ]; then\n        log \"Try running $fun\"\n    else\n        return 2\n    fi\n    while [ $rc -ne 0 ]; do\n        $fun $lock $requester $args\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Operation $1 succeeded\"\n            return 0\n        elif [ $rc -eq 3 ]; then\n            # rc == 3 -> CIB changed before push\n            if [ $tries -eq 0 ]; then\n                log \"Failed to commit after $MAX_RETRIES retries. Bailing out.\"\n                return 2\n            else\n                log \"Failed to commit. Retrying operation.\"\n                tries=$(($tries - 1))\n            fi\n        elif [ $rc -eq 2 ]; then\n            # rc == 2 -> unrecoverable cib error (e.g. pacemaker down)\n            log \"Unexpected failure. Bailing out\"\n            return $rc\n        else\n            # rc == 1 -> lock error (not owner, lock doesn't exists)\n            return $rc\n        fi\n    done\n}\n\n# The lock mechanism uses cibadmin's atomic creation so cluster-wide\n# state coherency is guaranteed by pacemaker\nlock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc\n    local lock\n    local expiry\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -n \"$lock\" ]; then\n        lock_has_expired $lock\n        rc=$?\n        if [ $rc -eq 0 ]; then\n            log \"Lock has expired, now available for being held\"\n        else\n            # lock is still held. check whether we're the owner\n            owner=$(lock_owner $lock)\n            if [ \"$owner\" = \"$requester\" ];then\n                log \"Requester already owns the lock, acquiring attempt will just reconfigure the TTL\"\n            else\n                log \"Lock is held by someone else ($owner)\"\n                return 1\n            fi\n        fi\n    else\n        log \"Lock is not held yet\"\n    fi\n\n    # prepare the lock info\n    expiry=$(($(date +%s) + $ttl))\n\n    if [ -n \"$lock\" ]; then\n        log \"Attempting to update the lock\"\n        lock_update $lockname \"$lock\" \"$requester:$expiry\"\n        rc=$?\n    else\n        log \"Attempting to acquire the lock\"\n        lock_create $lockname \"$requester:$expiry\"\n        rc=$?\n    fi\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' acquired by '$requester', valid until $(date -d @$expiry)\"\n        return 0\n    else\n        log \"CIB changed, lock cannot be acquired\"\n        return 3\n    fi\n}\n\n\n# The lock mechanism uses the CIB's num_updates tag to implement\n# a conditional store. Cluster-wide locking is guaranteed by pacemaker\nlock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n    local lock\n    local owner\n\n    log \"Check whether the lock is already held in the CIB\"\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        log \"Could not retrieve info from the CIB\"\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        log \"Lock doesn't exist. Nothing to release\"\n        return 0\n    else\n        log \"Lock exists, check whether we're the owner\"\n        owner=$(lock_owner $lock)\n        if [ \"$owner\" != \"$requester\" ];then\n            log \"Lock is held by someone else ($owner), will not unlock\"\n            return 1\n        fi\n    fi\n\n    lock_delete $lockname \"$lock\"\n    rc=$?\n\n    if [ $rc -eq 0 ]; then\n        log \"Lock '$lockname' released by '$requester'\"\n        return 0\n    else\n        log \"CIB deletion error, lock cannot be released\"\n        return 3\n    fi\n}\n\n\n# Retrieve the owner of a lock from the CIB\n# this is a read-only operation, so no need to log debug info\nlock_get_owner() {\n    local lockname=$1\n    local rc\n    local lock\n    local owner\n\n    lock=$(lock_get $lockname)\n    rc=$?\n    if [ $rc -ne 0 ] && [ $rc -ne $CIB_ENOTFOUND ]; then\n        return 2\n    fi\n\n    if [ -z \"$lock\" ]; then\n        return 1\n    else\n        lock_owner $lock\n        return 0\n    fi\n}\n\n\nACTION=$1\nLOCKNAME=$2\nREQUESTER=$3\nTTL=${4:-60}\n\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nif [ $ACTION != \"--help\" ]; then\n    if [ -z \"$LOCKNAME\" ]; then\n        error \"You must specific a lock name\"\n    fi\n    if [ $ACTION != \"--owner\" ] && [ $ACTION != \"-o\" ]; then\n        if [ -z \"$REQUESTER\" ]; then\n            error \"You must specific a lock requester\"\n        fi\n    fi\nfi\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) try_action lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --release|-r) try_action lock_release $LOCKNAME $REQUESTER;;\n    --acquire-once|-A) lock_acquire $LOCKNAME $REQUESTER $TTL;;\n    --owner|-o) lock_get_owner $LOCKNAME;;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}, "pacemaker_mutex_restart_bundle.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_restart_bundle.sh --lock mysql galera galera-bundle Master _\n# pacemaker_mutex_restart_bundle.sh --lock ovn_dbs ovndb_servers ovn-dbs-bundle Slave Master\n\nset -u\n\nusage() {\n    echo \"Restart a clustered resource in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --lock <tripleo-service> <pcmk-resource> <pcmk-bundle> <target-state-local> <target-state-cluster>\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\npacemaker_supports_promoted() {\n    # The Promoted token is only matched in recent pacemaker versions\n    grep -wq \"<value>Promoted</value>\" /usr/share/pacemaker/resources-*.rng\n}\n\nACTION=$1\ncase $ACTION in\n    --help) usage; exit 0;;\n    --lock) ;;\n    *) error \"Unknown action '$ACTION'\";;\nesac\n\nTRIPLEO_SERVICE=$2\nLOCK_NAME=${TRIPLEO_SERVICE}-restart-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to restart resource $TRIPLEO_SERVICE\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\nRESOURCE_NAME=$3\nBUNDLE_NAME=$4\nWAIT_TARGET_LOCAL=$5\nWAIT_TARGET_ANYWHERE=${6:-_}\n\nif pacemaker_supports_promoted; then\n    WAIT_TARGET_LOCAL=$(echo \"$5\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    WAIT_TARGET_ANYWHERE=$(echo \"${6:-_}\" | sed -e 's/Master/Promoted/' -e 's/Slave/Unpromoted/')\n    promoted_role=\"Promoted\"\nelse\n    promoted_role=\"Master\"\nfi\n\n# The lock TTL should accomodate for the resource start/promote timeout\nif [ \"$RESOURCE_NAME\" != \"$BUNDLE_NAME\" ]; then\n    if [ \"$WAIT_TARGET_LOCAL\" = \"$promoted_role\" ] || [ \"$WAIT_TARGET_ANYWHERE\" = \"$promoted_role\" ]; then\n        rsc_op=\"promote\"\n    else\n        rsc_op=\"start\"\n    fi\n    # <op id=\"galera-promote-interval-0s\" interval=\"0s\" name=\"promote\" on-fail=\"block\" timeout=\"300s\"/>\n    PCMK_TTL=$(cibadmin -Q | xmllint -xpath \"string(//primitive[@id='${RESOURCE_NAME}']/operations/op[@name='${rsc_op}']/@timeout)\" - | sed 's/s$//')\n    LOCK_TTL=$((PCMK_TTL + 30))\nelse\n    # The podman RA's default start timeout\n    LOCK_TTL=90\nfi\n\nlog \"Acquire a ${LOCK_TTL}s restart lock for service $TRIPLEO_SERVICE before restarting it\"\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nrc=1\nwhile [ $rc -ne 0 ]; do\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire $LOCK_NAME $LOCK_OWNER $LOCK_TTL\n    rc=$?\n    if [ $rc != 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not acquire lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Could not acquire lock, retrying\"\n            sleep 10\n        fi\n    fi\ndone\n\nlog \"Restart the service $TRIPLEO_SERVICE locally\"\n# Reuse the local restart script in t-h-t (driven by env var TRIPLEO_MINOR_UPDATE)\nTRIPLEO_MINOR_UPDATE=true /var/lib/container-config-scripts/pacemaker_restart_bundle.sh $TRIPLEO_SERVICE $RESOURCE_NAME $BUNDLE_NAME $WAIT_TARGET_LOCAL $WAIT_TARGET_ANYWHERE\n\n# If we reached this point, always try to release the lock\nlog \"Release the restart lock for service $TRIPLEO_SERVICE\"\n/var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $LOCK_NAME $LOCK_OWNER\nrc=$?\nif [ $rc -ne 0 ] && [ $rc -ne 1 ]; then\n    error \"Could not release held lock (rc: $rc)\"\nfi\n"}, "pacemaker_mutex_shutdown.sh": {"mode": "0755", "content": "#!/usr/bin/bash\n\n# pacemaker_mutex_shutdown.sh --acquire\n# pacemaker_mutex_shutdown.sh --release\n\nset -u\n\nusage() {\n    echo \"Shutdown a cluster node in a coordinated way across the cluster\"\n    echo \"Usage:\"\n    echo \"   $0 --acquire # prevent other node from shutting down until we hold the lock\"\n    echo \"   $0 --release # release the lock, other node can compete for the shutdown lock\"\n    echo\n}\n\nlog() {\n    echo \"$(date -u): $1\"\n}\n\nerror() {\n    echo \"$(date -u): $1\" 1>&2\n    exit 1\n}\n\n# Loop until we hold the lock. The lock has a TTL, so we're guaranteed to get it eventually\nshutdown_lock_acquire() {\n    local lockname=$1\n    local requester=$2\n    local ttl=$3\n    local rc=1\n    local current_owner\n    local owner_stopped\n    local owner_rc\n\n    log \"Acquiring the shutdown lock\"\n    while [ $rc -ne 0 ]; do\n        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --acquire-once $lockname $requester $ttl\n        rc=$?\n        if [ $rc -ne 0 ]; then\n            if [ $rc -eq 2 ]; then\n                error \"Could not acquire the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n            else\n                # The lock is held by another node.\n                current_owner=$(/var/lib/container-config-scripts/pacemaker_resource_lock.sh --owner $lockname)\n                owner_rc=$?\n                if [ $owner_rc -eq 2 ]; then\n                    error \"Could not get the shutdown lock owner due to unrecoverable error (rc: $owner_rc), bailing out\"\n                fi\n                if [ $owner_rc -eq 0 ]; then\n                    # If the owner is marked as offline, that means it has shutdown and\n                    # we can clean the lock preemptively and try to acquire it.\n                    owner_stopped=$(crm_mon -1X | xmllint --xpath 'count(//nodes/node[@name=\"'${current_owner}'\" and @online=\"false\" and @unclean=\"false\"])' -)\n                    if [ \"${owner_stopped}\" = \"1\" ]; then\n                        log \"Shutdown lock held by stopped node '${current_owner}', lock can be released\"\n                        /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $current_owner\n                        continue\n                    fi\n                fi\n                log \"Shutdown lock held by another node (rc: $rc), retrying\"\n                sleep 10\n            fi\n        fi\n    done\n    log \"Shutdown lock acquired\"\n    return 0\n}\n\n\n# Release the lock if we still own it. Not owning it anymore is not fatal\nshutdown_lock_release() {\n    local lockname=$1\n    local requester=$2\n    local rc\n\n    log \"Releasing the shutdown lock\"\n    /var/lib/container-config-scripts/pacemaker_resource_lock.sh --release $lockname $requester\n    rc=$?\n    if [ $rc -ne 0 ]; then\n        if [ $rc -gt 1 ]; then\n            error \"Could not release the shutdown lock due to unrecoverable error (rc: $rc), bailing out\"\n        else\n            log \"Shutdown lock no longer held, nothing to do\"\n        fi\n    else\n        log \"Shutdown lock released\"\n    fi\n    return 0\n}\n\n\nACTION=$1\nif [ -z \"$ACTION\" ]; then\n    error \"Action must be specified\"\nfi\n\nLOCK_NAME=tripleo-shutdown-lock\nLOCK_OWNER=$(crm_node -n 2>/dev/null)\nrc=$?\nif [ $rc -ne 0 ]; then\n    if [ $rc -eq 102 ]; then\n        log \"Cluster is not running locally, no need to aquire the shutdown lock\"\n        exit 0\n    else\n        error \"Unexpected error while connecting to the cluster (rc: $rc), bailing out\"\n    fi\nfi\n\n# We start with a very high TTL, that long enough to accomodate a cluster stop.\n# As soon as the node will get offline, the other competing node will be entitled\n# to steal the lock, so they should never wait that long in practice.\nLOCK_TTL=600\n\n\ncase $ACTION in\n    --help) usage; exit 0;;\n    --acquire|-a) shutdown_lock_acquire ${LOCK_NAME} ${LOCK_OWNER} ${LOCK_TTL};;\n    --release|-r) shutdown_lock_release ${LOCK_NAME} ${LOCK_OWNER};;\n    *) error \"Invalid action\";;\nesac\nexit $?\n"}}, "docker_config": {"step_1": {"rabbitmq_bootstrap": {"start_order": 0, "image": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1", "net": "host", "privileged": false, "user": "root", "command": ["bash", "-ec", "kolla_set_configs\nif [[ -e \"/var/lib/rabbitmq/.erlang.cookie\" ]]; then rm -f /var/lib/rabbitmq/.erlang.cookie; fi\nhiera 'rabbitmq::erlang_cookie' > /var/lib/rabbitmq/.erlang.cookie\nchown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie\nchmod 400 /var/lib/rabbitmq/.erlang.cookie"], "volumes": ["/var/lib/kolla/config_files/rabbitmq.json:/var/lib/kolla/config_files/config.json:ro", "/var/lib/config-data/puppet-generated/rabbitmq:/var/lib/kolla/config_files/src:ro", "/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/var/lib/rabbitmq:/var/lib/rabbitmq:z", "/etc/puppet:/etc/puppet:ro,z"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS", "TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}}, "step_2": {"rabbitmq_wait_bundle": {"start_order": 0, "detach": false, "net": "host", "ipc": "host", "user": "root", "command": ["/container_puppet_apply.sh", "2", "file,file_line,concat,augeas,rabbitmq_policy,rabbitmq_user,rabbitmq_ready", "include tripleo::profile::pacemaker::rabbitmq_bundle", ""], "image": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1", "volumes": ["/etc/hosts:/etc/hosts:ro", "/etc/localtime:/etc/localtime:ro", "/etc/pki/ca-trust/extracted:/etc/pki/ca-trust/extracted:ro", "/etc/pki/ca-trust/source/anchors:/etc/pki/ca-trust/source/anchors:ro", "/etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro", "/etc/pki/tls/certs/ca-bundle.trust.crt:/etc/pki/tls/certs/ca-bundle.trust.crt:ro", "/etc/pki/tls/cert.pem:/etc/pki/tls/cert.pem:ro", "/dev/log:/dev/log", "/etc/ipa/ca.crt:/etc/ipa/ca.crt:ro", "/var/lib/container-config-scripts/container_puppet_apply.sh:/container_puppet_apply.sh:ro", "/etc/puppet:/tmp/puppet-etc:ro", "/usr/share/openstack-puppet/modules:/usr/share/openstack-puppet/modules:ro", "/bin/true:/bin/epmd"], "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS", "KOLLA_BOOTSTRAP": true, "TRIPLEO_DEPLOY_IDENTIFIER": "1781335725"}}}}, "metadata_settings": [{"service": "rabbitmq", "network": "internal_api", "type": "node"}], "host_prep_tasks": [{"name": "create fcontext for rabbitmq data", "community.general.sefcontext": {"target": "/var/lib/rabbitmq(/.*)?", "setype": "container_file_t", "state": "present"}}, {"name": "create persistent directories", "file": {"path": "{{ item.path }}", "state": "directory", "setype": "{{ item.setype }}", "mode": "{{ item.mode|default(omit) }}"}, "with_items": [{"path": "/var/lib/rabbitmq", "setype": "container_file_t"}, {"path": "/var/log/containers/rabbitmq", "setype": "container_file_t", "mode": "0750"}]}, {"name": "stop the Erlang port mapper on the host and make sure it cannot bind to the port used by container", "shell": "echo 'export ERL_EPMD_ADDRESS=127.0.0.1' > /etc/rabbitmq/rabbitmq-env.conf\necho 'export ERL_EPMD_PORT=4370' >> /etc/rabbitmq/rabbitmq-env.conf\nfor pid in $(pgrep epmd --ns 1 --nslist pid); do kill $pid; done\n"}], "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": "rabbitmq", "dns": "{{fqdn_internal_api}}", "principal": "rabbitmq/{{fqdn_internal_api}}@{{idm_realm}}", "run_after": "container_name=$({{container_cli}} ps --format=\\{\\{.Names\\}\\} | grep -w -E 'rabbitmq(-bundle-.*-[0-9]+)?')\nservice_crt=\"/etc/pki/tls/certs/rabbitmq.crt\"\nservice_key=\"/etc/pki/tls/private/rabbitmq.key\"\nif echo \"$container_name\" | grep -q \"^rabbitmq-bundle\"; then\n  # lp#1917868: Do not use podman cp with HA containers as they get\n  # frozen temporarily and that can make pacemaker operation fail.\n  tar -c \"$service_crt\" \"$service_key\" | {{container_cli}} exec -i \"$container_name\" tar -C / -xv\n  # no need to update the mount point, because pacemaker\n  # recreates the container when it's restarted\nelse\n  # Refresh the cert at the mount-point\n  {{container_cli}} cp $service_crt \"$container_name:/var/lib/kolla/config_files/src-tls/$service_crt\"\n  # Refresh the key at the mount-point\n  {{container_cli}} cp $service_key \"$container_name:/var/lib/kolla/config_files/src-tls/$service_key\"\n  # Copy the new cert from the mount-point to the real path\n  {{container_cli}} exec -u root \"$container_name\" cp \"/var/lib/kolla/config_files/src-tls$service_crt\" \"$service_crt\"\n  # Copy the new key from the mount-point to the real path\n  {{container_cli}} exec -u root \"$container_name\" cp \"/var/lib/kolla/config_files/src-tls$service_key\" \"$service_key\"\nfi\n# Set appropriate permissions\n{{container_cli}} exec -u root \"$container_name\" chown rabbitmq:rabbitmq \"$service_crt\"\n{{container_cli}} exec -u root \"$container_name\" chown rabbitmq:rabbitmq \"$service_key\"\n# Trigger a pem cache clear in RabbitMQ to read the new certificates\n{{container_cli}} exec \"$container_name\" rabbitmqctl eval \"ssl:clear_pem_cache().\"\n", "key_size": "2048", "ca": "ipa"}]}}]}, {"name": "RabbitMQ tag container image for pacemaker", "when": "step|int == 1", "import_role": {"name": "tripleo_container_tag"}, "vars": {"container_image": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1", "container_image_latest": "cluster.common.tag/rabbitmq:pcmklatest"}}, {"name": "RabbitMQ RPC HA Wrappers Step", "when": "step|int == 2", "block": [{"name": "Rabbitmq rpc puppet bundle", "import_role": {"name": "tripleo_ha_wrapper"}, "vars": {"tripleo_ha_wrapper_service_name": "oslo_messaging_rpc", "tripleo_ha_wrapper_resource_name": "rabbitmq", "tripleo_ha_wrapper_bundle_name": "rabbitmq-bundle", "tripleo_ha_wrapper_resource_state": "Started", "tripleo_ha_wrapper_puppet_config_volume": "rabbitmq", "tripleo_ha_wrapper_puppet_execute": "[\"Rabbitmq_policy\", \"Rabbitmq_user\"].each |String $val| { noop_resource($val) }; include ::tripleo::profile::base::pacemaker; include ::tripleo::profile::pacemaker::rabbitmq_bundle", "tripleo_ha_wrapper_puppet_tags": "pacemaker::resource::bundle,pacemaker::property,pacemaker::resource::ip,pacemaker::resource::ocf,pacemaker::constraint::order,pacemaker::constraint::colocation", "tripleo_ha_wrapper_puppet_debug": false, "tripleo_ha_wrapper_config_suffix": ".previous_run"}}]}], "external_update_tasks": [{"when": "step|int == 1", "tags": "ha_image_update", "block": [{"block": [{"name": "Get rabbitmq image from pacemaker", "become": true, "register": "xmllint_pcmk_rabbitmq_rpc_image", "shell": "xmllint --xpath \"string(//bundle[@id='rabbitmq-bundle']/podman/@image)\" /var/lib/pacemaker/cib/cib.xml"}, {"name": "Get container rabbitmq image", "set_fact": {"rabbitmq_rpc_image": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1", "rabbitmq_rpc_image_latest": "cluster.common.tag/rabbitmq:pcmklatest", "pcmk_rabbitmq_rpc_image": "{{xmllint_pcmk_rabbitmq_rpc_image.stdout}}"}}], "delegate_to": "{{ (groups[\"oslo_messaging_rpc\"] | difference(groups[\"excluded_overcloud\"]))[0] }}"}, {"name": "rabbitmq temporary pacemaker container tag in case of image switch", "become": true, "import_role": {"name": "tripleo_ha_image_update"}, "vars": {"tripleo_ha_image_update_node_names": "{{ groups[\"oslo_messaging_rpc\"] | difference(groups[\"excluded_overcloud\"]) }}", "tripleo_ha_image_update_bundle": "rabbitmq-bundle", "tripleo_ha_image_update_new_image": "{{rabbitmq_rpc_image_latest}}", "tripleo_ha_image_update_old_image": "{{pcmk_rabbitmq_rpc_image}}"}, "when": ["(pcmk_rabbitmq_rpc_image != \"\")", "(pcmk_rabbitmq_rpc_image != rabbitmq_rpc_image_latest)"]}]}], "update_tasks": [{"block": [{"name": "Get rabbitmq image from pacemaker", "become": true, "register": "xmllint_pcmk_rabbitmq_rpc_image", "shell": "xmllint --xpath \"string(//bundle[@id='rabbitmq-bundle']/podman/@image)\" /var/lib/pacemaker/cib/cib.xml"}, {"name": "Get container rabbitmq image", "set_fact": {"rabbitmq_rpc_image": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1", "rabbitmq_rpc_image_latest": "cluster.common.tag/rabbitmq:pcmklatest", "pcmk_rabbitmq_rpc_image": "{{xmllint_pcmk_rabbitmq_rpc_image.stdout}}"}}], "when": "(step|int == 0 or step|int == 2)"}, {"name": "Check for update of rabbitmq container image name", "when": "step|int == 0", "assert": {"that": "pcmk_rabbitmq_rpc_image == rabbitmq_rpc_image_latest", "fail_msg": "rabbitmq image change detected, run overcloud external-update --tags ha_image_update first"}}, {"name": "Tear-down non-HA rabbitmq container", "when": ["step|int == 1"], "block": [{"name": "Remove non-HA rabbitmq container", "include_role": {"name": "tripleo_container_rm"}, "vars": {"tripleo_container_cli": "{{ container_cli }}", "tripleo_containers_to_rm": ["rabbitmq"]}}]}, {"name": "Rabbitmq fetch and retag container image for pacemaker", "when": "step|int == 2", "block": [{"name": "Retag pcmklatest to latest rabbitmq image", "include_role": {"name": "tripleo_container_tag"}, "vars": {"container_image": "{{rabbitmq_rpc_image}}", "container_image_latest": "{{rabbitmq_rpc_image_latest}}"}}]}], "post_update_tasks": [{"name": "Rabbitmq rpc bundle post update", "when": "step|int == 1", "block": [{"name": "Rabbitmq rpc puppet bundle", "import_role": {"name": "tripleo_ha_wrapper"}, "vars": {"tripleo_ha_wrapper_service_name": "oslo_messaging_rpc", "tripleo_ha_wrapper_resource_name": "rabbitmq", "tripleo_ha_wrapper_bundle_name": "rabbitmq-bundle", "tripleo_ha_wrapper_resource_state": "Started", "tripleo_ha_wrapper_puppet_config_volume": "rabbitmq", "tripleo_ha_wrapper_puppet_execute": "[\"Rabbitmq_policy\", \"Rabbitmq_user\"].each |String $val| { noop_resource($val) }; include ::tripleo::profile::base::pacemaker; include ::tripleo::profile::pacemaker::rabbitmq_bundle", "tripleo_ha_wrapper_puppet_tags": "pacemaker::resource::bundle,pacemaker::property,pacemaker::resource::ip,pacemaker::resource::ocf,pacemaker::constraint::order,pacemaker::constraint::colocation", "tripleo_ha_wrapper_puppet_debug": false, "tripleo_ha_wrapper_config_suffix": ".previous_run"}}], "vars": {"tripleo_ha_wrapper_minor_update": true}}], "upgrade_tasks": [{"name": "Tear-down non-HA rabbitmq container", "when": ["step|int == 0"], "block": [{"name": "Remove non-HA rabbitmq container", "include_role": {"name": "tripleo_container_rm"}, "vars": {"tripleo_container_cli": "{{ container_cli }}", "tripleo_containers_to_rm": ["rabbitmq"]}}]}, {"name": "Prepare switch of rabbitmq image name", "when": ["step|int == 0"], "block": [{"name": "Get rabbitmq image id currently used by pacemaker", "shell": "pcs resource config rabbitmq-bundle | grep -Eo 'image=[^ ]+' | awk -F= '{print $2;}'", "register": "rabbitmq_rpc_image_current_res", "failed_when": false}, {"name": "Image facts for rabbitmq", "set_fact": {"rabbitmq_rpc_image_latest": "cluster.common.tag/rabbitmq:pcmklatest", "rabbitmq_rpc_image_current": "{{rabbitmq_rpc_image_current_res.stdout}}"}}, {"name": "Temporarily tag the current rabbitmq image id with the upgraded image name", "import_role": {"name": "tripleo_container_tag"}, "vars": {"container_image": "{{rabbitmq_rpc_image_current}}", "container_image_latest": "{{rabbitmq_rpc_image_latest}}", "pull_image": false}, "when": ["rabbitmq_rpc_image_current != ''", "rabbitmq_rpc_image_current != rabbitmq_rpc_image_latest"]}, {"name": "Create rabbitmq_rpc retag statefile", "file": {"path": "/var/lib/tripleo/rabbitmq_rpc_needs_retag", "state": "touch"}, "when": ["rabbitmq_rpc_image_current != ''", "rabbitmq_rpc_image_current != rabbitmq_rpc_image_latest"]}]}, {"name": "Update rabbitmq-bundle pcs resource bundle for new container image", "when": ["step|int == 1"], "block": [{"name": "set is_rpc_rabbitmq_bootstrap_node fact", "set_fact": "is_rpc_rabbitmq_bootstrap_node={{oslo_messaging_rpc_short_bootstrap_node_name|lower == ansible_facts['hostname']|lower}}"}, {"name": "Check for rabbitmq_rpc retag statefile", "stat": {"path": "/var/lib/tripleo/rabbitmq_rpc_needs_retag"}, "register": "rabbitmq_rpc_retag_state_file"}]}, {"name": "Update rabbitmq-bundle pcs resource bundle for new container image", "when": ["step|int == 1", "is_rpc_rabbitmq_bootstrap_node|bool", "rabbitmq_rpc_retag_state_file.stat.exists|bool"], "block": [{"name": "Disable the rabbitmq cluster resource before container upgrade", "pacemaker_resource": {"resource": "rabbitmq-bundle", "state": "disable", "wait_for_resource": true}, "register": "output", "retries": 5, "until": "output.rc == 0"}, {"name": "Check rabbitmq logging configuration in pacemaker", "command": "cibadmin --query --xpath \"//storage-mapping[@id='rabbitmq-log']\"", "failed_when": false, "register": "rabbitmq_logs_moved"}, {"name": "Add a bind mount for logging in the rabbitmq bundle", "when": "rabbitmq_logs_moved.rc == 6", "command": "pcs resource bundle update rabbitmq-bundle storage-map add id=rabbitmq-log source-dir=/var/log/containers/rabbitmq target-dir=/var/log/rabbitmq options=rw"}, {"name": "Update the rabbitmq bundle to use the new container image name", "command": "pcs resource bundle update rabbitmq-bundle container image={{rabbitmq_rpc_image_latest}}"}, {"name": "Enable the rabbitmq cluster resource", "pacemaker_resource": {"resource": "rabbitmq-bundle", "state": "enable", "wait_for_resource": true}, "register": "output", "retries": 5, "until": "output.rc == 0"}]}, {"name": "Check for rabbitmq_rpc retag statefile", "when": ["step|int == 3"], "stat": {"path": "/var/lib/tripleo/rabbitmq_rpc_needs_retag"}, "register": "rabbitmq_rpc_retag_state_file"}, {"name": "Retag rabbitmq-bundle container image", "when": ["step|int == 3", "rabbitmq_rpc_retag_state_file.stat.exists|bool"], "block": [{"name": "Disable the rabbitmq cluster resource before container upgrade", "pacemaker_resource": {"resource": "rabbitmq-bundle", "state": "disable", "wait_for_resource": true}, "register": "output", "retries": 5, "until": "output.rc == 0"}, {"name": "Retag the pacemaker image if containerized", "block": [{"block": [{"name": "Get rabbitmq image from pacemaker", "become": true, "register": "xmllint_pcmk_rabbitmq_rpc_image", "shell": "xmllint --xpath \"string(//bundle[@id='rabbitmq-bundle']/podman/@image)\" /var/lib/pacemaker/cib/cib.xml"}, {"name": "Get container rabbitmq image", "set_fact": {"rabbitmq_rpc_image": "registry.redhat.io/rhosp-rhel9/openstack-rabbitmq:17.1", "rabbitmq_rpc_image_latest": "cluster.common.tag/rabbitmq:pcmklatest", "pcmk_rabbitmq_rpc_image": "{{xmllint_pcmk_rabbitmq_rpc_image.stdout}}"}}]}, {"block": [{"name": "Retag pcmklatest to latest rabbitmq image", "include_role": {"name": "tripleo_container_tag"}, "vars": {"container_image": "{{rabbitmq_rpc_image}}", "container_image_latest": "{{rabbitmq_rpc_image_latest}}"}}]}]}, {"name": "Enable the rabbitmq cluster resource", "pacemaker_resource": {"resource": "rabbitmq-bundle", "state": "enable", "wait_for_resource": true}, "register": "output", "retries": 5, "until": "output.rc == 0"}, {"name": "Remove rabbitmq_rpc retag statefile", "file": {"path": "/var/lib/tripleo/rabbitmq_rpc_needs_retag", "state": "absent"}}]}]}, "tuple:('role_data', 'service_names')": null, "tuple:('role_data', 'config_settings')": {"rabbitmq::file_limit": 65536, "rabbitmq::default_user": "guest", "rabbitmq::default_pass": "CXYUjEO3wxDmzZtKlwuHEqtzC", "rabbit_ipv6": false, "rabbitmq::delete_guest_user": false, "rabbitmq::wipe_db_on_cookie_change": true, "rabbitmq::port": 5672, "rabbitmq::loopback_users": [], "rabbitmq::tcp_backlog": 4096, "rabbitmq::repos_ensure": false, "rabbitmq::tcp_keepalive": true, "rabbitmq_environment": {"LANG": "en_US.UTF-8", "LC_ALL": "en_US.UTF-8", "NODE_PORT": "", "NODE_IP_ADDRESS": "", "RABBITMQ_NODENAME": "rabbit@%{hiera('fqdn_internal_api')}", "RABBITMQ_USE_LONGNAME": "true", "RABBITMQ_CTL_DIST_PORT_MIN": "25673", "RABBITMQ_CTL_DIST_PORT_MAX": "25683", "export ERL_EPMD_ADDRESS": "%{hiera('rabbitmq::interface')}"}, "tripleo::profile::base::rabbitmq::additional_erl_args": "'+sbwt none +sbwtdcpu none +sbwtdio none'", "rabbitmq_kernel_variables": {"inet_dist_listen_min": "25672", "inet_dist_listen_max": "25672", "net_ticktime": 15}, "rabbitmq_config_variables": {"cluster_partition_handling": "ignore", "queue_master_locator": "<<\"min-masters\">>"}, "rabbitmq::config_additional_variables": {"lager": "[{crash_log_count, 0}, { crash_log_date, \"\"}, { crash_log_size, 0 }]"}, "rabbitmq::erlang_cookie": "mpHJWwKkkBAv6EusO06i", "rabbitmq::interface": "%{hiera('internal_api')}", "rabbitmq::nr_ha_queues": 0, "rabbitmq::ssl": true, "rabbitmq::ssl_erl_dist": true, "rabbitmq::ssl_port": 5672, "rabbitmq::ssl_depth": 1, "rabbitmq::ssl_only": true, "rabbitmq::ssl_interface": "%{hiera('internal_api')}", "tripleo::profile::base::rabbitmq::enable_internal_tls": true, "tripleo::profile::base::rabbitmq::fips_mode": false, "rabbitmq::collect_statistics_interval": 30000, "tripleo::rabbitmq::service_certificate": "/etc/pki/tls/certs/rabbitmq.crt", "tripleo::profile::base::rabbitmq::certificate_specs": {"service_certificate": "/etc/pki/tls/certs/rabbitmq.crt", "service_key": "/etc/pki/tls/private/rabbitmq.key"}, "rabbitmq::ssl_versions": ["tlsv1.2"], "rabbitmq::admin_enable": false, "rabbitmq::management_enable": true, "rabbitmq::use_config_file_for_plugins": true, "rabbitmq::management_ip_address": "127.0.0.1", "rabbitmq::management_port": 15672, "rabbitmq::config_management_variables": {"rates_mode": "none"}, "rabbitmq::ssl_cacert": "/etc/ipa/ca.crt", "rabbitmq::ssl_management_cacert": "/etc/ipa/ca.crt", "tripleo::certmonger::rabbitmq::postsave_cmd": "true", "rabbitmq::service_manage": false, "tripleo::profile::pacemaker::rabbitmq_bundle::rabbitmq_docker_image": "cluster.common.tag/rabbitmq:pcmklatest", "tripleo::profile::pacemaker::rabbitmq_bundle::control_port": 3122, "tripleo::profile::pacemaker::rabbitmq_bundle::container_backend": "podman", "tripleo::profile::pacemaker::rabbitmq_bundle::force_ocf": true}, "OS::stack_id": "arn:openstack:heat::admin:stacks/standalone-StandaloneServiceChain-crsk2ghna6xy-ServiceChain-wkba2mh25u55-47-ladweh3urreb/c8d71805-bd82-4814-bb1b-8c983215297d"}


