|
|
|
|
#-*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
|
|
#Copyright 2008 Calculate Pack, http://www.calculate-linux.ru
|
|
|
|
|
#
|
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
|
#
|
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
#
|
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
|
# limitations under the License.
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
import cl_base
|
|
|
|
|
import cl_profile
|
|
|
|
|
import cl_utils2
|
|
|
|
|
import cl_utils
|
|
|
|
|
|
|
|
|
|
import ldap
|
|
|
|
|
import types
|
|
|
|
|
import getpass
|
|
|
|
|
import _cl_keys
|
|
|
|
|
|
|
|
|
|
import time
|
|
|
|
|
import stat
|
|
|
|
|
import popen2
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
|
Version = "calculate-client 2.0.15"
|
|
|
|
|
|
|
|
|
|
tr = cl_base.lang()
|
|
|
|
|
tr.setLanguage(sys.modules[__name__])
|
|
|
|
|
|
|
|
|
|
pcs = cl_utils.prettyColumnStr
|
|
|
|
|
|
|
|
|
|
class printNoColor:
|
|
|
|
|
def colorPrint(self,attr,fg,bg,string):
|
|
|
|
|
sys.stdout.write(string)
|
|
|
|
|
|
|
|
|
|
class ProgressBar:
|
|
|
|
|
suffixSet = 'org.freedesktop.DBus.Properties.Set \
|
|
|
|
|
org.kde.kdialog.ProgressDialog'
|
|
|
|
|
execenv = 'HOME="/root" '
|
|
|
|
|
max = 100
|
|
|
|
|
kdialog = None
|
|
|
|
|
def __init__(self,title,kdialog=None):
|
|
|
|
|
self.title = title
|
|
|
|
|
if kdialog == None:
|
|
|
|
|
self.openDialog(self.title)
|
|
|
|
|
|
|
|
|
|
def openDialog(self,title):
|
|
|
|
|
pipe = popen2.Popen4(self.execenv+
|
|
|
|
|
'/usr/bin/kdialog --progressbar "%s" %d' % (\
|
|
|
|
|
self.title,self.max))
|
|
|
|
|
if pipe.poll() != 0:
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
if pipe.poll() == 0:
|
|
|
|
|
self.kdialog = pipe.fromchild.readline().strip()
|
|
|
|
|
while not "org.kde.kdialog" in self.kdialog:
|
|
|
|
|
s = fout.fromchild.readline()
|
|
|
|
|
if s == "":
|
|
|
|
|
self.kdialog = None
|
|
|
|
|
self.kdialog = s.strip()
|
|
|
|
|
|
|
|
|
|
def setValue(self,value):
|
|
|
|
|
'''Установить текущее значения для прогресса'''
|
|
|
|
|
if self.kdialog and value <= self.max:
|
|
|
|
|
os.system(self.execenv+
|
|
|
|
|
'/usr/bin/qdbus %s %s value %d >/dev/null' % (\
|
|
|
|
|
self.kdialog,self.suffixSet, value));
|
|
|
|
|
|
|
|
|
|
def setMaximum(self,max):
|
|
|
|
|
'''Установить максимальное значения для прогресса'''
|
|
|
|
|
self.max = max
|
|
|
|
|
if self.kdialog:
|
|
|
|
|
os.system(self.execenv+
|
|
|
|
|
'/usr/bin/qdbus %s %s maximum %d >/dev/null' % (\
|
|
|
|
|
self.kdialog,self.suffixSet, self.max));
|
|
|
|
|
|
|
|
|
|
def setTitle(self,title):
|
|
|
|
|
'''Установить описания прогресса'''
|
|
|
|
|
self.title = title
|
|
|
|
|
if self.kdialog:
|
|
|
|
|
os.system(self.execenv+
|
|
|
|
|
'/usr/bin/qdbus %s setLabelText "%s" >/dev/null' % \
|
|
|
|
|
(self.kdialog,self.title))
|
|
|
|
|
|
|
|
|
|
def close(self):
|
|
|
|
|
'''Закрыть прогресс'''
|
|
|
|
|
if self.kdialog:
|
|
|
|
|
self.setValue(self.max)
|
|
|
|
|
os.system(self.execenv+
|
|
|
|
|
'/usr/bin/qdbus %s close >/dev/null' % self.kdialog)
|
|
|
|
|
|
|
|
|
|
class ProgressProfile(cl_profile.profile):
|
|
|
|
|
def __init__(self, vars):
|
|
|
|
|
cl_profile.profile.__init__(self,vars)
|
|
|
|
|
self.progress = ProgressBar(_("Merging profiles ..."))
|
|
|
|
|
|
|
|
|
|
def numberAllProfiles(self, number):
|
|
|
|
|
self.progress.setMaximum(number)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def numberProcessProfiles(self,number):
|
|
|
|
|
self.progress.setValue(number)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
class RsyncProgressBar(ProgressBar):
|
|
|
|
|
'''Объект запуска rsync для получения количества созданных файлов и
|
|
|
|
|
при необходимости вывода progressbar
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
# получение номера передаваемого файла из инф потока rsync
|
|
|
|
|
senderre = re.compile("\[sender\] i=(\d+) ", re.S)
|
|
|
|
|
# получение номера получаемого файла из потока rsync
|
|
|
|
|
receiverre = re.compile("recv_generator\(.+,([0-9]+)\)", re.S)
|
|
|
|
|
pipe = None
|
|
|
|
|
maximum = 1
|
|
|
|
|
copyStarting = False
|
|
|
|
|
|
|
|
|
|
def __init__(self, title, secondtitle, rsyncstr, maximum=1):
|
|
|
|
|
self.title = title
|
|
|
|
|
self.secondtitle = secondtitle
|
|
|
|
|
self.maximum = maximum
|
|
|
|
|
self.rsyncstr = rsyncstr
|
|
|
|
|
|
|
|
|
|
def getFilesNum(self):
|
|
|
|
|
'''Получить количество файлов созданных генератором'''
|
|
|
|
|
if self.pipe:
|
|
|
|
|
return self.value
|
|
|
|
|
|
|
|
|
|
def getExitCode(self):
|
|
|
|
|
'''Получить код выхода rsync'''
|
|
|
|
|
if self.pipe:
|
|
|
|
|
return os.WEXITSTATUS(self.pipe.wait())
|
|
|
|
|
|
|
|
|
|
def runsilent(self):
|
|
|
|
|
'''Запустить rsync без progressbar'''
|
|
|
|
|
self.pipe = popen2.Popen4(self.rsyncstr)
|
|
|
|
|
while True:
|
|
|
|
|
s = self.pipe.fromchild.readline()
|
|
|
|
|
if len(s) == 0:
|
|
|
|
|
break
|
|
|
|
|
q = self.receiverre.search(s)
|
|
|
|
|
if q:
|
|
|
|
|
self.value = int(q.groups()[0])
|
|
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
|
'''Запустить rsync с progressbar'''
|
|
|
|
|
self.openDialog(self.title)
|
|
|
|
|
self.pipe = popen2.Popen4(self.rsyncstr)
|
|
|
|
|
oldpercent = 0
|
|
|
|
|
while True:
|
|
|
|
|
s = self.pipe.fromchild.readline()
|
|
|
|
|
if len(s) == 0:
|
|
|
|
|
break
|
|
|
|
|
q = self.senderre.search(s)
|
|
|
|
|
if q:
|
|
|
|
|
maximum = int(q.groups()[0])
|
|
|
|
|
if self.maximum < maximum:
|
|
|
|
|
self.maximum = maximum
|
|
|
|
|
continue
|
|
|
|
|
q = self.receiverre.search(s)
|
|
|
|
|
if q:
|
|
|
|
|
self.value = int(q.groups()[0])
|
|
|
|
|
newpercent = self.value * 100 / self.maximum
|
|
|
|
|
if oldpercent < newpercent:
|
|
|
|
|
if not self.copyStarting:
|
|
|
|
|
self.copyStarting = True
|
|
|
|
|
self.setTitle(self.secondtitle)
|
|
|
|
|
oldpercent = newpercent
|
|
|
|
|
self.setValue(oldpercent)
|
|
|
|
|
|
|
|
|
|
# Импортированные классы в cl_ldap
|
|
|
|
|
# Запись ошибок
|
|
|
|
|
imp_cl_err = cl_profile._error
|
|
|
|
|
# Работа с XML
|
|
|
|
|
imp_cl_xml = cl_profile.xmlShare
|
|
|
|
|
# Обработка параметров командной строки
|
|
|
|
|
imp_cl_help = cl_utils2.cl_help
|
|
|
|
|
# Форматированный вывод
|
|
|
|
|
imp_cl_smcon = cl_utils2.cl_smartcon
|
|
|
|
|
|
|
|
|
|
class cl_client(imp_cl_err, imp_cl_xml, imp_cl_help, imp_cl_smcon):
|
|
|
|
|
"""Основной класс для работы клиентских приложений"""
|
|
|
|
|
def __init__(self, cmdName):
|
|
|
|
|
# объект для форматированного вывода
|
|
|
|
|
imp_cl_help.__init__(self, cmdName)
|
|
|
|
|
|
|
|
|
|
servName = ""
|
|
|
|
|
if "user" in cmdName:
|
|
|
|
|
servName = _("user")
|
|
|
|
|
|
|
|
|
|
self.chapter = [\
|
|
|
|
|
# расположение разделов на странице
|
|
|
|
|
# имя раздела, видимый или невидимый, кол. "\n" после
|
|
|
|
|
# названия раздела, кол. "\n" после раздела
|
|
|
|
|
# тип раздела
|
|
|
|
|
("Copyright",False,0,2,""),
|
|
|
|
|
(_("Usage"),True,0,1,""),
|
|
|
|
|
("Function",False,0,2,""),
|
|
|
|
|
(_("Examples"),True,1,1,""),
|
|
|
|
|
(_("Common options"),True,1,0,"options"),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# имена используемых программ и их номера для доступа к переменным
|
|
|
|
|
# self.data
|
|
|
|
|
self.progName = { 'cl-client':0,
|
|
|
|
|
'cl-createhome':1,
|
|
|
|
|
'cl-sync':2
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Cвязь длинных опций помощи и выводимых разделов помощи с опциями
|
|
|
|
|
self.relOptions = {"h":[_("Common options")],}
|
|
|
|
|
|
|
|
|
|
# список разделов, которые на наличие в ней информации
|
|
|
|
|
# используется для автоматического отображения/скрытия
|
|
|
|
|
# опций help-имя
|
|
|
|
|
# Пример: self.relOption =
|
|
|
|
|
# { "help-all":[_("Common options"], _("Unix service options"),
|
|
|
|
|
# _("Samba service options"), _("LDAP service options")}]
|
|
|
|
|
# self.relChapterPass = (_("Common options"),)
|
|
|
|
|
# это означается что опция будет активна, если только в разделах
|
|
|
|
|
# кроме Common options есть хоть одна доступная опция.
|
|
|
|
|
self.relChapterPass = (_("Common options"),)
|
|
|
|
|
|
|
|
|
|
self.data = [\
|
|
|
|
|
{
|
|
|
|
|
#Copyright
|
|
|
|
|
#'progAccess':(3,),
|
|
|
|
|
'helpChapter':"Copyright",
|
|
|
|
|
'help':Version
|
|
|
|
|
},
|
|
|
|
|
#Usage
|
|
|
|
|
{
|
|
|
|
|
'progAccess':(0,),
|
|
|
|
|
'helpChapter':_("Usage"),
|
|
|
|
|
'help': cmdName + " [" + _("options") + "] " + _("domain")
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
'progAccess':(1,),
|
|
|
|
|
'helpChapter':_("Usage"),
|
|
|
|
|
'help': cmdName + " " + _("user")
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
'progAccess':(2,),
|
|
|
|
|
'helpChapter':_("Usage"),
|
|
|
|
|
'help': cmdName + " [" + _("options") + "] " + _("user")
|
|
|
|
|
},
|
|
|
|
|
# Function
|
|
|
|
|
{
|
|
|
|
|
'progAccess':(0,),
|
|
|
|
|
'helpChapter':"Function",
|
|
|
|
|
'help':_("Changes settings for connecting to domain \
|
|
|
|
|
(calculate-server)")
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
'progAccess':(1,),
|
|
|
|
|
'helpChapter':"Function",
|
|
|
|
|
'help':_("Create home directory for the new user account")
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
'progAccess':(2,),
|
|
|
|
|
'helpChapter':"Function",
|
|
|
|
|
'help':_("Mounting directories and synchronize the user preferences")
|
|
|
|
|
},
|
|
|
|
|
# Examples
|
|
|
|
|
{
|
|
|
|
|
'progAccess':(0,),
|
|
|
|
|
'helpChapter':_("Examples"),
|
|
|
|
|
'help':pcs( " cl-client 192.168.0.1", self.column_width,
|
|
|
|
|
"# " + _("Adds settings for connecting to domain \
|
|
|
|
|
(ip 192.168.0.1)"),
|
|
|
|
|
self.consolewidth-self.column_width )
|
|
|
|
|
},
|
|
|
|
|
# Options
|
|
|
|
|
{'shortOption':"h",
|
|
|
|
|
'longOption':"help",
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("display this help and exit")
|
|
|
|
|
},
|
|
|
|
|
{'shortOption':"h",
|
|
|
|
|
'longOption':"help",
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("display this help and exit")
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(0,),
|
|
|
|
|
'shortOption':"r",
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("Removes the settings for connecting to a domain")
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(2,),
|
|
|
|
|
'longOption':'progress',
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("Show progress bar for kde startup (works only with options \
|
|
|
|
|
--login)")
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(1,),
|
|
|
|
|
'longOption':'progress',
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("Show progress bar for kde startup")
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(0,1,2),
|
|
|
|
|
'longOption':"vars",
|
|
|
|
|
'optVal':_("TYPE_VAR"),
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("print variables (TYPE_VAR - all:full var)")
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(0,1,2),
|
|
|
|
|
'longOption':"color",
|
|
|
|
|
'optVal':_("WHEN"),
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("control whether color is used to distinguish file types. \
|
|
|
|
|
WHEN may be 'never', 'always', or 'auto'")
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(1,),
|
|
|
|
|
'shortOption':"f",
|
|
|
|
|
'longOption':"force",
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("always join the user profiles and preferences")
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(0,),
|
|
|
|
|
'longOption':"mount",
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("mount [remote] resource for Samba (calculate-server)")
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(2,),
|
|
|
|
|
'longOption':"login",
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("mount user resource")+ " " +\
|
|
|
|
|
_("and synchronize the user preferences")
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(2,),
|
|
|
|
|
'longOption':"logout",
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("synchronize the user preferences") + " " +\
|
|
|
|
|
_("and umount user resource")
|
|
|
|
|
},
|
|
|
|
|
{'progAccess':(2,),
|
|
|
|
|
'longOption':"nosync",
|
|
|
|
|
'helpChapter':_("Common options"),
|
|
|
|
|
'help':_("not synchronize the user preferences, is used in \
|
|
|
|
|
conjunction with the 'login' or 'logout'")
|
|
|
|
|
},
|
|
|
|
|
#{'progAccess':(0,),
|
|
|
|
|
#'shortOption':"p",
|
|
|
|
|
#'longOption':"prvar",
|
|
|
|
|
#'optVal':_("TYPES_VAR"),
|
|
|
|
|
#'helpChapter':_("Common options"),
|
|
|
|
|
#'help':_("print variable (filter type - comma delimited)")
|
|
|
|
|
#},
|
|
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
self._cl_help__setParamHelp()
|
|
|
|
|
|
|
|
|
|
# Удаляем ненужный аттрибут класса cl_profile.xmlShare
|
|
|
|
|
self._createElement = False
|
|
|
|
|
delattr(self, "_createElement")
|
|
|
|
|
|
|
|
|
|
# Переменная объект Vars
|
|
|
|
|
self.clVars = False
|
|
|
|
|
# Переменная объект ldapFunction
|
|
|
|
|
self.ldapObj = False
|
|
|
|
|
# Переменная соединение с LDAP сервером
|
|
|
|
|
self.conLdap = False
|
|
|
|
|
# Базовый DN LDAP сервера
|
|
|
|
|
self.baseDN = False
|
|
|
|
|
# DN сервисов относительно базового
|
|
|
|
|
self.ServicesDN = "ou=Services"
|
|
|
|
|
|
|
|
|
|
self.relGrDN = 'ou=Groups'
|
|
|
|
|
self.relUsDN = 'ou=Users'
|
|
|
|
|
self.relServDN = 'ou=Unix'
|
|
|
|
|
self.relDN = self.addDN(self.relServDN,self.ServicesDN)
|
|
|
|
|
# DN пользователей, относительно базового DN
|
|
|
|
|
self.relUsersDN = self.addDN(self.relUsDN, self.relDN)
|
|
|
|
|
# DN групп, относительно базового DN
|
|
|
|
|
self.relGroupsDN = self.addDN(self.relGrDN, self.relDN)
|
|
|
|
|
# Объект хранения переменных
|
|
|
|
|
self.clVars = False
|
|
|
|
|
# Файл в ресурсе share для обработки подключения клиента
|
|
|
|
|
self.replRunFileShare = ".reprun"
|
|
|
|
|
# файл с дополнительной информацией о профиле
|
|
|
|
|
# на данный момент только количество файлов для rsync
|
|
|
|
|
# используемое для прогрессбара
|
|
|
|
|
self.configFile = ".calculate.ini"
|
|
|
|
|
# При включениии репликации
|
|
|
|
|
# Временные задержки для монтирования в секундах
|
|
|
|
|
self.sleeps = [0.5, 2, 5]
|
|
|
|
|
# DN хранения последнего посещенного пользователя
|
|
|
|
|
self.replHostsDN = self.addDN("ou=Worked","ou=Replication",
|
|
|
|
|
"ou=LDAP", self.ServicesDN)
|
|
|
|
|
self.replLogoutFile = ".logout"
|
|
|
|
|
# Если атрибут установлен то значит (ошибка и отмонтируются
|
|
|
|
|
# пользовательские ресурсы)
|
|
|
|
|
self.errorAndUnmountUserRes = False
|
|
|
|
|
# Имя пользователя
|
|
|
|
|
self.userName = ""
|
|
|
|
|
cl_base.exit = lambda x: self.exit(x)
|
|
|
|
|
# Строка нужна для корректной работы __del__
|
|
|
|
|
self._exit = cl_base.exit
|
|
|
|
|
|
|
|
|
|
def exit(self, exitCode):
|
|
|
|
|
"""Метод выхода при ошибке"""
|
|
|
|
|
self.errorExit(self)
|
|
|
|
|
sys.exit(exitCode)
|
|
|
|
|
|
|
|
|
|
def errorExit(self):
|
|
|
|
|
"""Отмонтирование пользовательских ресурсов при ошибке"""
|
|
|
|
|
if self.errorAndUnmountUserRes and self.userName:
|
|
|
|
|
self.umountUserResNoSync(self.userName, False, False, False, True)
|
|
|
|
|
|
|
|
|
|
def __del__(self):
|
|
|
|
|
"""Выполняется при удалении объекта"""
|
|
|
|
|
self.errorExit()
|
|
|
|
|
|
|
|
|
|
def isRoot(self):
|
|
|
|
|
"""Определяет является ли пользователь root"""
|
|
|
|
|
if os.getuid() == 0 and os.getgid() == 0:
|
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
self.printERROR("The user is not root")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def createClVars(self, clVars=False):
|
|
|
|
|
"""Создает объект Vars"""
|
|
|
|
|
if not clVars:
|
|
|
|
|
clVars = cl_base.DataVars()
|
|
|
|
|
clVars.flClient()
|
|
|
|
|
clVars.flIniFile()
|
|
|
|
|
# Устанавливаем у объекта объект Vars
|
|
|
|
|
self.clVars = clVars
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def addDN(self, *arg):
|
|
|
|
|
"""Складывает текстовые элементы DN"""
|
|
|
|
|
DNs = []
|
|
|
|
|
for dn in arg:
|
|
|
|
|
if dn:
|
|
|
|
|
DNs.append(dn)
|
|
|
|
|
return ','.join(DNs)
|
|
|
|
|
|
|
|
|
|
def searchLdapDN(self, name, relDN, attr, retAttr=None):
|
|
|
|
|
"""Находит DN в LDAP"""
|
|
|
|
|
baseDN = self.clVars.Get("ld_base_dn")
|
|
|
|
|
DN = self.addDN(relDN,baseDN)
|
|
|
|
|
#searchScope = ldap.SCOPE_SUBTREE
|
|
|
|
|
searchScope = ldap.SCOPE_ONELEVEL
|
|
|
|
|
searchFilter = "%s=%s" %(attr,name)
|
|
|
|
|
retrieveAttributes = retAttr
|
|
|
|
|
resSearch = self.ldapObj.ldapSearch(DN, searchScope,
|
|
|
|
|
searchFilter, retrieveAttributes)
|
|
|
|
|
return resSearch
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def searchPrevHost(self, userName):
|
|
|
|
|
"""Находит сервер к которому был подключен пользователь"""
|
|
|
|
|
resSearch = self.searchLdapDN(userName, self.replHostsDN, "uid")
|
|
|
|
|
return resSearch
|
|
|
|
|
|
|
|
|
|
def searchUnixUser(self, userName):
|
|
|
|
|
"""Находит пользователя сервиса Unix"""
|
|
|
|
|
resSearch = self.searchLdapDN(userName, self.relUsersDN, "uid")
|
|
|
|
|
return resSearch
|
|
|
|
|
|
|
|
|
|
def searchUnixGid(self, groupId):
|
|
|
|
|
"""Находит группу сервиса Unix по ёе id"""
|
|
|
|
|
resSearch = self.searchLdapDN(str(groupId), self.relGroupsDN,
|
|
|
|
|
"gidNumber")
|
|
|
|
|
return resSearch
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getLdapObjBind(self, host, printError=True):
|
|
|
|
|
"""Получаем объект ldapFunction
|
|
|
|
|
|
|
|
|
|
Соединяемся пользователем bind
|
|
|
|
|
В выходном объекте есть соединение с LDAP сервером: self.conLdap
|
|
|
|
|
"""
|
|
|
|
|
self.createClVars(self.clVars)
|
|
|
|
|
bindDn = self.clVars.Get("ld_bind_dn")
|
|
|
|
|
bindPw = self.clVars.Get("ld_bind_pw")
|
|
|
|
|
if not (bindDn or bindPw):
|
|
|
|
|
if printError:
|
|
|
|
|
self.printERROR(_("Not found LDAP bind DN or password") +\
|
|
|
|
|
" ...")
|
|
|
|
|
return False
|
|
|
|
|
ldapObj = cl_utils2.ldapFun(bindDn, bindPw, host)
|
|
|
|
|
if ldapObj.getError():
|
|
|
|
|
if printError:
|
|
|
|
|
self.printERROR (_("LDAP connect error") + ": " +\
|
|
|
|
|
ldapObj.getError().strip())
|
|
|
|
|
return False
|
|
|
|
|
# Устанавливаем у объекта соединение и объект LDAP функций
|
|
|
|
|
self.ldapObj = ldapObj
|
|
|
|
|
self.conLdap = ldapObj.conLdap
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def searchLineInFile(self, name, fileName, numEl=0):
|
|
|
|
|
"""Ищет строку в которой есть название разделенное ':'
|
|
|
|
|
|
|
|
|
|
в файле похожем на /etc/passwd"""
|
|
|
|
|
if os.path.exists(fileName):
|
|
|
|
|
FD = open(fileName)
|
|
|
|
|
lines = FD.readlines()
|
|
|
|
|
FD.close()
|
|
|
|
|
lineFound = ""
|
|
|
|
|
for line in lines:
|
|
|
|
|
if name == line.split(":")[numEl]:
|
|
|
|
|
lineFound = line
|
|
|
|
|
break
|
|
|
|
|
if lineFound:
|
|
|
|
|
return lineFound
|
|
|
|
|
else:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def searchPasswdUser(self, userName):
|
|
|
|
|
"""Ищет пользователей в /etc/passwd"""
|
|
|
|
|
filePasswd = "/etc/passwd"
|
|
|
|
|
return self.searchLineInFile(userName, filePasswd)
|
|
|
|
|
|
|
|
|
|
def searchGroupGid(self, groupId):
|
|
|
|
|
"""Ищет gid в /etc/group"""
|
|
|
|
|
gid = str(groupId)
|
|
|
|
|
fileGroup = "/etc/group"
|
|
|
|
|
return self.searchLineInFile(gid, fileGroup, 2)
|
|
|
|
|
|
|
|
|
|
def getUserLdapInfo(self, userName, printError=True):
|
|
|
|
|
"""Выдаем uid и gid пользователя"""
|
|
|
|
|
searchUser = self.searchUnixUser(userName)
|
|
|
|
|
if not searchUser:
|
|
|
|
|
if printError:
|
|
|
|
|
self.printERROR(_("User %s not found in Unix service")\
|
|
|
|
|
%str(userName))
|
|
|
|
|
return False
|
|
|
|
|
uid = False
|
|
|
|
|
gid = False
|
|
|
|
|
fullName = ""
|
|
|
|
|
mail = ""
|
|
|
|
|
if searchUser[0][0][1].has_key('uidNumber'):
|
|
|
|
|
uid = searchUser[0][0][1]['uidNumber'][0]
|
|
|
|
|
if searchUser[0][0][1].has_key('gidNumber'):
|
|
|
|
|
gid = searchUser[0][0][1]['gidNumber'][0]
|
|
|
|
|
searchGroup = self.searchUnixGid(gid)
|
|
|
|
|
if searchGroup and searchGroup[0][0][1].has_key('cn'):
|
|
|
|
|
group = searchGroup[0][0][1]['cn'][0]
|
|
|
|
|
if searchUser[0][0][1].has_key('cn'):
|
|
|
|
|
fullName = searchUser[0][0][1]['cn'][0]
|
|
|
|
|
if searchUser[0][0][1].has_key('mail'):
|
|
|
|
|
mail = searchUser[0][0][1]['mail'][0]
|
|
|
|
|
if searchUser[0][0][1].has_key('homeDirectory'):
|
|
|
|
|
home = searchUser[0][0][1]['homeDirectory'][0]
|
|
|
|
|
if uid and gid:
|
|
|
|
|
return (uid, gid, fullName, mail, home, group)
|
|
|
|
|
else:
|
|
|
|
|
return ()
|
|
|
|
|
|
|
|
|
|
def createUserDir(self, uid, gid, userDir, mode=0700):
|
|
|
|
|
"""Создание пользовательской директории"""
|
|
|
|
|
if not os.path.exists(userDir):
|
|
|
|
|
os.makedirs(userDir)
|
|
|
|
|
if mode:
|
|
|
|
|
os.chmod(userDir,mode)
|
|
|
|
|
os.chown(userDir,uid,gid)
|
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
self.printERROR(_("Path %s exists") %userDir)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def applyProfilesFromUser(self,progress=False):
|
|
|
|
|
"""Применяем профили для пользователя"""
|
|
|
|
|
# Cоздаем объект профиль
|
|
|
|
|
if progress:
|
|
|
|
|
clProf = ProgressProfile(self.clVars)
|
|
|
|
|
else:
|
|
|
|
|
clProf = cl_profile.profile(self.clVars)
|
|
|
|
|
# Объединяем профили
|
|
|
|
|
dirsFiles = clProf.applyProfiles()
|
|
|
|
|
if progress:
|
|
|
|
|
clProf.progress.close()
|
|
|
|
|
if clProf.getError():
|
|
|
|
|
self.printERROR(clProf.getError())
|
|
|
|
|
return False
|
|
|
|
|
else:
|
|
|
|
|
return dirsFiles
|
|
|
|
|
|
|
|
|
|
def getUserPassword(self, pwDialog=False):
|
|
|
|
|
"""Получить пароль у пользователя
|
|
|
|
|
|
|
|
|
|
pwDialog - приглашение ввода пароля
|
|
|
|
|
"""
|
|
|
|
|
if not pwDialog:
|
|
|
|
|
pwDialog = _("Password")
|
|
|
|
|
userPwd = getpass.getpass(pwDialog+":")
|
|
|
|
|
return userPwd
|
|
|
|
|
|
|
|
|
|
def chownR(self, directory, uid, gid, dirsAndFiles=False):
|
|
|
|
|
"""изменяет владельца и группу
|
|
|
|
|
|
|
|
|
|
для всех файлов и директорий внутри directory
|
|
|
|
|
"""
|
|
|
|
|
if dirsAndFiles:
|
|
|
|
|
dirs, files = dirsAndFiles
|
|
|
|
|
# меняем владельца домашней директории
|
|
|
|
|
os.chown(directory, uid,gid)
|
|
|
|
|
# Меняем владельца директорий
|
|
|
|
|
for dirCh in dirs:
|
|
|
|
|
if os.path.exists(dirCh):
|
|
|
|
|
os.chown(dirCh, uid,gid)
|
|
|
|
|
# Меняем владельца файлов
|
|
|
|
|
for fileCh in files:
|
|
|
|
|
if os.path.exists(fileCh):
|
|
|
|
|
if os.path.islink(fileCh):
|
|
|
|
|
os.lchown(fileCh, uid, gid)
|
|
|
|
|
else:
|
|
|
|
|
os.chown(fileCh, uid,gid)
|
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
fileObj = cl_profile._file()
|
|
|
|
|
scanObjs = fileObj.scanDirs([directory])
|
|
|
|
|
# меняем владельца домашней директории
|
|
|
|
|
os.chown(directory, uid,gid)
|
|
|
|
|
# Меняем владельца директорий
|
|
|
|
|
for dirCh in scanObjs[0].dirs:
|
|
|
|
|
os.chown(dirCh, uid,gid)
|
|
|
|
|
# Меняем владельца файлов
|
|
|
|
|
for fileCh in scanObjs[0].files:
|
|
|
|
|
os.chown(fileCh, uid,gid)
|
|
|
|
|
# Меняем владельца ссылок
|
|
|
|
|
for linkCh in scanObjs[0].links:
|
|
|
|
|
os.lchown(linkCh[1], uid, gid)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def execProg(self, cmdStrProg, inStr=False, retFull=True):
|
|
|
|
|
"""Выполняет внешнюю программу
|
|
|
|
|
|
|
|
|
|
Параметры:
|
|
|
|
|
cmdStrProg внешняя программа
|
|
|
|
|
inStr данные передаваемые программе на страндартный вход.
|
|
|
|
|
Возвращаемые параметры:
|
|
|
|
|
строка которую выведет внешняя программа
|
|
|
|
|
"""
|
|
|
|
|
return cl_utils.runOsCommand(cmdStrProg, inStr, retFull)
|
|
|
|
|
|
|
|
|
|
#def getUidAndGidUser(self, userName):
|
|
|
|
|
#strRes = self.execProg("id %s" %userName)
|
|
|
|
|
#reFind = re.compile("uid=(\d+)\(.+gid=(\d+)\(")
|
|
|
|
|
#res = reFind.search(strRes)
|
|
|
|
|
#if res:
|
|
|
|
|
#return res.group(1), res.group(2)
|
|
|
|
|
#else:
|
|
|
|
|
#self.printERROR(_("User %s not found")\
|
|
|
|
|
#%str(userName))
|
|
|
|
|
#return False
|
|
|
|
|
|
|
|
|
|
def getUserPasswdInfo(self, userName):
|
|
|
|
|
"""получаем uid и gid пользователя из /etc/passwd"""
|
|
|
|
|
resPasswd = self.searchPasswdUser(userName)
|
|
|
|
|
if resPasswd:
|
|
|
|
|
uid = resPasswd.split(":")[2]
|
|
|
|
|
gid = resPasswd.split(":")[3]
|
|
|
|
|
fullName = resPasswd.split(":")[4]
|
|
|
|
|
mail = ""
|
|
|
|
|
group = ""
|
|
|
|
|
home = os.path.join("/home",userName)
|
|
|
|
|
resGroup = self.searchGroupGid(gid)
|
|
|
|
|
if resGroup:
|
|
|
|
|
group = resGroup.split(":")[0]
|
|
|
|
|
return (uid, gid, fullName, mail, home, group)
|
|
|
|
|
else:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
def getAlwaysProfilePath(self):
|
|
|
|
|
"""Получаем пути к профилям которые применяются постоянно"""
|
|
|
|
|
profilePath = self.clVars.Get('cl_profile_path')
|
|
|
|
|
alwProfilePath = []
|
|
|
|
|
for prPath in profilePath:
|
|
|
|
|
if os.path.split(prPath)[1] == "always":
|
|
|
|
|
alwProfilePath.append(prPath)
|
|
|
|
|
return alwProfilePath
|
|
|
|
|
|
|
|
|
|
def createHome(self, userName, applyAlways=False, progress=False):
|
|
|
|
|
"""Создание пользовательской директории с настройками для kde4"""
|
|
|
|
|
# Имя пользователя
|
|
|
|
|
self.userName = userName
|
|
|
|
|
# Проверяем на root
|
|
|
|
|
if not self.isRoot():
|
|
|
|
|
return False
|
|
|
|
|
# Создаем объект переменных
|
|
|
|
|
self.createClVars()
|
|
|
|
|
uidGid = False
|
|
|
|
|
# Подсоединяемся к серверу
|
|
|
|
|
domain = self.clVars.Get("cl_remote_host")
|
|
|
|
|
connectLdap = False
|
|
|
|
|
if domain:
|
|
|
|
|
if not self.getLdapObjBind(domain):
|
|
|
|
|
return False
|
|
|
|
|
connectLdap = True
|
|
|
|
|
if connectLdap:
|
|
|
|
|
# uid и gid и mail из Ldap
|
|
|
|
|
uidGid = self.getUserLdapInfo(userName,False)
|
|
|
|
|
if not domain:
|
|
|
|
|
# uid и gid и mail из passwd
|
|
|
|
|
uidGid = self.getUserPasswdInfo(userName)
|
|
|
|
|
if not uidGid:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
self.printERROR(_("Not found user uid and gid"))
|
|
|
|
|
return False
|
|
|
|
|
uid = int(uidGid[0])
|
|
|
|
|
gid = int(uidGid[1])
|
|
|
|
|
fullName = uidGid[2]
|
|
|
|
|
mail = uidGid[3]
|
|
|
|
|
homeDir = uidGid[4]
|
|
|
|
|
group = uidGid[5]
|
|
|
|
|
# Создаем пользовательскую директорию
|
|
|
|
|
self.clVars.Set('cl_root_path',homeDir,True)
|
|
|
|
|
homeExists = os.path.exists(homeDir)
|
|
|
|
|
|
|
|
|
|
if homeExists:
|
|
|
|
|
self.printWARNING(_("Home dir %s exists")%homeDir)
|
|
|
|
|
if set(os.listdir(homeDir))-set(["Home","Disks","FTP",\
|
|
|
|
|
self.replLogoutFile]):
|
|
|
|
|
if not applyAlways:
|
|
|
|
|
# Получаем пути к профилям постоянного наложения
|
|
|
|
|
alwProfilePath = self.getAlwaysProfilePath()
|
|
|
|
|
if not alwProfilePath:
|
|
|
|
|
return True
|
|
|
|
|
# Записываем пути к профилям постоянного наложения
|
|
|
|
|
#в переменную
|
|
|
|
|
self.printSUCCESS(_("Apply always profiles") + " ...")
|
|
|
|
|
self.clVars.Set('cl_profile_path',alwProfilePath, True)
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(homeDir):
|
|
|
|
|
self.createUserDir(uid, gid, homeDir)
|
|
|
|
|
# Записываем переменные
|
|
|
|
|
self.clVars.Set('ur_login',userName)
|
|
|
|
|
self.clVars.Set('ur_fullname',fullName)
|
|
|
|
|
self.clVars.Set('ur_mail',mail)
|
|
|
|
|
self.clVars.Set('ur_group',group)
|
|
|
|
|
# Применяем профили для пользователя
|
|
|
|
|
dirsAndFiles = self.applyProfilesFromUser(progress)
|
|
|
|
|
if not dirsAndFiles:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
self.printERROR(_("Not apply user profile"))
|
|
|
|
|
return False
|
|
|
|
|
self.chownR(homeDir, uid, gid, dirsAndFiles)
|
|
|
|
|
if not homeExists:
|
|
|
|
|
self.printSUCCESS(_("Created home dir %s")%homeDir + " ...")
|
|
|
|
|
self.printSUCCESS(_("User account is configured") + " ...")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def isDomain(self):
|
|
|
|
|
"""Находится ли компьютер в домене"""
|
|
|
|
|
self.createClVars(self.clVars)
|
|
|
|
|
foundMountRemote =self.isMount("/var/calculate/remote" ,"cifs")
|
|
|
|
|
foundMountHome =self.isMount("/var/calculate/client-home","none",False)
|
|
|
|
|
if not (self.clVars.Get("cl_remote_host") and foundMountRemote and\
|
|
|
|
|
foundMountHome):
|
|
|
|
|
self.printERROR("The computer is not in domain")
|
|
|
|
|
return False
|
|
|
|
|
return (foundMountRemote,foundMountHome)
|
|
|
|
|
|
|
|
|
|
def killRsync(self):
|
|
|
|
|
"""Убивает все процессы rsync и cl-sync --login"""
|
|
|
|
|
listProcess = self.execProg("ps ax",False,False)
|
|
|
|
|
killPid = []
|
|
|
|
|
flagError = False
|
|
|
|
|
for process in listProcess:
|
|
|
|
|
if "rsync" in process:
|
|
|
|
|
killPid.append(process.split(" ")[0])
|
|
|
|
|
if "--login" in process and "cl-sync" in process:
|
|
|
|
|
killPid.append(process.split(" ")[0])
|
|
|
|
|
if killPid and " ".join(killPid).strip():
|
|
|
|
|
textLine = self.execProg("kill -9 %s" %" ".join(killPid))
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not 'kill %s'")\
|
|
|
|
|
%" ".join(killPid))
|
|
|
|
|
flagError = True
|
|
|
|
|
if flagError:
|
|
|
|
|
return False
|
|
|
|
|
else:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def isMount(self, pathMount ,typeMount, secondPath=True):
|
|
|
|
|
"""Примонтирована ли директория"""
|
|
|
|
|
path = os.path.realpath(pathMount)
|
|
|
|
|
foundMount = False
|
|
|
|
|
if secondPath:
|
|
|
|
|
reFoundMount = re.compile("on\s+%s\s+type\s+%s"%(path,typeMount))
|
|
|
|
|
else:
|
|
|
|
|
reFoundMount = re.compile("%s\s+.+type\s+%s"%(path,typeMount))
|
|
|
|
|
resMount = self.execProg("mount",False,False)
|
|
|
|
|
if resMount and type(resMount) == types.ListType:
|
|
|
|
|
for string in resMount:
|
|
|
|
|
if reFoundMount.search(string):
|
|
|
|
|
foundMount = string
|
|
|
|
|
break
|
|
|
|
|
return foundMount
|
|
|
|
|
|
|
|
|
|
def mountRemote(self):
|
|
|
|
|
"""Монтирование remote и домашней директории если компьютер в домене"""
|
|
|
|
|
# Проверяем на root
|
|
|
|
|
if not self.isRoot():
|
|
|
|
|
return False
|
|
|
|
|
self.createClVars(self.clVars)
|
|
|
|
|
domain = self.clVars.Get("cl_remote_host")
|
|
|
|
|
if domain:
|
|
|
|
|
foundMountRemote = self.isMount("/var/calculate/remote" ,"cifs")
|
|
|
|
|
foundMountHome = self.isMount("/var/calculate/client-home","none",
|
|
|
|
|
False)
|
|
|
|
|
else:
|
|
|
|
|
self.printERROR("The computer is not in domain")
|
|
|
|
|
return False
|
|
|
|
|
pathHome = "/var/calculate/client-home"
|
|
|
|
|
if foundMountRemote:
|
|
|
|
|
self.printWARNING(_("Samba resource [remote] is mount") + \
|
|
|
|
|
" ...")
|
|
|
|
|
if foundMountHome:
|
|
|
|
|
self.printWARNING(str(pathHome) + " " +_("is mount")+
|
|
|
|
|
" ...")
|
|
|
|
|
if foundMountHome and foundMountRemote:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
if not foundMountRemote:
|
|
|
|
|
pathRemote = "/var/calculate/remote"
|
|
|
|
|
pwdRemote = self.clVars.Get("cl_remote_pw")
|
|
|
|
|
if not (domain and pwdRemote):
|
|
|
|
|
self.printERROR(_("Not found vaiable: cl_remote_pw") + " ...")
|
|
|
|
|
return False
|
|
|
|
|
if not os.path.exists(pathRemote):
|
|
|
|
|
os.makedirs(pathRemote)
|
|
|
|
|
#Экранируем символы
|
|
|
|
|
escPwdRemote = re.sub("(\W)", r"\\\1",pwdRemote)
|
|
|
|
|
mountStr = "PASSWD=%s mount -t cifs -o user=client \
|
|
|
|
|
//%s/remote %s" %(escPwdRemote,domain,pathRemote)
|
|
|
|
|
textLine = self.execProg(mountStr)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not mount Samba resource [remote]") +\
|
|
|
|
|
" ...")
|
|
|
|
|
return False
|
|
|
|
|
self.printSUCCESS(_("Mount Samba resource [remote]") +\
|
|
|
|
|
" ...")
|
|
|
|
|
if not foundMountHome:
|
|
|
|
|
if not os.path.exists(pathHome):
|
|
|
|
|
os.makedirs(pathHome)
|
|
|
|
|
mountStr = "mount -o bind %s /home" %pathHome
|
|
|
|
|
textLine = self.execProg(mountStr)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not mount") + " " + str(pathHome) +\
|
|
|
|
|
" ...")
|
|
|
|
|
return False
|
|
|
|
|
self.printSUCCESS(_("Mount") + " " + str(pathHome) + " " +\
|
|
|
|
|
" ...")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def delDomain(self):
|
|
|
|
|
"""выводим из домена"""
|
|
|
|
|
# Проверяем на root
|
|
|
|
|
if not self.isRoot():
|
|
|
|
|
return False
|
|
|
|
|
self.createClVars()
|
|
|
|
|
pathRemote = "/var/calculate/remote"
|
|
|
|
|
pathHome = "/var/calculate/client-home"
|
|
|
|
|
foundMountRemote = self.isMount(pathRemote ,"cifs")
|
|
|
|
|
foundMountHome = self.isMount(pathHome ,"none",False)
|
|
|
|
|
domain = self.clVars.Get("cl_remote_host")
|
|
|
|
|
if not domain:
|
|
|
|
|
self.printWARNING("The computer is not in domain")
|
|
|
|
|
return True
|
|
|
|
|
if foundMountRemote:
|
|
|
|
|
textLineUmount = self.umountSleepPath(pathRemote)
|
|
|
|
|
if not textLineUmount:
|
|
|
|
|
return False
|
|
|
|
|
if foundMountHome:
|
|
|
|
|
textLineUmount = self.umountSleepPath(pathHome ,"none", False)
|
|
|
|
|
if not textLineUmount:
|
|
|
|
|
return False
|
|
|
|
|
self.clVars.Delete("cl_remote_host","local")
|
|
|
|
|
self.clVars.Delete("cl_remote_pw","local")
|
|
|
|
|
self.execProg("calculate -P install/6intranet")
|
|
|
|
|
self.printOK(_("Computer removed from domain %s")%domain + " ...")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def addDomain(self, domainName):
|
|
|
|
|
"""Вводим в домен"""
|
|
|
|
|
# Проверяем на root
|
|
|
|
|
if not self.isRoot():
|
|
|
|
|
return False
|
|
|
|
|
# Создаем объект переменных
|
|
|
|
|
self.createClVars()
|
|
|
|
|
netDomain = self.clVars.Get("os_net_domain")
|
|
|
|
|
# Получам имя сервера (домена)
|
|
|
|
|
if "." in domainName:
|
|
|
|
|
domain = domainName
|
|
|
|
|
else:
|
|
|
|
|
domain = "%s.%s" %(domainName,netDomain)
|
|
|
|
|
resPing = self.execProg("ping -c 2 -i 0.3 %s" %domain,False,False)
|
|
|
|
|
foudHost = False
|
|
|
|
|
foudHostSamba = False
|
|
|
|
|
foundMountRemote = False
|
|
|
|
|
reFoundHost = re.compile("(\d+)\% packet loss")
|
|
|
|
|
if resPing and type(resPing) == types.ListType and len(resPing)>=2:
|
|
|
|
|
pingStr = resPing[-2].strip()
|
|
|
|
|
reSearch = reFoundHost.search(pingStr)
|
|
|
|
|
if reSearch and reSearch.group(1) == "0":
|
|
|
|
|
foudHost = True
|
|
|
|
|
if not foudHost:
|
|
|
|
|
self.printERROR(_("Not found domain %s")%domain)
|
|
|
|
|
return False
|
|
|
|
|
reFoundHostSamba = re.compile("Server=\[Samba.+\]")
|
|
|
|
|
resSmbClient = self.execProg("smbclient -N -L %s" %domain,
|
|
|
|
|
False,False)
|
|
|
|
|
if resSmbClient and type(resSmbClient) == types.ListType:
|
|
|
|
|
for string in resSmbClient:
|
|
|
|
|
if reFoundHostSamba.search(string):
|
|
|
|
|
foudHostSamba = True
|
|
|
|
|
break
|
|
|
|
|
if not foudHostSamba:
|
|
|
|
|
self.printERROR(_("Not found Samba server in %s")%domain)
|
|
|
|
|
return False
|
|
|
|
|
pwd = False
|
|
|
|
|
if self.clVars.Get("cl_remote_host") and \
|
|
|
|
|
self.clVars.Get("cl_remote_host") != domain:
|
|
|
|
|
if not self.delDomain():
|
|
|
|
|
return False
|
|
|
|
|
elif self.clVars.Get("cl_remote_host") and \
|
|
|
|
|
self.clVars.Get("cl_remote_host") == domain:
|
|
|
|
|
pwd = self.clVars.Get("cl_remote_pw")
|
|
|
|
|
foundMountRemote =self.isMount("/var/calculate/remote" ,"cifs")
|
|
|
|
|
foundMountHome =self.isMount("/var/calculate/client-home","none",False)
|
|
|
|
|
if foundMountRemote:
|
|
|
|
|
self.printWARNING(_("Samba resource [remote] mount") + \
|
|
|
|
|
" ...")
|
|
|
|
|
else:
|
|
|
|
|
if pwd:
|
|
|
|
|
userPwd = pwd
|
|
|
|
|
else:
|
|
|
|
|
userPwd=self.getUserPassword("Domain password for the desktop")
|
|
|
|
|
pathRemote = "/var/calculate/remote"
|
|
|
|
|
pwdRemote = userPwd
|
|
|
|
|
if not os.path.exists(pathRemote):
|
|
|
|
|
os.makedirs(pathRemote)
|
|
|
|
|
# Экранируем символы
|
|
|
|
|
escPwdRemote = re.sub("(\W)", r"\\\1",pwdRemote)
|
|
|
|
|
mountStr = "PASSWD=%s mount -t cifs -o user=client \
|
|
|
|
|
//%s/remote %s" %(escPwdRemote,domain,pathRemote)
|
|
|
|
|
textLine = self.execProg(mountStr)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not mount Samba resource [remote]") + \
|
|
|
|
|
" ...")
|
|
|
|
|
return False
|
|
|
|
|
else:
|
|
|
|
|
self.printSUCCESS(_("Mount Samba resource [remote]") + \
|
|
|
|
|
" ...")
|
|
|
|
|
self.clVars.Write("cl_remote_host", domain, False, "local")
|
|
|
|
|
self.clVars.Write("cl_remote_pw", userPwd, False, "local")
|
|
|
|
|
pathHome = "/var/calculate/client-home"
|
|
|
|
|
if foundMountHome:
|
|
|
|
|
self.printWARNING(str(pathHome)+ " " +_("is mount")+
|
|
|
|
|
" ...")
|
|
|
|
|
else:
|
|
|
|
|
if not os.path.exists(pathHome):
|
|
|
|
|
os.makedirs(pathHome)
|
|
|
|
|
mountStr = "mount -o bind %s /home" %pathHome
|
|
|
|
|
textLine = self.execProg(mountStr)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not mount") + " " + str(pathHome) +\
|
|
|
|
|
" ...")
|
|
|
|
|
return False
|
|
|
|
|
self.printSUCCESS(_("Mount") + " " + str(pathHome) + " " +\
|
|
|
|
|
" ...")
|
|
|
|
|
self.clVars.flIniFile()
|
|
|
|
|
#считаем переменные для клиента
|
|
|
|
|
servDn = self.clVars.Get("ld_services_dn")
|
|
|
|
|
unixDN = self.clVars.Get("ld_unix_dn")
|
|
|
|
|
bindDn = self.clVars.Get("ld_bind_dn")
|
|
|
|
|
bindPw = self.clVars.Get("ld_bind_pw")
|
|
|
|
|
# запишем их
|
|
|
|
|
if not (servDn and unixDN and bindDn and bindPw):
|
|
|
|
|
self.printERROR(_("Not found variables:"))
|
|
|
|
|
self.printERROR("ld_services_dn or ld_unix_dn \
|
|
|
|
|
or ld_bind_dn or ld_bind_pw")
|
|
|
|
|
return False
|
|
|
|
|
execStr = "calculate --set-server_url=%s --set-ldap_base=%s \
|
|
|
|
|
--set-ldap_root=%s --set-ldap_bind=%s --set-ldap_bindpw=%s -P \
|
|
|
|
|
install/6intranet" %(domain,servDn,unixDN,bindDn,bindPw)
|
|
|
|
|
self.execProg(execStr)
|
|
|
|
|
textLine = self.execProg("/etc/init.d/dbus restart")
|
|
|
|
|
if not "ok" in textLine:
|
|
|
|
|
self.printWARNING(_("Error restarting /etc/init.d/dbus")+ " ...")
|
|
|
|
|
return False
|
|
|
|
|
self.printOK(_("Computer added to domain %s")%domain + " ...")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def removePrivateFiles(self, userHome):
|
|
|
|
|
"""Удаление приватных файлов"""
|
|
|
|
|
privateFiles = ['.kde4/share/apps/kwallet/kdewallet.kwl']
|
|
|
|
|
for prFile in privateFiles:
|
|
|
|
|
rmFile = os.path.join(userHome, prFile)
|
|
|
|
|
if os.path.exists(rmFile):
|
|
|
|
|
os.remove(rmFile)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def umountSleepPath(self, path, typeMount='cifs', secondPath=True):
|
|
|
|
|
"""Отмонтирует путь при неудаче задержка потом повтор"""
|
|
|
|
|
#Проверяем на монтирование директории
|
|
|
|
|
if self.isMount(path, typeMount, secondPath):
|
|
|
|
|
textLine = self.execProg("umount %s"%path)
|
|
|
|
|
if textLine != None:
|
|
|
|
|
i = 0
|
|
|
|
|
flagError = False
|
|
|
|
|
while (i<len(self.sleeps) and textLine != None):
|
|
|
|
|
# Задержка перед следующей попыткой
|
|
|
|
|
time.sleep(self.sleeps[i])
|
|
|
|
|
# Отмонтируем Samba ресурс
|
|
|
|
|
if self.isMount(path, typeMount, secondPath):
|
|
|
|
|
textLine = self.execProg("umount %s"%path)
|
|
|
|
|
else:
|
|
|
|
|
textLine = None
|
|
|
|
|
break
|
|
|
|
|
i += 1
|
|
|
|
|
if textLine != None:
|
|
|
|
|
self.printERROR(_("Can not unmount path %s")%path + " ...")
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def umountUserRes(self, userName,progress=False):
|
|
|
|
|
"""Отмонтирование пользовательских ресурсов и синхронизация настроек"""
|
|
|
|
|
# Имя пользователя
|
|
|
|
|
self.userName = userName
|
|
|
|
|
# Проверяем на root
|
|
|
|
|
if not self.isRoot():
|
|
|
|
|
return False
|
|
|
|
|
self.createClVars()
|
|
|
|
|
# В случае компьютера вне домена
|
|
|
|
|
if not self.clVars.Get("cl_remote_host"):
|
|
|
|
|
self.printSUCCESS(_("To be used by local profile."))
|
|
|
|
|
return True
|
|
|
|
|
connectDomain = self.isDomain()
|
|
|
|
|
if not connectDomain:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
elif not connectDomain[0]:
|
|
|
|
|
self.printERROR(_("Can not mount Samba resource [remote]") + \
|
|
|
|
|
" ...")
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
# Если пользователь в X сессии тогда не будем отмонтировать ресурсы
|
|
|
|
|
if self.isSessionUser(userName):
|
|
|
|
|
self.printERROR(_("User %s is in X session")%userName)
|
|
|
|
|
self.printERROR(_("Can not unmount user %s resource")%userName)
|
|
|
|
|
return False
|
|
|
|
|
# Подсоединяемся к серверу
|
|
|
|
|
domain = self.clVars.Get("cl_remote_host")
|
|
|
|
|
if not self.getLdapObjBind(domain):
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
# homeDir из LDAP
|
|
|
|
|
resLdap = self.getUserLdapInfo(userName)
|
|
|
|
|
if not resLdap:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
uid = int(resLdap[0])
|
|
|
|
|
gid = int(resLdap[1])
|
|
|
|
|
homeDir = resLdap[4]
|
|
|
|
|
home = os.path.split(homeDir)[0]
|
|
|
|
|
pathRemote = []
|
|
|
|
|
# Удаленный ресурс профилей
|
|
|
|
|
pathRemote.append((os.path.join(home,"." + userName), "unix"))
|
|
|
|
|
# Удаленный ресурс home
|
|
|
|
|
pathRemote.append((os.path.join(homeDir,"Home"), "homes"))
|
|
|
|
|
# Удаленный ресурс ftp
|
|
|
|
|
if self.clVars.Get("cl_remote_ftp"):
|
|
|
|
|
pathRemote.append((os.path.join(homeDir,"FTP"), "ftp"))
|
|
|
|
|
# Удаленный ресурс share
|
|
|
|
|
pathRemote.append((os.path.join(homeDir,"Disks"), "share"))
|
|
|
|
|
if os.path.exists(homeDir):
|
|
|
|
|
self.moveHomeDir(homeDir)
|
|
|
|
|
else:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
self.printERROR(_("Directory %s not found") % homeDir)
|
|
|
|
|
return False
|
|
|
|
|
# Синхронизируем настройки
|
|
|
|
|
pathUnix = ""
|
|
|
|
|
for path, res in pathRemote:
|
|
|
|
|
if res == 'unix':
|
|
|
|
|
pathUnix = path
|
|
|
|
|
break
|
|
|
|
|
if pathUnix and self.isMount(pathUnix ,"cifs") and \
|
|
|
|
|
not(domain in self.isMount(pathUnix ,"cifs")):
|
|
|
|
|
# Убиваем rsync
|
|
|
|
|
if not self.killRsync():
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
textLine = self.umountSleepPath(pathUnix)
|
|
|
|
|
if not textLine:
|
|
|
|
|
self.printERROR(_("Can not unmount path %s")%pathUnix+ " ...")
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
# Монтируем ресурс Unix
|
|
|
|
|
# Получаем пароль пользователя из ключей ядра
|
|
|
|
|
userPwd = _cl_keys.getKey(userName)
|
|
|
|
|
if not userPwd:
|
|
|
|
|
self.printERROR(_("Not found user password"))
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
textLine = self.mountSleepRes(userName,userPwd,uid,gid,
|
|
|
|
|
"unix",pathUnix)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not mount Samba resource [%s]")\
|
|
|
|
|
%"unix" + " ...")
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
if not self.syncUser(userName, homeDir, "logout", uid, gid):
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
# Удаляем приватные файлы
|
|
|
|
|
self.removePrivateFiles(homeDir)
|
|
|
|
|
flagError = False
|
|
|
|
|
for path, res in pathRemote:
|
|
|
|
|
if self.isMount(path ,"cifs"):
|
|
|
|
|
# В случае репликации
|
|
|
|
|
if res == "share":
|
|
|
|
|
# Проверка на репликацию
|
|
|
|
|
pathReplRun = os.path.join(path, self.replRunFileShare)
|
|
|
|
|
if os.path.exists(pathReplRun):
|
|
|
|
|
FD = open(pathReplRun)
|
|
|
|
|
# Записывает доменное имя сервера если
|
|
|
|
|
# с сервером корректно соединились
|
|
|
|
|
FD.close()
|
|
|
|
|
textLine = self.umountSleepPath(path)
|
|
|
|
|
if not textLine:
|
|
|
|
|
flagError = True
|
|
|
|
|
break
|
|
|
|
|
if os.path.exists(path) and not os.listdir(path):
|
|
|
|
|
try:
|
|
|
|
|
os.rmdir(path)
|
|
|
|
|
except:
|
|
|
|
|
self.printERROR(_("Can not remove dir %s")% path)
|
|
|
|
|
flagError = True
|
|
|
|
|
break
|
|
|
|
|
if flagError:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
self.printERROR(_("Can not keep a user profile in the domain"))
|
|
|
|
|
return False
|
|
|
|
|
self.printSUCCESS(_("Keep a user profile in the domain"))
|
|
|
|
|
self.printOK(_("Umount user resource in domain") + " ...")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def umountUserResNoSync(self, userName, printError=True,
|
|
|
|
|
printSuccess=True, isXsession=True, killRsync=False,
|
|
|
|
|
progress=False):
|
|
|
|
|
"""Отмонтирование пользовательских ресурсов
|
|
|
|
|
|
|
|
|
|
без синхронизации настроек"""
|
|
|
|
|
# Имя пользователя
|
|
|
|
|
self.userName = userName
|
|
|
|
|
# Проверяем на root
|
|
|
|
|
if not self.isRoot():
|
|
|
|
|
return False
|
|
|
|
|
if killRsync:
|
|
|
|
|
self.killRsync()
|
|
|
|
|
self.createClVars(self.clVars)
|
|
|
|
|
# В случае компьютера вне домена
|
|
|
|
|
if not self.clVars.Get("cl_remote_host"):
|
|
|
|
|
self.printSUCCESS(_("To be used by local profile."))
|
|
|
|
|
return True
|
|
|
|
|
# Подсоединяемся к серверу
|
|
|
|
|
domain = self.clVars.Get("cl_remote_host")
|
|
|
|
|
home = ""
|
|
|
|
|
homeDir = ""
|
|
|
|
|
if not self.getLdapObjBind(domain, printError):
|
|
|
|
|
home = "/home"
|
|
|
|
|
homeDir = os.path.join(home,userName)
|
|
|
|
|
# Если пользователь в X сессии тогда не будем отмонтировать ресурсы
|
|
|
|
|
if isXsession and self.isSessionUser(userName):
|
|
|
|
|
self.printERROR(_("User %s is in X session")%userName)
|
|
|
|
|
elf.printERROR(_("Can not unmount user %s resource")%userName)
|
|
|
|
|
return False
|
|
|
|
|
if not homeDir:
|
|
|
|
|
# homeDir из LDAP
|
|
|
|
|
resLdap = self.getUserLdapInfo(userName, printError)
|
|
|
|
|
if not resLdap:
|
|
|
|
|
home = "/home"
|
|
|
|
|
homeDir = os.path.join(home,userName)
|
|
|
|
|
else:
|
|
|
|
|
homeDir = resLdap[4]
|
|
|
|
|
home = os.path.split(homeDir)[0]
|
|
|
|
|
pathRemote = []
|
|
|
|
|
# Удаленный ресурс профилей
|
|
|
|
|
pathRemote.append((os.path.join(home,"." + userName), "unix"))
|
|
|
|
|
# Удаленный ресурс home
|
|
|
|
|
pathRemote.append((os.path.join(homeDir,"Home"), "homes"))
|
|
|
|
|
# Удаленный ресурс ftp
|
|
|
|
|
if self.clVars.Get("cl_remote_ftp"):
|
|
|
|
|
pathRemote.append((os.path.join(homeDir,"FTP"), "ftp"))
|
|
|
|
|
# Удаленный ресурс share
|
|
|
|
|
pathRemote.append((os.path.join(homeDir,"Disks"), "share"))
|
|
|
|
|
flagError = False
|
|
|
|
|
if self.isMount(pathRemote[1][0] ,"cifs"):
|
|
|
|
|
self.moveHomeDir(homeDir)
|
|
|
|
|
for path, res in pathRemote:
|
|
|
|
|
if self.isMount(path ,"cifs"):
|
|
|
|
|
textLine = self.umountSleepPath(path)
|
|
|
|
|
if not textLine:
|
|
|
|
|
flagError = True
|
|
|
|
|
break
|
|
|
|
|
if os.path.exists(path) and not os.listdir(path):
|
|
|
|
|
try:
|
|
|
|
|
os.rmdir(path)
|
|
|
|
|
except:
|
|
|
|
|
if printError:
|
|
|
|
|
self.printERROR(_("Can not remove dir %s")% path)
|
|
|
|
|
flagError = True
|
|
|
|
|
break
|
|
|
|
|
if flagError:
|
|
|
|
|
if printError:
|
|
|
|
|
self.printERROR(_("Can not unmount user %s resource")%userName)
|
|
|
|
|
return False
|
|
|
|
|
if printSuccess:
|
|
|
|
|
self.printOK(_("Umount user %s resources") %userName + " ...")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def isSessionUser(self, userName):
|
|
|
|
|
"""Проверка на вход пользователя в X"""
|
|
|
|
|
xSession = False
|
|
|
|
|
reFoundUser = re.compile("%s\s:\d+\s+"%(userName))
|
|
|
|
|
resWho = self.execProg("who",False,False)
|
|
|
|
|
if resWho and type(resWho) == types.ListType:
|
|
|
|
|
for string in resWho:
|
|
|
|
|
if reFoundUser.search(string):
|
|
|
|
|
xSession = True
|
|
|
|
|
break
|
|
|
|
|
return xSession
|
|
|
|
|
|
|
|
|
|
def isTwoSessionsUser(self, userName):
|
|
|
|
|
"""Проверка на повторный вход пользователя"""
|
|
|
|
|
xSession = 0
|
|
|
|
|
foundTwoSession = False
|
|
|
|
|
reFoundUser = re.compile("%s\s:\d+\s+"%(userName))
|
|
|
|
|
resWho = self.execProg("who",False,False)
|
|
|
|
|
if resWho and type(resWho) == types.ListType:
|
|
|
|
|
for string in resWho:
|
|
|
|
|
if reFoundUser.search(string):
|
|
|
|
|
xSession +=1
|
|
|
|
|
if xSession>1:
|
|
|
|
|
foundTwoSession = True
|
|
|
|
|
self.printERROR(\
|
|
|
|
|
_("Second X session for user %s can not be opened.")\
|
|
|
|
|
%userName)
|
|
|
|
|
break
|
|
|
|
|
return foundTwoSession
|
|
|
|
|
|
|
|
|
|
def mountSambaRes(self,userName,userPwd,uid,gid,res,path,
|
|
|
|
|
mountUidList=['ftp','share']):
|
|
|
|
|
"""Монтирует Samba ресурсы"""
|
|
|
|
|
#Экранируем символы
|
|
|
|
|
escUserPwd = re.sub("(\W)", r"\\\1",userPwd)
|
|
|
|
|
if res in mountUidList:
|
|
|
|
|
# Монтируем директории c uid
|
|
|
|
|
mountStr="PASSWD=%s mount -t cifs -o user=%s,uid=%s,gid=%s"\
|
|
|
|
|
%(escUserPwd,userName,uid,gid) +\
|
|
|
|
|
" //%s/%s %s" %(self.clVars.Get("cl_remote_host"),
|
|
|
|
|
res, path)
|
|
|
|
|
else:
|
|
|
|
|
# Монтируем директории
|
|
|
|
|
mountStr="PASSWD=%s mount -t cifs -o user=%s"%(escUserPwd,
|
|
|
|
|
userName)+\
|
|
|
|
|
" //%s/%s %s" %(self.clVars.Get("cl_remote_host"),
|
|
|
|
|
res, path)
|
|
|
|
|
textLine = self.execProg(mountStr)
|
|
|
|
|
return textLine
|
|
|
|
|
|
|
|
|
|
def removeDir(self, rmDir):
|
|
|
|
|
"""Рекурсивное удаление директории"""
|
|
|
|
|
if not os.path.exists(rmDir):
|
|
|
|
|
self.printERROR(_("Not found remove dir %s") %rmDir)
|
|
|
|
|
return False
|
|
|
|
|
fileObj = cl_profile._file()
|
|
|
|
|
# Сканируем директорию
|
|
|
|
|
scanObjs = fileObj.scanDirs([rmDir])
|
|
|
|
|
for fileRm in scanObjs[0].files:
|
|
|
|
|
# Удаляем файлы
|
|
|
|
|
os.remove(fileRm)
|
|
|
|
|
for socketRm in scanObjs[0].sockets:
|
|
|
|
|
# Удаляем сокеты
|
|
|
|
|
os.remove(socketRm)
|
|
|
|
|
for linkRm in scanObjs[0].links:
|
|
|
|
|
# Удаляем ссылки
|
|
|
|
|
os.unlink(linkRm[1])
|
|
|
|
|
scanObjs[0].dirs.sort(lambda x, y: cmp(len(y), len(x)))
|
|
|
|
|
for dirRm in scanObjs[0].dirs:
|
|
|
|
|
# Удаляем директории
|
|
|
|
|
os.rmdir(dirRm)
|
|
|
|
|
os.rmdir(rmDir)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def mountUserRes(self, userName, sync=True, progress=False):
|
|
|
|
|
"""Монтирование пользовательских ресурсов и синхронизация настроек"""
|
|
|
|
|
# Имя пользователя
|
|
|
|
|
self.userName = userName
|
|
|
|
|
# Проверяем на root
|
|
|
|
|
if not self.isRoot():
|
|
|
|
|
return False
|
|
|
|
|
# Проверка на повторный вход пользователя
|
|
|
|
|
if self.isTwoSessionsUser(userName):
|
|
|
|
|
return False
|
|
|
|
|
self.createClVars()
|
|
|
|
|
# В случае компьютера вне домена
|
|
|
|
|
if not self.clVars.Get("cl_remote_host"):
|
|
|
|
|
self.printSUCCESS(_("To be used by local profile."))
|
|
|
|
|
return True
|
|
|
|
|
# Проверим что компьютер в домене и смонтирован [remote]
|
|
|
|
|
connectDomain = self.isDomain()
|
|
|
|
|
if not connectDomain:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
elif not connectDomain[0]:
|
|
|
|
|
self.printERROR(_("Can not mount Samba resource [remote]") + \
|
|
|
|
|
" ...")
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
# Подсоединяемся к серверу
|
|
|
|
|
domain = self.clVars.Get("cl_remote_host")
|
|
|
|
|
if not self.getLdapObjBind(domain):
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
# homeDir из LDAP
|
|
|
|
|
resLdap = self.getUserLdapInfo(userName)
|
|
|
|
|
if not resLdap:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
uid = int(resLdap[0])
|
|
|
|
|
gid = int(resLdap[1])
|
|
|
|
|
homeDir = resLdap[4]
|
|
|
|
|
# При отсуствии создаем домашнюю директорию
|
|
|
|
|
if not os.path.exists(homeDir):
|
|
|
|
|
os.makedirs(homeDir)
|
|
|
|
|
os.chown(homeDir,uid,gid)
|
|
|
|
|
os.chmod(homeDir,0700)
|
|
|
|
|
# Получаем пароль пользователя из ключей ядра
|
|
|
|
|
userPwd = _cl_keys.getKey(userName)
|
|
|
|
|
if not userPwd:
|
|
|
|
|
self.printERROR(_("Not found user password"))
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
home = os.path.split(homeDir)[0]
|
|
|
|
|
pathRemote = []
|
|
|
|
|
# Удаленный ресурс share
|
|
|
|
|
pathRemote.append((os.path.join(homeDir,"Disks"), "share"))
|
|
|
|
|
# Удаленный ресурс профилей
|
|
|
|
|
pathRemote.append((os.path.join(home,"." + userName), "unix"))
|
|
|
|
|
# Удаленный ресурс home
|
|
|
|
|
pathRemote.append((os.path.join(homeDir,"Home"), "homes"))
|
|
|
|
|
if self.clVars.Get("cl_remote_ftp"):
|
|
|
|
|
# Удаленный ресурс ftp
|
|
|
|
|
pathRemote.append((os.path.join(homeDir,"FTP"), "ftp"))
|
|
|
|
|
flagError = False
|
|
|
|
|
# Запускаемый файл на сервере в случае репликации
|
|
|
|
|
pathReplRun = ""
|
|
|
|
|
# Путь к профилю пользователя по умолчанию
|
|
|
|
|
defaultPath = ""
|
|
|
|
|
# Ност пользователя по умолчанию
|
|
|
|
|
defaultHost = self.clVars.Get("cl_remote_host")
|
|
|
|
|
for path, res in pathRemote:
|
|
|
|
|
# Создаем директории для монтирования
|
|
|
|
|
if not os.path.exists(path):
|
|
|
|
|
try:
|
|
|
|
|
os.mkdir(path)
|
|
|
|
|
os.chown(path, uid, gid)
|
|
|
|
|
os.chmod(path,0700)
|
|
|
|
|
except OSError:
|
|
|
|
|
self.printERROR(_("Error creating directory"))
|
|
|
|
|
self.printERROR(_("Permission denied: '%s'")%path)
|
|
|
|
|
flagError = True
|
|
|
|
|
break
|
|
|
|
|
# Проверяем на монтирование директории
|
|
|
|
|
if self.isMount(path, 'cifs'):
|
|
|
|
|
continue
|
|
|
|
|
# В случае репликации не монтируем профиль пользователя
|
|
|
|
|
if pathReplRun and res=="unix":
|
|
|
|
|
defaultPath = path
|
|
|
|
|
continue
|
|
|
|
|
# Монтируем Samba ресурс
|
|
|
|
|
textLine = self.mountSambaRes(userName,userPwd,uid,gid,res,path)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not mount Samba resource [%s]")\
|
|
|
|
|
%res + " ...")
|
|
|
|
|
flagError = True
|
|
|
|
|
break
|
|
|
|
|
# В случае репликации
|
|
|
|
|
if res == "share":
|
|
|
|
|
# Проверка на репликацию
|
|
|
|
|
pathReplRun = os.path.join(path, self.replRunFileShare)
|
|
|
|
|
if os.path.exists(pathReplRun):
|
|
|
|
|
FD = open(pathReplRun)
|
|
|
|
|
# Создание директорий пользователя на сервере
|
|
|
|
|
# в случае если их нет
|
|
|
|
|
FD.close()
|
|
|
|
|
else:
|
|
|
|
|
pathReplRun = ""
|
|
|
|
|
if flagError:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
# Синхронизируем настройки
|
|
|
|
|
if sync:
|
|
|
|
|
# Ошибка при монтировании unix ресурса удаленного сервера при
|
|
|
|
|
# включенной репликации
|
|
|
|
|
replErrorMount = False
|
|
|
|
|
# Ошибка при cинхронизации unix ресурса удаленного сервера при
|
|
|
|
|
# включенной репликации
|
|
|
|
|
replErrorSync = False
|
|
|
|
|
# В случае репликации
|
|
|
|
|
prevHost = ""
|
|
|
|
|
# Монтирование по умолчанию (default - cвой сервер, remote - чужой)
|
|
|
|
|
mountServer = ""
|
|
|
|
|
if pathReplRun:
|
|
|
|
|
searchPrevHost = self.searchPrevHost(userName)
|
|
|
|
|
if searchPrevHost and searchPrevHost[0][0][1].has_key('host'):
|
|
|
|
|
prevHost = searchPrevHost[0][0][1]['host'][0]
|
|
|
|
|
# Монтируем ресурс unix текущего сервера
|
|
|
|
|
mountServer = "default"
|
|
|
|
|
textLine = self.mountSleepRes(userName,userPwd,uid,gid,
|
|
|
|
|
"unix",defaultPath)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not mount Samba resource [%s]")\
|
|
|
|
|
%"unix" + " ...")
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
# Если на текущем сервере в ресурсе unix есть файлы
|
|
|
|
|
# то синхронируем настройки
|
|
|
|
|
if os.listdir(defaultPath):
|
|
|
|
|
if not self.syncUser(userName, homeDir, "login", uid, gid,\
|
|
|
|
|
progress=progress,
|
|
|
|
|
host=self.clVars.Get('cl_remote_host')):
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
else:
|
|
|
|
|
#Удаляем ненужные файлы
|
|
|
|
|
rmFiles = list(set(os.listdir(homeDir))-\
|
|
|
|
|
set(["Home","Disks","FTP",\
|
|
|
|
|
self.replLogoutFile]))
|
|
|
|
|
for rmFile in rmFiles:
|
|
|
|
|
delFile = os.path.join(homeDir,rmFile)
|
|
|
|
|
if os.path.islink(delFile):
|
|
|
|
|
os.unlink(delFile)
|
|
|
|
|
elif os.path.isfile(delFile):
|
|
|
|
|
os.remove(delFile)
|
|
|
|
|
elif os.path.isdir(delFile):
|
|
|
|
|
if not self.removeDir(delFile):
|
|
|
|
|
# Отмонтируем пользовательские ресурсы
|
|
|
|
|
# в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
elif stat.S_ISSOCK(os.stat(delFile)[stat.ST_MODE]):
|
|
|
|
|
os.remove(delFile)
|
|
|
|
|
# Отмонтируем ресурс
|
|
|
|
|
textLine = self.umountSleepPath(defaultPath)
|
|
|
|
|
if not textLine:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
if prevHost and prevHost != self.clVars.Get("cl_remote_host"):
|
|
|
|
|
# Монтируем настройки пользователя удаленного сервера
|
|
|
|
|
# если сервер найден
|
|
|
|
|
self.clVars.Set("cl_remote_host", prevHost, True)
|
|
|
|
|
mountServer = "remote"
|
|
|
|
|
textLine = self.mountSleepRes(userName,userPwd,uid,gid,
|
|
|
|
|
"unix",defaultPath)
|
|
|
|
|
self.clVars.Set("cl_remote_host", defaultHost, True)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
if self.isMount(defaultPath, 'cifs'):
|
|
|
|
|
textLine = self.umountSleepPath(defaultPath)
|
|
|
|
|
if not textLine:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы
|
|
|
|
|
# в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
# Монтируем текущий сервер если ошибка подключения к
|
|
|
|
|
# к найденному серверу
|
|
|
|
|
mountServer = "default"
|
|
|
|
|
textLine = self.mountSleepRes(userName,userPwd,uid,gid,
|
|
|
|
|
"unix",defaultPath)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not mount Samba resource \
|
|
|
|
|
[%s]")%"unix" + " ...")
|
|
|
|
|
# Отмонтируем пользовательские ресурсы
|
|
|
|
|
# в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
replErrorMount = True
|
|
|
|
|
else:
|
|
|
|
|
mountServer = "default"
|
|
|
|
|
# Монтируем текущий сервер если сервер не найден в LDAP
|
|
|
|
|
textLine = self.mountSleepRes(userName,userPwd,uid,gid,
|
|
|
|
|
"unix",defaultPath)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not mount Samba resource \
|
|
|
|
|
[%s]")%"unix" + " ...")
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
# Синхронизируем настройки пользователя
|
|
|
|
|
if not (pathReplRun and mountServer == "default"):
|
|
|
|
|
if not self.syncUser(userName, homeDir, "login", uid, gid,\
|
|
|
|
|
progress=progress,host=prevHost):
|
|
|
|
|
if pathReplRun and mountServer == "remote":
|
|
|
|
|
replErrorSync = True
|
|
|
|
|
else:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
if pathReplRun and mountServer == "remote":
|
|
|
|
|
# В случае репликации перемонтируем ресурс профилей
|
|
|
|
|
# на текущий сервер (в случае необходимости)
|
|
|
|
|
textLine = self.umountSleepPath(defaultPath)
|
|
|
|
|
if not textLine:
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
textLine = self.mountSambaRes(userName,userPwd,uid,gid,
|
|
|
|
|
"unix",defaultPath)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not mount Samba resource [%s]")\
|
|
|
|
|
%"unix" + " ...")
|
|
|
|
|
# Отмонтируем пользовательские ресурсы в случае ошибки
|
|
|
|
|
self.errorAndUnmountUserRes = True
|
|
|
|
|
return False
|
|
|
|
|
if pathReplRun:
|
|
|
|
|
logOutFile = os.path.join(homeDir,self.replLogoutFile)
|
|
|
|
|
if replErrorMount or replErrorSync:
|
|
|
|
|
self.createUserFile(logOutFile,"ERROR", uid, gid)
|
|
|
|
|
else:
|
|
|
|
|
self.createUserFile(logOutFile,"SUCCESS", uid, gid)
|
|
|
|
|
self.printSUCCESS(_("Mount user resource in domain"))
|
|
|
|
|
self.printOK(_("Get a user profile in the domain") + " ...")
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def mountSleepRes(self,userName,userPwd,uid,gid,res,path):
|
|
|
|
|
"""Монтирует ресурс при неудаче задержка потом повторное монитрование"""
|
|
|
|
|
textLine = self.mountSambaRes(userName,userPwd,uid,gid,res,path)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
# Проверяем на монтирование директории
|
|
|
|
|
if self.isMount(path, 'cifs'):
|
|
|
|
|
textLineUmount = self.umountSleepPath(path)
|
|
|
|
|
if not textLineUmount:
|
|
|
|
|
return False
|
|
|
|
|
i = 0
|
|
|
|
|
while (i<len(self.sleeps) and not (textLine == None)):
|
|
|
|
|
# Задержка перед следующей попыткой
|
|
|
|
|
time.sleep(self.sleeps[i])
|
|
|
|
|
# Монтируем Samba ресурс
|
|
|
|
|
textLine = self.mountSambaRes(userName,userPwd,uid,
|
|
|
|
|
gid,res,path)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
# Проверяем на монтирование директории
|
|
|
|
|
if self.isMount(path, 'cifs'):
|
|
|
|
|
textLineUmount = self.umountSleepPath(path)
|
|
|
|
|
if not textLineUmount:
|
|
|
|
|
return False
|
|
|
|
|
i += 1
|
|
|
|
|
return textLine
|
|
|
|
|
|
|
|
|
|
def copyFilesToMovie(self, userHome):
|
|
|
|
|
"""Переносим файлы пользователя в Home/Moved"""
|
|
|
|
|
# Находим директории и файлы в домащней директории
|
|
|
|
|
pathProg = os.getcwd()
|
|
|
|
|
os.chdir(userHome)
|
|
|
|
|
dirs = []
|
|
|
|
|
files = []
|
|
|
|
|
movedLink = os.path.join('Moved')
|
|
|
|
|
movedPath = os.path.join('Home',"Moved")
|
|
|
|
|
filesAndDir = filter(lambda x: not ('.' in x[0] or x in\
|
|
|
|
|
['Disks','Home','Moved','FTP']), os.listdir('.'))
|
|
|
|
|
filesDir = []
|
|
|
|
|
for fd in filesAndDir:
|
|
|
|
|
if os.path.islink(fd):
|
|
|
|
|
os.unlink(fd)
|
|
|
|
|
else:
|
|
|
|
|
filesDir.append(fd)
|
|
|
|
|
if not filesDir or not os.path.exists("Home"):
|
|
|
|
|
# Удаляем пустую папку Moved
|
|
|
|
|
if os.path.exists(movedPath) and not os.listdir(movedPath):
|
|
|
|
|
os.rmdir(movedPath)
|
|
|
|
|
# Удалям ссылку на Moved в домашней директории
|
|
|
|
|
if os.path.islink(movedLink) and not os.path.exists(movedPath):
|
|
|
|
|
os.unlink(movedLink)
|
|
|
|
|
return True
|
|
|
|
|
if not os.path.exists(movedPath):
|
|
|
|
|
os.mkdir(movedPath)
|
|
|
|
|
directFile = os.path.join(movedPath,".directory")
|
|
|
|
|
if not os.path.exists(directFile):
|
|
|
|
|
txt = "[Desktop Entry]\nIcon=folder-development"
|
|
|
|
|
fd = os.open(directFile, os.O_CREAT)
|
|
|
|
|
os.close(fd)
|
|
|
|
|
FD = open (directFile, "r+")
|
|
|
|
|
FD.write(txt)
|
|
|
|
|
FD.close()
|
|
|
|
|
if not os.path.exists(movedLink):
|
|
|
|
|
os.symlink(movedPath, movedLink)
|
|
|
|
|
for fd in filesDir:
|
|
|
|
|
execStr = "cp -r '%s' '%s'" %(fd, movedPath)
|
|
|
|
|
textLine = self.execProg(execStr)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not exec ") + " " + str(execStr) +\
|
|
|
|
|
" ...")
|
|
|
|
|
return False
|
|
|
|
|
execStr = "rm -rf '%s'" %fd
|
|
|
|
|
textLine = self.execProg(execStr)
|
|
|
|
|
if not (textLine == None):
|
|
|
|
|
self.printERROR(_("Can not exec ") + " " + str(execStr) +\
|
|
|
|
|
" ...")
|
|
|
|
|
return False
|
|
|
|
|
os.chdir(pathProg)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def moveHomeDir(self, userHome):
|
|
|
|
|
"""Переносим файлы пользователя в директорию Home/Moved если в домене"""
|
|
|
|
|
if self.isDomain():
|
|
|
|
|
return self.copyFilesToMovie(userHome)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def createUserFile(self, fileName, fileTxt, uid, gid, mode=0644):
|
|
|
|
|
"""Создает пользовательский файл с содержимым
|
|
|
|
|
|
|
|
|
|
Если директория файла не существует то ошибка
|
|
|
|
|
"""
|
|
|
|
|
userDir = os.path.split(fileName)[0]
|
|
|
|
|
if not os.path.exists(userDir):
|
|
|
|
|
self.printERROR(_("Path %s not exists") %userDir)
|
|
|
|
|
return False
|
|
|
|
|
fd = os.open(fileName, os.O_CREAT)
|
|
|
|
|
os.close(fd)
|
|
|
|
|
os.chmod(fileName, mode)
|
|
|
|
|
os.chown(fileName,uid,gid)
|
|
|
|
|
FD = open(fileName, "r+")
|
|
|
|
|
FD.write(fileTxt)
|
|
|
|
|
FD.close()
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def syncUser(self, userName, userHome, sync, uid, gid, progress=False,\
|
|
|
|
|
host="default"):
|
|
|
|
|
"""Синхронизация пользовательских настроек"""
|
|
|
|
|
home = os.path.split(userHome)[0]
|
|
|
|
|
homeProfile = os.path.join(home,"." + userName)
|
|
|
|
|
flagError = False
|
|
|
|
|
execStr = ""
|
|
|
|
|
if sync == "login":
|
|
|
|
|
# исключаемые пути при синхронизации
|
|
|
|
|
# /.local/share/akonadi/db_data
|
|
|
|
|
# хранит базу acanadi
|
|
|
|
|
# /.mozilla/firefox/calculate.default/urlclassifier3.sqlite
|
|
|
|
|
# хранит БД для firefox
|
|
|
|
|
# /.local/share/mime/mime.cache
|
|
|
|
|
# отключение ошибочного кэширования изображений
|
|
|
|
|
# /.kde4/share/apps/nepomuk/repository/main/data
|
|
|
|
|
# база nepomuk
|
|
|
|
|
# /.VirtualBox
|
|
|
|
|
# содержит данные о виртуальных машинах
|
|
|
|
|
if os.path.exists(userHome) and\
|
|
|
|
|
os.path.exists(homeProfile):
|
|
|
|
|
execStr = '/usr/bin/rsync --delete-excluded --delete \
|
|
|
|
|
--exclude="/.googleearth" --exclude="/.kde4/share/config/phonondevicesrc" \
|
|
|
|
|
--exclude="*~" --exclude="/Home" --exclude="/Disks" --exclude="/FTP" \
|
|
|
|
|
--exclude="/.local/share/akonadi/db_data" --exclude="/.VirtualBox" \
|
|
|
|
|
--exclude="/.mozilla/firefox/calculate.default/urlclassifier3.sqlite" \
|
|
|
|
|
--exclude="/.local/share/mime/mime.cache" \
|
|
|
|
|
--exclude="/.kde4/share/apps/nepomuk/repository/main/data" \
|
|
|
|
|
--filter="P /.googleearth" --filter="P /Home" --filter="P /Disks" \
|
|
|
|
|
--filter="P /.local/share/akonadi/db_data" --filter="P /.VirtualBox" \
|
|
|
|
|
--filter="P /.mozilla/firefox/calculate.default/urlclassifier3.sqlite" \
|
|
|
|
|
--filter="P /.local/share/mime/mime.cache" \
|
|
|
|
|
--filter="P /.kde4/share/apps/nepomuk/repository/main/data" \
|
|
|
|
|
--filter="P /FTP" -a -x -v -v -v -v %s/ %s/' %(homeProfile,userHome)
|
|
|
|
|
elif sync == "logout":
|
|
|
|
|
if os.path.exists(userHome) and os.listdir(userHome) and\
|
|
|
|
|
os.path.exists(homeProfile):
|
|
|
|
|
execStr = '/usr/bin/rsync --delete-excluded --delete \
|
|
|
|
|
--exclude="/.googleearth" --exclude="/Home" --exclude="/Disks" --exclude="/FTP"\
|
|
|
|
|
--exclude="*~" --exclude="/.kde4/cache-*" --exclude="/.kde4/tmp-*" \
|
|
|
|
|
--exclude="/.local/share/akonadi/db_data" --exclude="/.VirtualBox" \
|
|
|
|
|
--exclude="/.mozilla/firefox/calculate.default/urlclassifier3.sqlite" \
|
|
|
|
|
--exclude="/.local/share/mime/mime.cache" \
|
|
|
|
|
--exclude="/.kde4/share/apps/nepomuk/repository/main/data" \
|
|
|
|
|
--exclude="/.kde4/socket-*" --exclude="/.kde4/share/config/phonondevicesrc"\
|
|
|
|
|
-a -x -v -v -v -v %s/ %s/'%(userHome,homeProfile)
|
|
|
|
|
else:
|
|
|
|
|
self.printERROR(_("Method syncUser: option sync=%s incorrect")\
|
|
|
|
|
%str(sync))
|
|
|
|
|
return False
|
|
|
|
|
if execStr:
|
|
|
|
|
host = "<i>" + host +"</i>"
|
|
|
|
|
rsync = RsyncProgressBar(\
|
|
|
|
|
_("Receiving file list from %s server ...") % host,
|
|
|
|
|
_("Syncronizing user settings with %s server ...") %
|
|
|
|
|
host,execStr)
|
|
|
|
|
configFileName = os.path.join(homeProfile,self.configFile)
|
|
|
|
|
if sync == "login":
|
|
|
|
|
# получить переменную files из секции Rsync файла
|
|
|
|
|
# .calculate.ini
|
|
|
|
|
try:
|
|
|
|
|
numfiles = cl_base.iniParser( \
|
|
|
|
|
configFileName).getVar('rsync','files')
|
|
|
|
|
if numfiles == False:
|
|
|
|
|
if os.path.exists(configFileName):
|
|
|
|
|
os.remove(configFileName)
|
|
|
|
|
numfiles = 1
|
|
|
|
|
else:
|
|
|
|
|
numfiles = int(numfiles)
|
|
|
|
|
except:
|
|
|
|
|
numfiles = 1
|
|
|
|
|
rsync.maximum = numfiles
|
|
|
|
|
if progress:
|
|
|
|
|
rsync.run()
|
|
|
|
|
else:
|
|
|
|
|
rsync.runsilent()
|
|
|
|
|
if sync == "logout":
|
|
|
|
|
rsync.runsilent()
|
|
|
|
|
# получаем uid и gid пользователя
|
|
|
|
|
try:
|
|
|
|
|
if cl_base.iniParser(configFileName).setVar('rsync',{'files':\
|
|
|
|
|
rsync.getFilesNum()}):
|
|
|
|
|
os.chmod(configFileName, 0600)
|
|
|
|
|
os.chown(configFileName,uid,gid)
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
rsync.close()
|
|
|
|
|
if rsync.getExitCode() != 0:
|
|
|
|
|
self.printERROR(_("Can not rsync") + " " + str(sync) +\
|
|
|
|
|
" ...")
|
|
|
|
|
flagError = True
|
|
|
|
|
else:
|
|
|
|
|
if sync == "login":
|
|
|
|
|
if not (os.path.exists(userHome)):
|
|
|
|
|
self.printERROR(_("Directory %s not exists")%userHome)
|
|
|
|
|
else:
|
|
|
|
|
self.printERROR(_("Directory %s not exists")%homeProfile)
|
|
|
|
|
elif sync == "logout":
|
|
|
|
|
if not (os.path.exists(userHome)):
|
|
|
|
|
self.printERROR(_("Directory %s is empty or not exists")\
|
|
|
|
|
%userHome)
|
|
|
|
|
else:
|
|
|
|
|
self.printERROR(_("Directory %s not exists")%homeProfile)
|
|
|
|
|
flagError = True
|
|
|
|
|
if flagError:
|
|
|
|
|
return False
|
|
|
|
|
else:
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
class tsOpt(cl_base.opt):
|
|
|
|
|
"""Класс для обработки параметров и вывода help
|
|
|
|
|
|
|
|
|
|
Параметры:
|
|
|
|
|
helpObj объект-справка содержащий необходимые опции
|
|
|
|
|
notOptError выдавать ошибку при отсутствии опций командной строки
|
|
|
|
|
"""
|
|
|
|
|
def __init__(self, helpObj, notOptError=False):
|
|
|
|
|
# от cl_help получаем короткие и длинные опции
|
|
|
|
|
shortOpt,longOpt = helpObj.getAllOpt('all', helpObj.relOptions['h'])
|
|
|
|
|
# вызвать конструктор объекта, распознающего опции
|
|
|
|
|
cl_base.opt.__init__(self,shortOpt,longOpt)
|
|
|
|
|
self.nameParams = ['user']
|
|
|
|
|
self.sysArgv = sys.argv[1:]
|
|
|
|
|
self.helpObj = helpObj
|
|
|
|
|
self.__iter = 0
|
|
|
|
|
self.opt = {}
|
|
|
|
|
self.params = {}
|
|
|
|
|
self.getopt()
|
|
|
|
|
# Обработка help
|
|
|
|
|
self.flagHelp = False
|
|
|
|
|
# определяем есть ли среди опций опции, которые влияют на показ
|
|
|
|
|
# опциональных разделов (метод пересечения множеств)
|
|
|
|
|
helpopt = \
|
|
|
|
|
tuple(set(self.opt.keys()).intersection(helpObj.relOptions.keys()))
|
|
|
|
|
#Если есть опции help
|
|
|
|
|
if len(helpopt) > 0:
|
|
|
|
|
print helpObj.getHelp(helpObj.relOptions[helpopt[0]])
|
|
|
|
|
self.flagHelp = True
|
|
|
|
|
#Если нет хвостов
|
|
|
|
|
#elif not self.params:
|
|
|
|
|
#print helpObj.getHelp(helpObj.relOptions['h'])
|
|
|
|
|
#self.flagHelp = True
|
|
|
|
|
else:
|
|
|
|
|
if self.params.has_key('user'):
|
|
|
|
|
if len(self.nameParams) != self.__iter:
|
|
|
|
|
self.handlerErrOpt()
|
|
|
|
|
# В случае остсутствия опций командной строки и имени пользователя
|
|
|
|
|
if notOptError:
|
|
|
|
|
if not self.opt:
|
|
|
|
|
self.printErrorNotOpt()
|
|
|
|
|
self.flagHelp = True
|
|
|
|
|
elif not self.opt and not self.params.has_key('user'):
|
|
|
|
|
print helpObj.getHelp(helpObj.relOptions['h'])
|
|
|
|
|
self.flagHelp = True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def printErrorNotOpt(self):
|
|
|
|
|
"""Сообщение в случае отсутствия опций"""
|
|
|
|
|
print _("Options are absent.")
|
|
|
|
|
|
|
|
|
|
def handlerOpt(self,option,value):
|
|
|
|
|
# Обработчик (опция значение)
|
|
|
|
|
#print option, value
|
|
|
|
|
shortOpt = self.helpObj.getShortOpt(option)
|
|
|
|
|
if not shortOpt:
|
|
|
|
|
shortOpt = option
|
|
|
|
|
if not shortOpt in self.opt:
|
|
|
|
|
self.opt[shortOpt] = value
|
|
|
|
|
|
|
|
|
|
def handlerErrOpt(self):
|
|
|
|
|
# Обработчик ошибок
|
|
|
|
|
argv = " ".join(sys.argv[1:])
|
|
|
|
|
print _("Unrecognized option") + ' "' + argv + '"\n' + \
|
|
|
|
|
_("Try") + ' "' + sys.argv[0].split("/")[-1] + ' --help" ' +\
|
|
|
|
|
_("for more information.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def handlerParam(self,param):
|
|
|
|
|
# Обработчик хвостов (значение)
|
|
|
|
|
self.__iter += 1
|
|
|
|
|
if self.__iter<=len(self.nameParams):
|
|
|
|
|
self.params[self.nameParams[self.__iter-1]] = param
|
|
|
|
|
|