|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
# Copyright 2008-2016 Mir Calculate. 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
|
|
|
import re
|
|
|
from calculate.lib.datavars import (Variable, VariableError, FieldValue,
|
|
|
VariableInterface, HumanReadable,
|
|
|
ReadonlyVariable, ReadonlyTableVariable)
|
|
|
import calculate.lib.utils.device as device
|
|
|
from calculate.lib.utils.device import humanreadableSize
|
|
|
from calculate.lib.utils import partition
|
|
|
from calculate.lib.utils.files import (readLinesFile)
|
|
|
from calculate.install.fs_manager import FileSystemManager
|
|
|
from calculate.lib.utils.tools import Sizes, traverse
|
|
|
from itertools import *
|
|
|
|
|
|
from calculate.lib.cl_lang import setLocalTranslate, _
|
|
|
from calculate.lib.variables.system import RootType
|
|
|
|
|
|
setLocalTranslate('cl_install3', sys.modules[__name__])
|
|
|
|
|
|
|
|
|
class SizeHelper(VariableInterface):
|
|
|
"""
|
|
|
Объект помогает переменной преобразовывать размер с суффиксами,
|
|
|
ведённый пользователями к "числовому" необходимому размеру
|
|
|
"""
|
|
|
default_size = Sizes.M
|
|
|
|
|
|
def set(self, value):
|
|
|
# convert table from value to MB
|
|
|
sizeMap = {'kB': Sizes.kB,
|
|
|
'K': Sizes.K,
|
|
|
'M': Sizes.M,
|
|
|
'Mb': Sizes.Mb,
|
|
|
'G': Sizes.G,
|
|
|
'Gb': Sizes.Gb,
|
|
|
'T': Sizes.T,
|
|
|
'Tb': Sizes.Tb}
|
|
|
value = value.strip()
|
|
|
reSizeValue = re.compile('^(\d+)\s*(%s)?' % "|".join(sizeMap.keys()))
|
|
|
res = reSizeValue.search(value)
|
|
|
if not res:
|
|
|
return "0"
|
|
|
intValue = int(res.group(1))
|
|
|
if res.group(2):
|
|
|
intValue = intValue * sizeMap[res.group(2)]
|
|
|
else:
|
|
|
intValue = intValue * self.default_size
|
|
|
return str(intValue)
|
|
|
|
|
|
|
|
|
class AutopartitionError(Exception):
|
|
|
"""
|
|
|
Autopartition error
|
|
|
"""
|
|
|
pass
|
|
|
|
|
|
|
|
|
class SchemeOpt(object):
|
|
|
Swap = "swap"
|
|
|
Update = "update"
|
|
|
UEFI = "uefi"
|
|
|
LVM = "lvm"
|
|
|
Calculate = "data"
|
|
|
|
|
|
|
|
|
class AutopartitionHelper(VariableInterface):
|
|
|
"""
|
|
|
Helper for autopartiton device and mount point creating
|
|
|
"""
|
|
|
def uncompatible(self):
|
|
|
if self.Get('cl_autopartition_set') == "off":
|
|
|
return _("Autopartition options are not available with manual "
|
|
|
"partitioning")
|
|
|
return ""
|
|
|
|
|
|
|
|
|
class VariableHrMemorySize(ReadonlyVariable):
|
|
|
"""
|
|
|
Memory size in bytes
|
|
|
"""
|
|
|
type = "int"
|
|
|
|
|
|
def get(self):
|
|
|
reMemTotal = re.compile(r'^MemTotal:\s*(\d+)\s*kB$')
|
|
|
totalMemList = filter(lambda x: x,
|
|
|
map(reMemTotal.search,
|
|
|
readLinesFile('/proc/meminfo')))
|
|
|
if totalMemList:
|
|
|
size = int(totalMemList[0].group(1)) * Sizes.K
|
|
|
return str(size)
|
|
|
return "0"
|
|
|
|
|
|
def humanReadable(self):
|
|
|
return humanreadableSize(self.Get())
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionSwapSize(SizeHelper, AutopartitionHelper,
|
|
|
Variable):
|
|
|
"""
|
|
|
Swap size
|
|
|
"""
|
|
|
type = "size-m"
|
|
|
opt = ["--swap-size"]
|
|
|
metavalue = "SIZE"
|
|
|
untrusted = True
|
|
|
|
|
|
def init(self):
|
|
|
self.label = _("Swap partition size") + " (MB)"
|
|
|
self.help = _("set the swap partition size for autopartition")
|
|
|
|
|
|
def get(self):
|
|
|
size = int(self.Get('hr_memory_size'))
|
|
|
if size < Sizes.G:
|
|
|
size = Sizes.G
|
|
|
return str(size)
|
|
|
|
|
|
def check(self, value):
|
|
|
if value.isdigit() and int(value) <= Sizes.M:
|
|
|
raise VariableError(
|
|
|
_("Swap size should not be less that 1MiB"))
|
|
|
|
|
|
def humanReadable(self):
|
|
|
return humanreadableSize(int(self.Get()))
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDeviceData(ReadonlyTableVariable):
|
|
|
"""
|
|
|
Список устройств, которые могут выбраны в качестве дисков под разметку
|
|
|
"""
|
|
|
|
|
|
source = ['cl_autopartition_device_dev',
|
|
|
'cl_autopartition_device_type',
|
|
|
'cl_autopartition_device_size',
|
|
|
'cl_autopartition_device_name']
|
|
|
|
|
|
re_raid = re.compile("raid[1-9]")
|
|
|
|
|
|
def get(self, hr=HumanReadable.No):
|
|
|
def generator():
|
|
|
for dev, _type, fulltype, size, name in self.ZipVars(
|
|
|
'os_device_dev', 'os_device_type',
|
|
|
'os_device_fulltype',
|
|
|
'os_device_size', 'os_device_name'):
|
|
|
if not _type.startswith('raid'):
|
|
|
_type = "device"
|
|
|
if not name:
|
|
|
name = _("Unknown")
|
|
|
else:
|
|
|
name = _type.upper()
|
|
|
if self.re_raid.search(fulltype):
|
|
|
_type = "raid"
|
|
|
else:
|
|
|
_type = "raid0"
|
|
|
|
|
|
yield [dev, _type, size, name]
|
|
|
|
|
|
return list(generator()) or [[]]
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDeviceDev(FieldValue, ReadonlyVariable):
|
|
|
type = "list"
|
|
|
source_variable = "cl_autopartition_device_data"
|
|
|
column = 0
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDeviceType(FieldValue, ReadonlyVariable):
|
|
|
type = "list"
|
|
|
source_variable = "cl_autopartition_device_data"
|
|
|
column = 1
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDeviceSize(FieldValue, ReadonlyVariable):
|
|
|
type = "list"
|
|
|
source_variable = "cl_autopartition_device_data"
|
|
|
column = 2
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDeviceName(FieldValue, ReadonlyVariable):
|
|
|
type = "list"
|
|
|
source_variable = "cl_autopartition_device_data"
|
|
|
column = 3
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDevice(AutopartitionHelper, Variable):
|
|
|
"""
|
|
|
Device for autopartition
|
|
|
"""
|
|
|
type = "choice-list"
|
|
|
element = "selecttable"
|
|
|
opt = ["-D"]
|
|
|
metavalue = "DEVICE"
|
|
|
untrusted = True
|
|
|
|
|
|
def init(self):
|
|
|
self.help = _("set the device for autopartition")
|
|
|
self.label = _("Devices for install")
|
|
|
|
|
|
def get(self):
|
|
|
choiceVal = map(lambda x: x[0], self.choice())
|
|
|
devicesTypes = self.Select(['os_device_dev','os_device_type'],
|
|
|
where='os_device_dev', _in=choiceVal)
|
|
|
notFlashDevices = [x[0] for x in devicesTypes if x[1] != 'flash']
|
|
|
if len(notFlashDevices) == 1:
|
|
|
return [notFlashDevices[0]]
|
|
|
return []
|
|
|
|
|
|
def choice(self):
|
|
|
getname = lambda dev, name, size: "%s (%s, %s)" % (
|
|
|
dev, name, humanreadableSize(size)
|
|
|
)
|
|
|
return [(dev, getname(dev, name, size))
|
|
|
for dev, name, size in self.ZipVars(
|
|
|
'cl_autopartition_device_dev', 'cl_autopartition_device_name',
|
|
|
'cl_autopartition_device_size')]
|
|
|
|
|
|
def checkNeeded(self, valuelist, usedDevices, agregationType):
|
|
|
needDevices = list(set(usedDevices) - set(valuelist))
|
|
|
if needDevices:
|
|
|
raise VariableError(
|
|
|
_("Disks {selecteddisk} are part of "
|
|
|
"{agrtype}\nYou need to use {needdisk} as well or "
|
|
|
"clear {agrtype} manually").format(
|
|
|
selecteddisk=",".join(
|
|
|
list(set(usedDevices) & set(valuelist))),
|
|
|
needdisk=",".join(needDevices),
|
|
|
agrtype=agregationType))
|
|
|
|
|
|
def checkOnLvm(self, valuelist):
|
|
|
disks = self.Select('os_disk_dev',
|
|
|
where='os_disk_parent', _in=valuelist)
|
|
|
vgroups = self.Select('os_lvm_vgname',
|
|
|
where='os_lvm_pvname', _in=disks)
|
|
|
lvmDisks = self.Select('os_lvm_pvname',
|
|
|
where='os_lvm_vgname', _in=vgroups)
|
|
|
lvmDevices = self.Select('os_disk_parent', where='os_disk_dev',
|
|
|
_in=lvmDisks)
|
|
|
self.checkNeeded(valuelist, lvmDevices, "LVM")
|
|
|
|
|
|
def checkOnRaid(self, valuelist):
|
|
|
disks = self.Select('os_disk_dev',
|
|
|
where='os_disk_parent', _in=valuelist)
|
|
|
raids = filter(None, self.Select('os_disk_raid',
|
|
|
where='os_disk_dev', _in=disks))
|
|
|
raidDisks = self.Select('os_disk_dev', where='os_disk_raid', _in=raids)
|
|
|
raidDevices = self.Select('os_disk_parent',
|
|
|
where='os_disk_dev',
|
|
|
_in=raidDisks)
|
|
|
self.checkNeeded(valuelist, raidDevices, "RAID")
|
|
|
|
|
|
def checkOnSelectParentAndChild(self, valuelist):
|
|
|
"""
|
|
|
Проверка на попытку одновременно выбрать RAID и диски из которых
|
|
|
он состоит
|
|
|
"""
|
|
|
for device in valuelist:
|
|
|
parents = self.select('os_device_parent',
|
|
|
os_device_dev=device, limit=1).split(',')
|
|
|
common = set(parents) & set(valuelist)
|
|
|
if common:
|
|
|
if len(common) > 1:
|
|
|
raise VariableError(
|
|
|
_("Devices {devices} are used for {selected}").format(
|
|
|
devices=",".join(sorted(common)),
|
|
|
selected=device))
|
|
|
else:
|
|
|
raise VariableError(
|
|
|
_("Device {device} is used for {selected}").format(
|
|
|
device=",".join(common),
|
|
|
selected=device))
|
|
|
|
|
|
def checkSelectedRaid(self, valuelist):
|
|
|
"""
|
|
|
Проверить схемы RAID, чтобы исключить базирование их на lvm
|
|
|
"""
|
|
|
typecheck = re.compile("lvm.*raid")
|
|
|
for dev, fulltype in self.ZipVars("os_device_dev",
|
|
|
"os_device_fulltype"):
|
|
|
if dev in valuelist:
|
|
|
if typecheck.search(fulltype):
|
|
|
raise VariableError(_("RAID %s is wrong") % dev)
|
|
|
|
|
|
def check(self, valuelist):
|
|
|
if self.Get('cl_autopartition_set') == "on":
|
|
|
if not valuelist:
|
|
|
raise VariableError(
|
|
|
_("For autopartition, please select the device"))
|
|
|
|
|
|
useDisks = set(traverse(x.split(',') for x in self.Select(
|
|
|
'os_disk_parent', where='os_disk_mount', ne='')))
|
|
|
for value in chain(valuelist):
|
|
|
for disk in set(chain(self.select(
|
|
|
'os_device_parent', os_device_dev=value,
|
|
|
limit=1).split(","), [value])):
|
|
|
if disk in useDisks:
|
|
|
raise VariableError(
|
|
|
_("Device %s is already in use by the current "
|
|
|
"system") % value)
|
|
|
self.checkSelectedRaid(valuelist)
|
|
|
self.checkOnSelectParentAndChild(valuelist)
|
|
|
self.checkOnLvm(valuelist)
|
|
|
self.checkOnRaid(valuelist)
|
|
|
try:
|
|
|
df = partition.VariableFactory(device.udev)
|
|
|
sb = self.Get('cl_autopartition_scheme_builder')
|
|
|
if sb and sb.devices:
|
|
|
sb.process(df)
|
|
|
except (partition.SchemeError,
|
|
|
partition.VirtualDiskError) as e:
|
|
|
raise VariableError(str(e))
|
|
|
if self.GetBool('cl_autopartition_uefi_set'):
|
|
|
if not self.Get('cl_autopartition_efi'):
|
|
|
raise VariableError(
|
|
|
_("Selected devices have not EFI partition"))
|
|
|
if not self.GetBool('cl_autopartition_uefi_set'):
|
|
|
if not self.Get('cl_autopartition_mbr'):
|
|
|
raise VariableError(
|
|
|
_("Selected devices have not BIOS boot partition"))
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionSchemeBuilder(ReadonlyVariable):
|
|
|
def get(self):
|
|
|
if not self.GetBool('cl_autopartition_set'):
|
|
|
return ""
|
|
|
sb = partition.SchemeBuilder()
|
|
|
if self.Get('cl_autopartition_table') == "dos":
|
|
|
sb.partition_table = sb.PartitionTable.DOS
|
|
|
if self.Get('cl_autopartition_table') == "gpt":
|
|
|
sb.partition_table = sb.PartitionTable.GPT
|
|
|
sb.vgname = self.Get('cl_autopartition_lvm_vgname')
|
|
|
sb.lvm = self.GetBool('cl_autopartition_lvm_set')
|
|
|
sb.efi = self.GetBool('cl_autopartition_uefi_set')
|
|
|
|
|
|
sb.efi_size = int(self.Get('cl_autopartition_uefi_size'))
|
|
|
sb.biosboot_size = int(self.Get('cl_autopartition_bios_grub_size'))
|
|
|
sb.root_size = int(self.Get('cl_autopartition_root_size'))
|
|
|
sb.swap_size = int(self.Get('cl_autopartition_swap_size'))
|
|
|
|
|
|
scheme = self.Get('cl_autopartition_scheme')
|
|
|
if SchemeOpt.Swap in scheme:
|
|
|
sb.swap = True
|
|
|
if SchemeOpt.Update in scheme:
|
|
|
sb.update = True
|
|
|
if SchemeOpt.Calculate in scheme:
|
|
|
sb.calculate = True
|
|
|
|
|
|
deviceSizeAll = int(self.Get('cl_autopartition_device_size_all'))
|
|
|
if not sb.update and not sb.calculate and deviceSizeAll == sb.root_size:
|
|
|
sb.rootall = True
|
|
|
|
|
|
sb.minimal_calculate_size = \
|
|
|
int(self.Get('cl_autopartition_calculate_size'))
|
|
|
|
|
|
used_devices = self.Get('cl_autopartition_device')
|
|
|
for dev, _type, size in self.ZipVars("cl_autopartition_device_dev",
|
|
|
"cl_autopartition_device_type",
|
|
|
"cl_autopartition_device_size"):
|
|
|
if dev in used_devices:
|
|
|
if _type.startswith("raid"):
|
|
|
device_type = partition.VolumesBuilder.DeviceType.RAID
|
|
|
else:
|
|
|
device_type = partition.VolumesBuilder.DeviceType.Device
|
|
|
sb.add_device(dev, device_type, int(size))
|
|
|
|
|
|
sb.default_format = self.Get('cl_autopartition_default_format')
|
|
|
|
|
|
return sb
|
|
|
|
|
|
class VariableClAutopartitionFactory(ReadonlyVariable):
|
|
|
"""
|
|
|
Объект для вычисления параметров/переменных выбранной конфигурации
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
df = partition.VariableFactory(device.udev)
|
|
|
sb = self.Get('cl_autopartition_scheme_builder')
|
|
|
if sb and sb.devices:
|
|
|
df.default_format = sb.default_format
|
|
|
root_purpose = partition.VolumesBuilder.Purpose.MainRoot
|
|
|
data_purpose = partition.VolumesBuilder.Purpose.Calculate
|
|
|
df.purpose_format[root_purpose] = \
|
|
|
self.Get('cl_autopartition_root_format')
|
|
|
df.purpose_format[data_purpose] = \
|
|
|
self.Get('cl_autopartition_calculate_format')
|
|
|
try:
|
|
|
sb.process(df)
|
|
|
except (partition.SchemeError, partition.VirtualDiskError):
|
|
|
return partition.VariableFactory(device.udev)
|
|
|
return df
|
|
|
|
|
|
def __str__(self):
|
|
|
return "AutopartitionObject"
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDefaultFormat(Variable):
|
|
|
"""
|
|
|
Формат файловой системы
|
|
|
"""
|
|
|
type = "choice"
|
|
|
|
|
|
def get(self):
|
|
|
return FileSystemManager.defaultFS['hdd']
|
|
|
|
|
|
def choice(self):
|
|
|
allfs = set([k for k,v in FileSystemManager.supportFS.items()
|
|
|
if v.get('auto',True)])
|
|
|
availFS = set(self.Select('os_format_type',
|
|
|
where='os_format_use',
|
|
|
eq='yes'))
|
|
|
return list(sorted(allfs & availFS))
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionRootFormat(VariableClAutopartitionDefaultFormat):
|
|
|
"""
|
|
|
Формат файловой системы для корня
|
|
|
"""
|
|
|
opt = ["--root-fs"]
|
|
|
metavalue = "FS"
|
|
|
|
|
|
def init(self):
|
|
|
self.label = _("Filesystem for root partition")
|
|
|
self.help = _("set filesystem for root partititon")
|
|
|
|
|
|
def get(self):
|
|
|
return self.Get('cl_autopartition_default_format')
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionCalculateFormat(VariableClAutopartitionDefaultFormat):
|
|
|
"""
|
|
|
Формат файловой системы для calculate
|
|
|
"""
|
|
|
opt = ["--data-fs"]
|
|
|
metavalue = "FS"
|
|
|
|
|
|
def init(self):
|
|
|
self.label = _("Filesystem for data partition")
|
|
|
self.help = _("set filesystem for data partititon")
|
|
|
|
|
|
def get(self):
|
|
|
return self.Get('cl_autopartition_default_format')
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionCalculateSize(Variable):
|
|
|
"""
|
|
|
Минимальный размер для раздела /var/calculate
|
|
|
"""
|
|
|
value = str(Sizes.G * 1)
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionSet(Variable):
|
|
|
"""
|
|
|
Using autopartition
|
|
|
"""
|
|
|
type = "bool"
|
|
|
element = "radio"
|
|
|
|
|
|
def init(self):
|
|
|
self.label = _("Allocate drive space")
|
|
|
self.help = _("use the autopartition")
|
|
|
|
|
|
def choice(self):
|
|
|
name = "Calculate Linux"
|
|
|
return [("on", _("Erase disk and install %s") % name),
|
|
|
("off", _("Use current partitions"))]
|
|
|
|
|
|
def get(self):
|
|
|
if self.is_console_set("os_location_data"):
|
|
|
return "off"
|
|
|
elif self.is_console_set("cl_autopartition_device"):
|
|
|
return "on"
|
|
|
if self.Get('os_root_type_ext') in (RootType.Value.LiveCD,
|
|
|
RootType.Value.LiveFlash,
|
|
|
RootType.Value.IsoScanFlash,
|
|
|
RootType.Value.NetBoot):
|
|
|
return "on"
|
|
|
else:
|
|
|
return "off"
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionBriefSet(VariableClAutopartitionSet):
|
|
|
def get(self):
|
|
|
return self.Get('cl_autopartition_set')
|
|
|
|
|
|
def uncompatible(self):
|
|
|
if self.Get('os_install_root_type') == 'flash':
|
|
|
return _("This option not used for Flash install")
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionScheme(AutopartitionHelper, Variable):
|
|
|
"""
|
|
|
Autopartition scheme
|
|
|
"""
|
|
|
type = "choice-list"
|
|
|
element = "selecttable"
|
|
|
opt = ["--auto-scheme", "-S"]
|
|
|
metavalue = "AUTOPARTOPTS"
|
|
|
check_after = ["cl_autopartition_table"]
|
|
|
|
|
|
def init(self):
|
|
|
self.help = _("autopartition options")
|
|
|
self.label = _("Partitions options")
|
|
|
|
|
|
def get(self):
|
|
|
default_value = [
|
|
|
SchemeOpt.Swap,
|
|
|
SchemeOpt.Update,
|
|
|
SchemeOpt.Calculate
|
|
|
]
|
|
|
if self.Get('os_uefi_set') == 'on':
|
|
|
return [SchemeOpt.UEFI] + default_value
|
|
|
else:
|
|
|
return default_value
|
|
|
|
|
|
def choice(self):
|
|
|
return [
|
|
|
(SchemeOpt.Swap, _("Swap partition")),
|
|
|
(SchemeOpt.Update, _("The partition for the update")),
|
|
|
(SchemeOpt.Calculate, _("Data partition")),
|
|
|
(SchemeOpt.UEFI, _("Use the UEFI bootloader")),
|
|
|
(SchemeOpt.LVM, _("Use LVM")),
|
|
|
]
|
|
|
|
|
|
def check(self, value):
|
|
|
if SchemeOpt.UEFI in value:
|
|
|
if self.Get('os_uefi_set') == 'off':
|
|
|
raise VariableError(
|
|
|
_("Your system must be loaded in UEFI for using this "
|
|
|
"bootloader"))
|
|
|
if self.Get('os_install_arch_machine') != 'x86_64':
|
|
|
raise VariableError(
|
|
|
_("Architecture of the target system must be x86_64 "
|
|
|
"for using the UEFI bootloader"))
|
|
|
if self.Get('cl_autopartition_table') != 'gpt':
|
|
|
raise VariableError(
|
|
|
_("The partition table must be GPT for using "
|
|
|
"UEFI bootloader"))
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionRootSizeDefault(Variable):
|
|
|
"""
|
|
|
Размер root раздела при авторазметке
|
|
|
"""
|
|
|
value = str(Sizes.G * 15)
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionRootSizeMin(Variable):
|
|
|
"""
|
|
|
Минимальнй размер root раздела
|
|
|
"""
|
|
|
value = str(Sizes.G * 7)
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDeviceSizeAll(ReadonlyVariable):
|
|
|
"""
|
|
|
Общий объем дискового пространства
|
|
|
"""
|
|
|
def get(self):
|
|
|
deviceSize = sum(
|
|
|
int(x) for x in self.Get('cl_autopartition_device_size'))
|
|
|
scheme = self.Get('cl_autopartition_scheme')
|
|
|
if SchemeOpt.Swap in scheme:
|
|
|
return deviceSize - int(self.Get('cl_autopartition_swap_size'))
|
|
|
return deviceSize
|
|
|
|
|
|
class VariableClAutopartitionRootSize(SizeHelper, AutopartitionHelper,
|
|
|
Variable):
|
|
|
"""
|
|
|
Root partition size for autopartition
|
|
|
"""
|
|
|
type = "size-m"
|
|
|
opt = ["--root-size"]
|
|
|
metavalue = "SIZE"
|
|
|
untrusted = True
|
|
|
|
|
|
def init(self):
|
|
|
self.label = _("Root partition size") + " (MB)"
|
|
|
self.help = _("set the root partition size for autopartition")
|
|
|
|
|
|
def use_rootall(self):
|
|
|
scheme = self.Get('cl_autopartition_scheme')
|
|
|
return SchemeOpt.Update not in scheme and SchemeOpt.Calculate not in scheme
|
|
|
|
|
|
def get(self):
|
|
|
size = int(self.Get('cl_autopartition_root_size_default'))
|
|
|
deviceSize = int(self.Get('cl_autopartition_device_size_all'))
|
|
|
minRootSize = int(self.Get('cl_autopartition_root_size_min'))
|
|
|
if self.use_rootall():
|
|
|
size = max(deviceSize, minRootSize)
|
|
|
return str(size)
|
|
|
|
|
|
def check(self, value):
|
|
|
minRootSize = int(self.Get('cl_autopartition_root_size_min'))
|
|
|
if (self.Get('cl_autopartition_device') and
|
|
|
self.Get('cl_autopartition_set') == "on"):
|
|
|
if int(value) < minRootSize:
|
|
|
raise VariableError(
|
|
|
_("The root partition should be at least {size}").format(
|
|
|
size="%s Gb" % (Sizes().to_G(minRootSize))))
|
|
|
|
|
|
def humanReadable(self):
|
|
|
return humanreadableSize(int(self.Get()))
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionTable(AutopartitionHelper, Variable):
|
|
|
"""
|
|
|
Partition table for autopartition
|
|
|
"""
|
|
|
type = "choice"
|
|
|
value = "gpt"
|
|
|
opt = ["--partition-table", "-T"]
|
|
|
metavalue = "TABLE"
|
|
|
|
|
|
def init(self):
|
|
|
self.label = _("Partition table")
|
|
|
self.help = _("set the partition table for autopartition")
|
|
|
|
|
|
def choice(self):
|
|
|
return [("dos", "DOS-type Partition Table"),
|
|
|
("gpt", "GUID Partition Table (GPT)")]
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionLvmSet(ReadonlyVariable):
|
|
|
"""
|
|
|
Using LVM for autopartition
|
|
|
"""
|
|
|
type = "bool"
|
|
|
|
|
|
def get(self):
|
|
|
return ("on" if SchemeOpt.LVM in self.Get('cl_autopartition_scheme')
|
|
|
else "off")
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionUefiSet(ReadonlyVariable):
|
|
|
"""
|
|
|
Using UEFI bootloader
|
|
|
"""
|
|
|
type = "bool"
|
|
|
|
|
|
def get(self):
|
|
|
return ("on" if SchemeOpt.UEFI in self.Get('cl_autopartition_scheme')
|
|
|
else "off")
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionLvmVgname(Variable):
|
|
|
"""
|
|
|
Volume group name for LVM autopartition
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
def generateName(startName):
|
|
|
yield startName
|
|
|
for i in count(20):
|
|
|
yield "%s%d" % (startName, i)
|
|
|
|
|
|
for name in generateName("calculate"):
|
|
|
disks = self.Select('os_lvm_pvname', where='os_lvm_vgname', eq=name)
|
|
|
devices = self.Select('os_disk_parent',
|
|
|
where='os_disk_dev', _in=disks)
|
|
|
if set(devices) <= set(self.Get('cl_autopartition_device')):
|
|
|
return name
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskData(ReadonlyTableVariable):
|
|
|
"""
|
|
|
Серия переменных содержит список устройств, используемых для построения
|
|
|
переменных os_location_source и т.д.
|
|
|
"""
|
|
|
source = ['cl_autopartition_disk_dev',
|
|
|
'cl_autopartition_disk_mount',
|
|
|
'cl_autopartition_disk_format',
|
|
|
'cl_autopartition_disk_size',
|
|
|
'cl_autopartition_disk_part',
|
|
|
'cl_autopartition_disk_type']
|
|
|
|
|
|
|
|
|
class DiskFilter(VariableInterface):
|
|
|
field = ""
|
|
|
|
|
|
def get(self):
|
|
|
factory = self.Get('cl_autopartition_factory')
|
|
|
return [str(x) for x, mount in zip(getattr(factory, self.field),
|
|
|
factory.disk_mount)
|
|
|
if mount and not mount.startswith("/boot/efi")]
|
|
|
|
|
|
class VariableClAutopartitionDiskDev(DiskFilter, ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition virtual disk on device
|
|
|
"""
|
|
|
type = "list"
|
|
|
field = "disk_dev"
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskMount(DiskFilter, ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition mount points
|
|
|
"""
|
|
|
type = "list"
|
|
|
field = "disk_mount"
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskFormat(DiskFilter, ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition disk filesystem
|
|
|
"""
|
|
|
type = "list"
|
|
|
field = "disk_format"
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskPart(DiskFilter, ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition partition type (primary,extended,logical,gpt)
|
|
|
"""
|
|
|
type = "list"
|
|
|
field = "disk_part"
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskType(DiskFilter, ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition partition scheme (simple - disk-partition)
|
|
|
"""
|
|
|
type = "list"
|
|
|
field = "disk_type"
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskSize(DiskFilter, ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition disk size
|
|
|
"""
|
|
|
type = "list"
|
|
|
field = "disk_size"
|
|
|
|
|
|
def get(self):
|
|
|
return map(str, super(VariableClAutopartitionDiskSize, self).get())
|
|
|
|
|
|
def humanReadable(self):
|
|
|
return map(humanreadableSize, self.Get())
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskDataFull(ReadonlyTableVariable):
|
|
|
"""
|
|
|
Серия переменных содержит полный список созданной разметки
|
|
|
"""
|
|
|
source = ['cl_autopartition_disk_dev_full',
|
|
|
'cl_autopartition_disk_mount_full',
|
|
|
'cl_autopartition_disk_format_full',
|
|
|
'cl_autopartition_disk_perform_format_full',
|
|
|
'cl_autopartition_disk_size_full',
|
|
|
'cl_autopartition_disk_part_full',
|
|
|
'cl_autopartition_disk_type_full']
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskDevFull(ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition virtual disk on device
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
var_factory = self.Get('cl_autopartition_factory')
|
|
|
return var_factory.disk_dev
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskMountFull(ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition mount points
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
var_factory = self.Get('cl_autopartition_factory')
|
|
|
return var_factory.disk_mount
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskFormatFull(ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition disk filesystem
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
var_factory = self.Get('cl_autopartition_factory')
|
|
|
return var_factory.disk_format
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskPerformFormatFull(ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition disk filesystem
|
|
|
"""
|
|
|
type = "bool-list"
|
|
|
|
|
|
def get(self):
|
|
|
return ["on" if mp else "off"
|
|
|
for mp in self.Get('cl_autopartition_disk_mount_full')]
|
|
|
|
|
|
class VariableClAutopartitionDiskPartFull(ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition partition type (primary,extended,logical,gpt)
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
var_factory = self.Get('cl_autopartition_factory')
|
|
|
return var_factory.disk_part
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskTypeFull(ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition partition scheme (simple - disk-partition)
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
var_factory = self.Get('cl_autopartition_factory')
|
|
|
return var_factory.disk_type
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionDiskSizeFull(ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition disk size
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
var_factory = self.Get('cl_autopartition_factory')
|
|
|
return map(str, var_factory.disk_size)
|
|
|
|
|
|
def humanReadable(self):
|
|
|
return map(humanreadableSize, self.Get())
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionRaid(ReadonlyVariable):
|
|
|
"""
|
|
|
Список выбранных для разметки RAID устройств
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
selected_dev = self.Get('cl_autopartition_device')
|
|
|
return [
|
|
|
dev for dev, _type in self.ZipVars(
|
|
|
"cl_autopartition_device_dev", "cl_autopartition_device_type")
|
|
|
if dev in selected_dev and _type.startswith("raid")]
|
|
|
|
|
|
class VariableClAutopartitionRaidParent(ReadonlyVariable):
|
|
|
"""
|
|
|
Список физических устройств, из которых построены выбранные RAID
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
selected_raid = set(self.Get('cl_autopartition_raid'))
|
|
|
return list(set(traverse(
|
|
|
parents.split(',')
|
|
|
for parents in self.select('os_device_parent',
|
|
|
os_device_dev__in=selected_raid))))
|
|
|
|
|
|
class VariableClAutopartitionMbr(ReadonlyVariable):
|
|
|
"""
|
|
|
Диски на которые будет установлен загрузчик
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
if self.GetBool('cl_autopartition_uefi_set'):
|
|
|
return []
|
|
|
|
|
|
selected_raid_devices = self.Get('cl_autopartition_raid_parent')
|
|
|
|
|
|
mbr = (mbr for mbr in self.select(
|
|
|
'os_device_mbr', os_device_dev__in=selected_raid_devices)
|
|
|
if mbr)
|
|
|
|
|
|
var_factory = self.Get('cl_autopartition_factory')
|
|
|
return sorted(set(mbr) | set(var_factory.mbr))
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionEfi(ReadonlyVariable):
|
|
|
"""
|
|
|
Диски на которые будет установлен загрузчик
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
if not self.GetBool('cl_autopartition_uefi_set'):
|
|
|
return []
|
|
|
|
|
|
var_factory = self.Get('cl_autopartition_factory')
|
|
|
selected_dev = self.Get('cl_autopartition_device')
|
|
|
selected_data = ((dev, _type) for dev, _type in self.ZipVars(
|
|
|
"cl_autopartition_device_dev", "cl_autopartition_device_type")
|
|
|
if dev in selected_dev)
|
|
|
for dev, _type in selected_data:
|
|
|
if _type == "device":
|
|
|
if var_factory.efi:
|
|
|
return var_factory.efi[:1]
|
|
|
elif _type == "raid0":
|
|
|
parents = self.select('os_device_parent',
|
|
|
os_device_dev=dev, limit=1).split(',')
|
|
|
efidev = self.select('os_device_efi', os_device_dev__in=parents,
|
|
|
limit=1)
|
|
|
if efidev:
|
|
|
return [efidev]
|
|
|
# прочие raid
|
|
|
else:
|
|
|
parents = self.select('os_device_parent',
|
|
|
os_device_dev=dev, limit=1).split(',')
|
|
|
efidevs = self.select('os_device_efi',
|
|
|
os_device_dev__in=parents)
|
|
|
if efidevs:
|
|
|
return sorted(set(filter(None, efidevs)))
|
|
|
return []
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionParent(ReadonlyVariable):
|
|
|
"""
|
|
|
disk_parent для install переменных
|
|
|
"""
|
|
|
def get(self):
|
|
|
def generate():
|
|
|
for device in self.Get('cl_autopartition_raid_parent'):
|
|
|
yield device
|
|
|
selected_dev = self.Get('cl_autopartition_device')
|
|
|
for dev, _type in self.ZipVars(
|
|
|
"cl_autopartition_device_dev",
|
|
|
"cl_autopartition_device_type"):
|
|
|
if dev in selected_dev and not _type.startswith("raid"):
|
|
|
yield dev
|
|
|
|
|
|
return ",".join(sorted(set(generate())))
|
|
|
|
|
|
class VariableClAutopartitionUefiSize(Variable):
|
|
|
"""
|
|
|
Size of EF00 partition
|
|
|
"""
|
|
|
value = str(200 * Sizes.M)
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionBootSize(Variable):
|
|
|
"""
|
|
|
Size of boot partition
|
|
|
"""
|
|
|
value = str(512 * Sizes.M)
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionBiosGrubSize(Variable):
|
|
|
"""
|
|
|
Размер раздела bios_grub для авторазметки
|
|
|
"""
|
|
|
value = str(50 * Sizes.M)
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionBindData(ReadonlyTableVariable):
|
|
|
"""
|
|
|
Autopartition bind data
|
|
|
"""
|
|
|
source = ['cl_autopartition_bind_path',
|
|
|
'cl_autopartition_bind_mountpoint']
|
|
|
|
|
|
def get(self, hr=HumanReadable.No):
|
|
|
def generator():
|
|
|
scheme = self.Get('cl_autopartition_scheme')
|
|
|
if (self.Get('cl_autopartition_set') == "on" and
|
|
|
SchemeOpt.Calculate in scheme):
|
|
|
yield ["/var/calculate/home", "/home"]
|
|
|
return list(generator()) or [[]]
|
|
|
|
|
|
|
|
|
class VariableClAutopartitionBindPath(FieldValue, ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition bind points
|
|
|
"""
|
|
|
type = "list"
|
|
|
source_variable = "cl_autopartition_bind_data"
|
|
|
column = 0
|
|
|
|
|
|
def get(self):
|
|
|
return list(super(VariableClAutopartitionBindPath, self).get())
|
|
|
|
|
|
class VariableClAutopartitionBindMountpoint(FieldValue, ReadonlyVariable):
|
|
|
"""
|
|
|
Autopartition bind points
|
|
|
"""
|
|
|
type = "list"
|
|
|
source_variable = "cl_autopartition_bind_data"
|
|
|
column = 1
|
|
|
|
|
|
def get(self):
|
|
|
return list(super(VariableClAutopartitionBindMountpoint, self).get())
|