datapath-windows: set the nlBuf tail properly
[cascardo/ovs.git] / utilities / ovs-docker
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 get_port_for_container_interface () {
46     CONTAINER="$1"
47     INTERFACE="$2"
48
49     PORT=`ovs_vsctl --data=bare --no-heading --columns=name find interface \
50              external_ids:container_id="$CONTAINER"  \
51              external_ids:container_iface="$INTERFACE"`
52     if [ -z "$PORT" ]; then
53         echo >&2 "$UTIL: Failed to find any attached port" \
54                  "for CONTAINER=$CONTAINER and INTERFACE=$INTERFACE"
55     fi
56     echo "$PORT"
57 }
58
59 add_port () {
60     BRIDGE="$1"
61     INTERFACE="$2"
62     CONTAINER="$3"
63     ADDRESS="$4"
64     GATEWAY="$5"
65
66     if [ "$#" -lt 3 ]; then
67         usage
68         exit 1
69     fi
70
71     if ovs_vsctl br-exists "$BRIDGE" || \
72         ovs_vsctl add-br "$BRIDGE"; then :; else
73         echo >&2 "$UTIL: Failed to create bridge $BRIDGE"
74         exit 1
75     fi
76
77     if PID=`docker inspect -f '{{.State.Pid}}' "$CONTAINER"`; then :; else
78         echo >&2 "$UTIL: Failed to get the PID of the container"
79         exit 1
80     fi
81
82     create_netns_link
83
84     # Create a veth pair.
85     ID=`uuidgen | sed 's/-//g'`
86     PORTNAME="${ID:0:13}"
87     ip link add "${PORTNAME}_l" type veth peer name "${PORTNAME}_c"
88
89     # Add one end of veth to OVS bridge.
90     if ovs_vsctl --may-exist add-port "$BRIDGE" "${PORTNAME}_l" \
91        -- set interface "${PORTNAME}_l" \
92        external_ids:container_id="$CONTAINER" \
93        external_ids:container_iface="$INTERFACE"; then :; else
94         echo >&2 "$UTIL: Failed to add "${PORTNAME}_l" port to bridge $BRIDGE"
95         ip link delete "${PORTNAME}_l"
96         exit 1
97     fi
98
99     ip link set "${PORTNAME}_l" up
100
101     # Move "${PORTNAME}_c" inside the container and changes its name.
102     ip link set "${PORTNAME}_c" netns "$PID"
103     ip netns exec "$PID" ip link set dev "${PORTNAME}_c" name "$INTERFACE"
104     ip netns exec "$PID" ip link set "$INTERFACE" up
105
106     if [ -n "$ADDRESS" ]; then
107         ip netns exec "$PID" ip addr add "$ADDRESS" dev "$INTERFACE"
108     fi
109
110     if [ -n "$GATEWAY" ]; then
111         ip netns exec "$PID" ip route add default via "$GATEWAY"
112     fi
113 }
114
115 del_port () {
116     BRIDGE="$1"
117     INTERFACE="$2"
118     CONTAINER="$3"
119
120     if [ "$#" -lt 3 ]; then
121         usage
122         exit 1
123     fi
124
125     PORT=`get_port_for_container_interface "$CONTAINER" "$INTERFACE"`
126     if [ -z "$PORT" ]; then
127         exit 1
128     fi
129
130     ovs_vsctl --if-exists del-port "$PORT"
131
132     ip link delete "$PORT"
133 }
134
135 del_ports () {
136     BRIDGE="$1"
137     CONTAINER="$2"
138     if [ "$#" -lt 2 ]; then
139         usage
140         exit 1
141     fi
142
143     PORTS=`ovs_vsctl --data=bare --no-heading --columns=name find interface \
144              external_ids:container_id="$CONTAINER"`
145     if [ -z "$PORTS" ]; then
146         exit 0
147     fi
148
149     for PORT in $PORTS; do
150         ovs_vsctl --if-exists del-port "$PORT"
151         ip link delete "$PORT"
152     done
153 }
154
155 set_vlan () {
156     BRIDGE="$1"
157     INTERFACE="$2"
158     CONTAINER_ID="$3"
159     VLAN="$4"
160
161     if [ "$#" -lt 4 ]; then
162         usage
163         exit 1
164     fi
165
166     PORT=`get_port_for_container_interface "$CONTAINER_ID" "$INTERFACE"`
167     if [ -z "$PORT" ]; then
168         exit 1
169     fi
170     ovs_vsctl set port "$PORT" tag="$VLAN"
171 }
172
173 usage() {
174     cat << EOF
175 ${UTIL}: Performs integration of Open vSwitch with Docker.
176 usage: ${UTIL} COMMAND
177
178 Commands:
179   add-port BRIDGE INTERFACE CONTAINER [ADDRESS [GATEWAY]]
180                     Adds INTERFACE inside CONTAINER and connects it as a port
181                     in Open vSwitch BRIDGE. Optionally, sets ADDRESS on
182                     INTERFACE. ADDRESS can include a '/' to represent network
183                     prefix length. Along with ADDRESS, optionally set the
184                     default gateway for the container. e.g.:
185                     ${UTIL} add-port br-int eth1 c474a0e2830e 192.168.1.2/24 \
186                         192.168.1.1
187   del-port BRIDGE INTERFACE CONTAINER
188                     Deletes INTERFACE inside CONTAINER and removes its
189                     connection to Open vSwitch BRIDGE. e.g.:
190                     ${UTIL} del-port br-int eth1 c474a0e2830e
191   del-ports BRIDGE CONTAINER
192                     Removes all Open vSwitch interfaces from CONTAINER. e.g.:
193                     ${UTIL} del-ports br-int c474a0e2830e
194   set-vlan BRIDGE INTERFACE CONTAINER VLAN
195                     Configures the INTERFACE of CONTAINER attached to BRIDGE
196                     to become an access port of VLAN. e.g.:
197                     ${UTIL} set-vlan br-int eth1 c474a0e2830e 5
198 Options:
199   -h, --help        display this help message.
200 EOF
201 }
202
203 UTIL=$(basename $0)
204 check_command_avail ovs-vsctl docker uuidgen
205
206 if (ip netns) > /dev/null 2>&1; then :; else
207     echo >&2 "$UTIL: ip utility not found (or it does not support netns),"\
208              "cannot proceed"
209     exit 1
210 fi
211
212 if [ $# -eq 0 ]; then
213     usage
214     exit 0
215 fi
216
217 case $1 in
218     "add-port")
219         shift
220         add_port "$@"
221         exit 0
222         ;;
223     "del-port")
224         shift
225         del_port "$@"
226         exit 0
227         ;;
228     "del-ports")
229         shift
230         del_ports "$@"
231         exit 0
232         ;;
233     "set-vlan")
234         shift
235         set_vlan "$@"
236         exit 0
237         ;;
238     -h | --help)
239         usage
240         exit 0
241         ;;
242     *)
243         echo >&2 "$UTIL: unknown command \"$1\" (use --help for help)"
244         exit 1
245         ;;
246 esac