Vagrant 2.1.2
macOS 10.13.5
Ubuntu 14.04 (but it shouldn't matter)
here's the vagrantfile I used but you probably won't need it
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
# Vagrant 1.7.0+ removes the insecure_private_key by default
# and substitutes a dynamically generated SSH key for each box.
# Unfortunately this breaks Ansible provisioning with Vagrant,
# so the key insertion feature should be disabled.
config.ssh.insert_key = false
# The staging hosts are just like production but allow non-tor access
# for the web interfaces and ssh.
config.vm.define 'mon-staging', autostart: false do |staging|
if ENV['SECUREDROP_SSH_OVER_TOR']
config.ssh.host = find_ssh_aths("mon-ssh-aths")
config.ssh.proxy_command = tor_ssh_proxy_command
config.ssh.port = 22
elsif ARGV[0] == "ssh"
config.ssh.host = "10.0.1.3"
config.ssh.port = 22
end
staging.vm.hostname = "mon-staging"
staging.vm.box = "bento/ubuntu-14.04"
staging.vm.network "private_network", ip: "10.0.1.3"
staging.vm.synced_folder './', '/vagrant', disabled: true
end
config.vm.define 'app-staging', autostart: false do |staging|
if ENV['SECUREDROP_SSH_OVER_TOR']
config.ssh.host = find_ssh_aths("app-ssh-aths")
config.ssh.proxy_command = tor_ssh_proxy_command
config.ssh.port = 22
elsif ARGV[0] == "ssh"
config.ssh.host = "10.0.1.2"
config.ssh.port = 22
end
staging.vm.hostname = "app-staging"
staging.vm.box = "bento/ubuntu-14.04"
staging.vm.network "private_network", ip: "10.0.1.2"
staging.vm.synced_folder './', '/vagrant', disabled: true
staging.vm.provider "virtualbox" do |v|
v.memory = 1024
end
staging.vm.provider "libvirt" do |lv, override|
lv.memory = 1024
end
staging.vm.provision "ansible" do |ansible|
ansible.playbook = "install_files/ansible-base/securedrop-staging.yml"
ansible.inventory_path = "install_files/ansible-base/inventory-staging"
ansible.verbose = 'v'
# Taken from the parallel execution tips and tricks
# https://docs.vagrantup.com/v2/provisioning/ansible.html
ansible.limit = 'all,localhost'
ansible.raw_arguments = Shellwords.shellsplit(ENV['ANSIBLE_ARGS']) if ENV['ANSIBLE_ARGS']
end
end
# The prod hosts are just like production but are virtualized.
# All access to SSH and the web interfaces is only over Tor.
config.vm.define 'mon-prod', autostart: false do |prod|
if ENV['SECUREDROP_SSH_OVER_TOR']
config.ssh.host = find_ssh_aths("mon-ssh-aths")
config.ssh.proxy_command = tor_ssh_proxy_command
config.ssh.port = 22
end
prod.vm.hostname = "mon-prod"
prod.vm.box = "bento/ubuntu-14.04"
prod.vm.network "private_network", ip: "10.0.1.5", virtualbox__intnet: internal_network_name
prod.vm.synced_folder './', '/vagrant', disabled: true
end
config.vm.define 'app-prod', autostart: false do |prod|
if ENV['SECUREDROP_SSH_OVER_TOR']
config.ssh.host = find_ssh_aths("app-ssh-aths")
config.ssh.proxy_command = tor_ssh_proxy_command
config.ssh.port = 22
end
prod.vm.hostname = "app-prod"
prod.vm.box = "bento/ubuntu-14.04"
prod.vm.network "private_network", ip: "10.0.1.4", virtualbox__intnet: internal_network_name
prod.vm.synced_folder './', '/vagrant', disabled: true
prod.vm.provider "virtualbox" do |v|
v.memory = 1024
end
prod.vm.provision "ansible" do |ansible|
ansible.playbook = "install_files/ansible-base/securedrop-prod.yml"
ansible.verbose = 'v'
# the production playbook verifies that staging default values are not
# used will need to skip the this role to run in Vagrant
ansible.raw_arguments = Shellwords.shellsplit(ENV['ANSIBLE_ARGS']) if ENV['ANSIBLE_ARGS']
# Taken from the parallel execution tips and tricks
# https://docs.vagrantup.com/v2/provisioning/ansible.html
ansible.limit = 'all,localhost'
ansible.groups = {
'securedrop_application_server' => %w(app-prod),
'securedrop_monitor_server' => %w(mon-prod),
'securedrop' => %w(app-prod mon-prod)
}
end
end
end
# Get .onion URL for connecting to instances over Tor.
# The Ansible playbooks fetch these values back to the
# Admin Workstation (localhost) so they can be manually
# added to the inventory file. Possible values for filename
# are "app-ssh-aths" and "mon-ssh-aths".
def find_ssh_aths(filename)
repo_root = File.expand_path(File.dirname(__FILE__))
aths_file = File.join(repo_root, "install_files", "ansible-base", filename)
if FileTest.file?(aths_file)
File.open(aths_file).each do |line|
# Take second value for URL; format for the ATHS file is:
# /^HidServAuth \w{16}.onion \w{22} # client: admin$/
return line.split()[1]
end
else
puts "Failed to find ATHS file: #{filename}"
puts "Cannot connect via SSH."
exit(1)
end
end
# Build proxy command for connecting to prod instances over Tor.
def tor_ssh_proxy_command
def command?(command)
system("which #{command} > /dev/null 2>&1")
end
if command?("nc")
base_cmd = "nc -x"
else
puts "Failed to build proxy command for SSH over Tor."
puts "Install or 'netcat-openbsd'."
exit(1)
end
return "#{base_cmd} 127.0.0.1:9050 %h %p"
end
# Create a unique name for the VirtualBox internal network,
# based on the directory name of the repo. This is to avoid
# accidental IP collisions when running multiple instances
# of the staging or prod environment concurrently.
def internal_network_name
repo_root = File.expand_path(File.dirname(__FILE__))
return File.basename(repo_root)
end
https://gist.github.com/redshiftzero/bbfcf5c16508ffb332c1a4e043f14685
Returns 0
Returns 2
vagrant up one of themvagrant destroy -fIs that the right exit code? seems like if everything was destroyed cleanly it should exit 0, feel free to close this ticket if exiting non-zero is the expected behavior
Related to #9137
Hi @redshiftzero - Yes, this is expected behavior. I suspect you have more than just 1 vm defined in your Vagrant environment. If you do a general vagrant destroy -f and not all vms are able to be destroyed (like perhaps they are not created, or for any other reason), Vagrant will return 2 and not 0. If you specify a guest or guests with the command like vagrant destroy myguest -f and it is able to successfully destroy all of the target guests, it will return 0.
An example below...I've omitted some irrelevant output with ...'s:
brian@localghost:vagrant-sandbox % be vagrant up bork ±[●●][master]
Bringing machine 'bork' up with 'virtualbox' provider...
.....
.....
.....
brian@localghost:vagrant-sandbox % be vagrant destroy -f ±[●●][master]
==> suse: VM not created. Moving on...
==> dockerwindows: VM not created. Moving on...
==> ubuntu17: VM not created. Moving on...
==> debian: VM not created. Moving on...
==> gentoo: VM not created. Moving on...
==> openbsd: VM not created. Moving on...
==> arch: VM not created. Moving on...
==> macos: VM not created. Moving on...
==> windows: VM not created. Moving on...
==> windoze: VM not created. Moving on...
==> salt: VM not created. Moving on...
==> ansible: VM not created. Moving on...
==> centos: VM not created. Moving on...
==> puppet: VM not created. Moving on...
==> chef: VM not created. Moving on...
==> docker-3: The container hasn't been created yet.
==> docker-2: The container hasn't been created yet.
==> docker-1: The container hasn't been created yet.
==> vbox: VM not created. Moving on...
==> bork: Forcing shutdown of VM...
==> bork: Destroying VM and associated drives...
brian@localghost:vagrant-sandbox % echo $? ±[●●][master]
2
brian@localghost:vagrant-sandbox % be vagrant up bork ±[●●][master]
Bringing machine 'bork' up with 'virtualbox' provider...
.....
......
.....
....
brian@localghost:vagrant-sandbox % be vagrant destroy bork -f ±[●●][master]
==> bork: Forcing shutdown of VM...
==> bork: Destroying VM and associated drives...
brian@localghost:vagrant-sandbox % echo $? ±[●●][master]
0
brian@localghost:vagrant-sandbox %
I'll go ahead and close this ticket. But if you have any other issues or questions feel free to comment or open a new issue, thank you!
Thanks for the clarification, @briancain! That's not the behavior I would have expected; I'd expect a more idempotent command, in that vagrant destroy -f (with no VM explicitly targeted) returns 0 if the end state results in 0 VMs. Still, with the information you provided, at least we're on the same page about what we're observing.
For wrapper scripts to Vagrant, we'll append || true to any vagrant destroy -f commands, and that'll suit our needs.
I'd 2nd that this behaviour is unusual. Is there any chance you'd reconsider changing it?
See e.g. the behaviour of rm, cp.
For people used to these commands -f signifies "I just want it done", and as @conorsch mentions, this makes the command easier to use as part of a script, as it's idempotent.
Forcing scripts to append || true is also suboptimal because it'll mask other failure causes (couldn't find `Vagrantfile at all?, VM provider failed to actually stop a running VM?).
I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
I'd 2nd that this behaviour is unusual. Is there any chance you'd reconsider changing it?
See e.g. the behaviour of
rm,cp.For people used to these commands
-fsignifies "I just want it done", and as @conorsch mentions, this makes the command easier to use as part of a script, as it's idempotent.Forcing scripts to append
|| trueis also suboptimal because it'll mask other failure causes (couldn't find `Vagrantfile at all?, VM provider failed to actually stop a running VM?).