Skip to content

Commit

Permalink
Merge pull request #252 from nsidc/suspend-resume
Browse files Browse the repository at this point in the history
Suspend and Resume commands
  • Loading branch information
michaeljb authored Nov 6, 2017
2 parents 1573a5b + 8050199 commit 62b5395
Show file tree
Hide file tree
Showing 17 changed files with 241 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 1.12.1
current_version = 1.13.0
tag = true
commit = true

Expand Down
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.3.5
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
language: ruby
cache: bundler
rvm:
- 2.2.3
- 2.3.5

before_install:
- rvm @global do gem uninstall bundler --all --executables
- gem uninstall bundler --all --executables
- gem install bundler --version '1.12.5'
- gem install bundler --version '1.15.4'

sudo: false
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## [1.13.0 (2017-11-06)](https://github.com/nsidc/vagrant-vsphere/releases/tag/v1.13.0)

- Add support for the commands
[`suspend`](https://www.vagrantup.com/docs/cli/suspend.html) and
[`resume`](https://www.vagrantup.com/docs/cli/resume.html).

## [1.12.1 (2017-03-07)](https://github.com/nsidc/vagrant-vsphere/releases/tag/v1.12.1)

- If no valid adapters can be found on a host when using the `real_nic_ip`
Expand Down
4 changes: 1 addition & 3 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
source 'http://rubygems.org'

gemspec

group :development do
# We depend on Vagrant for development, but we don't add it as a
# gem dependency because we expect to be installed within the
Expand All @@ -10,5 +8,5 @@ group :development do
end

group :plugins do
gem 'vagrant-vsphere', path: '.'
gemspec
end
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ This provider is built on top of the
* libxml2, libxml2-dev, libxslt, libxslt-dev

## Current Version
**version: 1.12.1**
**version: 1.13.0**

vagrant-vsphere (**version: 1.12.1**) is available from
vagrant-vsphere (**version: 1.13.0**) is available from
[RubyGems.org](https://rubygems.org/gems/vagrant-vsphere)

## Installation
Expand Down
50 changes: 50 additions & 0 deletions lib/vSphere/action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,52 @@ def self.action_reload
end
end

def self.action_resume
Vagrant::Action::Builder.new.tap do |b|
b.use ConfigValidate
b.use ConnectVSphere
b.use Call, IsCreated do |env, b2|
unless env[:result]
b2.use MessageNotCreated
next
end

b2.use Call, IsSuspended do |env2, b3|
unless env2[:result]
b3.use MessageNotSuspended
next
end

b3.use Resume
end
end
b.use CloseVSphere
end
end

def self.action_suspend
Vagrant::Action::Builder.new.tap do |b|
b.use ConfigValidate
b.use ConnectVSphere
b.use Call, IsCreated do |env, b2|
unless env[:result]
b2.use MessageNotCreated
next
end

b2.use Call, IsRunning do |env2, b3|
unless env2[:result]
b3.use MessageNotRunning
next
end

b3.use Suspend
end
end
b.use CloseVSphere
end
end

# vSphere specific actions
def self.action_get_state
Vagrant::Action::Builder.new.tap do |b|
Expand Down Expand Up @@ -259,11 +305,15 @@ def self.action_snapshot_save
autoload :GetState, action_root.join('get_state')
autoload :IsCreated, action_root.join('is_created')
autoload :IsRunning, action_root.join('is_running')
autoload :IsSuspended, action_root.join('is_suspended')
autoload :MessageAlreadyCreated, action_root.join('message_already_created')
autoload :MessageNotCreated, action_root.join('message_not_created')
autoload :MessageNotRunning, action_root.join('message_not_running')
autoload :MessageNotSuspended, action_root.join('message_not_suspended')
autoload :PowerOff, action_root.join('power_off')
autoload :PowerOn, action_root.join('power_on')
autoload :Resume, action_root.join('resume')
autoload :Suspend, action_root.join('suspend')
autoload :WaitForIPAddress, action_root.join('wait_for_ip_address')

# TODO: Remove the if guard when Vagrant 1.8.0 is the minimum version.
Expand Down
3 changes: 2 additions & 1 deletion lib/vSphere/action/get_state.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ def get_state(connection, machine)

if powered_on?(vm)
:running
elsif suspended?(vm)
:suspended
else
# If the VM is powered off or suspended, we consider it to be powered off. A power on command will either turn on or resume the VM
:poweroff
end
end
Expand Down
16 changes: 16 additions & 0 deletions lib/vSphere/action/is_suspended.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module VagrantPlugins
module VSphere
module Action
class IsSuspended
def initialize(app, _env)
@app = app
end

def call(env)
env[:result] = env[:machine].state.id == :suspended
@app.call env
end
end
end
end
end
18 changes: 18 additions & 0 deletions lib/vSphere/action/message_not_suspended.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require 'i18n'

module VagrantPlugins
module VSphere
module Action
class MessageNotSuspended
def initialize(app, _env)
@app = app
end

def call(env)
env[:ui].info I18n.t('vsphere.vm_not_suspended')
@app.call(env)
end
end
end
end
end
30 changes: 30 additions & 0 deletions lib/vSphere/action/resume.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require 'rbvmomi'
require 'i18n'
require 'vSphere/util/vim_helpers'
require 'vSphere/util/vm_helpers'

module VagrantPlugins
module VSphere
module Action
class Resume
include Util::VimHelpers
include Util::VmHelpers

def initialize(app, _env)
@app = app
end

def call(env)
vm = get_vm_by_uuid env[:vSphere_connection], env[:machine]

if suspended?(vm)
env[:ui].info I18n.t('vsphere.resume_vm')
resume_vm(vm)
end

@app.call env
end
end
end
end
end
32 changes: 32 additions & 0 deletions lib/vSphere/action/suspend.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
require 'rbvmomi'
require 'i18n'
require 'vSphere/util/vim_helpers'
require 'vSphere/util/vm_helpers'

module VagrantPlugins
module VSphere
module Action
class Suspend
include Util::VimHelpers
include Util::VmHelpers

def initialize(app, _env)
@app = app
end

def call(env)
vm = get_vm_by_uuid env[:vSphere_connection], env[:machine]

# Suspending is a no-op if we can't find the VM or it is already off
# or suspended
unless vm.nil? || suspended?(vm) || powered_off?(vm)
env[:ui].info I18n.t('vsphere.suspend_vm')
suspend_vm(vm)
end

@app.call env
end
end
end
end
end
9 changes: 9 additions & 0 deletions lib/vSphere/util/vm_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ def power_off_vm(vm)
vm.PowerOffVM_Task.wait_for_completion
end

# https://www.vmware.com/support/developer/converter-sdk/conv61_apireference/vim.VirtualMachine.html#powerOn
def resume_vm(vm)
vm.PowerOnVM_Task.wait_for_completion
end

def suspend_vm(vm)
vm.SuspendVM_Task.wait_for_completion
end

def get_vm_state(vm)
vm.runtime.powerState
end
Expand Down
2 changes: 1 addition & 1 deletion lib/vSphere/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module VagrantPlugins
module VSphere
VERSION = '1.12.1'
VERSION = '1.13.0'
end
end
6 changes: 6 additions & 0 deletions locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,18 @@ en:
Calling vSphere PowerOff
power_on_vm: |-
Calling vSphere PowerOn
resume_vm: |-
Calling vSphere PowerOn
suspend_vm: |-
Calling vSphere Suspend
vm_already_created: |-
The VM is already created
vm_not_created: |-
The VM has not been created
vm_not_running: |-
The VM is not running
vm_not_suspended: |-
The VM is not suspended
wait_sysprep: |-
Waiting for sysprep
Expand Down
62 changes: 62 additions & 0 deletions spec/action_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,66 @@ def run_get_ssh_info
VagrantPlugins::VSphere::Action::MessageAlreadyCreated.any_instance.should_receive(:call)
end
end

describe 'suspend' do
it 'should connect to vSphere' do
VagrantPlugins::VSphere::Action::ConnectVSphere.any_instance.should_receive(:call)
run :suspend
end

it 'should check if the VM exits' do
@machine.state.stub(:id).and_return(:running)
VagrantPlugins::VSphere::Action::IsCreated.any_instance.should_receive(:call)
run :suspend
end

it 'should suspend the VM when the VM is running' do
@machine.state.stub(:id).and_return(:running)
VagrantPlugins::VSphere::Action::Suspend.any_instance.should_receive(:call)
run :suspend
end

it 'should not suspend the VM when the VM is suspended' do
@machine.state.stub(:id).and_return(:suspended)
VagrantPlugins::VSphere::Action::Suspend.any_instance.should_not_receive(:call)
run :suspend
end

it 'should not suspend the VM when the VM is off' do
@machine.state.stub(:id).and_return(:poweroff)
VagrantPlugins::VSphere::Action::Suspend.any_instance.should_not_receive(:call)
run :suspend
end
end

describe 'resume' do
it 'should connect to vSphere' do
VagrantPlugins::VSphere::Action::ConnectVSphere.any_instance.should_receive(:call)
run :resume
end

it 'should check if the VM exits' do
@machine.state.stub(:id).and_return(:suspended)
VagrantPlugins::VSphere::Action::IsCreated.any_instance.should_receive(:call)
run :resume
end

it 'should not resume the VM when the VM is running' do
@machine.state.stub(:id).and_return(:running)
VagrantPlugins::VSphere::Action::Resume.any_instance.should_not_receive(:call)
run :resume
end

it 'should resume the VM when the VM is suspended' do
@machine.state.stub(:id).and_return(:suspended)
VagrantPlugins::VSphere::Action::Resume.any_instance.should_receive(:call)
run :resume
end

it 'should not resume the VM when the VM is off' do
@machine.state.stub(:id).and_return(:poweroff)
VagrantPlugins::VSphere::Action::Resume.any_instance.should_not_receive(:call)
run :resume
end
end
end
4 changes: 2 additions & 2 deletions spec/get_state_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@
expect(@env[:machine_state_id]).to be :poweroff
end

it 'should set state id to powered off if machine is suspended' do
it 'should set state id to suspended if machine is suspended' do
@env[:machine].stub(:id).and_return(EXISTING_UUID)
@vm.runtime.stub(:powerState).and_return(VagrantPlugins::VSphere::Util::VmState::SUSPENDED)

call

expect(@env[:machine_state_id]).to be :poweroff
expect(@env[:machine_state_id]).to be :suspended
end

it 'should call the next item in the middleware stack' do
Expand Down

0 comments on commit 62b5395

Please sign in to comment.