[PATCH] Dependent changes for rename tool
Tim Beale
timbeale at catalyst.net.nz
Thu Jun 28 03:07:00 UTC 2018
Hi,
Attached are the first few 'pre-work' patches for the backup-rename tool
(the rename tool is dependent on these changes, but this patch-set
doesn't include the rename tool itself). These changes mostly try to
tidy up the join.py clone code so that it's simpler to re-use. These are
ready for review and delivery.
Clean CI results here:
https://gitlab.com/catalyst-samba/samba/pipelines/24718107
Branch also here:
https://gitlab.com/catalyst-samba/samba/commits/tim-rename-set1
Review appreciated.
Thanks,
Tim
-------------- next part --------------
From 2cf83d3b16b3da9198f549ee81555bfc9d292567 Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale at catalyst.net.nz>
Date: Mon, 11 Jun 2018 09:14:06 +1200
Subject: [PATCH 1/4] provision: Small refactor to host-IP logic
Split out the code that determines the host-IP of the new server into
separate functions. This will allow us to re-use the same logic in the
backup/restore case.
Signed-off-by: Tim Beale <timbeale at catalyst.net.nz
---
python/samba/provision/__init__.py | 54 ++++++++++++++++++++++----------------
1 file changed, 31 insertions(+), 23 deletions(-)
diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py
index 36f50f2..5609680 100644
--- a/python/samba/provision/__init__.py
+++ b/python/samba/provision/__init__.py
@@ -2040,6 +2040,35 @@ def directory_create_or_exists(path, mode=0o755):
else:
raise ProvisioningError("Failed to create directory %s: %s" % (path, e.strerror))
+def determine_host_ip(logger, lp, hostip=None):
+ if hostip is None:
+ logger.info("Looking up IPv4 addresses")
+ hostips = interface_ips_v4(lp)
+ if len(hostips) > 0:
+ hostip = hostips[0]
+ if len(hostips) > 1:
+ logger.warning("More than one IPv4 address found. Using %s",
+ hostip)
+ if hostip == "127.0.0.1":
+ hostip = None
+ if hostip is None:
+ logger.warning("No IPv4 address will be assigned")
+
+ return hostip
+
+def determine_host_ip6(logger, lp, hostip6=None):
+ if hostip6 is None:
+ logger.info("Looking up IPv6 addresses")
+ hostips = interface_ips_v6(lp)
+ if hostips:
+ hostip6 = hostips[0]
+ if len(hostips) > 1:
+ logger.warning("More than one IPv6 address found. Using %s", hostip6)
+ if hostip6 is None:
+ logger.warning("No IPv6 address will be assigned")
+
+ return hostip6
+
def provision(logger, session_info, smbconf=None,
targetdir=None, samdb_fill=FILL_FULL, realm=None, rootdn=None,
domaindn=None, schemadn=None, configdn=None, serverdn=None,
@@ -2147,29 +2176,8 @@ def provision(logger, session_info, smbconf=None,
paths.root_uid = root_uid;
paths.root_gid = root_gid
- if hostip is None:
- logger.info("Looking up IPv4 addresses")
- hostips = interface_ips_v4(lp)
- if len(hostips) > 0:
- hostip = hostips[0]
- if len(hostips) > 1:
- logger.warning("More than one IPv4 address found. Using %s",
- hostip)
- if hostip == "127.0.0.1":
- hostip = None
- if hostip is None:
- logger.warning("No IPv4 address will be assigned")
-
- if hostip6 is None:
- logger.info("Looking up IPv6 addresses")
- hostips = interface_ips_v6(lp)
- if hostips:
- hostip6 = hostips[0]
- if len(hostips) > 1:
- logger.warning("More than one IPv6 address found. Using %s", hostip6)
- if hostip6 is None:
- logger.warning("No IPv6 address will be assigned")
-
+ hostip = determine_host_ip(logger, lp, hostip)
+ hostip6 = determine_host_ip6(logger, lp, hostip6)
names.hostip = hostip
names.hostip6 = hostip6
names.domainguid = domainguid
--
2.7.4
From 5e35da190d56c3a72ad67285115a439f3d49f11d Mon Sep 17 00:00:00 2001
From: Aaron Haslett <aaronhaslett at catalyst.net.nz>
Date: Tue, 1 May 2018 11:10:11 +1200
Subject: [PATCH 2/4] join: Pipe through dns_backend option for clones
Allow join_clone() calls to specify a dns_backend parameter for the new
cloned DB.
Signed-off-by: Aaron Haslett<aaronhaslett at catalyst.net.nz>
---
python/samba/join.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/python/samba/join.py b/python/samba/join.py
index 30ecce7..b5cdf52 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -1495,10 +1495,10 @@ def join_DC(logger=None, server=None, creds=None, lp=None, site=None, netbios_na
logger.info("Joined domain %s (SID %s) as a DC" % (ctx.domain_name, ctx.domsid))
def join_clone(logger=None, server=None, creds=None, lp=None,
- targetdir=None, domain=None, include_secrets=False):
+ targetdir=None, domain=None, include_secrets=False, dns_backend="NONE"):
"""Join as a DC."""
ctx = dc_join(logger, server, creds, lp, site=None, netbios_name=None, targetdir=targetdir, domain=domain,
- machinepass=None, use_ntvfs=False, dns_backend="NONE", promote_existing=False, clone_only=True)
+ machinepass=None, use_ntvfs=False, dns_backend=dns_backend, promote_existing=False, clone_only=True)
lp.set("workgroup", ctx.domain_name)
logger.info("workgroup is %s" % ctx.domain_name)
--
2.7.4
From 9940f32fdcfa750dbb9dd94552d9b9af9f7f1cf5 Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale at catalyst.net.nz>
Date: Mon, 25 Jun 2018 17:21:00 +1200
Subject: [PATCH 3/4] join: Rename dc_join() so it looks like an object
dc_join() is creating an object, but it currently looks like it's
just a function call. Rename it to look more object-like.
Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
---
python/samba/join.py | 29 +++++++++++++++++------------
python/samba/tests/join.py | 13 +++++++------
source4/dsdb/tests/python/acl.py | 13 +++++++------
source4/torture/drs/python/repl_rodc.py | 20 +++++++++++++-------
4 files changed, 44 insertions(+), 31 deletions(-)
diff --git a/python/samba/join.py b/python/samba/join.py
index b5cdf52..e20a444 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -50,7 +50,7 @@ class DCJoinException(Exception):
super(DCJoinException, self).__init__("Can't join, error: %s" % msg)
-class dc_join(object):
+class DCJoinContext(object):
"""Perform a DC join."""
def __init__(ctx, logger=None, server=None, creds=None, lp=None, site=None,
@@ -1418,9 +1418,10 @@ def join_RODC(logger=None, server=None, creds=None, lp=None, site=None, netbios_
backend_store=None):
"""Join as a RODC."""
- ctx = dc_join(logger, server, creds, lp, site, netbios_name, targetdir, domain,
- machinepass, use_ntvfs, dns_backend, promote_existing,
- plaintext_secrets, backend_store=backend_store)
+ ctx = DCJoinContext(logger, server, creds, lp, site, netbios_name,
+ targetdir, domain, machinepass, use_ntvfs, dns_backend,
+ promote_existing, plaintext_secrets,
+ backend_store=backend_store)
lp.set("workgroup", ctx.domain_name)
logger.info("workgroup is %s" % ctx.domain_name)
@@ -1470,9 +1471,10 @@ def join_DC(logger=None, server=None, creds=None, lp=None, site=None, netbios_na
promote_existing=False, plaintext_secrets=False,
backend_store=None):
"""Join as a DC."""
- ctx = dc_join(logger, server, creds, lp, site, netbios_name, targetdir, domain,
- machinepass, use_ntvfs, dns_backend, promote_existing,
- plaintext_secrets, backend_store=backend_store)
+ ctx = DCJoinContext(logger, server, creds, lp, site, netbios_name,
+ targetdir, domain, machinepass, use_ntvfs, dns_backend,
+ promote_existing, plaintext_secrets,
+ backend_store=backend_store)
lp.set("workgroup", ctx.domain_name)
logger.info("workgroup is %s" % ctx.domain_name)
@@ -1497,8 +1499,10 @@ def join_DC(logger=None, server=None, creds=None, lp=None, site=None, netbios_na
def join_clone(logger=None, server=None, creds=None, lp=None,
targetdir=None, domain=None, include_secrets=False, dns_backend="NONE"):
"""Join as a DC."""
- ctx = dc_join(logger, server, creds, lp, site=None, netbios_name=None, targetdir=targetdir, domain=domain,
- machinepass=None, use_ntvfs=False, dns_backend=dns_backend, promote_existing=False, clone_only=True)
+ ctx = DCJoinContext(logger, server, creds, lp, site=None, netbios_name=None,
+ targetdir=targetdir, domain=domain, machinepass=None,
+ use_ntvfs=False, dns_backend=dns_backend,
+ promote_existing=False, clone_only=True)
lp.set("workgroup", ctx.domain_name)
logger.info("workgroup is %s" % ctx.domain_name)
@@ -1521,9 +1525,10 @@ def join_subdomain(logger=None, server=None, creds=None, lp=None, site=None,
dns_backend=None, plaintext_secrets=False,
backend_store=None):
"""Join as a DC."""
- ctx = dc_join(logger, server, creds, lp, site, netbios_name, targetdir, parent_domain,
- machinepass, use_ntvfs, dns_backend, plaintext_secrets,
- backend_store=backend_store)
+ ctx = DCJoinContext(logger, server, creds, lp, site, netbios_name,
+ targetdir, parent_domain, machinepass, use_ntvfs,
+ dns_backend, plaintext_secrets,
+ backend_store=backend_store)
ctx.subdomain = True
if adminpass is None:
ctx.adminpass = samba.generate_random_password(12, 32)
diff --git a/python/samba/tests/join.py b/python/samba/tests/join.py
index 1f9fab1..904c283 100644
--- a/python/samba/tests/join.py
+++ b/python/samba/tests/join.py
@@ -21,7 +21,7 @@ import sys
import shutil
import os
from samba.tests.dns_base import DNSTKeyTest
-from samba.join import dc_join
+from samba.join import DCJoinContext
from samba.dcerpc import drsuapi, misc, dns
from samba.credentials import Credentials
@@ -42,11 +42,12 @@ class JoinTestCase(DNSTKeyTest):
self.netbios_name = "jointest1"
logger = get_logger()
- self.join_ctx = dc_join(server=self.server, creds=self.creds, lp=self.get_loadparm(),
- netbios_name=self.netbios_name,
- targetdir=self.tempdir,
- domain=None, logger=logger,
- dns_backend="SAMBA_INTERNAL")
+ self.join_ctx = DCJoinContext(server=self.server, creds=self.creds,
+ lp=self.get_loadparm(),
+ netbios_name=self.netbios_name,
+ targetdir=self.tempdir,
+ domain=None, logger=logger,
+ dns_backend="SAMBA_INTERNAL")
self.join_ctx.userAccountControl = (samba.dsdb.UF_SERVER_TRUST_ACCOUNT |
samba.dsdb.UF_TRUSTED_FOR_DELEGATION)
diff --git a/source4/dsdb/tests/python/acl.py b/source4/dsdb/tests/python/acl.py
index 29fcf55..c698bf1 100755
--- a/source4/dsdb/tests/python/acl.py
+++ b/source4/dsdb/tests/python/acl.py
@@ -13,7 +13,7 @@ import samba
from samba.tests.subunitrun import SubunitOptions, TestProgram
import samba.getopt as options
-from samba.join import dc_join
+from samba.join import DCJoinContext
from ldb import (
SCOPE_BASE, SCOPE_SUBTREE, LdbError, ERR_NO_SUCH_OBJECT,
@@ -1841,11 +1841,12 @@ class AclSPNTests(AclTests):
self.computerdn = "CN=%s,CN=computers,%s" % (self.computername, self.base_dn)
self.dc_dn = "CN=%s,OU=Domain Controllers,%s" % (self.dcname, self.base_dn)
self.site = "Default-First-Site-Name"
- self.rodcctx = dc_join(server=host, creds=creds, lp=lp,
- site=self.site, netbios_name=self.rodcname, targetdir=None,
- domain=None)
- self.dcctx = dc_join(server=host, creds=creds, lp=lp, site=self.site,
- netbios_name=self.dcname, targetdir=None, domain=None)
+ self.rodcctx = DCJoinContext(server=host, creds=creds, lp=lp,
+ site=self.site, netbios_name=self.rodcname,
+ targetdir=None, domain=None)
+ self.dcctx = DCJoinContext(server=host, creds=creds, lp=lp,
+ site=self.site, netbios_name=self.dcname,
+ targetdir=None, domain=None)
self.ldb_admin.newuser(self.test_user, self.user_pass)
self.ldb_user1 = self.get_ldb_connection(self.test_user, self.user_pass)
self.user_sid1 = self.sd_utils.get_object_sid(self.get_user_dn(self.test_user))
diff --git a/source4/torture/drs/python/repl_rodc.py b/source4/torture/drs/python/repl_rodc.py
index 1d84c99..a785932 100644
--- a/source4/torture/drs/python/repl_rodc.py
+++ b/source4/torture/drs/python/repl_rodc.py
@@ -33,7 +33,7 @@ import ldb
from ldb import SCOPE_BASE
from samba import WERRORError
-from samba.join import dc_join
+from samba.join import DCJoinContext
from samba.dcerpc import drsuapi, misc, drsblobs, security
from samba.drs_utils import drs_DsBind, drs_Replicate
from samba.ndr import ndr_unpack, ndr_pack
@@ -101,9 +101,12 @@ class DrsRodcTestCase(drs_base.DrsBaseTestCase):
self.computer_dn = "CN=%s,OU=Domain Controllers,%s" % (self.rodc_name, self.base_dn)
- self.rodc_ctx = dc_join(server=self.ldb_dc1.host_dns_name(), creds=self.get_credentials(), lp=self.get_loadparm(),
- site=self.site, netbios_name=self.rodc_name,
- targetdir=None, domain=None, machinepass=self.rodc_pass)
+ self.rodc_ctx = DCJoinContext(server=self.ldb_dc1.host_dns_name(),
+ creds=self.get_credentials(),
+ lp=self.get_loadparm(), site=self.site,
+ netbios_name=self.rodc_name,
+ targetdir=None, domain=None,
+ machinepass=self.rodc_pass)
self._create_rodc(self.rodc_ctx)
self.rodc_ctx.create_tmp_samdb()
self.tmp_samdb = self.rodc_ctx.tmp_samdb
@@ -459,9 +462,12 @@ class DrsRodcTestCase(drs_base.DrsBaseTestCase):
"""
# Create a new identical RODC with just the first letter missing
other_rodc_name = self.rodc_name[1:]
- other_rodc_ctx = dc_join(server=self.ldb_dc1.host_dns_name(), creds=self.get_credentials(), lp=self.get_loadparm(),
- site=self.site, netbios_name=other_rodc_name,
- targetdir=None, domain=None, machinepass=self.rodc_pass)
+ other_rodc_ctx = DCJoinContext(server=self.ldb_dc1.host_dns_name(),
+ creds=self.get_credentials(),
+ lp=self.get_loadparm(), site=self.site,
+ netbios_name=other_rodc_name,
+ targetdir=None, domain=None,
+ machinepass=self.rodc_pass)
self._create_rodc(other_rodc_ctx)
other_rodc_creds = Credentials()
--
2.7.4
From c29e0676ff4d5ea807c15f5c2e9267b1539087e9 Mon Sep 17 00:00:00 2001
From: Tim Beale <timbeale at catalyst.net.nz>
Date: Mon, 11 Jun 2018 16:33:19 +1200
Subject: [PATCH 4/4] join: Refactor clone_only case to simplify code
Currently for DC clones, we create a regular DCJoinContext, se a
'clone_only' flag, and then make lots of special checks for this flag
throughout the code. Instead, we can use inheritance to create a
DCCloneContext sub-class, and put the specialization there.
This means we can remove all the 'clone_only' checks from the code. The
only 2 methods that really differ are do_join() and join_finalize(), and
these don't share much code at all. (To avoid duplication, I split the
first part of do_join() into a new build_nc_lists() function, but this
is a pretty trivial code move).
Signed-off-by: Tim Beale <timbeale at catalyst.net.nz>
---
python/samba/join.py | 123 ++++++++++++++++++++++++++++++---------------------
1 file changed, 73 insertions(+), 50 deletions(-)
diff --git a/python/samba/join.py b/python/samba/join.py
index e20a444..3922e43 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -56,13 +56,11 @@ class DCJoinContext(object):
def __init__(ctx, logger=None, server=None, creds=None, lp=None, site=None,
netbios_name=None, targetdir=None, domain=None,
machinepass=None, use_ntvfs=False, dns_backend=None,
- promote_existing=False, clone_only=False,
+ promote_existing=False,
plaintext_secrets=False, backend_store=None):
if site is None:
site = "Default-First-Site-Name"
- ctx.clone_only=clone_only
-
ctx.logger = logger
ctx.creds = creds
ctx.lp = lp
@@ -119,18 +117,7 @@ class DCJoinContext(object):
ctx.acct_pass = samba.generate_random_machine_password(128, 255)
ctx.dnsdomain = ctx.samdb.domain_dns_name()
- if clone_only:
- # As we don't want to create or delete these DNs, we set them to None
- ctx.server_dn = None
- ctx.ntds_dn = None
- ctx.acct_dn = None
- ctx.myname = ctx.server.split('.')[0]
- ctx.ntds_guid = None
- ctx.rid_manager_dn = None
-
- # Save this early
- ctx.remote_dc_ntds_guid = ctx.samdb.get_ntds_GUID()
- else:
+ if netbios_name:
# work out the DNs of all the objects we will be adding
ctx.myname = netbios_name
ctx.samname = "%s$" % ctx.myname
@@ -1188,12 +1175,11 @@ class DCJoinContext(object):
# DC we just replicated from then we don't need to send the updatereplicateref
# as replication between sites is time based and on the initiative of the
# requesting DC
- if not ctx.clone_only:
- ctx.logger.info("Sending DsReplicaUpdateRefs for all the replicated partitions")
- for nc in ctx.nc_list:
- ctx.send_DsReplicaUpdateRefs(nc)
+ ctx.logger.info("Sending DsReplicaUpdateRefs for all the replicated partitions")
+ for nc in ctx.nc_list:
+ ctx.send_DsReplicaUpdateRefs(nc)
- if not ctx.clone_only and ctx.RODC:
+ if ctx.RODC:
print("Setting RODC invocationId")
ctx.local_samdb.set_invocation_id(str(ctx.invocation_id))
ctx.local_samdb.set_opaque_integer("domainFunctionality",
@@ -1224,17 +1210,12 @@ class DCJoinContext(object):
m.dn = ldb.Dn(ctx.local_samdb, '@ROOTDSE')
m["isSynchronized"] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_REPLACE, "isSynchronized")
- # We want to appear to be the server we just cloned
- if ctx.clone_only:
- guid = ctx.remote_dc_ntds_guid
- else:
- guid = ctx.ntds_guid
-
+ guid = ctx.ntds_guid
m["dsServiceName"] = ldb.MessageElement("<GUID=%s>" % str(guid),
ldb.FLAG_MOD_REPLACE, "dsServiceName")
ctx.local_samdb.modify(m)
- if ctx.clone_only or ctx.subdomain:
+ if ctx.subdomain:
return
secrets_ldb = Ldb(ctx.paths.secrets, session_info=system_session(), lp=ctx.lp)
@@ -1359,7 +1340,7 @@ class DCJoinContext(object):
ctx.local_samdb.add(rec)
- def do_join(ctx):
+ def build_nc_lists(ctx):
# nc_list is the list of naming context (NC) for which we will
# replicate in and send a updateRef command to the partner DC
@@ -1380,23 +1361,24 @@ class DCJoinContext(object):
ctx.full_nc_list += [ctx.domaindns_zone]
ctx.full_nc_list += [ctx.forestdns_zone]
- if not ctx.clone_only:
- if ctx.promote_existing:
- ctx.promote_possible()
- else:
- ctx.cleanup_old_join()
+ def do_join(ctx):
+ ctx.build_nc_lists()
+
+ if ctx.promote_existing:
+ ctx.promote_possible()
+ else:
+ ctx.cleanup_old_join()
try:
- if not ctx.clone_only:
- ctx.join_add_objects()
+ ctx.join_add_objects()
ctx.join_provision()
ctx.join_replicate()
- if (not ctx.clone_only and ctx.subdomain):
+ if ctx.subdomain:
ctx.join_add_objects2()
ctx.join_provision_own_domain()
ctx.join_setup_trusts()
- if not ctx.clone_only and ctx.dns_backend != "NONE":
+ if ctx.dns_backend != "NONE":
ctx.join_add_dns_records()
ctx.join_replicate_new_dns_records()
@@ -1406,8 +1388,7 @@ class DCJoinContext(object):
print("Join failed - cleaning up")
except IOError:
pass
- if not ctx.clone_only:
- ctx.cleanup_old_join()
+ ctx.cleanup_old_join()
raise
@@ -1498,11 +1479,10 @@ def join_DC(logger=None, server=None, creds=None, lp=None, site=None, netbios_na
def join_clone(logger=None, server=None, creds=None, lp=None,
targetdir=None, domain=None, include_secrets=False, dns_backend="NONE"):
- """Join as a DC."""
- ctx = DCJoinContext(logger, server, creds, lp, site=None, netbios_name=None,
- targetdir=targetdir, domain=domain, machinepass=None,
- use_ntvfs=False, dns_backend=dns_backend,
- promote_existing=False, clone_only=True)
+ """Creates a local clone of a remote DC."""
+ ctx = DCCloneContext(logger, server, creds, lp, targetdir=targetdir,
+ domain=domain, dns_backend=dns_backend,
+ include_secrets=include_secrets)
lp.set("workgroup", ctx.domain_name)
logger.info("workgroup is %s" % ctx.domain_name)
@@ -1510,12 +1490,6 @@ def join_clone(logger=None, server=None, creds=None, lp=None,
lp.set("realm", ctx.realm)
logger.info("realm is %s" % ctx.realm)
- ctx.replica_flags |= (drsuapi.DRSUAPI_DRS_WRIT_REP |
- drsuapi.DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS)
- if not include_secrets:
- ctx.replica_flags |= drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING
- ctx.domain_replica_flags = ctx.replica_flags
-
ctx.do_join()
logger.info("Cloned domain %s (SID %s)" % (ctx.domain_name, ctx.domsid))
@@ -1572,3 +1546,52 @@ def join_subdomain(logger=None, server=None, creds=None, lp=None, site=None,
ctx.do_join()
ctx.logger.info("Created domain %s (SID %s) as a DC" % (ctx.domain_name, ctx.domsid))
+
+
+class DCCloneContext(DCJoinContext):
+ """Clones a remote DC."""
+
+ def __init__(ctx, logger=None, server=None, creds=None, lp=None,
+ targetdir=None, domain=None, dns_backend=None,
+ include_secrets=False):
+ super(DCCloneContext, ctx).__init__(logger, server, creds, lp,
+ targetdir=targetdir, domain=domain,
+ dns_backend=dns_backend)
+
+ # As we don't want to create or delete these DNs, we set them to None
+ ctx.server_dn = None
+ ctx.ntds_dn = None
+ ctx.acct_dn = None
+ ctx.myname = ctx.server.split('.')[0]
+ ctx.ntds_guid = None
+ ctx.rid_manager_dn = None
+
+ # Save this early
+ ctx.remote_dc_ntds_guid = ctx.samdb.get_ntds_GUID()
+
+ ctx.replica_flags |= (drsuapi.DRSUAPI_DRS_WRIT_REP |
+ drsuapi.DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS)
+ if not include_secrets:
+ ctx.replica_flags |= drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING
+ ctx.domain_replica_flags = ctx.replica_flags
+
+ def join_finalise(ctx):
+ ctx.logger.info("Setting isSynchronized and dsServiceName")
+ m = ldb.Message()
+ m.dn = ldb.Dn(ctx.local_samdb, '@ROOTDSE')
+ m["isSynchronized"] = ldb.MessageElement("TRUE", ldb.FLAG_MOD_REPLACE, "isSynchronized")
+
+ # We want to appear to be the server we just cloned
+ guid = ctx.remote_dc_ntds_guid
+ m["dsServiceName"] = ldb.MessageElement("<GUID=%s>" % str(guid),
+ ldb.FLAG_MOD_REPLACE, "dsServiceName")
+ ctx.local_samdb.modify(m)
+
+ def do_join(ctx):
+ ctx.build_nc_lists()
+
+ # When cloning a DC, we just want to provision a DC locally, then
+ # grab the remote DC's entire DB via DRS replication
+ ctx.join_provision()
+ ctx.join_replicate()
+ ctx.join_finalise()
--
2.7.4
More information about the samba-technical
mailing list