From 89630bbfafe924454776decc407e43a6f33a220c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A5=D0=B8=D1=80=D0=B5=D1=86=D0=BA=D0=B8=D0=B9=20=D0=9C?= =?UTF-8?q?=D0=B8=D1=85=D0=B0=D0=B8=D0=BB?= Date: Mon, 18 Sep 2017 10:54:44 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=BE=20=D1=81=D0=BE=D0=B4=D0=B5=D1=80=D0=B6=D0=B8=D0=BC=D0=BE?= =?UTF-8?q?=D0=B5=20os=5Fdisk=5Fparent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * переменная содержит все родительские устройства через запятую --- pym/install/fs_manager.py | 2 + pym/install/variables/disk.py | 399 +++++++++++++++------------------- 2 files changed, 182 insertions(+), 219 deletions(-) diff --git a/pym/install/fs_manager.py b/pym/install/fs_manager.py index f25a7bd..06091b9 100644 --- a/pym/install/fs_manager.py +++ b/pym/install/fs_manager.py @@ -133,6 +133,8 @@ class FileSystemManager(object): 'compatible': ['ntfs']}} default_param = {'defaultopt': defaultOpt, + 'gpt': '8300', + 'msdos': '83', 'ssd': []} @classmethod diff --git a/pym/install/variables/disk.py b/pym/install/variables/disk.py index 2017c46..40c28c5 100644 --- a/pym/install/variables/disk.py +++ b/pym/install/variables/disk.py @@ -22,9 +22,8 @@ import fcntl from subprocess import Popen from os import path from itertools import * -from operator import itemgetter -from calculate.install.distr import FlashDistributive, DistributiveError, \ - IsoDistributive +from calculate.install.distr import (FlashDistributive, DistributiveError, + IsoDistributive) from calculate.lib.datavars import (TableVariable, Variable, VariableError, ReadonlyVariable, ReadonlyTableVariable, SourceReadonlyVariable, VariableInterface, @@ -571,7 +570,7 @@ class VariableOsDiskParent(ReadonlyVariable): def get(self): """Get disk parent""" - return [",".join(device.udev.get_disk_devices(name=x)).partition(',')[0] + return [",".join(device.udev.get_disk_devices(name=x)) for x in self.Get('os_disk_dev')] @@ -607,7 +606,11 @@ class VariableOsDiskGrub(ReadonlyVariable): self.Get('os_device_map'))) def getGrubMap(devParent): - dev, parent = devParent + dev, disktype, parent = devParent + # grub id вычисляем только для разделов расположенных на диске + # (исключаются lvm, raid и прочие абстракции) + if disktype != "disk-partition": + return "" prop = device.udev.get_device_info(name=dev) partnum = int(prop.get('ID_PART_ENTRY_NUMBER', 0)) if parent in devicesMap.keys() and partnum: @@ -617,6 +620,7 @@ class VariableOsDiskGrub(ReadonlyVariable): return map(getGrubMap, zip(self.Get('os_disk_dev'), + self.Get('os_disk_type'), self.Get('os_disk_parent'))) @@ -630,9 +634,9 @@ class VariableOsDiskPart(ReadonlyVariable): def get(self): def generator(): - for disk_dev, disk_parent in self.ZipVars( - 'os_disk_dev', 'os_disk_parent'): - if disk_parent: + for disk_dev, disk_type in self.ZipVars( + 'os_disk_dev', 'os_disk_type'): + if disk_type.endswith("-partition"): yield device.udev.get_partition_type(name=disk_dev) else: yield "" @@ -812,28 +816,23 @@ class VariableOsLocationSource(LocationHelper, DeviceHelper, Variable): Available devices """ if self.Get('cl_install_type') == 'flash': - flashDrives = self.Select('os_device_dev', - where='os_device_type', - eq="flash") - return self.Select('os_disk_dev', - where='os_disk_parent', - _in=flashDrives) + flashes = self.Select('os_device_dev', + where='os_device_type', + eq="flash") + return [disk_dev for disk_dev, disk_parent, disk_type in + self.ZipVars("os_disk_dev", "os_disk_parent", + "os_disk_type") + if disk_type == "disk-partition" and disk_parent in flashes] else: if choice: return self.Get('os_disk_dev') + self.Get('os_bind_path') else: - devFrom = self.Get('cl_install_dev_from') - if self.Get('os_install_scratch') == 'on': - return self.Select('os_disk_dev', - where='os_disk_mount', - func=lambda x: x[0] == "swap" or - x[1] == devFrom) - else: - return self.Select('os_disk_dev', - where='os_disk_mount', - func=lambda x: not x[0] in ("", "/") or - x[1] == devFrom) + \ - self.Get('os_bind_path') + dev_from = self.Get('cl_install_dev_from') + return [ + disk_dev for disk_dev, disk_mount in self.ZipVars( + "os_disk_dev", "os_disk_mount") + if disk_mount not in ("", "/") or disk_dev == dev_from + ] + self.Get('os_bind_path') def get(self): if self.Get('cl_autopartition_set') == "on": @@ -853,8 +852,7 @@ class VariableOsLocationSource(LocationHelper, DeviceHelper, Variable): def choice(self): return map(lambda x: (x, self.getPerfectName(x) or x), - self.fixOsDiskDev(self.availDevs(choice=True))) \ - + [("", "")] + self.fixOsDiskDev(self.availDevs(choice=True))) + [("", "")] def fixOsDiskDev(self, sourcelist=None): """ @@ -864,13 +862,17 @@ class VariableOsLocationSource(LocationHelper, DeviceHelper, Variable): sourcelist = self.Get('os_disk_dev') scheme = self.Get('cl_autopartition_set') == "on" if scheme: - excludeDisks = self.Select('os_disk_dev', - where='os_disk_parent', - eq=self.Get('cl_autopartition_device')) - appendDisks = self.Get('cl_autopartition_disk_dev') + \ - self.Get('cl_autopartition_bind_path') - return list(ifilterfalse(excludeDisks.__contains__, - sourcelist)) + appendDisks + autopartition_devices = self.Get('cl_autopartition_device') + exclude = { + disk_dev + for disk_dev, disk_parent in self.ZipVars("os_disk_dev", + "os_disk_parent") + if any(x in autopartition_devices + for x in disk_parent.split(',')) + } + appendDisks = (self.Get('cl_autopartition_disk_dev') + + self.Get('cl_autopartition_bind_path')) + return [x for x in sourcelist if x not in exclude] + appendDisks else: return sourcelist @@ -1407,13 +1409,37 @@ class VariableOsInstallDiskEfi(ReadonlyVariable): where='os_install_disk_mount_base', eq='/') else: - validParent = self.Select('os_device_dev', - where='os_device_type', eq='hdd') - efiPartitions = self.Select('os_disk_dev', - where=['os_disk_id', 'os_disk_parent'], - func=lambda x: x[0] == 'EF00' and x[ - 1] in validParent) - return list(set(efiPartitions) - set(self.Get('os_location_source'))) + validParent = self.Get('os_install_boot_devices') + + efi_partitions = { + disk_dev + for disk_dev, disk_id, disk_parent in self.ZipVars('os_disk_dev', + 'os_disk_id', + 'os_disk_parent') + if disk_id == 'EF00' and any(x in validParent + for x in disk_parent.split(',')) + } + + return list(efi_partitions - set(self.Get('os_location_source'))) + + +class VariableOsInstallDiskParent(SourceReadonlyVariable): + """ + Partition parent devices using for install + """ + type = "list" + indexField = "os_install_disk_dev" + + def getMap(self): + diskParent = dict(self.ZipVars('os_disk_dev', 'os_disk_parent')) + # replace value for autopartition + if self.Get('cl_autopartition_set') == 'on': + disk_parent = ",".join(self.Get('cl_autopartition_device')) + for disk_dev in self.Get('cl_autopartition_disk_dev'): + diskParent[disk_dev] = disk_parent + return diskParent + + humanReadable = Variable.humanReadable class VariableOsAddonDiskDev(DeviceHelper, ReadonlyVariable): @@ -1421,7 +1447,7 @@ class VariableOsAddonDiskDev(DeviceHelper, ReadonlyVariable): def get(self): if self.Get('os_install_uefi_set') == 'on': - if not "/boot/efi" in self.Get('os_location_dest'): + if "/boot/efi" not in self.Get('os_location_dest'): efiPartition = self.Get('os_install_disk_efi') if efiPartition: return efiPartition[:1] @@ -1433,7 +1459,7 @@ class VariableOsAddonDiskMount(DeviceHelper, ReadonlyVariable): def get(self): if self.Get('os_install_uefi_set') == 'on': - if not "/boot/efi" in self.Get('os_location_dest'): + if "/boot/efi" not in self.Get('os_location_dest'): efiPartition = self.Get('os_install_disk_efi') if efiPartition: return ['/boot/efi'] @@ -1445,7 +1471,7 @@ class VariableOsAddonDiskFormat(DeviceHelper, ReadonlyVariable): def get(self): if self.Get('os_install_uefi_set') == 'on': - if not "/boot/efi" in self.Get('os_location_dest'): + if "/boot/efi" not in self.Get('os_location_dest'): efiPartition = self.Get('os_install_disk_efi') if efiPartition: return ['vfat'] @@ -1457,7 +1483,7 @@ class VariableOsAddonDiskPerformFormat(DeviceHelper, ReadonlyVariable): def get(self): if self.Get('os_install_uefi_set') == 'on': - if not "/boot/efi" in self.Get('os_location_dest'): + if "/boot/efi" not in self.Get('os_location_dest'): efiPartition = self.Get('os_install_disk_efi') if efiPartition: fsPart = self.Select('os_disk_format', where='os_disk_dev', @@ -1487,22 +1513,12 @@ class VariableOsInstallDiskDevBase(DeviceHelper, ReadonlyVariable): if dest and source.startswith("/dev/")] -class VariableOsInstallDiskParentBase(SourceReadonlyVariable): +class VariableOsInstallDiskParentBase(VariableOsInstallDiskParent): """ Partition parent devices using for install """ type = "list" indexField = "os_install_disk_dev_base" - - def getMap(self): - diskParent = dict(self.ZipVars('os_disk_dev', 'os_disk_parent')) - # replace value for autopartition - if self.Get('cl_autopartition_set') == 'on': - diskParent.update(zip(self.Get('cl_autopartition_disk_dev'), - self.Get('cl_autopartition_device') * - len(self.Get('cl_autopartition_disk_dev')))) - return diskParent - humanReadable = Variable.humanReadable @@ -1513,8 +1529,8 @@ class VariableOsInstallDiskDev(ReadonlyVariable, DeviceHelper): type = "list" def get(self): - return self.Get('os_addon_disk_dev') + \ - self.Get('os_install_disk_dev_base') + return (self.Get('os_addon_disk_dev') + + self.Get('os_install_disk_dev_base')) def humanReadable(self): return map(lambda x: self.getPerfectName(x, defaultValue=x), @@ -1588,25 +1604,31 @@ class VariableOsInstallDiskOptions(ReadonlyVariable): type = "list" def get(self): - def postProcess(opt): - l_opt = filter(None, opt.split(',')) - return ",".join(l_opt) - - diskOpts = dict(filter(lambda x: x[1], - zip(self.Get('os_disk_dev'), - self.Get('os_disk_options')))) - ssdDisk = dict(self.ZipVars('install.os_device_dev', - 'install.os_device_ssd_set')) - return map(postProcess, - map(lambda x: diskOpts.get(x[0], x[1]), - map(lambda x: ( - x[0], FileSystemManager.getDefaultOpt(x[1], - ssd=ssdDisk.get( - x[2], - 'off') == 'on')), - self.ZipVars('os_install_disk_dev', - 'os_install_disk_format', - 'os_install_disk_parent')))) + ssd_devices = { + dev for dev, ssd in self.ZipVars('install.os_device_dev', + 'install.os_device_ssd_set') + if ssd == 'on' + } + old_options = { + dev: options for dev, options in self.ZipVars('os_disk_dev', + 'os_disk_options') + if options + } + + def generator(): + for disk_dev, disk_format, disk_parent in self.ZipVars( + 'os_install_disk_dev', + 'os_install_disk_format', + 'os_install_disk_parent'): + if disk_dev in old_options: + yield old_options[disk_dev] + else: + all_ssd = all(x in ssd_devices + for x in disk_parent.split(',')) + yield ",".join(FileSystemManager.getDefaultOpt(disk_format, + all_ssd)) + + return list(generator()) class VariableOsInstallDiskFormat(ReadonlyVariable): @@ -1646,31 +1668,25 @@ class VariableOsInstallDiskId(ReadonlyVariable): type = "list" def get(self): - diskId = dict(zip(self.Get('os_disk_dev'), - self.Get('os_disk_id'))) - diskId.update(zip(self.Get('cl_autopartition_disk_dev'), - [""] * len(self.Get('cl_autopartition_disk_dev')))) - - def getIdByFS(fs, parttable, oldid, mp): - if parttable == "gpt": - if mp == '/boot/efi': - fs = 'uefi' - fsinfo = FileSystemManager.supportFS.get(fs, {}) - return fsinfo.get('gpt', '8300') - elif parttable in ("primary", "extended", "logical"): - fsinfo = FileSystemManager.supportFS.get(fs, {}) - return fsinfo.get('msdos', '83') - return oldid - - FORMAT, PART, DEV, MOUNT, PARENT = 0, 1, 2, 3, 4 - return map(lambda x: getIdByFS(x[FORMAT], - x[PART], diskId.get(x[DEV], ''), x[MOUNT] - ) if x[PARENT] else '', - self.ZipVars('os_install_disk_format', - 'os_install_disk_part', - 'os_install_disk_dev', - 'os_install_disk_mount', - 'os_install_disk_parent')) + def generator(): + for (disk_dev, disk_part, disk_mount, + disk_format) in self.ZipVars('os_install_disk_dev', + 'os_install_disk_part', + 'os_install_disk_mount', + 'os_install_disk_format'): + if disk_part in ("gpt", "primary", "extended", "logical"): + if disk_part == "gpt": + if disk_mount == "/boot/efi": + disk_format = "uefi" + else: + disk_part = "msdos" + fsinfo = FileSystemManager.supportFS.get( + disk_format, FileSystemManager.default_param) + yield fsinfo.get(disk_part) + else: + yield "" + + return list(generator()) class VariableOsInstallDiskName(Variable): @@ -1736,25 +1752,6 @@ class VariableOsInstallDiskType(SourceReadonlyVariable): humanReadable = Variable.humanReadable -class VariableOsInstallDiskParent(SourceReadonlyVariable): - """ - Partition parent devices using for install - """ - type = "list" - indexField = "os_install_disk_dev" - - def getMap(self): - diskParent = dict(self.ZipVars('os_disk_dev', 'os_disk_parent')) - # replace value for autopartition - if self.Get('cl_autopartition_set') == 'on': - diskParent.update(zip(self.Get('cl_autopartition_disk_dev'), - self.Get('cl_autopartition_device') * - len(self.Get('cl_autopartition_disk_dev')))) - return diskParent - - humanReadable = Variable.humanReadable - - class VariableOsInstallDiskPart(SourceReadonlyVariable): """ Get new type partitions using for install @@ -1824,6 +1821,29 @@ class VariableOsInstallBootloader(ReadonlyVariable): return ",".join(self.Get('os_install_mbr', humanreadable=True)) +class VariableOsInstallBootDevices(ReadonlyVariable): + """ + Физическое устройство с которого будет производиться загрузка системы на + котором находится /boot или /, т.е. если / находится на RAID, расположенном + на двух дисках, то это будет те самые диски + """ + type = "list" + + def get(self): + bootDev = self.Select('os_install_disk_parent_base', + where='os_install_disk_mount_base', + _in=('/', '/boot'), sort="DESC", limit=1) + if bootDev: + devices = self.Select('os_disk_parent', + where='os_disk_dev', + _eq=bootDev, limit=1).split(",") + return [dev + for dev, table in self.ZipVars('os_device_dev', + 'os_device_table') + if table and dev in devices] + return [] + + class VariableOsInstallMbr(LocationHelper, Variable): """ Disks for boot mbr @@ -1853,51 +1873,11 @@ class VariableOsInstallMbr(LocationHelper, Variable): return [device[0]] else: return [] - bootDev = self.Select('os_install_disk_dev', - where='os_install_disk_mount', - _in=('/', '/boot'), sort="DESC", limit=1) - # if install on lvm detected - if self.Get('os_install_lvm_set') == "on": - if bootDev: - lvmDisk = self.Select('os_disk_lvm', - where='os_disk_dev', - eq=bootDev, limit=1) - if lvmDisk: - vgName, lvName = lvmDisk[5:].split('/') - disks = self.Select('os_lvm_pvname', - where='os_lvm_vgname', - eq=vgName) - devices = self.Select('os_disk_parent', - where='os_disk_dev', - _in=disks) - res = map(itemgetter(0), - filter(lambda x: x[0] in devices and x[1], - self.ZipVars('os_device_dev', - 'os_device_table'))) - if res: - return res - if self.Get('os_install_mdadm_set') == "on": - if bootDev: - disks = self.Select('os_disk_parent', - where='os_disk_type', - like='raidmember\(%s\)' % bootDev) - res = map(itemgetter(0), - filter(lambda x: x[0] in disks and x[1], - self.ZipVars('os_device_dev', - 'os_device_table'))) - if res: - return res - # if loaded system livecd - if self.Get('os_root_type') == "livecd": - bootDevice = self.Select('os_install_disk_parent', - where='os_install_disk_mount', - _in=('/', '/boot'), - sort="DESC")[:1] - # search /boot device or / device, by priority /boot,/ - if bootDevice: - return bootDevice - return [self.Select('os_device_dev', where='os_device_type', eq='hdd', - limit=1)] + bootdevices = self.Get('os_install_boot_devices') + if self.Get('os_root_type') == "hdd": + bootdevices.append(self.Select( + 'os_device_dev', where='os_device_type', eq='hdd', limit=1)) + return sorted(set(bootdevices)) def choice(self): deviceParentMap = dict(self.ZipVars('os_device_dev', 'os_device_name')) @@ -1940,52 +1920,33 @@ class VariableOsInstallMbr(LocationHelper, Variable): raise VariableError(_("You need a disk with a dos " "table for Flash install")) if rootType in ("usb-hdd", "hdd") and tableOnBootDisk == "gpt": - efisize = self.Select('os_disk_size', - where=['os_disk_id', 'os_disk_parent'], - func=lambda os_disk_id, os_disk_parent: ( - os_disk_id == 'EF02' and os_disk_parent == mbrDisk), - limit=1) + bbsizes = ( + size + for size, disk_id, disk_parent in self.ZipVars( + 'os_disk_size', 'os_disk_id', 'os_disk_parent' + ) + if disk_id == 'EF02' and mbrDisk in disk_parent + ) bios_grub_size = self.Get('cl_autopartition_bios_grub_size') - minsize = "%dMb" % (int(bios_grub_size) / Sizes.M) - if not efisize: - raise VariableError( - _("Your boot device must have a BIOS Boot partition " - "({minsize})").format(minsize=minsize)) - # проверка размера EF02 при установке на btrfs - elif useBtrfs: - if (efisize.isdigit() and bios_grub_size.isdigit() and - int(efisize) < int(bios_grub_size)): + for bbsize in bbsizes: + minsize = "%dMb" % (int(bios_grub_size) / Sizes.M) + if not bbsize: raise VariableError( - _("Your boot device must have a BIOS Boot " - "partition ({minsize})").format(minsize=minsize)) + _("Your boot device must have a " + "BIOS Boot partition ({minsize})").format( + minsize=minsize)) + # проверка размера EF02 при установке на btrfs + elif useBtrfs: + if (bbsize.isdigit() and bios_grub_size.isdigit() and + int(bbsize) < int(bios_grub_size)): + raise VariableError( + _("Your boot device must have a BIOS Boot " + "partition ({minsize})").format( + minsize=minsize)) if value: - if self.Get('os_grub2_path'): - self.checkForGrub2() - else: + if not self.Get('os_grub2_path'): self.checkForLegacyGrub() - def checkForGrub2(self): - """ - Проверить текущую конфигурацию диска для установки GRUB2 - """ - grubDiskType = self.Select('os_install_disk_parent', - where='os_install_disk_mount', - _in=('/', '/boot'), - sort="DESC", limit=1) - - if "lvm-raid" in grubDiskType: - raise VariableError( - _( - "Grub does not support booting from a RAID assembled from a LVM") - + ". " + - _("Try to use a separate /boot partition")) - if grubDiskType.count("raid") > 1: - raise VariableError( - _("Grub does not support booting from a RAID assembled " - "from another RAID") - + ". " + - _("Try to use a separate /boot partition")) - def checkForLegacyGrub(self): """Check current disk configuration for installation for install legacy grub""" @@ -1997,8 +1958,8 @@ class VariableOsInstallMbr(LocationHelper, Variable): sort="DESC", limit=1) if "lvm" in bootDiskType or "raid" in bootDiskType: raise ValueError( - _( - "Legacy grub requires a separate /boot partition to support boot from a RAID or a LVM")) + _("Legacy grub requires a separate /boot partition " + "to support boot from a RAID or a LVM")) if bootDiskFormat in ("btrfs", "nilfs2"): raise ValueError( _("To support booting from %s, legacy grub needs a " @@ -2166,15 +2127,15 @@ class VariableOsInstallDiskSingle(Variable): self.help = _("set the USB Flash device") def choice(self): - diskParentMap = dict(zip(self.Get('os_disk_dev'), - self.Get('os_disk_parent'))) - deviceParentMap = dict(self.ZipVars('os_device_dev', 'os_device_name')) - disks = self.select('os_disk_dev', os_disk_part__ne="") - return map(lambda x: (x, "%s (%s)" % (x, - deviceParentMap.get( - diskParentMap.get(x, x), - _("Unknown")))), - disks) + def generator(): + device_names = dict(self.ZipVars('os_device_dev', + 'os_device_name')) + for disk_dev, disk_type, disk_parent in self.ZipVars( + 'os_disk_dev', 'os_disk_type', 'os_disk_parent'): + if disk_type == "disk-partition": + device_name = device_names.get(disk_parent, _("Unknown")) + yield disk_dev, device_name + return list(generator()) def check(self, value): # проверить, чтобы был выбран именно раздел