bmabey-vagrant 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. data/.gitignore +12 -0
  2. data/Gemfile +17 -0
  3. data/LICENSE +21 -0
  4. data/README.md +53 -0
  5. data/Rakefile +41 -0
  6. data/VERSION +1 -0
  7. data/bin/.gitignore +0 -0
  8. data/bin/vagrant +15 -0
  9. data/bin/vagrant-box +34 -0
  10. data/bin/vagrant-down +27 -0
  11. data/bin/vagrant-halt +28 -0
  12. data/bin/vagrant-init +27 -0
  13. data/bin/vagrant-package +29 -0
  14. data/bin/vagrant-reload +29 -0
  15. data/bin/vagrant-resume +27 -0
  16. data/bin/vagrant-ssh +27 -0
  17. data/bin/vagrant-status +29 -0
  18. data/bin/vagrant-suspend +27 -0
  19. data/bin/vagrant-up +29 -0
  20. data/config/default.rb +26 -0
  21. data/keys/README.md +10 -0
  22. data/keys/vagrant +27 -0
  23. data/keys/vagrant.pub +1 -0
  24. data/lib/vagrant.rb +19 -0
  25. data/lib/vagrant/actions/base.rb +118 -0
  26. data/lib/vagrant/actions/box/add.rb +22 -0
  27. data/lib/vagrant/actions/box/destroy.rb +14 -0
  28. data/lib/vagrant/actions/box/download.rb +72 -0
  29. data/lib/vagrant/actions/box/unpackage.rb +43 -0
  30. data/lib/vagrant/actions/collection.rb +36 -0
  31. data/lib/vagrant/actions/runner.rb +132 -0
  32. data/lib/vagrant/actions/vm/boot.rb +47 -0
  33. data/lib/vagrant/actions/vm/customize.rb +17 -0
  34. data/lib/vagrant/actions/vm/destroy.rb +23 -0
  35. data/lib/vagrant/actions/vm/down.rb +12 -0
  36. data/lib/vagrant/actions/vm/export.rb +41 -0
  37. data/lib/vagrant/actions/vm/forward_ports.rb +46 -0
  38. data/lib/vagrant/actions/vm/halt.rb +14 -0
  39. data/lib/vagrant/actions/vm/import.rb +18 -0
  40. data/lib/vagrant/actions/vm/move_hard_drive.rb +51 -0
  41. data/lib/vagrant/actions/vm/package.rb +65 -0
  42. data/lib/vagrant/actions/vm/provision.rb +49 -0
  43. data/lib/vagrant/actions/vm/reload.rb +17 -0
  44. data/lib/vagrant/actions/vm/resume.rb +16 -0
  45. data/lib/vagrant/actions/vm/shared_folders.rb +81 -0
  46. data/lib/vagrant/actions/vm/start.rb +18 -0
  47. data/lib/vagrant/actions/vm/suspend.rb +16 -0
  48. data/lib/vagrant/actions/vm/up.rb +40 -0
  49. data/lib/vagrant/active_list.rb +73 -0
  50. data/lib/vagrant/box.rb +152 -0
  51. data/lib/vagrant/busy.rb +73 -0
  52. data/lib/vagrant/commands.rb +219 -0
  53. data/lib/vagrant/config.rb +183 -0
  54. data/lib/vagrant/downloaders/base.rb +16 -0
  55. data/lib/vagrant/downloaders/file.rb +17 -0
  56. data/lib/vagrant/downloaders/http.rb +47 -0
  57. data/lib/vagrant/environment.rb +263 -0
  58. data/lib/vagrant/provisioners/base.rb +29 -0
  59. data/lib/vagrant/provisioners/chef.rb +103 -0
  60. data/lib/vagrant/provisioners/chef_server.rb +84 -0
  61. data/lib/vagrant/provisioners/chef_solo.rb +97 -0
  62. data/lib/vagrant/ssh.rb +104 -0
  63. data/lib/vagrant/util.rb +51 -0
  64. data/lib/vagrant/util/errors.rb +36 -0
  65. data/lib/vagrant/util/stacked_proc_runner.rb +35 -0
  66. data/lib/vagrant/util/template_renderer.rb +83 -0
  67. data/lib/vagrant/vm.rb +61 -0
  68. data/templates/Vagrantfile.erb +8 -0
  69. data/templates/errors.yml +117 -0
  70. data/test/test_helper.rb +163 -0
  71. data/test/vagrant/actions/base_test.rb +32 -0
  72. data/test/vagrant/actions/box/add_test.rb +37 -0
  73. data/test/vagrant/actions/box/destroy_test.rb +18 -0
  74. data/test/vagrant/actions/box/download_test.rb +131 -0
  75. data/test/vagrant/actions/box/unpackage_test.rb +100 -0
  76. data/test/vagrant/actions/collection_test.rb +110 -0
  77. data/test/vagrant/actions/runner_test.rb +265 -0
  78. data/test/vagrant/actions/vm/boot_test.rb +55 -0
  79. data/test/vagrant/actions/vm/customize_test.rb +16 -0
  80. data/test/vagrant/actions/vm/destroy_test.rb +36 -0
  81. data/test/vagrant/actions/vm/down_test.rb +32 -0
  82. data/test/vagrant/actions/vm/export_test.rb +88 -0
  83. data/test/vagrant/actions/vm/forward_ports_test.rb +104 -0
  84. data/test/vagrant/actions/vm/halt_test.rb +27 -0
  85. data/test/vagrant/actions/vm/import_test.rb +43 -0
  86. data/test/vagrant/actions/vm/move_hard_drive_test.rb +108 -0
  87. data/test/vagrant/actions/vm/package_test.rb +181 -0
  88. data/test/vagrant/actions/vm/provision_test.rb +108 -0
  89. data/test/vagrant/actions/vm/reload_test.rb +47 -0
  90. data/test/vagrant/actions/vm/resume_test.rb +27 -0
  91. data/test/vagrant/actions/vm/shared_folders_test.rb +176 -0
  92. data/test/vagrant/actions/vm/start_test.rb +36 -0
  93. data/test/vagrant/actions/vm/suspend_test.rb +27 -0
  94. data/test/vagrant/actions/vm/up_test.rb +107 -0
  95. data/test/vagrant/active_list_test.rb +190 -0
  96. data/test/vagrant/box_test.rb +151 -0
  97. data/test/vagrant/busy_test.rb +83 -0
  98. data/test/vagrant/commands_test.rb +307 -0
  99. data/test/vagrant/config_test.rb +256 -0
  100. data/test/vagrant/downloaders/base_test.rb +27 -0
  101. data/test/vagrant/downloaders/file_test.rb +26 -0
  102. data/test/vagrant/downloaders/http_test.rb +40 -0
  103. data/test/vagrant/environment_test.rb +607 -0
  104. data/test/vagrant/provisioners/base_test.rb +33 -0
  105. data/test/vagrant/provisioners/chef_server_test.rb +187 -0
  106. data/test/vagrant/provisioners/chef_solo_test.rb +149 -0
  107. data/test/vagrant/provisioners/chef_test.rb +117 -0
  108. data/test/vagrant/ssh_test.rb +222 -0
  109. data/test/vagrant/util/errors_test.rb +57 -0
  110. data/test/vagrant/util/stacked_proc_runner_test.rb +43 -0
  111. data/test/vagrant/util/template_renderer_test.rb +138 -0
  112. data/test/vagrant/util_test.rb +64 -0
  113. data/test/vagrant/vm_test.rb +114 -0
  114. data/vagrant.gemspec +216 -0
  115. metadata +285 -0
@@ -0,0 +1,47 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Boot < Base
5
+ def prepare
6
+ @runner.env.config.vm.share_folder("vagrant-root", @runner.env.config.vm.project_directory, @runner.env.root_path)
7
+ end
8
+
9
+ def execute!
10
+ @runner.invoke_around_callback(:boot) do
11
+ # Startup the VM
12
+ boot
13
+
14
+ # Wait for it to complete booting, or error if we could
15
+ # never detect it booted up successfully
16
+ if !wait_for_boot
17
+ error_and_exit(:vm_failed_to_boot)
18
+ end
19
+ end
20
+ end
21
+
22
+ def boot
23
+ logger.info "Booting VM..."
24
+ @runner.vm.start(:headless, true)
25
+ end
26
+
27
+ def wait_for_boot(sleeptime=5)
28
+ logger.info "Waiting for VM to boot..."
29
+
30
+ @runner.env.config.ssh.max_tries.to_i.times do |i|
31
+ logger.info "Trying to connect (attempt ##{i+1} of #{Vagrant.config[:ssh][:max_tries]})..."
32
+
33
+ if @runner.env.ssh.up?
34
+ logger.info "VM booted and ready for use!"
35
+ return true
36
+ end
37
+
38
+ sleep sleeptime
39
+ end
40
+
41
+ logger.info "Failed to connect to VM! Failed to boot?"
42
+ false
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Customize < Base
5
+ def execute!
6
+ logger.info "Running any VM customizations..."
7
+
8
+ # Run the customization procs over the VM
9
+ @runner.env.config.vm.run_procs!(@runner.vm)
10
+
11
+ # Save the vm
12
+ @runner.vm.save(true)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Destroy < Base
5
+ def execute!
6
+ @runner.invoke_around_callback(:destroy) do
7
+ destroy_vm
8
+ depersist
9
+ end
10
+ end
11
+
12
+ def destroy_vm
13
+ logger.info "Destroying VM and associated drives..."
14
+ @runner.vm.destroy(:destroy_image => true)
15
+ end
16
+
17
+ def depersist
18
+ @runner.env.depersist_vm
19
+ end
20
+ end
21
+ end
22
+ end
23
+ 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
@@ -0,0 +1,41 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Export < Base
5
+ attr_reader :temp_dir
6
+
7
+ def execute!
8
+ setup_temp_dir
9
+ export
10
+ end
11
+
12
+ def cleanup
13
+ if temp_dir
14
+ logger.info "Removing temporary export directory..."
15
+ FileUtils.rm_r(temp_dir)
16
+ end
17
+ end
18
+
19
+ def rescue(exception)
20
+ cleanup
21
+ end
22
+
23
+ def setup_temp_dir
24
+ @temp_dir = File.join(@runner.env.tmp_path, Time.now.to_i.to_s)
25
+
26
+ logger.info "Creating temporary directory for export..."
27
+ FileUtils.mkpath(temp_dir)
28
+ end
29
+
30
+ def ovf_path
31
+ File.join(temp_dir, @runner.env.config.vm.box_ovf)
32
+ end
33
+
34
+ def export
35
+ logger.info "Exporting VM to #{ovf_path} ..."
36
+ @runner.vm.export(ovf_path, {}, true)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,46 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class ForwardPorts < Base
5
+ def prepare
6
+ VirtualBox::VM.all.each do |vm|
7
+ next if !vm.running? || vm.uuid == @runner.uuid
8
+
9
+ vm.forwarded_ports.each do |fp|
10
+ @runner.env.config.vm.forwarded_ports.each do |name, options|
11
+ if fp.hostport.to_s == options[:hostport].to_s
12
+ raise ActionException.new(:vm_port_collision, :name => name, :hostport => fp.hostport.to_s, :guestport => options[:guestport].to_s)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def execute!
20
+ clear
21
+ forward_ports
22
+ end
23
+
24
+ def clear
25
+ logger.info "Deleting any previously set forwarded ports..."
26
+ @runner.vm.forwarded_ports.collect { |p| p.destroy(true) }
27
+ end
28
+
29
+ def forward_ports
30
+ logger.info "Forwarding ports..."
31
+
32
+ @runner.env.config.vm.forwarded_ports.each do |name, options|
33
+ logger.info "Forwarding \"#{name}\": #{options[:guestport]} => #{options[:hostport]}"
34
+ port = VirtualBox::ForwardedPort.new
35
+ port.name = name
36
+ port.hostport = options[:hostport]
37
+ port.guestport = options[:guestport]
38
+ @runner.vm.forwarded_ports << port
39
+ end
40
+
41
+ @runner.vm.save(true)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,14 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Halt < Base
5
+ def execute!
6
+ raise ActionException.new(:vm_not_running) unless @runner.vm.running?
7
+
8
+ logger.info "Forcing shutdown of VM..."
9
+ @runner.vm.stop(true)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Import < Base
5
+ def execute!
6
+ @runner.invoke_around_callback(:import) do
7
+ Busy.busy do
8
+ logger.info "Importing base VM (#{@runner.env.box.ovf_file})..."
9
+ # Use the first argument passed to the action
10
+ @runner.vm = VirtualBox::VM.import(@runner.env.box.ovf_file)
11
+ raise ActionException.new(:virtualbox_import_failure) unless @runner.vm
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,51 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class MoveHardDrive < Base
5
+ def execute!
6
+ unless @runner.powered_off?
7
+ error_and_exit(:vm_power_off_to_move_hd)
8
+ return
9
+ end
10
+
11
+ destroy_drive_after { clone_and_attach }
12
+ end
13
+
14
+ def hard_drive
15
+ @hard_drive ||= find_hard_drive
16
+ end
17
+
18
+ # TODO won't work if the first disk is not the boot disk or even if there are multiple disks
19
+ def find_hard_drive
20
+ @runner.vm.storage_controllers.each do |sc|
21
+ sc.devices.each do |d|
22
+ return d if d.image.is_a?(VirtualBox::HardDrive)
23
+ end
24
+ end
25
+ end
26
+
27
+ def clone_and_attach
28
+ logger.info "Cloning current VM Disk to new location (#{new_image_path})..."
29
+ hard_drive.image = hard_drive.image.clone(new_image_path, Vagrant.config.vm.disk_image_format, true)
30
+
31
+ logger.info "Attaching new disk to VM ..."
32
+ @runner.vm.save
33
+ end
34
+
35
+ def destroy_drive_after
36
+ old_image = hard_drive.image
37
+
38
+ yield
39
+
40
+ logger.info "Destroying old VM Disk (#{old_image.filename})..."
41
+ old_image.destroy(true)
42
+ end
43
+
44
+ # Returns the path to the new location for the hard drive
45
+ def new_image_path
46
+ File.join(Vagrant.config.vm.hd_location, hard_drive.image.filename)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,65 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Package < Base
5
+ attr_accessor :out_path
6
+ attr_accessor :include_files
7
+ attr_reader :export_action
8
+
9
+ def initialize(vm, out_path = nil, include_files = nil, *args)
10
+ super
11
+ @out_path = out_path || "package"
12
+ @include_files = include_files || []
13
+ @temp_path = nil
14
+ end
15
+
16
+ def prepare
17
+ # Verify the existance of all the additional files, if any
18
+ @include_files.each do |file|
19
+ raise ActionException.new(:package_include_file_doesnt_exist, :filename => file) unless File.exists?(file)
20
+ end
21
+
22
+ # Get the export action and store a reference to it
23
+ @export_action = @runner.find_action(Export)
24
+ raise ActionException.new(:packaged_requires_export) unless @export_action
25
+ end
26
+
27
+ def execute!
28
+ compress
29
+ end
30
+
31
+ def tar_path
32
+ File.join(FileUtils.pwd, "#{out_path}#{@runner.env.config.package.extension}")
33
+ end
34
+
35
+ def temp_path
36
+ export_action.temp_dir
37
+ end
38
+
39
+ def compress
40
+ logger.info "Packaging VM into #{tar_path} ..."
41
+ File.open(tar_path, File::CREAT | File::WRONLY, 0644) do |tar|
42
+ Archive::Tar::Minitar::Output.open(tar) do |output|
43
+ begin
44
+ current_dir = FileUtils.pwd
45
+
46
+ include_files.each do |f|
47
+ logger.info "Packaging additional file: #{f}"
48
+ Archive::Tar::Minitar.pack_file(f, output)
49
+ end
50
+
51
+ FileUtils.cd(temp_path)
52
+
53
+ Dir.glob(File.join(".", "*")).each do |entry|
54
+ Archive::Tar::Minitar.pack_file(entry, output)
55
+ end
56
+ ensure
57
+ FileUtils.cd(current_dir)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,49 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Provision < Base
5
+ attr_reader :provisioner
6
+
7
+ def intialize(*args)
8
+ super
9
+
10
+ @provisioner = nil
11
+ end
12
+
13
+ def prepare
14
+ provisioner = Vagrant.config.vm.provisioner
15
+
16
+ if provisioner.nil?
17
+ logger.info("Provisioning not enabled, ignoring this step")
18
+ return
19
+ end
20
+
21
+ if provisioner.is_a?(Class)
22
+ @provisioner = provisioner.new(@runner.env)
23
+ raise ActionException.new(:provisioner_invalid_class) unless @provisioner.is_a?(Provisioners::Base)
24
+ elsif provisioner.is_a?(Symbol)
25
+ # We have a few hard coded provisioners for built-ins
26
+ mapping = {
27
+ :chef_solo => Provisioners::ChefSolo,
28
+ :chef_server => Provisioners::ChefServer
29
+ }
30
+
31
+ provisioner_klass = mapping[provisioner]
32
+ raise ActionException.new(:provisioner_unknown_type, :provisioner => provisioner.to_s) if provisioner_klass.nil?
33
+ @provisioner = provisioner_klass.new(@runner.env)
34
+ end
35
+
36
+ logger.info "Provisioning enabled with #{@provisioner.class}"
37
+ @provisioner.prepare
38
+ end
39
+
40
+ def execute!
41
+ if provisioner
42
+ logger.info "Beginning provisioning process..."
43
+ provisioner.provision!
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,17 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Reload < Base
5
+ def prepare
6
+ steps = [Customize, ForwardPorts, SharedFolders, Boot]
7
+ steps.unshift(Halt) if @runner.vm.running?
8
+ steps << Provision if !@runner.env.config.vm.provisioner.nil?
9
+
10
+ steps.each do |action_klass|
11
+ @runner.add_action(action_klass)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class Resume < Base
5
+ def execute!
6
+ if !@runner.vm.saved?
7
+ raise ActionException.new(:vm_not_suspended)
8
+ end
9
+
10
+ logger.info "Resuming suspended VM..."
11
+ @runner.start
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,81 @@
1
+ module Vagrant
2
+ module Actions
3
+ module VM
4
+ class SharedFolders < Base
5
+ def shared_folders
6
+ @runner.env.config.vm.shared_folders.inject([]) do |acc, data|
7
+ name, value = data
8
+ acc << [name, File.expand_path(value[:hostpath]), value[:guestpath]]
9
+ end
10
+ end
11
+
12
+ def before_boot
13
+ clear_shared_folders
14
+ create_metadata
15
+ end
16
+
17
+ def after_boot
18
+ logger.info "Mounting shared folders..."
19
+
20
+ @runner.env.ssh.execute do |ssh|
21
+ shared_folders.each do |name, hostpath, guestpath|
22
+ logger.info "-- #{name}: #{guestpath}"
23
+ ssh.exec!("sudo mkdir -p #{guestpath}")
24
+ mount_folder(ssh, name, guestpath)
25
+ ssh.exec!("sudo chown #{Vagrant.config.ssh.username} #{guestpath}")
26
+ end
27
+ end
28
+ end
29
+
30
+ def clear_shared_folders
31
+ logger.info "Clearing previously set shared folders..."
32
+
33
+ @runner.vm.shared_folders.each do |shared_folder|
34
+ shared_folder.destroy
35
+ end
36
+
37
+ @runner.reload!
38
+ end
39
+
40
+ def create_metadata
41
+ logger.info "Creating shared folders metadata..."
42
+
43
+ shared_folders.each do |name, hostpath, guestpath|
44
+ folder = VirtualBox::SharedFolder.new
45
+ folder.name = name
46
+ folder.hostpath = hostpath
47
+ @runner.vm.shared_folders << folder
48
+ end
49
+
50
+ @runner.vm.save(true)
51
+ end
52
+
53
+ def mount_folder(ssh, name, guestpath, sleeptime=5)
54
+ # Note: This method seems pretty OS-specific and could also use
55
+ # some configuration options. For now its duct tape and "works"
56
+ # but should be looked at in the future.
57
+
58
+ # Determine the permission string to attach to the mount command
59
+ perms = []
60
+ perms << "uid=#{@runner.env.config.vm.shared_folder_uid}"
61
+ perms << "gid=#{@runner.env.config.vm.shared_folder_gid}"
62
+ perms = " -o #{perms.join(",")}" if !perms.empty?
63
+
64
+ attempts = 0
65
+ while true
66
+ result = ssh.exec!("sudo mount -t vboxsf#{perms} #{name} #{guestpath}") do |ch, type, data|
67
+ # net/ssh returns the value in ch[:result] (based on looking at source)
68
+ ch[:result] = !!(type == :stderr && data =~ /No such device/i)
69
+ end
70
+
71
+ break unless result
72
+
73
+ attempts += 1
74
+ raise ActionException.new(:vm_mount_fail) if attempts >= 10
75
+ sleep sleeptime
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end