Добавлена поддержка ssh+rsync для синхронизации профиля

legacy27 3.6.9
parent 6887f7bc5f
commit fb8a68f4ed

@ -30,7 +30,7 @@ from calculate.lib.cl_ini_parser import iniParser
from calculate.lib.cl_print import color_print
from calculate.lib.utils.ip import Pinger, IPError
from calculate.lib.utils.files import (getModeFile, removeDir,
pathJoin, tarLinks, readFile,
pathJoin, tarLinks, readFile, writeFile,
listDirectory, process, find, STDOUT,
checkUtils)
from calculate.lib.utils.samba import Samba, SambaError
@ -44,6 +44,7 @@ from shutil import copy2
from socket import gethostbyname
import tarfile
from calculate.desktop.desktop import Desktop
from calculate.client.rsync import ProfileSyncer, ProfileSyncerError
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
@ -1298,3 +1299,132 @@ class Client(commandServer, encrypt, Desktop):
return False
return False
return res
def get_syncer(self, remotehost, user, pwd):
return ProfileSyncer(remotehost, 2009, user, pwd)
def checkSync(self, remotehost):
status = self.get_syncer(remotehost, None, None).check()
self.clVars.Set('cl_client_rsync_profile_set',
"on" if status else "off",
force=True)
return status
def syncLoginProfileNew(self, host, username, pwd,
uid, gid, homeDir,
profileName, clearHomeDir=True):
"""
Получить профиль пользователя из домена
"""
ps = self.get_syncer(host, username, pwd)
# if currect server has any files then sync it
remoteProfile = "::profile/{}".format(profileName)
if not self.syncUserNew(ps, uid, gid, homeDir, "login",
remoteProfile, host=host):
if re.search(r'\[sender\] change_dir "{resPath}" \(in {resName}\) '
'failed: No such file or directory'.format(
resPath=profileName,
resName="profile"), ps.output):
if clearHomeDir:
# clean home directory
if not self.clearHomeDir(homeDir):
return False
return True
else:
self.printERROR(ps.output)
self.printERROR(_("Failed to execute rsync"))
return False
return True
def syncLogoutProfileNew(self, host, username, pwd,
uid, gid, homeDir,
profileName, skipList):
"""
Закачать профиль пользователя в домен
"""
skipList = [os.path.relpath(x, homeDir) for x in skipList]
ps = self.get_syncer(host, username, pwd)
# if currect server has any files then sync it
remoteProfile = "::profile/{}".format(profileName)
if listDirectory(homeDir):
with writeFile(os.path.join(homeDir,".logout")) as f:
f.write("SUCCESS")
if not self.syncUserNew(ps, uid, gid, homeDir, "logout",
remoteProfile, host=host, skipList=skipList):
self.printERROR(ps.output)
self.printERROR(_("Failed to execute rsync"))
return False
return True
def syncUserNew(self, ps, uid, gid, userHome, sync,
remoteProfile,
host="default", skipList=()):
"""
Синхронизация профиля пользователя
"""
execStr = ""
skipPaths = self.clVars.Get("cl_sync_skip_path")
if not skipPaths:
self.printERROR(
_("Variable 'cl_sync_skip_path' empty") % userHome)
return False
deletePaths = self.clVars.Get("cl_sync_del_path")
if not deletePaths:
deletePaths = []
excludePaths = ['--exclude=/%s'% x
for x in skipPaths + deletePaths + list(skipList)
if x not in {".logout"} ]
rsyncParams = []
if sync == "login":
if os.path.exists(userHome):
filterPath = ['--filter=P /%s'% x for x in skipPaths
if x not in {".logout"}
]
rsyncParams = ['--delete-excluded',
'--delete'] + excludePaths + filterPath + [
'-rlptgo', '-x'
]
source, target = remoteProfile, userHome
elif sync == "logout":
if os.path.exists(userHome) and os.listdir(userHome):
rsyncParams = ['--delete-excluded',
'--delete'] + excludePaths + [
'-rlpt', '-x'
]
source, target = userHome, remoteProfile
else:
raise ClientError(
_("Method syncUser: wrong option sync=%s") % str(sync))
if rsyncParams:
host = "<i>" + host + "</i>"
if sync == "login":
title = _("Fetching the user profile from %s") % host
elif sync == "logout":
title = _("Uploading the user profile to %s") % host
self.startTask(title)
self.addProgress()
for i in ps.sync("%s/"%source, "%s/"%target, *rsyncParams):
self.setProgress(i)
pathConfig = os.path.join(userHome,
self.pathConfig)
try:
if iniParser(configFileName).setVar(
'rsync', {'exitcode': rsync.getExitCode()}):
os.chmod(configFileName, 0600)
os.chown(configFileName, uid, gid)
except Exception:
pass
if ps.exitstatus != 0:
return False
# change permissions
changeDirs = [userHome]
for changeDir in filter(path.exists, changeDirs):
# get directory permissions
mode = getModeFile(changeDir, mode="mode")
# if permission wrong( not 0700) then change it
if mode != 0700:
os.chmod(changeDir, 0700)
self.endTask()
return True

@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
# Copyright 2010-2016 Mir Calculate. 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.
import pexpect
import sys
import os
import tempfile
from calculate.lib.utils.ip import check_port
from calculate.lib.utils.files import readFile
class ProfileSyncerError(Exception):
pass
class ProfileSyncer(object):
def __init__(self, hostname, port, username, passwd):
self.hostname = hostname
self.port = port
self.username = username
self.passwd = passwd
self.exitstatus = None
def check(self):
return check_port(self.hostname, self.port)
def create_process(self, source, target, *params):
self.process = pexpect.spawn('/usr/bin/rsync',
['--rsh=/usr/bin/ssh -o "ControlMaster no" -p{port} {username}@{hostname}'.format(
port=self.port, hostname=self.hostname, username=self.username),
'--info=progress2'] + list(params) + [source, target])
def readfile(self, filename):
tmp_fn = tempfile.mktemp()
for i in self.sync(filename, tmp_fn):
pass
if self.exitstatus == 0:
data = readFile(tmp_fn)
if os.path.exists(tmp_fn):
os.unlink(tmp_fn)
return data
raise ProfileSyncerError("Profile server not found")
def exists(self, filename):
env = dict(os.environ)
env["LANG"] = "C"
self.process = pexpect.spawn('/usr/bin/rsync',
['--rsh=/usr/bin/ssh -o "ControlMaster no" -p{port} {username}@{hostname}'.format(
port=self.port, hostname=self.hostname, username=self.username),
'--list-only',
filename], env=env)
i = self.process.expect(['[Pp]assword', '(\d+)%', pexpect.EOF])
if i == 0:
self.process.sendline("{}\n".format(self.passwd))
self.process.wait()
data = self.process.read()
self.process.close()
return "No such file or directory (2)" not in data
def sync(self, source, target, *params):
num = -1
self.create_process(source, target, *params)
while True:
i = self.process.expect(['[Pp]assword', '(\d+)%', pexpect.EOF])
if i == 0:
self.process.sendline("{}\n".format(self.passwd))
elif i == 1:
newnum = int(self.process.match.group(1))
if newnum > num:
num = newnum
yield newnum
else:
self.output = self.process.before
self.process.close()
self.exitstatus = self.process.exitstatus
yield 100
break

@ -16,7 +16,7 @@
import sys
from os import path
from calculate.core.server.func import Action, Tasks
from calculate.core.server.func import Action, Tasks, AllTasks
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
from calculate.lib.utils.files import FilesError
from calculate.desktop.desktop import DesktopError
@ -42,69 +42,14 @@ class ClClientSyncLoginAction(Action):
failedMessage = None
interruptMessage = __("Synchronization manually interrupted")
tasks = [
# подключить удаленный ресурс домена
{'name': 'mount_remote',
'method': 'Client.mountRemoteRes(cl_remote_pw,cl_client_remote_path,'
'cl_remote_host)',
'condition': lambda Get: (Get('cl_remote_host') and
Get('os_remote_auth') and
not isMount(Get('cl_client_remote_path'))),
},
# check on domain user
{'name': 'domain_user',
'condition': lambda Get: (Get('os_remote_auth') and
Get('cl_remote_host') and
Get('desktop.ur_domain_set') == 'on'),
'else_message': __("The local profile will be used")
},
{'name': 'domain_user:create_home',
'message': __("Creating the home directory for {ur_login}"),
'method': 'Client.createUserDirectory(ur_home_path,ur_uid,'
'ur_gid)',
'condition': lambda Get: not path.exists(Get('ur_home_path'))
},
# password in kernel key
{'name': 'domain_user:check_password',
'condition': lambda Get: Get('desktop.ur_password'),
'else_error': __("User password not found")
},
{'name': 'ecryptfs',
'message': __("Mounting encrypted data"),
'method': 'Desktop.createCryptDir(ur_login,ur_uid,ur_gid,'
'ur_home_path,True)',
'condition': lambda Get: (Get('desktop.ur_home_crypt_set') == 'on' and
Get('install.cl_autologin') != Get(
'ur_login'))
},
{'name': 'domain_user:add_to_cache',
'essential': False,
'method': 'Client.cAddUserToCache(ur_login,desktop.ur_password)',
'failed_warning': __("Unable to cache user info")
},
old_sync = [
# подключить удаленные ресурсы пользователя
{'name': 'domain_user:mount_resources',
{'name': 'domain_sync:mount_resources',
'message': __("Mounting user resources"),
'method': 'Client.mountUserDomainRes(ur_login,'
'desktop.ur_password,'
'ur_uid,ur_gid,"unix","share","homes","ftp")',
},
# проверка на попытку открыть вторую сессию для этого пользователя
{'name': 'two_session',
'error':
__("A second X session cannot be opened for user {ur_login}."),
'condition': lambda dv: (dv.Get('ur_login') in
dv.Get('desktop.cl_desktop_online_user') and
int(dv.Select(
'desktop.cl_desktop_online_count',
where='desktop.cl_desktop_online_user',
eq=dv.Get('ur_login'), limit=1) > 1) and
dv.Get('cl_client_sync') == 'on')
},
{'name': 'domain_user:domain_sync',
'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"process")',
'condition': lambda Get: Get('cl_client_sync') == 'on'
},
# подключить профиль пользователя на удаленном домене
# если на нем находится актуальный профиль
{'name': 'domain_sync:repl_profile',
@ -221,26 +166,154 @@ class ClClientSyncLoginAction(Action):
(Tasks.hasnot('domain_sync') & Tasks.failed()) |
Tasks.failed_one_of('mount_resources', 'two_session')
},
]
new_sync = [
# подключить удаленные ресурсы пользователя
{'name': 'domain_sync2:mount_resources2',
'message': __("Mounting user resources"),
'method': 'Client.mountUserDomainRes(ur_login,'
'desktop.ur_password,'
'ur_uid,ur_gid,"share","homes","ftp")',
},
# монтируем профиль локального домена, если локальный профиль
# старее удаленного доменного или актуальный профиль
{'name': 'domain_sync2:mount_local2',
# нет более ранних ошибок и локальный профиль нуждается
# в синхронизации с удаленным или профиль на локальном домене
'depend': Tasks.success_all('mount_resources2')
},
# синхронизируем с профилем локального домена
{'name': 'mount_local2!:sync_local2',
'method': 'Client.syncLoginProfileNew(cl_remote_host,ur_login,desktop.ur_password,ur_uid,'
'ur_gid,ur_home_path,cl_client_profile_name)',
},
# ошибка синхронизации с локальным доменом
{'name': 'local_sync_error',
'warning': __(
"Error synchronizing with the local server {cl_remote_host}"),
'depend': Tasks.failed_one_of("mount_local2", "sync_local2")
},
{'name': 'sync_local2:sync_remote2',
'method': 'Client.syncLoginProfileNew(cl_replication_host,ur_login,desktop.ur_password,ur_uid,'
'ur_gid,ur_home_path,cl_client_profile_name)',
'condition': lambda Get: Get('cl_replication_host')
},
# если синхронизация с удаленным доменом прошла с ошибкой
# синхронизировать локальный профиль с локальным доменом
# как запасной профиль
{'name': 'fallback_warning2',
'warning': __("Error synchronizing with the "
"{cl_replication_host} remote server"),
'depend': Tasks.failed_one_of('sync_remote2')
},
{'name': 'fallback_warning2!:fallback_sync2',
'method': 'Client.syncLoginProfileNew(cl_remote_host,ur_login,desktop.ur_password,ur_uid,'
'ur_gid,ur_home_path,cl_client_profile_name)',
},
# сообщение о том, что будет использоваться запасной профиль
# с локального домена
{'name': 'fallback_success2',
'message': __("Got a user fallback profile from the "
"{cl_remote_host} domain"),
'depend': Tasks.success_one_of('fallback_sync2')
},
# ошибка синхронизации профиль не готов! к использованию
{'name': 'failed',
'error': __("Failed to get the user profile from the domain"),
'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"error")',
'depend': (Tasks.failed_all('sync_local2', 'sync_remote2', 'fallback_sync2') |
Tasks.failed_one_of('mount_resources2', 'two_session'))
},
]
tasks = [
# подключить удаленный ресурс домена
{'name': 'mount_remote',
'method': 'Client.mountRemoteRes(cl_remote_pw,cl_client_remote_path,'
'cl_remote_host)',
'condition': lambda Get: (Get('cl_remote_host') and
Get('os_remote_auth') and
not isMount(Get('cl_client_remote_path'))),
},
# check on domain user
{'name': 'domain_user',
'condition': lambda Get: (Get('os_remote_auth') and
Get('cl_remote_host') and
Get('desktop.ur_domain_set') == 'on'),
'else_message': __("The local profile will be used")
},
{'name': 'domain_user:create_home',
'message': __("Creating the home directory for {ur_login}"),
'method': 'Client.createUserDirectory(ur_home_path,ur_uid,'
'ur_gid)',
'condition': lambda Get: not path.exists(Get('ur_home_path'))
},
# password in kernel key
{'name': 'domain_user:check_password',
'condition': lambda Get: Get('desktop.ur_password'),
'else_error': __("User password not found")
},
{'name': 'ecryptfs',
'message': __("Mounting encrypted data"),
'method': 'Desktop.createCryptDir(ur_login,ur_uid,ur_gid,'
'ur_home_path,True)',
'condition': lambda Get: (Get('desktop.ur_home_crypt_set') == 'on' and
Get('install.cl_autologin') != Get(
'ur_login'))
},
{'name': 'domain_user:add_to_cache',
'essential': False,
'method': 'Client.cAddUserToCache(ur_login,desktop.ur_password)',
'failed_warning': __("Unable to cache user info")
},
# проверка на попытку открыть вторую сессию для этого пользователя
{'name': 'two_session',
'error':
__("A second X session cannot be opened for user {ur_login}."),
'condition': lambda dv: (dv.Get('ur_login') in
dv.Get('desktop.cl_desktop_online_user') and
int(dv.Select(
'desktop.cl_desktop_online_count',
where='desktop.cl_desktop_online_user',
eq=dv.Get('ur_login'), limit=1) > 1) and
dv.Get('cl_client_sync') == 'on')
},
{'name': 'domain_user:newsync',
'method': 'Client.checkSync(cl_remote_host)',
'essential': False,
'condition': lambda Get: Get('cl_client_sync') == 'on'
},
{'name': 'domain_user:domain_sync',
'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"process")',
'condition': lambda Get: Get('cl_client_sync') == 'on',
'depend': AllTasks.failed_one_of('newsync')
},
{'name': 'domain_user:domain_sync2',
'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"process")',
'condition': lambda Get: Get('cl_client_sync') == 'on',
'depend': AllTasks.success_one_of('newsync')
}, ] + old_sync + new_sync + [
# распаковать ссылки
{'name': 'domain_sync:unpack_links',
{'name': 'unpack_links',
'method': 'Client.unpackLinks(ur_home_path)',
'failed_warning': __("Failed to unpack the links archive"),
'depend': Tasks.hasnot('failed')
'depend': Tasks.hasnot('failed') & Tasks.success_one_of("domain_sync", "domain_sync2")
},
# синхронизация профиля завершилась успешно
{'name': 'domain_sync:success_sync',
{'name': 'success_sync',
'message': __("User profile fetched from the domain"),
'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"success")',
'depend': Tasks.success_all('sync_remote', 'unpack_links') |
Tasks.success()
Tasks.success() & Tasks.success_one_of("domain_sync", "domain_sync2")
},
# во время синхронизации профиля произошли ошибки, которые не
# гарантируют целостность профиля
{'name': 'domain_sync:error_sync',
{'name': 'error_sync',
'warning': __("User profile modifications will not "
"be saved to the domain"),
'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"error")',
'depend': Tasks.hasnot('success_sync', 'failed')
'depend': Tasks.hasnot('success_sync', 'failed') & Tasks.success_one_of("domain_sync", "domain_sync2")
},
# отключить удалённый профиль
{'name': 'domain_sync:umount_unix',
@ -275,6 +348,25 @@ class ClClientSyncLogoutAction(Action):
Get('desktop.ur_domain_set') == 'on'),
'else_message': __("The local profile will be used")
},
{'name': 'domain_user:ecryptfs',
'message': __("Mounting encrypted data"),
'method': 'Desktop.createCryptDir(ur_login,ur_uid,ur_gid,'
'ur_home_path,True)',
'condition': lambda Get: (Get('desktop.ur_home_crypt_set') == 'on' and
Get('install.cl_autologin') != Get(
'ur_login'))
},
{'name': 'domain_user:check_sync',
'method': 'Client.checkSync(cl_remote_host)',
'essential': False,
'condition': lambda Get: Get('cl_client_sync') == 'on'
},
{'name': 'domain_user:oldsync',
'depend': AllTasks.failed_one_of('check_sync')
},
{'name': 'domain_user:newsync',
'depend': AllTasks.success_one_of('check_sync')
},
# проверка на попытку отключить ресурсы пользователя в X сессии
{'name': 'domain_user:in_xsession',
'error': __("User {ur_login} is already on the X session"),
@ -286,9 +378,13 @@ class ClClientSyncLogoutAction(Action):
'condition': lambda Get: path.exists(Get('ur_home_path')),
'else_error': __("Home directory {ur_home_path} not found"),
},
{'name': 'domain_user:mount_local',
{'name': 'oldsync:mount_local',
'method': 'Client.mountUserDomainRes(ur_login,desktop.ur_password,'
'ur_uid,ur_gid,"unix")',
'ur_uid,ur_gid,"unix","homes","share","ftp")',
},
{'name': 'newsync:mount_local',
'method': 'Client.mountUserDomainRes(ur_login,desktop.ur_password,'
'ur_uid,ur_gid,"homes","share","ftp")',
},
# проверить наличие подключенных ресурсов
{'name': 'domain_user:check_mount',
@ -325,6 +421,12 @@ class ClClientSyncLogoutAction(Action):
'method': 'Client.syncLogoutProfile(cl_remote_host,ur_uid,'
'ur_gid,ur_home_path,"unix",cl_client_profile_name,'
'cl_client_symlinks)',
'depend': Tasks.has('oldsync')
},
{'name': 'domain_sync:sync_logout',
'method': 'Client.syncLogoutProfileNew(cl_remote_host,ur_login,desktop.ur_password,ur_uid,'
'ur_gid,ur_home_path,cl_client_profile_name,cl_client_symlinks)',
'depend': Tasks.has('newsync')
},
# удалить файлы, которые могут помешать следующему входу в сеанс
{'name': 'domain_sync:remove_noise_files',

@ -22,6 +22,7 @@ from calculate.lib.datavars import (Variable, VariableError, ReadonlyVariable,
ReadonlyTableVariable, FieldValue,
HumanReadable)
from calculate.lib.cl_ini_parser import iniParser
from calculate.lib.configparser import ConfigParser
import calculate.lib.utils.device as device
from calculate.lib.utils.files import (readFile, find,
FindFileType)
@ -38,6 +39,7 @@ from calculate.lib.cl_ldap import ldapUser
from calculate.lib.variables.user import LdapHelper
import pwd
from calculate.client.client import Client
from calculate.client.rsync import ProfileSyncer, ProfileSyncerError
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
@ -631,6 +633,49 @@ class SyncHelper(object):
return False
return True
def getSyncDate(self, osLinuxShort, ps):
"""
Получить время синхронизации из ::profile/.calculate/desktop.env
"""
desktopEnvRemoteData = ps.readfile("::profile/{}/{}".format(
osLinuxShort, Client.configFileDesktop))
if desktopEnvRemoteData:
cpRemote = ConfigParser(strict=False)
cpRemote.read_string(desktopEnvRemoteData)
timeLogout = cpRemote.get("main", "date_logout", fallback=None)
timeConfig = cpRemote.get("main", "date", fallback=None)
dates = filter(None,
[self.convertDate(timeLogout),
self.convertDate(timeConfig)])
if dates:
return dates[0]
return ""
def checkNeedSyncNew(self, homeDir, rpath, curTimeObj, curStatusSync,
osLinuxShort, ps):
"""
Проверить необходимость синхронизации текущего профиля с удаленным
"""
iniEnvRemoteData = ps.readfile("::profile/{}/{}".format(
osLinuxShort, Client.configFileSoft))
fileConfigCur = os.path.join(homeDir, Client.configFileSoft)
iniEnvCurrentData = readFile(fileConfigCur)
cpCur = ConfigParser(strict=False)
cpCur.read_string(iniEnvCurrentData)
cpRemote = ConfigParser(strict=False)
cpRemote.read_string(iniEnvRemoteData)
xSessionCur = cpCur.get('main', 'xsession', fallback=None)
xSessionThis = cpThis.get('main', 'xsession', fallback=None)
if curStatusSync == "success_logout" and \
xSessionCur == xSessionThis:
thisTimeObj = self.getSyncDate(osLinuxShort, ps)
if thisTimeObj and curTimeObj and \
curTimeObj >= thisTimeObj:
return False
return True
class VariableClClientSyncTime(SyncHelper, ReadonlyVariable):
"""
@ -672,18 +717,27 @@ class VariableClClientLocalSyncTime(SyncHelper, ReadonlyVariable):
limit=1), self.Get('cl_client_profile_name')))
class VariableClClientRsyncProfileSet(ReadonlyVariable):
"""
Используется rsync через ssh для синхронизации пользовательского профиля
"""
type = "bool"
value = "off"
class VariableClClientSyncReplicationSet(SyncHelper, ReadonlyVariable):
"""
Нужно ли синхронизировать текущий профиль с удаленным доменом
"""
type = "bool"
def get(self):
if not self.Get('cl_replication_host'):
return "off"
host_varname = "cl_replication_host"
profile_type = "remote_profile"
def old_synchronize(self):
profilePath = self.Select('cl_client_user_mount_path',
where='cl_client_user_mount_name',
eq='remote_profile', limit=1)
eq=self.profile_type, limit=1)
if self.Get('cl_action') == 'login' and not isMount(profilePath):
raise VariableError(_("Remote profile not mounted"))
return "on" if self.checkNeedSync(self.Get('ur_home_path'), profilePath,
@ -692,26 +746,39 @@ class VariableClClientSyncReplicationSet(SyncHelper, ReadonlyVariable):
self.Get(
'cl_client_profile_name')) else "off"
def new_synchronize(self):
user = self.Get('ur_login')
pwd = self.Get('desktop.ur_password')
remotehost = self.Get(self.host_varname)
ps = ProfileSyncer(remotehost, 2009, user, pwd)
if ps.check():
return "on" if self.checkNeedSyncNew(
self.Get('ur_home_path'), profilePath,
self.Get('cl_client_sync_time'),
self.Get('cl_client_sync_status'),
self.Get('cl_client_profile_name'),
ps) else "off"
return "off"
def get(self):
if not self.Get(self.host_varname):
return "off"
if self.GetBool('cl_client_rsync_profile_set'):
return self.new_synchronize()
else:
return self.old_synchronize()
class VariableClClientSyncLocalSet(SyncHelper, ReadonlyVariable):
class VariableClClientSyncLocalSet(VariableClClientSyncReplicationSet):
"""
Нужно ли синхронизировать текущий профиль с локальным доменом
"""
type = "bool"
def get(self):
if not self.Get('cl_remote_host'):
return "off"
profilePath = self.Select('cl_client_user_mount_path',
where='cl_client_user_mount_name',
eq='unix', limit=1)
if self.Get('cl_action') == 'login' and not isMount(profilePath):
raise VariableError(_("Remote profile not mounted"))
return "on" if self.checkNeedSync(self.Get('ur_home_path'), profilePath,
self.Get('cl_client_sync_time'),
self.Get('cl_client_sync_status'),
self.Get(
'cl_client_profile_name')) else "off"
host_varname = "cl_remote_host"
profile_type = "unix"
class VariableClClientSymlinks(ReadonlyVariable):

Loading…
Cancel
Save