#-*- 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