Merge branch 'master' of git.calculate.ru:calculate-lib

develop
Mike Hiretsky 14 years ago
commit 90ee22f6cc

@ -261,7 +261,7 @@ class fillVars(glob_attr):
def get_cl_template_clt_path(self):
'''Пути к файлам ,clt'''
if "CONFIG_PROTECT" in os.environ:
protectPaths = ["/etc"] + map(lambda x: x.strip(),
protectPaths = ["/etc"] + filter(lambda x: x.strip(),
os.environ["CONFIG_PROTECT"].split(" "))
else:
protectPaths = ["/etc", "/usr/share/X11/xkb", "var/lib/hsqldb",

@ -144,7 +144,7 @@ class ldapUser(_error):
return groupsDNs
return False
def getUserLdapInfo(self, userName):
def getUserLdapInfo(self, userName, shadowAttr=False):
"""Выдаем информацию о пользователе из LDAP"""
connectData = self.getBindConnectData()
if not connectData:
@ -159,39 +159,59 @@ class ldapUser(_error):
"uid=%s" %userName, None)
if not searchUser:
return False
uid = False
gid = False
fullName = ""
mail = ""
jid = ""
group = ""
if 'uidNumber' in searchUser[0][0][1]:
uid = searchUser[0][0][1]['uidNumber'][0]
if 'gidNumber' in searchUser[0][0][1]:
gid = searchUser[0][0][1]['gidNumber'][0]
for groupDN in groupsDNs:
searchGroup = self.ldapObj.ldapSearch(groupDN,
convertDict = {'uid':('user','uidNumber'),
'gid':('user','gidNumber'),
'fullName':('user','cn'),
'mail':('user','mail'),
'jid':('user','registeredAddress'),
'home':('user','homeDirectory'),
'group':('group','cn')}
if shadowAttr:
convertDict.update({'loginShell':('user','loginShell'),
'shadowLastChange':('user','shadowLastChange'),
'shadowMin':('user','shadowMin'),
'shadowMax':('user','shadowMax'),
'shadowWarning':('user','shadowWarning'),
'shadowExpire':('user','shadowExpire'),
'shadowFlag':('user','shadowFlag')})
listUserAttr = map(lambda x: x[0],
filter(lambda x: x[1][0]=="user",
convertDict.items()))
listGroupAttr = map(lambda x: x[0],
filter(lambda x: x[1][0]=="group",
convertDict.items()))
uid = ""
gid = ""
dictOut = {}
for dictAttr in listUserAttr:
ldapAttr = convertDict[dictAttr][1]
if ldapAttr in searchUser[0][0][1]:
dictOut[dictAttr] = searchUser[0][0][1][ldapAttr][0]
else:
dictOut[dictAttr] = ""
if dictAttr == 'uid':
uid = dictOut[dictAttr]
if dictAttr == 'gid':
gid = dictOut[dictAttr]
if gid:
for dictAttr in listGroupAttr:
searchGroup = []
ldapAttr = convertDict[dictAttr][1]
for groupDN in groupsDNs:
searchGroup = self.ldapObj.ldapSearch(groupDN,
ldap.SCOPE_ONELEVEL,
"gidNumber=%s" %gid, ['cn'])
"gidNumber=%s" %gid, None)
if searchGroup:
break
if searchGroup:
group = searchGroup[0][0][1]['cn'][0]
break
if 'cn' in searchUser[0][0][1]:
fullName = searchUser[0][0][1]['cn'][0]
if 'mail' in searchUser[0][0][1]:
mail = searchUser[0][0][1]['mail'][0]
if 'registeredAddress' in searchUser[0][0][1]:
jid = searchUser[0][0][1]['registeredAddress'][0]
if 'homeDirectory' in searchUser[0][0][1]:
home = searchUser[0][0][1]['homeDirectory'][0]
if ldapAttr in searchGroup[0][0][1]:
dictOut[dictAttr] = searchGroup[0][0][1][ldapAttr][0]
else:
dictOut[dictAttr] = ""
else:
dictOut[dictAttr] = ""
if uid and gid:
return {"uid":uid,
"gid":gid,
"fullName":fullName,
"mail":mail,
"jid":jid,
"home":home,
"group":group}
return dictOut
else:
return {}

@ -301,13 +301,14 @@ class fileHeader(_terms):
# Тип вставки шаблона
typeAppend = ""
# Возможные типы вставки шаблонов
_fileAppend = "join", "before", "after", "replace", "remove", "skip"
_fileAppend = "join", "before", "after", "replace", "remove", "skip",\
"patch"
# Интерпретатор (#!/bin/bash) (#!/usr/bin/python)
execStr = ""
# Символ комментария
comment = False
# Выражение для поиска строки интерпретатора
reExecStr = re.compile("^#!.+\s*",re.I)
reExecStr = re.compile("^#!.+\s*",re.M)
# условные операторы
terms = ('>', '<', '==', '!=', '>=', '<=')
# параметры без значения
@ -323,7 +324,14 @@ class fileHeader(_terms):
# Параметры описанные в заголовке файла шаблона
self.params = {}
# некорректные параметры
incorrectParams = set([])
incorrectParams = []
# Поиск строки запустка (#!/bin/bash и.т. д)
if comment or fileType!="bin":
reExecRes = self.reExecStr.search(self.body)
if reExecRes:
self.execStr = self.body[reExecRes.start():reExecRes.end()]
self.body = self.body[:reExecRes.start()] +\
self.body[reExecRes.end():]
# Удаление Заголовка Calculate
if comment:
titleFirst = _("Modified")
@ -332,25 +340,24 @@ class fileHeader(_terms):
reCalcHeader =\
re.compile("\s*%s\s+%s.+\s+(.+\n)+%s\s?"\
%(comment[0], titleFirst, comment[1]),re.M|re.I)
reS = reCalcHeader.search(text)
reS = reCalcHeader.search(self.body)
if reS:
self.body = text[:reS.start()]+text[reS.end():]
self.body = self.body[:reS.start()]+self.body[reS.end():]
else:
reCalcHeader = re.compile(\
"\s*%s\-+\s+%s\s+%s.+\s+(%s.+\s+)+%s\-+\s?"\
%(comment, comment, titleFirst ,comment,comment),
re.M|re.I)
reS = reCalcHeader.search(text)
reS = reCalcHeader.search(self.body)
if reS:
self.body = text[reS.end():]
self.body = self.body[reS.end():]
if fileType != False:
if fileType=="bin":
self.params["format"] = fileType
self.fileType = self._getType()
self.typeAppend = self._getAppend()
else:
textLines = text.splitlines()
textLines = self.body.splitlines()
if textLines:
textLine = textLines[0]
rePar = re.compile("\s*#\s*calculate\s+",re.I)
@ -358,17 +365,17 @@ class fileHeader(_terms):
if reP:
reL = False
reLns = re.compile(r"\A([^\\\n]*\\\n)+[^\n]*\n*",re.M)
reLs = reLns.search(text)
reLs = reLns.search(self.body)
if reLs:
reL = reLs
paramLine = text[reP.end():reLs.end()]
paramLine = self.body[reP.end():reLs.end()]
paramLine = paramLine.replace("\\"," ")
else:
reLn = re.compile("\n")
reL = reLn.search(text)
reL = reLn.search(self.body)
paramLine = textLine[reP.end():]
if reL:
self.body = text[reL.end():]
self.body = self.body[reL.end():]
else:
self.body = ""
paramList = re.split("\s+",paramLine)
@ -405,12 +412,14 @@ class fileHeader(_terms):
self.comment = self._getComment()
self.fileType = self._getType()
self.typeAppend = self._getAppend()
reExecRes = self.reExecStr.search(self.body)
if reExecRes:
self.execStr = self.body[reExecRes.start():reExecRes.end()]
self.body = self.body[reExecRes.end():]
if not incorrectParams:
typeAppend = self._getAppend()
if typeAppend:
self.typeAppend = typeAppend
else:
self.headerTerm = False
self.setError(_("incorrect header parameters - '%s'")\
%"append=%s"%self.params["append"])
if not incorrectParams and self.params:
incorrectParams = set(self.params.keys()) - set(self.allowParam)
if incorrectParams:
self.headerTerm = False
@ -419,19 +428,24 @@ class fileHeader(_terms):
def _getType(self):
"""Выдать тип файла"""
if self.params.has_key("format"):
if "format" in self.params:
return self.params["format"]
else:
return "raw"
def _getAppend(self):
"""Выдать тип добавления файла"""
if self.params.has_key("append") and self.params["append"] in\
self._fileAppend:
return self.params["append"]
if self.params.has_key("append"):
if self.params["append"] in self._fileAppend:
return self.params["append"]
else:
return False
else:
if self.fileType != "raw" and self.fileType != "bin" and\
self.fileType != "":
if "format" in self.params and self.params["format"] == "patch":
self.params["append"] = "patch"
return "patch"
self.params["append"] = "join"
return "join"
self.params["append"] = "replace"
@ -532,7 +546,13 @@ class dirHeader(_terms):
incorrectParams = set([i])
elif len(par) == 2:
self.params[par[0]] = par[1]
self.typeAppend = self._getAppend()
typeAppend = self._getAppend()
if typeAppend:
self.typeAppend = typeAppend
else:
self.headerTerm = False
self.setError(_("incorrect header parameters - '%s'")\
%"append=%s"%self.params["append"])
if not flagErrorBody:
if not incorrectParams:
incorrectParams = set(self.params.keys()) - set(self.allowParam)
@ -543,9 +563,11 @@ class dirHeader(_terms):
def _getAppend(self):
"""Выдать тип добавления директории"""
if self.params.has_key("append") and self.params["append"] in\
self._fileAppend:
return self.params["append"]
if self.params.has_key("append"):
if self.params["append"] in self._fileAppend:
return self.params["append"]
else:
return False
else:
return "join"
@ -3283,14 +3305,18 @@ re.M|re.S)
def getTemplateType(self):
"""выдать тип шаблона (text, bin)"""
isBin = self.typeFileObj.isBinary(self.nameFileTemplate)
return self.getFileType(self.nameFileTemplate)
def getFileType(self, fileName):
"""выдать тип файла (text, bin)"""
isBin = self.typeFileObj.isBinary(fileName)
typeTemplate = "bin"
if isBin is True:
typeTemplate = "bin"
elif isBin is False:
typeTemplate = "text"
else:
self.setError(_("ERROR") + ": getTemplateType()")
self.setError(_("ERROR") + ": getFileType()")
self.setError(isBin)
return False
return typeTemplate
@ -3567,10 +3593,9 @@ re.M|re.S)
self.cltObj.dictProcessedTemplates = self.dictProcessedTemplates
if self.cltFilter:
# Шаблоны + .clt которые будут применены
self.cltObj.filterApplyTemplates=\
self.cltObj.filterApplyTemplates +=\
map(lambda x: pathJoin('/', x.partition(self._baseDir)[2]),
self.dictProcessedTemplates.keys())
# Обрабатываем шаблоны clt
if not self.cltObj.applyTemplates():
return False
return (self.createdDirs, self.filesApply)
@ -4213,7 +4238,7 @@ re.M|re.S)
return ([], False)
if not objHeadNew.body.strip():
preReturn(pathProg)
return ([], False)
return (applyFiles, False)
else:
applyFiles = [pathOldFile]
if pathProg:
@ -4333,9 +4358,48 @@ re.M|re.S)
if objHeadNew.comment:
objHeadOld = fileHeader(nameFileConfig, self.textConfig,
objHeadNew.comment)
elif objHeadNew.fileType and\
objHeadNew.typeAppend in ("before", "after"):
configFileType = self.getFileType(nameFileConfig)
objHeadOld = fileHeader(nameFileConfig, self.textConfig,
fileType=configFileType)
# Строка вызова скрипта (#!/bin/bash ...)
execStr = ""
if objHeadNew.execStr:
execStr = objHeadNew.execStr
elif objHeadOld and objHeadOld.execStr:
execStr = objHeadOld.execStr
if objHeadNew.fileType:
formatTemplate = objHeadNew.fileType
typeAppendTemplate = objHeadNew.typeAppend
if formatTemplate == "patch":
if typeAppendTemplate != "patch":
self.setError(\
_("False option append=%(type)s in template %(file)s")\
%{"type":typeAppendTemplate,"file":nameFileTemplate})
return False
# создаем объект формата шаблона
objTempl = self.getFormatObj(formatTemplate, self.textTemplate)
if not objTempl:
self.setError(\
_("Incorrect header parmeter format=%s in template")\
%formatTemplate + " " + nameFileTemplate)
return False
if objHeadOld and objHeadOld.body:
self.textConfig = objHeadOld.body
# обработка конфигурационного файла
self.textTemplate = objTempl.processingFile(self.textConfig)
if objTempl.getError():
self.setError(_("False template") + ": " +\
nameFileTemplate)
return False
if execStr:
self.textConfig = execStr + title + self.textTemplate
else:
self.textConfig = title + self.textTemplate
self.saveConfFile()
return filesApply
# Создаем объект в случае параметра format в заголовке
if (typeAppendTemplate == "replace" or\
typeAppendTemplate == "before" or\
@ -4397,7 +4461,7 @@ re.M|re.S)
self.textConfig = title + self.textTemplate
self.saveConfFile()
return filesApply
# Впереди
# Вверху
elif typeAppendTemplate == "before":
if "xml_" in formatTemplate:
self.setError(\
@ -4410,16 +4474,14 @@ re.M|re.S)
tmpTemplate = self.textTemplate + self.textConfig
else:
tmpTemplate = self.textTemplate + "\n" + self.textConfig
if objHeadNew.execStr:
self.textConfig = objHeadNew.execStr + title + tmpTemplate
elif objHeadOld and objHeadOld.execStr:
self.textConfig = objHeadOld.execStr + title + tmpTemplate
if execStr:
self.textConfig = execStr + title + tmpTemplate
else:
self.textConfig = title + tmpTemplate
self.saveConfFile()
return filesApply
# ади
# Внизу
elif typeAppendTemplate == "after":
if "xml_" in formatTemplate:
self.setError(\
@ -4432,10 +4494,8 @@ re.M|re.S)
tmpTemplate = self.textConfig + self.textTemplate
else:
tmpTemplate = self.textConfig + "\n" + self.textTemplate
if objHeadNew.execStr:
self.textConfig = objHeadNew.execStr + title + tmpTemplate
elif objHeadOld and objHeadOld.execStr:
self.textConfig = objHeadOld.execStr + title + tmpTemplate
if execStr:
self.textConfig = execStr + title + tmpTemplate
else:
self.textConfig = title + tmpTemplate
self.saveConfFile()
@ -4476,14 +4536,6 @@ re.M|re.S)
if not self.textConfig or\
not reNoClean.search(self.textConfig):
self.textConfig = ""
#if objHeadNew.execStr:
#self.textConfig = objHeadNew.execStr + \
#title + objTemplNew.getConfig().encode("UTF-8")
#else:
#self.textConfig = title +\
#objTemplNew.getConfig().encode("UTF-8")
#self.saveConfFile()
#return True
objHeadOld = fileHeader(nameFileConfig, self.textConfig,
objTemplNew._comment)
@ -4518,12 +4570,9 @@ re.M|re.S)
data.insert(1,title)
self.textConfig = "\n".join(data)
else:
if objHeadNew.execStr:
self.textConfig = objHeadNew.execStr + title +\
objTemplOld.getConfig().encode("UTF-8")
elif objHeadOld.execStr:
self.textConfig = objHeadOld.execStr + title +\
objTemplOld.getConfig().encode("UTF-8")
if execStr:
self.textConfig = execStr + title +\
objTemplOld.getConfig().encode("UTF-8")
else:
self.textConfig = title +\
objTemplOld.getConfig().encode("UTF-8")
@ -4588,6 +4637,9 @@ class templateClt(scanDirectoryClt, template):
self.flagApplyTemplates = False
if self.objVar.Get("cl_name") in applyPackages:
self.flagApplyTemplates = True
# Базовая директория переноса шаблонов "/mnt/calculate" или "/" и.т.д
self._baseDir = pathJoin(self.objVar.Get("cl_chroot_path"),
self.objVar.Get("cl_root_path"))
def applyTemplate(self, path):
"""Применение отдельного .clt шаблона"""
@ -4616,6 +4668,7 @@ class templateClt(scanDirectoryClt, template):
else:
nameFileConfig = path
nameFileConfig = nameFileConfig[:-self.lenExtFileTemplate]
nameFileConfig = pathJoin(self._baseDir, nameFileConfig)
# файл в системе без условий
nameFileConfig = "/".join(map(lambda x:x.split("?")[0],\
nameFileConfig.split("/")))
@ -4631,8 +4684,10 @@ class templateClt(scanDirectoryClt, template):
if filesApl:
self.filesApply += filesApl
# Настоящее имя конфигурационного файла
nameFileConfig = filesApl[0]
return nameFileConfig
nameFileConfig = filesApl[0]
return nameFileConfig
else:
return True
def countsNumberTemplates(self, dirsTemplates=[]):
"""Считаем количество шаблонов"""

@ -0,0 +1,106 @@
#-*- 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 sys, re
import xml.dom.minidom
from cl_utils import _error
# Перевод cообщений модуля
from cl_lang import lang
tr = lang()
tr.setLocalDomain('cl_lib')
tr.setLanguage(sys.modules[__name__])
class patch(_error):
"""Класс для замены, добавления, удаления, строк в файле"""
# root нода
rootNode = False
# Документ
doc = False
# Текст шаблона
text = ""
def __init__(self, text):
self.text = text
# Создаем XML документ
self.doc = self.textToXML()
if self.doc:
self.rootNode = self.doc.documentElement
def textToXML(self):
"""Создание из текста XML документа
Храним xml в своем формате
"""
if not self.text.strip():
self.text = ''
text = '<?xml version="1.0" encoding="UTF-8"?>\n<patch>%s</patch>'\
%self.text
try:
self.doc = xml.dom.minidom.parseString(text)
except:
return False
return self.doc
def processingFile(self, textConfigFile):
"""Обработка конфигурационного файла"""
if not self.doc:
self.setError(_("Can not convert text template in XML"))
return False
retTextConfigFile = textConfigFile
tags = ["reg", "text"]
dataList = []
tagsIndex = 0
for node in self.rootNode.childNodes:
if node.nodeType==node.ELEMENT_NODE:
if not node.tagName == tags[tagsIndex]:
self.setError(_("Incorrect text template"))
return False
if tagsIndex == 1:
tagsIndex = 0
else:
tagsIndex += 1
# регулярное выражение
if node.tagName == "reg":
if node.firstChild:
reText = node.firstChild.nodeValue
else:
self.setError(\
_("Incorrect text template '<reg></reg>'"))
return False
if not reText.strip():
self.setError(\
_("Incorrect text template '<reg>%s</reg>'")\
%reText)
return False
try:
regex = re.compile(reText)
except:
self.setError(\
_("Incorrect text template '<reg>%s</reg>'")\
%reText)
return False
elif node.tagName == "text" and regex:
if node.firstChild:
text = node.firstChild.nodeValue
else:
text = ""
dataList.append((regex, text))
regex = False
for regex, text in dataList:
# Замены в тексте конфигурационного файла
retTextConfigFile = regex.sub(text, retTextConfigFile)
return retTextConfigFile

@ -72,8 +72,9 @@ def dialogYesNo(message):
"""Вывод сообщения, ожидание набора Yes или No (в любом регистре)
если Yes - True, если No - False"""
sys.stdout.write(message + ": ")
strIn=sys.stdin.readline().lower().strip()
#sys.stdout.write(message + ": ")
#strIn=sys.stdin.readline().lower().strip()
strIn = raw_input(message + ": ")
sys.stdout.write("\n")
if "yes" == strIn:
return True

@ -22,7 +22,7 @@ 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
from cl_utils import runOsCommand, scanDirectory, pathJoin
import cl_overriding
import cl_lang
@ -189,7 +189,6 @@ class updateUserConfigs(shareUpdateConfigs):
self.logger.warn(_("Not found templates"))
return True
class updateSystemConfigs(shareUpdateConfigs):
"""Обновление системных конфигурационных файлов"""
@ -198,7 +197,7 @@ class updateSystemConfigs(shareUpdateConfigs):
if not "CONFIG_PROTECT" in os.environ:
self.printERROR(_("Missing environment variable CONFIG_PROTECT"))
exit(1)
protectPaths = ["/etc"] + map(lambda x: x.strip(),
protectPaths = ["/etc"] + filter(lambda x: x.strip(),
os.environ["CONFIG_PROTECT"].split(" "))
flagFoundProtect = False
for pPath in protectPaths:
@ -210,6 +209,21 @@ class updateSystemConfigs(shareUpdateConfigs):
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)
@ -235,9 +249,18 @@ class updateSystemConfigs(shareUpdateConfigs):
clVars.Set("cl_root_path", configPath, True)
clVars.Set("cl_belong_pkg", nameProgram, True)
clVars.Set("cl_action", 'merge', True)
clTempl = cl_template.template(clVars)
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 = clVars.Get("cl_name")+"-"+clVars.Get("cl_ver")
nameAndVerPkg = nameProg + "-"+clVars.Get("cl_ver")
if dirsFiles is False:
self.printERROR(_("Error template in a package %s")\
%nameAndVerPkg)

Loading…
Cancel
Save