vagrant 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ begin
10
10
  gemspec.homepage = "http://github.com/mitchellh/vagrant"
11
11
  gemspec.authors = ["Mitchell Hashimoto", "John Bender"]
12
12
 
13
- gemspec.add_dependency('virtualbox', '~> 0.7.0')
13
+ gemspec.add_dependency('virtualbox', '~> 0.7.3')
14
14
  gemspec.add_dependency('net-ssh', '>= 2.0.19')
15
15
  gemspec.add_dependency('net-scp', '>= 1.0.2')
16
16
  gemspec.add_dependency('json', '>= 1.2.0')
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.4.2
@@ -27,10 +27,16 @@ Vagrant::Config.run do |config|
27
27
  # other Vagrantfiles, if they wish.
28
28
  config.vm.share_folder("v-root", "/vagrant", ".")
29
29
 
30
- # TODO new config class
31
- config.vm.sync_opts = "-terse -group -owner -batch -silent"
32
- config.vm.sync_script = "/tmp/sync"
33
- config.vm.sync_crontab_entry_file = "/tmp/crontab-entry"
30
+ config.unison.folder_suffix = ".sync"
31
+ config.unison.script = "/tmp/vagrant-unison"
32
+ config.unison.options = "-terse -owner -group -batch"
33
+ config.unison.crontab_entry_file = "/tmp/vagrant-unison-crontab"
34
+ config.unison.log_file = "/tmp/v-unison-log-%s"
35
+
36
+ # TODO fix these
37
+ # config.vm.sync_opts = "-terse -group -owner -batch -silent"
38
+ # config.vm.sync_script = "/tmp/sync"
39
+ # config.vm.sync_crontab_entry_file = "/tmp/crontab-entry"
34
40
 
35
41
  config.package.name = 'vagrant'
36
42
  config.package.extension = '.box'
@@ -100,18 +100,10 @@ module Vagrant
100
100
  def used_ports
101
101
  result = VirtualBox::VM.all.collect do |vm|
102
102
  if vm.running? && vm.uuid != runner.uuid
103
- if VirtualBox.version =~ /^3\.1\./
104
- # VirtualBox 3.1.x uses forwarded ports via extra-data
105
- vm.forwarded_ports.collect do |fp|
103
+ vm.network_adapters.collect do |na|
104
+ na.nat_driver.forwarded_ports.collect do |fp|
106
105
  fp.hostport.to_s
107
106
  end
108
- else
109
- # VirtualBox 3.2.x uses forwarded ports via NAT engines
110
- vm.network_adapters.collect do |na|
111
- na.nat_driver.forwarded_ports.collect do |fp|
112
- fp.hostport.to_s
113
- end
114
- end
115
107
  end
116
108
  end
117
109
  end
@@ -121,34 +113,20 @@ module Vagrant
121
113
 
122
114
  # Deletes existing forwarded ports.
123
115
  def clear_ports
124
- if VirtualBox.version =~ /^3\.1\./
125
- fp = runner.vm.forwarded_ports.dup
126
- fp.each { |p| p.destroy }
127
- else
128
- runner.vm.network_adapters.each do |na|
129
- na.nat_driver.forwarded_ports.dup.each do |fp|
130
- fp.destroy
131
- end
116
+ runner.vm.network_adapters.each do |na|
117
+ na.nat_driver.forwarded_ports.dup.each do |fp|
118
+ fp.destroy
132
119
  end
133
120
  end
134
121
  end
135
122
 
136
123
  # Forwards a port.
137
124
  def forward_port(name, options)
138
- if VirtualBox.version =~ /^3\.1\./
139
- port = VirtualBox::ForwardedPort.new
140
- port.name = name
141
- port.hostport = options[:hostport]
142
- port.guestport = options[:guestport]
143
- port.instance = options[:adapter]
144
- runner.vm.forwarded_ports << port
145
- else
146
- port = VirtualBox::NATForwardedPort.new
147
- port.name = name
148
- port.guestport = options[:guestport]
149
- port.hostport = options[:hostport]
150
- runner.vm.network_adapters[options[:adapter]].nat_driver.forwarded_ports << port
151
- end
125
+ port = VirtualBox::NATForwardedPort.new
126
+ port.name = name
127
+ port.guestport = options[:guestport]
128
+ port.hostport = options[:hostport]
129
+ runner.vm.network_adapters[options[:adapter]].nat_driver.forwarded_ports << port
152
130
  end
153
131
  end
154
132
  end
@@ -2,6 +2,13 @@ module Vagrant
2
2
  module Actions
3
3
  module VM
4
4
  class Network < Base
5
+ def prepare
6
+ # Verify that the given network options are valid
7
+ runner.env.config.vm.network_options.compact.each do |network_options|
8
+ verify_no_bridge_collision(network_options)
9
+ end
10
+ end
11
+
5
12
  def before_destroy
6
13
  # We need to check if the host only network specified by any
7
14
  # of the adapters would not have any more clients if it was
@@ -55,6 +62,24 @@ module Vagrant
55
62
  end
56
63
  end
57
64
 
65
+ # Verifies that there is no collision with a bridged network interface
66
+ # for the given network options.
67
+ def verify_no_bridge_collision(net_options)
68
+ # First try to find a matching network
69
+ interfaces = VirtualBox::Global.global.host.network_interfaces
70
+ interfaces.each do |ni|
71
+ next if ni.interface_type == :host_only
72
+
73
+ result = if net_options[:name]
74
+ true if net_options[:name] == ni.name
75
+ else
76
+ true if matching_network?(ni, net_options)
77
+ end
78
+
79
+ raise ActionException.new(:network_collides) if result
80
+ end
81
+ end
82
+
58
83
  # Returns the name of the proper host only network, or creates
59
84
  # it if it does not exist. Vagrant determines if the host only
60
85
  # network exists by comparing the netmask and the IP.
@@ -62,6 +87,10 @@ module Vagrant
62
87
  # First try to find a matching network
63
88
  interfaces = VirtualBox::Global.global.host.network_interfaces
64
89
  interfaces.each do |ni|
90
+ # Ignore non-host only interfaces which may also match,
91
+ # since they're not valid options.
92
+ next if ni.interface_type != :host_only
93
+
65
94
  if net_options[:name]
66
95
  return ni.name if net_options[:name] == ni.name
67
96
  else
@@ -10,6 +10,8 @@ module Vagrant
10
10
  end
11
11
 
12
12
  def prepare
13
+ raise ActionException.new(:box_file_exists, :output_file => tar_path) if File.exist?(tar_path)
14
+
13
15
  # Verify the existance of all the additional files, if any
14
16
  include_files.each do |file|
15
17
  raise ActionException.new(:package_include_file_doesnt_exist, :filename => file) unless File.exists?(file)
@@ -2,10 +2,34 @@ module Vagrant
2
2
  module Actions
3
3
  module VM
4
4
  class SharedFolders < Base
5
+ # This method returns an actual list of VirtualBox shared
6
+ # folders to create and their proper path.
5
7
  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], @runner.env.root_path), value[:guestpath], value[:syncpath]].compact
8
+ runner.env.config.vm.shared_folders.inject({}) do |acc, data|
9
+ key, value = data
10
+
11
+ # This to prevent overwriting the actual shared folders data
12
+ value = value.dup
13
+
14
+ if value[:sync]
15
+ # Syncing this folder. Change the guestpath to reflect
16
+ # what we're actually mounting.
17
+ value[:original] = value.dup
18
+ value[:guestpath] = "#{value[:guestpath]}#{runner.env.config.unison.folder_suffix}"
19
+ end
20
+
21
+ acc[key] = value
22
+ acc
23
+ end
24
+ end
25
+
26
+ # This method returns the list of shared folders which are to
27
+ # be synced via unison.
28
+ def unison_folders
29
+ shared_folders.inject({}) do |acc, data|
30
+ key, value = data
31
+ acc[key] = value if !!value[:sync]
32
+ acc
9
33
  end
10
34
  end
11
35
 
@@ -15,17 +39,30 @@ module Vagrant
15
39
  end
16
40
 
17
41
  def after_boot
42
+ mount_shared_folders
43
+ setup_unison
44
+ end
45
+
46
+ def mount_shared_folders
18
47
  logger.info "Mounting shared folders..."
19
48
 
20
49
  @runner.ssh.execute do |ssh|
21
- @runner.system.prepare_sync(ssh) if @runner.env.config.vm.sync_required
22
-
23
- shared_folders.each do |name, hostpath, guestpath, syncpath|
24
- logger.info "-- #{name}: #{syncpath ? guestpath + " -sync-> " + syncpath : guestpath}"
25
- @runner.system.mount_shared_folder(ssh, name, guestpath)
26
- if syncpath
27
- @runner.system.create_sync(ssh, :syncpath => syncpath, :guestpath => guestpath)
28
- end
50
+ shared_folders.each do |name, data|
51
+ logger.info "-- #{name}: #{data[:guestpath]}"
52
+ @runner.system.mount_shared_folder(ssh, name, data[:guestpath])
53
+ end
54
+ end
55
+ end
56
+
57
+ def setup_unison
58
+ return if unison_folders.empty?
59
+
60
+ runner.ssh.execute do |ssh|
61
+ runner.system.prepare_unison(ssh)
62
+
63
+ logger.info "Creating unison crontab entries..."
64
+ unison_folders.each do |name, data|
65
+ runner.system.create_unison(ssh, data)
29
66
  end
30
67
  end
31
68
  end
@@ -46,10 +83,10 @@ module Vagrant
46
83
  def create_metadata
47
84
  logger.info "Creating shared folders metadata..."
48
85
 
49
- shared_folders.each do |name, hostpath, guestpath|
86
+ shared_folders.each do |name, data|
50
87
  folder = VirtualBox::SharedFolder.new
51
88
  folder.name = name
52
- folder.host_path = hostpath
89
+ folder.host_path = File.expand_path(data[:hostpath], runner.env.root_path)
53
90
  @runner.vm.shared_folders << folder
54
91
  end
55
92
 
@@ -77,6 +77,14 @@ module Vagrant
77
77
  end
78
78
  end
79
79
 
80
+ class UnisonConfig < Base
81
+ attr_accessor :folder_suffix
82
+ attr_accessor :script
83
+ attr_accessor :options
84
+ attr_accessor :crontab_entry_file
85
+ attr_accessor :log_file
86
+ end
87
+
80
88
  class VMConfig < Base
81
89
  include Util::StackedProcRunner
82
90
 
@@ -85,10 +93,6 @@ module Vagrant
85
93
  attr_accessor :box_ovf
86
94
  attr_accessor :base_mac
87
95
  attr_accessor :boot_mode
88
- attr_accessor :sync_opts
89
- attr_accessor :sync_script
90
- attr_accessor :sync_crontab_entry_file
91
- attr_reader :sync_required
92
96
  attr_reader :forwarded_ports
93
97
  attr_reader :shared_folders
94
98
  attr_reader :network_options
@@ -128,19 +132,11 @@ module Vagrant
128
132
  forwarded_ports[name] = options
129
133
  end
130
134
 
131
- def share_folder(name, guestpath, hostpath = nil, opts = {})
132
- guestpath, opts[:sync] = shift(guestpath, opts[:sync])
133
-
134
- # TODO if both are nil the exception information will be unusable
135
- if opts[:sync] == guestpath
136
- raise Exception.new("The sync directory #{opts[:sync]} is identical to the shifted shared folder mount point #{guestpath}")
137
- end
138
-
135
+ def share_folder(name, guestpath, hostpath, opts=nil)
139
136
  @shared_folders[name] = {
140
- :syncpath => opts[:sync],
141
137
  :guestpath => guestpath,
142
138
  :hostpath => hostpath
143
- }
139
+ }.merge(opts || {})
144
140
  end
145
141
 
146
142
  def network(ip, options=nil)
@@ -185,15 +181,6 @@ module Vagrant
185
181
  defined_vms[name.to_sym].options.merge!(options)
186
182
  defined_vms[name.to_sym].push_proc(&block)
187
183
  end
188
-
189
- def shift(orig, sync)
190
- if sync
191
- @sync_required = true
192
- [orig + '-sync', sync == true ? orig : sync]
193
- else
194
- [orig, sync]
195
- end
196
- end
197
184
  end
198
185
 
199
186
  class PackageConfig < Base
@@ -228,6 +215,7 @@ module Vagrant
228
215
  # Setup default configures
229
216
  configures :package, PackageConfig
230
217
  configures :ssh, SSHConfig
218
+ configures :unison, UnisonConfig
231
219
  configures :vm, VMConfig
232
220
  configures :vagrant, VagrantConfig
233
221
 
@@ -40,7 +40,7 @@ module Vagrant
40
40
  version = VirtualBox.version
41
41
  if version.nil?
42
42
  error_and_exit(:virtualbox_not_detected)
43
- elsif version.to_f < 3.1
43
+ elsif version.to_f < 3.2
44
44
  error_and_exit(:virtualbox_invalid_version, :version => version.to_s)
45
45
  elsif version.to_s.downcase.include?("ose")
46
46
  error_and_exit(:virtualbox_invalid_ose, :version => version.to_s)
@@ -24,6 +24,7 @@ module Vagrant
24
24
  end
25
25
 
26
26
  options = {}
27
+ options[:port] = port(opts)
27
28
  [:host, :username, :private_key_path].each do |param|
28
29
  options[param] = opts[param] || env.config.ssh.send(param)
29
30
  end
@@ -35,7 +36,7 @@ module Vagrant
35
36
  # we simply exec.
36
37
  pid = nil
37
38
  pid = fork if Util::Platform.leopard?
38
- Kernel.exec "ssh -p #{port(opts)} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i #{options[:private_key_path]} #{options[:username]}@#{options[:host]}".strip if pid.nil?
39
+ Kernel.exec "ssh -p #{options[:port]} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i #{options[:private_key_path]} #{options[:username]}@#{options[:host]}".strip if pid.nil?
39
40
  Process.wait(pid) if pid
40
41
  end
41
42
 
@@ -132,20 +133,13 @@ module Vagrant
132
133
  return pnum if pnum
133
134
 
134
135
  # Check if we have an SSH forwarded port
135
- if VirtualBox.version =~ /^3\.1\./
136
- pnum = env.vm.vm.forwarded_ports.detect do |fp|
136
+ pnum = nil
137
+ env.vm.vm.network_adapters.each do |na|
138
+ pnum = na.nat_driver.forwarded_ports.detect do |fp|
137
139
  fp.name == env.config.ssh.forwarded_port_key
138
140
  end
139
- else
140
- # VirtualBox 3.2 specific
141
- pnum = nil
142
- env.vm.vm.network_adapters.each do |na|
143
- pnum = na.nat_driver.forwarded_ports.detect do |fp|
144
- fp.name == env.config.ssh.forwarded_port_key
145
- end
146
141
 
147
- break if pnum
148
- end
142
+ break if pnum
149
143
  end
150
144
 
151
145
  return pnum.hostport if pnum
@@ -55,6 +55,13 @@ module Vagrant
55
55
  # wants the folder mounted.
56
56
  def mount_shared_folder(ssh, name, guestpath); end
57
57
 
58
+ # Prepares the system for unison folder syncing. This is called
59
+ # once once prior to any `create_unison` calls.
60
+ def prepare_unison(ssh); end
61
+
62
+ # Creates an entry for folder syncing via unison.
63
+ def create_unison(ssh, options); end
64
+
58
65
  # Prepares the system for host only networks. This is called
59
66
  # once prior to any `enable_host_only_network` calls.
60
67
  def prepare_host_only_network; end
@@ -17,7 +17,7 @@ module Vagrant
17
17
  attr_accessor :halt_check_interval
18
18
 
19
19
  def initialize
20
- @halt_timeout = 15
20
+ @halt_timeout = 30
21
21
  @halt_check_interval = 1
22
22
  end
23
23
  end
@@ -49,24 +49,31 @@ module Vagrant
49
49
  def mount_shared_folder(ssh, name, guestpath)
50
50
  ssh.exec!("sudo mkdir -p #{guestpath}")
51
51
  mount_folder(ssh, name, guestpath)
52
- chown(ssh, guestpath)
52
+ ssh.exec!("sudo chown #{config.ssh.username} #{guestpath}")
53
53
  end
54
54
 
55
- def create_sync(ssh, opts)
56
- crontab_entry = render_crontab_entry(opts.merge(:syncopts => config.vm.sync_opts,
57
- :scriptname => config.vm.sync_script))
55
+ def prepare_unison(ssh)
56
+ ssh.exec!("which unison", :error_key => :unison_not_found)
58
57
 
59
- ssh.exec!("sudo mkdir -p #{opts[:syncpath]}")
60
- chown(ssh, opts[:syncpath])
61
- ssh.exec!("sudo echo \"#{crontab_entry}\" >> #{config.vm.sync_crontab_entry_file}")
62
- ssh.exec!("crontab #{config.vm.sync_crontab_entry_file}")
58
+ logger.info "Preparing system for unison sync..."
59
+ vm.ssh.upload!(StringIO.new(TemplateRenderer.render('/unison/script')), config.unison.script)
60
+ ssh.exec!("sudo chmod +x #{config.unison.script}")
61
+ ssh.exec!("sudo rm #{config.unison.crontab_entry_file}", :error_check => false)
63
62
  end
64
63
 
65
- def prepare_sync(ssh)
66
- logger.info "Preparing system for sync..."
67
- vm.ssh.upload!(StringIO.new(render_sync), config.vm.sync_script)
68
- ssh.exec!("sudo chmod +x #{config.vm.sync_script}")
69
- ssh.exec!("sudo rm #{config.vm.sync_crontab_entry_file}", :error_check => false)
64
+ def create_unison(ssh, opts)
65
+ sanitized_string = opts[:original][:guestpath].gsub(/[^a-zA-Z0-9_-]/, '-')
66
+ crontab_entry = TemplateRenderer.render('/unison/crontab_entry',
67
+ :from => opts[:guestpath],
68
+ :to => opts[:original][:guestpath],
69
+ :options => config.unison.options,
70
+ :script => config.unison.script,
71
+ :log_file => (config.unison.log_file % sanitized_string))
72
+
73
+ ssh.exec!("sudo rm -rf ~/.unison")
74
+ ssh.exec!("sudo rm -rf #{opts[:original][:guestpath]}")
75
+ ssh.exec!("sudo echo \"#{crontab_entry}\" >> #{config.unison.crontab_entry_file}")
76
+ ssh.exec!("crontab #{config.unison.crontab_entry_file}")
70
77
  end
71
78
 
72
79
  def prepare_host_only_network
@@ -117,21 +124,9 @@ module Vagrant
117
124
  end
118
125
  end
119
126
 
120
- def chown(ssh, dir)
121
- ssh.exec!("sudo chown #{config.ssh.username} #{dir}")
122
- end
123
-
124
127
  def config
125
128
  vm.env.config
126
129
  end
127
-
128
- def render_sync
129
- TemplateRenderer.render('sync')
130
- end
131
-
132
- def render_crontab_entry(opts)
133
- TemplateRenderer.render('crontab_entry', opts)
134
- end
135
130
  end
136
131
  end
137
132
  end