128 lines
5.8 KiB
Diff
128 lines
5.8 KiB
Diff
From 2a2773d4bf8553ba64b396d567fe05506b22c94c Mon Sep 17 00:00:00 2001
|
|
From: progier389 <72748589+progier389@users.noreply.github.com>
|
|
Date: Tue, 24 Nov 2020 19:22:49 +0100
|
|
Subject: [PATCH] Issue 4449 - dsconf replication monitor fails to retrieve
|
|
database RUV - consumer (Unavailable) (#4451)
|
|
|
|
Bug Description:
|
|
|
|
"dsconf replication monitor" fails to retrieve database RUV entry from consumer and this
|
|
appears into the Cockpit web UI too.
|
|
The problem is that the bind credentials are not rightly propagated when trying to get
|
|
the consumers agreement status. Then supplier credntials are used instead and RUV
|
|
is searched anonymously because there is no bind dn in ldapi case.
|
|
|
|
Fix Description:
|
|
|
|
- Propagates the bind credentials when computing agreement status
|
|
- Add a credential cache because now a replica password could get asked several times:
|
|
when discovering the topology and
|
|
when getting the agreement maxcsn
|
|
- No testcase in 1.4.3 branch as the file modfied in master does not exists
|
|
|
|
- Add a comment about nonlocal keyword
|
|
|
|
Relates: #4449
|
|
|
|
Reviewers:
|
|
firstyear
|
|
droideck
|
|
mreynolds
|
|
|
|
Issue 4449: Add a comment about nonlocal keyword
|
|
|
|
(cherry picked from commit 73ee04fa12cd1de3a5e47c109e79e31c1aaaa2ab)
|
|
---
|
|
src/lib389/lib389/cli_conf/replication.py | 13 +++++++++++--
|
|
src/lib389/lib389/replica.py | 16 ++++++++++++----
|
|
2 files changed, 23 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/src/lib389/lib389/cli_conf/replication.py b/src/lib389/lib389/cli_conf/replication.py
|
|
index 9dbaa320a..248972cba 100644
|
|
--- a/src/lib389/lib389/cli_conf/replication.py
|
|
+++ b/src/lib389/lib389/cli_conf/replication.py
|
|
@@ -369,9 +369,16 @@ def set_repl_config(inst, basedn, log, args):
|
|
|
|
def get_repl_monitor_info(inst, basedn, log, args):
|
|
connection_data = dsrc_to_repl_monitor(DSRC_HOME, log)
|
|
+ credentials_cache = {}
|
|
|
|
# Additional details for the connections to the topology
|
|
def get_credentials(host, port):
|
|
+ # credentials_cache is nonlocal to refer to the instance
|
|
+ # from enclosing function (get_repl_monitor_info)`
|
|
+ nonlocal credentials_cache
|
|
+ key = f'{host}:{port}'
|
|
+ if key in credentials_cache:
|
|
+ return credentials_cache[key]
|
|
found = False
|
|
if args.connections:
|
|
connections = args.connections
|
|
@@ -406,8 +413,10 @@ def get_repl_monitor_info(inst, basedn, log, args):
|
|
binddn = input(f'\nEnter a bind DN for {host}:{port}: ').rstrip()
|
|
bindpw = getpass(f"Enter a password for {binddn} on {host}:{port}: ").rstrip()
|
|
|
|
- return {"binddn": binddn,
|
|
- "bindpw": bindpw}
|
|
+ credentials = {"binddn": binddn,
|
|
+ "bindpw": bindpw}
|
|
+ credentials_cache[key] = credentials
|
|
+ return credentials
|
|
|
|
repl_monitor = ReplicationMonitor(inst)
|
|
report_dict = repl_monitor.generate_report(get_credentials, args.json)
|
|
diff --git a/src/lib389/lib389/replica.py b/src/lib389/lib389/replica.py
|
|
index c2ad2104d..3d89e61fb 100644
|
|
--- a/src/lib389/lib389/replica.py
|
|
+++ b/src/lib389/lib389/replica.py
|
|
@@ -2487,9 +2487,10 @@ class ReplicationMonitor(object):
|
|
else:
|
|
self._log = logging.getLogger(__name__)
|
|
|
|
- def _get_replica_status(self, instance, report_data, use_json):
|
|
+ def _get_replica_status(self, instance, report_data, use_json, get_credentials=None):
|
|
"""Load all of the status data to report
|
|
and add new hostname:port pairs for future processing
|
|
+ :type get_credentials: function
|
|
"""
|
|
|
|
replicas_status = []
|
|
@@ -2503,6 +2504,13 @@ class ReplicationMonitor(object):
|
|
for agmt in agmts.list():
|
|
host = agmt.get_attr_val_utf8_l("nsds5replicahost")
|
|
port = agmt.get_attr_val_utf8_l("nsds5replicaport")
|
|
+ if get_credentials is not None:
|
|
+ credentials = get_credentials(host, port)
|
|
+ binddn = credentials["binddn"]
|
|
+ bindpw = credentials["bindpw"]
|
|
+ else:
|
|
+ binddn = instance.binddn
|
|
+ bindpw = instance.bindpw
|
|
protocol = agmt.get_attr_val_utf8_l('nsds5replicatransportinfo')
|
|
# Supply protocol here because we need it only for connection
|
|
# and agreement status is already preformatted for the user output
|
|
@@ -2510,9 +2518,9 @@ class ReplicationMonitor(object):
|
|
if consumer not in report_data:
|
|
report_data[f"{consumer}:{protocol}"] = None
|
|
if use_json:
|
|
- agmts_status.append(json.loads(agmt.status(use_json=True)))
|
|
+ agmts_status.append(json.loads(agmt.status(use_json=True, binddn=binddn, bindpw=bindpw)))
|
|
else:
|
|
- agmts_status.append(agmt.status())
|
|
+ agmts_status.append(agmt.status(binddn=binddn, bindpw=bindpw))
|
|
replicas_status.append({"replica_id": replica_id,
|
|
"replica_root": replica_root,
|
|
"replica_status": "Available",
|
|
@@ -2535,7 +2543,7 @@ class ReplicationMonitor(object):
|
|
initial_inst_key = f"{self._instance.config.get_attr_val_utf8_l('nsslapd-localhost')}:{self._instance.config.get_attr_val_utf8_l('nsslapd-port')}"
|
|
# Do this on an initial instance to get the agreements to other instances
|
|
try:
|
|
- report_data[initial_inst_key] = self._get_replica_status(self._instance, report_data, use_json)
|
|
+ report_data[initial_inst_key] = self._get_replica_status(self._instance, report_data, use_json, get_credentials)
|
|
except ldap.LDAPError as e:
|
|
self._log.debug(f"Connection to consumer ({supplier_hostname}:{supplier_port}) failed, error: {e}")
|
|
report_data[initial_inst_key] = [{"replica_status": f"Unavailable - {e.args[0]['desc']}"}]
|
|
--
|
|
2.26.2
|
|
|