vagrant-libvirt 0.1.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|