source: n4d-nfs/trunk/fuentes/install/usr/share/n4d/python-plugins/NfsManager.py @ 5249

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

adding nfsvers=3 to mount options

File size: 8.0 KB
Line 
1import subprocess
2import re
3import os
4import tempfile
5from jinja2 import Environment
6from jinja2.loaders import FileSystemLoader
7from jinja2 import Template
8
9
10class NfsManager:
11       
12        def __init__(self):
13               
14                self.nfs_dir="/etc/exports.d/"
15                self.nfs_file=self.nfs_dir+"net.exports"
16                self.default_options="rw,sync,no_subtree_check,no_root_squash"
17                self.regex_pattern="^(/[\-/\w]+)(\s+)((((\d{1,3}\.){3}\d{1,3})|\w+)\((.*)\)(\s+|$))+"
18                self.file_header="#\n# File generated by NfsManager plugin. Do not edit\n#\n\n"
19               
20                self.default_mount_options="rw,hard,intr,nosuid,nfsvers=3"
21                self.tpl_env = Environment(loader=FileSystemLoader('/usr/share/n4d/templates/nfs'))
22               
23                self.backup_files=[r'/lib/systemd/system/net-server\x2dsync.mount']
24                self.backup_dirs=["/etc/exports.d/"]
25
26                # LLX TESTING
27                #self.nfs_file="/tmp/exports"
28                #
29               
30                if not os.path.exists(self.nfs_dir):
31                        os.makedirs(self.nfs_dir)
32               
33               
34        #def __init__
35               
36               
37        def parse_exports_file(self,f=None):
38               
39                if f==None:
40                        f=self.nfs_file
41
42                if not os.path.isfile(f):
43                        return {}
44               
45                f=open(f)
46                lines=f.readlines()
47                f.close()
48               
49                exports={}
50               
51                for line in lines:
52                        ret=re.match(self.regex_pattern,line)
53                        if ret:
54                                d,ip_list=ret.group(1),ret.group(3)
55                               
56                                for info in ip_list.split(" "):
57                                        info=info.strip("\n")
58                                        info=info.split("(")
59                                        ip=info[0]
60                                        options=info[1].strip(")")
61                                       
62                                        if d not in exports:
63                                                exports[d]={}
64                                       
65                                        exports[d][ip]=options
66                return exports
67
68       
69        #def parse_exports_file
70
71        def fix_missing_no_root_squash(self):
72               
73                exports=self.parse_exports_file()
74
75                for d in exports:
76                        for ip in exports[d]:
77                                if "no_root_squash" not in exports[d][ip]:
78                                        exports[d][ip]+=",no_root_squash"
79
80                self.write_exports_file(exports)
81
82        #def fix_missing_no_root_squash
83       
84
85        def export_directories(self):
86               
87                #ret=os.system("exportfs -ra")
88                p=subprocess.Popen(["exportfs","-ra"],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
89                ret=p.communicate()
90               
91                if p.poll()==0:
92               
93                        return {"status":True , "msg": "NFS shares exported"}
94                       
95                else:
96                       
97                        return {"status":False, "msg":ret[1]}
98               
99        #def export_directories
100
101       
102        def add_share(self,d,ip,options=None):
103               
104                if options==None:
105                        options=self.default_options
106                       
107                exports=self.parse_exports_file()
108       
109                if d not in exports:
110                        exports[d]={}
111                exports[d][ip]=options
112                return self.write_exports_file(exports)
113               
114        #def add_share
115       
116       
117        def remove_ip_from_share(self,share,ip):
118               
119                exports=self.parse_exports_file()
120               
121                if share in exports:
122                        if ip in exports[share]:
123                                exports[share].pop(ip)
124                               
125                                self.write_exports_file(exports)
126                               
127                                return {"status":True,"msg":"Removed IP from server"}
128                       
129                        else:
130                                return {"status":False,"msg":"IP not found"}
131                               
132                else:
133                        return {"status":True,"msg":"Share dir. not found"}
134                       
135               
136        #def remove_ip_from_share
137       
138       
139       
140        def write_exports_file(self,exports,f=None):
141               
142                if f==None:
143                        f=self.nfs_file
144                       
145                file_lines=[]
146                file_lines.append(self.file_header)
147                       
148                for d in exports:
149                        line="%s\t\t%s\n"
150                        ip_list=""
151                        for ip in exports[d]:
152                                ip_list+="%s(%s) "%(ip,exports[d][ip])
153                        ip_list=ip_list.rstrip(" ")
154                        file_lines.append(line%(d,ip_list))
155                       
156                file_lines.append("\n")
157               
158                f=open(f,"w")
159                for line in file_lines:
160                        f.write(line)
161                f.close()
162                self.export_directories()
163                return {"status":True,"msg":"NFS exports.d file written"}
164                       
165        #def write_exports_file
166       
167       
168        def configure_mount_on_boot(self,source,target,options=None):
169               
170                if options==None:
171                        options=self.default_mount_options
172                       
173               
174                template_cname = self.tpl_env.get_template("mount.skel")
175                list_variables = {}
176                list_variables["SRC"]=source
177                list_variables["DEST"]=target
178                list_variables["OPTIONS"]=options
179               
180                string_template = template_cname.render(list_variables).encode('UTF-8')
181               
182                fd, tmpfilepath = tempfile.mkstemp()
183                new_export_file = open(tmpfilepath,'w')
184                new_export_file.write(string_template)
185                new_export_file.close()
186                os.close(fd)
187               
188                p=subprocess.Popen(["systemd-escape",target.lstrip("/")],stdout=subprocess.PIPE)
189                file_name=p.communicate()[0].strip("\n")+".mount"
190                file_dest="/lib/systemd/system/"+file_name
191               
192                n4d_mv(tmpfilepath,file_dest,True,'root','root','0644',False )
193               
194                os.system("systemctl daemon-reload")
195                o=subprocess.Popen(["systemctl","enable",file_name],stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()
196                o2=subprocess.Popen(["systemctl","start",file_name],stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()
197               
198                ret=(o,o2)
199               
200                return {"status":True,"msg":ret}
201               
202        #def configure_mount_on_boot
203       
204        def remove_mount_on_boot(self,target):
205               
206                p=subprocess.Popen(["systemd-escape",target.lstrip("/")],stdout=subprocess.PIPE)
207                file_name=p.communicate()[0].strip("\n")+".mount"
208                file_dest="/lib/systemd/system/"+file_name
209               
210                ret=""
211               
212                if os.path.exists(file_dest):
213                        o2=subprocess.Popen(["systemctl","stop",file_name],stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()
214                        o=subprocess.Popen(["systemctl","disable",file_name],stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()
215                        os.remove(file_dest)
216                        ret=(o,o2)
217                       
218                return {"status":True,"msg":ret}
219               
220        #def remove_mount_on_boot
221       
222        def clean_exports_file(self):
223               
224                if os.path.exists(self.nfs_file):
225                        os.remove(self.nfs_file)
226                        self.export_directories()
227               
228                return {"status":True,"msg":"NfsManager exports.d file is now clean"}
229
230        def makedir(self,dir_path=None):
231
232                if not os.path.isdir(dir_path):
233                        os.makedirs(dir_path)
234
235                return [True]
236               
237        def backup(self,dir_path="/backup"):
238                try:
239                        self.makedir(dir_path)
240
241                        #get_backup_name es una funcion que esta definida en n4d
242                        file_path=dir_path+"/"+get_backup_name("NfsManager")
243
244                        tar=tarfile.open(file_path,"w:gz")
245                        for f in self.backup_files:
246                                if os.path.exists(f):
247                                        tar.add(f)
248                        for d in self.backup_dirs:
249                             if os.path.exists(d):
250                                for f in os.listdir(d):
251                                        tar.add(d+f)
252
253                        tar.close()
254                        print "Backup generated in %s" % file_path
255                        return [True,file_path]
256
257
258                except Exception as e:
259                                print "Backup failed", e
260                                return [False,str(e)]
261
262        #def backup
263
264
265        def restore(self,file_path=None):
266
267                #Ordeno de manera alfabetica el directorio y busco el fichero que tiene mi cadena
268                if file_path==None:
269                        dir_path="/backup"
270                        for f in sorted(os.listdir(dir_path),reverse=True):
271
272                                if "NfsManager" in f:
273                                        file_path=dir_path+"/"+f
274                                        break
275
276                #Descomprimo el fichero y solo las cadenas que espero encontrar son las que restauro, reiniciando el servicio
277
278
279                try:
280                        if os.path.exists(file_path):
281
282                                tmp_dir=tempfile.mkdtemp()
283                                tar=tarfile.open(file_path)
284                                tar.extractall(tmp_dir)
285                                tar.close
286
287                                for f in self.backup_files:
288                                                tmp_path=tmp_dir+f
289                                                if os.path.exists(tmp_path):
290                                                        shutil.copy(tmp_path,f)
291
292
293                                for d in self.backup_dirs:
294                                        tmp_path=tmp_dir+d     
295                                        if os.path.exists(tmp_path):
296                                                cmd="cp -r " + tmp_path + "/* " + d
297                                                if not os.path.exists(d):
298                                                        os.makedirs(d)
299                                                os.system(cmd)
300
301
302                        print "File is restored in %s" % self.backup_files
303
304                        return [True,""]
305
306
307                except Exception as e:
308
309                        print "Restored failed", e
310                        return [False,str(e)]
311
312                pass
313
314        #def restore
315
316       
317       
318#class NfsManager
319
320if __name__=="__main__":
321       
322        pass
323
324
Note: See TracBrowser for help on using the repository browser.