Refactoring

develop 3.4.1.1
Mike Khiretskiy 9 years ago
parent 943ae97e3a
commit 4f4d4ce2cf

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# Copyright 2008-2012 Calculate Ltd. http://www.calculate-linux.org # Copyright 2008-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -15,7 +15,9 @@
# limitations under the License. # limitations under the License.
from PySide import QtCore, QtGui from PySide import QtCore, QtGui
import os,sys import os
import re
class ImageViewer(QtGui.QMainWindow): class ImageViewer(QtGui.QMainWindow):
def __init__(self): def __init__(self):
@ -28,25 +30,27 @@ class ImageViewer(QtGui.QMainWindow):
screen = QtGui.QDesktopWidget().screenGeometry() screen = QtGui.QDesktopWidget().screenGeometry()
self.setGeometry(screen) self.setGeometry(screen)
self.open('/usr/share/wallpapers/dm-background.png') or \ if not any(self.open(x) for x in
self.open('/usr/share/apps/ksplash/Themes/CalculateSplashEn/' ('/usr/share/wallpapers/dm-background.png',
'400x300/background.png') or \ '/usr/share/apps/ksplash/Themes/CalculateSplashEn/'
self.setBackground() '400x300/background.png')):
self.set_background()
def selectColor(self): @staticmethod
def select_color():
try: try:
if filter(re.compile(r"(cld|cldx|cldg|cmc|cls)-themes-12").search, if filter(re.compile(r"(cld|cldx|cldg|cmc|cls)-themes-12").search,
os.listdir('/var/db/pkg/media-gfx')): os.listdir('/var/db/pkg/media-gfx')):
return "#73a363" return "#73a363"
except: except OSError:
pass pass
return '#30648b' return '#30648b'
def setBackground(self): def set_background(self):
self.setStyleSheet("background-color: %s"%self.selectColor()) self.setStyleSheet("background-color: %s" % self.select_color())
def open(self,fileName): def open(self, fn):
image = QtGui.QImage(fileName) image = QtGui.QImage(fn)
if image.isNull(): if image.isNull():
return False return False
@ -55,8 +59,10 @@ class ImageViewer(QtGui.QMainWindow):
self.imageLabel.adjustSize() self.imageLabel.adjustSize()
return True return True
if __name__ == '__main__': if __name__ == '__main__':
import sys import sys
app = QtGui.QApplication(sys.argv) app = QtGui.QApplication(sys.argv)
imageViewer = ImageViewer() imageViewer = ImageViewer()
imageViewer.show() imageViewer.show()

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2012-2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2012-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -15,14 +15,15 @@
# limitations under the License. # limitations under the License.
__app__ = 'calculate-desktop' __app__ = 'calculate-desktop'
__version__ = '3.1.8' __version__ = '3.4.2'
import os
import sys import sys
from calculate.lib.datavars import DataVars from calculate.lib.datavars import DataVars
from calculate.lib.cl_lang import setLocalTranslate from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_desktop3',sys.modules[__name__])
setLocalTranslate('cl_desktop3', sys.modules[__name__])
class DataVarsDesktop(DataVars): class DataVarsDesktop(DataVars):
"""Variable class for desktop package""" """Variable class for desktop package"""

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2010-2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2010-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -16,51 +16,49 @@
import os import os
from os import path from os import path
import re
import sys import sys
import pwd
import time import time
import traceback from calculate.core.server.core_interfaces import MethodsInterface
from calculate.desktop._cl_keys import getKey, clearKey from calculate.desktop._cl_keys import getKey
from datavars import DataVarsDesktop, DataVars, __version__,__app__
from calculate.lib.cl_template import (Template, ProgressTemplate, from calculate.lib.utils.files import (isMount, process,
TemplatesError,templateFunction,iniParser) getRunCommands, STDOUT, childMounts,
from calculate.lib.utils.files import (runOsCommand, isMount,process, getLoopFromPath,
getRunCommands,STDOUT,childMounts,getLoopFromPath, getMdRaidDevices, listDirectory,
getMdRaidDevices,listDirectory,removeDir, removeDir,
makeDirectory) makeDirectory, getProgPath)
from calculate.lib.utils.common import (getpathenv,appendProgramToEnvFile, from calculate.lib.utils.common import (mountEcryptfs,
removeProgramToEnvFile,mountEcryptfs, CommonError, isBootstrapDataOnly)
CommonError, isBootstrapDataOnly)
from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
setLocalTranslate('cl_desktop3',sys.modules[__name__])
_ = lambda x: x
setLocalTranslate('cl_desktop3', sys.modules[__name__])
__ = getLazyLocalTranslate(_) __ = getLazyLocalTranslate(_)
from itertools import ifilter
import tarfile import tarfile
import tempfile import tempfile
import shutil import shutil
from itertools import count
class DesktopError(Exception): class DesktopError(Exception):
"""Desktop Error""" """Desktop Error"""
class Desktop: class Desktop(MethodsInterface):
""" """
Модуль для настройки пользовательского сеанса и выполнения Модуль для настройки пользовательского сеанса и выполнения
принудительного выхода из X сессии пользователя принудительного выхода из X сессии пользователя
""" """
def __init__(self): def __init__(self):
self.homeDir = "" self.homeDir = ""
self.clTempl = None self.clTempl = None
self.clVars = None self.clVars = None
def createCryptDir(self,userName,uid,gid,userDir,recreateOnError=False): def createCryptDir(self, userName, uid, gid, userDir,
recreateOnError=False):
""" """
Создать шифрование домашней директории, или подключить существующую Создать шифрование домашней директории, или подключить существующую
@ -73,20 +71,21 @@ class Desktop:
# проверить наличие пароля в ключах ядра # проверить наличие пароля в ключах ядра
if not userPwd or userPwd == "XXXXXXXX": if not userPwd or userPwd == "XXXXXXXX":
raise DesktopError(_("User password not found")) raise DesktopError(_("User password not found"))
ecryptfsPath = path.join('/home/.ecryptfs',userName) ecryptfsPath = path.join('/home/.ecryptfs', userName)
# если шифрование уже используется # если шифрование уже используется
if path.exists(ecryptfsPath): if path.exists(ecryptfsPath):
for d in (".ecryptfs",".Private"): for d in (".ecryptfs", ".Private"):
source,target = path.join(ecryptfsPath,d),path.join(userDir,d) source, target = path.join(ecryptfsPath, d), path.join(userDir,
d)
if not path.lexists(target): if not path.lexists(target):
os.symlink(source,target) os.symlink(source, target)
# попытаться подключить шифрованные данные # попытаться подключить шифрованные данные
try: try:
if not mountEcryptfs(userName,userPwd,userDir): if not mountEcryptfs(userName, userPwd, userDir):
error = _("Failed to mount ecrypted data") error = _("Failed to mount ecrypted data")
except CommonError as e: except CommonError as e:
error = (_("Failed to mount ecrypted data")+ error = (_("Failed to mount ecrypted data") +
_(": ")+'":%s"'%str(e)) _(": ") + '":%s"' % str(e))
# если при подключении произошли ошибки # если при подключении произошли ошибки
if error: if error:
# заархивировать текущий профиль и удалить его # заархивировать текущий профиль и удалить его
@ -94,17 +93,17 @@ class Desktop:
self.printSUCCESS(_("Recovering encrypted data")) self.printSUCCESS(_("Recovering encrypted data"))
if self.getMountUserPaths(userDir): if self.getMountUserPaths(userDir):
raise DesktopError(_("Failed to encrypt the directory")) raise DesktopError(_("Failed to encrypt the directory"))
for source in (userDir,ecryptfsPath): for source in (userDir, ecryptfsPath):
if path.exists(source): if path.exists(source):
if listDirectory(source): if listDirectory(source):
target = source+".bak" target = source + ".bak"
newtarget = target newtarget = target
if path.exists(target): if path.exists(target):
removeDir(target) removeDir(target)
os.rename(source,newtarget) os.rename(source, newtarget)
else: else:
os.rmdir(source) os.rmdir(source)
self.createUserDir(userName,uid,gid,userDir) self.createUserDir(userName, uid, gid, userDir)
# ошибка создания шифрования # ошибка создания шифрования
else: else:
raise DesktopError(error) raise DesktopError(error)
@ -116,39 +115,40 @@ class Desktop:
if isBootstrapDataOnly(userDir): if isBootstrapDataOnly(userDir):
if childMounts(userDir): if childMounts(userDir):
raise DesktopError( raise DesktopError(
_("Failed to create an encrypted user profile")+ _("Failed to create an encrypted user profile") +
_(": ")+ _(": ") +
_("The home directory contains mount points")) _("The home directory contains mount points"))
# поместить данные во временный tarfile # поместить данные во временный tarfile
calculateName = ".calculate" calculateName = ".calculate"
calculatePath = path.join(userDir,calculateName) calculatePath = path.join(userDir, calculateName)
tf = tempfile.TemporaryFile() tf = tempfile.TemporaryFile()
with tarfile.open(fileobj=tf,mode='w:') as tarf: with tarfile.open(fileobj=tf, mode='w:') as tarf:
tarf.add(calculatePath,calculateName) tarf.add(calculatePath, calculateName)
tf.flush() tf.flush()
tf.seek(0) tf.seek(0)
# удалить эти данные # удалить эти данные
shutil.rmtree(calculatePath) shutil.rmtree(calculatePath)
# создать шифрованные данные # создать шифрованные данные
e = process('/usr/bin/ecryptfs-setup-private','-u',userName, e = process('/usr/bin/ecryptfs-setup-private', '-u', userName,
'-b','-l',userPwd,stderr=STDOUT) '-b', '-l', userPwd, stderr=STDOUT)
if e.failed(): if e.failed():
raise DesktopError(e.read()) raise DesktopError(e.read())
# если были данные от бутстрапа, то распаковать их # если были данные от бутстрапа, то распаковать их
if tf: if tf:
with tarfile.open(fileobj=tf,mode='r:') as tarf: with tarfile.open(fileobj=tf, mode='r:') as tarf:
tarf.extractall(userDir) tarf.extractall(userDir)
except Exception as e: except Exception as e:
# в случае ошибки сохраняем архив (с данными bootstrap) # в случае ошибки сохраняем архив (с данными bootstrap)
# из памяти в файловую систему # из памяти в файловую систему
if tf: if tf:
tf.seek(0) tf.seek(0)
bakArchName = path.join(userDir,".calculate.tar.bz2") bakArchName = path.join(userDir, ".calculate.tar.bz2")
with open(bakArchName,'w') as f: with open(bakArchName, 'w') as f:
f.write(tf.read()) f.write(tf.read())
raise DesktopError(str(e)+ raise DesktopError(str(e) +
_("Failed to create an encrypted user profile")) _(
"Failed to create an encrypted user profile"))
finally: finally:
if tf: if tf:
tf.close() tf.close()
@ -161,11 +161,11 @@ class Desktop:
if not path.exists(userDir): if not path.exists(userDir):
os.makedirs(userDir) os.makedirs(userDir)
if mode: if mode:
os.chmod(userDir,mode) os.chmod(userDir, mode)
os.chown(userDir,uid,gid) os.chown(userDir, uid, gid)
return True return True
else: else:
raise DesktopError(_("Path %s exists") %userDir) raise DesktopError(_("Path %s exists") % userDir)
def umountUserRes(self, *umountPaths): def umountUserRes(self, *umountPaths):
""" """
@ -183,66 +183,53 @@ class Desktop:
Found user resources Found user resources
""" """
if not homeDir: if not homeDir:
userName = self.clVars.Get("ur_login") self.clVars.Get("ur_login")
homeDir = self.clVars.Get("ur_home_path") homeDir = self.clVars.Get("ur_home_path")
if not homeDir: if not homeDir:
raise DesktopError(_("Failed to determine the home directory")) raise DesktopError(_("Failed to determine the home directory"))
dirStart, dirEnd = path.split(homeDir) dirStart, dirEnd = path.split(homeDir)
mountProfileDir = path.join(dirStart, ".%s" %dirEnd) mountProfileDir = path.join(dirStart, ".%s" % dirEnd)
mountRemoteProfileDir = path.join(dirStart, ".%s.remote" %dirEnd) mountRemoteProfileDir = path.join(dirStart, ".%s.remote" % dirEnd)
return filter(lambda x: x.startswith(homeDir) or\ return filter(lambda x: x.startswith(homeDir) or
x.startswith(mountProfileDir) or\ x.startswith(mountProfileDir) or
x.startswith(mountRemoteProfileDir), x.startswith(mountRemoteProfileDir),
map(lambda x: x.split(" ")[1],\ map(lambda x: x.split(" ")[1],
open("/proc/mounts").readlines())) open("/proc/mounts").readlines()))
def execProg(self, cmdStrProg, inStr=False, envProg={}):
"""
Exec external program
"""
env_path = {"PATH":getpathenv()}
env = {}
env.update(os.environ.items() + env_path.items() + envProg.items())
retCode,programOut = runOsCommand(cmdStrProg,in_str=inStr,env_dict=env)
if not retCode:
return programOut
return False
def umountSleepPath(self, rpath): def umountSleepPath(self, rpath):
""" """
Отмонтировать указанный путь, а также отключить используемые Отмонтировать указанный путь, а также отключить используемые
в этом пути loop устройства и raid в этом пути loop устройства и raid
""" """
# check for mount # check for mount
umount_cmd = getProgPath('/bin/umount')
fuser_cmd = getProgPath("/bin/fuser")
loops = getLoopFromPath(rpath) loops = getLoopFromPath(rpath)
if loops: if loops:
setLoops = set(map(lambda x:x.partition('/dev/')[2],loops)) setLoops = set(map(lambda x: x.partition('/dev/')[2], loops))
mdInfo = getMdRaidDevices() mdInfo = getMdRaidDevices()
for k,v in mdInfo.items(): for k, v in mdInfo.items():
if setLoops & set(v): if setLoops & set(v):
self.umountSleepPath('/dev/%s'%k) self.umountSleepPath('/dev/%s' % k)
process('/sbin/mdadm','--stop','/dev/%s'%k).success() process('/sbin/mdadm', '--stop', '/dev/%s' % k).success()
for loop in loops: for loop in loops:
self.umountSleepPath(loop) self.umountSleepPath(loop)
process('/sbin/losetup','-d',loop).success() process('/sbin/losetup', '-d', loop).success()
if isMount(rpath): if isMount(rpath):
for waittime in [0,0.5,1,2]: for waittime in [0, 0.5, 1, 2]:
time.sleep(waittime) time.sleep(waittime)
if not self.execProg("umount %s"%rpath) is False \ process(umount_cmd, rpath).success()
or not isMount(rpath): if not isMount(rpath):
if not isMount(rpath): return True
return True process(fuser_cmd, "-km", rpath).success()
self.execProg("fuser -km %s"%rpath)
for waittime in [0.5, 0.5, 0.5, 0.5, 0.5, 0.5]: for waittime in [0.5, 0.5, 0.5, 0.5, 0.5, 0.5]:
time.sleep(waittime) time.sleep(waittime)
if not self.execProg("umount %s"%rpath) is False \ if not isMount(rpath):
or not isMount(rpath): return True
if not isMount(rpath): process(umount_cmd, "-l", rpath).success()
return True
self.execProg("umount -l %s"%rpath)
else: else:
if isMount(rpath): if isMount(rpath):
self.printERROR(_("Failed to unmount directory %s")%rpath) self.printERROR(_("Failed to unmount directory %s") % rpath)
return False return False
return True return True
@ -257,9 +244,9 @@ class Desktop:
fastlogin_user = path.join(fastlogin, urLogin) fastlogin_user = path.join(fastlogin, urLogin)
if not path.exists(fastlogin_user): if not path.exists(fastlogin_user):
try: try:
open(fastlogin_user,'w').close() open(fastlogin_user, 'w').close()
return True return True
except: except IOError:
self.printWARNING(_("Failed to create the fastlogin mark file")) self.printWARNING(_("Failed to create the fastlogin mark file"))
return False return False
@ -268,24 +255,25 @@ class Desktop:
Выполнить logout пользователя через dbus Выполнить logout пользователя через dbus
""" """
display = self.clVars.Select('cl_desktop_online_display', display = self.clVars.Select('cl_desktop_online_display',
where='cl_desktop_online_user',eq=urLogin,limit=1) where='cl_desktop_online_user', eq=urLogin,
limit=1)
session = self.clVars.Get('cl_desktop_xsession') session = self.clVars.Get('cl_desktop_xsession')
if session == 'xfce': if session == 'xfce':
logoutCommand = "/usr/bin/qdbus org.xfce.SessionManager " \ logoutCommand = "/usr/bin/qdbus org.xfce.SessionManager " \
"/org/xfce/SessionManager Logout False False" "/org/xfce/SessionManager Logout False False"
elif session == 'kde': elif session == 'kde':
logoutCommand = "/usr/bin/kquitapp ksmserver" logoutCommand = "/usr/bin/kquitapp ksmserver"
elif session == 'gnome': elif session == 'gnome':
logoutCommand = "/usr/bin/qdbus org.gnome.SessionManager " \ logoutCommand = "/usr/bin/qdbus org.gnome.SessionManager " \
"/org/gnome/SessionManager Logout 1" "/org/gnome/SessionManager Logout 1"
else: else:
raise DesktopError(_("Unable to detect the X session")) raise DesktopError(_("Unable to detect the X session"))
if process("su",urLogin,"-c", if process("su", urLogin, "-c",
("DISPLAY=:%s "%display)+logoutCommand).failed(): ("DISPLAY=:%s " % display) + logoutCommand).failed():
raise DesktopError(_("Unable to send the logout command")) raise DesktopError(_("Unable to send the logout command"))
return True return True
def waitLogout(self,urLogin,waitTime,postWaitTime=5): def waitLogout(self, urLogin, waitTime, postWaitTime=5):
""" """
Ожидать завершения пользовательского сеанса Ожидать завершения пользовательского сеанса
@ -294,24 +282,24 @@ class Desktop:
waitTime: время ожидания завершения сеанса waitTime: время ожидания завершения сеанса
""" """
if filter(lambda x: "xdm/xdm\x00--logout" in x, if filter(lambda x: "xdm/xdm\x00--logout" in x,
getRunCommands()): getRunCommands()):
for i in range(0,waitTime): for i in range(0, waitTime):
if not filter(lambda x: "xdm/xdm\x00--logout" in x, if not filter(lambda x: "xdm/xdm\x00--logout" in x,
getRunCommands()): getRunCommands()):
return True return True
time.sleep(1) time.sleep(1)
else: else:
raise DesktopError(_("Unable to wait for completion " raise DesktopError(_("Unable to wait for completion "
"of the user logout")) "of the user logout"))
for wait in range(0,5): for wait in range(0, 5):
self.clVars.Invalidate('cl_desktop_online_data') self.clVars.Invalidate('cl_desktop_online_data')
if not urLogin in self.clVars.Get('cl_desktop_online_user'): if urLogin not in self.clVars.Get('cl_desktop_online_user'):
return True return True
time.sleep(1) time.sleep(1)
else: else:
return False return False
def prepareFace(self,ur_home_path): def prepareFace(self, ur_home_path):
"""Подготовить каталог пользователя с шифрованием для работы с .face """Подготовить каталог пользователя с шифрованием для работы с .face
Для шифрованных профилей в корне домашней директории Для шифрованных профилей в корне домашней директории
@ -325,7 +313,7 @@ class Desktop:
True/False в зависимости от успешности True/False в зависимости от успешности
""" """
if path.exists(ur_home_path): if path.exists(ur_home_path):
symlink_path = path.join(ur_home_path,'.face') symlink_path = path.join(ur_home_path, '.face')
if not path.lexists(symlink_path): if not path.lexists(symlink_path):
os.symlink('.ecryptfs/.face', symlink_path) os.symlink('.ecryptfs/.face', symlink_path)
return True return True

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2010-2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2010-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -16,21 +16,23 @@
import sys import sys
from os import path from os import path
from calculate.core.server.func import Action,Tasks from calculate.core.server.func import Action, Tasks
from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
from calculate.lib.utils.files import FilesError, isMount from calculate.lib.utils.files import FilesError, isMount
from calculate.desktop.desktop import DesktopError from calculate.desktop.desktop import DesktopError
from calculate.lib.cl_template import TemplatesError from calculate.lib.cl_template import TemplatesError
setLocalTranslate('cl_desktop3',sys.modules[__name__]) _ = lambda x: x
setLocalTranslate('cl_desktop3', sys.modules[__name__])
__ = getLazyLocalTranslate(_) __ = getLazyLocalTranslate(_)
class ClDesktopLogoutAction(Action): class ClDesktopLogoutAction(Action):
""" """
Вывести пользователя из X сессии Вывести пользователя из X сессии
""" """
# ошибки, которые отображаются без подробностей # ошибки, которые отображаются без подробностей
native_error = (FilesError,DesktopError,TemplatesError) native_error = (FilesError, DesktopError, TemplatesError)
successMessage = __("User logged out!") successMessage = __("User logged out!")
failedMessage = __("Unable to log out") failedMessage = __("Unable to log out")
@ -38,20 +40,21 @@ class ClDesktopLogoutAction(Action):
# список задач для действия # список задач для действия
tasks = [ tasks = [
{'name':'user_logout', {'name': 'user_logout',
'method':'Desktop.userLogout(cl_desktop_login)', 'method': 'Desktop.userLogout(cl_desktop_login)',
}, },
{'name':'wait_logout', {'name': 'wait_logout',
'message':__("Waiting for the logout"), 'message': __("Waiting for the logout"),
'method':'Desktop.waitLogout(cl_desktop_login,300)'} 'method': 'Desktop.waitLogout(cl_desktop_login,300)'}
] ]
class ClDesktopAction(Action): class ClDesktopAction(Action):
""" """
Настроить пользовательский профиль Настроить пользовательский профиль
""" """
# ошибки, которые отображаются без подробностей # ошибки, которые отображаются без подробностей
native_error = (FilesError,DesktopError,TemplatesError) native_error = (FilesError, DesktopError, TemplatesError)
successMessage = __("User account {ur_login} has been " successMessage = __("User account {ur_login} has been "
"successfully configured") "successfully configured")
@ -60,50 +63,51 @@ class ClDesktopAction(Action):
# список задач для действия # список задач для действия
tasks = [ tasks = [
# создать домашниюю директорию # создать домашниюю директорию
{'name':'create_home', {'name': 'create_home',
'message':__("Creating the home directory for {ur_login}"), 'message': __("Creating the home directory for {ur_login}"),
'method':'Desktop.createUserDir(ur_login,ur_uid,ur_gid,ur_home_path)', 'method': 'Desktop.createUserDir(ur_login,ur_uid,ur_gid,ur_home_path)',
'condition':lambda dv:not path.exists(dv.Get('ur_home_path')) 'condition': lambda dv: not path.exists(dv.Get('ur_home_path'))
}, },
# используется ли шифрование # используется ли шифрование
{'name':'crypt', {'name': 'crypt',
'condition':lambda dv:(not isMount(dv.Get('ur_home_path')) and \ 'condition': lambda dv: (not isMount(dv.Get('ur_home_path')) and
dv.Get('ur_home_crypt_set') == 'on' and dv.Get('ur_home_crypt_set') == 'on' and
(not dv.isModuleInstalled("install") or (not dv.isModuleInstalled("install") or
dv.Get('install.cl_autologin') != dv.Get('ur_login'))) dv.Get('install.cl_autologin') != dv.Get(
'ur_login')))
}, },
# подготовить шифрованный профиль пользователя для работы с .icon # подготовить шифрованный профиль пользователя для работы с .icon
{'name':'crypt:prepare_icon', {'name': 'crypt:prepare_icon',
'method':'Desktop.prepareFace(ur_home_path)', 'method': 'Desktop.prepareFace(ur_home_path)',
'condition':lambda Get:Get('ur_domain_set') == 'off' 'condition': lambda Get: Get('ur_domain_set') == 'off'
}, },
# подключить шифрованные данные # подключить шифрованные данные
{'name':'crypt:ecryptfs', {'name': 'crypt:ecryptfs',
'message':__("Mounting encrypted data"), 'message': __("Mounting encrypted data"),
'method':'Desktop.createCryptDir(ur_login,ur_uid,ur_gid,' 'method': 'Desktop.createCryptDir(ur_login,ur_uid,ur_gid,'
'ur_home_path,False)' 'ur_home_path,False)'
}, },
# настроить пользовательских профиль шаблонами # настроить пользовательских профиль шаблонами
{'name':'user_profile', {'name': 'user_profile',
'message':__("Setting up the user profile"), 'message': __("Setting up the user profile"),
'method':'Desktop.applyTemplates(None,False,'\ 'method': 'Desktop.applyTemplates(None,False,'
'False,None)', 'False,None)',
'condition':lambda Get: Get('cl_desktop_force_setup_set') == 'on' or \ 'condition': lambda Get: (Get('cl_desktop_force_setup_set') == 'on' or
Get('cl_desktop_update_profile_set') == 'on' Get('cl_desktop_update_profile_set') == 'on')
}, },
{'name':'fast_login', {'name': 'fast_login',
'method':'Desktop.setFastlogin(ur_login)', 'method': 'Desktop.setFastlogin(ur_login)',
'essential':False, 'essential': False,
'condition':lambda Get: Get('ur_domain_set') == 'off' 'condition': lambda Get: Get('ur_domain_set') == 'off'
}, },
# отключить ресурсы подключенные в каталоге пользователя # отключить ресурсы подключенные в каталоге пользователя
{'name':'umount_userres', {'name': 'umount_userres',
'message': _("Unmouning user resources"), 'message': _("Unmouning user resources"),
'method':'Desktop.umountUserRes(ur_mount_dirs)', 'method': 'Desktop.umountUserRes(ur_mount_dirs)',
'condition': lambda dv:dv.Get('ur_mount_dirs'), 'condition': lambda dv: dv.Get('ur_mount_dirs'),
'depend': Tasks.failed()}, 'depend': Tasks.failed()},
{'name':'ecryptfs:umount_homedir', {'name': 'ecryptfs:umount_homedir',
'method':'Desktop.umountUserRes(ur_home_path)', 'method': 'Desktop.umountUserRes(ur_home_path)',
'depend': Tasks.failed()} 'depend': Tasks.failed()}
] ]

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2008-2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2008-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -14,14 +14,13 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import os
import sys import sys
from os import path from calculate.lib.datavars import ActionVariable
from calculate.lib.datavars import (Variable,VariableError,ReadonlyVariable,
ActionVariable)
from calculate.lib.cl_lang import setLocalTranslate from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_desktop3',sys.modules[__name__])
setLocalTranslate('cl_desktop3', sys.modules[__name__])
class VariableAcDesktopMerge(ActionVariable): class VariableAcDesktopMerge(ActionVariable):
""" """
@ -30,18 +29,19 @@ class VariableAcDesktopMerge(ActionVariable):
""" """
nonchroot = True nonchroot = True
def action(self,cl_action): def action(self, cl_action):
if cl_action == "merge": if cl_action == "merge":
return "on" return "on"
return "off" return "off"
class VariableAcDesktopProfile(ActionVariable): class VariableAcDesktopProfile(ActionVariable):
""" """
Action variable which has value "on" on user profile setup Action variable which has value "on" on user profile setup
""" """
nonchroot = True nonchroot = True
def action(self,cl_action): def action(self, cl_action):
if cl_action in ("desktop",): if cl_action in ("desktop",):
return "on" return "on"
return "off" return "off"

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2010-2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2010-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -19,50 +19,60 @@ import sys
import re import re
from os import path from os import path
import pwd import pwd
from calculate.lib.datavars import Variable,VariableError,ReadonlyVariable, \ from calculate.lib.datavars import (Variable, VariableError, ReadonlyVariable,
ReadonlyTableVariable,FieldValue ReadonlyTableVariable, FieldValue,
VariableInterface)
from calculate.lib.utils.common import getValueFromConfig
from calculate.lib.variables.user import VariableUrLogin from calculate.lib.variables.user import VariableUrLogin
from calculate.lib.utils.files import (readLinesFile,process,isMount, from calculate.lib.utils.files import (readLinesFile, process,
listDirectory) listDirectory)
from calculate.desktop._cl_keys import getKey from calculate.desktop._cl_keys import getKey
from itertools import * from itertools import *
from calculate.lib.cl_template import (templateFunction,iniParser) from calculate.lib.cl_template import templateFunction
from calculate.lib.cl_ini_parser import iniParser
import hashlib import hashlib
from calculate.lib.cl_lang import setLocalTranslate from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_desktop3',sys.modules[__name__])
_ = lambda x: x
setLocalTranslate('cl_desktop3', sys.modules[__name__])
class VariableUrJidHost(ReadonlyVariable): class VariableUrJidHost(ReadonlyVariable):
""" """
Jabber host for user Jabber host for user
""" """
def get(self): def get(self):
userJid = self.Get("ur_jid") userJid = self.Get("ur_jid")
if userJid: if userJid:
return userJid.partition('@')[2] return userJid.partition('@')[2]
return "" return ""
class DomainInfoHelper:
class DomainInfoHelper(VariableInterface):
""" """
Вспомогательный класс для определения доменный ли пользователь Вспомогательный класс для определения доменный ли пользователь
""" """
def getUserDataInFile(self, login, filePasswd): def getUserDataInFile(self, login, filePasswd):
return filter(lambda x: x[0]==login, return filter(lambda x: x[0] == login,
map(lambda x: x.strip().split(':'), map(lambda x: x.strip().split(':'),
readLinesFile(filePasswd))) readLinesFile(filePasswd)))
def isDomainUser(self,userName): def isDomainUser(self, userName):
if userName: if userName:
try: try:
passwdUserData = self.getUserDataInFile(userName, "/etc/passwd") passwdUserData = self.getUserDataInFile(userName, "/etc/passwd")
except: except Exception:
return False return False
if passwdUserData: if passwdUserData:
passwdUserData = passwdUserData[0] passwdUserData = passwdUserData[0]
try: try:
cacheUserData = self.getUserDataInFile(userName, cacheUserData = self.getUserDataInFile(
userName,
"/var/lib/calculate/calculate-client/cache/passwd") "/var/lib/calculate/calculate-client/cache/passwd")
except: except Exception:
return False return False
if cacheUserData: if cacheUserData:
cacheUserData = cacheUserData[0] cacheUserData = cacheUserData[0]
@ -73,70 +83,65 @@ class DomainInfoHelper:
return False return False
class VariableUrDomainSet(ReadonlyVariable,DomainInfoHelper): class VariableUrDomainSet(ReadonlyVariable, DomainInfoHelper):
""" """
Flag for determining domain user or local Flag for determining domain user or local
""" """
type = "bool" type = "bool"
def getUserDataInFile(self, login, filePasswd): def getUserDataInFile(self, login, file_passwd):
return filter(lambda x: x[0]==login, return filter(lambda x: x[0] == login,
map(lambda x: x.strip().split(':'), map(lambda x: x.strip().split(':'),
readLinesFile(filePasswd))) readLinesFile(file_passwd)))
def get(self): def get(self):
return "on" if self.isDomainUser(self.Get('ur_login')) else "off" return "on" if self.isDomainUser(self.Get('ur_login')) else "off"
class VariableClDesktopXsession(ReadonlyVariable): class VariableClDesktopXsession(ReadonlyVariable):
""" """
User current X session User current X session
""" """
session_list = ("kde", "gnome", "mate", "xfce", "plasma")
def get(self): def get(self):
envXsessionFile = "/etc/env.d/90xsession" envXsessionFile = "/etc/env.d/90xsession"
xsession = os.environ.get("XSESSION",None) xsession = os.environ.get("XSESSION", None)
desktopSession = os.environ.get("DESKTOP_SESSION",None) desktopSession = os.environ.get("DESKTOP_SESSION", None)
if not xsession: if not xsession:
if os.path.exists(envXsessionFile): xsession = getValueFromConfig(envXsessionFile, "XSESSION")
xsession = \
map(lambda x:x.partition("=")[2].strip("'\""),
filter(lambda x:x.startswith("XSESSION="),
filter(lambda x:not x.startswith("#"),
open(envXsessionFile,"r"))))
if xsession:
xsession = xsession[-1]
if xsession: if xsession:
if desktopSession and \ if (desktopSession and any(x in desktopSession.lower()
any(x in desktopSession.lower() for x in self.session_list)):
for x in ("kde","xfce","gnome")):
xsession = desktopSession xsession = desktopSession
if "kde" in xsession.lower(): xsession = xsession.lower()
return "kde" for session in self.session_list:
elif "gnome" in xsession.lower(): if session in xsession:
return "gnome" return session
elif "xfce" in xsession.lower():
return "xfce"
else: else:
return xsession.lower() return xsession
return "" return ""
class VariableClDesktopGstData(ReadonlyVariable): class VariableClDesktopGstData(ReadonlyVariable):
""" """
GStreamer data GStreamer data
""" """
def get(self): def get(self):
# try import gst # try import gst
copyargv = sys.argv
sys.argv = []
olderr = os.dup(sys.stderr.fileno())
try: try:
copyargv = sys.argv
sys.argv = []
olderr = os.dup(sys.stderr.fileno())
os.close(sys.stderr.fileno()) os.close(sys.stderr.fileno())
import gst import gst
import gst.interfaces import gst.interfaces
except ImportError: except ImportError:
gst = None gst = None
finally: finally:
sys.argv= copyargv sys.argv = copyargv
os.dup2(olderr,sys.stderr.fileno()) os.dup2(olderr, sys.stderr.fileno())
if gst is None: if gst is None:
return {} return {}
@ -149,48 +154,55 @@ class VariableClDesktopGstData(ReadonlyVariable):
outdata['device_name'] = alsamixer.get_property("device-name") outdata['device_name'] = alsamixer.get_property("device-name")
outdata['long_name'] = alsamixer.get_factory().get_longname() outdata['long_name'] = alsamixer.get_factory().get_longname()
outdata['internal_name'] = filter(str.isalnum, outdata['internal_name'] = filter(str.isalnum,
"%s (%s)"%(outdata['device_name'], "%s (%s)" % (
outdata['long_name'])) outdata['device_name'],
outdata['long_name']))
outdata['channels'] = [] outdata['channels'] = []
for t in alsamixer.list_tracks(): for t in alsamixer.list_tracks():
if t.flags & gst.interfaces.MIXER_TRACK_OUTPUT: if t.flags & gst.interfaces.MIXER_TRACK_OUTPUT:
if t.flags & gst.interfaces.MIXER_TRACK_MASTER or \ if t.flags & gst.interfaces.MIXER_TRACK_MASTER or \
any(x in t.label any(x in t.label
for x in ("Wave","Front","LFE","Center", for x in ("Wave", "Front", "LFE", "Center",
"Head","Side","Speaker", "Head", "Side", "Speaker",
"Surround","PCM")): "Surround", "PCM")):
outdata['channels'].append(t.label) outdata['channels'].append(t.label)
if t.flags & gst.interfaces.MIXER_TRACK_MASTER: if t.flags & gst.interfaces.MIXER_TRACK_MASTER:
outdata['master_channel'] = t.label outdata['master_channel'] = t.label
except: except Exception:
pass pass
return outdata return outdata
class VariableClDesktopGstCard(ReadonlyVariable): class VariableClDesktopGstCard(ReadonlyVariable):
""" """
Internal card name for xfce mixer Internal card name for xfce mixer
""" """
def get(self): def get(self):
return self.Get('cl_desktop_gst_data').get('internal_name','') return self.Get('cl_desktop_gst_data').get('internal_name', '')
class VariableClDesktopGstMasterchannel(ReadonlyVariable): class VariableClDesktopGstMasterchannel(ReadonlyVariable):
""" """
Master track name Master track name
""" """
def get(self): def get(self):
return self.Get('cl_desktop_gst_data').get('master_channel','') return self.Get('cl_desktop_gst_data').get('master_channel', '')
class VariableClDesktopXfceMixer(ReadonlyVariable): class VariableClDesktopXfceMixer(ReadonlyVariable):
""" """
List of channel for xfce-perchannel mixer List of channel for xfce-perchannel mixer
""" """
def get(self): def get(self):
return "\n".join( return "\n".join(
map(lambda x:' <value type="string" value="%s" />'%x, map(lambda x: ' <value type="string" value="%s" />' % x,
self.Get('cl_desktop_gst_data').get('channels',[]))) self.Get('cl_desktop_gst_data').get('channels', [])))
class VariableClDesktopOnlineData(ReadonlyTableVariable,DomainInfoHelper): class VariableClDesktopOnlineData(ReadonlyTableVariable, DomainInfoHelper):
""" """
Information about online users Information about online users
""" """
@ -202,52 +214,53 @@ class VariableClDesktopOnlineData(ReadonlyTableVariable,DomainInfoHelper):
reDisplay = re.compile(r"^\(?:(\d+\.?\d*)") reDisplay = re.compile(r"^\(?:(\d+\.?\d*)")
def _getDisplay(self,*args): def _getDisplay(self, *args):
""" """
Get DISPLAY from args Get DISPLAY from args
""" """
for arg in map(self.reDisplay.search,args): for arg in map(self.reDisplay.search, args):
if arg: if arg:
return arg.group(1) return arg.group(1)
return "" return ""
def get_user_uid(self,username): def get_user_uid(self, username):
try: try:
return str(pwd.getpwnam(username).pw_uid) return str(pwd.getpwnam(username).pw_uid)
except: except Exception:
return "" return ""
def get(self,hr=False): def get(self, hr=False):
xSession = 0 # TODO: need to KISS rewrite
foundTwoSession = False
resWho = process("who") resWho = process("who")
xData = [[]] xData = [[]]
if resWho.success(): if resWho.success():
listProcessing = lambda x: (x[0], x[1], x[-1]) \ listProcessing = lambda x: (x[0], x[1], x[-1]) \
if len(x)>=5 else [] if len(x) >= 5 else []
xData = groupby( xData = groupby(
sorted( sorted(
filter(lambda x: x[0]!="root", filter(lambda x: x[0] != "root",
map(lambda x: (x[0],self._getDisplay(x[1],x[2])), map(lambda x: (x[0], self._getDisplay(x[1], x[2])),
filter(lambda x: x and\ filter(lambda x: x and \
(x[2].startswith("(:") or \ (x[2].startswith("(:") or
x[1].startswith(":")), x[1].startswith(":")),
map(lambda x: listProcessing(\ map(lambda x: listProcessing(
filter(lambda y: y, x.split())), filter(lambda y: y, x.split())),
resWho)))), resWho)))),
key=lambda x:x[0]), key=lambda x: x[0]),
lambda x:x[0]) lambda x: x[0])
xData = map(lambda x:(x[0][0],x[0][1], xData = map(lambda x: (x[0][0], x[0][1],
self.get_user_uid(x[0][0]), self.get_user_uid(x[0][0]),
"on" if self.isDomainUser(x[0][0]) else "off", "on" if self.isDomainUser(
len(x)), x[0][0]) else "off",
map(lambda x:list(x[1]), len(x)),
xData)) map(lambda x: list(x[1]),
xData))
return xData return xData
setValue = Variable.setValue setValue = Variable.setValue
class VariableClDesktopOnlineUser(FieldValue,ReadonlyVariable):
class VariableClDesktopOnlineUser(FieldValue, ReadonlyVariable):
""" """
Логин пользователя Логин пользователя
""" """
@ -255,7 +268,8 @@ class VariableClDesktopOnlineUser(FieldValue,ReadonlyVariable):
source_variable = "cl_desktop_online_data" source_variable = "cl_desktop_online_data"
column = 0 column = 0
class VariableClDesktopOnlineDisplay(FieldValue,ReadonlyVariable):
class VariableClDesktopOnlineDisplay(FieldValue, ReadonlyVariable):
""" """
Display пользователя Display пользователя
""" """
@ -263,7 +277,8 @@ class VariableClDesktopOnlineDisplay(FieldValue,ReadonlyVariable):
source_variable = "cl_desktop_online_data" source_variable = "cl_desktop_online_data"
column = 1 column = 1
class VariableClDesktopOnlineUid(FieldValue,ReadonlyVariable):
class VariableClDesktopOnlineUid(FieldValue, ReadonlyVariable):
""" """
UID пользователя UID пользователя
""" """
@ -271,7 +286,8 @@ class VariableClDesktopOnlineUid(FieldValue,ReadonlyVariable):
source_variable = "cl_desktop_online_data" source_variable = "cl_desktop_online_data"
column = 2 column = 2
class VariableClDesktopOnlineDomainSet(FieldValue,ReadonlyVariable):
class VariableClDesktopOnlineDomainSet(FieldValue, ReadonlyVariable):
""" """
Является ли пользователь доменным Является ли пользователь доменным
""" """
@ -279,7 +295,8 @@ class VariableClDesktopOnlineDomainSet(FieldValue,ReadonlyVariable):
source_variable = "cl_desktop_online_data" source_variable = "cl_desktop_online_data"
column = 3 column = 3
class VariableClDesktopOnlineCount(FieldValue,ReadonlyVariable):
class VariableClDesktopOnlineCount(FieldValue, ReadonlyVariable):
""" """
Количество сеансов пользователя Количество сеансов пользователя
""" """
@ -287,6 +304,7 @@ class VariableClDesktopOnlineCount(FieldValue,ReadonlyVariable):
source_variable = "cl_desktop_online_data" source_variable = "cl_desktop_online_data"
column = 4 column = 4
class VariableClDesktopLogin(VariableUrLogin): class VariableClDesktopLogin(VariableUrLogin):
""" """
User Login User Login
@ -299,20 +317,21 @@ class VariableClDesktopLogin(VariableUrLogin):
else: else:
return VariableUrLogin.choice(self) return VariableUrLogin.choice(self)
def check(self,value): def check(self, value):
"""Does user exist""" """Does user exist"""
if not value in self.choice() and self.Get('cl_action') == 'logout': if value not in self.choice() and self.Get('cl_action') == 'logout':
raise VariableError(_("No X session user found")) raise VariableError(_("No X session user found"))
if value == "": if value == "":
raise VariableError(_("Please specify the user name")) raise VariableError(_("Please specify the user name"))
try: try:
pwd.getpwnam(value).pw_gid pwd.getpwnam(value).pw_gid
except: except Exception:
raise VariableError(_("User %s does not exist")%value) raise VariableError(_("User %s does not exist") % value)
def get(self): def get(self):
return "" return ""
class VariableUrMountDirs(ReadonlyVariable): class VariableUrMountDirs(ReadonlyVariable):
""" """
Примонтированные директории в профиле пользователя Примонтированные директории в профиле пользователя
@ -324,26 +343,30 @@ class VariableUrMountDirs(ReadonlyVariable):
if not homeDir: if not homeDir:
return [] return []
dirStart, dirEnd = path.split(homeDir) dirStart, dirEnd = path.split(homeDir)
mountProfileDir = path.join(dirStart, ".%s" %dirEnd) mountProfileDir = path.join(dirStart, ".%s" % dirEnd)
mountRemoteProfileDir = path.join(dirStart, ".%s.remote" %dirEnd) mountRemoteProfileDir = path.join(dirStart, ".%s.remote" % dirEnd)
directories = filter(lambda x:x != homeDir, directories = filter(lambda x: x != homeDir,
filter(lambda x: (x.startswith(homeDir) or filter(lambda x: (x.startswith(homeDir) or
x.startswith(mountProfileDir) or x.startswith(mountProfileDir) or
x.startswith(mountRemoteProfileDir)), x.startswith(
map(lambda x: x.split(" ")[1], mountRemoteProfileDir)),
readLinesFile('/proc/mounts')))) map(lambda x: x.split(" ")[1],
#if isMount(homeDir): readLinesFile('/proc/mounts'))))
# if isMount(homeDir):
# directories.append(homeDir) # directories.append(homeDir)
return sorted(directories,reverse=True) return sorted(directories, reverse=True)
class VariableUrPassword(ReadonlyVariable): class VariableUrPassword(ReadonlyVariable):
""" """
Пароль пользователя, получаемый из ключей ядра Пароль пользователя, получаемый из ключей ядра
""" """
def get(self): def get(self):
return getKey(self.Get('ur_login')) or "" return getKey(self.Get('ur_login')) or ""
class VariableClDesktopUpdateProfileSet(Variable): class VariableClDesktopUpdateProfileSet(Variable):
""" """
Нужно ли выполнять обновление профиля пользователя на основании Нужно ли выполнять обновление профиля пользователя на основании
@ -353,19 +376,20 @@ class VariableClDesktopUpdateProfileSet(Variable):
def get(self): def get(self):
lastTimestamp = templateFunction.getLastElog() lastTimestamp = templateFunction.getLastElog()
iniEnv = path.join(self.Get('ur_home_path'),'.calculate/ini.env') iniEnv = path.join(self.Get('ur_home_path'), '.calculate/ini.env')
userIni = iniParser(iniEnv) userIni = iniParser(iniEnv)
userTimestamp = userIni.getVar('main','elog') userTimestamp = userIni.getVar('main', 'elog')
if userTimestamp: if userTimestamp:
userTimestamp = userTimestamp.encode('utf-8') userTimestamp = userTimestamp.encode('utf-8')
profileSetup = userIni.getVar('main','profile_setup') profileSetup = userIni.getVar('main', 'profile_setup')
login_setup = profileSetup == 'on' login_setup = profileSetup == 'on'
if (self.Get('ur_domain_set') == 'on' or login_setup or if (self.Get('ur_domain_set') == 'on' or login_setup or
not path.exists(iniEnv) or userTimestamp != lastTimestamp): not path.exists(iniEnv) or userTimestamp != lastTimestamp):
return 'on' return 'on'
else: else:
return 'off' return 'off'
class VariableClDesktopForceSetupSet(Variable): class VariableClDesktopForceSetupSet(Variable):
""" """
Принудительно выполнить обновление пользовательского профиля Принудительно выполнить обновление пользовательского профиля
@ -379,37 +403,43 @@ class VariableClDesktopForceSetupSet(Variable):
self.label = _("Force configuration") self.label = _("Force configuration")
self.help = _("force configuration") self.help = _("force configuration")
class VariableClDesktopFacePath(Variable): class VariableClDesktopFacePath(Variable):
"""Путь к стандартным иконкам пользователей""" """Путь к стандартным иконкам пользователей"""
value = "/usr/share/pixmaps/faces" value = "/usr/share/pixmaps/faces"
class VariableClDesktopFaceList(Variable): class VariableClDesktopFaceList(Variable):
"""Список доступных иконок по умолчанию для пользователей""" """Список доступных иконок по умолчанию для пользователей"""
type = "list" type = "list"
def get(self): def get(self):
return sorted( return sorted(
filter(lambda x:x.endswith('.png'), filter(lambda x: x.endswith('.png'),
listDirectory(self.Get('cl_desktop_face_path')))) listDirectory(self.Get('cl_desktop_face_path'))))
class VariableClDesktopHashFace(Variable): class VariableClDesktopHashFace(Variable):
"""Номер иконки пользователя """Номер иконки пользователя
Номер вычисляется по контрольной сумму md5 логина пользователя Номер вычисляется по контрольной сумму md5 логина пользователя
""" """
def get(self): def get(self):
login = self.Get('ur_login') login = self.Get('ur_login')
icon_list = self.Get('cl_desktop_face_list') icon_list = self.Get('cl_desktop_face_list')
if icon_list: if icon_list:
return path.join(self.Get('cl_desktop_face_path'), return path.join(self.Get('cl_desktop_face_path'),
icon_list[sum(map(lambda x:ord(x), icon_list[sum(map(lambda x: ord(x),
hashlib.md5(login).digest()))%len(icon_list)]) hashlib.md5(
login).digest())) % len(
icon_list)])
else: else:
return "" return ""
class VariableClDesktopFastloginPath(ReadonlyVariable): class VariableClDesktopFastloginPath(ReadonlyVariable):
""" """
Путь до каталога в котором указаны пользователи быстрого входа в сеанс Путь до каталога в котором указаны пользователи быстрого входа в сеанс
""" """
value = "/var/lib/calculate/calculate-desktop/fastlogin" value = "/var/lib/calculate/calculate-desktop/fastlogin"

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2012-2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2012-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -13,16 +13,18 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import sys, time, os import sys
from calculate.lib.datavars import VariableError,DataVarsError,DataVars from calculate.lib.datavars import VariableError, DataVarsError
from calculate.core.server.func import WsdlBase from calculate.core.server.func import WsdlBase
from desktop import DesktopError from desktop import DesktopError
from utils.cl_desktop import ClDesktopLogoutAction,ClDesktopAction from utils.cl_desktop import ClDesktopLogoutAction, ClDesktopAction
import desktop import desktop
from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
setLocalTranslate('cl_desktop3',sys.modules[__name__])
_ = lambda x: x
setLocalTranslate('cl_desktop3', sys.modules[__name__])
__ = getLazyLocalTranslate(_) __ = getLazyLocalTranslate(_)
@ -32,69 +34,70 @@ class Wsdl(WsdlBase):
# вывести пользователя из сеанса # вывести пользователя из сеанса
# #
{ {
# идентификатор метода # идентификатор метода
'method_name':"desktop_logout", 'method_name': "desktop_logout",
# категория метода # категория метода
'category':__('Desktop'), 'category': __('Desktop'),
# заголовок метода # заголовок метода
'title':__("User Logout"), 'title': __("User Logout"),
# иконка для графической консоли # иконка для графической консоли
'image':'system-log-out', 'image': 'system-log-out',
# метод присутствует в графической консоли # метод присутствует в графической консоли
'gui':True, 'gui': True,
# консольная команда # консольная команда
'command':'cl-desktop-logout', 'command': 'cl-desktop-logout',
# права для запуска метода # права для запуска метода
'rights':['userconfigure'], 'rights': ['userconfigure'],
# объект содержащий модули для действия # объект содержащий модули для действия
'logic':{'Desktop':desktop.Desktop}, 'logic': {'Desktop': desktop.Desktop},
# описание действия # описание действия
'action':ClDesktopLogoutAction, 'action': ClDesktopLogoutAction,
# объект переменных # объект переменных
'datavars':"desktop", 'datavars': "desktop",
'native_error':(VariableError,DataVarsError, 'native_error': (VariableError, DataVarsError,
DesktopError), DesktopError),
# значения по умолчанию для переменных этого метода # значения по умолчанию для переменных этого метода
'setvars':{'cl_action!':'logout'}, 'setvars': {'cl_action!': 'logout'},
# описание груп (список лямбда функций) # описание груп (список лямбда функций)
'groups':[ 'groups': [
lambda group:group(_("User logout"), lambda group: group(_("User logout"),
normal=('cl_desktop_login',), normal=('cl_desktop_login',),
next_label=_("Execute"))]}, next_label=_("Execute"))]},
# #
# настроить пользовательский сеанс # настроить пользовательский сеанс
# #
{ {
# идентификатор метода # идентификатор метода
'method_name':"desktop", 'method_name': "desktop",
# категория метода # категория метода
'category':__('Desktop'), 'category': __('Desktop'),
# заголовок метода # заголовок метода
'title':__("User Account Configuration"), 'title': __("User Account Configuration"),
# иконка для графической консоли # иконка для графической консоли
'image':'user-desktop,preferences-desktop', 'image': 'user-desktop,preferences-desktop',
# метод присутствует в графической консоли # метод присутствует в графической консоли
'gui':True, 'gui': True,
# консольная команда # консольная команда
'command':'cl-desktop', 'command': 'cl-desktop',
# права для запуска метода # права для запуска метода
'rights':['userconfigure'], 'rights': ['userconfigure'],
# объект содержащий модули для действия # объект содержащий модули для действия
'logic':{'Desktop':desktop.Desktop}, 'logic': {'Desktop': desktop.Desktop},
# описание действия # описание действия
'action':ClDesktopAction, 'action': ClDesktopAction,
# объект переменных # объект переменных
'datavars':"desktop", 'datavars': "desktop",
'native_error':(VariableError,DataVarsError, 'native_error': (VariableError, DataVarsError,
DesktopError), DesktopError),
# значения по умолчанию для переменных этого метода # значения по умолчанию для переменных этого метода
'setvars':{'cl_action!':'desktop', 'setvars': {'cl_action!': 'desktop',
'cl_protect_use_set!':'off'}, 'cl_protect_use_set!': 'off'},
# описание груп (список лямбда функций) # описание груп (список лямбда функций)
'groups':[ 'groups': [
lambda group:group(_("User account configuration"), lambda group: group(_("User account configuration"),
normal=('ur_login',), normal=('ur_login',),
expert=('cl_desktop_force_setup_set','cl_verbose_set', expert=('cl_desktop_force_setup_set',
'cl_templates_locate'), 'cl_verbose_set',
next_label=_("Execute"))]}, 'cl_templates_locate'),
] next_label=_("Execute"))]},
]

Loading…
Cancel
Save