mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
correct management of one directional segments
this patch contains the following improvements: check for existing segments works for all combinations of one directional and bidirectional segments rdns of replication agreements generated from one directional segments are preserves after merging of segments, so that deletion of the segment deletes the corresponding replication agreements Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
This commit is contained in:
parent
ffd6b039a7
commit
a86f2b3c62
@ -177,11 +177,12 @@ void ipa_topo_cfg_host_add(Slapi_Entry *hostentry);
|
||||
void ipa_topo_cfg_host_del(Slapi_Entry *hostentry);
|
||||
TopoReplicaHost *ipa_topo_cfg_host_find(TopoReplica *tconf, char *host, int lock);
|
||||
TopoReplicaHost *ipa_topo_cfg_host_new(char *newhost);
|
||||
int ipa_topo_util_segm_dir(char *direction);
|
||||
TopoReplicaSegment *
|
||||
ipa_topo_cfg_segment_find(char *repl_root, char *leftHost, char *rightHost);
|
||||
ipa_topo_cfg_segment_find(char *repl_root, char *leftHost, char *rightHosti, int dir);
|
||||
TopoReplicaSegment *
|
||||
ipa_topo_cfg_replica_segment_find(TopoReplica *tconf, char *leftHost,
|
||||
char *rightHost, int lock);
|
||||
char *rightHost, int dir, int lock);
|
||||
void ipa_topo_cfg_segment_set_visited(TopoReplica *tconf, TopoReplicaSegment *tsegm);
|
||||
void ipa_topo_cfg_segment_add(TopoReplica *tconf, TopoReplicaSegment *tsegm);
|
||||
void ipa_topo_cfg_segment_del(TopoReplica *tconf, TopoReplicaSegment *tsegm);
|
||||
|
@ -545,19 +545,25 @@ ipa_topo_cfg_host_del(Slapi_Entry *hostentry)
|
||||
}
|
||||
|
||||
TopoReplicaSegment *
|
||||
ipa_topo_cfg_replica_segment_find(TopoReplica *replica, char *leftHost, char *rightHost, int lock)
|
||||
ipa_topo_cfg_replica_segment_find(TopoReplica *replica, char *leftHost, char *rightHost, int dir, int lock)
|
||||
{
|
||||
TopoReplicaSegment *tsegm = NULL;
|
||||
TopoReplicaSegmentList *segments = NULL;
|
||||
int reverse_dir = SEGMENT_BIDIRECTIONAL;
|
||||
|
||||
if (dir == SEGMENT_LEFT_RIGHT) reverse_dir = SEGMENT_RIGHT_LEFT;
|
||||
else if (dir == SEGMENT_RIGHT_LEFT) reverse_dir = SEGMENT_LEFT_RIGHT;
|
||||
else reverse_dir = SEGMENT_BIDIRECTIONAL;
|
||||
|
||||
if (lock) slapi_lock_mutex(replica->repl_lock);
|
||||
segments = replica->repl_segments;
|
||||
while (segments) {
|
||||
|
||||
tsegm = segments->segm;
|
||||
if ( (!strcasecmp(leftHost,tsegm->from) && !strcasecmp(rightHost,tsegm->to) &&
|
||||
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_LEFT_RIGHT)) ||
|
||||
(tsegm->direct & dir)) ||
|
||||
(!strcasecmp(leftHost,tsegm->to) && !strcasecmp(rightHost,tsegm->from) &&
|
||||
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_RIGHT_LEFT))) {
|
||||
(tsegm->direct & reverse_dir))) {
|
||||
break;
|
||||
}
|
||||
tsegm = NULL;
|
||||
@ -680,7 +686,7 @@ ipa_topo_cfg_segment_dup(TopoReplicaSegment *orig)
|
||||
}
|
||||
|
||||
TopoReplicaSegment *
|
||||
ipa_topo_cfg_segment_find(char *repl_root, char *leftHost, char *rightHost)
|
||||
ipa_topo_cfg_segment_find(char *repl_root, char *leftHost, char *rightHost, int dir)
|
||||
{
|
||||
TopoReplicaSegment *tsegm = NULL;
|
||||
TopoReplica *replica = NULL;
|
||||
@ -689,7 +695,7 @@ ipa_topo_cfg_segment_find(char *repl_root, char *leftHost, char *rightHost)
|
||||
|
||||
replica = ipa_topo_cfg_replica_find(repl_root, 0);
|
||||
if (replica) {
|
||||
tsegm = ipa_topo_cfg_replica_segment_find(replica,leftHost,rightHost, 1);
|
||||
tsegm = ipa_topo_cfg_replica_segment_find(replica,leftHost,rightHost, dir, 1);
|
||||
}
|
||||
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
||||
return tsegm;
|
||||
@ -731,7 +737,7 @@ ipa_topo_cfg_segment_add(TopoReplica *replica, TopoReplicaSegment *tsegm)
|
||||
slapi_lock_mutex(replica->repl_lock);
|
||||
if (ipa_topo_cfg_replica_segment_find(replica,
|
||||
tsegm->from,
|
||||
tsegm->to, 0)){
|
||||
tsegm->to, tsegm->direct, 0)){
|
||||
/* already exists: log error */
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_cfg_segment_add: error: segment exists: %s\n",
|
||||
|
@ -129,14 +129,16 @@ ipa_topo_post_mod(Slapi_PBlock *pb)
|
||||
int result = SLAPI_PLUGIN_SUCCESS;
|
||||
int entry_type;
|
||||
Slapi_Entry *mod_entry = NULL;
|
||||
Slapi_Entry *pre_entry = NULL;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"--> ipa_topo_post_mod\n");
|
||||
|
||||
/* 1. get entry */
|
||||
slapi_pblock_get(pb,SLAPI_ENTRY_POST_OP,&mod_entry);
|
||||
slapi_pblock_get(pb,SLAPI_ENTRY_PRE_OP,&pre_entry);
|
||||
|
||||
if (mod_entry == NULL) {
|
||||
if (mod_entry == NULL || pre_entry == NULL) {
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "no entry\n");
|
||||
return (1);
|
||||
}
|
||||
@ -155,8 +157,8 @@ ipa_topo_post_mod(Slapi_PBlock *pb)
|
||||
case TOPO_SEGMENT_ENTRY: {
|
||||
LDAPMod **mods;
|
||||
TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(mod_entry);
|
||||
TopoReplicaSegment *tsegm;
|
||||
tsegm = ipa_topo_util_find_segment(tconf, mod_entry);
|
||||
TopoReplicaSegment *tsegm = NULL;
|
||||
if (tconf) tsegm = ipa_topo_util_find_segment(tconf, pre_entry);
|
||||
if (tsegm == NULL) {
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_post_mod - segment to be modified does not exist\n");
|
||||
|
@ -306,7 +306,13 @@ ipa_topo_check_segment_is_valid(Slapi_PBlock *pb)
|
||||
*/
|
||||
char *leftnode = slapi_entry_attr_get_charptr(add_entry,"ipaReplTopoSegmentLeftNode");
|
||||
char *rightnode = slapi_entry_attr_get_charptr(add_entry,"ipaReplTopoSegmentRightNode");
|
||||
if (0 == strcasecmp(leftnode,rightnode)) {
|
||||
char *dir = slapi_entry_attr_get_charptr(add_entry,"ipaReplTopoSegmentDirection");
|
||||
if (strcasecmp(dir,SEGMENT_DIR_BOTH) && strcasecmp(dir,SEGMENT_DIR_LEFT_ORIGIN) &&
|
||||
strcasecmp(dir,SEGMENT_DIR_RIGHT_ORIGIN)) {
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"segment has unknown direction: %s\n", dir);
|
||||
rc = 1;
|
||||
} else if (0 == strcasecmp(leftnode,rightnode)) {
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"segment is self referential\n");
|
||||
rc = 1;
|
||||
@ -322,6 +328,7 @@ ipa_topo_check_segment_is_valid(Slapi_PBlock *pb)
|
||||
}
|
||||
slapi_ch_free_string(&leftnode);
|
||||
slapi_ch_free_string(&rightnode);
|
||||
slapi_ch_free_string(&dir);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -319,20 +319,38 @@ ipa_topo_util_agmt_from_entry(Slapi_Entry *entry, char *replRoot, char *fromHost
|
||||
}
|
||||
return agmt;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_util_segm_dir(char *direction)
|
||||
{
|
||||
int dir = -1;
|
||||
if (strcasecmp(direction,SEGMENT_DIR_BOTH) == 0){
|
||||
dir = SEGMENT_BIDIRECTIONAL;
|
||||
} else if (strcasecmp(direction,SEGMENT_DIR_LEFT_ORIGIN) == 0) {
|
||||
dir = SEGMENT_LEFT_RIGHT;
|
||||
} else if (strcasecmp(direction,SEGMENT_DIR_RIGHT_ORIGIN) == 0) {
|
||||
dir = SEGMENT_RIGHT_LEFT;
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
TopoReplicaSegment *
|
||||
ipa_topo_util_find_segment(TopoReplica *conf, Slapi_Entry *entry)
|
||||
{
|
||||
char *leftHost;
|
||||
char *rightHost;
|
||||
char *direction;
|
||||
TopoReplicaSegment *segment = NULL;
|
||||
|
||||
leftHost = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentLeftNode");
|
||||
rightHost = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentRightNode");
|
||||
direction = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentDirection");
|
||||
|
||||
segment = ipa_topo_cfg_segment_find(conf->repl_root, leftHost, rightHost);
|
||||
segment = ipa_topo_cfg_segment_find(conf->repl_root, leftHost, rightHost, ipa_topo_util_segm_dir(direction));
|
||||
|
||||
slapi_ch_free((void **)&leftHost);
|
||||
slapi_ch_free((void **)&rightHost);
|
||||
slapi_ch_free((void **)&direction);
|
||||
return segment;
|
||||
}
|
||||
|
||||
@ -450,13 +468,63 @@ ipa_topo_util_conf_from_entry(Slapi_Entry *entry)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_util_set_agmt_rdn(TopoReplicaAgmt *topo_agmt, Slapi_Entry *repl_agmt)
|
||||
{
|
||||
const Slapi_DN *agmt_dn = slapi_entry_get_sdn_const(repl_agmt);
|
||||
Slapi_RDN *agmt_rdn = slapi_rdn_new();
|
||||
slapi_sdn_get_rdn(agmt_dn, agmt_rdn);
|
||||
const char *agmt_rdn_str = slapi_rdn_get_rdn(agmt_rdn);
|
||||
if (strcasecmp(agmt_rdn_str, topo_agmt->rdn)) {
|
||||
slapi_ch_free_string(&topo_agmt->rdn);
|
||||
topo_agmt->rdn = slapi_ch_strdup(agmt_rdn_str);
|
||||
}
|
||||
slapi_rdn_free(&agmt_rdn);
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_util_update_agmt_rdn(TopoReplica *conf, TopoReplicaAgmt *agmt,
|
||||
char *toHost)
|
||||
{
|
||||
int rc = 0;
|
||||
Slapi_PBlock *pb = NULL;
|
||||
Slapi_Entry **entries = NULL;
|
||||
char *filter;
|
||||
|
||||
pb = slapi_pblock_new();
|
||||
filter = slapi_ch_smprintf("(&(objectclass=nsds5replicationagreement)"
|
||||
"(nsds5replicaroot=%s)(nsds5replicahost=%s))",
|
||||
conf->repl_root, toHost);
|
||||
slapi_search_internal_set_pb(pb, "cn=config", LDAP_SCOPE_SUB,
|
||||
filter, NULL, 0, NULL, NULL,
|
||||
ipa_topo_get_plugin_id(), 0);
|
||||
slapi_search_internal_pb(pb);
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
|
||||
if (rc == 0) {
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
||||
}
|
||||
|
||||
if (NULL == entries || NULL == entries[0]) {
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_util_update_agmt_rdn: "
|
||||
"no agreements found\n");
|
||||
} else {
|
||||
ipa_topo_util_set_agmt_rdn(agmt, entries[0]);
|
||||
}
|
||||
|
||||
slapi_free_search_results_internal(pb);
|
||||
slapi_ch_free_string(&filter);
|
||||
slapi_pblock_destroy(pb);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_util_update_agmt_list(TopoReplica *conf, TopoReplicaSegmentList *repl_segments)
|
||||
{
|
||||
int rc = 0;
|
||||
int i;
|
||||
int nentries;
|
||||
Slapi_Entry **entries;
|
||||
Slapi_Entry **entries = NULL;
|
||||
Slapi_Entry *repl_agmt;
|
||||
Slapi_PBlock *pb = NULL;
|
||||
char *filter;
|
||||
@ -482,7 +550,7 @@ ipa_topo_util_update_agmt_list(TopoReplica *conf, TopoReplicaSegmentList *repl_s
|
||||
if (NULL == entries || NULL == entries[0]) {
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_util_update_agmts_list: "
|
||||
"no agrements found\n");
|
||||
"no agreements found\n");
|
||||
goto update_only;
|
||||
}
|
||||
}
|
||||
@ -511,15 +579,7 @@ ipa_topo_util_update_agmt_list(TopoReplica *conf, TopoReplicaSegmentList *repl_s
|
||||
targetHost);
|
||||
if (topo_agmt) {
|
||||
/* compare rdns, use rdn of existing agreement */
|
||||
const Slapi_DN *agmt_dn = slapi_entry_get_sdn_const(repl_agmt);
|
||||
Slapi_RDN *agmt_rdn = slapi_rdn_new();
|
||||
slapi_sdn_get_rdn(agmt_dn, agmt_rdn);
|
||||
const char *agmt_rdn_str = slapi_rdn_get_rdn(agmt_rdn);
|
||||
if (strcasecmp(agmt_rdn_str, topo_agmt->rdn)) {
|
||||
slapi_ch_free_string(&topo_agmt->rdn);
|
||||
topo_agmt->rdn = slapi_ch_strdup(agmt_rdn_str);
|
||||
}
|
||||
slapi_rdn_free(&agmt_rdn);
|
||||
ipa_topo_util_set_agmt_rdn(topo_agmt, repl_agmt);
|
||||
|
||||
/* update agreement params which are different in the segment*/
|
||||
char *segm_attr_val;
|
||||
@ -742,10 +802,29 @@ ipa_topo_util_segment_update(TopoReplica *repl_conf,
|
||||
case LDAP_MOD_REPLACE:
|
||||
if (0 == strcasecmp(mods[i]->mod_type,"ipaReplTopoSegmentDirection")) {
|
||||
if (0 == strcasecmp(mods[i]->mod_bvalues[0]->bv_val,"both")) {
|
||||
TopoReplicaSegment *ex_segm;
|
||||
if (segment->direct == SEGMENT_LEFT_RIGHT) {
|
||||
segment->right = ipa_topo_cfg_agmt_dup_reverse(segment->left);
|
||||
ex_segm = ipa_topo_cfg_replica_segment_find(repl_conf, segment->from, segment->to,
|
||||
SEGMENT_RIGHT_LEFT, 1);
|
||||
if (ex_segm) {
|
||||
segment->right = ipa_topo_cfg_agmt_dup(ex_segm->left?ex_segm->left:ex_segm->right);
|
||||
} else {
|
||||
segment->right = ipa_topo_cfg_agmt_dup_reverse(segment->left);
|
||||
if(0 == strcasecmp(fromHost,segment->right->origin)) {
|
||||
ipa_topo_util_update_agmt_rdn(repl_conf, segment->right, segment->right->target);
|
||||
}
|
||||
}
|
||||
} else if (segment->direct == SEGMENT_RIGHT_LEFT) {
|
||||
segment->left = ipa_topo_cfg_agmt_dup_reverse(segment->right);
|
||||
ex_segm = ipa_topo_cfg_replica_segment_find(repl_conf, segment->from, segment->to,
|
||||
SEGMENT_LEFT_RIGHT, 1);
|
||||
if (ex_segm) {
|
||||
segment->left = ipa_topo_cfg_agmt_dup(ex_segm->left?ex_segm->left:ex_segm->right);
|
||||
} else {
|
||||
segment->left = ipa_topo_cfg_agmt_dup_reverse(segment->right);
|
||||
if(0 == strcasecmp(fromHost,segment->left->origin)) {
|
||||
ipa_topo_util_update_agmt_rdn(repl_conf, segment->left, segment->left->target);
|
||||
}
|
||||
}
|
||||
}
|
||||
segment->direct = SEGMENT_BIDIRECTIONAL;
|
||||
} else {
|
||||
@ -982,6 +1061,32 @@ ipa_topo_util_segm_order(TopoReplicaSegment *l, TopoReplicaSegment *r)
|
||||
return strcasecmp(l->from, r->from);
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_util_segment_do_merge(TopoReplica *tconf,
|
||||
TopoReplicaSegment *ex_segm, TopoReplicaSegment *tsegm)
|
||||
{
|
||||
/* we are merging two one directional segments, tehy can have been created in
|
||||
* several ways and we need to find the agreeemnt to copy
|
||||
*/
|
||||
if (NULL == tsegm->right) {
|
||||
if(ex_segm->left) {
|
||||
tsegm->right = ipa_topo_cfg_agmt_dup(ex_segm->left);
|
||||
} else {
|
||||
tsegm->right = ipa_topo_cfg_agmt_dup(ex_segm->right);
|
||||
}
|
||||
} else {
|
||||
if(ex_segm->left) {
|
||||
tsegm->left = ipa_topo_cfg_agmt_dup(ex_segm->left);
|
||||
} else {
|
||||
tsegm->left = ipa_topo_cfg_agmt_dup(ex_segm->right);
|
||||
}
|
||||
}
|
||||
ipa_topo_util_segm_update(tconf,ex_segm, SEGMENT_OBSOLETE);
|
||||
ipa_topo_util_segm_remove(tconf, ex_segm);
|
||||
ipa_topo_util_segm_update(tconf,tsegm, SEGMENT_BIDIRECTIONAL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ipa_topo_util_segment_merge(TopoReplica *tconf,
|
||||
TopoReplicaSegment *tsegm)
|
||||
@ -996,7 +1101,13 @@ ipa_topo_util_segment_merge(TopoReplica *tconf,
|
||||
return;
|
||||
}
|
||||
|
||||
ex_segm = ipa_topo_cfg_replica_segment_find(tconf, tsegm->to, tsegm->from, 1 /*lock*/);
|
||||
if (tsegm->direct == SEGMENT_LEFT_RIGHT) {
|
||||
ex_segm = ipa_topo_cfg_replica_segment_find(tconf, tsegm->from, tsegm->to,
|
||||
SEGMENT_RIGHT_LEFT, 1 /*lock*/);
|
||||
} else {
|
||||
ex_segm = ipa_topo_cfg_replica_segment_find(tconf, tsegm->from, tsegm->to,
|
||||
SEGMENT_LEFT_RIGHT, 1 /*lock*/);
|
||||
}
|
||||
if (ex_segm == NULL) return;
|
||||
|
||||
/* to avoid conflicts merging has to be done only once and
|
||||
@ -1005,17 +1116,11 @@ ipa_topo_util_segment_merge(TopoReplica *tconf,
|
||||
*/
|
||||
if (ipa_topo_util_segm_order(ex_segm, tsegm) > 0) {
|
||||
if (0 == strcasecmp(tsegm->from,ipa_topo_get_plugin_hostname())) {
|
||||
tsegm->right = ipa_topo_cfg_agmt_dup(ex_segm->left);
|
||||
ipa_topo_util_segm_update(tconf,ex_segm, SEGMENT_OBSOLETE);
|
||||
ipa_topo_util_segm_remove(tconf, ex_segm);
|
||||
ipa_topo_util_segm_update(tconf,tsegm, SEGMENT_BIDIRECTIONAL);
|
||||
ipa_topo_util_segment_do_merge(tconf, ex_segm, tsegm);
|
||||
}
|
||||
} else {
|
||||
if (0 == strcasecmp(ex_segm->from,ipa_topo_get_plugin_hostname())) {
|
||||
ex_segm->right = ipa_topo_cfg_agmt_dup(tsegm->left);
|
||||
ipa_topo_util_segm_update(tconf,tsegm, SEGMENT_OBSOLETE);
|
||||
ipa_topo_util_segm_remove(tconf, tsegm);
|
||||
ipa_topo_util_segm_update(tconf,ex_segm, SEGMENT_BIDIRECTIONAL);
|
||||
ipa_topo_util_segment_do_merge(tconf, tsegm, ex_segm);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1221,8 +1326,8 @@ ipa_topo_util_delete_segments_for_host(char *repl_root, char *delhost)
|
||||
int check_reverse = 1;
|
||||
|
||||
/* first check if a segment originating at localhost exists */
|
||||
segm = ipa_topo_cfg_segment_find(repl_root,
|
||||
ipa_topo_get_plugin_hostname(), delhost);
|
||||
segm = ipa_topo_cfg_segment_find(repl_root, ipa_topo_get_plugin_hostname(),
|
||||
delhost, SEGMENT_LEFT_RIGHT);
|
||||
if (segm) {
|
||||
/* mark segment as removable, bypass connectivity check when replicated */
|
||||
if (segm->direct == SEGMENT_BIDIRECTIONAL) check_reverse = 0;
|
||||
@ -1233,8 +1338,8 @@ ipa_topo_util_delete_segments_for_host(char *repl_root, char *delhost)
|
||||
}
|
||||
/* check if one directional segment in reverse direction exists */
|
||||
if (check_reverse) {
|
||||
segm = ipa_topo_cfg_segment_find(repl_root,
|
||||
delhost, ipa_topo_get_plugin_hostname());
|
||||
segm = ipa_topo_cfg_segment_find(repl_root, delhost,
|
||||
ipa_topo_get_plugin_hostname(), SEGMENT_LEFT_RIGHT);
|
||||
if (segm) {
|
||||
ipa_topo_util_segm_update(tconf,segm, SEGMENT_REMOVED);
|
||||
/* mark and delete, no repl agmt on this server */
|
||||
|
Loading…
Reference in New Issue
Block a user