vagrant-lxc 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -0
- data/lib/vagrant-lxc/action/fetch_ip_with_lxc_attach.rb +3 -1
- data/lib/vagrant-lxc/config.rb +4 -0
- data/lib/vagrant-lxc/driver/cli.rb +12 -1
- data/lib/vagrant-lxc/errors.rb +2 -1
- data/lib/vagrant-lxc/plugin.rb +13 -4
- data/lib/vagrant-lxc/sudo_wrapper.rb +1 -1
- data/lib/vagrant-lxc/version.rb +1 -1
- data/scripts/lxc-template +1 -1
- data/scripts/pipework +346 -222
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d84ceba1d5fb8d5d083ade786cbacccc062dafe0
|
4
|
+
data.tar.gz: 433489fcf70ecd5ae43094c8470c025f4040d59b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 840b7e84fad95f8585486a8b5dea5a86ce292a2c8edbb02a45fe6f99071480f4fd469db462783717418b8a48a49df59bc561425dd8ac69090d7327d1c1fd345e
|
7
|
+
data.tar.gz: 56c4c1fe8a20e36f45f0edbb6e587de557f67ceb8bd7d78beeacc47497833228e2fbb038e9d1d514456d01208e6746016d7f1995c8cb6ba1e9a80937e1c35629
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## [1.2.2](https://github.com/fgrehm/vagrant-lxc/compare/v1.2.1...v1.2.2) (Dec 20, 2016)
|
2
|
+
|
3
|
+
- Make the timeout for fetching container IP's configurable [[GH-426]]
|
4
|
+
- Load locale file only once [[GH-423]]
|
5
|
+
- Preserve xattrs in container filesystems [[GH-411]]
|
6
|
+
- Forward port latest pipework script [[GH-408]]
|
7
|
+
- Fix handling of non-fatal lxc-stop return code [[GH-405]]
|
8
|
+
|
1
9
|
## [1.2.1](https://github.com/fgrehm/vagrant-lxc/compare/v1.2.0...v1.2.1) (Sep 24, 2015)
|
2
10
|
|
3
11
|
BUGFIX:
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -19,6 +19,7 @@ to see it in action.
|
|
19
19
|
|
20
20
|
* [Vagrant 1.5+](http://www.vagrantup.com/downloads.html) (tested with 1.7.2)
|
21
21
|
* lxc 0.7.5+
|
22
|
+
* tar 1.27 (the lxc-template script uses the --xattrs option)
|
22
23
|
* `redir` (if you are planning to use port forwarding)
|
23
24
|
* `brctl` (if you are planning to use private networks, on Ubuntu this means `apt-get install bridge-utils`)
|
24
25
|
* A [kernel != 3.5.0-17.28](https://github.com/fgrehm/vagrant-lxc/wiki/Troubleshooting#wiki-im-unable-to-restart-containers)
|
@@ -19,9 +19,11 @@ module Vagrant
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def assigned_ip(env)
|
22
|
+
config = env[:machine].provider_config
|
23
|
+
fetch_ip_tries = config.fetch_ip_tries
|
22
24
|
driver = env[:machine].provider.driver
|
23
25
|
ip = ''
|
24
|
-
retryable(:on => LXC::Errors::ExecuteError, :tries =>
|
26
|
+
retryable(:on => LXC::Errors::ExecuteError, :tries => fetch_ip_tries, :sleep => 3) do
|
25
27
|
unless ip = get_container_ip_from_ip_addr(driver)
|
26
28
|
# retry
|
27
29
|
raise LXC::Errors::ExecuteError, :command => "lxc-attach"
|
data/lib/vagrant-lxc/config.rb
CHANGED
@@ -18,12 +18,15 @@ module Vagrant
|
|
18
18
|
# machine name, set this to :machine
|
19
19
|
attr_accessor :container_name
|
20
20
|
|
21
|
+
attr_accessor :fetch_ip_tries
|
22
|
+
|
21
23
|
def initialize
|
22
24
|
@customizations = []
|
23
25
|
@backingstore = UNSET_VALUE
|
24
26
|
@backingstore_options = []
|
25
27
|
@sudo_wrapper = UNSET_VALUE
|
26
28
|
@container_name = UNSET_VALUE
|
29
|
+
@fetch_ip_tries = UNSET_VALUE
|
27
30
|
end
|
28
31
|
|
29
32
|
# Customize the container by calling `lxc-start` with the given
|
@@ -51,6 +54,7 @@ module Vagrant
|
|
51
54
|
@container_name = nil if @container_name == UNSET_VALUE
|
52
55
|
@backingstore = "best" if @backingstore == UNSET_VALUE
|
53
56
|
@existing_container_name = nil if @existing_container_name == UNSET_VALUE
|
57
|
+
@fetch_ip_tries = 10 if @fetch_ip_tries == UNSET_VALUE
|
54
58
|
end
|
55
59
|
end
|
56
60
|
end
|
@@ -85,9 +85,20 @@ module Vagrant
|
|
85
85
|
run :start, '-d', '--name', @name, *Array(options)
|
86
86
|
end
|
87
87
|
|
88
|
+
## lxc-stop will exit 2 if machine was already stopped
|
89
|
+
# Man Page:
|
90
|
+
# 2 The specified container exists but was not running.
|
88
91
|
def stop
|
89
92
|
attach '/sbin/halt' if supports_attach?
|
90
|
-
|
93
|
+
begin
|
94
|
+
run :stop, '--name', @name
|
95
|
+
rescue LXC::Errors::ExecuteError => e
|
96
|
+
if e.exitcode == 2
|
97
|
+
@logger.debug "Machine already stopped, lxc-stop returned 2"
|
98
|
+
else
|
99
|
+
raise e
|
100
|
+
end
|
101
|
+
end
|
91
102
|
end
|
92
103
|
|
93
104
|
def attach(*cmd)
|
data/lib/vagrant-lxc/errors.rb
CHANGED
@@ -5,12 +5,13 @@ module Vagrant
|
|
5
5
|
module Errors
|
6
6
|
class ExecuteError < Vagrant::Errors::VagrantError
|
7
7
|
error_key(:lxc_execute_error)
|
8
|
-
attr_reader :stderr, :stdout
|
8
|
+
attr_reader :stderr, :stdout, :exitcode
|
9
9
|
def initialize(message, *args)
|
10
10
|
super
|
11
11
|
if message.is_a?(Hash)
|
12
12
|
@stderr = message[:stderr]
|
13
13
|
@stdout = message[:stdout]
|
14
|
+
@exitcode = message[:exitcode]
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
data/lib/vagrant-lxc/plugin.rb
CHANGED
@@ -11,20 +11,19 @@ module Vagrant
|
|
11
11
|
|
12
12
|
provider(:lxc, parallel: true, priority: 7) do
|
13
13
|
require File.expand_path("../provider", __FILE__)
|
14
|
-
|
15
|
-
I18n.load_path << File.expand_path(File.dirname(__FILE__) + '/../../locales/en.yml')
|
16
|
-
I18n.reload!
|
17
|
-
|
14
|
+
init!
|
18
15
|
Provider
|
19
16
|
end
|
20
17
|
|
21
18
|
command "lxc" do
|
22
19
|
require_relative 'command/root'
|
20
|
+
init!
|
23
21
|
Command::Root
|
24
22
|
end
|
25
23
|
|
26
24
|
config(:lxc, :provider) do
|
27
25
|
require File.expand_path("../config", __FILE__)
|
26
|
+
init!
|
28
27
|
Config
|
29
28
|
end
|
30
29
|
|
@@ -37,6 +36,16 @@ module Vagrant
|
|
37
36
|
require_relative "provider/cap/public_address"
|
38
37
|
Provider::Cap::PublicAddress
|
39
38
|
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def self.init!
|
43
|
+
return if defined?(@_init)
|
44
|
+
I18n.load_path << File.expand_path(File.dirname(__FILE__) + '/../../locales/en.yml')
|
45
|
+
I18n.reload!
|
46
|
+
@_init = true
|
47
|
+
end
|
48
|
+
|
40
49
|
end
|
41
50
|
end
|
42
51
|
end
|
@@ -49,7 +49,7 @@ module Vagrant
|
|
49
49
|
@logger.info("Exit code != 0, but interrupted. Ignoring.")
|
50
50
|
else
|
51
51
|
raise LXC::Errors::ExecuteError,
|
52
|
-
command: command.inspect, stderr: r.stderr, stdout: r.stdout
|
52
|
+
command: command.inspect, stderr: r.stderr, stdout: r.stdout, exitcode: r.exit_code
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
data/lib/vagrant-lxc/version.rb
CHANGED
data/scripts/lxc-template
CHANGED
@@ -124,7 +124,7 @@ mkdir -p /var/lock/subsys
|
|
124
124
|
fi
|
125
125
|
|
126
126
|
mkdir -p ${LXC_ROOTFS}
|
127
|
-
(cd ${LXC_ROOTFS} && tar xfz ${LXC_TARBALL} --strip-components=${LXC_STRIP_COMPONENTS})
|
127
|
+
(cd ${LXC_ROOTFS} && tar xfz ${LXC_TARBALL} --strip-components=${LXC_STRIP_COMPONENTS} --xattrs --xattrs-include=*)
|
128
128
|
if [ $? -ne 0 ]; then
|
129
129
|
echo "Failed to extract rootfs"
|
130
130
|
exit 1
|
data/scripts/pipework
CHANGED
@@ -1,13 +1,12 @@
|
|
1
|
-
#!/
|
2
|
-
|
3
|
-
#
|
4
|
-
|
1
|
+
#!/bin/sh
|
2
|
+
# This code should (try to) follow Google's Shell Style Guide
|
3
|
+
# (https://google-styleguide.googlecode.com/svn/trunk/shell.xml)
|
5
4
|
set -e
|
6
5
|
|
7
6
|
case "$1" in
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
--wait)
|
8
|
+
WAIT=1
|
9
|
+
;;
|
11
10
|
esac
|
12
11
|
|
13
12
|
IFNAME=$1
|
@@ -19,280 +18,405 @@ if [ "$2" = "-i" ]; then
|
|
19
18
|
shift 2
|
20
19
|
fi
|
21
20
|
|
21
|
+
if [ "$2" = "-l" ]; then
|
22
|
+
LOCAL_IFNAME=$3
|
23
|
+
shift 2
|
24
|
+
fi
|
25
|
+
|
22
26
|
GUESTNAME=$2
|
23
27
|
IPADDR=$3
|
24
28
|
MACADDR=$4
|
25
29
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
case "$MACADDR" in
|
31
|
+
*@*)
|
32
|
+
VLAN="${MACADDR#*@}"
|
33
|
+
VLAN="${VLAN%%@*}"
|
34
|
+
MACADDR="${MACADDR%%@*}"
|
35
|
+
;;
|
36
|
+
*)
|
37
|
+
VLAN=
|
38
|
+
;;
|
39
|
+
esac
|
40
|
+
|
41
|
+
# did they ask to generate a custom MACADDR?
|
42
|
+
# generate the unique string
|
43
|
+
case "$MACADDR" in
|
44
|
+
U:*)
|
45
|
+
macunique="${MACADDR#*:}"
|
46
|
+
# now generate a 48-bit hash string from $macunique
|
47
|
+
MACADDR=$(echo $macunique|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/')
|
48
|
+
;;
|
49
|
+
esac
|
50
|
+
|
33
51
|
|
34
52
|
[ "$IPADDR" ] || [ "$WAIT" ] || {
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
53
|
+
echo "Syntax:"
|
54
|
+
echo "pipework <hostinterface> [-i containerinterface] [-l localinterfacename] <guest> <ipaddr>/<subnet>[@default_gateway] [macaddr][@vlan]"
|
55
|
+
echo "pipework <hostinterface> [-i containerinterface] [-l localinterfacename] <guest> dhcp [macaddr][@vlan]"
|
56
|
+
echo "pipework route <guest> <route_command>"
|
57
|
+
echo "pipework --wait [-i containerinterface]"
|
58
|
+
exit 1
|
40
59
|
}
|
41
60
|
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
# exit 1
|
79
|
-
# ;;
|
80
|
-
# esac
|
61
|
+
# Succeed if the given utility is installed. Fail otherwise.
|
62
|
+
# For explanations about `which` vs `type` vs `command`, see:
|
63
|
+
# http://stackoverflow.com/questions/592620/check-if-a-program-exists-from-a-bash-script/677212#677212
|
64
|
+
# (Thanks to @chenhanxiao for pointing this out!)
|
65
|
+
installed () {
|
66
|
+
command -v "$1" >/dev/null 2>&1
|
67
|
+
}
|
68
|
+
|
69
|
+
# Google Styleguide says error messages should go to standard error.
|
70
|
+
warn () {
|
71
|
+
echo "$@" >&2
|
72
|
+
}
|
73
|
+
die () {
|
74
|
+
status="$1"
|
75
|
+
shift
|
76
|
+
warn "$@"
|
77
|
+
exit "$status"
|
78
|
+
}
|
79
|
+
|
80
|
+
# First step: determine type of first argument (bridge, physical interface...),
|
81
|
+
# Unless "--wait" is set (then skip the whole section)
|
82
|
+
if [ -z "$WAIT" ]; then
|
83
|
+
if [ -d "/sys/class/net/$IFNAME" ]
|
84
|
+
then
|
85
|
+
if [ -d "/sys/class/net/$IFNAME/bridge" ]; then
|
86
|
+
IFTYPE=bridge
|
87
|
+
BRTYPE=linux
|
88
|
+
elif installed ovs-vsctl && ovs-vsctl list-br|grep -q "^${IFNAME}$"; then
|
89
|
+
IFTYPE=bridge
|
90
|
+
BRTYPE=openvswitch
|
91
|
+
elif [ "$(cat "/sys/class/net/$IFNAME/type")" -eq 32 ]; then # InfiniBand IPoIB interface type 32
|
92
|
+
IFTYPE=ipoib
|
93
|
+
# The IPoIB kernel module is fussy, set device name to ib0 if not overridden
|
94
|
+
CONTAINER_IFNAME=${CONTAINER_IFNAME:-ib0}
|
95
|
+
PKEY=$VLAN
|
96
|
+
else IFTYPE=phys
|
81
97
|
fi
|
98
|
+
else
|
99
|
+
case "$IFNAME" in
|
100
|
+
br*)
|
101
|
+
IFTYPE=bridge
|
102
|
+
BRTYPE=linux
|
103
|
+
;;
|
104
|
+
ovs*)
|
105
|
+
if ! installed ovs-vsctl; then
|
106
|
+
die 1 "Need OVS installed on the system to create an ovs bridge"
|
107
|
+
fi
|
108
|
+
IFTYPE=bridge
|
109
|
+
BRTYPE=openvswitch
|
110
|
+
;;
|
111
|
+
route*)
|
112
|
+
IFTYPE=route
|
113
|
+
;;
|
114
|
+
dummy*)
|
115
|
+
IFTYPE=dummy
|
116
|
+
;;
|
117
|
+
*) die 1 "I do not know how to setup interface $IFNAME." ;;
|
118
|
+
esac
|
119
|
+
fi
|
82
120
|
fi
|
83
121
|
|
84
122
|
# Set the default container interface name to eth1 if not already set
|
85
123
|
CONTAINER_IFNAME=${CONTAINER_IFNAME:-eth1}
|
86
124
|
|
87
125
|
[ "$WAIT" ] && {
|
88
|
-
while
|
89
|
-
|
90
|
-
|
126
|
+
while true; do
|
127
|
+
# This first method works even without `ip` or `ifconfig` installed,
|
128
|
+
# but doesn't work on older kernels (e.g. CentOS 6.X). See #128.
|
129
|
+
grep -q '^1$' "/sys/class/net/$CONTAINER_IFNAME/carrier" && break
|
130
|
+
# This method hopefully works on those older kernels.
|
131
|
+
ip link ls dev "$CONTAINER_IFNAME" && break
|
132
|
+
sleep 1
|
133
|
+
done > /dev/null 2>&1
|
91
134
|
exit 0
|
92
135
|
}
|
93
136
|
|
94
|
-
[ $IFTYPE = bridge ] && [ $BRTYPE = linux ] && [ "$VLAN" ] && {
|
95
|
-
|
96
|
-
exit 1
|
137
|
+
[ "$IFTYPE" = bridge ] && [ "$BRTYPE" = linux ] && [ "$VLAN" ] && {
|
138
|
+
die 1 "VLAN configuration currently unsupported for Linux bridge."
|
97
139
|
}
|
98
140
|
|
99
|
-
[ $IFTYPE = ipoib ] && [ $MACADDR ] && {
|
100
|
-
|
101
|
-
exit 1
|
141
|
+
[ "$IFTYPE" = ipoib ] && [ "$MACADDR" ] && {
|
142
|
+
die 1 "MACADDR configuration unsupported for IPoIB interfaces."
|
102
143
|
}
|
103
144
|
|
104
145
|
# Second step: find the guest (for now, we only support LXC containers)
|
105
|
-
while read
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
CGROUPMNT=$mnt
|
146
|
+
while read _ mnt fstype options _; do
|
147
|
+
[ "$fstype" != "cgroup" ] && continue
|
148
|
+
echo "$options" | grep -qw devices || continue
|
149
|
+
CGROUPMNT=$mnt
|
110
150
|
done < /proc/mounts
|
111
151
|
|
112
152
|
[ "$CGROUPMNT" ] || {
|
113
|
-
|
114
|
-
exit 1
|
153
|
+
die 1 "Could not locate cgroup mount point."
|
115
154
|
}
|
116
155
|
|
117
156
|
# Try to find a cgroup matching exactly the provided name.
|
118
157
|
N=$(find "$CGROUPMNT" -name "$GUESTNAME" | wc -l)
|
119
158
|
case "$N" in
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
done
|
131
|
-
|
132
|
-
[ "$DOCKERPID" = 0 ] && {
|
133
|
-
echo "Docker inspect returned invalid PID 0"
|
134
|
-
exit 1
|
135
|
-
}
|
136
|
-
|
137
|
-
[ "$DOCKERPID" = "<no value>" ] && {
|
138
|
-
echo "Container $GUESTNAME not found, and unknown to Docker."
|
139
|
-
exit 1
|
140
|
-
}
|
141
|
-
else
|
142
|
-
echo "Container $GUESTNAME not found, and Docker not installed."
|
143
|
-
exit 1
|
144
|
-
fi
|
145
|
-
;;
|
146
|
-
1)
|
147
|
-
true
|
148
|
-
;;
|
149
|
-
*)
|
150
|
-
echo "Found more than one container matching $GUESTNAME."
|
151
|
-
exit 1
|
152
|
-
;;
|
153
|
-
esac
|
159
|
+
0)
|
160
|
+
# If we didn't find anything, try to lookup the container with Docker.
|
161
|
+
if installed docker; then
|
162
|
+
RETRIES=3
|
163
|
+
while [ "$RETRIES" -gt 0 ]; do
|
164
|
+
DOCKERPID=$(docker inspect --format='{{ .State.Pid }}' "$GUESTNAME")
|
165
|
+
[ "$DOCKERPID" != 0 ] && break
|
166
|
+
sleep 1
|
167
|
+
RETRIES=$((RETRIES - 1))
|
168
|
+
done
|
154
169
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
break
|
163
|
-
}
|
164
|
-
done
|
165
|
-
[ -z $DHCP_CLIENT ] && {
|
166
|
-
echo "You asked for DHCP; but no DHCP client could be found."
|
167
|
-
exit 1
|
168
|
-
}
|
169
|
-
else
|
170
|
-
# Check if a subnet mask was provided.
|
171
|
-
echo $IPADDR | grep -q / || {
|
172
|
-
echo "The IP address should include a netmask."
|
173
|
-
echo "Maybe you meant $IPADDR/24 ?"
|
174
|
-
exit 1
|
175
|
-
}
|
176
|
-
# Check if a gateway address was provided.
|
177
|
-
if echo $IPADDR | grep -q @
|
178
|
-
then
|
179
|
-
GATEWAY=$(echo $IPADDR | cut -d@ -f2)
|
180
|
-
IPADDR=$(echo $IPADDR | cut -d@ -f1)
|
170
|
+
[ "$DOCKERPID" = 0 ] && {
|
171
|
+
die 1 "Docker inspect returned invalid PID 0"
|
172
|
+
}
|
173
|
+
|
174
|
+
[ "$DOCKERPID" = "<no value>" ] && {
|
175
|
+
die 1 "Container $GUESTNAME not found, and unknown to Docker."
|
176
|
+
}
|
181
177
|
else
|
182
|
-
|
178
|
+
die 1 "Container $GUESTNAME not found, and Docker not installed."
|
183
179
|
fi
|
180
|
+
;;
|
181
|
+
1) true ;;
|
182
|
+
*) die 1 "Found more than one container matching $GUESTNAME." ;;
|
183
|
+
esac
|
184
|
+
|
185
|
+
# only check IPADDR if we are not in a route mode
|
186
|
+
[ "$IFTYPE" != route ] && {
|
187
|
+
case "$IPADDR" in
|
188
|
+
# Let's check first if the user asked for DHCP allocation.
|
189
|
+
dhcp|dhcp:*)
|
190
|
+
# Use Docker-specific strategy to run the DHCP client
|
191
|
+
# from the busybox image, in the network namespace of
|
192
|
+
# the container.
|
193
|
+
if ! [ "$DOCKERPID" ]; then
|
194
|
+
warn "You asked for a Docker-specific DHCP method."
|
195
|
+
warn "However, $GUESTNAME doesn't seem to be a Docker container."
|
196
|
+
warn "Try to replace 'dhcp' with another option?"
|
197
|
+
die 1 "Aborting."
|
198
|
+
fi
|
199
|
+
DHCP_CLIENT=${IPADDR%%:*}
|
200
|
+
;;
|
201
|
+
udhcpc|udhcpc:*|udhcpc-f|udhcpc-f:*|dhcpcd|dhcpcd:*|dhclient|dhclient:*|dhclient-f|dhclient-f:*)
|
202
|
+
DHCP_CLIENT=${IPADDR%%:*}
|
203
|
+
# did they ask for the client to remain?
|
204
|
+
DHCP_FOREGROUND=
|
205
|
+
[ "${DHCP_CLIENT: -2}" = '-f' ] && {
|
206
|
+
DHCP_FOREGROUND=true
|
207
|
+
}
|
208
|
+
DHCP_CLIENT=${DHCP_CLIENT%-f}
|
209
|
+
if ! installed "$DHCP_CLIENT"; then
|
210
|
+
die 1 "You asked for DHCP client $DHCP_CLIENT, but I can't find it."
|
211
|
+
fi
|
212
|
+
;;
|
213
|
+
# Alright, no DHCP? Then let's see if we have a subnet *and* gateway.
|
214
|
+
*/*@*)
|
215
|
+
GATEWAY="${IPADDR#*@}" GATEWAY="${GATEWAY%%@*}"
|
216
|
+
IPADDR="${IPADDR%%@*}"
|
217
|
+
;;
|
218
|
+
# No gateway? We need at least a subnet, anyway!
|
219
|
+
*/*) : ;;
|
220
|
+
# ... No? Then stop right here.
|
221
|
+
*)
|
222
|
+
warn "The IP address should include a netmask."
|
223
|
+
die 1 "Maybe you meant $IPADDR/24 ?"
|
224
|
+
;;
|
225
|
+
esac
|
226
|
+
}
|
227
|
+
|
228
|
+
# If a DHCP method was specified, extract the DHCP options.
|
229
|
+
if [ "$DHCP_CLIENT" ]; then
|
230
|
+
case "$IPADDR" in
|
231
|
+
*:*) DHCP_OPTIONS="${IPADDR#*:}" ;;
|
232
|
+
esac
|
184
233
|
fi
|
185
234
|
|
186
|
-
if [ $DOCKERPID ]; then
|
235
|
+
if [ "$DOCKERPID" ]; then
|
187
236
|
NSPID=$DOCKERPID
|
188
237
|
else
|
189
|
-
NSPID=$(head -n 1 $(find "$CGROUPMNT" -name "$GUESTNAME" | head -n 1)/tasks)
|
238
|
+
NSPID=$(head -n 1 "$(find "$CGROUPMNT" -name "$GUESTNAME" | head -n 1)/tasks")
|
190
239
|
[ "$NSPID" ] || {
|
191
|
-
|
192
|
-
|
240
|
+
# it is an alternative way to get the pid
|
241
|
+
NSPID=$(lxc-info -n "$GUESTNAME" | grep PID | grep -Eo '[0-9]+')
|
242
|
+
[ "$NSPID" ] || {
|
243
|
+
die 1 "Could not find a process inside container $GUESTNAME."
|
244
|
+
}
|
193
245
|
}
|
194
246
|
fi
|
195
247
|
|
196
248
|
# Check if an incompatible VLAN device already exists
|
197
|
-
[ $IFTYPE = phys ] && [ "$VLAN" ] && [ -d /sys/class/net/$IFNAME.VLAN ] && {
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
}
|
249
|
+
[ "$IFTYPE" = phys ] && [ "$VLAN" ] && [ -d "/sys/class/net/$IFNAME.VLAN" ] && {
|
250
|
+
ip -d link show "$IFNAME.$VLAN" | grep -q "vlan.*id $VLAN" || {
|
251
|
+
die 1 "$IFNAME.VLAN already exists but is not a VLAN device for tag $VLAN"
|
252
|
+
}
|
202
253
|
}
|
203
254
|
|
204
255
|
[ ! -d /var/run/netns ] && mkdir -p /var/run/netns
|
205
|
-
|
206
|
-
ln -s /proc/$NSPID/ns/net /var/run/netns/$NSPID
|
256
|
+
rm -f "/var/run/netns/$NSPID"
|
257
|
+
ln -s "/proc/$NSPID/ns/net" "/var/run/netns/$NSPID"
|
207
258
|
|
208
259
|
# Check if we need to create a bridge.
|
209
|
-
[ $IFTYPE = bridge ] && [ ! -d /sys/class/net/$IFNAME ] && {
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
260
|
+
[ "$IFTYPE" = bridge ] && [ ! -d "/sys/class/net/$IFNAME" ] && {
|
261
|
+
[ "$BRTYPE" = linux ] && {
|
262
|
+
(ip link add dev "$IFNAME" type bridge > /dev/null 2>&1) || (brctl addbr "$IFNAME")
|
263
|
+
ip link set "$IFNAME" up
|
264
|
+
}
|
265
|
+
[ "$BRTYPE" = openvswitch ] && {
|
266
|
+
ovs-vsctl add-br "$IFNAME"
|
267
|
+
}
|
217
268
|
}
|
218
269
|
|
219
|
-
MTU=$(ip link show $IFNAME | awk '{print $5}')
|
270
|
+
[ "$IFTYPE" != "route" ] && [ "$IFTYPE" != "dummy" ] && MTU=$(ip link show "$IFNAME" | awk '{print $5}')
|
271
|
+
|
220
272
|
# If it's a bridge, we need to create a veth pair
|
221
|
-
[ $IFTYPE = bridge ] && {
|
273
|
+
[ "$IFTYPE" = bridge ] && {
|
274
|
+
if [ -z "$LOCAL_IFNAME" ]; then
|
222
275
|
LOCAL_IFNAME="v${CONTAINER_IFNAME}pl${NSPID}"
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
ip link
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
276
|
+
fi
|
277
|
+
GUEST_IFNAME="v${CONTAINER_IFNAME}pg${NSPID}"
|
278
|
+
# Does the link already exist?
|
279
|
+
if ip link show "$LOCAL_IFNAME" >/dev/null 2>&1; then
|
280
|
+
# link exists, is it in use?
|
281
|
+
if ip link show "$LOCAL_IFNAME" up | grep -q "UP"; then
|
282
|
+
echo "Link $LOCAL_IFNAME exists and is up"
|
283
|
+
exit 1
|
284
|
+
fi
|
285
|
+
# delete the link so we can re-add it afterwards
|
286
|
+
ip link del "$LOCAL_IFNAME"
|
287
|
+
fi
|
288
|
+
ip link add name "$LOCAL_IFNAME" mtu "$MTU" type veth peer name "$GUEST_IFNAME" mtu "$MTU"
|
289
|
+
case "$BRTYPE" in
|
290
|
+
linux)
|
291
|
+
(ip link set "$LOCAL_IFNAME" master "$IFNAME" > /dev/null 2>&1) || (brctl addif "$IFNAME" "$LOCAL_IFNAME")
|
292
|
+
;;
|
293
|
+
openvswitch)
|
294
|
+
if ! ovs-vsctl list-ports "$IFNAME" | grep -q "^${LOCAL_IFNAME}$"; then
|
295
|
+
ovs-vsctl add-port "$IFNAME" "$LOCAL_IFNAME" ${VLAN:+tag="$VLAN"}
|
296
|
+
fi
|
297
|
+
;;
|
298
|
+
esac
|
299
|
+
ip link set "$LOCAL_IFNAME" up
|
243
300
|
}
|
244
301
|
|
245
302
|
# If it's a physical interface, create a macvlan subinterface
|
246
|
-
[ $IFTYPE = phys ] && {
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
}
|
251
|
-
|
252
|
-
ip link set $IFNAME up
|
253
|
-
IFNAME=$IFNAME.$VLAN
|
303
|
+
[ "$IFTYPE" = phys ] && {
|
304
|
+
[ "$VLAN" ] && {
|
305
|
+
[ ! -d "/sys/class/net/${IFNAME}.${VLAN}" ] && {
|
306
|
+
ip link add link "$IFNAME" name "$IFNAME.$VLAN" mtu "$MTU" type vlan id "$VLAN"
|
254
307
|
}
|
255
|
-
|
256
|
-
|
257
|
-
|
308
|
+
ip link set "$IFNAME" up
|
309
|
+
IFNAME=$IFNAME.$VLAN
|
310
|
+
}
|
311
|
+
GUEST_IFNAME=ph$NSPID$CONTAINER_IFNAME
|
312
|
+
ip link add link "$IFNAME" dev "$GUEST_IFNAME" mtu "$MTU" type macvlan mode bridge
|
313
|
+
ip link set "$IFNAME" up
|
258
314
|
}
|
259
315
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
# kill dhclient after get ip address to prevent device be used after container close
|
269
|
-
ip netns exec $NSPID $DHCP_CLIENT -pf "/var/run/dhclient.$NSPID.pid" $CONTAINER_IFNAME
|
270
|
-
kill "$(cat "/var/run/dhclient.$NSPID.pid")"
|
271
|
-
rm "/var/run/dhclient.$NSPID.pid"
|
272
|
-
fi
|
273
|
-
[ $DHCP_CLIENT = "dhcpcd" ] && ip netns exec $NSPID $DHCP_CLIENT -q $CONTAINER_IFNAME -h $GUESTNAME
|
274
|
-
else
|
275
|
-
ip netns exec $NSPID ip addr add $IPADDR dev $CONTAINER_IFNAME
|
276
|
-
[ "$GATEWAY" ] && {
|
277
|
-
ip netns exec $NSPID ip route delete default >/dev/null 2>&1 && true
|
278
|
-
}
|
279
|
-
ip netns exec $NSPID ip link set $CONTAINER_IFNAME up
|
280
|
-
[ "$GATEWAY" ] && {
|
281
|
-
ip netns exec $NSPID ip route get $GATEWAY >/dev/null 2>&1 || \
|
282
|
-
ip netns exec $NSPID ip route add $GATEWAY/32 dev $CONTAINER_IFNAME
|
283
|
-
ip netns exec $NSPID ip route replace default via $GATEWAY
|
284
|
-
}
|
285
|
-
fi
|
316
|
+
# If it's an IPoIB interface, create a virtual IPoIB interface (the IPoIB
|
317
|
+
# equivalent of a macvlan device)
|
318
|
+
#
|
319
|
+
# Note: no macvlan subinterface nor Ethernet bridge can be created on top of an
|
320
|
+
# IPoIB interface. InfiniBand is not Ethernet. IPoIB is an IP layer on top of
|
321
|
+
# InfiniBand, without an intermediate Ethernet layer.
|
322
|
+
[ "$IFTYPE" = ipoib ] && {
|
323
|
+
GUEST_IFNAME="${IFNAME}.${NSPID}"
|
286
324
|
|
287
|
-
#
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
325
|
+
# If a partition key is provided, use it
|
326
|
+
[ "$PKEY" ] && {
|
327
|
+
GUEST_IFNAME="${IFNAME}.${PKEY}.${NSPID}"
|
328
|
+
PKEY="pkey 0x$PKEY"
|
329
|
+
}
|
330
|
+
|
331
|
+
ip link add link "$IFNAME" name "$GUEST_IFNAME" type ipoib $PKEY
|
332
|
+
ip link set "$IFNAME" up
|
333
|
+
}
|
334
|
+
|
335
|
+
# If its a dummy interface, create a dummy interface.
|
336
|
+
[ "$IFTYPE" = dummy ] && {
|
337
|
+
GUEST_IFNAME=du$NSPID$CONTAINER_IFNAME
|
338
|
+
ip link add dev "$GUEST_IFNAME" type dummy
|
339
|
+
}
|
340
|
+
|
341
|
+
# If the `route` command was specified ...
|
342
|
+
if [ "$IFTYPE" = route ]; then
|
343
|
+
# ... discard the first two arguments and pass the rest to the route command.
|
344
|
+
shift 2
|
345
|
+
ip netns exec "$NSPID" ip route "$@"
|
346
|
+
else
|
347
|
+
# Otherwise, run normally.
|
348
|
+
ip link set "$GUEST_IFNAME" netns "$NSPID"
|
349
|
+
ip netns exec "$NSPID" ip link set "$GUEST_IFNAME" name "$CONTAINER_IFNAME"
|
350
|
+
[ "$MACADDR" ] && ip netns exec "$NSPID" ip link set dev "$CONTAINER_IFNAME" address "$MACADDR"
|
351
|
+
|
352
|
+
# When using any of the DHCP methods, we start a DHCP client in the
|
353
|
+
# network namespace of the container. With the 'dhcp' method, the
|
354
|
+
# client used is taken from the Docker busybox image (therefore
|
355
|
+
# requiring no specific client installed on the host). Other methods
|
356
|
+
# use a locally installed client.
|
357
|
+
case "$DHCP_CLIENT" in
|
358
|
+
dhcp)
|
359
|
+
docker run -d --net container:$GUESTNAME --cap-add NET_ADMIN \
|
360
|
+
busybox udhcpc -i "$CONTAINER_IFNAME" -x "hostname:$GUESTNAME" \
|
361
|
+
$DHCP_OPTIONS \
|
362
|
+
>/dev/null
|
363
|
+
;;
|
364
|
+
udhcpc)
|
365
|
+
DHCP_Q="-q"
|
366
|
+
[ "$DHCP_FOREGROUND" ] && {
|
367
|
+
DHCP_OPTIONS="$DHCP_OPTIONS -f"
|
368
|
+
}
|
369
|
+
ip netns exec "$NSPID" "$DHCP_CLIENT" -qi "$CONTAINER_IFNAME" \
|
370
|
+
-x "hostname:$GUESTNAME" \
|
371
|
+
-p "/var/run/udhcpc.$GUESTNAME.pid" \
|
372
|
+
$DHCP_OPTIONS
|
373
|
+
[ ! "$DHCP_FOREGROUND" ] && {
|
374
|
+
rm "/var/run/udhcpc.$GUESTNAME.pid"
|
375
|
+
}
|
376
|
+
;;
|
377
|
+
dhclient)
|
378
|
+
ip netns exec "$NSPID" "$DHCP_CLIENT" "$CONTAINER_IFNAME" \
|
379
|
+
-pf "/var/run/dhclient.$GUESTNAME.pid" \
|
380
|
+
-lf "/etc/dhclient/dhclient.$GUESTNAME.leases" \
|
381
|
+
$DHCP_OPTIONS
|
382
|
+
# kill dhclient after get ip address to prevent device be used after container close
|
383
|
+
[ ! "$DHCP_FOREGROUND" ] && {
|
384
|
+
kill "$(cat "/var/run/dhclient.$GUESTNAME.pid")"
|
385
|
+
rm "/var/run/dhclient.$GUESTNAME.pid"
|
386
|
+
}
|
387
|
+
;;
|
388
|
+
dhcpcd)
|
389
|
+
ip netns exec "$NSPID" "$DHCP_CLIENT" -q "$CONTAINER_IFNAME" -h "$GUESTNAME"
|
390
|
+
;;
|
391
|
+
"")
|
392
|
+
if installed ipcalc; then
|
393
|
+
eval $(ipcalc -b $IPADDR)
|
394
|
+
ip netns exec "$NSPID" ip addr add "$IPADDR" brd "$BROADCAST" dev "$CONTAINER_IFNAME"
|
395
|
+
else
|
396
|
+
ip netns exec "$NSPID" ip addr add "$IPADDR" dev "$CONTAINER_IFNAME"
|
397
|
+
fi
|
398
|
+
|
399
|
+
[ "$GATEWAY" ] && {
|
400
|
+
ip netns exec "$NSPID" ip route delete default >/dev/null 2>&1 && true
|
401
|
+
}
|
402
|
+
ip netns exec "$NSPID" ip link set "$CONTAINER_IFNAME" up
|
403
|
+
[ "$GATEWAY" ] && {
|
404
|
+
ip netns exec "$NSPID" ip route get "$GATEWAY" >/dev/null 2>&1 || \
|
405
|
+
ip netns exec "$NSPID" ip route add "$GATEWAY/32" dev "$CONTAINER_IFNAME"
|
406
|
+
ip netns exec "$NSPID" ip route replace default via "$GATEWAY"
|
407
|
+
}
|
408
|
+
;;
|
409
|
+
esac
|
410
|
+
|
411
|
+
# Give our ARP neighbors a nudge about the new interface
|
412
|
+
if installed arping; then
|
413
|
+
IPADDR=$(echo "$IPADDR" | cut -d/ -f1)
|
414
|
+
ip netns exec "$NSPID" arping -c 1 -A -I "$CONTAINER_IFNAME" "$IPADDR" > /dev/null 2>&1 || true
|
415
|
+
else
|
293
416
|
echo "Warning: arping not found; interface may not be immediately reachable"
|
417
|
+
fi
|
294
418
|
fi
|
295
|
-
|
296
419
|
# Remove NSPID to avoid `ip netns` catch it.
|
297
|
-
|
298
|
-
|
420
|
+
rm -f "/var/run/netns/$NSPID"
|
421
|
+
|
422
|
+
# vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab :
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-lxc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fabio Rehm
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Linux Containers provider for Vagrant
|
14
14
|
email:
|
@@ -101,7 +101,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
101
|
version: '0'
|
102
102
|
requirements: []
|
103
103
|
rubyforge_project:
|
104
|
-
rubygems_version: 2.
|
104
|
+
rubygems_version: 2.2.2
|
105
105
|
signing_key:
|
106
106
|
specification_version: 4
|
107
107
|
summary: Linux Containers provider for Vagrant
|