Move hard drive action.
This commit is contained in:
parent
ddfbe13b1d
commit
1753d97d45
|
@ -0,0 +1,43 @@
|
||||||
|
module Vagrant
|
||||||
|
module Actions
|
||||||
|
class MoveHardDrive < Base
|
||||||
|
def execute!
|
||||||
|
unless @vm.powered_off?
|
||||||
|
error_and_exit(<<-error)
|
||||||
|
The virtual machine must be powered off to move its disk.
|
||||||
|
error
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
destroy_drive_after { clone_and_attach }
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO: Better way to detect main bootup drive?
|
||||||
|
def hard_drive
|
||||||
|
@vm.storage_controllers.first.devices.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def clone_and_attach
|
||||||
|
logger.info "Cloning current VM Disk to new location (#{new_image_path})..."
|
||||||
|
hard_drive.image = hard_drive.image.clone(new_image_path, Vagrant.config.vm.disk_image_format, true)
|
||||||
|
|
||||||
|
logger.info "Attaching new disk to VM ..."
|
||||||
|
@vm.vm.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy_drive_after
|
||||||
|
old_image = hard_drive.image
|
||||||
|
|
||||||
|
yield
|
||||||
|
|
||||||
|
logger.info "Destroying old VM Disk (#{old_image.filename})..."
|
||||||
|
old_image.destroy(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the path to the new location for the hard drive
|
||||||
|
def new_image_path
|
||||||
|
File.join(Vagrant.config.vm.hd_location, hard_drive.image.filename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -35,6 +35,7 @@ class Test::Unit::TestCase
|
||||||
config.vm.base = "foo"
|
config.vm.base = "foo"
|
||||||
config.vm.base_mac = "42"
|
config.vm.base_mac = "42"
|
||||||
config.vm.project_directory = "/hobo"
|
config.vm.project_directory = "/hobo"
|
||||||
|
config.vm.disk_image_format = 'VMDK'
|
||||||
config.vm.forward_port("ssh", 22, 2222)
|
config.vm.forward_port("ssh", 22, 2222)
|
||||||
|
|
||||||
config.chef.cookbooks_path = "cookbooks"
|
config.chef.cookbooks_path = "cookbooks"
|
||||||
|
@ -44,6 +45,12 @@ class Test::Unit::TestCase
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if block_given?
|
||||||
|
Vagrant::Config.run do |config|
|
||||||
|
yield config
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Vagrant::Config.execute!
|
Vagrant::Config.execute!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
||||||
|
|
||||||
|
class MoveHardDriveActionTest < Test::Unit::TestCase
|
||||||
|
setup do
|
||||||
|
@mock_vm, @vm, @action = mock_action(Vagrant::Actions::MoveHardDrive)
|
||||||
|
@hd_location = "/foo"
|
||||||
|
mock_config do |config|
|
||||||
|
File.expects(:directory?).with(@hd_location).returns(true)
|
||||||
|
config.vm.hd_location = @hd_location
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "execution" do
|
||||||
|
should "error and exit if the vm is not powered off" do
|
||||||
|
@mock_vm.expects(:powered_off?).returns(false)
|
||||||
|
@action.expects(:error_and_exit).once
|
||||||
|
@action.execute!
|
||||||
|
end
|
||||||
|
|
||||||
|
should "move the hard drive if vm is powered off" do
|
||||||
|
@mock_vm.expects(:powered_off?).returns(true)
|
||||||
|
@action.expects(:error_and_exit).never
|
||||||
|
@action.expects(:destroy_drive_after).once
|
||||||
|
@action.execute!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "new image path" do
|
||||||
|
setup do
|
||||||
|
@hd = mock("hd")
|
||||||
|
@image = mock("image")
|
||||||
|
@filename = "foo"
|
||||||
|
@hd.stubs(:image).returns(@image)
|
||||||
|
@image.stubs(:filename).returns(@filename)
|
||||||
|
@action.stubs(:hard_drive).returns(@hd)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "be the configured hd location and the existing hard drive filename" do
|
||||||
|
joined = File.join(Vagrant.config.vm.hd_location, @filename)
|
||||||
|
assert_equal joined, @action.new_image_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "cloning and attaching new image" do
|
||||||
|
setup do
|
||||||
|
@hd = mock("hd")
|
||||||
|
@image = mock("image")
|
||||||
|
@hd.stubs(:image).returns(@image)
|
||||||
|
@action.stubs(:hard_drive).returns(@hd)
|
||||||
|
@new_image_path = "foo"
|
||||||
|
@action.stubs(:new_image_path).returns(@new_image_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "clone to the new path" do
|
||||||
|
new_image = mock("new_image")
|
||||||
|
@image.expects(:clone).with(@new_image_path, Vagrant.config.vm.disk_image_format, true).returns(new_image).once
|
||||||
|
@hd.expects(:image=).with(new_image).once
|
||||||
|
@vm.expects(:save).once
|
||||||
|
@action.clone_and_attach
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "destroying the old image" do
|
||||||
|
setup do
|
||||||
|
@hd = mock("hd")
|
||||||
|
@action.stubs(:hard_drive).returns(@hd)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "yield the block, and destroy the old image after" do
|
||||||
|
image = mock("image")
|
||||||
|
image.stubs(:filename).returns("foo")
|
||||||
|
destroy_seq = sequence("destroy_seq")
|
||||||
|
@hd.expects(:image).returns(image).in_sequence(destroy_seq)
|
||||||
|
@hd.expects(:foo).once.in_sequence(destroy_seq)
|
||||||
|
image.expects(:destroy).with(true).once.in_sequence(destroy_seq)
|
||||||
|
|
||||||
|
@action.destroy_drive_after { @hd.foo }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Ensures that the image is not destroyed in an "ensure" block
|
||||||
|
should "not destroy the image if an exception is raised" do
|
||||||
|
image = mock("image")
|
||||||
|
image.expects(:destroy).never
|
||||||
|
@hd.expects(:image).returns(image)
|
||||||
|
|
||||||
|
assert_raises(Exception) do
|
||||||
|
@action.destroy_drive_after do
|
||||||
|
raise Exception.new("FOO")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue