diff options
Diffstat (limited to 'source4/scripting/python/samba/drs_utils.py')
-rw-r--r-- | source4/scripting/python/samba/drs_utils.py | 110 |
1 files changed, 96 insertions, 14 deletions
diff --git a/source4/scripting/python/samba/drs_utils.py b/source4/scripting/python/samba/drs_utils.py index 77f415ed17..481eec2920 100644 --- a/source4/scripting/python/samba/drs_utils.py +++ b/source4/scripting/python/samba/drs_utils.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python -# # DRS utility code # # Copyright Andrew Tridgell 2010 @@ -24,6 +22,90 @@ from samba.net import Net import samba, ldb +class drsException(Exception): + """Base element for drs errors""" + + def __init__(self, value): + self.value = value + + def __str__(self): + return "drsException: " + self.value + + +def drsuapi_connect(server, lp, creds): + """Make a DRSUAPI connection to the server. + + :param server: the name of the server to connect to + :param lp: a samba line parameter object + :param creds: credential used for the connection + :return: A tuple with the drsuapi bind object, the drsuapi handle + and the supported extensions. + :raise drsException: if the connection fails + """ + + binding_options = "seal" + if int(lp.get("log level")) >= 5: + binding_options += ",print" + binding_string = "ncacn_ip_tcp:%s[%s]" % (server, binding_options) + try: + drsuapiBind = drsuapi.drsuapi(binding_string, lp, creds) + (drsuapiHandle, bindSupportedExtensions) = drs_DsBind(drsuapiBind) + except Exception, e: + raise drsException("DRS connection to %s failed: %s" % (server, e)) + + return (drsuapiBind, drsuapiHandle, bindSupportedExtensions) + + +def sendDsReplicaSync(drsuapiBind, drsuapi_handle, source_dsa_guid, + naming_context, req_option): + """Send DS replica sync request. + + :param drsuapiBind: a drsuapi Bind object + :param drsuapi_handle: a drsuapi hanle on the drsuapi connection + :param source_dsa_guid: the guid of the source dsa for the replication + :param naming_context: the DN of the naming context to replicate + :param req_options: replication options for the DsReplicaSync call + :raise drsException: if any error occur while sending and receiving the + reply for the dsReplicaSync + """ + + nc = drsuapi.DsReplicaObjectIdentifier() + nc.dn = naming_context + + req1 = drsuapi.DsReplicaSyncRequest1() + req1.naming_context = nc; + req1.options = req_option + req1.source_dsa_guid = misc.GUID(source_dsa_guid) + + try: + drsuapiBind.DsReplicaSync(drsuapi_handle, 1, req1) + except Exception, estr: + raise drsException("DsReplicaSync failed %s" % estr) + + +def sendRemoveDsServer(drsuapiBind, drsuapi_handle, server_dsa_dn, domain): + """Send RemoveDSServer request. + + :param drsuapiBind: a drsuapi Bind object + :param drsuapi_handle: a drsuapi hanle on the drsuapi connection + :param server_dsa_dn: a DN object of the server's dsa that we want to + demote + :param domain: a DN object of the server's domain + :raise drsException: if any error occur while sending and receiving the + reply for the DsRemoveDSServer + """ + + try: + req1 = drsuapi.DsRemoveDSServerRequest1() + req1.server_dn = str(server_dsa_dn) + req1.domain_dn = str(domain) + req1.commit = 1 + + drsuapiBind.DsRemoveDSServer(drsuapi_handle, 1, req1) + except Exception, estr: + raise drsException("DsRemoveDSServer failed %s" % estr) + + def drs_DsBind(drs): '''make a DsBind call, returning the binding handle''' bind_info = drsuapi.DsBindInfoCtr() @@ -62,7 +144,7 @@ def drs_DsBind(drs): return (handle, info.info.supported_extensions) -class drs_Replicate: +class drs_Replicate(object): '''DRS replication calls''' def __init__(self, binding_string, lp, creds, samdb): @@ -139,14 +221,14 @@ class drs_Replicate: req8.replica_flags |= drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING else: req8.replica_flags |= drsuapi.DRSUAPI_DRS_WRIT_REP - req8.max_object_count = 402 - req8.max_ndr_size = 402116 - req8.extended_op = exop - req8.fsmo_info = 0 - req8.partial_attribute_set = None - req8.partial_attribute_set_ex = None - req8.mapping_ctr.num_mappings = 0 - req8.mapping_ctr.mappings = None + req8.max_object_count = 402 + req8.max_ndr_size = 402116 + req8.extended_op = exop + req8.fsmo_info = 0 + req8.partial_attribute_set = None + req8.partial_attribute_set_ex = None + req8.mapping_ctr.num_mappings = 0 + req8.mapping_ctr.mappings = None if not schema and rodc: req8.partial_attribute_set = self.drs_get_rodc_partial_attribute_set() @@ -162,12 +244,12 @@ class drs_Replicate: setattr(req5, a, getattr(req8, a)) req = req5 - while True: (level, ctr) = self.drs.DsGetNCChanges(self.drs_handle, req_level, req) - if ctr.first_object == None and ctr.object_count != 0: + if ctr.first_object is None and ctr.object_count != 0: raise RuntimeError("DsGetNCChanges: NULL first_object with object_count=%u" % (ctr.object_count)) - self.net.replicate_chunk(self.replication_state, level, ctr, schema=schema) + self.net.replicate_chunk(self.replication_state, level, ctr, + schema=schema, req_level=req_level, req=req) if ctr.more_data == 0: break req.highwatermark.tmp_highest_usn = ctr.new_highwatermark.tmp_highest_usn |