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
@@ -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
@@ -187,7 +187,7 @@ module VagrantPlugins
187
187
  b2.use Call, DestroyConfirm do |env2, b3|
188
188
  if env2[:result]
189
189
  b3.use ClearForwardedPorts
190
- # b3.use PruneNFSExports
190
+ b3.use PruneNFSExports
191
191
  b3.use DestroyDomain
192
192
  b3.use DestroyNetworks
193
193
  b3.use ProvisionerCleanup
@@ -33,10 +33,13 @@ module VagrantPlugins
33
33
  @name = env[:domain_name]
34
34
  @uuid = config.uuid
35
35
  @cpus = config.cpus.to_i
36
+ @cpuset = config.cpuset
36
37
  @cpu_features = config.cpu_features
37
38
  @cpu_topology = config.cpu_topology
39
+ @nodeset = config.nodeset
38
40
  @features = config.features
39
41
  @features_hyperv = config.features_hyperv
42
+ @shares = config.shares
40
43
  @cpu_mode = config.cpu_mode
41
44
  @cpu_model = config.cpu_model
42
45
  @cpu_fallback = config.cpu_fallback
@@ -81,6 +84,7 @@ module VagrantPlugins
81
84
 
82
85
  # Storage
83
86
  @storage_pool_name = config.storage_pool_name
87
+ @snapshot_pool_name = config.snapshot_pool_name
84
88
  @disks = config.disks
85
89
  @cdroms = config.cdroms
86
90
 
@@ -106,6 +110,12 @@ module VagrantPlugins
106
110
  @redirdevs = config.redirdevs
107
111
  @redirfilters = config.redirfilters
108
112
 
113
+ # Additional QEMU commandline arguments
114
+ @qemu_args = config.qemu_args
115
+
116
+ # Additional QEMU commandline environment variables
117
+ @qemu_env = config.qemu_env
118
+
109
119
  # smartcard device
110
120
  @smartcard_dev = config.smartcard_dev
111
121
 
@@ -119,13 +129,15 @@ module VagrantPlugins
119
129
 
120
130
  # Get path to domain image from the storage pool selected if we have a box.
121
131
  if env[:machine].config.vm.box
122
- actual_volumes =
123
- env[:machine].provider.driver.connection.volumes.all.select do |x|
124
- x.pool_name == @storage_pool_name
125
- end
126
- domain_volume = ProviderLibvirt::Util::Collection.find_matching(
127
- actual_volumes, "#{@name}.img"
128
- )
132
+ if @snapshot_pool_name != @storage_pool_name
133
+ pool_name = @snapshot_pool_name
134
+ else
135
+ pool_name = @storage_pool_name
136
+ end
137
+ @logger.debug "Search for volume in pool: #{pool_name}"
138
+ domain_volume = env[:machine].provider.driver.connection.volumes.all(
139
+ name: "#{@name}.img"
140
+ ).find { |x| x.pool_name == pool_name }
129
141
  raise Errors::DomainVolumeExists if domain_volume.nil?
130
142
  @domain_volume_path = domain_volume.path
131
143
  end
@@ -155,26 +167,28 @@ module VagrantPlugins
155
167
 
156
168
  disk[:absolute_path] = storage_prefix + disk[:path]
157
169
 
158
- if env[:machine].provider.driver.connection.volumes.select do |x|
159
- x.name == disk[:name] && x.pool_name == @storage_pool_name
160
- end.empty?
161
- # make the disk. equivalent to:
162
- # qemu-img create -f qcow2 <path> 5g
163
- begin
164
- env[:machine].provider.driver.connection.volumes.create(
165
- name: disk[:name],
166
- format_type: disk[:type],
167
- path: disk[:absolute_path],
168
- capacity: disk[:size],
169
- #:allocation => ?,
170
- pool_name: @storage_pool_name
171
- )
172
- rescue Fog::Errors::Error => e
170
+ # make the disk. equivalent to:
171
+ # qemu-img create -f qcow2 <path> 5g
172
+ begin
173
+ env[:machine].provider.driver.connection.volumes.create(
174
+ name: disk[:name],
175
+ format_type: disk[:type],
176
+ path: disk[:absolute_path],
177
+ capacity: disk[:size],
178
+ #:allocation => ?,
179
+ pool_name: @storage_pool_name
180
+ )
181
+ rescue Libvirt::Error => e
182
+ # It is hard to believe that e contains just a string
183
+ # and no useful error code!
184
+ msg = "Call to virStorageVolCreateXML failed: " +
185
+ "storage volume '#{disk[:path]}' exists already"
186
+ if e.message == msg and disk[:allow_existing]
187
+ disk[:preexisting] = true
188
+ else
173
189
  raise Errors::FogDomainVolumeCreateError,
174
190
  error_message: e.message
175
191
  end
176
- else
177
- disk[:preexisting] = true
178
192
  end
179
193
  end
180
194
 
@@ -184,6 +198,9 @@ module VagrantPlugins
184
198
  env[:ui].info(" -- Forced UUID: #{@uuid}") if @uuid != ''
185
199
  env[:ui].info(" -- Domain type: #{@domain_type}")
186
200
  env[:ui].info(" -- Cpus: #{@cpus}")
201
+ unless @cpuset.nil?
202
+ env[:ui].info(" -- Cpuset: #{@cpuset}")
203
+ end
187
204
  if not @cpu_topology.empty?
188
205
  env[:ui].info(" -- CPU topology: sockets=#{@cpu_topology[:sockets]}, cores=#{@cpu_topology[:cores]}, threads=#{@cpu_topology[:threads]}")
189
206
  end
@@ -197,9 +214,15 @@ module VagrantPlugins
197
214
  env[:ui].info(" -- Feature (HyperV): name=#{feature[:name]}, state=#{feature[:state]}")
198
215
  end
199
216
  env[:ui].info(" -- Memory: #{@memory_size / 1024}M")
217
+ unless @nodeset.nil?
218
+ env[:ui].info(" -- Nodeset: #{@nodeset}")
219
+ end
200
220
  @memory_backing.each do |backing|
201
221
  env[:ui].info(" -- Memory Backing: #{backing[:name]}: #{backing[:config].map { |k,v| "#{k}='#{v}'"}.join(' ')}")
202
222
  end
223
+ unless @shares.nil?
224
+ env[:ui].info(" -- Shares: #{@shares}")
225
+ end
203
226
  env[:ui].info(" -- Management MAC: #{@management_network_mac}")
204
227
  env[:ui].info(" -- Loader: #{@loader}")
205
228
  env[:ui].info(" -- Nvram: #{@nvram}")
@@ -255,7 +278,7 @@ module VagrantPlugins
255
278
  end
256
279
 
257
280
  @pcis.each do |pci|
258
- env[:ui].info(" -- PCI passthrough: #{pci[:bus]}:#{pci[:slot]}.#{pci[:function]}")
281
+ env[:ui].info(" -- PCI passthrough: #{pci[:domain]}:#{pci[:bus]}:#{pci[:slot]}.#{pci[:function]}")
259
282
  end
260
283
 
261
284
  unless @rng[:model].nil?
@@ -305,18 +328,25 @@ module VagrantPlugins
305
328
  env[:ui].info(" -- smartcard device: mode=#{@smartcard_dev[:mode]}, type=#{@smartcard_dev[:type]}")
306
329
  end
307
330
 
308
- @qargs = config.qemu_args
309
- if not @qargs.empty?
331
+ unless @qemu_args.empty?
310
332
  env[:ui].info(' -- Command line args: ')
311
- @qargs.each do |arg|
333
+ @qemu_args.each do |arg|
312
334
  msg = " -> value=#{arg[:value]}, "
313
335
  env[:ui].info(msg)
314
336
  end
315
337
  end
316
338
 
339
+ unless @qemu_env.empty?
340
+ env[:ui].info(' -- Command line environment variables: ')
341
+ @qemu_env.each do |env_var, env_value|
342
+ msg = " -> #{env_var}=#{env_value}, "
343
+ env[:ui].info(msg)
344
+ end
345
+ end
346
+
317
347
  env[:ui].info(" -- Command line : #{@cmd_line}") unless @cmd_line.empty?
318
348
 
319
- # Create libvirt domain.
349
+ # Create Libvirt domain.
320
350
  # Is there a way to tell fog to create new domain with already
321
351
  # existing volume? Use domain creation from template..
322
352
  begin
@@ -25,15 +25,15 @@ module VagrantPlugins
25
25
  @name = "#{env[:domain_name]}.img"
26
26
 
27
27
  # Verify the volume doesn't exist already.
28
- domain_volume = ProviderLibvirt::Util::Collection.find_matching(
29
- env[:machine].provider.driver.connection.volumes.all, @name
30
- )
31
- 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
32
32
 
33
33
  # Get path to backing image - box volume.
34
- box_volume = ProviderLibvirt::Util::Collection.find_matching(
35
- env[:machine].provider.driver.connection.volumes.all, env[:box_volume_name]
36
- )
34
+ box_volume = env[:machine].provider.driver.connection.volumes.all(
35
+ name: env[:box_volume_name]
36
+ ).first
37
37
  @backing_file = box_volume.path
38
38
 
39
39
  # Virtual size of image. Take value worked out by HandleBoxImage
@@ -71,9 +71,15 @@ module VagrantPlugins
71
71
  Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS |
72
72
  Nokogiri::XML::Node::SaveOptions::FORMAT
73
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
78
+ end
79
+ @logger.debug "Using pool #{pool_name} for base box snapshot"
74
80
  domain_volume = env[:machine].provider.driver.connection.volumes.create(
75
81
  xml: xml,
76
- pool_name: config.storage_pool_name
82
+ pool_name: pool_name
77
83
  )
78
84
  rescue Fog::Errors::Error => e
79
85
  raise Errors::FogDomainVolumeCreateError,
@@ -219,10 +219,12 @@ module VagrantPlugins
219
219
  networks_to_configure << network
220
220
  end
221
221
 
222
- env[:ui].info I18n.t('vagrant.actions.vm.network.configuring')
223
- env[:machine].guest.capability(
224
- :configure_networks, networks_to_configure
225
- )
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
226
228
 
227
229
  end
228
230
  end
@@ -281,7 +283,7 @@ module VagrantPlugins
281
283
  return options[:network_name]
282
284
  end
283
285
 
284
- # Get list of all (active and inactive) libvirt networks.
286
+ # Get list of all (active and inactive) Libvirt networks.
285
287
  available_networks = libvirt_networks(libvirt_client)
286
288
 
287
289
  return 'public' if options[:iface_type] == :public_network
@@ -47,9 +47,9 @@ module VagrantPlugins
47
47
  # should fix other methods so this doesn't have to be instance var
48
48
  @options = options
49
49
 
50
- # Get a list of all (active and inactive) libvirt networks. This
50
+ # Get a list of all (active and inactive) Libvirt networks. This
51
51
  # list is used throughout this class and should be easier to
52
- # process than libvirt API calls.
52
+ # process than Libvirt API calls.
53
53
  @available_networks = libvirt_networks(
54
54
  env[:machine].provider.driver.connection.client
55
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(
@@ -54,7 +54,7 @@ module VagrantPlugins
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,7 @@ module VagrantPlugins
97
97
  User=#{ssh_info[:username]}
98
98
  Port=#{ssh_info[:port]}
99
99
  UserKnownHostsFile=/dev/null
100
+ ExitOnForwardFailure=yes
100
101
  StrictHostKeyChecking=no
101
102
  PasswordAuthentication=no
102
103
  ForwardX11=#{ssh_info[:forward_x11] ? 'yes' : 'no'}
@@ -120,7 +121,7 @@ module VagrantPlugins
120
121
  end
121
122
  end
122
123
 
123
- ssh_cmd << "ssh #{options} #{params}"
124
+ ssh_cmd << "ssh -n #{options} #{params}"
124
125
 
125
126
  @logger.debug "Forwarding port with `#{ssh_cmd}`"
126
127
  log_file = ssh_forward_log_file(host_ip, host_port,
@@ -210,9 +211,9 @@ module VagrantPlugins
210
211
  end
211
212
 
212
213
  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/
214
+ @logger.debug "Checking if #{pid} is an ssh process "\
215
+ "with `ps -o command= #{pid}`"
216
+ `ps -o command= #{pid}`.strip.chomp =~ /ssh/
216
217
  end
217
218
 
218
219
  def remove_ssh_pids
@@ -19,7 +19,7 @@ module VagrantPlugins
19
19
  begin
20
20
  env[:machine].guest.capability(:halt)
21
21
  rescue
22
- @logger.info('Trying libvirt graceful shutdown.')
22
+ @logger.info('Trying Libvirt graceful shutdown.')
23
23
  domain.shutdown
24
24
  end
25
25
 
@@ -4,7 +4,6 @@ module VagrantPlugins
4
4
  module ProviderLibvirt
5
5
  module Action
6
6
  class HandleBoxImage
7
- include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
8
7
  include VagrantPlugins::ProviderLibvirt::Util::StorageUtil
9
8
 
10
9
 
@@ -64,9 +63,10 @@ module VagrantPlugins
64
63
  # locking all subsequent actions as well.
65
64
  @@lock.synchronize do
66
65
  # Don't continue if image already exists in storage pool.
67
- break if ProviderLibvirt::Util::Collection.find_matching(
68
- env[:machine].provider.driver.connection.volumes.all, env[:box_volume_name]
69
- )
66
+ box_volume = env[:machine].provider.driver.connection.volumes.all(
67
+ name: env[:box_volume_name]
68
+ ).first
69
+ break if box_volume && box_volume.id
70
70
 
71
71
  # Box is not available as a storage pool volume. Create and upload
72
72
  # it as a copy of local box image.
@@ -81,40 +81,22 @@ module VagrantPlugins
81
81
  message << " in storage pool #{config.storage_pool_name}."
82
82
  @logger.info(message)
83
83
 
84
- if config.qemu_use_session
85
- begin
86
- @name = env[:box_volume_name]
87
- @allocation = "#{box_image_size / 1024 / 1024}M"
88
- @capacity = "#{box_virtual_size}G"
89
- @format_type = box_format ? box_format : 'raw'
90
-
91
- @storage_volume_uid = storage_uid env
92
- @storage_volume_gid = storage_gid env
93
-
94
- libvirt_client = env[:machine].provider.driver.connection.client
95
- libvirt_pool = libvirt_client.lookup_storage_pool_by_name(
96
- config.storage_pool_name
97
- )
98
- libvirt_volume = libvirt_pool.create_volume_xml(
99
- to_xml('default_storage_volume')
100
- )
101
- rescue => e
102
- raise Errors::CreatingVolumeError,
103
- error_message: e.message
104
- end
105
- else
106
- begin
107
- fog_volume = env[:machine].provider.driver.connection.volumes.create(
108
- name: env[:box_volume_name],
109
- allocation: "#{box_image_size / 1024 / 1024}M",
110
- capacity: "#{box_virtual_size}G",
111
- format_type: box_format,
112
- pool_name: config.storage_pool_name
113
- )
114
- rescue Fog::Errors::Error => e
115
- raise Errors::FogCreateVolumeError,
116
- error_message: e.message
117
- end
84
+ @storage_volume_uid = storage_uid env
85
+ @storage_volume_gid = storage_gid env
86
+
87
+ begin
88
+ fog_volume = env[:machine].provider.driver.connection.volumes.create(
89
+ name: env[:box_volume_name],
90
+ allocation: "#{box_image_size / 1024 / 1024}M",
91
+ capacity: "#{box_virtual_size}G",
92
+ format_type: box_format,
93
+ owner: @storage_volume_uid,
94
+ group: @storage_volume_gid,
95
+ pool_name: config.storage_pool_name
96
+ )
97
+ rescue Fog::Errors::Error => e
98
+ raise Errors::FogCreateVolumeError,
99
+ error_message: e.message
118
100
  end
119
101
 
120
102
  # Upload box image to storage pool
@@ -132,11 +114,7 @@ module VagrantPlugins
132
114
  # storage pool.
133
115
  if env[:interrupted] || !ret
134
116
  begin
135
- if config.qemu_use_session
136
- libvirt_volume.delete
137
- else
138
- fog_volume.destroy
139
- end
117
+ fog_volume.destroy
140
118
  rescue
141
119
  nil
142
120
  end
@@ -146,22 +124,9 @@ module VagrantPlugins
146
124
  @app.call(env)
147
125
  end
148
126
 
149
- def split_size_unit(text)
150
- if text.kind_of? Integer
151
- # if text is an integer, match will fail
152
- size = text
153
- unit = 'G'
154
- else
155
- matcher = text.match(/(\d+)(.+)/)
156
- size = matcher[1]
157
- unit = matcher[2]
158
- end
159
- [size, unit]
160
- end
161
-
162
127
  protected
163
128
 
164
- # Fog libvirt currently doesn't support uploading images to storage
129
+ # Fog Libvirt currently doesn't support uploading images to storage
165
130
  # pool volumes. Use ruby-libvirt client instead.
166
131
  def upload_image(image_file, pool_name, volume_name, env)
167
132
  image_size = File.size(image_file) # B
@@ -24,9 +24,9 @@ module VagrantPlugins
24
24
  # locking all subsequent actions as well.
25
25
  @@lock.synchronize do
26
26
  # Check for storage pool, where box image should be created
27
- break if ProviderLibvirt::Util::Collection.find_matching(
28
- env[:machine].provider.driver.connection.pools.all, config.storage_pool_name
29
- )
27
+ break unless env[:machine].provider.driver.connection.pools.all(
28
+ name: config.storage_pool_name
29
+ ).empty?
30
30
 
31
31
  @logger.info("No storage pool '#{config.storage_pool_name}' is available.")
32
32
 
@@ -36,7 +36,7 @@ module VagrantPlugins
36
36
 
37
37
  @logger.info("Creating storage pool 'default'")
38
38
 
39
- # Fog libvirt currently doesn't support creating pools. Use
39
+ # Fog Libvirt currently doesn't support creating pools. Use
40
40
  # ruby-libvirt client directly.
41
41
  begin
42
42
  @storage_pool_path = storage_pool_path(env)