vagrant-libvirt 0.0.40 → 0.0.41
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- metadata +13 -103
- data/.coveralls.yml +0 -1
- data/.github/issue_template.md +0 -37
- data/.gitignore +0 -21
- data/.travis.yml +0 -28
- data/CHANGELOG.md +0 -99
- data/Gemfile +0 -27
- data/LICENSE +0 -22
- data/README.md +0 -1311
- data/Rakefile +0 -8
- data/example_box/README.md +0 -29
- data/example_box/Vagrantfile +0 -60
- data/example_box/metadata.json +0 -5
- data/lib/vagrant-libvirt.rb +0 -29
- data/lib/vagrant-libvirt/action.rb +0 -362
- data/lib/vagrant-libvirt/action/create_domain.rb +0 -313
- data/lib/vagrant-libvirt/action/create_domain_volume.rb +0 -87
- data/lib/vagrant-libvirt/action/create_network_interfaces.rb +0 -294
- data/lib/vagrant-libvirt/action/create_networks.rb +0 -353
- data/lib/vagrant-libvirt/action/destroy_domain.rb +0 -83
- data/lib/vagrant-libvirt/action/destroy_networks.rb +0 -95
- data/lib/vagrant-libvirt/action/forward_ports.rb +0 -221
- data/lib/vagrant-libvirt/action/halt_domain.rb +0 -35
- data/lib/vagrant-libvirt/action/handle_box_image.rb +0 -156
- data/lib/vagrant-libvirt/action/handle_storage_pool.rb +0 -57
- data/lib/vagrant-libvirt/action/is_created.rb +0 -18
- data/lib/vagrant-libvirt/action/is_running.rb +0 -21
- data/lib/vagrant-libvirt/action/is_suspended.rb +0 -42
- data/lib/vagrant-libvirt/action/message_already_created.rb +0 -16
- data/lib/vagrant-libvirt/action/message_not_created.rb +0 -16
- data/lib/vagrant-libvirt/action/message_not_running.rb +0 -16
- data/lib/vagrant-libvirt/action/message_not_suspended.rb +0 -16
- data/lib/vagrant-libvirt/action/package_domain.rb +0 -105
- data/lib/vagrant-libvirt/action/prepare_nfs_settings.rb +0 -94
- data/lib/vagrant-libvirt/action/prepare_nfs_valid_ids.rb +0 -17
- data/lib/vagrant-libvirt/action/prune_nfs_exports.rb +0 -27
- data/lib/vagrant-libvirt/action/read_mac_addresses.rb +0 -40
- data/lib/vagrant-libvirt/action/remove_libvirt_image.rb +0 -20
- data/lib/vagrant-libvirt/action/remove_stale_volume.rb +0 -50
- data/lib/vagrant-libvirt/action/resume_domain.rb +0 -34
- data/lib/vagrant-libvirt/action/set_boot_order.rb +0 -109
- data/lib/vagrant-libvirt/action/set_name_of_domain.rb +0 -64
- data/lib/vagrant-libvirt/action/share_folders.rb +0 -71
- data/lib/vagrant-libvirt/action/start_domain.rb +0 -303
- data/lib/vagrant-libvirt/action/suspend_domain.rb +0 -40
- data/lib/vagrant-libvirt/action/wait_till_up.rb +0 -102
- data/lib/vagrant-libvirt/cap/mount_p9.rb +0 -42
- data/lib/vagrant-libvirt/cap/nic_mac_addresses.rb +0 -17
- data/lib/vagrant-libvirt/cap/synced_folder.rb +0 -113
- data/lib/vagrant-libvirt/config.rb +0 -698
- data/lib/vagrant-libvirt/driver.rb +0 -118
- data/lib/vagrant-libvirt/errors.rb +0 -149
- data/lib/vagrant-libvirt/plugin.rb +0 -92
- data/lib/vagrant-libvirt/provider.rb +0 -130
- data/lib/vagrant-libvirt/templates/default_storage_pool.xml.erb +0 -13
- data/lib/vagrant-libvirt/templates/domain.xml.erb +0 -229
- data/lib/vagrant-libvirt/templates/private_network.xml.erb +0 -34
- data/lib/vagrant-libvirt/templates/public_interface.xml.erb +0 -23
- data/lib/vagrant-libvirt/util.rb +0 -11
- data/lib/vagrant-libvirt/util/collection.rb +0 -19
- data/lib/vagrant-libvirt/util/erb_template.rb +0 -22
- data/lib/vagrant-libvirt/util/error_codes.rb +0 -100
- data/lib/vagrant-libvirt/util/network_util.rb +0 -138
- data/lib/vagrant-libvirt/util/timer.rb +0 -17
- data/lib/vagrant-libvirt/version.rb +0 -5
- data/locales/en.yml +0 -159
- data/spec/spec_helper.rb +0 -9
- data/spec/support/environment_helper.rb +0 -46
- data/spec/support/libvirt_context.rb +0 -30
- data/spec/support/sharedcontext.rb +0 -34
- data/spec/unit/action/destroy_domain_spec.rb +0 -97
- data/spec/unit/action/set_name_of_domain_spec.rb +0 -21
- data/spec/unit/action/wait_till_up_spec.rb +0 -127
- data/spec/unit/config_spec.rb +0 -106
- data/spec/unit/templates/domain_all_settings.xml +0 -133
- data/spec/unit/templates/domain_defaults.xml +0 -46
- data/spec/unit/templates/domain_spec.rb +0 -75
- data/tools/create_box.sh +0 -130
- data/tools/prepare_redhat_for_box.sh +0 -119
- data/vagrant-libvirt.gemspec +0 -28
@@ -1,313 +0,0 @@
|
|
1
|
-
require 'log4r'
|
2
|
-
|
3
|
-
module VagrantPlugins
|
4
|
-
module ProviderLibvirt
|
5
|
-
module Action
|
6
|
-
class CreateDomain
|
7
|
-
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
8
|
-
|
9
|
-
def initialize(app, _env)
|
10
|
-
@logger = Log4r::Logger.new('vagrant_libvirt::action::create_domain')
|
11
|
-
@app = app
|
12
|
-
end
|
13
|
-
|
14
|
-
def _disk_name(name, disk)
|
15
|
-
"#{name}-#{disk[:device]}.#{disk[:type]}" # disk name
|
16
|
-
end
|
17
|
-
|
18
|
-
def _disks_print(disks)
|
19
|
-
disks.collect do |x|
|
20
|
-
"#{x[:device]}(#{x[:type]},#{x[:size]})"
|
21
|
-
end.join(', ')
|
22
|
-
end
|
23
|
-
|
24
|
-
def _cdroms_print(cdroms)
|
25
|
-
cdroms.collect { |x| x[:dev] }.join(', ')
|
26
|
-
end
|
27
|
-
|
28
|
-
def call(env)
|
29
|
-
# Get config.
|
30
|
-
config = env[:machine].provider_config
|
31
|
-
|
32
|
-
# Gather some info about domain
|
33
|
-
@name = env[:domain_name]
|
34
|
-
@uuid = config.uuid
|
35
|
-
@cpus = config.cpus.to_i
|
36
|
-
@cpu_features = config.cpu_features
|
37
|
-
@features = config.features
|
38
|
-
@cpu_mode = config.cpu_mode
|
39
|
-
@cpu_model = config.cpu_model
|
40
|
-
@cpu_fallback = config.cpu_fallback
|
41
|
-
@numa_nodes = config.numa_nodes
|
42
|
-
@loader = config.loader
|
43
|
-
@machine_type = config.machine_type
|
44
|
-
@machine_arch = config.machine_arch
|
45
|
-
@disk_bus = config.disk_bus
|
46
|
-
@disk_device = config.disk_device
|
47
|
-
@nested = config.nested
|
48
|
-
@memory_size = config.memory.to_i * 1024
|
49
|
-
@management_network_mac = config.management_network_mac
|
50
|
-
@domain_volume_cache = config.volume_cache
|
51
|
-
@kernel = config.kernel
|
52
|
-
@cmd_line = config.cmd_line
|
53
|
-
@emulator_path = config.emulator_path
|
54
|
-
@initrd = config.initrd
|
55
|
-
@dtb = config.dtb
|
56
|
-
@graphics_type = config.graphics_type
|
57
|
-
@graphics_autoport = config.graphics_autoport
|
58
|
-
@graphics_port = config.graphics_port
|
59
|
-
@graphics_ip = config.graphics_ip
|
60
|
-
@graphics_passwd = if config.graphics_passwd.to_s.empty?
|
61
|
-
''
|
62
|
-
else
|
63
|
-
"passwd='#{config.graphics_passwd}'"
|
64
|
-
end
|
65
|
-
@video_type = config.video_type
|
66
|
-
@sound_type = config.sound_type
|
67
|
-
@video_vram = config.video_vram
|
68
|
-
@keymap = config.keymap
|
69
|
-
@kvm_hidden = config.kvm_hidden
|
70
|
-
|
71
|
-
@tpm_model = config.tpm_model
|
72
|
-
@tpm_type = config.tpm_type
|
73
|
-
@tpm_path = config.tpm_path
|
74
|
-
|
75
|
-
# Boot order
|
76
|
-
@boot_order = config.boot_order
|
77
|
-
|
78
|
-
# Storage
|
79
|
-
@storage_pool_name = config.storage_pool_name
|
80
|
-
@disks = config.disks
|
81
|
-
@cdroms = config.cdroms
|
82
|
-
|
83
|
-
# Input
|
84
|
-
@inputs = config.inputs
|
85
|
-
|
86
|
-
# Channels
|
87
|
-
@channels = config.channels
|
88
|
-
|
89
|
-
# PCI device passthrough
|
90
|
-
@pcis = config.pcis
|
91
|
-
|
92
|
-
# Watchdog device
|
93
|
-
@watchdog_dev = config.watchdog_dev
|
94
|
-
|
95
|
-
# USB device passthrough
|
96
|
-
@usbs = config.usbs
|
97
|
-
|
98
|
-
# Redirected devices
|
99
|
-
@redirdevs = config.redirdevs
|
100
|
-
@redirfilters = config.redirfilters
|
101
|
-
|
102
|
-
# smartcard device
|
103
|
-
@smartcard_dev = config.smartcard_dev
|
104
|
-
|
105
|
-
# RNG device passthrough
|
106
|
-
@rng = config.rng
|
107
|
-
|
108
|
-
config = env[:machine].provider_config
|
109
|
-
@domain_type = config.driver
|
110
|
-
|
111
|
-
@os_type = 'hvm'
|
112
|
-
|
113
|
-
# Get path to domain image from the storage pool selected if we have a box.
|
114
|
-
if env[:machine].config.vm.box
|
115
|
-
actual_volumes =
|
116
|
-
env[:machine].provider.driver.connection.volumes.all.select do |x|
|
117
|
-
x.pool_name == @storage_pool_name
|
118
|
-
end
|
119
|
-
domain_volume = ProviderLibvirt::Util::Collection.find_matching(
|
120
|
-
actual_volumes, "#{@name}.img"
|
121
|
-
)
|
122
|
-
raise Errors::DomainVolumeExists if domain_volume.nil?
|
123
|
-
@domain_volume_path = domain_volume.path
|
124
|
-
end
|
125
|
-
|
126
|
-
# If we have a box, take the path from the domain volume and set our storage_prefix.
|
127
|
-
# If not, we dump the storage pool xml to get its defined path.
|
128
|
-
# the default storage prefix is typically: /var/lib/libvirt/images/
|
129
|
-
if env[:machine].config.vm.box
|
130
|
-
storage_prefix = File.dirname(@domain_volume_path) + '/' # steal
|
131
|
-
else
|
132
|
-
storage_pool = env[:machine].provider.driver.connection.client.lookup_storage_pool_by_name(@storage_pool_name)
|
133
|
-
raise Errors::NoStoragePool if storage_pool.nil?
|
134
|
-
xml = Nokogiri::XML(storage_pool.xml_desc)
|
135
|
-
storage_prefix = xml.xpath('/pool/target/path').inner_text.to_s + '/'
|
136
|
-
end
|
137
|
-
|
138
|
-
@disks.each do |disk|
|
139
|
-
disk[:path] ||= _disk_name(@name, disk)
|
140
|
-
|
141
|
-
# On volume creation, the <path> element inside <target>
|
142
|
-
# is oddly ignored; instead the path is taken from the
|
143
|
-
# <name> element:
|
144
|
-
# http://www.redhat.com/archives/libvir-list/2008-August/msg00329.html
|
145
|
-
disk[:name] = disk[:path]
|
146
|
-
|
147
|
-
disk[:absolute_path] = storage_prefix + disk[:path]
|
148
|
-
|
149
|
-
if env[:machine].provider.driver.connection.volumes.select do |x|
|
150
|
-
x.name == disk[:name] && x.pool_name == @storage_pool_name
|
151
|
-
end.empty?
|
152
|
-
# make the disk. equivalent to:
|
153
|
-
# qemu-img create -f qcow2 <path> 5g
|
154
|
-
begin
|
155
|
-
env[:machine].provider.driver.connection.volumes.create(
|
156
|
-
name: disk[:name],
|
157
|
-
format_type: disk[:type],
|
158
|
-
path: disk[:absolute_path],
|
159
|
-
capacity: disk[:size],
|
160
|
-
#:allocation => ?,
|
161
|
-
pool_name: @storage_pool_name
|
162
|
-
)
|
163
|
-
rescue Fog::Errors::Error => e
|
164
|
-
raise Errors::FogDomainVolumeCreateError,
|
165
|
-
error_message: e.message
|
166
|
-
end
|
167
|
-
else
|
168
|
-
disk[:preexisting] = true
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
# Output the settings we're going to use to the user
|
173
|
-
env[:ui].info(I18n.t('vagrant_libvirt.creating_domain'))
|
174
|
-
env[:ui].info(" -- Name: #{@name}")
|
175
|
-
env[:ui].info(" -- Forced UUID: #{@uuid}") if @uuid != ''
|
176
|
-
env[:ui].info(" -- Domain type: #{@domain_type}")
|
177
|
-
env[:ui].info(" -- Cpus: #{@cpus}")
|
178
|
-
@cpu_features.each do |cpu_feature|
|
179
|
-
env[:ui].info(" -- CPU Feature: name=#{cpu_feature[:name]}, policy=#{cpu_feature[:policy]}")
|
180
|
-
end
|
181
|
-
@features.each do |feature|
|
182
|
-
env[:ui].info(" -- Feature: #{feature}")
|
183
|
-
end
|
184
|
-
env[:ui].info(" -- Memory: #{@memory_size / 1024}M")
|
185
|
-
env[:ui].info(" -- Management MAC: #{@management_network_mac}")
|
186
|
-
env[:ui].info(" -- Loader: #{@loader}")
|
187
|
-
if env[:machine].config.vm.box
|
188
|
-
env[:ui].info(" -- Base box: #{env[:machine].box.name}")
|
189
|
-
end
|
190
|
-
env[:ui].info(" -- Storage pool: #{@storage_pool_name}")
|
191
|
-
env[:ui].info(" -- Image: #{@domain_volume_path} (#{env[:box_virtual_size]}G)")
|
192
|
-
env[:ui].info(" -- Volume Cache: #{@domain_volume_cache}")
|
193
|
-
env[:ui].info(" -- Kernel: #{@kernel}")
|
194
|
-
env[:ui].info(" -- Initrd: #{@initrd}")
|
195
|
-
env[:ui].info(" -- Graphics Type: #{@graphics_type}")
|
196
|
-
env[:ui].info(" -- Graphics Port: #{@graphics_port}")
|
197
|
-
env[:ui].info(" -- Graphics IP: #{@graphics_ip}")
|
198
|
-
env[:ui].info(" -- Graphics Password: #{@graphics_passwd.empty? ? 'Not defined' : 'Defined'}")
|
199
|
-
env[:ui].info(" -- Video Type: #{@video_type}")
|
200
|
-
env[:ui].info(" -- Video VRAM: #{@video_vram}")
|
201
|
-
env[:ui].info(" -- Sound Type: #{@sound_type}")
|
202
|
-
env[:ui].info(" -- Keymap: #{@keymap}")
|
203
|
-
env[:ui].info(" -- TPM Path: #{@tpm_path}")
|
204
|
-
|
205
|
-
@boot_order.each do |device|
|
206
|
-
env[:ui].info(" -- Boot device: #{device}")
|
207
|
-
end
|
208
|
-
|
209
|
-
unless @disks.empty?
|
210
|
-
env[:ui].info(" -- Disks: #{_disks_print(@disks)}")
|
211
|
-
end
|
212
|
-
|
213
|
-
@disks.each do |disk|
|
214
|
-
msg = " -- Disk(#{disk[:device]}): #{disk[:absolute_path]}"
|
215
|
-
msg += ' Shared' if disk[:shareable]
|
216
|
-
msg += ' (Remove only manually)' if disk[:allow_existing]
|
217
|
-
msg += ' Not created - using existed.' if disk[:preexisting]
|
218
|
-
env[:ui].info(msg)
|
219
|
-
end
|
220
|
-
|
221
|
-
unless @cdroms.empty?
|
222
|
-
env[:ui].info(" -- CDROMS: #{_cdroms_print(@cdroms)}")
|
223
|
-
end
|
224
|
-
|
225
|
-
@cdroms.each do |cdrom|
|
226
|
-
env[:ui].info(" -- CDROM(#{cdrom[:dev]}): #{cdrom[:path]}")
|
227
|
-
end
|
228
|
-
|
229
|
-
@inputs.each do |input|
|
230
|
-
env[:ui].info(" -- INPUT: type=#{input[:type]}, bus=#{input[:bus]}")
|
231
|
-
end
|
232
|
-
|
233
|
-
@channels.each do |channel|
|
234
|
-
env[:ui].info(" -- CHANNEL: type=#{channel[:type]}, mode=#{channel[:source_mode]}")
|
235
|
-
env[:ui].info(" -- CHANNEL: target_type=#{channel[:target_type]}, target_name=#{channel[:target_name]}")
|
236
|
-
end
|
237
|
-
|
238
|
-
@pcis.each do |pci|
|
239
|
-
env[:ui].info(" -- PCI passthrough: #{pci[:bus]}:#{pci[:slot]}.#{pci[:function]}")
|
240
|
-
end
|
241
|
-
|
242
|
-
unless @rng[:model].nil?
|
243
|
-
env[:ui].info(" -- RNG device model: #{@rng[:model]}")
|
244
|
-
end
|
245
|
-
|
246
|
-
if not @watchdog_dev.empty?
|
247
|
-
env[:ui].info(" -- Watchdog device: model=#{@watchdog_dev[:model]}, action=#{@watchdog_dev[:action]}")
|
248
|
-
end
|
249
|
-
|
250
|
-
@usbs.each do |usb|
|
251
|
-
usb_dev = []
|
252
|
-
usb_dev.push("bus=#{usb[:bus]}") if usb[:bus]
|
253
|
-
usb_dev.push("device=#{usb[:device]}") if usb[:device]
|
254
|
-
usb_dev.push("vendor=#{usb[:vendor]}") if usb[:vendor]
|
255
|
-
usb_dev.push("product=#{usb[:product]}") if usb[:product]
|
256
|
-
env[:ui].info(" -- USB passthrough: #{usb_dev.join(', ')}")
|
257
|
-
end
|
258
|
-
|
259
|
-
unless @redirdevs.empty?
|
260
|
-
env[:ui].info(' -- Redirected Devices: ')
|
261
|
-
@redirdevs.each do |redirdev|
|
262
|
-
msg = " -> bus=usb, type=#{redirdev[:type]}"
|
263
|
-
env[:ui].info(msg)
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
unless @redirfilters.empty?
|
268
|
-
env[:ui].info(' -- USB Device filter for Redirected Devices: ')
|
269
|
-
@redirfilters.each do |redirfilter|
|
270
|
-
msg = " -> class=#{redirfilter[:class]}, "
|
271
|
-
msg += "vendor=#{redirfilter[:vendor]}, "
|
272
|
-
msg += "product=#{redirfilter[:product]}, "
|
273
|
-
msg += "version=#{redirfilter[:version]}, "
|
274
|
-
msg += "allow=#{redirfilter[:allow]}"
|
275
|
-
env[:ui].info(msg)
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
if not @smartcard_dev.empty?
|
280
|
-
env[:ui].info(" -- smartcard device: mode=#{@smartcard_dev[:mode]}, type=#{@smartcard_dev[:type]}")
|
281
|
-
end
|
282
|
-
|
283
|
-
@qargs = config.qemu_args
|
284
|
-
if not @qargs.empty?
|
285
|
-
env[:ui].info(' -- Command line args: ')
|
286
|
-
@qargs.each do |arg|
|
287
|
-
msg = " -> value=#{arg[:value]}, "
|
288
|
-
env[:ui].info(msg)
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
env[:ui].info(" -- Command line : #{@cmd_line}") unless @cmd_line.empty?
|
293
|
-
|
294
|
-
# Create libvirt domain.
|
295
|
-
# Is there a way to tell fog to create new domain with already
|
296
|
-
# existing volume? Use domain creation from template..
|
297
|
-
begin
|
298
|
-
server = env[:machine].provider.driver.connection.servers.create(
|
299
|
-
xml: to_xml('domain')
|
300
|
-
)
|
301
|
-
rescue Fog::Errors::Error => e
|
302
|
-
raise Errors::FogCreateServerError, error_message: e.message
|
303
|
-
end
|
304
|
-
|
305
|
-
# Immediately save the ID since it is created at this point.
|
306
|
-
env[:machine].id = server.id
|
307
|
-
|
308
|
-
@app.call(env)
|
309
|
-
end
|
310
|
-
end
|
311
|
-
end
|
312
|
-
end
|
313
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'log4r'
|
2
|
-
|
3
|
-
module VagrantPlugins
|
4
|
-
module ProviderLibvirt
|
5
|
-
module Action
|
6
|
-
# Create a snapshot of base box image. This new snapshot is just new
|
7
|
-
# cow image with backing storage pointing to base box image. Use this
|
8
|
-
# image as new domain volume.
|
9
|
-
class CreateDomainVolume
|
10
|
-
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
11
|
-
|
12
|
-
def initialize(app, _env)
|
13
|
-
@logger = Log4r::Logger.new('vagrant_libvirt::action::create_domain_volume')
|
14
|
-
@app = app
|
15
|
-
end
|
16
|
-
|
17
|
-
def call(env)
|
18
|
-
env[:ui].info(I18n.t('vagrant_libvirt.creating_domain_volume'))
|
19
|
-
|
20
|
-
# Get config options.
|
21
|
-
config = env[:machine].provider_config
|
22
|
-
|
23
|
-
# This is name of newly created image for vm.
|
24
|
-
@name = "#{env[:domain_name]}.img"
|
25
|
-
|
26
|
-
# Verify the volume doesn't exist already.
|
27
|
-
domain_volume = ProviderLibvirt::Util::Collection.find_matching(
|
28
|
-
env[:machine].provider.driver.connection.volumes.all, @name
|
29
|
-
)
|
30
|
-
raise Errors::DomainVolumeExists if domain_volume
|
31
|
-
|
32
|
-
# Get path to backing image - box volume.
|
33
|
-
box_volume = ProviderLibvirt::Util::Collection.find_matching(
|
34
|
-
env[:machine].provider.driver.connection.volumes.all, env[:box_volume_name]
|
35
|
-
)
|
36
|
-
@backing_file = box_volume.path
|
37
|
-
|
38
|
-
# Virtual size of image. Take value worked out by HandleBoxImage
|
39
|
-
@capacity = env[:box_virtual_size] # G
|
40
|
-
|
41
|
-
# Create new volume from xml template. Fog currently doesn't support
|
42
|
-
# volume snapshots directly.
|
43
|
-
begin
|
44
|
-
xml = Nokogiri::XML::Builder.new do |xml|
|
45
|
-
xml.volume do
|
46
|
-
xml.name(@name)
|
47
|
-
xml.capacity(@capacity, unit: 'G')
|
48
|
-
xml.target do
|
49
|
-
xml.format(type: 'qcow2')
|
50
|
-
xml.permissions do
|
51
|
-
xml.owner 0
|
52
|
-
xml.group 0
|
53
|
-
xml.mode '0600'
|
54
|
-
xml.label 'virt_image_t'
|
55
|
-
end
|
56
|
-
end
|
57
|
-
xml.backingStore do
|
58
|
-
xml.path(@backing_file)
|
59
|
-
xml.format(type: 'qcow2')
|
60
|
-
xml.permissions do
|
61
|
-
xml.owner 0
|
62
|
-
xml.group 0
|
63
|
-
xml.mode '0600'
|
64
|
-
xml.label 'virt_image_t'
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end.to_xml(
|
69
|
-
save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION |
|
70
|
-
Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS |
|
71
|
-
Nokogiri::XML::Node::SaveOptions::FORMAT
|
72
|
-
)
|
73
|
-
domain_volume = env[:machine].provider.driver.connection.volumes.create(
|
74
|
-
xml: xml,
|
75
|
-
pool_name: config.storage_pool_name
|
76
|
-
)
|
77
|
-
rescue Fog::Errors::Error => e
|
78
|
-
raise Errors::FogDomainVolumeCreateError,
|
79
|
-
error_message: e.message
|
80
|
-
end
|
81
|
-
|
82
|
-
@app.call(env)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
@@ -1,294 +0,0 @@
|
|
1
|
-
require 'log4r'
|
2
|
-
require 'vagrant/util/network_ip'
|
3
|
-
require 'vagrant/util/scoped_hash_override'
|
4
|
-
|
5
|
-
module VagrantPlugins
|
6
|
-
module ProviderLibvirt
|
7
|
-
module Action
|
8
|
-
# Create network interfaces for domain, before domain is running.
|
9
|
-
# Networks for connecting those interfaces should be already prepared.
|
10
|
-
class CreateNetworkInterfaces
|
11
|
-
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
12
|
-
include VagrantPlugins::ProviderLibvirt::Util::NetworkUtil
|
13
|
-
include Vagrant::Util::NetworkIP
|
14
|
-
include Vagrant::Util::ScopedHashOverride
|
15
|
-
|
16
|
-
def initialize(app, env)
|
17
|
-
@logger = Log4r::Logger.new('vagrant_libvirt::action::create_network_interfaces')
|
18
|
-
@management_network_name = env[:machine].provider_config.management_network_name
|
19
|
-
config = env[:machine].provider_config
|
20
|
-
@nic_model_type = config.nic_model_type || 'virtio'
|
21
|
-
@nic_adapter_count = config.nic_adapter_count
|
22
|
-
@app = app
|
23
|
-
end
|
24
|
-
|
25
|
-
def call(env)
|
26
|
-
# Get domain first.
|
27
|
-
begin
|
28
|
-
domain = env[:machine].provider.driver.connection.client.lookup_domain_by_uuid(
|
29
|
-
env[:machine].id.to_s
|
30
|
-
)
|
31
|
-
rescue => e
|
32
|
-
raise Errors::NoDomainError,
|
33
|
-
error_message: e.message
|
34
|
-
end
|
35
|
-
|
36
|
-
# Setup list of interfaces before creating them.
|
37
|
-
adapters = []
|
38
|
-
|
39
|
-
# Vagrant gives you adapter 0 by default
|
40
|
-
# Assign interfaces to slots.
|
41
|
-
configured_networks(env, @logger).each do |options|
|
42
|
-
# dont need to create interface for this type
|
43
|
-
next if options[:iface_type] == :forwarded_port
|
44
|
-
|
45
|
-
# TODO: fill first ifaces with adapter option specified.
|
46
|
-
if options[:adapter]
|
47
|
-
if adapters[options[:adapter]]
|
48
|
-
raise Errors::InterfaceSlotNotAvailable
|
49
|
-
end
|
50
|
-
|
51
|
-
free_slot = options[:adapter].to_i
|
52
|
-
@logger.debug "Using specified adapter slot #{free_slot}"
|
53
|
-
else
|
54
|
-
free_slot = find_empty(adapters)
|
55
|
-
@logger.debug "Adapter not specified so found slot #{free_slot}"
|
56
|
-
raise Errors::InterfaceSlotNotAvailable if free_slot.nil?
|
57
|
-
end
|
58
|
-
|
59
|
-
# We have slot for interface, fill it with interface configuration.
|
60
|
-
adapters[free_slot] = options
|
61
|
-
adapters[free_slot][:network_name] = interface_network(
|
62
|
-
env[:machine].provider.driver.connection.client, adapters[free_slot]
|
63
|
-
)
|
64
|
-
end
|
65
|
-
|
66
|
-
# Create each interface as new domain device.
|
67
|
-
@macs_per_network = Hash.new(0)
|
68
|
-
adapters.each_with_index do |iface_configuration, slot_number|
|
69
|
-
@iface_number = slot_number
|
70
|
-
@network_name = iface_configuration[:network_name]
|
71
|
-
@source_options = {
|
72
|
-
network: @network_name
|
73
|
-
}
|
74
|
-
@mac = iface_configuration.fetch(:mac, false)
|
75
|
-
@model_type = iface_configuration.fetch(:model_type, @nic_model_type)
|
76
|
-
@driver_name = iface_configuration.fetch(:driver_name, false)
|
77
|
-
@driver_queues = iface_configuration.fetch(:driver_queues, false)
|
78
|
-
@device_name = iface_configuration.fetch(:iface_name, false)
|
79
|
-
template_name = 'interface'
|
80
|
-
# Configuration for public interfaces which use the macvtap driver
|
81
|
-
if iface_configuration[:iface_type] == :public_network
|
82
|
-
@device = iface_configuration.fetch(:dev, 'eth0')
|
83
|
-
@mode = iface_configuration.fetch(:mode, 'bridge')
|
84
|
-
@type = iface_configuration.fetch(:type, 'direct')
|
85
|
-
@model_type = iface_configuration.fetch(:model_type, @nic_model_type)
|
86
|
-
@driver_name = iface_configuration.fetch(:driver_name, false)
|
87
|
-
@driver_queues = iface_configuration.fetch(:driver_queues, false)
|
88
|
-
@portgroup = iface_configuration.fetch(:portgroup, nil)
|
89
|
-
@network_name = iface_configuration.fetch(:network_name, @network_name)
|
90
|
-
template_name = 'public_interface'
|
91
|
-
@logger.info("Setting up public interface using device #{@device} in mode #{@mode}")
|
92
|
-
@ovs = iface_configuration.fetch(:ovs, false)
|
93
|
-
@trust_guest_rx_filters = iface_configuration.fetch(:trust_guest_rx_filters, false)
|
94
|
-
# configuration for udp or tcp tunnel interfaces (p2p conn btwn guest OSes)
|
95
|
-
elsif iface_configuration.fetch(:tunnel_type, nil)
|
96
|
-
@type = iface_configuration.fetch(:tunnel_type)
|
97
|
-
@tunnel_port = iface_configuration.fetch(:tunnel_port, nil)
|
98
|
-
raise Errors::TunnelPortNotDefined if @tunnel_port.nil?
|
99
|
-
if @type == 'udp'
|
100
|
-
# default udp tunnel source to 127.0.0.1
|
101
|
-
@udp_tunnel={
|
102
|
-
address: iface_configuration.fetch(:tunnel_local_ip,'127.0.0.1'),
|
103
|
-
port: iface_configuration.fetch(:tunnel_local_port)
|
104
|
-
}
|
105
|
-
end
|
106
|
-
# default mcast tunnel to 239.255.1.1. Web search says this
|
107
|
-
# 239.255.x.x is a safe range to use for general use mcast
|
108
|
-
default_ip = if @type == 'mcast'
|
109
|
-
'239.255.1.1'
|
110
|
-
else
|
111
|
-
'127.0.0.1'
|
112
|
-
end
|
113
|
-
@source_options = {
|
114
|
-
address: iface_configuration.fetch(:tunnel_ip, default_ip),
|
115
|
-
port: @tunnel_port
|
116
|
-
}
|
117
|
-
@tunnel_type = iface_configuration.fetch(:model_type, @nic_model_type)
|
118
|
-
@driver_name = iface_configuration.fetch(:driver_name, false)
|
119
|
-
@driver_queues = iface_configuration.fetch(:driver_queues, false)
|
120
|
-
template_name = 'tunnel_interface'
|
121
|
-
@logger.info("Setting up #{@type} tunnel interface using #{@tunnel_ip} port #{@tunnel_port}")
|
122
|
-
end
|
123
|
-
|
124
|
-
message = "Creating network interface eth#{@iface_number}"
|
125
|
-
message << " connected to network #{@network_name}."
|
126
|
-
if @mac
|
127
|
-
@mac = @mac.scan(/(\h{2})/).join(':')
|
128
|
-
message << " Using MAC address: #{@mac}"
|
129
|
-
end
|
130
|
-
@logger.info(message)
|
131
|
-
|
132
|
-
begin
|
133
|
-
# FIXME: all options for network driver should be hash from Vagrantfile
|
134
|
-
driver_options = {}
|
135
|
-
driver_options[:name] = @driver_name if @driver_name
|
136
|
-
driver_options[:queues] = @driver_queues if @driver_queues
|
137
|
-
@udp_tunnel ||= {}
|
138
|
-
xml = if template_name == 'interface' or
|
139
|
-
template_name == 'tunnel_interface'
|
140
|
-
interface_xml(@type,
|
141
|
-
@source_options,
|
142
|
-
@mac,
|
143
|
-
@device_name,
|
144
|
-
@iface_number,
|
145
|
-
@model_type,
|
146
|
-
driver_options,
|
147
|
-
@udp_tunnel)
|
148
|
-
else
|
149
|
-
to_xml(template_name)
|
150
|
-
end
|
151
|
-
domain.attach_device(xml)
|
152
|
-
rescue => e
|
153
|
-
raise Errors::AttachDeviceError,
|
154
|
-
error_message: e.message
|
155
|
-
end
|
156
|
-
|
157
|
-
# Re-read the network configuration and grab the MAC address
|
158
|
-
if iface_configuration[:iface_type] == :public_network
|
159
|
-
xml = Nokogiri::XML(domain.xml_desc)
|
160
|
-
source = "@network='#{@network_name}'"
|
161
|
-
if @type == 'direct'
|
162
|
-
source = "@dev='#{@device}'"
|
163
|
-
elsif @portgroup.nil?
|
164
|
-
source = "@bridge='#{@device}'"
|
165
|
-
end
|
166
|
-
if not @mac
|
167
|
-
macs = xml.xpath("/domain/devices/interface[source[#{source}]]/mac/@address")
|
168
|
-
@mac = macs[@macs_per_network[source]]
|
169
|
-
iface_configuration[:mac] = @mac.to_s
|
170
|
-
end
|
171
|
-
@macs_per_network[source] += 1
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
# Continue the middleware chain.
|
176
|
-
@app.call(env)
|
177
|
-
|
178
|
-
if env[:machine].config.vm.box
|
179
|
-
# Configure interfaces that user requested. Machine should be up and
|
180
|
-
# running now.
|
181
|
-
networks_to_configure = []
|
182
|
-
|
183
|
-
adapters.each_with_index do |options, slot_number|
|
184
|
-
# Skip configuring the management network, which is on the first interface.
|
185
|
-
# It's used for provisioning and it has to be available during provisioning,
|
186
|
-
# ifdown command is not acceptable here.
|
187
|
-
next if slot_number.zero?
|
188
|
-
next if options[:auto_config] === false
|
189
|
-
@logger.debug "Configuring interface slot_number #{slot_number} options #{options}"
|
190
|
-
|
191
|
-
network = {
|
192
|
-
interface: slot_number,
|
193
|
-
use_dhcp_assigned_default_route: options[:use_dhcp_assigned_default_route],
|
194
|
-
mac_address: options[:mac]
|
195
|
-
}
|
196
|
-
|
197
|
-
if options[:ip]
|
198
|
-
network = {
|
199
|
-
type: :static,
|
200
|
-
ip: options[:ip],
|
201
|
-
netmask: options[:netmask],
|
202
|
-
gateway: options[:gateway]
|
203
|
-
}.merge(network)
|
204
|
-
else
|
205
|
-
network[:type] = :dhcp
|
206
|
-
end
|
207
|
-
|
208
|
-
# do not run configure_networks for tcp tunnel interfaces
|
209
|
-
next if options.fetch(:tunnel_type, nil)
|
210
|
-
|
211
|
-
networks_to_configure << network
|
212
|
-
end
|
213
|
-
|
214
|
-
env[:ui].info I18n.t('vagrant.actions.vm.network.configuring')
|
215
|
-
env[:machine].guest.capability(
|
216
|
-
:configure_networks, networks_to_configure
|
217
|
-
)
|
218
|
-
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
private
|
223
|
-
|
224
|
-
def target_dev_name(device_name, type, iface_number)
|
225
|
-
if device_name
|
226
|
-
device_name
|
227
|
-
elsif type == 'netwrok'
|
228
|
-
"vnet#{iface_number}"
|
229
|
-
else
|
230
|
-
# TODO can we use same name vnet#ifnum?
|
231
|
-
#"tnet#{iface_number}" FIXME plugin vagrant-libvirt trying to create second tnet0 interface
|
232
|
-
"vnet#{iface_number}"
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
def interface_xml(type, source_options, mac, device_name,
|
237
|
-
iface_number, model_type, driver_options,
|
238
|
-
udp_tunnel={})
|
239
|
-
Nokogiri::XML::Builder.new do |xml|
|
240
|
-
xml.interface(type: type || 'network') do
|
241
|
-
xml.source(source_options) do
|
242
|
-
xml.local(udp_tunnel) if type == 'udp'
|
243
|
-
end
|
244
|
-
xml.mac(address: mac) if mac
|
245
|
-
xml.target(dev: target_dev_name(device_name, type, iface_number))
|
246
|
-
xml.alias(name: "net#{iface_number}")
|
247
|
-
xml.model(type: model_type.to_s)
|
248
|
-
xml.driver(driver_options)
|
249
|
-
end
|
250
|
-
end.to_xml(
|
251
|
-
save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION |
|
252
|
-
Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS |
|
253
|
-
Nokogiri::XML::Node::SaveOptions::FORMAT
|
254
|
-
)
|
255
|
-
end
|
256
|
-
|
257
|
-
def find_empty(array, start = 0, stop = @nic_adapter_count)
|
258
|
-
(start..stop).each do |i|
|
259
|
-
return i unless array[i]
|
260
|
-
end
|
261
|
-
nil
|
262
|
-
end
|
263
|
-
|
264
|
-
# Return network name according to interface options.
|
265
|
-
def interface_network(libvirt_client, options)
|
266
|
-
# no need to get interface network for tcp tunnel config
|
267
|
-
return 'tunnel_interface' if options.fetch(:tunnel_type, nil)
|
268
|
-
|
269
|
-
if options[:network_name]
|
270
|
-
@logger.debug 'Found network by name'
|
271
|
-
return options[:network_name]
|
272
|
-
end
|
273
|
-
|
274
|
-
# Get list of all (active and inactive) libvirt networks.
|
275
|
-
available_networks = libvirt_networks(libvirt_client)
|
276
|
-
|
277
|
-
return 'public' if options[:iface_type] == :public_network
|
278
|
-
|
279
|
-
if options[:ip]
|
280
|
-
address = network_address(options[:ip], options[:netmask])
|
281
|
-
available_networks.each do |network|
|
282
|
-
if address == network[:network_address]
|
283
|
-
@logger.debug 'Found network by ip'
|
284
|
-
return network[:name]
|
285
|
-
end
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
raise Errors::NetworkNotAvailableError, network_name: options[:ip]
|
290
|
-
end
|
291
|
-
end
|
292
|
-
end
|
293
|
-
end
|
294
|
-
end
|