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|
|
Vagrant::Config.run do |config|
|
||||||
# default config goes here
|
# default config goes here
|
||||||
config.vagrant.log_output = STDOUT
|
config.vagrant.log_output = STDOUT
|
||||||
|
config.vagrant.home = "~/.vagrant"
|
||||||
|
|
||||||
config.ssh.username = "vagrant"
|
config.ssh.username = "vagrant"
|
||||||
config.ssh.password = "vagrant"
|
config.ssh.password = "vagrant"
|
||||||
|
@ -17,6 +18,8 @@ Vagrant::Config.run do |config|
|
||||||
config.vm.disk_image_format = 'VMDK'
|
config.vm.disk_image_format = 'VMDK'
|
||||||
|
|
||||||
config.package.name = 'vagrant'
|
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.cookbooks_path = "cookbooks"
|
||||||
config.chef.provisioning_path = "/tmp/vagrant-chef"
|
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
|
error
|
||||||
Env.persisted_vm.package(name || Vagrant.config[:package][:name], FileUtils.pwd)
|
Env.persisted_vm.package(name || Vagrant.config[:package][:name], FileUtils.pwd)
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -70,10 +70,16 @@ module Vagrant
|
||||||
raise Exception.new "disk_storage must be set to a directory" unless File.directory?(val)
|
raise Exception.new "disk_storage must be set to a directory" unless File.directory?(val)
|
||||||
@hd_location=val
|
@hd_location=val
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def base
|
||||||
|
File.expand_path(@base)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class PackageConfig < Base
|
class PackageConfig < Base
|
||||||
attr_accessor :name
|
attr_accessor :name
|
||||||
|
attr_accessor :delimiter
|
||||||
|
attr_accessor :delimiter_regex
|
||||||
end
|
end
|
||||||
|
|
||||||
class ChefConfig < Base
|
class ChefConfig < Base
|
||||||
|
@ -84,6 +90,11 @@ module Vagrant
|
||||||
|
|
||||||
class VagrantConfig < Base
|
class VagrantConfig < Base
|
||||||
attr_accessor :log_output
|
attr_accessor :log_output
|
||||||
|
attr_accessor :home
|
||||||
|
|
||||||
|
def home
|
||||||
|
File.expand_path(@home)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Top < Base
|
class Top < Base
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module Util
|
module Util
|
||||||
def self.included?(base)
|
def self.included(base)
|
||||||
base.extend Vagrant::Util
|
base.extend Vagrant::Util
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,71 @@ module Vagrant
|
||||||
class VM
|
class VM
|
||||||
include Vagrant::Util
|
include Vagrant::Util
|
||||||
attr_reader :vm
|
attr_reader :vm
|
||||||
|
attr_accessor :from
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
# Bring up the virtual machine. Imports the base image and
|
# Bring up the virtual machine. Imports the base image and
|
||||||
# provisions it.
|
# provisions it.
|
||||||
def up
|
def up(from=Vagrant.config[:vm][:base])
|
||||||
new.create
|
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
|
end
|
||||||
|
|
||||||
# Finds a virtual machine by a given UUID and either returns
|
# Finds a virtual machine by a given UUID and either returns
|
||||||
|
@ -76,7 +135,7 @@ error
|
||||||
|
|
||||||
def import
|
def import
|
||||||
logger.info "Importing base VM (#{Vagrant.config[:vm][:base]})..."
|
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
|
end
|
||||||
|
|
||||||
def persist
|
def persist
|
||||||
|
@ -173,6 +232,7 @@ error
|
||||||
|
|
||||||
# TODO the longest method, needs to be split up
|
# TODO the longest method, needs to be split up
|
||||||
def package(name, to)
|
def package(name, to)
|
||||||
|
delimiter = Vagrant.config[:package][:delimiter]
|
||||||
folder = FileUtils.mkpath(File.join(to, name))
|
folder = FileUtils.mkpath(File.join(to, name))
|
||||||
logger.info "Creating working directory: #{folder} ..."
|
logger.info "Creating working directory: #{folder} ..."
|
||||||
|
|
||||||
|
@ -182,17 +242,15 @@ error
|
||||||
logger.info "Exporting required VM files to working directory ..."
|
logger.info "Exporting required VM files to working directory ..."
|
||||||
@vm.export(ovf_path)
|
@vm.export(ovf_path)
|
||||||
|
|
||||||
# TODO use zlib ...
|
logger.info "Packaging VM into #{tar_path} ..."
|
||||||
logger.info "Packaging VM into #{name}.box ..."
|
Zlib::GzipWriter.open(tar_path) do |gz|
|
||||||
Tar.open(tar_path, File::CREAT | File::WRONLY, 0644, Tar::GNU) do |tar|
|
first_file = true
|
||||||
begin
|
Dir.new(folder).each do |file|
|
||||||
# appending the expanded file path adds the whole folder tree
|
next if File.directory?(file)
|
||||||
# to the tar archive there must be a better way
|
# Delimit the files, and guarantee new line for next file if not the first
|
||||||
working_dir = FileUtils.pwd
|
gz.write "#{delimiter}#{file}#{delimiter}"
|
||||||
FileUtils.cd(to)
|
File.open(File.join(folder, file)).each { |line| gz.write(line) }
|
||||||
tar.append_tree(name)
|
first_file = false
|
||||||
ensure
|
|
||||||
FileUtils.cd(working_dir)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -202,6 +260,7 @@ error
|
||||||
tar_path
|
tar_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# TODO need a better way to which controller is the hd
|
# TODO need a better way to which controller is the hd
|
||||||
def hd
|
def hd
|
||||||
@vm.storage_controllers.first.devices.first
|
@vm.storage_controllers.first.devices.first
|
||||||
|
|
|
@ -36,11 +36,16 @@ class Test::Unit::TestCase
|
||||||
config.vm.project_directory = "/hobo"
|
config.vm.project_directory = "/hobo"
|
||||||
config.vm.forward_port("ssh", 22, 2222)
|
config.vm.forward_port("ssh", 22, 2222)
|
||||||
|
|
||||||
|
config.package.delimiter = 'V'
|
||||||
|
config.package.delimiter_regex = /'V(.+)V'/
|
||||||
|
|
||||||
config.chef.cookbooks_path = "cookbooks"
|
config.chef.cookbooks_path = "cookbooks"
|
||||||
config.chef.provisioning_path = "/tmp/hobo-chef"
|
config.chef.provisioning_path = "/tmp/hobo-chef"
|
||||||
config.chef.json = {
|
config.chef.json = {
|
||||||
:recipes => ["hobo_main"]
|
:recipes => ["hobo_main"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.vagrant.home = '~/.home'
|
||||||
end
|
end
|
||||||
|
|
||||||
Vagrant::Config.execute!
|
Vagrant::Config.execute!
|
||||||
|
|
|
@ -15,6 +15,7 @@ class VMTest < Test::Unit::TestCase
|
||||||
should "create a Vagrant::VM instance and call create" do
|
should "create a Vagrant::VM instance and call create" do
|
||||||
inst = mock("instance")
|
inst = mock("instance")
|
||||||
inst.expects(:create).once
|
inst.expects(:create).once
|
||||||
|
inst.expects(:from=).with(File.expand_path(Vagrant.config[:vm][:base]))
|
||||||
Vagrant::VM.expects(:new).returns(inst)
|
Vagrant::VM.expects(:new).returns(inst)
|
||||||
Vagrant::VM.up
|
Vagrant::VM.up
|
||||||
end
|
end
|
||||||
|
@ -242,6 +243,7 @@ class VMTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO more comprehensive testing
|
||||||
context "packaging a vm" do
|
context "packaging a vm" do
|
||||||
should "dump the three necessary files to a tar in the current working dir" do
|
should "dump the three necessary files to a tar in the current working dir" do
|
||||||
location = FileUtils.pwd
|
location = FileUtils.pwd
|
||||||
|
@ -250,10 +252,24 @@ class VMTest < Test::Unit::TestCase
|
||||||
@mock_vm.expects(:export).with(File.join(new_dir, "#{name}.ovf"))
|
@mock_vm.expects(:export).with(File.join(new_dir, "#{name}.ovf"))
|
||||||
FileUtils.expects(:mkpath).with(new_dir).returns(new_dir)
|
FileUtils.expects(:mkpath).with(new_dir).returns(new_dir)
|
||||||
FileUtils.expects(:rm_r).with(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
|
# TODO test whats passed to the open tar.append_tree
|
||||||
assert_equal Vagrant::VM.new(@mock_vm).package(name, location), "#{new_dir}.box"
|
assert_equal Vagrant::VM.new(@mock_vm).package(name, location), "#{new_dir}.box"
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue