replication_manager_dn: 'cn=Replication Manager,cn=config'
replication_manager_password_file: '/root/.private/dirserv-repl-mngr-pwd.txt'
replication_manager_idle_timeout: 0
+ ds389_replication_role: supplier
ldaps_validate_certs: false
# ds389_plugin_attr_uniq_purge: false
ds389_plugin_attr_uniq_attributes:
replication_manager_password_file: '/root/.private/dirserv-repl-mngr-pwd.txt'
replication_manager_idle_timeout: 0
ldaps_validate_certs: false
+ ds389_replication_role: supplier
ds389_plugin_attr_uniq_purge: false
ds389_plugin_attr_uniq_attributes:
'uid':
replication_manager_dn: 'cn=Replication Manager,cn=config'
replication_manager_password_file: '/root/.private/dirserv-repl-mngr-pwd.txt'
replication_manager_idle_timeout: 0
+ ds389_replication_role: supplier
ldaps_validate_certs: false
# ds389_plugin_attr_uniq_purge: false
ds389_plugin_attr_uniq_attributes:
subtrees:
- 'dc=spk,dc=pixelpark,dc=net'
ds389_plugin_account_policy_config: false
+ ds389_replication_role: supplier
# Temporary
# ds389_logging_config: false
subtrees:
- 'dc=spk,dc=pixelpark,dc=net'
ds389_plugin_account_policy_config: false
+ ds389_replication_role: supplier
# Temporary
# ds389_logging_config: false
gather_facts: false
vars_prompt:
- name: ldap_server
- prompt: "On wich LDAP server should replication be enabled"
+ prompt: "To wich LDAP server should should the complete replica be mirrord (a.k.a. replication init - leave empty to skip it)"
private: false
tasks:
ansible.builtin.set_fact:
found_ldapserver: false
- - name: "Searching for LDAP server '{{ ldapserver_to_enable }}' ..."
+ - name: 'Actions, if no ldapserver_to_enable was set.'
+ when: ldapserver_to_enable is empty
+ block:
+
+ - name: "End play because ldapserver_to_enable was not set."
+ ansible.builtin.meta: end_play
+ when: ("No LDAP server set, where the replica should be mirrored to." | warn_me())
+
+ - name: "Searching for LDAP server {{ ldapserver_to_enable | quote }} ..."
ansible.builtin.set_fact:
found_ldapserver: true
when: "item == ldapserver_to_enable"
- name: "Fail for non LDAP server."
ansible.builtin.fail:
- msg: "The given host '{{ ldapserver_to_enable }}' is not a valid LDAP server."
+ msg: "The given host {{ ldapserver_to_enable | quote }} is not a valid LDAP server."
when: found_ldapserver == false
- name: "Initial checks for the HAProxy."
hosts: haproxy_servers
gather_facts: false
+ any_errors_fatal: true
tasks:
include_role:
name: haproxy-check-initial
-- name: "Enabling Replication on a particular LDAP server."
+- name: "Enabling Replication on all LDAP servers."
hosts: ldap_servers
gather_facts: false
+ any_errors_fatal: true
tasks:
var: ldapserver_to_enable
verbosity: 0
+ - name: "Enable replica on all backends."
+ include_role:
+ name: '389ds-enable-replication'
+
# vim: filetype=yaml
import re
+from ansible.utils.display import Display
+
try:
from collections.abc import Sequence
except ImportError:
'compare_lc_list': self.compare_lc_list,
'bool_to_on_off': self.bool_to_on_off,
'bool_to_yes_no': self.bool_to_yes_no,
+ 'warn_me': self.warn_filter,
}
# ------------------
return 'yes'
return 'no'
+ # ------------------
+ def warn_filter(self, message, **kwargs):
+ """Emit a warning."""
+ Display().warning(message)
+ return message
+
# =============================================================================
verbosity: 0
- name: "Finally remove replication from suffix {{ suffix | quote }}."
- ansible.builtin.shell: "dsconf {{ slapd_instance | quote }} disable --suffix {{ suffix | quote }}"
+ ansible.builtin.shell: "dsconf {{ slapd_instance | quote }} replication disable --suffix {{ suffix | quote }}"
when: suffix_is_replicated == true
# vim: filetype=yaml
--- /dev/null
+---
+
+# Checking all preferences for replication
+
+- name: "Check existence of replication Id of host."
+ ansible.builtin.fail:
+ msg: "No replica Id for host {{ inventory_hostname | quote }} given."
+ when: replica_id is empty
+
+- name: "Convert replication Id of host to int."
+ ansible.builtin.set_fact:
+ replica_id: "{{ replica_id | int }}"
+
+- name: "Current replication Id of host:"
+ debug:
+ var: replica_id
+ verbosity: 0
+
+- name: "Checking value of replication Id of host."
+ ansible.builtin.fail:
+ msg: "Invalid value for replication Id {{ replica_id }} - must be greater than 0 and less or equal then {{ max_replication_id }}."
+ when: (replica_id | int) <= 0 or (replica_id | int) >= max_replication_id
+
+- name: "Checking replication Id of host to those of other hosts."
+ ansible.builtin.fail:
+ msg: "Replication Id {{ replica_id }} also used on host {{ other_host | quote }}."
+ when: other_host != inventory_hostname and hostvars[other_host].replica_id == replica_id
+ loop: "{{ groups['ldap_servers'] }}"
+ loop_control:
+ loop_var: other_host
+
+- name: "Define replication role of this host, if not given."
+ set_fact:
+ ds389_replication_role: "{{ ds389_default_replication_role }}"
+ when: ds389_replication_role is empty
+
+- name: "Checking replication role of this host."
+ ansible.builtin.fail:
+ msg: "Wrong replication role '{{ ds389_replication_role }}', must be one of .'supplier', 'hub' or 'consumer'"
+ when: "ds389_replication_role not in ['supplier', 'hub', 'consumer']"
+
+- name: "Replication role of this host:"
+ debug:
+ var: ds389_replication_role
+ verbosity: 0
+
+- name: "Checking replication Bind DN"
+ ansible.builtin.fail:
+ msg: "Bind DN of replication manager not set."
+ when: replication_manager_dn is empty
+
+- name: "Checking existence of variable replication_manager_password_file."
+ ansible.builtin.fail:
+ msg: "Password file replication_manager_password_file not set."
+ when: replication_manager_password_file is empty
+
+- name: "Get file stat of Replication manager password file ..."
+ ansible.builtin.stat:
+ path: "{{ replication_manager_password_file }}"
+ register: repl_mngr_password_file
+
+- name: "File stat of Replication manager password file: "
+ debug:
+ var: repl_mngr_password_file
+ verbosity: 3
+
+- name: "Check existence of Replication manager password file."
+ ansible.builtin.fail:
+ msg: "The Replication manager password file {{ replication_manager_password_file | quote }} does not exists."
+ when: repl_mngr_password_file.stat.exists != true
+
+- name: "Checking, whether Replication manager password file is a regular file."
+ ansible.builtin.fail:
+ msg: "The path {{ replication_manager_password_file | quote }} for the Replication manager password file is not a regular file."
+ when: repl_mngr_password_file.stat.isreg != true
+
+# vim: filetype=yaml
--- /dev/null
+---
+
+- name: "Checking all preferences for replication..."
+ include_tasks: 'check.yaml'
+
+- name: "Get a list of all replicated Suffixes."
+ ansible.builtin.shell: "dsconf {{ slapd_instance | quote }} replication list"
+ check_mode: false
+ changed_when: false
+ register: list_of_replicated_suffixes
+
+- name: "Show current list_of_replicated_suffixes"
+ debug:
+ var: list_of_replicated_suffixes
+ verbosity: 2
+
+- name: "Retrieve all backends from {{ ldapserver_to_disable | quote }}."
+ ansible.builtin.shell: "dsconf {{ slapd_instance | quote }} backend suffix list"
+ register: backend_suffix_list
+ changed_when: false
+ check_mode: false
+
+- name: "Show current backend_suffix_list"
+ debug:
+ var: backend_suffix_list
+ verbosity: 2
+
+- name: "Set backend variable"
+ no_log: true
+ set_fact:
+ suffix_names: "{{ backend_suffix_list.stdout_lines | map('regex_replace', '\\s+\\(.+\\)\\s*$', '') | list }}"
+ backend_names: "{{ 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: 0
+
+- name: "Enable replication for particular suffix."
+ include_tasks: 'suffix.yaml'
+ vars:
+ suffix: "{{ item.key }}"
+ loop: "{{ suffixes | dict2items | list }}"
+
+# vim: filetype=yaml
--- /dev/null
+---
+
+# Enabling replication for a particular suffix
+
+- name: "Ensure enabled replication for particular suffix."
+ debug:
+ var: suffix
+ verbosity: 0
+
+- name: "Get a list of all replicated Suffixes."
+ ansible.builtin.shell: "dsconf {{ slapd_instance | quote }} replication list"
+ check_mode: false
+ changed_when: false
+ register: list_of_replicated_suffixes
+
+- name: "Show current list_of_replicated_suffixes"
+ debug:
+ var: list_of_replicated_suffixes
+ verbosity: 2
+
+- name: "Set fact suffix_is_replicated."
+ no_log: true
+ set_fact:
+ suffix_is_replicated: false
+
+- name: "Searching for suffix {{ suffix | quote }} in the list of replicated suffixes."
+ set_fact:
+ suffix_is_replicated: true
+ when: ( this_line | regex_replace('^\\s*') | regex_replace('\\s*$') ) == suffix
+ loop: "{{ list_of_replicated_suffixes.stdout_lines }}"
+ loop_control:
+ loop_var: this_line
+
+- name: "Check existing replication."
+ when: suffix_is_replicated == true
+ block:
+
+ - name: "Get current replication Id."
+ ansible.builtin.shell: "dsconf {{ slapd_instance | quote }} replication get --suffix {{ suffix | quote }} | \
+ grep -P -i '^nsDS5ReplicaId:' | sed -e 's/^nsDS5ReplicaId:[ ]*//i'"
+ check_mode: false
+ changed_when: false
+ register: get_cur_replication_id
+
+ - name: "Show get_cur_replication_id"
+ debug:
+ var: get_cur_replication_id
+ verbosity: 2
+
+ - name: "Set fact cur_replication_id."
+ set_fact:
+ cur_replication_id: "{{ get_cur_replication_id.stdout | int }}"
+
+ - name: "Show cur_replication_id"
+ debug:
+ var: cur_replication_id
+ verbosity: 1
+
+ - name: "Check current replication Id against the configured one"
+ ansible.builtin.fail:
+ msg: "The configured replication Id {{ replica_id | int }} does not match the existing \
+ replication Id {{ cur_replication_id | int ]] of suffix {{ suffix | quote }}."
+ when: (replica_id | int) != (cur_replication_id | int)
+
+- name: "Enable relication."
+ when: suffix_is_replicated == false
+ block:
+
+ - name: "Define command for enabling replication."
+ set_fact:
+ cmd_enable_replica: "dsconf {{ slapd_instance | quote }} replication enable --suffix {{ suffix | quote }} \
+ --role {{ ds389_replication_role | quote }} \
+ --replica-id {{ replica_id | int }} \
+ --bind-dn {{ replication_manager_dn | quote }} \
+ --bind-passwd-file {{ replication_manager_password_file | quote }}"
+
+ - name: "Command for enabling replication:"
+ debug:
+ var: cmd_enable_replica
+ verbosity: 0
+
+ - name: "Finally enabling replication."
+ ansible.builtin.shell: "{{ cmd_enable_replica }}"
+
+# vim: filetype=yaml
--- /dev/null
+---
+
+max_replication_id: 32767
+ds389_default_replication_role: 'supplier'
+
+# vim: filetype=yaml