vagrant-unbundled 2.2.9.0 → 2.2.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +60 -0
  3. data/README.md +5 -5
  4. data/contrib/README.md +1 -0
  5. data/contrib/sudoers/linux-suse +2 -2
  6. data/contrib/zsh/_vagrant +736 -0
  7. data/contrib/zsh/generate_zsh_completion.rb +166 -0
  8. data/lib/vagrant/action.rb +3 -0
  9. data/lib/vagrant/action/builder.rb +52 -18
  10. data/lib/vagrant/action/builtin/box_add.rb +6 -5
  11. data/lib/vagrant/action/builtin/cloud_init_setup.rb +127 -0
  12. data/lib/vagrant/action/builtin/cloud_init_wait.rb +30 -0
  13. data/lib/vagrant/action/builtin/handle_box.rb +1 -1
  14. data/lib/vagrant/action/builtin/handle_forwarded_port_collisions.rb +13 -13
  15. data/lib/vagrant/action/builtin/has_provisioner.rb +36 -0
  16. data/lib/vagrant/action/builtin/mixin_provisioners.rb +1 -0
  17. data/lib/vagrant/action/builtin/mixin_synced_folders.rb +20 -21
  18. data/lib/vagrant/action/builtin/set_hostname.rb +5 -1
  19. data/lib/vagrant/action/builtin/synced_folders.rb +10 -0
  20. data/lib/vagrant/action/builtin/trigger.rb +3 -2
  21. data/lib/vagrant/action/hook.rb +59 -24
  22. data/lib/vagrant/action/warden.rb +25 -5
  23. data/lib/vagrant/box.rb +5 -4
  24. data/lib/vagrant/bundler.rb +6 -1
  25. data/lib/vagrant/errors.rb +37 -1
  26. data/lib/vagrant/machine.rb +47 -0
  27. data/lib/vagrant/machine_index.rb +27 -1
  28. data/lib/vagrant/plugin/v2/command.rb +5 -1
  29. data/lib/vagrant/plugin/v2/components.rb +6 -0
  30. data/lib/vagrant/plugin/v2/manager.rb +14 -0
  31. data/lib/vagrant/plugin/v2/plugin.rb +12 -0
  32. data/lib/vagrant/plugin/v2/synced_folder.rb +50 -0
  33. data/lib/vagrant/plugin/v2/trigger.rb +6 -5
  34. data/lib/vagrant/ui.rb +1 -1
  35. data/lib/vagrant/util/ansi_escape_code_remover.rb +1 -1
  36. data/lib/vagrant/util/caps.rb +48 -0
  37. data/lib/vagrant/util/credential_scrubber.rb +1 -1
  38. data/lib/vagrant/util/directory.rb +19 -0
  39. data/lib/vagrant/util/downloader.rb +3 -3
  40. data/lib/vagrant/util/guest_hosts.rb +68 -0
  41. data/lib/vagrant/util/install_cli_autocomplete.rb +118 -0
  42. data/lib/vagrant/util/ipv4_interfaces.rb +15 -0
  43. data/lib/vagrant/util/is_port_open.rb +8 -19
  44. data/lib/vagrant/util/network_ip.rb +11 -1
  45. data/lib/vagrant/util/powershell.rb +1 -1
  46. data/lib/vagrant/util/subprocess.rb +9 -1
  47. data/lib/vagrant/vagrantfile.rb +1 -1
  48. data/plugins/commands/autocomplete/command/install.rb +49 -0
  49. data/plugins/commands/autocomplete/command/root.rb +64 -0
  50. data/plugins/commands/autocomplete/plugin.rb +18 -0
  51. data/plugins/commands/destroy/command.rb +6 -2
  52. data/plugins/communicators/ssh/communicator.rb +7 -1
  53. data/plugins/communicators/winrm/helper.rb +1 -1
  54. data/plugins/communicators/winssh/communicator.rb +1 -1
  55. data/plugins/guests/alpine/cap/change_host_name.rb +10 -11
  56. data/plugins/guests/alt/cap/change_host_name.rb +40 -53
  57. data/plugins/guests/arch/cap/change_host_name.rb +5 -14
  58. data/plugins/guests/arch/cap/configure_networks.rb +27 -10
  59. data/plugins/guests/atomic/cap/change_host_name.rb +5 -14
  60. data/plugins/guests/darwin/cap/change_host_name.rb +10 -6
  61. data/plugins/guests/debian/cap/change_host_name.rb +11 -11
  62. data/plugins/guests/esxi/cap/public_key.rb +3 -1
  63. data/plugins/guests/freebsd/cap/change_host_name.rb +10 -6
  64. data/plugins/guests/gentoo/cap/change_host_name.rb +14 -22
  65. data/plugins/guests/haiku/cap/rsync.rb +19 -0
  66. data/plugins/guests/haiku/plugin.rb +15 -0
  67. data/plugins/guests/linux/cap/change_host_name.rb +46 -0
  68. data/plugins/guests/linux/cap/mount_virtualbox_shared_folder.rb +4 -11
  69. data/plugins/guests/linux/cap/persist_mount_shared_folder.rb +62 -0
  70. data/plugins/guests/linux/plugin.rb +10 -0
  71. data/plugins/guests/omnios/cap/change_host_name.rb +10 -16
  72. data/plugins/guests/openbsd/cap/change_host_name.rb +10 -6
  73. data/plugins/guests/photon/cap/change_host_name.rb +9 -15
  74. data/plugins/guests/pld/cap/change_host_name.rb +11 -17
  75. data/plugins/guests/redhat/cap/change_host_name.rb +10 -5
  76. data/plugins/guests/slackware/cap/change_host_name.rb +11 -17
  77. data/plugins/guests/solaris11/plugin.rb +5 -0
  78. data/plugins/guests/suse/cap/change_host_name.rb +12 -11
  79. data/plugins/hosts/darwin/cap/fs_iso.rb +49 -0
  80. data/plugins/hosts/darwin/plugin.rb +10 -0
  81. data/plugins/hosts/linux/cap/fs_iso.rb +49 -0
  82. data/plugins/hosts/linux/cap/rdp.rb +1 -1
  83. data/plugins/hosts/linux/plugin.rb +10 -0
  84. data/plugins/hosts/windows/cap/fs_iso.rb +48 -0
  85. data/plugins/hosts/windows/cap/rdp.rb +1 -1
  86. data/plugins/hosts/windows/plugin.rb +15 -0
  87. data/plugins/kernel_v2/config/cloud_init.rb +126 -0
  88. data/plugins/kernel_v2/config/disk.rb +40 -18
  89. data/plugins/kernel_v2/config/vm.rb +122 -13
  90. data/plugins/kernel_v2/config/vm_provisioner.rb +13 -2
  91. data/plugins/kernel_v2/config/vm_trigger.rb +5 -1
  92. data/plugins/providers/docker/action.rb +8 -17
  93. data/plugins/providers/docker/action/forwarded_ports.rb +2 -0
  94. data/plugins/providers/docker/action/prepare_forwarded_port_collision_params.rb +61 -0
  95. data/plugins/providers/docker/cap/has_communicator.rb +11 -0
  96. data/plugins/providers/docker/communicator.rb +1 -1
  97. data/plugins/providers/docker/driver.rb +35 -0
  98. data/plugins/providers/docker/plugin.rb +5 -0
  99. data/plugins/providers/hyperv/action.rb +2 -0
  100. data/plugins/providers/hyperv/action/configure.rb +8 -0
  101. data/plugins/providers/hyperv/cap/cleanup_disks.rb +54 -0
  102. data/plugins/providers/hyperv/cap/configure_disks.rb +200 -0
  103. data/plugins/providers/hyperv/cap/validate_disk_ext.rb +34 -0
  104. data/plugins/providers/hyperv/config.rb +5 -0
  105. data/plugins/providers/hyperv/driver.rb +80 -0
  106. data/plugins/providers/hyperv/plugin.rb +25 -0
  107. data/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 +28 -0
  108. data/plugins/providers/hyperv/scripts/dismount_vhd.ps1 +13 -0
  109. data/plugins/providers/hyperv/scripts/get_vhd.ps1 +16 -0
  110. data/plugins/providers/hyperv/scripts/get_vm_status.ps1 +1 -1
  111. data/plugins/providers/hyperv/scripts/list_hdds.ps1 +17 -0
  112. data/plugins/providers/hyperv/scripts/new_vhd.ps1 +31 -0
  113. data/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 +25 -0
  114. data/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 +18 -0
  115. data/plugins/providers/hyperv/scripts/set_enhanced_session_transport_type.ps1 +24 -0
  116. data/plugins/providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 +8 -0
  117. data/plugins/providers/virtualbox/action.rb +12 -1
  118. data/plugins/providers/virtualbox/action/forward_ports.rb +2 -2
  119. data/plugins/providers/virtualbox/cap/cleanup_disks.rb +40 -9
  120. data/plugins/providers/virtualbox/cap/configure_disks.rb +230 -77
  121. data/plugins/providers/virtualbox/cap/mount_options.rb +35 -0
  122. data/plugins/providers/virtualbox/cap/validate_disk_ext.rb +10 -3
  123. data/plugins/providers/virtualbox/driver/meta.rb +3 -0
  124. data/plugins/providers/virtualbox/driver/version_5_0.rb +96 -21
  125. data/plugins/providers/virtualbox/model/storage_controller.rb +135 -0
  126. data/plugins/providers/virtualbox/model/storage_controller_array.rb +100 -0
  127. data/plugins/providers/virtualbox/plugin.rb +18 -1
  128. data/plugins/providers/virtualbox/synced_folder.rb +1 -0
  129. data/plugins/provisioners/container/client.rb +1 -1
  130. data/plugins/provisioners/shell/provisioner.rb +15 -9
  131. data/plugins/synced_folders/nfs/synced_folder.rb +3 -1
  132. data/plugins/synced_folders/smb/cap/default_fstab_modification.rb +11 -0
  133. data/plugins/synced_folders/smb/cap/mount_options.rb +36 -0
  134. data/plugins/synced_folders/smb/plugin.rb +10 -0
  135. data/plugins/synced_folders/smb/synced_folder.rb +1 -1
  136. data/plugins/synced_folders/unix_mount_helpers.rb +14 -0
  137. data/templates/guests/arch/{network_dhcp.erb → default_network/network_dhcp.erb} +0 -0
  138. data/templates/guests/arch/{network_static.erb → default_network/network_static.erb} +0 -0
  139. data/templates/guests/arch/{network_static6.erb → default_network/network_static6.erb} +0 -0
  140. data/templates/guests/arch/systemd_networkd/network_dhcp.erb +6 -0
  141. data/templates/guests/arch/systemd_networkd/network_static.erb +9 -0
  142. data/templates/guests/arch/systemd_networkd/network_static6.erb +9 -0
  143. data/templates/guests/linux/etc_fstab.erb +6 -0
  144. data/templates/locales/en.yml +121 -11
  145. data/templates/locales/providers_docker.yml +4 -0
  146. data/vagrant.gemspec +8 -7
  147. data/version.txt +1 -1
  148. metadata +1492 -1309
@@ -12,6 +12,8 @@ module VagrantPlugins
12
12
 
13
13
  DEFAULT_DISK_TYPES = [:disk, :dvd, :floppy].freeze
14
14
 
15
+ FILE_CHAR_REGEX = /[^-a-z0-9_]/i.freeze
16
+
15
17
  # Note: This value is for internal use only
16
18
  #
17
19
  # @return [String]
@@ -39,7 +41,8 @@ module VagrantPlugins
39
41
  # @return [Integer,String]
40
42
  attr_accessor :size
41
43
 
42
- # Path to the location of the disk file (Optional)
44
+ # Path to the location of the disk file (Optional for `:disk` type,
45
+ # required for `:dvd` type.)
43
46
  #
44
47
  # @return [String]
45
48
  attr_accessor :file
@@ -97,7 +100,11 @@ module VagrantPlugins
97
100
  end
98
101
 
99
102
  current = @provider_config.merge(current) if !@provider_config.empty?
100
- @provider_config = current
103
+ if current
104
+ @provider_config = current[:provider_config]
105
+ else
106
+ @provider_config = {}
107
+ end
101
108
  end
102
109
 
103
110
  def finalize!
@@ -107,27 +114,25 @@ module VagrantPlugins
107
114
  @size = nil if @size == UNSET_VALUE
108
115
  @file = nil if @file == UNSET_VALUE
109
116
 
110
- @disk_ext = "vdi" if @disk_ext == UNSET_VALUE
111
-
112
117
  if @primary == UNSET_VALUE
113
118
  @primary = false
114
119
  end
115
120
 
116
- if @name == UNSET_VALUE
121
+ if @name.is_a?(String) && @name.match(FILE_CHAR_REGEX)
122
+ @logger.warn("Vagrant will remove detected invalid characters in '#{@name}' and convert the disk name into something usable for a file")
123
+ @name.gsub!(FILE_CHAR_REGEX, "_")
124
+ elsif @name == UNSET_VALUE
117
125
  if @primary
118
126
  @name = "vagrant_primary"
119
127
  else
120
128
  @name = nil
121
129
  end
122
130
  end
123
-
124
- @provider_config = nil if @provider_config == {}
125
131
  end
126
132
 
127
133
  # @return [Array] array of strings of error messages from config option validation
128
134
  def validate(machine)
129
135
  errors = _detected_errors
130
-
131
136
  # validate type with list of known disk types
132
137
 
133
138
  if !DEFAULT_DISK_TYPES.include?(@type)
@@ -135,13 +140,20 @@ module VagrantPlugins
135
140
  types: DEFAULT_DISK_TYPES.join(', '))
136
141
  end
137
142
 
138
- if @disk_ext
143
+ if @disk_ext == UNSET_VALUE
144
+ if machine.provider.capability?(:set_default_disk_ext)
145
+ @disk_ext = machine.provider.capability(:set_default_disk_ext)
146
+ else
147
+ @logger.warn("No provider capability defined to set default 'disk_ext' type. Will use 'vdi' for disk extension.")
148
+ @disk_ext = "vdi"
149
+ end
150
+ elsif @disk_ext
139
151
  @disk_ext = @disk_ext.downcase
140
152
 
141
153
  if machine.provider.capability?(:validate_disk_ext)
142
154
  if !machine.provider.capability(:validate_disk_ext, @disk_ext)
143
- if machine.provider.capability?(:get_default_disk_ext)
144
- disk_exts = machine.provider.capability(:get_default_disk_ext).join(', ')
155
+ if machine.provider.capability?(:default_disk_exts)
156
+ disk_exts = machine.provider.capability(:default_disk_exts).join(', ')
145
157
  else
146
158
  disk_exts = "not found"
147
159
  end
@@ -158,10 +170,18 @@ module VagrantPlugins
158
170
  if @size.is_a?(String)
159
171
  @size = Vagrant::Util::Numeric.string_to_bytes(@size)
160
172
  end
173
+ end
161
174
 
162
- if !@size
163
- errors << I18n.t("vagrant.config.disk.invalid_size", name: @name, machine: machine.name)
164
- end
175
+ if !@size && type == :disk
176
+ errors << I18n.t("vagrant.config.disk.invalid_size", name: @name, machine: machine.name)
177
+ end
178
+
179
+ if @type == :dvd && !@file
180
+ errors << I18n.t("vagrant.config.disk.dvd_type_file_required", name: @name, machine: machine.name)
181
+ end
182
+
183
+ if @type == :dvd && @primary
184
+ errors << I18n.t("vagrant.config.disk.dvd_type_primary", name: @name, machine: machine.name)
165
185
  end
166
186
 
167
187
  if @file
@@ -174,10 +194,12 @@ module VagrantPlugins
174
194
  end
175
195
 
176
196
  if @provider_config
177
- if !@provider_config.keys.include?(machine.provider_name)
178
- machine.env.ui.warn(I18n.t("vagrant.config.disk.missing_provider",
179
- machine: machine.name,
180
- provider_name: machine.provider_name))
197
+ if !@provider_config.empty?
198
+ if !@provider_config.key?(machine.provider_name)
199
+ machine.env.ui.warn(I18n.t("vagrant.config.disk.missing_provider",
200
+ machine: machine.name,
201
+ provider_name: machine.provider_name))
202
+ end
181
203
  end
182
204
  end
183
205
 
@@ -8,10 +8,12 @@ require "vagrant/config/v2/util"
8
8
  require "vagrant/util/platform"
9
9
  require "vagrant/util/presence"
10
10
  require "vagrant/util/experimental"
11
+ require "vagrant/util/map_command_options"
11
12
 
12
13
  require File.expand_path("../vm_provisioner", __FILE__)
13
14
  require File.expand_path("../vm_subvm", __FILE__)
14
15
  require File.expand_path("../disk", __FILE__)
16
+ require File.expand_path("../cloud_init", __FILE__)
15
17
 
16
18
  module VagrantPlugins
17
19
  module Kernel_V2
@@ -21,6 +23,8 @@ module VagrantPlugins
21
23
  DEFAULT_VM_NAME = :default
22
24
 
23
25
  attr_accessor :allowed_synced_folder_types
26
+ attr_accessor :allow_fstab_modification
27
+ attr_accessor :allow_hosts_modification
24
28
  attr_accessor :base_mac
25
29
  attr_accessor :base_address
26
30
  attr_accessor :boot_timeout
@@ -46,6 +50,7 @@ module VagrantPlugins
46
50
  attr_accessor :usable_port_range
47
51
  attr_reader :provisioners
48
52
  attr_reader :disks
53
+ attr_reader :cloud_init_configs
49
54
  attr_reader :box_extra_download_options
50
55
 
51
56
  # This is an experimental feature that isn't public yet.
@@ -55,6 +60,7 @@ module VagrantPlugins
55
60
  @logger = Log4r::Logger.new("vagrant::config::vm")
56
61
 
57
62
  @allowed_synced_folder_types = UNSET_VALUE
63
+ @allow_fstab_modification = UNSET_VALUE
58
64
  @base_mac = UNSET_VALUE
59
65
  @base_address = UNSET_VALUE
60
66
  @boot_timeout = UNSET_VALUE
@@ -72,6 +78,7 @@ module VagrantPlugins
72
78
  @box_extra_download_options = UNSET_VALUE
73
79
  @box_url = UNSET_VALUE
74
80
  @box_version = UNSET_VALUE
81
+ @allow_hosts_modification = UNSET_VALUE
75
82
  @clone = UNSET_VALUE
76
83
  @communicator = UNSET_VALUE
77
84
  @graceful_halt_timeout = UNSET_VALUE
@@ -80,6 +87,7 @@ module VagrantPlugins
80
87
  @post_up_message = UNSET_VALUE
81
88
  @provisioners = []
82
89
  @disks = []
90
+ @cloud_init_configs = []
83
91
  @usable_port_range = UNSET_VALUE
84
92
 
85
93
  # Internal state
@@ -152,6 +160,28 @@ module VagrantPlugins
152
160
  end
153
161
  result.instance_variable_set(:@disks, new_disks)
154
162
 
163
+ # Merge defined cloud_init_configs
164
+ other_cloud_init_configs = other.instance_variable_get(:@cloud_init_configs)
165
+ new_cloud_init_configs = []
166
+ @cloud_init_configs.each do |p|
167
+ other_p = other_cloud_init_configs.find { |o| p.id == o.id }
168
+ if other_p
169
+ # there is an override. take it.
170
+ other_p.config = p.config.merge(other_p.config)
171
+
172
+ # Remove duplicate disk config from other
173
+ p = other_p
174
+ other_cloud_init_configs.delete(other_p)
175
+ end
176
+
177
+ # there is an override, merge it into the
178
+ new_cloud_init_configs << p.dup
179
+ end
180
+ other_cloud_init_configs.each do |p|
181
+ new_cloud_init_configs << p.dup
182
+ end
183
+ result.instance_variable_set(:@cloud_init_configs, new_cloud_init_configs)
184
+
155
185
  # Merge the providers by prepending any configuration blocks we
156
186
  # have for providers onto the new configuration.
157
187
  other_providers = other.instance_variable_get(:@__providers)
@@ -370,7 +400,7 @@ module VagrantPlugins
370
400
 
371
401
  if Vagrant::Util::Experimental.feature_enabled?("dependency_provisioners")
372
402
  opts = {before: before, after: after}
373
- prov = VagrantConfigProvisioner.new(name, type.to_sym, opts)
403
+ prov = VagrantConfigProvisioner.new(name, type.to_sym, **opts)
374
404
  else
375
405
  prov = VagrantConfigProvisioner.new(name, type.to_sym)
376
406
  end
@@ -380,7 +410,9 @@ module VagrantPlugins
380
410
  prov.preserve_order = !!options.delete(:preserve_order) if \
381
411
  options.key?(:preserve_order)
382
412
  prov.run = options.delete(:run) if options.key?(:run)
383
- prov.add_config(options, &block)
413
+ prov.communicator_required = options.delete(:communicator_required) if options.key?(:communicator_required)
414
+
415
+ prov.add_config(**options, &block)
384
416
  nil
385
417
  end
386
418
 
@@ -435,7 +467,7 @@ module VagrantPlugins
435
467
  disk_config.set_options(options)
436
468
 
437
469
  # Add provider config
438
- disk_config.add_provider_config(provider_options, &block)
470
+ disk_config.add_provider_config(**provider_options, &block)
439
471
 
440
472
  if !Vagrant::Util::Experimental.feature_enabled?("disks")
441
473
  @logger.warn("Disk config defined, but experimental feature is not enabled. To use this feature, enable it with the experimental flag `disks`. Disk will not be added to internal config, and will be ignored.")
@@ -445,6 +477,31 @@ module VagrantPlugins
445
477
  @disks << disk_config
446
478
  end
447
479
 
480
+ # Stores config options for cloud_init
481
+ #
482
+ # @param [Symbol] type
483
+ # @param [Hash] options
484
+ # @param [Block] block
485
+ def cloud_init(type=nil, **options, &block)
486
+ type = type.to_sym if type
487
+
488
+ cloud_init_config = VagrantConfigCloudInit.new(type)
489
+
490
+ if block_given?
491
+ block.call(cloud_init_config, VagrantConfigCloudInit)
492
+ else
493
+ # config is hash
494
+ cloud_init_config.set_options(options)
495
+ end
496
+
497
+ if !Vagrant::Util::Experimental.feature_enabled?("cloud_init")
498
+ @logger.warn("cloud_init config defined, but experimental feature is not enabled. To use this feature, enable it with the experimental flag `cloud_init`. cloud_init config will not be added to internal config, and will be ignored.")
499
+ return
500
+ end
501
+
502
+ @cloud_init_configs << cloud_init_config
503
+ end
504
+
448
505
  #-------------------------------------------------------------------
449
506
  # Internal methods, don't call these.
450
507
  #-------------------------------------------------------------------
@@ -473,6 +530,7 @@ module VagrantPlugins
473
530
  @box_version = nil if @box_version == UNSET_VALUE
474
531
  @box_download_options = {} if @box_download_options == UNSET_VALUE
475
532
  @box_extra_download_options = Vagrant::Util::MapCommandOptions.map_to_command_options(@box_download_options)
533
+ @allow_hosts_modification = true if @allow_hosts_modification == UNSET_VALUE
476
534
  @clone = nil if @clone == UNSET_VALUE
477
535
  @communicator = nil if @communicator == UNSET_VALUE
478
536
  @graceful_halt_timeout = 60 if @graceful_halt_timeout == UNSET_VALUE
@@ -600,11 +658,6 @@ module VagrantPlugins
600
658
  options[:type] = :nfs
601
659
  end
602
660
 
603
- # Ignore NFS on Windows
604
- if options[:type] == :nfs && Vagrant::Util::Platform.windows?
605
- options.delete(:type)
606
- end
607
-
608
661
  if options[:hostpath] == '.'
609
662
  current_dir_shared = true
610
663
  end
@@ -614,6 +667,10 @@ module VagrantPlugins
614
667
  d.finalize!
615
668
  end
616
669
 
670
+ @cloud_init_configs.each do |c|
671
+ c.finalize!
672
+ end
673
+
617
674
  if !current_dir_shared && !@__synced_folders["/vagrant"]
618
675
  synced_folder(".", "/vagrant")
619
676
  end
@@ -668,6 +725,17 @@ module VagrantPlugins
668
725
  def validate(machine, ignore_provider=nil)
669
726
  errors = _detected_errors
670
727
 
728
+ if @allow_fstab_modification == UNSET_VALUE
729
+ machine.synced_folders.types.each do |impl_name|
730
+ inst = machine.synced_folders.type(impl_name)
731
+ if inst.capability?(:default_fstab_modification) && inst.capability(:default_fstab_modification) == false
732
+ @allow_fstab_modification = false
733
+ break
734
+ end
735
+ end
736
+ @allow_fstab_modification = true if @allow_fstab_modification == UNSET_VALUE
737
+ end
738
+
671
739
  if !box && !clone && !machine.provider_options[:box_optional]
672
740
  errors << I18n.t("vagrant.config.vm.box_missing")
673
741
  end
@@ -676,6 +744,10 @@ module VagrantPlugins
676
744
  errors << I18n.t("vagrant.config.vm.clone_and_box")
677
745
  end
678
746
 
747
+ if box && box.empty?
748
+ errors << I18n.t("vagrant.config.vm.box_empty", machine_name: machine.name)
749
+ end
750
+
679
751
  errors << I18n.t("vagrant.config.vm.hostname_invalid_characters", name: machine.name) if \
680
752
  @hostname && @hostname !~ /^[a-z0-9][-.a-z0-9]*$/i
681
753
 
@@ -725,7 +797,7 @@ module VagrantPlugins
725
797
  end
726
798
 
727
799
  box_download_options.each do |k, v|
728
- # If the value is truthy and
800
+ # If the value is truthy and
729
801
  # if `box_extra_download_options` does not include the key
730
802
  # then the conversion to extra download options produced an error
731
803
  if v && !box_extra_download_options.include?("--#{k}")
@@ -791,7 +863,17 @@ module VagrantPlugins
791
863
  valid_network_types = [:forwarded_port, :private_network, :public_network]
792
864
 
793
865
  port_range=(1..65535)
866
+ has_hostname_config = false
794
867
  networks.each do |type, options|
868
+ if options[:hostname]
869
+ if has_hostname_config
870
+ errors << I18n.t("vagrant.config.vm.multiple_networks_set_hostname")
871
+ end
872
+ if options[:ip] == nil
873
+ errors << I18n.t("vagrant.config.vm.network_with_hostname_must_set_ip")
874
+ end
875
+ has_hostname_config = true
876
+ end
795
877
  if !valid_network_types.include?(type)
796
878
  errors << I18n.t("vagrant.config.vm.network_type_invalid",
797
879
  type: type.to_s)
@@ -834,7 +916,7 @@ module VagrantPlugins
834
916
  end
835
917
 
836
918
  # Validate disks
837
- # Check if there is more than one primrary disk defined and throw an error
919
+ # Check if there is more than one primary disk defined and throw an error
838
920
  primary_disks = @disks.select { |d| d.primary && d.type == :disk }
839
921
  if primary_disks.size > 1
840
922
  errors << I18n.t("vagrant.config.vm.multiple_primary_disks_error",
@@ -842,14 +924,29 @@ module VagrantPlugins
842
924
  end
843
925
 
844
926
  disk_names = @disks.map { |d| d.name }
845
- duplicate_names = disk_names.detect{ |d| disk_names.count(d) > 1 }
846
- if duplicate_names && duplicate_names.size
927
+ duplicate_names = disk_names.find_all { |d| disk_names.count(d) > 1 }
928
+ if duplicate_names.any?
847
929
  errors << I18n.t("vagrant.config.vm.multiple_disk_names_error",
848
- name: duplicate_names)
930
+ name: machine.name,
931
+ disk_names: duplicate_names.uniq.join("\n"))
932
+ end
933
+
934
+ disk_files = @disks.map { |d| d.file }
935
+ duplicate_files = disk_files.find_all { |d| d && disk_files.count(d) > 1 }
936
+ if duplicate_files.any?
937
+ errors << I18n.t("vagrant.config.vm.multiple_disk_files_error",
938
+ name: machine.name,
939
+ disk_files: duplicate_files.uniq.join("\n"))
849
940
  end
850
941
 
851
942
  @disks.each do |d|
852
943
  error = d.validate(machine)
944
+ errors.concat(error) if !error.empty?
945
+ end
946
+
947
+ # Validate clout_init_configs
948
+ @cloud_init_configs.each do |c|
949
+ error = c.validate(machine)
853
950
  errors.concat error if !error.empty?
854
951
  end
855
952
 
@@ -927,6 +1024,18 @@ module VagrantPlugins
927
1024
  end
928
1025
  end
929
1026
 
1027
+ if ![TrueClass, FalseClass].include?(@allow_fstab_modification.class)
1028
+ errors["vm"] << I18n.t("vagrant.config.vm.config_type",
1029
+ option: "allow_fstab_modification", given: @allow_fstab_modification.class, required: "Boolean"
1030
+ )
1031
+ end
1032
+
1033
+ if ![TrueClass, FalseClass].include?(@allow_hosts_modification.class)
1034
+ errors["vm"] << I18n.t("vagrant.config.vm.config_type",
1035
+ option: "allow_hosts_modification", given: @allow_hosts_modification.class, required: "Boolean"
1036
+ )
1037
+ end
1038
+
930
1039
  errors
931
1040
  end
932
1041
 
@@ -56,6 +56,12 @@ module VagrantPlugins
56
56
  # @return [String, Symbol]
57
57
  attr_accessor :after
58
58
 
59
+ # Boolean, when true signifies that some communicator must
60
+ # be available in order for the provisioner to run.
61
+ #
62
+ # @return [Boolean]
63
+ attr_accessor :communicator_required
64
+
59
65
  def initialize(name, type, **options)
60
66
  @logger = Log4r::Logger.new("vagrant::config::vm::provisioner")
61
67
  @logger.debug("Provisioner defined: #{name}")
@@ -69,6 +75,7 @@ module VagrantPlugins
69
75
  @type = type
70
76
  @before = options[:before]
71
77
  @after = options[:after]
78
+ @communicator_required = options.fetch(:communicator_required, true)
72
79
 
73
80
  # Attempt to find the provisioner...
74
81
  if !Vagrant.plugin("2").manager.provisioners[type]
@@ -118,6 +125,10 @@ module VagrantPlugins
118
125
 
119
126
  provisioner_names = provisioners.map { |i| i.name.to_s if i.name != name }.compact
120
127
 
128
+ if ![TrueClass, FalseClass].include?(@communicator_required.class)
129
+ errors << I18n.t("vagrant.provisioners.base.wrong_type", opt: "communicator_required", type: "boolean")
130
+ end
131
+
121
132
  if @before && @after
122
133
  errors << I18n.t("vagrant.provisioners.base.both_before_after_set")
123
134
  end
@@ -127,7 +138,7 @@ module VagrantPlugins
127
138
  if @before.is_a?(Symbol) && !VALID_BEFORE_AFTER_TYPES.include?(@before)
128
139
  errors << I18n.t("vagrant.provisioners.base.invalid_alias_value", opt: "before", alias: VALID_BEFORE_AFTER_TYPES.join(", "))
129
140
  elsif !@before.is_a?(String) && !VALID_BEFORE_AFTER_TYPES.include?(@before)
130
- errors << I18n.t("vagrant.provisioners.base.wrong_type", opt: "before")
141
+ errors << I18n.t("vagrant.provisioners.base.wrong_type", opt: "before", type: "string")
131
142
  end
132
143
 
133
144
  if !provisioner_names.include?(@before)
@@ -153,7 +164,7 @@ module VagrantPlugins
153
164
  if @after.is_a?(Symbol)
154
165
  errors << I18n.t("vagrant.provisioners.base.invalid_alias_value", opt: "after", alias: VALID_BEFORE_AFTER_TYPES.join(", "))
155
166
  elsif !@after.is_a?(String)
156
- errors << I18n.t("vagrant.provisioners.base.wrong_type", opt: "after")
167
+ errors << I18n.t("vagrant.provisioners.base.wrong_type", opt: "after", type: "string")
157
168
  end
158
169
 
159
170
  if !provisioner_names.include?(@after)