vagrant-libvirt 0.0.32 → 0.0.33

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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/Gemfile +4 -0
  4. data/README.md +146 -22
  5. data/lib/vagrant-libvirt/action/create_domain.rb +35 -0
  6. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +1 -0
  7. data/lib/vagrant-libvirt/action/create_networks.rb +2 -0
  8. data/lib/vagrant-libvirt/action/forward_ports.rb +2 -2
  9. data/lib/vagrant-libvirt/action/handle_box_image.rb +3 -1
  10. data/lib/vagrant-libvirt/action/prepare_nfs_settings.rb +9 -9
  11. data/lib/vagrant-libvirt/action/set_name_of_domain.rb +6 -4
  12. data/lib/vagrant-libvirt/action/start_domain.rb +136 -30
  13. data/lib/vagrant-libvirt/action/wait_till_up.rb +22 -14
  14. data/lib/vagrant-libvirt/cap/nic_mac_addresses.rb +7 -1
  15. data/lib/vagrant-libvirt/cap/synced_folder.rb +6 -3
  16. data/lib/vagrant-libvirt/config.rb +109 -0
  17. data/lib/vagrant-libvirt/plugin.rb +3 -0
  18. data/lib/vagrant-libvirt/templates/domain.xml.erb +57 -7
  19. data/lib/vagrant-libvirt/templates/interface.xml.erb +5 -1
  20. data/lib/vagrant-libvirt/templates/private_network.xml.erb +1 -1
  21. data/lib/vagrant-libvirt/templates/tunnel_interface.xml.erb +6 -0
  22. data/lib/vagrant-libvirt/util/network_util.rb +2 -0
  23. data/lib/vagrant-libvirt/version.rb +1 -1
  24. data/locales/en.yml +1 -1
  25. data/spec/spec_helper.rb +1 -0
  26. data/spec/support/libvirt_context.rb +28 -0
  27. data/spec/support/sharedcontext.rb +34 -0
  28. data/spec/{vagrant-libvirt → unit}/action/set_name_of_domain_spec.rb +0 -0
  29. data/spec/unit/action/wait_till_up_spec.rb +128 -0
  30. data/tools/create_box.sh +3 -1
  31. data/vagrant-libvirt.gemspec +4 -4
  32. metadata +21 -15
@@ -67,7 +67,9 @@ module VagrantPlugins
67
67
  env[:ui].info(I18n.t('vagrant_libvirt.uploading_volume'))
68
68
 
69
69
  # Create new volume in storage pool
70
- raise Errors::BoxNotFound if !File.exists?(box_image_file)
70
+ unless File.exists?(box_image_file)
71
+ raise Vagrant::Errors::BoxNotFound.new(name: env[:machine].box.name)
72
+ end
71
73
  box_image_size = File.size(box_image_file) # B
72
74
  message = "Creating volume #{env[:box_volume_name]}"
73
75
  message << " in storage pool #{config.storage_pool_name}."
@@ -40,15 +40,15 @@ module VagrantPlugins
40
40
  # @param [Machine] machine
41
41
  # @return [String]
42
42
  def read_host_ip(ip)
43
- UDPSocket.open do |s|
44
- if(ip.kind_of?(Array))
45
- s.connect(ip.last, 1)
46
- else
47
- s.connect(ip, 1)
43
+ UDPSocket.open do |s|
44
+ if(ip.kind_of?(Array))
45
+ s.connect(ip.last, 1)
46
+ else
47
+ s.connect(ip, 1)
48
+ end
49
+ s.addr.last
50
+ end
48
51
  end
49
- s.addr.last
50
- end
51
- end
52
52
  # Returns the IP address of the guest
53
53
  #
54
54
  # @param [Machine] machine
@@ -65,7 +65,7 @@ module VagrantPlugins
65
65
  result << data if type == :stdout
66
66
  end
67
67
 
68
- ips = result.chomp.split("\n")
68
+ ips = result.chomp.split("\n").uniq
69
69
  @logger.info("guest IPs: #{ips.join(', ')}")
70
70
  ips.each do |ip|
71
71
  next if ip == ssh_host
@@ -46,13 +46,15 @@ module VagrantPlugins
46
46
  config = env[:machine].provider_config
47
47
  domain_name =
48
48
  if config.default_prefix.nil?
49
- env[:root_path].basename.to_s.dup
49
+ env[:root_path].basename.to_s.dup.concat("_")
50
+ elsif config.default_prefix.empty?
51
+ # don't have any prefix, not even "_"
52
+ ""
50
53
  else
51
- config.default_prefix.to_s
54
+ config.default_prefix.to_s.concat("_")
52
55
  end
53
- domain_name << '_'
54
56
  domain_name << env[:machine].name.to_s
55
- domain_name.gsub!(/[^-a-z0-9_]/i, '')
57
+ domain_name.gsub!(/[^-a-z0-9_\.]/i, '')
56
58
  domain_name << "_#{Time.now.utc.to_i}_#{SecureRandom.hex(10)}" if config.random_hostname
57
59
  domain_name
58
60
  end
@@ -23,8 +23,8 @@ module VagrantPlugins
23
23
 
24
24
  libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(env[:machine].id)
25
25
 
26
- if config.memory*1024 != libvirt_domain.max_memory
27
- libvirt_domain.max_memory = config.memory*1024
26
+ if config.memory.to_i*1024 != libvirt_domain.max_memory
27
+ libvirt_domain.max_memory = config.memory.to_i*1024
28
28
  libvirt_domain.memory = libvirt_domain.max_memory
29
29
  end
30
30
  begin
@@ -88,7 +88,16 @@ module VagrantPlugins
88
88
  descr_changed = true
89
89
  cpu_model = REXML::Element.new('model', REXML::XPath.first(xml_descr,'/domain/cpu'))
90
90
  cpu_model.attributes['fallback'] = 'allow'
91
- cpu_model.text = 'qemu64'
91
+ cpu_model.text = config.cpu_model
92
+ else
93
+ if cpu_model.text != config.cpu_model
94
+ descr_changed = true
95
+ cpu_model.text = config.cpu_model
96
+ end
97
+ if cpu_model.attributes['fallback'] != config.cpu_fallback
98
+ descr_changed = true
99
+ cpu_model.attributes['fallback'] = config.cpu_fallback
100
+ end
92
101
  end
93
102
  vmx_feature = REXML::XPath.first(xml_descr,'/domain/cpu/feature[@name="vmx"]')
94
103
  svm_feature = REXML::XPath.first(xml_descr,'/domain/cpu/feature[@name="svm"]')
@@ -126,42 +135,137 @@ module VagrantPlugins
126
135
 
127
136
  # Graphics
128
137
  graphics = REXML::XPath.first(xml_descr,'/domain/devices/graphics')
129
- if graphics.attributes['type'] != config.graphics_type
130
- descr_changed = true
131
- graphics.attributes['type'] = config.graphics_type
132
- end
133
- if graphics.attributes['listen'] != config.graphics_ip
134
- descr_changed = true
135
- graphics.attributes['listen'] = config.graphics_ip
136
- graphics.delete_element('//listen')
138
+ if config.graphics_type != 'none'
139
+ if graphics.nil?
140
+ descr_changed = true
141
+ graphics = REXML::Element.new('graphics', REXML::XPath.first(xml_descr,'/domain/devices'))
142
+ end
143
+ if graphics.attributes['type'] != config.graphics_type
144
+ descr_changed = true
145
+ graphics.attributes['type'] = config.graphics_type
146
+ end
147
+ if graphics.attributes['listen'] != config.graphics_ip
148
+ descr_changed = true
149
+ graphics.attributes['listen'] = config.graphics_ip
150
+ graphics.delete_element('//listen')
151
+ end
152
+ if graphics.attributes['autoport'] != config.graphics_autoport
153
+ descr_changed = true
154
+ graphics.attributes['autoport'] = config.graphics_autoport
155
+ if config.graphics_autoport == 'no'
156
+ graphics.attributes['port'] = config.graphics_port
157
+ end
158
+ end
159
+ if graphics.attributes['keymap'] != config.keymap
160
+ descr_changed = true
161
+ graphics.attributes['keymap'] = config.keymap
162
+ end
163
+ if graphics.attributes['passwd'] != config.graphics_passwd
164
+ descr_changed = true
165
+ if config.graphics_passwd.nil?
166
+ graphics.attributes.delete 'passwd'
167
+ else
168
+ graphics.attributes['passwd'] = config.graphics_passwd
169
+ end
170
+ end
171
+ else
172
+ # graphics_type = none, remove entire element
173
+ if !graphics.nil?
174
+ graphics.parent.delete_element(graphics)
175
+ end
137
176
  end
138
- if graphics.attributes['autoport'] != config.graphics_autoport
139
- descr_changed = true
140
- graphics.attributes['autoport'] = config.graphics_autoport
141
- if config.graphics_autoport == 'no'
142
- graphics.attributes['port'] = config.graphics_port
177
+
178
+ #TPM
179
+ if config.tpm_path
180
+ raise Errors::FogCreateServerError, "The TPM Path must be fully qualified" unless config.tpm_path[0].chr == '/'
181
+
182
+ tpm = REXML::XPath.first(xml_descr,'/domain/devices/tpm')
183
+ if tpm.nil?
184
+ descr_changed = true
185
+ tpm = REXML::Element.new('tpm', REXML::XPath.first(xml_descr,'/domain/devices/tpm/model'))
186
+ tpm.attributes['model'] = config.tpm_model
187
+ tpm_backend_type = tpm.add_element('backend')
188
+ tpm_backend_type.attributes['type'] = config.tpm_type
189
+ tpm_device_path = tpm_backend_type.add_element('device')
190
+ tpm_device_path.attributes['path'] = config.tpm_path
191
+ else
192
+ if tpm.attributes['model'] != config.tpm_model
193
+ descr_changed = true
194
+ tpm.attributes['model'] = config.tpm_model
195
+ end
196
+ if tpm.elements['backend'].attributes['type'] != config.tpm_type
197
+ descr_changed = true
198
+ tpm.elements['backend'].attributes['type'] = config.tpm_type
199
+ end
200
+ if tpm.elements['backend'].elements['device'].attributes['path'] != config.tpm_path
201
+ descr_changed = true
202
+ tpm.elements['backend'].elements['device'].attributes['path'] = config.tpm_path
203
+ end
143
204
  end
144
205
  end
145
- if graphics.attributes['keymap'] != config.keymap
206
+
207
+ # Video device
208
+ video = REXML::XPath.first(xml_descr,'/domain/devices/video')
209
+ if !video.nil? and config.graphics_type == 'none'
210
+ # graphics_type = none, video devices are removed since there is no possible output
146
211
  descr_changed = true
147
- graphics.attributes['keymap'] = config.keymap
212
+ video.parent.delete_element(video)
213
+ else
214
+ video_model = REXML::XPath.first(xml_descr,'/domain/devices/video/model')
215
+ if video_model.nil?
216
+ video_model = REXML::Element.new('model', REXML::XPath.first(xml_descr,'/domain/devices/video'))
217
+ video_model.attributes['type'] = config.video_type
218
+ video_model.attributes['vram'] = config.video_vram
219
+ else
220
+ if video_model.attributes['type'] != config.video_type || video_model.attributes['vram'] != config.video_vram
221
+ descr_changed = true
222
+ video_model.attributes['type'] = config.video_type
223
+ video_model.attributes['vram'] = config.video_vram
224
+ end
225
+ end
148
226
  end
149
- if graphics.attributes['passwd'] != config.graphics_passwd
150
- descr_changed = true
151
- if config.graphics_passwd.nil?
152
- graphics.attributes.delete 'passwd'
227
+
228
+ # dtb
229
+ if config.dtb
230
+ dtb = REXML::XPath.first(xml_descr,'/domain/os/dtb')
231
+ if dtb.nil?
232
+ descr_changed = true
233
+ dtb = REXML::Element.new('dtb', REXML::XPath.first(xml_descr,'/domain/os'))
234
+ dtb.text = config.dtb
153
235
  else
154
- graphics.attributes['passwd'] = config.graphics_passwd
236
+ if dtb.text != config.dtb
237
+ descr_changed = true
238
+ dtb.text = config.dtb
239
+ end
155
240
  end
156
241
  end
157
242
 
158
- # Video device
159
- video = REXML::XPath.first(xml_descr,'/domain/devices/video/model')
160
- if video.attributes['type'] != config.video_type || video.attributes['vram'] != config.video_vram
161
- descr_changed = true
162
- video.attributes.each_attribute {|attr| video.attributes.delete attr}
163
- video.attributes['type'] = config.video_type
164
- video.attributes['vram'] = config.video_vram
243
+ # kernel and initrd
244
+ if config.kernel
245
+ kernel= REXML::XPath.first(xml_descr,'/domain/os/kernel')
246
+ if kernel.nil?
247
+ descr_changed = true
248
+ kernel = REXML::Element.new('kernel', REXML::XPath.first(xml_descr,'/domain/os'))
249
+ kernel.text = config.kernel
250
+ else
251
+ if kernel.text != config.kernel
252
+ descr_changed = true
253
+ kernel.text = config.kernel
254
+ end
255
+ end
256
+ end
257
+ if config.initrd
258
+ initrd = REXML::XPath.first(xml_descr,'/domain/os/initrd')
259
+ if initrd.nil?
260
+ descr_changed = true
261
+ initrd = REXML::Element.new('initrd', REXML::XPath.first(xml_descr,'/domain/os'))
262
+ initrd.text = config.initrd
263
+ else
264
+ if initrd.text != config.initrd
265
+ descr_changed = true
266
+ initrd.text = config.initrd
267
+ end
268
+ end
165
269
  end
166
270
 
167
271
  # Apply
@@ -179,6 +283,8 @@ module VagrantPlugins
179
283
  rescue => e
180
284
  env[:ui].error("Error when updating domain settings: #{e.message}")
181
285
  end
286
+ # Autostart with host if enabled in Vagrantfile
287
+ libvirt_domain.autostart = config.autostart
182
288
  # Actually start the domain
183
289
  domain.start
184
290
  rescue => e
@@ -1,4 +1,5 @@
1
1
  require 'log4r'
2
+ require 'vagrant-libvirt/errors'
2
3
  require 'vagrant-libvirt/util/timer'
3
4
  require 'vagrant/util/retryable'
4
5
 
@@ -21,18 +22,22 @@ module VagrantPlugins
21
22
  env[:metrics] ||= {}
22
23
 
23
24
  # Get domain object
24
- domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
25
- raise NoDomainError if domain == nil
25
+ domain = env[:machine].provider.driver.get_domain(env[:machine].id.to_s)
26
+ if domain == nil
27
+ raise Errors::NoDomainError,
28
+ :error_message => "Domain #{env[:machine].id} not found"
29
+ end
26
30
 
27
31
  # Wait for domain to obtain an ip address. Ip address is searched
28
32
  # from arp table, either localy or remotely via ssh, if libvirt
29
33
  # connection was done via ssh.
30
34
  env[:ip_address] = nil
31
35
  env[:metrics]["instance_ip_time"] = Util::Timer.time do
36
+ @logger.debug("Searching for IP for MAC address: #{domain.mac}")
32
37
  env[:ui].info(I18n.t("vagrant_libvirt.waiting_for_ip"))
33
38
  retryable(:on => Fog::Errors::TimeoutError, :tries => 300) do
34
39
  # If we're interrupted don't worry about waiting
35
- next if env[:interrupted]
40
+ return terminate(env) if env[:interrupted]
36
41
 
37
42
  # Wait for domain to obtain an ip address
38
43
  domain.wait_for(2) {
@@ -43,7 +48,6 @@ module VagrantPlugins
43
48
  }
44
49
  end
45
50
  end
46
- terminate(env) if env[:interrupted]
47
51
  @logger.info("Got IP address #{env[:ip_address]}")
48
52
  @logger.info("Time for getting IP: #{env[:metrics]["instance_ip_time"]}")
49
53
 
@@ -64,7 +68,8 @@ module VagrantPlugins
64
68
  end
65
69
  end
66
70
  end
67
- terminate(env) if env[:interrupted]
71
+ # if interrupted above, just terminate immediately
72
+ return terminate(env) if env[:interrupted]
68
73
  @logger.info("Time for SSH ready: #{env[:metrics]["instance_ssh_time"]}")
69
74
 
70
75
  # Booted and ready for use.
@@ -76,18 +81,21 @@ module VagrantPlugins
76
81
  def recover(env)
77
82
  return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
78
83
 
79
- if env[:machine].provider.state.id != :not_created
80
- # Undo the import
81
- terminate(env)
82
- end
84
+ # Undo the import
85
+ terminate(env)
83
86
  end
84
87
 
85
88
  def terminate(env)
86
- destroy_env = env.dup
87
- destroy_env.delete(:interrupted)
88
- destroy_env[:config_validate] = false
89
- destroy_env[:force_confirm_destroy] = true
90
- env[:action_runner].run(Action.action_destroy, destroy_env)
89
+ if env[:machine].provider.state.id != :not_created
90
+ # If we're not supposed to destroy on error then just return
91
+ return if !env[:destroy_on_error]
92
+
93
+ destroy_env = env.dup
94
+ destroy_env.delete(:interrupted)
95
+ destroy_env[:config_validate] = false
96
+ destroy_env[:force_confirm_destroy] = true
97
+ env[:action_runner].run(Action.action_destroy, destroy_env)
98
+ end
91
99
  end
92
100
  end
93
101
  end
@@ -3,7 +3,13 @@ module VagrantPlugins
3
3
  module Cap
4
4
  class NicMacAddresses
5
5
  def self.nic_mac_addresses(machine)
6
- machine.provider.mac_addresses
6
+ # Vagrant expects a Hash with an index starting at 1 as key
7
+ # and the mac as uppercase string without colons as value
8
+ nic_macs = {}
9
+ machine.provider.mac_addresses.each do |index, mac|
10
+ nic_macs[index+1] = mac.upcase.gsub(':','')
11
+ end
12
+ nic_macs
7
13
  end
8
14
  end
9
15
  end
@@ -38,6 +38,7 @@ module VagrantPlugins
38
38
  folders.each do |id, folder_opts|
39
39
  folder_opts.merge!({ target: id,
40
40
  accessmode: 'passthrough',
41
+ mount: true,
41
42
  readonly: nil }) { |_k, ov, _nv| ov }
42
43
 
43
44
  mount_tag = Digest::MD5.new.update(folder_opts[:hostpath]).to_s[0,31]
@@ -63,9 +64,11 @@ module VagrantPlugins
63
64
  # Only mount folders that have a guest path specified.
64
65
  mount_folders = {}
65
66
  folders.each do |id, opts|
66
- mount_folders[id] = opts.dup if opts[:guestpath]
67
- # merge common options if not given
68
- mount_folders[id].merge!(version: '9p2000.L') { |_k, ov, _nv| ov }
67
+ if opts[:mount] && opts[:guestpath] && ! opts[:guestpath].empty?
68
+ mount_folders[id] = opts.dup
69
+ # merge common options if not given
70
+ mount_folders[id].merge!(version: '9p2000.L') { |_k, ov, _nv| ov }
71
+ end
69
72
  end
70
73
  # Mount the actual folder
71
74
  machine.guest.capability(
@@ -48,6 +48,7 @@ module VagrantPlugins
48
48
  attr_accessor :management_network_address
49
49
  attr_accessor :management_network_mode
50
50
  attr_accessor :management_network_mac
51
+ attr_accessor :management_network_guest_ipv6
51
52
 
52
53
  # Default host prefix (alternative to use project folder name)
53
54
  attr_accessor :default_prefix
@@ -57,6 +58,9 @@ module VagrantPlugins
57
58
  attr_accessor :memory
58
59
  attr_accessor :cpus
59
60
  attr_accessor :cpu_mode
61
+ attr_accessor :cpu_model
62
+ attr_accessor :cpu_fallback
63
+ attr_accessor :cpu_features
60
64
  attr_accessor :loader
61
65
  attr_accessor :boot_order
62
66
  attr_accessor :machine_type
@@ -69,6 +73,8 @@ module VagrantPlugins
69
73
  attr_accessor :kernel
70
74
  attr_accessor :cmd_line
71
75
  attr_accessor :initrd
76
+ attr_accessor :dtb
77
+ attr_accessor :emulator_path
72
78
  attr_accessor :graphics_type
73
79
  attr_accessor :graphics_autoport
74
80
  attr_accessor :graphics_port
@@ -77,6 +83,13 @@ module VagrantPlugins
77
83
  attr_accessor :video_type
78
84
  attr_accessor :video_vram
79
85
  attr_accessor :keymap
86
+ attr_accessor :kvm_hidden
87
+
88
+ # Sets the information for connecting to a host TPM device
89
+ # Only supports socket-based TPMs
90
+ attr_accessor :tpm_model
91
+ attr_accessor :tpm_type
92
+ attr_accessor :tpm_path
80
93
 
81
94
  # Sets the max number of NICs that can be created
82
95
  # Default set to 8. Don't change the default unless you know
@@ -90,9 +103,18 @@ module VagrantPlugins
90
103
  # Inputs
91
104
  attr_accessor :inputs
92
105
 
106
+ # PCI device passthrough
107
+ attr_accessor :pcis
108
+
109
+ # USB device passthrough
110
+ attr_accessor :usbs
111
+
93
112
  # Suspend mode
94
113
  attr_accessor :suspend_mode
95
114
 
115
+ # Autostart
116
+ attr_accessor :autostart
117
+
96
118
  def initialize
97
119
  @uri = UNSET_VALUE
98
120
  @driver = UNSET_VALUE
@@ -107,12 +129,16 @@ module VagrantPlugins
107
129
  @management_network_address = UNSET_VALUE
108
130
  @management_network_mode = UNSET_VALUE
109
131
  @management_network_mac = UNSET_VALUE
132
+ @management_network_guest_ipv6 = UNSET_VALUE
110
133
 
111
134
  # Domain specific settings.
112
135
  @uuid = UNSET_VALUE
113
136
  @memory = UNSET_VALUE
114
137
  @cpus = UNSET_VALUE
115
138
  @cpu_mode = UNSET_VALUE
139
+ @cpu_model = UNSET_VALUE
140
+ @cpu_fallback = UNSET_VALUE
141
+ @cpu_features = UNSET_VALUE
116
142
  @loader = UNSET_VALUE
117
143
  @machine_type = UNSET_VALUE
118
144
  @machine_arch = UNSET_VALUE
@@ -123,7 +149,9 @@ module VagrantPlugins
123
149
  @volume_cache = UNSET_VALUE
124
150
  @kernel = UNSET_VALUE
125
151
  @initrd = UNSET_VALUE
152
+ @dtb = UNSET_VALUE
126
153
  @cmd_line = UNSET_VALUE
154
+ @emulator_path = UNSET_VALUE
127
155
  @graphics_type = UNSET_VALUE
128
156
  @graphics_autoport = UNSET_VALUE
129
157
  @graphics_port = UNSET_VALUE
@@ -132,6 +160,11 @@ module VagrantPlugins
132
160
  @video_type = UNSET_VALUE
133
161
  @video_vram = UNSET_VALUE
134
162
  @keymap = UNSET_VALUE
163
+ @kvm_hidden = UNSET_VALUE
164
+
165
+ @tpm_model = UNSET_VALUE
166
+ @tpm_type = UNSET_VALUE
167
+ @tpm_path = UNSET_VALUE
135
168
 
136
169
  @nic_adapter_count = UNSET_VALUE
137
170
 
@@ -144,8 +177,17 @@ module VagrantPlugins
144
177
  # Inputs
145
178
  @inputs = UNSET_VALUE
146
179
 
180
+ # PCI device passthrough
181
+ @pcis = UNSET_VALUE
182
+
183
+ # USB device passthrough
184
+ @usbs = UNSET_VALUE
185
+
147
186
  # Suspend mode
148
187
  @suspend_mode = UNSET_VALUE
188
+
189
+ # Autostart
190
+ @autostart = UNSET_VALUE
149
191
  end
150
192
 
151
193
  def boot(device)
@@ -183,6 +225,21 @@ module VagrantPlugins
183
225
  raise 'Only four cdroms may be attached at a time'
184
226
  end
185
227
 
228
+ def cpu_feature(options={})
229
+ if options[:name].nil? || options[:policy].nil?
230
+ raise 'CPU Feature name AND policy must be specified'
231
+ end
232
+
233
+ if @cpu_features == UNSET_VALUE
234
+ @cpu_features = []
235
+ end
236
+
237
+ @cpu_features.push({
238
+ name: options[:name],
239
+ policy: options[:policy]
240
+ })
241
+ end
242
+
186
243
  def input(options={})
187
244
  if options[:type].nil? || options[:bus].nil?
188
245
  raise 'Input type AND bus must be specified'
@@ -198,6 +255,40 @@ module VagrantPlugins
198
255
  })
199
256
  end
200
257
 
258
+ def pci(options={})
259
+ if options[:bus].nil? || options[:slot].nil? || options[:function].nil?
260
+ raise 'Bus AND slot AND function must be specified. Check `lspci` for that numbers.'
261
+ end
262
+
263
+ if @pcis == UNSET_VALUE
264
+ @pcis = []
265
+ end
266
+
267
+ @pcis.push({
268
+ bus: options[:bus],
269
+ slot: options[:slot],
270
+ function: options[:function]
271
+ })
272
+ end
273
+
274
+ def usb(options={})
275
+ if (options[:bus].nil? || options[:device].nil?) && options[:vendor].nil? && options[:product].nil?
276
+ raise 'Bus and device and/or vendor and/or product must be specified. Check `lsusb` for these.'
277
+ end
278
+
279
+ if @usbs == UNSET_VALUE
280
+ @usbs = []
281
+ end
282
+
283
+ @usbs.push({
284
+ bus: options[:bus],
285
+ device: options[:device],
286
+ vendor: options[:vendor],
287
+ product: options[:product],
288
+ startupPolicy: options[:startupPolicy],
289
+ })
290
+ end
291
+
201
292
  # NOTE: this will run twice for each time it's needed- keep it idempotent
202
293
  def storage(storage_type, options={})
203
294
  if storage_type == :file
@@ -320,6 +411,7 @@ module VagrantPlugins
320
411
  @management_network_address = '192.168.121.0/24' if @management_network_address == UNSET_VALUE
321
412
  @management_network_mode = 'nat' if @management_network_mode == UNSET_VALUE
322
413
  @management_network_mac = nil if @management_network_mac == UNSET_VALUE
414
+ @management_network_guest_ipv6 = 'yes' if @management_network_guest_ipv6 == UNSET_VALUE
323
415
 
324
416
  # generate a URI if none is supplied
325
417
  @uri = _generate_uri() if @uri == UNSET_VALUE
@@ -329,6 +421,9 @@ module VagrantPlugins
329
421
  @memory = 512 if @memory == UNSET_VALUE
330
422
  @cpus = 1 if @cpus == UNSET_VALUE
331
423
  @cpu_mode = 'host-model' if @cpu_mode == UNSET_VALUE
424
+ @cpu_model = 'qemu64' if @cpu_model == UNSET_VALUE
425
+ @cpu_fallback = 'allow' if @cpu_fallback == UNSET_VALUE
426
+ @cpu_features = [] if @cpu_features == UNSET_VALUE
332
427
  @loader = nil if @loader == UNSET_VALUE
333
428
  @machine_type = nil if @machine_type == UNSET_VALUE
334
429
  @machine_arch = nil if @machine_arch == UNSET_VALUE
@@ -340,6 +435,7 @@ module VagrantPlugins
340
435
  @kernel = nil if @kernel == UNSET_VALUE
341
436
  @cmd_line = '' if @cmd_line == UNSET_VALUE
342
437
  @initrd = '' if @initrd == UNSET_VALUE
438
+ @dtb = nil if @dtb == UNSET_VALUE
343
439
  @graphics_type = 'vnc' if @graphics_type == UNSET_VALUE
344
440
  @graphics_autoport = 'yes' if @graphics_port == UNSET_VALUE
345
441
  @graphics_autoport = 'no' if @graphics_port != UNSET_VALUE
@@ -352,7 +448,12 @@ module VagrantPlugins
352
448
  @video_type = 'cirrus' if @video_type == UNSET_VALUE
353
449
  @video_vram = 9216 if @video_vram == UNSET_VALUE
354
450
  @keymap = 'en-us' if @keymap == UNSET_VALUE
451
+ @kvm_hidden = false if @kvm_hidden == UNSET_VALUE
452
+ @tpm_model = 'tpm-tis' if @tpm_model == UNSET_VALUE
453
+ @tpm_type = 'passthrough' if @tpm_type == UNSET_VALUE
454
+ @tpm_path = nil if @tpm_path == UNSET_VALUE
355
455
  @nic_adapter_count = 8 if @nic_adapter_count == UNSET_VALUE
456
+ @emulator_path = nil if @emulator_path == UNSET_VALUE
356
457
 
357
458
  # Boot order
358
459
  @boot_order = [] if @boot_order == UNSET_VALUE
@@ -364,9 +465,17 @@ module VagrantPlugins
364
465
  # Inputs
365
466
  @inputs = [{:type => "mouse", :bus => "ps2"}] if @inputs == UNSET_VALUE
366
467
 
468
+ # PCI device passthrough
469
+ @pcis = [] if @pcis == UNSET_VALUE
470
+
471
+ # USB device passthrough
472
+ @usbs = [] if @usbs == UNSET_VALUE
473
+
367
474
  # Suspend mode
368
475
  @suspend_mode = "pause" if @suspend_mode == UNSET_VALUE
369
476
 
477
+ # Autostart
478
+ @autostart = false if @autostart == UNSET_VALUE
370
479
  end
371
480
 
372
481
  def validate(machine)