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

Last change on this file since 5576 was 5576, checked in by hectorgh, 3 years ago

trying to fix utf-8 problems

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