#!/usr/bin/env python # -*- coding: utf-8 -*- # # univention-support-info - collect system information # # Copyright 2011 Univention GmbH # # http://www.univention.de/ # # All rights reserved. # # The source code of this program is made available # under the terms of the GNU Affero General Public License version 3 # (GNU AGPL V3) as published by the Free Software Foundation. # # Binary versions of this program provided by Univention to you as # well as other copyrighted, protected or trademarked materials like # Logos, graphics, fonts, specific documentations and configurations, # cryptographic keys etc. are subject to a license agreement between # you and Univention and not subject to the GNU AGPL V3. # # In the case you use this program under the terms of the GNU AGPL V3, # the program is provided 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 Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public # License with the Debian GNU/Linux or Univention distribution in file # /usr/share/common-licenses/AGPL-3; if not, see # . keyID = '18B913ABF3C1550B8C2DFDA994F01970E89E3BEC' # create with: gpg --armor --export --export-options export-minimal $keyID keyData = '\n'.join(('-----BEGIN PGP PUBLIC KEY BLOCK-----', 'Version: GnuPG v1.4.9 (GNU/Linux)', '', 'mQGiBEA2RhgRBADee7hGh5TPPwqs+z5tfLett9xaVxmRkUfBvqesVIj93WzrKsU3', 'S7hjnMlh+JieFjJLy6jTJYtvqqFIxh3vw5btCwhntrTQnu00U/r3UdznqE/zGH2L', 'A734aHaSaq6UFKE5kwX0DECgSI1hwc20d7guLJXSqOpwfYktXiB+27GRCwCgh4OR', 'MWncPkhaJhusO8YCSnSN0GED/2ez8utubP1FloTfTof4/OLfBvPwdgJ5Q7FRqeF9', 'wDmfd8Hetzr+Fh4zMs6dY0c5+unUQiLXjY9F01WT7SM+yFrs5EHzb+gyjIdTmTtn', 'mtNTL2cZK8freAv9LPWCHfQ1rii+Qd71+/CKLDfwwLqQxEAkOsrpOsUD4dip6vkm', 'ZtaRBACUYoOtB738OzjPqOpbnmNQjQYVtGCocDjfKs+bMyq+LPOyC31NVC4LvqhC', 'nwXSUSy8jfXLzInPXgEUiHvGAEvnNzRLAIh6W/pIaK7tIITESmV/C3PBvxLEkJNm', '8Ll+2qGVspYnGTUFe6JzxARzcTVow4JlB+dX40bk7LNqUe6Au7QqVW5pdmVudGlv', 'biBTdXBwb3J0IDxzdXBwb3J0QHVuaXZlbnRpb24uZGU+iF4EExECAB4GCwkIBwMC', 'AxUCAwMWAgECHgECF4AFAkm+NOYCGQEACgkQlPAZcOieO+xhXwCfdZ7+eWGpJfhz', 'CnrfuzgdzqsetMMAn3oUbDZCqzH083DKCNS5547V8XkCtCpVbml2ZW50aW9uIFN1', 'cHBvcnQgPHNlcnZpY2VAdW5pdmVudGlvbi5kZT6IYAQTEQIAIAUCSNdW8wIbIwYL', 'CQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEJTwGXDonjvsQcoAn2b9FNPECtPus0Sf', '3ENGafyXSIq7AJ9sbNm+QryXW1rtvtsHlNgYI9eGpLQrVW5pdmVudGlvbiBTdXBw', 'b3J0IDxmZWVkYmFja0B1bml2ZW50aW9uLmRlPohgBBMRAgAgBQJI11aYAhsjBgsJ', 'CAcDAgQVAggDBBYCAwECHgECF4AACgkQlPAZcOieO+wmzACfVmZKVc37T7W9FQGN', 'K+dXsLbDplkAniAYh0l9Nd8wMh/QZrxcRdlgOBrhtDRVbml2ZW50aW9uIFN1cHBv', 'cnQgPHBhcnRuZXItdGVjaG5pY2FsQHVuaXZlbnRpb24uZGU+iGAEExECACAFAkho', 'p9gCGyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU8Blw6J477IMYAJ9oZoTS', 'vHsxF7TYJSGo3pcutuV4RACfbxLxxjU7suCGs+khvINRl9pJel60KlVuaXZlbnRp', 'b24gU2VydmljZSA8c2VydmljZUB1bml2ZW50aW9uLmRlPohgBBMRAgAgBQJJvjVV', 'AhsjBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQlPAZcOieO+ycGwCeM8pJxUrL', 'oiKylTxiKZ4MwQoV/L0An3y/9GafqT8SaUgSjYO+9P4szWATtCtQYXJ0bmVyLUxp', 'c3RzIDxwYXJ0bmVyLWxpc3RzQHVuaXZlbnRpb24uZGU+iGAEExECACAFAkm+NQEC', 'GyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU8Blw6J477C67AJ93Pv9Dcq7g', 'HreBv3f1Q07IjDI3bACfUZgClXNISIewXER8FzV5cC08LRm0LFVuaXZlbnRpb24g', 'RmVlZGJhY2sgPGZlZWRiYWNrQHVuaXZlbnRpb24uZGU+iGAEExECACAFAkm+NSsC', 'GyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU8Blw6J477E8QAJ0XE91GawgL', 'lVGfeiiT7c32P35IDACePCNLSzHA6K6JrV7CP98BeZUUNYu0LFVuaXZlbnRpb24g', 'SGVscGRlc2sgPGhlbHBkZXNrQHVuaXZlbnRpb24uZGU+iGAEExECACAFAkm+NUMC', 'GyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU8Blw6J477JNxAJ4l9wqf+WtV', 'C0sAtu91aGWvgW/JQACfTJUCWf1DTqn1sDhbNiCG2jA+B9K0LFVuaXZlbnRpb24g', 'VmVydHJpZWIgPHZlcnRyaWViQHVuaXZlbnRpb24uZGU+iGAEExECACAFAkm+NWwC', 'GyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU8Blw6J477Jq3AJ9fN/6oKbqY', 'exKHPdLQw31wC8HGTgCfZ5gn5zDd2JSY9tirDtMw5SSdfk20M1BhcnRuZXItVGVj', 'aG5pY2FsIDxwYXJ0bmVyLXRlY2huaWNhbEB1bml2ZW50aW9uLmRlPohgBBMRAgAg', 'BQJJvjUPAhsjBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQlPAZcOieO+wlNQCf', 'eZ7Z4PeCx7SF+k1CK0bC8oouICkAn3/NYT1ASQLFP8CBqku1shs1lFCstDNQcmVt', 'aXVtLVRlY2huaWNhbCA8cHJlbWl1bS10ZWNobmljYWxAdW5pdmVudGlvbi5kZT6I', 'YAQTEQIAIAUCSb41GgIbIwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEJTwGXDo', 'njvsxqcAnjRmgwWtXJqEbptTSSkaamNmGp9KAJ0R7b4RYDSKr+aFGPhhgetqLNXO', 'MrQwVW5pdmVudGlvbiBPWCBTdXBwb3J0IDxveC1zdXBwb3J0QHVuaXZlbnRpb24u', 'ZGU+iGAEExECACAFAk1GmXcCGyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU', '8Blw6J477JwmAJ9WeeR2SzUtHY7pPolhm4fQmtM20QCfaebVO97CHdKkcAqPjJ3K', 'RwWVtpC5AQ0EQDZGGxAEAJotyyct6jvNscl9q2stDB+BUuXefdd7UMdSySSGqt5c', '7f/6IEX/eiG/2nIsqX1IsSQ+Bw0ZQTQUhgI8hICUsmjdjvWnBCyHX8xnMESITDv/', 'fJmxgaP8fbMSJexhnizjlz8m74OgnfFew6EuRWRXA/SDeTwmsaUafTv7biKaDlU7', 'AAMFA/9hJUqdh+tSaEfwUzPgHdFT8EIM2B0VSmVnqHSWwCjuJTLTWJi+DDe2hq7p', 'QPpcATzgEg5qu5lsqh0AAXV998fD/RiO3B+ct1rwYbNlchACIXtgDTe43dmUaKkp', 'fPRxeQZr8iym706LJOyppF+jXqOm2oy6Sf++/YElcCBmPPDIwIhGBBgRAgAGBQJA', 'NkYbAAoJEJTwGXDonjvsqD0AnRVxlYyWk3DrKL0ZCxRZrtpW6pbwAJ9R/HZLaaH+', '043H7VXVPPTjhs6Tig==', '=BE0y', '-----END PGP PUBLIC KEY BLOCK-----', )) toprc = '\n'.join(('RCfile for "top with windows" # shameless braggin\'', 'Id:a, Mode_altscr=0, Mode_irixps=1, Delay_time=3.000, Curwin=0', 'Def fieldscur=AEHIOQTWKNMbcdfgjplrsuvyzX', ' winflags=62905, sortindx=10, maxtasks=0', ' summclr=1, msgsclr=1, headclr=3, taskclr=1', 'Job fieldscur=ABcefgjlrstuvyzMKNHIWOPQDX', ' winflags=62777, sortindx=0, maxtasks=0', ' summclr=6, msgsclr=6, headclr=7, taskclr=6', 'Mem fieldscur=ANOPQRSTUVbcdefgjlmyzWHIKX', ' winflags=62777, sortindx=13, maxtasks=0', ' summclr=5, msgsclr=5, headclr=4, taskclr=5', 'Usr fieldscur=ABDECGfhijlopqrstuvyzMKNWX', ' winflags=62777, sortindx=4, maxtasks=0', ' summclr=3, msgsclr=3, headclr=2, taskclr=3', '', )) import cStringIO import glob import gzip import optparse import os import shutil import socket import stat import subprocess import sys import tarfile import tempfile import time def Popen(CommandTuple, Input=None): try: process = subprocess.Popen(CommandTuple, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, env=env) (stdoutdata, stderrdata) = process.communicate(input=Input) return (process.returncode, stdoutdata, stderrdata) except (OSError, IOError), error: return ('Could not execute %s: %s' % (repr(CommandTuple), repr(' '.join(map(str, error.args)))), '', '') timeString = time.strftime('%Y-%m-%d_%H-%M-%SZ', time.gmtime()) hostname = socket.gethostname() def addFile(name, size, fileobj): info = tarfile.TarInfo() info.size = size info.name = 'univention-support-info-' + hostname + '-' + timeString + '/' + name info.mode = stat.S_IRUSR info.mtime = time.time() archive.addfile(info, fileobj) def addFileByPath(filename): try: fileobj = open(filename, 'rb') except (OSError, IOError), error: error = '\n'.join(map(str, error.args)) addFile('files/' + filename.strip('/').replace('/', '_') + '.ERROR', len(error), cStringIO.StringIO(error)) else: addFile('files/' + filename.strip('/').replace('/', '_'), os.stat(filename).st_size, fileobj) fileobj.close() def certificateValidity(CertificatePath): try: import M2Crypto except ImportError, error: error = '\n'.join(map(str, error.args)) addFile('info/ssl/' + CertificatePath.strip('/').replace('/', '_') + '.ERROR', len(error), cStringIO.StringIO(error)) return try: cert = M2Crypto.X509.load_cert(CertificatePath) validity = '%s\nNot Before: %s\nNot After : %s\n' % (CertificatePath, cert.get_not_before(), cert.get_not_after(), ) addFile('info/ssl/' + CertificatePath.strip('/').replace('/', '_'), len(validity), cStringIO.StringIO(validity)) except (OSError, IOError, M2Crypto.X509.X509Error), error: error = '\n'.join(map(str, error.args)) addFile('info/ssl/' + CertificatePath.strip('/').replace('/', '_') + '.ERROR', len(error), cStringIO.StringIO(error)) def certificateValidities(): CertificatePatterns = [ '/etc/univention/ssl/*.*/cert.pem', '/etc/univention/ssl/ucsCA/CAcert.pem', ] for CertificatePattern in CertificatePatterns: for CertificatePath in glob.glob(CertificatePattern): certificateValidity(CertificatePath) def simpleFiles(): FilePatterns = [ '/boot/config-*', '/etc/apache2/*', '/etc/apache2/*/*', '/etc/apt/sources.list', '/etc/apt/sources.list.d/*', '/etc/apt/mirror.list', '/etc/cron*/*', '/etc/fstab', '/etc/imapd/*', '/etc/mtab', '/etc/passwd', '/etc/procmailrc', '/etc/spamassassin/*', '/etc/univention/installation_profile', '/opt/open-xchange/etc/*', '/opt/open-xchange/etc/*/*', '/opt/open-xchange/etc/*/*/*', '/proc/mounts', '/var/lib/univention-directory-replication/failed.ldif', ] Files = set() for FilePattern in FilePatterns: for Filename in glob.glob(FilePattern): Files.add(Filename) for Filename in sorted(list(Files)): if os.path.isfile(Filename): addFileByPath(Filename) def executeCommand(commandName, command, log_stderr = False): (exitcode, stdout, stderr, ) = Popen(command) if exitcode or log_stderr: if type(exitcode) is int: stderr += '\nExitcode was %d\n' % exitcode else: stderr += exitcode + '\n' addFile('info/' + commandName + '.stderr', len(stderr), cStringIO.StringIO(stderr)) return stdout def templateFiles(): stdout = executeCommand('check-templates', ('/usr/bin/find', '/etc/univention/templates/files/', '(', '-name', '*.dpkg-new', '-o', '-name', '*.dpkg-dist', ')', '-print0', )) files = [templatefile for templatefile in stdout.split('\0') if templatefile] message = ('Found %d:\n' % len(files)) + '\n'.join(files) + '\n' addFile('info/check-templates', len(message), cStringIO.StringIO(message)) for templatefile in files: addFileByPath(templatefile) if templatefile.endswith('.dpkg-new'): addFileByPath(templatefile[:-len('.dpkg-new')]) elif templatefile.endswith('.dpkg-dist'): addFileByPath(templatefile[:-len('.dpkg-dist')]) def collectData(): commands = {'hostname-f': ('/bin/hostname', '--fqdn', ), 'ifconfig-a': ('/sbin/ifconfig', '-v', '-a', ), 'iptables-L_filter': ('/sbin/iptables', '-L', '-n', '-v', '-t', 'filter', ), 'iptables-L_nat': ('/sbin/iptables', '-L', '-n', '-v', '-t', 'nat', ), 'iptables-L_mangle': ('/sbin/iptables', '-L', '-n', '-v', '-t', 'mangle', ), 'iptables-L_raw': ('/sbin/iptables', '-L', '-n', '-v', '-t', 'raw', ), 'iptables-save': ('/sbin/iptables-save', '-c', ), 'route-4': ('/sbin/route', '-v', '-ee', '-n', '-A', 'inet', ), 'route-6': ('/sbin/route', '-v', '-ee', '-n', '-A', 'inet6', ), 'netstat': ('/bin/netstat', '--tcp', '--udp', '--listening', '--program', '--extend', '--extend', '--verbose', '--timers', '--numeric', '--wide', ), 'dpkg-l': ('/usr/bin/dpkg-query', '--show', '--showformat=${Status}\t${Package}\t${Version}\n', ), 'dpkg--audit': ('/usr/bin/dpkg', '--audit', ), 'uname': ('/bin/uname', '-a', ), 'ps': ('/bin/ps', '-AHFly', ), 'ps-full': ('/bin/ps', '-ALwwo', 'stat,pid,ppid,sid,tty,nlwp,lwp,pri,ni,sched,wchan,vsz,rss,sz,pcpu,pmem,cmd,blocked,caught,ignored,pending,lstart,cls,time,flags,uid,user,ruid,ruser,suid,suser,gid,group,rgid,rgroup,sgid,sgroup', ), 'ucr-dump': ('/usr/sbin/univention-config-registry', 'dump', ), 'df-full': ('/bin/df', '--portability', '--print-type', ), 'df-i-full': ('/bin/df', '--portability', '--print-type', '--inodes', ), 'df': ('/bin/df', '-h', ), 'df-i': ('/bin/df', '-h', '-i', ), 'join-status': ('/usr/sbin/univention-check-join-status', ), 'virsh-qemu': ('/usr/bin/virsh', '-c', 'qemu:///system', 'capabilities', ), 'virsh-xen': ('/usr/bin/virsh', '-c', 'xen:///', 'capabilities', ), 'test-join': ('/usr/bin/net', 'rpc', 'testjoin', ), 'top': ('/usr/bin/top', '-b', '-n2', ), 'testparm': (('/usr/bin/testparm', '-s', '-vvv', ), True), 'listenerID': ('/bin/cat', '/var/lib/univention-directory-listener/notifier_id', ), 'notifierID': ('/usr/share/univention-directory-listener/get_notifier_id.py', ), } for commandName in commands: command = commands[commandName] if type(command[0]) == tuple: stdout = executeCommand(commandName, command[0], command[1]) else: stdout = executeCommand(commandName, command) addFile('info/' + commandName, len(stdout), cStringIO.StringIO(stdout)) def univentionSystemInfo(): manu = executeCommand('dmidecode', ('/usr/sbin/dmidecode', '-s', 'system-manufacturer')) product = executeCommand('dmidecode', ('/usr/sbin/dmidecode', '-s', 'system-product-name')) if not manu: manu = 'Unknown' if not product: product = 'Unknown' stdout = executeCommand('univention-system-info', ('/usr/bin/univention-system-info','-u','-m',manu,'-t',product,'-c','Created by univention-support-info','-s','-',)) archive = None for line in stdout.split('\n'): if line.startswith('archive'): archive = line.split(':', 1)[1] if not archive: error = 'No archive returned!' error += '\nunivention-system-info stdout:\n%s' % stdout addFile('info/univention-system-info.ERROR', len(error), cStringIO.StringIO(error)) return filename =os.path.join( '/var/www/univention-management-console/system-info/', archive ) # If UMC is not installed /var/www/univention-management-console/system-info/ does not exist and archive stays in /tmp if not os.path.isfile( filename ): filename = os.path.join( '/tmp/', archive ) try: archive = tarfile.open(name=filename, mode='r:*') for member in archive: if member.isfile(): fileobj = archive.extractfile(member) addFile('info/univention-system-info/' + member.name, member.size, fileobj) fileobj.close() archive.close() except (IOError, tarfile.TarError, ), error: error = '\n'.join(map(str, error.args)) error += '\nunivention-system-info stdout:\n%s' % stdout addFile('info/univention-system-info.ERROR', len(error), cStringIO.StringIO(error)) def rotatedLogs(): FilePatterns = [ '/var/log/apache/*', '/var/log/apache2/*', '/var/log/auth.log*', '/var/log/dpkg.log*', '/var/log/mail.log*', '/var/log/open-xchange/*', '/var/log/samba/log.*', '/var/log/syslog*', '/var/log/kern*', '/var/log/univention/*', ] FullLogs = set(( # for these every available log-file shall be included '/var/log/dpkg.log', '/var/log/syslog', )) MinLineCount = 1000 GzipSuffix = '.gz' logs = {} for FilePattern in FilePatterns: for filename in glob.glob(FilePattern): if filename.endswith(GzipSuffix): gzipped = True filename = filename[:-len(GzipSuffix)] else: gzipped = False if os.path.splitext(filename)[1].strip('0123456789') == '.': # has extension and only digits in it (filename, ext, ) = os.path.splitext(filename) number = int(ext.lstrip('.')) else: number = -1 if filename not in logs: logs[filename] = {} logs[filename][number] = gzipped for logname in sorted(logs): linecount = 0 nonemptyNumber = 0 for number in sorted(logs[logname]): gzipped = logs[logname][number] path = logname if number != -1: path += '.%d' % number bytes = 0 try: if gzipped: logfile = gzip.GzipFile(path + GzipSuffix, 'rb') else: logfile = open(path, 'rb') except (OSError, IOError, ), error: error = '\n'.join(map(str, error.args)) addFile('files/' + '%s_%d.stderr' % (logname.strip('/').replace('/', '_'), number, ), len(error), cStringIO.StringIO(error)) continue empty = True for line in logfile: empty = False linecount+=1 bytes+=len(line) logfile.close() if empty: continue nonemptyNumber += 1 try: if gzipped: logfile = gzip.GzipFile(path + GzipSuffix, 'rb') else: logfile = open(path, 'rb') except (OSError, IOError, ), error: error = '\n'.join(map(str, error.args)) addFile('files/' + '%s_%d.stderr' % (logname.strip('/').replace('/', '_'), nonemptyNumber, ), len(error), cStringIO.StringIO(error)) continue addFile('files/' + '%s_%d' % (logname.strip('/').replace('/', '_'), nonemptyNumber, ), bytes, logfile) logfile.close() if linecount > MinLineCount and logname not in FullLogs: break def tryDelete(filename): try: os.remove(filename) except (OSError, IOError, ): pass def gpg(archiveFileName): keyringFileName = tempfile.mkstemp(prefix='univention-support-info-keyring.', suffix='.gpg')[1] secringFileName = tempfile.mkstemp(prefix='univention-support-info-secring.', suffix='.gpg')[1] trustdbFileName = tempfile.mkstemp(prefix='univention-support-info-trustdb.', suffix='.gpg')[1] tryDelete(trustdbFileName) # HACK: file must not exist for gpg to work gpgFileName = archiveFileName + '.gpg' gpgBase = ('gpg', '--batch', '--quiet', '--no-tty', '--with-colons', '--utf8-strings', '--no-auto-check-trustdb', '--no-auto-key-locate', '--no-use-agent', '--no-options', '--no-random-seed-file', '--trust-model','always', '--trustdb-name', trustdbFileName, '--secret-keyring', secringFileName, '--no-default-keyring', '--keyring', keyringFileName, ) gpgImport = gpgBase + ('--import', ) gpgEncrypt = gpgBase + ('--recipient', keyID, '--encrypt', archiveFileName, ) (exitcode, stdout, stderr, ) = Popen(gpgImport, Input=keyData) if exitcode: print 'gpg-import failed with %s' % exitcode if stdout: print 'stdout: ' + repr(stdout) if stderr: print 'stderr: ' + repr(stderr) tryDelete(keyringFileName) tryDelete(keyringFileName + '~') tryDelete(secringFileName) tryDelete(trustdbFileName) tryDelete(gpgFileName) return (exitcode, stdout, stderr, ) = Popen(gpgEncrypt) if exitcode: print 'gpg-encrypt failed with %s' % exitcode if stdout: print 'stdout: ' + repr(stdout) if stderr: print 'stderr: ' + repr(stderr) tryDelete(keyringFileName) tryDelete(keyringFileName + '~') tryDelete(secringFileName) tryDelete(trustdbFileName) tryDelete(gpgFileName) return tryDelete(keyringFileName) tryDelete(keyringFileName + '~') tryDelete(secringFileName) tryDelete(trustdbFileName) os.chmod(gpgFileName, stat.S_IWUSR | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) return gpgFileName def checkForRoot(): if os.geteuid() != 0: print 'Please run this program as root!' sys.exit(3) def prepareArchive(): global archiveFileName, archiveFile, archive archiveFileName = tempfile.mkstemp(prefix='univention-support-info-%s.' % hostname, suffix='.tar.bz2')[1] archiveFile = open(archiveFileName, 'wb') archive = tarfile.open(mode='w|bz2', fileobj=archiveFile) def closeArchive(): archive.close() archiveFile.close() def prepareEnvironment(): global env env = os.environ.copy() env['LC_ALL'] = 'C' env['COLUMNS'] = '250' env['HOME'] = tempfile.mkdtemp(prefix='univention-support-info_') try: shutil.copy('/etc/skel/.bashrc', env['HOME']) shutil.copy('/etc/skel/.profile', env['HOME']) f = open(os.path.join(env['HOME'], '.toprc'), 'w') f.write(toprc) f.close() except (OSError, IOError, ): pass def cleanup(): shutil.rmtree(env['HOME']) def main(encrypt=False): checkForRoot() global archive, env prepareArchive() prepareEnvironment() collectData() simpleFiles() templateFiles() rotatedLogs() univentionSystemInfo() certificateValidities() closeArchive() print 'Data collection completed.' print if encrypt: gpgArchiveFileName = gpg(archiveFileName) if gpgArchiveFileName: print 'The encrypted data can be found here:' print ' ' + gpgArchiveFileName else: print 'WARNING: The data could not be encrypted!' print print 'The unencrypted data can be found here:' else: print 'The data can be found here:' print ' ' + archiveFileName cleanup() if __name__ == "__main__": parser = optparse.OptionParser() parser.add_option('--encrypt', action='store_true', dest='encrypt', default=False, help='encrypt data (can only be decrypted by Univention support)') parser.usage = '\n'.join(('%prog [options]', 'collect system information', '', "%prog collects information about the system's configuration.", 'The information is stored in a temporary tar archive, the path of which is printed to stdout.', )) (options, args, ) = parser.parse_args() if args: parser.print_help() sys.exit(0) main(options.encrypt)