vagrant-libvirt 0.6.2 → 0.8.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 +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
|
[](https://gitter.im/vagrant-libvirt/vagrant-libvirt?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
4
|
-
[](https://github.com/vagrant-libvirt/vagrant-libvirt/actions/workflows/unit-tests.yml)
|
|
5
5
|
[](https://coveralls.io/github/vagrant-libvirt/vagrant-libvirt?branch=master)
|
|
6
|
+
[](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
|