#-*- coding: utf-8 -*- # Copyright 2008-2010 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 import sys import types import time from cl_print import color_print from cl_template import template from server.utils import execProg # Перевод модуля import cl_lang tr = cl_lang.lang() tr.setLocalDomain('cl_lib') tr.setLanguage(sys.modules[__name__]) class services(color_print): """Общие методы для серверных программ, Методы для работы с сервисами""" # Переменная объект Vars clVars = False # Сервисы и демоны servicesDaemons = {"ldap":["slapd"], "unix":["slapd"], "samba":["samba"], "mail":["postfix","dovecot"], "mail_relay":["postfix"], "jabber":["ejabberd"], "ftp":["proftpd"], "proxy":["squid"], "dns":["named"], "dhcp":["dhcpd"]} def getServiceSetup(self): """находит установленные сервисы Выдаем список [установленные сервисы] """ # инсталированнные сервисы servInstalled = [] # доступные сервисы services = ('ldap', 'unix', 'samba', 'mail', 'jabber', 'ftp', 'proxy', 'dns', 'dhcp') for serv in services: if self.clVars.Get("sr_%s_set"%serv) == "on": servInstalled.append(serv) return servInstalled def _getDefaultRunlevelDaemons(self): """Получаем всех демонов в default уровне""" execStr = "rc-update show" textLine = execProg(execStr, None, False) if textLine == False: self.printERROR(_("ERROR") + ": " + execStr) return False else: splLines = filter(lambda x: len(x)==2 and "default" in x[1],\ map(lambda x: x.split("|"),textLine)) splLines = map(lambda x: x[0].strip(), splLines) return splLines def setDaemonAutostart(self, daemon): """Прописывает демона в автозагрузку""" if daemon in self._getDefaultRunlevelDaemons(): return True execStr = "rc-update add %s default" %daemon textLine = execProg(execStr) if textLine == False: self.printERROR(_("ERROR") + ": " + execStr) self.printERROR(_("Can not add '%s' at default runlevel")%daemon) return False else: return True def delDaemonAutostart(self, daemon): """Удаляет демона из автозагрузки""" if not (daemon in self._getDefaultRunlevelDaemons()): return True self._getDefaultRunlevelDaemons() execStr = "rc-update del %s default" %daemon textLine = execProg(execStr) if textLine == False: self.printERROR(_("ERROR") + ": " + execStr) self.printERROR(_("Can not deleted '%s' from default runlevel")\ %daemon) return False else: return True def runLdapServer(self): """Запускает LDAP сервер""" textLines = execProg("/etc/init.d/slapd start") if textLines == False: self.printNotOK(_("Starting LDAP")+ " ...") return False else: return True def restartLdapServer(self): """Запускает LDAP сервер""" textLines = execProg("/etc/init.d/slapd restart") if textLines == False: self.printNotOK(_("Restarting LDAP")+ " ...") return False else: return True def stopLdapServer(self): """Останавливает LDAP сервер""" textLines = execProg("/etc/init.d/slapd stop") if textLines == False: self.printNotOK(_("Stopping LDAP")+ " ...") return False else: return True def getALLServices(self): """Получаем все сервисы которые описаны в шаблонах""" # путь к директории шаблонов templatePath = self.clVars.Get("cl_template_path")[0] data = os.listdir(templatePath) service = [] for fileData in data: if os.path.isdir(os.path.join(templatePath, fileData)): service.append(fileData) if service: # После добавления сервисов в класс необходимо удалить # apache и backup if 'backup' in service: service.remove('backup') if 'apache' in service: service.remove('apache') return service def getTemplatePath(self, nameService): """список накладываемых профилей в зависимости от сервиса""" profpath = [] profPaths = ['/usr/lib/calculate/calculate-server/profile/%s'\ %nameService, '/var/calculate/remote/server-profile/%s'%nameService, '/var/calculate/server-profile/%s'%nameService] for profPath in profPaths: if os.path.exists(profPath): profpath.append(profPath) return profpath def applyTemplatesFromService(self, service, verbose=False): """Применяем шаблоны для данного сервиса""" # Пути к шаблонам для сервиса profPaths = self.getTemplatePath(service) # Устанавливаем пути к шаблонам для сервиса self.clVars.Set("cl_template_path", profPaths, True) clTempl = template(self.clVars) # Объединяем шаблоны data = clTempl.applyTemplates() if clTempl.getError(): self.printERROR(clTempl.getError()) return False else: if verbose and type(data) == types.TupleType: dirs, files = data return files return True def delServicesAutostart(self, servInstalled): """Удаляет из автозагрузки сервисы Входные данные - список названий сервисов """ flagError = False delDaemons = [] for service in servInstalled: if not service in self.servicesDaemons.keys(): self.printERROR(_("Not supported service '%s'")%service) self.printERROR(\ _("Can not deleted service from default runlevel")) flagError = True break for daemon in self.servicesDaemons[service]: if not daemon in delDaemons: delDaemons.append(daemon) if not self.delDaemonAutostart(daemon): flagError = True break if flagError: break if flagError: return False else: return True def startDaemons(self, service, daemons, printSuccess=True): """Стартует демонов""" flagError = False for daemon in daemons: if not self.getRunDaemons([daemon]): textLines = execProg("/etc/init.d/%s start" %(daemon)) if textLines == False: self.printERROR( _("Daemon %s was not started") %daemon) flagError = True break prnService = self.printNameService(service) if flagError: self.printNotOK(_("Starting") + " " + prnService + " " +\ _("service") + " ...") return False else: if printSuccess: self.printOK(_("Starting") + " " + prnService + " "+\ _("service") + " ...") return True def startServices(self, servInstalled, printSuccess=True): """Запускает все сервисы поданные на вход этому методу Также прописывает в автозагрузку Входные даннные - список названий сервисов """ addDaemons = [] if 'ldap' in servInstalled or 'unix' in servInstalled: if not self.startDaemons('ldap',['slapd'], printSuccess): return False # Устанавливаем автозапуск демона if not self.setDaemonAutostart("slapd"): return False addDaemons.append("slapd") flagError = False for service in servInstalled: if not service in self.servicesDaemons.keys(): self.printERROR(_("Can not supported service '%s'")%service) self.printERROR(_("Can not add service at default runlevel")) flagError = True break for daemon in self.servicesDaemons[service]: if not daemon in addDaemons: addDaemons.append(daemon) if not self.startDaemons(service, [daemon], printSuccess): flagError = True break if not self.setDaemonAutostart(daemon): flagError = True break if flagError: break if flagError: return False else: return True def stopServices(self, servInstalled): """Останавливает все сервисы поданные на вход этому методу Входные даннные - список названий сервисов """ addDaemons = [] if 'ldap' in servInstalled or 'unix' in servInstalled: addDaemons.append("slapd") flagError = False for service in servInstalled: if not service in self.servicesDaemons.keys(): self.printERROR(_("Can not supported service '%s'")%service) self.printERROR(_("Can not stop service")) flagError = True break # Название сервиса для вывода на экран servicePrn = self.printNameService(service) for daemon in self.servicesDaemons[service]: if not daemon in addDaemons: addDaemons.append(daemon) # Если демон запущен и не squid то останавливаем его if not daemon in ["squid"] and self.getRunDaemons([daemon]): ret = execProg("/etc/init.d/%s stop"%daemon) if ret == False: self.printERROR(servicePrn + " " +\ _("service is not stopped")) flagError = True break # Удаляем процессы ejabberd if daemon == "ejabberd": strCmd = "ps ax" listProcess = execProg(strCmd,False,False) if listProcess == False: self.printERROR(_('Can not execute "%s"')%strCmd) return False killPid = [] for process in listProcess: if "erlang" in process: killPid.append(process.split(" ")[0]) if killPid and " ".join(killPid).strip(): textLine=execProg("kill %s" %" ".join(killPid)) if textLine == False: self.printERROR(_("Can not 'kill %s'")\ %" ".join(killPid)) flagError = True break elif daemon == "squid" and self.getRunDaemons(["squid"]): errStopProxy = False # Создаем 2 процесса pid = os.fork() tic = 0 if pid: message = _("Waiting for squid to shutdown") + " " self.printSUCCESS(message, 0, False) perm = [0] offset = 0 while not perm[0]: perm = os.waitpid(pid, os.WNOHANG) if perm[1]: errStopProxy = True break time.sleep(0.1) tic += 1 if tic>=15: sys.stdout.flush() sys.stdout.write(".") offset += 1 tic = 0 if errStopProxy: self.printOnlyNotOK(" ",\ self.lenString(message)+\ offset+3) else: self.printOnlyOK(" ",self.lenString(message)+\ offset+3) else: sys.stdout.flush() if os.system("/etc/init.d/squid stop &>/dev/null"): sys.exit(1) else: sys.exit(0) # Если ошибка при остановке proxy сервера if errStopProxy: self.printERROR(servicePrn + " " +\ _("service is not stopped")) flagError = True break if flagError: break if not flagError and "slapd" in addDaemons: if self.getRunService('ldap'): textLines = execProg("/etc/init.d/slapd stop") if textLines == False: self.printERROR("LDAP" + " " +\ _("service is not stopped")) flagError = True if flagError: return False else: return True def getRunDaemons(self, daemons, printError=False): """Проверка, запущены ли демоны""" baseDir = "/var/run" runDaemons = {} flagBaselayoutDir = False for daemon in daemons: # Проверка на запуск демона postfix if daemon == 'postfix': flagRun = False strCmd = "ps ax" listProcess = execProg(strCmd, False, False) if not listProcess: self.printERROR(_('Can not execute "%s"')%strCmd) return False for process in listProcess: if "postfix/master" in process: flagRun = True break if flagRun: runDaemons['postfix'] = True else: runDaemons['postfix'] = False continue addDirDict = {"slapd":("openldap","slapd.pid"), "dovecot":("dovecot","master.pid"), "proftpd":("","proftpd.pid"), "squid":("","squid.pid")} baselayoutDir = "/var/lib/init.d/daemons" if not flagBaselayoutDir: if os.path.exists(baselayoutDir): flagBaselayoutDir = True if flagBaselayoutDir: addDirDict["ejabberd"] = (baselayoutDir,"ejabberd") addDirDict["samba"] = (baselayoutDir,"samba") addDirDict["named"] = (baselayoutDir,"named") addDirDict["dhcpd"] = (baselayoutDir,"dhcpd") elif daemon in ["ejabberd", "samba", "named", "dhcpd"]: if not os.system("/lib/rc/bin/service_started %s" %daemon): runDaemons[daemon] = True else: runDaemons[daemon] = False continue if addDirDict[daemon][0][:1] == "/": pidDir = addDirDict[daemon][0] else: pidDir = os.path.join(baseDir,addDirDict[daemon][0]) if os.access(pidDir, os.F_OK) and os.listdir(pidDir) and\ os.path.exists(os.path.join(pidDir,addDirDict[daemon][1])): runDaemons[daemon] = True else: runDaemons[daemon] = False if printError: for daemon in daemons: if not runDaemons[daemon]: self.printERROR(_("Daemon %s is not started") %daemon) if False in runDaemons.values(): return False else: return True def getRunService(self, nameService, printError=False): """Проверка, запущен ли сервис с данным именем""" flagError = False if not nameService in self.servicesDaemons.keys(): self.printERROR(_("Can not supported service '%s'")%nameService) self.printERROR(_("Can not check run service")) return False # Названия демонов для сервиса daemons = self.servicesDaemons[nameService] if not self.getRunDaemons(daemons, printError): flagError = True if flagError: if printError: self.printERROR(self.printNameService(nameService) + " " +\ _("service is not started")) return False return True def isServiceSetup(self, service, printError=True): """Проверяет установлен ли сервис""" if not self.clVars: # Cоздаем объект переменные self.createClVars() if self.clVars.Get("sr_%s_set"%service) == "on": return True if printError: self.printERROR(_("Service %s is not installed")%service) return False def initialChecks(self, service, printError=True): """Начальная проверка перед запуском методов сервиса""" # Создаем объект переменных self.createClVars() if self.clVars.Get("sr_mail_relay_set") == "on": if printError: self.printERROR(_("This server is a mail relay. \ This command is not allowed.")) return False if not self.isServiceSetup(service, printError): return False return True def initialChecksSetup(self): # Создаем объект переменных self.createClVars() """Начальная проверка перед запуском метода setup""" if self.clVars.Get("sr_mail_relay_set") == "on": self.printERROR(_("This server is a mail relay. \ This command is not allowed.")) return False return True