[SCM] Samba Shared Repository - branch master updated

Kamen Mazdrashki kamenim at samba.org
Wed Feb 9 03:46:02 MST 2011


The branch, master has been updated
       via  4d058ca s4/tests: Implement a blackbox test for 'samba-tool drs' command
       via  099644f s4/tests: Move command line processing into separate method to be reused
       via  6b15746 s4/tests: Implement BlackboxTestCase.check_output() method
       via  d0867e5 s4/samba-tool/drs: Make use of Command.message() method instead of using 'print'
       via  ad48c70 s4/samba-tool/drs: Move get_dsServiceName function at module level to be re-used
       via  f3db67e s4/samba-tool: 'drs options' command implementation
      from  6c89bb8 waf Remove debugging hacks left in the top level build

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 4d058ca7c043e7d28385bec21c9e1d7575895625
Author: Kamen Mazdrashki <kamenim at samba.org>
Date:   Wed Feb 9 03:40:52 2011 +0200

    s4/tests: Implement a blackbox test for 'samba-tool drs' command
    
    Autobuild-User: Kamen Mazdrashki <kamenim at samba.org>
    Autobuild-Date: Wed Feb  9 11:45:30 CET 2011 on sn-devel-104

commit 099644f0a7d16d865a39cfab069ab762dc26377f
Author: Kamen Mazdrashki <kamenim at samba.org>
Date:   Wed Feb 9 03:40:17 2011 +0200

    s4/tests: Move command line processing into separate method to be reused

commit 6b1574636a8493d043795b7f397657846a637f28
Author: Kamen Mazdrashki <kamenim at samba.org>
Date:   Wed Feb 9 03:01:16 2011 +0200

    s4/tests: Implement BlackboxTestCase.check_output() method
    
    I am going to need this to check if output is OK (kind of)

commit d0867e5c6c164fdd927a7e961d60287a8bd7e9f5
Author: Kamen Mazdrashki <kamenim at samba.org>
Date:   Wed Feb 9 03:00:06 2011 +0200

    s4/samba-tool/drs: Make use of Command.message() method instead of using 'print'

commit ad48c70db61a5e35a85a317c4c0f4a179a2aae77
Author: Kamen Mazdrashki <kamenim at samba.org>
Date:   Mon Feb 7 14:13:06 2011 +0200

    s4/samba-tool/drs: Move get_dsServiceName function at module level to be re-used

commit f3db67e14fd9ebcf5720e82b125d2939fdc2ac17
Author: Kamen Mazdrashki <kamenim at samba.org>
Date:   Fri Feb 4 04:14:13 2011 +0200

    s4/samba-tool: 'drs options' command implementation
    
    Current implementation handle only one flag change per call

-----------------------------------------------------------------------

Summary of changes:
 source4/scripting/python/samba/netcmd/drs.py       |  152 ++++++++++++++------
 source4/scripting/python/samba/tests/__init__.py   |   13 ++-
 .../python/samba/tests/blackbox/samba_tool_drs.py  |  100 +++++++++++++
 source4/selftest/tests.py                          |    1 +
 4 files changed, 223 insertions(+), 43 deletions(-)
 create mode 100644 source4/scripting/python/samba/tests/blackbox/samba_tool_drs.py


Changeset truncated at 500 lines:

diff --git a/source4/scripting/python/samba/netcmd/drs.py b/source4/scripting/python/samba/netcmd/drs.py
index 740bd20..7dea9de 100644
--- a/source4/scripting/python/samba/netcmd/drs.py
+++ b/source4/scripting/python/samba/netcmd/drs.py
@@ -83,6 +83,12 @@ def drs_parse_ntds_dn(ntds_dn):
     return (site, server)
 
 
+def get_dsServiceName(samdb):
+    '''get the NTDS DN from the rootDSE'''
+    res = samdb.search(base="", scope=ldb.SCOPE_BASE, attrs=["dsServiceName"])
+    return res[0]["dsServiceName"][0]
+
+
 class cmd_drs_showrepl(Command):
     """show replication status"""
 
@@ -98,22 +104,18 @@ class cmd_drs_showrepl(Command):
 
     def print_neighbour(self, n):
         '''print one set of neighbour information'''
-        print("%s" % n.naming_context_dn)
+        self.message("%s" % n.naming_context_dn)
         try:
             (site, server) = drs_parse_ntds_dn(n.source_dsa_obj_dn)
-            print("\t%s\%s via RPC" % (site, server))
+            self.message("\t%s\%s via RPC" % (site, server))
         except RuntimeError:
-            print("\tNTDS DN: %s" % n.source_dsa_obj_dn)
-        print("\t\tDSA object GUID: %s" % n.source_dsa_obj_guid)
-        print("\t\tLast attempt @ %s %s" % (nttime2string(n.last_attempt), drs_errmsg(n.result_last_attempt)))
-        print("\t\t%u consecutive failure(s)." % n.consecutive_sync_failures)
-        print("\t\tLast success @ %s" % nttime2string(n.last_success))
-        print("")
-
-    def get_dsServiceName(ctx):
-        '''get the NTDS DN from the rootDSE'''
-        res = ctx.samdb.search(base="", scope=ldb.SCOPE_BASE, attrs=["dsServiceName"])
-        return res[0]["dsServiceName"][0]
+            self.message("\tNTDS DN: %s" % n.source_dsa_obj_dn)
+        self.message("\t\tDSA object GUID: %s" % n.source_dsa_obj_guid)
+        self.message("\t\tLast attempt @ %s %s" % (nttime2string(n.last_attempt),
+                                                   drs_errmsg(n.result_last_attempt)))
+        self.message("\t\t%u consecutive failure(s)." % n.consecutive_sync_failures)
+        self.message("\t\tLast success @ %s" % nttime2string(n.last_success))
+        self.message("")
 
     def drsuapi_ReplicaInfo(ctx, info_type):
         '''call a DsReplicaInfo'''
@@ -140,7 +142,7 @@ class cmd_drs_showrepl(Command):
         samdb_connect(self)
 
         # show domain information
-        ntds_dn = self.get_dsServiceName()
+        ntds_dn = get_dsServiceName(self.samdb)
         server_dns = self.samdb.search(base="", scope=ldb.SCOPE_BASE, attrs=["dnsHostName"])[0]['dnsHostName'][0]
 
         (site, server) = drs_parse_ntds_dn(ntds_dn)
@@ -150,18 +152,18 @@ class cmd_drs_showrepl(Command):
             raise CommandError("Failed to search NTDS DN %s" % ntds_dn)
         conn = self.samdb.search(base=ntds_dn, expression="(objectClass=nTDSConnection)")
 
-        print("%s\\%s" % (site, server))
-        print("DSA Options: 0x%08x" % int(attr_default(ntds[0], "options", 0)))
-        print("DSA object GUID: %s" % self.samdb.schema_format_value("objectGUID", ntds[0]["objectGUID"][0]))
-        print("DSA invocationId: %s\n" % self.samdb.schema_format_value("objectGUID", ntds[0]["invocationId"][0]))
+        self.message("%s\\%s" % (site, server))
+        self.message("DSA Options: 0x%08x" % int(attr_default(ntds[0], "options", 0)))
+        self.message("DSA object GUID: %s" % self.samdb.schema_format_value("objectGUID", ntds[0]["objectGUID"][0]))
+        self.message("DSA invocationId: %s\n" % self.samdb.schema_format_value("objectGUID", ntds[0]["invocationId"][0]))
 
-        print("==== INBOUND NEIGHBORS ====\n")
+        self.message("==== INBOUND NEIGHBORS ====\n")
         (info_type, info) = self.drsuapi_ReplicaInfo(drsuapi.DRSUAPI_DS_REPLICA_INFO_NEIGHBORS)
         for n in info.array:
             self.print_neighbour(n)
 
 
-        print("==== OUTBOUND NEIGHBORS ====\n")
+        self.message("==== OUTBOUND NEIGHBORS ====\n")
         (info_type, info) = self.drsuapi_ReplicaInfo(drsuapi.DRSUAPI_DS_REPLICA_INFO_REPSTO)
         for n in info.array:
             self.print_neighbour(n)
@@ -177,25 +179,25 @@ class cmd_drs_showrepl(Command):
                    'NTDSCONN_KCC_SITE_FAILOVER_TOPOLOGY',
                    'NTDSCONN_KCC_REDUNDANT_SERVER_TOPOLOGY']
 
-        print("==== KCC CONNECTION OBJECTS ====\n")
+        self.message("==== KCC CONNECTION OBJECTS ====\n")
         for c in conn:
-            print("Connection --")
-            print("\tConnection name: %s" % c['name'][0])
-            print("\tEnabled        : %s" % attr_default(c, 'enabledConnection', 'TRUE'))
-            print("\tServer DNS name : %s" % server_dns)
-            print("\tServer DN name  : %s" % c['fromServer'][0])
-            print("\t\tTransportType: RPC")
-            print("\t\toptions: 0x%08X" % int(attr_default(c, 'options', 0)))
+            self.message("Connection --")
+            self.message("\tConnection name: %s" % c['name'][0])
+            self.message("\tEnabled        : %s" % attr_default(c, 'enabledConnection', 'TRUE'))
+            self.message("\tServer DNS name : %s" % server_dns)
+            self.message("\tServer DN name  : %s" % c['fromServer'][0])
+            self.message("\t\tTransportType: RPC")
+            self.message("\t\toptions: 0x%08X" % int(attr_default(c, 'options', 0)))
             if not 'mS-DS-ReplicatesNCReason' in c:
-                print("Warning: No NC replicated for Connection!")
+                self.message("Warning: No NC replicated for Connection!")
                 continue
             for r in c['mS-DS-ReplicatesNCReason']:
                 a = str(r).split(':')
-                print("\t\tReplicatesNC: %s" % a[3])
-                print("\t\tReason: 0x%08x" % int(a[2]))
+                self.message("\t\tReplicatesNC: %s" % a[3])
+                self.message("\t\tReason: 0x%08x" % int(a[2]))
                 for s in reasons:
                     if getattr(dsdb, s, 0) & int(a[2]):
-                        print("\t\t\t%s" % s)
+                        self.message("\t\t\t%s" % s)
 
 
 class cmd_drs_kcc(Command):
@@ -228,7 +230,7 @@ class cmd_drs_kcc(Command):
             self.drsuapi.DsExecuteKCC(self.drsuapi_handle, 1, req1)
         except Exception, e:
             raise CommandError("DsExecuteKCC failed", e)
-        print("Consistency check on %s successful." % DC)
+        self.message("Consistency check on %s successful." % DC)
 
 
 
@@ -297,7 +299,7 @@ class cmd_drs_replicate(Command):
             self.drsuapi.DsReplicaSync(self.drsuapi_handle, 1, req1)
         except Exception, estr:
             raise CommandError("DsReplicaSync failed", estr)
-	print("Replicate from %s to %s was successful." % (SOURCE_DC, DEST_DC))
+        self.message("Replicate from %s to %s was successful." % (SOURCE_DC, DEST_DC))
 
 
 
@@ -373,30 +375,95 @@ class cmd_drs_bind(Command):
             ("DRSUAPI_SUPPORTED_EXTENSION_LH_BETA2",			"DRS_EXT_LH_BETA2"),
             ("DRSUAPI_SUPPORTED_EXTENSION_RECYCLE_BIN",			"DRS_EXT_RECYCLE_BIN")]
 
-        print("Bind to %s succeeded." % DC)
-        print("Extensions supported:")
+        self.message("Bind to %s succeeded." % DC)
+        self.message("Extensions supported:")
         for (opt, str) in optmap:
             optval = getattr(drsuapi, opt, 0)
             if info.info.supported_extensions & optval:
                 yesno = "Yes"
             else:
                 yesno = "No "
-            print("  %-60s: %s (%s)" % (opt, yesno, str))
+            self.message("  %-60s: %s (%s)" % (opt, yesno, str))
 
         if isinstance(info.info, drsuapi.DsBindInfo48):
-            print("\nExtended Extensions supported:")
+            self.message("\nExtended Extensions supported:")
             for (opt, str) in optmap_ext:
                 optval = getattr(drsuapi, opt, 0)
                 if info.info.supported_extensions_ext & optval:
                     yesno = "Yes"
                 else:
                     yesno = "No "
-                print("  %-60s: %s (%s)" % (opt, yesno, str))
+                self.message("  %-60s: %s (%s)" % (opt, yesno, str))
 
-        print("\nSite GUID: %s" % info.info.site_guid)
-        print("Repl epoch: %u" % info.info.repl_epoch)
+        self.message("\nSite GUID: %s" % info.info.site_guid)
+        self.message("Repl epoch: %u" % info.info.repl_epoch)
         if isinstance(info.info, drsuapi.DsBindInfo48):
-            print("Forest GUID: %s" % info.info.config_dn_guid)
+            self.message("Forest GUID: %s" % info.info.config_dn_guid)
+
+
+
+class cmd_drs_options(Command):
+    """query or change 'options' for NTDS Settings object of a domain controller"""
+
+    synopsis = ("%prog drs options <DC>"
+                " [--dsa-option={+|-}IS_GC | {+|-}DISABLE_INBOUND_REPL"
+                " |{+|-}DISABLE_OUTBOUND_REPL | {+|-}DISABLE_NTDSCONN_XLATE]")
+
+    takes_optiongroups = {
+        "sambaopts": options.SambaOptions,
+        "versionopts": options.VersionOptions,
+        "credopts": options.CredentialsOptions,
+    }
+
+    takes_args = ["DC"]
+
+    takes_options = [
+        Option("--dsa-option", help="DSA option to enable/disable", type="str"),
+        ]
+
+    option_map = {"IS_GC": 0x00000001,
+                  "DISABLE_INBOUND_REPL": 0x00000002,
+                  "DISABLE_OUTBOUND_REPL": 0x00000004,
+                  "DISABLE_NTDSCONN_XLATE": 0x00000008}
+
+    def run(self, DC, dsa_option=None,
+            sambaopts=None, credopts=None, versionopts=None):
+
+        self.lp = sambaopts.get_loadparm()
+        if DC is None:
+            DC = common.netcmd_dnsname(self.lp)
+        self.server = DC
+        self.creds = credopts.get_credentials(self.lp, fallback_machine=True)
+
+        samdb_connect(self)
+
+        ntds_dn = get_dsServiceName(self.samdb)
+        res = self.samdb.search(base=ntds_dn, scope=ldb.SCOPE_BASE, attrs=["options"])
+        dsa_opts = int(res[0]["options"][0])
+
+        # print out current DSA options
+        cur_opts = [x for x in self.option_map if self.option_map[x] & dsa_opts]
+        self.message("Current DSA options: " + ", ".join(cur_opts))
+
+        # modify options
+        if dsa_option:
+            if dsa_option[:1] not in ("+", "-"):
+                raise CommandError("Unknown option %s" % dsa_option)
+            flag = dsa_option[1:]
+            if flag not in self.option_map.keys():
+                raise CommandError("Unknown option %s" % dsa_option)
+            if dsa_option[:1] == "+":
+                dsa_opts |= self.option_map[flag]
+            else:
+                dsa_opts &= ~self.option_map[flag]
+            #save new options
+            m = ldb.Message()
+            m.dn = ldb.Dn(self.samdb, ntds_dn)
+            m["options"]= ldb.MessageElement(str(dsa_opts), ldb.FLAG_MOD_REPLACE, "options")
+            self.samdb.modify(m)
+            # print out new DSA options
+            cur_opts = [x for x in self.option_map if self.option_map[x] & dsa_opts]
+            self.message("New DSA options: " + ", ".join(cur_opts))
 
 
 class cmd_drs(SuperCommand):
@@ -407,3 +474,4 @@ class cmd_drs(SuperCommand):
     subcommands["kcc"] = cmd_drs_kcc()
     subcommands["replicate"] = cmd_drs_replicate()
     subcommands["showrepl"] = cmd_drs_showrepl()
+    subcommands["options"] = cmd_drs_options()
diff --git a/source4/scripting/python/samba/tests/__init__.py b/source4/scripting/python/samba/tests/__init__.py
index d0362ef..d6b962c 100644
--- a/source4/scripting/python/samba/tests/__init__.py
+++ b/source4/scripting/python/samba/tests/__init__.py
@@ -124,14 +124,25 @@ class ValidNetbiosNameTests(TestCase):
 class BlackboxTestCase(TestCase):
     """Base test case for blackbox tests."""
 
-    def check_run(self, line):
+    def _make_cmdline(self, line):
         bindir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../../bin"))
         parts = line.split(" ")
         if os.path.exists(os.path.join(bindir, parts[0])):
             parts[0] = os.path.join(bindir, parts[0])
         line = " ".join(parts)
+        return line
+
+    def check_run(self, line):
+        line = self._make_cmdline(line)
         subprocess.check_call(line, shell=True)
 
+    def check_output(self, line):
+        line = self._make_cmdline(line)
+        p = subprocess.Popen(line, stdout=subprocess.PIPE, shell=True, close_fds=True)
+        retcode = p.wait()
+        if retcode:
+            raise subprocess.CalledProcessError(retcode, line)
+        return p.stdout.read()
 
 def connect_samdb(samdb_url, lp=None, session_info=None, credentials=None,
                   flags=0, ldb_options=None, ldap_only=False):
diff --git a/source4/scripting/python/samba/tests/blackbox/samba_tool_drs.py b/source4/scripting/python/samba/tests/blackbox/samba_tool_drs.py
new file mode 100644
index 0000000..51274cc
--- /dev/null
+++ b/source4/scripting/python/samba/tests/blackbox/samba_tool_drs.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+
+# Blackbox tests for "samba-tool drs" command
+# Copyright (C) Kamen Mazdrashki <kamenim at samba.org> 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
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+"""Blackbox tests for samba-tool drs."""
+
+import os
+import samba.tests
+
+
+class SambaToolDrsTests(samba.tests.BlackboxTestCase):
+    """Blackbox test case for samba-tool drs."""
+
+    def setUp(self):
+        super(SambaToolDrsTests, self).setUp()
+
+        self.dc1 = samba.tests.env_get_var_value("DC1")
+        self.dc2 = samba.tests.env_get_var_value("DC2")
+
+        creds = self.get_credentials()
+        self.cmdline_creds = "-U%s/%s%%%s" % (creds.get_domain(),
+                                              creds.get_username(), creds.get_password())
+
+    def _get_rootDSE(self, dc):
+        samdb = samba.tests.connect_samdb(dc, lp=self.get_loadparm(),
+                                          credentials=self.get_credentials(),
+                                          ldap_only=True)
+        return samdb.search(base="", scope=samba.tests.ldb.SCOPE_BASE)[0]
+
+    def test_samba_tool_bind(self):
+        """Tests 'samba-tool drs bind' command
+           Output should be like:
+               Extensions supported:
+                 <list-of-supported-extensions>
+               Site GUID: <GUID>
+               Repl epoch: 0"""
+        out = self.check_output("samba-tool drs bind %s %s" % (self.dc1,
+                                                               self.cmdline_creds))
+        self.assertTrue("Site GUID:" in out)
+        self.assertTrue("Repl epoch:" in out)
+
+    def test_samba_tool_kcc(self):
+        """Tests 'samba-tool drs kcc' command
+           Output should be like 'Consistency check on <DC> successful.'"""
+        out = self.check_output("samba-tool drs kcc %s %s" % (self.dc1,
+                                                              self.cmdline_creds))
+        self.assertTrue("Consistency check on" in out)
+        self.assertTrue("successful" in out)
+
+    def test_samba_tool_showrepl(self):
+        """Tests 'samba-tool drs showrepl' command
+           Output should be like:
+               <site-name>/<domain-name>
+               DSA Options: <hex-options>
+               DSA object GUID: <DSA-object-GUID>
+               DSA invocationId: <DSA-invocationId>
+               <Inbound-connections-list>
+               <Outbound-connections-list>
+               <KCC-objects>
+               ...
+            TODO: Perhaps we should check at least for
+                  DSA's objectGUDI and invocationId"""
+        out = self.check_output("samba-tool drs showrepl %s %s" % (self.dc1,
+                                                                   self.cmdline_creds))
+        self.assertTrue("DSA Options:" in out)
+        self.assertTrue("DSA object GUID:" in out)
+        self.assertTrue("DSA invocationId:" in out)
+
+    def test_samba_tool_options(self):
+        """Tests 'samba-tool drs options' command
+           Output should be like 'Current DSA options: IS_GC <OTHER_FLAGS>'"""
+        out = self.check_output("samba-tool drs options %s %s" % (self.dc1,
+                                                                  self.cmdline_creds))
+        self.assertTrue("Current DSA options:" in out)
+
+    def test_samba_tool_replicate(self):
+        """Tests 'samba-tool drs replicate' command
+           Output should be like 'Replicate from <DC-SRC> to <DC-DEST> was successful.'"""
+        nc_name = self._get_rootDSE(self.dc1)["defaultNamingContext"]
+        out = self.check_output("samba-tool drs replicate %s %s %s %s" % (self.dc1,
+                                                                          self.dc2,
+                                                                          nc_name,
+                                                                          self.cmdline_creds))
+        self.assertTrue("Replicate from" in out)
+        self.assertTrue("was successful" in out)
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index 33524e6..aa7ee5a 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -536,6 +536,7 @@ plantestsuite("samba4.blackbox.spn.py(dc:local)", "dc:local", ["PYTHON=%s" % pyt
 plantestsuite("samba4.ldap.bind(dc)", "dc", [python, os.path.join(samba4srcdir, "auth/credentials/tests/bind.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"'])
 
 # DRS python tests
+plansambapythontestsuite("samba4.blackbox.samba-tool.drs(vampire_dc)", "vampire_dc", os.path.join(samba4srcdir, 'scripting/python'), "samba.tests.blackbox.samba_tool_drs", environ={'DC1': '$DC_SERVER', 'DC2': '$VAMPIRE_DC_SERVER'}, extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD'])
 plansambapythontestsuite("samba4.drs.delete_object.python(vampire_dc)", "vampire_dc", os.path.join(samba4srcdir, 'torture/drs/python'), "delete_object", environ={'DC1': '$DC_SERVER', 'DC2': '$VAMPIRE_DC_SERVER'}, extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD'])
 plansambapythontestsuite("samba4.drs.fsmo.python(vampire_dc)", "vampire_dc", os.path.join(samba4srcdir, 'torture/drs/python'), "fsmo", environ={'DC1': "$DC_SERVER", 'DC2': "$VAMPIRE_DC_SERVER"}, extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD'])
 plansambapythontestsuite("samba4.drs.repl_schema.python(vampire_dc)", "vampire_dc", os.path.join(samba4srcdir, 'torture/drs/python'), "repl_schema", environ={'DC1': "$DC_SERVER", 'DC2': '$VAMPIRE_DC_SERVER'}, extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD'])


-- 
Samba Shared Repository


More information about the samba-cvs mailing list