diff --git a/.gitignore b/.gitignore index 1909cb5597f..ae39dc45220 100644 --- a/.gitignore +++ b/.gitignore @@ -80,3 +80,7 @@ lib/vagrant/vagrant_ssl.so # direnv directory .direnv + +bundle +embedded +vendor diff --git a/Gemfile b/Gemfile index 25dcdc40b86..b13a5a5590d 100644 --- a/Gemfile +++ b/Gemfile @@ -4,9 +4,3 @@ source "https://rubygems.org" gemspec - -if File.exist?(File.expand_path("../../vagrant-spec", __FILE__)) - gem 'vagrant-spec', path: "../vagrant-spec" -else - gem 'vagrant-spec', git: "https://github.com/hashicorp/vagrant-spec.git", branch: :main -end diff --git a/bin/vagrant b/bin/vagrant index 7ca30b391e6..d3f4ea61a25 100755 --- a/bin/vagrant +++ b/bin/vagrant @@ -221,11 +221,6 @@ begin end end - if !Vagrant.in_installer? && !Vagrant.very_quiet? - # If we're not in the installer, warn. - env.ui.warn(I18n.t("vagrant.general.not_in_installer") + "\n", prefix: false) - end - # Acceptable experimental flag values include: # # Unset - Disables experimental features diff --git a/debian/.gitignore b/debian/.gitignore new file mode 100644 index 00000000000..8622862d27c --- /dev/null +++ b/debian/.gitignore @@ -0,0 +1,6 @@ +*.substvars +*debhelper* +.debhelper +files +vagrant +tmp diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 00000000000..3d59aaafd59 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +vagrant (100:2.4.1-1) UNRELEASED; urgency=medium + + * https://github.com/hashicorp/vagrant/releases/tag/v2.4.1 + + -- Wong Hoi Sing Edison Sat, 20 Jan 2024 11:04:06 +0800 diff --git a/debian/control b/debian/control new file mode 100644 index 00000000000..e17bc15a351 --- /dev/null +++ b/debian/control @@ -0,0 +1,31 @@ +Source: vagrant +Section: admin +Priority: optional +Standards-Version: 4.5.0 +Maintainer: Wong Hoi Sing Edison +Homepage: https://github.com/hashicorp/vagrant/tags +Vcs-Browser: https://github.com/alvistack/hashicorp-vagrant +Vcs-Git: https://github.com/alvistack/hashicorp-vagrant.git +Build-Depends: + debhelper, + debhelper-compat (= 10), + chrpath, + fdupes, + libffi-dev, + ruby-bundler, + ruby-dev (>= 3.0), + +Package: vagrant +Architecture: amd64 +Description: Build and distribute virtualized development environments + Vagrant is a tool for building and distributing virtualized development + environments. +Depends: + ${misc:Depends}, + ${shlibs:Depends}, + curl, + libarchive-tools, + openssh-client, + rsync, + ruby (>= 3.0), + ruby-bundler, diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 00000000000..12900b4193c --- /dev/null +++ b/debian/copyright @@ -0,0 +1,21 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ + +Files: debian/* +Copyright: 2024 Wong Hoi Sing Edison +License: Apache-2.0 + +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + The complete text of the Apache version 2.0 license + can be found in "/usr/share/common-licenses/Apache-2.0". diff --git a/debian/rules b/debian/rules new file mode 100755 index 00000000000..19a9e6f1fec --- /dev/null +++ b/debian/rules @@ -0,0 +1,46 @@ +#!/usr/bin/make -f + +SHELL := /bin/bash + +override_dh_auto_build: + mkdir -p bin + bundle config set --local without development + bundle config set --local path ./bundle + bundle install --verbose --local --standalone + bundle config set --local deployment true + bundle install --verbose --local --standalone + +override_dh_auto_install: + install -Dpm755 -d debian/tmp/usr/bin + install -Dpm755 -d debian/tmp/usr/share/bash-completion/completions + install -Dpm755 -d debian/tmp/opt + install -Dpm644 contrib/bash/completion.sh debian/tmp/usr/share/bash-completion/completions/vagrant + mkdir -p debian/tmp/opt/vagrant + tar xf ./vendor/cache/vagrant-2.4.1.gem data.tar.gz -O | tar zx -C debian/tmp/opt/vagrant + cp -rfp .bundle bundle Gemfile.lock debian/tmp/opt/vagrant/ + pushd debian/tmp/opt/vagrant && \ + bundle binstubs --all --force --path binstubs && \ + bundle exec vagrant --version && \ + popd + ln -fs /opt/vagrant/binstubs/vagrant debian/tmp/usr/bin/vagrant + fdupes -qnrps debian/tmp + find debian/tmp -type f -name '*.so' -exec chrpath -d {} \; + find debian/tmp -type f -exec sed -i 's?$(CURDIR)/debian/tmp??g' {} \; + find debian/tmp -type f -exec sed -i 's?^#!.*ruby.*?#!/usr/bin/ruby?g' {} \; + +override_dh_strip: + +override_dh_strip_nondeterminism: + +override_dh_shlibdeps: + +override_dh_makeshlibs: + +override_dh_dwz: + +override_dh_auto_test: + +override_dh_auto_clean: + +%: + dh $@ diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 00000000000..163aaf8d82b --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides new file mode 100644 index 00000000000..52661c6cef0 --- /dev/null +++ b/debian/source/lintian-overrides @@ -0,0 +1,3 @@ +vagrant source: file-without-copyright-information +vagrant source: missing-notice-file-for-apache-license +vagrant source: no-debian-changes diff --git a/debian/vagrant.install b/debian/vagrant.install new file mode 100644 index 00000000000..3fda480898c --- /dev/null +++ b/debian/vagrant.install @@ -0,0 +1,3 @@ +opt/vagrant +usr/bin/* +usr/share/bash-completion/completions/* diff --git a/debian/vagrant.lintian-overrides b/debian/vagrant.lintian-overrides new file mode 100644 index 00000000000..1e52f71cec3 --- /dev/null +++ b/debian/vagrant.lintian-overrides @@ -0,0 +1,17 @@ +vagrant: copyright-without-copyright-notice +vagrant: custom-library-search-path +vagrant: dir-or-file-in-opt +vagrant: embedded-library +vagrant: executable-not-elf-or-script +vagrant: hardening-no-pie +vagrant: initial-upload-closes-no-bugs +vagrant: mismatched-override embedded-library +vagrant: no-manual-page +vagrant: package-contains-vcs-control-file +vagrant: ruby-script-but-no-ruby-dep +vagrant: script-not-executable +vagrant: shared-library-lacks-prerequisites +vagrant: statically-linked-binary +vagrant: unstripped-binary-or-object +vagrant: windows-devel-file-in-package +vagrant: zero-byte-file-in-doc-directory diff --git a/plugins/guests/alt/cap/configure_networks.rb b/plugins/guests/alt/cap/configure_networks.rb index ad31ac6ea04..df9561f2338 100644 --- a/plugins/guests/alt/cap/configure_networks.rb +++ b/plugins/guests/alt/cap/configure_networks.rb @@ -3,7 +3,7 @@ require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestALT diff --git a/plugins/guests/arch/cap/configure_networks.rb b/plugins/guests/arch/cap/configure_networks.rb index 52ed72f5c43..634c5aa5692 100644 --- a/plugins/guests/arch/cap/configure_networks.rb +++ b/plugins/guests/arch/cap/configure_networks.rb @@ -5,7 +5,7 @@ require "socket" require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestArch diff --git a/plugins/guests/coreos/cap/configure_networks.rb b/plugins/guests/coreos/cap/configure_networks.rb index 857d746a7b0..b7328588cd8 100644 --- a/plugins/guests/coreos/cap/configure_networks.rb +++ b/plugins/guests/coreos/cap/configure_networks.rb @@ -4,7 +4,7 @@ require "tempfile" require "yaml" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestCoreOS diff --git a/plugins/guests/debian/cap/configure_networks.rb b/plugins/guests/debian/cap/configure_networks.rb index ce18ac13af3..c1028833f08 100644 --- a/plugins/guests/debian/cap/configure_networks.rb +++ b/plugins/guests/debian/cap/configure_networks.rb @@ -3,7 +3,7 @@ require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestDebian diff --git a/plugins/guests/freebsd/cap/configure_networks.rb b/plugins/guests/freebsd/cap/configure_networks.rb index 4c117805a99..53276296195 100644 --- a/plugins/guests/freebsd/cap/configure_networks.rb +++ b/plugins/guests/freebsd/cap/configure_networks.rb @@ -3,7 +3,7 @@ require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestFreeBSD diff --git a/plugins/guests/funtoo/cap/configure_networks.rb b/plugins/guests/funtoo/cap/configure_networks.rb index 2980c8f4a31..631bad5e7e4 100644 --- a/plugins/guests/funtoo/cap/configure_networks.rb +++ b/plugins/guests/funtoo/cap/configure_networks.rb @@ -3,7 +3,7 @@ require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestFuntoo diff --git a/plugins/guests/gentoo/cap/configure_networks.rb b/plugins/guests/gentoo/cap/configure_networks.rb index 691dde90380..1a3afe08eae 100644 --- a/plugins/guests/gentoo/cap/configure_networks.rb +++ b/plugins/guests/gentoo/cap/configure_networks.rb @@ -4,7 +4,7 @@ require "tempfile" require "ipaddr" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestGentoo diff --git a/plugins/guests/netbsd/cap/configure_networks.rb b/plugins/guests/netbsd/cap/configure_networks.rb index 697e4915432..f015664a2ea 100644 --- a/plugins/guests/netbsd/cap/configure_networks.rb +++ b/plugins/guests/netbsd/cap/configure_networks.rb @@ -3,7 +3,7 @@ require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestNetBSD diff --git a/plugins/guests/nixos/cap/change_host_name.rb b/plugins/guests/nixos/cap/change_host_name.rb index 381b373d516..442140b56b8 100644 --- a/plugins/guests/nixos/cap/change_host_name.rb +++ b/plugins/guests/nixos/cap/change_host_name.rb @@ -3,7 +3,7 @@ require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestNixos diff --git a/plugins/guests/nixos/cap/configure_networks.rb b/plugins/guests/nixos/cap/configure_networks.rb index c4380cd322b..60739295396 100644 --- a/plugins/guests/nixos/cap/configure_networks.rb +++ b/plugins/guests/nixos/cap/configure_networks.rb @@ -4,7 +4,7 @@ require "ipaddr" require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestNixos diff --git a/plugins/guests/openbsd/cap/configure_networks.rb b/plugins/guests/openbsd/cap/configure_networks.rb index 3cbd34cde77..5b739e27e4b 100644 --- a/plugins/guests/openbsd/cap/configure_networks.rb +++ b/plugins/guests/openbsd/cap/configure_networks.rb @@ -3,7 +3,7 @@ require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestOpenBSD diff --git a/plugins/guests/redhat/cap/configure_networks.rb b/plugins/guests/redhat/cap/configure_networks.rb index 0f9bb32369d..3d81373281c 100644 --- a/plugins/guests/redhat/cap/configure_networks.rb +++ b/plugins/guests/redhat/cap/configure_networks.rb @@ -3,7 +3,7 @@ require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestRedHat diff --git a/plugins/guests/slackware/cap/configure_networks.rb b/plugins/guests/slackware/cap/configure_networks.rb index c4986e8a29f..b37fe12ad7a 100644 --- a/plugins/guests/slackware/cap/configure_networks.rb +++ b/plugins/guests/slackware/cap/configure_networks.rb @@ -3,7 +3,7 @@ require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestSlackware diff --git a/plugins/guests/suse/cap/configure_networks.rb b/plugins/guests/suse/cap/configure_networks.rb index ac98b57bf47..3081af5fa7b 100644 --- a/plugins/guests/suse/cap/configure_networks.rb +++ b/plugins/guests/suse/cap/configure_networks.rb @@ -3,7 +3,7 @@ require "tempfile" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" module VagrantPlugins module GuestSUSE diff --git a/plugins/providers/docker/config.rb b/plugins/providers/docker/config.rb index dfababb5358..0fdc7b698ea 100644 --- a/plugins/providers/docker/config.rb +++ b/plugins/providers/docker/config.rb @@ -3,7 +3,7 @@ require "pathname" -require_relative "../../../lib/vagrant/util/platform" +require "vagrant/util/platform" module VagrantPlugins module DockerProvider diff --git a/plugins/providers/virtualbox/action/package_setup_folders.rb b/plugins/providers/virtualbox/action/package_setup_folders.rb index 9be34e6a5ed..047f6ff227b 100644 --- a/plugins/providers/virtualbox/action/package_setup_folders.rb +++ b/plugins/providers/virtualbox/action/package_setup_folders.rb @@ -3,7 +3,7 @@ require "fileutils" -require_relative "../../../../lib/vagrant/action/general/package_setup_folders" +require "vagrant/action/general/package" module VagrantPlugins module ProviderVirtualBox diff --git a/plugins/providers/virtualbox/driver/meta.rb b/plugins/providers/virtualbox/driver/meta.rb index 63af500c65a..4b1878bde5e 100644 --- a/plugins/providers/virtualbox/driver/meta.rb +++ b/plugins/providers/virtualbox/driver/meta.rb @@ -69,6 +69,7 @@ def initialize(uuid=nil) "6.0" => Version_6_0, "6.1" => Version_6_1, "7.0" => Version_7_0, + "7.1" => Version_7_1, } if @@version.start_with?("4.2.14") diff --git a/plugins/providers/virtualbox/driver/version_7_1.rb b/plugins/providers/virtualbox/driver/version_7_1.rb new file mode 100644 index 00000000000..f0a4a26efcf --- /dev/null +++ b/plugins/providers/virtualbox/driver/version_7_1.rb @@ -0,0 +1,305 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +require "rexml" +require File.expand_path("../version_7_0", __FILE__) + +module VagrantPlugins + module ProviderVirtualBox + module Driver + # Driver for VirtualBox 7.1.x + class Version_7_1 < Version_7_0 + # VirtualBox version requirement for using host only networks + # instead of host only interfaces + HOSTONLY_NET_REQUIREMENT=Gem::Requirement.new(">= 7") + # Prefix of name used for host only networks + HOSTONLY_NAME_PREFIX="vagrantnet-vbox" + DEFAULT_NETMASK="255.255.255.0" + + def initialize(uuid) + super + + @logger = Log4r::Logger.new("vagrant::provider::virtualbox_7_1") + end + + def read_bridged_interfaces + ifaces = super + return ifaces if !use_host_only_nets? + + # Get a list of all subnets which are in use for hostonly networks + hostonly_ifaces = read_host_only_networks.map do |net| + IPAddr.new(net[:lowerip]).mask(net[:networkmask]) + end + + # Prune any hostonly interfaces in the list + ifaces.delete_if { |i| + addr = begin + IPAddr.new(i[:ip]).mask(i[:netmask]) + rescue IPAddr::Error => err + @logger.warn("skipping bridged interface due to parse error #{err} (#{i}) ") + nil + end + addr.nil? || + hostonly_ifaces.include?(addr) + } + + ifaces + end + + def delete_unused_host_only_networks + return super if !use_host_only_nets? + + # First get the list of existing host only network names + network_names = read_host_only_networks.map { |net| net[:name] } + # Prune the network names to only include ones we manage + network_names.delete_if { |name| !name.start_with?(HOSTONLY_NAME_PREFIX) } + + @logger.debug("managed host only network names: #{network_names}") + + return if network_names.empty? + + # Next get the list of host only networks currently in use + inuse_names = [] + execute("list", "vms", retryable: true).split("\n").each do |line| + match = line.match(/^".+?"\s+\{(?.+?)\}$/) + next if match.nil? + begin + info = execute("showvminfo", match[:vmid].to_s, "--machinereadable", retryable: true) + info.split("\n").each do |vmline| + if vmline.start_with?("hostonly-network") + net_name = vmline.split("=", 2).last.to_s.gsub('"', "") + inuse_names << net_name + end + end + rescue Vagrant::Errors::VBoxManageError => err + raise if !err.extra_data[:stderr].include?("VBOX_E_OBJECT_NOT_FOUND") + end + end + + @logger.debug("currently in use network names: #{inuse_names}") + + # Now remove all the networks not in use + (network_names - inuse_names).each do |name| + execute("hostonlynet", "remove", "--name", name, retryable: true) + end + end + + def enable_adapters(adapters) + return super if !use_host_only_nets? + + hostonly_adapters = adapters.find_all { |adapter| adapter[:hostonly] } + other_adapters = adapters - hostonly_adapters + super(other_adapters) if !other_adapters.empty? + + if !hostonly_adapters.empty? + args = [] + hostonly_adapters.each do |adapter| + args.concat(["--nic#{adapter[:adapter]}", "hostonlynet"]) + args.concat(["--host-only-net#{adapter[:adapter]}", adapter[:hostonly], + "--cableconnected#{adapter[:adapter]}", "on"]) + end + + execute("modifyvm", @uuid, *args, retryable: true) + end + end + + def create_host_only_network(options) + # If we are not on macOS, just setup the hostonly interface + return super if !use_host_only_nets? + + opts = { + netmask: options.fetch(:netmask, DEFAULT_NETMASK), + } + + if options[:type] == :dhcp + opts[:lower] = options[:dhcp_lower] + opts[:upper] = options[:dhcp_upper] + else + addr = IPAddr.new(options[:adapter_ip]) + opts[:upper] = opts[:lower] = addr.mask(opts[:netmask]).to_range.first.to_s + end + + name_idx = read_host_only_networks.map { |hn| + next if !hn[:name].start_with?(HOSTONLY_NAME_PREFIX) + hn[:name].sub(HOSTONLY_NAME_PREFIX, "").to_i + }.compact.max.to_i + 1 + opts[:name] = HOSTONLY_NAME_PREFIX + name_idx.to_s + + execute("hostonlynet", "add", + "--name", opts[:name], + "--netmask", opts[:netmask], + "--lower-ip", opts[:lower], + "--upper-ip", opts[:upper], + retryable: true) + + { + name: opts[:name], + ip: options[:adapter_ip], + netmask: opts[:netmask], + } + end + + # Disabled when host only nets are in use + def reconfig_host_only(options) + return super if !use_host_only_nets? + end + + # Disabled when host only nets are in use since + # the host only nets will provide the dhcp server + def remove_dhcp_server(*_, **_) + super if !use_host_only_nets? + end + + # Disabled when host only nets are in use since + # the host only nets will provide the dhcp server + def create_dhcp_server(*_, **_) + super if !use_host_only_nets? + end + + def read_host_only_interfaces + return super if !use_host_only_nets? + + # When host only nets are in use, read them and + # reformat the information to line up with how + # the interfaces is structured + read_host_only_networks.map do |net| + addr = begin + IPAddr.new(net[:lowerip]) + rescue IPAddr::Error => err + @logger.warn("invalid host only network lower IP encountered: #{err} (#{net})") + next + end + # Address of the interface will be the lower bound of the range or + # the first available address in the subnet + if addr == addr.mask(net[:networkmask]) + addr = addr.succ + end + + net[:netmask] = net[:networkmask] + if addr.ipv4? + net[:ip] = addr.to_s + net[:ipv6] = "" + else + net[:ip] = "" + net[:ipv6] = addr.to_s + net[:ipv6_prefix] = net[:netmask] + end + + net[:status] = net[:state] == "Enabled" ? "Up" : "Down" + + net + end.compact + end + + def read_network_interfaces + return super if !use_host_only_nets? + + {}.tap do |nics| + execute("showvminfo", @uuid, "--machinereadable", retryable: true).each_line do |line| + if m = line.match(/nic(?\d+)="(?.+?)"$/) + nics[m[:adapter].to_i] ||= {} + if m[:type] == "hostonlynetwork" + nics[m[:adapter].to_i][:type] = :hostonly + else + nics[m[:adapter].to_i][:type] = m[:type].to_sym + end + elsif m = line.match(/^bridgeadapter(?\d+)="(?.+?)"$/) + nics[m[:adapter].to_i] ||= {} + nics[m[:adapter].to_i][:bridge] = m[:network] + elsif m = line.match(/^hostonly-network(?\d+)="(?.+?)"$/) + nics[m[:adapter].to_i] ||= {} + nics[m[:adapter].to_i][:hostonly] = m[:network] + end + end + end + end + + # Generate list of host only networks + def read_host_only_networks + networks = [] + current = nil + execute("list", "hostonlynets", retryable: true).split("\n").each do |line| + line.chomp! + next if line.empty? + key, value = line.split(":", 2).map(&:strip) + key = key.downcase + if key == "name" + networks.push(current) if !current.nil? + current = Vagrant::Util::HashWithIndifferentAccess.new + end + current[key] = value + end + networks.push(current) if !current.nil? + + networks + end + + # The initial VirtualBox 7.1 release has an issue with displaying port + # forward information. When a single port forward is defined, the forwarding + # information can be found in the `showvminfo` output. Once more than a + # single port forward is defined, no forwarding information is provided + # in the `showvminfo` output. To work around this we grab the VM configuration + # file from the `showvminfo` output and extract the port forward information + # from there instead. + def read_forwarded_ports(uuid=nil, active_only=false) + # Only use this override for the 7.1.0 release. + return super if get_version.to_s != "7.1.0" + + uuid ||= @uuid + + @logger.debug("read_forward_ports: uuid=#{uuid} active_only=#{active_only}") + + results = [] + + info = execute("showvminfo", uuid, "--machinereadable", retryable: true) + result = info.match(/CfgFile="(?.+?)"/) + if result.nil? + raise Vagrant::Errors::VirtualBoxConfigNotFound, + uuid: uuid + end + + File.open(result[:path], "r") do |f| + doc = REXML::Document.new(f) + networks = REXML::XPath.each(doc.root, "Machine/Hardware/Network/Adapter") + networks.each do |net| + REXML::XPath.each(doc.root, net.xpath + "/NAT/Forwarding") do |fwd| + # Result Array values: + # [NIC Slot, Name, Host Port, Guest Port, Host IP] + result = [ + net.attribute("slot").value.to_i + 1, + fwd.attribute("name")&.value.to_s, + fwd.attribute("hostport")&.value.to_i, + fwd.attribute("guestport")&.value.to_i, + fwd.attribute("hostip")&.value.to_s + ] + @logger.debug(" - #{result.inspect}") + results << result + end + end + end + + results + end + + private + + # Returns if hostonlynets are enabled on the current + # host platform + # + # @return [Boolean] + def use_host_only_nets? + Vagrant::Util::Platform.darwin? && + HOSTONLY_NET_REQUIREMENT.satisfied_by?(get_version) + end + + # VirtualBox version in use + # + # @return [Gem::Version] + def get_version + return @version if @version + @version = Gem::Version.new(Meta.new.version) + end + end + end + end +end diff --git a/plugins/providers/virtualbox/plugin.rb b/plugins/providers/virtualbox/plugin.rb index 8c0ff08fb2c..25b49fd3160 100644 --- a/plugins/providers/virtualbox/plugin.rb +++ b/plugins/providers/virtualbox/plugin.rb @@ -104,6 +104,7 @@ module Driver autoload :Version_6_0, File.expand_path("../driver/version_6_0", __FILE__) autoload :Version_6_1, File.expand_path("../driver/version_6_1", __FILE__) autoload :Version_7_0, File.expand_path("../driver/version_7_0", __FILE__) + autoload :Version_7_1, File.expand_path("../driver/version_7_1", __FILE__) end module Model diff --git a/plugins/provisioners/chef/provisioner/base.rb b/plugins/provisioners/chef/provisioner/base.rb index fad7574b1d4..9dca9b83f56 100644 --- a/plugins/provisioners/chef/provisioner/base.rb +++ b/plugins/provisioners/chef/provisioner/base.rb @@ -4,7 +4,7 @@ require "tempfile" require_relative "../../../../lib/vagrant/util/presence" -require_relative "../../../../lib/vagrant/util/template_renderer" +require "vagrant/util/template_renderer" require_relative "../installer" diff --git a/test/unit/plugins/providers/virtualbox/driver/version_7_1_test.rb b/test/unit/plugins/providers/virtualbox/driver/version_7_1_test.rb new file mode 100644 index 00000000000..d9241b65ef6 --- /dev/null +++ b/test/unit/plugins/providers/virtualbox/driver/version_7_1_test.rb @@ -0,0 +1,856 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: BUSL-1.1 + +require "stringio" +require_relative "../base" + +describe VagrantPlugins::ProviderVirtualBox::Driver::Version_7_1 do + include_context "virtualbox" + + let(:vbox_version) { "7.1.0" } + + subject { VagrantPlugins::ProviderVirtualBox::Driver::Version_7_1.new(uuid) } + + it_behaves_like "a version 5.x virtualbox driver" + it_behaves_like "a version 6.x virtualbox driver" + + describe "#read_forwarded_ports" do + let(:uuid) { "MACHINE-UUID" } + let(:cfg_path) { "MACHINE_CONFIG_PATH" } + let(:vm_info) { +%(name="vagrant-test_default_1665781960041_56631" +Encryption: disabled +groups="/" +ostype="Ubuntu (64-bit)" +UUID="#{uuid}" +CfgFile="#{cfg_path}" +SnapFldr="/VirtualBox VMs/vagrant-test_default_1665781960041_56631/Snapshots" +LogFldr="/VirtualBox VMs/vagrant-test_default_1665781960041_56631/Logs" +memory=1024) + } + let(:config_file) { + StringIO.new(VBOX_VMCONFIG_FILE) + } + + before do + allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta).to receive(:version).and_return(vbox_version) + end + + describe "VirtualBox version 7.1.0" do + let(:vbox_version) { "7.1.0" } + + before do + allow(subject).to receive(:execute).with("showvminfo", uuid, any_args).and_return(vm_info) + allow(File).to receive(:open).with(cfg_path, "r").and_yield(config_file) + end + + it "should return two port forward values" do + expect(subject.read_forwarded_ports.size).to eq(2) + end + + it "should have port forwards on slot one" do + subject.read_forwarded_ports.each do |fwd| + expect(fwd.first).to eq(1) + end + end + + it "should include host ip for ssh forward" do + fwd = subject.read_forwarded_ports.detect { |f| f[1] == "ssh" } + expect(fwd).not_to be_nil + expect(fwd.last).to eq("127.0.0.1") + end + + describe "when config file cannot be determine" do + let(:vm_info) { %(name="vagrant-test_default_1665781960041_56631") } + + it "should raise a custom error" do + expect(File).not_to receive(:open).with(cfg_path, "r") + + expect { subject.read_forwarded_ports }.to raise_error(Vagrant::Errors::VirtualBoxConfigNotFound) + end + end + end + + describe "VirtualBox version greater than 7.1.0" do + let(:vbox_version) { "7.1.1" } + + before do + allow(subject).to receive(:execute).with("showvminfo", uuid, any_args).and_return(vm_info) + end + + it "should not read configuration file" do + expect(File).not_to receive(:open).with(cfg_path, "r") + subject.read_forwarded_ports + end + end + + end + + describe "#use_host_only_nets?" do + context "when platform is darwin" do + before do + allow(Vagrant::Util::Platform).to receive(:darwin?).and_return(true) + end + + context "when virtualbox version is less than 7" do + before do + allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta). + to receive(:version).and_return("6.0.28") + end + + it "should return false" do + expect(subject.send(:use_host_only_nets?)).to be(false) + end + end + + context "when virtualbox version is greater than 7" do + before do + allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta). + to receive(:version).and_return("7.0.2") + end + + it "should return true" do + expect(subject.send(:use_host_only_nets?)).to be(true) + end + end + + context "when virtualbox version is equal to 7" do + before do + allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta). + to receive(:version).and_return("7.0.0") + end + + it "should return true" do + expect(subject.send(:use_host_only_nets?)).to be(true) + end + end + end + + context "when platform is not darwin" do + before do + allow(Vagrant::Util::Platform).to receive(:darwin?).and_return(false) + end + + context "when virtualbox version is less than 7" do + before do + allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta). + to receive(:version).and_return("6.0.28") + end + + it "should return false" do + expect(subject.send(:use_host_only_nets?)).to be(false) + end + end + + context "when virtualbox version is greater than 7" do + before do + allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta). + to receive(:version).and_return("7.0.2") + end + + it "should return false" do + expect(subject.send(:use_host_only_nets?)).to be(false) + end + end + + context "when virtualbox version is equal to 7" do + before do + allow_any_instance_of(VagrantPlugins::ProviderVirtualBox::Driver::Meta). + to receive(:version).and_return("7.0.0") + end + + it "should return false" do + expect(subject.send(:use_host_only_nets?)).to be(false) + end + end + end + end + + describe "#read_bridged_interfaces" do + let(:bridgedifs) { VBOX_BRIDGEDIFS } + + before do + allow(subject).to receive(:execute).and_call_original + expect(subject). + to receive(:execute). + with("list", "bridgedifs"). + and_return(bridgedifs) + end + + context "when hostonlynets are not enabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(false) + end + + it "should return all interfaces in list" do + expect(subject.read_bridged_interfaces.size).to eq(5) + end + + it "should not read host only networks" do + expect(subject).not_to receive(:read_host_only_networks) + subject.read_bridged_interfaces + end + end + + context "when hostonlynets are enabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(true) + end + + it "should return all interfaces in list" do + expect(subject).to receive(:read_host_only_networks).and_return([]) + expect(subject.read_bridged_interfaces.size).to eq(5) + end + + context "when hostonly networks are defined" do + before do + expect(subject). + to receive(:execute). + with("list", "hostonlynets", any_args). + and_return(VBOX_HOSTONLYNETS) + end + + it "should not return all interfaces in list" do + expect(subject.read_bridged_interfaces.size).to_not eq(5) + end + + it "should not include hostonly network devices" do + expect( + subject.read_bridged_interfaces.any? { |int| + int[:name].start_with?("bridge") + } + ).to be(false) + end + end + end + + context "when address is empty" do + let(:bridgedifs) { VBOX_BRIDGEDIFS.sub("0.0.0.0", "") } + + it "should not raise an error" do + expect { subject.read_bridged_interfaces }.to_not raise_error + end + end + end + + describe "#delete_unused_host_only_networks" do + context "when hostonlynets are not enabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(false) + end + + it "should remove host only interfaces" do + expect(subject).to receive(:execute).with("list", "hostonlyifs", any_args).and_return("") + expect(subject).to receive(:execute).with("list", "vms", any_args).and_return("") + subject.delete_unused_host_only_networks + end + + it "should not read host only networks" do + expect(subject).to receive(:execute).with("list", "hostonlyifs", any_args).and_return("") + expect(subject).to receive(:execute).with("list", "vms", any_args).and_return("") + expect(subject).not_to receive(:read_host_only_networks) + subject.delete_unused_host_only_networks + end + end + + context "when hostonlynets are enabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(true) + allow(subject).to receive(:read_host_only_networks).and_return([]) + allow(subject).to receive(:execute).with("list", "vms", any_args).and_return("") + end + + it "should not read host only interfaces" do + expect(subject).not_to receive(:execute).with("list", "hostonlyifs", any_args) + subject.delete_unused_host_only_networks + end + + context "when no host only networks are defined" do + before do + expect(subject).to receive(:read_host_only_networks).and_return([]) + end + + it "should not list vms" do + expect(subject).not_to receive(:execute).with("list", "vms", any_args) + subject.delete_unused_host_only_networks + end + end + + context "when host only networks are defined" do + before do + expect(subject). + to receive(:read_host_only_networks). + and_return([{name: "vagrantnet-vbox-1"}]) + + end + + context "when no vms are using the network" do + before do + expect(subject).to receive(:execute).with("list", "vms", any_args).and_return("") + end + + it "should delete the network" do + expect(subject). + to receive(:execute). + with("hostonlynet", "remove", "--name", "vagrantnet-vbox-1", any_args) + subject.delete_unused_host_only_networks + end + end + + context "when vms are using the network" do + before do + expect(subject). + to receive(:execute). + with("list", "vms", any_args). + and_return(%("VM_NAME" {VM_ID})) + expect(subject). + to receive(:execute). + with("showvminfo", "VM_ID", any_args). + and_return(%(hostonly-network="vagrantnet-vbox-1")) + end + + it "should not delete the network" do + expect(subject).not_to receive(:execute).with("hostonlynet", "remove", any_args) + subject.delete_unused_host_only_networks + end + end + end + end + end + + describe "#enable_adapters" do + let(:adapters) { + [{hostonly: "hostonlynetwork", adapter: 1}, + {bridge: "eth0", adapter: 2}] + } + + before do + allow(subject).to receive(:execute).with("modifyvm", any_args) + end + + context "when hostonlynets are not enabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(false) + end + + it "should only call modifyvm once" do + expect(subject).to receive(:execute).with("modifyvm", any_args).once + subject.enable_adapters(adapters) + end + + it "should configure host only network using hostonlyadapter" do + expect(subject).to receive(:execute) { |*args| + expect(args.first).to eq("modifyvm") + expect(args).to include("--hostonlyadapter1") + true + } + subject.enable_adapters(adapters) + end + end + + context "when hostonlynets are enabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(true) + end + + it "should call modifyvm twice" do + expect(subject).to receive(:execute).with("modifyvm", any_args).twice + subject.enable_adapters(adapters) + end + + it "should configure host only network using hostonlynet" do + expect(subject).to receive(:execute).once + expect(subject).to receive(:execute) { |*args| + expect(args.first).to eq("modifyvm") + expect(args).to include("--host-only-net1") + true + } + subject.enable_adapters(adapters) + end + end + end + + describe "#create_host_only_network" do + let(:options) { + { + adapter_ip: "127.0.0.1", + netmask: "255.255.255.0" + } + } + + context "when hostonlynets are disabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(false) + end + + it "should create using hostonlyif" do + expect(subject). + to receive(:execute). + with("hostonlyif", "create", any_args). + and_return("Interface 'host_only' was successfully created") + expect(subject). + to receive(:execute). + with("hostonlyif", "ipconfig", "host_only", any_args) + subject.create_host_only_network(options) + end + end + + context "when hostonlynets are enabled" do + let(:prefix) { described_class.const_get(:HOSTONLY_NAME_PREFIX) } + before do + allow(subject).to receive(:use_host_only_nets?).and_return(true) + allow(subject).to receive(:read_host_only_networks).and_return([]) + end + + it "should create using hostonlynet" do + expect(subject). + to receive(:execute). + with("hostonlynet", "add", "--name", prefix + "1", + "--netmask", options[:netmask], "--lower-ip", + "127.0.0.0", "--upper-ip", "127.0.0.0", any_args) + subject.create_host_only_network(options) + end + + context "when other host only networks exist" do + before do + expect(subject). + to receive(:read_host_only_networks). + and_return(["custom", prefix + "1", prefix + "20"].map { |n| {name: n} }) + end + + it "should create network with incremented name" do + expect(subject). + to receive(:execute). + with("hostonlynet", "add", "--name", prefix + "21", any_args) + subject.create_host_only_network(options) + end + end + + context "when dhcp information is included" do + let(:options) { + { + type: :dhcp, + dhcp_lower: "127.0.0.1", + dhcp_upper: "127.0.1.200", + netmask: "255.255.240.0" + } + } + + it "should set DHCP range" do + expect(subject). + to receive(:execute). + with("hostonlynet", "add", "--name", anything, "--netmask", options[:netmask], + "--lower-ip", options[:dhcp_lower], "--upper-ip", options[:dhcp_upper], + any_args) + subject.create_host_only_network(options) + end + end + end + end + + describe "#reconfig_host_only" do + let(:interface) { {name: "iname", ipv6: "VALUE"} } + + context "when hostonlynets are disabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(false) + end + + it "should apply ipv6 update" do + expect(subject).to receive(:execute).with("hostonlyif", "ipconfig", interface[:name], + "--ipv6", interface[:ipv6], any_args) + subject.reconfig_host_only(interface) + end + end + + context "when hostonlynets are enabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(true) + end + + it "should do nothing" do + expect(subject).not_to receive(:execute) + subject.reconfig_host_only(interface) + end + end + end + + describe "#remove_dhcp_server" do + let(:dhcp_name) { double(:dhcp_name) } + + context "when hostonlynets are disabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(false) + end + + it "should remove the dhcp server" do + expect(subject).to receive(:execute).with("dhcpserver", "remove", "--netname", + dhcp_name, any_args) + subject.remove_dhcp_server(dhcp_name) + end + end + + context "when hostonlynets are enabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(true) + end + + it "should do nothing" do + expect(subject).not_to receive(:execute) + subject.remove_dhcp_server(dhcp_name) + end + end + end + + describe "#create_dhcp_server" do + let(:network) { double("network") } + let(:options) { + { + dhcp_ip: "127.0.0.1", + netmask: "255.255.255.0", + dhcp_lower: "127.0.0.2", + dhcp_upper: "127.0.0.200" + } + } + + context "when hostonlynets is diabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(false) + end + + it "should create a dhcp server" do + expect(subject).to receive(:execute).with("dhcpserver", "add", "--ifname", network, + "--ip", options[:dhcp_ip], any_args) + subject.create_dhcp_server(network, options) + end + end + + context "when hostonlynets is enabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(true) + end + + it "should do nothing" do + expect(subject).not_to receive(:execute) + subject.create_dhcp_server(network, options) + end + end + end + + describe "#read_host_only_interfaces" do + context "when hostonlynets is diabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(false) + allow(subject).to receive(:execute).and_return("") + end + + it "should list hostonlyifs" do + expect(subject).to receive(:execute).with("list", "hostonlyifs", any_args).and_return("") + subject.read_host_only_interfaces + end + + it "should not call read_host_only_networks" do + expect(subject).not_to receive(:read_host_only_networks) + subject.read_host_only_interfaces + end + end + + context "when hostonlynets is enabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(true) + allow(subject).to receive(:execute).with("list", "hostonlynets", any_args). + and_return(VBOX_HOSTONLYNETS) + end + + it "should call read_host_only_networks" do + expect(subject).to receive(:read_host_only_networks).and_return([]) + subject.read_host_only_interfaces + end + + it "should return defined networks" do + expect(subject.read_host_only_interfaces.size).to eq(2) + end + + it "should add compat information to network entries" do + result = subject.read_host_only_interfaces + expect(result.first[:netmask]).to eq(result.first[:networkmask]) + expect(result.first[:status]).to eq("Up") + end + + it "should assign the address as the first in the subnet" do + result = subject.read_host_only_interfaces + expect(result.first[:ip]).to eq(IPAddr.new(result.first[:lowerip]).succ.to_s) + end + + context "when dhcp range is set" do + before do + allow(subject).to receive(:execute).with("list", "hostonlynets", any_args). + and_return(VBOX_RANGE_HOSTONLYNETS) + end + + it "should assign the address as the first in the dhcp range" do + result = subject.read_host_only_interfaces + expect(result.first[:ip]).to eq(result.first[:lowerip]) + end + end + end + end + + describe "#read_host_only_networks" do + before do + allow(subject).to receive(:execute).with("list", "hostonlynets", any_args). + and_return(VBOX_HOSTONLYNETS) + end + + it "should return defined networks" do + expect(subject.read_host_only_networks.size).to eq(2) + end + + it "should return expected network information" do + result = subject.read_host_only_networks + expect(result.first[:name]).to eq("vagrantnet-vbox1") + expect(result.first[:lowerip]).to eq("192.168.61.0") + expect(result.first[:networkmask]).to eq("255.255.255.0") + expect(result.last[:name]).to eq("vagrantnet-vbox2") + expect(result.last[:lowerip]).to eq("192.168.22.0") + expect(result.last[:networkmask]).to eq("255.255.255.0") + end + end + + describe "#read_network_interfaces" do + before do + allow(subject) + .to receive(:execute). + with("showvminfo", any_args). + and_return(VBOX_GUEST_HOSTONLYVNETS_INFO) + end + + context "when hostonlynets is disabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(false) + end + + it "should return two interfaces" do + valid_interfaces = subject.read_network_interfaces.find_all { |k, v| + v[:type] != :none + } + expect(valid_interfaces.size).to eq(2) + end + + it "should include a nat type" do + expect(subject.read_network_interfaces.detect { |_, v| v[:type] == :nat }).to be + end + + it "should include a hostonlynetwork type with no information" do + expect(subject.read_network_interfaces[2]).to eq({type: :hostonlynetwork}) + end + end + + context "when hostonlynets is enabled" do + before do + allow(subject).to receive(:use_host_only_nets?).and_return(true) + end + + it "should return two interfaces" do + valid_interfaces = subject.read_network_interfaces.find_all { |k, v| + v[:type] != :none + } + expect(valid_interfaces.size).to eq(2) + end + + it "should include a nat type" do + expect(subject.read_network_interfaces.detect { |_, v| v[:type] == :nat }).to be + end + + it "should include a hostonly type" do + expect(subject.read_network_interfaces.detect { |_, v| v[:type] == :hostonly }).to be + end + + it "should not include a hostonlynetwork type" do + expect(subject.read_network_interfaces.detect { |_, v| + v[:type] == :hostonlynetwork + }).to_not be + end + + it "should include the hostonly network name" do + hostonly = subject.read_network_interfaces.values.detect { |v| + v[:type] == :hostonly + } + expect(hostonly).to be + expect(hostonly[:hostonly]).to eq("vagrantnet-vbox1") + end + end + end +end + +VBOX_VMCONFIG_FILE=%( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + + +VBOX_BRIDGEDIFS=%(Name: en1: Wi-Fi (AirPort) +GUID: 00000000-0000-0000-0000-000000000001 +DHCP: Disabled +IPAddress: 10.0.0.49 +NetworkMask: 255.255.255.0 +IPV6Address: +IPV6NetworkMaskPrefixLength: 0 +HardwareAddress: xx:xx:xx:xx:xx:01 +MediumType: Ethernet +Wireless: Yes +Status: Up +VBoxNetworkName: HostInterfaceNetworking-en1 + +Name: en0: Ethernet +GUID: 00000000-0000-0000-0000-000000000002 +DHCP: Disabled +IPAddress: 0.0.0.0 +NetworkMask: 0.0.0.0 +IPV6Address: +IPV6NetworkMaskPrefixLength: 0 +HardwareAddress: xx:xx:xx:xx:xx:02 +MediumType: Ethernet +Wireless: No +Status: Up +VBoxNetworkName: HostInterfaceNetworking-en0 + +Name: bridge100 +GUID: 00000000-0000-0000-0000-000000000003 +DHCP: Disabled +IPAddress: 192.168.61.1 +NetworkMask: 255.255.255.0 +IPV6Address: +IPV6NetworkMaskPrefixLength: 0 +HardwareAddress: xx:xx:xx:xx:xx:03 +MediumType: Ethernet +Wireless: No +Status: Up +VBoxNetworkName: HostInterfaceNetworking-bridge100 + +Name: en2: Thunderbolt 1 +GUID: 00000000-0000-0000-0000-000000000004 +DHCP: Disabled +IPAddress: 0.0.0.0 +NetworkMask: 0.0.0.0 +IPV6Address: +IPV6NetworkMaskPrefixLength: 0 +HardwareAddress: xx:xx:xx:xx:xx:04 +MediumType: Ethernet +Wireless: No +Status: Up +VBoxNetworkName: HostInterfaceNetworking-en2 + +Name: bridge101 +GUID: 00000000-0000-0000-0000-000000000005 +DHCP: Disabled +IPAddress: 192.168.22.1 +NetworkMask: 255.255.255.0 +IPV6Address: +IPV6NetworkMaskPrefixLength: 0 +HardwareAddress: xx:xx:xx:xx:xx:05 +MediumType: Ethernet +Wireless: No +Status: Up +VBoxNetworkName: HostInterfaceNetworking-bridge101) + +VBOX_HOSTONLYNETS=%(Name: vagrantnet-vbox1 +GUID: 10000000-0000-0000-0000-000000000000 + +State: Enabled +NetworkMask: 255.255.255.0 +LowerIP: 192.168.61.0 +UpperIP: 192.168.61.0 +VBoxNetworkName: hostonly-vagrantnet-vbox1 + +Name: vagrantnet-vbox2 +GUID: 20000000-0000-0000-0000-000000000000 + +State: Enabled +NetworkMask: 255.255.255.0 +LowerIP: 192.168.22.0 +UpperIP: 192.168.22.0 +VBoxNetworkName: hostonly-vagrantnet-vbox2) + +VBOX_RANGE_HOSTONLYNETS=%(Name: vagrantnet-vbox1 +GUID: 10000000-0000-0000-0000-000000000000 + +State: Enabled +NetworkMask: 255.255.255.0 +LowerIP: 192.168.61.10 +UpperIP: 192.168.61.100 +VBoxNetworkName: hostonly-vagrantnet-vbox1 + +Name: vagrantnet-vbox2 +GUID: 20000000-0000-0000-0000-000000000000 + +State: Enabled +NetworkMask: 255.255.255.0 +LowerIP: 192.168.22.0 +UpperIP: 192.168.22.0 +VBoxNetworkName: hostonly-vagrantnet-vbox2) + +VBOX_GUEST_HOSTONLYVNETS_INFO=%( +natnet1="nat" +macaddress1="080027BB1475" +cableconnected1="on" +nic1="nat" +nictype1="82540EM" +nicspeed1="0" +mtu="0" +sockSnd="64" +sockRcv="64" +tcpWndSnd="64" +tcpWndRcv="64" +Forwarding(0)="ssh,tcp,127.0.0.1,2222,,22" +hostonly-network2="vagrantnet-vbox1" +macaddress2="080027FBC15B" +cableconnected2="on" +nic2="hostonlynetwork" +nictype2="82540EM" +nicspeed2="0" +nic3="none" +nic4="none" +nic5="none" +nic6="none" +nic7="none" +nic8="none" +) diff --git a/vagrant.gemspec b/vagrant.gemspec index 05c4edebff2..58ca7a91da0 100644 --- a/vagrant.gemspec +++ b/vagrant.gemspec @@ -15,12 +15,13 @@ Gem::Specification.new do |s| s.required_ruby_version = ">= 3.0", "< 3.4" s.required_rubygems_version = ">= 1.3.6" + s.add_dependency "base64", "~> 0.2.0" + s.add_dependency "logger", "~> 1.6.1" + s.add_dependency "ostruct", "~> 0.1.0" s.add_dependency "bcrypt_pbkdf", "~> 1.1" s.add_dependency "childprocess", "~> 4.1.0" s.add_dependency "ed25519", "~> 1.3.0" s.add_dependency "erubi" - s.add_dependency 'googleapis-common-protos-types', '~> 1.3' - s.add_dependency "grpc", "~> 1.56.0" s.add_dependency "hashicorp-checkpoint", "~> 0.1.5" s.add_dependency "i18n", "~> 1.12" s.add_dependency "listen", "~> 3.7" @@ -32,17 +33,13 @@ Gem::Specification.new do |s| s.add_dependency "net-scp", "~> 4.0" s.add_dependency "rb-kqueue", "~> 0.2.0" s.add_dependency "rexml", "~> 3.2" - s.add_dependency "rgl", "~> 0.5.10" + s.add_dependency "rgl", "~> 0.6.6" s.add_dependency "rubyzip", "~> 2.3.2" s.add_dependency "vagrant_cloud", "~> 3.1.1" - s.add_dependency "wdm", "~> 0.1.1" s.add_dependency "winrm", ">= 2.3.6", "< 3.0" s.add_dependency "winrm-elevated", ">= 1.2.3", "< 2.0" s.add_dependency "winrm-fs", ">= 1.3.5", "< 2.0" - # Needed for go generate to use grpc_tools_ruby_protoc - s.add_development_dependency "grpc-tools", "~> 1.41" - # required to include https://github.com/ruby/ipaddr/issues/35 s.add_dependency "ipaddr", ">= 1.2.4" @@ -53,7 +50,7 @@ Gem::Specification.new do |s| s.add_development_dependency "rspec", "~> 3.11" s.add_development_dependency "rspec-its", "~> 1.3.0" s.add_development_dependency "fake_ftp", "~> 0.3.0" - s.add_development_dependency "webrick", "~> 1.7.0" + s.add_development_dependency "webrick", "~> 1.8.0" # The following block of code determines the files that should be included # in the gem. It does this by reading all the files in the directory where diff --git a/vagrant.rpmlintrc b/vagrant.rpmlintrc new file mode 100644 index 00000000000..0008800b1a9 --- /dev/null +++ b/vagrant.rpmlintrc @@ -0,0 +1,13 @@ +addFilter("devel-file-in-non-devel-package") +addFilter("env-script-interpreter") +addFilter("files-duplicate") +addFilter("hidden-file-or-dir") +addFilter("no-soname") +addFilter("non-executable-script") +addFilter("potential-bashisms") +addFilter("script-without-shebang") +addFilter("spurious-executable-perm") +addFilter("strange-permission") +addFilter("unstripped-binary-or-object") +addFilter("version-control-internal-file") +addFilter("zero-length") diff --git a/vagrant.spec b/vagrant.spec new file mode 100644 index 00000000000..331ffd4ca26 --- /dev/null +++ b/vagrant.spec @@ -0,0 +1,83 @@ +# Copyright 2024 Wong Hoi Sing Edison +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +%global debug_package %{nil} + +%global source_date_epoch_from_changelog 0 + +%global __strip /bin/true + +%global __brp_mangle_shebangs /bin/true + +Name: vagrant +Epoch: 100 +Version: 2.4.1 +Release: 1%{?dist} +Summary: Build and distribute virtualized development environments +License: MIT +URL: https://github.com/hashicorp/vagrant/tags +Source0: %{name}_%{version}.orig.tar.gz +Source99: %{name}.rpmlintrc +BuildRequires: chrpath +BuildRequires: fdupes +BuildRequires: glibc-static +BuildRequires: libffi-devel +BuildRequires: ruby-devel >= 3.0 +BuildRequires: rubygem(bundler) +Requires: ruby >= 3.0 +Requires: rubygem(bundler) + +%description +Vagrant is a tool for building and distributing virtualized development +environments. + +%prep +%autosetup -T -c -n %{name}_%{version}-%{release} +tar -zx -f %{S:0} --strip-components=1 -C . + +%build +mkdir -p bin +bundle config set --local without development +bundle config set --local path ./bundle +bundle install --verbose --local --standalone +bundle config set --local deployment true +bundle install --verbose --local --standalone + +%install +install -Dpm755 -d %{buildroot}%{_bindir} +install -Dpm755 -d %{buildroot}%{_prefix}/share/bash-completion/completions +install -Dpm755 -d %{buildroot}/opt +install -Dpm644 contrib/bash/completion.sh %{buildroot}%{_prefix}/share/bash-completion/completions/vagrant +mkdir -p %{buildroot}/opt/vagrant +tar xf ./vendor/cache/vagrant-2.4.1.gem data.tar.gz -O | tar zx -C %{buildroot}/opt/vagrant +cp -rfp .bundle bundle Gemfile.lock %{buildroot}/opt/vagrant/ +pushd %{buildroot}/opt/vagrant && \ + bundle binstubs --all --force --path binstubs && \ + bundle exec vagrant --version && \ +popd +ln -fs /opt/vagrant/binstubs/vagrant %{buildroot}%{_bindir}/vagrant +fdupes -qnrps %{buildroot} +find %{buildroot} -type f -name '*.so' -exec chrpath -d {} \; +find %{buildroot} -type f -exec sed -i 's?%{buildroot}??g' {} \; +find %{buildroot} -type f -exec sed -i 's?^#!.*ruby.*?#!/usr/bin/ruby?g' {} \; + +%check + +%files +%license LICENSE +%{_bindir}/* +%{_prefix}/share/bash-completion/completions/* +/opt/vagrant + +%changelog diff --git a/website/content/docs/providers/virtualbox/index.mdx b/website/content/docs/providers/virtualbox/index.mdx index 96f47151c76..6c685971f0e 100644 --- a/website/content/docs/providers/virtualbox/index.mdx +++ b/website/content/docs/providers/virtualbox/index.mdx @@ -12,7 +12,7 @@ Vagrant comes with support out of the box for [VirtualBox](https://www.virtualbo a free, cross-platform consumer virtualization product. The VirtualBox provider is compatible with VirtualBox versions 4.0.x, 4.1.x, -4.2.x, 4.3.x, 5.0.x, 5.1.x, 5.2.x, 6.0.x, 6.1.x and 7.0.x. Other versions are unsupported and the provider +4.2.x, 4.3.x, 5.0.x, 5.1.x, 5.2.x, 6.0.x, 6.1.x, 7.0.x and 7.1.x. Other versions are unsupported and the provider will display an error message. Please note that beta and pre-release versions of VirtualBox are not supported and may not be well-behaved.