{"heat_template_version": "wallaby", "description": "MySQL service deployment with pacemaker bundle\n", "parameters": {"ContainerMysqlImage": {"description": "image", "type": "string", "tags": ["role_specific"]}, "ContainerMysqlConfigImage": {"description": "The container image to use for the mysql config_volume", "type": "string", "tags": ["role_specific"]}, "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": true, "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. Use parameter_merge_strategies to merge it with the defaults.", "type": "json"}, "MysqlRootPassword": {"type": "string", "hidden": true, "default": ""}, "MysqlClustercheckPassword": {"type": "string", "hidden": true}, "MysqlUpgradePersist": {"type": "boolean", "default": false}, "MysqlUpgradeTransfer": {"type": "boolean", "default": true}, "RoleName": {"default": "", "description": "Role name on which the service is applied", "type": "string"}, "RoleParameters": {"default": {}, "description": "Parameters specific to the role", "type": "json"}, "EnableInternalTLS": {"type": "boolean", "default": false}, "InternalTLSCAFile": {"default": "/etc/ipa/ca.crt", "type": "string", "description": "Specifies the default CA cert to use if TLS is used for services in the internal network."}, "ConfigDebug": {"default": false, "description": "Whether to run config management (e.g. Puppet) in debug mode.", "type": "boolean"}, "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.\n"}, "ContainerCli": {"type": "string", "default": "podman", "description": "CLI tool used to manage containers.", "constraints": [{"allowed_values": ["docker", "podman"]}]}, "MysqlGaleraSSTMethod": {"type": "string", "default": "rsync", "description": "Method used by galera to perform State Snapshot Transfers", "constraints": [{"allowed_values": ["rsync", "mariabackup"]}]}, "MysqlMariabackupUser": {"type": "string", "default": "mariabackup", "description": "When MysqlGaleraSSTMethod is set to mariabackup, the name of the database user that executes the SST."}, "MysqlMariabackupPassword": {"type": "string", "hidden": true, "description": "When MysqlGaleraSSTMethod is set to mariabackup, the password of the database user that executes the SST."}, "MysqlGaleraSSLCipher": {"type": "string", "default": "AES128-SHA256", "description": "Symmetric cipher to use."}}, "resources": {"ContainersCommon": {"type": "file:///usr/share/openstack-tripleo-heat-templates/deployment/containers-common.yaml"}, "MysqlBase": {"type": "file:///usr/share/openstack-tripleo-heat-templates/deployment/database/mysql-base.yaml", "properties": {"EndpointMap": {"get_param": "EndpointMap"}, "ServiceData": {"get_param": "ServiceData"}, "ServiceNetMap": {"get_param": "ServiceNetMap"}, "RoleName": {"get_param": "RoleName"}, "RoleParameters": {"get_param": "RoleParameters"}}}, "RoleParametersValue": {"type": "OS::Heat::Value", "properties": {"type": "json", "value": {"map_replace": [{"map_replace": [{"ContainerMysqlImage": "ContainerMysqlImage", "ContainerMysqlConfigImage": "ContainerMysqlConfigImage"}, {"values": {"get_param": ["RoleParameters"]}}]}, {"values": {"ContainerMysqlImage": {"get_param": "ContainerMysqlImage"}, "ContainerMysqlConfigImage": {"get_param": "ContainerMysqlConfigImage"}}}]}}}}, "conditions": {"docker_enabled": {"equals": [{"get_param": "ContainerCli"}, "docker"]}}, "outputs": {"role_data": {"description": "Containerized service MySQL using composable services.", "value": {"service_name": {"get_attr": ["MysqlBase", "role_data", "service_name"]}, "firewall_rules": {"104 mysql galera-bundle": {"dport": [873, 3123, 3306, 4444, 4567, 4568, 9200]}}, "firewall_frontend_rules": {"100 mysql_haproxy": {"dport": [3306]}}, "config_settings": {"map_merge": [{"get_attr": ["MysqlBase", "role_data", "config_settings"]}, {"tripleo::profile::pacemaker::database::mysql::bind_address": {"str_replace": {"template": "%{hiera('fqdn_$NETWORK')}", "params": {"$NETWORK": {"get_param": ["ServiceNetMap", "MysqlNetwork"]}}}}, "tripleo::profile::pacemaker::database::mysql::gmcast_listen_addr": {"str_replace": {"template": "%{hiera('$NETWORK')}", "params": {"$NETWORK": {"get_param": ["ServiceNetMap", "MysqlNetwork"]}}}}, "tripleo::profile::pacemaker::database::mysql::ca_file": {"get_param": "InternalTLSCAFile"}, "tripleo::profile::pacemaker::database::mysql_bundle::mysql_docker_image": {"if": [{"get_param": "ClusterFullTag"}, "cluster.common.tag/mariadb:pcmklatest", {"yaql": {"data": {"if": [{"get_param": "ClusterCommonTag"}, {"yaql": {"data": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "expression": "concat(\"cluster.common.tag/\", $.data.rightSplit(separator => \"/\", maxSplits => 1)[1])"}}, {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}]}, "expression": "concat($.data.rightSplit(separator => \":\", maxSplits => 1)[0], \":pcmklatest\")"}}]}, "tripleo::profile::pacemaker::database::mysql_bundle::control_port": 3123, "tripleo::profile::pacemaker::database::mysql_bundle::container_backend": {"get_param": "ContainerCli"}, "tripleo::profile::pacemaker::database::mysql_bundle::bind_address": {"str_replace": {"template": "%{hiera('fqdn_$NETWORK')}", "params": {"$NETWORK": {"get_param": ["ServiceNetMap", "MysqlNetwork"]}}}}, "tripleo::profile::pacemaker::database::mysql_bundle::ca_file": {"if": [{"get_param": "EnableInternalTLS"}, {"get_param": "InternalTLSCAFile"}]}, "tripleo::profile::pacemaker::database::mysql_bundle::sst_method": {"get_param": "MysqlGaleraSSTMethod"}, "tripleo::profile::pacemaker::database::mysql_bundle::mariabackup_user": {"get_param": "MysqlMariabackupUser"}, "tripleo::profile::pacemaker::database::mysql_bundle::mariabackup_password": {"get_param": "MysqlMariabackupPassword"}, "tripleo::profile::pacemaker::database::mysql_bundle::force_ocf": true, "tripleo::profile::pacemaker::database::mysql_bundle::gcomm_cipher": {"get_param": "MysqlGaleraSSLCipher"}}]}, "puppet_config": {"config_volume": "mysql", "puppet_tags": "file", "step_config": {"list_join": ["\n", ["['Mysql_datadir', 'Mysql_user', 'Mysql_database', 'Mysql_grant', 'Mysql_plugin'].each |String $val| { noop_resource($val) }", "exec {'wait-for-settle': command => '/bin/true' }", "include tripleo::profile::pacemaker::database::mysql_bundle"]]}, "config_image": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlConfigImage"]}}, "kolla_config": {"/var/lib/kolla/config_files/mysql.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}, {"source": "/var/lib/kolla/config_files/src-tls/*", "dest": "/", "merge": true, "optional": true, "preserve_properties": true}], "permissions": [{"path": "/var/log/mysql", "owner": "mysql:mysql", "recurse": true}, {"path": "/etc/pki/tls/certs/mysql.crt", "owner": "mysql:mysql", "perm": "0600", "optional": true}, {"path": "/etc/pki/tls/private/mysql.key", "owner": "mysql:mysql", "perm": "0600", "optional": true}]}}, "container_config_scripts": {"get_attr": ["ContainersCommon", "container_config_scripts"]}, "docker_config": {"step_1": {"mysql_data_ownership": {"start_order": 0, "detach": false, "image": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "net": "host", "user": "root", "command": ["chown", "-R", "mysql:", "/var/lib/mysql"], "volumes": ["/var/lib/mysql:/var/lib/mysql:z"]}, "mysql_bootstrap": {"start_order": 1, "detach": false, "image": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "net": "host", "user": "root", "command": ["bash", "-ec", {"list_join": ["\n", ["if [ -e /var/lib/mysql/mysql ]; then exit 0; fi", "echo -e \"\\n[mysqld]\\nwsrep_provider=none\" >> /etc/my.cnf", "export DB_ROOT_PASSWORD=$(hiera 'mysql::server::root_password')", "kolla_set_configs", "sudo -u mysql -E kolla_extend_start", "timeout ${DB_MAX_TIMEOUT} /bin/bash -c 'while pgrep -af /usr/bin/mysqld_safe | grep -q -v grep; do sleep 1; done'", "mysqld_safe --skip-networking --wsrep-on=OFF &", "timeout ${DB_MAX_TIMEOUT} /bin/bash -c 'until mysqladmin -uroot -p\"$(hiera 'mysql::server::root_password')\" ping 2>/dev/null; do sleep 1; done'"], {"if": [{"equals": [{"get_param": "MysqlGaleraSSTMethod"}, "mariabackup"]}, ["mysql -uroot -p\"$(hiera 'mysql::server::root_password')\" -e \"CREATE USER '${DB_MARIABACKUP_USER}'@'localhost' IDENTIFIED BY '${DB_MARIABACKUP_PASSWORD}';\"", "mysql -uroot -p\"$(hiera 'mysql::server::root_password')\" -e \"GRANT RELOAD, PROCESS, LOCK TABLES, REPLICATION CLIENT ON *.* TO '${DB_MARIABACKUP_USER}'@'localhost';\""]]}, ["mysql -uroot -p\"$(hiera 'mysql::server::root_password')\" -e \"CREATE USER 'clustercheck'@'localhost' IDENTIFIED BY '$(hiera mysql_clustercheck_password)';\"", "mysql -uroot -p\"$(hiera 'mysql::server::root_password')\" -e \"GRANT PROCESS ON *.* TO 'clustercheck'@'localhost' WITH GRANT OPTION;\"", "mysql -uroot -p\"$(hiera 'mysql::server::root_password')\" -e \"DELETE FROM mysql.user WHERE user = 'root' AND host NOT IN ('%','localhost');\"", "timeout ${DB_MAX_TIMEOUT} mysqladmin -uroot -p\"$(hiera 'mysql::server::root_password')\" shutdown"]]}], "volumes": {"list_concat": [{"get_attr": ["ContainersCommon", "volumes"]}, ["/var/lib/kolla/config_files/mysql.json:/var/lib/kolla/config_files/config.json:rw,z", "/var/lib/config-data/puppet-generated/mysql:/var/lib/kolla/config_files/src:ro,z", "/var/lib/mysql:/var/lib/mysql:rw,z"], {"if": [{"get_param": "EnableInternalTLS"}, ["/etc/pki/tls/certs/mysql.crt:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/mysql.crt:ro", "/etc/pki/tls/private/mysql.key:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/mysql.key:ro"]]}]}, "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS", "KOLLA_BOOTSTRAP": true, "DB_MAX_TIMEOUT": 60, "DB_MARIABACKUP_USER": {"get_param": "MysqlMariabackupUser"}, "DB_MARIABACKUP_PASSWORD": {"get_param": "MysqlMariabackupPassword"}}}}, "step_2": {"mysql_wait_bundle": {"start_order": 0, "detach": false, "net": "host", "ipc": "host", "user": "root", "command": {"list_concat": [["/container_puppet_apply.sh", "2", "file,file_line,concat,augeas,galera_ready,mysql_database,mysql_grant,mysql_user", "include tripleo::profile::pacemaker::database::mysql_bundle"], {"if": [{"get_param": "ConfigDebug"}, ["--debug"]]}]}, "image": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "volumes": {"list_concat": [{"get_attr": ["ContainersCommon", "container_puppet_apply_volumes"]}, ["/var/lib/mysql:/var/lib/mysql:rw,z", "/var/lib/config-data/puppet-generated/mysql/root:/root:rw"], {"if": ["docker_enabled", ["/etc/corosync/corosync.conf:/etc/corosync/corosync.conf:ro"]]}]}, "environment": {"TRIPLEO_DEPLOY_IDENTIFIER": {"get_param": "DeployIdentifier"}}}}}, "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/mysql", "setype": "container_file_t", "mode": "0750"}, {"path": "/var/lib/mysql", "setype": "container_file_t"}, {"path": "/var/log/mariadb", "setype": "container_file_t", "mode": "0750"}]}], "metadata_settings": {"get_attr": ["MysqlBase", "role_data", "metadata_settings"]}, "deploy_steps_tasks": {"list_concat": [{"get_attr": ["MysqlBase", "role_data", "deploy_steps_tasks"]}, [{"name": "MySQL tag container image for pacemaker", "when": "step|int == 1", "import_role": {"name": "tripleo_container_tag"}, "vars": {"container_image": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "container_image_latest": {"if": [{"get_param": "ClusterFullTag"}, "cluster.common.tag/mariadb:pcmklatest", {"yaql": {"data": {"if": [{"get_param": "ClusterCommonTag"}, {"yaql": {"data": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "expression": "concat(\"cluster.common.tag/\", $.data.rightSplit(separator => \"/\", maxSplits => 1)[1])"}}, {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}]}, "expression": "concat($.data.rightSplit(separator => \":\", maxSplits => 1)[0], \":pcmklatest\")"}}]}}}, {"name": "MySQL HA Wrappers Step", "when": "step|int == 2", "block": [{"name": "Mysql puppet bundle", "import_role": {"name": "tripleo_ha_wrapper"}, "vars": {"tripleo_ha_wrapper_service_name": "mysql", "tripleo_ha_wrapper_resource_name": "galera", "tripleo_ha_wrapper_bundle_name": "galera-bundle", "tripleo_ha_wrapper_resource_state": "Master", "tripleo_ha_wrapper_puppet_config_volume": "mysql", "tripleo_ha_wrapper_puppet_execute": "[\"Mysql_datadir\", \"Mysql_user\", \"Mysql_database\", \"Mysql_grant\", \"Mysql_plugin\"].each |String $val| { noop_resource($val) }; include ::tripleo::profile::base::pacemaker; include ::tripleo::profile::pacemaker::database::mysql_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"}, "tripleo_ha_wrapper_config_suffix": ".previous_run"}}]}]]}, "external_update_tasks": [{"when": "step|int == 1", "tags": "ha_image_update", "block": [{"block": [{"name": "Get galera image from pacemaker", "become": true, "register": "xmllint_pcmk_galera_image", "shell": "xmllint --xpath \"string(//bundle[@id='galera-bundle']/podman/@image)\" /var/lib/pacemaker/cib/cib.xml"}, {"name": "Get container galera image", "set_fact": {"galera_image": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "galera_image_latest": {"if": [{"get_param": "ClusterFullTag"}, "cluster.common.tag/mariadb:pcmklatest", {"yaql": {"data": {"if": [{"get_param": "ClusterCommonTag"}, {"yaql": {"data": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "expression": "concat(\"cluster.common.tag/\", $.data.rightSplit(separator => \"/\", maxSplits => 1)[1])"}}, {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}]}, "expression": "concat($.data.rightSplit(separator => \":\", maxSplits => 1)[0], \":pcmklatest\")"}}]}, "pcmk_galera_image": "{{xmllint_pcmk_galera_image.stdout}}"}}], "delegate_to": "{{ (groups[\"mysql\"] | difference(groups[\"excluded_overcloud\"]))[0] }}"}, {"name": "MySQL 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[\"mysql\"] | difference(groups[\"excluded_overcloud\"]) }}", "tripleo_ha_image_update_bundle": "galera-bundle", "tripleo_ha_image_update_new_image": "{{galera_image_latest}}", "tripleo_ha_image_update_old_image": "{{pcmk_galera_image}}"}, "when": ["(pcmk_galera_image != \"\")", "(pcmk_galera_image != galera_image_latest)"]}]}], "update_tasks": [{"block": [{"name": "Get galera image from pacemaker", "become": true, "register": "xmllint_pcmk_galera_image", "shell": "xmllint --xpath \"string(//bundle[@id='galera-bundle']/podman/@image)\" /var/lib/pacemaker/cib/cib.xml"}, {"name": "Get container galera image", "set_fact": {"galera_image": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "galera_image_latest": {"if": [{"get_param": "ClusterFullTag"}, "cluster.common.tag/mariadb:pcmklatest", {"yaql": {"data": {"if": [{"get_param": "ClusterCommonTag"}, {"yaql": {"data": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "expression": "concat(\"cluster.common.tag/\", $.data.rightSplit(separator => \"/\", maxSplits => 1)[1])"}}, {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}]}, "expression": "concat($.data.rightSplit(separator => \":\", maxSplits => 1)[0], \":pcmklatest\")"}}]}, "pcmk_galera_image": "{{xmllint_pcmk_galera_image.stdout}}"}}], "when": "(step|int == 0 or step|int == 2)"}, {"name": "Check for update of galera container image name", "when": "step|int == 0", "assert": {"that": "pcmk_galera_image == galera_image_latest", "fail_msg": "galera image change detected, run overcloud external-update --tags ha_image_update first"}}, {"name": "Tear-down non-HA mysql container", "when": ["step|int == 1"], "block": [{"name": "stat mysql container", "command": "podman container exists mysql", "failed_when": false, "changed_when": false, "register": "stat_mysql_container"}, {"name": "Create clustercheck user and permissions", "command": {"argv": "{{ mysql_exec_data | container_exec_cmd }}"}, "changed_when": true, "when": ["stat_mysql_container.rc == 0"], "vars": {"mysql_exec_data": {"environment": {"CLUSTERCHECK_PASSWORD": {"get_param": "MysqlClustercheckPassword"}}, "command": ["mysql", "/bin/sh", "-c", "mysql -e \"CREATE USER IF NOT EXISTS 'clustercheck'@'localhost' IDENTIFIED BY '${CLUSTERCHECK_PASSWORD}'; GRANT PROCESS ON *.* TO 'clustercheck'@'localhost' WITH GRANT OPTION;\""]}}}, {"name": "Remove non-HA mysql container", "include_role": {"name": "tripleo_container_rm"}, "vars": {"tripleo_container_cli": "{{ container_cli }}", "tripleo_containers_to_rm": ["mysql"]}}]}, {"name": "Mariadb fetch and retag container image for pacemaker", "when": "step|int == 2", "block": [{"name": "Retag pcmklatest to latest galera image", "include_role": {"name": "tripleo_container_tag"}, "vars": {"container_image": "{{galera_image}}", "container_image_latest": "{{galera_image_latest}}"}}]}, {"name": "Ensure mariadb-server is not installed on the host", "when": "step|int == 2", "yum": {"name": "mariadb-server*", "state": "absent"}}], "post_update_tasks": [{"name": "Mysql bundle post update", "when": "step|int == 1", "block": [{"name": "Mysql puppet bundle", "import_role": {"name": "tripleo_ha_wrapper"}, "vars": {"tripleo_ha_wrapper_service_name": "mysql", "tripleo_ha_wrapper_resource_name": "galera", "tripleo_ha_wrapper_bundle_name": "galera-bundle", "tripleo_ha_wrapper_resource_state": "Master", "tripleo_ha_wrapper_puppet_config_volume": "mysql", "tripleo_ha_wrapper_puppet_execute": "[\"Mysql_datadir\", \"Mysql_user\", \"Mysql_database\", \"Mysql_grant\", \"Mysql_plugin\"].each |String $val| { noop_resource($val) }; include ::tripleo::profile::base::pacemaker; include ::tripleo::profile::pacemaker::database::mysql_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"}, "tripleo_ha_wrapper_config_suffix": ".previous_run"}}], "vars": {"tripleo_ha_wrapper_minor_update": true}}], "upgrade_tasks": {"list_concat": [[{"name": "Tear-down non-HA mysql container", "when": ["step|int == 0"], "block": [{"name": "stat mysql container", "command": "podman container exists mysql", "failed_when": false, "changed_when": false, "register": "stat_mysql_container"}, {"name": "Create clustercheck user and permissions", "command": {"argv": "{{ mysql_exec_data | container_exec_cmd }}"}, "changed_when": true, "when": ["stat_mysql_container.rc == 0"], "vars": {"mysql_exec_data": {"environment": {"CLUSTERCHECK_PASSWORD": {"get_param": "MysqlClustercheckPassword"}}, "command": ["mysql", "/bin/sh", "-c", "mysql -e \"CREATE USER IF NOT EXISTS 'clustercheck'@'localhost' IDENTIFIED BY '${CLUSTERCHECK_PASSWORD}'; GRANT PROCESS ON *.* TO 'clustercheck'@'localhost' WITH GRANT OPTION;\""]}}}, {"name": "Remove non-HA mysql container", "include_role": {"name": "tripleo_container_rm"}, "vars": {"tripleo_container_cli": "{{ container_cli }}", "tripleo_containers_to_rm": ["mysql"]}}]}], [{"name": "set mysql container name fact", "when": ["step|int == 1"], "set_fact": {"mysql_container_name": "galera-bundle"}}], {"get_attr": ["MysqlBase", "mysql_drop_unused_users"]}, [{"vars": {"mysql_upgrade_persist": {"get_param": "MysqlUpgradePersist"}}, "when": ["step|int == 3", "mysql_upgrade_persist"], "tags": ["never", "system_upgrade", "system_upgrade_prepare"], "block": [{"name": "Persist mysql data", "include_role": {"name": "tripleo_persist", "tasks_from": "persist.yml"}, "vars": {"tripleo_persist_dir": "/var/lib/mysql"}}]}, {"vars": {"mysql_upgrade_persist": {"get_param": "MysqlUpgradePersist"}}, "when": ["step|int == 5", "mysql_upgrade_persist"], "tags": ["never", "system_upgrade", "system_upgrade_run"], "block": [{"name": "Restore mysql data", "include_role": {"name": "tripleo_persist", "tasks_from": "restore.yml"}, "vars": {"tripleo_persist_dir": "/var/lib/mysql"}}]}, {"name": "Prepare switch of galera image name", "when": ["step|int == 0"], "block": [{"name": "Get galera image id currently used by pacemaker", "shell": "pcs resource config galera-bundle | grep -Eo 'image=[^ ]+' | awk -F= '{print $2;}'", "register": "galera_image_current_res", "failed_when": false}, {"name": "Image facts for galera", "set_fact": {"galera_image_latest": {"if": [{"get_param": "ClusterFullTag"}, "cluster.common.tag/mariadb:pcmklatest", {"yaql": {"data": {"if": [{"get_param": "ClusterCommonTag"}, {"yaql": {"data": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "expression": "concat(\"cluster.common.tag/\", $.data.rightSplit(separator => \"/\", maxSplits => 1)[1])"}}, {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}]}, "expression": "concat($.data.rightSplit(separator => \":\", maxSplits => 1)[0], \":pcmklatest\")"}}]}, "galera_image_current": "{{galera_image_current_res.stdout}}"}}, {"name": "Temporarily tag the current galera image id with the upgraded image name", "import_role": {"name": "tripleo_container_tag"}, "vars": {"container_image": "{{galera_image_current}}", "container_image_latest": "{{galera_image_latest}}", "pull_image": false}, "when": ["galera_image_current != ''", "galera_image_current != galera_image_latest"]}, {"name": "Create galera retag statefile", "file": {"path": "/var/lib/tripleo/galera_needs_retag", "state": "touch"}, "when": ["galera_image_current != ''", "galera_image_current != galera_image_latest"]}]}, {"name": "Update galera pcs resource bundle for new container image - check", "when": ["step|int == 1"], "block": [{"name": "set is_mysql_bootstrap_node fact", "tags": "common", "set_fact": "is_mysql_bootstrap_node={{mysql_short_bootstrap_node_name|lower == ansible_facts['hostname']|lower}}"}, {"name": "Check for galera retag statefile", "stat": {"path": "/var/lib/tripleo/galera_needs_retag"}, "register": "galera_retag_state_file"}]}, {"name": "Update galera pcs resource bundle for new container image", "when": ["step|int == 1", "is_mysql_bootstrap_node|bool", "galera_retag_state_file.stat.exists|bool"], "block": [{"name": "Disable the galera cluster resource before container upgrade", "pacemaker_resource": {"resource": "galera-bundle", "state": "disable", "wait_for_resource": true}, "register": "output", "retries": 5, "until": "output.rc == 0"}, {"name": "Move Mysql logging to /var/log/containers", "block": [{"name": "Check Mysql logging configuration in pacemaker", "command": "cibadmin --query --xpath \"//storage-mapping[@id='mysql-log']\"", "failed_when": false, "register": "mysql_logs_moved"}, {"name": "Change Mysql logging configuration in pacemaker", "when": "mysql_logs_moved.rc == 6", "block": [{"name": "Add a bind mount for logging in the galera bundle", "command": "pcs resource bundle update galera-bundle storage-map add id=mysql-log source-dir=/var/log/containers/mysql target-dir=/var/log/mysql options=rw"}, {"name": "Reconfigure Mysql log file in the galera resource agent", "command": "pcs resource update galera log=/var/log/mysql/mysqld.log"}]}]}, {"name": "Update the galera bundle to use the new container image name", "command": "pcs resource bundle update galera-bundle container image={{galera_image_latest}}"}, {"name": "Enable the galera cluster resource", "pacemaker_resource": {"resource": "galera-bundle", "state": "enable", "wait_for_resource": true}, "register": "output", "retries": 5, "until": "output.rc == 0"}]}, {"name": "Upgrade galera in step3", "when": ["step|int == 3"], "block": [{"name": "Bind mounts for temporary container", "set_fact": {"mysql_upgrade_db_bind_mounts": {"list_concat": [{"get_attr": ["ContainersCommon", "volumes"]}, ["/var/lib/kolla/config_files/mysql.json:/var/lib/kolla/config_files/config.json:rw,z", "/var/lib/config-data/puppet-generated/mysql:/var/lib/kolla/config_files/src:ro,z", "/var/lib/mysql:/var/lib/mysql:rw,z"], ["/var/log/containers/mysql:/var/log/mysql:rw,z"], {"if": [{"get_param": "EnableInternalTLS"}, ["/etc/pki/tls/certs/mysql.crt:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/mysql.crt:ro", "/etc/pki/tls/private/mysql.key:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/mysql.key:ro"]]}]}}}, {"name": "Check if Galera needs upgrade", "shell": {"str_replace": {"template": "CONTAINER_CLI run --rm --log-driver=k8s-file --log-opt path=LOG_DIR/db-upgrade.log \\ -u root --net=host UPGRADE_ENV UPGRADE_VOLUMES \"UPGRADE_IMAGE\" /bin/bash -ecx \"$UPGRADE_SCRIPT\"", "params": {"UPGRADE_ENV": "-e \"KOLLA_CONFIG_STRATEGY=COPY_ALWAYS\"", "UPGRADE_IMAGE": {"if": [{"get_param": "ClusterFullTag"}, "cluster.common.tag/mariadb:pcmklatest", {"yaql": {"data": {"if": [{"get_param": "ClusterCommonTag"}, {"yaql": {"data": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "expression": "concat(\"cluster.common.tag/\", $.data.rightSplit(separator => \"/\", maxSplits => 1)[1])"}}, {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}]}, "expression": "concat($.data.rightSplit(separator => \":\", maxSplits => 1)[0], \":pcmklatest\")"}}]}, "UPGRADE_VOLUMES": "-v {{ mysql_upgrade_db_bind_mounts | join(' -v ')}}", "CONTAINER_CLI": "{{ container_cli }}", "LOG_DIR": "/var/log/containers/mysql"}}}, "environment": {"UPGRADE_SCRIPT": "kolla_set_configs\nupgraded_ver=$(cat /var/lib/mysql/mysql_upgrade_info 2>/dev/null || true)\nmysql_ver=$(mysql --version | awk -F'[ ,]*' '{print $5}')\nif [ \"${upgraded_ver}\" = \"${mysql_ver}\" ]; then\n echo \"mysql already upgraded\"\nelse\n echo \"${upgraded_ver} VS ${mysql_ver}\"\nfi\n"}, "register": "mysql_upgrade_needed"}, {"name": "Set fact upgrade_mysql", "set_fact": {"upgrade_mysql": "{{ (mysql_upgrade_needed.stdout != \"mysql already upgraded\") | bool }}"}}, {"debug": {"msg": "MYSQL check - {{ mysql_upgrade_needed.stdout }} - Upgrade needed: {{ upgrade_mysql }}"}}, {"name": "Disable the galera cluster resource before container upgrade", "when": ["upgrade_mysql|bool"], "pacemaker_resource": {"resource": "galera-bundle", "state": "disable", "wait_for_resource": true}, "register": "output", "retries": 5, "until": "output.rc == 0"}, {"block": [{"name": "Get galera image from pacemaker", "become": true, "register": "xmllint_pcmk_galera_image", "shell": "xmllint --xpath \"string(//bundle[@id='galera-bundle']/podman/@image)\" /var/lib/pacemaker/cib/cib.xml"}, {"name": "Get container galera image", "set_fact": {"galera_image": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "galera_image_latest": {"if": [{"get_param": "ClusterFullTag"}, "cluster.common.tag/mariadb:pcmklatest", {"yaql": {"data": {"if": [{"get_param": "ClusterCommonTag"}, {"yaql": {"data": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "expression": "concat(\"cluster.common.tag/\", $.data.rightSplit(separator => \"/\", maxSplits => 1)[1])"}}, {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}]}, "expression": "concat($.data.rightSplit(separator => \":\", maxSplits => 1)[0], \":pcmklatest\")"}}]}, "pcmk_galera_image": "{{xmllint_pcmk_galera_image.stdout}}"}}]}, {"name": "Check for galera retag statefile", "stat": {"path": "/var/lib/tripleo/galera_needs_retag"}, "register": "galera_retag_state_file"}, {"name": "Retag the pacemaker image if containerized", "when": ["galera_retag_state_file.stat.exists|bool"], "block": [{"name": "Retag pcmklatest to latest galera image", "include_role": {"name": "tripleo_container_tag"}, "vars": {"container_image": "{{galera_image}}", "container_image_latest": "{{galera_image_latest}}"}}]}, {"name": "Remove galera retag statefile", "file": {"path": "/var/lib/tripleo/galera_needs_retag", "state": "absent"}}, {"name": "Mysql upgrade script", "when": ["upgrade_mysql|bool"], "set_fact": {"mysql_upgrade_script": {"list_join": ["\n", ["kolla_set_configs\nif mysqladmin ping --silent; then exit 0; fi\nupgraded_ver=$(cat /var/lib/mysql/mysql_upgrade_info 2>/dev/null || true)\nmysql_ver=$(mysql --version | awk -F'[ ,]*' '{print $5}')\nif [ \"${upgraded_ver}\" = \"${mysql_ver}\" ]; then\n echo \"mysql already upgraded\"\n exit 0\nfi\nchown -R mysql:mysql /var/lib/mysql\nchown -R mysql:mysql /var/log/mysql\nmysqld_safe --user=mysql --wsrep-provider=none --skip-networking --wsrep-on=off --log-error=/var/log/mysql/mysqld-upgrade.log &\n", {"get_file": "file:///usr/share/openstack-tripleo-heat-templates/container_config_scripts/mysql_upgrade_db.sh"}, "mysqladmin shutdown"]]}}}, {"name": "Upgrade Mysql database from a temporary container", "when": ["upgrade_mysql|bool"], "shell": {"str_replace": {"template": "CONTAINER_CLI run --rm --log-driver=k8s-file --log-opt path=LOG_DIR/db-upgrade.log \\ -u root --net=host UPGRADE_ENV UPGRADE_VOLUMES \"UPGRADE_IMAGE\" /bin/bash -ecx \"$UPGRADE_SCRIPT\"", "params": {"UPGRADE_ENV": "-e \"KOLLA_CONFIG_STRATEGY=COPY_ALWAYS\"", "UPGRADE_IMAGE": {"if": [{"get_param": "ClusterFullTag"}, "cluster.common.tag/mariadb:pcmklatest", {"yaql": {"data": {"if": [{"get_param": "ClusterCommonTag"}, {"yaql": {"data": {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}, "expression": "concat(\"cluster.common.tag/\", $.data.rightSplit(separator => \"/\", maxSplits => 1)[1])"}}, {"get_attr": ["RoleParametersValue", "value", "ContainerMysqlImage"]}]}, "expression": "concat($.data.rightSplit(separator => \":\", maxSplits => 1)[0], \":pcmklatest\")"}}]}, "UPGRADE_VOLUMES": "-v {{ mysql_upgrade_db_bind_mounts | join(' -v ')}}", "CONTAINER_CLI": "{{ container_cli }}", "LOG_DIR": "/var/log/containers/mysql"}}}, "environment": {"UPGRADE_SCRIPT": "{{ mysql_upgrade_script }}"}}, {"name": "Enable the galera cluster resource", "when": ["upgrade_mysql|bool"], "pacemaker_resource": {"resource": "galera-bundle", "state": "enable", "wait_for_resource": true}, "register": "output", "retries": 5, "until": "output.rc == 0"}]}]]}, "external_upgrade_tasks": [{"vars": {"mysql_upgrade_transfer": {"get_param": "MysqlUpgradeTransfer"}}, "when": ["step|int == 2", "mysql_upgrade_transfer"], "tags": ["never", "system_upgrade_transfer_data"], "block": [{"name": "Transfer mysql data", "include_role": {"name": "tripleo_transfer"}, "vars": {"tripleo_transfer_src_dir": "/var/lib/mysql", "tripleo_transfer_src_host": "{{hostvars[groups['overcloud'][0]]['mysql_short_node_names'][1]}}", "tripleo_transfer_dest_dir": "/var/lib/mysql", "tripleo_transfer_dest_host": "{{hostvars[groups['overcloud'][0]]['mysql_short_bootstrap_node_name']}}", "tripleo_transfer_flag_file": "/var/lib/tripleo/transfer-flags/var-lib-mysql", "tripleo_transfer_sync_options": "--whole-file --ignore-times --inplace --archive --delete", "tripleo_transfer_include": ["/ibdata*", "/ib_lru_dump", "/ib_logfile[0-9]*", "/undo*", "/*/"], "tripleo_transfer_exclude": "/*"}}]}]}}}}