Refactoring

develop 3.4.1.1
Mike Khiretskiy 9 years ago
parent b0ce98e865
commit 76171566a9

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2013-2014 Calculate Ltd. http://www.calculate-linux.org # Copyright 2013-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -25,11 +25,11 @@ import os
from os import path from os import path
import dbus.mainloop.glib import dbus.mainloop.glib
from calculate.lib.datavars import DataVars, VariableError from calculate.lib.datavars import DataVars, VariableError
from calculate.lib.utils.files import isMount, getRunCommands
from calculate.client.client import Client from calculate.client.client import Client
from argparse import ArgumentParser from argparse import ArgumentParser
from time import sleep from time import sleep
class ResourceRemounter: class ResourceRemounter:
""" """
Object contains one method for handle 'Resuming' dbus signal. Object contains one method for handle 'Resuming' dbus signal.
@ -37,30 +37,27 @@ class ResourceRemounter:
'handle_resuming' method checks and remounts user remote resources. 'handle_resuming' method checks and remounts user remote resources.
Also the object refreshes NSS-cache. Also the object refreshes NSS-cache.
""" """
def __init__(self,dv): nscd_refresh = "/usr/sbin/nscd-refresh"
def __init__(self, dv):
self.dv = dv self.dv = dv
self.dv.defaultModule = 'client' self.dv.defaultModule = 'client'
self.client = Client() self.client = Client()
self.client.clVars = dv self.client.clVars = dv
self.check_server(True) self.check_server(True)
def check_server(self,refresh_nscd=False): def check_server(self, refresh_nscd=False):
""" """
Check the available of domain server and refresh nscd cache Check the available of domain server and refresh nscd cache
""" """
if self.client.checkDomainServer( if self.client.checkDomainServer(
self.dv.Get('cl_remote_host'), self.dv.Get('cl_remote_host'),
self.dv.Get('os_net_domain')): self.dv.Get('os_net_domain')):
try: if refresh_nscd and path.exists(self.nscd_refresh):
if refresh_nscd and path.exists(self.nscd_refresh): os.system(self.nscd_refresh)
os.system(self.nscd_refresh)
except:
pass
return True return True
return False return False
nscd_refresh = "/usr/sbin/nscd-refresh"
def remount_remote(self): def remount_remote(self):
""" """
Remount remote resource of the domain Remount remote resource of the domain
@ -69,7 +66,7 @@ class ResourceRemounter:
self.client.mountRemoteRes(self.dv.Get('cl_remote_pw'), self.client.mountRemoteRes(self.dv.Get('cl_remote_pw'),
self.dv.Get('cl_client_remote_path'), self.dv.Get('cl_client_remote_path'),
self.dv.Get('cl_remote_host')) self.dv.Get('cl_remote_host'))
except: except Exception:
pass pass
def remount_user_resources(self): def remount_user_resources(self):
@ -78,21 +75,21 @@ class ResourceRemounter:
""" """
try: try:
self.client.mountUserDomainRes(self.dv.Get('ur_login'), self.client.mountUserDomainRes(self.dv.Get('ur_login'),
self.dv.Get('desktop.ur_password'), self.dv.Get('desktop.ur_password'),
int(self.dv.Get('ur_uid')), int(self.dv.Get('ur_uid')),
int(self.dv.Get('ur_gid')), int(self.dv.Get('ur_gid')),
"unix","share","homes","ftp") "unix", "share", "homes", "ftp")
except: except Exception:
pass pass
def handle_resuming(self,statename): def handle_resuming(self, statename):
print("Restoring remote mounts for user %s"%self.dv.Get('ur_login')) print("Restoring remote mounts for user %s" % self.dv.Get('ur_login'))
# waiting for the domain # waiting for the domain
for wait in [1,2,5,10]: for wait in [1, 2, 5, 10]:
try: try:
if self.check_server(True): if self.check_server(True):
break break
except: except Exception:
pass pass
sleep(wait) sleep(wait)
# check and remount remote resources # check and remount remote resources
@ -103,7 +100,7 @@ class ResourceRemounter:
def main(argv): def main(argv):
# processing the user argument # processing the user argument
argp = ArgumentParser(add_help=True) argp = ArgumentParser(add_help=True)
argp.add_argument("user",help="tracked user",metavar="USER") argp.add_argument("user", help="tracked user", metavar="USER")
namespace = argp.parse_args(argv[1:]) namespace = argp.parse_args(argv[1:])
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
@ -114,17 +111,18 @@ def main(argv):
dv = DataVars() dv = DataVars()
dv.importData() dv.importData()
dv.flIniFile() dv.flIniFile()
dv.Set('ur_login',namespace.user) dv.Set('ur_login', namespace.user)
if dv.Get('desktop.ur_domain_set') == 'off': if dv.Get('desktop.ur_domain_set') == 'off':
print("%s isn't a domain user"%namespace.user) print("%s isn't a domain user" % namespace.user)
sys.exit(0) sys.exit(0)
except VariableError as e: except VariableError as e:
sys.stderr.write(str(e)+'\n') sys.stderr.write(str(e) + '\n')
sys.exit(1) sys.exit(1)
rm = ResourceRemounter(dv) rm = ResourceRemounter(dv)
bus.add_signal_receiver(rm.handle_resuming,dbus_interface="org.freedesktop.UPower", bus.add_signal_receiver(rm.handle_resuming,
signal_name = "NotifyResume") dbus_interface="org.freedesktop.UPower",
signal_name="NotifyResume")
loop = gobject.MainLoop() loop = gobject.MainLoop()
context = loop.get_context() context = loop.get_context()
while True: while True:
@ -132,5 +130,6 @@ def main(argv):
context.iteration(1) context.iteration(1)
sleep(1) sleep(1)
if __name__ == '__main__': if __name__ == '__main__':
main(sys.argv) main(sys.argv)

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2012-2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2012-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -14,21 +14,38 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import os, sys, time import os
import sys
import time
from calculate.lib.utils.files import getModeFile from calculate.lib.utils.files import getModeFile
from calculate.lib.cl_print import color_print from calculate.lib.cl_ldap import ldapUser
from calculate.lib.cl_ldap import ldapUser
from calculate.lib.cl_lang import setLocalTranslate from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_client3',sys.modules[__name__])
class _shareData(color_print): _ = lambda x: x
setLocalTranslate('cl_client3', sys.modules[__name__])
class Printable(object):
def __init__(self, parent):
if isinstance(parent, Printable):
self.parent = parent.parent
self.parent = parent
def printERROR(self, s):
self.parent.printERROR(s)
class _shareData(Printable):
"""Share class""" """Share class"""
fileName = ""
template = ""
lenData = 0
data = [] data = []
def getDataInFile(self, fileName='', lenData=0): def getDataInFile(self, fileName='', lenData=0):
"""Get data list from file""" """Get data list from file"""
return filter(lambda x: len(x)==lenData, return filter(lambda x: len(x) == lenData,
map(lambda x: x.rstrip().split(":"), open(fileName))) map(lambda x: x.rstrip().split(":"), open(fileName)))
def getFileAccess(self, perm="READ"): def getFileAccess(self, perm="READ"):
@ -36,14 +53,14 @@ class _shareData(color_print):
if os.access(self.fileName, os.R_OK): if os.access(self.fileName, os.R_OK):
return True return True
else: else:
self.printERROR(_("Failed to read the file")+_(": ") + self.printERROR(_("Failed to read the file") + _(": ") +
self.fileName) self.fileName)
return False return False
elif perm == "WRITE": elif perm == "WRITE":
if os.access(self.fileName, os.W_OK): if os.access(self.fileName, os.W_OK):
return True return True
else: else:
self.printERROR(_("Failed to write to file")+_(": ") + self.printERROR(_("Failed to write to file") + _(": ") +
self.fileName) self.fileName)
return False return False
@ -55,14 +72,14 @@ class _shareData(color_print):
elif self.getFileAccess(perm="READ"): elif self.getFileAccess(perm="READ"):
self.data = self.getDataInFile(fileName=self.fileName, self.data = self.getDataInFile(fileName=self.fileName,
lenData=self.lenData) lenData=self.lenData)
return self.data return self.data
else: else:
return False return False
def save(self): def save(self):
if self.getFileAccess(perm="WRITE"): if self.getFileAccess(perm="WRITE"):
buff = "\n".join(map(lambda x: ":".join(x), self.data)) + "\n" buff = "\n".join(map(lambda x: ":".join(x), self.data)) + "\n"
FD = open(self.fileName, "w+") FD = open(self.fileName, "w+")
FD.write(buff) FD.write(buff)
FD.close() FD.close()
return True return True
@ -73,7 +90,7 @@ class _shareData(color_print):
if self.getData() is False: if self.getData() is False:
return False return False
else: else:
self.data = filter(lambda x: x[0]!=name, self.data) self.data = filter(lambda x: x[0] != name, self.data)
return True return True
def replace(self, name, listData): def replace(self, name, listData):
@ -101,12 +118,13 @@ class _shareData(color_print):
if self.getData() is False: if self.getData() is False:
return False return False
else: else:
listData = filter(lambda x: x[0]==name, self.data) listData = filter(lambda x: x[0] == name, self.data)
if listData: if listData:
return listData[0] return listData[0]
else: else:
return [] return []
class passwd(_shareData): class passwd(_shareData):
'''Class for working with the file /etc/passwd''' '''Class for working with the file /etc/passwd'''
fileName = "/etc/passwd" fileName = "/etc/passwd"
@ -115,10 +133,10 @@ class passwd(_shareData):
def add(self, name, uid, gid, gecos="", directory="", shell="/bin/bash"): def add(self, name, uid, gid, gecos="", directory="", shell="/bin/bash"):
if not directory: if not directory:
directory = "/home/%s" %name directory = "/home/%s" % name
userData = self.template%{'login':name, 'uid':uid, 'gid':gid, userData = self.template % {'login': name, 'uid': uid, 'gid': gid,
'gecos':gecos, 'directory':directory, 'gecos': gecos, 'directory': directory,
'shell':shell} 'shell': shell}
userList = userData.split(":") userList = userData.split(":")
if self.getData() is False: if self.getData() is False:
return False return False
@ -130,15 +148,16 @@ class passwd(_shareData):
self.data.append(userList) self.data.append(userList)
return True return True
class group(_shareData): class group(_shareData):
'''Class for working with the file /etc/group''' '''Class for working with the file /etc/group'''
fileName = "/etc/group" fileName = "/etc/group"
template = "%(group_name)s:x:%(gid)s:%(user_list)s" template = "%(group_name)s:x:%(gid)s:%(user_list)s"
lenData = 4 lenData = 4
def add(self, name, gid, userList=[]): def add(self, name, gid, userList=()):
groupData = self.template%{'group_name':name, 'gid':gid, groupData = self.template % {'group_name': name, 'gid': gid,
'user_list':','.join(userList)} 'user_list': ','.join(userList)}
groupList = groupData.split(":") groupList = groupData.split(":")
if self.getData() is False: if self.getData() is False:
return False return False
@ -165,12 +184,12 @@ class group(_shareData):
# Constant gid # Constant gid
listDataWork[2] = self.data[index][2] listDataWork[2] = self.data[index][2]
# Join user list # Join user list
userList = delEmpty(self.data[index][3].split(',') +\ userList = delEmpty(self.data[index][3].split(',') +
listDataWork[3].split(',')) listDataWork[3].split(','))
# unique list # unique list
userList = reduce(lambda x,y:\ userList = reduce(lambda x, y: \
(y in x and x) or x +[y], (y in x and x) or x + [y],
userList,[]) userList, [])
listDataWork[3] = ','.join(userList) listDataWork[3] = ','.join(userList)
self.data[index] = listDataWork self.data[index] = listDataWork
if flagFound: if flagFound:
@ -200,7 +219,7 @@ class group(_shareData):
return False return False
else: else:
dataGroup = map(lambda x: x[3].split(","), dataGroup = map(lambda x: x[3].split(","),
filter(lambda x: x[0]==name, self.data)) filter(lambda x: x[0] == name, self.data))
if dataGroup: if dataGroup:
return dataGroup[0] return dataGroup[0]
else: else:
@ -214,28 +233,29 @@ class group(_shareData):
for dataList in self.data: for dataList in self.data:
groupName, x, gid, userList = dataList groupName, x, gid, userList = dataList
if groupName in groups: if groupName in groups:
usersList = ",".join(filter(lambda x: x!=userName, usersList = ",".join(filter(lambda x: x != userName,
userList.split(","))) userList.split(",")))
dataList[3] = usersList dataList[3] = usersList
data.append(dataList) data.append(dataList)
self.data = data self.data = data
return self.data return self.data
class shadow(_shareData): class shadow(_shareData):
'''Class for working with the file /etc/shadow''' '''Class for working with the file /etc/shadow'''
fileName = "/etc/shadow" fileName = "/etc/shadow"
template = "%(login)s:%(hash)s:%(shadowLastChange)s:\ template = ("%(login)s:%(hash)s:%(shadowLastChange)s:"
%(shadowMin)s:%(shadowMax)s:%(shadowWarning)s:::" "%(shadowMin)s:%(shadowMax)s:%(shadowWarning)s:::")
lenData = 9 lenData = 9
def add(self, name, pwdHash, def add(self, name, pwdHash,
shadowLastChange=str(int(time.time()/86400)), shadowMin="0", shadowLastChange=str(int(time.time() / 86400)), shadowMin="0",
shadowMax="99999", shadowWarning="7"): shadowMax="99999", shadowWarning="7"):
shadowData = self.template%{'login':name, 'hash':pwdHash, shadowData = self.template % {'login': name, 'hash': pwdHash,
'shadowLastChange':shadowLastChange, 'shadowLastChange': shadowLastChange,
'shadowMin':shadowMin, 'shadowMin': shadowMin,
'shadowMax':shadowMax, 'shadowMax': shadowMax,
'shadowWarning':shadowWarning} 'shadowWarning': shadowWarning}
shadowList = shadowData.split(":") shadowList = shadowData.split(":")
if self.getData() is False: if self.getData() is False:
return False return False
@ -248,32 +268,32 @@ class shadow(_shareData):
return True return True
def equally(self, listDataA, listDataB): def equally(self, listDataA, listDataB):
getData = lambda x: x[:1] + x[2:] getData = lambda x: x[:1] + x[2:]
return _shareData.equally(self, getData(listDataA), return _shareData.equally(self, getData(listDataA),
getData(listDataB)) getData(listDataB))
class _shareCache():
class _shareCache(_shareData):
def save(self): def save(self):
path = os.path.dirname(self.fileName) path = os.path.dirname(self.fileName)
if not os.path.exists(path): if not os.path.exists(path):
try: try:
os.makedirs(path) os.makedirs(path)
except: except OSError:
self.printERROR(_("Failed to create directory %s")%path) self.printERROR(_("Failed to create directory %s") % path)
return False return False
if not os.path.exists(self.fileName): if not os.path.exists(self.fileName):
try: try:
open(self.fileName, "w") open(self.fileName, "w")
except: except IOError:
self.printERROR(_("Failed to create file %s")%self.fileName) self.printERROR(_("Failed to create file %s") % self.fileName)
return False return False
if self.getFileAccess(perm="WRITE"): if self.getFileAccess(perm="WRITE"):
modeFile = 0600 modeFile = 0600
if getModeFile(self.fileName, mode="mode") != modeFile: if getModeFile(self.fileName, mode="mode") != modeFile:
os.chmod(self.fileName, modeFile) os.chmod(self.fileName, modeFile)
buff = "\n".join(map(lambda x: ":".join(x), self.data)) + "\n" buff = "\n".join(map(lambda x: ":".join(x), self.data)) + "\n"
FD = open(self.fileName, "w+") FD = open(self.fileName, "w+")
FD.write(buff) FD.write(buff)
FD.close() FD.close()
return True return True
@ -294,9 +314,11 @@ class _shareCache():
else: else:
return False return False
class cachePasswd(_shareCache, passwd): class cachePasswd(_shareCache, passwd):
fileName = "/var/lib/calculate/calculate-client/cache/passwd" fileName = "/var/lib/calculate/calculate-client/cache/passwd"
class cacheGroup(_shareCache, group): class cacheGroup(_shareCache, group):
fileName = "/var/lib/calculate/calculate-client/cache/group" fileName = "/var/lib/calculate/calculate-client/cache/group"
@ -306,27 +328,31 @@ class cacheGroup(_shareCache, group):
def equally(self, listDataA, listDataB): def equally(self, listDataA, listDataB):
return _shareData.equally(self, listDataA, listDataB) return _shareData.equally(self, listDataA, listDataB)
class cacheShadow(_shareCache, shadow): class cacheShadow(_shareCache, shadow):
fileName = "/var/lib/calculate/calculate-client/cache/shadow" fileName = "/var/lib/calculate/calculate-client/cache/shadow"
class cacheCreateGroup(cacheGroup): class cacheCreateGroup(cacheGroup):
fileName = "/var/lib/calculate/calculate-client/cache/create_group" fileName = "/var/lib/calculate/calculate-client/cache/create_group"
class cacheCreatePasswd(cachePasswd): class cacheCreatePasswd(cachePasswd):
fileName = "/var/lib/calculate/calculate-client/cache/create_passwd" fileName = "/var/lib/calculate/calculate-client/cache/create_passwd"
class userCache(color_print):
class userCache(Printable):
ldapObj = ldapUser() ldapObj = ldapUser()
def addUserToCache(self, userName, pwdHash): def addUserToCache(self, userName, pwdHash):
'''Add LDAP user to cache''' '''Add LDAP user to cache'''
ldapData = self.ldapObj.getUserLdapInfo(userName, shadowAttr=True) ldapData = self.ldapObj.getUserLdapInfo(userName, shadowAttr=True)
if not ldapData: if not ldapData:
self.printERROR(_("User %s not found in LDAP")%userName) self.printERROR(_("User %s not found in LDAP") % userName)
return False return False
groupName = ldapData['group'] groupName = ldapData['group']
# Add user # Add user
cachePasswdObj = cachePasswd() cachePasswdObj = cachePasswd(self)
if not cachePasswdObj.add(userName, ldapData['uid'], ldapData['gid'], if not cachePasswdObj.add(userName, ldapData['uid'], ldapData['gid'],
gecos=ldapData['fullName'], gecos=ldapData['fullName'],
directory=ldapData['home'], directory=ldapData['home'],
@ -334,9 +360,9 @@ class userCache(color_print):
return False return False
if not cachePasswdObj.save(): if not cachePasswdObj.save():
return False return False
cacheGroupObj = cacheGroup() cacheGroupObj = cacheGroup(self)
# Add primary group # Add primary group
if not cacheGroupObj.add(groupName,ldapData['gid']): if not cacheGroupObj.add(groupName, ldapData['gid']):
return False return False
# Add second groups # Add second groups
secondGroupsData = ldapData['groups'] secondGroupsData = ldapData['groups']
@ -353,14 +379,14 @@ class userCache(color_print):
if not cacheGroupObj.add(groupName, gid, usersInGroup): if not cacheGroupObj.add(groupName, gid, usersInGroup):
return False return False
allUsersSecondGroups.append(groupName) allUsersSecondGroups.append(groupName)
deleteSecondGroups = list(set(cacheSecondUserGroups) -\ deleteSecondGroups = list(set(cacheSecondUserGroups) - \
set(allUsersSecondGroups)) set(allUsersSecondGroups))
if not cacheGroupObj.deleteUserInGroups(userName, deleteSecondGroups): if not cacheGroupObj.deleteUserInGroups(userName, deleteSecondGroups):
return False return False
if not cacheGroupObj.save(): if not cacheGroupObj.save():
return False return False
# Add shadow user # Add shadow user
cacheShadowObj = cacheShadow() cacheShadowObj = cacheShadow(self)
if not cacheShadowObj.add(userName, pwdHash, if not cacheShadowObj.add(userName, pwdHash,
shadowLastChange=ldapData['shadowLastChange'], shadowLastChange=ldapData['shadowLastChange'],
shadowMin=ldapData['shadowMin'], shadowMin=ldapData['shadowMin'],
@ -373,14 +399,14 @@ class userCache(color_print):
def delUserFromCacheCreate(self, userName): def delUserFromCacheCreate(self, userName):
'''Delete LDAP user from createCache''' '''Delete LDAP user from createCache'''
cacheCreatePasswdObj = cacheCreatePasswd() cacheCreatePasswdObj = cacheCreatePasswd(self)
cacheUserData = cacheCreatePasswdObj.get(userName) cacheUserData = cacheCreatePasswdObj.get(userName)
if cacheUserData is False: if cacheUserData is False:
return False return False
if not cacheUserData: if not cacheUserData:
return True return True
gid = cacheUserData[3] gid = cacheUserData[3]
cacheCreateGroupObj = cacheCreateGroup() cacheCreateGroupObj = cacheCreateGroup(self)
cacheSecondGroups = cacheCreateGroupObj.getSecondUserGroups(userName) cacheSecondGroups = cacheCreateGroupObj.getSecondUserGroups(userName)
if cacheSecondGroups is False: if cacheSecondGroups is False:
return False return False
@ -393,13 +419,13 @@ class userCache(color_print):
return False return False
if not cacheCreatePasswdObj.save(): if not cacheCreatePasswdObj.save():
return False return False
#delete groups # delete groups
usersGids = map(lambda x: x[3], cacheCreatePasswdObj.data) usersGids = map(lambda x: x[3], cacheCreatePasswdObj.data)
deleteGroups = map(lambda x: x[0], deleteGroups = map(lambda x: x[0],
filter(lambda x: not x[2] in usersGids and not x[3], filter(lambda x: not x[2] in usersGids and not x[3],
cacheCreateGroupObj.data)) cacheCreateGroupObj.data))
for delGroupName in deleteGroups: for delGroupName in deleteGroups:
if not cacheCreateGroupObj.delete(delGroupName): if not cacheCreateGroupObj.delete(delGroupName):
return False return False
if not cacheCreateGroupObj.save(): if not cacheCreateGroupObj.save():
return False return False
@ -407,14 +433,14 @@ class userCache(color_print):
def delUserFromCache(self, userName): def delUserFromCache(self, userName):
'''Delete LDAP user from cache''' '''Delete LDAP user from cache'''
cachePasswdObj = cachePasswd() cachePasswdObj = cachePasswd(self)
cacheUserData = cachePasswdObj.get(userName) cacheUserData = cachePasswdObj.get(userName)
if cacheUserData is False: if cacheUserData is False:
return False return False
if not cacheUserData: if not cacheUserData:
return True return True
gid = cacheUserData[3] gid = cacheUserData[3]
cacheGroupObj = cacheGroup() cacheGroupObj = cacheGroup(self)
cacheSecondGroups = cacheGroupObj.getSecondUserGroups(userName) cacheSecondGroups = cacheGroupObj.getSecondUserGroups(userName)
if cacheSecondGroups is False: if cacheSecondGroups is False:
return False return False
@ -426,18 +452,18 @@ class userCache(color_print):
return False return False
if not cachePasswdObj.save(): if not cachePasswdObj.save():
return False return False
#delete groups # delete groups
usersGids = map(lambda x: x[3], cachePasswdObj.data) usersGids = map(lambda x: x[3], cachePasswdObj.data)
deleteGroups = map(lambda x: x[0], deleteGroups = map(lambda x: x[0],
filter(lambda x: not x[2] in usersGids and not x[3], filter(lambda x: not x[2] in usersGids and not x[3],
cacheGroupObj.data)) cacheGroupObj.data))
for delGroupName in deleteGroups: for delGroupName in deleteGroups:
if not cacheGroupObj.delete(delGroupName): if not cacheGroupObj.delete(delGroupName):
return False return False
if not cacheGroupObj.save(): if not cacheGroupObj.save():
return False return False
# delete shadow user # delete shadow user
cacheShadowObj = cacheShadow() cacheShadowObj = cacheShadow(self)
if not cacheShadowObj.delete(userName): if not cacheShadowObj.delete(userName):
return False return False
if not cacheShadowObj.save(): if not cacheShadowObj.save():
@ -446,13 +472,13 @@ class userCache(color_print):
def delUserFromSystem(self, userName): def delUserFromSystem(self, userName):
'''Delete LDAP user from system files ( passwd, group, shadow )''' '''Delete LDAP user from system files ( passwd, group, shadow )'''
cacheCreatePasswdObj = cacheCreatePasswd() cacheCreatePasswdObj = cacheCreatePasswd(self)
cacheCreatePasswdData = cacheCreatePasswdObj.get(userName) cacheCreatePasswdData = cacheCreatePasswdObj.get(userName)
if cacheCreatePasswdData is False: if cacheCreatePasswdData is False:
return False return False
if not cacheCreatePasswdData: if not cacheCreatePasswdData:
return True return True
passwdObj = passwd() passwdObj = passwd(self)
userData = passwdObj.get(userName) userData = passwdObj.get(userName)
if userData is False: if userData is False:
return False return False
@ -464,18 +490,18 @@ class userCache(color_print):
if not passwdObj.save(): if not passwdObj.save():
return False return False
# delete user group # delete user group
groupObj = group() groupObj = group(self)
listGroupData = groupObj.getData() listGroupData = groupObj.getData()
if listGroupData is False: if listGroupData is False:
return False return False
cacheCreateGroupObj = cacheCreateGroup() cacheCreateGroupObj = cacheCreateGroup(self)
secondUsersGroups = groupObj.getSecondUserGroups(userName) secondUsersGroups = groupObj.getSecondUserGroups(userName)
usersGids = map(lambda x: x[3], passwdObj.data) usersGids = map(lambda x: x[3], passwdObj.data)
listGroupDataWork = [] listGroupDataWork = []
for index, groupData in enumerate(listGroupData): for index, groupData in enumerate(listGroupData):
groupName, x, gid, listUsers = groupData groupName, x, gid, listUsers = groupData
listUsers = filter(lambda x: x.strip(), listUsers.split(',')) listUsers = filter(lambda x: x.strip(), listUsers.split(','))
listUsers = ",".join(filter(lambda x: x!=userName, listUsers)) listUsers = ",".join(filter(lambda x: x != userName, listUsers))
cacheCreateGroupData = cacheCreateGroupObj.get(groupName) cacheCreateGroupData = cacheCreateGroupObj.get(groupName)
if cacheCreateGroupData is False: if cacheCreateGroupData is False:
return False return False
@ -487,7 +513,7 @@ class userCache(color_print):
if not groupObj.save(): if not groupObj.save():
return False return False
# delete user shadow # delete user shadow
shadowObj = shadow() shadowObj = shadow(self)
shadowData = shadowObj.get(userName) shadowData = shadowObj.get(userName)
if shadowData is False: if shadowData is False:
return False return False
@ -515,7 +541,7 @@ class userCache(color_print):
def deleteCacheUsersFromSystem(self): def deleteCacheUsersFromSystem(self):
'''Delete cache users from system''' '''Delete cache users from system'''
cacheCreatePasswdObj = cacheCreatePasswd() cacheCreatePasswdObj = cacheCreatePasswd(self)
cacheCreateListPasswdData = cacheCreatePasswdObj.getData() cacheCreateListPasswdData = cacheCreatePasswdObj.getData()
if cacheCreateListPasswdData is False: if cacheCreateListPasswdData is False:
return False return False
@ -527,7 +553,7 @@ class userCache(color_print):
def getLoginDomainUsers(self): def getLoginDomainUsers(self):
'''Get all domain login users''' '''Get all domain login users'''
cacheCreatePasswdObj = cacheCreatePasswd() cacheCreatePasswdObj = cacheCreatePasswd(self)
cacheListCreatePasswdData = cacheCreatePasswdObj.getData() cacheListCreatePasswdData = cacheCreatePasswdObj.getData()
if cacheListCreatePasswdData is False: if cacheListCreatePasswdData is False:
return False return False
@ -535,19 +561,19 @@ class userCache(color_print):
def addCacheUsersFromSystem(self): def addCacheUsersFromSystem(self):
'''Add cache users from system''' '''Add cache users from system'''
cachePasswdObj = cachePasswd() cachePasswdObj = cachePasswd(self)
cacheListPasswdData = cachePasswdObj.getData() cacheListPasswdData = cachePasswdObj.getData()
if cacheListPasswdData is False: if not isinstance(cacheListPasswdData, (list, tuple)):
return False return False
# Add cache passwd users to system # Add cache passwd users to system
passwdObj = passwd() passwdObj = passwd(self)
cacheCreatePasswdObj = cacheCreatePasswd() cacheCreatePasswdObj = cacheCreatePasswd(self)
cacheListCreatePasswdData = cacheCreatePasswdObj.getData() cacheListCreatePasswdData = cacheCreatePasswdObj.getData()
if cacheListCreatePasswdData is False: if cacheListCreatePasswdData is False:
return False return False
# remove deleted users # remove deleted users
cacheUsers = map(lambda x: x[0], cacheListPasswdData) cacheUsers = map(lambda x: x[0], cacheListPasswdData)
createUsers = map(lambda x: x[0], cacheListCreatePasswdData) createUsers = map(lambda x: x[0], cacheListCreatePasswdData)
deletedUsers = list(set(createUsers) - set(cacheUsers)) deletedUsers = list(set(createUsers) - set(cacheUsers))
for delUser in deletedUsers: for delUser in deletedUsers:
if not self.delUserFromSystem(delUser): if not self.delUserFromSystem(delUser):
@ -573,9 +599,9 @@ class userCache(color_print):
return False return False
if retCacheCreate: if retCacheCreate:
if not passwdObj.add(userName, uid, gid, if not passwdObj.add(userName, uid, gid,
gecos=gecos, gecos=gecos,
directory=directory, directory=directory,
shell=shell): shell=shell):
return False return False
addUsers.append(userName) addUsers.append(userName)
addUsersGid.append(gid) addUsersGid.append(gid)
@ -586,32 +612,32 @@ class userCache(color_print):
return False return False
if not cacheCreatePasswdObj.save(): if not cacheCreatePasswdObj.save():
return False return False
cacheShadowObj = cacheShadow() cacheShadowObj = cacheShadow(self)
cacheListShadowData = cacheShadowObj.getData() cacheListShadowData = cacheShadowObj.getData()
if cacheListShadowData is False: if not isinstance(cacheListShadowData, (list, tuple)):
return False return False
# Add cache shadow users to system # Add cache shadow users to system
shadowObj = shadow() shadowObj = shadow(self)
for cacheShadowData in cacheListShadowData: for cacheShadowData in cacheListShadowData:
userName, pwdHash, shadowLastChange, shadowMin, shadowMax,\ userName, pwdHash, shadowLastChange, shadowMin, shadowMax, \
shadowWarning, x,x,x = cacheShadowData shadowWarning, x, x, x = cacheShadowData
if userName in addUsers: if userName in addUsers:
if not shadowObj.add(userName, pwdHash, if not shadowObj.add(userName, pwdHash,
shadowLastChange=shadowLastChange, shadowLastChange=shadowLastChange,
shadowMin=shadowMin, shadowMin=shadowMin,
shadowMax=shadowMax, shadowMax=shadowMax,
shadowWarning=shadowWarning): shadowWarning=shadowWarning):
return False return False
if shadowObj.data: if shadowObj.data:
if not shadowObj.save(): if not shadowObj.save():
return False return False
cacheGroupObj = cacheGroup() cacheGroupObj = cacheGroup(self)
cacheListGroupData = cacheGroupObj.getData() cacheListGroupData = cacheGroupObj.getData()
if cacheListGroupData is False: if not isinstance(cacheListGroupData, (list, tuple)):
return False return False
cacheCreateGroupObj = cacheCreateGroup() cacheCreateGroupObj = cacheCreateGroup(self)
# Add cache group users to system # Add cache group users to system
groupObj = group() groupObj = group(self)
setAddUsers = set(addUsers) setAddUsers = set(addUsers)
for cacheGroupData in cacheListGroupData: for cacheGroupData in cacheListGroupData:
groupName, x, gid, listUsers = cacheGroupData groupName, x, gid, listUsers = cacheGroupData
@ -641,17 +667,18 @@ class userCache(color_print):
if not self.isConnectToLdap(): if not self.isConnectToLdap():
self.printERROR(_("Failed to connect to the LDAP server")) self.printERROR(_("Failed to connect to the LDAP server"))
return False return False
cachePasswdObj = cachePasswd() cachePasswdObj = cachePasswd(self)
cacheListPasswdData = cachePasswdObj.getData() cacheListPasswdData = cachePasswdObj.getData()
if cacheListPasswdData is False: if cacheListPasswdData is False:
return False return False
if not cacheListPasswdData: if (not isinstance(cacheListPasswdData, (tuple, list)) or
not cacheListPasswdData):
return True return True
cacheGroupObj = cacheGroup() cacheGroupObj = cacheGroup(self)
cacheListGroupData = cacheGroupObj.getData() cacheListGroupData = cacheGroupObj.getData()
if cacheListGroupData is False: if cacheListGroupData is False:
return False return False
cacheShadowObj = cacheShadow() cacheShadowObj = cacheShadow(self)
deletedCacheUsers = [] deletedCacheUsers = []
for cachePasswdData in cacheListPasswdData: for cachePasswdData in cacheListPasswdData:
userName, x, uid, gid, gecos, directory, shell = cachePasswdData userName, x, uid, gid, gecos, directory, shell = cachePasswdData
@ -659,8 +686,8 @@ class userCache(color_print):
if not ldapData: if not ldapData:
deletedCacheUsers.append(userName) deletedCacheUsers.append(userName)
continue continue
cacheGroupData = map(lambda x: x[0], filter(lambda x: x[2]==gid, cacheGroupData = map(lambda x: x[0], filter(lambda x: x[2] == gid,
cacheListGroupData)) cacheListGroupData))
if not cacheGroupData: if not cacheGroupData:
deletedCacheUsers.append(userName) deletedCacheUsers.append(userName)
continue continue
@ -671,29 +698,29 @@ class userCache(color_print):
if not cacheShadowData: if not cacheShadowData:
deletedCacheUsers.append(userName) deletedCacheUsers.append(userName)
continue continue
x,x, shadowLastChange, shadowMin, shadowMax, shadowWarning,\ x, x, shadowLastChange, shadowMin, shadowMax, shadowWarning, \
x,x,x = cacheShadowData x, x, x = cacheShadowData
groups = cacheGroupObj.getSecondUserGroups(userName) groups = cacheGroupObj.getSecondUserGroups(userName)
gidsGroups = map(lambda x: x[2], gidsGroups = map(lambda x: x[2],
filter(lambda x : x[0] in groups, filter(lambda x: x[0] in groups,
cacheGroupObj.data)) cacheGroupObj.data))
userShadowDict = {'uid': uid, userShadowDict = {'uid': uid,
'gid': gid, 'gid': gid,
'fullName': gecos, 'fullName': gecos,
'home': directory, 'home': directory,
'group': groupName, 'group': groupName,
'groups': (groups,gidsGroups), 'groups': (groups, gidsGroups),
'loginShell':shell, 'loginShell': shell,
'shadowLastChange':shadowLastChange, 'shadowLastChange': shadowLastChange,
'shadowMin':shadowMin, 'shadowMin': shadowMin,
'shadowMax':shadowMax, 'shadowMax': shadowMax,
'shadowWarning':shadowWarning} 'shadowWarning': shadowWarning}
flagDeleteUser = False flagDeleteUser = False
for attr, value in userShadowDict.items(): for attr, value in userShadowDict.items():
if attr == "groups": if attr == "groups":
for index, val in enumerate(value): for index, val in enumerate(value):
if set(map(lambda x: x[index], if set(map(lambda x: x[index],
ldapData[attr])) != set(val): ldapData[attr])) != set(val):
flagDeleteUser = True flagDeleteUser = True
break break
else: else:
@ -711,8 +738,8 @@ class userCache(color_print):
def clearCache(self): def clearCache(self):
'''Clear cache files''' '''Clear cache files'''
cacheObjs = (cachePasswd(), cacheShadow(), cacheGroup(), cacheObjs = (cachePasswd(self), cacheShadow(self), cacheGroup(self),
cacheCreateGroup(), cacheCreatePasswd()) cacheCreateGroup(self), cacheCreatePasswd(self))
for cacheObj in cacheObjs: for cacheObj in cacheObjs:
if not cacheObj.save(): if not cacheObj.save():
return False return False

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2012-2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2012-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -15,14 +15,15 @@
# limitations under the License. # limitations under the License.
__app__ = 'calculate-client' __app__ = 'calculate-client'
__version__ = '3.1.8' __version__ = '3.4.2'
import os
import sys import sys
from calculate.lib.datavars import DataVars from calculate.lib.datavars import DataVars
from calculate.lib.cl_lang import setLocalTranslate from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_client3',sys.modules[__name__])
setLocalTranslate('cl_client3', sys.modules[__name__])
class DataVarsClient(DataVars): class DataVarsClient(DataVars):
"""Variable class for client package""" """Variable class for client package"""

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2013-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -15,24 +15,24 @@
# limitations under the License. # limitations under the License.
import sys import sys
from os import path from calculate.core.server.func import Action, Tasks
from calculate.core.server.func import Action,Tasks from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate
from calculate.lib.utils.files import FilesError from calculate.lib.utils.files import FilesError
from calculate.desktop.desktop import DesktopError from calculate.desktop.desktop import DesktopError
from calculate.client.client import ClientError from calculate.client.client import ClientError
from calculate.lib.cl_template import TemplatesError from calculate.lib.cl_template import TemplatesError
from calculate.lib.utils.files import isMount
setLocalTranslate('cl_client3',sys.modules[__name__]) _ = lambda x: x
setLocalTranslate('cl_client3', sys.modules[__name__])
__ = getLazyLocalTranslate(_) __ = getLazyLocalTranslate(_)
class ClClientAction(Action): class ClClientAction(Action):
""" """
Ввести машину в домен или вывести Ввести машину в домен или вывести
""" """
# ошибки, которые отображаются без подробностей # ошибки, которые отображаются без подробностей
native_error = (FilesError,ClientError,DesktopError,TemplatesError) native_error = (FilesError, ClientError, DesktopError, TemplatesError)
successMessage = None successMessage = None
failedMessage = None failedMessage = None
@ -40,114 +40,115 @@ class ClClientAction(Action):
# список задач для действия # список задач для действия
tasks = [ tasks = [
# команда вызвана только для монтировния remote ресурсов # команда вызвана только для монтировния remote ресурсов
{'name':'only_mount', {'name': 'only_mount',
'condition':lambda Get:Get('cl_client_mount_set') == 'on' 'condition': lambda Get: Get('cl_client_mount_set') == 'on'
}, },
# ввод в домен # ввод в домен
{'name':'domain', {'name': 'domain',
'condition':lambda Get:Get('cl_localhost_set') == 'off', 'condition': lambda Get: Get('cl_localhost_set') == 'off',
'depend':Tasks.hasnot('only_mount') 'depend': Tasks.hasnot('only_mount')
}, },
# вывод из домена # вывод из домена
{'name':'undomain', {'name': 'undomain',
'condition':lambda Get:Get('cl_localhost_set') == 'on', 'condition': lambda Get: Get('cl_localhost_set') == 'on',
'depend':Tasks.hasnot('only_mount') 'depend': Tasks.hasnot('only_mount')
}, },
# машина не доменная # машина не доменная
{'name':'only_mount:localpc', {'name': 'only_mount:localpc',
'warning':__("This workstation is not in the domain"), 'warning': __("This workstation is not in the domain"),
'condition':lambda Get:not Get('cl_remote_host') 'condition': lambda Get: not Get('cl_remote_host')
}, },
# проверить может ли указанный сервер являться доменом # проверить может ли указанный сервер являться доменом
{'name':'domain:check_domain', {'name': 'domain:check_domain',
'message':__("Checking {cl_remote_host_new} for domain resources"), 'message': __("Checking {cl_remote_host_new} for domain resources"),
'method':'Client.checkDomainServer(cl_remote_host_new,os_net_domain)', 'method': 'Client.checkDomainServer(cl_remote_host_new,os_net_domain)',
}, },
# получить пароль для ввода в домен (или воспользоваться кэшированным) # получить пароль для ввода в домен (или воспользоваться кэшированным)
{'name':'domain:get_password', {'name': 'domain:get_password',
'method':'Client.getDomainPassword(cl_remote_host_new)' 'method': 'Client.getDomainPassword(cl_remote_host_new)'
}, },
{'name':'domain:set_remote_host', {'name': 'domain:set_remote_host',
'method':'Client.setVariable("cl_remote_host",cl_remote_host_new)' 'method': 'Client.setVariable("cl_remote_host",cl_remote_host_new)'
}, },
# машина доменная # машина доменная
{'name':'mount_remote', {'name': 'mount_remote',
'method':'Client.mountRemoteRes(cl_remote_pw,cl_client_remote_path,' 'method': 'Client.mountRemoteRes(cl_remote_pw,cl_client_remote_path,'
'cl_remote_host)', 'cl_remote_host)',
'depend':Tasks.success() & Tasks.hasnot('localpc','undomain') 'depend': Tasks.success() & Tasks.hasnot('localpc', 'undomain')
}, },
# отключить удаленный доменный ресурс # отключить удаленный доменный ресурс
{'name':'undomain:unmount_remote', {'name': 'undomain:unmount_remote',
'method':'Client.umountSleepPath(cl_client_remote_path)', 'method': 'Client.umountSleepPath(cl_client_remote_path)',
}, },
# удалить переменные клиента # удалить переменные клиента
{'name':'undomain:remove_vars', {'name': 'undomain:remove_vars',
'method':'Client.removeVars()' 'method': 'Client.removeVars()'
}, },
# наложить шаблоны если они не актуальны # наложить шаблоны если они не актуальны
{'name':'need_templates', {'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']) 'depend': Tasks.success(inessential=['mount_remote'])
}, },
# проверить информацию для ldap расположенную в домене # проверить информацию для ldap расположенную в домене
{'name':'domain:check_domain_info', {'name': 'domain:check_domain_info',
'method':'Client.checkDomainInfo(cl_remote_host)', 'method': 'Client.checkDomainInfo(cl_remote_host)',
}, },
# наложить доменные шаблоны, если успешно подключен удаленный ресурс # наложить доменные шаблоны, если успешно подключен удаленный ресурс
{'name':'need_templates:apply_templates', {'name': 'need_templates:apply_templates',
'message':__("Applying domain templates"), 'message': __("Applying domain templates"),
'method':'Client.applyClientTemplates(cl_remote_host)', 'method': 'Client.applyClientTemplates(cl_remote_host)',
'depend':Tasks.success_all('mount_remote') 'depend': Tasks.success_all('mount_remote')
}, },
# наложить недоменные шаблоны в случае локального режима # наложить недоменные шаблоны в случае локального режима
# или были проблемы с подключением удаленноых ресурсов # или были проблемы с подключением удаленноых ресурсов
{'name':'need_templates:apply_templates', {'name': 'need_templates:apply_templates',
'message':__("Applying non-domain templates"), 'message': __("Applying non-domain templates"),
'method':'Client.applyClientTemplates("")', 'method': 'Client.applyClientTemplates("")',
'depend':Tasks.result('mount_remote',ne=True) 'depend': Tasks.result('mount_remote', ne=True)
}, },
# удалить записи из /etc/passwd и синхронизировать кэш # удалить записи из /etc/passwd и синхронизировать кэш
{'name':'del_sync_cache', {'name': 'del_sync_cache',
'method':'Client.cDelLdapSysUsersAndSyncCache()', 'method': 'Client.cDelLdapSysUsersAndSyncCache()',
'condition':lambda Get:Get('cl_remote_host'), 'condition': lambda Get: Get('cl_remote_host'),
'depend':Tasks.success_all('mount_remote','need_templates') 'depend': Tasks.success_all('mount_remote', 'need_templates')
}, },
# удалить записи из /etc/passwd и очистить кэш # удалить записи из /etc/passwd и очистить кэш
{'name':'undomain:del_clear_cache', {'name': 'undomain:del_clear_cache',
'message':__("Clearing the user cache"), 'message': __("Clearing the user cache"),
'method':'Client.cDelLdapSysUsersAndClearCache()' 'method': 'Client.cDelLdapSysUsersAndClearCache()'
}, },
# синхронизировать кэш, добавить записи в /etc/passwd # синхронизировать кэш, добавить записи в /etc/passwd
{'name':'only_mount:add_sync_cache', {'name': 'only_mount:add_sync_cache',
'method':'Client.cAddCacheUsersFromSystem()', 'method': 'Client.cAddCacheUsersFromSystem()',
'depend':Tasks.failed_all('mount_remote') 'depend': Tasks.failed_all('mount_remote')
}, },
# удалить службу client из автозапуска # удалить службу client из автозапуска
{'name':'undomain:noautorun_client', {'name': 'undomain:noautorun_client',
'method':'Client.delDaemonAutostart("client")' 'method': 'Client.delDaemonAutostart("client")'
}, },
# добавить службу client в автозапуск # добавить службу client в автозапуск
{'name':'domain:autorun_client', {'name': 'domain:autorun_client',
'method':'Client.addDaemonAutostart("client")' 'method': 'Client.addDaemonAutostart("client")'
}, },
# записать переменные клиента # записать переменные клиента
{'name':'domain:write_vars', {'name': 'domain:write_vars',
'method':'Client.writeClientVars(cl_remote_host,cl_ver,cl_remote_pw)', 'method': 'Client.writeClientVars(cl_remote_host,cl_ver,cl_remote_pw)',
}, },
# сообщения о результатах работы действия # сообщения о результатах работы действия
{'name':'domain:success', {'name': 'domain:success',
'message':__("Workstation added to domain {cl_remote_host}") 'message': __("Workstation added to domain {cl_remote_host}")
}, },
{'name':'domain:failed', {'name': 'domain:failed',
'error':__("Failed to add the workstation to domain {cl_remote_host}"), 'error': __(
'depend':Tasks.failed() & Tasks.hasnot("interrupt"), "Failed to add the workstation to domain {cl_remote_host}"),
}, 'depend': Tasks.failed() & Tasks.hasnot("interrupt"),
{'name':'undomain:success', },
'message':__("Workstation removed from domain {cl_remote_host}") {'name': 'undomain:success',
}, 'message': __("Workstation removed from domain {cl_remote_host}")
{'name':'undomain:failed', },
'error':__("Failed to remove the workstation from the domain"), {'name': 'undomain:failed',
'depend':Tasks.failed() & Tasks.hasnot("interrupt"), 'error': __("Failed to remove the workstation from the domain"),
}, 'depend': Tasks.failed() & Tasks.hasnot("interrupt"),
] },
]

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2013-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -16,230 +16,237 @@
import sys import sys
from os import path from os import path
from calculate.core.server.func import Action,Tasks from calculate.core.server.func import Action, Tasks
from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
from calculate.lib.utils.files import FilesError from calculate.lib.utils.files import FilesError
from calculate.desktop.desktop import DesktopError from calculate.desktop.desktop import DesktopError
from calculate.client.client import ClientError from calculate.client.client import ClientError
from calculate.lib.cl_template import TemplatesError from calculate.lib.cl_template import TemplatesError
from calculate.lib.utils.files import isMount from calculate.lib.utils.files import isMount
setLocalTranslate('cl_client3',sys.modules[__name__]) _ = lambda x: x
setLocalTranslate('cl_client3', sys.modules[__name__])
__ = getLazyLocalTranslate(_) __ = getLazyLocalTranslate(_)
class ClClientSyncLoginAction(Action): class ClClientSyncLoginAction(Action):
""" """
Синхронизировать локальный профиль с удаленным, подключить удаленные Синхронизировать локальный профиль с удаленным, подключить удаленные
ресурсы пользователя ресурсы пользователя
""" """
native_error = (FilesError,ClientError,DesktopError,TemplatesError) native_error = (FilesError, ClientError, DesktopError, TemplatesError)
successMessage = None successMessage = None
failedMessage = None failedMessage = None
interruptMessage = __("Synchronization manually interrupted") interruptMessage = __("Synchronization manually interrupted")
tasks = [ tasks = [
# подключить удаленный ресурс домена # подключить удаленный ресурс домена
{'name':'mount_remote', {'name': 'mount_remote',
'method':'Client.mountRemoteRes(cl_remote_pw,cl_client_remote_path,' 'method': 'Client.mountRemoteRes(cl_remote_pw,cl_client_remote_path,'
'cl_remote_host)', 'cl_remote_host)',
'condition':lambda Get: (Get('cl_remote_host') and 'condition': lambda Get: (Get('cl_remote_host') and
Get('os_remote_auth') and Get('os_remote_auth') and
not isMount(Get('cl_client_remote_path'))), not isMount(Get('cl_client_remote_path'))),
}, },
# check on domain user # check on domain user
{'name':'domain_user', {'name': 'domain_user',
'condition':lambda Get: (Get('os_remote_auth') and 'condition': lambda Get: (Get('os_remote_auth') and
Get('cl_remote_host') and Get('cl_remote_host') and
Get('desktop.ur_domain_set') == 'on'), Get('desktop.ur_domain_set') == 'on'),
'else_message':__("The local profile will be used") 'else_message': __("The local profile will be used")
}, },
{'name':'domain_user:create_home', {'name': 'domain_user:create_home',
'message':__("Creating the home directory for {ur_login}"), 'message': __("Creating the home directory for {ur_login}"),
'method':'Client.createUserDirectory(ur_home_path,ur_uid,' 'method': 'Client.createUserDirectory(ur_home_path,ur_uid,'
'ur_gid)', 'ur_gid)',
'condition':lambda Get:not path.exists(Get('ur_home_path')) 'condition': lambda Get: not path.exists(Get('ur_home_path'))
}, },
# password in kernel key # password in kernel key
{'name':'domain_user:check_password', {'name': 'domain_user:check_password',
'condition':lambda Get:Get('desktop.ur_password'), 'condition': lambda Get: Get('desktop.ur_password'),
'else_error':__("User password not found") 'else_error': __("User password not found")
}, },
{'name':'ecryptfs', {'name': 'ecryptfs',
'message':__("Mounting encrypted data"), 'message': __("Mounting encrypted data"),
'method':'Desktop.createCryptDir(ur_login,ur_uid,ur_gid,' 'method': 'Desktop.createCryptDir(ur_login,ur_uid,ur_gid,'
'ur_home_path,True)', 'ur_home_path,True)',
'condition':lambda Get:(Get('desktop.ur_home_crypt_set') == 'on' and 'condition': lambda Get: (Get('desktop.ur_home_crypt_set') == 'on' and
Get('install.cl_autologin') != Get('ur_login')) Get('install.cl_autologin') != Get(
}, 'ur_login'))
{'name':'domain_user:add_to_cache', },
'essential':False, {'name': 'domain_user:add_to_cache',
'method':'Client.cAddUserToCache(ur_login,desktop.ur_password)', 'essential': False,
'failed_warning':__("Unable to cache user info") 'method': 'Client.cAddUserToCache(ur_login,desktop.ur_password)',
}, 'failed_warning': __("Unable to cache user info")
# подключить удаленные ресурсы пользователя },
{'name':'domain_user:mount_resources', # подключить удаленные ресурсы пользователя
'message':__("Mounting user resources"), {'name': 'domain_user:mount_resources',
'method':'Client.mountUserDomainRes(ur_login,' 'message': __("Mounting user resources"),
'desktop.ur_password,' 'method': 'Client.mountUserDomainRes(ur_login,'
'ur_uid,ur_gid,"unix","share","homes","ftp")', 'desktop.ur_password,'
}, 'ur_uid,ur_gid,"unix","share","homes","ftp")',
# проверка на попытку открыть вторую сессию для этого пользователя },
{'name':'two_session', # проверка на попытку открыть вторую сессию для этого пользователя
'error': {'name': 'two_session',
__("A second X session cannot be opened for user {ur_login}."), 'error':
'condition':lambda dv: (dv.Get('ur_login') in __("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 dv.Get('desktop.cl_desktop_online_user') and
int(dv.Select('desktop.cl_desktop_online_count', int(dv.Select(
where='desktop.cl_desktop_online_user', 'desktop.cl_desktop_online_count',
eq=dv.Get('ur_login'),limit=1) > 1) and where='desktop.cl_desktop_online_user',
dv.Get('cl_client_sync') == 'on') 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")', {'name': 'domain_user:domain_sync',
'condition':lambda Get:Get('cl_client_sync') == 'on' '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,' {'name': 'domain_sync:repl_profile',
'ur_uid,ur_gid,"unix","remote_profile")', 'method': 'Client.mountUserDomainRes(ur_login,desktop.ur_password,'
'condition':lambda Get:Get('cl_replication_host') 'ur_uid,ur_gid,"unix","remote_profile")',
}, 'condition': lambda Get: Get('cl_replication_host')
# отправить команду архивирования профиля на удаленном домене },
# если он новее локального профиля # отправить команду архивирования профиля на удаленном домене
{'name':'repl_profile:pack_remote', # если он новее локального профиля
'method':'Client.packRemote("remote_profile",' {'name': 'repl_profile:pack_remote',
'cl_client_local_sync_time,cl_client_pack_time,' 'method': 'Client.packRemote("remote_profile",'
'cl_client_profile_name,ur_uid,ur_gid)', 'cl_client_local_sync_time,cl_client_pack_time,'
'condition':lambda Get:Get('cl_client_sync_replication_set') == 'on', 'cl_client_profile_name,ur_uid,ur_gid)',
'else_message':__("The local user profile does not " '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") "need to be synchronized with the remote domain")
}, },
# монтируем профиль локального домена, если локальный профиль # монтируем профиль локального домена, если локальный профиль
# старее удаленного доменного или актуальный профиль # старее удаленного доменного или актуальный профиль
{'name':'domain_sync:mount_local', {'name': 'domain_sync:mount_local',
'method':'Client.mountUserDomainRes(ur_login,desktop.ur_password,' 'method': 'Client.mountUserDomainRes(ur_login,desktop.ur_password,'
'ur_uid,ur_gid,"unix")', 'ur_uid,ur_gid,"unix")',
# нет более ранних ошибок и локальный профиль нуждается # нет более ранних ошибок и локальный профиль нуждается
# в синхронизации с удаленным или профиль на локальном домене # в синхронизации с удаленным или профиль на локальном домене
'depend':(Tasks.success_all('mount_resources') & 'depend': (Tasks.success_all('mount_resources') &
(Tasks.hasnot('repl_profile') | (Tasks.hasnot('repl_profile') |
Tasks.has('pack_remote'))) Tasks.has('pack_remote')))
}, },
# синхронизируем с профилем локального домена # синхронизируем с профилем локального домена
{'name':'mount_local!:sync_local', {'name': 'mount_local!:sync_local',
'method':'Client.syncLoginProfile(cl_remote_host,ur_uid,' 'method': 'Client.syncLoginProfile(cl_remote_host,ur_uid,'
'ur_gid,ur_home_path,"unix",cl_client_profile_name)', 'ur_gid,ur_home_path,"unix",cl_client_profile_name)',
'condition':lambda Get:Get('cl_client_sync_local_set') == 'on', 'condition': lambda Get: Get('cl_client_sync_local_set') == 'on',
'else_message':__("The local user profile does not " 'else_message': __("The local user profile does not "
"need to be synchronized with the local domain") "need to be synchronized with the local domain")
}, },
# ошибка синхронизации с локальным доменом # ошибка синхронизации с локальным доменом
{'name':'local_sync_error', {'name': 'local_sync_error',
'warning':__("Error synchronizing with the local server {cl_remote_host}"), 'warning': __(
'depend':Tasks.failed_one_of("mount_local","sync_local") "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,' {'name': 'repl_profile:repeat_repl_profile',
'ur_uid,ur_gid,"remote_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"), {'name': 'pack_remote:wait_archive',
'method':'Client.waitingArchFile(cl_client_pack_time,' 'message': __("Packing the archive on the server"),
'cl_client_profile_name,"remote_profile")', 'method': 'Client.waitingArchFile(cl_client_pack_time,'
'failed_warning':__("Failed to find the profile " 'cl_client_profile_name,"remote_profile")',
'failed_warning': __("Failed to find the profile "
"archive of {cl_replication_host}") "archive of {cl_replication_host}")
}, },
# распаковать архив из удаленного домена и удалить # распаковать архив из удаленного домена и удалить
# файлы которые отсутствуют в удаленном профиле # файлы которые отсутствуют в удаленном профиле
{'name':'wait_archive:unpack_profile', {'name': 'wait_archive:unpack_profile',
'message':__("Unpacking the profile"), 'message': __("Unpacking the profile"),
'method':'Client.unpackArch(ur_home_path,cl_client_pack_time,' 'method': 'Client.unpackArch(ur_home_path,cl_client_pack_time,'
'cl_client_profile_name,"remote_profile")', 'cl_client_profile_name,"remote_profile")',
'failed_warning':__("Failed to unpack") 'failed_warning': __("Failed to unpack")
}, },
# удалить временные архивы # удалить временные архивы
{'name':'clean_archfiles', {'name': 'clean_archfiles',
'method':'Client.cleanArchs(cl_client_pack_time,' 'method': 'Client.cleanArchs(cl_client_pack_time,'
'cl_client_profile_name,"remote_profile")', 'cl_client_profile_name,"remote_profile")',
'failed_warning':__("Unable to remove useless files"), 'failed_warning': __("Unable to remove useless files"),
'essential':False, 'essential': False,
'depend': Tasks.has('pack_remote') 'depend': Tasks.has('pack_remote')
}, },
# синхронизировать профиль с удаленным доменом в случае ошибки # синхронизировать профиль с удаленным доменом в случае ошибки
{'name':'repl_profile:sync_remote', {'name': 'repl_profile:sync_remote',
'method':'Client.syncLoginProfile(cl_replication_host,ur_uid,' 'method': 'Client.syncLoginProfile(cl_replication_host,ur_uid,'
'ur_gid,ur_home_path,"remote_profile",' 'ur_gid,ur_home_path,"remote_profile",'
'cl_client_profile_name)', 'cl_client_profile_name)',
'depend':Tasks.failed_one_of('pack_remote','mount_local','sync_local', 'depend': Tasks.failed_one_of('pack_remote', 'mount_local',
'wait_archive','unpack_profile'), 'sync_local',
'condition':lambda Select:isMount( 'wait_archive', 'unpack_profile'),
Select('cl_client_user_mount_path', 'condition': lambda Select: isMount(
where='cl_client_user_mount_name',eq='remote_profile', Select('cl_client_user_mount_path',
limit=1)) where='cl_client_user_mount_name', eq='remote_profile',
}, limit=1))
# если синхронизация с удаленным доменом прошла с ошибкой },
# синхронизировать локальный профиль с локальным доменом # если синхронизация с удаленным доменом прошла с ошибкой
# как запасной профиль # синхронизировать локальный профиль с локальным доменом
{'name':'pack_remote:fallback_warning', # как запасной профиль
'warning':__("Error synchronizing with the " {'name': 'pack_remote:fallback_warning',
'warning': __("Error synchronizing with the "
"{cl_replication_host} remote server"), "{cl_replication_host} remote server"),
'depend': ~Tasks.success_one_of('unpack_profile','sync_remote') 'depend': ~Tasks.success_one_of('unpack_profile', 'sync_remote')
}, },
{'name':'pack_remote:fallback_sync', {'name': 'pack_remote:fallback_sync',
'method':'Client.syncLoginProfile(cl_remote_host,ur_uid,' 'method': 'Client.syncLoginProfile(cl_remote_host,ur_uid,'
'ur_gid,ur_home_path,"unix",cl_client_profile_name)', 'ur_gid,ur_home_path,"unix",cl_client_profile_name)',
'depend': ~Tasks.success_one_of('unpack_profile','sync_remote') 'depend': ~Tasks.success_one_of('unpack_profile', 'sync_remote')
}, },
# отключить профиль на удаленном домене # отключить профиль на удаленном домене
{'name':'repl_profile!:umount_remote_profile', {'name': 'repl_profile!:umount_remote_profile',
'method':'Client.umountRemoteUserRes(True,"remote_profile")', 'method': 'Client.umountRemoteUserRes(True,"remote_profile")',
}, },
# сообщение о том, что будет использоваться запасной профиль # сообщение о том, что будет использоваться запасной профиль
# с локального домена # с локального домена
{'name':'fallback_sync!:fallback_success', {'name': 'fallback_sync!:fallback_success',
'message': __("Got a user fallback profile from the " 'message': __("Got a user fallback profile from the "
"{cl_remote_host} domain") "{cl_remote_host} domain")
}, },
# ошибка синхронизации профиль не готов! к использованию # ошибка синхронизации профиль не готов! к использованию
{'name':'failed', {'name': 'failed',
'error':__("Failed to get the user profile from the domain"), 'error': __("Failed to get the user profile from the domain"),
'method':'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"error")', 'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"error")',
'depend':Tasks.failed_all('sync_remote','sync_local','fallback_sync') | 'depend': Tasks.failed_all('sync_remote', 'sync_local',
'fallback_sync') |
(Tasks.hasnot('domain_sync') & Tasks.failed()) | (Tasks.hasnot('domain_sync') & Tasks.failed()) |
Tasks.failed_one_of('mount_resources','two_session') Tasks.failed_one_of('mount_resources', 'two_session')
}, },
# распаковать ссылки # распаковать ссылки
{'name':'domain_sync:unpack_links', {'name': 'domain_sync:unpack_links',
'method':'Client.unpackLinks(ur_home_path)', 'method': 'Client.unpackLinks(ur_home_path)',
'failed_warning': __("Failed to unpack the links archive"), 'failed_warning': __("Failed to unpack the links archive"),
'depend':Tasks.hasnot('failed') 'depend': Tasks.hasnot('failed')
}, },
# синхронизация профиля завершилась успешно # синхронизация профиля завершилась успешно
{'name':'domain_sync:success_sync', {'name': 'domain_sync:success_sync',
'message':__("User profile fetched from the domain"), 'message': __("User profile fetched from the domain"),
'method':'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"success")', 'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"success")',
'depend': Tasks.success_all('sync_remote','unpack_links') | 'depend': Tasks.success_all('sync_remote', 'unpack_links') |
Tasks.success() Tasks.success()
}, },
# во время синхронизации профиля произошли ошибки, которые не # во время синхронизации профиля произошли ошибки, которые не
# гарантируют целостность профиля # гарантируют целостность профиля
{'name':'domain_sync:error_sync', {'name': 'domain_sync:error_sync',
'warning':__("User profile modifications will not " 'warning': __("User profile modifications will not "
"be saved to the domain"), "be saved to the domain"),
'method':'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"error")', 'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,"error")',
'depend': Tasks.hasnot('success_sync','failed') 'depend': Tasks.hasnot('success_sync', 'failed')
}, },
# отключить ресурсы в случае ошибки # отключить ресурсы в случае ошибки
{'name':'umount_remote_res', {'name': 'umount_remote_res',
'message':__("Umounting user resources"), 'message': __("Umounting user resources"),
'method':'Client.umountUserRes(desktop.ur_mount_dirs)', 'method': 'Client.umountUserRes(desktop.ur_mount_dirs)',
'depend':Tasks.has('failed') 'depend': Tasks.has('failed')
} }
] ]
class ClClientSyncLogoutAction(Action): class ClClientSyncLogoutAction(Action):
@ -247,99 +254,100 @@ class ClClientSyncLogoutAction(Action):
Синхронизировать локальный профиль с удаленным, отключить удаленные Синхронизировать локальный профиль с удаленным, отключить удаленные
ресурсы пользователя ресурсы пользователя
""" """
native_error = (FilesError,ClientError,DesktopError,TemplatesError) native_error = (FilesError, ClientError, DesktopError, TemplatesError)
successMessage = None successMessage = None
failedMessage = None failedMessage = None
interruptMessage = __("Synchronization manually interrupted") interruptMessage = __("Synchronization manually interrupted")
tasks = [ tasks = [
# проверка доменный ли пользователь # проверка доменный ли пользователь
{'name':'domain_user', {'name': 'domain_user',
'condition':lambda Get: (Get('os_remote_auth') and 'condition': lambda Get: (Get('os_remote_auth') and
Get('cl_remote_host') and Get('cl_remote_host') and
Get('desktop.ur_domain_set') == 'on'), Get('desktop.ur_domain_set') == 'on'),
'else_message':__("The local profile will be used") 'else_message': __("The local profile will be used")
}, },
# проверка на попытку отключить ресурсы пользователя в X сессии # проверка на попытку отключить ресурсы пользователя в X сессии
{'name':'domain_user:in_xsession', {'name': 'domain_user:in_xsession',
'error':__("User {ur_login} is already on the X session"), 'error': __("User {ur_login} is already on the X session"),
'condition':lambda Get:Get('ur_login') in \ 'condition': lambda Get: Get('ur_login') in
Get('desktop.cl_desktop_online_user'), Get('desktop.cl_desktop_online_user'),
}, },
# проверить наличие домашней директории # проверить наличие домашней директории
{'name':'domain_user:check_homedir', {'name': 'domain_user:check_homedir',
'condition':lambda Get:path.exists(Get('ur_home_path')), 'condition': lambda Get: path.exists(Get('ur_home_path')),
'else_error':__("Home directory {ur_home_path} not found"), 'else_error': __("Home directory {ur_home_path} not found"),
}, },
# проверить наличие подключенных ресурсов # проверить наличие подключенных ресурсов
{'name':'domain_user:check_mount', {'name': 'domain_user:check_mount',
'condition':lambda Get:any(x and isMount(x) 'condition': lambda Get: any(x and isMount(x)
for x in Get('cl_client_user_mount_path')), for x in
'else_error':__("Remote user resources not found") 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: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 {'name': 'domain_user:domain_sync',
Get('cl_client_sync') == 'on', 'condition': lambda Get: Get('cl_client_sync_status') == 'success' and
'else_warning':__("The profile will not be uploaded to the domain") Get('cl_client_sync') == 'on',
}, 'else_warning': __("The profile will not be uploaded to the domain")
# переместить файлы из профиля в Moved },
{'name':'domain_user:move_home_dir', # переместить файлы из профиля в Moved
'message':__("Moving non-profile files to the Home/Moved directory"), {'name': 'domain_user:move_home_dir',
'method':'Client.moveHomeDir(ur_home_path,"Moved","homes",' 'message': __("Moving non-profile files to the Home/Moved directory"),
'method': 'Client.moveHomeDir(ur_home_path,"Moved","homes",'
'cl_moved_skip_path)', 'cl_moved_skip_path)',
}, },
# архивировать симлинки # архивировать симлинки
{'name':'domain_sync:tar_symlinks', {'name': 'domain_sync:tar_symlinks',
'method':'Client.tarSymLinks(ur_uid,ur_gid,ur_home_path,' 'method': 'Client.tarSymLinks(ur_uid,ur_gid,ur_home_path,'
'cl_sync_del_path,cl_sync_skip_path)', 'cl_sync_del_path,cl_sync_skip_path)',
'failed_error':_("Failed to make a links archive") 'failed_error': _("Failed to make a links archive")
}, },
# закачать профиль пользователя в домен # закачать профиль пользователя в домен
{'name':'domain_sync:sync_logout', {'name': 'domain_sync:sync_logout',
'method':'Client.syncLogoutProfile(cl_remote_host,ur_uid,' 'method': 'Client.syncLogoutProfile(cl_remote_host,ur_uid,'
'ur_gid,ur_home_path,"unix",cl_client_profile_name,' 'ur_gid,ur_home_path,"unix",cl_client_profile_name,'
'cl_client_symlinks)', 'cl_client_symlinks)',
}, },
# удалить файлы, которые могут помешать следующему входу в сеанс # удалить файлы, которые могут помешать следующему входу в сеанс
{'name':'domain_sync:remove_noise_files', {'name': 'domain_sync:remove_noise_files',
'message':__("Removing hindering files"), 'message': __("Removing hindering files"),
'method':'Client.removeNoiseFiles(ur_home_path)' 'method': 'Client.removeNoiseFiles(ur_home_path)'
}, },
# удалить "личные" файлы # удалить "личные" файлы
{'name':'domain_sync:remove_private_files', {'name': 'domain_sync:remove_private_files',
'message':__("Removing user private files"), 'message': __("Removing user private files"),
'method':'Client.removePrivateFiles(ur_home_path)' 'method': 'Client.removePrivateFiles(ur_home_path)'
}, },
# удалить пользовательские ключи ядра # удалить пользовательские ключи ядра
{'name':'domain_user!:clear_user_key', {'name': 'domain_user!:clear_user_key',
'message':__("Clearing user keys"), 'message': __("Clearing user keys"),
'method':'Client.clearUserKey(ur_login)' 'method': 'Client.clearUserKey(ur_login)'
}, },
# отключить пользовательские ресурсы # отключить пользовательские ресурсы
{'name':'check_mount!:umount_user_res', {'name': 'check_mount!:umount_user_res',
'message':__("Umounting user resources"), 'message': __("Umounting user resources"),
'method':'Client.umountUserRes(desktop.ur_mount_dirs)', 'method': 'Client.umountUserRes(desktop.ur_mount_dirs)',
}, },
# установить статус синхронизации # установить статус синхронизации
{'name':'domain_sync:success_sync', {'name': 'domain_sync:success_sync',
'message':__("Modified user profile saved in the domain"), 'message': __("Modified user profile saved in the domain"),
'method':'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,' 'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,'
'"success_logout")', '"success_logout")',
'depend': Tasks.success_all('sync_logout','check_mount') 'depend': Tasks.success_all('sync_logout', 'check_mount')
}, },
{'name':'domain_sync:failed', {'name': 'domain_sync:failed',
'error':__("Modified user profile saved in the domain with errors"), 'error': __("Modified user profile saved in the domain with errors"),
'method':'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,' 'method': 'Client.setSyncStatus(ur_home_path,ur_uid,ur_gid,'
'"error")', '"error")',
'depend': Tasks.hasnot('success_sync') 'depend': Tasks.hasnot('success_sync')
}, },
{'name':'umount_allres', {'name': 'umount_allres',
'method':'Desktop.umountUserRes(ur_home_path)', 'method': 'Desktop.umountUserRes(ur_home_path)',
} }
] ]

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2013-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -15,23 +15,24 @@
# limitations under the License. # limitations under the License.
import sys import sys
from os import path from calculate.core.server.func import Action
from calculate.core.server.func import Action,Tasks from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate
from calculate.lib.utils.files import FilesError from calculate.lib.utils.files import FilesError
from calculate.desktop.desktop import DesktopError from calculate.desktop.desktop import DesktopError
from calculate.client.client import ClientError from calculate.client.client import ClientError
from calculate.lib.cl_template import TemplatesError from calculate.lib.cl_template import TemplatesError
setLocalTranslate('cl_client3',sys.modules[__name__]) _ = lambda x: x
setLocalTranslate('cl_client3', sys.modules[__name__])
__ = getLazyLocalTranslate(_) __ = getLazyLocalTranslate(_)
class ClPasswdAction(Action): class ClPasswdAction(Action):
""" """
Изменить пароль доменного пользователя Изменить пароль доменного пользователя
""" """
# ошибки, которые отображаются без подробностей # ошибки, которые отображаются без подробностей
native_error = (FilesError,DesktopError,TemplatesError,ClientError) native_error = (FilesError, DesktopError, TemplatesError, ClientError)
successMessage = (__("{cl_client_login}'s password changed\n" successMessage = (__("{cl_client_login}'s password changed\n"
"This modification will be applied when " "This modification will be applied when "
@ -41,7 +42,7 @@ class ClPasswdAction(Action):
# список задач для действия # список задач для действия
tasks = [ tasks = [
{'name':'change_passwd', {'name': 'change_passwd',
'method':'Client.clientPasswd(cl_client_login,ur_uid,ur_gid,' 'method': 'Client.clientPasswd(cl_client_login,ur_uid,ur_gid,'
'ur_home_path,ur_user_new_pw,ur_user_pw)', 'ur_home_path,ur_user_new_pw,ur_user_pw)',
}] }]

@ -1,4 +1,4 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2008-2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2008-2013 Calculate Ltd. http://www.calculate-linux.org
# #
@ -14,14 +14,13 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import os
import sys import sys
from os import path from calculate.lib.datavars import ActionVariable
from calculate.lib.datavars import (Variable,VariableError,ReadonlyVariable,
ActionVariable)
from calculate.lib.cl_lang import setLocalTranslate from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_client3',sys.modules[__name__])
setLocalTranslate('cl_client3', sys.modules[__name__])
class VariableAcClientMerge(ActionVariable): class VariableAcClientMerge(ActionVariable):
""" """
@ -30,34 +29,36 @@ class VariableAcClientMerge(ActionVariable):
""" """
nonchroot = True nonchroot = True
def action(self,cl_action): def action(self, cl_action):
if cl_action in ("merge","domain","undomain"): if cl_action in ("merge", "domain", "undomain"):
ret = "on" return "on"
return "off" return "off"
class VariableAcClientDomain(ActionVariable): class VariableAcClientDomain(ActionVariable):
""" """
Action variable which has value "on" for domain action Action variable which has value "on" for domain action
""" """
nonchroot = True nonchroot = True
def action(self,cl_action): def action(self, cl_action):
remoteHost = self.Get("cl_remote_host") remoteHost = self.Get("cl_remote_host")
remoteAuth = self.Get("os_remote_auth") remoteAuth = self.Get("os_remote_auth")
if cl_action == "domain": if cl_action == "domain":
return "on" return "on"
elif ((cl_action in ("merge",'sync') and self.Get('cl_merge_pkg')) elif ((cl_action in ("merge", 'sync') and self.Get('cl_merge_pkg'))
and remoteHost and remoteAuth): and remoteHost and remoteAuth):
return "on" return "on"
return "off" return "off"
class VariableAcClientUndomain(ActionVariable): class VariableAcClientUndomain(ActionVariable):
""" """
Action variable which has value "on" for undomain action Action variable which has value "on" for undomain action
""" """
nonchroot = True nonchroot = True
def action(self,cl_action): def action(self, cl_action):
if cl_action in ("undomain",): if cl_action in ("undomain",):
return "on" return "on"
return "off" return "off"

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2008-2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2008-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -18,12 +18,13 @@ import os
import sys import sys
from os import path from os import path
import re import re
from calculate.lib.datavars import (Variable,VariableError,ReadonlyVariable, from calculate.lib.datavars import (Variable, VariableError, ReadonlyVariable,
ReadonlyTableVariable,FieldValue) ReadonlyTableVariable, FieldValue,
from calculate.lib.cl_template import iniParser HumanReadable)
from calculate.lib.utils.files import (readLinesFile,isMount,readFile, find, from calculate.lib.cl_ini_parser import iniParser
FindFileType) from calculate.lib.utils.files import (isMount, readFile, find,
from calculate.lib.utils.common import getValueFromCmdLine,cmpVersion FindFileType)
from calculate.lib.utils.common import getValueFromCmdLine
from calculate.lib.utils.portage import isPkgInstalled from calculate.lib.utils.portage import isPkgInstalled
from calculate.lib.variables.user import VariableUrLogin from calculate.lib.variables.user import VariableUrLogin
from calculate.lib.convertenv import convertEnv from calculate.lib.convertenv import convertEnv
@ -37,7 +38,10 @@ import pwd
from calculate.client.client import Client from calculate.client.client import Client
from calculate.lib.cl_lang import setLocalTranslate from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_client3',sys.modules[__name__])
_ = lambda x: x
setLocalTranslate('cl_client3', sys.modules[__name__])
class VariableClRemoteHost(Variable): class VariableClRemoteHost(Variable):
""" """
@ -45,6 +49,7 @@ class VariableClRemoteHost(Variable):
""" """
value = "" value = ""
class VariableClRemoteHostNew(Variable): class VariableClRemoteHostNew(Variable):
""" """
IP or domain name of CDS IP or domain name of CDS
@ -59,22 +64,24 @@ class VariableClRemoteHostNew(Variable):
self.label = _("Domain IP") self.label = _("Domain IP")
self.help = _("domain") self.help = _("domain")
def check(self,value): def check(self, value):
if self.Get('cl_client_mount_set') == 'off': if self.Get('cl_client_mount_set') == 'off':
if self.Get('cl_localhost_set') == 'off': if self.Get('cl_localhost_set') == 'off':
if self.Get('cl_remote_host') == '': if self.Get('cl_remote_host') == '':
if not value: if not value:
raise VariableError(_("Please specify the domain")) raise VariableError(_("Please specify the domain"))
elif not isOpenPort(value,445): elif not isOpenPort(value, 445):
raise VariableError( raise VariableError(
_("The specified address is not available")) _("The specified address is not available"))
class VariableClRemoteHostLive(ReadonlyVariable): class VariableClRemoteHostLive(ReadonlyVariable):
""" """
Remote host from /proc/cmdline param domain Remote host from /proc/cmdline param domain
""" """
def get(self): def get(self):
return getValueFromCmdLine("calculate","domain") or "" return getValueFromCmdLine("calculate", "domain") or ""
class VariableOsRemoteAuth(Variable): class VariableOsRemoteAuth(Variable):
@ -102,14 +109,16 @@ class VariableClRemotePw(Variable):
self.help = _("specify the domain password") self.help = _("specify the domain password")
def get(self): def get(self):
return getValueFromCmdLine("calculate","domain_pw") or "" return getValueFromCmdLine("calculate", "domain_pw") or ""
class VariableClMovedSkipPath(Variable): class VariableClMovedSkipPath(Variable):
""" """
Skip "Moved" path Skip "Moved" path
""" """
type = "list" type = "list"
value = ['Disks','Home','Moved','FTP','Desktop', 'Share'] value = ['Disks', 'Home', 'Moved', 'FTP', 'Desktop', 'Share']
class VariableClSyncSkipPath(Variable): class VariableClSyncSkipPath(Variable):
""" """
@ -117,12 +126,13 @@ class VariableClSyncSkipPath(Variable):
""" """
type = "list" type = "list"
value = [".googleearth", "Home", "Disks", "FTP", value = [".googleearth", "Home", "Disks", "FTP",
'Share', ".local/share/akonadi/db_data", ".VirtualBox", 'Share', ".local/share/akonadi/db_data", ".VirtualBox",
".mozilla/firefox/calculate.default/urlclassifier3.sqlite", ".mozilla/firefox/calculate.default/urlclassifier3.sqlite",
".local/share/mime/mime.cache", ".gvfs", ".local/share/mime/mime.cache", ".gvfs",
".kde4/share/apps/nepomuk/repository/main/data", ".logout", ".kde4/share/apps/nepomuk/repository/main/data", ".logout",
".Xauthority", ".thumbnails", ".mozilla/firefox/*/Cache", ".Xauthority", ".thumbnails", ".mozilla/firefox/*/Cache",
".kde4/socket-*", ".cache/", ".local/share/Trash"] ".kde4/socket-*", ".cache/", ".local/share/Trash"]
class VariableClSyncDelPath(Variable): class VariableClSyncDelPath(Variable):
""" """
@ -132,10 +142,12 @@ class VariableClSyncDelPath(Variable):
value = [".kde4/share/config/phonondevicesrc", value = [".kde4/share/config/phonondevicesrc",
".kde4/cache-*", ".kde4/tmp-*"] ".kde4/cache-*", ".kde4/tmp-*"]
class VariableClProfileAllSet(Variable): class VariableClProfileAllSet(Variable):
type = "bool" type = "bool"
value = "off" value = "off"
class VariableClClientSync(Variable): class VariableClClientSync(Variable):
type = "bool" type = "bool"
value = "on" value = "on"
@ -147,6 +159,7 @@ class VariableClClientSync(Variable):
self.label = _("Synchronize the user profile") self.label = _("Synchronize the user profile")
self.help = _("synchronize user preferences") self.help = _("synchronize user preferences")
class VariableClLocalhostSet(Variable): class VariableClLocalhostSet(Variable):
""" """
Using autopartition Using autopartition
@ -163,24 +176,26 @@ class VariableClLocalhostSet(Variable):
self.help = _("remove the domain connection settings") self.help = _("remove the domain connection settings")
def choice(self): def choice(self):
return [("off",_("Domain workstation")), return [("off", _("Domain workstation")),
("on",_("Local workstation"))] ("on", _("Local workstation"))]
def check(self,value): def check(self, value):
if self.Get('cl_client_mount_set') == 'off': if self.Get('cl_client_mount_set') == 'off':
if self.Get('cl_remote_host') == '' and value == "on": if self.Get('cl_remote_host') == '' and value == "on":
raise VariableError(_("The workstation is not in the domain")) raise VariableError(_("The workstation is not in the domain"))
if self.Get('cl_remote_host') != '' and value == "off": if self.Get('cl_remote_host') != '' and value == "off":
raise VariableError(_("The workstation is already in the domain %s") raise VariableError(
%self.Get('cl_remote_host') + "\n" + _("The workstation is already in the domain %s")
_("Before joining the domain, " % self.Get('cl_remote_host') + "\n" +
"you need to remove it from the previous domain")) _("Before joining the domain, "
"you need to remove it from the previous domain"))
# def get(self):
# if self.Get('cl_remote_host') == '':
# return "on"
# else:
# return "off"
#def get(self):
# if self.Get('cl_remote_host') == '':
# return "on"
# else:
# return "off"
class VariableClClientMountSet(Variable): class VariableClClientMountSet(Variable):
""" """
@ -195,7 +210,8 @@ class VariableClClientMountSet(Variable):
self.label = _("Only mount the domain resource") self.label = _("Only mount the domain resource")
self.help = _("only mount the [remote] domain resource") self.help = _("only mount the [remote] domain resource")
class VariableUrUserPw(Variable,LdapHelper):
class VariableUrUserPw(Variable, LdapHelper):
""" """
Current user password Current user password
""" """
@ -211,9 +227,8 @@ class VariableUrUserPw(Variable,LdapHelper):
def checkUserPwdLDAP(self, server, userDN, password): def checkUserPwdLDAP(self, server, userDN, password):
"""Check unix user password on server""" """Check unix user password on server"""
ldapInit = ldap.initialize("ldap://%s"%server) ldapInit = ldap.initialize("ldap://%s" % server)
errMessage = "" try:
try:
ldapInit.bind_s(userDN, password) ldapInit.bind_s(userDN, password)
except ldap.INVALID_CREDENTIALS: except ldap.INVALID_CREDENTIALS:
raise VariableError(_("Wrong password")) raise VariableError(_("Wrong password"))
@ -222,7 +237,7 @@ class VariableUrUserPw(Variable,LdapHelper):
raise VariableError(errMessage) raise VariableError(errMessage)
return True return True
def check(self,value): def check(self, value):
if not value: if not value:
raise VariableError(_("Empty password")) raise VariableError(_("Empty password"))
# читаем os_remote_auth, так как при смене пароля # читаем os_remote_auth, так как при смене пароля
@ -232,9 +247,10 @@ class VariableUrUserPw(Variable,LdapHelper):
ldapObj = self.getLdapUserObject() ldapObj = self.getLdapUserObject()
if ldapObj: if ldapObj:
usersDN = ldapObj.getUsersDN() usersDN = ldapObj.getUsersDN()
userDN = ldapObj.addDN("uid=%s"%self.Get('ur_login'), userDN = ldapObj.addDN("uid=%s" % self.Get('ur_login'),
usersDN) usersDN)
self.checkUserPwdLDAP(server,userDN,value) self.checkUserPwdLDAP(server, userDN, value)
class VariableUrUserNewPw(Variable): class VariableUrUserNewPw(Variable):
""" """
@ -250,10 +266,11 @@ class VariableUrUserNewPw(Variable):
self.label = _("New password") self.label = _("New password")
self.help = _("new user password") self.help = _("new user password")
def check(self,value): def check(self, value):
if not value: if not value:
raise VariableError(_("Empty password")) raise VariableError(_("Empty password"))
class VariableClClientLogin(VariableUrLogin): class VariableClClientLogin(VariableUrLogin):
""" """
User Login User Login
@ -264,30 +281,31 @@ class VariableClClientLogin(VariableUrLogin):
def choice(self): def choice(self):
loginChoice = VariableUrLogin.choice(self) loginChoice = VariableUrLogin.choice(self)
if self.Get('cl_action') == 'passwd': if self.Get('cl_action') == 'passwd':
return filter(lambda x:x != "root",loginChoice) return filter(lambda x: x != "root", loginChoice)
else: else:
return loginChoice return loginChoice
def check(self,value): def check(self, value):
"""Does user exist""" """Does user exist"""
if not value in self.choice() and self.Get('cl_action') == 'logout': if not value in self.choice() and self.Get('cl_action') == 'logout':
raise VariableError(_("X session users not found")) raise VariableError(_("X session users not found"))
if value == "": if value == "":
raise VariableError(_("Please specify the user")) raise VariableError(_("Please specify the user"))
if value == "root" and self.Get('cl_action') == 'passwd': if value == "root" and self.Get('cl_action') == 'passwd':
raise VariableError(\ raise VariableError(
_("This action can be executed by a non-root user only")) _("This action can be executed by a non-root user only"))
try: try:
pwd.getpwnam(value).pw_gid pwd.getpwnam(value).pw_gid
except: except (TypeError, KeyError):
raise VariableError(_("User %s does not exist")%value) raise VariableError(_("User %s does not exist") % value)
def get(self): def get(self):
if (self.Get('cl_action') == 'passwd' and if (self.Get('cl_action') == 'passwd' and
self.Get('ur_login') != 'root'): self.Get('ur_login') != 'root'):
return self.Get('ur_login') return self.Get('ur_login')
return "" return ""
class VariableClClientRelevanceSet(ReadonlyVariable): class VariableClClientRelevanceSet(ReadonlyVariable):
""" """
Актуальны ли сейчас выполненные шаблоны Актуальны ли сейчас выполненные шаблоны
@ -296,32 +314,36 @@ class VariableClClientRelevanceSet(ReadonlyVariable):
def get(self): def get(self):
# если происходят действия ввода или вывода из домена # если происходят действия ввода или вывода из домена
if (self.Get('cl_action') in ("domain","undomain") and if (self.Get('cl_action') in ("domain", "undomain") and
self.Get('cl_client_mount_set') == 'off'): self.Get('cl_client_mount_set') == 'off'):
return "off" return "off"
# если изменился домен # если изменился домен
if self.Get('cl_remote_host') != self.Get("os_remote_auth"): if self.Get('cl_remote_host') != self.Get("os_remote_auth"):
return "off" return "off"
if (self.Get('cl_remote_host') and if (self.Get('cl_remote_host') and
not isMount(self.Get('cl_client_remote_path'))): not isMount(self.Get('cl_client_remote_path'))):
return "off" return "off"
return "on" return "on"
class VariableClClientRemotePath(Variable): class VariableClClientRemotePath(Variable):
""" """
Путь для монитрования //domain/remote Путь для монитрования //domain/remote
""" """
value = "/var/calculate/remote" value = "/var/calculate/remote"
class VariableClClientProfileName(Variable): class VariableClClientProfileName(Variable):
""" """
Название удаленного профиля (CLD,CLDX,all) Название удаленного профиля (CLD,CLDX,all)
""" """
def get(self): def get(self):
return ("all" if self.Get('cl_profile_all_set') == 'on' return ("all" if self.Get('cl_profile_all_set') == 'on'
else self.Get('os_linux_shortname')) else self.Get('os_linux_shortname'))
class VariableClLdapData(ldapUser,ReadonlyVariable):
class VariableClLdapData(ldapUser, ReadonlyVariable):
""" """
Внутренняя переменная, содержащая объект для доступа к данным LDAP Внутренняя переменная, содержащая объект для доступа к данным LDAP
""" """
@ -341,7 +363,7 @@ class VariableClLdapData(ldapUser,ReadonlyVariable):
if usersDN: if usersDN:
partDN = "ou=Worked,ou=Replication,ou=LDAP" partDN = "ou=Worked,ou=Replication,ou=LDAP"
servicesDN = "ou=Services" servicesDN = "ou=Services"
baseDN = usersDN.rpartition(servicesDN+",")[2] baseDN = usersDN.rpartition(servicesDN + ",")[2]
replDN = self.addDN(partDN, servicesDN, baseDN) replDN = self.addDN(partDN, servicesDN, baseDN)
return replDN return replDN
return False return False
@ -353,8 +375,8 @@ class VariableClLdapData(ldapUser,ReadonlyVariable):
bindDn, bindPw, host = connectData bindDn, bindPw, host = connectData
replDN = self.getReplDN() replDN = self.getReplDN()
# find string for service replication branch # find string for service replication branch
userAndOsName = "%s@%s"%(userName,osLinuxShort) userAndOsName = "%s@%s" % (userName, osLinuxShort)
findAttr = "uid=%s"%userAndOsName findAttr = "uid=%s" % userAndOsName
# connect to LDAP # connect to LDAP
if not self.ldapConnect(bindDn, bindPw, host): if not self.ldapConnect(bindDn, bindPw, host):
return False return False
@ -363,14 +385,13 @@ class VariableClLdapData(ldapUser,ReadonlyVariable):
return resSearch return resSearch
return False return False
def _gethostbyname(self,hostname): def _gethostbyname(self, hostname):
try: try:
return gethostbyname(hostname) return gethostbyname(hostname)
except: except Exception:
pass return None
return None
def getNameRemoteServer(self,userName, osLinuxShort, curHost): def getNameRemoteServer(self, userName, osLinuxShort, curHost):
""" """
Get remote domain hostname or empty if profile is keeped on Get remote domain hostname or empty if profile is keeped on
current server current server
@ -399,7 +420,7 @@ class VariableClLdapData(ldapUser,ReadonlyVariable):
usersDN = self.getUsersDN() usersDN = self.getUsersDN()
partDN = "ou=Replication,ou=LDAP" partDN = "ou=Replication,ou=LDAP"
servicesDN = "ou=Services" servicesDN = "ou=Services"
baseDN = usersDN.rpartition(servicesDN+",")[2] baseDN = usersDN.rpartition(servicesDN + ",")[2]
replDN = self.addDN(partDN, servicesDN, baseDN) replDN = self.addDN(partDN, servicesDN, baseDN)
findAttr = "ou=Worked" findAttr = "ou=Worked"
# connect to LDAP # connect to LDAP
@ -417,11 +438,13 @@ class VariableClReplicationHost(ReadonlyVariable):
""" """
Удаленный сервер при репликации, который содержит актуальный профиль Удаленный сервер при репликации, который содержит актуальный профиль
""" """
def get(self): def get(self):
return self.Get('cl_ldap_data').getNameRemoteServer( return self.Get('cl_ldap_data').getNameRemoteServer(
self.Get('ur_login'),self.Get('cl_client_profile_name'), self.Get('ur_login'), self.Get('cl_client_profile_name'),
self.Get('cl_remote_host')) self.Get('cl_remote_host'))
class VariableClClientUserMountData(ReadonlyTableVariable): class VariableClClientUserMountData(ReadonlyTableVariable):
""" """
Таблица монтирования ресурсов Таблица монтирования ресурсов
@ -431,30 +454,36 @@ class VariableClClientUserMountData(ReadonlyTableVariable):
'cl_client_user_mount_path', 'cl_client_user_mount_path',
'cl_client_user_mount_host'] 'cl_client_user_mount_host']
def get(self): def get(self, hr=HumanReadable.No):
home = path.split(self.Get('ur_home_path'))[0] home = path.split(self.Get('ur_home_path'))[0]
envFile = self.Get('cl_env_server_path') envFile = self.Get('cl_env_server_path')
def generate(): def generate():
yield ("share","share",path.join(self.Get('ur_home_path'),"Share"), yield (
self.Get('cl_remote_host')) "share", "share", path.join(self.Get('ur_home_path'), "Share"),
yield ("unix","unix",path.join(home,".%s"%self.Get('ur_login')), self.Get('cl_remote_host'))
self.Get('cl_remote_host')) yield (
yield ("homes","homes",path.join(self.Get('ur_home_path'),"Home"), "unix", "unix", path.join(home, ".%s" % self.Get('ur_login')),
self.Get('cl_remote_host')) self.Get('cl_remote_host'))
if convertEnv().getVar("ftp","host"): yield (
yield ("ftp","ftp",path.join(self.Get('ur_home_path'),"FTP"), "homes", "homes", path.join(self.Get('ur_home_path'), "Home"),
self.Get('cl_remote_host')) self.Get('cl_remote_host'))
if convertEnv().getVar("ftp", "host"):
yield ("ftp", "ftp", path.join(self.Get('ur_home_path'), "FTP"),
self.Get('cl_remote_host'))
else: else:
yield ("ftp",'','','') yield ("ftp", '', '', '')
if self.Get('cl_replication_host'): if self.Get('cl_replication_host'):
yield ("remote_profile","unix", yield ("remote_profile", "unix",
path.join(home,".%s.remote"%self.Get('ur_login')), path.join(home, ".%s.remote" % self.Get('ur_login')),
self.Get('cl_replication_host')) self.Get('cl_replication_host'))
else: else:
yield ("remote_profile",'unix','','') yield ("remote_profile", 'unix', '', '')
return list(generate()) return list(generate())
class VariableClClientUserMountName(FieldValue,ReadonlyVariable):
class VariableClClientUserMountName(FieldValue, ReadonlyVariable):
""" """
Название удаленного ресурса Название удаленного ресурса
""" """
@ -463,7 +492,7 @@ class VariableClClientUserMountName(FieldValue,ReadonlyVariable):
column = 0 column = 0
class VariableClClientUserMountResource(FieldValue,ReadonlyVariable): class VariableClClientUserMountResource(FieldValue, ReadonlyVariable):
""" """
Название удаленного ресурса Название удаленного ресурса
""" """
@ -471,7 +500,8 @@ class VariableClClientUserMountResource(FieldValue,ReadonlyVariable):
source_variable = "cl_client_user_mount_data" source_variable = "cl_client_user_mount_data"
column = 1 column = 1
class VariableClClientUserMountPath(FieldValue,ReadonlyVariable):
class VariableClClientUserMountPath(FieldValue, ReadonlyVariable):
""" """
Путь подключения удаленного ресурса Путь подключения удаленного ресурса
""" """
@ -479,7 +509,8 @@ class VariableClClientUserMountPath(FieldValue,ReadonlyVariable):
source_variable = "cl_client_user_mount_data" source_variable = "cl_client_user_mount_data"
column = 2 column = 2
class VariableClClientUserMountHost(FieldValue,ReadonlyVariable):
class VariableClClientUserMountHost(FieldValue, ReadonlyVariable):
""" """
Удаленный сервер Удаленный сервер
""" """
@ -487,12 +518,14 @@ class VariableClClientUserMountHost(FieldValue,ReadonlyVariable):
source_variable = "cl_client_user_mount_data" source_variable = "cl_client_user_mount_data"
column = 3 column = 3
class SyncHelper:
class SyncHelper(object):
""" """
Вспомогательный объект для определения статуса синхронизации и времени Вспомогательный объект для определения статуса синхронизации и времени
по конфигурационным файлам по конфигурационным файлам
""" """
def getSyncStatus(self,rpath):
def getSyncStatus(self, rpath):
""" """
Получить status_sync из desktop файла Получить status_sync из desktop файла
""" """
@ -501,9 +534,9 @@ class SyncHelper:
if os.path.exists(fileConfig): if os.path.exists(fileConfig):
objConfig = iniParser(fileConfig) objConfig = iniParser(fileConfig)
data = self.getDataInConfig("main", ["status_sync"], data = self.getDataInConfig("main", ["status_sync"],
objConfig) objConfig)
if data: if data:
return data.get("status_sync","") return data.get("status_sync", "")
return "" return ""
def getDataInConfig(self, section, listVars, objConfig): def getDataInConfig(self, section, listVars, objConfig):
@ -512,19 +545,18 @@ class SyncHelper:
""" """
varsConfig = {} varsConfig = {}
for varName in listVars: for varName in listVars:
varsConfig[varName] = objConfig.getVar(section,varName) varsConfig[varName] = objConfig.getVar(section, varName)
if objConfig.getError(): if objConfig.getError():
return False return False
return varsConfig return varsConfig
def convertDate(self, strdate, dateformat="%Y-%m-%d %H:%M:%S"):
def convertDate(self,strdate,dateformat="%Y-%m-%d %H:%M:%S"):
""" """
Convert date from string format (dateformat) to stuct or None Convert date from string format (dateformat) to stuct or None
""" """
if strdate: if strdate:
try: try:
return time.strptime(strdate,dateformat) return time.strptime(strdate, dateformat)
except ValueError: except ValueError:
pass pass
return "" return ""
@ -541,73 +573,83 @@ class SyncHelper:
timeLogout = data["date_logout"] timeLogout = data["date_logout"]
timeConfig = data["date"] timeConfig = data["date"]
dates = filter(None, dates = filter(None,
[self.convertDate(timeLogout), [self.convertDate(timeLogout),
self.convertDate(timeConfig)]) self.convertDate(timeConfig)])
if dates: if dates:
return dates[0] return dates[0]
return "" return ""
def checkNeedSync(self,homeDir,rpath,curTimeObj,curStatusSync,osLinuxShort): def checkNeedSync(self, homeDir, rpath, curTimeObj, curStatusSync,
osLinuxShort):
""" """
Проверить необходимость синхронизации текущего профиля с удаленным Проверить необходимость синхронизации текущего профиля с удаленным
""" """
# profile directory # profile directory
#fileConfig = os.path.join(homeDir, Client.configFileServer) # fileConfig = os.path.join(homeDir, Client.configFileServer)
pathProfile = os.path.join(rpath, osLinuxShort) pathProfile = os.path.join(rpath, osLinuxShort)
#if readFile(fileConfig).strip(): # if readFile(fileConfig).strip():
# return True # return True
fileSoftConfigThis = os.path.join(pathProfile, fileSoftConfigThis = os.path.join(pathProfile,
Client.configFileSoft) Client.configFileSoft)
fileSoftConfigCur = os.path.join(homeDir, fileSoftConfigCur = os.path.join(homeDir,
Client.configFileSoft) Client.configFileSoft)
xSessionCur = iniParser(fileSoftConfigCur).getVar('main','xsession') xSessionCur = iniParser(fileSoftConfigCur).getVar('main', 'xsession')
xSessionThis = iniParser(fileSoftConfigThis).getVar('main','xsession') xSessionThis = iniParser(fileSoftConfigThis).getVar('main', 'xsession')
# check profile date on current server # check profile date on current server
#fileConfigThis = os.path.join(pathProfile, Client.configFileDesktop) # fileConfigThis = os.path.join(pathProfile, Client.configFileDesktop)
#if iniParser(fileConfigThis).getVar('main','status_sync') == "success": # if iniParser(fileConfigThis).getVar('main','status_sync') == "success":
# self.setVarToConfig("main", {"status_sync":"success_mount"}, # self.setVarToConfig("main", {"status_sync":"success_mount"},
# fileConfigThis) # fileConfigThis)
thisTimeObj = self.getDateObjClientConf(pathProfile) thisTimeObj = self.getDateObjClientConf(pathProfile)
if curStatusSync == "success_logout" and \ if curStatusSync == "success_logout" and \
xSessionCur == xSessionThis and \ xSessionCur == xSessionThis and \
thisTimeObj and curTimeObj and \ thisTimeObj and curTimeObj and \
curTimeObj >= thisTimeObj: curTimeObj >= thisTimeObj:
return False return False
return True return True
class VariableClClientSyncTime(SyncHelper,ReadonlyVariable):
class VariableClClientSyncTime(SyncHelper, ReadonlyVariable):
""" """
Текущее время синхронизации профиля Текущее время синхронизации профиля
""" """
def get(self): def get(self):
return self.getDateObjClientConf(self.Get('ur_home_path')) return self.getDateObjClientConf(self.Get('ur_home_path'))
class VariableClClientPackTime(SyncHelper,ReadonlyVariable):
class VariableClClientPackTime(SyncHelper, ReadonlyVariable):
""" """
Время комады упаковки профиля Время комады упаковки профиля
""" """
def get(self): def get(self):
return str(float(time.time())) return str(float(time.time()))
class VariableClClientSyncStatus(SyncHelper,ReadonlyVariable):
class VariableClClientSyncStatus(SyncHelper, ReadonlyVariable):
""" """
Текущий статус синхронизации профиля Текущий статус синхронизации профиля
""" """
def get(self): def get(self):
return self.getSyncStatus(self.Get('ur_home_path')) return self.getSyncStatus(self.Get('ur_home_path'))
class VariableClClientLocalSyncTime(SyncHelper,ReadonlyVariable):
class VariableClClientLocalSyncTime(SyncHelper, ReadonlyVariable):
""" """
Текущий статус синхронизации профиля Текущий статус синхронизации профиля
""" """
def get(self): def get(self):
return self.getDateObjClientConf( return self.getDateObjClientConf(
path.join( path.join(
self.Select('cl_client_user_mount_path', self.Select('cl_client_user_mount_path',
where='cl_client_user_mount_name',eq='unix', where='cl_client_user_mount_name', eq='unix',
limit=1),self.Get('cl_client_profile_name'))) limit=1), self.Get('cl_client_profile_name')))
class VariableClClientSyncReplicationSet(SyncHelper,ReadonlyVariable):
class VariableClClientSyncReplicationSet(SyncHelper, ReadonlyVariable):
""" """
Нужно ли синхронизировать текущий профиль с удаленным доменом Нужно ли синхронизировать текущий профиль с удаленным доменом
""" """
@ -617,16 +659,18 @@ class VariableClClientSyncReplicationSet(SyncHelper,ReadonlyVariable):
if not self.Get('cl_replication_host'): if not self.Get('cl_replication_host'):
return "off" return "off"
profilePath = self.Select('cl_client_user_mount_path', profilePath = self.Select('cl_client_user_mount_path',
where='cl_client_user_mount_name', where='cl_client_user_mount_name',
eq='remote_profile',limit=1) eq='remote_profile', limit=1)
if self.Get('cl_action') == 'login' and not isMount(profilePath): if self.Get('cl_action') == 'login' and not isMount(profilePath):
raise VariableError(_("Remote profile not mounted")) raise VariableError(_("Remote profile not mounted"))
return "on" if self.checkNeedSync(self.Get('ur_home_path'),profilePath, return "on" if self.checkNeedSync(self.Get('ur_home_path'), profilePath,
self.Get('cl_client_sync_time'), self.Get('cl_client_sync_time'),
self.Get('cl_client_sync_status'), self.Get('cl_client_sync_status'),
self.Get('cl_client_profile_name')) else "off" self.Get(
'cl_client_profile_name')) else "off"
class VariableClClientSyncLocalSet(SyncHelper,ReadonlyVariable): class VariableClClientSyncLocalSet(SyncHelper, ReadonlyVariable):
""" """
Нужно ли синхронизировать текущий профиль с локальным доменом Нужно ли синхронизировать текущий профиль с локальным доменом
""" """
@ -636,44 +680,52 @@ class VariableClClientSyncLocalSet(SyncHelper,ReadonlyVariable):
if not self.Get('cl_remote_host'): if not self.Get('cl_remote_host'):
return "off" return "off"
profilePath = self.Select('cl_client_user_mount_path', profilePath = self.Select('cl_client_user_mount_path',
where='cl_client_user_mount_name', where='cl_client_user_mount_name',
eq='unix',limit=1) eq='unix', limit=1)
if self.Get('cl_action') == 'login' and not isMount(profilePath): if self.Get('cl_action') == 'login' and not isMount(profilePath):
raise VariableError(_("Remote profile not mounted")) raise VariableError(_("Remote profile not mounted"))
return "on" if self.checkNeedSync(self.Get('ur_home_path'),profilePath, return "on" if self.checkNeedSync(self.Get('ur_home_path'), profilePath,
self.Get('cl_client_sync_time'), self.Get('cl_client_sync_time'),
self.Get('cl_client_sync_status'), self.Get('cl_client_sync_status'),
self.Get('cl_client_profile_name')) else "off" self.Get(
'cl_client_profile_name')) else "off"
class VariableClClientSymlinks(ReadonlyVariable): class VariableClClientSymlinks(ReadonlyVariable):
""" """
Список симлинков в пользовательском профиле Список симлинков в пользовательском профиле
""" """
def get(self): def get(self):
skipFiles = (self.Get('cl_sync_del_path') + skipFiles = (self.Get('cl_sync_del_path') +
self.Get('cl_sync_skip_path')) self.Get('cl_sync_skip_path'))
reSkip = re.compile("|".join(map(lambda x:x.replace("*",".*"), reSkip = re.compile("|".join(map(lambda x: x.replace("*", ".*"),
skipFiles))).search skipFiles))).search
return filter(lambda x:not reSkip(x), return filter(lambda x: not reSkip(x),
find(self.Get('ur_home_path'),onefilesystem=True, find(self.Get('ur_home_path'), onefilesystem=True,
filetype=FindFileType.SymbolicLink)) filetype=FindFileType.SymbolicLink))
class VariableClClientNscdCache(Variable): class VariableClClientNscdCache(Variable):
""" """
Частота обновления кэша nscd при работе в домене в часах Частота обновления кэша nscd при работе в домене в часах
""" """
class VariableClCifsVer(ReadonlyVariable): class VariableClCifsVer(ReadonlyVariable):
""" """
Версия модуля CIFS Версия модуля CIFS
""" """
def get(self): def get(self):
return readFile("/sys/module/cifs/version") return readFile("/sys/module/cifs/version")
class VariableClRsyncVer(ReadonlyVariable): class VariableClRsyncVer(ReadonlyVariable):
""" """
Версия rsync Версия rsync
""" """
def get(self): def get(self):
data = isPkgInstalled('net-misc/rsync') data = isPkgInstalled('net-misc/rsync')
if data: if data:

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright 2012-2013 Calculate Ltd. http://www.calculate-linux.org # Copyright 2012-2015 Calculate Ltd. http://www.calculate-linux.org
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -28,6 +28,7 @@ import calculate.client.client as client
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
_ = lambda x: x
setLocalTranslate('cl_client3', sys.modules[__name__]) setLocalTranslate('cl_client3', sys.modules[__name__])
__ = getLazyLocalTranslate(_) __ = getLazyLocalTranslate(_)
@ -63,15 +64,16 @@ class Wsdl(WsdlBase):
ClientError, DesktopError), ClientError, DesktopError),
# значения по умолчанию для переменных этого метода # значения по умолчанию для переменных этого метода
'setvars': {'cl_action!': 'domain', 'setvars': {'cl_action!': 'domain',
'cl_protect_use_set!':'off' 'cl_protect_use_set!': 'off'
}, },
'guivars': {'cl_localhost_set!': lambda dv: ( 'guivars': {'cl_localhost_set!': lambda dv: (
"on" if dv.Get('cl_remote_host') == '' else 'off')}, "on" if dv.Get('cl_remote_host') == '' else 'off')},
# описание груп (список лямбда функций) # описание груп (список лямбда функций)
'groups': [ 'groups': [
lambda group: group(_("Domain"), lambda group: group(_("Domain"),
normal=( normal=(
'cl_localhost_set', 'cl_remote_host_new', 'cl_localhost_set',
'cl_remote_host_new',
'cl_remote_pw'), 'cl_remote_pw'),
expert=('cl_client_mount_set', expert=('cl_client_mount_set',
'cl_templates_locate', 'cl_templates_locate',

Loading…
Cancel
Save