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/client/utils/cl_client_sync.py

473 lines
24 KiB

9 years ago
# -*- coding: utf-8 -*-
# Copyright 2013-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 sys
from os import path
from calculate.core.server.func import Action, Tasks, AllTasks
9 years ago
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
from calculate.lib.utils.files import FilesError
from calculate.desktop.desktop import DesktopError
from calculate.lib.utils.samba import SambaError
from calculate.client.client import ClientError
from calculate.lib.cl_template import TemplatesError
from calculate.lib.utils.mount import isMount
9 years ago
_ = lambda x: x
setLocalTranslate('cl_client3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
9 years ago
class ClClientSyncLoginAction(Action):
"""
Синхронизировать локальный профиль с удаленным, подключить удаленные
ресурсы пользователя
"""
native_error = (FilesError, ClientError, DesktopError, TemplatesError,
SambaError)
successMessage = None
failedMessage = None
interruptMessage = __("Synchronization manually interrupted")
old_sync = [
9 years ago
# подключить удаленные ресурсы пользователя
{'name': 'oldsync:mount_resources',
9 years ago
'message': __("Mounting user resources"),
'method': 'Client.mountUserDomainRes(ur_login,'
'desktop.ur_password,'
'ur_uid,ur_gid,"unix","share","homes","ftp")',
},
# подключить профиль пользователя на удаленном домене
# если на нем находится актуальный профиль
{'name': 'domain_sync:repl_profile',
'method': 'Client.mountUserDomainRes(ur_login,desktop.ur_password,'
'ur_uid,ur_gid,"unix","remote_profile")',
'condition': lambda Get: Get('cl_replication_host')
},
# отправить команду архивирования профиля на удаленном домене
# если он новее локального профиля
{'name': 'repl_profile:pack_remote',
'method': 'Client.packRemote("remote_profile",'
'cl_client_local_sync_time,cl_client_pack_time,'
'cl_client_profile_name,ur_uid,ur_gid)',
'condition': lambda Get: Get('cl_client_sync_replication_set') == 'on',
'else_message': __("The local user profile does not "
"need to be synchronized with the remote domain")
},
9 years ago
# монтируем профиль локального домена, если локальный профиль
# старее удаленного доменного или актуальный профиль
{'name': 'domain_sync:mount_local',
'method': 'Client.mountUserDomainRes(ur_login,desktop.ur_password,'
'ur_uid,ur_gid,"unix")',
# нет более ранних ошибок и локальный профиль нуждается
# в синхронизации с удаленным или профиль на локальном домене
'depend': (Tasks.success_all('mount_resources') &
(Tasks.hasnot('repl_profile') |
Tasks.has('pack_remote')))
},
9 years ago
# синхронизируем с профилем локального домена
{'name': 'mount_local!:sync_local',
'method': 'Client.syncLoginProfile(cl_remote_host,ur_uid,'
'ur_gid,ur_home_path,"unix",cl_client_profile_name)',
9 years ago
'condition': lambda Get: Get('cl_client_sync_local_set') == 'on',
'else_message': __("The local user profile does not "
"need to be synchronized with the local domain")
},
9 years ago
# ошибка синхронизации с локальным доменом
{'name': 'local_sync_error',
'warning': __(
"Error synchronizing with the local server {cl_remote_host}"),
'depend': Tasks.failed_one_of("mount_local", "sync_local")
},
# подключить удаленный профиль пользователя с "репликации"
{'name': 'repl_profile:repeat_repl_profile',
'method': 'Client.mountUserDomainRes(ur_login,desktop.ur_password,'
'ur_uid,ur_gid,"remote_profile")',
},
# ждать архив от удаленного домена
{'name': 'pack_remote:wait_archive',
'message': __("Packing the archive on the server"),
'method': 'Client.waitingArchFile(cl_client_pack_time,'
'cl_client_profile_name,"remote_profile")',
'failed_warning': __("Failed to find the profile "
"archive of {cl_replication_host}")
},
9 years ago
# распаковать архив из удаленного домена и удалить
# файлы которые отсутствуют в удаленном профиле
{'name': 'wait_archive:unpack_profile',
'message': __("Unpacking the profile"),
'method': 'Client.unpackArch(ur_home_path,cl_client_pack_time,'
'cl_client_profile_name,"remote_profile")',
'failed_warning': __("Failed to unpack")
},
# удалить временные архивы
{'name': 'clean_archfiles',
'method': 'Client.cleanArchs(cl_client_pack_time,'
'cl_client_profile_name,"remote_profile")',
'failed_warning': __("Unable to remove useless files"),
'essential': False,
'depend': Tasks.has('pack_remote')
},
# синхронизировать профиль с удаленным доменом в случае ошибки
{'name': 'repl_profile:sync_remote',
'method': 'Client.syncLoginProfile(cl_replication_host,ur_uid,'
'ur_gid,ur_home_path,"remote_profile",'
'cl_client_profile_name)',
9 years ago
'depend': Tasks.failed_one_of('pack_remote', 'mount_local',
'sync_local',
'wait_archive', 'unpack_profile'),
'condition': lambda Select: isMount(
Select('cl_client_user_mount_path',
where='cl_client_user_mount_name', eq='remote_profile',
limit=1))
},
# если синхронизация с удаленным доменом прошла с ошибкой
# синхронизировать локальный профиль с локальным доменом
# как запасной профиль
{'name': 'pack_remote:fallback_warning',
'warning': __("Error synchronizing with the "
"{cl_replication_host} remote server"),
9 years ago
'depend': ~Tasks.success_one_of('unpack_profile', 'sync_remote')
},
9 years ago
{'name': 'pack_remote:fallback_sync',
'method': 'Client.syncLoginProfile(cl_remote_host,ur_uid,'
'ur_gid,ur_home_path,"unix",cl_client_profile_name)',
9 years ago
'depend': ~Tasks.success_one_of('unpack_profile', 'sync_remote')
},
# отключить профиль на удаленном домене
{'name': 'repl_profile!:umount_remote_profile',
'method': 'Client.umountRemoteUserRes(True,"remote_profile")',
},
# сообщение о том, что будет использоваться запасной профиль
# с локального домена
{'name': 'fallback_sync!:fallback_success',
'message': __("Got a user fallback profile from the "
"{cl_remote_host} domain")
},
# ошибка синхронизации профиль не готов! к использованию
{'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_remote', 'sync_local',
'fallback_sync') |
(Tasks.hasnot('domain_sync') & Tasks.failed()) |
9 years ago
Tasks.failed_one_of('mount_resources', 'two_session')
},
]
new_sync = [
# подключить удаленные ресурсы пользователя
{'name': 'newsync:mount_resources2',
'message': __("Mounting user resources"),
'method': 'Client.mountUserDomainRes(ur_login,'
'desktop.ur_password,'
'ur_uid,ur_gid,"homes","share","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,True)',
'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:check_sync',
'method': 'Client.checkSync(cl_remote_host)',
'essential': False,
},
{'name': 'domain_user:oldsync',
'depend': AllTasks.failed_one_of('check_sync')
},
{'name': 'domain_user:newsync',
'depend': AllTasks.success_one_of('check_sync')
},
{'name': 'oldsync:domain_sync',
'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"process")',
'condition': lambda Get: Get('cl_client_sync') == 'on',
},
{'name': 'newsync:domain_sync2',
'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"process")',
'condition': lambda Get: Get('cl_client_sync') == 'on',
}, ] + old_sync + new_sync + [
9 years ago
# распаковать ссылки
{'name': 'unpack_links',
9 years ago
'method': 'Client.unpackLinks(ur_home_path)',
'failed_warning': __("Failed to unpack the links archive"),
'depend': Tasks.hasnot('failed') & Tasks.success_one_of("domain_sync", "domain_sync2")
9 years ago
},
# синхронизация профиля завершилась успешно
{'name': 'success_sync',
9 years ago
'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_one_of("domain_sync", "domain_sync2")
9 years ago
},
# во время синхронизации профиля произошли ошибки, которые не
# гарантируют целостность профиля
{'name': 'error_sync',
9 years ago
'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') & Tasks.success_one_of("domain_sync", "domain_sync2")
9 years ago
},
# отключить удалённый профиль
{'name': 'domain_sync:umount_unix',
'method': 'Client.umountRemoteUserRes(True,"unix","remote_profile")',
'depend': Tasks.hasnot('failed'),
'condition': lambda GetBool: not GetBool('cl_client_ignore_errors_set')
},
9 years ago
# отключить ресурсы в случае ошибки
{'name': 'umount_remote_res',
'message': __("Umounting user resources"),
'method': 'Client.umountUserRes(desktop.ur_mount_dirs)',
'depend': Tasks.has('failed'),
'condition': lambda GetBool: not GetBool('cl_client_ignore_errors_set')
}
9 years ago
]
class ClClientSyncLogoutAction(Action):
"""
Синхронизировать локальный профиль с удаленным, отключить удаленные
ресурсы пользователя
"""
9 years ago
native_error = (FilesError, ClientError, DesktopError, TemplatesError)
successMessage = None
failedMessage = None
interruptMessage = __("Synchronization manually interrupted")
tasks = [
9 years ago
# проверка доменный ли пользователь
{'name': 'domain_user',
'condition': lambda Get: (Get('os_remote_auth') and
Get('cl_remote_host') and
Get('desktop.ur_domain_set') == 'on'),
9 years ago
'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')
},
9 years ago
# проверка на попытку отключить ресурсы пользователя в X сессии
{'name': 'domain_user:in_xsession',
'error': __("User {ur_login} is already on the X session"),
'condition': lambda Get: Get('ur_login') in
Get('desktop.cl_desktop_online_user'),
},
# проверить наличие домашней директории
{'name': 'domain_user:check_homedir',
'condition': lambda Get: path.exists(Get('ur_home_path')),
'else_error': __("Home directory {ur_home_path} not found"),
},
{'name': 'oldsync:mount_local',
'method': 'Client.mountUserDomainRes(ur_login,desktop.ur_password,'
'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")',
},
9 years ago
# проверить наличие подключенных ресурсов
{'name': 'domain_user:check_mount',
'condition': lambda Get: any(x and isMount(x)
for x in
Get('cl_client_user_mount_path')),
'else_error': __("Remote user resources not found")
},
# установить время выхода из сеанса
{'name': 'domain_user:set_logout_date',
'method': 'Client.setLogoutDate(ur_home_path,ur_uid,ur_gid)'
},
# выполнять ли синхронизацию
{'name': 'domain_user:domain_sync',
'condition': lambda Get: Get('cl_client_sync_status') == 'success' and
Get('cl_client_sync') == 'on',
'else_warning': __("The profile will not be uploaded to the domain")
},
# переместить файлы из профиля в Moved
{'name': 'domain_user:move_home_dir',
'message': __("Moving non-profile files to the Home/Moved directory"),
'method': 'Client.moveHomeDir(ur_home_path,"Moved","homes",'
'cl_moved_skip_path)',
'condition': lambda Get: Get('cl_sync_moved_set') == 'on'
},
9 years ago
# архивировать симлинки
{'name': 'domain_sync:tar_symlinks',
'method': 'Client.tarSymLinks(ur_uid,ur_gid,ur_home_path,'
'cl_sync_del_path,cl_sync_skip_path)',
'failed_error': _("Failed to make a links archive")
},
9 years ago
# закачать профиль пользователя в домен
{'name': 'domain_sync:sync_logout',
'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')
},
9 years ago
# удалить файлы, которые могут помешать следующему входу в сеанс
{'name': 'domain_sync:remove_noise_files',
'message': __("Removing hindering files"),
'method': 'Client.removeNoiseFiles(ur_home_path)'
},
# удалить "личные" файлы
{'name': 'domain_sync:remove_private_files',
'message': __("Removing user private files"),
'method': 'Client.removePrivateFiles(ur_home_path)'
},
# удалить пользовательские ключи ядра
{'name': 'domain_user!:clear_user_key',
'message': __("Clearing user keys"),
'method': 'Client.clearUserKey(ur_login)'
},
# отключить пользовательские ресурсы
{'name': 'check_mount!:umount_user_res',
'message': __("Umounting user resources"),
'method': 'Client.umountUserRes(desktop.ur_mount_dirs)',
},
# установить статус синхронизации
{'name': 'domain_sync:success_sync',
'message': __("Modified user profile saved in the domain"),
'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,'
'"success_logout")',
'depend': Tasks.success_all('sync_logout', 'check_mount')
},
{'name': 'domain_sync:failed',
'error': __("Modified user profile saved in the domain with errors"),
'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,'
'"error")',
'depend': Tasks.hasnot('success_sync')
},
{'name': 'umount_allres',
'method': 'Desktop.umountUserRes(ur_home_path)',
}
9 years ago
]