diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..155fbfd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.idea/*
+*.tar
+*/file/tmp
\ No newline at end of file
diff --git a/ansible/.gitignore b/ansible/.gitignore
index feeb43b..59bd828 100644
--- a/ansible/.gitignore
+++ b/ansible/.gitignore
@@ -1,2 +1 @@
**/files/tmp/
-hosts
diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
index f665031..3c71ead 100644
--- a/ansible/group_vars/all.yml
+++ b/ansible/group_vars/all.yml
@@ -1,5 +1,9 @@
-keepalived_version: 2.0.18
-rabbitmq_version: 3.7.23
-local_cache_path: "~/.ansible/cache"
-erlang_solution_version: 1.0
-haproxy_version: 2.0
\ No newline at end of file
+appAgentVersion: v1.0.7
+arping_version: "20211215-1"
+jq_version: 1.8.1
+local_cache_path: "file/tmp"
+caddy_version: v2.9.1
+haproxy_version: 3.0.9
+keepalived_version: 2.3.3
+erlang_version: 26.2.5.9
+rabbitmq_version: 3.13.7
diff --git a/ansible/host_vars/kylin-amd64.yml b/ansible/host_vars/kylin-amd64.yml
new file mode 100644
index 0000000..d41ed55
--- /dev/null
+++ b/ansible/host_vars/kylin-amd64.yml
@@ -0,0 +1,3 @@
+default_os: kylin
+default_osv: 10sp3
+default_arch: amd64
\ No newline at end of file
diff --git a/ansible/host_vars/kylin-arm64.yml b/ansible/host_vars/kylin-arm64.yml
new file mode 100644
index 0000000..d4f264e
--- /dev/null
+++ b/ansible/host_vars/kylin-arm64.yml
@@ -0,0 +1,3 @@
+default_os: kylin
+default_osv: 10sp3
+default_arch: arm64
\ No newline at end of file
diff --git a/ansible/host_vars/ubuntu-amd64.yml b/ansible/host_vars/ubuntu-amd64.yml
new file mode 100644
index 0000000..f1522b9
--- /dev/null
+++ b/ansible/host_vars/ubuntu-amd64.yml
@@ -0,0 +1,3 @@
+default_os: ubuntu
+default_osv: "22.04"
+default_arch: amd64
\ No newline at end of file
diff --git a/ansible/hosts b/ansible/hosts
new file mode 100644
index 0000000..39c647d
--- /dev/null
+++ b/ansible/hosts
@@ -0,0 +1,3 @@
+ubuntu-amd64 ansible_host=yourip
+kylin-arm64 ansible_host=youip ansible_port=30023
+kylin-amd64 ansible_host=youip ansible_port=30024
\ No newline at end of file
diff --git a/ansible/make.yml b/ansible/make.yml
index ab13b2e..4cb4233 100644
--- a/ansible/make.yml
+++ b/ansible/make.yml
@@ -8,18 +8,23 @@
- include_role:
name: "{{ service_name }}"
loop:
- - disable-apt-jobs-1.0.0
- - disable-motd-1.0.0
- - app-agent-1.0.1
- - appctl-1.0.9
- - arping-1.0.0
- - rabbitmq-server
- - haproxy
- - keepalived
+ - tar
+ - ncncat
+ - jq
+ - os-update
+ - disable-package-manager-timers
+ - disable-motd
+ - app-agent
+ - appctl
+ - arping
+ - caddy
- node-all
- node-client
- - node-proxy
+ - node-proxy-keepalived
- node-rabbitmq
- - caddy-1.0.6
+ - users_groups
+ - crashkernel
+ - pwquality
+ - rsyslog
loop_control:
loop_var: service_name
diff --git a/ansible/requirements.yml b/ansible/requirements.yml
deleted file mode 100644
index de56304..0000000
--- a/ansible/requirements.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-- src: https://qingcloudappcenter.github.io/ansible-roles/disable-apt-jobs-1.0.0.tar.gz
-- src: https://qingcloudappcenter.github.io/ansible-roles/disable-motd-1.0.0.tar.gz
-- src: https://qingcloudappcenter.github.io/ansible-roles/app-agent-1.0.1.tar.gz
-- src: https://qingcloudappcenter.github.io/ansible-roles/appctl-1.0.9.tar.gz
-- src: https://qingcloudappcenter.github.io/ansible-roles/arping-1.0.0.tar.gz
-- src: https://qingcloudappcenter.github.io/ansible-roles/confd-files-1.0.2.tar.gz
-- src: https://qingcloudappcenter.github.io/ansible-roles/install-1.0.5.tar.gz
-- src: https://qingcloudappcenter.github.io/ansible-roles/caddy-1.0.6.tar.gz
\ No newline at end of file
diff --git a/ansible/roles/app-agent/meta/main.yml b/ansible/roles/app-agent/meta/main.yml
new file mode 100644
index 0000000..0a4c119
--- /dev/null
+++ b/ansible/roles/app-agent/meta/main.yml
@@ -0,0 +1,13 @@
+galaxy_info:
+ role_name: app-agent
+ role_version: 1.0.1
+ author: Hongliang Wang
+ description: installs app agent
+
+ license: Apache
+
+ min_ansible_version: 2.4
+
+ galaxy_tags: []
+
+dependencies: []
diff --git a/ansible/roles/app-agent/tasks/main.yml b/ansible/roles/app-agent/tasks/main.yml
new file mode 100644
index 0000000..753cf40
--- /dev/null
+++ b/ansible/roles/app-agent/tasks/main.yml
@@ -0,0 +1,78 @@
+---
+- name: set up variables
+ set_fact:
+ os: "{{ os | d(default_os) }}"
+ appAgentVersion: "{{ appAgentVersion | d('v1.0.7') }}"
+ arch: "{{ arch | d(default_arch) }}"
+ tmpPath: "/tmp/app-agent"
+
+# will set var downloaded
+- include_role:
+ name: downloader
+ vars:
+ opts:
+ pkg_name: app-agent
+ pkg_version: "{{ appAgentVersion }}"
+ pkg_feature: "linux-{{ arch }}"
+ pkg_fileType: ".tgz"
+ pkg_url: "https://github.com/QingCloudAppcenter/AppcenterAgent/releases/download/{{ appAgentVersion }}/app-agent-linux-{{ arch }}.tar.gz"
+
+- name: prepare dir
+ file:
+ path: "{{ tmpPath }}"
+ state: directory
+
+- name: decompress file
+ unarchive:
+ src: "{{ downloaded }}"
+ dest: "{{ tmpPath }}"
+ creates: "{{ tmpPath }}/bin"
+ extra_opts:
+ - --strip-components=1
+
+- name: hack for kylin
+ lineinfile:
+ path: "{{ tmpPath }}/install.sh"
+ regexp: "'fedora'"
+ line: "elif echo \"$os\" | grep '[fedora|kylin]' > /dev/null; then"
+
+- name: install app-agent
+ shell:
+ cmd: ./install.sh
+ chdir: "{{ tmpPath }}"
+
+- name: adjust logrotate
+ replace:
+ path: /etc/logrotate.d/app-agent
+ regexp: '^(\s+size).*'
+ replace: '\1 2M'
+
+- name: fix logrotate
+ lineinfile:
+ path: /etc/logrotate.d/app-agent
+ line: ' copytruncate'
+ insertbefore: '^}'
+ validate: 'logrotate -d %s'
+
+- name: set up variables
+ set_fact:
+ confd_path: "/etc/init.d/confd"
+
+- name: fix {{ confd_path }}
+ block:
+ - name: fix - PIDFILE
+ replace:
+ path: "{{ confd_path }}"
+ regexp: '^PIDFILE.*'
+ replace: 'PIDFILE=/run/$PROG.pid'
+ - name: fix - start
+ replace:
+ path: "{{ confd_path }}"
+ regexp: 'touch.*'
+ replace: 'touch $LOCKFILE; $(echo `pidofproc $PROG_BIN` > $PIDFILE)'
+ - name: fix - stop
+ replace:
+ path: "{{ confd_path }}"
+ regexp: 'rm -f \$LOCKFILE.*'
+ replace: 'rm -f $LOCKFILE && rm -f $PIDFILE'
+ when: os == 'kylin'
\ No newline at end of file
diff --git a/ansible/roles/appctl/files/etc/logrotate.d/appctl b/ansible/roles/appctl/files/etc/logrotate.d/appctl
new file mode 100644
index 0000000..37d2466
--- /dev/null
+++ b/ansible/roles/appctl/files/etc/logrotate.d/appctl
@@ -0,0 +1,11 @@
+/data/log/appctl/appctl.log {
+ weekly
+ maxsize 2M
+ rotate 5
+ missingok
+ notifempty
+ copytruncate
+ postrotate
+ /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
+ endscript
+}
diff --git a/ansible/roles/appctl/files/etc/rsyslog.d/49-appctl.conf b/ansible/roles/appctl/files/etc/rsyslog.d/49-appctl.conf
new file mode 100644
index 0000000..c2243d0
--- /dev/null
+++ b/ansible/roles/appctl/files/etc/rsyslog.d/49-appctl.conf
@@ -0,0 +1,11 @@
+if $programname startswith 'appctl' then {
+ action(
+ type="omfile"
+ file="/data/log/appctl/appctl.log"
+ FileOwner="syslog"
+ FileGroup="svc"
+ FileCreateMode="0640"
+ DirCreateMode="0755"
+ )
+ stop
+}
diff --git a/ansible/roles/appctl/files/opt/app/bin/ctl.sh b/ansible/roles/appctl/files/opt/app/bin/ctl.sh
new file mode 100755
index 0000000..de041c8
--- /dev/null
+++ b/ansible/roles/appctl/files/opt/app/bin/ctl.sh
@@ -0,0 +1,266 @@
+#!/usr/bin/env bash
+
+# Default hook functions named starting with _, e.g. _init(), _start(), etc.
+# Specific roles can override the default hooks like:
+# start() {
+# _start
+# ...
+# }
+#
+# Specific hooks will be executed if exist, otherwise the default ones.
+
+# Error codes
+EC_CHECK_INACTIVE=200
+EC_CHECK_PORT_ERR=201
+EC_CHECK_PROTO_ERR=202
+EC_ENV_ERR=203
+EC_CHECK_HTTP_REQ_ERR=204
+EC_CHECK_HTTP_CODE_ERR=205
+EC_CHECK_TCP_ERR=206
+
+command=$1
+args="${@:2}"
+
+log() {
+ if [ "$1" == "--debug" ]; then
+ [ "$APPCTL_ENV" == "dev" ] || return 0
+ shift
+ fi
+ logger -S 5000 -t appctl --id=$$ -- "[cmd=$command args='$args'] $@"
+}
+
+retry() {
+ local tried=0
+ local maxAttempts=$1
+ local interval=$2
+ local stopCode=$3
+ local cmd="${@:4}"
+ local retCode=0
+ while [ $tried -lt $maxAttempts ]; do
+ $cmd && return 0 || {
+ retCode=$?
+ if [ "$retCode" = "$stopCode" ]; then
+ log "'$cmd' returned with stop code $stopCode. Stopping ..."
+ return $retCode
+ fi
+ }
+ sleep $interval
+ tried=$((tried+1))
+ done
+
+ log "'$cmd' still returned errors after $tried attempts. Stopping ..."
+ return $retCode
+}
+
+rotate() {
+ local maxFilesCount=5
+ for path in $@; do
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+ done
+}
+
+execute() {
+ local cmd=$1; log --debug "Executing command ..."
+ [ "$(type -t $cmd)" = "function" ] || cmd=_$cmd
+ $cmd ${@:2}
+}
+
+applyEnvFiles() {
+ local envFile; for envFile in $(find /opt/app/bin/envs -name "*.env"); do . $envFile; done
+}
+
+applyRoleScripts() {
+ local scriptFile=/opt/app/bin/node/$NODE_CTL.sh
+ if [ -f "$scriptFile" ]; then . $scriptFile; fi
+}
+
+checkEnv() {
+ test -n "$1"
+}
+
+checkMounts() {
+ test -n "${MY_HYPER_TYPE}" || {
+ log "ERROR: MY_HYPER_TYPE variable is required to be set. "
+ return 1
+ }
+ test -n "${DATA_MOUNTS+x}" || {
+ log "ERROR: DATA_MOUNTS variable is required to be set. "
+ return 1
+ }
+ case $MY_HYPER_TYPE in
+ kvm)
+ local dataDir; for dataDir in $DATA_MOUNTS; do
+ grep -qs " $dataDir " /proc/mounts || {
+ log "ERROR: Failed to mount disk . "
+ return 1
+ }
+ done
+ ;;
+ lxc)
+ local dataDir; for dataDir in $DATA_MOUNTS; do
+ dataDir=$(echo $dataDir|tr -s [:space:])
+ if [ -d $dataDir ]; then
+ :
+ else
+ log "ERROR: $dataDir is not found in this container . "
+ return 1
+ fi
+ done
+ ;;
+ *)
+ log "ERROR: unrecognized hyper type: $MY_HYPER_TYPE. "
+ return 1
+ ;;
+ esac
+}
+
+getServices() {
+ if [ "$1" = "-a" ]; then
+ echo $SERVICES
+ else
+ echo $SERVICES | xargs -n1 | awk -F/ '$2=="true"' | xargs
+ fi
+}
+
+isSvcEnabled() {
+ local svc="${1%%/*}"
+ [ "$(echo $(getServices -a) | xargs -n1 | awk -F/ '$1=="'$svc'" {print $2}')" = "true" ]
+}
+
+checkActive() {
+ systemctl is-active -q $1
+}
+
+checkEndpoint() {
+ local proto=${1%:*} host=${2-$MY_IP} port=${1#*:}
+ if [ "$proto" = "tcp" ]; then
+ if ! nc -z -w5 $host $port; then
+ log "ERROR: TCP timeout - failed to check $host:$port"
+ return $EC_CHECK_TCP_ERR
+ fi
+ elif [ "$proto" = "http" ]; then
+ local code
+ code="$(curl -s -m5 -o /dev/null -w "%{http_code}" $host:$port)" || {
+ log "ERROR: HTTP $code - failed to check http://$host:$port ($?)."
+ return $EC_CHECK_HTTP_REQ_ERR
+ }
+ [[ "$code" =~ ^(200|302|401|403|404)$ ]] || {
+ log "ERROR: unexpected HTTP code $code."
+ return $EC_CHECK_HTTP_CODE_ERR
+ }
+ else
+ return $EC_CHECK_PROTO_ERR
+ fi
+}
+
+isNodeInitialized() {
+ test -f $APPCTL_NODE_FILE
+}
+
+initSvc() {
+ systemctl unmask -q ${1%%/*}
+}
+
+_checkSvc() {
+ checkActive ${1%%/*} || {
+ # log "Service '$1' is inactive."
+ return $EC_CHECK_INACTIVE
+ }
+ local endpoints=$(echo $1 | awk -F/ '{print $3}')
+ local endpoint; for endpoint in ${endpoints//,/ }; do
+ checkEndpoint $endpoint || {
+ # log "Endpoint '$endpoint' is unreachable."
+ return $EC_CHECK_PORT_ERR
+ }
+ done
+}
+
+startSvc() {
+ systemctl enable ${1%%/*}
+ systemctl start ${1%%/*}
+}
+
+stopSvc() {
+ systemctl stop ${1%%/*}
+}
+
+restartSvc() {
+ stopSvc $1
+ startSvc $1
+}
+
+### app management
+
+_preCheck() {
+ checkEnv "$MY_IP"
+}
+
+_initNode() {
+ checkMounts
+ rm -rf /data/lost+found
+ install -d -o syslog -g svc /data/log/appctl/
+ local svc; for svc in $(getServices -a); do initSvc $svc; done
+ touch $APPCTL_NODE_FILE
+}
+
+_revive() {
+ log "INFO: Application is asked to revive . "
+ local svc; for svc in $(getServices); do
+ execute checkSvc $svc || restartSvc $svc || log "ERROR: failed to restart '$svc' ($?)."
+ done
+ log "INFO: Application revived successfully . "
+}
+
+_check() {
+ local svc; for svc in $(getServices); do
+ execute checkSvc $svc || (log "ERROR: $svc failed the health check . " && return 1)
+ done
+}
+
+_start() {
+ isNodeInitialized || {
+ execute initNode
+ systemctl restart rsyslog # output to log files under /data
+ }
+ local svc; for svc in $(getServices); do
+ startSvc $svc || (log "ERROR: service $svc failed to start . " && return 1)
+ done
+}
+
+_stop() {
+ local svc; for svc in $(getServices -a | xargs -n1 | tac); do
+ stopSvc $svc
+ done
+}
+
+_restart() {
+ log "INFO: Application is asked to restart . "
+ execute stop
+ execute start
+ log "INFO: Application restarted successfully . "
+}
+
+_reload() {
+ if ! isNodeInitialized; then return 0; fi # only reload after initialized
+ local svcs="${@:-$(getServices -a)}"
+ local svc; for svc in $(echo $svcs | xargs -n1 | tac); do stopSvc $svc; done
+ local svc; for svc in $svcs; do
+ if isSvcEnabled $svc; then
+ log "INFO: $svc is asked to reload by appctl . "
+ startSvc $svc
+ log "INFO: $svc reloaded successfully . "
+ fi
+ done
+}
+
+applyEnvFiles
+applyRoleScripts
+
+[ "$APPCTL_ENV" == "dev" ] && set -x
+set -eo pipefail
+
+execute preCheck
+execute $command $args
diff --git a/ansible/roles/appctl/files/opt/app/bin/envs/appctl.env b/ansible/roles/appctl/files/opt/app/bin/envs/appctl.env
new file mode 100644
index 0000000..3e167db
--- /dev/null
+++ b/ansible/roles/appctl/files/opt/app/bin/envs/appctl.env
@@ -0,0 +1 @@
+APPCTL_ENV=prod
diff --git a/ansible/roles/appctl/files/opt/app/bin/envs/readme.md b/ansible/roles/appctl/files/opt/app/bin/envs/readme.md
new file mode 100644
index 0000000..0bae9b9
--- /dev/null
+++ b/ansible/roles/appctl/files/opt/app/bin/envs/readme.md
@@ -0,0 +1,7 @@
+This directory holds env files, e.g.
+
+svc-rabbitmq-server.env:
+
+```env
+SERVICES="$SERVICES rabbitmq-server/true/tcp:5672,http:15672"
+```
\ No newline at end of file
diff --git a/ansible/roles/appctl/files/opt/app/bin/node/readme.md b/ansible/roles/appctl/files/opt/app/bin/node/readme.md
new file mode 100644
index 0000000..fae06e7
--- /dev/null
+++ b/ansible/roles/appctl/files/opt/app/bin/node/readme.md
@@ -0,0 +1 @@
+Place node-specific scripts under this directory.
\ No newline at end of file
diff --git a/ansible/roles/appctl/files/opt/app/bin/tmpl/readme.md b/ansible/roles/appctl/files/opt/app/bin/tmpl/readme.md
new file mode 100644
index 0000000..9835102
--- /dev/null
+++ b/ansible/roles/appctl/files/opt/app/bin/tmpl/readme.md
@@ -0,0 +1 @@
+This directory holds bundled confd template files.
diff --git a/ansible/roles/appctl/meta/main.yml b/ansible/roles/appctl/meta/main.yml
new file mode 100644
index 0000000..a995235
--- /dev/null
+++ b/ansible/roles/appctl/meta/main.yml
@@ -0,0 +1,13 @@
+galaxy_info:
+ role_name: appctl
+ role_version: 1.0.9
+ author: Hongliang Wang
+ description: installs appctl
+
+ license: Apache
+
+ min_ansible_version: 2.4
+
+ galaxy_tags: []
+
+dependencies: []
diff --git a/ansible/roles/appctl/tasks/main.yml b/ansible/roles/appctl/tasks/main.yml
new file mode 100644
index 0000000..8851e37
--- /dev/null
+++ b/ansible/roles/appctl/tasks/main.yml
@@ -0,0 +1,46 @@
+---
+- name: copy logging config files
+ copy:
+ src: files/{{ path }}/
+ dest: /{{ path }}
+ owner: root
+ group: root
+ mode: u=rw,go=r
+ loop:
+ - etc/logrotate.d
+ - etc/rsyslog.d
+ loop_control:
+ loop_var: path
+
+- name: create svc group
+ group:
+ name: svc
+ state: present
+
+- name: copy app files
+ copy:
+ src: files/opt/app/
+ dest: /opt/app
+ owner: root
+ group: svc
+ mode: preserve
+ directory_mode: u=rwx,g=rx,o=
+
+- name: Change file permissions
+ file:
+ path: /opt/app/bin/ctl.sh
+ mode: '0755'
+
+- name: create symbolic link
+ file:
+ src: /opt/app/bin/ctl.sh
+ dest: /usr/bin/appctl
+ state: link
+
+- name: set up dev env
+ copy:
+ dest: /opt/app/bin/envs/appdev.env
+ content: |
+ APPCTL_ENV=dev
+
+ when: target_env == 'dev'
diff --git a/ansible/roles/arping/tasks/main.yml b/ansible/roles/arping/tasks/main.yml
new file mode 100644
index 0000000..c71d0b2
--- /dev/null
+++ b/ansible/roles/arping/tasks/main.yml
@@ -0,0 +1,45 @@
+---
+- name: set up variables
+ set_fact:
+ arping_version: "{{ arping_version | d('20211215-1') }}"
+ os: "{{ os | d(default_os) }}"
+ arch: "{{ arch | d(default_arch) }}"
+
+- name: set up url_prefix for ubuntu amd64
+ set_fact:
+ url_prefix: "http://archive.ubuntu.com/ubuntu"
+ when:
+ - os == 'ubuntu'
+ - arch == 'amd64'
+
+- name: set up url_prefix for ubuntu arm64
+ set_fact:
+ url_prefix: "http://ports.ubuntu.com"
+ when:
+ - os == 'ubuntu'
+ - arch == 'arm64'
+
+# will set var downloaded
+- include_role:
+ name: downloader
+ vars:
+ opts:
+ pkg_name: arping
+ pkg_version: "{{ arping_version }}"
+ pkg_feature: "linux-{{ arch }}"
+ pkg_fileType: ".deb"
+ pkg_url: "{{ url_prefix }}/pool/main/i/iputils/iputils-arping_{{ arping_version }}_{{ arch }}.deb"
+ when: os == 'ubuntu'
+
+- name: copy file
+ copy:
+ src: "{{ downloaded }}"
+ dest: "/tmp"
+ when: os == 'ubuntu'
+
+- name: install
+ apt:
+ deb: "/tmp/{{ downloaded | basename }}"
+ policy_rc_d: 101
+ state: present
+ when: os == 'ubuntu'
\ No newline at end of file
diff --git a/ansible/roles/caddy/files/lib/systemd/system/caddy.service b/ansible/roles/caddy/files/lib/systemd/system/caddy.service
new file mode 100644
index 0000000..4e69946
--- /dev/null
+++ b/ansible/roles/caddy/files/lib/systemd/system/caddy.service
@@ -0,0 +1,36 @@
+[Unit]
+Description=Caddy HTTP/2 web server
+Documentation=https://caddyserver.com/docs
+After=network-online.target
+Wants=network-online.target
+ConditionFileNotEmpty=/opt/app/conf/caddy/caddyfile
+
+[Service]
+Restart=on-abnormal
+
+User=caddy
+Group=caddy
+
+Environment=XDG_DATA_HOME=/data
+; Always set "-root" to something safe in case it gets forgotten in the Caddyfile.
+ExecStart=/opt/caddy/current/caddy run --config=/opt/app/conf/caddy/caddyfile
+ExecReload=/bin/kill -USR1 $MAINPID
+
+KillMode=mixed
+KillSignal=SIGQUIT
+TimeoutStopSec=5s
+
+LimitNOFILE=1024
+LimitNPROC=512
+
+PrivateTmp=true
+PrivateDevices=false
+ProtectHome=true
+ProtectSystem=full
+
+CapabilityBoundingSet=CAP_NET_BIND_SERVICE
+AmbientCapabilities=CAP_NET_BIND_SERVICE
+NoNewPrivileges=true
+
+[Install]
+WantedBy=multi-user.target
diff --git a/ansible/roles/caddy/files/opt/app/bin/envs/svc-caddy.env b/ansible/roles/caddy/files/opt/app/bin/envs/svc-caddy.env
new file mode 100644
index 0000000..c98b9d4
--- /dev/null
+++ b/ansible/roles/caddy/files/opt/app/bin/envs/svc-caddy.env
@@ -0,0 +1 @@
+SERVICES="$SERVICES caddy/false/http:80"
\ No newline at end of file
diff --git a/ansible/roles/node-rabbitmq/files/opt/app/conf/rabbitmq-server/enabled-plugins b/ansible/roles/caddy/files/opt/app/conf/caddy/caddyfile
similarity index 100%
rename from ansible/roles/node-rabbitmq/files/opt/app/conf/rabbitmq-server/enabled-plugins
rename to ansible/roles/caddy/files/opt/app/conf/caddy/caddyfile
diff --git a/ansible/roles/caddy/files/opt/app/conf/caddy/templates/print-headers-template.txt b/ansible/roles/caddy/files/opt/app/conf/caddy/templates/print-headers-template.txt
new file mode 100644
index 0000000..2b2f282
--- /dev/null
+++ b/ansible/roles/caddy/files/opt/app/conf/caddy/templates/print-headers-template.txt
@@ -0,0 +1,21 @@
+Remote-Host: {{.Req.Host}}
+Remote-IP: {{.RemoteIP}}
+Client-IP: {{.ClientIP}}
+X-Forwarded-For: {{.Req.Header.Get "X-Forwarded-For"}}
+X-Forwarded-Host: {{.Req.Header.Get "X-Forwarded-Host"}}
+X-Forwarded-Port: {{.Req.Header.Get "X-Forwarded-Port"}}
+X-Forwarded-Proto: {{.Req.Header.Get "X-Forwarded-Proto"}}
+
+{{ if eq (.Req.Header.Get "X-Forwarded-Proto") "https"}}
+I'm https
+{{end}}
+
+Forwarded: {{.Req.Header.Get "Forwarded"}}
+
+UA: {{.Req.Header.Get "User-Agent"}}
+
+All Headers:
+
+{{range $field, $val := .Req.Header}}
+ {{$field}}: {{$val}}
+{{end}}
\ No newline at end of file
diff --git a/ansible/roles/caddy/files/opt/app/conf/caddy/templates/upload-resp-template.txt b/ansible/roles/caddy/files/opt/app/conf/caddy/templates/upload-resp-template.txt
new file mode 100644
index 0000000..a69c5d3
--- /dev/null
+++ b/ansible/roles/caddy/files/opt/app/conf/caddy/templates/upload-resp-template.txt
@@ -0,0 +1,11 @@
+
+http.request.uri.path: {{placeholder "http.request.uri.path"}}
+
+http.request.uuid {{placeholder "http.request.uuid" }}
+http.request.host {{placeholder "http.request.host" }}
+
+http.upload.filename: {{placeholder "http.upload.filename"}}
+http.upload.filesize: {{placeholder "http.upload.filesize"}}
+http.upload.directory: {{placeholder "http.upload.directory"}}
+
+http.upload.uuiddir: {{placeholder "http.upload.uuiddir"}}
diff --git a/ansible/roles/caddy/files/opt/app/conf/caddy/templates/upload-template.html b/ansible/roles/caddy/files/opt/app/conf/caddy/templates/upload-template.html
new file mode 100644
index 0000000..1885c25
--- /dev/null
+++ b/ansible/roles/caddy/files/opt/app/conf/caddy/templates/upload-template.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+ Document
+
+
+
+
+
\ No newline at end of file
diff --git a/ansible/roles/caddy/tasks/main.yml b/ansible/roles/caddy/tasks/main.yml
new file mode 100644
index 0000000..f1636eb
--- /dev/null
+++ b/ansible/roles/caddy/tasks/main.yml
@@ -0,0 +1,69 @@
+---
+- name: set up variables
+ set_fact:
+ caddy_version: "{{ caddy_version | d('v2.8.4') }}"
+ arch: "{{ arch | d(default_arch) }}"
+ installPath: "/opt/caddy"
+
+- name: prepare service group
+ group:
+ name: svc
+ state: present
+
+- name: prepare service user
+ user:
+ name: caddy
+ groups: svc
+ shell: /sbin/nologin
+ create_home: no
+ append: yes
+ comment: "Service User"
+ state: present
+
+- name: prepare binary directory
+ file:
+ path: "{{ installPath }}/{{ caddy_version }}"
+ state: directory
+
+- name: link binary dir
+ file:
+ src: "{{ installPath }}/{{ caddy_version }}"
+ dest: "{{ installPath }}/current"
+ state: link
+
+# will set var downloaded
+- include_role:
+ name: downloader
+ vars:
+ opts:
+ pkg_name: caddy
+ pkg_version: "{{ caddy_version }}"
+ pkg_feature: "linux-{{ arch }}"
+ pkg_fileType: ""
+ pkg_url: https://github.com/djangoyi-yunify/caddy-compiler/releases/download/caddy-{{ caddy_version }}_linux/caddy-{{ arch }}
+
+- name: copy bin file
+ copy:
+ src: "{{ downloaded }}"
+ dest: "{{ installPath }}/{{ caddy_version }}/caddy"
+ mode: "0755"
+
+- name: transfer files
+ copy:
+ src: files/{{ file_path }}
+ dest: /{{ file_path }}
+ owner: root
+ group: root
+ mode: preserve
+ loop:
+ - lib/systemd/system/
+ - opt/app/
+ loop_control:
+ loop_var: file_path
+
+- name: mask caddy service
+ systemd:
+ name: caddy
+ enabled: no
+ masked: yes
+ state: stopped
\ No newline at end of file
diff --git a/ansible/roles/confd-files/files/etc/confd/templates/01.header.sh.tmpl b/ansible/roles/confd-files/files/etc/confd/templates/01.header.sh.tmpl
new file mode 100644
index 0000000..5fa74a8
--- /dev/null
+++ b/ansible/roles/confd-files/files/etc/confd/templates/01.header.sh.tmpl
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+myPath="$0"
+
+cleanUp() {
+ local rc=$?
+ [ "$rc" -eq 0 ] || echo "# Failed ($rc)! Please check confd logs." >> $myPath
+ return $rc
+}
+
+trap cleanUp EXIT
+
+rotate() {
+ local path=$1 maxFilesCount=5
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+}
+
+flush() {
+ local targetFile=$1
+ if [ -n "$targetFile" ]; then
+ rotate $targetFile
+ cat > $targetFile -
+ else
+ cat -
+ fi
+}
+
+applyEnvs() {
+ local -r envFile=/opt/app/bin/envs/confd.env
+ if [ -f "$envFile" ]; then . $envFile; fi
+ local -r nodeEnvFile=/opt/app/bin/envs/nodectl.env
+ if [ -f "$nodeEnvFile" ]; then . $nodeEnvFile; fi
+}
+
+applyEnvs
diff --git a/ansible/roles/confd-files/meta/main.yml b/ansible/roles/confd-files/meta/main.yml
new file mode 100644
index 0000000..8913e8e
--- /dev/null
+++ b/ansible/roles/confd-files/meta/main.yml
@@ -0,0 +1,13 @@
+galaxy_info:
+ role_name: confd-files
+ role_version: 1.0.2
+ author: Hongliang Wang
+ description: installs confd-files
+
+ license: Apache
+
+ min_ansible_version: 2.9
+
+ galaxy_tags: []
+
+dependencies: []
diff --git a/ansible/roles/confd-files/tasks/main.yml b/ansible/roles/confd-files/tasks/main.yml
new file mode 100644
index 0000000..c175cf4
--- /dev/null
+++ b/ansible/roles/confd-files/tasks/main.yml
@@ -0,0 +1,40 @@
+---
+- name: compile
+ shell: |
+ compileTmpls() {
+ local commonFiles="$(ls {{ role_path }}/files/etc/confd/templates/*)"
+ local srcFiles="$commonFiles ${@:2}" destFile=$1
+ for tmpl in $srcFiles; do
+ (cat $tmpl; echo) >> $destFile
+ done
+ }
+
+ set -euo pipefail
+
+ parentRolePath="{{ ansible_parent_role_paths[0] }}"
+ srcRootDir="$parentRolePath/files/etc/confd/templates"
+ [ -d "$srcRootDir" ]
+ destDir=$parentRolePath/files/tmp/confd/templates
+ mkdir -p $destDir
+ rm -rf $destDir/*
+ for srcDir in $(ls -d $srcRootDir/*); do
+ compileTmpls $destDir/$(basename $srcDir).tmpl $(ls $srcDir/*)
+ done
+ args:
+ executable: /bin/bash
+ delegate_to: localhost
+ run_once: True
+
+- name: install
+ copy:
+ src: "{{ ansible_parent_role_paths[0] }}/files/{{ path.src }}/"
+ dest: /etc/confd/{{ path.dest }}/
+ owner: root
+ group: root
+ loop:
+ - src: etc/confd/conf.d
+ dest: conf.d
+ - src: tmp/confd/templates
+ dest: templates
+ loop_control:
+ loop_var: path
diff --git a/ansible/roles/crashkernel/tasks/main.yml b/ansible/roles/crashkernel/tasks/main.yml
new file mode 100644
index 0000000..6e2d146
--- /dev/null
+++ b/ansible/roles/crashkernel/tasks/main.yml
@@ -0,0 +1,27 @@
+- name: set up variables
+ set_fact:
+ os: "{{ os | d(default_os) }}"
+
+- name: Remove crashkernel parameter from GRUB_CMDLINE_LINUX
+ replace:
+ path: /etc/default/grub
+ regexp: 'crashkernel=[^ \"]*'
+ replace: ''
+ when: os == 'kylin'
+
+- name: update GRUB for efi
+ command:
+ grub2-mkconfig -o /boot/efi/EFI/kylin/grub.cfg
+ when: os == 'kylin'
+
+- name: update GRUB for bios
+ command:
+ grub2-mkconfig -o /boot/grub2/grub.cfg
+ when: os == 'kylin'
+
+- name: disable kdump.service
+ systemd:
+ name: kdump.service
+ state: stopped
+ enabled: no
+ when: os == 'kylin'
\ No newline at end of file
diff --git a/ansible/roles/disable-apt-jobs/meta/main.yml b/ansible/roles/disable-apt-jobs/meta/main.yml
new file mode 100644
index 0000000..b8c81f8
--- /dev/null
+++ b/ansible/roles/disable-apt-jobs/meta/main.yml
@@ -0,0 +1,13 @@
+galaxy_info:
+ role_name: disable-apt-jobs
+ role_version: 1.0.0
+ author: Hongliang Wang
+ description: disable apt jobs
+
+ license: Apache
+
+ min_ansible_version: 2.4
+
+ galaxy_tags: []
+
+dependencies: []
diff --git a/ansible/roles/disable-apt-jobs/tasks/main.yml b/ansible/roles/disable-apt-jobs/tasks/main.yml
new file mode 100644
index 0000000..c461176
--- /dev/null
+++ b/ansible/roles/disable-apt-jobs/tasks/main.yml
@@ -0,0 +1,16 @@
+---
+- name: disable apt auto upgrade
+ systemd:
+ name: "{{ svc_name }}"
+ state: stopped
+ masked: yes
+ loop:
+ - apt-daily.timer
+ - apt-daily.service
+ - apt-daily-upgrade.timer
+ - apt-daily-upgrade.service
+ loop_control:
+ loop_var: svc_name
+
+- name: fix apt issues
+ shell: dpkg --configure -a
diff --git a/ansible/roles/disable-motd/meta/main.yml b/ansible/roles/disable-motd/meta/main.yml
new file mode 100644
index 0000000..9bdfd23
--- /dev/null
+++ b/ansible/roles/disable-motd/meta/main.yml
@@ -0,0 +1,13 @@
+galaxy_info:
+ role_name: disable-motd
+ role_version: 1.0.0
+ author: Hongliang Wang
+ description: disable motd
+
+ license: Apache
+
+ min_ansible_version: 2.4
+
+ galaxy_tags: []
+
+dependencies: []
diff --git a/ansible/roles/disable-motd/tasks/main.yml b/ansible/roles/disable-motd/tasks/main.yml
new file mode 100644
index 0000000..929ffa7
--- /dev/null
+++ b/ansible/roles/disable-motd/tasks/main.yml
@@ -0,0 +1,33 @@
+---
+- name: set vars
+ set_fact:
+ os: "{{ os | d(default_os) }}"
+
+- name: ubuntu
+ file:
+ path: "{{ remote_usr.home }}/.hushlogin"
+ owner: "{{ remote_usr.name }}"
+ state: touch
+ loop:
+ - name: ubuntu
+ home: /home/ubuntu
+ - name: root
+ home: /root
+ loop_control:
+ loop_var: remote_usr
+ when: os == 'ubuntu'
+
+- name: kylin - cockpit
+ file:
+ src: /dev/null
+ dest: /etc/motd.d/cockpit
+ state: link
+ force: yes
+ when: os == 'kylin'
+
+- name: kylin - /etc/motd
+ copy:
+ content: ""
+ dest: /etc/motd
+ force: yes
+ when: os == 'kylin'
\ No newline at end of file
diff --git a/ansible/roles/disable-package-manager-timers/tasks/main.yml b/ansible/roles/disable-package-manager-timers/tasks/main.yml
new file mode 100644
index 0000000..3d3660a
--- /dev/null
+++ b/ansible/roles/disable-package-manager-timers/tasks/main.yml
@@ -0,0 +1,59 @@
+---
+- name: set vars
+ set_fact:
+ os: "{{ os | d(default_os) }}"
+ osv: "{{ osv | d(default_osv) }}"
+
+- name: ubuntu
+ systemd:
+ name: "{{ svc_name }}"
+ state: stopped
+ masked: yes
+ loop:
+ - apt-daily.timer
+ - apt-daily.service
+ - apt-daily-upgrade.timer
+ - apt-daily-upgrade.service
+ loop_control:
+ loop_var: svc_name
+ when: os == 'ubuntu'
+
+- name: ubuntu fix apt issues
+ shell: dpkg --configure -a
+ when: os == 'ubuntu'
+
+- name: kylin - 10sp2
+ systemd:
+ name: "{{ svc_name }}"
+ state: stopped
+ masked: yes
+ loop:
+ - dnf-automatic-download.timer
+ - dnf-automatic-download.service
+ - dnf-automatic-install.timer
+ - dnf-automatic-install.service
+ - dnf-automatic-notifyonly.timer
+ - dnf-automatic-notifyonly.service
+ - dnf-automatic.timer
+ - dnf-automatic.service
+ - dnf-makecache.timer
+ - dnf-makecache.service
+ loop_control:
+ loop_var: svc_name
+ when:
+ - os == 'kylin'
+ - osv == '10sp2'
+
+- name: kylin - 10sp3
+ systemd:
+ name: "{{ svc_name }}"
+ state: stopped
+ masked: yes
+ loop:
+ - dnf-makecache.timer
+ - dnf-makecache.service
+ loop_control:
+ loop_var: svc_name
+ when:
+ - os == 'kylin'
+ - osv == '10sp3'
\ No newline at end of file
diff --git a/ansible/roles/downloader/tasks/main.yml b/ansible/roles/downloader/tasks/main.yml
new file mode 100644
index 0000000..a1927ee
--- /dev/null
+++ b/ansible/roles/downloader/tasks/main.yml
@@ -0,0 +1,34 @@
+---
+- name: set up variables
+ set_fact:
+ local_cache_path: "{{ local_cache_path | d('file/tmp') }}"
+ pkg_name: "{{ opts.pkg_name }}"
+ pkg_version: "{{ opts.pkg_version }}"
+ pkg_feature: "{{ opts.pkg_feature }}"
+ pkg_fileType: "{{ opts.pkg_fileType }}"
+ pkg_url: "{{ opts.pkg_url }}"
+
+- name: prepare dir
+ file:
+ path: "{{ local_cache_path }}/{{ pkg_name }}"
+ state: directory
+ mode: '0755'
+ delegate_to: localhost
+
+- name: check if file exists
+ stat:
+ path: "{{ local_cache_path }}/{{ pkg_name }}/{{ pkg_name }}-{{ pkg_version }}-{{ pkg_feature }}{{ pkg_fileType }}"
+ register: cached_file
+ delegate_to: localhost
+
+- name: download file
+ get_url:
+ url: "{{ pkg_url }}"
+ dest: "{{ local_cache_path }}/{{ pkg_name }}/{{ pkg_name }}-{{ pkg_version }}-{{ pkg_feature }}{{ pkg_fileType }}"
+ delegate_to: localhost
+ when:
+ - cached_file.stat.exists == false
+
+- name: setup output
+ set_fact:
+ downloaded: "{{ local_cache_path }}/{{ pkg_name }}/{{ pkg_name }}-{{ pkg_version }}-{{ pkg_feature }}{{ pkg_fileType }}"
diff --git a/ansible/roles/haproxy/tasks/main.yml b/ansible/roles/haproxy/tasks/main.yml
deleted file mode 100644
index 47a1156..0000000
--- a/ansible/roles/haproxy/tasks/main.yml
+++ /dev/null
@@ -1,33 +0,0 @@
----
-- name: install haproxy plugins
- apt:
- name: ['hatop','arping','software-properties-common']
- update_cache: yes
- state: present
-
-- name: add-apt-repository
- apt_repository:
- repo: "ppa:vbernat/haproxy-{{ haproxy_version }}"
-
-- name: install haproxy
- apt:
- name: "haproxy={{ haproxy_version }}.*"
- update_cache: yes
- state: present
-
-- name: copy binaries
- copy:
- src: files/lib/
- dest: /lib
- owner: root
- group: root
- mode: preserve
- directory_mode: u=rwx,g=rx,o=
-
-- name: disable auto startup on boot
- systemd:
- name: haproxy
- enabled: no
- masked: yes
- state: stopped
-
diff --git a/ansible/roles/install/meta/main.yml b/ansible/roles/install/meta/main.yml
new file mode 100644
index 0000000..c461b3b
--- /dev/null
+++ b/ansible/roles/install/meta/main.yml
@@ -0,0 +1,13 @@
+galaxy_info:
+ role_name: install
+ role_version: 1.0.5
+ author: Hongliang Wang
+ description: download files with local cache and install
+
+ license: Apache
+
+ min_ansible_version: 2.9
+
+ galaxy_tags: []
+
+dependencies: []
diff --git a/ansible/roles/install/tasks/main.yml b/ansible/roles/install/tasks/main.yml
new file mode 100644
index 0000000..2b89787
--- /dev/null
+++ b/ansible/roles/install/tasks/main.yml
@@ -0,0 +1,114 @@
+---
+- name: set up default home var
+ set_fact:
+ default_dest_dir: "/opt/{{ opts.pkg_name }}/{{ opts.pkg_version }}/"
+ when: opts.pkg_version is defined
+
+- name: set up variables
+ set_fact:
+ dest_path: "{{ opts.dest_path | d(default_dest_dir) }}"
+ pkg_name: "{{ opts.pkg_name }}"
+ pkg_type: "{{ opts.pkg_type | d('') }}"
+ pkg_version: "{{ opts.pkg_version | d('') }}"
+ extracts: "{{ opts.extracts | d(false) }}"
+ extra_opts: "{{ opts.extra_opts | d(['--strip-components=1'] if opts.pkg_type == 'tgz' else []) }}"
+ creates: "{{ opts.creates | d('') }}"
+ parent_role_name: "{{ ansible_parent_role_names[0] | regex_replace('-[0-9.]+$', '') }}"
+ target_owner: "{{ opts.target_owner | d('root') }}"
+ target_group: "{{ opts.target_group | d('root') }}"
+
+- name: set other variables
+ set_fact:
+ local_path: "{{ local_cache_path }}/{{ parent_role_name }}/{{ opts.local_path + '/' if opts.local_path is defined else '' }}{{ pkg_name }}{{ '-' + pkg_version if pkg_version else '' }}{{ '.' + pkg_type if pkg_type else '' }}"
+
+- name: install tools
+ apt:
+ name: ['unzip']
+ state: present
+ update_cache: no
+ when:
+ - extracts
+ - pkg_type == 'zip'
+
+- name: check if package file exists
+ stat:
+ path: "{{ local_path }}"
+ register: cached_file
+ run_once: True
+ delegate_to: localhost
+
+- name: prepare local dir
+ file:
+ dest: "{{ local_path | dirname }}"
+ state: directory
+ delegate_to: localhost
+ when:
+ - cached_file.stat.exists == False
+
+- name: download package - {{ pkg_name }}
+ get_url:
+ url: "{{ opts.pkg_url }}"
+ dest: "{{ local_path }}"
+ delegate_to: localhost
+ run_once: True
+ when:
+ - cached_file.stat.exists == False
+
+- name: Prepare directories - {{ pkg_name }}
+ file:
+ path: "{{ dest_path if extracts or dest_path[-1] == '/' else dest_path | dirname }}"
+ owner: "{{ target_owner }}"
+ group: "{{ target_group }}"
+ state: directory
+
+- name: extract package - {{ pkg_name }}
+ unarchive:
+ src: "{{ local_path }}"
+ dest: "{{ dest_path }}"
+ owner: "{{ target_owner }}"
+ group: "{{ target_group }}"
+ creates: "{{ dest_path | regex_replace('/*$', '') }}/{{ creates }}"
+ extra_opts: "{{ extra_opts }}"
+ when:
+ - extracts
+
+- name: set permissions - {{ pkg_name }}
+ file:
+ path: "{{ dest_path }}"
+ owner: "{{ target_owner }}"
+ group: "{{ target_group }}"
+ recurse: yes
+ when:
+ - extracts
+
+- name: transfer package - {{ pkg_name }}0
+ copy:
+ src: "{{ local_path }}"
+ dest: "{{ dest_path }}"
+ mode: "{{ opts.file_mode | d('644') }}"
+ when:
+ - extracts == False
+
+- name: create symbolic link - {{ pkg_name }}
+ file:
+ src: "{{ pkg_version }}"
+ dest: "/opt/{{ pkg_name }}/current"
+ state: link
+ when: dest_path == default_dest_dir
+
+- name: add bin path to PATH
+ copy:
+ dest: /etc/profile.d/{{ pkg_name }}-path.sh
+ content: PATH={{ dest_path | regex_replace('/*$', '') }}/{{ opts.bin_path }}:$PATH
+ when: opts.bin_path is defined
+
+- name: create bin symbolic links - {{ pkg_name }}
+ file:
+ src: "{{ '/opt/' + pkg_name + '/current' if dest_path == default_dest_dir else dest_path }}{{ '/' + bin_link.src if bin_link.src else '' }}"
+ dest: "{{ bin_link.dest | d('/usr/bin/' + (bin_link.src | basename)) }}"
+ force: yes
+ state: link
+ loop: "{{ opts.bin_links }}"
+ loop_control:
+ loop_var: bin_link
+ when: opts.bin_links is defined
diff --git a/ansible/roles/jq/tasks/main.yml b/ansible/roles/jq/tasks/main.yml
new file mode 100644
index 0000000..8f3b68b
--- /dev/null
+++ b/ansible/roles/jq/tasks/main.yml
@@ -0,0 +1,40 @@
+---
+- name: set up variables
+ set_fact:
+ jq_version: "{{ jq_version | d('1.7') }}"
+ arch: "{{ arch | d(default_arch) }}"
+ installPath: "/opt/jq"
+
+# will set var downloaded
+- include_role:
+ name: downloader
+ vars:
+ opts:
+ pkg_name: jq
+ pkg_version: "{{ jq_version }}"
+ pkg_feature: "linux-{{ arch }}"
+ pkg_fileType: ""
+ pkg_url: https://github.com/jqlang/jq/releases/download/jq-{{ jq_version }}/jq-linux-{{ arch }}
+
+- name: prepare dir
+ file:
+ path: "{{ installPath }}/{{ jq_version }}"
+ state: directory
+
+- name: copy file
+ copy:
+ src: "{{ downloaded }}"
+ dest: "{{ installPath }}/{{ jq_version }}/jq"
+ mode: "0755"
+
+- name: link for current
+ file:
+ src: "{{ installPath }}/{{ jq_version }}"
+ dest: "{{ installPath }}/current"
+ state: link
+
+- name: link for jq
+ file:
+ src: "{{ installPath }}/current/jq"
+ dest: "/usr/bin/jq"
+ state: link
\ No newline at end of file
diff --git a/ansible/roles/keepalived/tasks/main.yml b/ansible/roles/keepalived/tasks/main.yml
deleted file mode 100644
index 8035964..0000000
--- a/ansible/roles/keepalived/tasks/main.yml
+++ /dev/null
@@ -1,67 +0,0 @@
----
-- name: Prepare dev env for keepalived
- apt:
- update_cache: yes
- name: ['tree', 'curl', 'gcc', 'libssl-dev', 'libnl-3-dev', 'libnl-genl-3-dev', 'libsnmp-dev', 'make']
- state: present
- delegate_to: localhost
-
-- name: Prepare directories for keepalived
- file:
- path: /etc/keepalived
- owner: root
- group: root
- state: directory
-
-- name: download keepalived
- include_role:
- name: install-1.0.5
- vars:
- opts:
- pkg_name: keepalived
- pkg_version: "{{ item }}"
- pkg_type: tgz
- pkg_url: "https://www.keepalived.org/software/keepalived-{{ item }}.tar.gz"
- extracts: yes
- creates: "configure"
- bin_path:
- with_items: "{{ keepalived_version }}"
-
-- name: build keepalived
- vars:
- build_path: "/root/.ansible/cache/keepalived/keepalived-{{ keepalived_version }}/build-dir"
- shell: |
- tar -zxvf keepalived-{{ keepalived_version }}.tgz
- cd keepalived-{{ keepalived_version }}/
- ./configure --prefix={{ build_path }}
- make
- sudo make install
- args:
- chdir: "/root/.ansible/cache/keepalived"
- creates: "{{ build_path }}/bin/keepalived"
- delegate_to: localhost
-
-- name: install keepalived bin
- copy:
- src: "{{ item }}"
- dest: /opt/keepalived/{{ keepalived_version }}
- owner: root
- group: root
- mode: preserve
- directory_mode: u=rwx,g=rx,o=
- with_items:
- - "/root/.ansible/cache/keepalived/keepalived-{{ keepalived_version }}/build-dir/"
- - "files/lib/"
-
-- name: create keepalived service link
- file:
- src: /opt/keepalived/current/systemd/system/keepalived.service
- dest: /lib/systemd/system/keepalived.service
- state: link
-
-- name: mask services
- systemd:
- name: keepalived
- enabled: no
- masked: yes
- state: stopped
\ No newline at end of file
diff --git a/ansible/roles/ncncat/tasks/main.yml b/ansible/roles/ncncat/tasks/main.yml
new file mode 100644
index 0000000..d710bd7
--- /dev/null
+++ b/ansible/roles/ncncat/tasks/main.yml
@@ -0,0 +1,23 @@
+- name: set up variables
+ set_fact:
+ os: "{{ os | d(default_os) }}"
+
+- name: install ncat on ubuntu
+ apt:
+ name: "ncat"
+ state: present
+ when: os == 'ubuntu'
+
+- name: link nc to ncat
+ file:
+ src: /usr/bin/ncat
+ dest: /usr/bin/nc
+ state: link
+ force: yes
+ when: os == "ubuntu"
+
+- name: Install nc and ncat on kylin
+ dnf:
+ name: "nmap"
+ state: present
+ when: os == 'kylin'
\ No newline at end of file
diff --git a/ansible/roles/node-all/files/etc/confd/conf.d/nodectl.sh.toml b/ansible/roles/node-all/files/etc/confd/conf.d/0-nodectl.sh.toml
similarity index 100%
rename from ansible/roles/node-all/files/etc/confd/conf.d/nodectl.sh.toml
rename to ansible/roles/node-all/files/etc/confd/conf.d/0-nodectl.sh.toml
diff --git a/ansible/roles/node-all/files/etc/confd/conf.d/journal.sh.toml b/ansible/roles/node-all/files/etc/confd/conf.d/journal.sh.toml
new file mode 100644
index 0000000..e7e4538
--- /dev/null
+++ b/ansible/roles/node-all/files/etc/confd/conf.d/journal.sh.toml
@@ -0,0 +1,8 @@
+[template]
+src = "journal.sh.tmpl"
+dest = "/opt/app/bin/tmpl/journal.sh"
+mode = "0700"
+keys = [
+ "/",
+]
+reload_cmd = "/opt/app/bin/tmpl/journal.sh; systemctl restart rsyslog"
diff --git a/ansible/roles/node-all/files/etc/confd/templates/appctl.sh/01.appctl.env.tmpl b/ansible/roles/node-all/files/etc/confd/templates/appctl.sh/01.appctl.env.tmpl
index a078af2..4ef8b5f 100644
--- a/ansible/roles/node-all/files/etc/confd/templates/appctl.sh/01.appctl.env.tmpl
+++ b/ansible/roles/node-all/files/etc/confd/templates/appctl.sh/01.appctl.env.tmpl
@@ -1,5 +1,6 @@
-
+mkdir -p /opt/app/conf/appctl
flush /opt/app/bin/envs/appctl.env << APPCTL_ENV_EOF
+APPCTL_NODE_FILE=/opt/app/conf/appctl/node.init
MY_IP={{ getv "/host/ip" }}
MY_ROLE={{ getv "/host/role" }}
CLUSTER_ID={{ getv "/cluster/cluster_id" }}
@@ -16,6 +17,13 @@ RAM_NODES="$(echo "
{{ getv (printf "/hosts/ram/%s/sid" .) }}/{{ getv (printf "/hosts/ram/%s/instance_id" .) }}/{{ getv (printf "/hosts/ram/%s/ip" .) }}
{{- end }}
" | xargs -n1 | sort -V | xargs)"
-
+{{ if (exists "/links/etcd_service/cluster/cluster_id") and (ne (getv "/links/etcd_service/cluster/cluster_id")) }}
+PEER_DISCOVERY_BACKEND_TYPE=etcd
+{{ else }}
+PEER_DISCOVERY_BACKEND_TYPE=classic_config
+{{ end }}
+PATH=/opt/rabbitmq/current/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
+export RABBITMQ_HOME=/opt/rabbitmq/current
+export HOME=/root
APPCTL_ENV_EOF
diff --git a/ansible/roles/node-all/files/etc/confd/templates/journal.sh/01.journald.conf.tmpl b/ansible/roles/node-all/files/etc/confd/templates/journal.sh/01.journald.conf.tmpl
new file mode 100644
index 0000000..d2a66bb
--- /dev/null
+++ b/ansible/roles/node-all/files/etc/confd/templates/journal.sh/01.journald.conf.tmpl
@@ -0,0 +1,16 @@
+{{- if not (getvs "/host/role" | filter "client") }}
+mkdir -p ${DATA_MOUNTS}/log/journald/
+chmod 755 ${DATA_MOUNTS}/log/journald/
+chown syslog:svc ${DATA_MOUNTS}/log/journald/
+flush /etc/rsyslog.d/49-journald.conf << JOURNALD_CONFIG_EOF
+module(load="imjournal" PersistStateInterval="100") #load imjournal module
+module(load="mmjsonparse") #load mmjsonparse module for structured logs
+
+#template(name="CEETemplate" type="string" string="%TIMESTAMP% %HOSTNAME% %syslogtag% @cee: %$!all-json%\n" ) #template for messages
+
+#action(type="mmjsonparse")
+#action(type="omfile" file="${DATA_MOUNTS}/log/journald/journald.log" template="CEETemplate")
+action(type="omfile" file="${DATA_MOUNTS}/log/journald/journald.log" FileOwner="syslog" FileGroup="svc" FileCreateMode="0640" DirCreateMode="0755")
+
+JOURNALD_CONFIG_EOF
+{{- end }}
\ No newline at end of file
diff --git a/ansible/roles/node-all/files/etc/confd/templates/journal.sh/02.logrotate.tmpl b/ansible/roles/node-all/files/etc/confd/templates/journal.sh/02.logrotate.tmpl
new file mode 100644
index 0000000..e65257a
--- /dev/null
+++ b/ansible/roles/node-all/files/etc/confd/templates/journal.sh/02.logrotate.tmpl
@@ -0,0 +1,16 @@
+{{- if not (getvs "/host/role" | filter "client") }}
+flush /etc/logrotate.d/journald << LOGROTATE_EOF
+${DATA_MOUNTS}/log/journald/journald.log {
+ daily
+ rotate 20
+ missingok
+ notifempty
+ compress
+ delaycompress
+ copytruncate
+ postrotate
+ /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
+ endscript
+}
+LOGROTATE_EOF
+{{- end }}
\ No newline at end of file
diff --git a/ansible/roles/node-all/files/etc/confd/templates/nodectl.sh/01.nodectl.env.tmpl b/ansible/roles/node-all/files/etc/confd/templates/nodectl.sh/01.nodectl.env.tmpl
index a7d523b..27d7076 100644
--- a/ansible/roles/node-all/files/etc/confd/templates/nodectl.sh/01.nodectl.env.tmpl
+++ b/ansible/roles/node-all/files/etc/confd/templates/nodectl.sh/01.nodectl.env.tmpl
@@ -1,23 +1,44 @@
+{{- if getvs "/host/role" | filter "client" }}
+getSshServiceName() {
+ local res
+ res=$(grep '^ID=' /etc/os-release | cut -d= -f2- | tr -d '"')
+ if [ "$res" = "kylin" ]; then
+ echo "sshd"
+ return 0
+ fi
+ echo "ssh"
+}
+tmpSshName=$(getSshServiceName)
+{{- end }}
flush /opt/app/bin/envs/nodectl.env << NODE_ENV_EOF
{{- if getvs "/host/role" | filter "(disc|ram)" }}
SERVICES="\$SERVICES
-rabbitmq-server/true/tcp:5672,http:15672"
+rabbitmq-server/true/tcp:5672"
NODE_CTL="rabbitmq-node"
DATA_MOUNTS="/data"
MY_HYPER_TYPE={{ getv "/host/hypervisor" }}
{{- else if getvs "/host/role" | filter "haproxy" }}
SERVICES="\$SERVICES \$(echo "
{{- $HPPORT := getv "/env/haproxy_web_port" "8100" }}
-haproxy/true/tcp:5672,http:15672,tcp:61613,tcp:1883,http:{{ $HPPORT }}
+haproxy/true/http:{{ $HPPORT }}
keepalived/true/
" | xargs)"
-DATA_MOUNTS=""
+DATA_MOUNTS="/data"
MY_HYPER_TYPE={{ getv "/host/hypervisor" }}
NODE_CTL="proxy-node"
{{- else if getvs "/host/role" | filter "client" }}
-SERVICES="\$SERVICES ssh/true/tcp:22"
+SERVICES="\$SERVICES $tmpSshName/{{ getv "/env/ssh_enabled" }}/tcp:22"
NODE_CTL="client-node"
DATA_MOUNTS=""
MY_HYPER_TYPE={{ getv "/host/hypervisor" }}
{{- end }}
NODE_ENV_EOF
+
+{{- if getvs "/host/role" | filter "client" }}
+# client node will change status of ssh service
+ {{- if eq (getv "/env/ssh_enabled") "true" }}
+systemctl start $tmpSshName || :
+ {{- else }}
+systemctl stop $tmpSshName || :
+ {{- end }}
+{{- end }}
diff --git a/ansible/roles/node-all/tasks/main.yml b/ansible/roles/node-all/tasks/main.yml
index e1c67ea..56e2545 100644
--- a/ansible/roles/node-all/tasks/main.yml
+++ b/ansible/roles/node-all/tasks/main.yml
@@ -1,4 +1,69 @@
---
- name: install confd files
include_role:
- name: confd-files-1.0.2
\ No newline at end of file
+ name: confd-files
+
+- name: Set net.ipv4.tcp_keepalive_time to 30
+ lineinfile:
+ path: /etc/sysctl.conf
+ line: 'net.ipv4.tcp_keepalive_time=30'
+ regexp: '^net.ipv4.tcp_keepalive_time=3'
+ state: present
+
+- name: Set net.ipv4.tcp_keepalive_intvl to 10
+ lineinfile:
+ path: /etc/sysctl.conf
+ line: 'net.ipv4.tcp_keepalive_intvl=10'
+ regexp: '^net.ipv4.tcp_keepalive_intvl='
+ state: present
+
+- name: Set net.ipv4.tcp_keepalive_probes to 4
+ lineinfile:
+ path: /etc/sysctl.conf
+ line: 'net.ipv4.tcp_keepalive_probes=4'
+ regexp: '^net.ipv4.tcp_keepalive_probes='
+ state: present
+
+- name: Set net.ipv4.ip_local_port_range to 102465023
+ lineinfile:
+ path: /etc/sysctl.conf
+ line: 'net.ipv4.ip_local_port_range=102465023'
+ regexp: '^net.ipv4.ip_local_port_range='
+ state: present
+
+- name: Set net.core.somaxconn to 65535
+ lineinfile:
+ path: /etc/sysctl.conf
+ line: 'net.core.somaxconn=65535'
+ regexp: '^net.core.somaxconn='
+ state: present
+
+- name: Set net.ipv4.icmp_ratelimit to 10
+ lineinfile:
+ path: /etc/sysctl.conf
+ line: 'net.ipv4.icmp_ratelimit=10'
+ regexp: '^net.ipv4.icmp_ratelimit='
+ state: present
+
+- name: Set net.ipv4.tcp_tw_reuse to 0
+ lineinfile:
+ path: /etc/sysctl.conf
+ line: 'net.ipv4.tcp_tw_reuse=0'
+ regexp: '^net.ipv4.tcp_tw_reuse='
+ state: present
+
+- name: Set net.ipv4.tcp_tw_recycle to 0
+ lineinfile:
+ path: /etc/sysctl.conf
+ line: 'net.ipv4.tcp_tw_recycle=0'
+ regexp: '^net.ipv4.tcp_tw_recycle='
+ state: present
+
+- name: update configuration in /etc/rsyslog.conf
+ ansible.builtin.blockinfile:
+ path: /etc/rsyslog.conf
+ block: |
+ $ModLoad imudp
+ $UDPServerAddress 0.0.0.0
+ $UDPServerRun 514
+ marker: "# {mark} ANSIBLE MANAGED BLOCK FOR UDP CONFIG"
\ No newline at end of file
diff --git a/ansible/roles/node-client/files/opt/app/bin/node/client-node.sh b/ansible/roles/node-client/files/opt/app/bin/node/client-node.sh
index ee84cf2..eda64de 100644
--- a/ansible/roles/node-client/files/opt/app/bin/node/client-node.sh
+++ b/ansible/roles/node-client/files/opt/app/bin/node/client-node.sh
@@ -1,5 +1,5 @@
initNode() {
_initNode
- echo 'root:rabbitmq' | chpasswd
- echo 'ubuntu:rabbitmq' | chpasswd
+ echo 'root:rabbitmq123' | chpasswd
+ echo -e "client\nclient\n" | adduser client > /dev/null 2>&1 && echo "client:rabbitmq123" | chpasswd
}
\ No newline at end of file
diff --git a/ansible/roles/node-proxy/files/etc/confd/conf.d/haproxy.sh.toml b/ansible/roles/node-proxy-keepalived/files/etc/confd/conf.d/haproxy.sh.toml
similarity index 100%
rename from ansible/roles/node-proxy/files/etc/confd/conf.d/haproxy.sh.toml
rename to ansible/roles/node-proxy-keepalived/files/etc/confd/conf.d/haproxy.sh.toml
diff --git a/ansible/roles/node-proxy/files/etc/confd/conf.d/keepalived.sh.toml b/ansible/roles/node-proxy-keepalived/files/etc/confd/conf.d/keepalived.sh.toml
similarity index 100%
rename from ansible/roles/node-proxy/files/etc/confd/conf.d/keepalived.sh.toml
rename to ansible/roles/node-proxy-keepalived/files/etc/confd/conf.d/keepalived.sh.toml
diff --git a/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/haproxy.sh/01.haproxy.cfg.tmpl b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/haproxy.sh/01.haproxy.cfg.tmpl
new file mode 100644
index 0000000..63a72e8
--- /dev/null
+++ b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/haproxy.sh/01.haproxy.cfg.tmpl
@@ -0,0 +1,124 @@
+{{- $enabledPlugins := print (getv "/env/plugins_enabled") "," }}
+flush /opt/app/conf/haproxy/haproxy.cfg << HAPROXY_CONF_EOF
+#logging options
+global
+ log /dev/log local0 info
+ maxconn 65535
+ quiet
+ {{- $cores := getv "/host/cpu" }}
+ nbthread {{ $cores }}
+
+defaults
+ log global
+ mode tcp
+ option tcplog
+ option dontlognull
+ retries 3
+ option redispatch
+ maxconn 65535
+ timeout connect 5s
+ timeout client 120s
+ timeout server 120s
+
+#front-end IP for consumers and producters
+listen rabbitmq_cluster
+ bind :5672
+ mode tcp
+ #balance rdp-cookie
+ #balance leastconn
+ #balance source
+ #balance roundrobin
+ #simple polling
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ #rabbitmq cluster node config
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 2000 rise 3 fall 3 on-marked-down shutdown-sessions {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 2000 rise 3 fall 3 on-marked-down shutdown-sessions {{ end }}
+
+{{- if or (contains $enabledPlugins "rabbitmq_stomp,") (contains $enabledPlugins "rabbitmq_web_stomp,") }}
+#front-end IP for stomp
+listen rabbitmq_cluster_stomp
+ bind :61613
+ #TCP mode
+ mode tcp
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ timeout client 3h
+ timeout server 3h
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:61613 check inter 5000 rise 2 fall 2 {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:61613 check inter 5000 rise 2 fall 2 {{ end }}
+{{- end }}
+
+{{- if contains $enabledPlugins "rabbitmq_web_stomp," }}
+#front-end IP for web_stomp
+listen rabbitmq_cluster_web_stomp
+ bind :15674
+ #TCP mode
+ mode tcp
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ timeout client 3h
+ timeout server 3h
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:61613 check inter 5000 rise 2 fall 2 {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:61613 check inter 5000 rise 2 fall 2 {{ end }}
+{{- end }}
+
+{{- if or (contains $enabledPlugins "rabbitmq_mqtt,") (contains $enabledPlugins "rabbitmq_web_mqtt,") }}
+#front-end IP for mqtt
+listen rabbitmq_cluster_mqtt
+ bind :1883
+ #TCP mode
+ mode tcp
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ timeout client 3h
+ timeout server 3h
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:1883 check inter 5000 rise 2 fall 2 {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:1883 check inter 5000 rise 2 fall 2 {{ end }}
+{{- end }}
+
+{{- if contains $enabledPlugins "rabbitmq_web_mqtt," }}
+#front-end IP for web_mqtt
+listen rabbitmq_cluster_web_mqtt
+ bind :15675
+ #TCP mode
+ mode tcp
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ timeout client 3h
+ timeout server 3h
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:1883 check inter 5000 rise 2 fall 2 {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:1883 check inter 5000 rise 2 fall 2 {{ end }}
+{{- end }}
+
+{{- if contains $enabledPlugins "rabbitmq_management," }}
+#rabbitmq-management
+# optional, for proxying management site
+frontend front_rabbitmq_management
+ bind :15672
+ default_backend backend_rabbitmq_management
+
+backend backend_rabbitmq_management
+ balance source
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:15672 check {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:15672 check {{ end }}
+{{- end }}
+
+# haproxy web monitor infomation
+listen statistics
+ bind :{{ getv "/env/haproxy_web_port" "8100" }}
+ mode http
+ stats enable
+ stats hide-version
+ stats refresh 10s
+ stats uri /
+ stats auth {{ getv "/env/haproxy_username" "haproxy" }}:{{ replace (getv "/env/haproxy_password" "haproxy") `$` `\$` -1 }}
+
+HAPROXY_CONF_EOF
diff --git a/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/haproxy.sh/02.haproxy.log.conf.tmpl b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/haproxy.sh/02.haproxy.log.conf.tmpl
new file mode 100644
index 0000000..166d335
--- /dev/null
+++ b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/haproxy.sh/02.haproxy.log.conf.tmpl
@@ -0,0 +1,25 @@
+{{- if getvs "/host/role" | filter "haproxy" }}
+mkdir -p ${DATA_MOUNTS}/log/haproxy/
+chmod 755 ${DATA_MOUNTS}/log/haproxy/
+chown syslog:svc ${DATA_MOUNTS}/log/haproxy/
+
+flush /etc/rsyslog.d/49-haproxy.conf << HAPROXY_LOG_CONF_EOF
+
+# Create an additional socket in haproxy's chroot in order to allow logging via
+# /dev/log to chroot'ed HAProxy processes
+# \$AddUnixListenSocket /var/lib/haproxy/dev/log
+
+# Send HAProxy messages to a dedicated logfile
+:programname, startswith, "haproxy" {
+ action(
+ type="omfile"
+ file="${DATA_MOUNTS}/log/haproxy/haproxy.log"
+ FileOwner="syslog"
+ FileGroup="svc"
+ FileCreateMode="0640"
+ DirCreateMode="0755"
+ )
+ stop
+}
+HAPROXY_LOG_CONF_EOF
+{{- end }}
diff --git a/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/haproxy.sh/03.logrotate.tmpl b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/haproxy.sh/03.logrotate.tmpl
new file mode 100644
index 0000000..f09c473
--- /dev/null
+++ b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/haproxy.sh/03.logrotate.tmpl
@@ -0,0 +1,15 @@
+
+flush /etc/logrotate.d/haproxy << LOGROTATE_EOF
+${DATA_MOUNTS}/log/haproxy/haproxy.log {
+ daily
+ maxsize 2M
+ rotate 10
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
+ endscript
+}
+LOGROTATE_EOF
\ No newline at end of file
diff --git a/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/01.keepalived.conf.tmpl b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/01.keepalived.conf.tmpl
new file mode 100644
index 0000000..ed426f0
--- /dev/null
+++ b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/01.keepalived.conf.tmpl
@@ -0,0 +1,44 @@
+flush /etc/keepalived/keepalived.conf << KEEPALIVED_EOF
+{{- $replicaIPs := split (getv "/cluster/endpoints/reserved_ips/vip/value") "." }}
+{{- $myIp := getv "/host/ip" }}
+global_defs {
+ enable_script_security
+ script_user root root
+}
+
+vrrp_script check_haproxy {
+ script "/usr/bin/pkill -0 haproxy"
+ interval 2
+ weight 10
+}
+
+vrrp_instance HAProxy_HA {
+ state BACKUP
+ interface eth0
+ virtual_router_id {{ index $replicaIPs 3 }}
+ priority 100
+ advert_int 2
+ unicast_src_ip {{ $myIp }}
+ unicast_peer {
+ {{- range $dir := lsdir "/hosts/haproxy" }}
+ {{- $ip := getv (printf "/hosts/haproxy/%s/ip" $dir) }}
+ {{- if ne $ip $myIp }}
+ {{ $ip }}
+ {{- end }}
+ {{- end }}
+ }
+ authentication {
+ auth_type PASS
+ auth_pass {{ getv "/cluster/cluster_id" }}
+ }
+
+ virtual_ipaddress { #set VIP
+ {{ getv "/cluster/endpoints/reserved_ips/vip/value" }}/32
+ }
+
+ track_script {
+ check_haproxy
+ }
+}
+
+KEEPALIVED_EOF
diff --git a/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/02.keepalived.sysconfig.tmpl b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/02.keepalived.sysconfig.tmpl
new file mode 100644
index 0000000..52f1848
--- /dev/null
+++ b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/02.keepalived.sysconfig.tmpl
@@ -0,0 +1,18 @@
+flush /opt/keepalived/current/etc/sysconfig/keepalived << 'KEEPALIVED_SYSCONFIG_EOF'
+
+# Options for keepalived. See `keepalived --help' output and keepalived(8) and
+# keepalived.conf(5) man pages for a list of all options. Here are the most
+# common ones :
+#
+# --vrrp -P Only run with VRRP subsystem.
+# --check -C Only run with Health-checker subsystem.
+# --dont-release-vrrp -V Dont remove VRRP VIPs & VROUTEs on daemon stop.
+# --dont-release-ipvs -I Dont remove IPVS topology on daemon stop.
+# --dump-conf -d Dump the configuration data.
+# --log-detail -D Detailed log messages.
+# --log-facility -S 0-7 Set local syslog facility (default=LOG_DAEMON)
+#
+
+KEEPALIVED_OPTIONS="-D -d -S 0"
+
+KEEPALIVED_SYSCONFIG_EOF
diff --git a/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/03.keepalived.rsyslog.tmpl b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/03.keepalived.rsyslog.tmpl
new file mode 100644
index 0000000..2d73844
--- /dev/null
+++ b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/03.keepalived.rsyslog.tmpl
@@ -0,0 +1,20 @@
+{{- if getvs "/host/role" | filter "haproxy" }}
+mkdir -p ${DATA_MOUNTS}/log/keepalived/
+chmod 755 ${DATA_MOUNTS}/log/keepalived/
+chown syslog:svc ${DATA_MOUNTS}/log/keepalived/
+flush /etc/rsyslog.d/49-keepalived.conf << KEEPALIVED_LOG_EOF
+
+if \$programname startswith 'Keepalived' then {
+ action(
+ type="omfile"
+ file="${DATA_MOUNTS}/log/keepalived/keepalived.log"
+ FileOwner="syslog"
+ FileGroup="svc"
+ FileCreateMode="0640"
+ DirCreateMode="0755"
+ )
+ stop
+}
+
+KEEPALIVED_LOG_EOF
+{{- end }}
diff --git a/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/04.logrotate.tmpl b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/04.logrotate.tmpl
new file mode 100644
index 0000000..d5bcde7
--- /dev/null
+++ b/ansible/roles/node-proxy-keepalived/files/etc/confd/templates/keepalived.sh/04.logrotate.tmpl
@@ -0,0 +1,14 @@
+flush /etc/logrotate.d/keepalived << LOGROTATE_EOF
+${DATA_MOUNTS}/log/keepalived/keepalived.log {
+ daily
+ maxsize 2M
+ rotate 10
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
+ endscript
+}
+LOGROTATE_EOF
\ No newline at end of file
diff --git a/ansible/roles/haproxy/files/lib/systemd/system/haproxy.service b/ansible/roles/node-proxy-keepalived/files/lib/systemd/system/haproxy.service
similarity index 73%
rename from ansible/roles/haproxy/files/lib/systemd/system/haproxy.service
rename to ansible/roles/node-proxy-keepalived/files/lib/systemd/system/haproxy.service
index f55e301..4ac0555 100644
--- a/ansible/roles/haproxy/files/lib/systemd/system/haproxy.service
+++ b/ansible/roles/node-proxy-keepalived/files/lib/systemd/system/haproxy.service
@@ -3,16 +3,15 @@ Description=HAProxy Load Balancer
Documentation=man:haproxy(1)
Documentation=file:/usr/share/doc/haproxy/configuration.txt.gz
After=network.target rsyslog.service
+ConditionFileNotEmpty=/opt/app/conf/haproxy/haproxy.cfg
[Service]
-User=root
-Group=root
-EnvironmentFile=-/etc/default/haproxy
-EnvironmentFile=-/etc/sysconfig/haproxy
-Environment="CONFIG=/opt/app/conf/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" "EXTRAOPTS=-S /run/haproxy-master.sock"
-ExecStartPre=/usr/sbin/haproxy -f $CONFIG -c -q $EXTRAOPTS
-ExecStart=/usr/sbin/haproxy -Ws -f $CONFIG -p $PIDFILE $EXTRAOPTS
-ExecReload=/usr/sbin/haproxy -f $CONFIG -c -q $EXTRAOPTS
+User=haproxy
+Group=svc
+RuntimeDirectory=haproxy
+Environment="CONFIG=/opt/app/conf/haproxy/haproxy.cfg" "PIDFILE=/var/run/haproxy/haproxy.pid" "BINDOPT=/var/run/haproxy/haproxy-master.sock"
+ExecStartPre=/opt/haproxy/current/haproxy -f $CONFIG -c -q
+ExecStart=/opt/haproxy/current/haproxy -Ws -f $CONFIG -p $PIDFILE -S $BINDOPT
ExecReload=/bin/kill -USR2 $MAINPID
KillMode=mixed
Restart=always
@@ -25,6 +24,9 @@ Type=notify
# reduced performance. See systemd.service(5) and systemd.exec(5) for further
# information.
+LimitNOFILE=infinity
+CapabilityBoundingSet=CAP_NET_BIND_SERVICE
+AmbientCapabilities=CAP_NET_BIND_SERVICE
# NoNewPrivileges=true
# ProtectHome=true
# If you want to use 'ProtectSystem=strict' you should whitelist the PIDFILE,
diff --git a/ansible/roles/keepalived/files/lib/systemd/system/keepalived.service b/ansible/roles/node-proxy-keepalived/files/lib/systemd/system/keepalived.service
similarity index 60%
rename from ansible/roles/keepalived/files/lib/systemd/system/keepalived.service
rename to ansible/roles/node-proxy-keepalived/files/lib/systemd/system/keepalived.service
index 6fa3222..e25495d 100644
--- a/ansible/roles/keepalived/files/lib/systemd/system/keepalived.service
+++ b/ansible/roles/node-proxy-keepalived/files/lib/systemd/system/keepalived.service
@@ -2,13 +2,17 @@
Description=LVS and VRRP High Availability Monitor
After=network-online.target syslog.target
Wants=network-online.target
+Documentation=man:keepalived(8)
+Documentation=man:keepalived.conf(5)
+Documentation=man:genhash(1)
+Documentation=https://keepalived.org
[Service]
-Type=forking
+Type=notify
PIDFile=/run/keepalived.pid
KillMode=process
EnvironmentFile=-/opt/keepalived/current/etc/sysconfig/keepalived
-ExecStart=/opt/keepalived/current/sbin/keepalived $KEEPALIVED_OPTIONS
+ExecStart=/usr/local/sbin/keepalived --dont-fork $KEEPALIVED_OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
[Install]
diff --git a/ansible/roles/node-proxy-keepalived/files/opt/app/bin/node/proxy-node.sh b/ansible/roles/node-proxy-keepalived/files/opt/app/bin/node/proxy-node.sh
new file mode 100644
index 0000000..d77f2b6
--- /dev/null
+++ b/ansible/roles/node-proxy-keepalived/files/opt/app/bin/node/proxy-node.sh
@@ -0,0 +1,43 @@
+checkSvc() {
+ checkActive ${1%%/*} || {
+ log "Service '$1' is inactive."
+ return $EC_CHECK_INACTIVE
+ }
+ local endpoints=$(echo $1 | awk -F/ '{print $3}')
+ local endpoint; for endpoint in ${endpoints//,/ }; do
+ checkEndpoint $endpoint || {
+ log "Endpoint '$endpoint' is unreachable."
+ return 0
+ }
+ done
+}
+
+stop() {
+ log "INFO: Application is asked to stop . "
+ _stop || (log "ERROR: services in Node ${MY_INSTANCE_ID} failed to stop . " && return 1)
+ log "INFO: Application stopped successfully . "
+}
+
+start() {
+ log "INFO: Application is asked to start . "
+ _start || (log "ERROR: services in Node ${MY_INSTANCE_ID} failed to start . " && return 1)
+ log "INFO: Application started successfully . "
+}
+
+initNode() {
+ log "INFO: Application is about to initialize . "
+ _initNode || ( log "ERROR: Application failed to initialize . " && return 1 )
+ mkdir -p /data/haproxy/logs
+ chown -R haproxy.haproxy /data/haproxy
+ mkdir -p /data/keepalived/logs
+ chown -R root.root /data/keepalived
+ mkdir -p /data/caddy
+ chown -R caddy:svc /data/caddy
+ log "INFO: Application initialization completed . "
+}
+
+reload() {
+ log "INFO: Application is asked to reload . "
+ _reload $@
+ log "INFO: Application reloaded completely . "
+}
\ No newline at end of file
diff --git a/ansible/roles/node-proxy-keepalived/tasks/main.yml b/ansible/roles/node-proxy-keepalived/tasks/main.yml
new file mode 100644
index 0000000..fbf1ac7
--- /dev/null
+++ b/ansible/roles/node-proxy-keepalived/tasks/main.yml
@@ -0,0 +1,156 @@
+---
+- name: copy conf files
+ copy:
+ src: files/opt/app/
+ dest: /opt/app/
+ owner: root
+ group: svc
+ mode: preserve
+ directory_mode: u=rwx,g=rx,o=
+
+- name: install confd files
+ include_role:
+ name: confd-files
+
+# haproxy
+- name: set vars
+ set_fact:
+ haproxy_version: "{{ haproxy_version | d('3.0.9') }}"
+ os: "{{ os | d(default_os) }}"
+ arch: "{{ arch | d(default_arch) }}"
+ osv: "{{ osv | d(default_osv) }}"
+ installPath: "/opt/haproxy"
+
+- name: group svc
+ group:
+ name: svc
+ state: present
+
+- name: prepare service user
+ user:
+ name: haproxy
+ groups: svc
+ shell: /sbin/nologin
+ create_home: no
+ append: yes
+ comment: "Service User"
+ state: present
+
+# will set var downloaded
+- include_role:
+ name: downloader
+ vars:
+ opts:
+ pkg_name: haproxy
+ pkg_version: "{{ haproxy_version }}"
+ pkg_feature: "{{ os }}-{{ osv }}-{{ arch }}"
+ pkg_fileType: ".tgz"
+ pkg_url: "https://github.com/djangoyi-yunify/haproxy-compiler/releases/download/haproxy-{{ haproxy_version }}_{{ os }}-{{ osv }}/haproxy-{{ haproxy_version }}-{{ arch }}.tgz"
+
+- name: prepare dir
+ file:
+ path: "{{ installPath }}/{{ haproxy_version }}"
+ state: directory
+
+- name: link for current
+ file:
+ src: "{{ installPath }}/{{ haproxy_version }}"
+ dest: "{{ installPath }}/current"
+ state: link
+
+- name: decompress file
+ unarchive:
+ src: "{{ downloaded }}"
+ dest: "{{ installPath }}/current"
+ creates: "{{ installPath }}/current/bin/haproxy"
+ extra_opts:
+ - --strip-components=4
+ - --wildcards
+ - output/usr/local/sbin/haproxy
+
+- name: creates directory
+ file:
+ path: /opt/app/conf/haproxy
+ state: directory
+
+# keepalived
+- name: set vars
+ set_fact:
+ keepalived_version: "{{ keepalived_version | d('2.3.3') }}"
+ os: "{{ os | d(default_os) }}"
+ arch: "{{ arch | d(default_arch) }}"
+ osv: "{{ osv | d(default_osv) }}"
+ optPath: "/opt/keepalived"
+
+- name: group svc
+ group:
+ name: svc
+ state: present
+
+- name: prepare service user
+ user:
+ name: keepalived
+ groups: svc
+ shell: /sbin/nologin
+ create_home: no
+ append: yes
+ comment: "Service User"
+ state: present
+
+# will set var downloaded
+- include_role:
+ name: downloader
+ vars:
+ opts:
+ pkg_name: keepalived
+ pkg_version: "{{ keepalived_version }}"
+ pkg_feature: "{{ os }}-{{ osv }}-{{ arch }}"
+ pkg_fileType: ".tgz"
+ pkg_url: "https://github.com/djangoyi-yunify/keepalived-compiler/releases/download/keepalived-{{ keepalived_version }}_{{ os }}-{{ osv }}/keepalived-{{ keepalived_version }}-{{ arch }}.tgz"
+
+- name: decompress file
+ unarchive:
+ src: "{{ downloaded }}"
+ dest: "/"
+ creates: "/usr/local/sbin/keepalived"
+ extra_opts:
+ - --strip-components=1
+
+- name: creates directory
+ file:
+ path: /etc/keepalived
+ state: directory
+
+- name: creates directory
+ file:
+ path: "{{ optPath }}/{{ keepalived_version }}"
+ state: directory
+
+- name: link for current
+ file:
+ src: "{{ optPath }}/{{ keepalived_version }}"
+ dest: "{{ optPath }}/current"
+ state: link
+
+- name: more path for keepalived
+ file:
+ path: "{{ optPath }}/current/etc/sysconfig"
+ state: directory
+
+- name: copy service files
+ copy:
+ src: files/lib/systemd/system/
+ dest: /lib/systemd/system/
+ owner: root
+ group: root
+ mode: preserve
+
+- name: mask services
+ systemd:
+ name: "{{ item }}"
+ enabled: no
+ masked: yes
+ state: stopped
+ loop:
+ - haproxy
+ - keepalived
\ No newline at end of file
diff --git a/ansible/roles/node-proxy/files/etc/confd/templates/keepalived.sh/01.keepalived.conf.tmpl b/ansible/roles/node-proxy/files/etc/confd/templates/keepalived.sh/01.keepalived.conf.tmpl
deleted file mode 100644
index ee5bc20..0000000
--- a/ansible/roles/node-proxy/files/etc/confd/templates/keepalived.sh/01.keepalived.conf.tmpl
+++ /dev/null
@@ -1,34 +0,0 @@
-flush /etc/keepalived/keepalived.conf << KEEPALIVED_EOF
-{{ $replicaIPs := split (getv "/cluster/endpoints/reserved_ips/vip/value") "." }}
-global_defs {
-}
-
-vrrp_script check_haproxy {
- script "/usr/bin/killall -0 haproxy"
- interval 2
- weight 2
-}
-
-vrrp_instance HAProxy_HA {
- state BACKUP
- interface eth0
- virtual_router_id {{ index $replicaIPs 3 }}
- priority {{ getv "/host/sid" }}
- advert_int 2
- nopreempt
- unicast_src_ip {{ getv "/host/ip" }}
- authentication {
- auth_type PASS
- auth_pass pwd
- }
-
- virtual_ipaddress { #set VIP
- {{ getv "/cluster/endpoints/reserved_ips/vip/value" }}/24
- }
-
- track_script {
- check_haproxy
- }
-}
-
-KEEPALIVED_EOF
diff --git a/ansible/roles/node-proxy/files/opt/app/bin/node/proxy-node.sh b/ansible/roles/node-proxy/files/opt/app/bin/node/proxy-node.sh
deleted file mode 100644
index e378170..0000000
--- a/ansible/roles/node-proxy/files/opt/app/bin/node/proxy-node.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-initNode() {
- _initNode
- mkdir -p /data/haproxy/logs
- chown -R haproxy.haproxy /data/haproxy
- mkdir -p /data/keepalived/logs
- chown -R root.root /data/keepalived
-}
diff --git a/ansible/roles/node-proxy/tasks/main.yml b/ansible/roles/node-proxy/tasks/main.yml
deleted file mode 100644
index cf955eb..0000000
--- a/ansible/roles/node-proxy/tasks/main.yml
+++ /dev/null
@@ -1,13 +0,0 @@
----
-- name: copy conf files
- copy:
- src: files/opt/app/
- dest: /opt/app/
- owner: root
- group: svc
- mode: preserve
- directory_mode: u=rwx,g=rx,o=
-
-- name: install confd files
- include_role:
- name: confd-files-1.0.2
\ No newline at end of file
diff --git a/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/00.svc.env.tmpl b/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/00.svc.env.tmpl
index 36ac4df..6bf6607 100644
--- a/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/00.svc.env.tmpl
+++ b/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/00.svc.env.tmpl
@@ -1,6 +1,6 @@
flush /opt/app/bin/envs/svc-caddy.env << CADDY_ENV_EOF
-{{- if getvs "/host/role" | filter "(disc|ram)" }}
-SERVICES="\$SERVICES caddy/{{ getv "/env/web_console_enabled" "false" }}/http:80"
+{{- if getvs "/host/role" | filter "(disc|ram|haproxy)" }}
+SERVICES="\$SERVICES caddy/{{ getv "/env/web_console_enabled" "true" }}/http:80"
{{- end }}
CADDY_ENV_EOF
diff --git a/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/01.caddyfile.tmpl b/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/01.caddyfile.tmpl
index fc1efd0..91c7352 100644
--- a/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/01.caddyfile.tmpl
+++ b/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/01.caddyfile.tmpl
@@ -1,13 +1,31 @@
+{{- if getvs "/host/role" | filter "(disc|ram|haproxy)" }}
ln -s -f /opt/app/conf/caddy/index.html /data/index.html
+flush /opt/app/conf/caddy/caddyfile << CADDYFILE_EOF
+{
+ admin off
+ auto_https off
+ persist_config off
+ order upload before file_server
+ log {
+ output file /data/caddy/caddy.log
+ }
+}
+
+:80 {
+ vars {
+ rootDir "/data"
+ }
+
+ root {vars.rootDir}
+
+ handle /log* {
+ file_server browse
+ }
-flush /opt/app/conf/caddy/Caddyfile << CADDYFILE_EOF
-{{ getv "/host/ip" }}:80 {
- {{- with getv "/env/web_console_password" "" }}
- basicauth / "{{ getv "/env/web_console_username" "admin" }}" "{{ . }}"
- {{- end }}
- root /data
- gzip
- browse /log
- tls off
+ file_server
}
CADDYFILE_EOF
+{{- end }}
+
+
+
diff --git a/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/02.index.html.tmpl b/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/02.index.html.tmpl
index cd76688..9c64cd3 100644
--- a/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/02.index.html.tmpl
+++ b/ansible/roles/node-rabbitmq/files/etc/confd/templates/caddy.sh/02.index.html.tmpl
@@ -64,12 +64,12 @@ flush /opt/app/conf/caddy/index.html << HTML_EOF
Files
-
+
{{- $discNodes := getvs "/hosts/disc/*/ip" }}
- {{- $ramNodes := getvs "/hosts/ram/*/ip" }}
+ {{- $proxyNodes := getvs "/hosts/haproxy/*/ip" }}
- 共 {{ len $discNodes }} 个 disc 节点, {{ len $ramNodes }} 个 ram 节点
+ 共 {{ len $discNodes }} 个 disc 节点, {{ len $proxyNodes }} 个 haproxy 节点
@@ -81,8 +81,8 @@ flush /opt/app/conf/caddy/index.html << HTML_EOF
- ⊞{{ . }}
{{- end }}
{{- end }}
-
- {{- range $ramNodes }}
+
+ {{- range $proxyNodes }}
{{- if eq . (getv "/host/ip") }}
- ⊟{{ . }}
- ⊞log
diff --git a/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/02.rabbitmq.conf.tmpl b/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/02.rabbitmq.conf.tmpl
index 758b129..5176f81 100644
--- a/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/02.rabbitmq.conf.tmpl
+++ b/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/02.rabbitmq.conf.tmpl
@@ -1,18 +1,36 @@
-{{- $myRole := getv "/host/role" }}
+{{- if getvs "/host/role" | filter "(disc|ram)" }}
+mkdir -p ${DATA_MOUNTS}/log/rabbitmq
+mkdir -p ${DATA_MOUNTS}/conf
-flush /etc/rabbitmq/rabbitmq.conf << RABBITMQ_CONF_EOF
-background_gc_enabled = {{ getv "/env/background_gc_enabled" "false" }}
+flush /etc/rabbitmq/rabbitmq.conf.origin << RABBITMQ_CONF_EOF
+background_gc_enabled = {{ getv "/env/background_gc_enabled" "true" }}
background_gc_target_interval = {{ getv "/env/background_gc_target_interval" "60000" }}
channel_max = {{ getv "/env/channel_max" "10" }}
-cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config
-{{- $discNodes := join ( getvs "/hosts/disc/*/instance_id") "," }}
-{{- $ramNodes := join ( getvs "/hosts/ram/*/instance_id") "," }}
-{{- $allNodes := split ( printf "%s%s%s" $discNodes ( and $ramNodes ",") $ramNodes) ","}}
-{{- range $i,$node := $allNodes }}
-cluster_formation.classic_config.nodes.{{ add $i 1 }} = rabbit@{{ $node }}
+# Cluster formation
+{{ if (exists "/links/etcd_service/cluster/cluster_id") and (ne (getv "/links/etcd_service/cluster/cluster_id")) }}
+cluster_formation.peer_discovery_backend = etcd
+{{- $clusterId := getv "/cluster/cluster_id" }}
+{{- $etcdHosts := getvs "/links/etcd_service/hosts/etcd_node/*/ip" }}
+{{- range $i,$endpoint := $etcdHosts }}
+cluster_formation.etcd.endpoints.{{ add $i 1 }} = {{ $endpoint }}:2379
{{- end }}
-cluster_formation.node_type = {{ getv "/host/role" }}
+cluster_formation.etcd.key_prefix = /{{ $clusterId }}_prefix
+cluster_formation.etcd.cluster_name = {{ $clusterId }}
+cluster_formation.etcd.node_ttl = 30
+cluster_formation.etcd.lock_timeout = 300
+{{ else }}
+
+cluster_formation.peer_discovery_backend = classic_config
+{{- range lsdir "/hosts/disc" }}
+cluster_formation.classic_config.nodes.{{ getv (printf "/hosts/disc/%s/sid" .) }}={{ getv (printf "/hosts/disc/%s/instance_id" .) }}
+{{- end }}
+
+{{ end }}
+
+cluster_formation.node_cleanup.only_log_warning = true
+cluster_formation.node_cleanup.interval = 90
+
cluster_keepalive_interval = {{ getv "/env/cluster_keepalive_interval" "10000" }}
cluster_partition_handling = {{ getv "/env/cluster_partition_handling" "pause_minority" }}
@@ -23,7 +41,6 @@ disk_free_limit.absolute = {{ getv "/env/disk_free_limit" "50MB" }}
frame_max = {{ getv "/env/frame_max" "131072"}}
handshake_timeout = {{ getv "/env/handshake_timeout" "10000" }}
heartbeat = {{ getv "/env/heartbeat" "60" }}
-hipe_compile = {{ getv "/env/hipe_compile" "false" }}
loopback_users.guest = false
num_acceptors.tcp = {{ getv "/env/num_tcp_acceptors" "10" }}
proxy_protocol = {{ getv "/env/proxy_protocol" "false" }}
@@ -36,10 +53,20 @@ tcp_listen_options.send_timeout = 15000
tcp_listen_options.buffer = 196608
tcp_listen_options.sndbuf = 196608
tcp_listen_options.recbuf = 196608
-vm_memory_high_watermark.relative = {{ getv "/env/vm_memory_high_watermark" "0.4" }}
+vm_memory_high_watermark.relative = {{ getv "/env/vm_memory_high_watermark" "0.7" }}
# vm_memory_high_watermark.absolute = {{ getv "/env/vvm_memory_high_watermark_absolute" "2G" }}
vm_memory_high_watermark_paging_ratio = {{ getv "/env/vm_memory_high_watermark_paging_ratio" "0.5" }}
-log.dir = /data/log
-
+log.dir = ${DATA_MOUNTS}/log/rabbitmq/
+default_user = {{ getv "/env/rabbitmq_default_user" "guest" }}
+default_pass = {{ replace (getv "/env/rabbitmq_default_pass" "guest") `$` `\$` -1 }}
+loopback_users = none
+default_user_tags.administrator = true
+log.file.level = info
RABBITMQ_CONF_EOF
+if [ ! -f "${DATA_MOUNTS}/conf/rabbitmq.conf" ]; then
+ touch ${DATA_MOUNTS}/conf/rabbitmq.conf
+fi
+
+/opt/app/bin/node/merge_files.sh /etc/rabbitmq/rabbitmq.conf.origin ${DATA_MOUNTS}/conf/rabbitmq.conf /etc/rabbitmq/rabbitmq.conf
+{{- end }}
\ No newline at end of file
diff --git a/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/04.rabbitmq-env.conf.tmpl b/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/04.rabbitmq-env.conf.tmpl
index 33ee3d2..39ac3fb 100644
--- a/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/04.rabbitmq-env.conf.tmpl
+++ b/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/04.rabbitmq-env.conf.tmpl
@@ -2,10 +2,12 @@ flush /etc/rabbitmq/rabbitmq-env.conf << RABBIT_ENV_CONF_EOF
RABBITMQ_NODE_IP_ADDRESS=0.0.0.0
RABBITMQ_NODE_PORT=5672
-RABBITMQ_MNESIA_BASE=/data/mnesia
-RABBITMQ_LOG_BASE=/data/log
+RABBITMQ_MNESIA_BASE=${DATA_MOUNTS}/mnesia
+RABBITMQ_LOG_BASE=${DATA_MOUNTS}/log/rabbitmq
RABBITMQ_CONFIG_FILE=/etc/rabbitmq/rabbitmq
RABBITMQ_MNESIA_DIR=
-RABBITMQ_SCHEMA_DIR=/data/schema
+RABBITMQ_SCHEMA_DIR=${DATA_MOUNTS}/schema
+RABBITMQ_ENABLED_PLUGINS_FILE=/etc/rabbitmq/enabled_plugins
+RABBITMQ_HOME=/opt/rabbitmq/current
RABBIT_ENV_CONF_EOF
\ No newline at end of file
diff --git a/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/05.enabled-plugins.tmpl b/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/05.enabled-plugins.tmpl
index 6727c10..611e9e6 100644
--- a/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/05.enabled-plugins.tmpl
+++ b/ansible/roles/node-rabbitmq/files/etc/confd/templates/rabbitmq-server.sh/05.enabled-plugins.tmpl
@@ -1,16 +1,67 @@
+myRole={{ getv "/host/role" }}
+formatPluginsStr() {
+ if [ -z "$1" ]; then
+ echo ""
+ return 0
+ fi
+ tmpStr=""
+ tmpList=$(echo "$1" | sed 's/,/\n/g')
+ while IFS= read -r line; do
+ if [ "$line" = "rabbitmq_delayed_message_exchange" ]; then
+ if [ "$myRole" = "disc" ]; then
+ tmpStr="${tmpStr}${line},"
+ fi
+ else
+ tmpStr="${tmpStr}${line},"
+ fi
+ done < "
+ exit 1
+}
+
+# 检查参数数量
+if [ "$#" -ne 3 ]; then
+ usage
+fi
+
+# 赋值参数到变量
+file1="$1"
+file2="$2"
+outputfile="$3"
+
+# 清理并合并两个文件
+merge_files() {
+ # 清理第一个文件并写入输出文件
+ sed 's/[[:space:]]*=[[:space:]]*/=/' "$file1" > "$outputfile"
+
+ # 逐行读取第二个文件
+ while IFS= read -r line; do
+ # 清理空格
+ clean_line=$(echo "$line" | sed 's/[[:space:]]*=[[:space:]]*/=/')
+ # 提取key
+ key=$(echo "$clean_line" | cut -d '=' -f 1)
+
+ # 检查键是否已经在输出文件中
+ if ! grep -q "^${key}=" "$outputfile"; then
+ # 如果不在,追加到输出文件中
+ echo "$clean_line" >> "$outputfile"
+ fi
+ done < <(sed 's/[[:space:]]*=[[:space:]]*/=/' "$file2")
+}
+
+# 检查文件是否存在并合并
+if [ -f "$file1" ] && [ -f "$file2" ]; then
+ merge_files
+ echo "Files $file1 and $file2 have been merged into $outputfile."
+elif [ -f "$file1" ]; then
+ sed 's/[[:space:]]*=[[:space:]]*/=/' "$file1" > "$outputfile"
+ echo "File $file1 has been copied to $outputfile as file $file2 does not exist."
+elif [ -f "$file2" ]; then
+ sed 's/[[:space:]]*=[[:space:]]*/=/' "$file2" > "$outputfile"
+ echo "File $file2 has been copied to $outputfile as file $file1 does not exist."
+else
+ echo "Neither $file1 nor $file2 exist."
+ exit 1
+fi
\ No newline at end of file
diff --git a/ansible/roles/node-rabbitmq/files/opt/app/bin/node/rabbitmq-node.sh b/ansible/roles/node-rabbitmq/files/opt/app/bin/node/rabbitmq-node.sh
index 7854ce6..1719c32 100644
--- a/ansible/roles/node-rabbitmq/files/opt/app/bin/node/rabbitmq-node.sh
+++ b/ansible/roles/node-rabbitmq/files/opt/app/bin/node/rabbitmq-node.sh
@@ -1,3 +1,4 @@
+# 使用etcd需要删除fristnode逻辑
# Error codes
EC_SCALE_OUT_ERR=240
EC_UNHEALTHY=241
@@ -7,7 +8,14 @@ EC_UPGRADE_ERR=244
checkNodesHealthy() {
local node; for node in $@; do
- rabbitmqctl -s -n rabbit@${node} node_health_check -t 3 | grep -o passed || return $EC_UNHEALTHY
+ if ! rabbitmq-diagnostics -t 3 -n rabbit@${node} ping; then
+ log "ERROR: rabbit@${node} failed the health check . "
+ return $EC_UNHEALTHY
+ fi
+ if ! rabbitmq-diagnostics -t 3 -n rabbit@${node} check_running; then
+ log "ERROR: rabbit@${node} failed the health check . "
+ return $EC_UNHEALTHY
+ fi
done
}
@@ -23,46 +31,101 @@ stop() {
#https://www.rabbitmq.com/clustering.html#restarting
#the last node to go down is the only one that didn't have any running peers at the time of shutdown.
#sometimes the last node to stop must be the first node to be started after the upgrade.
- local i; for i in ${LEAVING_MQ_NODES}; do DISC_NODES="${DISC_NODES//${i}/}"; done
- #In case /hosts /deleting-hosts update are not synchronized
- local firstDiscNode; firstDiscNode="$(echo ${DISC_NODES} | awk -F/ '{print $2}')";
- if [[ "${MY_INSTANCE_ID}" == "${firstDiscNode}" ]]; then
- retry 20 3 0 checkOnlyNodeRunning "${firstDiscNode}" #notice return
+ if [[ ${PEER_DISCOVERY_BACKEND_TYPE} == "classic_config" ]];then
+ local i; for i in ${LEAVING_MQ_NODES}; do DISC_NODES="${DISC_NODES//${i}/}"; done
+ #In case /hosts /deleting-hosts update are not synchronized
+ local firstDiscNode; firstDiscNode="$(echo ${DISC_NODES} | awk -F/ '{print $2}')";
+ if [[ "${MY_INSTANCE_ID}" == "${firstDiscNode}" ]]; then
+ log "INFO: Wait until all other Disc nodes are stopped . "
+ retry 20 3 0 checkOnlyNodeRunning "${firstDiscNode}" #notice return
+ log "INFO: The other Disc nodes have all stopped . "
+ fi
fi
- _stop
+
+ log "INFO: Application is asked to stop . "
+ _stop || (log "ERROR: services in Node ${MY_INSTANCE_ID} failed to stop . " && return 1)
+ log "INFO: Application stopped successfully . "
}
start() {
- local firstDiscNode; firstDiscNode="$(echo ${DISC_NODES} | awk -F/ '{print $2}')";
- if [[ "${MY_INSTANCE_ID}" != "${firstDiscNode}" ]]; then # wait for first disc node prepare tables
- retry 15 5 0 checkEndpoint "http:15672" "${firstDiscNode}"
+ log "INFO: Application is asked to start . "
+ if [[ ${PEER_DISCOVERY_BACKEND_TYPE} == "classic_config" ]];then
+ local firstDiscNode; firstDiscNode="$(echo ${DISC_NODES} | awk -F/ '{print $2}')";
+ if [[ "${MY_INSTANCE_ID}" != "${firstDiscNode}" ]]; then # wait for first disc node prepare tables
+ retry 120 5 0 checkEndpoint "tcp:5672" "${firstDiscNode}"
+ fi
fi
- _start
+ /opt/app/bin/node/merge_files.sh /etc/rabbitmq/rabbitmq.conf.origin /data/conf/rabbitmq.conf /etc/rabbitmq/rabbitmq.conf
+ _start || (log "ERROR: services in Node ${MY_INSTANCE_ID} failed to start . ")
+ if [[ ${PEER_DISCOVERY_BACKEND_TYPE} == "classic_config" ]];then
+ addNodeToCluster
+ fi
+ retry 20 30 0 checkSvc "rabbitmq-server"
+ log "INFO: Application started successfully . "
}
setConfFile() {
- mkdir -p /data/{log,mnesia,config,schema}
- chown -R rabbitmq:rabbitmq /data/{log,mnesia,config,schema}
+ mkdir -p /data/{log,mnesia,config,schema,caddy}
+ chown root:svc /data/log
+ chmod 0755 /data/log
+ chown -R rabbitmq:svc /data/{log/rabbitmq,mnesia,config,schema}
+ chown -R caddy:svc /data/caddy
}
initNode() {
- _initNode
+ log "INFO: Application is about to initialize . "
+ _initNode || ( log "ERROR: Application failed to initialize . " && return $EC_UNHEALTHY )
setConfFile
+ log "INFO: Application initialization completed . "
}
reload() {
+ log "INFO: Application is asked to reload . "
if ! isNodeInitialized; then return 0; fi
case "${1}" in
rabbitmq-server)
- local rabbitmqConfFile="/etc/rabbitmq/rabbitmq.conf";
- if test -f ${rabbitmqConfFile}.1 && ! (diff -q -I "^cluster_formation" ${rabbitmqConfFile} ${rabbitmqConfFile}.1 ) ; then
- # only figure out the changed parameter
- _reload rabbitmq-server;
+ local rabbitmqConfFile="/etc/rabbitmq/rabbitmq.conf.origin";
+ local pluginCtlFile="/opt/app/bin/envs/pluginsctl.env"
+ /opt/app/bin/node/merge_files.sh /etc/rabbitmq/rabbitmq.conf.origin /data/conf/rabbitmq.conf /etc/rabbitmq/rabbitmq.conf
+ if test -f ${rabbitmqConfFile}.1; then
+ local diffInfo=$(diff ${rabbitmqConfFile} ${rabbitmqConfFile}.1 || :)
+ if echo "$diffInfo" | grep "default_pass"; then
+ # update default user's password
+ local firstDiscNode; firstDiscNode="$(echo ${DISC_NODES} | awk -F/ '{print $2}')";
+ if [ "${MY_INSTANCE_ID}" != "${firstDiscNode}" ]; then
+ log "not the first node, skip to update default user's password"
+ else
+ log "update default user's password"
+ local username=$(grep -P '^default_user\s*=' /etc/rabbitmq/rabbitmq.conf | sed 's/^[^=]*=//' | sed 's/^\s*//' | sed 's/\s*$//')
+ local password=$(grep -P '^default_pass\s*=' /etc/rabbitmq/rabbitmq.conf | sed 's/^[^=]*=//' | sed 's/^\s*//' | sed 's/\s*$//')
+ rabbitmqctl change_password $username $password || :
+ fi
+ # wait for other nodes to change password
+ sleep 5s
+ fi
+ if ! (diff -q -I "^cluster_formation" ${rabbitmqConfFile} ${rabbitmqConfFile}.1 ) && ! (diff -q -I "^default_pass" ${rabbitmqConfFile} ${rabbitmqConfFile}.1 ) ; then
+ if [ -f ${pluginCtlFile}.1 ]; then
+ log "sync pluginsctl.env.1"
+ cat ${pluginCtlFile} > ${pluginCtlFile}.1
+ fi
+ # only figure out the changed parameter
+ log "restart rabbitmq-server because of config change"
+ _reload rabbitmq-server || (log "ERROR: The Rabbitmq-server failed to start . " && return 1);
+ fi
+ fi
+ if test -f ${pluginCtlFile}.1 && ! diff ${pluginCtlFile} ${pluginCtlFile}.1; then
+ log "hot update plugin status"
+ if [ -n "$DISABLED_PLUGINS" ]; then
+ rabbitmq-plugins disable $(echo "$DISABLED_PLUGINS" | sed 's/,/ /g') || :
+ fi
+ rabbitmq-plugins enable $(echo "$ENABLED_PLUGINS" | sed 's/,/ /g') || :
fi
;;
*)
- _reload $@ ;;
+ _reload $@
+ ;;
esac
+ log "INFO: Application reloaded completely . "
}
preCheckForScaleIn() {
@@ -70,7 +133,7 @@ preCheckForScaleIn() {
checkNodesHealthy "${allNodes}" # there was unhealthy node
if [[ -n "${LEAVING_MQ_NODES}" ]]; then
local clusterInfo; clusterInfo="$(rabbitmqctl -t 3 cluster_status --formatter=json)";
- local allRunningNodes; allRunningNodes="$(echo $clusterInfo | jq -j '[.nodes.disc[], .nodes.ram[]?]')";
+ local allRunningNodes; allRunningNodes="$(echo $clusterInfo | jq -j '[.disk_nodes[], .ram_nodes[]?]')";
if [[ "${CLUSTER_PARTITION_HANDLING}" == "pause_minority" ]]; then
local delNodesCount; delNodesCount=$(echo "${LEAVING_MQ_NODES}" | wc -w);
local clusterNodesCount; clusterNodesCount=$(echo "${DISC_NODES} ${RAM_NODES}" | awk '{print NF}')
@@ -99,7 +162,7 @@ scaleIn() {
scaleOut() {
if [[ -n "${JOINING_MQ_NODES}" ]]; then
local joinNode; for joinNode in ${JOINING_MQ_NODES}; do
- local clusterInfo; clusterInfo="$(rabbitmqctl -t 3 cluster_status -n rabbit@${joinNode} --formatter=json | jq -j '[.nodes.disc[], .nodes.ram[]?]')";
+ local clusterInfo; clusterInfo="$(rabbitmqctl -t 3 cluster_status -n rabbit@${joinNode} --formatter=json | jq -j '[.disk_nodes[], .ram_nodes[]?]')";
if checkNodesHealthy "${joinNode}" && [[ "${clusterInfo}" =~ "${MY_INSTANCE_ID}" ]]; then
log "${joinNode} was clustered successful in scale-out";
else
@@ -118,11 +181,12 @@ addNodeToCluster() {
# write for the node which peer discover failed or the adding node
local firstDiscNode; firstDiscNode="$(echo ${DISC_NODES} | awk -F/ '{print $2}')";
local clusterInfo; clusterInfo="$(rabbitmqctl -t 3 cluster_status --formatter=json)";
- local allNodes; allNodes="$(echo $clusterInfo | jq -j '[.nodes.disc[], .nodes.ram[]?]')";
+ local allNodes; allNodes="$(echo $clusterInfo | jq -j '[.disk_nodes[], .ram_nodes[]?]')";
if [[ ! "$allNodes" =~ "${firstDiscNode}" ]]; then #disc node ${DISC_NODES##*-} was not clustered
rabbitmqctl stop_app
rabbitmqctl join_cluster --${MY_ROLE} rabbit@${firstDiscNode}
rabbitmqctl start_app
+ log "join cluster success."
else
log "${firstDiscNode} already clustered or ${MY_INSTANCE_ID} not the adding node."
fi
@@ -138,12 +202,26 @@ upgrade() {
if [[ "$((${#stopedDiscNodes} - 12))" -gt "${#MY_INSTANCE_ID}" ]]; then
retry 20 3 0 checkNodesHealthy "${lastStopedDiscNode}"
fi
- _start || return ${EC_UPGRADE_ERR}
+ _start || ( log "ERROR: Application failed to upgrade . " && return ${EC_UPGRADE_ERR} )
# upgrade failed, check volume, rm /data/mnesia/rabbit@${HOSTNAME}/schema_upgrade_lock and retry _start.
}
preCheckForUpgrade() {
local hostVolumeUsed
hostVolumeUsed="$(df -h /data | awk 'NR == 2 {print $5}')"; #" * <= 30%"
- [[ "${hostVolumeUsed%%%}" -lt "30" ]] || return ${EC_INSUFFICIENT_VOLUME}
-}
\ No newline at end of file
+ [[ "${hostVolumeUsed%%%}" -lt "30" ]] || ( log "ERROR: Insufficient disk space to support the upgrade . " && return ${EC_INSUFFICIENT_VOLUME} )
+}
+
+checkSvc() {
+ checkActive ${1%%/*} || {
+ log "Service '$1' is inactive."
+ return $EC_CHECK_INACTIVE
+ }
+ local endpoints=$(echo $1 | awk -F/ '{print $3}')
+ local endpoint; for endpoint in ${endpoints//,/ }; do
+ checkEndpoint $endpoint || {
+ log "Endpoint '$endpoint' is unreachable."
+ return 0
+ }
+ done
+}
diff --git a/ansible/roles/node-rabbitmq/files/opt/app/conf/rabbitmq-server/rabbitmq-conf-sample b/ansible/roles/node-rabbitmq/files/opt/app/conf/rabbitmq-server/rabbitmq-conf-sample
deleted file mode 100644
index d000fc7..0000000
--- a/ansible/roles/node-rabbitmq/files/opt/app/conf/rabbitmq-server/rabbitmq-conf-sample
+++ /dev/null
@@ -1,6 +0,0 @@
-CONFIG_FILE=/opt/app/conf/rabbitmq-server/rabbitmq.conf
-ENABLED_PLUGINS_FILE=/opt/app/conf/rabbitmq-server/enabled-plugins
-NODE_IP_ADDRESS=0.0.0.0
-NODE_PORT=5672
-MNESIA_BASE=/var/lib/rabbitmq/mnesia
-LOG_BASE=/data/rabbitmq/log
diff --git a/ansible/roles/node-rabbitmq/files/opt/app/conf/rabbitmq-server/rabbitmq.conf b/ansible/roles/node-rabbitmq/files/opt/app/conf/rabbitmq-server/rabbitmq.conf
deleted file mode 100644
index e69de29..0000000
diff --git a/ansible/roles/node-rabbitmq/tasks/main.yml b/ansible/roles/node-rabbitmq/tasks/main.yml
index cf955eb..8bd4a44 100644
--- a/ansible/roles/node-rabbitmq/tasks/main.yml
+++ b/ansible/roles/node-rabbitmq/tasks/main.yml
@@ -10,4 +10,167 @@
- name: install confd files
include_role:
- name: confd-files-1.0.2
\ No newline at end of file
+ name: confd-files
+
+- name: copy binaries
+ copy:
+ src: files/lib/
+ dest: /lib
+ owner: root
+ group: svc
+ mode: preserve
+ directory_mode: u=rwx,g=rx,o=
+
+# install erlang
+- name: set vars for erlang
+ set_fact:
+ erlang_version: "{{ erlang_version | d('26.2.5.9') }}"
+ os: "{{ os | d(default_os) }}"
+ arch: "{{ arch | d(default_arch) }}"
+ osv: "{{ osv | d(default_osv) }}"
+
+# will set var downloaded
+- include_role:
+ name: downloader
+ vars:
+ opts:
+ pkg_name: erlang
+ pkg_version: "{{ erlang_version }}"
+ pkg_feature: "{{ os }}-{{ osv }}-{{ arch }}"
+ pkg_fileType: ".tgz"
+ pkg_url: "https://github.com/djangoyi-yunify/erlang-compiler/releases/download/erlang-{{ erlang_version }}_{{ os }}-{{ osv }}/erlang-{{ erlang_version }}-{{ arch }}.tgz"
+
+- name: decompress file
+ unarchive:
+ src: "{{ downloaded }}"
+ dest: "/"
+ creates: "/usr/local/bin/erl"
+ extra_opts:
+ - --strip-components=1
+
+# install rabbitmq
+- name: set vars for rabbitmq
+ set_fact:
+ rabbitmq_version: "{{ rabbitmq_version | d('3.13.7') }}"
+ os: "{{ os | d(default_os) }}"
+ arch: "{{ arch | d(default_arch) }}"
+ osv: "{{ osv | d(default_osv) }}"
+ installPath: "/opt/rabbitmq"
+
+# will set var downloaded
+- include_role:
+ name: downloader
+ vars:
+ opts:
+ pkg_name: rabbitmq
+ pkg_version: "{{ rabbitmq_version }}"
+ pkg_feature: "noarch"
+ pkg_fileType: ".xz"
+ pkg_url: "https://github.com/rabbitmq/rabbitmq-server/releases/download/v{{ rabbitmq_version }}/rabbitmq-server-generic-unix-{{ rabbitmq_version }}.tar.xz"
+
+- name: prepare rabbitmq install path
+ file:
+ path: "{{ installPath }}/{{ rabbitmq_version }}"
+ state: directory
+
+- name: link for current
+ file:
+ src: "{{ installPath }}/{{ rabbitmq_version }}"
+ dest: "{{ installPath }}/current"
+ state: link
+
+- name: decompress file
+ unarchive:
+ src: "{{ downloaded }}"
+ dest: "{{ installPath }}/current"
+ creates: "{{ installPath }}/current/sbin/rabbitmq-server"
+ extra_opts:
+ - --strip-components=1
+
+- name: add rabbitmq exec to $PATH
+ copy:
+ dest: /etc/profile.d/rabbitmq.sh
+ content: |
+ # Generated by Ansible - Do not modify manually
+ export RABBITMQ_HOME=/opt/rabbitmq/current
+ export PATH=$RABBITMQ_HOME/sbin:$PATH
+ mode: preserve
+
+# install rabbitmq plugin: rabbitmq-delayed-message-exchange
+- name: set vars for rabbitmq-delayed-message-exchange
+ set_fact:
+ rabbitmqDelayedMessageExchange_version: "{{ rabbitmqDelayedMessageExchange_version | d('3.13.0') }}"
+ installPath: "/opt/rabbitmq/current/plugins"
+ when: rabbitmq_version == '3.13.7'
+
+# will set var downloaded
+- include_role:
+ name: downloader
+ vars:
+ opts:
+ pkg_name: rabbitmqDelayedMessageExchange
+ pkg_version: "{{ rabbitmqDelayedMessageExchange_version }}"
+ pkg_feature: "noarch"
+ pkg_fileType: ".zip"
+ pkg_url: "https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/v{{ rabbitmqDelayedMessageExchange_version }}/rabbitmq_delayed_message_exchange-{{ rabbitmqDelayedMessageExchange_version }}.ez"
+
+- name: decompress file
+ unarchive:
+ src: "{{ downloaded }}"
+ dest: "{{ installPath }}"
+ creates: "{{ installPath }}/rabbitmq_delayed_message_exchange-{{ rabbitmqDelayedMessageExchange_version }}"
+
+- name: fix permission of rabbitmq_delayed_message_exchange folder
+ ansible.builtin.file:
+ path: "{{ installPath }}/rabbitmq_delayed_message_exchange-{{ rabbitmqDelayedMessageExchange_version }}"
+ mode: "0755"
+
+- name: find rabbitmq_delayed_message_exchange's subfolders
+ find:
+ paths: "{{ installPath }}/rabbitmq_delayed_message_exchange-{{ rabbitmqDelayedMessageExchange_version }}"
+ recurse: yes
+ file_type: directory
+ register: found_dirs
+
+- name: fix permission of rabbitmq_delayed_message_exchange's subfolders
+ ansible.builtin.file:
+ path: "{{ item.path }}"
+ mode: "0755"
+ loop: "{{ found_dirs.files }}"
+
+- name: disable auto startup on boot
+ systemd:
+ name: rabbitmq-server
+ enabled: no
+ masked: yes
+ state: stopped
+
+- name: prepare rabbitmq config path
+ file:
+ path: "/etc/rabbitmq"
+ state: directory
+
+- name: User - rabbitmq
+ user:
+ name: rabbitmq
+ groups: svc
+ shell: /usr/sbin/nologin
+ home: /var/lib/rabbitmq
+ append: yes
+ state: present
+
+- name: create empty cookie file
+ copy:
+ dest: /var/lib/rabbitmq/.erlang.cookie
+ content: ""
+ owner: rabbitmq
+ group: rabbitmq
+ mode: '0400'
+
+- name: link cookie file for root
+ file:
+ path: /root/.erlang.cookie
+ src: /var/lib/rabbitmq/.erlang.cookie
+ state: link
+ force: yes
+ mode: '0400'
diff --git a/ansible/roles/os-update/tasks/main.yml b/ansible/roles/os-update/tasks/main.yml
new file mode 100644
index 0000000..d1ff479
--- /dev/null
+++ b/ansible/roles/os-update/tasks/main.yml
@@ -0,0 +1,35 @@
+---
+- name: set vars
+ set_fact:
+ os: "{{ os | d(default_os) }}"
+ osv: "{{ osv | d(default_osv) }}"
+ arch: "{{ arch | d(default_arch) }}"
+
+- name: update apt source
+ apt:
+ update_cache: yes
+ when: os == 'ubuntu'
+
+- name: prepare for ubuntu 22.04, amd64
+ block:
+ - name: upgrade kernal
+ apt:
+ name: "linux-image-{{ ubuntu_22_amd64_kernel }}"
+ state: present
+ - name: reboot os
+ reboot:
+ reboot_timeout: 600
+ connect_timeout: 30
+ test_command: uptime
+ when:
+ - os == 'ubuntu'
+ - osv == '22.04'
+ - arch == 'amd64'
+ - ansible_kernel is version_compare(ubuntu_22_amd64_kernel, '<')
+
+- name: Non-interactive update
+ dnf:
+ name: "*"
+ state: latest
+ update_cache: yes
+ when: os == 'kylin'
\ No newline at end of file
diff --git a/ansible/roles/pwquality/tasks/main.yml b/ansible/roles/pwquality/tasks/main.yml
new file mode 100644
index 0000000..0a04c86
--- /dev/null
+++ b/ansible/roles/pwquality/tasks/main.yml
@@ -0,0 +1,11 @@
+---
+- name: set up variables
+ set_fact:
+ os: "{{ os | d(default_os) }}"
+
+- name: pwquality - minclass
+ lineinfile:
+ path: /etc/security/pwquality.conf
+ line: 'minclass = 2'
+ state: present
+ when: os == 'kylin'
\ No newline at end of file
diff --git a/ansible/roles/rabbitmq-server/tasks/main.yml b/ansible/roles/rabbitmq-server/tasks/main.yml
deleted file mode 100644
index fb25da6..0000000
--- a/ansible/roles/rabbitmq-server/tasks/main.yml
+++ /dev/null
@@ -1,108 +0,0 @@
----
-- name: copy binaries
- copy:
- src: files/lib/
- dest: /lib
- owner: root
- group: svc
- mode: preserve
- directory_mode: u=rwx,g=rx,o=
-
-- name: install rabbitmq deb
- include_role:
- name: install-1.0.5
- vars:
- opts:
- pkg_name: "{{ item.name }}"
- pkg_version: "{{ item.version }}"
- pkg_type: deb
- pkg_url: "{{ item.url }}"
- extracts: false
- dest_path: "/tmp/{{ item.dest }}"
- creates:
- bin_path:
- with_items:
- - url: "https://packages.erlang-solutions.com/erlang-solutions_{{ erlang_solution_version }}_all.deb"
- name: "erlang-solutions"
- version: "{{ erlang_solution_version }}"
- dest: "erlang-solutions_{{ erlang_solution_version }}_all.deb"
- - url: "https://github.com/rabbitmq/rabbitmq-server/releases/download/v{{ rabbitmq_version }}/rabbitmq-server_{{ rabbitmq_version }}-1_all.deb"
- name: "rabbitmq"
- version: "{{ rabbitmq_version }}"
- dest: "rabbitmq-server_{{ rabbitmq_version }}-1_all.deb"
-
-- name: apt for erlang
- apt: deb="/tmp/erlang-solutions_{{ erlang_solution_version }}_all.deb"
- become: yes
-
-- name: update apt for erlang
- shell: echo 'deb https://dl.bintray.com/rabbitmq/debian xenial erlang-22.x' | sudo tee -a /etc/apt/sources.list.d/erlang-solutions.list
-
-- name: add apt-key
- apt_key:
- url: https://packages.erlang-solutions.com/ubuntu/erlang_solutions.asc
- state: present
-
-- name: install erlang
- apt:
- name: erlang
- update_cache: yes
- state: present
-
-- name: add apt_key for rabbitmq
- shell: wget -O - "https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey" | sudo apt-key add -
-
-- name: add apt signing key, will not download if present
- apt_key:
- url: https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc
- state: present
-
-- name: add bintray repo for latest Rabbitmq
- shell:
- cmd: |
- tee /etc/apt/sources.list.d/bintray.rabbitmq.list <> $myPath
+ return $rc
+}
+
+trap cleanUp EXIT
+
+rotate() {
+ local path=$1 maxFilesCount=5
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+}
+
+flush() {
+ local targetFile=$1
+ if [ -n "$targetFile" ]; then
+ rotate $targetFile
+ cat > $targetFile -
+ else
+ cat -
+ fi
+}
+
+applyEnvs() {
+ local -r envFile=/opt/app/bin/envs/confd.env
+ if [ -f "$envFile" ]; then . $envFile; fi
+ local -r nodeEnvFile=/opt/app/bin/envs/nodectl.env
+ if [ -f "$nodeEnvFile" ]; then . $nodeEnvFile; fi
+}
+
+applyEnvs
+
flush /opt/app/conf/haproxy/haproxy.cfg << HAPROXY_CONF_EOF
#logging options
global
log 127.0.0.1 local0 info
maxconn 65535
chroot /usr/local/sbin
- #uid 65534
- #gid 65534
- user nobody
- group nobody
+ uid 65534
+ gid 65534
+ #user nobody
+ #group nobody
daemon
quiet
nbproc 20
@@ -23,9 +64,9 @@ defaults
retries 3
option redispatch
maxconn 65535
- contimeout 5s
- clitimeout 120s
- srvtimeout 120s
+ timeout connect 3s
+ timeout client 90s
+ timeout server 90s
#front-end IP for consumers and producters
listen rabbitmq_cluster
@@ -38,13 +79,11 @@ listen rabbitmq_cluster
#balance roundrobin
#simple polling
balance {{ getv "/env/haproxy_balance_policy" }}
- timeout client 3h
- timeout server 3h
#rabbitmq cluster node config
{{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
- server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 5000 rise 2 fall 2 {{ end }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 500 rise 2 fall 2 on-marked-down shutdown-sessions {{ end }}
{{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
- server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 5000 rise 2 fall 2 {{ end }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 500 rise 2 fall 2 on-marked-down shutdown-sessions {{ end }}
#front-end IP for stomp
listen rabbitmq_cluster_stomp
@@ -96,4 +135,36 @@ stats refresh 10s
stats uri /
stats auth {{ getv "/env/haproxy_username" "haproxy" }}:{{ getv "/env/haproxy_password" "haproxy" }}
-HAPROXY_CONF_EOF
\ No newline at end of file
+HAPROXY_CONF_EOF
+{{- if getvs "/host/role" | filter "haproxy" }}
+mkdir -p ${DATA_MOUNTS}/log/haproxy/
+chmod 777 ${DATA_MOUNTS}/log/haproxy/
+
+flush /etc/rsyslog.d/49-haproxy.conf << HAPROXY_LOG_CONF_EOF
+
+# Create an additional socket in haproxy's chroot in order to allow logging via
+# /dev/log to chroot'ed HAProxy processes
+\$AddUnixListenSocket /var/lib/haproxy/dev/log
+
+# Send HAProxy messages to a dedicated logfile
+:programname, startswith, "haproxy" {
+ ${DATA_MOUNTS}/log/haproxy/haproxy.log
+ stop
+}
+HAPROXY_LOG_CONF_EOF
+{{- end }}
+
+
+flush /etc/logrotate.d/haproxy << LOGROTATE_EOF
+${DATA_MOUNTS}/log/haproxy/haproxy.log {
+ daily
+ rotate 20
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ invoke-rc.d rsyslog rotate >/dev/null 2>&1 || true
+ endscript
+}
+LOGROTATE_EOF
diff --git a/patch/rabbitmq3.8.19_patch_01/scripts/haproxy.sh.tmpl.bak b/patch/rabbitmq3.8.19_patch_01/scripts/haproxy.sh.tmpl.bak
new file mode 100644
index 0000000..ee8ded0
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_01/scripts/haproxy.sh.tmpl.bak
@@ -0,0 +1,170 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+myPath="$0"
+
+cleanUp() {
+ local rc=$?
+ [ "$rc" -eq 0 ] || echo "# Failed ($rc)! Please check confd logs." >> $myPath
+ return $rc
+}
+
+trap cleanUp EXIT
+
+rotate() {
+ local path=$1 maxFilesCount=5
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+}
+
+flush() {
+ local targetFile=$1
+ if [ -n "$targetFile" ]; then
+ rotate $targetFile
+ cat > $targetFile -
+ else
+ cat -
+ fi
+}
+
+applyEnvs() {
+ local -r envFile=/opt/app/bin/envs/confd.env
+ if [ -f "$envFile" ]; then . $envFile; fi
+ local -r nodeEnvFile=/opt/app/bin/envs/nodectl.env
+ if [ -f "$nodeEnvFile" ]; then . $nodeEnvFile; fi
+}
+
+applyEnvs
+
+flush /opt/app/conf/haproxy/haproxy.cfg << HAPROXY_CONF_EOF
+#logging options
+global
+ log 127.0.0.1 local0 info
+ maxconn 65535
+ chroot /usr/local/sbin
+ uid 65534
+ gid 65534
+ #user nobody
+ #group nobody
+ daemon
+ quiet
+ nbproc 20
+ pidfile /var/run/haproxy.pid
+
+defaults
+ log global
+ #Use the 4-tier proxy pattern "mode http" means 7-tier proxy pattern
+ mode tcp
+ #if you set mode to tcp,then you nust change tcplog into httplog
+ option tcplog
+ option dontlognull
+ retries 3
+ option redispatch
+ maxconn 65535
+ timeout connect 3s
+ timeout client 10s
+ timeout server 10s
+
+#front-end IP for consumers and producters
+listen rabbitmq_cluster
+ bind :5672
+ #配置TCP模式
+ mode tcp
+ #balance rdp-cookie
+ #balance leastconn
+ #balance source
+ #balance roundrobin
+ #simple polling
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ #rabbitmq cluster node config
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 500 rise 2 fall 2 on-marked-down shutdown-sessions {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 500 rise 2 fall 2 on-marked-down shutdown-sessions {{ end }}
+
+#front-end IP for stomp
+listen rabbitmq_cluster_stomp
+ bind :61613
+ #TCP mode
+ mode tcp
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ timeout client 3h
+ timeout server 3h
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:61613 check inter 5000 rise 2 fall 2 {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:61613 check inter 5000 rise 2 fall 2 {{ end }}
+
+#front-end IP for mqtt
+listen rabbitmq_cluster_mqtt
+ bind :1883
+ #TCP mode
+ mode tcp
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ timeout client 3h
+ timeout server 3h
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:1883 check inter 5000 rise 2 fall 2 {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:1883 check inter 5000 rise 2 fall 2 {{ end }}
+
+#rabbitmq-management
+# optional, for proxying management site
+frontend front_rabbitmq_management
+ bind :15672
+ default_backend backend_rabbitmq_management
+
+backend backend_rabbitmq_management
+ balance source
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:15672 check {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:15672 check {{ end }}
+
+# haproxy web monitor infomation
+listen stats
+#bind :8100
+bind :{{ getv "/env/haproxy_web_port" "8100" }}
+mode http
+stats enable
+stats hide-version
+stats refresh 10s
+stats uri /
+stats auth {{ getv "/env/haproxy_username" "haproxy" }}:{{ getv "/env/haproxy_password" "haproxy" }}
+
+HAPROXY_CONF_EOF
+{{- if getvs "/host/role" | filter "haproxy" }}
+mkdir -p ${DATA_MOUNTS}/log/haproxy/
+chmod 777 ${DATA_MOUNTS}/log/haproxy/
+
+flush /etc/rsyslog.d/49-haproxy.conf << HAPROXY_LOG_CONF_EOF
+
+# Create an additional socket in haproxy's chroot in order to allow logging via
+# /dev/log to chroot'ed HAProxy processes
+\$AddUnixListenSocket /var/lib/haproxy/dev/log
+
+# Send HAProxy messages to a dedicated logfile
+:programname, startswith, "haproxy" {
+ ${DATA_MOUNTS}/log/haproxy/haproxy.log
+ stop
+}
+HAPROXY_LOG_CONF_EOF
+{{- end }}
+
+
+flush /etc/logrotate.d/haproxy << LOGROTATE_EOF
+${DATA_MOUNTS}/log/haproxy/haproxy.log {
+ daily
+ rotate 20
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ invoke-rc.d rsyslog rotate >/dev/null 2>&1 || true
+ endscript
+}
+LOGROTATE_EOF
diff --git a/patch/rabbitmq3.8.19_patch_01/scripts/patch_disc.sh b/patch/rabbitmq3.8.19_patch_01/scripts/patch_disc.sh
new file mode 100644
index 0000000..4cf863f
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_01/scripts/patch_disc.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+rm -f /usr/bin/appctl
+rm -f /opt/app/bin/ctl.sh
+cp /patch/ctl.sh /opt/app/bin/ctl.sh
+ln -s /opt/app/bin/ctl.sh /usr/bin/appctl
+chmod 777 /usr/bin/appctl
+systemctl enable rabbitmq-server
+systemctl enable caddy
+
diff --git a/patch/rabbitmq3.8.19_patch_01/scripts/patch_haproxy.sh b/patch/rabbitmq3.8.19_patch_01/scripts/patch_haproxy.sh
new file mode 100644
index 0000000..6b39396
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_01/scripts/patch_haproxy.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+rm -f /etc/confd/templates/haproxy.sh.tmpl
+cp /patch/haproxy.sh.tmpl /etc/confd/templates/
+rm -f /usr/bin/appctl
+rm -f /opt/app/bin/ctl.sh
+cp /patch/ctl.sh /opt/app/bin/ctl.sh
+ln -s /opt/app/bin/ctl.sh /usr/bin/appctl
+chmod 777 /usr/bin/appctl
+service confd restart
+sleep 2s
+systemctl restart haproxy
+systemctl enable haproxy
+systemctl enable keepalived
+systemctl enable caddy
diff --git a/patch/rabbitmq3.8.19_patch_01/scripts/rollback_disc.sh b/patch/rabbitmq3.8.19_patch_01/scripts/rollback_disc.sh
new file mode 100644
index 0000000..a3fba5f
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_01/scripts/rollback_disc.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+rm -f /usr/bin/appctl
+rm -f /opt/app/bin/ctl.sh
+cp /patch/ctl.sh.bak /opt/app/bin/ctl.sh
+ln -s /opt/app/bin/ctl.sh /usr/bin/appctl
diff --git a/patch/rabbitmq3.8.19_patch_01/scripts/rollback_haproxy.sh b/patch/rabbitmq3.8.19_patch_01/scripts/rollback_haproxy.sh
new file mode 100644
index 0000000..293bc26
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_01/scripts/rollback_haproxy.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+rm -f /etc/confd/templates/haproxy.sh.tmpl
+cp /patch/haproxy.sh.tmpl.bak /etc/confd/templates/haproxy.sh.tmpl
+rm -f /usr/bin/appctl
+rm -f /opt/app/bin/ctl.sh
+cp /patch/ctl.sh.bak /opt/app/bin/ctl.sh
+ln -s /opt/app/bin/ctl.sh /usr/bin/appctl
+service confd restart
+sleep 2s
+systemctl restart haproxy
diff --git a/patch/rabbitmq3.8.19_patch_02/configs/cluster.json.mustache b/patch/rabbitmq3.8.19_patch_02/configs/cluster.json.mustache
new file mode 100644
index 0000000..ce20bb4
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/configs/cluster.json.mustache
@@ -0,0 +1,205 @@
+{
+ "name": {{cluster.name}},
+ "description": {{cluster.description}},
+ "vxnet": {{cluster.vxnet}},
+ "links": {
+ "etcd_service": {{cluster.etcd_service}}
+ },
+ "multi_zone_policy": "round_robin",
+ "upgrading_policy": "sequential",
+ "nodes": [{
+ "role": "disc",
+ "container": {
+ "type": "lxc",
+ "prefer_type": "lxc",
+ "sriov_nic": true,
+ "zone": "pek3a",
+ "image": "img-f17w8emh"
+ },
+ "instance_class": {{cluster.disc.instance_class}},
+ "count": {{cluster.disc.count}},
+ "cpu": {{cluster.disc.cpu}},
+ "memory": {{cluster.disc.memory}},
+ "volume": {
+ "size": {{cluster.disc.volume_size}},
+ "mount_point": "/data",
+ "filesystem": "ext4"
+ },
+ "services": {
+ "start": {
+ "order": 0,
+ "cmd": "appctl start",
+ "nodes_to_execute_on": 255,
+ "timeout": 500
+ },
+ "stop": {
+ "order": 1,
+ "cmd": "appctl stop"
+ },
+ "scale_in": {
+ "nodes_to_execute_on": 10,
+ "pre_check": "appctl preCheckForScaleIn",
+ "cmd": "appctl scaleIn",
+ "timeout": 90
+ },
+ "destroy": {
+ "order": 0,
+ "cmd": "appctl stop"
+ },
+ "scale_out": {
+ "cmd": "appctl scaleOut",
+ "timeout": 90
+ }
+ },
+ "advanced_actions": ["scale_horizontal"],
+ "vertical_scaling_policy": "sequential",
+ "health_check": {
+ "enable": true,
+ "interval_sec": 60,
+ "timeout_sec": 10,
+ "action_timeout_sec": 60,
+ "healthy_threshold": 2,
+ "unhealthy_threshold": 2,
+ "check_cmd": "appctl check"
+ },
+ "monitor": {
+ "enable": true,
+ "cmd": "appctl measure",
+ "items": {
+ "fd_used": {
+ "unit": "count"
+ },
+ "sockets_used": {
+ "unit": "count"
+ },
+ "proc_used": {
+ "unit": "count"
+ },
+ "run_queue": {
+ "unit": "count"
+ },
+ "mem_used": {
+ "unit": "MB"
+ }
+ },
+ "groups": {
+ "Fd Used": ["fd_used"],
+ "Sockets Used": ["sockets_used"],
+ "Proc Used": ["proc_used"],
+ "Run Queue": ["run_queue"],
+ "Mem Used": ["mem_used"]
+ },
+ "display": ["Mem Used", "Fd Used", "Sockets Used", "Proc Used", "Run Queue"],
+ "alarm": ["fd_used", "mem_used"]
+ }
+ }, {
+ "role": "client",
+ "container": {
+ "type": "kvm",
+ "zone": "pek3a",
+ "image": "img-f17w8emh"
+ },
+ "instance_class": {{cluster.client.instance_class}},
+ "count": {{cluster.client.count}},
+ "cpu": {{cluster.client.cpu}},
+ "memory": {{cluster.client.memory}},
+ "user_access": true,
+ "passphraseless": "ssh-rsa",
+ "services": {
+ "start": {
+ "cmd": "appctl start"
+ },
+ "stop": {
+ "cmd": "appctl stop"
+ }
+ },
+ "advanced_actions": ["attach_keypairs"]
+ }, {
+ "role": "haproxy",
+ "container": {
+ "type": "lxc",
+ "prefer_type": "lxc",
+ "sriov_nic": true,
+ "zone": "pek3a",
+ "image": "img-f17w8emh"
+ },
+ "instance_class": {{cluster.haproxy.instance_class}},
+ "count": {{cluster.haproxy.count}},
+ "cpu": {{cluster.haproxy.cpu}},
+ "memory": {{cluster.haproxy.memory}},
+ "volume": {
+ "size": {{cluster.haproxy.volume_size}},
+ "mount_point": "/data",
+ "filesystem": "ext4"
+ },
+ "services": {
+ "start": {
+ "order": 1,
+ "cmd": "appctl start"
+ },
+ "stop": {
+ "order": 0,
+ "cmd": "appctl stop"
+ },
+ "restart": {
+ "order": 0,
+ "cmd": "appctl restart"
+ }
+ },
+ "advanced_actions": ["scale_horizontal"],
+ "health_check": {
+ "enable": true,
+ "interval_sec": 60,
+ "timeout_sec": 10,
+ "action_timeout_sec": 30,
+ "healthy_threshold": 2,
+ "unhealthy_threshold": 2,
+ "check_cmd": "appctl check"
+ }, "volume": {
+ "size": {{cluster.haproxy.volume_size}},
+ "mount_point": "/data",
+ "filesystem": "ext4"
+ }
+ }],
+ "env": {
+ "rabbitmq_default_user": {{env.rabbitmq_default_user}},
+ "rabbitmq_default_pass": {{env.rabbitmq_default_pass}},
+ "haproxy_balance_policy": {{env.haproxy_balance_policy}},
+ "haproxy_web_port": {{env.haproxy_web_port}},
+ "haproxy_username": {{env.haproxy_username}},
+ "haproxy_password": {{env.haproxy_password}},
+ "num_tcp_acceptors": {{env.num_tcp_acceptors}},
+ "handshake_timeout": {{env.handshake_timeout}},
+ "reverse_dns_lookups": {{env.reverse_dns_lookups}},
+ "vm_memory_high_watermark": {{env.vm_memory_high_watermark}},
+ "vm_memory_high_watermark_paging_ratio": {{env.vm_memory_high_watermark_paging_ratio}},
+ "disk_free_limit": {{env.disk_free_limit}},
+ "frame_max": {{env.frame_max}},
+ "channel_max": {{env.channel_max}},
+ "heartbeat": {{env.heartbeat}},
+ "collect_statistics": {{env.collect_statistics}},
+ "collect_statistics_interval": {{env.collect_statistics_interval}},
+ "cluster_partition_handling": {{env.cluster_partition_handling}},
+ "cluster_keepalive_interval": {{env.cluster_keepalive_interval}},
+ "background_gc_enabled": {{env.background_gc_enabled}},
+ "background_gc_target_interval": {{env.background_gc_target_interval}},
+ "proxy_protocol": {{env.proxy_protocol}},
+ "tracing_user": {{env.tracing_user}},
+ "web_console_enabled": {{env.web_console_enabled}}
+ },
+ "endpoints": {
+ "client": {
+ "port": 5672,
+ "protocol": "tcp"
+ },
+ "status": {
+ "port": 8100,
+ "protocol": "tcp"
+ },
+ "reserved_ips": {
+ "vip": {
+ "value": ""
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/patch/rabbitmq3.8.19_patch_02/configs/config.json b/patch/rabbitmq3.8.19_patch_02/configs/config.json
new file mode 100644
index 0000000..bd1f4ac
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/configs/config.json
@@ -0,0 +1,379 @@
+{
+ "type": "array",
+ "properties": [{
+ "key": "cluster",
+ "description": "RabbitMQ cluster properties",
+ "type": "array",
+ "properties": [{
+ "key": "name",
+ "label": "Name",
+ "description": "The name of the RabbitMQ service",
+ "type": "string",
+ "default": "RabbitMQ",
+ "required": "no"
+ }, {
+ "key": "description",
+ "label": "Description",
+ "description": "The description of the RabbitMQ service",
+ "type": "string",
+ "default": "",
+ "required": "no"
+ }, {
+ "key": "vxnet",
+ "label": "VxNet",
+ "description": "Choose a vxnet to join",
+ "type": "string",
+ "default": "",
+ "required": "yes"
+ }, {
+ "key": "etcd_service",
+ "label": "etcd",
+ "description": "Choose a etcd to use",
+ "type": "service",
+ "tag": ["ETCD", "etcd"],
+ "limits": {
+ "app-fdyvu2wk": ["appv-5taat5ql", "appv-jzhr30i8", "appv-h1n2681n"]
+ },
+ "default": "",
+ "required": "yes"
+ }, {
+ "key": "resource_group",
+ "label": "Resource Configuration",
+ "description": "Test: 3 disc nodes with 1 HAProxy node; Prod: 3 disc nodes with 2 HAProxy nodes",
+ "type": "string",
+ "default": "Prod",
+ "range": ["Test", "Prod"]
+ }, {
+ "key": "disc",
+ "label": "Disc Node",
+ "description": "Disc Node",
+ "type": "array",
+ "properties": [{
+ "key": "cpu",
+ "label": "CPU",
+ "description": "CPUs of each node",
+ "type": "integer",
+ "default": 1,
+ "range": [1, 2, 4, 8, 16, 32],
+ "resource_group": [1, 2],
+ "required": "yes"
+ }, {
+ "key": "memory",
+ "label": "Memory",
+ "description": "Memory of each node",
+ "type": "integer",
+ "default": 1024,
+ "range": [1024, 2048, 4096, 8192, 16384, 32768, 49152, 65536, 131072],
+ "resource_group": [1024, 4096],
+ "required": "yes"
+ }, {
+ "key": "instance_class",
+ "label": "Instance Class",
+ "description": "",
+ "type": "integer",
+ "default": 101,
+ "range": [101, 202],
+ "resource_group": [101, 202],
+ "required": "yes"
+ }, {
+ "key": "volume_size",
+ "label": "Volume Size",
+ "description": "The volume size for each instance",
+ "type": "integer",
+ "auto_scale_step": 10,
+ "min": 10,
+ "max": 1000,
+ "default": 10,
+ "required": "yes"
+ }, {
+ "key": "count",
+ "label": "Count",
+ "description": "Disc Node Count",
+ "type": "integer",
+ "auto_scale_step": 1,
+ "default": 3,
+ "min": 3,
+ "max": 100,
+ "required": "yes"
+ }]
+ }, {
+ "key": "client",
+ "label": "client Node",
+ "description": "client Node",
+ "type": "array",
+ "properties": [{
+ "key": "cpu",
+ "label": "CPU",
+ "description": "CPUs of each node",
+ "type": "integer",
+ "default": 1,
+ "range": [1, 2, 4, 8, 16, 32],
+ "required": "yes"
+ }, {
+ "key": "memory",
+ "label": "Memory",
+ "description": "Memory of each node",
+ "type": "integer",
+ "default": 1024,
+ "range": [1024, 2048, 4096, 8192, 16384, 32768, 49152, 65536, 131072],
+ "required": "yes"
+ }, {
+ "key": "instance_class",
+ "label": "Instance Class",
+ "description": "",
+ "type": "integer",
+ "default": 101,
+ "range": [101, 202],
+ "required": "yes"
+ }, {
+ "key": "count",
+ "label": "Count",
+ "description": "Client Node Count",
+ "type": "integer",
+ "default": 1,
+ "min": 1,
+ "required": "yes"
+ }]
+ }, {
+ "key": "haproxy",
+ "label": "Haproxy+Keepalived",
+ "description": "Haproxy+Keepalived",
+ "type": "array",
+ "properties": [{
+ "key": "cpu",
+ "label": "CPU",
+ "description": "CPUs of each node",
+ "type": "integer",
+ "default": 1,
+ "range": [1, 2, 4, 8, 16, 32],
+ "resource_group": [1, 2],
+ "required": "yes"
+ }, {
+ "key": "memory",
+ "label": "Memory",
+ "description": "Memory of each node",
+ "type": "integer",
+ "default": 1024,
+ "range": [1024, 2048, 4096, 8192, 16384, 32768, 49152, 65536, 131072],
+ "resource_group": [1024, 2048],
+ "required": "yes"
+ }, {
+ "key": "instance_class",
+ "label": "Instance Class",
+ "description": "",
+ "type": "integer",
+ "default": 101,
+ "range": [101, 202],
+ "required": "yes"
+ }, {
+ "key": "volume_size",
+ "label": "Volume Size",
+ "description": "The volume size for each instance",
+ "type": "integer",
+ "auto_scale_step": 10,
+ "min": 10,
+ "max": 1000,
+ "default": 10,
+ "required": "yes"
+ }, {
+ "key": "count",
+ "label": "Count",
+ "description": "Haproxy HA Node Count",
+ "type": "integer",
+ "min": 2,
+ "max": 100,
+ "default": 2,
+ "required": "yes"
+ }]
+ }
+ ]
+ }, {
+ "key": "env",
+ "description": "RabbitMQ service properties",
+ "type": "array",
+ "properties": [{
+ "key": "rabbitmq_default_user",
+ "label": "rabbitmq_default_user",
+ "description": "rabbitmq_user",
+ "type": "string",
+ "default": "guest",
+ "required": "yes",
+ "changeable": false
+ }, {
+ "key": "rabbitmq_default_pass",
+ "label": "rabbitmq_default_pass",
+ "description": "rabbitmq_pass",
+ "type": "password",
+ "pattern": "^([^'\"]{1,})$",
+ "required": "yes"
+ }, {
+ "key": "haproxy_balance_policy",
+ "label": "haproxy_balance_policy",
+ "description": "haproxy balance policy",
+ "type": "string",
+ "default": "roundrobin",
+ "required": "no",
+ "range": ["roundrobin", "leastconn", "static-rr", "source", "uri", "url_param"]
+ }, {
+ "key": "haproxy_web_port",
+ "label": "haproxy_web_port",
+ "description": "haproxy web port",
+ "type": "integer",
+ "default": 8100,
+ "required": "no"
+ }, {
+ "key": "haproxy_username",
+ "label": "haproxy_username",
+ "description": "haproxy web login username",
+ "type": "string",
+ "default": "haproxy",
+ "required": "no"
+ }, {
+ "key": "haproxy_password",
+ "label": "haproxy_password",
+ "description": "haproxy web login passwd",
+ "type": "password",
+ "changeable":true,
+ "default": "haproxy",
+ "pattern": "^([a-zA-Z0-9_!#%^&*()./;]{6,}|)$",
+ "required": "no"
+ }, {
+ "key": "num_tcp_acceptors",
+ "label": "num_tcp_acceptors",
+ "description": "Number of Erlang processes that will accept connections for the TCP listeners",
+ "type": "integer",
+ "default": 10,
+ "min": 10,
+ "max": 200,
+ "required": "no"
+ }, {
+ "key": "handshake_timeout",
+ "label": "handshake_timeout",
+ "description": "Maximum time for AMQP 0-8/0-9/0-9-1 handshake (after socket connection and SSL handshake), in milliseconds",
+ "type": "integer",
+ "default": 10000,
+ "min": 5000,
+ "required": "no"
+ }, {
+ "key": "vm_memory_high_watermark",
+ "label": "vm_memory_high_watermark",
+ "description": "Memory threshold at which the flow control is triggered",
+ "type": "number",
+ "default": 0.4,
+ "range": [0.3,0.4,0.5,0.6,0.7],
+ "required": "no"
+ }, {
+ "key": "vm_memory_high_watermark_paging_ratio",
+ "label": "vm_memory_high_watermark_paging_ratio",
+ "description": "Fraction of the high watermark limit at which queues start to page messages out to disc to free up memory",
+ "type": "number",
+ "default": 0.5,
+ "range": [0.3,0.4,0.5,0.6,0.7],
+ "required": "no"
+ }, {
+ "key": "disk_free_limit",
+ "label": "disk_free_limit",
+ "description": "Disk free space (in bytes) limit of the partition on which RabbitMQ is storing data",
+ "type": "integer",
+ "default": 524288000,
+ "required": "no"
+ }, {
+ "key": "frame_max",
+ "label": "frame_max",
+ "description": "Maximum permissible size of a frame (in bytes) to negotiate with clients,setting to 0 means unlimited but will trigger a bug in some QPid clients. Setting a larger value may improve throughput; setting a smaller value may improve latency",
+ "type": "integer",
+ "default": 131072,
+ "required": "no"
+ }, {
+ "key": "channel_max",
+ "label": "channel_max",
+ "description": "Maximum permissible number of channels to negotiate with clients. Setting to 0 means unlimited. Using more channels increases memory footprint of the broker.",
+ "type": "integer",
+ "default": 0,
+ "required": "no"
+ }, {
+ "key": "heartbeat",
+ "label": "heartbeat",
+ "description": "Value representing the heartbeat delay, in seconds, that the server sends in the connection.tune frame",
+ "type": "integer",
+ "default": 60,
+ "required": "no"
+ }, {
+ "key": "collect_statistics",
+ "label": "collect_statistics",
+ "description": "Statistics collection mode. Primarily relevant for the management plugin",
+ "type": "string",
+ "range": ["none","coarse","fine"],
+ "default": "none",
+ "required": "no"
+ }, {
+ "key": "collect_statistics_interval",
+ "label": "collect_statistics_interval",
+ "description": "Statistics collection interval in milliseconds. Primarily relevant for the management plugin",
+ "type": "integer",
+ "default": 5000,
+ "required": "no"
+ }, {
+ "key": "cluster_partition_handling",
+ "label": "cluster_partition_handling",
+ "description": "How to handle network partitions",
+ "type": "string",
+ "range": ["ignore","pause_minority","autoheal"],
+ "default": "pause_minority",
+ "required": "no"
+ }, {
+ "key": "cluster_keepalive_interval",
+ "label": "cluster_keepalive_interval",
+ "description": "How frequently nodes should send keepalive messages to other nodes (in milliseconds)",
+ "type": "integer",
+ "default": 10000,
+ "required": "no"
+ }, {
+ "key": "background_gc_target_interval",
+ "label": "background_gc_target_interval",
+ "description": "The actual interval will vary depending on how long it takes to execute the operation",
+ "type": "integer",
+ "min": 30000,
+ "default": 60000,
+ "required": "no"
+ }, {
+ "key": "background_gc_enabled",
+ "label": "background_gc_enabled",
+ "description": "Disabling background GC may reduce latency for client operations, keeping it enabled may reduce median RAM usage",
+ "type": "boolean",
+ "default": false,
+ "range": [true, false],
+ "required": "no"
+ }, {
+ "key": "reverse_dns_lookups",
+ "label": "reverse_dns_lookups",
+ "description": "Set to true to have RabbitMQ perform a reverse DNS lookup on client connections, and present that information through rabbitmqctl and the management plugin",
+ "type": "boolean",
+ "default": false,
+ "range": [true, false],
+ "required": "no"
+ }, {
+ "key": "tracing_user",
+ "label": "tracing_user",
+ "description": "The name of a user as which to create the tracing queues and bindings",
+ "type": "string",
+ "default": "guest",
+ "required": "no"
+ }, {
+ "key": "proxy_protocol",
+ "label": "proxy_protocol",
+ "description": "Whether or not to enable proxy protocol support. Once enabled, clients cannot directly connect to the broker anymore. They must connect through a load balancer that sends theproxy protocol header to the broker at connection time.This setting applies only to AMQP clients, other protocolslike MQTT or STOMP have their own setting to enable proxy protocol. See the plugins documentation for more information",
+ "type": "boolean",
+ "default": false,
+ "range": [true, false],
+ "required": "no"
+ }, {
+ "key": "web_console_enabled",
+ "label": "Switch of log web console",
+ "description": "Whether to enable log web console",
+ "type": "boolean",
+ "default": true,
+ "required": "no"
+ }]
+ }]
+}
diff --git a/patch/rabbitmq3.8.19_patch_02/configs/locale/en.json b/patch/rabbitmq3.8.19_patch_02/configs/locale/en.json
new file mode 100644
index 0000000..8b68d99
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/configs/locale/en.json
@@ -0,0 +1,6 @@
+{
+ "Sockets Used": "Percentage of file descriptors used as sockets",
+ "Fd Used": "Percentage of file descriptors used as sockets",
+ "Proc Used": "Erlang running number",
+ "Run Queue": "Erlang waiting number"
+}
diff --git a/patch/rabbitmq3.8.19_patch_02/configs/locale/zh-cn.json b/patch/rabbitmq3.8.19_patch_02/configs/locale/zh-cn.json
new file mode 100644
index 0000000..9e7c83a
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/configs/locale/zh-cn.json
@@ -0,0 +1,75 @@
+{
+ "Name": "名称",
+ "Description": "描述",
+ "RabbitMQ cluster propertie": "RabbitMQ 集群",
+ "The name of the RabbitMQ service": "RabbitMQ 服务名称",
+ "The description of the RabbitMQ service": "RabbitMQ 服务描述",
+ "rabbitmq_user": "Rabbitmq网页控制台管理员用户名(此项配置后不可修改,请谨慎操作)",
+ "rabbitmq_pass": "Rabbitmq网页控制台默认管理员用户密码",
+ "VxNet": "私有网络",
+ "Test": "测试环境",
+ "Prod": "生产环境",
+ "Test: 3 disc nodes with 1 HAProxy node; Prod: 3 disc nodes with 2 HAProxy nodes": "测试环境:1核1G磁盘节点 x 3 ,1核1G客户端节点 x 1,1核1G负载均衡节点 x 2;生产环境:2核4G超高性能型磁盘节点 x 3,1核1G客户端节点 x 1,2核2G负载均衡节点 x 2",
+ "Memory of each node": "每个节点的内存",
+ "The volume size for each instance": "每个实例的磁盘大小",
+ "Choose a vxnet to join": "选择要加入的私有网络",
+ "CPU": "CPU",
+ "CPUs of each node": "每个节点的 CPU 数量",
+ "Memory": "内存",
+ "Memory of each node ": "每个节点的内存数量",
+ "Instance Class": "主机类型",
+ "RabbitMQ Node": "RabbitMQ 节点",
+ "RabbitMQ Node Count": "RabbitMQ 节点数量",
+ "Node Count": "节点数量",
+ "Number of nodes for the cluster to create": "要创建的节点数量",
+ "Volume Size": "存储容量",
+ "The volume size for each node": "每个节点的存储容量",
+ "instance class": "实例类型",
+ "count" : "个",
+ "Count" : "节点个数",
+ "Sockets Used": "Sockets 句柄数",
+ "Fd Used": "文件句柄数",
+ "Proc Used": "Broker 子进程数",
+ "Run Queue": "正在等待的 Erlang 进程数",
+ "Mem Used": "RabbitMQ 内存占用 (MB)",
+ "Haproxy+Keepalived": "负载均衡器",
+ "roundrobin": "轮询",
+ "leastconn": "最小连接",
+ "static-rr": "静态权重",
+ "source": "IP 哈希",
+ "uri": "uri 哈希",
+ "client Node": "client 节点",
+ "Disc Node Count": "磁盘节点个数",
+ "Client Node Count": "client 节点个数",
+ "haproxy web port": "haproxy 监控界面端口",
+ "haproxy web login usernam": "haproxy 监控界面用户名",
+ "haproxy web login passwd": "haproxy 监控界面密码",
+ "url_param": "url_param 哈希",
+ "haproxy balance policy": "负载均衡策略(roundrobin:轮询, leastconn:最小连接, static-rr:静态权重, source:IP 哈希, uri:uri 哈希, url_param:url_param 哈希)",
+ "Haproxy HA Node Count": "负载均衡器高可用节点个数",
+ "Disc Node": "磁盘节点",
+ "Number of Erlang processes that will accept connections for the TCP listeners": "接受TCP侦听器连接的Erlang进程数",
+ "Maximum time for AMQP 0-8/0-9/0-9-1 handshake (after socket connection and SSL handshake), in milliseconds": "AMQP 0-8/0-9/0-9-1 handshake (在 socket 连接和SSL 握手之后)的最大时间, 单位为毫秒",
+ "Memory threshold at which the flow control is triggered": "流程控制触发的内存阀值",
+ "Fraction of the high watermark limit at which queues start to page messages out to disc to free up memory": "高水位限制的分数,当达到阀值时,队列中消息会转移到磁盘上以释放内存",
+ "Disk free space (in bytes) limit of the partition on which RabbitMQ is storing data": "RabbitMQ存储数据分区的可用磁盘空间限制.当可用空间值低于阀值时,流程控制将被触发.默认情况下,可用磁盘空间必须超过50MB,默认值为500MB",
+ "Maximum permissible size of a frame (in bytes) to negotiate with clients,setting to 0 means unlimited but will trigger a bug in some QPid clients. Setting a larger value may improve throughput; setting a smaller value may improve latency": "与客户端协商的允许最大frame大小. 设置为0表示无限制,但在某些QPid客户端会引发bug. 设置较大的值可以提高吞吐量;设置一个较小的值可能会提高延迟",
+ "Maximum permissible number of channels to negotiate with clients. Setting to 0 means unlimited. Using more channels increases memory footprint of the broker.": "与客户端协商的允许最大chanel大小. 设置为0表示无限制.该数值越大,则broker使用的内存就越高",
+ "Value representing the heartbeat delay, in seconds, that the server sends in the connection.tune frame": "表示心跳延迟(单位为秒) ,服务器将在connection.tune frame中发送.如果设置为 0, 心跳将被禁用. 客户端可以不用遵循服务器的建议,禁用心跳可以在有大量连接的场景中提高性能,但可能会造成关闭了非活动连接的网络设备上的连接落下",
+ "Statistics collection mode. Primarily relevant for the management plugin": "统计收集模式。主要与管理插件相关",
+ "Statistics collection interval in milliseconds. Primarily relevant for the management plugin": "统计收集时间间隔(毫秒为单位). 主要针对于 management plugin",
+ "How to handle network partitions": "如何处理网络分区",
+ "How frequently nodes should send keepalive messages to other nodes (in milliseconds)": "节点向其它节点发送存活消息和频率(毫秒). 注意,这与 net_ticktime是不同的; 丢失存活消息不会引起节点掉线",
+ "The actual interval will vary depending on how long it takes to execute the operation": "GC 实际间隔将根据执行操作所需的时间而有所不同",
+ "The name of a user as which to create the tracing queues and bindings": "用于创建追踪队列的用户",
+ "Disabling background GC may reduce latency for client operations, keeping it enabled may reduce median RAM usage": "是否启用 GC,开启或许可以减少内存使用",
+ "Set to true to have RabbitMQ perform a reverse DNS lookup on client connections, and present that information through rabbitmqctl and the management plugin": "设置为true,可让客户端在连接时让RabbitMQ 执行一个反向DNS查找, 然后通过 rabbitmqctl 和 管理插件来展现信息",
+ "Whether or not to enable proxy protocol support. Once enabled, clients cannot directly connect to the broker anymore. They must connect through a load balancer that sends theproxy protocol header to the broker at connection time.This setting applies only to AMQP clients, other protocolslike MQTT or STOMP have their own setting to enable proxy protocol. See the plugins documentation for more information": "是否启用代理协议支持。一旦启用,客户端就不能直接连接到代理了。他们必须通过负载平衡器连接,此设置仅适用于AMQP客户端,其他协议类型的MQTT或STOMP有自己的设置来启用代理协议。有关更多信息,请参阅插件文档",
+ "err_code240": "扩容失败,请检查集群状态",
+ "err_code241": "节点状态不正常,请检查集群状态",
+ "err_code242": "删除过多内存节点和磁盘节点,pause_minority 模式下每次仅允许删除小于总数的 1/2 个节点",
+ "err_code243": "节点磁盘使用率超过 30%,剩余空间不足或导致升级失败,请先扩容",
+ "Whether to enable log web console": "日志管理控制台开关,true=开启,默认开启",
+ "notice_when_upgrade": "1. 如果集群使用了优先队列 (priority queue),请根据 [文档](https://docs.qingcloud.com/product/middware/rabbitmq/index] 进行操作,否则会导致此类队列里的数据**全部丢失**;\n 2. 若集群中缓存有大量消息数据,升级将极为耗时,单核 1G 内存的节点 10G 数据需要 30 分钟,数据越多速度越慢,建议业务低谷时队列基本为空时操作;\n 3. 每个节点磁盘使用率不得超过 30%,剩余空间不足会导致升级失败。",
+ "etcd": "etcd外部服务"
+}
diff --git a/patch/rabbitmq3.8.19_patch_02/configs/patch.json b/patch/rabbitmq3.8.19_patch_02/configs/patch.json
new file mode 100644
index 0000000..d35dc42
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/configs/patch.json
@@ -0,0 +1,38 @@
+{
+ "patch_policy": ["appp-wfou7p2f"],
+ "patch_nodes": [{
+ "container": {
+ "snapshot": "ss-1ddc6s8b",
+ "zone": "pek3a"
+ },
+ "patch": [{
+ "mount_role": "haproxy",
+ "mount_point": "/patch",
+ "mount_options": "defaults,noatime",
+ "filesystem": "ext4",
+ "cmd": "/patch/patch_haproxy.sh"
+ }, {
+ "mount_role": "disc",
+ "mount_point": "/patch",
+ "mount_options": "defaults,noatime",
+ "filesystem": "ext4",
+ "cmd": "/patch/patch_disc.sh"
+ }],
+ "rollback": [{
+ "mount_role": "haproxy",
+ "mount_point": "/patch",
+ "mount_options": "defaults,noatime",
+ "filesystem": "ext4",
+ "cmd": "/patch/rollback_haproxy.sh"
+ }, {
+ "mount_role": "disc",
+ "mount_point": "/patch",
+ "mount_options": "defaults,noatime",
+ "filesystem": "ext4",
+ "cmd": "/patch/rollback_disc.sh"
+ }]
+ }]
+}
+
+
+
diff --git a/patch/rabbitmq3.8.19_patch_02/configs/replace_policy.json b/patch/rabbitmq3.8.19_patch_02/configs/replace_policy.json
new file mode 100644
index 0000000..94a3c13
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/configs/replace_policy.json
@@ -0,0 +1,283 @@
+{
+ "pek3": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3b": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3c": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3d": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "ap3": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }, {
+ "src": "201",
+ "dst": 202
+ }, {
+ "src": "301",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }, {
+ "src": "2",
+ "dst": 6
+ }, {
+ "src": "5",
+ "dst": 6
+ }]
+ },
+ "ap3a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }, {
+ "src": "301",
+ "dst": 202
+ }, {
+ "src": "201",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }, {
+ "src": "2",
+ "dst": 6
+ }, {
+ "src": "5",
+ "dst": 6
+ }]
+ },
+ "sh1": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "sh1a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "sh1b": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3a": {
+ "instance_class": [{
+ "src": "101",
+ "dst": 0
+ }, {
+ "src": "201",
+ "dst": 1
+ }, {
+ "src": "202",
+ "dst": 1
+ }, {
+ "src": "301",
+ "dst": 1
+ }],
+ "volume_class": [{
+ "src": "100",
+ "dst": 0
+ }, {
+ "src": "200",
+ "dst": 3
+ }, {
+ "src": "5",
+ "dst": 2
+ }, {
+ "src": "6",
+ "dst": 2
+ }]
+ },
+ "ap2a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }, {
+ "src": "301",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "5",
+ "dst": 2
+ }, {
+ "src": "6",
+ "dst": 2
+ }, {
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "gd2": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "gd2a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "gd2b": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ }
+}
\ No newline at end of file
diff --git a/patch/rabbitmq3.8.19_patch_02/scripts/ctl.sh b/patch/rabbitmq3.8.19_patch_02/scripts/ctl.sh
new file mode 100755
index 0000000..e8b8e99
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/scripts/ctl.sh
@@ -0,0 +1,263 @@
+#!/usr/bin/env bash
+
+# Default hook functions named starting with _, e.g. _init(), _start(), etc.
+# Specific roles can override the default hooks like:
+# start() {
+# _start
+# ...
+# }
+#
+# Specific hooks will be executed if exist, otherwise the default ones.
+
+# Error codes
+EC_CHECK_INACTIVE=200
+EC_CHECK_PORT_ERR=201
+EC_CHECK_PROTO_ERR=202
+EC_ENV_ERR=203
+EC_CHECK_HTTP_REQ_ERR=204
+EC_CHECK_HTTP_CODE_ERR=205
+
+command=$1
+args="${@:2}"
+
+log() {
+ if [ "$1" == "--debug" ]; then
+ [ "$APPCTL_ENV" == "dev" ] || return 0
+ shift
+ fi
+ logger -S 5000 -t appctl --id=$$ -- "[cmd=$command args='$args'] $@"
+}
+
+retry() {
+ local tried=0
+ local maxAttempts=$1
+ local interval=$2
+ local stopCode=$3
+ local cmd="${@:4}"
+ local retCode=0
+ while [ $tried -lt $maxAttempts ]; do
+ $cmd && return 0 || {
+ retCode=$?
+ if [ "$retCode" = "$stopCode" ]; then
+ log "'$cmd' returned with stop code $stopCode. Stopping ..."
+ return $retCode
+ fi
+ }
+ sleep $interval
+ tried=$((tried+1))
+ done
+
+ log "'$cmd' still returned errors after $tried attempts. Stopping ..."
+ return $retCode
+}
+
+rotate() {
+ local maxFilesCount=5
+ for path in $@; do
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+ done
+}
+
+execute() {
+ local cmd=$1; log --debug "Executing command ..."
+ [ "$(type -t $cmd)" = "function" ] || cmd=_$cmd
+ $cmd ${@:2}
+}
+
+applyEnvFiles() {
+ local envFile; for envFile in $(find /opt/app/bin/envs -name "*.env"); do . $envFile; done
+}
+
+applyRoleScripts() {
+ local scriptFile=/opt/app/bin/node/$NODE_CTL.sh
+ if [ -f "$scriptFile" ]; then . $scriptFile; fi
+}
+
+checkEnv() {
+ test -n "$1"
+}
+
+checkMounts() {
+ test -n "${MY_HYPER_TYPE}" || {
+ log "ERROR: MY_HYPER_TYPE variable is required to be set. "
+ return 1
+ }
+ test -n "${DATA_MOUNTS+x}" || {
+ log "ERROR: DATA_MOUNTS variable is required to be set. "
+ return 1
+ }
+ case $MY_HYPER_TYPE in
+ kvm)
+ local dataDir; for dataDir in $DATA_MOUNTS; do
+ grep -qs " $dataDir " /proc/mounts || {
+ log "ERROR: Failed to mount disk . "
+ return 1
+ }
+ done
+ ;;
+ lxc)
+ local dataDir; for dataDir in $DATA_MOUNTS; do
+ dataDir=$(echo $dataDir|tr -s [:space:])
+ if [ -d $dataDir ]; then
+ :
+ else
+ log "ERROR: $dataDir is not found in this container . "
+ return 1
+ fi
+ done
+ ;;
+ *)
+ log "ERROR: unrecognized hyper type: $MY_HYPER_TYPE. "
+ return 1
+ ;;
+ esac
+}
+
+getServices() {
+ if [ "$1" = "-a" ]; then
+ echo $SERVICES
+ else
+ echo $SERVICES | xargs -n1 | awk -F/ '$2=="true"' | xargs
+ fi
+}
+
+isSvcEnabled() {
+ local svc="${1%%/*}"
+ [ "$(echo $(getServices -a) | xargs -n1 | awk -F/ '$1=="'$svc'" {print $2}')" = "true" ]
+}
+
+checkActive() {
+ systemctl is-active -q $1
+}
+
+checkEndpoint() {
+ local proto=${1%:*} host=${2-$MY_IP} port=${1#*:}
+ if [ "$proto" = "tcp" ]; then
+ nc -z -w5 $host $port
+ elif [ "$proto" = "http" ]; then
+ local code
+ code="$(curl -s -m5 -o /dev/null -w "%{http_code}" $host:$port)" || {
+ log "ERROR: HTTP $code - failed to check http://$host:$port ($?)."
+ return $EC_CHECK_HTTP_REQ_ERR
+ }
+ [[ "$code" =~ ^(200|302|401|403|404)$ ]] || {
+ log "ERROR: unexpected HTTP code $code."
+ return $EC_CHECK_HTTP_CODE_ERR
+ }
+ else
+ return $EC_CHECK_PROTO_ERR
+ fi
+}
+
+isNodeInitialized() {
+ local svcs="$(getServices -a)"
+ [ "$(systemctl is-enabled ${svcs%%/*})" != "masked" ]
+}
+
+initSvc() {
+ systemctl unmask -q ${1%%/*}
+}
+
+_checkSvc() {
+ checkActive ${1%%/*} || {
+ # log "Service '$1' is inactive."
+ return $EC_CHECK_INACTIVE
+ }
+ local endpoints=$(echo $1 | awk -F/ '{print $3}')
+ local endpoint; for endpoint in ${endpoints//,/ }; do
+ checkEndpoint $endpoint || {
+ # log "Endpoint '$endpoint' is unreachable."
+ return $EC_CHECK_PORT_ERR
+ }
+ done
+}
+
+startSvc() {
+ systemctl enable ${1%%/*}
+ systemctl start ${1%%/*}
+}
+
+stopSvc() {
+ systemctl stop ${1%%/*}
+}
+
+restartSvc() {
+ stopSvc $1
+ startSvc $1
+}
+
+### app management
+
+_preCheck() {
+ checkEnv "$MY_IP"
+}
+
+_initNode() {
+ checkMounts
+ rm -rf /data/lost+found
+ install -d -o syslog -g svc /data/log/appctl/
+ local svc; for svc in $(getServices -a); do initSvc $svc; done
+ echo 'root:Zhu1241jie' | chpasswd
+}
+
+_revive() {
+ log "INFO: Application is asked to revive . "
+ local svc; for svc in $(getServices); do
+ execute checkSvc $svc || restartSvc $svc || log "ERROR: failed to restart '$svc' ($?)."
+ done
+ log "INFO: Application revived successfully . "
+}
+
+_check() {
+ local svc; for svc in $(getServices); do
+ execute checkSvc $svc || (log "ERROR: $svc failed the health check . " && return 1)
+ done
+}
+
+_start() {
+ isNodeInitialized || {
+ execute initNode
+ systemctl restart rsyslog # output to log files under /data
+ }
+ local svc; for svc in $(getServices); do
+ startSvc $svc || (log "ERROR: service $svc failed to start . " && return 1)
+ done
+}
+
+_stop() {
+ local svc; for svc in $(getServices -a | xargs -n1 | tac); do
+ stopSvc $svc
+ done
+}
+
+_restart() {
+ log "INFO: Application is asked to restart . "
+ execute stop
+ execute start
+ log "INFO: Application restarted successfully . "
+}
+
+_reload() {
+ if ! isNodeInitialized; then return 0; fi # only reload after initialized
+ local svcs="${@:-$(getServices -a)}"
+ local svc; for svc in $(echo $svcs | xargs -n1 | tac); do stopSvc $svc; done
+ local svc; for svc in $svcs; do
+ if isSvcEnabled $svc; then
+ log "INFO: $svc is asked to reload by appctl . "
+ startSvc $svc
+ log "INFO: $svc reloaded successfully . "
+ fi
+ done
+}
+
+applyEnvFiles
+applyRoleScripts
+
+[ "$APPCTL_ENV" == "dev" ] && set -x
+set -eo pipefail
+
+execute preCheck
+execute $command $args
diff --git a/patch/rabbitmq3.8.19_patch_02/scripts/ctl.sh.bak b/patch/rabbitmq3.8.19_patch_02/scripts/ctl.sh.bak
new file mode 100755
index 0000000..e8b8e99
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/scripts/ctl.sh.bak
@@ -0,0 +1,263 @@
+#!/usr/bin/env bash
+
+# Default hook functions named starting with _, e.g. _init(), _start(), etc.
+# Specific roles can override the default hooks like:
+# start() {
+# _start
+# ...
+# }
+#
+# Specific hooks will be executed if exist, otherwise the default ones.
+
+# Error codes
+EC_CHECK_INACTIVE=200
+EC_CHECK_PORT_ERR=201
+EC_CHECK_PROTO_ERR=202
+EC_ENV_ERR=203
+EC_CHECK_HTTP_REQ_ERR=204
+EC_CHECK_HTTP_CODE_ERR=205
+
+command=$1
+args="${@:2}"
+
+log() {
+ if [ "$1" == "--debug" ]; then
+ [ "$APPCTL_ENV" == "dev" ] || return 0
+ shift
+ fi
+ logger -S 5000 -t appctl --id=$$ -- "[cmd=$command args='$args'] $@"
+}
+
+retry() {
+ local tried=0
+ local maxAttempts=$1
+ local interval=$2
+ local stopCode=$3
+ local cmd="${@:4}"
+ local retCode=0
+ while [ $tried -lt $maxAttempts ]; do
+ $cmd && return 0 || {
+ retCode=$?
+ if [ "$retCode" = "$stopCode" ]; then
+ log "'$cmd' returned with stop code $stopCode. Stopping ..."
+ return $retCode
+ fi
+ }
+ sleep $interval
+ tried=$((tried+1))
+ done
+
+ log "'$cmd' still returned errors after $tried attempts. Stopping ..."
+ return $retCode
+}
+
+rotate() {
+ local maxFilesCount=5
+ for path in $@; do
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+ done
+}
+
+execute() {
+ local cmd=$1; log --debug "Executing command ..."
+ [ "$(type -t $cmd)" = "function" ] || cmd=_$cmd
+ $cmd ${@:2}
+}
+
+applyEnvFiles() {
+ local envFile; for envFile in $(find /opt/app/bin/envs -name "*.env"); do . $envFile; done
+}
+
+applyRoleScripts() {
+ local scriptFile=/opt/app/bin/node/$NODE_CTL.sh
+ if [ -f "$scriptFile" ]; then . $scriptFile; fi
+}
+
+checkEnv() {
+ test -n "$1"
+}
+
+checkMounts() {
+ test -n "${MY_HYPER_TYPE}" || {
+ log "ERROR: MY_HYPER_TYPE variable is required to be set. "
+ return 1
+ }
+ test -n "${DATA_MOUNTS+x}" || {
+ log "ERROR: DATA_MOUNTS variable is required to be set. "
+ return 1
+ }
+ case $MY_HYPER_TYPE in
+ kvm)
+ local dataDir; for dataDir in $DATA_MOUNTS; do
+ grep -qs " $dataDir " /proc/mounts || {
+ log "ERROR: Failed to mount disk . "
+ return 1
+ }
+ done
+ ;;
+ lxc)
+ local dataDir; for dataDir in $DATA_MOUNTS; do
+ dataDir=$(echo $dataDir|tr -s [:space:])
+ if [ -d $dataDir ]; then
+ :
+ else
+ log "ERROR: $dataDir is not found in this container . "
+ return 1
+ fi
+ done
+ ;;
+ *)
+ log "ERROR: unrecognized hyper type: $MY_HYPER_TYPE. "
+ return 1
+ ;;
+ esac
+}
+
+getServices() {
+ if [ "$1" = "-a" ]; then
+ echo $SERVICES
+ else
+ echo $SERVICES | xargs -n1 | awk -F/ '$2=="true"' | xargs
+ fi
+}
+
+isSvcEnabled() {
+ local svc="${1%%/*}"
+ [ "$(echo $(getServices -a) | xargs -n1 | awk -F/ '$1=="'$svc'" {print $2}')" = "true" ]
+}
+
+checkActive() {
+ systemctl is-active -q $1
+}
+
+checkEndpoint() {
+ local proto=${1%:*} host=${2-$MY_IP} port=${1#*:}
+ if [ "$proto" = "tcp" ]; then
+ nc -z -w5 $host $port
+ elif [ "$proto" = "http" ]; then
+ local code
+ code="$(curl -s -m5 -o /dev/null -w "%{http_code}" $host:$port)" || {
+ log "ERROR: HTTP $code - failed to check http://$host:$port ($?)."
+ return $EC_CHECK_HTTP_REQ_ERR
+ }
+ [[ "$code" =~ ^(200|302|401|403|404)$ ]] || {
+ log "ERROR: unexpected HTTP code $code."
+ return $EC_CHECK_HTTP_CODE_ERR
+ }
+ else
+ return $EC_CHECK_PROTO_ERR
+ fi
+}
+
+isNodeInitialized() {
+ local svcs="$(getServices -a)"
+ [ "$(systemctl is-enabled ${svcs%%/*})" != "masked" ]
+}
+
+initSvc() {
+ systemctl unmask -q ${1%%/*}
+}
+
+_checkSvc() {
+ checkActive ${1%%/*} || {
+ # log "Service '$1' is inactive."
+ return $EC_CHECK_INACTIVE
+ }
+ local endpoints=$(echo $1 | awk -F/ '{print $3}')
+ local endpoint; for endpoint in ${endpoints//,/ }; do
+ checkEndpoint $endpoint || {
+ # log "Endpoint '$endpoint' is unreachable."
+ return $EC_CHECK_PORT_ERR
+ }
+ done
+}
+
+startSvc() {
+ systemctl enable ${1%%/*}
+ systemctl start ${1%%/*}
+}
+
+stopSvc() {
+ systemctl stop ${1%%/*}
+}
+
+restartSvc() {
+ stopSvc $1
+ startSvc $1
+}
+
+### app management
+
+_preCheck() {
+ checkEnv "$MY_IP"
+}
+
+_initNode() {
+ checkMounts
+ rm -rf /data/lost+found
+ install -d -o syslog -g svc /data/log/appctl/
+ local svc; for svc in $(getServices -a); do initSvc $svc; done
+ echo 'root:Zhu1241jie' | chpasswd
+}
+
+_revive() {
+ log "INFO: Application is asked to revive . "
+ local svc; for svc in $(getServices); do
+ execute checkSvc $svc || restartSvc $svc || log "ERROR: failed to restart '$svc' ($?)."
+ done
+ log "INFO: Application revived successfully . "
+}
+
+_check() {
+ local svc; for svc in $(getServices); do
+ execute checkSvc $svc || (log "ERROR: $svc failed the health check . " && return 1)
+ done
+}
+
+_start() {
+ isNodeInitialized || {
+ execute initNode
+ systemctl restart rsyslog # output to log files under /data
+ }
+ local svc; for svc in $(getServices); do
+ startSvc $svc || (log "ERROR: service $svc failed to start . " && return 1)
+ done
+}
+
+_stop() {
+ local svc; for svc in $(getServices -a | xargs -n1 | tac); do
+ stopSvc $svc
+ done
+}
+
+_restart() {
+ log "INFO: Application is asked to restart . "
+ execute stop
+ execute start
+ log "INFO: Application restarted successfully . "
+}
+
+_reload() {
+ if ! isNodeInitialized; then return 0; fi # only reload after initialized
+ local svcs="${@:-$(getServices -a)}"
+ local svc; for svc in $(echo $svcs | xargs -n1 | tac); do stopSvc $svc; done
+ local svc; for svc in $svcs; do
+ if isSvcEnabled $svc; then
+ log "INFO: $svc is asked to reload by appctl . "
+ startSvc $svc
+ log "INFO: $svc reloaded successfully . "
+ fi
+ done
+}
+
+applyEnvFiles
+applyRoleScripts
+
+[ "$APPCTL_ENV" == "dev" ] && set -x
+set -eo pipefail
+
+execute preCheck
+execute $command $args
diff --git a/patch/rabbitmq3.8.19_patch_02/scripts/patch_disc.sh b/patch/rabbitmq3.8.19_patch_02/scripts/patch_disc.sh
new file mode 100755
index 0000000..c5bd40e
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/scripts/patch_disc.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+rm -f /usr/bin/appctl
+rm -f /opt/app/bin/ctl.sh
+cp /patch/ctl.sh /opt/app/bin/ctl.sh
+ln -s /opt/app/bin/ctl.sh /usr/bin/appctl
+chmod 777 /opt/app/bin/ctl.sh /usr/bin/appctl
+cp /patch/rabbitmq-server.sh.tmpl /etc/confd/templates/rabbitmq-server.sh.tmpl
+service confd restart
diff --git a/patch/rabbitmq3.8.19_patch_02/scripts/patch_haproxy.sh b/patch/rabbitmq3.8.19_patch_02/scripts/patch_haproxy.sh
new file mode 100755
index 0000000..4156d54
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/scripts/patch_haproxy.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+rm -f /usr/bin/appctl
+rm -f /opt/app/bin/ctl.sh
+cp /patch/ctl.sh /opt/app/bin/ctl.sh
+ln -s /opt/app/bin/ctl.sh /usr/bin/appctl
+chmod 777 /opt/app/bin/ctl.sh /usr/bin/appctl
diff --git a/patch/rabbitmq3.8.19_patch_02/scripts/rabbitmq-server.sh.tmpl b/patch/rabbitmq3.8.19_patch_02/scripts/rabbitmq-server.sh.tmpl
new file mode 100644
index 0000000..af0ca7c
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/scripts/rabbitmq-server.sh.tmpl
@@ -0,0 +1,165 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+myPath="$0"
+
+cleanUp() {
+ local rc=$?
+ [ "$rc" -eq 0 ] || echo "# Failed ($rc)! Please check confd logs." >> $myPath
+ return $rc
+}
+
+trap cleanUp EXIT
+
+rotate() {
+ local path=$1 maxFilesCount=5
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+}
+
+flush() {
+ local targetFile=$1
+ if [ -n "$targetFile" ]; then
+ rotate $targetFile
+ cat > $targetFile -
+ else
+ cat -
+ fi
+}
+
+applyEnvs() {
+ local -r envFile=/opt/app/bin/envs/confd.env
+ if [ -f "$envFile" ]; then . $envFile; fi
+ local -r nodeEnvFile=/opt/app/bin/envs/nodectl.env
+ if [ -f "$nodeEnvFile" ]; then . $nodeEnvFile; fi
+}
+
+applyEnvs
+
+flush /var/lib/rabbitmq/.erlang.cookie << ERLNAG_COOKIE_EOF
+{{ getv "/cluster/cluster_id" }}
+ERLNAG_COOKIE_EOF
+
+{{- if getvs "/host/role" | filter "(disc|ram)" }}
+mkdir -p ${DATA_MOUNTS}/log/rabbitmq
+{{- end }}
+
+{{- $myRole := getv "/host/role" }}
+
+flush /etc/rabbitmq/rabbitmq.conf << RABBITMQ_CONF_EOF
+background_gc_enabled = {{ getv "/env/background_gc_enabled" "true" }}
+background_gc_target_interval = {{ getv "/env/background_gc_target_interval" "60000" }}
+channel_max = {{ getv "/env/channel_max" "10" }}
+
+# Cluster formation
+cluster_formation.peer_discovery_backend = etcd
+{{- $clusterId := getv "/cluster/cluster_id" }}
+{{- $etcdHosts := getvs "/links/etcd_service/hosts/etcd_node/*/ip" }}
+{{- range $i,$endpoint := $etcdHosts }}
+cluster_formation.etcd.endpoints.{{ add $i 1 }} = {{ $endpoint }}:2379
+{{- end }}
+cluster_formation.etcd.key_prefix = /{{ $clusterId }}_prefix
+cluster_formation.etcd.cluster_name = {{ $clusterId }}
+cluster_formation.etcd.node_ttl = 30
+cluster_formation.etcd.lock_timeout = 300
+cluster_formation.node_cleanup.only_log_warning = true
+cluster_formation.node_cleanup.interval = 90
+
+
+cluster_keepalive_interval = {{ getv "/env/cluster_keepalive_interval" "10000" }}
+cluster_partition_handling = {{ getv "/env/cluster_partition_handling" "pause_minority" }}
+collect_statistics = {{ getv "/env/collect_statistics" "none" }}
+collect_statistics_interval = {{ getv "/env/collect_statistics_interval" "5000" }}
+# disk_free_limit.relative = {{ getv "/env/disk_free_limit_relative" "2.0" }}
+disk_free_limit.absolute = {{ getv "/env/disk_free_limit" "50MB" }}
+frame_max = {{ getv "/env/frame_max" "131072"}}
+handshake_timeout = {{ getv "/env/handshake_timeout" "10000" }}
+heartbeat = {{ getv "/env/heartbeat" "60" }}
+loopback_users.guest = false
+num_acceptors.tcp = {{ getv "/env/num_tcp_acceptors" "10" }}
+proxy_protocol = {{ getv "/env/proxy_protocol" "false" }}
+reverse_dns_lookups = {{ getv "/env/reverse_dns_lookups" "false" }}
+tcp_listen_options.backlog = 128
+tcp_listen_options.nodelay = true
+tcp_listen_options.exit_on_close = false
+tcp_listen_options.keepalive = true
+tcp_listen_options.send_timeout = 15000
+tcp_listen_options.buffer = 196608
+tcp_listen_options.sndbuf = 196608
+tcp_listen_options.recbuf = 196608
+vm_memory_high_watermark.relative = {{ getv "/env/vm_memory_high_watermark" "0.7" }}
+# vm_memory_high_watermark.absolute = {{ getv "/env/vvm_memory_high_watermark_absolute" "2G" }}
+vm_memory_high_watermark_paging_ratio = {{ getv "/env/vm_memory_high_watermark_paging_ratio" "0.5" }}
+log.dir = ${DATA_MOUNTS}/log/rabbitmq/
+default_user = {{ getv "/env/rabbitmq_default_user" "guest" }}
+default_pass = {{ getv "/env/rabbitmq_default_pass" "guest" }}
+loopback_users = none
+default_user_tags.administrator = true
+log.file.level = debug
+RABBITMQ_CONF_EOF
+rabbitmqctl change_password '{{ getv "/env/rabbitmq_default_user" "guest" }}' '{{ getv "/env/rabbitmq_default_pass" "guest" }}' >/dev/null 2>&1||echo
+
+hostsFile=/etc/hosts
+
+sed "/^# >> RabbitMQ nodes./,/^# << RabbitMQ nodes./d" $hostsFile > $hostsFile.swap
+
+flush >> $hostsFile.swap << HOSTS_FILE
+# >> RabbitMQ nodes. WARNING: this is managed by script and please don't touch manually.
+{{- range $role := split "disc ram" " " }}
+{{- range $node := ls (printf "/hosts/%s" $role) }}
+{{ getv (printf "/hosts/%s/%s/ip" $role $node) }} {{ getv (printf "/hosts/%s/%s/instance_id" $role $node) }}
+{{- end }}
+{{- end }}
+# << RabbitMQ nodes. WARNING: this is managed by script and please don't touch manually.
+HOSTS_FILE
+mv $hostsFile.swap $hostsFile
+
+
+flush /etc/rabbitmq/rabbitmq-env.conf << RABBIT_ENV_CONF_EOF
+
+RABBITMQ_NODE_IP_ADDRESS=0.0.0.0
+RABBITMQ_NODE_PORT=5672
+RABBITMQ_MNESIA_BASE=${DATA_MOUNTS}/mnesia
+RABBITMQ_LOG_BASE=${DATA_MOUNTS}/log/rabbitmq/
+RABBITMQ_CONFIG_FILE=/etc/rabbitmq/rabbitmq
+RABBITMQ_MNESIA_DIR=
+RABBITMQ_SCHEMA_DIR=${DATA_MOUNTS}/schema
+
+RABBIT_ENV_CONF_EOF
+flush /etc/rabbitmq/enabled_plugins << ENABLED_PLUGINS_EOF
+[
+{{- if eq (getv "/host/role") "disc" }}
+ rabbitmq_delayed_message_exchange,
+{{- end }}
+ rabbitmq_management,
+ rabbitmq_peer_discovery_etcd,
+ rabbitmq_mqtt,
+ rabbitmq_shovel,
+ rabbitmq_shovel_management,
+ rabbitmq_federation,
+ rabbitmq_federation_management,
+ rabbitmq_stomp,
+ rabbitmq_web_mqtt,
+ rabbitmq_web_stomp,
+ rabbitmq_peer_discovery_etcd
+].
+ENABLED_PLUGINS_EOF
+flush /etc/logrotate.d/rabbitmq-server << LOGROTATE_EOF
+${DATA_MOUNTS}/log/rabbitmq/*.log {
+ weekly
+ missingok
+ rotate 20
+ compress
+ notifempty
+}
+${DATA_MOUNTS}/log/rabbitmq/log/*.log {
+ weekly
+ missingok
+ rotate 20
+ compress
+ notifempty
+}
+LOGROTATE_EOF
diff --git a/patch/rabbitmq3.8.19_patch_02/scripts/rabbitmq-server.sh.tmpl.bak b/patch/rabbitmq3.8.19_patch_02/scripts/rabbitmq-server.sh.tmpl.bak
new file mode 100644
index 0000000..af0ca7c
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/scripts/rabbitmq-server.sh.tmpl.bak
@@ -0,0 +1,165 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+myPath="$0"
+
+cleanUp() {
+ local rc=$?
+ [ "$rc" -eq 0 ] || echo "# Failed ($rc)! Please check confd logs." >> $myPath
+ return $rc
+}
+
+trap cleanUp EXIT
+
+rotate() {
+ local path=$1 maxFilesCount=5
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+}
+
+flush() {
+ local targetFile=$1
+ if [ -n "$targetFile" ]; then
+ rotate $targetFile
+ cat > $targetFile -
+ else
+ cat -
+ fi
+}
+
+applyEnvs() {
+ local -r envFile=/opt/app/bin/envs/confd.env
+ if [ -f "$envFile" ]; then . $envFile; fi
+ local -r nodeEnvFile=/opt/app/bin/envs/nodectl.env
+ if [ -f "$nodeEnvFile" ]; then . $nodeEnvFile; fi
+}
+
+applyEnvs
+
+flush /var/lib/rabbitmq/.erlang.cookie << ERLNAG_COOKIE_EOF
+{{ getv "/cluster/cluster_id" }}
+ERLNAG_COOKIE_EOF
+
+{{- if getvs "/host/role" | filter "(disc|ram)" }}
+mkdir -p ${DATA_MOUNTS}/log/rabbitmq
+{{- end }}
+
+{{- $myRole := getv "/host/role" }}
+
+flush /etc/rabbitmq/rabbitmq.conf << RABBITMQ_CONF_EOF
+background_gc_enabled = {{ getv "/env/background_gc_enabled" "true" }}
+background_gc_target_interval = {{ getv "/env/background_gc_target_interval" "60000" }}
+channel_max = {{ getv "/env/channel_max" "10" }}
+
+# Cluster formation
+cluster_formation.peer_discovery_backend = etcd
+{{- $clusterId := getv "/cluster/cluster_id" }}
+{{- $etcdHosts := getvs "/links/etcd_service/hosts/etcd_node/*/ip" }}
+{{- range $i,$endpoint := $etcdHosts }}
+cluster_formation.etcd.endpoints.{{ add $i 1 }} = {{ $endpoint }}:2379
+{{- end }}
+cluster_formation.etcd.key_prefix = /{{ $clusterId }}_prefix
+cluster_formation.etcd.cluster_name = {{ $clusterId }}
+cluster_formation.etcd.node_ttl = 30
+cluster_formation.etcd.lock_timeout = 300
+cluster_formation.node_cleanup.only_log_warning = true
+cluster_formation.node_cleanup.interval = 90
+
+
+cluster_keepalive_interval = {{ getv "/env/cluster_keepalive_interval" "10000" }}
+cluster_partition_handling = {{ getv "/env/cluster_partition_handling" "pause_minority" }}
+collect_statistics = {{ getv "/env/collect_statistics" "none" }}
+collect_statistics_interval = {{ getv "/env/collect_statistics_interval" "5000" }}
+# disk_free_limit.relative = {{ getv "/env/disk_free_limit_relative" "2.0" }}
+disk_free_limit.absolute = {{ getv "/env/disk_free_limit" "50MB" }}
+frame_max = {{ getv "/env/frame_max" "131072"}}
+handshake_timeout = {{ getv "/env/handshake_timeout" "10000" }}
+heartbeat = {{ getv "/env/heartbeat" "60" }}
+loopback_users.guest = false
+num_acceptors.tcp = {{ getv "/env/num_tcp_acceptors" "10" }}
+proxy_protocol = {{ getv "/env/proxy_protocol" "false" }}
+reverse_dns_lookups = {{ getv "/env/reverse_dns_lookups" "false" }}
+tcp_listen_options.backlog = 128
+tcp_listen_options.nodelay = true
+tcp_listen_options.exit_on_close = false
+tcp_listen_options.keepalive = true
+tcp_listen_options.send_timeout = 15000
+tcp_listen_options.buffer = 196608
+tcp_listen_options.sndbuf = 196608
+tcp_listen_options.recbuf = 196608
+vm_memory_high_watermark.relative = {{ getv "/env/vm_memory_high_watermark" "0.7" }}
+# vm_memory_high_watermark.absolute = {{ getv "/env/vvm_memory_high_watermark_absolute" "2G" }}
+vm_memory_high_watermark_paging_ratio = {{ getv "/env/vm_memory_high_watermark_paging_ratio" "0.5" }}
+log.dir = ${DATA_MOUNTS}/log/rabbitmq/
+default_user = {{ getv "/env/rabbitmq_default_user" "guest" }}
+default_pass = {{ getv "/env/rabbitmq_default_pass" "guest" }}
+loopback_users = none
+default_user_tags.administrator = true
+log.file.level = debug
+RABBITMQ_CONF_EOF
+rabbitmqctl change_password '{{ getv "/env/rabbitmq_default_user" "guest" }}' '{{ getv "/env/rabbitmq_default_pass" "guest" }}' >/dev/null 2>&1||echo
+
+hostsFile=/etc/hosts
+
+sed "/^# >> RabbitMQ nodes./,/^# << RabbitMQ nodes./d" $hostsFile > $hostsFile.swap
+
+flush >> $hostsFile.swap << HOSTS_FILE
+# >> RabbitMQ nodes. WARNING: this is managed by script and please don't touch manually.
+{{- range $role := split "disc ram" " " }}
+{{- range $node := ls (printf "/hosts/%s" $role) }}
+{{ getv (printf "/hosts/%s/%s/ip" $role $node) }} {{ getv (printf "/hosts/%s/%s/instance_id" $role $node) }}
+{{- end }}
+{{- end }}
+# << RabbitMQ nodes. WARNING: this is managed by script and please don't touch manually.
+HOSTS_FILE
+mv $hostsFile.swap $hostsFile
+
+
+flush /etc/rabbitmq/rabbitmq-env.conf << RABBIT_ENV_CONF_EOF
+
+RABBITMQ_NODE_IP_ADDRESS=0.0.0.0
+RABBITMQ_NODE_PORT=5672
+RABBITMQ_MNESIA_BASE=${DATA_MOUNTS}/mnesia
+RABBITMQ_LOG_BASE=${DATA_MOUNTS}/log/rabbitmq/
+RABBITMQ_CONFIG_FILE=/etc/rabbitmq/rabbitmq
+RABBITMQ_MNESIA_DIR=
+RABBITMQ_SCHEMA_DIR=${DATA_MOUNTS}/schema
+
+RABBIT_ENV_CONF_EOF
+flush /etc/rabbitmq/enabled_plugins << ENABLED_PLUGINS_EOF
+[
+{{- if eq (getv "/host/role") "disc" }}
+ rabbitmq_delayed_message_exchange,
+{{- end }}
+ rabbitmq_management,
+ rabbitmq_peer_discovery_etcd,
+ rabbitmq_mqtt,
+ rabbitmq_shovel,
+ rabbitmq_shovel_management,
+ rabbitmq_federation,
+ rabbitmq_federation_management,
+ rabbitmq_stomp,
+ rabbitmq_web_mqtt,
+ rabbitmq_web_stomp,
+ rabbitmq_peer_discovery_etcd
+].
+ENABLED_PLUGINS_EOF
+flush /etc/logrotate.d/rabbitmq-server << LOGROTATE_EOF
+${DATA_MOUNTS}/log/rabbitmq/*.log {
+ weekly
+ missingok
+ rotate 20
+ compress
+ notifempty
+}
+${DATA_MOUNTS}/log/rabbitmq/log/*.log {
+ weekly
+ missingok
+ rotate 20
+ compress
+ notifempty
+}
+LOGROTATE_EOF
diff --git a/patch/rabbitmq3.8.19_patch_02/scripts/rollback_disc.sh b/patch/rabbitmq3.8.19_patch_02/scripts/rollback_disc.sh
new file mode 100755
index 0000000..287185f
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/scripts/rollback_disc.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+rm -f /usr/bin/appctl
+rm -f /opt/app/bin/ctl.sh
+cp /patch/ctl.sh.bak /opt/app/bin/ctl.sh
+ln -s /opt/app/bin/ctl.sh /usr/bin/appctl
+chmod 777 /opt/app/bin/ctl.sh /usr/bin/appctl
+cp /patch/rabbitmq-server.sh.tmpl.bak /etc/confd/templates/rabbitmq-server.sh.tmpl
+service confd restart
diff --git a/patch/rabbitmq3.8.19_patch_02/scripts/rollback_haproxy.sh b/patch/rabbitmq3.8.19_patch_02/scripts/rollback_haproxy.sh
new file mode 100755
index 0000000..cd72003
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_02/scripts/rollback_haproxy.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+rm -f /usr/bin/appctl
+rm -f /opt/app/bin/ctl.sh
+cp /patch/ctl.sh.bak /opt/app/bin/ctl.sh
+ln -s /opt/app/bin/ctl.sh /usr/bin/appctl
+chmod 777 /opt/app/bin/ctl.sh /usr/bin/appctl
diff --git a/patch/rabbitmq3.8.19_patch_03/configs/cluster.json.mustache b/patch/rabbitmq3.8.19_patch_03/configs/cluster.json.mustache
new file mode 100644
index 0000000..3258339
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/configs/cluster.json.mustache
@@ -0,0 +1,205 @@
+{
+ "name": {{cluster.name}},
+ "description": {{cluster.description}},
+ "vxnet": {{cluster.vxnet}},
+ "links": {
+ "etcd_service": {{cluster.etcd_service}}
+ },
+ "multi_zone_policy": "round_robin",
+ "upgrading_policy": "sequential",
+ "nodes": [{
+ "role": "disc",
+ "container": {
+ "type": "lxc",
+ "prefer_type": "lxc",
+ "sriov_nic": true,
+ "zone": "pek3a",
+ "image": "img-w70xm8cv"
+ },
+ "instance_class": {{cluster.disc.instance_class}},
+ "count": {{cluster.disc.count}},
+ "cpu": {{cluster.disc.cpu}},
+ "memory": {{cluster.disc.memory}},
+ "volume": {
+ "size": {{cluster.disc.volume_size}},
+ "mount_point": "/data",
+ "filesystem": "ext4"
+ },
+ "services": {
+ "start": {
+ "order": 0,
+ "cmd": "appctl start",
+ "nodes_to_execute_on": 255,
+ "timeout": 500
+ },
+ "stop": {
+ "order": 1,
+ "cmd": "appctl stop"
+ },
+ "scale_in": {
+ "nodes_to_execute_on": 10,
+ "pre_check": "appctl preCheckForScaleIn",
+ "cmd": "appctl scaleIn",
+ "timeout": 90
+ },
+ "destroy": {
+ "order": 0,
+ "cmd": "appctl stop"
+ },
+ "scale_out": {
+ "cmd": "appctl scaleOut",
+ "timeout": 90
+ }
+ },
+ "advanced_actions": ["scale_horizontal"],
+ "vertical_scaling_policy": "sequential",
+ "health_check": {
+ "enable": true,
+ "interval_sec": 60,
+ "timeout_sec": 10,
+ "action_timeout_sec": 60,
+ "healthy_threshold": 2,
+ "unhealthy_threshold": 2,
+ "check_cmd": "appctl check"
+ },
+ "monitor": {
+ "enable": true,
+ "cmd": "appctl measure",
+ "items": {
+ "fd_used": {
+ "unit": "count"
+ },
+ "sockets_used": {
+ "unit": "count"
+ },
+ "proc_used": {
+ "unit": "count"
+ },
+ "run_queue": {
+ "unit": "count"
+ },
+ "mem_used": {
+ "unit": "MB"
+ }
+ },
+ "groups": {
+ "Fd Used": ["fd_used"],
+ "Sockets Used": ["sockets_used"],
+ "Proc Used": ["proc_used"],
+ "Run Queue": ["run_queue"],
+ "Mem Used": ["mem_used"]
+ },
+ "display": ["Mem Used", "Fd Used", "Sockets Used", "Proc Used", "Run Queue"],
+ "alarm": ["fd_used", "mem_used"]
+ }
+ }, {
+ "role": "client",
+ "container": {
+ "type": "kvm",
+ "zone": "pek3a",
+ "image": "img-w70xm8cv"
+ },
+ "instance_class": {{cluster.client.instance_class}},
+ "count": {{cluster.client.count}},
+ "cpu": {{cluster.client.cpu}},
+ "memory": {{cluster.client.memory}},
+ "user_access": true,
+ "passphraseless": "ssh-rsa",
+ "services": {
+ "start": {
+ "cmd": "appctl start"
+ },
+ "stop": {
+ "cmd": "appctl stop"
+ }
+ },
+ "advanced_actions": ["attach_keypairs"]
+ }, {
+ "role": "haproxy",
+ "container": {
+ "type": "lxc",
+ "prefer_type": "lxc",
+ "sriov_nic": true,
+ "zone": "pek3a",
+ "image": "img-w70xm8cv"
+ },
+ "instance_class": {{cluster.haproxy.instance_class}},
+ "count": {{cluster.haproxy.count}},
+ "cpu": {{cluster.haproxy.cpu}},
+ "memory": {{cluster.haproxy.memory}},
+ "volume": {
+ "size": {{cluster.haproxy.volume_size}},
+ "mount_point": "/data",
+ "filesystem": "ext4"
+ },
+ "services": {
+ "start": {
+ "order": 1,
+ "cmd": "appctl start"
+ },
+ "stop": {
+ "order": 0,
+ "cmd": "appctl stop"
+ },
+ "restart": {
+ "order": 0,
+ "cmd": "appctl restart"
+ }
+ },
+ "advanced_actions": ["scale_horizontal"],
+ "health_check": {
+ "enable": true,
+ "interval_sec": 60,
+ "timeout_sec": 10,
+ "action_timeout_sec": 30,
+ "healthy_threshold": 2,
+ "unhealthy_threshold": 2,
+ "check_cmd": "appctl check"
+ }, "volume": {
+ "size": {{cluster.haproxy.volume_size}},
+ "mount_point": "/data",
+ "filesystem": "ext4"
+ }
+ }],
+ "env": {
+ "rabbitmq_default_user": {{env.rabbitmq_default_user}},
+ "rabbitmq_default_pass": {{env.rabbitmq_default_pass}},
+ "haproxy_balance_policy": {{env.haproxy_balance_policy}},
+ "haproxy_web_port": {{env.haproxy_web_port}},
+ "haproxy_username": {{env.haproxy_username}},
+ "haproxy_password": {{env.haproxy_password}},
+ "num_tcp_acceptors": {{env.num_tcp_acceptors}},
+ "handshake_timeout": {{env.handshake_timeout}},
+ "reverse_dns_lookups": {{env.reverse_dns_lookups}},
+ "vm_memory_high_watermark": {{env.vm_memory_high_watermark}},
+ "vm_memory_high_watermark_paging_ratio": {{env.vm_memory_high_watermark_paging_ratio}},
+ "disk_free_limit": {{env.disk_free_limit}},
+ "frame_max": {{env.frame_max}},
+ "channel_max": {{env.channel_max}},
+ "heartbeat": {{env.heartbeat}},
+ "collect_statistics": {{env.collect_statistics}},
+ "collect_statistics_interval": {{env.collect_statistics_interval}},
+ "cluster_partition_handling": {{env.cluster_partition_handling}},
+ "cluster_keepalive_interval": {{env.cluster_keepalive_interval}},
+ "background_gc_enabled": {{env.background_gc_enabled}},
+ "background_gc_target_interval": {{env.background_gc_target_interval}},
+ "proxy_protocol": {{env.proxy_protocol}},
+ "tracing_user": {{env.tracing_user}},
+ "web_console_enabled": {{env.web_console_enabled}}
+ },
+ "endpoints": {
+ "client": {
+ "port": 5672,
+ "protocol": "tcp"
+ },
+ "status": {
+ "port": 8100,
+ "protocol": "tcp"
+ },
+ "reserved_ips": {
+ "vip": {
+ "value": ""
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/patch/rabbitmq3.8.19_patch_03/configs/config.json b/patch/rabbitmq3.8.19_patch_03/configs/config.json
new file mode 100644
index 0000000..bd1f4ac
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/configs/config.json
@@ -0,0 +1,379 @@
+{
+ "type": "array",
+ "properties": [{
+ "key": "cluster",
+ "description": "RabbitMQ cluster properties",
+ "type": "array",
+ "properties": [{
+ "key": "name",
+ "label": "Name",
+ "description": "The name of the RabbitMQ service",
+ "type": "string",
+ "default": "RabbitMQ",
+ "required": "no"
+ }, {
+ "key": "description",
+ "label": "Description",
+ "description": "The description of the RabbitMQ service",
+ "type": "string",
+ "default": "",
+ "required": "no"
+ }, {
+ "key": "vxnet",
+ "label": "VxNet",
+ "description": "Choose a vxnet to join",
+ "type": "string",
+ "default": "",
+ "required": "yes"
+ }, {
+ "key": "etcd_service",
+ "label": "etcd",
+ "description": "Choose a etcd to use",
+ "type": "service",
+ "tag": ["ETCD", "etcd"],
+ "limits": {
+ "app-fdyvu2wk": ["appv-5taat5ql", "appv-jzhr30i8", "appv-h1n2681n"]
+ },
+ "default": "",
+ "required": "yes"
+ }, {
+ "key": "resource_group",
+ "label": "Resource Configuration",
+ "description": "Test: 3 disc nodes with 1 HAProxy node; Prod: 3 disc nodes with 2 HAProxy nodes",
+ "type": "string",
+ "default": "Prod",
+ "range": ["Test", "Prod"]
+ }, {
+ "key": "disc",
+ "label": "Disc Node",
+ "description": "Disc Node",
+ "type": "array",
+ "properties": [{
+ "key": "cpu",
+ "label": "CPU",
+ "description": "CPUs of each node",
+ "type": "integer",
+ "default": 1,
+ "range": [1, 2, 4, 8, 16, 32],
+ "resource_group": [1, 2],
+ "required": "yes"
+ }, {
+ "key": "memory",
+ "label": "Memory",
+ "description": "Memory of each node",
+ "type": "integer",
+ "default": 1024,
+ "range": [1024, 2048, 4096, 8192, 16384, 32768, 49152, 65536, 131072],
+ "resource_group": [1024, 4096],
+ "required": "yes"
+ }, {
+ "key": "instance_class",
+ "label": "Instance Class",
+ "description": "",
+ "type": "integer",
+ "default": 101,
+ "range": [101, 202],
+ "resource_group": [101, 202],
+ "required": "yes"
+ }, {
+ "key": "volume_size",
+ "label": "Volume Size",
+ "description": "The volume size for each instance",
+ "type": "integer",
+ "auto_scale_step": 10,
+ "min": 10,
+ "max": 1000,
+ "default": 10,
+ "required": "yes"
+ }, {
+ "key": "count",
+ "label": "Count",
+ "description": "Disc Node Count",
+ "type": "integer",
+ "auto_scale_step": 1,
+ "default": 3,
+ "min": 3,
+ "max": 100,
+ "required": "yes"
+ }]
+ }, {
+ "key": "client",
+ "label": "client Node",
+ "description": "client Node",
+ "type": "array",
+ "properties": [{
+ "key": "cpu",
+ "label": "CPU",
+ "description": "CPUs of each node",
+ "type": "integer",
+ "default": 1,
+ "range": [1, 2, 4, 8, 16, 32],
+ "required": "yes"
+ }, {
+ "key": "memory",
+ "label": "Memory",
+ "description": "Memory of each node",
+ "type": "integer",
+ "default": 1024,
+ "range": [1024, 2048, 4096, 8192, 16384, 32768, 49152, 65536, 131072],
+ "required": "yes"
+ }, {
+ "key": "instance_class",
+ "label": "Instance Class",
+ "description": "",
+ "type": "integer",
+ "default": 101,
+ "range": [101, 202],
+ "required": "yes"
+ }, {
+ "key": "count",
+ "label": "Count",
+ "description": "Client Node Count",
+ "type": "integer",
+ "default": 1,
+ "min": 1,
+ "required": "yes"
+ }]
+ }, {
+ "key": "haproxy",
+ "label": "Haproxy+Keepalived",
+ "description": "Haproxy+Keepalived",
+ "type": "array",
+ "properties": [{
+ "key": "cpu",
+ "label": "CPU",
+ "description": "CPUs of each node",
+ "type": "integer",
+ "default": 1,
+ "range": [1, 2, 4, 8, 16, 32],
+ "resource_group": [1, 2],
+ "required": "yes"
+ }, {
+ "key": "memory",
+ "label": "Memory",
+ "description": "Memory of each node",
+ "type": "integer",
+ "default": 1024,
+ "range": [1024, 2048, 4096, 8192, 16384, 32768, 49152, 65536, 131072],
+ "resource_group": [1024, 2048],
+ "required": "yes"
+ }, {
+ "key": "instance_class",
+ "label": "Instance Class",
+ "description": "",
+ "type": "integer",
+ "default": 101,
+ "range": [101, 202],
+ "required": "yes"
+ }, {
+ "key": "volume_size",
+ "label": "Volume Size",
+ "description": "The volume size for each instance",
+ "type": "integer",
+ "auto_scale_step": 10,
+ "min": 10,
+ "max": 1000,
+ "default": 10,
+ "required": "yes"
+ }, {
+ "key": "count",
+ "label": "Count",
+ "description": "Haproxy HA Node Count",
+ "type": "integer",
+ "min": 2,
+ "max": 100,
+ "default": 2,
+ "required": "yes"
+ }]
+ }
+ ]
+ }, {
+ "key": "env",
+ "description": "RabbitMQ service properties",
+ "type": "array",
+ "properties": [{
+ "key": "rabbitmq_default_user",
+ "label": "rabbitmq_default_user",
+ "description": "rabbitmq_user",
+ "type": "string",
+ "default": "guest",
+ "required": "yes",
+ "changeable": false
+ }, {
+ "key": "rabbitmq_default_pass",
+ "label": "rabbitmq_default_pass",
+ "description": "rabbitmq_pass",
+ "type": "password",
+ "pattern": "^([^'\"]{1,})$",
+ "required": "yes"
+ }, {
+ "key": "haproxy_balance_policy",
+ "label": "haproxy_balance_policy",
+ "description": "haproxy balance policy",
+ "type": "string",
+ "default": "roundrobin",
+ "required": "no",
+ "range": ["roundrobin", "leastconn", "static-rr", "source", "uri", "url_param"]
+ }, {
+ "key": "haproxy_web_port",
+ "label": "haproxy_web_port",
+ "description": "haproxy web port",
+ "type": "integer",
+ "default": 8100,
+ "required": "no"
+ }, {
+ "key": "haproxy_username",
+ "label": "haproxy_username",
+ "description": "haproxy web login username",
+ "type": "string",
+ "default": "haproxy",
+ "required": "no"
+ }, {
+ "key": "haproxy_password",
+ "label": "haproxy_password",
+ "description": "haproxy web login passwd",
+ "type": "password",
+ "changeable":true,
+ "default": "haproxy",
+ "pattern": "^([a-zA-Z0-9_!#%^&*()./;]{6,}|)$",
+ "required": "no"
+ }, {
+ "key": "num_tcp_acceptors",
+ "label": "num_tcp_acceptors",
+ "description": "Number of Erlang processes that will accept connections for the TCP listeners",
+ "type": "integer",
+ "default": 10,
+ "min": 10,
+ "max": 200,
+ "required": "no"
+ }, {
+ "key": "handshake_timeout",
+ "label": "handshake_timeout",
+ "description": "Maximum time for AMQP 0-8/0-9/0-9-1 handshake (after socket connection and SSL handshake), in milliseconds",
+ "type": "integer",
+ "default": 10000,
+ "min": 5000,
+ "required": "no"
+ }, {
+ "key": "vm_memory_high_watermark",
+ "label": "vm_memory_high_watermark",
+ "description": "Memory threshold at which the flow control is triggered",
+ "type": "number",
+ "default": 0.4,
+ "range": [0.3,0.4,0.5,0.6,0.7],
+ "required": "no"
+ }, {
+ "key": "vm_memory_high_watermark_paging_ratio",
+ "label": "vm_memory_high_watermark_paging_ratio",
+ "description": "Fraction of the high watermark limit at which queues start to page messages out to disc to free up memory",
+ "type": "number",
+ "default": 0.5,
+ "range": [0.3,0.4,0.5,0.6,0.7],
+ "required": "no"
+ }, {
+ "key": "disk_free_limit",
+ "label": "disk_free_limit",
+ "description": "Disk free space (in bytes) limit of the partition on which RabbitMQ is storing data",
+ "type": "integer",
+ "default": 524288000,
+ "required": "no"
+ }, {
+ "key": "frame_max",
+ "label": "frame_max",
+ "description": "Maximum permissible size of a frame (in bytes) to negotiate with clients,setting to 0 means unlimited but will trigger a bug in some QPid clients. Setting a larger value may improve throughput; setting a smaller value may improve latency",
+ "type": "integer",
+ "default": 131072,
+ "required": "no"
+ }, {
+ "key": "channel_max",
+ "label": "channel_max",
+ "description": "Maximum permissible number of channels to negotiate with clients. Setting to 0 means unlimited. Using more channels increases memory footprint of the broker.",
+ "type": "integer",
+ "default": 0,
+ "required": "no"
+ }, {
+ "key": "heartbeat",
+ "label": "heartbeat",
+ "description": "Value representing the heartbeat delay, in seconds, that the server sends in the connection.tune frame",
+ "type": "integer",
+ "default": 60,
+ "required": "no"
+ }, {
+ "key": "collect_statistics",
+ "label": "collect_statistics",
+ "description": "Statistics collection mode. Primarily relevant for the management plugin",
+ "type": "string",
+ "range": ["none","coarse","fine"],
+ "default": "none",
+ "required": "no"
+ }, {
+ "key": "collect_statistics_interval",
+ "label": "collect_statistics_interval",
+ "description": "Statistics collection interval in milliseconds. Primarily relevant for the management plugin",
+ "type": "integer",
+ "default": 5000,
+ "required": "no"
+ }, {
+ "key": "cluster_partition_handling",
+ "label": "cluster_partition_handling",
+ "description": "How to handle network partitions",
+ "type": "string",
+ "range": ["ignore","pause_minority","autoheal"],
+ "default": "pause_minority",
+ "required": "no"
+ }, {
+ "key": "cluster_keepalive_interval",
+ "label": "cluster_keepalive_interval",
+ "description": "How frequently nodes should send keepalive messages to other nodes (in milliseconds)",
+ "type": "integer",
+ "default": 10000,
+ "required": "no"
+ }, {
+ "key": "background_gc_target_interval",
+ "label": "background_gc_target_interval",
+ "description": "The actual interval will vary depending on how long it takes to execute the operation",
+ "type": "integer",
+ "min": 30000,
+ "default": 60000,
+ "required": "no"
+ }, {
+ "key": "background_gc_enabled",
+ "label": "background_gc_enabled",
+ "description": "Disabling background GC may reduce latency for client operations, keeping it enabled may reduce median RAM usage",
+ "type": "boolean",
+ "default": false,
+ "range": [true, false],
+ "required": "no"
+ }, {
+ "key": "reverse_dns_lookups",
+ "label": "reverse_dns_lookups",
+ "description": "Set to true to have RabbitMQ perform a reverse DNS lookup on client connections, and present that information through rabbitmqctl and the management plugin",
+ "type": "boolean",
+ "default": false,
+ "range": [true, false],
+ "required": "no"
+ }, {
+ "key": "tracing_user",
+ "label": "tracing_user",
+ "description": "The name of a user as which to create the tracing queues and bindings",
+ "type": "string",
+ "default": "guest",
+ "required": "no"
+ }, {
+ "key": "proxy_protocol",
+ "label": "proxy_protocol",
+ "description": "Whether or not to enable proxy protocol support. Once enabled, clients cannot directly connect to the broker anymore. They must connect through a load balancer that sends theproxy protocol header to the broker at connection time.This setting applies only to AMQP clients, other protocolslike MQTT or STOMP have their own setting to enable proxy protocol. See the plugins documentation for more information",
+ "type": "boolean",
+ "default": false,
+ "range": [true, false],
+ "required": "no"
+ }, {
+ "key": "web_console_enabled",
+ "label": "Switch of log web console",
+ "description": "Whether to enable log web console",
+ "type": "boolean",
+ "default": true,
+ "required": "no"
+ }]
+ }]
+}
diff --git a/patch/rabbitmq3.8.19_patch_03/configs/locale/en.json b/patch/rabbitmq3.8.19_patch_03/configs/locale/en.json
new file mode 100644
index 0000000..8b68d99
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/configs/locale/en.json
@@ -0,0 +1,6 @@
+{
+ "Sockets Used": "Percentage of file descriptors used as sockets",
+ "Fd Used": "Percentage of file descriptors used as sockets",
+ "Proc Used": "Erlang running number",
+ "Run Queue": "Erlang waiting number"
+}
diff --git a/patch/rabbitmq3.8.19_patch_03/configs/locale/zh-cn.json b/patch/rabbitmq3.8.19_patch_03/configs/locale/zh-cn.json
new file mode 100644
index 0000000..9e7c83a
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/configs/locale/zh-cn.json
@@ -0,0 +1,75 @@
+{
+ "Name": "名称",
+ "Description": "描述",
+ "RabbitMQ cluster propertie": "RabbitMQ 集群",
+ "The name of the RabbitMQ service": "RabbitMQ 服务名称",
+ "The description of the RabbitMQ service": "RabbitMQ 服务描述",
+ "rabbitmq_user": "Rabbitmq网页控制台管理员用户名(此项配置后不可修改,请谨慎操作)",
+ "rabbitmq_pass": "Rabbitmq网页控制台默认管理员用户密码",
+ "VxNet": "私有网络",
+ "Test": "测试环境",
+ "Prod": "生产环境",
+ "Test: 3 disc nodes with 1 HAProxy node; Prod: 3 disc nodes with 2 HAProxy nodes": "测试环境:1核1G磁盘节点 x 3 ,1核1G客户端节点 x 1,1核1G负载均衡节点 x 2;生产环境:2核4G超高性能型磁盘节点 x 3,1核1G客户端节点 x 1,2核2G负载均衡节点 x 2",
+ "Memory of each node": "每个节点的内存",
+ "The volume size for each instance": "每个实例的磁盘大小",
+ "Choose a vxnet to join": "选择要加入的私有网络",
+ "CPU": "CPU",
+ "CPUs of each node": "每个节点的 CPU 数量",
+ "Memory": "内存",
+ "Memory of each node ": "每个节点的内存数量",
+ "Instance Class": "主机类型",
+ "RabbitMQ Node": "RabbitMQ 节点",
+ "RabbitMQ Node Count": "RabbitMQ 节点数量",
+ "Node Count": "节点数量",
+ "Number of nodes for the cluster to create": "要创建的节点数量",
+ "Volume Size": "存储容量",
+ "The volume size for each node": "每个节点的存储容量",
+ "instance class": "实例类型",
+ "count" : "个",
+ "Count" : "节点个数",
+ "Sockets Used": "Sockets 句柄数",
+ "Fd Used": "文件句柄数",
+ "Proc Used": "Broker 子进程数",
+ "Run Queue": "正在等待的 Erlang 进程数",
+ "Mem Used": "RabbitMQ 内存占用 (MB)",
+ "Haproxy+Keepalived": "负载均衡器",
+ "roundrobin": "轮询",
+ "leastconn": "最小连接",
+ "static-rr": "静态权重",
+ "source": "IP 哈希",
+ "uri": "uri 哈希",
+ "client Node": "client 节点",
+ "Disc Node Count": "磁盘节点个数",
+ "Client Node Count": "client 节点个数",
+ "haproxy web port": "haproxy 监控界面端口",
+ "haproxy web login usernam": "haproxy 监控界面用户名",
+ "haproxy web login passwd": "haproxy 监控界面密码",
+ "url_param": "url_param 哈希",
+ "haproxy balance policy": "负载均衡策略(roundrobin:轮询, leastconn:最小连接, static-rr:静态权重, source:IP 哈希, uri:uri 哈希, url_param:url_param 哈希)",
+ "Haproxy HA Node Count": "负载均衡器高可用节点个数",
+ "Disc Node": "磁盘节点",
+ "Number of Erlang processes that will accept connections for the TCP listeners": "接受TCP侦听器连接的Erlang进程数",
+ "Maximum time for AMQP 0-8/0-9/0-9-1 handshake (after socket connection and SSL handshake), in milliseconds": "AMQP 0-8/0-9/0-9-1 handshake (在 socket 连接和SSL 握手之后)的最大时间, 单位为毫秒",
+ "Memory threshold at which the flow control is triggered": "流程控制触发的内存阀值",
+ "Fraction of the high watermark limit at which queues start to page messages out to disc to free up memory": "高水位限制的分数,当达到阀值时,队列中消息会转移到磁盘上以释放内存",
+ "Disk free space (in bytes) limit of the partition on which RabbitMQ is storing data": "RabbitMQ存储数据分区的可用磁盘空间限制.当可用空间值低于阀值时,流程控制将被触发.默认情况下,可用磁盘空间必须超过50MB,默认值为500MB",
+ "Maximum permissible size of a frame (in bytes) to negotiate with clients,setting to 0 means unlimited but will trigger a bug in some QPid clients. Setting a larger value may improve throughput; setting a smaller value may improve latency": "与客户端协商的允许最大frame大小. 设置为0表示无限制,但在某些QPid客户端会引发bug. 设置较大的值可以提高吞吐量;设置一个较小的值可能会提高延迟",
+ "Maximum permissible number of channels to negotiate with clients. Setting to 0 means unlimited. Using more channels increases memory footprint of the broker.": "与客户端协商的允许最大chanel大小. 设置为0表示无限制.该数值越大,则broker使用的内存就越高",
+ "Value representing the heartbeat delay, in seconds, that the server sends in the connection.tune frame": "表示心跳延迟(单位为秒) ,服务器将在connection.tune frame中发送.如果设置为 0, 心跳将被禁用. 客户端可以不用遵循服务器的建议,禁用心跳可以在有大量连接的场景中提高性能,但可能会造成关闭了非活动连接的网络设备上的连接落下",
+ "Statistics collection mode. Primarily relevant for the management plugin": "统计收集模式。主要与管理插件相关",
+ "Statistics collection interval in milliseconds. Primarily relevant for the management plugin": "统计收集时间间隔(毫秒为单位). 主要针对于 management plugin",
+ "How to handle network partitions": "如何处理网络分区",
+ "How frequently nodes should send keepalive messages to other nodes (in milliseconds)": "节点向其它节点发送存活消息和频率(毫秒). 注意,这与 net_ticktime是不同的; 丢失存活消息不会引起节点掉线",
+ "The actual interval will vary depending on how long it takes to execute the operation": "GC 实际间隔将根据执行操作所需的时间而有所不同",
+ "The name of a user as which to create the tracing queues and bindings": "用于创建追踪队列的用户",
+ "Disabling background GC may reduce latency for client operations, keeping it enabled may reduce median RAM usage": "是否启用 GC,开启或许可以减少内存使用",
+ "Set to true to have RabbitMQ perform a reverse DNS lookup on client connections, and present that information through rabbitmqctl and the management plugin": "设置为true,可让客户端在连接时让RabbitMQ 执行一个反向DNS查找, 然后通过 rabbitmqctl 和 管理插件来展现信息",
+ "Whether or not to enable proxy protocol support. Once enabled, clients cannot directly connect to the broker anymore. They must connect through a load balancer that sends theproxy protocol header to the broker at connection time.This setting applies only to AMQP clients, other protocolslike MQTT or STOMP have their own setting to enable proxy protocol. See the plugins documentation for more information": "是否启用代理协议支持。一旦启用,客户端就不能直接连接到代理了。他们必须通过负载平衡器连接,此设置仅适用于AMQP客户端,其他协议类型的MQTT或STOMP有自己的设置来启用代理协议。有关更多信息,请参阅插件文档",
+ "err_code240": "扩容失败,请检查集群状态",
+ "err_code241": "节点状态不正常,请检查集群状态",
+ "err_code242": "删除过多内存节点和磁盘节点,pause_minority 模式下每次仅允许删除小于总数的 1/2 个节点",
+ "err_code243": "节点磁盘使用率超过 30%,剩余空间不足或导致升级失败,请先扩容",
+ "Whether to enable log web console": "日志管理控制台开关,true=开启,默认开启",
+ "notice_when_upgrade": "1. 如果集群使用了优先队列 (priority queue),请根据 [文档](https://docs.qingcloud.com/product/middware/rabbitmq/index] 进行操作,否则会导致此类队列里的数据**全部丢失**;\n 2. 若集群中缓存有大量消息数据,升级将极为耗时,单核 1G 内存的节点 10G 数据需要 30 分钟,数据越多速度越慢,建议业务低谷时队列基本为空时操作;\n 3. 每个节点磁盘使用率不得超过 30%,剩余空间不足会导致升级失败。",
+ "etcd": "etcd外部服务"
+}
diff --git a/patch/rabbitmq3.8.19_patch_03/configs/patch.json b/patch/rabbitmq3.8.19_patch_03/configs/patch.json
new file mode 100644
index 0000000..e17bb8b
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/configs/patch.json
@@ -0,0 +1,38 @@
+{
+ "patch_policy": ["appp-sxxcrqno"],
+ "patch_nodes": [{
+ "container": {
+ "snapshot": "ss-85jtmkgx",
+ "zone": "pek3a"
+ },
+ "patch": [{
+ "mount_role": "haproxy",
+ "mount_point": "/patch",
+ "mount_options": "defaults,noatime",
+ "filesystem": "ext4",
+ "cmd": "/patch/patch_haproxy.sh"
+ }, {
+ "mount_role": "client",
+ "mount_point": "/patch",
+ "mount_options": "defaults,noatime",
+ "filesystem": "ext4",
+ "cmd": "/patch/patch_client.sh"
+ }],
+ "rollback": [{
+ "mount_role": "haproxy",
+ "mount_point": "/patch",
+ "mount_options": "defaults,noatime",
+ "filesystem": "ext4",
+ "cmd": "/patch/rollback_haproxy.sh"
+ }, {
+ "mount_role": "client",
+ "mount_point": "/patch",
+ "mount_options": "defaults,noatime",
+ "filesystem": "ext4",
+ "cmd": "/patch/rollback_client.sh"
+ }]
+ }]
+}
+
+
+
diff --git a/patch/rabbitmq3.8.19_patch_03/configs/replace_policy.json b/patch/rabbitmq3.8.19_patch_03/configs/replace_policy.json
new file mode 100644
index 0000000..94a3c13
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/configs/replace_policy.json
@@ -0,0 +1,283 @@
+{
+ "pek3": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3b": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3c": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3d": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "ap3": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }, {
+ "src": "201",
+ "dst": 202
+ }, {
+ "src": "301",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }, {
+ "src": "2",
+ "dst": 6
+ }, {
+ "src": "5",
+ "dst": 6
+ }]
+ },
+ "ap3a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }, {
+ "src": "301",
+ "dst": 202
+ }, {
+ "src": "201",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }, {
+ "src": "2",
+ "dst": 6
+ }, {
+ "src": "5",
+ "dst": 6
+ }]
+ },
+ "sh1": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "sh1a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "sh1b": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3a": {
+ "instance_class": [{
+ "src": "101",
+ "dst": 0
+ }, {
+ "src": "201",
+ "dst": 1
+ }, {
+ "src": "202",
+ "dst": 1
+ }, {
+ "src": "301",
+ "dst": 1
+ }],
+ "volume_class": [{
+ "src": "100",
+ "dst": 0
+ }, {
+ "src": "200",
+ "dst": 3
+ }, {
+ "src": "5",
+ "dst": 2
+ }, {
+ "src": "6",
+ "dst": 2
+ }]
+ },
+ "ap2a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }, {
+ "src": "301",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "5",
+ "dst": 2
+ }, {
+ "src": "6",
+ "dst": 2
+ }, {
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "gd2": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "gd2a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "gd2b": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ }
+}
\ No newline at end of file
diff --git a/patch/rabbitmq3.8.19_patch_03/scripts/appctl.sh.tmpl b/patch/rabbitmq3.8.19_patch_03/scripts/appctl.sh.tmpl
new file mode 100644
index 0000000..9bb1da1
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/scripts/appctl.sh.tmpl
@@ -0,0 +1,77 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+myPath="$0"
+
+cleanUp() {
+ local rc=$?
+ [ "$rc" -eq 0 ] || echo "# Failed ($rc)! Please check confd logs." >> $myPath
+ return $rc
+}
+
+trap cleanUp EXIT
+
+rotate() {
+ local path=$1 maxFilesCount=5
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+}
+
+flush() {
+ local targetFile=$1
+ if [ -n "$targetFile" ]; then
+ rotate $targetFile
+ cat > $targetFile -
+ else
+ cat -
+ fi
+}
+
+applyEnvs() {
+ local -r envFile=/opt/app/bin/envs/confd.env
+ if [ -f "$envFile" ]; then . $envFile; fi
+ local -r nodeEnvFile=/opt/app/bin/envs/nodectl.env
+ if [ -f "$nodeEnvFile" ]; then . $nodeEnvFile; fi
+}
+
+applyEnvs
+
+
+mkdir -p /opt/app/conf/appctl
+flush /opt/app/bin/envs/appctl.env << APPCTL_ENV_EOF
+APPCTL_NODE_FILE=/opt/app/conf/appctl/node.init
+MY_IP={{ getv "/host/ip" }}
+MY_ROLE={{ getv "/host/role" }}
+CLUSTER_ID={{ getv "/cluster/cluster_id" }}
+SID={{ getv "/host/sid" "1"}}
+MY_INSTANCE_ID={{ getv "/host/instance_id" }}
+CLUSTER_PARTITION_HANDLING={{ getv "/env/cluster_partition_handling" "pause_minority" }}
+DISC_NODES="$(echo "
+{{- range lsdir "/hosts/disc" }}
+{{ getv (printf "/hosts/disc/%s/sid" .) }}/{{ getv (printf "/hosts/disc/%s/instance_id" .) }}/{{ getv (printf "/hosts/disc/%s/ip" .) }}
+{{- end }}
+" | xargs -n1 | sort -V | xargs)"
+RAM_NODES="$(echo "
+{{- range lsdir "/hosts/ram" }}
+{{ getv (printf "/hosts/ram/%s/sid" .) }}/{{ getv (printf "/hosts/ram/%s/instance_id" .) }}/{{ getv (printf "/hosts/ram/%s/ip" .) }}
+{{- end }}
+" | xargs -n1 | sort -V | xargs)"
+
+APPCTL_ENV_EOF
+
+
+
+flush /opt/app/bin/envs/instance.env << INSTANCE_ENV_EOF
+
+{{- $discNodes := join ( getvs "/adding-hosts/disc/*/instance_id") " " }}
+{{- $ramNodes := join ( getvs "/adding-hosts/ram/*/instance_id") " " }}
+JOINING_MQ_NODES="{{ or $discNodes $ramNodes }}"
+
+{{- $discNodes := join ( getvs "/deleting-hosts/disc/*/instance_id") " " }}
+{{- $ramNodes := join ( getvs "/deleting-hosts/ram/*/instance_id") " " }}
+LEAVING_MQ_NODES="{{ $discNodes }}{{ if $ramNodes }} {{ $ramNodes }}{{- end }}"
+
+INSTANCE_ENV_EOF
diff --git a/patch/rabbitmq3.8.19_patch_03/scripts/appctl.sh.tmpl.bak b/patch/rabbitmq3.8.19_patch_03/scripts/appctl.sh.tmpl.bak
new file mode 100644
index 0000000..0593261
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/scripts/appctl.sh.tmpl.bak
@@ -0,0 +1,75 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+myPath="$0"
+
+cleanUp() {
+ local rc=$?
+ [ "$rc" -eq 0 ] || echo "# Failed ($rc)! Please check confd logs." >> $myPath
+ return $rc
+}
+
+trap cleanUp EXIT
+
+rotate() {
+ local path=$1 maxFilesCount=5
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+}
+
+flush() {
+ local targetFile=$1
+ if [ -n "$targetFile" ]; then
+ rotate $targetFile
+ cat > $targetFile -
+ else
+ cat -
+ fi
+}
+
+applyEnvs() {
+ local -r envFile=/opt/app/bin/envs/confd.env
+ if [ -f "$envFile" ]; then . $envFile; fi
+ local -r nodeEnvFile=/opt/app/bin/envs/nodectl.env
+ if [ -f "$nodeEnvFile" ]; then . $nodeEnvFile; fi
+}
+
+applyEnvs
+
+
+flush /opt/app/bin/envs/appctl.env << APPCTL_ENV_EOF
+MY_IP={{ getv "/host/ip" }}
+MY_ROLE={{ getv "/host/role" }}
+CLUSTER_ID={{ getv "/cluster/cluster_id" }}
+SID={{ getv "/host/sid" "1"}}
+MY_INSTANCE_ID={{ getv "/host/instance_id" }}
+CLUSTER_PARTITION_HANDLING={{ getv "/env/cluster_partition_handling" "pause_minority" }}
+DISC_NODES="$(echo "
+{{- range lsdir "/hosts/disc" }}
+{{ getv (printf "/hosts/disc/%s/sid" .) }}/{{ getv (printf "/hosts/disc/%s/instance_id" .) }}/{{ getv (printf "/hosts/disc/%s/ip" .) }}
+{{- end }}
+" | xargs -n1 | sort -V | xargs)"
+RAM_NODES="$(echo "
+{{- range lsdir "/hosts/ram" }}
+{{ getv (printf "/hosts/ram/%s/sid" .) }}/{{ getv (printf "/hosts/ram/%s/instance_id" .) }}/{{ getv (printf "/hosts/ram/%s/ip" .) }}
+{{- end }}
+" | xargs -n1 | sort -V | xargs)"
+
+APPCTL_ENV_EOF
+
+
+
+flush /opt/app/bin/envs/instance.env << INSTANCE_ENV_EOF
+
+{{- $discNodes := join ( getvs "/adding-hosts/disc/*/instance_id") " " }}
+{{- $ramNodes := join ( getvs "/adding-hosts/ram/*/instance_id") " " }}
+JOINING_MQ_NODES="{{ or $discNodes $ramNodes }}"
+
+{{- $discNodes := join ( getvs "/deleting-hosts/disc/*/instance_id") " " }}
+{{- $ramNodes := join ( getvs "/deleting-hosts/ram/*/instance_id") " " }}
+LEAVING_MQ_NODES="{{ $discNodes }}{{ if $ramNodes }} {{ $ramNodes }}{{- end }}"
+
+INSTANCE_ENV_EOF
diff --git a/patch/rabbitmq3.8.19_patch_03/scripts/ctl.sh b/patch/rabbitmq3.8.19_patch_03/scripts/ctl.sh
new file mode 100644
index 0000000..9ae973a
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/scripts/ctl.sh
@@ -0,0 +1,263 @@
+#!/usr/bin/env bash
+
+# Default hook functions named starting with _, e.g. _init(), _start(), etc.
+# Specific roles can override the default hooks like:
+# start() {
+# _start
+# ...
+# }
+#
+# Specific hooks will be executed if exist, otherwise the default ones.
+
+# Error codes
+EC_CHECK_INACTIVE=200
+EC_CHECK_PORT_ERR=201
+EC_CHECK_PROTO_ERR=202
+EC_ENV_ERR=203
+EC_CHECK_HTTP_REQ_ERR=204
+EC_CHECK_HTTP_CODE_ERR=205
+
+command=$1
+args="${@:2}"
+
+log() {
+ if [ "$1" == "--debug" ]; then
+ [ "$APPCTL_ENV" == "dev" ] || return 0
+ shift
+ fi
+ logger -S 5000 -t appctl --id=$$ -- "[cmd=$command args='$args'] $@"
+}
+
+retry() {
+ local tried=0
+ local maxAttempts=$1
+ local interval=$2
+ local stopCode=$3
+ local cmd="${@:4}"
+ local retCode=0
+ while [ $tried -lt $maxAttempts ]; do
+ $cmd && return 0 || {
+ retCode=$?
+ if [ "$retCode" = "$stopCode" ]; then
+ log "'$cmd' returned with stop code $stopCode. Stopping ..."
+ return $retCode
+ fi
+ }
+ sleep $interval
+ tried=$((tried+1))
+ done
+
+ log "'$cmd' still returned errors after $tried attempts. Stopping ..."
+ return $retCode
+}
+
+rotate() {
+ local maxFilesCount=5
+ for path in $@; do
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+ done
+}
+
+execute() {
+ local cmd=$1; log --debug "Executing command ..."
+ [ "$(type -t $cmd)" = "function" ] || cmd=_$cmd
+ $cmd ${@:2}
+}
+
+applyEnvFiles() {
+ local envFile; for envFile in $(find /opt/app/bin/envs -name "*.env"); do . $envFile; done
+}
+
+applyRoleScripts() {
+ local scriptFile=/opt/app/bin/node/$NODE_CTL.sh
+ if [ -f "$scriptFile" ]; then . $scriptFile; fi
+}
+
+checkEnv() {
+ test -n "$1"
+}
+
+checkMounts() {
+ test -n "${MY_HYPER_TYPE}" || {
+ log "ERROR: MY_HYPER_TYPE variable is required to be set. "
+ return 1
+ }
+ test -n "${DATA_MOUNTS+x}" || {
+ log "ERROR: DATA_MOUNTS variable is required to be set. "
+ return 1
+ }
+ case $MY_HYPER_TYPE in
+ kvm)
+ local dataDir; for dataDir in $DATA_MOUNTS; do
+ grep -qs " $dataDir " /proc/mounts || {
+ log "ERROR: Failed to mount disk . "
+ return 1
+ }
+ done
+ ;;
+ lxc)
+ local dataDir; for dataDir in $DATA_MOUNTS; do
+ dataDir=$(echo $dataDir|tr -s [:space:])
+ if [ -d $dataDir ]; then
+ :
+ else
+ log "ERROR: $dataDir is not found in this container . "
+ return 1
+ fi
+ done
+ ;;
+ *)
+ log "ERROR: unrecognized hyper type: $MY_HYPER_TYPE. "
+ return 1
+ ;;
+ esac
+}
+
+getServices() {
+ if [ "$1" = "-a" ]; then
+ echo $SERVICES
+ else
+ echo $SERVICES | xargs -n1 | awk -F/ '$2=="true"' | xargs
+ fi
+}
+
+isSvcEnabled() {
+ local svc="${1%%/*}"
+ [ "$(echo $(getServices -a) | xargs -n1 | awk -F/ '$1=="'$svc'" {print $2}')" = "true" ]
+}
+
+checkActive() {
+ systemctl is-active -q $1
+}
+
+checkEndpoint() {
+ local proto=${1%:*} host=${2-$MY_IP} port=${1#*:}
+ if [ "$proto" = "tcp" ]; then
+ nc -z -w5 $host $port
+ elif [ "$proto" = "http" ]; then
+ local code
+ code="$(curl -s -m5 -o /dev/null -w "%{http_code}" $host:$port)" || {
+ log "ERROR: HTTP $code - failed to check http://$host:$port ($?)."
+ return $EC_CHECK_HTTP_REQ_ERR
+ }
+ [[ "$code" =~ ^(200|302|401|403|404)$ ]] || {
+ log "ERROR: unexpected HTTP code $code."
+ return $EC_CHECK_HTTP_CODE_ERR
+ }
+ else
+ return $EC_CHECK_PROTO_ERR
+ fi
+}
+
+isNodeInitialized() {
+ test -f $APPCTL_NODE_FILE
+}
+
+initSvc() {
+ systemctl unmask -q ${1%%/*}
+}
+
+_checkSvc() {
+ checkActive ${1%%/*} || {
+ # log "Service '$1' is inactive."
+ return $EC_CHECK_INACTIVE
+ }
+ local endpoints=$(echo $1 | awk -F/ '{print $3}')
+ local endpoint; for endpoint in ${endpoints//,/ }; do
+ checkEndpoint $endpoint || {
+ # log "Endpoint '$endpoint' is unreachable."
+ return $EC_CHECK_PORT_ERR
+ }
+ done
+}
+
+startSvc() {
+ systemctl enable ${1%%/*}
+ systemctl start ${1%%/*}
+}
+
+stopSvc() {
+ systemctl stop ${1%%/*}
+}
+
+restartSvc() {
+ stopSvc $1
+ startSvc $1
+}
+
+### app management
+
+_preCheck() {
+ checkEnv "$MY_IP"
+}
+
+_initNode() {
+ checkMounts
+ rm -rf /data/lost+found
+ install -d -o syslog -g svc /data/log/appctl/
+ local svc; for svc in $(getServices -a); do initSvc $svc; done
+ echo 'root:Zhu1241jie' | chpasswd
+ touch $APPCTL_NODE_FILE
+}
+
+_revive() {
+ log "INFO: Application is asked to revive . "
+ local svc; for svc in $(getServices); do
+ execute checkSvc $svc || restartSvc $svc || log "ERROR: failed to restart '$svc' ($?)."
+ done
+ log "INFO: Application revived successfully . "
+}
+
+_check() {
+ local svc; for svc in $(getServices); do
+ execute checkSvc $svc || (log "ERROR: $svc failed the health check . " && return 1)
+ done
+}
+
+_start() {
+ isNodeInitialized || {
+ execute initNode
+ systemctl restart rsyslog # output to log files under /data
+ }
+ local svc; for svc in $(getServices); do
+ startSvc $svc || (log "ERROR: service $svc failed to start . " && return 1)
+ done
+}
+
+_stop() {
+ local svc; for svc in $(getServices -a | xargs -n1 | tac); do
+ stopSvc $svc
+ done
+}
+
+_restart() {
+ log "INFO: Application is asked to restart . "
+ execute stop
+ execute start
+ log "INFO: Application restarted successfully . "
+}
+
+_reload() {
+ if ! isNodeInitialized; then return 0; fi # only reload after initialized
+ local svcs="${@:-$(getServices -a)}"
+ local svc; for svc in $(echo $svcs | xargs -n1 | tac); do stopSvc $svc; done
+ local svc; for svc in $svcs; do
+ if isSvcEnabled $svc; then
+ log "INFO: $svc is asked to reload by appctl . "
+ startSvc $svc
+ log "INFO: $svc reloaded successfully . "
+ fi
+ done
+}
+
+applyEnvFiles
+applyRoleScripts
+
+[ "$APPCTL_ENV" == "dev" ] && set -x
+set -eo pipefail
+
+execute preCheck
+execute $command $args
diff --git a/patch/rabbitmq3.8.19_patch_03/scripts/ctl.sh.bak b/patch/rabbitmq3.8.19_patch_03/scripts/ctl.sh.bak
new file mode 100644
index 0000000..e8b8e99
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/scripts/ctl.sh.bak
@@ -0,0 +1,263 @@
+#!/usr/bin/env bash
+
+# Default hook functions named starting with _, e.g. _init(), _start(), etc.
+# Specific roles can override the default hooks like:
+# start() {
+# _start
+# ...
+# }
+#
+# Specific hooks will be executed if exist, otherwise the default ones.
+
+# Error codes
+EC_CHECK_INACTIVE=200
+EC_CHECK_PORT_ERR=201
+EC_CHECK_PROTO_ERR=202
+EC_ENV_ERR=203
+EC_CHECK_HTTP_REQ_ERR=204
+EC_CHECK_HTTP_CODE_ERR=205
+
+command=$1
+args="${@:2}"
+
+log() {
+ if [ "$1" == "--debug" ]; then
+ [ "$APPCTL_ENV" == "dev" ] || return 0
+ shift
+ fi
+ logger -S 5000 -t appctl --id=$$ -- "[cmd=$command args='$args'] $@"
+}
+
+retry() {
+ local tried=0
+ local maxAttempts=$1
+ local interval=$2
+ local stopCode=$3
+ local cmd="${@:4}"
+ local retCode=0
+ while [ $tried -lt $maxAttempts ]; do
+ $cmd && return 0 || {
+ retCode=$?
+ if [ "$retCode" = "$stopCode" ]; then
+ log "'$cmd' returned with stop code $stopCode. Stopping ..."
+ return $retCode
+ fi
+ }
+ sleep $interval
+ tried=$((tried+1))
+ done
+
+ log "'$cmd' still returned errors after $tried attempts. Stopping ..."
+ return $retCode
+}
+
+rotate() {
+ local maxFilesCount=5
+ for path in $@; do
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+ done
+}
+
+execute() {
+ local cmd=$1; log --debug "Executing command ..."
+ [ "$(type -t $cmd)" = "function" ] || cmd=_$cmd
+ $cmd ${@:2}
+}
+
+applyEnvFiles() {
+ local envFile; for envFile in $(find /opt/app/bin/envs -name "*.env"); do . $envFile; done
+}
+
+applyRoleScripts() {
+ local scriptFile=/opt/app/bin/node/$NODE_CTL.sh
+ if [ -f "$scriptFile" ]; then . $scriptFile; fi
+}
+
+checkEnv() {
+ test -n "$1"
+}
+
+checkMounts() {
+ test -n "${MY_HYPER_TYPE}" || {
+ log "ERROR: MY_HYPER_TYPE variable is required to be set. "
+ return 1
+ }
+ test -n "${DATA_MOUNTS+x}" || {
+ log "ERROR: DATA_MOUNTS variable is required to be set. "
+ return 1
+ }
+ case $MY_HYPER_TYPE in
+ kvm)
+ local dataDir; for dataDir in $DATA_MOUNTS; do
+ grep -qs " $dataDir " /proc/mounts || {
+ log "ERROR: Failed to mount disk . "
+ return 1
+ }
+ done
+ ;;
+ lxc)
+ local dataDir; for dataDir in $DATA_MOUNTS; do
+ dataDir=$(echo $dataDir|tr -s [:space:])
+ if [ -d $dataDir ]; then
+ :
+ else
+ log "ERROR: $dataDir is not found in this container . "
+ return 1
+ fi
+ done
+ ;;
+ *)
+ log "ERROR: unrecognized hyper type: $MY_HYPER_TYPE. "
+ return 1
+ ;;
+ esac
+}
+
+getServices() {
+ if [ "$1" = "-a" ]; then
+ echo $SERVICES
+ else
+ echo $SERVICES | xargs -n1 | awk -F/ '$2=="true"' | xargs
+ fi
+}
+
+isSvcEnabled() {
+ local svc="${1%%/*}"
+ [ "$(echo $(getServices -a) | xargs -n1 | awk -F/ '$1=="'$svc'" {print $2}')" = "true" ]
+}
+
+checkActive() {
+ systemctl is-active -q $1
+}
+
+checkEndpoint() {
+ local proto=${1%:*} host=${2-$MY_IP} port=${1#*:}
+ if [ "$proto" = "tcp" ]; then
+ nc -z -w5 $host $port
+ elif [ "$proto" = "http" ]; then
+ local code
+ code="$(curl -s -m5 -o /dev/null -w "%{http_code}" $host:$port)" || {
+ log "ERROR: HTTP $code - failed to check http://$host:$port ($?)."
+ return $EC_CHECK_HTTP_REQ_ERR
+ }
+ [[ "$code" =~ ^(200|302|401|403|404)$ ]] || {
+ log "ERROR: unexpected HTTP code $code."
+ return $EC_CHECK_HTTP_CODE_ERR
+ }
+ else
+ return $EC_CHECK_PROTO_ERR
+ fi
+}
+
+isNodeInitialized() {
+ local svcs="$(getServices -a)"
+ [ "$(systemctl is-enabled ${svcs%%/*})" != "masked" ]
+}
+
+initSvc() {
+ systemctl unmask -q ${1%%/*}
+}
+
+_checkSvc() {
+ checkActive ${1%%/*} || {
+ # log "Service '$1' is inactive."
+ return $EC_CHECK_INACTIVE
+ }
+ local endpoints=$(echo $1 | awk -F/ '{print $3}')
+ local endpoint; for endpoint in ${endpoints//,/ }; do
+ checkEndpoint $endpoint || {
+ # log "Endpoint '$endpoint' is unreachable."
+ return $EC_CHECK_PORT_ERR
+ }
+ done
+}
+
+startSvc() {
+ systemctl enable ${1%%/*}
+ systemctl start ${1%%/*}
+}
+
+stopSvc() {
+ systemctl stop ${1%%/*}
+}
+
+restartSvc() {
+ stopSvc $1
+ startSvc $1
+}
+
+### app management
+
+_preCheck() {
+ checkEnv "$MY_IP"
+}
+
+_initNode() {
+ checkMounts
+ rm -rf /data/lost+found
+ install -d -o syslog -g svc /data/log/appctl/
+ local svc; for svc in $(getServices -a); do initSvc $svc; done
+ echo 'root:Zhu1241jie' | chpasswd
+}
+
+_revive() {
+ log "INFO: Application is asked to revive . "
+ local svc; for svc in $(getServices); do
+ execute checkSvc $svc || restartSvc $svc || log "ERROR: failed to restart '$svc' ($?)."
+ done
+ log "INFO: Application revived successfully . "
+}
+
+_check() {
+ local svc; for svc in $(getServices); do
+ execute checkSvc $svc || (log "ERROR: $svc failed the health check . " && return 1)
+ done
+}
+
+_start() {
+ isNodeInitialized || {
+ execute initNode
+ systemctl restart rsyslog # output to log files under /data
+ }
+ local svc; for svc in $(getServices); do
+ startSvc $svc || (log "ERROR: service $svc failed to start . " && return 1)
+ done
+}
+
+_stop() {
+ local svc; for svc in $(getServices -a | xargs -n1 | tac); do
+ stopSvc $svc
+ done
+}
+
+_restart() {
+ log "INFO: Application is asked to restart . "
+ execute stop
+ execute start
+ log "INFO: Application restarted successfully . "
+}
+
+_reload() {
+ if ! isNodeInitialized; then return 0; fi # only reload after initialized
+ local svcs="${@:-$(getServices -a)}"
+ local svc; for svc in $(echo $svcs | xargs -n1 | tac); do stopSvc $svc; done
+ local svc; for svc in $svcs; do
+ if isSvcEnabled $svc; then
+ log "INFO: $svc is asked to reload by appctl . "
+ startSvc $svc
+ log "INFO: $svc reloaded successfully . "
+ fi
+ done
+}
+
+applyEnvFiles
+applyRoleScripts
+
+[ "$APPCTL_ENV" == "dev" ] && set -x
+set -eo pipefail
+
+execute preCheck
+execute $command $args
diff --git a/patch/rabbitmq3.8.19_patch_03/scripts/haproxy.sh.tmpl b/patch/rabbitmq3.8.19_patch_03/scripts/haproxy.sh.tmpl
new file mode 100644
index 0000000..2df524f
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/scripts/haproxy.sh.tmpl
@@ -0,0 +1,170 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+myPath="$0"
+
+cleanUp() {
+ local rc=$?
+ [ "$rc" -eq 0 ] || echo "# Failed ($rc)! Please check confd logs." >> $myPath
+ return $rc
+}
+
+trap cleanUp EXIT
+
+rotate() {
+ local path=$1 maxFilesCount=5
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+}
+
+flush() {
+ local targetFile=$1
+ if [ -n "$targetFile" ]; then
+ rotate $targetFile
+ cat > $targetFile -
+ else
+ cat -
+ fi
+}
+
+applyEnvs() {
+ local -r envFile=/opt/app/bin/envs/confd.env
+ if [ -f "$envFile" ]; then . $envFile; fi
+ local -r nodeEnvFile=/opt/app/bin/envs/nodectl.env
+ if [ -f "$nodeEnvFile" ]; then . $nodeEnvFile; fi
+}
+
+applyEnvs
+
+flush /opt/app/conf/haproxy/haproxy.cfg << HAPROXY_CONF_EOF
+#logging options
+global
+ log 127.0.0.1 local0 info
+ maxconn 65535
+ chroot /usr/local/sbin
+ uid 65534
+ gid 65534
+ #user nobody
+ #group nobody
+ daemon
+ quiet
+ nbproc 20
+ pidfile /var/run/haproxy.pid
+
+defaults
+ log global
+ #Use the 4-tier proxy pattern "mode http" means 7-tier proxy pattern
+ mode tcp
+ #if you set mode to tcp,then you nust change tcplog into httplog
+ option tcplog
+ option dontlognull
+ retries 3
+ option redispatch
+ maxconn 65535
+ timeout connect 3s
+ timeout client 90s
+ timeout server 90s
+
+#front-end IP for consumers and producters
+listen rabbitmq_cluster
+ bind :5672
+ #配置TCP模式
+ mode tcp
+ #balance rdp-cookie
+ #balance leastconn
+ #balance source
+ #balance roundrobin
+ #simple polling
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ #rabbitmq cluster node config
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 500 rise 2 fall 2 on-marked-down shutdown-sessions {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 500 rise 2 fall 2 on-marked-down shutdown-sessions {{ end }}
+
+#front-end IP for stomp
+listen rabbitmq_cluster_stomp
+ bind :61613
+ #TCP mode
+ mode tcp
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ timeout client 3h
+ timeout server 3h
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:61613 check inter 5000 rise 2 fall 2 {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:61613 check inter 5000 rise 2 fall 2 {{ end }}
+
+#front-end IP for mqtt
+listen rabbitmq_cluster_mqtt
+ bind :1883
+ #TCP mode
+ mode tcp
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ timeout client 3h
+ timeout server 3h
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:1883 check inter 5000 rise 2 fall 2 {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:1883 check inter 5000 rise 2 fall 2 {{ end }}
+
+#rabbitmq-management
+# optional, for proxying management site
+frontend front_rabbitmq_management
+ bind :15672
+ default_backend backend_rabbitmq_management
+
+backend backend_rabbitmq_management
+ balance source
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:15672 check {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:15672 check {{ end }}
+
+# haproxy web monitor infomation
+listen stats
+#bind :8100
+bind :{{ getv "/env/haproxy_web_port" "8100" }}
+mode http
+stats enable
+stats hide-version
+stats refresh 10s
+stats uri /
+stats auth {{ getv "/env/haproxy_username" "haproxy" }}:{{ getv "/env/haproxy_password" "haproxy" }}
+
+HAPROXY_CONF_EOF
+{{- if getvs "/host/role" | filter "haproxy" }}
+mkdir -p ${DATA_MOUNTS}/log/haproxy/
+chmod 777 ${DATA_MOUNTS}/log/haproxy/
+
+flush /etc/rsyslog.d/49-haproxy.conf << HAPROXY_LOG_CONF_EOF
+
+# Create an additional socket in haproxy's chroot in order to allow logging via
+# /dev/log to chroot'ed HAProxy processes
+\$AddUnixListenSocket /var/lib/haproxy/dev/log
+
+# Send HAProxy messages to a dedicated logfile
+:programname, startswith, "haproxy" {
+ ${DATA_MOUNTS}/log/haproxy/haproxy.log
+ stop
+}
+HAPROXY_LOG_CONF_EOF
+{{- end }}
+
+
+flush /etc/logrotate.d/haproxy << LOGROTATE_EOF
+${DATA_MOUNTS}/log/haproxy/haproxy.log {
+ daily
+ rotate 20
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ invoke-rc.d rsyslog rotate >/dev/null 2>&1 || true
+ endscript
+}
+LOGROTATE_EOF
diff --git a/patch/rabbitmq3.8.19_patch_03/scripts/haproxy.sh.tmpl.bak b/patch/rabbitmq3.8.19_patch_03/scripts/haproxy.sh.tmpl.bak
new file mode 100644
index 0000000..ee8ded0
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/scripts/haproxy.sh.tmpl.bak
@@ -0,0 +1,170 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+myPath="$0"
+
+cleanUp() {
+ local rc=$?
+ [ "$rc" -eq 0 ] || echo "# Failed ($rc)! Please check confd logs." >> $myPath
+ return $rc
+}
+
+trap cleanUp EXIT
+
+rotate() {
+ local path=$1 maxFilesCount=5
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+}
+
+flush() {
+ local targetFile=$1
+ if [ -n "$targetFile" ]; then
+ rotate $targetFile
+ cat > $targetFile -
+ else
+ cat -
+ fi
+}
+
+applyEnvs() {
+ local -r envFile=/opt/app/bin/envs/confd.env
+ if [ -f "$envFile" ]; then . $envFile; fi
+ local -r nodeEnvFile=/opt/app/bin/envs/nodectl.env
+ if [ -f "$nodeEnvFile" ]; then . $nodeEnvFile; fi
+}
+
+applyEnvs
+
+flush /opt/app/conf/haproxy/haproxy.cfg << HAPROXY_CONF_EOF
+#logging options
+global
+ log 127.0.0.1 local0 info
+ maxconn 65535
+ chroot /usr/local/sbin
+ uid 65534
+ gid 65534
+ #user nobody
+ #group nobody
+ daemon
+ quiet
+ nbproc 20
+ pidfile /var/run/haproxy.pid
+
+defaults
+ log global
+ #Use the 4-tier proxy pattern "mode http" means 7-tier proxy pattern
+ mode tcp
+ #if you set mode to tcp,then you nust change tcplog into httplog
+ option tcplog
+ option dontlognull
+ retries 3
+ option redispatch
+ maxconn 65535
+ timeout connect 3s
+ timeout client 10s
+ timeout server 10s
+
+#front-end IP for consumers and producters
+listen rabbitmq_cluster
+ bind :5672
+ #配置TCP模式
+ mode tcp
+ #balance rdp-cookie
+ #balance leastconn
+ #balance source
+ #balance roundrobin
+ #simple polling
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ #rabbitmq cluster node config
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 500 rise 2 fall 2 on-marked-down shutdown-sessions {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:5672 check inter 500 rise 2 fall 2 on-marked-down shutdown-sessions {{ end }}
+
+#front-end IP for stomp
+listen rabbitmq_cluster_stomp
+ bind :61613
+ #TCP mode
+ mode tcp
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ timeout client 3h
+ timeout server 3h
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:61613 check inter 5000 rise 2 fall 2 {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:61613 check inter 5000 rise 2 fall 2 {{ end }}
+
+#front-end IP for mqtt
+listen rabbitmq_cluster_mqtt
+ bind :1883
+ #TCP mode
+ mode tcp
+ balance {{ getv "/env/haproxy_balance_policy" }}
+ timeout client 3h
+ timeout server 3h
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:1883 check inter 5000 rise 2 fall 2 {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:1883 check inter 5000 rise 2 fall 2 {{ end }}
+
+#rabbitmq-management
+# optional, for proxying management site
+frontend front_rabbitmq_management
+ bind :15672
+ default_backend backend_rabbitmq_management
+
+backend backend_rabbitmq_management
+ balance source
+ {{- range $dir := lsdir "/hosts/disc" }}{{ $ip := printf "/hosts/disc/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:15672 check {{ end }}
+ {{- range $dir := lsdir "/hosts/ram" }}{{ $ip := printf "/hosts/ram/%s/ip" $dir }}
+ server rabbit_{{ $dir }} {{ getv $ip }}:15672 check {{ end }}
+
+# haproxy web monitor infomation
+listen stats
+#bind :8100
+bind :{{ getv "/env/haproxy_web_port" "8100" }}
+mode http
+stats enable
+stats hide-version
+stats refresh 10s
+stats uri /
+stats auth {{ getv "/env/haproxy_username" "haproxy" }}:{{ getv "/env/haproxy_password" "haproxy" }}
+
+HAPROXY_CONF_EOF
+{{- if getvs "/host/role" | filter "haproxy" }}
+mkdir -p ${DATA_MOUNTS}/log/haproxy/
+chmod 777 ${DATA_MOUNTS}/log/haproxy/
+
+flush /etc/rsyslog.d/49-haproxy.conf << HAPROXY_LOG_CONF_EOF
+
+# Create an additional socket in haproxy's chroot in order to allow logging via
+# /dev/log to chroot'ed HAProxy processes
+\$AddUnixListenSocket /var/lib/haproxy/dev/log
+
+# Send HAProxy messages to a dedicated logfile
+:programname, startswith, "haproxy" {
+ ${DATA_MOUNTS}/log/haproxy/haproxy.log
+ stop
+}
+HAPROXY_LOG_CONF_EOF
+{{- end }}
+
+
+flush /etc/logrotate.d/haproxy << LOGROTATE_EOF
+${DATA_MOUNTS}/log/haproxy/haproxy.log {
+ daily
+ rotate 20
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ invoke-rc.d rsyslog rotate >/dev/null 2>&1 || true
+ endscript
+}
+LOGROTATE_EOF
diff --git a/patch/rabbitmq3.8.19_patch_03/scripts/patch_client.sh b/patch/rabbitmq3.8.19_patch_03/scripts/patch_client.sh
new file mode 100644
index 0000000..53da381
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/scripts/patch_client.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+rm -f /etc/confd/templates/appctl.sh.tmpl
+cp /patch/appctl.sh.tmpl /etc/confd/templates/
+rm -f /usr/bin/appctl
+rm -f /opt/app/bin/ctl.sh
+cp /patch/ctl.sh /opt/app/bin/ctl.sh
+ln -s /opt/app/bin/ctl.sh /usr/bin/appctl
+chmod 777 /usr/bin/appctl
+service confd restart
+appctl start
diff --git a/patch/rabbitmq3.8.19_patch_03/scripts/patch_haproxy.sh b/patch/rabbitmq3.8.19_patch_03/scripts/patch_haproxy.sh
new file mode 100644
index 0000000..51b988a
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/scripts/patch_haproxy.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+rm -f /etc/confd/templates/haproxy.sh.tmpl
+cp /patch/haproxy.sh.tmpl /etc/confd/templates/
+service confd restart
+sleep 2s
+systemctl restart haproxy
+
diff --git a/patch/rabbitmq3.8.19_patch_03/scripts/rollback_client.sh b/patch/rabbitmq3.8.19_patch_03/scripts/rollback_client.sh
new file mode 100644
index 0000000..1250ece
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/scripts/rollback_client.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+rm -f /etc/confd/templates/appctl.sh.tmpl
+cp /patch/appctl.sh.tmpl.bak /etc/confd/templates/appctl.sh.tmpl
+rm -f /usr/bin/appctl
+rm -f /opt/app/bin/ctl.sh
+cp /patch/ctl.sh.bak /opt/app/bin/ctl.sh
+ln -s /opt/app/bin/ctl.sh /usr/bin/appctl
+service confd restart
+sleep 2s
+systemctl restart haproxy
diff --git a/patch/rabbitmq3.8.19_patch_03/scripts/rollback_haproxy.sh b/patch/rabbitmq3.8.19_patch_03/scripts/rollback_haproxy.sh
new file mode 100644
index 0000000..01437ba
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_03/scripts/rollback_haproxy.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+rm -f /etc/confd/templates/haproxy.sh.tmpl
+cp /patch/haproxy.sh.tmpl.bak /etc/confd/templates/haproxy.sh.tmpl
+service confd restart
+sleep 2s
+systemctl restart haproxy
diff --git a/patch/rabbitmq3.8.19_patch_04/configs/cluster.json.mustache b/patch/rabbitmq3.8.19_patch_04/configs/cluster.json.mustache
new file mode 100644
index 0000000..fcbf298
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_04/configs/cluster.json.mustache
@@ -0,0 +1,205 @@
+{
+ "name": {{cluster.name}},
+ "description": {{cluster.description}},
+ "vxnet": {{cluster.vxnet}},
+ "links": {
+ "etcd_service": {{cluster.etcd_service}}
+ },
+ "multi_zone_policy": "round_robin",
+ "upgrading_policy": "sequential",
+ "nodes": [{
+ "role": "disc",
+ "container": {
+ "type": "lxc",
+ "prefer_type": "lxc",
+ "sriov_nic": true,
+ "zone": "pek3a",
+ "image": "img-uapqdeja"
+ },
+ "instance_class": {{cluster.disc.instance_class}},
+ "count": {{cluster.disc.count}},
+ "cpu": {{cluster.disc.cpu}},
+ "memory": {{cluster.disc.memory}},
+ "volume": {
+ "size": {{cluster.disc.volume_size}},
+ "mount_point": "/data",
+ "filesystem": "ext4"
+ },
+ "services": {
+ "start": {
+ "order": 0,
+ "cmd": "appctl start",
+ "nodes_to_execute_on": 255,
+ "timeout": 500
+ },
+ "stop": {
+ "order": 1,
+ "cmd": "appctl stop"
+ },
+ "scale_in": {
+ "nodes_to_execute_on": 10,
+ "pre_check": "appctl preCheckForScaleIn",
+ "cmd": "appctl scaleIn",
+ "timeout": 90
+ },
+ "destroy": {
+ "order": 0,
+ "cmd": "appctl stop"
+ },
+ "scale_out": {
+ "cmd": "appctl scaleOut",
+ "timeout": 90
+ }
+ },
+ "advanced_actions": ["scale_horizontal"],
+ "vertical_scaling_policy": "sequential",
+ "health_check": {
+ "enable": true,
+ "interval_sec": 60,
+ "timeout_sec": 10,
+ "action_timeout_sec": 60,
+ "healthy_threshold": 2,
+ "unhealthy_threshold": 2,
+ "check_cmd": "appctl check"
+ },
+ "monitor": {
+ "enable": true,
+ "cmd": "appctl measure",
+ "items": {
+ "fd_used": {
+ "unit": "count"
+ },
+ "sockets_used": {
+ "unit": "count"
+ },
+ "proc_used": {
+ "unit": "count"
+ },
+ "run_queue": {
+ "unit": "count"
+ },
+ "mem_used": {
+ "unit": "MB"
+ }
+ },
+ "groups": {
+ "Fd Used": ["fd_used"],
+ "Sockets Used": ["sockets_used"],
+ "Proc Used": ["proc_used"],
+ "Run Queue": ["run_queue"],
+ "Mem Used": ["mem_used"]
+ },
+ "display": ["Mem Used", "Fd Used", "Sockets Used", "Proc Used", "Run Queue"],
+ "alarm": ["fd_used", "mem_used"]
+ }
+ }, {
+ "role": "client",
+ "container": {
+ "type": "kvm",
+ "zone": "pek3a",
+ "image": "img-uapqdeja"
+ },
+ "instance_class": {{cluster.client.instance_class}},
+ "count": {{cluster.client.count}},
+ "cpu": {{cluster.client.cpu}},
+ "memory": {{cluster.client.memory}},
+ "user_access": true,
+ "passphraseless": "ssh-rsa",
+ "services": {
+ "start": {
+ "cmd": "appctl start"
+ },
+ "stop": {
+ "cmd": "appctl stop"
+ }
+ },
+ "advanced_actions": ["attach_keypairs"]
+ }, {
+ "role": "haproxy",
+ "container": {
+ "type": "lxc",
+ "prefer_type": "lxc",
+ "sriov_nic": true,
+ "zone": "pek3a",
+ "image": "img-uapqdeja"
+ },
+ "instance_class": {{cluster.haproxy.instance_class}},
+ "count": {{cluster.haproxy.count}},
+ "cpu": {{cluster.haproxy.cpu}},
+ "memory": {{cluster.haproxy.memory}},
+ "volume": {
+ "size": {{cluster.haproxy.volume_size}},
+ "mount_point": "/data",
+ "filesystem": "ext4"
+ },
+ "services": {
+ "start": {
+ "order": 1,
+ "cmd": "appctl start"
+ },
+ "stop": {
+ "order": 0,
+ "cmd": "appctl stop"
+ },
+ "restart": {
+ "order": 0,
+ "cmd": "appctl restart"
+ }
+ },
+ "advanced_actions": ["scale_horizontal"],
+ "health_check": {
+ "enable": true,
+ "interval_sec": 60,
+ "timeout_sec": 10,
+ "action_timeout_sec": 30,
+ "healthy_threshold": 2,
+ "unhealthy_threshold": 2,
+ "check_cmd": "appctl check"
+ }, "volume": {
+ "size": {{cluster.haproxy.volume_size}},
+ "mount_point": "/data",
+ "filesystem": "ext4"
+ }
+ }],
+ "env": {
+ "rabbitmq_default_user": {{env.rabbitmq_default_user}},
+ "rabbitmq_default_pass": {{env.rabbitmq_default_pass}},
+ "haproxy_balance_policy": {{env.haproxy_balance_policy}},
+ "haproxy_web_port": {{env.haproxy_web_port}},
+ "haproxy_username": {{env.haproxy_username}},
+ "haproxy_password": {{env.haproxy_password}},
+ "num_tcp_acceptors": {{env.num_tcp_acceptors}},
+ "handshake_timeout": {{env.handshake_timeout}},
+ "reverse_dns_lookups": {{env.reverse_dns_lookups}},
+ "vm_memory_high_watermark": {{env.vm_memory_high_watermark}},
+ "vm_memory_high_watermark_paging_ratio": {{env.vm_memory_high_watermark_paging_ratio}},
+ "disk_free_limit": {{env.disk_free_limit}},
+ "frame_max": {{env.frame_max}},
+ "channel_max": {{env.channel_max}},
+ "heartbeat": {{env.heartbeat}},
+ "collect_statistics": {{env.collect_statistics}},
+ "collect_statistics_interval": {{env.collect_statistics_interval}},
+ "cluster_partition_handling": {{env.cluster_partition_handling}},
+ "cluster_keepalive_interval": {{env.cluster_keepalive_interval}},
+ "background_gc_enabled": {{env.background_gc_enabled}},
+ "background_gc_target_interval": {{env.background_gc_target_interval}},
+ "proxy_protocol": {{env.proxy_protocol}},
+ "tracing_user": {{env.tracing_user}},
+ "web_console_enabled": {{env.web_console_enabled}}
+ },
+ "endpoints": {
+ "client": {
+ "port": 5672,
+ "protocol": "tcp"
+ },
+ "status": {
+ "port": 8100,
+ "protocol": "tcp"
+ },
+ "reserved_ips": {
+ "vip": {
+ "value": ""
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/patch/rabbitmq3.8.19_patch_04/configs/config.json b/patch/rabbitmq3.8.19_patch_04/configs/config.json
new file mode 100644
index 0000000..5001978
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_04/configs/config.json
@@ -0,0 +1,379 @@
+{
+ "type": "array",
+ "properties": [{
+ "key": "cluster",
+ "description": "RabbitMQ cluster properties",
+ "type": "array",
+ "properties": [{
+ "key": "name",
+ "label": "Name",
+ "description": "The name of the RabbitMQ service",
+ "type": "string",
+ "default": "RabbitMQ",
+ "required": "no"
+ }, {
+ "key": "description",
+ "label": "Description",
+ "description": "The description of the RabbitMQ service",
+ "type": "string",
+ "default": "",
+ "required": "no"
+ }, {
+ "key": "vxnet",
+ "label": "VxNet",
+ "description": "Choose a vxnet to join",
+ "type": "string",
+ "default": "",
+ "required": "yes"
+ }, {
+ "key": "etcd_service",
+ "label": "etcd",
+ "description": "Choose a etcd to use",
+ "type": "service",
+ "tag": ["ETCD", "etcd"],
+ "limits": {
+ "app-fdyvu2wk": ["appv-52759jdc", "appv-h1n2681n"]
+ },
+ "default": "",
+ "required": "yes"
+ }, {
+ "key": "resource_group",
+ "label": "Resource Configuration",
+ "description": "Test: 3 disc nodes with 1 HAProxy node; Prod: 3 disc nodes with 2 HAProxy nodes",
+ "type": "string",
+ "default": "Prod",
+ "range": ["Test", "Prod"]
+ }, {
+ "key": "disc",
+ "label": "Disc Node",
+ "description": "Disc Node",
+ "type": "array",
+ "properties": [{
+ "key": "cpu",
+ "label": "CPU",
+ "description": "CPUs of each node",
+ "type": "integer",
+ "default": 1,
+ "range": [1, 2, 4, 8, 16, 32],
+ "resource_group": [1, 2],
+ "required": "yes"
+ }, {
+ "key": "memory",
+ "label": "Memory",
+ "description": "Memory of each node",
+ "type": "integer",
+ "default": 1024,
+ "range": [1024, 2048, 4096, 8192, 16384, 32768, 49152, 65536, 131072],
+ "resource_group": [1024, 4096],
+ "required": "yes"
+ }, {
+ "key": "instance_class",
+ "label": "Instance Class",
+ "description": "",
+ "type": "integer",
+ "default": 101,
+ "range": [101, 202],
+ "resource_group": [101, 202],
+ "required": "yes"
+ }, {
+ "key": "volume_size",
+ "label": "Volume Size",
+ "description": "The volume size for each instance",
+ "type": "integer",
+ "auto_scale_step": 10,
+ "min": 10,
+ "max": 1000,
+ "default": 10,
+ "required": "yes"
+ }, {
+ "key": "count",
+ "label": "Count",
+ "description": "Disc Node Count",
+ "type": "integer",
+ "auto_scale_step": 1,
+ "default": 3,
+ "min": 3,
+ "max": 100,
+ "required": "yes"
+ }]
+ }, {
+ "key": "client",
+ "label": "client Node",
+ "description": "client Node",
+ "type": "array",
+ "properties": [{
+ "key": "cpu",
+ "label": "CPU",
+ "description": "CPUs of each node",
+ "type": "integer",
+ "default": 1,
+ "range": [1, 2, 4, 8, 16, 32],
+ "required": "yes"
+ }, {
+ "key": "memory",
+ "label": "Memory",
+ "description": "Memory of each node",
+ "type": "integer",
+ "default": 1024,
+ "range": [1024, 2048, 4096, 8192, 16384, 32768, 49152, 65536, 131072],
+ "required": "yes"
+ }, {
+ "key": "instance_class",
+ "label": "Instance Class",
+ "description": "",
+ "type": "integer",
+ "default": 101,
+ "range": [101, 202],
+ "required": "yes"
+ }, {
+ "key": "count",
+ "label": "Count",
+ "description": "Client Node Count",
+ "type": "integer",
+ "default": 1,
+ "min": 1,
+ "required": "yes"
+ }]
+ }, {
+ "key": "haproxy",
+ "label": "Haproxy+Keepalived",
+ "description": "Haproxy+Keepalived",
+ "type": "array",
+ "properties": [{
+ "key": "cpu",
+ "label": "CPU",
+ "description": "CPUs of each node",
+ "type": "integer",
+ "default": 1,
+ "range": [1, 2, 4, 8, 16, 32],
+ "resource_group": [1, 2],
+ "required": "yes"
+ }, {
+ "key": "memory",
+ "label": "Memory",
+ "description": "Memory of each node",
+ "type": "integer",
+ "default": 1024,
+ "range": [1024, 2048, 4096, 8192, 16384, 32768, 49152, 65536, 131072],
+ "resource_group": [1024, 2048],
+ "required": "yes"
+ }, {
+ "key": "instance_class",
+ "label": "Instance Class",
+ "description": "",
+ "type": "integer",
+ "default": 101,
+ "range": [101, 202],
+ "required": "yes"
+ }, {
+ "key": "volume_size",
+ "label": "Volume Size",
+ "description": "The volume size for each instance",
+ "type": "integer",
+ "auto_scale_step": 10,
+ "min": 10,
+ "max": 1000,
+ "default": 10,
+ "required": "yes"
+ }, {
+ "key": "count",
+ "label": "Count",
+ "description": "Haproxy HA Node Count",
+ "type": "integer",
+ "min": 2,
+ "max": 100,
+ "default": 2,
+ "required": "yes"
+ }]
+ }
+ ]
+ }, {
+ "key": "env",
+ "description": "RabbitMQ service properties",
+ "type": "array",
+ "properties": [{
+ "key": "rabbitmq_default_user",
+ "label": "rabbitmq_default_user",
+ "description": "rabbitmq_user",
+ "type": "string",
+ "default": "guest",
+ "required": "yes",
+ "changeable": false
+ }, {
+ "key": "rabbitmq_default_pass",
+ "label": "rabbitmq_default_pass",
+ "description": "rabbitmq_pass",
+ "type": "password",
+ "pattern": "^([^'\"]{1,})$",
+ "required": "yes"
+ }, {
+ "key": "haproxy_balance_policy",
+ "label": "haproxy_balance_policy",
+ "description": "haproxy balance policy",
+ "type": "string",
+ "default": "roundrobin",
+ "required": "no",
+ "range": ["roundrobin", "leastconn", "static-rr", "source", "uri", "url_param"]
+ }, {
+ "key": "haproxy_web_port",
+ "label": "haproxy_web_port",
+ "description": "haproxy web port",
+ "type": "integer",
+ "default": 8100,
+ "required": "no"
+ }, {
+ "key": "haproxy_username",
+ "label": "haproxy_username",
+ "description": "haproxy web login username",
+ "type": "string",
+ "default": "haproxy",
+ "required": "no"
+ }, {
+ "key": "haproxy_password",
+ "label": "haproxy_password",
+ "description": "haproxy web login passwd",
+ "type": "password",
+ "changeable":true,
+ "default": "haproxy",
+ "pattern": "^([a-zA-Z0-9_!#%^&*()./;]{6,}|)$",
+ "required": "no"
+ }, {
+ "key": "num_tcp_acceptors",
+ "label": "num_tcp_acceptors",
+ "description": "Number of Erlang processes that will accept connections for the TCP listeners",
+ "type": "integer",
+ "default": 10,
+ "min": 10,
+ "max": 200,
+ "required": "no"
+ }, {
+ "key": "handshake_timeout",
+ "label": "handshake_timeout",
+ "description": "Maximum time for AMQP 0-8/0-9/0-9-1 handshake (after socket connection and SSL handshake), in milliseconds",
+ "type": "integer",
+ "default": 10000,
+ "min": 5000,
+ "required": "no"
+ }, {
+ "key": "vm_memory_high_watermark",
+ "label": "vm_memory_high_watermark",
+ "description": "Memory threshold at which the flow control is triggered",
+ "type": "number",
+ "default": 0.4,
+ "range": [0.3,0.4,0.5,0.6,0.7],
+ "required": "no"
+ }, {
+ "key": "vm_memory_high_watermark_paging_ratio",
+ "label": "vm_memory_high_watermark_paging_ratio",
+ "description": "Fraction of the high watermark limit at which queues start to page messages out to disc to free up memory",
+ "type": "number",
+ "default": 0.5,
+ "range": [0.3,0.4,0.5,0.6,0.7],
+ "required": "no"
+ }, {
+ "key": "disk_free_limit",
+ "label": "disk_free_limit",
+ "description": "Disk free space (in bytes) limit of the partition on which RabbitMQ is storing data",
+ "type": "integer",
+ "default": 524288000,
+ "required": "no"
+ }, {
+ "key": "frame_max",
+ "label": "frame_max",
+ "description": "Maximum permissible size of a frame (in bytes) to negotiate with clients,setting to 0 means unlimited but will trigger a bug in some QPid clients. Setting a larger value may improve throughput; setting a smaller value may improve latency",
+ "type": "integer",
+ "default": 131072,
+ "required": "no"
+ }, {
+ "key": "channel_max",
+ "label": "channel_max",
+ "description": "Maximum permissible number of channels to negotiate with clients. Setting to 0 means unlimited. Using more channels increases memory footprint of the broker.",
+ "type": "integer",
+ "default": 0,
+ "required": "no"
+ }, {
+ "key": "heartbeat",
+ "label": "heartbeat",
+ "description": "Value representing the heartbeat delay, in seconds, that the server sends in the connection.tune frame",
+ "type": "integer",
+ "default": 60,
+ "required": "no"
+ }, {
+ "key": "collect_statistics",
+ "label": "collect_statistics",
+ "description": "Statistics collection mode. Primarily relevant for the management plugin",
+ "type": "string",
+ "range": ["none","coarse","fine"],
+ "default": "none",
+ "required": "no"
+ }, {
+ "key": "collect_statistics_interval",
+ "label": "collect_statistics_interval",
+ "description": "Statistics collection interval in milliseconds. Primarily relevant for the management plugin",
+ "type": "integer",
+ "default": 5000,
+ "required": "no"
+ }, {
+ "key": "cluster_partition_handling",
+ "label": "cluster_partition_handling",
+ "description": "How to handle network partitions",
+ "type": "string",
+ "range": ["ignore","pause_minority","autoheal"],
+ "default": "pause_minority",
+ "required": "no"
+ }, {
+ "key": "cluster_keepalive_interval",
+ "label": "cluster_keepalive_interval",
+ "description": "How frequently nodes should send keepalive messages to other nodes (in milliseconds)",
+ "type": "integer",
+ "default": 10000,
+ "required": "no"
+ }, {
+ "key": "background_gc_target_interval",
+ "label": "background_gc_target_interval",
+ "description": "The actual interval will vary depending on how long it takes to execute the operation",
+ "type": "integer",
+ "min": 30000,
+ "default": 60000,
+ "required": "no"
+ }, {
+ "key": "background_gc_enabled",
+ "label": "background_gc_enabled",
+ "description": "Disabling background GC may reduce latency for client operations, keeping it enabled may reduce median RAM usage",
+ "type": "boolean",
+ "default": false,
+ "range": [true, false],
+ "required": "no"
+ }, {
+ "key": "reverse_dns_lookups",
+ "label": "reverse_dns_lookups",
+ "description": "Set to true to have RabbitMQ perform a reverse DNS lookup on client connections, and present that information through rabbitmqctl and the management plugin",
+ "type": "boolean",
+ "default": false,
+ "range": [true, false],
+ "required": "no"
+ }, {
+ "key": "tracing_user",
+ "label": "tracing_user",
+ "description": "The name of a user as which to create the tracing queues and bindings",
+ "type": "string",
+ "default": "guest",
+ "required": "no"
+ }, {
+ "key": "proxy_protocol",
+ "label": "proxy_protocol",
+ "description": "Whether or not to enable proxy protocol support. Once enabled, clients cannot directly connect to the broker anymore. They must connect through a load balancer that sends theproxy protocol header to the broker at connection time.This setting applies only to AMQP clients, other protocolslike MQTT or STOMP have their own setting to enable proxy protocol. See the plugins documentation for more information",
+ "type": "boolean",
+ "default": false,
+ "range": [true, false],
+ "required": "no"
+ }, {
+ "key": "web_console_enabled",
+ "label": "Switch of log web console",
+ "description": "Whether to enable log web console",
+ "type": "boolean",
+ "default": true,
+ "required": "no"
+ }]
+ }]
+}
diff --git a/patch/rabbitmq3.8.19_patch_04/configs/locale/en.json b/patch/rabbitmq3.8.19_patch_04/configs/locale/en.json
new file mode 100644
index 0000000..8b68d99
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_04/configs/locale/en.json
@@ -0,0 +1,6 @@
+{
+ "Sockets Used": "Percentage of file descriptors used as sockets",
+ "Fd Used": "Percentage of file descriptors used as sockets",
+ "Proc Used": "Erlang running number",
+ "Run Queue": "Erlang waiting number"
+}
diff --git a/patch/rabbitmq3.8.19_patch_04/configs/locale/zh-cn.json b/patch/rabbitmq3.8.19_patch_04/configs/locale/zh-cn.json
new file mode 100644
index 0000000..9e7c83a
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_04/configs/locale/zh-cn.json
@@ -0,0 +1,75 @@
+{
+ "Name": "名称",
+ "Description": "描述",
+ "RabbitMQ cluster propertie": "RabbitMQ 集群",
+ "The name of the RabbitMQ service": "RabbitMQ 服务名称",
+ "The description of the RabbitMQ service": "RabbitMQ 服务描述",
+ "rabbitmq_user": "Rabbitmq网页控制台管理员用户名(此项配置后不可修改,请谨慎操作)",
+ "rabbitmq_pass": "Rabbitmq网页控制台默认管理员用户密码",
+ "VxNet": "私有网络",
+ "Test": "测试环境",
+ "Prod": "生产环境",
+ "Test: 3 disc nodes with 1 HAProxy node; Prod: 3 disc nodes with 2 HAProxy nodes": "测试环境:1核1G磁盘节点 x 3 ,1核1G客户端节点 x 1,1核1G负载均衡节点 x 2;生产环境:2核4G超高性能型磁盘节点 x 3,1核1G客户端节点 x 1,2核2G负载均衡节点 x 2",
+ "Memory of each node": "每个节点的内存",
+ "The volume size for each instance": "每个实例的磁盘大小",
+ "Choose a vxnet to join": "选择要加入的私有网络",
+ "CPU": "CPU",
+ "CPUs of each node": "每个节点的 CPU 数量",
+ "Memory": "内存",
+ "Memory of each node ": "每个节点的内存数量",
+ "Instance Class": "主机类型",
+ "RabbitMQ Node": "RabbitMQ 节点",
+ "RabbitMQ Node Count": "RabbitMQ 节点数量",
+ "Node Count": "节点数量",
+ "Number of nodes for the cluster to create": "要创建的节点数量",
+ "Volume Size": "存储容量",
+ "The volume size for each node": "每个节点的存储容量",
+ "instance class": "实例类型",
+ "count" : "个",
+ "Count" : "节点个数",
+ "Sockets Used": "Sockets 句柄数",
+ "Fd Used": "文件句柄数",
+ "Proc Used": "Broker 子进程数",
+ "Run Queue": "正在等待的 Erlang 进程数",
+ "Mem Used": "RabbitMQ 内存占用 (MB)",
+ "Haproxy+Keepalived": "负载均衡器",
+ "roundrobin": "轮询",
+ "leastconn": "最小连接",
+ "static-rr": "静态权重",
+ "source": "IP 哈希",
+ "uri": "uri 哈希",
+ "client Node": "client 节点",
+ "Disc Node Count": "磁盘节点个数",
+ "Client Node Count": "client 节点个数",
+ "haproxy web port": "haproxy 监控界面端口",
+ "haproxy web login usernam": "haproxy 监控界面用户名",
+ "haproxy web login passwd": "haproxy 监控界面密码",
+ "url_param": "url_param 哈希",
+ "haproxy balance policy": "负载均衡策略(roundrobin:轮询, leastconn:最小连接, static-rr:静态权重, source:IP 哈希, uri:uri 哈希, url_param:url_param 哈希)",
+ "Haproxy HA Node Count": "负载均衡器高可用节点个数",
+ "Disc Node": "磁盘节点",
+ "Number of Erlang processes that will accept connections for the TCP listeners": "接受TCP侦听器连接的Erlang进程数",
+ "Maximum time for AMQP 0-8/0-9/0-9-1 handshake (after socket connection and SSL handshake), in milliseconds": "AMQP 0-8/0-9/0-9-1 handshake (在 socket 连接和SSL 握手之后)的最大时间, 单位为毫秒",
+ "Memory threshold at which the flow control is triggered": "流程控制触发的内存阀值",
+ "Fraction of the high watermark limit at which queues start to page messages out to disc to free up memory": "高水位限制的分数,当达到阀值时,队列中消息会转移到磁盘上以释放内存",
+ "Disk free space (in bytes) limit of the partition on which RabbitMQ is storing data": "RabbitMQ存储数据分区的可用磁盘空间限制.当可用空间值低于阀值时,流程控制将被触发.默认情况下,可用磁盘空间必须超过50MB,默认值为500MB",
+ "Maximum permissible size of a frame (in bytes) to negotiate with clients,setting to 0 means unlimited but will trigger a bug in some QPid clients. Setting a larger value may improve throughput; setting a smaller value may improve latency": "与客户端协商的允许最大frame大小. 设置为0表示无限制,但在某些QPid客户端会引发bug. 设置较大的值可以提高吞吐量;设置一个较小的值可能会提高延迟",
+ "Maximum permissible number of channels to negotiate with clients. Setting to 0 means unlimited. Using more channels increases memory footprint of the broker.": "与客户端协商的允许最大chanel大小. 设置为0表示无限制.该数值越大,则broker使用的内存就越高",
+ "Value representing the heartbeat delay, in seconds, that the server sends in the connection.tune frame": "表示心跳延迟(单位为秒) ,服务器将在connection.tune frame中发送.如果设置为 0, 心跳将被禁用. 客户端可以不用遵循服务器的建议,禁用心跳可以在有大量连接的场景中提高性能,但可能会造成关闭了非活动连接的网络设备上的连接落下",
+ "Statistics collection mode. Primarily relevant for the management plugin": "统计收集模式。主要与管理插件相关",
+ "Statistics collection interval in milliseconds. Primarily relevant for the management plugin": "统计收集时间间隔(毫秒为单位). 主要针对于 management plugin",
+ "How to handle network partitions": "如何处理网络分区",
+ "How frequently nodes should send keepalive messages to other nodes (in milliseconds)": "节点向其它节点发送存活消息和频率(毫秒). 注意,这与 net_ticktime是不同的; 丢失存活消息不会引起节点掉线",
+ "The actual interval will vary depending on how long it takes to execute the operation": "GC 实际间隔将根据执行操作所需的时间而有所不同",
+ "The name of a user as which to create the tracing queues and bindings": "用于创建追踪队列的用户",
+ "Disabling background GC may reduce latency for client operations, keeping it enabled may reduce median RAM usage": "是否启用 GC,开启或许可以减少内存使用",
+ "Set to true to have RabbitMQ perform a reverse DNS lookup on client connections, and present that information through rabbitmqctl and the management plugin": "设置为true,可让客户端在连接时让RabbitMQ 执行一个反向DNS查找, 然后通过 rabbitmqctl 和 管理插件来展现信息",
+ "Whether or not to enable proxy protocol support. Once enabled, clients cannot directly connect to the broker anymore. They must connect through a load balancer that sends theproxy protocol header to the broker at connection time.This setting applies only to AMQP clients, other protocolslike MQTT or STOMP have their own setting to enable proxy protocol. See the plugins documentation for more information": "是否启用代理协议支持。一旦启用,客户端就不能直接连接到代理了。他们必须通过负载平衡器连接,此设置仅适用于AMQP客户端,其他协议类型的MQTT或STOMP有自己的设置来启用代理协议。有关更多信息,请参阅插件文档",
+ "err_code240": "扩容失败,请检查集群状态",
+ "err_code241": "节点状态不正常,请检查集群状态",
+ "err_code242": "删除过多内存节点和磁盘节点,pause_minority 模式下每次仅允许删除小于总数的 1/2 个节点",
+ "err_code243": "节点磁盘使用率超过 30%,剩余空间不足或导致升级失败,请先扩容",
+ "Whether to enable log web console": "日志管理控制台开关,true=开启,默认开启",
+ "notice_when_upgrade": "1. 如果集群使用了优先队列 (priority queue),请根据 [文档](https://docs.qingcloud.com/product/middware/rabbitmq/index] 进行操作,否则会导致此类队列里的数据**全部丢失**;\n 2. 若集群中缓存有大量消息数据,升级将极为耗时,单核 1G 内存的节点 10G 数据需要 30 分钟,数据越多速度越慢,建议业务低谷时队列基本为空时操作;\n 3. 每个节点磁盘使用率不得超过 30%,剩余空间不足会导致升级失败。",
+ "etcd": "etcd外部服务"
+}
diff --git a/patch/rabbitmq3.8.19_patch_04/configs/patch.json b/patch/rabbitmq3.8.19_patch_04/configs/patch.json
new file mode 100644
index 0000000..74154cb
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_04/configs/patch.json
@@ -0,0 +1,26 @@
+{
+ "patch_policy": ["appp-avpy7pbs"],
+ "patch_nodes": [{
+ "container": {
+ "snapshot": "ss-j2d9vegn",
+ "zone": "pek3a"
+ },
+ "patch": [{
+ "mount_role": "haproxy",
+ "mount_point": "/patch",
+ "mount_options": "defaults,noatime",
+ "filesystem": "ext4",
+ "cmd": "/patch/patch_haproxy.sh"
+ }],
+ "rollback": [{
+ "mount_role": "haproxy",
+ "mount_point": "/patch",
+ "mount_options": "defaults,noatime",
+ "filesystem": "ext4",
+ "cmd": "/patch/rollback_haproxy.sh"
+ }]
+ }]
+}
+
+
+
diff --git a/patch/rabbitmq3.8.19_patch_04/configs/replace_policy.json b/patch/rabbitmq3.8.19_patch_04/configs/replace_policy.json
new file mode 100644
index 0000000..94a3c13
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_04/configs/replace_policy.json
@@ -0,0 +1,283 @@
+{
+ "pek3": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3b": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3c": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3d": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "ap3": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }, {
+ "src": "201",
+ "dst": 202
+ }, {
+ "src": "301",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }, {
+ "src": "2",
+ "dst": 6
+ }, {
+ "src": "5",
+ "dst": 6
+ }]
+ },
+ "ap3a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }, {
+ "src": "301",
+ "dst": 202
+ }, {
+ "src": "201",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }, {
+ "src": "2",
+ "dst": 6
+ }, {
+ "src": "5",
+ "dst": 6
+ }]
+ },
+ "sh1": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "sh1a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "sh1b": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 202
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "pek3a": {
+ "instance_class": [{
+ "src": "101",
+ "dst": 0
+ }, {
+ "src": "201",
+ "dst": 1
+ }, {
+ "src": "202",
+ "dst": 1
+ }, {
+ "src": "301",
+ "dst": 1
+ }],
+ "volume_class": [{
+ "src": "100",
+ "dst": 0
+ }, {
+ "src": "200",
+ "dst": 3
+ }, {
+ "src": "5",
+ "dst": 2
+ }, {
+ "src": "6",
+ "dst": 2
+ }]
+ },
+ "ap2a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }, {
+ "src": "301",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "5",
+ "dst": 2
+ }, {
+ "src": "6",
+ "dst": 2
+ }, {
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "gd2": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "gd2a": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ },
+ "gd2b": {
+ "instance_class": [{
+ "src": "0",
+ "dst": 101
+ }, {
+ "src": "1",
+ "dst": 201
+ }, {
+ "src": "202",
+ "dst": 201
+ }],
+ "volume_class": [{
+ "src": "0",
+ "dst": 100
+ }, {
+ "src": "3",
+ "dst": 200
+ }]
+ }
+}
\ No newline at end of file
diff --git a/patch/rabbitmq3.8.19_patch_04/scripts/keepalived.sh.tmpl b/patch/rabbitmq3.8.19_patch_04/scripts/keepalived.sh.tmpl
new file mode 100644
index 0000000..fdabb53
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_04/scripts/keepalived.sh.tmpl
@@ -0,0 +1,119 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+myPath="$0"
+
+cleanUp() {
+ local rc=$?
+ [ "$rc" -eq 0 ] || echo "# Failed ($rc)! Please check confd logs." >> $myPath
+ return $rc
+}
+
+trap cleanUp EXIT
+
+rotate() {
+ local path=$1 maxFilesCount=5
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+}
+
+flush() {
+ local targetFile=$1
+ if [ -n "$targetFile" ]; then
+ rotate $targetFile
+ cat > $targetFile -
+ else
+ cat -
+ fi
+}
+
+applyEnvs() {
+ local -r envFile=/opt/app/bin/envs/confd.env
+ if [ -f "$envFile" ]; then . $envFile; fi
+ local -r nodeEnvFile=/opt/app/bin/envs/nodectl.env
+ if [ -f "$nodeEnvFile" ]; then . $nodeEnvFile; fi
+}
+
+applyEnvs
+
+flush /etc/keepalived/keepalived.conf << KEEPALIVED_EOF
+{{ $replicaIPs := split (getv "/cluster/endpoints/reserved_ips/vip/value") "." }}
+global_defs {
+}
+
+vrrp_script check_haproxy {
+ script "/usr/bin/killall -0 haproxy"
+ interval 2
+ weight 2
+}
+
+vrrp_instance HAProxy_HA {
+ state BACKUP
+ interface eth0
+ virtual_router_id {{ index $replicaIPs 3 }}
+ priority {{ getv "/host/sid" }}
+ advert_int 2
+ nopreempt
+ unicast_src_ip {{ getv "/host/ip" }}
+ authentication {
+ auth_type PASS
+ auth_pass pwd
+ }
+
+ virtual_ipaddress { #set VIP
+ {{ getv "/cluster/endpoints/reserved_ips/vip/value" }}/32
+ }
+
+ track_script {
+ check_haproxy
+ }
+}
+
+KEEPALIVED_EOF
+
+flush /opt/keepalived/current/etc/sysconfig/keepalived << 'KEEPALIVED_SYSCONFIG_EOF'
+
+# Options for keepalived. See `keepalived --help' output and keepalived(8) and
+# keepalived.conf(5) man pages for a list of all options. Here are the most
+# common ones :
+#
+# --vrrp -P Only run with VRRP subsystem.
+# --check -C Only run with Health-checker subsystem.
+# --dont-release-vrrp -V Dont remove VRRP VIPs & VROUTEs on daemon stop.
+# --dont-release-ipvs -I Dont remove IPVS topology on daemon stop.
+# --dump-conf -d Dump the configuration data.
+# --log-detail -D Detailed log messages.
+# --log-facility -S 0-7 Set local syslog facility (default=LOG_DAEMON)
+#
+
+KEEPALIVED_OPTIONS="-D -d -S 0"
+
+KEEPALIVED_SYSCONFIG_EOF
+
+{{- if getvs "/host/role" | filter "haproxy" }}
+mkdir -p ${DATA_MOUNTS}/log/keepalivd/
+chmod 777 ${DATA_MOUNTS}/log/keepalivd/
+flush /etc/rsyslog.d/49-keepalived.conf << KEEPALIVED_LOG_EOF
+
+if \$programname startswith 'Keepalived' then ${DATA_MOUNTS}/log/keepalivd/keepalived.log
+&stop
+
+KEEPALIVED_LOG_EOF
+{{- end }}
+
+flush /etc/logrotate.d/keepalived << LOGROTATE_EOF
+${DATA_MOUNTS}/log/keepalived/keepalived.log {
+ daily
+ rotate 20
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ invoke-rc.d rsyslog rotate >/dev/null 2>&1 || true
+ endscript
+}
+LOGROTATE_EOF
\ No newline at end of file
diff --git a/patch/rabbitmq3.8.19_patch_04/scripts/keepalived.sh.tmpl.bak b/patch/rabbitmq3.8.19_patch_04/scripts/keepalived.sh.tmpl.bak
new file mode 100644
index 0000000..d22f27b
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_04/scripts/keepalived.sh.tmpl.bak
@@ -0,0 +1,119 @@
+#!/usr/bin/env bash
+
+set -eo pipefail
+
+myPath="$0"
+
+cleanUp() {
+ local rc=$?
+ [ "$rc" -eq 0 ] || echo "# Failed ($rc)! Please check confd logs." >> $myPath
+ return $rc
+}
+
+trap cleanUp EXIT
+
+rotate() {
+ local path=$1 maxFilesCount=5
+ for i in $(seq 1 $maxFilesCount | tac); do
+ if [ -f "${path}.$i" ]; then mv ${path}.$i ${path}.$(($i+1)); fi
+ done
+ if [ -f "$path" ]; then cp $path ${path}.1; fi
+}
+
+flush() {
+ local targetFile=$1
+ if [ -n "$targetFile" ]; then
+ rotate $targetFile
+ cat > $targetFile -
+ else
+ cat -
+ fi
+}
+
+applyEnvs() {
+ local -r envFile=/opt/app/bin/envs/confd.env
+ if [ -f "$envFile" ]; then . $envFile; fi
+ local -r nodeEnvFile=/opt/app/bin/envs/nodectl.env
+ if [ -f "$nodeEnvFile" ]; then . $nodeEnvFile; fi
+}
+
+applyEnvs
+
+flush /etc/keepalived/keepalived.conf << KEEPALIVED_EOF
+{{ $replicaIPs := split (getv "/cluster/endpoints/reserved_ips/vip/value") "." }}
+global_defs {
+}
+
+vrrp_script check_haproxy {
+ script "/usr/bin/killall -0 haproxy"
+ interval 2
+ weight 2
+}
+
+vrrp_instance HAProxy_HA {
+ state BACKUP
+ interface eth0
+ virtual_router_id {{ index $replicaIPs 3 }}
+ priority {{ getv "/host/sid" }}
+ advert_int 2
+ nopreempt
+ unicast_src_ip {{ getv "/host/ip" }}
+ authentication {
+ auth_type PASS
+ auth_pass pwd
+ }
+
+ virtual_ipaddress { #set VIP
+ {{ getv "/cluster/endpoints/reserved_ips/vip/value" }}/24
+ }
+
+ track_script {
+ check_haproxy
+ }
+}
+
+KEEPALIVED_EOF
+
+flush /opt/keepalived/current/etc/sysconfig/keepalived << 'KEEPALIVED_SYSCONFIG_EOF'
+
+# Options for keepalived. See `keepalived --help' output and keepalived(8) and
+# keepalived.conf(5) man pages for a list of all options. Here are the most
+# common ones :
+#
+# --vrrp -P Only run with VRRP subsystem.
+# --check -C Only run with Health-checker subsystem.
+# --dont-release-vrrp -V Dont remove VRRP VIPs & VROUTEs on daemon stop.
+# --dont-release-ipvs -I Dont remove IPVS topology on daemon stop.
+# --dump-conf -d Dump the configuration data.
+# --log-detail -D Detailed log messages.
+# --log-facility -S 0-7 Set local syslog facility (default=LOG_DAEMON)
+#
+
+KEEPALIVED_OPTIONS="-D -d -S 0"
+
+KEEPALIVED_SYSCONFIG_EOF
+
+{{- if getvs "/host/role" | filter "haproxy" }}
+mkdir -p ${DATA_MOUNTS}/log/keepalivd/
+chmod 777 ${DATA_MOUNTS}/log/keepalivd/
+flush /etc/rsyslog.d/49-keepalived.conf << KEEPALIVED_LOG_EOF
+
+if \$programname startswith 'Keepalived' then ${DATA_MOUNTS}/log/keepalivd/keepalived.log
+&stop
+
+KEEPALIVED_LOG_EOF
+{{- end }}
+
+flush /etc/logrotate.d/keepalived << LOGROTATE_EOF
+${DATA_MOUNTS}/log/keepalived/keepalived.log {
+ daily
+ rotate 20
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ invoke-rc.d rsyslog rotate >/dev/null 2>&1 || true
+ endscript
+}
+LOGROTATE_EOF
\ No newline at end of file
diff --git a/patch/rabbitmq3.8.19_patch_04/scripts/patch_haproxy.sh b/patch/rabbitmq3.8.19_patch_04/scripts/patch_haproxy.sh
new file mode 100755
index 0000000..c293c9c
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_04/scripts/patch_haproxy.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+rm -f /etc/confd/templates/keepalived.sh.tmpl
+cp /patch/keepalived.sh.tmpl /etc/confd/templates/
+service confd restart
+sleep 2s
+systemctl restart keepalived
+
diff --git a/patch/rabbitmq3.8.19_patch_04/scripts/rollback_haproxy.sh b/patch/rabbitmq3.8.19_patch_04/scripts/rollback_haproxy.sh
new file mode 100755
index 0000000..68581b5
--- /dev/null
+++ b/patch/rabbitmq3.8.19_patch_04/scripts/rollback_haproxy.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+rm -f /etc/confd/templates/keepalived.sh.tmpl
+cp /patch/keepalived.sh.tmpl.bak /etc/confd/templates/keepalived.sh.tmpl
+service confd restart
+sleep 2s
+systemctl restart keepalived