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_mac = "42"
|
||||
config.vm.project_directory = "/hobo"
|
||||
config.vm.disk_image_format = 'VMDK'
|
||||
config.vm.forward_port("ssh", 22, 2222)
|
||||
|
||||
config.chef.cookbooks_path = "cookbooks"
|
||||
|
@ -44,6 +45,12 @@ class Test::Unit::TestCase
|
|||
}
|
||||
end
|
||||
|
||||
if block_given?
|
||||
Vagrant::Config.run do |config|
|
||||
yield config
|
||||
end
|
||||
end
|
||||
|
||||
Vagrant::Config.execute!
|
||||
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