|
|
|
@ -0,0 +1,816 @@
|
|
|
|
|
diff --git client/utils/cl_client.py client/utils/cl_client.py
|
|
|
|
|
index 7513bce..3104f65 100644
|
|
|
|
|
--- client/utils/cl_client.py
|
|
|
|
|
+++ client/utils/cl_client.py
|
|
|
|
|
@@ -1,6 +1,6 @@
|
|
|
|
|
#-*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
|
|
-# Copyright 2010-2013 Calculate Ltd. http://www.calculate-linux.org
|
|
|
|
|
+# Copyright 2013 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.
|
|
|
|
|
@@ -24,7 +24,7 @@ from calculate.client.client import ClientError
|
|
|
|
|
from calculate.lib.cl_template import TemplatesError
|
|
|
|
|
from calculate.lib.utils.files import isMount
|
|
|
|
|
|
|
|
|
|
-setLocalTranslate('cl_desktop3',sys.modules[__name__])
|
|
|
|
|
+setLocalTranslate('cl_client3',sys.modules[__name__])
|
|
|
|
|
__ = getLazyLocalTranslate(_)
|
|
|
|
|
|
|
|
|
|
class ClClientAction(Action):
|
|
|
|
|
@@ -87,7 +87,8 @@ class ClClientAction(Action):
|
|
|
|
|
},
|
|
|
|
|
# наложить шаблоны если они не актуальны
|
|
|
|
|
{'name':'need_templates',
|
|
|
|
|
- 'condition':lambda Get:Get('cl_client_relevance_set') == 'off'
|
|
|
|
|
+ 'condition':lambda Get:Get('cl_client_relevance_set') == 'off',
|
|
|
|
|
+ 'depend':Tasks.success(inessential=['mount_remote'])
|
|
|
|
|
},
|
|
|
|
|
# проверить информацию для ldap расположенную в домене
|
|
|
|
|
{'name':'domain:check_domain_info',
|
|
|
|
|
@@ -146,341 +147,3 @@ class ClClientAction(Action):
|
|
|
|
|
'depend':Tasks.failed() & Tasks.hasnot("interrupt"),
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
-
|
|
|
|
|
-class ClClientSyncLoginAction(Action):
|
|
|
|
|
- """
|
|
|
|
|
- Синхронизировать локальный профиль с удаленным, подключить удаленные
|
|
|
|
|
- ресурсы пользователя
|
|
|
|
|
- """
|
|
|
|
|
- native_error = (FilesError,ClientError,DesktopError,TemplatesError)
|
|
|
|
|
-
|
|
|
|
|
- successMessage = None
|
|
|
|
|
- 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
|
|
|
|
|
- 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':'domain_user: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':__("Second X session for user %s cannot be opened."),
|
|
|
|
|
- 'condition':lambda Get:Get('ur_login') in \
|
|
|
|
|
- Get('desktop.cl_desktop_online_user') and \
|
|
|
|
|
- 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',
|
|
|
|
|
- '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:check_clock_scew',
|
|
|
|
|
- # 'method':'Client.checkClockScew('
|
|
|
|
|
- # 'failed_warning':__("Profile synchronization will be applied "
|
|
|
|
|
- # "without archiving")
|
|
|
|
|
- #},
|
|
|
|
|
- # отправить команду архивирования профиля на удаленном домене
|
|
|
|
|
- # если он новее локального профиля
|
|
|
|
|
- {'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 remote domain")
|
|
|
|
|
- },
|
|
|
|
|
- # монтируем профиль локального домена, если локальный профиль
|
|
|
|
|
- # старее удаленного доменного или актуальный профиль
|
|
|
|
|
- {'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')))
|
|
|
|
|
- },
|
|
|
|
|
- # синхронизируем с профилем локального домена
|
|
|
|
|
- {'name':'mount_local!:sync_local',
|
|
|
|
|
- 'method':'Client.syncLoginProfile(cl_remote_host,ur_uid,'
|
|
|
|
|
- 'ur_gid,ur_home_path,"unix",cl_client_profile_name)',
|
|
|
|
|
- 'condition':lambda Get:Get('cl_client_sync_local_set') == 'on',
|
|
|
|
|
- 'else_message':__("The local user profile does not "
|
|
|
|
|
- "need to be synchronized with local domain")
|
|
|
|
|
- },
|
|
|
|
|
- # ошибка синхронизации с локальным доменом
|
|
|
|
|
- {'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 from {cl_replication_host}")
|
|
|
|
|
- },
|
|
|
|
|
- # распаковать архив из удаленного домена и удалить
|
|
|
|
|
- # файлы которые отсутствуют в удаленном профиле
|
|
|
|
|
- {'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)',
|
|
|
|
|
- '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 remote server "
|
|
|
|
|
- "{cl_replication_host}"),
|
|
|
|
|
- 'depend': ~Tasks.success_one_of('unpack_profile','sync_remote')
|
|
|
|
|
- },
|
|
|
|
|
- {'name':'pack_remote:fallback_sync',
|
|
|
|
|
- 'method':'Client.syncLoginProfile(cl_remote_host,ur_uid,'
|
|
|
|
|
- 'ur_gid,ur_home_path,"unix",cl_client_profile_name)',
|
|
|
|
|
- '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': __("Get 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()) |
|
|
|
|
|
- Tasks.failed_one_of('mount_resources')
|
|
|
|
|
- },
|
|
|
|
|
- # распаковать ссылки
|
|
|
|
|
- {'name':'domain_sync:unpack_links',
|
|
|
|
|
- 'method':'Client.unpackLinks(ur_home_path)',
|
|
|
|
|
- 'failed_warning': __("Failed to unpack the links archive"),
|
|
|
|
|
- 'depend':Tasks.hasnot('failed')
|
|
|
|
|
- },
|
|
|
|
|
- # синхронизация профиля завершилась успешно
|
|
|
|
|
- {'name':'domain_sync:success_sync',
|
|
|
|
|
- 'message':__("Get the user profile from domain"),
|
|
|
|
|
- 'method':'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"success")',
|
|
|
|
|
- 'depend': Tasks.success_all('sync_remote','unpack_links') |
|
|
|
|
|
- Tasks.success()
|
|
|
|
|
- },
|
|
|
|
|
- # во время синхронизации профиля произошли ошибки, которые не
|
|
|
|
|
- # гарантируют целостность профиля
|
|
|
|
|
- {'name':'domain_sync:error_sync',
|
|
|
|
|
- 'warning':__("Changings in the user profile will not "
|
|
|
|
|
- "be saved to the domain"),
|
|
|
|
|
- 'method':'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"error")',
|
|
|
|
|
- 'depend': Tasks.hasnot('success_sync','failed')
|
|
|
|
|
- },
|
|
|
|
|
- # отключить ресурсы в случае ошибки
|
|
|
|
|
- {'name':'umount_remote_res',
|
|
|
|
|
- 'message':__("Umounting user resources"),
|
|
|
|
|
- 'method':'Client.umountUserRes(desktop.ur_mount_dirs)',
|
|
|
|
|
- 'depend':Tasks.has('failed')
|
|
|
|
|
- }
|
|
|
|
|
- ]
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class ClClientSyncLogoutAction(Action):
|
|
|
|
|
- """
|
|
|
|
|
- Синхронизировать локальный профиль с удаленным, отключить удаленные
|
|
|
|
|
- ресурсы пользователя
|
|
|
|
|
- """
|
|
|
|
|
- native_error = (FilesError,ClientError,DesktopError,TemplatesError)
|
|
|
|
|
-
|
|
|
|
|
- successMessage = None
|
|
|
|
|
- failedMessage = None
|
|
|
|
|
- interruptMessage = __("Synchronization manually interrupted")
|
|
|
|
|
-
|
|
|
|
|
- tasks = [
|
|
|
|
|
- # проверка доменный ли пользователь
|
|
|
|
|
- {'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 is used")
|
|
|
|
|
- },
|
|
|
|
|
- # проверка на попытку отключить ресурсы пользователя в X сессии
|
|
|
|
|
- {'name':'domain_user:in_xsession',
|
|
|
|
|
- 'error':__("User {ur_login} is already in 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':__("User home directory {ur_home_path} not found"),
|
|
|
|
|
- },
|
|
|
|
|
- # проверить наличие подключенных ресурсов
|
|
|
|
|
- {'name':'check_mount',
|
|
|
|
|
- 'condition':lambda Get:any(x and isMount(x)
|
|
|
|
|
- for x in Get('cl_client_user_mount_path')),
|
|
|
|
|
- 'else_error':__("User remote 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':__("Profile will not be upload to domain")
|
|
|
|
|
- },
|
|
|
|
|
- # переместить файлы из профиля в Moved
|
|
|
|
|
- {'name':'domain_user:move_home_dir',
|
|
|
|
|
- 'message':__("Moving not profile files to Home/Moved directory"),
|
|
|
|
|
- 'method':'Client.moveHomeDir(ur_home_path,"Moved","homes",'
|
|
|
|
|
- 'cl_moved_skip_path)',
|
|
|
|
|
- },
|
|
|
|
|
- # архивировать симлинки
|
|
|
|
|
- {'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")
|
|
|
|
|
- },
|
|
|
|
|
- # закачать профиль пользователя в домен
|
|
|
|
|
- {'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)',
|
|
|
|
|
- },
|
|
|
|
|
- # удалить файлы, которые могут помешать следующему входу в сеанс
|
|
|
|
|
- {'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':'skip:clear_user_key',
|
|
|
|
|
- 'message':__("Clearing user key"),
|
|
|
|
|
- '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)',
|
|
|
|
|
- }
|
|
|
|
|
- ]
|
|
|
|
|
-
|
|
|
|
|
-class ClPasswdAction(Action):
|
|
|
|
|
- """
|
|
|
|
|
- Изменить пароль доменного пользователя
|
|
|
|
|
- """
|
|
|
|
|
- # ошибки, которые отображаются без подробностей
|
|
|
|
|
- native_error = (FilesError,DesktopError,TemplatesError)
|
|
|
|
|
-
|
|
|
|
|
- successMessage = (__("{cl_client_login}'s password changed\n"
|
|
|
|
|
- "The password will be changed when you log out"
|
|
|
|
|
- "from the X session"))
|
|
|
|
|
- failedMessage = __("Failed to change password")
|
|
|
|
|
- interruptMessage = __("Logout manually interrupted")
|
|
|
|
|
-
|
|
|
|
|
- # список задач для действия
|
|
|
|
|
- tasks = [
|
|
|
|
|
- {'name':'change_passwd',
|
|
|
|
|
- 'method':'Client.clientPasswd(cl_client_login,ur_uid,ur_gid,'
|
|
|
|
|
- 'ur_home_path,ur_user_new_pw,ur_user_pw)',
|
|
|
|
|
- }]
|
|
|
|
|
diff --git client/utils/cl_client_sync.py client/utils/cl_client_sync.py
|
|
|
|
|
new file mode 100644
|
|
|
|
|
index 0000000..b5f53bf
|
|
|
|
|
--- /dev/null
|
|
|
|
|
+++ client/utils/cl_client_sync.py
|
|
|
|
|
@@ -0,0 +1,345 @@
|
|
|
|
|
+#-*- coding: utf-8 -*-
|
|
|
|
|
+
|
|
|
|
|
+# Copyright 2013 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.
|
|
|
|
|
+
|
|
|
|
|
+import sys
|
|
|
|
|
+from os import path
|
|
|
|
|
+from calculate.core.server.func import Action,Tasks
|
|
|
|
|
+from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate
|
|
|
|
|
+from calculate.lib.utils.files import FilesError
|
|
|
|
|
+from calculate.desktop.desktop import DesktopError
|
|
|
|
|
+from calculate.client.client import ClientError
|
|
|
|
|
+from calculate.lib.cl_template import TemplatesError
|
|
|
|
|
+
|
|
|
|
|
+setLocalTranslate('cl_client3',sys.modules[__name__])
|
|
|
|
|
+__ = getLazyLocalTranslate(_)
|
|
|
|
|
+
|
|
|
|
|
+class ClClientSyncLoginAction(Action):
|
|
|
|
|
+ """
|
|
|
|
|
+ Синхронизировать локальный профиль с удаленным, подключить удаленные
|
|
|
|
|
+ ресурсы пользователя
|
|
|
|
|
+ """
|
|
|
|
|
+ native_error = (FilesError,ClientError,DesktopError,TemplatesError)
|
|
|
|
|
+
|
|
|
|
|
+ successMessage = None
|
|
|
|
|
+ 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
|
|
|
|
|
+ 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':'domain_user: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':__("Second X session for user %s cannot be opened."),
|
|
|
|
|
+ 'condition':lambda Get:Get('ur_login') in \
|
|
|
|
|
+ Get('desktop.cl_desktop_online_user') and \
|
|
|
|
|
+ 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',
|
|
|
|
|
+ '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:check_clock_scew',
|
|
|
|
|
+ # 'method':'Client.checkClockScew('
|
|
|
|
|
+ # 'failed_warning':__("Profile synchronization will be applied "
|
|
|
|
|
+ # "without archiving")
|
|
|
|
|
+ #},
|
|
|
|
|
+ # отправить команду архивирования профиля на удаленном домене
|
|
|
|
|
+ # если он новее локального профиля
|
|
|
|
|
+ {'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 remote domain")
|
|
|
|
|
+ },
|
|
|
|
|
+ # монтируем профиль локального домена, если локальный профиль
|
|
|
|
|
+ # старее удаленного доменного или актуальный профиль
|
|
|
|
|
+ {'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')))
|
|
|
|
|
+ },
|
|
|
|
|
+ # синхронизируем с профилем локального домена
|
|
|
|
|
+ {'name':'mount_local!:sync_local',
|
|
|
|
|
+ 'method':'Client.syncLoginProfile(cl_remote_host,ur_uid,'
|
|
|
|
|
+ 'ur_gid,ur_home_path,"unix",cl_client_profile_name)',
|
|
|
|
|
+ 'condition':lambda Get:Get('cl_client_sync_local_set') == 'on',
|
|
|
|
|
+ 'else_message':__("The local user profile does not "
|
|
|
|
|
+ "need to be synchronized with local domain")
|
|
|
|
|
+ },
|
|
|
|
|
+ # ошибка синхронизации с локальным доменом
|
|
|
|
|
+ {'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 from {cl_replication_host}")
|
|
|
|
|
+ },
|
|
|
|
|
+ # распаковать архив из удаленного домена и удалить
|
|
|
|
|
+ # файлы которые отсутствуют в удаленном профиле
|
|
|
|
|
+ {'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)',
|
|
|
|
|
+ '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 remote server "
|
|
|
|
|
+ "{cl_replication_host}"),
|
|
|
|
|
+ 'depend': ~Tasks.success_one_of('unpack_profile','sync_remote')
|
|
|
|
|
+ },
|
|
|
|
|
+ {'name':'pack_remote:fallback_sync',
|
|
|
|
|
+ 'method':'Client.syncLoginProfile(cl_remote_host,ur_uid,'
|
|
|
|
|
+ 'ur_gid,ur_home_path,"unix",cl_client_profile_name)',
|
|
|
|
|
+ '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': __("Get 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()) |
|
|
|
|
|
+ Tasks.failed_one_of('mount_resources')
|
|
|
|
|
+ },
|
|
|
|
|
+ # распаковать ссылки
|
|
|
|
|
+ {'name':'domain_sync:unpack_links',
|
|
|
|
|
+ 'method':'Client.unpackLinks(ur_home_path)',
|
|
|
|
|
+ 'failed_warning': __("Failed to unpack the links archive"),
|
|
|
|
|
+ 'depend':Tasks.hasnot('failed')
|
|
|
|
|
+ },
|
|
|
|
|
+ # синхронизация профиля завершилась успешно
|
|
|
|
|
+ {'name':'domain_sync:success_sync',
|
|
|
|
|
+ 'message':__("Get the user profile from domain"),
|
|
|
|
|
+ 'method':'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"success")',
|
|
|
|
|
+ 'depend': Tasks.success_all('sync_remote','unpack_links') |
|
|
|
|
|
+ Tasks.success()
|
|
|
|
|
+ },
|
|
|
|
|
+ # во время синхронизации профиля произошли ошибки, которые не
|
|
|
|
|
+ # гарантируют целостность профиля
|
|
|
|
|
+ {'name':'domain_sync:error_sync',
|
|
|
|
|
+ 'warning':__("Changings in the user profile will not "
|
|
|
|
|
+ "be saved to the domain"),
|
|
|
|
|
+ 'method':'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"error")',
|
|
|
|
|
+ 'depend': Tasks.hasnot('success_sync','failed')
|
|
|
|
|
+ },
|
|
|
|
|
+ # отключить ресурсы в случае ошибки
|
|
|
|
|
+ {'name':'umount_remote_res',
|
|
|
|
|
+ 'message':__("Umounting user resources"),
|
|
|
|
|
+ 'method':'Client.umountUserRes(desktop.ur_mount_dirs)',
|
|
|
|
|
+ 'depend':Tasks.has('failed')
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class ClClientSyncLogoutAction(Action):
|
|
|
|
|
+ """
|
|
|
|
|
+ Синхронизировать локальный профиль с удаленным, отключить удаленные
|
|
|
|
|
+ ресурсы пользователя
|
|
|
|
|
+ """
|
|
|
|
|
+ native_error = (FilesError,ClientError,DesktopError,TemplatesError)
|
|
|
|
|
+
|
|
|
|
|
+ successMessage = None
|
|
|
|
|
+ failedMessage = None
|
|
|
|
|
+ interruptMessage = __("Synchronization manually interrupted")
|
|
|
|
|
+
|
|
|
|
|
+ tasks = [
|
|
|
|
|
+ # проверка доменный ли пользователь
|
|
|
|
|
+ {'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 is used")
|
|
|
|
|
+ },
|
|
|
|
|
+ # проверка на попытку отключить ресурсы пользователя в X сессии
|
|
|
|
|
+ {'name':'domain_user:in_xsession',
|
|
|
|
|
+ 'error':__("User {ur_login} is already in 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':__("User home directory {ur_home_path} not found"),
|
|
|
|
|
+ },
|
|
|
|
|
+ # проверить наличие подключенных ресурсов
|
|
|
|
|
+ {'name':'check_mount',
|
|
|
|
|
+ 'condition':lambda Get:any(x and isMount(x)
|
|
|
|
|
+ for x in Get('cl_client_user_mount_path')),
|
|
|
|
|
+ 'else_error':__("User remote 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':__("Profile will not be upload to domain")
|
|
|
|
|
+ },
|
|
|
|
|
+ # переместить файлы из профиля в Moved
|
|
|
|
|
+ {'name':'domain_user:move_home_dir',
|
|
|
|
|
+ 'message':__("Moving not profile files to Home/Moved directory"),
|
|
|
|
|
+ 'method':'Client.moveHomeDir(ur_home_path,"Moved","homes",'
|
|
|
|
|
+ 'cl_moved_skip_path)',
|
|
|
|
|
+ },
|
|
|
|
|
+ # архивировать симлинки
|
|
|
|
|
+ {'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")
|
|
|
|
|
+ },
|
|
|
|
|
+ # закачать профиль пользователя в домен
|
|
|
|
|
+ {'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)',
|
|
|
|
|
+ },
|
|
|
|
|
+ # удалить файлы, которые могут помешать следующему входу в сеанс
|
|
|
|
|
+ {'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':'skip:clear_user_key',
|
|
|
|
|
+ 'message':__("Clearing user key"),
|
|
|
|
|
+ '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':'check_mount!:umount_allres',
|
|
|
|
|
+ 'method':'Desktop.umountUserRes(ur_home_path)',
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
diff --git client/utils/cl_passwd.py client/utils/cl_passwd.py
|
|
|
|
|
new file mode 100644
|
|
|
|
|
index 0000000..18323eb
|
|
|
|
|
--- /dev/null
|
|
|
|
|
+++ client/utils/cl_passwd.py
|
|
|
|
|
@@ -0,0 +1,47 @@
|
|
|
|
|
+#-*- coding: utf-8 -*-
|
|
|
|
|
+
|
|
|
|
|
+# Copyright 2013 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.
|
|
|
|
|
+
|
|
|
|
|
+import sys
|
|
|
|
|
+from os import path
|
|
|
|
|
+from calculate.core.server.func import Action,Tasks
|
|
|
|
|
+from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate
|
|
|
|
|
+from calculate.lib.utils.files import FilesError
|
|
|
|
|
+from calculate.desktop.desktop import DesktopError
|
|
|
|
|
+from calculate.client.client import ClientError
|
|
|
|
|
+from calculate.lib.cl_template import TemplatesError
|
|
|
|
|
+
|
|
|
|
|
+setLocalTranslate('cl_client3',sys.modules[__name__])
|
|
|
|
|
+__ = getLazyLocalTranslate(_)
|
|
|
|
|
+
|
|
|
|
|
+class ClPasswdAction(Action):
|
|
|
|
|
+ """
|
|
|
|
|
+ Изменить пароль доменного пользователя
|
|
|
|
|
+ """
|
|
|
|
|
+ # ошибки, которые отображаются без подробностей
|
|
|
|
|
+ native_error = (FilesError,DesktopError,TemplatesError,ClientError)
|
|
|
|
|
+
|
|
|
|
|
+ successMessage = (__("{cl_client_login}'s password changed\n"
|
|
|
|
|
+ "The password will be changed when you log out"
|
|
|
|
|
+ "from the X session"))
|
|
|
|
|
+ failedMessage = __("Failed to change password")
|
|
|
|
|
+ interruptMessage = __("Logout manually interrupted")
|
|
|
|
|
+
|
|
|
|
|
+ # список задач для действия
|
|
|
|
|
+ tasks = [
|
|
|
|
|
+ {'name':'change_passwd',
|
|
|
|
|
+ 'method':'Client.clientPasswd(cl_client_login,ur_uid,ur_gid,'
|
|
|
|
|
+ 'ur_home_path,ur_user_new_pw,ur_user_pw)',
|
|
|
|
|
+ }]
|
|
|
|
|
diff --git client/variables/client.py client/variables/client.py
|
|
|
|
|
index 88f7ab5..4620e81 100644
|
|
|
|
|
--- client/variables/client.py
|
|
|
|
|
+++ client/variables/client.py
|
|
|
|
|
@@ -296,6 +296,9 @@ class VariableClClientRelevanceSet(ReadonlyVariable):
|
|
|
|
|
# если изменился домен
|
|
|
|
|
if self.Get('cl_remote_host') != self.Get("os_remote_auth"):
|
|
|
|
|
return "off"
|
|
|
|
|
+ if (self.Get('cl_remote_host') and
|
|
|
|
|
+ not isMount(self.Get('cl_client_remote_path'))):
|
|
|
|
|
+ return "off"
|
|
|
|
|
currentVersion = self.Get("cl_ver")
|
|
|
|
|
# версия программы, который были наложены шаблоны
|
|
|
|
|
previousVersion = self.Get("os_remote_client")
|
|
|
|
|
diff --git client/wsdl_client.py client/wsdl_client.py
|
|
|
|
|
index 2bd0ee6..90b2302 100644
|
|
|
|
|
--- client/wsdl_client.py
|
|
|
|
|
+++ client/wsdl_client.py
|
|
|
|
|
@@ -19,15 +19,16 @@ from calculate.lib.datavars import VariableError, DataVarsError
|
|
|
|
|
from calculate.core.server.func import WsdlBase
|
|
|
|
|
from calculate.desktop.desktop import DesktopError
|
|
|
|
|
from client import ClientError
|
|
|
|
|
-from utils.cl_client import (ClClientAction, ClClientSyncLoginAction,
|
|
|
|
|
- ClClientSyncLogoutAction, ClPasswdAction)
|
|
|
|
|
+from utils.cl_client import ClClientAction
|
|
|
|
|
+from utils.cl_passwd import ClPasswdAction
|
|
|
|
|
+from utils.cl_client_sync import (ClClientSyncLoginAction,
|
|
|
|
|
+ ClClientSyncLogoutAction)
|
|
|
|
|
import calculate.desktop.desktop as desktop
|
|
|
|
|
import calculate.client.client as client
|
|
|
|
|
-import calculate.install.install as install
|
|
|
|
|
|
|
|
|
|
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
|
|
|
|
|
|
|
|
|
|
-setLocalTranslate('cl_desktop3', sys.modules[__name__])
|
|
|
|
|
+setLocalTranslate('cl_client3', sys.modules[__name__])
|
|
|
|
|
__ = getLazyLocalTranslate(_)
|
|
|
|
|
|
|
|
|
|
|