Added the creation of a differential archive for the user profile

legacy
Самоукин Алексей 14 years ago
parent 03ecd4a9c8
commit f9e3740148

@ -992,7 +992,7 @@ in a sambaDomainName',
userPwd = ""
if optStdIn and options.has_key(optStdIn):
pwdA = sys.stdin.readline().rstrip()
pwdB = sys.stdin.readline().rstrip()
pwdB = pwdA
elif optDialog and options.has_key(optDialog):
if not pwDialog:
pwDialog = [_("New password"),
@ -11634,7 +11634,11 @@ class servRepl(shareLdap):
# Файл для определения выхода пользователя.
logOutFile = ".logout"
# Файл для управления сервером
envFile = ".calculate/server.env"
srvFile = ".calculate/server.env"
# Файл для клиента
deskFile = ".calculate/desktop.env"
# Файл - список файлов профиля пользователя
listProfFile = ".calculate/files.txt"
# Переменные (/etc/calculate/calculate.env)
# которые будут сохранены при rebuild
restoreDefaultVar =["sr_ldap_set", "ld_repl_pw", "ld_repl_set",
@ -11663,6 +11667,12 @@ class servRepl(shareLdap):
replCronFile = "replcron"
# поддерживаемые сервисы
replServices = ("unix", "samba", "mail")
# Файлы и директории которые нужно пропускать при нахождении времени
# модификации в профиле пользователя
skipDatePathsInProfile = list(set([".calculate.ini",
os.path.split(srvFile),
os.path.split(deskFile),
logOutFile]))
def __init__(self):
shareLdap.__init__(self)
@ -11956,16 +11966,16 @@ class servRepl(shareLdap):
return False
@adminConnectLdap
def isExistsLogout(self, userName):
"""Проверяет существует ли в директорииях профиля пользователя .logout
в случае удачи выводит эти директории"""
def getProfileDirs(self, userName):
"""Выводит директории профилей для пользователя"""
profileDir = os.path.join(self.clVars.Get("sr_samba_linprof_path"),
userName)
if not os.path.exists(profileDir):
return False
return filter(lambda x:\
os.path.exists(os.path.join(x, self.logOutFile)),\
os.path.exists(os.path.join(x, self.logOutFile)) or \
os.path.exists(os.path.join(x, self.srvFile)) or\
os.path.exists(os.path.join(x, self.deskFile)),
[profileDir] + map(lambda x: os.path.join(profileDir, x),\
filter(lambda x:\
os.path.isdir(os.path.join(profileDir, x)) ,\
@ -12056,13 +12066,6 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios)
return False
return True
def isLoginUser(self, userName):
"""Логинится ли пользователь"""
if self.isExistsLogout(userName):
return False
else:
return True
@adminConnectLdap
def isReplDNExists(self):
"""Существует ли ветка репликации LDAP"""
@ -12468,22 +12471,186 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios)
return False
return True
def maxDateAndListInDir(self, scanDir, listFiles, skipPathTime=[],
checkTime=True, prefix=None, maxTime=None,
flagDir=False):
"""Время последней модификации внутри директории scanDir
Генерация списка файлов и директорий
"""
startCheckTime = checkTime
if not prefix:
prefix = os.path.join(scanDir,"")
if startCheckTime and not maxTime:
maxTime = os.lstat(scanDir)[stat.ST_CTIME]
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]
listFiles.append(relPath)
if startCheckTime is True:
checkTime = True
for skipPath in skipPathTime:
if relPath.startswith(skipPath):
checkTime = False
break
#print absPath
stInfo = os.lstat(absPath)
statInfo = stInfo[stat.ST_MODE]
if stat.S_ISREG(statInfo):
if checkTime:
curTime = stInfo[stat.ST_CTIME]
if curTime>maxTime:
maxTime = curTime
elif stat.S_ISDIR(statInfo):
if checkTime:
curTime = stInfo[stat.ST_CTIME]
if curTime>maxTime:
maxTime = curTime
maxTime = self.maxDateAndListInDir(absPath, listFiles,
skipPathTime, checkTime,
prefix, maxTime, True)
elif stat.S_ISLNK(statInfo):
if checkTime:
curTime = stInfo[stat.ST_CTIME]
if curTime>maxTime:
maxTime = curTime
return maxTime
def setListFilesAndDatesInUserProfiles(self, userName):
"""Устанавливает дату профиля в конфигурационный файл клиента
а также спискок файлов профиля пользователя
"""
listFiles = []
def printErrMessages(error):
"""Печать сообщений о ошибках"""
errors = error.splitlines()
for err in errors:
self.printERROR(err)
resSearchUnix = self.servUnixObj.searchUnixUser(userName)
uid = None
gid = None
if resSearchUnix:
uid = int(resSearchUnix[0][0][1]['uidNumber'][0])
gid = int(resSearchUnix[0][0][1]['gidNumber'][0])
else:
resPasswd = self.servUnixObj.searchPasswdUser(userName)
if resPasswd:
uid = int(resPasswd.split(":")[2])
gid = int(resPasswd.split(":")[3])
if uid == None or gid == None:
print _("User %s not found in Unix service")
return False
linProfDir =\
os.path.join(self.clVars.Get("sr_samba_linprof_path"),
userName)
# Если чистая директория профиля то пропускаем
if not os.listdir(linProfDir):
return True
for relDirProf in os.listdir(linProfDir):
dirProf = os.path.join(linProfDir,relDirProf)
if os.path.isdir(dirProf):
# Находим максимальную дату в каждом профиле пользователя
# и создаем список файлов
listFiles = []
desktopFile = os.path.join(dirProf,self.deskFile)
maxDate = self.maxDateAndListInDir(dirProf,listFiles,
self.skipDatePathsInProfile)
# Записываем список файлов
# calculate/files.txt
listProfFile = os.path.join(dirProf, self.listProfFile)
# Создаем директорию если необходимо
listProfDir = os.path.split(listProfFile)[0]
if not os.path.exists(listProfDir):
os.makedirs(listProfDir)
os.chown(listProfDir,uid,gid)
try:
open(listProfFile,"w").write("\n".join(listFiles))
except:
os.remove(desktopFile)
self.printERROR(_("Can not open %s")%listProfFile)
return False
# Записываем дату профиля в файл .calculate/desktop.env
# Создаем директорию если необходимо
desktopDir = os.path.split(desktopFile)[0]
if not os.path.exists(desktopDir):
os.makedirs(desktopDir)
os.chown(desktopDir,uid,gid)
strDate = time.strftime("%Y-%m-%d %H:%M:%S",
time.localtime(maxDate))
# Изменяем дату профиля
data = {"date":strDate}
objConfig = cl_base.iniParser(desktopFile)
objConfig.setVar("main", data)
error = objConfig.getError()
if error:
printErrMessages(error)
return False
return True
def packUserProfile(self,pathProfile,strArchDate,strCurrentTime,objConfig):
"""Создает инкрементальный архив профиля пользователя
def execLoginUser(self, userName):
с определенной даты"""
# Текущий путь
extSuccess = "gz"
extProcess = "process"
pathProg = os.getcwd()
strCurrentTimeRepl = strCurrentTime.replace(".","_")
prevPath, osShortName = os.path.split(pathProfile)
archPathTmp = os.path.join(prevPath, "profile.%s.%s.tar"\
%(osShortName, strCurrentTimeRepl))
# имя файла архива в процессе архивации
archPathSuccess = "%s.%s"%(archPathTmp,extSuccess)
# имя файла архива - после архивации
archPathProcess = "%s.%s"%(archPathTmp,extProcess)
# Если файлы архивов существует то удаляем их
pathsRemove = (archPathProcess, archPathSuccess)
for rmPath in pathsRemove:
if os.path.exists(rmPath):
os.remove(rmPath)
execStr = 'tar --exclude=.calculate/server.env \
--newer "%s" -czf %s . &>/dev/null'\
%(strArchDate, archPathProcess)
os.chdir(pathProfile)
# Выполняем архивацию
ret = os.system(execStr)
# восстановление текущего пути
os.chdir(pathProg)
# При успешной архивации переименовываем файл архива
if os.path.exists(archPathProcess):
os.rename(archPathProcess, archPathSuccess)
if ret:
self.printERROR(_("Can not create %s")%archPath)
return False
else:
return True
def execLoginUser(self, userName, flagRepl):
"""Действия на сервере при входе пользователя в сеанс"""
if self.isLoginUser(userName):
# Поиск пользователя в Samba сервисе
if not self.servSambaObj.searchSambaUser(userName):
self.printERROR(_("Samba user %s is not found")%str(userName))
return False
# Создаем пользовательские директории на сервере
if not self.createUserDirs(userName):
self.printERROR(_("Can not create user %s directories")\
%str(userName))
return False
self.printSUCCESS(_("User %s login")%userName)
# Поиск пользователя в Samba сервисе
if not self.servSambaObj.searchSambaUser(userName):
self.printERROR(_("Samba user %s is not found")%str(userName))
return False
# Создаем пользовательские директории на сервере
if not self.createUserDirs(userName):
self.printERROR(_("Can not create user %s directories")\
%str(userName))
return False
# В случае репликации
if flagRepl:
# Устанавливаем время модификации профиля в конф. файл
# desktop.env для всех профилей пользователя
# а также получаем список файлов
if not self.setListFilesAndDatesInUserProfiles(userName):
return False
self.printSUCCESS(_("User %s login")%userName)
return True
def execLogoutUser(self, userName, flagRepl):
"""Действия на сервере при выходе пользователя из сеанса"""
@ -12493,76 +12660,151 @@ if %%errorlevel%%==0 NET USE T: \\\\%s\\ftp' %(netbios,netbios,netbios)
for err in errors:
self.printERROR(err)
if not self.isLoginUser(userName):
# Поиск пользователя в Samba сервисе
if not self.servSambaObj.searchSambaUser(userName):
self.printERROR(_("Samba user %s is not found")%str(userName))
return False
# Директория хранения профилей
profileDir = os.path.join(\
self.clVars.Get("sr_samba_linprof_path"), userName)
# получаем директории с self.logOutFile в них
dirsLogOut= self.isExistsLogout(userName)
flagLogOut = True
# Удаляем файлы .logout
for dirLogOut in dirsLogOut:
logoutFile = os.path.join(dirLogOut, self.logOutFile)
retStr = self.deleteLogoutFile(userName, logoutFile)
if not retStr:
self.printERROR(\
_("No access to the file %s")%logoutFile)
def setWorkedUser(userName, dirLogOut, profileDir):
"""Запись пользователя в Worked ветку LDAP"""
if dirLogOut == profileDir:
userLogin = userName
else:
clientOs = os.path.split(dirLogOut)[1].\
replace(".","")
# если есть старый пользователь в ветке
# Worked и клиентская система CLD -
# удаляем старого пользователя
if self.searchWorkedUser(userName) and\
clientOs=="CLD":
# Удаляем пользователя из ветки
# второй параметр False
if not self.delReplWorkedUser(userName,
False):
self.printERROR(_("Can not \
remove user %s in the LDAP branch 'Worked'")%str(userName))
return False
userLogin = "%s@%s"%(userName,clientOs)
# Добавляем пользователя в ветку репликации
if not self.addReplWorkedUser(userLogin):
self.printERROR(_("Can not add user \
%s in LDAP branch 'Replication'")%str(userName))
return False
return True
# Поиск пользователя в Samba сервисе
if not self.servSambaObj.searchSambaUser(userName):
self.printERROR(_("Samba user %s is not found")%str(userName))
return False
# Директория хранения профилей
profileDir = os.path.join(\
self.clVars.Get("sr_samba_linprof_path"), userName)
# получаем директории профилей
dirsLogOut= self.getProfileDirs(userName)
flagLogOut = True
# Удаляем файлы .logout
for dirLogOut in dirsLogOut:
logoutFile = os.path.join(dirLogOut, self.logOutFile)
retStr = self.deleteLogoutFile(userName, logoutFile)
if not retStr:
self.printERROR(\
_("No access to the file %s")%logoutFile)
return False
# Читаем данные из ~/.calculate/desktop.env файла
desktopFile = os.path.join(dirLogOut,self.deskFile)
if os.path.exists(desktopFile):
# Получаем переменные из env файла
txtDskConfig = cl_base.iniParser(desktopFile)
# Статус профиля
profStatus = txtDskConfig.getVar("main","status_sync")
if profStatus:
# Очищаем статус
# txtDskConfig.delVar("main","status_sync")
# Если нет .logout файла или он пуст
if retStr in ("NOFILE", "EMPTY"):
retStr = profStatus.upper()
error = txtDskConfig.getError()
if error:
printErrMessages(error)
return False
if retStr == "SUCCESS":
if retStr == "SUCCESS":
varsPackDict = {}
# Управление сервером
srvFile = os.path.join(dirLogOut,self.srvFile)
if os.path.exists(srvFile):
# Поддерживаемые секции которые не нужно удалять
supportSections = []
# Получим текущую дату
strCurrentTime = time.strftime(\
"%Y-%m-%d %H:%M:%S",time.localtime(time.time()))
# Получаем переменные из env файла
txtConfig = cl_base.iniParser(srvFile)
# Cловарь переменных из файла для изменения пароля
# пользователя
sectionPwd = ["command","passwd_samba"]
varsPwdDict = txtConfig.getAreaVars(sectionPwd)
# Если включена репликация
if flagRepl:
if dirLogOut == profileDir:
userLogin = userName
else:
clientOs = os.path.split(dirLogOut)[1].\
replace(".","")
# если есть старый пользователь в ветке
# Worked и клиентская систем CLD -
# удаляем старого пользователя
if self.searchWorkedUser(userName) and\
clientOs=="CLD":
# Удаляем конкретного пользователя
# второй параметр False
if not self.delReplWorkedUser(userName,
False):
self.printERROR(_("Can not \
remove user %s in the LDAP branch 'Worked'")%str(userName))
# Команда для упаковки профиля
sectionPack = ["command","pack"]
varsPackDict = txtConfig.getAreaVars(sectionPack)
print varsPackDict
error = txtConfig.getError()
if error:
printErrMessages(error)
return False
# Изменение пароля пользователя
if varsPwdDict:
# Если run=on выполняем команду
if varsPwdDict.get("run") == "on":
supportSections.append(",".join(sectionPwd))
if self.changeUserPassword(userName,
varsPwdDict,
srvFile,strCurrentTime):
# Записываем статус - успех
if not self.setDateAndStatusToConfig(\
sectionPwd,
"success",
strCurrentTime,
txtConfig):
return False
userLogin = "%s@%s"%(userName,clientOs)
# Добавляем пользователя в ветку репликации
if not self.addReplWorkedUser(userLogin):
self.printERROR(_("Can not add user \
%s in LDAP branch 'Replication'")%str(userName))
return False
# Управление сервером
envFile = os.path.join(dirLogOut,self.envFile)
if os.path.exists(envFile):
# Получаем переменные из env файла
txtConfig = cl_base.iniParser(envFile)
# Cловарь переменных из файла для изменения пароля
# пользователя
varsPwdDict = txtConfig.getAreaVars(["passwd","samba"])
error = txtConfig.getError()
if error:
printErrMessages(error)
return False
if varsPwdDict:
if not self.changeUserPassword(userName,varsPwdDict,
envFile):
return False
# Удаляем область изменения пароля из
# конфигурационного файла
txtConfig.delArea(["passwd", "samba"])
error = txtConfig.getError()
if error:
printErrMessages(error)
else:
# Записываем статус - ошибка
self.setDateAndStatusToConfig(sectionPwd,
"error",
strCurrentTime,
txtConfig)
return False
self.printSUCCESS(_("User %s logout")%userName)
else:
if set(varsPwdDict.keys()) == set(["date",
"status"]):
supportSections.append(",".join(sectionPwd))
# Упаковка профиля пользователя
if flagRepl and varsPackDict:
# Если run=on выполняем команду
if varsPackDict.get("run") == "on":
# Дата новее которой файлы помещаются в архив
strArchDate = varsPackDict.get("arch_date")
# Текущее время на клинтском компьютере
strCurrentTime = varsPackDict.get("curr_time")
if strArchDate and strCurrentTime:
# Создаем инкрементный архив
if not self.packUserProfile(dirLogOut,
strArchDate,
strCurrentTime,
txtConfig):
return False
# Удаление секций которые не можем отработать
# и секции для создания архива профиля пользователя
sections = txtConfig.getAllSectionNames()
if supportSections:
sections = list(set(sections)-set(["command"]))
sections = set(sections)-set(supportSections)
delSections = map(lambda x: x.split(","), sections)
for delSect in delSections:
txtConfig.delArea(delSect)
# Если включена репликация и нет команды на упаковку
# профиля пользователя
if flagRepl and not varsPackDict:
# Запись пользователя в Worked ветку LDAP
if not setWorkedUser(userName, dirLogOut, profileDir):
return False
self.printSUCCESS(_("User %s logout")%userName)
return True
def execServer(self, options, logObj=False):
@ -12649,7 +12891,7 @@ remove user %s in the LDAP branch 'Worked'")%str(userName))
prnSucces, prnErr = redefinePrintMethods(messages, errMessages)
# Вход пользователя в сеанс
userName = login
if self.execLoginUser(userName):
if self.execLoginUser(userName, flagRepl):
# Восстановление печати успешных сообщений и ошибок
restorePrintMethods(prnSucces, prnErr)
return printSuccessMessages(messages, verboseMode, logObj)
@ -12669,8 +12911,30 @@ remove user %s in the LDAP branch 'Worked'")%str(userName))
restorePrintMethods(prnSucces, prnErr)
return printErrMessages(errMessages, verboseMode, logObj)
def setDateAndStatusToConfig(self, section, status, strDate, objConfig):
"""Устанавливает для секции текущюю дату и статус"""
def printErrMessages(error):
"""Печать сообщений о ошибках"""
errors = error.splitlines()
for err in errors:
self.printERROR(err)
data = {"date":strDate, "status":status}
# Удаляем область из конфигурационного файла
objConfig.delArea(section)
error = objConfig.getError()
if error:
printErrMessages(error)
return False
objConfig.setVar(section, data)
error = objConfig.getError()
if error:
printErrMessages(error)
return False
return True
def changeUserPassword(self, userName, varsDict, confFile):
def changeUserPassword(self, userName, varsDict, confFile, strTime):
"""Изменение пароля пользователя при помощи конфигурационного файла
.calculate.env в домашней директории пользователя

Loading…
Cancel
Save