vagrant-libvirt 0.1.2 → 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 +530 -100
- data/lib/vagrant-libvirt/action.rb +7 -1
- data/lib/vagrant-libvirt/action/clean_machine_folder.rb +28 -0
- data/lib/vagrant-libvirt/action/create_domain.rb +78 -22
- data/lib/vagrant-libvirt/action/create_domain_volume.rb +57 -57
- data/lib/vagrant-libvirt/action/create_network_interfaces.rb +1 -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 +40 -40
- data/lib/vagrant-libvirt/action/halt_domain.rb +25 -9
- data/lib/vagrant-libvirt/action/handle_box_image.rb +163 -72
- 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/package_domain.rb +10 -4
- data/lib/vagrant-libvirt/action/start_domain.rb +86 -29
- data/lib/vagrant-libvirt/action/wait_till_up.rb +8 -52
- 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/public_address.rb +16 -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 +257 -34
- data/lib/vagrant-libvirt/driver.rb +49 -32
- data/lib/vagrant-libvirt/errors.rb +24 -1
- data/lib/vagrant-libvirt/plugin.rb +19 -5
- data/lib/vagrant-libvirt/provider.rb +2 -9
- data/lib/vagrant-libvirt/templates/domain.xml.erb +40 -10
- data/lib/vagrant-libvirt/templates/private_network.xml.erb +1 -1
- data/lib/vagrant-libvirt/templates/public_interface.xml.erb +5 -1
- data/lib/vagrant-libvirt/util.rb +1 -0
- data/lib/vagrant-libvirt/util/erb_template.rb +6 -7
- data/lib/vagrant-libvirt/util/network_util.rb +21 -3
- data/lib/vagrant-libvirt/util/ui.rb +23 -0
- data/lib/vagrant-libvirt/version +1 -0
- data/lib/vagrant-libvirt/version.rb +72 -1
- data/locales/en.yml +12 -0
- data/spec/spec_helper.rb +37 -3
- data/spec/support/binding_proc.rb +24 -0
- data/spec/support/libvirt_context.rb +3 -1
- data/spec/support/matchers/have_file_content.rb +63 -0
- data/spec/support/sharedcontext.rb +7 -3
- data/spec/unit/action/clean_machine_folder_spec.rb +48 -0
- data/spec/unit/action/create_domain_spec.rb +166 -0
- data/spec/unit/action/create_domain_spec/default_system_storage_pool.xml +17 -0
- data/spec/unit/action/create_domain_spec/default_user_storage_pool.xml +17 -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 +3 -3
- 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/set_name_of_domain_spec.rb +2 -2
- data/spec/unit/action/start_domain_spec.rb +231 -0
- data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +50 -0
- data/spec/unit/action/start_domain_spec/default.xml +48 -0
- data/spec/unit/action/start_domain_spec/default_added_tpm_path.xml +48 -0
- data/spec/unit/action/start_domain_spec/default_added_tpm_version.xml +48 -0
- data/spec/unit/action/wait_till_up_spec.rb +22 -21
- data/spec/unit/config_spec.rb +438 -0
- data/spec/unit/provider_spec.rb +11 -0
- data/spec/unit/templates/domain_all_settings.xml +16 -3
- data/spec/unit/templates/domain_custom_cpu_model.xml +4 -1
- data/spec/unit/templates/domain_defaults.xml +4 -1
- data/spec/unit/templates/domain_spec.rb +102 -3
- data/spec/unit/templates/tpm/version_1.2.xml +54 -0
- data/spec/unit/templates/tpm/version_2.0.xml +53 -0
- metadata +108 -16
- data/lib/vagrant-libvirt/action/halt_confirm.rb +0 -20
@@ -11,10 +11,8 @@ module VagrantPlugins
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def call(env)
|
14
|
-
@env = env
|
15
|
-
|
16
14
|
# Get the ports we're forwarding
|
17
|
-
env[:forwarded_ports] = compile_forwarded_ports(env[:machine].config)
|
15
|
+
env[:forwarded_ports] = compile_forwarded_ports(env, env[:machine].config)
|
18
16
|
|
19
17
|
# Warn if we're port forwarding to any privileged ports
|
20
18
|
env[:forwarded_ports].each do |fp|
|
@@ -28,51 +26,52 @@ module VagrantPlugins
|
|
28
26
|
# Continue, we need the VM to be booted in order to grab its IP
|
29
27
|
@app.call env
|
30
28
|
|
31
|
-
if
|
29
|
+
if env[:forwarded_ports].any?
|
32
30
|
env[:ui].info I18n.t('vagrant.actions.vm.forward_ports.forwarding')
|
33
|
-
forward_ports
|
31
|
+
forward_ports(env)
|
34
32
|
end
|
35
33
|
end
|
36
34
|
|
37
|
-
def forward_ports
|
38
|
-
|
35
|
+
def forward_ports(env)
|
36
|
+
env[:forwarded_ports].each do |fp|
|
39
37
|
message_attributes = {
|
40
38
|
adapter: fp[:adapter] || 'eth0',
|
41
39
|
guest_port: fp[:guest],
|
42
40
|
host_port: fp[:host]
|
43
41
|
}
|
44
42
|
|
45
|
-
|
43
|
+
env[:ui].info(I18n.t(
|
46
44
|
'vagrant.actions.vm.forward_ports.forwarding_entry',
|
47
|
-
message_attributes
|
45
|
+
**message_attributes
|
48
46
|
))
|
49
47
|
|
50
|
-
if fp[:protocol] == 'udp'
|
51
|
-
@env[:ui].warn I18n.t('vagrant_libvirt.warnings.forwarding_udp')
|
52
|
-
next
|
53
|
-
end
|
54
|
-
|
55
48
|
ssh_pid = redirect_port(
|
56
|
-
|
49
|
+
env,
|
50
|
+
env[:machine],
|
57
51
|
fp[:host_ip] || '*',
|
58
52
|
fp[:host],
|
59
|
-
fp[:guest_ip] ||
|
53
|
+
fp[:guest_ip] || env[:machine].provider.ssh_info[:host],
|
60
54
|
fp[:guest],
|
61
55
|
fp[:gateway_ports] || false
|
62
56
|
)
|
63
|
-
store_ssh_pid(fp[:host], ssh_pid)
|
57
|
+
store_ssh_pid(env[:machine], fp[:host], ssh_pid)
|
64
58
|
end
|
65
59
|
end
|
66
60
|
|
67
61
|
private
|
68
62
|
|
69
|
-
def compile_forwarded_ports(config)
|
63
|
+
def compile_forwarded_ports(env, config)
|
70
64
|
mappings = {}
|
71
65
|
|
72
66
|
config.vm.networks.each do |type, options|
|
73
67
|
next if options[:disabled]
|
74
68
|
|
75
|
-
|
69
|
+
if options[:protocol] == 'udp'
|
70
|
+
env[:ui].warn I18n.t('vagrant_libvirt.warnings.forwarding_udp')
|
71
|
+
next
|
72
|
+
end
|
73
|
+
|
74
|
+
next if type != :forwarded_port || ( options[:id] == 'ssh' && !env[:machine].provider_config.forward_ssh_port )
|
76
75
|
if options.fetch(:host_ip, '').to_s.strip.empty?
|
77
76
|
options.delete(:host_ip)
|
78
77
|
end
|
@@ -82,7 +81,7 @@ module VagrantPlugins
|
|
82
81
|
mappings.values
|
83
82
|
end
|
84
83
|
|
85
|
-
def redirect_port(machine, host_ip, host_port, guest_ip, guest_port,
|
84
|
+
def redirect_port(env, machine, host_ip, host_port, guest_ip, guest_port,
|
86
85
|
gateway_ports)
|
87
86
|
ssh_info = machine.ssh_info
|
88
87
|
params = %W(
|
@@ -98,6 +97,7 @@ module VagrantPlugins
|
|
98
97
|
Port=#{ssh_info[:port]}
|
99
98
|
UserKnownHostsFile=/dev/null
|
100
99
|
ExitOnForwardFailure=yes
|
100
|
+
ControlMaster=no
|
101
101
|
StrictHostKeyChecking=no
|
102
102
|
PasswordAuthentication=no
|
103
103
|
ForwardX11=#{ssh_info[:forward_x11] ? 'yes' : 'no'}
|
@@ -106,14 +106,14 @@ module VagrantPlugins
|
|
106
106
|
"IdentityFile='\"#{pk}\"'"
|
107
107
|
end).map { |s| s.prepend('-o ') }.join(' ')
|
108
108
|
|
109
|
-
options += " -o ProxyCommand=\"#{ssh_info[:proxy_command]}\"" if machine.provider_config.
|
109
|
+
options += " -o ProxyCommand=\"#{ssh_info[:proxy_command]}\"" if machine.provider_config.proxy_command
|
110
110
|
|
111
111
|
# TODO: instead of this, try and lock and get the stdin from spawn...
|
112
|
-
ssh_cmd = '
|
112
|
+
ssh_cmd = ''
|
113
113
|
if host_port <= 1024
|
114
114
|
@@lock.synchronize do
|
115
115
|
# TODO: add i18n
|
116
|
-
|
116
|
+
env[:ui].info 'Requesting sudo for host port(s) <= 1024'
|
117
117
|
r = system('sudo -v')
|
118
118
|
if r
|
119
119
|
ssh_cmd << 'sudo ' # add sudo prefix
|
@@ -124,14 +124,15 @@ module VagrantPlugins
|
|
124
124
|
ssh_cmd << "ssh -n #{options} #{params}"
|
125
125
|
|
126
126
|
@logger.debug "Forwarding port with `#{ssh_cmd}`"
|
127
|
-
log_file = ssh_forward_log_file(
|
128
|
-
|
127
|
+
log_file = ssh_forward_log_file(
|
128
|
+
env[:machine], host_ip, host_port, guest_ip, guest_port,
|
129
|
+
)
|
129
130
|
@logger.info "Logging to #{log_file}"
|
130
|
-
spawn(ssh_cmd, [:out, :err] => [log_file, 'w'])
|
131
|
+
spawn(ssh_cmd, [:out, :err] => [log_file, 'w'], :pgroup => true)
|
131
132
|
end
|
132
133
|
|
133
|
-
def ssh_forward_log_file(host_ip, host_port, guest_ip, guest_port)
|
134
|
-
log_dir =
|
134
|
+
def ssh_forward_log_file(machine, host_ip, host_port, guest_ip, guest_port)
|
135
|
+
log_dir = machine.data_dir.join('logs')
|
135
136
|
log_dir.mkdir unless log_dir.directory?
|
136
137
|
File.join(
|
137
138
|
log_dir,
|
@@ -140,8 +141,8 @@ module VagrantPlugins
|
|
140
141
|
)
|
141
142
|
end
|
142
143
|
|
143
|
-
def store_ssh_pid(host_port, ssh_pid)
|
144
|
-
data_dir =
|
144
|
+
def store_ssh_pid(machine, host_port, ssh_pid)
|
145
|
+
data_dir = machine.data_dir.join('pids')
|
145
146
|
data_dir.mkdir unless data_dir.directory?
|
146
147
|
|
147
148
|
data_dir.join("ssh_#{host_port}.pid").open('w') do |pid_file|
|
@@ -168,13 +169,12 @@ module VagrantPlugins
|
|
168
169
|
end
|
169
170
|
|
170
171
|
def call(env)
|
171
|
-
|
172
|
-
|
173
|
-
if ssh_pids.any?
|
172
|
+
pids = ssh_pids(env[:machine])
|
173
|
+
if pids.any?
|
174
174
|
env[:ui].info I18n.t(
|
175
175
|
'vagrant.actions.vm.clear_forward_ports.deleting'
|
176
176
|
)
|
177
|
-
|
177
|
+
pids.each do |tag|
|
178
178
|
next unless ssh_pid?(tag[:pid])
|
179
179
|
@logger.debug "Killing pid #{tag[:pid]}"
|
180
180
|
kill_cmd = ''
|
@@ -190,7 +190,7 @@ module VagrantPlugins
|
|
190
190
|
end
|
191
191
|
|
192
192
|
@logger.info 'Removing ssh pid files'
|
193
|
-
remove_ssh_pids
|
193
|
+
remove_ssh_pids(env[:machine])
|
194
194
|
else
|
195
195
|
@logger.info 'No ssh pids found'
|
196
196
|
end
|
@@ -200,9 +200,9 @@ module VagrantPlugins
|
|
200
200
|
|
201
201
|
protected
|
202
202
|
|
203
|
-
def ssh_pids
|
204
|
-
glob =
|
205
|
-
|
203
|
+
def ssh_pids(machine)
|
204
|
+
glob = machine.data_dir.join('pids').to_s + '/ssh_*.pid'
|
205
|
+
ssh_pids = Dir[glob].map do |file|
|
206
206
|
{
|
207
207
|
pid: File.read(file).strip.chomp,
|
208
208
|
port: File.basename(file)['ssh_'.length..-1 * ('.pid'.length + 1)].to_i
|
@@ -216,8 +216,8 @@ module VagrantPlugins
|
|
216
216
|
`ps -o command= #{pid}`.strip.chomp =~ /ssh/
|
217
217
|
end
|
218
218
|
|
219
|
-
def remove_ssh_pids
|
220
|
-
glob =
|
219
|
+
def remove_ssh_pids(machine)
|
220
|
+
glob = machine.data_dir.join('pids').to_s + '/ssh_*.pid'
|
221
221
|
Dir[glob].each do |file|
|
222
222
|
File.delete file
|
223
223
|
end
|
@@ -13,24 +13,40 @@ module VagrantPlugins
|
|
13
13
|
def call(env)
|
14
14
|
env[:ui].info(I18n.t('vagrant_libvirt.halt_domain'))
|
15
15
|
|
16
|
+
timeout = env[:machine].config.vm.graceful_halt_timeout
|
16
17
|
domain = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
17
18
|
raise Errors::NoDomainError if domain.nil?
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@logger.info('Trying Libvirt graceful shutdown.')
|
23
|
-
domain.shutdown
|
20
|
+
if env[:force_halt]
|
21
|
+
domain.poweroff
|
22
|
+
return @app.call(env)
|
24
23
|
end
|
25
24
|
|
26
|
-
|
27
25
|
begin
|
28
|
-
|
29
|
-
|
26
|
+
Timeout.timeout(timeout) do
|
27
|
+
begin
|
28
|
+
env[:machine].guest.capability(:halt)
|
29
|
+
rescue Timeout::Error
|
30
|
+
raise
|
31
|
+
rescue
|
32
|
+
@logger.info('Trying Libvirt graceful shutdown.')
|
33
|
+
# Read domain object again
|
34
|
+
dom = env[:machine].provider.driver.connection.servers.get(env[:machine].id.to_s)
|
35
|
+
if dom.state.to_s == 'running'
|
36
|
+
dom.shutdown
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
domain.wait_for(timeout) do
|
41
|
+
!ready?
|
42
|
+
end
|
30
43
|
end
|
31
|
-
rescue
|
44
|
+
rescue Timeout::Error
|
32
45
|
@logger.info('VM is still running. Calling force poweroff.')
|
33
46
|
domain.poweroff
|
47
|
+
rescue
|
48
|
+
@logger.error('Failed to shutdown cleanly. Calling force poweroff.')
|
49
|
+
domain.poweroff
|
34
50
|
end
|
35
51
|
|
36
52
|
@app.call(env)
|
@@ -5,6 +5,7 @@ module VagrantPlugins
|
|
5
5
|
module Action
|
6
6
|
class HandleBoxImage
|
7
7
|
include VagrantPlugins::ProviderLibvirt::Util::StorageUtil
|
8
|
+
include VagrantPlugins::ProviderLibvirt::Util::Ui
|
8
9
|
|
9
10
|
|
10
11
|
@@lock = Mutex.new
|
@@ -15,33 +16,69 @@ module VagrantPlugins
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def call(env)
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# Virtual size has to be set for allocating space in storage pool.
|
21
|
-
box_virtual_size = env[:machine].box.metadata['virtual_size']
|
22
|
-
raise Errors::NoBoxVirtualSizeSet if box_virtual_size.nil?
|
19
|
+
# Handle box formats converting between v1 => v2 and ensuring
|
20
|
+
# any obsolete settings are rejected.
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
disks = env[:machine].box.metadata.fetch('disks', [])
|
23
|
+
if disks.empty?
|
24
|
+
# Handle box v1 format
|
25
|
+
|
26
|
+
# Only qcow2 format is supported in v1, but other formats with backing
|
27
|
+
# store capability should be usable.
|
28
|
+
box_format = env[:machine].box.metadata['format']
|
29
|
+
HandleBoxImage.verify_box_format(box_format)
|
30
|
+
|
31
|
+
env[:box_volume_number] = 1
|
32
|
+
env[:box_volumes] = [{
|
33
|
+
:path => HandleBoxImage.get_box_image_path(env[:machine].box, 'box.img'),
|
34
|
+
:name => HandleBoxImage.get_volume_name(env[:machine].box, 'box'),
|
35
|
+
:virtual_size => HandleBoxImage.get_virtual_size(env),
|
36
|
+
:format => box_format,
|
37
|
+
}]
|
38
|
+
else
|
39
|
+
# Handle box v2 format
|
40
|
+
# {
|
41
|
+
# 'path': '<path-of-file-box>',
|
42
|
+
# 'name': '<name-to-use-in-storage>' # optional, will use index
|
43
|
+
# }
|
44
|
+
#
|
45
|
+
env[:box_volume_number] = disks.length()
|
46
|
+
target_volumes = Hash[]
|
47
|
+
env[:box_volumes] = Array.new(env[:box_volume_number]) { |i|
|
48
|
+
raise Errors::BoxFormatMissingAttribute, attribute: "disks[#{i}]['path']" if disks[i]['path'].nil?
|
49
|
+
|
50
|
+
image_path = HandleBoxImage.get_box_image_path(env[:machine].box, disks[i]['path'])
|
51
|
+
format, virtual_size = HandleBoxImage.get_box_disk_settings(image_path)
|
52
|
+
volume_name = HandleBoxImage.get_volume_name(
|
53
|
+
env[:machine].box,
|
54
|
+
disks[i].fetch('name', disks[i]['path'].sub(/#{File.extname(disks[i]['path'])}$/, '')),
|
55
|
+
)
|
56
|
+
|
57
|
+
# allowing name means needing to check that it doesn't cause a clash
|
58
|
+
existing = target_volumes[volume_name]
|
59
|
+
if !existing.nil?
|
60
|
+
raise Errors::BoxFormatDuplicateVolume, volume: volume_name, new_disk: "disks[#{i}]", orig_disk: "disks[#{existing}]"
|
61
|
+
end
|
62
|
+
target_volumes[volume_name] = i
|
63
|
+
|
64
|
+
{
|
65
|
+
:path => image_path,
|
66
|
+
:name => volume_name,
|
67
|
+
:virtual_size => virtual_size.to_i,
|
68
|
+
:format => HandleBoxImage.verify_box_format(format)
|
69
|
+
}
|
70
|
+
}
|
31
71
|
end
|
32
72
|
|
33
73
|
# Get config options
|
34
74
|
config = env[:machine].provider_config
|
35
|
-
|
36
|
-
env[:
|
37
|
-
|
38
|
-
|
39
|
-
env[:machine].box.version.to_s
|
40
|
-
rescue
|
41
|
-
''
|
42
|
-
end}.img"
|
75
|
+
box_image_files = []
|
76
|
+
env[:box_volumes].each do |d|
|
77
|
+
box_image_files.push(d[:path])
|
78
|
+
end
|
43
79
|
|
44
80
|
# Override box_virtual_size
|
81
|
+
box_virtual_size = env[:box_volumes][0][:virtual_size]
|
45
82
|
if config.machine_virtual_size
|
46
83
|
if config.machine_virtual_size < box_virtual_size
|
47
84
|
# Warn that a virtual size less than the box metadata size
|
@@ -56,75 +93,129 @@ module VagrantPlugins
|
|
56
93
|
end
|
57
94
|
end
|
58
95
|
# save for use by later actions
|
59
|
-
env[:
|
96
|
+
env[:box_volumes][0][:virtual_size] = box_virtual_size
|
60
97
|
|
61
98
|
# while inside the synchronize block take care not to call the next
|
62
99
|
# action in the chain, as must exit this block first to prevent
|
63
100
|
# locking all subsequent actions as well.
|
64
101
|
@@lock.synchronize do
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
env[:ui].info(I18n.t('vagrant_libvirt.uploading_volume'))
|
74
|
-
|
75
|
-
# Create new volume in storage pool
|
76
|
-
unless File.exist?(box_image_file)
|
77
|
-
raise Vagrant::Errors::BoxNotFound, name: env[:machine].box.name
|
102
|
+
env[:box_volumes].each_index do |i|
|
103
|
+
# Don't continue if image already exists in storage pool.
|
104
|
+
box_volume = env[:machine].provider.driver.connection.volumes.all(
|
105
|
+
name: env[:box_volumes][i][:name]
|
106
|
+
).first
|
107
|
+
next if box_volume && box_volume.id
|
108
|
+
|
109
|
+
send_box_image(env, config, box_image_files[i], env[:box_volumes][i])
|
78
110
|
end
|
79
|
-
|
80
|
-
message = "Creating volume #{env[:box_volume_name]}"
|
81
|
-
message << " in storage pool #{config.storage_pool_name}."
|
82
|
-
@logger.info(message)
|
111
|
+
end
|
83
112
|
|
84
|
-
|
85
|
-
|
113
|
+
@app.call(env)
|
114
|
+
end
|
115
|
+
|
116
|
+
protected
|
86
117
|
|
118
|
+
def self.get_volume_name(box, name)
|
119
|
+
vol_name = box.name.to_s.dup.gsub('/', '-VAGRANTSLASH-')
|
120
|
+
vol_name << "_vagrant_box_image_#{
|
87
121
|
begin
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
capacity: "#{box_virtual_size}G",
|
92
|
-
format_type: box_format,
|
93
|
-
owner: @storage_volume_uid,
|
94
|
-
group: @storage_volume_gid,
|
95
|
-
pool_name: config.storage_pool_name
|
96
|
-
)
|
97
|
-
rescue Fog::Errors::Error => e
|
98
|
-
raise Errors::FogCreateVolumeError,
|
99
|
-
error_message: e.message
|
122
|
+
box.version.to_s
|
123
|
+
rescue
|
124
|
+
''
|
100
125
|
end
|
126
|
+
}_#{name.dup.gsub('/', '-SLASH-')}.img"
|
127
|
+
end
|
101
128
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
129
|
+
def self.get_virtual_size(env)
|
130
|
+
# Virtual size has to be set for allocating space in storage pool.
|
131
|
+
box_virtual_size = env[:machine].box.metadata['virtual_size']
|
132
|
+
raise Errors::NoBoxVirtualSizeSet if box_virtual_size.nil?
|
133
|
+
return box_virtual_size
|
134
|
+
end
|
108
135
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
136
|
+
def self.get_box_image_path(box, box_name)
|
137
|
+
return box.directory.join(box_name).to_s
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.verify_box_format(box_format, disk_index=nil)
|
141
|
+
if box_format.nil?
|
142
|
+
raise Errors::NoBoxFormatSet
|
143
|
+
elsif box_format != 'qcow2'
|
144
|
+
if disk_index.nil?
|
145
|
+
raise Errors::WrongBoxFormatSet
|
146
|
+
else
|
147
|
+
raise Errors::WrongDiskFormatSet,
|
148
|
+
disk_index: disk_index
|
121
149
|
end
|
122
150
|
end
|
151
|
+
return box_format
|
152
|
+
end
|
123
153
|
|
124
|
-
|
154
|
+
def self.get_box_disk_settings(image_path)
|
155
|
+
stdout, stderr, status = Open3.capture3('qemu-img', 'info', image_path)
|
156
|
+
if !status.success?
|
157
|
+
raise Errors::BadBoxImage, image: image_path, out: stdout, err: stderr
|
158
|
+
end
|
159
|
+
|
160
|
+
image_info_lines = stdout.split("\n")
|
161
|
+
format = image_info_lines.find { |l| l.start_with?('file format:') }.split(' ')[2]
|
162
|
+
virtual_size = image_info_lines.find { |l| l.start_with?('virtual size:') }.split(' ')[2]
|
163
|
+
|
164
|
+
return format, virtual_size
|
125
165
|
end
|
126
166
|
|
127
|
-
|
167
|
+
def send_box_image(env, config, box_image_file, box_volume)
|
168
|
+
# Box is not available as a storage pool volume. Create and upload
|
169
|
+
# it as a copy of local box image.
|
170
|
+
env[:ui].info(I18n.t('vagrant_libvirt.uploading_volume'))
|
171
|
+
|
172
|
+
# Create new volume in storage pool
|
173
|
+
unless File.exist?(box_image_file)
|
174
|
+
raise Vagrant::Errors::BoxNotFound, name: env[:machine].box.name
|
175
|
+
end
|
176
|
+
box_image_size = File.size(box_image_file) # B
|
177
|
+
message = "Creating volume #{box_volume[:name]}"
|
178
|
+
message << " in storage pool #{config.storage_pool_name}."
|
179
|
+
@logger.info(message)
|
180
|
+
|
181
|
+
begin
|
182
|
+
fog_volume = env[:machine].provider.driver.connection.volumes.create(
|
183
|
+
name: box_volume[:name],
|
184
|
+
allocation: "#{box_image_size / 1024 / 1024}M",
|
185
|
+
capacity: "#{box_volume[:virtual_size]}G",
|
186
|
+
format_type: box_volume[:format],
|
187
|
+
owner: storage_uid(env),
|
188
|
+
group: storage_gid(env),
|
189
|
+
pool_name: config.storage_pool_name
|
190
|
+
)
|
191
|
+
rescue Fog::Errors::Error => e
|
192
|
+
raise Errors::FogCreateVolumeError,
|
193
|
+
error_message: e.message
|
194
|
+
end
|
195
|
+
|
196
|
+
# Upload box image to storage pool
|
197
|
+
ret = upload_image(box_image_file, config.storage_pool_name,
|
198
|
+
box_volume[:name], env) do |progress|
|
199
|
+
rewriting(env[:ui]) do |ui|
|
200
|
+
ui.clear_line
|
201
|
+
ui.report_progress(progress, box_image_size, false)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Clear the line one last time since the progress meter doesn't
|
206
|
+
# disappear immediately.
|
207
|
+
rewriting(env[:ui]) {|ui| ui.clear_line}
|
208
|
+
|
209
|
+
# If upload failed or was interrupted, remove created volume from
|
210
|
+
# storage pool.
|
211
|
+
if env[:interrupted] || !ret
|
212
|
+
begin
|
213
|
+
fog_volume.destroy
|
214
|
+
rescue
|
215
|
+
nil
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
128
219
|
|
129
220
|
# Fog Libvirt currently doesn't support uploading images to storage
|
130
221
|
# pool volumes. Use ruby-libvirt client instead.
|