vagrant-libvirt 0.0.42 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +393 -147
  3. data/lib/vagrant-libvirt/action.rb +3 -2
  4. data/lib/vagrant-libvirt/action/create_domain.rb +87 -37
  5. data/lib/vagrant-libvirt/action/create_domain_volume.rb +19 -14
  6. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +9 -5
  7. data/lib/vagrant-libvirt/action/create_networks.rb +7 -2
  8. data/lib/vagrant-libvirt/action/destroy_domain.rb +1 -1
  9. data/lib/vagrant-libvirt/action/destroy_networks.rb +5 -0
  10. data/lib/vagrant-libvirt/action/forward_ports.rb +10 -8
  11. data/lib/vagrant-libvirt/action/halt_domain.rb +1 -1
  12. data/lib/vagrant-libvirt/action/handle_box_image.rb +26 -15
  13. data/lib/vagrant-libvirt/action/handle_storage_pool.rb +9 -4
  14. data/lib/vagrant-libvirt/action/package_domain.rb +58 -12
  15. data/lib/vagrant-libvirt/action/prepare_nfs_settings.rb +3 -9
  16. data/lib/vagrant-libvirt/action/prune_nfs_exports.rb +19 -9
  17. data/lib/vagrant-libvirt/action/remove_libvirt_image.rb +2 -2
  18. data/lib/vagrant-libvirt/action/remove_stale_volume.rb +17 -11
  19. data/lib/vagrant-libvirt/action/set_boot_order.rb +2 -2
  20. data/lib/vagrant-libvirt/action/set_name_of_domain.rb +6 -9
  21. data/lib/vagrant-libvirt/action/start_domain.rb +2 -2
  22. data/lib/vagrant-libvirt/action/wait_till_up.rb +31 -16
  23. data/lib/vagrant-libvirt/cap/public_address.rb +16 -0
  24. data/lib/vagrant-libvirt/cap/synced_folder.rb +3 -3
  25. data/lib/vagrant-libvirt/config.rb +177 -29
  26. data/lib/vagrant-libvirt/driver.rb +31 -2
  27. data/lib/vagrant-libvirt/errors.rb +5 -1
  28. data/lib/vagrant-libvirt/plugin.rb +7 -2
  29. data/lib/vagrant-libvirt/templates/default_storage_pool.xml.erb +3 -3
  30. data/lib/vagrant-libvirt/templates/domain.xml.erb +48 -8
  31. data/lib/vagrant-libvirt/util.rb +1 -0
  32. data/lib/vagrant-libvirt/util/erb_template.rb +6 -7
  33. data/lib/vagrant-libvirt/util/network_util.rb +33 -13
  34. data/lib/vagrant-libvirt/util/nfs.rb +17 -0
  35. data/lib/vagrant-libvirt/util/storage_util.rb +27 -0
  36. data/lib/vagrant-libvirt/version.rb +1 -1
  37. data/locales/en.yml +8 -4
  38. data/spec/support/environment_helper.rb +1 -1
  39. data/spec/support/libvirt_context.rb +1 -1
  40. data/spec/support/sharedcontext.rb +2 -2
  41. data/spec/unit/action/destroy_domain_spec.rb +2 -2
  42. data/spec/unit/action/set_name_of_domain_spec.rb +3 -3
  43. data/spec/unit/config_spec.rb +173 -0
  44. data/spec/unit/templates/domain_all_settings.xml +20 -4
  45. data/spec/unit/templates/domain_custom_cpu_model.xml +48 -0
  46. data/spec/unit/templates/domain_defaults.xml +2 -0
  47. data/spec/unit/templates/domain_spec.rb +26 -2
  48. metadata +24 -32
  49. data/.coveralls.yml +0 -1
  50. data/.github/issue_template.md +0 -37
  51. data/.gitignore +0 -21
  52. data/.travis.yml +0 -24
  53. data/Gemfile +0 -26
  54. data/Rakefile +0 -8
  55. data/example_box/README.md +0 -29
  56. data/example_box/Vagrantfile +0 -60
  57. data/example_box/metadata.json +0 -5
  58. data/tools/create_box.sh +0 -130
  59. data/tools/prepare_redhat_for_box.sh +0 -119
  60. data/vagrant-libvirt.gemspec +0 -54
@@ -8,7 +8,7 @@ module VagrantPlugins
8
8
  include Vagrant::Action::Builtin
9
9
  @logger = Log4r::Logger.new('vagrant_libvirt::action')
10
10
 
11
- # remove image from libvirt storage pool
11
+ # remove image from Libvirt storage pool
12
12
  def self.remove_libvirt_image
13
13
  Vagrant::Action::Builder.new.tap do |b|
14
14
  b.use RemoveLibvirtImage
@@ -19,6 +19,7 @@ module VagrantPlugins
19
19
  def self.action_up
20
20
  Vagrant::Action::Builder.new.tap do |b|
21
21
  b.use ConfigValidate
22
+ b.use BoxCheckOutdated
22
23
  b.use Call, IsCreated do |env, b2|
23
24
  # Create VM if not yet created.
24
25
  if !env[:result]
@@ -186,7 +187,7 @@ module VagrantPlugins
186
187
  b2.use Call, DestroyConfirm do |env2, b3|
187
188
  if env2[:result]
188
189
  b3.use ClearForwardedPorts
189
- # b3.use PruneNFSExports
190
+ b3.use PruneNFSExports
190
191
  b3.use DestroyDomain
191
192
  b3.use DestroyNetworks
192
193
  b3.use ProvisionerCleanup
@@ -31,16 +31,23 @@ module VagrantPlugins
31
31
 
32
32
  # Gather some info about domain
33
33
  @name = env[:domain_name]
34
+ @title = config.title
35
+ @description = config.description
34
36
  @uuid = config.uuid
35
37
  @cpus = config.cpus.to_i
38
+ @cpuset = config.cpuset
36
39
  @cpu_features = config.cpu_features
37
40
  @cpu_topology = config.cpu_topology
41
+ @nodeset = config.nodeset
38
42
  @features = config.features
43
+ @features_hyperv = config.features_hyperv
44
+ @shares = config.shares
39
45
  @cpu_mode = config.cpu_mode
40
46
  @cpu_model = config.cpu_model
41
47
  @cpu_fallback = config.cpu_fallback
42
48
  @numa_nodes = config.numa_nodes
43
49
  @loader = config.loader
50
+ @nvram = config.nvram
44
51
  @machine_type = config.machine_type
45
52
  @machine_arch = config.machine_arch
46
53
  @disk_bus = config.disk_bus
@@ -79,6 +86,7 @@ module VagrantPlugins
79
86
 
80
87
  # Storage
81
88
  @storage_pool_name = config.storage_pool_name
89
+ @snapshot_pool_name = config.snapshot_pool_name
82
90
  @disks = config.disks
83
91
  @cdroms = config.cdroms
84
92
 
@@ -94,6 +102,9 @@ module VagrantPlugins
94
102
  # Watchdog device
95
103
  @watchdog_dev = config.watchdog_dev
96
104
 
105
+ # USB controller
106
+ @usbctl_dev = config.usbctl_dev
107
+
97
108
  # USB device passthrough
98
109
  @usbs = config.usbs
99
110
 
@@ -101,6 +112,12 @@ module VagrantPlugins
101
112
  @redirdevs = config.redirdevs
102
113
  @redirfilters = config.redirfilters
103
114
 
115
+ # Additional QEMU commandline arguments
116
+ @qemu_args = config.qemu_args
117
+
118
+ # Additional QEMU commandline environment variables
119
+ @qemu_env = config.qemu_env
120
+
104
121
  # smartcard device
105
122
  @smartcard_dev = config.smartcard_dev
106
123
 
@@ -114,13 +131,15 @@ module VagrantPlugins
114
131
 
115
132
  # Get path to domain image from the storage pool selected if we have a box.
116
133
  if env[:machine].config.vm.box
117
- actual_volumes =
118
- env[:machine].provider.driver.connection.volumes.all.select do |x|
119
- x.pool_name == @storage_pool_name
120
- end
121
- domain_volume = ProviderLibvirt::Util::Collection.find_matching(
122
- actual_volumes, "#{@name}.img"
123
- )
134
+ if @snapshot_pool_name != @storage_pool_name
135
+ pool_name = @snapshot_pool_name
136
+ else
137
+ pool_name = @storage_pool_name
138
+ end
139
+ @logger.debug "Search for volume in pool: #{pool_name}"
140
+ domain_volume = env[:machine].provider.driver.connection.volumes.all(
141
+ name: "#{@name}.img"
142
+ ).find { |x| x.pool_name == pool_name }
124
143
  raise Errors::DomainVolumeExists if domain_volume.nil?
125
144
  @domain_volume_path = domain_volume.path
126
145
  end
@@ -128,13 +147,15 @@ module VagrantPlugins
128
147
  # If we have a box, take the path from the domain volume and set our storage_prefix.
129
148
  # If not, we dump the storage pool xml to get its defined path.
130
149
  # the default storage prefix is typically: /var/lib/libvirt/images/
131
- if env[:machine].config.vm.box
132
- storage_prefix = File.dirname(@domain_volume_path) + '/' # steal
133
- else
134
- storage_pool = env[:machine].provider.driver.connection.client.lookup_storage_pool_by_name(@storage_pool_name)
135
- raise Errors::NoStoragePool if storage_pool.nil?
136
- xml = Nokogiri::XML(storage_pool.xml_desc)
137
- storage_prefix = xml.xpath('/pool/target/path').inner_text.to_s + '/'
150
+ if !config.qemu_use_session
151
+ if env[:machine].config.vm.box
152
+ storage_prefix = File.dirname(@domain_volume_path) + '/' # steal
153
+ else
154
+ storage_pool = env[:machine].provider.driver.connection.client.lookup_storage_pool_by_name(@storage_pool_name)
155
+ raise Errors::NoStoragePool if storage_pool.nil?
156
+ xml = Nokogiri::XML(storage_pool.xml_desc)
157
+ storage_prefix = xml.xpath('/pool/target/path').inner_text.to_s + '/'
158
+ end
138
159
  end
139
160
 
140
161
  @disks.each do |disk|
@@ -148,51 +169,67 @@ module VagrantPlugins
148
169
 
149
170
  disk[:absolute_path] = storage_prefix + disk[:path]
150
171
 
151
- if env[:machine].provider.driver.connection.volumes.select do |x|
152
- x.name == disk[:name] && x.pool_name == @storage_pool_name
153
- end.empty?
154
- # make the disk. equivalent to:
155
- # qemu-img create -f qcow2 <path> 5g
156
- begin
157
- env[:machine].provider.driver.connection.volumes.create(
158
- name: disk[:name],
159
- format_type: disk[:type],
160
- path: disk[:absolute_path],
161
- capacity: disk[:size],
162
- #:allocation => ?,
163
- pool_name: @storage_pool_name
164
- )
165
- rescue Fog::Errors::Error => e
172
+ # make the disk. equivalent to:
173
+ # qemu-img create -f qcow2 <path> 5g
174
+ begin
175
+ env[:machine].provider.driver.connection.volumes.create(
176
+ name: disk[:name],
177
+ format_type: disk[:type],
178
+ path: disk[:absolute_path],
179
+ capacity: disk[:size],
180
+ #:allocation => ?,
181
+ pool_name: @storage_pool_name
182
+ )
183
+ rescue Libvirt::Error => e
184
+ # It is hard to believe that e contains just a string
185
+ # and no useful error code!
186
+ msg = "Call to virStorageVolCreateXML failed: " +
187
+ "storage volume '#{disk[:path]}' exists already"
188
+ if e.message == msg and disk[:allow_existing]
189
+ disk[:preexisting] = true
190
+ else
166
191
  raise Errors::FogDomainVolumeCreateError,
167
192
  error_message: e.message
168
193
  end
169
- else
170
- disk[:preexisting] = true
171
194
  end
172
195
  end
173
196
 
174
197
  # Output the settings we're going to use to the user
175
198
  env[:ui].info(I18n.t('vagrant_libvirt.creating_domain'))
176
199
  env[:ui].info(" -- Name: #{@name}")
200
+ env[:ui].info(" -- Title: #{@title}") if @title != ''
201
+ env[:ui].info(" -- Description: #{@description}") if @description != ''
177
202
  env[:ui].info(" -- Forced UUID: #{@uuid}") if @uuid != ''
178
203
  env[:ui].info(" -- Domain type: #{@domain_type}")
179
204
  env[:ui].info(" -- Cpus: #{@cpus}")
205
+ unless @cpuset.nil?
206
+ env[:ui].info(" -- Cpuset: #{@cpuset}")
207
+ end
180
208
  if not @cpu_topology.empty?
181
209
  env[:ui].info(" -- CPU topology: sockets=#{@cpu_topology[:sockets]}, cores=#{@cpu_topology[:cores]}, threads=#{@cpu_topology[:threads]}")
182
210
  end
183
- env[:ui].info("")
184
211
  @cpu_features.each do |cpu_feature|
185
212
  env[:ui].info(" -- CPU Feature: name=#{cpu_feature[:name]}, policy=#{cpu_feature[:policy]}")
186
213
  end
187
214
  @features.each do |feature|
188
215
  env[:ui].info(" -- Feature: #{feature}")
189
216
  end
217
+ @features_hyperv.each do |feature|
218
+ env[:ui].info(" -- Feature (HyperV): name=#{feature[:name]}, state=#{feature[:state]}")
219
+ end
190
220
  env[:ui].info(" -- Memory: #{@memory_size / 1024}M")
221
+ unless @nodeset.nil?
222
+ env[:ui].info(" -- Nodeset: #{@nodeset}")
223
+ end
191
224
  @memory_backing.each do |backing|
192
225
  env[:ui].info(" -- Memory Backing: #{backing[:name]}: #{backing[:config].map { |k,v| "#{k}='#{v}'"}.join(' ')}")
193
226
  end
227
+ unless @shares.nil?
228
+ env[:ui].info(" -- Shares: #{@shares}")
229
+ end
194
230
  env[:ui].info(" -- Management MAC: #{@management_network_mac}")
195
231
  env[:ui].info(" -- Loader: #{@loader}")
232
+ env[:ui].info(" -- Nvram: #{@nvram}")
196
233
  if env[:machine].config.vm.box
197
234
  env[:ui].info(" -- Base box: #{env[:machine].box.name}")
198
235
  end
@@ -245,7 +282,7 @@ module VagrantPlugins
245
282
  end
246
283
 
247
284
  @pcis.each do |pci|
248
- env[:ui].info(" -- PCI passthrough: #{pci[:bus]}:#{pci[:slot]}.#{pci[:function]}")
285
+ env[:ui].info(" -- PCI passthrough: #{pci[:domain]}:#{pci[:bus]}:#{pci[:slot]}.#{pci[:function]}")
249
286
  end
250
287
 
251
288
  unless @rng[:model].nil?
@@ -256,6 +293,12 @@ module VagrantPlugins
256
293
  env[:ui].info(" -- Watchdog device: model=#{@watchdog_dev[:model]}, action=#{@watchdog_dev[:action]}")
257
294
  end
258
295
 
296
+ if not @usbctl_dev.empty?
297
+ msg = " -- USB controller: model=#{@usbctl_dev[:model]}"
298
+ msg += ", ports=#{@usbctl_dev[:ports]}" if @usbctl_dev[:ports]
299
+ env[:ui].info(msg)
300
+ end
301
+
259
302
  @usbs.each do |usb|
260
303
  usb_dev = []
261
304
  usb_dev.push("bus=#{usb[:bus]}") if usb[:bus]
@@ -289,18 +332,25 @@ module VagrantPlugins
289
332
  env[:ui].info(" -- smartcard device: mode=#{@smartcard_dev[:mode]}, type=#{@smartcard_dev[:type]}")
290
333
  end
291
334
 
292
- @qargs = config.qemu_args
293
- if not @qargs.empty?
335
+ unless @qemu_args.empty?
294
336
  env[:ui].info(' -- Command line args: ')
295
- @qargs.each do |arg|
337
+ @qemu_args.each do |arg|
296
338
  msg = " -> value=#{arg[:value]}, "
297
339
  env[:ui].info(msg)
298
340
  end
299
341
  end
300
342
 
343
+ unless @qemu_env.empty?
344
+ env[:ui].info(' -- Command line environment variables: ')
345
+ @qemu_env.each do |env_var, env_value|
346
+ msg = " -> #{env_var}=#{env_value}, "
347
+ env[:ui].info(msg)
348
+ end
349
+ end
350
+
301
351
  env[:ui].info(" -- Command line : #{@cmd_line}") unless @cmd_line.empty?
302
352
 
303
- # Create libvirt domain.
353
+ # Create Libvirt domain.
304
354
  # Is there a way to tell fog to create new domain with already
305
355
  # existing volume? Use domain creation from template..
306
356
  begin
@@ -8,6 +8,7 @@ module VagrantPlugins
8
8
  # image as new domain volume.
9
9
  class CreateDomainVolume
10
10
  include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
11
+ include VagrantPlugins::ProviderLibvirt::Util::StorageUtil
11
12
 
12
13
  def initialize(app, _env)
13
14
  @logger = Log4r::Logger.new('vagrant_libvirt::action::create_domain_volume')
@@ -24,15 +25,15 @@ module VagrantPlugins
24
25
  @name = "#{env[:domain_name]}.img"
25
26
 
26
27
  # Verify the volume doesn't exist already.
27
- domain_volume = ProviderLibvirt::Util::Collection.find_matching(
28
- env[:machine].provider.driver.connection.volumes.all, @name
29
- )
30
- raise Errors::DomainVolumeExists if domain_volume
28
+ domain_volume = env[:machine].provider.driver.connection.volumes.all(
29
+ name: @name
30
+ ).first
31
+ raise Errors::DomainVolumeExists if domain_volume && domain_volume.id
31
32
 
32
33
  # Get path to backing image - box volume.
33
- box_volume = ProviderLibvirt::Util::Collection.find_matching(
34
- env[:machine].provider.driver.connection.volumes.all, env[:box_volume_name]
35
- )
34
+ box_volume = env[:machine].provider.driver.connection.volumes.all(
35
+ name: env[:box_volume_name]
36
+ ).first
36
37
  @backing_file = box_volume.path
37
38
 
38
39
  # Virtual size of image. Take value worked out by HandleBoxImage
@@ -48,9 +49,8 @@ module VagrantPlugins
48
49
  xml.target do
49
50
  xml.format(type: 'qcow2')
50
51
  xml.permissions do
51
- xml.owner 0
52
- xml.group 0
53
- xml.mode '0600'
52
+ xml.owner storage_uid(env)
53
+ xml.group storage_gid(env)
54
54
  xml.label 'virt_image_t'
55
55
  end
56
56
  end
@@ -58,9 +58,8 @@ module VagrantPlugins
58
58
  xml.path(@backing_file)
59
59
  xml.format(type: 'qcow2')
60
60
  xml.permissions do
61
- xml.owner 0
62
- xml.group 0
63
- xml.mode '0600'
61
+ xml.owner storage_uid(env)
62
+ xml.group storage_gid(env)
64
63
  xml.label 'virt_image_t'
65
64
  end
66
65
  end
@@ -70,9 +69,15 @@ module VagrantPlugins
70
69
  Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS |
71
70
  Nokogiri::XML::Node::SaveOptions::FORMAT
72
71
  )
72
+ if config.snapshot_pool_name != config.storage_pool_name
73
+ pool_name = config.snapshot_pool_name
74
+ else
75
+ pool_name = config.storage_pool_name
76
+ end
77
+ @logger.debug "Using pool #{pool_name} for base box snapshot"
73
78
  domain_volume = env[:machine].provider.driver.connection.volumes.create(
74
79
  xml: xml,
75
- pool_name: config.storage_pool_name
80
+ pool_name: pool_name
76
81
  )
77
82
  rescue Fog::Errors::Error => e
78
83
  raise Errors::FogDomainVolumeCreateError,
@@ -80,6 +80,8 @@ module VagrantPlugins
80
80
  @pci_bus = iface_configuration.fetch(:bus, nil)
81
81
  @pci_slot = iface_configuration.fetch(:slot, nil)
82
82
  template_name = 'interface'
83
+ @type = nil
84
+ @udp_tunnel = nil
83
85
  # Configuration for public interfaces which use the macvtap driver
84
86
  if iface_configuration[:iface_type] == :public_network
85
87
  @device = iface_configuration.fetch(:dev, 'eth0')
@@ -217,10 +219,12 @@ module VagrantPlugins
217
219
  networks_to_configure << network
218
220
  end
219
221
 
220
- env[:ui].info I18n.t('vagrant.actions.vm.network.configuring')
221
- env[:machine].guest.capability(
222
- :configure_networks, networks_to_configure
223
- )
222
+ unless networks_to_configure.empty?
223
+ env[:ui].info I18n.t('vagrant.actions.vm.network.configuring')
224
+ env[:machine].guest.capability(
225
+ :configure_networks, networks_to_configure
226
+ )
227
+ end
224
228
 
225
229
  end
226
230
  end
@@ -279,7 +283,7 @@ module VagrantPlugins
279
283
  return options[:network_name]
280
284
  end
281
285
 
282
- # Get list of all (active and inactive) libvirt networks.
286
+ # Get list of all (active and inactive) Libvirt networks.
283
287
  available_networks = libvirt_networks(libvirt_client)
284
288
 
285
289
  return 'public' if options[:iface_type] == :public_network
@@ -27,6 +27,11 @@ module VagrantPlugins
27
27
  end
28
28
 
29
29
  def call(env)
30
+ if env[:machine].provider_config.qemu_use_session
31
+ @app.call(env)
32
+ return
33
+ end
34
+
30
35
  # only one vm at a time should try to set up networks
31
36
  # otherwise they'll have inconsitent views of current state
32
37
  # and conduct redundant operations that cause errors
@@ -42,9 +47,9 @@ module VagrantPlugins
42
47
  # should fix other methods so this doesn't have to be instance var
43
48
  @options = options
44
49
 
45
- # Get a list of all (active and inactive) libvirt networks. This
50
+ # Get a list of all (active and inactive) Libvirt networks. This
46
51
  # list is used throughout this class and should be easier to
47
- # process than libvirt API calls.
52
+ # process than Libvirt API calls.
48
53
  @available_networks = libvirt_networks(
49
54
  env[:machine].provider.driver.connection.client
50
55
  )
@@ -14,7 +14,7 @@ module VagrantPlugins
14
14
  env[:ui].info(I18n.t('vagrant_libvirt.destroy_domain'))
15
15
 
16
16
  # Must delete any snapshots before domain can be destroyed
17
- # Fog libvirt currently doesn't support snapshots. Use
17
+ # Fog Libvirt currently doesn't support snapshots. Use
18
18
  # ruby-libvirt client directly. Note this is racy, see
19
19
  # http://www.libvirt.org/html/libvirt-libvirt.html#virDomainSnapshotListNames
20
20
  libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
@@ -13,6 +13,11 @@ module VagrantPlugins
13
13
  end
14
14
 
15
15
  def call(env)
16
+ if env[:machine].provider_config.qemu_use_session
17
+ @app.call(env)
18
+ return
19
+ end
20
+
16
21
  # If there were some networks created for this machine, in machines
17
22
  # data directory, created_networks file holds UUIDs of each network.
18
23
  created_networks_file = env[:machine].data_dir + 'created_networks'
@@ -48,13 +48,13 @@ module VagrantPlugins
48
48
  ))
49
49
 
50
50
  if fp[:protocol] == 'udp'
51
- env[:ui].warn I18n.t('vagrant_libvirt.warnings.forwarding_udp')
51
+ @env[:ui].warn I18n.t('vagrant_libvirt.warnings.forwarding_udp')
52
52
  next
53
53
  end
54
54
 
55
55
  ssh_pid = redirect_port(
56
56
  @env[:machine],
57
- fp[:host_ip] || 'localhost',
57
+ fp[:host_ip] || '*',
58
58
  fp[:host],
59
59
  fp[:guest_ip] || @env[:machine].provider.ssh_info[:host],
60
60
  fp[:guest],
@@ -97,6 +97,8 @@ module VagrantPlugins
97
97
  User=#{ssh_info[:username]}
98
98
  Port=#{ssh_info[:port]}
99
99
  UserKnownHostsFile=/dev/null
100
+ ExitOnForwardFailure=yes
101
+ ControlMaster=no
100
102
  StrictHostKeyChecking=no
101
103
  PasswordAuthentication=no
102
104
  ForwardX11=#{ssh_info[:forward_x11] ? 'yes' : 'no'}
@@ -108,7 +110,7 @@ module VagrantPlugins
108
110
  options += " -o ProxyCommand=\"#{ssh_info[:proxy_command]}\"" if machine.provider_config.connect_via_ssh
109
111
 
110
112
  # TODO: instead of this, try and lock and get the stdin from spawn...
111
- ssh_cmd = 'exec '
113
+ ssh_cmd = ''
112
114
  if host_port <= 1024
113
115
  @@lock.synchronize do
114
116
  # TODO: add i18n
@@ -120,13 +122,13 @@ module VagrantPlugins
120
122
  end
121
123
  end
122
124
 
123
- ssh_cmd << "ssh #{options} #{params}"
125
+ ssh_cmd << "ssh -n #{options} #{params}"
124
126
 
125
127
  @logger.debug "Forwarding port with `#{ssh_cmd}`"
126
128
  log_file = ssh_forward_log_file(host_ip, host_port,
127
129
  guest_ip, guest_port)
128
130
  @logger.info "Logging to #{log_file}"
129
- spawn(ssh_cmd, [:out, :err] => [log_file, 'w'])
131
+ spawn(ssh_cmd, [:out, :err] => [log_file, 'w'], :pgroup => true)
130
132
  end
131
133
 
132
134
  def ssh_forward_log_file(host_ip, host_port, guest_ip, guest_port)
@@ -210,9 +212,9 @@ module VagrantPlugins
210
212
  end
211
213
 
212
214
  def ssh_pid?(pid)
213
- @logger.debug 'Checking if #{pid} is an ssh process '\
214
- 'with `ps -o cmd= #{pid}`'
215
- `ps -o cmd= #{pid}`.strip.chomp =~ /ssh/
215
+ @logger.debug "Checking if #{pid} is an ssh process "\
216
+ "with `ps -o command= #{pid}`"
217
+ `ps -o command= #{pid}`.strip.chomp =~ /ssh/
216
218
  end
217
219
 
218
220
  def remove_ssh_pids