[SCM] Samba Shared Repository - branch master updated
Andrew Tridgell
tridge at samba.org
Fri Jan 13 23:46:02 MST 2012
The branch, master has been updated
via ab1f896 KCC importldif/exportldif and intersite topology
via aff8dad Intersite KCC flags for python
via 11e2c84 Intersite KCC flags
from b8a8870 idl: add to_null property
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit ab1f896c5152dfd10609ac146eaaecd1bd2d5b70
Author: Dave Craft <wimberosa at gmail.com>
Date: Wed Jan 11 08:11:35 2012 -0600
KCC importldif/exportldif and intersite topology
Add options for extracting an LDIF file from a database
and reimporting the LDIF into a schema-less database for
subsequent topology test/debug. Add intersite topology
generation with computation of ISTG and bridgehead servers
Signed-off-by: Andrew Tridgell <tridge at samba.org>
Autobuild-User: Andrew Tridgell <tridge at samba.org>
Autobuild-Date: Sat Jan 14 07:45:11 CET 2012 on sn-devel-104
commit aff8dad076f803e6deb2c5b59fa3bc5cb7ca7bd7
Author: Dave Craft <wimberosa at gmail.com>
Date: Wed Jan 11 08:10:27 2012 -0600
Intersite KCC flags for python
Add NTDSSITELINK options to dsdb class for use
in python samba_kcc
Signed-off-by: Andrew Tridgell <tridge at samba.org>
commit 11e2c8493f08214c290fec87dac18ad23de234bf
Author: Dave Craft <wimberosa at gmail.com>
Date: Wed Jan 11 08:08:52 2012 -0600
Intersite KCC flags
NTDSSITELINK option flags added
Signed-off-by: Andrew Tridgell <tridge at samba.org>
-----------------------------------------------------------------------
Summary of changes:
libds/common/flags.h | 5 +
source4/dsdb/pydsdb.c | 5 +
source4/scripting/bin/samba_kcc | 1629 ++++++++++++++++++++++++---
source4/scripting/python/samba/kcc_utils.py | 1176 ++++++++++++++++----
4 files changed, 2439 insertions(+), 376 deletions(-)
Changeset truncated at 500 lines:
diff --git a/libds/common/flags.h b/libds/common/flags.h
index c25a9e9..96709af 100644
--- a/libds/common/flags.h
+++ b/libds/common/flags.h
@@ -268,3 +268,8 @@
#define NTDSCONN_OPT_DISABLE_INTERSITE_COMPRESSION 0x00000010
#define NTDSCONN_OPT_USER_OWNED_SCHEDULE 0x00000020
#define NTDSCONN_OPT_RODC_TOPOLOGY 0x00000040
+
+/* 7.1.1.2.2.3.3 Site Link Object options flags */
+#define NTDSSITELINK_OPT_USE_NOTIFY 0x00000001
+#define NTDSSITELINK_OPT_TWOWAY_SYNC 0x00000002
+#define NTDSSITELINK_OPT_DISABLE_COMPRESSION 0x00000004
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index f9896c0..616e169 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -1186,6 +1186,11 @@ void initdsdb(void)
ADD_DSDB_FLAG(NTDSCONN_OPT_USER_OWNED_SCHEDULE);
ADD_DSDB_FLAG(NTDSCONN_OPT_RODC_TOPOLOGY);
+ /* Site Link Object options */
+ ADD_DSDB_FLAG(NTDSSITELINK_OPT_USE_NOTIFY);
+ ADD_DSDB_FLAG(NTDSSITELINK_OPT_TWOWAY_SYNC);
+ ADD_DSDB_FLAG(NTDSSITELINK_OPT_DISABLE_COMPRESSION);
+
/* GPO policy flags */
ADD_DSDB_FLAG(GPLINK_OPT_DISABLE);
ADD_DSDB_FLAG(GPLINK_OPT_ENFORCE);
diff --git a/source4/scripting/bin/samba_kcc b/source4/scripting/bin/samba_kcc
index c17439e..583d88f 100755
--- a/source4/scripting/bin/samba_kcc
+++ b/source4/scripting/bin/samba_kcc
@@ -18,6 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
+import tempfile
import sys
import random
import copy
@@ -35,11 +36,15 @@ os.environ["TZ"] = "GMT"
# Find right directory when running from source tree
sys.path.insert(0, "bin/python")
-import samba, ldb
import optparse
import logging
-from samba import getopt as options
+from samba import (getopt as options, \
+ Ldb, \
+ ldb, \
+ dsdb, \
+ param, \
+ read_and_sub_file)
from samba.auth import system_session
from samba.samdb import SamDB
from samba.dcerpc import drsuapi
@@ -47,19 +52,25 @@ from samba.kcc_utils import *
class KCC:
"""The Knowledge Consistency Checker class. A container for
- objects and methods allowing a run of the KCC. Produces
- a set of connections in the samdb for which the Distributed
- Replication Service can then utilize to replicate naming
- contexts
+ objects and methods allowing a run of the KCC. Produces
+ a set of connections in the samdb for which the Distributed
+ Replication Service can then utilize to replicate naming
+ contexts
"""
- def __init__(self, samdb):
+ def __init__(self):
"""Initializes the partitions class which can hold
- our local DCs partitions or all the partitions in
- the forest
+ our local DCs partitions or all the partitions in
+ the forest
"""
self.part_table = {} # partition objects
self.site_table = {}
self.transport_table = {}
+ self.sitelink_table = {}
+
+ # Used in inter-site topology computation. A list
+ # of connections (by NTDSConnection object) that are
+ # to be kept when pruning un-needed NTDS Connections
+ self.keep_connection_list = []
self.my_dsa_dnstr = None # My dsa DN
self.my_dsa = None # My dsa object
@@ -67,18 +78,19 @@ class KCC:
self.my_site_dnstr = None
self.my_site = None
- self.samdb = samdb
+ self.samdb = None
return
def load_all_transports(self):
"""Loads the inter-site transport objects for Sites
- Raises an Exception on error
+
+ ::returns: Raises an Exception on error
"""
try:
- res = samdb.search("CN=Inter-Site Transports,CN=Sites,%s" % \
- samdb.get_config_basedn(),
- scope=ldb.SCOPE_SUBTREE,
- expression="(objectClass=interSiteTransport)")
+ res = self.samdb.search("CN=Inter-Site Transports,CN=Sites,%s" % \
+ self.samdb.get_config_basedn(),
+ scope=ldb.SCOPE_SUBTREE,
+ expression="(objectClass=interSiteTransport)")
except ldb.LdbError, (enum, estr):
raise Exception("Unable to find inter-site transports - (%s)" % estr)
@@ -91,7 +103,7 @@ class KCC:
transport = Transport(dnstr)
- transport.load_transport(samdb)
+ transport.load_transport(self.samdb)
# Assign this transport to table
# and index by dn
@@ -99,27 +111,96 @@ class KCC:
return
+ def load_all_sitelinks(self):
+ """Loads the inter-site siteLink objects
+
+ ::returns: Raises an Exception on error
+ """
+ try:
+ res = self.samdb.search("CN=Inter-Site Transports,CN=Sites,%s" % \
+ self.samdb.get_config_basedn(),
+ scope=ldb.SCOPE_SUBTREE,
+ expression="(objectClass=siteLink)")
+ except ldb.LdbError, (enum, estr):
+ raise Exception("Unable to find inter-site siteLinks - (%s)" % estr)
+
+ for msg in res:
+ dnstr = str(msg.dn)
+
+ # already loaded
+ if dnstr in self.sitelink_table.keys():
+ continue
+
+ sitelink = SiteLink(dnstr)
+
+ sitelink.load_sitelink(self.samdb)
+
+ # Assign this siteLink to table
+ # and index by dn
+ self.sitelink_table[dnstr] = sitelink
+
+ return
+
+ def get_sitelink(self, site1_dnstr, site2_dnstr):
+ """Return the siteLink (if it exists) that connects the
+ two input site DNs
+ """
+ for sitelink in self.sitelink_table.values():
+ if sitelink.is_sitelink(site1_dnstr, site2_dnstr):
+ return sitelink
+ return None
+
def load_my_site(self):
"""Loads the Site class for the local DSA
- Raises an Exception on error
+
+ ::returns: Raises an Exception on error
"""
- self.my_site_dnstr = "CN=%s,CN=Sites,%s" % (samdb.server_site_name(),
- samdb.get_config_basedn())
+ self.my_site_dnstr = "CN=%s,CN=Sites,%s" % \
+ (self.samdb.server_site_name(),
+ self.samdb.get_config_basedn())
site = Site(self.my_site_dnstr)
- site.load_site(samdb)
+ site.load_site(self.samdb)
self.site_table[self.my_site_dnstr] = site
self.my_site = site
return
+ def load_all_sites(self):
+ """Discover all sites and instantiate and load each
+ NTDS Site settings.
+
+ ::returns: Raises an Exception on error
+ """
+ try:
+ res = self.samdb.search("CN=Sites,%s" %
+ self.samdb.get_config_basedn(),
+ scope=ldb.SCOPE_SUBTREE,
+ expression="(objectClass=site)")
+ except ldb.LdbError, (enum, estr):
+ raise Exception("Unable to find sites - (%s)" % estr)
+
+ for msg in res:
+ sitestr = str(msg.dn)
+
+ # already loaded
+ if sitestr in self.site_table.keys():
+ continue
+
+ site = Site(sitestr)
+ site.load_site(self.samdb)
+
+ self.site_table[sitestr] = site
+ return
+
def load_my_dsa(self):
"""Discover my nTDSDSA dn thru the rootDSE entry
- Raises an Exception on error.
+
+ ::returns: Raises an Exception on error.
"""
dn = ldb.Dn(self.samdb, "")
try:
- res = samdb.search(base=dn, scope=ldb.SCOPE_BASE,
- attrs=["dsServiceName"])
+ res = self.samdb.search(base=dn, scope=ldb.SCOPE_BASE,
+ attrs=["dsServiceName"])
except ldb.LdbError, (enum, estr):
raise Exception("Unable to find my nTDSDSA - (%s)" % estr)
@@ -130,10 +211,12 @@ class KCC:
def load_all_partitions(self):
"""Discover all NCs thru the Partitions dn and
- instantiate and load the NCs. Each NC is inserted
- into the part_table by partition dn string (not
- the nCName dn string)
- Raises an Exception on error
+ instantiate and load the NCs.
+
+ Each NC is inserted into the part_table by partition
+ dn string (not the nCName dn string)
+
+ ::returns: Raises an Exception on error
"""
try:
res = self.samdb.search("CN=Partitions,%s" %
@@ -157,7 +240,7 @@ class KCC:
def should_be_present_test(self):
"""Enumerate all loaded partitions and DSAs in local
- site and test if NC should be present as replica
+ site and test if NC should be present as replica
"""
for partdn, part in self.part_table.items():
for dsadn, dsa in self.my_site.dsa_table.items():
@@ -172,9 +255,9 @@ class KCC:
def is_stale_link_connection(self, target_dsa):
"""Returns False if no tuple z exists in the kCCFailedLinks or
- kCCFailedConnections variables such that z.UUIDDsa is the
- objectGUID of the target dsa, z.FailureCount > 0, and
- the current time - z.TimeFirstFailure > 2 hours.
+ kCCFailedConnections variables such that z.UUIDDsa is the
+ objectGUID of the target dsa, z.FailureCount > 0, and
+ the current time - z.TimeFirstFailure > 2 hours.
"""
# XXX - not implemented yet
return False
@@ -183,13 +266,147 @@ class KCC:
# XXX - not implemented yet
return
- def remove_unneeded_ntdsconn(self):
- # XXX - not implemented yet
+ def remove_unneeded_ntdsconn(self, all_connected):
+ """Removes unneeded NTDS Connections after computation
+ of KCC intra and inter-site topology has finished.
+ """
+ mydsa = self.my_dsa
+
+ # Loop thru connections
+ for cn_dnstr, cn_conn in mydsa.connect_table.items():
+
+ s_dnstr = cn_conn.get_from_dnstr()
+ if s_dnstr is None:
+ cn_conn.to_be_deleted = True
+ continue
+
+ # Get the source DSA no matter what site
+ s_dsa = self.get_dsa(s_dnstr)
+
+ # Check if the DSA is in our site
+ if self.my_site.same_site(s_dsa):
+ same_site = True
+ else:
+ same_site = False
+
+ # Given an nTDSConnection object cn, if the DC with the
+ # nTDSDSA object dc that is the parent object of cn and
+ # the DC with the nTDSDA object referenced by cn!fromServer
+ # are in the same site, the KCC on dc deletes cn if all of
+ # the following are true:
+ #
+ # Bit NTDSCONN_OPT_IS_GENERATED is clear in cn!options.
+ #
+ # No site settings object s exists for the local DC's site, or
+ # bit NTDSSETTINGS_OPT_IS_TOPL_CLEANUP_DISABLED is clear in
+ # s!options.
+ #
+ # Another nTDSConnection object cn2 exists such that cn and
+ # cn2 have the same parent object, cn!fromServer = cn2!fromServer,
+ # and either
+ #
+ # cn!whenCreated < cn2!whenCreated
+ #
+ # cn!whenCreated = cn2!whenCreated and
+ # cn!objectGUID < cn2!objectGUID
+ #
+ # Bit NTDSCONN_OPT_RODC_TOPOLOGY is clear in cn!options
+ if same_site:
+ if cn_conn.is_generated() == False:
+ continue
+
+ if self.my_site.is_cleanup_ntdsconn_disabled() == True:
+ continue
+
+ # Loop thru connections looking for a duplicate that
+ # fulfills the previous criteria
+ lesser = False
+
+ for cn2_dnstr, cn2_conn in mydsa.connect_table.items():
+ if cn2_conn is cn_conn:
+ continue
+
+ s2_dnstr = cn2_conn.get_from_dnstr()
+ if s2_dnstr is None:
+ continue
+
+ # If the NTDS Connections has a different
+ # fromServer field then no match
+ if s2_dnstr != s_dnstr:
+ continue
+
+ lesser = (cn_conn.whenCreated < cn2_conn.whenCreated or
+ (cn_conn.whenCreated == cn2_conn.whenCreated and
+ cmp(cn_conn.guid, cn2_conn.guid) < 0))
+
+ if lesser == True:
+ break
+
+ if lesser and cn_conn.is_rodc_topology() == False:
+ cn_conn.to_be_deleted = True
+
+ # Given an nTDSConnection object cn, if the DC with the nTDSDSA
+ # object dc that is the parent object of cn and the DC with
+ # the nTDSDSA object referenced by cn!fromServer are in
+ # different sites, a KCC acting as an ISTG in dc's site
+ # deletes cn if all of the following are true:
+ #
+ # Bit NTDSCONN_OPT_IS_GENERATED is clear in cn!options.
+ #
+ # cn!fromServer references an nTDSDSA object for a DC
+ # in a site other than the local DC's site.
+ #
+ # The keepConnections sequence returned by
+ # CreateIntersiteConnections() does not contain
+ # cn!objectGUID, or cn is "superseded by" (see below)
+ # another nTDSConnection cn2 and keepConnections
+ # contains cn2!objectGUID.
+ #
+ # The return value of CreateIntersiteConnections()
+ # was true.
+ #
+ # Bit NTDSCONN_OPT_RODC_TOPOLOGY is clear in
+ # cn!options
+ #
+ else: # different site
+
+ if mydsa.is_istg() == False:
+ continue
+
+ if cn_conn.is_generated() == False:
+ continue
+
+ if self.keep_connection(cn_conn) == True:
+ continue
+
+ # XXX - To be implemented
+
+ if all_connected == False:
+ continue
+
+ if cn_conn.is_rodc_topology() == False:
+ cn_conn.to_be_deleted = True
+
+
+ if opts.readonly:
+ for dnstr, connect in mydsa.connect_table.items():
+ if connect.to_be_deleted == True:
+ logger.info("TO BE DELETED:\n%s" % connect)
+ if connect.to_be_added == True:
+ logger.info("TO BE ADDED:\n%s" % connect)
+
+ # Peform deletion from our tables but perform
+ # no database modification
+ mydsa.commit_connections(self.samdb, ro=True)
+ else:
+ # Commit any modified connections
+ mydsa.commit_connections(self.samdb)
+
return
def get_dsa_by_guidstr(self, guidstr):
"""Given a DSA guid string, consule all sites looking
- for the corresponding DSA and return it.
+ for the corresponding DSA and return it.
"""
for site in self.site_table.values():
dsa = site.get_dsa_by_guidstr(guidstr)
@@ -199,7 +416,7 @@ class KCC:
def get_dsa(self, dnstr):
"""Given a DSA dn string, consule all sites looking
- for the corresponding DSA and return it.
+ for the corresponding DSA and return it.
"""
for site in self.site_table.values():
dsa = site.get_dsa(dnstr)
@@ -209,16 +426,18 @@ class KCC:
def modify_repsFrom(self, n_rep, t_repsFrom, s_rep, s_dsa, cn_conn):
"""Update t_repsFrom if necessary to satisfy requirements. Such
- updates are typically required when the IDL_DRSGetNCChanges
- server has moved from one site to another--for example, to
- enable compression when the server is moved from the
- client's site to another site.
- :param n_rep: NC replica we need
- :param t_repsFrom: repsFrom tuple to modify
- :param s_rep: NC replica at source DSA
- :param s_dsa: source DSA
- :param cn_conn: Local DSA NTDSConnection child
- Returns (update) bit field containing which portion of the
+ updates are typically required when the IDL_DRSGetNCChanges
+ server has moved from one site to another--for example, to
+ enable compression when the server is moved from the
+ client's site to another site.
+
+ :param n_rep: NC replica we need
+ :param t_repsFrom: repsFrom tuple to modify
+ :param s_rep: NC replica at source DSA
+ :param s_dsa: source DSA
+ :param cn_conn: Local DSA NTDSConnection child
+
+ ::returns: (update) bit field containing which portion of the
repsFrom was modified. This bit field is suitable as input
to IDL_DRSReplicaModify ulModifyFields element, as it consists
of these bits:
@@ -229,7 +448,7 @@ class KCC:
s_dnstr = s_dsa.dsa_dnstr
update = 0x0
- if self.my_site.get_dsa(s_dnstr) is s_dsa:
+ if self.my_site.same_site(s_dsa):
same_site = True
else:
same_site = False
@@ -424,7 +643,7 @@ class KCC:
t_repsFrom.transport_guid = x_transport.guid
# See (NOTE MS-TECH INCORRECT) above
- if x_transport.addr_attr == "dNSHostName":
+ if x_transport.address_attr == "dNSHostName":
if t_repsFrom.version == 0x1:
if t_repsFrom.dns_name1 is None or \
@@ -440,21 +659,21 @@ class KCC:
else:
# MS tech specification says we retrieve the named
- # attribute in "addr_attr" from the parent of the
- # DSA object
+ # attribute in "transportAddressAttribute" from the parent of
+ # the DSA object
try:
pdnstr = s_dsa.get_parent_dnstr()
- attrs = [ x_transport.addr_attr ]
+ attrs = [ x_transport.address_attr ]
res = self.samdb.search(base=pdnstr, scope=ldb.SCOPE_BASE,
attrs=attrs)
except ldb.ldbError, (enum, estr):
raise Exception \
("Unable to find attr (%s) for (%s) - (%s)" % \
- (x_transport.addr_attr, pdnstr, estr))
+ (x_transport.address_attr, pdnstr, estr))
msg = res[0]
- nastr = str(msg[x_transport.addr_attr][0])
--
Samba Shared Repository
More information about the samba-cvs
mailing list