Better host loading scheme
This commit is contained in:
parent
b8d40ea463
commit
668bab0ba9
|
@ -42,6 +42,10 @@ module Vagrant
|
||||||
def self.source_root
|
def self.source_root
|
||||||
@source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
|
@source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.hosts
|
||||||
|
@hosts ||= Registry.new
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# # Default I18n to load the en locale
|
# # Default I18n to load the en locale
|
||||||
|
@ -53,3 +57,10 @@ require 'vagrant/provisioners'
|
||||||
require 'vagrant/systems'
|
require 'vagrant/systems'
|
||||||
require 'vagrant/version'
|
require 'vagrant/version'
|
||||||
Vagrant::Plugin.load!
|
Vagrant::Plugin.load!
|
||||||
|
|
||||||
|
# Register the built-in hosts
|
||||||
|
Vagrant.hosts.register(:arch) { Vagrant::Hosts::Arch }
|
||||||
|
Vagrant.hosts.register(:freebsd) { Vagrant::Hosts::FreeBSD }
|
||||||
|
Vagrant.hosts.register(:fedora) { Vagrant::Hosts::Fedora }
|
||||||
|
Vagrant.hosts.register(:linux) { Vagrant::Hosts::Linux }
|
||||||
|
Vagrant.hosts.register(:bsd) { Vagrant::Hosts::BSD }
|
||||||
|
|
|
@ -179,7 +179,16 @@ module Vagrant
|
||||||
#
|
#
|
||||||
# @return [Hosts::Base]
|
# @return [Hosts::Base]
|
||||||
def host
|
def host
|
||||||
@host ||= Hosts::Base.load(self, config.vagrant.host)
|
return @host if defined?(@host)
|
||||||
|
|
||||||
|
# Attempt to figure out the host class. Note that the order
|
||||||
|
# matters here, so please don't touch. Specifically: The symbol
|
||||||
|
# check is done after the detect check because the symbol check
|
||||||
|
# will return nil, and we don't want to trigger a detect load.
|
||||||
|
host_klass = config.global.vagrant.host
|
||||||
|
host_klass = Hosts.detect(Vagrant.hosts) if host_klass.nil? || host_klass == :detect
|
||||||
|
host_klass = Vagrant.hosts.get(host_klass) if host_klass.is_a?(Symbol)
|
||||||
|
@host ||= host_klass.new(@ui)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Action runner for executing actions in the context of this environment.
|
# Action runner for executing actions in the context of this environment.
|
||||||
|
|
|
@ -6,5 +6,21 @@ module Vagrant
|
||||||
autoload :FreeBSD,'vagrant/hosts/freebsd'
|
autoload :FreeBSD,'vagrant/hosts/freebsd'
|
||||||
autoload :Fedora, 'vagrant/hosts/fedora'
|
autoload :Fedora, 'vagrant/hosts/fedora'
|
||||||
autoload :Linux, 'vagrant/hosts/linux'
|
autoload :Linux, 'vagrant/hosts/linux'
|
||||||
|
|
||||||
|
# This method detects the correct host based on the `match?` methods
|
||||||
|
# implemented in the registered hosts.
|
||||||
|
def self.detect(registry)
|
||||||
|
# Sort the hosts by their precedence
|
||||||
|
host_klasses = registry.to_hash.values
|
||||||
|
host_klasses = host_klasses.sort_by { |a| a.precedence }.reverse
|
||||||
|
|
||||||
|
# Test for matches and return the host class that matches
|
||||||
|
host_klasses.each do |klass|
|
||||||
|
return klass if klass.match?
|
||||||
|
end
|
||||||
|
|
||||||
|
# No matches found...
|
||||||
|
return nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module Hosts
|
module Hosts
|
||||||
class Arch < Linux
|
class Arch < Linux
|
||||||
def nfs_export(ip, folders)
|
def self.match?
|
||||||
|
File.exist?("/etc/rc.conf") && File.exist?("/etc/pacman.conf")
|
||||||
|
end
|
||||||
|
|
||||||
|
def nfs_export(id, ip, folders)
|
||||||
output = TemplateRenderer.render('nfs/exports_linux',
|
output = TemplateRenderer.render('nfs/exports_linux',
|
||||||
:uuid => env.vm.uuid,
|
:uuid => id,
|
||||||
:ip => ip,
|
:ip => ip,
|
||||||
:folders => folders)
|
:folders => folders)
|
||||||
|
|
||||||
env.ui.info I18n.t("vagrant.hosts.arch.nfs_export.prepare")
|
@ui.info I18n.t("vagrant.hosts.arch.nfs_export.prepare")
|
||||||
sleep 0.5
|
sleep 0.5
|
||||||
|
|
||||||
output.split("\n").each do |line|
|
output.split("\n").each do |line|
|
||||||
|
|
|
@ -1,54 +1,39 @@
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module Hosts
|
module Hosts
|
||||||
# Base class representing a host machine. These classes
|
# Interface for classes which house behavior that is specific
|
||||||
# define methods which may have host-specific (Mac OS X, Windows,
|
# to the host OS that is running Vagrant.
|
||||||
# Linux, etc) behavior. The class is automatically determined by
|
#
|
||||||
# default but may be explicitly set via `config.vagrant.host`.
|
# By default, Vagrant will attempt to choose the best option
|
||||||
|
# for your machine, but the host may also be explicitly set
|
||||||
|
# via the `config.vagrant.host` parameter.
|
||||||
class Base
|
class Base
|
||||||
# The {Environment} which this host belongs to.
|
# This returns true/false depending on if the current running system
|
||||||
attr_reader :env
|
# matches the host class.
|
||||||
|
|
||||||
# Loads the proper host for the given value. If the value is nil
|
|
||||||
# or is the symbol `:detect`, then the host class will be detected
|
|
||||||
# using the `RUBY_PLATFORM` constant.
|
|
||||||
#
|
#
|
||||||
# @param [Environment] env
|
# @return [Boolean]
|
||||||
# @param [String] klass
|
def self.match?
|
||||||
# @return [Base]
|
|
||||||
def self.load(env, klass)
|
|
||||||
klass = detect if klass.nil? || klass == :detect
|
|
||||||
return nil if !klass
|
|
||||||
return klass.new(env)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Detects the proper host class for current platform and returns
|
|
||||||
# the class.
|
|
||||||
#
|
|
||||||
# @return [Class]
|
|
||||||
def self.detect
|
|
||||||
[BSD, Linux].each do |type|
|
|
||||||
result = type.distro_dispatch
|
|
||||||
return result if result
|
|
||||||
end
|
|
||||||
|
|
||||||
nil
|
|
||||||
rescue Exception
|
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# This must be implemented by subclasses to dispatch to the proper
|
# The precedence of the host when checking for matches. This is to
|
||||||
# distro-specific class for the host. If this returns nil then it is
|
# allow certain host such as generic OS's ("Linux", "BSD", etc.)
|
||||||
# an invalid host class.
|
# to be specified last.
|
||||||
def self.distro_dispatch
|
#
|
||||||
nil
|
# The hosts with the higher numbers will be checked first.
|
||||||
|
#
|
||||||
|
# If you're implementing a basic host, you can probably ignore this.
|
||||||
|
def self.precedence
|
||||||
|
5
|
||||||
end
|
end
|
||||||
|
|
||||||
# Initialzes a new host. This method shouldn't be called directly,
|
# Initializes a new host class.
|
||||||
# typically, since it will be called by {Environment#load!}.
|
|
||||||
#
|
#
|
||||||
# @param [Environment] env
|
# The only required parameter is a UI object so that the host
|
||||||
def initialize(env)
|
# objects have some way to communicate with the outside world.
|
||||||
@env = env
|
#
|
||||||
|
# @param [UI] ui UI for the hosts to output to.
|
||||||
|
def initialize(ui)
|
||||||
|
@ui = ui
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns true of false denoting whether or not this host supports
|
# Returns true of false denoting whether or not this host supports
|
||||||
|
@ -60,16 +45,19 @@ module Vagrant
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
# Exports the given hash of folders via NFS. This method will raise
|
# Exports the given hash of folders via NFS.
|
||||||
# an {Vagrant::Action::ActionException} if anything goes wrong.
|
|
||||||
#
|
#
|
||||||
|
# @param [String] id A unique ID that is guaranteed to be unique to
|
||||||
|
# match these sets of folders.
|
||||||
# @param [String] ip IP of the guest machine.
|
# @param [String] ip IP of the guest machine.
|
||||||
# @param [Hash] folders Shared folders to sync.
|
# @param [Hash] folders Shared folders to sync.
|
||||||
def nfs_export(ip, folders)
|
def nfs_export(id, ip, folders)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Cleans up the exports for the current VM.
|
# Cleans up the exports for the given ID.
|
||||||
def nfs_cleanup
|
#
|
||||||
|
# @param [String] id A unique ID to identify the folder set to cleanup.
|
||||||
|
def nfs_cleanup(id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,9 +7,20 @@ module Vagrant
|
||||||
include Util
|
include Util
|
||||||
include Util::Retryable
|
include Util::Retryable
|
||||||
|
|
||||||
def self.distro_dispatch
|
def self.match?
|
||||||
return FreeBSD if Util::Platform.freebsd?
|
Util::Platform.darwin? || Util::Platform.bsd?
|
||||||
return self if Util::Platform.darwin? || Util::Platform.bsd?
|
end
|
||||||
|
|
||||||
|
def self.precedence
|
||||||
|
# Set a lower precedence because this is a generic OS. We
|
||||||
|
# want specific distros to match first.
|
||||||
|
2
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(*args)
|
||||||
|
super
|
||||||
|
|
||||||
|
@nfs_restart_command = "sudo nfsd restart"
|
||||||
end
|
end
|
||||||
|
|
||||||
def nfs?
|
def nfs?
|
||||||
|
@ -18,15 +29,15 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def nfs_export(ip, folders)
|
def nfs_export(id, ip, folders)
|
||||||
output = TemplateRenderer.render('nfs/exports',
|
output = TemplateRenderer.render('nfs/exports',
|
||||||
:uuid => env.vm.uuid,
|
:uuid => id,
|
||||||
:ip => ip,
|
:ip => ip,
|
||||||
:folders => folders)
|
:folders => folders)
|
||||||
|
|
||||||
# The sleep ensures that the output is truly flushed before any `sudo`
|
# The sleep ensures that the output is truly flushed before any `sudo`
|
||||||
# commands are issued.
|
# commands are issued.
|
||||||
env.ui.info I18n.t("vagrant.hosts.bsd.nfs_export.prepare")
|
@ui.info I18n.t("vagrant.hosts.bsd.nfs_export.prepare")
|
||||||
sleep 0.5
|
sleep 0.5
|
||||||
|
|
||||||
output.split("\n").each do |line|
|
output.split("\n").each do |line|
|
||||||
|
@ -38,19 +49,20 @@ module Vagrant
|
||||||
|
|
||||||
# We run restart here instead of "update" just in case nfsd
|
# We run restart here instead of "update" just in case nfsd
|
||||||
# is not starting
|
# is not starting
|
||||||
system("sudo nfsd restart")
|
system(@nfs_restart_command)
|
||||||
end
|
end
|
||||||
|
|
||||||
def nfs_cleanup
|
def nfs_cleanup(id)
|
||||||
return if !File.exist?("/etc/exports")
|
return if !File.exist?("/etc/exports")
|
||||||
|
|
||||||
retryable(:tries => 10, :on => TypeError) do
|
retryable(:tries => 10, :on => TypeError) do
|
||||||
system("cat /etc/exports | grep 'VAGRANT-BEGIN: #{env.vm.uuid}' > /dev/null 2>&1")
|
system("cat /etc/exports | grep 'VAGRANT-BEGIN: #{id}' > /dev/null 2>&1")
|
||||||
|
|
||||||
if $?.to_i == 0
|
if $?.to_i == 0
|
||||||
# Use sed to just strip out the block of code which was inserted
|
# Use sed to just strip out the block of code which was inserted
|
||||||
# by Vagrant
|
# by Vagrant, and restart NFS.
|
||||||
system("sudo sed -e '/^# VAGRANT-BEGIN: #{env.vm.uuid}/,/^# VAGRANT-END: #{env.vm.uuid}/ d' -ibak /etc/exports")
|
system("sudo sed -e '/^# VAGRANT-BEGIN: #{id}/,/^# VAGRANT-END: #{id}/ d' -ibak /etc/exports")
|
||||||
|
system(@nfs_restart_command)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
|
require 'pathname'
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module Hosts
|
module Hosts
|
||||||
class Fedora < Linux
|
class Fedora < Linux
|
||||||
|
def self.match?
|
||||||
|
release_file = Pathname.new("/etc/redhat-release")
|
||||||
|
|
||||||
|
if release_file.exist?
|
||||||
|
release_file.open("r") do |f|
|
||||||
|
return true if f.gets =~ /^Fedora/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
super
|
super
|
||||||
|
|
||||||
|
|
|
@ -7,45 +7,15 @@ module Vagrant
|
||||||
include Util
|
include Util
|
||||||
include Util::Retryable
|
include Util::Retryable
|
||||||
|
|
||||||
def nfs_export(ip, folders)
|
def self.match?
|
||||||
output = TemplateRenderer.render('nfs/exports',
|
Util::Platform.freebsd?
|
||||||
:uuid => env.vm.uuid,
|
|
||||||
:ip => ip,
|
|
||||||
:folders => folders)
|
|
||||||
|
|
||||||
# The sleep ensures that the output is truly flushed before any `sudo`
|
|
||||||
# commands are issued.
|
|
||||||
env.ui.info I18n.t("vagrant.hosts.bsd.nfs_export.prepare")
|
|
||||||
sleep 0.5
|
|
||||||
|
|
||||||
output.split("\n").each do |line|
|
|
||||||
# This should only ask for administrative permission once, even
|
|
||||||
# though its executed in multiple subshells.
|
|
||||||
line = line.gsub('"', '\"')
|
|
||||||
system(%Q[sudo su root -c "echo '#{line}' >> /etc/exports"])
|
|
||||||
end
|
|
||||||
|
|
||||||
# We run restart here instead of "update" just in case nfsd
|
|
||||||
# is not starting
|
|
||||||
system("sudo /etc/rc.d/mountd onereload")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def initialize(*args)
|
||||||
|
super
|
||||||
|
|
||||||
|
@nfs_restart_command = "sudo /etc/rc.d/mountd onereload"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def nfs_cleanup
|
|
||||||
return if !File.exist?("/etc/exports")
|
|
||||||
|
|
||||||
retryable(:tries => 10, :on => TypeError) do
|
|
||||||
system("cat /etc/exports | grep 'VAGRANT-BEGIN: #{env.vm.uuid}' > /dev/null 2>&1")
|
|
||||||
|
|
||||||
if $?.to_i == 0
|
|
||||||
# Use sed to just strip out the block of code which was inserted
|
|
||||||
# by Vagrant
|
|
||||||
system("sudo sed -e '/^# VAGRANT-BEGIN: #{env.vm.uuid}/,/^# VAGRANT-END: #{env.vm.uuid}/ d' -ibak /etc/exports")
|
|
||||||
end
|
|
||||||
|
|
||||||
system("sudo /etc/rc.d/mountd onereload")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,18 +7,14 @@ module Vagrant
|
||||||
include Util
|
include Util
|
||||||
include Util::Retryable
|
include Util::Retryable
|
||||||
|
|
||||||
def self.distro_dispatch
|
def self.match?
|
||||||
return nil if !Util::Platform.linux?
|
Util::Platform.linux?
|
||||||
return Arch if File.exist?("/etc/rc.conf") && File.exist?("/etc/pacman.conf")
|
end
|
||||||
|
|
||||||
if File.exist?("/etc/redhat-release")
|
def self.precedence
|
||||||
# Check if we have a known redhat release
|
# Set a lower precedence because this is a generic OS. We
|
||||||
File.open("/etc/redhat-release") do |f|
|
# want specific distros to match first.
|
||||||
return Fedora if f.gets =~ /^Fedora/
|
2
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
|
@ -34,13 +30,13 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def nfs_export(ip, folders)
|
def nfs_export(id, ip, folders)
|
||||||
output = TemplateRenderer.render('nfs/exports_linux',
|
output = TemplateRenderer.render('nfs/exports_linux',
|
||||||
:uuid => env.vm.uuid,
|
:uuid => id,
|
||||||
:ip => ip,
|
:ip => ip,
|
||||||
:folders => folders)
|
:folders => folders)
|
||||||
|
|
||||||
env.ui.info I18n.t("vagrant.hosts.linux.nfs_export.prepare")
|
@ui.info I18n.t("vagrant.hosts.linux.nfs_export.prepare")
|
||||||
sleep 0.5
|
sleep 0.5
|
||||||
|
|
||||||
output.split("\n").each do |line|
|
output.split("\n").each do |line|
|
||||||
|
@ -54,14 +50,14 @@ module Vagrant
|
||||||
system("sudo #{@nfs_server_binary} restart")
|
system("sudo #{@nfs_server_binary} restart")
|
||||||
end
|
end
|
||||||
|
|
||||||
def nfs_cleanup
|
def nfs_cleanup(id)
|
||||||
return if !File.exist?("/etc/exports")
|
return if !File.exist?("/etc/exports")
|
||||||
system("cat /etc/exports | grep 'VAGRANT-BEGIN: #{env.vm.uuid}' > /dev/null 2>&1")
|
system("cat /etc/exports | grep 'VAGRANT-BEGIN: #{id}' > /dev/null 2>&1")
|
||||||
|
|
||||||
if $?.to_i == 0
|
if $?.to_i == 0
|
||||||
# Use sed to just strip out the block of code which was inserted
|
# Use sed to just strip out the block of code which was inserted
|
||||||
# by Vagrant
|
# by Vagrant
|
||||||
system("sudo sed -e '/^# VAGRANT-BEGIN: #{env.vm.uuid}/,/^# VAGRANT-END: #{env.vm.uuid}/ d' -ibak /etc/exports")
|
system("sudo sed -e '/^# VAGRANT-BEGIN: #{id}/,/^# VAGRANT-END: #{id}/ d' -ibak /etc/exports")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -35,5 +35,15 @@ module Vagrant
|
||||||
yield key, get(key)
|
yield key, get(key)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Converts this registry to a hash
|
||||||
|
def to_hash
|
||||||
|
result = {}
|
||||||
|
self.each do |key, value|
|
||||||
|
result[key] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
require File.expand_path("../../base", __FILE__)
|
||||||
|
|
||||||
|
describe Vagrant::Hosts do
|
||||||
|
let(:registry) { Vagrant::Registry.new }
|
||||||
|
|
||||||
|
it "detects the host that matches true" do
|
||||||
|
foo_klass = Class.new(Vagrant::Hosts::Base) do
|
||||||
|
def self.match?; false; end
|
||||||
|
end
|
||||||
|
|
||||||
|
bar_klass = Class.new(Vagrant::Hosts::Base) do
|
||||||
|
def self.match?; true; end
|
||||||
|
end
|
||||||
|
|
||||||
|
registry.register(:foo, foo_klass)
|
||||||
|
registry.register(:bar, bar_klass)
|
||||||
|
|
||||||
|
described_class.detect(registry).should == bar_klass
|
||||||
|
end
|
||||||
|
|
||||||
|
it "detects the host that matches true with the highest precedence first" do
|
||||||
|
foo_klass = Class.new(Vagrant::Hosts::Base) do
|
||||||
|
def self.match?; true; end
|
||||||
|
end
|
||||||
|
|
||||||
|
bar_klass = Class.new(Vagrant::Hosts::Base) do
|
||||||
|
def self.match?; true; end
|
||||||
|
def self.precedence; 9; end
|
||||||
|
end
|
||||||
|
|
||||||
|
registry.register(:foo, foo_klass)
|
||||||
|
registry.register(:bar, bar_klass)
|
||||||
|
|
||||||
|
described_class.detect(registry).should == bar_klass
|
||||||
|
end
|
||||||
|
end
|
|
@ -43,4 +43,14 @@ describe Vagrant::Registry do
|
||||||
keys.sort.should == ["bar", "foo"]
|
keys.sort.should == ["bar", "foo"]
|
||||||
values.sort.should == ["barvalue", "foovalue"]
|
values.sort.should == ["barvalue", "foovalue"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "should be able to convert to a hash" do
|
||||||
|
instance.register("foo", "foovalue")
|
||||||
|
instance.register("bar", "barvalue")
|
||||||
|
|
||||||
|
result = instance.to_hash
|
||||||
|
result.should be_a(Hash)
|
||||||
|
result["foo"].should == "foovalue"
|
||||||
|
result["bar"].should == "barvalue"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue