diff --git a/ucs-school-umc-installer/umc/python/schoolinstaller/__init__.py b/ucs-school-umc-installer/umc/python/schoolinstaller/__init__.py index 81f37f7..6447c16 100644 --- a/ucs-school-umc-installer/umc/python/schoolinstaller/__init__.py +++ b/ucs-school-umc-installer/umc/python/schoolinstaller/__init__.py @@ -43,6 +43,8 @@ import traceback import ast import urllib import filecmp +import fcntl +import errno # related third party import notifier @@ -359,19 +361,14 @@ def system_join(username, password, info_handler = _dummyFunc, error_handler = _ process = subprocess.Popen(['/usr/sbin/univention-run-join-scripts', '-dcaccount', username, '-dcpwd', passwordFile.name], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) failedJoinScripts = [] - while True: - # get the next line - line = process.stdout.readline() - if not line: - # no more text from stdout - break - MODULE.process(line.strip()) + def parse(line): + MODULE.process(repr(line.strip()).strip('"\'')) # parse output... first check for errors m = regError.match(line) if m: error_handler(_('Software packages have been installed, however, the system join could not be completed: %s. More details can be found in the log file /var/log/univention/join.log. Please retry the join process via the UMC module "Domain join" after resolving any conflicting issues.') % m.groupdict().get('message')) - continue + return # check for currently called join script m = regJoinScript.match(line) @@ -380,13 +377,37 @@ def system_join(username, password, info_handler = _dummyFunc, error_handler = _ step_handler(stepsPerScript) if 'failed' in line: failedJoinScripts.append(m.groupdict().get('script')) - continue + return # check for other information m = regInfo.match(line) if m: info_handler(m.groupdict().get('message')) - continue + return + + # make stdout file descriptor of the process non-blocking + fd = process.stdout.fileno() + fl = fcntl.fcntl(fd, fcntl.F_GETFL) + fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) + + unfinished_line = '' + while True: + # get the next line + try: + line = process.stdout.read() + except IOError as exc: + if exc.errno == errno.EAGAIN: + continue + raise + + if not line: + break # no more text from stdout + + unfinished_line = '' if line.endswith('\n') else '%s%s' % (unfinished_line, line.rsplit('\n', 1)[-1]) + for line in line.splitlines(): + parse(line) + if unfinished_line: + parse(unfinished_line) # get all remaining output stdout, stderr = process.communicate()