s4-dsdb: perform FSMO transfers asynchronously
authorAndrew Tridgell <tridge@samba.org>
Mon, 28 Mar 2011 05:44:32 +0000 (16:44 +1100)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 28 Mar 2011 22:00:22 +0000 (00:00 +0200)
this gives the administrator a proper error message on the command
line

Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>

source4/dsdb/repl/drepl_fsmo.c
source4/dsdb/repl/drepl_service.c

index 0355459bc0a3d58df5e2bdcc0aacc5c7a96752a4..f8f4769f1b640ce73beeadd5c4b9b7aec6e85460 100644 (file)
 #include "dsdb/repl/drepl_service.h"
 #include "param/param.h"
 
+struct fsmo_role_state {
+       struct irpc_message *msg;
+       struct drepl_takeFSMORole *r;
+};
+
 static void drepl_role_callback(struct dreplsrv_service *service,
                                WERROR werr,
                                enum drsuapi_DsExtendedError ext_err,
                                void *cb_data)
 {
+       struct fsmo_role_state *fsmo = talloc_get_type_abort(cb_data, struct fsmo_role_state);
        if (!W_ERROR_IS_OK(werr)) {
-               DEBUG(0,(__location__ ": Failed role transfer - %s - extended_ret[0x%X]\n",
+               DEBUG(2,(__location__ ": Failed role transfer - %s - extended_ret[0x%X]\n",
                         win_errstr(werr), ext_err));
        } else {
-               DEBUG(0,(__location__ ": Successful role transfer\n"));
+               DEBUG(2,(__location__ ": Successful role transfer\n"));
        }
+       fsmo->r->out.result = werr;
+       irpc_send_reply(fsmo->msg, NT_STATUS_OK);
 }
 
-static bool fsmo_master_cmp(struct ldb_dn *ntds_dn, struct ldb_dn *role_owner_dn)
+static bool fsmo_master_equal(struct ldb_dn *ntds_dn, struct ldb_dn *role_owner_dn)
 {
        if (ldb_dn_compare(ntds_dn, role_owner_dn) == 0) {
                DEBUG(0,("\nWe are the FSMO master.\n"));
@@ -56,24 +64,30 @@ static bool fsmo_master_cmp(struct ldb_dn *ntds_dn, struct ldb_dn *role_owner_dn
 /*
   see which role is we are asked to assume, initialize data and send request
  */
-WERROR dreplsrv_fsmo_role_check(struct dreplsrv_service *service,
-                               enum drepl_role_master role)
+NTSTATUS drepl_take_FSMO_role(struct irpc_message *msg,
+                             struct drepl_takeFSMORole *r)
 {
+       struct dreplsrv_service *service = talloc_get_type(msg->private_data,
+                                                          struct dreplsrv_service);
        struct ldb_dn *role_owner_dn, *fsmo_role_dn, *ntds_dn;
        TALLOC_CTX *tmp_ctx = talloc_new(service);
        uint64_t fsmo_info = 0;
        enum drsuapi_DsExtendedOperation extended_op = DRSUAPI_EXOP_NONE;
        WERROR werr;
+       enum drepl_role_master role = r->in.role;
+       struct fsmo_role_state *fsmo;
 
        ntds_dn = samdb_ntds_settings_dn(service->samdb);
        if (!ntds_dn) {
-               return WERR_DS_DRA_INTERNAL_ERROR;
+               r->out.result = WERR_DS_DRA_INTERNAL_ERROR;
+               return NT_STATUS_OK;
        }
 
        werr = dsdb_get_fsmo_role_info(tmp_ctx, service->samdb, role,
                                       &fsmo_role_dn, &role_owner_dn);
        if (!W_ERROR_IS_OK(werr)) {
-               return werr;
+               r->out.result = werr;
+               return NT_STATUS_OK;
        }
 
        switch (role) {
@@ -89,17 +103,27 @@ WERROR dreplsrv_fsmo_role_check(struct dreplsrv_service *service,
                extended_op = DRSUAPI_EXOP_FSMO_REQ_PDC;
                break;
        default:
-               return WERR_DS_DRA_INTERNAL_ERROR;
+               DEBUG(2,("Unknown role %u in role transfer\n",
+                        (unsigned)role));
+               r->out.result = WERR_DS_DRA_INTERNAL_ERROR;
+               return NT_STATUS_OK;
        }
 
-       if (fsmo_master_cmp(ntds_dn, role_owner_dn) ||
+       if (fsmo_master_equal(ntds_dn, role_owner_dn) ||
            (extended_op == DRSUAPI_EXOP_NONE)) {
                DEBUG(0,("FSMO role check failed for DN %s and owner %s ",
                         ldb_dn_get_linearized(fsmo_role_dn),
                         ldb_dn_get_linearized(role_owner_dn)));
-               return WERR_OK;
+               r->out.result = WERR_OK;
+               return NT_STATUS_OK;
        }
 
+       fsmo = talloc(msg, struct fsmo_role_state);
+       NT_STATUS_HAVE_NO_MEMORY(fsmo);
+
+       fsmo->msg = msg;
+       fsmo->r   = r;
+
        werr = drepl_request_extended_op(service,
                                         fsmo_role_dn,
                                         role_owner_dn,
@@ -107,12 +131,14 @@ WERROR dreplsrv_fsmo_role_check(struct dreplsrv_service *service,
                                         fsmo_info,
                                         0,
                                         drepl_role_callback,
-                                        NULL);
-       if (W_ERROR_IS_OK(werr)) {
-               dreplsrv_run_pending_ops(service);
-       } else {
-               DEBUG(0,("%s: drepl_request_extended_op() failed with %s",
-                        __FUNCTION__, win_errstr(werr)));
+                                        fsmo);
+       if (!W_ERROR_IS_OK(werr)) {
+               r->out.result = werr;
+               return NT_STATUS_OK;
        }
-       return werr;
+
+       /* mark this message to be answered later */
+       msg->defer_reply = true;
+       dreplsrv_run_pending_ops(service);
+       return NT_STATUS_OK;
 }
index 9248c831110fa5caca4970c5e69815e5dac1e580..0931a340b1a5043ea89776b9226cb4095726c271 100644 (file)
@@ -352,15 +352,6 @@ static NTSTATUS dreplsrv_refresh(struct irpc_message *msg,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS drepl_take_FSMO_role(struct irpc_message *msg,
-                                    struct drepl_takeFSMORole *r)
-{
-       struct dreplsrv_service *service = talloc_get_type(msg->private_data,
-                                                          struct dreplsrv_service);
-       r->out.result = dreplsrv_fsmo_role_check(service, r->in.role);
-       return NT_STATUS_OK;
-}
-
 /**
  * Called when the auth code wants us to try and replicate
  * a users secrets