├── .gitignore
├── LICENSE
├── README.md
├── defaults
└── main.yml
├── files
└── pgpool2
├── handlers
└── main.yml
├── meta
└── main.yml
├── tasks
├── configure.yml
├── install.yml
└── main.yml
└── templates
├── pcp.conf.j2
├── pcpctl.j2
├── pgpool.conf.j2
├── pgpool2.j2
├── pgpool2_reattach.sh.j2
└── pool_hba.conf.j2
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | pgpool2
2 | =======
3 |
4 | This role configures PgPool2 PostgreSQL connection mux utility.
5 |
6 | TODO
7 | -------
8 |
9 | * Examples, variables, explanation
10 |
11 | License
12 | -------
13 |
14 | LGPL
15 |
16 | Author Information
17 | ------------------
18 |
19 | - Evgeniy Dekhtyarev, 2GIS, LLC
20 | - Alexey Medvedchikov, 2GIS, LLC
21 |
22 |
--------------------------------------------------------------------------------
/defaults/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | pgpool2_packages:
4 | - pgpool2
5 | - rsync
6 | - arping
7 | - postgresql-client
8 |
9 | pgpool2_package_state: present
10 | pgpool2_user: postgres
11 | pgpool2_group: postgres
12 | pgpool2_confdir: /etc/pgpool2
13 | pgpool2_pcp_user_name: pcpAdmin
14 | pgpool2_pcp_user_password: passw0rd
15 |
16 | pgpool2_auto_reattach: off
17 |
18 | pgpool2_hba_default:
19 | - comment: unix socket connections
20 | type: local
21 | database: all
22 | user: all
23 | address: ""
24 | method: trust
25 | - comment: local IPv4 connections
26 | type: host
27 | database: all
28 | user: all
29 | address: 127.0.0.1/32
30 | method: md5
31 |
32 | pgpool2_hba_custom: []
33 |
34 | # Enabling md5 auth on pgpool2
35 | #
36 | # pgpool2_pool_users:
37 | # - name: test
38 | # pass: 1qa2ws3ed
39 | #
40 |
41 | pgpool2_pool_users: []
42 |
43 | # pgpool2_backends:
44 | # - name: name_of_host
45 | # host: hostname or 10.10.10.10
46 | # port: 5432
47 | # weight: 1
48 | # data_directory: /var/lib/postgresql/9.4/main
49 | # flag: ALLOW_TO_FAILOVER
50 |
51 | pgpool2_backends: []
52 |
53 | # pgpool2_heartbeat_nodes:
54 | # - hostname: hostname2
55 | # address: 10.10.10.10
56 | # port: 9694
57 | # device: eth0
58 |
59 | pgpool2_heartbeat_nodes: []
60 |
61 | # pgpool2_query_nodes:
62 | # - hostname: hostname1
63 | # address: 10.10.10.10
64 | # port: 5432
65 | # wd_port: 9000
66 |
67 | pgpool2_query_nodes: []
68 |
69 | pgpool2_allow_sql_comments: off
70 | pgpool2_app_name_redirect_preference_list: ''
71 | pgpool2_arping_cmd: sudo /usr/sbin/arping -c 2 -q $_IP_$
72 | pgpool2_arping_path: /usr/bin
73 | pgpool2_authentication_timeout: 60
74 | pgpool2_black_function_list: nextval,setval
75 | pgpool2_black_memqcache_table_list: ''
76 | pgpool2_check_temp_table: on
77 | pgpool2_check_unlogged_table: on
78 | pgpool2_child_life_time: 300
79 | pgpool2_child_max_connections: 0
80 | pgpool2_clear_memqcache_on_escalation: on
81 | pgpool2_client_idle_limit: 0
82 | pgpool2_client_idle_limit_in_recovery: 0
83 | pgpool2_client_min_messages: notice
84 | pgpool2_connect_timeout: 10000
85 | pgpool2_connection_cache: on
86 | pgpool2_connection_life_time: 0
87 | pgpool2_database_redirect_preference_list: ''
88 | pgpool2_debug_level: 0
89 | pgpool2_delay_threshold: 0
90 | pgpool2_delegate_IP: ''
91 | pgpool2_enable_pool_hba: off
92 | pgpool2_fail_over_on_backend_error: on
93 | pgpool2_failback_command: ''
94 | pgpool2_failover_command: ''
95 | pgpool2_failover_if_affected_tuples_mismatch: off
96 | pgpool2_follow_master_command: ''
97 | pgpool2_health_check_database: ''
98 | pgpool2_health_check_max_retries: 0
99 | pgpool2_health_check_password: ''
100 | pgpool2_health_check_period: 0
101 | pgpool2_health_check_retry_delay: 1
102 | pgpool2_health_check_timeout: 20
103 | pgpool2_health_check_user: nobody
104 | pgpool2_hostname: ''
105 | pgpool2_if_cmd_path: '/sbin'
106 | pgpool2_if_down_cmd: sudo /sbin/ifconfig eth0:0 down
107 | pgpool2_if_up_cmd: sudo /sbin/ifconfig eth0:0 inet $_IP_$ netmask 255.255.255.0
108 | pgpool2_ignore_leading_white_space: on
109 | pgpool2_insert_lock: on
110 | pgpool2_listen_addresses: localhost
111 | pgpool2_listen_backlog_multiplier: 2
112 | pgpool2_load_balance_mode: off
113 | pgpool2_lobj_lock_table: ''
114 | pgpool2_log_connections: off
115 | pgpool2_log_destination: syslog
116 | pgpool2_log_error_verbosity: default
117 | pgpool2_log_hostname: off
118 | pgpool2_log_line_prefix: '%t: pid %p: '
119 | pgpool2_log_min_messages: warning
120 | pgpool2_log_per_node_statement: off
121 | pgpool2_log_standby_delay: none
122 | pgpool2_log_statement: off
123 | pgpool2_logdir: /var/log/postgresql
124 | pgpool2_master_slave_mode: off
125 | pgpool2_master_slave_sub_mode: slony
126 | pgpool2_max_pool: 4
127 | pgpool2_memory_cache_enabled: off
128 | pgpool2_memqcache_auto_cache_invalidation: on
129 | pgpool2_memqcache_cache_block_size: 1048576
130 | pgpool2_memqcache_expire: 0
131 | pgpool2_memqcache_max_num_cache: 1000000
132 | pgpool2_memqcache_maxcache: 409600
133 | pgpool2_memqcache_memcached_host: localhost
134 | pgpool2_memqcache_memcached_port: 11211
135 | pgpool2_memqcache_method: shmem
136 | pgpool2_memqcache_oiddir: /var/log/pgpool/oiddir
137 | pgpool2_memqcache_total_size: 67108864
138 | pgpool2_num_init_children: 32
139 | pgpool2_pcp_listen_addresses: '*'
140 | pgpool2_pcp_port: 9898
141 | pgpool2_pcp_socket_dir: /var/run/postgresql
142 | pgpool2_pid_file_name: /var/run/postgresql/pgpool.pid
143 | pgpool2_ping_path: /bin
144 | pgpool2_pool_passwd: 'passwd_file'
145 | pgpool2_port: 5433
146 | pgpool2_recovery_1st_stage_command: ''
147 | pgpool2_recovery_2nd_stage_command: ''
148 | pgpool2_recovery_password: ''
149 | pgpool2_recovery_timeout: 90
150 | pgpool2_recovery_user: nobody
151 | pgpool2_relcache_expire: 0
152 | pgpool2_relcache_size: 256
153 | pgpool2_replicate_select: off
154 | pgpool2_replication_mode: off
155 | pgpool2_replication_stop_on_mismatch: off
156 | pgpool2_reset_query_list: ABORT; DISCARD ALL
157 | pgpool2_search_primary_node_timeout: 10
158 | pgpool2_serialize_accept: off
159 | pgpool2_socket_dir: /var/run/postgresql
160 | pgpool2_sr_check_database: 'postgres'
161 | pgpool2_sr_check_password: ''
162 | pgpool2_sr_check_period: 0
163 | pgpool2_sr_check_user: nobody
164 | pgpool2_ssl: off
165 | pgpool2_ssl_ca_cert: ''
166 | pgpool2_ssl_ca_cert_dir: ''
167 | pgpool2_ssl_cert: ./server.cert
168 | pgpool2_ssl_key: ./server.key
169 | pgpool2_syslog_facility: LOCAL0
170 | pgpool2_syslog_ident: pgpool
171 | pgpool2_trusted_servers: ''
172 | pgpool2_use_watchdog: off
173 | pgpool2_wd_authkey: ''
174 | pgpool2_wd_de_escalation_command: ''
175 | pgpool2_wd_escalation_command: ''
176 | pgpool2_wd_heartbeat_deadtime: 30
177 | pgpool2_wd_heartbeat_keepalive: 2
178 | pgpool2_wd_heartbeat_port: 9694
179 | pgpool2_wd_interval: 10
180 | pgpool2_wd_ipc_socket_dir: '/tmp'
181 | pgpool2_wd_life_point: 3
182 | pgpool2_wd_lifecheck_dbname: template1
183 | pgpool2_wd_lifecheck_method: heartbeat
184 | pgpool2_wd_lifecheck_password: ''
185 | pgpool2_wd_lifecheck_query: SELECT 1
186 | pgpool2_wd_lifecheck_user: nobody
187 | pgpool2_wd_monitoring_interfaces_list: ''
188 | pgpool2_wd_port: 9000
189 | pgpool2_wd_priority: 1
190 | pgpool2_white_function_list: ''
191 | pgpool2_white_memqcache_table_list: ''
192 |
--------------------------------------------------------------------------------
/files/pgpool2:
--------------------------------------------------------------------------------
1 | Cmnd_Alias NETCFG_CMD = /sbin/ifconfig, /usr/sbin/arping
2 | postgres ALL=(ALL) NOPASSWD: NETCFG_CMD
3 |
--------------------------------------------------------------------------------
/handlers/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: start pgpool2
4 | service:
5 | name: pgpool2
6 | state: started
7 |
8 | - name: stop pgpool2
9 | service:
10 | name: pgpool2
11 | state: stopped
12 |
13 | - name: restart pgpool2
14 | service:
15 | name: pgpool2
16 | state: restarted
17 |
18 | - name: reload pgpool2
19 | service:
20 | name: pgpool2
21 | state: reloaded
22 |
23 |
--------------------------------------------------------------------------------
/meta/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 | galaxy_info:
3 | author: 2GIS IT
4 | description: Role for PostgreSQL load balancer and replication system pgpool2
5 | min_ansible_version: 2.0.0
6 | license: LGPL
7 | platforms:
8 | - name: Ubuntu
9 | versions:
10 | - all
11 | categories:
12 | - database
13 | - postgresql
14 |
15 | dependencies: []
16 |
--------------------------------------------------------------------------------
/tasks/configure.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: Create "/var/log/postgresql/" directory with necessary privileges
4 | file:
5 | dest: "/var/log/postgresql/"
6 | owner: "{{ pgpool2_user }}"
7 | group: "{{ pgpool2_group }}"
8 | mode: 0755
9 | state: directory
10 |
11 | - name: Divert PCP authentication registry file {{ pgpool2_confdir }}/pcp.conf
12 | command: dpkg-divert --quiet --local --divert {{ pgpool2_confdir }}/pcp.conf.dpkg-divert --rename {{ pgpool2_confdir }}/pcp.conf
13 | args:
14 | creates: "{{ pgpool2_confdir }}/pcp.conf.dpkg-divert"
15 |
16 | - name: PCP authentication registry file {{ pgpool2_confdir }}/pcp.conf
17 | template:
18 | src: pcp.conf.j2
19 | dest: "{{ pgpool2_confdir }}/pcp.conf"
20 | owner: "{{ pgpool2_user }}"
21 | group: "{{ pgpool2_group }}"
22 | mode: 0640
23 |
24 | - name: Divert pgpool2 main configuration file {{ pgpool2_confdir }}/pgpool.conf
25 | command: dpkg-divert --quiet --local --divert {{ pgpool2_confdir }}/pgpool.conf.dpkg-divert --rename {{ pgpool2_confdir }}/pgpool.conf
26 | args:
27 | creates: "{{ pgpool2_confdir }}/pgpool.conf.dpkg-divert"
28 |
29 | - name: pgpool2 main configuration file {{ pgpool2_confdir }}/pgpool.conf
30 | template:
31 | src: pgpool.conf.j2
32 | dest: "{{ pgpool2_confdir }}/pgpool.conf"
33 | owner: "{{ pgpool2_user }}"
34 | group: "{{ pgpool2_group }}"
35 | mode: 0640
36 | notify:
37 | - restart pgpool2
38 |
39 | - name: Divert pgpool2 pool hba file {{ pgpool2_confdir }}/pool_hba.conf
40 | command: dpkg-divert --quiet --local --divert {{ pgpool2_confdir }}/pool_hba.conf.dpkg-divert --rename {{ pgpool2_confdir }}/pool_hba.conf
41 | args:
42 | creates: "{{ pgpool2_confdir }}/pool_hba.conf.dpkg-divert"
43 |
44 | - name: pgpool2 pool hba file {{ pgpool2_confdir }}/pool_hba.conf
45 | template:
46 | src: pool_hba.conf.j2
47 | dest: "{{ pgpool2_confdir }}/pool_hba.conf"
48 | owner: "{{ pgpool2_user }}"
49 | group: "{{ pgpool2_group }}"
50 | mode: 0640
51 | notify:
52 | - restart pgpool2
53 |
54 | - name: Divert pgpool2 initscript /etc/init.d/pgpool2
55 | command: dpkg-divert --quiet --local --divert /etc/init.d/pgpool2.dpkg-divert --rename /etc/init.d/pgpool2
56 | args:
57 | creates: "/etc/init.d/pgpool2.dpkg-divert"
58 |
59 | - name: pgpool2 initscript /etc/init.d/pgpool2
60 | template:
61 | src: pgpool2.j2
62 | dest: "/etc/init.d/pgpool2"
63 | mode: 0755
64 | notify:
65 | - restart pgpool2
66 |
67 | - name: pgpool2 node reattach script
68 | template:
69 | src: pgpool2_reattach.sh.j2
70 | dest: "{{ pgpool2_confdir }}/pgpool2_reattach.sh"
71 | mode: 0700
72 |
73 | - name: try to reattach nodes every 10 seconds
74 | cron:
75 | name: "pgpool2 reattach detached backends"
76 | job: "for i in 0 1 2 3 4 5 ; do {{ pgpool2_confdir }}/pgpool2_reattach.sh >/dev/null 2>&1; sleep 10 ; done"
77 | state: "{{'present' if pgpool2_auto_reattach else 'absent'}}"
78 |
79 | - name: add users to pool_passwd
80 | copy:
81 | dest: "{{ pgpool2_confdir }}/{{ pgpool2_pool_passwd }}"
82 | owner: "{{ pgpool2_user }}"
83 | group: "{{ pgpool2_group }}"
84 | mode: 0640
85 | content: |
86 | {% for user in pgpool2_pool_users %}
87 | {{ user.name }}:md5{{ (user.pass + user.name) | hash('md5') }}
88 | {% endfor %}
89 | notify:
90 | - reload pgpool2
91 |
92 | - name: Create sudo permissions for pgpool2
93 | copy:
94 | src: pgpool2
95 | dest: "/etc/sudoers.d/pgpool2"
96 | owner: "root"
97 | group: "root"
98 | mode: 0440
99 |
100 | - name: ensure pgpool2 is running
101 | service:
102 | name: pgpool2
103 | state: started
104 |
105 |
--------------------------------------------------------------------------------
/tasks/install.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - name: install required pgpool2 packages
4 | apt:
5 | pkg: "{{ item }}"
6 | state: "{{ pgpool2_package_state }}"
7 | with_items: "{{ pgpool2_packages }}"
8 |
9 | - name: short command wrapper
10 | template:
11 | src: pcpctl.j2
12 | dest: /usr/local/bin/pcpctl
13 | owner: root
14 | group: root
15 | mode: 0755
16 |
17 |
--------------------------------------------------------------------------------
/tasks/main.yml:
--------------------------------------------------------------------------------
1 | ---
2 |
3 | - include: install.yml
4 | tags: [pgpool2, pgpool2-install]
5 |
6 | - include: configure.yml
7 | tags: [pgpool2, pgpool2-configure]
8 |
--------------------------------------------------------------------------------
/templates/pcp.conf.j2:
--------------------------------------------------------------------------------
1 | # PCP Client Authentication Configuration File
2 | # ============================================
3 | #
4 | # This file contains user ID and his password for pgpool
5 | # communication manager authentication.
6 | #
7 | # Note that users defined here do not need to be PostgreSQL
8 | # users. These users are authorized ONLY for pgpool
9 | # communication manager.
10 | #
11 | # File Format
12 | # ===========
13 | #
14 | # List one UserID and password on a single line. They must
15 | # be concatenated together using ':' (colon) between them.
16 | # No spaces or tabs are allowed anywhere in the line.
17 | #
18 | # Example:
19 | # postgres:e8a48653851e28c69d0506508fb27fc5
20 | #
21 | # Be aware that there will be no spaces or tabs at the
22 | # beginning of the line! although the above example looks
23 | # like so.
24 | #
25 | # Lines beginning with '#' (pound) are comments and will
26 | # be ignored. Again, no spaces or tabs allowed before '#'.
27 |
28 | # USERID:MD5PASSWD
29 |
30 | {{ pgpool2_pcp_user_name }}:{{ pgpool2_pcp_user_password|hash('md5') }}
31 |
32 |
--------------------------------------------------------------------------------
/templates/pcpctl.j2:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # pgpool-II pcp wrapper
4 | #
5 | # Interfaces with pgpool's pcp command-line tools to provide access to common functions for managing
6 | # load-balancing and failover.
7 | #
8 |
9 | PATH="/bin:/sbin:/usr/bin:/usr/sbin"
10 |
11 | # PCP configuration
12 | pcp_host="127.0.0.1"
13 | pcp_port="{{ pgpool2_pcp_port }}"
14 | pcp_username="{{ pgpool2_pcp_user_name }}"
15 | pcp_password="{{ pgpool2_pcp_user_password }}"
16 | pcp_timeout="10"
17 |
18 | # Health check uses psql to connect to each backend server. Specify options required to connect here
19 | psql_healthcheck_opts="-U postgres"
20 |
21 | # Default options to send to pcp commands
22 | pcp_cmd_preamble="$pcp_timeout $pcp_host $pcp_port $pcp_username $pcp_password"
23 |
24 | #
25 | # Get the node ID of the first master
26 | #
27 | _get_master_node()
28 | {
29 | # Get total number of nodes
30 | nodes=$(_get_node_count)
31 |
32 | if [ $? -gt 0 ]; then
33 | echo "ERROR: Failed getting node count: $nodes" >&2
34 | exit 1
35 | fi
36 |
37 | c=0
38 |
39 | # Loop through each node to check if it's the master
40 | while [ $c -lt $nodes ]; do
41 | if [ "$(_is_standby $c)" == "0" ]; then
42 | echo $c
43 | return 0
44 | fi
45 | let c=c+1
46 | done
47 |
48 | echo "-1"
49 | return 1
50 | }
51 |
52 | #
53 | # Checks if the node is in postgresql recovery mode (ie. if it is a slave)
54 | #
55 | _is_standby()
56 | {
57 | if [ -z $1 ]; then
58 | echo "Usage: $0 _is_standby " >&2
59 | return 99
60 | fi
61 |
62 | # Get node connection information
63 | node_info=($(_get_node_info $1))
64 |
65 | if [ $? -gt 0 ]; then
66 | echo "ERROR: Failed getting node info for node $1" >&2
67 | return 1
68 | fi
69 |
70 | export PGCONNECT_TIMEOUT=2
71 | result=$(psql $psql_healthcheck_opts -h "${node_info[0]}" -p "${node_info[1]}" -Atc "SELECT pg_is_in_recovery();" 2>/dev/null)
72 |
73 | if [ "$result" == "t" ]; then
74 | echo 1
75 | return 1
76 | else
77 | echo 0
78 | return 0
79 | fi
80 | }
81 |
82 | #
83 | # Prints whether the postgresql service on the specified node is responding.
84 | #
85 | _is_node_alive()
86 | {
87 | if [ -z $1 ]; then
88 | echo "Usage: $0 _is_node_alive " >&2
89 | return 99
90 | fi
91 |
92 | # Get node connection information
93 | node_info=($(_get_node_info $1))
94 |
95 | if [ $? -gt 0 ]; then
96 | echo "ERROR: Failed getting node info for node $1" >&2
97 | return 1
98 | fi
99 |
100 | export PGCONNECT_TIMEOUT=2
101 | result=$(psql $psql_healthcheck_opts -h "${node_info[0]}" -p "${node_info[1]}" -Atc "SELECT 1;" 2>/dev/null)
102 |
103 | if [ "$result" == "1" ]; then
104 | echo 1
105 | return 1
106 | else
107 | echo 0
108 | return 0
109 | fi
110 | }
111 |
112 | #
113 | # Prints the status of the specified node in human readable format.
114 | #
115 | _get_node_status()
116 | {
117 | if [ -z $1 ]; then
118 | echo "Usage: $0 _get_node_status " >&2
119 | return 99
120 | fi
121 |
122 | node_info=($(_get_node_info $1))
123 |
124 | if [ $? -gt 0 ]; then
125 | echo "ERROR: Failed getting node info for node $1" >&2
126 | else
127 | node_role=""
128 | node_alive=""
129 | case "$(_is_node_alive $1)" in
130 | 1)
131 | node_alive="Up"
132 | ;;
133 | *)
134 | node_alive="Down"
135 | ;;
136 | esac
137 | if [ "$node_alive" == "Up" ]; then
138 |
139 | # Find out what role this node has
140 | if [ "$(_is_standby $1)" == "1" ]; then
141 | node_role="Slave"
142 | else
143 | node_role="Master"
144 | fi
145 | fi
146 | case "${node_info[2]}" in
147 | 3)
148 | node_status="detached from pool"
149 | ;;
150 | 2)
151 | node_status="in pool and connected"
152 | ;;
153 | 1)
154 | node_status="in pool"
155 | ;;
156 | *)
157 | node_status="Unknown"
158 | ;;
159 | esac
160 |
161 | # Print status information about this node
162 | echo "Node: $1"
163 | echo "Host: ${node_info[0]}"
164 | echo "Port: ${node_info[1]}"
165 | echo "Weight: ${node_info[3]}"
166 | echo "Status: $node_alive, $node_status (${node_info[2]})"
167 | [ -n "$node_role" ] && echo "Role: $node_role"
168 | echo ""
169 | fi
170 | }
171 |
172 | #
173 | # Prints the total number of pgpool nodes.
174 | #
175 | _get_node_count() {
176 | pcp_node_count $pcp_cmd_preamble
177 | }
178 |
179 | #
180 | # Prints out node information for the specified pgpool node
181 | #
182 | _get_node_info() {
183 | if [ -z $1 ]; then
184 | echo "Usage: $0 _get_node_info " >&2
185 | return 99
186 | fi
187 | pcp_node_info $pcp_cmd_preamble $1
188 | }
189 |
190 | #
191 | # Attaches the specified node to the pool
192 | #
193 | attach() {
194 | if [ -z $1 ]; then
195 | echo "Usage: $0 attach " >&2
196 | return 99
197 | fi
198 | pcp_attach_node $pcp_cmd_preamble $1
199 | }
200 |
201 | #
202 | # Detaches the specified node from the pool
203 | #
204 | detach() {
205 | if [ -z $1 ]; then
206 | echo "Usage: $0 detach " >&2
207 | return 99
208 | fi
209 | pcp_detach_node $pcp_cmd_preamble $1
210 | }
211 |
212 | #
213 | # Recovers the specified node (restores it from current master and re-attaches)
214 | #
215 | recover() {
216 | if [ -z $1 ]; then
217 | echo "Usage: $0 recover " >&2
218 | return 99
219 | fi
220 | pcp_recovery_node $pcp_cmd_preamble $1
221 | }
222 |
223 | #
224 | # Prints out the status of all pgpool nodes in human readable form.
225 | #
226 | status() {
227 | # Get total number of nodes
228 | nodes=$(_get_node_count)
229 | if [ $? -gt 0 ]; then
230 | echo "ERROR: Failed getting node count: $nodes" >&2
231 | exit 1
232 | fi
233 | c=0
234 | # Loop through each node to retrieve info
235 | while [ $c -lt $nodes ]; do
236 | _get_node_status $c
237 | let c=c+1
238 | done
239 | }
240 |
241 | main()
242 | {
243 | if [ ! "$(type -t $1)" ]; then
244 | echo "Usage $0