Skip to content

Commit 2f3aaea

Browse files
committed
feat(pg_wal): add parameter pg_fs_wal (G) for define/changing pg_wal dir
new pg_wal style is `<pg_fs_wal>/<pg_cluster>-<pg_version>/pg_wal` when pg_fs_wal defined pg_fs_wal validatiton: pg_fs_wal must start with '/' and not contain spaces modify pg_wal of current pg_cluster: 1. edit and save pigsty.yml by setting the global `pg_wal` 2. run command `./pgsql.yml -l <cls> -t pg_wal` tested scenarios: - `pig sty install` - pg_fs_wal undefined - pg_fs_wal defined - `bin/pgsql-add pg-a` - pg_fs_wal undefined - pg_fs_wal defined - `./pgsql.yml -t pg_wal` - set pg_fs_wal=/wal - set pg_fs_wal=/wal2 (from /wal) - remove pg_fs_wal (from /wal2) - multiple call `./pgsql.yml -t pg_wal` - keep pg_fs_wal undefined or blank - keep pg_fs_wal=/wal `pg-backup full` will be executed automatically if pg_fs_wal changed and apply this settings: - full installation with valid pg_fs_wal (no backup operation if pg_fs_wal undefined or blank) - pg_fs_wal changed after installation - undefined or empty to `/wal` - `/wal` to `/wal2` - `/wal2` to undefined or empty
1 parent 1909c15 commit 2f3aaea

File tree

10 files changed

+306
-6
lines changed

10 files changed

+306
-6
lines changed

roles/pg_remove/tasks/main.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@
9090
- /pg/data
9191
- "{{ pg_fs_main }}/postgres"
9292

93+
- name: remove pg_fs_wal/?/pg_wal (if pg_fs_wal defined)
94+
tags: pg_data
95+
when: pg_clean|bool and (pg_fs_wal | length > 0)
96+
ignore_errors: yes
97+
file: path={{ item }} state=absent
98+
with_items:
99+
- "{{ pg_fs_wal }}/{{ pg_cluster }}-{{ pg_version }}"
93100

94101
#--------------------------------------------------------------#
95102
# remove packages [pg_pkg]
@@ -120,12 +127,12 @@
120127
pg_packages_list: |-
121128
{% set pkg_map = package_map | default({}) %}
122129
{% for pkg_list in pg_packages %}{% for pkg in pkg_list | trim | regex_replace('(,|\\s)+', ',') | regex_findall('([^,\\s]+)') | default([]) %}{% if pkg != '' %}{% if pkg in pkg_map %}{% set pkg = pkg_map[pkg] %}{% endif %}{% if not loop.first %},{% endif %}{{ pkg|replace('${pg_version}', pg_version|string)|replace('$v', pg_version|string) }}{% endif %}{% endfor %}
123-
130+
124131
{% endfor %}
125132
pg_extension_list: |-
126133
{% set pkg_map = package_map | default({}) %}
127134
{% for ext_list in pg_extensions %}{% for ext in ext_list | trim | regex_replace('(,|\\s)+', ',') | regex_findall('([^,\\s]+)') | default([]) %}{% if ext != '' %}{% if ext in pkg_map %}{% set ext = pkg_map[ext] %}{% endif %}{% if not loop.first %},{% endif %}{{ ext|replace('${pg_version}', pg_version|string)|replace('$v', pg_version|string) }}{% endif %}{% endfor %}
128-
135+
129136
{% endfor %}
130137
131138
# uninstall extensions first

roles/pgsql/defaults/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ pg_safeguard: false # prevent purging running postgres instance? f
5656
pg_clean: true # purging existing postgres during pgsql init? true by default
5757
pg_data: /pg/data # postgres data directory, `/pg/data` by default
5858
pg_fs_main: /data # mountpoint/path for postgres main data, `/data` by default
59+
pg_fs_wal: '' # mountpoint/path for pg_wal dir, default blank, new pg_wal will be <pg_fs_wal>/<pg_cluster>-<pg_version>/pg_wal
5960
pg_fs_bkup: /data/backups # mountpoint/path for pg backup data, `/data/backup` by default
6061
pg_storage_type: SSD # storage type for pg main data, SSD,HDD, SSD by default
6162
pg_dummy_filesize: 64MiB # size of `/pg/dummy`, hold 64MB disk space for emergency use

roles/pgsql/tasks/clean.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
ignore_errors: false
2020
fail:
2121
msg: >-
22-
Abort because the node {{ inventory_hostname }} seems not managed by pigsty, use ./node.yml to init node first.
22+
Abort because the node {{ inventory_hostname }} seems not managed by pigsty, use ./node.yml to init node first.
2323
2424
# check postgres by listening port
2525
- name: check postgres exists
@@ -41,7 +41,7 @@
4141
ignore_errors: false
4242
fail:
4343
msg: >-
44-
Abort because pg instance {{ pg_cluster }}-{{ pg_seq }} @ {{ inventory_hostname }} exists.
44+
Abort because pg instance {{ pg_cluster }}-{{ pg_seq }} @ {{ inventory_hostname }} exists.
4545
{% if pg_safeguard|bool %}pg_safeguard enabled, please disable it before purging.{% endif %}
4646
{% if not pg_clean|bool %}pg_clean = false, use -e pg_safeguard=false to override.{% endif %}
4747
@@ -94,7 +94,7 @@
9494
rm -rf /lib/systemd/system/[email protected] /lib/systemd/system/postgresql.service /etc/init.d/postgresql
9595
systemctl daemon-reload
9696
{% endif %}
97-
97+
9898
if ps -u postgres -o pid:1,command | grep -E 'postmaster|postgres:|-D' ; then
9999
{{ pg_bin_dir }}/pg_ctl -D {{ pg_data }} stop --mode=immediate
100100
fi
@@ -121,7 +121,7 @@
121121
{% else %}
122122
META_DIR="{{ pg_namespace|default('/pg') }}/{{ pg_cluster }}"
123123
{% endif %}
124-
124+
125125
export ETCDCTL_API=3
126126
export ETCDCTL_ENDPOINTS="{% for ip in groups['etcd']|sort %}{% if not loop.first %},{% endif %}https://{{ ip }}:{{ etcd_port }}{% endfor %}"
127127
export ETCDCTL_CACERT=/etc/pki/ca.crt
@@ -145,4 +145,10 @@
145145
- /etc/pgbouncer
146146
- /var/run/pgbouncer
147147

148+
- name: remove pg_fs_wal/?/pg_wal (if pg_fs_wal defined)
149+
tags: pg_clean_data
150+
when: pg_fs_wal | length > 0
151+
file: path={{ item }} state=absent
152+
with_items:
153+
- "{{ pg_fs_wal }}/{{ pg_cluster }}-{{ pg_version }}"
148154
...

roles/pgsql/tasks/dir.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
- "{{ pg_backup_dir }}/backup"
4343
- "/var/run/postgresql"
4444

45+
- name: List files in a directory
46+
ansible.builtin.command:
47+
cmd: ls "{{ pg_cluster_dir }}/data"
48+
4549
# make sure the /var/run/postgresql is created
4650
- name: create /var/run/postgresql tmpfiles.d
4751
copy:

roles/pgsql/tasks/main.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@
8383
tags: pgbackrest
8484
when: pgbackrest_enabled|bool
8585

86+
#--------------------------------------------------------------#
87+
# WAL [pg_wal]
88+
#--------------------------------------------------------------#
89+
- import_tasks: pg_wal.yml
90+
tags: pg_wal
91+
8692
#--------------------------------------------------------------#
8793
# Pgbouncer [pgbouncer]
8894
#--------------------------------------------------------------#

roles/pgsql/tasks/pg_wal.yml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/usr/bin/ansible-playbook
2+
---
3+
#--------------------------------------------------------------#
4+
# Modify pg_wal destination if pg_fs_wal defined [pg_wal]
5+
# new pg_wal is <pg_fs_wal>/<pg_cluster>-<pg_version>/pg_wal
6+
#--------------------------------------------------------------#
7+
8+
- name: run pg-role
9+
command: /pg/bin/pg-role
10+
register: pg_role_cmd
11+
12+
- name: update variable pg_role
13+
set_fact:
14+
pg_role: "{{ pg_role_cmd.stdout | trim }}"
15+
16+
- name: validate variable pg_fs_wal
17+
tags: [ validate_pg_fs_wal ]
18+
when: pg_fs_wal | length > 0
19+
block:
20+
- name: validate pg_fs_wal "{{ pg_fs_wal }}"
21+
fail:
22+
msg: "The variable pg_fs_wal must start with '/' and not contain spaces"
23+
when: >
24+
(pg_fs_wal[0] != '/') or (' ' in pg_fs_wal)
25+
26+
- name: retrieve path of pg_wal directory
27+
become: yes
28+
block:
29+
- name: validate variable pg_data
30+
assert:
31+
that: pg_data is defined and pg_data | length > 0
32+
msg: "pg_data must be defined"
33+
changed_when: false
34+
35+
- name: get current pg_wal real path
36+
command: realpath -m "{{ pg_data }}/pg_wal"
37+
register: real_curr_pg_wal_cmd
38+
changed_when: false
39+
40+
- name: calculate new pg_data path (parent of target pg_wal)
41+
set_fact:
42+
target_new_pg_data: >-
43+
{% if pg_fs_wal is defined and pg_fs_wal %}
44+
{{ pg_fs_wal | trim }}/{{ pg_cluster }}-{{ pg_version }}
45+
{% else %}
46+
{{ pg_data }}
47+
{% endif %}
48+
changed_when: false
49+
50+
- name: get target pg_wal real path
51+
command: "realpath -m {{ target_new_pg_data }}" # do not quote the var like "{{ target_new_pg_data }}"
52+
register: new_pg_data_cmd
53+
changed_when: false
54+
55+
- name: Set final path facts
56+
set_fact:
57+
new_pg_data: "{{ new_pg_data_cmd.stdout }}"
58+
real_curr_pg_wal: "{{ real_curr_pg_wal_cmd.stdout }}"
59+
pg_wal_dst: "{{ new_pg_data_cmd.stdout }}/pg_wal"
60+
changed_when: false
61+
62+
- name: get current pg_wal stat
63+
stat:
64+
path: "{{ pg_data }}/pg_wal" # do not use real_curr_pg_wal, use pg_data instead
65+
register: real_curr_pg_wal_stat
66+
changed_when: false
67+
68+
- name: Set real_curr_pg_wal_is_link variable
69+
set_fact:
70+
real_curr_pg_wal_is_link: "{{ real_curr_pg_wal_stat.stat.exists and real_curr_pg_wal_stat.stat.islnk }}"
71+
changed_when: false
72+
73+
- name: variable output for pg_wal
74+
debug:
75+
msg: |
76+
real_curr_pg_wal: {{ real_curr_pg_wal }}, pg_wal_dst: {{ pg_wal_dst }},
77+
real_curr_pg_wal_is_link: {{ real_curr_pg_wal_is_link }},
78+
pg_data: {{ pg_data }}, new_pg_data: {{ new_pg_data }},
79+
pg_fs_wal: {{ pg_fs_wal }},
80+
changed_when: false
81+
82+
83+
84+
#--------------------------------------------------------------#
85+
# Modify WAL [modify_pg_wal]
86+
#--------------------------------------------------------------#
87+
- include_tasks: pg_wal/pg_wal_modification.yml
88+
tags: modify_pg_wal
89+
when: (real_curr_pg_wal != pg_wal_dst) and (pg_fs_wal | length > 0)
90+
91+
92+
#--------------------------------------------------------------#
93+
# Restore WAL [restore_pg_wal]
94+
#--------------------------------------------------------------#
95+
- include_tasks: pg_wal/pg_wal_restoration.yml
96+
tags: restore_pg_wal
97+
when: (real_curr_pg_wal != pg_wal_dst) and (pg_fs_wal is not defined or (pg_fs_wal | trim | length == 0))
98+
99+
100+
...
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/ansible-playbook
2+
---
3+
4+
- name: operations after updating pg_wal dir
5+
vars:
6+
tmp_wal_dir: "pg_wal.tmp-backup"
7+
pg_data_lock: "{{ pg_data }}.locked"
8+
pg_wal_src_tmp: "{{ pg_data_lock }}/{{ tmp_wal_dir }}"
9+
block:
10+
- import_tasks: ../util/grace_start_pg.yml
11+
- import_tasks: ../util/grace_patroni_resume.yml
12+
13+
# finally, check if all postgres is ready
14+
- import_tasks: ../util/check_pg_ready.yml
15+
16+
- name: clean tmp directory after modifying pg_wal
17+
ignore_errors: yes
18+
file: path={{ item }} state=absent
19+
with_items:
20+
- "{{ pg_data }}/{{ tmp_wal_dir }}"
21+
- "{{ pg_wal_src_tmp }}"
22+
23+
- name: clean old pg_wal directory after modifying pg_wal
24+
ignore_errors: yes
25+
when: (real_curr_pg_wal != pg_wal_dst) and (real_curr_pg_wal_is_link == true)
26+
file: path={{ item }} state=absent
27+
with_items:
28+
- "{{ real_curr_pg_wal }}"
29+
30+
...
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/ansible-playbook
2+
---
3+
4+
- name: operations before updating pg_wal dir
5+
vars:
6+
tmp_wal_dir: "pg_wal.tmp-backup"
7+
pg_data_lock: "{{ pg_data }}.locked"
8+
pg_wal_src_tmp: "{{ pg_data_lock }}/{{ tmp_wal_dir }}"
9+
any_errors_fatal: true
10+
block:
11+
- import_tasks: ../util/pg_backup.yml
12+
- import_tasks: ../util/grace_patroni_pause.yml
13+
- import_tasks: ../util/grace_stop_pg.yml
14+
15+
- name: clean tmp dir before modify pg_wal
16+
file: path={{ item }} state=absent
17+
with_items:
18+
- "{{ pg_data_lock }}"
19+
- "{{ pg_wal_src_tmp }}"
20+
21+
...
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/ansible-playbook
2+
---
3+
#--------------------------------------------------------------#
4+
# Modify pg_wal destination if pg_fs_wal defined [pg_wal]
5+
# new pg_wal is <pg_fs_wal>/<pg_cluster>-<pg_version>/pg_wal
6+
#--------------------------------------------------------------#
7+
8+
- name: modify postgres wal directory to pg_fs_wal
9+
vars:
10+
tmp_wal_dir: "pg_wal.tmp-backup"
11+
pg_data_lock: "{{ pg_data }}.locked"
12+
pg_wal_src: "{{ pg_data_lock }}/pg_wal"
13+
pg_wal_src_tmp: "{{ pg_data_lock }}/{{ tmp_wal_dir }}"
14+
dbsu: "{{ pg_dbsu|default('postgres') }}"
15+
when: (pg_fs_wal | length > 0) and (real_curr_pg_wal != pg_wal_dst)
16+
block:
17+
- name: stat new pg_wal before modifying pg_wal
18+
find:
19+
paths: "{{ pg_wal_dst }}"
20+
register: pg_wal_dst_stat
21+
ignore_errors: yes
22+
23+
- name: check if new pg_wal is empty
24+
fail:
25+
msg: "The directory is not empty: {{ pg_wal_dst }} "
26+
when: pg_wal_dst_stat.matched > 0
27+
28+
- name: create new pg_data dir before modifying pg_wal
29+
file: path={{ item }} state=directory owner={{ dbsu }} group=postgres mode=0700
30+
with_items:
31+
- "{{ new_pg_data }}"
32+
33+
- import_tasks: pg_wal_before.yml
34+
35+
- name: clean tmp dir before modify pg_wal
36+
file: path={{ item }} state=absent
37+
with_items:
38+
- "{{ pg_wal_dst }}"
39+
40+
- name: lock pg data directory temporarily before modifying pg_wal
41+
command: mv "{{ pg_data }}" "{{ pg_data_lock }}"
42+
43+
- name: copy files from backup pg_wal to {{ new_pg_data }}
44+
copy:
45+
src: "{{ pg_wal_src }}"
46+
dest: "{{ new_pg_data }}"
47+
owner: postgres
48+
group: postgres
49+
mode: '0700'
50+
remote_src: yes
51+
52+
- name: backup current pg_wal
53+
command: mv "{{ pg_wal_src }}" "{{ pg_wal_src_tmp }}"
54+
55+
- name: create symlink for pg_wal
56+
file:
57+
src: "{{ pg_wal_dst }}"
58+
dest: "{{ pg_wal_src }}"
59+
state: link
60+
force: yes
61+
62+
- name: restore pg data directory after modifying pg_wal
63+
command: mv "{{ pg_data_lock }}" "{{ pg_data }}"
64+
65+
- import_tasks: pg_wal_after.yml
66+
67+
...
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/ansible-playbook
2+
---
3+
#--------------------------------------------------------------#
4+
# Modify pg_wal destination if pg_fs_wal defined [pg_wal]
5+
# new pg_wal is <pg_fs_wal>/<pg_cluster>-<pg_version>/pg_wal
6+
#--------------------------------------------------------------#
7+
8+
- name: restore postgres wal directory to default
9+
vars:
10+
tmp_wal_dir: "pg_wal.tmp-backup"
11+
pg_data_lock: "{{ pg_data }}.locked"
12+
pg_wal_src: "{{ pg_data_lock }}/pg_wal"
13+
pg_wal_src_tmp: "{{ pg_data_lock }}/{{ tmp_wal_dir }}"
14+
dbsu: "{{ pg_dbsu|default('postgres') }}"
15+
when: real_curr_pg_wal_is_link == true
16+
block:
17+
- import_tasks: pg_wal_before.yml
18+
19+
- name: lock pg data directory temporarily before restoring pg_wal
20+
command: mv "{{ pg_data }}" "{{ pg_data_lock }}"
21+
22+
- name: copy current pg_wal to {{ pg_wal_src_tmp }}
23+
become: yes
24+
copy:
25+
src: "{{ pg_wal_src }}"
26+
dest: "{{ pg_wal_src_tmp }}"
27+
owner: "{{ dbsu }}"
28+
group: "{{ dbsu }}"
29+
mode: '0700'
30+
remote_src: yes
31+
32+
- name: unlink current pg_wal
33+
file: path={{ item }} state=absent
34+
with_items:
35+
- "{{ pg_wal_src }}"
36+
37+
- name: restore default pg_wal
38+
become: yes
39+
command: mv "{{ pg_wal_src_tmp }}/pg_wal" "{{ pg_wal_src }}"
40+
41+
- name: update pg_wal owner
42+
args: { executable: /bin/bash }
43+
shell: |
44+
chown -R {{ dbsu }}:{{ dbsu }} "{{ pg_wal_src }}"
45+
chmod -R 0700 "{{ pg_wal_src }}"
46+
47+
- name: remove tmp directory after restoring pg_wal
48+
become: yes
49+
file: path={{ item }} state=absent
50+
with_items:
51+
- "{{ pg_wal_src_tmp }}"
52+
- "{{ real_curr_pg_wal }}"
53+
54+
- name: restore pg data directory after restoring pg_wal
55+
command: mv "{{ pg_data_lock }}" "{{ pg_data }}"
56+
57+
- import_tasks: pg_wal_after.yml
58+
...

0 commit comments

Comments
 (0)