|
Line 0
Link Here
|
|
|
1 |
#!/usr/bin/env python |
| 2 |
# -*- coding: utf-8 -*- |
| 3 |
# |
| 4 |
# univention-support-info - collect system information |
| 5 |
# |
| 6 |
# Copyright 2011 Univention GmbH |
| 7 |
# |
| 8 |
# http://www.univention.de/ |
| 9 |
# |
| 10 |
# All rights reserved. |
| 11 |
# |
| 12 |
# The source code of this program is made available |
| 13 |
# under the terms of the GNU Affero General Public License version 3 |
| 14 |
# (GNU AGPL V3) as published by the Free Software Foundation. |
| 15 |
# |
| 16 |
# Binary versions of this program provided by Univention to you as |
| 17 |
# well as other copyrighted, protected or trademarked materials like |
| 18 |
# Logos, graphics, fonts, specific documentations and configurations, |
| 19 |
# cryptographic keys etc. are subject to a license agreement between |
| 20 |
# you and Univention and not subject to the GNU AGPL V3. |
| 21 |
# |
| 22 |
# In the case you use this program under the terms of the GNU AGPL V3, |
| 23 |
# the program is provided in the hope that it will be useful, |
| 24 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 25 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 26 |
# GNU Affero General Public License for more details. |
| 27 |
# |
| 28 |
# You should have received a copy of the GNU Affero General Public |
| 29 |
# License with the Debian GNU/Linux or Univention distribution in file |
| 30 |
# /usr/share/common-licenses/AGPL-3; if not, see |
| 31 |
# <http://www.gnu.org/licenses/>. |
| 32 |
|
| 33 |
keyID = '18B913ABF3C1550B8C2DFDA994F01970E89E3BEC' |
| 34 |
# create with: gpg --armor --export --export-options export-minimal $keyID |
| 35 |
keyData = '\n'.join(('-----BEGIN PGP PUBLIC KEY BLOCK-----', |
| 36 |
'Version: GnuPG v1.4.9 (GNU/Linux)', |
| 37 |
'', |
| 38 |
'mQGiBEA2RhgRBADee7hGh5TPPwqs+z5tfLett9xaVxmRkUfBvqesVIj93WzrKsU3', |
| 39 |
'S7hjnMlh+JieFjJLy6jTJYtvqqFIxh3vw5btCwhntrTQnu00U/r3UdznqE/zGH2L', |
| 40 |
'A734aHaSaq6UFKE5kwX0DECgSI1hwc20d7guLJXSqOpwfYktXiB+27GRCwCgh4OR', |
| 41 |
'MWncPkhaJhusO8YCSnSN0GED/2ez8utubP1FloTfTof4/OLfBvPwdgJ5Q7FRqeF9', |
| 42 |
'wDmfd8Hetzr+Fh4zMs6dY0c5+unUQiLXjY9F01WT7SM+yFrs5EHzb+gyjIdTmTtn', |
| 43 |
'mtNTL2cZK8freAv9LPWCHfQ1rii+Qd71+/CKLDfwwLqQxEAkOsrpOsUD4dip6vkm', |
| 44 |
'ZtaRBACUYoOtB738OzjPqOpbnmNQjQYVtGCocDjfKs+bMyq+LPOyC31NVC4LvqhC', |
| 45 |
'nwXSUSy8jfXLzInPXgEUiHvGAEvnNzRLAIh6W/pIaK7tIITESmV/C3PBvxLEkJNm', |
| 46 |
'8Ll+2qGVspYnGTUFe6JzxARzcTVow4JlB+dX40bk7LNqUe6Au7QqVW5pdmVudGlv', |
| 47 |
'biBTdXBwb3J0IDxzdXBwb3J0QHVuaXZlbnRpb24uZGU+iF4EExECAB4GCwkIBwMC', |
| 48 |
'AxUCAwMWAgECHgECF4AFAkm+NOYCGQEACgkQlPAZcOieO+xhXwCfdZ7+eWGpJfhz', |
| 49 |
'CnrfuzgdzqsetMMAn3oUbDZCqzH083DKCNS5547V8XkCtCpVbml2ZW50aW9uIFN1', |
| 50 |
'cHBvcnQgPHNlcnZpY2VAdW5pdmVudGlvbi5kZT6IYAQTEQIAIAUCSNdW8wIbIwYL', |
| 51 |
'CQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEJTwGXDonjvsQcoAn2b9FNPECtPus0Sf', |
| 52 |
'3ENGafyXSIq7AJ9sbNm+QryXW1rtvtsHlNgYI9eGpLQrVW5pdmVudGlvbiBTdXBw', |
| 53 |
'b3J0IDxmZWVkYmFja0B1bml2ZW50aW9uLmRlPohgBBMRAgAgBQJI11aYAhsjBgsJ', |
| 54 |
'CAcDAgQVAggDBBYCAwECHgECF4AACgkQlPAZcOieO+wmzACfVmZKVc37T7W9FQGN', |
| 55 |
'K+dXsLbDplkAniAYh0l9Nd8wMh/QZrxcRdlgOBrhtDRVbml2ZW50aW9uIFN1cHBv', |
| 56 |
'cnQgPHBhcnRuZXItdGVjaG5pY2FsQHVuaXZlbnRpb24uZGU+iGAEExECACAFAkho', |
| 57 |
'p9gCGyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU8Blw6J477IMYAJ9oZoTS', |
| 58 |
'vHsxF7TYJSGo3pcutuV4RACfbxLxxjU7suCGs+khvINRl9pJel60KlVuaXZlbnRp', |
| 59 |
'b24gU2VydmljZSA8c2VydmljZUB1bml2ZW50aW9uLmRlPohgBBMRAgAgBQJJvjVV', |
| 60 |
'AhsjBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQlPAZcOieO+ycGwCeM8pJxUrL', |
| 61 |
'oiKylTxiKZ4MwQoV/L0An3y/9GafqT8SaUgSjYO+9P4szWATtCtQYXJ0bmVyLUxp', |
| 62 |
'c3RzIDxwYXJ0bmVyLWxpc3RzQHVuaXZlbnRpb24uZGU+iGAEExECACAFAkm+NQEC', |
| 63 |
'GyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU8Blw6J477C67AJ93Pv9Dcq7g', |
| 64 |
'HreBv3f1Q07IjDI3bACfUZgClXNISIewXER8FzV5cC08LRm0LFVuaXZlbnRpb24g', |
| 65 |
'RmVlZGJhY2sgPGZlZWRiYWNrQHVuaXZlbnRpb24uZGU+iGAEExECACAFAkm+NSsC', |
| 66 |
'GyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU8Blw6J477E8QAJ0XE91GawgL', |
| 67 |
'lVGfeiiT7c32P35IDACePCNLSzHA6K6JrV7CP98BeZUUNYu0LFVuaXZlbnRpb24g', |
| 68 |
'SGVscGRlc2sgPGhlbHBkZXNrQHVuaXZlbnRpb24uZGU+iGAEExECACAFAkm+NUMC', |
| 69 |
'GyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU8Blw6J477JNxAJ4l9wqf+WtV', |
| 70 |
'C0sAtu91aGWvgW/JQACfTJUCWf1DTqn1sDhbNiCG2jA+B9K0LFVuaXZlbnRpb24g', |
| 71 |
'VmVydHJpZWIgPHZlcnRyaWViQHVuaXZlbnRpb24uZGU+iGAEExECACAFAkm+NWwC', |
| 72 |
'GyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU8Blw6J477Jq3AJ9fN/6oKbqY', |
| 73 |
'exKHPdLQw31wC8HGTgCfZ5gn5zDd2JSY9tirDtMw5SSdfk20M1BhcnRuZXItVGVj', |
| 74 |
'aG5pY2FsIDxwYXJ0bmVyLXRlY2huaWNhbEB1bml2ZW50aW9uLmRlPohgBBMRAgAg', |
| 75 |
'BQJJvjUPAhsjBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQlPAZcOieO+wlNQCf', |
| 76 |
'eZ7Z4PeCx7SF+k1CK0bC8oouICkAn3/NYT1ASQLFP8CBqku1shs1lFCstDNQcmVt', |
| 77 |
'aXVtLVRlY2huaWNhbCA8cHJlbWl1bS10ZWNobmljYWxAdW5pdmVudGlvbi5kZT6I', |
| 78 |
'YAQTEQIAIAUCSb41GgIbIwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEJTwGXDo', |
| 79 |
'njvsxqcAnjRmgwWtXJqEbptTSSkaamNmGp9KAJ0R7b4RYDSKr+aFGPhhgetqLNXO', |
| 80 |
'MrQwVW5pdmVudGlvbiBPWCBTdXBwb3J0IDxveC1zdXBwb3J0QHVuaXZlbnRpb24u', |
| 81 |
'ZGU+iGAEExECACAFAk1GmXcCGyMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCU', |
| 82 |
'8Blw6J477JwmAJ9WeeR2SzUtHY7pPolhm4fQmtM20QCfaebVO97CHdKkcAqPjJ3K', |
| 83 |
'RwWVtpC5AQ0EQDZGGxAEAJotyyct6jvNscl9q2stDB+BUuXefdd7UMdSySSGqt5c', |
| 84 |
'7f/6IEX/eiG/2nIsqX1IsSQ+Bw0ZQTQUhgI8hICUsmjdjvWnBCyHX8xnMESITDv/', |
| 85 |
'fJmxgaP8fbMSJexhnizjlz8m74OgnfFew6EuRWRXA/SDeTwmsaUafTv7biKaDlU7', |
| 86 |
'AAMFA/9hJUqdh+tSaEfwUzPgHdFT8EIM2B0VSmVnqHSWwCjuJTLTWJi+DDe2hq7p', |
| 87 |
'QPpcATzgEg5qu5lsqh0AAXV998fD/RiO3B+ct1rwYbNlchACIXtgDTe43dmUaKkp', |
| 88 |
'fPRxeQZr8iym706LJOyppF+jXqOm2oy6Sf++/YElcCBmPPDIwIhGBBgRAgAGBQJA', |
| 89 |
'NkYbAAoJEJTwGXDonjvsqD0AnRVxlYyWk3DrKL0ZCxRZrtpW6pbwAJ9R/HZLaaH+', |
| 90 |
'043H7VXVPPTjhs6Tig==', |
| 91 |
'=BE0y', |
| 92 |
'-----END PGP PUBLIC KEY BLOCK-----', |
| 93 |
)) |
| 94 |
toprc = '\n'.join(('RCfile for "top with windows" # shameless braggin\'', |
| 95 |
'Id:a, Mode_altscr=0, Mode_irixps=1, Delay_time=3.000, Curwin=0', |
| 96 |
'Def fieldscur=AEHIOQTWKNMbcdfgjplrsuvyzX', |
| 97 |
' winflags=62905, sortindx=10, maxtasks=0', |
| 98 |
' summclr=1, msgsclr=1, headclr=3, taskclr=1', |
| 99 |
'Job fieldscur=ABcefgjlrstuvyzMKNHIWOPQDX', |
| 100 |
' winflags=62777, sortindx=0, maxtasks=0', |
| 101 |
' summclr=6, msgsclr=6, headclr=7, taskclr=6', |
| 102 |
'Mem fieldscur=ANOPQRSTUVbcdefgjlmyzWHIKX', |
| 103 |
' winflags=62777, sortindx=13, maxtasks=0', |
| 104 |
' summclr=5, msgsclr=5, headclr=4, taskclr=5', |
| 105 |
'Usr fieldscur=ABDECGfhijlopqrstuvyzMKNWX', |
| 106 |
' winflags=62777, sortindx=4, maxtasks=0', |
| 107 |
' summclr=3, msgsclr=3, headclr=2, taskclr=3', |
| 108 |
'', |
| 109 |
)) |
| 110 |
|
| 111 |
import cStringIO |
| 112 |
import glob |
| 113 |
import gzip |
| 114 |
import optparse |
| 115 |
import os |
| 116 |
import shutil |
| 117 |
import socket |
| 118 |
import stat |
| 119 |
import subprocess |
| 120 |
import sys |
| 121 |
import tarfile |
| 122 |
import tempfile |
| 123 |
import time |
| 124 |
from distutils.spawn import find_executable |
| 125 |
|
| 126 |
# ignore apt's "API not stable yet" warning |
| 127 |
import warnings |
| 128 |
warnings.filterwarnings("ignore", category=FutureWarning, append=True) |
| 129 |
|
| 130 |
import apt |
| 131 |
import apt_pkg |
| 132 |
|
| 133 |
try: |
| 134 |
from univention import config_registry |
| 135 |
except ImportError: |
| 136 |
if os.path.isfile('/usr/share/pyshared/univention/config_registry.py'): |
| 137 |
import imp |
| 138 |
config_registry = imp.load_source('config_registry', '/usr/share/pyshared/univention/config_registry.py') |
| 139 |
else: |
| 140 |
sys.path.append('/usr/share/pyshared') |
| 141 |
from univention import config_registry |
| 142 |
|
| 143 |
ucr = config_registry.ConfigRegistry() |
| 144 |
ucr.load() |
| 145 |
timeString = time.strftime('%Y-%m-%d_%H-%M-%SZ', time.gmtime()) |
| 146 |
hostname = socket.gethostname() |
| 147 |
|
| 148 |
|
| 149 |
|
| 150 |
def Popen(CommandTuple, Input=None): |
| 151 |
try: |
| 152 |
process = subprocess.Popen(CommandTuple, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True, env=env) |
| 153 |
(stdoutdata, stderrdata) = process.communicate(input=Input) |
| 154 |
return (process.returncode, stdoutdata, stderrdata) |
| 155 |
except (OSError, IOError), error: |
| 156 |
return ('Could not execute %s: %s' % (repr(CommandTuple), repr(' '.join(map(str, error.args)))), '', '') |
| 157 |
|
| 158 |
def _ldapsearchCommand(): |
| 159 |
''' Get ldapsearch command depending on UCS version ''' |
| 160 |
if find_executable('univention-ldapsearch'): |
| 161 |
return 'univention-ldapsearch' |
| 162 |
return 'ldapsearch' |
| 163 |
|
| 164 |
def _sprint(string): |
| 165 |
''' write status string to stdout without newline ''' |
| 166 |
sys.stdout.write(string) |
| 167 |
sys.stdout.flush() |
| 168 |
|
| 169 |
def U32(i): |
| 170 |
''' |
| 171 |
Return i as an unsigned integer, assuming it fits in 32 bits. |
| 172 |
If it's >= 2GB when viewed as a 32-bit unsigned int, return a long. |
| 173 |
''' |
| 174 |
if i < 0: |
| 175 |
i += 1L << 32 |
| 176 |
return i |
| 177 |
|
| 178 |
def addFile(name, size, fileobj): |
| 179 |
# try to determine filesize |
| 180 |
if size == None or size == False: |
| 181 |
fileobj.seek(0,os.SEEK_END) |
| 182 |
size = fileobj.tell() |
| 183 |
if fileobj.tell() > 0: |
| 184 |
fileobj.seek(0) |
| 185 |
|
| 186 |
info = tarfile.TarInfo() |
| 187 |
info.size = size |
| 188 |
info.name = 'univention-support-info-' + hostname + '-' + timeString + '/' + name |
| 189 |
info.mode = stat.S_IRUSR |
| 190 |
info.mtime = time.time() |
| 191 |
archive.addfile(info, fileobj) |
| 192 |
|
| 193 |
def addFileByPath(filename): |
| 194 |
if filename.startswith('/proc/'): |
| 195 |
# This is a /proc/ file, os.stat(filename).st_size will always return 0 |
| 196 |
tmpf = tempfile.mkstemp(prefix='univention-support-info.')[1] |
| 197 |
try: |
| 198 |
shutil.copy(filename, tmpf) |
| 199 |
except (OSError, IOError), error: |
| 200 |
error = '\n'.join(map(str, error.args)) |
| 201 |
addFile('files/' + filename.strip('/').replace('/', '_') + '.ERROR', len(error), cStringIO.StringIO(error)) |
| 202 |
os.unlink(tmpf) |
| 203 |
filesize = os.stat(tmpf).st_size |
| 204 |
os.unlink(tmpf) |
| 205 |
else: |
| 206 |
try: |
| 207 |
filesize = os.stat(filename).st_size |
| 208 |
except (OSError, IOError), error: |
| 209 |
filesize = 0 |
| 210 |
|
| 211 |
try: |
| 212 |
fileobj = open(filename, 'rb') |
| 213 |
except (OSError, IOError), error: |
| 214 |
error = '\n'.join(map(str, error.args)) |
| 215 |
addFile('files/' + filename.strip('/').replace('/', '_') + '.ERROR', len(error), cStringIO.StringIO(error)) |
| 216 |
else: |
| 217 |
addFile('files/' + filename.strip('/').replace('/', '_'), filesize, fileobj) |
| 218 |
fileobj.close() |
| 219 |
|
| 220 |
def certificateValidity(CertificatePath): |
| 221 |
try: |
| 222 |
import M2Crypto |
| 223 |
except ImportError, error: |
| 224 |
error = '\n'.join(map(str, error.args)) |
| 225 |
addFile('info/ssl/' + CertificatePath.strip('/').replace('/', '_') + '.ERROR', len(error), cStringIO.StringIO(error)) |
| 226 |
return |
| 227 |
|
| 228 |
try: |
| 229 |
cert = M2Crypto.X509.load_cert(CertificatePath) |
| 230 |
validity = '%s\nNot Before: %s\nNot After : %s\n' % (CertificatePath, cert.get_not_before(), cert.get_not_after(), ) |
| 231 |
addFile('info/ssl/' + CertificatePath.strip('/').replace('/', '_'), len(validity), cStringIO.StringIO(validity)) |
| 232 |
except (OSError, IOError, M2Crypto.X509.X509Error), error: |
| 233 |
error = '\n'.join(map(str, error.args)) |
| 234 |
addFile('info/ssl/' + CertificatePath.strip('/').replace('/', '_') + '.ERROR', len(error), cStringIO.StringIO(error)) |
| 235 |
|
| 236 |
def certificateValidities(): |
| 237 |
_sprint( 'Checking certificate validity: ' ) |
| 238 |
CertificatePatterns = [ |
| 239 |
'/etc/univention/ssl/*.*/cert.pem', |
| 240 |
'/etc/univention/ssl/ucsCA/CAcert.pem', |
| 241 |
] |
| 242 |
for CertificatePattern in CertificatePatterns: |
| 243 |
for CertificatePath in glob.glob(CertificatePattern): |
| 244 |
certificateValidity(CertificatePath) |
| 245 |
print 'done.' |
| 246 |
|
| 247 |
def simpleFiles(): |
| 248 |
FilePatterns = [ |
| 249 |
'/boot/config-*', |
| 250 |
'/etc/apache2/*', |
| 251 |
'/etc/apache2/*/*', |
| 252 |
'/etc/apt/*', |
| 253 |
'/etc/apt/*/*', |
| 254 |
'/etc/cron*/*', |
| 255 |
'/etc/fstab', |
| 256 |
'/etc/imapd/*', |
| 257 |
'/etc/mtab', |
| 258 |
'/etc/passwd', |
| 259 |
'/etc/procmailrc', |
| 260 |
'/etc/spamassassin/*', |
| 261 |
'/etc/univention/connector/ad/mapping.py', |
| 262 |
'/etc/univention/installation_profile', |
| 263 |
'/etc/ox-secrets/*', |
| 264 |
'/opt/open-xchange/etc/*', |
| 265 |
'/opt/open-xchange/etc/*/*', |
| 266 |
'/opt/open-xchange/etc/*/*/*', |
| 267 |
'/proc/mounts*', |
| 268 |
'/proc/mdstat', |
| 269 |
'/proc/drbd', |
| 270 |
'/proc/cmdline', |
| 271 |
'/var/lib/univention-directory-replication/failed.ldif', |
| 272 |
'/etc/postfix/*', |
| 273 |
'/etc/imapd/*', |
| 274 |
'/var/univention-backup/ad-takeover/*', |
| 275 |
'/etc/*/local.conf*', |
| 276 |
'/root/.bash_history', |
| 277 |
'/var/log/installer/*', |
| 278 |
'/etc/ldap/slapd.conf', |
| 279 |
] |
| 280 |
FileExcludePatterns = [ '/etc/apache2/mods-available/*', '/etc/apache2/sites-available/*' ] |
| 281 |
|
| 282 |
Files = set() |
| 283 |
ExcludeFiles = list() |
| 284 |
for FileExcludePattern in FileExcludePatterns: |
| 285 |
ExcludeFiles.extend(glob.glob(FileExcludePattern)) |
| 286 |
for FilePattern in FilePatterns: |
| 287 |
for Filename in glob.glob(FilePattern): |
| 288 |
if not Filename in ExcludeFiles: |
| 289 |
Files.add(Filename) |
| 290 |
|
| 291 |
_sprint( 'Collecting files: ' ) |
| 292 |
for Filename in sorted(list(Files)): |
| 293 |
if os.path.isfile(Filename): |
| 294 |
addFileByPath(Filename) |
| 295 |
_sprint('.') |
| 296 |
print 'done.' |
| 297 |
|
| 298 |
def licenseObject(): |
| 299 |
''' Get license object from ldap (cn=license) ''' |
| 300 |
stdout = executeCommand( 'univention-license-object', (_ldapsearchCommand(), '-x' , '-b', 'cn=license,cn=univention,'+ucr.get('ldap/base')) ) |
| 301 |
addFile('info/univention-license-object', len(stdout), cStringIO.StringIO(stdout)) |
| 302 |
|
| 303 |
|
| 304 |
def checkMaintenance(): |
| 305 |
''' Check if UCS-Version is in maintenance ''' |
| 306 |
if ucr.get('version/version') <= '3.1' and ucr.get('server/role') != 'ucc': |
| 307 |
tmpf = tempfile.TemporaryFile(prefix='univention-support-info.') |
| 308 |
print "Please note, system is no longer maintained, security updates are no longer available for current UCS Version %s" % (ucr.get('version/version')) |
| 309 |
print >> tmpf, "Please note, system is no longer maintained, security updates are no longer available for current UCS Version %s" % (ucr.get('version/version')) |
| 310 |
addFile( 'info/no_maintenance', None, tmpf ) |
| 311 |
|
| 312 |
def checkEntryUUID(): |
| 313 |
''' Check if ldap base is searchable by its entryUUID ''' |
| 314 |
entryuuid="" |
| 315 |
basedn="" |
| 316 |
tmpf = tempfile.TemporaryFile(prefix='univention-support-info.') |
| 317 |
(exitcode, stdout, stderr, ) = Popen( (_ldapsearchCommand(), '-xLLL', '-sbase', 'entryUUID', ) ) |
| 318 |
if exitcode == 0: |
| 319 |
entryuuid = stdout.split()[3] |
| 320 |
else: |
| 321 |
print >> tmpf, "ERROR: ldapsearch for base failed: %s" % str(stderr) |
| 322 |
addFile( 'info/entryUUID.stderr', None, tmpf ) |
| 323 |
return |
| 324 |
(exitcode, stdout, stderr, ) = Popen( (_ldapsearchCommand(), '-xLLL', 'entryUUID='+entryuuid, 'dn', ) ) |
| 325 |
if exitcode == 0: |
| 326 |
basedn = stdout.split()[1] |
| 327 |
else: |
| 328 |
print >> tmpf, "ERROR: ldapsearch by entryUUID failed: %s" % str(stderr) |
| 329 |
addFile( 'info/entryUUID.stderr', None, tmpf ) |
| 330 |
return |
| 331 |
if ucr.get('ldap/base') == basedn: |
| 332 |
print >> tmpf, "OK: ldap base found by entryUUID" |
| 333 |
else: |
| 334 |
print >> tmpf, "ERROR: ldap base not found by entryUUID, check ldap index" |
| 335 |
addFile( 'info/entryUUID', None, tmpf ) |
| 336 |
|
| 337 |
def aptPackageList(): |
| 338 |
"""List installed packages and their source repository.""" |
| 339 |
_sprint( 'Collecting package lists: ' ) |
| 340 |
cache = apt.Cache() |
| 341 |
|
| 342 |
packagesAll = tempfile.TemporaryFile(prefix='univention-support-info.') |
| 343 |
packagesUnknownSource = tempfile.TemporaryFile(prefix='univention-support-info.') |
| 344 |
|
| 345 |
if not hasattr(apt, 'deprecation'): # python apt 0.7.7 in UCS < 3.0 |
| 346 |
packages = [_ for _ in cache if _.isInstalled] |
| 347 |
for pkg in packages: |
| 348 |
pkg._lookupRecord(True) |
| 349 |
try: |
| 350 |
path = apt_pkg.ParseSection(pkg._records.Record)["Filename"] |
| 351 |
except KeyError: |
| 352 |
print >> packagesUnknownSource, "%s\tUNKNOWN" % (pkg.name,) |
| 353 |
continue |
| 354 |
cand = pkg._depcache.GetCandidateVer(pkg._pkg) |
| 355 |
for packagefile, _ in cand.FileList: |
| 356 |
indexfile = cache._list.FindIndex(packagefile) |
| 357 |
if indexfile: |
| 358 |
uri = indexfile.ArchiveURI(path) |
| 359 |
print >> packagesAll, "%s\t%s" % (pkg.name, uri) |
| 360 |
else: |
| 361 |
packages = [_ for _ in cache if _.is_installed] |
| 362 |
for pkg in packages: |
| 363 |
version = pkg.installed.version |
| 364 |
package = pkg.versions[version] |
| 365 |
try: |
| 366 |
uri = package.uri |
| 367 |
except StopIteration: |
| 368 |
print >> packagesUnknownSource, "%s\tUNKNOWN" % (pkg.name,) |
| 369 |
continue |
| 370 |
print >> packagesAll, "%s\t%s" % (pkg.name, uri) |
| 371 |
|
| 372 |
addFile( 'info/packages_all', None, packagesAll ) |
| 373 |
addFile( 'info/packages_unknown-source', None, packagesUnknownSource ) |
| 374 |
print 'done.' |
| 375 |
|
| 376 |
def executeCommand(commandName, command, log_stderr = False): |
| 377 |
(exitcode, stdout, stderr, ) = Popen(command) |
| 378 |
if exitcode or log_stderr: |
| 379 |
if type(exitcode) is int: |
| 380 |
stderr += '\nExitcode was %d\n' % exitcode |
| 381 |
else: |
| 382 |
stderr += exitcode + '\n' |
| 383 |
addFile('info/' + commandName + '.stderr', len(stderr), cStringIO.StringIO(stderr)) |
| 384 |
return stdout |
| 385 |
|
| 386 |
def templateFiles(): |
| 387 |
_sprint( 'Searching for changed template files: ' ) |
| 388 |
stdout = executeCommand('check-templates', ('find', '/etc/univention/templates/files/', '(', '-name', '*.dpkg-new', '-o', '-name', '*.dpkg-dist', ')', '-print0', )) |
| 389 |
files = [templatefile for templatefile in stdout.split('\0') if templatefile] |
| 390 |
message = ('Found %d:\n' % len(files)) + '\n'.join(files) + '\n' |
| 391 |
addFile('info/check-templates', len(message), cStringIO.StringIO(message)) |
| 392 |
for templatefile in files: |
| 393 |
addFileByPath(templatefile) |
| 394 |
if templatefile.endswith('.dpkg-new'): |
| 395 |
addFileByPath(templatefile[:-len('.dpkg-new')]) |
| 396 |
elif templatefile.endswith('.dpkg-dist'): |
| 397 |
addFileByPath(templatefile[:-len('.dpkg-dist')]) |
| 398 |
_sprint('.') |
| 399 |
print 'done.' |
| 400 |
|
| 401 |
def collectCommandData(): |
| 402 |
commands = {'hostname-f': |
| 403 |
('hostname', '--fqdn', ), |
| 404 |
'ifconfig-a': |
| 405 |
('ifconfig', '-v', '-a', ), |
| 406 |
'iptables-L_filter': |
| 407 |
('iptables', '-L', '-n', '-v', '-t', 'filter', ), |
| 408 |
'iptables-L_nat': |
| 409 |
('iptables', '-L', '-n', '-v', '-t', 'nat', ), |
| 410 |
'iptables-L_mangle': |
| 411 |
('iptables', '-L', '-n', '-v', '-t', 'mangle', ), |
| 412 |
'iptables-L_raw': |
| 413 |
('iptables', '-L', '-n', '-v', '-t', 'raw', ), |
| 414 |
'iptables-save': |
| 415 |
('iptables-save', '-c', ), |
| 416 |
'route-4': |
| 417 |
('route', '-v', '-ee', '-n', '-A', 'inet', ), |
| 418 |
'route-6': |
| 419 |
('route', '-v', '-ee', '-n', '-A', 'inet6', ), |
| 420 |
'netstat': |
| 421 |
('netstat', '--tcp', '--udp', '--listening', '--program', '--extend', '--extend', '--verbose', '--timers', '--numeric', '--wide', ), |
| 422 |
'dpkg-l': |
| 423 |
('dpkg-query', '--show', '--showformat=${Status}\t${Package}\t${Version}\n', ), |
| 424 |
'dpkg--audit': |
| 425 |
('dpkg', '--audit', ), |
| 426 |
'uname': |
| 427 |
('uname', '-a', ), |
| 428 |
'ps': |
| 429 |
('ps', '-AHFly', ), |
| 430 |
'ps-full': |
| 431 |
('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', ), |
| 432 |
'ucr-dump': |
| 433 |
('univention-config-registry', 'dump', ), |
| 434 |
'df-full': |
| 435 |
('df', '--portability', '--print-type', ), |
| 436 |
'df-i-full': |
| 437 |
('df', '--portability', '--print-type', '--inodes', ), |
| 438 |
'df': |
| 439 |
('df', '-h', ), |
| 440 |
'df-i': |
| 441 |
('df', '-h', '-i', ), |
| 442 |
'join-status': |
| 443 |
('univention-check-join-status', ), |
| 444 |
'virsh-qemu': |
| 445 |
('virsh', '-c', 'qemu:///system', 'capabilities', ), |
| 446 |
'virsh-xen': |
| 447 |
('virsh', '-c', 'xen:///', 'capabilities', ), |
| 448 |
'top': |
| 449 |
('top', '-b', '-n2', ), |
| 450 |
'testparm': |
| 451 |
(('testparm', '-s', '-vvv', ), True), |
| 452 |
'listenerID': |
| 453 |
('cat', '/var/lib/univention-directory-listener/notifier_id', ), |
| 454 |
'notifierID': |
| 455 |
('/usr/share/univention-directory-listener/get_notifier_id.py', ), |
| 456 |
'mailq': |
| 457 |
('mailq', ), |
| 458 |
'univention-license-check': |
| 459 |
('univention-license-check', ), |
| 460 |
'hostaccount-id': |
| 461 |
('id', ucr.get('hostname') + '$', ), |
| 462 |
'dig_AXFR': |
| 463 |
('dig', '@'+ucr.get('nameserver1'), ucr.get('domainname'), '-t', 'AXFR'), |
| 464 |
'univention-connector-list-rejected': |
| 465 |
('univention-connector-list-rejected', ), |
| 466 |
} |
| 467 |
|
| 468 |
# Commands depending on samba version |
| 469 |
if sambaDomainVersion == 3: |
| 470 |
commands.update({'test-join': |
| 471 |
('net', 'rpc', 'testjoin', ), |
| 472 |
}) |
| 473 |
elif sambaDomainVersion == 4: |
| 474 |
commands.update({'net-ads-info': |
| 475 |
('net', 'ads', 'info', ), |
| 476 |
'net-ads-lookup': |
| 477 |
('net', 'ads', 'lookup', ), |
| 478 |
}) |
| 479 |
if ucr.get('samba4/role', None): |
| 480 |
# Run only S4 |
| 481 |
commands.update({'samba-tool-drs-showrepl': |
| 482 |
('samba-tool', 'drs', 'showrepl', ), |
| 483 |
'samba-tool-domain-level-show': |
| 484 |
('samba-tool', 'domain', 'level', 'show'), |
| 485 |
'samba-tool-domain-passwordsettings': |
| 486 |
('samba-tool', 'domain', 'passwordsettings', 'show' ), |
| 487 |
'testparm-samba4': |
| 488 |
(('testparm.samba4', '-s', '-vvv'), True), |
| 489 |
'samba-tool-fsmo-show': |
| 490 |
('samba-tool', 'fsmo', 'show'), |
| 491 |
'univention-s4connector-list-rejected': |
| 492 |
('univention-s4connector-list-rejected', ), |
| 493 |
'samba-tool-processes': |
| 494 |
('samba-tool', 'processes'), |
| 495 |
}) |
| 496 |
# >= Samba4 RC (UCS 3.1) |
| 497 |
if ucr.get('version/version') >= '3.1': |
| 498 |
commands.update({'samba-tool-domain-info': |
| 499 |
('samba-tool', 'domain', 'info', '127.0.0.1', ), |
| 500 |
}) |
| 501 |
else: |
| 502 |
# Run only on S3 member in S4 domain |
| 503 |
commands.update({'test-join': |
| 504 |
('net', 'ads', 'testjoin', ), |
| 505 |
}) |
| 506 |
|
| 507 |
_sprint( 'Collecting command output: ' ) |
| 508 |
for commandName in commands: |
| 509 |
command = commands[commandName] |
| 510 |
if type(command[0]) == tuple: |
| 511 |
stdout = executeCommand(commandName, command[0], command[1]) |
| 512 |
else: |
| 513 |
stdout = executeCommand(commandName, command) |
| 514 |
|
| 515 |
addFile('info/' + commandName, len(stdout), cStringIO.StringIO(stdout)) |
| 516 |
_sprint('.') |
| 517 |
print 'done.' |
| 518 |
|
| 519 |
def univentionSystemInfo(): |
| 520 |
_sprint( 'Collecting hardware information: ' ) |
| 521 |
manu = executeCommand('dmidecode', ('dmidecode', '-s', 'system-manufacturer')) |
| 522 |
product = executeCommand('dmidecode', ('dmidecode', '-s', 'system-product-name')) |
| 523 |
if not manu: |
| 524 |
manu = 'Unknown' |
| 525 |
if not product: |
| 526 |
product = 'Unknown' |
| 527 |
stdout = executeCommand('univention-system-info', ('univention-system-info','-u','-m',manu,'-t',product,'-c','Created by univention-support-info','-s','-',)) |
| 528 |
archive = None |
| 529 |
for line in stdout.split('\n'): |
| 530 |
if line.startswith('archive'): |
| 531 |
archive = line.split(':', 1)[1] |
| 532 |
if not archive: |
| 533 |
error = 'No archive returned!' |
| 534 |
error += '\nunivention-system-info stdout:\n%s' % stdout |
| 535 |
addFile('info/univention-system-info.ERROR', len(error), cStringIO.StringIO(error)) |
| 536 |
return |
| 537 |
filename =os.path.join( '/var/www/univention-management-console/system-info/', archive ) |
| 538 |
# If UMC is not installed /var/www/univention-management-console/system-info/ does not exist and archive stays in /tmp |
| 539 |
if not os.path.isfile( filename ): |
| 540 |
filename = os.path.join( '/tmp/', archive ) |
| 541 |
try: |
| 542 |
archive = tarfile.open(name=filename, mode='r:*') |
| 543 |
for member in archive: |
| 544 |
if member.isfile(): |
| 545 |
fileobj = archive.extractfile(member) |
| 546 |
addFile('info/univention-system-info/' + member.name, member.size, fileobj) |
| 547 |
fileobj.close() |
| 548 |
archive.close() |
| 549 |
except (IOError, tarfile.TarError, ), error: |
| 550 |
error = '\n'.join(map(str, error.args)) |
| 551 |
error += '\nunivention-system-info stdout:\n%s' % stdout |
| 552 |
addFile('info/univention-system-info.ERROR', len(error), cStringIO.StringIO(error)) |
| 553 |
print 'done.' |
| 554 |
|
| 555 |
def rotatedLogs(): |
| 556 |
DefaultMaxLineCount = 1000 |
| 557 |
FilePatterns = [ |
| 558 |
('/var/log/apache/*', DefaultMaxLineCount), |
| 559 |
('/var/log/apache2/*', DefaultMaxLineCount), |
| 560 |
('/var/log/auth.log*', DefaultMaxLineCount), |
| 561 |
('/var/log/dpkg.log*', DefaultMaxLineCount), |
| 562 |
('/var/log/mail.log*', DefaultMaxLineCount), |
| 563 |
('/var/log/open-xchange/*', DefaultMaxLineCount), |
| 564 |
('/var/log/samba/log.*', DefaultMaxLineCount), |
| 565 |
('/var/log/kern*', DefaultMaxLineCount), |
| 566 |
('/var/log/univention/*', DefaultMaxLineCount), |
| 567 |
('/var/log/univention/ucc-clients/*', DefaultMaxLineCount), |
| 568 |
('/var/log/apt/term.log*', DefaultMaxLineCount), |
| 569 |
('/var/log/squid/*', DefaultMaxLineCount), |
| 570 |
('/var/log/dansguardian/*', DefaultMaxLineCount), |
| 571 |
('/var/log/squidguard/*', DefaultMaxLineCount), |
| 572 |
('/var/log/syslog*', 2000000), |
| 573 |
('/var/log/univention/system-stats.log*', 5000000), |
| 574 |
('/var/log/freeradius/*', DefaultMaxLineCount), |
| 575 |
('/var/log/cups/*', DefaultMaxLineCount), |
| 576 |
] |
| 577 |
FullLogs = set(( # for these every available log-file shall be included |
| 578 |
'/var/log/dpkg.log', |
| 579 |
'/var/log/univention/updater.log', |
| 580 |
'/var/log/apt/term.log', |
| 581 |
'/var/log/univention/ad-takeover.log', |
| 582 |
)) |
| 583 |
GzipSuffix = '.gz' |
| 584 |
logs = {} |
| 585 |
for FilePattern in [fp[0] for fp in FilePatterns]: |
| 586 |
for filename in glob.glob(FilePattern): |
| 587 |
if os.stat(filename).st_size <= 0 or os.path.isdir(filename): |
| 588 |
# ignore 0 byte files |
| 589 |
continue |
| 590 |
if filename.endswith(GzipSuffix): |
| 591 |
gzipped = True |
| 592 |
filename = filename[:-len(GzipSuffix)] |
| 593 |
else: |
| 594 |
gzipped = False |
| 595 |
if not filename.endswith('.') and os.path.splitext(filename)[1].strip('0123456789') == '.': # has extension and only digits in it |
| 596 |
(filename, ext, ) = os.path.splitext(filename) |
| 597 |
number = int(ext.lstrip('.')) |
| 598 |
else: |
| 599 |
number = -1 |
| 600 |
if filename not in logs: |
| 601 |
logs[filename] = {} |
| 602 |
logs[filename][number] = gzipped |
| 603 |
|
| 604 |
_sprint( 'Collecting logfiles: ' ) |
| 605 |
for logname in sorted(logs): |
| 606 |
logLinecount = 0 |
| 607 |
nonemptyNumber = 0 |
| 608 |
for number in sorted(logs[logname]): |
| 609 |
# is logname gzipped? |
| 610 |
gzipped = logs[logname][number] |
| 611 |
path = logname |
| 612 |
fileLinecount = 0 |
| 613 |
if number != -1: |
| 614 |
path += '.%d' % number |
| 615 |
|
| 616 |
if gzipped: |
| 617 |
try: |
| 618 |
logfile = open(path + GzipSuffix, 'rb') |
| 619 |
except (OSError, IOError, ), error: |
| 620 |
error = '\n'.join(map(str, error.args)) |
| 621 |
addFile('files/' + '%s_%d.stderr' % (logname.strip('/').replace('/', '_'), number, ), len(error), cStringIO.StringIO(error)) |
| 622 |
continue |
| 623 |
|
| 624 |
# calc bytes and linecount of logfile |
| 625 |
# last 4 bytes of a gzip file contain the size of the original (uncompressed) input data modulo 2^32. |
| 626 |
try: |
| 627 |
logfile.seek(-4, os.SEEK_END) |
| 628 |
except IOError, e: |
| 629 |
print '\n\nFilename: %s' %path + GzipSuffix |
| 630 |
raise IOError(e) |
| 631 |
fileBytes = U32( gzip.read32(logfile) ) |
| 632 |
logfile.close() |
| 633 |
fileLinecount = int( subprocess.Popen( 'zcat -f %s | wc -l' % (path + GzipSuffix), stdout=subprocess.PIPE, shell=True).stdout.read().strip() ) |
| 634 |
else: |
| 635 |
# addFile may calculate the size for us |
| 636 |
fileBytes = None |
| 637 |
fileLinecount = int( subprocess.Popen( ('wc', '-l', path), stdout=subprocess.PIPE).stdout.read().strip().split()[0] ) |
| 638 |
logLinecount += fileLinecount |
| 639 |
#if gzipped: |
| 640 |
# _sprint( '"%s", "%s", "%s" -> ' % (path + GzipSuffix, fileBytes, fileLinecount) ) |
| 641 |
#else: |
| 642 |
# _sprint( '"%s", "%s", "%s" -> ' % (path, fileBytes, fileLinecount) ) |
| 643 |
|
| 644 |
if fileLinecount <= 0: |
| 645 |
# skip logname if empty |
| 646 |
#print 'ERROR: Empty file? "%s"' % path |
| 647 |
continue |
| 648 |
|
| 649 |
|
| 650 |
nonemptyNumber += 1 |
| 651 |
try: |
| 652 |
if gzipped: |
| 653 |
logfile = gzip.GzipFile(path + GzipSuffix, 'rb') |
| 654 |
else: |
| 655 |
logfile = open(path, 'rb') |
| 656 |
except (OSError, IOError, ), error: |
| 657 |
error = '\n'.join(map(str, error.args)) |
| 658 |
addFile('files/' + '%s_%d.stderr' % (logname.strip('/').replace('/', '_'), nonemptyNumber, ), len(error), cStringIO.StringIO(error)) |
| 659 |
continue |
| 660 |
|
| 661 |
# Add file to archive ... |
| 662 |
addFile('files/' + '%s_%d' % (logname.strip('/').replace('/', '_'), nonemptyNumber, ), fileBytes, logfile) |
| 663 |
#print 'Added as "%s_%d"' % (logname.strip('/').replace('/', '_'), nonemptyNumber, ) |
| 664 |
logfile.close() |
| 665 |
|
| 666 |
if logname not in FullLogs and logLinecount > filter(lambda x: logname.startswith(x[0].replace('*', '')), FilePatterns)[0][1]: |
| 667 |
break |
| 668 |
|
| 669 |
_sprint('.') |
| 670 |
print 'done.' |
| 671 |
|
| 672 |
def atJobs(): |
| 673 |
''' |
| 674 |
Generate a list of at-Jobs (usefull for UCS@school) |
| 675 |
''' |
| 676 |
try: |
| 677 |
from univention.lib import atjobs as at |
| 678 |
except ImportError, error: |
| 679 |
error = str(error.message) |
| 680 |
addFile('info/at-jobs' + '.ERROR', len(error), cStringIO.StringIO(error)) |
| 681 |
return |
| 682 |
|
| 683 |
jobs = '' |
| 684 |
try: |
| 685 |
for job in at.list( extended=True ): |
| 686 |
jobs += '\n'.join( (str(job), job.command) ) |
| 687 |
except OSError, error: |
| 688 |
error = str(error.message) |
| 689 |
addFile('info/at-jobs' + '.ERROR', len(error), cStringIO.StringIO(error)) |
| 690 |
addFile('info/at-jobs', len(jobs), cStringIO.StringIO(jobs)) |
| 691 |
|
| 692 |
def tryDelete(filename): |
| 693 |
try: |
| 694 |
os.remove(filename) |
| 695 |
except (OSError, IOError, ): |
| 696 |
pass |
| 697 |
|
| 698 |
def gpg(archiveFileName): |
| 699 |
_sprint( 'Encrypting file: ' ) |
| 700 |
keyringFileName = tempfile.mkstemp(prefix='univention-support-info-keyring.', suffix='.gpg')[1] |
| 701 |
secringFileName = tempfile.mkstemp(prefix='univention-support-info-secring.', suffix='.gpg')[1] |
| 702 |
trustdbFileName = tempfile.mkstemp(prefix='univention-support-info-trustdb.', suffix='.gpg')[1] |
| 703 |
tryDelete(trustdbFileName) # HACK: file must not exist for gpg to work |
| 704 |
gpgFileName = archiveFileName + '.gpg' |
| 705 |
gpgBase = ('gpg', |
| 706 |
'--batch', '--quiet', '--no-tty', |
| 707 |
'--with-colons', '--utf8-strings', |
| 708 |
'--no-auto-check-trustdb', '--no-auto-key-locate', '--no-use-agent', |
| 709 |
'--no-options', |
| 710 |
'--no-random-seed-file', |
| 711 |
'--trust-model','always', |
| 712 |
'--trustdb-name', trustdbFileName, |
| 713 |
'--secret-keyring', secringFileName, |
| 714 |
'--no-default-keyring', '--keyring', keyringFileName, |
| 715 |
) |
| 716 |
gpgImport = gpgBase + ('--import', |
| 717 |
) |
| 718 |
gpgEncrypt = gpgBase + ('--recipient', keyID, |
| 719 |
'--encrypt', archiveFileName, |
| 720 |
) |
| 721 |
(exitcode, stdout, stderr, ) = Popen(gpgImport, Input=keyData) |
| 722 |
if exitcode: |
| 723 |
print 'gpg-import failed with %s' % exitcode |
| 724 |
if stdout: |
| 725 |
print 'stdout: ' + repr(stdout) |
| 726 |
if stderr: |
| 727 |
print 'stderr: ' + repr(stderr) |
| 728 |
tryDelete(keyringFileName) |
| 729 |
tryDelete(keyringFileName + '~') |
| 730 |
tryDelete(secringFileName) |
| 731 |
tryDelete(trustdbFileName) |
| 732 |
tryDelete(gpgFileName) |
| 733 |
return |
| 734 |
(exitcode, stdout, stderr, ) = Popen(gpgEncrypt) |
| 735 |
if exitcode: |
| 736 |
print 'gpg-encrypt failed with %s' % exitcode |
| 737 |
if stdout: |
| 738 |
print 'stdout: ' + repr(stdout) |
| 739 |
if stderr: |
| 740 |
print 'stderr: ' + repr(stderr) |
| 741 |
tryDelete(keyringFileName) |
| 742 |
tryDelete(keyringFileName + '~') |
| 743 |
tryDelete(secringFileName) |
| 744 |
tryDelete(trustdbFileName) |
| 745 |
tryDelete(gpgFileName) |
| 746 |
return |
| 747 |
tryDelete(keyringFileName) |
| 748 |
tryDelete(keyringFileName + '~') |
| 749 |
tryDelete(secringFileName) |
| 750 |
tryDelete(trustdbFileName) |
| 751 |
os.chmod(gpgFileName, stat.S_IWUSR | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH) |
| 752 |
print 'done.' |
| 753 |
return gpgFileName |
| 754 |
|
| 755 |
def checkForRoot(): |
| 756 |
if os.geteuid() != 0: |
| 757 |
print 'Please run this program as root!' |
| 758 |
sys.exit(3) |
| 759 |
|
| 760 |
def prepareArchive(): |
| 761 |
global archiveFileName, archiveFile, archive |
| 762 |
archiveFileName = tempfile.mkstemp(prefix='univention-support-info-%s.' % hostname, suffix='.tar.bz2')[1] |
| 763 |
archiveFile = open(archiveFileName, 'wb') |
| 764 |
archive = tarfile.open(mode='w|bz2', fileobj=archiveFile) |
| 765 |
|
| 766 |
def closeArchive(): |
| 767 |
archive.close() |
| 768 |
archiveFile.close() |
| 769 |
|
| 770 |
def prepareEnvironment(): |
| 771 |
global env |
| 772 |
env = os.environ.copy() |
| 773 |
env['LC_ALL'] = 'C' |
| 774 |
env['COLUMNS'] = '250' |
| 775 |
env['HOME'] = tempfile.mkdtemp(prefix='univention-support-info_') |
| 776 |
try: |
| 777 |
shutil.copy('/etc/skel/.bashrc', env['HOME']) |
| 778 |
shutil.copy('/etc/skel/.profile', env['HOME']) |
| 779 |
f = open(os.path.join(env['HOME'], '.toprc'), 'w') |
| 780 |
f.write(toprc) |
| 781 |
f.close() |
| 782 |
except (OSError, IOError, ): |
| 783 |
pass |
| 784 |
|
| 785 |
def cleanup(): |
| 786 |
shutil.rmtree(env['HOME']) |
| 787 |
|
| 788 |
def main(encrypt=False): |
| 789 |
checkForRoot() |
| 790 |
global archive, env, sambaDomainVersion |
| 791 |
prepareArchive() |
| 792 |
prepareEnvironment() |
| 793 |
|
| 794 |
# Check Samba Version |
| 795 |
if executeCommand( 'samba4-pdc-dn', (_ldapsearchCommand(), '-xLLL', '(&(univentionService=Samba 4)(objectClass=univentionDomainController))', 'dn') ): |
| 796 |
sambaDomainVersion = 4 |
| 797 |
else: |
| 798 |
sambaDomainVersion = 3 |
| 799 |
|
| 800 |
# Place new calls below this line |
| 801 |
checkMaintenance() |
| 802 |
collectCommandData() |
| 803 |
simpleFiles() |
| 804 |
licenseObject() |
| 805 |
templateFiles() |
| 806 |
aptPackageList() |
| 807 |
atJobs() |
| 808 |
certificateValidities() |
| 809 |
univentionSystemInfo() |
| 810 |
rotatedLogs() |
| 811 |
checkEntryUUID() |
| 812 |
# Place new calls above this line |
| 813 |
|
| 814 |
closeArchive() |
| 815 |
print 'Data collection completed.' |
| 816 |
print |
| 817 |
print |
| 818 |
if encrypt: |
| 819 |
gpgArchiveFileName = gpg(archiveFileName) |
| 820 |
if gpgArchiveFileName: |
| 821 |
print 'The encrypted data can be found here:' |
| 822 |
print ' ' + gpgArchiveFileName |
| 823 |
print ' ' |
| 824 |
else: |
| 825 |
print 'WARNING: The data could not be encrypted!' |
| 826 |
print |
| 827 |
print 'The unencrypted data can be found here:' |
| 828 |
else: |
| 829 |
print 'The data can be found here:' |
| 830 |
print ' ' + archiveFileName |
| 831 |
cleanup() |
| 832 |
|
| 833 |
if __name__ == "__main__": |
| 834 |
parser = optparse.OptionParser() |
| 835 |
parser.add_option('--encrypt', action='store_true', dest='encrypt', default=False, help='encrypt data (can only be decrypted by Univention support)') |
| 836 |
parser.usage = '\n'.join(('%prog [options]', |
| 837 |
'collect system information', |
| 838 |
'', |
| 839 |
"%prog collects information about the system's configuration.", |
| 840 |
'The information is stored in a temporary tar archive, the path of which is printed to stdout.', |
| 841 |
)) |
| 842 |
(options, args, ) = parser.parse_args() |
| 843 |
if args: |
| 844 |
parser.print_help() |
| 845 |
sys.exit(0) |
| 846 |
|
| 847 |
main(options.encrypt) |