vagrant-libvirt 0.6.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +65 -13
- data/lib/vagrant-libvirt/action/cleanup_on_failure.rb +76 -0
- data/lib/vagrant-libvirt/action/create_domain.rb +56 -10
- data/lib/vagrant-libvirt/action/create_network_interfaces.rb +5 -1
- data/lib/vagrant-libvirt/action/create_networks.rb +24 -0
- data/lib/vagrant-libvirt/action/destroy_domain.rb +106 -21
- data/lib/vagrant-libvirt/action/destroy_networks.rb +1 -1
- data/lib/vagrant-libvirt/action/forward_ports.rb +12 -11
- data/lib/vagrant-libvirt/action/handle_box_image.rb +19 -10
- data/lib/vagrant-libvirt/action/prepare_nfs_settings.rb +1 -1
- data/lib/vagrant-libvirt/action/start_domain.rb +36 -0
- data/lib/vagrant-libvirt/action/wait_till_up.rb +6 -32
- data/lib/vagrant-libvirt/action.rb +67 -80
- data/lib/vagrant-libvirt/config.rb +85 -30
- data/lib/vagrant-libvirt/driver.rb +11 -9
- data/lib/vagrant-libvirt/errors.rb +12 -0
- data/lib/vagrant-libvirt/templates/domain.xml.erb +228 -218
- data/lib/vagrant-libvirt/templates/private_network.xml.erb +4 -1
- data/lib/vagrant-libvirt/util/network_util.rb +15 -3
- data/lib/vagrant-libvirt/util/nfs.rb +2 -0
- data/lib/vagrant-libvirt/util/resolvers.rb +80 -0
- data/lib/vagrant-libvirt/version +1 -1
- data/locales/en.yml +21 -0
- data/spec/spec_helper.rb +36 -23
- data/spec/support/libvirt_context.rb +7 -4
- data/spec/support/sharedcontext.rb +1 -1
- data/spec/unit/action/cleanup_on_failure_spec.rb +131 -0
- data/spec/unit/action/create_domain_spec/additional_disks_domain.xml +6 -18
- data/spec/unit/action/create_domain_spec/custom_disk_settings.xml +43 -0
- data/spec/unit/action/create_domain_spec/default_domain.xml +6 -18
- data/spec/unit/action/create_domain_spec/two_disk_settings.xml +49 -0
- data/spec/unit/action/create_domain_spec.rb +51 -7
- data/spec/unit/action/create_domain_volume_spec.rb +5 -3
- data/spec/unit/action/destroy_domain_spec/additional_disks_domain.xml +47 -0
- data/spec/unit/action/destroy_domain_spec/box_multiple_disks.xml +55 -0
- data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_and_custom_disks.xml +72 -0
- data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_and_custom_disks_no_aliases.xml +67 -0
- data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_disks.xml +67 -0
- data/spec/unit/action/destroy_domain_spec/cdrom_domain.xml +48 -0
- data/spec/unit/action/destroy_domain_spec.rb +134 -30
- data/spec/unit/action/forward_ports_spec.rb +10 -2
- data/spec/unit/action/handle_box_image_spec.rb +30 -0
- data/spec/unit/action/prepare_nfs_settings_spec.rb +59 -0
- data/spec/unit/action/shutdown_domain_spec.rb +1 -1
- data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +6 -18
- data/spec/unit/action/start_domain_spec/default.xml +6 -18
- data/spec/unit/action/start_domain_spec/default_added_tpm_path.xml +6 -18
- data/spec/unit/action/start_domain_spec/default_added_tpm_version.xml +6 -18
- data/spec/unit/action/start_domain_spec/existing.xml +1 -1
- data/spec/unit/action/wait_till_up_spec.rb +4 -43
- data/spec/unit/action_spec.rb +2 -0
- data/spec/unit/config_spec.rb +133 -26
- data/spec/unit/driver_spec.rb +154 -10
- data/spec/unit/provider_spec.rb +11 -0
- data/spec/unit/templates/domain_all_settings.xml +56 -77
- data/spec/unit/templates/domain_cpu_mode_passthrough.xml +39 -0
- data/spec/unit/templates/domain_custom_cpu_model.xml +6 -18
- data/spec/unit/templates/domain_defaults.xml +6 -18
- data/spec/unit/templates/domain_spec.rb +39 -13
- data/spec/unit/templates/tpm/version_1.2.xml +6 -18
- data/spec/unit/templates/tpm/version_2.0.xml +6 -18
- data/spec/unit/util/resolvers_spec.rb +116 -0
- metadata +65 -64
@@ -4,15 +4,8 @@ require 'cgi'
|
|
4
4
|
|
5
5
|
require 'vagrant'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
def vdev
|
10
|
-
s = String.new
|
11
|
-
q = self
|
12
|
-
(q, r = (q - 1).divmod(26)) && s.prepend(Alphabet[r]) until q.zero?
|
13
|
-
"vd#{s}"
|
14
|
-
end
|
15
|
-
end
|
7
|
+
require 'vagrant-libvirt/errors'
|
8
|
+
require 'vagrant-libvirt/util/resolvers'
|
16
9
|
|
17
10
|
module VagrantPlugins
|
18
11
|
module ProviderLibvirt
|
@@ -69,6 +62,7 @@ module VagrantPlugins
|
|
69
62
|
attr_accessor :management_network_pci_slot
|
70
63
|
attr_accessor :management_network_domain
|
71
64
|
attr_accessor :management_network_mtu
|
65
|
+
attr_accessor :management_network_keep
|
72
66
|
|
73
67
|
# System connection information
|
74
68
|
attr_accessor :system_uri
|
@@ -119,8 +113,10 @@ module VagrantPlugins
|
|
119
113
|
attr_accessor :graphics_port
|
120
114
|
attr_accessor :graphics_passwd
|
121
115
|
attr_accessor :graphics_ip
|
116
|
+
attr_accessor :graphics_gl
|
122
117
|
attr_accessor :video_type
|
123
118
|
attr_accessor :video_vram
|
119
|
+
attr_accessor :video_accel3d
|
124
120
|
attr_accessor :keymap
|
125
121
|
attr_accessor :kvm_hidden
|
126
122
|
attr_accessor :sound_type
|
@@ -196,6 +192,9 @@ module VagrantPlugins
|
|
196
192
|
# Use QEMU Agent to get ip address
|
197
193
|
attr_accessor :qemu_use_agent
|
198
194
|
|
195
|
+
# serial consoles
|
196
|
+
attr_accessor :serials
|
197
|
+
|
199
198
|
def initialize
|
200
199
|
@uri = UNSET_VALUE
|
201
200
|
@driver = UNSET_VALUE
|
@@ -222,6 +221,7 @@ module VagrantPlugins
|
|
222
221
|
@management_network_pci_bus = UNSET_VALUE
|
223
222
|
@management_network_domain = UNSET_VALUE
|
224
223
|
@management_network_mtu = UNSET_VALUE
|
224
|
+
@management_network_keep = UNSET_VALUE
|
225
225
|
|
226
226
|
# System connection information
|
227
227
|
@system_uri = UNSET_VALUE
|
@@ -267,8 +267,10 @@ module VagrantPlugins
|
|
267
267
|
@graphics_port = UNSET_VALUE
|
268
268
|
@graphics_ip = UNSET_VALUE
|
269
269
|
@graphics_passwd = UNSET_VALUE
|
270
|
+
@graphics_gl = UNSET_VALUE
|
270
271
|
@video_type = UNSET_VALUE
|
271
272
|
@video_vram = UNSET_VALUE
|
273
|
+
@video_accel3d = UNSET_VALUE
|
272
274
|
@sound_type = UNSET_VALUE
|
273
275
|
@keymap = UNSET_VALUE
|
274
276
|
@kvm_hidden = UNSET_VALUE
|
@@ -338,23 +340,14 @@ module VagrantPlugins
|
|
338
340
|
|
339
341
|
# Use Qemu agent to get ip address
|
340
342
|
@qemu_use_agent = UNSET_VALUE
|
343
|
+
|
344
|
+
@serials = UNSET_VALUE
|
341
345
|
end
|
342
346
|
|
343
347
|
def boot(device)
|
344
348
|
@boot_order << device # append
|
345
349
|
end
|
346
350
|
|
347
|
-
def _get_device(disks)
|
348
|
-
# skip existing devices and also the first one (vda)
|
349
|
-
exist = disks.collect { |x| x[:device] } + [1.vdev.to_s]
|
350
|
-
skip = 1 # we're 1 based, not 0 based...
|
351
|
-
loop do
|
352
|
-
dev = skip.vdev # get lettered device
|
353
|
-
return dev unless exist.include?(dev)
|
354
|
-
skip += 1
|
355
|
-
end
|
356
|
-
end
|
357
|
-
|
358
351
|
def _get_cdrom_dev(cdroms)
|
359
352
|
exist = Hash[cdroms.collect { |x| [x[:dev], true] }]
|
360
353
|
# hda - hdc
|
@@ -507,7 +500,9 @@ module VagrantPlugins
|
|
507
500
|
target_address: options[:target_address],
|
508
501
|
target_name: options[:target_name],
|
509
502
|
target_port: options[:target_port],
|
510
|
-
target_type: options[:target_type]
|
503
|
+
target_type: options[:target_type],
|
504
|
+
disabled: options[:disabled],
|
505
|
+
)
|
511
506
|
end
|
512
507
|
|
513
508
|
def random(options = {})
|
@@ -705,6 +700,22 @@ module VagrantPlugins
|
|
705
700
|
@qemu_env.merge!(options)
|
706
701
|
end
|
707
702
|
|
703
|
+
def serial(options={})
|
704
|
+
@serials = [] if @serials == UNSET_VALUE
|
705
|
+
|
706
|
+
options = {
|
707
|
+
:type => "pty",
|
708
|
+
:source => nil,
|
709
|
+
}.merge(options)
|
710
|
+
|
711
|
+
serial = {
|
712
|
+
:type => options[:type],
|
713
|
+
:source => options[:source],
|
714
|
+
}
|
715
|
+
|
716
|
+
@serials << serial
|
717
|
+
end
|
718
|
+
|
708
719
|
def _default_uri
|
709
720
|
# Determine if any settings except driver provided explicitly, if not
|
710
721
|
# and the LIBVIRT_DEFAULT_URI var is set, use that.
|
@@ -817,7 +828,7 @@ module VagrantPlugins
|
|
817
828
|
@management_network_pci_slot = nil if @management_network_pci_slot == UNSET_VALUE
|
818
829
|
@management_network_domain = nil if @management_network_domain == UNSET_VALUE
|
819
830
|
@management_network_mtu = nil if @management_network_mtu == UNSET_VALUE
|
820
|
-
@
|
831
|
+
@management_network_keep = false if @management_network_keep == UNSET_VALUE
|
821
832
|
|
822
833
|
# Domain specific settings.
|
823
834
|
@title = '' if @title == UNSET_VALUE
|
@@ -870,7 +881,9 @@ module VagrantPlugins
|
|
870
881
|
@graphics_port = -1 if @graphics_port == UNSET_VALUE
|
871
882
|
@graphics_ip = '127.0.0.1' if @graphics_ip == UNSET_VALUE
|
872
883
|
@video_type = 'cirrus' if @video_type == UNSET_VALUE
|
873
|
-
@video_vram =
|
884
|
+
@video_vram = 16384 if @video_vram == UNSET_VALUE
|
885
|
+
@video_accel3d = false if @video_accel3d == UNSET_VALUE
|
886
|
+
@graphics_gl = @video_accel3d if @graphics_gl == UNSET_VALUE
|
874
887
|
@sound_type = nil if @sound_type == UNSET_VALUE
|
875
888
|
@keymap = 'en-us' if @keymap == UNSET_VALUE
|
876
889
|
@kvm_hidden = false if @kvm_hidden == UNSET_VALUE
|
@@ -890,10 +903,6 @@ module VagrantPlugins
|
|
890
903
|
|
891
904
|
# Storage
|
892
905
|
@disks = [] if @disks == UNSET_VALUE
|
893
|
-
@disks.map! do |disk|
|
894
|
-
disk[:device] = _get_device(@disks) if disk[:device].nil?
|
895
|
-
disk
|
896
|
-
end
|
897
906
|
@cdroms = [] if @cdroms == UNSET_VALUE
|
898
907
|
@cdroms.map! do |cdrom|
|
899
908
|
cdrom[:dev] = _get_cdrom_dev(@cdroms) if cdrom[:dev].nil?
|
@@ -904,7 +913,18 @@ module VagrantPlugins
|
|
904
913
|
@inputs = [{ type: 'mouse', bus: 'ps2' }] if @inputs == UNSET_VALUE
|
905
914
|
|
906
915
|
# Channels
|
907
|
-
|
916
|
+
if @channels == UNSET_VALUE
|
917
|
+
@channels = []
|
918
|
+
if @qemu_use_agent == true
|
919
|
+
if @channels.all? { |channel| !channel.fetch(:target_name, '').start_with?('org.qemu.guest_agent.') }
|
920
|
+
channel(:type => 'unix', :target_name => 'org.qemu.guest_agent.0', :target_type => 'virtio')
|
921
|
+
end
|
922
|
+
end
|
923
|
+
end
|
924
|
+
|
925
|
+
# filter channels of anything explicitly disabled so it's possible to inject an entry to
|
926
|
+
# avoid the automatic addition of the guest_agent above, and disable it from subsequent use.
|
927
|
+
@channels = @channels.reject { |channel| channel[:disabled] }.tap {|channel| channel.delete(:disabled) }
|
908
928
|
|
909
929
|
# PCI device passthrough
|
910
930
|
@pcis = [] if @pcis == UNSET_VALUE
|
@@ -945,12 +965,19 @@ module VagrantPlugins
|
|
945
965
|
# Additional QEMU commandline environment variables
|
946
966
|
@qemu_env = {} if @qemu_env == UNSET_VALUE
|
947
967
|
|
948
|
-
@qemu_use_agent =
|
968
|
+
@qemu_use_agent = false if @qemu_use_agent == UNSET_VALUE
|
969
|
+
|
970
|
+
@serials = [{:type => 'pty', :source => nil}] if @serials == UNSET_VALUE
|
949
971
|
end
|
950
972
|
|
951
973
|
def validate(machine)
|
952
974
|
errors = _detected_errors
|
953
975
|
|
976
|
+
# technically this shouldn't occur, but ensure that if somehow it does, it gets rejected.
|
977
|
+
if @cpu_mode == 'host-passthrough' && @cpu_model != ''
|
978
|
+
errors << "cannot set cpu_model with cpu_mode of 'host-passthrough'. leave model unset or switch mode."
|
979
|
+
end
|
980
|
+
|
954
981
|
# The @uri and @qemu_use_session should not conflict
|
955
982
|
uri = _parse_uri(@uri)
|
956
983
|
if (uri.scheme.start_with? "qemu") && (uri.path.include? "session")
|
@@ -959,6 +986,9 @@ module VagrantPlugins
|
|
959
986
|
end
|
960
987
|
end
|
961
988
|
|
989
|
+
unless @qemu_use_agent == true || @qemu_use_agent == false
|
990
|
+
errors << "libvirt.qemu_use_agent must be a boolean."
|
991
|
+
end
|
962
992
|
|
963
993
|
if @qemu_use_agent == true
|
964
994
|
# if qemu agent is used to optain domain ip configuration, at least
|
@@ -969,13 +999,28 @@ module VagrantPlugins
|
|
969
999
|
end
|
970
1000
|
end
|
971
1001
|
|
972
|
-
|
973
1002
|
machine.provider_config.disks.each do |disk|
|
974
1003
|
if disk[:path] && (disk[:path][0] == '/')
|
975
1004
|
errors << "absolute volume paths like '#{disk[:path]}' not yet supported"
|
976
1005
|
end
|
977
1006
|
end
|
978
1007
|
|
1008
|
+
machine.provider_config.serials.each do |serial|
|
1009
|
+
if serial[:source] and serial[:source][:path].nil?
|
1010
|
+
errors << "serial :source requires :path to be defined"
|
1011
|
+
end
|
1012
|
+
end
|
1013
|
+
|
1014
|
+
# this won't be able to fully resolve the disks until the box has
|
1015
|
+
# been downloaded and any devices that need to be assigned to the
|
1016
|
+
# disks contained have been allocated
|
1017
|
+
disk_resolver = ::VagrantPlugins::ProviderLibvirt::Util::DiskDeviceResolver.new
|
1018
|
+
begin
|
1019
|
+
disk_resolver.resolve(machine.provider_config.disks)
|
1020
|
+
rescue Errors::VagrantLibvirtError => e
|
1021
|
+
errors << "#{e}"
|
1022
|
+
end
|
1023
|
+
|
979
1024
|
machine.config.vm.networks.each do |_type, opts|
|
980
1025
|
if opts[:mac]
|
981
1026
|
if opts[:mac] =~ /\A([0-9a-fA-F]{12})\z/
|
@@ -1017,6 +1062,12 @@ module VagrantPlugins
|
|
1017
1062
|
c = qemu_env != UNSET_VALUE ? qemu_env.dup : {}
|
1018
1063
|
c.merge!(other.qemu_env) if other.qemu_env != UNSET_VALUE
|
1019
1064
|
result.qemu_env = c
|
1065
|
+
|
1066
|
+
if serials != UNSET_VALUE
|
1067
|
+
s = serials.dup
|
1068
|
+
s += other.serials
|
1069
|
+
result.serials = s
|
1070
|
+
end
|
1020
1071
|
end
|
1021
1072
|
end
|
1022
1073
|
|
@@ -1026,6 +1077,10 @@ module VagrantPlugins
|
|
1026
1077
|
# Parse uri to extract individual components
|
1027
1078
|
uri = _parse_uri(@uri)
|
1028
1079
|
|
1080
|
+
system_uri = uri.dup
|
1081
|
+
system_uri.path = '/system'
|
1082
|
+
@system_uri = system_uri.to_s if @system_uri == UNSET_VALUE
|
1083
|
+
|
1029
1084
|
# only set @connect_via_ssh if not explicitly to avoid overriding
|
1030
1085
|
# and allow an error to occur if the @uri and @connect_via_ssh disagree
|
1031
1086
|
@connect_via_ssh = uri.scheme.include? "ssh" if @connect_via_ssh == UNSET_VALUE
|
@@ -61,7 +61,7 @@ module VagrantPlugins
|
|
61
61
|
|
62
62
|
config = @machine.provider_config
|
63
63
|
|
64
|
-
@system_connection = Libvirt::
|
64
|
+
@system_connection = Libvirt::open_read_only(config.system_uri)
|
65
65
|
@system_connection
|
66
66
|
end
|
67
67
|
|
@@ -98,16 +98,16 @@ module VagrantPlugins
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def get_domain_ipaddress(machine, domain)
|
101
|
-
if @machine.provider_config.qemu_use_session
|
102
|
-
return get_ipaddress_from_system domain.mac
|
103
|
-
end
|
104
|
-
|
105
101
|
# attempt to get ip address from qemu agent
|
106
102
|
if @machine.provider_config.qemu_use_agent == true
|
107
103
|
@logger.info('Get IP via qemu agent')
|
108
104
|
return get_ipaddress_from_qemu_agent(domain, machine.id)
|
109
105
|
end
|
110
106
|
|
107
|
+
if @machine.provider_config.qemu_use_session
|
108
|
+
return get_ipaddress_from_system domain.mac
|
109
|
+
end
|
110
|
+
|
111
111
|
# Get IP address from dhcp leases table
|
112
112
|
begin
|
113
113
|
ip_address = get_ipaddress_from_domain(domain)
|
@@ -135,7 +135,9 @@ module VagrantPlugins
|
|
135
135
|
end
|
136
136
|
|
137
137
|
# TODO: terminated no longer appears to be a valid fog state, remove?
|
138
|
-
return :not_created if domain.nil?
|
138
|
+
return :not_created if domain.nil?
|
139
|
+
return :unknown if domain.state.nil?
|
140
|
+
return :not_created if domain.state.to_sym == :terminated
|
139
141
|
|
140
142
|
state = domain.state.tr('-', '_').to_sym
|
141
143
|
if state == :running
|
@@ -168,9 +170,9 @@ module VagrantPlugins
|
|
168
170
|
def get_ipaddress_from_qemu_agent(domain, machine_id)
|
169
171
|
ip_address = nil
|
170
172
|
addresses = nil
|
171
|
-
|
173
|
+
libvirt_domain = connection.client.lookup_domain_by_uuid(machine_id)
|
172
174
|
begin
|
173
|
-
response =
|
175
|
+
response = libvirt_domain.qemu_agent_command('{"execute":"guest-network-get-interfaces"}', timeout=10)
|
174
176
|
@logger.debug("Got Response from qemu agent")
|
175
177
|
@logger.debug(response)
|
176
178
|
addresses = JSON.parse(response)
|
@@ -180,7 +182,7 @@ module VagrantPlugins
|
|
180
182
|
|
181
183
|
unless addresses.nil?
|
182
184
|
addresses["return"].each{ |interface|
|
183
|
-
if domain.mac == interface["hardware-address"]
|
185
|
+
if domain.mac.downcase == interface["hardware-address"].downcase
|
184
186
|
@logger.debug("Found mathing interface: [%s]" % interface["name"])
|
185
187
|
if interface.has_key?("ip-addresses")
|
186
188
|
interface["ip-addresses"].each{ |ip|
|
@@ -18,6 +18,14 @@ module VagrantPlugins
|
|
18
18
|
error_key(:package_not_supported)
|
19
19
|
end
|
20
20
|
|
21
|
+
class DuplicateDiskDevice < VagrantLibvirtError
|
22
|
+
error_key(:duplicate_disk_device)
|
23
|
+
end
|
24
|
+
|
25
|
+
class NoDiskDeviceAvailable < VagrantLibvirtError
|
26
|
+
error_key(:no_disk_device_available)
|
27
|
+
end
|
28
|
+
|
21
29
|
# Storage pools and volumes exceptions
|
22
30
|
class NoStoragePool < VagrantLibvirtError
|
23
31
|
error_key(:no_storage_pool)
|
@@ -181,6 +189,10 @@ module VagrantPlugins
|
|
181
189
|
class DeleteSnapshotError < VagrantLibvirtError
|
182
190
|
error_key(:delete_snapshot_error)
|
183
191
|
end
|
192
|
+
|
193
|
+
class SerialCannotCreatePathError < VagrantLibvirtError
|
194
|
+
error_key(:serial_cannot_create_path_error)
|
195
|
+
end
|
184
196
|
end
|
185
197
|
end
|
186
198
|
end
|