diff --git a/lib/vagrant/action/builtin/graceful_halt.rb b/lib/vagrant/action/builtin/graceful_halt.rb index 832695ff4..da1235551 100644 --- a/lib/vagrant/action/builtin/graceful_halt.rb +++ b/lib/vagrant/action/builtin/graceful_halt.rb @@ -44,7 +44,7 @@ module Vagrant # checked above. if graceful env[:ui].info I18n.t("vagrant.actions.vm.halt.graceful") - env[:machine].guest.halt + env[:machine].guest.capability(:halt) @logger.debug("Waiting for target graceful halt state: #{@target_state}") count = 0 diff --git a/lib/vagrant/action/builtin/nfs.rb b/lib/vagrant/action/builtin/nfs.rb index 364233668..05ec94bc1 100644 --- a/lib/vagrant/action/builtin/nfs.rb +++ b/lib/vagrant/action/builtin/nfs.rb @@ -78,7 +78,8 @@ module Vagrant end # Mount them! - env[:machine].guest.mount_nfs(env[:nfs_host_ip], mount_folders) + env[:machine].guest.capability( + :mount_nfs, env[:nfs_host_ip], mount_folders) end end diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index 4c7c151ea..d37695f31 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -243,6 +243,10 @@ module Vagrant error_key(:linux_mount_failed) end + class LinuxNFSMountFailed < VagrantError + error_key(:linux_nfs_mount_failed) + end + class LinuxShellExpandFailed < VagrantError error_key(:linux_shell_expand_failed) end diff --git a/plugins/guests/linux/cap/halt.rb b/plugins/guests/linux/cap/halt.rb new file mode 100644 index 000000000..6125a2082 --- /dev/null +++ b/plugins/guests/linux/cap/halt.rb @@ -0,0 +1,16 @@ +module VagrantPlugins + module GuestLinux + module Cap + class Halt + def self.halt(machine) + begin + machine.communicate.sudo("shutdown -h now") + rescue IOError + # Do nothing, because it probably means the machine shut down + # and SSH connection was lost. + end + end + end + end + end +end diff --git a/plugins/guests/linux/cap/mount_nfs.rb b/plugins/guests/linux/cap/mount_nfs.rb new file mode 100644 index 000000000..efff4fea3 --- /dev/null +++ b/plugins/guests/linux/cap/mount_nfs.rb @@ -0,0 +1,26 @@ +module VagrantPlugins + module GuestLinux + module Cap + class MountNFS + def self.mount_nfs(machine, ip, folders) + folders.each do |name, opts| + # Expand the guest path so we can handle things like "~/vagrant" + expanded_guest_path = machine.guest.capability( + :shell_expand_guest_path, opts[:guestpath]) + + # Do the actual creating and mounting + machine.communicate.sudo("mkdir -p #{expanded_guest_path}") + + # Mount + mount_command = "mount -o vers=#{opts[:nfs_version]} #{ip}:'#{opts[:hostpath]}' #{expanded_guest_path}" + + retryable(:on => Vagrant::Errors::LinuxNFSMountFailed, :tries => 5, :sleep => 2) do + machine.communicate.sudo(mount_command, + :error_class => Vagrant::Errors::LinuxNFSMountFailed) + end + end + end + end + end + end +end diff --git a/plugins/guests/linux/guest.rb b/plugins/guests/linux/guest.rb index 0a9261277..59d09a608 100644 --- a/plugins/guests/linux/guest.rb +++ b/plugins/guests/linux/guest.rb @@ -1,71 +1,12 @@ -require 'log4r' - require "vagrant" -require "vagrant/util/retryable" module VagrantPlugins module GuestLinux class Guest < Vagrant.plugin("2", :guest) - include Vagrant::Util::Retryable - def detect?(machine) # TODO: Linux detection false end - - def halt - begin - @vm.communicate.sudo("shutdown -h now") - rescue IOError - # Do nothing, because it probably means the machine shut down - # and SSH connection was lost. - end - end - - def mount_nfs(ip, folders) - # TODO: Maybe check for nfs support on the guest, since its often - # not installed by default - folders.each do |name, opts| - # Expand the guestpath, so we can handle things like "~/vagrant" - real_guestpath = expanded_guest_path(opts[:guestpath]) - - # Do the actual creating and mounting - @vm.communicate.sudo("mkdir -p #{real_guestpath}") - - retryable(:on => LinuxError, :tries => 5, :sleep => 2) do - @vm.communicate.sudo("mount -o vers=#{opts[:nfs_version]} #{ip}:'#{opts[:hostpath]}' #{real_guestpath}", - :error_class => LinuxError, - :error_key => :mount_nfs_fail) - end - end - end - - protected - - # Determine the real guest path. Since we use a `sudo` shell everywhere - # else, things like '~' don't expand properly in shared folders. We have - # to `echo` here to get that path. - # - # @param [String] guestpath The unexpanded guest path. - # @return [String] The expanded guestpath - def expanded_guest_path(guestpath) - real_guestpath = nil - @vm.communicate.execute("printf #{guestpath}") do |type, data| - if type == :stdout - real_guestpath ||= "" - real_guestpath += data - end - end - - if !real_guestpath - # Really strange error case if this happens. Let's throw an error, - # tell the user to check the echo output. - raise LinuxError, :_key => :guestpath_expand_fail - end - - # Chomp the string so that any trailing newlines are killed - return real_guestpath.chomp - end end end end diff --git a/plugins/guests/linux/plugin.rb b/plugins/guests/linux/plugin.rb index ee0ce1065..91f579048 100644 --- a/plugins/guests/linux/plugin.rb +++ b/plugins/guests/linux/plugin.rb @@ -16,11 +16,21 @@ module VagrantPlugins Guest end + guest_capability("linux", "halt") do + require_relative "cap/halt" + Cap::Halt + end + guest_capability("linux", "shell_expand_guest_path") do require_relative "cap/shell_expand_guest_path" Cap::ShellExpandGuestPath end + guest_capability("linux", "mount_nfs_folder") do + require_relative "cap/mount_nfs" + Cap::MountNFS + end + guest_capability("linux", "mount_virtualbox_shared_folder") do require_relative "cap/mount_virtualbox_shared_folder" Cap::MountVirtualBoxSharedFolder diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 44fd0e801..92768e584 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -211,6 +211,12 @@ en: can work properly. The command attempted was: %{command} + linux_nfs_mount_failed: |- + Mounting NFS shared folders failed. This is most often caused by the NFS + client software not being installed on the guest machine. Please verify + that the NFS client software is properly installed, and consult any resources + specific to the linux distro you're using for more information on how to + do this. linux_shell_expand_failed: |- Vagrant failed to determine the shell expansion of the guest path for one of your shared folders. This is an extremely rare error case @@ -1032,12 +1038,3 @@ en: no_path_or_inline: "One of `path` or `inline` must be set." path_invalid: "`path` for shell provisioner does not exist on the host system: %{path}" upload_path_not_set: "`upload_path` must be set for the shell provisioner." - - guest: - linux: - mount_nfs_fail: |- - Mounting NFS shared folders failed. This is most often caused by the NFS - client software not being installed on the guest machine. Please verify - that the NFS client software is properly installed, and consult any resources - specific to the linux distro you're using for more information on how to - do this.