source: lliurex-statistics/trunk/fuentes/lliurex-statistics.install/usr/sbin/analytics @ 6845

Last change on this file since 6845 was 6845, checked in by mabarracus, 22 months ago

Fix json bug

  • Property svn:executable set to *
File size: 25.9 KB
Line 
1#!/usr/bin/env python3
2import sys
3import os
4import re
5import signal
6import time
7import subprocess
8import requests
9import json
10import configparser
11import daemon
12from xmlrpc import client
13import lockfile
14import logging.handlers
15from logging import config as cfg
16import ssl
17
18
19oldsignals = {}
20for sig in signal.Signals:
21    try:
22        oldsignals.setdefault(sig.name, signal.getsignal(sig))
23        signal.signal(sig.value, signal.SIG_IGN)
24    except:
25        continue
26
27#
28# START EDITABLE VARS (OVERRIDES VALUES IN CONFIGFILE)
29#
30
31# DEBUG = 1
32
33MODE = 'PROCEDURAL'
34# MODE = 'THREADED'
35
36CONFIGFILE = '/etc/lliurex-analytics/agent.cfg'
37# CONFIGFILE = 'config.txt'
38
39# OVERRIDE_SEND_PERMISSION   = 1
40
41# MIN_LOG_LEVEL = 'info'
42
43# DAEMON_MODE = 1
44
45# FILELOCK = '/tmp/analytics'
46
47# PIDFILE = '/var/run/analitics.pid'
48# PIDFILE = '/tmp/analitics.pid'
49
50# STATUSFILE = '/etc/lliurex-analytics/status'
51
52# TIMEOUT = 1
53
54#
55# END EDITABLE VARS #
56#
57
58
59if MODE == 'PROCEDURAL':
60    from multiprocessing import Process, Manager
61    str_formatter = '(%(processName)s)'
62if MODE == 'THREADED':
63    from multiprocessing.dummy import Process, Manager
64    str_formatter = '(%(threadName)s)'
65
66def get_var_value(varname, config=None, mode='string', section='Agent'):
67    value = None
68
69    if config:
70        varname = varname.lower()
71        try:
72            if mode == 'string':
73                value = config.get(section, varname)
74            elif mode == 'bool':
75                value = config.getboolean(section, varname)
76            elif mode == 'int':
77                value = config.getint(section, varname)
78            elif mode == 'float':
79                value = config.getfloat(section, varname)
80        except:
81            pass
82
83    def f(item):
84        if isinstance(item, str) or isinstance(item, bool) or isinstance(item, int) or isinstance(item, float):
85            return True
86        else:
87            return False
88
89    for x in (v for v in globals() if varname.lower() == v.lower() and f(globals()[v])):
90        value = globals()[x]
91
92    if mode == 'string':
93        return str(value)
94    elif mode == 'bool':
95        return bool(value)
96    elif mode == 'int':
97        return int(value)
98    elif mode == 'float':
99        return float(value)
100    else:
101        return value
102
103
104if get_var_value('DEBUG', mode='bool'):
105    loglevel = get_var_value('MIN_LOG_LEVEL')
106    if loglevel:
107        if loglevel == 'debug' or loglevel == logging.DEBUG:
108            loglevel = logging.DEBUG
109        elif loglevel == 'critical' or loglevel == logging.CRITICAL:
110            loglevel = logging.CRITICAL
111        elif loglevel == 'error' or loglevel == logging.ERROR:
112            loglevel = logging.ERROR
113        elif loglevel == 'warning' or loglevel == logging.WARNING:
114            loglevel = logging.WARNING
115        elif loglevel == 'info' or loglevel == logging.INFO:
116            loglevel = logging.INFO
117        else:
118            loglevel = logging.DEBUG
119    else:
120        loglevel = logging.DEBUG
121else:
122    loglevel = logging.INFO
123
124
125LOGGING = {
126    'version': 1,
127    'disable_existing_loggers': False,
128    'formatters': {
129        'verbose': {
130#            'format': '%(levelname)s %(module)s (%(pathname)s:%(lineno)d) ' + str_formatter  + ' %(message)s'
131            'format': '%(levelname)s %(module)s ' + str_formatter + ' %(message)s'
132        },
133    },
134    'handlers': {
135        'stdout': {
136            'class': 'logging.StreamHandler',
137            'stream': sys.stdout,
138            'formatter': 'verbose',
139        },
140        'sys-logger6': {
141            'class': 'logging.handlers.SysLogHandler',
142            'address': '/dev/log',
143            'facility': "local6",
144            'formatter': 'verbose',
145        },
146    },
147    'loggers': {
148        'analytics-logger': {
149            'handlers': ['sys-logger6', 'stdout'],
150            'level': loglevel,
151            'propagate': True,
152        },
153    }
154}
155
156
157cfg.dictConfig(LOGGING)
158log = logging.getLogger('analytics-logger')
159
160
161def print_config(config):
162    global log
163
164    for sect in config:
165        for key in config[sect]:
166            log.debug("Config Loaded: '{}' '{}' '{}'".format(sect, key, config[sect][key]))
167
168
169def init_config():
170
171    config = configparser.ConfigParser()
172    config.read(CONFIGFILE)
173
174    return config
175
176
177def init_logging(config):
178    global DEBUG, log
179
180    if get_var_value('DEBUG', config):
181        DEBUG = True
182        log.setLevel(loglevel)
183        print_config(config)
184
185
186def bin_to_ascii(value):
187    global log
188
189    try:
190        if isinstance(value, bytes):
191            return value.decode('utf-8')
192        else:
193            return value
194    except Exception as e:
195        log.error('Error bin_to_ascii {}'.format(e))
196        return value
197
198
199def get_llx_version():
200    global log
201
202    output = bin_to_ascii(subprocess.check_output(['lliurex-version', '-n']))
203    release = output[0:2].strip()
204    if release == '15':
205        use = 'lliurex-detect'
206    else:
207        use = 'lliurex-version'
208    output = bin_to_ascii(subprocess.check_output([use, '-f']))
209    flavour = output.strip()
210    log.info("Detected release:'{}' flavour:'{}'".format(release, flavour))
211    return release, flavour
212
213
214def detect_proxy():
215    global log
216
217    px = subprocess.Popen(["bash", "-c", "source /etc/profile && echo $http_proxy"], stdout=subprocess.PIPE)
218    proxy = bin_to_ascii(px.stdout.readline()).strip()
219    log.info("Detected proxy: '{}'".format(proxy))
220    return proxy
221
222
223def daemonize(*args, **kwargs):
224    global glob, log, CONFIG
225
226    log.info('Running daemon mode...')
227    filelock = get_var_value('filelock', CONFIG)
228    if not filelock:
229        filelock = '/var/run/analytics'
230
231    try:
232        with daemon.DaemonContext(detach_process=True,
233                                  working_directory='/tmp',
234                                  umask=0o002,
235                                  pidfile=lockfile.FileLock(filelock),
236                                  files_preserve=[log.handlers[0].socket.fileno()]):
237            start(daemon_mode=True)
238    except Exception as e:
239        log.critical("Error daemonizing {}".format(e))
240        sys.exit(1)
241
242
243def add_item(item):
244    global glob, log
245
246    log.debug('Request to add {}'.format(item))
247
248    parts_item = item.split(' ')
249
250    executable = None
251    not_valid = ['-', ':']
252    for i in range(len(parts_item)):
253        executable = parts_item[i].strip()
254        if executable[0] in not_valid:
255            log.debug('Skipping malformed executable {}'.format(executable))
256            executable = None
257            continue
258        if '/' in executable:
259            executable = executable.split('/')[-1]
260            log.debug('Trimming executable to {}'.format(executable))
261        if executable in glob['INTERPRETERS']:
262            log.debug('Trimming interpreter part {}'.format(executable))
263            executable = None
264            continue
265        else:
266            if executable in glob['BLACKLIST']:
267                log.debug('Skipping add due to blacklisted command {}'.format(executable))
268                return None
269            log.debug('Valid executable {}'.format(executable))
270            break
271
272    the_list = glob['LIST']
273    if executable:
274        if executable in the_list:
275            the_list[executable] = the_list[executable] + 1
276            log.info('+++ Incrementing {} = {}'.format(executable, the_list[executable]))
277        else:
278            log.info('*** Adding {} = 1'.format(executable, 1))
279            the_list[executable] = 1
280    glob['LIST'] = the_list
281
282
283def monitor():
284    global glob, log
285
286    log.info('Start monitor')
287    logfilename = get_var_value('file', glob['config'], section='Audit')
288
289    glob['BLACKLIST'] = get_var_value('blacklist', glob['config'], section='Audit')
290    glob['INTERPRETERS'] = get_var_value('interpreters', glob['config'], section='Audit')
291
292    try:
293        glob['INTERPRETERS'] = [x.strip() for x in glob['INTERPRETERS'].split(',')]
294    except Exception as e:
295        log.error('Malformed interpreters list ,{}'.format(e))
296        glob['INTERPRETERS'] = []
297        return None
298
299    try:
300        with open(glob['BLACKLIST'], 'r') as fp:
301            glob['BLACKLIST'] = [line.strip() for line in fp]
302    except Exception as e:
303        log.error('Unable to read blacklist from {} , {}'.format(glob['BLACKLIST'], e))
304        glob['BLACKLIST'] = []
305        return None
306
307    try:
308        if not (os.path.isfile(logfilename) and os.access(logfilename, os.R_OK)):
309            log.critical('File {} not readable'.format(logfilename))
310            glob['TERMINATE'] = True
311
312        fp = subprocess.Popen(['tail', '-F', logfilename], stdout=subprocess.PIPE, stderr=open(os.devnull, 'w'))
313    except Exception as e:
314        log.critical('Error initializing {} read, {}'.format(logfilename, e))
315        glob['TERMINATE'] = True
316        return None
317
318    try:
319        log.info('Starting monitoring {}'.format(logfilename))
320
321        while not glob['TERMINATE']:
322            if fp.poll() is not None:
323                log.error('Dead subprocess monitoring {}'.format(logfilename))
324                fp = subprocess.Popen(['tail', '-F', logfilename], stdout=subprocess.PIPE, stderr=open(os.devnull, 'w'))
325            else:
326                line = bin_to_ascii(fp.stdout.readline()).strip()
327                if re.search('type=EXECVE', line):
328                    m = re.findall('a[0-9]+="([^"]+)"', line)
329                    if m:
330                        captured = ' '.join(m)
331                        add_item(captured)
332
333    except Exception as e:
334        if isinstance(e, ConnectionResetError):
335            log.info('Connection reset exitting monitor thread')
336            glob['TERMINATE'] = True
337            return
338        else:
339            log.error('Error reading file {}, {}'.format(logfilename, e))
340            glob['TERMINATE'] = True
341            return
342
343    log.info('Exitting monitor thread')
344    return
345
346def update_list():
347    global glob, log
348
349    log.info('Start update list')
350    try:
351        list_path = get_var_value('list_path', glob['config'], mode='string', section='Server')
352        server = get_var_value('server', glob['config'], mode='string', section='Server')
353        url = 'http://' + server + '/' + list_path
354        agent = glob['user_agent']
355        headers = {'user-agent': agent}
356    except Exception as e:
357        log.warning('Error gettting update list settings {}'.format(e))
358
359    log.debug('List path {}'.format(url))
360
361    tick = 1
362    timeout = 60 * 60 * 12
363    c = 10
364
365    while not glob['TERMINATE']:
366        time.sleep(tick)
367        if c > 0:
368            c = c - tick
369        else:
370            c = timeout
371
372            sent = False
373            rq = None
374
375            try:
376                if glob['use_proxy']:
377                    proxy_obj = dict()
378                    proxy_obj.setdefault('http', glob['proxy'])
379
380                    rq = requests.get(url, headers=headers, proxies=proxy_obj, timeout=5)
381                    sent = True
382                else:
383                    rq = requests.get(url, headers=headers, timeout=5)
384                    sent = True
385            except Exception as e:
386                log.warning('Error getting list from {}, {}'.format(url,e))
387
388            try:
389                blist = glob['BLACKLIST']
390            except Exception as e:
391                log.error('Error loading current blacklist on update_list, {}'.format(e))
392
393            try:
394                the_list = glob['LIST']
395            except Exception as e:
396                log.error('Error loading current applist on update_list, {}'.format(e))
397
398            if sent and rq:
399                result = rq.text
400                try:
401                    json_list = json.loads(result)
402                except Exception as e:
403                    log.warning('Wrong list received {}, {}'.format(result,e))
404                    continue
405
406                try:
407                    for item in json_list:
408                        if item not in blist:
409                            blist.append(item)
410                            log.info("Received item list '{}'".format(item))
411                        if item in the_list:
412                            del the_list[item]
413                            log.info("Removed item from list '{}'".format(item))
414                    glob['BLACKLIST'] = blist
415                    glob['LIST'] = the_list
416                except Exception as e:
417                    log.error('Error updating blacklist, {}'.format(e))
418            else:
419                log.warning('Unable to get list data')
420
421    log.info('Exitting update list thread')
422
423
424def timed_send():
425    global glob, log
426
427    log.debug('Start timed_send ')
428    try:
429        count = get_var_value('timeout', glob['config'], mode='int')
430        if count < 0:
431            log.warning('Not valid timeout value setting default 300')
432    except Exception as e:
433        log.warning('Unable to read timeout value defaulting to 300, {}'.format(e))
434        count = 300
435
436    log.info('Initialized timed send with value {} seconds'.format(count))
437    c = count
438    tick = 0.2
439    try:
440        while not glob['TERMINATE']:
441            while glob['PRINTING'] == True:
442                time.sleep(1)
443            time.sleep(tick)
444            if c > 0:
445                c = c - tick
446            else:
447                c = count
448                log.debug('Triggering timed send')
449                clean_and_send()
450
451    except Exception as e:
452        if isinstance(e, ConnectionResetError):
453            log.info('Connection reset exitting timer thread')
454        else:
455            log.error('Error with timed send, {}'.format(e))
456
457    log.info('Exitting timer thread')
458    return
459
460
461def start(*args, daemon_mode=False, **kwargs):
462    global THREADS, oldsignals, log, CONFIG, glob
463
464    log.info("Starting analytics")
465
466    mgr = Manager()
467    glob = mgr.dict()
468
469    glob['DAEMON_MODE'] = daemon_mode
470    glob['config'] = CONFIG
471
472    try:
473        glob['release'], glob['flavour'] = get_llx_version()
474    except Exception as e:
475        log.error('Error getting llx version {}'.format(e))
476        glob['release'] = 'Unknown'
477        glob['flavour'] = 'Unknown'
478
479    try:
480        glob['proxy'] = detect_proxy()
481        if glob['proxy'] == '':
482            log.info('Not using proxy')
483            glob['use_proxy'] = False
484        else:
485            glob['use_proxy'] = True
486    except Exception as e:
487        log.warning('Error detecting proxy {}'.format(e))
488        glob['use_proxy'] = False
489
490    pidfile = get_var_value('pidfile', glob['config'])
491
492    try:
493        server = get_var_value('server', glob['config'], section='Server')
494        server_path = get_var_value('server-path', glob['config'], section='Server')
495        if server.strip() == '' or server_path.strip() == '':
496            raise Exception('Empty server or server-path')
497        glob['server'] = server
498        glob['server_path'] = server_path
499    except Exception as e:
500        log.critical('Error getting server url, {}'.format(e))
501
502    try:
503        agent = get_var_value('user-agent', glob['config'])
504        if agent.strip() == '' or agent == 'None':
505            agent = 'lliurex-analytics-agent'
506        glob['user_agent'] = agent
507    except Exception as e:
508        log.warning('Error getting user-agent, {}'.format(e))
509
510    # write pid
511    try:
512        with open(pidfile, 'w') as fp:
513            fp.write(str(os.getpid()))
514    except Exception as e:
515        log.error('Error writting pidfile {}'.format(e))
516
517    glob['TERMINATE'] = False
518    glob['PRINTING'] = False
519    glob['LIST'] = {}
520
521    glob['platform_data'] = get_platform_data()
522
523    THREADS = dict()
524    THREADS['monitor'] = Process(target=monitor, name='monitor')
525    THREADS['monitor'].daemon = glob['DAEMON_MODE']
526
527    THREADS['timed_send'] = Process(target=timed_send, name='timed_send')
528    THREADS['timed_send'].daemon = glob['DAEMON_MODE']
529
530    THREADS['update_list'] = Process(target=update_list, name='update_list')
531    THREADS['update_list'].daemon = glob['DAEMON_MODE']
532
533    THREADS['monitor'].start()
534    THREADS['timed_send'].start()
535    THREADS['update_list'].start()
536
537    signals = {'SIGTERM': interrupt, 'SIGINT': interrupt, 'SIGUSR1': clean_and_send, 'SIGUSR2': show_captured}
538    for sig in oldsignals:
539        if sig in signals:
540            signal.signal(signal.__dict__[sig], signals[sig])
541        else:
542            try:
543                signal.signal(signal.__dict__[sig], oldsignals[sig])
544            except:
545                continue
546
547
548def clean_and_send(*args, **kwargs):
549    global glob, log
550
551    override_send_permission = get_var_value('override_send_permission', glob['config'], mode='bool')
552
553    if allow_send() or override_send_permission:
554        send_data(glob['LIST'])
555    else:
556        log.info('Sending not allowed when try to send results')
557    glob['LIST'] = {}
558
559
560def get_mac():
561    global log
562
563    dirmac = '/sys/class/net'
564    eth = 'eth0'
565    filemac = 'address'
566    file = '{}/{}/{}'.format(dirmac, eth, filemac)
567    uid = None
568    try:
569        with open(file, 'r') as fp:
570            uid = bin_to_ascii(fp.read()).strip()
571    except:
572        log.warning('Unable to read {}'.format(file))
573        eth = sorted(os.listdir(dirmac))
574        if len(eth) > 0:
575            eth = eth[0]
576        file = '{}/{}/{}'.format(dirmac, eth, filemac)
577        try:
578            with open(file, 'r') as fp:
579                uid = bin_to_ascii(fp.read()).strip()
580        except Exception as e:
581            log.error('Unable to read mac address, {}'.format(e))
582
583    return str(uid)
584
585
586def get_cpu():
587    global log
588
589    file = '/proc/cpuinfo'
590    cpu = {}
591    try:
592        with open(file, 'r') as fp:
593            for line in fp:
594                if re.search('^processor\s+:\s+([0-9]+)$', line):
595                    m = re.findall('^processor\s+:\s+([0-9]+)', line)
596                    if m and len(m) > 0:
597                        cpu['ncpus'] = int(m[0]) + 1
598                if re.search('^model name\s+:\s+(.+)$', line):
599                    m = re.findall('^model name\s+:\s+(.+)$', line)
600                    if m and len(m) > 0:
601                        cpu['model'] = str(m[0])
602    except Exception as e:
603        log.warning('Unable to read cpuinfo, {}'.format(e))
604        cpu = None
605    return cpu
606
607
608def get_mem():
609    global log
610
611    file = '/proc/meminfo'
612    mem = None
613
614    try:
615        with open(file, 'r') as fp:
616            for line in fp:
617                if re.search('^MemTotal:\s+([0-9]+)\s+\S+$', line):
618                    m = re.findall('^MemTotal:\s+([0-9]+)\s+\S+$', line)
619                    if m and len(m) > 0:
620                        mem = int(m[0])
621                        break
622    except Exception as e:
623        log.warning('Unable to read meminfo, {}'.format(e))
624        mem = None
625    return str(mem)
626
627
628def get_vga():
629    global log
630
631    vga = None
632    try:
633        out = bin_to_ascii(subprocess.check_output(['lspci'])).split('\n')
634        for line in out:
635            line_strip = line.strip()
636            if re.search('VGA', line_strip, re.IGNORECASE):
637                m = re.findall('^\S+\s(.+)$', line_strip)
638                if m and len(m) > 0:
639                    vga = m[0]
640                    break
641    except Exception as e:
642        log.warning('Unable to read pciinfo, {}'.format(e))
643        vga = None
644    return str(vga)
645
646
647def get_arch():
648    global log
649
650    arch = None
651    try:
652        arch = bin_to_ascii(subprocess.check_output(['uname', '-m'])).strip()
653    except Exception as e:
654        log.warning('Unable to read architecture, {}'.format(e))
655        arch = None
656    return str(arch)
657
658
659def get_platform_data():
660    global log
661
662    data = {}
663    data.setdefault('mac', get_mac())
664    data.setdefault('cpu', get_cpu())
665    data.setdefault('mem', get_mem())
666    data.setdefault('vga', get_vga())
667    data.setdefault('arch', get_arch())
668
669    log.debug("Detected mac='{}' arch='{}' cpu='{}' mem='{}' vga='{}'".format(data['mac'], data['arch'], data['cpu'], data['mem'], data['vga']))
670    return data
671
672
673def send_data(data):
674    global log, glob
675
676    log.debug('sending specs {}'.format(glob['platform_data']))
677    log.debug('sending data {}'.format(glob['LIST']))
678
679    agent = glob['user_agent']
680    url = 'http://' + glob['server'] + '/' + glob['server_path']
681    headers = {'user-agent': agent}
682
683    version = glob['release']
684    flavour = glob['flavour']
685
686    list_data = data
687    try:
688        json_list_data = json.dumps(list_data)
689    except Exception as e:
690        log.error('Json error on internal data list')
691        return None
692
693    platform_data = glob['platform_data']
694    uid = platform_data['mac']
695
696    data_to_send = dict()
697    data_to_send.setdefault('uid', uid)
698    data_to_send.setdefault('vers', version)
699    data_to_send.setdefault('sab', flavour)
700    data_to_send.setdefault('specs', platform_data)
701    data_to_send.setdefault('stats', json_list_data)
702
703    try:
704        json_data_to_send = json.dumps(data_to_send)
705    except Exception as e:
706        log.error('Json error on data to send')
707        return None
708
709    payload = {'stats': json_data_to_send}
710    log.debug('Payload to send: {}'.format(payload))
711
712    sent = False
713    rq = None
714    if glob['use_proxy']:
715        proxy_obj = dict()
716        proxy_obj.setdefault('http', glob['proxy'])
717        try:
718            rq = requests.post(url, data=payload, headers=headers, proxies=proxy_obj, timeout=5)
719            sent = True
720        except Exception as e:
721            log.error('Error sending data through proxy, {}'.format(e))
722
723    if not glob['use_proxy'] or sent == False:
724        try:
725            rq = requests.post(url, data=payload, headers=headers, timeout=5)
726            sent = True
727        except Exception as e:
728            log.error('Error sending data, {}'.format(e))
729
730    if sent and rq:
731        result = rq.text
732        result = result.strip().lower()
733        if result == 'ok':
734            log.debug('Sending was success with reply OK ')
735        elif result == 'nok':
736            log.info('Sending was success but reply is NOK ')
737        else:
738            log.warning("Sending was success but reply is unknown '{}'".format(result))
739    else:
740        log.warning('Unable to send data')
741
742
743def interrupt(*args, **kwargs):
744    global glob, log, THREADS
745
746    log.info('Interrupting analytics')
747    try:
748        clean_and_send()
749        try:
750            glob['TERMINATE'] = True
751        except:
752            log.error('Requested kill the program')
753            sys.exit(1)
754        for x in THREADS:
755            THREADS[x].join()
756
757    except Exception as e:
758        log.error('Error while interrupting, {}'.format(e))
759
760
761def show_captured(*args, **kwargs):
762    global glob, log
763
764    glob['PRINTING'] = True
765    log.info('Requested to show list')
766
767    list_items = glob['LIST']
768    if not isinstance(list_items, dict):
769        log.warning('Error showing captured items, LIST is not a dictionary')
770
771    listkeys_sorted = sorted(list_items, key=list_items.get, reverse=True)
772
773    if len(listkeys_sorted) > 0:
774        log.info('analytics is showing currently capture list in memory')
775        for i in listkeys_sorted:
776            log.info('{} = {}'.format(i, list_items.get(i)))
777    else:
778        log.info('analytics detect an empty capture list in memory')
779
780    glob['PRINTING'] = False
781
782
783def check_server_acknowledge():
784    global log
785
786    try:
787        c = client.ServerProxy("https://server:9779/",
788                               verbose=False,
789                               use_datetime=True,
790                               context=ssl._create_unverified_context())
791        return c.get_variable("", "VariablesManager", "STATS_ENABLED")
792    except Exception as e:
793        log.error('Error getting variables, {}'.format(e))
794        return None
795
796
797def check_local_acknowledge():
798    global glob, log
799
800    if glob['TERMINATE']:
801        return None
802
803    try:
804        statusfile = get_var_value('statusfile', glob['config'])
805        if str(statusfile) == 'None':
806            statusfile = '/etc/lliurex-analytics/status'
807            log.warning('Warning statusfile not set, defaulting to {}'.format(statusfile))
808    except Exception as e:
809        log.error('Error getting value for statusfile, {}'.format(e))
810
811    answer = None
812    try:
813
814        if os.path.isfile(statusfile):
815            fp = open(statusfile, 'r')
816            answer = fp.readline()
817            fp.close()
818        else:
819            log.error('wrong statusfile {}'.format(statusfile))
820            return None
821
822        return answer.strip()
823    except Exception as e:
824        log.warning('Error reading status file, {}'.format(e))
825        return None
826
827
828def allow_send():
829    global glob, log
830
831    if glob['TERMINATE']:
832        return False
833
834    if glob['flavour'].lower() == 'server':
835        answer = str(check_server_acknowledge())
836        answer = answer.strip()
837        if answer == '1':
838            log.info('Allowed to send stats checking server acknowledge')
839            return True
840        elif answer == '0':
841            log.info('Denied to send stats checking server acknowledge')
842            return False
843        elif answer == 'None':
844            pass
845        else:
846            log.info('Unknown value checking server acknowledge, {}'.format(answer))
847    answer = str(check_local_acknowledge()).lower()
848    answer = answer.strip()
849    if answer == 'yes':
850        log.info('Allowed to send stats checking local acknowledge')
851        return True
852    elif answer == 'no':
853        log.info('Denied to send stats checking local acknowledge')
854        return False
855    elif answer == '':
856        pass
857    else:
858        log.info('Unknown value checking local acknowledge, {}'.format(answer))
859
860    log.info('Denied to send stats by default')
861    return False
862
863
864if __name__ == '__main__':
865
866    try:
867        CONFIG = init_config()
868    except Exception as e:
869        print('Error initializing config analytics {}'.format(e), file=sys.stderr)
870        sys.exit(1)
871    try:
872        init_logging(CONFIG)
873    except Exception as e:
874        print('Error initializing logging analytics {}'.format(e), file=sys.stderr)
875        sys.exit(1)
876
877    THREADS = {}
878
879    DAEMON_MODE = get_var_value('DAEMON_MODE', CONFIG, 'bool')
880
881    if DAEMON_MODE:
882        daemonize(daemon_mode=True)
883    else:
884        start(daemon_mode=False)
885
886    log.debug('End main')
887    ended = False
888    while not ended:
889        for t in THREADS:
890            THREADS[t].join()
891            if THREADS[t].is_alive():
892                ended = False
893                break
894            else:
895                ended = True
896                continue
897
898    log.info('Exitting analytics')
899    sys.exit(0)
Note: See TracBrowser for help on using the repository browser.