guests/arch: Configure networks in one command
This commit updates the procedure for configuring arch networks to occur in a single command. Previously, each network was configured independently. If, for some reason, one of the networks destroyed the SSH connection, the box would be irrecoverable. This commit does not alleviate that behavior, but attempts to mitigate it by running all network-related configuration commands in a single communicator (SSH) session. The new procedure looks like this: 1. Upload a temp file to /tmp/vagrant-network-id... for each interface on the guest. 2. Compile a commands array (of bash) to execute after all network configurations have been uploaded. 3. Concatenate all the commands together in a single communicator session. This was tested against `terrywant/archlinux` using the following Vagrantfile: ```ruby Vagrant.configure(2) do |config| config.vm.box = "terrywang/archlinux" config.vm.hostname = "banana-ramama.example.com" config.vm.network "private_network", type: "dhcp" config.vm.network "private_network", ip: "33.33.33.10" config.vm.provision "file", source: "Vagrantfile", destination: "/tmp/vf" config.vm.provision "shell", inline: "echo hi" end ```
This commit is contained in:
parent
41d61120a5
commit
d77ad5c941
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
require "tempfile"
|
||||
|
||||
require_relative "../../../../lib/vagrant/util/template_renderer"
|
||||
|
@ -10,32 +9,45 @@ module VagrantPlugins
|
|||
include Vagrant::Util
|
||||
|
||||
def self.configure_networks(machine, networks)
|
||||
tempfiles = []
|
||||
comm = machine.communicate
|
||||
|
||||
commands = []
|
||||
interfaces = []
|
||||
|
||||
machine.communicate.sudo("ip -o -0 addr | grep -v LOOPBACK | awk '{print $2}' | sed 's/://'") do |_, result|
|
||||
interfaces = result.split("\n")
|
||||
# The result will be something like:
|
||||
# eth0\nenp0s8\nenp0s9
|
||||
comm.sudo("ip -o -0 addr | grep -v LOOPBACK | awk '{print $2}' | sed 's/://'") do |_, stdout|
|
||||
interfaces = stdout.split("\n")
|
||||
end
|
||||
|
||||
networks.each.with_index do |network, i|
|
||||
network[:device] = interfaces[network[:interface]]
|
||||
|
||||
entry = TemplateRenderer.render("guests/arch/network_#{network[:type]}",
|
||||
options: network)
|
||||
options: network,
|
||||
)
|
||||
|
||||
remote_path = "/tmp/vagrant-network-#{Time.now.to_i}-#{i}"
|
||||
remote_path = "/tmp/vagrant-network-#{network[:device]}-#{Time.now.to_i}-#{i}"
|
||||
|
||||
Tempfile.open("vagrant-arch-configure-networks") do |f|
|
||||
f.binmode
|
||||
f.write(entry)
|
||||
f.fsync
|
||||
f.close
|
||||
machine.communicate.upload(f.path, remote_path)
|
||||
comm.upload(f.path, remote_path)
|
||||
end
|
||||
|
||||
machine.communicate.sudo("mv #{remote_path} /etc/netctl/#{network[:device]}")
|
||||
machine.communicate.sudo("ip link set #{network[:device]} down && netctl restart #{network[:device]} && netctl enable #{network[:device]}")
|
||||
commands << <<-EOH.gsub(/^ {14}/, '')
|
||||
# Configure #{network[:device]}
|
||||
mv '#{remote_path}' '/etc/netctl/#{network[:device]}'
|
||||
ip link set '#{network[:device]}' down
|
||||
netctl restart '#{network[:device]}'
|
||||
netctl enable '#{network[:device]}'
|
||||
EOH
|
||||
end
|
||||
|
||||
# Run all the network modification commands in one communicator call.
|
||||
comm.sudo(commands.join("\n"))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,16 +9,16 @@ describe "VagrantPlugins::GuestArch::Cap::ConfigureNetworks" do
|
|||
end
|
||||
|
||||
let(:machine) { double("machine") }
|
||||
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||
|
||||
before do
|
||||
allow(machine).to receive(:communicate).and_return(communicator)
|
||||
communicator.stub_command("ip -o -0 addr | grep -v LOOPBACK | awk '{print $2}' | sed 's/://'",
|
||||
allow(machine).to receive(:communicate).and_return(comm)
|
||||
comm.stub_command("ip -o -0 addr | grep -v LOOPBACK | awk '{print $2}' | sed 's/://'",
|
||||
stdout: "eth1\neth2")
|
||||
end
|
||||
|
||||
after do
|
||||
communicator.verify_expectations!
|
||||
comm.verify_expectations!
|
||||
end
|
||||
|
||||
describe ".configure_networks" do
|
||||
|
@ -40,9 +40,16 @@ describe "VagrantPlugins::GuestArch::Cap::ConfigureNetworks" do
|
|||
end
|
||||
|
||||
it "creates and starts the networks" do
|
||||
communicator.expect_command("ip link set eth1 down && netctl restart eth1 && netctl enable eth1")
|
||||
communicator.expect_command("ip link set eth2 down && netctl restart eth2 && netctl enable eth2")
|
||||
described_class.configure_networks(machine, [network_1, network_2])
|
||||
expect(comm.received_commands[1]).to match(/mv (.+) '\/etc\/netctl\/eth1'/)
|
||||
expect(comm.received_commands[1]).to match(/ip link set 'eth1' down/)
|
||||
expect(comm.received_commands[1]).to match(/netctl restart 'eth1'/)
|
||||
expect(comm.received_commands[1]).to match(/netctl enable 'eth1'/)
|
||||
|
||||
expect(comm.received_commands[1]).to match(/mv (.+) '\/etc\/netctl\/eth2'/)
|
||||
expect(comm.received_commands[1]).to match(/ip link set 'eth2' down/)
|
||||
expect(comm.received_commands[1]).to match(/netctl restart 'eth2'/)
|
||||
expect(comm.received_commands[1]).to match(/netctl enable 'eth2'/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
require_relative "../../../../base"
|
||||
|
||||
describe "VagrantPlugins::GuestCoreOS::Cap::ChangeHostName" do
|
||||
let(:described_class) do
|
||||
VagrantPlugins::GuestCoreOS::Plugin
|
||||
.components
|
||||
.guest_capabilities[:coreos]
|
||||
.get(:docker_daemon_running)
|
||||
end
|
||||
|
||||
let(:machine) { double("machine") }
|
||||
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||
|
||||
before do
|
||||
allow(machine).to receive(:communicate).and_return(comm)
|
||||
end
|
||||
|
||||
after do
|
||||
comm.verify_expectations!
|
||||
end
|
||||
|
||||
describe ".docker_daemon_running" do
|
||||
it "checks /run/docker/sock" do
|
||||
described_class.docker_daemon_running(machine)
|
||||
expect(comm.received_commands[0]).to eq("test -S /run/docker.sock")
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue