Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move network configuration to the 1st stage by default #606

Merged
merged 7 commits into from May 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions package/autoyast2.changes
@@ -1,3 +1,10 @@
-------------------------------------------------------------------
Fri May 22 09:58:24 UTC 2020 - Knut Anderssen <kanderssen@suse.com>

- The network configuration is applied during the first stage by
default (bsc#1171922)
- 4.3.4

-------------------------------------------------------------------
Thu May 21 13:51:22 UTC 2020 - David Díaz <dgonzalez@suse.com>

Expand Down
2 changes: 1 addition & 1 deletion package/autoyast2.spec
Expand Up @@ -22,7 +22,7 @@
%endif

Name: autoyast2
Version: 4.3.3
Version: 4.3.4
Release: 0
Summary: YaST2 - Automated Installation
License: GPL-2.0-only
Expand Down
63 changes: 0 additions & 63 deletions src/clients/inst_autoconfigure.rb
Expand Up @@ -128,21 +128,6 @@ def main
Ops.get_string(d, "res", "")
end)

# keep network on AutoYaST ugprade
if !Mode.autoupgrade
if !Builtins.haskey(Profile.current, "networking")
removeNetwork([]) # no networking section -> no network
elsif Ops.get_boolean(
Profile.current,
["networking", "keep_install_network"],
true
) == false
removeNetwork(
Ops.get_list(Profile.current, ["networking", "interfaces"], [])
) # networking section without keeping the install network
end
end

Builtins.foreach(@deps) do |r|
p = Ops.get_string(r, "res", "")
d = Ops.get_map(r, "data", {})
Expand Down Expand Up @@ -417,54 +402,6 @@ def MatchInterface(id)
ret
end

def removeNetwork(ilist)
ilist = deep_copy(ilist)
Yast.import "NetworkInterfaces"
Builtins.y2milestone("removeNetwork ifaces:%1", ilist)
ilist = Builtins.maplist(ilist) do |i|
if Builtins.substring(Ops.get_string(i, "device", ""), 0, 7) == "eth-id-"
Ops.set(i, "device", MatchInterface(Ops.get_string(i, "device", "")))
end
deep_copy(i)
end
Builtins.y2milestone("removeNetwork ifaces:%1", ilist)
l = SCR.Read(path(".target.dir"), ["/etc/sysconfig/network", []])
netlist = []
Builtins.y2milestone("removeNetwork list:%1", l)
Builtins.foreach(
Convert.convert(l, from: "any", to: "list <string>")
) do |s|
if Builtins.issubstring(s, "ifcfg-") &&
!Builtins.issubstring(s, "ifcfg-lo")
if Builtins.substring(s, 0, 6) == "ifcfg-" && s != "ifcfg-lo"
net = Builtins.substring(s, 6)
tmp = Builtins.filter(ilist) do |l2|
Ops.get_string(l2, "device", "") == net
end
if Builtins.isempty(tmp)
Builtins.y2milestone("removeNetwork net:%1", net)
NetworkInterfaces.Delete(net)
netlist = Builtins.add(netlist, net)
Builtins.y2milestone(
"removing installation network: /etc/sysconfig/network/%1",
s
)
SCR.Execute(
path(".target.remove"),
Builtins.sformat("/etc/sysconfig/network/%1", s)
)
end
end
end
end
Builtins.y2milestone("removeNetwork netlist:%1", netlist)
if !Builtins.isempty(netlist)
NetworkInterfaces.Commit
# NetworkInterfaces::Write( ".*" );
end
nil
end

def processWait(resource, stage)
Builtins.foreach(
Ops.get_list(Profile.current, ["general", "wait", stage], [])
Expand Down
39 changes: 1 addition & 38 deletions src/clients/inst_autosetup.rb
Expand Up @@ -165,44 +165,7 @@ def main
)
AutoinstGeneral.Write

AutoinstConfig.network_before_proposal = false
general_section = Profile.current["general"] || {}
semiauto_network = general_section["semi-automatic"]&.include?("networking")

if Profile.current["networking"] &&
(Profile.current["networking"]["setup_before_proposal"] ||
semiauto_network ||
!AutoinstConfig.second_stage
)
if Profile.current["networking"]["setup_before_proposal"]
Builtins.y2milestone("Networking setup before the proposal")
AutoinstConfig.network_before_proposal = true
elsif !AutoinstConfig.second_stage
# Second stage of installation will not be called but a
# network configuration is available. So this will be written
# during the general inst_finish process at the end of the
# first stage. But for the installation workflow the linuxrc
# network settings will be taken. (bnc#944942)
Builtins.y2milestone(
"Networking setup at the end of first installation stage"
)
end
Builtins.y2milestone(
"Importing Network settings from configuration file"
)
Call.Function(
"lan_auto",
["Import", Ops.get_map(Profile.current, "networking", {})]
)
end

if semiauto_network
Builtins.y2milestone("Networking manual setup before proposal")
Call.Function("inst_lan", ["enable_next" => true])
AutoinstConfig.network_before_proposal = true
end

Call.Function("lan_auto", ["Write"]) if AutoinstConfig.network_before_proposal
autosetup_network

if Builtins.haskey(Profile.current, "add-on")
Progress.Title(_("Handling Add-On Products..."))
Expand Down
62 changes: 60 additions & 2 deletions src/lib/autoinstall/autosetup_helpers.rb
Expand Up @@ -81,7 +81,6 @@ def modified_profile?
def suse_register
return true unless registration_module_available? # do nothing

general_section = Yast::Profile.current["general"] || {}
# autoupgrade detects itself if system is registered and if needed do migration via scc
if Yast::Profile.current[REGISTER_SECTION] || Yast::Mode.autoupgrade
Yast::WFM.CallFunction(
Expand All @@ -98,12 +97,71 @@ def suse_register

# failed relnotes download is not fatal, ignore ret code
Yast::WFM.CallFunction("inst_download_release_notes")
elsif general_section["semi-automatic"]&.include?("scc")
elsif semi_auto?("scc")
Yast::WFM.CallFunction("inst_scc", ["enable_next" => true])
end
true
end

# Convenience method to fetch the general profile section
#
# @return [Hash] the general section from the current profile when present;
# an empty hash when not
def general_section
Yast::Profile.current["general"] || {}
end

# Convenienve method to check whether a particular client should be run to
# be configured manually during the autoinstallation according to the
# semi-automatic section
#
# @return [Boolean]
def semi_auto?(name)
!!general_section["semi-automatic"]&.include?(name)
end

# Autosetup the network
def autosetup_network
@network_before_proposal = false

if Yast::Profile.current["networking"]
if Yast::Profile.current["networking"]["setup_before_proposal"]
log.info("Networking setup before the proposal")
@network_before_proposal = true
else
log.info("Networking setup at the end of first installation stage")
end

log.info("Importing Network settings from configuration file")
Yast::WFM.CallFunction("lan_auto", ["Import", Yast::Profile.current["networking"]])
Yast::Profile.remove_sections("networking")

# Import also the host section in order to resolve hosts only available
# with the network configuration and the host entry
if Yast::Profile.current["host"] && network_before_proposal?
Yast::WFM.CallFunction("host_auto", ["Import", Yast::Profile.current["host"]])
Yast::Profile.remove_sections("host")
end
end

if semi_auto?("networking")
log.info("Networking manual setup before proposal")
Yast::WFM.CallFunction("inst_lan", ["enable_next" => true])
@network_before_proposal = true
end

Yast::WFM.CallFunction("lan_auto", ["Write"]) if network_before_proposal?
end

# Convenience method to check whether the network configuration should be
# written before the proposal
#
# @return [Boolean] true when network config should be written before the
# proposal; false when not
def network_before_proposal?
!!@network_before_proposal
end

private

# Backup AutoYaST profile
Expand Down
5 changes: 5 additions & 0 deletions src/lib/autoinstall/clients/inst_autoinit.rb
Expand Up @@ -76,6 +76,11 @@ def run

Yast::Progress.Finish

# TODO: In case that a specific network configuration is needed and
# defined in the profile, with the online media, this configuration
# will not be available. Maybe we should configure the network at this
# point

# when installing from the online installation medium we need to
# register the system earlier because the medium does not contain any
# repositories, we need the repositories from the registration server
Expand Down
4 changes: 0 additions & 4 deletions src/modules/AutoinstConfig.rb
Expand Up @@ -154,9 +154,6 @@ def main
# Running autoyast second_stage
@second_stage = true

# Network is configured during the first stage before the proposal
@network_before_proposal = false

@OriginalURI = ""

@message = ""
Expand Down Expand Up @@ -569,7 +566,6 @@ def profile_backup_path
publish variable: :Confirm, type: "boolean"
publish variable: :cio_ignore, type: "boolean"
publish variable: :second_stage, type: "boolean"
publish variable: :network_before_proposal, type: "boolean"
publish variable: :OriginalURI, type: "string"
publish variable: :message, type: "string"
publish variable: :dontmerge, type: "list <string>"
Expand Down
125 changes: 125 additions & 0 deletions test/lib/autosetup_helpers_test.rb
Expand Up @@ -218,5 +218,130 @@ class DummyClient < Yast::Client
expect(client.modified_profile?).to eq(false)
end
end

end

describe "#network_autosetup" do
let(:profile) { networking_section }
let(:networking_section) { { "networking" => { "setup_before_proposal" => true } } }
let(:host_section) { { "host" => { "hosts" => [] } } }

before do
Yast::Profile.current = profile
Yast::AutoinstConfig.main
allow(Yast::WFM).to receive(:CallFunction).with("lan_auto", anything)
allow(Yast::WFM).to receive(:CallFunction).with("inst_lan", anything)
allow(Yast::WFM).to receive(:CallFunction).with("host_auto", anything)
end

context "when a networking section is defined in the profile" do
it "imports the networking config" do
expect(Yast::WFM)
.to receive(:CallFunction)
.with("lan_auto", ["Import", profile["networking"]])

client.autosetup_network
end

it "removes the networking section from the profile" do
client.autosetup_network
expect(Yast::Profile.current.keys).to_not include("networking")
end

context "and the setup is defined to be run before the proposal" do
let(:profile) { networking_section.merge(host_section) }
let(:networking_section) { { "networking" => { "setup_before_proposal" => true } } }

it "sets the network config to be written before the proposal" do
expect { client.autosetup_network }
.to change { client.network_before_proposal? }
.from(false).to(true)
end

context "and a host section is defined" do
it "imports the /etc/hosts config from the profile" do
expect(Yast::WFM)
.to receive(:CallFunction)
.with("host_auto", ["Import", profile["host"]])

client.autosetup_network
end

it "removes the host section from the profile" do
client.autosetup_network
expect(Yast::Profile.current.keys).to_not include("host")
end
end
end
end

context "when the network configuration is semiautomatic" do
let(:networking_section) { { "general" => { "semi-automatic" => ["networking"] } } }

it "runs the network configuration client" do
expect(Yast::WFM).to receive(:CallFunction).with("inst_lan", anything)

client.autosetup_network
end

it "sets the network config to be written before the proposal" do
expect { client.autosetup_network }
.to change { client.network_before_proposal? }
.from(false).to(true)
end
end

context "in case it was definitely se to be configured before the proposal" do
before do
allow(client).to receive(:network_before_proposal?).and_return(true)
end
it "writes the network configuration calling the auto client" do
expect(Yast::WFM).to receive(:CallFunction).with("lan_auto", ["Write"])

client.autosetup_network
end
end
end

describe "#general_section" do
let(:profile) { general_section }
let(:general_section) { { "general" => { "semi-automatic" => ["networking"] } } }
let(:register_section) { { "suse_register" => { "reg_code" => "12345" } } }

before do
Yast::Profile.current = profile
end

context "when the profile contains the general section" do
it "returns it" do
expect(client.general_section).to eql(general_section["general"])
end
end

context "when the profile does not contain the general section" do
let(:profile) { register_section }
it "returns and empty hash" do
expect(client.general_section).to eql({})
end
end
end

describe "#semi_auto?" do
let(:profile) { general_section }
let(:general_section) { { "general" => { "semi-automatic" => ["networking"] } } }

before do
Yast::Profile.current = profile
end

context "given a module name" do
it "returns true if the module is part ot the profile semi-automatic list" do
expect(client.semi_auto?("networking")).to eql(true)
end

it "returns false otherwise" do
expect(client.semi_auto?("partitioning")).to eql(false)
end
end
end
end