vagrant-libvirt 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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