From 3de52afae39266e096841b8b6b9d184434bc89ec Mon Sep 17 00:00:00 2001 From: Thierry Bordaz Date: Fri, 28 Oct 2022 13:15:45 +0200 Subject: [PATCH] Issue 1700097 - IdM creates pairs of left-right replicas rather than bidirectional for "domain" suffix Bug description: tentative fix to fetch config on demand Fix description: relates: https://bugzilla.redhat.com/show_bug.cgi?id=1700097 Reviewed by: --- daemons/ipa-slapi-plugins/topology/topology.h | 2 + .../ipa-slapi-plugins/topology/topology_cfg.c | 15 ++++--- .../ipa-slapi-plugins/topology/topology_pre.c | 2 +- .../topology/topology_util.c | 42 ++++++++++++++++--- 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/daemons/ipa-slapi-plugins/topology/topology.h b/daemons/ipa-slapi-plugins/topology/topology.h index 4ea2b368f27..245d9585a89 100644 --- a/daemons/ipa-slapi-plugins/topology/topology.h +++ b/daemons/ipa-slapi-plugins/topology/topology.h @@ -95,6 +95,7 @@ typedef struct topo_replica { char *total_attrs; char *repl_attrs; TopoReplicaSegmentList *repl_segments; + PRBool repl_segments_fetched; TopoReplicaHost *hosts; } TopoReplica; @@ -311,6 +312,7 @@ Slapi_Entry *ipa_topo_util_get_entry(char *dn); int ipa_topo_util_modify(Slapi_DN *entrySDN, Slapi_Mods *smods); char *ipa_topo_util_get_pluginhost(void); TopoReplica *ipa_topo_util_get_replica_conf(char *repl_root); +TopoReplicaSegmentList *ipa_topo_util_get_repl_segments(TopoReplica *replica); TopoReplicaSegmentList *ipa_topo_util_get_replica_segments(TopoReplica *replica); void ipa_topo_util_set_domain_level(void); void ipa_topo_util_reset_init(char *repl_root); diff --git a/daemons/ipa-slapi-plugins/topology/topology_cfg.c b/daemons/ipa-slapi-plugins/topology/topology_cfg.c index 5365ab1ac63..303e8f7859d 100644 --- a/daemons/ipa-slapi-plugins/topology/topology_cfg.c +++ b/daemons/ipa-slapi-plugins/topology/topology_cfg.c @@ -1,4 +1,6 @@ +#include + #include "topology.h" /* two static data structures to hold the @@ -562,7 +564,7 @@ ipa_topo_cfg_replica_segment_find(TopoReplica *replica, char *leftHost, char *ri else reverse_dir = SEGMENT_BIDIRECTIONAL; if (lock) slapi_lock_mutex(replica->repl_lock); - segments = replica->repl_segments; + segments = ipa_topo_util_get_repl_segments(replica); while (segments) { tsegm = segments->segm; @@ -716,7 +718,7 @@ ipa_topo_cfg_segment_set_visited(TopoReplica *replica, TopoReplicaSegment *vsegm char *rightHost = vsegm->to; slapi_lock_mutex(replica->repl_lock); - segments = replica->repl_segments; + segments = ipa_topo_util_get_repl_segments(replica); while (segments) { tsegm = segments->segm; if ( ((strcasecmp(leftHost,tsegm->from) == 0) && (strcasecmp(rightHost,tsegm->to) == 0) && @@ -754,10 +756,10 @@ ipa_topo_cfg_segment_add(TopoReplica *replica, TopoReplicaSegment *tsegm) slapi_ch_calloc(1,sizeof(TopoReplicaSegmentList)); seglist->visited = 0; seglist->segm = tsegm; - if (replica->repl_segments == NULL) { + if (ipa_topo_util_get_repl_segments(replica) == NULL) { replica->repl_segments = seglist; } else { - seglist->next = replica->repl_segments; + seglist->next = ipa_topo_util_get_repl_segments(replica); replica->repl_segments = seglist; } slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, @@ -775,7 +777,7 @@ ipa_topo_cfg_segment_del(TopoReplica *tconf, TopoReplicaSegment *tsegm) slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_cfg_segment_del: %s\n", tsegm->name); slapi_lock_mutex(tconf->repl_lock); - segment = tconf->repl_segments; + segment = ipa_topo_util_get_repl_segments(tconf); while (segment) { if (segment->segm == tsegm) { if (prev == NULL) { @@ -802,6 +804,7 @@ ipa_topo_cfg_replica_new(void) if (topoRepl) { topoRepl->next = NULL; topoRepl->repl_segments = NULL; + topoRepl->repl_segments_fetched = PR_FALSE; topoRepl->repl_root = NULL; topoRepl->strip_attrs = NULL; topoRepl->total_attrs = NULL; @@ -848,7 +851,7 @@ ipa_topo_cfg_replica_free(TopoReplica *tconf) slapi_destroy_mutex(tconf->repl_lock); slapi_ch_free_string(&tconf->shared_config_base); slapi_ch_free_string(&tconf->repl_root); - seg = tconf->repl_segments; + seg = ipa_topo_util_get_repl_segments(tconf); while (seg) { seg_next = seg->next; ipa_topo_cfg_segment_free(seg->segm); diff --git a/daemons/ipa-slapi-plugins/topology/topology_pre.c b/daemons/ipa-slapi-plugins/topology/topology_pre.c index f1e99be169f..9f01aa97e6d 100644 --- a/daemons/ipa-slapi-plugins/topology/topology_pre.c +++ b/daemons/ipa-slapi-plugins/topology/topology_pre.c @@ -238,7 +238,7 @@ ipa_topo_connection_fanout(TopoReplica *tconf, TopoReplicaSegment *tseg) slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_connection_fanout for segment: %s\n",tseg->name); /* lock it */ - TopoReplicaSegmentList *seglist = tconf->repl_segments; + TopoReplicaSegmentList *seglist = ipa_topo_util_get_repl_segments(tconf); while (seglist) { segm = seglist->segm; if (strcasecmp(segm->name, tseg->name) != 0) { diff --git a/daemons/ipa-slapi-plugins/topology/topology_util.c b/daemons/ipa-slapi-plugins/topology/topology_util.c index 3f9bf137fdc..4d72555db1b 100644 --- a/daemons/ipa-slapi-plugins/topology/topology_util.c +++ b/daemons/ipa-slapi-plugins/topology/topology_util.c @@ -1,3 +1,5 @@ +#include +#include #include "topology.h" @@ -204,6 +206,30 @@ ipa_topo_util_get_replica_conf(char *repl_root) return topoRepl; } +/* This routine just return the segments associated to + * a given replica. + * In addition it logs a warning that this segments (in memory) may + * be out of sync (shared config entries) because ipa_topo_util_start + * was called with a delay (DS startup or total init). + */ +TopoReplicaSegmentList * +ipa_topo_util_get_repl_segments(TopoReplica *replica) +{ + if (!replica->repl_segments_fetched) { + int nb_segments = 0; + TopoReplicaSegmentList *segm = replica->repl_segments; + for(; segm; nb_segments++) segm = segm->next; + + slapi_log_error(SLAPI_LOG_WARNING, IPA_TOPO_PLUGIN_SUBSYSTEM, + "ipa_topo_util_get_repl_segments: " + "in memory replica %d segments for %s " + "can differ from the shared tree. You may try to reduce %s\n", + nb_segments, replica->repl_root, CONFIG_ATTR_STARTUP_DELAY); + } + return replica->repl_segments; +} + + TopoReplicaSegmentList * ipa_topo_util_get_replica_segments(TopoReplica *replica) { @@ -241,7 +267,8 @@ ipa_topo_util_get_replica_segments(TopoReplica *replica) } slapi_free_search_results_internal(pb); slapi_pblock_destroy(pb); - return replica->repl_segments; + replica->repl_segments_fetched = PR_TRUE; + return ipa_topo_util_get_repl_segments(replica); } int @@ -512,7 +539,7 @@ ipa_topo_util_segm_modify (TopoReplica *tconf, void ipa_topo_util_remove_init_attr(TopoReplica *repl_conf, TopoReplicaAgmt *topo_agmt) { - TopoReplicaSegmentList *seglist = repl_conf->repl_segments; + TopoReplicaSegmentList *seglist = ipa_topo_util_get_repl_segments(repl_conf); TopoReplicaSegment *segment = NULL; char *dirattr = NULL; @@ -644,7 +671,7 @@ ipa_topo_util_update_agmt_list(TopoReplica *conf, TopoReplicaSegmentList *repl_s "cannot read targethost: error %d\n", rc); continue; } - topo_agmt = ipa_topo_util_find_segment_agmt(conf->repl_segments, + topo_agmt = ipa_topo_util_find_segment_agmt(ipa_topo_util_get_repl_segments(conf), ipa_topo_get_plugin_hostname(), targetHost); if (topo_agmt) { @@ -720,7 +747,7 @@ ipa_topo_util_update_agmt_list(TopoReplica *conf, TopoReplicaSegmentList *repl_s /* check if segments not covered by agreement exist * add agreeement */ - ipa_topo_util_missing_agmts_add_list(conf, conf->repl_segments, + ipa_topo_util_missing_agmts_add_list(conf, ipa_topo_util_get_repl_segments(conf), ipa_topo_get_plugin_hostname()); error_return: @@ -1190,6 +1217,11 @@ ipa_topo_util_segment_merge(TopoReplica *tconf, /* merging is only done on one of the endpoints of the segm */ return; } + if (!tconf->repl_segments_fetched) { + /* Let's fetch the in memory segment from the shared config area */ + ipa_topo_util_get_replica_segments(tconf); + } + if (tsegm->direct == SEGMENT_LEFT_RIGHT) { ex_segm = ipa_topo_cfg_replica_segment_find(tconf, tsegm->from, tsegm->to, @@ -1374,7 +1406,7 @@ ipa_topo_util_update_segments_for_host(TopoReplica *conf, char *hostname) } /* segment has been recreated and added during postp of segment_write * but the correct agreement rdn was lost, set it now */ - topo_agmt = ipa_topo_util_find_segment_agmt(conf->repl_segments, + topo_agmt = ipa_topo_util_find_segment_agmt(ipa_topo_util_get_repl_segments(conf), ipa_topo_get_plugin_hostname(), hostname); if (topo_agmt) {