vagrant-libvirt 0.9.0 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +51 -2079
  3. data/lib/vagrant-libvirt/action/create_domain.rb +39 -4
  4. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +1 -1
  5. data/lib/vagrant-libvirt/action/create_networks.rb +3 -3
  6. data/lib/vagrant-libvirt/action/destroy_domain.rb +1 -1
  7. data/lib/vagrant-libvirt/action/destroy_networks.rb +1 -1
  8. data/lib/vagrant-libvirt/action/handle_box_image.rb +1 -1
  9. data/lib/vagrant-libvirt/action/package_domain.rb +1 -5
  10. data/lib/vagrant-libvirt/action/remove_libvirt_image.rb +3 -1
  11. data/lib/vagrant-libvirt/action/resolve_disk_settings.rb +15 -8
  12. data/lib/vagrant-libvirt/action/snapshot_delete.rb +26 -0
  13. data/lib/vagrant-libvirt/action/snapshot_restore.rb +22 -0
  14. data/lib/vagrant-libvirt/action/snapshot_save.rb +27 -0
  15. data/lib/vagrant-libvirt/action/start_domain.rb +43 -14
  16. data/lib/vagrant-libvirt/action.rb +49 -1
  17. data/lib/vagrant-libvirt/cap/snapshots.rb +12 -0
  18. data/lib/vagrant-libvirt/cap/synced_folder_9p.rb +4 -4
  19. data/lib/vagrant-libvirt/cap/synced_folder_virtiofs.rb +4 -4
  20. data/lib/vagrant-libvirt/config.rb +104 -6
  21. data/lib/vagrant-libvirt/driver.rb +116 -46
  22. data/lib/vagrant-libvirt/errors.rb +23 -3
  23. data/lib/vagrant-libvirt/plugin.rb +7 -3
  24. data/lib/vagrant-libvirt/provider.rb +1 -1
  25. data/lib/vagrant-libvirt/templates/domain.xml.erb +30 -4
  26. data/lib/vagrant-libvirt/util/byte_number.rb +0 -1
  27. data/lib/vagrant-libvirt/util/compat.rb +23 -0
  28. data/lib/vagrant-libvirt/util/unindent.rb +7 -0
  29. data/lib/vagrant-libvirt/version +1 -1
  30. data/locales/en.yml +24 -2
  31. data/spec/acceptance/additional_storage_spec.rb +32 -0
  32. data/spec/acceptance/package_domain_spec.rb +90 -0
  33. data/spec/acceptance/provider_settings_spec.rb +54 -0
  34. data/spec/acceptance/simple_vm_provision_via_shell_spec.rb +31 -0
  35. data/spec/acceptance/snapshots_spec.rb +41 -0
  36. data/spec/acceptance/support-skeletons/package_complex/Vagrantfile.testbox +14 -0
  37. data/spec/acceptance/support-skeletons/package_complex/scripts/sysprep.sh +32 -0
  38. data/spec/acceptance/support-skeletons/package_simple/Vagrantfile.testbox +10 -0
  39. data/spec/acceptance/two_disks_spec.rb +29 -0
  40. data/spec/acceptance/use_qemu_agent_for_connectivity_spec.rb +35 -0
  41. data/spec/spec_helper.rb +3 -0
  42. data/spec/support/acceptance/configuration.rb +21 -0
  43. data/spec/support/acceptance/context.rb +70 -0
  44. data/spec/support/acceptance/isolated_environment.rb +41 -0
  45. data/spec/support/libvirt_acceptance_context.rb +64 -0
  46. data/spec/support/sharedcontext.rb +1 -0
  47. data/spec/unit/action/create_domain_spec/sysinfo.xml +66 -0
  48. data/spec/unit/action/create_domain_spec/sysinfo_only_required.xml +49 -0
  49. data/spec/unit/action/create_domain_spec.rb +82 -0
  50. data/spec/unit/action/forward_ports_spec.rb +0 -1
  51. data/spec/unit/action/handle_box_image_spec.rb +18 -1
  52. data/spec/unit/action/remove_libvirt_image_spec.rb +43 -0
  53. data/spec/unit/action/resolve_disk_settings_spec.rb +24 -0
  54. data/spec/unit/action/start_domain_spec/clock_timer_removed.xml +38 -0
  55. data/spec/unit/action/start_domain_spec/clock_timer_rtc_tsc.xml +39 -0
  56. data/spec/unit/action/start_domain_spec/nvram_domain_other_setting.xml +2 -2
  57. data/spec/unit/action/start_domain_spec.rb +72 -30
  58. data/spec/unit/action_spec.rb +88 -0
  59. data/spec/unit/cap/synced_folder_9p_spec.rb +120 -0
  60. data/spec/unit/cap/synced_folder_virtiofs_spec.rb +120 -0
  61. data/spec/unit/config_spec.rb +143 -6
  62. data/spec/unit/driver_spec.rb +1 -1
  63. data/spec/unit/plugin_spec.rb +42 -0
  64. data/spec/unit/templates/domain_all_settings.xml +13 -4
  65. data/spec/unit/templates/domain_scsi_bus_storage.xml +44 -0
  66. data/spec/unit/templates/domain_scsi_device_storage.xml +44 -0
  67. data/spec/unit/templates/domain_scsi_multiple_controllers_storage.xml +130 -0
  68. data/spec/unit/templates/domain_spec.rb +105 -21
  69. data/spec/unit/util/byte_number_spec.rb +1 -1
  70. metadata +148 -80
  71. data/spec/unit/provider_spec.rb +0 -11
data/locales/en.yml CHANGED
@@ -16,7 +16,7 @@ en:
16
16
  Created volume larger than box defaults, will require manual resizing of
17
17
  filesystems to utilize.
18
18
  box_version_missing: |-
19
- No verison detected for %{name}, using timestamp to watch for modifications. Consider
19
+ No version detected for %{name}, using timestamp to watch for modifications. Consider
20
20
  generating a local metadata for the box with a version to allow better handling.
21
21
  See https://www.vagrantup.com/docs/boxes/format#box-metadata for further details.
22
22
  uploading_volume: |-
@@ -25,6 +25,8 @@ en:
25
25
  Creating image (snapshot of base box volume).
26
26
  removing_domain_volume: |-
27
27
  Removing image (snapshot of base box volume).
28
+ updating_domain: |-
29
+ Updating domain definition due to configuration change
28
30
  starting_domain: |-
29
31
  Starting domain.
30
32
  terminating: |-
@@ -138,7 +140,7 @@ en:
138
140
  Error while creating a storage pool volume: %{error_message}
139
141
  fog_create_domain_volume_error: |-
140
142
  Error while creating volume for domain: %{error_message}
141
- fog_create_server_error: |-
143
+ create_server_error: |-
142
144
  Error while creating domain: %{error_message}
143
145
  domain_name_exists: |-
144
146
  Name `%{domain_name}` of domain about to create is already taken. Please try to run
@@ -183,6 +185,16 @@ en:
183
185
  management_network_required: |-
184
186
  Management network can't be disabled when VM use box.
185
187
  Please fix your configuration and run vagrant again.
188
+ snapshot_deletion_error: |-
189
+ Error while deleting snapshot: %{error_message}.
190
+ snapshot_missing: |-
191
+ Snapshot not found: %{error_message}.
192
+ snapshot_list_error: |-
193
+ Cannot list snapshots: %{error_message}.
194
+ snapshot_creation_error: |-
195
+ Cannot create snapshot(s): %{error_message}.
196
+ snapshot_reversion_error: |-
197
+ Cannot revert snapshot(s): %{error_message}.
186
198
  serial_cannot_create_path_error: |-
187
199
  Error creating path for serial port output log: %{path}
188
200
 
@@ -202,3 +214,13 @@ en:
202
214
  preparing: |-
203
215
  The vagrant machine is being prepared for creation, please wait for
204
216
  it to reach a steady state before issuing commands on it.
217
+
218
+ cap:
219
+ virtiofs:
220
+ preparing: Configuring virtiofs devices for shared folders...
221
+ mounting: Mounting virtiofs shared folders...
222
+ cleanup: Removing virtiofs devices for shared folders...
223
+ 9p:
224
+ preparing: Configuring 9p devices for shared folders...
225
+ mounting: Mounting 9p shared folders...
226
+ cleanup: Removing 9p devices for shared folders...
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'additional storage configured', acceptance: true do
6
+ include_context 'libvirt_acceptance'
7
+
8
+ before do
9
+ environment.skeleton('additional_storage')
10
+ end
11
+
12
+ after do
13
+ assert_execute('vagrant', 'destroy', '--force')
14
+ end
15
+
16
+ it 'should succeed' do
17
+ status('Test: machine is created successfully')
18
+ result = environment.execute('vagrant', 'up')
19
+ expect(result).to exit_with(0)
20
+
21
+ status('Test: additional storage configured')
22
+ expect(result.stdout).to match(/\(vda\).*work_default.img/)
23
+ expect(result.stdout).to match(/\(vdb\).*work_default-vdb\.qcow2/)
24
+
25
+ status('Test: reload handles additional storage correctly')
26
+ result = environment.execute('vagrant', 'reload')
27
+ expect(result).to exit_with(0)
28
+
29
+ status('Test: additional storage reported correctly')
30
+ expect(result.stdout).to match(/\(vdb\).*work_default-vdb\.qcow2/)
31
+ end
32
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'package domain', acceptance: true do
6
+ include_context 'libvirt_acceptance'
7
+
8
+ before(:all) do
9
+ expect(Vagrant::Util::Which.which('virt-sysprep')).to be_truthy,
10
+ 'packaging tests require virt-sysprep, please install'
11
+ expect(Vagrant::Util::Which.which('virt-sparsify')).to be_truthy,
12
+ 'packaging tests require virt-sparsify, please install'
13
+
14
+ result = (File.exist?('C:\\') ? `dir /-C #{Dir.tmpdir}` : `df #{Dir.tmpdir}`).split("\n").last
15
+ expect(result.split[3].to_i).to be > 6 * 1024 * 1024,
16
+ "packaging tests require more than 6GiB of space under #{Dir.tmpdir}"
17
+ end
18
+
19
+ after(:each) do
20
+ assert_execute('vagrant', 'destroy', '--force')
21
+ end
22
+
23
+ let(:testbox_envvars) { { VAGRANT_VAGRANTFILE: 'Vagrantfile.testbox' } }
24
+
25
+ context 'simple' do
26
+ before do
27
+ environment.skeleton('package_simple')
28
+ end
29
+
30
+ after do
31
+ result = environment.execute('vagrant', 'destroy', '--force', extra_env: testbox_envvars)
32
+ expect(result).to exit_with(0)
33
+
34
+ assert_execute('vagrant', 'box', 'remove', '--force', 'test-package-simple-domain')
35
+ end
36
+
37
+ it 'should succeed' do
38
+ status('Test: machine is created successfully')
39
+ expect(environment.execute('vagrant', 'up')).to exit_with(0)
40
+
41
+ status('Test: package machine successfully')
42
+ expect(environment.execute('vagrant', 'package')).to exit_with(0)
43
+
44
+ status('Test: add packaged box')
45
+ expect(environment.execute(
46
+ 'vagrant', 'box', 'add', '--force', '--name', 'test-package-simple-domain', 'package.box'
47
+ )).to exit_with(0)
48
+
49
+ status('Test: machine from packaged box is created successfully')
50
+ result = environment.execute('vagrant', 'up', extra_env: testbox_envvars)
51
+ expect(result).to exit_with(0)
52
+ expect(result.stdout).to match(/test-package-complex-domain/)
53
+ end
54
+ end
55
+
56
+ context 'complex' do
57
+ before do
58
+ environment.skeleton('package_complex')
59
+ extra_env.merge!(
60
+ {
61
+ VAGRANT_LIBVIRT_VIRT_SYSPREP_OPERATIONS: 'defaults,-ssh-userdir,customize',
62
+ VAGRANT_LIBVIRT_VIRT_SYSPREP_OPTIONS: '--run $(pwd)/scripts/sysprep.sh',
63
+ }
64
+ )
65
+ end
66
+
67
+ after do
68
+ expect(environment.execute('vagrant', 'destroy', '--force', extra_env: testbox_envvars)).to exit_with(0)
69
+ assert_execute('vagrant', 'box', 'remove', '--force', 'test-package-complex-domain')
70
+ end
71
+
72
+ it 'should succeed' do
73
+ status('Test: machine is created successfully')
74
+ expect(environment.execute('vagrant', 'up')).to exit_with(0)
75
+
76
+ status('Test: package machine successfully')
77
+ expect(environment.execute('vagrant', 'package')).to exit_with(0)
78
+
79
+ status('Test: add packaged box')
80
+ expect(environment.execute(
81
+ 'vagrant', 'box', 'add', '--force', '--name', 'test-package-complex-domain', 'package.box'
82
+ )).to exit_with(0)
83
+
84
+ status('Test: machine from packaged box is created successfully')
85
+ result = environment.execute('vagrant', 'up', extra_env: testbox_envvars)
86
+ expect(result).to exit_with(0)
87
+ expect(result.stdout).to match(/test-package-complex-domain/)
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'provider settings', acceptance: true do
6
+ include_context 'libvirt_acceptance'
7
+
8
+ after do
9
+ assert_execute('vagrant', 'destroy', '--force')
10
+ end
11
+
12
+ context 'with defaults' do
13
+ before do
14
+ environment.skeleton('default_settings')
15
+ end
16
+
17
+ it 'should succeed' do
18
+ status('Test: machine is created successfully')
19
+ result = environment.execute('vagrant', 'up')
20
+ expect(result).to exit_with(0)
21
+
22
+ status('Test: CPU matches default')
23
+ expect(result.stdout).to match(/Cpus:\s+1$/)
24
+
25
+ status('Test: memory matches default')
26
+ expect(result.stdout).to match(/Memory:\s+512M/)
27
+
28
+ status('Test: default prefix is used')
29
+ expect(result.stdout).to match(/Name:\s+work_default$/)
30
+ end
31
+ end
32
+
33
+ context 'with modified config' do
34
+ before do
35
+ environment.skeleton('adjusted_settings')
36
+ end
37
+
38
+ it 'should succeed' do
39
+ status('Test: machine is created successfully')
40
+ result = environment.execute('vagrant', 'up')
41
+ expect(result).to exit_with(0)
42
+
43
+ status('Test: CPUs are changed')
44
+ expect(result.stdout).to match(/Cpus:\s+2$/)
45
+
46
+ status('Test: memory is changed')
47
+ expect(result.stdout).to match(/Memory:\s+1000M$/)
48
+
49
+ status('Test: default prefix is changed')
50
+ expect(result.stdout).to match(/Name:\s+changed_default_prefixdefault$/)
51
+ expect(result.stdout).to match(/\(vda\).*changed_default_prefixdefault\.img/)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'simple vm provision via shell', acceptance: true do
6
+ include_context 'libvirt_acceptance'
7
+
8
+ before do
9
+ environment.skeleton('simple_vm_provision')
10
+ end
11
+
12
+ after do
13
+ assert_execute('vagrant', 'destroy', '--force')
14
+ end
15
+
16
+ it 'should succeed' do
17
+ status('Test: machine is created successfully')
18
+ result = environment.execute('vagrant', 'up')
19
+ expect(result).to exit_with(0)
20
+
21
+ status('Test: provision script executed')
22
+ expect(result.stdout).to match(/Hello, World/)
23
+
24
+ status('Test: reload')
25
+ result = environment.execute('vagrant', 'reload')
26
+ expect(result).to exit_with(0)
27
+
28
+ status('Test: provision checked if already executed')
29
+ expect(result.stdout).to match(/Machine already provisioned/)
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'snapshots', acceptance: true do
6
+ include_context 'libvirt_acceptance'
7
+
8
+ after(:each) do
9
+ assert_execute('vagrant', 'destroy', '--force')
10
+ end
11
+
12
+ before do
13
+ environment.skeleton('snapshots')
14
+ end
15
+
16
+ it 'should succeed' do
17
+ status('Test: machine is created successfully')
18
+ expect(environment.execute('vagrant', 'up')).to exit_with(0)
19
+
20
+ status('Test: add test file')
21
+ expect(environment.execute('vagrant', 'ssh', '--', '-t', 'touch a.txt')).to exit_with(0)
22
+
23
+ status('Test: create snapshot')
24
+ expect(environment.execute('vagrant', 'snapshot', 'save', 'default', 'test')).to exit_with(0)
25
+
26
+ status('Test: modify files')
27
+ expect(environment.execute('vagrant', 'ssh', '--', '-t', 'rm a.txt')).to exit_with(0)
28
+ expect(environment.execute('vagrant', 'ssh', '--', '-t', 'ls a.txt')).to exit_with(1)
29
+ expect(environment.execute('vagrant', 'ssh', '--', '-t', 'touch b.txt')).to exit_with(0)
30
+
31
+ status('Test: restore snapshot')
32
+ expect(environment.execute('vagrant', 'snapshot', 'restore', 'test')).to exit_with(0)
33
+
34
+ status('Test: files are as expected')
35
+ expect(environment.execute('vagrant', 'ssh', '--', '-t', 'ls a.txt')).to exit_with(0)
36
+ expect(environment.execute('vagrant', 'ssh', '--', '-t', 'ls b.txt')).to exit_with(1)
37
+
38
+ status('Test: snapshot removal works')
39
+ expect(environment.execute('vagrant', 'snapshot', 'delete', 'test')).to exit_with(0)
40
+ end
41
+ end
@@ -0,0 +1,14 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant.configure("2") do |config|
5
+ config.vm.box = "test-package-complex-domain"
6
+ config.vm.define 'package-complex'
7
+ config.vm.synced_folder ".", "/vagrant", disabled: true
8
+
9
+ config.vm.provider :libvirt do |libvirt|
10
+ libvirt.driver = "qemu"
11
+ libvirt.cpus = 2
12
+ libvirt.memory = 2048
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ #!/bin/sh -eux
2
+
3
+ # consider purging any packages you don't need here
4
+
5
+ echo "autoremoving packages and cleaning apt data"
6
+ apt-get -y autoremove;
7
+ apt-get -y clean;
8
+
9
+ # repeat what machine-ids does in sysprep as this script needs to run via customize
10
+ # which has a bug resulting in the machine-ids being regenerated
11
+
12
+ if [ -f /etc/machine-id ]
13
+ then
14
+ truncate --size=0 /etc/machine-id
15
+ fi
16
+
17
+ if [ -f /var/lib/dbus/machine-id ]
18
+ then
19
+ truncate --size=0 /run/machine-id
20
+ fi
21
+
22
+ echo "remove /var/cache"
23
+ find /var/cache -type f -exec rm -rf {} \;
24
+
25
+ echo "force a new random seed to be generated"
26
+ rm -f /var/lib/systemd/random-seed
27
+
28
+ # for debian based systems ensure host keys regenerated on boot
29
+ if [ -e /usr/sbin/dpkg-reconfigure ]
30
+ then
31
+ printf "@reboot root command bash -c 'export PATH=$PATH:/usr/sbin ; export DEBIAN_FRONTEND=noninteractive ; export DEBCONF_NONINTERACTIVE_SEEN=true ; /usr/sbin/dpkg-reconfigure openssh-server &>/dev/null ; /bin/systemctl restart ssh.service ; rm --force /etc/cron.d/keys'\n" > /etc/cron.d/keys
32
+ fi
@@ -0,0 +1,10 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant.configure("2") do |config|
5
+ config.vm.box = "test-package-simple-domain"
6
+ config.vm.define 'package-simple'
7
+ config.ssh.shell = "/bin/sh"
8
+ config.ssh.insert_key = false
9
+ config.vm.synced_folder ".", "/vagrant", disabled: true
10
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'handle two disk machine', acceptance: true do
6
+ include_context 'libvirt_acceptance'
7
+
8
+ after do
9
+ assert_execute('vagrant', 'destroy', '--force')
10
+ end
11
+
12
+ before do
13
+ environment.skeleton('two_disks')
14
+ environment.execute(File.expand_path('../../tools/create_box_with_two_disks.sh', __dir__),
15
+ environment.homedir.to_s, 'vagrant')
16
+ end
17
+
18
+ it 'should succeed' do
19
+ status('Test: machine is created successfully')
20
+ result = environment.execute('vagrant', 'up')
21
+ expect(result).to exit_with(0)
22
+
23
+ status('Test: disk one referenced')
24
+ expect(result.stdout).to match(/Image\(vda\):.*work_default.img, virtio, 2G/)
25
+
26
+ status('Test: disk two referenced')
27
+ expect(result.stdout).to match(/Image\(vdb\):.*work_default_1.img, virtio, 10G/)
28
+ end
29
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'use qemu agent to determine machine private address', acceptance: true do
6
+ include_context 'libvirt_acceptance'
7
+
8
+ before do
9
+ environment.skeleton('qemu_agent')
10
+ end
11
+
12
+ after do
13
+ assert_execute('vagrant', 'destroy', '--force')
14
+ end
15
+
16
+ it 'should succeed' do
17
+ status('Test: machine is created successfully')
18
+ result = environment.execute('vagrant', 'up')
19
+ expect(result).to exit_with(0)
20
+
21
+ # extract SSH IP address emitted as it should be the private network since
22
+ # the mgmt network has not been attached
23
+ hostname = result.stdout.each_line.find { |line| line.include?('SSH address:') }
24
+ expect(hostname).to_not be_nil
25
+ ip_address = hostname.strip.split.last.split(':').first
26
+ # default private network for vagrant-libvirt unless explicitly configured
27
+ expect(IPAddr.new('172.28.128.0/255.255.255.0')).to include(IPAddr.new(ip_address))
28
+
29
+ # ssh'ing successfully means that the private network is accessible
30
+ status('Test: machine private network is accessible')
31
+ result = environment.execute('vagrant', 'ssh', '-c', 'echo "hello, world"')
32
+ expect(result).to exit_with(0)
33
+ expect(result.stdout).to match(/hello, world/)
34
+ end
35
+ end
data/spec/spec_helper.rb CHANGED
@@ -55,4 +55,7 @@ RSpec.configure do |config|
55
55
  config.mock_with :rspec do |mocks|
56
56
  mocks.verify_partial_doubles = true
57
57
  end
58
+
59
+ # don't run acceptance tests by default
60
+ config.filter_run_excluding :acceptance => true
58
61
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'vagrant-spec/acceptance/configuration'
4
+
5
+ module VagrantPlugins
6
+ module VagrantLibvirt
7
+ module Spec
8
+ module Acceptance
9
+ class Configuration < Vagrant::Spec::Acceptance::Configuration
10
+ attr_accessor :clean_on_fail
11
+
12
+ def initialize
13
+ super
14
+
15
+ @clean_on_fail = true
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'vagrant-spec/acceptance/configuration'
4
+ require "vagrant-spec/acceptance/rspec/matcher_exit_with"
5
+
6
+ require_relative 'isolated_environment'
7
+
8
+ shared_context "acceptance" do
9
+ # Setup the environment so that we have an isolated area
10
+ # to run Vagrant. We do some configuration here as well in order
11
+ # to replace "vagrant" with the proper path to Vagrant as well
12
+ # as tell the isolated environment about custom environmental
13
+ # variables to pass in.
14
+ let!(:environment) { new_environment }
15
+
16
+ let(:config) { Vagrant::Spec::Acceptance::Configuration.new }
17
+
18
+ let(:extra_env) { {} }
19
+
20
+ # The skeleton paths that will be used to configure environments.
21
+ let(:skeleton_paths) do
22
+ root = Vagrant::Spec.source_root.join("acceptance", "support-skeletons")
23
+ config.skeleton_paths.dup.unshift(root)
24
+ end
25
+
26
+ after(:each) do |example|
27
+ if example.exception.nil? || config.clean_on_fail
28
+ environment.close
29
+ else
30
+ example.reporter.message("Temporary work and home dirs (#{environment.workdir} and #{environment.homedir}) not removed to allow debug")
31
+ end
32
+ end
33
+
34
+ # Creates a new isolated environment instance each time it is called.
35
+ #
36
+ # @return [Acceptance::IsolatedEnvironment]
37
+ def new_environment(env=nil)
38
+ apps = { "vagrant" => config.vagrant_path }
39
+ env = config.env.merge(env || {})
40
+ env.merge!(extra_env)
41
+
42
+ VagrantPlugins::VagrantLibvirt::Spec::AcceptanceIsolatedEnvironment.new(
43
+ apps: apps,
44
+ env: env,
45
+ skeleton_paths: skeleton_paths,
46
+ )
47
+ end
48
+
49
+ # Executes the given command in the context of the isolated environment.
50
+ #
51
+ # @return [Object]
52
+ def execute(*args, env: nil, log: true, &block)
53
+ env ||= environment
54
+ status("Execute: #{args.join(" ")}") if log
55
+ env.execute(*args, &block)
56
+ end
57
+
58
+ # This method is an assertion helper for asserting that a process
59
+ # succeeds. It is a wrapper around `execute` that asserts that the
60
+ # exit status was successful.
61
+ def assert_execute(*args, env: nil, &block)
62
+ result = execute(*args, env: env, &block)
63
+ expect(result).to exit_with(0)
64
+ result
65
+ end
66
+
67
+ def status(message)
68
+ RSpec.world.reporter.message(message)
69
+ end
70
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'vagrant-spec/acceptance/isolated_environment'
4
+ require 'vagrant-spec/subprocess'
5
+ require 'vagrant-spec/which'
6
+
7
+ module VagrantPlugins
8
+ module VagrantLibvirt
9
+ module Spec
10
+ class AcceptanceIsolatedEnvironment < Vagrant::Spec::AcceptanceIsolatedEnvironment
11
+ # Executes a command in the context of this isolated environment.
12
+ # Any command executed will therefore see our temporary directory
13
+ # as the home directory.
14
+ #
15
+ # If the command has been defined with a special path, then the
16
+ # command will be replaced with the full path to that command.
17
+ def execute(command, *args, **options)
18
+ # Create the command
19
+ command = replace_command(command)
20
+ # Use provided command if it is a valid executable
21
+ if !File.executable?(command)
22
+ # If it's not a valid executable, search for vagrant
23
+ command = Vagrant::Spec::Which.which(command)
24
+ end
25
+
26
+ # Build up the options
27
+ options[:env] = @env.merge(options.delete(:extra_env) || {})
28
+ options[:notify] = [:stdin, :stderr, :stdout]
29
+ options[:workdir] = @workdir.to_s
30
+
31
+ # Execute, logging out the stdout/stderr as we get it
32
+ @logger.info("Executing: #{[command].concat(args).inspect}")
33
+ Vagrant::Spec::Subprocess.execute(command, *args, **options) do |type, data|
34
+ @logger.debug("#{type}: #{data}") if type == :stdout || type == :stderr
35
+ yield type, data if block_given?
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'acceptance/context'
4
+
5
+ FALSEY_VALUES = %w[f false no n 0].freeze
6
+
7
+ shared_context 'libvirt_acceptance' do
8
+ include_context 'acceptance'
9
+
10
+ # The skeleton paths that will be used to configure environments.
11
+ let(:skeleton_paths) do
12
+ root = File.expand_path('../acceptance/support-skeletons', __dir__)
13
+ config.skeleton_paths.dup.unshift(root)
14
+ end
15
+
16
+ let(:config) do
17
+ c = VagrantPlugins::VagrantLibvirt::Spec::Acceptance::Configuration.new
18
+ c.clean_on_fail = FALSEY_VALUES.include?(ENV.fetch('VAGRANT_SPEC_SKIP_CLEANUP', 'false').to_s.downcase)
19
+
20
+ c
21
+ end
22
+
23
+ before(:each) do
24
+ # allow execution environment to cache boxes used
25
+ symlink_boxes(ENV.fetch('VAGRANT_HOME', nil), environment)
26
+ end
27
+
28
+ after(:each) do
29
+ # ensure we remove the symlink
30
+ boxes_symlink = File.join(environment.homedir, 'boxes')
31
+ File.delete(boxes_symlink) if File.symlink?(boxes_symlink)
32
+ end
33
+
34
+ around do |example|
35
+ vagrant_cwd = ENV.delete('VAGRANT_CWD')
36
+ env_provider_before = ENV.fetch('VAGRANT_DEFAULT_PROVIDER', nil)
37
+ ENV['VAGRANT_DEFAULT_PROVIDER'] = 'libvirt'
38
+
39
+ begin
40
+ example.run
41
+ ensure
42
+ ENV['VAGRANT_CWD'] = vagrant_cwd if vagrant_cwd
43
+ if env_provider_before.nil?
44
+ ENV.delete('VAGRANT_DEFAULT_PROVIDER')
45
+ else
46
+ ENV['VAGRANT_DEFAULT_PROVIDER'] = env_provider_before
47
+ end
48
+ end
49
+ end
50
+
51
+ def duplicate_environment(env, *args)
52
+ dup_env = new_environment(*args)
53
+ symlink_boxes(env.homedir, dup_env)
54
+
55
+ dup_env
56
+ end
57
+
58
+ def symlink_boxes(vagrant_home, target_env)
59
+ return if vagrant_home.nil?
60
+
61
+ # allow use the same boxes location as source environment
62
+ File.symlink File.realpath(File.join(vagrant_home, 'boxes')), File.join(target_env.homedir, 'boxes')
63
+ end
64
+ end
@@ -37,5 +37,6 @@ shared_context 'unit' do
37
37
  before (:each) do
38
38
  allow(machine).to receive(:guest).and_return(guest)
39
39
  allow(machine).to receive(:communicate).and_return(communicator)
40
+ allow(machine).to receive(:ui).and_return(ui)
40
41
  end
41
42
  end