diff --git a/lib/cl_keys.c b/lib/cl_keys.c index 66501ec..0101051 100644 --- a/lib/cl_keys.c +++ b/lib/cl_keys.c @@ -52,5 +52,8 @@ int clearKey(char *login) buffer = "XXXXXXXX"; key_serial_t dest; dest = KEY_SPEC_USER_SESSION_KEYRING; - return add_key("user", login, buffer, strlen(buffer), dest); -}; \ No newline at end of file + if (add_key("user", login, buffer, strlen(buffer), dest)!=-1) + return 0; + else + return 1; +}; diff --git a/pym/cl_client.py b/pym/cl_client.py index d225924..31bf40b 100644 --- a/pym/cl_client.py +++ b/pym/cl_client.py @@ -31,7 +31,6 @@ import _cl_keys import time import stat import subprocess -import time from encrypt import encrypt from signal import SIGTERM @@ -234,7 +233,7 @@ org.kde.kdialog.ProgressDialog' %(self.kdialog,self.suffixSet, 100)) self.max = max self.kmax = max / 100.0 - + def setTitle(self,title): '''Установить описания прогресса''' @@ -365,6 +364,7 @@ class cl_client(imp_cl_err, imp_cl_xml, imp_cl_help, imp_cl_smcon, encrypt): rootProfilePaths=['/usr/lib/calculate/calculate-client/profiles', '/var/calculate/remote/profiles', '/var/calculate/profiles'] + def __init__(self, cmdName): # объект для форматированного вывода imp_cl_help.__init__(self, cmdName) @@ -584,6 +584,8 @@ conjunction with the 'login' or 'logout'") # используемое для прогрессбара self.configFileDesktop = "desktop.env" self.configFileServer = "server.env" + # Файл - список файлов профиля пользователя + self.listProfFile = ".calculate/files.txt" # Путь относительно домашней директории в котором находятся # конфигурационные файлы self.pathConfig = ".calculate" @@ -599,10 +601,9 @@ conjunction with the 'login' or 'logout'") replBranch = self.replAttr + "=" + self.replBranchName # DN хранения последнего посещенного пользователя self.replHostsDN = self.addDN(replBranch,self.sysDN) - # Файл репликации - self.replLogoutFile = ".logout" + self.logOutFile = ".logout" self.skipHomeFile = ["Home","Disks","FTP", - self.replLogoutFile, + self.logOutFile, os.path.join(self.pathConfig,self.configFileDesktop)] # Если атрибут установлен то значит (ошибка и отмонтируются # пользовательские ресурсы) @@ -923,7 +924,7 @@ conjunction with the 'login' or 'logout'") objConfig = cl_base.iniParser(fileConfig) varsRun = {"run":"on"} varsRun.update(varsCommand) - if not objConfig.setVar(["command", command], varsRun): + if not objConfig.setVar(["command"]+command, varsRun): self.printERROR(_("Can not write variables in file %s")\ %fileConfig) return False @@ -931,6 +932,16 @@ conjunction with the 'login' or 'logout'") os.chown(fileConfig, uid, gid) 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 setUserPasswordToServer(self, options): """Установка пароля пользователя на сервере""" # Проверяем на root @@ -971,9 +982,10 @@ conjunction with the 'login' or 'logout'") if filter(lambda x: not x, varsConfig.values()): return False # ~/.calculate/server.env - fileConfig = os.path.join(os.environ["HOME"], self.pathConfig, + fileConfig = os.path.join(os.environ["HOME"], self.pathConfig, self.configFileServer) - if not self.setServerCommand("passwd_samba", varsConfig, fileConfig): + if not self.setServerCommand(["passwd_samba"], varsConfig, + fileConfig): return False self.printOK(_("Changed password of user %s")%os.environ["USER"] + \ " ...") @@ -1686,7 +1698,8 @@ or ld_bind_dn or ld_bind_pw") # Ищем ключ в ядре if _cl_keys.getKey(userName): # Если нашли очищаем - if _cl_keys.clearKey(userName) == 0: + ret = _cl_keys.clearKey(userName) + if ret == 0: return True else: self.printERROR(_("Can not clear kernel key from user %s")\ @@ -1740,17 +1753,8 @@ or ld_bind_dn or ld_bind_pw") # Файл хранения настроек пакета configFileName = os.path.join(homeDir, self.pathConfig, self.configFileDesktop) - home = os.path.split(homeDir)[0] - pathRemote = [] - # Удаленный ресурс профилей - pathRemote.append((os.path.join(home,"." + userName), "unix")) - # Удаленный ресурс home - pathRemote.append((os.path.join(homeDir,"Home"), "homes")) - # Удаленный ресурс ftp - if self.clVars.Get("cl_remote_ftp"): - pathRemote.append((os.path.join(homeDir,"FTP"), "ftp")) - # Удаленный ресурс share - pathRemote.append((os.path.join(homeDir,"Disks"), "share")) + # Получаем монтируемые директории + names, dictRes = self.getUserMountResources(userName, homeDir, False) if os.path.exists(homeDir): self.moveHomeDir(homeDir) else: @@ -1759,11 +1763,7 @@ or ld_bind_dn or ld_bind_pw") self.printERROR(_("Directory %s not found") % homeDir) return False # Синхронизируем настройки - pathUnix = "" - for path, res in pathRemote: - if res == 'unix': - pathUnix = path - break + pathUnix = dictRes["profile"]["path"] if pathUnix and self.isMount(pathUnix ,"cifs") and \ not(domain in self.isMount(pathUnix ,"cifs")): # Убиваем rsync @@ -1795,7 +1795,6 @@ or ld_bind_dn or ld_bind_pw") return False # проверяем произведен ли корректный вход в систему - # в этом случае закачиваем профиль с локальной машины на сервер - logOutFile = os.path.join(homeDir,self.replLogoutFile) # необходима ли синхронизация с локальным сервером needSync = False try: @@ -1803,12 +1802,12 @@ or ld_bind_dn or ld_bind_pw") # то на локальный сервер закачиваем профиль # так как даже если он будет поврежден на другом сервере # остаётся правильная копия - if not self.isCorrectProfileOnLocalServer(userName): + if self.getNameRemoteServer(userName): needSync = True else: exitStr = cl_base.iniParser(\ - configFileName).getVar('main','status') - # проверяем logOutFile: не содержит ли он "process" + configFileName).getVar('main','status_sync') + # проверяем cтатус синхронизации: не содержит ли он "process" if exitStr != "process": needSync = True except: @@ -1821,8 +1820,10 @@ or ld_bind_dn or ld_bind_pw") # Отмонтируем пользовательские ресурсы в случае ошибки self.errorAndUnmountUserRes = True return False - - if needSync and not self.syncUser(userName,homeDir,"logout",uid,gid): + osLinuxShort = self.clVars.Get("os_linux_shortname") + homeProfile = os.path.join(pathUnix, osLinuxShort) + if needSync and not self.syncUser(userName, homeDir,"logout",uid,gid, + homeProfile): # Удаляем файлы, мешающие работе dm self.removeNoiseFiles(homeDir) # Удаляем приватные файлы @@ -1839,7 +1840,9 @@ or ld_bind_dn or ld_bind_pw") # Очищаем ключ в ядре self.clearUserKey(userName) flagError = False - for path, res in pathRemote: + # Отмонтируем директории + for name in names: + path = dictRes[name]["path"] if self.isMount(path ,"cifs"): textLine = self.umountSleepPath(path) if not textLine: @@ -1900,20 +1903,14 @@ or ld_bind_dn or ld_bind_pw") else: homeDir = resLdap[5] home = os.path.split(homeDir)[0] - pathRemote = [] - # Удаленный ресурс профилей - pathRemote.append((os.path.join(home,"." + userName), "unix")) - # Удаленный ресурс home - pathRemote.append((os.path.join(homeDir,"Home"), "homes")) - # Удаленный ресурс ftp - if self.clVars.Get("cl_remote_ftp"): - pathRemote.append((os.path.join(homeDir,"FTP"), "ftp")) - # Удаленный ресурс share - pathRemote.append((os.path.join(homeDir,"Disks"), "share")) + # Получаем монтируемые директории + names, dictRes = self.getUserMountResources(userName, homeDir, True) + serverHomePath = dictRes["home"]["path"] flagError = False - if self.isMount(pathRemote[1][0] ,"cifs"): + if self.isMount(serverHomePath, "cifs"): self.moveHomeDir(homeDir) - for path, res in pathRemote: + for name in names: + path = dictRes[name]["path"] if self.isMount(path ,"cifs"): textLine = self.umountSleepPath(path) if not textLine: @@ -2016,9 +2013,8 @@ or ld_bind_dn or ld_bind_pw") os.rmdir(rmDir) return True - def isCorrectProfileOnLocalServer(self,userName): - """Узнать находится ли актуальный профиль пользователя на локальном - сервере + def getNameRemoteServer(self,userName): + """Если профиль на удаленном сервере, то выдать DNS имя этого сервера """ searchPrevHost = self.searchPrevHost(userName) if searchPrevHost and searchPrevHost[0][0][1].has_key('host'): @@ -2028,15 +2024,16 @@ or ld_bind_dn or ld_bind_pw") # если местоположение актуального профиля найти не удалось # или его местоположение не на локальном сервере if not prevHost or prevHost == self.clVars.Get('cl_remote_host'): - return True - else: return False + else: + return prevHost - def setCurrentVersionToConfig(self, configFileName, uid, gid): + def setDateAndVersionToConfig(self, configFileName, uid, gid, strTime): """Записывает текущую версию в файл конфигурации""" # Текущая версия программы currentVersion = self.clVars.Get("cl_ver") - if self.setVarToConfig("main", {"version":currentVersion}, + if self.setVarToConfig("main", {"version":currentVersion, + "date":strTime}, configFileName, uid, gid): return True self.printERROR(_("can not write the version number in the file %s")\ @@ -2075,6 +2072,248 @@ or ld_bind_dn or ld_bind_pw") os.remove(delFile) return True + 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,"Disks")} + 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.clVars.Get("cl_remote_ftp"): + # Ресурс 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 syncLoginProfile(self, userName, homeDir, homeProfile, uid, gid, + progress, flagClearHomeDir=True): + """Синхронизация профиля пользователя с сервера + в переменной 'cl_remote_host' хост для прогрессбара + """ + home = os.path.split(homeDir)[0] + # Если на текущем сервере в ресурсе unix есть файлы + # то синхронируем настройки + if os.listdir(homeProfile): + if not self.syncUser(userName, homeDir, "login", uid, gid,\ + homeProfile, progress=progress, + host=self.clVars.Get('cl_remote_host')): + return False + else: + if flagClearHomeDir: + # Удаляем ненужные файлы (очищаем домашнюю директорию) + if not self.clearHomeDir(homeDir): + return False + 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 unpackProfile(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() + #ret = os.system(execStr) + if ret: + self.printERROR(_("Can not execute %s") %execStr) + self.printERROR(_("Can not unpack %s") %archFile) + return False + 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 getListFilesProfile(self, homeDir): + """Генерация списка файлов в домашней директориии + + Исключая монтируемые директории + """ + home = os.path.join(homeDir, "") + execStr = "mount" + textLines = self.execProg(execStr,False,False) + # Пропускаемые директории для сканирования + 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 removeFilesInProfile(self, homeDir, pathListFile): + """Удаляем файлы которых нет в профиле пользователя""" + # Получаем файлы профиля на сервере + try: + filesProfileTxt = open(pathListFile).read() + except: + self.printERROR(_("Can not open %s")%pathListFile) + return False + listFilesProfile = filter(lambda x: x.strip(), + filesProfileTxt.split("\n")) + filesProfile = set(listFilesProfile) + # Получаем файлы в домашней директории + listFilesHome = self.getListFilesProfile(homeDir) + if listFilesHome is False: + return False + filesHome = set(listFilesHome) + filesRemove = list(filesHome - filesProfile) + 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.isdir(rmPath): + os.rmdir(rmPath) + elif os.path.isfile(rmPath): + os.remove(rmPath) + elif os.path.islink(rmPath): + os.unlink(rmPath) + else: + os.remove(rmPath) + except: + self.printERROR(_("Can nor remove %s")%rmPath) + return False + return True + + 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=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 mountUserRes(self, userName, sync=True, progress=False): """Монтирование пользовательских ресурсов и синхронизация настроек""" # Имя пользователя @@ -2126,11 +2365,8 @@ or ld_bind_dn or ld_bind_pw") os.chown(homeDir,uid,gid) os.chmod(homeDir,0700) # записываем в конфигурационный файл статус "в процессе" - self.setVarToConfig("main", {"status":"process"}, - configFileName, uid, gid) - # записываем в .logout файл статус "в процессе" - logOutFile = os.path.join(homeDir,self.replLogoutFile) - self.createUserFile(logOutFile,"PROCESS", uid, gid) + self.setVarToConfig("main", {"status_sync":"process"}, + configFileName, uid, gid) # Получаем пароль пользователя из ключей ядра userPwd = _cl_keys.getKey(userName) if not userPwd: @@ -2138,239 +2374,279 @@ or ld_bind_dn or ld_bind_pw") # Отмонтируем пользовательские ресурсы в случае ошибки self.errorAndUnmountUserRes = True return False - home = os.path.split(homeDir)[0] - pathRemote = [] - # Удаленный ресурс share - pathRemote.append((os.path.join(homeDir,"Disks"), "share")) - # Удаленный ресурс профилей - pathRemote.append((os.path.join(home,"." + userName), "unix")) - # Удаленный ресурс home - pathRemote.append((os.path.join(homeDir,"Home"), "homes")) - if self.clVars.Get("cl_remote_ftp"): - # Удаленный ресурс ftp - pathRemote.append((os.path.join(homeDir,"FTP"), "ftp")) + # Флаг ошибки flagError = False + # Имя удаленного сервера + remoteServer = "" # В случае включения репликации на сервере True replOn = self.searchReplBranch() + if replOn: + remoteServer = self.getNameRemoteServer(userName) + # Получаем монтируемые директории + names, dictRes = self.getUserMountResources(userName, homeDir, + remoteServer) # Путь к профилю пользователя по умолчанию defaultPath = "" # Хост пользователя по умолчанию defaultHost = self.clVars.Get("cl_remote_host") - for path, res in pathRemote: - # Создаем директории для монтирования - 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 - # Проверяем на монтирование директории - if self.isMount(path, 'cifs'): - continue - # Создаем директории пользователя - # на текущем сервере - if replOn and res=="unix": - defaultPath = path - # Монтируем Samba ресурс - textLine = self.mountSambaRes(userName,userPwd,uid,gid,res,path) - if not (textLine is None): - self.printERROR(_("Can not mount Samba resource [%s]")\ - %res + " ...") - flagError = True - break - if flagError: - # Отмонтируем пользовательские ресурсы в случае ошибки - self.errorAndUnmountUserRes = True - return False - flagFirstSync = False - if replOn or sync: - # Ошибка при монтировании unix ресурса удаленного сервера при - # включенной репликации - replErrorMount = False - # Ошибка при cинхронизации unix ресурса удаленного сервера при - # включенной репликации - replErrorSync = False - # Синхронизируем настройки - if sync: - # Короткое имя системы - osLinuxShort = self.clVars.Get("os_linux_shortname") - # В случае репликации + # Флаг - будет использован инкрементальный архив + flagIncrArch = True + + # Ошибка при монтировании удаленного сервера + flagErrorMountRemote = False + # Ошибка при cинхронизации с удаленного сервера + flagErrorSyncRemote = False + # Статус синхронизации + syncStatus = True + osLinuxShort = self.clVars.Get("os_linux_shortname") + + # Если профиль на удаленном сервере + if remoteServer and replOn: + # имя файла архива в процессе архивации + archPathProcess = "" + # имя файла архива - после архивации + archPathSuccess = "" + # Создаем инкрементальный архив в случае репликации prevHost = "" - # Монтирование по умолчанию (default - cвой сервер, remote - чужой) - mountServer = "" - if replOn: - searchPrevHost = self.searchPrevHost(userName) - if searchPrevHost and searchPrevHost[0][0][1].has_key('host'): - prevHost = searchPrevHost[0][0][1]['host'][0] - # Монтируем ресурс unix текущего сервера - mountServer = "default" - # Переносим настройки пользователя в новую директорию - # CLD - if not self.upgradeProfileClient(userName, homeDir): - # Отмонтируем пользовательские ресурсы в случае ошибки - self.errorAndUnmountUserRes = True - return False - # Если на текущем сервере в ресурсе unix есть файлы - # то синхронируем настройки - # Получаем директорию хранения профиля на сервере - homeProfile = os.path.join(home, "." + userName, osLinuxShort) - if os.listdir(homeProfile): - # Конфигурационный файл клинта на сервере desktop.env - configFileNameServer = os.path.join(homeProfile, - self.pathConfig, - self.configFileDesktop) - # Пишем версию клиента на сервер - if not self.setCurrentVersionToConfig(configFileNameServer, - uid,gid): - # Отмонтируем пользовательские ресурсы в случае ошибки - self.errorAndUnmountUserRes = True - return False - if not self.syncUser(userName, homeDir, "login", uid, gid,\ - progress=progress, - host=self.clVars.Get('cl_remote_host')): - # Отмонтируем пользовательские ресурсы в случае ошибки - self.errorAndUnmountUserRes = True - return False - else: - # Удаляем ненужные файлы (очищаем домашнюю директорию) - if not self.clearHomeDir(homeDir): - self.errorAndUnmountUserRes = True - return False - if prevHost and prevHost != self.clVars.Get("cl_remote_host"): - # Отмонтируем ресурс - textLine = self.umountSleepPath(defaultPath) + # Дата профиля на текущем сервере + dateDefaultProfile = "" + # Текущее время + currTime = str(float(time.time())) + # Создаваемые пути при монтировании + 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 + #Проверяем на монтирование директории + if self.isMount(path, 'cifs'): + continue + # Монтируем Samba ресурс + if name == "remote_profile": + self.clVars.Set("cl_remote_host", remoteServer, True) + textLine = self.mountSleepRes(userName,userPwd,uid,gid, + res,path) + if name == "remote_profile": + self.clVars.Set("cl_remote_host", defaultHost, True) + if not (textLine is None): + if name == "remote_profile": + flagErrorMountRemote = True + break + else: + self.printERROR(_("Can not mount Samba resource [%s]")\ + %res + " ...") + flagError = True + break + if name == "profile" or name == "remote_profile": + # Находим директорию профиля + homeProfile = os.path.join(path, osLinuxShort) + if not os.path.exists(homeProfile): + homeProfile = os.path.join(path, "." + osLinuxShort) + # Примонтирована директория профиля с текущего сервера + if name == "profile": + # Перенос профиля на сервере в директорию без точки + if not self.upgradeProfileClient(userName, homeDir, + path): + flagError = True + break + fileConfig = os.path.join(homeProfile, + self.pathConfig, + self.configFileDesktop) + if os.path.exists(fileConfig): + objConfig = cl_base.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": + dateDefaultProfile = date + # Примонтирована директория профиля с удаленного сервера + # и есть дата профиля текущего сервера + if name == "remote_profile" and dateDefaultProfile: + # Даем команду на создание инкрементального архива проф. + fileConfig = os.path.join(homeProfile, + self.pathConfig, + self.configFileServer) + varsConfig = {"arch_date":dateDefaultProfile, + "curr_time":currTime} + self.setServerCommand(["pack"], varsConfig, fileConfig) + # Отмонтируем директорию профиля с удаленного сервера + textLine = self.umountSleepPath(path) if not textLine: - # Отмонтируем пользовательские ресурсы в случае ошибки - self.errorAndUnmountUserRes = True - return False - # Монтируем настройки пользователя удаленного сервера - # если сервер найден - self.clVars.Set("cl_remote_host", prevHost, True) - mountServer = "remote" + flagError = True + break + pathProfileCurr = dictRes["profile"]["path"] + homeProfileCurr = os.path.join(pathProfileCurr,osLinuxShort) + # Синхронизация профиля с текущего сервера + if not self.syncLoginProfile(userName,homeDir, + homeProfileCurr, + uid, gid, progress): + flagError = True + break + # Монтируем директорию профиля с удаленного сервера + self.clVars.Set("cl_remote_host", remoteServer, True) textLine = self.mountSleepRes(userName,userPwd,uid,gid, - "unix",defaultPath) + res,path) self.clVars.Set("cl_remote_host", defaultHost, True) if not (textLine is None): - if self.isMount(defaultPath, 'cifs'): - textLine = self.umountSleepPath(defaultPath) - if not textLine: - # Отмонтируем пользовательские ресурсы - # в случае ошибки - self.errorAndUnmountUserRes = True - return False - # Монтируем текущий сервер если ошибка подключения к - # к найденному серверу - mountServer = "default" - textLine = self.mountSleepRes(userName,userPwd,uid,gid, - "unix",defaultPath) - if not (textLine is None): - self.printERROR(_("Can not mount Samba resource \ -[%s]")%"unix" + " ...") - # Отмонтируем пользовательские ресурсы - # в случае ошибки - self.errorAndUnmountUserRes = True - return False - replErrorMount = True - if mountServer == "remote": - # Переносим настройки пользователя в новую директорию - # CLD - if not self.upgradeProfileClient(userName, homeDir): - # Отмонтируем пользовательские ресурсы в случае ошибки - self.errorAndUnmountUserRes = True - return False - # Получаем директорию хранения профиля на сервере - homeProfile = os.path.join(home, "." + userName, - osLinuxShort) - if os.listdir(homeProfile): - # Конфигурационный файл клинта на сервере - # desktop.env - configFileNameServer = os.path.join(homeProfile, - self.pathConfig, - self.configFileDesktop) - # Пишем версию клиента на сервер - if not self.setCurrentVersionToConfig(\ - configFileNameServer, - uid,gid): - # Отмонтируем пользовательские ресурсы в случае ошибки - self.errorAndUnmountUserRes = True - return False - if not self.syncUser(userName,homeDir,"login", - uid,gid, progress=progress, - host=prevHost): - replErrorSync = True - else: - # Удаляем ненужные файлы (очищаем домашнюю директорию) - if not self.clearHomeDir(homeDir): - self.errorAndUnmountUserRes = True - return False - # Перемонтируем ресурс профилей - # на текущий сервер - textLine = self.umountSleepPath(defaultPath) - if not textLine: - # Отмонтируем пользовательские ресурсы в случае ошибки - self.errorAndUnmountUserRes = True - return False - textLine = self.mountSambaRes(userName,userPwd,uid,gid, - "unix",defaultPath) - if not (textLine is None): - self.printERROR(_("Can not mount Samba resource [%s]")\ - %"unix" + " ...") - # Отмонтируем пользовательские ресурсы в случае ошибки - self.errorAndUnmountUserRes = True - return False - # если репликации нет - else: - curHost=self.clVars.Get('cl_remote_host') - # Синхронизируем настройки пользователя + 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: + # Распаковываем архив в домашнюю директорию + if not self.unpackProfile(homeDir, archPathSuccess, + progress, remoteServer): + flagError = True + break + # Cканирование домашней директории и получение списка + # файлов + pathListFile = os.path.join(homeProfile, + self.listProfFile) + self.removeFilesInProfile(homeDir, pathListFile) + else: + if name == "remote_profile": + flagIncrArch = False + if archPathProcess or archPathSuccess: + # Удаление архивных файлов + rmFiles = [archPathProcess, archPathSuccess] + for rmFile in rmFiles: + if os.path.exists(rmFile): + # Удаляем файл архива + os.remove(archPathSuccess) + # Если не удалось замонтировать удаленный профиль + if flagErrorMountRemote: + syncStatus = False + # Если не удалось использовать инкрементальный архив + elif flagIncrArch is False: + # Синхронизируем удаленный профиль + homeProfile = os.path.join(dictRes["remote_profile"]["path"], + osLinuxShort) + if not self.upgradeProfileClient(userName, homeDir, + homeProfile): + + # Отмонтируем пользовательские ресурсы в случае ошибки + self.errorAndUnmountUserRes = True + return False + # Синхронизация профиля с удаленного сервера + self.clVars.Set("cl_remote_host", remoteServer, True) + ret = self.syncLoginProfile(userName, homeDir, homeProfile, + uid, gid, progress, False) + self.clVars.Set("cl_remote_host", defaultHost, True) + if not ret: + flagErrorSyncRemote = True + syncStatus = False + # Если не удалось синхронизировать удаленный синхронизируем + # текущий + homeProfile = os.path.join(dictRes["profile"]["path"], + osLinuxShort) + if not self.syncLoginProfile(userName, homeDir, homeProfile, + uid, gid, progress): + # Отмонтируем пользовательские ресурсы в случае ошибки + self.errorAndUnmountUserRes = True + return False - # Переносим настройки пользователя в новую директорию - # CLD - if not self.upgradeProfileClient(userName, homeDir): + # Отмонтируем директорию профиля пользователя на удаленном сервере + if "remote_profile" in dictRes: + umountPath = dictRes["remote_profile"]["path"] + textLine = self.umountSleepPath(umountPath) + if not textLine: # Отмонтируем пользовательские ресурсы в случае ошибки self.errorAndUnmountUserRes = True return False - # Получаем директорию хранения профиля на сервере - homeProfile = os.path.join(home, "." + userName, osLinuxShort) - if os.listdir(homeProfile): - # Конфигурационный файл клинта на сервере desktop.env - configFileNameServer = os.path.join(homeProfile, - self.pathConfig, - self.configFileDesktop) - # Пишем версию клиента на сервер - if not self.setCurrentVersionToConfig(configFileNameServer, - uid,gid): + # Удаляем директорию удаленного профиля у клиента + if os.path.exists(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 + # Проверяем на монтирование директории + if self.isMount(path, 'cifs'): + continue + textLine = self.mountSleepRes(userName,userPwd,uid,gid, + res, path) + if not (textLine is None): + self.printERROR(_("Can not mount Samba resource [%s]")\ + %res + " ...") + flagError = True + break + if name == "profile": + pathProfile = path + # Перенос профиля на сервере в директорию без точки + if not self.upgradeProfileClient(userName, homeDir, + pathProfile): + flagError = True + break + # Директория профиля + homeProfile = os.path.join(path, osLinuxShort) + # Синхронизируем + if not self.syncLoginProfile(userName, homeDir, homeProfile, + uid, gid, progress): # Отмонтируем пользовательские ресурсы в случае ошибки self.errorAndUnmountUserRes = True return False - if not self.syncUser(userName, homeDir, "login", uid, gid,\ - progress=progress,host=curHost): - # Отмонтируем пользовательские ресурсы - # в случае ошибки - self.errorAndUnmountUserRes = True - return False - else: - # Удаляем ненужные файлы (очищаем домашнюю директорию) - if not self.clearHomeDir(homeDir): - self.errorAndUnmountUserRes = True - return False - if replOn: - if replErrorMount or replErrorSync: - self.createUserFile(logOutFile,"ERROR", uid, gid) - self.setVarToConfig("main", {"status":"error"}, - configFileName, uid, gid) - else: - self.setVarToConfig("main", {"status":"success"}, + + if flagError: + # Отмонтируем пользовательские ресурсы в случае ошибки + self.errorAndUnmountUserRes = True + return False + + logOutFile = os.path.join(homeDir,self.logOutFile) + if syncStatus: + self.setVarToConfig("main", {"status_sync":"success"}, configFileName, uid, gid) - self.createUserFile(logOutFile,"SUCCESS", uid, gid) + self.createUserFile(logOutFile,"SUCCESS", uid, gid) else: - self.setVarToConfig("main", {"status":"success"}, + self.createUserFile(logOutFile,"ERROR", uid, gid) + self.setVarToConfig("main", {"status_sync":"error"}, configFileName, uid, gid) - self.createUserFile(logOutFile,"SUCCESS", uid, gid) - + self.printWARNING(_("Error in sync with the remote server %s")\ + %remoteServer) self.printSUCCESS(_("Mounted user resource of the domain")) self.printOK(_("Get a user profile from the domain") + " ...") return True @@ -2499,7 +2775,7 @@ or ld_bind_dn or ld_bind_pw") return False return True - def upgradeProfileClient(self, userName, userHome): + def upgradeProfileClient(self, userName, userHome, pathProfiles): """Переносит данные клиента в директорию без точки например: было /home/.user/.CLD стало /home/.user/CLD @@ -2508,7 +2784,6 @@ or ld_bind_dn or ld_bind_pw") """ # Директория хранения старых профилей home = os.path.split(userHome)[0] - pathProfiles = os.path.join(home, "." + userName) if os.path.exists(pathProfiles): osLinuxShort = self.clVars.Get("os_linux_shortname") pathNewProfile = os.path.join(pathProfiles, osLinuxShort) @@ -2529,19 +2804,13 @@ or ld_bind_dn or ld_bind_pw") os.rmdir(pathOldProfile) return True - def syncUser(self, userName, userHome, sync, uid, gid, progress=False,\ - host="default"): + def syncUser(self, userName, userHome, sync, uid, gid, homeProfile, \ + progress=False, host="default"): """Синхронизация пользовательских настроек Перед вызовом этого метода обязательно должен быть определен атрибут объекта self.clVars - объект переменных """ - home = os.path.split(userHome)[0] - osLinuxShort = self.clVars.Get("os_linux_shortname") - homeProfile = os.path.join(home, "." + userName, osLinuxShort) - if not os.path.exists(homeProfile): - homeProfile = os.path.join(home, "." + userName, - "." + osLinuxShort) flagError = False execStr = "" if sync == "login":