ds plugin - manage replication topology in the shared tree

Implementation of ticket: https://fedorahosted.org/freeipa/ticket/4302
        Design page: http://www.freeipa.org/page/V4/Manage_replication_topology

Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
This commit is contained in:
Ludwig Krispenz 2015-05-20 17:28:39 +02:00 committed by Petr Vobornik
parent c5f319d3e8
commit 25bf0c6e78
14 changed files with 4079 additions and 0 deletions

View File

@ -362,6 +362,7 @@ AC_CONFIG_FILES([
ipa-slapi-plugins/ipa-modrdn/Makefile ipa-slapi-plugins/ipa-modrdn/Makefile
ipa-slapi-plugins/ipa-sidgen/Makefile ipa-slapi-plugins/ipa-sidgen/Makefile
ipa-slapi-plugins/ipa-range-check/Makefile ipa-slapi-plugins/ipa-range-check/Makefile
ipa-slapi-plugins/topology/Makefile
]) ])
AC_OUTPUT AC_OUTPUT

View File

@ -16,6 +16,7 @@ SUBDIRS = \
ipa-winsync \ ipa-winsync \
ipa-sidgen \ ipa-sidgen \
ipa-range-check \ ipa-range-check \
topology \
$(NULL) $(NULL)
EXTRA_DIST = \ EXTRA_DIST = \

View File

@ -0,0 +1,51 @@
NULL =
PLUGIN_COMMON_DIR=../common
AM_CPPFLAGS = \
-I. \
-I$(srcdir) \
-I$(PLUGIN_COMMON_DIR) \
-I/usr/include/dirsrv \
-DPREFIX=\""$(prefix)"\" \
-DBINDIR=\""$(bindir)"\" \
-DLIBDIR=\""$(libdir)"\" \
-DLIBEXECDIR=\""$(libexecdir)"\" \
-DDATADIR=\""$(datadir)"\" \
$(LDAP_CFLAGS) \
$(WARN_CFLAGS) \
$(NULL)
plugindir = $(libdir)/dirsrv/plugins
plugin_LTLIBRARIES = \
libtopology.la \
$(NULL)
libtopology_la_SOURCES = \
topology_agmt.c \
topology_init.c \
topology_cfg.c \
topology_post.c \
topology_pre.c \
topology_util.c \
$(NULL)
libtopology_la_LDFLAGS = -avoid-version
#libtopology_la_LIBADD = \
# $(LDAP_LIBS) \
# $(NULL)
appdir = $(IPA_DATA_DIR)
app_DATA = \
ipa-topology-conf.ldif \
$(NULL)
EXTRA_DIST = \
README \
$(app_DATA) \
$(NULL)
MAINTAINERCLEANFILES = \
*~ \
Makefile.in

View File

@ -0,0 +1,20 @@
dn: cn=IPA Topology Configuration,cn=plugins,cn=config
changetype: add
objectClass: top
objectClass: nsSlapdPlugin
objectClass: extensibleObject
cn: IPA Topology Configuration
nsslapd-pluginPath: libtopology
nsslapd-pluginInitfunc: ipa_topo_init
nsslapd-pluginType: object
nsslapd-pluginEnabled: on
nsslapd-topo-plugin-shared-config-base: cn=ipa,cn=etc,$SUFFIX
nsslapd-topo-plugin-shared-replica-root: $SUFFIX
nsslapd-topo-plugin-shared-binddngroup: cn=replication managers,cn=etc,$SUFFIX
nsslapd-topo-plugin-startup-delay: 20
nsslapd-pluginId: none
nsslapd-plugin-depends-on-named: ldbm database
nsslapd-plugin-depends-on-named: Multimaster Replication Plugin
nsslapd-pluginVersion: 1.0
nsslapd-pluginVendor: none
nsslapd-pluginDescription: none

View File

@ -0,0 +1,302 @@
/**
* IPA Replication Topology Plugin
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "slapi-plugin.h"
#define PLUGIN_NAME "ipa-topology-plugin"
#define PLUGIN_VENDOR "freeipa"
#define PLUGIN_VERSION "1.0"
#define IPA_TOPO_PLUGIN_SUBSYSTEM "ipa-topology-plugin"
#define IPA_TOPO_PREOP_DESC "ipa-topology-preop-subplugin"
#define IPA_TOPO_POSTOP_DESC "ipa-topology-postop-subplugin"
#define IPA_TOPO_INTERNAL_POSTOP_DESC "ipa-topology-internal-postop-subplugin"
#define AGMT_TIMEOUT "300"
#define REPL_MAN_DN "cn=replman,cn=config"
#define REPL_MAN_PASSWD "replman"
#define REPL_ATTR_LIST "(objectclass=*) $ EXCLUDE memberof idnssoaserial " \
"entryusn krblastsuccessfulauth krblastfailedauth "\
"krbloginfailedcount"
#define REPL_ATTR_STRIP "modifiersName modifyTimestamp internalModifiersName "\
"internalModifyTimestamp"
#define REPL_ATTR_LIST_TOTAL "(objectclass=*) $ EXCLUDE entryusn "\
"krblastsuccessfulauth krblastfailedauth "\
"krbloginfailedcount"
#define SEGMENT_DIR_BOTH "both"
#define SEGMENT_DIR_LEFT_ORIGIN "left-right"
#define SEGMENT_DIR_RIGHT_ORIGIN "right-left"
#define SEGMENT_LEFT_RIGHT 0x01
#define SEGMENT_RIGHT_LEFT 0x02
#define SEGMENT_BIDIRECTIONAL 0x03
#define SEGMENT_OBSOLETE 0x04
#define SEGMENT_AUTOGEN 0x05
#define SEGMENT_REMOVED 0x06
#define SEGMENT_OBSOLETE_STR "obsolete"
#define SEGMENT_AUTOGEN_STR "autogen"
#define SEGMENT_REMOVED_STR "removed"
#define TOPO_IGNORE_ENTRY 0
#define TOPO_CONFIG_ENTRY 1
#define TOPO_SEGMENT_ENTRY 2
#define TOPO_HOST_ENTRY 3
#define TOPO_DOMLEVEL_ENTRY 4
typedef struct topo_replica_agmt {
char *rdn;
char *origin; /* supplier side of agmt */
char *target; /* consumer side of agmt */
char *enabled;
char *repl_root;
char *strip_attrs;
char *total_attrs;
char *repl_attrs;
char *repl_pause;
char *repl_timeout;
char *repl_refresh;
char *repl_transport;
char *repl_bind_dn;
char *repl_bind_cred;
char *repl_bind_method;
} TopoReplicaAgmt;
typedef struct topo_replica_segment {
char *name;
int direct;
char *from;
char *to;
int state;
TopoReplicaAgmt *left;
TopoReplicaAgmt *right;
} TopoReplicaSegment;
typedef struct topo_replica_segment_list {
struct topo_replica_segment_list *next;
TopoReplicaSegment *segm;
int visited;
} TopoReplicaSegmentList;
typedef struct topo_replica_host {
struct topo_replica_host *next;
char *hostname;
} TopoReplicaHost;
typedef struct topo_replica {
struct topo_replica *next;
Slapi_Mutex *repl_lock;
char *shared_config_base;
Slapi_DN *shared_config_sdn;
char *repl_root;
TopoReplicaSegmentList *repl_segments;
TopoReplicaHost *hosts;
} TopoReplica;
typedef struct topo_replica_conf {
Slapi_Mutex *conf_lock;
int startup_inprogress;
TopoReplica *replicas;
TopoReplicaHost *allhosts; /* maybe not needed */
} TopoReplicaConf;
typedef struct topo_plugin_config {
Slapi_Mutex *plg_lock;
void *identity;
int version_major;
int version_minor;
int startup_delay;
char *hostname;
char *shared_config_base;
char *shared_topo;
Slapi_DN *shared_topo_sdn;
char *shared_hosts;
Slapi_DN *shared_hosts_sdn;
char *shared_bindgroup;
Slapi_DN *shared_bindgroup_sdn;
char *domain_level;
Slapi_DN *domain_level_sdn;
char **shared_replica_root;
char **managed_attrs;
char **restricted_attrs;
int activated;
} TopoPluginConf;
typedef struct ipa_domain_level {
int major;
int minor;
} IpaDomainLevel;
#define CONFIG_ATTR_SHARED_BASE "nsslapd-topo-plugin-shared-config-base"
#define CONFIG_ATTR_REPLICA_ROOT "nsslapd-topo-plugin-shared-replica-root"
#define CONFIG_ATTR_SHARED_BINDDNGROUP "nsslapd-topo-plugin-shared-binddngroup"
#define CONFIG_ATTR_STARTUP_DELAY "nsslapd-topo-plugin-startup-delay"
#define CONFIG_ATTR_PLUGIN_ACTIVE "nsslapd-topo-plugin-activated"
#define CONFIG_ATTR_PLUGIN_VERSION "nsslapd-pluginVersion"
/* functions to manage config and global variables */
int ipa_topo_init_plugin_config(Slapi_PBlock *pb);
void ipa_topo_init_shared_config(void);
int ipa_topo_init_config(Slapi_PBlock *pb);
void *ipa_topo_get_plugin_id(void);
int ipa_topo_get_plugin_active(void);
char *ipa_topo_get_plugin_shared_config(void);
Slapi_DN *ipa_topo_get_plugin_shared_topo_dn(void);
Slapi_DN *ipa_topo_get_plugin_shared_hosts_dn(void);
Slapi_DN *ipa_topo_get_plugin_shared_bindgroup_dn(void);
char *ipa_topo_get_plugin_shared_topo(void);
char *ipa_topo_get_plugin_shared_hosts(void);
char *ipa_topo_get_plugin_shared_bindgroup(void);
char *ipa_topo_get_plugin_hostname(void);
char **ipa_topo_get_plugin_replica_root(void);
char **ipa_topo_get_plugin_managed_attrs(void);
char **ipa_topo_get_plugin_restricted_attrs(void);
int ipa_topo_get_plugin_version_major(void);
int ipa_topo_get_plugin_version_minor(void);
char *ipa_topo_get_domain_level_entry(void);
Slapi_DN *ipa_topo_get_domain_level_entry_dn(void);
int ipa_topo_get_domain_level_major(void);
int ipa_topo_get_domain_level_minor(void);
int ipa_topo_get_plugin_startup_delay(void);
void ipa_topo_set_plugin_id(void *plg_id);
void ipa_topo_set_plugin_active(int state);
void ipa_topo_set_plugin_shared_config(char *);
void ipa_topo_set_plugin_hostname(char *hostname);
void ipa_topo_set_plugin_replica_root(char **roots);
void ipa_topo_set_plugin_managed_attrs(char **mattrs);
void ipa_topo_set_plugin_restricted_attrs(char **mattrs);
void ipa_topo_set_plugin_startup_delay(char *delay);
void ipa_topo_set_plugin_version(char *version);
int ipa_topo_cfg_plugin_suffix_is_managed(const char *be_suffix);
void ipa_topo_free_plugin_config(void);
void ipa_topo_set_domain_level(char *level);
void ipa_topo_util_check_plugin_active(void);
void ipa_topo_lock_conf(void);
void ipa_topo_unlock_conf(void);
int ipa_topo_acquire_startup_inprogress(void);
void ipa_topo_release_startup_inprogress(void);
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);
TopoReplicaSegment *
ipa_topo_cfg_segment_find(char *repl_root, char *leftHost, char *rightHost);
TopoReplicaSegment *
ipa_topo_cfg_replica_segment_find(TopoReplica *tconf, char *leftHost,
char *rightHost, 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);
void ipa_topo_cfg_segment_free(TopoReplicaSegment *tsegm);
TopoReplicaSegment *ipa_topo_cfg_segment_dup(TopoReplicaSegment *orig);
TopoReplicaAgmt *ipa_topo_cfg_agmt_dup(TopoReplicaAgmt *agmt);
TopoReplicaAgmt *ipa_topo_cfg_agmt_dup_reverse(TopoReplicaAgmt *agmt);
TopoReplica *ipa_topo_cfg_replica_new(void);
int ipa_topo_cfg_replica_add(TopoReplica *tconf);
void ipa_topo_cfg_replica_del(TopoReplica *tconf);
void ipa_topo_cfg_replica_free(TopoReplica *tconf);
TopoReplica *ipa_topo_cfg_replica_find(char *repl_root, int lock);
/* pre and postop plugin functions */
int ipa_topo_check_entry_type(Slapi_Entry *entry);
/* postop plugin functions */
int ipa_topo_post_add(Slapi_PBlock *pb);
int ipa_topo_post_mod(Slapi_PBlock *pb);
int ipa_topo_post_del(Slapi_PBlock *pb);
/* preop plugin functions */
int ipa_topo_pre_add(Slapi_PBlock *pb);
int ipa_topo_pre_mod(Slapi_PBlock *pb);
int ipa_topo_pre_del(Slapi_PBlock *pb);
/* functions to modify agreements */
int ipa_topo_agmt_new(char *hostname, TopoReplica *repl_conf,
TopoReplicaAgmt *agmt);
int ipa_topo_agmt_del_dn(char *dn);
int ipa_topo_agmt_del(char *hostname, TopoReplica *conf,
TopoReplicaAgmt *agmt);
int ipa_topo_agmt_mod(TopoReplica *conf, TopoReplicaAgmt *agmt,
LDAPMod **mod, char *direction);
int ipa_topo_agmt_setup(char *hostname, TopoReplica *repl_conf,
TopoReplicaAgmt *agmt, int isgssapi);
int ipa_topo_setup_std_agmt(char *hostname, TopoReplica *repl_conf,
TopoReplicaAgmt *agmt);
int ipa_topo_setup_gssapi_agmt(char *hostname, TopoReplica *repl_conf,
TopoReplicaAgmt *agmt);
void ipa_topo_queue_apply_shared_config(time_t event_time, void *arg);
int ipa_topo_apply_shared_config(void);
int ipa_topo_setup_managed_servers(void);
int ipa_topo_util_start(int delay);
int ipa_topo_util_update_agmt_list(TopoReplica *repl_conf,
TopoReplicaSegmentList *repl_segments);
char *ipa_topo_agmt_gen_rdn(char *from, char *to);
char *ipa_topo_agmt_std_rdn(char *to);
char *ipa_topo_agreement_dn(TopoReplica *conf, TopoReplicaAgmt *agmt, char *rdn);
char *ipa_topo_segment_dn(TopoReplica *tconf, char *segname);
void ipa_topo_util_segment_update(TopoReplica *repl_conf,
TopoReplicaSegment *repl_segment,
LDAPMod **mods ,char *fromHost);
void ipa_topo_util_missing_agmts_add(TopoReplica *repl_conf,
TopoReplicaSegment *repl_segment,
char *fromHost);
void ipa_topo_util_existing_agmts_del(TopoReplica *repl_conf,
TopoReplicaSegment *repl_segment,
char *fromHost);
void ipa_topo_util_existing_agmts_update(TopoReplica *repl_conf,
TopoReplicaSegment *repl_segment,
LDAPMod **mods ,char *fromHost);
void ipa_topo_util_missing_agmts_add_list(TopoReplica *repl_conf,
TopoReplicaSegmentList *repl_segments,
char *fromHost);
void ipa_topo_util_existing_agmts_del_list(TopoReplica *repl_conf,
TopoReplicaSegmentList *repl_segments,
char *fromHost);
void ipa_topo_util_existing_agmts_update_list(TopoReplica *repl_conf,
TopoReplicaSegmentList *repl_segments,
LDAPMod **mods ,char *fromHost);
TopoReplicaAgmt *ipa_topo_util_agmt_from_entry(Slapi_Entry *entry,
char* replRoot, char *fromHost,
char *toHost, char *direction);
TopoReplicaAgmt *
ipa_topo_util_find_segment_agmt(TopoReplicaSegmentList *repl_segments,
char *fromHost, char *toHost);
void ipa_topo_util_segm_update(TopoReplica *tconf, TopoReplicaSegment *tsegm,
int property);
int ipa_topo_util_segment_write(TopoReplica *tconf, TopoReplicaSegment *tsegm);
void ipa_topo_util_segm_remove(TopoReplica *tconf, TopoReplicaSegment *tsegm);
void ipa_topo_util_segment_merge(TopoReplica *tconf,
TopoReplicaSegment *tsegm);
int ipa_topo_util_agmt_mark(TopoReplica *tconf, Slapi_Entry * repl_agmt,
TopoReplicaSegment *tsegm);
int ipa_topo_util_agmt_is_marked(Slapi_Entry * repl_agmt);
char *ipa_topo_agmt_attr_is_managed(char *type, char *direction);
int ipa_topo_cfg_attr_is_restricted(char *type);
int ipa_topo_util_setup_servers(void);
void ipa_topo_util_update_segments_for_host(Slapi_Entry *hostentry);
char *ipa_topo_util_get_ldap_principal(char *repl_root, char *hostname);
void ipa_topo_util_disable_repl_for_principal(char *repl_root, char *principal);
void ipa_topo_util_delete_host(Slapi_Entry *hostentry);
void ipa_topo_util_disable_repl_from_host(char *repl_root, char *delhost);
void ipa_topo_util_delete_segments_for_host(char *repl_root, char *delhost);
int ipa_topo_util_entry_is_candidate(Slapi_Entry *e);
int ipa_topo_util_target_is_managed(Slapi_Entry *e);
char * ipa_topo_util_get_segm_attr(TopoReplicaAgmt *agmt, char *attr_type);
void ipa_topo_util_set_segm_attr(TopoReplicaAgmt *agmt, char *attr_type,
char *attr_val);
TopoReplicaSegment *ipa_topo_util_segm_from_agmt(Slapi_Entry *repl_agmt);
TopoReplicaSegment *ipa_topo_util_segment_from_entry(TopoReplica *conf,
Slapi_Entry *entry);
TopoReplicaSegment *ipa_topo_util_find_segment(TopoReplica *conf,
Slapi_Entry *entry);
TopoReplica *ipa_topo_util_conf_from_entry(Slapi_Entry *entry);
TopoReplica *ipa_topo_util_get_conf_for_segment(Slapi_Entry *segment_entry);
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_replica_segments(TopoReplica *replica);
void ipa_topo_util_set_domain_level(void);

View File

@ -0,0 +1,314 @@
#include "topology.h"
/* generate the dn for a topology segment by providing replroot and segment name */
char *
ipa_topo_segment_dn(TopoReplica *tconf, char *segname)
{
char *dn = NULL;
dn = slapi_ch_smprintf("cn=%s,%s", segname, tconf->shared_config_base);
return dn;
}
/* generate the rdn for a replication agreement by providing connected nodes */
char *
ipa_topo_agmt_gen_rdn(char *from, char *to)
{
char *agmt_rdn = slapi_ch_smprintf("cn=%s-to-%s", from, to);
return agmt_rdn;
}
/* generate the rdn for a replication agreement by providing target node */
char *
ipa_topo_agmt_std_rdn(char *to)
{
char *agmt_rdn = slapi_ch_smprintf("cn=meTo%s", to);
return agmt_rdn;
}
/* generate the dn for a replication agreement by providing replroot and host */
char *
ipa_topo_agreement_dn(TopoReplica *conf, TopoReplicaAgmt *agmt, char *rdn)
{
char *dn;
char *filter;
Slapi_PBlock *pb;
Slapi_Entry **entries;
int ret;
pb = slapi_pblock_new();
filter = slapi_ch_smprintf("(&(objectclass=nsds5replica)(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, &ret);
if (ret != 0) {
dn = NULL;
} 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_agreement_dn: no replica found\n");
dn = NULL;
} else if (rdn) {
dn = slapi_ch_smprintf("%s,%s", rdn,
slapi_entry_get_dn_const(entries[0]));
} else {
dn = slapi_ch_smprintf("cn=meTo%s,%s", agmt->target,
slapi_entry_get_dn_const(entries[0]));
}
}
slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
return dn;
}
int
ipa_topo_agmt_new(char *hostname, TopoReplica *conf, TopoReplicaAgmt *agmt)
{
int ret = 0;
if (strcasecmp(agmt->repl_bind_method,"SASL/GSSAPI") == 0) {
ret = ipa_topo_agmt_setup(hostname, conf, agmt, 1);
} else {
ret = ipa_topo_agmt_setup(hostname, conf, agmt, 0);
}
return ret;
}
int ipa_topo_agmt_mod(TopoReplica *conf, TopoReplicaAgmt *agmt, LDAPMod **mods,
char *direction)
{
int ret;
Slapi_PBlock *pb;
char *dn = NULL;
Slapi_Entry **entries;
int i;
LDAPMod *tmp;
Slapi_Mods *smods = NULL;
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
if (dn == NULL)
return 1;
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, &ret);
if (ret != 0) {
/* search failed */
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_agmt_mod: agreement not found: %s\n", dn);
goto done;
}
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
if (NULL == entries || NULL == entries[0]) {
/* no entry */
ret = 1;
goto done;
}
/* apply mods to entry */
smods = slapi_mods_new();
for (i = 0; (mods != NULL) && (mods[i] != NULL); i++) {
char *type = ipa_topo_agmt_attr_is_managed(mods[i]->mod_type,direction);
if (type) {
tmp = mods[i];
switch (tmp->mod_op & ~LDAP_MOD_BVALUES) {
case LDAP_MOD_DELETE:
break;
case LDAP_MOD_ADD:
case LDAP_MOD_REPLACE:
slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE,
type, tmp->mod_bvalues);
break;
}
slapi_ch_free_string(&type);
}
}
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);
} else {
slapi_ch_free_string(&dn);
}
slapi_mods_free(&smods);
done:
if (ret) slapi_ch_free_string(&dn);
slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
return ret;
}
int
ipa_topo_agmt_del(char *hostname, TopoReplica *conf, TopoReplicaAgmt *agmt)
{
char *dn = NULL;
int rc;
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_agmt_del: %s\n", agmt->rdn?agmt->rdn:"RDN missing");
if (dn == NULL)
return (-1);
rc = ipa_topo_agmt_del_dn(dn);
slapi_ch_free_string(&dn);
return rc;
}
int
ipa_topo_agmt_del_dn(char *dn)
{
int ret = 0;
Slapi_PBlock *pb;
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);
return ret;
}
int
ipa_topo_agmt_setup(char *hostname, TopoReplica *conf,
TopoReplicaAgmt *agmt, int isgssapi)
{
Slapi_Entry *e = NULL;
Slapi_PBlock *pb;
char *dn = NULL;
Slapi_DN *sdn = NULL;
char *cn;
char port[] = "389";
char *description;
int ret;
/* Set up the new replication agreement entry */
agmt->rdn = ipa_topo_agmt_gen_rdn(agmt->origin, agmt->target);
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
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, "nsds5replicationagreement");
slapi_entry_add_string(e, SLAPI_ATTR_OBJECTCLASS, "ipaReplTopoManagedAgreement");
cn = slapi_ch_smprintf("%s-to-%s", agmt->origin, agmt->target);
slapi_entry_add_string(e, "cn",cn);
slapi_ch_free_string(&cn);
slapi_entry_add_string(e, "nsds5replicahost",hostname);
slapi_entry_add_string(e, "nsds5replicaport",port);
slapi_entry_add_string(e, "nsds5replicatimeout",AGMT_TIMEOUT);
slapi_entry_add_string(e, "nsds5replicaroot",agmt->repl_root);
description = slapi_ch_smprintf("%s to %s", ipa_topo_get_plugin_hostname(), hostname);
slapi_entry_add_string(e, "description",description);
slapi_ch_free_string(&description);
slapi_entry_add_string(e, "ipaReplTopoManagedAgreementState",
"managed agreement - generated by topology plugin");
if (isgssapi) {
slapi_entry_add_string(e, "nsds5replicatransportinfo","LDAP");
slapi_entry_add_string(e, "nsds5replicabindmethod","SASL/GSSAPI");
} else {
slapi_entry_add_string(e, "nsds5replicabinddn",REPL_MAN_DN);
slapi_entry_add_string(e, "nsds5replicacredentials",REPL_MAN_PASSWD);
slapi_entry_add_string(e, "nsds5replicatransportinfo","TLS");
slapi_entry_add_string(e, "nsds5replicabindmethod","simple");
}
if (agmt->repl_attrs) {
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeList",agmt->repl_attrs);
} else {
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeList", REPL_ATTR_LIST);
}
if (agmt->strip_attrs) {
slapi_entry_add_string(e, "nsds5ReplicaStripAttrs", agmt->strip_attrs);
} else {
slapi_entry_add_string(e, "nsds5ReplicaStripAttrs", REPL_ATTR_STRIP);
}
if (agmt->total_attrs) {
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeListTotal",
agmt->total_attrs);
} else {
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeListTotal",
REPL_ATTR_LIST_TOTAL);
}
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;
}
int
ipa_topo_agmt_initialize_replication(char *hostname,
TopoReplica *conf, TopoReplicaAgmt *agmt)
{
int ret = 0;
char *dn;
Slapi_Mods *smods = slapi_mods_new();
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
"nsds5ReplicaEnabled", "on");
slapi_mods_add_string(smods, LDAP_MOD_ADD,
"nsds5BeginReplicaRefresh", "start");
if (slapi_mods_get_num_mods(smods) > 0) {
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
Slapi_DN *sdn = slapi_sdn_new_normdn_byref(dn);
ipa_topo_util_modify(sdn, smods);
slapi_sdn_free(&sdn);
}
slapi_mods_free(&smods);
return ret;
}
char *
ipa_topo_agmt_attr_is_managed(char *type, char *direction)
{
char *mtype = NULL;
char **mattrs = NULL;
char *subtype;
char *ctype = slapi_ch_strdup(type);
int i;
/* segment attrs have the form
* attrtype od attrtype;direction
* find the attrtype and return the corresponding
* repl agreeement attribute type
*/
subtype = strchr(ctype,';');
if (subtype) {
/* attr is handling specific direction,
* check if interested
*/
if (strstr(ctype,direction)) {
*subtype = '\0';
} else {
return NULL;
}
}
mattrs = ipa_topo_get_plugin_managed_attrs();
for (i=0; mattrs[i]; i++) {
if(0 == strcasecmp(mattrs[i], ctype)) {
mtype = slapi_ch_strdup(mattrs[i]);
break;
}
}
return mtype;
}

View File

@ -0,0 +1,888 @@
#include "topology.h"
/* two static data structures to hold the
* plugin configuration and the information
* stored in the shared tree.
* They will be initialized at plugin init/start,
* updated when the shared config is modified
* and accessed via set/get functions
*/
static TopoPluginConf topo_plugin_conf = {0};
static TopoReplicaConf topo_shared_conf = {0};
static IpaDomainLevel ipa_domain_level = {0,0};
char *ipa_topo_plugin_managed_attrs[] = {
"nsds5ReplicaStripAttrs",
"nsds5ReplicatedAttributeList",
"nsDS5ReplicatedAttributeListTotal",
"nsds5BeginReplicaRefresh",
"nsds5replicaTimeout",
"nsds5ReplicaEnabled",
"nsds5replicaSessionPauseTime",
"nsds5replicabinddn",
"nsds5replicacredentials",
"nsds5replicatransportinfo",
"nsds5replicabindmethod",
NULL };
/* subset of attrs which can only be modified via
* modification of segments in the shared tree.
* Other attributes still can be directly modified
* eg to reinit a replica or change bind method and
* credentials.
* This is currently needed to make ipa-replica-install work
*/
char *ipa_topo_plugin_restricted_attrs[] = {
"nsds5ReplicaStripAttrs",
"nsds5ReplicatedAttributeList",
"nsDS5ReplicatedAttributeListTotal",
"nsds5replicaTimeout",
"nsds5replicaSessionPauseTime",
NULL };
void *
ipa_topo_get_plugin_id(void)
{
return topo_plugin_conf.identity;
}
char *
ipa_topo_get_plugin_hostname(void)
{
return topo_plugin_conf.hostname;
}
char **
ipa_topo_get_plugin_managed_attrs(void)
{
return topo_plugin_conf.managed_attrs;
}
char **
ipa_topo_get_plugin_restricted_attrs(void)
{
return topo_plugin_conf.restricted_attrs;
}
char *
ipa_topo_get_plugin_shared_config(void)
{
return topo_plugin_conf.shared_config_base;
}
char *
ipa_topo_get_plugin_shared_topo(void)
{
return topo_plugin_conf.shared_topo;
}
Slapi_DN *
ipa_topo_get_plugin_shared_topo_dn(void)
{
return topo_plugin_conf.shared_topo_sdn;
}
char *
ipa_topo_get_domain_level_entry(void)
{
return topo_plugin_conf.domain_level;
}
Slapi_DN *
ipa_topo_get_domain_level_entry_dn(void)
{
return topo_plugin_conf.domain_level_sdn;
}
int
ipa_topo_get_domain_level_major(void)
{
return ipa_domain_level.major;
}
int
ipa_topo_get_domain_level_minor(void)
{
return ipa_domain_level.minor;
}
char *
ipa_topo_get_plugin_shared_hosts(void)
{
return topo_plugin_conf.shared_hosts;
}
Slapi_DN *
ipa_topo_get_plugin_shared_hosts_dn(void)
{
return topo_plugin_conf.shared_hosts_sdn;
}
char *
ipa_topo_get_plugin_shared_bindgroup(void)
{
return topo_plugin_conf.shared_bindgroup;
}
Slapi_DN *
ipa_topo_get_plugin_shared_bindgroup_dn(void)
{
return topo_plugin_conf.shared_bindgroup_sdn;
}
char **
ipa_topo_get_plugin_replica_root(void)
{
return topo_plugin_conf.shared_replica_root;
}
int
ipa_topo_get_plugin_version_major(void)
{
return topo_plugin_conf.version_major;
}
int
ipa_topo_get_plugin_version_minor(void)
{
return topo_plugin_conf.version_minor;
}
int
ipa_topo_get_plugin_startup_delay(void)
{
return topo_plugin_conf.startup_delay;
}
void
ipa_topo_set_plugin_id(void *plg_id)
{
topo_plugin_conf.identity = plg_id;
}
void
ipa_topo_set_plugin_active(int state)
{
topo_plugin_conf.activated = state;
}
int
ipa_topo_get_plugin_active(void)
{
return topo_plugin_conf.activated;
}
void
ipa_topo_set_plugin_shared_config(char *cfg)
{
char *topo;
char *hosts;
char *domain_level;
topo_plugin_conf.shared_config_base = cfg;
topo = slapi_ch_smprintf("%s,%s","cn=topology",cfg);
hosts = slapi_ch_smprintf("%s,%s","cn=masters",cfg);
domain_level = slapi_ch_smprintf("%s,%s","cn=domain level",cfg);
topo_plugin_conf.shared_topo = topo;
topo_plugin_conf.shared_topo_sdn = slapi_sdn_new_normdn_byref(topo);
topo_plugin_conf.shared_hosts = hosts;
topo_plugin_conf.shared_hosts_sdn = slapi_sdn_new_normdn_byref(hosts);
topo_plugin_conf.domain_level = domain_level;
topo_plugin_conf.domain_level_sdn = slapi_sdn_new_normdn_byref(domain_level);
}
void
ipa_topo_set_plugin_shared_bindgroup(char *bindgroup)
{
topo_plugin_conf.shared_bindgroup = bindgroup;
topo_plugin_conf.shared_bindgroup_sdn = slapi_sdn_new_normdn_byref(bindgroup);
}
void
ipa_topo_set_domain_level(char *level)
{
char *minor;
if (level == NULL) {
ipa_domain_level.major = 0;
ipa_domain_level.minor = 0;
return;
}
minor = strchr(level,'.');
if (minor) {
*minor = '\0';
ipa_domain_level.minor = atoi(++minor);
} else {
ipa_domain_level.minor = 0;
}
ipa_domain_level.major = atoi(level);
}
void
ipa_topo_set_plugin_hostname(char *hostname)
{
topo_plugin_conf.hostname = hostname;
}
#define TOPO_PLUGIN_DEFAULT_STARTUP_DELAY 20
void
ipa_topo_set_plugin_startup_delay(char *delay)
{
if (delay) {
topo_plugin_conf.startup_delay = atoi(delay);
} else {
topo_plugin_conf.startup_delay = TOPO_PLUGIN_DEFAULT_STARTUP_DELAY;
}
}
void
ipa_topo_set_plugin_version(char *version)
{
char *minor;
if ( version == NULL) {
topo_plugin_conf.version_major = 0;
topo_plugin_conf.version_minor = 0;
return;
}
minor = strchr(version,'.');
if (minor) {
*minor = '\0';
topo_plugin_conf.version_minor = atoi(++minor);
} else {
topo_plugin_conf.version_minor = 0;
}
topo_plugin_conf.version_major = atoi(version);
}
void
ipa_topo_init_shared_config(void)
{
topo_shared_conf.allhosts = NULL;
topo_shared_conf.replicas = NULL;
topo_shared_conf.conf_lock = slapi_new_mutex();
}
void
ipa_topo_set_plugin_managed_attrs(char **attrs)
{
if (attrs) {
topo_plugin_conf.managed_attrs = attrs;
} else {
topo_plugin_conf.managed_attrs = ipa_topo_plugin_managed_attrs;
}
}
void
ipa_topo_set_plugin_restricted_attrs(char **attrs)
{
if (attrs) {
topo_plugin_conf.restricted_attrs = attrs;
} else {
topo_plugin_conf.restricted_attrs = ipa_topo_plugin_restricted_attrs;
}
}
int
ipa_topo_cfg_plugin_suffix_is_managed(const char *be_suffix) {
int i = 0;
char **shared_replica_root = ipa_topo_get_plugin_replica_root();
while (shared_replica_root[i]) {
if (0 == strcasecmp(shared_replica_root[i], be_suffix)) return 1;
i++;
}
return 0;
}
int
ipa_topo_cfg_attr_is_restricted(char *type)
{
int i;
int rc = 0;
char **rattrs = ipa_topo_get_plugin_restricted_attrs();
for (i=0; rattrs[i]; i++) {
if(0 == strcasecmp(rattrs[i], type)) {
rc = 1;
break;
}
}
return rc;
}
void
ipa_topo_set_plugin_replica_root(char **root)
{
topo_plugin_conf.shared_replica_root = root;
}
int
ipa_topo_init_plugin_config(Slapi_PBlock * pb)
{
Slapi_Entry *plugin_entry = NULL;
char *hostname;
char *config_base;
char *startup_delay;
char *plugin_version;
char *bindgroup;
char **replica_root;
/* get the local hostname */
hostname = ipa_topo_util_get_pluginhost();
if (hostname == NULL) {
/* log error */
return -1;
} else {
ipa_topo_set_plugin_hostname(hostname);
}
/* get the args */
/* slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry); */
slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &plugin_entry);
if(plugin_entry == NULL){
return -1;
}
ipa_topo_set_plugin_active(0);
config_base = slapi_entry_attr_get_charptr(plugin_entry,
CONFIG_ATTR_SHARED_BASE);
if(config_base){
ipa_topo_set_plugin_shared_config(config_base);
}
replica_root = slapi_entry_attr_get_charray(plugin_entry,
CONFIG_ATTR_REPLICA_ROOT);
if(replica_root){
ipa_topo_set_plugin_replica_root(replica_root);
}
bindgroup = slapi_entry_attr_get_charptr(plugin_entry,
CONFIG_ATTR_SHARED_BINDDNGROUP);
if(bindgroup){
ipa_topo_set_plugin_shared_bindgroup(bindgroup);
}
startup_delay = slapi_entry_attr_get_charptr(plugin_entry,
CONFIG_ATTR_STARTUP_DELAY);
ipa_topo_set_plugin_startup_delay(startup_delay);
slapi_ch_free_string(&startup_delay);
plugin_version = slapi_entry_attr_get_charptr(plugin_entry,
CONFIG_ATTR_PLUGIN_VERSION);
ipa_topo_set_plugin_version(plugin_version);
slapi_ch_free_string(&plugin_version);
ipa_topo_util_set_domain_level();
ipa_topo_util_check_plugin_active();
ipa_topo_set_plugin_managed_attrs(NULL); /* use defaults */
ipa_topo_set_plugin_restricted_attrs(NULL); /* use defaults */
return 0;
}
void
ipa_topo_free_plugin_config(void)
{
slapi_destroy_mutex(topo_plugin_conf.plg_lock);
slapi_ch_free((void **)topo_plugin_conf.identity);
slapi_ch_free_string(&topo_plugin_conf.hostname);
slapi_ch_free_string(&topo_plugin_conf.shared_config_base);
slapi_ch_free_string(&topo_plugin_conf.shared_topo);
slapi_sdn_free(&topo_plugin_conf.shared_topo_sdn);
slapi_ch_free_string(&topo_plugin_conf.shared_hosts);
slapi_sdn_free(&topo_plugin_conf.shared_hosts_sdn);
slapi_ch_free_string(&topo_plugin_conf.shared_bindgroup);
slapi_sdn_free(&topo_plugin_conf.shared_bindgroup_sdn);
slapi_ch_free_string(&topo_plugin_conf.domain_level);
slapi_sdn_free(&topo_plugin_conf.domain_level_sdn);
slapi_ch_array_free(topo_plugin_conf.shared_replica_root);
if (ipa_topo_plugin_managed_attrs != topo_plugin_conf.managed_attrs)
slapi_ch_array_free(topo_plugin_conf.managed_attrs);
if (ipa_topo_plugin_restricted_attrs != topo_plugin_conf.restricted_attrs)
slapi_ch_array_free(topo_plugin_conf.restricted_attrs);
}
void
ipa_topo_lock_conf(void)
{
slapi_lock_mutex(topo_shared_conf.conf_lock);
}
void
ipa_topo_unlock_conf(void)
{
slapi_unlock_mutex(topo_shared_conf.conf_lock);
}
int
ipa_topo_acquire_startup_inprogress(void)
{
int acquired = 0;
slapi_lock_mutex(topo_shared_conf.conf_lock);
if (topo_shared_conf.startup_inprogress == 0 ) {
topo_shared_conf.startup_inprogress = 1;
acquired = 1;
}
slapi_unlock_mutex(topo_shared_conf.conf_lock);
return acquired;
}
void
ipa_topo_release_startup_inprogress(void)
{
slapi_lock_mutex(topo_shared_conf.conf_lock);
topo_shared_conf.startup_inprogress = 0;
slapi_unlock_mutex(topo_shared_conf.conf_lock);
}
TopoReplicaHost *
ipa_topo_cfg_host_find(TopoReplica *tconf, char *findhost, int lock)
{
TopoReplicaHost *host = NULL;
if (tconf->hosts == NULL) return NULL;
if (lock) slapi_lock_mutex(tconf->repl_lock);
for (host=tconf->hosts;host;host=host->next) {
if (!strcasecmp(host->hostname,findhost)) {
break;
}
}
if (lock) slapi_unlock_mutex(tconf->repl_lock);
return host;
}
TopoReplicaHost *
ipa_topo_cfg_host_new(char *newhost)
{
TopoReplicaHost *newnode;
newnode = (TopoReplicaHost *)slapi_ch_malloc(sizeof(TopoReplicaHost));
newnode->next = NULL;
newnode->hostname = newhost;
return newnode;
}
void
ipa_topo_cfg_host_add(Slapi_Entry *hostentry)
{
char *newhost;
char **repl_root = NULL;
TopoReplicaHost *hostnode = NULL;
TopoReplica *replica = NULL;
int i;
newhost = slapi_entry_attr_get_charptr(hostentry,"cn");
if (newhost == NULL) return;
repl_root = slapi_entry_attr_get_charray(hostentry,"ipaReplTopoManagedSuffix");
if (repl_root == NULL || *repl_root == NULL) return;
for (i=0; repl_root[i];i++) {
replica = ipa_topo_cfg_replica_find(repl_root[i], 1);
if (replica == NULL) continue;
slapi_lock_mutex(replica->repl_lock);
if (ipa_topo_cfg_host_find(replica, newhost, 0)) {
/* log error */
slapi_unlock_mutex(replica->repl_lock);
continue;
}
hostnode = ipa_topo_cfg_host_new(slapi_ch_strdup(newhost));
hostnode->next = replica->hosts;
replica->hosts = hostnode;
slapi_unlock_mutex(replica->repl_lock);
}
slapi_ch_array_free(repl_root);
slapi_ch_free_string(&newhost);
return;
}
void
ipa_topo_cfg_host_free(TopoReplicaHost **node)
{
slapi_ch_free((void **)&((*node)->hostname));
slapi_ch_free((void **)node);
}
void
ipa_topo_cfg_host_del(Slapi_Entry *hostentry)
{
char *delhost;
TopoReplicaHost *hostnode = NULL;
TopoReplicaHost *prevnode = NULL;
char **repl_root = NULL;
TopoReplica *replica = NULL;
int i;
delhost = slapi_entry_attr_get_charptr(hostentry,"cn");
if (delhost == NULL) return;
repl_root = slapi_entry_attr_get_charray(hostentry,"ipaReplTopoManagedSuffix");
if (repl_root == NULL || *repl_root == NULL) return;
for (i=0; repl_root[i];i++) {
replica = ipa_topo_cfg_replica_find(repl_root[i], 1);
if (replica == NULL) continue;
slapi_lock_mutex(replica->repl_lock);
hostnode = replica->hosts;
while (hostnode) {
if (!strcasecmp(hostnode->hostname,delhost)) {
/*remove from list and free*/
if (prevnode) {
prevnode->next = hostnode->next;
} else {
replica->hosts = hostnode->next;
}
ipa_topo_cfg_host_free(&hostnode);
break;
} else {
prevnode = hostnode;
hostnode = hostnode->next;
}
}
slapi_unlock_mutex(replica->repl_lock);
}
return;
}
TopoReplicaSegment *
ipa_topo_cfg_replica_segment_find(TopoReplica *replica, char *leftHost, char *rightHost, int lock)
{
TopoReplicaSegment *tsegm = NULL;
TopoReplicaSegmentList *segments = NULL;
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)) ||
(!strcasecmp(leftHost,tsegm->to) && !strcasecmp(rightHost,tsegm->from) &&
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_RIGHT_LEFT))) {
break;
}
tsegm = NULL;
segments = segments->next;
}
if (lock) slapi_unlock_mutex(replica->repl_lock);
return tsegm;
}
TopoReplicaAgmt *
ipa_topo_cfg_agmt_dup(TopoReplicaAgmt *agmt)
{
TopoReplicaAgmt *dup = NULL;
if (agmt == NULL) return NULL;
dup = (TopoReplicaAgmt *) slapi_ch_calloc(1,sizeof(TopoReplicaAgmt));
dup->rdn = slapi_ch_strdup(agmt->rdn);
dup->origin = slapi_ch_strdup(agmt->origin);
dup->target = slapi_ch_strdup(agmt->target);
dup->enabled = slapi_ch_strdup(agmt->enabled);
dup->repl_root = slapi_ch_strdup(agmt->repl_root);
dup->strip_attrs = slapi_ch_strdup(agmt->strip_attrs);
dup->total_attrs = slapi_ch_strdup(agmt->total_attrs);
dup->repl_attrs = slapi_ch_strdup(agmt->repl_attrs);
dup->repl_pause = slapi_ch_strdup(agmt->repl_pause);
dup->repl_timeout = slapi_ch_strdup(agmt->repl_timeout);
dup->repl_refresh = slapi_ch_strdup(agmt->repl_refresh);
dup->repl_transport = slapi_ch_strdup(agmt->repl_transport);
dup->repl_bind_dn = slapi_ch_strdup(agmt->repl_bind_dn);
dup->repl_bind_cred = slapi_ch_strdup(agmt->repl_bind_cred);
dup->repl_bind_method = slapi_ch_strdup(agmt->repl_bind_method);
return dup;
}
TopoReplicaAgmt *
ipa_topo_cfg_agmt_dup_reverse(TopoReplicaAgmt *agmt)
{
char *tmp;
TopoReplicaAgmt *dup = NULL;
dup = ipa_topo_cfg_agmt_dup(agmt);
if (dup == NULL) return NULL;
tmp = dup->origin;
dup->origin = dup->target;
dup->target = tmp;
/* this is not enough, if a reverse agmt is
* created because segment becomes bidirectional
* we don't really know the rdn of the other direction
* As long as this info is not in the segment,
* assume std agmt naming and do best effort.
*/
slapi_ch_free_string(&dup->rdn);
dup->rdn = ipa_topo_agmt_std_rdn(dup->target);
return dup;
}
static void
ipa_topo_cfg_agmt_done(TopoReplicaAgmt *agmt)
{
if (agmt == NULL) return;
slapi_ch_free_string(&agmt->origin);
slapi_ch_free_string(&agmt->target);
slapi_ch_free_string(&agmt->enabled);
slapi_ch_free_string(&agmt->repl_root);
slapi_ch_free_string(&agmt->strip_attrs);
slapi_ch_free_string(&agmt->total_attrs);
slapi_ch_free_string(&agmt->repl_attrs);
slapi_ch_free_string(&agmt->repl_pause);
slapi_ch_free_string(&agmt->repl_timeout);
slapi_ch_free_string(&agmt->repl_refresh);
slapi_ch_free_string(&agmt->repl_transport);
slapi_ch_free_string(&agmt->repl_bind_dn);
slapi_ch_free_string(&agmt->repl_bind_cred);
slapi_ch_free_string(&agmt->repl_bind_method);
}
static void
ipa_topo_cfg_segment_done(TopoReplicaSegment *tsegm)
{
if (tsegm == NULL) return;
slapi_ch_free_string(&tsegm->name);
slapi_ch_free_string(&tsegm->from);
slapi_ch_free_string(&tsegm->to);
ipa_topo_cfg_agmt_done(tsegm->left);
ipa_topo_cfg_agmt_done(tsegm->right);
slapi_ch_free((void **)&tsegm->left);
slapi_ch_free((void **)&tsegm->right);
}
void
ipa_topo_cfg_segment_free(TopoReplicaSegment *tsegm)
{
ipa_topo_cfg_segment_done(tsegm);
slapi_ch_free((void **)&tsegm);
}
TopoReplicaSegment *
ipa_topo_cfg_segment_dup(TopoReplicaSegment *orig)
{
TopoReplicaSegment *dup = NULL;
if (orig == NULL) return NULL;
dup = (TopoReplicaSegment *) slapi_ch_calloc(1,sizeof(TopoReplicaSegment));
dup->name = slapi_ch_strdup(orig->name);
dup->from = slapi_ch_strdup(orig->from);
dup->to = slapi_ch_strdup(orig->to);
dup->left = ipa_topo_cfg_agmt_dup(orig->left);
dup->left = ipa_topo_cfg_agmt_dup(orig->left);
dup->direct = orig->direct;
dup->state = orig->state;
return dup;
}
TopoReplicaSegment *
ipa_topo_cfg_segment_find(char *repl_root, char *leftHost, char *rightHost)
{
TopoReplicaSegment *tsegm = NULL;
TopoReplica *replica = NULL;
slapi_lock_mutex(topo_shared_conf.conf_lock);
replica = ipa_topo_cfg_replica_find(repl_root, 0);
if (replica) {
tsegm = ipa_topo_cfg_replica_segment_find(replica,leftHost,rightHost, 1);
}
slapi_unlock_mutex(topo_shared_conf.conf_lock);
return tsegm;
}
void
ipa_topo_cfg_segment_set_visited(TopoReplica *replica, TopoReplicaSegment *vsegm)
{
TopoReplicaSegmentList *segments = NULL;
TopoReplicaSegment *tsegm = NULL;
char *leftHost = vsegm->from;
char *rightHost = vsegm->to;
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)) ||
(!strcasecmp(leftHost,tsegm->to) && !strcasecmp(rightHost,tsegm->from) &&
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_RIGHT_LEFT))) {
segments->visited = 1;
break;
}
tsegm = NULL;
segments = segments->next;
}
slapi_unlock_mutex(replica->repl_lock);
}
void
ipa_topo_cfg_segment_add(TopoReplica *replica, TopoReplicaSegment *tsegm)
{
TopoReplicaSegmentList *seglist = NULL;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_cfg_segment_add: %s\n", tsegm->name);
slapi_lock_mutex(replica->repl_lock);
if (ipa_topo_cfg_replica_segment_find(replica,
tsegm->from,
tsegm->to, 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",
tsegm->name);
goto done;
}
seglist = (TopoReplicaSegmentList *)
slapi_ch_calloc(1,sizeof(TopoReplicaSegmentList));
seglist->visited = 0;
seglist->segm = tsegm;
if (replica->repl_segments == NULL) {
replica->repl_segments = seglist;
} else {
seglist->next = replica->repl_segments;
replica->repl_segments = seglist;
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_cfg_segment_added: %s\n", tsegm->name);
done:
slapi_unlock_mutex(replica->repl_lock);
}
void
ipa_topo_cfg_segment_del(TopoReplica *tconf, TopoReplicaSegment *tsegm)
{
TopoReplicaSegmentList *segment = NULL;
TopoReplicaSegmentList *prev = NULL;
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;
while (segment) {
if (segment->segm == tsegm) {
if (prev == NULL) {
tconf->repl_segments = segment->next;
} else {
prev->next = segment->next;
}
/* free segment */
ipa_topo_cfg_segment_free(tsegm);
slapi_ch_free((void **)&segment);
break;
}
prev = segment;
segment = segment->next;
}
slapi_unlock_mutex(tconf->repl_lock);
}
TopoReplica *
ipa_topo_cfg_replica_new(void)
{
TopoReplica *topoRepl;
topoRepl = (TopoReplica *)slapi_ch_malloc(sizeof(TopoReplica));
if (topoRepl) {
topoRepl->next = NULL;
topoRepl->repl_segments = NULL;
topoRepl->repl_root = NULL;
topoRepl->shared_config_base = NULL;
topoRepl->hosts = NULL;
topoRepl->repl_lock = slapi_new_mutex();
}
return topoRepl;
}
int
ipa_topo_cfg_replica_add(TopoReplica *tconf)
{
int rc = 0;
slapi_lock_mutex(topo_shared_conf.conf_lock);
if (topo_shared_conf.replicas == NULL) {
topo_shared_conf.replicas = tconf;
} else if (ipa_topo_cfg_replica_find(tconf->repl_root,0)) {
/* log error: already exists */
rc = -1;
} else {
tconf->next = topo_shared_conf.replicas;
topo_shared_conf.replicas = tconf;
}
slapi_unlock_mutex(topo_shared_conf.conf_lock);
return rc;
}
void
ipa_topo_cfg_replica_del(TopoReplica *tconf)
{
/* TBD */
}
void
ipa_topo_cfg_replica_free(TopoReplica *tconf)
{
TopoReplicaSegmentList *seg, *seg_next;
TopoReplicaHost *host, *host_next;
if (tconf) {
slapi_destroy_mutex(tconf->repl_lock);
slapi_ch_free_string(&tconf->shared_config_base);
slapi_ch_free_string(&tconf->repl_root);
slapi_sdn_free(&tconf->shared_config_sdn);
seg = tconf->repl_segments;
while (seg) {
seg_next = seg->next;
ipa_topo_cfg_segment_free(seg->segm);
slapi_ch_free((void **)&seg);
seg = seg_next;
}
host = tconf->hosts;
while (host) {
host_next = host->next;
slapi_ch_free_string(&host->hostname);
host = host_next;
slapi_ch_free((void **)&host);
}
slapi_ch_free((void **)&tconf);
}
}
TopoReplica *
ipa_topo_cfg_replica_find(char *repl_root, int lock)
{
TopoReplica *tconf = NULL;
if (lock) {
slapi_lock_mutex(topo_shared_conf.conf_lock);
}
if (topo_shared_conf.replicas == NULL) goto done;
tconf = topo_shared_conf.replicas;
while (tconf) {
if (!strcasecmp(repl_root,tconf->repl_root)) {
break;
}
tconf = tconf->next;
}
done:
if (lock) {
slapi_unlock_mutex(topo_shared_conf.conf_lock);
}
return tconf;
}

View File

@ -0,0 +1,313 @@
#include "topology.h"
char *ipa_topo_plugin_hostname;
char *ipa_topo_plugin_shared_config_base;
int ipa_topo_plugin_activated;
static Slapi_PluginDesc pdesc = { PLUGIN_NAME, PLUGIN_VENDOR, PLUGIN_VERSION,
IPA_TOPO_PLUGIN_SUBSYSTEM };
static int ipa_topo_start(Slapi_PBlock * pb);
static int ipa_topo_close(Slapi_PBlock * pb);
static int ipa_topo_preop_init(Slapi_PBlock *pb);
static int ipa_topo_postop_init(Slapi_PBlock *pb);
static int ipa_topo_internal_postop_init(Slapi_PBlock *pb);
static int ipa_topo_apply_shared_replica_config(char *replica_root);
static int ipa_topo_rootdse_init(Slapi_PBlock *pb);
static int ipa_topo_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e,
Slapi_Entry* entryAfter, int *returncode,
char *returntext, void *arg);
void ipa_topo_be_state_change(void *handle, char *be_name,
int old_be_state, int new_be_state);
int ipa_topo_init(Slapi_PBlock *pb)
{
int rc = 0;
void *ipa_topo_plugin_identity = NULL;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"--> ipa_topo_init\n");
/**
* Store the plugin identity for later use.
* Used for internal operations
*/
slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &ipa_topo_plugin_identity);
ipa_topo_set_plugin_id(ipa_topo_plugin_identity);
if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01) != 0
|| slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, (void *)ipa_topo_start) != 0
|| slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN, (void *)ipa_topo_close) != 0
|| slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &pdesc) != 0) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_init: failed to register plugin\n");
rc = 1;
}
if (rc == 0) {
char *plugin_type = "bepreoperation";
if (slapi_register_plugin(plugin_type, 1, "ipa_topo_init",
ipa_topo_preop_init, IPA_TOPO_PREOP_DESC,
NULL, ipa_topo_get_plugin_id())) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_init: failed to register preop plugin\n");
rc = 1;
}
}
if (rc == 0) {
char *plugin_type = "postoperation";
if (slapi_register_plugin(plugin_type, 1, "ipa_topo_init",
ipa_topo_postop_init, IPA_TOPO_POSTOP_DESC,
NULL, ipa_topo_get_plugin_id())) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_init: failed to register postop plugin\n");
rc = 1;
}
}
if (rc == 0) {
char *plugin_type = "internalpostoperation";
if (slapi_register_plugin(plugin_type, 1, "ipa_topo_internal_init",
ipa_topo_internal_postop_init,
IPA_TOPO_INTERNAL_POSTOP_DESC,
NULL, ipa_topo_get_plugin_id())) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_init: failed to register internal postop plugin\n");
rc = 1;
}
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_init\n");
return(rc);
}
static int
ipa_topo_preop_init(Slapi_PBlock *pb)
{
int rc;
rc = slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN,
(void *)ipa_topo_pre_mod);
rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN,
(void *)ipa_topo_pre_add);
rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN,
(void *)ipa_topo_pre_del);
return(rc);
}
static int
ipa_topo_postop_init(Slapi_PBlock *pb)
{
int rc;
rc = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN,
(void *)ipa_topo_post_add);
rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN,
(void *)ipa_topo_post_del);
rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN,
(void *)ipa_topo_post_mod);
return(rc);
}
static int
ipa_topo_internal_postop_init(Slapi_PBlock *pb)
{
int rc;
rc = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN,
(void *)ipa_topo_post_add);
rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN,
(void *)ipa_topo_post_del);
return(rc);
}
int
ipa_topo_setup_managed_servers(void)
{
int rc = 0;
/* initially only read the entries below cn=masters
* and build the list of hostnames
*/
rc = ipa_topo_util_setup_servers();
return rc;
}
void
ipa_topo_queue_apply_shared_config(time_t event_time, void *arg)
{
ipa_topo_apply_shared_config();
}
int
ipa_topo_apply_shared_config(void)
{
int i = 0;
int rc = 0;
char **shared_replica_root = NULL;
while (0 == ipa_topo_acquire_startup_inprogress()) {
DS_Sleep(1);
}
shared_replica_root = ipa_topo_get_plugin_replica_root();
while (rc == 0 && shared_replica_root[i]) {
rc = ipa_topo_apply_shared_replica_config(shared_replica_root[i]);
i++;
}
/* initialize the list of managed servers */
rc = ipa_topo_setup_managed_servers();
ipa_topo_release_startup_inprogress();
return (rc);
}
static int
ipa_topo_apply_shared_replica_config(char *replica_root)
{
TopoReplica *replica_config = NULL;
TopoReplicaSegmentList *replica_segments = NULL;
int rc = 0;
/* step 1. get replica onfig entry from shared tree
* search replica entry for replcia root below shared config base
*/
replica_config = ipa_topo_util_get_replica_conf(replica_root);
if (replica_config) {
/* step 2. get all segments for the replica from the shared config */
replica_segments = ipa_topo_util_get_replica_segments(replica_config);
/* step 3. get all replication agreements for replica root */
rc = ipa_topo_util_update_agmt_list(replica_config, replica_segments);
}
return (rc);
}
static int
ipa_topo_start(Slapi_PBlock * pb)
{
int rc = 0;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"--> ipa_topo_start\n");
/* expose info about the plugin via rootdse */
rc = ipa_topo_rootdse_init(pb);
/* register callback to handle state changes of backends,
* required to check changes in domain level after online initialization
*/
slapi_register_backend_state_change((void *)ipa_topo_be_state_change,
ipa_topo_be_state_change);
/* init plugin config data from the plugin entry in cn=config */
rc = ipa_topo_init_plugin_config(pb);
if (rc != 0) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"unable to get configuration\n");
return (rc);
}
if (0 == ipa_topo_get_plugin_active()) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"plugin not activated, waiting for increase of domain level\n");
return rc;
}
rc = ipa_topo_util_start(1);
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_start\n");
return (rc);
}
static int
ipa_topo_close(Slapi_PBlock * pb)
{
slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP,
"", LDAP_SCOPE_BASE, "(objectclass=*)", ipa_topo_rootdse_search);
slapi_unregister_backend_state_change((void *)ipa_topo_be_state_change);
ipa_topo_free_plugin_config();
return 0;
}
static int
ipa_topo_rootdse_init(Slapi_PBlock *pb)
{
int rc = SLAPI_PLUGIN_FAILURE;
if (slapi_config_register_callback_plugin(SLAPI_OPERATION_SEARCH,
DSE_FLAG_PREOP | DSE_FLAG_PLUGIN,
"", LDAP_SCOPE_BASE, "(objectclass=*)",
ipa_topo_rootdse_search, NULL, pb)) {
rc = SLAPI_PLUGIN_SUCCESS;
}
return rc;
}
static int
ipa_topo_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter,
int *returncode, char *returntext, void *arg)
{
char *version = slapi_ch_smprintf("%d.%d", ipa_topo_get_plugin_version_major(),
ipa_topo_get_plugin_version_minor());
slapi_entry_attr_set_charptr(e, "ipaTopologyPluginVersion", version);
if (ipa_topo_get_plugin_active()) {
slapi_entry_attr_set_charptr(e, "ipaTopologyIsManaged", "on");
} else {
slapi_entry_attr_set_charptr(e, "ipaTopologyIsManaged", "off");
}
/* we expose temporarily the domain level in this function, should
* finally be handled in a plugin managing the domain level
*/
char *level = slapi_ch_smprintf("%d", ipa_topo_get_domain_level_major());
slapi_entry_attr_set_charptr(e, "ipaDomainLevel", level);
slapi_ch_free_string(&version);
slapi_ch_free_string(&level);
return SLAPI_DSE_CALLBACK_OK;
}
void
ipa_topo_be_state_change(void *handle, char *be_name,
int old_be_state, int new_be_state)
{
Slapi_Backend *be=NULL;
const char *be_suffix;
/* check if different backends require different actions */
be = slapi_be_select_by_instance_name(be_name);
be_suffix = slapi_sdn_get_dn(slapi_be_getsuffix(be, 0));
if (0 == ipa_topo_cfg_plugin_suffix_is_managed(be_suffix)) {
/* nothing to do */
return;
}
if (new_be_state == SLAPI_BE_STATE_ON) {
/* backend came back online - check change in domain level */
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_be_state_change - "
"backend %s is coming online; "
"checking domain level and init shared topology\n",
be_name);
ipa_topo_util_set_domain_level();
ipa_topo_util_check_plugin_active();
if (ipa_topo_get_plugin_active()) {
ipa_topo_util_start(1);
}
} else if (new_be_state == SLAPI_BE_STATE_OFFLINE) {
/* backend is about to be taken down - inactivate plugin */
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_be_state_change"
"backend %s is going offline; inactivate plugin\n", be_name);
} else if (new_be_state == SLAPI_BE_STATE_DELETE) {
/* backend is about to be removed - disable replication */
if (old_be_state == SLAPI_BE_STATE_ON) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_be_state_change"
"backend %s is about to be deleted; inactivate plugin\n", be_name);
}
}
}

View File

@ -0,0 +1,272 @@
#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 */
break;
case TOPO_SEGMENT_ENTRY: {
TopoReplicaSegment *tsegm;
TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(add_entry);
char *status;
/* 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: {
/* add to list of managed hosts */
ipa_topo_cfg_host_add(add_entry);
/* we are adding a new master, there could be
* a segment which so far was inactive since
* the host was not managed
*/
ipa_topo_util_update_segments_for_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_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);
if (mod_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:
break;
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);
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;
}
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
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:
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");
/* 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;
char *status;
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);
break;
case TOPO_IGNORE_ENTRY:
break;
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_post_del\n");
return result;
}

View File

@ -0,0 +1,458 @@
#include "topology.h"
/* the preoperation plugins check if the managed replication config
* is attempted to be directly modified.
* This is only allowed for internal operations triggerd by the
* topology plugin itself
*/
static int ipa_topo_pre_entry_in_scope(Slapi_PBlock *pb)
{
Slapi_DN *dn;
static Slapi_DN *config_dn = NULL;;
slapi_pblock_get(pb, SLAPI_TARGET_SDN, &dn);
if (config_dn == NULL) {
config_dn = slapi_sdn_new_dn_byval("cn=mapping tree,cn=config");
/* this rules out entries in regular backends and most of
* cn=config entries.
*/
}
return slapi_sdn_issuffix(dn,config_dn);
}
int ipa_topo_is_entry_managed(Slapi_PBlock *pb)
{
Slapi_Entry *e;
char *pi;
int op_type;
if (!ipa_topo_pre_entry_in_scope(pb)) {
/* we don't care for general mods, only specific
* entries in the mapping tree
*/
return 0;
}
slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &op_type);
if (op_type == SLAPI_OPERATION_ADD) {
slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
} else {
slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e);
}
if (!ipa_topo_util_entry_is_candidate(e)) {
/* entry has no objectclass the plugin controls */
return 0;
}
/* we have to check if the operation is triggered by the
* topology plugin itself - allow it
*/
slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY,&pi);
if (pi && 0 == strcasecmp(pi, ipa_topo_get_plugin_id())) {
return 0;
}
/* last check: is the endpoint of the agreement amanaged host ? */
if (ipa_topo_util_target_is_managed(e)) {
return 1;
} else {
return 0;
}
}
int
ipa_topo_is_modattr_restricted(Slapi_PBlock *pb)
{
LDAPMod **mods;
int i;
int rc = 0;
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
for (i = 0; (mods != NULL) && (mods[i] != NULL); i++) {
if (ipa_topo_cfg_attr_is_restricted(mods[i]->mod_type)) {
rc = 1;
break;
}
}
return rc;
}
/* connectivity check for topology
* checks if the nodes of a segment would still be connected after
* removal of the segments.
* For description of the algorithm see design page
*/
struct node_list {
struct node_list *next;
char *node;
};
struct node_fanout {
struct node_fanout *next;
char *node;
struct node_list *targets;
int visited;
};
struct node_list *
node_list_dup (struct node_list *orig)
{
struct node_list *dup = NULL;
struct node_list *cursor = orig;
struct node_list *start_dup = NULL;
while (cursor) {
if (dup) {
dup->next = (struct node_list *)slapi_ch_malloc(sizeof(struct node_list));
dup = dup->next;
} else {
dup = (struct node_list *)slapi_ch_malloc(sizeof(struct node_list));
start_dup = dup;
}
dup->next = NULL;
dup->node = slapi_ch_strdup(cursor->node);
cursor = cursor->next;
}
return start_dup;
}
void
node_list_free(struct node_list *orig)
{
struct node_list *cursor = orig;
struct node_list *cur_next = NULL;
while (cursor) {
cur_next = cursor->next;
slapi_ch_free_string(&cursor->node);
slapi_ch_free((void **)&cursor);
cursor = cur_next;
}
}
struct node_fanout *
ipa_topo_connection_fanout_new (char *from, char *to)
{
struct node_fanout *new_fanout = (struct node_fanout *)
slapi_ch_malloc(sizeof(struct node_fanout));
struct node_list *targets = (struct node_list *)
slapi_ch_malloc(sizeof(struct node_list));
targets->next = NULL;
targets->node = slapi_ch_strdup(to);
new_fanout->next = NULL;
new_fanout->node = slapi_ch_strdup(from);
new_fanout->targets = targets;
new_fanout->visited = 0;
return new_fanout;
}
void
ipa_topo_connection_fanout_free (struct node_fanout *fanout)
{
struct node_fanout *cursor = fanout;
struct node_fanout *cur_next = NULL;
while (cursor) {
cur_next = cursor->next;
slapi_ch_free_string(&cursor->node);
node_list_free(cursor->targets);
slapi_ch_free((void **)&cursor);
cursor = cur_next;
}
}
struct node_fanout *
ipa_topo_connection_fanout_extend (struct node_fanout *fanout_in, char *from, char *to)
{
struct node_fanout *cursor;
if (fanout_in == NULL) {
/* init fanout */
return ipa_topo_connection_fanout_new(from,to);
}
/* extend existing fanout struct */
cursor = fanout_in;
while (cursor) {
if (strcasecmp(cursor->node, from) == 0) break;
cursor = cursor->next;
}
if (cursor) {
struct node_list *target = (struct node_list *)
slapi_ch_malloc(sizeof(struct node_list));
target->next = cursor->targets;
target->node = slapi_ch_strdup(to);
cursor->targets = target;
return fanout_in;
} else {
cursor = ipa_topo_connection_fanout_new(from,to);
cursor->next = fanout_in;
return cursor;
}
}
struct node_fanout *
ipa_topo_connection_fanout(TopoReplica *tconf, TopoReplicaSegment *tseg)
{
struct node_fanout *fout = NULL;
TopoReplicaSegment *segm;
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;
while (seglist) {
segm = seglist->segm;
if (strcasecmp(segm->name, tseg->name)) {
if (segm->direct == SEGMENT_LEFT_RIGHT ||
segm->direct == SEGMENT_BIDIRECTIONAL ) {
fout = ipa_topo_connection_fanout_extend(fout, segm->from, segm->to);
}
if (segm->direct == SEGMENT_RIGHT_LEFT ||
segm->direct == SEGMENT_BIDIRECTIONAL) {
fout = ipa_topo_connection_fanout_extend(fout, segm->to, segm->from);
}
}
seglist = seglist->next;
}
return fout;
}
void
ipa_topo_connection_append(struct node_fanout *fanout, struct node_list *reachable)
{
struct node_fanout *cursor = fanout;
while (cursor) {
if (strcasecmp(reachable->node, cursor->node) == 0 &&
cursor->visited == 0) {
struct node_list *tail;
struct node_list *extend;
cursor->visited = 1;
extend = node_list_dup(cursor->targets);
tail = reachable;
while (tail->next) {
tail = tail->next;
}
tail->next = extend;
break;
}
cursor = cursor->next;
}
}
int
ipa_topo_connection_exists(struct node_fanout *fanout, char* from, char *to)
{
struct node_list *reachable = NULL;
struct node_fanout *cursor = fanout;
int connected = 0;
/* init reachable nodes */
while (cursor) {
if (strcasecmp(cursor->node, from) == 0) {
cursor->visited = 1;
reachable = node_list_dup(cursor->targets);
} else {
cursor->visited = 0;
}
cursor = cursor->next;
}
/* check if target is in reachable nodes, if
* not, expand reachables
*/
if (reachable == NULL) return 0;
while (reachable) {
if (strcasecmp(reachable->node, to) == 0) {
connected = 1;
break;
}
ipa_topo_connection_append(fanout, reachable);
reachable = reachable->next;
}
node_list_free(reachable);
return connected;
}
int
ipa_topo_check_connect_reject(Slapi_PBlock *pb)
{
int rc = 0;
Slapi_Entry *add_entry;
char *pi;
/* we have to check if the operation is triggered by the
* topology plugin itself - allow it
*/
slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY,&pi);
if (pi && 0 == strcasecmp(pi, ipa_topo_get_plugin_id())) {
return 0;
}
slapi_pblock_get(pb,SLAPI_DELETE_EXISTING_ENTRY,&add_entry);
if (TOPO_SEGMENT_ENTRY != ipa_topo_check_entry_type(add_entry)) {
return 0;
} else {
/* a new segment is added
* verify that the segment does not yet exist
*/
TopoReplicaSegment *tsegm;
TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(add_entry);
tsegm = ipa_topo_util_find_segment(tconf, add_entry);
if (tsegm) {
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
"segment to be added does already exist\n");
rc = 1;
}
}
return rc;
}
int
ipa_topo_check_disconnect_reject(Slapi_PBlock *pb)
{
int rc = 1;
Slapi_Entry *del_entry;
struct node_fanout *fanout = NULL;
char *pi;
/* we have to check if the operation is triggered by the
* topology plugin itself - allow it
*/
slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY,&pi);
if (pi && 0 == strcasecmp(pi, ipa_topo_get_plugin_id())) {
return 0;
}
slapi_pblock_get(pb,SLAPI_DELETE_EXISTING_ENTRY,&del_entry);
if (TOPO_SEGMENT_ENTRY != ipa_topo_check_entry_type(del_entry)) {
return 0;
} else {
TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(del_entry);
TopoReplicaSegment *tsegm;
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");
goto done;
}
/* check if removal of segment would break connectivity */
fanout = ipa_topo_connection_fanout(tconf, tsegm);
if (fanout == NULL) goto done;
if (ipa_topo_connection_exists(fanout, tsegm->from, tsegm->to) &&
ipa_topo_connection_exists(fanout, tsegm->to, tsegm->from)) {
rc = 0;
}
ipa_topo_connection_fanout_free(fanout);
}
done:
return rc;
}
static int
ipa_topo_pre_ignore_op(Slapi_PBlock *pb)
{
int repl_op = 0;
/* changes to cn=config aren't replicated, for changes to
* shared topology area checks have been done on master
* accepting the operation
*/
slapi_pblock_get (pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op);
return repl_op;
}
int ipa_topo_pre_add(Slapi_PBlock *pb)
{
int result = SLAPI_PLUGIN_SUCCESS;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"--> ipa_topo_pre_add\n");
if (0 == ipa_topo_get_plugin_active()) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_pre_add - plugin not active\n");
return 0;
}
if (ipa_topo_pre_ignore_op(pb)) return result;
if (ipa_topo_is_entry_managed(pb)) {
int rc = LDAP_UNWILLING_TO_PERFORM;
char *errtxt;
errtxt = slapi_ch_smprintf("Entry is managed by topology plugin."
" Adding of entry not allowed.\n");
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
result = SLAPI_PLUGIN_FAILURE;
} else if (ipa_topo_check_connect_reject(pb)) {
int rc = LDAP_UNWILLING_TO_PERFORM;
char *errtxt;
errtxt = slapi_ch_smprintf("Segment already exists in topology."
"Add rejected.\n");
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
result = SLAPI_PLUGIN_FAILURE;
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_pre_add\n");
return result;
}
int
ipa_topo_pre_mod(Slapi_PBlock *pb)
{
int result = SLAPI_PLUGIN_SUCCESS;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"--> ipa_topo_pre_mod\n");
if (0 == ipa_topo_get_plugin_active()) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_pre_mod - plugin not active\n");
return 0;
}
if (ipa_topo_pre_ignore_op(pb)) return result;
if (ipa_topo_is_entry_managed(pb) && ipa_topo_is_modattr_restricted(pb)) {
int rc = LDAP_UNWILLING_TO_PERFORM;
char *errtxt;
errtxt = slapi_ch_smprintf("Entry and attributes are managed by topology plugin."
"No direct modifications allowed.\n");
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
result = SLAPI_PLUGIN_FAILURE;
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_pre_mod\n");
return result;
}
int
ipa_topo_pre_del(Slapi_PBlock *pb)
{
int result = SLAPI_PLUGIN_SUCCESS;
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"--> ipa_topo_pre_del\n");
if (0 == ipa_topo_get_plugin_active()) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_pre_del - plugin not active\n");
return 0;
}
if (ipa_topo_pre_ignore_op(pb)) return result;
if (ipa_topo_is_entry_managed(pb)) {
int rc = LDAP_UNWILLING_TO_PERFORM;
char *errtxt;
errtxt = slapi_ch_smprintf("Entry is managed by topology plugin."
"Deletion not allowed.\n");
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
result = SLAPI_PLUGIN_FAILURE;
} else if (ipa_topo_check_disconnect_reject(pb)) {
int rc = LDAP_UNWILLING_TO_PERFORM;
char *errtxt;
errtxt = slapi_ch_smprintf("Removal of Segment disconnects topology."
"Deletion not allowed.\n");
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
result = SLAPI_PLUGIN_FAILURE;
}
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"<-- ipa_topo_pre_del\n");
return result;
}

File diff suppressed because it is too large Load Diff

View File

@ -405,6 +405,7 @@ rm %{buildroot}/%{plugin_dir}/libipa_extdom_extop.la
rm %{buildroot}/%{plugin_dir}/libipa_range_check.la rm %{buildroot}/%{plugin_dir}/libipa_range_check.la
rm %{buildroot}/%{plugin_dir}/libipa_otp_counter.la rm %{buildroot}/%{plugin_dir}/libipa_otp_counter.la
rm %{buildroot}/%{plugin_dir}/libipa_otp_lasttoken.la rm %{buildroot}/%{plugin_dir}/libipa_otp_lasttoken.la
rm %{buildroot}/%{plugin_dir}/libtopology.la
rm %{buildroot}/%{_libdir}/krb5/plugins/kdb/ipadb.la rm %{buildroot}/%{_libdir}/krb5/plugins/kdb/ipadb.la
rm %{buildroot}/%{_libdir}/samba/pdb/ipasam.la rm %{buildroot}/%{_libdir}/samba/pdb/ipasam.la
@ -798,6 +799,7 @@ fi
%attr(755,root,root) %{plugin_dir}/libipa_range_check.so %attr(755,root,root) %{plugin_dir}/libipa_range_check.so
%attr(755,root,root) %{plugin_dir}/libipa_otp_counter.so %attr(755,root,root) %{plugin_dir}/libipa_otp_counter.so
%attr(755,root,root) %{plugin_dir}/libipa_otp_lasttoken.so %attr(755,root,root) %{plugin_dir}/libipa_otp_lasttoken.so
%attr(755,root,root) %{plugin_dir}/libtopology.so
%dir %{_localstatedir}/lib/ipa %dir %{_localstatedir}/lib/ipa
%attr(700,root,root) %dir %{_localstatedir}/lib/ipa/backup %attr(700,root,root) %dir %{_localstatedir}/lib/ipa/backup
%attr(700,root,root) %dir %{_localstatedir}/lib/ipa/sysrestore %attr(700,root,root) %dir %{_localstatedir}/lib/ipa/sysrestore

View File

@ -0,0 +1,15 @@
# IPA Topology Plugin schema
# BaseOID: 2.16.840.1.113730.3.8.20
dn: cn=schema
attributetypes: ( 2.16.840.1.113730.3.8.20.2.1 NAME 'ipaReplTopoConfRoot' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
attributetypes: ( 2.16.840.1.113730.3.8.20.2.2 NAME 'ipaReplTopoSegmentDirection' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
attributetypes: ( 2.16.840.1.113730.3.8.20.2.3 NAME 'ipaReplTopoSegmentLeftNode' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
attributetypes: ( 2.16.840.1.113730.3.8.20.2.4 NAME 'ipaReplTopoSegmentRightNode' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
attributetypes: ( 2.16.840.1.113730.3.8.20.2.5 NAME 'ipaReplTopoSegmentStatus' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
attributetypes: ( 2.16.840.1.113730.3.8.20.2.6 NAME 'ipaReplTopoSegmentGenerated' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
attributetypes: ( 2.16.840.1.113730.3.8.20.2.7 NAME 'ipaReplTopoManagedAgreementState' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
attributetypes: ( 2.16.840.1.113730.3.8.20.2.8 NAME 'ipaReplTopoManagedSuffix' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
objectclasses: ( 2.16.840.1.113730.3.8.20.1.1 NAME 'ipaReplTopoConf' DESC 'IPA defined objectclass' SUP top STRUCTURAL MUST ipaReplTopoConfRoot MAY ( cn $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal ) X-ORIGIN 'Free IPA' )
objectclasses: ( 2.16.840.1.113730.3.8.20.1.2 NAME 'ipaReplTopoSegment' DESC 'IPA defined objectclass' SUP top STRUCTURAL MUST ( ipaReplTopoSegmentDirection $ ipaReplTopoSegmentLeftNode $ ipaReplTopoSegmentRightNode) MAY ( cn $ ipaReplTopoSegmentStatus $ ipaReplTopoSegmentGenerated $ nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal $ nsds5BeginReplicaRefresh $ description $ nsds5replicaTimeout $ nsds5ReplicaEnabled $ nsds5ReplicaStripAttrs $ nsds5replicaSessionPauseTime $ nsds5ReplicaProtocolTimeout ) X-ORIGIN 'Free IPA' )
objectclasses: ( 2.16.840.1.113730.3.8.20.1.3 NAME 'ipaReplTopoManagedAgreement' DESC 'marker objectclass for managed replication agreements' SUP top AUXILIARY MAY ( ipaReplTopoManagedAgreementState ) X-ORIGIN 'Free IPA' )
objectclasses: ( 2.16.840.1.113730.3.8.20.1.4 NAME 'ipaReplTopoManagedServer' DESC 'part of managed replication topology' SUP top AUXILIARY MAY ( ipaReplTopoManagedSuffix ) X-ORIGIN 'Free IPA' )

View File

@ -20,6 +20,7 @@ app_DATA = \
65ipacertstore.ldif \ 65ipacertstore.ldif \
65ipasudo.ldif \ 65ipasudo.ldif \
70ipaotp.ldif \ 70ipaotp.ldif \
70topology.ldif \
71idviews.ldif \ 71idviews.ldif \
anonymous-vlv.ldif \ anonymous-vlv.ldif \
bootstrap-template.ldif \ bootstrap-template.ldif \