vagrant-libvirt 0.9.0 → 0.10.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 +51 -2079
- data/lib/vagrant-libvirt/action/create_domain.rb +39 -4
- data/lib/vagrant-libvirt/action/create_network_interfaces.rb +1 -1
- data/lib/vagrant-libvirt/action/create_networks.rb +3 -3
- data/lib/vagrant-libvirt/action/destroy_domain.rb +1 -1
- data/lib/vagrant-libvirt/action/destroy_networks.rb +1 -1
- data/lib/vagrant-libvirt/action/handle_box_image.rb +1 -1
- data/lib/vagrant-libvirt/action/package_domain.rb +1 -5
- data/lib/vagrant-libvirt/action/remove_libvirt_image.rb +3 -1
- data/lib/vagrant-libvirt/action/resolve_disk_settings.rb +15 -8
- data/lib/vagrant-libvirt/action/snapshot_delete.rb +26 -0
- data/lib/vagrant-libvirt/action/snapshot_restore.rb +22 -0
- data/lib/vagrant-libvirt/action/snapshot_save.rb +27 -0
- data/lib/vagrant-libvirt/action/start_domain.rb +43 -14
- data/lib/vagrant-libvirt/action.rb +49 -1
- data/lib/vagrant-libvirt/cap/snapshots.rb +12 -0
- data/lib/vagrant-libvirt/cap/synced_folder_9p.rb +4 -4
- data/lib/vagrant-libvirt/cap/synced_folder_virtiofs.rb +4 -4
- data/lib/vagrant-libvirt/config.rb +101 -6
- data/lib/vagrant-libvirt/driver.rb +108 -46
- data/lib/vagrant-libvirt/errors.rb +23 -3
- data/lib/vagrant-libvirt/plugin.rb +7 -3
- data/lib/vagrant-libvirt/provider.rb +1 -1
- data/lib/vagrant-libvirt/templates/domain.xml.erb +30 -4
- data/lib/vagrant-libvirt/util/byte_number.rb +0 -1
- data/lib/vagrant-libvirt/util/compat.rb +23 -0
- data/lib/vagrant-libvirt/util/unindent.rb +7 -0
- data/lib/vagrant-libvirt/version +1 -1
- data/locales/en.yml +24 -2
- data/spec/acceptance/additional_storage_spec.rb +32 -0
- data/spec/acceptance/package_domain_spec.rb +90 -0
- data/spec/acceptance/provider_settings_spec.rb +54 -0
- data/spec/acceptance/simple_vm_provision_via_shell_spec.rb +31 -0
- data/spec/acceptance/snapshots_spec.rb +41 -0
- data/spec/acceptance/support-skeletons/package_complex/Vagrantfile.testbox +14 -0
- data/spec/acceptance/support-skeletons/package_complex/scripts/sysprep.sh +32 -0
- data/spec/acceptance/support-skeletons/package_simple/Vagrantfile.testbox +10 -0
- data/spec/acceptance/two_disks_spec.rb +29 -0
- data/spec/acceptance/use_qemu_agent_for_connectivity_spec.rb +35 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/acceptance/configuration.rb +21 -0
- data/spec/support/acceptance/context.rb +70 -0
- data/spec/support/acceptance/isolated_environment.rb +41 -0
- data/spec/support/libvirt_acceptance_context.rb +64 -0
- data/spec/support/sharedcontext.rb +1 -0
- data/spec/unit/action/create_domain_spec/sysinfo.xml +66 -0
- data/spec/unit/action/create_domain_spec/sysinfo_only_required.xml +49 -0
- data/spec/unit/action/create_domain_spec.rb +82 -0
- data/spec/unit/action/forward_ports_spec.rb +0 -1
- data/spec/unit/action/handle_box_image_spec.rb +18 -1
- data/spec/unit/action/remove_libvirt_image_spec.rb +43 -0
- data/spec/unit/action/resolve_disk_settings_spec.rb +24 -0
- data/spec/unit/action/start_domain_spec/clock_timer_removed.xml +38 -0
- data/spec/unit/action/start_domain_spec/clock_timer_rtc_tsc.xml +39 -0
- data/spec/unit/action/start_domain_spec/nvram_domain_other_setting.xml +2 -2
- data/spec/unit/action/start_domain_spec.rb +72 -30
- data/spec/unit/action_spec.rb +88 -0
- data/spec/unit/cap/synced_folder_9p_spec.rb +120 -0
- data/spec/unit/cap/synced_folder_virtiofs_spec.rb +120 -0
- data/spec/unit/config_spec.rb +133 -6
- data/spec/unit/driver_spec.rb +1 -1
- data/spec/unit/plugin_spec.rb +42 -0
- data/spec/unit/templates/domain_all_settings.xml +13 -4
- data/spec/unit/templates/domain_scsi_bus_storage.xml +44 -0
- data/spec/unit/templates/domain_scsi_device_storage.xml +44 -0
- data/spec/unit/templates/domain_scsi_multiple_controllers_storage.xml +130 -0
- data/spec/unit/templates/domain_spec.rb +105 -21
- data/spec/unit/util/byte_number_spec.rb +1 -1
- metadata +155 -87
- data/spec/unit/provider_spec.rb +0 -11
@@ -11,7 +11,7 @@ module VagrantPlugins
|
|
11
11
|
module ProviderLibvirt
|
12
12
|
class Config < Vagrant.plugin('2', :config)
|
13
13
|
# manually specify URI
|
14
|
-
# will
|
14
|
+
# will supersede most other options if provided
|
15
15
|
attr_accessor :uri
|
16
16
|
|
17
17
|
# A hypervisor name to access via Libvirt.
|
@@ -99,6 +99,7 @@ module VagrantPlugins
|
|
99
99
|
attr_accessor :machine_virtual_size
|
100
100
|
attr_accessor :disk_bus
|
101
101
|
attr_accessor :disk_device
|
102
|
+
attr_accessor :disk_controller_model
|
102
103
|
attr_accessor :disk_driver_opts
|
103
104
|
attr_accessor :nic_model_type
|
104
105
|
attr_accessor :nested
|
@@ -128,6 +129,9 @@ module VagrantPlugins
|
|
128
129
|
attr_accessor :tpm_path
|
129
130
|
attr_accessor :tpm_version
|
130
131
|
|
132
|
+
# Configure sysinfo values
|
133
|
+
attr_accessor :sysinfo
|
134
|
+
|
131
135
|
# Configure the memballoon
|
132
136
|
attr_accessor :memballoon_enabled
|
133
137
|
attr_accessor :memballoon_model
|
@@ -195,6 +199,9 @@ module VagrantPlugins
|
|
195
199
|
# serial consoles
|
196
200
|
attr_accessor :serials
|
197
201
|
|
202
|
+
# internal helper attributes
|
203
|
+
attr_accessor :host_device_exclude_prefixes
|
204
|
+
|
198
205
|
def initialize
|
199
206
|
@uri = UNSET_VALUE
|
200
207
|
@driver = UNSET_VALUE
|
@@ -253,6 +260,7 @@ module VagrantPlugins
|
|
253
260
|
@machine_virtual_size = UNSET_VALUE
|
254
261
|
@disk_bus = UNSET_VALUE
|
255
262
|
@disk_device = UNSET_VALUE
|
263
|
+
@disk_controller_model = UNSET_VALUE
|
256
264
|
@disk_driver_opts = {}
|
257
265
|
@nic_model_type = UNSET_VALUE
|
258
266
|
@nested = UNSET_VALUE
|
@@ -280,6 +288,8 @@ module VagrantPlugins
|
|
280
288
|
@tpm_path = UNSET_VALUE
|
281
289
|
@tpm_version = UNSET_VALUE
|
282
290
|
|
291
|
+
@sysinfo = UNSET_VALUE
|
292
|
+
|
283
293
|
@memballoon_enabled = UNSET_VALUE
|
284
294
|
@memballoon_model = UNSET_VALUE
|
285
295
|
@memballoon_pci_bus = UNSET_VALUE
|
@@ -342,6 +352,9 @@ module VagrantPlugins
|
|
342
352
|
@qemu_use_agent = UNSET_VALUE
|
343
353
|
|
344
354
|
@serials = UNSET_VALUE
|
355
|
+
|
356
|
+
# internal options to help override behaviour
|
357
|
+
@host_device_exclude_prefixes = UNSET_VALUE
|
345
358
|
end
|
346
359
|
|
347
360
|
def boot(device)
|
@@ -865,8 +878,15 @@ module VagrantPlugins
|
|
865
878
|
@machine_type = nil if @machine_type == UNSET_VALUE
|
866
879
|
@machine_arch = nil if @machine_arch == UNSET_VALUE
|
867
880
|
@machine_virtual_size = nil if @machine_virtual_size == UNSET_VALUE
|
868
|
-
@
|
869
|
-
@
|
881
|
+
@disk_device = @disk_bus == 'scsi' ? 'sda' : 'vda' if @disk_device == UNSET_VALUE
|
882
|
+
@disk_bus = @disk_device.start_with?('sd') ? 'scsi' : 'virtio' if @disk_bus == UNSET_VALUE
|
883
|
+
if @disk_controller_model == UNSET_VALUE
|
884
|
+
if @disk_bus == 'scsi' or @disk_device.start_with?('sd') == 'sd'
|
885
|
+
@disk_controller_model = 'virtio-scsi'
|
886
|
+
else
|
887
|
+
@disk_controller_model = nil
|
888
|
+
end
|
889
|
+
end
|
870
890
|
@disk_driver_opts = {} if @disk_driver_opts == UNSET_VALUE
|
871
891
|
@nic_model_type = nil if @nic_model_type == UNSET_VALUE
|
872
892
|
@nested = false if @nested == UNSET_VALUE
|
@@ -902,6 +922,8 @@ module VagrantPlugins
|
|
902
922
|
@nic_adapter_count = 8 if @nic_adapter_count == UNSET_VALUE
|
903
923
|
@emulator_path = nil if @emulator_path == UNSET_VALUE
|
904
924
|
|
925
|
+
@sysinfo = {} if @sysinfo == UNSET_VALUE
|
926
|
+
|
905
927
|
# Boot order
|
906
928
|
@boot_order = [] if @boot_order == UNSET_VALUE
|
907
929
|
|
@@ -972,6 +994,8 @@ module VagrantPlugins
|
|
972
994
|
@qemu_use_agent = false if @qemu_use_agent == UNSET_VALUE
|
973
995
|
|
974
996
|
@serials = [{:type => 'pty', :source => nil}] if @serials == UNSET_VALUE
|
997
|
+
|
998
|
+
@host_device_exclude_prefixes = ['docker', 'macvtap', 'virbr', 'vnet'] if @host_device_exclude_prefixes == UNSET_VALUE
|
975
999
|
end
|
976
1000
|
|
977
1001
|
def validate(machine)
|
@@ -999,7 +1023,7 @@ module VagrantPlugins
|
|
999
1023
|
end
|
1000
1024
|
|
1001
1025
|
if @qemu_use_agent == true
|
1002
|
-
# if qemu agent is used to
|
1026
|
+
# if qemu agent is used to obtain domain ip configuration, at least
|
1003
1027
|
# one qemu channel has to be configured. As there are various options,
|
1004
1028
|
# error out and leave configuration to the user
|
1005
1029
|
unless machine.provider_config.channels.any? { |channel| channel[:target_name].start_with?("org.qemu.guest_agent") }
|
@@ -1029,7 +1053,9 @@ module VagrantPlugins
|
|
1029
1053
|
errors << "#{e}"
|
1030
1054
|
end
|
1031
1055
|
|
1032
|
-
machine.config.vm.networks.
|
1056
|
+
machine.config.vm.networks.each_with_index do |network, index|
|
1057
|
+
type, opts = network
|
1058
|
+
|
1033
1059
|
if opts[:mac]
|
1034
1060
|
if opts[:mac] =~ /\A([0-9a-fA-F]{12})\z/
|
1035
1061
|
opts[:mac] = opts[:mac].scan(/../).join(':')
|
@@ -1038,6 +1064,13 @@ module VagrantPlugins
|
|
1038
1064
|
errors << "Configured NIC MAC '#{opts[:mac]}' is not in 'xx:xx:xx:xx:xx:xx' or 'xxxxxxxxxxxx' format"
|
1039
1065
|
end
|
1040
1066
|
end
|
1067
|
+
|
1068
|
+
# only interested in public networks where portgroup is nil, as then source will be a host device
|
1069
|
+
if type == :public_network && opts[:portgroup] == nil
|
1070
|
+
if !host_devices.include?(opts[:dev])
|
1071
|
+
errors << "network configuration #{index} for machine #{machine.name} is a public_network referencing host device '#{opts[:dev]}' which does not exist, consider adding ':dev => ....' referencing one of #{host_devices.join(", ")}"
|
1072
|
+
end
|
1073
|
+
end
|
1041
1074
|
end
|
1042
1075
|
|
1043
1076
|
if !machine.provider_config.volume_cache.nil? and machine.provider_config.volume_cache != UNSET_VALUE
|
@@ -1048,6 +1081,8 @@ module VagrantPlugins
|
|
1048
1081
|
end
|
1049
1082
|
end
|
1050
1083
|
|
1084
|
+
errors = validate_sysinfo(machine, errors)
|
1085
|
+
|
1051
1086
|
{ 'Libvirt Provider' => errors }
|
1052
1087
|
end
|
1053
1088
|
|
@@ -1062,7 +1097,11 @@ module VagrantPlugins
|
|
1062
1097
|
result.cdroms = c
|
1063
1098
|
|
1064
1099
|
result.disk_driver_opts = disk_driver_opts.merge(other.disk_driver_opts)
|
1065
|
-
|
1100
|
+
|
1101
|
+
c = sysinfo == UNSET_VALUE ? {} : sysinfo.dup
|
1102
|
+
c.merge!(other.sysinfo) { |_k, x, y| x.respond_to?(:each_pair) ? x.merge(y) : x + y } if other.sysinfo != UNSET_VALUE
|
1103
|
+
result.sysinfo = c
|
1104
|
+
|
1066
1105
|
c = clock_timers.dup
|
1067
1106
|
c += other.clock_timers
|
1068
1107
|
result.clock_timers = c
|
@@ -1170,6 +1209,62 @@ module VagrantPlugins
|
|
1170
1209
|
@proxy_command = nil
|
1171
1210
|
end
|
1172
1211
|
end
|
1212
|
+
|
1213
|
+
def host_devices
|
1214
|
+
@host_devices ||= begin
|
1215
|
+
require 'socket'
|
1216
|
+
|
1217
|
+
Socket.getifaddrs.map { |iface| iface.name }.uniq.select do |dev|
|
1218
|
+
dev != "lo" && !@host_device_exclude_prefixes.any? { |exclude| dev.start_with?(exclude) }
|
1219
|
+
end
|
1220
|
+
end
|
1221
|
+
end
|
1222
|
+
|
1223
|
+
def validate_sysinfo(machine, errors)
|
1224
|
+
valid_sysinfo = {
|
1225
|
+
'bios' => %w[vendor version date release],
|
1226
|
+
'system' => %w[manufacturer product version serial uuid sku family],
|
1227
|
+
'base board' => %w[manufacturer product version serial asset location],
|
1228
|
+
'chassis' => %w[manufacturer version serial asset sku],
|
1229
|
+
'oem strings' => nil,
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
machine.provider_config.sysinfo.each_pair do |block_name, entries|
|
1233
|
+
block_name = block_name.to_s
|
1234
|
+
unless valid_sysinfo.key?(block_name)
|
1235
|
+
errors << "invalid sysinfo element '#{block_name}'; smbios sysinfo elements supported: #{valid_sysinfo.keys.join(', ')}"
|
1236
|
+
next
|
1237
|
+
end
|
1238
|
+
|
1239
|
+
if valid_sysinfo[block_name].nil?
|
1240
|
+
# assume simple array of text entries
|
1241
|
+
entries.each do |entry|
|
1242
|
+
if entry.respond_to?(:to_str)
|
1243
|
+
if entry.to_s.empty?
|
1244
|
+
machine.ui.warn("Libvirt Provider: 'sysinfo.#{block_name}' contains an empty or nil entry and will be discarded")
|
1245
|
+
end
|
1246
|
+
else
|
1247
|
+
errors << "sysinfo.#{block_name} expects entries to be stringy, got #{entry.class} containing '#{entry}'"
|
1248
|
+
end
|
1249
|
+
end
|
1250
|
+
else
|
1251
|
+
entries.each_pair do |entry_name, entry_text|
|
1252
|
+
entry_name = entry_name.to_s
|
1253
|
+
unless valid_sysinfo[block_name].include?(entry_name)
|
1254
|
+
errors << "'sysinfo.#{block_name}' does not support entry name '#{entry_name}'; entries supported: #{valid_sysinfo[block_name].join(', ')}"
|
1255
|
+
next
|
1256
|
+
end
|
1257
|
+
|
1258
|
+
# this allows removal of entries specified by other Vagrantfile's in the hierarchy
|
1259
|
+
if entry_text.to_s.empty?
|
1260
|
+
machine.ui.warn("Libvirt Provider: sysinfo.#{block_name}.#{entry_name} is nil or empty and therefore has no effect.")
|
1261
|
+
end
|
1262
|
+
end
|
1263
|
+
end
|
1264
|
+
end
|
1265
|
+
|
1266
|
+
errors
|
1267
|
+
end
|
1173
1268
|
end
|
1174
1269
|
end
|
1175
1270
|
end
|
@@ -32,16 +32,17 @@ module VagrantPlugins
|
|
32
32
|
config = @machine.provider_config
|
33
33
|
uri = config.uri
|
34
34
|
|
35
|
-
conn_attr = {}
|
36
|
-
conn_attr[:provider] = 'libvirt'
|
37
|
-
conn_attr[:libvirt_uri] = uri
|
38
|
-
conn_attr[:libvirt_username] = config.username if config.username
|
39
|
-
conn_attr[:libvirt_password] = config.password if config.password
|
40
|
-
|
41
35
|
# Setup command for retrieving IP address for newly created machine
|
42
36
|
# with some MAC address. Get it from dnsmasq leases table
|
43
37
|
ip_command = %q( awk "/$mac/ {print \$1}" /proc/net/arp )
|
44
|
-
|
38
|
+
|
39
|
+
conn_attr = {
|
40
|
+
provider: 'libvirt',
|
41
|
+
libvirt_uri: uri,
|
42
|
+
libvirt_ip_command: ip_command,
|
43
|
+
}
|
44
|
+
conn_attr[:libvirt_username] = config.username if config.username
|
45
|
+
conn_attr[:libvirt_password] = config.password if config.password
|
45
46
|
|
46
47
|
@logger.info("Connecting to Libvirt (#{uri}) ...")
|
47
48
|
begin
|
@@ -61,7 +62,7 @@ module VagrantPlugins
|
|
61
62
|
|
62
63
|
config = @machine.provider_config
|
63
64
|
|
64
|
-
@system_connection = Libvirt
|
65
|
+
@system_connection = Libvirt.open_read_only(config.system_uri)
|
65
66
|
@system_connection
|
66
67
|
end
|
67
68
|
|
@@ -69,12 +70,10 @@ module VagrantPlugins
|
|
69
70
|
begin
|
70
71
|
domain = connection.servers.get(machine.id)
|
71
72
|
rescue Libvirt::RetrieveError => e
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
raise e
|
77
|
-
end
|
73
|
+
raise e unless e.libvirt_code == ProviderLibvirt::Util::ErrorCodes::VIR_ERR_NO_DOMAIN
|
74
|
+
|
75
|
+
@logger.debug("machine #{machine.name} domain not found #{e}.")
|
76
|
+
return nil
|
78
77
|
end
|
79
78
|
|
80
79
|
domain
|
@@ -99,32 +98,82 @@ module VagrantPlugins
|
|
99
98
|
|
100
99
|
def get_domain_ipaddress(machine, domain)
|
101
100
|
# attempt to get ip address from qemu agent
|
102
|
-
if
|
101
|
+
if machine.provider_config.qemu_use_agent == true
|
103
102
|
@logger.info('Get IP via qemu agent')
|
104
|
-
return get_ipaddress_from_qemu_agent(domain, machine.id)
|
103
|
+
return get_ipaddress_from_qemu_agent(domain, machine.id, machine.config.vm.boot_timeout)
|
105
104
|
end
|
106
105
|
|
107
|
-
if
|
108
|
-
return get_ipaddress_from_system domain.mac
|
109
|
-
end
|
106
|
+
return get_ipaddress_from_system domain.mac if machine.provider_config.qemu_use_session
|
110
107
|
|
111
108
|
# Get IP address from dhcp leases table
|
112
109
|
begin
|
113
110
|
ip_address = get_ipaddress_from_domain(domain)
|
114
111
|
rescue Fog::Errors::TimeoutError
|
115
|
-
@logger.info(
|
112
|
+
@logger.info("Timeout at waiting for an ip address for machine #{machine.name}")
|
116
113
|
|
117
114
|
raise
|
118
115
|
end
|
119
116
|
|
120
117
|
unless ip_address
|
121
|
-
@logger.info(
|
118
|
+
@logger.info("No arp table entry found for machine #{machine.name}")
|
122
119
|
return nil
|
123
120
|
end
|
124
121
|
|
125
122
|
ip_address
|
126
123
|
end
|
127
124
|
|
125
|
+
def restore_snapshot(machine, snapshot_name)
|
126
|
+
domain = get_libvirt_domain(machine)
|
127
|
+
snapshot = get_snapshot_if_exists(machine, snapshot_name)
|
128
|
+
begin
|
129
|
+
# 4 is VIR_DOMAIN_SNAPSHOT_REVERT_FORCE
|
130
|
+
# needed due to https://bugzilla.redhat.com/show_bug.cgi?id=1006886
|
131
|
+
domain.revert_to_snapshot(snapshot, 4)
|
132
|
+
rescue Fog::Errors::Error => e
|
133
|
+
raise Errors::SnapshotReversionError, error_message: e.message
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def list_snapshots(machine)
|
138
|
+
get_libvirt_domain(machine).list_snapshots
|
139
|
+
rescue Fog::Errors::Error => e
|
140
|
+
raise Errors::SnapshotListError, error_message: e.message
|
141
|
+
end
|
142
|
+
|
143
|
+
def delete_snapshot(machine, snapshot_name)
|
144
|
+
get_snapshot_if_exists(machine, snapshot_name).delete
|
145
|
+
rescue Errors::SnapshotMissing => e
|
146
|
+
raise Errors::SnapshotDeletionError, error_message: e.message
|
147
|
+
end
|
148
|
+
|
149
|
+
def create_new_snapshot(machine, snapshot_name)
|
150
|
+
snapshot_desc = <<-EOF
|
151
|
+
<domainsnapshot>
|
152
|
+
<name>#{snapshot_name}</name>
|
153
|
+
<description>Snapshot for vagrant sandbox</description>
|
154
|
+
</domainsnapshot>
|
155
|
+
EOF
|
156
|
+
get_libvirt_domain(machine).snapshot_create_xml(snapshot_desc)
|
157
|
+
rescue Fog::Errors::Error => e
|
158
|
+
raise Errors::SnapshotCreationError, error_message: e.message
|
159
|
+
end
|
160
|
+
|
161
|
+
def create_snapshot(machine, snapshot_name)
|
162
|
+
begin
|
163
|
+
delete_snapshot(machine, snapshot_name)
|
164
|
+
rescue Errors::SnapshotDeletionError
|
165
|
+
end
|
166
|
+
create_new_snapshot(machine, snapshot_name)
|
167
|
+
end
|
168
|
+
|
169
|
+
# if we can get snapshot description without exception it exists
|
170
|
+
def get_snapshot_if_exists(machine, snapshot_name)
|
171
|
+
snapshot = get_libvirt_domain(machine).lookup_snapshot_by_name(snapshot_name)
|
172
|
+
return snapshot if snapshot.xml_desc
|
173
|
+
rescue Libvirt::RetrieveError => e
|
174
|
+
raise Errors::SnapshotMissing, error_message: e.message
|
175
|
+
end
|
176
|
+
|
128
177
|
def state(machine)
|
129
178
|
# may be other error states with initial retreival we can't handle
|
130
179
|
begin
|
@@ -149,7 +198,7 @@ module VagrantPlugins
|
|
149
198
|
end
|
150
199
|
end
|
151
200
|
|
152
|
-
|
201
|
+
state
|
153
202
|
end
|
154
203
|
|
155
204
|
private
|
@@ -160,43 +209,44 @@ module VagrantPlugins
|
|
160
209
|
system_connection.list_all_networks.each do |net|
|
161
210
|
leases = net.dhcp_leases(mac, 0)
|
162
211
|
# Assume the lease expiring last is the current IP address
|
163
|
-
ip_address = leases.
|
212
|
+
ip_address = leases.max_by { |lse| lse['expirytime'] }['ipaddr'] unless leases.empty?
|
164
213
|
break if ip_address
|
165
214
|
end
|
166
215
|
|
167
216
|
ip_address
|
168
217
|
end
|
169
218
|
|
170
|
-
def get_ipaddress_from_qemu_agent(domain, machine_id)
|
219
|
+
def get_ipaddress_from_qemu_agent(domain, machine_id, timeout)
|
171
220
|
ip_address = nil
|
172
221
|
addresses = nil
|
173
222
|
libvirt_domain = connection.client.lookup_domain_by_uuid(machine_id)
|
174
223
|
begin
|
175
|
-
response = libvirt_domain.qemu_agent_command('{"execute":"guest-network-get-interfaces"}', timeout
|
176
|
-
@logger.debug(
|
224
|
+
response = libvirt_domain.qemu_agent_command('{"execute":"guest-network-get-interfaces"}', timeout)
|
225
|
+
@logger.debug('Got Response from qemu agent')
|
177
226
|
@logger.debug(response)
|
178
227
|
addresses = JSON.parse(response)
|
179
|
-
rescue => e
|
180
|
-
|
228
|
+
rescue StandardError => e
|
229
|
+
puts "Unable to receive IP via qemu agent: [#{e.message}]"
|
230
|
+
@logger.debug("Unable to receive IP via qemu agent: [#{e.message}]")
|
181
231
|
end
|
182
232
|
|
183
233
|
unless addresses.nil?
|
184
|
-
addresses[
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
234
|
+
addresses['return'].each do |interface|
|
235
|
+
next unless domain.mac.downcase == interface['hardware-address'].downcase
|
236
|
+
|
237
|
+
@logger.debug("Found matching interface: [#{interface['name']}]")
|
238
|
+
next unless interface.key?('ip-addresses')
|
239
|
+
|
240
|
+
interface['ip-addresses'].each do |ip|
|
241
|
+
# returning ipv6 addresses might break windows guests because
|
242
|
+
# winrm can't handle connection, winrm fails with "invalid uri"
|
243
|
+
next unless ip['ip-address-type'] == 'ipv4'
|
244
|
+
|
245
|
+
ip_address = ip['ip-address']
|
246
|
+
@logger.debug("Return IP: [#{ip_address}]")
|
247
|
+
break
|
198
248
|
end
|
199
|
-
|
249
|
+
end
|
200
250
|
end
|
201
251
|
ip_address
|
202
252
|
end
|
@@ -204,18 +254,30 @@ module VagrantPlugins
|
|
204
254
|
def get_ipaddress_from_domain(domain)
|
205
255
|
ip_address = nil
|
206
256
|
domain.wait_for(2) do
|
207
|
-
addresses.each_pair do |
|
257
|
+
addresses.each_pair do |_type, ip|
|
208
258
|
# Multiple leases are separated with a newline, return only
|
209
259
|
# the most recent address
|
210
|
-
ip_address = ip[0].split("\n").first
|
260
|
+
ip_address = ip[0].split("\n").first unless ip[0].nil?
|
211
261
|
end
|
212
262
|
|
213
|
-
ip_address
|
263
|
+
!ip_address.nil?
|
214
264
|
end
|
215
265
|
|
216
266
|
ip_address
|
217
267
|
end
|
218
268
|
|
269
|
+
def get_libvirt_domain(machine)
|
270
|
+
begin
|
271
|
+
libvirt_domain = connection.client.lookup_domain_by_uuid(machine.id)
|
272
|
+
rescue Libvirt::RetrieveError => e
|
273
|
+
raise e unless e.libvirt_code == ProviderLibvirt::Util::ErrorCodes::VIR_ERR_NO_DOMAIN
|
274
|
+
|
275
|
+
@logger.debug("machine #{machine.name} not found #{e}.")
|
276
|
+
return nil
|
277
|
+
end
|
278
|
+
|
279
|
+
libvirt_domain
|
280
|
+
end
|
219
281
|
end
|
220
282
|
end
|
221
283
|
end
|
@@ -109,7 +109,7 @@ module VagrantPlugins
|
|
109
109
|
end
|
110
110
|
|
111
111
|
class FogCreateServerError < VagrantLibvirtError
|
112
|
-
error_key(:
|
112
|
+
error_key(:create_server_error)
|
113
113
|
end
|
114
114
|
|
115
115
|
# Network exceptions
|
@@ -154,6 +154,10 @@ module VagrantPlugins
|
|
154
154
|
end
|
155
155
|
|
156
156
|
# Other exceptions
|
157
|
+
class UpdateServerError < VagrantLibvirtError
|
158
|
+
error_key(:create_server_error)
|
159
|
+
end
|
160
|
+
|
157
161
|
class InterfaceSlotNotAvailable < VagrantLibvirtError
|
158
162
|
error_key(:interface_slot_not_available)
|
159
163
|
end
|
@@ -186,8 +190,24 @@ module VagrantPlugins
|
|
186
190
|
error_key(:no_ip_address_error)
|
187
191
|
end
|
188
192
|
|
189
|
-
class
|
190
|
-
error_key(:
|
193
|
+
class SnapshotMissing < VagrantLibvirtError
|
194
|
+
error_key(:snapshot_missing)
|
195
|
+
end
|
196
|
+
|
197
|
+
class SnapshotDeletionError < VagrantLibvirtError
|
198
|
+
error_key(:snapshot_deletion_error)
|
199
|
+
end
|
200
|
+
|
201
|
+
class SnapshotListError < VagrantLibvirtError
|
202
|
+
error_key(:snapshot_list_error)
|
203
|
+
end
|
204
|
+
|
205
|
+
class SnapshotCreationError < VagrantLibvirtError
|
206
|
+
error_key(:snapshot_creation_error)
|
207
|
+
end
|
208
|
+
|
209
|
+
class SnapshotReversionError < VagrantLibvirtError
|
210
|
+
error_key(:snapshot_reversion_error)
|
191
211
|
end
|
192
212
|
|
193
213
|
class SerialCannotCreatePathError < VagrantLibvirtError
|
@@ -6,8 +6,7 @@ rescue LoadError
|
|
6
6
|
raise 'The Vagrant Libvirt plugin must be run within Vagrant.'
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
::Vagrant::MachineState::NOT_CREATED_ID ||= :not_created
|
9
|
+
require 'vagrant-libvirt/util/compat'
|
11
10
|
|
12
11
|
module VagrantPlugins
|
13
12
|
module ProviderLibvirt
|
@@ -27,7 +26,7 @@ module VagrantPlugins
|
|
27
26
|
Provider
|
28
27
|
end
|
29
28
|
|
30
|
-
action_hook(:remove_libvirt_image) do |hook|
|
29
|
+
action_hook(*(Util::Compat.action_hook_args(:remove_libvirt_image, :box_remove))) do |hook|
|
31
30
|
require_relative 'action'
|
32
31
|
hook.after Vagrant::Action::Builtin::BoxRemove, Action.remove_libvirt_image
|
33
32
|
end
|
@@ -51,6 +50,11 @@ module VagrantPlugins
|
|
51
50
|
Cap::PublicAddress
|
52
51
|
end
|
53
52
|
|
53
|
+
provider_capability(:libvirt, :snapshot_list) do
|
54
|
+
require_relative 'cap/snapshots'
|
55
|
+
Cap::Snapshots
|
56
|
+
end
|
57
|
+
|
54
58
|
# lower priority than nfs or rsync
|
55
59
|
# https://github.com/vagrant-libvirt/vagrant-libvirt/pull/170
|
56
60
|
synced_folder('9p', 4) do
|
@@ -52,7 +52,7 @@ module VagrantPlugins
|
|
52
52
|
# :username => "mitchellh",
|
53
53
|
# :private_key_path => "/path/to/my/key"
|
54
54
|
# }
|
55
|
-
# note that
|
55
|
+
# note that modifying @machine.id or accessing @machine.state is not
|
56
56
|
# thread safe, so be careful to avoid these here as this method may
|
57
57
|
# be called from other threads of execution.
|
58
58
|
return nil if state.id != :running
|
@@ -81,8 +81,28 @@
|
|
81
81
|
<cmdline><%= @cmd_line %></cmdline>
|
82
82
|
<%- if @dtb -%>
|
83
83
|
<dtb><%= @dtb %></dtb>
|
84
|
+
<% end -%>
|
85
|
+
<%- unless @sysinfo.empty? -%>
|
86
|
+
<smbios mode='sysinfo'/>
|
84
87
|
<% end -%>
|
85
88
|
</os>
|
89
|
+
<%- unless @sysinfo.empty? -%>
|
90
|
+
<sysinfo type='smbios'>
|
91
|
+
<%- @sysinfo.each_pair do |block, values| -%>
|
92
|
+
<<%= @sysinfo_blocks[block.to_s][:xml] %>>
|
93
|
+
<%- if values.respond_to?(:each_pair) -%>
|
94
|
+
<%- values.each do |name, value| -%>
|
95
|
+
<entry name='<%= name %>'><%= value %></entry>
|
96
|
+
<% end -%>
|
97
|
+
<%- else -%>
|
98
|
+
<%- values.each do |value| -%>
|
99
|
+
<entry><%= value %></entry>
|
100
|
+
<% end -%>
|
101
|
+
<% end -%>
|
102
|
+
</<%= @sysinfo_blocks[block.to_s][:xml] %>>
|
103
|
+
<% end -%>
|
104
|
+
</sysinfo>
|
105
|
+
<% end -%>
|
86
106
|
<features>
|
87
107
|
<%- @features.each do |feature| -%>
|
88
108
|
<<%= feature %>/>
|
@@ -122,6 +142,12 @@
|
|
122
142
|
<target dev='<%= volume[:device] %>' bus='<%= volume[:bus] %>'/>
|
123
143
|
</disk>
|
124
144
|
<%- end -%>
|
145
|
+
<%- scsi_volumes = @domain_volumes.select { |x| x[:bus] == 'scsi' } %>
|
146
|
+
<%- if !scsi_volumes.empty? and !@disk_controller_model.nil? %>
|
147
|
+
<%- for idx in 0..(scsi_volumes.length / 7) do %>
|
148
|
+
<controller type='scsi' model='<%= @disk_controller_model %>' index='<%= idx -%>'/>
|
149
|
+
<%- end -%>
|
150
|
+
<%- end -%>
|
125
151
|
<%# additional disks -%>
|
126
152
|
<%- @disks.each_with_index do |d, index| -%>
|
127
153
|
<disk type='file' device='disk'>
|
@@ -220,7 +246,7 @@
|
|
220
246
|
</graphics><% end -%>
|
221
247
|
<video>
|
222
248
|
<model type='<%= @video_type %>' vram='<%= @video_vram %>' heads='1'<% if not @video_accel3d %>/><% else %>>
|
223
|
-
|
249
|
+
<acceleration accel3d='yes'/>
|
224
250
|
</model><% end -%>
|
225
251
|
</video>
|
226
252
|
<%#End Video -%>
|
@@ -250,13 +276,13 @@
|
|
250
276
|
<hostdev mode='subsystem' type='usb'>
|
251
277
|
<source startupPolicy='<%= usb[:startupPolicy] || "mandatory" %>'>
|
252
278
|
<%- if usb[:vendor] -%>
|
253
|
-
|
279
|
+
<vendor id='<%= usb[:vendor] %>'/>
|
254
280
|
<%- end -%>
|
255
281
|
<%- if usb[:product] -%>
|
256
|
-
|
282
|
+
<product id='<%= usb[:product] %>'/>
|
257
283
|
<%- end -%>
|
258
284
|
<%- if usb[:bus] && usb[:device] -%>
|
259
|
-
|
285
|
+
<address bus='<%= usb[:bus] %>' device='<%= usb[:device] %>'/>
|
260
286
|
<%- end -%>
|
261
287
|
</source>
|
262
288
|
</hostdev>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'vagrant'
|
4
|
+
|
5
|
+
# compatibility fix to define constant not available Vagrant <1.6
|
6
|
+
::Vagrant::MachineState::NOT_CREATED_ID ||= :not_created
|
7
|
+
|
8
|
+
module VagrantPlugins
|
9
|
+
module ProviderLibvirt
|
10
|
+
module Util
|
11
|
+
module Compat
|
12
|
+
def self.action_hook_args(name, action)
|
13
|
+
# handle different number of arguments for action_hook depending on vagrant version
|
14
|
+
if Gem::Version.new(Vagrant::VERSION) >= Gem::Version.new('2.2.11')
|
15
|
+
return name, action
|
16
|
+
end
|
17
|
+
|
18
|
+
return name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/vagrant-libvirt/version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.10.0
|