[SCM] Samba Shared Repository - branch master updated
Andrew Bartlett
abartlet at samba.org
Fri Jul 6 02:00:02 MDT 2012
The branch, master has been updated
via 8f44389 s4-classicupgrade: Demote any other 'BDC' accounts back to a member server during upgrade
via 2908bbe s4-selftest: Test samba-tool domain dcpromo
via 1c86ab9 s4-samba-tool: Provide a samba-tool domain dcpromo that upgrades a member to a DC
via c436f98 s4-dsdb: Give a much better error message when parentGUID generation fails
via 8b32d9a s4-dsdb: Use parent_object_guid to find the correct parent for new objects
from 7abe51f talloc: remove unused variables
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 8f443895f20aa6d03fd5ae02cbbc6c3064bf42f4
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 6 15:40:02 2012 +1000
s4-classicupgrade: Demote any other 'BDC' accounts back to a member server during upgrade
This makes it clear that they cannot be a DC until they are upgraded with
samba-tool domain dcpromo.
Andrew Bartlett
Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
Autobuild-Date(master): Fri Jul 6 09:59:13 CEST 2012 on sn-devel-104
commit 2908bbe06a3905007864c6caeaa77fb46cc442ef
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 6 15:39:09 2012 +1000
s4-selftest: Test samba-tool domain dcpromo
This needs a new environment to test it properly. This requires a raise in the
number of socket wrapper interfaces.
Andrew Bartlett
commit 1c86ab9c5056c457a40dc4c8e3b39c9b940c077b
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 6 15:38:06 2012 +1000
s4-samba-tool: Provide a samba-tool domain dcpromo that upgrades a member to a DC
This command is like dcpromo in that it upgrades the existing workstation account
to be a domain controller.
The SID (and therefore any file ownerships) is preserved.
Andrew Bartlett
commit c436f986ca67c71fe5d0855a14dfea65942a47fb
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 6 15:36:12 2012 +1000
s4-dsdb: Give a much better error message when parentGUID generation fails
commit 8b32d9ad2de96679108fd7bffe804da10a652b2f
Author: Andrew Bartlett <abartlet at samba.org>
Date: Fri Jul 6 15:35:42 2012 +1000
s4-dsdb: Use parent_object_guid to find the correct parent for new objects
This allows the parent to be renmaed while a new object is added on another replica.
This rename may also be a delete, in which case we must move it to lostandfound.
Andrew Bartlett
-----------------------------------------------------------------------
Summary of changes:
lib/socket_wrapper/socket_wrapper.c | 2 +-
selftest/target/Samba.pm | 1 +
selftest/target/Samba4.pm | 131 ++++++++++++++++++++++-
source4/dsdb/repl/replicated_objects.c | 11 ++
source4/dsdb/samdb/ldb_modules/operational.c | 6 +-
source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 118 ++++++++++++++++++++-
source4/dsdb/samdb/samdb.h | 1 +
source4/scripting/python/samba/join.py | 64 +++++++++--
source4/scripting/python/samba/netcmd/domain.py | 67 ++++++++++++
source4/scripting/python/samba/upgrade.py | 14 ++-
source4/selftest/tests.py | 3 +-
11 files changed, 399 insertions(+), 19 deletions(-)
Changeset truncated at 500 lines:
diff --git a/lib/socket_wrapper/socket_wrapper.c b/lib/socket_wrapper/socket_wrapper.c
index 2c24ab7..44d21fb 100644
--- a/lib/socket_wrapper/socket_wrapper.c
+++ b/lib/socket_wrapper/socket_wrapper.c
@@ -154,7 +154,7 @@
/* This limit is to avoid broadcast sendto() needing to stat too many
* files. It may be raised (with a performance cost) to up to 254
* without changing the format above */
-#define MAX_WRAPPED_INTERFACES 32
+#define MAX_WRAPPED_INTERFACES 40
#ifdef HAVE_IPV6
/*
diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm
index 72f26a5..ec6fc48 100644
--- a/selftest/target/Samba.pm
+++ b/selftest/target/Samba.pm
@@ -161,6 +161,7 @@ sub get_interface($)
$interfaces{"plugindc"} = 30;
$interfaces{"localsubdc"} = 31;
$interfaces{"chgdcpass"} = 32;
+ $interfaces{"promotedvdc"} = 33;
# update lib/socket_wrapper/socket_wrapper.c
# #define MAX_WRAPPED_INTERFACES 32
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index f472bb5..b1998a6 100644
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -966,6 +966,78 @@ sub provision_rpc_proxy($$$)
return $ret;
}
+sub provision_promoted_vampire_dc($$$)
+{
+ my ($self, $prefix, $dcvars) = @_;
+ print "PROVISIONING VAMPIRE DC...";
+
+ # We do this so that we don't run the provision. That's the job of 'net vampire'.
+ my $ctx = $self->provision_raw_prepare($prefix, "domain controller",
+ "promotedvdc",
+ "SAMBADOMAIN",
+ "samba.example.com",
+ "2008",
+ $dcvars->{PASSWORD},
+ $dcvars->{SERVER_IP});
+
+ $ctx->{smb_conf_extra_options} = "
+ max xmit = 32K
+ server max protocol = SMB2
+
+[sysvol]
+ path = $ctx->{statedir}/sysvol
+ read only = yes
+
+[netlogon]
+ path = $ctx->{statedir}/sysvol/$ctx->{dnsname}/scripts
+ read only = no
+
+";
+
+ my $ret = $self->provision_raw_step1($ctx);
+ unless ($ret) {
+ return undef;
+ }
+
+ my $samba_tool = Samba::bindir_path($self, "samba-tool");
+ my $cmd = "";
+ $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
+ $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
+ $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} MEMBER --realm=$dcvars->{REALM}";
+ $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
+ $cmd .= " --machinepass=machine$ret->{password}";
+
+ unless (system($cmd) == 0) {
+ warn("Join failed\n$cmd");
+ return undef;
+ }
+
+ my $samba_tool = Samba::bindir_path($self, "samba-tool");
+ my $cmd = "";
+ $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
+ $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
+ $cmd .= "$samba_tool domain dcpromo $ret->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}";
+ $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
+ $cmd .= " --machinepass=machine$ret->{password}";
+
+ unless (system($cmd) == 0) {
+ warn("Join failed\n$cmd");
+ return undef;
+ }
+
+ $ret->{PROMOTED_VAMPIRE_DC_SERVER} = $ret->{SERVER};
+ $ret->{PROMOTED_VAMPIRE_DC_SERVER_IP} = $ret->{SERVER_IP};
+ $ret->{PROMOTED_VAMPIRE_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
+
+ $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
+ $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
+ $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
+ $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
+ $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
+
+ return $ret;
+}
+
sub provision_vampire_dc($$$)
{
my ($self, $prefix, $dcvars) = @_;
@@ -1486,6 +1558,11 @@ sub setup_env($$$)
$self->setup_dc("$path/dc");
}
return $self->setup_vampire_dc("$path/vampire_dc", $self->{vars}->{dc});
+ } elsif ($envname eq "promoted_vampire_dc") {
+ if (not defined($self->{vars}->{dc})) {
+ $self->setup_dc("$path/dc");
+ }
+ return $self->setup_promoted_vampire_dc("$path/promoted_vampire_dc", $self->{vars}->{dc});
} elsif ($envname eq "subdom_dc") {
if (not defined($self->{vars}->{dc})) {
$self->setup_dc("$path/dc");
@@ -1659,7 +1736,59 @@ sub setup_vampire_dc($$$)
my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
$cmd = "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
$cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
- $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{VAMPIRE_DC_SERVER}";
+ $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SERVER}";
+ $cmd .= " $dc_vars->{CONFIGURATION}";
+ $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
+ # replicate Configuration NC
+ my $cmd_repl = "$cmd \"CN=Configuration,$base_dn\"";
+ unless(system($cmd_repl) == 0) {
+ warn("Failed to replicate\n$cmd_repl");
+ return undef;
+ }
+ # replicate Default NC
+ $cmd_repl = "$cmd \"$base_dn\"";
+ unless(system($cmd_repl) == 0) {
+ warn("Failed to replicate\n$cmd_repl");
+ return undef;
+ }
+ }
+
+ return $env;
+}
+
+sub setup_promoted_vampire_dc($$$)
+{
+ my ($self, $path, $dc_vars) = @_;
+
+ my $env = $self->provision_promoted_vampire_dc($path, $dc_vars);
+
+ if (defined $env) {
+ $self->check_or_start($env, "single");
+
+ $self->wait_for_start($env);
+
+ $self->{vars}->{promoted_vampire_dc} = $env;
+
+ # force replicated DC to update repsTo/repsFrom
+ # for vampired partitions
+ my $samba_tool = Samba::bindir_path($self, "samba-tool");
+ my $cmd = "";
+ $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
+ $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
+ $cmd .= " $samba_tool drs kcc $env->{DC_SERVER}";
+ $cmd .= " $env->{CONFIGURATION}";
+ $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
+ unless (system($cmd) == 0) {
+ warn("Failed to exec kcc\n$cmd");
+ return undef;
+ }
+
+ # as 'vampired' dc may add data in its local replica
+ # we need to synchronize data between DCs
+ my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
+ $cmd = "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\"";
+ $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
+ $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SERVER}";
$cmd .= " $dc_vars->{CONFIGURATION}";
$cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
# replicate Configuration NC
diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c
index 481ff60..ec4dffe 100644
--- a/source4/dsdb/repl/replicated_objects.c
+++ b/source4/dsdb/repl/replicated_objects.c
@@ -203,6 +203,7 @@ WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
struct ldb_message *msg;
struct replPropertyMetaDataBlob *md;
struct ldb_val guid_value;
+ struct ldb_val parent_guid_value;
NTTIME whenChanged = 0;
time_t whenChanged_t;
const char *whenChanged_s;
@@ -375,8 +376,18 @@ WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
return ntstatus_to_werror(nt_status);
}
+ if (in->parent_object_guid) {
+ nt_status = GUID_to_ndr_blob(in->parent_object_guid, msg, &parent_guid_value);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return ntstatus_to_werror(nt_status);
+ }
+ } else {
+ parent_guid_value = data_blob_null;
+ }
+
out->msg = msg;
out->guid_value = guid_value;
+ out->parent_guid_value = parent_guid_value;
out->when_changed = whenChanged_s;
out->meta_data = md;
return WERR_OK;
diff --git a/source4/dsdb/samdb/ldb_modules/operational.c b/source4/dsdb/samdb/ldb_modules/operational.c
index 79a1d6f..4ce8b8f 100644
--- a/source4/dsdb/samdb/ldb_modules/operational.c
+++ b/source4/dsdb/samdb/ldb_modules/operational.c
@@ -309,9 +309,9 @@ static int construct_parent_guid(struct ldb_module *module,
/* not NC, so the object should have a parent*/
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
- DEBUG(4,(__location__ ": Parent dn for %s does not exist \n",
- ldb_dn_get_linearized(msg->dn)));
- return ldb_operr(ldb_module_get_ctx(module));
+ return ldb_error(ldb_module_get_ctx(module), LDB_ERR_OPERATIONS_ERROR,
+ talloc_asprintf(msg, "Parent dn for %s does not exist",
+ ldb_dn_get_linearized(msg->dn)));
} else if (ret != LDB_SUCCESS) {
return ret;
}
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 49fca5f..1dc7ea0 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -3671,6 +3671,122 @@ static int replmd_replicated_apply_add(struct replmd_replicated_request *ar)
return ldb_next_request(ar->module, change_req);
}
+static int replmd_replicated_apply_search_for_parent_callback(struct ldb_request *req,
+ struct ldb_reply *ares)
+{
+ struct replmd_replicated_request *ar = talloc_get_type(req->context,
+ struct replmd_replicated_request);
+ int ret;
+
+ if (!ares) {
+ return ldb_module_done(ar->req, NULL, NULL,
+ LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS &&
+ ares->error != LDB_ERR_NO_SUCH_OBJECT) {
+ return ldb_module_done(ar->req, ares->controls,
+ ares->response, ares->error);
+ }
+
+ switch (ares->type) {
+ case LDB_REPLY_ENTRY:
+ {
+ struct ldb_message *parent_msg = ares->message;
+ struct ldb_message *msg = ar->objs->objects[ar->index_current].msg;
+ struct ldb_dn *parent_dn;
+ int comp_num = ldb_dn_get_comp_num(msg->dn);
+ if (comp_num > 1) {
+ if (!ldb_dn_remove_base_components(msg->dn, comp_num - 1)) {
+ talloc_free(ares);
+ return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module));
+ }
+ }
+ if (!ldb_msg_check_string_attribute(msg, "isDeleted", "TRUE")
+ && ldb_msg_check_string_attribute(parent_msg, "isDeleted", "TRUE")) {
+ /* Per MS-DRSR 4.1.10.6.10
+ * FindBestParentObject we need to move this
+ * new object under a deleted object to
+ * lost-and-found */
+
+ ret = dsdb_wellknown_dn(ldb_module_get_ctx(ar->module), msg,
+ ldb_get_default_basedn(ldb_module_get_ctx(ar->module)),
+ DS_GUID_LOSTANDFOUND_CONTAINER,
+ &parent_dn);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module));
+ }
+ } else {
+ parent_dn = parent_msg->dn;
+ }
+ if (!ldb_dn_add_base(msg->dn, parent_dn)) {
+ talloc_free(ares);
+ return ldb_module_done(ar->req, NULL, NULL, ldb_module_operr(ar->module));
+ }
+ break;
+ }
+ case LDB_REPLY_REFERRAL:
+ /* we ignore referrals */
+ break;
+
+ case LDB_REPLY_DONE:
+ ret = replmd_replicated_apply_add(ar);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ar->req, NULL, NULL, ret);
+ }
+ }
+
+ talloc_free(ares);
+ return LDB_SUCCESS;
+}
+
+/*
+ * Look for the parent object, so we put the new object in the right place
+ */
+
+static int replmd_replicated_apply_search_for_parent(struct replmd_replicated_request *ar)
+{
+ struct ldb_context *ldb;
+ int ret;
+ char *tmp_str;
+ char *filter;
+ struct ldb_request *search_req;
+ static const char *attrs[] = {"isDeleted", NULL};
+
+ ldb = ldb_module_get_ctx(ar->module);
+
+ if (!ar->objs->objects[ar->index_current].parent_guid_value.data) {
+ return replmd_replicated_apply_add(ar);
+ }
+
+ tmp_str = ldb_binary_encode(ar, ar->objs->objects[ar->index_current].parent_guid_value);
+ if (!tmp_str) return replmd_replicated_request_werror(ar, WERR_NOMEM);
+
+ filter = talloc_asprintf(ar, "(objectGUID=%s)", tmp_str);
+ if (!filter) return replmd_replicated_request_werror(ar, WERR_NOMEM);
+ talloc_free(tmp_str);
+
+ ret = ldb_build_search_req(&search_req,
+ ldb,
+ ar,
+ ar->objs->partition_dn,
+ LDB_SCOPE_SUBTREE,
+ filter,
+ attrs,
+ NULL,
+ ar,
+ replmd_replicated_apply_search_for_parent_callback,
+ ar->req);
+ LDB_REQ_SET_LOCATION(search_req);
+
+ ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,
+ true, NULL);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ return ldb_next_request(ar->module, search_req);
+}
+
/*
handle renames that come in over DRS replication
*/
@@ -3964,7 +4080,7 @@ static int replmd_replicated_apply_search_callback(struct ldb_request *req,
if (ar->search_msg != NULL) {
ret = replmd_replicated_apply_merge(ar);
} else {
- ret = replmd_replicated_apply_add(ar);
+ ret = replmd_replicated_apply_search_for_parent(ar);
}
if (ret != LDB_SUCCESS) {
return ldb_module_done(ar->req, NULL, NULL, ret);
diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h
index 3e2f4a2..5422218 100644
--- a/source4/dsdb/samdb/samdb.h
+++ b/source4/dsdb/samdb/samdb.h
@@ -129,6 +129,7 @@ struct dsdb_control_password_change {
struct dsdb_extended_replicated_object {
struct ldb_message *msg;
struct ldb_val guid_value;
+ struct ldb_val parent_guid_value;
const char *when_changed;
struct replPropertyMetaDataBlob *meta_data;
};
diff --git a/source4/scripting/python/samba/join.py b/source4/scripting/python/samba/join.py
index 9ef7d3d..0d21279 100644
--- a/source4/scripting/python/samba/join.py
+++ b/source4/scripting/python/samba/join.py
@@ -47,8 +47,9 @@ class dc_join(object):
'''perform a DC join'''
def __init__(ctx, server=None, creds=None, lp=None, site=None,
- netbios_name=None, targetdir=None, domain=None,
- machinepass=None, use_ntvfs=False, dns_backend=None):
+ netbios_name=None, targetdir=None, domain=None,
+ machinepass=None, use_ntvfs=False, dns_backend=None,
+ promote_existing=False):
ctx.creds = creds
ctx.lp = lp
ctx.site = site
@@ -60,6 +61,9 @@ class dc_join(object):
else:
ctx.dns_backend = dns_backend
+ ctx.promote_existing = promote_existing
+ ctx.promote_from_dn = None
+
ctx.nc_list = []
ctx.full_nc_list = []
@@ -203,6 +207,25 @@ class dc_join(object):
except Exception:
pass
+ def promote_possible(ctx):
+ '''confirm that the account is just a bare NT4 BDC or a member server, so can be safely promoted'''
+ if ctx.subdomain:
+ # This shouldn't happen
+ raise Exception("Can not promote into a subdomain")
+
+ res = ctx.samdb.search(base=ctx.samdb.get_default_basedn(),
+ expression='sAMAccountName=%s' % ldb.binary_encode(ctx.samname),
+ attrs=["msDS-krbTgtLink", "userAccountControl", "serverReferenceBL", "rIDSetReferences"])
+ if len(res) == 0:
+ raise Exception("Could not find domain member account '%s' to promote to a DC, use 'samba-tool domain join' instead'" % ctx.samname)
+ if "msDS-krbTgtLink" in res[0] or "serverReferenceBL" in res[0] or "rIDSetReferences" in res[0]:
+ raise Exception("Account '%s' appears to be an active DC, use 'samba-tool domain join' if you must re-create this account" % ctx.samname)
+ if (int(res[0]["userAccountControl"][0]) & (samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT|samba.dsdb.UF_SERVER_TRUST_ACCOUNT) == 0):
+ raise Exception("Account %s is not a domain member or a bare NT4 BDC, use 'samba-tool domain join' instead'" % ctx.samname)
+
+ ctx.promote_from_dn = res[0].dn
+
+
def find_dc(ctx, domain):
'''find a writeable DC for the given domain'''
try:
@@ -439,13 +462,29 @@ class dc_join(object):
"dnshostname" : ctx.dnshostname}
if ctx.behavior_version >= samba.dsdb.DS_DOMAIN_FUNCTION_2008:
rec['msDS-SupportedEncryptionTypes'] = str(samba.dsdb.ENC_ALL_TYPES)
+ elif ctx.promote_existing:
+ rec['msDS-SupportedEncryptionTypes'] = []
if ctx.managedby:
rec["managedby"] = ctx.managedby
+ elif ctx.promote_existing:
+ rec["managedby"] = []
+
if ctx.never_reveal_sid:
rec["msDS-NeverRevealGroup"] = ctx.never_reveal_sid
+ elif ctx.promote_existing:
+ rec["msDS-NeverRevealGroup"] = []
+
if ctx.reveal_sid:
rec["msDS-RevealOnDemandGroup"] = ctx.reveal_sid
- ctx.samdb.add(rec)
+ elif ctx.promote_existing:
+ rec["msDS-RevealOnDemandGroup"] = []
+
+ if ctx.promote_existing:
+ if ctx.promote_from_dn != ctx.acct_dn:
+ ctx.samdb.rename(ctx.promote_from_dn, ctx.acct_dn)
+ ctx.samdb.modify(ldb.Message.from_dict(ctx.samdb, rec, ldb.FLAG_MOD_REPLACE))
+ else:
+ ctx.samdb.add(rec)
if ctx.krbtgt_dn:
ctx.add_krbtgt_account()
@@ -490,7 +529,7 @@ class dc_join(object):
for i in range(len(ctx.SPNs)):
ctx.SPNs[i] = ctx.SPNs[i].replace("$NTDSGUID", str(ctx.ntds_guid))
m["servicePrincipalName"] = ldb.MessageElement(ctx.SPNs,
- ldb.FLAG_MOD_ADD,
+ ldb.FLAG_MOD_REPLACE,
"servicePrincipalName")
ctx.samdb.modify(m)
@@ -908,8 +947,11 @@ class dc_join(object):
ctx.full_nc_list += ['DC=ForestDnsZones,%s' % ctx.root_dn]
ctx.nc_list += ['DC=ForestDnsZones,%s' % ctx.root_dn]
-
- ctx.cleanup_old_join()
+ if ctx.promote_existing:
+ ctx.promote_possible()
+ else:
+ ctx.cleanup_old_join()
+
try:
ctx.join_add_objects()
ctx.join_provision()
@@ -927,11 +969,12 @@ class dc_join(object):
def join_RODC(server=None, creds=None, lp=None, site=None, netbios_name=None,
targetdir=None, domain=None, domain_critical_only=False,
- machinepass=None, use_ntvfs=False, dns_backend=None):
+ machinepass=None, use_ntvfs=False, dns_backend=None,
+ promote_existing=False):
"""join as a RODC"""
ctx = dc_join(server, creds, lp, site, netbios_name, targetdir, domain,
- machinepass, use_ntvfs, dns_backend)
+ machinepass, use_ntvfs, dns_backend, promote_existing)
lp.set("workgroup", ctx.domain_name)
print("workgroup is %s" % ctx.domain_name)
@@ -981,10 +1024,11 @@ def join_RODC(server=None, creds=None, lp=None, site=None, netbios_name=None,
--
Samba Shared Repository
More information about the samba-cvs
mailing list