Skip to content

Commit

Permalink
Merge 8db06fa into a3a5217
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Oct 2, 2018
2 parents a3a5217 + 8db06fa commit bc27cc8
Show file tree
Hide file tree
Showing 18 changed files with 895 additions and 200 deletions.
60 changes: 56 additions & 4 deletions src/lib/y2storage/autoinst_profile/drive_section.rb
Expand Up @@ -190,6 +190,30 @@ def section_name
"drives"
end

# @return [String] disklabel value which indicates that no partition table is wanted.
NO_PARTITION_TABLE = "none".freeze

# Determine whether the drive should have a partition table or not
#
# @note When the disklabel is set to 'none', a partition table should be created.
# For backward compatibility reasons, setting partition_nr to 0 has the same effect.
#
# @return [Boolean] Returns true when a partition table is wanted; false otherwise.
def partition_table?
disklabel != NO_PARTITION_TABLE && partitions.none? { |i| i.partition_nr == 0 }
end

# Returns the partition which contains the configuration for the whole disk
#
# @return [PartitionSection,nil] Partition section for the whole disk; it returns
# nil if the device will use a partition table.
#
# @see #partition_table?
def master_partition
return if partition_table?
partitions.find { |i| i.partition_nr == 0 } || partitions.first
end

protected

# Method used by {.new_from_storage} to populate the attributes when
Expand All @@ -201,14 +225,14 @@ def section_name
# @param disk [Y2Storage::Disk, Y2Storage::Dasd] Disk
# @return [Boolean]
def init_from_disk(disk)
return false if disk.partitions.empty?
return false unless used?(disk)

@type = :CT_DISK
# s390 prefers udev by-path device names (bsc#591603)
@device = Yast::Arch.s390 ? disk.udev_full_paths.first : disk.name
# if disk.udev_full_paths.first is nil go for disk.name anyway
@device ||= disk.name
@disklabel = disk.partition_table.type.to_s
@disklabel = disklabel_from_disk(disk)

@partitions = partitions_from_disk(disk)
return false if @partitions.empty?
Expand Down Expand Up @@ -266,9 +290,19 @@ def partitions_from_hash(hash)
hash["partitions"].map { |part| PartitionSection.new_from_hashes(part, self) }
end

# Return the partition sections for the given disk
#
# @note If there is no partition table, an array containing a single section
# (which represents the whole disk) will be returned.
#
# @return [Array<AutoinstProfile::PartitionSection>] List of partition sections
def partitions_from_disk(disk)
collection = disk.partitions.reject { |p| skip_partition?(p) }
partitions_from_collection(collection.sort_by(&:number))
if disk.partition_table
collection = disk.partitions.reject { |p| skip_partition?(p) }
partitions_from_collection(collection.sort_by(&:number))
else
[PartitionSection.new_from_storage(disk)]
end
end

def partitions_from_collection(collection)
Expand Down Expand Up @@ -374,6 +408,24 @@ def use_value_from_string(use)
def enabled_snapshots?(filesystems)
filesystems.any? { |f| f.respond_to?(:snapshots?) && f.snapshots? }
end

# Determine whether the disk is used or not
#
# @param disk [Array<Y2Storage::Disk,Y2Storage::Dasd>] Disk to check whether it is used
# @return [Boolean] true if the disk is being used
def used?(disk)
!(disk.partitions.empty? && disk.component_of.empty?)
end

# Return the disklabel value for the given disk
#
# @note When no partition table is wanted, the value 'none' will be used.
#
# @param disk [Array<Y2Storage::Disk,Y2Storage::Dasd>] Disk to check get the disklabel from
# @return [String] Disklabel value
def disklabel_from_disk(disk)
disk.partition_table ? disk.partition_table.type.to_s : NO_PARTITION_TABLE
end
end
end
end
10 changes: 9 additions & 1 deletion src/lib/y2storage/autoinst_profile/partition_section.rb
Expand Up @@ -252,7 +252,7 @@ def init_from_device(device)
# unit (that equals to 8225280 bytes in my experiments).
# According to the comments there, that was done due to bnc#415005 and
# bnc#262535.
@size = device.size.to_i.to_s if create && !device.is?(:md)
@size = device.size.to_i.to_s if create && !device.is?(:disk_device)
end

def to_hashes
Expand Down Expand Up @@ -289,6 +289,8 @@ def init_fields_by_type(device)
init_lv_fields(device)
elsif device.is?(:md)
init_md_fields(device)
elsif device.is?(:disk_device)
init_disk_fields(device)
else
init_partition_fields(device)
end
Expand All @@ -303,6 +305,12 @@ def init_partition_fields(partition)
@raid_name = partition.md.name if partition.md
end

def init_disk_fields(disk)
@create = false
@lvm_group = lvm_group_name(disk)
@raid_name = disk.md.name if disk.md
end

def init_lv_fields(lv)
@lv_name = lv.basename
@stripes = lv.stripes
Expand Down
41 changes: 14 additions & 27 deletions src/lib/y2storage/autoinst_proposal.rb
Expand Up @@ -22,6 +22,7 @@
require "yast"
require "y2storage/proposal_settings"
require "y2storage/exceptions"
require "y2storage/planned"
require "y2storage/proposal"

module Y2Storage
Expand Down Expand Up @@ -115,6 +116,7 @@ def propose_devicegraph(devicegraph, drives)
# @param drives [Proposal::AutoinstDrivesMap] Devices map from an AutoYaST profile
def add_partition_tables(devicegraph, drives)
drives.each do |disk_name, drive_spec|
next unless drive_spec.partition_table?
disk = devicegraph.disk_devices.find { |d| d.name == disk_name }
next if disk.nil? || !disk.partitions.empty?

Expand Down Expand Up @@ -155,29 +157,13 @@ def update_partition_table(disk, ptable_type)
# The devicegraph which is passed as first argument will be modified.
#
# @param devicegraph [Devicegraph] Starting point
# @param devices [Array<Planned:Device>] List of planned devices
# @return [Array<Planned::Device>] List of required planned devices to boot
# @return [Array<Planned::DevicesCollection>] List of required planned devices to boot
def boot_devices(devicegraph, devices)
mountable_devices = find_mountable_devices(devices)
return unless root?(mountable_devices)
checker = BootRequirementsChecker.new(devicegraph, planned_devices: mountable_devices)
return unless root?(devices.mountable)
checker = BootRequirementsChecker.new(devicegraph, planned_devices: devices.mountable)
checker.needed_partitions
end

# Return mountable devices from the list of planned ones
#
# @param devices [Array<Planned::Device>] List of planned devices
# @return [Array<Planned::Device>] List of devices that can be mounted
def find_mountable_devices(devices)
devices.each_with_object([]) do |dev, all|
if dev.respond_to?(:mount_point)
all << dev
elsif dev.is_a?(Planned::LvmVg)
all.concat(dev.all_lvs)
end
end
end

# Determines whether the list of devices includes a root partition
#
# @param devices [Array<Planned:Device>] List of planned devices
Expand Down Expand Up @@ -213,7 +199,7 @@ def propose_guided_devicegraph(devicegraph, drives)
#
# @param devicegraph [Devicegraph] Starting point
# @param drives [Proposal::AutoinstDrivesMap] Devices map from an AutoYaST profile
# @return [Array<Planned::Device>] Devices to add
# @return [Planned::DevicesCollection] Devices to add
def plan_devices(devicegraph, drives)
planner = Proposal::AutoinstDevicesPlanner.new(devicegraph, issues_list)
planner.planned_devices(drives)
Expand All @@ -223,7 +209,7 @@ def plan_devices(devicegraph, drives)
#
# @param devicegraph [Devicegraph] Starting point
# @param drives [AutoinstDrivesMap] Devices map from an AutoYaST profile
# @param planned_devices [<Planned::Device>] Planned devices
# @param planned_devices [<Planned::DevicesCollection>] Planned devices
# @return [Devicegraph] Clean devicegraph
#
# @see Y2Storage::Proposal::AutoinstSpaceMaker
Expand All @@ -242,7 +228,7 @@ def clean_graph(devicegraph, drives, planned_devices)
def guided_devicegraph_for_target(devicegraph, drives, target)
guided_settings = proposal_settings_for_disks(drives)
guided_planner = Proposal::DevicesPlanner.new(guided_settings, devicegraph)
@planned_devices = guided_planner.planned_devices(target)
@planned_devices = Planned::DevicesCollection.new(guided_planner.planned_devices(target))
result = create_devices(devicegraph, @planned_devices, drives.disk_names)
result.devicegraph
end
Expand All @@ -255,16 +241,17 @@ def guided_devicegraph_for_target(devicegraph, drives, target)
#
# As a side effect, it updates the planned devices list if needed.
#
# @param devicegraph [Devicegraph] Starting point
# @param planned_devices [Array<Planned::Device>] Devices to add
# @param disk_names [Array<String>] Names of the disks to consider
# @param devicegraph [Devicegraph] Starting point
# @param planned_devices [Planned::DevicesCollection] Devices to add
# @param disk_names [Array<String>] Names of the disks to consider
# @return [Devicegraph] Copy of devicegraph containing the planned devices
def create_devices(devicegraph, planned_devices, disk_names)
boot_parts = boot_devices(devicegraph, @planned_devices)
devices_creator = Proposal::AutoinstDevicesCreator.new(devicegraph)
begin
result = devices_creator.populated_devicegraph(boot_parts + planned_devices, disk_names)
@planned_devices.unshift(*boot_parts)
planned_with_boot = planned_devices.prepend(boot_parts)
result = devices_creator.populated_devicegraph(planned_with_boot, disk_names)
@planned_devices = planned_with_boot
rescue Y2Storage::NoDiskSpaceError
raise if boot_parts.empty?
result = devices_creator.populated_devicegraph(planned_devices, disk_names)
Expand Down
2 changes: 2 additions & 0 deletions src/lib/y2storage/planned.rb
Expand Up @@ -19,10 +19,12 @@
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "y2storage/planned/disk"
require "y2storage/planned/partition"
require "y2storage/planned/stray_blk_device"
require "y2storage/planned/lvm_lv"
require "y2storage/planned/lvm_vg"
require "y2storage/planned/md"
require "y2storage/planned/assigned_space"
require "y2storage/planned/partitions_distribution"
require "y2storage/planned/devices_collection"
142 changes: 142 additions & 0 deletions src/lib/y2storage/planned/devices_collection.rb
@@ -0,0 +1,142 @@
# encoding: utf-8

# Copyright (c) [2018] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "forwardable"

module Y2Storage
module Planned
# This class holds a list of planned devices and offers an API to query the collection
#
# Instances of this classes are immutable, so methods like {#append} or {#prepend} will return
# new instances.
#
# @example Create a collection
# disk = Disk.new
# vg = LvmVg.new
# collection = DevicesCollection.new([disk, vg])
#
# @example Filter by device type (e.g., disk devices)
# sda = Disk.new
# sdb = Disk.new
# vg = LvmVg.new
# collection = DevicesCollection.new([sda, sdb, vg])
# collection.disks #=> [sda, sdb]
#
# @example Combining collections
# disk = Disk.new
# vg = LvmVg.new
# collection0 = DevicesCollection.new([disk])
# collection1 = DevicesCollection.new([vg])
# combined = collection0.append(collection1)
# combined.devices #=> [disk, vg]
class DevicesCollection
extend Forwardable
include Enumerable

# @!attribute [r] devices
# @return [Array<Planned::Device>] List of planned devices
attr_reader :devices

def_delegators :all, :each

def initialize(devices = [])
@devices = devices
end

# Prepends the given devices to the collection
#
# @note This method returns a new instance.
#
# @param devices [Array<Y2Storage::Planned::Device>,Y2Storage::Planned::Device]
# Devices to add
# @return [DevicesCollection]
def prepend(devices)
self.class.new(devices + @devices)
end

# Returns a new instance including the devices
#
# @param devices [Array<Y2Storage::Planned::Device>,Y2Storage::Planned::Device]
# Devices to add
# @return [DevicesCollection]
def append(devices)
self.class.new(@devices + devices)
end

# Returns the list of planned partitions, including nested ones (within a disk)
#
# @return [Array<Planned::Partition>]
def partitions
@partitions ||= devices.select { |d| d.is_a?(Planned::Partition) } +
disks.map(&:partitions).flatten
end

# Returns the list of planned disks
#
# @return [Array<Planned::Disk>]
def disks
@disks ||= devices.select { |d| d.is_a?(Planned::Disk) }
end

# Returns the list of planned volume groups
#
# @return [Array<Planned::LvmVg>]
def vgs
@vgs ||= devices.select { |d| d.is_a?(Planned::LvmVg) }
end

# Returns the list of planned MD RAID devices
#
# @return [Array<Planned::Md>]
def mds
@mds ||= devices.select { |d| d.is_a?(Planned::Md) }
end

# Returns the list of planned LVM logical volumes
#
# @return [Array<Planned::LvmLv>]
def lvs
@lvs ||= vgs.map(&:all_lvs).flatten
end

# Returns the list of planned stray block devices.
#
# @return [Array<Planned::StrayBlkDevice>]
def stray_blk_devices
@stray_blk_devices ||= devices.select { |d| d.is_a?(Planned::StrayBlkDevice) }
end

# Returns all devices, including nested ones
#
# @return [Array<Planned::Device>]
def all
@all ||= partitions + disks + stray_blk_devices + vgs + lvs + mds
end

# Returns the list of devices that can be mounted
#
# @return [Array<Planned::Device>]
def mountable
@mountable ||= all.select { |d| d.respond_to?(:mount_point) }
end
end
end
end

0 comments on commit bc27cc8

Please sign in to comment.