core: modify Guest to use new CapabilityHost mixin
This commit is contained in:
parent
1f760b2c48
commit
40babfc3f7
|
@ -1,5 +1,7 @@
|
||||||
require "log4r"
|
require "log4r"
|
||||||
|
|
||||||
|
require "vagrant/capability_host"
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
# This class handles guest-OS specific interactions with a machine.
|
# This class handles guest-OS specific interactions with a machine.
|
||||||
# It is primarily responsible for detecting the proper guest OS
|
# It is primarily responsible for detecting the proper guest OS
|
||||||
|
@ -17,21 +19,13 @@ module Vagrant
|
||||||
# This system allows for maximum flexibility and pluginability for doing
|
# This system allows for maximum flexibility and pluginability for doing
|
||||||
# guest OS specific operations.
|
# guest OS specific operations.
|
||||||
class Guest
|
class Guest
|
||||||
attr_reader :chain
|
include CapabilityHost
|
||||||
|
|
||||||
# The name of the guest OS. This is available after {#detect!} is
|
|
||||||
# called.
|
|
||||||
#
|
|
||||||
# @return [Symbol]
|
|
||||||
attr_reader :name
|
|
||||||
|
|
||||||
def initialize(machine, guests, capabilities)
|
def initialize(machine, guests, capabilities)
|
||||||
@logger = Log4r::Logger.new("vagrant::guest")
|
@logger = Log4r::Logger.new("vagrant::guest")
|
||||||
@capabilities = capabilities
|
@capabilities = capabilities
|
||||||
@chain = []
|
|
||||||
@guests = guests
|
@guests = guests
|
||||||
@machine = machine
|
@machine = machine
|
||||||
@name = nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# This will detect the proper guest OS for the machine and set up
|
# This will detect the proper guest OS for the machine and set up
|
||||||
|
@ -40,52 +34,7 @@ module Vagrant
|
||||||
@logger.info("Detect guest for machine: #{@machine}")
|
@logger.info("Detect guest for machine: #{@machine}")
|
||||||
|
|
||||||
guest_name = @machine.config.vm.guest
|
guest_name = @machine.config.vm.guest
|
||||||
if guest_name
|
initialize_capabilities!(guest_name, @guests, @capabilities, @machine)
|
||||||
@logger.info("Using explicit config.vm.guest value: #{guest_name}")
|
|
||||||
else
|
|
||||||
# No explicit guest was specified, so autodetect it.
|
|
||||||
guest_name = autodetect_guest
|
|
||||||
raise Errors::GuestNotDetected if !guest_name
|
|
||||||
end
|
|
||||||
|
|
||||||
if !@guests[guest_name]
|
|
||||||
# This can happen if config.vm.guest was specified with a value
|
|
||||||
# that doesn't exist.
|
|
||||||
raise Errors::GuestExplicitNotDetected, value: guest_name.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
@name = guest_name
|
|
||||||
@chain = guest_chain(@name)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Tests whether the guest has the named capability.
|
|
||||||
#
|
|
||||||
# @return [Boolean]
|
|
||||||
def capability?(cap_name)
|
|
||||||
!capability_module(cap_name.to_sym).nil?
|
|
||||||
end
|
|
||||||
|
|
||||||
# Executes the capability with the given name, optionally passing
|
|
||||||
# more arguments onwards to the capability.
|
|
||||||
def capability(cap_name, *args)
|
|
||||||
@logger.info("Execute capability: #{cap_name} (#{@chain[0][0]})")
|
|
||||||
cap_mod = capability_module(cap_name.to_sym)
|
|
||||||
if !cap_mod
|
|
||||||
raise Errors::GuestCapabilityNotFound,
|
|
||||||
:cap => cap_name.to_s,
|
|
||||||
:guest => @chain[0][0].to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
cap_method = nil
|
|
||||||
begin
|
|
||||||
cap_method = cap_mod.method(cap_name)
|
|
||||||
rescue NameError
|
|
||||||
raise Errors::GuestCapabilityInvalid,
|
|
||||||
:cap => cap_name.to_s,
|
|
||||||
:guest => @chain[0][0].to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
cap_method.call(@machine, *args)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# This returns whether the guest is ready to work. If this returns
|
# This returns whether the guest is ready to work. If this returns
|
||||||
|
@ -94,98 +43,7 @@ module Vagrant
|
||||||
#
|
#
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
def ready?
|
def ready?
|
||||||
!@chain.empty?
|
!!capability_host_chain
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
# Returns the registered module for a capability with the given name.
|
|
||||||
#
|
|
||||||
# @param [Symbol] cap_name
|
|
||||||
# @return [Module]
|
|
||||||
def capability_module(cap_name)
|
|
||||||
@logger.debug("Searching for cap: #{cap_name}")
|
|
||||||
@chain.each do |guest_name, guest|
|
|
||||||
@logger.debug("Checking in: #{guest_name}")
|
|
||||||
caps = @capabilities[guest_name]
|
|
||||||
|
|
||||||
if caps && caps.has_key?(cap_name)
|
|
||||||
@logger.debug("Found cap: #{cap_name} in #{guest_name}")
|
|
||||||
return caps[cap_name]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
# This autodetects the guest to use and returns the name of the guest.
|
|
||||||
# This returns nil if the guest type could not be autodetected.
|
|
||||||
#
|
|
||||||
# @return [Symbol]
|
|
||||||
def autodetect_guest
|
|
||||||
@logger.info("Autodetecting guest for machine: #{@machine}")
|
|
||||||
|
|
||||||
# Get the mapping of guests with the most parents. We start searching
|
|
||||||
# with the guests with the most parents first.
|
|
||||||
parent_count = {}
|
|
||||||
@guests.each do |name, parts|
|
|
||||||
parent_count[name] = 0
|
|
||||||
|
|
||||||
parent = parts[1]
|
|
||||||
while parent
|
|
||||||
parent_count[name] += 1
|
|
||||||
parent = @guests[parent]
|
|
||||||
parent = parent[1] if parent
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Now swap around the mapping so that it is a mapping of
|
|
||||||
# count to the actual list of guest names
|
|
||||||
parent_count_to_guests = {}
|
|
||||||
parent_count.each do |name, count|
|
|
||||||
parent_count_to_guests[count] ||= []
|
|
||||||
parent_count_to_guests[count] << name
|
|
||||||
end
|
|
||||||
|
|
||||||
sorted_counts = parent_count_to_guests.keys.sort.reverse
|
|
||||||
sorted_counts.each do |count|
|
|
||||||
parent_count_to_guests[count].each do |name|
|
|
||||||
@logger.debug("Trying: #{name}")
|
|
||||||
guest_info = @guests[name]
|
|
||||||
guest = guest_info[0].new
|
|
||||||
|
|
||||||
if guest.detect?(@machine)
|
|
||||||
@logger.info("Detected: #{name}!")
|
|
||||||
return name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
# This returns the complete chain for the given guest.
|
|
||||||
#
|
|
||||||
# @return [Array]
|
|
||||||
def guest_chain(name)
|
|
||||||
guest_info = @guests[name]
|
|
||||||
guest = guest_info[0].new
|
|
||||||
chain = []
|
|
||||||
chain << [name, guest]
|
|
||||||
|
|
||||||
# Build the proper chain of parents if there are any.
|
|
||||||
# This allows us to do "inheritance" of capabilities later
|
|
||||||
if guest_info[1]
|
|
||||||
parent_name = guest_info[1]
|
|
||||||
parent_info = @guests[parent_name]
|
|
||||||
while parent_info
|
|
||||||
chain << [parent_name, parent_info[0].new]
|
|
||||||
parent_name = parent_info[1]
|
|
||||||
parent_info = @guests[parent_name]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return chain
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ require "pathname"
|
||||||
require File.expand_path("../../base", __FILE__)
|
require File.expand_path("../../base", __FILE__)
|
||||||
|
|
||||||
describe Vagrant::Guest do
|
describe Vagrant::Guest do
|
||||||
include_context "unit"
|
include_context "capability_helpers"
|
||||||
|
|
||||||
let(:capabilities) { {} }
|
let(:capabilities) { {} }
|
||||||
let(:guests) { {} }
|
let(:guests) { {} }
|
||||||
|
@ -18,44 +18,27 @@ describe Vagrant::Guest do
|
||||||
|
|
||||||
subject { described_class.new(machine, guests, capabilities) }
|
subject { described_class.new(machine, guests, capabilities) }
|
||||||
|
|
||||||
# This registers a capability with a specific guest
|
describe "#detect!" do
|
||||||
def register_capability(guest, capability, options=nil)
|
it "auto-detects if no explicit guest name given" do
|
||||||
options ||= {}
|
machine.config.vm.stub(guest: nil)
|
||||||
|
subject.should_receive(:initialize_capabilities!).
|
||||||
|
with(nil, guests, capabilities, machine)
|
||||||
|
|
||||||
cap = Class.new do
|
subject.detect!
|
||||||
if !options[:corrupt]
|
|
||||||
define_method(capability) do |*args|
|
|
||||||
raise "cap: #{capability} #{args.inspect}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
capabilities[guest] ||= {}
|
it "uses the explicit guest name if specified" do
|
||||||
capabilities[guest][capability] = cap.new
|
machine.config.vm.stub(guest: :foo)
|
||||||
end
|
subject.should_receive(:initialize_capabilities!).
|
||||||
|
with(:foo, guests, capabilities, machine)
|
||||||
|
|
||||||
# This registers a guest with the class.
|
subject.detect!
|
||||||
#
|
|
||||||
# @param [Symbol] name Name of the guest
|
|
||||||
# @param [Symbol] parent Name of the parent
|
|
||||||
# @param [Boolean] detect Whether or not to detect properly
|
|
||||||
def register_guest(name, parent, detect)
|
|
||||||
guest = Class.new(Vagrant.plugin("2", "guest")) do
|
|
||||||
define_method(:name) do
|
|
||||||
name
|
|
||||||
end
|
|
||||||
|
|
||||||
define_method(:detect?) do |m|
|
|
||||||
detect
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
guests[name] = [guest, parent]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#ready?" do
|
describe "#ready?" do
|
||||||
before(:each) do
|
before(:each) do
|
||||||
register_guest(:foo, nil, true)
|
guests[:foo] = [detect_class(true), nil]
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not be ready by default" do
|
it "should not be ready by default" do
|
||||||
|
|
Loading…
Reference in New Issue