source: lliurex-base-files/trunk/fuentes/install/usr/bin/lliurex-version @ 5428

Last change on this file since 5428 was 5428, checked in by hectorgh, 23 months ago

adding changes to support failed mirror check.

  • Property svn:executable set to *
File size: 17.5 KB
Line 
1#!/usr/bin/python3
2
3#
4# Examples:
5# Export all variables into environment:>  eval export $(lliurex-detect -e -a)
6# Test one condition:> lliurex-detect -x thin && echo si || echo no
7# Test one condition:> if lliurex-detect -x ltsp; then echo si; else echo no; fi
8# Get flavour:> FLA=$(lliurex-detect -f)
9#
10import sys
11import os 
12import pwd,grp
13import argparse
14import re
15# import glob  # Commented: python 3.5 is not available on lliurex 15
16import fnmatch # allows search recursively without glob
17
18from subprocess import check_output
19
20ltsConfFile="/etc/lts.conf"
21
22def detect_live():
23    test1=False
24    test2=False
25    test3=False
26
27    if os.path.isdir('/rofs'):
28        r1=re.compile('^tmpfs\s/cow\stmpfs')
29        r2=re.compile('^/cow\s/\soverlayfs')
30        r3=re.compile('^/dev/loop0\s/rofs\ssquashfs')
31        with open('/proc/mounts') as mounts_file:
32            for line in mounts_file.readlines():
33                if r1.match(line):
34                    test1=True
35                if r2.match(line):
36                    test2=True
37                if r3.match(line):
38                    test3=True
39    if test1 and test2 and test3:
40        pass
41    else:
42        raise Exception('Not live')
43
44#def detect_live():
45
46def detect_flavour():
47# Use with python > 3.5 with glob new features
48#        cdd_content=[]
49#        file_name= [ filename for filename in glob.iglob('/usr/share/lliurex-cdd/**/cddflavour', recursive=True) ]
50#        if len(file_name) > 0:
51#           for cddfile in file_name:
52#               try:
53#                    with open(cddfile,'r') as fileccd:
54#                       cdd= [ line.strip() for line in fileccd ]
55#                       cdd_content.extend(cdd)
56#               except Exception as e:
57#                   raise Exception('cddflavour error '+str(e))
58#        else:
59#            file_name= [ filename for filename in glob.iglob('/usr/share/lliurex-cdd/**/cddversion', recursive=True) ]
60#            if len(file_name) > 0:
61#                for cddfile in file_name:
62#                    try:
63#                       with open(cddfile,'r') as fileccd:
64#                          cdd= [ line.strip() for line in fileccd ]
65#                          cdd_content.extend(cdd)
66#                    except Exception as e:
67#                        raise Exception('cddversion file error '+str(e))
68#            else:
69#               raise Exception('cddflavour or cddversion file not found! ')
70#       cdd_content=list(set(cdd_content))
71#       cdd_content.sort()
72#       return cdd_content
73
74# Code for python < 3.5 without glob
75        file_name=[]
76        cdd_content=[]
77        for root,dirnames,filenames in os.walk('/usr/share/lliurex-cdd'):
78            for filename in fnmatch.filter(filenames,'cddflavour'):
79                file_name.append(os.path.join(root,filename))
80        if len(file_name) > 0:
81            for cddfile in file_name:
82                try:
83                    with open(cddfile,'r') as fileccd:
84                        cdd= [ line.strip() for line in fileccd ]
85                        cdd_content.extend(cdd)
86                except Exception as e:
87                    cdd_content.append('None')
88                    #raise Exception('cddflavour file error '+str(e))
89        else:
90            for root,dirnames,filenames in os.walk('/usr/share/lliurex-cdd'):
91                for filename in fnmatch.filter(filenames,'cddversion'):
92                    file_name.append(os.path.join(root,filename))
93            if len(file_name) > 0:
94                for cddfile in file_name:
95                    try:
96                        with open(cddfile,'r') as fileccd:
97                            cdd= [ line.strip() for line in fileccd ]
98                            cdd_content.extend(cdd)
99                    except Exception as e:
100                        cdd_content.append('None')
101                        #raise Exception('cddversion file error '+str(e))
102            else:
103                #raise Exception('cddflavour or cddversion file not found! ')
104                cdd_content.append('None')
105        cdd_content=list(set(cdd_content))
106        cdd_content.sort()
107        return cdd_content
108#def detect_flavour
109
110def detect_num_cdd():
111    try:
112        with open(os.devnull, 'w') as devnull:
113            num_cdd=check_output(['dpkg-query','--showformat=\'${Version}\'','--show','lliurex-version-timestamp'],stderr=devnull).decode('utf-8')
114        return num_cdd.strip('\'')
115    except Exception as e1:
116        try:
117            with open('/usr/share/lliurex-cdd/version','r') as cdd_num_file:
118                return cdd_num_file.readline().strip()
119        except Exception as e2:
120            return '0'
121            #raise Exception('Error1: '+e1+' and Error2: '+e2)
122#def detect_num_cdd():
123
124def get_history_version():
125    try:
126        with open('/etc/lliurex-cdd-version','r') as etc_cdd_file:
127            return etc_cdd_file.read()
128    except Exception as e:
129        raise Exception('Error: '+e)
130#def get_history_version()
131
132def detect_type():
133#
134#   Possible output values: live,thin,semi,fat,unknown
135#
136#
137
138    display=os.environ.get('DISPLAY')
139    #On thin clients display is ip+display so it's at least 7 chars
140    if display != None and len(display)>= 7:
141        client_type='thin'
142    else:
143        if os.path.exists(ltsConfFile):
144        #Attempt to open lts.conf as is more reliable than check environment
145            try:
146                 re_true=re.compile('LTSP_FATCLIENT(\s)*=(\s)*true',re.IGNORECASE)
147                 re_false=re.compile('LTSP_FATCLIENT(\s)*=(\s)*false',re.IGNORECASE)
148                 with open(ltsConfFile) as ltsfile:
149                      for line in ltsfile.readlines():
150                             if re_true.match(line):
151                                 client_type='semi'
152                                 break
153                             elif re_false.match(line):
154                                 client_type='thin'
155                                 break
156                             else:
157                                 client_type='unknown'
158            except Exception as e:
159                fatclient=os.environ.get('LTSP_FATCLIENT')
160                if fatclient=='true':
161                    client_type="semi"
162                else:
163                    if fatclient=='false':
164                        client_type="thin"
165                    else:
166                        client_type="unknown" 
167        else:
168            client_type='fat'
169    try:
170        detect_live()
171        client_type=client_type+',live'
172    except:
173        pass
174
175    return client_type.rstrip()
176#def detect_type
177
178def detect_user(user=''):
179    if user == '' or user == None:
180        user_id=os.getuid()
181        user_name=pwd.getpwuid(user_id)[0]
182    else:
183        try:
184            user_uid=pwd.getpwnam(user)[3]
185        except:
186            raise Exception('user not found!')
187        user_name=user
188    #user_info [0]=>username [1]=>pwd [2]=>uid [3]=>gid [4]=>gecos [5]=>homedir [6]=>shell
189    #grp_info [0]=>name [1]=>pwd [2]=>gid [3]=>member
190    grupos = [ group[0] for group in grp.getgrall() if user_name in group[3] ]
191    with open('/etc/passwd','r') as filepwd:
192        localusers=[ line.split(':')[0] for line in filepwd.readlines() ]
193
194    ret=user_name
195    if 'admins' in grupos :
196        ret='*'+str(user_name)
197    if user_name in localusers:
198        ret += '/local'
199    else:
200        ret += '/ldap'
201    return ret
202#def detect_user():
203
204def check_mirror():
205    #
206    # Run checks against mirror
207    #
208    mirror_location='/net/mirror/llx16'
209    #dict = check keys & recurse into values
210    #list = check items
211    #tuple = check items(files or regexp) ; syntax=('type','value') where type = 'regexp' or something else to exact match
212    #string = check items
213
214    #need_structure={'pool':[{'main':{'l/lliurex-version-timestamp':('regexp','lliurex-version-timestamp_.*\.deb$')}},'universe','multiverse','preschool','restricted'],
215    #                'dists':['xenial','xenial-security','xenial-updates'],
216    #                'lists':[('regexp','.*xenial.*_amd64_Packages$'),('regexp','.*xenial.*_i386_Packages$')]}
217
218    need_structure={'pool':[{'main':{'l/lliurex-version-timestamp':('regexp','lliurex-version-timestamp_.*\.deb$')}},'universe','multiverse','preschool','restricted'],
219                    'dists':['xenial','xenial-security','xenial-updates']}
220    try:
221        return os.path.isdir(mirror_location) and check_structure(mirror_location,need_structure)
222    except Exception as e:
223        # As a guest user, /net isn't accessible somehow. Nontheless, if something goes wrong, we return False anyway
224        #print(e)
225        return False
226
227def check_structure(path_from,child=''):
228    DBG=False
229    dbg=lambda x: DBG and sys.stdout.write(x+'\n')
230    typeparam=type(child)
231    if typeparam == type(dict()):
232        for item in child:
233            new_path=path_from+'/'+item
234            if not check_structure(path_from,item):
235                return False
236            if not check_structure(new_path,child[item]):
237                return False
238    elif typeparam == type(list()):
239        for item in child:
240            if not check_structure(path_from,item):
241                return False
242    elif typeparam == type(tuple()):
243        mode,value=child
244        if mode=='regexp':
245            reg=re.compile(value)
246            for f in os.listdir(path_from):
247                path_check=path_from+'/'+f
248                dbg('checking file ' + path_check)
249                if os.path.isfile(path_check):
250                    if reg.match(f):
251                        return True
252            return False
253        else:
254            path_check=path_from+'/'+value
255            dbg('checking file ' + path_check)
256            return os.path.isfile(path_check)
257    elif typeparam == type(str()):
258        path_check=path_from+'/'+child
259        dbg('checking dir ' + path_check)
260        if not os.path.isdir(path_check):
261            return False
262    return True
263
264def store_result(results='',namevar='',action='store'):
265    global eval_mode
266    global result
267    global exit_return_code_mode
268
269    if action == 'init':
270        if eval_mode:
271            result={}
272            return 0
273        else:
274            result=[]
275            return 0
276    elif action == 'store':
277        if results=='':
278            raise Exception('Missing param results to store')
279        if eval_mode and namevar=='':
280            raise Exception('Eval mode need namevar param')
281
282        if eval_mode:
283            if namevar=='USERTYPE':
284                res=results
285                if res[0] == '*':
286                    result['PROMOTED_USER']='yes'
287                    res=results[1:]
288                else:
289                    result['PROMOTED_USER']='no'
290                result['USERNAME']=res.split('/')[0]
291                result['LOGIN_TYPE']=res.split('/')[1]
292            elif namevar=='SESSION_TYPE':
293                res=results.split(',')
294                result['LIVE']='no'
295                result['LTSP']='no'
296                result['THIN']='no'
297                result['SEMI']='no'
298                result['FAT']='no'
299
300                if len(res) > 1:
301                    result['LIVE']='yes'
302                if res[0] != 'fat':
303                    result['LTSP']='yes'
304
305                result[res[0].upper()]='yes'
306            elif namevar=='FLAVOUR':
307                res=results[-1]
308                result['SERVER']='no'
309                result['DESKTOP']='no'
310                result['CLIENT']='no'
311                result['INFANTIL']='no'
312                result['MUSIC']='no'
313                result['PIME']='no'
314
315                #lliurex 15 specific options & catch all
316                if res.upper() == 'NETWORK-CLIENT-PROMO':
317                    result['CLIENT']='yes'
318                elif res.upper() == 'LLIUREX':
319                    if 'INFANTIL' in [ x.upper() for x in results ]:
320                        result['INFANTIL']='yes'
321                    else:
322                        result['DESKTOP']='yes'
323                #end lliurex15 specific options
324                elif 'CLIENT' in [ x.upper() for x in results ] and 'EDU' in [ x.upper() for x in results ]:
325                    result['CLIENT']='yes'
326                else:
327                    result[res.upper()]='yes'
328            else:
329                result[namevar]=results
330               
331        else:
332            if type(list()) == type(results):
333                res=results[-1]
334            elif type(str()) == type(results):
335                res=results
336            else:
337                raise Exception('Unknown result type to store')
338            if namevar=='FLAVOUR':
339                #lliurex 15 specific options & catch all
340                if res.upper() == 'NETWORK-CLIENT-PROMO':
341                    res='client'
342                elif res.upper() == 'LLIUREX':
343                    if 'INFANTIL' in [ x.upper() for x in results ]:
344                        res='infantil'
345                    else:
346                        res='desktop'
347                #end lliurex15 specific options
348                elif 'CLIENT' in [ x.upper() for x in results ] and 'EDU' in [ x.upper() for x in results ]:
349                    res='client'
350            result.append(res)
351    elif action == 'print':
352        if exit_return_code_mode != False:
353            if exit_return_code_mode.upper() == 'LOCAL':
354                if result['LOGIN_TYPE']=='local':
355                    sys.exit(0)
356                else:
357                    sys.exit(1)
358            elif exit_return_code_mode.upper() == 'LDAP':
359                if result['LOGIN_TYPE']=='ldap':
360                    sys.exit(0)
361                else:
362                    sys.exit(1)
363            elif exit_return_code_mode.upper() == 'PROMOTED':
364                if result['PROMOTED_USER']=='yes':
365                    sys.exit(0)
366                else:
367                    sys.exit(1)
368            elif exit_return_code_mode.upper() == 'MIRROR':
369                if result['MIRROR']=='True':
370                    sys.exit(0)
371                else:
372                    sys.exit(1)
373            else:
374                if result[exit_return_code_mode.upper()]=='yes':
375                    sys.exit(0)
376                else:
377                    sys.exit(1)
378        if len(result) > 0:
379            if eval_mode:
380                for k,v in result.items():
381                    print(k+'='+v)
382            else:
383                print (','.join(result))
384    else:
385        raise Exception('Unknow action')
386
387
388#def store_result():
389
390
391#
392# MAIN PROGRAM
393#
394
395parser = argparse.ArgumentParser(description='Get information about running environment')
396parser.add_argument('-a','--all',metavar='',action='store_const',help='Get all information',const=True)
397parser.add_argument('-m','--mirror',metavar='',action='store_const',help='Check mirror available',const=True)
398parser.add_argument('-e','--eval',metavar='',action='store_const',help='Show all information to evaluate in bash variables',const=True)
399parser.add_argument('-s','--session',metavar='',action='store_const',help='Get current session type',const=True)
400parser.add_argument('-f','--flavour',metavar='',action='store_const',help='Get the flavour of current system',const=True)
401parser.add_argument('-u','--usertype',metavar='username',nargs='?',const='',help='Get the usertype from current user or from passed username')
402code_types=['live','ltsp','fat','semi','thin','desktop','server','client','infantil','pime','music','local','ldap','promoted','mirror']
403parser.add_argument('-x','--with-return-code',metavar='[live|ltsp|fat|semi|thin|desktop|server|client|infantil|pime|music|local|ldap|promoted|mirror]',nargs=1,choices=code_types,help='Execute mode testing value passed')
404# lliurex-version options
405parser.add_argument('-n','--number',metavar='',action='store_const',const=True,help='Get the cdd number version')
406parser.add_argument('-v','--version',metavar='',action='store_const',const=True,help='Get the cdd version')
407parser.add_argument('-t','--test',metavar='cdd_name',help='Test if the cdd is installed')
408parser.add_argument('--history',metavar='',action='store_const',const=True,help='Get the installed meta\'s history')
409args=parser.parse_args()
410
411#print(args)
412
413args_all=args.all
414#Commented due to compatibility with lliurex-version without parameters
415#args_all=True
416#if args.all != True:
417#    for arg in vars(args):
418#        if getattr(args,arg) != None:
419#            args_all=False
420#            break
421arg_none_for_lliurex_version=True
422if args.all != True:
423    for arg in vars(args):
424        if getattr(args,arg) != None:
425            arg_none_for_lliurex_version=False
426            break
427else:
428    arg_none_for_lliurex_version=False
429
430eval_mode=args.eval
431
432exit_return_code_mode=False
433if args.with_return_code != None:
434    eval_mode=True
435    args_all=True
436    exit_return_code_mode=args.with_return_code[0]
437   
438
439store_result(action='init')
440
441try:
442    if args_all or args.session != None:
443        store_result(detect_type(),'SESSION_TYPE')
444    if args_all or args.flavour != None:
445        store_result(detect_flavour(),'FLAVOUR')
446    if args_all or args.usertype != None:
447        store_result(detect_user(args.usertype),'USERTYPE')
448    if args_all or args.mirror != None:
449        store_result(str(check_mirror()),'MIRROR')
450
451#lliurex version options
452    if args.number != None:
453        print(detect_num_cdd())
454    if args.version != None:
455        print(', '.join(detect_flavour()))
456    if arg_none_for_lliurex_version:
457        ret=detect_flavour()
458        ret.append(detect_num_cdd())
459        print(', '.join(ret))
460    if args.test != None:
461        try:
462            ret=detect_flavour()
463        except:
464            sys.exit(1)
465        if args.test in ret:
466            sys.exit(0)
467        else:
468            sys.exit(1)
469    if args.history != None:
470        print(get_history_version().rstrip())
471#end lliurex-version options
472    store_result(action='print')
473except Exception as e:
474    print('Error '+str(e))
475    sys.exit(1)
476
477sys.exit(0)
Note: See TracBrowser for help on using the repository browser.