[SSSD] [PATCHES] views: allow view name change at startup

Sumit Bose sbose at redhat.com
Tue Nov 25 16:37:17 UTC 2014


On Tue, Nov 25, 2014 at 03:04:10PM +0100, Sumit Bose wrote:
> On Mon, Nov 24, 2014 at 10:25:46AM +0100, Sumit Bose wrote:
> > On Mon, Nov 24, 2014 at 10:20:18AM +0100, Sumit Bose wrote:
> > > On Sat, Nov 22, 2014 at 03:39:45PM +0100, Jakub Hrozek wrote:
> > > > On Wed, Nov 19, 2014 at 01:36:02PM +0100, Sumit Bose wrote:
> > > > > Hi,
> > > > > 
> > > > > with this patch SSSD can switch to a new view at startup. There is a
> > > > > todo in the third patch. Currently the user and group entries are only
> > > > > invalidated so that the new view/override data is checked at the next
> > > > > request for the given object. Additionally we might want to start a
> > > > > background task with refreshes the existing entries in the cache
> > > > > unconditionally. But this might result in unwanted network peaks during
> > > > > startup. So I left the implementation for a later patch, if this is
> > > > > needed.
> > > > > 
> > > > > bye,
> > > > > Sumit
> > > > 
> > > > Do these patches depend on some other patchset? I'm getting:
> > > > 
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:237:59: error: use of undeclared identifier 'TEST_VIEW_NAME'
> > > >     ret = sysdb_update_view_name(test_ctx->domain->sysdb, TEST_VIEW_NAME);
> > > >                                                           ^
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:240:46: error: use of undeclared identifier 'TEST_USER_NAME'
> > > >     ret = sysdb_store_user(test_ctx->domain, TEST_USER_NAME, NULL,
> > > >                                              ^
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:246:65: error: use of undeclared identifier 'TEST_USER_NAME'
> > > >     ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
> > > >                                                                 ^
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:255:34: error: use of undeclared identifier 'TEST_ANCHOR_PREFIX'
> > > >                                  TEST_ANCHOR_PREFIX TEST_USER_SID);
> > > >                                  ^
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:258:50: error: use of undeclared identifier 'TEST_VIEW_NAME'
> > > >     ret = sysdb_store_override(test_ctx->domain, TEST_VIEW_NAME,
> > > >                                                  ^
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:272:59: error: use of undeclared identifier 'TEST_VIEW_NAME'
> > > >     ret = sysdb_delete_view_tree(test_ctx->domain->sysdb, TEST_VIEW_NAME);
> > > >                                                           ^
> > > >   CC       src/responder/ifp/ifp_tests-ifpsrv_util.o
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:299:59: error: use of undeclared identifier 'TEST_VIEW_NAME'
> > > >     ret = sysdb_update_view_name(test_ctx->domain->sysdb, TEST_VIEW_NAME);
> > > >                                                           ^
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:302:46: error: use of undeclared identifier 'TEST_USER_NAME'
> > > >     ret = sysdb_store_user(test_ctx->domain, TEST_USER_NAME, NULL,
> > > >                                              ^
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:308:65: error: use of undeclared identifier 'TEST_USER_NAME'
> > > >     ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
> > > >                                                                 ^
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:317:34: error: use of undeclared identifier 'TEST_ANCHOR_PREFIX'
> > > >                                  TEST_ANCHOR_PREFIX TEST_USER_SID);
> > > >                                  ^
> > > >   CC       src/responder/common/ifp_tests-responder_utils.o
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:320:50: error: use of undeclared identifier 'TEST_VIEW_NAME'
> > > >     ret = sysdb_store_override(test_ctx->domain, TEST_VIEW_NAME,
> > > >                                                  ^
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:328:59: error: use of undeclared identifier 'TEST_VIEW_NAME'
> > > >     ret = sysdb_delete_view_tree(test_ctx->domain->sysdb, TEST_VIEW_NAME);
> > > >                                                           ^
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:331:65: error: use of undeclared identifier 'TEST_USER_NAME'
> > > >     ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
> > > >                                                                 ^
> > > > /home/remote/jhrozek/devel/sssd/src/tests/cmocka/test_sysdb_views.c:341:65: error: use of undeclared identifier 'TEST_USER_NAME'
> > > >     ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
> > > >                                                                 ^
> > > > 14 errors generated.
> > > > 
> > > 
> > > ah, sorry, I attached a new version with the missing defines.
> > 
> > and now with the patches ...
> 
> > > > The code looks good, but I always get:
> > > > (Sat Nov 22 15:37:28 2014) [sssd[be[ipa.example.com]]]
> > > > [ipa_get_view_name_done] (0x0020): View name changed, this is currently
> > > > not supported!
> > > > 
> > > > When switching from one view to another...I tested using idview-unapply
> > > > and then idview-apply to another view, is there some other way?
> 
> I retested with the same steps and it worked for me. I changed the log
> message to "View name changed, this is not supported at runtime.  Please
> restart SSSD to get the new view applied." to hopefully make more clear
> what is happening.
> 
> New version attached.
> 
> bye,
> Sumit

Jakub found another issue in the 2nd patch. New versions attached.

bye,
Sumit
-------------- next part --------------
From 20c2c2836686058284f7722a7b90aa34fdd5a78e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 12 Nov 2014 12:43:23 +0100
Subject: [PATCH 1/3] sysdb: add sysdb_delete_view_tree()

---
 src/db/sysdb.h                      |  2 +
 src/db/sysdb_views.c                | 34 +++++++++++++++++
 src/tests/cmocka/test_sysdb_views.c | 74 +++++++++++++++++++++++++++++++++++++
 3 files changed, 110 insertions(+)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 7a51117..a3ffa7b 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -444,6 +444,8 @@ errno_t sysdb_update_view_name(struct sysdb_ctx *sysdb, const char *view_name);
 errno_t sysdb_get_view_name(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
                             char **view_name);
 
+errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name);
+
 errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
                                      struct sysdb_attrs *override_attrs,
                                      struct ldb_dn *obj_dn);
diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
index 27b5870..e173214 100644
--- a/src/db/sysdb_views.c
+++ b/src/db/sysdb_views.c
@@ -180,6 +180,40 @@ done:
     return ret;
 }
 
+errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name)
+{
+    struct ldb_dn *dn;
+    TALLOC_CTX *tmp_ctx;
+    int ret;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+        return ENOMEM;
+    }
+
+    dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_VIEW_SEARCH_BASE,
+                        view_name);
+    if (dn == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n");
+        ret = EIO;
+        goto done;
+    }
+
+    ret = sysdb_delete_recursive(sysdb, dn, true);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n");
+        goto done;
+    }
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+
+    return ret;
+}
+
 static errno_t
 add_name_and_aliases_for_name_override(struct sss_domain_info *domain,
                                        struct sysdb_attrs *attrs,
diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
index 0dc5144..6be28e6 100644
--- a/src/tests/cmocka/test_sysdb_views.c
+++ b/src/tests/cmocka/test_sysdb_views.c
@@ -30,10 +30,22 @@
 
 #include "tests/cmocka/common_mock.h"
 #include "providers/ipa/ipa_id.h"
+#include "db/sysdb_private.h" /* for sysdb->ldb member */
 
 #define TESTS_PATH "tests_sysdb_views"
 #define TEST_CONF_FILE "tests_conf.ldb"
 
+#define TEST_ANCHOR_PREFIX ":ANCHOR:"
+#define TEST_VIEW_NAME "test view"
+#define TEST_VIEW_CONTAINER "cn=" TEST_VIEW_NAME ",cn=views,cn=sysdb"
+#define TEST_USER_NAME "test_user"
+#define TEST_USER_UID 1234
+#define TEST_USER_GID 5678
+#define TEST_USER_GECOS "Gecos field"
+#define TEST_USER_HOMEDIR "/home/home"
+#define TEST_USER_SHELL "/bin/shell"
+#define TEST_USER_SID "S-1-2-3-4"
+
 struct sysdb_test_ctx {
     struct sysdb_ctx *sysdb;
     struct confdb_ctx *confdb;
@@ -219,6 +231,66 @@ void test_split_ipa_anchor(void **state)
     assert_string_equal(uuid, "def");
 }
 
+void test_sysdb_delete_view_tree(void **state)
+{
+    int ret;
+    struct ldb_message *msg;
+    struct ldb_message **msgs = NULL;
+    struct sysdb_attrs *attrs;
+    size_t count;
+    struct ldb_dn *views_dn;
+
+    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
+                                                         struct sysdb_test_ctx);
+
+    test_ctx->domain->mpg = false;
+
+    ret = sysdb_update_view_name(test_ctx->domain->sysdb, TEST_VIEW_NAME);
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_store_user(test_ctx->domain, TEST_USER_NAME, NULL,
+                           TEST_USER_UID, TEST_USER_GID, TEST_USER_GECOS,
+                           TEST_USER_HOMEDIR, TEST_USER_SHELL, NULL, NULL, NULL,
+                           0,0);
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
+                                    NULL, &msg);
+    assert_int_equal(ret, EOK);
+    assert_non_null(msg);
+
+    attrs = sysdb_new_attrs(test_ctx);
+    assert_non_null(attrs);
+
+    ret = sysdb_attrs_add_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID,
+                                 TEST_ANCHOR_PREFIX TEST_USER_SID);
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_store_override(test_ctx->domain, TEST_VIEW_NAME,
+                               SYSDB_MEMBER_USER, attrs, msg->dn);
+    assert_int_equal(ret, EOK);
+
+    views_dn = ldb_dn_new(test_ctx, test_ctx->domain->sysdb->ldb,
+                          SYSDB_TMPL_VIEW_BASE);
+    assert_non_null(views_dn);
+
+    ret = sysdb_search_entry(test_ctx, test_ctx->domain->sysdb, views_dn,
+                             LDB_SCOPE_SUBTREE, NULL, NULL, &count, &msgs);
+    assert_int_equal(ret, EOK);
+    assert_true(count > 1);
+    assert_non_null(msgs);
+
+    ret = sysdb_delete_view_tree(test_ctx->domain->sysdb, TEST_VIEW_NAME);
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_search_entry(test_ctx, test_ctx->domain->sysdb, views_dn,
+                             LDB_SCOPE_SUBTREE, NULL, NULL, &count, &msgs);
+    assert_int_equal(ret, EOK);
+    assert_int_equal(count, 1);
+    assert_true(ldb_dn_compare(views_dn, msgs[0]->dn) == 0);
+
+}
+
 int main(int argc, const char *argv[])
 {
     int rv;
@@ -238,6 +310,8 @@ int main(int argc, const char *argv[])
                                  test_sysdb_setup, test_sysdb_teardown),
         unit_test_setup_teardown(test_split_ipa_anchor,
                                  test_sysdb_setup, test_sysdb_teardown),
+        unit_test_setup_teardown(test_sysdb_delete_view_tree,
+                                 test_sysdb_setup, test_sysdb_teardown),
     };
 
     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-- 
1.8.3.1

-------------- next part --------------
From 3f28677766ece263dcda2a7d1407b1cc81cf9779 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 12 Nov 2014 16:26:55 +0100
Subject: [PATCH 2/3] sysdb: add sysdb_invalidate_overrides()

---
 src/db/sysdb.h                      |   2 +
 src/db/sysdb_views.c                | 124 ++++++++++++++++++++++++++++++++++++
 src/tests/cmocka/test_sysdb_views.c |  69 ++++++++++++++++++++
 3 files changed, 195 insertions(+)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index a3ffa7b..5bd7f90 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -446,6 +446,8 @@ errno_t sysdb_get_view_name(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
 
 errno_t sysdb_delete_view_tree(struct sysdb_ctx *sysdb, const char *view_name);
 
+errno_t sysdb_invalidate_overrides(struct sysdb_ctx *sysdb);
+
 errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
                                      struct sysdb_attrs *override_attrs,
                                      struct ldb_dn *obj_dn);
diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
index e173214..079e2bb 100644
--- a/src/db/sysdb_views.c
+++ b/src/db/sysdb_views.c
@@ -214,6 +214,130 @@ done:
     return ret;
 }
 
+errno_t sysdb_invalidate_overrides(struct sysdb_ctx *sysdb)
+{
+    int ret;
+    int sret;
+    TALLOC_CTX *tmp_ctx;
+    bool in_transaction = false;
+    struct ldb_result *res;
+    size_t c;
+    struct ldb_message *msg;
+    struct ldb_dn *base_dn;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
+        return ENOMEM;
+    }
+
+    msg = ldb_msg_new(tmp_ctx);
+    if (msg == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    base_dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_BASE);
+    if (base_dn == NULL) {
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed");
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = ldb_msg_add_empty(msg, SYSDB_CACHE_EXPIRE, LDB_FLAG_MOD_REPLACE,
+                            NULL);
+    if (ret != LDB_SUCCESS) {
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+    ret = ldb_msg_add_string(msg, SYSDB_CACHE_EXPIRE, "1");
+    if (ret != LDB_SUCCESS) {
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_string failed.\n");
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN, LDB_FLAG_MOD_DELETE, NULL);
+    if (ret != LDB_SUCCESS) {
+        DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty failed.\n");
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    ret = sysdb_transaction_start(sysdb);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start failed.\n");
+        goto done;
+    }
+    in_transaction = true;
+
+    ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
+                     NULL, "%s", SYSDB_UC);
+    if (ret != LDB_SUCCESS) {
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    for (c = 0; c < res->count; c++) {
+        msg->dn = res->msgs[c]->dn;
+
+        ret = ldb_modify(sysdb->ldb, msg);
+        if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
+            DEBUG(SSSDBG_OP_FAILURE, "ldb_modify failed.\n");
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+    }
+
+    talloc_free(res);
+
+    ret = ldb_search(sysdb->ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
+                     NULL, "%s", SYSDB_GC);
+    if (ret != LDB_SUCCESS) {
+        DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n");
+        ret = sysdb_error_to_errno(ret);
+        goto done;
+    }
+
+    for (c = 0; c < res->count; c++) {
+        msg->dn = res->msgs[c]->dn;
+
+        ret = ldb_modify(sysdb->ldb, msg);
+        if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
+            DEBUG(SSSDBG_OP_FAILURE, "ldb_modify failed.\n");
+            ret = sysdb_error_to_errno(ret);
+            goto done;
+        }
+    }
+
+    ret = EOK;
+
+done:
+    if (in_transaction) {
+        if (ret == EOK) {
+            sret = sysdb_transaction_commit(sysdb);
+            if (sret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_commit failed, " \
+                                         "nothing we can do about.\n");
+                ret = sret;
+            }
+        } else {
+            sret = sysdb_transaction_cancel(sysdb);
+            if (sret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_cancel failed, " \
+                                         "nothing we can do about.\n");
+            }
+        }
+    }
+
+    talloc_free(tmp_ctx);
+
+    return ret;
+}
+
 static errno_t
 add_name_and_aliases_for_name_override(struct sss_domain_info *domain,
                                        struct sysdb_attrs *attrs,
diff --git a/src/tests/cmocka/test_sysdb_views.c b/src/tests/cmocka/test_sysdb_views.c
index 6be28e6..7238467 100644
--- a/src/tests/cmocka/test_sysdb_views.c
+++ b/src/tests/cmocka/test_sysdb_views.c
@@ -291,6 +291,73 @@ void test_sysdb_delete_view_tree(void **state)
 
 }
 
+void test_sysdb_invalidate_overrides(void **state)
+{
+    int ret;
+    struct ldb_message *msg;
+    struct sysdb_attrs *attrs;
+    struct ldb_dn *views_dn;
+    const char *user_attrs[] = { SYSDB_NAME,
+                                 SYSDB_CACHE_EXPIRE,
+                                 SYSDB_OVERRIDE_DN,
+                                 NULL};
+
+    struct sysdb_test_ctx *test_ctx = talloc_get_type_abort(*state,
+                                                         struct sysdb_test_ctx);
+
+    test_ctx->domain->mpg = false;
+
+    ret = sysdb_update_view_name(test_ctx->domain->sysdb, TEST_VIEW_NAME);
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_store_user(test_ctx->domain, TEST_USER_NAME, NULL,
+                           TEST_USER_UID, TEST_USER_GID, TEST_USER_GECOS,
+                           TEST_USER_HOMEDIR, TEST_USER_SHELL, NULL, NULL, NULL,
+                           10,0);
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
+                                    NULL, &msg);
+    assert_int_equal(ret, EOK);
+    assert_non_null(msg);
+
+    attrs = sysdb_new_attrs(test_ctx);
+    assert_non_null(attrs);
+
+    ret = sysdb_attrs_add_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID,
+                                 TEST_ANCHOR_PREFIX TEST_USER_SID);
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_store_override(test_ctx->domain, TEST_VIEW_NAME,
+                               SYSDB_MEMBER_USER, attrs, msg->dn);
+    assert_int_equal(ret, EOK);
+
+    views_dn = ldb_dn_new(test_ctx, test_ctx->domain->sysdb->ldb,
+                          SYSDB_TMPL_VIEW_BASE);
+    assert_non_null(views_dn);
+
+    ret = sysdb_delete_view_tree(test_ctx->domain->sysdb, TEST_VIEW_NAME);
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
+                                    user_attrs, &msg);
+    assert_int_equal(ret, EOK);
+    assert_non_null(msg);
+    assert_true(ldb_msg_find_attr_as_uint64(msg, SYSDB_CACHE_EXPIRE, 0) > 1);
+    assert_non_null(ldb_msg_find_attr_as_string(msg, SYSDB_OVERRIDE_DN, NULL));
+
+    ret = sysdb_invalidate_overrides(test_ctx->domain->sysdb);
+    assert_int_equal(ret, EOK);
+
+    ret = sysdb_search_user_by_name(test_ctx, test_ctx->domain, TEST_USER_NAME,
+                                    user_attrs, &msg);
+    assert_int_equal(ret, EOK);
+    assert_non_null(msg);
+    assert_int_equal(ldb_msg_find_attr_as_uint64(msg, SYSDB_CACHE_EXPIRE, 0),
+                     1);
+    assert_null(ldb_msg_find_attr_as_string(msg, SYSDB_OVERRIDE_DN, NULL));
+}
+
 int main(int argc, const char *argv[])
 {
     int rv;
@@ -312,6 +379,8 @@ int main(int argc, const char *argv[])
                                  test_sysdb_setup, test_sysdb_teardown),
         unit_test_setup_teardown(test_sysdb_delete_view_tree,
                                  test_sysdb_setup, test_sysdb_teardown),
+        unit_test_setup_teardown(test_sysdb_invalidate_overrides,
+                                 test_sysdb_setup, test_sysdb_teardown),
     };
 
     /* Set debug level to invalid value so we can deside if -d 0 was used. */
-- 
1.8.3.1

-------------- next part --------------
From d539b6140b745e3aa054eba13b88bab3e4f5b849 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 12 Nov 2014 16:30:57 +0100
Subject: [PATCH 3/3] views: allow view name change at startup

Currently some manual steps are needed on a FreeIPA to switch from one
view to another. With this patch the IPA provider checks at startup if
the view name changed and does the needed steps automatically. Besides
saving the new view name this includes removing the old view data and
marking the user and group entries as invalid.
---
 src/db/sysdb_views.c               | 12 ++---
 src/providers/ipa/ipa_subdomains.c | 97 +++++++++++++++++++++++++++++++-------
 2 files changed, 85 insertions(+), 24 deletions(-)

diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
index 079e2bb..8cc279a 100644
--- a/src/db/sysdb_views.c
+++ b/src/db/sysdb_views.c
@@ -123,17 +123,13 @@ errno_t sysdb_update_view_name(struct sysdb_ctx *sysdb,
             goto done;
         } else {
             /* view name changed */
-            /* not supported atm */
-            DEBUG(SSSDBG_CRIT_FAILURE,
-                  "View name changed from [%s] to [%s]. NOT SUPPORTED.\n",
-                  tmp_str, view_name);
-            ret = ENOTSUP;
-            goto done;
+            DEBUG(SSSDBG_CONF_SETTINGS,
+                  "View name changed from [%s] to [%s].\n", tmp_str, view_name);
         }
+    } else {
+        add_view_name = true;
     }
 
-    add_view_name = true;
-
     msg = ldb_msg_new(tmp_ctx);
     if (msg == NULL) {
         DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n");
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index 883558c..6fdb0be 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -80,8 +80,17 @@ struct ipa_subdomains_ctx {
     struct tevent_timer *timer_event;
     bool configured_explicit;
     time_t disabled_until;
+    bool view_read_at_init;
 };
 
+static void ipa_subdomains_done(struct ipa_subdomains_ctx *sd_ctx,
+                                struct be_req *req, int dp_err,
+                                int error, const char *errstr)
+{
+    sd_ctx->view_read_at_init = true;
+    return be_req_terminate(req, dp_err, error, errstr);
+}
+
 struct be_ctx *ipa_get_subdomains_be_ctx(struct be_ctx *be_ctx)
 {
     struct ipa_subdomains_ctx *subdom_ctx;
@@ -903,7 +912,7 @@ done:
     if (ret == EOK) {
         dp_error = DP_ERR_OK;
     }
-    be_req_terminate(be_req, dp_error, ret, NULL);
+    ipa_subdomains_done(ctx, be_req, dp_error, ret, NULL);
 }
 
 static void ipa_subdomains_get_conn_done(struct tevent_req *req)
@@ -938,7 +947,7 @@ static void ipa_subdomains_get_conn_done(struct tevent_req *req)
     return;
 
 fail:
-    be_req_terminate(ctx->be_req, dp_error, ret, NULL);
+    ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
 }
 
 static errno_t
@@ -1030,6 +1039,7 @@ static errno_t ipa_get_view_name(struct ipa_subdomains_req_ctx *ctx)
 static void ipa_get_view_name_done(struct tevent_req *req)
 {
     int ret;
+    int sret;
     struct ipa_subdomains_req_ctx *ctx;
     size_t reply_count;
     struct sdap_deref_attrs **reply = NULL;
@@ -1089,24 +1099,79 @@ static void ipa_get_view_name_done(struct tevent_req *req)
         view_name = SYSDB_DEFAULT_VIEW_NAME;
     }
 
+    DEBUG(SSSDBG_TRACE_ALL, "read_at_init [%s] current view  [%s].\n",
+                             ctx->sd_ctx->view_read_at_init ? "true" : "false",
+                             ctx->sd_ctx->id_ctx->view_name);
+
     if (ctx->sd_ctx->id_ctx->view_name != NULL
-            && strcmp(ctx->sd_ctx->id_ctx->view_name, view_name) != 0) {
+            && strcmp(ctx->sd_ctx->id_ctx->view_name, view_name) != 0
+            && ctx->sd_ctx->view_read_at_init) {
         DEBUG(SSSDBG_CRIT_FAILURE,
-              "View name changed, this is currently not supported!\n");
+              "View name changed, this is not supported at runtime. " \
+              "Please restart SSSD to get the new view applied.\n");
     } else {
+        ctx->sd_ctx->view_read_at_init = true;
+        /* View name changed */
+        if (ctx->sd_ctx->id_ctx->view_name != NULL) {
+            ret = sysdb_transaction_start(ctx->sd_ctx->be_ctx->domain->sysdb);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start failed.\n");
+                goto done;
+            }
+
+            if (strcmp(ctx->sd_ctx->id_ctx->view_name,
+                       SYSDB_DEFAULT_VIEW_NAME) != 0) {
+                /* Old view was not the default view, delete view tree */
+                ret = sysdb_delete_view_tree(ctx->sd_ctx->be_ctx->domain->sysdb,
+                                             ctx->sd_ctx->id_ctx->view_name);
+                if (ret != EOK) {
+                    DEBUG(SSSDBG_OP_FAILURE,
+                          "sysdb_delete_view_tree failed.\n");
+                    sret = sysdb_transaction_cancel(
+                                            ctx->sd_ctx->be_ctx->domain->sysdb);
+                    if (sret != EOK) {
+                        DEBUG(SSSDBG_OP_FAILURE,
+                              "sysdb_transaction_cancel failed.\n");
+                        goto done;
+                    }
+                    goto done;
+                }
+            }
+
+            ret = sysdb_invalidate_overrides(
+                                            ctx->sd_ctx->be_ctx->domain->sysdb);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE,
+                      "sysdb_invalidate_overrides failed.\n");
+                sret = sysdb_transaction_cancel(
+                                            ctx->sd_ctx->be_ctx->domain->sysdb);
+                if (sret != EOK) {
+                    DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_cancel failed.\n");
+                    goto done;
+                }
+                goto done;
+            }
+
+            ret = sysdb_transaction_commit(ctx->sd_ctx->be_ctx->domain->sysdb);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_commit failed.\n");
+                goto done;
+            }
+
+            /* TODO: start referesh task */
+        }
+
         ret = sysdb_update_view_name(ctx->sd_ctx->be_ctx->domain->sysdb,
                                      view_name);
         if (ret != EOK) {
             DEBUG(SSSDBG_CRIT_FAILURE,
                   "Cannot add/update view name to sysdb.\n");
         } else {
+            talloc_free(ctx->sd_ctx->id_ctx->view_name);
+            ctx->sd_ctx->id_ctx->view_name = talloc_strdup(ctx->sd_ctx->id_ctx,
+                                                           view_name);
             if (ctx->sd_ctx->id_ctx->view_name == NULL) {
-                ctx->sd_ctx->id_ctx->view_name =
-                                              talloc_strdup(ctx->sd_ctx->id_ctx,
-                                                            view_name);
-                if (ctx->sd_ctx->id_ctx->view_name == NULL) {
-                    DEBUG(SSSDBG_CRIT_FAILURE, "Cannot copy view name.\n");
-                }
+                DEBUG(SSSDBG_CRIT_FAILURE, "Cannot copy view name.\n");
             }
         }
     }
@@ -1122,7 +1187,7 @@ done:
     if (ret == EOK) {
         dp_error = DP_ERR_OK;
     }
-    be_req_terminate(ctx->be_req, dp_error, ret, NULL);
+    ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
 }
 
 static void ipa_subdomains_handler_done(struct tevent_req *req)
@@ -1222,7 +1287,7 @@ done:
     if (ret == EOK) {
         dp_error = DP_ERR_OK;
     }
-    be_req_terminate(ctx->be_req, dp_error, ret, NULL);
+    ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
 }
 
 static errno_t ipa_check_master(struct ipa_subdomains_req_ctx *ctx)
@@ -1308,7 +1373,7 @@ done:
     if (ret == EOK) {
         dp_error = DP_ERR_OK;
     }
-    be_req_terminate(ctx->be_req, dp_error, ret, NULL);
+    ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
 }
 
 static void ipa_subdomains_handler_master_done(struct tevent_req *req)
@@ -1370,7 +1435,7 @@ done:
     if (ret == EOK) {
         dp_error = DP_ERR_OK;
     }
-    be_req_terminate(ctx->be_req, dp_error, ret, NULL);
+    ipa_subdomains_done(ctx->sd_ctx, ctx->be_req, dp_error, ret, NULL);
 }
 
 static void ipa_subdom_online_cb(void *pvt);
@@ -1505,12 +1570,12 @@ void ipa_subdomains_handler(struct be_req *be_req)
 
     if (ctx->disabled_until > now) {
         DEBUG(SSSDBG_TRACE_ALL, "Subdomain provider disabled.\n");
-        be_req_terminate(be_req, DP_ERR_OK, EOK, NULL);
+        ipa_subdomains_done(ctx, be_req, DP_ERR_OK, EOK, NULL);
         return;
     }
 
     if (ctx->last_refreshed > now - IPA_SUBDOMAIN_REFRESH_LIMIT) {
-        be_req_terminate(be_req, DP_ERR_OK, EOK, NULL);
+        ipa_subdomains_done(ctx, be_req, DP_ERR_OK, EOK, NULL);
         return;
     }
 
-- 
1.8.3.1



More information about the sssd-devel mailing list