vagrant-libvirt 0.6.3 → 0.8.1

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +65 -13
  3. data/lib/vagrant-libvirt/action/cleanup_on_failure.rb +76 -0
  4. data/lib/vagrant-libvirt/action/create_domain.rb +56 -10
  5. data/lib/vagrant-libvirt/action/create_network_interfaces.rb +5 -1
  6. data/lib/vagrant-libvirt/action/create_networks.rb +24 -0
  7. data/lib/vagrant-libvirt/action/destroy_domain.rb +106 -21
  8. data/lib/vagrant-libvirt/action/destroy_networks.rb +1 -1
  9. data/lib/vagrant-libvirt/action/forward_ports.rb +12 -11
  10. data/lib/vagrant-libvirt/action/prepare_nfs_settings.rb +1 -1
  11. data/lib/vagrant-libvirt/action/start_domain.rb +36 -0
  12. data/lib/vagrant-libvirt/action/wait_till_up.rb +6 -32
  13. data/lib/vagrant-libvirt/action.rb +72 -83
  14. data/lib/vagrant-libvirt/config.rb +85 -30
  15. data/lib/vagrant-libvirt/driver.rb +11 -9
  16. data/lib/vagrant-libvirt/errors.rb +12 -0
  17. data/lib/vagrant-libvirt/templates/domain.xml.erb +228 -218
  18. data/lib/vagrant-libvirt/templates/private_network.xml.erb +4 -1
  19. data/lib/vagrant-libvirt/util/network_util.rb +15 -3
  20. data/lib/vagrant-libvirt/util/nfs.rb +2 -0
  21. data/lib/vagrant-libvirt/util/resolvers.rb +80 -0
  22. data/lib/vagrant-libvirt/version +1 -1
  23. data/locales/en.yml +17 -0
  24. data/spec/spec_helper.rb +36 -23
  25. data/spec/support/libvirt_context.rb +7 -4
  26. data/spec/support/sharedcontext.rb +1 -1
  27. data/spec/unit/action/cleanup_on_failure_spec.rb +131 -0
  28. data/spec/unit/action/create_domain_spec/additional_disks_domain.xml +6 -18
  29. data/spec/unit/action/create_domain_spec/custom_disk_settings.xml +43 -0
  30. data/spec/unit/action/create_domain_spec/default_domain.xml +6 -18
  31. data/spec/unit/action/create_domain_spec/two_disk_settings.xml +49 -0
  32. data/spec/unit/action/create_domain_spec.rb +51 -7
  33. data/spec/unit/action/create_domain_volume_spec.rb +5 -3
  34. data/spec/unit/action/destroy_domain_spec/additional_disks_domain.xml +47 -0
  35. data/spec/unit/action/destroy_domain_spec/box_multiple_disks.xml +55 -0
  36. data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_and_custom_disks.xml +72 -0
  37. data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_and_custom_disks_no_aliases.xml +67 -0
  38. data/spec/unit/action/destroy_domain_spec/box_multiple_disks_and_additional_disks.xml +67 -0
  39. data/spec/unit/action/destroy_domain_spec/cdrom_domain.xml +48 -0
  40. data/spec/unit/action/destroy_domain_spec.rb +134 -30
  41. data/spec/unit/action/forward_ports_spec.rb +10 -2
  42. data/spec/unit/action/prepare_nfs_settings_spec.rb +59 -0
  43. data/spec/unit/action/shutdown_domain_spec.rb +1 -1
  44. data/spec/unit/action/start_domain_spec/clock_timer_rtc.xml +6 -18
  45. data/spec/unit/action/start_domain_spec/default.xml +6 -18
  46. data/spec/unit/action/start_domain_spec/default_added_tpm_path.xml +6 -18
  47. data/spec/unit/action/start_domain_spec/default_added_tpm_version.xml +6 -18
  48. data/spec/unit/action/start_domain_spec/existing.xml +1 -1
  49. data/spec/unit/action/wait_till_up_spec.rb +4 -43
  50. data/spec/unit/action_spec.rb +2 -0
  51. data/spec/unit/config_spec.rb +133 -26
  52. data/spec/unit/driver_spec.rb +154 -10
  53. data/spec/unit/templates/domain_all_settings.xml +56 -77
  54. data/spec/unit/templates/domain_cpu_mode_passthrough.xml +39 -0
  55. data/spec/unit/templates/domain_custom_cpu_model.xml +6 -18
  56. data/spec/unit/templates/domain_defaults.xml +6 -18
  57. data/spec/unit/templates/domain_spec.rb +39 -13
  58. data/spec/unit/templates/tpm/version_1.2.xml +6 -18
  59. data/spec/unit/templates/tpm/version_2.0.xml +6 -18
  60. data/spec/unit/util/resolvers_spec.rb +116 -0
  61. metadata +40 -41
@@ -4,15 +4,8 @@ require 'cgi'
4
4
 
5
5
  require 'vagrant'
6
6
 
7
- class Numeric
8
- Alphabet = ('a'..'z').to_a
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
- @system_uri = 'qemu:///system' if @system_uri == UNSET_VALUE
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 = 9216 if @video_vram == UNSET_VALUE
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
- @channels = [] if @channels == UNSET_VALUE
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 = true if @qemu_use_agent != UNSET_VALUE
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::open(config.system_uri)
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? || domain.state.to_sym == :terminated
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
- dom = system_connection.lookup_domain_by_uuid(machine_id)
173
+ libvirt_domain = connection.client.lookup_domain_by_uuid(machine_id)
172
174
  begin
173
- response = dom.qemu_agent_command('{"execute":"guest-network-get-interfaces"}', timeout=10)
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