diff options
Diffstat (limited to 'python/samba/netcmd/domain/classicupgrade.py')
-rw-r--r-- | python/samba/netcmd/domain/classicupgrade.py | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/python/samba/netcmd/domain/classicupgrade.py b/python/samba/netcmd/domain/classicupgrade.py new file mode 100644 index 0000000..5b6a8a8 --- /dev/null +++ b/python/samba/netcmd/domain/classicupgrade.py @@ -0,0 +1,189 @@ +# domain management - domain classicupgrade +# +# Copyright Matthias Dieter Wallnoefer 2009 +# Copyright Andrew Kroeger 2009 +# Copyright Jelmer Vernooij 2007-2012 +# Copyright Giampaolo Lauria 2011 +# Copyright Matthieu Patou <mat@matws.net> 2011 +# Copyright Andrew Bartlett 2008-2015 +# Copyright Stefan Metzmacher 2012 +# +# 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 tempfile +import subprocess + +import samba +import samba.getopt as options +from samba.auth import system_session +from samba.auth_util import system_session_unix +from samba.common import get_string +from samba.netcmd import Command, CommandError, Option +from samba.samba3 import Samba3 +from samba.samba3 import param as s3param +from samba.upgrade import upgrade_from_samba3 + +from .common import common_ntvfs_options + + +def get_testparm_var(testparm, smbconf, varname): + errfile = open(os.devnull, 'w') + p = subprocess.Popen([testparm, '-s', '-l', + '--parameter-name=%s' % varname, smbconf], + stdout=subprocess.PIPE, stderr=errfile) + (out, err) = p.communicate() + errfile.close() + lines = out.split(b'\n') + if lines: + return get_string(lines[0]).strip() + return "" + + +class cmd_domain_classicupgrade(Command): + """Upgrade from Samba classic (NT4-like) database to Samba AD DC database. + + Specify either a directory with all Samba classic DC databases and state files (with --dbdir) or + the testparm utility from your classic installation (with --testparm). + """ + + synopsis = "%prog [options] <classic_smb_conf>" + + takes_optiongroups = { + "sambaopts": options.SambaOptions, + "versionopts": options.VersionOptions + } + + takes_options = [ + Option("--dbdir", type="string", metavar="DIR", + help="Path to samba classic DC database directory"), + Option("--testparm", type="string", metavar="PATH", + help="Path to samba classic DC testparm utility from the previous installation. This allows the default paths of the previous installation to be followed"), + Option("--targetdir", type="string", metavar="DIR", + help="Path prefix where the new Samba 4.0 AD domain should be initialised"), + Option("-q", "--quiet", help="Be quiet", action="store_true"), + Option("-v", "--verbose", help="Be verbose", action="store_true"), + Option("--dns-backend", type="choice", metavar="NAMESERVER-BACKEND", + choices=["SAMBA_INTERNAL", "BIND9_FLATFILE", "BIND9_DLZ", "NONE"], + help="The DNS server backend. SAMBA_INTERNAL is the builtin name server (default), " + "BIND9_FLATFILE uses bind9 text database to store zone information, " + "BIND9_DLZ uses samba4 AD to store zone information, " + "NONE skips the DNS setup entirely (this DC will not be a DNS server)", + default="SAMBA_INTERNAL") + ] + + ntvfs_options = [ + Option("--use-xattrs", type="choice", choices=["yes", "no", "auto"], + metavar="[yes|no|auto]", + help="Define if we should use the native fs capabilities or a tdb file for " + "storing attributes likes ntacl when --use-ntvfs is set. " + "auto tries to make an intelligent guess based on the user rights and system capabilities", + default="auto") + ] + if samba.is_ntvfs_fileserver_built(): + takes_options.extend(common_ntvfs_options) + takes_options.extend(ntvfs_options) + + takes_args = ["smbconf"] + + def run(self, smbconf=None, targetdir=None, dbdir=None, testparm=None, + quiet=False, verbose=False, use_xattrs="auto", sambaopts=None, versionopts=None, + dns_backend=None, use_ntvfs=False): + + if not os.path.exists(smbconf): + raise CommandError("File %s does not exist" % smbconf) + + if testparm and not os.path.exists(testparm): + raise CommandError("Testparm utility %s does not exist" % testparm) + + if dbdir and not os.path.exists(dbdir): + raise CommandError("Directory %s does not exist" % dbdir) + + if not dbdir and not testparm: + raise CommandError("Please specify either dbdir or testparm") + + logger = self.get_logger(verbose=verbose, quiet=quiet) + + if dbdir and testparm: + logger.warning("both dbdir and testparm specified, ignoring dbdir.") + dbdir = None + + lp = sambaopts.get_loadparm() + + s3conf = s3param.get_context() + + if sambaopts.realm: + s3conf.set("realm", sambaopts.realm) + + if targetdir is not None: + if not os.path.isdir(targetdir): + os.mkdir(targetdir) + + eadb = True + if use_xattrs == "yes": + eadb = False + elif use_xattrs == "auto" and not use_ntvfs: + eadb = False + elif not use_ntvfs: + raise CommandError("--use-xattrs=no requires --use-ntvfs (not supported for production use). " + "Please re-run with --use-xattrs omitted.") + elif use_xattrs == "auto" and not s3conf.get("posix:eadb"): + if targetdir: + tmpfile = tempfile.NamedTemporaryFile(dir=os.path.abspath(targetdir)) + else: + tmpfile = tempfile.NamedTemporaryFile(dir=os.path.abspath(os.path.dirname(lp.get("private dir")))) + try: + try: + samba.ntacls.setntacl(lp, tmpfile.name, + "O:S-1-5-32G:S-1-5-32", + "S-1-5-32", + system_session_unix(), + "native") + eadb = False + except Exception: + # FIXME: Don't catch all exceptions here + logger.info("You are not root or your system does not support xattr, using tdb backend for attributes. " + "If you intend to use this provision in production, rerun the script as root on a system supporting xattrs.") + finally: + tmpfile.close() + + # Set correct default values from dbdir or testparm + paths = {} + if dbdir: + paths["state directory"] = dbdir + paths["private dir"] = dbdir + paths["lock directory"] = dbdir + paths["smb passwd file"] = dbdir + "/smbpasswd" + else: + paths["state directory"] = get_testparm_var(testparm, smbconf, "state directory") + paths["private dir"] = get_testparm_var(testparm, smbconf, "private dir") + paths["smb passwd file"] = get_testparm_var(testparm, smbconf, "smb passwd file") + paths["lock directory"] = get_testparm_var(testparm, smbconf, "lock directory") + # "testparm" from Samba 3 < 3.4.x is not aware of the parameter + # "state directory", instead make use of "lock directory" + if len(paths["state directory"]) == 0: + paths["state directory"] = paths["lock directory"] + + for p in paths: + s3conf.set(p, paths[p]) + + # load smb.conf parameters + logger.info("Reading smb.conf") + s3conf.load(smbconf) + samba3 = Samba3(smbconf, s3conf) + + logger.info("Provisioning") + upgrade_from_samba3(samba3, logger, targetdir, session_info=system_session(), + useeadb=eadb, dns_backend=dns_backend, use_ntvfs=use_ntvfs) |