#-*- coding: utf-8 -*- # Copyright 2008-2013 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 re from os import path from calculate.lib.datavars import (Variable, VariableError, ReadonlyVariable, ReadonlyTableVariable, TableVariable, FieldValue, SimpleDataVars, DataVarsError) from calculate.lib.utils.files import readFile, \ listDirectory, process, pathJoin from calculate.lib.configparser import ConfigParser from calculate.lib.cl_lang import setLocalTranslate from calculate.lib.utils.text import simplify_profiles from calculate.lib.utils.portage import Git, GitError, Layman from ..profile import RepositoryStorageSet, DEFAULT_BRANCH, \ LocalStorage, ProfileRepository, CacheStorage from calculate.lib.variables import linux as lib_linux from calculate.lib.variables import env from calculate.update.update_info import UpdateInfo import urllib2 import time _ = lambda x:x setLocalTranslate('cl_update3', sys.modules[__name__]) class VariableAcUpdateSync(ReadonlyVariable): """ Action variable which has value "up" for package install and install this package """ def get(self): action = self.Get("cl_action") if action in ("sync",): if self.Get('cl_update_world'): return self.Get('cl_update_world') return "" class VariableClUpdateWorld(Variable): type = "choice" value = "update" opt = ["--world"] syntax = "--{choice}-world" metavalue = "MODE" def init(self): self.help = ("'rebuild' - " + _("rebuild the system packages list") + ",\n'merge' - " + _("append the profile packages list") + ",\n'update' - " + _("update the system packages list")) self.label = _("System packages list") def choice(self): return [("rebuild", _("Rebuild")), ("merge", _("Merge")), ("update", _("Update"))] class VariableClRebuildWorldSet(Variable): """ List of action update world, rebuild world, """ type = "bool" opt = ["--rebuild-world"] untrusted = True value = "off" def init(self): self.help = _("Rebuild world") self.label = _("Rebuild world") class VariableClUpdateRevSet(Variable): """ List of action update world, rebuild world, """ type = "bool" opt = ["--update-rev"] untrusted = True value = "on" check_after = ["cl_update_sync_rep", "cl_update_metadata_force", "cl_update_other_set", "cl_update_eixupdate_force"] def init(self): self.help = _("make a revision update") self.label = _("Make a revision update") class VariableClUpdateRep(Variable): """ Обновлять репозитории до конкретной ревизии или до последней """ type = "choice" value = "rev" def choice(self): return ["last", "rev"] class VariableClUpdateRepData(ReadonlyTableVariable): """ Информация о репозиториях """ source = ['cl_update_rep_name', 'cl_update_rep_url', 'cl_update_rep_path', 'cl_update_rep_rev'] class VariableClUpdateRepName(Variable): """ Список имен используемых репозиториев """ type = "list" value = [] class VariableClUpdateRepUrl(Variable): """ Список путей до репозиториев """ type = "list" value = [] class VariableClUpdateLaymanConfig(ReadonlyVariable): """ Объект конфига layman """ type = "object" def get(self): chroot = self.Get('cl_chroot_path') cp = ConfigParser() cp.read(path.join(chroot, 'etc/layman/layman.cfg')) return cp class VariableClUpdateLaymanStorage(Variable): """ Путь к репозиториям layman """ param_name = "storage" fallback_value = "var/lib/layman" def get(self): cp = self.Get('cl_update_layman_config') res = cp.get('MAIN', self.param_name, fallback=self.fallback_value) return pathJoin(self.Get('cl_chroot_path'), res) class VariableClUpdateRepPath(ReadonlyVariable): """ Пути до репозиториев """ type = "list" mapPath = {'portage': 'usr/portage', 'gentoo': '/usr/portage'} def get(self): repPath = self.Get('cl_update_layman_storage') chroot_path = self.Get('cl_chroot_path') def generatePaths(names): for name in names: if name in self.mapPath: yield path.join(chroot_path, self.mapPath[name]) else: yield path.join(repPath, name) return list(generatePaths(self.Get('cl_update_rep_name'))) class VariableClUpdateRepRev(Variable): """ Ревизии до которых необходимо обновить репозитории """ type = "list" def get(self): cp = ConfigParser() revisions = self.Get('update.cl_update_binhost_revisions') if revisions: cp.read_string(unicode(revisions[0])) branch = self.Get('cl_update_branch') def generateBranch(): for repname, branchname in zip( self.Get('cl_update_rep_name'), self.Get('cl_update_branch_name')): if branchname == "binhost": yield cp.get("vcs", repname, fallback=branch) else: yield branchname return list(generateBranch()) class VariableClUpdateBranch(Variable): """ Ветка на которую будет обновляться репозиторий если -getbinpkg """ value = "master" class VariableClUpdateBranchData(TableVariable): """ Выбор веток репозиториев до которых необходимо обновиться """ opt = ["--branch"] metavalue = 'BRANCHES' untrusted = True source = ["cl_update_branch_rep", "cl_update_branch_name"] def init(self): self.help = _("set branches for repository (REPOSITORY:BRANCH)") self.label = _("Repositories branches") def raiseReadonlyIndexError(self, fieldname="", variablename="", value=""): """ Неизвестный оврелей """ raise VariableError(_("Repository %s not found")%value) class VariableClUpdateBranchRep(ReadonlyVariable): """ Список доступных репозиторием """ type = "list" def init(self): self.label = _("Repositories") def get(self): return self.Get('cl_update_rep_name') class VariableClUpdateBinhostData(ReadonlyTableVariable): """ Таблица содержащая binhost/содержимое файла ревизий/время доступа """ source = ["cl_update_binhost_host", "cl_update_binhost_revisions", "cl_update_binhost_time"] def check_binhost(self, binhost): revision_files = [path.join(binhost, x) for x in self.Get('cl_update_binhost_revision_path')] timeout = self.GetInteger('cl_update_binhost_timeout') try: data = None for fn in revision_files: if data is None: data = urllib2.urlopen(fn, timeout=timeout).read() elif data != urllib2.urlopen(fn, timeout=timeout).read(): return "" return data except urllib2.URLError: return "" re_revison = re.compile("\w+=(\w+)") def binhost_key(self, data): host, t = data try: cp = ConfigParser() cp.read_string(data.decode('utf-8')) data = sum(int(x) for x in cp['vcs'].values()) except (TypeError, KeyError) as e: data = 0 return (1 if int(time) >= 0 else 0, data, -int(time)) def get_timestamp(self, binhost): DAY = 60 * 60 * 24 timeout = self.GetInteger('cl_update_binhost_timeout') timestamp_file = path.join(binhost, self.Get('cl_update_binhost_timestamp_path')) try: t = time.time() data = urllib2.urlopen(timestamp_file, timeout=timeout).read().strip() if data.isdigit() and t - int(data) < 5 * DAY: return data, int((time.time() - t)*1000) except urllib2.URLError as e: pass return "", -1 def get(self, hr=False): binhost = self.Get('cl_update_binhost') recheck = self.GetBool('cl_update_binhost_recheck_set') def generate_by_timestamp(): for host in self.Get('cl_update_binhosts'): if host: ts_content, duration = self.get_timestamp(host) if ts_content: yield host, ts_content, str(duration) if not recheck and binhost: ts, t = self.get_timestamp(binhost) if ts: data = self.check_binhost(binhost) if data: return [[binhost, data, str(t)]] for host, ts, t in sorted(generate_by_timestamp(), key=lambda x: (-int(x[1]), int(x[2]))): data = self.check_binhost(host) if data: return [[host, data, str(t)]] return [[]] class VariableClUpdateBinhostRecheckSet(Variable): """ Принудительно обновить binhost """ type = "bool" value = "off" opt = ["--recheck-binhost"] def init(self): self.help = _("re-check binary hosts") self.label = _("Re-check binary hosts") class VariableClUpdateBinhostHost(FieldValue, ReadonlyVariable): """ Список имен прочих репозиториев """ type = "list" source_variable = "cl_update_binhost_data" column = 0 class VariableClUpdateBinhostRevisions(FieldValue,ReadonlyVariable): """ Список имен прочих репозиториев """ type = "list" source_variable = "cl_update_binhost_data" column = 1 class VariableClUpdateBinhostTime(FieldValue,ReadonlyVariable): """ Список имен прочих репозиториев """ type = "list" source_variable = "cl_update_binhost_data" column = 2 class VariableClUpdateBranchName(Variable): """ Список доступных репозиторием """ type = "choiceedit-list" def init(self): self.label = _("Branches") def choice(self): return ["master", "develop", "update", "binhost"] def get(self): if "getbinpkg" in self.Get('cl_features'): return ["binhost" for x in self.Get('cl_update_rep_name')] else: branch = self.Get('cl_update_branch') return [branch for x in self.Get('cl_update_rep_name')] class VariableClUpdateSyncRep(Variable): """ Обновляемый репозиторий """ type = "choice-list" element = "selecttable" opt = ["-r", "--repositories"] metavalue = "REPOSITORIES" untrusted = True @property def rep_name(self): return self.Get('update.cl_update_rep_name') def init(self): self.help = _("synchronized repositories (all by default)") self.label = _("Synchronized repositories") def set(self, value): orderList = self.rep_name return sorted(value, key=lambda x: (orderList.index(x) if x in orderList else -1), reverse=True) def get(self): return list(reversed(self.rep_name)) def choice(self): return self.rep_name class VariableClUpdateSyncOverlayRep(ReadonlyVariable): """ Обновляемые репозитории (исключая portage) """ type = "list" def get(self): return filter(lambda x: x != "portage", self.Get('cl_update_sync_rep')) class VariableClUpdateOutdateSet(ReadonlyVariable): """ Флаг устанавливаемый в ходе обновления репозиториев, сообщающий что хотя бы один из запланированных репозиториев обновлен и следует обновляет различные метаданные Если обновляются прочие оверлеи - данные считаются что устарели """ type = "bool" def get(self): if (self.Get('cl_update_other_set') == 'on' and self.Get('cl_update_other_rep_name')): return "on" return "off" class VariableClUpdateMetadataForce(Variable): """ Принудительное действие с метаданными """ type = "choice" value = "auto" opt = ["--update-metadata"] syntax = "--{choice}-update-metadata" metavalue = "MODE" #untrusted = True def init(self): self.help = ("'force' - " + _("force the update ebuilds metadata") + ",\n'skip' - " + _("skip the ebuild metadata update") + ",\n'auto' - " + _("update metadata if it is outdated")) self.label = _("Update metadata") def choice(self): return [("force", _("Force")), ("skip", _("Skip")), ("auto", _("If needed"))] class VariableClUpdateEgencacheForce(Variable): """ Принудительное выполнение egencache """ type = "choice" value = "auto" opt = ["--egencache"] syntax = "--{choice}-egencache" metavalue = "MODE" #untrusted = True def init(self): self.help = ("'force' - " + _("force the update of the overlays cache") + ",\n'skip' - " + _("skip the update of the overlays cache") + ",\n'auto' - " + _("update the overlays cache if outdated")) self.label = _("Update the overlays cache") def choice(self): return [("force", _("Force")), ("skip", _("Skip")), ("auto", _("If needed"))] class VariableClUpdateEixupdateForce(Variable): """ Принудительное действие с eix-update """ type = "choice" value = "auto" opt = ["--eix-update"] syntax = "--{choice}-eix-update" metavalue = "MODE" #untrusted = True def init(self): self.help = ("'force' - " + _("force the eix cache update") + ",\n'skip' - " + _("skip the eix cache update") + ",\n'auto' - " + _("update the eix cache if it " "is outdated")) self.label = _("Update the eix cache") def choice(self): return [("force", _("Force")), ("skip", _("Skip")), ("auto", _("If needed"))] class VariableClUpdateOtherSet(Variable): """ Обновить остальные оверлеи """ type = "bool" value = "off" opt = ["-o", "--update-other"] def init(self): self.help = _("update other overlays") self.label = _("Update other overlays") class VariableClUpdateOtherRepData(ReadonlyTableVariable): """ Информация о прочих репозиториях """ source = ['cl_update_other_rep_name', 'cl_update_other_rep_path'] portdir_overlay = "main.cl_portdir_overlay" def generator(self): repNames = self.Get('update.cl_update_rep_name') layman = Layman(self.Get('update.cl_update_layman_installed'), self.Get('update.cl_update_layman_make'), self.Get('update.cl_update_layman_conf')) layman_overlays = layman.get_installed() for rpath in self.Get(self.portdir_overlay): repo_file = path.join(rpath, "profiles/repo_name") rname = readFile(repo_file).strip() or path.basename(rpath) if rname in layman_overlays and rname not in repNames: yield (rname, rpath) def get(self): return list(self.generator()) class VariableClUpdateOtherRepName(FieldValue,ReadonlyVariable): """ Список имен прочих репозиториев """ type = "list" source_variable = "cl_update_other_rep_data" column = 0 class VariableClUpdateOtherRepPath(FieldValue,ReadonlyVariable): """ Список путей до прочих репозиториев """ type = "list" source_variable = "cl_update_other_rep_data" column = 1 class VariableClUpdateLaymanInstalled(VariableClUpdateLaymanStorage): """ Путь до файла layman installed.xml """ param_name = "installed" fallback_value = "var/lib/layman/installed.xml" class VariableClUpdateLaymanMake(VariableClUpdateLaymanStorage): """ Путь до файла make.conf изменяемого layman`ом """ param_name = "make_conf" fallback_value = "var/lib/layman/make.conf" class VariableClUpdateLaymanConf(VariableClUpdateLaymanStorage): """ Путь до конфигурационного файла репозиториев для layman """ param_name = "repos_conf" fallback_value = "etc/portage/repos.conf/layman.conf" class VariableClUpdatePretendSet(Variable): """ Запустить предварительную проверку на обновления """ type = "bool" value = "off" opt = ["-p", "--pretend"] def init(self): self.label = _("Pretend a package update") self.help = _("instead of actually performing the update, " "simply display the list of packages that " "will be installed") class VariableClUpdateSyncOnlySet(Variable): """ Не выполнять установку/обновление пакетов при обновлении """ type = "bool" value = "off" opt = ["-s", "--sync-only"] def init(self): self.label = _("Only synchronize repositories") self.help = _("do not update packages") def check(self, value): if (value == "on" and self.Get('cl_rebuild_world_set') != 'on' and not self.Get('cl_update_sync_rep') and self.Get('cl_update_other_set') == 'off' and self.Get('cl_update_rev_set') == 'off' and self.Get('cl_update_metadata_force') != "force" and self.Get('cl_update_eixupdate_force') != "force"): raise VariableError(_("Select at least one sync repository")) class VariableClUpdateWaitAnotherSet(Variable): """ Ждать завершения другого процесса обновления """ type = "bool" value = "on" opt = ["--wait-another-update"] def init(self): self.label = _("Wait for another update to be complete") self.help = _("wait until the running update is finished") class VariableClUpdateProfileStorage(ReadonlyVariable): type = "object" def get(self): return RepositoryStorageSet( LocalStorage('/var/lib/layman'), CacheStorage('/var/calculate/tmp/update')) class VariableClUpdateRepHost(Variable): type = "list" value = ['calculate'] class VariableClUpdateRepHostUrl(Variable): type = "list" value = ['git://git.calculate.ru/calculate/%s.git'] class VariableClUpdateProfileDatavars(ReadonlyVariable): type = "object" profile = "cl_update_profile_system" profiles_path = "cl_update_profile_path" profiles_shortname = "cl_update_profile_shortname" def get(self): profile = self.Get(self.profile) path_profile = self.Select(self.profiles_path, where=self.profiles_shortname, eq=profile, limit=1) if path_profile: return DataVarsUpdateProfile(path_profile) return "" class VariableClUpdateProfileLinuxFullname(ReadonlyVariable): """ Имя системы в профиле """ def init(self): self.label = _("Distribution name") datavars = "cl_update_profile_datavars" def get(self): dv = self.Get(self.datavars) if dv: try: subname = dv.Get('os_linux_subname') linuxname = dv.Get('os_linux_name') linuxver = dv.Get('os_linux_ver') if subname: return "%s %s %s" % (linuxname, linuxver, subname) return "%s %s" %(linuxname,linuxver) except DataVarsError as s: raise VariableError("Wrong Calculate Linux profile") return "" class VariableClUpdateProfileDependData(ReadonlyTableVariable): """ Зависимые репозитории """ source = ['cl_update_profile_depend_name', 'cl_update_profile_depend_url'] datavars = "cl_update_profile_datavars" def init(self): self.label = _("Used repositories") @staticmethod def url_like(url1, url2): match1 = VariableClUpdateProfileUrl.re_url.search(url1) match2 = VariableClUpdateProfileUrl.re_url.search(url2) if match1 and match2: return match1.group(2).lower() == match2.group(2).lower() return False def get(self, hr=False): dv = self.Get(self.datavars) # TODO: неиспользуемая переменная возможно # испольуется для инициализации #url = self.Get('cl_update_profile_url').lower() if dv: return reversed(zip(dv.Get('cl_update_rep_name'), dv.Get('cl_update_rep_url'))) return "" setValue = Variable.setValue class VariableClUpdateTemplatesLocate(Variable): """ Выбранные типы хранилищ шаблонов """ type = "choice-list" element = "selecttable" opt = ["-T","--templates"] metavalue = "TEMPLATES" untrusted = True check_after = ['cl_update_profile_system'] profile_datevars = "update.cl_update_profile_datavars" descriptionMap = {'overlay': _('Overlay templates'), 'local': _('Local templates'), 'calculate': _("Calculate overlay templates"), 'distros': _('Distribution templates'), 'distro': _('Distribution templates'), 'remote': _('Remote templates'), 'clt': _('clt templates')} def init(self): self.label = _("Templates location") self.help = _("select the location for templates %s") \ %",".join(self.get()) def get(self): dv = self.Get(self.profile_datevars) if dv: return dv.Get('cl_template_location') + ['clt'] else: return self.Get('cl_templates_locate') def choice(self): descr = lambda x: self.descriptionMap.get(x, _("%s overlay templates" % x)) return map(lambda x: (x, descr(x)), self.get()) class VariableClUpdateProfileDependName(FieldValue, ReadonlyVariable): type = "list" source_variable = "cl_update_profile_depend_data" column = 0 def init(self): self.label = _("Name") class VariableClUpdateProfileDependUrl(FieldValue, ReadonlyVariable): type = "list" source_variable = "cl_update_profile_depend_data" column = 1 def init(self): self.label = _("URL") class VariableClUpdateProfileRepName(ReadonlyVariable): type = "list" def get(self): dv = self.Get('cl_update_profile_datavars') if dv: return dv.Get('cl_update_rep_name') return [] class VariableClUpdateProfileSyncRep(ReadonlyVariable): type = "list" def get(self): return list(reversed(self.Get('cl_update_profile_rep_name'))) class VariableClUpdateProfileRepUrl(ReadonlyVariable): type = "list" def get(self): dv = self.Get('cl_update_profile_datavars') if dv: return dv.Get('cl_update_rep_url') return [] class VariableClUpdateProfileLinuxVer(ReadonlyVariable): """ Имя системы в профиле """ def init(self): self.label = _("System profile version") def get(self): dv = self.Get('cl_update_profile_datavars') if dv: return dv.Get('os_linux_ver') return "" class VariableClUpdateProfileLinuxName(ReadonlyVariable): """ Имя системы в профиле """ def get(self): dv = self.Get('cl_update_profile_datavars') if dv: dv.Get('os_linux_name') return "" class VariableClUpdateProfileUrl(Variable): """ URL текущего репозитория """ untrusted = True check_after = ["cl_update_profile_branch"] opt = ["--url"] metavalue = "URL" profile = "cl_profile_system" branch = "cl_update_profile_branch" storage = "cl_update_profile_storage" default_url = "git://git.calculate.ru/calculate/distros.git" profiles_shortname = 'cl_update_profile_shortname' @property def current_root(self): return '/' def init(self): self.label = _("Profile repository") self.help = _("set the profile repository") re_url = re.compile( r"^(?:(%s)://)?(\w[\w\./:-]+?\w)(\.git)?$" % "|".join( ["http", "https", "git"])) re_shortname = re.compile('^(?:([\w\.-]+):)?([\w\.-]+)$') @classmethod def normalize_url(cls, url): match = cls.re_url.match(url) if not match: raise VariableError(_("Wrong repository URL")) url = match.group(2) url = "%s://%s" % (match.group(1) or "git", url) url = "%s.git" % url return url def url_by_shortname(self, value): match = self.re_shortname.match(value) if not match.group(1): template = self.Get('update.cl_update_rep_host_url') if template: template = template[0] else: template = self.Select('update.cl_update_rep_host_url', where='update.cl_update_rep_host', eq=match.group(1), limit=1) if not template: raise VariableError(_("Failed to determine the repository host")) try: return template % match.group(2) except TypeError: raise VariableError(_("Failed to determine the repository host")) def set(self, value): if self.re_shortname.match(value): value = self.url_by_shortname(value) return self.normalize_url(value) def check(self, value): if not value: raise VariableError("Need to specify profile repository") try: branch = self.Get(self.branch) self.Get(self.storage).get_profiles(value, branch) except GitError as e: raise VariableError(str(e)) if not self.Get(self.profiles_shortname): raise VariableError(_("Repository %s has no profiles")%value) def get(self): try: profile = self.Get(self.profile) if profile: while (profile != self.current_root and ".git" not in listDirectory(profile)): profile = path.dirname(profile) if profile == self.current_root: return "" git = Git() return git.get_url(profile, "origin") or "" except: pass return self.default_url class VariableClUpdateProfileRepoName(ReadonlyVariable): def init(self): self.label = _("Repository name") storage = "cl_update_profile_storage" url = "cl_update_profile_url" def get(self): rep_set = self.Get(self.storage) url = self.Get(self.url) rep = rep_set.get_repository(url, branch=None) if rep: return rep.repo_name return "" class VariableClUpdateProfileBranch(Variable): """ Текущий репозиторий """ untrusted = True type = "edit" opt = ["--branch"] metavalue = "BRANCH" storage = "cl_update_profile_storage" url = "cl_update_profile_url" value = DEFAULT_BRANCH def init(self): self.label = _("Repository branch") self.help = _("set the repository branch") def check(self, value): pass ## TODO: проверка ветки #try: # url = self.Get('cl_update_profile_url') # self.Get('cl_update_profile_storage').get_profiles(url, value) #except GitError as e: # raise VariableError(str(e)) class VariableClProfileRepository(ReadonlyVariable): """ Репозиторий из которого будут получены профили """ type = "object" def get(self): try: profile_dn = self.Get('cl_profile_system') while profile_dn != '/' and ".git" not in listDirectory(profile_dn): profile_dn = path.dirname(profile_dn) if profile_dn == '/': return "" ls = LocalStorage(path.dirname(profile_dn)) return ProfileRepository(path.basename(profile_dn), ls) except: return "" class VariableClProfileData(ReadonlyTableVariable): """ Таблица данных о текущих профилях системы """ source = [] repository = "cl_profile_repository" def profile_filter(self, profiles): arch = self.Get('os_arch_machine_gentoo') return [x for x in profiles if x.arch == arch] def get(self, hr=False): rep = self.Get(self.repository) if not rep: return [[]] profiles = rep.get_profiles() if not profiles: return [[]] repo_name = profiles[0].repository.repo_name filtered_profiles = self.profile_filter(profiles) full_name = [x.profile for x in filtered_profiles] profile_path = [x.path for x in filtered_profiles] profile_arch = [x.arch for x in filtered_profiles] short_name = simplify_profiles(full_name) full_name = ["%s:%s" % (repo_name, x) for x in full_name] return zip(full_name, short_name, profile_path, profile_arch) setValue = Variable.setValue class VariableClUpdateProfileRepository(ReadonlyVariable): """ Репозиторий из которого будет извлечён список профилей """ type = "object" url = "cl_update_profile_url" storage = "cl_update_profile_storage" branch = "cl_update_profile_branch" sync_set = "update.cl_update_profile_sync_set" def get(self): url = self.Get(self.url) if not url: return "" try: rep_set = self.Get(self.storage) branch = self.Get(self.branch) rep = rep_set.get_repository(url, branch) if rep and self.Get(self.sync_set) == 'on': rep.sync() return rep_set.get_repository(url, branch) or "" except GitError: return "" class VariableClUpdateProfileRepositoryName(ReadonlyVariable): """ Название репозитория, из которого будут извлечены профили """ def get(self): rep = self.Get('cl_update_profile_repository') if rep: return rep.repo_name return "" class VariableClUpdateProfileData(VariableClProfileData): source = ["cl_update_profile_fullname", "cl_update_profile_shortname", "cl_update_profile_path", "cl_update_profile_arch"] repository = "cl_update_profile_repository" class VariableClUpdateProfileFullname(FieldValue, ReadonlyVariable): """ Полное название профиля """ type = "list" source_variable = "cl_update_profile_data" column = 0 class VariableClUpdateProfileShortname(FieldValue, ReadonlyVariable): """ Упрощенное название профиля """ type = "list" source_variable = "cl_update_profile_data" column = 1 class VariableClUpdateProfilePath(FieldValue, ReadonlyVariable): """ Путь от корня до профиля """ type = "list" source_variable = "cl_update_profile_data" column = 2 class VariableClUpdateProfileArch(FieldValue, ReadonlyVariable): """ Архитектура профиля """ type = "list" source_variable = "cl_update_profile_data" column = 3 class VariableClUpdateProfileSystem(Variable): """ Профиль системы (симлинк /etc/make.profile') """ type = "choice" opt = ["cl_update_profile_system"] untrusted = True metavalue = "PROFILE" profiles_path = "cl_update_profile_path" profiles_shortname = "cl_update_profile_shortname" profiles_fullname = "cl_update_profile_fullname" profiles_arch = "cl_update_profile_arch" profile = "cl_profile_system" url = "cl_update_profile_url" gentoo_arch = 'os_arch_machine_gentoo' def init(self): self.label = _("System profile") self.help = _("set the system profile") def check(self, profile): if not profile: raise VariableError(_("You must specify the profile")) path_profile = self.Select(self.profiles_path, where=self.profiles_shortname, eq=profile, limit=1) profile_fullname = self.Select(self.profiles_fullname, where=self.profiles_shortname, eq=profile, limit=1) if path_profile: dv = DataVarsUpdateProfile(path_profile) if ":" in profile_fullname: repo_name = profile_fullname.partition(":")[0] else: repo_name = "" try: if (not dv.Get('cl_update_rep_name') or not dv.Get('cl_update_rep_url')): raise VariableError( _("Repository variables " "were not configured for the profile")) if not dv.Get('os_linux_name'): raise VariableError("") if repo_name not in list(dv.Get('cl_update_rep_name')): raise VariableError( _("Overlay %s is not specified " "in cl_update_rep_name") % repo_name) except (DataVarsError,VariableError) as e: if str(e): message = ". " + str(e) else: message = "" raise VariableError(_("The selected profile is not Calculate") + message) else: raise VariableError(_("Wrong Calculate profile")) def get(self): try: profile_system = self.Get(self.profile) profile = self.Select(self.profiles_shortname, where=self.profiles_path, eq=profile_system, limit=1) if profile: return profile except VariableError: pass shortname = self.Get(self.profiles_shortname) if len(shortname) == 1: return shortname[0] return "" def choice(self): url = self.Get(self.url) if not url: return [] arch = self.Get(self.gentoo_arch) profiles = zip(*self.Select([self.profiles_shortname, self.profiles_fullname], where=self.profiles_arch, eq=arch)) if profiles: short_name, full_name = profiles return zip(short_name, full_name) return [] class DataVarsUpdateProfile(SimpleDataVars): """ Упрощенная модель переменных для получения данных с удаленного профиля """ source = ['cl_update_rep_name', 'cl_update_rep_url', 'cl_update_rep_path', 'cl_update_rep_rev', 'cl_update_branch_name'] def __init__(self, profile, chroot_path='/', recheck=None): SimpleDataVars.__init__( self, lib_linux.VariableOsLinuxName(), lib_linux.VariableOsLinuxShortname(), lib_linux.VariableOsLinuxSubname(), lib_linux.VariableOsLinuxVer(), lib_linux.VariableClProfileSystem(), env.VariableClRepositoryData(), env.VariableClRepositoryName(), env.VariableClRepositoryLocation(), env.VariableClChrootPath(), env.VariableClTemplateLocation(), env.VariableClTemplatePath(), env.VariableClEmergeConfig(systemRoot=chroot_path), env.VariableClFeatures(), VariableClUpdateRepData(section="update"), VariableClUpdateRepPath(section="update"), VariableClUpdateRepRev(section="update"), VariableClUpdateBranch(section="update"), VariableClUpdateBranchName(section="update"), VariableClUpdateLaymanConfig(section="update"), VariableClUpdateLaymanStorage(section="update"), VariableClUpdateRepName(section="update"), VariableClUpdateRep(section="update"), VariableClUpdateRepUrl(section="update"), VariableClUpdateBinhost(section="update"), VariableClUpdateBinhostData(section="update"), VariableClUpdateBinhostHost(section="update"), VariableClUpdateBinhostRecheckSet(section="update"), VariableClUpdateBinhostRevisions(section="update"), VariableClUpdateBinhostTime(section="update"), VariableClUpdateBinhostTimeout(section="update"), VariableClUpdateBinhostTimestampPath(section="update"), VariableClUpdateBinhosts(section="update"), VariableClUpdateBinhostRevisionPath(section="update"), ) # TODO: при переключении профиля использовать master ветки self.cache['cl_profile_system'] = profile self.cache['cl_chroot_path'] = chroot_path if recheck is not None: self.cache['cl_update_binhost_recheck_set'] = recheck self.flIniFileFrom(profile) def __repr__(self): return "Profile variables" class VariableClUpdateProfileSyncSet(Variable): """ Синхронизировать репозиторий перед сменой профиля """ type = "bool" value = "off" opt = ["-u", "--update-cache"] def init(self): self.label = _("Update the cache") self.help = _("Update the cache") class VariableClUpdateAutocheckSet(Variable): """ Выполнять/невыполнять автопроверку обновлений """ type = "bool" value = "on" opt = ["-a", "--autocheck"] def init(self): self.label = _("Automatically check updates") self.help = _("automatically check updates") class VariableClUpdateAutocheckInterval(Variable): """ Интервал выполнения проверки """ type = "choiceedit" opt = ["-I", "--autocheck-interval"] metavalue = "INTERVAL" def init(self): self.label = _("Interval for the updates checking") self.help = _("set interval for the updates checking") def choice(self): return [["6h",_("every six hours")], ["12h",_("every twelve hours")], ["1d",_("daily")]] class VariableClUpdateAutocheckScheduleSet(Variable): """ Запустить проверку только если со времени последнего запуска прошло необходимое время """ type = "bool" value = "off" opt = ["--schedule"] def init(self): self.label = _("Consider the autocheck schedule") self.help = _("consider the autocheck schedule") class VariableClUpdateEmergelistSet(Variable): """ Вывести список пакетов в формате emerge """ type = "bool" value = "off" opt = ["-e","--emergelist"] def init(self): self.label = _("Emerge-like packages list") self.help = _("display the packages list in emerge format") class VariableClUpdateKernelVersion(ReadonlyVariable): """ Текущая версия ядра """ def get(self): return process('/bin/uname','-r').read().strip() class VariableClUpdateKernelSrcPath(ReadonlyVariable): """ Каталог содержащий исходный код текущего ядра """ def get(self): kernel_ver = self.Get('cl_update_kernel_version') for template_path in ("/lib/modules/%s/build", "/usr/src/linux-%s"): src_path = template_path % kernel_ver if path.exists(src_path): if path.islink(src_path): return os.readlink(src_path) else: return src_path else: return "" class VariableClUpdateKernelPkg(ReadonlyVariable): """ Пакет текущего ядра """ def get(self): src_path = self.Get('cl_update_kernel_src_path') if src_path: qfile = process('/usr/bin/qfile', '-vC', src_path) if qfile.success(): return qfile.read().partition(" ")[0] return "" class VariableClUpdateLinesLimit(Variable): """ Количество выводимых строк при ошибке """ type = "int" value = "30" class VariableClUpdateSkipSetupSet(Variable): """ Пропустить выполнение cl-setup-system в cl-update-profile """ type = "bool" value = "off" opt = ["--skip-setup-system"] def init(self): self.label = _("Skip the system setup") self.help = _("skip the system setup") class VariableClUpdateCleanpkgSet(Variable): """ Пропустить выполнение cl-setup-system в cl-update-profile """ type = "bool" value = "off" opt = ["--clean-pkg"] def init(self): self.label = _("Clean obsolete programs archives") self.help = _("clean obsolete programs archives") class VariableClUpdateOutdatedKernelPath(Variable): """ Файл-флаг наличия устаревшего, неудаленного ядра """ value = "/var/lib/calculate/calculate-update/outdated_kernel" class VariableClUpdateSkipRbSet(Variable): """ Пропусить revdep-rebuild """ type = "bool" value = "off" opt = ["-R", "--skip-revdep-rebuild"] def init(self): self.label = _("Skip reverse dependencies check") self.help = _("skip reverse dependencies check") class VariableClUpdateOutdatedKernelSet(ReadonlyVariable): """ Есть наличие устаревшего ядра """ type = "bool" def get(self): ui = UpdateInfo(self.parent) return "on" if ui.outdated_kernel else "off" class VariableClUpdateBinhosts(Variable): """ Список хостов с бинарными обновлениями """ type = "list" value = ["ftp://ftp.calculate.ru/pub/calculate"] class VariableClUpdateBinhost(Variable): """ Хост с бинарными обновлениями """ value = "" class VariableClUpdateBinhostRevisionPath(Variable): """ Путь до revisions файлов """ type = "list" value = [ "grp/default/ini.env", "grp/kde/ini.env", "grp/server/ini.env", "grp/x/ini.env" ] class VariableClUpdateBinhostTimestampPath(Variable): """ Путь до файла timestamp """ value = "timestamp" class VariableClUpdateBinhostTimeout(Variable): """ Таймаут на проверку одного binhost """ type = "int" value = "5"