Better host loading scheme
This commit is contained in:
parent
b8d40ea463
commit
668bab0ba9
|
@ -42,6 +42,10 @@ module Vagrant
|
|||
def self.source_root
|
||||
@source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
|
||||
end
|
||||
|
||||
def self.hosts
|
||||
@hosts ||= Registry.new
|
||||
end
|
||||
end
|
||||
|
||||
# # Default I18n to load the en locale
|
||||
|
@ -53,3 +57,10 @@ require 'vagrant/provisioners'
|
|||
require 'vagrant/systems'
|
||||
require 'vagrant/version'
|
||||
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]
|
||||
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
|
||||
|
||||
# Action runner for executing actions in the context of this environment.
|
||||
|
|
|
@ -6,5 +6,21 @@ module Vagrant
|
|||
autoload :FreeBSD,'vagrant/hosts/freebsd'
|
||||
autoload :Fedora, 'vagrant/hosts/fedora'
|
||||
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
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
module Vagrant
|
||||
module Hosts
|
||||
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',
|
||||
:uuid => env.vm.uuid,
|
||||
:uuid => id,
|
||||
:ip => ip,
|
||||
: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
|
||||
|
||||
output.split("\n").each do |line|
|
||||
|
|
|
@ -1,54 +1,39 @@
|
|||
module Vagrant
|
||||
module Hosts
|
||||
# Base class representing a host machine. These classes
|
||||
# define methods which may have host-specific (Mac OS X, Windows,
|
||||
# Linux, etc) behavior. The class is automatically determined by
|
||||
# default but may be explicitly set via `config.vagrant.host`.
|
||||
# Interface for classes which house behavior that is specific
|
||||
# to the host OS that is running Vagrant.
|
||||
#
|
||||
# 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
|
||||
# The {Environment} which this host belongs to.
|
||||
attr_reader :env
|
||||
|
||||
# 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.
|
||||
# This returns true/false depending on if the current running system
|
||||
# matches the host class.
|
||||
#
|
||||
# @param [Environment] env
|
||||
# @param [String] klass
|
||||
# @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
|
||||
# @return [Boolean]
|
||||
def self.match?
|
||||
nil
|
||||
end
|
||||
|
||||
# This must be implemented by subclasses to dispatch to the proper
|
||||
# distro-specific class for the host. If this returns nil then it is
|
||||
# an invalid host class.
|
||||
def self.distro_dispatch
|
||||
nil
|
||||
# The precedence of the host when checking for matches. This is to
|
||||
# allow certain host such as generic OS's ("Linux", "BSD", etc.)
|
||||
# to be specified last.
|
||||
#
|
||||
# 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
|
||||
|
||||
# Initialzes a new host. This method shouldn't be called directly,
|
||||
# typically, since it will be called by {Environment#load!}.
|
||||
# Initializes a new host class.
|
||||
#
|
||||
# @param [Environment] env
|
||||
def initialize(env)
|
||||
@env = env
|
||||
# The only required parameter is a UI object so that the host
|
||||
# objects have some way to communicate with the outside world.
|
||||
#
|
||||
# @param [UI] ui UI for the hosts to output to.
|
||||
def initialize(ui)
|
||||
@ui = ui
|
||||
end
|
||||
|
||||
# Returns true of false denoting whether or not this host supports
|
||||
|
@ -60,16 +45,19 @@ module Vagrant
|
|||
false
|
||||
end
|
||||
|
||||
# Exports the given hash of folders via NFS. This method will raise
|
||||
# an {Vagrant::Action::ActionException} if anything goes wrong.
|
||||
# Exports the given hash of folders via NFS.
|
||||
#
|
||||
# @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 [Hash] folders Shared folders to sync.
|
||||
def nfs_export(ip, folders)
|
||||
def nfs_export(id, ip, folders)
|
||||
end
|
||||
|
||||
# Cleans up the exports for the current VM.
|
||||
def nfs_cleanup
|
||||
# Cleans up the exports for the given ID.
|
||||
#
|
||||
# @param [String] id A unique ID to identify the folder set to cleanup.
|
||||
def nfs_cleanup(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,9 +7,20 @@ module Vagrant
|
|||
include Util
|
||||
include Util::Retryable
|
||||
|
||||
def self.distro_dispatch
|
||||
return FreeBSD if Util::Platform.freebsd?
|
||||
return self if Util::Platform.darwin? || Util::Platform.bsd?
|
||||
def self.match?
|
||||
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
|
||||
|
||||
def nfs?
|
||||
|
@ -18,15 +29,15 @@ module Vagrant
|
|||
end
|
||||
end
|
||||
|
||||
def nfs_export(ip, folders)
|
||||
def nfs_export(id, ip, folders)
|
||||
output = TemplateRenderer.render('nfs/exports',
|
||||
:uuid => env.vm.uuid,
|
||||
:uuid => id,
|
||||
: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")
|
||||
@ui.info I18n.t("vagrant.hosts.bsd.nfs_export.prepare")
|
||||
sleep 0.5
|
||||
|
||||
output.split("\n").each do |line|
|
||||
|
@ -38,19 +49,20 @@ module Vagrant
|
|||
|
||||
# We run restart here instead of "update" just in case nfsd
|
||||
# is not starting
|
||||
system("sudo nfsd restart")
|
||||
system(@nfs_restart_command)
|
||||
end
|
||||
|
||||
def nfs_cleanup
|
||||
def nfs_cleanup(id)
|
||||
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")
|
||||
system("cat /etc/exports | grep 'VAGRANT-BEGIN: #{id}' > /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")
|
||||
# by Vagrant, and restart NFS.
|
||||
system("sudo sed -e '/^# VAGRANT-BEGIN: #{id}/,/^# VAGRANT-END: #{id}/ d' -ibak /etc/exports")
|
||||
system(@nfs_restart_command)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,20 @@
|
|||
require 'pathname'
|
||||
|
||||
module Vagrant
|
||||
module Hosts
|
||||
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)
|
||||
super
|
||||
|
||||
|
|
|
@ -7,44 +7,14 @@ module Vagrant
|
|||
include Util
|
||||
include Util::Retryable
|
||||
|
||||
def nfs_export(ip, folders)
|
||||
output = TemplateRenderer.render('nfs/exports',
|
||||
: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"])
|
||||
def self.match?
|
||||
Util::Platform.freebsd?
|
||||
end
|
||||
|
||||
# We run restart here instead of "update" just in case nfsd
|
||||
# is not starting
|
||||
system("sudo /etc/rc.d/mountd onereload")
|
||||
end
|
||||
def initialize(*args)
|
||||
super
|
||||
|
||||
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")
|
||||
@nfs_restart_command = "sudo /etc/rc.d/mountd onereload"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,18 +7,14 @@ module Vagrant
|
|||
include Util
|
||||
include Util::Retryable
|
||||
|
||||
def self.distro_dispatch
|
||||
return nil if !Util::Platform.linux?
|
||||
return Arch if File.exist?("/etc/rc.conf") && File.exist?("/etc/pacman.conf")
|
||||
|
||||
if File.exist?("/etc/redhat-release")
|
||||
# Check if we have a known redhat release
|
||||
File.open("/etc/redhat-release") do |f|
|
||||
return Fedora if f.gets =~ /^Fedora/
|
||||
end
|
||||
def self.match?
|
||||
Util::Platform.linux?
|
||||
end
|
||||
|
||||
return self
|
||||
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)
|
||||
|
@ -34,13 +30,13 @@ module Vagrant
|
|||
end
|
||||
end
|
||||
|
||||
def nfs_export(ip, folders)
|
||||
def nfs_export(id, ip, folders)
|
||||
output = TemplateRenderer.render('nfs/exports_linux',
|
||||
:uuid => env.vm.uuid,
|
||||
:uuid => id,
|
||||
:ip => ip,
|
||||
: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
|
||||
|
||||
output.split("\n").each do |line|
|
||||
|
@ -54,14 +50,14 @@ module Vagrant
|
|||
system("sudo #{@nfs_server_binary} restart")
|
||||
end
|
||||
|
||||
def nfs_cleanup
|
||||
def nfs_cleanup(id)
|
||||
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
|
||||
# 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")
|
||||
system("sudo sed -e '/^# VAGRANT-BEGIN: #{id}/,/^# VAGRANT-END: #{id}/ d' -ibak /etc/exports")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -35,5 +35,15 @@ module Vagrant
|
|||
yield key, get(key)
|
||||
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
|
||||
|
|
|
@ -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"]
|
||||
values.sort.should == ["barvalue", "foovalue"]
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue