vagrant 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. data/.gitignore +11 -0
  2. data/Gemfile +17 -0
  3. data/README.md +45 -0
  4. data/Rakefile +41 -0
  5. data/VERSION +1 -0
  6. data/bin/.gitignore +0 -0
  7. data/bin/vagrant +15 -0
  8. data/bin/vagrant-box +35 -0
  9. data/bin/vagrant-down +28 -0
  10. data/bin/vagrant-halt +29 -0
  11. data/bin/vagrant-init +28 -0
  12. data/bin/vagrant-package +30 -0
  13. data/bin/vagrant-reload +30 -0
  14. data/bin/vagrant-resume +28 -0
  15. data/bin/vagrant-ssh +28 -0
  16. data/bin/vagrant-suspend +28 -0
  17. data/bin/vagrant-up +30 -0
  18. data/config/default.rb +29 -0
  19. data/lib/vagrant.rb +14 -0
  20. data/lib/vagrant/actions/base.rb +93 -0
  21. data/lib/vagrant/actions/box/add.rb +22 -0
  22. data/lib/vagrant/actions/box/destroy.rb +14 -0
  23. data/lib/vagrant/actions/box/download.rb +63 -0
  24. data/lib/vagrant/actions/box/unpackage.rb +49 -0
  25. data/lib/vagrant/actions/runner.rb +128 -0
  26. data/lib/vagrant/actions/vm/destroy.rb +14 -0
  27. data/lib/vagrant/actions/vm/down.rb +12 -0
  28. data/lib/vagrant/actions/vm/export.rb +41 -0
  29. data/lib/vagrant/actions/vm/forward_ports.rb +32 -0
  30. data/lib/vagrant/actions/vm/halt.rb +14 -0
  31. data/lib/vagrant/actions/vm/import.rb +17 -0
  32. data/lib/vagrant/actions/vm/move_hard_drive.rb +53 -0
  33. data/lib/vagrant/actions/vm/package.rb +61 -0
  34. data/lib/vagrant/actions/vm/provision.rb +71 -0
  35. data/lib/vagrant/actions/vm/reload.rb +17 -0
  36. data/lib/vagrant/actions/vm/resume.rb +16 -0
  37. data/lib/vagrant/actions/vm/shared_folders.rb +69 -0
  38. data/lib/vagrant/actions/vm/start.rb +50 -0
  39. data/lib/vagrant/actions/vm/suspend.rb +16 -0
  40. data/lib/vagrant/actions/vm/up.rb +35 -0
  41. data/lib/vagrant/box.rb +129 -0
  42. data/lib/vagrant/busy.rb +73 -0
  43. data/lib/vagrant/commands.rb +174 -0
  44. data/lib/vagrant/config.rb +156 -0
  45. data/lib/vagrant/downloaders/base.rb +13 -0
  46. data/lib/vagrant/downloaders/file.rb +21 -0
  47. data/lib/vagrant/downloaders/http.rb +47 -0
  48. data/lib/vagrant/env.rb +140 -0
  49. data/lib/vagrant/ssh.rb +43 -0
  50. data/lib/vagrant/util.rb +45 -0
  51. data/lib/vagrant/vm.rb +57 -0
  52. data/script/vagrant-ssh-expect.sh +22 -0
  53. data/templates/Vagrantfile +8 -0
  54. data/test/test_helper.rb +91 -0
  55. data/test/vagrant/actions/base_test.rb +32 -0
  56. data/test/vagrant/actions/box/add_test.rb +37 -0
  57. data/test/vagrant/actions/box/destroy_test.rb +18 -0
  58. data/test/vagrant/actions/box/download_test.rb +118 -0
  59. data/test/vagrant/actions/box/unpackage_test.rb +101 -0
  60. data/test/vagrant/actions/runner_test.rb +236 -0
  61. data/test/vagrant/actions/vm/destroy_test.rb +24 -0
  62. data/test/vagrant/actions/vm/down_test.rb +32 -0
  63. data/test/vagrant/actions/vm/export_test.rb +88 -0
  64. data/test/vagrant/actions/vm/forward_ports_test.rb +50 -0
  65. data/test/vagrant/actions/vm/halt_test.rb +27 -0
  66. data/test/vagrant/actions/vm/import_test.rb +36 -0
  67. data/test/vagrant/actions/vm/move_hard_drive_test.rb +108 -0
  68. data/test/vagrant/actions/vm/package_test.rb +155 -0
  69. data/test/vagrant/actions/vm/provision_test.rb +103 -0
  70. data/test/vagrant/actions/vm/reload_test.rb +44 -0
  71. data/test/vagrant/actions/vm/resume_test.rb +27 -0
  72. data/test/vagrant/actions/vm/shared_folders_test.rb +117 -0
  73. data/test/vagrant/actions/vm/start_test.rb +55 -0
  74. data/test/vagrant/actions/vm/suspend_test.rb +27 -0
  75. data/test/vagrant/actions/vm/up_test.rb +76 -0
  76. data/test/vagrant/box_test.rb +92 -0
  77. data/test/vagrant/busy_test.rb +81 -0
  78. data/test/vagrant/commands_test.rb +252 -0
  79. data/test/vagrant/config_test.rb +123 -0
  80. data/test/vagrant/downloaders/base_test.rb +20 -0
  81. data/test/vagrant/downloaders/file_test.rb +32 -0
  82. data/test/vagrant/downloaders/http_test.rb +40 -0
  83. data/test/vagrant/env_test.rb +293 -0
  84. data/test/vagrant/ssh_test.rb +95 -0
  85. data/test/vagrant/util_test.rb +64 -0
  86. data/test/vagrant/vm_test.rb +96 -0
  87. metadata +275 -0
@@ -0,0 +1,29 @@
1
+ Vagrant::Config.run do |config|
2
+ # default config goes here
3
+ config.vagrant.log_output = STDOUT
4
+ config.vagrant.dotfile_name = ".vagrant"
5
+ config.vagrant.home = "~/.vagrant"
6
+
7
+ config.ssh.username = "vagrant"
8
+ config.ssh.password = "vagrant"
9
+ config.ssh.host = "localhost"
10
+ config.ssh.forwarded_port_key = "ssh"
11
+ config.ssh.max_tries = 10
12
+
13
+ config.vm.box_ovf = "box.ovf"
14
+ config.vm.base_mac = "0800279C2E42"
15
+ config.vm.project_directory = "/vagrant"
16
+ config.vm.forward_port("ssh", 22, 2222)
17
+ config.vm.disk_image_format = 'VMDK'
18
+
19
+ config.package.name = 'vagrant'
20
+ config.package.extension = '.box'
21
+
22
+ config.chef.enabled = false
23
+ config.chef.cookbooks_path = "cookbooks"
24
+ config.chef.provisioning_path = "/tmp/vagrant-chef"
25
+ config.chef.json = {
26
+ :instance_role => "vagrant",
27
+ :recipes => ["vagrant_main"]
28
+ }
29
+ end
@@ -0,0 +1,14 @@
1
+ libdir = File.dirname(__FILE__)
2
+ $:.unshift(libdir)
3
+ PROJECT_ROOT = File.join(libdir, '..') unless defined?(PROJECT_ROOT)
4
+
5
+ # The libs which must be loaded prior to the rest
6
+ %w{tempfile open-uri ftools json pathname logger uri net/http virtualbox net/ssh tarruby
7
+ net/scp fileutils vagrant/util vagrant/actions/base vagrant/downloaders/base}.each do |f|
8
+ require f
9
+ end
10
+
11
+ # Glob require the rest
12
+ Dir[File.join(PROJECT_ROOT, "lib", "vagrant", "**", "*.rb")].each do |f|
13
+ require f
14
+ end
@@ -0,0 +1,93 @@
1
+ module Vagrant
2
+ module Actions
3
+ # Base class for any command actions.
4
+ #
5
+ # Actions are the smallest unit of functionality found within
6
+ # Vagrant. Vagrant composes many actions together to execute
7
+ # its complex tasks while keeping the individual pieces of a
8
+ # task as discrete reusable actions. Actions are ran exclusively
9
+ # by an {Runner action runner} which is simply a subclass of {Runner}.
10
+ #
11
+ # Actions work by implementing any or all of the following methods
12
+ # which a {Runner} executes:
13
+ #
14
+ # * `prepare` - Called once for each action before any action has `execute!`
15
+ # called. This is meant for basic setup.
16
+ # * `execute!` - This is where the meat of the action typically goes;
17
+ # the main code which executes the action.
18
+ # * `cleanup` - This is called exactly once for each action after every
19
+ # other action is completed. It is meant for cleaning up any resources.
20
+ # * `rescue` - This is called if an exception occurs in _any action_. This
21
+ # gives every other action a chance to clean itself up.
22
+ #
23
+ # For details of each step of an action, read the specific function call
24
+ # documentation below.
25
+ class Base
26
+ # The {Runner runner} which is executing the action
27
+ attr_reader :runner
28
+
29
+ # Included so subclasses don't need to include it themselves.
30
+ include Vagrant::Util
31
+
32
+ # Initialization of the action, passing any arguments which may have
33
+ # been given to the {Runner runner}. This method can be used by subclasses
34
+ # to save any of the configuration options which are passed in.
35
+ def initialize(runner, *args)
36
+ @runner = runner
37
+ end
38
+
39
+ # This method is called once per action, allowing the action
40
+ # to setup any callbacks, add more events, etc. Prepare is
41
+ # called in the order the actions are defined, and the action
42
+ # itself has no control over this.
43
+ #
44
+ # Examples of its usage:
45
+ #
46
+ # Perhaps we need an additional action only if a configuration is set:
47
+ #
48
+ # def prepare
49
+ # @vm.actions << FooAction if Vagrant.config[:foo] == :bar
50
+ # end
51
+ #
52
+ def prepare; end
53
+
54
+ # This method is called once, after preparing, to execute the
55
+ # actual task. This method is responsible for calling any
56
+ # callbacks. Adding new actions here will have unpredictable
57
+ # effects and should never be done.
58
+ #
59
+ # Examples of its usage:
60
+ #
61
+ # def execute!
62
+ # @vm.invoke_callback(:before_oven, "cookies")
63
+ # # Do lots of stuff here
64
+ # @vm.invoke_callback(:after_oven, "more", "than", "one", "option")
65
+ # end
66
+ #
67
+ def execute!; end
68
+
69
+ # This method is called after all actions have finished executing.
70
+ # It is meant as a place where final cleanup code can be done, knowing
71
+ # that all other actions are finished using your data.
72
+ def cleanup; end
73
+
74
+ # This method is only called if some exception occurs in the chain
75
+ # of actions. If an exception is raised in any action in the current
76
+ # chain, then every action part of that chain has {#rescue} called
77
+ # before raising the exception further. This method should be used to
78
+ # perform any cleanup necessary in the face of errors.
79
+ #
80
+ # **Warning:** Since this method is called when an exception is already
81
+ # raised, be _extra careful_ when implementing this method to handle
82
+ # all your own exceptions, otherwise it'll mask the initially raised
83
+ # exception.
84
+ def rescue(exception); end
85
+ end
86
+
87
+ # An exception which occured within an action. This should be used instead of
88
+ # {Vagrant::Util#error_and_exit error_and_exit}, since it allows the {Runner} to call
89
+ # {Base#rescue rescue} on all the actions and properly exit. Any message
90
+ # passed into the {ActionException} is then shown and and vagrant exits.
91
+ class ActionException < Exception; end
92
+ end
93
+ end
@@ -0,0 +1,22 @@
1
+ module Vagrant
2
+ module Actions
3
+ module Box
4
+ # A meta-action which adds a box by downloading and unpackaging it.
5
+ # This action downloads and unpackages a box with a given URI. This
6
+ # is a _meta action_, meaning it simply adds more actions to the
7
+ # action chain, and those actions do the work.
8
+ #
9
+ # This is the action called by {Box#add}.
10
+ class Add < Base
11
+ def prepare
12
+ if File.exists?(@runner.directory)
13
+ raise ActionException.new("A box with the name '#{@runner.name}' already exists, please use another name or use `vagrant box remove #{@runner.name}`")
14
+ end
15
+
16
+ @runner.add_action(Download)
17
+ @runner.add_action(Unpackage)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module Vagrant
2
+ module Actions
3
+ module Box
4
+ # Action to destroy a box. This action is not reversible and expects
5
+ # to be called by a {Box} object.
6
+ class Destroy < Base
7
+ def execute!
8
+ logger.info "Deleting box directory..."
9
+ FileUtils.rm_rf(@runner.directory)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,63 @@
1
+ module Vagrant
2
+ module Actions
3
+ module Box
4
+ # An action which acts on a box by downloading the box file from
5
+ # the given URI into a temporary location. This action parses a
6
+ # given URI and handles downloading it via one of the many Vagrant
7
+ # downloads (such as {Vagrant::Downloaders::File}).
8
+ #
9
+ # This action cleans itself up by removing the downloaded box file.
10
+ class Download < Base
11
+ BASENAME = "box"
12
+ BUFFERSIZE = 1048576 # 1 MB
13
+
14
+ attr_reader :downloader
15
+
16
+ def prepare
17
+ # Parse the URI given and prepare a downloader
18
+ uri = URI.parse(@runner.uri)
19
+ uri_map = [[URI::HTTP, Downloaders::HTTP], [URI::Generic, Downloaders::File]]
20
+
21
+ uri_map.find do |uri_type, downloader_klass|
22
+ if uri.is_a?(uri_type)
23
+ logger.info "#{uri_type} for URI, downloading via #{downloader_klass}..."
24
+ @downloader = downloader_klass.new
25
+ end
26
+ end
27
+
28
+ raise ActionException.new("Unknown URI type for box download.") unless @downloader
29
+ end
30
+
31
+ def execute!
32
+ with_tempfile do |tempfile|
33
+ download_to(tempfile)
34
+ @runner.temp_path = tempfile.path
35
+ end
36
+ end
37
+
38
+ def cleanup
39
+ if @runner.temp_path && File.exist?(@runner.temp_path)
40
+ logger.info "Cleaning up downloaded box..."
41
+ File.unlink(@runner.temp_path)
42
+ end
43
+ end
44
+
45
+ def rescue(exception)
46
+ cleanup
47
+ end
48
+
49
+ def with_tempfile
50
+ logger.info "Creating tempfile for storing box file..."
51
+ Tempfile.open(BASENAME, Env.tmp_path) do |tempfile|
52
+ yield tempfile
53
+ end
54
+ end
55
+
56
+ def download_to(f)
57
+ logger.info "Copying box to temporary location..."
58
+ downloader.download!(@runner.uri, f)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,49 @@
1
+ module Vagrant
2
+ module Actions
3
+ module Box
4
+ # This action unpackages a downloaded box file into its final
5
+ # box destination within the vagrant home folder.
6
+ class Unpackage < Base
7
+ TAR_OPTIONS = [File::RDONLY, 0644, Tar::GNU]
8
+
9
+ def execute!
10
+ @runner.invoke_around_callback(:unpackage) do
11
+ setup_box_dir
12
+ decompress
13
+ end
14
+ end
15
+
16
+ def rescue(exception)
17
+ if File.directory?(box_dir)
18
+ logger.info "An error occurred, rolling back box unpackaging..."
19
+ FileUtils.rm_rf(box_dir)
20
+ end
21
+ end
22
+
23
+ def setup_box_dir
24
+ if File.directory?(box_dir)
25
+ error_and_exit(<<-msg)
26
+ This box appears to already exist! Please call `vagrant box remove #{@runner.name}`
27
+ and then try to add it again.
28
+ msg
29
+ end
30
+
31
+ FileUtils.mkdir_p(box_dir)
32
+ end
33
+
34
+ def box_dir
35
+ @runner.directory
36
+ end
37
+
38
+ def decompress
39
+ Dir.chdir(box_dir) do
40
+ logger.info "Extracting box to #{box_dir}..."
41
+ Tar.open(@runner.temp_path, *TAR_OPTIONS) do |tar|
42
+ tar.extract_all
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,128 @@
1
+ module Vagrant
2
+ module Actions
3
+ # Base class for any class which will act as a runner
4
+ # for actions. A runner handles queueing up and executing actions,
5
+ # and executing the methods of an action in the proper order. The
6
+ # action runner also handles invoking callbacks that actions may
7
+ # request.
8
+ #
9
+ # # Executing Actions
10
+ #
11
+ # Actions can be executed by adding them and executing them all
12
+ # at once:
13
+ #
14
+ # runner = Vagrant::Actions::Runner.new
15
+ # runner.add_action(FooAction)
16
+ # runner.add_action(BarAction)
17
+ # runner.add_action(BazAction)
18
+ # runner.execute!
19
+ #
20
+ # Single actions have a shorthand to be executed:
21
+ #
22
+ # Vagrant::Actions::Runner.execute!(FooAction)
23
+ #
24
+ # Arguments may be passed into added actions by adding them after
25
+ # the action class:
26
+ #
27
+ # runner.add_action(FooAction, "many", "arguments", "may", "follow")
28
+ #
29
+ class Runner
30
+ include Vagrant::Util
31
+
32
+ class << self
33
+ # Executes a specific action, optionally passing in any arguments to that
34
+ # action. This method is shorthand to initializing a runner, adding a single
35
+ # action, and executing it.
36
+ def execute!(action_klass, *args)
37
+ runner = new
38
+ runner.add_action(action_klass, *args)
39
+ runner.execute!
40
+ end
41
+ end
42
+
43
+ # Returns an array of all the actions in queue. Because this
44
+ # will persist accross calls (calling {#actions} twice will yield
45
+ # exactly the same object), to clear or modify it, use the ruby
46
+ # array methods which act on `self`, such as `Array#clear`.
47
+ #
48
+ # @return [Array]
49
+ def actions
50
+ @actions ||= []
51
+ end
52
+
53
+ # Returns the first action instance which matches the given class.
54
+ #
55
+ # @param [Class] action_klass The action to search for in the queue
56
+ # @return [Object]
57
+ def find_action(action_klass)
58
+ actions.find { |a| a.is_a?(action_klass) }
59
+ end
60
+
61
+ # Add an action to the list of queued actions to execute. This method
62
+ # appends the given action class to the end of the queue. Any arguments
63
+ # given after the class are passed into the class constructor.
64
+ def add_action(action_klass, *args)
65
+ actions << action_klass.new(self, *args)
66
+ end
67
+
68
+ # Execute the actions in queue. This method can also optionally be used
69
+ # to execute a single action on an instance. The syntax for executing a
70
+ # single method on an instance is the same as the {execute!} class method.
71
+ def execute!(single_action=nil, *args)
72
+ if single_action
73
+ actions.clear
74
+ add_action(single_action, *args)
75
+ end
76
+
77
+ # Call the prepare method on each once its
78
+ # initialized, then call the execute! method
79
+ begin
80
+ [:prepare, :execute!, :cleanup].each do |method|
81
+ actions.each do |action|
82
+ action.send(method)
83
+ end
84
+ end
85
+ rescue Exception => e
86
+ # Run the rescue code to do any emergency cleanup
87
+ actions.each do |action|
88
+ action.rescue(e)
89
+ end
90
+
91
+ # If its an ActionException, error and exit the message
92
+ if e.is_a?(ActionException)
93
+ error_and_exit(e.message)
94
+ return
95
+ end
96
+
97
+ # Finally, reraise the exception
98
+ raise
99
+ end
100
+
101
+ # Clear the actions
102
+ actions.clear
103
+ end
104
+
105
+ # Invokes an "around callback" which invokes before_name and
106
+ # after_name for the given callback name, yielding a block between
107
+ # callback invokations.
108
+ def invoke_around_callback(name, *args)
109
+ invoke_callback("before_#{name}".to_sym, *args)
110
+ yield
111
+ invoke_callback("after_#{name}".to_sym, *args)
112
+ end
113
+
114
+ # Invokes a single callback. This method will go through each action
115
+ # and call the method given in the parameter `name` if the action
116
+ # responds to it.
117
+ def invoke_callback(name, *args)
118
+ # Attempt to call the method for the callback on each of the
119
+ # actions
120
+ results = []
121
+ actions.each do |action|
122
+ results << action.send(name, *args) if action.respond_to?(name)
123
+ end
124
+ results
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,14 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Destroy < Base
5
+ def execute!
6
+ @runner.invoke_around_callback(:destroy) do
7
+ logger.info "Destroying VM and associated drives..."
8
+ @runner.vm.destroy(:destroy_image => true)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Down < Base
5
+ def prepare
6
+ @runner.add_action(Halt) if @runner.vm.running?
7
+ @runner.add_action(Destroy)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end