vagrant-libvirt 0.3.0 → 0.5.2

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +421 -50
  3. data/lib/vagrant-libvirt/action.rb +7 -1
  4. data/lib/vagrant-libvirt/action/clean_machine_folder.rb +30 -0
  5. data/lib/vagrant-libvirt/action/create_domain.rb +56 -18
  6. data/lib/vagrant-libvirt/action/create_domain_volume.rb +57 -55
  7. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +0 -3
  8. data/lib/vagrant-libvirt/action/create_networks.rb +11 -4
  9. data/lib/vagrant-libvirt/action/destroy_domain.rb +1 -1
  10. data/lib/vagrant-libvirt/action/forward_ports.rb +37 -38
  11. data/lib/vagrant-libvirt/action/halt_domain.rb +25 -9
  12. data/lib/vagrant-libvirt/action/handle_box_image.rb +163 -74
  13. data/lib/vagrant-libvirt/action/is_running.rb +1 -3
  14. data/lib/vagrant-libvirt/action/is_suspended.rb +4 -4
  15. data/lib/vagrant-libvirt/action/package_domain.rb +2 -1
  16. data/lib/vagrant-libvirt/action/set_boot_order.rb +6 -2
  17. data/lib/vagrant-libvirt/action/start_domain.rb +86 -29
  18. data/lib/vagrant-libvirt/action/wait_till_up.rb +8 -52
  19. data/lib/vagrant-libvirt/cap/{mount_p9.rb → mount_9p.rb} +2 -2
  20. data/lib/vagrant-libvirt/cap/mount_virtiofs.rb +37 -0
  21. data/lib/vagrant-libvirt/cap/{synced_folder.rb → synced_folder_9p.rb} +4 -5
  22. data/lib/vagrant-libvirt/cap/synced_folder_virtiofs.rb +109 -0
  23. data/lib/vagrant-libvirt/config.rb +236 -43
  24. data/lib/vagrant-libvirt/driver.rb +49 -32
  25. data/lib/vagrant-libvirt/errors.rb +24 -1
  26. data/lib/vagrant-libvirt/plugin.rb +14 -5
  27. data/lib/vagrant-libvirt/provider.rb +2 -9
  28. data/lib/vagrant-libvirt/templates/domain.xml.erb +35 -10
  29. data/lib/vagrant-libvirt/templates/private_network.xml.erb +1 -1
  30. data/lib/vagrant-libvirt/util/network_util.rb +21 -3
  31. data/lib/vagrant-libvirt/version +1 -1
  32. data/lib/vagrant-libvirt/version.rb +57 -9
  33. data/locales/en.yml +12 -0
  34. data/spec/spec_helper.rb +37 -3
  35. data/spec/support/binding_proc.rb +24 -0
  36. data/spec/support/libvirt_context.rb +2 -0
  37. data/spec/support/matchers/have_file_content.rb +63 -0
  38. data/spec/support/sharedcontext.rb +4 -0
  39. data/spec/unit/action/clean_machine_folder_spec.rb +58 -0
  40. data/spec/unit/action/create_domain_spec.rb +121 -36
  41. data/spec/unit/action/create_domain_spec/additional_disks_domain.xml +54 -0
  42. data/spec/unit/action/create_domain_spec/default_domain.xml +49 -0
  43. data/spec/unit/action/create_domain_spec/{default_storage_pool.xml → default_system_storage_pool.xml} +0 -0
  44. data/spec/unit/action/create_domain_spec/default_user_storage_pool.xml +17 -0
  45. data/spec/unit/action/create_domain_volume_spec.rb +102 -0
  46. data/spec/unit/action/create_domain_volume_spec/one_disk_in_storage.xml +21 -0
  47. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_0.xml +21 -0
  48. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_1.xml +21 -0
  49. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_2.xml +21 -0
  50. data/spec/unit/action/destroy_domain_spec.rb +1 -1
  51. data/spec/unit/action/forward_ports_spec.rb +202 -0
  52. data/spec/unit/action/halt_domain_spec.rb +90 -0
  53. data/spec/unit/action/handle_box_image_spec.rb +363 -0
  54. data/spec/unit/action/start_domain_spec.rb +183 -1
  55. data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +50 -0
  56. data/spec/unit/action/start_domain_spec/default.xml +2 -2
  57. data/spec/unit/action/start_domain_spec/default_added_tpm_path.xml +48 -0
  58. data/spec/unit/action/start_domain_spec/default_added_tpm_version.xml +48 -0
  59. data/spec/unit/action/wait_till_up_spec.rb +22 -21
  60. data/spec/unit/config_spec.rb +395 -127
  61. data/spec/unit/templates/domain_all_settings.xml +14 -3
  62. data/spec/unit/templates/domain_custom_cpu_model.xml +2 -1
  63. data/spec/unit/templates/domain_defaults.xml +2 -1
  64. data/spec/unit/templates/domain_spec.rb +100 -3
  65. data/spec/unit/templates/tpm/version_1.2.xml +54 -0
  66. data/spec/unit/templates/tpm/version_2.0.xml +53 -0
  67. metadata +105 -19
@@ -49,6 +49,7 @@ module VagrantPlugins
49
49
 
50
50
  b2.use StartDomain
51
51
  b2.use WaitTillUp
52
+ b2.use WaitForCommunicator, [:running]
52
53
 
53
54
  b2.use ForwardPorts
54
55
  b2.use SetHostname
@@ -107,6 +108,7 @@ module VagrantPlugins
107
108
  # Machine should gain IP address when comming up,
108
109
  # so wait for dhcp lease and store IP into machines data_dir.
109
110
  b3.use WaitTillUp
111
+ b3.use WaitForCommunicator, [:running]
110
112
 
111
113
  b3.use ForwardPorts
112
114
  b3.use PrepareNFSSettings
@@ -179,6 +181,7 @@ module VagrantPlugins
179
181
  # Try to remove stale volumes anyway
180
182
  b2.use SetNameOfDomain
181
183
  b2.use RemoveStaleVolume if env[:machine].config.vm.box
184
+ b2.use CleanMachineFolder, quiet: true
182
185
  b2.use MessageNotCreated unless env[:result]
183
186
 
184
187
  next
@@ -186,11 +189,12 @@ module VagrantPlugins
186
189
 
187
190
  b2.use Call, DestroyConfirm do |env2, b3|
188
191
  if env2[:result]
192
+ b3.use ProvisionerCleanup, :before
189
193
  b3.use ClearForwardedPorts
190
194
  b3.use PruneNFSExports
191
195
  b3.use DestroyDomain
192
196
  b3.use DestroyNetworks
193
- b3.use ProvisionerCleanup
197
+ b3.use CleanMachineFolder
194
198
  else
195
199
  b3.use MessageWillNotDestroy
196
200
  end
@@ -324,6 +328,7 @@ module VagrantPlugins
324
328
  autoload :CreateDomainVolume, action_root.join('create_domain_volume')
325
329
  autoload :CreateNetworkInterfaces, action_root.join('create_network_interfaces')
326
330
  autoload :CreateNetworks, action_root.join('create_networks')
331
+ autoload :CleanMachineFolder, action_root.join('clean_machine_folder')
327
332
  autoload :DestroyDomain, action_root.join('destroy_domain')
328
333
  autoload :DestroyNetworks, action_root.join('destroy_networks')
329
334
  autoload :ForwardPorts, action_root.join('forward_ports')
@@ -366,6 +371,7 @@ module VagrantPlugins
366
371
  autoload :SyncedFolders, 'vagrant/action/builtin/synced_folders'
367
372
  autoload :SyncedFolderCleanup, 'vagrant/action/builtin/synced_folder_cleanup'
368
373
  autoload :ProvisionerCleanup, 'vagrant/action/builtin/provisioner_cleanup'
374
+ autoload :WaitForCommunicator, 'vagrant/action/builtin/wait_for_communicator'
369
375
  end
370
376
  end
371
377
  end
@@ -0,0 +1,30 @@
1
+ require 'log4r'
2
+
3
+ module VagrantPlugins
4
+ module ProviderLibvirt
5
+ module Action
6
+ class CleanMachineFolder
7
+
8
+ def initialize(app, env, options=nil)
9
+ @logger = Log4r::Logger.new('vagrant_libvirt::action::create_domain')
10
+ @app = app
11
+ @ui = env[:ui]
12
+ @quiet = (options || {}).fetch(:quiet, false)
13
+ end
14
+
15
+ def call(env)
16
+ machine_folder = env[:machine].data_dir
17
+
18
+ @ui.info("Deleting the machine folder") unless @quiet
19
+
20
+ @logger.debug("Recursively removing: #{machine_folder}")
21
+ FileUtils.rm_rf(machine_folder, :secure => true)
22
+ # need to recreate to prevent exception during a cancelled up
23
+ FileUtils.mkdir_p(machine_folder)
24
+
25
+ @app.call(env)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -5,6 +5,7 @@ module VagrantPlugins
5
5
  module Action
6
6
  class CreateDomain
7
7
  include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
8
+ include VagrantPlugins::ProviderLibvirt::Util::StorageUtil
8
9
 
9
10
  def initialize(app, _env)
10
11
  @logger = Log4r::Logger.new('vagrant_libvirt::action::create_domain')
@@ -32,7 +33,8 @@ module VagrantPlugins
32
33
  # Gather some info about domain
33
34
  @name = env[:domain_name]
34
35
  @title = config.title
35
- @description = config.description
36
+ vagrantfile = File.join(env[:root_path], (env[:vagrantfile_name] || "Vagrantfile"))
37
+ @description = !config.description.empty? ? config.description : "Source: #{vagrantfile}"
36
38
  @uuid = config.uuid
37
39
  @cpus = config.cpus.to_i
38
40
  @cpuset = config.cpuset
@@ -41,6 +43,8 @@ module VagrantPlugins
41
43
  @nodeset = config.nodeset
42
44
  @features = config.features
43
45
  @features_hyperv = config.features_hyperv
46
+ @clock_offset = config.clock_offset
47
+ @clock_timers = config.clock_timers
44
48
  @shares = config.shares
45
49
  @cpu_mode = config.cpu_mode
46
50
  @cpu_model = config.cpu_model
@@ -52,11 +56,12 @@ module VagrantPlugins
52
56
  @machine_arch = config.machine_arch
53
57
  @disk_bus = config.disk_bus
54
58
  @disk_device = config.disk_device
59
+ @disk_driver_opts = config.disk_driver_opts
55
60
  @nested = config.nested
56
61
  @memory_size = config.memory.to_i * 1024
57
62
  @memory_backing = config.memory_backing
58
63
  @management_network_mac = config.management_network_mac
59
- @domain_volume_cache = config.volume_cache
64
+ @domain_volume_cache = config.volume_cache || 'default'
60
65
  @kernel = config.kernel
61
66
  @cmd_line = config.cmd_line
62
67
  @emulator_path = config.emulator_path
@@ -80,6 +85,7 @@ module VagrantPlugins
80
85
  @tpm_model = config.tpm_model
81
86
  @tpm_type = config.tpm_type
82
87
  @tpm_path = config.tpm_path
88
+ @tpm_version = config.tpm_version
83
89
 
84
90
  # Boot order
85
91
  @boot_order = config.boot_order
@@ -87,6 +93,7 @@ module VagrantPlugins
87
93
  # Storage
88
94
  @storage_pool_name = config.storage_pool_name
89
95
  @snapshot_pool_name = config.snapshot_pool_name
96
+ @domain_volumes = []
90
97
  @disks = config.disks
91
98
  @cdroms = config.cdroms
92
99
 
@@ -136,23 +143,30 @@ module VagrantPlugins
136
143
  else
137
144
  pool_name = @storage_pool_name
138
145
  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 }
143
- raise Errors::DomainVolumeExists if domain_volume.nil?
144
- @domain_volume_path = domain_volume.path
146
+ @logger.debug "Search for volumes in pool: #{pool_name}"
147
+ env[:box_volumes].each_index do |index|
148
+ suffix_index = index > 0 ? "_#{index}" : ''
149
+ domain_volume = env[:machine].provider.driver.connection.volumes.all(
150
+ name: "#{@name}#{suffix_index}.img"
151
+ ).find { |x| x.pool_name == pool_name }
152
+ raise Errors::DomainVolumeExists if domain_volume.nil?
153
+ @domain_volumes.push({
154
+ :dev => (index+1).vdev.to_s,
155
+ :cache => @domain_volume_cache,
156
+ :bus => @disk_bus,
157
+ :path => domain_volume.path,
158
+ :virtual_size => env[:box_volumes][index][:virtual_size]
159
+ })
160
+ end
145
161
  end
146
162
 
147
163
  # If we have a box, take the path from the domain volume and set our storage_prefix.
148
164
  # If not, we dump the storage pool xml to get its defined path.
149
165
  # the default storage prefix is typically: /var/lib/libvirt/images/
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_prefix = get_disk_storage_prefix(env, @storage_pool_name)
155
- end
166
+ if env[:machine].config.vm.box
167
+ storage_prefix = File.dirname(@domain_volumes[0][:path]) + '/' # steal
168
+ else
169
+ storage_prefix = get_disk_storage_prefix(env, @storage_pool_name)
156
170
  end
157
171
 
158
172
  @disks.each do |disk|
@@ -184,6 +198,8 @@ module VagrantPlugins
184
198
  format_type: disk[:type],
185
199
  path: disk[:absolute_path],
186
200
  capacity: disk[:size],
201
+ owner: storage_uid(env),
202
+ group: storage_gid(env),
187
203
  #:allocation => ?,
188
204
  pool_name: disk_pool_name
189
205
  )
@@ -222,7 +238,15 @@ module VagrantPlugins
222
238
  env[:ui].info(" -- Feature: #{feature}")
223
239
  end
224
240
  @features_hyperv.each do |feature|
225
- env[:ui].info(" -- Feature (HyperV): name=#{feature[:name]}, state=#{feature[:state]}")
241
+ if feature[:name] == 'spinlocks'
242
+ env[:ui].info(" -- Feature (HyperV): name=#{feature[:name]}, state=#{feature[:state]}, retries=#{feature[:retries]}")
243
+ else
244
+ env[:ui].info(" -- Feature (HyperV): name=#{feature[:name]}, state=#{feature[:state]}")
245
+ end
246
+ end
247
+ env[:ui].info(" -- Clock offset: #{@clock_offset}")
248
+ @clock_timers.each do |timer|
249
+ env[:ui].info(" -- Clock timer: #{timer.map { |k,v| "#{k}=#{v}"}.join(', ')}")
226
250
  end
227
251
  env[:ui].info(" -- Memory: #{@memory_size / 1024}M")
228
252
  unless @nodeset.nil?
@@ -241,8 +265,16 @@ module VagrantPlugins
241
265
  env[:ui].info(" -- Base box: #{env[:machine].box.name}")
242
266
  end
243
267
  env[:ui].info(" -- Storage pool: #{@storage_pool_name}")
244
- env[:ui].info(" -- Image: #{@domain_volume_path} (#{env[:box_virtual_size]}G)")
245
- env[:ui].info(" -- Volume Cache: #{@domain_volume_cache}")
268
+ @domain_volumes.each do |volume|
269
+ env[:ui].info(" -- Image(#{volume[:device]}): #{volume[:path]}, #{volume[:virtual_size]}G")
270
+ end
271
+
272
+ if not @disk_driver_opts.empty?
273
+ env[:ui].info(" -- Disk driver opts: #{@disk_driver_opts.reject { |k,v| v.nil? }.map { |k,v| "#{k}='#{v}'"}.join(' ')}")
274
+ else
275
+ env[:ui].info(" -- Disk driver opts: cache='#{@domain_volume_cache}'")
276
+ end
277
+
246
278
  env[:ui].info(" -- Kernel: #{@kernel}")
247
279
  env[:ui].info(" -- Initrd: #{@initrd}")
248
280
  env[:ui].info(" -- Graphics Type: #{@graphics_type}")
@@ -253,7 +285,13 @@ module VagrantPlugins
253
285
  env[:ui].info(" -- Video VRAM: #{@video_vram}")
254
286
  env[:ui].info(" -- Sound Type: #{@sound_type}")
255
287
  env[:ui].info(" -- Keymap: #{@keymap}")
256
- env[:ui].info(" -- TPM Path: #{@tpm_path}")
288
+ env[:ui].info(" -- TPM Backend: #{@tpm_type}")
289
+ if @tpm_type == 'emulator'
290
+ env[:ui].info(" -- TPM Model: #{@tpm_model}")
291
+ env[:ui].info(" -- TPM Version: #{@tpm_version}")
292
+ else
293
+ env[:ui].info(" -- TPM Path: #{@tpm_path}")
294
+ end
257
295
 
258
296
  @boot_order.each do |device|
259
297
  env[:ui].info(" -- Boot device: #{device}")
@@ -18,72 +18,74 @@ module VagrantPlugins
18
18
  def call(env)
19
19
  env[:ui].info(I18n.t('vagrant_libvirt.creating_domain_volume'))
20
20
 
21
- # Get config options.
22
- config = env[:machine].provider_config
21
+ env[:box_volumes].each_index do |index|
22
+ suffix_index = index > 0 ? "_#{index}" : ''
23
+ # Get config options.
24
+ config = env[:machine].provider_config
23
25
 
24
- # This is name of newly created image for vm.
25
- @name = "#{env[:domain_name]}.img"
26
+ # This is name of newly created image for vm.
27
+ @name = "#{env[:domain_name]}#{suffix_index}.img"
26
28
 
27
- # Verify the volume doesn't exist already.
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
29
+ # Verify the volume doesn't exist already.
30
+ domain_volume = env[:machine].provider.driver.connection.volumes.all(
31
+ name: @name
32
+ ).first
33
+ raise Errors::DomainVolumeExists if domain_volume && domain_volume.id
32
34
 
33
- # Get path to backing image - box volume.
34
- box_volume = env[:machine].provider.driver.connection.volumes.all(
35
- name: env[:box_volume_name]
36
- ).first
37
- @backing_file = box_volume.path
35
+ # Get path to backing image - box volume.
36
+ box_volume = env[:machine].provider.driver.connection.volumes.all(
37
+ name: env[:box_volumes][index][:name]
38
+ ).first
39
+ @backing_file = box_volume.path
38
40
 
39
- # Virtual size of image. Take value worked out by HandleBoxImage
40
- @capacity = env[:box_virtual_size] # G
41
+ # Virtual size of image. Take value worked out by HandleBoxImage
42
+ @capacity = env[:box_volumes][index][:virtual_size] # G
41
43
 
42
- # Create new volume from xml template. Fog currently doesn't support
43
- # volume snapshots directly.
44
- begin
45
- xml = Nokogiri::XML::Builder.new do |xml|
46
- xml.volume do
47
- xml.name(@name)
48
- xml.capacity(@capacity, unit: 'G')
49
- xml.target do
50
- xml.format(type: 'qcow2')
51
- xml.permissions do
52
- xml.owner storage_uid(env)
53
- xml.group storage_gid(env)
54
- xml.label 'virt_image_t'
44
+ # Create new volume from xml template. Fog currently doesn't support
45
+ # volume snapshots directly.
46
+ begin
47
+ xml = Nokogiri::XML::Builder.new do |xml|
48
+ xml.volume do
49
+ xml.name(@name)
50
+ xml.capacity(@capacity, unit: 'G')
51
+ xml.target do
52
+ xml.format(type: 'qcow2')
53
+ xml.permissions do
54
+ xml.owner storage_uid(env)
55
+ xml.group storage_gid(env)
56
+ xml.label 'virt_image_t'
57
+ end
55
58
  end
56
- end
57
- xml.backingStore do
58
- xml.path(@backing_file)
59
- xml.format(type: 'qcow2')
60
- xml.permissions do
61
- xml.owner storage_uid(env)
62
- xml.group storage_gid(env)
63
- xml.label 'virt_image_t'
59
+ xml.backingStore do
60
+ xml.path(@backing_file)
61
+ xml.format(type: 'qcow2')
62
+ xml.permissions do
63
+ xml.owner storage_uid(env)
64
+ xml.group storage_gid(env)
65
+ xml.label 'virt_image_t'
66
+ end
64
67
  end
65
68
  end
69
+ end.to_xml(
70
+ save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION |
71
+ Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS |
72
+ Nokogiri::XML::Node::SaveOptions::FORMAT
73
+ )
74
+ if config.snapshot_pool_name != config.storage_pool_name
75
+ pool_name = config.snapshot_pool_name
76
+ else
77
+ pool_name = config.storage_pool_name
66
78
  end
67
- end.to_xml(
68
- save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION |
69
- Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS |
70
- Nokogiri::XML::Node::SaveOptions::FORMAT
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
79
+ @logger.debug "Using pool #{pool_name} for base box snapshot"
80
+ domain_volume = env[:machine].provider.driver.connection.volumes.create(
81
+ xml: xml,
82
+ pool_name: pool_name
83
+ )
84
+ rescue Fog::Errors::Error => e
85
+ raise Errors::FogDomainVolumeCreateError,
86
+ error_message: e.message
76
87
  end
77
- @logger.debug "Using pool #{pool_name} for base box snapshot"
78
- domain_volume = env[:machine].provider.driver.connection.volumes.create(
79
- xml: xml,
80
- pool_name: pool_name
81
- )
82
- rescue Fog::Errors::Error => e
83
- raise Errors::FogDomainVolumeCreateError,
84
- error_message: e.message
85
88
  end
86
-
87
89
  @app.call(env)
88
90
  end
89
91
  end
@@ -214,9 +214,6 @@ module VagrantPlugins
214
214
  network[:type] = :dhcp
215
215
  end
216
216
 
217
- # do not run configure_networks for tcp tunnel interfaces
218
- next if options.fetch(:tunnel_type, nil)
219
-
220
217
  networks_to_configure << network
221
218
  end
222
219
 
@@ -54,6 +54,8 @@ module VagrantPlugins
54
54
  env[:machine].provider.driver.connection.client
55
55
  )
56
56
 
57
+ current_network = @available_networks.detect { |network| network[:name] == @options[:network_name] }
58
+
57
59
  # Prepare a hash describing network for this specific interface.
58
60
  @interface_network = {
59
61
  name: nil,
@@ -64,11 +66,11 @@ module VagrantPlugins
64
66
  domain_name: nil,
65
67
  ipv6_address: options[:ipv6_address] || nil,
66
68
  ipv6_prefix: options[:ipv6_prefix] || nil,
67
- created: false,
68
- active: false,
69
+ created: current_network.nil? ? false : true,
70
+ active: current_network.nil? ? false : current_network[:active],
69
71
  autostart: options[:autostart] || false,
70
72
  guest_ipv6: @options[:guest_ipv6] || 'yes',
71
- libvirt_network: nil
73
+ libvirt_network: current_network.nil? ? nil : current_network[:libvirt_network]
72
74
  }
73
75
 
74
76
  if @options[:ip]
@@ -255,7 +257,9 @@ module VagrantPlugins
255
257
 
256
258
  # Do we need to create new network?
257
259
  unless @interface_network[:created]
258
- @interface_network[:name] = 'vagrant-private-dhcp'
260
+ @interface_network[:name] = @options[:network_name] ?
261
+ @options[:network_name] :
262
+ 'vagrant-private-dhcp'
259
263
  @interface_network[:network_address] = net_address
260
264
 
261
265
  # Set IP address of network (actually bridge). It will be used as
@@ -297,6 +301,9 @@ module VagrantPlugins
297
301
 
298
302
  @network_ipv6_address = @interface_network[:ipv6_address]
299
303
  @network_ipv6_prefix = @interface_network[:ipv6_prefix]
304
+
305
+ @network_bridge_stp = @options[:bridge_stp].nil? || @options[:bridge_stp] ? 'on' : 'off'
306
+ @network_bridge_delay = @options[:bridge_delay] ? @options[:bridge_delay] : 0
300
307
 
301
308
  @network_forward_mode = @options[:forward_mode]
302
309
  if @options[:forward_device]
@@ -70,7 +70,7 @@ module VagrantPlugins
70
70
 
71
71
  # remove root storage
72
72
  root_disk = domain.volumes.select do |x|
73
- x.name == libvirt_domain.name + '.img'
73
+ x.name == libvirt_domain.name + '.img' if x
74
74
  end.first
75
75
  root_disk.destroy if root_disk
76
76
  end
@@ -11,10 +11,8 @@ module VagrantPlugins
11
11
  end
12
12
 
13
13
  def call(env)
14
- @env = env
15
-
16
14
  # Get the ports we're forwarding
17
- env[:forwarded_ports] = compile_forwarded_ports(env[:machine].config)
15
+ env[:forwarded_ports] = compile_forwarded_ports(env, env[:machine].config)
18
16
 
19
17
  # Warn if we're port forwarding to any privileged ports
20
18
  env[:forwarded_ports].each do |fp|
@@ -28,51 +26,52 @@ module VagrantPlugins
28
26
  # Continue, we need the VM to be booted in order to grab its IP
29
27
  @app.call env
30
28
 
31
- if @env[:forwarded_ports].any?
29
+ if env[:forwarded_ports].any?
32
30
  env[:ui].info I18n.t('vagrant.actions.vm.forward_ports.forwarding')
33
- forward_ports
31
+ forward_ports(env)
34
32
  end
35
33
  end
36
34
 
37
- def forward_ports
38
- @env[:forwarded_ports].each do |fp|
35
+ def forward_ports(env)
36
+ env[:forwarded_ports].each do |fp|
39
37
  message_attributes = {
40
38
  adapter: fp[:adapter] || 'eth0',
41
39
  guest_port: fp[:guest],
42
40
  host_port: fp[:host]
43
41
  }
44
42
 
45
- @env[:ui].info(I18n.t(
43
+ env[:ui].info(I18n.t(
46
44
  'vagrant.actions.vm.forward_ports.forwarding_entry',
47
- message_attributes
45
+ **message_attributes
48
46
  ))
49
47
 
50
- if fp[:protocol] == 'udp'
51
- @env[:ui].warn I18n.t('vagrant_libvirt.warnings.forwarding_udp')
52
- next
53
- end
54
-
55
48
  ssh_pid = redirect_port(
56
- @env[:machine],
49
+ env,
50
+ env[:machine],
57
51
  fp[:host_ip] || '*',
58
52
  fp[:host],
59
- fp[:guest_ip] || @env[:machine].provider.ssh_info[:host],
53
+ fp[:guest_ip] || env[:machine].provider.ssh_info[:host],
60
54
  fp[:guest],
61
55
  fp[:gateway_ports] || false
62
56
  )
63
- store_ssh_pid(fp[:host], ssh_pid)
57
+ store_ssh_pid(env[:machine], fp[:host], ssh_pid)
64
58
  end
65
59
  end
66
60
 
67
61
  private
68
62
 
69
- def compile_forwarded_ports(config)
63
+ def compile_forwarded_ports(env, config)
70
64
  mappings = {}
71
65
 
72
66
  config.vm.networks.each do |type, options|
73
67
  next if options[:disabled]
74
68
 
75
- next unless type == :forwarded_port && options[:id] != 'ssh'
69
+ if options[:protocol] == 'udp'
70
+ env[:ui].warn I18n.t('vagrant_libvirt.warnings.forwarding_udp')
71
+ next
72
+ end
73
+
74
+ next if type != :forwarded_port || ( options[:id] == 'ssh' && !env[:machine].provider_config.forward_ssh_port )
76
75
  if options.fetch(:host_ip, '').to_s.strip.empty?
77
76
  options.delete(:host_ip)
78
77
  end
@@ -82,7 +81,7 @@ module VagrantPlugins
82
81
  mappings.values
83
82
  end
84
83
 
85
- def redirect_port(machine, host_ip, host_port, guest_ip, guest_port,
84
+ def redirect_port(env, machine, host_ip, host_port, guest_ip, guest_port,
86
85
  gateway_ports)
87
86
  ssh_info = machine.ssh_info
88
87
  params = %W(
@@ -107,14 +106,14 @@ module VagrantPlugins
107
106
  "IdentityFile='\"#{pk}\"'"
108
107
  end).map { |s| s.prepend('-o ') }.join(' ')
109
108
 
110
- options += " -o ProxyCommand=\"#{ssh_info[:proxy_command]}\"" if machine.provider_config.connect_via_ssh
109
+ options += " -o ProxyCommand=\"#{ssh_info[:proxy_command]}\"" if machine.provider_config.proxy_command
111
110
 
112
111
  # TODO: instead of this, try and lock and get the stdin from spawn...
113
112
  ssh_cmd = ''
114
113
  if host_port <= 1024
115
114
  @@lock.synchronize do
116
115
  # TODO: add i18n
117
- @env[:ui].info 'Requesting sudo for host port(s) <= 1024'
116
+ env[:ui].info 'Requesting sudo for host port(s) <= 1024'
118
117
  r = system('sudo -v')
119
118
  if r
120
119
  ssh_cmd << 'sudo ' # add sudo prefix
@@ -125,14 +124,15 @@ module VagrantPlugins
125
124
  ssh_cmd << "ssh -n #{options} #{params}"
126
125
 
127
126
  @logger.debug "Forwarding port with `#{ssh_cmd}`"
128
- log_file = ssh_forward_log_file(host_ip, host_port,
129
- guest_ip, guest_port)
127
+ log_file = ssh_forward_log_file(
128
+ env[:machine], host_ip, host_port, guest_ip, guest_port,
129
+ )
130
130
  @logger.info "Logging to #{log_file}"
131
131
  spawn(ssh_cmd, [:out, :err] => [log_file, 'w'], :pgroup => true)
132
132
  end
133
133
 
134
- def ssh_forward_log_file(host_ip, host_port, guest_ip, guest_port)
135
- log_dir = @env[:machine].data_dir.join('logs')
134
+ def ssh_forward_log_file(machine, host_ip, host_port, guest_ip, guest_port)
135
+ log_dir = machine.data_dir.join('logs')
136
136
  log_dir.mkdir unless log_dir.directory?
137
137
  File.join(
138
138
  log_dir,
@@ -141,8 +141,8 @@ module VagrantPlugins
141
141
  )
142
142
  end
143
143
 
144
- def store_ssh_pid(host_port, ssh_pid)
145
- data_dir = @env[:machine].data_dir.join('pids')
144
+ def store_ssh_pid(machine, host_port, ssh_pid)
145
+ data_dir = machine.data_dir.join('pids')
146
146
  data_dir.mkdir unless data_dir.directory?
147
147
 
148
148
  data_dir.join("ssh_#{host_port}.pid").open('w') do |pid_file|
@@ -169,13 +169,12 @@ module VagrantPlugins
169
169
  end
170
170
 
171
171
  def call(env)
172
- @env = env
173
-
174
- if ssh_pids.any?
172
+ pids = ssh_pids(env[:machine])
173
+ if pids.any?
175
174
  env[:ui].info I18n.t(
176
175
  'vagrant.actions.vm.clear_forward_ports.deleting'
177
176
  )
178
- ssh_pids.each do |tag|
177
+ pids.each do |tag|
179
178
  next unless ssh_pid?(tag[:pid])
180
179
  @logger.debug "Killing pid #{tag[:pid]}"
181
180
  kill_cmd = ''
@@ -191,7 +190,7 @@ module VagrantPlugins
191
190
  end
192
191
 
193
192
  @logger.info 'Removing ssh pid files'
194
- remove_ssh_pids
193
+ remove_ssh_pids(env[:machine])
195
194
  else
196
195
  @logger.info 'No ssh pids found'
197
196
  end
@@ -201,9 +200,9 @@ module VagrantPlugins
201
200
 
202
201
  protected
203
202
 
204
- def ssh_pids
205
- glob = @env[:machine].data_dir.join('pids').to_s + '/ssh_*.pid'
206
- @ssh_pids = Dir[glob].map do |file|
203
+ def ssh_pids(machine)
204
+ glob = machine.data_dir.join('pids').to_s + '/ssh_*.pid'
205
+ ssh_pids = Dir[glob].map do |file|
207
206
  {
208
207
  pid: File.read(file).strip.chomp,
209
208
  port: File.basename(file)['ssh_'.length..-1 * ('.pid'.length + 1)].to_i
@@ -217,8 +216,8 @@ module VagrantPlugins
217
216
  `ps -o command= #{pid}`.strip.chomp =~ /ssh/
218
217
  end
219
218
 
220
- def remove_ssh_pids
221
- glob = @env[:machine].data_dir.join('pids').to_s + '/ssh_*.pid'
219
+ def remove_ssh_pids(machine)
220
+ glob = machine.data_dir.join('pids').to_s + '/ssh_*.pid'
222
221
  Dir[glob].each do |file|
223
222
  File.delete file
224
223
  end