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-client/pym/cl_client.py

2331 lines
108 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.
14 years ago
__version__ = "2.2.9"
__app__ = "calculate-client"
import os
14 years ago
import stat
import re
import sys
import pwd
import subprocess
import ldap
import time
import types
import getpass
from cl_lang import lang
from cl_template import template, iniParser
from cl_datavars import DataVars
from cl_print import color_print
from cl_ldap import ldapUser
from client.progressbar import ProgressBar
from cl_utils import runOsCommand, getpathenv, getModeFile, removeDir, isMount,\
14 years ago
appendProgramToEnvFile, removeProgramToEnvFile, pathJoin
from _cl_keys import getKey, clearKey
from convertenv import convertEnv
from encrypt import encrypt
from cl_client_cache import userCache
from shutil import copy2
lang().setLanguage(sys.modules[__name__])
class DataVarsClient(DataVars):
"""Хранение переменных"""
14 years ago
def importClient(self, **args):
'''Импорт переменных для клиента'''
# Имя секции в calculate2.env
envSection = "client"
14 years ago
# импорт переменных
self.importData(envSection, ('cl_vars_client','cl_fill_client'))
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 = DataVarsClient()
14 years ago
# Импортируем переменные
clVars.importClient()
# Заменяем значения переменных переменными из 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 RsyncProgressBar:
'''Объект запуска rsync для получения количества созданных файлов и
при необходимости вывода progressbar
'''
# получение номера передаваемого файла из инф потока rsync
senderre = re.compile("\[sender\] i=(\d+) ", re.S)
# получение номера получаемого файла из потока rsync
receiverre = re.compile("recv_generator\(.+,([0-9]+)\)", re.S)
pipe = None
maximum = 1
copyStarting = False
def __init__(self, title, secondtitle, rsyncstr, maximum=1):
self.title = title
self.secondtitle = secondtitle
self.maximum = maximum
self.rsyncstr = rsyncstr
self.progress = ProgressBar(title,1)
self.progress.setMaximum(self.maximum)
def getFilesNum(self):
'''Получить количество файлов созданных генератором'''
if self.pipe:
return self.value
def getExitCode(self):
'''Получить код выхода rsync'''
if self.pipe:
return self.pipe.wait()
return 255
def getErrMessage(self):
'''Сообщение ошибки rsync при синхронизации'''
if self.pipe:
return self.pipe.stderr.read()
return _("RsyncProgressBar: Wrong pipe")
def runsilent(self):
'''Запустить rsync без progressbar'''
self.pipe = subprocess.Popen(self.rsyncstr, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True, shell=True)
while True:
s = self.pipe.stdout.readline()
if len(s) == 0:
break
q = self.receiverre.search(s)
if q:
self.value = int(q.groups()[0])
def run(self):
'''Запустить rsync с progressbar'''
self.progress.openDialog(self.title,0)
self.pipe = subprocess.Popen(self.rsyncstr, stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True, shell=True)
oldpercent = 0
while True:
s = self.pipe.stdout.readline()
if len(s) == 0:
break
q = self.receiverre.search(s)
if q:
if not self.copyStarting:
self.progress.shutdownDialog()
self.progress.openDialog(self.secondtitle)
self.progress.setMaximum(self.maximum)
self.copyStarting = True
value = int(q.groups()[0])
self.progress.setValue(value)
def close(self):
self.progress.shutdownDialog()
class ldapData(ldapUser):
"""Методы для LDAP"""
def addDN(self, *arg):
"""Складывает текстовые элементы DN"""
DNs = []
for dn in arg:
if dn:
DNs.append(dn)
return ','.join(DNs)
def getReplDN(self):
"""Получаем DN ветки хранения последнего посещенного сервера
В ветке находятся ((имя пользователя, имя системы, хост) ....)
"""
usersDN = self.getUsersDN()
if usersDN:
partDN = "ou=Worked,ou=Replication,ou=LDAP"
servicesDN = "ou=Services"
baseDN = usersDN.rpartition(servicesDN+",")[2]
replDN = self.addDN(partDN, servicesDN, baseDN)
return replDN
return False
def searchPrevHost(self, userName, osLinuxShort):
"""Находит сервер к которому был подключен пользователь"""
connectData = self.getBindConnectData()
if connectData:
bindDn, bindPw, host = connectData
replDN = self.getReplDN()
# cтрока для поиска в служебной ветке репликации
userAndOsName = "%s@%s"%(userName,osLinuxShort)
findAttr = "uid=%s"%userAndOsName
# Соединяемся с LDAP
if not self.ldapConnect(bindDn, bindPw, host):
return False
resSearch = self.ldapObj.ldapSearch(replDN, ldap.SCOPE_ONELEVEL,
findAttr, ["host"])
return resSearch
return False
14 years ago
def getNameRemoteServer(self,userName, osLinuxShort, curHost):
"""Если профиль на удаленном сервере, то выдать DNS имя этого сервера
"""
searchPrevHost = self.searchPrevHost(userName, osLinuxShort)
if searchPrevHost and searchPrevHost[0][0][1].has_key('host'):
prevHost = searchPrevHost[0][0][1]['host'][0]
else:
prevHost = None
# если местоположение актуального профиля найти не удалось
# или его местоположение не на локальном сервере
14 years ago
if not prevHost or prevHost == curHost:
return False
else:
return prevHost
def isRepl(self):
"""Включена ли репликация на сервере"""
connectData = self.getBindConnectData()
if connectData:
bindDn, bindPw, host = connectData
usersDN = self.getUsersDN()
partDN = "ou=Replication,ou=LDAP"
servicesDN = "ou=Services"
baseDN = usersDN.rpartition(servicesDN+",")[2]
replDN = self.addDN(partDN, servicesDN, baseDN)
findAttr = "ou=Worked"
# Соединяемся с LDAP
if not self.ldapConnect(bindDn, bindPw, host):
return False
resSearch = self.ldapObj.ldapSearch(replDN, ldap.SCOPE_ONELEVEL,
findAttr,
[findAttr.partition("=")[0]])
if resSearch:
return True
return False
class commandServer(color_print):
"""Отправка команд на сервер (изменение пароля пользователя на сервере)"""
def setServerCommand(self, command, varsCommand, fileConfig,
uid=None, gid=None):
"""Установить команду для сервера"""
pathConfig = os.path.split(fileConfig)[0]
# Создаем директорию если ее нет
if not os.path.exists(pathConfig):
os.makedirs(pathConfig)
if not uid is None and not gid is None:
os.chown(pathConfig, uid, gid)
objConfig = iniParser(fileConfig)
varsRun = {"run":"on"}
varsRun.update(varsCommand)
if not objConfig.setVar(["command"]+command, varsRun):
self.printERROR(_("Can not write variables in file %s")\
%fileConfig)
return False
if not uid is None and not gid is None:
os.chown(fileConfig, uid, gid)
return True
def checkUserPwdLDAP(self, server, userDN, password):
"""Проверка пароля Unix пользователя на сервере"""
ldapInit = ldap.initialize("ldap://%s"%server)
errMessage = ""
try:
ldapInit.bind_s(userDN, password)
except ldap.INVALID_CREDENTIALS:
errMessage = _("Password incorrect")
return False, errMessage
except ldap.LDAPError, e:
errMessage = e[0]['desc']
return False, errMessage
return True, errMessage
def getUserPwd(self, options, optDialog, optStdIn, pwDialog=False):
"""Получить пароль у пользователя
options - полученные опции командной строки
optDialog - опция командной строки для вывода диалога для получения
пароля
optStdIn - опция командной строки для получения пароля из
стандартного ввода (stdin)
pwDialog - структура для вывода приглашения в режиме диалога
"""
userPwd = ""
if optStdIn and options.has_key(optStdIn):
pwdA = sys.stdin.readline().rstrip()
pwdB = sys.stdin.readline().rstrip()
elif optDialog and options.has_key(optDialog):
if not pwDialog:
pwDialog = [_("New password"),
_("Retype new password")]
pwdA = getpass.getpass(pwDialog[0]+":")
pwdB = getpass.getpass(pwDialog[1]+":")
if (optStdIn and options.has_key(optStdIn)) or\
(optDialog and options.has_key(optDialog)):
if not pwdA or not (pwdA == pwdB):
self.printERROR (_("ERROR") + ": " +\
_("passwords do not match"))
return False
userPwd = pwdA
return userPwd
class client(share, commandServer, encrypt):
"""Методы работы для подключения пользователя к серверу и синхронизации"""
# Объект для поиска пользовательских данных в LDAP
ldapDataObj = ldapData()
# Путь относительно домашней директории в котором находятся
# конфигурационные файлы
pathConfig = ".calculate"
# Конфигурационный файл для клиента
configFileDesktop = os.path.join(pathConfig, "desktop.env")
# Конфигурационный файл для сервера
configFileServer = os.path.join(pathConfig, "server.env")
# Файл - список файлов профиля пользователя
listTemplFile = os.path.join(pathConfig, "files.txt")
logOutFile = ".logout"
# Файлы котороые не удаляются при очистке домашней директории
skipHomeFile = ["Home","Disks","Share","FTP",logOutFile,configFileDesktop]
14 years ago
# словарь опций сервисов из /var/calculate/remote/server.env
optionsInfo = {}
# объект конвертирования из старого remote env файла
convObj = None
# Приватный файлы пользователя
privateFiles = ['.kde4/share/apps/kwallet/kdewallet.kwl', configFileServer]
# Приватные директории пользователя
privateDirs = [".ssh"]
def removeVars(self):
"""Удаление переменных шаблонов
при удалении пакета и выходе из домена"""
self.clVars.Delete("cl_remote_host", "local")
self.clVars.Delete("cl_remote_pw", "local")
self.clVars.Delete("os_remote_auth")
self.clVars.Delete("os_remote_client")
self.clVars.Set("cl_remote_host", "", True)
self.clVars.Set("cl_remote_pw", "", True)
self.clVars.Set("os_remote_auth", "", True)
self.clVars.Set("os_remote_client", "", True)
def isTwoSessionsUser(self, userName):
"""Проверка на повторный вход пользователя"""
xSession = 0
foundTwoSession = False
reFoundUser = re.compile("%s\s+:\d+\s+"%(userName))
resWho = self.execProg("who")
if resWho:
for string in resWho:
if reFoundUser.search(string):
xSession +=1
if xSession>1:
foundTwoSession = True
self.printERROR(\
_("Second X session for user %s can not be opened.")\
%userName)
break
return foundTwoSession
def isDomain(self):
"""Находится ли компьютер в домене"""
14 years ago
foundMountRemote = isMount("/var/calculate/remote")
remoteHost = self.clVars.Get("cl_remote_host")
if remoteHost and foundMountRemote:
return True
self.printERROR(_("The computer is not in domain"))
return False
def getUserMountResources(self, userName, homeDir, flagRemoteServer):
"""Получение монтируемых ресурсов для пользователя"""
home = os.path.split(homeDir)[0]
dictResources = {}
names = []
# Pесурс share
name = "share"
dictResources[name] = {"resource":"share",
"path":os.path.join(homeDir,"Share")}
names.append(name)
# Ресурс шаблонов
name = "profile"
dictResources[name] = {"resource":"unix",
"path":os.path.join(home,"."+userName)}
names.append(name)
# Ресурс - домашняя директория (файлы пользователя на сервере)
name = "home"
dictResources[name] = {"resource":"homes",
"path":os.path.join(homeDir,"Home")}
names.append(name)
if self.getInfoService("ftp", "host"):
# Ресурс ftp
name = "ftp"
dictResources[name] = {"resource":"ftp",
"path":os.path.join(homeDir,"FTP")}
names.append(name)
if flagRemoteServer:
# Ресурс шаблонов на удаленном сервере
name = "remote_profile"
dictResources[name] = {"resource":"unix",
"path":os.path.join(home,"."+userName+"."+"remote")}
names.append(name)
return names, dictResources
def mountSambaRes(self,host,userName,userPwd,uid,gid,res,path,
mountUidList=['ftp','home','share']):
"""Монтирует Samba ресурсы"""
if res in mountUidList:
# Монтируем директории c uid
mountStr = "mount -t cifs -o user=%s,uid=%s,gid=%s,noperm"\
%(userName,uid,gid) +\
" //%s/%s %s" %(host, res, path)
else:
# Монтируем директории
mountStr = "mount -t cifs -o user=%s"%(userName)+\
" //%s/%s %s" %(host, res, path)
textLine = self.execProg(mountStr, envProg={"PASSWD":userPwd})
return textLine
def mountSleepRes(self,host,userName,userPwd,uid,gid,res,path):
"""Монтирует ресурс при неудаче задержка потом повторное монитрование"""
textLine = self.mountSambaRes(host,userName,userPwd,uid,gid,res,path)
if textLine is False:
# Проверяем на монтирование директории
14 years ago
if isMount(path):
textLineUmount = self.umountSleepPath(path)
if not textLineUmount:
return False
i = 0
sleeps = [0.5, 2, 5]
while (i<len(sleeps) and textLine is False):
# Задержка перед следующей попыткой
time.sleep(sleeps[i])
# Монтируем Samba ресурс
textLine = self.mountSambaRes(host,userName,userPwd,uid,
gid,res,path)
if textLine is False:
# Проверяем на монтирование директории
14 years ago
if isMount(path):
textLineUmount = self.umountSleepPath(path)
if not textLineUmount:
return False
i += 1
return textLine
def copyTemplateDir(self, srcDir, destDir):
"""Перенос директории srcDir в директорию destDir
При копировании сохраняются владелец, группа, права
"""
if os.system("mv %s %s &>/dev/null"%(srcDir, destDir)) != 0:
self.printERROR(_("Can not move %s")%srcDir + " " +\
_("to %s")%destDir)
return False
return True
def upgradeTemplateClient(self, userName, userHome, pathTemplates):
"""Переносит данные клиента в директорию без точки
например: было /home/.user/.CLD стало /home/.user/CLD
Перед вызовом этого метода обязательно должен быть определен атрибут
объекта self.clVars - объект переменных
"""
# Директория хранения старых шаблонов
home = os.path.split(userHome)[0]
if os.path.exists(pathTemplates):
if self.clVars.Get("cl_profile_all_set") == "on":
osLinuxShort = "all"
else:
osLinuxShort = self.clVars.Get("os_linux_shortname")
pathNewTemplate = os.path.join(pathTemplates, osLinuxShort)
pathOldTemplate = os.path.join(pathTemplates, "."+osLinuxShort)
if not os.path.exists(pathNewTemplate) and\
os.path.exists(pathOldTemplate) and\
os.listdir(pathOldTemplate):
# Переносим профиль
if not self.copyTemplateDir(pathOldTemplate,
pathNewTemplate):
return False
if not os.path.exists(pathNewTemplate):
# Создаем директорию для хранения профиля
os.mkdir(pathNewTemplate)
os.chmod(pathNewTemplate, 0700)
if os.path.exists(pathOldTemplate) and\
not os.listdir(pathOldTemplate):
os.rmdir(pathOldTemplate)
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 syncUser(self, userName, userHome, sync, uid, gid, homeTemplate, \
progress=False, host="default"):
"""Синхронизация пользовательских настроек
Перед вызовом этого метода обязательно должен быть определен атрибут
объекта self.clVars - объект переменных
"""
flagError = False
execStr = ""
skipPaths = self.clVars.Get("cl_sync_skip_path")
if not skipPaths:
self.printERROR(_("Variable 'cl_sync_skip_path' is empty")%userHome)
return False
deletePaths = self.clVars.Get("cl_sync_del_path")
if not deletePaths:
deletePaths = []
excludePaths = " ".join(map(lambda x: '--exclude="/%s"'\
%x.replace('"',"").replace("'",""),
skipPaths + deletePaths))
if sync == "login":
if os.path.exists(userHome) and\
os.path.exists(homeTemplate):
filterPath = " ".join(map(lambda x: '--filter="P /%s"'\
%x.replace('"',"").replace("'",""),
skipPaths))
execStr = '/usr/bin/rsync --delete-excluded --delete %s %s \
14 years ago
-rlptgo -x -v -v -v %s/ %s/' %(excludePaths, filterPath, homeTemplate, userHome)
elif sync == "logout":
if os.path.exists(userHome) and os.listdir(userHome) and\
os.path.exists(homeTemplate):
execStr = '/usr/bin/rsync --delete-excluded --delete %s \
14 years ago
-rlptgo -x -v -v -v %s/ %s/'%(excludePaths, userHome, homeTemplate)
else:
self.printERROR(_("Method syncUser: option sync=%s incorrect")\
%str(sync))
return False
if execStr:
host = "<i>" + host +"</i>"
rsync = RsyncProgressBar(\
_("Receiving file list from %s") % host + " ...",
_("Downloading the user profile from %s") % host +\
" ...", execStr)
pathConfig = os.path.join(homeTemplate,
self.pathConfig)
# Удаляем предыдущий ini файл
prevIniFile = os.path.join(homeTemplate,".calculate.ini")
if os.path.exists(prevIniFile):
os.remove(prevIniFile)
# Создаем директорию для конфигурационных файлов
if not os.path.exists(pathConfig):
self.createUserDir(uid, gid, pathConfig, mode=False)
14 years ago
configFileName = os.path.join(homeTemplate, self.configFileDesktop)
if sync == "login":
# получить переменную files из секции Rsync файла
# .calculate.ini
try:
numfiles = iniParser(\
configFileName).getVar('rsync','files')
if numfiles is False:
if os.path.exists(configFileName):
os.remove(configFileName)
numfiles = 0
else:
numfiles = int(numfiles)
except:
numfiles = 0
rsync.maximum = numfiles
if progress:
rsync.run()
else:
rsync.runsilent()
if sync == "logout":
rsync.runsilent()
try:
if iniParser(configFileName).setVar('rsync',
{'files':rsync.getFilesNum()}):
os.chmod(configFileName, 0600)
os.chown(configFileName,uid,gid)
except:
pass
rsync.close()
if rsync.getExitCode() != 0:
try:
if iniParser(configFileName).setVar(\
'rsync',{'exitcode':rsync.getExitCode()}):
os.chmod(configFileName, 0600)
os.chown(configFileName,uid,gid)
except:
pass
self.printERROR(rsync.getErrMessage())
self.printERROR(_("Can not execute rsync") + " " + str(sync) +\
" ...")
flagError = True
else:
if sync == "login":
if not (os.path.exists(userHome)):
self.printERROR(_("Directory %s not exists")%userHome)
else:
self.printERROR(_("Directory %s not exists")%homeTemplate)
elif sync == "logout":
if not (os.path.exists(userHome)):
self.printERROR(_("Directory %s is empty or not exists")\
%userHome)
else:
self.printERROR(_("Directory %s not exists")%homeTemplate)
flagError = True
if flagError:
return False
else:
# Домашняя директория и директория хранения профиля
changeDirs = [userHome, homeTemplate]
for changeDir in changeDirs:
# Получаем права на директорию
mode = getModeFile(changeDir, mode="mode")
# Если права не равны 0700 меняем их
if mode != 0700:
os.chmod(changeDir,0700)
return True
def clearHomeDir(self, homeDir):
"""Очистка домашней директории от файлов"""
rmFiles = list(set(os.listdir(homeDir))-\
set(self.skipHomeFile))
for rmFile in rmFiles:
delFile = os.path.join(homeDir,rmFile)
if os.path.islink(delFile):
os.unlink(delFile)
elif os.path.isfile(delFile):
os.remove(delFile)
elif os.path.isdir(delFile):
if not removeDir(delFile):
return False
elif stat.S_ISSOCK(os.stat(delFile)[stat.ST_MODE]):
os.remove(delFile)
return True
def syncLoginTemplate(self, host, userName, homeDir, homeTemplate, uid, gid,
progress, flagClearHomeDir=True):
"""Синхронизация профиля пользователя с сервера
в переменной 'cl_remote_host' хост для прогрессбара
"""
home = os.path.split(homeDir)[0]
# Если на текущем сервере в ресурсе unix есть файлы
# то синхронируем настройки
if filter(lambda x: not x in ('.calculate',), os.listdir(homeTemplate)):
if not self.syncUser(userName, homeDir, "login", uid, gid,\
homeTemplate, progress=progress,
host=host):
return False
else:
if flagClearHomeDir:
# Удаляем ненужные файлы (очищаем домашнюю директорию)
if not self.clearHomeDir(homeDir):
return False
return True
def getDataInConfig(self, section, listVars, objConfig):
"""Читаем переменные listVars из секции section конф. файла"""
varsConfig = {}
for varName in listVars:
varsConfig[varName] = objConfig.getVar(section,varName)
if objConfig.getError():
return False
return varsConfig
def foundArchFile(self,strCurrentTime,archPathProcess,
archPathSuccess, progress=False,
remoteServer=False):
"""Поиск архива профиля пользователя"""
# Ищем архив профиля
# Задержки при поиске файла архива .process
if progress:
title = _("Packing the archive at the server")
if remoteServer:
title += " " + remoteServer
title += " ..."
progressObj = ProgressBar(title, 0)
progressObj.openDialog(title, 0)
sleepsFindProcess = [0.1, 0.2, 0.5]
# Задержки при проверке размера архива
sleepsArch = [0.5, 1, 2]
lenFP = len(sleepsFindProcess)
lenA = len(sleepsArch)
i = 0
# Ждем появления файла архива
while(not (os.path.exists(archPathProcess) or\
os.path.exists(archPathSuccess)) and i<lenFP):
time.sleep(sleepsFindProcess[i])
i +=1
# Если нет архива применяем rsync синхронизацию
if not (os.path.exists(archPathProcess) or\
os.path.exists(archPathSuccess)):
# Архив не найден rsync схема синхронизации
if progress:
progressObj.shutdownDialog()
return False
# Ожидание создания архива
if os.path.exists(archPathProcess):
i = 0
while(os.path.exists(archPathProcess)):
if os.path.exists(archPathSuccess):
break
if i>=lenA:
# rsync схема синхронизации
if progress:
progressObj.shutdownDialog()
return False
startSize = os.stat(archPathProcess).st_size
time.sleep(sleepsArch[i])
if os.path.exists(archPathSuccess):
break
endSize = os.stat(archPathProcess).st_size
if startSize == endSize:
i += 1
if progress:
progressObj.shutdownDialog()
return True
def fileReader(self, fileName, stdin, progressObj=False):
"""Читает файл блоками в поток"""
fd = os.open(fileName, os.O_RDONLY)
if progressObj:
currSize = 0
# Размер файлового буфера в байтах
buffSize=131072
dataBlock = os.read(fd, buffSize)
while dataBlock:
if progressObj:
currSize += len(dataBlock)
progressObj.setValue(currSize)
stdin.write(dataBlock)
dataBlock = os.read(fd, buffSize)
stdin.close()
os.close(fd)
def moveArch(self, srcArchFile, dstArchFile, progress=False,\
14 years ago
remoteServer=False, mode=0600):
"""Перенос архива из одной директории в другую"""
class copyTo(color_print):
def __init__(self, destFile):
self.FD = open(destFile, "w")
14 years ago
os.chmod(destFile, mode)
def write(self, data):
self.FD.write(data)
def close(self):
self.FD.close()
# Создаем прогрессбар
if progress:
title = _("Copying archive from server")
if remoteServer:
title += " " + remoteServer
title += " ..."
progressObj = ProgressBar(title)
archiveSize = os.stat(srcArchFile).st_size
progressObj.setMaximum(archiveSize)
try:
copyToObj = copyTo(dstArchFile)
except:
self.printERROR(_("Can not create file '%s'")%dstArchFile)
return False
# Копирование файла
try:
if progress:
self.fileReader(srcArchFile, copyToObj, progressObj)
else:
self.fileReader(srcArchFile, copyToObj)
except:
self.printERROR(_("Can not copy '%(from)s' -> '%(to)s'")\
%{'from':srcArchFile,
'to':dstArchFile})
return False
if progress:
progressObj.shutdownDialog()
return True
def unpackArch(self, homeDir, archFile, progress=False,\
remoteServer=False):
"""Распаковка архива в домашнюю директорию пользователя"""
# Создаем прогрессбар
if progress:
title = _("Unpacking the archive from server")
if remoteServer:
title += " " + remoteServer
title += " ..."
progressObj = ProgressBar(title)
archiveSize = os.stat(archFile).st_size
progressObj.setMaximum(archiveSize)
execStr = "tar -C '%s' -xzf -" %homeDir
# Выполняем разархивацию
pipe = subprocess.Popen(execStr,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
close_fds=True,
env=os.environ, shell=True)
# Чтение файла в поток
if progress:
self.fileReader(archFile, pipe.stdin, progressObj)
else:
self.fileReader(archFile, pipe.stdin)
ret = pipe.wait()
pipe.stdout.close()
pipe.stderr.close()
if progress:
progressObj.shutdownDialog()
if ret:
self.printERROR(_("Can not execute %s") %execStr)
self.printERROR(_("Can not unpack %s") %archFile)
return False
return True
def setVarToConfig(self, nameSection, varsDict, configFileName, uid, gid):
"""Записывает переменную в файл конфигурации"""
# Создаем директорию для конфигурационных файлов
pathConfig = os.path.split(configFileName)[0]
if not os.path.exists(pathConfig):
self.createUserDir(uid, gid, pathConfig, mode=False)
try:
if iniParser(configFileName).setVar(nameSection, varsDict):
os.chmod(configFileName, 0600)
os.chown(configFileName,uid,gid)
except:
return False
return True
def createUserFile(self, fileName, fileTxt, uid, gid, mode=0644):
"""Создает пользовательский файл с содержимым
Если директория файла не существует то ошибка
"""
userDir = os.path.split(fileName)[0]
if not os.path.exists(userDir):
self.printERROR(_("Path %s not exists") %userDir)
return False
FD = open(fileName, "w")
modeFile, uidFile, gidFile = getModeFile(fileName)
if mode != modeFile:
os.chmod(fileName, mode)
if (uidFile, gidFile) != (uid, gid):
os.chown(fileName,uid,gid)
if fileTxt:
FD.write(fileTxt)
FD.close()
return True
def getDateObjClientConf(self, fileConfig):
"""Возващает объект времени из конфигурационного файла
.calculate/desktop.env"""
if os.path.exists(fileConfig):
objConfig = iniParser(fileConfig)
data = self.getDataInConfig("main", ["date", "date_logout"],
objConfig)
timeLogout = data["date_logout"]
timeConfig = data["date"]
timeLogoutObj = False
if timeLogout:
try:
timeLogoutObj = time.strptime(timeLogout,
"%Y-%m-%d %H:%M:%S")
except:
pass
timeConfigObj = False
if timeConfig:
try:
timeConfigObj = time.strptime(timeConfig,
"%Y-%m-%d %H:%M:%S")
except:
pass
listDataObj = filter(lambda x: x, (timeLogoutObj, timeConfigObj))
if listDataObj:
return max(listDataObj)
return False
def mountUserResAndSync(self, userName, sync=True, progress=False):
"""Монтирование пользовательских ресурсов и синхронизация настроек"""
# Проверяем на root
if not self.isRoot():
return False
# Проверка на повторный вход пользователя
if self.isTwoSessionsUser(userName):
return False
domain = self.clVars.Get("cl_remote_host")
hostAuth = self.clVars.Get("os_remote_auth")
# В случае компьютера вне домена
if not hostAuth or not domain:
self.printSUCCESS(_("To be used local profile"))
return True
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
if userName in passwdUsers:
try:
pwdObj = pwd.getpwnam(userName)
except:
self.printERROR(_("Can not found user %s")%userName)
self.umountUserRes()
return False
self.printWARNING(_("We use user information from /etc/passwd"))
return True
# Проверим что компьютер в домене и смонтирован [remote]
connectDomain = self.isDomain()
if not connectDomain:
# Отмонтируем пользовательские ресурсы в случае ошибки
self.umountUserRes()
return False
# Информация о пользователе из LDAP
userLdapInfo = self.ldapDataObj.getUserLdapInfo(userName)
if userLdapInfo:
uid = int(userLdapInfo['uid'])
gid = int(userLdapInfo['gid'])
homeDir = userLdapInfo['home']
else:
self.printERROR(_("Can not found user %s in LDAP") %userName)
self.umountUserRes()
return False
# Файл хранения настроек пакета
configFileName = os.path.join(homeDir, self.configFileDesktop)
# объект времени для текущего профиля
currentTimeObj = self.getDateObjClientConf(configFileName)
# При отсуствии создаем домашнюю директорию
if not os.path.exists(homeDir):
os.makedirs(homeDir)
os.chown(homeDir,uid,gid)
os.chmod(homeDir,0700)
# записываем в конфигурационный файл статус "в процессе"
self.setVarToConfig("main", {"status_sync":"process"},
configFileName, uid, gid)
# Получаем пароль пользователя из ключей ядра
userPwd = getKey(userName)
if not userPwd:
self.printERROR(_("Not found user password"))
# Отмонтируем пользовательские ресурсы в случае ошибки
self.umountUserRes(homeDir)
return False
# Кеширование пользователя
if not self.cAddUserToCache(userName, userPwd):
return False
# Флаг ошибки
flagError = False
# Имя удаленного сервера
remoteServer = ""
if self.clVars.Get("cl_profile_all_set") == "on":
osLinuxShort = "all"
else:
osLinuxShort = self.clVars.Get("os_linux_shortname")
# В случае включения репликации на сервере True
replOn = self.ldapDataObj.isRepl()
if replOn:
remoteServer = self.ldapDataObj.getNameRemoteServer(userName,
14 years ago
osLinuxShort,
domain)
# Получаем монтируемые директории
names, dictRes = self.getUserMountResources(userName, homeDir,
remoteServer)
# Путь к профилю пользователя по умолчанию
defaultPath = ""
# Хост пользователя по умолчанию
defaultHost = domain
# Флаг - будет использован инкрементальный архив
flagIncrArch = True
# Ошибка при монтировании удаленного сервера
flagErrorMountRemote = False
# Ошибка при cинхронизации с удаленного сервера
flagErrorSyncRemote = False
# Статус синхронизации
syncStatus = True
# Флаг копирования приватных файлов с сервера в случае
# устаревшей даты профиля
flagCopyPrivateFiles = False
# Если профиль на удаленном сервере
if remoteServer and replOn:
# имя файла архива в процессе архивации
archPathProcess = ""
# имя файла архива - после архивации
archPathSuccess = ""
# Создаем инкрементальный архив в случае репликации
prevHost = ""
# Дата профиля на текущем сервере
dateDefaultTemplate = ""
# Текущее время
currTime = str(float(time.time()))
archPathSrc = ""
archPathDst = ""
# Создаваемые пути при монтировании
for name in names:
# Пропускаем монтирование директории если нет синхронизации
if not sync and name == "remote_profile":
continue
path = dictRes[name]["path"]
res = dictRes[name]["resource"]
# Создаем пользовательскую директории для профиля
if not os.path.exists(path):
try:
os.mkdir(path)
os.chown(path, uid, gid)
os.chmod(path,0700)
except OSError:
self.printERROR(_("Error creating directory"))
self.printERROR(_("Permission denied: '%s'")%path)
flagError = True
break
#Проверяем на монтирование директории
14 years ago
if isMount(path):
continue
# Имя хоста для монтирования ресурса
hostConnect = defaultHost
if name == "remote_profile":
hostConnect = remoteServer
# Монтируем Samba ресурс
textLine = self.mountSleepRes(hostConnect, userName, userPwd,
uid, gid, res, path)
if textLine is False:
if name == "remote_profile":
flagErrorMountRemote = True
break
else:
self.printERROR(_("Can not mount Samba resource [%s]")\
%res + " ...")
flagError = True
break
# Если нет синхронизации отменяем обработку
if not sync:
continue
if name == "profile" or name == "remote_profile":
# Находим директорию профиля
homeTemplate = os.path.join(path, osLinuxShort)
if not os.path.exists(homeTemplate):
homeTemplate = os.path.join(path, "." + osLinuxShort)
# Проверка на дату профиля на удаленном сервере
if name == "remote_profile":
fileConfigRemote = os.path.join(homeTemplate,
self.configFileDesktop)
# объект времени для удаленного сервера
remoteTimeObj = self.getDateObjClientConf(fileConfigRemote)
if remoteTimeObj and currentTimeObj:
if currentTimeObj > remoteTimeObj:
sync = False
flagCopyPrivateFiles = True
# Если нет синхронизации отменяем обработку
if not sync:
continue
# Примонтирована директория профиля с текущего сервера
if name == "profile":
# Перенос профиля на сервере в директорию без точки
if not self.upgradeTemplateClient(userName, homeDir,
path):
flagError = True
break
fileConfig = os.path.join(homeTemplate,
self.configFileDesktop)
if os.path.exists(fileConfig):
objConfig = iniParser(fileConfig)
data = self.getDataInConfig("main", ["status_sync",
"date"],
objConfig)
if data:
status = data.get("status_sync")
date = data.get("date")
if date and status=="success":
dateDefaultTemplate = date
# Примонтирована директория профиля с удаленного сервера
# и есть дата профиля текущего сервера
if name == "remote_profile" and dateDefaultTemplate:
# Даем команду на создание инкрементального архива проф.
fileConfig = os.path.join(homeTemplate,self.configFileServer)
varsConfig = {"arch_date":dateDefaultTemplate,
"curr_time":currTime}
self.setServerCommand(["pack"], varsConfig, fileConfig)
# Отмонтируем директорию профиля с удаленного сервера
textLine = self.umountSleepPath(path)
if not textLine:
flagError = True
break
pathTemplateCurr = dictRes["profile"]["path"]
homeTemplateCurr = os.path.join(pathTemplateCurr,
osLinuxShort)
# Синхронизация профиля с текущего сервера
hostConnect = defaultHost
if not self.syncLoginTemplate(hostConnect, userName,homeDir,
homeTemplateCurr, uid, gid,
progress):
flagError = True
break
# Монтируем директорию профиля с удаленного сервера
hostConnect = remoteServer
textLine = self.mountSleepRes(hostConnect,userName,userPwd,
uid,gid,res,path)
if textLine is False:
self.printERROR(_("Can not mount Samba resource [%s]")\
%res + " ...")
flagError = True
break
extSuccess = "gz"
extProcess = "process"
strCurrentTime = currTime.replace(".","_")
archPathTmp = os.path.join(path, "profile.%s.%s.tar"\
%(osLinuxShort, strCurrentTime))
# имя файла архива в процессе архивации
archPathSuccess = "%s.%s"%(archPathTmp,extSuccess)
# имя файла архива - после архивации
archPathProcess = "%s.%s"%(archPathTmp,extProcess)
# Ищем файл архива
if not self.foundArchFile(strCurrentTime, archPathProcess,
archPathSuccess, progress,
remoteServer):
flagIncrArch = False
break
# Если нет архива применяем rsync синхронизацию
if not os.path.exists(archPathSuccess):
flagIncrArch = False
break
else:
archPathSrc = archPathSuccess
archPathDst = ".".join(filter(lambda x: x!="/",
archPathSuccess.rpartition("/")))
# Копируем архив
if not self.moveArch(archPathSrc, archPathDst,
progress, remoteServer):
flagError = True
if archPathSrc:
# Удаление архивного файла
if os.path.exists(archPathSrc):
# Удаляем файл архива
os.remove(archPathSrc)
if archPathDst:
# Удаление архивного файла
if os.path.exists(archPathDst):
# Удаляем файл архива
os.remove(archPathDst)
break
# Распаковываем архив в домашнюю директорию
if not self.unpackArch(homeDir, archPathDst,
progress, remoteServer):
flagError = True
if archPathDst:
# Удаление архивного файла
if os.path.exists(archPathDst):
# Удаляем файл архива
os.remove(archPathDst)
break
# Cканирование домашней директории и получение списка
# файлов
pathListFile = os.path.join(homeTemplate,
self.listTemplFile)
if not self.removeFilesInTemplate(homeDir,pathListFile):
# Отмонтируем пользовательские ресурсы в
# случае ошибки
self.umountUserRes(homeDir)
return False
else:
if name == "remote_profile":
flagIncrArch = False
if archPathProcess or archPathSuccess or archPathSrc or archPathDst:
# Удаление архивных файлов
rmFiles = [archPathProcess, archPathSuccess, archPathSrc,
archPathDst]
rmFiles = filter(lambda x: x, list(set(rmFiles)))
for rmFile in rmFiles:
if os.path.exists(rmFile):
# Удаляем файл архива
os.remove(rmFile)
# Если не удалось замонтировать удаленный профиль
if flagErrorMountRemote:
syncStatus = False
# Если не удалось использовать инкрементальный архив
elif flagIncrArch is False:
# Синхронизируем удаленный профиль
pathTemplate = dictRes["remote_profile"]["path"]
homeTemplate = os.path.join(pathTemplate, osLinuxShort)
if not self.upgradeTemplateClient(userName, homeDir,
pathTemplate):
# Отмонтируем пользовательские ресурсы в случае ошибки
self.umountUserRes(homeDir)
return False
# Синхронизация профиля с удаленного сервера
hostConnect = remoteServer
ret = self.syncLoginTemplate(hostConnect, userName, homeDir,
homeTemplate, uid, gid, progress,
False)
if not ret:
flagErrorSyncRemote = True
syncStatus = False
# Если не удалось синхронизировать удаленный синхронизируем
# текущий
homeTemplate = os.path.join(dictRes["profile"]["path"],
osLinuxShort)
# Синхронизация профиля пользователя с текущего сервера
hostConnect = defaultHost
if not self.syncLoginTemplate(hostConnect,userName,homeDir,
homeTemplate,uid,gid,progress):
# Отмонтируем пользовательские ресурсы в случае ошибки
self.umountUserRes(homeDir)
return False
if not flagError and flagCopyPrivateFiles:
configFileName = os.path.join(homeDir, self.configFileDesktop)
# записываем в конфигурационный файл статус
# Write to the configuration file status
self.setVarToConfig("main", {"status_sync":"success"},
configFileName, uid, gid)
# Копируем приватные файлы с сервера
# Copy private files from the server
self.copyPrivateFiles(homeTemplate, homeDir)
# Отмонтируем директорию профиля пользователя на удаленном сервере
if sync and "remote_profile" in dictRes:
umountPath = dictRes["remote_profile"]["path"]
if isMount(umountPath):
textLine = self.umountSleepPath(umountPath)
if not textLine:
# Отмонтируем пользовательские ресурсы в случае ошибки
self.umountUserRes(homeDir)
return False
# Удаляем директорию удаленного профиля у клиента
if os.path.exists(umountPath) and not os.listdir(umountPath):
os.rmdir(umountPath)
# Если профиль на текущем сервере
elif not remoteServer and replOn or not replOn:
# Создаваемые пути при монтировании
for name in names:
path = dictRes[name]["path"]
res = dictRes[name]["resource"]
# Создаем пользовательскую директории для профиля
if not os.path.exists(path):
try:
os.mkdir(path)
os.chown(path, uid, gid)
os.chmod(path,0700)
except OSError:
self.printERROR(_("Error creating directory"))
self.printERROR(_("Permission denied: '%s'")%path)
flagError = True
break
# Проверяем на монтирование директории
14 years ago
if isMount(path):
continue
# Имя хоста для монтирования ресурса
hostConnect = defaultHost
textLine = self.mountSleepRes(hostConnect, userName, userPwd,
uid, gid, res, path)
if textLine is False:
self.printERROR(_("Can not mount Samba resource [%s]")\
%res + " ...")
flagError = True
break
# Если нет синхронизации отменяем обработку
if not sync:
continue
if name == "profile":
pathTemplate = path
# Перенос профиля на сервере в директорию без точки
if not self.upgradeTemplateClient(userName, homeDir,
pathTemplate):
flagError = True
break
# Директория профиля
homeTemplate = os.path.join(path, osLinuxShort)
# Проверка на дату профиля на текущем сервере
fileConfigThis = os.path.join(homeTemplate,
self.configFileDesktop)
thisTimeObj = self.getDateObjClientConf(fileConfigThis)
if thisTimeObj and currentTimeObj:
if currentTimeObj > thisTimeObj:
sync = False
flagCopyPrivateFiles = True
# Если нет синхронизации отменяем обработку
if not sync:
continue
# Синхронизация профиля пользователя с текущего сервера
hostConnect = defaultHost
if not self.syncLoginTemplate(hostConnect, userName, homeDir,
homeTemplate, uid, gid,
progress):
# Отмонтируем пользовательские ресурсы в случае ошибки
self.umountUserRes(homeDir)
return False
if not flagError and flagCopyPrivateFiles:
configFileName = os.path.join(homeDir, self.configFileDesktop)
# записываем в конфигурационный файл статус
# Write to the configuration file status
self.setVarToConfig("main", {"status_sync":"success"},
configFileName, uid, gid)
# Копируем приватные файлы с сервера
# Copy private files from the server
self.copyPrivateFiles(homeTemplate, homeDir)
if flagError:
# Отмонтируем пользовательские ресурсы в случае ошибки
self.umountUserRes(homeDir)
return False
if sync:
logOutFile = os.path.join(homeDir,self.logOutFile)
if syncStatus:
self.setVarToConfig("main", {"status_sync":"success"},
configFileName, uid, gid)
self.createUserFile(logOutFile,"SUCCESS", uid, gid)
else:
self.createUserFile(logOutFile,"ERROR", uid, gid)
self.setVarToConfig("main", {"status_sync":"error"},
configFileName, uid, gid)
self.printWARNING(_("Error in sync with the remote server %s")\
%remoteServer)
self.printSUCCESS(_("Mounted user resource of the domain"))
if sync:
self.printOK(_("Get a user profile from the domain") + " ...")
return True
def isSessionUser(self, userName):
"""Проверка на вход пользователя в X"""
xSession = False
reFoundUser = re.compile("%s\s+:\d+\s+"%(userName))
resWho = self.execProg("who")
if resWho:
for string in resWho:
if reFoundUser.search(string):
xSession = True
break
return xSession
def moveHomeDir(self, userHome):
"""Переносим файлы пользователя в Home/Moved"""
# Находим директории и файлы в домашней директории
pathProg = os.getcwd()
os.chdir(userHome)
dirs = []
files = []
movedLink = os.path.join('Moved')
movedPath = os.path.join('Home',"Moved")
skipPaths = self.clVars.Get("cl_moved_skip_path")
if not skipPaths:
skipPaths = ['Disks','Share','Home','Moved','FTP','Desktop']
filesAndDir = filter(lambda x: not ('.' in x[0] or x in\
skipPaths or os.path.islink(x)),
os.listdir('.'))
filesDir = []
for fd in filesAndDir:
if os.path.islink(fd):
os.unlink(fd)
else:
filesDir.append(fd)
# Нахождение файлов отличных ссылок и .* в Desktop
pathDesktop = './Desktop'
filesDirDesk = []
if os.path.exists(pathDesktop):
filesDirDesk = filter(lambda x: not os.path.islink(x) and\
not os.path.split(x)[1].startswith('.') and\
not x.rpartition('.')[2]=='desktop',
map(lambda x: os.path.join(pathDesktop,x),\
os.listdir(pathDesktop)))
movedPathDesk = os.path.join(movedPath, pathDesktop)
filesDir += filesDirDesk
if not filesDir or not os.path.exists("Home"):
# Удаляем пустую папку Moved
if os.path.exists(movedPath) and not os.listdir(movedPath):
os.rmdir(movedPath)
# Удалям ссылку на Moved в домашней директории
if os.path.islink(movedLink) and not os.path.exists(movedPath):
os.unlink(movedLink)
return True
if not os.path.exists(movedPath):
os.mkdir(movedPath)
directFile = os.path.join(movedPath,".directory")
if not os.path.exists(directFile):
txt = "[Desktop Entry]\nIcon=folder-development"
fd = os.open(directFile, os.O_CREAT)
os.close(fd)
FD = open (directFile, "r+")
FD.write(txt)
FD.close()
if not os.path.exists(movedLink):
os.symlink(movedPath, movedLink)
for fd in filesDir:
execStr = "cp -r '%s' '%s'" %(fd, movedPath)
textLine = self.execProg(execStr)
if textLine is False:
self.printERROR(_("Can not exec") + " " + str(execStr) +\
" ...")
return False
execStr = "rm -rf '%s'" %fd
textLine = self.execProg(execStr)
if textLine is False:
self.printERROR(_("Can not exec") + " " + str(execStr) +\
" ...")
return False
os.chdir(pathProg)
return True
def removeNoiseFiles(self, userHome):
"""Удаление файлов, создающих помехи работе dm"""
noiseFiles = ['.dmrc']
for nsFile in noiseFiles:
rmFile = os.path.join(userHome, nsFile)
if os.path.exists(rmFile):
os.remove(rmFile)
return True
def getPrivateFiles(self, userHome):
"""Все приватные файлы пользователя относительно директории userHome"""
privateFiles = []
for privateHomeDir in self.privateDirs:
privateDir = os.path.join(userHome,privateHomeDir)
if os.path.isdir(privateDir):
# .ssh файлы относительно домашней директории пользователя
privateFiles += map(lambda x:os.path.join(privateHomeDir,x),
filter(lambda x:\
os.path.isfile(os.path.join(privateDir,x)),
os.listdir(privateDir)))
return self.privateFiles + privateFiles
def removePrivateFiles(self, userHome):
"""Удаление приватных файлов"""
privateFiles = self.getPrivateFiles(userHome)
for prFile in privateFiles:
rmFile = os.path.join(userHome, prFile)
if os.path.exists(rmFile):
os.remove(rmFile)
return True
def copyPrivateFiles(self, serverProfileDir, userHomeDir):
"""Копирование приватных файлов c сервера в домашнюю директорию"""
privateFiles = self.getPrivateFiles(serverProfileDir)
for prFile in privateFiles:
src = os.path.join(serverProfileDir, prFile)
dst = os.path.join(userHomeDir, prFile)
if os.path.exists(src):
dstPath = os.path.dirname(dst)
if not os.path.exists(dstPath):
listElPath = []
for el in filter(lambda x: x,
dstPath.partition(userHomeDir)[2].split("/")):
listElPath.append(el)
joinPath = "/".join(listElPath)
dPath = os.path.join(userHomeDir, joinPath)
if not os.path.exists(dPath):
sPath = os.path.join(serverProfileDir, joinPath)
sMode, sUid, sGid = getModeFile(sPath)
os.mkdir(dPath,sMode)
os.chown(dPath, sUid, sGid)
copy2(src, dst)
sUid, sGid = getModeFile(src, mode="owner")
os.chown(dst, sUid, sGid)
return True
def scanDirectory(self, scanDir, listFiles, skipPath=[], prefix=False,
flagDir=False):
"""Генерация списка файлов и директорий"""
if not prefix:
prefix = os.path.join(scanDir,"")
if flagDir or stat.S_ISDIR(os.lstat(scanDir)[stat.ST_MODE]):
for fileOrDir in os.listdir(scanDir):
absPath = os.path.join(scanDir,fileOrDir)
relPath = absPath.split(prefix)[1]
if relPath in skipPath:
continue
listFiles.append(relPath)
stInfo = os.lstat(absPath)
statInfo = stInfo[stat.ST_MODE]
if stat.S_ISDIR(statInfo):
self.scanDirectory(absPath, listFiles,
skipPath, prefix, True)
def getListFilesTemplate(self, homeDir):
"""Генерация списка файлов в домашней директориии
Исключая монтируемые директории
"""
home = os.path.join(homeDir, "")
execStr = "mount"
textLines = self.execProg(execStr)
# Пропускаемые директории для сканирования
skipPaths = []
if textLines:
for line in textLines:
if home in line:
skipPath =\
line.partition(home)[2].rpartition(" type")[0]
skipPaths.append(skipPath)
# Список файлов в профиле пользователя
listFiles = []
if not skipPaths:
self.printERROR(_("Not found the mount point of server resources"))
return False
self.scanDirectory(homeDir, listFiles, skipPaths)
return listFiles
def removeFilesInTemplate(self, homeDir, pathListFile):
"""Удаляем файлы которых нет в профиле пользователя"""
# Получаем файлы профиля на сервере
try:
filesTemplateTxt = open(pathListFile).read()
except:
self.printERROR(_("Can not open %s")%pathListFile)
return False
listFilesTemplate = filter(lambda x: x.strip(),
filesTemplateTxt.split("\n"))
filesTemplate = set(listFilesTemplate)
# Получаем файлы в домашней директории
listFilesHome = self.getListFilesTemplate(homeDir)
if listFilesHome is False:
return False
filesHome = set(listFilesHome)
filesRemove = list(filesHome - filesTemplate)
filesRemove.sort(lambda x, y: cmp(len(y), len(x)))
rmPath = ""
try:
for rmFile in filesRemove:
rmPath = os.path.join(homeDir, rmFile)
if os.path.islink(rmPath):
os.unlink(rmPath)
elif os.path.isfile(rmPath):
os.remove(rmPath)
elif os.path.isdir(rmPath):
os.rmdir(rmPath)
else:
os.remove(rmPath)
except:
self.printERROR(_("Can not remove %s")%rmPath)
return False
return True
def clearUserKey(self, userName):
"""Очищает пользовательский ключ ядра"""
# Ищем ключ в ядре
if getKey(userName):
# Если нашли очищаем
ret = clearKey(userName)
if ret == 0:
return True
else:
self.printERROR(_("Can not clear kernel key from user %s")\
%userName)
return False
return True
def umountUserResAndSync(self, userName, progress=False, sync=True):
"""Отмонтирование пользовательских ресурсов и синхронизация настроек"""
# Проверяем на root
if not self.isRoot():
return False
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
currentDateStr = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
if userName in passwdUsers:
try:
pwdObj = pwd.getpwnam(userName)
except:
self.printERROR(_("Can not found user %s")%userName)
self.umountUserRes()
return False
homeDir = pwdObj.pw_dir
uid = pwdObj.pw_uid
gid = pwdObj.pw_gid
configFileName = os.path.join(homeDir, self.configFileDesktop)
self.setVarToConfig("main", {"date_logout":currentDateStr},
configFileName, uid, gid)
self.printWARNING(_("We use user information from /etc/passwd"))
self.printSUCCESS(_("To be used local profile"))
return True
domain = self.clVars.Get("cl_remote_host")
hostAuth = self.clVars.Get("os_remote_auth")
# В случае компьютера вне домена
if not hostAuth or not domain:
self.printSUCCESS(_("To be used local profile"))
return True
connectDomain = self.isDomain()
if not connectDomain:
# Отмонтируем пользовательские ресурсы в случае ошибки
self.umountUserRes()
return False
# Если пользователь в X сессии тогда не будем отмонтировать ресурсы
if self.isSessionUser(userName):
self.printERROR(_("User %s is in X session")%userName)
self.printERROR(_("Can not unmount user %s resource")%userName)
return False
# Информация о пользователе из LDAP
userLdapInfo = self.ldapDataObj.getUserLdapInfo(userName)
if userLdapInfo:
uid = int(userLdapInfo['uid'])
14 years ago
gid = int(userLdapInfo['gid'])
homeDir = userLdapInfo['home']
else:
self.printERROR(_("Can not found user %s in LDAP")%userName)
self.umountUserRes()
return False
# Файл хранения настроек пакета
configFileName = os.path.join(homeDir, self.configFileDesktop)
self.setVarToConfig("main", {"date_logout":currentDateStr},
configFileName, uid, gid)
if os.path.exists(homeDir):
self.moveHomeDir(homeDir)
else:
# Отмонтируем пользовательские ресурсы в случае ошибки
self.printERROR(_("Directory %s not found") % homeDir)
self.umountUserRes(homeDir)
return False
# необходима ли синхронизация с локальным сервером
needSync = sync
# проверяем произведен ли корректный вход в систему -
# в этом случае закачиваем профиль с локальной машины на сервер
exitStr = iniParser(configFileName).getVar('main','status_sync')
# проверяем cтатус синхронизации: не содержит ли он "process"
if exitStr == "process" or exitStr == "error":
needSync = False
if self.clVars.Get("cl_profile_all_set") == "on":
osLinuxShort = "all"
else:
osLinuxShort = self.clVars.Get("os_linux_shortname")
# Получаем монтируемые директории
names, dictRes = self.getUserMountResources(userName, homeDir, False)
pathUnix = dictRes["profile"]["path"]
homeTemplate = os.path.join(pathUnix, osLinuxShort)
if needSync:
# Синхронизация профиля пользователя на сервер
if not self.syncUser(userName, homeDir, "logout", uid, gid,
homeTemplate):
# Удаляем файлы, мешающие работе dm
self.removeNoiseFiles(homeDir)
# Удаляем приватные файлы
self.removePrivateFiles(homeDir)
# Очищаем ключ в ядре
self.clearUserKey(userName)
# Отмонтируем пользовательские ресурсы в случае ошибки
self.umountUserRes(homeDir)
return False
# Удаляем файлы, мешающие работе dm
self.removeNoiseFiles(homeDir)
# Удаляем приватные файлы
self.removePrivateFiles(homeDir)
# Очищаем ключ в ядре
self.clearUserKey(userName)
# Отмонтируем директории
if not self.umountUserRes(homeDir):
return False
# Удаляем пустые директории
for name in names:
path = dictRes[name]["path"]
if os.path.exists(path) and not os.listdir(path):
try:
os.rmdir(path)
except:
self.printERROR(_("Can not remove dir %s")% path)
return False
# Удаляем Disks директорию если она пуста
pathDisks = os.path.join(homeDir,"Disks")
if os.path.exists(pathDisks) and not os.listdir(pathDisks):
try:
os.rmdir(pathDisks)
except:
self.printERROR(_("Can not remove dir %s")% pathDisks)
return False
if needSync:
self.printSUCCESS(_("Saved a user profile in the domain"))
self.printOK(_("Umounted user resource in domain") + " ...")
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)
mountTemplateDir = os.path.join(dirStart, ".%s" %dirEnd)
mountRemoteTemplateDir = os.path.join(dirStart, ".%s.remote" %dirEnd)
return filter(lambda x: x.startswith(homeDir) or\
x.startswith(mountTemplateDir) or\
x.startswith(mountRemoteTemplateDir),
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, 1, 2]
# Проверяем на монтирование директорию
14 years ago
if isMount(path):
textLines = self.execProg("umount %s"%path)
if textLines is False:
i = 0
flagError = False
while (i<len(sleeps) and textLines is False):
# Задержка перед следующей попыткой
time.sleep(sleeps[i])
# Отмонтируем Samba ресурс
14 years ago
if isMount(path):
textLines = self.execProg("umount %s"%path)
else:
textLines = True
break
i += 1
if textLines is False:
self.execProg("fuser -km %s"%path)
sleeps = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
i = 0
while (i<len(sleeps) and isMount(path)):
time.sleep(sleeps[i])
self.execProg("umount %s"%path)
i += 1
if isMount(path):
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
def installProg(self):
"""Наложение шаблонов на систему при инсталяции"""
# Действие выход из домена
self.clVars.Set("cl_action", "install", True)
domain = self.clVars.Get("cl_remote_host")
14 years ago
self.clVars.AppendToList("cl_merges", __app__, force=True)
# Добавление программы в инсталяционную переменную
if not appendProgramToEnvFile(__app__, self.clVars):
self.printERROR(_("Can not save '%s'") %__app__ + " " +\
_("to %s") %self.clVars.Get("cl_env_path")[0])
return False
if domain:
if not self.addDaemonAutostart("client"):
return False
if not self.mountRemote():
return False
if not self.applyTemplatesFromSystem():
14 years ago
self.printERROR(_("Can not apply install templates"))
return False
14 years ago
if domain:
self.printOK(_("To be used domain profile") + " ...")
else:
self.printOK(_("To be used local profile") + " ...")
return True
def getDefaultRunlevelDaemons(self):
"""Получаем всех демонов в default уровне"""
execStr = "rc-update show"
textLine = self.execProg(execStr)
if textLine is False:
self.printERROR(_("ERROR") + ": " + execStr)
return False
else:
splLines = filter(lambda x: len(x)==2 and "default" in x[1],\
map(lambda x: x.split("|"),textLine))
splLines = map(lambda x: x[0].strip(), splLines)
return splLines
def uninstallProg(self):
"""Наложение шаблонов на систему при деинсталяции"""
# Проверяем на root
if not self.isRoot():
return False
# Действие удаление
self.clVars.Set("cl_action", "uninstall", True)
# Удаляем переменные из env файлов
self.removeVars()
# Удаление программы из инсталяционной переменной
if not removeProgramToEnvFile(__app__, self.clVars):
self.printERROR(_("Can not remove '%(app)s' from %(path)s")%
{'app':__app__,
'path':self.clVars.Get("cl_env_path")[0]})
return False
if not self.applyTemplatesFromSystem():
self.printERROR(_("Can not apply uninstall templates"))
return False
if not self.delDaemonAutostart("client"):
return False
self.printOK(_("Apply uninstall templates"))
return True
def delDaemonAutostart(self, daemon):
"""Удаляет демона из автозагрузки"""
defaultDaemons = self.getDefaultRunlevelDaemons()
if defaultDaemons is False:
return False
if daemon in defaultDaemons:
execStr = "rc-update del %s default" %daemon
textLine = self.execProg(execStr)
if textLine is False:
self.printERROR(_("ERROR") + ": " + execStr)
self.printERROR(_("Can not delete from default runlevel"))
return False
else:
return True
return True
def delDomain(self):
"""выводим из домена"""
# Проверяем на root
if not self.isRoot():
return False
pathRemote = "/var/calculate/remote"
14 years ago
foundMountRemote = isMount(pathRemote)
domain = self.clVars.Get("cl_remote_host")
if foundMountRemote:
textLineUmount = self.umountSleepPath(pathRemote)
if not textLineUmount:
return False
if not domain:
self.printWARNING(_("The computer is not in domain"))
return True
# Удаляем переменные из env файлов
self.removeVars()
14 years ago
# Устанавливаем действие выход из домена
self.clVars.Set("cl_action", "undomain", True)
if not self.applyTemplatesFromSystem():
self.printERROR(_("Can not apply undomain templates"))
return False
# Delete LDAP users from system and clear cache
if not self.cDelLdapSysUsersAndClearCache():
return False
# Рестартуем dbus
self.restartDBus()
self.printSUCCESS(_("Apply undomain templates"))
if not self.delDaemonAutostart("client"):
return False
self.printOK(_("Computer removed from domain %s")%domain + " ...")
return True
def getUserPassword(self, pwDialog=False):
"""Получить пароль у пользователя
pwDialog - приглашение ввода пароля
"""
if not pwDialog:
pwDialog = _("Password")
userPwd = getpass.getpass(pwDialog+":")
return userPwd
def addDaemonAutostart(self, daemon):
"""Прописывает демона в автозагрузку"""
defaultDaemons = self.getDefaultRunlevelDaemons()
if defaultDaemons is False:
return False
if daemon in defaultDaemons:
return True
execStr = "rc-update add %s default" %daemon
textLine = self.execProg(execStr)
if textLine is False:
self.printERROR(_("ERROR") + ": " + execStr)
self.printERROR(_("Can not add at default runlevel"))
return False
else:
return True
def restartDBus(self):
"""Перезапускаем службу D-Bus"""
dbusDaemon = '/etc/init.d/dbus'
if os.path.exists(dbusDaemon):
if os.system(dbusDaemon + ' restart &>/dev/null') != 0:
self.printWARNING(_("Error restarting")+" "+dbusDaemon+" ...")
return False
return True
def getInfoService(self, service, option, envFile=False):
"""Получить параметр сервиса из env"""
if not envFile:
if self.convObj == None:
# файл /var/calculate/remote/server.env
envFile = self.clVars.Get("cl_env_server_path")
if os.access(envFile, os.R_OK):
self.convObj = False
elif os.access("/var/calculate/remote/calculate.env", os.R_OK):
self.convObj = convertEnv()
if self.convObj:
return self.convObj.getVar(service, option)
if not self.optionsInfo:
if not envFile:
# файл /var/calculate/remote/server.env
envFile = self.clVars.Get("cl_env_server_path")
optInfo = self.clVars.GetRemoteInfo(envFile)
if optInfo is False:
return False
if optInfo:
self.optionsInfo = optInfo
value = ''
if service in self.optionsInfo and option in self.optionsInfo[service]:
value = self.optionsInfo[service][option]
return value
def addDomain(self, domainName):
"""Вводим в домен"""
# Проверяем на root
if not self.isRoot():
return False
netDomain = self.clVars.Get("os_net_domain")
# Получам имя сервера (домена)
if "." in domainName:
domain = domainName
else:
domain = "%s.%s" %(domainName,netDomain)
execStr = "ping -c 2 -i 0.3 %s" %domain
resPing = self.execProg(execStr)
if resPing is False:
self.printERROR(_('Can not execute "%s"')%execStr)
return False
foudHost = False
foundHostSamba = False
foundMountRemote = False
reFoundHost = re.compile("(\d+)\% packet loss")
if resPing and len(resPing)>=2:
pingStr = resPing[-2].strip()
reSearch = reFoundHost.search(pingStr)
if reSearch and reSearch.group(1) == "0":
foudHost = True
if not foudHost:
self.printERROR(_("Not found domain %s")%domain)
return False
reFoundHostSamba = re.compile("Server=\[Samba.+\]")
resSmbClient = self.execProg("smbclient -N -L %s" %domain)
if not resSmbClient is False:
for string in resSmbClient:
if reFoundHostSamba.search(string):
foundHostSamba = True
break
if not foundHostSamba:
self.printERROR(_("Not found Samba server in %s")%domain)
return False
remoteHost = self.clVars.Get("cl_remote_host")
if remoteHost:
self.printERROR(_("The computer is already in the domain %s")\
%remoteHost)
self.printWARNING(_("Before joining the domain, \
you need to remove it from the previous domain"))
14 years ago
self.printWARNING(_("Run 'cl-client -r'"))
return False
14 years ago
foundMountRemote = isMount("/var/calculate/remote")
if foundMountRemote:
self.printERROR(_("Samba resource [%s] is mount")%\
"remote" + " ...")
return False
else:
userPwd=self.getUserPassword(\
_("Domain password for the desktop"))
pathRemote = "/var/calculate/remote"
pwdRemote = userPwd
if not os.path.exists(pathRemote):
os.makedirs(pathRemote)
mountStr = "mount -t cifs -o user=client //%s/remote %s"\
%(domain,pathRemote)
textLine = self.execProg(mountStr, envProg={"PASSWD":pwdRemote})
if textLine is False:
self.printERROR(_("Can not mount Samba resource [%s]")%\
"remote" + " ...")
return False
else:
self.printSUCCESS(_("Mount Samba resource [%s]")%"remote" + \
" ...")
self.clVars.Write("cl_remote_host", domain, True, "local")
self.clVars.Write("cl_remote_pw", userPwd, True, "local")
servDn = self.getInfoService("ldap", "services_dn")
unixDn = self.getInfoService("unix", "dn")
bindDn = self.getInfoService("unix", "bind_dn")
bindPw = self.getInfoService("unix", "bind_pw")
# запишем их
if not (servDn and unixDn and bindDn and bindPw):
self.printERROR(_("Not found server info") + ": " +\
_("services DN or unix DN or bind DN or bind password"))
return False
14 years ago
# Наложим шаблоны - domain
# Действие - ввод в домен
self.clVars.Set("cl_action", "domain", True)
# Доменная авторизация
self.clVars.Set("os_remote_auth", domain)
if not self.applyTemplatesFromSystem():
self.printERROR(_("Can not apply install or domain templates"))
return False
# Рестартуем dbus
self.restartDBus()
if not self.addDaemonAutostart("client"):
return False
# Записываем переменную
self.clVars.Write("os_remote_auth", domain, True)
# Записываем текущую версию программы
currentVersion = self.clVars.Get("cl_ver")
self.clVars.Write("os_remote_client", currentVersion, True)
self.printOK(_("Computer added to domain %s")%domain + " ...")
return True
def relevanceTemplates(self, hostAuth):
"""Определяем актуальность наложенных шаблонов
в зависимости от версии программы
Перед запуском обязательно должен быть определен объект переменных
self.clVars
Если актуальны - True, если нет False
"""
# '' или имя хоста
if hostAuth != self.clVars.Get("os_remote_auth"):
return False
clTempl = template(self.clVars)
# Текущая версия программы
currentVersion = self.clVars.Get("cl_ver")
# Версия программы которая ранее работала с шаблонами
previousVersion = self.clVars.Get("os_remote_client")
cVersion,pVersion = clTempl._convertVers(currentVersion,previousVersion)
# Если версии программ не равны то шаблоны не актуальные
if cVersion != pVersion:
return False
return True
def applyRelevanceTemplates(self, hostAuth=""):
"""Накладывает релевантные шаблоны
Перед запуском обязательно должен быть определен объект переменных
self.clVars
"""
if not self.relevanceTemplates(hostAuth):
if hostAuth:
14 years ago
# Устанавливаем действие вход в домен
self.clVars.Set("cl_action","domain",True)
else:
14 years ago
# Устанавливаем действие выход из домена
self.clVars.Set("cl_action","undomain",True)
self.clVars.Set("os_remote_auth", hostAuth)
# Наложим шаблоны
dirsAndFiles = self.applyTemplatesFromSystem()
if not dirsAndFiles:
if hostAuth:
self.printERROR(_("Can not apply domain templates"))
else:
self.printERROR(_("Can not apply undomain templates"))
return False
if hostAuth:
self.printOK(_("Set templates of network mode"))
currentVersion = self.clVars.Get("cl_ver")
self.clVars.Write("os_remote_client", currentVersion, True)
self.clVars.Write("os_remote_auth", hostAuth, True)
else:
self.printOK(_("Set templates of local mode"))
self.clVars.Delete("os_remote_auth")
self.clVars.Delete("os_remote_client")
return True
def cDelLdapSysUsersAndSyncCache(self):
"""Delete LDAP users from system and synchronize cache"""
cacheObj = userCache()
if not cacheObj.deleteCacheUsersFromSystem():
return False
if not cacheObj.syncCacheToLdap():
return False
return True
def cAddCacheUsersFromSystem(self):
"""Add cache users from system"""
cacheObj = userCache()
if not cacheObj.addCacheUsersFromSystem():
return False
return True
def cAddUserToCache(self, userName, userPwd):
"""Add user to cache"""
cacheObj = userCache()
pwdHash = self.getHashPasswd(userPwd, "shadow_ssha256")
if not cacheObj.addUserToCache(userName, pwdHash):
return False
return True
def cDelLdapSysUsersAndClearCache(self):
"""Delete LDAP users from system and clear cache"""
cacheObj = userCache()
if not cacheObj.deleteCacheUsersFromSystem():
return False
if not cacheObj.clearCache():
return False
return True
14 years ago
def moveHomeDirs(self):
"""Move home dirs /var/calculate/client-home -> /home
if user in cache
"""
14 years ago
cacheObj = userCache()
loginUsersData = cacheObj.getLoginDomainUsers()
if loginUsersData is False:
return False
previousHome = "/var/calculate/client-home"
14 years ago
if isMount(previousHome):
return True
14 years ago
if os.path.exists(previousHome):
14 years ago
flagMovedUsers = False
14 years ago
for userName,x,uid,gid,gecos,directory,shell in loginUsersData:
homeDir = directory
14 years ago
pathUserList = filter(lambda x: x, directory.split('/'))
if not pathUserList:
continue
pathUser = "/".join(pathUserList[1:])
14 years ago
srcDir = pathJoin(previousHome, pathUser)
14 years ago
if os.path.exists(srcDir) and not os.path.exists(homeDir):
14 years ago
flagMovedUsers = True
14 years ago
destDir = os.path.dirname(homeDir)
14 years ago
self.printWARNING(_("Moved %(src)s to %(dest)s")\
%{"src":srcDir,"dest":homeDir})
14 years ago
if not self.copyTemplateDir(srcDir, destDir):
return False
14 years ago
if flagMovedUsers and not os.listdir(previousHome):
os.rmdir(previousHome)
14 years ago
return True
def mountRemote(self):
"""Монтирование remote если компьютер в домене
а так-же ввод в домен если найдено имя хоста и пароль для подключения
"""
# Проверяем на root
if not self.isRoot():
return False
domain = self.clVars.Get("cl_remote_host")
if domain:
14 years ago
foundMountRemote = isMount("/var/calculate/remote")
else:
self.printWARNING(_("This computer is not in domain"))
# Если шаблоны не актуальны накладываем новую версию шаблонов
if not self.applyRelevanceTemplates():
return False
return True
if foundMountRemote:
self.printWARNING(_("Samba resource [%s] is mount")%"remote" + \
" ...")
# Накладываем сетевые шаблоны
if domain:
self.clVars.flIniFile()
if not self.applyRelevanceTemplates(domain):
return False
# Delete LDAP users from system and synchronize cache
if not self.cDelLdapSysUsersAndSyncCache():
return False
return True
else:
pathRemote = "/var/calculate/remote"
pwdRemote = self.clVars.Get("cl_remote_pw")
if not (domain and pwdRemote):
self.printERROR(_("Not found variable")+\
": cl_remote_pw ...")
return False
if not os.path.exists(pathRemote):
os.makedirs(pathRemote)
mountStr = "mount -t cifs -o user=client //%s/remote %s"\
%(domain,pathRemote)
textLine = self.execProg(mountStr, envProg={"PASSWD":pwdRemote})
if textLine is False:
self.printWARNING(_("Can not mount Samba resource [%s]")%\
"remote" + " ...")
beforeRemoteAuth = self.clVars.Get('os_remote_auth')
# Если шаблоны не актуальны накладываем новую версию шаблонов
if not self.applyRelevanceTemplates():
return False
if not self.cAddCacheUsersFromSystem():
return False
14 years ago
if not self.moveHomeDirs():
14 years ago
return False
if beforeRemoteAuth != self.clVars.Get('os_remote_auth'):
self.restartDBus()
return True
self.printSUCCESS(_("Mount Samba resource [%s]") % "remote" +\
" ...")
# Накладываем сетевые шаблоны
if domain:
self.clVars.flIniFile()
beforeRemoteAuth = self.clVars.Get('os_remote_auth')
if not self.applyRelevanceTemplates(domain):
return False
# Delete LDAP users from system and synchronize cache
if not self.cDelLdapSysUsersAndSyncCache():
return False
if beforeRemoteAuth != self.clVars.Get('os_remote_auth'):
self.restartDBus()
return True
def updateEnvFiles(self):
"""Апдейт env файлов до версии 2.2"""
previousVersion = self.clVars.Get("os_remote_client")
flagUpdate = False
if not previousVersion:
# Апдейт
envFile="/var/calculate/calculate.env"
remoteHost = self.getInfoService("client", "cl_remote_host",
envFile=envFile)
remotePw = self.getInfoService("client", "cl_remote_pw",
envFile=envFile)
if remoteHost and remotePw:
self.clVars.Write("cl_remote_host", remoteHost, True, "local")
self.clVars.Write("cl_remote_pw", remotePw, True, "local")
envFile="/etc/calculate/calculate.env"
previousVersion = self.getInfoService("client", "os_remote_client",
envFile=envFile)
workHost = self.getInfoService("client", "os_remote_auth",
envFile=envFile)
if previousVersion and workHost:
self.clVars.Write("os_remote_client", previousVersion, True)
if workHost != "local":
self.clVars.Write("os_remote_auth", workHost, True)
self.printOK(_("Update env files") + " ...")
flagUpdate = True
return flagUpdate
def setUserPasswordToServer(self):
"""Установка пароля пользователя на сервере"""
# Проверяем на root
if self.isRoot(False):
self.printERROR(_("The user is root"))
self.printWARNING(\
_("The program can be executed from a non-root user only"))
return False
# DNS имя хоста
server = self.ldapDataObj.getHost()
# DN пользователей
usersDN = self.ldapDataObj.getUsersDN()
if not (server and usersDN):
self.printERROR(_("The computer is not in domain"))
self.printWARNING(_("Use passwd"))
return False
count = 2
# Получаем старый пароль пользователя
curPassword = self.getUserPassword(_("Enter current password"))
if not curPassword:
self.printERROR(_("Current password is empty"))
for i in range(count):
count -= 1
# Получаем старый пароль пользователя
curPassword = self.getUserPassword(_("Enter current password"))
if curPassword:
break
self.printERROR(_("Current password is empty"))
if not curPassword:
return False
userDN = self.ldapDataObj.addDN("uid=%s"%os.environ["USER"], usersDN)
# Проверяем в LDAP сервере текущий пароль пользователя
ret, err = self.checkUserPwdLDAP(server, userDN, curPassword)
if not ret:
self.printERROR(err)
for i in range(count):
# Получаем старый пароль пользователя
curPassword = self.getUserPassword(_("Enter current password"))
if not curPassword:
self.printERROR(_("Current password is empty"))
continue
# Проверяем в LDAP сервере текущий пароль пользователя
ret, err = self.checkUserPwdLDAP(server, userDN, curPassword)
if ret:
break
self.printERROR(err)
if not ret:
return False
password = self.getUserPwd({"p":""}, "p", False)
if password is False:
for i in range(2):
password = self.getUserPwd({"p":""}, "p", False)
if password:
break
if password is False:
return False
# Переменные для записи в env файл
varsConfig = {"unix_hash":self.getHashPasswd(password,"ssha"),
"samba_lm_hash":self.getHashPasswd(password,"lm"),
"samba_nt_hash":self.getHashPasswd(password,"nt"),
"samba_nt_hash_old":self.getHashPasswd(curPassword,"nt")}
if filter(lambda x: not x, varsConfig.values()):
return False
# ~/.calculate/server.env
fileConfig = os.path.join(os.environ["HOME"], self.configFileServer)
if not self.setServerCommand(["passwd_samba"], varsConfig, fileConfig):
return False
self.printOK(_("Changed password of user %s")%os.environ["USER"] + \
" ...")
self.printWARNING(_("Password will be changed when you logout from the \
X session"))
return True