OSDN Git Service

82beccd0b52a1fa7882328bf38bbcd8bbbd043d1
[karesansui/karesansui.git] / installer / installer / utils.py
1 #/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # This file is part of Karesansui.
5 #
6 # Copyright (C) 2009 HDE, Inc.
7 #
8 # This program is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU General Public License
10 # as published by the Free Software Foundation; either version 2
11 # of the License, or (at your option) any later version.
12 #
13
14 import os
15 import sys
16 import stat
17 import subprocess
18 import time
19 import datetime
20 import re
21 import pwd
22 import grp
23 import fcntl
24 import random
25
26 from installer.const import *
27
28 global logfile
29 env = os._Environ(os.environ)
30 logfile = env.get("LOGFILE")
31
32 def generate_uuid():
33     """
34     <comment-ja>
35     ランダムなUUIDを生成する
36
37     @return: UUID用の16個のバイト要素を持つ配列
38     </comment-ja>
39     <comment-en>
40     Generate UUID
41
42     @return: Array UUID
43     </comment-en>
44     """
45     uuid = []
46     for _x in range(0, 16):
47       uuid.append(random.randint(0x00,0xff))
48     return uuid
49
50 def string_from_uuid(uuid):
51     """
52     <comment-ja>
53     UUIDデータを文字列に変換する
54
55     @param uuid: generate_uuid関数等で生成されたUUIDデータ
56     @return: UUID文字列
57     </comment-ja>
58     <comment-en>
59     Convert UUID data to string
60
61     @param uuid: UUID data that was generated by certain function like as generate_uuid()
62     @return: The string that stands for uuid
63     </comment-en>
64     """
65     tuuid = tuple(uuid)
66     return "-".join(["%02x"*4 % tuuid[0:4],
67                     "%02x"*2 % tuuid[4:6],
68                     "%02x"*2 % tuuid[6:8],
69                     "%02x"*2 % tuuid[8:10],
70                     "%02x"*6 % tuuid[10:16]
71                    ]);
72
73 def detect_encoding(string,encoding_list=None):
74     func = lambda data,encoding: data.decode(encoding) and encoding
75
76     if not encoding_list:
77         encoding_list = [ 'euc-jp', 'utf-8', 'shift-jis', 'iso2022-jp' ]
78
79     for encoding in encoding_list:
80         try:
81             return func(string, encoding)
82         except:
83             pass
84
85     return None
86
87 def execute_command(command_args):
88     global logfile
89     ret = -1
90     res = []
91
92     subproc_args = { 'stdin': subprocess.PIPE,
93                      'stdout': subprocess.PIPE,
94                      'stderr': subprocess.STDOUT,
95 #                     'shell': True,
96                      'cwd': os.getcwd(),
97                      'close_fds': True,
98                    }
99
100     if logfile is None:
101         logfile = "/dev/null"
102     logf = open(logfile, "a")
103
104     try:
105         pp = subprocess.Popen(command_args, **subproc_args)
106         logf.write("Exec: '%s'\n" % (command_args))
107     except OSError:
108         logf.write("Exec: '%s' failed.\n" % (command_args))
109         logf.close()
110         return [ret,res]
111
112     (stdouterr, stdin) = (pp.stdout, pp.stdin)
113     while True:
114         line = stdouterr.readline()
115         logf.write(line)
116         if not line:
117             break
118         line = line.rstrip()
119         res.append(unicode(line, detect_encoding(line)).encode("utf-8"))
120     ret = pp.wait()
121
122     logf.close()
123     return [ret,res]
124
125 def is_int(val):
126     try:
127         ret = int(val)
128         return True
129     except (TypeError, ValueError):
130         return False
131
132 def r_chown(path,owner):
133     global logfile
134     owner = str(owner)
135     if not os.path.exists(path):
136         return False
137
138     if ':' in owner:
139         user, group = owner.split(':')
140     else:
141         user, group = [owner,None ]
142
143     if is_int(user) is not True:
144         try:
145             pw = pwd.getpwnam(user)
146         except:
147             return False
148     else:
149         try:
150             pw = pwd.getpwuid(int(user))
151         except:
152             return False
153     uid = pw[2]
154
155     if group == None:
156         statinfo = os.stat(path)
157         gid = statinfo.st_gid
158     else:
159         if is_int(group) is not True:
160             try:
161                 gr = grp.getgrnam(group)
162             except:
163                 return False
164         else:
165             try:
166                 gr = grp.getgrgid(int(group))
167             except:
168                 return False
169         gid = gr[2]
170
171     if os.path.isfile(path) or os.path.islink(path):
172         try:
173             os.chown(path,uid,gid)
174         except:
175             return False
176
177     elif os.path.isdir(path):
178         try:
179             os.chown(path,uid,gid)
180         except:
181             return False
182
183         for name in os.listdir(path):
184             sub_path = os.path.join(path, name)
185             r_chown(sub_path,owner)
186
187     return True
188
189 def r_chgrp(path,group):
190     global logfile
191     group = str(group)
192     if not os.path.exists(path):
193         return False
194
195     statinfo = os.stat(path)
196     uid = statinfo.st_uid
197
198     if is_int(group) is not True:
199         try:
200             gr = grp.getgrnam(group)
201         except:
202             return False
203     else:
204         try:
205             gr = grp.getgrgid(int(group))
206         except:
207             return False
208     gid = gr[2]
209
210     if os.path.isfile(path) or os.path.islink(path):
211         try:
212             os.chown(path,uid,gid)
213         except:
214             return False
215
216     elif os.path.isdir(path):
217         try:
218             os.chown(path,uid,gid)
219         except:
220             return False
221
222         for name in os.listdir(path):
223             sub_path = os.path.join(path, name)
224             r_chgrp(sub_path,group)
225
226     return True
227
228 def r_chmod(path,perm):
229     perm_regex = re.compile(r"""^(?P<user>[ugo]{0,3})(?P<action>[\+\-])(?P<value>[rwxst]{1,3})$""")
230
231     user_table = {"u":"USR","g":"GRP","o":"OTH"}
232     perm_table = {"r":"R","w":"W","x":"X"}
233
234     if not os.path.exists(path):
235         return False
236
237     original_perm = perm
238     if is_int(perm):
239         if type(perm) == str:
240             perm = oct2dec(perm)
241         new_perm = perm
242     else:
243         s = os.lstat(path)
244         new_perm = stat.S_IMODE(s.st_mode)
245
246         m = perm_regex.match(perm)
247         if m:
248             user = m.group('user')
249             action = m.group('action')
250             value = m.group('value')
251             if user == "":
252                 user = "ugo"
253
254             mask_perm = 0
255             for k,v in user_table.iteritems():
256                 if k in user:
257                     for k2,v2 in perm_table.iteritems():
258                         if k2 in value:
259                             exec("bit = stat.S_I%s%s" % (v2,v,))
260                             mask_perm = mask_perm | bit
261
262
263             if "t" in value:
264                 bit = stat.S_ISVTX
265                 mask_perm = mask_perm | bit
266
267             if "s" in value:
268                 if "u" in user:
269                     bit = stat.S_ISUID
270                     mask_perm = mask_perm | bit
271                 if "g" in user:
272                     bit = stat.S_ISGID
273                     mask_perm = mask_perm | bit
274
275             #print "new_perm1:" + dec2oct(new_perm)
276             #print "mask_perm:" + dec2oct(mask_perm)
277             if action == "-":
278                 new_perm = new_perm & (~ mask_perm)
279             elif action == "+":
280                 new_perm = new_perm | mask_perm
281             #print "new_perm2:" + dec2oct(new_perm)
282
283         else:
284             return False
285
286     if os.path.isfile(path) or os.path.islink(path):
287         try:
288             os.chmod(path,new_perm)
289         except:
290             return False
291
292     elif os.path.isdir(path):
293         try:
294             os.chmod(path,new_perm)
295         except:
296             return False
297
298         for name in os.listdir(path):
299             sub_path = os.path.join(path, name)
300             r_chmod(sub_path,original_perm)
301
302     return True
303
304 def sh_config_read(filename):
305     ret = {}
306     try:
307         fp = open(filename,"r")
308         fcntl.lockf(fp.fileno(), fcntl.LOCK_SH)
309         for line in fp.readlines():
310             line = line.strip()
311             if len(line) <= 0 or line[0] == "#":
312                 continue
313             key, value = line.split('=',1)
314             ret[key] = value
315         fcntl.lockf(fp.fileno(), fcntl.LOCK_UN)
316         fp.close()
317     except:
318         ret = False
319
320     return ret
321
322 def sh_config_write(filename,opts):
323     ret = True
324
325     res = {}
326     if type(opts) == dict:
327         res = opts
328     else:
329         for k in dir(opts):
330             res[k] = getattr(opts,k)
331
332     try:
333         fp = open(filename,"w")
334         fcntl.lockf(fp.fileno(), fcntl.LOCK_EX)
335         for k,v in res.iteritems():
336             if type(v) == str and k[0:2] != "__" and k[0:4] != "pass":
337                 fp.write("%s=%s\n" % (k, v,))
338         fcntl.lockf(fp.fileno(), fcntl.LOCK_UN)
339         fp.close()
340     except:
341         ret = False
342
343     return ret
344
345 def run_chkconfig(name,flag=None):
346     ret = False
347
348     if flag is None:
349         (ret,res) = execute_command([COMMAND_CHKCONFIG,name])
350     else:
351         (ret,res) = execute_command([COMMAND_CHKCONFIG,name,flag])
352     if ret == 0:
353         ret = True
354
355     return ret
356
357 def run_service(name,flag=None):
358     ret = False
359
360     if flag is None:
361         (ret,res) = execute_command([COMMAND_SERVICE,name,"status"])
362     else:
363         (ret,res) = execute_command([COMMAND_SERVICE,name,flag])
364     if ret == 0:
365         ret = True
366
367     return ret
368
369 def get_kss_url():
370     import socket
371
372     fqdn = socket.gethostname()
373     urls = []
374
375     url_prefix = sh_config_read(DEFAULT_KARESANSUI_CONF)["application.url.prefix"]
376
377     """ HTTPS """
378     ssl_port_regex = re.compile(r"^\$SERVER\[\"socket\"\] == \".*:(?P<port>[0-9]+)\"")
379     try:
380         fp = open(LIGHTY_SSL_CONF,"r")
381         fcntl.lockf(fp.fileno(), fcntl.LOCK_SH)
382         for line in fp.readlines():
383             line = line.strip()
384             m = ssl_port_regex.match(line)
385             if m:
386                 ssl_port = m.group('port')
387                 if ssl_port == "443":
388                     urls.append("https://%s%s/" % (fqdn,url_prefix))
389                 else:
390                     urls.append("https://%s:%s%s/" % (fqdn,m.group('port'),url_prefix))
391         fcntl.lockf(fp.fileno(), fcntl.LOCK_UN)
392         fp.close()
393     except:
394         pass
395
396     """ HTTP """
397     try:
398         port = sh_config_read(LIGHTY_PORT_CONF)["server.port"]
399     except:
400         port = "80"
401
402     if port == "80":
403         urls.append("http://%s%s/" % (fqdn,url_prefix))
404     else:
405         urls.append("http://%s:%s%s/" % (fqdn,port,url_prefix))
406
407     return urls
408
409 def deco_msg(string,font="green"):
410     if font == "bold":
411         return "\e[1m%s\e[0m" % string
412     elif font == "underline":
413         return "\e[4m%s\e[0m" % string
414     elif font == "red":
415         return "\e[31m%s\e[0m" % string
416     elif font == "green":
417         return "\e[32m%s\e[0m" % string
418     elif font == "orange":
419         return "\e[33m%s\e[0m" % string
420     elif font == "blue":
421         return "\e[34m%s\e[0m" % string
422     elif font == "gray":
423         return "\e[37m%s\e[0m" % string
424     elif font == "red|bold":
425         return "\e[1m\e[31m%s\e[0m" % string
426     elif font == "green|bold":
427         return "\e[1m\e[32m%s\e[0m" % string
428     elif font == "blue|bold":
429         return "\e[1m\e[34m%s\e[0m" % string
430     else:
431         return string
432
433 def is_installed(name,rpmlib=None):
434     if rpmlib is None:
435         from installer.rpmlib import RpmLib
436         rpmlib = RpmLib()
437     try:
438         rpmlib.doQuery("^%s$" % name)[name]
439         ret = True
440     except:
441         ret = False
442     rpmlib.__del__
443     return ret
444
445 def get_distrubution(rpmlib=None):
446     ret = ('unknown',None)
447
448     if rpmlib is None:
449         from installer.rpmlib import RpmLib
450         rpmlib = RpmLib()
451
452     distros = [
453       "centos-release",
454       "redhat-release",
455       "redhat-release-as",
456       "redhat-release-es",
457       "redhat-release-ws",
458       "distribution-release",
459       "miraclelinux-release",
460       "fedora-release",
461       "suse-release",
462       "asianux-release",
463     ]
464
465     rpminfo = rpmlib.doQuery("")
466     for _name in distros:
467         try:
468             _info = rpminfo[_name]
469             ret = (_name, "%s-%s" % (_info["version"],_info["release"],))
470             break
471         except:
472             pass
473     rpmlib.__del__
474     return ret