Множественные изменения

Mike Khiretskiy 9 years ago
parent 22703407d2
commit 08bbdc6142

@ -20,6 +20,7 @@ import os
import sys import sys
from os import path from os import path
from calculate.lib.datavars import SimpleDataVars, Variable
from calculate.install.distr import Distributive from calculate.install.distr import Distributive
from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate, _) from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate, _)
import time import time
@ -33,13 +34,33 @@ from .datavars import builder_data
setLocalTranslate('cl_builder3', sys.modules[__name__]) setLocalTranslate('cl_builder3', sys.modules[__name__])
__ = getLazyLocalTranslate(_) __ = getLazyLocalTranslate(_)
UTF8 = 'utf-8'
class Build(object): class Build(object):
""" """
Сборка Сборка
""" """
class Status(object): class Status(object):
WORKED, REGISTERED, REMOVED, BROKEN, UNREGISTERED = range(5) Worked, Registered, Removed, Broken, Unregistered = range(5)
class Parameter(object):
HashId = "hash"
Directory = "directory"
PkgDir = "pkgdir"
References = "references"
types = {HashId: Variable.Types.String,
Directory: Variable.Types.String,
References: Variable.Types.List,
PkgDir: Variable.Types.String,
}
attrs = {'pkgdir': PkgDir,
'references': References}
class Branches:
Stable = "master"
Unstable = "update"
def __init__(self, build_id, distributive, parent, restore=False): def __init__(self, build_id, distributive, parent, restore=False):
""" """
@ -50,10 +71,12 @@ class Build(object):
self.parent = parent self.parent = parent
self.id = build_id self.id = build_id
self.pkgdir = "" self.pkgdir = ""
self.default_branch = Build.Branches.Stable
self.references = []
self._hash = None self._hash = None
if not restore: if not restore:
self.parent.reserve_id(self.id) self.parent.reserve_id(self.id)
self.status = Build.Status.REGISTERED self.status = Build.Status.Registered
@property @property
def build_hash(self): def build_hash(self):
@ -65,14 +88,17 @@ class Build(object):
self._hash = hash_info self._hash = hash_info
return self._hash return self._hash
def set_overlays(self, overlays):
self.references = [self.default_branch for x in overlays]
@property @property
def directory(self): def directory(self):
return self.distributive.getDirectory() return self.distributive.getDirectory()
def generate_hash_id(self): def generate_hash_id(self):
assemble_name = (self.id + assemble_name = (self.id +
self.distributive.getType().decode('utf-8') self.distributive.getType().decode(UTF8)
+ unicode(time.time())).encode('utf-8') + unicode(time.time())).encode(UTF8)
return hashlib.sha1(assemble_name).hexdigest() return hashlib.sha1(assemble_name).hexdigest()
def save(self): def save(self):
@ -80,16 +106,16 @@ class Build(object):
Сохранить сборку Сохранить сборку
""" """
self.parent.save_build(self) self.parent.save_build(self)
self.status = Build.Status.WORKED self.status = Build.Status.Worked
def remove(self): def remove(self):
""" """
Удалить сборку Удалить сборку
""" """
if self.status in (Build.Status.REGISTERED, Build.Status.WORKED, if self.status in (Build.Status.Registered, Build.Status.Worked,
Build.Status.BROKEN): Build.Status.Broken):
self.parent.remove_build(self) self.parent.remove_build(self)
self.status = Build.Status.REMOVED self.status = Build.Status.Removed
self.id = None self.id = None
self._hash = None self._hash = None
@ -129,7 +155,7 @@ class BuildStorage(object):
def _get_ini(self): def _get_ini(self):
ini = ConfigParser() ini = ConfigParser()
ini.read(self.ini_file, encoding='utf-8') ini.read(self.ini_file, encoding=UTF8)
return ini return ini
def _get_ini_with_lock(self): def _get_ini_with_lock(self):
@ -166,14 +192,15 @@ class BuildStorage(object):
:param build: сборка :param build: сборка
:return: :return:
""" """
build_directory = build.distributive.getDirectory()
build_id = build.id build_id = build.id
build_hash = build.build_hash d = {Build.Parameter.Directory: build.distributive.getDirectory(),
build_pkgdir = build.pkgdir Build.Parameter.HashId: build.build_hash}
for k, v in Build.Parameter.attrs.items():
d[v] = SimpleDataVars.serialize(Build.Parameter.types[v],
getattr(build, k))
with self.modify_ini() as ini: with self.modify_ini() as ini:
ini[build_id]['hash'] = build_hash for k, v in d.items():
ini[build_id]['directory'] = build_directory ini[build_id][k] = v
ini[build_id]['pkgdir'] = build_pkgdir
mount_dump_file = self.get_dump_name(build.build_hash) mount_dump_file = self.get_dump_name(build.build_hash)
with writeFile(mount_dump_file) as f: with writeFile(mount_dump_file) as f:
@ -190,7 +217,8 @@ class BuildStorage(object):
:return: :return:
""" """
ini = self._get_ini_with_lock() ini = self._get_ini_with_lock()
hashes = [ini.get(x, 'hash', fallback="").encode('utf-8') for x in ini] hashes = [ini.get(x, Build.Parameter.HashId,
fallback="").encode(UTF8) for x in ini]
for fn in listDirectory(self.data_dir): for fn in listDirectory(self.data_dir):
if fn not in hashes: if fn not in hashes:
try: try:
@ -200,7 +228,7 @@ class BuildStorage(object):
def __iter__(self): def __iter__(self):
ini = self._get_ini_with_lock() ini = self._get_ini_with_lock()
return iter([x.encode('utf-8') for x in ini if x != 'DEFAULT']) return iter([x.encode(UTF8) for x in ini if x != 'DEFAULT'])
def clear_unmounted(self): def clear_unmounted(self):
""" """
@ -209,22 +237,23 @@ class BuildStorage(object):
:return: :return:
""" """
with self.modify_ini() as ini: with self.modify_ini() as ini:
dist_dirs = [(x.encode('utf-8'), dist_dirs = [(x.encode(UTF8),
ini.get(x, 'directory', ini.get(x, Build.Parameter.Directory,
fallback="").encode('utf-8')) fallback="").encode(UTF8))
for x in ini.keys()] for x in ini.keys()]
for k, v in dist_dirs: for k, v in dist_dirs:
if v is None or not isMount(v): if v is None or not isMount(v):
ini.remove_section(k) ini.remove_section(k)
def get_build_hash(self, build_id): def get_build_hash(self, build_id):
return self._get_ini_with_lock().get(build_id, 'hash', fallback=None) return self._get_ini_with_lock().get(build_id, Build.Parameter.HashId,
fallback=None)
def get_build(self, build_id): def get_build(self, build_id):
ini = self._get_ini_with_lock() ini = self._get_ini_with_lock()
build_hash = ini.get(build_id, 'hash', fallback=None) build_hash = ini.get(build_id, Build.Parameter.HashId, fallback=None)
if build_hash: if build_hash:
build_dir = ini.get(build_id, 'directory') build_dir = ini.get(build_id, Build.Parameter.Directory)
data = readFile(self.get_dump_name(build_hash)) data = readFile(self.get_dump_name(build_hash))
if data: if data:
try: try:
@ -236,10 +265,14 @@ class BuildStorage(object):
build = Build(build_id, dist, self, restore=True) build = Build(build_id, dist, self, restore=True)
proc_build_dir = path.join(build_dir, 'proc') proc_build_dir = path.join(build_dir, 'proc')
if isMount(build_dir) and isMount(proc_build_dir): if isMount(build_dir) and isMount(proc_build_dir):
build.status = build.Status.WORKED build.status = build.Status.Worked
else: else:
build.status = build.Status.BROKEN build.status = build.Status.Broken
build.pkgdir = ini.get(build_id, 'pkgdir', fallback=None) for param_name, ini_name in Build.Parameter.attrs.items():
value = ini.get(build_id, ini_name, fallback="")
value = SimpleDataVars.unserialize(
Build.Parameter.types[ini_name], value)
setattr(build, param_name, value)
return build return build
def remove_build(self, build): def remove_build(self, build):

@ -13,23 +13,42 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from itertools import chain
import sys import sys
import time
from calculate.lib.datavars import DataVars
from calculate.lib.utils.colortext import TextState, get_color_print, \
convert_console_to_xml
from calculate.lib.utils.files import (
pathJoin, PercentProgress, getProgPath, process, STDOUT, removeDir,
makeDirectory, writeFile, readLinesFile, chmod, chown, FilePermission,
find, FindFileType, removeFileWithEmptyDirectory,
copyWithPath)
from calculate.lib.utils.portage import Layman, EmergeLog, EmergeLogNamedTask, \
InstalledPackageInfo, EbuildInfoError, EbuildInfo, ChrootEix
from calculate.update.emerge_parser import EmergeParser, \
EmergeError, ChrootEmergeCommand, ChrootCommandExecutor
from .build_storage import Build from .build_storage import Build
from calculate.update.update import Update
from calculate.install.distr import Distributive from calculate.install.distr import Distributive
import os
from os import path from os import path
from .datavars import BuilderError from .datavars import BuilderError
from .emerge_fetch import EmergeFetcher, EmergeFetcherError
from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate, _) from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate, _)
setLocalTranslate('cl_builder3', sys.modules[__name__]) setLocalTranslate('cl_builder3', sys.modules[__name__])
__ = getLazyLocalTranslate(_) __ = getLazyLocalTranslate(_)
class Builder(object): class Builder(Update):
"""Основной объект для выполнения действий связанных со сборкой системы """Основной объект для выполнения действий связанных со сборкой системы
""" """
def init(self): def init(self):
pass self.pretend_package_list = {}
self.update_map = {}
self.color_print = get_color_print()
def mount_target(self, target): def mount_target(self, target):
dir_distro = target.convertToDirectory() dir_distro = target.convertToDirectory()
@ -65,8 +84,11 @@ class Builder(object):
build.restore() build.restore()
return True return True
def save_build(self, build): def save_build(self, build, dv):
build.pkgdir = self.clVars.Get('cl_builder_pkgdir') build.pkgdir = self.clVars.Get('cl_builder_pkgdir')
if dv:
overlays = dv.Get('cl_update_rep_name')
build.set_overlays(overlays)
build.save() build.save()
return True return True
@ -87,3 +109,567 @@ class Builder(object):
def prepare_image(self, image): def prepare_image(self, image):
image.eventPrepareIso.connect(self.prepare_iso) image.eventPrepareIso.connect(self.prepare_iso)
return True return True
#def test_builder(self):
# path_chroot = self.clVars.Get('cl_builder_path')
# d1 = dict(zip(
# map(lambda x: pathJoin(path_chroot, x),
# self.clVars.Get('cl_builder_repository_location')),
# self.clVars.Get('cl_builder_repository_name')))
# print d1
# d2 = dict(zip(self.clVars.Get('update.cl_update_rep_path'),
# self.clVars.Get('update.cl_update_rep_name')))
# print d2
# print "!!!!!!",self.clVars.Get('cl_builder_linux_datavars').Get('cl_update_rep_path')
# print "!!!!!!",self.clVars.Get('cl_builder_profile_datavars').Get('cl_update_rep_path')
# return True
def remove_repositories(self, repname):
dv = self.clVars.Get('cl_builder_linux_datavars')
rpath = dv.Select("cl_update_rep_path",
where="cl_update_rep_name", eq=repname, limit=1)
chroot_path = path.normpath(self.clVars.Get('cl_chroot_path'))
rpath_orig = rpath[len(chroot_path):]
layman = Layman(self.clVars.Get('update.cl_update_layman_installed'),
self.clVars.Get('update.cl_update_layman_make'),
self.clVars.Get('update.cl_update_layman_conf'))
if repname != "portage":
layman.remove(repname, rpath_orig)
removeDir(rpath)
return True
def set_profile(self, profile_shortname, chroot_path):
profile = self.clVars.Select('cl_builder_profile_path',
where='cl_builder_profile_shortname',
eq=profile_shortname, limit=1)
if not profile:
raise BuilderError(_("Failed to determine profile %s") %
profile_shortname)
chroot_join = lambda x: path.join(chroot_path, x)
profile_path = path.relpath(profile, chroot_join('etc/portage'))
try:
for rm_fn in filter(path.lexists,
(chroot_join('etc/make.profile'),
chroot_join('etc/portage/make.profile'))):
os.unlink(rm_fn)
os.symlink(profile_path, chroot_join('etc/portage/make.profile'))
except (OSError,IOError) as e:
print str(e)
raise BuilderError(_("Failed to set the profile: %s")%str(e))
return True
def apply_templates(self,target=None,useClt=None,cltFilter=False,root=None,
useDispatch=True, action="merge", distro_dv=None):
"""
Применить шаблоны.
Args:
target: дистрибутив, куда необходимо выполнить шаблоны (/ по умолчанию)
useClt: использовать clt шаблоны
cltFilter: применять фильтр на clt шаблоны
root: каталог, куда будут наложны шаблоны (cl_root_path)
"""
from calculate.lib.cl_template import (TemplatesError,
ProgressTemplate)
if target is None:
chroot = '/'
elif isinstance(target, Distributive):
chroot = target.getDirectory()
else:
chroot = target
if root is None:
root = '/'
elif isinstance(root, Distributive):
root = root.getDirectory()
clVars = DataVars()
clTempl = None
try:
clVars.importData()
# TODO: использование параметра -T
if distro_dv:
clVars.Set('cl_template_path_use',
[pathJoin(chroot, x) for x in distro_dv.Get('cl_template_path')],
force=True)
clVars.Set('cl_env_path',
[pathJoin(chroot, x) for x in clVars.Get('cl_env_path')],
force=True)
clVars.Set('cl_make_profile', path.join(chroot,
'etc/portage/make.profile'), force=True)
clVars.Set('cl_action', action, force=True)
clVars.Set('cl_verbose_set', self.clVars.Get('cl_verbose_set'))
clVars.Set('cl_chroot_status', 'on', force=True)
#clVars.Set("cl_dispatch_conf", self.clVars.Get('cl_dispatch_conf'),
# force=True)
clVars.flIniFile()
cltFilter=True if cltFilter in (True,"on") else False
clVars.Set("cl_chroot_path", chroot, True)
clVars.Set("cl_root_path", root, True)
# определение каталогов содержащих шаблоны
dirs_list, files_list = ([],[])
useClt = useClt in ("on", True)
self.addProgress()
nullProgress = lambda *args,**kw:None
dispatch = self.dispatchConf if useDispatch else None
clTempl = ProgressTemplate(nullProgress,clVars,
cltObj=useClt,
cltFilter=cltFilter,
printSUCCESS=self.printSUCCESS,
printWARNING=self.printWARNING,
askConfirm=self.askConfirm,
dispatchConf=dispatch,
printERROR=self.printERROR)
def execute_command(cmd, lang):
chroot_cmd = getProgPath("/usr/bin/chroot", )
chroot_path = self.clVars.Get('cl_builder_path')
return process(chroot_cmd, chroot_path,
cmd, lang=lang, envdict=dict(os.environ))
# замена выполения команд: вместо оычного запуска - запуск через
# /usr/bin/chroot
clTempl.execute_command = execute_command
clTempl.applyTemplates()
if clTempl.hasError():
if clTempl.getError():
raise TemplatesError(clTempl.getError())
finally:
clVars.close()
if clTempl:
if clTempl.cltObj:
clTempl.cltObj.closeFiles()
clTempl.closeFiles()
return True
def get_prog_path(self, progname):
chroot_path = self.clVars.Get('builder.cl_builder_path')
return getProgPath(progname, chroot_path)
def _eixUpdateCommand(self, eix_cmd, countRep):
chroot_path = self.clVars.Get('cl_builder_path')
return PercentProgress("/usr/bin/chroot", chroot_path, eix_cmd,
"-F", part=countRep or 1, atty=True)
def regenCache(self, repname):
with self.clVars.useDefaultModule("update"):
return super(Builder, self).regenCache(repname)
def syncRepositories(self, repname, clean_on_error=True):
with self.clVars.useDefaultModule("update"):
return super(Builder, self).syncRepositories(repname)
def _regenCache_process(self, progname, repname, cpu_num):
chroot_path = self.clVars.Get('builder.cl_builder_path')
return process("/usr/bin/chroot", chroot_path,
progname, "--repo=%s" % repname, "--update",
"--jobs=%s" % cpu_num, stderr=STDOUT)
def clear_log(self, builder_id):
logname = "build-%s" % builder_id
mainlog = self.clVars.Get('core.cl_log_path')
logpath = path.join(mainlog, logname)
if path.exists(logpath):
removeDir(logpath)
makeDirectory(logpath)
return True
def _get_log_file(self):
logname = "build-%s/%s" % (self.clVars.Get('cl_builder_id'),
self.clVars.Get('cl_task_name'))
mainlog = self.clVars.Get('core.cl_log_path')
return path.join(mainlog, logname)
def emerge_ask(self, param, *packages):
"""
Вывести информацию об обновлении
"""
deo = self.clVars.Get('cl_emerge_default_opts')
param = [param]
chroot_path = self.clVars.Get('cl_builder_path')
logfile = self._get_log_file()
with EmergeParser(ChrootEmergeCommand(chroot_path,
list(packages),
emerge_default_opts=deo,
extra_params=param,
logfile=logfile
)) as emerge:
try:
emerge.question.action = lambda x: False
emerge.run()
if emerge.install_packages.list:
emergelike = self.clVars.Get(
'update.cl_update_emergelist_set') == 'on'
self._display_install_package(emerge, emergelike)
answer = self.askConfirm(
_("Would you like to merge these packages?"), "yes")
if answer == "no":
emerge.command.send("no\n")
raise KeyboardInterrupt
else:
self.printSUCCESS("Nothing to merge")
except EmergeError as e:
self.set_need_update(False)
self.emerge_cache.drop_cache("Emerge error")
self._display_install_package(emerge, emergelike=True)
self._display_error(emerge.prepare_error)
raise
self._startEmerging(emerge)
return True
def depclean(self):
"""
Выполнить очистку системы от лишних пакетов
"""
deo = self.clVars.Get('cl_emerge_default_opts')
chroot_path = self.clVars.Get('cl_builder_path')
logfile = self._get_log_file()
with EmergeParser(
ChrootEmergeCommand(chroot_path, ["--depclean", "--ask=y"],
logfile=logfile,
emerge_default_opts=deo)) as emerge:
try:
emerge.question.action = lambda x: False
emerge.run()
if emerge.uninstall_packages.list:
self._display_remove_list(emerge)
if (self.askConfirm(
_("Would you like to unmerge these unused packages "
"(recommended)?")) != 'yes'):
return True
self._startEmerging(emerge)
else:
self.printSUCCESS("Nothing to unmerge")
except EmergeError:
self._display_error(emerge.prepare_error)
raise
return True
def chroot_command(self, builder_path, command, *params):
"""
Выполенине eix-update для репозиторием
eix-update выполнятется только для тех репозиториев, которые
обновлялись, если cl_update_eixsync_force==auto, либо
все, если cl_update_eixupdate_force==force
"""
cmdpath = self.get_prog_path(command)
if not cmdpath:
return "skip"
#raise BuilderError(_("The %s tool is not found")%command)
p = process("/usr/bin/chroot",
*([builder_path, cmdpath] + list(params)),
stderr=STDOUT)
with writeFile(self._get_log_file()) as f:
f.write(p.read())
if p.failed():
raise BuilderError(_("Failed to execute %s")%command)
return True
def update_task(self, task_name):
"""
Декоратор для добавления меток запуска и останова задачи
"""
def decor(f):
def wrapper(*args, **kwargs):
logger = EmergeLog(EmergeLogNamedTask(task_name),
prefix=self.clVars.Get('cl_builder_path'))
logger.mark_begin_task()
ret = f(*args, **kwargs)
if ret:
logger.mark_end_task()
return ret
return wrapper
return decor
def rebuild_changed_packages(self, builder_path, repository_data):
"""
Пересобрать изменённые пакеты
"""
var_db_path = path.join(builder_path, 'var/db/pkg')
map_rep = {k: pathJoin(builder_path, v)
for k, v in repository_data}
def rebuild_generator():
for pkg in InstalledPackageInfo.get_install_packages(var_db_path):
try:
if pkg['repository'] not in map_rep:
yield pkg.atom
elif pkg != EbuildInfo(pkg.atom,
map_rep[pkg['repository']]):
yield pkg.atom
except EbuildInfoError:
yield pkg.atom
rebuild_list = map(lambda x: "=%s" % x, rebuild_generator())
if rebuild_list:
return self.emerge_ask("-1", *rebuild_list)
return True
class Driver(object):
Package = None
Id = None
def __init__(self, builder_path="/"):
self.builder_path = builder_path
def generate(self):
raise StopIteration
def __iter__(self):
yield (self.Id, '', self.Package)
for x in self.generate():
yield x
class NvidiaDriver(Driver):
Id = 'nvidia-drivers'
Package = 'x11-drivers/nvidia-drivers'
Eclass = 'usr/portage/eclass/nvidia-driver.eclass'
SkipVers = ('71', '96', '173', '304')
def generate(self):
nvidia_eclass = path.join(self.builder_path, self.Eclass)
mask_prefix = "mask_"
for mask in (x for x in readLinesFile(nvidia_eclass)
if x.startswith(mask_prefix)):
# пропустить сборку для 71, 96 и 173
if any(mask.startswith("%s%s" % (mask_prefix, x))
for x in self.SkipVers):
continue
mask = mask.partition('=')[2].strip("\n")
yield (self.Id, mask, mask.replace('>=', '<'))
class AtiDriver(Driver):
Id = 'ati-drivers'
Package = 'x11-drivers/ati-drivers'
def pretend_package_install(self, atom, chroot_path, logfile=None):
"""
Получить список пакетов для установки
:return: список пакетов
"""
if atom not in self.pretend_package_list:
emerge = EmergeParser(ChrootEmergeCommand(
chroot_path, [atom], extra_params=['-pv', '--ask=n'],
logfile=logfile))
emerge.question.default_answer = "n"
emerge.run()
self.pretend_package_list[atom] = list(emerge.install_packages.list)
return self.pretend_package_list[atom]
def _display_video_install_package(self, package_list, drv_name):
"""
Отобразить список устанавливаемых пакетов, если пакет не бинарный
и не является непосредственно видеодрайвером - то он отмечен красной
"*"
:param package_list: список пакетов
:param drv_name: имя драйвера (PN)
:return:
"""
#asterisk = self.color_print.bold("*")
#ebuild_wrong = TextState.Colors.RED
ebuild_color = TextState.Colors.GREEN
binary_color = TextState.Colors.PURPLE
output_package_list = ", ".join(
self.color_print.foreground(binary_color)(str(x))
if x['binary'] else
self.color_print.foreground(ebuild_color)(str(x))
for x in package_list if x['PN'] != drv_name
)
wrong_package = any(not x['binary'] and x['PN'] != drv_name
for x in package_list)
if wrong_package:
self.printERROR(_("Depends %s")%output_package_list)
else:
self.printSUCCESS(_("Depends %s")%output_package_list)
def fetch_drivers(self, builder_path, builder_distdir, builder_pkgdir):
"""
Скачать файлы для установки видеодрайверов
:param builder_path:
:param builder_distdir:
:param builder_pkgdir:
:return:
"""
distrdir_perm = (FilePermission.SetGid |
FilePermission.UserAll |
FilePermission.GroupRead |
FilePermission.GroupExecute |
FilePermission.OtherRead |
FilePermission.OtherExecute)
portage_group = 250
root_user = 0
logfile = self._get_log_file()
driver_list = list(chain(self.NvidiaDriver(builder_path),
self.AtiDriver(builder_path)))
distrdir = path.join(builder_path, 'usr/portage/distfiles')
pkgdir = path.join(builder_path, 'usr/portage/packages')
for target_dn in (distrdir, pkgdir):
makeDirectory(target_dn)
chmod(target_dn, distrdir_perm)
chown(target_dn, root_user, portage_group)
# TODO: /var/calculate/remote возможно тоже должен монтировать для образов
pkgdir_files = []
distdir_files = []
repeat_driver_list = []
while driver_list or repeat_driver_list:
drv_name, drv_mask, drv_atom = driver_list.pop(0)
self.startTask(_("Calculating dependencies for %s") %
drv_atom.strip('"').replace("<", "&lt;"))
package_list = self.pretend_package_install(drv_atom, builder_path,
logfile=logfile)
binary_map = {str(x): x['binary'] for x in package_list}
self._display_video_install_package(package_list, drv_name)
self.startTask(_("Fetching binary packages and sources tarballs") %
[x for x in package_list if x['PN'] == drv_name][0])
ef = EmergeFetcher(ChrootEmergeCommand(
builder_path, ["=%s" % x for x in package_list],
extra_params=["-Of", "--ask=n"]))
try:
for package in ef:
pkg_name = str(package)
if binary_map.get(pkg_name, False):
for fn in package.files:
pkgdir_files.append("%s/%s"%(package['CATEGORY'],
fn))
else:
for fn in package.files:
distdir_files.append(fn)
except EmergeFetcherError:
repeat_driver_list.append([drv_name, drv_mask, drv_atom])
if not driver_list and repeat_driver_list:
driver_list = repeat_driver_list
repeat_driver_list = []
self.printWARNING(_("Waiting for unlock %s")
% driver_list[0][0])
time.sleep(10)
self.startTask(_("Cleaning and copying driver files"))
for source_dn, source, target_dn, target in [
(builder_distdir, distdir_files,
distrdir, find(distrdir,
filetype=FindFileType.RegularFile,
fullpath=False)),
(builder_pkgdir, pkgdir_files,
pkgdir, find(pkgdir,
filetype=FindFileType.RegularFile,
fullpath=False))]:
# удаляем все ненужные файлы
for fn in target:
if fn not in source:
removeFileWithEmptyDirectory(path.join(target_dn, fn),
stopDirectory=target_dn)
# копируем отсутствующие файлы
for fn in source:
if fn not in target:
copyWithPath(path.join(source_dn, fn),
target_dn, prefix=source_dn)
return True
def create_video_data(self, builder_path, repository_data):
driver_list = list(chain(self.NvidiaDriver(builder_path),
self.AtiDriver(builder_path)))
logfile = self._get_log_file()
cache_file = self.clVars.Get('builder.cl_builder_video_driver_path')
map_rep = dict(repository_data)
with writeFile(cache_file) as f:
for drv_name, drv_mask, drv_atom in driver_list:
package_list = self.pretend_package_install(
drv_atom, builder_path, logfile=logfile)
for package in package_list:
if package['binary']:
s = "{category} {pn} {pv} binary {drv} {mask}\n".format(
category=package['CATEGORY'],
pn=package['PN'],
pv=package['PVR'],
drv=drv_name,
mask=drv_mask.strip('"'))
f.write(s)
else:
if package['REPO'] not in map_rep:
raise BuilderError(
_("Failed to determine path "
"for %s repository") % package['REPO'])
s = "{category} {pn} {pv} {dn} {drv} {mask}\n".format(
category=package['CATEGORY'],
pn=package['PN'],
pv=package['PV'],
dn=map_rep[package['REPO']],
drv=drv_name,
mask=drv_mask.strip('"'))
f.write(s)
return True
def remove_video_drivers(self, builder_path):
"""
Удалить данные и архивы для установки видео драйверов
:param builder_path: путь до сборки
:return:
"""
cache_file = self.clVars.Get('builder.cl_builder_video_driver_path')
if path.exists(cache_file):
removeFileWithEmptyDirectory(cache_file)
distrdir = path.join(builder_path, 'usr/portage/distfiles')
pkgdir = path.join(builder_path, 'usr/portage/packages')
for target_dn, target in [
(distrdir, find(distrdir,
fullpath=False)),
(pkgdir, find(pkgdir,
fullpath=False))]:
# удаляем все найденные файлы
for fn in target:
removeFileWithEmptyDirectory(path.join(target_dn, fn),
stopDirectory=target_dn)
return True
def reading_news(self, builder_path):
"""
'Прочитать' новости
:param builder_path: путь до сборки
:return:
"""
eselect_command = "/usr/bin/eselect"
p = process("/usr/bin/chroot",
*[builder_path, eselect_command, "--colour=yes",
"news", "read", "new"],
stderr=STDOUT)
self.printPre(convert_console_to_xml(
p.read()).replace(" ", "&nbsp;&nbsp;"))
return True
def check_obsolete(self, builder_path):
chroot_eix = ChrootEix(builder_path, [], ChrootEix.Option.TestObsolete)
l = chroot_eix.get_packages()
if l:
self.printERROR("Obsolete packages list:")
mult = self.color_print.bold("*")
for pkg in l:
self.printDefault(
"&nbsp;{mult} {package}".format(
mult=mult, package=pkg['CATEGORY/PN']))
return True
def emergelike(self, builder_path, cmd, *params):
"""
Запуск команды, которая подразумевает выполнение emerge
"""
cmd_path = self.get_prog_path(cmd)
logfile = self._get_log_file()
if not cmd_path:
raise BuilderError(_("Failed to find the %s command") % cmd)
with EmergeParser(
ChrootCommandExecutor(builder_path,
cmd_path, params,
logfile=logfile)) as emerge:
self._startEmerging(emerge)
return True

@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
# Copyright 2015 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 re
import sys
from calculate.update.emerge_parser import EmergeInformationBlock
from calculate.lib.utils.portage import EmergePackage
from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate, _)
setLocalTranslate('cl_builder3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
class EmergePackageFetch(EmergePackage):
files = []
class EmergeFetcherError(Exception):
pass
class EmergeFetcher(object):
_color_block = EmergeInformationBlock._color_block
_new_line = EmergeInformationBlock._new_line
re_fetching = re.compile(
">>> Fetching \({c}\d+{c} of {c}\d+{c}\) {c}(.*?){c}{nl}(.*?)"
"(?=>>> Fetching|$)".format(c=_color_block, nl=_new_line), re.S)
re_filename = re.compile("^{c} [*] {c}(\S+).*;-\)".format(c=_color_block),
re.M)
def __init__(self, emerge_command):
"""
:param package_list: список пакетов типа (EmergeUpdateInfo)
:return:
"""
self.emerge_command = emerge_command
def parse(self, data):
if "is already locked by another fetcher" in data:
raise EmergeFetcherError(
_("File is already locked by another fetcher."))
for package, block in self.re_fetching.findall(data):
ep = EmergePackageFetch(package)
ep.files = [x for x in self.re_filename.findall(block)]
yield ep
def __iter__(self):
child = self.emerge_command.execute()
for i in self.parse(child.read()):
yield i

@ -26,7 +26,7 @@ setLocalTranslate('cl_builder3', sys.modules[__name__])
__ = getLazyLocalTranslate(_) __ = getLazyLocalTranslate(_)
class ClBuilderCreateAction(Action): class ClBuilderPrepareAction(Action):
""" """
Действие обновление конфигурационных файлов Действие обновление конфигурационных файлов
""" """
@ -63,7 +63,8 @@ class ClBuilderCreateAction(Action):
}, },
# save # save
{'name': 'save', {'name': 'save',
'method': 'Builder.save_build(cl_builder_build)', 'method': 'Builder.save_build(cl_builder_build,'
'cl_builder_linux_datavars)',
}, },
# закрепить подключенные данные # закрепить подключенные данные
{'name': 'detach', {'name': 'detach',

@ -0,0 +1,146 @@
# -*- coding: utf-8 -*-
# Copyright 2015 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
from calculate.core.server.func import Action, Tasks
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
from calculate.lib.utils.files import FilesError, isMount
from calculate.update.update import UpdateError
from ..datavars import BuilderError
from calculate.lib.utils.portage import GitError, isPkgInstalled
from calculate.install.distr import DistributiveError
setLocalTranslate('cl_builder3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
class ClBuilderProfileAction(Action):
"""
Действие обновление конфигурационных файлов
"""
# ошибки, которые отображаются без подробностей
native_error = (DistributiveError, FilesError, UpdateError,
BuilderError, GitError)
successMessage = __("The profile was successfully updated")
failedMessage = __("Failed to update the profile")
interruptMessage = __("Profile update manually interrupted")
# список задач для действия
tasks = [
{'name': 'migrate_repository',
'method': 'Builder.migrateCacheRepository('
'cl_builder_profile_url,cl_builder_profile_branch,'
'cl_builder_profile_storage)',
'message': __("Repository transfer"),
'condition': lambda Get: not (
Get('cl_builder_profile_storage').is_local(
Get('cl_builder_profile_url'),
Get('cl_builder_profile_branch')))
},
{'name': 'reconfigure_vars1',
'method': 'Builder.invalidateVariables("cl_builder_profile_storage")',
'depend': Tasks.has('migrate_repository')
},
{'name': 'reconfigure_vars',
'method': 'Builder.reconfigureProfileVars(cl_builder_profile_datavars,'
'cl_builder_path)'
},
{'name': 'remove_old_reps',
'foreach': 'cl_builder_remove_rep',
'message': __("Remove the {eachvar:capitalize} repository"),
'method': 'Builder.remove_repositories(eachvar)'
},
{'name': 'reps_synchronization',
'group': __("Repositories synchronization"),
'tasks': [
{'name': 'sync_reps',
'foreach': 'cl_builder_profile_sync_rep',
'message': __("Syncing the {eachvar:capitalize} repository"),
'method': 'Builder.syncRepositories(eachvar)',
#'condition': lambda Get: Get('cl_update_profile_sync_rep')
},
{'name': 'regen_cache',
'foreach': 'cl_builder_sync_overlay_rep',
'message': __("Updating the {eachvar:capitalize} repository cache"),
'essential': False,
'method': 'Builder.regenCache(eachvar)',
#'condition': (
# lambda Get: (Get('cl_update_outdate_set') == 'on' and
# Get('cl_update_metadata_force') != 'skip' or
# Get('cl_update_metadata_force') == 'force'))
},
{'name': 'eix_update',
'message': __("Updating the eix cache"),
'method': 'Builder.eixUpdate(cl_builder_repository_name)',
#'condition': (
# lambda Get: (Get('cl_update_outdate_set') == 'on' and
# Get('cl_update_eixupdate_force') != 'skip' or
# Get('cl_update_eixupdate_force') == 'force'))
},
# save
{'name': 'save',
'method': 'Builder.save_build(cl_builder_build,'
'cl_builder_profile_datavars)',
},
# сообщение удачного завершения при обновлении репозиториев
{'name': 'success_syncrep',
'message': __("Synchronization finished"),
'depend': (Tasks.success() & Tasks.has_any("sync_reps",
"sync_other_reps",
"emerge_metadata",
"eix_update")),
}
]
},
{'name': 'reps_synchronization',
'group': __("Setting up the profile"),
'tasks': [
{'name': 'set_profile',
'message': __("Switching to profile "
"{cl_builder_profile_system_shortname}"),
'method': 'Builder.set_profile('
'cl_builder_profile_system_shortname,cl_builder_path)'
},
{'name': 'merge_utils',
'message': __("Calculating dependencies"),
'method': 'Builder.emerge("-console -pxe","-1","sys-apps/calculate-utils")',
# TODO: возможно добавить параметр необходимости установки
'condition': lambda Get: not isPkgInstalled(
'sys-apps/calculate-utils', Get('cl_builder_path'))
},
{'name': 'reconfigure',
'message': __("Reconfigure the settings"),
'method': 'Builder.apply_templates(cl_builder_path,'
'cl_template_clt_set,True,None,False,"merge",'
'cl_builder_profile_datavars)',
'condition': lambda Get: Get('cl_templates_locate')
},
{'name': 'fix_settings',
'message': __("Fixing the settings"),
'method': 'Builder.apply_templates(cl_builder_path,'
'cl_template_clt_set,True,None,False,"sync",'
'cl_builder_profile_datavars)',
'condition': lambda Get: Get('cl_templates_locate')
},
{'name': 'dispatch_conf',
'message': __("Updating configuration files"),
'method':'Builder.dispatchConf(None,cl_builder_path)',
'condition': lambda Get: Get('cl_dispatch_conf') != 'skip'
},
]
}
]

@ -52,7 +52,8 @@ class ClBuilderRestoreAction(Action):
# save # save
{'name': 'save', {'name': 'save',
'message': __("Save distro"), 'message': __("Save distro"),
'method': 'Builder.save_build(cl_builder_build)', 'method': 'Builder.save_build(cl_builder_build,'
'cl_builder_linux_datavars)',
}, },
# закрепить подключенные данные # закрепить подключенные данные
{'name': 'detach', {'name': 'detach',

@ -0,0 +1,247 @@
# -*- coding: utf-8 -*-
# Copyright 2015 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
from calculate.core.server.func import Action, Tasks
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
from calculate.lib.utils.files import FilesError, isMount
from calculate.update.emerge_parser import EmergeError
from calculate.update.update import UpdateError
from ..datavars import BuilderError
from calculate.lib.utils.portage import GitError, isPkgInstalled, \
EmergeLogNamedTask, PackageList, EmergeLog
from calculate.install.distr import DistributiveError
from os import path
from calculate.update.update_tasks import EmergeMark
setLocalTranslate('cl_builder3', sys.modules[__name__])
__ = getLazyLocalTranslate(_)
class ClBuilderUpdateAction(Action):
"""
Действие обновление конфигурационных файлов
"""
# ошибки, которые отображаются без подробностей
native_error = (DistributiveError, FilesError, UpdateError,
BuilderError, GitError, EmergeError)
successMessage = __("The system was successfully updated")
failedMessage = __("Failed to update the system")
interruptMessage = __("System update manually interrupted")
def was_installed(pkg, task_name):
def func(Get):
task = EmergeLog(EmergeLogNamedTask(task_name),
prefix=Get('cl_builder_path'))
return bool(PackageList(task.list)[pkg])
return func
def need_depclean(pkg, task_name):
def func(Get):
task = EmergeLog(EmergeLogNamedTask(task_name),
prefix=Get('cl_builder_path'))
return bool(PackageList(task.list)[pkg])
return func
# список задач для действия
tasks = [
{'name': 'clear_log',
'method': 'Builder.clear_log(cl_builder_id)',
},
{'name': 'apply_template',
'message': __("Configuring build"),
'method': 'Builder.applyTemplates(cl_builder_target,False,False,None)',
},
{'name': 'invalidate_vars',
'method': 'Builder.invalidateVariables("cl_builder_linux_datavars")'
},
{'name': 'reconfigure_vars',
'method': 'Builder.reconfigureProfileVars(cl_builder_linux_datavars,'
'cl_builder_path)'
},
{'name': 'reps_synchronization',
'group': __("Repositories synchronization"),
'tasks': [
{'name': 'sync_reps',
'foreach': 'cl_builder_profile_sync_rep',
'message': __("Syncing the {eachvar:capitalize} repository"),
'method': 'Builder.syncRepositories(eachvar)',
},
{'name': 'regen_cache',
'foreach': 'cl_builder_sync_overlay_rep',
'message': __("Updating the {eachvar:capitalize} repository cache"),
'essential': False,
'method': 'Builder.regenCache(eachvar)',
},
{'name': 'eix_update',
'message': __("Updating the eix cache"),
'method': 'Builder.eixUpdate(cl_builder_repository_name)',
},
# сообщение удачного завершения при обновлении репозиториев
{'name': 'success_syncrep',
'message': __("Synchronization finished"),
'depend': (Tasks.success() & Tasks.has_any("sync_reps",
"sync_other_reps",
"emerge_metadata",
"eix_update")),
}
]
},
{'name': 'reps_synchronization',
'group': __("System configuration"),
'tasks': [
{'name': 'revision',
'message': __("Fixing the settings"),
'method': 'Builder.apply_templates(cl_builder_path,'
'cl_template_clt_set,True,None,False,"sync",'
'cl_builder_linux_datavars)',
'condition': lambda Get: Get('cl_templates_locate')
},
{'name': 'dispatch_conf',
'message': __("Updating configuration files"),
'method': 'Builder.dispatchConf(None,cl_builder_path)',
'condition': lambda Get: Get('cl_dispatch_conf') != 'skip'
},
]
},
{'name': 'emerge_update_world',
'group': __("Updating packages"),
'tasks': [
{'name': 'update_world',
'message': __("Calculating dependencies"),
'method': 'Builder.emerge_ask("-uDN", "--changed-deps",'
'"--with-bdeps=y", "@world")'
}
]
},
{'name': 'group_changed_packages',
'group': __("Rebuild modified packages"),
'tasks': [
{'name': 'changed_packages',
'message': __("Calculating dependencies"),
'method': 'Builder.rebuild_changed_packages(cl_builder_path,'
'cl_builder_repository_data)'
}
]
},
{'name': 'update_python',
'group': __("Updating Python"),
'tasks': [
{'name': 'python_updater',
'message': __('Find & rebuild packages broken due '
'to a Python upgrade'),
'method': 'Builder.emergelike(cl_builder_path,"python-updater")',
'condition': was_installed('dev-lang/python$',
EmergeMark.PythonUpdater),
'decoration': 'Builder.update_task("%s")' %
EmergeMark.PythonUpdater
},
]
},
{'name': 'update_perl',
'group': __("Updating Perl"),
'tasks': [
{'name': 'perl_cleaner',
'message': __('Find & rebuild packages and Perl header files '
'broken due to a perl upgrade'),
'method': 'Builder.emergelike(cl_builder_path,"perl-cleaner",'
'"all")',
'condition': was_installed('dev-lang/perl$',
EmergeMark.PerlCleaner),
'decoration': 'Builder.update_task("%s")' % EmergeMark.PerlCleaner
},
]
},
{'name': 'depclean',
'group': __("Cleaning the system from needless packages"),
'tasks': [
{'name': 'update_depclean',
'message': __("Calculating dependencies"),
'method': 'Builder.depclean()',
'condition': need_depclean('.*', EmergeMark.Depclean),
'decoration': 'Builder.update_task("%s")' % EmergeMark.Depclean
},
]
},
{'name': 'update_world:update_modules',
'group': __("Rebuilding dependent modules"),
'tasks': [
{'name': 'update_world:module_rebuild',
'message': __('Updating Kernel modules'),
'method': 'Builder.emerge("","@module-rebuild")',
'condition': was_installed('sys-kernel/.*source',
EmergeMark.KernelModules),
'decoration': 'Builder.update_task("%s")' %
EmergeMark.KernelModules
},
{'name': 'update_world:x11_module_rebuild',
'message': __('Updating X.Org server modules'),
'method': 'Builder.emerge("","@x11-module-rebuild")',
'condition': was_installed('x11-base/xorg-server',
EmergeMark.XorgModules),
'decoration': 'Builder.update_task("%s")' % EmergeMark.XorgModules
},
{'name': 'update_world:preserved_rebuild',
'message': __('Updating preserved libraries'),
'method': 'Builder.emerge("","@preserved-rebuild")',
'condition': was_installed('.*', EmergeMark.PreservedLibs),
'decoration': 'Builder.update_task("%s")' %
EmergeMark.PreservedLibs
},
{'name': 'update_world:dispatch_conf_end',
'message': __("Updating configuration files"),
'method':'Builder.dispatchConf()',
'condition': lambda Get: Get('cl_dispatch_conf') != 'skip'
},
]
},
{'name': 'prelink',
'message': __("Executing prelink"),
'method': 'Builder.chroot_command(cl_builder_path,"prelink",'
'"-afmR")',
'condition': was_installed('.*', EmergeMark.Prelink),
'decoration': 'Builder.update_task("%s")' % EmergeMark.Prelink
},
{'name': 'fetch_video_drivers',
'group': __("Fetching video drivers"),
'tasks': [
{'name': 'fetch_drivers',
'method': 'Builder.fetch_drivers(cl_builder_path,'
'cl_builder_linux_distdir,cl_builder_linux_pkgdir)',
'condition': lambda Get: Get('cl_builder_videodrv_set') == 'on'
},
{'name': 'create_video_data',
'message': __("Creating install video driver data"),
'method': 'Builder.create_video_data(cl_builder_path,'
'cl_builder_repository_data)',
'condition': lambda Get: Get('cl_builder_videodrv_set') == 'on'
},
]
},
{'name': 'remove_video_drivers',
'method': 'Builder.remove_video_drivers(cl_builder_path)',
'condition': lambda Get: Get('cl_builder_videodrv_set') == 'off'
},
{'name': 'reading_news',
'method': 'Builder.reading_news(cl_builder_path)'
},
{'name': 'check_obsolete',
'method': 'Builder.check_obsolete(cl_builder_path)'
}
]

@ -21,6 +21,20 @@ from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_builder3', sys.modules[__name__]) setLocalTranslate('cl_builder3', sys.modules[__name__])
class Actions:
Prepare = "prepare"
Image = "image"
Break = "break"
Restore = "restore"
Update = "assemble_update"
ChangeProfile = "builder_profile"
NewAssemble = (Prepare,)
WorkAssemble = (Image, Break, ChangeProfile, Update)
BrokenAssemble = (Restore,)
ImageSquash = "squash"
ImageIso = "iso"
class VariableAcBuilderSquash(ReadonlyVariable): class VariableAcBuilderSquash(ReadonlyVariable):
""" """
@ -29,7 +43,7 @@ class VariableAcBuilderSquash(ReadonlyVariable):
def get(self): def get(self):
action = self.Get("cl_action") action = self.Get("cl_action")
image_action = self.Get('cl_builder_action') image_action = self.Get('cl_builder_action')
if action == 'image' and image_action == "squash": if action == Actions.Image and image_action == Actions.ImageSquash:
return "on" return "on"
return "off" return "off"
@ -41,7 +55,7 @@ class VariableAcBuilderIso(ReadonlyVariable):
def get(self): def get(self):
action = self.Get("cl_action") action = self.Get("cl_action")
image_action = self.Get('cl_builder_action') image_action = self.Get('cl_builder_action')
if action == 'image' and image_action == "iso": if action == Actions.Image and image_action == Actions.ImageIso:
return "on" return "on"
return "off" return "off"
@ -52,7 +66,8 @@ class VariableAcBuilderSetup(ReadonlyVariable):
""" """
def get(self): def get(self):
action = self.Get('cl_action') action = self.Get('cl_action')
if action in ("create",): if (action in (Actions.Prepare, Actions.Update) and
not self.GetBool('cl_builder_stage_set')):
return "on" return "on"
return "off" return "off"
@ -63,6 +78,6 @@ class VariableAcBuilderPrepare(ReadonlyVariable):
""" """
def get(self): def get(self):
action = self.Get('cl_action') action = self.Get('cl_action')
if action in ("create",): if action in (Actions.Prepare, Actions.Update):
return "on" return "on"
return "off" return "off"

@ -18,6 +18,7 @@ import sys
from os import path from os import path
import os import os
import re import re
from .action import Actions
from calculate.install import distr from calculate.install import distr
from calculate.lib.utils.device import getUdevDeviceInfo, humanreadableSize from calculate.lib.utils.device import getUdevDeviceInfo, humanreadableSize
from calculate.lib.utils.files import isMount, process, typeFile, listDirectory, \ from calculate.lib.utils.files import isMount, process, typeFile, listDirectory, \
@ -29,6 +30,8 @@ from ..drive_spool import DriveSpool
from calculate.lib.datavars import Variable, VariableError, ReadonlyVariable from calculate.lib.datavars import Variable, VariableError, ReadonlyVariable
from functools import wraps from functools import wraps
_ = lambda x:x
from calculate.lib.cl_lang import setLocalTranslate from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_builder3',sys.modules[__name__]) setLocalTranslate('cl_builder3',sys.modules[__name__])
@ -94,6 +97,31 @@ class BaseBuildId(Variable):
self.label = _("Build ID") self.label = _("Build ID")
self.help = _("build ID") self.help = _("build ID")
class VariableClBuilderVideoDriverPath(Variable):
"""
Имя файла, содержащего данные об установки драйверов во время загрузки
"""
def get(self):
builder_path = self.Get('cl_builder_path')
return path.join(
builder_path,
'var/cache/calculate/video_drivers')
class VariableClBuilderVideodrvSet(Variable):
"""
Нужно ли скачивать пакеты в дистрибутив для установки проприетарных
драйверов во время загрузки
"""
type = "bool"
opt = ["--video", "-V"]
def init(self):
self.label = _("Fetch video drivers")
self.help = _("fetch video drivers")
def get(self):
fn = self.Get("cl_builder_video_driver_path")
return "on" if path.exists(fn) else "off"
class VariableClBuilderSourceFilename(Variable): class VariableClBuilderSourceFilename(Variable):
""" """
@ -111,7 +139,7 @@ class VariableClBuilderSourceFilename(Variable):
def check(self, isoimage): def check(self, isoimage):
"""Set image file""" """Set image file"""
if self.Get('cl_action') == 'create' and not isoimage: if self.Get('cl_action') in Actions.NewAssemble and not isoimage:
raise VariableError(_("You need to select a source image")) raise VariableError(_("You need to select a source image"))
shortname = self.Get('os_builder_linux_shortname') shortname = self.Get('os_builder_linux_shortname')
build = self.Get('os_builder_linux_build') build = self.Get('os_builder_linux_build')
@ -220,9 +248,10 @@ class VariableClBuilderDiskSize(ReadonlyVariable):
def get(self): def get(self):
action = self.Get('cl_action') action = self.Get('cl_action')
if action == 'create': if action in Actions.NewAssemble:
return self.get_create() return self.get_create()
elif action in ('break', 'restore'): elif action in (Actions.Break, Actions.Restore):
# TODO: disk size для остальных
return return
def humanReadable(self): def humanReadable(self):
@ -299,9 +328,11 @@ class VariableClBuilderTarget(Variable):
def get(self): def get(self):
action = self.Get('cl_action') action = self.Get('cl_action')
if action == 'create': if action in Actions.NewAssemble:
return self.get_create() return self.get_create()
elif action in ('break', 'restore', 'image'): elif action in Actions.WorkAssemble:
return self.get_worked()
elif action in Actions.BrokenAssemble:
return self.get_worked() return self.get_worked()
else: else:
return "" return ""
@ -347,9 +378,11 @@ class VariableClBuilderBuild(Variable):
def get(self): def get(self):
action = self.Get('cl_action') action = self.Get('cl_action')
if action == 'create': if action in Actions.NewAssemble:
return self.get_create() return self.get_create()
if action in ('break', 'restore', 'image'): if action in Actions.WorkAssemble:
return self.get_worked()
elif action in Actions.BrokenAssemble:
return self.get_worked() return self.get_worked()
return "" return ""
@ -381,8 +414,8 @@ class VariableClBuilderPreparedId(BaseBuildId):
action = self.Get('cl_action') action = self.Get('cl_action')
for x in bs: for x in bs:
build = bs.get_build(x) build = bs.get_build(x)
if (build and (action == 'break' or if (build and (action == Actions.Break or
build.status == Build.Status.WORKED)): build.status == Build.Status.Worked)):
yield x yield x
def get(self): def get(self):
@ -397,7 +430,7 @@ class VariableClBuilderPreparedId(BaseBuildId):
for x in bs: for x in bs:
build = bs.get_build(x) build = bs.get_build(x)
if build: if build:
if build.status == Build.Status.BROKEN: if build.status == Build.Status.Broken:
yield (x, "%s (%s)" % (x, _("broken"))) yield (x, "%s (%s)" % (x, _("broken")))
else: else:
yield (x, x) yield (x, x)
@ -408,8 +441,8 @@ class VariableClBuilderPreparedId(BaseBuildId):
l = self.available() l = self.available()
if not l: if not l:
raise VariableError(_("Assemble %s is not found") % value) raise VariableError(_("Assemble %s is not found") % value)
if (self.Get('cl_builder_build').status == Build.Status.BROKEN and if (self.Get('cl_builder_build').status == Build.Status.Broken and
self.Get('cl_action') != 'break'): self.Get('cl_action') != Actions.Break):
raise VariableError( raise VariableError(
_("Assemble %s is broken, try to restore build") % value) _("Assemble %s is broken, try to restore build") % value)
@ -426,10 +459,10 @@ class VariableClBuilderBrokenId(BaseBuildId):
bs = self.Get('cl_builder_storage') bs = self.Get('cl_builder_storage')
for x in bs: for x in bs:
build = bs.get_build(x) build = bs.get_build(x)
if build and build.status == Build.Status.BROKEN: if build and build.status == Build.Status.Broken:
yield x yield x
@is_action('restore') @is_action(Actions.Restore)
def get(self): def get(self):
l = self.available() l = self.available()
if l and len(l) == 1: if l and len(l) == 1:
@ -437,12 +470,12 @@ class VariableClBuilderBrokenId(BaseBuildId):
return "" return ""
@as_list @as_list
@is_action('restore', default_value=[]) @is_action(Actions.Restore, default_value=[])
def choice(self): def choice(self):
bs = self.Get('cl_builder_storage') bs = self.Get('cl_builder_storage')
for x in bs: for x in bs:
build = bs.get_build(x) build = bs.get_build(x)
if build.status == Build.Status.BROKEN: if build.status == Build.Status.Broken:
yield (x, "%s (%s)" % (x, _("broken"))) yield (x, "%s (%s)" % (x, _("broken")))
def check(self, value): def check(self, value):
@ -459,11 +492,11 @@ class VariableClBuilderId(ReadonlyVariable):
""" """
def get(self): def get(self):
action = self.Get('cl_action') action = self.Get('cl_action')
if action == 'create': if action in Actions.NewAssemble:
return self.Get('cl_builder_new_id') return self.Get('cl_builder_new_id')
elif action in ('break', 'image'): elif action in Actions.WorkAssemble:
return self.Get('cl_builder_prepared_id') return self.Get('cl_builder_prepared_id')
elif action == 'restore': elif action in Actions.BrokenAssemble:
return self.Get('cl_builder_broken_id') return self.Get('cl_builder_broken_id')
@ -500,6 +533,16 @@ class VariableClBuilderParentPath(ReadonlyVariable):
return ("../"*len(filter(None, return ("../"*len(filter(None,
builder_path.split('/'))))[:-1] builder_path.split('/'))))[:-1]
class VariableClBuilderStageSet(ReadonlyVariable):
"""
Разворачиваемый образ является stage (Gentoo системой)
"""
type = "bool"
def get(self):
return ("on"
if self.Get('os_builder_linux_shortname') == "Gentoo"
else "off")
class VariableClBuilderPkgdir(Variable): class VariableClBuilderPkgdir(Variable):
""" """
@ -511,9 +554,9 @@ class VariableClBuilderPkgdir(Variable):
def get(self): def get(self):
action = self.Get('cl_action') action = self.Get('cl_action')
if action == 'create': if action in Actions.NewAssemble:
return self.fallback() return self.fallback()
elif action in ('restore', 'image'): elif action in Actions.WorkAssemble:
build = self.Get('cl_builder_build') build = self.Get('cl_builder_build')
return build.pkgdir or self.fallback() return build.pkgdir or self.fallback()
else: else:
@ -583,7 +626,7 @@ class VariableClBuilderSquashPath(ReadonlyVariable):
""" """
Путь от iso до содержимого squash Путь от iso до содержимого squash
""" """
@is_action('image') @is_action(Actions.Image)
def get(self): def get(self):
return path.relpath(self.Get('cl_builder_path'), return path.relpath(self.Get('cl_builder_path'),
self.Get('cl_builder_iso_path')) self.Get('cl_builder_iso_path'))
@ -593,7 +636,7 @@ class VariableClBuilderImage(ReadonlyVariable):
""" """
Создаваемый образ Создаваемый образ
""" """
@is_action('image') @is_action(Actions.Image)
def get(self): def get(self):
image_name = self.Get('cl_builder_image_filename') image_name = self.Get('cl_builder_image_filename')
bdn = self.Get('cl_builder_iso_path') bdn = self.Get('cl_builder_iso_path')
@ -614,7 +657,7 @@ class VariableClBuilderCdname(ReadonlyVariable):
""" """
Type of iso (CD/DVD) Type of iso (CD/DVD)
""" """
@is_action("image") @is_action(Actions.Image)
def get(self): def get(self):
squashfile = pathJoin(self.Get('cl_builder_iso_path'), squashfile = pathJoin(self.Get('cl_builder_iso_path'),
self.Get('cl_builder_current_squash')) self.Get('cl_builder_current_squash'))
@ -641,7 +684,7 @@ class VariableClBuilderIsoLabel(Variable):
""" """
LABEL для iso LABEL для iso
""" """
@is_action("image") @is_action(Actions.Image)
def get(self): def get(self):
return "%s-%s" % (self.Get('os_builder_linux_shortname').upper(), return "%s-%s" % (self.Get('os_builder_linux_shortname').upper(),
self.Get('os_builder_linux_build')) self.Get('os_builder_linux_build'))
@ -652,7 +695,7 @@ class VariableClBuilderRootParam(Variable):
параметр root= для livecd параметр root= для livecd
""" """
@is_action("image") @is_action(Actions.Image)
def get(self): def get(self):
return "live:LABEL=%s" % self.Get('cl_builder_iso_label') return "live:LABEL=%s" % self.Get('cl_builder_iso_label')
@ -796,16 +839,29 @@ class VariableClBuilderTemplateLocation(Variable):
""" """
Устанавливаются только дистрибутивные шаблоны Устанавливаются только дистрибутивные шаблоны
""" """
type = "list"
def get(self): def get(self):
return [x for x in self.Get('main.cl_template_location') return [x for x in self.Get('main.cl_template_location')
if x not in ('remote', 'local')] if x not in ('remote', 'local')]
class VariableClBuilderBranchName(Variable): class VariableClBuilderBranchName(Variable):
""" """
Ветки оверлеев используемые для сборки системы Ветки оверлеев используемые для сборки системы
""" """
type = "list" type = "list"
def get(self): def get(self):
# TODO: заглушка action = self.Get('cl_action')
return self.Get('update.cl_update_branch_name') default_branch = Build.Branches.Stable
if action == Actions.ChangeProfile:
pass
else:
build = self.Get('cl_builder_build')
if build and build.references:
return build.references
dv = self.Get('cl_builder_linux_datavars')
if dv:
return map(lambda x: default_branch,
dv.Get('cl_update_rep_name'))
return []

@ -20,11 +20,15 @@ from os import path
import re import re
from calculate.install import distr from calculate.install import distr
from calculate.install.distr import DistributiveError from calculate.install.distr import DistributiveError
from calculate.lib.datavars import ReadonlyVariable, SimpleDataVars from calculate.lib.datavars import ReadonlyVariable, SimpleDataVars, \
VariableError, ReadonlyTableVariable, FieldValue
from calculate.lib.utils.files import pathJoin
from calculate.lib.utils.tools import ignore from calculate.lib.utils.tools import ignore
from calculate.lib.variables import linux from calculate.lib.variables import linux
from calculate.lib.variables import env
from calculate.update.variables import update from calculate.update.variables import update
from calculate.lib.variables import system from calculate.lib.variables import system, linux
from .action import Actions
from calculate.lib.cl_lang import setLocalTranslate from calculate.lib.cl_lang import setLocalTranslate
import datetime import datetime
@ -38,7 +42,10 @@ class BuilderLinux(ReadonlyVariable):
variable = "" variable = ""
def get(self): def get(self):
dv = self.Get('cl_builder_linux_datavars') try:
dv = self.Get('cl_builder_linux_datavars')
except VariableError:
return ""
if dv: if dv:
return dv[self.variable] return dv[self.variable]
else: else:
@ -50,10 +57,26 @@ class DataVarsBuilderLinux(linux.LinuxDataVars):
""" """
def variables(self): def variables(self):
l = super(DataVarsBuilderLinux, self).variables() l = super(DataVarsBuilderLinux, self).variables()
return l + [update.VariableClProfileSystem(), return l + [linux.VariableClProfileSystem(),
update.VariableClProfileRepository(), env.VariableClRepositoryData(),
system.VariableOsArchMachineGentoo(), env.VariableClRepositoryName(),
update.VariableClProfileData()] env.VariableClRepositoryLocation(),
env.VariableClTemplateLocation(),
env.VariableClTemplatePath(),
env.VariableClPkgdir(),
env.VariableClDistdir(),
env.VariableClEmergeConfig(systemRoot=self.systemRoot),
update.VariableClUpdateRepData(section="update"),
update.VariableClUpdateRepPath(section="update"),
update.VariableClUpdateRepName(section="update"),
update.VariableClUpdateRepUrl(section="update"),
update.VariableClUpdateRep(section="update"),
update.VariableClUpdateRepRev(section="update"),
update.VariableClUpdateBranchName(section="update"),
update.VariableClUpdateLaymanConfig(section="update"),
update.VariableClUpdateLaymanStorage(section="update"),
update.VariableClProfileRepository(section="update"),
system.VariableOsArchMachineGentoo()]
@classmethod @classmethod
def StageInformation(cls, fn): def StageInformation(cls, fn):
@ -107,9 +130,9 @@ class VariableClBuilderLinuxDatavars(ReadonlyVariable):
def get(self): def get(self):
"""Get by distroinfo or current info""" """Get by distroinfo or current info"""
if self.Get('cl_action') == 'create': if self.Get('cl_action') in Actions.NewAssemble:
return self.source_data() return self.source_data()
elif self.Get('cl_action') in ('break', 'restore', 'image'): elif self.Get('cl_action') in Actions.WorkAssemble:
return self.target_data() return self.target_data()
return "" return ""
@ -132,7 +155,7 @@ class VariableOsBuilderLinuxBuild(BuilderLinux):
def get(self): def get(self):
action = self.Get('cl_action') action = self.Get('cl_action')
if action == 'image': if action == Actions.Image:
curdate = datetime.datetime.now() curdate = datetime.datetime.now()
return "%04d%02d%02d" % (curdate.year, curdate.month, curdate.day) return "%04d%02d%02d" % (curdate.year, curdate.month, curdate.day)
else: else:
@ -156,6 +179,21 @@ class VariableOsBuilderLinuxName(BuilderLinux):
variable = "os_linux_name" variable = "os_linux_name"
class VariableClBuilderProfileSystem(BuilderLinux):
variable = "cl_profile_system"
#def get(self):
# action = self.Get('cl_action')
# if action == 'create':
# shortname = self.Get('cl_builder_profile_system_shortname')
# profile = self.Select('cl_builder_profile_path',
# where="cl_builder_profile_shortname",
# eq=shortname, limit=1)
# if profile:
# return profile
# return ""
class VariableOsBuilderLinuxSystem(BuilderLinux): class VariableOsBuilderLinuxSystem(BuilderLinux):
""" """
Install system name Install system name
@ -168,3 +206,74 @@ class VariableOsBuilderLinuxSubname(BuilderLinux):
Install subname Install subname
""" """
variable = "os_linux_subname" variable = "os_linux_subname"
class VariableClBuilderRepositoryData(ReadonlyTableVariable):
"""
"""
source = ["cl_repository_name", "cl_repository_location"]
def get(self):
try:
dv = self.Get('cl_builder_linux_datavars')
if dv:
return dv.Get('cl_repository_data')
except VariableError:
pass
return [[]]
class VariableClBuilderRepositoryName(FieldValue,ReadonlyVariable):
"""
"""
type = "list"
source_variable = "cl_builder_repository_data"
column = 0
class VariableClBuilderRepositoryLocation(FieldValue,ReadonlyVariable):
"""
"""
type = "list"
source_variable = "cl_builder_repository_data"
column = 1
class VariableClBuilderSyncOverlayRep(ReadonlyVariable):
"""
Обновляемые репозитории (исключая portage)
"""
type = "list"
def get(self):
action = self.Get('cl_action')
if action in Actions.ChangeProfile:
dv = self.Get('cl_builder_profile_datavars')
else:
dv = self.Get('cl_builder_linux_datavars')
if dv:
return filter(lambda x: x not in ("portage", "gentoo"),
dv.Get('cl_repository_name'))
else:
return []
class VariableClBuilderLinuxDistdir(ReadonlyVariable):
"""
Полный путь до DISTDIR собираемой системы относительно текущего корня
"""
def get(self):
fallback_distdir = '/var/calculate/remote/distfiles'
dv = self.Get('cl_builder_linux_datavars')
builder_path = self.Get('cl_builder_path')
if dv:
return pathJoin(builder_path, dv.Get('cl_distdir'))
return pathJoin(builder_path, fallback_distdir)
class VariableClBuilderLinuxPkgdir(ReadonlyVariable):
"""
Полный путь до PKGDIR собираемой системы относительно текущего корня
"""
def get(self):
fallback_pkgdir = '/var/calculate/remote/packages'
dv = self.Get('cl_builder_linux_datavars')
builder_path = self.Get('cl_builder_path')
if dv:
return pathJoin(builder_path, dv.Get('cl_pkgdir'))
return pathJoin(builder_path, fallback_pkgdir)

@ -19,14 +19,17 @@ import os
from os import path from os import path
from calculate.lib.datavars import (ReadonlyVariable, FieldValue, VariableError, from calculate.lib.datavars import (ReadonlyVariable, FieldValue, VariableError,
DataVarsError, Variable) DataVarsError, Variable)
from calculate.lib.utils.files import listDirectory
from calculate.lib.utils.portage import GitError from calculate.lib.utils.portage import GitError
from calculate.lib.variables import linux as lib_linux from calculate.lib.variables import linux as lib_linux
from calculate.lib.variables import system as lib_system
from calculate.install import distr from calculate.install import distr
from calculate.update.variables import update from calculate.update.variables import update
from calculate.update import profile as update_profile from calculate.update import profile as update_profile
from calculate.lib.cl_lang import setLocalTranslate from calculate.lib.cl_lang import setLocalTranslate
from calculate.update.variables.update import DataVarsUpdateProfile
setLocalTranslate('cl_builder3', sys.modules[__name__]) setLocalTranslate('cl_builder3', sys.modules[__name__])
@ -34,7 +37,10 @@ class VariableClBuilderProfileStorage(ReadonlyVariable):
type = "object" type = "object"
def get(self): def get(self):
builder_path = self.Get('cl_builder_path')
builder_ls = path.join(builder_path, "var/lib/layman")
return update_profile.RepositoryStorageSet( return update_profile.RepositoryStorageSet(
update_profile.LocalStorage(builder_ls),
update_profile.CacheStorage('/var/calculate/tmp/update')) update_profile.CacheStorage('/var/calculate/tmp/update'))
@ -44,76 +50,21 @@ class VariableClBuilderProfileUrl(update.VariableClUpdateProfileUrl):
""" """
check_after = ["cl_builder_profile_branch"] check_after = ["cl_builder_profile_branch"]
def check(self, value): profile = "builder.cl_builder_profile_system"
action = self.Get('cl_action') branch = "builder.cl_builder_profile_branch"
if not value and action == 'create': storage = "builder.cl_builder_profile_storage"
branch = self.Get('cl_builder_profile_branch') profiles_shortname = 'builder.cl_builder_profile_shortname'
if branch != update_profile.DEFAULT_BRANCH:
raise VariableError("Need to specify profile repository")
return
if not value:
raise VariableError("Need to specify profile repository")
try:
branch = self.Get('cl_builder_profile_branch')
self.Get('cl_builder_profile_storage').get_profiles(value, branch)
except GitError as e:
raise VariableError(str(e))
if not self.Get('cl_builder_profile_shortname'):
raise VariableError(_("Repository %s has no profiles")%value)
def get(self):
action = self.Get('cl_action')
if action == 'create':
return ""
if action in ("image"):
return update.VariableClUpdateProfileUrl.get(self)
return ""
class VariableClBuilderProfileBranch(update.VariableClUpdateProfileBranch): class VariableClBuilderProfileBranch(update.VariableClUpdateProfileBranch):
""" """
Текущая ветка репозитория Текущая ветка репозитория
""" """
untrusted = True
def get(self): storage = "builder.cl_builder_profile_storage"
action = self.Get('cl_action') url = "builder.cl_builder_profile_url"
if action in ("image"):
pass
#rep_set = self.Get('cl_update_profile_storage')
#url = self.Get('cl_update_profile_url')
##print url, rep_set.is_local(url, branch=None)
#if rep_set.is_local(url, branch=None):
# rep = rep_set.get_repository(url, branch=None)
# git = Git()
# return git.getBranch(rep.directory)
return update_profile.DEFAULT_BRANCH
class VariableClProfileCacheRepository(ReadonlyVariable):
"""
Репозиторий из которого будет извлечён список профилей
"""
type = "object"
def get(self):
url = self.Get('cl_builder_profile_url')
if not url:
return ""
try:
rep_set = self.Get('cl_builder_profile_storage')
branch = self.Get('cl_builder_profile_branch')
rep = rep_set.get_repository(url, branch)
#if rep and self.Get('cl_update_profile_sync_set') == 'on':
if rep:
rep.sync()
return rep_set.get_repository(url, branch) or ""
except GitError:
return ""
class VariableClProfileCacheData(update.VariableClProfileData):
source = []
repository = "cl_profile_cache_repository"
class VariableClBuilderProfileData(update.VariableClProfileData): class VariableClBuilderProfileData(update.VariableClProfileData):
type = "table" type = "table"
@ -122,18 +73,7 @@ class VariableClBuilderProfileData(update.VariableClProfileData):
"cl_builder_profile_path", "cl_builder_profile_path",
"cl_builder_profile_arch"] "cl_builder_profile_arch"]
def init(self): repository = "builder.cl_builder_profile_repository"
self.label = "test"
def get(self, hr=False):
url = self.Get('cl_builder_profile_url')
if not url:
dv = self.Get('cl_builder_linux_datavars')
if dv:
return dv['cl_profile_data']
return [[]]
else:
return self.Get('cl_profile_cache_data')
class VariableClBuilderProfileFullname(FieldValue, ReadonlyVariable): class VariableClBuilderProfileFullname(FieldValue, ReadonlyVariable):
@ -172,159 +112,133 @@ class VariableClBuilderProfileArch(FieldValue, ReadonlyVariable):
column = 3 column = 3
class VariableClBuilderProfileSystemShortname(Variable): class VariableClBuilderProfileName(lib_linux.VariableClProfileName):
""" """
Профиль системы Install subname
""" """
type = "choice" source_var = "cl_builder_profile_system"
opt = ["--profile"]
untrusted = True
metavalue = "PROFILE"
def init(self): def init(self):
self.label = _("System profile") self.label = _("System profile")
self.help = _("set the system profile")
def check_profile(self, path_profile, profile_fullname): class VariableClBuilderProfileRepoName(update.VariableClUpdateProfileRepoName):
if path_profile: """
dv = update.DataVarsUpdateProfile(path_profile) Название репозитория
if ":" in profile_fullname: """
repo_name = profile_fullname.partition(":")[0] storage = "builder.cl_builder_profile_storage"
else: url = "builder.cl_builder_profile_url"
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 check(self, profile):
if not profile:
raise VariableError(_("You must specify the profile"))
action = self.Get('cl_action')
if action == 'create':
url = self.Get('cl_builder_profile_url')
# внеший репозиторий профилей
if url:
path_profile, profile_fullname = \
path_profile = self.Select(
'cl_builder_profile_path',
where='cl_builder_profile_shortname',
eq=profile, limit=1)
profile_fullname = self.Select(
'cl_builder_profile_fullname',
where='cl_builder_profile_shortname',
eq=profile, limit=1)
self.check_profile(path_profile, profile_fullname)
# репозиторий в образе
else:
self.check_inner_profile(profile)
def check_inner_profile(self, profile):
"""
Проверка профиля находящегося в репозитории образа системы
"""
image = self.Get('cl_builder_source')
dv = self.Get('cl_builder_linux_datavars')
if not image or not dv:
raise VariableError(_("Failed to check profile: "
"wrong source"))
if image:
if isinstance(image, distr.ArchiveDistributive):
raise VariableError(_("Unavailable to use profile from "
"stage distributive"))
with image:
try:
distr_dn = image.getDirectory()
profile_dn = self.Select(
'cl_builder_profile_path',
where="cl_builder_profile_shortname",
eq=profile, limit=1)
profile_fullname = self.Select(
'cl_builder_profile_fullname',
where="cl_builder_profile_shortname",
eq=profile, limit=1)
if not profile_dn:
raise VariableError()
profile_dn = dv.change_root(profile_dn, distr_dn)
self.check_profile(profile_dn, profile_fullname)
except distr.DistributiveError:
raise VariableError(_("Failed to check profile: "
"failed to mount source"))
def get_by_url(self):
shortname = self.Get('cl_builder_profile_shortname')
if len(shortname) == 1:
return shortname[0]
return ""
def get_from_image(self): class VariableClBuilderProfileRepository(
dv = self.Get('cl_builder_linux_datavars') update.VariableClUpdateProfileRepository):
if dv: """
try: Репозиторий из которого будет извлечён список профилей
profile_system = dv["cl_profile_system"] """
for (fullname, shortname, type = "object"
_path, arch) in dv.Get('cl_profile_data'): url = "builder.cl_builder_profile_url"
if _path == profile_system: storage = "builder.cl_builder_profile_storage"
return shortname branch = "builder.cl_builder_profile_branch"
except VariableError:
pass
return ""
def get(self):
action = self.Get('cl_action')
if action == 'create':
url = self.Get('cl_builder_profile_url')
if url:
return self.get_by_url()
else:
return self.get_from_image()
return ""
def choice(self): class VariableClBuilderTemplatesLocate(update.VariableClUpdateTemplatesLocate):
arch = self.Get('os_arch_machine_gentoo') """
profiles = zip(*self.Select(['cl_builder_profile_shortname', Выбранные типы хранилищ шаблонов
'cl_builder_profile_fullname'], """
where='cl_builder_profile_arch', eq=arch)) check_after = ['cl_builder_profile_system']
if profiles:
short_name, full_name = profiles profile_datevars = "builder.cl_builder_profile_datavars"
return zip(short_name, full_name)
return []
class VariableClBuilderProfileSystem(ReadonlyVariable): class VariableClBuilderProfileDatavars(update.VariableClUpdateProfileDatavars):
type = "object"
profile = "builder.cl_builder_profile_system_shortname"
profiles_path = "builder.cl_builder_profile_path"
profiles_shortname = "builder.cl_builder_profile_shortname"
def get(self): def get(self):
action = self.Get('cl_action') profile = self.Get(self.profile)
if action == 'create': path_profile = self.Select(self.profiles_path,
shortname = self.Get('cl_builder_profile_system_shortname') where=self.profiles_shortname,
profile = self.Select('cl_builder_profile_path', eq=profile, limit=1)
where="cl_builder_profile_shortname", #print self.Get(self.profiles_path)
eq=shortname, limit=1) #print self.Get(self.profiles_shortname)
if profile: #print profile
return profile builder_path = self.Get('cl_builder_path')
#print "BUILDER_PATH", builder_path
if path_profile:
return DataVarsUpdateProfile(path_profile, builder_path)
return "" return ""
class VariableClBuilderProfileSystemShortname(
update.VariableClUpdateProfileSystem):
"""
Выбираемый профиль
"""
opt = ["cl_builder_profile_system_shortname"]
class VariableClBuilderProfileName(lib_linux.VariableClProfileName): profiles_path = "builder.cl_builder_profile_path"
profiles_shortname = "builder.cl_builder_profile_shortname"
profiles_fullname = "builder.cl_builder_profile_fullname"
profiles_arch = "builder.cl_builder_profile_arch"
profile = "builder.cl_builder_profile_system"
url = "builder.cl_builder_profile_url"
gentoo_arch = 'builder.os_builder_arch_machine_gentoo'
class VariableOsBuilderArchMachineGentoo(lib_system.VariableOsArchMachineGentoo):
""" """
Install subname Архитектура пакетов
""" """
source_var = "cl_builder_profile_system" source_arch = "builder.os_builder_arch_machine"
class VariableClBuilderProfileLinuxFullname(
update.VariableClUpdateProfileLinuxFullname):
"""
Имя системы в профиле
"""
datavars = "builder.cl_builder_profile_datavars"
class VariableClBuilderProfileDependData(
update.VariableClUpdateProfileDependData):
"""
Зависимые репозитории
"""
source = ['cl_builder_profile_depend_name',
'cl_builder_profile_depend_url']
datavars = "cl_builder_profile_datavars"
class VariableClBuilderProfileDependName(FieldValue, ReadonlyVariable):
type = "list"
source_variable = "cl_builder_profile_depend_data"
column = 0
def init(self): def init(self):
self.label = _("System profile") self.label = _("Name")
class VariableClBuilderProfileDependUrl(FieldValue, ReadonlyVariable):
type = "list"
source_variable = "cl_builder_profile_depend_data"
column = 1
def init(self):
self.label = _("URL")
class VariableClBuilderProfileSyncRep(ReadonlyVariable):
type = "list"
def get(self):
return list(reversed(self.Get('update.cl_update_rep_name')))
class VariableClBuilderRemoveRep(ReadonlyVariable):
def get(self):
dv_builder_linux = self.Get('cl_builder_linux_datavars')
dv_builder_profile = self.Get('cl_builder_profile_datavars')
if dv_builder_linux and dv_builder_profile:
return list(set(dv_builder_linux.Get('cl_update_rep_name')) -
set(dv_builder_profile.Get('cl_update_rep_name')))
else:
return []

@ -16,15 +16,20 @@
import sys import sys
from calculate.lib.datavars import VariableError,DataVarsError,DataVars from calculate.lib.datavars import VariableError, DataVarsError, DataVars
from calculate.core.server.func import WsdlBase from calculate.core.server.func import WsdlBase
from calculate.install.install import InstallError, Install from calculate.install.install import InstallError, Install
from calculate.update.emerge_parser import EmergeError
from .builder import Builder from .builder import Builder
from calculate.update.update import Update, UpdateError
from .datavars import BuilderError from .datavars import BuilderError
from .variables.action import Actions as BuilderActions
from calculate.lib.utils.portage import GitError from calculate.lib.utils.portage import GitError
from utils.cl_builder_create import ClBuilderCreateAction from utils.cl_builder_prepare import ClBuilderPrepareAction
from utils.cl_builder_profile import ClBuilderProfileAction
from utils.cl_builder_break import ClBuilderBreakAction from utils.cl_builder_break import ClBuilderBreakAction
from utils.cl_builder_update import ClBuilderUpdateAction
from utils.cl_builder_restore import ClBuilderRestoreAction from utils.cl_builder_restore import ClBuilderRestoreAction
from utils.cl_builder_image import ClBuilderImageAction from utils.cl_builder_image import ClBuilderImageAction
from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate from calculate.lib.cl_lang import setLocalTranslate,getLazyLocalTranslate
@ -39,7 +44,7 @@ class Wsdl(WsdlBase):
# #
{ {
# идентификатор метода # идентификатор метода
'method_name': "builder_create", 'method_name': "builder_prepare",
# категория метода # категория метода
'category': __('Builder'), 'category': __('Builder'),
# заголовок метода # заголовок метода
@ -49,20 +54,20 @@ class Wsdl(WsdlBase):
# метод присутствует в графической консоли # метод присутствует в графической консоли
'gui': True, 'gui': True,
# консольная команда # консольная команда
'command': 'cl-builder-create', 'command': 'cl-builder-prepare',
# права для запуска метода # права для запуска метода
'rights': ['build'], 'rights': ['build'],
# объект содержащий модули для действия # объект содержащий модули для действия
'logic': {'Builder': Builder, 'logic': {'Builder': Builder,
'Install': Install}, 'Install': Install},
# описание действия # описание действия
'action': ClBuilderCreateAction, 'action': ClBuilderPrepareAction,
# объект переменных # объект переменных
'datavars': "builder", 'datavars': "builder",
'native_error': (VariableError, DataVarsError, 'native_error': (VariableError, DataVarsError,
InstallError, BuilderError, GitError), InstallError, BuilderError, GitError),
# значения по умолчанию для переменных этого метода # значения по умолчанию для переменных этого метода
'setvars': {'cl_action!': 'create', 'setvars': {'cl_action!': BuilderActions.Prepare,
'cl_dispatch_conf': 'usenew'}, 'cl_dispatch_conf': 'usenew'},
# описание груп (список лямбда функций) # описание груп (список лямбда функций)
'groups': [ 'groups': [
@ -70,9 +75,6 @@ class Wsdl(WsdlBase):
normal=('cl_builder_source_filename', normal=('cl_builder_source_filename',
'cl_builder_new_id', 'cl_builder_new_id',
'cl_builder_disk_dev', 'cl_builder_disk_dev',
'cl_builder_profile_url',
'cl_builder_profile_branch',
'cl_builder_profile_system_shortname',
'cl_builder_layered_set'), 'cl_builder_layered_set'),
expert=('cl_templates_locate', expert=('cl_templates_locate',
'cl_verbose_set', 'cl_verbose_set',
@ -83,7 +85,6 @@ class Wsdl(WsdlBase):
brief=('os_builder_linux_ver', brief=('os_builder_linux_ver',
'os_builder_linux_system', 'os_builder_linux_system',
'cl_builder_disk_size', 'cl_builder_disk_size',
'cl_builder_profile_data',
'cl_builder_profile_name'), 'cl_builder_profile_name'),
next_label=_("Perform"))], next_label=_("Perform"))],
'brief': {'next': __("Perform"), 'brief': {'next': __("Perform"),
@ -114,7 +115,7 @@ class Wsdl(WsdlBase):
'native_error': (VariableError, DataVarsError, 'native_error': (VariableError, DataVarsError,
InstallError, BuilderError, GitError), InstallError, BuilderError, GitError),
# значения по умолчанию для переменных этого метода # значения по умолчанию для переменных этого метода
'setvars': {'cl_action!': 'break'}, 'setvars': {'cl_action!': BuilderActions.Break},
# описание груп (список лямбда функций) # описание груп (список лямбда функций)
'groups': [ 'groups': [
lambda group: group(_("Break the assemble"), lambda group: group(_("Break the assemble"),
@ -124,6 +125,42 @@ class Wsdl(WsdlBase):
'cl_verbose_set', 'cl_dispatch_conf'), 'cl_verbose_set', 'cl_dispatch_conf'),
next_label=_("Perform"))] next_label=_("Perform"))]
}, },
{
# идентификатор метода
'method_name': "builder_update",
# категория метода
'category': __('Builder'),
# заголовок метода
'title': __("Update the assemble"),
# иконка для графической консоли
'image': 'calculate-update',
# метод присутствует в графической консоли
'gui': True,
# консольная команда
'command': 'cl-builder-update',
# права для запуска метода
'rights': ['build'],
# объект содержащий модули для действия
'logic': {'Builder': Builder,
'Install': Install},
# описание действия
'action': ClBuilderUpdateAction,
# объект переменных
'datavars': "builder",
'native_error': (VariableError, DataVarsError,
InstallError, BuilderError, GitError),
# значения по умолчанию для переменных этого метода
'setvars': {'cl_action!': BuilderActions.Update,
'cl_dispatch_conf': 'usenew'},
# описание груп (список лямбда функций)
'groups': [
lambda group: group(_("Update the assemble"),
normal=('cl_builder_prepared_id',
'cl_builder_videodrv_set',),
expert=('cl_templates_locate',
'cl_verbose_set', 'cl_dispatch_conf'),
next_label=_("Perform"))]
},
{ {
# идентификатор метода # идентификатор метода
'method_name': "builder_restore", 'method_name': "builder_restore",
@ -149,7 +186,7 @@ class Wsdl(WsdlBase):
'native_error': (VariableError, DataVarsError, 'native_error': (VariableError, DataVarsError,
InstallError, BuilderError, GitError), InstallError, BuilderError, GitError),
# значения по умолчанию для переменных этого метода # значения по умолчанию для переменных этого метода
'setvars': {'cl_action!': 'restore'}, 'setvars': {'cl_action!': BuilderActions.Restore},
# описание груп (список лямбда функций) # описание груп (список лямбда функций)
'groups': [ 'groups': [
lambda group: group(_("Break the assemble"), lambda group: group(_("Break the assemble"),
@ -180,10 +217,10 @@ class Wsdl(WsdlBase):
'action': ClBuilderImageAction, 'action': ClBuilderImageAction,
# объект переменных # объект переменных
'datavars': "builder", 'datavars': "builder",
'native_error': (VariableError, DataVarsError, 'native_error': (VariableError, DataVarsError, EmergeError,
InstallError, BuilderError, GitError), InstallError, BuilderError, GitError),
# значения по умолчанию для переменных этого метода # значения по умолчанию для переменных этого метода
'setvars': {'cl_action!': 'image', 'setvars': {'cl_action!': BuilderActions.Image,
'cl_dispatch_conf': 'usenew'}, 'cl_dispatch_conf': 'usenew'},
# описание груп (список лямбда функций) # описание груп (список лямбда функций)
'groups': [ 'groups': [
@ -202,5 +239,58 @@ class Wsdl(WsdlBase):
next_label=_("Perform")),], next_label=_("Perform")),],
'brief': {'next': __("Perform"), 'brief': {'next': __("Perform"),
'name': __("Create the image")} 'name': __("Create the image")}
} },
#
# Сменить профиль
#
{
# идентификатор метода
'method_name': "builder_profile",
# категория метода
'category': __('Builder'),
# заголовок метода
'title': __("Change the Assemble Profile"),
# иконка для графической консоли
'image': 'extension',
# метод присутствует в графической консоли
'gui': True,
# консольная команда
'command': 'cl-builder-profile',
# права для запуска метода
'rights': ['builder'],
# объект содержащий модули для действия
'logic': {'Builder': Builder},
# описание действия
'action': ClBuilderProfileAction,
# объект переменных
'datavars': "builder",
'native_error': (VariableError, DataVarsError, UpdateError,
InstallError, BuilderError, GitError),
# значения по умолчанию для переменных этого метода
'setvars': {'cl_action!': BuilderActions.ChangeProfile},
# описание груп (список лямбда функций)
'groups': [
lambda group: group(_("Repository"),
brief=('cl_builder_profile_repo_name',),
hide=('cl_builder_profile_url',
'update.cl_update_profile_sync_set'),
normal=('cl_builder_profile_url',
'cl_builder_prepared_id'),
expert=('update.cl_update_profile_sync_set',
'cl_builder_profile_branch')),
lambda group: group(_("Profile"),
normal=('cl_builder_profile_system_shortname',
'update.cl_update_world'),
expert=('update.cl_update_skip_setup_set',
'cl_builder_templates_locate',
'cl_verbose_set',
'cl_dispatch_conf'),
hide=('cl_builder_templates_locate',
'cl_verbose_set',
'cl_dispatch_conf'),
brief=('cl_builder_profile_linux_fullname',
'cl_builder_profile_depend_data')
)],
'brief': {'next': __("Perform"),
'name': __("Set the profile")}},
] ]

Loading…
Cancel
Save