From 1316a9ac17b8e9c1ead2b7aa0eb3d11574efa567 Mon Sep 17 00:00:00 2001 From: John Bender Date: Thu, 11 Feb 2010 21:48:48 -0800 Subject: [PATCH] packaging working --- .gitignore | 3 ++- Gemfile | 1 + bin/vagrant-package | 30 +++++++++++++++++++++ lib/vagrant.rb | 2 ++ lib/vagrant/packaged.rb | 51 +++++++++++++++++++++++++++++++++++ lib/vagrant/vm.rb | 13 +++++++++ test/vagrant/packaged_test.rb | 18 +++++++++++++ test/vagrant/vm_test.rb | 3 +-- 8 files changed, 118 insertions(+), 3 deletions(-) create mode 100755 bin/vagrant-package create mode 100644 lib/vagrant/packaged.rb create mode 100644 test/vagrant/packaged_test.rb diff --git a/.gitignore b/.gitignore index 47f22ca4c..36d08933e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ Vagrantfile *.lock cookbooks/* _site/* -!templates/* \ No newline at end of file +!templates/* +*.org diff --git a/Gemfile b/Gemfile index 0a0bf59de..36fc07e2a 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,7 @@ gem "net-ssh", ">= 2.0.19" gem "net-scp", ">= 1.0.2" gem "jashmenn-git-style-binaries", ">= 0.1.10" gem "json", ">= 1.2.0" +gem "tarruby", ">= 0.1.5" # Gems required for testing only. To install run # gem bundle test diff --git a/bin/vagrant-package b/bin/vagrant-package new file mode 100755 index 000000000..e83f69873 --- /dev/null +++ b/bin/vagrant-package @@ -0,0 +1,30 @@ +#!/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 "package the current vagrant environment" + banner <<-EOS +Usage: #{command.full_name} #{all_options_string} + +Package the current vagrant environment + +EOS + + opt :file, "the name of the resulting packaged file" + + run do |command| + Vagrant::VM.package((command.argv[0] || 'vagrant.box')) + end +end diff --git a/lib/vagrant.rb b/lib/vagrant.rb index c6567344a..6eae2302a 100644 --- a/lib/vagrant.rb +++ b/lib/vagrant.rb @@ -9,6 +9,8 @@ require 'logger' require 'virtualbox' require 'net/ssh' require 'net/scp' +require 'tarruby' +require 'fileutils' require 'vagrant/busy' require 'vagrant/util' require 'vagrant/commands' diff --git a/lib/vagrant/packaged.rb b/lib/vagrant/packaged.rb new file mode 100644 index 000000000..e16450a0c --- /dev/null +++ b/lib/vagrant/packaged.rb @@ -0,0 +1,51 @@ +module Vagrant + class Packaged + attr_reader :vm, :file, :name + + def initialize(name, params) + @vm = params[:vm] + @file = params[:file] + @name = name + end + + def compressed? + @file + end + + def decompress(to) + # move folder unless compressed? + # decompress + # return File object of ovf for import + end + + def compress(to) + folder = FileUtils.mkpath(File.join(to, @name)) + + return @file if compressed? + + ovf_path = File.join(folder, "#{@name}.ovf") + tar_path = "#{folder}.tar" + + @vm.export(ovf_path) + + # TODO use zlib ... + Tar.open(tar_path, File::CREAT | File::WRONLY, 0644, Tar::GNU) do |tar| + begin + working_dir = FileUtils.pwd + FileUtils.cd(to) + tar.append_tree(@name) + ensure + FileUtils.cd(working_dir) + + end + end + + # TODO remove directory + + + tar_path + end + + def ovf; "#{@name}.ovf" end + end +end diff --git a/lib/vagrant/vm.rb b/lib/vagrant/vm.rb index 615f734e8..ec6338eb2 100644 --- a/lib/vagrant/vm.rb +++ b/lib/vagrant/vm.rb @@ -20,6 +20,15 @@ module Vagrant return nil if vm.nil? new(vm) end + + def package(name, to=FileUtils.pwd) + Env.require_persisted_vm + error_and_exit(<<-error) unless Env.persisted_vm.powered_off? +The vagrant virtual environment you are trying to package must be powered off +error + + Packaged.new(name, :vm => Env.persisted_vm).compress(to) + end end def initialize(vm=nil) @@ -178,5 +187,9 @@ error def hd @vm.storage_controllers.first.devices.first end + + def powered_off?; @vm.powered_off? end + + def export(filename); @vm.export(filename, {}, true) end end end diff --git a/test/vagrant/packaged_test.rb b/test/vagrant/packaged_test.rb new file mode 100644 index 000000000..6f6019eb7 --- /dev/null +++ b/test/vagrant/packaged_test.rb @@ -0,0 +1,18 @@ +require File.join(File.dirname(__FILE__), '..', 'test_helper') + +class BoxedTest< Test::Unit::TestCase + context "exporting a vm" do + should "create a tar in the specified directory" do + vm = mock('vm') + location = '/Users/johnbender/Desktop' + name = 'my_box' + new_dir = File.join(location, name) + vm.expects(:export).with(File.join(new_dir, "#{name}.ovf")) + FileUtils.expects(:mkpath).with(new_dir).returns(new_dir) + Tar.expects(:open) + + # TODO test whats passed to the open tar.append_tree + assert_equal Vagrant::Packaged.new(name, :vm => vm).compress(location), "#{new_dir}.tar" + end + end +end diff --git a/test/vagrant/vm_test.rb b/test/vagrant/vm_test.rb index 7d4b43e2a..66aa3b1f8 100644 --- a/test/vagrant/vm_test.rb +++ b/test/vagrant/vm_test.rb @@ -228,12 +228,11 @@ class VMTest < Test::Unit::TestCase Vagrant.config[:vm].expects(:hd_location).at_least_once.returns('/locations/') image.expects(:clone).with(Vagrant.config[:vm][:hd_location] + 'foo', Vagrant::VM::HD_EXT_DEFAULT, true).returns(image) image.expects(:filename).twice.returns('foo') + image.expects(:destroy) hd.expects(:image).twice.returns(image) hd.expects(:image=).with(image) - image.expects(:destroy) - @mock_vm.expects(:save) vm = Vagrant::VM.new(@mock_vm)