freeipa/daemons/ipa-slapi-plugins/topology/topology_util.c
Ludwig Krispenz b3c2a4b810 make sure the agremment rdn match the rdn used in the segment
Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
2015-06-11 13:58:02 +02:00

1446 lines
52 KiB
C

#include "topology.h"
int
ipa_topo_util_modify(Slapi_DN *entrySDN, Slapi_Mods *smods)
{
int rc = 0;
Slapi_PBlock *mod_pb;
LDAPMod **mods;
mod_pb = slapi_pblock_new();
slapi_pblock_init(mod_pb);
mods = (slapi_mods_get_ldapmods_passout(smods));
slapi_modify_internal_set_pb_ext(mod_pb, entrySDN, mods, NULL, NULL,
ipa_topo_get_plugin_id(), 0);
slapi_modify_internal_pb(mod_pb);
slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
slapi_pblock_destroy(mod_pb);
if (rc != 0)
{
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_modify: "
"failed to modify entry (%s): error %d\n", slapi_sdn_get_dn(entrySDN), rc);
}
return rc;
}
Slapi_Entry *
ipa_topo_util_get_entry (char *dn)
{
int rc = 0;
Slapi_Entry *res_entry = NULL;
Slapi_Entry **entries;
Slapi_PBlock *pb = NULL;
pb = slapi_pblock_new();
slapi_search_internal_set_pb(pb, dn, LDAP_SCOPE_BASE,
"objectclass=*", 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_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_get_entry: "
"unable to read entry (%s): error %d\n", dn, rc);
} else {
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
if (NULL == entries || NULL == entries[0]) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_get_entry: entry not found: %s\n", dn);
} else {
res_entry = slapi_entry_dup(entries[0]);
}
}
slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
return res_entry;
}
/*
* the plugin needs to determine if segments in the shared topology
* affect the instance it is running in. There are many ways to determine
* this "pluginhost":
* - get the machines hostname
* - define hostname in plugin conf
* - use nsslapd-localhost from cn=config
* - ...
* This first version will use the nsslapd-localhost
*/
char *
ipa_topo_util_get_pluginhost(void)
{
int rc = 0;
Slapi_Entry **entries;
Slapi_PBlock *pb = NULL;
char *host = NULL;
char *host_attrs[] = {"nsslapd-localhost", NULL};
pb = slapi_pblock_new();
slapi_search_internal_set_pb(pb, "cn=config", LDAP_SCOPE_BASE,
"objectclass=*", host_attrs, 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_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_get_localhost: "
"unable to read server configuration: error %d\n", rc);
} else {
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
if (NULL == entries || NULL == entries[0]) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_get_localhost: server configuration missing\n");
} else {
host = slapi_entry_attr_get_charptr(entries[0], "nsslapd-localhost");
}
}
slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
return host;
}
void
ipa_topo_util_check_plugin_active(void)
{
if (ipa_topo_get_min_domain_level() <= ipa_topo_get_domain_level()) {
ipa_topo_set_plugin_active(1);
} else {
ipa_topo_set_plugin_active(0);
}
}
void
ipa_topo_util_set_domain_level(void)
{
int rc = 0;
Slapi_Entry **entries;
Slapi_PBlock *pb = NULL;
pb = slapi_pblock_new();
slapi_search_internal_set_pb(pb, ipa_topo_get_domain_level_entry(),
LDAP_SCOPE_BASE,
"objectclass=*", 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_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_set_domain_level: "
"failed to lookup domain level entry: error %d\n", rc);
} else {
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_set_domain_level: domain level"
" entry does not exist, use default domain level of 0\n");
ipa_topo_set_domain_level(NULL);
} else {
char *domlevel = slapi_entry_attr_get_charptr(entries[0], "ipaDomainLevel");
ipa_topo_set_domain_level(domlevel);
slapi_ch_free_string(&domlevel);
}
}
slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
}
TopoReplica *
ipa_topo_util_get_replica_conf(char *repl_root)
{
int rc = 0;
Slapi_Entry **entries;
Slapi_PBlock *pb = NULL;
char *filter;
TopoReplica *topoRepl = NULL;
pb = slapi_pblock_new();
filter = slapi_ch_smprintf("(ipaReplTopoConfRoot=%s)",repl_root);
slapi_search_internal_set_pb(pb, ipa_topo_get_plugin_shared_topo(),
LDAP_SCOPE_ONELEVEL,
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_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_get_replica_conf: "
"no replica configuration found: error %d\n", rc);
} else {
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
if (NULL == entries || NULL == entries[0]) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_get_replica_conf: "
"server configuration missing\n");
} else {
topoRepl = ipa_topo_cfg_replica_new();
topoRepl->shared_config_base =
slapi_ch_strdup(slapi_entry_get_dn_const(entries[0]));
topoRepl->repl_root = slapi_ch_strdup(repl_root);
}
}
slapi_ch_free_string(&filter);
slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
if (0 != ipa_topo_cfg_replica_add(topoRepl)) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_get_replica_conf: "
"replica already exists\n");
ipa_topo_cfg_replica_free(topoRepl);
topoRepl = NULL;
}
return topoRepl;
}
TopoReplicaSegmentList *
ipa_topo_util_get_replica_segments(TopoReplica *replica)
{
TopoReplicaSegment *repl_segment = NULL;
int rc = 0;
Slapi_Entry **entries;
Slapi_PBlock *pb = NULL;
char *filter;
pb = slapi_pblock_new();
filter = "objectclass=*";
slapi_search_internal_set_pb(pb, replica->shared_config_base,
LDAP_SCOPE_ONELEVEL, 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_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_get_replica_segments: "
"no replica configuration found: error %d\n", rc);
} else {
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_get_replica_segments: no segments found\n");
} else {
/* get number of segments and allocate */
int i = 0;
for (i=0;entries[i];i++) {
repl_segment = ipa_topo_util_segment_from_entry(replica, entries[i]);
ipa_topo_cfg_segment_add(replica, repl_segment);
}
}
}
slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
return replica->repl_segments;
}
int
ipa_topo_util_setup_servers(void)
{
int rc = 0;
Slapi_Entry **entries;
Slapi_PBlock *pb = NULL;
char *filter;
pb = slapi_pblock_new();
filter = "objectclass=*";
slapi_search_internal_set_pb(pb,ipa_topo_get_plugin_shared_hosts(),
LDAP_SCOPE_ONELEVEL,
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 == LDAP_NO_SUCH_OBJECT) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_setup_servers: "
"search for servers failed (continuing): error %d\n", rc);
/* masters not yet configured, continue plugin startup */
rc = 0;
} else if (rc != 0) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_setup_servers: "
"search for servers failed: error %d\n", rc);
} else {
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_setup_servers: no servers found\n");
} else {
int i = 0;
for (i=0;entries[i];i++) {
ipa_topo_cfg_host_add(entries[i]);
}
}
}
slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
return rc;
}
TopoReplicaAgmt *
ipa_topo_util_agmt_from_entry(Slapi_Entry *entry, char *replRoot, char *fromHost,
char *toHost, char *direction)
{
TopoReplicaAgmt *agmt = NULL;
char **mattrs = NULL;
char *mattr = NULL;
char *mval = NULL;
int i;
agmt = (TopoReplicaAgmt *) slapi_ch_calloc(1,sizeof(TopoReplicaAgmt));
agmt->origin = slapi_ch_strdup(fromHost);
agmt->target = slapi_ch_strdup(toHost);
agmt->repl_root = slapi_ch_strdup(replRoot);
/* use std agmt rdn, it may be updated when matching real agmt is found */
agmt->rdn = ipa_topo_agmt_std_rdn(toHost);
mattrs = ipa_topo_get_plugin_managed_attrs();
for (i=0; mattrs[i]; i++) {
mattr = slapi_ch_smprintf("%s;%s",mattrs[i],direction);
mval = slapi_entry_attr_get_charptr(entry,mattr);
slapi_ch_free_string(&mattr);
if (mval == 0) {
mval = slapi_entry_attr_get_charptr(entry,mattrs[i]);
}
if (mval) {
ipa_topo_util_set_segm_attr(agmt, mattrs[i], mval);
}
}
return agmt;
}
TopoReplicaSegment *
ipa_topo_util_find_segment(TopoReplica *conf, Slapi_Entry *entry)
{
char *leftHost;
char *rightHost;
TopoReplicaSegment *segment = NULL;
leftHost = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentLeftNode");
rightHost = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentRightNode");
segment = ipa_topo_cfg_segment_find(conf->repl_root, leftHost, rightHost);
slapi_ch_free((void **)&leftHost);
slapi_ch_free((void **)&rightHost);
return segment;
}
TopoReplicaSegment *
ipa_topo_util_segment_from_entry(TopoReplica *conf, Slapi_Entry *entry)
{
char *leftHost;
char *rightHost;
char *direction;
char *name;
char *state;
TopoReplicaSegment *segment = NULL;
segment = (TopoReplicaSegment *) slapi_ch_calloc(1,sizeof(TopoReplicaSegment));
leftHost = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentLeftNode");
rightHost = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentRightNode");
direction = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentDirection");
name = slapi_entry_attr_get_charptr(entry,"cn");
if (strcasecmp(direction,SEGMENT_DIR_BOTH) == 0){
segment->direct = SEGMENT_BIDIRECTIONAL;
segment->left = ipa_topo_util_agmt_from_entry(entry,conf->repl_root,
leftHost,rightHost, "left");
segment->right = ipa_topo_util_agmt_from_entry(entry,conf->repl_root,
rightHost,leftHost, "right");
} else if (strcasecmp(direction,SEGMENT_DIR_LEFT_ORIGIN) == 0) {
segment->direct = SEGMENT_LEFT_RIGHT;
segment->left = ipa_topo_util_agmt_from_entry(entry,conf->repl_root,
leftHost,rightHost, "left");
} else if (strcasecmp(direction,SEGMENT_DIR_RIGHT_ORIGIN) == 0) {
segment->direct = SEGMENT_RIGHT_LEFT;
segment->right = ipa_topo_util_agmt_from_entry(entry,conf->repl_root,
rightHost,leftHost, "right");
}
state = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentStatus");
if (state && 0 == strcasecmp(state, SEGMENT_OBSOLETE_STR)) {
/* state obsolete was set during merge */
segment->state = SEGMENT_OBSOLETE;
} else if (state && 0 == strcasecmp(state, SEGMENT_REMOVED_STR)) {
/* state removed was set during host delete */
segment->state = SEGMENT_REMOVED;
} else {
segment->state = 0;
}
segment->from = leftHost;
segment->to = rightHost;
segment->name = name;
slapi_ch_free((void **)&direction);
slapi_ch_free((void **)&state);
return segment;
}
TopoReplicaSegment *
ipa_topo_util_segm_from_agmt(Slapi_Entry *repl_agmt)
{
TopoReplicaSegment *segment = NULL;
TopoReplicaAgmt *agmt = NULL;
segment = (TopoReplicaSegment *) slapi_ch_calloc(1,sizeof(TopoReplicaSegment));
agmt = (TopoReplicaAgmt *) slapi_ch_calloc(1,sizeof(TopoReplicaAgmt));
segment->from = slapi_ch_strdup(ipa_topo_get_plugin_hostname());
segment->to = slapi_entry_attr_get_charptr(repl_agmt, "nsds5replicahost");
segment->direct = SEGMENT_LEFT_RIGHT;
segment->state = SEGMENT_AUTOGEN;
segment->name = slapi_ch_smprintf("%s-to-%s", segment->from, segment->to);
segment->left = agmt;
segment->right = NULL;
agmt->origin = slapi_ch_strdup(segment->from);
agmt->target = slapi_ch_strdup(segment->to);
agmt->repl_timeout = slapi_entry_attr_get_charptr(repl_agmt, "nsds5replicatimeout");
agmt->repl_root = slapi_entry_attr_get_charptr(repl_agmt, "nsds5replicaroot");
agmt->repl_attrs = slapi_entry_attr_get_charptr(repl_agmt, "nsDS5ReplicatedAttributeList");
agmt->strip_attrs = slapi_entry_attr_get_charptr(repl_agmt, "nsds5ReplicaStripAttrs");
agmt->total_attrs = slapi_entry_attr_get_charptr(repl_agmt, "nsDS5ReplicatedAttributeListTotal");
agmt->repl_bind_dn = slapi_entry_attr_get_charptr(repl_agmt, "nsds5replicabinddn");
agmt->repl_bind_cred = slapi_entry_attr_get_charptr(repl_agmt, "nsds5replicacredentials");
agmt->repl_transport = slapi_entry_attr_get_charptr(repl_agmt, "nsds5replicatransportinfo");
agmt->repl_bind_method = slapi_entry_attr_get_charptr(repl_agmt, "nsds5replicabindmethod");
return segment;
}
TopoReplica *
ipa_topo_util_get_conf_for_segment(Slapi_Entry *segment_entry)
{
/* we have a segment entry and need to determine the corresponding
* replica conf, to get the replica root */
TopoReplica *tconf = NULL;
char *parent = slapi_dn_parent(slapi_entry_get_dn_const(segment_entry));
Slapi_Entry *conf = ipa_topo_util_get_entry(parent);
tconf = ipa_topo_util_conf_from_entry(conf);
slapi_entry_free(conf);
return tconf;
}
TopoReplica *
ipa_topo_util_conf_from_entry(Slapi_Entry *entry)
{
TopoReplica *conf = NULL;
char *repl_root = NULL;
repl_root = slapi_entry_attr_get_charptr(entry,"ipaReplTopoConfRoot");
conf = ipa_topo_cfg_replica_find(repl_root, 1);
if (conf) {
slapi_ch_free((void **)&repl_root);
return conf;
} else {
conf = (TopoReplica *) slapi_ch_calloc(1,sizeof(TopoReplica));
conf->repl_root = repl_root;
/* TBD read defined managed attrs as defaults */
return conf;
}
}
int
ipa_topo_util_update_agmt_list(TopoReplica *conf, TopoReplicaSegmentList *repl_segments)
{
int rc = 0;
int i;
int nentries;
Slapi_Entry **entries;
Slapi_Entry *repl_agmt;
Slapi_PBlock *pb = NULL;
char *filter;
/* find all replication agreements */
pb = slapi_pblock_new();
filter = slapi_ch_smprintf("(&(objectclass=nsds5replicationagreement)(nsds5replicaroot=%s))",
conf->repl_root);
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_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_update_agmts_list: "
"cannot read replication agreeements: error %d\n", rc);
goto error_return;
} else {
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_agmts_list: "
"no agrements found\n");
goto update_only;
}
}
/* for each agreement find segment */
nentries = 0;
repl_agmt = entries[0];
while (repl_agmt) {
char *targetHost;
TopoReplicaAgmt *topo_agmt;
TopoReplicaSegment *topo_segm;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_update_agmts_list: processing agreement: %s\n",
slapi_entry_get_dn_const(repl_agmt));
targetHost = slapi_entry_attr_get_charptr(repl_agmt,"nsDS5ReplicaHost");
if(!targetHost){
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_update_agmts: "
"cannot read targethost: error %d\n", rc);
continue;
}
topo_agmt = ipa_topo_util_find_segment_agmt(conf->repl_segments,
ipa_topo_get_plugin_hostname(),
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);
/* update agreement params which are different in the segment*/
char *segm_attr_val;
char *agmt_attr_val;
Slapi_Mods *smods = slapi_mods_new();
char **mattrs = ipa_topo_get_plugin_managed_attrs();
for (i=0; mattrs[i]; i++) {
segm_attr_val = ipa_topo_util_get_segm_attr(topo_agmt,mattrs[i]);
if (segm_attr_val) {
agmt_attr_val = slapi_entry_attr_get_charptr(repl_agmt,mattrs[i]);
if (agmt_attr_val == NULL ||
strcasecmp(agmt_attr_val,segm_attr_val)) {
/* value does not exist in agmt or
* is different from segment: replace
*/
slapi_mods_add_string(smods,
LDAP_MOD_REPLACE,
mattrs[i],
segm_attr_val);
}
}
}
if (slapi_mods_get_num_mods(smods) > 0) {
ipa_topo_util_modify((Slapi_DN *)slapi_entry_get_sdn_const(repl_agmt),
smods);
}
slapi_mods_free(&smods);
} else {
if (ipa_topo_util_agmt_is_marked(repl_agmt)) {
/* agreement is marked and no segment exists, delete agreement */
ipa_topo_agmt_del_dn((char *)slapi_sdn_get_dn(slapi_entry_get_sdn_const(repl_agmt)));
} else {
/* generate segment from agreement */
topo_segm = ipa_topo_util_segm_from_agmt(repl_agmt);
rc = ipa_topo_util_segment_write(conf, topo_segm);
if ( rc != 0) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_update_agmts_list: "
"failed to write segment: error %d\n", rc);
}
rc = ipa_topo_util_agmt_mark(conf, repl_agmt, topo_segm);
if (rc != 0) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_update_agmt_list: "
"failed to mark agreement for host %s: error %d\n", targetHost, rc);
}
/* segment has been added in postop of segment write,
* prevent adding an agreement again
*/
ipa_topo_cfg_segment_set_visited(conf, topo_segm);
}
}
repl_agmt = entries[++nentries];
}
slapi_free_search_results_internal(pb);
update_only:
/* check if segments not covered by agreement exist
* add agreeement
*/
ipa_topo_util_missing_agmts_add_list(conf, conf->repl_segments,
ipa_topo_get_plugin_hostname());
error_return:
slapi_ch_free_string(&filter);
slapi_pblock_destroy(pb);
return rc;
}
TopoReplicaAgmt *
ipa_topo_util_find_segment_agmt(TopoReplicaSegmentList *repl_segments,
char *fromHost, char *toHost)
{
TopoReplicaAgmt *agmt = NULL;
TopoReplicaAgmt *agmtfound = NULL;
TopoReplicaSegmentList *segment = repl_segments;
while (segment) {
if (segment->visited) {
segment = segment->next;
continue;
}
agmt = segment->segm->left;
if (agmt && (0 == strcasecmp(agmt->origin, fromHost)) &&
(0 == strcasecmp(agmt->target, toHost))) {
agmtfound = agmt;
break;
}
agmt = segment->segm->right;
if (agmt && (0 == strcasecmp(agmt->origin, fromHost)) &&
(0 == strcasecmp(agmt->target, toHost))) {
agmtfound = agmt;
break;
}
segment = segment->next;
}
if (segment) {
segment->visited = 1;
}
return agmtfound;
}
void
ipa_topo_util_missing_agmts_add_list(TopoReplica *repl_conf,
TopoReplicaSegmentList *repl_segments,
char *fromHost)
{
TopoReplicaSegmentList *segment = repl_segments;
while (segment) {
if (segment->visited) {
segment->visited = 0;
segment = segment->next;
continue;
}
ipa_topo_util_missing_agmts_add(repl_conf, segment->segm, fromHost);
segment = segment->next;
}
}
void
ipa_topo_util_missing_agmts_add(TopoReplica *repl_conf,
TopoReplicaSegment *segment,
char *fromHost)
{
if (0 == strcasecmp(segment->from, fromHost)) {
if (segment->left) {
ipa_topo_agmt_new(segment->to,repl_conf, segment->left);
}
} else if (0 == strcasecmp(segment->to, fromHost)) {
if (segment->right) {
ipa_topo_agmt_new(segment->from,repl_conf, segment->right);
}
}
}
void
ipa_topo_util_existing_agmts_del_list(TopoReplica *repl_conf,
TopoReplicaSegmentList *repl_segments,
char *fromHost)
{
TopoReplicaSegmentList *segment = repl_segments;
while (segment) {
if (segment->visited) {
segment->visited = 0;
segment = segment->next;
continue;
}
ipa_topo_util_existing_agmts_del(repl_conf, segment->segm,fromHost);
segment = segment->next;
}
}
void
ipa_topo_util_existing_agmts_del(TopoReplica *repl_conf,
TopoReplicaSegment *segment,
char *fromHost)
{
if (0 == strcasecmp(segment->from, fromHost)) {
if (segment->left) {
ipa_topo_agmt_del(segment->to,repl_conf, segment->left);
}
} else if (0 == strcasecmp(segment->to, fromHost)) {
if (segment->right) {
ipa_topo_agmt_del(segment->from,repl_conf, segment->right);
}
}
}
void
ipa_topo_util_existing_agmts_update_list(TopoReplica *repl_conf,
TopoReplicaSegmentList *repl_segments,
LDAPMod **mods ,char *fromHost)
{
TopoReplicaSegmentList *segment = repl_segments;
while (segment) {
if (segment->visited) {
segment->visited = 0;
segment = segment->next;
continue;
}
ipa_topo_util_existing_agmts_update(repl_conf, segment->segm, mods, fromHost);
segment = segment->next;
}
}
void
ipa_topo_util_existing_agmts_update(TopoReplica *repl_conf,
TopoReplicaSegment *segment,
LDAPMod **mods ,char *fromHost)
{
TopoReplicaAgmt *l_agmt = NULL;
TopoReplicaAgmt *r_agmt = NULL;
l_agmt = segment->left;
r_agmt = segment->right;
if (l_agmt && r_agmt) {
if (0 == strcasecmp(l_agmt->origin, fromHost)) {
ipa_topo_agmt_mod(repl_conf, l_agmt, mods, "left");
} else if (0 == strcasecmp(r_agmt->origin, fromHost)) {
ipa_topo_agmt_mod(repl_conf, r_agmt, mods, "right");
}
}
}
void
ipa_topo_util_segment_update(TopoReplica *repl_conf,
TopoReplicaSegment *segment,
LDAPMod **mods ,char *fromHost)
{
int i;
for (i = 0; (mods != NULL) && (mods[i] != NULL); i++) {
switch (mods[i]->mod_op & ~LDAP_MOD_BVALUES) {
case LDAP_MOD_DELETE:
break;
case LDAP_MOD_ADD:
case LDAP_MOD_REPLACE:
if (0 == strcasecmp(mods[i]->mod_type,"ipaReplTopoSegmentDirection")) {
if (0 == strcasecmp(mods[i]->mod_bvalues[0]->bv_val,"both")) {
if (segment->direct == SEGMENT_LEFT_RIGHT) {
segment->right = ipa_topo_cfg_agmt_dup_reverse(segment->left);
} else if (segment->direct == SEGMENT_RIGHT_LEFT) {
segment->left = ipa_topo_cfg_agmt_dup_reverse(segment->right);
}
segment->direct = SEGMENT_BIDIRECTIONAL;
} else {
/* only onedirectionl --> bidirectional handled so far */
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_segment_update: no downgrade of direction\n");
}
} else if (0 == strcasecmp(mods[i]->mod_type,"ipaReplTopoSegmentStatus")) {
if (0 == strcasecmp(mods[i]->mod_bvalues[0]->bv_val,SEGMENT_OBSOLETE_STR)) {
segment->state = SEGMENT_OBSOLETE;
} else if (0 == strcasecmp(mods[i]->mod_bvalues[0]->bv_val,SEGMENT_AUTOGEN_STR)) {
segment->state = SEGMENT_AUTOGEN;
}
}
break;
}
}
}
char *
ipa_topo_util_get_segm_attr(TopoReplicaAgmt *agmt, char *attr_type)
{
char *attr = NULL;
if (strcasecmp(attr_type, "nsds5ReplicaEnabled") == 0) {
attr = agmt->enabled;
} else if (strcasecmp(attr_type, "nsds5ReplicaStripAttrs") == 0){
attr = agmt->strip_attrs;
} else if (strcasecmp(attr_type, "nsds5ReplicatedAttributeList") == 0){
attr = agmt->repl_attrs;
} else if (strcasecmp(attr_type, "nsDS5ReplicatedAttributeListTotal") == 0) {
attr = agmt->total_attrs;
} else if (strcasecmp(attr_type, "nsds5BeginReplicaRefresh") == 0){
attr = agmt->repl_refresh;
} else if (strcasecmp(attr_type, "nsds5replicaTimeout") == 0) {
attr = agmt->repl_timeout;
} else if (strcasecmp(attr_type, "nsds5ReplicaEnabled") == 0) {
attr = agmt->enabled;
} else if (strcasecmp(attr_type, "nsds5replicaSessionPauseTime") == 0) {
attr = agmt->repl_pause;
} else if (strcasecmp(attr_type, "nsds5replicabinddn") == 0) {
attr = agmt->repl_bind_dn;
} else if (strcasecmp(attr_type, "nsds5replicacredentials") == 0) {
attr = agmt->repl_bind_cred;
} else if (strcasecmp(attr_type, "nsds5replicatransportinfo") == 0) {
attr = agmt->repl_transport;
} else if (strcasecmp(attr_type, "nsds5replicabindmethod") == 0) {
attr = agmt->repl_bind_method;
}
return attr;
}
void
ipa_topo_util_set_segm_attr(TopoReplicaAgmt *agmt, char *attr_type, char *attr_val)
{
if (strcasecmp(attr_type, "nsds5ReplicaEnabled") == 0) {
agmt->enabled = attr_val;
} else if (strcasecmp(attr_type, "nsds5ReplicaStripAttrs") == 0){
agmt->strip_attrs = attr_val;
} else if (strcasecmp(attr_type, "nsds5ReplicatedAttributeList") == 0){
agmt->repl_attrs = attr_val;
} else if (strcasecmp(attr_type, "nsDS5ReplicatedAttributeListTotal") == 0) {
agmt->total_attrs = attr_val;
} else if (strcasecmp(attr_type, "nsds5BeginReplicaRefresh") == 0){
agmt->repl_refresh = attr_val;
} else if (strcasecmp(attr_type, "nsds5replicaTimeout") == 0) {
agmt->repl_timeout = attr_val;
} else if (strcasecmp(attr_type, "nsds5ReplicaEnabled") == 0) {
agmt->enabled = attr_val;
} else if (strcasecmp(attr_type, "nsds5replicaSessionPauseTime") == 0) {
agmt->repl_pause = attr_val;
} else if (strcasecmp(attr_type, "nsds5replicabinddn") == 0) {
agmt->repl_bind_dn = attr_val;
} else if (strcasecmp(attr_type, "nsds5replicacredentials") == 0) {
agmt->repl_bind_cred = attr_val;
} else if (strcasecmp(attr_type, "nsds5replicatransportinfo") == 0) {
agmt->repl_transport = attr_val;
} else if (strcasecmp(attr_type, "nsds5replicabindmethod") == 0) {
agmt->repl_bind_method = attr_val;
}
}
/* check if the entry is a standard replication agreement (ignore winsync)
* and if the replication suffix is in the list of managed replication roots.
* This qualifies the entry as a candidate, further checks have to be done.
*/
int
ipa_topo_util_entry_is_candidate(Slapi_Entry *e)
{
char **ocs;
char *oc = NULL;
char *repl_root;
char **shared_root;
int rc = 0;
int i;
ocs = slapi_entry_attr_get_charray(e,"objectclass");
for (i=0; ocs && ocs[i]; i++) {
if (strcasecmp(ocs[i],"nsds5ReplicationAgreement") == 0) {
oc = ocs[i];
break;
}
}
if (oc) {
repl_root = slapi_entry_attr_get_charptr(e,"nsDS5ReplicaRoot");
shared_root = ipa_topo_get_plugin_replica_root();
for (i=0; shared_root && shared_root[i]; i++) {
if (strcasecmp(repl_root,shared_root[i]) == 0) {
rc = 1;
break;
}
}
slapi_ch_free((void **) &repl_root);
}
slapi_ch_array_free(ocs);
return rc;
}
int
ipa_topo_util_target_is_managed(Slapi_Entry *e)
{
char *targethost;
char *repl_root;
TopoReplica *replica;
int ret = 0;
/* first check: is the entry managed alreday by the topology plugin */
/* at the moment only replication agreements are managed */
if (ipa_topo_util_agmt_is_marked(e)) return 1;
/* next check: is the replcation agreement targeting a meanged server
* deny agreements to an managed server
* allow other agreements
*/
targethost = slapi_entry_attr_get_charptr(e,"nsDS5ReplicaHost");
repl_root = slapi_entry_attr_get_charptr(e,"nsDS5ReplicaRoot");
replica = ipa_topo_cfg_replica_find(repl_root,1);
if (targethost && replica &&
ipa_topo_cfg_host_find(replica, targethost, 1)) {
ret = 1;
}
slapi_ch_free_string(&targethost);
slapi_ch_free_string(&repl_root);
return ret;
}
void
ipa_topo_util_segm_update (TopoReplica *tconf,
TopoReplicaSegment *tsegm,
int property)
{
char *dn = NULL;
Slapi_Mods *smods;
dn = ipa_topo_segment_dn(tconf, tsegm->name);
if (dn == NULL) return;
/* apply mods to entry */
smods = slapi_mods_new();
switch (property) {
case SEGMENT_BIDIRECTIONAL:
tsegm->direct = SEGMENT_BIDIRECTIONAL;
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
"ipaReplTopoSegmentDirection", "both");
break;
case SEGMENT_LEFT_RIGHT:
tsegm->direct = SEGMENT_LEFT_RIGHT;
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
"ipaReplTopoSegmentDirection", "left-right");
break;
case SEGMENT_RIGHT_LEFT:
tsegm->direct = SEGMENT_RIGHT_LEFT;
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
"ipaReplTopoSegmentDirection", "right-left");
break;
case SEGMENT_OBSOLETE:
tsegm->state = SEGMENT_OBSOLETE;
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
"ipaReplTopoSegmentStatus", SEGMENT_OBSOLETE_STR);
break;
case SEGMENT_REMOVED:
tsegm->state = SEGMENT_OBSOLETE;
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
"ipaReplTopoSegmentStatus", SEGMENT_REMOVED_STR);
break;
}
if (slapi_mods_get_num_mods(smods) > 0) {
Slapi_DN *sdn = slapi_sdn_new_normdn_byref(dn);
ipa_topo_util_modify(sdn, smods);
slapi_sdn_free(&sdn);
}
slapi_mods_free(&smods);
slapi_ch_free_string(&dn);
}
void
ipa_topo_util_segm_remove(TopoReplica *tconf,
TopoReplicaSegment *tsegm)
{
Slapi_PBlock *pb;
char *dn = NULL;
int ret;
/* remove it from the database */
dn = ipa_topo_segment_dn(tconf, tsegm->name);
if (dn == NULL) return;
pb = slapi_pblock_new();
slapi_delete_internal_set_pb(pb, dn, NULL, NULL,
ipa_topo_get_plugin_id(), 0);
slapi_delete_internal_pb(pb);
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
slapi_pblock_destroy(pb);
slapi_ch_free_string(&dn);
/* removed from the internal data struct in the delete postop */
/* ipa_topo_cfg_segment_del(tconf, tsegm); */
}
/* for merging segments the result should be the same on any server
* an deliberate decision is to compare hostnames to get a preference
*/
static int
ipa_topo_util_segm_order(TopoReplicaSegment *l, TopoReplicaSegment *r)
{
return strcasecmp(l->from, r->from);
}
void
ipa_topo_util_segment_merge(TopoReplica *tconf,
TopoReplicaSegment *tsegm)
{
TopoReplicaSegment *ex_segm;
if (tsegm->direct == SEGMENT_BIDIRECTIONAL) return;
if (strcasecmp(tsegm->from,ipa_topo_get_plugin_hostname()) &&
strcasecmp(tsegm->to,ipa_topo_get_plugin_hostname())) {
/* merging is only done on one of the endpoints of the segm */
return;
}
ex_segm = ipa_topo_cfg_replica_segment_find(tconf, tsegm->to, tsegm->from, 1 /*lock*/);
if (ex_segm == NULL) return;
/* to avoid conflicts merging has to be done only once and
* so there is a preference which segment survives and on
* which server it will be done
*/
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);
}
} 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);
}
}
}
int
ipa_topo_util_segment_write(TopoReplica *tconf, TopoReplicaSegment *tsegm)
{
Slapi_Entry *e = NULL;
Slapi_PBlock *pb;
char *dn = NULL;
Slapi_DN *sdn = NULL;
int ret = 0;
/* Set up the new segment entry */
dn = ipa_topo_segment_dn(tconf, tsegm->name);
if (dn == NULL) return -1;
sdn = slapi_sdn_new_normdn_byref(dn);
e = slapi_entry_alloc();
/* the entry now owns the dup'd dn */
slapi_entry_init_ext(e, sdn, NULL); /* sdn is copied into e */
slapi_sdn_free(&sdn);
slapi_entry_add_string(e, SLAPI_ATTR_OBJECTCLASS, "iparepltoposegment");
slapi_entry_add_string(e, "cn",tsegm->name);
slapi_entry_add_string(e, "iparepltoposegmentleftnode",tsegm->from);
slapi_entry_add_string(e, "iparepltoposegmentrightnode",tsegm->to);
slapi_entry_add_string(e, "iparepltoposegmentdirection", "left-right");
/* write other attributes of the segment if present */
if (tsegm->state == SEGMENT_AUTOGEN) {
slapi_entry_add_string(e, "iparepltoposegmentstatus", "autogen");
}
pb = slapi_pblock_new();
slapi_pblock_init(pb);
/* e will be consumed by slapi_add_internal() */
slapi_add_entry_internal_set_pb(pb, e, NULL, ipa_topo_get_plugin_id(), 0);
slapi_add_internal_pb(pb);
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
slapi_pblock_destroy(pb);
return ret;
}
/*
* to distinguish replication agreements created by the topology plugin
* and agreemens created by admins or legacy tools a "marker" objectclass is used.
* Witheout extending the schema the description attribute is used and a
* specific value is added:
* - when a segment is created from an agreement an so put under control of
* the plugin:
* "ipaReplTopoManagedAgreementState: managed agreement - controlled by topology plugin"
* - when an agreement is created from a segment:
* "ipaReplTopoManagedAgreementState: managed agreement - generated by topology plugin"
*/
int
ipa_topo_util_agmt_mark(TopoReplica *tconf, Slapi_Entry *repl_agmt,
TopoReplicaSegment *tsegm)
{
int ret = 0;
Slapi_Mods *smods = slapi_mods_new();
slapi_mods_add_string(smods, LDAP_MOD_ADD, "objectclass",
"ipaReplTopoManagedAgreement");
slapi_mods_add_string(smods, LDAP_MOD_ADD, "ipaReplTopoManagedAgreementState",
"managed agreement - controlled by topology plugin");
if (slapi_mods_get_num_mods(smods) > 0) {
ret = ipa_topo_util_modify(
(Slapi_DN *)slapi_entry_get_sdn_const(repl_agmt), smods);
}
slapi_mods_free(&smods);
return ret;
}
int
ipa_topo_util_agmt_is_marked(Slapi_Entry *repl_agmt)
{
int ret = 0;
int i;
char **descs;
descs = slapi_entry_attr_get_charray(repl_agmt, "objectclass");
for (i=0; descs &&descs[i]; i++) {
if (strcasecmp(descs[i],"ipaReplTopoManagedAgreement") == 0) {
ret = 1;
break;
}
}
slapi_ch_array_free(descs);
return ret;
}
void
ipa_topo_util_update_segments_for_host(Slapi_Entry *hostentry)
{
int rc = 0;
int nentries;
char* newhost = NULL;
Slapi_Entry **entries;
Slapi_Entry *repl_agmt;
Slapi_PBlock *pb = NULL;
char *filter;
/* find all replication agreements to the new host entry
* Since the host was not yet managed new segments ghave to be
* created
*/
newhost = slapi_entry_attr_get_charptr(hostentry,"cn");
pb = slapi_pblock_new();
filter = slapi_ch_smprintf("(&(objectclass=nsds5replicationagreement)(nsds5replicahost=%s))",
newhost);
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_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_update_segments_for_host: "
"no replication agreeements for host %s: error %d\n",
newhost, rc);
goto error_return;
} else {
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_segments_for_host: "
"no agrements found\n");
goto error_return;
}
}
/* for each agreement find segment */
nentries = 0;
repl_agmt = entries[0];
while (repl_agmt) {
TopoReplica *conf = NULL;
TopoReplicaSegment *topo_segm;
char *repl_root = NULL;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_update_segments_for_host: "
"processing agreement: %s\n",
slapi_entry_get_dn_const(repl_agmt));
/* generate segment from agreement */
repl_root = slapi_entry_attr_get_charptr(repl_agmt,"nsds5replicaroot");
conf = ipa_topo_cfg_replica_find(repl_root,1);
if (conf == NULL) goto next_agmt;
topo_segm = ipa_topo_util_segm_from_agmt(repl_agmt);
rc = ipa_topo_util_segment_write(conf, topo_segm);
if (rc != 0) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_update_segments_for_host: "
"failed to write segment for host %s: error %d\n",
newhost, rc);
}
rc = ipa_topo_util_agmt_mark(conf, repl_agmt, topo_segm);
if (rc != 0) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_update_segments_for_host: "
"failed to mark agreement for host %s: error %d\n",
newhost, rc);
}
ipa_topo_cfg_segment_add(conf, topo_segm);
next_agmt:
slapi_ch_free_string(&repl_root);
repl_agmt = entries[++nentries];
}
slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
error_return:
slapi_ch_free_string(&newhost);
}
void
ipa_topo_util_disable_repl_from_host(char *repl_root, char *delhost)
{
char *principal = ipa_topo_util_get_ldap_principal(repl_root, delhost);
if (principal) {
ipa_topo_util_disable_repl_for_principal(repl_root, principal);
slapi_ch_free_string(&principal);
} else {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_disable_repl_from_host: "
"failed to get ldap principal for host: %s \n",
delhost);
}
}
void
ipa_topo_util_delete_segments_for_host(char *repl_root, char *delhost)
{
TopoReplicaSegment *segm = NULL;
TopoReplica *tconf = ipa_topo_cfg_replica_find(repl_root, 1);
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);
if (segm) {
/* mark segment as removable, bypass connectivity check when replicated */
if (segm->direct == SEGMENT_BIDIRECTIONAL) check_reverse = 0;
ipa_topo_util_segm_update(tconf,segm, SEGMENT_REMOVED);
/* delete segment */
/* the replication agreement will be deleted in the postop_del*/
ipa_topo_util_segm_remove(tconf, segm);
}
/* 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());
if (segm) {
ipa_topo_util_segm_update(tconf,segm, SEGMENT_REMOVED);
/* mark and delete, no repl agmt on this server */
ipa_topo_util_segm_remove(tconf, segm);
}
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_delete_segments_for_host <-- done\n");
}
void
ipa_topo_util_delete_host(Slapi_Entry *hostentry)
{
char* delhost = NULL;
delhost = slapi_entry_attr_get_charptr(hostentry,"cn");
/* if the deleted host is the current host, do not
* delete the segments, deleting segments will trigger
* removal of replication agreements and it cannot be
* ensured that the deletion of the host will reach
* other servers in the replica before.
* So wait until the delete is received on the other
* servers and the deletion of segments is received.
*/
if (0 == strcasecmp(delhost,ipa_topo_get_plugin_hostname())) {
return;
} else {
/* find all segments connecting the local master to the
* deleted master.
* - mark the segments as no longer managed
* - delete the segments
* - if the segment originates at the local host
* remove the corresponding replication agreement
*/
int i = 0;
char **shared_root = ipa_topo_get_plugin_replica_root();
while (shared_root[i]) {
ipa_topo_util_disable_repl_from_host(shared_root[i], delhost);
ipa_topo_util_delete_segments_for_host(shared_root[i], delhost);
i++;
}
}
}
int
ipa_topo_util_start(int delay)
{
/* main routine to synchronize data in the shared tree and
* config data. It will be called:
* - at startup of the server
* - if the domain level increases above the plugin version
* and the plugin becomes active
* - after a backup state change, eg after online initialization
* when there is no guarantee that data in the shared tree
* and plugin data still match.
*
* the parameter delay controls if the operation is performed
* immediately or after some delay. This delay is necessary
* during startup because the plugins only become active after
* all plugins have been started and modifications would not be
* logged in the changelog and replicated
*/
time_t now;
int rc = 0;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"--> ipa_topo_util_start - deleay: %d\n",delay);
ipa_topo_init_shared_config();
/* initialize the config data from the shared tree and apply to
* the managed data under cn=config
*/
if (delay) {
time(&now);
if (!slapi_eq_once(ipa_topo_queue_apply_shared_config,NULL,now +
ipa_topo_get_plugin_startup_delay())) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"unable to queue configuration update\n");
return -1;
}
} else {
rc = ipa_topo_apply_shared_config();
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_util_start\n");
return rc;
}
char *
ipa_topo_util_get_ldap_principal(char *repl_root, char *hostname)
{
int rc = 0;
Slapi_Entry **entries = NULL;
Slapi_PBlock *pb = NULL;
char *filter;
char *dn = NULL;
filter = slapi_ch_smprintf("krbprincipalname=ldap/%s*",hostname);
pb = slapi_pblock_new();
slapi_search_internal_set_pb(pb, repl_root, LDAP_SCOPE_SUBTREE,
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_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_get_ldap_principal: "
"unable to search for entry (%s): error %d\n", filter, rc);
} else {
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_get_ldap_principal: entry not found: (%s)\n", filter);
} else {
dn = slapi_ch_strdup(slapi_entry_get_dn(entries[0]));
}
}
slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
slapi_ch_free_string(&filter);
return dn;
}
void
ipa_topo_util_disable_repl_for_principal(char *repl_root, char *principal)
{
Slapi_DN *sdn;
char *filter;
Slapi_PBlock *pb;
Slapi_Entry **entries;
Slapi_Mods *smods;
int ret;
/* to disable replication for a user/principal it ahs to be removed from the
* allowed bind dns in the replica object and from the bind dn group
*/
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"--> ipa_topo_util_disable_repl_for_principal\n");
/* find replica object */
pb = slapi_pblock_new();
filter = slapi_ch_smprintf("(&(objectclass=nsds5replica)(nsds5replicaroot=%s))", repl_root);
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, &ret);
if (ret != 0) {
sdn = NULL;
} else {
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_agreement_dn: no replica found\n");
sdn = NULL;
} else {
sdn = slapi_sdn_dup(slapi_entry_get_sdn(entries[0]));
}
}
slapi_free_search_results_internal(pb);
/* remove principal from binddns */
smods = slapi_mods_new();
slapi_mods_add_string(smods, LDAP_MOD_DELETE,
"nsds5replicabinddn", principal);
ret = ipa_topo_util_modify(sdn, smods);
slapi_sdn_free(&sdn);
/* find binddn group */
slapi_pblock_init(pb);
slapi_search_internal_set_pb(pb, ipa_topo_get_plugin_shared_bindgroup(), LDAP_SCOPE_BASE,
"(objectclass=groupofnames)",
NULL, 0, NULL, NULL, ipa_topo_get_plugin_id(), 0);
slapi_search_internal_pb(pb);
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
if (ret != 0) {
sdn = NULL;
} else {
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_agreement_dn: no replica found\n");
sdn = NULL;
} else {
sdn = slapi_sdn_dup(slapi_entry_get_sdn(entries[0]));
}
}
slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
/* delete principal as binddn group member */
smods = slapi_mods_new();
slapi_mods_add_string(smods, LDAP_MOD_DELETE,
"member", principal);
ret = ipa_topo_util_modify(sdn, smods);
slapi_mods_free(&smods);
slapi_sdn_free(&sdn);
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_util_disable_repl_for_principal\n");
}