source: n4d-netfolders/trunk/fuentes/install-files/usr/share/n4d/python-plugins/NetFoldersManager.py @ 7121

Last change on this file since 7121 was 7121, checked in by hectorgh, 2 years ago

removing mount protection. plugin will always try to create server-sync dir structure

File size: 10.2 KB
Line 
1import os
2import os.path
3import shutil
4import json
5import re
6import subprocess
7import stat
8import grp
9import pwd
10import imp
11import threading
12sambaparser=imp.load_source("SambaParser","/usr/share/n4d/python-plugins/support/sambaparser.py")
13
14
15class NetFoldersManager:
16       
17       
18        LOCAL_CONF_FOLDER="/var/lib/lliurex-folders/local/"
19        SMB_CONF_FOLDER="/var/lib/lliurex-folders/smb/"
20        BASE_DIR="/net/server-sync/"
21       
22        def __init__(self):
23                       
24                self.debug=False       
25               
26                self.acl_thread=threading.Thread()
27               
28                if not os.path.exists(self.LOCAL_CONF_FOLDER):
29                        os.makedirs(self.LOCAL_CONF_FOLDER)
30                if not os.path.exists(self.SMB_CONF_FOLDER):
31                        os.makedirs(self.SMB_CONF_FOLDER)
32               
33        #def __init__
34       
35       
36        def startup(self,options):
37               
38                self.check_local_folders()
39                self.get_shared_folders()
40               
41        #def startup
42       
43        def backup(self,backup_target=None,backup_dest="/backup"):
44                if not backup_dest.endswith("/"):
45                        backup_dest+="/"
46                file_path=backup_dest+get_backup_name("NetFoldersManager")
47                if backup_target is None:
48                        backup_target = [os.path.join(self.BASE_DIR,x) for x in os.listdir(self.BASE_DIR)]
49                return objects['FileUtils'].backup(backup_target,file_path)
50
51        #def backup
52
53        def restore(self,backup_file=None):
54                if backup_file==None:
55                        for f in sorted(os.listdir("/backup"),reverse=True):
56                                if "NetFoldersManager" in f:
57                                        backup_file="/backup/"+f
58                                        break
59                return objects['FileUtils'].restore(backup_file,'/')
60
61        #def restore
62
63        def mount_gluster_volumes(self):
64                try:
65                        list_mount = []
66                        if not os.path.exists('/var/lib/n4d-glusterfs/volumes'):
67                                return True
68                        f = open('/var/lib/n4d-glusterfs/volumes')
69                        lines = f.readlines()
70                        to_mount = [ x[:x.find('#') - 1] for x in lines ]
71                        for x in range(1,10):
72                                mounted=objects['MountManager'].mount_list().keys()
73                                to_mount_b=[]
74                                for item in to_mount:
75                                        #to_mount_b.append(" ".join(item.split(" ")[0]))
76                                        to_mount_b.append(item.split(" ")[0])
77                                to_process=[]
78                                for item in to_mount_b:
79                                        if item not in mounted:
80                                                to_process.append(item)
81                                if len(to_process)==0:
82                                        break
83                                for item in to_mount:
84                                        for item2 in to_process:
85                                                if item.find(item2)!=-1:
86                                                        os.system("mount -t glusterfs -o acl " + item )
87                                                        continue
88                except Exception, e:
89                        pass
90                return True
91
92        #def mount_gluster_volumes
93
94
95        def get_acl_info(self,path):
96               
97                info={}
98                regex="(\w+:|\A)(user|group|mask|other):([a-zA-Z0-9\-]*):([r|w|x|\-]{1,3})\s*[#]*(\S+)*\Z"
99                os.environ["LANG"]="C"
100                p=subprocess.Popen(["getfacl","-n",path],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
101                out=p.communicate()[0]
102               
103                info["acl"]=[]
104                info["perm"]=int(str(oct(stat.S_IMODE(os.lstat(path).st_mode))).lstrip("0"))
105                info["path"]=path
106               
107                for item in out.split("\n"):
108                       
109                        #item=item.strip("\n")
110                        x=re.match(regex,item)
111                       
112                        if x!=None:
113                               
114                                special=x.group(1)
115                                type_=x.group(2)
116                                custom_group=x.group(3)
117                                acl=x.group(4)
118                                extra=x.group(5)
119                               
120                                if special.find("default")!=-1:
121                                        mode="-d -m"
122                                else:
123                                        mode="-m"
124                                       
125                                if type_=="group":
126                                        type_="g:"
127                                elif type_=="user":
128                                        type_="u:"
129                                elif type_=="mask":
130                                        type_="m:"
131                                elif type_=="other":
132                                        type_="o:"
133                                       
134                               
135                                info["acl"].append([mode,type_+custom_group+":"+acl])
136                                       
137
138
139                return info
140               
141        #def get_acl_info
142       
143        def get_missing_acl_conf(self,info):
144               
145                ret=[]
146                ret_={}
147                for f in os.listdir(NetFoldersManager.LOCAL_CONF_FOLDER):
148                        try:
149                                ff=open(NetFoldersManager.LOCAL_CONF_FOLDER+f)
150                                txt="".join(ff.readlines())
151                                ff.close()
152                                orig_info=eval(txt)
153                                for item in orig_info:
154                                        found=False
155                                        if orig_info[item]["path"]==info["path"]:
156                                                for acl in orig_info[item]["acl"]:
157                                                        if not acl in info["acl"]:
158                                                                ret.append(acl)
159                                                        found=True
160                                                       
161                                                if found:
162                                               
163                                                        ret_[info["path"]]={}
164                                                        ret_[info["path"]]["path"]=info["path"]
165                                                        ret_[info["path"]]["perm"]=orig_info[item]["perm"]
166                                                        ret_[info["path"]]["acl"]=ret
167                                                               
168                                                        return(ret_)
169                       
170                       
171                               
172                        except Exception as e:
173                                print e
174                       
175                       
176                return None
177                       
178               
179        #def get_diferences
180       
181        def parse_local_folders_conf(self):
182               
183                for f in sorted(os.listdir(self.LOCAL_CONF_FOLDER)):
184                        try:
185                                #execfile(self.LOCAL_CONF_FOLDER+f)
186                                #self.local_dirs=dict(self.local_dirs.items()+locals()["folder"].items())
187                               
188                                f_=open(self.LOCAL_CONF_FOLDER+f,"r")
189                                data=json.load(f_)
190                                f_.close()                             
191                                self.local_dirs=dict(self.local_dirs.items()+data.items())
192                               
193                        except Exception as e:
194                                print("!!",e,"File: " + f)
195
196
197
198       
199        def check_local_folders(self,recursive=False):
200
201                # this is no longer true. root access had to be enabled after all
202                '''
203                if os.path.exists("/lib/systemd/system/net-server\\x2dsync.mount"):
204                        # Root has no access to /net/server-sync if it is mounted. Returning
205                        return True
206                '''
207
208                self.local_dirs={}
209                #sorted!!!
210               
211                self.parse_local_folders_conf()
212               
213                #path,perm,acl
214               
215                for item in sorted(self.local_dirs.keys()):
216                       
217                        self.dprint("Checking %s configuration..."%item)
218                        path=self.local_dirs[item]["path"]
219                        try:
220                                user = int(self.local_dirs[item]["owner"])
221                        except:
222                                user = int(pwd.getpwnam(self.local_dirs[item]["owner"]).pw_uid)
223                        try:
224                                group = int(self.local_dirs[item]["group"])
225                        except:
226                                group = int(grp.getgrnam(self.local_dirs[item]["group"]).gr_gid)
227                        if not os.path.exists(path):
228                                print("\t* Creating path %s ..."%path)
229                                try:
230                                        os.makedirs(path)
231                                        prevmask=os.umask(0)
232                                        os.chmod(path,int(str(self.local_dirs[item]["perm"]),8))
233                                        os.lchown(path,user,group)
234                                        os.umask(prevmask)
235                                except Exception as e:
236                                        print("!!",e,path)
237
238
239
240                        try:                                   
241                                info=self.get_acl_info(path)
242                                info=self.get_missing_acl_conf(info)
243                               
244                                if ( os.lstat(path).st_uid != user ) or (os.lstat(path).st_gid != group):
245                                        os.lchown(path,user,group)
246                                if int(str(oct(stat.S_IMODE(os.lstat(path).st_mode))).lstrip("0"))!=info[path]["perm"]:
247                                        prevmask=os.umask(0)
248                                        os.chmod(path,int(str(info[path]["perm"]),8))
249                                        os.umask(prevmask)
250                               
251
252                                for acl in info[path]["acl"]:
253                                        print("\t* Setting acls to " + path + " ...")
254                                        options,value=acl
255                                        self.set_acl(path,options,value,recursive)
256                        except Exception as e:
257                                print e
258
259        #def check_local_folders
260       
261        def set_acl(self,path,options,value,recursive=False):
262               
263                if recursive:
264                        recursive="-R"
265                else:
266                        recursive=""
267       
268                if type(path)==type(""):
269                        path=path.decode("utf-8")
270               
271                cmd_str="setfacl %s %s %s '%s'"%(recursive,options,value,path)
272               
273                self.dprint(cmd_str)
274               
275                os.system(cmd_str.encode("utf-8"))
276                #here goes executing command
277               
278        #def set_acl
279       
280        def get_shared_folders(self):
281               
282                self.remote_dirs={}
283               
284                try:
285                        srv_ip=objects["VariablesManager"].get_variable("SRV_IP")
286                except:
287                        pass
288                       
289                if srv_ip!=None:
290                        sp=sambaparser.SambaParser()
291                        for item in os.listdir(self.SMB_CONF_FOLDER):
292                                f=self.SMB_CONF_FOLDER+item
293                                sp.read(f)
294                                for key in sp.conf:
295                                        if key!=None:
296                                                try:
297                                                        line="//"+srv_ip+"/"+key
298                                                        self.remote_dirs[line]={}
299                                                        self.remote_dirs[line]["dst"]=sp.conf[key]["mount_point"]
300                                                        self.remote_dirs[line]["fstype"]="cifs"
301                                                except Exception as e:
302                                                        #print e
303                                                        pass
304                                               
305                return self.remote_dirs
306               
307        #def check_shared_folders
308       
309       
310        def dprint(self,item):
311               
312                if self.debug:
313               
314                        try:
315                                print("[NetFoldersManager] " + str(item) )
316                        except:
317                                pass
318               
319        #def dprint
320
321        def get_acl_group_filtered(self,group):
322                result = []
323                path = self.LOCAL_CONF_FOLDER + os.path.sep + group.lower()
324                if os.path.exists(path):
325                        aux_file = open(path)
326                        list_acl = json.load(aux_file)
327                       
328                        for items in list_acl.values():
329                                for x in items['acl']:
330                                        if '-d' in x[0]:
331                                                x[0] = u'-m'
332                                                result.append(x)
333                        aux_file.close()
334                return result
335               
336               
337        def is_dir_workable(self,current_dir,banned_list):
338               
339                for dir in banned_list:
340                       
341                        if dir in current_dir:
342                               
343                                return False
344                               
345                               
346                return True
347               
348        #def is_dir_workable
349
350
351        def restore_acls(self):
352               
353                try:
354               
355                        self.local_folders={}
356                        self.local_dirs={}
357                        self.parse_local_folders_conf()
358                       
359                        dirs_to_process={}
360                       
361                        for item in self.local_dirs:
362                                dirs_to_process[self.local_dirs[item]["path"]]=""
363                               
364                       
365
366                        for item in self.local_dirs:
367                               
368                               
369                                        owner=self.local_dirs[item]["owner"]
370                                        group=self.local_dirs[item]["group"]
371                                        path=self.local_dirs[item]["path"]
372                                        perm=self.local_dirs[item]["perm"]
373                                        acls=self.local_dirs[item]["acl"]
374                                        file_acls=[]
375                                       
376                                        dirs_to_process.pop(path)
377                                       
378                                        for acl in acls:
379                                                options,value=acl
380                                                if "-d" not in options:
381                                                        file_acls.append(acl)
382                                                       
383                                        '''
384                                        print item
385                                        print "\t",owner,group,path,perm
386                                        print "\t",file_acls
387                                        '''
388                                       
389                                        for walk_item in os.walk(path):
390                                                dir,subdirs,files=walk_item
391                                               
392                                                if self.is_dir_workable(dir,dirs_to_process):
393                                                        #print dir
394                                                        #print "\t",files
395                                                        dir=dir.encode("utf-8") 
396                                                        cmd="setfacl -k -b '" + dir + "'"
397                                                        os.system(cmd)
398                                                       
399                                                        prevmask=os.umask(0)
400                                                        os.chmod(path,int(str(perm),8))
401                                                                                                       
402                                                        for f in files:
403                                                                for acl in file_acls:
404                                                                        options,value=acl
405                                                                        if type(f)==type(u""):
406                                                                                f=f.encode("utf-8")
407                                                                       
408                                                                        self.set_acl(dir+"/"+f,options,value)
409                                                                self.set_acl(dir+"/"+f,"-m","m:rw")
410                                                       
411                                                        for acl in acls:
412                                                                options,value=acl
413                                                                self.set_acl(dir,options,value)
414                                                               
415                                                        os.umask(prevmask)
416                                                       
417                                                       
418                        return [True,""]
419                       
420                       
421                except Exception as e:
422                       
423                        return [False,str(e)]
424               
425               
426        #def restore_acls
427       
428        def restore_acls_via_thread(self):
429               
430                if not self.acl_thread.is_alive():
431                       
432                        self.acl_thread=threading.Thread(target=self.restore_acls)
433                        self.daemon=True
434                        self.acl_thread.start()
435                       
436                       
437                return True
438               
439               
440        #def restore_acls_via_thread
441       
442        def is_acl_thread_alive(self):
443               
444                return self.acl_thread.is_alive()
445
446        #def is_acl_thread_alive
447
448        def restore_teacher_access(self,student):
449
450                folders=["/net/server-sync/home/students/%s/Desktop","/net/server-sync/home/students/%s/Documents"]
451                if pwd.getpwnam(student).pw_uid > 20000:
452
453                        print "Fixing %s ..."%student
454
455                        for folder in folders:
456
457                                os.system("chown %s:nogroup '%s'"%(student,folder%student))
458                                os.system("chmod 770 -R '%s'"%(folder%student))
459
460                        return True
461
462                else:
463                        return False
464
465
466        #def restore_teacher_access
467
468       
469#class NetFoldersManager
470
471if __name__=="__main__":
472       
473        nfm=NetFoldersManager()
474        #nfm.restore_acls()
Note: See TracBrowser for help on using the repository browser.