Добавлена поддержка grub live

parent 86cbc19e2f
commit 9d7f8723f6

@ -15,11 +15,13 @@
# limitations under the License.
from itertools import chain
import re
import sys
import time
import stat
from calculate.core.server.gen_pid import search_worked_process2
from calculate.core.setup_package import ChainProgressTemplate
from calculate.lib.datavars import DataVars
from calculate.lib.utils.colortext import TextState, get_color_print, \
convert_console_to_xml
@ -45,6 +47,7 @@ import os
from os import path
from .datavars import BuilderError
from .emerge_fetch import EmergeFetcher, EmergeFetcherError
from calculate.lib.utils.grub import GrubCommand
_ = lambda x: x
from calculate.lib.cl_lang import (setLocalTranslate, getLazyLocalTranslate)
@ -65,7 +68,7 @@ class Builder(Update):
Restore = "builder_restore"
Image = "builder_image"
Profile = "builder_profile"
UpdateMenu = "builder_menu"
UpdateMenu = "update_livemenu"
All = (Prepare, Break, Update, Restore, Image, Profile)
def init(self):
@ -1128,6 +1131,7 @@ class Builder(Update):
"""
if not dn:
raise BuilderError(_("Failed to remount Flash drive"))
p = process('/bin/mount', '-o', 'remount,rw', dn, stderr=STDOUT)
if p.failed():
self.printERROR(p.read().strip())
@ -1196,3 +1200,79 @@ class Builder(Update):
self.printWARNING(_("Failed to migrate flash linux directory"))
self.printWARNING(str(e))
return True
def create_iso_grub_cfg(self, dn):
gc = GrubCommand()
content = []
for label, iso, splash in self.clVars.ZipVars(
'cl_builder_image_label',
'cl_builder_image_iso',
'cl_builder_image_splash'):
entry = (
"menuentry '%(label)s' {\n"
"\tset isofile=%(iso)s\n"
"\tloopback loop $isofile\n"
"\tlinux (loop)/boot/vmlinuz root=live "
"iso-scan/filename=$isofile quiet %(splash)s\n"
"\tinitrd (loop)/boot/initrd\n}\n\n" % {
'label': label,
'iso': gc.get_relpath(iso),
'splash': 'splash=silent,theme:calculate console=tty1'
})
content.append(entry)
fn_grubcfg = path.join(dn, 'grub.cfg')
try:
with writeFile(fn_grubcfg) as f:
f.write(("\n".join(content)).strip()+"\n")
except IOError:
raise BuilderError(_("Failed to write %s") % fn_grubcfg)
return True
def clear_iso_grub_cfg(self, dn):
if dn:
cfg_fn = path.join(dn, 'grub.cfg')
if path.exists(cfg_fn):
try:
os.unlink(cfg_fn)
except OSError:
raise BuilderError(_("Failed to remove %s")%cfg_fn)
return True
def setup_package(self, package):
"""
Обновить конфигурационные файлы системы
"""
clVars = DataVars()
try:
clVars.importData()
clVars.flIniFile()
clVars.Set("cl_root_path", "/", True)
clVars.Set("cl_merge_pkg", [package], True)
clVars.Set("cl_action", 'merge', True)
for copyvar in ("cl_dispatch_conf", "cl_verbose_set",
"cl_template_path_use",
"builder.cl_livemenu_path",
"builder.cl_builder_livemenu_path"):
clVars.Set(copyvar, self.clVars.Get(copyvar), force=True)
useClt = self.clVars.Get('cl_template_clt_set') in (True, "on")
# используем объект шаблонов
# с clt шаблонами, clt фильтром, без использования postDispatchConf
clTempl = ChainProgressTemplate(
self.startTask,
self.endTask,
self.setProgress,
clVars, cltObj=useClt,
cltFilter=True,
printSUCCESS=self.printSUCCESS,
printERROR=self.printERROR,
printWARNING=self.printWARNING,
askConfirm=self.askConfirm,
dispatchConf=self.dispatchConf,
printWarning=False)
clTempl.applyTemplates()
finally:
clVars.close()
self.endTask()
return True

@ -37,8 +37,7 @@ class ClBuilderMenuAction(Action):
"""
# ошибки, которые отображаются без подробностей
native_error = (DistributiveError, FilesError, UpdateError,
TemplatesError,
BuilderError, GitError, EmergeError)
TemplatesError, BuilderError, GitError, EmergeError)
successMessage = __("Boot menu updated successfully")
failedMessage = __("Failed to update boot menu")
@ -46,16 +45,46 @@ class ClBuilderMenuAction(Action):
# список задач для действия
tasks = [
{'name': 'mount_flash',
{'name': 'flash',
'condition': lambda Get: Get('cl_builder_livemenu_type') == 'flash'
},
{'name': 'grub',
'condition': lambda Get: Get('cl_builder_livemenu_type') != 'flash'
},
{'name': 'grub:grub_image_menu',
'method': 'Builder.set_builder_action("%s")' % Actions.ImageMenu,
},
{'name': 'grub:update_grub_menu',
'message': __("Creating the ISO images menu"),
'method': 'Builder.create_iso_grub_cfg(cl_builder_livemenu_path)',
'condition': lambda Get: (
Get('os_root_type') == 'hdd' and
Get('builder.cl_builder_livemenu_path') != "")
},
{'name': 'grub:clear_grub_menu',
'message': __("Clearing the ISO images menu"),
'method': 'Builder.clear_iso_grub_cfg(cl_livemenu_path)',
'condition': lambda Get: (
Get('os_root_type') == 'hdd' and
Get('builder.cl_builder_livemenu_path') == "")
},
{'name': 'grub:setup_grub',
'message': __("Configuration grub {cl_builder_livemenu_path}"),
'method': 'Builder.setup_package("sys-boot/grub")',
'condition': lambda Get: (Get('os_root_type') == "hdd" and
Get('builder.cl_builder_livemenu_path') !=
Get('builder.cl_livemenu_path'))
},
{'name': 'flash:mount_flash',
'method': 'Builder.remount_rw(cl_builder_flash_path)',
},
{'name': 'iso_linux_migrate',
{'name': 'flash:iso_linux_migrate',
'method': 'Builder.iso_migrate(cl_builder_flash_path)'
},
{'name': 'protect_off',
{'name': 'flash:protect_off',
'method': 'Builder.setVariable("cl_protect_use_set","off",True)'
},
{'name': 'image_menu',
{'name': 'flash:image_menu',
'method': 'Builder.set_builder_action("%s")' % Actions.ImageMenu,
},
{'name': 'image_menu:sync_vmlinuz',
@ -63,7 +92,7 @@ class ClBuilderMenuAction(Action):
'method': 'Builder.sync_vmlinuz(cl_builder_flash_path)'
},
{'name': 'image_menu:update_menu',
'message': __("Recreating ISO image menu"),
'message': __("Recreating the ISO images menu"),
'method': 'Builder.update_menu(cl_builder_flash_path)',
},
]

@ -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 ""

@ -22,11 +22,8 @@ from calculate.install.distr import IsoDistributive, DistributiveError
from calculate.lib.utils.files import listDirectory
from calculate.lib.datavars import ReadonlyVariable, HumanReadable, \
ReadonlyTableVariable, FieldValue, VariableError, Variable
from calculate.install.variables.system import VariableOsInstallX11ServerSet
from builder import (VariableClBuilderPath, VariableClBuilderKernel,
VariableClBuilderKernelVer, VariableClBuilderInitrdInstall,
VariableClBuilderVideoDriverPath,
VariableClBuilderVideodrvSet)
from calculate.install.variables import system
import builder
from action import Actions
_ = lambda x: x
@ -74,14 +71,14 @@ class DataVarsBuilderImage(LinuxDataVars):
def variables(self):
l = super(DataVarsBuilderImage, self).variables()
return l + [
VariableClBuilderPath(),
VariableClBuilderKernel(),
VariableClBuilderInitrdInstall(),
VariableClBuilderKernelVer(),
VariableOsInstallX11ServerSet(image=False,
builder.VariableClBuilderPath(),
builder.VariableClBuilderKernel(),
builder.VariableClBuilderInitrdInstall(),
builder.VariableClBuilderKernelVer(),
system.VariableOsInstallX11ServerSet(image=False,
prefix_variable="cl_builder_path"),
VariableClBuilderVideoDriverPath(),
VariableClBuilderVideodrvSet(autodetect=True),
builder.VariableClBuilderVideoDriverPath(),
builder.VariableClBuilderVideodrvSet(autodetect=True),
VariableClBuilderIsoLabel(),
VariableClBuilderSplash(),
]
@ -168,7 +165,7 @@ class VariableClBuilderImageData(ReadonlyTableVariable):
pass
def get(self, hr=HumanReadable.No):
isopath = self.Get('cl_builder_flash_repository')
isopath = self.Get('cl_builder_image_repository')
if self.Get('cl_builder_action') != Actions.ImageMenu or not isopath:
return [[]]
return list(self.generator(isopath))

@ -205,15 +205,15 @@ class Wsdl(WsdlBase):
# идентификатор метода
'method_name': Builder.Method.UpdateMenu,
# категория метода
'category': __('Builder'),
'category': __('Update'),
# заголовок метода
'title': __("Update Boot Menu"),
'title': __("Update Live-Menu"),
# иконка для графической консоли
'image': 'format-indent-less-rtl,format-indent-more',
# метод присутствует в графической консоли
'gui': True,
# консольная команда
'command': 'cl-builder-menu',
'command': 'cl-update-livemenu',
# права для запуска метода
'rights': ['build'],
# объект содержащий модули для действия
@ -230,8 +230,12 @@ class Wsdl(WsdlBase):
# описание груп (список лямбда функций)
'groups': [
lambda group: group(_("Update Boot Menu"),
normal=('cl_builder_flash_dev_path',),
normal=(
'cl_builder_livemenu_type',
'cl_builder_livemenu_path',),
next_label=_("Perform"))],
'brief': {'next': __("Perform"),
'name': __("Update Live-Menu")},
},
{
# идентификатор метода

Loading…
Cancel
Save