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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#-*- 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.
__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):
"""Хранение переменных"""
def importDesktop(self, **args):
'''Импорт переменных для десктопа'''
# Имя секции в calculate2.env
envSection = "desktop"
# импорт переменных
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()
# Импортируем переменные
clVars.importDesktop()
# Заменяем значения переменных переменными из env файлов
clVars.flIniFile()
# Устанавливаем у объекта атрибут объект переменных
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
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):
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
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"))
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
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