s4-python: Simplify code, improve formatting.
authorJelmer Vernooij <jelmer@samba.org>
Thu, 8 Apr 2010 16:57:09 +0000 (18:57 +0200)
committerJelmer Vernooij <jelmer@samba.org>
Thu, 8 Apr 2010 21:20:36 +0000 (23:20 +0200)
source4/scripting/bin/upgradeprovision
source4/scripting/python/samba/netcmd/domainlevel.py
source4/scripting/python/samba/netcmd/dsacl.py
source4/scripting/python/samba/provision.py
source4/scripting/python/samba/provisionbackend.py
source4/scripting/python/samba/provisionexceptions.py [deleted file]
source4/scripting/python/samba/upgradehelpers.py
source4/setup/provision

index 234152b002a761a71ae370aedbfd5a3f182f208e..a900728ed47a5bb8055ace89ccb40afd1e017500 100755 (executable)
@@ -40,8 +40,7 @@ from ldb import SCOPE_SUBTREE, SCOPE_BASE, \
                 MessageElement, Message, Dn
 from samba import param
 from samba.misc import messageEltFlagToString
-from samba.provision import find_setup_dir, get_domain_descriptor, get_config_descriptor, secretsdb_self_join,set_gpo_acl,getpolicypath,create_gpo_struct
-from samba.provisionexceptions import ProvisioningError
+from samba.provision import find_setup_dir, get_domain_descriptor, get_config_descriptor, secretsdb_self_join,set_gpo_acl,getpolicypath,create_gpo_struct, ProvisioningError
 from samba.schema import get_linked_attributes, Schema, get_schema_descriptor
 from samba.dcerpc import security
 from samba.ndr import ndr_unpack
@@ -321,16 +320,22 @@ def handle_special_case(att, delta, new, old, ischema):
 def update_secrets(newpaths, paths, creds, session):
     """Update secrets.ldb
 
-    :param newpaths: a list of paths for different provision objects from the reference provision
-    :param paths: a list of paths for different provision objects from the upgraded provision
+    :param newpaths: a list of paths for different provision objects from the
+        reference provision
+    :param paths: a list of paths for different provision objects from the
+        upgraded provision
     :param creds: credential for the authentification
     :param session: session for connexion"""
 
     message(SIMPLE,"update secrets.ldb")
-    newsecrets_ldb = Ldb(newpaths.secrets, session_info=session, credentials=creds,lp=lp)
-    secrets_ldb = Ldb(paths.secrets, session_info=session, credentials=creds,lp=lp, options=["modules:samba_secrets"])
-    reference = newsecrets_ldb.search(expression="dn=@MODULES",base="", scope=SCOPE_SUBTREE)
-    current = secrets_ldb.search(expression="dn=@MODULES",base="", scope=SCOPE_SUBTREE)
+    newsecrets_ldb = Ldb(newpaths.secrets, session_info=session,
+        credentials=creds,lp=lp)
+    secrets_ldb = Ldb(paths.secrets, session_info=session,
+        credentials=creds,lp=lp, options=["modules:samba_secrets"])
+    reference = newsecrets_ldb.search(expression="dn=@MODULES",base="",
+        scope=SCOPE_SUBTREE)
+    current = secrets_ldb.search(expression="dn=@MODULES",base="",
+        scope=SCOPE_SUBTREE)
     delta = secrets_ldb.msg_diff(current[0],reference[0])
     delta.dn = current[0].dn
     secrets_ldb.modify(delta)
@@ -449,7 +454,8 @@ def handle_special_add(sam_ldb,dn,names):
             message(CHANGE,"Existing object %s must be replaced by %s, removing old object"%(dntoremove,str(dn)))
             sam_ldb.delete(res[0]["dn"])
 
-def check_dn_nottobecreated(hash,index,listdn):
+
+def check_dn_nottobecreated(hash, index, listdn):
     """Check if one of the DN present in the list has a creation order greater than the current.
 
     Hash is indexed by dn to be created, with each key is associated the creation order
@@ -780,22 +786,22 @@ def update_basesamdb(newpaths, paths, names):
     shutil.copy(newpaths.samdb,paths.samdb)
 
     message(SIMPLE,"Update partitions filename if needed")
-    schemaldb=os.path.join(paths.private_dir,"schema.ldb")
-    configldb=os.path.join(paths.private_dir,"configuration.ldb")
-    usersldb=os.path.join(paths.private_dir,"users.ldb")
-    samldbdir=os.path.join(paths.private_dir,"sam.ldb.d")
+    schemaldb = os.path.join(paths.private_dir, "schema.ldb")
+    configldb = os.path.join(paths.private_dir, "configuration.ldb")
+    usersldb = os.path.join(paths.private_dir, "users.ldb")
+    samldbdir = os.path.join(paths.private_dir, "sam.ldb.d")
 
     if not os.path.isdir(samldbdir):
         os.mkdir(samldbdir)
         os.chmod(samldbdir,0700)
     if os.path.isfile(schemaldb):
-        shutil.copy(schemaldb, os.path.join(samldbdir, "%s.ldb"%str(names.schemadn).upper()))
+        shutil.copy(schemaldb, os.path.join(samldbdir, "%s.ldb" % str(names.schemadn).upper()))
         os.remove(schemaldb)
     if os.path.isfile(usersldb):
-        shutil.copy(usersldb, os.path.join(samldbdir, "%s.ldb"%str(names.rootdn).upper()))
+        shutil.copy(usersldb, os.path.join(samldbdir, "%s.ldb" % str(names.rootdn).upper()))
         os.remove(usersldb)
     if os.path.isfile(configldb):
-        shutil.copy(configldb, os.path.join(samldbdir, "%s.ldb"%str(names.configdn).upper()))
+        shutil.copy(configldb, os.path.join(samldbdir, "%s.ldb" % str(names.configdn).upper()))
         os.remove(configldb)
 
 
@@ -834,7 +840,8 @@ def update_machine_account_password(paths, creds, session, names):
     :param session: Session for connexion
     :param names: List of key provision parameters"""
 
-    secrets_ldb = Ldb(paths.secrets, session_info=session, credentials=creds,lp=lp)
+    secrets_ldb = Ldb(paths.secrets, session_info=session,
+        credentials=creds,lp=lp)
     secrets_ldb.transaction_start()
     secrets_msg = secrets_ldb.search(expression=("samAccountName=%s$" % names.netbiosname), attrs=["secureChannelType"])
     sam_ldb = Ldb(paths.samdb, session_info=session, credentials=creds,lp=lp)
@@ -885,6 +892,7 @@ def update_gpo(paths,creds,session,names):
     set_gpo_acl(paths.sysvol, names.dnsdomain, names.domainsid,
         names.domaindn, samdb, lp)
 
+
 def updateOEMInfo(paths, creds, session,names):
     sam_ldb = Ldb(paths.samdb, session_info=session, credentials=creds, lp=lp,
         options=["modules:samba_dsdb"])
index c97ed7bad64ac95188a48a2919e27a8f219b0c68..1874191e1f31b8b5c1038a790d41f2de0ecbccf9 100644 (file)
@@ -114,7 +114,7 @@ class cmd_domainlevel(Command):
             raise CommandError("Could not retrieve the actual domain, forest level and/or lowest DC function level!")
 
         if subcommand == "show":
-            self.message("Domain and forest function level for domain '" + domain_dn + "'")
+            self.message("Domain and forest function level for domain '%s'" % domain_dn)
             if level_forest < DS_DOMAIN_FUNCTION_2003:
                 self.message("\nATTENTION: You run SAMBA 4 on a forest function level lower than Windows 2003 (Native). This isn't supported! Please raise!")
             if level_domain < DS_DOMAIN_FUNCTION_2003:
index 58fb9c611a75e1460e63cf2a259b38e2c340ad8c..17982b811952243adcb933ac3a8c5dca76f1532b 100644 (file)
@@ -57,7 +57,8 @@ class cmd_ds_acl_set(Command):
         }
 
     takes_options = [
-        Option("--host", help="LDB URL for database or target server", type=str),
+        Option("--host", help="LDB URL for database or target server",
+            type=str),
         Option("--car", type="choice", choices=["change-rid",
                                                 "change-pdc",
                                                 "change-infrastructure",
@@ -74,12 +75,15 @@ class cmd_ds_acl_set(Command):
                help=car_help),
         Option("--action", type="choice", choices=["allow", "deny"],
                 help="""Deny or allow access"""),
-        Option("--objectdn", help="DN of the object whose SD to modify", type="string"),
-        Option("--trusteedn", help="DN of the entity that gets access", type="string"),
+        Option("--objectdn", help="DN of the object whose SD to modify",
+            type="string"),
+        Option("--trusteedn", help="DN of the entity that gets access",
+            type="string"),
         ]
 
     def find_trustee_sid(self, samdb, trusteedn):
-        res = samdb.search(base=trusteedn, expression="(objectClass=*)", scope=SCOPE_BASE)
+        res = samdb.search(base=trusteedn, expression="(objectClass=*)",
+            scope=SCOPE_BASE)
         assert(len(res) == 1)
         return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
 
@@ -93,18 +97,20 @@ class cmd_ds_acl_set(Command):
         samdb.modify(m)
 
     def read_descriptor(self, samdb, object_dn):
-        res = samdb.search(base=object_dn, scope=SCOPE_BASE, attrs=["nTSecurityDescriptor"])
+        res = samdb.search(base=object_dn, scope=SCOPE_BASE,
+                attrs=["nTSecurityDescriptor"])
         # we should theoretically always have an SD
         assert(len(res) == 1)
         desc = res[0]["nTSecurityDescriptor"][0]
         return ndr_unpack(security.descriptor, desc)
 
     def get_domain_sid(self, samdb):
-        res = samdb.search(base=SamDB.domain_dn(samdb), expression="(objectClass=*)", scope=SCOPE_BASE)
+        res = samdb.search(base=SamDB.domain_dn(samdb),
+                expression="(objectClass=*)", scope=SCOPE_BASE)
         return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
 
-    #add new ace explicitly
     def add_ace(self, samdb, object_dn, new_ace):
+        """Add new ace explicitly."""
         desc = self.read_descriptor(samdb, object_dn)
         desc_sddl = desc.as_sddl(self.get_domain_sid(samdb))
         #TODO add bindings for descriptor manipulation and get rid of this
@@ -164,6 +170,7 @@ class cmd_ds_acl_set(Command):
         self.add_ace(samdb, objectdn, new_ace)
         self.print_new_acl(samdb, objectdn)
 
+
 class cmd_ds_acl(SuperCommand):
     """DS ACLs manipulation"""
 
index 4bef0ed7d407183f8e12cfe82061dbe77648052d..eb89ee9f3a4b503bef8f213e38f748b4f53f4c29 100644 (file)
@@ -2,7 +2,7 @@
 # Unix SMB/CIFS implementation.
 # backend code for provisioning a Samba4 server
 
-# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
+# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2010
 # Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008-2009
 # Copyright (C) Oliver Liebel <oliver@itc.li> 2008-2009
 #
@@ -53,7 +53,6 @@ from samba.schema import Schema
 from samba.samdb import SamDB
 from ms_display_specifiers import read_ms_ldif
 from samba.provisionbackend import LDBBackend, ExistingBackend, FDSBackend, OpenLDAPBackend
-from provisionexceptions import ProvisioningError, InvalidNetbiosName
 
 __docformat__ = "restructuredText"
 
@@ -150,9 +149,8 @@ def get_domain_descriptor(domain_sid):
 
 DEFAULTSITE = "Default-First-Site-Name"
 
-# Exception classes
-
 class ProvisionPaths(object):
+
     def __init__(self):
         self.shareconf = None
         self.hklm = None
@@ -172,6 +170,7 @@ class ProvisionPaths(object):
 
 
 class ProvisionNames(object):
+
     def __init__(self):
         self.rootdn = None
         self.domaindn = None
@@ -188,12 +187,14 @@ class ProvisionNames(object):
     
 
 class ProvisionResult(object):
+
     def __init__(self):
         self.paths = None
         self.domaindn = None
         self.lp = None
         self.samdb = None
 
+
 def check_install(lp, session_info, credentials):
     """Check whether the current install seems ok.
     
@@ -203,9 +204,9 @@ def check_install(lp, session_info, credentials):
     """
     if lp.get("realm") == "":
         raise Exception("Realm empty")
-    ldb = Ldb(lp.get("sam database"), session_info=session_info, 
+    samdb = Ldb(lp.get("sam database"), session_info=session_info, 
             credentials=credentials, lp=lp)
-    if len(ldb.search("(cn=Administrator)")) != 1:
+    if len(samdb.search("(cn=Administrator)")) != 1:
         raise ProvisioningError("No administrator account found")
 
 
@@ -825,6 +826,7 @@ def create_gpo_struct(policy_path):
     os.makedirs(os.path.join(policy_path, "MACHINE"), 0755)
     os.makedirs(os.path.join(policy_path, "USER"), 0755)
 
+
 def setup_gpo(sysvolpath, dnsdomain, policyguid, policyguid_dc):
     policy_path = getpolicypath(sysvolpath,dnsdomain,policyguid)
     create_gpo_struct(policy_path)
@@ -832,6 +834,7 @@ def setup_gpo(sysvolpath, dnsdomain, policyguid, policyguid_dc):
     policy_path = getpolicypath(sysvolpath,dnsdomain,policyguid_dc)
     create_gpo_struct(policy_path)
 
+
 def setup_samdb(path, setup_path, session_info, provision_backend, lp, 
                 names, message, 
                 domainsid, domainguid, policyguid, policyguid_dc,
@@ -851,7 +854,8 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp,
     if dom_for_fun_level is None:
         dom_for_fun_level = DS_DOMAIN_FUNCTION_2003
     if dom_for_fun_level < DS_DOMAIN_FUNCTION_2003:
-        message("You want to run SAMBA 4 on a domain and forest function level lower than Windows 2003 (Native). This is not recommended")
+        message("You want to run SAMBA 4 on a domain and forest function level"
+                " lower than Windows 2003 (Native). This is not recommended")
 
     if dom_for_fun_level > domainControllerFunctionality:
         raise ProvisioningError("You want to run SAMBA 4 on a domain and forest function level which itself is higher than its actual DC function level (2008). This won't work!")
@@ -864,7 +868,7 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp,
         provision_backend=provision_backend, session_info=session_info,
         names=names, serverrole=serverrole, schema=schema)
 
-    if (schema == None):
+    if schema is None:
         schema = Schema(setup_path, domainsid, schemadn=names.schemadn, serverdn=names.serverdn)
 
     # Load the database, but importantly, use Ldb not SamDB as we don't want to
@@ -1033,7 +1037,6 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp,
             names.ntdsguid = samdb.searchone(basedn=ntds_dn,
                 attribute="objectGUID", expression="", scope=ldb.SCOPE_BASE)
             assert isinstance(names.ntdsguid, str)
-
     except:
         samdb.transaction_cancel()
         raise
@@ -1066,9 +1069,11 @@ def set_gpo_acl(sysvol, dnsdomain, domainsid, domaindn, samdb, lp):
                         attrs=["cn","nTSecurityDescriptor"],
                         expression="", scope=ldb.SCOPE_ONELEVEL)
     for policy in res:
-        acl = ndr_unpack(security.descriptor,str(policy["nTSecurityDescriptor"])).as_sddl()
+        acl = ndr_unpack(security.descriptor, 
+                         str(policy["nTSecurityDescriptor"])).as_sddl()
         policy_path = getpolicypath(sysvol,dnsdomain,str(policy["cn"]))
-        set_dir_acl(policy_path,dsacl2fsacl(acl,str(domainsid)),lp,str(domainsid))
+        set_dir_acl(policy_path, dsacl2fsacl(acl, str(domainsid)), lp, 
+                    str(domainsid))
 
 def setsysvolacl(samdb, netlogon, sysvol, gid, domainsid, dnsdomain, domaindn,
     lp):
@@ -1177,8 +1182,8 @@ def provision(setup_dir, message, session_info,
         data = open(smbconf, 'r').read()
         data = data.lstrip()
         if data is None or data == "":
-            make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, 
-                         targetdir, sid_generator, useeadb)
+            make_smbconf(smbconf, setup_path, hostname, domain, realm,
+                         serverrole, targetdir, sid_generator, useeadb)
     else: 
         make_smbconf(smbconf, setup_path, hostname, domain, realm, serverrole, 
                      targetdir, sid_generator, useeadb)
@@ -1229,7 +1234,8 @@ def provision(setup_dir, message, session_info,
 
     ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="")
  
-    schema = Schema(setup_path, domainsid, schemadn=names.schemadn, serverdn=names.serverdn)
+    schema = Schema(setup_path, domainsid, schemadn=names.schemadn,
+                    serverdn=names.serverdn)
     
     if backend_type == "ldb":
         provision_backend = LDBBackend(backend_type,
@@ -1275,7 +1281,7 @@ def provision(setup_dir, message, session_info,
                                          ol_mmr_urls=ol_mmr_urls, 
                                          nosync=nosync)
     else:
-        raise ProvisioningError("Unknown LDAP backend type selected")
+        raise ValueError("Unknown LDAP backend type selected")
 
     provision_backend.init()
     provision_backend.start()
@@ -1290,8 +1296,8 @@ def provision(setup_dir, message, session_info,
      
     message("Setting up secrets.ldb")
     secrets_ldb = setup_secretsdb(paths.secrets, setup_path, 
-                                  session_info=session_info, 
-                                  backend_credentials=provision_backend.secrets_credentials, lp=lp)
+        session_info=session_info,
+        backend_credentials=provision_backend.secrets_credentials, lp=lp)
 
     message("Setting up the registry")
     setup_registry(paths.hklm, setup_path, session_info, 
@@ -1322,15 +1328,15 @@ def provision(setup_dir, message, session_info,
         if paths.netlogon is None:
             message("Existing smb.conf does not have a [netlogon] share, but you are configuring a DC.")
             message("Please either remove %s or see the template at %s" % 
-                    ( paths.smbconf, setup_path("provision.smb.conf.dc")))
-            assert(paths.netlogon is not None)
+                    (paths.smbconf, setup_path("provision.smb.conf.dc")))
+            assert paths.netlogon is not None
 
         if paths.sysvol is None:
-            message("Existing smb.conf does not have a [sysvol] share, but you are configuring a DC.")
+            message("Existing smb.conf does not have a [sysvol] share, but you"
+                    " are configuring a DC.")
             message("Please either remove %s or see the template at %s" % 
                     (paths.smbconf, setup_path("provision.smb.conf.dc")))
-            assert(paths.sysvol is not None)            
-            
+            assert paths.sysvol is not None
 
         if not os.path.isdir(paths.netlogon):
             os.makedirs(paths.netlogon, 0755)
@@ -1342,8 +1348,9 @@ def provision(setup_dir, message, session_info,
 
         if serverrole == "domain controller":
             # Set up group policies (domain policy and domain controller policy)
-            setup_gpo(paths.sysvol,names.dnsdomain,policyguid,policyguid_dc)
-            setsysvolacl(samdb,paths.netlogon,paths.sysvol,wheel_gid,domainsid,names.dnsdomain,names.domaindn,lp)
+            setup_gpo(paths.sysvol, names.dnsdomain, policyguid, policyguid_dc)
+            setsysvolacl(samdb, paths.netlogon, paths.sysvol, wheel_gid, 
+                         domainsid, names.dnsdomain, names.domaindn, lp)
 
         message("Setting up sam.ldb rootDSE marking as synchronized")
         setup_modify_ldif(samdb, setup_path("provision_rootdse_modify.ldif"))
@@ -1368,11 +1375,10 @@ def provision(setup_dir, message, session_info,
 
             # Only make a zone file on the first DC, it should be replicated
             # with DNS replication
-            create_zone_file(lp, message, paths, targetdir, setup_path, dnsdomain=names.dnsdomain,
-                             hostip=hostip,
-                             hostip6=hostip6, hostname=names.hostname,
-                             realm=names.realm,
-                             domainguid=domainguid, ntdsguid=names.ntdsguid)
+            create_zone_file(lp, message, paths, targetdir, setup_path,
+                dnsdomain=names.dnsdomain, hostip=hostip, hostip6=hostip6,
+                hostname=names.hostname, realm=names.realm, 
+                domainguid=domainguid, ntdsguid=names.ntdsguid)
 
             create_named_conf(paths, setup_path, realm=names.realm,
                               dnsdomain=names.dnsdomain, private_dir=paths.private_dir)
@@ -1381,12 +1387,14 @@ def provision(setup_dir, message, session_info,
                               dnsdomain=names.dnsdomain, private_dir=paths.private_dir,
                               keytab_name=paths.dns_keytab)
             message("See %s for an example configuration include file for BIND" % paths.namedconf)
-            message("and %s for further documentation required for secure DNS updates" % paths.namedtxt)
+            message("and %s for further documentation required for secure DNS "
+                    "updates" % paths.namedtxt)
 
             create_krb5_conf(paths.krb5conf, setup_path,
                              dnsdomain=names.dnsdomain, hostname=names.hostname,
                              realm=names.realm)
-            message("A Kerberos configuration suitable for Samba 4 has been generated at %s" % paths.krb5conf)
+            message("A Kerberos configuration suitable for Samba 4 has been "
+                    "generated at %s" % paths.krb5conf)
 
     if serverrole == "domain controller":
         create_dns_update_list(lp, message, paths, setup_path)
@@ -1407,7 +1415,8 @@ def provision(setup_dir, message, session_info,
             os.chmod(dns_keytab_path, 0640)
             os.chown(dns_keytab_path, -1, paths.bind_gid)
         except OSError:
-            message("Failed to chown %s to bind gid %u" % (dns_keytab_path, paths.bind_gid))
+            message("Failed to chown %s to bind gid %u" % (dns_keytab_path,
+                paths.bind_gid))
 
 
     message("Please install the phpLDAPadmin configuration located at %s into /etc/phpldapadmin/config.php" % paths.phpldapadminconfig)
@@ -1443,7 +1452,6 @@ def provision(setup_dir, message, session_info,
     return result
 
 
-
 def provision_become_dc(setup_dir=None,
                         smbconf=None, targetdir=None, realm=None, 
                         rootdn=None, domaindn=None, schemadn=None,
@@ -1622,7 +1630,6 @@ def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm):
     :param hostname: Local hostname
     :param realm: Realm name
     """
-
     setup_file(setup_path("krb5.conf"), path, {
             "DNSDOMAIN": dnsdomain,
             "HOSTNAME": hostname,
@@ -1630,3 +1637,17 @@ def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm):
         })
 
 
+class ProvisioningError(Exception):
+    """A generic provision error."""
+
+    def __init__(self, value):
+        self.value = value
+
+    def __str__(self):
+        return "ProvisioningError: " + self.value
+
+
+class InvalidNetbiosName(Exception):
+    """A specified name was not a valid NetBIOS name."""
+    def __init__(self, name):
+        super(InvalidNetbiosName, self).__init__("The name '%r' is not a valid NetBIOS name" % name)
index 479d965f273677499d4e45a896892ccc4acabdaf..e5d4d8e1b1aa4553406f81555fee4caf3a9149c4 100644 (file)
@@ -26,6 +26,7 @@
 """Functions for setting up a Samba configuration (LDB and LDAP backends)."""
 
 from base64 import b64encode
+import errno
 import ldb
 import os
 import sys
@@ -40,11 +41,21 @@ from ldb import SCOPE_BASE, SCOPE_ONELEVEL, LdbError, timestring
 from samba import Ldb, read_and_sub_file, setup_file
 from samba.credentials import Credentials, DONT_USE_KERBEROS
 from samba.schema import Schema
-from samba.provisionexceptions import ProvisioningError
+
+
+class SlapdAlreadyRunning(Exception):
+
+    def __init__(self, uri):
+        self.ldapi_uri = uri
+        super(SlapdAlreadyRunning, self).__init__("Another slapd Instance "
+            "seems already running on this host, listening to %s." %
+            self.ldapi_uri)
+
 
 class ProvisionBackend(object):
-    def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None, 
-                 names=None, message=None):
+
+    def __init__(self, backend_type, paths=None, setup_path=None, lp=None,
+            credentials=None, names=None, message=None):
         """Provision a backend for samba4"""
         self.paths = paths
         self.setup_path = setup_path
@@ -72,15 +83,6 @@ class ProvisionBackend(object):
 
 
 class LDBBackend(ProvisionBackend):
-    def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None, 
-                 names=None, message=None):
-
-        super(LDBBackend, self).__init__(
-                backend_type=backend_type,
-                paths=paths, setup_path=setup_path,
-                lp=lp, credentials=credentials,
-                names=names,
-                message=message)
 
     def init(self):
         self.credentials = None
@@ -91,49 +93,40 @@ class LDBBackend(ProvisionBackend):
 
 
 class ExistingBackend(ProvisionBackend):
-    def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None, 
-                 names=None, message=None,
-                 ldapi_uri=None):
 
-        super(ExistingBackend, self).__init__(
-                backend_type=backend_type,
-                paths=paths, setup_path=setup_path,
-                lp=lp, credentials=credentials,
-                names=names,
-                message=message)
+    def __init__(self, backend_type, paths=None, setup_path=None, lp=None,
+            credentials=None, names=None, message=None, ldapi_uri=None):
+
+        super(ExistingBackend, self).__init__(backend_type=backend_type,
+                paths=paths, setup_path=setup_path, lp=lp,
+                credentials=credentials, names=names, message=message)
 
         self.ldapi_uri = ldapi_uri
 
     def init(self):
-        #Check to see that this 'existing' LDAP backend in fact exists
+        # Check to see that this 'existing' LDAP backend in fact exists
         ldapi_db = Ldb(self.ldapi_uri, credentials=self.credentials)
         ldapi_db.search(base="", scope=SCOPE_BASE,
-                                            expression="(objectClass=OpenLDAProotDSE)")
+            expression="(objectClass=OpenLDAProotDSE)")
 
-        # If we have got here, then we must have a valid connection to the LDAP server, with valid credentials supplied
-        # This caused them to be set into the long-term database later in the script.
+        # If we have got here, then we must have a valid connection to the LDAP
+        # server, with valid credentials supplied This caused them to be set
+        # into the long-term database later in the script.
         self.secrets_credentials = self.credentials
 
-        self.ldap_backend_type = "openldap" #For now, assume existing backends at least emulate OpenLDAP
+        self.ldap_backend_type = "openldap" # For now, assume existing backends at least emulate OpenLDAP
 
 
 class LDAPBackend(ProvisionBackend):
-    def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
-                 names=None, message=None,
-                 domainsid=None,
-                 schema=None,
-                 hostname=None,
-                 ldapadminpass=None,
-                 slapd_path=None,
-                 ldap_backend_extra_port=None,
-                 ldap_dryrun_mode=False):
-
-        super(LDAPBackend, self).__init__(
-                backend_type=backend_type,
-                paths=paths, setup_path=setup_path,
-                lp=lp, credentials=credentials,
-                names=names,
-                message=message)
+
+    def __init__(self, backend_type, paths=None, setup_path=None, lp=None,
+            credentials=None, names=None, message=None, domainsid=None,
+            schema=None, hostname=None, ldapadminpass=None, slapd_path=None,
+            ldap_backend_extra_port=None, ldap_dryrun_mode=False):
+
+        super(LDAPBackend, self).__init__(backend_type=backend_type,
+                paths=paths, setup_path=setup_path, lp=lp,
+                credentials=credentials, names=names, message=message)
 
         self.domainsid = domainsid
         self.schema = schema
@@ -156,23 +149,26 @@ class LDAPBackend(ProvisionBackend):
             os.mkdir(self.ldapdir)
 
     def init(self):
-        # we will shortly start slapd with ldapi for final provisioning. first check with ldapsearch -> rootDSE via self.ldapi_uri
-        # if another instance of slapd is already running 
+        from samba.provision import ProvisioningError
+        # we will shortly start slapd with ldapi for final provisioning. first
+        # check with ldapsearch -> rootDSE via self.ldapi_uri if another
+        # instance of slapd is already running 
         try:
             ldapi_db = Ldb(self.ldapi_uri)
             ldapi_db.search(base="", scope=SCOPE_BASE,
                 expression="(objectClass=OpenLDAProotDSE)")
             try:
                 f = open(self.slapd_pid, "r")
+            except IOError, err:
+                if err != errno.ENOENT:
+                    raise
+            else:
                 p = f.read()
                 f.close()
                 self.message("Check for slapd Process with PID: " + str(p) + " and terminate it manually.")
-            except:
-                pass
-            
-            raise ProvisioningError("Warning: Another slapd Instance seems already running on this host, listening to " + self.ldapi_uri + ". Please shut it down before you continue. ")
-        
+            raise SlapdAlreadyRunning(self.ldapi_uri)
         except LdbError:
+            # XXX: We should never be catching all Ldb errors
             pass
 
         # Try to print helpful messages when the user has not specified the path to slapd
@@ -216,13 +212,15 @@ class LDAPBackend(ProvisionBackend):
         pass
 
     def start(self):
+        from samba.provision import ProvisioningError
         self.slapd_command_escaped = "\'" + "\' \'".join(self.slapd_command) + "\'"
-        open(self.ldapdir + "/ldap_backend_startup.sh", 'w').write("#!/bin/sh\n" + self.slapd_command_escaped + "\n")
+        open(os.path.join(self.ldapdir, "ldap_backend_startup.sh"), 'w').write("#!/bin/sh\n" + self.slapd_command_escaped + "\n")
 
         # Now start the slapd, so we can provision onto it.  We keep the
         # subprocess context around, to kill this off at the successful
         # end of the script
-        self.slapd = subprocess.Popen(self.slapd_provision_command, close_fds=True, shell=False)
+        self.slapd = subprocess.Popen(self.slapd_provision_command,
+            close_fds=True, shell=False)
     
         while self.slapd.poll() is None:
             # Wait until the socket appears
@@ -253,29 +251,18 @@ class LDAPBackend(ProvisionBackend):
 
 
 class OpenLDAPBackend(LDAPBackend):
-    def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
-                 names=None, message=None,
-                 domainsid=None,
-                 schema=None,
-                 hostname=None,
-                 ldapadminpass=None,
-                 slapd_path=None,
-                 ldap_backend_extra_port=None,
-                 ldap_dryrun_mode=False,
-                 ol_mmr_urls=None,
-                 nosync=False):
-
-        super(OpenLDAPBackend, self).__init__(
-                backend_type=backend_type,
-                paths=paths, setup_path=setup_path,
-                lp=lp, credentials=credentials,
-                names=names,
-                message=message,
-                domainsid=domainsid,
-                schema=schema,
-                hostname=hostname,
-                ldapadminpass=ldapadminpass,
-                slapd_path=slapd_path,
+
+    def __init__(self, backend_type, paths=None, setup_path=None, lp=None,
+            credentials=None, names=None, message=None, domainsid=None,
+            schema=None, hostname=None, ldapadminpass=None, slapd_path=None,
+            ldap_backend_extra_port=None, ldap_dryrun_mode=False,
+            ol_mmr_urls=None, nosync=False):
+
+        super(OpenLDAPBackend, self).__init__( backend_type=backend_type,
+                paths=paths, setup_path=setup_path, lp=lp,
+                credentials=credentials, names=names, message=message,
+                domainsid=domainsid, schema=schema, hostname=hostname,
+                ldapadminpass=ldapadminpass, slapd_path=slapd_path,
                 ldap_backend_extra_port=ldap_backend_extra_port,
                 ldap_dryrun_mode=ldap_dryrun_mode)
 
@@ -290,11 +277,8 @@ class OpenLDAPBackend(LDAPBackend):
         self.olcdir             = os.path.join(self.ldapdir, "slapd.d")
         self.olcseedldif        = os.path.join(self.ldapdir, "olc_seed.ldif")
 
-        self.schema = Schema(
-                self.setup_path,
-                self.domainsid,
-                schemadn=self.names.schemadn,
-                serverdn=self.names.serverdn,
+        self.schema = Schema(self.setup_path, self.domainsid,
+                schemadn=self.names.schemadn, serverdn=self.names.serverdn,
                 files=[setup_path("schema_samba4.ldif")])
 
     def setup_db_config(self, dbdir):
@@ -307,10 +291,11 @@ class OpenLDAPBackend(LDAPBackend):
             if not os.path.isdir(os.path.join(dbdir, "tmp")):
                 os.makedirs(os.path.join(dbdir, "tmp"), 0700)
 
-        setup_file(self.setup_path("DB_CONFIG"), os.path.join(dbdir, "DB_CONFIG"),
-                   {"LDAPDBDIR": dbdir})
+        setup_file(self.setup_path("DB_CONFIG"),
+            os.path.join(dbdir, "DB_CONFIG"), {"LDAPDBDIR": dbdir})
 
     def provision(self):
+        from samba.provision import ProvisioningError
         # Wipe the directories so we can start
         shutil.rmtree(os.path.join(self.ldapdir, "db"), True)
 
@@ -350,7 +335,6 @@ class OpenLDAPBackend(LDAPBackend):
         mmr_syncrepl_schema_config = "" 
         mmr_syncrepl_config_config = "" 
         mmr_syncrepl_user_config = "" 
-       
     
         if self.ol_mmr_urls is not None:
             # For now, make these equal
@@ -485,7 +469,8 @@ class OpenLDAPBackend(LDAPBackend):
             if self.ol_mmr_urls is None:
                 server_port_string = "ldap://0.0.0.0:%d" % self.ldap_backend_extra_port
             else:
-                server_port_string = "ldap://" + self.names.hostname + "." + self.names.dnsdomain +":%d" % self.ldap_backend_extra_port
+                server_port_string = "ldap://%s.%s:%d" (self.names.hostname,
+                    self.names.dnsdomain, self.ldap_backend_extra_port)
         else:
             server_port_string = ""
 
@@ -537,29 +522,18 @@ class OpenLDAPBackend(LDAPBackend):
 
 
 class FDSBackend(LDAPBackend):
-    def __init__(self, backend_type, paths=None, setup_path=None, lp=None, credentials=None,
-                 names=None, message=None,
-                 domainsid=None,
-                 schema=None,
-                 hostname=None,
-                 ldapadminpass=None,
-                 slapd_path=None,
-                 ldap_backend_extra_port=None,
-                 ldap_dryrun_mode=False,
-                 root=None,
-                 setup_ds_path=None):
-
-        super(FDSBackend, self).__init__(
-                backend_type=backend_type,
-                paths=paths, setup_path=setup_path,
-                lp=lp, credentials=credentials,
-                names=names,
-                message=message,
-                domainsid=domainsid,
-                schema=schema,
-                hostname=hostname,
-                ldapadminpass=ldapadminpass,
-                slapd_path=slapd_path,
+
+    def __init__(self, backend_type, paths=None, setup_path=None, lp=None,
+            credentials=None, names=None, message=None, domainsid=None,
+            schema=None, hostname=None, ldapadminpass=None, slapd_path=None,
+            ldap_backend_extra_port=None, ldap_dryrun_mode=False, root=None,
+            setup_ds_path=None):
+
+        super(FDSBackend, self).__init__(backend_type=backend_type,
+                paths=paths, setup_path=setup_path, lp=lp,
+                credentials=credentials, names=names, message=message,
+                domainsid=domainsid, schema=schema, hostname=hostname,
+                ldapadminpass=ldapadminpass, slapd_path=slapd_path,
                 ldap_backend_extra_port=ldap_backend_extra_port,
                 ldap_dryrun_mode=ldap_dryrun_mode)
 
@@ -600,6 +574,7 @@ class FDSBackend(LDAPBackend):
                 prefixmap=["1000:1.3.6.1.4.1.7165.2.1", "1001:1.3.6.1.4.1.7165.2.2"])
 
     def provision(self):
+        from samba.provision import ProvisioningError
         if self.ldap_backend_extra_port is not None:
             serverport = "ServerPort=%d" % self.ldap_backend_extra_port
         else:
@@ -616,7 +591,8 @@ class FDSBackend(LDAPBackend):
                     "LDAPMANAGERPASS": self.ldapadminpass, 
                     "SERVERPORT": serverport})
 
-        setup_file(self.setup_path("fedorads-partitions.ldif"), self.partitions_ldif, 
+        setup_file(self.setup_path("fedorads-partitions.ldif"),
+            self.partitions_ldif, 
                    {"CONFIGDN": self.names.configdn,
                     "SCHEMADN": self.names.schemadn,
                     "SAMBADN": self.sambadn,
diff --git a/source4/scripting/python/samba/provisionexceptions.py b/source4/scripting/python/samba/provisionexceptions.py
deleted file mode 100644 (file)
index 6159a02..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Unix SMB/CIFS implementation.
-# backend code for provisioning a Samba4 server
-
-# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
-# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008-2009
-# Copyright (C) Oliver Liebel <oliver@itc.li> 2008-2009
-#
-# Based on the original in EJS:
-# Copyright (C) Andrew Tridgell <tridge@samba.org> 2005
-#
-# 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/>.
-#
-
-class ProvisioningError(Exception):
-    """A generic provision error."""
-    def __init__(self, value):
-        self.value = value
-    def __str__(self):
-        return "ProvisioningError: " + self.value
-
-class InvalidNetbiosName(ProvisioningError):
-    """A specified name was not a valid NetBIOS name."""
-    def __init__(self, name):
-        super(InvalidNetbiosName, self).__init__("The name '%r' is not a valid NetBIOS name" % name)
-
-
index 25d1d7fe29653afe93e1a5abc51f23470c5996bf..3da739b1396102ba679ce8097fe36d5b49b2ff71 100755 (executable)
@@ -31,8 +31,8 @@ from samba import Ldb
 from samba.dsdb import DS_DOMAIN_FUNCTION_2000
 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE
 import ldb
-from samba.provision import ProvisionNames, provision_paths_from_lp, FILL_FULL, provision
-from samba.provisionexceptions import ProvisioningError
+from samba.provision import (ProvisionNames, provision_paths_from_lp,
+    FILL_FULL, provision, ProvisioningError)
 from samba.dcerpc import misc, security
 from samba.ndr import ndr_unpack
 
@@ -61,7 +61,8 @@ def get_paths(param, targetdir=None, smbconf=None):
     return paths
 
 
-def find_provision_key_parameters(param, credentials, session_info, paths, smbconf):
+def find_provision_key_parameters(param, credentials, session_info, paths,
+        smbconf):
     """Get key provision parameters (realm, domain, ...) from a given provision
 
     :param param: Param object
@@ -82,10 +83,10 @@ def find_provision_key_parameters(param, credentials, session_info, paths, smbco
     names.dnsdomain = names.realm
     names.realm = string.upper(names.realm)
     # netbiosname
-    secrets_ldb = Ldb(paths.secrets, session_info=session_info, credentials=credentials,lp=lp, options=["modules:samba_secrets"])
+    secrets_ldb = Ldb(paths.secrets, session_info=session_info,
+        credentials=credentials,lp=lp, options=["modules:samba_secrets"])
     # Get the netbiosname first (could be obtained from smb.conf in theory)
-    attrs = ["sAMAccountName"]
-    res = secrets_ldb.search(expression="(flatname=%s)"%names.domain,base="CN=Primary Domains", scope=SCOPE_SUBTREE, attrs=attrs)
+    res = secrets_ldb.search(expression="(flatname=%s)"%names.domain,base="CN=Primary Domains", scope=SCOPE_SUBTREE, attrs=["sAMAccountName"])
     names.netbiosname = str(res[0]["sAMAccountName"]).replace("$","")
 
     names.smbconf = smbconf
@@ -96,8 +97,7 @@ def find_provision_key_parameters(param, credentials, session_info, paths, smbco
 
     # That's a bit simplistic but it's ok as long as we have only 3
     # partitions
-    attrs2 = ["defaultNamingContext", "schemaNamingContext","configurationNamingContext","rootDomainNamingContext"]
-    current = samdb.search(expression="(objectClass=*)",base="", scope=SCOPE_BASE, attrs=attrs2)
+    current = samdb.search(expression="(objectClass=*)",base="", scope=SCOPE_BASE, attrs=["defaultNamingContext", "schemaNamingContext","configurationNamingContext","rootDomainNamingContext"])
 
     names.configdn = current[0]["configurationNamingContext"]
     configdn = str(names.configdn)
@@ -108,27 +108,28 @@ def find_provision_key_parameters(param, credentials, session_info, paths, smbco
     names.domaindn=current[0]["defaultNamingContext"]
     names.rootdn=current[0]["rootDomainNamingContext"]
     # default site name
-    attrs3 = ["cn"]
-    res3= samdb.search(expression="(objectClass=*)",base="CN=Sites,"+configdn, scope=SCOPE_ONELEVEL, attrs=attrs3)
+    res3= samdb.search(expression="(objectClass=*)",base="CN=Sites,"+configdn, scope=SCOPE_ONELEVEL, attrs=["cn"])
     names.sitename = str(res3[0]["cn"])
 
     # dns hostname and server dn
-    attrs4 = ["dNSHostName"]
     res4= samdb.search(expression="(CN=%s)"%names.netbiosname,base="OU=Domain Controllers,"+basedn, \
-                        scope=SCOPE_ONELEVEL, attrs=attrs4)
+                        scope=SCOPE_ONELEVEL, attrs=["dNSHostName"])
     names.hostname = str(res4[0]["dNSHostName"]).replace("."+names.dnsdomain,"")
 
     server_res = samdb.search(expression="serverReference=%s"%res4[0].dn, attrs=[], base=configdn)
     names.serverdn = server_res[0].dn
 
     # invocation id/objectguid
-    res5 = samdb.search(expression="(objectClass=*)",base="CN=NTDS Settings,%s" % str(names.serverdn), scope=SCOPE_BASE, attrs=["invocationID","objectGUID"])
-    names.invocation = str(ndr_unpack( misc.GUID,res5[0]["invocationId"][0]))
-    names.ntdsguid = str(ndr_unpack( misc.GUID,res5[0]["objectGUID"][0]))
+    res5 = samdb.search(expression="(objectClass=*)",
+            base="CN=NTDS Settings,%s" % str(names.serverdn), scope=SCOPE_BASE,
+            attrs=["invocationID", "objectGUID"])
+    names.invocation = str(ndr_unpack(misc.GUID, res5[0]["invocationId"][0]))
+    names.ntdsguid = str(ndr_unpack(misc.GUID, res5[0]["objectGUID"][0]))
 
     # domain guid/sid
-    attrs6 = ["objectGUID", "objectSid","msDS-Behavior-Version" ]
-    res6 = samdb.search(expression="(objectClass=*)",base=basedn, scope=SCOPE_BASE, attrs=attrs6)
+    res6 = samdb.search(expression="(objectClass=*)",base=basedn,
+            scope=SCOPE_BASE, attrs=["objectGUID",
+                "objectSid","msDS-Behavior-Version" ])
     names.domainguid = str(ndr_unpack( misc.GUID,res6[0]["objectGUID"][0]))
     names.domainsid = ndr_unpack( security.dom_sid,res6[0]["objectSid"][0])
     if res6[0].get("msDS-Behavior-Version") == None or int(res6[0]["msDS-Behavior-Version"][0]) < DS_DOMAIN_FUNCTION_2000:
@@ -137,14 +138,12 @@ def find_provision_key_parameters(param, credentials, session_info, paths, smbco
         names.domainlevel = int(res6[0]["msDS-Behavior-Version"][0])
 
     # policy guid
-    attrs7 = ["cn","displayName"]
     res7 = samdb.search(expression="(displayName=Default Domain Policy)",base="CN=Policies,CN=System,"+basedn, \
-                            scope=SCOPE_ONELEVEL, attrs=attrs7)
+                            scope=SCOPE_ONELEVEL, attrs=["cn","displayName"])
     names.policyid = str(res7[0]["cn"]).replace("{","").replace("}","")
     # dc policy guid
-    attrs8 = ["cn","displayName"]
     res8 = samdb.search(expression="(displayName=Default Domain Controllers Policy)",base="CN=Policies,CN=System,"+basedn, \
-                            scope=SCOPE_ONELEVEL, attrs=attrs8)
+                            scope=SCOPE_ONELEVEL, attrs=["cn","displayName"])
     if len(res8) == 1:
         names.policyid_dc = str(res8[0]["cn"]).replace("{","").replace("}","")
     else:
@@ -194,9 +193,12 @@ def newprovision(names,setup_dir,creds,session,smbconf,provdir,messagefunc):
 
 
 def dn_sort(x,y):
-    """Sorts two DNs in the lexicographical order it and put higher level DN before.
+    """Sorts two DNs in the lexicographical order it and put higher level DN
+    before.
+
+    So given the dns cn=bar,cn=foo and cn=foo the later will be return as
+    smaller
 
-    So given the dns cn=bar,cn=foo and cn=foo the later will be return as smaller
     :param x: First object to compare
     :param y: Second object to compare
     """
index bbd6298dc3f31b4445a9fd1d624306d795b69e96..d0d35f807e0a1cc3cc34aafdfbc0fcd8c541ae86 100755 (executable)
@@ -34,13 +34,12 @@ import samba.ntacls
 from samba.credentials import DONT_USE_KERBEROS
 from samba.auth import system_session
 import samba.getopt as options
-from samba.provision import provision, FILL_FULL, FILL_NT4SYNC, FILL_DRS, find_setup_dir
+from samba.provision import provision, FILL_FULL, FILL_NT4SYNC, FILL_DRS, find_setup_dir, ProvisioningError
 from samba.dsdb import (
        DS_DOMAIN_FUNCTION_2003,
        DS_DOMAIN_FUNCTION_2008,
        DS_DOMAIN_FUNCTION_2008_R2,
        )
-from samba.provisionexceptions import ProvisioningError
 
 # how do we make this case insensitive??
 
@@ -118,7 +117,7 @@ parser.add_option("--slapd-path", type="string", metavar="SLAPD-PATH",
 parser.add_option("--setup-ds-path", type="string", metavar="SETUP_DS-PATH", 
                help="Path to setup-ds.pl script for Fedora DS LDAP backend [e.g.:'/usr/sbin/setup-ds.pl']. Required for Setup with Fedora DS backend.") 
 parser.add_option("--nosync", help="Configure LDAP backend not to call fsync() (for performance in test environments)", action="store_true")
-parser.add_option("--use-xattrs", type="choice", choices=["yes","no","auto"], help="Define if we should use the native fs capabilities or a tdb file for storing attributes likes ntacl, auto tries to make an inteligent guess based on the user rights and system capabilities")
+parser.add_option("--use-xattrs", type="choice", choices=["yes","no","auto"], help="Define if we should use the native fs capabilities or a tdb file for storing attributes likes ntacl, auto tries to make an inteligent guess based on the user rights and system capabilities", default="auto")
 parser.add_option("--ldap-dryrun-mode", help="Configure LDAP backend, but do not run any binaries and exit early.  Used only for the test environment.  DO NOT USE", action="store_true")
 
 opts = parser.parse_args()[0]
@@ -210,16 +209,14 @@ if opts.blank:
 elif opts.partitions_only:
     samdb_fill = FILL_DRS
 
-if not opts.use_xattrs:
-       opts.use_xattrs="auto"
-
 eadb = True
 if opts.use_xattrs == "yes":
        eadb = False
 elif opts.use_xattrs == "auto":
-       file=tempfile.NamedTemporaryFile()
+       file = tempfile.NamedTemporaryFile()
        try:
-               samba.ntacls.setntacl(lp,file.name,"O:S-1-5-32G:S-1-5-32","S-1-5-32","native")
+               samba.ntacls.setntacl(lp, file.name, 
+                       "O:S-1-5-32G:S-1-5-32", "S-1-5-32", "native")
                eadb = False
        except:
                if lp.get("posix:eadb") == None: