vagrant-lxc 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|