qubes-installer-qubes-os/anaconda/utils/log_picker/__init__.py

147 lines
4.7 KiB
Python
Raw Normal View History

#!/usr/bin/python
import os
import sys
import tempfile
import log_picker.archiving as archiving
from log_picker.archiving import ArchivationError
from log_picker.archiving import NoFilesArchivationError
import log_picker.sending as sending
from log_picker.sending import SenderError
import log_picker.logmining as logmining
from log_picker.logmining import LogMinerError
class LogPickerError(Exception):
pass
class LogPicker(object):
def __init__(self, archive_obj=None, sender_obj=None, miners=[],
use_one_file=False):
self.sender_obj = sender_obj
self.archive_obj = archive_obj
self.miners = miners
self.archive = None
self.tmpdir = None
self.files = []
self.filename = self._get_tmp_file("completelog") if use_one_file else None
def _errprint(self, msg):
"""Print message on stderr."""
sys.stderr.write('%s\n' % msg)
def _get_tmp_file(self, name, suffix="", register=True):
"""Create temp file."""
if not self.tmpdir:
self.tmpdir = tempfile.mkdtemp(prefix="lp-logs-", dir="/tmp")
name += suffix
filename = os.path.join(self.tmpdir, name)
open(filename, 'w') # Create empty file
if register:
self.files.append(filename)
return filename
def create_archive(self, name=""):
"""Create archive (one file) containing multiple log files."""
name = name or self.tmpdir or "logs"
self.archive = self._get_tmp_file(name,
suffix=self.archive_obj.file_ext, register=False)
try:
self.archive_obj.create_archive(self.archive, self.files)
except (ArchivationError):
os.remove(self.archive)
raise
def send(self):
"""Send log/archive with logs via sender object."""
if not len(self.files):
return
if not self.archive and len(self.files) > 1:
raise LogPickerError('More than one file to send. ' + \
'You have to create archive. Use create_archive() method.')
file = self.files[0]
contenttype = "text/plain"
if self.archive:
file = self.archive
contenttype = self.archive_obj.mimetype
self.sender_obj.sendfile(file, contenttype)
def getlogs(self):
"""Collect logs generated by miners passed to the constructor."""
# self.filename != None means that we should put all logs into one file.
# self.filename == None means that every log should have its own file.
if self.filename:
f = open(self.filename, 'w')
for miner in self.miners:
if not self.filename:
tmpfilename = self._get_tmp_file(miner.get_filename())
f = open(tmpfilename, 'w')
desc = "%s\n\n" % (miner.get_description())
f.write(desc)
try:
miner.set_logfile(f)
miner.getlog()
except (LogMinerError) as e:
self._errprint("Warning: %s - %s" % (miner._name, e))
f.write("\n%s\n\n\n" % e)
if not self.filename:
f.close()
# XXX Cut our anaconda dump into pieces.
if isinstance(miner, logmining.AnacondaLogMiner):
self._cut_to_pieces(tmpfilename)
if self.filename:
f.close()
def _cut_to_pieces(self, filename):
"""Create multiple log files from Anaconda dump.
Attention: Anaconda dump file on input will be used and overwritten!
@filename file with Anaconda dump"""
actual_file = os.path.basename(filename)
files = {actual_file: []}
empty_lines = 0
# Split file into memmory
for line in open(filename):
striped = line.strip()
if not striped:
empty_lines += 1
elif empty_lines > 1 and striped.startswith('/') \
and striped.endswith(':') and len(line) > 2:
actual_file = striped[:-1].rsplit('/', 1)[-1]#.replace('.', '-')
files[actual_file] = []
empty_lines = 0
files[actual_file].append(line)
# Overwrite original file
actual_file = os.path.basename(filename)
open(filename, 'w').writelines(files[actual_file])
del files[actual_file]
# Write other individual files
for file in files:
open(self._get_tmp_file(file), 'w').writelines(files[file])