vagrant-libvirt 0.0.45 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +253 -109
  3. data/lib/vagrant-libvirt/action.rb +2 -2
  4. data/lib/vagrant-libvirt/action/create_domain.rb +59 -29
  5. data/lib/vagrant-libvirt/action/create_domain_volume.rb +14 -8
  6. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +7 -5
  7. data/lib/vagrant-libvirt/action/create_networks.rb +2 -2
  8. data/lib/vagrant-libvirt/action/destroy_domain.rb +1 -1
  9. data/lib/vagrant-libvirt/action/forward_ports.rb +6 -5
  10. data/lib/vagrant-libvirt/action/halt_domain.rb +1 -1
  11. data/lib/vagrant-libvirt/action/handle_box_image.rb +22 -57
  12. data/lib/vagrant-libvirt/action/handle_storage_pool.rb +4 -4
  13. data/lib/vagrant-libvirt/action/package_domain.rb +58 -12
  14. data/lib/vagrant-libvirt/action/prepare_nfs_settings.rb +3 -9
  15. data/lib/vagrant-libvirt/action/prune_nfs_exports.rb +18 -9
  16. data/lib/vagrant-libvirt/action/remove_libvirt_image.rb +2 -2
  17. data/lib/vagrant-libvirt/action/remove_stale_volume.rb +17 -11
  18. data/lib/vagrant-libvirt/action/set_boot_order.rb +2 -2
  19. data/lib/vagrant-libvirt/action/set_name_of_domain.rb +6 -9
  20. data/lib/vagrant-libvirt/action/start_domain.rb +2 -2
  21. data/lib/vagrant-libvirt/action/wait_till_up.rb +7 -9
  22. data/lib/vagrant-libvirt/cap/synced_folder.rb +3 -3
  23. data/lib/vagrant-libvirt/config.rb +62 -11
  24. data/lib/vagrant-libvirt/driver.rb +3 -3
  25. data/lib/vagrant-libvirt/errors.rb +5 -5
  26. data/lib/vagrant-libvirt/plugin.rb +2 -2
  27. data/lib/vagrant-libvirt/templates/domain.xml.erb +18 -5
  28. data/lib/vagrant-libvirt/util/network_util.rb +6 -1
  29. data/lib/vagrant-libvirt/util/nfs.rb +17 -0
  30. data/lib/vagrant-libvirt/version.rb +1 -1
  31. data/locales/en.yml +6 -6
  32. data/spec/unit/action/set_name_of_domain_spec.rb +1 -1
  33. data/spec/unit/templates/domain_all_settings.xml +12 -2
  34. data/spec/unit/templates/domain_spec.rb +10 -2
  35. metadata +21 -34
  36. data/.coveralls.yml +0 -1
  37. data/.github/issue_template.md +0 -37
  38. data/.gitignore +0 -21
  39. data/.travis.yml +0 -24
  40. data/Gemfile +0 -26
  41. data/Rakefile +0 -8
  42. data/example_box/README.md +0 -29
  43. data/example_box/Vagrantfile +0 -60
  44. data/example_box/metadata.json +0 -5
  45. data/lib/vagrant-libvirt/templates/default_storage_volume.xml.erb +0 -14
  46. data/tools/create_box.sh +0 -130
  47. data/tools/prepare_redhat_for_box.sh +0 -119
  48. data/vagrant-libvirt.gemspec +0 -51
@@ -1,9 +1,10 @@
1
+ require 'fileutils'
1
2
  require 'log4r'
2
3
 
3
4
  module VagrantPlugins
4
5
  module ProviderLibvirt
5
6
  module Action
6
- # Action for create new box for libvirt provider
7
+ # Action for create new box for Libvirt provider
7
8
  class PackageDomain
8
9
  def initialize(app, env)
9
10
  @logger = Log4r::Logger.new('vagrant_libvirt::action::package_domain')
@@ -21,24 +22,31 @@ module VagrantPlugins
21
22
  root_disk = domain.volumes.select do |x|
22
23
  x.name == libvirt_domain.name + '.img'
23
24
  end.first
25
+ raise Errors::NoDomainVolume if root_disk.nil?
24
26
  boxname = env['package.output']
25
27
  raise "#{boxname}: Already exists" if File.exist?(boxname)
26
28
  @tmp_dir = Dir.pwd + '/_tmp_package'
27
29
  @tmp_img = @tmp_dir + '/box.img'
28
- Dir.mkdir(@tmp_dir)
29
- if File.readable?(root_disk.path)
30
- backing = `qemu-img info "#{root_disk.path}" | grep 'backing file:' | cut -d ':' -f2`.chomp
31
- else
32
- env[:ui].error("Require set read access to #{root_disk.path}. sudo chmod a+r #{root_disk.path}")
33
- FileUtils.rm_rf(@tmp_dir)
34
- raise 'Have no access'
30
+ FileUtils.mkdir_p(@tmp_dir)
31
+ env[:ui].info("Downloading #{root_disk.name} to #{@tmp_img}")
32
+ ret = download_image(@tmp_img, env[:machine].provider_config.storage_pool_name,
33
+ root_disk.name, env) do |progress,image_size|
34
+ env[:ui].clear_line
35
+ env[:ui].report_progress(progress, image_size, false)
36
+ end
37
+ # Clear the line one last time since the progress meter doesn't
38
+ # disappear immediately.
39
+ env[:ui].clear_line
40
+ backing = `qemu-img info "#{@tmp_img}" | grep 'backing file:' | cut -d ':' -f2`.chomp
41
+ if backing
42
+ env[:ui].info('Image has backing image, copying image and rebasing ...')
43
+ `qemu-img rebase -p -b "" #{@tmp_img}`
35
44
  end
36
- env[:ui].info('Image has backing image, copying image and rebasing ...')
37
- FileUtils.cp(root_disk.path, @tmp_img)
38
- `qemu-img rebase -p -b "" #{@tmp_img}`
39
45
  # remove hw association with interface
40
46
  # working for centos with lvs default disks
41
- `virt-sysprep --no-logfile --operations defaults,-ssh-userdir -a #{@tmp_img}`
47
+ options = ENV.fetch('VAGRANT_LIBVIRT_VIRT_SYSPREP_OPTIONS', '')
48
+ operations = ENV.fetch('VAGRANT_LIBVIRT_VIRT_SYSPREP_OPERATIONS', 'defaults,-ssh-userdir')
49
+ `virt-sysprep --no-logfile --operations #{operations} -a #{@tmp_img} #{options}`
42
50
  # add any user provided file
43
51
  extra = ''
44
52
  @tmp_include = @tmp_dir + '/_include'
@@ -99,6 +107,44 @@ module VagrantPlugins
99
107
  }
100
108
  EOF
101
109
  end
110
+
111
+ protected
112
+
113
+ # Fog libvirt currently doesn't support downloading images from storage
114
+ # pool volumes. Use ruby-libvirt client instead.
115
+ def download_image(image_file, pool_name, volume_name, env)
116
+ begin
117
+ pool = env[:machine].provider.driver.connection.client.lookup_storage_pool_by_name(
118
+ pool_name
119
+ )
120
+ volume = pool.lookup_volume_by_name(volume_name)
121
+ image_size = volume.info.allocation # B
122
+
123
+ stream = env[:machine].provider.driver.connection.client.stream
124
+
125
+ # Use length of 0 to download remaining contents after offset
126
+ volume.download(stream, offset = 0, length = 0)
127
+
128
+ buf_size = 1024 * 250 # 250K, copied from upload_image in handle_box_image.rb
129
+ progress = 0
130
+ retval = stream.recv(buf_size)
131
+ open(image_file, 'wb') do |io|
132
+ while (retval.at(0) > 0)
133
+ recvd = io.write(retval.at(1))
134
+ progress += recvd
135
+ yield [progress, image_size]
136
+ retval = stream.recv(buf_size)
137
+ end
138
+ end
139
+ rescue => e
140
+ raise Errors::ImageDownloadError,
141
+ volume_name: volume_name,
142
+ pool_name: pool_name,
143
+ error_message: e.message
144
+ end
145
+
146
+ progress == image_size
147
+ end
102
148
  end
103
149
  end
104
150
  end
@@ -1,12 +1,13 @@
1
1
  require 'nokogiri'
2
2
  require 'socket'
3
3
  require 'timeout'
4
+ require 'vagrant-libvirt/util/nfs'
4
5
 
5
6
  module VagrantPlugins
6
7
  module ProviderLibvirt
7
8
  module Action
8
9
  class PrepareNFSSettings
9
- include Vagrant::Action::Builtin::MixinSyncedFolders
10
+ include VagrantPlugins::ProviderLibvirt::Util::Nfs
10
11
 
11
12
  def initialize(app, _env)
12
13
  @app = app
@@ -28,13 +29,6 @@ module VagrantPlugins
28
29
  end
29
30
  end
30
31
 
31
- # We're using NFS if we have any synced folder with NFS configured. If
32
- # we are not using NFS we don't need to do the extra work to
33
- # populate these fields in the environment.
34
- def using_nfs?
35
- !!synced_folders(@machine)[:nfs]
36
- end
37
-
38
32
  # Returns the IP address of the host
39
33
  #
40
34
  # @param [Machine] machine
@@ -79,7 +73,7 @@ module VagrantPlugins
79
73
  # Check if we can open a connection to the host
80
74
  def ping(host, timeout = 3)
81
75
  ::Timeout.timeout(timeout) do
82
- s = TCPSocket.new(host, 'echo')
76
+ s = TCPSocket.new(host, 'ssh')
83
77
  s.close
84
78
  end
85
79
  true
@@ -1,22 +1,31 @@
1
+ require 'vagrant-libvirt/util/nfs'
1
2
  require 'yaml'
3
+
2
4
  module VagrantPlugins
3
5
  module ProviderLibvirt
4
6
  module Action
5
7
  class PruneNFSExports
8
+ include VagrantPlugins::ProviderLibvirt::Util::Nfs
9
+
6
10
  def initialize(app, _env)
7
11
  @app = app
8
12
  end
9
13
 
10
14
  def call(env)
11
- if env[:host]
12
- uuid = env[:machine].id
13
- # get all uuids
14
- uuids = env[:machine].provider.driver.connection.servers.all.map(&:id)
15
- # not exiisted in array will removed from nfs
16
- uuids.delete(uuid)
17
- env[:host].capability(
18
- :nfs_prune, env[:machine].ui, uuids
19
- )
15
+ @machine = env[:machine]
16
+
17
+ if using_nfs?
18
+ @logger.info('Using NFS, prunning NFS settings from host')
19
+ if env[:host]
20
+ uuid = env[:machine].id
21
+ # get all uuids
22
+ uuids = env[:machine].provider.driver.connection.servers.all.map(&:id)
23
+ # not exiisted in array will removed from nfs
24
+ uuids.delete(uuid)
25
+ env[:host].capability(
26
+ :nfs_prune, env[:machine].ui, uuids
27
+ )
28
+ end
20
29
  end
21
30
 
22
31
  @app.call(env)
@@ -10,8 +10,8 @@ module VagrantPlugins
10
10
  end
11
11
 
12
12
  def call(env)
13
- env[:ui].info('Vagrant-libvirt plugin removed box only from you LOCAL ~/.vagrant/boxes directory')
14
- env[:ui].info('From libvirt storage pool you have to delete image manually(virsh, virt-manager or by any other tool)')
13
+ env[:ui].info('Vagrant-libvirt plugin removed box only from your LOCAL ~/.vagrant/boxes directory')
14
+ env[:ui].info('From Libvirt storage pool you have to delete image manually(virsh, virt-manager or by any other tool)')
15
15
  @app.call(env)
16
16
  end
17
17
  end
@@ -16,13 +16,19 @@ module VagrantPlugins
16
16
 
17
17
  def call(env)
18
18
  # Remove stale server volume
19
- env[:ui].info(I18n.t('vagrant_libvirt.remove_stale_volume'))
20
-
21
19
  config = env[:machine].provider_config
22
20
  # Check for storage pool, where box image should be created
23
- fog_pool = ProviderLibvirt::Util::Collection.find_matching(
24
- env[:machine].provider.driver.connection.pools.all, config.storage_pool_name
25
- )
21
+ fog_pool = env[:machine].provider.driver.connection.pools.all(
22
+ name: config.storage_pool_name
23
+ ).first
24
+
25
+ env[:result] = nil
26
+
27
+ if not fog_pool
28
+ @logger.debug("**** Pool #{config.storage_pool_name} not found")
29
+ return @app.call(env)
30
+ end
31
+
26
32
  @logger.debug("**** Pool #{fog_pool.name}")
27
33
 
28
34
  # This is name of newly created image for vm.
@@ -30,17 +36,17 @@ module VagrantPlugins
30
36
  @logger.debug("**** Volume name #{name}")
31
37
 
32
38
  # remove root storage
33
- box_volume = ProviderLibvirt::Util::Collection.find_matching(
34
- env[:machine].provider.driver.connection.volumes.all, name
35
- )
36
- if box_volume && box_volume.pool_name == fog_pool.name
39
+ box_volume = env[:machine].provider.driver.connection.volumes.all(
40
+ name: name
41
+ ).find { |x| x.pool_name == fog_pool.name }
42
+ if box_volume && box_volume.id
43
+ env[:ui].info(I18n.t('vagrant_libvirt.remove_stale_volume'))
37
44
  @logger.info("Deleting volume #{box_volume.key}")
38
45
  box_volume.destroy
39
46
  env[:result] = box_volume
40
47
  else
41
- env[:result] = nil
48
+ @logger.debug("**** Volume #{name} not found in pool #{fog_pool.name}")
42
49
  end
43
-
44
50
  # Continue the middleware chain.
45
51
  @app.call(env)
46
52
  end
@@ -33,7 +33,7 @@ module VagrantPlugins
33
33
  if @boot_order.count >= 1
34
34
 
35
35
  # If a domain is initially defined with no box or disk or
36
- # with an explicit boot order, libvirt adds <boot dev="foo">
36
+ # with an explicit boot order, Libvirt adds <boot dev="foo">
37
37
  # This conflicts with an explicit boot_order configuration,
38
38
  # so we need to remove it from the domain xml and feed it back.
39
39
  # Also see https://bugzilla.redhat.com/show_bug.cgi?id=1248514
@@ -66,7 +66,7 @@ module VagrantPlugins
66
66
  logger_msg(node, index)
67
67
  end
68
68
 
69
- # Finally redefine the domain XML through libvirt
69
+ # Finally redefine the domain XML through Libvirt
70
70
  # to apply the boot ordering
71
71
  env[:machine].provider
72
72
  .driver
@@ -13,20 +13,17 @@ module VagrantPlugins
13
13
  env[:domain_name] = build_domain_name(env)
14
14
 
15
15
  begin
16
- @logger.info("Looking for domain #{env[:domain_name]} through list " \
17
- "#{env[:machine].provider.driver.connection.servers.all}")
16
+ @logger.info("Looking for domain #{env[:domain_name]}")
18
17
  # Check if the domain name is not already taken
19
18
 
20
- domain = ProviderLibvirt::Util::Collection.find_matching(
21
- env[:machine].provider.driver.connection.servers.all, env[:domain_name]
19
+ domain = env[:machine].provider.driver.connection.servers.all(
20
+ name: env[:domain_name]
22
21
  )
23
- rescue Fog::Errors::Error => e
22
+ rescue Libvirt::RetrieveError => e
24
23
  @logger.info(e.to_s)
25
24
  domain = nil
26
25
  end
27
26
 
28
- @logger.info("Looking for domain #{env[:domain_name]}")
29
-
30
27
  unless domain.nil?
31
28
  raise ProviderLibvirt::Errors::DomainNameExists,
32
29
  domain_name: env[:domain_name]
@@ -41,7 +38,7 @@ module VagrantPlugins
41
38
  # parsable and sortable by epoch time
42
39
  # @example
43
40
  # development-centos-6-chef-11_1404488971_3b7a569e2fd7c554b852
44
- # @return [String] libvirt domain name
41
+ # @return [String] Libvirt domain name
45
42
  def build_domain_name(env)
46
43
  config = env[:machine].provider_config
47
44
  domain_name =
@@ -51,7 +48,7 @@ module VagrantPlugins
51
48
  # don't have any prefix, not even "_"
52
49
  ''
53
50
  else
54
- config.default_prefix.to_s.dup.concat('_')
51
+ config.default_prefix.to_s.dup
55
52
  end
56
53
  domain_name << env[:machine].name.to_s
57
54
  domain_name.gsub!(/[^-a-z0-9_\.]/i, '')
@@ -23,7 +23,7 @@ module VagrantPlugins
23
23
 
24
24
  libvirt_domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(env[:machine].id)
25
25
 
26
- # libvirt API doesn't support modifying memory on NUMA enabled CPUs
26
+ # Libvirt API doesn't support modifying memory on NUMA enabled CPUs
27
27
  # http://libvirt.org/git/?p=libvirt.git;a=commit;h=d174394105cf00ed266bf729ddf461c21637c736
28
28
  if config.numa_nodes == nil
29
29
  if config.memory.to_i * 1024 != libvirt_domain.max_memory
@@ -68,7 +68,7 @@ module VagrantPlugins
68
68
  end
69
69
 
70
70
  # vCpu count
71
- if config.cpus.to_i != libvirt_domain.vcpus.length
71
+ if config.cpus.to_i != libvirt_domain.num_vcpus(0)
72
72
  descr_changed = true
73
73
  REXML::XPath.first(xml_descr, '/domain/vcpu').text = config.cpus
74
74
  end
@@ -28,7 +28,7 @@ module VagrantPlugins
28
28
  end
29
29
 
30
30
  # Wait for domain to obtain an ip address. Ip address is searched
31
- # from arp table, either localy or remotely via ssh, if libvirt
31
+ # from arp table, either locally or remotely via ssh, if Libvirt
32
32
  # connection was done via ssh.
33
33
  env[:ip_address] = nil
34
34
  @logger.debug("Searching for IP for MAC address: #{domain.mac}")
@@ -37,8 +37,8 @@ module VagrantPlugins
37
37
  if env[:machine].provider_config.qemu_use_session
38
38
  env[:metrics]['instance_ip_time'] = Util::Timer.time do
39
39
  retryable(on: Fog::Errors::TimeoutError, tries: 300) do
40
- # If we're interrupted don't worry about waiting
41
- return terminate(env) if env[:interrupted]
40
+ # just return if interrupted and let the warden call recover
41
+ return if env[:interrupted]
42
42
 
43
43
  # Wait for domain to obtain an ip address
44
44
  domain.wait_for(2) do
@@ -50,8 +50,8 @@ module VagrantPlugins
50
50
  else
51
51
  env[:metrics]['instance_ip_time'] = Util::Timer.time do
52
52
  retryable(on: Fog::Errors::TimeoutError, tries: 300) do
53
- # If we're interrupted don't worry about waiting
54
- return terminate(env) if env[:interrupted]
53
+ # just return if interrupted and let the warden call recover
54
+ return if env[:interrupted]
55
55
 
56
56
  # Wait for domain to obtain an ip address
57
57
  domain.wait_for(2) do
@@ -84,8 +84,8 @@ module VagrantPlugins
84
84
  end
85
85
  end
86
86
  end
87
- # if interrupted above, just terminate immediately
88
- return terminate(env) if env[:interrupted]
87
+ # just return if interrupted and let the warden call recover
88
+ return if env[:interrupted]
89
89
  @logger.info("Time for SSH ready: #{env[:metrics]['instance_ssh_time']}")
90
90
 
91
91
  # Booted and ready for use.
@@ -95,8 +95,6 @@ module VagrantPlugins
95
95
  end
96
96
 
97
97
  def recover(env)
98
- return if env['vagrant.error'].is_a?(Vagrant::Errors::VagrantError)
99
-
100
98
  # Undo the import
101
99
  terminate(env)
102
100
  end
@@ -20,7 +20,7 @@ module VagrantPlugins
20
20
  end
21
21
 
22
22
  def usable?(machine, _raise_error = false)
23
- # bail now if not using libvirt since checking version would throw error
23
+ # bail now if not using Libvirt since checking version would throw error
24
24
  return false unless machine.provider_name == :libvirt
25
25
 
26
26
  # <filesystem/> support in device attach/detach introduced in 1.2.2
@@ -30,7 +30,7 @@ module VagrantPlugins
30
30
  end
31
31
 
32
32
  def prepare(machine, folders, _opts)
33
- raise Vagrant::Errors::Error('No libvirt connection') if machine.provider.driver.connection.nil?
33
+ raise Vagrant::Errors::Error('No Libvirt connection') if machine.provider.driver.connection.nil?
34
34
  @conn = machine.provider.driver.connection.client
35
35
 
36
36
  begin
@@ -89,7 +89,7 @@ module VagrantPlugins
89
89
 
90
90
  def cleanup(machine, _opts)
91
91
  if machine.provider.driver.connection.nil?
92
- raise Vagrant::Errors::Error('No libvirt connection')
92
+ raise Vagrant::Errors::Error('No Libvirt connection')
93
93
  end
94
94
  @conn = machine.provider.driver.connection.client
95
95
  begin
@@ -20,12 +20,12 @@ module VagrantPlugins
20
20
  # A hypervisor name to access via Libvirt.
21
21
  attr_accessor :driver
22
22
 
23
- # The name of the server, where libvirtd is running.
23
+ # The name of the server, where Libvirtd is running.
24
24
  attr_accessor :host
25
25
 
26
26
  # If use ssh tunnel to connect to Libvirt.
27
27
  attr_accessor :connect_via_ssh
28
- # Path towards the libvirt socket
28
+ # Path towards the Libvirt socket
29
29
  attr_accessor :socket
30
30
 
31
31
  # The username to access Libvirt.
@@ -42,6 +42,9 @@ module VagrantPlugins
42
42
  attr_accessor :storage_pool_name
43
43
  attr_accessor :storage_pool_path
44
44
 
45
+ # Libvirt storage pool where the base image snapshot shall be stored
46
+ attr_accessor :snapshot_pool_name
47
+
45
48
  # Turn on to prevent hostname conflicts
46
49
  attr_accessor :random_hostname
47
50
 
@@ -55,6 +58,7 @@ module VagrantPlugins
55
58
  attr_accessor :management_network_autostart
56
59
  attr_accessor :management_network_pci_bus
57
60
  attr_accessor :management_network_pci_slot
61
+ attr_accessor :management_network_domain
58
62
 
59
63
  # System connection information
60
64
  attr_accessor :system_uri
@@ -65,14 +69,17 @@ module VagrantPlugins
65
69
  # Domain specific settings used while creating new domain.
66
70
  attr_accessor :uuid
67
71
  attr_accessor :memory
72
+ attr_accessor :nodeset
68
73
  attr_accessor :memory_backing
69
74
  attr_accessor :channel
70
75
  attr_accessor :cpus
76
+ attr_accessor :cpuset
71
77
  attr_accessor :cpu_mode
72
78
  attr_accessor :cpu_model
73
79
  attr_accessor :cpu_fallback
74
80
  attr_accessor :cpu_features
75
81
  attr_accessor :cpu_topology
82
+ attr_accessor :shares
76
83
  attr_accessor :features
77
84
  attr_accessor :features_hyperv
78
85
  attr_accessor :numa_nodes
@@ -158,7 +165,10 @@ module VagrantPlugins
158
165
  # Additional qemuargs arguments
159
166
  attr_accessor :qemu_args
160
167
 
161
- # Use qemu session instead of system
168
+ # Additional qemuenv arguments
169
+ attr_accessor :qemu_env
170
+
171
+ # Use QEMU session instead of system
162
172
  attr_accessor :qemu_use_session
163
173
 
164
174
  def initialize
@@ -170,6 +180,7 @@ module VagrantPlugins
170
180
  @password = UNSET_VALUE
171
181
  @id_ssh_key_file = UNSET_VALUE
172
182
  @storage_pool_name = UNSET_VALUE
183
+ @snapshot_pool_name = UNSET_VALUE
173
184
  @random_hostname = UNSET_VALUE
174
185
  @management_network_device = UNSET_VALUE
175
186
  @management_network_name = UNSET_VALUE
@@ -180,6 +191,7 @@ module VagrantPlugins
180
191
  @management_network_autostart = UNSET_VALUE
181
192
  @management_network_pci_slot = UNSET_VALUE
182
193
  @management_network_pci_bus = UNSET_VALUE
194
+ @management_network_domain = UNSET_VALUE
183
195
 
184
196
  # System connection information
185
197
  @system_uri = UNSET_VALUE
@@ -187,13 +199,16 @@ module VagrantPlugins
187
199
  # Domain specific settings.
188
200
  @uuid = UNSET_VALUE
189
201
  @memory = UNSET_VALUE
202
+ @nodeset = UNSET_VALUE
190
203
  @memory_backing = UNSET_VALUE
191
204
  @cpus = UNSET_VALUE
205
+ @cpuset = UNSET_VALUE
192
206
  @cpu_mode = UNSET_VALUE
193
207
  @cpu_model = UNSET_VALUE
194
208
  @cpu_fallback = UNSET_VALUE
195
209
  @cpu_features = UNSET_VALUE
196
210
  @cpu_topology = UNSET_VALUE
211
+ @shares = UNSET_VALUE
197
212
  @features = UNSET_VALUE
198
213
  @features_hyperv = UNSET_VALUE
199
214
  @numa_nodes = UNSET_VALUE
@@ -272,7 +287,12 @@ module VagrantPlugins
272
287
  # Attach mgmt network
273
288
  @mgmt_attach = UNSET_VALUE
274
289
 
275
- @qemu_args = []
290
+ # Additional QEMU commandline arguments
291
+ @qemu_args = UNSET_VALUE
292
+
293
+ # Additional QEMU commandline environment variables
294
+ @qemu_env = UNSET_VALUE
295
+
276
296
  @qemu_use_session = UNSET_VALUE
277
297
  end
278
298
 
@@ -305,7 +325,7 @@ module VagrantPlugins
305
325
  end
306
326
  end
307
327
 
308
- # is it better to raise our own error, or let libvirt cause the exception?
328
+ # is it better to raise our own error, or let Libvirt cause the exception?
309
329
  raise 'Only four cdroms may be attached at a time'
310
330
  end
311
331
 
@@ -349,7 +369,10 @@ module VagrantPlugins
349
369
  raise 'Feature name AND state must be specified'
350
370
  end
351
371
 
352
- @features_hyperv = [{name: options[:name], state: options[:state]}] if @features_hyperv == UNSET_VALUE
372
+ @features_hyperv = [] if @features_hyperv == UNSET_VALUE
373
+
374
+ @features_hyperv.push(name: options[:name],
375
+ state: options[:state])
353
376
  end
354
377
 
355
378
  def cputopology(options = {})
@@ -431,7 +454,14 @@ module VagrantPlugins
431
454
 
432
455
  @pcis = [] if @pcis == UNSET_VALUE
433
456
 
434
- @pcis.push(bus: options[:bus],
457
+ if options[:domain].nil?
458
+ pci_domain = '0x0000'
459
+ else
460
+ pci_domain = options[:domain]
461
+ end
462
+
463
+ @pcis.push(domain: pci_domain,
464
+ bus: options[:bus],
435
465
  slot: options[:slot],
436
466
  function: options[:function])
437
467
  end
@@ -577,12 +607,20 @@ module VagrantPlugins
577
607
  end
578
608
 
579
609
  def qemuargs(options = {})
610
+ @qemu_args = [] if @qemu_args == UNSET_VALUE
611
+
580
612
  @qemu_args << options if options[:value]
581
613
  end
582
614
 
615
+ def qemuenv(options = {})
616
+ @qemu_env = {} if @qemu_env == UNSET_VALUE
617
+
618
+ @qemu_env.merge!(options)
619
+ end
620
+
583
621
  # code to generate URI from a config moved out of the connect action
584
622
  def _generate_uri
585
- # builds the libvirt connection URI from the given driver config
623
+ # builds the Libvirt connection URI from the given driver config
586
624
  # Setup connection uri.
587
625
  uri = @driver.dup
588
626
  virt_path = case uri
@@ -598,7 +636,7 @@ module VagrantPlugins
598
636
  raise "Require specify driver #{uri}"
599
637
  end
600
638
  if uri == 'kvm'
601
- uri = 'qemu' # use qemu uri for kvm domain type
639
+ uri = 'qemu' # use QEMU uri for KVM domain type
602
640
  end
603
641
 
604
642
  if @connect_via_ssh
@@ -619,13 +657,13 @@ module VagrantPlugins
619
657
  uri << '?no_verify=1'
620
658
 
621
659
  if @id_ssh_key_file
622
- # set ssh key for access to libvirt host
660
+ # set ssh key for access to Libvirt host
623
661
  uri << "\&keyfile="
624
662
  # if no slash, prepend $HOME/.ssh/
625
663
  @id_ssh_key_file.prepend("#{`echo ${HOME}`.chomp}/.ssh/") if @id_ssh_key_file !~ /\A\//
626
664
  uri << @id_ssh_key_file
627
665
  end
628
- # set path to libvirt socket
666
+ # set path to Libvirt socket
629
667
  uri << "\&socket=" + @socket if @socket
630
668
  uri
631
669
  end
@@ -638,6 +676,7 @@ module VagrantPlugins
638
676
  @password = nil if @password == UNSET_VALUE
639
677
  @id_ssh_key_file = 'id_rsa' if @id_ssh_key_file == UNSET_VALUE
640
678
  @storage_pool_name = 'default' if @storage_pool_name == UNSET_VALUE
679
+ @snapshot_pool_name = @storage_pool_name if @snapshot_pool_name == UNSET_VALUE
641
680
  @storage_pool_path = nil if @storage_pool_path == UNSET_VALUE
642
681
  @random_hostname = false if @random_hostname == UNSET_VALUE
643
682
  @management_network_device = 'virbr0' if @management_network_device == UNSET_VALUE
@@ -649,6 +688,7 @@ module VagrantPlugins
649
688
  @management_network_autostart = false if @management_network_autostart == UNSET_VALUE
650
689
  @management_network_pci_bus = nil if @management_network_pci_bus == UNSET_VALUE
651
690
  @management_network_pci_slot = nil if @management_network_pci_slot == UNSET_VALUE
691
+ @management_network_domain = nil if @management_network_domain == UNSET_VALUE
652
692
  @system_uri = 'qemu:///system' if @system_uri == UNSET_VALUE
653
693
 
654
694
  @qemu_use_session = false if @qemu_use_session == UNSET_VALUE
@@ -659,8 +699,10 @@ module VagrantPlugins
659
699
  # Domain specific settings.
660
700
  @uuid = '' if @uuid == UNSET_VALUE
661
701
  @memory = 512 if @memory == UNSET_VALUE
702
+ @nodeset = nil if @nodeset == UNSET_VALUE
662
703
  @memory_backing = [] if @memory_backing == UNSET_VALUE
663
704
  @cpus = 1 if @cpus == UNSET_VALUE
705
+ @cpuset = nil if @cpuset == UNSET_VALUE
664
706
  @cpu_mode = 'host-model' if @cpu_mode == UNSET_VALUE
665
707
  @cpu_model = if (@cpu_model == UNSET_VALUE) && (@cpu_mode == 'custom')
666
708
  'qemu64'
@@ -672,6 +714,7 @@ module VagrantPlugins
672
714
  @cpu_topology = {} if @cpu_topology == UNSET_VALUE
673
715
  @cpu_fallback = 'allow' if @cpu_fallback == UNSET_VALUE
674
716
  @cpu_features = [] if @cpu_features == UNSET_VALUE
717
+ @shares = nil if @shares == UNSET_VALUE
675
718
  @features = ['acpi','apic','pae'] if @features == UNSET_VALUE
676
719
  @features_hyperv = [] if @features_hyperv == UNSET_VALUE
677
720
  @numa_nodes = @numa_nodes == UNSET_VALUE ? nil : _generate_numa
@@ -761,7 +804,11 @@ module VagrantPlugins
761
804
  # Attach mgmt network
762
805
  @mgmt_attach = true if @mgmt_attach == UNSET_VALUE
763
806
 
807
+ # Additional QEMU commandline arguments
764
808
  @qemu_args = [] if @qemu_args == UNSET_VALUE
809
+
810
+ # Additional QEMU commandline environment variables
811
+ @qemu_env = {} if @qemu_env == UNSET_VALUE
765
812
  end
766
813
 
767
814
  def validate(machine)
@@ -797,6 +844,10 @@ module VagrantPlugins
797
844
  c = cdroms.dup
798
845
  c += other.cdroms
799
846
  result.cdroms = c
847
+
848
+ c = qemu_env != UNSET_VALUE ? qemu_env.dup : {}
849
+ c.merge!(other.qemu_env) if other.qemu_env != UNSET_VALUE
850
+ result.qemu_env = c
800
851
  end
801
852
  end
802
853
  end