You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
521 lines
18 KiB
521 lines
18 KiB
#-*- coding: utf-8 -*-
|
|
|
|
# Copyright 2008-2010 Calculate Ltd. http://www.calculate-linux.org
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import os
|
|
import sys
|
|
from cl_utils import getpathenv, runOsCommand, typeFile
|
|
import re
|
|
from os import path, R_OK
|
|
try:
|
|
from cl_ldap import ldapUser
|
|
except ImportError:
|
|
ldapUser = None
|
|
from operator import itemgetter
|
|
|
|
class clLocale:
|
|
lang = {
|
|
#Belarussian
|
|
'be_BY' : {
|
|
'locale':'be_BY.UTF-8',
|
|
'keymap':'by',
|
|
'dumpkeys_charset': 'koi8-u',
|
|
'consolefont':'Cyr_a8x16',
|
|
'xkblayout':'us,by',
|
|
'language':'be',
|
|
},
|
|
#Bulgarian
|
|
'bg_BG' : {
|
|
'locale':'bg_BG.UTF-8',
|
|
'keymap':'bg_bds-utf8',
|
|
'dumpkeys_charset': '',
|
|
'consolefont':'ter-m14n',
|
|
'xkblayout':'us,bg',
|
|
'language':'bg',
|
|
},
|
|
#Belgian
|
|
'fr_BE' : {
|
|
'locale':'fr_BE.UTF-8',
|
|
'keymap':'be-latin1',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'lat9w-16',
|
|
'xkblayout':'us,be',
|
|
'language':'fr',
|
|
},
|
|
#Brazilian Portuguese
|
|
'pt_BR' : {
|
|
'locale':'pt_BR.UTF-8',
|
|
'keymap':'br-abnt2',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'lat9w-16',
|
|
'xkblayout':'pt,us',
|
|
'language':'pt',
|
|
},
|
|
#Canadian French
|
|
'fr_CA' : {
|
|
'locale':'fr_CA.UTF-8',
|
|
'keymap':'cf',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'default8x16',
|
|
'xkblayout':'us,ca_enhanced',
|
|
'language':'fr',
|
|
},
|
|
#Danish
|
|
'da_DK' : {
|
|
'locale':'da_DK.UTF-8',
|
|
'keymap':'dk-latin1',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'lat0-16',
|
|
'xkblayout':'us,dk',
|
|
'language':'da',
|
|
},
|
|
#French
|
|
'fr_FR' : {
|
|
'locale':'fr_FR.UTF-8',
|
|
'keymap':'fr-latin9',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'lat0-16',
|
|
'xkblayout':'fr,us',
|
|
'language':'fr',
|
|
},
|
|
#German
|
|
'de_DE' : {
|
|
'locale':'de_DE.UTF-8',
|
|
'keymap':'de-latin1',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'lat9w-16',
|
|
'xkblayout':'de,us',
|
|
'language':'de',
|
|
},
|
|
#Icelandic
|
|
'is_IS' : {
|
|
'locale':'is_IS.UTF-8',
|
|
'keymap':'is-latin1',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'cp850-8x16',
|
|
'xkblayout':'us,is',
|
|
'language':'is',
|
|
},
|
|
#Italian
|
|
'it_IT' : {
|
|
'locale':'it_IT.UTF-8',
|
|
'keymap':'it',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'default8x16',
|
|
'xkblayout':'us,it',
|
|
'language':'it',
|
|
},
|
|
#Norwegian
|
|
'nn_NO' : {
|
|
'locale':'nn_NO.UTF-8',
|
|
'keymap':'no-latin1',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'lat9w-16',
|
|
'xkblayout':'us,no',
|
|
'language':'nn',
|
|
},
|
|
#Polish
|
|
'pl_PL' : {
|
|
'locale':'pl_PL.UTF-8',
|
|
'keymap':'pl',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'lat2-16',
|
|
'xkblayout':'us,pl',
|
|
'language':'pl',
|
|
},
|
|
#Russian
|
|
'ru_RU' : {
|
|
'locale':'ru_RU.UTF-8',
|
|
'keymap':'-u ruwin_cplk-UTF-8',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'ter-k14n',
|
|
'xkblayout':'us,ru(winkeys)',
|
|
'language':'ru',
|
|
},
|
|
#Spanish
|
|
'es_ES' : {
|
|
'locale':'es_ES.UTF-8',
|
|
'keymap':'es euro2',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'lat0-16',
|
|
'xkblayout':'es,us',
|
|
'language':'es',
|
|
},
|
|
#Swedish
|
|
'sv_SE' : {
|
|
'locale':'sv_SE.UTF-8',
|
|
'keymap':'sv-latin1',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'lat0-16',
|
|
'xkblayout':'us,se',
|
|
'language':'sv',
|
|
},
|
|
#Ukrainian
|
|
'uk_UA' : {
|
|
'locale':'uk_UA.UTF-8',
|
|
'keymap':'ua-utf',
|
|
'dumpkeys_charset':'koi8-u',
|
|
'consolefont':'ter-v14n',
|
|
'xkblayout':'us,ua(winkeys)',
|
|
'language':'uk',
|
|
},
|
|
#United Kingdom/British
|
|
'en_GB' : {
|
|
'locale':'en_GB.UTF-8',
|
|
'keymap':'uk',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'LatArCyrHeb-16',
|
|
'xkblayout':'us,gb',
|
|
'language':'en',
|
|
},
|
|
#United State/English
|
|
'en_US' : {
|
|
'locale':'en_US.UTF-8',
|
|
'keymap':'us',
|
|
'dumpkeys_charset':'',
|
|
'consolefont':'LatArCyrHeb-16',
|
|
'xkblayout':'us',
|
|
'language':'en',
|
|
}
|
|
}
|
|
|
|
def getLangs(self):
|
|
return self.lang.keys()
|
|
|
|
def getLanguages(self):
|
|
return map(lambda x:self.lang[x]['language'],
|
|
self.lang.keys())
|
|
|
|
def isLangExists(self,lang):
|
|
return lang in self.lang.keys()
|
|
|
|
def isValueInFieldExists(self,field,value):
|
|
return value in map(lambda x:self.lang[x][field],self.lang.keys())
|
|
|
|
def getFields(self,field):
|
|
return [ l[1][field] for l in self.lang.items() ]
|
|
|
|
def getFieldByLang(self,field,lang):
|
|
return self.lang.get(lang, self.lang['en_US'])[field]
|
|
|
|
def getFieldByKeymap(self,field,keymap):
|
|
return self.lang.get(self.getLangByField('keymap',keymap),
|
|
self.lang['en_US'])[field]
|
|
|
|
def getLangByField(self,field,value):
|
|
langs = [lang[0] for lang in self.lang.items()
|
|
if lang[1][field] == value ]
|
|
if not langs:
|
|
return 'en_US'
|
|
else:
|
|
return langs[0]
|
|
|
|
|
|
class varsShare:
|
|
"""Share methods and attributs for fill vars methods"""
|
|
|
|
dictLinuxName = {"CLD":"Calculate Linux Desktop",
|
|
"CLDX":"Calculate Linux Desktop",
|
|
"CLDG":"Calculate Linux Desktop",
|
|
"CDS":"Calculate Directory Server",
|
|
"CLS":"Calculate Linux Scratch",
|
|
"CSS":"Calculate Scratch Server",
|
|
"Gentoo":"Gentoo"}
|
|
|
|
dictLinuxSubName = {"CLD":"KDE", "CLDX":"XFCE", "CLDG":"GNOME"}
|
|
|
|
dictNameSystem = {'CDS':'server',
|
|
'CLD':'desktop',
|
|
'CLDG':'desktop',
|
|
'CLDX':'desktop',
|
|
'CLS':'desktop',
|
|
'CSS':'server'}
|
|
|
|
# data object from LDAP
|
|
_ldapUserObject = False
|
|
# user data from LDAP
|
|
_ldapUserData = {}
|
|
|
|
reFindVer = re.compile(
|
|
"(?<=version )(\d+\.?\d*\.?\d*\.?\d*)([^\d* ])*(\d*)")
|
|
|
|
def getFilesByType(self,pathname,descr):
|
|
"""Get files from "pathname" has "descr" in descriptions"""
|
|
filelist = map(lambda x:path.join(pathname,x),os.listdir(pathname))
|
|
ftype = typeFile(magic=0x4).getMType
|
|
filesWithType = map(lambda x:(x,ftype(x)), filelist)
|
|
return filter(lambda x:descr in x[1],filesWithType)
|
|
|
|
def getInitrd(self,arch,shortname,chroot,kernel,suffix="",notsuffix=""):
|
|
"""Get initrd for kernel"""
|
|
reInitrdVer = re.compile("(initrd|initramfs)-(.+?)(-install)?$",re.S)
|
|
def initrd_version_by_name(filename):
|
|
resInitrdVer = reInitrdVer.search(filename)
|
|
if resInitrdVer:
|
|
return resInitrdVer.groups()[1]
|
|
return ""
|
|
|
|
ftype = typeFile(magic=0x4).getMType
|
|
kernelfile = path.join(chroot,'boot',kernel)
|
|
resKernelVer = self.reFindVer.search(ftype(kernelfile))
|
|
if resKernelVer:
|
|
kernelVersion = "%s-%s-%s"% \
|
|
(resKernelVer.group().replace('-calculate',''),
|
|
arch, shortname)
|
|
origKernelVer = resKernelVer.group()
|
|
|
|
bootdir = path.join(chroot,'boot')
|
|
initramfsFiles = self.getFilesByType(bootdir,"ASCII cpio archive")
|
|
initramfsWithVer = \
|
|
filter(lambda x: (kernelVersion in x[1] or
|
|
origKernelVer in x[1]) and \
|
|
x[0].endswith(suffix) and \
|
|
(not notsuffix or not x[0].endswith(notsuffix)),
|
|
map(lambda x:(x[0],initrd_version_by_name(x[0])),
|
|
initramfsFiles))
|
|
if initramfsWithVer:
|
|
return path.split(min(initramfsWithVer,
|
|
key=itemgetter(0))[0])[-1]
|
|
return ""
|
|
|
|
def getDirList(self,pathname):
|
|
"""Get directory list by pathname"""
|
|
dirs = []
|
|
if path.exists(pathname):
|
|
dirs = filter(lambda x: path.isdir(path.join(pathname,x)),
|
|
os.listdir(pathname))
|
|
return dirs
|
|
|
|
def getUserInfo(self):
|
|
"""Get information about user from LDAP in dict format"""
|
|
userName = self.Get('ur_login')
|
|
if userName:
|
|
if userName in self._ldapUserData:
|
|
return self._ldapUserData[userName]
|
|
elif not ldapUser is None:
|
|
ldapObj = self.getLdapUserObject()
|
|
if ldapObj:
|
|
userInfo = ldapObj.getUserLdapInfo(userName)
|
|
if userInfo:
|
|
self._ldapUserData[userName] = userInfo
|
|
return userInfo
|
|
return {}
|
|
|
|
def getLdapUserObject(self):
|
|
"""Get data obejct from LDAP"""
|
|
if not self._ldapUserObject:
|
|
self._ldapUserObject = ldapUser()
|
|
return self._ldapUserObject
|
|
|
|
def _runos(self, cmd, env={}):
|
|
"""Return result of os command perform"""
|
|
if not env:
|
|
env.update(os.environ.items() + [("PATH",getpathenv())] +\
|
|
env.items())
|
|
retCode, programOut = runOsCommand(cmd, None, env_dict=env)
|
|
if not retCode:
|
|
return programOut
|
|
return False
|
|
|
|
def get_composite_from_xorgconf(self,chroot="/"):
|
|
"""Get composite value from xorg.conf"""
|
|
xorgConfig = path.join(chroot,
|
|
"etc/X11/xorg.conf")
|
|
try:
|
|
confLines = open(xorgConfig,"r").readlines()
|
|
except:
|
|
return None
|
|
|
|
flagStartExtensions = False
|
|
lineCompositeTmp = ""
|
|
lineComposite = ""
|
|
for line in confLines:
|
|
if flagStartExtensions:
|
|
if 'EndSection' in line:
|
|
lineComposite = lineCompositeTmp
|
|
break
|
|
elif 'Section' in line:
|
|
break
|
|
if 'Option' in line and '"Composite"' in line:
|
|
lineCompositeTmp = line
|
|
else:
|
|
if '"Extensions"' in line and 'Section' in line:
|
|
flagStartExtensions = True
|
|
if lineComposite:
|
|
listOpt = filter(lambda x: x.strip(), lineComposite.split('"'))
|
|
if len(listOpt) == 3:
|
|
ret = listOpt[2].lower()
|
|
if ret in ("on","true","yes","1"):
|
|
return "on"
|
|
elif ret in ("off","false","no","0"):
|
|
return "off"
|
|
return None
|
|
|
|
def getValueFromCmdLine(self,option,num):
|
|
"""Get value of parameter from boot params
|
|
|
|
Parameters:
|
|
option param name
|
|
num number part of value parameter (, split)
|
|
"""
|
|
cmdLine = "/proc/cmdline"
|
|
calculateParam = "calculate"
|
|
# try get timezone from kernel calculate param
|
|
try:
|
|
for param in open(cmdLine,"r").read().split(" "):
|
|
parname,op,value = param.partition("=")
|
|
if parname == calculateParam and op == "=":
|
|
values = value.split(",")
|
|
if len(values) > num and values[num].strip():
|
|
return values[num].strip()
|
|
except IOError,e:
|
|
return ""
|
|
|
|
def getValueFromConfig(self,config,name):
|
|
"""Get value of parameter from bash type file
|
|
|
|
Parameters:
|
|
config config file name
|
|
name param name
|
|
"""
|
|
reMatch = re.compile("^%s\s*=\s*\"?(.*?)(\"\s*)?$"%name, re.I)
|
|
try:
|
|
if path.exists(config):
|
|
for line in open(config,"r").readlines():
|
|
match = reMatch.match(line)
|
|
if match:
|
|
return match.groups()[0].strip()
|
|
except:
|
|
pass
|
|
return False
|
|
|
|
def getX11Resolution(self):
|
|
"""Return current screen resolution (width, height), X must be ran"""
|
|
lines=self._runos("xdpyinfo")
|
|
if not lines:
|
|
return ""
|
|
reRes = re.compile("dimensions:\s+(\d+)x(\d+)\s+pixels")
|
|
searchRes=False
|
|
for line in lines:
|
|
searchRes = reRes.search(line)
|
|
if searchRes:
|
|
break
|
|
if searchRes:
|
|
return (searchRes.group(1), searchRes.group(2))
|
|
else:
|
|
return ""
|
|
|
|
def getShortnameByMakeprofile(self,systemroot):
|
|
"""Get shortname by symlink of make.profile"""
|
|
makeprofile = path.join(systemroot,'etc/make.profile')
|
|
if path.exists(makeprofile):
|
|
link = os.readlink(makeprofile)
|
|
reMakeProfileLink = re.compile('/calculate/(desktop|server)/(%s)/'%
|
|
"|".join(self.dictLinuxName.keys()),re.S)
|
|
shortnameSearch = reMakeProfileLink.search(link)
|
|
if shortnameSearch:
|
|
return shortnameSearch.groups()[1]
|
|
return None
|
|
|
|
def getShortnameByIni(self,systemroot):
|
|
"""Get shortname by calculate.ini file"""
|
|
inifile = path.join(systemroot,'etc/calculate/calculate.ini')
|
|
if path.exists(inifile):
|
|
FD = open(inifile)
|
|
data = FD.readlines()
|
|
FD.close()
|
|
shortNameList = filter(lambda y:y,
|
|
map(lambda x:\
|
|
len(x.split("="))==2 and\
|
|
x.split("=")[0]=="calculate" and\
|
|
x.split("=")[1].strip(), data))
|
|
if shortNameList:
|
|
return shortNameList[0]
|
|
|
|
def detectOtherShortname(self,systemroot):
|
|
"""Detect other system. Now only Gentoo."""
|
|
gentooFile = path.join(systemroot,"etc/gentoo-release")
|
|
if path.exists(gentooFile):
|
|
return "Gentoo"
|
|
return None
|
|
|
|
def getVersionFromMetapackage(self,systemroot,shortname):
|
|
"""Get version from meta package"""
|
|
pkgInfoDir = path.join(systemroot,'var/db/pkg/app-misc/')
|
|
if not os.access(pkgInfoDir,os.R_OK):
|
|
return None
|
|
metaPkgs = sorted(filter(lambda x:"calculate-meta" in x or \
|
|
"%s-meta"%shortname.lower() in x,
|
|
os.listdir(pkgInfoDir)))
|
|
if metaPkgs:
|
|
reFindVer = re.compile("(?<=\-)\d+\.?\d*\.?\d*")
|
|
findVer = reFindVer.search(metaPkgs[0])
|
|
if findVer:
|
|
return findVer.group()
|
|
return None
|
|
|
|
def getVersionFromCalculateIni(self,systemroot):
|
|
"""Get version from calculate ini"""
|
|
pathname = path.join(systemroot,
|
|
'etc/calculate/calculate.ini')
|
|
if path.exists(pathname):
|
|
FD = open(pathname)
|
|
data = FD.readlines()
|
|
FD.close()
|
|
verList = filter(lambda y:y,
|
|
map(lambda x:\
|
|
len(x.split("="))==2 and\
|
|
x.split("=")[0]=="linuxver" and\
|
|
x.split("=")[1].strip(), data))
|
|
if verList:
|
|
reVer=re.compile("^(\d+\.)*\d$",re.S)
|
|
reRes = filter(reVer.search,verList)
|
|
if reRes:
|
|
return reRes[0]
|
|
|
|
def getVersionFromGentooFiles(self,systemroot):
|
|
"""Get version from gentoo files"""
|
|
gentooFile = path.join(systemroot,"etc/gentoo-release")
|
|
systemVersion = ""
|
|
flagGentoo = False
|
|
reVer=re.compile("^(\d+\.)*\d$",re.S)
|
|
if path.exists(gentooFile):
|
|
gentooLink = path.join(systemroot,"etc/make.profile")
|
|
if path.islink(gentooLink):
|
|
vers = filter(reVer.search,
|
|
os.readlink(gentooLink).split('/'))
|
|
if vers:
|
|
return vers[-1]
|
|
|
|
def getVersionFromUname(self):
|
|
"""Get version from uname"""
|
|
textLines = self._runos("uname -r")
|
|
reVer=re.compile("^(\d+\.)*\d",re.S)
|
|
kernelVersion = ""
|
|
if textLines:
|
|
kernelVersion = textLines[0]
|
|
if kernelVersion:
|
|
reRes = reVer.search(kernelVersion)
|
|
if reRes:
|
|
return reRes.group()
|
|
|
|
def isChroot(self,pid):
|
|
"""Detect chroot mode by different mountinfo"""
|
|
if not os.access('/proc/self/mountinfo',R_OK) or \
|
|
not os.access('/proc/1/mountinfo',R_OK):
|
|
return False
|
|
return open('/proc/1/mountinfo','r').read() != \
|
|
open('/proc/self/mountinfo','r').read()
|