#!/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])