|
|
|
|
#-*- 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
|
|
|
|
|
from os import path
|
|
|
|
|
from itertools import *
|
|
|
|
|
from calculate.lib.datavars import (TableVariable,Variable,ReadonlyVariable,
|
|
|
|
|
VariableError)
|
|
|
|
|
import calculate.lib.cl_template as cl_template
|
|
|
|
|
from calculate.lib.utils.files import listDirectory,process,PIPE,pathJoin
|
|
|
|
|
|
|
|
|
|
from calculate.lib.cl_lang import setLocalTranslate
|
|
|
|
|
setLocalTranslate('cl_lib3',sys.modules[__name__])
|
|
|
|
|
|
|
|
|
|
_envData = [('system', '/etc/calculate/calculate.env'),
|
|
|
|
|
('local', '/var/calculate/calculate.env'),
|
|
|
|
|
('remote', '/var/calculate/remote/calculate.env')]
|
|
|
|
|
|
|
|
|
|
class VariableClEnvData(TableVariable):
|
|
|
|
|
"""
|
|
|
|
|
Aliases and path to ini files
|
|
|
|
|
"""
|
|
|
|
|
source = ["cl_env_location","cl_env_path"]
|
|
|
|
|
|
|
|
|
|
class VariableClEnvLocation(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Aliases to ini files (from cl_env_data)
|
|
|
|
|
"""
|
|
|
|
|
type = 'list'
|
|
|
|
|
value = list(zip(*_envData)[0])
|
|
|
|
|
|
|
|
|
|
class VariableClEnvPath(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Path to ini files (from cl_env_data)
|
|
|
|
|
"""
|
|
|
|
|
type = 'list'
|
|
|
|
|
value = list(zip(*_envData)[1])
|
|
|
|
|
|
|
|
|
|
class VariableClTemplateData(TableVariable):
|
|
|
|
|
"""
|
|
|
|
|
Aliases to templates path
|
|
|
|
|
"""
|
|
|
|
|
source = ["cl_template_location","cl_template_path"]
|
|
|
|
|
|
|
|
|
|
class VariableClTemplateLocation(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Name to templates
|
|
|
|
|
"""
|
|
|
|
|
type = 'list'
|
|
|
|
|
value = ["overlay","local","remote"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VariableClTemplatePath(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Path to information file on server
|
|
|
|
|
"""
|
|
|
|
|
type = 'list'
|
|
|
|
|
value = ["/var/lib/layman/calculate/profiles/templates",
|
|
|
|
|
"/var/calculate/templates",
|
|
|
|
|
"/var/calculate/remote/templates"]
|
|
|
|
|
|
|
|
|
|
class VariableClEnvServerPath(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Path to server environment
|
|
|
|
|
"""
|
|
|
|
|
value = '/var/calculate/remote/server.env'
|
|
|
|
|
|
|
|
|
|
class VariableClTemplateCltPath(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Paths to clt-template files
|
|
|
|
|
"""
|
|
|
|
|
type = 'list'
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
"""
|
|
|
|
|
Clt templates path is /etc and CONFIG_PROTECT
|
|
|
|
|
"""
|
|
|
|
|
chroot = self.Get('cl_chroot_path')
|
|
|
|
|
if "CONFIG_PROTECT" in os.environ:
|
|
|
|
|
protectPaths = ["/etc"] + filter(lambda x: x.strip(),
|
|
|
|
|
os.environ["CONFIG_PROTECT"].split(" "))
|
|
|
|
|
else:
|
|
|
|
|
protectPaths = ["/etc", "/usr/share/X11/xkb", "var/lib/hsqldb",
|
|
|
|
|
"/usr/share/config"]
|
|
|
|
|
return filter(path.exists,
|
|
|
|
|
map(lambda x:pathJoin(chroot,x),
|
|
|
|
|
protectPaths))
|
|
|
|
|
|
|
|
|
|
class VariableClRootPath(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Path to directory relative which perform joining templates to system files
|
|
|
|
|
(sandbox)
|
|
|
|
|
"""
|
|
|
|
|
value = '/'
|
|
|
|
|
|
|
|
|
|
class VariableClRootPathNext(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Path to directory relative which perform joining templates to system files
|
|
|
|
|
(sandbox). This set for configure packages specified throug merge=
|
|
|
|
|
"""
|
|
|
|
|
def get(self):
|
|
|
|
|
return self.Get('cl_root_path')
|
|
|
|
|
|
|
|
|
|
class VariableClChrootPath(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Path to directory which contain other system
|
|
|
|
|
"""
|
|
|
|
|
value = '/'
|
|
|
|
|
|
|
|
|
|
class VariableClPassStep(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Pass for templates join 1,2,3,4,5 and etc
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
class VariableClPassFile(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Template file performed at now
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
class VariableClMergeSet(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Force by package template appling
|
|
|
|
|
"""
|
|
|
|
|
type = "bool"
|
|
|
|
|
value = "off"
|
|
|
|
|
|
|
|
|
|
class VariableClMergePkg(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
This variable work with template function belong(package_name)
|
|
|
|
|
if the variable is defined then will use only template, which
|
|
|
|
|
has package_name in belong equal value of this variable or
|
|
|
|
|
hasn't belong function
|
|
|
|
|
(package_name == value of cl_belong_pkg)
|
|
|
|
|
"""
|
|
|
|
|
type = "list"
|
|
|
|
|
def get(self):
|
|
|
|
|
return self.Get('cl_belong_pkg')
|
|
|
|
|
|
|
|
|
|
class VariableClMergePkgNew(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
New variable value for cl_merge_pkg
|
|
|
|
|
"""
|
|
|
|
|
type = "list"
|
|
|
|
|
|
|
|
|
|
class VariableClMergePkgPass(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Performed packages
|
|
|
|
|
"""
|
|
|
|
|
type = "list"
|
|
|
|
|
|
|
|
|
|
class VariableClBelongPkg(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Depricated by cl_merge_pkg
|
|
|
|
|
"""
|
|
|
|
|
type = "list"
|
|
|
|
|
|
|
|
|
|
class VariableClAction(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Program action
|
|
|
|
|
Example: install, uninstall, merge, domain, undomain, system, desktop
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
class VariableClPassState(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Program state
|
|
|
|
|
specifies addition to cl_pass_action for needing
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
class VariableClMerges(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Programs have templates setup
|
|
|
|
|
"""
|
|
|
|
|
type = 'list'
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
def set(self,value):
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
class VariableClAutoupdateSet(Variable):
|
|
|
|
|
"""
|
|
|
|
|
(on or off) autoupdate config from install program
|
|
|
|
|
"""
|
|
|
|
|
type = 'bool'
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
if self.Get('cl_dispatch_conf') == 'usenew':
|
|
|
|
|
return "on"
|
|
|
|
|
else:
|
|
|
|
|
return "off"
|
|
|
|
|
|
|
|
|
|
class VariableClHumanEditSet(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Параметр для отметки "ручной правки"
|
|
|
|
|
"""
|
|
|
|
|
type = "bool"
|
|
|
|
|
opt = ["--human-edit"]
|
|
|
|
|
value = "off"
|
|
|
|
|
|
|
|
|
|
def init(self):
|
|
|
|
|
self.help = _("mark as human modification")
|
|
|
|
|
self.label = _("Mark as human modification")
|
|
|
|
|
|
|
|
|
|
class VariableClProtectUseSet(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Использовать portage интеграцию с конфигурационными файлами
|
|
|
|
|
"""
|
|
|
|
|
type = "bool"
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
return "on" if self.Get('cl_human_edit_set') == 'off' else "off"
|
|
|
|
|
|
|
|
|
|
class VariableClDispatchConf(Variable):
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
type = "choice"
|
|
|
|
|
opt = ["--conf"]
|
|
|
|
|
value = "dispatch"
|
|
|
|
|
syntax = "--{choice}-conf"
|
|
|
|
|
metavalue = "METHOD"
|
|
|
|
|
|
|
|
|
|
def init(self):
|
|
|
|
|
self.help = "'usenew' - " +_("use the new config files") +\
|
|
|
|
|
",\n'skip' - " + _("skip the update of config files") +\
|
|
|
|
|
",\n'dispatch' - " + _("manually update config files")
|
|
|
|
|
self.label = _("Method for updating config files")
|
|
|
|
|
|
|
|
|
|
def choice(self):
|
|
|
|
|
return [("usenew",_("Use the new config files")),
|
|
|
|
|
("skip",_("Skip the update of config files")),
|
|
|
|
|
("dispatch",_("Manually update config files"))]
|
|
|
|
|
|
|
|
|
|
class VariableClWsdl(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Packages with wsdl
|
|
|
|
|
"""
|
|
|
|
|
type = "list-choice"
|
|
|
|
|
|
|
|
|
|
def choice(self):
|
|
|
|
|
return self.Get('cl_wsdl_available')
|
|
|
|
|
|
|
|
|
|
class VariableClWsdlAvailable(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Packages which has wsdl interfaces
|
|
|
|
|
"""
|
|
|
|
|
type = "list"
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
sitePackages = map(lambda x:path.join(x,"calculate"),
|
|
|
|
|
filter(lambda x:x.endswith('site-packages') and \
|
|
|
|
|
x.startswith('/usr/lib'),sys.path))
|
|
|
|
|
retList = []
|
|
|
|
|
for module,modDir in chain(*map(lambda x:map(lambda y:(path.basename(y),y),
|
|
|
|
|
listDirectory(x,True,True)),sitePackages)):
|
|
|
|
|
if path.exists(path.join(modDir,"wsdl_%s.py"%module)):
|
|
|
|
|
if not "calculate-%s"%module in retList:
|
|
|
|
|
retList.append("calculate-%s"%module)
|
|
|
|
|
return retList
|
|
|
|
|
|
|
|
|
|
class VariableClConfigProtectMask(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Value of CONFIG_PROTECT after source /etc/profile, and /etc append
|
|
|
|
|
"""
|
|
|
|
|
type = "list"
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
displayEnv = process('/bin/bash',"-c","source /etc/profile;env",
|
|
|
|
|
stdout=PIPE)
|
|
|
|
|
for line in displayEnv:
|
|
|
|
|
if line.startswith("CONFIG_PROTECT_MASK="):
|
|
|
|
|
configProtectMask=line.rstrip().partition('=')[2].split()
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
configProtectMask = []
|
|
|
|
|
return configProtectMask
|
|
|
|
|
|
|
|
|
|
class VariableClConfigProtect(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Value of CONFIG_PROTECT after source /etc/profile, and /etc append
|
|
|
|
|
"""
|
|
|
|
|
type = "list"
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
displayEnv = process('/bin/bash',"-c","source /etc/profile;env",
|
|
|
|
|
stdout=PIPE)
|
|
|
|
|
for line in displayEnv:
|
|
|
|
|
if line.startswith("CONFIG_PROTECT="):
|
|
|
|
|
configProtect=line.rstrip().partition('=')[2].split()
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
configProtect = []
|
|
|
|
|
configProtect.append('/etc')
|
|
|
|
|
return configProtect
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VariableClVerboseSet(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Verbose output variable
|
|
|
|
|
"""
|
|
|
|
|
type = "bool"
|
|
|
|
|
opt = ["-v", "--verbose"]
|
|
|
|
|
value = "off"
|
|
|
|
|
|
|
|
|
|
def init(self):
|
|
|
|
|
self.help = _("verbose output")
|
|
|
|
|
self.label = _("Verbose output")
|
|
|
|
|
|
|
|
|
|
class VariableClEbuildPhase(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Current ebuild phase
|
|
|
|
|
"""
|
|
|
|
|
def get(self):
|
|
|
|
|
return os.environ.get("EBUILD_PHASE","")
|
|
|
|
|
|
|
|
|
|
class VariableClEmergeInfo(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Emerge --info cache
|
|
|
|
|
"""
|
|
|
|
|
type = "list"
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
return filter(lambda x:x.startswith('PORTDIR_OVERLAY=') or \
|
|
|
|
|
x.startswith('EMERGE') or \
|
|
|
|
|
x.startswith('PORTDIR='),
|
|
|
|
|
process("/usr/bin/emerge","--ask=n","--info",
|
|
|
|
|
envdict=os.environ).read().split('\n'))
|
|
|
|
|
|
|
|
|
|
class VariableClPortdirOverlay(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Overlays path
|
|
|
|
|
"""
|
|
|
|
|
type = "list"
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
emergeInfo = self.Get('cl_emerge_info')
|
|
|
|
|
for line in filter(lambda x:x.startswith("PORTDIR_OVERLAY="),
|
|
|
|
|
emergeInfo):
|
|
|
|
|
return filter(None,
|
|
|
|
|
line.partition("=")[2].strip('\n"\'').split(' '))
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
class VariableClEmergeDefaultOpts(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
EMERGE_DEFAULT_OPTS
|
|
|
|
|
"""
|
|
|
|
|
type = "list"
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
emergeInfo = self.Get('cl_emerge_info')
|
|
|
|
|
for line in filter(lambda x:x.startswith("EMERGE_DEFAULT_OPTS="),
|
|
|
|
|
emergeInfo):
|
|
|
|
|
return filter(None,
|
|
|
|
|
line.partition("=")[2].strip('\n"\'').split(' '))
|
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
class VariableClTemplatesLocate(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Выбранные типы хранилищ шаблонов
|
|
|
|
|
"""
|
|
|
|
|
type = "choice-list"
|
|
|
|
|
#value = ['overlay','local','remote','clt']
|
|
|
|
|
element = "selecttable"
|
|
|
|
|
opt = ["-T","--templates"]
|
|
|
|
|
metavalue = "TEMPLATES"
|
|
|
|
|
untrusted = True
|
|
|
|
|
|
|
|
|
|
descriptionMap = {'overlay': _('Overlay templates'),
|
|
|
|
|
'local': _('Local templates'),
|
|
|
|
|
'distro': _('Distribution templates'),
|
|
|
|
|
'remote': _('Remote templates'),
|
|
|
|
|
'clt': _('clt templates')}
|
|
|
|
|
|
|
|
|
|
def init(self):
|
|
|
|
|
self.label = _("Templates location")
|
|
|
|
|
self.help = _("select location for templates %s") \
|
|
|
|
|
%",".join(self.get())
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
vals = \
|
|
|
|
|
self.Get('cl_template_location')[:len(self.Get('cl_template_path'))]
|
|
|
|
|
if self.Get('cl_action') == 'desktop':
|
|
|
|
|
return vals
|
|
|
|
|
else:
|
|
|
|
|
return vals + ['clt']
|
|
|
|
|
|
|
|
|
|
def choice(self):
|
|
|
|
|
return map(lambda x:(x,self.descriptionMap.get(x,x)),
|
|
|
|
|
self.get())
|
|
|
|
|
|
|
|
|
|
class VariableClTemplatePathUse(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Пути до шаблонов, используемых в настройке системы или профиля пользователя
|
|
|
|
|
"""
|
|
|
|
|
type = 'list'
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
return self.Select('cl_template_path',where='cl_template_location',
|
|
|
|
|
_in=self.Get('cl_templates_locate'))
|
|
|
|
|
|
|
|
|
|
class VariableClTemplateCltSet(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Использовать clt шаблоны для настройки системы
|
|
|
|
|
"""
|
|
|
|
|
def get(self):
|
|
|
|
|
return "on" if "clt" in self.Get('cl_templates_locate') else "off"
|
|
|
|
|
|
|
|
|
|
class VariableClEnvDebugSet(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Переменная для включения отладки
|
|
|
|
|
"""
|
|
|
|
|
type = "bool"
|
|
|
|
|
value = "on"
|
|
|
|
|
|
|
|
|
|
class VariableClMakeProfile(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Путь до актуального make.profile
|
|
|
|
|
"""
|
|
|
|
|
systemRoot = "/"
|
|
|
|
|
|
|
|
|
|
def get_work_link(self, *links):
|
|
|
|
|
for link in links:
|
|
|
|
|
if path.exists(link):
|
|
|
|
|
return link
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
files = ["etc/portage/make.profile", "etc/make.profile"]
|
|
|
|
|
val = self.get_work_link(
|
|
|
|
|
*[path.join(self.systemRoot, x) for x in files])
|
|
|
|
|
if not val:
|
|
|
|
|
raise VariableError(
|
|
|
|
|
_("Failed to detect the system profile.") + " " +
|
|
|
|
|
_("Select the profile with command {cmd}").format(
|
|
|
|
|
cmd="cl-update-profile"))
|
|
|
|
|
return val
|