packaging and unpackaging
This commit is contained in:
parent
8f63272403
commit
c9d0d0d9d9
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env ruby
|
||||
begin
|
||||
require File.expand_path('../../.bundle/environment', __FILE__)
|
||||
rescue LoadError
|
||||
# Fallback on rubygems
|
||||
require "rubygems"
|
||||
end
|
||||
|
||||
require 'git-style-binary/command'
|
||||
|
||||
# Get library
|
||||
libdir = File.join(File.dirname(__FILE__), '..', 'lib')
|
||||
$:.unshift(libdir) unless $:.include?(libdir)
|
||||
require 'vagrant'
|
||||
|
||||
GitStyleBinary.command do
|
||||
short_desc "unpackage a vagrant environment"
|
||||
banner <<-EOS
|
||||
Usage: #{command.full_name} #{all_options_string}
|
||||
|
||||
Unpackage a vagrant environment
|
||||
|
||||
EOS
|
||||
run do |command|
|
||||
Vagrant::Commands.unpackage(command.argv[0])
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
Vagrant::Config.run do |config|
|
||||
# default config goes here
|
||||
config.vagrant.log_output = STDOUT
|
||||
config.vagrant.home = "~/.vagrant"
|
||||
|
||||
config.ssh.username = "vagrant"
|
||||
config.ssh.password = "vagrant"
|
||||
|
@ -17,6 +18,8 @@ Vagrant::Config.run do |config|
|
|||
config.vm.disk_image_format = 'VMDK'
|
||||
|
||||
config.package.name = 'vagrant'
|
||||
config.package.delimiter = 'VAGRANT'
|
||||
config.package.delimiter_regex = /(.*)#{config.package.delimiter}(.+)#{config.package.delimiter}(.*[\n\r])/
|
||||
|
||||
config.chef.cookbooks_path = "cookbooks"
|
||||
config.chef.provisioning_path = "/tmp/vagrant-chef"
|
||||
|
|
|
@ -109,6 +109,14 @@ The vagrant virtual environment you are trying to package must be powered off
|
|||
error
|
||||
Env.persisted_vm.package(name || Vagrant.config[:package][:name], FileUtils.pwd)
|
||||
end
|
||||
|
||||
def unpackage(name)
|
||||
Env.load!
|
||||
error_and_exit(<<-error) unless name
|
||||
Please specify a target package to unpack and import
|
||||
error
|
||||
VM.up(VM.unpackage(name))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -70,10 +70,16 @@ module Vagrant
|
|||
raise Exception.new "disk_storage must be set to a directory" unless File.directory?(val)
|
||||
@hd_location=val
|
||||
end
|
||||
|
||||
def base
|
||||
File.expand_path(@base)
|
||||
end
|
||||
end
|
||||
|
||||
class PackageConfig < Base
|
||||
attr_accessor :name
|
||||
attr_accessor :delimiter
|
||||
attr_accessor :delimiter_regex
|
||||
end
|
||||
|
||||
class ChefConfig < Base
|
||||
|
@ -84,6 +90,11 @@ module Vagrant
|
|||
|
||||
class VagrantConfig < Base
|
||||
attr_accessor :log_output
|
||||
attr_accessor :home
|
||||
|
||||
def home
|
||||
File.expand_path(@home)
|
||||
end
|
||||
end
|
||||
|
||||
class Top < Base
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module Vagrant
|
||||
module Util
|
||||
def self.included?(base)
|
||||
def self.included(base)
|
||||
base.extend Vagrant::Util
|
||||
end
|
||||
|
||||
|
|
|
@ -2,12 +2,71 @@ module Vagrant
|
|||
class VM
|
||||
include Vagrant::Util
|
||||
attr_reader :vm
|
||||
attr_accessor :from
|
||||
|
||||
class << self
|
||||
# Bring up the virtual machine. Imports the base image and
|
||||
# provisions it.
|
||||
def up
|
||||
new.create
|
||||
def up(from=Vagrant.config[:vm][:base])
|
||||
vm = new
|
||||
vm.from = from
|
||||
vm.create
|
||||
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
|
||||
|
@ -76,7 +135,7 @@ error
|
|||
|
||||
def import
|
||||
logger.info "Importing base VM (#{Vagrant.config[:vm][:base]})..."
|
||||
@vm = VirtualBox::VM.import(File.expand_path(Vagrant.config[:vm][:base]))
|
||||
@vm = VirtualBox::VM.import(@from)
|
||||
end
|
||||
|
||||
def persist
|
||||
|
@ -173,6 +232,7 @@ error
|
|||
|
||||
# TODO the longest method, needs to be split up
|
||||
def package(name, to)
|
||||
delimiter = Vagrant.config[:package][:delimiter]
|
||||
folder = FileUtils.mkpath(File.join(to, name))
|
||||
logger.info "Creating working directory: #{folder} ..."
|
||||
|
||||
|
@ -182,17 +242,15 @@ error
|
|||
logger.info "Exporting required VM files to working directory ..."
|
||||
@vm.export(ovf_path)
|
||||
|
||||
# TODO use zlib ...
|
||||
logger.info "Packaging VM into #{name}.box ..."
|
||||
Tar.open(tar_path, File::CREAT | File::WRONLY, 0644, Tar::GNU) do |tar|
|
||||
begin
|
||||
# appending the expanded file path adds the whole folder tree
|
||||
# to the tar archive there must be a better way
|
||||
working_dir = FileUtils.pwd
|
||||
FileUtils.cd(to)
|
||||
tar.append_tree(name)
|
||||
ensure
|
||||
FileUtils.cd(working_dir)
|
||||
logger.info "Packaging VM into #{tar_path} ..."
|
||||
Zlib::GzipWriter.open(tar_path) do |gz|
|
||||
first_file = true
|
||||
Dir.new(folder).each do |file|
|
||||
next if File.directory?(file)
|
||||
# Delimit the files, and guarantee new line for next file if not the first
|
||||
gz.write "#{delimiter}#{file}#{delimiter}"
|
||||
File.open(File.join(folder, file)).each { |line| gz.write(line) }
|
||||
first_file = false
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -202,6 +260,7 @@ error
|
|||
tar_path
|
||||
end
|
||||
|
||||
|
||||
# TODO need a better way to which controller is the hd
|
||||
def hd
|
||||
@vm.storage_controllers.first.devices.first
|
||||
|
|
|
@ -36,11 +36,16 @@ class Test::Unit::TestCase
|
|||
config.vm.project_directory = "/hobo"
|
||||
config.vm.forward_port("ssh", 22, 2222)
|
||||
|
||||
config.package.delimiter = 'V'
|
||||
config.package.delimiter_regex = /'V(.+)V'/
|
||||
|
||||
config.chef.cookbooks_path = "cookbooks"
|
||||
config.chef.provisioning_path = "/tmp/hobo-chef"
|
||||
config.chef.json = {
|
||||
:recipes => ["hobo_main"]
|
||||
}
|
||||
|
||||
config.vagrant.home = '~/.home'
|
||||
end
|
||||
|
||||
Vagrant::Config.execute!
|
||||
|
|
|
@ -15,6 +15,7 @@ class VMTest < Test::Unit::TestCase
|
|||
should "create a Vagrant::VM instance and call create" do
|
||||
inst = mock("instance")
|
||||
inst.expects(:create).once
|
||||
inst.expects(:from=).with(File.expand_path(Vagrant.config[:vm][:base]))
|
||||
Vagrant::VM.expects(:new).returns(inst)
|
||||
Vagrant::VM.up
|
||||
end
|
||||
|
@ -242,6 +243,7 @@ class VMTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
# TODO more comprehensive testing
|
||||
context "packaging a vm" do
|
||||
should "dump the three necessary files to a tar in the current working dir" do
|
||||
location = FileUtils.pwd
|
||||
|
@ -250,10 +252,24 @@ class VMTest < Test::Unit::TestCase
|
|||
@mock_vm.expects(:export).with(File.join(new_dir, "#{name}.ovf"))
|
||||
FileUtils.expects(:mkpath).with(new_dir).returns(new_dir)
|
||||
FileUtils.expects(:rm_r).with(new_dir)
|
||||
Tar.expects(:open)
|
||||
Zlib::GzipWriter.expects(:open).with("#{location}/#{name}.box")
|
||||
|
||||
# TODO test whats passed to the open tar.append_tree
|
||||
assert_equal Vagrant::VM.new(@mock_vm).package(name, location), "#{new_dir}.box"
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue