vagrant-libvirt 0.4.0 → 0.5.3

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +251 -33
  3. data/lib/vagrant-libvirt/action.rb +7 -1
  4. data/lib/vagrant-libvirt/action/clean_machine_folder.rb +30 -0
  5. data/lib/vagrant-libvirt/action/create_domain.rb +28 -11
  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 +170 -77
  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/set_boot_order.rb +6 -2
  16. data/lib/vagrant-libvirt/action/wait_till_up.rb +1 -25
  17. data/lib/vagrant-libvirt/cap/{mount_p9.rb → mount_9p.rb} +2 -2
  18. data/lib/vagrant-libvirt/cap/mount_virtiofs.rb +37 -0
  19. data/lib/vagrant-libvirt/cap/{synced_folder.rb → synced_folder_9p.rb} +4 -5
  20. data/lib/vagrant-libvirt/cap/synced_folder_virtiofs.rb +109 -0
  21. data/lib/vagrant-libvirt/config.rb +34 -2
  22. data/lib/vagrant-libvirt/driver.rb +3 -1
  23. data/lib/vagrant-libvirt/errors.rb +24 -1
  24. data/lib/vagrant-libvirt/plugin.rb +14 -5
  25. data/lib/vagrant-libvirt/templates/domain.xml.erb +7 -6
  26. data/lib/vagrant-libvirt/templates/private_network.xml.erb +1 -1
  27. data/lib/vagrant-libvirt/util/byte_number.rb +71 -0
  28. data/lib/vagrant-libvirt/util/network_util.rb +21 -3
  29. data/lib/vagrant-libvirt/version +1 -1
  30. data/locales/en.yml +12 -0
  31. data/spec/spec_helper.rb +9 -1
  32. data/spec/support/binding_proc.rb +24 -0
  33. data/spec/support/matchers/have_file_content.rb +63 -0
  34. data/spec/unit/action/clean_machine_folder_spec.rb +58 -0
  35. data/spec/unit/action/create_domain_spec.rb +15 -5
  36. data/spec/unit/action/create_domain_spec/additional_disks_domain.xml +54 -0
  37. data/spec/unit/action/create_domain_spec/default_domain.xml +49 -0
  38. data/spec/unit/action/create_domain_volume_spec.rb +104 -0
  39. data/spec/unit/action/create_domain_volume_spec/one_disk_in_storage.xml +21 -0
  40. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_0.xml +21 -0
  41. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_1.xml +21 -0
  42. data/spec/unit/action/create_domain_volume_spec/three_disks_in_storage_disk_2.xml +21 -0
  43. data/spec/unit/action/destroy_domain_spec.rb +1 -1
  44. data/spec/unit/action/forward_ports_spec.rb +202 -0
  45. data/spec/unit/action/halt_domain_spec.rb +90 -0
  46. data/spec/unit/action/handle_box_image_spec.rb +441 -0
  47. data/spec/unit/action/wait_till_up_spec.rb +11 -15
  48. data/spec/unit/config_spec.rb +12 -9
  49. data/spec/unit/templates/domain_all_settings.xml +8 -0
  50. data/spec/unit/templates/domain_spec.rb +20 -1
  51. data/spec/unit/util/byte_number_spec.rb +26 -0
  52. metadata +52 -18
@@ -0,0 +1,71 @@
1
+ class ByteNumber < Numeric
2
+ def initialize(int)
3
+ @int = int
4
+ end
5
+
6
+ def to_s
7
+ @int.to_s
8
+ end
9
+
10
+ def to_i
11
+ @int
12
+ end
13
+
14
+ def to_f
15
+ @int.to_f
16
+ end
17
+
18
+ def to_B
19
+ to_i
20
+ end
21
+
22
+ def to_KB
23
+ _compute_unit_to_n_kilo(1)
24
+ end
25
+
26
+ def to_MB
27
+ _compute_unit_to_n_kilo(2)
28
+ end
29
+
30
+ def to_GB
31
+ _compute_unit_to_n_kilo(3)
32
+ end
33
+
34
+ def coerce(other)
35
+ to_i.coerce(other)
36
+ end
37
+
38
+ def <=>(other)
39
+ to_i <=> other
40
+ end
41
+
42
+ def +(other)
43
+ to_i + other
44
+ end
45
+
46
+ def -(other)
47
+ to_i - other
48
+ end
49
+
50
+ def *(other)
51
+ to_i * other
52
+ end
53
+
54
+ def /(other)
55
+ to_i / other
56
+ end
57
+
58
+ def pow(n)
59
+ self.class.new(to_i ** n)
60
+ end
61
+
62
+ def self.from_GB(value)
63
+ self.new(value*(1024**3))
64
+ end
65
+
66
+ private
67
+ def _compute_unit_to_n_kilo(n=0)
68
+ (to_f/(1024 ** n)).ceil
69
+ end
70
+ end
71
+
@@ -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.0
1
+ 0.5.3
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,24 @@
1
+ ##
2
+ # A simple extension of the Proc class that supports setting a custom binding
3
+ # and evaluates everything in the Proc using the new binding.
4
+
5
+ class ProcWithBinding < Proc
6
+ ##
7
+ # Set the binding for this instance
8
+
9
+ def apply_binding(bind, *args)
10
+ @binding = bind
11
+ instance_exec(*args, &self)
12
+ end
13
+
14
+ def method_missing(method, *args)
15
+ begin
16
+ method_from_binding = eval("method(#{method.inspect})", @binding)
17
+ return method_from_binding.call(*args)
18
+ rescue NameError
19
+ # fall through on purpose
20
+ end
21
+
22
+ super
23
+ end
24
+ 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,58 @@
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
+ before do
13
+ FileUtils.touch(File.join(machine.data_dir, "box.meta"))
14
+ end
15
+
16
+ context 'with default options' do
17
+ it 'should verbosely remove the folder' do
18
+ expect(ui).to receive(:info).with('Deleting the machine folder')
19
+
20
+ expect(subject.call(env)).to be_nil
21
+
22
+ expect(File.exists?(machine.data_dir)).to eq(true)
23
+ expect(Dir.entries(machine.data_dir)).to match_array([".", ".."])
24
+ end
25
+ end
26
+
27
+ context 'when the data dir doesn\'t exist' do
28
+ before do
29
+ Dir.mktmpdir do |d|
30
+ # returns a temporary directory that has been already deleted when running
31
+ expect(machine).to receive(:data_dir).and_return(d.to_s).exactly(3).times
32
+ end
33
+ end
34
+
35
+ it 'should remove the folder' do
36
+ expect(ui).to receive(:info).with('Deleting the machine folder')
37
+
38
+ expect(subject.call(env)).to be_nil
39
+
40
+ expect(File.exists?(machine.data_dir)).to eq(true)
41
+ expect(Dir.entries(machine.data_dir)).to match_array([".", ".."])
42
+ end
43
+ end
44
+
45
+ context 'with quiet option enabled' do
46
+ subject { described_class.new(app, env, {:quiet => true}) }
47
+
48
+ it 'should quietly remove the folder' do
49
+ expect(ui).to_not receive(:info).with('Deleting the machine folder')
50
+
51
+ expect(subject.call(env)).to be_nil
52
+
53
+ expect(File.exists?(machine.data_dir)).to eq(true)
54
+ expect(Dir.entries(machine.data_dir)).to match_array([".", ".."])
55
+ end
56
+ end
57
+ end
58
+ end
@@ -15,7 +15,8 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
15
15
  let(:servers) { double('servers') }
16
16
  let(:volumes) { double('volumes') }
17
17
 
18
- let(:storage_pool_xml) { File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), test_file)) }
18
+ let(:domain_xml) { File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), domain_xml_file)) }
19
+ let(:storage_pool_xml) { File.read(File.join(File.dirname(__FILE__), File.basename(__FILE__, '.rb'), storage_pool_xml_file)) }
19
20
  let(:libvirt_storage_pool) { double('storage_pool') }
20
21
 
21
22
  describe '#call' do
@@ -31,6 +32,12 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
31
32
 
32
33
  env[:domain_name] = "vagrant-test_default"
33
34
 
35
+ env[:box_volumes] = []
36
+ env[:box_volumes].push({
37
+ :path=>"/test/box.img",
38
+ :name=>"test_vagrant_box_image_1.1.1_0.img",
39
+ :virtual_size=>5
40
+ })
34
41
  # should be ignored for system session and used for user session
35
42
  allow(Process).to receive(:uid).and_return(9999)
36
43
  allow(Process).to receive(:gid).and_return(9999)
@@ -38,12 +45,13 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
38
45
 
39
46
  context 'connection => qemu:///system' do
40
47
  context 'default pool' do
41
- let(:test_file) { 'default_system_storage_pool.xml' }
48
+ let(:domain_xml_file) { 'default_domain.xml' }
49
+ let(:storage_pool_xml_file) { 'default_system_storage_pool.xml' }
42
50
 
43
51
  it 'should execute correctly' do
44
52
  expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
45
53
  expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
46
- expect(servers).to receive(:create).and_return(machine)
54
+ expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
47
55
  expect(volumes).to_not receive(:create) # additional disks only
48
56
 
49
57
  expect(subject.call(env)).to be_nil
@@ -72,6 +80,8 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
72
80
  end
73
81
 
74
82
  context 'volume create succeeded' do
83
+ let(:domain_xml_file) { 'additional_disks_domain.xml' }
84
+
75
85
  it 'should complete' do
76
86
  expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
77
87
  expect(libvirt_storage_pool).to receive(:xml_desc).and_return(storage_pool_xml)
@@ -83,7 +93,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
83
93
  :pool_name => "default",
84
94
  )
85
95
  )
86
- expect(servers).to receive(:create).and_return(machine)
96
+ expect(servers).to receive(:create).with(xml: domain_xml).and_return(machine)
87
97
 
88
98
  expect(subject.call(env)).to be_nil
89
99
  end
@@ -113,7 +123,7 @@ describe VagrantPlugins::ProviderLibvirt::Action::CreateDomain do
113
123
  end
114
124
 
115
125
  context 'default pool' do
116
- let(:test_file) { 'default_user_storage_pool.xml' }
126
+ let(:storage_pool_xml_file) { 'default_user_storage_pool.xml' }
117
127
 
118
128
  it 'should execute correctly' do
119
129
  expect(libvirt_client).to receive(:lookup_storage_pool_by_name).and_return(libvirt_storage_pool)
@@ -0,0 +1,54 @@
1
+ <domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
2
+ <name>vagrant-test_default</name>
3
+ <title></title>
4
+ <description>Source: /rootpath/Vagrantfile</description>
5
+ <uuid></uuid>
6
+ <memory>524288</memory>
7
+ <vcpu>1</vcpu>
8
+
9
+
10
+ <cpu mode='host-model'>
11
+ <model fallback='allow'></model>
12
+ </cpu>
13
+
14
+
15
+ <os>
16
+ <type>hvm</type>
17
+ <kernel></kernel>
18
+ <initrd></initrd>
19
+ <cmdline></cmdline>
20
+ </os>
21
+ <features>
22
+ <acpi/>
23
+ <apic/>
24
+ <pae/>
25
+ </features>
26
+ <clock offset='utc'>
27
+ </clock>
28
+ <devices>
29
+ <disk type='file' device='disk'>
30
+ <driver name='qemu' type='qcow2' cache='default'/>
31
+ <source file='/var/lib/libvirt/images/vagrant-test_default-vdb.qcow2'/>
32
+ <target dev='vdb' bus='virtio'/>
33
+ </disk>
34
+
35
+
36
+ <serial type='pty'>
37
+ <target port='0'/>
38
+ </serial>
39
+ <console type='pty'>
40
+ <target port='0'/>
41
+ </console>
42
+
43
+
44
+ <input type='mouse' bus='ps2'/>
45
+
46
+ <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' keymap='en-us' />
47
+ <video>
48
+ <model type='cirrus' vram='9216' heads='1'/>
49
+ </video>
50
+
51
+
52
+ </devices>
53
+
54
+ </domain>