diff --git a/package/yast2-network.changes b/package/yast2-network.changes index af73c58d39..f4636cc6b4 100644 --- a/package/yast2-network.changes +++ b/package/yast2-network.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Thu Jan 12 11:45:25 UTC 2023 - Knut Anderssen + +- Copy only the specific backend configuration to the target system + having a clean installation (bsc#1206723) +- 4.5.12 + ------------------------------------------------------------------- Thu Dec 29 06:44:50 UTC 2022 - Knut Anderssen diff --git a/package/yast2-network.spec b/package/yast2-network.spec index ef0bab181d..c3774f4865 100644 --- a/package/yast2-network.spec +++ b/package/yast2-network.spec @@ -17,7 +17,7 @@ Name: yast2-network -Version: 4.5.11 +Version: 4.5.12 Release: 0 Summary: YaST2 - Network Configuration License: GPL-2.0-only diff --git a/src/lib/network/clients/save_network.rb b/src/lib/network/clients/save_network.rb index e7b8734561..76c4e246fa 100644 --- a/src/lib/network/clients/save_network.rb +++ b/src/lib/network/clients/save_network.rb @@ -17,221 +17,109 @@ # To contact SUSE LLC about this file by physical or electronic mail, you may # find current contact information at www.suse.com. -require "y2storage" -require "network/install_inf_convertor" require "network/network_autoconfiguration" require "network/network_autoyast" require "y2network/proposal_settings" +require "y2network/helpers" -require "cfa/generic_sysconfig" - -require "shellwords" +Yast.import "Installation" +Yast.import "DNS" +Yast.import "Mode" +Yast.import "Arch" module Yast class SaveNetworkClient < Client + include Y2Network::Helpers include Logger - def main + def initialize textdomain "network" + end - Yast.import "DNS" - Yast.import "FileUtils" - Yast.import "Installation" - Yast.import "String" - Yast.import "Mode" - Yast.import "Arch" - - Yast.include self, "network/routines.rb" - Yast.include self, "network/complex.rb" - + def main # for update system don't copy network from inst_sys (#325738) - if !Mode.update - save_network - else - Builtins.y2milestone("update - skip save_network") - end + return save_network if !Mode.update + + log.info("update - skip save_network") nil end private - # Updates ifcfg file as needed when the "/" filesystem is accessed over network - # - # @param file [String] ifcfg name - def adjust_for_network_disks(file) - # storage-ng - # Check if installation is targeted to a remote destination. - devicegraph = Y2Storage::StorageManager.instance.staging - is_disk_in_network = devicegraph.filesystem_in_network?("/") - - if !is_disk_in_network - log.info("Root filesystem is not on a network based device") - return - end - - log.info("Root filesystem is on a network based device") - - # tune ifcfg file for remote filesystem - SCR.Execute( - path(".target.bash"), - "/usr/bin/sed -i s/^[[:space:]]*STARTMODE=.*/STARTMODE='nfsroot'/ #{file.shellescape}" - ) - end - - ETC = "/etc".freeze - SYSCONFIG = "/etc/sysconfig/network".freeze - NETWORK_MANAGER = "/etc/NetworkManager".freeze - # Make unit testing possible - ROOT_PATH = "/".freeze - - def CopyConfiguredNetworkFiles - return if Mode.autoinst && !Lan.autoinst.copy_network? - - log.info( - "Copy network configuration files from 1st stage into installed system" - ) - - inst_dir = Installation.destdir - - copy_recipes = [ - { dir: SYSCONFIG, file: "ifcfg-*" }, - { dir: SYSCONFIG, file: "ifroute-*" }, - { dir: SYSCONFIG, file: "routes" }, - { dir: ::File.join(ETC, "wicked"), file: "common.xml" }, - { dir: ETC, file: DNSClass::HOSTNAME_FILE }, - { dir: ETC, file: "hosts" }, - # Copy sysctl file as network writes there ip forwarding (bsc#1159295) - { dir: ::File.join(ETC, "sysctl.d"), file: "70-yast.conf" } - ] - - # just copy files - copy_recipes.each do |recipe| - # can be shell pattern like ifcfg-* - file_pattern = ::File.join(ROOT_PATH, recipe[:dir], recipe[:file]) - copy_to = ::File.join(inst_dir, recipe[:dir]) - log.info("Processing copy recipe #{file_pattern.inspect}") - - Dir.glob(file_pattern).each do |file| - adjust_for_network_disks(file) if file.include?("ifcfg-") - - copy_from = file - - log.info("Copying #{copy_from} to #{copy_to}") - - cmd = "cp #{copy_from.shellescape} #{copy_to.shellescape}" - ret = SCR.Execute(path(".target.bash_output"), cmd) - - log.warn("cmd: '#{cmd}' failed: #{ret}") if ret["exit"] != 0 - end - end - - copy_to = String.Quote(::File.join(inst_dir, SYSCONFIG)) - - # merge files with default installed by sysconfig - ["dhcp", "config"].each do |file| - modified_file = ::File.join(ROOT_PATH, SYSCONFIG, file) - dest_file = ::File.join(copy_to, file) - CFA::GenericSysconfig.merge_files(dest_file, modified_file) - end - # FIXME: proxy - - nil - end - + SYSCTL_PATH = "/etc/sysctl.d/70-yast.conf".freeze # Directory containing udev rules UDEV_RULES_DIR = "/etc/udev/rules.d".freeze + PERSISTENT_RULES = "70-persistent-net.rules".freeze def copy_udev_rules - dest_root = String.Quote(Installation.destdir) - - # Deleting lockfiles and re-triggering udev events for *net is not needed any more - # (#292375 c#18) + files = [PERSISTENT_RULES] + # chzdev creates the rules starting with "41-" + files << "41-*" if Arch.s390 - udev_rules_srcdir = File.join(ROOT_PATH, UDEV_RULES_DIR) - net_srcfile = "70-persistent-net.rules" - - udev_rules_destdir = dest_root + UDEV_RULES_DIR - net_destfile = dest_root + UDEV_RULES_DIR + "/" + net_srcfile - - log.info("udev_rules_destdir #{udev_rules_destdir}") - log.info("net_destfile #{net_destfile}") - - # Do not create udev_rules_destdir if it already exists (in case of update) - # (bug #293366, c#7) - - if !FileUtils.Exists(udev_rules_destdir) - log.info("#{udev_rules_destdir} does not exist yet, creating it") - WFM.Execute( - path(".local.bash"), - "/usr/bin/mkdir -p #{udev_rules_destdir.shellescape}" - ) - else - log.info("File #{udev_rules_destdir} exists") - end - - if Arch.s390 - # chzdev creates the rules starting with "41-" - log.info("Copy S390 specific udev rule files (/etc/udev/rules/41*)") - - WFM.Execute( - path(".local.bash"), - Builtins.sformat( - "/bin/cp -p %1/41-* '%2%3'", - File.join(ROOT_PATH, UDEV_RULES_DIR), - dest_root.shellescape, - UDEV_RULES_DIR - ) - ) - end - - if !Mode.update - log.info("Copying #{net_srcfile} to the installed system ") - WFM.Execute( - path(".local.bash"), - "/bin/cp -p #{udev_rules_srcdir.shellescape}/#{net_srcfile.shellescape} " \ - "#{net_destfile.shellescape}" - ) - else - log.info("Not copying file #{net_destfile} - update mode") - end + copy_to_target(UDEV_RULES_DIR, include: files) nil end - # Copies parts configuration created during installation. + # Run a block in the instsys # - # Copies several config files which should be preserved when installation - # is done. E.g. ifcfg-* files, custom udev rules and so on. - def copy_from_instsys + # @param block [Proc] Block to run in instsys + def on_local(&block) # skip from chroot old_SCR = WFM.SCRGetDefault new_SCR = WFM.SCROpen("chroot=/:scr", false) WFM.SCRSetDefault(new_SCR) - # this has to be done here (out of chroot) bcs: - # 1) udev agent doesn't support SetRoot - # 2) original ifcfg file is copied otherwise too. It doesn't break things itself - # but definitely not looking well ;-) - # TODO: implement support for create udev rules if needed - - # The s390 devices activation was part of the rules handling. - NetworkAutoYast.instance.activate_s390_devices if Mode.autoinst && Arch.s390 - - copy_dhcp_info - copy_udev_rules - CopyConfiguredNetworkFiles() + block.call # close and chroot back WFM.SCRSetDefault(old_SCR) WFM.SCRClose(new_SCR) + end + + # Copies the configuration created during installation to the target system only when it is + # needed + # + # Copies several config files which should be preserved when installation + # is done. E.g. ifcfg-* files, custom udev rules and so on. + def copy_from_instsys + # The backend need to be evaluated inside the chroot due to package installation checking + backend = proposal_backend + on_local do + # The s390 devices activation was part of the rules handling. + NetworkAutoYast.instance.activate_s390_devices if Mode.autoinst && Arch.s390 + + # this has to be done here (out of chroot) bcs: + # 1) udev agent doesn't support SetRoot + # 2) original ifcfg file is copied otherwise too. It doesn't break things itself + # but definitely not looking well ;-) + copy_udev_rules + return if Mode.autoinst && !Lan.autoinst.copy_network? + + log.info("Copy network configuration files from 1st stage into installed system") + copy_dhcp_info + copy_common_files + config_copier_for(backend)&.copy + end nil end - # For copying wicked dhcp files (bsc#1082832) - WICKED_DHCP_PATH = "/var/lib/wicked/".freeze - WICKED_DHCP_FILES = ["duid.xml", "iaid.xml", "lease*.xml"].freeze + # Convenience method to obtain a config copier for the given backend + # + # @param source [Symbol, String] + def config_copier_for(source) + require "y2network/#{source}/config_copier" + + modname = source.to_s.split("_").map(&:capitalize).join + klass = Y2Network.const_get("#{modname}::ConfigCopier") + klass.new + rescue LoadError, NameError => e + log.info("There is no config copier for #{source}. #{e.inspect}") + nil + end + # For copying dhcp-client leases # FIXME: We probably could omit the copy of these leases as we are using # wicked during the installation instead of dhclient. @@ -239,33 +127,15 @@ def copy_from_instsys DHCPV6_PATH = "/var/lib/dhcp6/".freeze DHCP_FILES = ["*.leases"].freeze - # Convenience method for copying dhcp files - def copy_dhcp_info - entries_to_copy = [ - { dir: WICKED_DHCP_PATH, files: WICKED_DHCP_FILES }, - { dir: DHCPV4_PATH, files: DHCP_FILES }, - { dir: DHCPV6_PATH, files: DHCP_FILES } - ] - - entries_to_copy.each { |e| copy_files_to_target(e[:files], e[:dir]) } + def copy_common_files + copy_to_target("/etc", include: ["hosts", DNSClass::HOSTNAME_FILE]) + copy_to_target(SYSCTL_PATH) end - # Convenvenience method for copying a list of files into the target system. - # It takes care of creating the target directory but only if some file - # needs to be copied - # - # @param files [Array] list of short filenames to be copied - # @param path [String] path where the files resides and where will be - # copied in the target system - # @return [Boolean] whether some file was copied - def copy_files_to_target(files, path) - dest_dir = ::File.join(Installation.destdir, path) - glob_files = ::Dir.glob(files.map { |f| File.join(ROOT_PATH, path, f) }) - return false if glob_files.empty? - - ::FileUtils.mkdir_p(dest_dir) - ::FileUtils.cp(glob_files, dest_dir, preserve: true) - true + # Convenience method for copying dhcp files + def copy_dhcp_info + copy_to_target(DHCPV4_PATH, include: DHCP_FILES) + copy_to_target(DHCPV6_PATH, include: DHCP_FILES) end # Creates target's /etc/hosts configuration @@ -304,16 +174,23 @@ def configure_lan configure_hosts end + # Convenience method to check the proposal backend + # + # @see Y2Network::ProposalSettings.instance.network_service + def proposal_backend + Y2Network::ProposalSettings.instance.network_service + end + # Configures NetworkManager # # When running the live installation, it is just a matter of copying # system-connections to the installed system. In a regular installation, # write the settings in the Yast::Lan.yast_config object. def configure_network_manager - return unless Y2Network::ProposalSettings.instance.network_service == :network_manager + return unless proposal_backend == :network_manager if Yast::Lan.system_config.backend&.id == :network_manager - copy_files_to_target(["*"], File.join(NETWORK_MANAGER, "system-connections")) + config_copier_for(:network_manager)&.copy else Yast::Lan.yast_config.backend = :network_manager Yast::Lan.write_config @@ -336,7 +213,8 @@ def configure_target # set proper network service set_network_service - # if portmap running - start it after reboot + # TODO: Still needed? Why the service is not enabled? + # if rpcbind running - start it after reboot (bsc#423026) WFM.Execute( path(".local.bash"), "/sbin/pidofproc rpcbind && /usr/bin/touch /var/lib/YaST2/network_install_rpcbind" @@ -348,7 +226,6 @@ def configure_target # Sets default network service def set_network_service log.info("Setting target system network service") - backend = Y2Network::ProposalSettings.instance.network_service # NetworkServices caches the selected backend. That is, it assumes the # state in the inst-sys and the chroot is the same but that is not true @@ -359,7 +236,7 @@ def set_network_service # running at the same time. (bsc#1202479) NetworkService.send(:disable_service, :wicked) NetworkService.send(:disable_service, :network_manager) - case backend + case proposal_backend when :network_manager log.info("- using NetworkManager") NetworkService.use_network_manager diff --git a/src/lib/y2network/helpers.rb b/src/lib/y2network/helpers.rb new file mode 100644 index 0000000000..9def8521da --- /dev/null +++ b/src/lib/y2network/helpers.rb @@ -0,0 +1,56 @@ +# Copyright (c) [2023] 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 "yast" + +module Y2Network + module Helpers + include Yast::Logger + + ROOT_PATH = "/".freeze + + def inst_dir + Yast::Installation.destdir + end + + # Convenvenience method for copying a list of files into the target system. + # It takes care of creating the target directory but only if some file + # needs to be copied + # + # @param path [String] path where the files resides and where will be + # copied in the target system + # @return [Boolean] whether some file was copied + def copy_to_target(path, include: nil, target: inst_dir) + dest_path = ::File.join(target, path) + files = if include + include.map { |f| File.join(ROOT_PATH, path, f) } + else + File.join(ROOT_PATH, path) + end + glob_files = ::Dir.glob(files) + return false if glob_files.empty? + + log.info("Copying '#{glob_files.join(",")}' to '#{dest_path}'.") + + ::FileUtils.mkdir_p(include ? dest_path : dest_path.dirname) + ::FileUtils.cp(glob_files, dest_path, preserve: true) + true + end + end +end diff --git a/src/lib/y2network/network_manager/config_copier.rb b/src/lib/y2network/network_manager/config_copier.rb new file mode 100644 index 0000000000..be02bfd925 --- /dev/null +++ b/src/lib/y2network/network_manager/config_copier.rb @@ -0,0 +1,35 @@ +# Copyright (c) [2023] 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 "yast" +require "y2network/helpers" + +module Y2Network + module NetworkManager + # This class copies NetworkManager specific configuration to the target system + class ConfigCopier + include Helpers + NETWORK_MANAGER_PATH = "/etc/NetworkManager".freeze + + def copy + copy_to_target(File.join(NETWORK_MANAGER_PATH, "system-connections"), include: ["*"]) + end + end + end +end diff --git a/src/lib/y2network/proposal_settings.rb b/src/lib/y2network/proposal_settings.rb index 5927917131..ec5cee5ea2 100644 --- a/src/lib/y2network/proposal_settings.rb +++ b/src/lib/y2network/proposal_settings.rb @@ -30,11 +30,16 @@ class ProposalSettings include Yast::Logger include Yast::I18n - # @return [Boolean] network service to be used after the installation + # @return [Symbol] network service to be used after the installation (:wicked, :network_manager + # or:none) attr_accessor :selected_backend + # @return [Boolean] attr_accessor :virt_bridge_proposal + # @return [Boolean] attr_accessor :ipv4_forward + # @return [Boolean] attr_accessor :ipv6_forward + # @return [Boolean] attr_accessor :defaults_applied DEFAULTS = [:ipv4_forward, :ipv6_forward].freeze @@ -159,6 +164,8 @@ def virtual_proposal_required? # Propose the network service to be use at the end of the installation # depending on the backend selected during the proposal and the packages # installed + # + # @return [Symbol] :network_manager, :wicked or :none def network_service case current_backend when :network_manager diff --git a/src/lib/y2network/wicked/config_copier.rb b/src/lib/y2network/wicked/config_copier.rb new file mode 100644 index 0000000000..fd2e09f70f --- /dev/null +++ b/src/lib/y2network/wicked/config_copier.rb @@ -0,0 +1,102 @@ +# Copyright (c) [2023] 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 "yast" +require "y2storage" +require "cfa/generic_sysconfig" +require "y2network/helpers" +require "shellwords" + +module Y2Network + module Wicked + # This class copies Wicked specific configuration to the target system + class ConfigCopier + include Yast::Logger + include Y2Network::Helpers + + SYSCONFIG = "/etc/sysconfig/network".freeze + WICKED_PATH = "/etc/wicked".freeze + WICKED_DHCP_PATH = "/var/lib/wicked/".freeze + WICKED_ENTRIES = [ + { dir: SYSCONFIG, files: ["ifcfg-*", "ifroute-*", "routes"] }, + { dir: WICKED_DHCP_PATH, files: ["duid.xml", "iaid.xml", "lease*.xml"] }, + { dir: WICKED_PATH, files: ["common.xml"] } + ].freeze + + def copy + adjust_files_for_network_disks! + WICKED_ENTRIES.each { |e| copy_to_target(e[:dir], include: e[:files]) } + merge_sysconfig_files + end + + private + + # Convenience method for checking if the root filesystem is in network or not + # + # @return [Boolean] true if '/' filesystem is in network; false otherwise + def root_filesystem_in_network? + # storage-ng + # Check if installation is targeted to a remote destination. + devicegraph = Y2Storage::StorageManager.instance.staging + if !devicegraph.filesystem_in_network?("/") + log.info("Root filesystem is not on a network based device") + return false + end + + log.info("Root filesystem is on a network based device") + true + end + + # Sets the startmode of the given file to be 'nfsroot' + # + # @param file [String] ifcfg name + def adjust_startmode!(file) + return unless file.include?("ifcfg-") + + # tune ifcfg file for remote filesystem + Yast::SCR.Execute( + Yast::Path.new(".target.bash"), + "/usr/bin/sed -i s/^[[:space:]]*STARTMODE=.*/STARTMODE='nfsroot'/ #{file.shellescape}" + ) + end + + def adjust_files_for_network_disks! + return unless root_filesystem_in_network? + + file_pattern = ::File.join(ROOT_PATH, SYSCONFIG, "ifcfg-*") + Dir.glob(file_pattern).each { |f| adjust_startmode!(f) } + end + + def merge_sysconfig_files + copy_to = Yast::String.Quote(::File.join(inst_dir, SYSCONFIG)) + + # merge files with default installed by sysconfig + ["dhcp", "config"].each do |file| + modified_file = ::File.join(ROOT_PATH, SYSCONFIG, file) + dest_file = ::File.join(copy_to, file) + if ::File.exist?(dest_file) + CFA::GenericSysconfig.merge_files(dest_file, modified_file) + else + copy_to_target(modified_file) + end + end + end + end + end +end diff --git a/test/data/instsys/etc/hostname b/test/data/instsys/etc/hostname new file mode 100644 index 0000000000..9daeafb986 --- /dev/null +++ b/test/data/instsys/etc/hostname @@ -0,0 +1 @@ +test diff --git a/test/data/instsys/etc/sysconfig/network/ifcfg-enp1s0 b/test/data/instsys/etc/sysconfig/network/ifcfg-enp1s0 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/save_network_test.rb b/test/save_network_test.rb index 129b72f0f0..4ecf0a0234 100755 --- a/test/save_network_test.rb +++ b/test/save_network_test.rb @@ -20,7 +20,6 @@ # find current contact information at www.suse.com. require_relative "test_helper" -require "y2storage" require "yast" require "y2network/config" @@ -29,6 +28,7 @@ require "tmpdir" Yast.import "Installation" +Yast.import "DNS" describe Yast::SaveNetworkClient do describe "#main" do @@ -45,7 +45,7 @@ let(:selected_backend) { :wicked } before do - stub_const("Yast::SaveNetworkClient::ROOT_PATH", scr_root) + stub_const("Y2Network::Helpers::ROOT_PATH", scr_root) allow(Yast::Installation).to receive(:destdir).and_return(destdir) allow(Yast::Package).to receive(:Installed).and_return(false) @@ -75,6 +75,13 @@ FileUtils.remove_entry(destdir) if Dir.exist?(destdir) end + it "copies /etc/hostname and /etc/hosts when exist" do + subject.main + expect(File).to_not exist(File.join(destdir, "etc", "hosts")) + content = File.read(File.join(destdir, "etc", "hostname")) + expect(content).to match(/test/) + end + it "copies wicked and DHCP files under /var/lib" do subject.main expect(File).to exist(File.join(destdir, "var", "lib", "dhcp", "dhclient.leases")) @@ -270,45 +277,4 @@ end end end - - describe "#adjust_for_network_disks" do - let(:template_file) { File.join(SCRStub::DATA_PATH, "ifcfg-eth0.template") } - let(:file) { File.join(SCRStub::DATA_PATH, "ifcfg-eth0") } - - around do |example| - ::FileUtils.cp(template_file, file) - example.run - ::FileUtils.rm(file) - end - - before do - Y2Storage::StorageManager.create_test_instance - - staging = Y2Storage::StorageManager.instance.staging - allow(staging).to receive(:filesystem_in_network?).with("/").and_return(in_network) - allow(subject).to receive(:save_network) - # Mainly for import - subject.main - end - - context "when the root filesystem of the target system is in a network device" do - let(:in_network) { true } - - it "tunes ifcfg file for remote filesystem" do - expect(Yast::SCR).to receive(:Execute).with(anything, /nfsroot/).once - subject.send(:adjust_for_network_disks, file) - expect(::File.read(file)).to include("STARTMODE=nfsroot") - end - end - - context "when the root filesystem of the target system is in a local device" do - let(:in_network) { false } - - it "does not touch any configuration file" do - expect(Yast::SCR).to_not receive(:Execute).with(anything, /nfsroot/) - subject.send(:adjust_for_network_disks, file) - expect(::File.read(file)).to eq(::File.read(template_file)) - end - end - end end diff --git a/test/y2network/wicked/config_copier_test.rb b/test/y2network/wicked/config_copier_test.rb new file mode 100644 index 0000000000..b0423543fb --- /dev/null +++ b/test/y2network/wicked/config_copier_test.rb @@ -0,0 +1,95 @@ +# Copyright (c) [2019] 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_relative "../../test_helper" +require "y2network/wicked/config_copier" + +describe Y2Network::Wicked::ConfigCopier do + let(:destdir) { Dir.mktmpdir } + let(:sysconfig) { described_class::SYSCONFIG } + let(:destdir_sysconfig) { File.join(destdir, sysconfig) } + let(:scr_root) { File.join(DATA_PATH, "instsys") } + + before do + stub_const("Y2Network::Helpers::ROOT_PATH", scr_root) + allow(Yast::Installation).to receive(:destdir).and_return(destdir) + end + + after do + FileUtils.remove_entry(destdir) if Dir.exist?(destdir) + end + + describe "#copy" do + let(:template_file) { File.join(SCRStub::DATA_PATH, "ifcfg-eth0.template") } + let(:file) { File.join(scr_root, sysconfig, "ifcfg-eth0") } + + around do |example| + ::FileUtils.cp(template_file, file) + example.run + ::FileUtils.rm(file) + end + + it "copies wicked DHCP files under /var/lib/wicked" do + subject.copy + expect(File).to exist(File.join(destdir, "var", "lib", "wicked", "lease.xml")) + end + + it "copies sysconfig network files under /etc/sysconfig/network dir" do + subject.copy + expect(File).to exist(File.join(destdir, sysconfig, "ifcfg-eth0")) + end + end + + describe "#adjust_files_for_network_disks!" do + let(:template_file) { File.join(SCRStub::DATA_PATH, "ifcfg-eth0.template") } + let(:file) { File.join(scr_root, sysconfig, "ifcfg-eth0") } + + around do |example| + ::FileUtils.cp(template_file, file) + example.run + ::FileUtils.rm(file) + end + + before do + Y2Storage::StorageManager.create_test_instance + + staging = Y2Storage::StorageManager.instance.staging + allow(staging).to receive(:filesystem_in_network?).with("/").and_return(in_network) + end + + context "when the root filesystem of the target system is in a network device" do + let(:in_network) { true } + + it "tunes ifcfg file for remote filesystem" do + expect(Yast::SCR).to receive(:Execute).with(anything, /nfsroot/).once + subject.send(:adjust_files_for_network_disks!) + expect(::File.read(file)).to include("STARTMODE=nfsroot") + end + end + + context "when the root filesystem of the target system is in a local device" do + let(:in_network) { false } + + it "does not touch any configuration file" do + expect(Yast::SCR).to_not receive(:Execute).with(anything, /nfsroot/) + subject.send(:adjust_files_for_network_disks!) + expect(::File.read(file)).to eq(::File.read(template_file)) + end + end + end +end