The branch, master has been updated via eb5cdce samba-tool: Support preloading multiple users via bd51778 python: Allow optional multi-value arguements for samba-tool commands from 873df9a s3: VFS: Modify mkdir to take a const struct smb_filename * instead of const char *
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit eb5cdce2470f5e77df534902d8f1dc7baf8195d4 Author: Andrew Bartlett <abart...@samba.org> Date: Wed Feb 24 16:39:38 2016 +1300 samba-tool: Support preloading multiple users Based on patches by Adrian Cochrane Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Thu Feb 25 07:58:55 CET 2016 on sn-devel-144 commit bd51778dc0241c169c0eea7aa52ac21341d7900d Author: Andrew Bartlett <abart...@samba.org> Date: Thu Feb 25 12:42:09 2016 +1300 python: Allow optional multi-value arguements for samba-tool commands Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Garming Sam <garm...@catalyst.net.nz> ----------------------------------------------------------------------- Summary of changes: python/samba/netcmd/__init__.py | 5 +- python/samba/netcmd/rodc.py | 59 ++++++++++++++-------- python/samba/tests/samba_tool/rodc.py | 94 +++++++++++++++++++++++++++++++++++ source4/selftest/tests.py | 2 + 4 files changed, 136 insertions(+), 24 deletions(-) create mode 100644 python/samba/tests/samba_tool/rodc.py Changeset truncated at 500 lines: diff --git a/python/samba/netcmd/__init__.py b/python/samba/netcmd/__init__.py index a3edf50..1debae8 100644 --- a/python/samba/netcmd/__init__.py +++ b/python/samba/netcmd/__init__.py @@ -153,13 +153,14 @@ class Command(object): # Check for a min a max number of allowed arguments, whenever possible # The suffix "?" means zero or one occurence # The suffix "+" means at least one occurence + # The suffix "*" means zero or more occurences min_args = 0 max_args = 0 undetermined_max_args = False for i, arg in enumerate(self.takes_args): - if arg[-1] != "?": + if arg[-1] != "?" and arg[-1] != "*": min_args += 1 - if arg[-1] == "+": + if arg[-1] == "+" or arg[-1] == "*": undetermined_max_args = True else: max_args += 1 diff --git a/python/samba/netcmd/rodc.py b/python/samba/netcmd/rodc.py index 4404b7b..ba29c74 100644 --- a/python/samba/netcmd/rodc.py +++ b/python/samba/netcmd/rodc.py @@ -23,12 +23,12 @@ from samba.auth import system_session import ldb from samba.dcerpc import misc, drsuapi from samba.drs_utils import drs_Replicate - +import sys class cmd_rodc_preload(Command): - """Preload one account for an RODC.""" + """Preload accounts for an RODC. Multiple accounts may be requested.""" - synopsis = "%prog (<SID>|<DN>|<accountname>) [options]" + synopsis = "%prog (<SID>|<DN>|<accountname>)+ ... [options]" takes_optiongroups = { "sambaopts": options.SambaOptions, @@ -38,9 +38,10 @@ class cmd_rodc_preload(Command): takes_options = [ Option("--server", help="DC to use", type=str), + Option("--file", help="Read account list from a file, or - for stdin (one per line)", type=str), ] - takes_args = ["account"] + takes_args = ["account*"] def get_dn(self, samdb, account): '''work out what DN they meant''' @@ -62,12 +63,25 @@ class cmd_rodc_preload(Command): return str(res[0]["dn"]) - def run(self, account, sambaopts=None, - credopts=None, versionopts=None, server=None): + def run(self, *accounts, **kwargs): + sambaopts = kwargs.get("sambaopts") + credopts = kwargs.get("credopts") + versionpts = kwargs.get("versionopts") + server = kwargs.get("server") + accounts_file = kwargs.get("file") if server is None: raise Exception("You must supply a server") + if accounts_file is not None: + accounts = [] + if accounts_file == "-": + for line in sys.stdin: + accounts.append(line.strip()) + else: + for line in open(accounts_file, 'r'): + accounts.append(line.strip()) + lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp, fallback_machine=True) @@ -80,26 +94,27 @@ class cmd_rodc_preload(Command): local_samdb = SamDB(url=None, session_info=system_session(), credentials=creds, lp=lp) - # work out the source and destination GUIDs - dc_ntds_dn = samdb.get_dsServiceName() - res = samdb.search(base=dc_ntds_dn, scope=ldb.SCOPE_BASE, attrs=["invocationId"]) - source_dsa_invocation_id = misc.GUID(local_samdb.schema_format_value("objectGUID", res[0]["invocationId"][0])) - - dn = self.get_dn(samdb, account) - self.outf.write("Replicating DN %s\n" % dn) - destination_dsa_guid = misc.GUID(local_samdb.get_ntds_GUID()) - local_samdb.transaction_start() repl = drs_Replicate("ncacn_ip_tcp:%s[seal,print]" % server, lp, creds, local_samdb, destination_dsa_guid) - try: - repl.replicate(dn, source_dsa_invocation_id, destination_dsa_guid, - exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True) - except Exception, e: - local_samdb.transaction_cancel() - raise CommandError("Error replicating DN %s" % dn, e) - local_samdb.transaction_commit() + for account in accounts: + # work out the source and destination GUIDs + dc_ntds_dn = samdb.get_dsServiceName() + res = samdb.search(base=dc_ntds_dn, scope=ldb.SCOPE_BASE, attrs=["invocationId"]) + source_dsa_invocation_id = misc.GUID(local_samdb.schema_format_value("objectGUID", res[0]["invocationId"][0])) + + dn = self.get_dn(samdb, account) + self.outf.write("Replicating DN %s\n" % dn) + + local_samdb.transaction_start() + try: + repl.replicate(dn, source_dsa_invocation_id, destination_dsa_guid, + exop=drsuapi.DRSUAPI_EXOP_REPL_SECRET, rodc=True) + except Exception, e: + local_samdb.transaction_cancel() + raise CommandError("Error replicating DN %s" % dn, e) + local_samdb.transaction_commit() diff --git a/python/samba/tests/samba_tool/rodc.py b/python/samba/tests/samba_tool/rodc.py new file mode 100644 index 0000000..9ae5dd1 --- /dev/null +++ b/python/samba/tests/samba_tool/rodc.py @@ -0,0 +1,94 @@ +# Unix SMB/CIFS implementation. +# Copyright (C) Catalyst IT Ltd. 2015 +# +# 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/>. +# + +import os +import ldb +import samba +from samba.samdb import SamDB +from samba.tests import delete_force +from samba.tests.samba_tool.base import SambaToolCmdTest +from samba.credentials import Credentials +from samba.auth import system_session + +class RodcCmdTestCase(SambaToolCmdTest): + def setUp(self): + super(RodcCmdTestCase, self).setUp() + self.lp = samba.param.LoadParm() + self.lp.load(os.environ["SMB_CONF_PATH"]) + self.creds = Credentials() + self.creds.set_username(os.environ["DC_USERNAME"]) + self.creds.set_password(os.environ["DC_PASSWORD"]) + self.creds.guess(self.lp) + self.session = system_session() + self.ldb = SamDB("ldap://" + os.environ["DC_SERVER"], + session_info=self.session, credentials=self.creds,lp=self.lp) + + self.base_dn = self.ldb.domain_dn() + + self.ldb.newuser("sambatool1", "1qazXSW@") + self.ldb.newuser("sambatool2", "2wsxCDE#") + self.ldb.newuser("sambatool3", "3edcVFR$") + self.ldb.newuser("sambatool4", "4rfvBGT%") + + self.ldb.add_remove_group_members("Allowed RODC Password Replication Group", + ["sambatool1", "sambatool2", "sambatool3", + "sambatool4"], + add_members_operation=True) + + def tearDown(self): + super(RodcCmdTestCase, self).tearDown() + self.ldb.deleteuser("sambatool1") + self.ldb.deleteuser("sambatool2") + self.ldb.deleteuser("sambatool3") + self.ldb.deleteuser("sambatool4") + (result, out, err) = self.runsubcmd("drs", "replicate", "--local", "unused", + os.environ["DC_SERVER"], self.base_dn) + + + def test_single_by_account_name(self): + (result, out, err) = self.runsubcmd("rodc", "preload", "sambatool1", + "--server", os.environ["DC_SERVER"]) + self.assertCmdSuccess(result, "ensuring rodc prefetch ran successfully") + self.assertEqual(out, "Replicating DN CN=sambatool1,CN=Users,%s\n" % self.base_dn) + self.assertEqual(err, "") + + def test_single_by_dn(self): + (result, out, err) = self.runsubcmd("rodc", "preload", "cn=sambatool2,cn=users,%s" % self.base_dn, + "--server", os.environ["DC_SERVER"]) + self.assertCmdSuccess(result, "ensuring rodc prefetch ran successfully") + self.assertEqual(out, "Replicating DN CN=sambatool2,CN=Users,%s\n" % self.base_dn) + + def test_multi_by_account_name(self): + (result, out, err) = self.runsubcmd("rodc", "preload", "sambatool1", "sambatool2", + "--server", os.environ["DC_SERVER"]) + self.assertCmdSuccess(result, "ensuring rodc prefetch ran successfully") + self.assertEqual(out, "Replicating DN CN=sambatool1,CN=Users,%s\nReplicating DN CN=sambatool2,CN=Users,%s\n" % (self.base_dn, self.base_dn)) + + def test_multi_by_dn(self): + (result, out, err) = self.runsubcmd("rodc", "preload", "cn=sambatool3,cn=users,%s" % self.base_dn, "cn=sambatool4,cn=users,%s" % self.base_dn, + "--server", os.environ["DC_SERVER"]) + self.assertCmdSuccess(result, "ensuring rodc prefetch ran successfully") + self.assertEqual(out, "Replicating DN CN=sambatool3,CN=Users,%s\nReplicating DN CN=sambatool4,CN=Users,%s\n" % (self.base_dn, self.base_dn)) + + def test_multi_in_file(self): + tempf = os.path.join(self.tempdir, "accountlist") + open(tempf, 'w').write("sambatool1\nsambatool2") + (result, out, err) = self.runsubcmd("rodc", "preload", "--file", tempf, + "--server", os.environ["DC_SERVER"]) + self.assertCmdSuccess(result, "ensuring rodc prefetch ran successfully") + self.assertEqual(out, "Replicating DN CN=sambatool1,CN=Users,%s\nReplicating DN CN=sambatool2,CN=Users,%s\n" % (self.base_dn, self.base_dn)) + os.unlink(tempf) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index d76eda6..32d47a0 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -544,6 +544,8 @@ plansmbtorture4testsuite(t, "vampire_dc", ['$SERVER', '-U$USERNAME%$PASSWORD', ' for env in ['rodc']: plansmbtorture4testsuite('rpc.echo', env, ['ncacn_np:$SERVER', "-k", "yes", '-U$USERNAME%$PASSWORD', '--workgroup=$DOMAIN'], modname="samba4.rpc.echo") plansmbtorture4testsuite('rpc.echo', "%s:local" % env, ['ncacn_np:$SERVER', "-k", "yes", '-P', '--workgroup=$DOMAIN'], modname="samba4.rpc.echo") +planpythontestsuite("rodc:local", "samba.tests.samba_tool.rodc") + plantestsuite("samba4.blackbox.provision-backend", "none", ["PYTHON=%s" % python, os.path.join(samba4srcdir, "setup/tests/blackbox_provision-backend.sh"), '$PREFIX/provision']) # Test renaming the DC -- Samba Shared Repository