mirror of
https://github.com/samba-team/samba.git
synced 2025-08-02 00:22:11 +03:00
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). We still pass the clone_only flag into the __init__() as there's still one case where we want to avoid doing work in the case of the clone. For clarity, I'll refactor this in a subsequent patch. Signed-off-by: Tim Beale <timbeale@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
This commit is contained in:
@ -61,8 +61,6 @@ class DCJoinContext(object):
|
||||
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 not clone_only:
|
||||
# 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
|
||||
|
||||
|
||||
@ -1499,11 +1480,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)
|
||||
@ -1511,12 +1491,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))
|
||||
|
||||
@ -1573,3 +1547,55 @@ 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,
|
||||
clone_only=True)
|
||||
|
||||
# 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()
|
||||
|
Reference in New Issue
Block a user