diff --git a/roles/init_dbserver/tasks/setup_tde.yml b/roles/init_dbserver/tasks/setup_tde.yml index bfae2258..511b8d1a 100644 --- a/roles/init_dbserver/tasks/setup_tde.yml +++ b/roles/init_dbserver/tasks/setup_tde.yml @@ -9,7 +9,7 @@ become: true when: - edb_master_key|length > 0 - - pg_data not in edb_master_key_location + - edb_master_key_location not in pg_data - name: Store edb_master_key in a secure location ansible.builtin.copy: diff --git a/roles/init_dbserver/tasks/validate_init_dbserver.yml b/roles/init_dbserver/tasks/validate_init_dbserver.yml index 544c7f05..5fa78133 100644 --- a/roles/init_dbserver/tasks/validate_init_dbserver.yml +++ b/roles/init_dbserver/tasks/validate_init_dbserver.yml @@ -67,7 +67,7 @@ ansible.builtin.wait_for: port: "{{ pg_port }}" state: started - msg: "Port {{ pg_port }} is listening." + msg: "Port {{ pg_port }} is not listening." become: true - name: Check pg_unix_socket_directories socket diff --git a/roles/init_dbserver/tasks/verify_tde_vars.yml b/roles/init_dbserver/tasks/verify_tde_vars.yml index ced44290..56306a96 100644 --- a/roles/init_dbserver/tasks/verify_tde_vars.yml +++ b/roles/init_dbserver/tasks/verify_tde_vars.yml @@ -1,7 +1,7 @@ --- -- name: Verify edb_key_wrap_cmd and edb_key_unwrap_cmd +- name: Verify edb_key_wrap_cmd is defined or not ansible.builtin.fail: - msg: "edb_key_wrap_cmd and edb_key_unwrap_cmd are must for initializing a cluster with TDE" + msg: "edb_key_wrap_cmd and edb_key_unwrap_cmd are must for initializing a cluster" when: edb_key_wrap_cmd|length < 1 or edb_key_unwrap_cmd|length < 1 - name: Verify edb_master_key and edb_secure_master_key diff --git a/roles/setup_pgd/README.md b/roles/setup_pgd/README.md index 14753889..0bea989d 100644 --- a/roles/setup_pgd/README.md +++ b/roles/setup_pgd/README.md @@ -63,6 +63,44 @@ The rest of the variables can be configured and are available in the: * [roles/setup_pgd/vars/PG_RedHat.yml](./vars/PG_RedHat.yml) * [roles/setup_pgd/vars/EPAS_RedHat.yml](./vars/EPAS_RedHat.yml) +### `PGD Commit Scopes Configuration` + +See examples for PGD Commit Scopes available at: [EDB PGD v5](https://www.enterprisedb.com/docs/pgd/5/durability/commit-scopes/). + +The code below is part of the [roles/setup_pgd/defaults/main.yml](./defaults/main.yml), and +example for configuring two PGD commit scopes is listed below. + +The configuration requirements for PGD through the configuration setting variables are: + 1. Only one scope can be configured as default at a time. The variable to configure is: `default_group_cs` + 2. The length of the `member_nodes` for a `camo` commit scope is exactly `two` + 3. No node in `member_nodes` for either commit scope can belong to the other commit scope + 4. All nodes in `member_nodes` must belong to a `parent_group` + 5. The `cs_rule` parameter must be: valid, correctly formatted, and adhere to the correct syntax + +COMMIT AT MOST ONCE SCOPE - CAMO +```yaml +pgd_commit_scopes: + - cs_name: 'camo_scope_1' + cs_type: 'CAMO' + parent_group: 'pgd_cluster' + cs_origin_node_group: 'pgd_two_nodes' + member_nodes: ['edb-primary1', 'edb-primary2'] + default_group_cs: true + cs_rule: "ALL ( pgd_two_nodes ) ON visible CAMO DEGRADE ON (timeout=500s) TO ASYNC" +``` + +GROUP COMMIT SCOPE +```yaml +pgd_commit_scopes: + - cs_name: 'groupcommit_scope_1' + cs_type: 'GROUP_COMMIT' + parent_group: 'pgd_cluster' + cs_origin_node_group: 'pgd_remaining_nodes' + member_nodes: ['edb-primary3'] + default_group_cs: true + cs_rule: "ALL ( pgd_remaining_nodes ) GROUP COMMIT" +``` + Host Variables -------------- @@ -93,6 +131,8 @@ This role does not have any dependencies, but package repositories should have b configured beforehand with the `setup_repo` role. At least one lead primary must exist and a database cluster must be initialized on that node. + + Example Playbook ---------------- @@ -196,5 +236,6 @@ Author: * Vibhor Kumar * Hannah Stoik + * Doug Ortiz * EDB Postgres - * edb-devops@enterprisedb.com www.enterprisedb.com \ No newline at end of file + * edb-devops@enterprisedb.com www.enterprisedb.com diff --git a/roles/setup_pgd/defaults/main.yml b/roles/setup_pgd/defaults/main.yml index 967fb800..99aed98e 100644 --- a/roles/setup_pgd/defaults/main.yml +++ b/roles/setup_pgd/defaults/main.yml @@ -34,7 +34,6 @@ pass_dir: "~/.edb" pg_local_wal_archive_dir: "" edb_audit_directory: "" - # unix socket domain directories pg_unix_socket_directories: - "/var/run/postgresql" @@ -92,6 +91,29 @@ pgd_cluster_nodes: [] local_node_dsn: "" lead_primary_dsn: "" +# For CAMO Commit Scopes +max_prepared_transactions: 100 + +# The following parameters must be configured in the 'pgd_commit_scopes' list +# the values below are examples and should be adjusted to your requirements +# for CAMO +# - cs_type: 'CAMO' +# - cs_name: 'camo_scope_1' +# - parent_group: 'pgd_cluster' +# - cs_origin_node_group: 'pgd_two_nodes' +# - member_nodes: ['edb-primary1', 'edb-primary2'] +# - default_group_cs: true +# - cs_rule: "ALL ( pgd_two_nodes ) ON visible CAMO DEGRADE ON (timeout=500s) TO ASYNC" +# for GROUP_COMMIT +# - cs_type: 'GROUP_COMMIT' +# - cs_name: 'group_commit_scope_1' +# - parent_group: 'pgd_cluster' +# - cs_origin_node_group: 'pgd_gc_nodes' +# - member_nodes: ['edb-primary3'] +# - default_group_cs: true +# - cs_rule: "ALL ( pgd_remaining_nodes ) GROUP COMMIT" +pgd_commit_scopes: "" + etc_hosts_lists: [] supported_os: diff --git a/roles/setup_pgd/tasks/pg_hba_config.yml b/roles/setup_pgd/tasks/pg_hba_config.yml index 776c4f3b..11c27e51 100644 --- a/roles/setup_pgd/tasks/pg_hba_config.yml +++ b/roles/setup_pgd/tasks/pg_hba_config.yml @@ -39,7 +39,6 @@ "databases": pgd_cluster_database }, { - "contype": "host", "users": pgd_replication_user, "source": node.private_ip + "/32", "databases": "replication" @@ -57,6 +56,52 @@ run_once: true no_log: "{{ disable_logging }}" +- name: Prepare hba non ssl list for user - pg_owner + ansible.builtin.set_fact: + pg_allow_ip_addresses: >- + {{ pg_allow_ip_addresses | default([]) + [ + { + "contype": "host", + "users": pg_owner, + "source": node.private_ip + "/32", + "databases": pgd_cluster_database + }, + { + "contype": "host", + "users": pg_owner, + "source": node.private_ip + "/32", + "databases": pg_database + } + ] }} + when: not pg_ssl + loop: "{{ pgd_cluster_nodes }}" + loop_control: + loop_var: node + run_once: true + no_log: "{{ disable_logging }}" + +- name: Prepare hba ssl list for user - pg_owner + ansible.builtin.set_fact: + pg_allow_ip_addresses: >- + {{ pg_allow_ip_addresses | default([]) + [ + { + "users": pg_owner, + "source": node.private_ip + "/32", + "databases": pgd_cluster_database + }, + { + "users": pg_owner, + "source": node.private_ip + "/32", + "databases": pg_database + } + ] }} + when: pg_ssl + loop: "{{ pgd_cluster_nodes }}" + loop_control: + loop_var: node + run_once: true + no_log: "{{ disable_logging }}" + - name: Update PGD node hba config ansible.builtin.include_role: name: manage_dbserver diff --git a/roles/setup_pgd/tasks/pgd_cluster_database.yml b/roles/setup_pgd/tasks/pgd_cluster_database.yml index 0308195b..472ffdb1 100644 --- a/roles/setup_pgd/tasks/pgd_cluster_database.yml +++ b/roles/setup_pgd/tasks/pgd_cluster_database.yml @@ -7,15 +7,15 @@ pg_databases: - name: "{{ pgd_cluster_database }}" owner: "{{ pgd_cluster_database_owner }}" - when: + when: - pgd_cluster_database != pg_database - name: Ensure BDR extension exists in {{ pgd_cluster_database }} ansible.builtin.include_role: - name: manage_dbserver - tasks_from: manage_extensions + name: manage_dbserver + tasks_from: manage_extensions vars: pg_extensions: - - name: bdr - state: present - database: "{{ pgd_cluster_database }}" + - name: bdr + state: present + database: "{{ pgd_cluster_database }}" diff --git a/roles/setup_pgd/tasks/pgd_cluster_database_owner.yml b/roles/setup_pgd/tasks/pgd_cluster_database_owner.yml index de128da1..c5f8a7e3 100644 --- a/roles/setup_pgd/tasks/pgd_cluster_database_owner.yml +++ b/roles/setup_pgd/tasks/pgd_cluster_database_owner.yml @@ -27,3 +27,14 @@ pass: "{{ pgd_cluster_database_owner_password }}" role_attr_flags: replication no_log: "{{ disable_logging }}" + +- name: Update the pgpass with postgres PGD database owners password + ansible.builtin.include_role: + name: manage_dbserver + tasks_from: manage_pgpass + vars: + pg_pgpass_values: + - user: "{{ pgd_cluster_database_owner }}" + password: "{{ pgd_cluster_database_owner_password }}" + create: true + no_log: "{{ disable_logging }}" diff --git a/roles/setup_pgd/tasks/pgd_parallel_processes_parameters.yml b/roles/setup_pgd/tasks/pgd_parallel_processes_parameters.yml index d70ab3b2..27d2c1a3 100644 --- a/roles/setup_pgd/tasks/pgd_parallel_processes_parameters.yml +++ b/roles/setup_pgd/tasks/pgd_parallel_processes_parameters.yml @@ -51,8 +51,8 @@ - name: Calculate required setting for max_worker_processes ansible.builtin.set_fact: - _base_max_worker_processes: "{{ (_num_pgd_nodes | int + 1*8 + 2*2 + 2 *( _num_pgd_nodes | int - 1 )) + _twice_pgd_nodes | int }}" - + _base_max_worker_processes: "{{ (_num_pgd_nodes | int + 1*8 + 2*2 + 2 *( _num_pgd_nodes | int-1 )) + _twice_pgd_nodes | int }}" + - name: Evaluate the current setting of max_worker_processes, max_replication_slots and max_wal_senders ansible.builtin.set_fact: max_replication_slots: "{{ [ _current_max_replication_slots | int, _twice_pgd_nodes | int ] | max }}" diff --git a/roles/setup_pgd/tasks/rm_pgd.yml b/roles/setup_pgd/tasks/rm_pgd.yml index a1851061..3c35fba8 100644 --- a/roles/setup_pgd/tasks/rm_pgd.yml +++ b/roles/setup_pgd/tasks/rm_pgd.yml @@ -10,57 +10,54 @@ when: - initdb_executed block: - - name: Gather PGD node information with state - ansible.builtin.include_tasks: verify_pgd_node_group.yml - - - name: Part node from PGD cluster - ansible.builtin.include_role: - name: manage_dbserver - tasks_from: execute_sql_scripts - apply: - throttle: 1 - delegate_to: "{{ lead_primary_node.ansible_host }}" - vars: - pg_query: - - query: "SELECT bdr.part_node( node_name := '{{ pgd_local_node_name }}', - wait_for_completion := true - )" - db: "{{ pgd_cluster_database }}" - ignore_query_execution_error: false - when: - - inventory_hostname != lead_primary_node.inventory_hostname - - _pgd_db_exists == 1 - - _pgd_extension_exists == 1 - - _pgd_local_node_created == 1 - - _pgd_cluster_group_joined == 1 - - - name: Drop node from PGD cluster - ansible.builtin.include_role: - name: manage_dbserver - tasks_from: execute_sql_scripts - apply: - throttle: 1 - delegate_to: "{{ lead_primary_node.ansible_host }}" - vars: - pg_query: - - query: "SELECT bdr.part_node( node_name := '{{ pgd_local_node_name }}' )" - db: "{{ pgd_cluster_database }}" - ignore_query_execution_error: false - when: - - inventory_hostname != lead_primary_node.inventory_hostname - - _pgd_db_exists == 1 - - _pgd_extension_exists == 1 - - _pgd_local_node_created == 1 - - _pgd_cluster_group_joined == 1 - - - name: Drop database in PGD Node - ansible.builtin.include_role: - name: manage_dbserver - tasks_from: manage_db - vars: - pg_databases: - - name: "{{ pgd_cluster_database }}" - owner: "{{ pgd_cluster_database_owner }}" - state: absent - when: - - pgd_cluster_database != pg_database + - name: Gather PGD node information with state + ansible.builtin.include_tasks: verify_pgd_node_group.yml + - name: Part node from PGD cluster + ansible.builtin.include_role: + name: manage_dbserver + tasks_from: execute_sql_scripts + apply: + throttle: 1 + delegate_to: "{{ lead_primary_node.ansible_host }}" + vars: + pg_query: + - query: "SELECT bdr.part_node( node_name := '{{ pgd_local_node_name }}', + wait_for_completion := true + )" + db: "{{ pgd_cluster_database }}" + ignore_query_execution_error: false + when: + - inventory_hostname != lead_primary_node.inventory_hostname + - _pgd_db_exists == 1 + - _pgd_extension_exists == 1 + - _pgd_local_node_created == 1 + - _pgd_cluster_group_joined == 1 + - name: Drop node from PGD cluster + ansible.builtin.include_role: + name: manage_dbserver + tasks_from: execute_sql_scripts + apply: + throttle: 1 + delegate_to: "{{ lead_primary_node.ansible_host }}" + vars: + pg_query: + - query: "SELECT bdr.part_node( node_name := '{{ pgd_local_node_name }}' )" + db: "{{ pgd_cluster_database }}" + ignore_query_execution_error: false + when: + - inventory_hostname != lead_primary_node.inventory_hostname + - _pgd_db_exists == 1 + - _pgd_extension_exists == 1 + - _pgd_local_node_created == 1 + - _pgd_cluster_group_joined == 1 + - name: Drop database in PGD Node + ansible.builtin.include_role: + name: manage_dbserver + tasks_from: manage_db + vars: + pg_databases: + - name: "{{ pgd_cluster_database }}" + owner: "{{ pgd_cluster_database_owner }}" + state: absent + when: + - pgd_cluster_database != pg_database diff --git a/roles/setup_pgd/tasks/setup_pgd.yml b/roles/setup_pgd/tasks/setup_pgd.yml index dae0bad2..d2a84b6d 100644 --- a/roles/setup_pgd/tasks/setup_pgd.yml +++ b/roles/setup_pgd/tasks/setup_pgd.yml @@ -19,6 +19,13 @@ msg: "PGD version {{ pgd_version }} is not supported" when: pgd_version|int not in supported_pgd_version +- name: Import PGD verify commit setstings tasks + ansible.builtin.import_tasks: verify_commitscope_settings.yml + when: + - not validate_only|bool + - not remove_only|bool + - pgd_commit_scopes | length > 0 + - name: Verify TDE parameters based on the version and pg_type ansible.builtin.include_tasks: verify_tde_vars.yml when: @@ -32,7 +39,7 @@ - name: Reference ssl variables ansible.builtin.include_vars: edb-ssl.yml when: pg_ssl - + - name: Gather service facts ansible.builtin.service_facts: @@ -51,7 +58,7 @@ - name: Set initdb_executed to false if cluster was already initialized set_fact: - initdb_executed: false + initdb_executed: false when: - hostvars[inventory_hostname].pgd.use_physical_backup is defined - hostvars[inventory_hostname].pgd.use_physical_backup|bool @@ -102,6 +109,11 @@ - name: Configure SSL if not exists ansible.builtin.import_tasks: pg_ssl_config.yml +- name: Include tasks to setup commit scopes + ansible.builtin.include_tasks: pgd_commit_scopes.yml + when: + - pgd_commit_scopes|length > 0 + - name: Import validate tasks ansible.builtin.import_tasks: validate_setup_pgd.yml when: diff --git a/roles/setup_pgd/tasks/setup_tde.yml b/roles/setup_pgd/tasks/setup_tde.yml index 2bccd8d2..9827ed2c 100644 --- a/roles/setup_pgd/tasks/setup_tde.yml +++ b/roles/setup_pgd/tasks/setup_tde.yml @@ -9,7 +9,7 @@ become: true when: - edb_master_key|length > 0 - - pg_data not in edb_master_key_location + - edb_master_key_location not in pg_data - name: Store edb_master_key in a secure location ansible.builtin.copy: diff --git a/roles/setup_pgd/tasks/verify_tde_vars.yml b/roles/setup_pgd/tasks/verify_tde_vars.yml index ced44290..56306a96 100644 --- a/roles/setup_pgd/tasks/verify_tde_vars.yml +++ b/roles/setup_pgd/tasks/verify_tde_vars.yml @@ -1,7 +1,7 @@ --- -- name: Verify edb_key_wrap_cmd and edb_key_unwrap_cmd +- name: Verify edb_key_wrap_cmd is defined or not ansible.builtin.fail: - msg: "edb_key_wrap_cmd and edb_key_unwrap_cmd are must for initializing a cluster with TDE" + msg: "edb_key_wrap_cmd and edb_key_unwrap_cmd are must for initializing a cluster" when: edb_key_wrap_cmd|length < 1 or edb_key_unwrap_cmd|length < 1 - name: Verify edb_master_key and edb_secure_master_key