vagrant-libvirt 0.1.0 → 0.4.1

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +321 -76
  3. data/lib/vagrant-libvirt/action.rb +1 -1
  4. data/lib/vagrant-libvirt/action/create_domain.rb +54 -14
  5. data/lib/vagrant-libvirt/action/create_domain_volume.rb +0 -2
  6. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +1 -0
  7. data/lib/vagrant-libvirt/action/forward_ports.rb +4 -3
  8. data/lib/vagrant-libvirt/action/handle_box_image.rb +6 -3
  9. data/lib/vagrant-libvirt/action/package_domain.rb +10 -4
  10. data/lib/vagrant-libvirt/action/prune_nfs_exports.rb +4 -3
  11. data/lib/vagrant-libvirt/action/start_domain.rb +86 -29
  12. data/lib/vagrant-libvirt/action/wait_till_up.rb +7 -27
  13. data/lib/vagrant-libvirt/cap/public_address.rb +16 -0
  14. data/lib/vagrant-libvirt/config.rb +233 -32
  15. data/lib/vagrant-libvirt/driver.rb +49 -32
  16. data/lib/vagrant-libvirt/plugin.rb +6 -0
  17. data/lib/vagrant-libvirt/provider.rb +2 -9
  18. data/lib/vagrant-libvirt/templates/domain.xml.erb +34 -5
  19. data/lib/vagrant-libvirt/templates/public_interface.xml.erb +5 -1
  20. data/lib/vagrant-libvirt/util.rb +1 -0
  21. data/lib/vagrant-libvirt/util/erb_template.rb +6 -7
  22. data/lib/vagrant-libvirt/util/ui.rb +23 -0
  23. data/lib/vagrant-libvirt/version +1 -0
  24. data/lib/vagrant-libvirt/version.rb +72 -1
  25. data/spec/spec_helper.rb +28 -2
  26. data/spec/support/binding_proc.rb +24 -0
  27. data/spec/support/libvirt_context.rb +3 -1
  28. data/spec/support/sharedcontext.rb +7 -3
  29. data/spec/unit/action/create_domain_spec.rb +160 -0
  30. data/spec/unit/action/create_domain_spec/default_system_storage_pool.xml +17 -0
  31. data/spec/unit/action/create_domain_spec/default_user_storage_pool.xml +17 -0
  32. data/spec/unit/action/destroy_domain_spec.rb +2 -2
  33. data/spec/unit/action/set_name_of_domain_spec.rb +2 -2
  34. data/spec/unit/action/start_domain_spec.rb +231 -0
  35. data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +50 -0
  36. data/spec/unit/action/start_domain_spec/default.xml +48 -0
  37. data/spec/unit/action/start_domain_spec/default_added_tpm_path.xml +48 -0
  38. data/spec/unit/action/start_domain_spec/default_added_tpm_version.xml +48 -0
  39. data/spec/unit/action/wait_till_up_spec.rb +32 -9
  40. data/spec/unit/config_spec.rb +438 -0
  41. data/spec/unit/provider_spec.rb +11 -0
  42. data/spec/unit/templates/domain_all_settings.xml +8 -3
  43. data/spec/unit/templates/domain_custom_cpu_model.xml +4 -1
  44. data/spec/unit/templates/domain_defaults.xml +4 -1
  45. data/spec/unit/templates/domain_spec.rb +82 -2
  46. data/spec/unit/templates/tpm/version_1.2.xml +54 -0
  47. data/spec/unit/templates/tpm/version_2.0.xml +53 -0
  48. metadata +62 -6
@@ -60,12 +60,12 @@ module VagrantPlugins
60
60
  @@system_connection
61
61
  end
62
62
 
63
- def get_domain(mid)
63
+ def get_domain(machine)
64
64
  begin
65
- domain = connection.servers.get(mid)
65
+ domain = connection.servers.get(machine.id)
66
66
  rescue Libvirt::RetrieveError => e
67
67
  if e.libvirt_code == ProviderLibvirt::Util::ErrorCodes::VIR_ERR_NO_DOMAIN
68
- @logger.debug("machine #{mid} not found #{e}.")
68
+ @logger.debug("machine #{machine.name} domain not found #{e}.")
69
69
  return nil
70
70
  else
71
71
  raise e
@@ -75,36 +75,35 @@ module VagrantPlugins
75
75
  domain
76
76
  end
77
77
 
78
- def created?(mid)
79
- domain = get_domain(mid)
78
+ def created?(machine)
79
+ domain = get_domain(machine)
80
80
  !domain.nil?
81
81
  end
82
82
 
83
83
  def get_ipaddress(machine)
84
84
  # Find the machine
85
- domain = get_domain(machine.id)
86
- if @machine.provider_config.qemu_use_session
87
- return get_ipaddress_system domain.mac
88
- end
85
+ domain = get_domain(machine)
89
86
 
90
87
  if domain.nil?
91
88
  # The machine can't be found
92
89
  return nil
93
90
  end
94
91
 
95
- # Get IP address from arp table
96
- ip_address = nil
92
+ get_domain_ipaddress(machine, domain)
93
+ end
94
+
95
+ def get_domain_ipaddress(machine, domain)
96
+ if @machine.provider_config.qemu_use_session
97
+ return get_ipaddress_from_system domain.mac
98
+ end
99
+
100
+ # Get IP address from dhcp leases table
97
101
  begin
98
- domain.wait_for(2) do
99
- addresses.each_pair do |_type, ip|
100
- # Multiple leases are separated with a newline, return only
101
- # the most recent address
102
- ip_address = ip[0].split("\n").first unless ip[0].nil?
103
- end
104
- !ip_address.nil?
105
- end
102
+ ip_address = get_ipaddress_from_domain(domain)
106
103
  rescue Fog::Errors::TimeoutError
107
104
  @logger.info('Timeout at waiting for an ip address for machine %s' % machine.name)
105
+
106
+ raise
108
107
  end
109
108
 
110
109
  unless ip_address
@@ -115,7 +114,24 @@ module VagrantPlugins
115
114
  ip_address
116
115
  end
117
116
 
118
- def get_ipaddress_system(mac)
117
+ def state(machine)
118
+ # may be other error states with initial retreival we can't handle
119
+ begin
120
+ domain = get_domain(machine)
121
+ rescue Libvirt::RetrieveError => e
122
+ @logger.debug("Machine #{machine.id} not found #{e}.")
123
+ return :not_created
124
+ end
125
+
126
+ # TODO: terminated no longer appears to be a valid fog state, remove?
127
+ return :not_created if domain.nil? || domain.state.to_sym == :terminated
128
+
129
+ domain.state.tr('-', '_').to_sym
130
+ end
131
+
132
+ private
133
+
134
+ def get_ipaddress_from_system(mac)
119
135
  ip_address = nil
120
136
 
121
137
  system_connection.list_all_networks.each do |net|
@@ -125,23 +141,24 @@ module VagrantPlugins
125
141
  break if ip_address
126
142
  end
127
143
 
128
- return ip_address
144
+ ip_address
129
145
  end
130
146
 
131
- def state(machine)
132
- # may be other error states with initial retreival we can't handle
133
- begin
134
- domain = get_domain(machine.id)
135
- rescue Libvirt::RetrieveError => e
136
- @logger.debug("Machine #{machine.id} not found #{e}.")
137
- return :not_created
138
- end
147
+ def get_ipaddress_from_domain(domain)
148
+ ip_address = nil
149
+ domain.wait_for(2) do
150
+ addresses.each_pair do |type, ip|
151
+ # Multiple leases are separated with a newline, return only
152
+ # the most recent address
153
+ ip_address = ip[0].split("\n").first if ip[0] != nil
154
+ end
139
155
 
140
- # TODO: terminated no longer appears to be a valid fog state, remove?
141
- return :not_created if domain.nil? || domain.state.to_sym == :terminated
156
+ ip_address != nil
157
+ end
142
158
 
143
- domain.state.tr('-', '_').to_sym
159
+ ip_address
144
160
  end
161
+
145
162
  end
146
163
  end
147
164
  end
@@ -26,6 +26,7 @@ module VagrantPlugins
26
26
  end
27
27
 
28
28
  action_hook(:remove_libvirt_image) do |hook|
29
+ require_relative 'action'
29
30
  hook.after Vagrant::Action::Builtin::BoxRemove, Action.remove_libvirt_image
30
31
  end
31
32
 
@@ -39,6 +40,11 @@ module VagrantPlugins
39
40
  Cap::NicMacAddresses
40
41
  end
41
42
 
43
+ provider_capability(:libvirt, :public_address) do
44
+ require_relative 'cap/public_address'
45
+ Cap::PublicAddress
46
+ end
47
+
42
48
  # lower priority than nfs or rsync
43
49
  # https://github.com/vagrant-libvirt/vagrant-libvirt/pull/170
44
50
  synced_folder('9p', 4) do
@@ -68,14 +68,7 @@ module VagrantPlugins
68
68
  forward_x11: @machine.config.ssh.forward_x11
69
69
  }
70
70
 
71
- if @machine.provider_config.connect_via_ssh
72
- ssh_info[:proxy_command] =
73
- "ssh '#{@machine.provider_config.host}' " \
74
- "-l '#{@machine.provider_config.username}' " \
75
- "-i '#{@machine.provider_config.id_ssh_key_file}' " \
76
- 'nc %h %p'
77
-
78
- end
71
+ ssh_info[:proxy_command] = @machine.provider_config.proxy_command if @machine.provider_config.proxy_command
79
72
 
80
73
  ssh_info
81
74
  end
@@ -98,7 +91,7 @@ module VagrantPlugins
98
91
  state_id = nil
99
92
  state_id = :not_created unless @machine.id
100
93
  state_id = :not_created if
101
- !state_id && (!@machine.id || !driver.created?(@machine.id))
94
+ !state_id && (!@machine.id || !driver.created?(@machine))
102
95
  # Query the driver for the current state of the machine
103
96
  state_id = driver.state(@machine) if @machine.id && !state_id
104
97
  state_id = :unknown unless state_id
@@ -1,5 +1,7 @@
1
1
  <domain type='<%= @domain_type %>' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
2
2
  <name><%= @name %></name>
3
+ <title><%= @title %></title>
4
+ <description><%= @description %></description>
3
5
  <uuid><%= @uuid %></uuid>
4
6
  <memory><%= @memory_size %></memory>
5
7
  <vcpu<% if @cpuset %> cpuset='<%= @cpuset %>'<% end %>><%= @cpus %></vcpu>
@@ -102,14 +104,22 @@
102
104
  </hyperv>
103
105
  <% end %>
104
106
  </features>
105
- <clock offset='utc'/>
107
+ <clock offset='<%= @clock_offset %>'>
108
+ <% @clock_timers.each do |clock_timer| %>
109
+ <timer<% clock_timer.each do |attr, value| %> <%= attr %>='<%= value %>'<% end %>/>
110
+ <% end %>
111
+ </clock>
106
112
  <devices>
107
113
  <% if @emulator_path %>
108
114
  <emulator><%= @emulator_path %></emulator>
109
115
  <% end %>
110
116
  <% if @domain_volume_path %>
111
117
  <disk type='file' device='disk'>
112
- <driver name='qemu' type='qcow2' cache='<%= @domain_volume_cache %>'/>
118
+ <driver name='qemu' type='qcow2' <%=
119
+ @disk_driver_opts.empty? ? "cache='#{@domain_volume_cache}'" :
120
+ @disk_driver_opts.reject { |k,v| v.nil? }
121
+ .map { |k,v| "#{k}='#{v}'"}
122
+ .join(' ') -%>/>
113
123
  <source file='<%= @domain_volume_path %>'/>
114
124
  <%# we need to ensure a unique target dev -%>
115
125
  <target dev='<%= @disk_device %>' bus='<%= @disk_bus %>'/>
@@ -118,7 +128,12 @@
118
128
  <%# additional disks -%>
119
129
  <% @disks.each do |d| -%>
120
130
  <disk type='file' device='disk'>
121
- <driver name='qemu' type='<%= d[:type] %>' cache='<%= d[:cache] %>'/>
131
+ <driver name='qemu' type='<%= d[:type] %>' <%=
132
+ d.select { |k,_| [:cache, :io, :copy_on_read, :discard, :detect_zeroes].include? k }
133
+ .reject { |k,v| v.nil? }
134
+ .map { |k,v| "#{k}='#{v}'"}
135
+ .join(' ')
136
+ -%>/>
122
137
  <source file='<%= d[:absolute_path] %>'/>
123
138
  <target dev='<%= d[:device] %>' bus='<%= d[:bus] %>'/>
124
139
  <% if d[:shareable] %>
@@ -127,6 +142,9 @@
127
142
  <% if d[:serial] %>
128
143
  <serial><%= d[:serial] %></serial>
129
144
  <% end %>
145
+ <% if d[:wwn] %>
146
+ <wwn><%= d[:wwn] %></wwn>
147
+ <% end %>
130
148
  <%# this will get auto generated by Libvirt
131
149
  <address type='pci' domain='0x0000' bus='0x00' slot='???' function='0x0'/>
132
150
  -%>
@@ -252,11 +270,13 @@
252
270
  <% end %>
253
271
  <% end -%>
254
272
 
255
- <% if @tpm_path -%>
273
+ <% if @tpm_path || @tpm_version -%>
256
274
  <%# TPM Device -%>
257
275
  <tpm model='<%= @tpm_model %>'>
258
- <backend type='<%= @tpm_type %>'>
276
+ <backend type='<%= @tpm_type %>'<% if @tpm_version %> version='<%= @tpm_version %>'<% end %>>
277
+ <% if @tpm_path -%>
259
278
  <device path='<%= @tpm_path %>'/>
279
+ <% end -%>
260
280
  </backend>
261
281
  </tpm>
262
282
  <% end -%>
@@ -264,6 +284,15 @@
264
284
  <%# USB Controller -%>
265
285
  <controller type='usb' model='<%= @usbctl_dev[:model] %>' <%= "ports=\"#{@usbctl_dev[:ports]}\" " if @usbctl_dev[:ports] %>/>
266
286
  <% end %>
287
+ <% unless @memballoon_enabled.nil? %>
288
+ <% if @memballoon_enabled %>
289
+ <memballoon model='<%= @memballoon_model %>'>
290
+ <address type='pci' domain='0x0000' bus='<%= @memballoon_pci_bus %>' slot='<%= @memballoon_pci_slot %>' function='0x0'/>
291
+ </memballoon>
292
+ <% else %>
293
+ <memballoon model='none'/>
294
+ <% end %>
295
+ <% end %>
267
296
  </devices>
268
297
 
269
298
  <% if not @qemu_args.empty? or not @qemu_env.empty? %>
@@ -18,7 +18,11 @@
18
18
  <driver name='<%=@driver_name%>'/>
19
19
  <% end %>
20
20
  <% if @ovs %>
21
- <virtualport type='openvswitch'/>
21
+ <virtualport type='openvswitch'>
22
+ <% if @ovs_interfaceid %>
23
+ <parameters interfaceid='<%=@ovs_interfaceid%>'/>
24
+ <% end %>
25
+ </virtualport>
22
26
  <% end %>
23
27
  <% if @pci_bus and @pci_slot %>
24
28
  <address type='pci' bus='<%=@pci_bus%>' slot='<%=@pci_slot%>' />
@@ -7,6 +7,7 @@ module VagrantPlugins
7
7
  autoload :NetworkUtil, 'vagrant-libvirt/util/network_util'
8
8
  autoload :StorageUtil, 'vagrant-libvirt/util/storage_util'
9
9
  autoload :ErrorCodes, 'vagrant-libvirt/util/error_codes'
10
+ autoload :Ui, 'vagrant-libvirt/util/ui'
10
11
  end
11
12
  end
12
13
  end
@@ -1,20 +1,19 @@
1
- require 'erubis'
2
-
3
1
  module VagrantPlugins
4
2
  module ProviderLibvirt
5
3
  module Util
6
4
  module ErbTemplate
7
5
  # TODO: remove and use nokogiri builder
8
- # TODO: might be a chance to use vagrant template system according to https://github.com/mitchellh/vagrant/issues/3231
9
6
  def to_xml(template_name = nil, data = binding)
10
7
  erb = template_name || self.class.to_s.split('::').last.downcase
11
- path = File.join(File.dirname(__FILE__), '..', 'templates',
12
- "#{erb}.xml.erb")
13
- template = File.read(path)
8
+ path = File.join(File.dirname(__FILE__), '..', 'templates')
9
+ template = "#{erb}.xml"
14
10
 
15
11
  # TODO: according to erubis documentation, we should rather use evaluate and forget about
16
12
  # binding since the template may then change variables values
17
- Erubis::Eruby.new(template, trim: true).result(data)
13
+ Vagrant::Util::TemplateRenderer.render_with(:render, template, template_root: path) do |renderer|
14
+ iv = data.eval ("instance_variables.collect {|i| [i, instance_variable_get(i.to_sym)]}")
15
+ iv.each {|k, v| renderer.instance_variable_set(k, v)}
16
+ end
18
17
  end
19
18
  end
20
19
  end
@@ -0,0 +1,23 @@
1
+
2
+ module VagrantPlugins
3
+ module ProviderLibvirt
4
+ module Util
5
+ module Ui
6
+ # Since v2.2.8 Vagrant support --no-tty option, which silences
7
+ # progress bars and other interactive elements for cleaner logs
8
+ # in scripts, but requires a slight change in UI object handling.
9
+ # This helper allows the vagrant-libvirt plugin to stay compatible
10
+ # with the older Vagrant versions.
11
+ # See: https://github.com/hashicorp/vagrant/pull/11465/
12
+ def rewriting(ui)
13
+ if ui.respond_to?(:rewriting)
14
+ ui.rewriting {|rw| yield rw}
15
+ else
16
+ yield ui
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1 @@
1
+ 0.4.1
@@ -1,5 +1,76 @@
1
+ require 'open3'
2
+ require 'tmpdir'
3
+
1
4
  module VagrantPlugins
2
5
  module ProviderLibvirt
3
- VERSION = '0.1.0'.freeze
6
+ VERSION_FILE = File.dirname(__FILE__) + "/version"
7
+
8
+ GIT_ARCHIVE_VERSION = "$Format:%H %D$"
9
+
10
+ HOMEPAGE = 'https://github.com/vagrant-libvirt/vagrant-libvirt'
11
+
12
+ def self.get_version
13
+ if File.exist?(VERSION_FILE)
14
+ # built gem
15
+ version = File.read(VERSION_FILE)
16
+ elsif self.inside_git_repository
17
+ # local repo
18
+ git_version = `git describe --tags`
19
+ version = self.version_from_describe(git_version)
20
+ elsif !GIT_ARCHIVE_VERSION.start_with?('$Format')
21
+ # archive - format string replaced during export
22
+ hash, refs = GIT_ARCHIVE_VERSION.split(' ', 2)
23
+
24
+ tag = refs.split(',').select { |ref| ref.strip.start_with?("tag:") }.first
25
+ if tag != nil
26
+ # tagged
27
+ version = tag.strip.split(' ').last
28
+ else
29
+ version = ""
30
+ # arbitrary branch/commit
31
+ Dir.mktmpdir do |dir|
32
+ stdout_and_stderr, status = Open3.capture2e("git -C #{dir} clone --bare #{HOMEPAGE}")
33
+ raise "failed to clone original to resolve version: #{stdout_and_stderr}" unless status.success?
34
+
35
+ stdout_and_stderr, status = Open3.capture2e("git --git-dir=#{dir}/vagrant-libvirt.git describe --tags #{hash}")
36
+ raise "failed to determine version for #{hash}: #{stdout_and_stderr}" unless status.success?
37
+
38
+ version = version_from_describe(stdout_and_stderr)
39
+ end
40
+
41
+ # in this case write the version file to avoid cloning a second time
42
+ File.write(VERSION_FILE, version)
43
+ end
44
+ else
45
+ # no idea
46
+ version = "9999"
47
+ end
48
+
49
+ return version.freeze
50
+ end
51
+
52
+ def self.write_version
53
+ File.write(VERSION_FILE, self.get_version)
54
+ end
55
+
56
+ private
57
+
58
+ def self.inside_git_repository
59
+ _, status = Open3.capture2e("git rev-parse --git-dir")
60
+
61
+ status.success?
62
+ end
63
+
64
+ def self.version_from_describe(describe)
65
+ version_parts = describe.split('-').first(2) # drop the git sha if it exists
66
+ if version_parts.length > 1
67
+ # increment the patch number so that this is marked as a pre-release of the
68
+ # next possible release
69
+ main_version_parts = Gem::Version.new(version_parts[0]).segments
70
+ main_version_parts[-1] = main_version_parts.last + 1
71
+ version_parts = main_version_parts + ["pre", version_parts[1]]
72
+ end
73
+ version = version_parts.join(".")
74
+ end
4
75
  end
5
76
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,31 @@
1
- require 'coveralls'
2
- Coveralls.wear!
1
+ require 'simplecov'
2
+ require 'simplecov-lcov'
3
+
4
+ # patch simplecov configuration
5
+ if ! SimpleCov::Configuration.method_defined? :branch_coverage?
6
+ module SimpleCov
7
+ module Configuration
8
+ def branch_coverage?
9
+ return false
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ SimpleCov::Formatter::LcovFormatter.config do |config|
16
+ config.report_with_single_file = true
17
+ config.single_report_path = 'coverage/lcov.info'
18
+ end
19
+
20
+ SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new(
21
+ [
22
+ SimpleCov::Formatter::HTMLFormatter,
23
+ SimpleCov::Formatter::LcovFormatter,
24
+ ]
25
+ )
26
+ SimpleCov.start do
27
+ add_filter 'spec/'
28
+ end
3
29
 
4
30
  require 'vagrant-libvirt'
5
31
  require 'support/environment_helper'