6762e885d1353d350fe36b46fdad9b30dd81e292
[samba.git] / python / samba / tests / domain_backup_offline.py
1 # Unix SMB/CIFS implementation.
2 # Copyright (C) Andrew Bartlett <abartlet@samba.org>
3 #
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 #
17
18 import tarfile
19 import os
20 import shutil
21 import tempfile
22 from samba.tests.samba_tool.base import SambaToolCmdTest
23 from samba.tests import TestCaseInTempDir
24 from samba.netcmd import CommandError
25
26 class DomainBackupOfflineCmp(SambaToolCmdTest, TestCaseInTempDir):
27
28     def test_domain_backup_offline_untar_tdb(self):
29         self.untar_testcase('tdb')
30
31     def test_domain_backup_offline_untar_mbd(self):
32         self.untar_testcase('mdb')
33
34     def test_domain_backup_offline_restore_tdb(self):
35         self.restore_testcase('tdb')
36
37     def test_domain_backup_offline_restore_mbd(self):
38         self.restore_testcase('mdb')
39
40     def restore_testcase(self, backend):
41         prov_dir, backup_file = self.provision_and_backup(backend)
42
43         extract_dir = tempfile.mkdtemp(dir=self.tempdir)
44         cmd = ("samba-tool domain backup restore --backup-file={f}"
45                " --targetdir={d} "
46                "--newservername=NEWSERVER").format(f=backup_file, d=extract_dir)
47         self.check_output(cmd)
48
49         # attrs that are altered by the restore process
50         ignore_attrs = ["servicePrincipalName", "lastLogonTimestamp",
51                         "rIDAllocationPool", "rIDAvailablePool",
52                         "localPolicyFlags", "operatingSystem", "displayName",
53                         "dnsRecord", "dNSTombstoned",
54                         "msDS-NC-Replica-Locations", "msDS-HasInstantiatedNCs",
55                         "interSiteTopologyGenerator"]
56         filter_arg = "--filter=" + ",".join(ignore_attrs)
57         args = ["--two", filter_arg]
58         self.ldapcmp(prov_dir, extract_dir, args)
59
60         shutil.rmtree(prov_dir)
61         shutil.rmtree(extract_dir)
62
63     def untar_testcase(self, backend):
64         prov_dir, backup_file = self.provision_and_backup(backend)
65
66         extract_dir = tempfile.mkdtemp(dir=self.tempdir)
67         tf = tarfile.open(backup_file)
68         tf.extractall(extract_dir)
69
70         self.ldapcmp(prov_dir, extract_dir)
71
72         shutil.rmtree(prov_dir)
73         shutil.rmtree(extract_dir)
74
75     def ldapcmp(self, prov_dir, ex_dir, args=[]):
76         sam_fn = os.path.join("private", "sam.ldb")
77         url1 = "tdb://" + os.path.join(os.path.realpath(prov_dir), sam_fn)
78         url2 = "tdb://" + os.path.join(os.path.realpath(ex_dir), sam_fn)
79
80         # Compare the restored sam.ldb with the old one
81         for partition in ["domain", "configuration", "schema",
82                           "dnsdomain", "dnsforest"]:
83             cmd = "samba-tool ldapcmp " + " ".join([url1, url2, partition] + args)
84             self.check_output(cmd)
85
86     # Test the "samba-tool domain backup" command with ldapcmp
87     def provision_and_backup(self, backend):
88         prov_dir = tempfile.mkdtemp(dir=self.tempdir)
89
90         # Provision domain.  Use fake ACLs and store xattrs in tdbs so that
91         # NTACL backup will work inside the testenv.
92         # host-name option must be given because if this test runs on a
93         # system with a very long hostname, it will be shortened in certain
94         # circumstances, causing the ldapcmp to fail.
95         prov_cmd = "samba-tool domain provision " +\
96                    "--domain FOO --realm foo.example.com " +\
97                    "--targetdir {prov_dir} " +\
98                    "--backend-store {backend} " +\
99                    "--host-name OLDSERVER "+\
100                    "--option=\"vfs objects=fake_acls xattr_tdb\""
101         prov_cmd = prov_cmd.format(prov_dir=prov_dir, backend=backend)
102         self.check_output(prov_cmd)
103
104         # Run the backup and check we got one backup tar file
105         cmd = ("samba-tool domain backup offline --targetdir={prov_dir} "
106                "-s {prov_dir}/etc/smb.conf").format(prov_dir=prov_dir)
107         self.check_output(cmd)
108
109         tar_files = [fn for fn in os.listdir(prov_dir)
110                      if fn.startswith("samba-backup-") and
111                      fn.endswith(".tar.bz2")]
112         if len(tar_files) != 1:
113             raise CommandError("expected domain backup to create one tar" +
114                                " file but got {}".format(len(tar_files)))
115
116         backup_file = os.path.join(prov_dir, tar_files[0])
117         return prov_dir, backup_file