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

Sumit Bose sbose at redhat.com
Mon Nov 24 09:25:46 UTC 2014


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 ...
-------------- next part --------------
From 4c8834b37a12f8d99ebe559ec26506aa6a81e8ec 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 c154306a01f4761e64368ad6a7b494d1a30ec0a7 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                | 122 ++++++++++++++++++++++++++++++++++++
 src/tests/cmocka/test_sysdb_views.c |  69 ++++++++++++++++++++
 3 files changed, 193 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..f7899b2 100644
--- a/src/db/sysdb_views.c
+++ b/src/db/sysdb_views.c
@@ -214,6 +214,128 @@ 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;
+        }
+    }
+
+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 4cba79d103eaccf4432d22305c5caa973f3ab4e6 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 | 92 +++++++++++++++++++++++++++++++-------
 2 files changed, 81 insertions(+), 23 deletions(-)

diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
index f7899b2..5721a43 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 9281aab..63f64c2 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;
@@ -895,7 +904,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)
@@ -930,7 +939,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
@@ -1022,6 +1031,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;
@@ -1081,24 +1091,76 @@ 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");
     } 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");
             }
         }
     }
@@ -1114,7 +1176,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)
@@ -1214,7 +1276,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)
@@ -1300,7 +1362,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)
@@ -1362,7 +1424,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);
@@ -1497,12 +1559,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