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-2.2-lib/pym/update_config/cl_update_config.py

349 lines
16 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#-*- coding: utf-8 -*-
# Copyright 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.
__version__ = "2.2.0.0"
__app__ = "calculate-lib"
import sys, os, stat, re
from cl_log import log
import cl_datavars
import cl_template
from cl_print import color_print as old_color_print
from cl_utils import runOsCommand
import cl_overriding
import cl_lang
# Перевод модуля
tr = cl_lang.lang()
tr.setLocalDomain('cl_lib')
tr.setLanguage(sys.modules[__name__])
cl_overriding.printERROR = lambda x:filter(lambda y:color_print().printERROR(y),
str(x).splitlines())
packagePath = "/usr/lib/calculate-2.2"
for path in os.listdir(packagePath):
realPath = os.path.join(packagePath,path)
if os.path.isdir(realPath):
pymPath = os.path.join(realPath,"pym")
if len(filter(lambda x:x.startswith("cl_vars_") and\
x.endswith(".py") or x.startswith("cl_fill_") and\
x.endswith(".py"), os.listdir(pymPath)))==2:
sys.path.insert(0, os.path.abspath(pymPath))
class writeLog:
"""Класс логгирования"""
logger = log("apply-templates",
filename="/var/log/calculate/update_config.log",
formatter="%(asctime)s - %(levelname)s - %(message)s")
class color_print(old_color_print, writeLog):
"""Класс для переопределения печати сообщений"""
_printObj = old_color_print()
def printERROR(self, *arg, **argv):
"""Вывод на печать ошибки"""
# Запись в log ошибки
self.logger.error(arg[0])
self._printObj.printERROR(*arg, **argv)
def printSUCCESS(self, *arg, **argv):
"""Вывод на печать в случае успеха без [ok] справа"""
# Запись в log информации
self.logger.info(arg[0])
self._printObj.printSUCCESS(*arg, **argv)
def printWARNING(self, *arg, **argv):
"""Вывод на печать предупреждения"""
# Запись в log предупреждения
self.logger.warn(arg[0])
self._printObj.printWARNING(*arg, **argv)
def printOK(self, *arg, **argv):
"""Вывод на печать в случае успеха с [ok] справа"""
# Запись в log информации
self.logger.info(arg[0])
self._printObj.printOK(*arg, **argv)
def printNotOK(self, *arg, **argv):
"""Вывод на печать в случае сбоя"""
# Запись в log предупреждения
self.logger.error(arg[0])
self._printObj.printNotOK(*arg, **argv)
class DataVarsObject(cl_datavars.DataVars):
"""Класс переменных для десктопа"""
def __init__(self, section):
cl_datavars.DataVars.__init__(self)
self.section=section
def importDataObject(self, **args):
'''Заполнить конфигурацию переменных, для десктопа'''
# Имя секции в calculate.env
#envSection = "calculate-desktop"
# заполнить переменные окружения алгоритмом по умолнанию
self.importData(self.section, ('cl_vars_%s' %self.section,
'cl_fill_%s' %self.section))
self.flIniFile()
class shareUpdateConfigs(color_print, writeLog):
"""Общие методы для обновления конфигурационных файлов"""
patternBelongDir = re.compile("belong\(\)")
patternBelongName = re.compile("belong\(([^\(\)]+)\)")
patternSect = re.compile("^\s*\[([^\[\]]+)\]\s*")
templatePaths = ['/usr/share/calculate/templates',
'/var/calculate/templates',
'/var/calculate/remote/templates']
firstEnvFile = "/etc/calculate/calculate2.env"
reCleanVer = re.compile("\d+\.?\d*\.?\d*")
def _isApplyTemplateDir(self, scanDir, nameProgram, flagSkipDesktop=True,
flagDir=False):
"""Есть ли шаблоны в директории scanDir для пакета nameProgram
выдает True, False
"""
ret = False
if flagDir or stat.S_ISDIR(os.stat(scanDir)[stat.ST_MODE]):
for fileOrDir in sorted(os.listdir(scanDir)):
absPath = os.path.join(scanDir,fileOrDir)
statInfo = os.stat(absPath)[stat.ST_MODE]
if stat.S_ISREG(statInfo):
textFile = open(absPath).read()
if flagSkipDesktop and\
"cl_pass_action==desktop" in textFile:
break
if self.patternBelongDir.search(textFile):
ret = os.path.basename(os.path.dirname(absPath))
if ret == nameProgram:
ret = True
break
else:
ret = False
else:
searchObj = self.patternBelongName.search(textFile)
if searchObj:
ret = searchObj.group(1)
if ret == nameProgram:
ret = True
break
else:
ret = False
elif stat.S_ISDIR(statInfo):
ret = self._isApplyTemplateDir(absPath, nameProgram, True,
flagSkipDesktop)
if ret:
break
return ret
class updateUserConfigs(shareUpdateConfigs):
"""Обновление пользовательских конфигурационных файлов"""
def getXUsers(self):
"""Имена пользователей в X сессии"""
xSession = 0
foundTwoSession = False
retCode, resWho = runOsCommand("who")
xUsers = []
if retCode==0:
if resWho and type(resWho) == list:
xUsers = map(lambda x: x[0],
filter(lambda x: x[1].startswith(":"),
map(lambda x: filter(lambda y: y,
x.split(" "))[:2] ,resWho)))
else:
self.printERROR(_("Can not execute 'who'"))
return False
return xUsers
def _getUserTemplateDirs(self, scanDir, userTemplDirs=[], flagDir=False):
"""Находит в директории scanDir директории шаблонов для пользователя
выдает найденные директории.
"""
if flagDir or stat.S_ISDIR(os.stat(scanDir)[stat.ST_MODE]):
for fileOrDir in sorted(os.listdir(scanDir)):
absPath = os.path.join(scanDir,fileOrDir)
statInfo = os.stat(absPath)[stat.ST_MODE]
if stat.S_ISREG(statInfo):
textFile = open(absPath).read()
if "cl_pass_action==desktop" in textFile:
userTemplDirs.append(scanDir)
break
elif stat.S_ISDIR(statInfo):
self._getUserTemplateDirs(absPath, userTemplDirs, True)
return userTemplDirs
def updateConfig(self, nameProgram, category, version, xUsers):
"""Обновление конфигурационных файлов у пользователей"""
cleanVer = self.reCleanVer.search(version)
if cleanVer:
version = cleanVer.group()
self.logger.info(_("Package %s") %nameProgram)
self.logger.info(_("Update desktop configuration files"))
if not os.path.exists(self.firstEnvFile):
self.printWARNING(_("File '%s' does not exist")%self.firstEnvFile)
return True
if not os.access(self.firstEnvFile, os.R_OK):
self.printWARNING(_("Permission denied: '%s'")%self.firstEnvFile)
return True
sectionsWork = []
for line in open(self.firstEnvFile).readlines():
sRet = self.patternSect.search(line)
if sRet:
sectionsWork.append(sRet.group(1))
sectName = "desktop"
dictPakkages = {}
# Если установлен calculate-desktop
if sectName in sectionsWork:
section = ""
for templatePath in self.templatePaths:
fullPath = os.path.join(templatePath,sectName)
if os.path.isdir(fullPath):
for foundUserPath in self._getUserTemplateDirs(fullPath):
if self._isApplyTemplateDir(foundUserPath, nameProgram,
flagSkipDesktop=False):
section = sectName
break
if section:
# Добавление условия, что программа category/nameProgram
# установлена
cl_template.templateFunction.installProg.update(\
{"%s/%s"%(category,nameProgram):[version],
"%s"%(nameProgram):[version]})
for userName in xUsers:
clVars = DataVarsObject(section)
clVars.importDataObject()
clVars.Set("ur_login", userName, True)
clVars.Set("cl_pass_action", section, True)
clVars.Set("cl_belong_pkg", nameProgram, True)
clTempl = cl_template.template(clVars)
dirsFiles = clTempl.applyTemplates()
if dirsFiles is False:
self.printERROR(\
_("Error using templates for the user %s")%userName)
for errMess in clTempl.getError().splitlines():
self.printERROR(errMess)
return False
if dirsFiles and dirsFiles[1]:
nameAndVerPkg = clVars.Get("cl_name")+"-"+\
clVars.Get("cl_ver")
if not nameAndVerPkg in dictPakkages:
dictPakkages[nameAndVerPkg] = []
dictPakkages[nameAndVerPkg].append((userName,
sorted(list(set(dirsFiles[1])))))
if dictPakkages:
for calcPkg in dictPakkages:
self.printWARNING(_("Package %s has changed files")\
%calcPkg+":")
for userName, configFiles in dictPakkages[calcPkg]:
self.printWARNING(" "*2 + _("User %s")%userName + ":")
for nameConfigFile in configFiles:
self.printWARNING(" "*5 + nameConfigFile)
if not dictPakkages:
self.logger.warn(_("Not found templates"))
return True
class updateSystemConfigs(shareUpdateConfigs):
"""Обновление системных конфигурационных файлов"""
def isExistsProtectFiles(self, configPath):
"""Есть ли в защищенных директориях конфигурационные файлы"""
if not "CONFIG_PROTECT" in os.environ:
self.printERROR(_("Missing environment variable CONFIG_PROTECT"))
exit(1)
protectPaths = ["/etc"] + map(lambda x: x.strip(),
os.environ["CONFIG_PROTECT"].split(" "))
flagFoundProtect = False
for pPath in protectPaths:
fPath = os.path.join(configPath, pPath[1:])
if os.path.exists(fPath) and os.listdir(fPath):
flagFoundProtect = True
break
if not flagFoundProtect:
return False
return True
def updateConfig(self, nameProgram, category, version, configPath):
"""Обновление системных конфигурационных файлов"""
cleanVer = self.reCleanVer.search(version)
if cleanVer:
version = cleanVer.group()
self.logger.info(_("Package %s") %nameProgram)
self.logger.info(_("Update system cofiguration files"))
if not os.path.exists(configPath):
self.printERROR(_("Path '%s' does not exist")%configPath)
return False
if not os.path.exists(self.firstEnvFile):
self.printWARNING(_("File '%s' does not exist")%self.firstEnvFile)
return True
if not os.access(self.firstEnvFile, os.R_OK):
self.printWARNING(_("Permission denied: '%s'")%self.firstEnvFile)
return True
sections = []
sectionsWork = []
for line in open(self.firstEnvFile).readlines():
sRet = self.patternSect.search(line)
if sRet:
sectionsWork.append(sRet.group(1))
#sectionsWork = os.listdir(self.templatePaths[0])
for sectName in sectionsWork:
for templatePath in self.templatePaths:
fullPath = os.path.join(templatePath,sectName)
if not sectName in sections and os.path.isdir(fullPath):
if self._isApplyTemplateDir(fullPath, nameProgram):
sections.append(sectName)
dictPakkages = {}
if sections:
# Добавление условия, что программа category/nameProgram установлена
cl_template.templateFunction.installProg.update(\
{"%s/%s"%(category,nameProgram):[version],
"%s"%(nameProgram):[version]})
for sectName in sections:
clVars = DataVarsObject(sectName)
clVars.importDataObject()
clVars.Set("cl_root_path",configPath, True)
clVars.Set("cl_belong_pkg",nameProgram, True)
clTempl = cl_template.template(clVars)
dirsFiles = clTempl.applyTemplates()
nameAndVerPkg = clVars.Get("cl_name")+"-"+clVars.Get("cl_ver")
if dirsFiles is False:
self.printERROR(_("Error template in a package %s")\
%nameAndVerPkg)
for errMess in clTempl.getError().splitlines():
self.printERROR(errMess)
return False
if dirsFiles and dirsFiles[1]:
dictPakkages[nameAndVerPkg] =\
sorted(list(set(dirsFiles[1])))
if dictPakkages:
for calcPkg in dictPakkages:
self.printWARNING(_("Package %s has changed files")%calcPkg+":")
for nameF in dictPakkages[calcPkg]:
nameFile = nameF.partition(configPath)[2]
if nameFile[:1] != "/":
nameFile = "/" + nameFile
self.printWARNING(" "*5 + nameFile)
else:
self.logger.warn(_("Not found templates"))
return True