You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-3-unix/pym/cl_ldap_api.py

474 lines
19 KiB

#-*- coding: utf-8 -*-
# Copyright 2008-2010 Mir Calculate Ltd. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os, sys, re
#from cl_print import color_print
from cl_datavars import DataVars
from server.utils import execProg
from cl_template import template
from cl_api import packagesAPI, APIError
from server.ldap import iniLdapParser, ldapFunction, shareldap
from server.utils import genSleep
from cl_utils import removeDir, _error
from cl_lang import lang
tr = lang()
tr.setLocalDomain('cl_ldap')
tr.setLanguage(sys.modules[__name__])
__version__ = "2.2.0.0"
__app__ = "calculate-ldap"
from cl_abstract import abs_api_service
class DataVarsLdap(DataVars):
"""Хранение переменных"""
# Имя секции в calculate2.env
envSection = "ldap"
def importLdap(self, **args):
'''Импорт переменных для calculate-ldap'''
# Импорт переменных
self.importData(self.envSection, ('cl_vars_ldap','cl_fill_ldap'))
class Template:
"""Templates methods"""
def applyTemplates(self):
"""Apply templates"""
clTempl = template(self.clVars)
dirsFiles = clTempl.applyTemplates()
if clTempl.getError():
self.printERROR(clTempl.getError().strip())
return False
else:
return dirsFiles
class shareVars:
"""share methods template vars"""
# template variables
clVars = False
def createClVars(self, clVars=False):
"""Создает объект Vars"""
if not clVars:
clVars = DataVarsLdap()
# Импортируем переменные
clVars.importLdap()
# Заменяем значения переменных переменными из env файлов
clVars.flIniFile()
# Устанавливаем у объекта атрибут объект переменных
self.clVars = clVars
return self.clVars
class internalMethods(abs_api_service, shareVars, Template):
'''Methods ldap service'''
prioritet = 25
nameService = "ldap"
nameDaemon = 'slapd'
_templDict = {'name':nameDaemon}
# files
pidFile = '/var/run/openldap/%(name)s.pid' %_templDict
# command
cmdPath = '/etc/init.d/%(name)s' %_templDict
_templDict.update({'cmd':cmdPath})
cmdStart = '%(cmd)s start' %_templDict
cmdReStart = '%(cmd)s restart' %_templDict
cmdStop = '%(cmd)s stop' %_templDict
cmdShowDaemons = 'rc-update show default'
reShowDaemons = re.compile("(.+)\s+\|\s+.+")
cmdAddRunlevel = 'rc-update add %(name)s default' %_templDict
cmdDelRunlevel = 'rc-update del %(name)s default' %_templDict
def get_service_name(self):
'''Get name service'''
return self.nameService
def get_pkg_name(self):
'''Get name service'''
return __app__
def get_vars(self):
'''Get Service vars'''
return self.createClVars(self.clVars)
def is_setup(self):
'''Is setup service (True/False)'''
self.createClVars(self.clVars)
return self.clVars.Get('sr_ldap_set') == "on"
def _getRunlevelDaemons(self):
"""Получаем всех демонов в default уровне"""
textLines = execProg(self.cmdShowDaemons)
if textLines is False:
self.printERROR(_("ERROR") + ": " + self.cmdShowDaemons)
return False
else:
daemons = []
for line in textLines:
res = self.reShowDaemons.search(line)
if res:
daemon = res.groups(0)[0]
daemons.append(daemon)
return daemons
def is_start(self):
'''Run ldap server (True/False)'''
if os.access(self.pidFile, os.R_OK):
pid = open(self.pidFile).read().strip()
if pid:
procDir = "/proc"+"/"+pid
if os.access(procDir, os.F_OK):
return True
return False
def start(self):
'''Start LDAP server'''
if not self.is_start():
if execProg(self.cmdStart) is False:
self.printERROR(_("Can't execute '%s'") %self.cmdStart)
self.printNotOK(_("Starting LDAP") + " ...")
return False
return True
def restart(self):
'''Restart LDAP server'''
if self.is_start():
if execProg(self.cmdReStart) is False:
self.printERROR(_("Can't execute '%s'") %self.cmdReStart)
self.printNotOK(_("Restarting LDAP")+ " ...")
return False
else:
return self.start()
return True
def stop(self):
'''Stop LDAP server'''
if self.is_start():
if execProg(self.cmdStop) is False:
self.printERROR(_("Can't execute '%s'") %self.cmdStop)
self.printNotOK(_("Stopping LDAP")+ " ...")
return False
return True
def is_runlevel(self):
'''Находится ли LDAP в автозагрузке'''
daemons = self._getRunlevelDaemons()
if daemons is False:
return False
if self.nameDaemon in daemons:
return True
else:
return False
def add_runlevel(self):
'''Add daemon to runlevel'''
if not self.is_runlevel():
if execProg(self.cmdAddRunlevel) is False:
self.printERROR(_("Can't execute '%s'") %self.cmdAddRunlevel)
self.printNotOK(_("service %(name)s added to runlevel")\
%self._templDict + " ...")
return False
return True
def del_runlevel(self):
'''Delete daemon from runlevel'''
if self.is_runlevel():
if execProg(self.cmdDelRunlevel) is False:
self.printERROR(_("Can't execute '%s'") %self.cmdDelRunlevel)
self.printNotOK(_("service %(name)s removed from runlevel")\
%self._templDict + " ...")
return False
return True
def get_prioritet(self):
'''Get run daemon prioritet'''
return self.prioritet
def del_vars_from_env(self):
'''Delete template vars in env files'''
self.createClVars(self.clVars)
deleteVariables = ("sr_ldap_set",)
locations = map(lambda x: x[0], self.clVars.Get("cl_env_data"))
for varName in deleteVariables:
for locate in locations:
if not self.clVars.Delete(varName, location=locate,
header=self.clVars.envSection):
fileName = filter(lambda x: x[0] == locate,
self.clVars.Get("cl_env_data"))[0][1]
self.printERROR(_("Can't delete variable '%(name)s' "
"in file %(file)s") %{'name':varName,
'file':fileName})
return False
return True
def updateVars(self):
self.createClVars()
return True
def get_service_info(self, request):
'''Get service information'''
res = ""
if request == "scheme":
self.createClVars(self.clVars)
res = self.clVars.Get('ld_ldap_scheme_conf')
elif request == "access_pw":
self.createClVars(self.clVars)
res = self.clVars.Get('ld_ldap_access_pw_conf')
elif request == "access_dn":
self.createClVars(self.clVars)
res = self.clVars.Get('ld_ldap_access_dn_conf')
return res
def scheme(self):
'''include lines in slapd.conf'''
return self.get_service_info('scheme')
def access_pw(self):
'''Access userPasswod lines in slapd.conf'''
return self.get_service_info('access_pw')
def access_dn(self):
'''Access DN lines in slapd.conf'''
return self.get_service_info('access_dn')
def apply_templates(self):
'''Apply package templates'''
if self.is_setup():
self.clVars.Set("ac_ldap_update","up", force=True)
return Template.applyTemplates(self)
return True
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(
cls, *args, **kwargs)
return cls._instance
class allMethods(Singleton, internalMethods, shareldap):
"""Методы севисa Ldap"""
# Базовый ldif файл
ldifFileBase = '/usr/lib/calculate-2.2/calculate-ldap/ldif/base.ldif'
apiFile = '/usr/lib/calculate-2.2/calculate-ldap/pym/cl_ldap_api.py'
libAPIObj = packagesAPI()
def removeLdapDatabase(self):
"""Удаляем предыдущую базу данных"""
pathDatabase = "/var/lib/openldap-data"
#if os.path.exists(pathDatabase) and os.listdir(pathDatabase):
#if os.system("rm /var/lib/openldap-data/* &>/dev/null") !=0:
#self.printERROR("Can't remove /var/lib/openldap-data/*")
#return False
#return True
if os.path.exists(pathDatabase):
fileOrDirNames = os.listdir(pathDatabase)
if fileOrDirNames:
for fileOrDirName in fileOrDirNames:
fullFileOrDirName = os.path.join(pathDatabase,
fileOrDirName)
if os.path.isdir(fullFileOrDirName):
try:
removeDir(pathDatabase)
except:
self.printERROR(_("Can't remove directory %s")\
%fullFileOrDirName)
return False
else:
try:
os.remove(fullFileOrDirName)
except:
self.printERROR(_("Can't remove file %s")\
%fullFileOrDirName)
return False
self.printOK(_("Erased LDAP Database") + " ...")
return True
def connectLdapServer(self):
"""Соединяемся с LDAP сервером
используем DN и пароль временного админстратора
"""
# Если раннее была ошибка то выходим
if self.getError():
self.printERROR (_("ERROR") + ": " +\
self.getError().strip())
return False
tmpDn = self.clVars.Get("ld_temp_dn")
tmpPw = self.clVars.Get("ld_temp_pw")
ldapObj = ldapFunction(tmpDn, tmpPw)
# Генератор задержек
wait = genSleep()
while ldapObj.getError():
try:
# Задержка
wait.next()
except StopIteration:
break
# Очистка ошибки
_error.error = []
ldapObj = ldapFunction(tmpDn, tmpPw)
self.ldapObj = ldapObj
self.conLdap = ldapObj.conLdap
if ldapObj.getError():
# Удаляем одинаковые ошибки
listError = []
for e in ldapObj.error:
if not e in listError:
listError.append(e)
_error.error = listError
self.printERROR(_("Can not connected to LDAP server"))
return False
return True
def setup(self, force=False):
"""Настройка LDAP сервиса (создание дерева)"""
# Принудительная установка
if self.clVars.Get("sr_ldap_set") == "on" and not force:
self.printWARNING (_("WARNING") + ": " +\
_("LDAP server is configured")+ ".")
return True
if not force:
# предупреждение при выполнении этой программы будут изменены
# конфигурационные файлы и база данных сервиса LDAP а также
# конфигурационные файлы установленных сервисов
self.printWARNING (_("WARNING") + ": " +\
_("Executing of the program will change") + " " +\
_("the configuration files and database of LDAP service")+\
".")
# если вы готовы продолжить работу программы нажмите Y если нет n
messDialog = \
_("If you are ready to continue executing the program")+", "+\
_("input 'yes'") +", "+ _("if not 'no'")
if not dialogYesNo(messDialog):
return True
else:
# делаем backup
# Проверим запущен ли ldap
if not self.is_start():
# Запускаем LDAP сервер
if not self.start():
return False
#if not self.backupServer():
#return False
if self.is_runlevel():
# Удаляем из автозапуска демона
if not self.del_runlevel():
return False
listAPIObj = self.libAPIObj.all.APIList()
listAPIObjReverse = self.libAPIObj.all.APIListReverse()
if filter(lambda x:\
x.api.get_pkg_name()=="calculate_ldap",listAPIObj):
self.printERROR(_("Can not found API module in package "
"calculate-ldap"))
self.printWARNING(_("Run: cl-ldap-setup --install"))
return False
# Останавливаем все установленные сервисы
for obj in listAPIObjReverse:
apiObj = obj.api
if hasattr(apiObj, 'stop') and not apiObj.stop():
return False
# Удаляем из автозагрузки все установленные сервисы
for obj in listAPIObjReverse:
apiObj = obj.api
if hasattr(apiObj, 'del_runlevel') and not apiObj.del_runlevel():
return False
# Удаляем из крона скрипт для чистки удаленых пользователей
# создаем объект репликации
#objRepl = servRepl()
#if not objRepl.cronReplicationOFF():
#return False
# Удаляем из share файл .replrun
#if not self.servSambaObj.delReplFile(self.clVars):
#return False
# Удаляем переменные
for obj in listAPIObjReverse:
apiObj = obj.api
if hasattr(apiObj,'del_vars_from_env') and \
not apiObj.del_vars_from_env():
return False
# Получим путь к ldap файлу
ldapParser = iniLdapParser()
ldapFile = ldapParser.nameIniFile
# Удаляем ldap файл
if os.path.exists(ldapFile):
os.remove(ldapFile)
self.clVars.Write("sr_ldap_set", "off",force=True)
self.clVars.Set("sr_ldap_set", "on", force=True)
self.clVars.Set("ac_ldap_setup","up", force=True)
# Первый проход
self.clVars.Set("cl_pass_step", "1", True)
if self.applyTemplates() is False:
self.printERROR(_("Can not apply templates") + ":" + " " +\
_("first pass"))
return False
# Удаляем старую базу данных
if not self.removeLdapDatabase():
return False
# Запускаем LDAP сервер
if not self.start():
return False
# Соединяемся с LDAP временным пользователем
if not self.connectLdapServer():
return False
# Получаем текст нужного ldif-a
baseLdif = self.createLdif(self.ldifFileBase)
# Если нет ошибок при соединении применяем ldif
if not self.ldapObj.getError():
self.ldapObj.ldapAdd(baseLdif)
if self.ldapObj.getError():
print _("LDAP Error") + ": " + self.ldapObj.getError().strip()
return False
self.printOK(_("Added ldif file") + " ...")
# Второй проход,
# удаляем временного пользователя root из конфигурационного файла
self.clVars.Set("cl_pass_step","2",True)
if self.applyTemplates() is False:
self.printERROR(_("Can not apply profiles") +":"+ _("second pass"))
return False
# Перезапускаем LDAP сервер
if not self.restart():
return False
# Записываем данные администратора сервера
ldapParser.setVar("admin",
{"DN":self.clVars.Get("ld_admin_dn"),
"PASS":self.clVars.Get("ld_admin_pw")})
# Устанавливаем автозапуск демона
if not self.add_runlevel():
return False
# Записываем переменные для пользователя
#clientVars = ["ur_organization", "ur_signature"]
#if not self.saveVarsClient(clientVars):
#return False
#self.apply_templates()
self.clVars.Write("sr_ldap_set","on",force=True)
self.printOK(_("LDAP service configured") + " ...")
return True
REGISTERED_METHODS = ['access_pw', 'access_pw', 'add_runlevel',
'apply_templates', 'get_pkg_name', 'get_prioritet', 'get_service_info',
'get_service_name', 'get_vars', 'is_runlevel', 'is_setup', 'is_start',
'restart', 'scheme', 'setup', 'start', 'stop']
class serviceAPI(object):
"""Proxy object"""
def __init__(self):
self.__subject = allMethods()
for attr in dir(self.__subject):
if attr in REGISTERED_METHODS:
object.__setattr__(self, attr, getattr(self.__subject, attr))