source: lliurex-gdrive/trunk/fuentes/python-lliurex-gdrive/lliurex/lliurexgdrive/__init__.py @ 6334

Last change on this file since 6334 was 6334, checked in by jrpelegrina, 2 years ago

New feature: Sync specific folder

  • Property svn:executable set to *
File size: 17.9 KB
Line 
1#!/usr/bin/env python
2import glob
3import ConfigParser
4import os
5import json
6import subprocess
7import shutil
8import urllib2
9import datetime
10import platform
11import time
12import tempfile
13
14
15DEBUG=False
16GDRIVE_CONFIG_DIR=os.path.expanduser("~/.gdfuse/")
17LLIUREX_CONFIG_FILE_64='/usr/share/lliurex-gdrive/llx-data/config_64'
18LLIUREX_CONFIG_FILE_32='/usr/share/lliurex-gdrive/llx-data/config_32'
19       
20
21
22class LliurexGoogleDriveManager(object):
23
24        def __init__(self):
25
26                super(LliurexGoogleDriveManager, self).__init__()
27
28                self.config_dir=os.path.expanduser("~/.config/lliurex-google-drive-profiles/")
29                self.config_file=self.config_dir+"configProfiles"
30               
31                self.mount_cmd="google-drive-ocamlfuse -label %s %s"
32                self.clean_cache="google-drive-ocamlfuse -cc -label %s"
33
34                self.gdrive_path=[]
35                self.read_gdrive_folder=False
36
37                self.read_conf()
38               
39
40        #def init
41
42        def create_conf(self):
43
44                if not os.path.exists(self.config_dir):
45                        os.makedirs(self.config_dir)
46
47                var={}
48                # var["default"]={}
49                # var["default"]["email"]=""
50                # var["default"]["mountpoint"]=""
51                # var["default"]["automount"]=""
52
53                f=open(self.config_file,"w")
54                data=unicode(json.dumps(var,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
55
56                f.write(data)
57                f.close()
58
59                msg_log="Creating conf..."
60                self.dprint(msg_log)
61               
62
63        #def create_conf
64       
65        def read_conf(self):
66               
67                if not os.path.exists(self.config_file):
68                        self.create_conf()
69               
70                log_msg="------------------------------------------\n"+"LLIUREX-GDRIVE STARTING AT: " + datetime.datetime.today().strftime("%d/%m/%y %H:%M:%S") +"\n------------------------------------------"
71                self.log(log_msg)
72                msg_log="Init: Reading conf..."
73                self.dprint(msg_log)
74                self.log(msg_log)
75                       
76                f=open(self.config_file)
77                try:
78                        self.profiles_config=json.load(f)
79                except:
80                        self.profiles_config={}
81                f.close()
82               
83        #def read_conf
84       
85        def check_config(self,profile):
86               
87                path=GDRIVE_CONFIG_DIR+profile+"/state"
88                profile=profile.encode("utf-8")
89
90                if os.path.exists(path):
91                        f=open(path)
92                        line=f.readline()
93                        f.close()
94               
95                        if "1970-" in line:
96                                msg_log="Check config: '%s' not configured"%profile
97                                self.dprint(msg_log)
98                                self.log(msg_log)
99                                return False
100                       
101                        msg_log="Check config: '%s' yet configured"%profile
102                        self.dprint(msg_log)
103                        self.log(msg_log)
104                        return True
105
106                else:
107                        msg_log="Check config: '%s' not yet create"%profile
108                        self.dprint(msg_log)
109                        self.log(msg_log)
110                        return False
111
112               
113        #def check_config
114
115        def check_google_connection(self):
116
117                try:
118                        req=urllib2.Request("http://google.com")
119                        res=urllib2.urlopen(req)
120                        return True
121                except:
122                        msg_log="Check connection: Cannot connect to google.com"
123                        self.dprint(msg_log)
124                        self.log(msg_log)
125                        return False
126
127        #def check_google_connection           
128       
129        def mount_drive(self,profile,mountpoint):
130               
131                #profile=profile.encode("utf-8")
132                #mountpoint=mountpoint.encode("utf-8")
133                               
134                try:
135                       
136                        if os.path.exists(GDRIVE_CONFIG_DIR+profile):
137                                check= self.check_config(profile)
138                                if check:
139                                        #if profile in self.profiles_config:
140                                                #mount_point=os.path.expanduser(self.profiles_config[profile]["mountpoint"])
141                                                #if type(mount_point)==type(u""):
142                                                if mountpoint!="":
143                                                        self.dprint("Mounting '%s'..."%profile)
144                                                        if not os.path.exists(mountpoint):
145                                                                try:
146                                                                        os.makedirs(mountpoint)
147                                                                except:
148                                                                        msg_log="Mount drive: Unable to create '%s' mount destination"%mountpoint.encode("utf-8")
149                                                                        self.dprint(msg_log)
150                                                                        self.log(msg_log)
151                                                                        return {"result":False,"code":1}
152                                                               
153
154                                                        if os.access(mountpoint,os.W_OK):
155                                                                #os.system(self.mount_cmd%(profile,mountpoint))
156                                                                cmd=self.mount_cmd%(profile,mountpoint)
157                                                                p=subprocess.Popen(cmd,shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
158                                                                poutput,perror=p.communicate()
159                                                                if len(perror)==0:
160                                                                        msg_log="Mount drive: drive '%s' mounted sucessfully:"%mountpoint.encode("utf-8")
161                                                                        self.dprint(msg_log)
162                                                                        self.log(msg_log)
163                                                                        return {"result":True,"code":0}
164
165                                                                else:
166                                                                        msg_log="Mount drive: Error mount '%s': %s"%(mountpoint.encode("utf-8"),str(perror))
167                                                                        self.code=2
168                                                                        self.dprint(msg_log)
169                                                                        self.log(msg_log)
170                                                                                                                                       
171                                                        else:
172                                                                msg_log="Mount drive: Mount drive: '%s' mount destination is not owned by user"%mountpoint.encode("utf-8")
173                                                                self.code=3
174                                                                self.dprint(msg_log)
175                                                                self.log(msg_log)
176                                                               
177                                                else:
178                                                        msg_log="Mount drive: No mount point indicated"
179                                                        self.code=4
180                                                        self.dprint(msg_log)
181                                                        self.log(msg_log)
182                                else:
183                                        msg_log="Mount drive: '%s' mount point not configured"%profile.encode("utf-8")
184                                        self.code=5
185                                        self.dprint(msg_log)
186                                        self.log(msg_log)
187                        else:
188                                msg_log="Mount drive: '%s' GDrive profile path does not exist"%profile.encode("utf-8")
189                                self.code=6
190                                self.dprint(msg_log)
191                                self.log(msg_log)
192                               
193                except Exception as e:
194
195                        raise e
196                       
197                       
198                return {"result":False,"code":self.code} 
199
200        #def mount_drive
201       
202        def mount_drives(self):
203               
204                if self.check_google_connection():
205                        for profile in self.profiles_config:
206                                automount=self.profiles_config[profile]["automount"]
207                                if automount:
208                                        mountpoint=self.profiles_config[profile]["mountpoint"]
209                                        #profile=profile.encode("utf-8")
210                                        #mountpoint=mountpoint.encode("utf-8")
211                                        self.mount_drive(profile,mountpoint)
212                                               
213               
214        #def mount_drives
215
216        def dprint(self,msg):
217               
218                if DEBUG:
219                        print("[LGDM] %s"%msg)
220                       
221        #def dprint
222       
223       
224        def save_profiles(self,info):
225               
226                self.profiles_config=info
227               
228                f=open(self.config_file,"w")
229                #data=json.dumps(info,indent=4,encoding="utf-8",ensure_ascii=False)
230                data=unicode(json.dumps(info,indent=4,encoding="utf-8",ensure_ascii=False)).encode("utf-8")
231                f.write(data)
232                f.close()
233
234        #def save_profiles     
235
236        def check_mountpoint_status(self,mountpoint,arg=None):
237
238                mountpoint_size=""
239                mountpoint_used=""
240                mountpoint_available=""
241                mountpoint_per=""
242                error=False
243                tmp=[]
244                connect=True
245               
246                if arg!=None:
247                        connect=self.check_google_connection()
248               
249                if connect:
250                        command='df -h | grep "google-drive-ocamlfuse" | grep ' +mountpoint+'$' 
251                               
252                        p=subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
253                        poutput,perror=p.communicate()
254
255                        if len(poutput)>0:
256                                status=True
257
258                                for item in poutput.split(" "):
259                                        if len(item)>1:
260                                                tmp.append(item)
261
262                                mountpoint_size=tmp[1]
263                                mountpoint_used=tmp[2]
264                                mountpoint_available=tmp[3]
265                                mountpoint_per=tmp[4]
266
267                        else:
268                                if len(perror)>0:
269                                        error=True
270                                        status=False
271                                        self.dismount_mountpoint(mountpoint)
272                                else:   
273                                        status=False
274                else:
275                        status=None
276                                       
277                return {"status":status,"size":mountpoint_size,"used":mountpoint_used,"available":mountpoint_available,"used%":mountpoint_per,"error":error}           
278               
279        #def check_mountpoint_status   
280               
281        def check_profile_info(self,profile,mountpoint,edition,root_folder,gdrive_folder):
282       
283                '''
284                        code=0: Form OK
285                        code=10: Profile empty
286                        code=11: Profile with blanck spaces
287                        code=12: Profile duplicate
288                       
289                '''     
290                #profile=profile.decode("utf-8")
291                ###############NUEVO PUNTO ##########""
292                if not edition:
293
294                       
295                        # type(unicode) ==> encode("utf-8")
296                        # type(str) ==> decode("utf-8")
297                       
298
299                        if profile=="":
300                                return {"result":False,"code":10}
301
302                        if ' ' in profile:
303                                return {"result":False,"code":11}
304       
305                        else:
306                                for item in self.profiles_config:
307                                        if profile==item:
308                                                return {"result":False,"code":12}
309
310                else:
311
312                        if root_folder:
313                                if len(self.gdrive_path)>1:
314                                        if gdrive_folder=="":
315                                                return {"result":False,"code":17}
316                                        else:
317                                                cont=0
318                                                for item in self.gdrive_path:
319                                                        if type(item) is str:
320                                                                item=item.decode("utf-8")
321                                                        if item == gdrive_folder:
322                                                                cont=cont+1
323                                                if cont==0:
324                                                        return {"result":False,"code":19}       
325
326                                else:
327                                        if self.read_gdrive_folder==True:
328                                                return {"result":False,"code":20}
329                                        else:
330                                                tmp_mountpoint=tempfile.mkdtemp('_Gdrive')
331                                                cmd=self.clean_cache%profile
332                                                os.system(cmd)
333                                                self.mount_drive(profile,tmp_mountpoint)
334                                                status=self.check_mountpoint_status(tmp_mountpoint)
335
336                                                if not status['error']:
337                                                        self.dismount_mountpoint(tmp_mountpoint,profile)
338                                                        error=False
339                                                else:
340                                                        error=True
341
342                                                try:
343                                                        shutil.rmtree(tmp_mountpoint)
344
345                                                except Exception as e:
346                                                        pass
347
348                                                if error:
349                                                        return {"result":False,"code":19}                               
350
351                '''
352                for item in self.profiles_config:
353                        if profile!=item:
354                                if mountpoint==self.profiles_config[item]["mountpoint"]:
355                                        return {"result":False,"code":4}
356
357
358                if not os.access(mountpoint,os.W_OK):
359                        return {"result":False,"code":6}
360                       
361
362                if os.listdir(mountpoint):
363                        if not edition:
364                                return {"result":False,"code":5}       
365                        else:
366                                if mountpoint != self.profiles_config[profile]["mountpoint"]:
367                                        return {"result":False,"code":5}                                       
368
369
370                return {"result":True,"code":0}                                                         
371                       
372                '''
373                return self.check_mountpoint_folder(profile,mountpoint,edition)
374
375       
376        #def check_profile_info
377
378
379        def check_mountpoint_folder(self,profile,mountpoint,edition):
380
381                '''
382                        code=13: Mountpoint duplicate
383                        code=14: Mountpoint not empty
384                        code=15: Mountpoint not owned by user
385                '''
386
387                for item in self.profiles_config:
388                        if profile!=item:
389                                if mountpoint==self.profiles_config[item]["mountpoint"]:
390                                        return {"result":False,"code":13}
391
392                if not os.access(mountpoint,os.W_OK):
393                        return {"result":False,"code":15}
394                       
395                if ' ' in mountpoint:
396                        return {"result":False,"code":16}       
397
398                if os.listdir(mountpoint):
399                        if not edition:
400                                return {"result":False,"code":14}       
401                        else:
402                                if mountpoint != self.profiles_config[profile]["mountpoint"]:
403                                        return {"result":False,"code":14}                                       
404
405               
406                return {"result":True,"code":0}         
407
408        #def check_mountpoint_folder   
409       
410
411        def create_profile(self,profile):
412
413                #profile=unicode(profile).encode("utf-8")
414                path=GDRIVE_CONFIG_DIR+profile+"/config"
415
416                if not self.check_config(profile):
417                        os.system("google-drive-ocamlfuse -label %s"%unicode(profile).encode("utf-8"))
418                        msg_log=("'%s' profile has been create")%profile.encode("utf-8")
419                        self.log(msg_log)
420                        self.dprint(msg_log)
421
422                        if os.path.exists(GDRIVE_CONFIG_DIR+profile):
423                                if platform.architecture()[0]=='64bit':
424                                        shutil.copy(LLIUREX_CONFIG_FILE_64,path )
425                                else:
426                                        shutil.copy(LLIUREX_CONFIG_FILE_32,path )
427                                               
428               
429                return True
430                               
431                       
432        #def create_profile
433
434        def create_mountpoint(self,info,profile):
435
436                mountpoint=info[profile]["mountpoint"]
437
438                result=self.mount_drive(profile,mountpoint)
439               
440                if result["result"]:
441                        self.save_profiles(info)
442                else:
443                        if profile !="":
444                                if os.path.exists(GDRIVE_CONFIG_DIR+profile):
445                                        shutil.rmtree(os.path.join(GDRIVE_CONFIG_DIR+profile))
446                                        self.dprint("'%s' profile has been delete"%profile)
447                       
448                return result
449
450        #def create_mountpoint 
451
452        def dismount_mountpoint(self,mountpoint,profile=None):
453
454                if profile != None:
455                        cmd='fusermount -u -z ' + mountpoint + ";"+self.clean_cache%profile
456                else:
457                        cmd='fusermount -u -z ' + mountpoint   
458
459                p=subprocess.Popen(cmd, shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
460                poutput,perror=p.communicate()
461
462                mountpoint=mountpoint.encode("utf-8")
463                if len(perror)>0:
464                        msg_log="Dismount mountpoint: Error dismounted '%s': '%s'"%(mountpoint,str(perror))
465                        self.dprint(msg_log)
466                        self.log(msg_log)
467                        result=False
468                        code=7
469                else:
470                        msg_log="Dismount mountpoint:'%s' mountpoint has been dismounted"%mountpoint
471                        self.dprint(msg_log)
472                        self.log(msg_log)
473                        result=True
474                        code=0                                 
475
476                return {"result":result,"code":code}
477
478        #def dismount_mountpoint       
479
480        def delete_profile(self,info,profile):
481
482                result={}
483                dismount={}
484                dismount["result"]=True
485                dismount["code"]=0
486
487                connect=self.check_google_connection()
488                #profile=str(profile)
489                #if connect:
490                mountpoint=self.profiles_config[profile]["mountpoint"]
491                       
492                if os.path.exists(GDRIVE_CONFIG_DIR+profile):
493                        is_mountpoint_mounted=self.check_mountpoint_status(mountpoint,True)
494
495                        if is_mountpoint_mounted["status"]==None:
496                                result['result']=False
497                                result['code']=8
498                        else:
499                                if is_mountpoint_mounted["status"]:     
500                                        dismount=self.dismount_mountpoint(mountpoint,profile)
501
502                                if dismount["result"]:
503                                        if profile!="":
504                                                shutil.rmtree(os.path.join(GDRIVE_CONFIG_DIR+profile))
505                                                msg_log="Delete profile: '%s' profile has been delete"%profile.encode("utf-8")
506                                                self.log(msg_log)
507                                                self.dprint(msg_log)
508                                        self.save_profiles(info)
509                               
510                                return dismount
511                               
512
513                else:
514                        self.save_profiles(info)
515                        msg_log="Delete profile: '%s' GDrive profile path does not exist"%profile.encode("utf-8")
516                        self.log(msg_log)
517                        self.dprint(msg_log)
518                        result['result']=True
519                        result['code']=0
520               
521                return result
522               
523                       
524        #def delete_profile     
525
526       
527        def edit_profile(self,info,profile):
528
529                result={}
530                result["result"]=True
531                result["code"]=0
532
533                change_config=False
534
535                old_mountpoint=self.profiles_config[profile]["mountpoint"]
536                old_automount=self.profiles_config[profile]["automount"]
537                new_mountpoint=info[profile]["mountpoint"]
538                new_automount=info[profile]["automount"]
539               
540                try:
541                        old_root_folder=self.profiles_config[profile]["root_folder"]
542                        old_gdrive_folder=self.profiles_config[profile]["gdrive_folder"]
543                except Exception as e:
544                        old_root_folder=""
545                        old_gdrive_folder=""   
546
547                new_root_folder=info[profile]["root_folder"]
548                new_gdrive_folder=info[profile]["gdrive_folder"]
549
550
551                if new_root_folder != old_root_folder:
552                        change_config=True
553
554                else:
555                        if      old_gdrive_folder !=new_gdrive_folder:
556                                change_config=True
557               
558                status=self.check_mountpoint_status(old_mountpoint)
559                       
560                if old_mountpoint!=new_mountpoint:
561                                       
562                        if status["status"]:
563                                result=self.dismount_mountpoint(old_mountpoint,profile)
564                                                                       
565                                if result["result"]:
566                                        if change_config:
567                                                self.change_config_file(profile,new_gdrive_folder)
568                                        result=self.mount_drive(profile,new_mountpoint)
569                        else:
570                                if change_config:
571                                        self.change_config_file(profile,new_gdrive_folder)                     
572
573                else:
574                        if change_config:
575                                if status["status"]:
576                                        result=self.dismount_mountpoint(old_mountpoint,profile)
577                                        if result["result"]:
578                                                self.change_config_file(profile,new_gdrive_folder)
579                                                result=self.mount_drive(profile,new_mountpoint)
580                                else:
581                                        self.change_config_file(profile,new_gdrive_folder)
582               
583
584                               
585                if result["result"]:
586                        self.save_profiles(info)
587                        msg_log="Edit profile: '%s' profile has been edited"%profile.encode("utf-8")
588                        self.log(msg_log)
589                        self.dprint(msg_log)
590
591                return {"result":result["result"],"code":result["code"]}               
592
593        #def edit_profile                       
594
595        def sync_profile(self,profile,mountpoint,current_status):
596               
597                result={}
598                status=self.check_mountpoint_status(mountpoint,True)
599       
600                if status["status"]==None:
601                        result['result']=False
602                        result['code']=8
603                       
604                else:
605                        if current_status!=None and status['status']==current_status:
606                                if status['status']:
607                                        result=self.dismount_mountpoint(mountpoint,profile)
608                                else:
609                                        if not status['error']:
610                                                result=self.mount_drive(profile,mountpoint)
611                                        else:
612                                                result['result']=False
613                                                result['code']=18
614                                                return result,status
615                       
616                        else:
617                                result['result']=True
618                                result['code']=9
619                               
620                        status=self.check_mountpoint_status(mountpoint) 
621                        if status['error']:
622                                result['result']=False
623                                result['code']=18
624               
625                return result,status   
626
627                #result["result"]:result["result"]
628                #result["code"]:result["code"]
629                #return {"result":result["result"],"code":result["code"]}       
630
631        #def_sync_profile       
632
633        def read_mountpoint_directory(self,profile):
634
635                result={}
636                result['result']=True
637                path_orig=GDRIVE_CONFIG_DIR+profile+"/config"
638                path_tmp=GDRIVE_CONFIG_DIR+profile+"/config_tmp"
639                create_tmp=False
640                copy_config=False
641                directory=[]
642               
643
644                mountpoint=self.profiles_config[profile]["mountpoint"]
645                       
646               
647                try:
648                        root_folder=self.profiles_config[profile]["root_folder"]
649                except Exception as e:
650                        root_folder=False
651               
652
653                status=self.check_mountpoint_status(mountpoint)
654
655                if status["status"]:
656                        if root_folder: 
657                                create_tmp=True
658                                copy_config=True
659
660                else:
661                        create_tmp=True
662                        if root_folder:
663                                copy_config=True
664
665               
666                if copy_config:
667                        if os.path.exists(GDRIVE_CONFIG_DIR+profile):
668                                if os.path.exists(path_orig):
669                                        os.rename(path_orig,path_tmp)
670                                if platform.architecture()[0]=='64bit':
671                                        shutil.copy(LLIUREX_CONFIG_FILE_64,path_orig )
672                                else:
673                                        shutil.copy(LLIUREX_CONFIG_FILE_32,path_orig )
674
675                if create_tmp:
676                                                                       
677                        if status['status']:
678                                cmd=self.clean_cache%profile
679                                os.system(cmd)
680                       
681                        tmp_mountpoint=tempfile.mkdtemp('_Gdrive')                                     
682                        result=self.mount_drive(profile,tmp_mountpoint)
683                               
684                        mountpoint=tmp_mountpoint
685
686               
687                if result['result']:
688
689                        self.gdrive_path=[]
690                        self.read_gdrive_folder=True
691
692                        for base,dirs,file in os.walk(mountpoint):
693                                if 'Trash' not in base:
694                                        if 'shared' not in base:
695                                                if base !=mountpoint:
696                                                        directory.append(base)
697
698                        directory=sorted(directory)
699                       
700                        self.gdrive_path.append('')
701
702                        for item in directory:                 
703                                path=os.path.relpath(item,mountpoint)
704                                self.gdrive_path.append(path)
705
706
707                        if create_tmp:
708                       
709                                if copy_config: 
710                                        os.rename(path_tmp,path_orig)
711                                       
712                                result=self.dismount_mountpoint(mountpoint,profile)
713
714                                if result['result']:
715
716                                        shutil.rmtree(mountpoint)
717                       
718                else:
719                        if copy_config: 
720                                os.rename(path_tmp,path_orig)
721
722                cmd=self.clean_cache%profile
723                os.system(cmd)         
724               
725                return self.gdrive_path
726
727        #def read_mountpoint_directory 
728
729
730        def change_config_file(self,profile,gdrive_folder):
731
732                       
733                file=GDRIVE_CONFIG_DIR+profile+"/config"
734
735
736                old_config=open(file,'r')
737                params=[]
738                cont=0
739                for line in old_config:
740                        if 'root_folder' in line:
741                                line='root_folder='+'/'+gdrive_folder.encode("utf-8")+'\n'     
742                                cont=cont+1
743                        params.append(line)
744                               
745               
746                if cont==0:
747                        line='root_folder='+'\n'
748                        params.append(line)             
749               
750                old_config.close()
751               
752                new_config=open(file,'w')
753
754                for item in params:
755                        new_config.write(item)         
756 
757                new_config.close()
758
759        #def change_config_file
760
761        def log(self,msg):
762               
763                log_file=self.config_dir+"lliurex-gdrive.log"
764
765                f=open(log_file,"a+")
766                f.write(msg + '\n')
767                f.close()       
768
769        #def log                 
770
771if __name__=="__main__":
772
773        llxgd=LliurexGoogleDriveManager()
774        llxgd.mount_drives()
775       
776       
777       
778        #llxgd.save_profiles(llxgd.var)
779       
780
781
782
783
784
785
786
787
788
Note: See TracBrowser for help on using the repository browser.