vagrant-libvirt 0.6.2 → 0.8.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 +65 -13
- data/lib/vagrant-libvirt/action/cleanup_on_failure.rb +76 -0
- data/lib/vagrant-libvirt/action/create_domain.rb +56 -10
- data/lib/vagrant-libvirt/action/create_network_interfaces.rb +5 -1
- data/lib/vagrant-libvirt/action/create_networks.rb +24 -0
- data/lib/vagrant-libvirt/action/destroy_domain.rb +106 -21
- data/lib/vagrant-libvirt/action/destroy_networks.rb +1 -1
- data/lib/vagrant-libvirt/action/forward_ports.rb +12 -11
- data/lib/vagrant-libvirt/action/handle_box_image.rb +19 -10
- data/lib/vagrant-libvirt/action/prepare_nfs_settings.rb +1 -1
- data/lib/vagrant-libvirt/action/start_domain.rb +36 -0
- data/lib/vagrant-libvirt/action/wait_till_up.rb +6 -32
- data/lib/vagrant-libvirt/action.rb +67 -80
- data/lib/vagrant-libvirt/config.rb +85 -30
- data/lib/vagrant-libvirt/driver.rb +11 -9
- data/lib/vagrant-libvirt/errors.rb +12 -0
- data/lib/vagrant-libvirt/templates/domain.xml.erb +228 -218
- data/lib/vagrant-libvirt/templates/private_network.xml.erb +4 -1
- data/lib/vagrant-libvirt/util/network_util.rb +15 -3
- data/lib/vagrant-libvirt/util/nfs.rb +2 -0
- data/lib/vagrant-libvirt/util/resolvers.rb +80 -0
- data/lib/vagrant-libvirt/version +1 -1
- data/locales/en.yml +21 -0
- data/spec/spec_helper.rb +36 -23
- data/spec/support/libvirt_context.rb +7 -4
- data/spec/support/sharedcontext.rb +1 -1
- data/spec/unit/action/cleanup_on_failure_spec.rb +131 -0
- data/spec/unit/action/create_domain_spec/additional_disks_domain.xml +6 -18
- data/spec/unit/action/create_domain_spec/custom_disk_settings.xml +43 -0
- data/spec/unit/action/create_domain_spec/default_domain.xml +6 -18
- data/spec/unit/action/create_domain_spec/two_disk_settings.xml +49 -0
- data/spec/unit/action/create_domain_spec.rb +51 -7
- data/spec/unit/action/create_domain_volume_spec.rb +5 -3
- data/spec/unit/action/destroy_domain_spec/additional_disks_domain.xml +47 -0
- data/spec/unit/action/destroy_domain_spec/box_multiple_disks.xml +55 -0
- data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_and_custom_disks.xml +72 -0
- data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_and_custom_disks_no_aliases.xml +67 -0
- data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_disks.xml +67 -0
- data/spec/unit/action/destroy_domain_spec/cdrom_domain.xml +48 -0
- data/spec/unit/action/destroy_domain_spec.rb +134 -30
- data/spec/unit/action/forward_ports_spec.rb +10 -2
- data/spec/unit/action/handle_box_image_spec.rb +30 -0
- data/spec/unit/action/prepare_nfs_settings_spec.rb +59 -0
- data/spec/unit/action/shutdown_domain_spec.rb +1 -1
- data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +6 -18
- data/spec/unit/action/start_domain_spec/default.xml +6 -18
- data/spec/unit/action/start_domain_spec/default_added_tpm_path.xml +6 -18
- data/spec/unit/action/start_domain_spec/default_added_tpm_version.xml +6 -18
- data/spec/unit/action/start_domain_spec/existing.xml +1 -1
- data/spec/unit/action/wait_till_up_spec.rb +4 -43
- data/spec/unit/action_spec.rb +2 -0
- data/spec/unit/config_spec.rb +133 -26
- data/spec/unit/driver_spec.rb +154 -10
- data/spec/unit/provider_spec.rb +11 -0
- data/spec/unit/templates/domain_all_settings.xml +56 -77
- data/spec/unit/templates/domain_cpu_mode_passthrough.xml +39 -0
- data/spec/unit/templates/domain_custom_cpu_model.xml +6 -18
- data/spec/unit/templates/domain_defaults.xml +6 -18
- data/spec/unit/templates/domain_spec.rb +39 -13
- data/spec/unit/templates/tpm/version_1.2.xml +6 -18
- data/spec/unit/templates/tpm/version_2.0.xml +6 -18
- data/spec/unit/util/resolvers_spec.rb +116 -0
- metadata +65 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1bfaefd1dab7cbdb1293e867e29fef05a9eb101fae5226a38203593de84e717
|
4
|
+
data.tar.gz: d36d4f487ed2ad0b4f00ba09c263a5cd8deda6c268eef50974376e2796b7e64d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 510c1b6ffd2fb4eea02ede8d7612c3a41a89e5c50b630370bec6fd70b79986caa222e6ce1cc0f4c2732b310f7c134866aa2283ee449441c92078b148c4734503
|
7
|
+
data.tar.gz: cb6ab754dcff508ec150c6ff67cf82b603243596b35ab6a5ef79d4dfe36042a933dde8eebc3630d5a2473c8fcd398111a98d12a64a66950ad0abe942c15bce40
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# Vagrant Libvirt Provider
|
2
2
|
|
3
3
|
[![Join the chat at https://gitter.im/vagrant-libvirt/vagrant-libvirt](https://badges.gitter.im/vagrant-libvirt/vagrant-libvirt.svg)](https://gitter.im/vagrant-libvirt/vagrant-libvirt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
4
|
-
[![Build Status](https://
|
4
|
+
[![Build Status](https://github.com/vagrant-libvirt/vagrant-libvirt/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/vagrant-libvirt/vagrant-libvirt/actions/workflows/unit-tests.yml)
|
5
5
|
[![Coverage Status](https://coveralls.io/repos/github/vagrant-libvirt/vagrant-libvirt/badge.svg?branch=master)](https://coveralls.io/github/vagrant-libvirt/vagrant-libvirt?branch=master)
|
6
|
+
[![Gem Version](https://badge.fury.io/rb/vagrant-libvirt.svg)](https://badge.fury.io/rb/vagrant-libvirt)
|
6
7
|
|
7
8
|
This is a [Vagrant](http://www.vagrantup.com) plugin that adds a
|
8
9
|
[Libvirt](http://libvirt.org) provider to Vagrant, allowing Vagrant to
|
@@ -48,6 +49,7 @@ can help a lot :-)
|
|
48
49
|
* [USB Device Passthrough](#usb-device-passthrough)
|
49
50
|
* [USB Redirector Devices](#usb-redirector-devices)
|
50
51
|
* [Filter for USB Redirector Devices](#filter-for-usb-redirector-devices)
|
52
|
+
* [Serial Console Devices](#serial-console-devices)
|
51
53
|
* [Random number generator passthrough](#random-number-generator-passthrough)
|
52
54
|
* [Watchdog device](#watchdog-device)
|
53
55
|
* [Smartcard device](#smartcard-device)
|
@@ -137,15 +139,9 @@ docker pull vagrantlibvirt/vagrant-libvirt:edge
|
|
137
139
|
```
|
138
140
|
---
|
139
141
|
|
140
|
-
Preparing the docker run, only once:
|
141
|
-
|
142
|
-
```bash
|
143
|
-
mkdir -p ~/.vagrant.d/{boxes,data,tmp}
|
144
|
-
```
|
145
|
-
|
146
142
|
Running the image:
|
147
143
|
```bash
|
148
|
-
docker run -
|
144
|
+
docker run -i --rm \
|
149
145
|
-e LIBVIRT_DEFAULT_URI \
|
150
146
|
-v /var/run/libvirt/:/var/run/libvirt/ \
|
151
147
|
-v ~/.vagrant.d:/.vagrant.d \
|
@@ -159,7 +155,7 @@ docker run -it --rm \
|
|
159
155
|
It's possible to define a function in `~/.bashrc`, for example:
|
160
156
|
```bash
|
161
157
|
vagrant(){
|
162
|
-
docker run -
|
158
|
+
docker run -i --rm \
|
163
159
|
-e LIBVIRT_DEFAULT_URI \
|
164
160
|
-v /var/run/libvirt/:/var/run/libvirt/ \
|
165
161
|
-v ~/.vagrant.d:/.vagrant.d \
|
@@ -173,6 +169,14 @@ vagrant(){
|
|
173
169
|
```
|
174
170
|
|
175
171
|
### Using Podman
|
172
|
+
|
173
|
+
Preparing the podman run, only once:
|
174
|
+
|
175
|
+
```bash
|
176
|
+
mkdir -p ~/.vagrant.d/{boxes,data,tmp}
|
177
|
+
```
|
178
|
+
_N.B. This is needed until the entrypoint works for podman to only mount the `~/.vagrant.d` directory_
|
179
|
+
|
176
180
|
To run with Podman you need to include
|
177
181
|
|
178
182
|
```bash
|
@@ -180,6 +184,7 @@ To run with Podman you need to include
|
|
180
184
|
--security-opt label=disable \
|
181
185
|
-v ~/.vagrant.d/boxes:/vagrant/boxes \
|
182
186
|
-v ~/.vagrant.d/data:/vagrant/data \
|
187
|
+
-v ~/.vagrant.d/tmp:/vagrant/tmp \
|
183
188
|
```
|
184
189
|
|
185
190
|
for example:
|
@@ -191,6 +196,7 @@ vagrant(){
|
|
191
196
|
-v /var/run/libvirt/:/var/run/libvirt/ \
|
192
197
|
-v ~/.vagrant.d/boxes:/vagrant/boxes \
|
193
198
|
-v ~/.vagrant.d/data:/vagrant/data \
|
199
|
+
-v ~/.vagrant.d/tmp:/vagrant/tmp \
|
194
200
|
-v $(realpath "${PWD}"):${PWD} \
|
195
201
|
-w $(realpath "${PWD}") \
|
196
202
|
--network host \
|
@@ -232,7 +238,7 @@ installed](http://docs.vagrantup.com/v2/installation/index.html).
|
|
232
238
|
Vagrant-libvirt supports Vagrant 2.0, 2.1 & 2.2. It should also work with earlier
|
233
239
|
releases from 1.5 onwards but they are not actively tested.
|
234
240
|
|
235
|
-
Check the [
|
241
|
+
Check the [unit tests](https://github.com/vagrant-libvirt/vagrant-libvirt/blob/master/.github/workflows/unit-tests.yml)
|
236
242
|
for the current list of tested versions.
|
237
243
|
|
238
244
|
*We only test with the upstream version!* If you decide to install your distro's
|
@@ -593,6 +599,8 @@ end
|
|
593
599
|
* `graphics_autoport` - Sets autoport for graphics, Libvirt in this case
|
594
600
|
ignores graphics_port value, Defaults to 'yes'. Possible value are "yes" and
|
595
601
|
"no"
|
602
|
+
* `graphics_gl` - Set to `true` to enable OpenGL. Defaults to `true` if
|
603
|
+
`video_accel3d` is `true`.
|
596
604
|
* `keymap` - Set keymap for vm. default: en-us
|
597
605
|
* `kvm_hidden` - [Hide the hypervisor from the
|
598
606
|
guest](https://libvirt.org/formatdomain.html#elementsFeatures). Useful for
|
@@ -602,7 +610,9 @@ end
|
|
602
610
|
values](http://libvirt.org/formatdomain.html#elementsVideo) are "vga",
|
603
611
|
"cirrus", "vmvga", "xen", "vbox", or "qxl".
|
604
612
|
* `video_vram` - Used by some graphics card types to vary the amount of RAM
|
605
|
-
dedicated to video. Defaults to
|
613
|
+
dedicated to video. Defaults to 16384.
|
614
|
+
* `video_accel3d` - Set to `true` to enable 3D acceleration. Defaults to
|
615
|
+
`false`.
|
606
616
|
* `sound_type` - [Set the virtual sound card](https://libvirt.org/formatdomain.html#elementsSound)
|
607
617
|
Defaults to "ich6".
|
608
618
|
* `machine_type` - Sets machine type. Equivalent to qemu `-machine`. Use
|
@@ -657,6 +667,9 @@ end
|
|
657
667
|
it is not possible to communicate with VM through `vagrant ssh` or run
|
658
668
|
provisioning. Setting to 'false' is only possible when VM doesn't use box.
|
659
669
|
Defaults set to 'true'.
|
670
|
+
* `serial` - [libvirt serial devices](https://libvirt.org/formatdomain.html#elementsConsole).
|
671
|
+
Configure a serial/console port to communicate with the guest. Can be used
|
672
|
+
to log to file boot time messages sent to ttyS0 console by the guest.
|
660
673
|
|
661
674
|
Specific domain settings can be set for each domain separately in multi-VM
|
662
675
|
environment. Example below shows a part of Vagrantfile, where specific options
|
@@ -846,6 +859,7 @@ starts with `libvirt__` string. Here is a list of those options:
|
|
846
859
|
* `:libvirt__dhcp_bootp_server` - The server that runs the DHCP server. Used
|
847
860
|
only when dhcp is enabled.By default is the same host that runs the DHCP
|
848
861
|
server.
|
862
|
+
* `:libvirt__tftp_root` - Path to the root directory served via TFTP.
|
849
863
|
* `:libvirt__adapter` - Number specifiyng sequence number of interface.
|
850
864
|
* `:libvirt__forward_mode` - Specify one of `veryisolated`, `none`, `open`, `nat`
|
851
865
|
or `route` options. This option is used only when creating new network. Mode
|
@@ -906,6 +920,9 @@ starts with `libvirt__` string. Here is a list of those options:
|
|
906
920
|
If not specified the default is 'false'.
|
907
921
|
* `:bus` - The bus of the PCI device. Both :bus and :slot have to be defined.
|
908
922
|
* `:slot` - The slot of the PCI device. Both :bus and :slot have to be defined.
|
923
|
+
* `:libvirt__always_destroy` - Allow domains that use but did not create a
|
924
|
+
network to destroy it when the domain is destroyed (default: `true`). Set to
|
925
|
+
`false` to only allow the domain that created the network to destroy it.
|
909
926
|
|
910
927
|
When the option `:libvirt__dhcp_enabled` is to to 'false' it shouldn't matter
|
911
928
|
whether the virtual network contains a DHCP server or not and vagrant-libvirt
|
@@ -961,6 +978,8 @@ used by this network are configurable at the provider level.
|
|
961
978
|
* `management_network_domain` - Domain name assigned to the management network.
|
962
979
|
* `management_network_mtu` - MTU size of management network. If not specified,
|
963
980
|
the Libvirt default (1500) will be used.
|
981
|
+
* `management_network_keep` - Starting from version *0.7.0*, *always_destroy* is set to *true* by default for any network.
|
982
|
+
This option allows to change this behaviour for the management network.
|
964
983
|
|
965
984
|
You may wonder how vagrant-libvirt knows the IP address a VM received. Libvirt
|
966
985
|
doesn't provide a standard way to find out the IP address of a running domain.
|
@@ -983,6 +1002,19 @@ if it detects an attached channel during boot.
|
|
983
1002
|
* `qemu_use_agent` - false by default, if set to true, attempt to extract configured
|
984
1003
|
ip address via qemu agent.
|
985
1004
|
|
1005
|
+
By default if `qemu_use_agent` is set to `true` the code will automatically
|
1006
|
+
inject a suitable channel unless there already exists an entry with a
|
1007
|
+
`:target_name` matching `'org.qemu.guest_agent.'`.
|
1008
|
+
Alternatively if setting `qemu_use_agent` but, needing to disable the addition
|
1009
|
+
of the channel, simply use a disabled flag as follows:
|
1010
|
+
```ruby
|
1011
|
+
Vagrant.configure(2) do |config|
|
1012
|
+
config.vm.provider :libvirt do |libvirt|
|
1013
|
+
libvirt.channel :type => 'unix', :target_name => 'org.qemu.guest_agent.0', :disabled => true
|
1014
|
+
end
|
1015
|
+
end
|
1016
|
+
```
|
1017
|
+
|
986
1018
|
To use the management network interface with an external dhcp service you need
|
987
1019
|
to setup a bridged host network manually and define it via
|
988
1020
|
`management_network_name` in your Vagrantfile.
|
@@ -1180,9 +1212,9 @@ Bus 001 Device 002: ID 1234:abcd Example device
|
|
1180
1212
|
Vagrant.configure("2") do |config|
|
1181
1213
|
config.vm.provider :libvirt do |libvirt|
|
1182
1214
|
# pass through specific device based on identifying it
|
1183
|
-
libvirt.
|
1215
|
+
libvirt.usb :vendor => '0x1234', :product => '0xabcd'
|
1184
1216
|
# pass through a host device where multiple of the same vendor/product exist
|
1185
|
-
libvirt.
|
1217
|
+
libvirt.usb :bus => '1', :device => '1'
|
1186
1218
|
end
|
1187
1219
|
end
|
1188
1220
|
```
|
@@ -1249,6 +1281,26 @@ Vagrant.configure("2") do |config|
|
|
1249
1281
|
end
|
1250
1282
|
```
|
1251
1283
|
|
1284
|
+
## Serial Console Devices
|
1285
|
+
You can define settings to redirect output from the serial console of any VM brought up with libvirt to a file or other devices that are listening. [See libvirt documentation](https://libvirt.org/formatdomain.html#elementCharSerial).
|
1286
|
+
|
1287
|
+
Currently only redirecting to a file is supported.
|
1288
|
+
|
1289
|
+
* `type` - only value that has an effect is file, in the future support may be added for virtual console, pty, dev, pipe, tcp, udp, unix socket, spiceport & nmdm.
|
1290
|
+
* `source` - options pertaining to how the connection attaches to the host, contains sub-settings dependent on `type`.
|
1291
|
+
`source` options for type `file`
|
1292
|
+
* `path` - file on host to connect to the serial port to record all output. May be created by qemu system user causing some permissions issues.
|
1293
|
+
|
1294
|
+
```ruby
|
1295
|
+
Vagrant.configure("2") do |config|
|
1296
|
+
config.vm.define :test do |test|
|
1297
|
+
test.vm.provider :libvirt do |domain|
|
1298
|
+
domain.serial :type => "file", :source => {:path => "/var/log/vm_consoles/test.log"}
|
1299
|
+
end
|
1300
|
+
end
|
1301
|
+
end
|
1302
|
+
```
|
1303
|
+
|
1252
1304
|
## Random number generator passthrough
|
1253
1305
|
|
1254
1306
|
You can pass through `/dev/random` to your VM by configuring the domain like this:
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module ProviderLibvirt
|
6
|
+
module Action
|
7
|
+
class CleanupOnFailure
|
8
|
+
def initialize(app, _env)
|
9
|
+
@logger = Log4r::Logger.new('vagrant_libvirt::action::cleanup_on_failure')
|
10
|
+
@app = app
|
11
|
+
@cleanup = true
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
# passing a value doesn't work as the env that is updated may be dupped from
|
16
|
+
# the original meaning the latter action's update is discarded. Instead pass
|
17
|
+
# a reference to the method on this class that will toggle the instance
|
18
|
+
# variable indicating whether cleanup is needed or not.
|
19
|
+
env['vagrant-libvirt.complete'] = method(:completed)
|
20
|
+
|
21
|
+
@app.call(env)
|
22
|
+
end
|
23
|
+
|
24
|
+
def recover(env)
|
25
|
+
return unless env[:machine] && env[:machine].state.id != :not_created
|
26
|
+
|
27
|
+
# only destroy if failed to complete bring up
|
28
|
+
unless @cleanup
|
29
|
+
@logger.debug('VM provider setup was completed, no need to halt/destroy')
|
30
|
+
return
|
31
|
+
end
|
32
|
+
|
33
|
+
# If we're not supposed to destroy on error then just return
|
34
|
+
return unless env[:destroy_on_error]
|
35
|
+
|
36
|
+
if env[:halt_on_error]
|
37
|
+
halt_env = env.dup
|
38
|
+
halt_env.delete(:interrupted)
|
39
|
+
halt_env[:config_validate] = false
|
40
|
+
env[:action_runner].run(Action.action_halt, halt_env)
|
41
|
+
else
|
42
|
+
destroy_env = env.dup
|
43
|
+
destroy_env.delete(:interrupted)
|
44
|
+
destroy_env[:config_validate] = false
|
45
|
+
destroy_env[:force_confirm_destroy] = true
|
46
|
+
env[:action_runner].run(Action.action_destroy, destroy_env)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def completed
|
51
|
+
@cleanup = false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class SetupComplete
|
56
|
+
def initialize(app, _env)
|
57
|
+
@logger = Log4r::Logger.new('vagrant_libvirt::action::setup_complete')
|
58
|
+
@app = app
|
59
|
+
end
|
60
|
+
|
61
|
+
def call(env)
|
62
|
+
if env['vagrant-libvirt.complete'].nil? or !env['vagrant-libvirt.complete'].respond_to? :call
|
63
|
+
raise Errors::CallChainError, require_action: CleanupOnFailure.name, current_action: SetupComplete.name
|
64
|
+
end
|
65
|
+
|
66
|
+
@logger.debug('Marking provider setup as completed')
|
67
|
+
# mark provider as finished setup so that any failure after this
|
68
|
+
# point doesn't result in destroying or shutting down the VM
|
69
|
+
env['vagrant-libvirt.complete'].call
|
70
|
+
|
71
|
+
@app.call(env)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'log4r'
|
4
4
|
|
5
|
+
require 'vagrant-libvirt/util/resolvers'
|
6
|
+
|
5
7
|
module VagrantPlugins
|
6
8
|
module ProviderLibvirt
|
7
9
|
module Action
|
@@ -20,7 +22,7 @@ module VagrantPlugins
|
|
20
22
|
|
21
23
|
def _disks_print(disks)
|
22
24
|
disks.collect do |x|
|
23
|
-
"#{x[:device]}(#{x[:type]}
|
25
|
+
"#{x[:device]}(#{x[:type]}, #{x[:bus]}, #{x[:size]})"
|
24
26
|
end.join(', ')
|
25
27
|
end
|
26
28
|
|
@@ -73,14 +75,12 @@ module VagrantPlugins
|
|
73
75
|
@graphics_autoport = config.graphics_autoport
|
74
76
|
@graphics_port = config.graphics_port
|
75
77
|
@graphics_ip = config.graphics_ip
|
76
|
-
@graphics_passwd =
|
77
|
-
|
78
|
-
else
|
79
|
-
"passwd='#{config.graphics_passwd}'"
|
80
|
-
end
|
78
|
+
@graphics_passwd = config.graphics_passwd
|
79
|
+
@graphics_gl = config.graphics_gl
|
81
80
|
@video_type = config.video_type
|
82
81
|
@sound_type = config.sound_type
|
83
82
|
@video_vram = config.video_vram
|
83
|
+
@video_accel3d = config.video_accel3d
|
84
84
|
@keymap = config.keymap
|
85
85
|
@kvm_hidden = config.kvm_hidden
|
86
86
|
|
@@ -133,11 +133,19 @@ module VagrantPlugins
|
|
133
133
|
# RNG device passthrough
|
134
134
|
@rng = config.rng
|
135
135
|
|
136
|
+
# Memballoon
|
137
|
+
@memballoon_enabled = config.memballoon_enabled
|
138
|
+
@memballoon_model = config.memballoon_model
|
139
|
+
@memballoon_pci_bus = config.memballoon_pci_bus
|
140
|
+
@memballoon_pci_slot = config.memballoon_pci_slot
|
141
|
+
|
136
142
|
config = env[:machine].provider_config
|
137
143
|
@domain_type = config.driver
|
138
144
|
|
139
145
|
@os_type = 'hvm'
|
140
146
|
|
147
|
+
resolver = ::VagrantPlugins::ProviderLibvirt::Util::DiskDeviceResolver.new(prefix=@disk_device[0..1])
|
148
|
+
|
141
149
|
# Get path to domain image from the storage pool selected if we have a box.
|
142
150
|
if env[:machine].config.vm.box
|
143
151
|
if @snapshot_pool_name != @storage_pool_name
|
@@ -145,6 +153,12 @@ module VagrantPlugins
|
|
145
153
|
else
|
146
154
|
pool_name = @storage_pool_name
|
147
155
|
end
|
156
|
+
|
157
|
+
# special handling for domain volume
|
158
|
+
env[:box_volumes][0][:device] = env[:box_volumes][0].fetch(:device, @disk_device)
|
159
|
+
|
160
|
+
resolver.resolve!(env[:box_volumes])
|
161
|
+
|
148
162
|
@logger.debug "Search for volumes in pool: #{pool_name}"
|
149
163
|
env[:box_volumes].each_index do |index|
|
150
164
|
suffix_index = index > 0 ? "_#{index}" : ''
|
@@ -152,14 +166,16 @@ module VagrantPlugins
|
|
152
166
|
name: "#{@name}#{suffix_index}.img"
|
153
167
|
).find { |x| x.pool_name == pool_name }
|
154
168
|
raise Errors::DomainVolumeExists if domain_volume.nil?
|
169
|
+
|
155
170
|
@domain_volumes.push({
|
156
|
-
:dev =>
|
171
|
+
:dev => env[:box_volumes][index][:device],
|
157
172
|
:cache => @domain_volume_cache,
|
158
173
|
:bus => @disk_bus,
|
159
174
|
:path => domain_volume.path,
|
160
175
|
:virtual_size => env[:box_volumes][index][:virtual_size]
|
161
176
|
})
|
162
|
-
|
177
|
+
end
|
178
|
+
|
163
179
|
end
|
164
180
|
|
165
181
|
# If we have a box, take the path from the domain volume and set our storage_prefix.
|
@@ -171,6 +187,8 @@ module VagrantPlugins
|
|
171
187
|
storage_prefix = get_disk_storage_prefix(env, @storage_pool_name)
|
172
188
|
end
|
173
189
|
|
190
|
+
resolver.resolve!(@disks)
|
191
|
+
|
174
192
|
@disks.each do |disk|
|
175
193
|
disk[:path] ||= _disk_name(@name, disk)
|
176
194
|
|
@@ -219,6 +237,20 @@ module VagrantPlugins
|
|
219
237
|
end
|
220
238
|
end
|
221
239
|
|
240
|
+
@serials = config.serials
|
241
|
+
|
242
|
+
@serials.each do |serial|
|
243
|
+
next unless serial[:source] && serial[:source][:path]
|
244
|
+
|
245
|
+
dir = File.dirname(serial[:source][:path])
|
246
|
+
begin
|
247
|
+
FileUtils.mkdir_p(dir)
|
248
|
+
rescue ::Errno::EACCES
|
249
|
+
raise Errors::SerialCannotCreatePathError,
|
250
|
+
path: dir
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
222
254
|
# Output the settings we're going to use to the user
|
223
255
|
env[:ui].info(I18n.t('vagrant_libvirt.creating_domain'))
|
224
256
|
env[:ui].info(" -- Name: #{@name}")
|
@@ -268,7 +300,7 @@ module VagrantPlugins
|
|
268
300
|
end
|
269
301
|
env[:ui].info(" -- Storage pool: #{@storage_pool_name}")
|
270
302
|
@domain_volumes.each do |volume|
|
271
|
-
env[:ui].info(" -- Image(#{volume[:
|
303
|
+
env[:ui].info(" -- Image(#{volume[:dev]}): #{volume[:path]}, #{volume[:bus]}, #{volume[:virtual_size].to_GB}G")
|
272
304
|
end
|
273
305
|
|
274
306
|
if not @disk_driver_opts.empty?
|
@@ -282,9 +314,10 @@ module VagrantPlugins
|
|
282
314
|
env[:ui].info(" -- Graphics Type: #{@graphics_type}")
|
283
315
|
env[:ui].info(" -- Graphics Port: #{@graphics_port}")
|
284
316
|
env[:ui].info(" -- Graphics IP: #{@graphics_ip}")
|
285
|
-
env[:ui].info(" -- Graphics Password: #{@graphics_passwd.
|
317
|
+
env[:ui].info(" -- Graphics Password: #{@graphics_passwd.nil? ? 'Not defined' : 'Defined'}")
|
286
318
|
env[:ui].info(" -- Video Type: #{@video_type}")
|
287
319
|
env[:ui].info(" -- Video VRAM: #{@video_vram}")
|
320
|
+
env[:ui].info(" -- Video 3D accel: #{@video_accel3d}")
|
288
321
|
env[:ui].info(" -- Sound Type: #{@sound_type}")
|
289
322
|
env[:ui].info(" -- Keymap: #{@keymap}")
|
290
323
|
env[:ui].info(" -- TPM Backend: #{@tpm_type}")
|
@@ -295,6 +328,12 @@ module VagrantPlugins
|
|
295
328
|
env[:ui].info(" -- TPM Path: #{@tpm_path}")
|
296
329
|
end
|
297
330
|
|
331
|
+
if @memballoon_enabled
|
332
|
+
env[:ui].info(" -- Memballoon model: #{@memballoon_model}")
|
333
|
+
env[:ui].info(" -- Memballoon bus: #{@memballoon_pci_bus}")
|
334
|
+
env[:ui].info(" -- Memballoon slot: #{@memballoon_pci_slot}")
|
335
|
+
end
|
336
|
+
|
298
337
|
@boot_order.each do |device|
|
299
338
|
env[:ui].info(" -- Boot device: #{device}")
|
300
339
|
end
|
@@ -379,6 +418,13 @@ module VagrantPlugins
|
|
379
418
|
env[:ui].info(" -- smartcard device: mode=#{@smartcard_dev[:mode]}, type=#{@smartcard_dev[:type]}")
|
380
419
|
end
|
381
420
|
|
421
|
+
@serials.each_with_index do |serial, port|
|
422
|
+
if serial[:source]
|
423
|
+
env[:ui].info(" -- SERIAL(COM#{port}: redirect to #{serial[:source][:path]}")
|
424
|
+
env[:ui].warn(I18n.t('vagrant_libvirt.warnings.creating_domain_console_access_disabled'))
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
382
428
|
unless @qemu_args.empty?
|
383
429
|
env[:ui].info(' -- Command line args: ')
|
384
430
|
@qemu_args.each do |arg|
|
@@ -213,8 +213,12 @@ module VagrantPlugins
|
|
213
213
|
type: :static,
|
214
214
|
ip: options[:ip],
|
215
215
|
netmask: options[:netmask],
|
216
|
-
gateway: options[:gateway]
|
216
|
+
gateway: options[:gateway],
|
217
|
+
route: options[:route]
|
217
218
|
}.merge(network)
|
219
|
+
if IPAddr.new(options[:ip]).ipv6?
|
220
|
+
network[:type] = :static6
|
221
|
+
end
|
218
222
|
else
|
219
223
|
network[:type] = :dhcp
|
220
224
|
end
|
@@ -30,6 +30,15 @@ module VagrantPlugins
|
|
30
30
|
|
31
31
|
def call(env)
|
32
32
|
if env[:machine].provider_config.qemu_use_session
|
33
|
+
# Get a list of all (active and inactive) Libvirt networks. This
|
34
|
+
# triggers a side effect to ensure networking is fully available
|
35
|
+
# for VMs using sessions. It is likely that this should be done
|
36
|
+
# to determine the correct virtual device for the management
|
37
|
+
# network for sessions instead of assuming the default of virbr0.
|
38
|
+
@available_networks = libvirt_networks(
|
39
|
+
env[:machine].provider.driver.system_connection
|
40
|
+
)
|
41
|
+
|
33
42
|
@app.call(env)
|
34
43
|
return
|
35
44
|
end
|
@@ -208,6 +217,9 @@ module VagrantPlugins
|
|
208
217
|
|
209
218
|
# Create a private network.
|
210
219
|
create_private_network(env)
|
220
|
+
write_created_network(env)
|
221
|
+
else
|
222
|
+
write_created_network(env) unless @options[:always_destroy] == false
|
211
223
|
end
|
212
224
|
end
|
213
225
|
|
@@ -247,6 +259,9 @@ module VagrantPlugins
|
|
247
259
|
|
248
260
|
# Create a private network.
|
249
261
|
create_private_network(env)
|
262
|
+
write_created_network(env)
|
263
|
+
else
|
264
|
+
write_created_network(env) unless @options[:always_destroy] == false
|
250
265
|
end
|
251
266
|
end
|
252
267
|
|
@@ -273,6 +288,9 @@ module VagrantPlugins
|
|
273
288
|
|
274
289
|
# Create a private network.
|
275
290
|
create_private_network(env)
|
291
|
+
write_created_network(env)
|
292
|
+
else
|
293
|
+
write_created_network(env) unless @options[:always_destroy] == false
|
276
294
|
end
|
277
295
|
end
|
278
296
|
|
@@ -334,6 +352,10 @@ module VagrantPlugins
|
|
334
352
|
@network_dhcp_enabled = false
|
335
353
|
end
|
336
354
|
|
355
|
+
if @options[:tftp_root]
|
356
|
+
@tftp_root = @options[:tftp_root]
|
357
|
+
end
|
358
|
+
|
337
359
|
@network_domain_name = @options[:domain_name]
|
338
360
|
|
339
361
|
begin
|
@@ -347,7 +369,9 @@ module VagrantPlugins
|
|
347
369
|
rescue => e
|
348
370
|
raise Errors::CreateNetworkError, error_message: e.message
|
349
371
|
end
|
372
|
+
end
|
350
373
|
|
374
|
+
def write_created_network(env)
|
351
375
|
created_networks_file = env[:machine].data_dir + 'created_networks'
|
352
376
|
|
353
377
|
message = 'Saving information about created network ' \
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'log4r'
|
4
|
+
require 'rexml'
|
4
5
|
|
5
6
|
module VagrantPlugins
|
6
7
|
module ProviderLibvirt
|
@@ -48,37 +49,121 @@ module VagrantPlugins
|
|
48
49
|
# cdroms are consider volumes, but cannot be destroyed
|
49
50
|
domain.destroy(destroy_volumes: true)
|
50
51
|
else
|
52
|
+
domain_xml = libvirt_domain.xml_desc(1)
|
53
|
+
xml_descr = REXML::Document.new(domain_xml)
|
54
|
+
disks_xml = REXML::XPath.match(xml_descr, '/domain/devices/disk[@device="disk"]')
|
55
|
+
have_aliases = !(REXML::XPath.match(disks_xml, './alias[@name="ua-box-volume-0"]').first).nil?
|
56
|
+
if !have_aliases
|
57
|
+
env[:ui].warn(I18n.t('vagrant_libvirt.destroy.obsolete_method'))
|
58
|
+
end
|
59
|
+
|
51
60
|
domain.destroy(destroy_volumes: false)
|
52
61
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
62
|
+
volumes = domain.volumes
|
63
|
+
|
64
|
+
# Remove root storage. If no aliases available, perform the removal by name and keep track
|
65
|
+
# of how many matches there are in the volumes. This will provide a fallback offset to where
|
66
|
+
# the additional storage devices are.
|
67
|
+
detected_box_volumes = 0
|
68
|
+
if have_aliases
|
69
|
+
REXML::XPath.match(disks_xml, './alias[contains(@name, "ua-box-volume-")]').each do |box_disk|
|
70
|
+
diskname = box_disk.parent.elements['source'].attributes['file'].rpartition('/').last
|
71
|
+
detected_box_volumes += 1
|
72
|
+
|
73
|
+
destroy_volume(volumes, diskname, env)
|
74
|
+
end
|
75
|
+
else
|
76
|
+
# fallback to try and infer which boxes are box images, as they are listed first
|
77
|
+
# as soon as there is no match, can exit
|
78
|
+
disks_xml.each_with_index do |box_disk, idx|
|
79
|
+
name = libvirt_domain.name + (idx == 0 ? '.img' : "_#{idx}.img")
|
80
|
+
diskname = box_disk.elements['source'].attributes['file'].rpartition('/').last
|
81
|
+
|
82
|
+
break if name != diskname
|
83
|
+
detected_box_volumes += 1
|
84
|
+
|
85
|
+
root_disk = volumes.select do |x|
|
86
|
+
x.name == name if x
|
68
87
|
end.first
|
69
|
-
|
88
|
+
if root_disk
|
89
|
+
root_disk.destroy
|
90
|
+
end
|
70
91
|
end
|
71
92
|
end
|
72
93
|
|
73
|
-
#
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
94
|
+
# work out if there are any custom disks attached that wasn't done by vagrant-libvirt,
|
95
|
+
# and warn there might be unexpected behaviour
|
96
|
+
total_disks = disks_xml.length
|
97
|
+
offset = total_disks - env[:machine].provider_config.disks.length
|
98
|
+
if offset != detected_box_volumes
|
99
|
+
env[:ui].warn(I18n.t('vagrant_libvirt.destroy.unexpected_volumes'))
|
100
|
+
end
|
101
|
+
|
102
|
+
if !have_aliases
|
103
|
+
# if no aliases found, see if it's possible to check the number of box disks
|
104
|
+
# otherwise the destroy could remove the wrong disk by accident.
|
105
|
+
if env[:machine].box != nil
|
106
|
+
box_disks = env[:machine].box.metadata.fetch('disks', [1])
|
107
|
+
offset = box_disks.length
|
108
|
+
if offset != detected_box_volumes
|
109
|
+
env[:ui].warn(I18n.t('vagrant_libvirt.destroy.expected_removal_mismatch'))
|
110
|
+
end
|
111
|
+
else
|
112
|
+
env[:ui].warn(I18n.t('vagrant_libvirt.destroy.box_metadata_unavailable'))
|
113
|
+
end
|
114
|
+
|
115
|
+
# offset only used when no aliases available
|
116
|
+
offset = detected_box_volumes
|
117
|
+
end
|
118
|
+
|
119
|
+
env[:machine].provider_config.disks.each_with_index.each do |disk, index|
|
120
|
+
# shared disks remove only manually or ???
|
121
|
+
next if disk[:allow_existing]
|
122
|
+
|
123
|
+
# look for exact match using aliases which will be used
|
124
|
+
# for subsequent domain creations
|
125
|
+
if have_aliases
|
126
|
+
domain_disk = REXML::XPath.match(disks_xml, './alias[@name="ua-disk-volume-' + index.to_s + '"]').first
|
127
|
+
domain_disk = domain_disk.parent if !domain_disk.nil?
|
128
|
+
else
|
129
|
+
# otherwise fallback to find the disk by device if specified by user
|
130
|
+
# and finally index counting with offset and hope the match is correct
|
131
|
+
if !disk[:device].nil?
|
132
|
+
domain_disk = REXML::XPath.match(disks_xml, './target[@dev="' + disk[:device] + '"]').first
|
133
|
+
domain_disk = domain_disk.parent if !domain_disk.nil?
|
134
|
+
else
|
135
|
+
domain_disk = disks_xml[offset + index]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
next if domain_disk.nil?
|
140
|
+
|
141
|
+
diskname = domain_disk.elements['source'].attributes['file'].rpartition('/').last
|
142
|
+
destroy_volume(volumes, diskname, env)
|
143
|
+
end
|
78
144
|
end
|
79
145
|
|
80
146
|
@app.call(env)
|
81
147
|
end
|
148
|
+
|
149
|
+
protected
|
150
|
+
|
151
|
+
def destroy_volume(volumes, diskname, env)
|
152
|
+
# diskname is unique
|
153
|
+
libvirt_disk = volumes.select do |x|
|
154
|
+
x.name == diskname if x
|
155
|
+
end.first
|
156
|
+
if libvirt_disk
|
157
|
+
libvirt_disk.destroy
|
158
|
+
elsif disk[:path]
|
159
|
+
poolname = env[:machine].provider_config.storage_pool_name
|
160
|
+
libvirt_disk = volumes.select do |x|
|
161
|
+
# FIXME: can remove pool/target.img and pool/123/target.img
|
162
|
+
x.path =~ /\/#{disk[:path]}$/ && x.pool_name == poolname
|
163
|
+
end.first
|
164
|
+
libvirt_disk.destroy if libvirt_disk
|
165
|
+
end
|
166
|
+
end
|
82
167
|
end
|
83
168
|
end
|
84
169
|
end
|