summaryrefslogtreecommitdiffstats
path: root/utils/log_picker/__init__.py
blob: 61bdaa17546fde5509fe58d3bec551f738c6a9eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/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])