From b23a2a40d847d1c052fc963c9026c5b51a6c51b0 Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Tue, 28 May 2019 14:06:45 +1000 Subject: [PATCH] DCD-352: First cut of a synchrony startup script. --- aws_confluence_synchrony_node.yml | 20 ++++++ roles/confluence_config/tasks/main.yml | 2 +- roles/synchrony_startup/defaults/main.yml | 7 +++ roles/synchrony_startup/files/start-synchrony | 63 +++++++++++++++++++ roles/synchrony_startup/handlers/main.yml | 9 +++ roles/synchrony_startup/tasks/main.yml | 27 ++++++++ .../templates/atl.synchrony.j2 | 28 +++++++++ .../templates/synchrony.service.j2 | 16 +++++ 8 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 aws_confluence_synchrony_node.yml create mode 100644 roles/synchrony_startup/defaults/main.yml create mode 100755 roles/synchrony_startup/files/start-synchrony create mode 100644 roles/synchrony_startup/handlers/main.yml create mode 100644 roles/synchrony_startup/tasks/main.yml create mode 100644 roles/synchrony_startup/templates/atl.synchrony.j2 create mode 100644 roles/synchrony_startup/templates/synchrony.service.j2 diff --git a/aws_confluence_synchrony_node.yml b/aws_confluence_synchrony_node.yml new file mode 100644 index 0000000..6733d42 --- /dev/null +++ b/aws_confluence_synchrony_node.yml @@ -0,0 +1,20 @@ +--- + +- hosts: aws_node_local + become: true + + vars: + # See group_vars/aws_node_local.yml, which pull vars from the environment. + atl_product_family: "confluence" + atl_product_user: "confluence" + atl_product_edition: "confluence" + + roles: + - role: linux_common + - role: aws_common + - role: aws_efs_config + - role: product_common + - role: product_install + - role: confluence_common + # Synchrony is 12-factor, so configuration in the startup + - role: synchrony_startup diff --git a/roles/confluence_config/tasks/main.yml b/roles/confluence_config/tasks/main.yml index f87bfdb..f1e69fc 100644 --- a/roles/confluence_config/tasks/main.yml +++ b/roles/confluence_config/tasks/main.yml @@ -29,7 +29,7 @@ - 'Xms' - name: Set the Tomcat environment - lineinfile: + lineinfile: path: "{{ atl_product_installation_versioned }}/bin/setenv.sh" insertafter: "EOF" line: 'export CATALINA_OPTS="${CATALINA_OPTS} {{ atl_catalina_opts }} {{ atl_catalina_opts_extra }}"' diff --git a/roles/synchrony_startup/defaults/main.yml b/roles/synchrony_startup/defaults/main.yml new file mode 100644 index 0000000..fd5cf74 --- /dev/null +++ b/roles/synchrony_startup/defaults/main.yml @@ -0,0 +1,7 @@ +--- + +# FIXME: Add others as map? +atl_synchrony_cluster_type: "aws" + +atl_synchrony_memory: "{{ lookup('env', 'ATL_SYNCHRONY_MEMORY') or '-Xmx2g'" +atl_synchrony_stack_space: "{{ lookup('env', 'ATL_SYNCHRONY_STACK_SPACE') or '-Xss2048k'" diff --git a/roles/synchrony_startup/files/start-synchrony b/roles/synchrony_startup/files/start-synchrony new file mode 100755 index 0000000..3a9d602 --- /dev/null +++ b/roles/synchrony_startup/files/start-synchrony @@ -0,0 +1,63 @@ +#!/bin/bash + +set -e + +# Synchrony startup wrapper for systemd. Note: This expects the +# environment to be setup, usually by sourceing /etc/atl and +# /etc/atl.synchrony with EnvironmentFile. See the rest of this role +# for details. The rest of the variables below need to be calculated +# at runtime. + +# Find the first Postgres driver in lib folder +SYNCHRONY_JWT_PRIVATE_KEY="UNSET" +SYNCHRONY_JWT_PUBLIC_KEY="UNSET" + +ATL_POSTGRES_DRIVER_PATH=$(ls -t ${ATL_CONFLUENCE_INSTALL_DIR}/confluence/WEB-INF/lib/postgresql*.jar | head -n 1) +SYNCHRONY_CLASSPATH="${ATL_SYNCHRONY_JAR_PATH}:${ATL_POSTGRES_DRIVER_PATH}" + + +# To support retries these commands won't fail the script by virtue of using `--shell` option for xmllint. +function extractJWTKeyFromConfluenceConfig { + local keyType=$1 + if [[ "${keyType}" != "jwt.private.key" && "${keyType}" != "jwt.public.key" ]]; then + atl_log "Unexpected value for keyType - ${keyType} to extract JWT key from confluence.cfg.xml" + exit 1 + fi + echo "cat //properties/property[@name='${keyType}']/text()" | xmllint --nocdata --shell ${ATL_CONFLUENCE_SHARED_CONFIG_FILE} | sed '1d;$d' +} + +# Synchrony requires JWT keys to communicate with Confluence application. These keys are written to the config file +# after admin will go through the setup and provide license. This function waits for the keys being available in the +# config file. +function waitForConfluenceConfigInSharedHome() { + atl_log "=== BEGIN: Waiting for confluence.cfg.xml available in shared home folder ===" + while [[ ! -f ${ATL_CONFLUENCE_SHARED_CONFIG_FILE} ]]; do + sleep ${ATL_SYNCHRONY_WAITING_CONFIG_TIME} + atl_log "====== : Keep waiting for ${ATL_SYNCHRONY_WAITING_CONFIG_TIME} seconds ======" + done + + atl_log "====== : Fetching JWT keys from Confluence config... ======" + while [[ -z ${SYNCHRONY_JWT_PRIVATE_KEY} || -z ${SYNCHRONY_JWT_PUBLIC_KEY} ]]; do + SYNCHRONY_JWT_PRIVATE_KEY=$(extractJWTKeyFromConfluenceConfig 'jwt.private.key') >> ${ATL_LOG} 2>&1 + SYNCHRONY_JWT_PUBLIC_KEY=$(extractJWTKeyFromConfluenceConfig 'jwt.public.key') >> ${ATL_LOG} 2>&1 + if [[ -z ${SYNCHRONY_JWT_PRIVATE_KEY} || -z ${SYNCHRONY_JWT_PUBLIC_KEY} ]]; then + atl_log "====== : Could not load value for JWT key; will wait for next ${ATL_SYNCHRONY_WAITING_CONFIG_TIME} seconds before reload ======" + sleep ${ATL_SYNCHRONY_WAITING_CONFIG_TIME} + fi + done + + atl_log "=== END: Waiting for confluence.cfg.xml available in shared home folder ===" +} + + +###################################################################### +# Start Synchrony service + +waitForConfluenceConfigInSharedHome + +exec ${_RUNJAVA} \ + ${SYNCHRONY_CLASSPATH} \ + ${ATL_SYNCHRONY_JVM_PROPERTIES} \ + -Djwt.private.key=${SYNCHRONY_JWT_PRIVATE_KEY} \ + -Djwt.public.key=${SYNCHRONY_JWT_PUBLIC_KEY} \ + synchrony.core sql diff --git a/roles/synchrony_startup/handlers/main.yml b/roles/synchrony_startup/handlers/main.yml new file mode 100644 index 0000000..8f393c9 --- /dev/null +++ b/roles/synchrony_startup/handlers/main.yml @@ -0,0 +1,9 @@ +--- + +- name: Restart Synchrony + service: + name: synchrony.service + state: restarted + +- name: Enable Synchrony + command: systemctl enable synchrony.service diff --git a/roles/synchrony_startup/tasks/main.yml b/roles/synchrony_startup/tasks/main.yml new file mode 100644 index 0000000..562742b --- /dev/null +++ b/roles/synchrony_startup/tasks/main.yml @@ -0,0 +1,27 @@ +--- + +- name: Install the startup wrapper script + copy: + src: start-synchrony + dest: "{{ atl_installation_base }}/bin/start-synchrony" + group: "{{ atl_product_user }}" + mode: "0750" + notify: + - Restart Synchrony + +- name: Install the Synchrony environment settings + template: + src: "atl.synchrony.j2" + dest: "/etc/atl.synchrony" + group: "{{ atl_product_user }}" + mode: "0640" + notify: + - Restart Synchrony + +- name: "Install Synchrony service file" + template: + src: "synchrony.service.j2" + dest: "/etc/systemd/system/synchrony.service" + notify: + - Enable Synchrony + - Restart Synchrony diff --git a/roles/synchrony_startup/templates/atl.synchrony.j2 b/roles/synchrony_startup/templates/atl.synchrony.j2 new file mode 100644 index 0000000..4b0dc87 --- /dev/null +++ b/roles/synchrony_startup/templates/atl.synchrony.j2 @@ -0,0 +1,28 @@ +# Generated by Ansible Synchrony playbook. Usually sourced with +# EnvironmentFile in the systemd service file. + +ATL_SYNCHRONY_SERVICE_NAME="synchrony" +ATL_CONFLUENCE_INSTALL_DIR="{{ atl_product_installation_current }}" +ATL_CONFLUENCE_SHARED_CONFIG_FILE="{{ atl_product_home_shared }}/confluence.cfg.xml" +ATL_SYNCHRONY_JAR_PATH="{{ atl_product_installation_current }}/confluence/WEB-INF/packages/synchrony-standalone.jar" + +AWS_EC2_PRIVATE_IP="{{ atl_local_ipv4 }}" +_RUNJAVA="{{ atl_product_installation_current }}/jre/bin/java" + +ATL_SYNCHRONY_JVM_PROPERTIES="{{ atl_synchrony_stack_space }} {{ atl_synchrony_memory }} \ + -Dsynchrony.cluster.impl=hazelcast-btf \ + -Dsynchrony.database.url={{ atl_jdbc_url }} \ + -Dsynchrony.database.username={{ atl_jdbc_user }} \ + -Dsynchrony.database.password={{ atl_jdbc_password }} \ + -Dsynchrony.bind={{ atl_local_ipv4 }} \ + -Dsynchrony.cluster.bind={{ atl_local_ipv4 }} \ + -Dcluster.interfaces={{ atl_local_ipv4 }} \ + -Dsynchrony.cluster.base.port=25500 \ + -Dsynchrony.service.url={{ atl_synchrony_service_url }} \ + -Dsynchrony.context.path=/synchrony \ + -Dsynchrony.port=8091 \ + -Dcluster.name=Synchrony-Cluster \ + -Dcluster.join.type={{ atl_synchrony_cluster_type }} \ + -Dcluster.join.aws.tag.key={{ atl_hazelcast_network_aws_tag_key }} \ + -Dcluster.join.aws.tag.value={{ atl_hazelcast_network_aws_tag_value }} \ + -Dcluster.join.aws.region={{ atl_hazelcast_network_aws_iam_region }} diff --git a/roles/synchrony_startup/templates/synchrony.service.j2 b/roles/synchrony_startup/templates/synchrony.service.j2 new file mode 100644 index 0000000..04f8f2f --- /dev/null +++ b/roles/synchrony_startup/templates/synchrony.service.j2 @@ -0,0 +1,16 @@ +[Unit] +Description=Atlassian Synchrony Server +After=network-online.target + +[Service] +User={{ atl_product_user }} +Group={{ atl_product_user }} + +EnvironmentFile=/etc/atl +EnvironmentFile=/etc/atl.synchrony + +ExecStart={{ atl_product_installation_current }}/bin/{{ atl_startup_script_map[atl_product_family] }} -fg +Restart=on-failure + +[Install] +WantedBy=multi-target.target