#-*- 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 import sys import cl_utils from cl_lang import lang from cl_template import iniParser from cl_string import columnWrite # Перевод модуля на другой язык tr = lang() tr.setLocalDomain('cl_lib') tr.setLanguage(sys.modules[__name__]) class var: '''Объект "Переменная окружения"''' # название сервиса которому принадлежит переменная #(Global, Builder, Client, Server итд) service = None # значение переменной value = "" # режим записи (атрибут mode) mode = "r" # переменная для внутреннего использования (official) official = False # количество вызовов метода заполнения countFill = 0 # объект в котором создан этот объект parentObj = None # запускать или нет метод заполнения fillStart = True # dynamic = True то переменная динамическая при повтороном запуске # запускается метод заполнения # метод заполнения не запускается только если fillStart = False # (осторожно возможно зацикливание программы если методы заполнения # переменных используют методы друг друга) dynamic = False def __init__(self, parentObj): # словарь зависимых переменных {имя:значение} self.dependValues = {} # тип переменной (атрибут type) self.type = ('default') # список допустимых значений переменных (select) self.select = () # объект который создал этот объект self.parentObj = parentObj def is_update(self): #Нужно ли перезапускать метод заполнения (если зависимые переменные #обновились то нужно) upd = False for depVarName in self.dependValues.keys(): value = self.parentObj.__getattribute__(depVarName).Get() if self.dependValues[depVarName] != value: self.dependValues[depVarName] =\ self.parentObj.__getattribute__(depVarName).value upd = True break return upd def Get(self): """Получение значения переменной""" if not self.fillStart: return self.value if self.dynamic: self.value = self.Fill() return self.value if not self.value: if self.countFill>0: return self.value self.countFill += 1 self.value = self.Fill() if self.dependValues and self.is_update(): self.countFill += 1 self.value = self.Fill() return self.value def Set(self, value): """Запись значения переменной""" self.value = value return self.value def Fill(self): """Заполнение переменной в далнейшем заменяем методом заполнения""" return self.value class DataVars(object): class DataVarsError(Exception): """Класс ошибок""" pass # добавляем пути к модулям если они не добавлены if not os.path.abspath(\ '/usr/lib/calculate/calculate-server/pym') in sys.path: sys.path.insert(0,os.path.abspath(\ '/usr/lib/calculate/calculate-server/pym')) if not os.path.abspath(\ '/usr/lib/calculate/calculate-lib/pym') in sys.path: sys.path.insert(0,os.path.abspath(\ '/usr/lib/calculate/calculate-lib/pym')) if not os.path.abspath(\ '/usr/lib/calculate/calculate-builder/pym') in sys.path: sys.path.insert(0,os.path.abspath(\ '/usr/lib/calculate/calculate-builder/pym')) # Импортируемые модули - (раздел: модуль переменных, модуль заполнения #переменных) __modlist={'Global':('cl_vars','cl_fill'), 'Server':('cl_vars_server','cl_fill_server'), 'Builder':('cl_vars_builder','cl_fill_builder'), 'Client':('cl_vars_client','cl_fill_client'), } def __init__(self): #self.t1 = fillVars() #self.t1.Get = self.Get #self.t1.Set = self.Set # Для нахождения зависимостей переменных self.__levelNumber = 0 self.__LevelsVar = [] # Для хранения импортированных модулей и объектов #[(cекция,импортированный модуль переменных, объект заполнения),] self._importList = [] self._importData("Global") def _importData(self, section): """Импортирует модули с переменными и модули с функциями заполнения section секция раздела (Global, Server, Client итд) создает необходимые структуры данных """ if not section in self.__modlist.keys(): raise self.DataVarsError(_("Unsupported section %s")%section) modVar = self.__modlist[section][0] modFill = self.__modlist[section][1] # Импортируем класс описания переменных и класс заполнения try: exec ("import %s" % (modVar)) except ImportError, e: err1 = _("Error in import module %s")%modVar err2 = _("error") + ": " +str(e) raise self.DataVarsError("%s\n%s"%(err1,err2)) flagFindFillModule = True try: exec ("import %s" % (modFill)) except ImportError, e: if "No module named" in str(e): flagFindFillModule = False else: err1 = _("Error in import module %s")%modFill err2 = _("error") + ": " +str(e) raise self.DataVarsError("%s\n%s"%(err1,err2)) if flagFindFillModule: # Создаем объект с методами заполнения переменных exec("fillObj = %s.fillVars()" %modFill) # Подключаем методы получения и записи переменных fillObj.Get = self.Get fillObj.Set = self.Set else: fillObj = False # Заполняем self._importList exec("self._importList.insert(0,(section,%s,fillObj))"%(modVar)) def __findVarData(self, nameVar): """Находит данные для создания объекта переменная в модулях и объектах """ # Ищем переменную в модуле dataVar = False e = False for section, moduleVar, fillobj in self._importList: try: exec("dataVar=moduleVar.Data.%s"%nameVar) except AttributeError, e: pass if dataVar: break if dataVar == False: err1 = _("Not found variable %s")%nameVar err2 = "" if e: err2 = _("error") + ": " +str(e) raise self.DataVarsError("%s\n%s"%(err1,err2)) dataVar['service'] = section # Ищем метод в объекте методов заполнения nameMethod = "get_" + nameVar flagFindMetod = False for section, moduleVar, fillobj in self._importList: if fillobj: if nameMethod in dir(fillobj): flagFindMetod = True method = fillobj.__getattribute__(nameMethod) break if flagFindMetod: return (dataVar,method) else: return (dataVar,False) def __setAttributesVar(self, var ,nameVar, dict): """Установка аттрибутов для созданного объекта var название аттрибута и его значение берется из словаря dict """ dict['type'] = nameVar.split('_') if not set(dict.keys()) <= set(dir(var)): raise self.DataVarsError(\ _("error initalize variable %s, incorrect data")%nameVar) for nameAttr in dict.keys(): setattr(var,nameAttr, dict[nameAttr]) return True def __Get(self, nameVar): ret = "" self.__LevelsVar.append((self.__levelNumber, nameVar)) self.__levelNumber += 1 #nameMethod = "get_" + nameVar if self.__dict__.has_key(nameVar): ret = self.__getattribute__(nameVar).Get() elif self.__findVarData(nameVar): dictVar, methodFill =self.__findVarData(nameVar) varobj = var(self) # Устанавливаем аттрибуты self.__setAttributesVar(varobj, nameVar, dictVar) if methodFill: varobj.Fill = methodFill self.__setattr__(nameVar, varobj) ret = self.__getattribute__(nameVar).Get() self.__levelNumber -= 1 if self.__levelNumber == 0 and\ self.__getattribute__(nameVar).fillStart and\ len(self.__LevelsVar)>1: links = self.__getLinks(self.__LevelsVar) for name in links.keys(): for nameLink in links[name].keys(): val = self.__getattribute__(nameLink).Get() self.__getattribute__(name).dependValues[nameLink] = val if self.__levelNumber == 0: self.__LevelsVar = [] return ret def Get(self, nameVar): return self.__Get(nameVar) def __Set(self, nameVar, value, force=False): nameMethod = "get_" +nameVar if not self.__dict__.has_key(nameVar) and self.__findVarData(nameVar): dictVar, methodFill =self.__findVarData(nameVar) varobj = var(self) # Устанавливаем аттрибуты self.__setAttributesVar(varobj, nameVar, dictVar) if methodFill: varobj.Fill = methodFill self.__setattr__(nameVar, varobj) if self.__dict__.has_key(nameVar): if not force and "r" in getattr(self, nameVar).mode: print _("Attempt to rewrite a variable for reading:%s")\ %nameVar return False self.__getattribute__(nameVar).fillStart = False return self.__getattribute__(nameVar).Set(value) def Set(self, nameVar, value, force=False): return self.__Set(nameVar, value, force) def __frame(self, lVar): """получить список областей зависимости переменных""" data = [] if not lVar: return data firstLevel = lVar[0][0] for level, name in lVar[1:]: if level> firstLevel: data.append((level, name)) else: break return data def __getLinks(self, lVar): """Получить список переменных и от каких переменных они зависят на вход список [(уровень рекурсии, название переменной),] """ links = {} frames = {} levelLinks = {} lVarFr = lVar for level, name in lVar: fr = self.__frame(lVarFr) if not frames.has_key(name): frames[name] = fr levelLinks[name] = level+1 lVarFr = lVarFr[1:] for name in frames.keys(): level = levelLinks[name] fr = frames[name] links[name] = {} for lv, nm in fr: if level == lv: links[name][nm] = "" return links def __getPathCalculateIni(self): """Получить пути до ini файлов""" return self.Get('cl_env_path') def __getSection(self, vname): """секция для записи в ini файл переменной vname - имя переменной """ if self.__dict__.has_key(vname): if self.__dict__[vname].service == 'Global': return 'calculate' else: return self.__dict__[vname].service.lower() def __writeVarValue(self, vname, val, location, header): '''Записать значение в calculate.ini Параметры: vname имя переменной val значение переменной location расположение ini файла ('default', 'local', 'remote') header раздел ini файла ('client', 'server', 'calculate') Возвращаемые значение: True запись успешна False запись не удалсь ''' # получаем все пути до ini файлов calculate_ini = self.__getPathCalculateIni() # получаем полный путь до файла ini if location == 'default': name_calculate_ini = calculate_ini[2] elif location == 'local': name_calculate_ini = calculate_ini[1] elif location == 'remote': name_calculate_ini = calculate_ini[0] else: return False # извлекаем из полного имени файла путь onlydir = os.path.split(name_calculate_ini)[0] try: # проверяем чтобы путь до ини файла существовал if not os.path.exists(onlydir): # создаем его если отсутствует os.makedirs(onlydir) except OSError (nerr,msg): print nerr, msg return False config = iniParser(name_calculate_ini) # Получаем секцию конфигурационного файла if not header: header = self.__getSection(vname) return config.setVar(header,{vname: cl_utils.convertStrListDict(val)}) def __deleteVarValue(self, vname, location, header): '''Удалить переменную в calculate.ini Параметры: vname имя переменной location расположение ini файла ('default', 'local', 'remote') Возвращаемые значение: True удалено успешна False удаление не удалсь ''' # получаем все пути до ini файлов calculate_ini = self.__getPathCalculateIni() # получаем полный путь до файла ini if location == 'default': name_calculate_ini = calculate_ini[2] elif location == 'local': name_calculate_ini = calculate_ini[1] elif location == 'remote': name_calculate_ini = calculate_ini[0] else: return False # извлекаем из полного имени файла путь onlydir = os.path.split(name_calculate_ini)[0] # проверяем чтобы путь до ини файла существовал if not os.path.exists(onlydir): return False config = iniParser(name_calculate_ini) # Получаем секцию конфигурационного файла if not header: header = self.__getSection(vname) # Удаляем переменную retDelVar = config.delVar(header, vname) retDelArea = True if not config.getAreaVars(header): retDelArea = config.delArea(header) if retDelArea and retDelVar: return True else: return False def Write(self, vname, val, force=False, location='default',header=False): '''Установить и записать значение переменной в ini файл Параметры: vname имя переменной val значение переменной force "принудительный режим" location расположение ini файла ('default', 'local', 'remote') header раздел ini файла ('client', 'server', 'calculate') ''' if self.__Set(vname, val, force)!= False: if not val.strip(): self.__deleteVarValue(vname, location, header) self.__writeVarValue(vname, val, location, header) return True return False def Delete(self, vname, location='default', header=False): '''Удалить переменную в calculate.ini Параметры: vname имя переменной location расположение ini файла ('default', 'local', 'remote') Возвращаемые значение: True удалено успешна False удаление не удалсь ''' return self.__deleteVarValue(vname, location, header) def __getActiveSections(self): """активные секции в ini файле""" act_section = [] for service,t,t in self._importList: if service == "Global": act_section.append('calculate') else: act_section.append(service.lower()) return act_section def flIniFile(self): '''Заместить значение переменных значениями из ини файлов Возвращаемые значения: cловарь импортированных переменных - переменные считаны False - файл не был обнаружен ''' #Cловарь переменных из ini файлов importVars = {} calculate_ini = self.__getPathCalculateIni() # активные секции (секции из которых будут использованы переменные) act_section = self.__getActiveSections() set_act_section = set(act_section) i = 0 locations = ['remote','local','default'] for name_calculate_ini in calculate_ini: # проверить сущестование ini файла if os.path.exists(name_calculate_ini): # получить объект настроенный на ini config = iniParser(name_calculate_ini) # получаем все секции из конфигурационного файла allsect = config.getAllSectionNames() if not allsect: continue # находим встречающиеся у обоих секции act_sect = tuple(set(allsect)& set_act_section) # словарь переменных для ini - файла importFileVars = {} # получаем все переменные из всех секций for section in act_sect: allvars = config.getAreaVars(section) if allvars == False: return False # словарь переменных для ini - файла importFileVars = {} # принудительно переписать все переменные окружения # полученные из ini for (k,v) in allvars.items(): k = k.encode("UTF-8") value = cl_utils.convertStrListDict(v.encode("UTF-8")) self.Set(k, value, True) importFileVars[k] = value if i < 3: importVars[locations[i]] = importFileVars i += 1 return importVars def flServer(self, **args): '''Заполнить конфигурацию переменных, для ldap''' # заполнить переменные окружения алгоритмом по умолнанию self._importData("Server") def flClient(self, **args): '''Заполнить конфигурацию переменных, для клиента''' # заполнить переменные окружения алгоритмом по умолнанию self._importData("Client") def flBuilder(self, **args): '''Заполнить конфигурацию переменных, для билдера''' self.Set('setup_pass','builder',True) # заполнить переменные окружения алгоритмом по умолнанию self._importData("Builder") def flInstall(self, **args): '''Заполнить конфигурацию переменных для инсталятора''' self.Set('setup_pass','install',True) #def defined(self, vname): #if vname: #if self.__dict__.has_key(vname): #return True #return False def defined(self, vname): return True def exists(self, nameVar): """ Определяет существует ли переменная с таким имененм """ if self.__dict__.has_key(nameVar): return True foundVar = False # Ищем переменную в импортируемых модулях for section, moduleVar, fillobj in self._importList: if moduleVar.Data.__dict__.has_key(nameVar): foundVar = True break return foundVar def getVars(self, type_names=None): ret = {} for section, moduleVar, fillobj in self._importList: dataVar=moduleVar.Data dictVars = dir(dataVar) for nameVar in dictVars: if not "__" in nameVar: if not (getattr(dataVar,nameVar).has_key("official") and\ getattr(dataVar,nameVar)['official']): self.Get(nameVar) if type_names: #type_names.sort() varType =list(getattr(dataVar,nameVar)['type']) #varType.sort() #print type_names #print varType #print if not set(type_names)<=set(varType): continue ret[nameVar] = getattr(self,nameVar) return ret #распечатать список переменных с значениями def printVars(self,type_names=None): var=None var=self.getVars(type_names) mlen_name=0; mlen_type=0; mlen_mode=0; for i,j in var.items(): if len(i)>mlen_name: mlen_name=len(i) #if len(str(j.type))>mlen_type: #mlen_type=len(str(j.type)) vtype=str(type(var[i].value)).split(" ")[1][1] if not '[' in var[i].mode: if vtype in ['d','l']: mode="[%s%s]"%(var[i].mode.lower(),vtype) else: mode="[%s]"%(var[i].mode.lower()) var[i].mode=mode if len(mode)>mlen_mode: mlen_mode=len(mode) plist=var.keys() plist.sort() br = cl_utils.fillstr("-",mlen_name) + " " +\ cl_utils.fillstr("-",mlen_mode) + " " + cl_utils.fillstr("-",10) #cl_utils.fillstr("-",mlen_type) + " " +\ print "The list of variables:" print "var name".center(mlen_name),\ "Mode","Value" #"Type".center(mlen_type),\ print br for i in plist: #if var[i].value is None: #continue p_val=var[i].value if var[i].official: continue columnWrite( i, mlen_name, var[i].mode.lower(), mlen_mode, #str(var[i].type), #mlen_type, p_val) print br class glob_attr: """Глобальные аттрибуты для методов заполнения переменных""" def _runos(self,cmd, ret_first=None, env={}): """Вернуть результат выполнения команды ОС""" if not env: envDict = {} env.update(os.environ.items() + [("PATH",cl_utils.getpathenv())] +\ env.items()) retCode, programOut = cl_utils.runOsCommand(cmd, None, ret_first, env) if not retCode: return programOut return False