Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions plugins/guests/devuan/cap/change_host_name.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
require "log4r"
require 'vagrant/util/guest_hosts'
require 'vagrant/util/guest_inspection'
require_relative "../../linux/cap/network_interfaces"

module VagrantPlugins
module GuestDevuan
module Cap
class ChangeHostName

extend Vagrant::Util::GuestInspection::Linux
extend Vagrant::Util::GuestHosts::Linux

def self.change_host_name(machine, name)
@logger = Log4r::Logger.new("vagrant::guest::devuan::changehostname")
comm = machine.communicate

if !comm.test("hostname -f | grep '^#{name}$'", sudo: false)
network_with_hostname = machine.config.vm.networks.map {|_, c| c if c[:hostname] }.compact[0]
if network_with_hostname
replace_host(comm, name, network_with_hostname[:ip])
else
add_hostname_to_loopback_interface(comm, name)
end

basename = name.split(".", 2)[0]
comm.sudo <<-EOH.gsub(/^ {14}/, '')
# Set the hostname
echo '#{basename}' > /etc/hostname

# Update mailname
echo '#{name}' > /etc/mailname

EOH

if hostnamectl?(comm)
comm.sudo("hostnamectl set-hostname '#{basename}'")
else
comm.sudo <<-EOH.gsub(/^ {14}/, '')
hostname -F /etc/hostname
# Restart hostname services
if test -f /etc/init.d/hostname; then
/etc/init.d/hostname start || true
fi

if test -f /etc/init.d/hostname.sh; then
/etc/init.d/hostname.sh start || true
fi
EOH
end

restart_command = nil
if systemd?(comm)
if systemd_networkd?(comm)
@logger.debug("Attempting to restart networking with systemd-networkd")
restart_command = "systemctl restart systemd-networkd.service"
elsif systemd_controlled?(comm, "NetworkManager.service")
@logger.debug("Attempting to restart networking with NetworkManager")
restart_command = "systemctl restart NetworkManager.service"
end
end

if restart_command
comm.sudo(restart_command)
else
restart_each_interface(machine, @logger)
end
end
end

protected

# Due to how most Devuan systems and older Ubuntu systems handle restarting
# networking, we cannot simply run the networking init script or use the ifup/down
# tools to restart all interfaces to renew the machines DHCP lease when setting
# its hostname. This method is a workaround for those older systems that
# cannoy reliably restart networking. It restarts each individual interface
# on its own instead.
#
# @param [Vagrant::Machine] machine
# @param [Log4r::Logger] logger
def self.restart_each_interface(machine, logger)
comm = machine.communicate
interfaces = VagrantPlugins::GuestLinux::Cap::NetworkInterfaces.network_interfaces(machine)
nettools = true
if systemd?(comm)
logger.debug("Attempting to restart networking with systemctl")
nettools = false
else
logger.debug("Attempting to restart networking with ifup/down nettools")
end

interfaces.each do |iface|
logger.debug("Restarting interface #{iface} on guest #{machine.name}")
if nettools
# Ubuntu 16.04+ returns an error when downing an interface that
# does not exist. The `|| true` preserves the behavior that older
# Ubuntu versions exhibit and Vagrant expects (GH-7155)
restart_command = "ifdown #{iface} || true;ifup #{iface} || true"
else
restart_command = "systemctl stop ifup@#{iface}.service;systemctl start ifup@#{iface}.service"
end
comm.sudo(restart_command)
end
end
end
end
end
end
208 changes: 208 additions & 0 deletions plugins/guests/devuan/cap/configure_networks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
require "tempfile"

require_relative "../../../../lib/vagrant/util/template_renderer"

module VagrantPlugins
module GuestDevuan
module Cap
class ConfigureNetworks
include Vagrant::Util
extend Vagrant::Util::GuestInspection::Linux
extend Vagrant::Util::Retryable

NETPLAN_DEFAULT_VERSION = 2
NETPLAN_DIRECTORY = "/etc/netplan".freeze
NETWORKD_DIRECTORY = "/etc/systemd/network".freeze


def self.configure_networks(machine, networks)
#puts "ASDF configuring networks"
comm = machine.communicate
interfaces = machine.guest.capability(:network_interfaces)

if systemd?(comm)
if netplan?(comm)
configure_netplan(machine, interfaces, comm, networks)
elsif systemd_networkd?(comm)
configure_networkd(machine, interfaces, comm, networks)
else
configure_nettools(machine, interfaces, comm, networks)
end
else
configure_nettools(machine, interfaces, comm, networks)
end
end

# Configure networking using netplan
def self.configure_netplan(machine, interfaces, comm, networks)
ethernets = {}.tap do |e_nets|
networks.each do |network|
e_config = {}.tap do |entry|
if network[:type].to_s == "dhcp"
entry["dhcp4"] = true
else
mask = network[:netmask]
if mask && IPAddr.new(network[:ip]).ipv4?
begin
mask = IPAddr.new(mask).to_i.to_s(2).count("1")
rescue IPAddr::Error
# ignore and use given value
end
end
entry["addresses"] = [[network[:ip], mask].compact.join("/")]
end
if network[:gateway]
entry["gateway4"] = network[:gateway]
end
end
e_nets[interfaces[network[:interface]]] = e_config
end
end

# By default, netplan expects the renderer to be systemd-networkd,
# but if any device is managed by NetworkManager, then we use that renderer
# ref: https://netplan.io/reference
if systemd_networkd?(comm)
renderer = "networkd"
ethernets.keys.each do |k|
if nm_controlled?(comm, k)
render = "NetworkManager"
if !nmcli?(comm)
raise Vagrant::Errors::NetworkManagerNotInstalled, device: k
end
break
end
end
elsif nmcli?(comm)
renderer = "NetworkManager"
else
raise Vagrant::Errors::NetplanNoAvailableRenderers
end

np_config = {"network" => {"version" => NETPLAN_DEFAULT_VERSION,
"renderer" => renderer, "ethernets" => ethernets}}

remote_path = upload_tmp_file(comm, np_config.to_yaml)
dest_path = "#{NETPLAN_DIRECTORY}/50-vagrant.yaml"
comm.sudo(["mv -f '#{remote_path}' '#{dest_path}'",
"chown root:root '#{dest_path}'",
"chmod 0644 '#{dest_path}'",
"netplan apply"].join("\n"))
end

# Configure guest networking using networkd
def self.configure_networkd(machine, interfaces, comm, networks)
root_device = interfaces.first
networks.each do |network|
dev_name = interfaces[network[:interface]]
net_conf = []
net_conf << "[Match]"
net_conf << "Name=#{dev_name}"
net_conf << "[Network]"
if network[:type].to_s == "dhcp"
net_conf << "DHCP=yes"
else
mask = network[:netmask]
if mask && IPAddr.new(network[:ip]).ipv4?
begin
mask = IPAddr.new(mask).to_i.to_s(2).count("1")
rescue IPAddr::Error
# ignore and use given value
end
end
address = [network[:ip], mask].compact.join("/")
net_conf << "DHCP=no"
net_conf << "Address=#{address}"
net_conf << "Gateway=#{network[:gateway]}" if network[:gateway]
end

remote_path = upload_tmp_file(comm, net_conf.join("\n"))
dest_path = "#{NETWORKD_DIRECTORY}/50-vagrant-#{dev_name}.network"
comm.sudo(["mkdir -p #{NETWORKD_DIRECTORY}",
"mv -f '#{remote_path}' '#{dest_path}'",
"chown root:root '#{dest_path}'",
"chmod 0644 '#{dest_path}'"].join("\n"))
end

comm.sudo(["systemctl restart systemd-networkd.service"].join("\n"))
end

# Configure guest networking using net-tools
def self.configure_nettools(machine, interfaces, comm, networks)
commands = []
entries = []
root_device = interfaces.first
networks.each do |network|
network[:device] = interfaces[network[:interface]]

entry = TemplateRenderer.render("guests/devuan/network_#{network[:type]}",
options: network.merge(:root_device => root_device),
)
entries << entry
end

content = entries.join("\n")
remote_path = "/tmp/vagrant-network-entry"
upload_tmp_file(comm, content, remote_path)

#puts "ASDF"
#puts content
#puts "ASDF"

networks.each do |network|
# Ubuntu 16.04+ returns an error when downing an interface that
# does not exist. The `|| true` preserves the behavior that older
# Ubuntu versions exhibit and Vagrant expects (GH-7155)
commands << "/sbin/ifdown '#{network[:device]}' || true"
commands << "/sbin/ip addr flush dev '#{network[:device]}'"
end

# Reconfigure /etc/network/interfaces.
commands << <<-EOH.gsub(/^ {12}/, "")
# Remove any previous network modifications from the interfaces file
sed -e '/^#VAGRANT-BEGIN/,$ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces.pre
sed -ne '/^#VAGRANT-END/,$ p' /etc/network/interfaces | tac | sed -e '/^#VAGRANT-END/,$ d' | tac > /tmp/vagrant-network-interfaces.post
cat \\
/tmp/vagrant-network-interfaces.pre \\
/tmp/vagrant-network-entry \\
/tmp/vagrant-network-interfaces.post \\
> /etc/network/interfaces
rm -f /tmp/vagrant-network-interfaces.pre
rm -f /tmp/vagrant-network-entry
rm -f /tmp/vagrant-network-interfaces.post
EOH

comm.sudo(commands.join("\n"))
network_up_commands = []

# Bring back up each network interface, reconfigured.
networks.each do |network|
network_up_commands << "/sbin/ifup '#{network[:device]}'"
end
retryable(on: Vagrant::Errors::VagrantError, sleep: 2, tries: 2) do
comm.sudo(network_up_commands.join("\n"))
end
end

# Simple helper to upload content to guest temporary file
#
# @param [Vagrant::Plugin::Communicator] comm
# @param [String] content
# @return [String] remote path
def self.upload_tmp_file(comm, content, remote_path=nil)
if remote_path.nil?
remote_path = "/tmp/vagrant-network-entry-#{Time.now.to_i}"
end
Tempfile.open("vagrant-devuan-configure-networks") do |f|
f.binmode
f.write(content)
f.fsync
f.close
comm.upload(f.path, remote_path)
end
remote_path
end
end
end
end
end
16 changes: 16 additions & 0 deletions plugins/guests/devuan/cap/nfs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module VagrantPlugins
module GuestDevuan
module Cap
class NFS
def self.nfs_client_install(machine)
comm = machine.communicate
comm.sudo <<-EOH.gsub(/^ {12}/, '')
apt-get -yqq update
apt-get -yqq install nfs-common portmap
exit $?
EOH
end
end
end
end
end
15 changes: 15 additions & 0 deletions plugins/guests/devuan/cap/rsync.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module VagrantPlugins
module GuestDevuan
module Cap
class RSync
def self.rsync_install(machine)
comm = machine.communicate
comm.sudo <<-EOH.gsub(/^ {14}/, '')
apt-get -yqq update
apt-get -yqq install rsync
EOH
end
end
end
end
end
17 changes: 17 additions & 0 deletions plugins/guests/devuan/cap/smb.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module VagrantPlugins
module GuestDevuan
module Cap
class SMB
def self.smb_install(machine)
comm = machine.communicate
if !comm.test("test -f /sbin/mount.cifs")
comm.sudo <<-EOH.gsub(/^ {14}/, '')
apt-get -yqq update
apt-get -yqq install cifs-utils
EOH
end
end
end
end
end
end
10 changes: 10 additions & 0 deletions plugins/guests/devuan/guest.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require_relative '../linux/guest'

module VagrantPlugins
module GuestDevuan
class Guest < VagrantPlugins::GuestLinux::Guest
# Name used for guest detection
GUEST_DETECTION_NAME = "devuan".freeze
end
end
end
Loading