def _wait_for_drs_replication(ldap_filter, attrs=None, base=None, scope=ldb.SCOPE_SUBTREE, lp=None, timeout=360, delta_t=1, verbose=True, should_exist=True, controls=None): # type: (str, Union[List[str], None, str], Optional[str], int, Optional[LoadParm], int, int, bool, bool, Optional[List[str]]) -> None if not package_installed('univention-samba4'): if package_installed('univention-samba'): time.sleep(15) print('Sleeping 15 seconds as a workaround for http://forge.univention.org/bugzilla/show_bug.cgi?id=52145') elif verbose: print('wait_for_drs_replication(): skip, univention-samba4 not installed.') return if not attrs: attrs = ['dn'] elif not isinstance(attrs, list): attrs = [attrs] if not lp: lp = LoadParm() lp.load('/etc/samba/smb.conf') samdb = SamDB("tdb://%s" % lp.private_path("sam.ldb"), session_info=system_session(lp), lp=lp) if not controls: controls = ["domain_scope:0"] if base is None: ucr = config_registry.ConfigRegistry() ucr.load() base = ucr['samba4/ldap/base'] else: if len(ldap.dn.str2dn(base)[0]) > 1: if verbose: print('wait_for_drs_replication(): skip, multiple RDNs are not supported') return if not base: if verbose: print('wait_for_drs_replication(): skip, no samba domain found') return if verbose: print("Waiting for DRS replication, filter: %r, base: %r, scope: %r, should_exist: %r" % (ldap_filter, base, scope, should_exist), end=' ') t = t0 = time.time() while t < t0 + timeout: try: res = samdb.search(base=base, scope=scope, expression=ldap_filter, attrs=attrs, controls=controls) if bool(res) is bool(should_exist): if verbose: print("\nDRS replication took %d seconds" % (t - t0, )) return # res except ldb.LdbError as exc: (_num, msg) = exc.args if _num == ldb.ERR_INVALID_DN_SYNTAX: raise if _num == ldb.ERR_NO_SUCH_OBJECT and not should_exist: if verbose: print("\nDRS replication took %d seconds" % (t - t0, )) return print("Error during samdb.search: %s" % (msg, )) print('.', end=' ') time.sleep(delta_t) t = time.time() raise DRSReplicationFailed("DRS replication for filter: %r failed due to timeout after %d sec." % (ldap_filter, t - t0))
def force_drs_replication(source_dc=None, destination_dc=None, partition_dn=None, direction="in"): if not package_installed('univention-samba4'): print( 'force_drs_replication(): skip, univention-samba4 not installed.') return if not source_dc: source_dc = get_available_s4connector_dc() if not source_dc: return 1 if not destination_dc: destination_dc = socket.gethostname() if destination_dc == source_dc: return if not partition_dn: lp = LoadParm() lp.load('/etc/samba/smb.conf') samdb = SamDB("tdb://%s" % lp.private_path("sam.ldb"), session_info=system_session(lp), lp=lp) partition_dn = str(samdb.domain_dn()) print("USING partition_dn:", partition_dn) if direction == "in": cmd = ("/usr/bin/samba-tool", "drs", "replicate", destination_dc, source_dc, partition_dn) else: cmd = ("/usr/bin/samba-tool", "drs", "replicate", source_dc, destination_dc, partition_dn) return subprocess.call(cmd)
def password_policy(complexity=False, minimum_password_age=0, maximum_password_age=3): if not package_installed('univention-samba4'): print('skipping samba password policy adjustment') yield return complexity = 'on' if complexity else 'off' minimum_password_age = str(minimum_password_age) maximum_password_age = str(maximum_password_age) min_pwd_age = subprocess.check_output( 'samba-tool domain passwordsettings show | grep "Minimum password age" | sed s/[^0-9]*/""/', shell=True).strip() max_pwd_age = subprocess.check_output( 'samba-tool domain passwordsettings show | grep "Maximum password age" | sed s/[^0-9]*/""/', shell=True).strip() pwd_complexity = subprocess.check_output( 'samba-tool domain passwordsettings show | grep complexity | sed "s/Password complexity: //"', shell=True).strip() if complexity != pwd_complexity or minimum_password_age != min_pwd_age or maximum_password_age != max_pwd_age: subprocess.call([ 'samba-tool', 'domain', 'passwordsettings', 'set', '--min-pwd-age', minimum_password_age, '--max-pwd-age', maximum_password_age, '--complexity', complexity ]) yield if complexity != pwd_complexity or minimum_password_age != min_pwd_age: subprocess.call([ 'samba-tool', 'domain', 'passwordsettings', 'set', '--min-pwd-age', min_pwd_age, '--max-pwd-age', max_pwd_age, '--complexity', pwd_complexity ])
def move_object(self, modulename, wait_for_replication=True, check_for_drs_replication=False, **kwargs): if not modulename: raise UCSTestUDM_MissingModulename() dn = kwargs.get('dn') if not dn: raise UCSTestUDM_MissingDn() if dn not in self._cleanup.get(modulename, set()): raise UCSTestUDM_CannotModifyExistingObject(dn) cmd = self._build_udm_cmdline(modulename, 'move', kwargs) print('Moving %s object %s' % (modulename, _prettify_cmd(cmd))) child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False) (stdout, stderr) = child.communicate() if child.returncode: raise UCSTestUDM_MoveUDMObjectFailed({'module': modulename, 'kwargs': kwargs, 'returncode': child.returncode, 'stdout': stdout, 'stderr': stderr}) for line in stdout.splitlines(): # :pylint: disable-msg=E1103 if line.startswith('Object modified: '): self._cleanup.get(modulename, []).remove(dn) new_dn = ldap.dn.dn2str(ldap.dn.str2dn(dn)[0:1] + ldap.dn.str2dn(kwargs.get('position', ''))) self._cleanup.setdefault(modulename, []).append(new_dn) break else: raise UCSTestUDM_ModifyUDMUnknownDN({'module': modulename, 'kwargs': kwargs, 'stdout': stdout, 'stderr': stderr}) if wait_for_replication: utils.wait_for_replication(verbose=False) if check_for_drs_replication: if utils.package_installed('univention-samba4'): wait_for_drs_replication(ldap.filter.filter_format('cn=%s', (ldap.dn.str2dn(dn)[0][0][1],))) return new_dn
def wait_for_drs_replication(ldap_filter, attrs=None, base=None, scope=ldb.SCOPE_SUBTREE, lp=None, timeout=360, delta_t=1, verbose=True, should_exist=True, controls=None): if not package_installed('univention-samba4'): if verbose: print('wait_for_drs_replication(): skip, univention-samba4 not installed.') return if not lp: lp = LoadParm() lp.load('/etc/samba/smb.conf') if not attrs: attrs = ['dn'] elif not isinstance(attrs, list): attrs = [attrs] samdb = SamDB("tdb://%s" % lp.private_path("sam.ldb"), session_info=system_session(lp), lp=lp) if not controls: controls = ["domain_scope:0"] if base is None: base = samdb.domain_dn() else: if len(ldap.dn.str2dn(base)[0]) > 1: if verbose: print('wait_for_drs_replication(): skip, multiple RDNs are not supported') return if not base or base == 'None': if verbose: print('wait_for_drs_replication(): skip, no samba domain found') return if verbose: print("Waiting for DRS replication, filter: %r, base: %r, scope: %r, should_exist: %r" % (ldap_filter, base, scope, should_exist), end=' ') t = t0 = time.time() while t < t0 + timeout: try: res = samdb.search(base=base, scope=scope, expression=ldap_filter, attrs=attrs, controls=controls) if res and should_exist: if verbose: print("\nDRS replication took %d seconds" % (t - t0, )) return res if not res and not should_exist: if verbose: print("\nDRS replication took %d seconds" % (t - t0, )) return res except ldb.LdbError as exc: (_num, msg) = exc.args if _num == ldb.ERR_INVALID_DN_SYNTAX: raise if _num == ldb.ERR_NO_SUCH_OBJECT and not should_exist: if verbose: print("\nDRS replication took %d seconds" % (t - t0, )) return print("Error during samdb.search: %s" % (msg, )) print('.', end=' ') time.sleep(delta_t) t = time.time() raise DRSReplicationFailed("DRS replication for filter: %r failed due to timeout after %d sec." % (ldap_filter, t - t0))
def wait_for_drs_replication(ldap_filter, attrs=None, base=None, scope=ldb.SCOPE_SUBTREE, lp=None, timeout=360, delta_t=1, verbose=True): if not package_installed('univention-samba4'): if verbose: print 'wait_for_drs_replication(): skip, univention-samba4 not installed.' return if not lp: lp = LoadParm() lp.load('/etc/samba/smb.conf') if not attrs: attrs = ['dn'] elif not isinstance(attrs, list): attrs = [attrs] samdb = SamDB("tdb://%s" % lp.private_path("sam.ldb"), session_info=system_session(lp), lp=lp) controls = ["domain_scope:0"] if base is None: base = samdb.domain_dn() if not base or base == 'None': if verbose: print 'wait_for_drs_replication(): skip, no samba domain found' return if verbose: print "Waiting for DRS replication, filter: '%s'" % (ldap_filter, ), t = t0 = time.time() while t < t0 + timeout: try: res = samdb.search(base=base, scope=scope, expression=ldap_filter, attrs=attrs, controls=controls) if res: if verbose: print "\nDRS replication took %d seconds" % (t - t0, ) return res except ldb.LdbError as (_num, msg): print "Error during samdb.search: %s" % (msg, ) print '.', time.sleep(delta_t) t = time.time()
def modify_object(self, modulename, wait_for_replication=True, check_for_drs_replication=False, **kwargs): """ Modifies a LDAP object via UDM. Values for UDM properties can be passed via keyword arguments only and have to exactly match UDM property names (case-sensitive!). Please note: the object has to be created by create_object otherwise this call will raise an exception! :param str modulename: name of UDM module (e.g. 'users/user') """ if not modulename: raise UCSTestUDM_MissingModulename() dn = kwargs.get('dn') if not dn: raise UCSTestUDM_MissingDn() if dn not in self._cleanup.get(modulename, set()): raise UCSTestUDM_CannotModifyExistingObject(dn) cmd = self._build_udm_cmdline(modulename, 'modify', kwargs) print('Modifying %s object with %s' % (modulename, _prettify_cmd(cmd))) child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False) (stdout, stderr) = child.communicate() if child.returncode: raise UCSTestUDM_ModifyUDMObjectFailed({'module': modulename, 'kwargs': kwargs, 'returncode': child.returncode, 'stdout': stdout, 'stderr': stderr}) for line in stdout.splitlines(): # :pylint: disable-msg=E1103 if line.startswith('Object modified: '): dn = line.split('Object modified: ', 1)[-1] if dn != kwargs.get('dn'): print('modrdn detected: %r ==> %r' % (kwargs.get('dn'), dn)) if kwargs.get('dn') in self._cleanup.get(modulename, []): self._cleanup.setdefault(modulename, []).append(dn) self._cleanup[modulename].remove(kwargs.get('dn')) break elif line.startswith('No modification: '): raise UCSTestUDM_NoModification({'module': modulename, 'kwargs': kwargs, 'stdout': stdout, 'stderr': stderr}) else: raise UCSTestUDM_ModifyUDMUnknownDN({'module': modulename, 'kwargs': kwargs, 'stdout': stdout, 'stderr': stderr}) if wait_for_replication: utils.wait_for_replication(verbose=False) if check_for_drs_replication: if utils.package_installed('univention-samba4'): wait_for_drs_replication(ldap.filter.filter_format('cn=%s', (ldap.dn.str2dn(dn)[0][0][1],))) return dn
def force_drs_replication(source_dc=None, destination_dc=None, partition_dn=None, direction="in"): # type: (Optional[str], Optional[str], Optional[str], str) -> int if not package_installed('univention-samba4'): print('force_drs_replication(): skip, univention-samba4 not installed.') return 0 src = source_dc or get_available_s4connector_dc() if not src: return 1 dst = destination_dc or socket.gethostname() if src == dst: return 0 if not partition_dn: ucr = config_registry.ConfigRegistry() ucr.load() partition_dn = str(ucr.get('samba4/ldap/base')) print("USING partition_dn:", partition_dn) cmd = ("/usr/bin/samba-tool", "drs", "replicate", dst, src, partition_dn) return subprocess.call(cmd)
def create_object(self, modulename, wait_for_replication=True, check_for_drs_replication=False, **kwargs): r""" Creates a LDAP object via UDM. Values for UDM properties can be passed via keyword arguments only and have to exactly match UDM property names (case-sensitive!). :param str modulename: name of UDM module (e.g. 'users/user') :param bool wait_for_replication: delay return until Listener has settled. :param bool check_for_drs_replication: delay return until Samab4 has settled. :param \*\*kwargs: """ if not modulename: raise UCSTestUDM_MissingModulename() dn = None cmd = self._build_udm_cmdline(modulename, 'create', kwargs) print('Creating %s object with %s' % (modulename, _prettify_cmd(cmd))) child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False) (stdout, stderr) = child.communicate() if child.returncode: raise UCSTestUDM_CreateUDMObjectFailed({'module': modulename, 'kwargs': kwargs, 'returncode': child.returncode, 'stdout': stdout, 'stderr': stderr}) # find DN of freshly created object and add it to cleanup list for line in stdout.splitlines(): # :pylint: disable-msg=E1103 if line.startswith('Object created: ') or line.startswith('Object exists: '): dn = line.split(': ', 1)[-1] if not line.startswith('Object exists: '): self._cleanup.setdefault(modulename, []).append(dn) break else: raise UCSTestUDM_CreateUDMUnknownDN({'module': modulename, 'kwargs': kwargs, 'stdout': stdout, 'stderr': stderr}) if wait_for_replication: utils.wait_for_replication(verbose=False) if check_for_drs_replication: if utils.package_installed('univention-samba4'): if "options" not in kwargs or "kerberos" in kwargs["options"]: wait_for_drs_replication(ldap.filter.filter_format('cn=%s', (ldap.dn.str2dn(dn)[0][0][1],))) return dn
def append_dot(verify_list): """The S4-Connector appends dots to various dns records. Helper function to adjust a list.""" if not package_installed('univention-s4-connector'): return verify_list return ['%s.' % (x, ) for x in verify_list]
def wait_for_s4connector(timeout=360, delta_t=1, s4cooldown_t=10): ucr = config_registry.ConfigRegistry() ucr.load() if not package_installed('univention-s4-connector'): print( 'wait_for_s4connector(): skip, univention-s4-connector not installed.' ) return if ucr.is_false('connector/s4/autostart'): print( 'wait_for_s4connector(): skip, connector/s4/autostart is set to false.' ) return conn = sqlite3.connect('/etc/univention/connector/s4internal.sqlite') c = conn.cursor() static_count = 0 highestCommittedUSN = -1 lastUSN = -1 t = t0 = time.time() while t < t0 + timeout: time.sleep(delta_t) if not _ldap_replication_complete(): continue previous_highestCommittedUSN = highestCommittedUSN highestCommittedUSN = -1 ldbresult = subprocess.check_output([ 'ldbsearch', '--url', '/var/lib/samba/private/sam.ldb', '--scope', 'base', '--basedn', '', 'highestCommittedUSN', ]) for line in ldbresult.split('\n'): line = line.strip() if line.startswith('highestCommittedUSN: '): highestCommittedUSN = line.replace('highestCommittedUSN: ', '') break else: raise KeyError('No highestCommittedUSN in ldbsearch') previous_lastUSN = lastUSN c.execute('select value from S4 where key=="lastUSN"') lastUSN = c.fetchone()[0] print('highestCommittedUSN: {}'.format(highestCommittedUSN)) print('lastUSN: {}'.format(lastUSN)) if not (lastUSN == highestCommittedUSN and lastUSN == previous_lastUSN and highestCommittedUSN == previous_highestCommittedUSN): static_count = 0 print('Reset counter') else: static_count = static_count + 1 print('Counter: %d' % static_count) if static_count * delta_t >= s4cooldown_t: return 0 t = time.time() conn.close() raise WaitForS4ConnectorTimeout()
import random import re import subprocess import time import os import sys import shlex import ldap.dn import pytest import univention.testing.strings as uts import univention.testing.ucr import univention.testing.utils as utils printserver_installed = utils.package_installed('univention-printserver') samba_common_bin_installed = utils.package_installed('samba-common-bin') PRINTER_PROTOCOLS = ['usb://', 'ipp://', 'socket://', 'parallel://', 'http://'] def random_fqdn( ucr): # type: (univention.testing.ucr.UCSTestConfigRegistry) -> str return '%s.%s' % (uts.random_name(), ucr.get('domainname')) @pytest.mark.tags('udm') @pytest.mark.roles('domaincontroller_master', 'domaincontroller_backup', 'domaincontroller_slave', 'memberserver') @pytest.mark.exposure('careful') def test_create_printer(ucr, udm):
def test_create_printer_and_check_printing_works(ucr, udm): """Create shares/printer and check if print access works""" ucr.load() admin_dn = ucr.get( 'tests/domainadmin/account', 'uid=Administrator,cn=users,%s' % (ucr.get('ldap/base'), )) admin_name = ldap.dn.str2dn(admin_dn)[0][0][1] password = ucr.get('tests/domainadmin/pwd', 'univention') spoolhost = '.'.join([ucr['hostname'], ucr['domainname']]) acltype = random.choice(['allow all', 'allow']) properties = { 'name': uts.random_name(), 'location': uts.random_string(), 'description': uts.random_name(), 'spoolHost': spoolhost, 'uri': '%s %s' % ( random.choice(PRINTER_PROTOCOLS), uts.random_ip(), ), 'model': 'hp-ppd/HP/HP_Business_Inkjet_2500C_Series.ppd', 'producer': 'cn=Generic,cn=cups,cn=univention,%s' % (ucr.get('ldap/base'), ), 'sambaName': uts.random_name(), 'ACLtype': acltype, 'ACLUsers': admin_dn, 'ACLGroups': 'cn=Printer Admins,cn=groups,%s' % (ucr.get('ldap/base'), ), } print('*** Create shares/printer object') print_share_dn = udm.create_object('shares/printer', position='cn=printers,%s' % (ucr['ldap/base'], ), **properties) utils.verify_ldap_object(print_share_dn, { 'cn': [properties['name']], 'description': [properties['description']], 'univentionObjectType': ['shares/printer'], 'univentionPrinterACLGroups': [properties['ACLGroups']], 'univentionPrinterACLUsers': [properties['ACLUsers']], 'univentionPrinterACLtype': [properties['ACLtype']], 'univentionPrinterLocation': [properties['location']], 'univentionPrinterModel': [properties['model']], 'univentionPrinterSambaName': [properties['sambaName']], 'univentionPrinterSpoolHost': [properties['spoolHost']], 'univentionPrinterURI': [properties['uri'].replace(' ', '')], }, delay=1) print('*** Modify shares/printer samba share name') properties['sambaName'] = uts.random_name() udm.modify_object('shares/printer', dn=print_share_dn, sambaName=properties['sambaName']) utils.verify_ldap_object( print_share_dn, {'univentionPrinterSambaName': [properties['sambaName']]}, delay=1) delay = 15 print('*** Wait %s seconds for listener postrun' % delay) time.sleep(delay) p = subprocess.Popen(['lpq', '-P', properties['name']], close_fds=True) p.wait() assert not p.returncode, "CUPS printer {} not created after {} seconds".format( properties['name'], delay) p = subprocess.Popen( ['su', admin_name, '-c', 'lpr -P %s /etc/hosts' % properties['name']], close_fds=True) p.wait() assert not p.returncode, "Printing to CUPS printer {} as {} failed".format( properties['name'], admin_name) s4_dc_installed = utils.package_installed("univention-samba4") s3_file_and_print_server_installed = utils.package_installed( "univention-samba") smb_server = s3_file_and_print_server_installed or s4_dc_installed if smb_server: delay = 1 time.sleep(delay) cmd = [ 'smbclient', '//localhost/%s' % properties['sambaName'], '-U', '%'.join([admin_name, password]), '-c', 'print /etc/hosts' ] print('\nRunning: %s' % ' '.join(cmd)) p = subprocess.Popen(cmd, close_fds=True) p.wait() if p.returncode: share_definition = '/etc/samba/printers.conf.d/%s' % properties[ 'sambaName'] with open(share_definition) as f: print('### Samba share file %s :' % share_definition) print(f.read()) print('### testpam for that smb.conf section:') p = subprocess.Popen( ['testparm', '-s', '--section-name', properties['sambaName']], close_fds=True) p.wait() assert False, 'Samba printer share {} not accessible'.format( properties['sambaName']) p = subprocess.Popen(['lprm', '-P', properties['name'], '-'], close_fds=True) p.wait()
#!/usr/share/ucs-test/runner /usr/bin/py.test -s ## desc: Test UMC authentication with expired accounts ## exposure: dangerous ## packages: [univention-management-console-server] ## roles: [domaincontroller_master, domaincontroller_backup] ## tags: [skip_admember] import pytest from univention.testing import utils # TODO: test detection of expired password + account disabled + both # TODO: test password history, complexity, length samba4_installed = utils.package_installed('univention-samba4') class TestPwdChangeNextLogin(object): """ Ensure that the UMC PAM configuration for pam_unix.so + pam_krb5.so is correct. This is tested by UMC authenticating a user with pwdChangeNextLogin=1 pam_ldap is therefore untested! """ PWD_CHANGE_NEXT_LOGIN_OPTIONS = [ [], # TODO: test without mail, person, ] @pytest.mark.parametrize('options', PWD_CHANGE_NEXT_LOGIN_OPTIONS) def test_expired_password_detection_create_pwdchangenextlogin( self, options, udm, Client, random_string, Unauthorized): print 'test_expired_password_detection_create_pwdchangenextlogin(%r)' % ( options, )
def test_container_cn_rename_uppercase_with_special_characters( self, udm, ucr): """Rename a container/cn with subobjects from lower to upper case""" if utils.package_installed('univention-s4-connector'): # this test is not stable with the s4-connector # somehow we end up with # # Creating container/cn object with /usr/sbin/udm-test container/cn create --position dc=four,dc=four --set 'name=ĝkn}_>ä%\6' # Waiting for connector replication # Modifying container/cn object with /usr/sbin/udm-test container/cn modify --dn 'cn=ĝkn}_\>ä%\\6,dc=four,dc=four' --set 'name=ĝKN}_>ä%\6' # modrdn detected: 'cn=\xc4\x9dkn}_\\>\xc3\xa4%\\\\6,dc=four,dc=four' ==> 'cn=\xc4\x9dKN}_\\>\xc3\xa4%\\\\6,dc=four,dc=four' # Waiting for connector replication # ### FAIL ### # #cn = ĝkn}_>ä%\6; expected: ĝKN}_>ä%\6 pytest.skip('S4-Connector') def test_container(parent, add_user): if parent is None: parent = ucr.get('ldap/base') user_name = 'X' + uts.random_string( ) # test preserving name (case sensitivity) cn_name = uts.random_name_special_characters() cn_name_new = cn_name.upper() cn = udm.create_object('container/cn', position=parent, name=cn_name) if add_user: udm.create_user(position=cn, username=user_name) try: udm.modify_object('container/cn', dn=cn, name=cn_name_new) except AssertionError: pass lo = utils.get_ldap_connection() for dn, entry in lo.search(filter='ou=temporary_move_container_*'): to_be_removed = udm._cleanup.setdefault('container/ou', []) to_be_removed.append(dn) assert False, 'ou = %s remained' % dn new_cn = 'cn=%s,%s' % (ldap.dn.escape_dn_chars(cn_name_new), parent) new_user = '******' % (ldap.dn.escape_dn_chars(user_name), new_cn) utils.verify_ldap_object(new_cn, should_exist=True) if add_user: for dn, entry in lo.search(filter=ldap.filter.filter_format( 'uid=%s', [user_name])): assert entry.get('uid')[0] == user_name.encode( 'UTF-8' ), 'CASE SENSITIVITY: uid = %s; expected: %s' % ( entry.get('uid')[0], user_name) utils.verify_ldap_object(new_user, should_exist=True) for dn, entry in lo.search( filter=ldap.filter.filter_format('cn=%s', [cn_name_new])): assert entry.get('cn')[0] == cn_name_new.encode( 'UTF-8'), 'cn = %s; expected: %s' % (entry.get('cn')[0], cn_name_new) return new_cn # EMPTY # FIRST LEVEL first_level_container = test_container(parent=None, add_user=False) # SECOND LEVEL test_container(parent=first_level_container, add_user=False) # WITH USER # FIRST LEVEL first_level_container = test_container(parent=None, add_user=True) # SECOND LEVEL test_container(parent=first_level_container, add_user=True)
def wait_for_s4connector(timeout=360, delta_t=1, s4cooldown_t=5): # type: (int, int, int) -> int ucr = config_registry.ConfigRegistry() ucr.load() if not package_installed('univention-s4-connector'): print('wait_for_s4connector(): skip, univention-s4-connector not installed.') return 0 if ucr.is_false('connector/s4/autostart'): print('wait_for_s4connector(): skip, connector/s4/autostart is set to false.') return 0 conn = sqlite3.connect('/etc/univention/connector/s4internal.sqlite') c = conn.cursor() static_count = 0 replication_complete = False highestCommittedUSN = -1 lastUSN = -1 t = t0 = time.time() while t < t0 + timeout: time.sleep(delta_t) if not _ldap_replication_complete(verbose=False): continue else: if not replication_complete: print('Start waiting for S4-Connector replication') replication_complete = True previous_highestCommittedUSN = highestCommittedUSN ldbresult = subprocess.Popen([ 'ldbsearch', '--url', '/var/lib/samba/private/sam.ldb', '--scope', 'base', '--basedn', '', 'highestCommittedUSN', ], stdout=subprocess.PIPE) assert ldbresult.stdout for chunk in ldbresult.stdout: line = chunk.decode('utf-8').strip() if line.startswith('highestCommittedUSN: '): highestCommittedUSN = int(line[len('highestCommittedUSN: '):]) break else: raise KeyError('No highestCommittedUSN in ldbsearch') previous_lastUSN = lastUSN c.execute('select value from S4 where key=="lastUSN"') lastUSN = int(c.fetchone()[0]) if not (lastUSN == highestCommittedUSN and lastUSN == previous_lastUSN and highestCommittedUSN == previous_highestCommittedUSN): static_count = 0 print('Reset counter') else: static_count += 1 print('Counter: {}; highestCommittedUSN: {!r}; lastUSN: {!r}'.format(static_count, highestCommittedUSN, lastUSN)) if static_count * delta_t >= s4cooldown_t: return 0 t = time.time() conn.close() raise WaitForS4ConnectorTimeout()
def wait_for_s4connector(): ucr = config_registry.ConfigRegistry() ucr.load() if not package_installed('univention-s4-connector'): print 'wait_for_s4connector(): skip, univention-s4-connector not installed.' return if ucr.is_false('connector/s4/autostart'): print 'wait_for_s4connector(): skip, connector/s4/autostart is set to false.' return conn = sqlite3.connect('/etc/univention/connector/s4internal.sqlite') c = conn.cursor() static_count = 0 highestCommittedUSN = -1 lastUSN = -1 while static_count < CONNECTOR_WAIT_INTERVAL: time.sleep(CONNECTOR_WAIT_SLEEP) if not _ldap_replication_complete(): continue previous_highestCommittedUSN = highestCommittedUSN highestCommittedUSN = -1 ldbsearch = subprocess.Popen( "ldbsearch -H /var/lib/samba/private/sam.ldb -s base -b '' highestCommittedUSN", shell=True, stdout=subprocess.PIPE) ldbresult = ldbsearch.communicate() for line in ldbresult[0].split('\n'): line = line.strip() if line.startswith('highestCommittedUSN: '): highestCommittedUSN = line.replace('highestCommittedUSN: ', '') break print highestCommittedUSN previous_lastUSN = lastUSN try: c.execute('select value from S4 where key=="lastUSN"') except sqlite3.OperationalError as e: static_count = 0 print 'Reset counter: sqlite3.OperationalError: %s' % e print 'Counter: %d' % static_count continue conn.commit() lastUSN = c.fetchone()[0] if not (lastUSN == highestCommittedUSN and lastUSN == previous_lastUSN and highestCommittedUSN == previous_highestCommittedUSN): static_count = 0 print 'Reset counter' else: static_count = static_count + 1 print 'Counter: %d' % static_count conn.close() return 0