vagrant/plugins/guests/linux/guest.rb

120 lines
4.0 KiB
Ruby

require 'log4r'
require "vagrant"
require "vagrant/util/retryable"
module VagrantPlugins
module GuestLinux
class Guest < Vagrant.plugin("2", :guest)
include Vagrant::Util::Retryable
class LinuxError < Vagrant::Errors::VagrantError
error_namespace("vagrant.guest.linux")
end
def initialize(*args)
super
@logger = Log4r::Logger.new("vagrant::guest::linux")
end
def distro_dispatch
@vm.communicate.tap do |comm|
if comm.test("cat /etc/debian_version")
return :debian if comm.test("cat /proc/version | grep 'Debian'")
return :ubuntu if comm.test("cat /proc/version | grep 'Ubuntu'")
end
return :gentoo if comm.test("cat /etc/gentoo-release")
return :fedora if comm.test("grep 'Fedora release 1[678]' /etc/redhat-release")
return :redhat if comm.test("cat /etc/redhat-release")
return :suse if comm.test("cat /etc/SuSE-release")
return :arch if comm.test("cat /etc/arch-release")
return :solaris if comm.test("grep 'Solaris' /etc/release")
end
# Can't detect the distro, assume vanilla linux
nil
end
def halt
@vm.communicate.sudo("shutdown -h now")
end
def mount_shared_folder(name, guestpath, options)
real_guestpath = expanded_guest_path(guestpath)
@logger.debug("Shell expanded guest path: #{real_guestpath}")
@vm.communicate.sudo("mkdir -p #{real_guestpath}")
mount_folder(name, real_guestpath, options)
@vm.communicate.sudo("chown `id -u #{options[:owner]}`:`id -g #{options[:group]}` #{real_guestpath}")
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
def mount_folder(name, guestpath, options)
# Determine the permission string to attach to the mount command
mount_options = "-o uid=`id -u #{options[:owner]}`,gid=`id -g #{options[:group]}`"
mount_options += ",#{options[:extra]}" if options[:extra]
attempts = 0
while true
success = true
@vm.communicate.sudo("mount -t vboxsf #{mount_options} #{name} #{guestpath}") do |type, data|
success = false if type == :stderr && data =~ /No such device/i
end
break if success
attempts += 1
raise LinuxError, :mount_fail if attempts >= 10
sleep 5
end
end
end
end
end