This involved defaulting all box searching at the moment to VirtualBox. Additionally, box upgrading is not yet handled. This needs to be done at some point.
206 lines
5.0 KiB
Ruby
206 lines
5.0 KiB
Ruby
require 'log4r'
|
|
|
|
module Vagrant
|
|
class VM
|
|
include Vagrant::Util
|
|
|
|
attr_reader :uuid
|
|
attr_reader :env
|
|
attr_reader :name
|
|
attr_reader :vm
|
|
attr_reader :box
|
|
attr_reader :config
|
|
attr_reader :driver
|
|
|
|
def initialize(name, env, config, opts=nil)
|
|
@logger = Log4r::Logger.new("vagrant::vm")
|
|
|
|
@name = name
|
|
@vm = nil
|
|
@env = env
|
|
@config = config
|
|
@box = nil
|
|
@box = env.boxes.find(config.vm.box, :virtualbox) if config.vm.box
|
|
|
|
opts ||= {}
|
|
if opts[:base]
|
|
# The name is the ID we use.
|
|
@uuid = name
|
|
else
|
|
# Load the UUID if its saved.
|
|
active = env.local_data[:active] || {}
|
|
@uuid = active[@name.to_s]
|
|
end
|
|
|
|
# Reload ourselves to get the state
|
|
reload!
|
|
|
|
# Load the associated guest.
|
|
load_guest!
|
|
@loaded_guest_distro = false
|
|
end
|
|
|
|
# Loads the guest associated with the VM. The guest class is
|
|
# responsible for OS-specific functionality. More information
|
|
# can be found by reading the documentation on {Vagrant::Guest::Base}.
|
|
#
|
|
# **This method should never be called manually.**
|
|
def load_guest!(guest=nil)
|
|
guest ||= config.vm.guest
|
|
@logger.info("Loading guest: #{guest}")
|
|
|
|
if guest.is_a?(Class)
|
|
raise Errors::VMGuestError, :_key => :invalid_class, :guest => guest.to_s if !(guest <= Vagrant.plugin("1", :guest))
|
|
@guest = guest.new(self)
|
|
elsif guest.is_a?(Symbol)
|
|
# Look for the guest as a registered plugin
|
|
guest_klass = nil
|
|
Vagrant.plugin("1").registered.each do |plugin|
|
|
if plugin.guest.has_key?(guest)
|
|
guest_klass = plugin.guest[guest]
|
|
break
|
|
end
|
|
end
|
|
|
|
raise Errors::VMGuestError, :_key => :unknown_type, :guest => guest.to_s if !guest_klass
|
|
@guest = guest_klass.new(self)
|
|
else
|
|
raise Errors::VMGuestError, :unspecified
|
|
end
|
|
end
|
|
|
|
# Returns a channel object to communicate with the virtual
|
|
# machine.
|
|
def channel
|
|
@channel ||= Communication::SSH.new(self)
|
|
end
|
|
|
|
# Returns the guest for this VM, loading the distro of the system if
|
|
# we can.
|
|
def guest
|
|
if !@loaded_guest_distro && state == :running
|
|
# Load the guest distro for the first time
|
|
result = @guest.distro_dispatch
|
|
load_guest!(result)
|
|
@loaded_guest_distro = true
|
|
@logger.info("Guest class: #{@guest.class}")
|
|
end
|
|
|
|
@guest
|
|
end
|
|
|
|
# Access the {Vagrant::SSH} object associated with this VM, which
|
|
# is used to get SSH credentials with the virtual machine.
|
|
def ssh
|
|
@ssh ||= SSH.new(self)
|
|
end
|
|
|
|
# Returns the state of the VM as a symbol.
|
|
#
|
|
# @return [Symbol]
|
|
def state
|
|
return :not_created if !@uuid
|
|
state = @driver.read_state
|
|
return :not_created if !state
|
|
return state
|
|
end
|
|
|
|
# Returns a boolean true if the VM has been created, otherwise
|
|
# returns false.
|
|
#
|
|
# @return [Boolean]
|
|
def created?
|
|
state != :not_created
|
|
end
|
|
|
|
# Sets the currently active VM for this VM. If the VM is a valid,
|
|
# created virtual machine, then it will also update the local data
|
|
# to persist the VM. Otherwise, it will remove itself from the
|
|
# local data (if it exists).
|
|
def uuid=(value)
|
|
env.local_data[:active] ||= {}
|
|
if value
|
|
env.local_data[:active][name.to_s] = value
|
|
else
|
|
env.local_data[:active].delete(name.to_s)
|
|
end
|
|
|
|
# Commit the local data so that the next time vagrant is initialized,
|
|
# it realizes the VM exists
|
|
env.local_data.commit
|
|
|
|
# Store the uuid and reload the instance
|
|
@uuid = value
|
|
reload!
|
|
end
|
|
|
|
def reload!
|
|
begin
|
|
@driver = Driver::VirtualBox.new(@uuid)
|
|
rescue Driver::VirtualBox::VMNotFound
|
|
# Clear the UUID since this VM doesn't exist.
|
|
@uuid = nil
|
|
|
|
# Reset the driver. This shouldn't raise a VMNotFound since we won't
|
|
# feed it a UUID.
|
|
@driver = Driver::VirtualBox.new
|
|
end
|
|
end
|
|
|
|
def package(options=nil)
|
|
run_action(:package, { "validate" => false }.merge(options || {}))
|
|
end
|
|
|
|
def up(options=nil)
|
|
run_action(:up, options)
|
|
end
|
|
|
|
def start(options=nil)
|
|
return if state == :running
|
|
return resume if state == :saved
|
|
|
|
run_action(:start, options)
|
|
end
|
|
|
|
def halt(options=nil)
|
|
run_action(:halt, options)
|
|
end
|
|
|
|
def reload(options=nil)
|
|
run_action(:reload, options)
|
|
end
|
|
|
|
def provision
|
|
run_action(:provision)
|
|
end
|
|
|
|
def destroy
|
|
run_action(:destroy)
|
|
end
|
|
|
|
def suspend
|
|
run_action(:suspend)
|
|
end
|
|
|
|
def resume
|
|
run_action(:resume)
|
|
end
|
|
|
|
def ui
|
|
return @_ui if defined?(@_ui)
|
|
@_ui = @env.ui.dup
|
|
@_ui.resource = @name
|
|
@_ui
|
|
end
|
|
|
|
def run_action(name, options=nil)
|
|
options = {
|
|
:vm => self,
|
|
:ui => ui
|
|
}.merge(options || {})
|
|
|
|
env.action_runner.run(name, options)
|
|
end
|
|
end
|
|
end
|