]>
Commit | Line | Data |
---|---|---|
ec8f0f0c GS |
1 | #!/bin/bash |
2 | # Copyright (C) 2014 Nicira, Inc. | |
3 | # | |
4 | # Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | # you may not use this file except in compliance with the License. | |
6 | # You may obtain a copy of the License at: | |
7 | # | |
8 | # http://www.apache.org/licenses/LICENSE-2.0 | |
9 | # | |
10 | # Unless required by applicable law or agreed to in writing, software | |
11 | # distributed under the License is distributed on an "AS IS" BASIS, | |
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | # See the License for the specific language governing permissions and | |
14 | # limitations under the License. | |
15 | ||
16 | check_command_avail () { | |
17 | while [ $# -ne 0 ]; do | |
18 | if ("$1" --version) > /dev/null 2>&1; then :; else | |
19 | echo >&2 "$UTIL: missing $1, cannot proceed" | |
20 | exit 1 | |
21 | fi | |
22 | shift | |
23 | done | |
24 | } | |
25 | ||
26 | ovs_vsctl () { | |
27 | ovs-vsctl --timeout=60 "$@" | |
28 | } | |
29 | ||
30 | create_netns_link () { | |
31 | mkdir -p /var/run/netns | |
32 | if [ ! -e /var/run/netns/"$PID" ]; then | |
33 | ln -s /proc/"$PID"/ns/net /var/run/netns/"$PID" | |
34 | trap 'delete_netns_link' 0 | |
35 | for signal in 1 2 3 13 14 15; do | |
36 | trap 'delete_netns_link; trap - $signal; kill -$signal $$' $signal | |
37 | done | |
38 | fi | |
39 | } | |
40 | ||
41 | delete_netns_link () { | |
42 | rm -f /var/run/netns/"$PID" | |
43 | } | |
44 | ||
45 | add_port () { | |
46 | BRIDGE="$1" | |
47 | INTERFACE="$2" | |
48 | CONTAINER="$3" | |
49 | ADDRESS="$4" | |
50 | ||
51 | if [ "$#" -lt 3 ]; then | |
52 | usage | |
53 | exit 1 | |
54 | fi | |
55 | ||
56 | if ovs_vsctl --may-exist add-br "$BRIDGE"; then :; else | |
57 | echo >&2 "$UTIL: Failed to create bridge $BRIDGE" | |
58 | exit 1 | |
59 | fi | |
60 | ||
61 | if PID=`docker inspect -f '{{.State.Pid}}' "$CONTAINER"`; then :; else | |
62 | echo >&2 "$UTIL: Failed to get the PID of the container" | |
63 | exit 1 | |
64 | fi | |
65 | ||
66 | create_netns_link | |
67 | ||
68 | # Create a veth pair. | |
69 | ID=`uuidgen | sed 's/-//g'` | |
70 | PORTNAME="${ID:0:13}" | |
71 | ip link add "${PORTNAME}_l" type veth peer name "${PORTNAME}_c" | |
72 | ||
73 | # Add one end of veth to OVS bridge. | |
74 | if ovs_vsctl --may-exist add-port "$BRIDGE" "${PORTNAME}_l" \ | |
75 | -- set interface "${PORTNAME}_l" \ | |
76 | external_ids:container_id="$CONTAINER" \ | |
77 | external_ids:container_iface="$INTERFACE"; then :; else | |
78 | echo >&2 "$UTIL: Failed to add "${PORTNAME}_l" port to bridge $BRIDGE" | |
79 | ip link delete "${PORTNAME}_l" | |
80 | exit 1 | |
81 | fi | |
82 | ||
83 | ip link set "${PORTNAME}_l" up | |
84 | ||
85 | # Move "${PORTNAME}_c" inside the container and changes its name. | |
86 | ip link set "${PORTNAME}_c" netns "$PID" | |
87 | ip netns exec "$PID" ip link set dev "${PORTNAME}_c" name "$INTERFACE" | |
88 | ip netns exec "$PID" ip link set "$INTERFACE" up | |
89 | ||
90 | if [ -n "$ADDRESS" ]; then | |
91 | ip netns exec "$PID" ip addr add "$ADDRESS" dev "$INTERFACE" | |
92 | fi | |
93 | } | |
94 | ||
95 | del_port () { | |
96 | BRIDGE="$1" | |
97 | INTERFACE="$2" | |
98 | CONTAINER="$3" | |
99 | ||
100 | if [ "$#" -lt 3 ]; then | |
101 | usage | |
102 | exit 1 | |
103 | fi | |
104 | ||
105 | PORT=`ovs_vsctl --data=bare --no-heading --columns=name find interface \ | |
106 | external_ids:container_id="$CONTAINER" \ | |
107 | external_ids:container_iface="$INTERFACE"` | |
108 | if [ -z "$PORT" ]; then | |
109 | echo >&2 "$UTIL: Failed to find any attached port in $BRIDGE" \ | |
110 | "for CONTAINER=$CONTAINER and INTERFACE=$INTERFACE" | |
111 | exit 1 | |
112 | fi | |
113 | ||
114 | ovs_vsctl --if-exists del-port "$PORT" | |
115 | ||
116 | ip link delete "$PORT" | |
117 | } | |
118 | ||
119 | del_ports () { | |
120 | BRIDGE="$1" | |
121 | CONTAINER="$2" | |
122 | if [ "$#" -lt 2 ]; then | |
123 | usage | |
124 | exit 1 | |
125 | fi | |
126 | ||
127 | PORTS=`ovs_vsctl --data=bare --no-heading --columns=name find interface \ | |
128 | external_ids:container_id="$CONTAINER"` | |
129 | if [ -z "$PORTS" ]; then | |
130 | exit 0 | |
131 | fi | |
132 | ||
133 | for PORT in $PORTS; do | |
134 | ovs_vsctl --if-exists del-port "$PORT" | |
135 | ip link delete "$PORT" | |
136 | done | |
137 | } | |
138 | ||
139 | usage() { | |
140 | cat << EOF | |
141 | ${UTIL}: Performs integration of Open vSwitch with Docker. | |
142 | usage: ${UTIL} COMMAND | |
143 | ||
144 | Commands: | |
145 | add-port BRIDGE INTERFACE CONTAINER [ADDRESS] | |
146 | Adds INTERFACE inside CONTAINER and connects it as a port | |
147 | in Open vSwitch BRIDGE. Optionally, sets ADDRESS on | |
148 | INTERFACE. ADDRESS can include a '/' to represent network | |
149 | prefix length. e.g.: | |
150 | ${UTIL} add-port br-int eth1 c474a0e2830e 192.168.1.2/24 | |
151 | del-port BRIDGE INTERFACE CONTAINER | |
152 | Deletes INTERFACE inside CONTAINER and removes its | |
153 | connection to Open vSwitch BRIDGE. e.g.: | |
154 | ${UTIL} del-port br-int eth1 c474a0e2830e | |
155 | del-ports BRIDGE CONTAINER | |
156 | Removes all Open vSwitch interfaces from CONTAINER. e.g.: | |
157 | ${UTIL} del-ports br-int c474a0e2830e | |
158 | Options: | |
159 | -h, --help display this help message. | |
160 | EOF | |
161 | } | |
162 | ||
163 | UTIL=$(basename $0) | |
164 | check_command_avail ovs-vsctl docker uuidgen | |
165 | ||
166 | if (ip netns) > /dev/null 2>&1; then :; else | |
167 | echo >&2 "$UTIL: ip utility not found (or it does not support netns),"\ | |
168 | "cannot proceed" | |
169 | exit 1 | |
170 | fi | |
171 | ||
172 | if [ $# -eq 0 ]; then | |
173 | usage | |
174 | exit 0 | |
175 | fi | |
176 | ||
177 | case $1 in | |
178 | "add-port") | |
179 | shift | |
180 | add_port "$@" | |
181 | exit 0 | |
182 | ;; | |
183 | "del-port") | |
184 | shift | |
185 | del_port "$@" | |
186 | exit 0 | |
187 | ;; | |
188 | "del-ports") | |
189 | shift | |
190 | del_ports "$@" | |
191 | exit 0 | |
192 | ;; | |
193 | -h | --help) | |
194 | usage | |
195 | exit 0 | |
196 | ;; | |
197 | *) | |
198 | echo >&2 "$UTIL: unknown command \"$1\" (use --help for help)" | |
199 | exit 1 | |
200 | ;; | |
201 | esac |