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