]> Frank Brehm's Git Trees - pixelpark/pp-admin-tools.git/commitdiff
Adding Ansible role 389ds-ensure-repl-agmt and using it in playbooks/enable-ldap...
authorFrank Brehm <frank.brehm@pixelpark.com>
Mon, 16 Dec 2024 14:51:37 +0000 (15:51 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Mon, 16 Dec 2024 14:51:37 +0000 (15:51 +0100)
inventory/dpx-ldap-dev1.yaml
inventory/spk-ldap-stage.yaml
playbooks/disable-ldap-server.yaml
playbooks/enable-ldap-server-replication.yaml
roles/389ds-ensure-repl-agmt/defaults/main.yaml [new file with mode: 0644]
roles/389ds-ensure-repl-agmt/tasks/main.yaml [new file with mode: 0644]
roles/389ds-ensure-repl-agmt/tasks/repl-agmts-suffix.yaml [new file with mode: 0644]

index 4c592ce6c745c389ca7c909d48c5e62cdbce2730..35d884bf836fff3063295df54efa6256c8e04e78 100644 (file)
@@ -55,6 +55,12 @@ all:
               - 'o=isp'
           'blaBlub':
             ensure: absent
+        ds389_repl_agmt_frac_list:
+          - 'authorityRevocationList'
+          - 'accountUnlockTime'
+          - 'memberOf'
+        ds389_repl_agmt_frac_list_total:
+          - 'memberOf'
 
         # Tempporary
         # ds389_logging_config: false
@@ -70,6 +76,13 @@ all:
   vars:
     ansible_user: root
     haproxy_backend_name: 'be-ldap-dev1'
+    ds389_repl_agmt_port: 389
+    ds389_repl_agmt_conn_proto: 'LDAP'
+    ds389_repl_agmt_bind_method: 'SIMPLE'
+    ds389_repl_agmt_frac_list:
+      - 'authorityRevocationList'
+      - 'accountUnlockTime'
+      - 'memberOf'
 
 
 # vim: filetype=yaml
index bc88321c4eab10626554cdfaa8abe783ccf0f3ce..4be4adb1aadbb758c7ac3b5074eba76c52e21d1f 100644 (file)
@@ -11,6 +11,16 @@ all:
           replica_id: 2
           slapd_instance: stage-ds02-spk
           ldap_uri: 'ldaps://stage-ds02-spk.spk.pixelpark.net'
+      vars:
+        ds389_repl_agmt_port: 389
+        ds389_repl_agmt_conn_proto: 'LDAP'
+        ds389_repl_agmt_bind_method: 'SIMPLE'
+        ds389_repl_agmt_frac_list:
+          - 'authorityRevocationList'
+          - 'accountUnlockTime'
+          - 'memberOf'
+        ds389_repl_agmt_frac_list_total:
+          - 'memberOf'
     haproxy_servers:
       hosts:
         live-ldap-hap01.spk.pixelpark.net: {}
index c1c4198822e223979948485a4d5f8443d811ea55..ebe3e29dd0e55545f9286764131db37a525932bb 100644 (file)
         state: stopped
       when: ldapserver_to_disable == inventory_hostname
 
-    - name: "Retrieve all backends from {{ ldapserver_to_disable | quote  }}."
+    - name: "Retrieve all backends."
       ansible.builtin.shell: "dsconf {{ slapd_instance | quote  }} backend suffix list"
       register: backend_suffix_list
       changed_when: false
index 022280b8e26544b2b82e79b75c1213b470ec4026..09cd1c4708f934d6b63b6c5fca7cf41c5999ded3 100644 (file)
@@ -78,5 +78,9 @@
       include_role:
         name: '389ds-enable-replication'
 
+    - name: 'Ensuring all necessary replication agreements.'
+      include_role:
+        name: '389ds-ensure-repl-agmt'
+
 
 # vim: filetype=yaml
diff --git a/roles/389ds-ensure-repl-agmt/defaults/main.yaml b/roles/389ds-ensure-repl-agmt/defaults/main.yaml
new file mode 100644 (file)
index 0000000..0e4b9ae
--- /dev/null
@@ -0,0 +1,55 @@
+---
+
+# Sets the port number of the replica
+ds389_repl_agmt_port: 389
+
+# Sets the replication connection protocol: LDAP, LDAPS, or StartTLS
+# Possible values: 'LDAP', 'LDAPS', 'StartTLS'
+ds389_repl_agmt_conn_proto: 'LDAP'
+
+# Sets the bind method.
+# Possible values: "SIMPLE", "SSLCLIENTAUTH", "SASL/DIGEST", or "SASL/GSSAPI"
+ds389_repl_agmt_bind_method: 'SIMPLE'
+
+# Sets the list of attributes to NOT replicate to the consumer during incremental updates
+ds389_repl_agmt_frac_list:
+  - 'authorityRevocationList'
+  - 'accountUnlockTime'
+  - 'memberOf'
+
+# Sets the list of attributes to NOT replicate during a total initialization
+ds389_repl_agmt_frac_list_total:
+  - 'memberOf'
+
+# Sets a list of attributes that are removed from updates only if the event would otherwise be empty.
+ds389_repl_agmt_strip_list:
+  - 'modifiersName'
+  - 'modifyTimestmap'
+
+# Sets the replication update schedule: 'HHMM-HHMM DDDDDDD' D = 0-6 (Sunday - Saturday).
+# ds389_repl_agmt_schedule: '0500-2100 0123456'
+ds389_repl_agmt_schedule: ~
+
+# Sets the timeout used for replication connections
+ds389_repl_agmt_conn_timeout: 300
+
+# Sets a timeout in seconds on how long to wait before stopping replication when the server is under load
+ds389_repl_agmt_protocol_timeout: 600
+
+# Sets the amount of time in milliseconds the server waits if the consumer is not ready before resending data.
+ds389_repl_agmt_wait_async_results: 3000
+
+# Sets the amount of time in seconds a supplier should wait
+# after a consumer sends back a busy response before making another attempt to acquire access.
+ds389_repl_agmt_busy_wait_time: 300
+
+# Sets the amount of time in seconds a supplier should wait between update sessions.
+ds389_repl_agmt_session_pause_time: ~
+
+# Sets the maximum number of entries and updates sent by a supplier, which are not acknowledged by the consumer.
+ds389_repl_agmt_flow_control_window: ~
+
+# Sets the time in milliseconds to pause after reaching the number of entries and updates set in 'ds389_repl_agmt_flow_control_window'.
+ds389_repl_agmt_flow_control_pause: ~
+
+# vim: filetype=yaml
diff --git a/roles/389ds-ensure-repl-agmt/tasks/main.yaml b/roles/389ds-ensure-repl-agmt/tasks/main.yaml
new file mode 100644 (file)
index 0000000..4b6bfaa
--- /dev/null
@@ -0,0 +1,41 @@
+---
+
+- debug:
+    msg: "Ensuring existence of all necessary replication agreements."
+
+- name: "Retrieve all backends."
+  ansible.builtin.shell: "dsconf {{ slapd_instance | quote  }} backend suffix list"
+  register: get_backend_suffix_list
+  changed_when: false
+  check_mode: false
+
+- name: "Show current get_backend_suffix_list"
+  debug:
+    var: get_backend_suffix_list
+    verbosity: 2
+
+- name: "Set backend variable"
+  no_log: true
+  set_fact:
+    suffix_names: "{{ get_backend_suffix_list.stdout_lines | map('regex_replace', '\\s+\\(.+\\)\\s*$', '') | list }}"
+    backend_names: "{{ get_backend_suffix_list.stdout_lines | map('regex_replace', '^.*\\((.+)\\)\\s*$', '\\1') | list }}"
+
+- name: "Set suffixes dict"
+  no_log: true
+  set_fact:
+    suffixes: "{{ dict( suffix_names | zip(backend_names) ) }}"
+
+- name: "Show current suffixes"
+  debug:
+    var: suffixes
+    verbosity: 1
+
+- name: "Ensure replication agreements on all suffixes."
+  include_tasks: 'repl-agmts-suffix.yaml'
+  when: item[1] != inventory_hostname
+  vars:
+    suffix: "{{ item[0].key }}"
+    other_host: "{{ item[1] }}"
+  loop: "{{ suffixes | dict2items | product( ansible_play_batch ) | list }}"
+
+# vim: filetype=yaml
diff --git a/roles/389ds-ensure-repl-agmt/tasks/repl-agmts-suffix.yaml b/roles/389ds-ensure-repl-agmt/tasks/repl-agmts-suffix.yaml
new file mode 100644 (file)
index 0000000..ad5abef
--- /dev/null
@@ -0,0 +1,152 @@
+---
+
+- debug:
+    msg: "Ensuring existence of replication agreement from {{ inventory_hostname | quote }} \
+          to {{ other_host | quote }} for suffix {{ suffix | quote }}."
+    verbosity: 0
+
+- name: "Set fact agreement_name."
+  set_fact:
+    agreement_name: "{{ slapd_instance }} to {{ other_host }} agreement"
+
+- name: "Show replication agreement name for suffix {{ suffix | quote }}."
+  debug:
+    var: agreement_name
+    verbosity: 0
+
+- name: "Get list of current replication agreements for suffix {{ suffix | quote }}."
+  ansible.builtin.shell: "dsconf {{ slapd_instance | quote }} repl-agmt list --suffix {{ suffix | quote }} | \
+                          grep -i '^cn: ' | sed -e 's/^cn:[    ]*//i' -e 's/[  ]*$//'"
+  register: get_repl_agmt_list
+  changed_when: false
+  check_mode: false
+
+- name: "Show current get_repl_agmt_list"
+  debug:
+    var: get_repl_agmt_list
+    verbosity: 2
+
+- name: "Predefine repl_agmt_exists"
+  set_fact:
+    repl_agmt_exists: false
+
+- name: "Search for current replication agreement."
+  set_fact:
+    repl_agmt_exists: true
+  when: (line | lower) == (agreement_name | lower)
+  loop: "{{ get_repl_agmt_list.stdout_lines }}"
+  loop_control:
+    loop_var: line
+
+- name: "Replication agreement already exists."
+  when: repl_agmt_exists == true
+  block:
+
+    - debug:
+        msg: "The replication agreement {{ agreement_name | quote }} is already existing for suffix {{ suffix | quote }}."
+
+- name: "Create replication agreement."
+  # when: repl_agmt_exists != true
+  block:
+
+    - debug:
+        var: hostvars[other_host]
+        verbosity: 3
+
+    - name: "Predefine variables."
+      set_fact:
+        used_port: "{{ ds389_repl_agmt_port }}"
+        used_proto: "{{ ds389_repl_agmt_conn_proto }}"
+        used_frac_list: "{{ ds389_repl_agmt_frac_list }}"
+        used_frac_list_total: "{{ ds389_repl_agmt_frac_list_total }}"
+
+    - name: "Get port from other host."
+      set_fact:
+        used_port: "{{ hostvars[other_host].ds389_repl_agmt_port }}"
+      when: "'ds389_repl_agmt_port' in hostvars[other_host] and hostvars[other_host].ds389_repl_agmt_port is not empty"
+
+    - name: "Get connection protocol from other host."
+      set_fact:
+        used_conn_proto: "{{ hostvars[other_host].ds389_repl_agmt_conn_proto }}"
+      when: "'ds389_repl_agmt_conn_proto' in hostvars[other_host] and hostvars[other_host].ds389_repl_agmt_conn_proto is not empty"
+
+    - name: "Get fractional list from other host."
+      set_fact:
+        used_frac_list: "{{ hostvars[other_host].ds389_repl_agmt_frac_list }}"
+      when: "'ds389_repl_agmt_frac_list' in hostvars[other_host] and hostvars[other_host].ds389_repl_agmt_frac_list is not empty"
+
+    - name: "Get fractional list for total from other host."
+      set_fact:
+        used_frac_list_total: "{{ hostvars[other_host].ds389_repl_agmt_frac_list_total }}"
+      when: "'ds389_repl_agmt_frac_list_total' in hostvars[other_host] and hostvars[other_host].ds389_repl_agmt_frac_list_total is not empty"
+
+    - name: "Define command for creating replication agreement."
+      set_fact:
+        create_cmd: "dsconf {{ slapd_instance | quote }} repl-agmt create --suffix {{ suffix | quote }} \
+                     --host {{ other_host | quote }} --port {{ used_port | int }} \
+                     --conn-protocol {{ used_conn_proto | quote }} \
+                     --bind-dn {{ replication_manager_dn | quote }} \
+                     --bind-passwd-file {{ replication_manager_password_file | quote }} \
+                     --bind-method {{ ds389_repl_agmt_bind_method | quote }} \
+                     --frac-list {{ used_frac_list | map('quote') | join(' ') }} \
+                     --frac-list-total {{ used_frac_list_total | map('quote') | join(' ') }}"
+
+    - name: "Add --strip-list to command for creating replication agreement."
+      set_fact:
+        create_cmd: "{{ create_cmd }} --strip-list {{ ds389_repl_agmt_strip_list | map('quote') | join(' ') }}"
+      when: ds389_repl_agmt_strip_list is not empty
+
+    - name: "Add --schedule to command for creating replication agreement."
+      set_fact:
+        create_cmd: "{{ create_cmd }} --schedule {{ ds389_repl_agmt_schedule | quote }}"
+      when: ds389_repl_agmt_schedule is not empty
+
+    - name: "Add --conn-timeout to command for creating replication agreement."
+      set_fact:
+        create_cmd: "{{ create_cmd }} --conn-timeout {{ ds389_repl_agmt_conn_timeout | quote }}"
+      when: ds389_repl_agmt_conn_timeout is not empty
+
+    - name: "Add --protocol-timeout to command for creating replication agreement."
+      set_fact:
+        create_cmd: "{{ create_cmd }} --protocol-timeout {{ ds389_repl_agmt_protocol_timeout | quote }}"
+      when: ds389_repl_agmt_protocol_timeout is not empty
+
+    - name: "Add --wait-async-results to command for creating replication agreement."
+      set_fact:
+        create_cmd: "{{ create_cmd }} --wait-async-results {{ ds389_repl_agmt_wait_async_results | quote }}"
+      when: ds389_repl_agmt_wait_async_results is not empty
+
+    - name: "Add --busy-wait-time to command for creating replication agreement."
+      set_fact:
+        create_cmd: "{{ create_cmd }} --busy-wait-time {{ ds389_repl_agmt_busy_wait_time | quote }}"
+      when: ds389_repl_agmt_busy_wait_time is not empty
+
+    - name: "Add --session-pause-time to command for creating replication agreement."
+      set_fact:
+        create_cmd: "{{ create_cmd }} --session-pause-time {{ cds389_repl_agmt_session_pause_time | quote }}"
+      when: cds389_repl_agmt_session_pause_time is not empty
+
+    - name: "Add --flow-control-window to command for creating replication agreement."
+      set_fact:
+        create_cmd: "{{ create_cmd }} --flow-control-window {{ ds389_repl_agmt_flow_control_window | quote }}"
+      when: ds389_repl_agmt_flow_control_window is not empty
+
+    - name: "Add --flow-control-pause to command for creating replication agreement."
+      set_fact:
+        create_cmd: "{{ create_cmd }} --flow-control-pause {{ ds389_repl_agmt_flow_control_pause | quote }}"
+      when: ds389_repl_agmt_flow_control_pause is not empty
+
+    - name: "Complete command for creating replication agreement."
+      set_fact:
+        create_cmd: "{{ create_cmd }} {{ agreement_name | quote }}"
+
+    - name: "Command for creating replication agreement:"
+      debug:
+        var: create_cmd
+        verbosity: 0
+
+    - name: "Finally create the replication agreement."
+      ansible.builtin.shell: "{{ create_cmd }}"
+
+
+# vim: filetype=yaml