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-desktop/pym/cl_desktop.py

328 lines
13 KiB

#-*- coding: utf-8 -*-
# Copyright 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.
13 years ago
__version__ = "2.2.24"
__app__ = "calculate-desktop"
import os
import re
import sys
import pwd
import time
from cl_lang import lang
from cl_template import template
from cl_datavars import DataVars
from cl_print import color_print
from client.progressbar import ProgressBar
from cl_utils import runOsCommand, getpathenv, appendProgramToEnvFile,\
removeProgramToEnvFile
lang().setLanguage(sys.modules[__name__])
class DataVarsDesktop(DataVars):
"""Хранение переменных"""
14 years ago
def importDesktop(self, **args):
'''Импорт переменных для десктопа'''
# Имя секции в calculate2.env
envSection = "desktop"
14 years ago
# импорт переменных
self.importData(envSection, ('cl_vars_desktop','cl_fill_desktop'))
class ProgressTemplate(template):
def __init__(self, vars):
template.__init__(self, vars)
self.progress = ProgressBar(_("Setting up user profile") + " ...")
def numberAllTemplates(self, number):
self.progress.setMaximum(number)
return True
def numberProcessTemplates(self,number):
self.progress.setValue(number)
return True
def close(self):
self.progress.shutdownDialog()
class share(color_print):
"""Общие методы"""
# Объект хранения переменных
clVars = False
def isRoot(self, printError=True):
"""Определяет является ли пользователь root"""
if os.getuid() == 0 and os.getgid() == 0:
return True
else:
if printError:
self.printERROR(_("The user is not root"))
return False
def createClVars(self, clVars=False):
"""Создает объект Vars"""
if not clVars:
clVars = DataVarsDesktop()
14 years ago
# Импортируем переменные
clVars.importDesktop()
# Заменяем значения переменных переменными из env файлов
clVars.flIniFile()
14 years ago
# Устанавливаем у объекта атрибут объект переменных
self.clVars = clVars
return True
def applyTemplatesFromSystem(self):
"""Применяем шаблоны для cистемы"""
# Cоздаем объект обработки шаблонов
clTempl = template(self.clVars)
# Объединяем шаблоны
dirsFiles = clTempl.applyTemplates()
if clTempl.getError():
self.printERROR(clTempl.getError().strip())
return False
else:
return dirsFiles
def printVars(self, *arg, **argv):
"""Печать существующих переменных"""
self.clVars.printVars(*arg, **argv)
class desktop(share):
"""Методы работы с профилем пользователя"""
# Имя пользователя
userName = ""
verbose = False
def installProg(self):
"""Наложение шаблонов на систему при инсталяции"""
# Проверяем на root
if not self.isRoot():
return False
14 years ago
self.clVars.AppendToList("cl_merges", __app__, force=True)
# Действие инсталяция
self.clVars.Set("cl_action", "install", True)
if not self.applyTemplatesFromSystem():
self.printERROR(_("Can not apply install templates"))
return False
# Добавление программы в инсталяционную переменную
if not appendProgramToEnvFile(__app__, self.clVars):
self.printERROR(_("Can not save '%s'") %__app__ + " " +\
_("to %s") %self.clVars.Get("cl_env_path")[0])
return False
self.printOK(_("Apply install templates"))
return True
def uninstallProg(self):
"""Наложение шаблонов на систему при деинсталяции"""
# Проверяем на root
if not self.isRoot():
return False
# Действие деинсталяция
self.clVars.Set("cl_action", "uninstall", True)
if not self.applyTemplatesFromSystem():
self.printERROR(_("Can not apply uninstall templates"))
return False
# Удаление программы из инсталяционной переменной
if not removeProgramToEnvFile(__app__, self.clVars):
14 years ago
self.printERROR(_("Can not remove '%(app)s' to %(path)s")%
{'app':__app__,
'path': self.clVars.Get("cl_env_path")[0]})
return False
self.printOK(_("Apply uninstall templates"))
return True
def existsUser(self, userName):
"""Существует ли пользователь"""
try:
pwd.getpwnam(userName).pw_gid
except:
self.printERROR(_("User %s not exists")%userName)
return False
return True
def createUserDir(self, uid, gid, userDir, mode=0700):
"""Создание пользовательской директории"""
if not os.path.exists(userDir):
os.makedirs(userDir)
if mode:
os.chmod(userDir,mode)
os.chown(userDir,uid,gid)
return True
else:
self.printERROR(_("Path %s exists") %userDir)
return False
def displayTemplatesApplied(self,dirsFiles):
"""
Display templates are applied (--verbose)
"""
self.printWARNING(_("Following files were changed")+":")
for nameF in dirsFiles[1]:
nameFile = nameF
if nameFile[:1] != "/":
nameFile = "/" + nameFile
self.printWARNING(" "*5 + nameFile)
def applyTemplatesFromUser(self, progress=False):
"""Применяем шаблоны для пользователя"""
# Cоздаем объект обработки шаблонов
if progress:
clTempl = ProgressTemplate(self.clVars)
else:
clTempl = template(self.clVars,cltObj=False)
# Объединяем шаблоны
dirsFiles = clTempl.applyTemplates()
if progress:
clTempl.close()
if clTempl.getError():
self.printERROR(clTempl.getError().strip())
return False
else:
if self.verbose:
self.displayTemplatesApplied(dirsFiles)
return dirsFiles
def createHome(self, progress=False, verbose=False):
"""Создание профиля пользователя (пользовательской директории)"""
# Имя пользователя
self.verbose = verbose
uid = os.getuid()
try:
realUserName = pwd.getpwuid(uid).pw_name
except:
realUserName = ""
userName = self.clVars.Get("ur_login")
if userName != realUserName and not self.isRoot():
return False
uidGid = False
# Домен для подключения Samba
14 years ago
domain = self.clVars.GetIniVar("client.cl_remote_host")
# Авторизация в домененe или локально
hostAuth = self.clVars.GetIniVar("client.os_remote_auth")
try:
passwdUsers = map(lambda x: x[0],
map(lambda x: x.split(':'),
map(lambda x: x.strip(),
open("/etc/passwd").readlines())))
except:
self.printERROR("Can not open /etc/passwd")
return False
try:
pwdInfo = pwd.getpwnam(userName)
except:
self.printERROR(_("Can not found user %s") %userName)
self.umountUserRes()
return False
uid = pwdInfo.pw_uid
gid = pwdInfo.pw_gid
homeDir = pwdInfo.pw_dir
# Создаем пользовательскую директорию
rootPath = self.clVars.Get('cl_root_path')
# Реальный путь к домашней директории
homeDir = os.path.join(rootPath, homeDir[1:])
# Домашняя директория существует
flagHomeExists = True
# Создаем домашнюю директорию если ее нет
if not os.path.exists(homeDir):
flagHomeExists = False
self.createUserDir(uid, gid, homeDir)
# Действие - шаблоны пользователя
self.clVars.Set("cl_action", "desktop", True)
# Применяем профили для пользователя
dirsAndFiles = self.applyTemplatesFromUser(progress)
if not dirsAndFiles:
# Отмонтируем пользовательские ресурсы в случае ошибки
self.printERROR(_("Can not apply user profile"))
14 years ago
self.umountUserRes(homeDir)
return False
if not flagHomeExists:
self.printSUCCESS(_("Created home dir %s")%homeDir + " ...")
self.printSUCCESS(_("User account %s is configured")%userName + " ...")
return True
def getMountUserPaths(self, homeDir=False):
"""Находит пользовательские примонтированные пути"""
# Имя пользователя
if not homeDir:
userName = self.clVars.Get("ur_login")
try:
homeDir = pwd.getpwnam(userName).pw_dir
except:
homeDir = os.path.join("/home",userName)
dirStart, dirEnd = os.path.split(homeDir)
mountProfileDir = os.path.join(dirStart, ".%s" %dirEnd)
mountRemoteProfileDir = os.path.join(dirStart, ".%s.remote" %dirEnd)
return filter(lambda x: x.startswith(homeDir) or\
x.startswith(mountProfileDir) or\
x.startswith(mountRemoteProfileDir),
map(lambda x: x.split(" ")[1],\
open("/proc/mounts").readlines()))
def execProg(self, cmdStrProg, inStr=False, envProg={}):
"""Выполняет внешнюю программу
Параметры:
cmdStrProg внешняя программа
inStr данные передаваемые программе на страндартный вход.
Возвращаемые параметры:
строки которые выведет внешняя программа или False в случае ошибки
"""
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, path):
"""Отмонтирует путь при неудаче задержка потом повтор"""
# Задержки при отмонтированиии директории
sleeps = [0.5, 2, 5]
# Проверяем на монтирование директорию
if os.path.ismount(path):
textLine = self.execProg("umount %s"%path)
if textLine is False:
i = 0
flagError = False
while (i<len(sleeps) and textLine is False):
# Задержка перед следующей попыткой
time.sleep(sleeps[i])
# Отмонтируем Samba ресурс
if os.path.ismount(path):
textLine = self.execProg("umount %s"%path)
else:
textLine = True
break
i += 1
if textLine is False:
self.printERROR(_("Can not unmount path %s")%path + " ...")
return False
return True
14 years ago
def umountUserRes(self, homeDir=False):
"""Отмонтируем пользовательские директории если они есть"""
umountPaths = self.getMountUserPaths(homeDir)
ret = True
for umountPath in umountPaths:
if not self.umountSleepPath(umountPath):
ret = False
break
return ret