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.
calculate-utils-3-lib/pym/calculate/lib/utils/common.py

592 lines
19 KiB

9 years ago
# -*- coding: utf-8 -*-
# Copyright 2008-2016 Mir Calculate. 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.
from random import choice
import os
import re
import math
from os import path
from calculate.lib.utils.dracut import Dracut
import sys
import getpass
from types import StringType
import string
import glob
import pwd
import itertools
from calculate.lib.cl_lang import setLocalTranslate
9 years ago
_ = lambda x: x
setLocalTranslate('cl_lib3', sys.modules[__name__])
class CommonError(Exception):
pass
9 years ago
class _error(object):
# Здесь ошибки, если они есть
error = []
9 years ago
def getError(self):
"""Выдать ошибки"""
if not self.error:
return False
error = ""
for e in self.error:
error += e + "\n"
return error
def setError(self, error):
"""Установка ошибки"""
self.error.append(error)
return True
def clearErrors(self):
9 years ago
while self.error:
self.error.pop()
9 years ago
class _warning(object):
# Здесь предупреждения
warning = []
9 years ago
def getWarning(self):
"""Выдать ошибки"""
if not self.warning:
return False
warning = ""
for w in self.warning:
warning += w + "\n"
return warning
def setWarning(self, warning):
"""Установка ошибки"""
self.warning.append(warning)
return True
def clearWarnings(self):
9 years ago
while self.warning:
self.warning.pop()
def genpassword(passlen=9, chars=string.ascii_letters + string.digits):
"""Return random charset specified lenght (passlen)"""
return ''.join(map(lambda x: choice(chars),
9 years ago
xrange(0, passlen)))
def getpathenv():
"""Return path for run utilities"""
9 years ago
bindir = set(filter(path.exists,
['/sbin', '/bin', '/usr/sbin', '/usr/bin']))
env = os.environ
envPath = set(env.get('PATH', '').split(":")) | bindir
return ":".join(envPath)
9 years ago
from files import process, listDirectory
def cmpVersion(v1, v2):
"""Compare versions specified by tuple or string"""
9 years ago
if isinstance(v1, StringType):
v1 = getTupleVersion(v1)
9 years ago
if isinstance(v2, StringType):
v2 = getTupleVersion(v2)
9 years ago
return cmp((v1[0] + [0, ] * (len(v2[0]) - len(v1[0])), v1[1]),
(v2[0] + [0, ] * (len(v1[0]) - len(v2[0])), v2[1]))
def getTupleVersion(ver):
"""Get version specified by string as list:
Example:
2.6.30 [(2,6,30),('r',0)]
2.6.31-r1 [(2,6,31),('r',1)]
"""
suffix_value = {"pre": -2, "p": 0, "alpha": -4, "beta": -3,
"rc": -1}
9 years ago
def toTuple(v):
return map(lambda x: suffix_value[x] if x in suffix_value else x,
9 years ago
map(lambda x: int(x) if x.isdigit() else x,
re.findall("r\d+$|\d+|[a-zA-Z+]+",
v.replace('-SNAPSHOT', ''))))
vers, revision = re.search("(^.*?)(-r\d+)?$", ver, re.S).groups()
vers = toTuple(vers)
9 years ago
vers.extend([0] * (10 - len(vers)))
revision = toTuple(revision or "r0")
9 years ago
return [vers, revision]
def getInstalledVideo(prefix="/"):
"""Get installed video drivers"""
9 years ago
x11Drivers = path.join(prefix, "usr/lib/xorg/modules/drivers")
return map(lambda x: x[:-7],
filter(lambda x: x.endswith('_drv.so'),
listDirectory(x11Drivers)))
def getDistfilesVideo(prefix="/"):
"""Get video drivers from distfiles"""
9 years ago
distFiles = path.join(prefix, "usr/portage/distfiles")
driver_map = {'ati': 'fglrx',
'amd': 'fglrx',
'radeon': 'fglrx',
9 years ago
'nvidia-linux': 'nvidia',
'fglrx': 'fglrx'}
def driver_by_fn(fn):
fn = fn.lower()
for part in driver_map:
if part in fn:
return driver_map[part]
else:
return None
return list(set(
9 years ago
filter(None,
map(driver_by_fn,
listDirectory(distFiles)))))
def getAvailableVideo(prefix="/"):
"""Get available video drivers (installed and maybe installed)"""
9 years ago
return list(set(getInstalledVideo(prefix=prefix) +
getDistfilesVideo(prefix=prefix)))
def getPasswdUsers(minId=1000, maxId=65000, prefix="/",
datafile="etc/passwd"):
"""
Get users from passwd from minId to maxId
"""
retList = []
fileName = path.join(prefix, datafile)
if os.access(fileName, os.R_OK):
reNumb = re.compile("^\d+$")
9 years ago
lenData = 7
userData = filter(lambda x: len(x) == lenData,
map(lambda x: x.rstrip().split(":"),
9 years ago
open(fileName)))
userData = filter(
lambda x: reNumb.match(x[2]) and minId <= int(x[2]) <= maxId,
userData)
sortUsers = map(lambda x: x[0], userData)
sortUsers.sort()
9 years ago
retList = ["root"] + sortUsers
return retList
9 years ago
def getSupportArch():
"""Get supported architectures by processor.
Is support processor x86_64 else only i686.
"""
9 years ago
if filter(lambda x: x.startswith('flags') and " lm " in x,
readLinesFile('/proc/cpuinfo')):
return ['i686', 'x86_64']
else:
return ['i686']
9 years ago
class CmdlineParams(object):
"""
Параметры опции загрузки ядра calculate=
"""
# названия параметров
Calculate = "calculate"
IsoscanFile = Dracut.IsoScanCmdParam
IOScheduler = "elevator"
# внутренние параметры calculate
Locale = "lang"
Keymap = "keymap"
Timezone = "timezone"
Resolution = "resolution"
Video = "video"
Composite = "composite"
Domain = "domain"
DomainPassword = "domain_pw"
Audio = "audio"
Clock = "clock"
def getValueFromCmdLine(option, num=None):
"""Get value of parameter from boot params
Parameters:
option param name
num number part of value parameter (, split)
"""
cmdLine = "/proc/cmdline"
calculateParam = option
names = (
CmdlineParams.Locale,
CmdlineParams.Keymap,
CmdlineParams.Timezone,
CmdlineParams.Resolution,
CmdlineParams.Video,
CmdlineParams.Composite,
CmdlineParams.Domain,
CmdlineParams.DomainPassword,
CmdlineParams.Audio,
CmdlineParams.Clock)
# try get timezone from kernel calculate param
try:
if num is None:
name = None
elif type(num) == str and not num.isdigit():
name = num
num = names.index(name)
else:
name = names[int(num)]
9 years ago
for param in open(cmdLine, "r").read().split(" "):
parname, op, value = param.partition("=")
if parname == calculateParam and op == "=":
# new format
if name is None:
return value.strip()
if ":" in value:
params = dict(
9 years ago
map(lambda x: x.partition(':')[0::2],
filter(lambda x: x,
value.split(','))))
return params.get(name, "").strip()
# old format
else:
values = value.split(",")
if len(values) > num and values[num].strip():
return values[num].strip()
9 years ago
except (IOError, ValueError, IndexError):
return ""
9 years ago
def getValueFromConfig(config, name):
"""Get value of parameter from bash type file
Parameters:
config config file name
name param name
"""
9 years ago
reMatch = re.compile("^%s\s*=\s*(.*?)\s*$" % name, re.I)
val = None
try:
if path.exists(config):
9 years ago
for line in open(config, "r").readlines():
match = reMatch.match(line)
if match:
9 years ago
val = match.groups()[0].strip()
for quotas in ('"', "'"):
if val.startswith(quotas) and val.endswith(quotas):
val = val.strip(quotas)
break
except Exception:
pass
9 years ago
return val
9 years ago
def getVideoFromXorgLog(prefix="/", available_drivers=()):
13 years ago
"""Get video driver from Xorg log"""
# Try analize Xorg.{DISPLAY}.log
9 years ago
display = os.environ.get('DISPLAY', ':0')
13 years ago
if display and available_drivers:
9 years ago
reDriver = re.compile('|'.join(map(lambda x: "%s_drv.so" % x,
13 years ago
available_drivers)))
display_number = re.search(r':(\d+)(\..*)?', display)
reDriverName = re.compile(r'([^/]+)_drv.so')
if display_number:
9 years ago
xorg_log_file = path.join(prefix, 'var/log/Xorg.%s.log' %
display_number.group(1))
13 years ago
if path.exists(xorg_log_file):
9 years ago
matchStrs = map(
lambda x: x.group(1),
filter(lambda x: x, map(
reDriverName.search,
filter(lambda x: "drv" in x and reDriver.search(x),
readLinesFile(xorg_log_file)))))
13 years ago
if matchStrs:
return matchStrs[-1]
return ""
9 years ago
13 years ago
def getVideoFromXorgConf(prefix="/"):
"""Get video driver from xorg.conf"""
9 years ago
xorg_conf = path.join(prefix, 'etc/X11/xorg.conf')
13 years ago
# analize /etc/X11/xorg.conf
if path.exists(xorg_conf):
matchSect = re.search(r'Section "Device".*?EndSection',
9 years ago
open(xorg_conf).read(), re.S)
13 years ago
if matchSect:
resDriver = re.search(r'\n\s*Driver\s*"([^"]+)"',
9 years ago
matchSect.group(0), re.S)
13 years ago
if resDriver:
return resDriver.group(1)
return ""
9 years ago
13 years ago
def getVideoFromCmdLine():
"""Get video driver from cmdline"""
videoVal = getValueFromCmdLine(CmdlineParams.Calculate,
CmdlineParams.Video)
9 years ago
videoVal = {'i915': 'intel'}.get(videoVal, videoVal)
13 years ago
return videoVal
9 years ago
13 years ago
def getVideoFromModules():
9 years ago
workedModules = map(lambda x: x[0],
filter(lambda x: x[1].isdigit() and int(x[1]) > 0,
map(lambda x: x.split()[:3:2],
readLinesFile('/proc/modules'))))
mapModules = {'nouveau': 'nouveau',
'radeon': 'radeon',
'i915': 'intel',
'fglrx': 'fglrx',
'nvidia': 'nvidia',
# 'amdgpu': 'amdgpu',
9 years ago
'via': 'via',
'vmware': 'vmware'}
for module, videodrv in mapModules.items():
13 years ago
if module in workedModules:
return videodrv
else:
return ""
9 years ago
def getVideoFromVendor(hr_video, available_drivers):
13 years ago
if "nvidia" in available_drivers:
defaultNvidia = "nvidia"
else:
defaultNvidia = "nv"
if "fglrx" in available_drivers:
defaultAti = "fglrx"
else:
defaultAti = "radeon"
defaultDriver = {
9 years ago
'nvidia': defaultNvidia,
'ati': defaultAti,
'intel': 'intel',
'via': 'via',
'vmware': 'vmware'}
13 years ago
if hr_video in defaultDriver and \
9 years ago
defaultDriver[hr_video] in available_drivers:
13 years ago
return defaultDriver[hr_video]
else:
return "other"
9 years ago
13 years ago
def getCompositeFromXorgconf(prefix="/"):
"""Get composite value from xorg.conf"""
xorgConfig = path.join(prefix,
9 years ago
"etc/X11/xorg.conf")
13 years ago
confLines = readLinesFile(xorgConfig)
flagStartExtensions = False
lineCompositeTmp = ""
lineComposite = ""
for line in confLines:
line = line.strip()
if flagStartExtensions:
if line.startswith('EndSection'):
lineComposite = lineCompositeTmp
break
elif line.startswith('Section'):
break
if line.startswith('Option') and '"Composite"' in line:
lineCompositeTmp = line
else:
if line.startswith('Section') and '"Extensions"' in line:
flagStartExtensions = True
if lineComposite:
listOpt = filter(lambda x: x.strip(), lineComposite.split('"'))
if len(listOpt) == 3:
ret = listOpt[2].lower()
9 years ago
if ret in ("on", "true", "yes", "1"):
13 years ago
return "on"
9 years ago
elif ret in ("off", "false", "no", "0"):
13 years ago
return "off"
return None
9 years ago
def getKernelUid(dev):
"""Get Kernel UID by UUID of device"""
9 years ago
blkidProcess = process('/sbin/blkid', '-c', '/dev/null', '-s', 'UUID',
'-o', 'value', dev)
res = blkidProcess.read().strip()
if res:
return res[:8]
else:
return dev.replace("/", "")
9 years ago
def dict_by_columns(i, sep, key, value):
"""
Получить словарь из файла, где каждая строка разделена sep символом
на колонки, key - номер колонки ключей, value номер колонки значений
"""
9 years ago
max_val = max(key, value)
return dict(
map(lambda x: (x[key], x[value]),
9 years ago
filter(lambda x: len(x) >= max_val,
map(lambda x: x.split(sep), i))))
from calculate.lib.utils.files import readLinesFile
9 years ago
def getUserGroups(userName, prefix="/"):
"""
Get user groups from /etc/groups
"""
9 years ago
return map(lambda x: x[0],
filter(lambda x: len(x) > 1 and userName in x[1].split(','),
map(lambda x: x.split(':')[0::3],
readLinesFile(path.join(prefix, 'etc/group')))))
def getUserPrimaryGroup(userName, prefix="/"):
"""
Получить основную группу пользователя
"""
9 years ago
passwd = path.join(prefix, 'etc/passwd')
group = path.join(prefix, 'etc/group')
sep_symb = ":"
9 years ago
userGidMap = dict_by_columns(readLinesFile(passwd), sep_symb, 0, 3)
gidGroupMap = dict_by_columns(readLinesFile(group), sep_symb, 2, 0)
if userName in userGidMap:
gid = userGidMap[userName]
9 years ago
return gidGroupMap.get(gid, None)
return None
def getGroups(prefix="/"):
"""
Get groups from etc/group
"""
return filter(None,
9 years ago
map(lambda x: x.split(':')[0],
readLinesFile(path.join(prefix, 'etc/group'))))
12 years ago
9 years ago
def getPagesInterval(count, offset, length):
"""
Получить интервал страниц (например 2 из 5, при (5,5,15)
"""
9 years ago
rt = max(0, length - offset - count)
lt = min(length, offset)
lt = int(math.ceil(float(lt) / count))
rt = int(math.ceil(float(rt) / count))
return lt + 1, rt + lt + 1
11 years ago
9 years ago
def mountEcryptfs(userName, userPwd, userDir):
"""
Подключить ecryptfs
Args:
userName: логин пользователя
userPwd: пароль пользователя
userDir: домашний каталог пользователя
"""
from calculate.lib.utils.files import (process, readLinesFile, STDOUT)
from calculate.lib.utils.mount import isMount
9 years ago
if ".Private" in isMount(userDir):
return True
# расшифровать passphrase
ecryptUserName = path.join('/home/.ecryptfs', userName)
wrappedPassphraseFile = path.join(ecryptUserName,
9 years ago
".ecryptfs/wrapped-passphrase")
p = process('/usr/bin/ecryptfs-unwrap-passphrase', wrappedPassphraseFile)
p.write(userPwd)
try:
if p.failed():
raise Exception
result = p.readlines()
if len(result) > 1 and "Passphrase:" in result[0] and result[1]:
passphrase = result[1]
else:
raise Exception
9 years ago
except Exception:
raise CommonError(_("Failed to unwrap the passphrase"))
# добавить passphrase в ключи ядра
9 years ago
p = process('/usr/bin/ecryptfs-add-passphrase', '--fnek', '-',
stderr=STDOUT)
p.write(passphrase)
if not p.success():
9 years ago
raise CommonError(p.read() + "Failed to add passphrase")
# получить сигнатуры шифрования содержимого файлов и имен файлов
try:
ecryptfs_sig, ecryptfs_fnek_sig = \
9 years ago
readLinesFile(path.join(ecryptUserName, ".ecryptfs/Private.sig"))
except ValueError:
raise CommonError(_("Failed to parse Private.sig"))
# подключить шифрованный раздел
9 years ago
mountProcess = process(
'/sbin/mount.ecryptfs',
path.join(ecryptUserName, '.Private'),
userDir,
9 years ago
'-o', 'ecryptfs_passthrough=n,' 'ecryptfs_cipher=aes,'
'ecryptfs_key_bytes=16,' 'no_sig_cache,'
'ecryptfs_enable_filename_crypto=y,'
'ecryptfs_sig={ecryptfs_sig},'
'ecryptfs_fnek_sig={ecryptfs_fnek_sig},'
'passphrase_passwd_fd=0'.format(
ecryptfs_sig=ecryptfs_sig,
9 years ago
ecryptfs_fnek_sig=ecryptfs_fnek_sig), stderr=STDOUT)
# отправить пароль через stdin
9 years ago
mountProcess.write("passphrase_passwd=" + userPwd)
return mountProcess.success()
9 years ago
def isBootstrapDataOnly(user_dir):
"""
Каталог содержит только сертификат, созданный командой cl-core
а так же настроенные симлинки на .face, skel
"""
from calculate.lib.utils.files import find
max_diff = 10
skel_files = set([x for x in find('/etc/skel', onefilesystem=True,
fullpath=False)
if not x.startswith(".calculate")])
user_data = find(user_dir, onefilesystem=True, fullpath=False)
user_files = itertools.islice((x for x in user_data
if not x.startswith(".calculate")),
len(skel_files)+max_diff)
user_files = set(user_files)
return not len(user_files - skel_files) > max_diff
9 years ago
def getPortageUidGid():
"""
Получить uid и gid пользователя portage
"""
data = pwd.getpwnam('portage')
if data:
9 years ago
return data.pw_uid, data.pw_gid
else:
9 years ago
return 250, 250
def getXorgConfContent(prefix="/"):
return "\n".join(open(x,'r').read() for x in
[path.join(prefix, "etc/X11/xorg.conf")] +
glob.glob(path.join(prefix,"etc/X11/xorg.conf.d/*"))
if path.isfile(x))