|
|
|
@ -19,31 +19,38 @@ import sys
|
|
|
|
|
from os import path
|
|
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
import random
|
|
|
|
|
import string
|
|
|
|
|
from calculate.install.distr import DistributiveError, IsoDistributive
|
|
|
|
|
from calculate.install.variables.kernel import KernelConfig
|
|
|
|
|
from calculate.lib.utils.common import getValueFromCmdLine
|
|
|
|
|
from calculate.lib.utils.dracut import Dracut
|
|
|
|
|
from calculate.lib.utils.grub import GrubCommand
|
|
|
|
|
from calculate.lib.utils.portage import getSquashList
|
|
|
|
|
from calculate.lib.variables.system import RootType
|
|
|
|
|
from .action import Actions
|
|
|
|
|
from calculate.install import distr
|
|
|
|
|
from calculate.lib.utils.device import getUdevDeviceInfo, humanreadableSize
|
|
|
|
|
from calculate.lib.utils.files import isMount, process, typeFile, listDirectory, \
|
|
|
|
|
pathJoin
|
|
|
|
|
pathJoin, readFile
|
|
|
|
|
from calculate.lib.utils.kernel import InitrdFile
|
|
|
|
|
from calculate.lib.utils.tools import max_default
|
|
|
|
|
from calculate.lib.utils.git import Git
|
|
|
|
|
from ..build_storage import BuildStorage, Build
|
|
|
|
|
from ..drive_spool import DriveSpool
|
|
|
|
|
from .action import Actions as BuilderActions
|
|
|
|
|
from calculate.lib.datavars import Variable, VariableError, ReadonlyVariable, \
|
|
|
|
|
TableVariable
|
|
|
|
|
from functools import wraps
|
|
|
|
|
|
|
|
|
|
_ = lambda x: x
|
|
|
|
|
|
|
|
|
|
from calculate.lib.cl_lang import setLocalTranslate
|
|
|
|
|
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
|
|
|
|
|
|
|
|
|
|
setLocalTranslate('cl_builder3', sys.modules[__name__])
|
|
|
|
|
|
|
|
|
|
__ = getLazyLocalTranslate(_)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_action(*available_action, **action_kwargs):
|
|
|
|
|
def decorator(func):
|
|
|
|
@ -731,6 +738,13 @@ class VariableClBuilderAction(ReadonlyVariable):
|
|
|
|
|
value = ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VariableClBuilderImagePath(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Путь по умолчанию для образов
|
|
|
|
|
"""
|
|
|
|
|
value = '/var/calculate/linux'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VariableClBuilderImageFilename(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Название iso образа
|
|
|
|
@ -739,8 +753,6 @@ class VariableClBuilderImageFilename(Variable):
|
|
|
|
|
metavalue = "IMAGE"
|
|
|
|
|
untrusted = True
|
|
|
|
|
|
|
|
|
|
default_base_dn = '/var/calculate/linux'
|
|
|
|
|
|
|
|
|
|
def init(self):
|
|
|
|
|
self.label = _("Image path")
|
|
|
|
|
self.help = _("set image path")
|
|
|
|
@ -776,7 +788,7 @@ class VariableClBuilderImageFilename(Variable):
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
build_id = self.Get('cl_builder_id')
|
|
|
|
|
base_dn = self.default_base_dn
|
|
|
|
|
base_dn = self.Get('cl_builder_image_path')
|
|
|
|
|
|
|
|
|
|
if build_id:
|
|
|
|
|
if self.Get('os_root_type_ext') in RootType.RebuildAvailable:
|
|
|
|
@ -1218,7 +1230,7 @@ class VariableClBuilderKeepTreeSet(Variable):
|
|
|
|
|
"""
|
|
|
|
|
type = "bool"
|
|
|
|
|
opt = ["--keep-tree"]
|
|
|
|
|
value = "off"
|
|
|
|
|
value = "on"
|
|
|
|
|
|
|
|
|
|
def init(self):
|
|
|
|
|
self.help = _("keep portage tree in image")
|
|
|
|
@ -1262,14 +1274,12 @@ class VariableClBuilderPrelinkSet(Variable):
|
|
|
|
|
"""
|
|
|
|
|
type = "bool"
|
|
|
|
|
opt = ["--prelink"]
|
|
|
|
|
value = "off"
|
|
|
|
|
|
|
|
|
|
def init(self):
|
|
|
|
|
self.help = _("perform prelink")
|
|
|
|
|
self.label = _("Perform prelink")
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
return "on" if self.GetBool('cl_builder_binary_set') else "off"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VariableClBuilderRebuildChangedSet(Variable):
|
|
|
|
|
"""
|
|
|
|
@ -1307,55 +1317,221 @@ class VariableClBuilderFlashRepository(ReadonlyVariable):
|
|
|
|
|
suffix = "linux"
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
return path.join(self.Get('cl_builder_flash_path'), self.suffix)
|
|
|
|
|
flash_path = self.Get('cl_builder_flash_path')
|
|
|
|
|
if flash_path:
|
|
|
|
|
return path.join(flash_path, self.suffix)
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VariableClBuilderFlashDevPath(Variable):
|
|
|
|
|
class VariableClBuilderLivemenuType(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Путь до устройства flash
|
|
|
|
|
Тип обновляемого live меню
|
|
|
|
|
"""
|
|
|
|
|
opt = ["-d", "--disk"]
|
|
|
|
|
metavalue = "FLASH"
|
|
|
|
|
type = "choiceedit"
|
|
|
|
|
type = "choice"
|
|
|
|
|
opt = ["--type"]
|
|
|
|
|
metavalue = "TYPE"
|
|
|
|
|
|
|
|
|
|
def init(self):
|
|
|
|
|
self.label = _("Flash drive")
|
|
|
|
|
self.help = _("set Flash drive")
|
|
|
|
|
self.label = _("Type")
|
|
|
|
|
self.help = _("set livemenu type")
|
|
|
|
|
|
|
|
|
|
untrusted = True
|
|
|
|
|
|
|
|
|
|
def choice(self):
|
|
|
|
|
return [("grub", _("Grub")),
|
|
|
|
|
("flash", _("Flash"))]
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
root_type_ext = self.Get('os_root_type_ext')
|
|
|
|
|
if root_type_ext == RootType.LiveFlash:
|
|
|
|
|
return Dracut.IsoLive
|
|
|
|
|
if root_type_ext == RootType.IsoScan:
|
|
|
|
|
return Dracut.IsoScanPath
|
|
|
|
|
if root_type_ext in RootType.Grubable:
|
|
|
|
|
return "grub"
|
|
|
|
|
elif root_type_ext in RootType.RebuildAvailable:
|
|
|
|
|
return "flash"
|
|
|
|
|
else:
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VariableClBuilderImageRepository(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Хранилище образов
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
livemenu_type = self.Get('cl_builder_livemenu_type')
|
|
|
|
|
if livemenu_type == "grub":
|
|
|
|
|
return self.Get('cl_builder_livemenu_path')
|
|
|
|
|
else:
|
|
|
|
|
return self.Get('cl_builder_flash_repository')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VariableClLivemenuPath(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Текущий путь до репозитория образов
|
|
|
|
|
"""
|
|
|
|
|
grub_config = "/etc/grub.d/90_calculate"
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
data = readFile(self.grub_config)
|
|
|
|
|
m = re.search('^livepath=([^\n]+)', data, re.M)
|
|
|
|
|
if m:
|
|
|
|
|
return m.group(1).strip("'\"")
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
def choice(self):
|
|
|
|
|
|
|
|
|
|
class VariableClIsoscanPath(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
|
Образ с которого загружена система
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
root_type_ext = self.Get('os_root_type_ext')
|
|
|
|
|
if root_type_ext in RootType.IsoScan:
|
|
|
|
|
return getValueFromCmdLine("iso-scan/filename", 0)
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VariableClBuilderLivemenuPath(Variable):
|
|
|
|
|
"""
|
|
|
|
|
Путь до устройства flash
|
|
|
|
|
"""
|
|
|
|
|
opt = ["cl_builder_livemenu_path"]
|
|
|
|
|
type = "choiceedit"
|
|
|
|
|
metavalue = "PATH"
|
|
|
|
|
untrusted = True
|
|
|
|
|
none_humanreadable = __("Clear live images from boot menu")
|
|
|
|
|
|
|
|
|
|
def init(self):
|
|
|
|
|
self.help = _("set path")
|
|
|
|
|
self.label = _("Path")
|
|
|
|
|
|
|
|
|
|
def get_isoscan_grub_repository(self):
|
|
|
|
|
isoscan_path = self.Get('cl_isoscan_path')
|
|
|
|
|
if isoscan_path:
|
|
|
|
|
return path.dirname(isoscan_path)
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
def get_live_path(self):
|
|
|
|
|
live_path = self.Get('cl_livemenu_path')
|
|
|
|
|
if not live_path and self.Get('cl_action') == BuilderActions.Image:
|
|
|
|
|
live_path = self.Get('cl_live_path')
|
|
|
|
|
return live_path
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
menutype = self.Get('cl_builder_livemenu_type')
|
|
|
|
|
root_type_ext = self.Get('os_root_type_ext')
|
|
|
|
|
if root_type_ext == RootType.LiveFlash:
|
|
|
|
|
choices = [(Dracut.IsoLive, _("Boot Flash"))]
|
|
|
|
|
elif root_type_ext == RootType.IsoScan:
|
|
|
|
|
choices = [(Dracut.IsoScanPath, _("Boot Flash"))]
|
|
|
|
|
if menutype == "flash":
|
|
|
|
|
if root_type_ext in RootType.LiveFlash:
|
|
|
|
|
return Dracut.IsoLive
|
|
|
|
|
if root_type_ext in RootType.IsoScanFlash:
|
|
|
|
|
return Dracut.IsoScanPath
|
|
|
|
|
else:
|
|
|
|
|
choices = []
|
|
|
|
|
return choices + \
|
|
|
|
|
[(x, x) for x in self.select('install.os_disk_dev',
|
|
|
|
|
install_os_disk_format="vfat")]
|
|
|
|
|
if root_type_ext in RootType.IsoScanGrub:
|
|
|
|
|
return self.get_isoscan_grub_repository()
|
|
|
|
|
elif root_type_ext in RootType.Grubable:
|
|
|
|
|
return self.get_live_path()
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
def check(self, value):
|
|
|
|
|
if not value:
|
|
|
|
|
raise VariableError(_("Please specify Flash drive"))
|
|
|
|
|
if not path.exists(value):
|
|
|
|
|
raise VariableError(_("Flash drive %s not found") % value)
|
|
|
|
|
def choice(self):
|
|
|
|
|
root_type_ext = self.Get('os_root_type_ext')
|
|
|
|
|
if root_type_ext in RootType.LiveFlash:
|
|
|
|
|
yield (Dracut.IsoLive, _("Boot Flash"))
|
|
|
|
|
elif root_type_ext in RootType.IsoScan:
|
|
|
|
|
yield (Dracut.IsoScanPath, _("Boot Flash"))
|
|
|
|
|
elif root_type_ext in RootType.IsoScanGrub:
|
|
|
|
|
grub_rep = self.get_isoscan_grub_repository()
|
|
|
|
|
if grub_rep:
|
|
|
|
|
yield (Dracut.IsoScanPath, _("HDD Grub"))
|
|
|
|
|
elif root_type_ext in RootType.Grubable:
|
|
|
|
|
live_path = self.get_live_path()
|
|
|
|
|
if live_path:
|
|
|
|
|
yield (live_path, _("ISO images directory (%s)") % live_path)
|
|
|
|
|
for dev in self.select('install.os_disk_dev',
|
|
|
|
|
install_os_disk_format="vfat"):
|
|
|
|
|
yield (dev, self.flash_name(dev))
|
|
|
|
|
if root_type_ext in RootType.Grubable and \
|
|
|
|
|
root_type_ext not in RootType.IsoScanGrub:
|
|
|
|
|
yield ("none", str(self.none_humanreadable))
|
|
|
|
|
|
|
|
|
|
def _random_string(self, l=10):
|
|
|
|
|
return "".join(
|
|
|
|
|
random.choice(string.ascii_letters) for i in xrange(0, l))
|
|
|
|
|
|
|
|
|
|
def check_flash(self, value):
|
|
|
|
|
try:
|
|
|
|
|
image = IsoDistributive(value)
|
|
|
|
|
image.getIsoContentDirectory()
|
|
|
|
|
d = image.getIsoContentDirectory()
|
|
|
|
|
mark_file = path.join(d, "_mark_%s" % self._random_string())
|
|
|
|
|
try:
|
|
|
|
|
open(mark_file, 'w')
|
|
|
|
|
os.unlink(mark_file)
|
|
|
|
|
except (OSError, IOError):
|
|
|
|
|
raise ValueError("Selected device is read-only")
|
|
|
|
|
image.close()
|
|
|
|
|
except DistributiveError as e:
|
|
|
|
|
raise VariableError(str(e).strip())
|
|
|
|
|
|
|
|
|
|
def flash_name(self, dev):
|
|
|
|
|
parent_dev = self.select("install.os_disk_parent",
|
|
|
|
|
install_os_disk_dev=dev, limit=1)
|
|
|
|
|
if parent_dev:
|
|
|
|
|
dev_name = self.select("install.os_device_name",
|
|
|
|
|
install_os_device_dev=parent_dev,
|
|
|
|
|
limit=1)
|
|
|
|
|
if dev_name:
|
|
|
|
|
return "%s (%s)" % (dev_name, dev)
|
|
|
|
|
return dev
|
|
|
|
|
|
|
|
|
|
def humanReadable(self):
|
|
|
|
|
"""
|
|
|
|
|
Преобразовать указанный путь в устройство и получить его имя
|
|
|
|
|
"""
|
|
|
|
|
value = self.Get()
|
|
|
|
|
if not value:
|
|
|
|
|
return str(self.none_humanreadable)
|
|
|
|
|
if not value.startswith('/dev/'):
|
|
|
|
|
m = isMount(value)
|
|
|
|
|
else:
|
|
|
|
|
m = value
|
|
|
|
|
if m:
|
|
|
|
|
return self.flash_name(m)
|
|
|
|
|
return value
|
|
|
|
|
|
|
|
|
|
def check(self, value):
|
|
|
|
|
livemenu_type = self.Get('cl_builder_livemenu_type')
|
|
|
|
|
if livemenu_type == "flash":
|
|
|
|
|
if not value:
|
|
|
|
|
raise VariableError(_("Please specify Flash drive"))
|
|
|
|
|
if not path.exists(value):
|
|
|
|
|
raise VariableError(_("Flash drive %s not found") % value)
|
|
|
|
|
if not self.Get('cl_builder_flash_path'):
|
|
|
|
|
self.check_flash(value)
|
|
|
|
|
else:
|
|
|
|
|
root_type_ext = self.Get('os_root_type_ext')
|
|
|
|
|
if not value and root_type_ext in RootType.IsoScanGrub:
|
|
|
|
|
raise VariableError(_("Please specify images directory"))
|
|
|
|
|
if root_type_ext in RootType.Grubable:
|
|
|
|
|
if root_type_ext in RootType.IsoScanGrub:
|
|
|
|
|
grub_rep = self.get_isoscan_grub_repository()
|
|
|
|
|
if grub_rep and value != grub_rep:
|
|
|
|
|
raise VariableError(
|
|
|
|
|
_("You cannot change images directory"))
|
|
|
|
|
else:
|
|
|
|
|
if (not path.exists(value) or value.startswith('/dev') or
|
|
|
|
|
not path.isdir(value)) and value:
|
|
|
|
|
raise VariableError(_("Please specify directory"))
|
|
|
|
|
if value:
|
|
|
|
|
gc = GrubCommand()
|
|
|
|
|
if not gc.is_available(value):
|
|
|
|
|
raise VariableError(
|
|
|
|
|
_("%s is unavailable for grub") % value)
|
|
|
|
|
|
|
|
|
|
def set(self, value):
|
|
|
|
|
if value == "none":
|
|
|
|
|
value = ""
|
|
|
|
|
if value:
|
|
|
|
|
return path.normpath(value)
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VariableClBuilderFlashDev(ReadonlyVariable):
|
|
|
|
|
"""
|
|
|
|
@ -1364,12 +1540,16 @@ class VariableClBuilderFlashDev(ReadonlyVariable):
|
|
|
|
|
object = ""
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
try:
|
|
|
|
|
iso_path = self.Get('cl_builder_flash_dev_path')
|
|
|
|
|
if iso_path:
|
|
|
|
|
return IsoDistributive(iso_path)
|
|
|
|
|
except DistributiveError:
|
|
|
|
|
return ""
|
|
|
|
|
typemenu = self.Get('cl_builder_livemenu_type')
|
|
|
|
|
if typemenu == "flash":
|
|
|
|
|
try:
|
|
|
|
|
iso_path = self.Get('cl_builder_livemenu_path')
|
|
|
|
|
if iso_path.startswith('/dev/') and isMount(iso_path):
|
|
|
|
|
iso_path = isMount(iso_path)
|
|
|
|
|
if iso_path:
|
|
|
|
|
return IsoDistributive(iso_path)
|
|
|
|
|
except DistributiveError:
|
|
|
|
|
return ""
|
|
|
|
|
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1395,9 +1575,10 @@ class VariableClBuilderFlashUuid(ReadonlyVariable):
|
|
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
|
flash_path = self.Get('cl_builder_flash_path')
|
|
|
|
|
dev = isMount(flash_path)
|
|
|
|
|
if dev:
|
|
|
|
|
return self.select(
|
|
|
|
|
'install.os_disk_uuid',
|
|
|
|
|
install_os_disk_dev=dev, limit=1)
|
|
|
|
|
if flash_path:
|
|
|
|
|
dev = isMount(flash_path)
|
|
|
|
|
if dev:
|
|
|
|
|
return self.select(
|
|
|
|
|
'install.os_disk_uuid',
|
|
|
|
|
install_os_disk_dev=dev, limit=1)
|
|
|
|
|
return ""
|
|
|
|
|