vagrant-libvirt 0.4.1 → 0.5.0

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +212 -27
  3. data/lib/vagrant-libvirt/action.rb +6 -0
  4. data/lib/vagrant-libvirt/action/clean_machine_folder.rb +28 -0
  5. data/lib/vagrant-libvirt/action/create_domain.rb +26 -10
  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 +36 -37
  11. data/lib/vagrant-libvirt/action/halt_domain.rb +25 -9
  12. data/lib/vagrant-libvirt/action/handle_box_image.rb +162 -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/wait_till_up.rb +1 -25
  16. data/lib/vagrant-libvirt/cap/{mount_p9.rb → mount_9p.rb} +2 -2
  17. data/lib/vagrant-libvirt/cap/mount_virtiofs.rb +37 -0
  18. data/lib/vagrant-libvirt/cap/{synced_folder.rb → synced_folder_9p.rb} +4 -5
  19. data/lib/vagrant-libvirt/cap/synced_folder_virtiofs.rb +109 -0
  20. data/lib/vagrant-libvirt/config.rb +24 -2
  21. data/lib/vagrant-libvirt/errors.rb +24 -1
  22. data/lib/vagrant-libvirt/plugin.rb +13 -5
  23. data/lib/vagrant-libvirt/templates/domain.xml.erb +7 -6
  24. data/lib/vagrant-libvirt/templates/private_network.xml.erb +1 -1
  25. data/lib/vagrant-libvirt/util/network_util.rb +21 -3
  26. data/lib/vagrant-libvirt/version +1 -1
  27. data/locales/en.yml +12 -0
  28. data/spec/spec_helper.rb +9 -1
  29. data/spec/support/matchers/have_file_content.rb +63 -0
  30. data/spec/unit/action/clean_machine_folder_spec.rb +48 -0
  31. data/spec/unit/action/create_domain_spec.rb +6 -0
  32. data/spec/unit/action/create_domain_volume_spec.rb +102 -0
  33. data/spec/unit/action/create_domain_volume_spec/one_disk_in_storage.xml +21 -0
  34. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_0.xml +21 -0
  35. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_1.xml +21 -0
  36. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_2.xml +21 -0
  37. data/spec/unit/action/destroy_domain_spec.rb +1 -1
  38. data/spec/unit/action/forward_ports_spec.rb +202 -0
  39. data/spec/unit/action/halt_domain_spec.rb +90 -0
  40. data/spec/unit/action/handle_box_image_spec.rb +363 -0
  41. data/spec/unit/action/wait_till_up_spec.rb +1 -23
  42. data/spec/unit/templates/domain_all_settings.xml +8 -0
  43. data/spec/unit/templates/domain_spec.rb +20 -1
  44. metadata +41 -4
@@ -1,6 +1,6 @@
1
1
  <network ipv6='<%= @guest_ipv6 %>'>
2
2
  <name><%= @network_name %></name>
3
- <bridge name="<%= @network_bridge_name %>" />
3
+ <bridge name="<%= @network_bridge_name %>" stp="<%= @network_bridge_stp %>" delay="<%= @network_bridge_delay %>" />
4
4
 
5
5
  <% if @network_domain_name %>
6
6
  <domain name="<%= @network_domain_name %>" localOnly="yes" />
@@ -1,6 +1,15 @@
1
+ require 'ipaddr'
1
2
  require 'nokogiri'
2
3
  require 'vagrant/util/network_ip'
3
4
 
5
+ class IPAddr
6
+ def get_mask
7
+ if @addr
8
+ _to_string(@mask_addr)
9
+ end
10
+ end
11
+ end
12
+
4
13
  module VagrantPlugins
5
14
  module ProviderLibvirt
6
15
  module Util
@@ -19,6 +28,7 @@ module VagrantPlugins
19
28
  management_network_pci_bus = env[:machine].provider_config.management_network_pci_bus
20
29
  management_network_pci_slot = env[:machine].provider_config.management_network_pci_slot
21
30
  management_network_domain = env[:machine].provider_config.management_network_domain
31
+ management_network_mtu = env[:machine].provider_config.management_network_mtu
22
32
  logger.info "Using #{management_network_name} at #{management_network_address} as the management network #{management_network_mode} is the mode"
23
33
 
24
34
  begin
@@ -70,6 +80,10 @@ module VagrantPlugins
70
80
  management_network_options[:domain_name] = management_network_domain
71
81
  end
72
82
 
83
+ unless management_network_mtu.nil?
84
+ management_network_options[:mtu] = management_network_mtu
85
+ end
86
+
73
87
  unless management_network_pci_bus.nil? and management_network_pci_slot.nil?
74
88
  management_network_options[:bus] = management_network_pci_bus
75
89
  management_network_options[:slot] = management_network_pci_slot
@@ -97,14 +111,18 @@ module VagrantPlugins
97
111
  # store type in options
98
112
  # use default values if not already set
99
113
  options = {
100
- iface_type: type,
101
- netmask: '255.255.255.0',
114
+ iface_type: type,
115
+ netmask: options[:network_address] ?
116
+ IPAddr.new(options[:network_address]).get_mask :
117
+ '255.255.255.0',
102
118
  dhcp_enabled: true,
103
119
  forward_mode: 'nat'
104
120
  }.merge(options)
105
121
 
106
122
  if options[:type].to_s == 'dhcp' && options[:ip].nil?
107
- options[:network_name] = 'vagrant-private-dhcp'
123
+ options[:network_name] = options[:network_name] ?
124
+ options[:network_name] :
125
+ 'vagrant-private-dhcp'
108
126
  end
109
127
 
110
128
  # add to list of networks to check
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.5.0
data/locales/en.yml CHANGED
@@ -72,6 +72,14 @@ en:
72
72
  no_storage_pool: |-
73
73
  No usable storage pool found! Please check if storage pool is
74
74
  created and available.
75
+ box_format_duplicate_volume: |-
76
+ Encountered a duplicate volume name '%{volume}' generated for disk '%{new_disk}', due to already allocated for disk '%{orig_disk}'.
77
+ box_format_missing_attribute: |-
78
+ Invalid box metadata, missing expected attribute: '%{attribute}'
79
+ bad_box_image: |-
80
+ Received error when query the box image details from '%{image}'.
81
+ Stdout: %{out}
82
+ Stderr: %{err}
75
83
  no_box_volume: |-
76
84
  Volume for box image is missing in storage pools. Try to run vagrant
77
85
  again, or check if storage volume is accessible.
@@ -92,10 +100,14 @@ en:
92
100
  Error: %{stderr}
93
101
  no_box_virtual_size: |-
94
102
  No image virtual size specified for box.
103
+ no_disk_virtual_size: |-
104
+ No image virtual size specified for disk with index %{disk_index}.
95
105
  no_box_format: |-
96
106
  No image format specified for box.
97
107
  wrong_box_format: |-
98
108
  Wrong image format specified for box.
109
+ wrong_disk_format: |-
110
+ Wrong image format specified for disk with index %{disk_index}.
99
111
  fog_libvirt_connection_error: |-
100
112
  Error while connecting to Libvirt: %{error_message}
101
113
  fog_create_volume_error: |-
data/spec/spec_helper.rb CHANGED
@@ -31,5 +31,13 @@ require 'vagrant-libvirt'
31
31
  require 'support/environment_helper'
32
32
  require 'vagrant-spec/unit'
33
33
 
34
- RSpec.configure do |spec|
34
+ Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each { |f| require f }
35
+
36
+ RSpec.configure do |config|
37
+ # ensure that setting of LIBVIRT_DEFAULT_URI in the environment is not picked
38
+ # up directly by tests, instead they must set as needed. Some build envs will
39
+ # may have it set to 'qemu:///session'.
40
+ config.before(:suite) do
41
+ ENV.delete('LIBVIRT_DEFAULT_URI')
42
+ end
35
43
  end
@@ -0,0 +1,63 @@
1
+ require "rspec/expectations/version"
2
+ #
3
+ # Taken from https://github.com/cucumber/aruba/blob/main/lib/aruba/matchers/file/have_file_content.rb
4
+ # with minor modifications
5
+ #
6
+ # @!method have_file_content(content)
7
+ # This matchers checks if <file> has content. `content` can be a string,
8
+ # regexp or an RSpec matcher.
9
+ #
10
+ # @param [String, Regexp, Matcher] content
11
+ # Specifies the content of the file
12
+ #
13
+ # @return [Boolean] The result
14
+ #
15
+ # false:
16
+ # * if file does not exist
17
+ # * if file content is not equal string
18
+ # * if file content does not include regexp
19
+ # * if file content does not match the content specification
20
+ #
21
+ # true:
22
+ # * if file content includes regexp
23
+ # * if file content is equal string
24
+ # * if file content matches the content specification
25
+ #
26
+ # @example Use matcher with string
27
+ #
28
+ # RSpec.describe do
29
+ # it { expect(file1).to have_file_content('a') }
30
+ # end
31
+ #
32
+ # @example Use matcher with regexp
33
+ #
34
+ # RSpec.describe do
35
+ # it { expect(file1).to have_file_content(/a/) }
36
+ # end
37
+ #
38
+ # @example Use matcher with an RSpec matcher
39
+ #
40
+ # RSpec.describe do
41
+ # it { expect(file1).to have_file_content(a_string_starting_with 'a') }
42
+ # it { expect(files1).to include a_file_having_content(a_string_starting_with 'a') }
43
+ # end
44
+ RSpec::Matchers.define :have_file_content do |expected|
45
+ match do |actual|
46
+ next false unless File.exists?(actual)
47
+
48
+ @actual = File.read(actual).chomp
49
+ @expected = if expected.is_a? String
50
+ expected.chomp
51
+ else
52
+ expected
53
+ end
54
+
55
+ values_match?(@expected, @actual)
56
+ end
57
+
58
+ diffable if expected.is_a? String
59
+
60
+ description { "have file content: #{description_of expected}" }
61
+ end
62
+
63
+ RSpec::Matchers.alias_matcher :a_file_having_content, :have_file_content
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+ require 'support/sharedcontext'
3
+
4
+ require 'vagrant-libvirt/action/clean_machine_folder'
5
+
6
+ describe VagrantPlugins::ProviderLibvirt::Action::CleanMachineFolder do
7
+ subject { described_class.new(app, env) }
8
+
9
+ include_context 'unit'
10
+
11
+ describe '#call' do
12
+ context 'with default options' do
13
+ it 'should verbosely remove the folder' do
14
+ expect(ui).to receive(:info).with('Deleting the machine folder')
15
+ expect(FileUtils).to receive(:rm_rf).with(machine.data_dir, {:secure => true})
16
+
17
+ expect(subject.call(env)).to be_nil
18
+ end
19
+ end
20
+
21
+ context 'when the data dir doesn\'t exist' do
22
+ before do
23
+ Dir.mktmpdir do |d|
24
+ # returns a temporary directory that has been already deleted when running
25
+ expect(machine).to receive(:data_dir).and_return(d.to_s).exactly(2).times
26
+ end
27
+ end
28
+
29
+ it 'should remove the folder' do
30
+ expect(ui).to receive(:info).with('Deleting the machine folder')
31
+ expect(FileUtils).to receive(:rm_rf).with(machine.data_dir, {:secure => true})
32
+
33
+ expect(subject.call(env)).to be_nil
34
+ end
35
+ end
36
+
37
+ context 'with quiet option enabled' do
38
+ subject { described_class.new(app, env, {:quiet => true}) }
39
+
40
+ it 'should quietly remove the folder' do
41
+ expect(ui).to_not receive(:info).with('Deleting the machine folder')
42
+ expect(FileUtils).to receive(:rm_rf).with(machine.data_dir, {:secure => true})
43
+
44
+ expect(subject.call(env)).to be_nil
45
+ end
46
+ end
47
+ end
48
+ end
@@ -31,6 +31,12 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
31
31
 
32
32
  env[:domain_name] = "vagrant-test_default"
33
33
 
34
+ env[:box_volumes] = []
35
+ env[:box_volumes].push({
36
+ :path=>"/test/box.img",
37
+ :name=>"test_vagrant_box_image_1.1.1_0.img",
38
+ :virtual_size=>5
39
+ })
34
40
  # should be ignored for system session and used for user session
35
41
  allow(Process).to receive(:uid).and_return(9999)
36
42
  allow(Process).to receive(:gid).and_return(9999)
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+ require 'support/sharedcontext'
3
+ require 'support/libvirt_context'
4
+
5
+ require 'vagrant-libvirt/action/destroy_domain'
6
+
7
+ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomainVolume do
8
+ subject { described_class.new(app, env) }
9
+
10
+ include_context 'unit'
11
+ include_context 'libvirt'
12
+
13
+ let(:libvirt_domain) { double('libvirt_domain') }
14
+ let(:libvirt_client) { double('libvirt_client') }
15
+ let(:volumes) { double('volumes') }
16
+ let(:all) { double('all') }
17
+ let(:box_volume) { double('box_volume') }
18
+
19
+ def read_test_file(name)
20
+ File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), name))
21
+ end
22
+
23
+ describe '#call' do
24
+ before do
25
+ allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
26
+ .to receive(:connection).and_return(connection)
27
+ allow(connection).to receive(:client).and_return(libvirt_client)
28
+ allow(connection).to receive(:volumes).and_return(volumes)
29
+ allow(volumes).to receive(:all).and_return(all)
30
+ allow(all).to receive(:first).and_return(box_volume)
31
+ allow(box_volume).to receive(:id).and_return(nil)
32
+ env[:domain_name] = 'test'
33
+ end
34
+
35
+ context 'when one disk' do
36
+ before do
37
+ allow(box_volume).to receive(:path).and_return('/test/path_0.img')
38
+ env[:box_volumes] = [
39
+ {
40
+ :name=>"test_vagrant_box_image_1.1.1_0.img",
41
+ :virtual_size=>5
42
+ }
43
+ ]
44
+ end
45
+
46
+ it 'should create one disk in storage' do
47
+ expected_xml = read_test_file('one_disk_in_storage.xml')
48
+ expect(ui).to receive(:info).with('Creating image (snapshot of base box volume).')
49
+ expect(logger).to receive(:debug).with('Using pool default for base box snapshot')
50
+ expect(volumes).to receive(:create).with(
51
+ :xml => expected_xml,
52
+ :pool_name => "default"
53
+ )
54
+ expect(subject.call(env)).to be_nil
55
+ end
56
+ end
57
+
58
+ context 'when three disks' do
59
+ before do
60
+ allow(box_volume).to receive(:path).and_return(
61
+ '/test/path_0.img',
62
+ '/test/path_1.img',
63
+ '/test/path_2.img',
64
+ )
65
+ env[:box_volumes] = [
66
+ {
67
+ :name=>"test_vagrant_box_image_1.1.1_0.img",
68
+ :virtual_size=>5
69
+ },
70
+ {
71
+ :name=>"test_vagrant_box_image_1.1.1_1.img",
72
+ :virtual_size=>10
73
+ },
74
+ {
75
+ :name=>"test_vagrant_box_image_1.1.1_2.img",
76
+ :virtual_size=>20
77
+ }
78
+ ]
79
+ end
80
+
81
+ it 'should create three disks in storage' do
82
+ expect(ui).to receive(:info).with('Creating image (snapshot of base box volume).')
83
+ expect(logger).to receive(:debug).with('Using pool default for base box snapshot')
84
+ expect(volumes).to receive(:create).with(
85
+ :xml => read_test_file('three_disks_in_storage_disk_0.xml'),
86
+ :pool_name => "default"
87
+ )
88
+ expect(logger).to receive(:debug).with('Using pool default for base box snapshot')
89
+ expect(volumes).to receive(:create).with(
90
+ :xml => read_test_file('three_disks_in_storage_disk_1.xml'),
91
+ :pool_name => "default"
92
+ )
93
+ expect(logger).to receive(:debug).with('Using pool default for base box snapshot')
94
+ expect(volumes).to receive(:create).with(
95
+ :xml => read_test_file('three_disks_in_storage_disk_2.xml'),
96
+ :pool_name => "default"
97
+ )
98
+ expect(subject.call(env)).to be_nil
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,21 @@
1
+ <volume>
2
+ <name>test.img</name>
3
+ <capacity unit="G">5</capacity>
4
+ <target>
5
+ <format type="qcow2"></format>
6
+ <permissions>
7
+ <owner>0</owner>
8
+ <group>0</group>
9
+ <label>virt_image_t</label>
10
+ </permissions>
11
+ </target>
12
+ <backingStore>
13
+ <path>/test/path_0.img</path>
14
+ <format type="qcow2"></format>
15
+ <permissions>
16
+ <owner>0</owner>
17
+ <group>0</group>
18
+ <label>virt_image_t</label>
19
+ </permissions>
20
+ </backingStore>
21
+ </volume>
@@ -0,0 +1,21 @@
1
+ <volume>
2
+ <name>test.img</name>
3
+ <capacity unit="G">5</capacity>
4
+ <target>
5
+ <format type="qcow2"></format>
6
+ <permissions>
7
+ <owner>0</owner>
8
+ <group>0</group>
9
+ <label>virt_image_t</label>
10
+ </permissions>
11
+ </target>
12
+ <backingStore>
13
+ <path>/test/path_0.img</path>
14
+ <format type="qcow2"></format>
15
+ <permissions>
16
+ <owner>0</owner>
17
+ <group>0</group>
18
+ <label>virt_image_t</label>
19
+ </permissions>
20
+ </backingStore>
21
+ </volume>
@@ -0,0 +1,21 @@
1
+ <volume>
2
+ <name>test_1.img</name>
3
+ <capacity unit="G">10</capacity>
4
+ <target>
5
+ <format type="qcow2"></format>
6
+ <permissions>
7
+ <owner>0</owner>
8
+ <group>0</group>
9
+ <label>virt_image_t</label>
10
+ </permissions>
11
+ </target>
12
+ <backingStore>
13
+ <path>/test/path_1.img</path>
14
+ <format type="qcow2"></format>
15
+ <permissions>
16
+ <owner>0</owner>
17
+ <group>0</group>
18
+ <label>virt_image_t</label>
19
+ </permissions>
20
+ </backingStore>
21
+ </volume>
@@ -0,0 +1,21 @@
1
+ <volume>
2
+ <name>test_2.img</name>
3
+ <capacity unit="G">20</capacity>
4
+ <target>
5
+ <format type="qcow2"></format>
6
+ <permissions>
7
+ <owner>0</owner>
8
+ <group>0</group>
9
+ <label>virt_image_t</label>
10
+ </permissions>
11
+ </target>
12
+ <backingStore>
13
+ <path>/test/path_2.img</path>
14
+ <format type="qcow2"></format>
15
+ <permissions>
16
+ <owner>0</owner>
17
+ <group>0</group>
18
+ <label>virt_image_t</label>
19
+ </permissions>
20
+ </backingStore>
21
+ </volume>
@@ -85,7 +85,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::DestroyDomain do
85
85
 
86
86
  it 'uses explicit removal of disks' do
87
87
  allow(libvirt_domain).to receive(:name).and_return('test')
88
- allow(domain).to receive(:volumes).and_return([root_disk])
88
+ allow(domain).to receive(:volumes).and_return([root_disk, nil])
89
89
 
90
90
  expect(domain).to_not receive(:destroy).with(destroy_volumes: true)
91
91
  expect(root_disk).to receive(:destroy) # root disk remove