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
@@ -0,0 +1,202 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/sharedcontext'
|
3
|
+
require 'support/libvirt_context'
|
4
|
+
|
5
|
+
require 'vagrant-libvirt/errors'
|
6
|
+
require 'vagrant-libvirt/action/forward_ports'
|
7
|
+
|
8
|
+
describe VagrantPlugins::ProviderLibvirt::Action::ForwardPorts do
|
9
|
+
subject { described_class.new(app, env) }
|
10
|
+
|
11
|
+
include_context 'unit'
|
12
|
+
|
13
|
+
let(:machine_config) { double("machine_config") }
|
14
|
+
let(:vm_config) { double("vm_config") }
|
15
|
+
let(:provider_config) { double("provider_config") }
|
16
|
+
|
17
|
+
before (:each) do
|
18
|
+
allow(machine).to receive(:config).and_return(machine_config)
|
19
|
+
allow(machine).to receive(:provider_config).and_return(provider_config)
|
20
|
+
allow(machine_config).to receive(:vm).and_return(vm_config)
|
21
|
+
allow(vm_config).to receive(:networks).and_return([])
|
22
|
+
allow(provider_config).to receive(:forward_ssh_port).and_return(false)
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#call' do
|
26
|
+
context 'with none defined' do
|
27
|
+
it 'should skip calling forward_ports' do
|
28
|
+
expect(subject).to_not receive(:forward_ports)
|
29
|
+
expect(subject.call(env)).to be_nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'with network including one forwarded port' do
|
34
|
+
let(:networks) { [
|
35
|
+
[:private_network, {:ip=>"10.20.30.40", :protocol=>"tcp", :id=>"6b8175ed-3220-4b63-abaf-0bb8d7cdd723"}],
|
36
|
+
[:forwarded_port, port_options],
|
37
|
+
]}
|
38
|
+
|
39
|
+
let(:port_options){ {guest: 80, host: 8080} }
|
40
|
+
|
41
|
+
it 'should compile a single port forward to set up' do
|
42
|
+
expect(vm_config).to receive(:networks).and_return(networks)
|
43
|
+
expect(ui).to_not receive(:warn)
|
44
|
+
expect(subject).to receive(:forward_ports).and_return(nil)
|
45
|
+
|
46
|
+
expect(subject.call(env)).to be_nil
|
47
|
+
|
48
|
+
expect(env[:forwarded_ports]).to eq([networks[1][1]])
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'when host port in protected range' do
|
52
|
+
let(:port_options){ {guest: 8080, host: 80} }
|
53
|
+
|
54
|
+
it 'should emit a warning' do
|
55
|
+
expect(vm_config).to receive(:networks).and_return(networks)
|
56
|
+
expect(ui).to receive(:warn).with(include("You are trying to forward to privileged ports"))
|
57
|
+
expect(subject).to receive(:forward_ports).and_return(nil)
|
58
|
+
|
59
|
+
expect(subject.call(env)).to be_nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when udp protocol is selected' do
|
65
|
+
let(:port_options){ {guest: 80, host: 8080, protocol: "udp"} }
|
66
|
+
|
67
|
+
it 'should skip and emit warning' do
|
68
|
+
expect(vm_config).to receive(:networks).and_return([[:forwarded_port, port_options]])
|
69
|
+
expect(ui).to receive(:warn).with("Forwarding UDP ports is not supported. Ignoring.")
|
70
|
+
expect(subject).to_not receive(:forward_ports)
|
71
|
+
|
72
|
+
expect(subject.call(env)).to be_nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when default ssh port forward provided' do
|
77
|
+
let(:networks){ [
|
78
|
+
[:private_network, {:ip=>"10.20.30.40", :protocol=>"tcp", :id=>"6b8175ed-3220-4b63-abaf-0bb8d7cdd723"}],
|
79
|
+
[:forwarded_port, {guest: 80, host: 8080}],
|
80
|
+
[:forwarded_port, {guest: 22, host: 2222, host_ip: '127.0.0.1', id: 'ssh'}],
|
81
|
+
]}
|
82
|
+
|
83
|
+
context 'with default config' do
|
84
|
+
it 'should not forward the ssh port' do
|
85
|
+
expect(vm_config).to receive(:networks).and_return(networks)
|
86
|
+
expect(subject).to receive(:forward_ports)
|
87
|
+
|
88
|
+
expect(subject.call(env)).to be_nil
|
89
|
+
|
90
|
+
expect(env[:forwarded_ports]).to eq([networks[1][1]])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'with forward_ssh_port enabled' do
|
95
|
+
before do
|
96
|
+
allow(provider_config).to receive(:forward_ssh_port).and_return(true)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should forward the port' do
|
100
|
+
expect(vm_config).to receive(:networks).and_return(networks)
|
101
|
+
expect(subject).to receive(:forward_ports)
|
102
|
+
|
103
|
+
expect(subject.call(env)).to be_nil
|
104
|
+
|
105
|
+
expect(env[:forwarded_ports]).to eq(networks.drop(1).map { |_, opts| opts })
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '#forward_ports' do
|
112
|
+
let(:pid_dir){ machine.data_dir.join('pids') }
|
113
|
+
|
114
|
+
before (:each) do
|
115
|
+
allow(env).to receive(:[]).and_call_original
|
116
|
+
allow(machine).to receive(:ssh_info).and_return(
|
117
|
+
{
|
118
|
+
:host => "localhost",
|
119
|
+
:username => "vagrant",
|
120
|
+
:port => 22,
|
121
|
+
:private_key_path => ["/home/test/.ssh/id_rsa"],
|
122
|
+
}
|
123
|
+
)
|
124
|
+
allow(provider_config).to receive(:proxy_command).and_return(nil)
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'with port to forward' do
|
128
|
+
let(:port_options){ {guest: 80, host: 8080, guest_ip: "192.168.1.121"} }
|
129
|
+
|
130
|
+
it 'should spawn ssh to setup forwarding' do
|
131
|
+
expect(env).to receive(:[]).with(:forwarded_ports).and_return([port_options])
|
132
|
+
expect(ui).to receive(:info).with("#{port_options[:guest]} (guest) => #{port_options[:host]} (host) (adapter eth0)")
|
133
|
+
expect(subject).to receive(:spawn).with(/ssh -n -o User=vagrant -o Port=22.*-L \*:8080:192.168.1.121:80 -N localhost/, anything).and_return(9999)
|
134
|
+
|
135
|
+
expect(subject.forward_ports(env)).to eq([port_options])
|
136
|
+
|
137
|
+
expect(pid_dir.join('ssh_8080.pid')).to have_file_content("9999")
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'with privileged host port' do
|
142
|
+
let(:port_options){ {guest: 80, host: 80, guest_ip: "192.168.1.121"} }
|
143
|
+
|
144
|
+
it 'should spawn ssh to setup forwarding' do
|
145
|
+
expect(env).to receive(:[]).with(:forwarded_ports).and_return([port_options])
|
146
|
+
expect(ui).to receive(:info).with("#{port_options[:guest]} (guest) => #{port_options[:host]} (host) (adapter eth0)")
|
147
|
+
expect(ui).to receive(:info).with('Requesting sudo for host port(s) <= 1024')
|
148
|
+
expect(subject).to receive(:system).with('sudo -v').and_return(true)
|
149
|
+
expect(subject).to receive(:spawn).with(/sudo ssh -n -o User=vagrant -o Port=22.*-L \*:80:192.168.1.121:80 -N localhost/, anything).and_return(10000)
|
150
|
+
|
151
|
+
expect(subject.forward_ports(env)).to eq([port_options])
|
152
|
+
|
153
|
+
expect(pid_dir.join('ssh_80.pid')).to have_file_content("10000")
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe VagrantPlugins::ProviderLibvirt::Action::ClearForwardedPorts do
|
160
|
+
subject { described_class.new(app, env) }
|
161
|
+
|
162
|
+
include_context 'unit'
|
163
|
+
include_context 'libvirt'
|
164
|
+
|
165
|
+
describe '#call' do
|
166
|
+
context 'no forwarded ports' do
|
167
|
+
it 'should skip checking if pids are running' do
|
168
|
+
expect(subject).to_not receive(:ssh_pid?)
|
169
|
+
expect(logger).to receive(:info).with('No ssh pids found')
|
170
|
+
|
171
|
+
expect(subject.call(env)).to be_nil
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'multiple forwarded ports' do
|
176
|
+
before do
|
177
|
+
data_dir = machine.data_dir.join('pids')
|
178
|
+
data_dir.mkdir unless data_dir.directory?
|
179
|
+
|
180
|
+
[
|
181
|
+
{:port => '8080', :pid => '10001'},
|
182
|
+
{:port => '8081', :pid => '10002'},
|
183
|
+
].each do |port_pid|
|
184
|
+
File.write(data_dir.to_s + "/ssh_#{port_pid[:port]}.pid", port_pid[:pid])
|
185
|
+
end
|
186
|
+
end
|
187
|
+
it 'should terminate each of the processes' do
|
188
|
+
expect(logger).to receive(:info).with(no_args) # don't know how to test translations from vagrant
|
189
|
+
expect(subject).to receive(:ssh_pid?).with("10001").and_return(true)
|
190
|
+
expect(subject).to receive(:ssh_pid?).with("10002").and_return(true)
|
191
|
+
expect(logger).to receive(:debug).with(/Killing pid/).twice()
|
192
|
+
expect(logger).to receive(:info).with('Removing ssh pid files')
|
193
|
+
expect(subject).to receive(:system).with("kill 10001")
|
194
|
+
expect(subject).to receive(:system).with("kill 10002")
|
195
|
+
|
196
|
+
expect(subject.call(env)).to be_nil
|
197
|
+
|
198
|
+
expect(Dir.entries(machine.data_dir.join('pids'))).to match_array(['.', '..'])
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/sharedcontext'
|
3
|
+
require 'support/libvirt_context'
|
4
|
+
require 'vagrant-libvirt/action/destroy_domain'
|
5
|
+
|
6
|
+
describe VagrantPlugins::ProviderLibvirt::Action::HaltDomain do
|
7
|
+
subject { described_class.new(app, env) }
|
8
|
+
|
9
|
+
include_context 'unit'
|
10
|
+
include_context 'libvirt'
|
11
|
+
|
12
|
+
let(:libvirt_domain) { double('libvirt_domain') }
|
13
|
+
let(:servers) { double('servers') }
|
14
|
+
|
15
|
+
describe '#call' do
|
16
|
+
before do
|
17
|
+
allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
|
18
|
+
.to receive(:connection).and_return(connection)
|
19
|
+
allow(connection).to receive(:servers).and_return(servers)
|
20
|
+
allow(servers).to receive(:get).and_return(domain)
|
21
|
+
# always see this at the start of #call
|
22
|
+
expect(ui).to receive(:info).with('Halting domain...')
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'with graceful timeout' do
|
26
|
+
it "should shutdown" do
|
27
|
+
expect(guest).to receive(:capability).with(:halt).and_return(true)
|
28
|
+
expect(domain).to receive(:wait_for).with(60).and_return(false)
|
29
|
+
expect(subject.call(env)).to be_nil
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when halt fails' do
|
33
|
+
before do
|
34
|
+
expect(logger).to receive(:info).with('Trying Libvirt graceful shutdown.')
|
35
|
+
expect(guest).to receive(:capability).with(:halt).and_raise(IOError)
|
36
|
+
expect(domain).to receive(:state).and_return('running')
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should call shutdown" do
|
40
|
+
expect(domain).to receive(:shutdown)
|
41
|
+
expect(domain).to receive(:wait_for).with(60).and_return(false)
|
42
|
+
expect(subject.call(env)).to be_nil
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when shutdown fails' do
|
46
|
+
it "should call power off" do
|
47
|
+
expect(logger).to receive(:error).with('Failed to shutdown cleanly. Calling force poweroff.')
|
48
|
+
expect(domain).to receive(:shutdown).and_raise(IOError)
|
49
|
+
expect(domain).to receive(:poweroff)
|
50
|
+
expect(subject.call(env)).to be_nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when shutdown exceeds the timeout' do
|
55
|
+
it "should call poweroff" do
|
56
|
+
expect(logger).to receive(:info).with('VM is still running. Calling force poweroff.')
|
57
|
+
expect(domain).to receive(:shutdown).and_raise(Timeout::Error)
|
58
|
+
expect(domain).to receive(:poweroff)
|
59
|
+
expect(subject.call(env)).to be_nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when halt exceeds the timeout' do
|
65
|
+
before do
|
66
|
+
expect(logger).to_not receive(:info).with('Trying Libvirt graceful shutdown.')
|
67
|
+
expect(guest).to receive(:capability).with(:halt).and_raise(Timeout::Error)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should call poweroff" do
|
71
|
+
expect(logger).to receive(:info).with('VM is still running. Calling force poweroff.')
|
72
|
+
expect(domain).to receive(:poweroff)
|
73
|
+
expect(subject.call(env)).to be_nil
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'with force halt enabled' do
|
79
|
+
before do
|
80
|
+
allow(env).to receive(:[]).and_call_original
|
81
|
+
expect(env).to receive(:[]).with(:force_halt).and_return(true)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should just call poweroff" do
|
85
|
+
expect(domain).to receive(:poweroff)
|
86
|
+
expect(subject.call(env)).to be_nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,363 @@
|
|
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::HandleBoxImage do
|
8
|
+
subject { described_class.new(app, env) }
|
9
|
+
|
10
|
+
include_context 'unit'
|
11
|
+
include_context 'libvirt'
|
12
|
+
|
13
|
+
let(:libvirt_client) { double('libvirt_client') }
|
14
|
+
let(:volumes) { double('volumes') }
|
15
|
+
let(:all) { double('all') }
|
16
|
+
let(:box_volume) { double('box_volume') }
|
17
|
+
let(:fog_volume) { double('fog_volume') }
|
18
|
+
|
19
|
+
describe '#call' do
|
20
|
+
before do
|
21
|
+
allow_any_instance_of(VagrantPlugins::ProviderLibvirt::Driver)
|
22
|
+
.to receive(:connection).and_return(connection)
|
23
|
+
allow(connection).to receive(:client).and_return(libvirt_client)
|
24
|
+
allow(connection).to receive(:volumes).and_return(volumes)
|
25
|
+
allow(volumes).to receive(:all).and_return(all)
|
26
|
+
allow(env[:ui]).to receive(:clear_line)
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when one disk in metadata.json' do
|
31
|
+
before do
|
32
|
+
allow(all).to receive(:first).and_return(box_volume)
|
33
|
+
allow(box_volume).to receive(:id).and_return(1)
|
34
|
+
allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
|
35
|
+
allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
|
36
|
+
allow(env[:machine]).to receive_message_chain("box.metadata") { Hash[
|
37
|
+
'virtual_size'=> 5,
|
38
|
+
'format' => 'qcow2'
|
39
|
+
]
|
40
|
+
}
|
41
|
+
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
42
|
+
'/test/'.concat(arg.to_s)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should have one disk in machine env' do
|
47
|
+
expect(subject.call(env)).to be_nil
|
48
|
+
expect(env[:box_volume_number]).to eq(1)
|
49
|
+
expect(env[:box_volumes]).to eq(
|
50
|
+
[
|
51
|
+
{
|
52
|
+
:path=>"/test/box.img",
|
53
|
+
:name=>"test_vagrant_box_image_1.1.1_box.img",
|
54
|
+
:virtual_size=>5,
|
55
|
+
:format=>"qcow2"
|
56
|
+
}
|
57
|
+
]
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'when disk image not in storage pool' do
|
62
|
+
before do
|
63
|
+
allow(File).to receive(:exist?).and_return(true)
|
64
|
+
allow(File).to receive(:size).and_return(5*1024*1024*1024)
|
65
|
+
allow(all).to receive(:first).and_return(nil)
|
66
|
+
allow(subject).to receive(:upload_image).and_return(true)
|
67
|
+
allow(volumes).to receive(:create).and_return(fog_volume)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should upload disk' do
|
71
|
+
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
72
|
+
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_box.img in storage pool default.')
|
73
|
+
expect(volumes).to receive(:create).with(
|
74
|
+
hash_including(
|
75
|
+
:name => "test_vagrant_box_image_1.1.1_box.img",
|
76
|
+
:allocation => "5120M",
|
77
|
+
:capacity => "5G",
|
78
|
+
)
|
79
|
+
)
|
80
|
+
expect(subject).to receive(:upload_image)
|
81
|
+
expect(subject.call(env)).to be_nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'when disk image already in storage pool' do
|
86
|
+
before do
|
87
|
+
allow(all).to receive(:first).and_return(box_volume)
|
88
|
+
allow(box_volume).to receive(:id).and_return(1)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should skip disk upload' do
|
92
|
+
expect(volumes).not_to receive(:create)
|
93
|
+
expect(subject).not_to receive(:upload_image)
|
94
|
+
expect(subject.call(env)).to be_nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'when three disks in metadata.json' do
|
100
|
+
let(:status) { double }
|
101
|
+
|
102
|
+
before do
|
103
|
+
allow(all).to receive(:first).and_return(box_volume)
|
104
|
+
allow(box_volume).to receive(:id).and_return(1)
|
105
|
+
allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
|
106
|
+
allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
|
107
|
+
allow(env[:machine]).to receive_message_chain("box.metadata") { Hash[
|
108
|
+
'disks' => [
|
109
|
+
{
|
110
|
+
'path' => 'box.img',
|
111
|
+
'name' => 'send_box_name',
|
112
|
+
},
|
113
|
+
{
|
114
|
+
'path' => 'disk.qcow2',
|
115
|
+
},
|
116
|
+
{
|
117
|
+
'path' => 'box_2.img',
|
118
|
+
},
|
119
|
+
],
|
120
|
+
]}
|
121
|
+
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
122
|
+
'/test/'.concat(arg.to_s)
|
123
|
+
end
|
124
|
+
allow(status).to receive(:success?).and_return(true)
|
125
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/box.img').and_return([
|
126
|
+
"image: /test/box.img\nfile format: qcow2\nvirtual size: 5 GiB (5368709120 bytes)\ndisk size: 1.45 GiB\n", "", status
|
127
|
+
])
|
128
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/disk.qcow2').and_return([
|
129
|
+
"image: /test/disk.qcow2\nfile format: qcow2\nvirtual size: 10 GiB (10737418240 bytes)\ndisk size: 1.45 GiB\n", "", status
|
130
|
+
])
|
131
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/box_2.img').and_return([
|
132
|
+
"image: /test/box_2.img\nfile format: qcow2\nvirtual size: 20 GiB (21474836480 bytes)\ndisk size: 1.45 GiB\n", "", status
|
133
|
+
])
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should have three disks in machine env' do
|
137
|
+
expect(subject.call(env)).to be_nil
|
138
|
+
expect(env[:box_volume_number]).to eq(3)
|
139
|
+
expect(env[:box_volumes]).to eq(
|
140
|
+
[
|
141
|
+
{
|
142
|
+
:path=>"/test/box.img",
|
143
|
+
:name=>"test_vagrant_box_image_1.1.1_send_box_name.img",
|
144
|
+
:virtual_size=>5,
|
145
|
+
:format=>"qcow2"
|
146
|
+
},
|
147
|
+
{
|
148
|
+
:path=>"/test/disk.qcow2",
|
149
|
+
:name=>"test_vagrant_box_image_1.1.1_disk.img",
|
150
|
+
:virtual_size=>10,
|
151
|
+
:format=>"qcow2"
|
152
|
+
},
|
153
|
+
{
|
154
|
+
:path=>"/test/box_2.img",
|
155
|
+
:name=>"test_vagrant_box_image_1.1.1_box_2.img",
|
156
|
+
:virtual_size=>20,
|
157
|
+
:format=>"qcow2"
|
158
|
+
}
|
159
|
+
]
|
160
|
+
)
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'when none of the disks in storage pool' do
|
164
|
+
before do
|
165
|
+
allow(File).to receive(:exist?).and_return(true)
|
166
|
+
allow(File).to receive(:size).and_return(5*1024*1024*1024, 10*1024*1024*1024, 20*1024*1024*1024)
|
167
|
+
allow(all).to receive(:first).and_return(nil)
|
168
|
+
allow(subject).to receive(:upload_image).and_return(true)
|
169
|
+
allow(volumes).to receive(:create).and_return(fog_volume)
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'should upload all 3 disks' do
|
173
|
+
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
174
|
+
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_send_box_name.img in storage pool default.')
|
175
|
+
expect(volumes).to receive(:create).with(
|
176
|
+
hash_including(
|
177
|
+
:name => "test_vagrant_box_image_1.1.1_send_box_name.img",
|
178
|
+
:allocation => "5120M",
|
179
|
+
:capacity => "5G",
|
180
|
+
)
|
181
|
+
)
|
182
|
+
expect(subject).to receive(:upload_image)
|
183
|
+
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
184
|
+
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_disk.img in storage pool default.')
|
185
|
+
expect(volumes).to receive(:create).with(
|
186
|
+
hash_including(
|
187
|
+
:name => "test_vagrant_box_image_1.1.1_disk.img",
|
188
|
+
:allocation => "10240M",
|
189
|
+
:capacity => "10G",
|
190
|
+
)
|
191
|
+
)
|
192
|
+
expect(subject).to receive(:upload_image)
|
193
|
+
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
194
|
+
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_box_2.img in storage pool default.')
|
195
|
+
expect(volumes).to receive(:create).with(
|
196
|
+
hash_including(
|
197
|
+
:name => "test_vagrant_box_image_1.1.1_box_2.img",
|
198
|
+
:allocation => "20480M",
|
199
|
+
:capacity => "20G",
|
200
|
+
)
|
201
|
+
)
|
202
|
+
expect(subject).to receive(:upload_image)
|
203
|
+
|
204
|
+
expect(subject.call(env)).to be_nil
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context 'when only disk 0 in storage pool' do
|
209
|
+
before do
|
210
|
+
allow(File).to receive(:exist?).and_return(true)
|
211
|
+
allow(File).to receive(:size).and_return(10*1024*1024*1024, 20*1024*1024*1024)
|
212
|
+
allow(all).to receive(:first).and_return(box_volume, nil, nil)
|
213
|
+
allow(box_volume).to receive(:id).and_return(1)
|
214
|
+
allow(subject).to receive(:upload_image).and_return(true)
|
215
|
+
allow(volumes).to receive(:create).and_return(fog_volume)
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'upload disks 1 and 2 only' do
|
219
|
+
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
220
|
+
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_disk.img in storage pool default.')
|
221
|
+
expect(volumes).to receive(:create).with(hash_including(:name => "test_vagrant_box_image_1.1.1_disk.img"))
|
222
|
+
expect(subject).to receive(:upload_image)
|
223
|
+
expect(ui).to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
224
|
+
expect(logger).to receive(:info).with('Creating volume test_vagrant_box_image_1.1.1_box_2.img in storage pool default.')
|
225
|
+
expect(volumes).to receive(:create).with(hash_including(:name => "test_vagrant_box_image_1.1.1_box_2.img"))
|
226
|
+
expect(subject).to receive(:upload_image)
|
227
|
+
|
228
|
+
expect(subject.call(env)).to be_nil
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
context 'when has all disks on storage pool' do
|
233
|
+
before do
|
234
|
+
allow(all).to receive(:first).and_return(box_volume)
|
235
|
+
allow(box_volume).to receive(:id).and_return(1)
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'should skip disk upload' do
|
239
|
+
expect(ui).not_to receive(:info).with('Uploading base box image as volume into Libvirt storage...')
|
240
|
+
expect(volumes).not_to receive(:create)
|
241
|
+
expect(subject).not_to receive(:upload_image)
|
242
|
+
expect(subject.call(env)).to be_nil
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
context 'when wrong box format in metadata.json' do
|
248
|
+
before do
|
249
|
+
allow(all).to receive(:first).and_return(box_volume)
|
250
|
+
allow(box_volume).to receive(:id).and_return(1)
|
251
|
+
allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
|
252
|
+
allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
|
253
|
+
allow(env[:machine]).to receive_message_chain("box.metadata") { Hash[
|
254
|
+
'virtual_size'=> 5,
|
255
|
+
'format' => 'wrongFormat'
|
256
|
+
]
|
257
|
+
}
|
258
|
+
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
259
|
+
'/test/'.concat(arg.to_s)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
it 'should raise WrongBoxFormatSet exception' do
|
264
|
+
expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::WrongBoxFormatSet)
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
context 'when invalid format in metadata.json' do
|
270
|
+
let(:status) { double }
|
271
|
+
|
272
|
+
before do
|
273
|
+
allow(all).to receive(:first).and_return(box_volume)
|
274
|
+
allow(box_volume).to receive(:id).and_return(1)
|
275
|
+
allow(env[:machine]).to receive_message_chain("box.name") { 'test' }
|
276
|
+
allow(env[:machine]).to receive_message_chain("box.version") { '1.1.1' }
|
277
|
+
allow(env[:machine]).to receive_message_chain("box.metadata") { box_metadata }
|
278
|
+
allow(env[:machine]).to receive_message_chain("box.directory.join") do |arg|
|
279
|
+
'/test/'.concat(arg.to_s)
|
280
|
+
end
|
281
|
+
allow(status).to receive(:success?).and_return(true)
|
282
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/box.img').and_return([
|
283
|
+
"image: /test/box.img\nfile format: qcow2\nvirtual size: 5 GiB (5368709120 bytes)\ndisk size: 1.45 GiB\n", "", status
|
284
|
+
])
|
285
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/disk.qcow2').and_return([
|
286
|
+
"image: /test/disk.qcow2\nfile format: qcow2\nvirtual size: 10 GiB (10737418240 bytes)\ndisk size: 1.45 GiB\n", "", status
|
287
|
+
])
|
288
|
+
allow(Open3).to receive(:capture3).with('qemu-img', 'info', '/test/box_2.img').and_return([
|
289
|
+
"image: /test/box_2.img\nfile format: qcow2\nvirtual size: 20 GiB (21474836480 bytes)\ndisk size: 1.45 GiB\n", "", status
|
290
|
+
])
|
291
|
+
end
|
292
|
+
|
293
|
+
context 'with one disk having wrong disk format' do
|
294
|
+
let(:box_metadata) {
|
295
|
+
Hash[
|
296
|
+
'disks' => [
|
297
|
+
{
|
298
|
+
'path' => 'box.img',
|
299
|
+
'name' =>'send_box_name.img',
|
300
|
+
'format' => 'wrongFormat'
|
301
|
+
},
|
302
|
+
{
|
303
|
+
'path' => 'disk.qcow2',
|
304
|
+
},
|
305
|
+
{
|
306
|
+
'path' => 'box_2.img',
|
307
|
+
},
|
308
|
+
],
|
309
|
+
]
|
310
|
+
}
|
311
|
+
|
312
|
+
it 'should be ignored' do
|
313
|
+
expect(subject.call(env)).to be_nil
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
context 'with one disk missing path' do
|
318
|
+
let(:box_metadata) {
|
319
|
+
Hash[
|
320
|
+
'disks' => [
|
321
|
+
{
|
322
|
+
'path' => 'box.img',
|
323
|
+
},
|
324
|
+
{
|
325
|
+
'name' => 'send_box_name',
|
326
|
+
},
|
327
|
+
{
|
328
|
+
'path' => 'box_2.img',
|
329
|
+
},
|
330
|
+
],
|
331
|
+
]
|
332
|
+
}
|
333
|
+
|
334
|
+
it 'should raise an exception' do
|
335
|
+
expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::BoxFormatMissingAttribute, /: 'disks\[1\]\['path'\]'/)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
context 'with one disk name duplicating a path of another' do
|
340
|
+
let(:box_metadata) {
|
341
|
+
Hash[
|
342
|
+
'disks' => [
|
343
|
+
{
|
344
|
+
'path' => 'box.img',
|
345
|
+
'name' => 'box_2',
|
346
|
+
},
|
347
|
+
{
|
348
|
+
'path' => 'disk.qcow2',
|
349
|
+
},
|
350
|
+
{
|
351
|
+
'path' => 'box_2.img',
|
352
|
+
},
|
353
|
+
],
|
354
|
+
]
|
355
|
+
}
|
356
|
+
|
357
|
+
it 'should raise an exception' do
|
358
|
+
expect{ subject.call(env) }.to raise_error(VagrantPlugins::ProviderLibvirt::Errors::BoxFormatDuplicateVolume, /test_vagrant_box_image_1.1.1_box_2.img.*'disks\[2\]'.*'disks\[0\]'/)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|