Skip to content

Commit

Permalink
Merge branch 'merge_after_SP2_release' into btrfs-subvolume-options-m…
Browse files Browse the repository at this point in the history
…aster

* merge_after_SP2_release:
  Btrfs subvolume opts (#252)
  • Loading branch information
imobachgs committed Nov 3, 2016
2 parents 9e64bad + e7eace2 commit 5a0c5d9
Show file tree
Hide file tree
Showing 15 changed files with 432 additions and 43 deletions.
9 changes: 9 additions & 0 deletions package/autoyast2.changes
@@ -1,3 +1,12 @@
-------------------------------------------------------------------
Mon Oct 24 09:04:25 UTC 2016 - igonzalezsosa@suse.com

- Add support to enable copy-on-write for Btrfs subvolumes
(FATE#320342)
- Add support to omit the Btrfs default subvolume name
(FATE#317775)
- 3.2.0

-------------------------------------------------------------------
Fri Sep 30 10:21:45 CEST 2016 - schubi@suse.de

Expand Down
5 changes: 3 additions & 2 deletions package/autoyast2.spec
Expand Up @@ -17,7 +17,7 @@


Name: autoyast2
Version: 3.1.152
Version: 3.2.0
Release: 0

BuildRoot: %{_tmppath}/%{name}-%{version}-build
Expand All @@ -34,7 +34,8 @@ BuildRequires: libxml2-tools
BuildRequires: libxslt
BuildRequires: rubygem(%{rb_default_ruby_abi}:rspec)
BuildRequires: yast2
BuildRequires: yast2-storage >= 3.1.59
# FileSystems.read_default_subvol_from_target
BuildRequires: yast2-storage >= 3.2.0
BuildRequires: yast2-xml
BuildRequires: yast2-transfer
BuildRequires: yast2-services-manager
Expand Down
4 changes: 3 additions & 1 deletion src/autoyast-rnc/general.rnc
Expand Up @@ -26,7 +26,9 @@ general = element general {
}? &
element storage {
element partition_alignment { SYMBOL }? &
element start_multipath { BOOLEAN }?
element start_multipath { BOOLEAN }? &
# FATE#317775: support for arbitraty Btrfs subvolume structure
element btrfs_set_default_subvolume_name { BOOLEAN }?
}? &
element wait {
element pre-modules {
Expand Down
13 changes: 12 additions & 1 deletion src/autoyast-rnc/partitioning.rnc
Expand Up @@ -110,9 +110,20 @@ device_order = element device_order {

subvolumes = element subvolumes {
LIST,
element listentry { text }*
subvolume*
}

# by default, AutoYaST exports list entries as 'listentry'
subvolume =
element subvolume { text } | element listentry { text } | subvolume_full

subvolume_full =
element subvolume {
element path { text } &
# FATE#320342: add support to enable copy-on-write for Btrfs subvolumes
element copy_on_write { BOOLEAN }?
}

part_fstopt = element fstopt { text }
part_label = element label { text }
part_loop_fs =
Expand Down
2 changes: 0 additions & 2 deletions src/clients/inst_autoinit.rb
Expand Up @@ -200,8 +200,6 @@ def processProfile
Builtins.y2milestone("Initial Configuration")
Report.Import(Profile.current.fetch("report",{}))
AutoinstGeneral.Import(Profile.current.fetch("general",{}))
AutoinstGeneral.SetSignatureHandling
AutoinstGeneral.SetMultipathing

#
# Copy the control file for easy access by user to a pre-defined
Expand Down
57 changes: 50 additions & 7 deletions src/include/autoinstall/autopart.rb
Expand Up @@ -35,13 +35,9 @@ def AddSubvolData(st_map, xml_map)
Ops.set(
ret,
"subvol",
Builtins.maplist(Ops.get_list(xml_map, "subvolumes", [])) do |s|
if !Builtins.isempty(sv_prep) &&
Builtins.substring(s, 0, Builtins.size(sv_prep)) != sv_prep
s = Ops.add(sv_prep, s)
end
{ "name" => s, "create" => true }
end
# Convert from "vol" or {"name" => "vol", "copy_on_write" => false }
# to { "name" => "vol", "nocow" => true}
xml_map.fetch("subvolumes", []).map { |s| import_subvolume(s, sv_prep) }.compact
)
end
if Builtins.haskey(ret, "subvolumes")
Expand All @@ -52,6 +48,53 @@ def AddSubvolData(st_map, xml_map)
deep_copy(ret)
end

# Build a subvolume representation from a definition
#
# This method is suitable to import an AutoYaST profile.
# It supports two kind of subvolume specification:
#
# * just a path
# * or a hash containing a "path" and an optional "copy_on_write"
# key
#
# @param spec_or_name [Hash,String] Subvolume specification
# @param prefix [String] Subvolume prefix (usually default subvolume + '/')
# @return [Hash,nil] Internal representation of a subvolume or nil if not valid
def import_subvolume(spec_or_path, prefix = "")
# Support strings or hashes
name = spec_or_path.is_a?(::String) ? spec_or_path : spec_or_path["path"]

if name.nil?
log.info "Subvolume path/name is undefined: #{spec_or_path.inspect}"
return nil
end

spec = {
"name" => name.start_with?(prefix) ? name : "#{prefix}#{name}",
"create" => true
}

if spec_or_path.is_a?(Hash) && spec_or_path.has_key?("copy_on_write")
spec["nocow"] = !spec_or_path["copy_on_write"]
end
spec
end

# Build a subvolume specification from the current definition
#
# The result is suitable to be used to generate an AutoYaST profile.
#
# @param subvolume [Hash] Subvolume definition (internal storage layer definition)
# @param prefix [String] Subvolume prefix (usually default subvolume + '/')
# @return [Hash] External representation of a subvolume (e.g. to be used by AutoYaST)
def export_subvolume(subvolume, prefix = "")
spec = {
"path" => subvolume["name"].sub(/\A#{prefix}/, "")
}
spec["copy_on_write"] = !subvolume["nocow"]
spec
end

def AddFilesysData(st_map, xml_map)
st_map = deep_copy(st_map)
xml_map = deep_copy(xml_map)
Expand Down
42 changes: 42 additions & 0 deletions src/modules/AutoinstGeneral.rb
Expand Up @@ -10,6 +10,8 @@

module Yast
class AutoinstGeneralClass < Module
include Yast::Logger

def main
Yast.import "Pkg"
textdomain "autoinst"
Expand Down Expand Up @@ -185,6 +187,10 @@ def Import(settings)
@proposals = Ops.get_list(settings, "proposals", [])
@storage = Ops.get_map(settings, "storage", {})

SetSignatureHandling()
SetMultipathing()
set_btrfs_default_subvolume_name

true
end

Expand All @@ -198,6 +204,11 @@ def Export
Ops.set(general, "signature-handling", @signature_handling)
Ops.set(general, "ask-list", @askList)
Ops.set(general, "proposals", @proposals)

btrfs_set_default_subvol = btrfs_default_subvol_to_profile
unless btrfs_set_default_subvol.nil?
Ops.set(@storage, "btrfs_set_default_subvolume_name", btrfs_set_default_subvol)
end
Ops.set(general, "storage", @storage)

if Yast::Arch.s390
Expand Down Expand Up @@ -410,6 +421,21 @@ def SetMultipathing
Storage.SetMultipathStartup(val)
end

# Set Btrfs default subvolume name
#
# Check "general/storage/btrfs_set_default_subvolume_name" in the profile.
# It does nothing if that element does not exist.
#
# @return ["@","",nil] Default subvolume name to use.
#
# @see FileSystems.default_subvol
def set_btrfs_default_subvolume_name
return unless @storage.has_key?("btrfs_set_default_subvolume_name")
value = @storage["btrfs_set_default_subvolume_name"] ? "@" : ""
log.info "Setting default subvolume to: '#{value}'"
FileSystems.default_subvol = value
end

# NTP syncing
def NtpSync
ntp_server = @mode["ntp_sync_time_before_installation"]
Expand Down Expand Up @@ -489,6 +515,22 @@ def AutoinstGeneral
nil
end

protected

# Return the value to use as 'btrfs_set_default_subvolume_name' in the profile
#
# In case it matches the product's default, it should not be exported.
#
# @return [Boolean,nil] Value to use (true or false). If nil, no value
# should be exported.
def btrfs_default_subvol_to_profile
if FileSystems.default_subvol != FileSystems.default_subvol_from_product
return FileSystems.default_subvol == "" ? false : true
end
nil
end


publish :variable => :Confirm, :type => "boolean"
publish :variable => :second_stage, :type => "boolean"
publish :variable => :mode, :type => "map"
Expand Down
29 changes: 7 additions & 22 deletions src/modules/AutoinstPartPlan.rb
Expand Up @@ -14,6 +14,7 @@ def main
Yast.import "UI"
textdomain "autoinst"

Yast.include self, "autoinstall/autopart.rb"
Yast.include self, "autoinstall/types.rb"
Yast.include self, "autoinstall/common.rb"
Yast.include self, "autoinstall/tree.rb"
Expand Down Expand Up @@ -345,6 +346,7 @@ def ReadHelper
Mode.SetMode("normal")
StorageDevices.InitDone
_StorageMap = Builtins.eval(Storage.GetTargetMap)
FileSystems.read_default_subvol_from_target

_StorageMap = _StorageMap.select do |d, p|
ok = true
Expand Down Expand Up @@ -530,30 +532,13 @@ def ReadHelper
end
# Subvolumes
# Save possibly existing subvolumes
if !Builtins.isempty(Ops.get_list(pe, "subvol", []))
if !pe.fetch("subvol", []).empty?
defsub = ""
if !Builtins.isempty(FileSystems.default_subvol)
defsub = Ops.add(FileSystems.default_subvol, "/")
if !FileSystems.default_subvol.empty?
defsub = FileSystems.default_subvol + "/"
end
Ops.set(
new_pe,
"subvolumes",
Builtins.maplist(Ops.get_list(pe, "subvol", [])) do |p|
if Ops.greater_than(Builtins.size(defsub), 0) &&
Builtins.substring(
Ops.get_string(p, "name", ""),
0,
Builtins.size(defsub)
) == defsub
next Builtins.substring(
Ops.get_string(p, "name", ""),
Builtins.size(defsub)
)
else
next Ops.get_string(p, "name", "")
end
end
)
new_pe["subvolumes"] = pe.fetch("subvol", []).map { |s| export_subvolume(s, defsub) }

Ops.set(
new_pe,
"subvolumes",
Expand Down
4 changes: 3 additions & 1 deletion src/modules/AutoinstPartition.rb
Expand Up @@ -276,7 +276,9 @@ def parsePartition(part)
end
if !Builtins.isempty(Ops.get_list(part, "subvolumes", []))
#Filtering out all snapper subvolumes
newPart["subvolumes"] = part["subvolumes"].reject { |s| s.start_with?(".snapshots") }
newPart["subvolumes"] = part["subvolumes"].reject do |subvolume|
subvolume["path"].start_with?(".snapshots")
end
else
newPart = Builtins.remove(newPart, "subvolumes")
end
Expand Down
11 changes: 11 additions & 0 deletions test/AutoinstGeneral_test.rb
Expand Up @@ -8,6 +8,17 @@
describe Yast::AutoinstGeneral do
FIXTURES_PATH = File.join(File.dirname(__FILE__), 'fixtures')

let(:default_subvol) { "@" }
let(:filesystems) do
double("filesystems",
default_subvol: default_subvol, read_default_subvol_from_target: default_subvol)
end

before do
allow(Yast).to receive(:import).with("FileSystems").and_return(nil)
stub_const("Yast::FileSystems", filesystems)
end

describe "#ntp syncing in Write call" do
let(:profile_sync) { File.join(FIXTURES_PATH, 'profiles', 'general_with_time_sync.xml') }
let(:profile_no_sync) { File.join(FIXTURES_PATH, 'profiles', 'general_without_time_sync.xml') }
Expand Down
44 changes: 40 additions & 4 deletions test/AutoinstPartPlan_test.rb 100644 → 100755
Expand Up @@ -5,11 +5,21 @@

Yast.import "AutoinstPartPlan"
Yast.import "Profile"
Yast.import "ProductFeatures"

describe Yast::AutoinstPartPlan do
FIXTURES_PATH = File.join(File.dirname(__FILE__), 'fixtures')
let(:target_map_path) { File.join(FIXTURES_PATH, 'storage', "nfs_root.yml") }
let(:target_map_clone) { File.join(FIXTURES_PATH, 'storage', "target_clone.yml") }
let(:target_map_path) { File.join(FIXTURES_PATH, "storage", "nfs_root.yml") }
let(:target_map_clone) { File.join(FIXTURES_PATH, "storage", "target_clone.yml") }
let(:default_subvol) { "@" }
let(:filesystems) do
double("filesystems",
default_subvol: default_subvol, read_default_subvol_from_target: default_subvol)
end

before do
allow(Yast).to receive(:import).with("FileSystems").and_return(nil)
stub_const("Yast::FileSystems", filesystems)
end

describe "#read partition target" do

Expand Down Expand Up @@ -44,7 +54,33 @@
]
)
end

end

describe "#Export" do
let(:target_map) { YAML.load_file(File.join(FIXTURES_PATH, "storage", "subvolumes.yml")) }

before do
allow(Yast::Storage).to receive(:GetTargetMap).and_return(target_map)
Yast::AutoinstPartPlan.Read
end

it "includes found subvolumes" do
exported = Yast::AutoinstPartPlan.Export
subvolumes = exported.first["partitions"].first["subvolumes"]
expect(subvolumes).to eq([
{ "path" => "@", "copy_on_write" => true},
{ "path" => "home", "copy_on_write" => true },
{ "path" => "var/log", "copy_on_write" => true },
{ "path" => "var/lib/pgsql", "copy_on_write" => true },
{ "path" => "myvol", "copy_on_write" => false },
])
end

it "does not include snapshots" do
exported = Yast::AutoinstPartPlan.Export
subvolumes = exported.first["partitions"].first["subvolumes"]
snapshots = subvolumes.select { |s| s.include?("snapshot") }
expect(snapshots).to be_empty
end
end
end
2 changes: 2 additions & 0 deletions test/Makefile.am
Expand Up @@ -9,9 +9,11 @@ TESTS = \
AutoinstConfig_tests.rb \
AutoinstFunctions_test.rb \
AutoinstGeneral_test.rb \
AutoinstPartPlan_test.rb \
AutoinstSoftware_test.rb \
profile_test.rb \
Y2ModuleConfig_test.rb \
include/autopart_test.rb \
include/ask_test.rb \
lib/module_config_builder_test.rb \
lib/pkg_gpg_check_handler_test.rb
Expand Down

0 comments on commit 5a0c5d9

Please sign in to comment.