hashicorp / vagrant

Vagrant is a tool for building and distributing development environments.
https://www.vagrantup.com
Other
26.12k stars 4.43k forks source link

Virtualbox 7: NFS requires a host-only network to be created #13072

Closed maxxer closed 1 year ago

maxxer commented 1 year ago

Debug output

https://gist.github.com/maxxer/ecda192180b3c74786d69f1b53e933a3

Expected behavior

Vagrant mounted NFS share

Actual behavior

==> master: Configuring and enabling network interfaces...
NFS requires a host-only network to be created.
Please add a host-only network to the machine (with either DHCP or a
static IP) for NFS to work.

Reproduction information

This configuration works fine (without virtualbox__intnet) with Virtualbox 6.1, fails on 7.

Adding intnet option allows the VM to boot, which otherwise would fail with

Stderr: VBoxManage: error: Error: vmnet_start_interface returned 1001 (VERR_INVALID_PARAMETER).
VBoxManage: error: Failed to attach the network LUN (VERR_INVALID_PARAMETER)
VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component ConsoleWrap, interface IConsole

I found a relevant discussion in #12959, where it's said this has been solved in 2.3.3, but some later comments show this is still somehow an issue. virtualbox__intnet seems to be the solution, but it breaks NFS Synced Folders.

Vagrant version

Vagrant 2.3.4

Host operating system

macOS 12.6.2

Guest operating system

Ubuntu 18.04

Steps to reproduce

vagrant up

Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.require_version ">= 2.0.1"

require 'getoptlong'

ENV['VAGRANT_DEFAULT_PROVIDER'] = 'virtualbox'

opts = GetoptLong.new(

  # Native Vagrant options
  [ '--force', '-f', GetoptLong::NO_ARGUMENT ],
  [ '--provision', '-p', GetoptLong::NO_ARGUMENT ],
  [ '--no-provision', GetoptLong::NO_ARGUMENT ],
  [ '--provision-with', GetoptLong::NO_ARGUMENT ],
  [ '--provider', GetoptLong::OPTIONAL_ARGUMENT ],
  [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
  [ '--check', GetoptLong::NO_ARGUMENT ],
  [ '--logout', GetoptLong::NO_ARGUMENT ],
  [ '--token', GetoptLong::NO_ARGUMENT ],
  [ '--disable-http', GetoptLong::NO_ARGUMENT ],
  [ '--http', GetoptLong::NO_ARGUMENT ],
  [ '--https', GetoptLong::NO_ARGUMENT ],
  [ '--ssh-no-password', GetoptLong::NO_ARGUMENT ],
  [ '--ssh', GetoptLong::NO_ARGUMENT ],
  [ '--ssh-port', GetoptLong::NO_ARGUMENT ],
  [ '--ssh-once', GetoptLong::NO_ARGUMENT ],
  [ '--host', GetoptLong::NO_ARGUMENT ],
  [ '--entry-point', GetoptLong::NO_ARGUMENT ],
  [ '--plugin-source', GetoptLong::NO_ARGUMENT ],
  [ '--plugin-version', GetoptLong::NO_ARGUMENT ],
  [ '--debug', GetoptLong::NO_ARGUMENT ],
  [ '--prune', GetoptLong::NO_ARGUMENT ],
  [ '--tags', GetoptLong::OPTIONAL_ARGUMENT ]

  )

customTags=['all']

opts.each do |opt, arg|
  case opt
  when '--tags'
    customTags=[arg]
  end
end

require 'yaml'

vagrant_root = File.dirname(__FILE__);

code_root = File.expand_path("../..", Dir.pwd)

_config = YAML.load(File.open(File.join(vagrant_root, "vagrantconfig.yml"), File::RDONLY).read)
CONF = _config

the_user = "vagrant"
Vagrant.configure("2") do |config|
    config.vm.box = "ubuntu/bionic64"
    config.disksize.size = '20GB'
  if Vagrant.has_plugin?("vagrant-cachier")
    config.cache.scope = :box
    config.cache.synced_folder_opts = {
     owner: "_apt",
   }
 end
 config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
 config.ssh.forward_agent = true
 config.ssh.username = the_user
 config.ssh.insert_key = true

 config.vm.synced_folder ".", "/vagrant", disabled: true
 config.vm.synced_folder code_root, "/vagrant", id: "vagrant-root", type: "nfs"

 if RUBY_PLATFORM =~ /darwin/
   if Vagrant.has_plugin?("vagrant-bindfs")

     config.bindfs.default_options = {
       force_user:   the_user,
       force_group:  'www-data',
       perms:        'u=rwX:g=rwX:o=rD'
     }

     config.bindfs.debug = true

     config.bindfs.skip_validations << :group

     config.bindfs.bindfs_version = "1.14.2"
     config.bindfs.install_bindfs_from_source = true

     config.bindfs.bind_folder "/vagrant", "/var/www",
     o: "nonempty" ,
     owner: the_user,
     group: "www-data",
     create_as_user: true
   else
    raise Vagrant::Errors::VagrantError.new, "install vagrant-bindfs (with vagrant plugin install vagrant-bindfs), OR DIE HARD!!"
  end

  if Vagrant.has_plugin?("vagrant-google")
  else
    raise Vagrant::Errors::VagrantError.new, "install vagrant-google (with vagrant plugin install vagrant-google), OR will not be able to interact with production machines"
  end

else
  config.vm.synced_folder code_root, "/var/www", id: "vagrant-root", owner: "vagrant", group: "www-data", mount_options: ["dmode=777,fmode=777"]
end

config.vm.provider "virtualbox" do |vb|
  vb.customize ["modifyvm", :id, "--memory", CONF["ram"]]
  vb.customize ["modifyvm", :id, "--cpus", CONF["cpus"]]
  vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
  vb.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"]
  vb.customize ["modifyvm", :id, "--accelerate3d", "off"]
end

def shared_ansible_config(ansible)
 ansible.playbook               = "/var/www/provisioning/provisioning/playbook.yml"
    ansible.verbose             = 'v' # can be true or "vvv" or false
    ansible.limit               = "all"
    ansible.provisioning_path   = "/var/www/provisioning/provisioning/"
    ansible.inventory_path      = "/var/www/provisioning/local/hosts"
    ansible.vault_password_file = "/tmp/vault_pass"

  end

  if Vagrant.has_plugin?('vagrant-cachier')
    config.cache.scope = :box
  else
    puts "Run `vagrant plugin install vagrant-cachier` to reduce caffeine intake when provisioning"
  end

  if Vagrant.has_plugin?("vagrant-timezone")
    config.timezone.value = "GMT"
  else
    raise Vagrant::Errors::VagrantError.new, "install vagrant-timezone (with vagrant plugin install vagrant-timezone), OR DIE HARD!!"
  end

  if Vagrant.has_plugin?("vagrant-vbguest")
    config.vbguest.auto_update = true
    config.vbguest.no_remote = false
    config.vbguest.installer_arguments = ['--nox11']
  else
    raise Vagrant::Errors::VagrantError.new, "install vagrant-vbguest (with vagrant plugin install vagrant-vbguest), OR DIE HARD!!"
  end

  config.vm.define "master", autostart:true do |machine|
   machine.vm.network "private_network", ip: "33.33.33.51", virtualbox__intnet: true
   machine.vm.network "forwarded_port", guest: 3306, host: 3308
   machine.vm.hostname = "master.domain.local"
   machine.vm.provider :virtualbox do |vb|
    vb.memory = 1024
    vb.cpus = 2
  end

  machine.vm.provision :shell, :path => "bootstrap.sh"
  machine.vm.provision "ansible_local" do |ansible|
    shared_ansible_config ansible
    ansible.limit               = ["master"]
    ansible.tags = customTags
  end

end

end
soapy1 commented 1 year ago

Hey there, thanks for opening up an issue. I can reproduce the problem with a following more concise Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/bionic64"
  config.vm.synced_folder ".", "/vagrant", disabled: true
  config.vm.synced_folder "<path to folder>", "/vagrant", id: "vagrant-root", type: "nfs"
  config.vm.network "private_network", ip: "33.33.33.51",  virtualbox__intnet: true

I can resolve this issue by changing the IP address of the private network to one in the reserved private network space as suggested in the vagrant docs and not using an internal network

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/bionic64"
  config.vm.synced_folder ".", "/vagrant", disabled: true
  config.vm.synced_folder "<path to folder>", "/vagrant", id: "vagrant-root", type: "nfs"
  config.vm.network "private_network", ip: "192.168.5.2"

Using the virtualbox__intnet option fails because this creates an internal network instead of a host only network. There are some virtual box docs about that here https://docs.oracle.com/en/virtualization/virtualbox/7.0/user/networkingdetails.html#network_internal

maxxer commented 1 year ago

Thank you very much for taking care of this issue.

If using a private space IP address is mandatory, it should be a requirement, not a suggestion 🤣 So there's a different behavior when using public and private IP? That's the only solution? Thanks again

soapy1 commented 1 year ago

If using a private space IP address is mandatory, it should be a requirement, not a suggestion 🤣 So there's a different behavior when using public and private IP? That's the only solution?

Here are the related Virtualbox docs: https://docs.oracle.com/en/virtualization/virtualbox/7.0/user/networkingdetails.html#network_hostonly. I think Vagrant is doing the right thing here, that is, it is doing what the Vagrantfile specified. Since there is maybe a situation where it is appropriate to use a public ip here instead of a private ip I don't think this is an issue with Vagrant. So, I'm going to go ahead and close this issue, but feel free to reopen if disagree 👍