vagrant-unbundled 2.2.0.0 → 2.2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -4
  3. data/CHANGELOG.md +49 -0
  4. data/lib/vagrant/action/builtin/box_check_outdated.rb +1 -0
  5. data/lib/vagrant/action/builtin/config_validate.rb +1 -1
  6. data/lib/vagrant/box.rb +27 -0
  7. data/lib/vagrant/bundler.rb +7 -2
  8. data/lib/vagrant/cli.rb +4 -0
  9. data/lib/vagrant/config/v2/root.rb +6 -2
  10. data/lib/vagrant/plugin/v2/communicator.rb +7 -0
  11. data/lib/vagrant/plugin/v2/trigger.rb +5 -1
  12. data/lib/vagrant/util/network_ip.rb +1 -26
  13. data/lib/vagrant/util/platform.rb +19 -7
  14. data/lib/vagrant/util/powershell.rb +23 -25
  15. data/lib/vagrant/util/ssh.rb +18 -5
  16. data/lib/vagrant/vagrantfile.rb +13 -2
  17. data/plugins/commands/login/plugin.rb +0 -1
  18. data/plugins/commands/validate/command.rb +17 -2
  19. data/plugins/communicators/ssh/communicator.rb +22 -12
  20. data/plugins/communicators/winrm/communicator.rb +5 -1
  21. data/plugins/communicators/winrm/shell.rb +25 -1
  22. data/plugins/guests/debian/cap/change_host_name.rb +66 -10
  23. data/plugins/guests/windows/cap/change_host_name.rb +4 -12
  24. data/plugins/guests/windows/cap/reboot.rb +36 -6
  25. data/plugins/guests/windows/plugin.rb +5 -0
  26. data/plugins/kernel_v2/config/vm.rb +8 -4
  27. data/plugins/providers/docker/action/host_machine_sync_folders.rb +2 -3
  28. data/plugins/providers/hyperv/provider.rb +15 -3
  29. data/plugins/providers/hyperv/scripts/delete_vm.ps1 +3 -0
  30. data/plugins/providers/hyperv/scripts/get_network_config.ps1 +1 -1
  31. data/plugins/providers/hyperv/scripts/set_network_vlan.ps1 +0 -6
  32. data/plugins/providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 +1 -1
  33. data/plugins/providers/virtualbox/action.rb +2 -0
  34. data/plugins/providers/virtualbox/action/network.rb +33 -42
  35. data/plugins/providers/virtualbox/action/set_default_nic_type.rb +69 -0
  36. data/plugins/providers/virtualbox/config.rb +10 -0
  37. data/plugins/providers/virtualbox/driver/meta.rb +1 -0
  38. data/plugins/providers/virtualbox/driver/version_5_0.rb +17 -6
  39. data/plugins/providers/virtualbox/driver/version_5_2.rb +2 -2
  40. data/plugins/providers/virtualbox/driver/version_6_0.rb +105 -0
  41. data/plugins/providers/virtualbox/plugin.rb +1 -0
  42. data/plugins/providers/virtualbox/synced_folder.rb +2 -1
  43. data/plugins/provisioners/docker/cap/linux/docker_configure_vagrant_user.rb +1 -0
  44. data/plugins/provisioners/shell/config.rb +4 -1
  45. data/plugins/provisioners/shell/provisioner.rb +6 -0
  46. data/plugins/synced_folders/smb/synced_folder.rb +18 -5
  47. data/templates/locales/en.yml +19 -3
  48. data/vagrant.gemspec +3 -1
  49. data/version.txt +1 -1
  50. metadata +407 -12
@@ -9,6 +9,9 @@ $ErrorActionPreference = "Stop"
9
9
 
10
10
  try {
11
11
  $VM = Hyper-V\Get-VM -Id $VmId
12
+ if((Get-Command Hyper-V\Set-VM).Parameters["AutomaticCheckpointsEnabled"] -ne $null) {
13
+ Hyper-V\Set-VM -VM $VM -AutomaticCheckpointsEnabled $false -ErrorAction SilentlyContinue
14
+ }
12
15
  Hyper-V\Remove-VM $VM -Force
13
16
  } catch {
14
17
  Write-ErrorMessage "Failed to delete VM: ${PSItem}"
@@ -35,7 +35,7 @@ try {
35
35
  foreach ($macaddr in $macaddresses) {
36
36
  $macaddress = $macaddr.MacAddress -replace '(.{2})(?!$)', '${1}-'
37
37
  $addr = Get-NetNeighbor -LinkLayerAddress $macaddress -ErrorAction SilentlyContinue | select IPAddress
38
- if ($ip_address) {
38
+ if ($addr) {
39
39
  $ip_address = $addr.IPAddress
40
40
  if ($ip_address.Contains(".")) {
41
41
  $ip4_address = $ip_address
@@ -7,12 +7,6 @@ param (
7
7
  [int]$VlanId
8
8
  )
9
9
 
10
- # Include the following modules
11
- $presentDir = Split-Path -parent $PSCommandPath
12
- $modules = @()
13
- $modules += $presentDir + "\utils\write_messages.ps1"
14
- forEach ($module in $modules) { . $module }
15
-
16
10
  try {
17
11
  $vm = Hyper-V\Get-VM -Id $VmId -ErrorAction "stop"
18
12
  Hyper-V\Set-VMNetworkAdapterVlan $vm -Access -Vlanid $VlanId
@@ -85,7 +85,7 @@ function New-VagrantVMVMCX {
85
85
  VhdDestinationPath = Join-Path $DataPath "Virtual Hard Disks";
86
86
  VirtualMachinePath = $DataPath;
87
87
  }
88
- $VMConfig = (Hyper-V\Compare-VM -Copy -GenerateNewID @NewVMConfig)
88
+ $VMConfig = (Hyper-V\Compare-VM -Copy -GenerateNewID @NewVMConfig -ErrorAction SilentlyContinue)
89
89
 
90
90
  # If the config is empty it means the import failed. Attempt to provide
91
91
  # context for failure
@@ -42,6 +42,7 @@ module VagrantPlugins
42
42
  autoload :PrepareForwardedPortCollisionParams, File.expand_path("../action/prepare_forwarded_port_collision_params", __FILE__)
43
43
  autoload :Resume, File.expand_path("../action/resume", __FILE__)
44
44
  autoload :SaneDefaults, File.expand_path("../action/sane_defaults", __FILE__)
45
+ autoload :SetDefaultNICType, File.expand_path("../action/set_default_nic_type", __FILE__)
45
46
  autoload :SetName, File.expand_path("../action/set_name", __FILE__)
46
47
  autoload :SnapshotDelete, File.expand_path("../action/snapshot_delete", __FILE__)
47
48
  autoload :SnapshotRestore, File.expand_path("../action/snapshot_restore", __FILE__)
@@ -71,6 +72,7 @@ module VagrantPlugins
71
72
  b.use SyncedFolderCleanup
72
73
  b.use SyncedFolders
73
74
  b.use PrepareNFSSettings
75
+ b.use SetDefaultNICType
74
76
  b.use ClearNetworkInterfaces
75
77
  b.use Network
76
78
  b.use NetworkFixIPv6
@@ -261,16 +261,26 @@ module VagrantPlugins
261
261
 
262
262
  begin
263
263
  ip = IPAddr.new(options[:ip])
264
- rescue IPAddr::InvalidAddressError => e
265
- raise Vagrant::Errors::NetworkAddressInvalid, :ip => options[:ip], :error_msg => e.message
266
- end
264
+ if ip.ipv4?
265
+ options[:netmask] ||= "255.255.255.0"
266
+ elsif ip.ipv6?
267
+ options[:netmask] ||= 64
267
268
 
268
- if ip.ipv4?
269
- options[:netmask] ||= "255.255.255.0"
269
+ # Append a 6 to the end of the type
270
+ options[:type] = "#{options[:type]}6".to_sym
271
+ else
272
+ raise IPAddr::AddressFamilyError, 'unknown address family'
273
+ end
270
274
 
271
275
  # Calculate our network address for the given IP/netmask
272
- netaddr = network_address(options[:ip], options[:netmask])
276
+ netaddr = IPAddr.new("#{options[:ip]}/#{options[:netmask]}")
277
+ rescue IPAddr::Error => e
278
+ raise Vagrant::Errors::NetworkAddressInvalid,
279
+ address: options[:ip], mask: options[:netmask],
280
+ error: e.message
281
+ end
273
282
 
283
+ if ip.ipv4?
274
284
  # Verify that a host-only network subnet would not collide
275
285
  # with a bridged networking interface.
276
286
  #
@@ -287,44 +297,24 @@ module VagrantPlugins
287
297
  interface_name: interface[:name]
288
298
  end
289
299
  end
290
-
291
- # Split the IP address into its components
292
- ip_parts = netaddr.split(".").map { |i| i.to_i }
293
-
294
- # Calculate the adapter IP, which we assume is the IP ".1" at
295
- # the end usually.
296
- adapter_ip = ip_parts.dup
297
- adapter_ip[3] += 1
298
- options[:adapter_ip] ||= adapter_ip.join(".")
299
- elsif ip.ipv6?
300
- # Default subnet prefix length
301
- options[:netmask] ||= 64
302
-
303
- # Set adapter IP to <prefix>::1
304
- options[:adapter_ip] ||= (ip.mask(options[:netmask].to_i) | 1).to_s
305
-
306
- # Append a 6 to the end of the type
307
- options[:type] = "#{options[:type]}6".to_sym
308
- else
309
- raise "BUG: Unknown IP type: #{ip.inspect}"
310
300
  end
311
301
 
302
+ # Calculate the adapter IP which is the network address with
303
+ # the final bit + 1. Usually it is "x.x.x.1" for IPv4 and
304
+ # "<prefix>::1" for IPv6
305
+ options[:adapter_ip] ||= (netaddr | 1).to_s
306
+
312
307
  dhcp_options = {}
313
308
  if options[:type] == :dhcp
314
- # Calculate the DHCP server IP, which is the network address
315
- # with the final octet + 2. So "172.28.0.0" turns into "172.28.0.2"
316
- dhcp_ip = ip_parts.dup
317
- dhcp_ip[3] += 2
318
- dhcp_options[:dhcp_ip] = options[:dhcp_ip] || dhcp_ip.join(".")
319
-
320
- # Calculate the lower and upper bound for the DHCP server
321
- dhcp_lower = ip_parts.dup
322
- dhcp_lower[3] += 3
323
- dhcp_options[:dhcp_lower] = options[:dhcp_lower] || dhcp_lower.join(".")
324
-
325
- dhcp_upper = ip_parts.dup
326
- dhcp_upper[3] = 254
327
- dhcp_options[:dhcp_upper] = options[:dhcp_upper] || dhcp_upper.join(".")
309
+ # Calculate the DHCP server IP and lower & upper bound
310
+ # Example: for "192.168.22.64/26" network range those are:
311
+ # dhcp_ip: "192.168.22.66",
312
+ # dhcp_lower: "192.168.22.67"
313
+ # dhcp_upper: "192.168.22.126"
314
+ ip_range = netaddr.to_range
315
+ dhcp_options[:dhcp_ip] = options[:dhcp_ip] || (ip_range.first | 2).to_s
316
+ dhcp_options[:dhcp_lower] = options[:dhcp_lower] || (ip_range.first | 3).to_s
317
+ dhcp_options[:dhcp_upper] = options[:dhcp_upper] || (ip_range.last(2).first).to_s
328
318
  end
329
319
 
330
320
  return {
@@ -413,15 +403,16 @@ module VagrantPlugins
413
403
  end
414
404
 
415
405
  def nat_config(options)
416
- return {
406
+ return options.merge(
417
407
  auto_config: false
418
- }
408
+ )
419
409
  end
420
410
 
421
411
  def nat_adapter(config)
422
412
  return {
423
413
  adapter: config[:adapter],
424
414
  type: :nat,
415
+ nic_type: config[:nic_type],
425
416
  }
426
417
  end
427
418
 
@@ -0,0 +1,69 @@
1
+ require "log4r"
2
+
3
+ module VagrantPlugins
4
+ module ProviderVirtualBox
5
+ module Action
6
+ # This sets the default NIC type used for network adapters created
7
+ # on the guest. Also includes a check of NIC types in use and VirtualBox
8
+ # version to determine if E1000 NIC types are vulnerable.
9
+ #
10
+ # NOTE: Vulnerability was fixed here: https://www.virtualbox.org/changeset/75330/vbox
11
+ class SetDefaultNICType
12
+ # Defines versions of VirtualBox with susceptible implementation
13
+ # of the E1000 devices.
14
+ E1000_SUSCEPTIBLE = Gem::Requirement.new("<= 5.2.22").freeze
15
+
16
+ def initialize(app, env)
17
+ @logger = Log4r::Logger.new("vagrant::plugins::virtualbox::set_default_nic_type")
18
+ @app = app
19
+ end
20
+
21
+ def call(env)
22
+ default_nic_type = env[:machine].provider_config.default_nic_type
23
+
24
+ e1000_in_use = [
25
+ # simple check on default_nic_type
26
+ ->{ default_nic_type.nil? || default_nic_type.to_s.start_with?("8254") },
27
+ # check provider defined adapters
28
+ ->{ env[:machine].provider_config.network_adapters.values.detect{ |_, opts|
29
+ opts[:nic_type].to_s.start_with?("8254") } },
30
+ # finish with inspecting configured networks
31
+ ->{ env[:machine].config.vm.networks.detect{ |_, opts|
32
+ opts.fetch(:virtualbox__nic_type, opts[:nic_type]).to_s.start_with?("8254") } }
33
+ ]
34
+
35
+ # Check if VirtualBox E1000 implementation is vulnerable
36
+ if E1000_SUSCEPTIBLE.satisfied_by?(Gem::Version.new(env[:machine].provider.driver.version))
37
+ @logger.info("Detected VirtualBox version with susceptible E1000 implementation (`#{E1000_SUSCEPTIBLE}`)")
38
+ if e1000_in_use.any?(&:call)
39
+ env[:ui].warn I18n.t("vagrant.actions.vm.set_default_nic_type.e1000_warning")
40
+ end
41
+ end
42
+
43
+ if default_nic_type
44
+ @logger.info("Default NIC type for VirtualBox interfaces `#{default_nic_type}`")
45
+ # Update network adapters defined in provider configuration
46
+ env[:machine].provider_config.network_adapters.each do |slot, args|
47
+ _, opts = args
48
+ if opts && !opts.key?(:nic_type)
49
+ @logger.info("Setting default NIC type (`#{default_nic_type}`) adapter `#{slot}` - `#{args}`")
50
+ opts[:nic_type] = default_nic_type
51
+ end
52
+ end
53
+
54
+ # Update generally defined networks
55
+ env[:machine].config.vm.networks.each do |type, options|
56
+ next if !type.to_s.end_with?("_network")
57
+ if !options.key?(:nic_type) && !options.key?(:virtualbox__nic_type)
58
+ @logger.info("Setting default NIC type (`#{default_nic_type}`) for `#{type}` - `#{options}`")
59
+ options[:virtualbox__nic_type] = default_nic_type
60
+ end
61
+ end
62
+ end
63
+
64
+ @app.call(env)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -19,6 +19,13 @@ module VagrantPlugins
19
19
  # @return [Array]
20
20
  attr_reader :customizations
21
21
 
22
+ # Set the default type of NIC hardware to be used for network
23
+ # devices. By default this is `nil` and VirtualBox's default
24
+ # will be used.
25
+ #
26
+ # @return [String]
27
+ attr_accessor :default_nic_type
28
+
22
29
  # If true, unused network interfaces will automatically be deleted.
23
30
  # This defaults to false because the detection does not work across
24
31
  # multiple users, and because on Windows this operation requires
@@ -68,6 +75,7 @@ module VagrantPlugins
68
75
  @auto_nat_dns_proxy = UNSET_VALUE
69
76
  @check_guest_additions = UNSET_VALUE
70
77
  @customizations = []
78
+ @default_nic_type = UNSET_VALUE
71
79
  @destroy_unused_network_interfaces = UNSET_VALUE
72
80
  @functional_vboxsf = UNSET_VALUE
73
81
  @name = UNSET_VALUE
@@ -158,6 +166,8 @@ module VagrantPlugins
158
166
 
159
167
  # The default name is just nothing, and we default it
160
168
  @name = nil if @name == UNSET_VALUE
169
+
170
+ @default_nic_type = nil if @default_nic_type == UNSET_VALUE
161
171
  end
162
172
 
163
173
  def validate(machine)
@@ -63,6 +63,7 @@ module VagrantPlugins
63
63
  "5.0" => Version_5_0,
64
64
  "5.1" => Version_5_1,
65
65
  "5.2" => Version_5_2,
66
+ "6.0" => Version_6_0,
66
67
  }
67
68
 
68
69
  if @@version.start_with?("4.2.14")
@@ -674,6 +674,8 @@ module VagrantPlugins
674
674
  hostpath]
675
675
  args << "--transient" if folder.key?(:transient) && folder[:transient]
676
676
 
677
+ args << "--automount" if folder.key?(:automount) && folder[:automount]
678
+
677
679
  if folder[:SharedFoldersEnableSymlinksCreate]
678
680
  # Enable symlinks on the shared folder
679
681
  execute("setextradata", @uuid, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/#{folder[:name]}", "1", retryable: true)
@@ -687,12 +689,21 @@ module VagrantPlugins
687
689
  def ssh_port(expected_port)
688
690
  @logger.debug("Searching for SSH port: #{expected_port.inspect}")
689
691
 
690
- # Look for the forwarded port only by comparing the guest port
691
- read_forwarded_ports.each do |_, _, hostport, guestport|
692
- return hostport if guestport == expected_port
693
- end
694
-
695
- nil
692
+ # Look for the forwarded port. Valid based on the guest port, but will do
693
+ # scoring based matching to determine best value when multiple results are
694
+ # available.
695
+ matches = read_forwarded_ports.map do |_, name, hostport, guestport, host_ip|
696
+ next if guestport != expected_port
697
+ match = [0, hostport]
698
+ match[0] += 1 if name == "ssh"
699
+ match[0] += 1 if name.downcase == "ssh"
700
+ match[0] += 1 if host_ip == "127.0.0.1"
701
+ match
702
+ end.compact
703
+
704
+ result = matches.sort_by(&:first).last
705
+
706
+ result.last if result
696
707
  end
697
708
 
698
709
  def resume
@@ -1,10 +1,10 @@
1
- require File.expand_path("../version_5_1", __FILE__)
1
+ require File.expand_path("../version_5_0", __FILE__)
2
2
 
3
3
  module VagrantPlugins
4
4
  module ProviderVirtualBox
5
5
  module Driver
6
6
  # Driver for VirtualBox 5.2.x
7
- class Version_5_2 < Version_5_1
7
+ class Version_5_2 < Version_5_0
8
8
  def initialize(uuid)
9
9
  super
10
10
 
@@ -0,0 +1,105 @@
1
+ require File.expand_path("../version_5_0", __FILE__)
2
+
3
+ module VagrantPlugins
4
+ module ProviderVirtualBox
5
+ module Driver
6
+ # Driver for VirtualBox 6.0.x
7
+ class Version_6_0 < Version_5_0
8
+ def initialize(uuid)
9
+ super
10
+
11
+ @logger = Log4r::Logger.new("vagrant::provider::virtualbox_6_0")
12
+ end
13
+
14
+ def import(ovf)
15
+ ovf = Vagrant::Util::Platform.windows_path(ovf)
16
+
17
+ output = ""
18
+ total = ""
19
+ last = 0
20
+
21
+ # Dry-run the import to get the suggested name and path
22
+ @logger.debug("Doing dry-run import to determine parallel-safe name...")
23
+ output = execute("import", "-n", ovf)
24
+ result = /Suggested VM name "(.+?)"/.match(output)
25
+ if !result
26
+ raise Vagrant::Errors::VirtualBoxNoName, output: output
27
+ end
28
+ suggested_name = result[1].to_s
29
+
30
+ # Append millisecond plus a random to the path in case we're
31
+ # importing the same box elsewhere.
32
+ specified_name = "#{suggested_name}_#{(Time.now.to_f * 1000.0).to_i}_#{rand(100000)}"
33
+ @logger.debug("-- Parallel safe name: #{specified_name}")
34
+
35
+ # Build the specified name param list
36
+ name_params = [
37
+ "--vsys", "0",
38
+ "--vmname", specified_name,
39
+ ]
40
+
41
+ # Target path for disks is no longer a full path. Extract the path for the
42
+ # settings file to determine the base directory which we can then use to
43
+ # build the disk paths
44
+ result = /Suggested VM settings file name "(?<settings_path>.+?)"/.match(output)
45
+ if !result
46
+ @logger.warn("Failed to locate base path for disks. Using current working directory.")
47
+ base_path = "."
48
+ else
49
+ base_path = File.dirname(result[:settings_path])
50
+ end
51
+
52
+ @logger.info("Base path for disk import: #{base_path}")
53
+
54
+ # Extract the disks list and build the disk target params
55
+ disk_params = []
56
+ disks = output.scan(/(\d+): Hard disk image: source image=.+, target path=(.+),/)
57
+ disks.each do |unit_num, path|
58
+ path = File.join(base_path, File.basename(path))
59
+ disk_params << "--vsys"
60
+ disk_params << "0"
61
+ disk_params << "--unit"
62
+ disk_params << unit_num
63
+ disk_params << "--disk"
64
+ if Vagrant::Util::Platform.windows?
65
+ # we use the block form of sub here to ensure that if the specified_name happens to end with a number (which is fairly likely) then
66
+ # we won't end up having the character sequence of a \ followed by a number be interpreted as a back reference. For example, if
67
+ # specified_name were "abc123", then "\\abc123\\".reverse would be "\\321cba\\", and the \3 would be treated as a back reference by the sub
68
+ disk_params << path.reverse.sub("\\#{suggested_name}\\".reverse) { "\\#{specified_name}\\".reverse }.reverse # Replace only last occurrence
69
+ else
70
+ disk_params << path.reverse.sub("/#{suggested_name}/".reverse, "/#{specified_name}/".reverse).reverse # Replace only last occurrence
71
+ end
72
+ end
73
+
74
+ execute("import", ovf , *name_params, *disk_params, retryable: true) do |type, data|
75
+ if type == :stdout
76
+ # Keep track of the stdout so that we can get the VM name
77
+ output << data
78
+ elsif type == :stderr
79
+ # Append the data so we can see the full view
80
+ total << data.gsub("\r", "")
81
+
82
+ # Break up the lines. We can't get the progress until we see an "OK"
83
+ lines = total.split("\n")
84
+ if lines.include?("OK.")
85
+ # The progress of the import will be in the last line. Do a greedy
86
+ # regular expression to find what we're looking for.
87
+ match = /.+(\d{2})%/.match(lines.last)
88
+ if match
89
+ current = match[1].to_i
90
+ if current > last
91
+ last = current
92
+ yield current if block_given?
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ return get_machine_id specified_name
100
+ end
101
+
102
+ end
103
+ end
104
+ end
105
+ end
@@ -58,6 +58,7 @@ module VagrantPlugins
58
58
  autoload :Version_5_0, File.expand_path("../driver/version_5_0", __FILE__)
59
59
  autoload :Version_5_1, File.expand_path("../driver/version_5_1", __FILE__)
60
60
  autoload :Version_5_2, File.expand_path("../driver/version_5_2", __FILE__)
61
+ autoload :Version_6_0, File.expand_path("../driver/version_6_0", __FILE__)
61
62
  end
62
63
 
63
64
  module Model
@@ -124,7 +124,8 @@ module VagrantPlugins
124
124
  name: os_friendly_id(id),
125
125
  hostpath: hostpath.to_s,
126
126
  transient: transient,
127
- SharedFoldersEnableSymlinksCreate: enable_symlink_create
127
+ SharedFoldersEnableSymlinksCreate: enable_symlink_create,
128
+ automount: !!data[:automount]
128
129
  }
129
130
  end
130
131
  end