From fcd1aee9bb20bf775bb58ab4972677577b88644c Mon Sep 17 00:00:00 2001 From: Chris Roberts Date: Wed, 30 Aug 2017 16:59:46 -0700 Subject: [PATCH] Update linux host NFS capability Add support for systemd detection and using correct method for starting/checking host nfs service. --- lib/vagrant/util/guest_inspection.rb | 2 +- lib/vagrant/util/platform.rb | 13 ++++++ plugins/hosts/gentoo/cap/nfs.rb | 19 +++----- plugins/hosts/linux/cap/nfs.rb | 29 +++++++++---- plugins/hosts/redhat/cap/nfs.rb | 12 +++++- test/unit/plugins/hosts/linux/cap/nfs_test.rb | 43 ++++++++++++++++++- test/unit/vagrant/util/platform_test.rb | 23 ++++++++++ 7 files changed, 115 insertions(+), 26 deletions(-) diff --git a/lib/vagrant/util/guest_inspection.rb b/lib/vagrant/util/guest_inspection.rb index fdfc1a632..033bb3e97 100644 --- a/lib/vagrant/util/guest_inspection.rb +++ b/lib/vagrant/util/guest_inspection.rb @@ -8,7 +8,7 @@ module Vagrant ## systemd helpers - # systemd is in used + # systemd is in use # # @return [Boolean] def systemd?(comm) diff --git a/lib/vagrant/util/platform.rb b/lib/vagrant/util/platform.rb index 2fbcac838..778f3a7ab 100644 --- a/lib/vagrant/util/platform.rb +++ b/lib/vagrant/util/platform.rb @@ -448,6 +448,19 @@ module Vagrant end end + # systemd is in use + def systemd? + if !defined?(@_systemd) + if !windows? + result = Vagrant::Util::Subprocess.execute("ps", "-o", "comm=", "1") + @_systemd = result.stdout.chomp == "systemd" + else + @_systemd = false + end + end + @_systemd + end + # @private # Reset the cached values for platform. This is not considered a public # API and should only be used for testing. diff --git a/plugins/hosts/gentoo/cap/nfs.rb b/plugins/hosts/gentoo/cap/nfs.rb index 995e9b43c..bc4902206 100644 --- a/plugins/hosts/gentoo/cap/nfs.rb +++ b/plugins/hosts/gentoo/cap/nfs.rb @@ -6,30 +6,23 @@ module VagrantPlugins module Cap class NFS def self.nfs_check_command(env) - if systemd? - return "#{systemctl_path} status --no-pager nfs-server.service" + if Vagrant::Util::Platform.systemd? + "#{systemctl_path} status --no-pager nfs-server.service" else - return "/etc/init.d/nfs status" + "/etc/init.d/nfs status" end end def self.nfs_start_command(env) - if systemd? - return "#{systemctl_path} start rpcbind nfs-server.service" + if Vagrant::Util::Platform.systemd? + "#{systemctl_path} start rpcbind nfs-server.service" else - return "/etc/init.d/nfs restart" + "/etc/init.d/nfs restart" end end protected - # This tests to see if systemd is used on the system. This is used - # in newer versions of Arch, and requires a change in behavior. - def self.systemd? - result = Vagrant::Util::Subprocess.execute("ps", "-o", "comm=", "1") - return result.stdout.chomp == "systemd" - end - def self.systemctl_path path = Vagrant::Util::Which.which("systemctl") return path if path diff --git a/plugins/hosts/linux/cap/nfs.rb b/plugins/hosts/linux/cap/nfs.rb index 45701f02b..c4743c774 100644 --- a/plugins/hosts/linux/cap/nfs.rb +++ b/plugins/hosts/linux/cap/nfs.rb @@ -1,3 +1,4 @@ +require "shellwords" require "vagrant/util" require "vagrant/util/shell_quote" require "vagrant/util/retryable" @@ -15,11 +16,19 @@ module VagrantPlugins end def self.nfs_check_command(env) - "/etc/init.d/nfs-kernel-server status" + if Vagrant::Util::Platform.systemd? + "systemctl status --no-pager nfs-server.service" + else + "/etc/init.d/nfs-kernel-server status" + end end def self.nfs_start_command(env) - "/etc/init.d/nfs-kernel-server start" + if Vagrant::Util::Platform.systemd? + "systemctl start nfs-server.service" + else + "/etc/init.d/nfs-kernel-server start" + end end def self.nfs_export(env, ui, id, ips, folders) @@ -44,16 +53,20 @@ module VagrantPlugins nfs_write_exports(output) if nfs_running?(nfs_check_command) - system("sudo #{nfs_apply_command}") + Vagrant::Util::Subprocess.execute("sudo", *Shellwords.split(nfs_apply_command)).exit_code == 0 else - system("sudo #{nfs_start_command}") + Vagrant::Util::Subprocess.execute("sudo", *Shellwords.split(nfs_start_command)).exit_code == 0 end end def self.nfs_installed(environment) - retryable(tries: 10, on: TypeError) do - # Check procfs to see if NFSd is a supported filesystem - system("cat /proc/filesystems | grep nfsd > /dev/null 2>&1") + if Vagrant::Util::Platform.systemd? + Vagrant::Util::Subprocess.execute("/bin/sh", "-c", + "systemctl --no-pager --no-legend --plain list-unit-files --all --type=service " \ + "| grep nfs-server.service").exit_code == 0 + else + Vagrant::Util::Subprocess.execute("modinfo", "nfsd").exit_code == 0 || + Vagrant::Util::Subprocess.execute("grep", "nfsd", "/proc/filesystems").exit_code == 0 end end @@ -218,7 +231,7 @@ module VagrantPlugins end def self.nfs_running?(check_command) - system(check_command) + Vagrant::Util::Subprocess.execute(*Shellwords.split(check_command)).exit_code == 0 end end end diff --git a/plugins/hosts/redhat/cap/nfs.rb b/plugins/hosts/redhat/cap/nfs.rb index edcabe21c..8bc4e5411 100644 --- a/plugins/hosts/redhat/cap/nfs.rb +++ b/plugins/hosts/redhat/cap/nfs.rb @@ -5,11 +5,19 @@ module VagrantPlugins module Cap class NFS def self.nfs_check_command(env) - "#{nfs_server_binary} status" + if Vagrant::Util::Platform.systemd? + "systemctl status --no-pager nfs-server.service" + else + "#{nfs_server_binary} status" + end end def self.nfs_start_command(env) - "#{nfs_server_binary} start" + if Vagrant::Util::Platform.systemd? + "systemctl start nfs-server.service" + else + "#{nfs_server_binary} start" + end end protected diff --git a/test/unit/plugins/hosts/linux/cap/nfs_test.rb b/test/unit/plugins/hosts/linux/cap/nfs_test.rb index 557a470d5..bb8ca9079 100644 --- a/test/unit/plugins/hosts/linux/cap/nfs_test.rb +++ b/test/unit/plugins/hosts/linux/cap/nfs_test.rb @@ -33,6 +33,44 @@ describe VagrantPlugins::HostLinux::Cap::NFS do @tmp_exports = nil end + describe ".nfs_check_command" do + let(:cap){ caps.get(:nfs_check_command) } + + context "without systemd" do + before{ expect(Vagrant::Util::Platform).to receive(:systemd?).and_return(false) } + + it "should use init.d script" do + expect(cap.nfs_check_command(env)).to include("init.d") + end + end + context "with systemd" do + before{ expect(Vagrant::Util::Platform).to receive(:systemd?).and_return(true) } + + it "should use systemctl" do + expect(cap.nfs_check_command(env)).to include("systemctl") + end + end + end + + describe ".nfs_start_command" do + let(:cap){ caps.get(:nfs_start_command) } + + context "without systemd" do + before{ expect(Vagrant::Util::Platform).to receive(:systemd?).and_return(false) } + + it "should use init.d script" do + expect(cap.nfs_start_command(env)).to include("init.d") + end + end + context "with systemd" do + before{ expect(Vagrant::Util::Platform).to receive(:systemd?).and_return(true) } + + it "should use systemctl" do + expect(cap.nfs_start_command(env)).to include("systemctl") + end + end + end + describe ".nfs_export" do let(:cap){ caps.get(:nfs_export) } @@ -43,8 +81,9 @@ describe VagrantPlugins::HostLinux::Cap::NFS do allow(host).to receive(:capability).with(:nfs_check_command).and_return("/bin/true") allow(host).to receive(:capability).with(:nfs_start_command).and_return("/bin/true") allow(ui).to receive(:info) - allow(cap).to receive(:system).with("sudo /bin/true").and_return(true) - allow(cap).to receive(:system).with("/bin/true").and_return(true) + allow(Vagrant::Util::Subprocess).to receive(:execute).and_call_original + allow(Vagrant::Util::Subprocess).to receive(:execute).with("sudo", "/bin/true").and_return(double(:result, exit_code: 0)) + allow(Vagrant::Util::Subprocess).to receive(:execute).with("/bin/true").and_return(double(:result, exit_code: 0)) end it "should export new entries" do diff --git a/test/unit/vagrant/util/platform_test.rb b/test/unit/vagrant/util/platform_test.rb index 28511b2a1..b97f11ff9 100644 --- a/test/unit/vagrant/util/platform_test.rb +++ b/test/unit/vagrant/util/platform_test.rb @@ -133,4 +133,27 @@ describe Vagrant::Util::Platform do end end end + + describe ".systemd?" do + before{ allow(subject).to receive(:windows?).and_return(false) } + after{ subject.reset! } + + context "on windows" do + before{ expect(subject).to receive(:windows?).and_return(true) } + + it "should return false" do + expect(subject.systemd?).to be_falsey + end + end + + it "should return true if systemd is in use" do + expect(Vagrant::Util::Subprocess).to receive(:execute).and_return(double(:result, stdout: "systemd")) + expect(subject.systemd?).to be_truthy + end + + it "should return false if systemd is not in use" do + expect(Vagrant::Util::Subprocess).to receive(:execute).and_return(double(:result, stdout: "other")) + expect(subject.systemd?).to be_falsey + end + end end