vaguerent/plugins/guests/arch/cap/configure_networks.rb
Seth Vargo d77ad5c941
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
```
2016-06-06 11:58:24 -04:00

56 lines
1.6 KiB
Ruby

require "tempfile"
require_relative "../../../../lib/vagrant/util/template_renderer"
module VagrantPlugins
module GuestArch
module Cap
class ConfigureNetworks
include Vagrant::Util
def self.configure_networks(machine, networks)
comm = machine.communicate
commands = []
interfaces = []
# 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,
)
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
comm.upload(f.path, remote_path)
end
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
end
end