From 5a57378d342e690c8736877fb481ef34b27d4ea4 Mon Sep 17 00:00:00 2001 From: Tim Beale Date: Thu, 25 Oct 2018 09:03:53 +1300 Subject: [PATCH] netcmd: Add backend-store option to domain backup/rename cmds Currently the online/rename backup files always use the default backend (TDB) and there is no way to change this. This patch adds the backend-store option to the backup commands so that you can create a backup with an MDB backend, if needed. Signed-off-by: Tim Beale Reviewed-by: Douglas Bagnall --- python/samba/join.py | 18 +++++++++++------- python/samba/netcmd/domain_backup.py | 24 +++++++++++++++++------- python/samba/tests/domain_backup.py | 21 +++++++++++++++++++++ 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/python/samba/join.py b/python/samba/join.py index 01636fe3840..321b8c2b4b3 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -1539,11 +1539,12 @@ def join_DC(logger=None, server=None, creds=None, lp=None, site=None, netbios_na def join_clone(logger=None, server=None, creds=None, lp=None, targetdir=None, domain=None, include_secrets=False, - dns_backend="NONE"): + dns_backend="NONE", backend_store=None): """Creates a local clone of a remote DC.""" ctx = DCCloneContext(logger, server, creds, lp, targetdir=targetdir, domain=domain, dns_backend=dns_backend, - include_secrets=include_secrets) + include_secrets=include_secrets, + backend_store=backend_store) lp.set("workgroup", ctx.domain_name) logger.info("workgroup is %s" % ctx.domain_name) @@ -1616,10 +1617,11 @@ class DCCloneContext(DCJoinContext): def __init__(ctx, logger=None, server=None, creds=None, lp=None, targetdir=None, domain=None, dns_backend=None, - include_secrets=False): + include_secrets=False, backend_store=None): super(DCCloneContext, ctx).__init__(logger, server, creds, lp, targetdir=targetdir, domain=domain, - dns_backend=dns_backend) + dns_backend=dns_backend, + backend_store=backend_store) # As we don't want to create or delete these DNs, we set them to None ctx.server_dn = None @@ -1669,12 +1671,13 @@ class DCCloneAndRenameContext(DCCloneContext): def __init__(ctx, new_base_dn, new_domain_name, new_realm, logger=None, server=None, creds=None, lp=None, targetdir=None, domain=None, - dns_backend=None, include_secrets=True): + dns_backend=None, include_secrets=True, backend_store=None): super(DCCloneAndRenameContext, ctx).__init__(logger, server, creds, lp, targetdir=targetdir, domain=domain, dns_backend=dns_backend, - include_secrets=include_secrets) + include_secrets=include_secrets, + backend_store=backend_store) # store the new DN (etc) that we want the cloned DB to use ctx.new_base_dn = new_base_dn ctx.new_domain_name = new_domain_name @@ -1741,7 +1744,8 @@ class DCCloneAndRenameContext(DCCloneContext): configdn=ctx.rename_dn(ctx.config_dn), domain=ctx.new_domain_name, domainsid=ctx.domsid, serverrole="active directory domain controller", - dns_backend=ctx.dns_backend) + dns_backend=ctx.dns_backend, + backend_store=ctx.backend_store) print("Provision OK for renamed domain DN %s" % presult.domaindn) ctx.local_samdb = presult.samdb diff --git a/python/samba/netcmd/domain_backup.py b/python/samba/netcmd/domain_backup.py index c4f20456943..8b8ecda0696 100644 --- a/python/samba/netcmd/domain_backup.py +++ b/python/samba/netcmd/domain_backup.py @@ -25,7 +25,7 @@ import tempfile import samba import tdb import samba.getopt as options -from samba.samdb import SamDB +from samba.samdb import SamDB, get_default_backend_store import ldb from samba import smb from samba.ntacls import backup_online, backup_restore, backup_offline @@ -207,11 +207,15 @@ class cmd_domain_backup_online(samba.netcmd.Command): Option("--targetdir", type=str, help="Directory to write the backup file to"), Option("--no-secrets", action="store_true", default=False, - help="Exclude secret values from the backup created") + help="Exclude secret values from the backup created"), + Option("--backend-store", type="choice", metavar="BACKENDSTORE", + choices=["tdb", "mdb"], + help="Specify the database backend to be used " + "(default is %s)" % get_default_backend_store()), ] def run(self, sambaopts=None, credopts=None, server=None, targetdir=None, - no_secrets=False): + no_secrets=False, backend_store=None): logger = self.get_logger() logger.setLevel(logging.DEBUG) @@ -230,7 +234,8 @@ class cmd_domain_backup_online(samba.netcmd.Command): include_secrets = not no_secrets ctx = join_clone(logger=logger, creds=creds, lp=lp, include_secrets=include_secrets, server=server, - dns_backend='SAMBA_INTERNAL', targetdir=tmpdir) + dns_backend='SAMBA_INTERNAL', targetdir=tmpdir, + backend_store=backend_store) # get the paths used for the clone, then drop the old samdb connection paths = ctx.paths @@ -607,7 +612,11 @@ class cmd_domain_backup_rename(samba.netcmd.Command): Option("--keep-dns-realm", action="store_true", default=False, help="Retain the DNS entries for the old realm in the backup"), Option("--no-secrets", action="store_true", default=False, - help="Exclude secret values from the backup created") + help="Exclude secret values from the backup created"), + Option("--backend-store", type="choice", metavar="BACKENDSTORE", + choices=["tdb", "mdb"], + help="Specify the database backend to be used " + "(default is %s)" % get_default_backend_store()), ] takes_args = ["new_domain_name", "new_dns_realm"] @@ -705,7 +714,7 @@ class cmd_domain_backup_rename(samba.netcmd.Command): def run(self, new_domain_name, new_dns_realm, sambaopts=None, credopts=None, server=None, targetdir=None, keep_dns_realm=False, - no_secrets=False): + no_secrets=False, backend_store=None): logger = self.get_logger() logger.setLevel(logging.INFO) @@ -737,7 +746,8 @@ class cmd_domain_backup_rename(samba.netcmd.Command): creds=creds, lp=lp, include_secrets=include_secrets, dns_backend='SAMBA_INTERNAL', - server=server, targetdir=tmpdir) + server=server, targetdir=tmpdir, + backend_store=backend_store) # sanity-check we're not "renaming" the domain to the same values old_domain = ctx.domain_name diff --git a/python/samba/tests/domain_backup.py b/python/samba/tests/domain_backup.py index 98863db5565..320ff1f89b3 100644 --- a/python/samba/tests/domain_backup.py +++ b/python/samba/tests/domain_backup.py @@ -57,6 +57,12 @@ class DomainBackupBase(SambaToolCmdTest, TestCaseInTempDir): self.backup_markers = ['sidForRestore', 'backupDate'] self.restore_domain = os.environ["DOMAIN"] self.restore_realm = os.environ["REALM"] + self.backend = None + + def use_backend(self, backend): + """Explicitly set the DB backend that the backup should use""" + self.backend = backend + self.base_cmd += ["--backend-store=" + backend] def assert_partitions_present(self, samdb): """Asserts all expected partitions are present in the backup samdb""" @@ -278,6 +284,13 @@ class DomainBackupBase(SambaToolCmdTest, TestCaseInTempDir): self.assertIsNone(res[0].get('repsFrom')) self.assertIsNone(res[0].get('repsTo')) + # check the DB is using the backend we supplied + if self.backend: + res = samdb.search(base="@PARTITION", scope=ldb.SCOPE_BASE, + attrs=["backendStore"]) + backend = str(res[0].get("backendStore")) + self.assertEqual(backend, self.backend) + # check the restored DB has the expected partitions/DC/FSMO roles self.assert_partitions_present(samdb) self.assert_dcs_present(samdb, self.new_server, expected_count=1) @@ -391,15 +404,19 @@ class DomainBackupOnline(DomainBackupBase): self._test_backup_untar() def test_backup_restore(self): + self.use_backend("tdb") self._test_backup_restore() def test_backup_restore_with_conf(self): + self.use_backend("mdb") self._test_backup_restore_with_conf() def test_backup_restore_no_secrets(self): + self.use_backend("tdb") self._test_backup_restore_no_secrets() def test_backup_restore_into_site(self): + self.use_backend("mdb") self._test_backup_restore_into_site() @@ -422,15 +439,19 @@ class DomainBackupRename(DomainBackupBase): self._test_backup_untar() def test_backup_restore(self): + self.use_backend("mdb") self._test_backup_restore() def test_backup_restore_with_conf(self): + self.use_backend("tdb") self._test_backup_restore_with_conf() def test_backup_restore_no_secrets(self): + self.use_backend("mdb") self._test_backup_restore_no_secrets() def test_backup_restore_into_site(self): + self.use_backend("tdb") self._test_backup_restore_into_site() def test_backup_invalid_args(self): -- 2.47.2