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.
- checksums.yaml +4 -4
- data/README.md +212 -27
- data/lib/vagrant-libvirt/action.rb +6 -0
- data/lib/vagrant-libvirt/action/clean_machine_folder.rb +28 -0
- data/lib/vagrant-libvirt/action/create_domain.rb +26 -10
- data/lib/vagrant-libvirt/action/create_domain_volume.rb +57 -55
- data/lib/vagrant-libvirt/action/create_network_interfaces.rb +0 -3
- data/lib/vagrant-libvirt/action/create_networks.rb +11 -4
- data/lib/vagrant-libvirt/action/destroy_domain.rb +1 -1
- data/lib/vagrant-libvirt/action/forward_ports.rb +36 -37
- data/lib/vagrant-libvirt/action/halt_domain.rb +25 -9
- data/lib/vagrant-libvirt/action/handle_box_image.rb +162 -74
- data/lib/vagrant-libvirt/action/is_running.rb +1 -3
- data/lib/vagrant-libvirt/action/is_suspended.rb +4 -4
- data/lib/vagrant-libvirt/action/wait_till_up.rb +1 -25
- data/lib/vagrant-libvirt/cap/{mount_p9.rb → mount_9p.rb} +2 -2
- data/lib/vagrant-libvirt/cap/mount_virtiofs.rb +37 -0
- data/lib/vagrant-libvirt/cap/{synced_folder.rb → synced_folder_9p.rb} +4 -5
- data/lib/vagrant-libvirt/cap/synced_folder_virtiofs.rb +109 -0
- data/lib/vagrant-libvirt/config.rb +24 -2
- data/lib/vagrant-libvirt/errors.rb +24 -1
- data/lib/vagrant-libvirt/plugin.rb +13 -5
- data/lib/vagrant-libvirt/templates/domain.xml.erb +7 -6
- data/lib/vagrant-libvirt/templates/private_network.xml.erb +1 -1
- data/lib/vagrant-libvirt/util/network_util.rb +21 -3
- data/lib/vagrant-libvirt/version +1 -1
- data/locales/en.yml +12 -0
- data/spec/spec_helper.rb +9 -1
- data/spec/support/matchers/have_file_content.rb +63 -0
- data/spec/unit/action/clean_machine_folder_spec.rb +48 -0
- data/spec/unit/action/create_domain_spec.rb +6 -0
- data/spec/unit/action/create_domain_volume_spec.rb +102 -0
- data/spec/unit/action/create_domain_volume_spec/one_disk_in_storage.xml +21 -0
- data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_0.xml +21 -0
- data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_1.xml +21 -0
- data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_2.xml +21 -0
- data/spec/unit/action/destroy_domain_spec.rb +1 -1
- data/spec/unit/action/forward_ports_spec.rb +202 -0
- data/spec/unit/action/halt_domain_spec.rb +90 -0
- data/spec/unit/action/handle_box_image_spec.rb +363 -0
- data/spec/unit/action/wait_till_up_spec.rb +1 -23
- data/spec/unit/templates/domain_all_settings.xml +8 -0
- data/spec/unit/templates/domain_spec.rb +20 -1
- 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:
|
101
|
-
netmask:
|
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] =
|
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
|
data/lib/vagrant-libvirt/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
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
|
-
|
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
|