vagrant 2.4.5 → 2.4.6

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/lib/vagrant/action/builtin/box_add.rb +51 -7
  4. data/lib/vagrant/action/builtin/cloud_init_setup.rb +56 -15
  5. data/lib/vagrant/action/builtin/cloud_init_wait.rb +28 -10
  6. data/lib/vagrant/action/builtin/disk.rb +4 -1
  7. data/lib/vagrant/box_metadata.rb +8 -2
  8. data/lib/vagrant/errors.rb +16 -0
  9. data/lib/vagrant/util/file_checksum.rb +59 -50
  10. data/lib/vagrant/util/mime.rb +1 -1
  11. data/plugins/commands/autocomplete/command/root.rb +8 -10
  12. data/plugins/commands/box/command/root.rb +10 -12
  13. data/plugins/commands/cloud/auth/root.rb +10 -12
  14. data/plugins/commands/cloud/box/root.rb +10 -12
  15. data/plugins/commands/cloud/provider/root.rb +10 -12
  16. data/plugins/commands/cloud/root.rb +10 -12
  17. data/plugins/commands/cloud/version/root.rb +10 -12
  18. data/plugins/commands/plugin/command/root.rb +10 -12
  19. data/plugins/hosts/windows/cap/fs_iso.rb +25 -3
  20. data/plugins/kernel_v2/config/vm.rb +3 -0
  21. data/plugins/providers/hyperv/action/import.rb +16 -2
  22. data/plugins/providers/hyperv/action.rb +2 -0
  23. data/plugins/providers/hyperv/scripts/import_vm.ps1 +8 -1
  24. data/plugins/providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 +22 -0
  25. data/plugins/providers/virtualbox/action/network.rb +6 -3
  26. data/plugins/providers/virtualbox/action.rb +2 -11
  27. data/plugins/providers/virtualbox/driver/base.rb +5 -4
  28. data/plugins/providers/virtualbox/driver/meta.rb +1 -0
  29. data/plugins/providers/virtualbox/driver/version_4_0.rb +2 -0
  30. data/plugins/providers/virtualbox/driver/version_4_1.rb +2 -0
  31. data/plugins/providers/virtualbox/driver/version_4_2.rb +2 -0
  32. data/plugins/providers/virtualbox/driver/version_4_3.rb +2 -0
  33. data/plugins/providers/virtualbox/driver/version_5_0.rb +2 -0
  34. data/plugins/providers/virtualbox/driver/version_7_0.rb +23 -20
  35. data/templates/locales/en.yml +43 -0
  36. data/version.txt +1 -1
  37. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 771bdb811142a04fbad06beadeec9a489d9200fc3649f7611600d189a5bae1cd
4
- data.tar.gz: 9539cc14227d6eb0935f7eabd4808a8304b3ae890febad6d5dd15951c3d54663
3
+ metadata.gz: 0626c2a374eefa0d6beab52f299d0d1ecaf4855ae7f53dc1a29bc4bb3372fb97
4
+ data.tar.gz: d37e2e061bfed1c565c87838f9810dbea194c73f64c61dc05be1e3da6c73740c
5
5
  SHA512:
6
- metadata.gz: 961e6ece9c756db4b34d8ac2cad08d13dfacdcb5089506d00274c2b903fe6ded75f22c956ea80a3487ed905e3a2882d1b5b1290b801e8bfdbe7a647aa0df70c1
7
- data.tar.gz: 77ac150c7313b57b7abe9541da461dc8642488333baafe48ca2404b080fd5941068159ef5971819b61cf8b907a477ba02a816376cfeea6a424a0dd169472047e
6
+ metadata.gz: 6c8598105fca1aa04c40df75a460115e94a6baf6731dc5d558e8cc3228e1f2e4894b085f0352f35bf3bcd11b0058007cdf7532044705903850729061fa1a87e7
7
+ data.tar.gz: b470ce0c8eefd4833999ab0f115ed224fac078b7362428e398b244dfeec73beb2a31371dfc4a2c2b57e52c2c6acad0b421690dd1e0f32da41f2bef59e7307845
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## 2.4.6 (May 21, 2025)
2
+
3
+ IMPROVEMENTS:
4
+
5
+ - core: Improve error messages on box add failures [GH-13660]
6
+ - core: Only generate and attach ISO for cloud-init on first boot [GH-13666]
7
+ - host/windows: Add basic oscdimg detection on Windows [GH-13668]
8
+ - provider/hyperv: Enable cloud-init support [GH-13671]
9
+ - provider/virtualbox: Allow link-local IPv6 addresses for hostonly [GH-12653]
10
+
11
+ BUG FIXES:
12
+
13
+ - command: Remove server mode checks [GH-13657]
14
+ - core: Prevent cloud-init from regenerating and attaching ISO [GH-13666]
15
+ - provider/hyperv: Extract machine ID if collection returned [GH-13669]
16
+ - provider/hyperv: Fix import failure due to lack of resources [GH-13670]
17
+ - provider/virtualbox: Fix VirtualBox private network setup [GH-13659]
18
+
1
19
  ## 2.4.5 (April 23, 2025)
2
20
 
3
21
  FEATURES:
@@ -263,20 +263,64 @@ module Vagrant
263
263
  provider: provider,
264
264
  architecture: architecture,
265
265
  )
266
+
266
267
  if !metadata_version
267
- if provider && !metadata.version(">= 0", provider: provider, architecture: architecture)
268
- raise Errors::BoxAddNoMatchingProvider,
268
+ if provider
269
+ # If no version found that supports the provider, then the
270
+ # box has no support for the provider
271
+ if !metadata.version(">= 0", provider: provider)
272
+ raise Errors::BoxAddNoMatchingProvider,
273
+ name: metadata.name,
274
+ requested: Array(provider).join(", "),
275
+ url: display_url
276
+ end
277
+
278
+ # Get all versions that support the provider and architecture
279
+ available_versions = metadata.versions(
280
+ provider: provider,
281
+ architecture: architecture
282
+ )
283
+
284
+ # If no versions are found, then the box does not provide
285
+ # support for the requested architecture using the requested
286
+ # architecture
287
+ if available_versions.empty?
288
+ supported_providers = metadata.versions(architecture: architecture).map do |v|
289
+ metadata.version(v).providers(architecture)
290
+ end.compact.uniq.sort
291
+
292
+ # If no providers are found, then the box does not
293
+ # have any support for the requested architecture
294
+ if supported_providers.empty?
295
+ raise Errors::BoxAddNoArchitectureSupport,
296
+ architecture: display_architecture,
297
+ name: metadata.name,
298
+ url: display_url
299
+ end
300
+
301
+ raise Errors::BoxAddNoMatchingArchitecture,
302
+ provider: Array(provider).join(", "),
303
+ architecture: display_architecture,
304
+ name: metadata.name,
305
+ url: display_url,
306
+ supported_providers: supported_providers
307
+ end
308
+
309
+ raise Errors::BoxAddNoMatchingProviderVersion,
310
+ constraints: version || ">= 0",
311
+ provider: Array(provider).join(", "),
312
+ architecture: display_architecture,
269
313
  name: metadata.name,
270
- requested: [provider,
271
- display_architecture ? "(#{display_architecture})" : nil
272
- ].compact.join(" "),
273
- url: display_url
314
+ url: display_url,
315
+ versions: available_versions.reverse.join(", ")
274
316
  else
317
+ # Report that no version can match the constraints requested
318
+ # but show what versions are supported
275
319
  raise Errors::BoxAddNoMatchingVersion,
276
320
  constraints: version || ">= 0",
277
321
  name: metadata.name,
278
322
  url: display_url,
279
- versions: metadata.versions.join(", ")
323
+ versions: metadata.versions(architecture: architecture).reverse.join(", ")
280
324
  end
281
325
  end
282
326
 
@@ -16,16 +16,38 @@ module Vagrant
16
16
  end
17
17
 
18
18
  def call(env)
19
- machine = env[:machine]
19
+ catch(:complete) do
20
+ machine = env[:machine]
21
+
22
+ # The sentinel file in this check is written by the cloud init
23
+ # wait action and is only written after cloud init has completed.
24
+ @logger.info("Checking cloud-init sentinel file...")
25
+ sentinel_path = machine.data_dir.join("action_cloud_init")
26
+ if sentinel_path.file?
27
+ contents = sentinel_path.read.chomp
28
+ if machine.id.to_s == contents
29
+ if machine.config.vm.cloud_init_first_boot_only
30
+ @logger.info("Sentinel found for cloud-init, skipping")
31
+ throw :complete
32
+ else
33
+ @logger.info("Sentinel found for cloud-init but is configuration enabled")
34
+ end
35
+ else
36
+ @logger.debug("Found stale sentinel file, removing... (#{machine.id} != #{contents})")
37
+ end
38
+ sentinel_path.unlink
39
+ end
20
40
 
21
- user_data_configs = machine.config.vm.cloud_init_configs
22
- .select { |c| c.type == :user_data }
41
+ user_data_configs = machine.config.vm.cloud_init_configs.select { |c|
42
+ c.type == :user_data
43
+ }
23
44
 
24
- if !user_data_configs.empty?
25
- user_data = setup_user_data(machine, env, user_data_configs)
26
- meta_data = { "instance-id" => "i-#{machine.id.split('-').join}" }
45
+ if !user_data_configs.empty?
46
+ user_data = setup_user_data(machine, env, user_data_configs)
47
+ meta_data = { "instance-id" => "i-#{machine.id.split('-').join}" }
27
48
 
28
- write_cfg_iso(machine, env, user_data, meta_data)
49
+ write_cfg_iso(machine, env, user_data, meta_data)
50
+ end
29
51
  end
30
52
 
31
53
  # Continue On
@@ -88,24 +110,43 @@ module Vagrant
88
110
  # @param [Vagrant::Util::Mime::Multipart] user_data
89
111
  # @param [Hash] meta_data
90
112
  def write_cfg_iso(machine, env, user_data, meta_data)
91
- iso_path = nil
113
+ raise Errors::CreateIsoHostCapNotFound if !env[:env].host.capability?(:create_iso)
114
+
115
+ iso_path = catch(:iso_path) do
116
+ # This iso sentinel file is used to store the path of the
117
+ # generated iso file and its checksum. If the file does
118
+ # not exist, or the actual checksum of the file does not
119
+ # match that stored in the sentinel file, it is ignored
120
+ # and the iso is generated. This is used to prevent multiple
121
+ # iso file from being created over time.
122
+ iso_sentinel = env[:machine].data_dir.join("action_cloud_init_iso")
123
+ if iso_sentinel.file?
124
+ checksum, path = iso_sentinel.read.chomp.split(":", 2)
125
+ if File.exist?(path) && Vagrant::Util::FileChecksum.new(path, :sha256).checksum == checksum
126
+ throw :iso_path, Pathname.new(path)
127
+ end
128
+ iso_sentinel.unlink
129
+ end
92
130
 
93
- if env[:env].host.capability?(:create_iso)
94
131
  begin
95
132
  source_dir = Pathname.new(Dir.mktmpdir(TEMP_PREFIX))
96
133
  File.open("#{source_dir}/user-data", 'w') { |file| file.write(user_data.to_s) }
97
-
98
134
  File.open("#{source_dir}/meta-data", 'w') { |file| file.write(meta_data.to_yaml) }
99
135
 
100
- iso_path = env[:env].host.capability(:create_iso,
101
- source_dir, volume_id: "cidata")
102
- attach_disk_config(machine, env, iso_path.to_path)
136
+ env[:env].host.capability(
137
+ :create_iso,
138
+ source_dir,
139
+ volume_id: "cidata"
140
+ ).tap { |path|
141
+ checksum = Vagrant::Util::FileChecksum.new(path.to_path, :sha256).checksum
142
+ iso_sentinel.write("#{checksum}:#{path.to_path}")
143
+ }
103
144
  ensure
104
145
  FileUtils.remove_entry(source_dir)
105
146
  end
106
- else
107
- raise Errors::CreateIsoHostCapNotFound
108
147
  end
148
+
149
+ attach_disk_config(machine, env, iso_path.to_path)
109
150
  end
110
151
 
111
152
  # Adds a new :dvd disk config with the given iso_path to be attached
@@ -14,19 +14,37 @@ module Vagrant
14
14
  end
15
15
 
16
16
  def call(env)
17
- machine = env[:machine]
18
- cloud_init_wait_cmd = "cloud-init status --wait"
19
- if !machine.config.vm.cloud_init_configs.empty?
20
- if machine.communicate.test("command -v cloud-init")
21
- env[:ui].output(I18n.t("vagrant.cloud_init_waiting"))
22
- result = machine.communicate.sudo(cloud_init_wait_cmd, error_check: false)
23
- if result != 0
24
- raise Vagrant::Errors::CloudInitCommandFailed, cmd: cloud_init_wait_cmd, guest_name: machine.name
17
+ catch(:complete) do
18
+ machine = env[:machine]
19
+ sentinel_path = machine.data_dir.join("action_cloud_init")
20
+
21
+ @logger.info("Checking cloud-init sentinel file...")
22
+ if sentinel_path.file?
23
+ contents = sentinel_path.read.chomp
24
+ if machine.id.to_s == contents
25
+ @logger.info("Sentinel found for cloud-init, skipping")
26
+ throw :complete
25
27
  end
26
- else
27
- raise Vagrant::Errors::CloudInitNotFound, guest_name: machine.name
28
+ @logger.debug("Found stale sentinel file, removing... (#{machine.id} != #{contents})")
29
+ sentinel_path.unlink
28
30
  end
31
+
32
+ cloud_init_wait_cmd = "cloud-init status --wait"
33
+ if !machine.config.vm.cloud_init_configs.empty?
34
+ if machine.communicate.test("command -v cloud-init")
35
+ env[:ui].output(I18n.t("vagrant.cloud_init_waiting"))
36
+ result = machine.communicate.sudo(cloud_init_wait_cmd, error_check: false)
37
+ if result != 0
38
+ raise Vagrant::Errors::CloudInitCommandFailed, cmd: cloud_init_wait_cmd, guest_name: machine.name
39
+ end
40
+ else
41
+ raise Vagrant::Errors::CloudInitNotFound, guest_name: machine.name
42
+ end
43
+ end
44
+ # Write sentinel path
45
+ sentinel_path.write(machine.id.to_s)
29
46
  end
47
+
30
48
  @app.call(env)
31
49
  end
32
50
  end
@@ -27,7 +27,10 @@ module Vagrant
27
27
  end
28
28
  end
29
29
 
30
- write_disk_metadata(machine, configured_disks) unless configured_disks.empty?
30
+ # Always write the disk metadata even if the configured
31
+ # disks is empty. This ensure that old entries are not
32
+ # orphaned in the metadata file.
33
+ write_disk_metadata(machine, configured_disks)
31
34
 
32
35
  # Continue On
33
36
  @app.call(env)
@@ -49,6 +49,9 @@ module Vagrant
49
49
  #
50
50
  # @param [String] version The version to return, this can also
51
51
  # be a constraint.
52
+ # @option [Symbol, Array<Symbol>] :provider Provider filter
53
+ # @option [Symbol] :architecture Architecture filter
54
+ #
52
55
  # @return [Version] The matching version or nil if a matching
53
56
  # version was not found.
54
57
  def version(version, **opts)
@@ -90,10 +93,13 @@ module Vagrant
90
93
  # latest version. Optionally filter versions by a matching
91
94
  # provider.
92
95
  #
96
+ # @option [Symbol, Array<Symbol>] :provider Provider filter
97
+ # @option [Symbol] :architecture Architecture filter
98
+ #
93
99
  # @return[Array<String>]
94
100
  def versions(**opts)
95
101
  architecture = opts[:architecture]
96
- provider = opts[:provider].to_sym if opts[:provider]
102
+ provider = Array(opts[:provider]).map(&:to_sym) if opts[:provider]
97
103
 
98
104
  # Return full version list if no filters provided
99
105
  if provider.nil? && architecture.nil?
@@ -109,7 +115,7 @@ module Vagrant
109
115
  end
110
116
 
111
117
  @version_map.select { |_, version|
112
- version.provider(provider, architecture)
118
+ provider.any? { |pv| version.provider(pv, architecture) }
113
119
  }.keys.sort.map(&:to_s)
114
120
  end
115
121
 
@@ -139,6 +139,18 @@ module Vagrant
139
139
  error_key(:box_add_no_matching_provider)
140
140
  end
141
141
 
142
+ class BoxAddNoArchitectureSupport < VagrantError
143
+ error_key(:box_add_no_architecture_support)
144
+ end
145
+
146
+ class BoxAddNoMatchingArchitecture < VagrantError
147
+ error_key(:box_add_no_matching_architecture)
148
+ end
149
+
150
+ class BoxAddNoMatchingProviderVersion < VagrantError
151
+ error_key(:box_add_no_matching_provider_version)
152
+ end
153
+
142
154
  class BoxAddNoMatchingVersion < VagrantError
143
155
  error_key(:box_add_no_matching_version)
144
156
  end
@@ -607,6 +619,10 @@ module Vagrant
607
619
  error_key(:no_env)
608
620
  end
609
621
 
622
+ class OscdimgCommandMissingError < VagrantError
623
+ error_key(:oscdimg_command_missing)
624
+ end
625
+
610
626
  class PackageIncludeMissing < VagrantError
611
627
  error_key(:include_file_missing, "vagrant.actions.general.package")
612
628
  end
@@ -13,65 +13,74 @@ class DigestClass
13
13
  def hexdigest; end
14
14
  end
15
15
 
16
- class FileChecksum
17
- BUFFER_SIZE = 1024 * 8
16
+ module Vagrant
17
+ module Util
18
+ class FileChecksum
19
+ BUFFER_SIZE = 1024 * 8
18
20
 
19
- # Supported file checksum
20
- CHECKSUM_MAP = {
21
- :md5 => Digest::MD5,
22
- :sha1 => Digest::SHA1,
23
- :sha256 => Digest::SHA256,
24
- :sha384 => Digest::SHA384,
25
- :sha512 => Digest::SHA512
26
- }.freeze
21
+ # Supported file checksum
22
+ CHECKSUM_MAP = {
23
+ :md5 => Digest::MD5,
24
+ :sha1 => Digest::SHA1,
25
+ :sha256 => Digest::SHA256,
26
+ :sha384 => Digest::SHA384,
27
+ :sha512 => Digest::SHA512
28
+ }.freeze
27
29
 
28
- # Initializes an object to calculate the checksum of a file. The given
29
- # ``digest_klass`` should implement the ``DigestClass`` interface. Note
30
- # that the built-in Ruby digest classes duck type this properly:
31
- # Digest::MD5, Digest::SHA1, etc.
32
- def initialize(path, digest_klass)
33
- if digest_klass.is_a?(Class)
34
- @digest_klass = digest_klass
35
- else
36
- @digest_klass = load_digest(digest_klass)
37
- end
30
+ # Initializes an object to calculate the checksum of a file. The given
31
+ # ``digest_klass`` should implement the ``DigestClass`` interface. Note
32
+ # that the built-in Ruby digest classes duck type this properly:
33
+ # Digest::MD5, Digest::SHA1, etc.
34
+ def initialize(path, digest_klass)
35
+ if digest_klass.is_a?(Class)
36
+ @digest_klass = digest_klass
37
+ else
38
+ @digest_klass = load_digest(digest_klass)
39
+ end
38
40
 
39
- @path = path
40
- end
41
+ @path = path
42
+ end
41
43
 
42
- # This calculates the checksum of the file and returns it as a
43
- # string.
44
- #
45
- # @return [String]
46
- def checksum
47
- digest = @digest_klass.new
48
- buf = ''
44
+ # This calculates the checksum of the file and returns it as a
45
+ # string.
46
+ #
47
+ # @return [String]
48
+ def checksum
49
+ digest = @digest_klass.new
50
+ buf = ''
49
51
 
50
- File.open(@path, "rb") do |f|
51
- while !f.eof
52
- begin
53
- f.readpartial(BUFFER_SIZE, buf)
54
- digest.update(buf)
55
- rescue EOFError
56
- # Although we check for EOF earlier, this seems to happen
57
- # sometimes anyways [GH-2716].
58
- break
52
+ File.open(@path, "rb") do |f|
53
+ while !f.eof
54
+ begin
55
+ f.readpartial(BUFFER_SIZE, buf)
56
+ digest.update(buf)
57
+ rescue EOFError
58
+ # Although we check for EOF earlier, this seems to happen
59
+ # sometimes anyways [GH-2716].
60
+ break
61
+ end
62
+ end
59
63
  end
60
- end
61
- end
62
64
 
63
- digest.hexdigest
64
- end
65
+ digest.hexdigest
66
+ end
65
67
 
66
- private
68
+ private
67
69
 
68
- def load_digest(type)
69
- digest = CHECKSUM_MAP[type.to_s.downcase.to_sym]
70
- if digest.nil?
71
- raise Vagrant::Errors::BoxChecksumInvalidType,
72
- type: type.to_s,
73
- types: CHECKSUM_MAP.keys.join(', ')
70
+ def load_digest(type)
71
+ digest = CHECKSUM_MAP[type.to_s.downcase.to_sym]
72
+ if digest.nil?
73
+ raise Vagrant::Errors::BoxChecksumInvalidType,
74
+ type: type.to_s,
75
+ types: CHECKSUM_MAP.keys.join(', ')
76
+ end
77
+ digest
78
+ end
74
79
  end
75
- digest
76
80
  end
77
81
  end
82
+
83
+ # NOTE: This class was not originally namespaced
84
+ # with the Util module so this is left for backwards
85
+ # compatibility.
86
+ FileChecksum = Vagrant::Util::FileChecksum
@@ -70,7 +70,7 @@ module Vagrant
70
70
  # @param [String] type of the entity content
71
71
  def initialize(content, content_type)
72
72
  if !MIME::Types.include?(content_type)
73
- MIME::Types.add(MIME::Type.new(content_type))
73
+ MIME::Types.add(MIME::Type.new("content-type" => content_type))
74
74
  end
75
75
  @content = content
76
76
  @content_type = MIME::Types[content_type].first
@@ -43,18 +43,16 @@ module VagrantPlugins
43
43
  def help
44
44
  opts = OptionParser.new do |opts|
45
45
  opts.banner = "Usage: vagrant autocomplete <subcommand>"
46
- if !Vagrant.server_mode?
47
- opts.separator ""
48
- opts.separator "Available subcommands:"
46
+ opts.separator ""
47
+ opts.separator "Available subcommands:"
49
48
 
50
- # Add the available subcommands as separators in order to print them
51
- # out as well.
52
- keys = []
53
- keys = @subcommands.keys.map(&:to_s)
49
+ # Add the available subcommands as separators in order to print them
50
+ # out as well.
51
+ keys = []
52
+ keys = @subcommands.keys.map(&:to_s)
54
53
 
55
- keys.sort.each do |key|
56
- opts.separator " #{key}"
57
- end
54
+ keys.sort.each do |key|
55
+ opts.separator " #{key}"
58
56
  end
59
57
 
60
58
  opts.separator ""
@@ -73,18 +73,16 @@ module VagrantPlugins
73
73
  def help
74
74
  opts = OptionParser.new do |opts|
75
75
  opts.banner = "Usage: vagrant box <subcommand> [<args>]"
76
- if !Vagrant.server_mode?
77
- opts.separator ""
78
- opts.separator "Available subcommands:"
79
-
80
- # Add the available subcommands as separators in order to print them
81
- # out as well.
82
- keys = []
83
- @subcommands.each { |key, value| keys << key.to_s }
84
-
85
- keys.sort.each do |key|
86
- opts.separator " #{key}"
87
- end
76
+ opts.separator ""
77
+ opts.separator "Available subcommands:"
78
+
79
+ # Add the available subcommands as separators in order to print them
80
+ # out as well.
81
+ keys = []
82
+ @subcommands.each { |key, value| keys << key.to_s }
83
+
84
+ keys.sort.each do |key|
85
+ opts.separator " #{key}"
88
86
  end
89
87
  opts.separator ""
90
88
  opts.separator "For help on any individual subcommand run `vagrant box <subcommand> -h`"
@@ -51,18 +51,16 @@ module VagrantPlugins
51
51
  opts.banner = "Usage: vagrant cloud auth <subcommand> [<args>]"
52
52
  opts.separator ""
53
53
  opts.separator "Authorization with Vagrant Cloud"
54
- if !Vagrant.server_mode?
55
- opts.separator ""
56
- opts.separator "Available subcommands:"
57
-
58
- # Add the available subcommands as separators in order to print them
59
- # out as well.
60
- keys = []
61
- @subcommands.each { |key, value| keys << key.to_s }
62
-
63
- keys.sort.each do |key|
64
- opts.separator " #{key}"
65
- end
54
+ opts.separator ""
55
+ opts.separator "Available subcommands:"
56
+
57
+ # Add the available subcommands as separators in order to print them
58
+ # out as well.
59
+ keys = []
60
+ @subcommands.each { |key, value| keys << key.to_s }
61
+
62
+ keys.sort.each do |key|
63
+ opts.separator " #{key}"
66
64
  end
67
65
  opts.separator ""
68
66
  opts.separator "For help on any individual subcommand run `vagrant cloud auth <subcommand> -h`"
@@ -55,18 +55,16 @@ module VagrantPlugins
55
55
  opts.banner = "Usage: vagrant cloud box <subcommand> [<args>]"
56
56
  opts.separator ""
57
57
  opts.separator "Commands to manage boxes on Vagrant Cloud"
58
- if !Vagrant.server_mode?
59
- opts.separator ""
60
- opts.separator "Available subcommands:"
61
-
62
- # Add the available subcommands as separators in order to print them
63
- # out as well.
64
- keys = []
65
- @subcommands.each { |key, value| keys << key.to_s }
66
-
67
- keys.sort.each do |key|
68
- opts.separator " #{key}"
69
- end
58
+ opts.separator ""
59
+ opts.separator "Available subcommands:"
60
+
61
+ # Add the available subcommands as separators in order to print them
62
+ # out as well.
63
+ keys = []
64
+ @subcommands.each { |key, value| keys << key.to_s }
65
+
66
+ keys.sort.each do |key|
67
+ opts.separator " #{key}"
70
68
  end
71
69
  opts.separator ""
72
70
  opts.separator "For help on any individual subcommand run `vagrant cloud box <subcommand> -h`"
@@ -55,18 +55,16 @@ module VagrantPlugins
55
55
  opts.banner = "Usage: vagrant cloud provider <subcommand> [<args>]"
56
56
  opts.separator ""
57
57
  opts.separator "For various provider actions with Vagrant Cloud"
58
- if !Vagrant.server_mode?
59
- opts.separator ""
60
- opts.separator "Available subcommands:"
61
-
62
- # Add the available subcommands as separators in order to print them
63
- # out as well.
64
- keys = []
65
- @subcommands.each { |key, value| keys << key.to_s }
66
-
67
- keys.sort.each do |key|
68
- opts.separator " #{key}"
69
- end
58
+ opts.separator ""
59
+ opts.separator "Available subcommands:"
60
+
61
+ # Add the available subcommands as separators in order to print them
62
+ # out as well.
63
+ keys = []
64
+ @subcommands.each { |key, value| keys << key.to_s }
65
+
66
+ keys.sort.each do |key|
67
+ opts.separator " #{key}"
70
68
  end
71
69
  opts.separator ""
72
70
  opts.separator "For help on any individual subcommand run `vagrant cloud provider <subcommand> -h`"
@@ -83,18 +83,16 @@ module VagrantPlugins
83
83
  opts.separator ""
84
84
  opts.separator "The cloud command can be used for taking actions against"
85
85
  opts.separator "Vagrant Cloud like searching or uploading a Vagrant Box"
86
- if !Vagrant.server_mode?
87
- opts.separator ""
88
- opts.separator "Available subcommands:"
89
-
90
- # Add the available subcommands as separators in order to print them
91
- # out as well.
92
- keys = []
93
- @subcommands.each { |key, value| keys << key.to_s }
94
-
95
- keys.sort.each do |key|
96
- opts.separator " #{key.ljust(15)} #{@subcommand_helptext[key.to_sym]}"
97
- end
86
+ opts.separator ""
87
+ opts.separator "Available subcommands:"
88
+
89
+ # Add the available subcommands as separators in order to print them
90
+ # out as well.
91
+ keys = []
92
+ @subcommands.each { |key, value| keys << key.to_s }
93
+
94
+ keys.sort.each do |key|
95
+ opts.separator " #{key.ljust(15)} #{@subcommand_helptext[key.to_sym]}"
98
96
  end
99
97
  opts.separator ""
100
98
  opts.separator "For help on any individual subcommand run `vagrant cloud <subcommand> -h`"
@@ -59,18 +59,16 @@ module VagrantPlugins
59
59
  opts.banner = "Usage: vagrant cloud version <subcommand> [<args>]"
60
60
  opts.separator ""
61
61
  opts.separator "For taking various actions against a Vagrant box's version attribute on Vagrant Cloud"
62
- if !Vagrant.server_mode?
63
- opts.separator ""
64
- opts.separator "Available subcommands:"
65
-
66
- # Add the available subcommands as separators in order to print them
67
- # out as well.
68
- keys = []
69
- @subcommands.each { |key, value| keys << key.to_s }
70
-
71
- keys.sort.each do |key|
72
- opts.separator " #{key}"
73
- end
62
+ opts.separator ""
63
+ opts.separator "Available subcommands:"
64
+
65
+ # Add the available subcommands as separators in order to print them
66
+ # out as well.
67
+ keys = []
68
+ @subcommands.each { |key, value| keys << key.to_s }
69
+
70
+ keys.sort.each do |key|
71
+ opts.separator " #{key}"
74
72
  end
75
73
  opts.separator ""
76
74
  opts.separator "For help on any individual subcommand run `vagrant cloud version <subcommand> -h`"
@@ -73,18 +73,16 @@ module VagrantPlugins
73
73
  def help
74
74
  opts = OptionParser.new do |o|
75
75
  o.banner = "Usage: vagrant plugin <command> [<args>]"
76
- if !Vagrant.server_mode?
77
- o.separator ""
78
- o.separator "Available subcommands:"
79
-
80
- # Add the available subcommands as separators in order to print them
81
- # out as well.
82
- keys = []
83
- @subcommands.each { |key, value| keys << key.to_s }
84
-
85
- keys.sort.each do |key|
86
- o.separator " #{key}"
87
- end
76
+ o.separator ""
77
+ o.separator "Available subcommands:"
78
+
79
+ # Add the available subcommands as separators in order to print them
80
+ # out as well.
81
+ keys = []
82
+ @subcommands.each { |key, value| keys << key.to_s }
83
+
84
+ keys.sort.each do |key|
85
+ o.separator " #{key}"
88
86
  end
89
87
  o.separator ""
90
88
  o.separator "For help on any individual command run `vagrant plugin COMMAND -h`"
@@ -12,14 +12,22 @@ module VagrantPlugins
12
12
 
13
13
  @@logger = Log4r::Logger.new("vagrant::host::windows::fs_iso")
14
14
 
15
- BUILD_ISO_CMD = "oscdimg".freeze
15
+ BUILD_ISO_CMD = "oscdimg.exe".freeze
16
+ DEPLOYMENT_KIT_PATHS = [
17
+ "C:/Program Files (x86)/Windows Kits/10/Assessment and Deployment Kit/Deployment Tools".freeze,
18
+ ].freeze
16
19
 
17
20
  # Check that the host has the ability to generate ISOs
18
21
  #
19
22
  # @param [Vagrant::Environment] env
20
23
  # @return [Boolean]
21
24
  def self.isofs_available(env)
22
- !!Vagrant::Util::Which.which(BUILD_ISO_CMD)
25
+ begin
26
+ oscdimg_path
27
+ true
28
+ rescue Vagrant::Errors::OscdimgCommandMissingError
29
+ false
30
+ end
23
31
  end
24
32
 
25
33
  # Generate an ISO file of the given source directory
@@ -36,7 +44,7 @@ module VagrantPlugins
36
44
  source_directory = Pathname.new(source_directory)
37
45
  file_destination = self.ensure_output_iso(extra_opts[:file_destination])
38
46
 
39
- iso_command = [BUILD_ISO_CMD, "-j1", "-o", "-m"]
47
+ iso_command = [oscdimg_path, "-j1", "-o", "-m"]
40
48
  iso_command << "-l#{extra_opts[:volume_id]}" if extra_opts[:volume_id]
41
49
  iso_command << source_directory.to_s
42
50
  iso_command << file_destination.to_s
@@ -45,6 +53,20 @@ module VagrantPlugins
45
53
  @@logger.info("ISO available at #{file_destination}")
46
54
  file_destination
47
55
  end
56
+
57
+ # @return [String] oscdimg executable
58
+ def self.oscdimg_path
59
+ return BUILD_ISO_CMD if Vagrant::Util::Which.which(BUILD_ISO_CMD)
60
+ @@logger.debug("#{BUILD_ISO_CMD} not found on PATH")
61
+ DEPLOYMENT_KIT_PATHS.each do |base|
62
+ path = File.join(base, Vagrant::Util::Platform.architecture,
63
+ "Oscdimg", BUILD_ISO_CMD)
64
+ @@logger.debug("#{BUILD_ISO_CMD} check at #{path}")
65
+ return path if File.executable?(path)
66
+ end
67
+
68
+ raise Vagrant::Errors::OscdimgCommandMissingError
69
+ end
48
70
  end
49
71
  end
50
72
  end
@@ -47,6 +47,7 @@ module VagrantPlugins
47
47
  attr_accessor :box_download_insecure
48
48
  attr_accessor :box_download_location_trusted
49
49
  attr_accessor :box_download_options
50
+ attr_accessor :cloud_init_first_boot_only
50
51
  attr_accessor :communicator
51
52
  attr_accessor :graceful_halt_timeout
52
53
  attr_accessor :guest
@@ -87,6 +88,7 @@ module VagrantPlugins
87
88
  @box_version = UNSET_VALUE
88
89
  @allow_hosts_modification = UNSET_VALUE
89
90
  @clone = UNSET_VALUE
91
+ @cloud_init_first_boot_only = UNSET_VALUE
90
92
  @communicator = UNSET_VALUE
91
93
  @graceful_halt_timeout = UNSET_VALUE
92
94
  @guest = UNSET_VALUE
@@ -536,6 +538,7 @@ module VagrantPlugins
536
538
  @box_extra_download_options = Vagrant::Util::MapCommandOptions.map_to_command_options(@box_download_options)
537
539
  @allow_hosts_modification = true if @allow_hosts_modification == UNSET_VALUE
538
540
  @clone = nil if @clone == UNSET_VALUE
541
+ @cloud_init_first_boot_only = @cloud_init_first_boot_only == UNSET_VALUE ? true : !!@cloud_init_first_boot_only
539
542
  @communicator = nil if @communicator == UNSET_VALUE
540
543
  @graceful_halt_timeout = 60 if @graceful_halt_timeout == UNSET_VALUE
541
544
  @guest = nil if @guest == UNSET_VALUE
@@ -70,14 +70,28 @@ module VagrantPlugins
70
70
  "LinkedClone" => !!env[:machine].provider_config.linked_clone,
71
71
  "SourcePath" => Vagrant::Util::Platform.wsl_to_windows_path(image_path).gsub("/", "\\"),
72
72
  "VMName" => env[:machine].provider_config.vmname,
73
+ "Memory" => env[:machine].provider_config.memory,
74
+ "MaxMemory" => env[:machine].provider_config.maxmemory,
75
+ "Processors" => env[:machine].provider_config.cpus,
73
76
  }
74
77
 
75
-
76
78
  env[:ui].detail("Creating and registering the VM...")
77
79
  server = env[:machine].provider.driver.import(options)
78
80
 
81
+ @logger.debug("import result value: #{server.inspect}")
82
+
83
+ sid = case server["id"]
84
+ when String
85
+ server["id"]
86
+ when Array
87
+ server["id"].first
88
+ else
89
+ raise TypeError,
90
+ "Expected String or Array value, received: #{server["id"].class}"
91
+ end
92
+
79
93
  env[:ui].detail("Successfully imported VM")
80
- env[:machine].id = server["id"]
94
+ env[:machine].id = sid
81
95
  @app.call(env)
82
96
  end
83
97
  end
@@ -152,12 +152,14 @@ module VagrantPlugins
152
152
  b3.use NetSetMac
153
153
  end
154
154
 
155
+ b3.use CloudInitSetup
155
156
  b3.use CleanupDisks
156
157
  b3.use Disk
157
158
  b3.use SyncedFolderCleanup
158
159
  b3.use StartInstance
159
160
  b3.use WaitForIPAddress
160
161
  b3.use WaitForCommunicator, [:running]
162
+ b3.use CloudInitWait
161
163
  b3.use SyncedFolders
162
164
  b3.use SetHostname
163
165
  end
@@ -15,6 +15,12 @@ param(
15
15
  [parameter (Mandatory=$false)]
16
16
  [switch] $LinkedClone,
17
17
  [parameter (Mandatory=$false)]
18
+ [int] $Memory = $null,
19
+ [parameter (Mandatory=$false)]
20
+ [int] $MaxMemory = $null,
21
+ [parameter (Mandatory=$false)]
22
+ [int] $Processors = $null,
23
+ [parameter (Mandatory=$false)]
18
24
  [string] $VMName=$null
19
25
  )
20
26
 
@@ -28,7 +34,8 @@ try {
28
34
  }
29
35
 
30
36
  $VM = New-VagrantVM -VMConfigFile $VMConfigFile -DestinationPath $DestinationPath `
31
- -DataPath $DataPath -SourcePath $SourcePath -LinkedClone $linked -VMName $VMName
37
+ -DataPath $DataPath -SourcePath $SourcePath -LinkedClone $linked -Memory $Memory `
38
+ -MaxMemory $MaxMemory -CPUCount $Processors -VMName $VMName
32
39
 
33
40
  $Result = @{
34
41
  id = $VM.Id.Guid;
@@ -33,6 +33,12 @@ function New-VagrantVM {
33
33
  [string] $SourcePath,
34
34
  [parameter (Mandatory=$false)]
35
35
  [bool] $LinkedClone = $false,
36
+ [parameter (Mandatory=$false)]
37
+ [int] $Memory = $null,
38
+ [parameter (Mandatory=$false)]
39
+ [int] $MaxMemory = $null,
40
+ [parameter (Mandatory=$false)]
41
+ [int] $CPUCount = $null,
36
42
  [parameter(Mandatory=$false)]
37
43
  [string] $VMName
38
44
  )
@@ -93,6 +99,12 @@ function New-VagrantVMVMCX {
93
99
  [string] $SourcePath,
94
100
  [parameter (Mandatory=$false)]
95
101
  [bool] $LinkedClone = $false,
102
+ [parameter (Mandatory=$false)]
103
+ [int] $Memory = $null,
104
+ [parameter (Mandatory=$false)]
105
+ [int] $MaxMemory = $null,
106
+ [parameter (Mandatory=$false)]
107
+ [int] $CPUCount = $null,
96
108
  [parameter(Mandatory=$false)]
97
109
  [string] $VMName
98
110
  )
@@ -127,6 +139,16 @@ function New-VagrantVMVMCX {
127
139
  # Disconnect adapters from switches
128
140
  Hyper-V\Get-VMNetworkAdapter -VM $VM | Hyper-V\Disconnect-VMNetworkAdapter
129
141
 
142
+ # If we have a memory value provided, set it here
143
+ if($Memory -ne $null) {
144
+ Set-VagrantVMMemory -VM $VM -Memory $Memory -MaxMemory $MaxMemory
145
+ }
146
+
147
+ # If we have a CPU count provided, set it here
148
+ if($CPUCount -ne $null) {
149
+ Set-VagrantVMCPUS -VM $VM -CPUCount $CPUCount
150
+ }
151
+
130
152
  # Verify new VM
131
153
  $Report = Hyper-V\Compare-VM -CompatibilityReport $VMConfig
132
154
  if($Report.Incompatibilities.Length -gt 0){
@@ -27,7 +27,10 @@ module VagrantPlugins
27
27
  # Version of VirtualBox on darwin platform that ignores restrictions
28
28
  DARWIN_IGNORE_HOSTONLY_VALIDATE_VERSION = Gem::Version.new("7.0.0")
29
29
  # Default valid range for hostonly networks
30
- HOSTONLY_DEFAULT_RANGE = [IPAddr.new("192.168.56.0/21").freeze].freeze
30
+ HOSTONLY_DEFAULT_RANGE = [
31
+ IPAddr.new("192.168.56.0/21").freeze,
32
+ IPAddr.new("fe80::/10").freeze
33
+ ].freeze
31
34
 
32
35
  include Vagrant::Util::NetworkIP
33
36
  include Vagrant::Util::ScopedHashOverride
@@ -359,9 +362,9 @@ module VagrantPlugins
359
362
  # Find the hostonly interface name if display name was
360
363
  # provided
361
364
  if options[:name]
362
- hostif = @env[:machine].provider.driver.read_host_only_networks.detect { |interface|
365
+ hostif = @env[:machine].provider.driver.read_host_only_interfaces.detect { |interface|
363
366
  interface[:name] == options[:name] ||
364
- interface[:vboxnetworkname] == options[:name]
367
+ interface[:display_name] == options[:name]
365
368
  }
366
369
  options[:name] = hostif[:name] if hostif
367
370
  end
@@ -82,22 +82,14 @@ module VagrantPlugins
82
82
  b.use ForwardPorts
83
83
  b.use SetHostname
84
84
  b.use SaneDefaults
85
- b.use Call, IsEnvSet, :cloud_init do |env, b2|
86
- if env[:result]
87
- b2.use CloudInitSetup
88
- end
89
- end
85
+ b.use CloudInitSetup
90
86
  b.use CleanupDisks
91
87
  b.use Disk
92
88
  b.use Customize, "pre-boot"
93
89
  b.use Boot
94
90
  b.use Customize, "post-boot"
95
91
  b.use WaitForCommunicator, [:starting, :running, :paused]
96
- b.use Call, IsEnvSet, :cloud_init do |env, b2|
97
- if env[:result]
98
- b2.use CloudInitWait
99
- end
100
- end
92
+ b.use CloudInitWait
101
93
  b.use Customize, "post-comm"
102
94
  b.use CheckGuestAdditions
103
95
  end
@@ -424,7 +416,6 @@ module VagrantPlugins
424
416
  end
425
417
  end
426
418
 
427
- b.use EnvSet, cloud_init: true
428
419
  b.use action_start
429
420
  end
430
421
  end
@@ -256,10 +256,11 @@ module VagrantPlugins
256
256
  # Each interface is represented as a Hash with the following details:
257
257
  #
258
258
  # {
259
- # :name => String, # interface name, e.g. "vboxnet0"
260
- # :ip => String, # IP address of the interface, e.g. "172.28.128.1"
261
- # :netmask => String, # netmask associated with the interface, e.g. "255.255.255.0"
262
- # :status => String, # status of the interface, e.g. "Up", "Down"
259
+ # :name => String, # interface name, e.g. "vboxnet0"
260
+ # :ip => String, # IP address of the interface, e.g. "172.28.128.1"
261
+ # :netmask => String, # netmask associated with the interface, e.g. "255.255.255.0"
262
+ # :status => String, # status of the interface, e.g. "Up", "Down"
263
+ # :display_name => String, # user friendly display name if available
263
264
  # }
264
265
  #
265
266
  # @return [Array<Hash>] See comment above for details
@@ -134,6 +134,7 @@ module VagrantPlugins
134
134
  :read_guest_ip,
135
135
  :read_guest_property,
136
136
  :read_host_only_interfaces,
137
+ :read_host_only_networks,
137
138
  :read_mac_address,
138
139
  :read_mac_addresses,
139
140
  :read_machine_folder,
@@ -345,6 +345,8 @@ module VagrantPlugins
345
345
  info[:ipv6_prefix] = $1.to_s.strip
346
346
  elsif status = line[/^Status:\s+(.+?)$/, 1]
347
347
  info[:status] = status
348
+ elsif line =~ /^VBoxNetworkName:\s+(.+?)$/
349
+ info[:display_name] = $1.to_s
348
350
  end
349
351
  end
350
352
 
@@ -447,6 +447,8 @@ module VagrantPlugins
447
447
  info[:ipv6_prefix] = $1.to_s.strip
448
448
  elsif status = line[/^Status:\s+(.+?)$/, 1]
449
449
  info[:status] = status
450
+ elsif line =~ /^VBoxNetworkName:\s+(.+?)$/
451
+ info[:display_name] = $1.to_s
450
452
  end
451
453
  end
452
454
 
@@ -381,6 +381,8 @@ module VagrantPlugins
381
381
  info[:ipv6_prefix] = $1.to_s.strip
382
382
  elsif line =~ /^Status:\s+(.+?)$/
383
383
  info[:status] = $1.to_s
384
+ elsif line =~ /^VBoxNetworkName:\s+(.+?)$/
385
+ info[:display_name] = $1.to_s
384
386
  end
385
387
  end
386
388
 
@@ -492,6 +492,8 @@ module VagrantPlugins
492
492
  info[:ipv6_prefix] = $1.to_s.strip
493
493
  elsif line =~ /^Status:\s+(.+?)$/
494
494
  info[:status] = $1.to_s
495
+ elsif line =~ /^VBoxNetworkName:\s+(.+?)$/
496
+ info[:display_name] = $1.to_s
495
497
  end
496
498
  end
497
499
 
@@ -635,6 +635,8 @@ module VagrantPlugins
635
635
  info[:ipv6_prefix] = $1.to_s.strip
636
636
  elsif line =~ /^Status:\s+(.+?)$/
637
637
  info[:status] = $1.to_s
638
+ elsif line =~ /^VBoxNetworkName:\s+(.+?)$/
639
+ info[:display_name] = $1.to_s
638
640
  end
639
641
  end
640
642
 
@@ -215,26 +215,6 @@ module VagrantPlugins
215
215
  end
216
216
  end
217
217
 
218
- # Generate list of host only networks
219
- def read_host_only_networks
220
- networks = []
221
- current = nil
222
- execute("list", "hostonlynets", retryable: true).split("\n").each do |line|
223
- line.chomp!
224
- next if line.empty?
225
- key, value = line.split(":", 2).map(&:strip)
226
- key = key.downcase
227
- if key == "name"
228
- networks.push(current) if !current.nil?
229
- current = Vagrant::Util::HashWithIndifferentAccess.new
230
- end
231
- current[key] = value
232
- end
233
- networks.push(current) if !current.nil?
234
-
235
- networks
236
- end
237
-
238
218
  # The initial VirtualBox 7.0 release has an issue with displaying port
239
219
  # forward information. When a single port forward is defined, the forwarding
240
220
  # information can be found in the `showvminfo` output. Once more than a
@@ -282,6 +262,29 @@ module VagrantPlugins
282
262
  results
283
263
  end
284
264
 
265
+ protected
266
+
267
+ # Generate list of host only networks
268
+ # NOTE: This is darwin specific
269
+ def read_host_only_networks
270
+ networks = []
271
+ current = nil
272
+ execute("list", "hostonlynets", retryable: true).split("\n").each do |line|
273
+ line.chomp!
274
+ next if line.empty?
275
+ key, value = line.split(":", 2).map(&:strip)
276
+ key = key.downcase
277
+ if key == "name"
278
+ networks.push(current) if !current.nil?
279
+ current = Vagrant::Util::HashWithIndifferentAccess.new
280
+ end
281
+ current[key] = value
282
+ end
283
+ networks.push(current) if !current.nil?
284
+
285
+ networks
286
+ end
287
+
285
288
  private
286
289
 
287
290
  # Returns if hostonlynets are enabled on the current
@@ -510,6 +510,41 @@ en:
510
510
  Name: %{name}
511
511
  Address: %{url}
512
512
  Requested provider: %{requested}
513
+ box_add_no_architecture_support: |-
514
+ The box you're attempting to add doesn't support the requested
515
+ architecture. Please find an alternate box that support the
516
+ requested architecture.
517
+
518
+ Box: %{name}
519
+ Address: %{url}
520
+ Architecture: %{architecture}
521
+ box_add_no_matching_architecture: |-
522
+ The box you're attempting to add doesn't support the requested
523
+ architecture with the current provider. The following providers
524
+ support the requested architecture for this box:
525
+
526
+ %{supported_providers}
527
+
528
+ If the above providers cannot be used, please find and alternate
529
+ box that supports the requested architecture.
530
+
531
+ Box: %{name}
532
+ Address: %{url}
533
+ Architecture: %{architecture}
534
+ Provider: %{provider}
535
+ box_add_no_matching_provider_version: |-
536
+ The box you're attempting to add has no available version that
537
+ matches the constraints you requested with support for the
538
+ required provider and architecture. Versions of the box that
539
+ support the required provider and architecture are listed
540
+ below.
541
+
542
+ Box: %{name}
543
+ Address: %{url}
544
+ Constraints: %{constraints}
545
+ Architecture: %{architecture}
546
+ Provider: %{provider}
547
+ Supported versions: %{versions}
513
548
  box_add_no_matching_version: |-
514
549
  The box you're attempting to add has no available version that
515
550
  matches the constraints you requested. Please double-check your
@@ -1215,6 +1250,14 @@ en:
1215
1250
  get an ID of a target machine from `vagrant global-status` to run
1216
1251
  this command on. A final option is to change to a directory with a
1217
1252
  Vagrantfile and to try again.
1253
+ oscdimg_command_missing: |-
1254
+ Vagrant failed to locate the oscdimg.exe executable which is required
1255
+ for creating ISO files. Please ensure the oscdimg.exe executable is
1256
+ available on the configured PATH. If the oscdimg.exe executable is
1257
+ not found on the local system, it can be installed with the Windows
1258
+ Assessment and Deployment Kit:
1259
+
1260
+ https://go.microsoft.com/fwlink/?linkid=2196127
1218
1261
  plugin_gem_not_found: |-
1219
1262
  The plugin '%{name}' could not be installed because it could not
1220
1263
  be found. Please double check the name and try again.
data/version.txt CHANGED
@@ -1 +1 @@
1
- 2.4.5
1
+ 2.4.6
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.5
4
+ version: 2.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mitchell Hashimoto
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-04-23 00:00:00.000000000 Z
12
+ date: 2025-05-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: base64