freeipa/daemons/ipa-slapi-plugins/topology/topology_post.c
Ludwig Krispenz 3f70c9aed7 update list of managed servers when a suffix becomes managed
when a suffix becomes managed for a host, the host needs to
    be added to the managed servers, otherwise connectivity check would fail

Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
2015-10-30 13:47:25 +01:00

290 lines
10 KiB
C

#include "topology.h"
/*
* detect if the plugin should handle this entry and return the entry type
*/
int
ipa_topo_check_entry_type(Slapi_Entry *entry)
{
int ret = TOPO_IGNORE_ENTRY;
Slapi_DN *add_dn = NULL;
char **ocs;
add_dn = slapi_entry_get_sdn(entry);
if (slapi_sdn_issuffix(add_dn,ipa_topo_get_plugin_shared_topo_dn())) {
/* check if it is a toplogy or a segment */
/* check if segment's left or right node is the local server*/
int i;
ocs = slapi_entry_attr_get_charray(entry,"objectclass");
for (i=0; ocs && ocs[i]; i++) {
if (strcasecmp(ocs[i],"ipaReplTopoConf") == 0) {
ret = TOPO_CONFIG_ENTRY;
break;
} else if (strcasecmp(ocs[i],"ipaReplTopoSegment") == 0) {
ret = TOPO_SEGMENT_ENTRY;
break;
}
}
} else if (slapi_sdn_isparent(ipa_topo_get_plugin_shared_hosts_dn(),add_dn)) {
ret = TOPO_HOST_ENTRY;
} else if (slapi_sdn_issuffix(add_dn,ipa_topo_get_domain_level_entry_dn())) {
ret = TOPO_DOMLEVEL_ENTRY;
}
return ret;
}
int
ipa_topo_post_add(Slapi_PBlock *pb)
{
int result = SLAPI_PLUGIN_SUCCESS;
int entry_type;
Slapi_Entry *add_entry = NULL;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"--> ipa_topo_post_add\n");
/* 1. get entry */
slapi_pblock_get(pb,SLAPI_ENTRY_POST_OP,&add_entry);
if (add_entry == NULL) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "no entry\n");
return 1;
}
/* 2. check if it is in scope and type
* and if plugin is active
*/
entry_type = ipa_topo_check_entry_type(add_entry);
if (0 == ipa_topo_get_plugin_active() &&
entry_type != TOPO_DOMLEVEL_ENTRY) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_post_add - plugin not active\n");
return 0;
}
switch (entry_type) {
case TOPO_CONFIG_ENTRY:
/* initialize the shared topology data for a replica */
ipa_topo_util_suffix_init(add_entry);
break;
case TOPO_SEGMENT_ENTRY: {
TopoReplicaSegment *tsegm = NULL;
TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(add_entry);
char *status;
if (tconf == NULL) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_post_add - config area for segment not found\n");
break;
}
/* TBD check that one node is the current server and
* that the other node is also managed by the
* shared config.
* If all checks pass create the replication agreement
*/
tsegm = ipa_topo_util_segment_from_entry(tconf, add_entry);
status = slapi_entry_attr_get_charptr(add_entry, "ipaReplTopoSegmentStatus");
if (status == NULL || strcasecmp(status,"autogen")) {
ipa_topo_util_missing_agmts_add(tconf, tsegm,
ipa_topo_get_plugin_hostname());
}
/* keep the new segment in tconf data */
ipa_topo_cfg_segment_add(tconf, tsegm);
/* TBD: do we know if the replica already has been initialized ?
* should the agreement be enabled ?
* For now assume everything is ok and enable
*/
/* check if it is unidirectional and if other direction exists */
ipa_topo_util_segment_merge(tconf, tsegm);
slapi_ch_free_string(&status);
break;
}
case TOPO_HOST_ENTRY: {
/* we are adding a new master, there could be
* a segment which so far was inactive since
* the host was not managed
*/
/* It will also add to list of managed hosts */
ipa_topo_util_add_host(add_entry);
break;
}
case TOPO_DOMLEVEL_ENTRY: {
/* the domain level entry was just added
* check and set the level, if plugin gets activated
* do initialization.
*/
char *domlevel = slapi_entry_attr_get_charptr(add_entry, "ipaDomainLevel");
ipa_topo_set_domain_level(domlevel);
ipa_topo_util_check_plugin_active();
if (ipa_topo_get_plugin_active()) {
ipa_topo_util_start(0);
}
slapi_ch_free_string(&domlevel);
break;
}
case TOPO_IGNORE_ENTRY:
break;
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_post_add\n");
return result;
}
int
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;
LDAPMod **mods;
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);
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
if (mod_entry == NULL || pre_entry == NULL) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "no entry\n");
return (1);
}
/* 2. check if it is in scope */
entry_type = ipa_topo_check_entry_type(mod_entry);
if (0 == ipa_topo_get_plugin_active() &&
entry_type != TOPO_DOMLEVEL_ENTRY) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_post_mod - plugin not active\n");
return 0;
}
switch (entry_type) {
case TOPO_CONFIG_ENTRY:
ipa_topo_util_suffix_update(mod_entry, pre_entry, mods);
break;
case TOPO_SEGMENT_ENTRY: {
TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(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");
break;
}
ipa_topo_util_segment_update(tconf, tsegm, mods,ipa_topo_get_plugin_hostname());
ipa_topo_util_existing_agmts_update(tconf, tsegm, mods,
ipa_topo_get_plugin_hostname());
/* also update local segment in tconf */
break;
}
case TOPO_DOMLEVEL_ENTRY: {
/* the domain level entry was just modified
* check and set the level, if plugin gets activated
* do initialization.
*/
char *domlevel = slapi_entry_attr_get_charptr(mod_entry, "ipaDomainLevel");
int already_active = ipa_topo_get_plugin_active();
ipa_topo_set_domain_level(domlevel);
ipa_topo_util_check_plugin_active();
if (!already_active && ipa_topo_get_plugin_active()) {
ipa_topo_util_start(0);
}
slapi_ch_free_string(&domlevel);
break;
}
case TOPO_HOST_ENTRY: {
/* check i host needs to be added to the managed hosts
* and if segments need to be created */
ipa_topo_util_update_host(mod_entry, mods);
break;
}
case TOPO_IGNORE_ENTRY:
break;
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_post_mod\n");
return result;
}
int
ipa_topo_post_del(Slapi_PBlock *pb)
{
int result = SLAPI_PLUGIN_SUCCESS;
int entry_type;
Slapi_Entry *del_entry = NULL;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"--> ipa_topo_post_del\n");
/* 0. prevent operation on tombstones */
if (ipa_topo_util_is_tombstone_op(pb)) return 0;
/* 1. get entry */
slapi_pblock_get(pb,SLAPI_ENTRY_PRE_OP,&del_entry);
if (del_entry == NULL) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "no entry\n");
return 1;
}
/* 2. check if it is in scope */
entry_type = ipa_topo_check_entry_type(del_entry);
if (0 == ipa_topo_get_plugin_active() &&
entry_type != TOPO_DOMLEVEL_ENTRY) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_post_del - plugin not active\n");
return 0;
}
switch (entry_type) {
case TOPO_CONFIG_ENTRY:
break;
case TOPO_SEGMENT_ENTRY: {
/* check if corresponding agreement exists and delete */
TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(del_entry);
TopoReplicaSegment *tsegm = NULL;
char *status;
if (tconf) tsegm = ipa_topo_util_find_segment(tconf, del_entry);
if (tsegm == NULL) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"segment to be deleted does not exist\n");
break;
}
status = slapi_entry_attr_get_charptr(del_entry, "ipaReplTopoSegmentStatus");
if (status == NULL || strcasecmp(status, SEGMENT_OBSOLETE_STR)) {
/* obsoleted segments are a result of merge, do not remove repl agmt */
ipa_topo_util_existing_agmts_del(tconf, tsegm,
ipa_topo_get_plugin_hostname());
}
/* also remove segment from local topo conf */
ipa_topo_cfg_segment_del(tconf, tsegm);
slapi_ch_free_string(&status);
break;
}
case TOPO_DOMLEVEL_ENTRY: {
/* the domain level entry was just deleted
* this should not happen, but it is identical
* to setting domlevel to 0
* log an error and inactivate plugin
*/
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"postop_del: domainlevel entry deleted - "
"plugin will be inactivated \n");
break;
}
case TOPO_HOST_ENTRY:
/* deleting an host entry means that the host becomes
* unmanaged, probably because a replica is removed.
* remove all marked replication agreements connecting
* this host.
*/
ipa_topo_util_delete_host(del_entry);
ipa_topo_cfg_host_del(del_entry);
ipa_topo_util_cleanruv(del_entry);
break;
case TOPO_IGNORE_ENTRY:
break;
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_post_del\n");
return result;
}