Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions service/lib/agama/network.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,33 @@ def install
ProxySetup.instance.install
end

def link_resolv
return unless File.exist?(RESOLV)

link = File.join(Yast::Installation.destdir, RESOLV)
target = File.join(RUN_NM_DIR, File.basename(RESOLV))

return if File.exist?(link)

FileUtils.touch RESOLV_FLAG
FileUtils.ln_s target, link
end

def unlink_resolv
return unless File.exist?(RESOLV_FLAG)

link = File.join(Yast::Installation.destdir, RESOLV)
FileUtils.rm_f link
FileUtils.rm_f RESOLV_FLAG
end

private

# @return [Logger]
attr_reader :logger

RESOLV = "/etc/resolv.conf"
RESOLV_FLAG = "/run/agama/manage_resolv"
ETC_NM_DIR = "/etc/NetworkManager"
RUN_NM_DIR = "/run/NetworkManager"
private_constant :ETC_NM_DIR
Expand Down
9 changes: 8 additions & 1 deletion service/lib/agama/storage/finisher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
require "agama/with_progress"
require "agama/helpers"
require "agama/http"
require "agama/network"
require "abstract_method"
require "fileutils"

Expand Down Expand Up @@ -261,9 +262,15 @@ def run

# Run the post scripts
def run_post_scripts
require "agama/http"
network.link_resolv
client = Agama::HTTP::Clients::Scripts.new
client.run("post")
ensure
network.unlink_resolv
end

def network
@network ||= Agama::Network.new(logger)
end

# Enables the agama-scripts service to run init scripts
Expand Down
7 changes: 7 additions & 0 deletions service/package/rubygem-agama-yast.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
-------------------------------------------------------------------
Thu Mar 20 08:41:23 UTC 2025 - Knut Anderssen <kanderssen@suse.com>

- Symlink the /mnt/etc/resolv.conf to the NetworkManager running
one in order to have DNS resolution in the chroot post scripts
(bsc#1235617, gh#agama-project/agama#2179).

-------------------------------------------------------------------
Fri Mar 14 12:34:03 UTC 2025 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

Expand Down
86 changes: 80 additions & 6 deletions service/test/agama/network_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,29 @@
subject(:network) { described_class.new(logger) }

let(:logger) { Logger.new($stdout, level: :warn) }
let(:targetdir) { File.join(rootdir, "mnt") }

before do
allow(Yast::Installation).to receive(:destdir).and_return(targetdir)
end

after do
FileUtils.remove_entry(rootdir)
end

describe "#install" do
let(:rootdir) { Dir.mktmpdir }

let(:etcdir) do
File.join(rootdir, "etc", "NetworkManager", "system-connections")
end
let(:targetdir) { File.join(rootdir, "mnt") }
let(:service) { instance_double(Yast2::Systemd::Service, enable: nil) }

before do
allow(Yast::Installation).to receive(:destdir).and_return(targetdir)
allow(Yast2::Systemd::Service).to receive(:find).with("NetworkManager").and_return(service)
stub_const("Agama::Network::ETC_NM_DIR", etcdir)
end

after do
FileUtils.remove_entry(rootdir)
end

context "when NetworkManager configuration files are present" do
before do
FileUtils.mkdir_p(File.join(etcdir, "system-connections"))
Expand Down Expand Up @@ -95,4 +99,74 @@
end
end
end

describe "#link_resolv" do
let(:rootdir) { Dir.mktmpdir }

let(:fixtures) { File.join(FIXTURES_PATH, "root_dir") }
let(:resolv_fixture) { File.join(FIXTURES_PATH, "etc", "resolv.conf") }
let(:resolv_flag) { File.join(rootdir, "run", "agama", "manage_resolv") }
let(:resolv) { File.join(targetdir, "etc", "resolv.conf") }

before do
stub_const("Agama::Network::RESOLV_FLAG", resolv_flag)
stub_const("Agama::Network::RUN_NM_DIR", File.join(rootdir, "run", "NetworkManager"))
FileUtils.mkdir_p targetdir
FileUtils.cp_r(Dir["#{fixtures}/*"], rootdir)
FileUtils.cp_r(Dir["#{fixtures}/*"], targetdir)
end

context "when the /etc/resolv.conf exists in the installation destdir" do
before do
FileUtils.mkdir_p File.join(targetdir, "etc")
FileUtils.touch File.join(targetdir, "etc", "resolv.conf")
end

it "does nothing" do
expect(FileUtils).to_not receive(:ln_s)
network.link_resolv
end
end

context "when there is no /etc/resolv.conf in the installation destdir" do
it "symlinks it to /run/NetworkManager/resolv.conf" do
network.link_resolv
expect(File.exist?(resolv)).to eql(true)
expect(File.symlink?(resolv)).to eql(true)
end

it "creates a flag indicating that the resolv.conf is managed by Agama" do
network.link_resolv
expect(File.exist?(resolv_flag)).to eql(true)
end
end
end

describe "#unlink_resolv" do
let(:rootdir) { Dir.mktmpdir }

let(:fixtures) { File.join(FIXTURES_PATH, "root_dir") }
let(:resolv_fixture) { File.join(FIXTURES_PATH, "etc", "resolv.conf") }
let(:resolv_flag) { File.join(rootdir, "run", "agama", "manage_resolv") }
let(:resolv) { File.join(targetdir, "etc", "resolv.conf") }

before do
stub_const("Agama::Network::RESOLV_FLAG", resolv_flag)
stub_const("Agama::Network::RUN_NM_DIR", File.join(rootdir, "run", "NetworkManager"))
FileUtils.mkdir_p targetdir
FileUtils.cp_r(Dir["#{fixtures}/*"], rootdir)
FileUtils.cp_r(Dir["#{fixtures}/*"], targetdir)
end

context "when the /etc/resolv.conf was marked as managed by Agama" do
it "removes the /etc/resolv.con symlink from the installation destdir" do
network.link_resolv
expect(File.exist?(resolv_flag)).to eql(true)
expect(File.symlink?(resolv)).to eql(true)
network.unlink_resolv
expect(File.exist?(resolv)).to eql(false)
expect(File.exist?(resolv_flag)).to eql(false)
end
end
end
end
9 changes: 7 additions & 2 deletions service/test/agama/storage/manager_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
require_relative "../../test_helper"
require_relative "../with_progress_examples"
require_relative "../with_issues_examples"
require_relative "./storage_helpers"
require_relative "storage_helpers"
require "agama/dbus/clients/questions"
require "agama/config"
require "agama/http"
Expand Down Expand Up @@ -59,6 +59,7 @@
# mock writting config as proposal call can do storage probing, which fails in CI
allow_any_instance_of(Agama::Storage::Bootloader).to receive(:write_config)
allow(Agama::HTTP::Clients::Scripts).to receive(:new).and_return(scripts_client)
allow(Agama::Network).to receive(:new).and_return(network)
allow(Yast::Installation).to receive(:destdir).and_return(File.join(tmp_dir, "mnt"))
stub_const("Agama::Storage::Finisher::CopyLogsStep::SCRIPTS_DIR",
File.join(tmp_dir, "run", "agama", "scripts"))
Expand All @@ -73,6 +74,7 @@
let(:software) do
instance_double(Agama::DBus::Clients::Software, selected_product: "ALP")
end
let(:network) { instance_double(Agama::Network, link_resolv: nil, unlink_resolv: nil) }
let(:bootloader_finish) { instance_double(Bootloader::FinishClient, write: nil) }
let(:security) { instance_double(Agama::Security, probe: nil, write: nil) }

Expand Down Expand Up @@ -378,13 +380,16 @@
let(:devicegraph) { "staging-plain-partitions.yaml" }

it "copy needed files, installs the bootloader, sets up the snapshots, " \
"copy logs, runs the post-installation scripts, and umounts the file systems" do
"copy logs, symlink resolv.conf, runs the post-installation scripts, " \
"unlink resolv.conf, and umounts the file systems" do
expect(security).to receive(:write)
expect(copy_files).to receive(:run)
expect(bootloader_finish).to receive(:write)
expect(Yast::WFM).to receive(:CallFunction).with("storage_finish", ["Write"])
expect(Yast::WFM).to receive(:CallFunction).with("snapshots_finish", ["Write"])
expect(network).to receive(:link_resolv)
Comment thread
dgdavid marked this conversation as resolved.
expect(scripts_client).to receive(:run).with("post")
expect(network).to receive(:unlink_resolv)
expect(Yast::Execute).to receive(:on_target!)
.with("systemctl", "enable", "agama-scripts", allowed_exitstatus: [0, 1])
expect(Yast::WFM).to receive(:CallFunction).with("umount_finish", ["Write"])
Expand Down
3 changes: 3 additions & 0 deletions service/test/fixtures/root_dir/run/NetworkManager/resolv.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Generated by NetworkManager
search default
nameserver 192.168.100.1