summaryrefslogtreecommitdiffstats
path: root/daemons/ipa-slapi-plugins/topology/topology_post.c
blob: 4eb3c2fd10643658804943112c1466091f9f624e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#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 = 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: {
        /* 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_Entry *pre_entry = NULL;

    slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
                    "--> ipa_topo_post_mod\n");

    /* 1. get entry  */
    slapi_pblock_get(pb,SLAPI_ENTRY_POST_OP,&mod_entry);
    slapi_pblock_get(pb,SLAPI_ENTRY_PRE_OP,&pre_entry);

    if (mod_entry == NULL || 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:
        break;
    case TOPO_SEGMENT_ENTRY: {
        LDAPMod **mods;
        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;
        }
        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 = 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);
        break;
    case TOPO_IGNORE_ENTRY:
        break;
    }

    slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
                    "<-- ipa_topo_post_del\n");
    return result;
}