summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/scripting/python/samba/kcc_utils.py460
1 files changed, 214 insertions, 246 deletions
diff --git a/source4/scripting/python/samba/kcc_utils.py b/source4/scripting/python/samba/kcc_utils.py
index 13bc2412d6..f762f4a252 100644
--- a/source4/scripting/python/samba/kcc_utils.py
+++ b/source4/scripting/python/samba/kcc_utils.py
@@ -3,6 +3,7 @@
# KCC topology utilities
#
# Copyright (C) Dave Craft 2011
+# Copyright (C) Jelmer Vernooij 2011
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,37 +18,41 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import samba, ldb
+import ldb
import uuid
-from samba import dsdb
-from samba.dcerpc import misc
-from samba.dcerpc import drsblobs
-from samba.dcerpc import drsuapi
-from samba.common import dsdb_Dn
-from samba.ndr import ndr_unpack
-from samba.ndr import ndr_pack
+from samba import dsdb
+from samba.dcerpc import (
+ drsblobs,
+ drsuapi,
+ misc,
+ )
+from samba.common import dsdb_Dn
+from samba.ndr import (ndr_unpack, ndr_pack)
-class NCType:
+
+class NCType(object):
(unknown, schema, domain, config, application) = range(0, 5)
-class NamingContext:
- """Base class for a naming context. Holds the DN,
- GUID, SID (if available) and type of the DN.
- Subclasses may inherit from this and specialize
+
+class NamingContext(object):
+ """Base class for a naming context.
+
+ Holds the DN, GUID, SID (if available) and type of the DN.
+ Subclasses may inherit from this and specialize
"""
def __init__(self, nc_dnstr, nc_guid=None, nc_sid=None):
"""Instantiate a NamingContext
- :param nc_dnstr: NC dn string
- :param nc_guid: NC guid
- :param nc_sid: NC sid
+
+ :param nc_dnstr: NC dn string
+ :param nc_guid: NC guid
+ :param nc_sid: NC sid
"""
- self.nc_dnstr = nc_dnstr
- self.nc_guid = nc_guid
- self.nc_sid = nc_sid
- self.nc_type = NCType.unknown
- return
+ self.nc_dnstr = nc_dnstr
+ self.nc_guid = nc_guid
+ self.nc_sid = nc_sid
+ self.nc_type = NCType.unknown
def __str__(self):
'''Debug dump string output of class'''
@@ -56,7 +61,6 @@ class NamingContext:
text = text + "\n\tnc_guid=%s" % str(self.nc_guid)
text = text + "\n\tnc_sid=%s" % self.nc_sid
text = text + "\n\tnc_type=%s" % self.nc_type
-
return text
def is_schema(self):
@@ -91,15 +95,15 @@ class NamingContext:
self.nc_type = NCType.domain
else:
self.nc_type = NCType.application
- return
def identify_by_dsa_attr(self, samdb, attr):
"""Given an NC which has been discovered thru the
- nTDSDSA database object, determine what type of NC
- it is (i.e. schema, config, domain, application) via
- the use of the schema attribute under which the NC
- was found.
- :param attr: attr of nTDSDSA object where NC DN appears
+ nTDSDSA database object, determine what type of NC
+ it is (i.e. schema, config, domain, application) via
+ the use of the schema attribute under which the NC
+ was found.
+
+ :param attr: attr of nTDSDSA object where NC DN appears
"""
# If the NC is listed under msDS-HasDomainNCs then
# this can only be a domain NC and it is our default
@@ -124,29 +128,29 @@ class NamingContext:
if self.nc_type == NCType.unknown:
self.identify_by_basedn(samdb)
- return
class NCReplica(NamingContext):
- """Class defines a naming context replica that is relative
- to a specific DSA. This is a more specific form of
- NamingContext class (inheriting from that class) and it
- identifies unique attributes of the DSA's replica for a NC.
+ """Naming context replica that is relative to a specific DSA.
+
+ This is a more specific form of NamingContext class (inheriting from that
+ class) and it identifies unique attributes of the DSA's replica for a NC.
"""
- def __init__(self, dsa_dnstr, dsa_guid, nc_dnstr, \
+ def __init__(self, dsa_dnstr, dsa_guid, nc_dnstr,
nc_guid=None, nc_sid=None):
"""Instantiate a Naming Context Replica
- :param dsa_guid: GUID of DSA where replica appears
- :param nc_dnstr: NC dn string
- :param nc_guid: NC guid
- :param nc_sid: NC sid
+
+ :param dsa_guid: GUID of DSA where replica appears
+ :param nc_dnstr: NC dn string
+ :param nc_guid: NC guid
+ :param nc_sid: NC sid
"""
- self.rep_dsa_dnstr = dsa_dnstr
- self.rep_dsa_guid = dsa_guid
- self.rep_default = False # replica for DSA's default domain
- self.rep_partial = False
- self.rep_ro = False
- self.rep_instantiated_flags = 0
+ self.rep_dsa_dnstr = dsa_dnstr
+ self.rep_dsa_guid = dsa_guid
+ self.rep_default = False # replica for DSA's default domain
+ self.rep_partial = False
+ self.rep_ro = False
+ self.rep_instantiated_flags = 0
# RepsFromTo tuples
self.rep_repsFrom = []
@@ -160,7 +164,6 @@ class NCReplica(NamingContext):
# Call my super class we inherited from
NamingContext.__init__(self, nc_dnstr, nc_guid, nc_sid)
- return
def __str__(self):
'''Debug dump string output of class'''
@@ -183,13 +186,13 @@ class NCReplica(NamingContext):
self.rep_instantiated_flags = 0
else:
self.rep_instantiated_flags = flags
- return
def identify_by_dsa_attr(self, samdb, attr):
"""Given an NC which has been discovered thru the
- nTDSDSA database object, determine what type of NC
- replica it is (i.e. partial, read only, default)
- :param attr: attr of nTDSDSA object where NC DN appears
+ nTDSDSA database object, determine what type of NC
+ replica it is (i.e. partial, read only, default)
+
+ :param attr: attr of nTDSDSA object where NC DN appears
"""
# If the NC was found under hasPartialReplicaNCs
# then a partial replica at this dsa
@@ -231,11 +234,9 @@ class NCReplica(NamingContext):
# context type by calling the super class method
# of the same name
NamingContext.identify_by_dsa_attr(self, samdb, attr)
- return
def is_default(self):
- """Returns True if this is a default domain NC for the dsa
- that this NC appears on
+ """Whether this is a default domain for the dsa that this NC appears on
"""
return self.rep_default
@@ -249,10 +250,10 @@ class NCReplica(NamingContext):
def is_present(self):
"""Given an NC replica which has been discovered thru the
- nTDSDSA database object and populated with replica flags
- from the msDS-HasInstantiatedNCs; return whether the NC
- replica is present (true) or if the IT_NC_GOING flag is
- set then the NC replica is not present (false)
+ nTDSDSA database object and populated with replica flags
+ from the msDS-HasInstantiatedNCs; return whether the NC
+ replica is present (true) or if the IT_NC_GOING flag is
+ set then the NC replica is not present (false)
"""
if self.rep_present_criteria_one and \
self.rep_instantiated_flags & dsdb.INSTANCE_TYPE_NC_GOING == 0:
@@ -261,28 +262,26 @@ class NCReplica(NamingContext):
def load_repsFrom(self, samdb):
"""Given an NC replica which has been discovered thru the nTDSDSA
- database object, load the repsFrom attribute for the local replica.
- held by my dsa. The repsFrom attribute is not replicated so this
- attribute is relative only to the local DSA that the samdb exists on
+ database object, load the repsFrom attribute for the local replica.
+ held by my dsa. The repsFrom attribute is not replicated so this
+ attribute is relative only to the local DSA that the samdb exists on
"""
try:
res = samdb.search(base=self.nc_dnstr, scope=ldb.SCOPE_BASE,
attrs=[ "repsFrom" ])
except ldb.LdbError, (enum, estr):
- raise Exception("Unable to find NC for (%s) - (%s)" % \
+ raise Exception("Unable to find NC for (%s) - (%s)" %
(self.nc_dnstr, estr))
- return
msg = res[0]
# Possibly no repsFrom if this is a singleton DC
if "repsFrom" in msg:
for value in msg["repsFrom"]:
- rep = RepsFromTo(self.nc_dnstr, \
+ rep = RepsFromTo(self.nc_dnstr,
ndr_unpack(drsblobs.repsFromToBlob, value))
self.rep_repsFrom.append(rep)
- return
def commit_repsFrom(self, samdb):
"""Commit repsFrom to the database"""
@@ -297,7 +296,7 @@ class NCReplica(NamingContext):
# reflect the reference docs. As of right now this
# commit to the database will work as its what the
# older KCC also did
- modify = False
+ modify = False
newreps = []
for repsFrom in self.rep_repsFrom:
@@ -318,7 +317,7 @@ class NCReplica(NamingContext):
if modify == False:
return
- m = ldb.Message()
+ m = ldb.Message()
m.dn = ldb.Dn(samdb, self.nc_dnstr)
m["repsFrom"] = \
@@ -328,9 +327,8 @@ class NCReplica(NamingContext):
samdb.modify(m)
except ldb.LdbError, estr:
- raise Exception("Could not set repsFrom for (%s) - (%s)" % \
+ raise Exception("Could not set repsFrom for (%s) - (%s)" %
(self.dsa_dnstr, estr))
- return
def load_fsmo_roles(self, samdb):
# XXX - to be implemented
@@ -340,19 +338,22 @@ class NCReplica(NamingContext):
# XXX - to be implemented
return False
-class DirectoryServiceAgent:
+
+class DirectoryServiceAgent(object):
def __init__(self, dsa_dnstr):
- """Initialize DSA class. Class is subsequently
- fully populated by calling the load_dsa() method
- :param dsa_dnstr: DN of the nTDSDSA
+ """Initialize DSA class.
+
+ Class is subsequently fully populated by calling the load_dsa() method
+
+ :param dsa_dnstr: DN of the nTDSDSA
"""
- self.dsa_dnstr = dsa_dnstr
- self.dsa_guid = None
- self.dsa_ivid = None
- self.dsa_is_ro = False
- self.dsa_options = 0
- self.dsa_behavior = 0
+ self.dsa_dnstr = dsa_dnstr
+ self.dsa_guid = None
+ self.dsa_ivid = None
+ self.dsa_is_ro = False
+ self.dsa_options = 0
+ self.dsa_behavior = 0
self.default_dnstr = None # default domain dn string for dsa
# NCReplicas for this dsa that are "present"
@@ -368,8 +369,6 @@ class DirectoryServiceAgent:
# in the database. Indexed by DN string of connection
self.connect_table = {}
- return
-
def __str__(self):
'''Debug dump string output of class'''
@@ -407,19 +406,17 @@ class DirectoryServiceAgent:
return False
def is_minimum_behavior(self, version):
- """Is dsa at minimum windows level greater than or
- equal to (version)
- :param version: Windows version to test against
- (e.g. DS_BEHAVIOR_WIN2008)
+ """Is dsa at minimum windows level greater than or equal to (version)
+
+ :param version: Windows version to test against
+ (e.g. DS_BEHAVIOR_WIN2008)
"""
if self.dsa_behavior >= version:
return True
return False
def should_translate_ntdsconn(self):
- """Returns True if DSA object allows NTDSConnection
- translation in its options. False otherwise.
- """
+ """Whether this allows NTDSConnection translation in its options."""
if (self.options & dsdb.DS_NTDSDSA_OPT_DISABLE_NTDSCONN_XLATE) != 0:
return False
return True
@@ -430,37 +427,33 @@ class DirectoryServiceAgent:
return self.current_rep_table, self.needed_rep_table
def get_parent_dnstr(self):
- """Drop the leading portion of the DN string
- (e.g. CN=NTDS Settings,) which will give us
- the parent DN string of this object
- """
+ """Get the parent DN string of this object."""
head, sep, tail = self.dsa_dnstr.partition(',')
return tail
def load_dsa(self, samdb):
- """Method to load a DSA from the samdb. Prior initialization
- has given us the DN of the DSA that we are to load. This
- method initializes all other attributes, including loading
- the NC replica table for this DSA.
- Raises an Exception on error.
+ """Load a DSA from the samdb.
+
+ Prior initialization has given us the DN of the DSA that we are to
+ load. This method initializes all other attributes, including loading
+ the NC replica table for this DSA.
"""
controls = [ "extended_dn:1:1" ]
- attrs = [ "objectGUID",
- "invocationID",
- "options",
- "msDS-isRODC",
- "msDS-Behavior-Version" ]
+ attrs = ["objectGUID",
+ "invocationID",
+ "options",
+ "msDS-isRODC",
+ "msDS-Behavior-Version"]
try:
res = samdb.search(base=self.dsa_dnstr, scope=ldb.SCOPE_BASE,
attrs=attrs, controls=controls)
except ldb.LdbError, (enum, estr):
- raise Exception("Unable to find nTDSDSA for (%s) - (%s)" % \
+ raise Exception("Unable to find nTDSDSA for (%s) - (%s)" %
(self.dsa_dnstr, estr))
- return
msg = res[0]
- self.dsa_guid = misc.GUID(samdb.schema_format_value("objectGUID", \
+ self.dsa_guid = misc.GUID(samdb.schema_format_value("objectGUID",
msg["objectGUID"][0]))
# RODCs don't originate changes and thus have no invocationId,
@@ -486,19 +479,17 @@ class DirectoryServiceAgent:
# Load the nTDSConnection that are enumerated on this dsa
self.load_connection_table(samdb)
- return
-
-
def load_current_replica_table(self, samdb):
- """Method to load the NC replica's listed for DSA object. This
- method queries the samdb for (hasMasterNCs, msDS-hasMasterNCs,
- hasPartialReplicaNCs, msDS-HasDomainNCs, msDS-hasFullReplicaNCs,
- and msDS-HasInstantiatedNCs) to determine complete list of
- NC replicas that are enumerated for the DSA. Once a NC
- replica is loaded it is identified (schema, config, etc) and
- the other replica attributes (partial, ro, etc) are determined.
- Raises an Exception on error.
- :param samdb: database to query for DSA replica list
+ """Method to load the NC replica's listed for DSA object.
+
+ This method queries the samdb for (hasMasterNCs, msDS-hasMasterNCs,
+ hasPartialReplicaNCs, msDS-HasDomainNCs, msDS-hasFullReplicaNCs, and
+ msDS-HasInstantiatedNCs) to determine complete list of NC replicas that
+ are enumerated for the DSA. Once a NC replica is loaded it is
+ identified (schema, config, etc) and the other replica attributes
+ (partial, ro, etc) are determined.
+
+ :param samdb: database to query for DSA replica list
"""
controls = ["extended_dn:1:1"]
ncattrs = [ # not RODC - default, config, schema (old style)
@@ -518,9 +509,8 @@ class DirectoryServiceAgent:
attrs=ncattrs, controls=controls)
except ldb.LdbError, (enum, estr):
- raise Exception("Unable to find nTDSDSA NCs for (%s) - (%s)" % \
+ raise Exception("Unable to find nTDSDSA NCs for (%s) - (%s)" %
(self.dsa_dnstr, estr))
- return
# The table of NCs for the dsa we are searching
tmp_table = {}
@@ -546,17 +536,16 @@ class DirectoryServiceAgent:
# its methods to parse the extended pieces.
# Note we don't really need the exact sid value
# but instead only need to know if its present.
- dsdn = dsdb_Dn(samdb, value)
- guid = dsdn.dn.get_extended_component('GUID')
- sid = dsdn.dn.get_extended_component('SID')
+ dsdn = dsdb_Dn(samdb, value)
+ guid = dsdn.dn.get_extended_component('GUID')
+ sid = dsdn.dn.get_extended_component('SID')
flags = dsdn.get_binary_integer()
dnstr = str(dsdn.dn)
if guid is None:
- raise Exception("Missing GUID for (%s) - (%s: %s)" % \
+ raise Exception("Missing GUID for (%s) - (%s: %s)" %
(self.dsa_dnstr, k, value))
- else:
- guid = misc.GUID(guid)
+ guid = misc.GUID(guid)
if not dnstr in tmp_table:
rep = NCReplica(self.dsa_dnstr, self.dsa_guid,
@@ -577,11 +566,9 @@ class DirectoryServiceAgent:
self.default_dnstr = dnstr
else:
raise Exception("No nTDSDSA NCs for (%s)" % self.dsa_dnstr)
- return
# Assign our newly built NC replica table to this dsa
self.current_rep_table = tmp_table
- return
def add_needed_replica(self, rep):
"""Method to add a NC replica that "should be present" to the
@@ -590,12 +577,10 @@ class DirectoryServiceAgent:
if not rep.nc_dnstr in self.needed_rep_table.keys():
self.needed_rep_table[rep.nc_dnstr] = rep
- return
-
def load_connection_table(self, samdb):
"""Method to load the nTDSConnections listed for DSA object.
- Raises an Exception on error.
- :param samdb: database to query for DSA connection list
+
+ :param samdb: database to query for DSA connection list
"""
try:
res = samdb.search(base=self.dsa_dnstr,
@@ -603,9 +588,8 @@ class DirectoryServiceAgent:
expression="(objectClass=nTDSConnection)")
except ldb.LdbError, (enum, estr):
- raise Exception("Unable to find nTDSConnection for (%s) - (%s)" % \
+ raise Exception("Unable to find nTDSConnection for (%s) - (%s)" %
(self.dsa_dnstr, estr))
- return
for msg in res:
dnstr = str(msg.dn)
@@ -618,7 +602,6 @@ class DirectoryServiceAgent:
connect.load_connection(samdb)
self.connect_table[dnstr] = connect
- return
def commit_connection_table(self, samdb):
"""Method to commit any uncommitted nTDSConnections
@@ -631,7 +614,6 @@ class DirectoryServiceAgent:
def add_connection(self, dnstr, connect):
self.connect_table[dnstr] = connect
- return
def get_connection_by_from_dnstr(self, from_dnstr):
"""Scan DSA nTDSConnection table and return connection
@@ -674,21 +656,21 @@ class DirectoryServiceAgent:
text = "%s" % self.connect_table[k]
return text
-class NTDSConnection():
+
+class NTDSConnection(object):
"""Class defines a nTDSConnection found under a DSA
"""
def __init__(self, dnstr):
- self.dnstr = dnstr
- self.enabled = False
- self.committed = False # new connection needs to be committed
- self.options = 0
- self.flags = 0
+ self.dnstr = dnstr
+ self.enabled = False
+ self.committed = False # new connection needs to be committed
+ self.options = 0
+ self.flags = 0
self.transport_dnstr = None
- self.transport_guid = None
- self.from_dnstr = None
- self.from_guid = None
- self.schedule = None
- return
+ self.transport_guid = None
+ self.from_dnstr = None
+ self.from_guid = None
+ self.schedule = None
def __str__(self):
'''Debug dump string output of NTDSConnection object'''
@@ -728,7 +710,6 @@ class NTDSConnection():
"""Given a NTDSConnection object with an prior initialization
for the object's DN, search for the DN and load attributes
from the samdb.
- Raises an Exception on error.
"""
controls = ["extended_dn:1:1"]
attrs = [ "options",
@@ -742,9 +723,8 @@ class NTDSConnection():
attrs=attrs, controls=controls)
except ldb.LdbError, (enum, estr):
- raise Exception("Unable to find nTDSConnection for (%s) - (%s)" % \
+ raise Exception("Unable to find nTDSConnection for (%s) - (%s)" %
(self.dnstr, estr))
- return
msg = res[0]
@@ -780,7 +760,6 @@ class NTDSConnection():
# Was loaded from database so connection is currently committed
self.committed = True
- return
def commit_connection(self, samdb):
"""Given a NTDSConnection object that is not committed in the
@@ -800,7 +779,7 @@ class NTDSConnection():
if enum == ldb.ERR_NO_SUCH_OBJECT:
found = False
else:
- raise Exception("Unable to search for (%s) - (%s)" % \
+ raise Exception("Unable to search for (%s) - (%s)" %
(self.dnstr, estr))
if found:
raise Exception("nTDSConnection for (%s) already exists!" % self.dnstr)
@@ -811,7 +790,7 @@ class NTDSConnection():
enablestr = "FALSE"
# Prepare a message for adding to the samdb
- m = ldb.Message()
+ m = ldb.Message()
m.dn = ldb.Dn(samdb, self.dnstr)
m["objectClass"] = \
@@ -839,7 +818,6 @@ class NTDSConnection():
raise Exception("Could not add nTDSConnection for (%s) - (%s)" % \
(self.dnstr, estr))
self.committed = True
- return
def is_schedule_minimum_once_per_week(self):
"""Returns True if our schedule includes at least one
@@ -893,16 +871,16 @@ class NTDSConnection():
'''Return fromServer dn string attribute'''
return self.from_dnstr
+
class Partition(NamingContext):
- """Class defines a naming context discovered thru the
- Partitions DN of the configuration schema. This is
- a more specific form of NamingContext class (inheriting
- from that class) and it identifies unique attributes
- enumerated in the Partitions such as which nTDSDSAs
- are cross referenced for replicas
+ """A naming context discovered thru Partitions DN of the config schema.
+
+ This is a more specific form of NamingContext class (inheriting from that
+ class) and it identifies unique attributes enumerated in the Partitions
+ such as which nTDSDSAs are cross referenced for replicas
"""
def __init__(self, partstr):
- self.partstr = partstr
+ self.partstr = partstr
self.rw_location_list = []
self.ro_location_list = []
@@ -913,14 +891,13 @@ class Partition(NamingContext):
def load_partition(self, samdb):
- """Given a Partition class object that has been initialized
- with its partition dn string, load the partition from the
- sam database, identify the type of the partition (schema,
- domain, etc) and record the list of nTDSDSAs that appear
- in the cross reference attributes msDS-NC-Replica-Locations
- and msDS-NC-RO-Replica-Locations.
- Raises an Exception on error.
- :param samdb: sam database to load partition from
+ """Given a Partition class object that has been initialized with its
+ partition dn string, load the partition from the sam database, identify
+ the type of the partition (schema, domain, etc) and record the list of
+ nTDSDSAs that appear in the cross reference attributes
+ msDS-NC-Replica-Locations and msDS-NC-RO-Replica-Locations.
+
+ :param samdb: sam database to load partition from
"""
controls = ["extended_dn:1:1"]
attrs = [ "nCName",
@@ -933,7 +910,6 @@ class Partition(NamingContext):
except ldb.LdbError, (enum, estr):
raise Exception("Unable to find partition for (%s) - (%s)" % (
self.partstr, estr))
- return
msg = res[0]
for k in msg.keys():
@@ -945,20 +921,19 @@ class Partition(NamingContext):
# its methods to parse the extended pieces.
# Note we don't really need the exact sid value
# but instead only need to know if its present.
- dsdn = dsdb_Dn(samdb, value)
- guid = dsdn.dn.get_extended_component('GUID')
- sid = dsdn.dn.get_extended_component('SID')
+ dsdn = dsdb_Dn(samdb, value)
+ guid = dsdn.dn.get_extended_component('GUID')
+ sid = dsdn.dn.get_extended_component('SID')
if guid is None:
raise Exception("Missing GUID for (%s) - (%s: %s)" % \
(self.partstr, k, value))
- else:
- guid = misc.GUID(guid)
+ guid = misc.GUID(guid)
if k == "nCName":
self.nc_dnstr = str(dsdn.dn)
- self.nc_guid = guid
- self.nc_sid = sid
+ self.nc_guid = guid
+ self.nc_sid = sid
continue
if k == "msDS-NC-Replica-Locations":
@@ -973,16 +948,14 @@ class Partition(NamingContext):
# enumerated
self.identify_by_basedn(samdb)
- return
-
def should_be_present(self, target_dsa):
"""Tests whether this partition should have an NC replica
on the target dsa. This method returns a tuple of
needed=True/False, ro=True/False, partial=True/False
:param target_dsa: should NC be present on target dsa
"""
- needed = False
- ro = False
+ needed = False
+ ro = False
partial = False
# If this is the config, schema, or default
@@ -990,7 +963,7 @@ class Partition(NamingContext):
# be present
if self.nc_type == NCType.config or \
self.nc_type == NCType.schema or \
- (self.nc_type == NCType.domain and \
+ (self.nc_type == NCType.domain and
self.nc_dnstr == target_dsa.default_dnstr):
needed = True
@@ -1013,9 +986,9 @@ class Partition(NamingContext):
if target_dsa.is_gc() and \
self.nc_type == NCType.domain and \
self.nc_dnstr != target_dsa.default_dnstr and \
- (target_dsa.dsa_dnstr in self.ro_location_list or \
+ (target_dsa.dsa_dnstr in self.ro_location_list or
target_dsa.dsa_dnstr in self.rw_location_list):
- needed = True
+ needed = True
partial = True
# partial NCs are always readonly
@@ -1034,38 +1007,35 @@ class Partition(NamingContext):
text = text + "\n\tmsDS-NC-RO-Replica-Locations=%s" % k
return text
-class Site:
+
+class Site(object):
+
def __init__(self, site_dnstr):
- self.site_dnstr = site_dnstr
+ self.site_dnstr = site_dnstr
self.site_options = 0
- self.dsa_table = {}
- return
+ self.dsa_table = {}
def load_site(self, samdb):
"""Loads the NTDS Site Settions options attribute for the site
- Raises an Exception on error.
"""
ssdn = "CN=NTDS Site Settings,%s" % self.site_dnstr
try:
res = samdb.search(base=ssdn, scope=ldb.SCOPE_BASE,
attrs=["options"])
except ldb.LdbError, (enum, estr):
- raise Exception("Unable to find site settings for (%s) - (%s)" % \
+ raise Exception("Unable to find site settings for (%s) - (%s)" %
(ssdn, estr))
- return
msg = res[0]
if "options" in msg:
self.site_options = int(msg["options"][0])
self.load_all_dsa(samdb)
- return
def load_all_dsa(self, samdb):
"""Discover all nTDSDSA thru the sites entry and
instantiate and load the DSAs. Each dsa is inserted
into the dsa_table by dn string.
- Raises an Exception on error.
"""
try:
res = samdb.search(self.site_dnstr,
@@ -1088,7 +1058,6 @@ class Site:
# Assign this dsa to my dsa table
# and index by dsa dn
self.dsa_table[dnstr] = dsa
- return
def get_dsa_by_guidstr(self, guidstr):
for dsa in self.dsa_table.values():
@@ -1099,7 +1068,8 @@ class Site:
def get_dsa(self, dnstr):
"""Return a previously loaded DSA object by consulting
the sites dsa_table for the provided DSA dn string
- Returns None if DSA doesn't exist
+
+ :return: None if DSA doesn't exist
"""
if dnstr in self.dsa_table.keys():
return self.dsa_table[dnstr]
@@ -1107,14 +1077,14 @@ class Site:
def is_intrasite_topology_disabled(self):
'''Returns True if intrasite topology is disabled for site'''
- if (self.site_options & \
+ if (self.site_options &
dsdb.DS_NTDSSETTINGS_OPT_IS_AUTO_TOPOLOGY_DISABLED) != 0:
return True
return False
def should_detect_stale(self):
'''Returns True if detect stale is enabled for site'''
- if (self.site_options & \
+ if (self.site_options &
dsdb.DS_NTDSSETTINGS_OPT_IS_TOPL_DETECT_STALE_DISABLED) == 0:
return True
return False
@@ -1129,16 +1099,18 @@ class Site:
return text
-class GraphNode:
- """This is a graph node describing a set of edges that should be
- directed to it. Each edge is a connection for a particular
- naming context replica directed from another node in the forest
- to this node.
+class GraphNode(object):
+ """A graph node describing a set of edges that should be directed to it.
+
+ Each edge is a connection for a particular naming context replica directed
+ from another node in the forest to this node.
"""
+
def __init__(self, dsa_dnstr, max_node_edges):
"""Instantiate the graph node according to a DSA dn string
- :param max_node_edges: maximum number of edges that should ever
- be directed to the node
+
+ :param max_node_edges: maximum number of edges that should ever
+ be directed to the node
"""
self.max_edges = max_node_edges
self.dsa_dnstr = dsa_dnstr
@@ -1155,7 +1127,8 @@ class GraphNode:
def add_edge_from(self, from_dsa_dnstr):
"""Add an edge from the dsa to our graph nodes edge from list
- :param from_dsa_dnstr: the dsa that the edge emanates from
+
+ :param from_dsa_dnstr: the dsa that the edge emanates from
"""
assert from_dsa_dnstr is not None
@@ -1177,11 +1150,11 @@ class GraphNode:
the "fromServer" attribute). If it does then we add an
edge from the server unless we are over the max edges for this
graph node
- :param dsa: dsa with a dnstr equivalent to his graph node
+
+ :param dsa: dsa with a dnstr equivalent to his graph node
"""
for dnstr, connect in dsa.connect_table.items():
self.add_edge_from(connect.from_dnstr)
- return
def add_connections_from_edges(self, dsa):
"""For each edge directed to this graph node, ensure there
@@ -1216,11 +1189,11 @@ class GraphNode:
dnstr = "CN=%s," % str(uuid.uuid4()) + self.dsa_dnstr
connect = NTDSConnection(dnstr)
- connect.committed = False
- connect.enabled = True
- connect.from_dnstr = edge_dnstr
- connect.options = dsdb.NTDSCONN_OPT_IS_GENERATED
- connect.flags = dsdb.SYSTEM_FLAG_CONFIG_ALLOW_RENAME + \
+ connect.committed = False
+ connect.enabled = True
+ connect.from_dnstr = edge_dnstr
+ connect.options = dsdb.NTDSCONN_OPT_IS_GENERATED
+ connect.flags = dsdb.SYSTEM_FLAG_CONFIG_ALLOW_RENAME + \
dsdb.SYSTEM_FLAG_CONFIG_ALLOW_MOVE
# Create schedule. Attribute valuse set according to MS-TECH
@@ -1249,23 +1222,22 @@ class GraphNode:
dsa.add_connection(dnstr, connect);
- return
-
def has_sufficient_edges(self):
'''Return True if we have met the maximum "from edges" criteria'''
if len(self.edge_from) >= self.max_edges:
return True
return False
-class Transport():
+
+class Transport(object):
"""Class defines a Inter-site transport found under Sites
"""
+
def __init__(self, dnstr):
- self.dnstr = dnstr
- self.options = 0
- self.guid = None
- self.address_attr = None
- return
+ self.dnstr = dnstr
+ self.options = 0
+ self.guid = None
+ self.address_attr = None
def __str__(self):
'''Debug dump string output of Transport object'''
@@ -1281,7 +1253,6 @@ class Transport():
"""Given a Transport object with an prior initialization
for the object's DN, search for the DN and load attributes
from the samdb.
- Raises an Exception on error.
"""
attrs = [ "objectGUID",
"options",
@@ -1291,9 +1262,8 @@ class Transport():
attrs=attrs)
except ldb.LdbError, (enum, estr):
- raise Exception("Unable to find Transport for (%s) - (%s)" % \
+ raise Exception("Unable to find Transport for (%s) - (%s)" %
(self.dnstr, estr))
- return
msg = res[0]
self.guid = misc.GUID(samdb.schema_format_value("objectGUID",
@@ -1304,19 +1274,19 @@ class Transport():
if "transportAddressAttribute" in msg:
self.address_attr = str(msg["transportAddressAttribute"][0])
- return
-class RepsFromTo:
+class RepsFromTo(object):
"""Class encapsulation of the NDR repsFromToBlob.
- Removes the necessity of external code having to
- understand about other_info or manipulation of
- update flags.
+
+ Removes the necessity of external code having to
+ understand about other_info or manipulation of
+ update flags.
"""
def __init__(self, nc_dnstr=None, ndr_blob=None):
self.__dict__['to_be_deleted'] = False
- self.__dict__['nc_dnstr'] = nc_dnstr
- self.__dict__['update_flags'] = 0x0
+ self.__dict__['nc_dnstr'] = nc_dnstr
+ self.__dict__['update_flags'] = 0x0
# WARNING:
#
@@ -1339,25 +1309,24 @@ class RepsFromTo:
# it is necessary to hold a proper python GC reference
# count.
if ndr_blob is None:
- self.__dict__['ndr_blob'] = drsblobs.repsFromToBlob()
+ self.__dict__['ndr_blob'] = drsblobs.repsFromToBlob()
self.__dict__['ndr_blob'].version = 0x1
- self.__dict__['dns_name1'] = None
- self.__dict__['dns_name2'] = None
+ self.__dict__['dns_name1'] = None
+ self.__dict__['dns_name2'] = None
self.__dict__['ndr_blob'].ctr.other_info = \
self.__dict__['other_info'] = drsblobs.repsFromTo1OtherInfo()
else:
- self.__dict__['ndr_blob'] = ndr_blob
+ self.__dict__['ndr_blob'] = ndr_blob
self.__dict__['other_info'] = ndr_blob.ctr.other_info
if ndr_blob.version == 0x1:
- self.__dict__['dns_name1'] = ndr_blob.ctr.other_info.dns_name
- self.__dict__['dns_name2'] = None
+ self.__dict__['dns_name1'] = ndr_blob.ctr.other_info.dns_name
+ self.__dict__['dns_name2'] = None
else:
- self.__dict__['dns_name1'] = ndr_blob.ctr.other_info.dns_name1
- self.__dict__['dns_name2'] = ndr_blob.ctr.other_info.dns_name2
- return
+ self.__dict__['dns_name1'] = ndr_blob.ctr.other_info.dns_name1
+ self.__dict__['dns_name2'] = ndr_blob.ctr.other_info.dns_name2
def __str__(self):
'''Debug dump string output of class'''
@@ -1394,9 +1363,9 @@ class RepsFromTo:
def __setattr__(self, item, value):
- if item in [ 'schedule', 'replica_flags', 'transport_guid', \
- 'source_dsa_obj_guid', 'source_dsa_invocation_id', \
- 'consecutive_sync_failures', 'last_success', \
+ if item in [ 'schedule', 'replica_flags', 'transport_guid',
+ 'source_dsa_obj_guid', 'source_dsa_invocation_id',
+ 'consecutive_sync_failures', 'last_success',
'last_attempt' ]:
setattr(self.__dict__['ndr_blob'].ctr, item, value)
@@ -1431,15 +1400,14 @@ class RepsFromTo:
else:
self.__dict__['update_flags'] |= drsuapi.DRSUAPI_DRS_UPDATE_ADDRESS
- return
-
def __getattr__(self, item):
- """Overload of RepsFromTo attribute retrieval. Allows
- external code to ignore substructures within the blob
+ """Overload of RepsFromTo attribute retrieval.
+
+ Allows external code to ignore substructures within the blob
"""
- if item in [ 'schedule', 'replica_flags', 'transport_guid', \
- 'source_dsa_obj_guid', 'source_dsa_invocation_id', \
- 'consecutive_sync_failures', 'last_success', \
+ if item in [ 'schedule', 'replica_flags', 'transport_guid',
+ 'source_dsa_obj_guid', 'source_dsa_invocation_id',
+ 'consecutive_sync_failures', 'last_success',
'last_attempt' ]:
return getattr(self.__dict__['ndr_blob'].ctr, item)