Skip to content

Commit

Permalink
Merge a7ea2e8 into 49ffb78
Browse files Browse the repository at this point in the history
  • Loading branch information
imobachgs committed Oct 25, 2017
2 parents 49ffb78 + a7ea2e8 commit 87bf94f
Show file tree
Hide file tree
Showing 14 changed files with 262 additions and 12 deletions.
6 changes: 6 additions & 0 deletions package/yast2-storage-ng.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Wed Oct 25 13:12:37 UTC 2017 - igonzalezsosa@suse.com

- Add support to clone subvolumes when using AutoYaST (bsc#1064875)
- 4.0.11

-------------------------------------------------------------------
Wed Oct 25 12:32:58 CEST 2017 - snwint@suse.de

Expand Down
2 changes: 1 addition & 1 deletion package/yast2-storage-ng.spec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#

Name: yast2-storage-ng
Version: 4.0.10
Version: 4.0.11
Release: 0
BuildArch: noarch

Expand Down
42 changes: 37 additions & 5 deletions src/lib/y2storage/autoinst_profile/partition_section.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ def self.attributes
{ name: :raid_name },
{ name: :raid_options },
{ name: :mkfs_options },
{ name: :fstab_options, xml_name: :fstopt }
{ name: :fstab_options, xml_name: :fstopt },
{ name: :default_btrfs_subvolume_name }
]
end

Expand Down Expand Up @@ -120,7 +121,8 @@ def self.attributes
# @return [String] undocumented attribute that can only contain "primary"

# @!attribute subvolumes
# @return [Array<SubvolSpecification>] list of subvolumes
# @return [Array<SubvolSpecification>,nil] list of subvolumes or nil if not
# supported (from storage) or not specified (from hashes)

# @!attribute size
# @return [String] size of the partition in the flexible AutoYaST format
Expand All @@ -141,9 +143,8 @@ def self.attributes
# @!attribute fstab_options
# @return [Array<String>] Options to be used in the fstab for the filesystem

def initialize
@subvolumes = []
end
# @!attribute default_btrfs_subvolume_name
# @return [String] Name of the default Btrfs subvolume

def init_from_hashes(hash)
super
Expand Down Expand Up @@ -245,6 +246,7 @@ def init_from_partition(partition)
def to_hashes
hash = super
hash["fstopt"] = fstab_options.join(",") if fstab_options && !fstab_options.empty?
hash["subvolumes"] = subvolumes_to_hashes if subvolumes
hash
end

Expand Down Expand Up @@ -276,6 +278,7 @@ def init_filesystem_fields(partition)
@filesystem = fs.type.to_sym
@label = fs.label unless fs.label.empty?
@mkfs_options = fs.mkfs_options unless fs.mkfs_options.empty?
init_subvolumes(fs)
init_mount_options(fs)
end

Expand All @@ -288,6 +291,23 @@ def init_mount_options(fs)
@fstab_options = fs.fstab_options unless fs.fstab_options.empty?
end

# @param fs [Filesystem::BlkFilesystem]
def init_subvolumes(fs)
return unless fs.supports_btrfs_subvolumes?

@default_btrfs_subvolume_name = fs.default_subvolume_name

snapshots_root = File.join(@default_btrfs_subvolume_name.to_s, ".snapshots")
valid_subvolumes = fs.btrfs_subvolumes.reject do |subvol|
subvol.path.empty? || subvol.path == @default_btrfs_subvolume_name ||
subvol.path.start_with?(snapshots_root)
end

@subvolumes = valid_subvolumes.map do |subvol|
SubvolSpecification.create_from_btrfs_subvolume(subvol)
end
end

# Whether the given existing partition should be reported as GRUB (GPT
# Bios Boot) in the cloned profile.
#
Expand All @@ -306,6 +326,18 @@ def enforce_bios_boot?(partition)
return false if partition.filesystem_mountpoint.nil?
partition.id.is?(:windows_system) && partition.filesystem_mountpoint.include?("/boot")
end

# Returns an array of hashes representing subvolumes
#
# AutoYaST only uses a subset of subvolumes properties: 'path' and 'copy_on_write'.
#
# @return [Array<Hash>] Array of hash-based representations of subvolumes
def subvolumes_to_hashes
subvolumes.map do |subvol|
subvol_path = subvol.path.sub(/\A#{@default_btrfs_subvolume_name}\//, "")
{ "path" => subvol_path, "copy_on_write" => subvol.copy_on_write }
end
end
end
end
end
12 changes: 12 additions & 0 deletions src/lib/y2storage/filesystems/btrfs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,18 @@ def restore_unshadowed_subvolumes(devicegraph)
end
end

# Determines the default subvolume name
#
# When a default subvolume name have been used, a subvolume named after
# it lives under the #top_level_btrfs_subvolume. Otherwise, an empty
# string will be taken as the default subvolume name.
#
# @return [String] Default subvolume name
def default_subvolume_name
children = top_level_btrfs_subvolume.children
children.size == 1 ? children.first.path : ""
end

protected

# Removes a subvolume
Expand Down
1 change: 1 addition & 0 deletions src/lib/y2storage/planned/can_be_formatted.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def subvolumes?
# @param all_devices [Array<Planned::Device>] all the devices planned for the system.
# @return [Array<SubvolSpecification>]
def shadowed_subvolumes(all_devices)
return [] if subvolumes.nil?
other_devices = all_devices - [self]
other_mount_points = other_devices.map { |dev| mount_point_for(dev) }.compact
subvolumes.select { |s| s.shadowed?(mount_point, other_mount_points) }
Expand Down
2 changes: 1 addition & 1 deletion src/lib/y2storage/proposal/autoinst_devices_planner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def add_subvolumes_attrs(device, section)
subvol_specs = section.subvolumes
mount = device.mount_point

if subvol_specs.empty? && mount == "/"
if subvol_specs.nil? && mount == "/"
@default_subvolumes_used = true
subvol_specs = proposal_settings.subvolumes
end
Expand Down
10 changes: 10 additions & 0 deletions src/lib/y2storage/subvol_specification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,16 @@ def self.create_from_xml(xml)
planned_subvol
end

# Create a SubvolSpecification from a Btrfs subvolume
#
# @param subvolume [BtrfsSubvolume] Btrfs subvolume
# @return [SubvolSpecification]
def self.create_from_btrfs_subvolume(subvolume)
subvol = SubvolSpecification.new(subvolume.path, copy_on_write: !subvolume.nocow?)
log.info "Creating from Btrfs subvolume: #{subvol}"
subvol
end

# Create a list of SubvolSpecification objects from the <subvolumes> part of
# control.xml or an AutoYaST profile. The map may be empty if there is a
# <subvolumes> section, but that section is empty.
Expand Down
40 changes: 40 additions & 0 deletions test/data/devicegraphs/autoyast_drive_examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,46 @@
id: linux
file_system: btrfs
mount_point: "/"
btrfs:
default_subvolume: "@"
subvolumes:
- subvolume:
path: "@/home"
nocow: false
- subvolume:
path: "@/srv"
nocow: false
- subvolume:
path: "@/tmp"
nocow: false
- subvolume:
path: "@/usr/local"
nocow: false
- subvolume:
path: "@/var/cache"
nocow: false
- subvolume:
path: "@/var/crash"
nocow: false
- subvolume:
path: "@/log"
nocow: false
- subvolume:
path: "@/opt"
nocow: false
- subvolume:
path: "@/var/lib/mariadb"
nocow: true
- subvolume:
path: "@/var/lib/mysql"
nocow: true
- subvolume:
path: "@/var/lib/pgsql"
nocow: true
- subvolume:
path: "@/.snapshots"
- subvolume:
path: "@/.snapshots/1/snapshot"

- partition:
size: 12290 MiB
Expand Down
48 changes: 48 additions & 0 deletions test/data/devicegraphs/mixed_disks_btrfs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,51 @@
name: /dev/sdc
size: 500 GiB
partition_table: ms-dos

- disk:
name: /dev/sdd
size: 200 GiB
partition_table: ms-dos
partitions:

- partition:
size: unlimited
name: /dev/sdd1
mount_point: /
label: root
file_system: btrfs
btrfs:
subvolumes:
- subvolume:
path: "@/home"
nocow: false
- subvolume:
path: "@/srv"
nocow: false
- subvolume:
path: "@/tmp"
nocow: false
- subvolume:
path: "@/usr/local"
nocow: false
- subvolume:
path: "@/var/cache"
nocow: false
- subvolume:
path: "@/var/crash"
nocow: false
- subvolume:
path: "@/log"
nocow: false
- subvolume:
path: "@/opt"
nocow: false
- subvolume:
path: "@/var/lib/mariadb"
nocow: true
- subvolume:
path: "@/var/lib/mysql"
nocow: true
- subvolume:
path: "@/var/lib/pgsql"
nocow: true
2 changes: 1 addition & 1 deletion test/y2partitioner/widgets/pages/btrfs_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
table = widgets.detect { |i| i.is_a?(Y2Partitioner::Widgets::BlkDevicesTable) }

expect(table).to_not be_nil
expect(table.items.size).to eq(3)
expect(table.items.size).to eq(4)

devices_name = btrfs_devices.map(&:name)
items_name = table.items.map { |i| i[1] }
Expand Down
68 changes: 64 additions & 4 deletions test/y2storage/autoinst_profile/partition_section_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,28 @@ def section_for(name)
expect(section_for("sdb1").size).to eq Y2Storage::DiskSize.GiB(780).to_i.to_s
end

context "when filesystem is btrfs" do
it "initializes subvolumes" do
subvolumes = section_for("sdd3").subvolumes
expect(subvolumes).to all(be_a(Y2Storage::SubvolSpecification))
end

it "initializes default_btrfs_subvolume_name" do
expect(section_for("sdd3").default_btrfs_subvolume_name).to eq("@")
end

it "ignores snapshots" do
paths = section_for("sdd3").subvolumes.map(&:path)
expect(paths).to_not include("@/.snapshots")
end

context "and there are not subvolumes" do
it "initializes subvolumes as an empty array" do
expect(section_for("dasdb2").subvolumes).to eq([])
end
end
end

context "if the partition contains a filesystem" do
it "initializes #filesystem with the corresponding symbol" do
expect(section_for("dasdb1").filesystem).to eq :swap
Expand Down Expand Up @@ -229,9 +251,16 @@ def section_for(name)
end

context "when subvolumes are not present in the hash" do
it "initializes #subvolumes to an empty array" do
it "initializes #subvolumes to nil" do
section = described_class.new_from_hashes(hash)
expect(section.subvolumes).to eq []
expect(section.subvolumes).to be_nil
end
end

context "when subvolumes are present in the hash but value is nil" do
it "initializes #subvolumes to an empty array" do
section = described_class.new_from_hashes(hash.merge("subvolumes" => nil))
expect(section.subvolumes).to be_nil
end
end

Expand Down Expand Up @@ -324,11 +353,42 @@ def section_for(name)
expect(section.to_hashes).to eq({})
end

it "does not export #subvolumes if it is empty" do
section.subvolumes = []
it "does not export #subvolumes if nil" do
section.subvolumes = nil
expect(section.to_hashes.keys).to_not include "subvolumes"
end

context "when some subvolume exist" do
before do
section.subvolumes = [
Y2Storage::SubvolSpecification.new("@/var/log", copy_on_write: true)
]
end

it "exports subvolumes as an array of hashes" do
expect(section.to_hashes["subvolumes"]).to eq(
[{ "path" => "@/var/log", "copy_on_write" => true }]
)
end

context "when a default subvolume was specified" do
before do
section.default_btrfs_subvolume_name = "@"
end

it "removes default subvolume from path" do
expect(section.to_hashes["subvolumes"]).to eq(
[{ "path" => "var/log", "copy_on_write" => true }]
)
end
end
end

it "exports default btrfs subvolume name" do
section.default_btrfs_subvolume_name = "@"
expect(section.to_hashes["default_btrfs_subvolume_name"]).to eq("@")
end

it "does not export fstab options if it is empty" do
section.fstab_options = []
expect(section.to_hashes.keys).to_not include("fstab_options")
Expand Down
18 changes: 18 additions & 0 deletions test/y2storage/filesystems/btrfs_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -639,4 +639,22 @@
end
end
end

describe "#default_subvolume_name" do
context "when a default subvolume name is set to '@'" do
let(:dev_name) { "/dev/sda2" }

it "returns the default subvolume name '@'" do
expect(subject.default_subvolume_name).to eq("@")
end
end

context "when default subvolume name is not set" do
let(:dev_name) { "/dev/sdd1" }

it "returns an empty string" do
expect(subject.default_subvolume_name).to eq("")
end
end
end
end

0 comments on commit 87bf94f

Please sign in to comment.