Merge remote-tracking branch 'origin/private-networks' into next
This commit is contained in:
commit
28bdbe371d
6 changed files with 261 additions and 6 deletions
|
@ -20,6 +20,7 @@ to see it in action.
|
||||||
* [Vagrant 1.1+](http://www.vagrantup.com/downloads.html)
|
* [Vagrant 1.1+](http://www.vagrantup.com/downloads.html)
|
||||||
* lxc 0.7.5+
|
* lxc 0.7.5+
|
||||||
* `redir` (if you are planning to use port forwarding)
|
* `redir` (if you are planning to use port forwarding)
|
||||||
|
* `brctl` (if you are planning to use private networks, on Ubuntu this means `apt-get install bridge-utils`)
|
||||||
* A [kernel != 3.5.0-17.28](https://github.com/fgrehm/vagrant-lxc/wiki/Troubleshooting#wiki-im-unable-to-restart-containers)
|
* A [kernel != 3.5.0-17.28](https://github.com/fgrehm/vagrant-lxc/wiki/Troubleshooting#wiki-im-unable-to-restart-containers)
|
||||||
|
|
||||||
The plugin is known to work better and pretty much out of the box on Ubuntu 14.04+
|
The plugin is known to work better and pretty much out of the box on Ubuntu 14.04+
|
||||||
|
|
|
@ -11,6 +11,7 @@ require 'vagrant-lxc/action/forward_ports'
|
||||||
require 'vagrant-lxc/action/handle_box_metadata'
|
require 'vagrant-lxc/action/handle_box_metadata'
|
||||||
require 'vagrant-lxc/action/prepare_nfs_settings'
|
require 'vagrant-lxc/action/prepare_nfs_settings'
|
||||||
require 'vagrant-lxc/action/prepare_nfs_valid_ids'
|
require 'vagrant-lxc/action/prepare_nfs_valid_ids'
|
||||||
|
require 'vagrant-lxc/action/private_networks'
|
||||||
require 'vagrant-lxc/action/remove_temporary_files'
|
require 'vagrant-lxc/action/remove_temporary_files'
|
||||||
require 'vagrant-lxc/action/setup_package_files'
|
require 'vagrant-lxc/action/setup_package_files'
|
||||||
require 'vagrant-lxc/action/warn_networks'
|
require 'vagrant-lxc/action/warn_networks'
|
||||||
|
@ -56,6 +57,7 @@ module Vagrant
|
||||||
b.use ForwardPorts
|
b.use ForwardPorts
|
||||||
b.use Boot
|
b.use Boot
|
||||||
b.use Builtin::WaitForCommunicator
|
b.use Builtin::WaitForCommunicator
|
||||||
|
b.use PrivateNetworks
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
60
lib/vagrant-lxc/action/private_networks.rb
Normal file
60
lib/vagrant-lxc/action/private_networks.rb
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
module Vagrant
|
||||||
|
module LXC
|
||||||
|
module Action
|
||||||
|
class PrivateNetworks
|
||||||
|
def initialize(app, env)
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
@app.call(env)
|
||||||
|
|
||||||
|
if private_network_configured?(env[:machine].config)
|
||||||
|
configure_private_networks(env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def private_network_configured?(config)
|
||||||
|
config.vm.networks.find do |type, _|
|
||||||
|
type.to_sym == :private_network
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def configure_private_networks(env)
|
||||||
|
env[:machine].config.vm.networks.find do |type, config|
|
||||||
|
next if type.to_sym != :private_network
|
||||||
|
|
||||||
|
container_name = env[:machine].provider.driver.container_name
|
||||||
|
ip = config[:ip]
|
||||||
|
configure_single_network('br1', container_name, ip)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def configure_single_network(bridge, container_name, ip)
|
||||||
|
cmd = [
|
||||||
|
'sudo',
|
||||||
|
Vagrant::LXC.source_root.join('scripts/private-network').to_s,
|
||||||
|
bridge,
|
||||||
|
container_name,
|
||||||
|
"#{ip}/24"
|
||||||
|
]
|
||||||
|
puts cmd.join(' ')
|
||||||
|
system cmd.join(' ')
|
||||||
|
|
||||||
|
cmd = [
|
||||||
|
'sudo',
|
||||||
|
'ip',
|
||||||
|
'addr',
|
||||||
|
'add',
|
||||||
|
# TODO: This should not be hard coded and has to run once per bridge
|
||||||
|
"192.168.1.254/24",
|
||||||
|
'dev',
|
||||||
|
bridge
|
||||||
|
]
|
||||||
|
puts cmd.join(' ')
|
||||||
|
system cmd.join(' ')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,16 +7,16 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
if public_or_private_network_configured?(env[:machine].config)
|
if public_network_configured?(env[:machine].config)
|
||||||
env[:ui].warn(I18n.t("vagrant_lxc.messages.warn_networks"))
|
env[:ui].warn(I18n.t("vagrant_lxc.messages.warn_networks"))
|
||||||
end
|
end
|
||||||
|
|
||||||
@app.call(env)
|
@app.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
def public_or_private_network_configured?(config)
|
def public_network_configured?(config)
|
||||||
config.vm.networks.find do |type, _|
|
config.vm.networks.find do |type, _|
|
||||||
[:private_network, :public_network].include?(type.to_sym)
|
type.to_sym == :public_network
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,9 +13,8 @@ en:
|
||||||
force_shutdown: |-
|
force_shutdown: |-
|
||||||
Forcing shutdown of container...
|
Forcing shutdown of container...
|
||||||
warn_networks: |-
|
warn_networks: |-
|
||||||
Warning! The LXC provider doesn't support any of the Vagrant public / private
|
Warning! The LXC provider doesn't support public networks, the settings
|
||||||
network configurations (ex: `config.vm.network :private_network, ip: "some-ip"`).
|
will be silently ignored.
|
||||||
They will be silently ignored.
|
|
||||||
warn_group: |-
|
warn_group: |-
|
||||||
Warning! The LXC provider doesn't support the :group parameter for synced
|
Warning! The LXC provider doesn't support the :group parameter for synced
|
||||||
folders. It will be silently ignored.
|
folders. It will be silently ignored.
|
||||||
|
|
193
scripts/private-network
Executable file
193
scripts/private-network
Executable file
|
@ -0,0 +1,193 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This is a snapshot of https://github.com/jpetazzo/pipework/blob/edbd33ab49ab0dff0bee46b019055360f325a6e5/pipework
|
||||||
|
# with docker specifics trimmed out
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
--wait)
|
||||||
|
WAIT=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
IFNAME=$1
|
||||||
|
if [ "$2" == "-i" ]; then
|
||||||
|
CONTAINER_IFNAME=$3
|
||||||
|
shift 2
|
||||||
|
else
|
||||||
|
CONTAINER_IFNAME=eth1
|
||||||
|
fi
|
||||||
|
GUESTNAME=$2
|
||||||
|
IPADDR=$3
|
||||||
|
MACADDR=$4
|
||||||
|
|
||||||
|
[ "$WAIT" ] && {
|
||||||
|
while ! grep -q ^1$ /sys/class/net/$CONTAINER_IFNAME/carrier 2>/dev/null
|
||||||
|
do sleep 1
|
||||||
|
done
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
[ "$IPADDR" ] || {
|
||||||
|
echo "Syntax:"
|
||||||
|
echo "pipework <hostinterface> [-i containerinterface] <guest> <ipaddr>/<subnet>[@default_gateway] [macaddr]"
|
||||||
|
echo "pipework <hostinterface> [-i containerinterface] <guest> dhcp [macaddr]"
|
||||||
|
echo "pipework --wait"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# First step: determine type of first argument (bridge, physical interface...)
|
||||||
|
if [ -d /sys/class/net/$IFNAME ]
|
||||||
|
then
|
||||||
|
if [ -d /sys/class/net/$IFNAME/bridge ]
|
||||||
|
then
|
||||||
|
IFTYPE=bridge
|
||||||
|
BRTYPE=linux
|
||||||
|
elif $(which ovs-vsctl >/dev/null) && $(ovs-vsctl list-br|grep -q ^$IFNAME$)
|
||||||
|
then
|
||||||
|
IFTYPE=bridge
|
||||||
|
BRTYPE=openvswitch
|
||||||
|
else IFTYPE=phys
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
case "$IFNAME" in
|
||||||
|
br*)
|
||||||
|
IFTYPE=bridge
|
||||||
|
BRTYPE=linux
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "I do not know how to setup interface $IFNAME."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Second step: find the guest
|
||||||
|
while read dev mnt fstype options dump fsck
|
||||||
|
do
|
||||||
|
[ "$fstype" != "cgroup" ] && continue
|
||||||
|
echo $options | grep -qw devices || continue
|
||||||
|
CGROUPMNT=$mnt
|
||||||
|
done < /proc/mounts
|
||||||
|
|
||||||
|
[ "$CGROUPMNT" ] || {
|
||||||
|
echo "Could not locate cgroup mount point."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try to find a cgroup matching exactly the provided name.
|
||||||
|
N=$(find "$CGROUPMNT" -name "$GUESTNAME" | wc -l)
|
||||||
|
case "$N" in
|
||||||
|
0)
|
||||||
|
echo "Container $GUESTNAME not found."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
1)
|
||||||
|
true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Found more than one container matching $GUESTNAME."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$IPADDR" = "dhcp" ]
|
||||||
|
then
|
||||||
|
# Check for first available dhcp client
|
||||||
|
DHCP_CLIENT_LIST="udhcpc dhcpcd dhclient"
|
||||||
|
for CLIENT in $DHCP_CLIENT_LIST; do
|
||||||
|
which $CLIENT >/dev/null && {
|
||||||
|
DHCP_CLIENT=$CLIENT
|
||||||
|
break
|
||||||
|
}
|
||||||
|
done
|
||||||
|
[ -z $DHCP_CLIENT ] && {
|
||||||
|
echo "You asked for DHCP; but no DHCP client could be found."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# Check if a subnet mask was provided.
|
||||||
|
echo $IPADDR | grep -q / || {
|
||||||
|
echo "The IP address should include a netmask."
|
||||||
|
echo "Maybe you meant $IPADDR/24 ?"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
# Check if a gateway address was provided.
|
||||||
|
if echo $IPADDR | grep -q @
|
||||||
|
then
|
||||||
|
GATEWAY=$(echo $IPADDR | cut -d@ -f2)
|
||||||
|
IPADDR=$(echo $IPADDR | cut -d@ -f1)
|
||||||
|
else
|
||||||
|
GATEWAY=
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
NSPID=$(head -n 1 $(find "$CGROUPMNT" -name "$GUESTNAME" | head -n 1)/tasks)
|
||||||
|
[ "$NSPID" ] || {
|
||||||
|
echo "Could not find a process inside container $GUESTNAME."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[ ! -d /var/run/netns ] && mkdir -p /var/run/netns
|
||||||
|
[ -f /var/run/netns/$NSPID ] && rm -f /var/run/netns/$NSPID
|
||||||
|
ln -s /proc/$NSPID/ns/net /var/run/netns/$NSPID
|
||||||
|
|
||||||
|
|
||||||
|
# Check if we need to create a bridge.
|
||||||
|
[ $IFTYPE = bridge ] && [ ! -d /sys/class/net/$IFNAME ] && {
|
||||||
|
(ip link set $IFNAME type bridge > /dev/null 2>&1) || (brctl addbr $IFNAME)
|
||||||
|
ip link set $IFNAME up
|
||||||
|
}
|
||||||
|
|
||||||
|
# If it's a bridge, we need to create a veth pair
|
||||||
|
[ $IFTYPE = bridge ] && {
|
||||||
|
LOCAL_IFNAME=pl$NSPID$CONTAINER_IFNAME
|
||||||
|
GUEST_IFNAME=pg$NSPID$CONTAINER_IFNAME
|
||||||
|
ip link add name $LOCAL_IFNAME type veth peer name $GUEST_IFNAME
|
||||||
|
case "$BRTYPE" in
|
||||||
|
linux)
|
||||||
|
(ip link set $LOCAL_IFNAME master $IFNAME > /dev/null 2>&1) || (brctl addif $IFNAME $LOCAL_IFNAME)
|
||||||
|
;;
|
||||||
|
openvswitch)
|
||||||
|
ovs-vsctl add-port $IFNAME $LOCAL_IFNAME
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
ip link set $LOCAL_IFNAME up
|
||||||
|
}
|
||||||
|
|
||||||
|
# If it's a physical interface, create a macvlan subinterface
|
||||||
|
[ $IFTYPE = phys ] && {
|
||||||
|
GUEST_IFNAME=ph$NSPID$CONTAINER_IFNAME
|
||||||
|
ip link add link $IFNAME dev $GUEST_IFNAME type macvlan mode bridge
|
||||||
|
ip link set $IFNAME up
|
||||||
|
}
|
||||||
|
|
||||||
|
ip link set $GUEST_IFNAME netns $NSPID
|
||||||
|
ip netns exec $NSPID ip link set $GUEST_IFNAME name $CONTAINER_IFNAME
|
||||||
|
[ "$MACADDR" ] && ip netns exec $NSPID ip link set $CONTAINER_IFNAME address $MACADDR
|
||||||
|
if [ "$IPADDR" = "dhcp" ]
|
||||||
|
then
|
||||||
|
[ $DHCP_CLIENT = "udhcpc" ] && ip netns exec $NSPID $DHCP_CLIENT -qi $CONTAINER_IFNAME
|
||||||
|
[ $DHCP_CLIENT = "dhclient" ] && ip netns exec $NSPID $DHCP_CLIENT $CONTAINER_IFNAME
|
||||||
|
[ $DHCP_CLIENT = "dhcpcd" ] && ip netns exec $NSPID $DHCP_CLIENT -q $CONTAINER_IFNAME
|
||||||
|
else
|
||||||
|
ip netns exec $NSPID ip addr add $IPADDR dev $CONTAINER_IFNAME
|
||||||
|
[ "$GATEWAY" ] && {
|
||||||
|
ip netns exec $NSPID ip route delete default >/dev/null 2>&1 && true
|
||||||
|
}
|
||||||
|
ip netns exec $NSPID ip link set $CONTAINER_IFNAME up
|
||||||
|
[ "$GATEWAY" ] && {
|
||||||
|
ip netns exec $NSPID ip route replace default via $GATEWAY
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Give our ARP neighbors a nudge about the new interface
|
||||||
|
if which arping > /dev/null 2>&1
|
||||||
|
then
|
||||||
|
IPADDR=$(echo $IPADDR | cut -d/ -f1)
|
||||||
|
ip netns exec $NSPID arping -c 1 -A -I $CONTAINER_IFNAME $IPADDR > /dev/null 2>&1
|
||||||
|
else
|
||||||
|
echo "Warning: arping not found; interface may not be immediately reachable"
|
||||||
|
fi
|
||||||
|
exit 0
|
Loading…
Reference in a new issue