source: hwdetector/trunk/fuentes/valentin.install/usr/bin/valentin @ 6413

Last change on this file since 6413 was 6413, checked in by mabarracus, 3 years ago

Remove stored useless information
Internal use with unicode strings
Clean json output

  • Property svn:executable set to *
File size: 10.2 KB
Line 
1#!/usr/bin/env python
2import sys,os
3sys.path.insert(0,'/usr/lib/valentin/')
4import logging
5import hwdetector.utils.log as log
6import tarfile
7import datetime
8import tempfile
9import json
10import argparse
11import zlib
12import base64
13from ruleset import ruleset
14
15def run_in_debug():
16    gettrace=getattr(sys,'gettrace',None)
17    if gettrace is None:
18        return False
19    elif gettrace():
20        return True
21    else:
22        return None
23
24def indent_var(st=u'',var={},indent=0):
25    creturn=u'\n'
26    if indent==0:
27        creturn=creturn*2
28    indentation=u'\t'*indent
29    try:
30        if isinstance(var,dict):
31            for x in sorted(var.keys()):
32                if not (x.lower().startswith('helper') and indent==0):
33                    st += u'{}{}\n{}{}'.format(indentation,x,indent_var(var=var[x],indent=indent+1),creturn)
34        elif isinstance(var,list) or isinstance(var,tuple):
35            if len(var) == 2 and var[0] == '__gz__':
36                content=zlib.decompress(base64.b64decode(var[1])).decode('utf-8')
37                replaced = content.replace(u'\n',indentation+u'\n'+indentation)
38                st += u'{}{}'.format(indentation,replaced)
39            else:
40                if isinstance(var,tuple):
41                    st += u'{}{}'.format(indentation,var)
42                else:
43                    for x in sorted(var):
44                        st += u'{}\n'.format(indent_var(var=x,indent=indent+1))
45        elif isinstance(var,str):
46            try:
47                var = var.encode('utf-8')
48            except:
49                var = var.decode('utf-8')
50            replaced = var.replace(u'\n',indentation+u'\n'+indentation)
51            st += u'{}{}'.format(indentation,replaced)
52        elif isinstance(var,unicode):
53            replaced = var.replace(u'\n',indentation+u'\n'+indentation)
54            st += u'{}{}'.format(indentation,replaced)
55        elif isinstance(var,bool) or isinstance(var,int) or isinstance(var,float) or var == None:
56            st += u'{}{}'.format(indentation,var)
57        else:
58            raise Exception('Unknown type var')
59        return st
60    except Exception as e:
61        return u''
62
63def make_file(capabilities,*args,**kwargs):
64    try:
65        txt = json.dumps(capabilities,indent=4,separators=(',',':'),sort_keys=True)
66        name = tempfile.mkstemp()[1]
67        with open(name,'w') as f:
68            f.write(txt.encode('utf-8'))
69        return name
70    except Exception as e:
71        return False
72
73def make_tar(file,*args,**kwargs):
74    try:
75        datestr='{:%Y%m%d%H%M}'.format(datetime.datetime.now())
76        if kwargs['fname']:
77            filename = kwargs['fname']
78        else:
79            filename = 'valentin-info-{}.tar.gz'.format(datestr)
80
81        if os.path.exists(file):
82            with tarfile.open(filename,'w:gz') as f:
83                f.add(file,arcname='debug-info-{}.txt'.format(datestr),recursive=False)
84                logger_message_file='/tmp/valentin-debug-log-messages.txt'
85                if os.path.exists(logger_message_file):
86                    f.add(logger_message_file,arcname=os.path.basename(logger_message_file))
87            return filename
88    except Exception as e:
89        return False
90
91def run_detection(*args,**kwargs):
92    log.debug("Importing hwdetector")
93    import hwdetector
94
95    log.debug("Instantiate HwDetector")
96    hwd=hwdetector.HwDetector()
97
98    #hwd.all_plugins_are_needed=True
99    if not run_in_debug():
100        log.info('USING MAX_RUNNING_TIME !!!')
101        hwd.MAX_RUNNING_TIME = 30
102
103    #hwd.fake_capabilities={'IAMGOD':'yes'}
104
105    log.debug("Calling run plugins")
106    #ret = hwd.run(needs=['ALL_TESTS'])
107    #ret = hwd.run(needs=['LLXSYSTEM_TEST','LLXNETWORK_TEST'])
108    ret = hwd.run()
109
110    # try:
111    #     file = make_file(hwd.capabilities,**kwargs)
112    #     if kwargs['to_stdout']:
113    #         print(file)
114    #     else:
115    #         fname=make_tar(file,**kwargs)
116    #         log.info("File {} created".format(fname))
117    # except Exception as e:
118    #     log.error("File creation unsuccessful "+str(e))
119
120    log.info("Total running time: {}".format(hwd.RUNNING_TIME))
121
122    return (ret,hwd.capabilities)
123
124def load_file(*args,**kwargs):
125    if kwargs.get('fname',None):
126        filename = kwargs['fname']
127    else:
128        return False
129    if os.path.exists(filename):
130        ftxt=None
131        if tarfile.is_tarfile(filename):
132            with tarfile.open(filename,'r:gz') as tar:
133                target_file=None
134
135                for tarinfo in tar.getmembers():
136                    if 'debug-info' in tarinfo.name.lower():
137                        target_file=tarinfo.name
138                        break
139                if target_file:
140                    ftxt = tar.extractfile(target_file).read()
141        else:
142            ftxt = None
143            with open(filename,'r') as f:
144                ftxt = f.read()
145        return ftxt
146    else:
147        return False
148
149def run_analysis(*args,**kwargs):
150
151    if kwargs.get('capabilities',None):
152        fileinfo = kwargs.get('capabilities')
153    if not kwargs.get('ruleset',None):
154        fileruleset='/usr/share/valentin/valentin.rules'
155        if not os.path.exists(fileruleset):
156            return False
157    else:
158        fileruleset=kwargs.get('ruleset')[0]
159
160    rs = ruleset()
161    try:
162        rs.load_ruleset(fileruleset=fileruleset,data=fileinfo)
163        rs.make_tree()
164        rs.make_suggestion()
165    except Exception as e:
166        log.error(e)
167
168    return True
169
170
171if __name__ == '__main__':
172    try:
173        parser = argparse.ArgumentParser(description='Simple system diagnostic tool')
174        dlevels = ['debug','info','warning','error']
175        parser.add_argument('-d','--debug-level',metavar='debug|info|warning|error',nargs='?',choices=dlevels,help='Set the debug level (default: warning)')
176        parser.add_argument('-c','--coloured',action='store_const',help='Colorize logger messages',const=True)
177
178        parser.add_argument('-f','--with-file',metavar='filename',nargs='?',help='Filename for results file (default valentin-info-(date).tar.gz')
179        parser.add_argument('-o','--to-stdout',action='store_const',help='Output results to stdout',const=True)
180        parser.add_argument('-w','--to-stdout-raw',action='store_const',help='Output results to stdout in json format',const=True)
181
182        parser.add_argument('-a','--analyze-file',metavar='filename',nargs=1,help='Filename to analyze')
183        parser.add_argument('-x','--run-detection',action='store_const',help='Run detection',const=True)
184
185        parser.add_argument('-s','--suggest',action='store_const',help='Suggest actions to repair system',const=True)
186        parser.add_argument('-r','--ruleset',metavar='filename',nargs=1,help='Load ruleset when suggest user actions')
187        args = parser.parse_args()
188
189        if not args.debug_level:
190            #log.set_level(logging.WARNING)
191            log.disable()
192        else:
193            levels={'debug':logging.DEBUG,'info':logging.INFO,'warning':logging.WARNING,'error':logging.ERROR}
194            log.set_level(levels[args.debug_level.lower()])
195
196        if args.coloured:
197            log.set_color(True)
198
199        kw=vars(args)
200
201        fname=None
202        if args.with_file:
203            fname=args.with_file
204            if '.' not in fname:
205                fname = fname + '.tar.gz'
206            kw.update({'fname':fname})
207
208        if args.analyze_file:
209            fname=args.analyze_file[0]
210            kw.update({'fname':fname})
211            capabilities=load_file(**kw)
212            if capabilities:
213                capabilities = json.loads(capabilities)
214                ret = True
215                log.info("File {} loaded".format(fname))
216                kw.update({'capabilities':capabilities})
217            else:
218                log.error("File {} can't be loaded".format(fname))
219                ret = False
220        else:
221            if args.run_detection:
222                ret,capabilities=run_detection(**kw)
223                log.info('Detection done!')
224                if args.with_file:
225                    try:
226                        file = make_file(capabilities,**kw)
227                        fname = make_tar(file,**kw)
228                        log.info("File {} created".format(fname))
229                    except Exception as e:
230                        log.error("File creation unsuccessful "+str(e))
231
232                kw.update({'capabilities':capabilities})
233            else:
234                sys.stderr.write('Missing detection option\n')
235                ret = False
236
237        if ret:
238            if args.to_stdout or args.to_stdout_raw:
239                if args.to_stdout:
240                    pr=indent_var(var=capabilities)
241                else:
242                    for x in (x for x in capabilities.keys() if x.lower().startswith('helper')):
243                        del capabilities[x]
244
245                    def clear_compressed(var):
246                        try:
247                            if isinstance(var,tuple) or isinstance(var,list):
248                                if len(var) == 2 and var[0]=='__gz__':
249                                    try:
250                                        var=zlib.decompress(base64.b64decode(var[1])).decode('utf-8')
251                                    except:
252                                        pass
253                                    return var
254                                var=list(var)
255                                for i in range(len(var)):
256                                    var[i]=clear_compressed(var[i])
257                            elif isinstance(var,dict):
258                                for x in var:
259                                    var[x]=clear_compressed(var[x])
260
261                            return var
262                        except Exception as e:
263                            log.error(e)
264
265                    capabilities=clear_compressed(capabilities)
266                    pr=json.dumps(capabilities,indent=4,separators=(',',':'),sort_keys=True)
267
268                sys.stdout.write(pr.encode('utf-8'))
269                sys.stderr.write('\n')
270
271            if args.suggest:
272                ret=run_analysis(**kw)
273
274
275        if ret:
276            log.info("Exit code = 0")
277            sys.exit(0)
278        else:
279            log.info("Exit code = 1")
280            sys.exit(1)
281
282    except Exception as e:
283        log.error("Exception occurred: {}".format(e))
284        log.error("Exit code = 1")
285        sys.exit(1)
286
Note: See TracBrowser for help on using the repository browser.