vagrant-libvirt 0.0.13 → 0.0.14
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 +7 -0
- data/Gemfile +4 -6
- data/README.md +24 -10
- data/Rakefile +0 -1
- data/example_box/Vagrantfile +3 -0
- data/lib/vagrant-libvirt/action.rb +28 -5
- data/lib/vagrant-libvirt/action/connect_libvirt.rb +3 -7
- data/lib/vagrant-libvirt/action/create_domain.rb +8 -0
- data/lib/vagrant-libvirt/action/create_network_interfaces.rb +20 -5
- data/lib/vagrant-libvirt/action/create_networks.rb +112 -45
- data/lib/vagrant-libvirt/action/destroy_networks.rb +21 -12
- data/lib/vagrant-libvirt/action/set_name_of_domain.rb +13 -3
- data/lib/vagrant-libvirt/action/share_folders.rb +1 -1
- data/lib/vagrant-libvirt/action/sync_folders.rb +10 -4
- data/lib/vagrant-libvirt/config.rb +24 -3
- data/lib/vagrant-libvirt/errors.rb +13 -5
- data/lib/vagrant-libvirt/templates/domain.xml.erb +5 -2
- data/lib/vagrant-libvirt/util/libvirt_util.rb +7 -0
- data/lib/vagrant-libvirt/version.rb +1 -1
- data/locales/en.yml +6 -1
- metadata +12 -23
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6a7de8bcfdcab60b3237c7d64fd047fa9b43bbf8
|
4
|
+
data.tar.gz: f98b1b521b2d6665be337341791ae260244d29eb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6d33e5ae966f1758ec327b73a9d3527cfa0b6c3ab461630beb4e13bc391c5f291ab04b48884bc0d568e2376ee3fda1361bce6efab0d3d5513b987f08f7b75513
|
7
|
+
data.tar.gz: 83408a1dcb5c55fd745e204b7d23f78cf1ec9d6e6eb5beb8a27f31cbff4154a916bd9068b7e80dade9318f97b504a77671171486ce954e65b9af73474487e151
|
data/Gemfile
CHANGED
@@ -4,11 +4,9 @@ source 'https://rubygems.org'
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
group :development do
|
7
|
-
|
8
|
-
gem
|
9
|
-
|
10
|
-
gem
|
11
|
-
gem 'coveralls', require: false
|
12
|
-
gem 'vagrant', :git => 'git://github.com/mitchellh/vagrant.git'
|
7
|
+
# We depend on Vagrant for development, but we don't add it as a
|
8
|
+
# gem dependency because we expect to be installed within the
|
9
|
+
# Vagrant environment itself using `vagrant plugin`.
|
10
|
+
gem "vagrant", :git => "git://github.com/mitchellh/vagrant.git"
|
13
11
|
end
|
14
12
|
|
data/README.md
CHANGED
@@ -99,14 +99,19 @@ This provider exposes quite a few provider-specific configuration options:
|
|
99
99
|
* `password` - Password to access Libvirt.
|
100
100
|
* `id_ssh_key_file` - The id ssh key file name to access Libvirt (eg: id_dsa or id_rsa or ... in the user .ssh directory)
|
101
101
|
* `storage_pool_name` - Libvirt storage pool name, where box image and instance snapshots will be stored.
|
102
|
-
* `default_network` - Libvirt default network name. If not specified default network name is 'default'.
|
103
102
|
|
104
103
|
### Domain Specific Options
|
105
104
|
|
105
|
+
* `disk_bus` - The type of disk device to emulate. Defaults to virtio if not set. Possible values are documented in libvirt's [description for _target_](http://libvirt.org/formatdomain.html#elementsDisks).
|
106
106
|
* `memory` - Amount of memory in MBytes. Defaults to 512 if not set.
|
107
107
|
* `cpus` - Number of virtual cpus. Defaults to 1 if not set.
|
108
108
|
* `nested` - [Enable nested virtualization](https://github.com/torvalds/linux/blob/master/Documentation/virtual/kvm/nested-vmx.txt). Default is false.
|
109
|
+
* `cpu_mode` - What cpu mode to use for nested virtualization. Defaults to 'host-model' if not set.
|
109
110
|
* `volume_cache` - Controls the cache mechanism. Possible values are "default", "none", "writethrough", "writeback", "directsync" and "unsafe". [See driver->cache in libvirt documentation](http://libvirt.org/formatdomain.html#elementsDisks).
|
111
|
+
* `kernel` - To launch the guest with a kernel residing on host filesystems (Equivalent to qemu `-kernel`)
|
112
|
+
* `initrd` - To specify the initramfs/initrd to use for the guest (Equivalent to qemu `-initrd`)
|
113
|
+
* `cmd_line` - Arguments passed on to the guest kernel initramfs or initrd to use (Equivalent to qemu `-append`)
|
114
|
+
|
110
115
|
|
111
116
|
Specific domain settings can be set for each domain separately in multi-VM
|
112
117
|
environment. Example below shows a part of Vagrantfile, where specific options
|
@@ -120,7 +125,7 @@ Vagrant.configure("2") do |config|
|
|
120
125
|
domain.memory = 2048
|
121
126
|
domain.cpus = 2
|
122
127
|
domain.nested = true
|
123
|
-
|
128
|
+
domain.volume_cache = 'none'
|
124
129
|
end
|
125
130
|
end
|
126
131
|
|
@@ -229,15 +234,24 @@ starts with 'libvirt__' string. Here is a list of those options:
|
|
229
234
|
Default mode is 'bridge'.
|
230
235
|
* `:mac` - MAC address for the interface.
|
231
236
|
|
232
|
-
|
237
|
+
### Management Network
|
238
|
+
|
239
|
+
Vagrant-libvirt uses a private network to perform some management operations
|
240
|
+
on VMs. All VMs will have an interface connected to this network and
|
241
|
+
an IP address dynamically assigned by libvirt. This is in addition to any
|
242
|
+
networks you configure. The name and address used by this network are
|
243
|
+
configurable at the provider level.
|
244
|
+
|
245
|
+
* `management_network_name` - Name of libvirt network to which all VMs will be connected. If not specified the default is 'vagrant-libvirt'.
|
246
|
+
* `management_network_address` - Address of network to which all VMs will be connected. Must include the address and subnet mask. If not specified the default is '192.168.121.0/24'.
|
233
247
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
248
|
+
You may wonder how vagrant-libvirt knows the IP address a VM received.
|
249
|
+
Libvirt doesn't provide a standard way to find out the IP address of a running
|
250
|
+
domain. But we do know the MAC address of the virtual machine's interface on
|
251
|
+
the management network. Libvirt is closely connected with dnsmasq, which acts as
|
252
|
+
a DHCP server. dnsmasq writes lease information in the `/var/lib/libvirt/dnsmasq`
|
253
|
+
directory. Vagrant-libvirt looks for the MAC address in this file and extracts
|
254
|
+
the corresponding IP address.
|
241
255
|
|
242
256
|
## SSH Access To VM
|
243
257
|
|
data/Rakefile
CHANGED
data/example_box/Vagrantfile
CHANGED
@@ -52,6 +52,9 @@ Vagrant.configure("2") do |config|
|
|
52
52
|
# Libvirt storage pool name, where box image and instance snapshots will
|
53
53
|
# be stored.
|
54
54
|
libvirt.storage_pool_name = "default"
|
55
|
+
|
56
|
+
# Set a prefix for the machines that's different than the project dir name.
|
57
|
+
#libvirt.default_prefix = ''
|
55
58
|
end
|
56
59
|
end
|
57
60
|
|
@@ -25,7 +25,13 @@ module VagrantPlugins
|
|
25
25
|
b2.use CreateNetworks
|
26
26
|
b2.use CreateNetworkInterfaces
|
27
27
|
|
28
|
-
|
28
|
+
if Vagrant::VERSION < "1.4.0"
|
29
|
+
b2.use NFS
|
30
|
+
else
|
31
|
+
b2.use SyncedFolderCleanup
|
32
|
+
b2.use SyncedFolders
|
33
|
+
end
|
34
|
+
|
29
35
|
b2.use PrepareNFSSettings
|
30
36
|
b2.use ShareFolders
|
31
37
|
b2.use SetHostname
|
@@ -51,19 +57,32 @@ module VagrantPlugins
|
|
51
57
|
next if env[:result]
|
52
58
|
|
53
59
|
b2.use Call, IsSuspended do |env2, b3|
|
60
|
+
# if vm is suspended resume it then exit
|
54
61
|
if env2[:result]
|
55
62
|
b3.use ResumeDomain
|
56
63
|
next
|
57
64
|
end
|
58
65
|
|
59
|
-
# VM is not running or suspended.
|
60
|
-
|
61
|
-
#
|
62
|
-
b3.use
|
66
|
+
# VM is not running or suspended.
|
67
|
+
|
68
|
+
# Ensure networks are created and active
|
69
|
+
b3.use CreateNetworks
|
70
|
+
|
71
|
+
# Handle shared folders
|
72
|
+
if Vagrant::VERSION < "1.4.0"
|
73
|
+
b3.use NFS
|
74
|
+
else
|
75
|
+
b3.use SyncedFolderCleanup
|
76
|
+
b3.use SyncedFolders
|
77
|
+
end
|
63
78
|
b3.use PrepareNFSSettings
|
64
79
|
b3.use ShareFolders
|
65
80
|
|
81
|
+
# Start it..
|
66
82
|
b3.use StartDomain
|
83
|
+
|
84
|
+
# Machine should gain IP address when comming up,
|
85
|
+
# so wait for dhcp lease and store IP into machines data_dir.
|
67
86
|
b3.use WaitTillUp
|
68
87
|
end
|
69
88
|
end
|
@@ -302,6 +321,10 @@ module VagrantPlugins
|
|
302
321
|
autoload :WaitTillUp, action_root.join('wait_till_up')
|
303
322
|
autoload :SSHRun, 'vagrant/action/builtin/ssh_run'
|
304
323
|
autoload :HandleBoxUrl, 'vagrant/action/builtin/handle_box_url'
|
324
|
+
unless Vagrant::VERSION < "1.4.0"
|
325
|
+
autoload :SyncedFolders, 'vagrant/action/builtin/synced_folders'
|
326
|
+
autoload :SyncedFolderCleanup, 'vagrant/action/builtin/synced_folder_cleanup'
|
327
|
+
end
|
305
328
|
end
|
306
329
|
end
|
307
330
|
end
|
@@ -67,13 +67,9 @@ module VagrantPlugins
|
|
67
67
|
conn_attr[:libvirt_password] = config.password if config.password
|
68
68
|
|
69
69
|
# Setup command for retrieving IP address for newly created machine
|
70
|
-
# with some MAC address. Get it from dnsmasq leases table
|
71
|
-
|
72
|
-
|
73
|
-
ip_command = "LEASES='/var/lib/libvirt/dnsmasq/*.leases'; "
|
74
|
-
ip_command << "[ -f /var/lib/misc/dnsmasq.leases ] && "
|
75
|
-
ip_command << "LEASES='/var/lib/misc/dnsmasq.leases'; "
|
76
|
-
ip_command << "grep $mac $LEASES | awk '{ print $3 }'"
|
70
|
+
# with some MAC address. Get it from dnsmasq leases table
|
71
|
+
ip_command = %q[ LEASES=$(find /var/lib/libvirt/dnsmasq/ /var/lib/misc/ -name '*leases'); ]
|
72
|
+
ip_command << %q[ [ -n "$LEASES" ] && grep $mac $LEASES | awk '{ print $3 }' ]
|
77
73
|
conn_attr[:libvirt_ip_command] = ip_command
|
78
74
|
|
79
75
|
@logger.info("Connecting to Libvirt (#{uri}) ...")
|
@@ -19,9 +19,14 @@ module VagrantPlugins
|
|
19
19
|
# Gather some info about domain
|
20
20
|
@name = env[:domain_name]
|
21
21
|
@cpus = config.cpus
|
22
|
+
@cpu_mode = config.cpu_mode
|
23
|
+
@disk_bus = config.disk_bus
|
22
24
|
@nested = config.nested
|
23
25
|
@memory_size = config.memory*1024
|
24
26
|
@domain_volume_cache = config.volume_cache
|
27
|
+
@kernel = config.kernel
|
28
|
+
@cmd_line = config.cmd_line
|
29
|
+
@initrd = config.initrd
|
25
30
|
|
26
31
|
# TODO get type from driver config option
|
27
32
|
@domain_type = 'kvm'
|
@@ -44,6 +49,9 @@ module VagrantPlugins
|
|
44
49
|
env[:ui].info(" -- Storage pool: #{env[:machine].provider_config.storage_pool_name}")
|
45
50
|
env[:ui].info(" -- Image: #{@domain_volume_path}")
|
46
51
|
env[:ui].info(" -- Volume Cache: #{@domain_volume_cache}")
|
52
|
+
env[:ui].info(" -- Kernel: #{@kernel}")
|
53
|
+
env[:ui].info(" -- Initrd: #{@initrd}")
|
54
|
+
env[:ui].info(" -- Command line : #{@cmd_line}")
|
47
55
|
|
48
56
|
# Create libvirt domain.
|
49
57
|
# Is there a way to tell fog to create new domain with already
|
@@ -16,7 +16,7 @@ module VagrantPlugins
|
|
16
16
|
|
17
17
|
def initialize(app, env)
|
18
18
|
@logger = Log4r::Logger.new('vagrant_libvirt::action::create_network_interfaces')
|
19
|
-
@
|
19
|
+
@management_network_name = env[:machine].provider_config.management_network_name
|
20
20
|
@app = app
|
21
21
|
end
|
22
22
|
|
@@ -37,6 +37,7 @@ module VagrantPlugins
|
|
37
37
|
|
38
38
|
# Assign interfaces to slots.
|
39
39
|
env[:machine].config.vm.networks.each do |type, options|
|
40
|
+
@logger.debug "In config found network type #{type} options #{options}"
|
40
41
|
|
41
42
|
# Get options for this interface. Options can be specified in
|
42
43
|
# Vagrantfile in short format (:ip => ...), or provider format
|
@@ -51,8 +52,10 @@ module VagrantPlugins
|
|
51
52
|
end
|
52
53
|
|
53
54
|
free_slot = options[:adapter].to_i
|
55
|
+
@logger.debug "Using specified adapter slot #{free_slot}"
|
54
56
|
else
|
55
57
|
free_slot = find_empty(adapters)
|
58
|
+
@logger.debug "Adapter not specified so found slot #{free_slot}"
|
56
59
|
raise Errors::InterfaceSlotNotAvailable if free_slot == nil
|
57
60
|
end
|
58
61
|
|
@@ -104,6 +107,7 @@ module VagrantPlugins
|
|
104
107
|
# it has to be available during provisioning - ifdown command is
|
105
108
|
# not acceptable here.
|
106
109
|
next if slot_number == 0
|
110
|
+
@logger.debug "Configuring interface slot_number #{slot_number} options #{options}"
|
107
111
|
|
108
112
|
network = {
|
109
113
|
:interface => slot_number,
|
@@ -139,7 +143,10 @@ module VagrantPlugins
|
|
139
143
|
|
140
144
|
# Return network name according to interface options.
|
141
145
|
def interface_network(libvirt_client, options)
|
142
|
-
|
146
|
+
if options[:network_name]
|
147
|
+
@logger.debug "Found network by name"
|
148
|
+
return options[:network_name]
|
149
|
+
end
|
143
150
|
|
144
151
|
# Get list of all (active and inactive) libvirt networks.
|
145
152
|
available_networks = libvirt_networks(libvirt_client)
|
@@ -147,12 +154,20 @@ module VagrantPlugins
|
|
147
154
|
if options[:ip]
|
148
155
|
address = network_address(options[:ip], options[:netmask])
|
149
156
|
available_networks.each do |network|
|
150
|
-
|
157
|
+
if address == network[:network_address]
|
158
|
+
@logger.debug "Found network by ip"
|
159
|
+
return network[:name]
|
160
|
+
end
|
151
161
|
end
|
152
162
|
end
|
153
163
|
|
154
|
-
#
|
155
|
-
|
164
|
+
# the management network always gets attached to slot 0
|
165
|
+
# because the first network is of type forwarded_port.
|
166
|
+
# this is confusing.
|
167
|
+
# TODO only iterate over networks of type private_network
|
168
|
+
# and prepend the management network to that list
|
169
|
+
@logger.debug "Did not find network so using default of #{@management_network_name}"
|
170
|
+
@management_network_name
|
156
171
|
end
|
157
172
|
end
|
158
173
|
end
|
@@ -2,6 +2,7 @@ require 'log4r'
|
|
2
2
|
require 'vagrant/util/network_ip'
|
3
3
|
require 'vagrant/util/scoped_hash_override'
|
4
4
|
require 'ipaddr'
|
5
|
+
require 'thread'
|
5
6
|
|
6
7
|
module VagrantPlugins
|
7
8
|
module ProviderLibvirt
|
@@ -13,6 +14,8 @@ module VagrantPlugins
|
|
13
14
|
include VagrantPlugins::ProviderLibvirt::Util::ErbTemplate
|
14
15
|
include VagrantPlugins::ProviderLibvirt::Util::LibvirtUtil
|
15
16
|
|
17
|
+
@@lock = Mutex.new
|
18
|
+
|
16
19
|
def initialize(app, env)
|
17
20
|
mess = 'vagrant_libvirt::action::create_networks'
|
18
21
|
@logger = Log4r::Logger.new(mess)
|
@@ -25,60 +28,98 @@ module VagrantPlugins
|
|
25
28
|
|
26
29
|
def call(env)
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
management_network_name = env[:machine].provider_config.management_network_name
|
32
|
+
management_network_address = env[:machine].provider_config.management_network_address
|
33
|
+
@logger.info "Using #{management_network_name} at #{management_network_address} as the management network"
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
begin
|
36
|
+
management_network_ip = IPAddr.new(management_network_address)
|
37
|
+
rescue ArgumentError
|
38
|
+
raise Errors::ManagementNetworkError,
|
39
|
+
error_message: "#{management_network_address} is not a valid IP address"
|
40
|
+
end
|
36
41
|
|
37
|
-
|
38
|
-
|
39
|
-
# creating them via libvirt API, so this provider doesn't implement
|
40
|
-
# them.
|
41
|
-
next if type != :private_network
|
42
|
+
# capture address into $1 and mask into $2
|
43
|
+
management_network_ip.inspect =~ /IPv4:(.*)\/(.*)>/
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
if $2 == '255.255.255.255'
|
46
|
+
raise Errors::ManagementNetworkError,
|
47
|
+
error_message: "#{management_network_address} does not include both an address and subnet mask"
|
48
|
+
end
|
49
|
+
|
50
|
+
management_network_options = {
|
51
|
+
network_name: management_network_name,
|
52
|
+
ip: $1,
|
53
|
+
netmask: $2,
|
54
|
+
dhcp_enabled: true,
|
55
|
+
forward_mode: 'nat',
|
56
|
+
}
|
57
|
+
|
58
|
+
# add management network to list of networks to check
|
59
|
+
networks = [ management_network_options ]
|
60
|
+
|
61
|
+
env[:machine].config.vm.networks.each do |type, original_options|
|
62
|
+
# There are two other types public network and port forwarding,
|
63
|
+
# but there are problems with creating them via libvirt API,
|
64
|
+
# so this provider doesn't implement them.
|
65
|
+
next if type != :private_network
|
66
|
+
# Options can be specified in Vagrantfile in short format (:ip => ...),
|
67
|
+
# or provider format # (:libvirt__network_name => ...).
|
68
|
+
# https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/util/scoped_hash_override.rb
|
69
|
+
options = scoped_hash_override(original_options, :libvirt)
|
70
|
+
# use default values if not already set
|
71
|
+
options = {
|
48
72
|
netmask: '255.255.255.0',
|
49
73
|
dhcp_enabled: true,
|
50
74
|
forward_mode: 'nat',
|
51
|
-
}.merge(
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
75
|
+
}.merge(options)
|
76
|
+
# add to list of networks to check
|
77
|
+
networks.push(options)
|
78
|
+
end
|
79
|
+
|
80
|
+
# only one vm at a time should try to set up networks
|
81
|
+
# otherwise they'll have inconsitent views of current state
|
82
|
+
# and conduct redundant operations that cause errors
|
83
|
+
@@lock.synchronize do
|
84
|
+
# Iterate over networks If some network is not
|
85
|
+
# available, create it if possible. Otherwise raise an error.
|
86
|
+
networks.each do |options|
|
87
|
+
@logger.debug "Searching for network with options #{options}"
|
88
|
+
|
89
|
+
# should fix other methods so this doesn't have to be instance var
|
90
|
+
@options = options
|
91
|
+
|
92
|
+
# Get a list of all (active and inactive) libvirt networks. This
|
93
|
+
# list is used throughout this class and should be easier to
|
94
|
+
# process than libvirt API calls.
|
95
|
+
@available_networks = libvirt_networks(env[:libvirt_compute].client)
|
96
|
+
|
97
|
+
# Prepare a hash describing network for this specific interface.
|
98
|
+
@interface_network = {
|
99
|
+
name: nil,
|
100
|
+
ip_address: nil,
|
101
|
+
netmask: @options[:netmask],
|
102
|
+
network_address: nil,
|
103
|
+
bridge_name: nil,
|
104
|
+
created: false,
|
105
|
+
active: false,
|
106
|
+
autostart: false,
|
107
|
+
libvirt_network: nil,
|
108
|
+
}
|
109
|
+
|
110
|
+
if @options[:ip]
|
111
|
+
handle_ip_option(env)
|
112
|
+
# in vagrant 1.2.3 and later it is not possible to take this branch
|
113
|
+
# because cannot have name without ip
|
114
|
+
# https://github.com/mitchellh/vagrant/commit/cf2f6da4dbcb4f57c9cdb3b94dcd0bba62c5f5fd
|
115
|
+
elsif @options[:network_name]
|
116
|
+
handle_network_name_option
|
76
117
|
end
|
77
|
-
end
|
78
118
|
|
79
|
-
|
80
|
-
|
119
|
+
autostart_network if !@interface_network[:autostart]
|
120
|
+
activate_network if !@interface_network[:active]
|
81
121
|
end
|
122
|
+
end
|
82
123
|
|
83
124
|
@app.call(env)
|
84
125
|
end
|
@@ -87,6 +128,7 @@ module VagrantPlugins
|
|
87
128
|
|
88
129
|
# Return hash of network for specified name, or nil if not found.
|
89
130
|
def lookup_network_by_name(network_name)
|
131
|
+
@logger.debug "looking up network named #{network_name}"
|
90
132
|
@available_networks.each do |network|
|
91
133
|
return network if network[:name] == network_name
|
92
134
|
end
|
@@ -95,12 +137,25 @@ module VagrantPlugins
|
|
95
137
|
|
96
138
|
# Return hash of network for specified bridge, or nil if not found.
|
97
139
|
def lookup_bridge_by_name(bridge_name)
|
140
|
+
@logger.debug "looking up bridge named #{bridge_name}"
|
98
141
|
@available_networks.each do |network|
|
99
142
|
return network if network[:bridge_name] == bridge_name
|
100
143
|
end
|
101
144
|
nil
|
102
145
|
end
|
103
146
|
|
147
|
+
# Throw an error if dhcp setting for an existing network does not
|
148
|
+
# match what was configured in the vagrantfile
|
149
|
+
# since we always enable dhcp for the management network
|
150
|
+
# this ensures we wont start a vm vagrant cant reach
|
151
|
+
def verify_dhcp
|
152
|
+
unless @options[:dhcp_enabled] == @interface_network[:dhcp_enabled]
|
153
|
+
raise Errors::DHCPMismatch,
|
154
|
+
network_name: @interface_network[:name],
|
155
|
+
requested: @options[:dhcp_enabled] ? 'enabled' : 'disabled'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
104
159
|
# Handle only situations, when ip is specified. Variables @options and
|
105
160
|
# @available_networks should be filled before calling this function.
|
106
161
|
def handle_ip_option(env)
|
@@ -120,11 +175,18 @@ module VagrantPlugins
|
|
120
175
|
if available_network[:network_address] == \
|
121
176
|
@interface_network[:network_address]
|
122
177
|
@interface_network = available_network
|
178
|
+
@logger.debug "found existing network by ip, values are"
|
179
|
+
@logger.debug @interface_network
|
123
180
|
break
|
124
181
|
end
|
125
182
|
end
|
126
183
|
|
184
|
+
if @interface_network[:created]
|
185
|
+
verify_dhcp
|
186
|
+
end
|
187
|
+
|
127
188
|
if @options[:network_name]
|
189
|
+
@logger.debug "Checking that network name does not clash with ip"
|
128
190
|
if @interface_network[:created]
|
129
191
|
# Just check for mismatch error here - if name and ip from
|
130
192
|
# config match together.
|
@@ -156,6 +218,7 @@ module VagrantPlugins
|
|
156
218
|
# Is name for new network set? If not, generate a unique one.
|
157
219
|
count = 0
|
158
220
|
while @interface_network[:name].nil?
|
221
|
+
@logger.debug "generating name for network"
|
159
222
|
|
160
223
|
# Generate a network name.
|
161
224
|
network_name = env[:root_path].basename.to_s.dup
|
@@ -171,6 +234,7 @@ module VagrantPlugins
|
|
171
234
|
# Generate a unique name for network bridge.
|
172
235
|
count = 0
|
173
236
|
while @interface_network[:bridge_name].nil?
|
237
|
+
@logger.debug "generating name for bridge"
|
174
238
|
bridge_name = 'virbr'
|
175
239
|
bridge_name << count.to_s
|
176
240
|
count += 1
|
@@ -195,6 +259,8 @@ module VagrantPlugins
|
|
195
259
|
if !@interface_network
|
196
260
|
raise Errors::NetworkNotAvailableError,
|
197
261
|
network_name: @options[:network_name]
|
262
|
+
else
|
263
|
+
verify_dhcp
|
198
264
|
end
|
199
265
|
end
|
200
266
|
|
@@ -234,6 +300,7 @@ module VagrantPlugins
|
|
234
300
|
begin
|
235
301
|
@interface_network[:libvirt_network] = \
|
236
302
|
@libvirt_client.define_network_xml(to_xml('private_network'))
|
303
|
+
@logger.debug "created network"
|
237
304
|
rescue => e
|
238
305
|
raise Errors::CreateNetworkError, error_message: e.message
|
239
306
|
end
|
@@ -18,7 +18,7 @@ module VagrantPlugins
|
|
18
18
|
# data directory, created_networks file holds UUIDs of each network.
|
19
19
|
created_networks_file = env[:machine].data_dir + 'created_networks'
|
20
20
|
|
21
|
-
@logger.info '
|
21
|
+
@logger.info 'Checking if any networks were created'
|
22
22
|
# If created_networks file doesn't exist, there are no networks we
|
23
23
|
# need to remove.
|
24
24
|
unless File.exist?(created_networks_file)
|
@@ -26,39 +26,45 @@ module VagrantPlugins
|
|
26
26
|
return @app.call(env)
|
27
27
|
end
|
28
28
|
|
29
|
-
@logger.info '
|
29
|
+
@logger.info 'File with created networks exists'
|
30
30
|
|
31
31
|
# Iterate over each created network UUID and try to remove it.
|
32
32
|
created_networks = []
|
33
33
|
file = File.open(created_networks_file, 'r')
|
34
34
|
file.readlines.each do |network_uuid|
|
35
|
-
@logger.info network_uuid
|
35
|
+
@logger.info "Checking for #{network_uuid}"
|
36
|
+
# lookup_network_by_uuid throws same exception
|
37
|
+
# if there is an error or if the network just doesn't exist
|
36
38
|
begin
|
37
39
|
libvirt_network = env[:libvirt_compute].client.lookup_network_by_uuid(
|
38
40
|
network_uuid)
|
39
|
-
rescue
|
40
|
-
|
41
|
-
|
41
|
+
rescue Libvirt::RetrieveError => e
|
42
|
+
# this network is already destroyed, so move on
|
43
|
+
if e.message =~ /Network not found/
|
44
|
+
@logger.info "It is already undefined"
|
45
|
+
next
|
46
|
+
# some other error occured, so raise it again
|
47
|
+
else
|
48
|
+
raise e
|
49
|
+
end
|
42
50
|
end
|
43
51
|
|
44
|
-
# Maybe network doesn't exist anymore.
|
45
|
-
next unless libvirt_network
|
46
|
-
|
47
52
|
# Skip removing if network has still active connections.
|
48
53
|
xml = Nokogiri::XML(libvirt_network.xml_desc)
|
49
54
|
connections = xml.xpath('/network/@connections').first
|
50
|
-
@logger.info connections
|
51
55
|
if connections != nil
|
56
|
+
@logger.info "Still has connections so will not undefine"
|
52
57
|
created_networks << network_uuid
|
53
58
|
next
|
54
59
|
end
|
55
60
|
|
56
|
-
# Shutdown network first.
|
57
|
-
libvirt_network.destroy
|
58
61
|
|
62
|
+
# Shutdown network first.
|
59
63
|
# Undefine network.
|
60
64
|
begin
|
65
|
+
libvirt_network.destroy
|
61
66
|
libvirt_network.undefine
|
67
|
+
@logger.info "Undefined it"
|
62
68
|
rescue => e
|
63
69
|
raise Error::DestroyNetworkError,
|
64
70
|
network_name: libvirt_network.name,
|
@@ -68,13 +74,16 @@ module VagrantPlugins
|
|
68
74
|
file.close
|
69
75
|
|
70
76
|
# Update status of created networks after removing some/all of them.
|
77
|
+
# Not sure why we are doing this, something else seems to always delete the file
|
71
78
|
if created_networks.length > 0
|
72
79
|
File.open(created_networks_file, 'w') do |file|
|
80
|
+
@logger.info "Writing new created_networks file"
|
73
81
|
created_networks.each do |network_uuid|
|
74
82
|
file.puts network_uuid
|
75
83
|
end
|
76
84
|
end
|
77
85
|
else
|
86
|
+
@logger.info "Deleting created_networks file"
|
78
87
|
File.delete(created_networks_file)
|
79
88
|
end
|
80
89
|
|
@@ -5,21 +5,31 @@ module VagrantPlugins
|
|
5
5
|
# Setup name for domain and domain volumes.
|
6
6
|
class SetNameOfDomain
|
7
7
|
def initialize(app, env)
|
8
|
+
@logger = Log4r::Logger.new("vagrant_libvirt::action::set_name_of_domain")
|
8
9
|
@app = app
|
9
10
|
end
|
10
11
|
|
11
12
|
def call(env)
|
12
13
|
require 'securerandom'
|
13
|
-
|
14
|
+
config = env[:machine].provider_config
|
15
|
+
if config.default_prefix.nil?
|
16
|
+
env[:domain_name] = env[:root_path].basename.to_s.dup
|
17
|
+
else
|
18
|
+
env[:domain_name] = config.default_prefix.to_s
|
19
|
+
end
|
14
20
|
env[:domain_name].gsub!(/[^-a-z0-9_]/i, '')
|
15
21
|
env[:domain_name] << '_'
|
16
22
|
env[:domain_name] << env[:machine].name.to_s
|
17
|
-
|
23
|
+
|
24
|
+
@logger.info("Looking for domain #{env[:domain_name]} through list #{env[:libvirt_compute].servers.all}")
|
18
25
|
# Check if the domain name is not already taken
|
19
26
|
domain = ProviderLibvirt::Util::Collection.find_matching(
|
20
27
|
env[:libvirt_compute].servers.all, env[:domain_name])
|
28
|
+
|
29
|
+
@logger.info("Looking for domain #{env[:domain_name]}")
|
30
|
+
|
21
31
|
if domain != nil
|
22
|
-
raise
|
32
|
+
raise ProviderLibvirt::Errors::DomainNameExists,
|
23
33
|
:domain_name => env[:domain_name]
|
24
34
|
end
|
25
35
|
|
@@ -27,7 +27,7 @@ module VagrantPlugins
|
|
27
27
|
# avoid creating an additional directory with rsync
|
28
28
|
hostpath = "#{hostpath}/" if hostpath !~ /\/$/
|
29
29
|
|
30
|
-
env[:ui].info(I18n.t(
|
30
|
+
env[:ui].info(I18n.t('vagrant_libvirt.rsync_folder',
|
31
31
|
:hostpath => hostpath,
|
32
32
|
:guestpath => guestpath))
|
33
33
|
|
@@ -38,9 +38,9 @@ module VagrantPlugins
|
|
38
38
|
|
39
39
|
# Rsync over to the guest path using the SSH info
|
40
40
|
command = [
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
'rsync', '--del', '--verbose', '--archive', '-z',
|
42
|
+
'--exclude', '.vagrant/',
|
43
|
+
'-e', "ssh -p #{ssh_info[:port]} #{proxycommand} -o StrictHostKeyChecking=no #{ssh_key_options(ssh_info)}",
|
44
44
|
hostpath,
|
45
45
|
"#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
|
46
46
|
|
@@ -53,6 +53,12 @@ module VagrantPlugins
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
56
|
+
private
|
57
|
+
|
58
|
+
def ssh_key_options(ssh_info)
|
59
|
+
# Ensure that `private_key_path` is an Array (for Vagrant < 1.4)
|
60
|
+
Array(ssh_info[:private_key_path]).map { |path| "-i '#{path}' " }.join
|
61
|
+
end
|
56
62
|
end
|
57
63
|
end
|
58
64
|
end
|
@@ -26,13 +26,22 @@ module VagrantPlugins
|
|
26
26
|
attr_accessor :storage_pool_name
|
27
27
|
|
28
28
|
# Libvirt default network
|
29
|
-
attr_accessor :
|
29
|
+
attr_accessor :management_network_name
|
30
|
+
attr_accessor :management_network_address
|
31
|
+
|
32
|
+
# Default host prefix (alternative to use project folder name)
|
33
|
+
attr_accessor :default_prefix
|
30
34
|
|
31
35
|
# Domain specific settings used while creating new domain.
|
32
36
|
attr_accessor :memory
|
33
37
|
attr_accessor :cpus
|
38
|
+
attr_accessor :cpu_mode
|
39
|
+
attr_accessor :disk_bus
|
34
40
|
attr_accessor :nested
|
35
41
|
attr_accessor :volume_cache
|
42
|
+
attr_accessor :kernel
|
43
|
+
attr_accessor :cmd_line
|
44
|
+
attr_accessor :initrd
|
36
45
|
|
37
46
|
def initialize
|
38
47
|
@driver = UNSET_VALUE
|
@@ -42,13 +51,19 @@ module VagrantPlugins
|
|
42
51
|
@password = UNSET_VALUE
|
43
52
|
@id_ssh_key_file = UNSET_VALUE
|
44
53
|
@storage_pool_name = UNSET_VALUE
|
45
|
-
@
|
54
|
+
@management_network_name = UNSET_VALUE
|
55
|
+
@management_network_address = UNSET_VALUE
|
46
56
|
|
47
57
|
# Domain specific settings.
|
48
58
|
@memory = UNSET_VALUE
|
49
59
|
@cpus = UNSET_VALUE
|
60
|
+
@cpu_mode = UNSET_VALUE
|
61
|
+
@disk_bus = UNSET_VALUE
|
50
62
|
@nested = UNSET_VALUE
|
51
63
|
@volume_cache = UNSET_VALUE
|
64
|
+
@kernel = UNSET_VALUE
|
65
|
+
@initrd = UNSET_VALUE
|
66
|
+
@cmd_line = UNSET_VALUE
|
52
67
|
end
|
53
68
|
|
54
69
|
def finalize!
|
@@ -59,13 +74,19 @@ module VagrantPlugins
|
|
59
74
|
@password = nil if @password == UNSET_VALUE
|
60
75
|
@id_ssh_key_file = 'id_rsa' if @id_ssh_key_file == UNSET_VALUE
|
61
76
|
@storage_pool_name = 'default' if @storage_pool_name == UNSET_VALUE
|
62
|
-
@
|
77
|
+
@management_network_name = 'vagrant-libvirt' if @management_network_name == UNSET_VALUE
|
78
|
+
@management_network_address = '192.168.121.0/24' if @management_network_address == UNSET_VALUE
|
63
79
|
|
64
80
|
# Domain specific settings.
|
65
81
|
@memory = 512 if @memory == UNSET_VALUE
|
66
82
|
@cpus = 1 if @cpus == UNSET_VALUE
|
83
|
+
@cpu_mode = 'host-model' if @cpu_mode == UNSET_VALUE
|
84
|
+
@disk_bus = 'virtio' if @disk_bus == UNSET_VALUE
|
67
85
|
@nested = false if @nested == UNSET_VALUE
|
68
86
|
@volume_cache = 'default' if @volume_cache == UNSET_VALUE
|
87
|
+
@kernel = nil if @kernel == UNSET_VALUE
|
88
|
+
@cmd_line = '' if @cmd_line == UNSET_VALUE
|
89
|
+
@initrd = '' if @initrd == UNSET_VALUE
|
69
90
|
end
|
70
91
|
|
71
92
|
def validate(machine)
|
@@ -68,16 +68,19 @@ module VagrantPlugins
|
|
68
68
|
error_key(:fog_create_server_error)
|
69
69
|
end
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
error_key(:interface_slot_not_available)
|
71
|
+
# Network exceptions
|
72
|
+
class ManagementNetworkError < VagrantLibvirtError
|
73
|
+
error_key(:management_network_error)
|
75
74
|
end
|
76
75
|
|
77
76
|
class NetworkNameAndAddressMismatch < VagrantLibvirtError
|
78
77
|
error_key(:network_name_and_address_mismatch)
|
79
78
|
end
|
80
79
|
|
80
|
+
class DHCPMismatch < VagrantLibvirtError
|
81
|
+
error_key(:dhcp_mismatch)
|
82
|
+
end
|
83
|
+
|
81
84
|
class CreateNetworkError < VagrantLibvirtError
|
82
85
|
error_key(:create_network_error)
|
83
86
|
end
|
@@ -98,12 +101,17 @@ module VagrantPlugins
|
|
98
101
|
error_key(:activate_network_error)
|
99
102
|
end
|
100
103
|
|
104
|
+
# Other exceptions
|
105
|
+
class InterfaceSlotNotAvailable < VagrantLibvirtError
|
106
|
+
error_key(:interface_slot_not_available)
|
107
|
+
end
|
108
|
+
|
101
109
|
class RsyncError < VagrantLibvirtError
|
102
110
|
error_key(:rsync_error)
|
103
111
|
end
|
104
112
|
|
105
113
|
class DomainNameExists < VagrantLibvirtError
|
106
|
-
error_key(:
|
114
|
+
error_key(:domain_name_exists)
|
107
115
|
end
|
108
116
|
|
109
117
|
class NoDomainError < VagrantLibvirtError
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<vcpu><%= @cpus %></vcpu>
|
5
5
|
|
6
6
|
<% if @nested %>
|
7
|
-
<cpu mode='
|
7
|
+
<cpu mode='<%= @cpu_mode %>'>
|
8
8
|
<model fallback='allow'>qemu64</model>
|
9
9
|
<feature policy='optional' name='vmx'/>
|
10
10
|
<feature policy='optional' name='svm'/>
|
@@ -14,6 +14,9 @@
|
|
14
14
|
<os>
|
15
15
|
<type arch='x86_64'>hvm</type>
|
16
16
|
<boot dev='hd'/>
|
17
|
+
<kernel><%= @kernel %></kernel>
|
18
|
+
<initrd><%= @initrd %></initrd>
|
19
|
+
<cmdline><%= @cmd_line %></cmdline>
|
17
20
|
</os>
|
18
21
|
<features>
|
19
22
|
<acpi/>
|
@@ -26,7 +29,7 @@
|
|
26
29
|
<driver name='qemu' type='qcow2' cache='<%= @domain_volume_cache %>'/>
|
27
30
|
<source file='<%= @domain_volume_path %>'/>
|
28
31
|
<%# we need to ensure a unique target dev -%>
|
29
|
-
<target dev='vda' bus='
|
32
|
+
<target dev='vda' bus='<%= @disk_bus %>'/>
|
30
33
|
</disk>
|
31
34
|
<serial type='pty'>
|
32
35
|
<target port='0'/>
|
@@ -27,6 +27,12 @@ module VagrantPlugins
|
|
27
27
|
netmask = xml.xpath('/network/ip/@netmask').first
|
28
28
|
netmask = netmask.value if netmask
|
29
29
|
|
30
|
+
if xml.at_xpath('//network/ip/dhcp')
|
31
|
+
dhcp_enabled = true
|
32
|
+
else
|
33
|
+
dhcp_enabled = false
|
34
|
+
end
|
35
|
+
|
30
36
|
# Calculate network address of network from ip address and
|
31
37
|
# netmask.
|
32
38
|
if ip && netmask
|
@@ -40,6 +46,7 @@ module VagrantPlugins
|
|
40
46
|
ip_address: ip,
|
41
47
|
netmask: netmask,
|
42
48
|
network_address: network_address,
|
49
|
+
dhcp_enabled: dhcp_enabled,
|
43
50
|
bridge_name: libvirt_network.bridge_name,
|
44
51
|
created: true,
|
45
52
|
active: libvirt_network.active?,
|
data/locales/en.yml
CHANGED
@@ -89,7 +89,7 @@ en:
|
|
89
89
|
fog_create_server_error: |-
|
90
90
|
Error while creating domain: %{error_message}
|
91
91
|
domain_name_exists: |-
|
92
|
-
Name of domain about to create is already taken. Please try to run
|
92
|
+
Name `%{domain_name}` of domain about to create is already taken. Please try to run
|
93
93
|
`vagrant up` command again.
|
94
94
|
creating_storage_pool_error: |-
|
95
95
|
There was error while creating libvirt storage pool: %{error_message}
|
@@ -101,9 +101,14 @@ en:
|
|
101
101
|
Error while attaching new device to domain. %{error_message}
|
102
102
|
no_ip_address_error: |-
|
103
103
|
No IP address found.
|
104
|
+
management_network_error: |-
|
105
|
+
Error in specification of management network: %{error_message}.
|
104
106
|
network_name_and_address_mismatch: |-
|
105
107
|
Address %{ip_address} does not match with network name %{network_name}.
|
106
108
|
Please fix your configuration and run vagrant again.
|
109
|
+
dhcp_mismatch: |-
|
110
|
+
Network %{network_name} exists but does not have dhcp %{requested}.
|
111
|
+
Please fix your configuration and run vagrant again.
|
107
112
|
create_network_error: |-
|
108
113
|
Error occured while creating new network: %{error_message}.
|
109
114
|
network_not_available_error: |-
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-libvirt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.14
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Lukas Stanek
|
@@ -10,12 +9,11 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2014-01-21 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: fog
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
18
|
- - '='
|
21
19
|
- !ruby/object:Gem::Version
|
@@ -23,7 +21,6 @@ dependencies:
|
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
25
|
- - '='
|
29
26
|
- !ruby/object:Gem::Version
|
@@ -31,23 +28,20 @@ dependencies:
|
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: ruby-libvirt
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
|
-
- - ~>
|
32
|
+
- - "~>"
|
37
33
|
- !ruby/object:Gem::Version
|
38
34
|
version: 0.4.0
|
39
35
|
type: :runtime
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
|
-
- - ~>
|
39
|
+
- - "~>"
|
45
40
|
- !ruby/object:Gem::Version
|
46
41
|
version: 0.4.0
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: nokogiri
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
46
|
- - '='
|
53
47
|
- !ruby/object:Gem::Version
|
@@ -55,7 +49,6 @@ dependencies:
|
|
55
49
|
type: :runtime
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
53
|
- - '='
|
61
54
|
- !ruby/object:Gem::Version
|
@@ -63,17 +56,15 @@ dependencies:
|
|
63
56
|
- !ruby/object:Gem::Dependency
|
64
57
|
name: rake
|
65
58
|
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
59
|
requirements:
|
68
|
-
- -
|
60
|
+
- - ">="
|
69
61
|
- !ruby/object:Gem::Version
|
70
62
|
version: '0'
|
71
63
|
type: :development
|
72
64
|
prerelease: false
|
73
65
|
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
66
|
requirements:
|
76
|
-
- -
|
67
|
+
- - ">="
|
77
68
|
- !ruby/object:Gem::Version
|
78
69
|
version: '0'
|
79
70
|
description: Vagrant provider for libvirt.
|
@@ -84,7 +75,7 @@ executables: []
|
|
84
75
|
extensions: []
|
85
76
|
extra_rdoc_files: []
|
86
77
|
files:
|
87
|
-
- .gitignore
|
78
|
+
- ".gitignore"
|
88
79
|
- CHANGELOG.md
|
89
80
|
- Gemfile
|
90
81
|
- LICENSE
|
@@ -146,27 +137,25 @@ files:
|
|
146
137
|
homepage: https://github.com/pradels/vagrant-libvirt
|
147
138
|
licenses:
|
148
139
|
- MIT
|
140
|
+
metadata: {}
|
149
141
|
post_install_message:
|
150
142
|
rdoc_options: []
|
151
143
|
require_paths:
|
152
144
|
- lib
|
153
145
|
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
-
none: false
|
155
146
|
requirements:
|
156
|
-
- -
|
147
|
+
- - ">="
|
157
148
|
- !ruby/object:Gem::Version
|
158
149
|
version: '0'
|
159
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
|
-
none: false
|
161
151
|
requirements:
|
162
|
-
- -
|
152
|
+
- - ">="
|
163
153
|
- !ruby/object:Gem::Version
|
164
154
|
version: '0'
|
165
155
|
requirements: []
|
166
156
|
rubyforge_project:
|
167
|
-
rubygems_version:
|
157
|
+
rubygems_version: 2.0.14
|
168
158
|
signing_key:
|
169
|
-
specification_version:
|
159
|
+
specification_version: 4
|
170
160
|
summary: Vagrant provider for libvirt.
|
171
161
|
test_files: []
|
172
|
-
has_rdoc:
|