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

284 lines
12 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 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, scanDirectory, pathJoin
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())
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):
"""Класс переменных для десктопа"""
packagePath = "/usr/lib/calculate-2.2"
def __init__(self, nameProgram):
cl_datavars.DataVars.__init__(self)
self.nameProgram = nameProgram
def findPathVars(self):
pymPath = os.path.join(self.packagePath, self.nameProgram, "pym")
if os.path.isdir(pymPath) and\
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:
importPath = os.path.abspath(pymPath)
if not importPath in sys.path:
sys.path.insert(0, importPath)
return True
return False
def importDataObject(self, **args):
'''Заполнить конфигурацию переменных, для десктопа'''
# заполнить переменные окружения алгоритмом по умолнанию
sectName = self.nameProgram.rpartition("-")[2]
self.importData(sectName, ('cl_vars_%s' %sectName,
'cl_fill_%s' %sectName))
self.flIniFile()
class shareUpdateConfigs(color_print, writeLog):
"""Общие методы для обновления конфигурационных файлов"""
reCleanVer = re.compile("\d+\.?\d*\.?\d*")
def getPrograms(self):
"""Получаем установленные программы работающие с шаблонами"""
clVars = cl_datavars.DataVars()
clVars.flIniFile()
return clVars.GetList("cl_merges")
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 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"))
# Программы используемые для наложения шаблонов
mergePrograms = self.getPrograms()
if "calculate-desktop" in mergePrograms:
mergePrograms = ["calculate-desktop"]
else:
mergePrograms = []
dictPakkages = {}
# Добавление условия, что программа category/nameProgram
# установлена
cl_template.templateFunction.installProg.update(\
{"%s/%s"%(category,nameProgram):[version],
"%s"%(nameProgram):[version]})
for mergeProgram in mergePrograms:
for userName in xUsers:
clVars = DataVarsObject(mergeProgram)
if not clVars.findPathVars():
continue
clVars.importDataObject()
clVars.Set("ur_login", userName, True)
clVars.Set("cl_action", "desktop", 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"] + filter(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 scanProtectDirs(self, configPath):
configFiles = []
scanObj = scanDirectory()
scanObj.processingFile = lambda path,prefix:configFiles.append(path) or\
True
protectPaths = ["/etc"] + filter(lambda x: x.strip(),
os.environ["CONFIG_PROTECT"].split(" "))
configPath = os.path.realpath(configPath)
for pPath in protectPaths:
realPath = pathJoin(configPath, pPath)
if os.path.exists(realPath):
scanObj.scanningDirectory(realPath)
configFiles = map(lambda x: x.partition(configPath)[2], configFiles)
return configFiles
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
# Программы используемые для наложения шаблонов
mergePrograms = self.getPrograms()
dictPakkages = {}
# Добавление условия, что программа category/nameProgram установлена
cl_template.templateFunction.installProg.update(\
{"%s/%s"%(category,nameProgram):[version],
"%s"%(nameProgram):[version]})
for mergeProgram in mergePrograms:
clVars = DataVarsObject(mergeProgram)
if not clVars.findPathVars():
continue
clVars.importDataObject()
clVars.Set("cl_root_path", configPath, True)
clVars.Set("cl_belong_pkg", nameProgram, True)
clVars.Set("cl_action", 'merge', True)
configFiles = []
nameProg = clVars.Get("cl_name")
if nameProg == "calculate-install":
configFiles = self.scanProtectDirs(configPath)
cltObject = cl_template.templateClt(clVars)
if configFiles:
cltObject.filterApplyTemplates = configFiles
else:
cltObject.filterApplyTemplates = []
clTempl = cl_template.template(clVars, cltObj=cltObject)
dirsFiles = clTempl.applyTemplates()
nameAndVerPkg = nameProg + "-"+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