unpackage added, still uses zlib

This commit is contained in:
John Bender 2010-02-17 15:34:54 -08:00
parent 8d9e53fe27
commit a690b13f78
11 changed files with 146 additions and 84 deletions

View File

@ -1,11 +1,18 @@
module Vagrant module Vagrant
module Actions module Actions
class Import < Base class Import < Base
#First arg should be the ovf_file location for import
def initialize(vm, *args)
super vm
@ovf_file = args[0]
end
def execute! def execute!
@vm.invoke_around_callback(:import) do @vm.invoke_around_callback(:import) do
Busy.busy do Busy.busy do
logger.info "Importing base VM (#{Vagrant.config[:vm][:base]})..." logger.info "Importing base VM (#{Vagrant.config[:vm][:base]})..."
@vm.vm = VirtualBox::VM.import(File.expand_path(Vagrant.config[:vm][:base])) # Use the first argument passed to the action
@vm.vm = VirtualBox::VM.import(@ovf_file || File.expand_path(Vagrant.config[:vm][:base]))
end end
end end
end end

View File

@ -12,9 +12,17 @@ error
destroy_drive_after { clone_and_attach } destroy_drive_after { clone_and_attach }
end end
# TODO: Better way to detect main bootup drive?
def hard_drive def hard_drive
@vm.storage_controllers.first.devices.first @hard_drive ||= find_hard_drive
end
# TODO won't work if the first disk is not the boot disk or even if there are multiple disks
def find_hard_drive
@vm.storage_controllers.each do |sc|
sc.devices.each do |d|
return d if d.image.is_a?(VirtualBox::HardDrive)
end
end
end end
def clone_and_attach def clone_and_attach

View File

@ -19,7 +19,7 @@ module Vagrant
Zlib::GzipWriter.open(compressed_file_name) do |gz| Zlib::GzipWriter.open(compressed_file_name) do |gz|
files_to_compress.each do |file| files_to_compress.each do |file|
# Delimit the files, and guarantee new line for next file if not the first # Delimit the files, and guarantee new line for next file if not the first
gz.write "#{delimiter}#{file}#{delimiter}" gz.write "#{delimiter}#{File.basename(file)}#{delimiter}"
File.open(file).each { |line| gz.write(line) } File.open(file).each { |line| gz.write(line) }
end end
end end

View File

@ -0,0 +1,71 @@
module Vagrant
module Actions
class Unpackage < Base
def initialize(vm, *args)
super vm
@package_file_path = args[0]
end
def execute!
# Exit if folder of same name exists
# TODO provide a way for them to specify the directory name
error_and_exit(<<-error) if File.exists?(new_base_dir)
The directory `#{file_name_without_extension}` already exists under #{Vagrant.config[:vagrant][:home]}. Please
remove it, rename your packaged VM file, or (TODO) specifiy an
alternate directory
error
logger.info "Creating working new base directory: #{new_base_dir} ..."
FileUtils.mkpath(new_base_dir)
logger.info "Decompressing the packaged VM: #{package_file_path} to: #{new_base_dir}..."
decompress_to new_base_dir
#Return the ovf file for importation
Dir["#{new_base_dir}/*.ovf"].first
end
def new_base_dir
File.join(Vagrant.config[:vagrant][:home], file_name_without_extension)
end
def file_name_without_extension
File.basename(package_file_path, '.*')
end
def package_file_path
File.expand_path(@package_file_path)
end
def decompress_to(dir, file_delimeter=Vagrant.config[:package][:delimiter_regex])
file = nil
Zlib::GzipReader.open(package_file_path) do |gz|
begin
gz.each_line do |line|
# If the line is a file delimiter create new file and write to it
if line =~ file_delimeter
#Write the the part of the line belonging to the previous file
if file
file.write $1
file.close
end
#Open a new file with the name contained in the delimiter
file = File.open(File.join(dir, $2), 'w')
#Write the rest of the line to the new file
file.write $3
else
file.write line
end
end
ensure
file.close if file
end
end
end
end
end
end

View File

@ -1,12 +1,20 @@
module Vagrant module Vagrant
module Actions module Actions
class Up < Base class Up < Base
#First arg should be the ovf_file location for import
def initialize(vm, *args)
super vm
@ovf_file = args[0]
end
def prepare def prepare
# Up is a "meta-action" so it really just queues up a bunch # Up is a "meta-action" so it really just queues up a bunch
# of other actions in its place: # of other actions in its place:
steps = [Import, ForwardPorts, SharedFolders, Start] @vm.add_action(Import, @ovf_file)
steps = [ForwardPorts, SharedFolders, Start]
steps << Provision if Vagrant.config.chef.enabled steps << Provision if Vagrant.config.chef.enabled
steps.insert(1, MoveHardDrive) if Vagrant.config.vm.hd_location steps.insert(0, MoveHardDrive) if Vagrant.config.vm.hd_location
steps.each do |action_klass| steps.each do |action_klass|
@vm.add_action(action_klass) @vm.add_action(action_klass)

View File

@ -130,12 +130,11 @@ error
error_and_exit(<<-error) unless name error_and_exit(<<-error) unless name
Please specify a target package to unpack and import Please specify a target package to unpack and import
error error
VM.up(VM.unpackage(name))
VM.execute!(Actions::Up, VM.execute!(Actions::Unpackage, name))
end end
private private
def act_on_vm(&block) def act_on_vm(&block)
yield Env.persisted_vm yield Env.persisted_vm
Env.persisted_vm.execute! Env.persisted_vm.execute!

View File

@ -14,62 +14,6 @@ module Vagrant
vm.execute! vm.execute!
end end
# Unpack the specified vm package
def unpackage(package_path)
working_dir = package_path.chomp(File.extname(package_path))
new_base_dir = File.join(Vagrant.config[:vagrant][:home], File.basename(package_path, '.*'))
# Exit if folder of same name exists
# TODO provide a way for them to specify the directory name
error_and_exit(<<-error) if File.exists?(new_base_dir)
The directory `#{File.basename(package_path, '.*')}` already exists under #{Vagrant.config[:vagrant][:home]}. Please
remove it, rename your packaged VM file, or (TODO) specifiy an
alternate directory
error
logger.info "Creating working dir: #{working_dir} ..."
FileUtils.mkpath(working_dir)
logger.info "Decompressing the packaged VM: #{package_path} ..."
decompress(package_path, working_dir)
logger.info "Moving the unpackaged VM to #{new_base_dir} ..."
FileUtils.mv(working_dir, Vagrant.config[:vagrant][:home])
#Return the ovf file for importation
Dir["#{new_base_dir}/*.ovf"].first
end
def decompress(path, dir, file_delimeter=Vagrant.config[:package][:delimiter_regex])
file = nil
Zlib::GzipReader.open(path) do |gz|
begin
gz.each_line do |line|
# If the line is a file delimiter create new file and write to it
if line =~ file_delimeter
#Write the the part of the line belonging to the previous file
if file
file.write $1
file.close
end
#Open a new file with the name contained in the delimiter
file = File.open(File.join(dir, $2), 'w')
#Write the rest of the line to the new file
file.write $3
else
file.write line
end
end
ensure
file.close if file
end
end
end
# Finds a virtual machine by a given UUID and either returns # Finds a virtual machine by a given UUID and either returns
# a Vagrant::VM object or returns nil. # a Vagrant::VM object or returns nil.
def find(uuid) def find(uuid)
@ -96,11 +40,13 @@ error
# Call the prepare method on each once its # Call the prepare method on each once its
# initialized, then call the execute! method # initialized, then call the execute! method
return_value = nil
[:prepare, :execute!].each do |method| [:prepare, :execute!].each do |method|
@actions.each do |action| @actions.each do |action|
action.send(method) return_value = action.send(method)
end end
end end
return_value
end end
# Invokes an "around callback" which invokes before_name and # Invokes an "around callback" which invokes before_name and
@ -141,5 +87,7 @@ error
def powered_off?; @vm.powered_off? end def powered_off?; @vm.powered_off? end
def export(filename); @vm.export(filename, {}, true) end def export(filename); @vm.export(filename, {}, true) end
def storage_controllers; @vm.storage_controllers end
end end
end end

View File

@ -10,6 +10,21 @@ class MoveHardDriveActionTest < Test::Unit::TestCase
end end
end end
should "be able to identifiy a hard drive within the storage controllers" do
hd = mock('hd')
hd_image = mock('hd_image')
hd_image.expects(:is_a?).returns(true)
hd.expects(:image).returns(hd_image)
dvd = mock('dvd')
controller = mock('controller')
controller.expects(:devices).returns([hd, dvd])
@mock_vm.expects(:storage_controllers).once.returns([controller])
assert_equal @action.find_hard_drive, hd
end
context "execution" do context "execution" do
should "error and exit if the vm is not powered off" do should "error and exit if the vm is not powered off" do
@mock_vm.expects(:powered_off?).returns(false) @mock_vm.expects(:powered_off?).returns(false)

View File

@ -0,0 +1,19 @@
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
class UnpackageActionTest < Test::Unit::TestCase
setup do
@wrapper_vm, @vm, @action = mock_action(Vagrant::Actions::Unpackage)
mock_config
end
# TODO test actual decompression
should "call decompress with the path to the file and the directory to decompress to" do
new_base_dir = File.join Vagrant.config[:vagrant][:home], 'something'
file = File.join(FileUtils.pwd, 'something.box')
FileUtils.expects(:mkpath).with(new_base_dir).once
Dir.expects(:[]).returns(File.join new_base_dir, 'something.ovf')
@action.expects(:decompress_to).with(new_base_dir).once
@action.stubs(:package_file_path).returns(file)
@action.execute!
end
end

View File

@ -8,11 +8,12 @@ class UpActionTest < Test::Unit::TestCase
context "sub-actions" do context "sub-actions" do
setup do setup do
@default_order = [Vagrant::Actions::Import, Vagrant::Actions::ForwardPorts, Vagrant::Actions::SharedFolders, Vagrant::Actions::Start] @default_order = [Vagrant::Actions::ForwardPorts, Vagrant::Actions::SharedFolders, Vagrant::Actions::Start]
end end
def setup_action_expectations def setup_action_expectations
default_seq = sequence("default_seq") default_seq = sequence("default_seq")
@mock_vm.expects(:add_action).with(Vagrant::Actions::Import, nil).once.in_sequence(default_seq)
@default_order.each do |action| @default_order.each do |action|
@mock_vm.expects(:add_action).with(action).once.in_sequence(default_seq) @mock_vm.expects(:add_action).with(action).once.in_sequence(default_seq)
end end
@ -39,7 +40,7 @@ class UpActionTest < Test::Unit::TestCase
config.vm.hd_location = "foo" config.vm.hd_location = "foo"
end end
@default_order.insert(1, Vagrant::Actions::MoveHardDrive) @default_order.insert(0, Vagrant::Actions::MoveHardDrive)
setup_action_expectations setup_action_expectations
@action.prepare @action.prepare
end end

View File

@ -197,18 +197,4 @@ class VMTest < Test::Unit::TestCase
end end
end end
end end
context "unpackaging a vm" do
# TODO test actual decompression
should "call decompress with the path to the file and the directory to decompress to" do
working_dir = File.join FileUtils.pwd, 'something'
file = File.join(FileUtils.pwd, 'something.box')
FileUtils.expects(:mkpath).with(working_dir).once
FileUtils.expects(:mv).with(working_dir, Vagrant.config[:vagrant][:home]).once
Vagrant::VM.expects(:decompress).with(file, working_dir).once
Vagrant::VM.unpackage(file)
end
end
end end