heat_template_version: rocky description: > OpenStack containerized Redis services parameters: ContainerRedisImage: description: image type: string ContainerRedisConfigImage: description: The container image to use for the redis config_volume type: string ClusterCommonTag: default: false description: When set to false, a pacemaker service is configured to use a floating tag for its container image name, e.g. 'REGISTRY/NAMESPACE/IMAGENAME:pcmklatest'. When set to true, the service uses a floating prefix as well, e.g. 'cluster.common.tag/IMAGENAME:pcmklatest'. type: boolean ClusterFullTag: default: false description: When set to true, the pacemaker service uses a fully constant tag for its container image name, e.g. 'cluster.common.tag/SERVICENAME:pcmklatest'. type: boolean EndpointMap: default: {} description: Mapping of service endpoint -> protocol. Typically set via parameter_defaults in the resource registry. type: json ServiceData: default: {} description: Dictionary packing service data type: json ServiceNetMap: default: {} description: Mapping of service_name -> network name. Typically set via parameter_defaults in the resource registry. This mapping overrides those in ServiceNetMapDefaults. type: json DefaultPasswords: default: {} type: json RoleName: default: '' description: Role name on which the service is applied type: string RoleParameters: default: {} description: Parameters specific to the role type: json ConfigDebug: default: false description: Whether to run config management (e.g. Puppet) in debug mode. type: boolean EnableInternalTLS: type: boolean default: false RedisIPv6: default: false description: Enable IPv6 in Redis type: boolean ContainerCli: type: string default: 'podman' description: CLI tool used to manage containers. constraints: - allowed_values: ['docker', 'podman'] DeployIdentifier: default: '' type: string description: > Setting this to a unique value will re-run any deployment tasks which perform configuration on a Heat stack-update. parameter_groups: - label: deprecated description: | The following parameters are deprecated and will be removed. They should not be relied on for new deployments. If you have concerns regarding deprecated parameters, please contact the TripleO development team on IRC or the OpenStack mailing list. parameters: - RedisIPv6 conditions: internal_tls_enabled: {equals: [{get_param: EnableInternalTLS}, true]} docker_enabled: {equals: [{get_param: ContainerCli}, 'docker']} common_tag_enabled: {equals: [{get_param: ClusterCommonTag}, true]} common_tag_full: {equals: [{get_param: ClusterFullTag}, true]} is_ipv6: equals: - {get_param: [ServiceData, net_ip_version_map, {get_param: [ServiceNetMap, RedisNetwork]}]} - 6 resources: ContainersCommon: type: ../containers-common.yaml RedisBase: type: ./redis-container-puppet.yaml properties: EndpointMap: {get_param: EndpointMap} ServiceData: {get_param: ServiceData} ServiceNetMap: {get_param: ServiceNetMap} DefaultPasswords: {get_param: DefaultPasswords} RoleName: {get_param: RoleName} RoleParameters: {get_param: RoleParameters} outputs: role_data: description: Role data for the Redis API role. value: service_name: redis firewall_rules: '108 redis-bundle': dport: - 3124 - 6379 - 26379 config_settings: map_merge: - {get_attr: [RedisBase, role_data, config_settings]} - redis::service_manage: false redis::notify_service: false redis::managed_by_cluster_manager: true tripleo::profile::pacemaker::database::redis_bundle::redis_docker_image: &redis_image_pcmklatest if: - common_tag_full - "cluster.common.tag/redis:pcmklatest" - yaql: data: if: - common_tag_enabled - yaql: data: {get_param: ContainerRedisImage} expression: concat("cluster.common.tag/", $.data.rightSplit(separator => "/", maxSplits => 1)[1]) - {get_param: ContainerRedisImage} expression: concat($.data.rightSplit(separator => ":", maxSplits => 1)[0], ":pcmklatest") tripleo::profile::pacemaker::database::redis_bundle::control_port: 3124 tripleo::profile::pacemaker::database::redis_bundle::container_backend: {get_param: ContainerCli} tripleo::stunnel::manage_service: false tripleo::stunnel::foreground: 'yes' tripleo::profile::pacemaker::database::redis_bundle::tls_proxy_bind_ip: str_replace: template: "%{hiera('$NETWORK')}" params: $NETWORK: {get_param: [ServiceNetMap, RedisNetwork]} tripleo::profile::pacemaker::database::redis_bundle::tls_proxy_fqdn: str_replace: template: "%{hiera('fqdn_$NETWORK')}" params: $NETWORK: {get_param: [ServiceNetMap, RedisNetwork]} tripleo::profile::pacemaker::database::redis_bundle::tls_proxy_port: 6379 tripleo::profile::pacemaker::database::redis::tls_proxy_bind_ip: str_replace: template: "%{hiera('$NETWORK')}" params: $NETWORK: {get_param: [ServiceNetMap, RedisNetwork]} tripleo::profile::pacemaker::database::redis::tls_proxy_fqdn: str_replace: template: "%{hiera('fqdn_$NETWORK')}" params: $NETWORK: {get_param: [ServiceNetMap, RedisNetwork]} tripleo::profile::pacemaker::database::redis::tls_proxy_port: 6379 - if: - internal_tls_enabled - redis::extra_config_file: "/etc/redis-tls.conf" tripleo::profile::pacemaker::database::redis_bundle::extra_config_file: "/etc/redis-tls.conf" tripleo::profile::pacemaker::database::redis_bundle::tls_tunnel_base_port: 6660 tripleo::profile::pacemaker::database::redis_bundle::tls_tunnel_local_name: if: - is_ipv6 - '::1' - '127.0.0.1' - {} service_config_settings: {get_attr: [RedisBase, role_data, service_config_settings]} # BEGIN DOCKER SETTINGS puppet_config: config_volume: 'redis' # NOTE: we need the exec tag to copy /etc/redis.conf.puppet to # /etc/redis.conf # https://github.com/arioch/puppet-redis/commit/1c004143223e660cbd433422ff8194508aab9763 puppet_tags: 'exec' step_config: | include tripleo::profile::pacemaker::database::redis_bundle config_image: &redis_config_image {get_param: ContainerRedisConfigImage} kolla_config: /var/lib/kolla/config_files/redis.json: command: /usr/sbin/pacemaker_remoted config_files: - dest: /etc/libqb/force-filesystem-sockets source: /dev/null owner: root perm: '0644' - source: "/var/lib/kolla/config_files/src/*" dest: "/" merge: true preserve_properties: true optional: true permissions: - path: /run/redis owner: redis:redis recurse: true - path: /var/lib/redis owner: redis:redis recurse: true - path: /var/log/redis owner: redis:redis recurse: true /var/lib/kolla/config_files/redis_tls_proxy.json: command: # Note: kolla doesn't process string arguments as expected, # so use a bash idiom to achieve the same result str_replace: template: bash -c $* -- eval /wait-port-and-run.sh $(hiera fqdn_$NETWORK) 6379 stunnel /etc/stunnel/stunnel.conf params: $NETWORK: {get_param: [ServiceNetMap, RedisNetwork]} 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 optional: true preserve_properties: true permissions: - path: /etc/pki/tls/certs/redis.crt owner: root:root perm: '0600' optional: true - path: /etc/pki/tls/private/redis.key owner: root:root perm: '0600' optional: true container_config_scripts: {get_attr: [ContainersCommon, container_config_scripts]} docker_config: step_1: if: - internal_tls_enabled - redis_tls_proxy: start_order: 0 image: {get_param: ContainerRedisImage} net: host user: root restart: always volumes: list_concat: - {get_attr: [ContainersCommon, volumes]} - - /var/lib/kolla/config_files/redis_tls_proxy.json:/var/lib/kolla/config_files/config.json:ro - /var/lib/config-data/puppet-generated/redis:/var/lib/kolla/config_files/src:ro - /etc/pki/tls/certs/redis.crt:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/redis.crt:ro - /etc/pki/tls/private/redis.key:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/redis.key:ro - /var/lib/container-config-scripts/wait-port-and-run.sh:/wait-port-and-run.sh:ro environment: KOLLA_CONFIG_STRATEGY: COPY_ALWAYS - {} metadata_settings: get_attr: [RedisBase, role_data, metadata_settings] 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/lib/redis, 'setype': container_file_t } - { 'path': /var/log/containers/redis, 'setype': container_file_t, 'mode': '0750' } - { 'path': /run/redis, 'setype': container_file_t } - name: ensure /run/redis is present upon reboot copy: dest: /etc/tmpfiles.d/run-redis.conf content: | d /run/redis 0755 root root - - deploy_steps_tasks: - name: Redis tag container image for pacemaker when: step|int == 1 import_role: name: tripleo_container_tag vars: container_image: {get_param: ContainerRedisImage} container_image_latest: *redis_image_pcmklatest - name: Redis HA Wrappers Step when: step|int == 2 block: &redis_puppet_bundle - name: Redis puppet bundle import_role: name: tripleo_ha_wrapper vars: tripleo_ha_wrapper_service_name: redis tripleo_ha_wrapper_resource_name: redis tripleo_ha_wrapper_bundle_name: redis-bundle tripleo_ha_wrapper_resource_state: Slave Master tripleo_ha_wrapper_puppet_config_volume: redis tripleo_ha_wrapper_puppet_execute: 'include ::tripleo::profile::base::pacemaker; include ::tripleo::profile::pacemaker::database::redis_bundle' tripleo_ha_wrapper_puppet_tags: 'pacemaker::resource::bundle,pacemaker::property,pacemaker::resource::ocf,pacemaker::constraint::order,pacemaker::constraint::colocation' tripleo_ha_wrapper_puppet_debug: {get_param: ConfigDebug} update_tasks: - name: redis_pacemaker_puppet_tmpfile_cleanup when: step|int == 1 block: &redis_pacemaker_puppet_tmpfile_cleanup - name: Clean old tmpfile configuration file: path: /etc/tmpfiles.d/var-run-redis.conf state: absent - name: Tear-down non-HA redis container when: - step|int == 1 block: &redis_teardown_nonha - name: Remove non-HA redis container include_role: name: tripleo_container_rm vars: tripleo_container_cli: "{{ container_cli }}" tripleo_containers_to_rm: - redis - name: Redis fetch and retag container image for pacemaker when: step|int == 2 block: &redis_fetch_retag_container_tasks - name: Get container redis image set_fact: redis_image: {get_param: ContainerRedisImage} redis_image_latest: *redis_image_pcmklatest - name: Pull latest redis images command: "{{container_cli}} pull {{redis_image}}" register: result retries: 3 delay: 3 until: result.rc == 0 - name: Get previous redis image id shell: "{{container_cli}} inspect --format '{{'{{'}}.Id{{'}}'}}' {{redis_image_latest}}" register: old_redis_image_id failed_when: false - name: Get new redis image id shell: "{{container_cli}} inspect --format '{{'{{'}}.Id{{'}}'}}' {{redis_image}}" register: new_redis_image_id - name: Retag pcmklatest to latest redis image include_role: name: tripleo_container_tag vars: container_image: "{{redis_image}}" container_image_latest: "{{redis_image_latest}}" when: - old_redis_image_id.stdout != new_redis_image_id.stdout post_update_tasks: - name: Redis bundle post update when: step|int == 1 block: *redis_puppet_bundle vars: tripleo_ha_wrapper_minor_update: true upgrade_tasks: - name: redis_pacemaker_puppet_tmpfile_cleanup when: step|int == 1 block: *redis_pacemaker_puppet_tmpfile_cleanup - name: Tear-down non-HA redis container when: - step|int == 0 block: *redis_teardown_nonha - name: Prepare switch of redis image name when: - step|int == 0 block: - name: Get redis image id currently used by pacemaker shell: "pcs resource config redis-bundle | grep -Eo 'image=[^ ]+' | awk -F= '{print $2;}'" register: redis_image_current_res failed_when: false - name: Image facts for redis set_fact: redis_image_latest: *redis_image_pcmklatest redis_image_current: "{{redis_image_current_res.stdout}}" - name: Temporarily tag the current redis image id with the upgraded image name import_role: name: tripleo_container_tag vars: container_image: "{{redis_image_current}}" container_image_latest: "{{redis_image_latest}}" pull_image: false when: - redis_image_current != '' - redis_image_current != redis_image_latest # During an OS Upgrade, the cluster may not exist so we use # the shell module instead. # TODO(odyssey4me): # Fix the pacemaker_resource module to handle the exception # for a non-existant cluster more gracefully. - name: Check redis cluster resource status shell: pcs resource config redis-bundle failed_when: false changed_when: false register: redis_pcs_res_result - name: Set upgrade redis facts set_fact: redis_pcs_res: "{{redis_pcs_res_result.rc == 0}}" is_redis_bootstrap_node: "{{redis_short_bootstrap_node_name|lower == ansible_facts['hostname']|lower}}" - name: Update redis-bundle pcs resource bundle for new container image when: - step|int == 1 - is_redis_bootstrap_node|bool - redis_pcs_res|bool - redis_image_current != redis_image_latest block: - name: Disable the redis cluster resource before container upgrade pacemaker_resource: resource: redis-bundle state: disable wait_for_resource: true register: output retries: 5 until: output.rc == 0 - name: Move redis logging to /var/log/containers block: - name: Check redis logging configuration in pacemaker command: cibadmin --query --xpath "//storage-mapping[@id='redis-log' and @source-dir='/var/log/containers/redis']" failed_when: false register: redis_logs_moved - name: Change redis logging configuration in pacemaker # rc == 6 means the configuration doesn't exist in the CIB when: redis_logs_moved.rc == 6 block: - name: Remove old bind mount for logging in the redis bundle command: pcs resource bundle update redis-bundle storage-map remove redis-log - name: Add a bind mount for logging in the redis bundle command: pcs resource bundle update redis-bundle storage-map add id=redis-log source-dir=/var/log/containers/redis target-dir=/var/log/redis options=rw - name: Update the redis bundle to use the new container image name command: "pcs resource bundle update redis-bundle container image={{redis_image_latest}}" - name: Create hiera data to upgrade redis in a stepwise manner. when: - step|int == 1 - cluster_recreate|bool block: - name: set redis upgrade node facts in a single-node environment set_fact: redis_short_node_names_upgraded: "{{ redis_short_node_names }}" cacheable: no when: groups['redis'] | length <= 1 - name: set redis upgrade node facts from the limit option set_fact: redis_short_node_names_upgraded: "{{ redis_short_node_names_upgraded|default([]) + [item.split('.')[0]] }}" cacheable: no when: - groups['redis'] | length > 1 - item.split('.')[0] in ansible_limit.split(':') loop: "{{ redis_short_node_names | default([]) }}" - fail: msg: > You can't upgrade redis without staged upgrade. You need to use the limit option in order to do so. when: >- redis_short_node_names_upgraded is not defined or redis_short_node_names_upgraded | length == 0 - debug: msg: "Prepare redis upgrade for {{ redis_short_node_names_upgraded }}" - name: remove redis init container on upgrade-scaleup to force re-init include_role: name: tripleo_container_rm vars: tripleo_containers_to_rm: - redis_init_bundle when: - redis_short_node_names_upgraded | length > 1 - name: add the redis short name to hiera data for the upgrade. include_role: name: tripleo_upgrade_hiera tasks_from: set.yml vars: tripleo_upgrade_key: redis_short_node_names_override tripleo_upgrade_value: "{{redis_short_node_names_upgraded}}" - name: remove the extra hiera data needed for the upgrade. include_role: name: tripleo_upgrade_hiera tasks_from: remove.yml vars: tripleo_upgrade_key: redis_short_node_names_override when: redis_short_node_names_upgraded | length == redis_short_node_names | length - name: Retag the pacemaker image if containerized when: - step|int == 3 block: *redis_fetch_retag_container_tasks