providers/hyperv: suspend/resume

This commit is contained in:
Mitchell Hashimoto 2014-02-26 17:41:02 -08:00
parent ef71729c24
commit e93038fd0e
11 changed files with 210 additions and 6 deletions

View File

@ -20,7 +20,9 @@ module Vagrant
autoload :HandleBox, "vagrant/action/builtin/handle_box"
autoload :HandleBoxUrl, "vagrant/action/builtin/handle_box_url"
autoload :HandleForwardedPortCollisions, "vagrant/action/builtin/handle_forwarded_port_collisions"
autoload :IsState, "vagrant/action/builtin/is_state"
autoload :Lock, "vagrant/action/builtin/lock"
autoload :Message, "vagrant/action/builtin/message"
autoload :Provision, "vagrant/action/builtin/provision"
autoload :ProvisionerCleanup, "vagrant/action/builtin/provisioner_cleanup"
autoload :SetHostname, "vagrant/action/builtin/set_hostname"

View File

@ -0,0 +1,30 @@
module Vagrant
module Action
module Builtin
# This middleware is meant to be used with Call and can check if
# a machine is in the given state ID.
class IsState
# Note: Any of the arguments can be arrays as well.
#
# @param [Symbol] target_state The target state ID that means that
# the machine was properly shut down.
# @param [Symbol] source_state The source state ID that the machine
# must be in to be shut down.
def initialize(app, env, check, **opts)
@app = app
@logger = Log4r::Logger.new("vagrant::action::builtin::is_state")
@check = check
end
def call(env)
@logger.debug("Checking if machine state is '#{@check}'")
state = env[:machine].state.id
@logger.debug("-- Machine state: #{state}")
env[:result] = @check == state
@app.call(env)
end
end
end
end
end

View File

@ -0,0 +1,19 @@
module Vagrant
module Action
module Builtin
# This middleware simply outputs a message to the UI.
class Message
def initialize(app, env, message, **opts)
@app = app
@logger = Log4r::Logger.new("vagrant::action::builtin::is_state")
@message = message
end
def call(env)
env[:ui].output(@message)
@app.call(env)
end
end
end
end
end

View File

@ -63,13 +63,44 @@ module VagrantPlugins
end
end
def self.action_resume
Vagrant::Action::Builder.new.tap do |b|
b.use HandleBox
b.use ConfigValidate
b.use Call, IsCreated do |env1, b1|
if !env1[:result]
b1.use Message, I18n.t("vagrant_hyperv.message_not_created")
next
end
b1.use ResumeVM
b1.use WaitForIPAddress
b1.use WaitForCommunicator, [:running]
end
end
end
def self.action_start
Vagrant::Action::Builder.new.tap do |b|
b.use Provision
b.use StartInstance
b.use WaitForIPAddress
b.use WaitForCommunicator, [:running]
b.use SyncedFolders
b.use Call, IsState, :running do |env1, b1|
if env1[:result]
b1.use Message, I18n.t("vagrant_hyperv.message_already_running")
next
end
b1.use Call, IsState, :paused do |env2, b2|
if env2[:result]
b2.use action_resume
next
end
b2.use Provision
b2.use StartInstance
b2.use WaitForIPAddress
b2.use WaitForCommunicator, [:running]
b2.use SyncedFolders
end
end
end
end
@ -113,6 +144,20 @@ module VagrantPlugins
end
end
def self.action_suspend
Vagrant::Action::Builder.new.tap do |b|
b.use ConfigValidate
b.use Call, IsCreated do |env, b2|
if !env[:result]
b2.use MessageNotCreated
next
end
b2.use SuspendVM
end
end
end
def self.action_read_guest_ip
Vagrant::Action::Builder.new.tap do |b|
b.use ConfigValidate
@ -126,10 +171,12 @@ module VagrantPlugins
autoload :DeleteVM, action_root.join("delete_vm")
autoload :IsCreated, action_root.join("is_created")
autoload :IsStopped, action_root.join("is_stopped")
autoload :ReadState, action_root.join("read_state")
autoload :Import, action_root.join("import")
autoload :ReadState, action_root.join("read_state")
autoload :ResumeVM, action_root.join("resume_vm")
autoload :StartInstance, action_root.join('start_instance')
autoload :StopInstance, action_root.join('stop_instance')
autoload :SuspendVM, action_root.join("suspend_vm")
autoload :MessageNotCreated, action_root.join('message_not_created')
autoload :MessageAlreadyCreated, action_root.join('message_already_created')
autoload :MessageNotRunning, action_root.join('message_not_running')

View File

@ -0,0 +1,18 @@
module VagrantPlugins
module HyperV
module Action
class ResumeVM
def initialize(app, env)
@app = app
end
def call(env)
env[:ui].info("Resuming the machine...")
options = { VmId: env[:machine].id }
env[:machine].provider.driver.execute("resume_vm.ps1", options)
@app.call(env)
end
end
end
end
end

View File

@ -0,0 +1,18 @@
module VagrantPlugins
module HyperV
module Action
class SuspendVM
def initialize(app, env)
@app = app
end
def call(env)
env[:ui].info("Suspending the machine...")
options = { VmId: env[:machine].id }
env[:machine].provider.driver.execute("suspend_vm.ps1", options)
@app.call(env)
end
end
end
end
end

View File

@ -0,0 +1,7 @@
Param(
[Parameter(Mandatory=$true)]
[string]$VmId
)
$VM = Get-VM -Id $VmId -ErrorAction "Stop"
Resume-VM $VM

View File

@ -0,0 +1,7 @@
Param(
[Parameter(Mandatory=$true)]
[string]$VmId
)
$VM = Get-VM -Id $VmId -ErrorAction "Stop"
Suspend-VM $VM

View File

@ -1,5 +1,10 @@
en:
vagrant_hyperv:
message_already_running: |-
Hyper-V instance already running.
message_not_created: |-
VM not created. Moving on...
errors:
admin_required: |-
The Hyper-V provider requires that Vagrant be run with

View File

@ -0,0 +1,29 @@
require "pathname"
require "tmpdir"
require File.expand_path("../../../../base", __FILE__)
describe Vagrant::Action::Builtin::IsState do
let(:app) { lambda { |env| } }
let(:env) { { :machine => machine } }
let(:machine) do
double("machine").tap do |machine|
machine.stub(:state).and_return(state)
end
end
let(:state) { double("state") }
describe "#call" do
it "sets result to true if is proper state" do
state.stub(id: :foo)
subject = described_class.new(app, env, :foo)
app.should_receive(:call).with(env)
subject.call(env)
expect(env[:result]).to be_true
end
end
end

View File

@ -0,0 +1,22 @@
require "pathname"
require "tmpdir"
require File.expand_path("../../../../base", __FILE__)
describe Vagrant::Action::Builtin::Message do
let(:app) { lambda { |env| } }
let(:env) { { :ui => ui } }
let(:ui) { double("ui") }
describe "#call" do
it "outputs the given message" do
subject = described_class.new(app, env, "foo")
ui.should_receive(:output).with("foo")
app.should_receive(:call).with(env)
subject.call(env)
end
end
end