ovs-ctl: Use iptables -n -L instead of -S for compatibility.
[cascardo/ovs.git] / utilities / ovs-ctl.in
1 #! /bin/sh
2 # Copyright (C) 2009, 2010, 2011 Nicira Networks, 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 case $0 in
17     */*) dir0=`echo "$0" | sed 's,/[^/]*$,,'` ;;
18     *) dir0=./ ;;
19 esac
20 . "$dir0/ovs-lib.sh" || exit 1
21
22 for dir in "$sbindir" "$bindir" /sbin /bin /usr/sbin /usr/bin; do
23     case :$PATH: in
24         *:$dir:*) ;;
25         *) PATH=$PATH:$dir ;;
26     esac
27 done
28
29 ## ----- ##
30 ## start ##
31 ## ----- ##
32
33 insert_modules_if_required () {
34     # If openvswitch_mod is already loaded then we're done.
35     test -e /sys/module/openvswitch_mod && return 0
36
37     # Load openvswitch_mod.  If that's successful then we're done.
38     action "Inserting openvswitch module" modprobe openvswitch_mod && return 0
39
40     # If the bridge module is loaded, then that might be blocking
41     # openvswitch_mod.  Try to unload it, if there are no bridges.
42     test -e /sys/module/bridge || return 1
43     bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
44     if test "$bridges" != "*"; then
45         log_warning_msg "not removing bridge module because bridges exist ($bridges)"
46         return 1
47     fi
48     action "removing bridge module" rmmod bridge || return 1
49
50     # Try loading openvswitch_mod again.
51     action "Inserting openvswitch module" modprobe openvswitch_mod
52 }
53
54 ovs_vsctl () {
55     ovs-vsctl --no-wait --timeout=5 "$@"
56 }
57
58 ovsdb_tool () {
59     ovsdb-tool -vANY:console:emer "$@"
60 }
61
62 upgrade_db () {
63     schemaver=`ovsdb_tool schema-version "$DB_SCHEMA"`
64     if test ! -e "$DB_FILE"; then
65         log_warning_msg "$DB_FILE does not exist"
66         install -d -m 755 -o root -g root `dirname $DB_FILE`
67
68         action "Creating empty database $DB_FILE" true
69         ovsdb_tool create "$DB_FILE" "$DB_SCHEMA"
70     elif test X"`ovsdb_tool needs-conversion "$DB_FILE" "$DB_SCHEMA"`" != Xno; then
71         # Back up the old version.
72         version=`ovsdb_tool db-version "$DB_FILE"`
73         cksum=`ovsdb_tool db-cksum "$DB_FILE" | awk '{print $1}'`
74         cp "$DB_FILE" "$DB_FILE.backup$version-$cksum"
75
76         # Compact database.  This is important if the old schema did not enable
77         # garbage collection (i.e. if it did not have any tables with "isRoot":
78         # true) but the new schema does.  In that situation the old database
79         # may contain a transaction that creates a record followed by a
80         # transaction that creates the first use of the record.  Replaying that
81         # series of transactions against the new database schema (as "convert"
82         # does) would cause the record to be dropped by the first transaction,
83         # then the second transaction would cause a referential integrity
84         # failure (for a strong reference).
85         ovsdb_tool compact "$DB_FILE"
86
87         # Upgrade or downgrade schema.
88         ovsdb_tool convert "$DB_FILE" "$DB_SCHEMA"
89     fi
90 }
91
92 set_system_ids () {
93     set ovs_vsctl set Open_vSwitch .
94
95     OVS_VERSION=`ovs-vswitchd --version | sed 's/.*) //;1q'`
96     set "$@" ovs-version="$OVS_VERSION"
97
98     case $SYSTEM_ID in
99         random)
100             id_file=$etcdir/system-id.conf
101             uuid_file=$etcdir/install_uuid.conf
102             if test -e "$id_file"; then
103                 SYSTEM_ID=`cat "$id_file"`
104             elif test -e "$uuid_file"; then
105                 # Migrate from old file name.
106                 . "$uuid_file"
107                 SYSTEM_ID=$INSTALLATION_UUID
108                 echo "$SYSTEM_ID" > "$id_file"
109             elif SYSTEM_ID=`uuidgen`; then
110                 echo "$SYSTEM_ID" > "$id_file"
111             else
112                 log_failure_msg "missing uuidgen, could not generate system ID"
113             fi
114             ;;
115
116         '')
117             log_failure_msg "system ID not configured, please use --system-id"
118             ;;
119
120         *)
121             ;;
122     esac
123     set "$@" external-ids:system-id="\"$SYSTEM_ID\""
124
125     if test X"$SYSTEM_TYPE" != X; then
126         set "$@" system-type="\"$SYSTEM_TYPE\""
127     else
128         log_failure_msg "no default system type, please use --system-type"
129     fi
130
131     if test X"$SYSTEM_VERSION" != X; then
132         set "$@" system-version="\"$SYSTEM_VERSION\""
133     else
134         log_failure_msg "no default system version, please use --system-version"
135     fi
136
137     action "Configuring Open vSwitch system IDs" "$@" $extra_ids
138 }
139
140 start () {
141     if test X"$FORCE_COREFILES" = Xyes; then
142         ulimit -Sc 67108864
143     fi
144
145     insert_modules_if_required || return 1
146
147     if daemon_is_running ovsdb-server; then
148         log_success_msg "ovsdb-server is already running"
149     else
150         # Create initial database or upgrade database schema.
151         upgrade_db || return 1
152
153         # Start ovsdb-server.
154         set ovsdb-server "$DB_FILE"
155         set "$@" -vANY:CONSOLE:EMER -vANY:SYSLOG:ERR -vANY:FILE:INFO
156         set "$@" --remote=punix:"$DB_SOCK"
157         set "$@" --remote=db:Open_vSwitch,manager_options
158         set "$@" --private-key=db:SSL,private_key
159         set "$@" --certificate=db:SSL,certificate
160         set "$@" --bootstrap-ca-cert=db:SSL,ca_cert
161         start_daemon "$OVSDB_SERVER_PRIORITY" "$@" || return 1
162
163         # Initialize database settings.
164         ovs_vsctl -- init -- set Open_vSwitch . db-version="$schemaver" \
165             || return 1
166         set_system_ids || return 1
167         if test X"$DELETE_BRIDGES" = Xyes; then
168             for bridge in `ovs_vsctl list-br`; do
169                 ovs_vsctl del-br $bridge
170             done
171         fi
172     fi
173
174     if daemon_is_running ovs-vswitchd; then
175         log_success_msg "ovs-vswitchd is already running"
176     else
177         # Increase the limit on the number of open file descriptors since
178         # ovs-vswitchd needs a few per bridge
179         ulimit -n 4096
180
181         # Start ovs-vswitchd.
182         set ovs-vswitchd unix:"$DB_SOCK"
183         set "$@" -vANY:CONSOLE:EMER -vANY:SYSLOG:ERR -vANY:FILE:INFO
184         if test X"$MLOCKALL" != Xno; then
185             set "$@" --mlockall
186         fi
187         start_daemon "$VSWITCHD_PRIORITY" "$@"
188     fi
189 }
190
191 ## ---- ##
192 ## stop ##
193 ## ---- ##
194
195 stop () {
196     stop_daemon ovs-vswitchd
197     stop_daemon ovsdb-server
198 }
199
200 ## ----------------- ##
201 ## force-reload-kmod ##
202 ## ----------------- ##
203
204 internal_interfaces () {
205     # Outputs a list of internal interfaces:
206     #
207     #   - There is an internal interface for every bridge, whether it
208     #     has an Interface record or not and whether the Interface
209     #     record's 'type' is properly set or not.
210     #
211     #   - There is an internal interface for each Interface record whose
212     #     'type' is 'internal'.
213     #
214     # But ignore interfaces that don't really exist.
215     for d in `(ovs_vsctl --bare \
216                 -- --columns=name find Interface type=internal \
217                 -- list-br) | sort -u`
218     do
219         if test -e "/sys/class/net/$d"; then
220             printf "%s " "$d"
221         fi
222     done
223 }
224
225 save_interfaces () {
226     "$datadir/scripts/ovs-save" $ifaces > "$script"
227 }
228
229 force_reload_kmod () {
230     ifaces=`internal_interfaces`
231     action "Detected internal interfaces: $ifaces" true
232
233     stop
234
235     script=`mktemp`
236     trap 'rm -f "$script"' 0 1 2 13 15
237     if action "Saving interface configuration" save_interfaces; then
238         :
239     else
240         log_warning_msg "Failed to save configuration, not replacing kernel module"
241         start
242         exit 1
243     fi
244     chmod +x "$script"
245
246     for dp in `ovs-dpctl dump-dps`; do
247         action "Removing datapath: $dp" "$dpctl" del-dp "$dp"
248     done
249
250     if test -e /sys/module/openvswitch_mod; then
251         action "Removing openvswitch module" rmmod openvswitch_mod
252     fi
253
254     start
255
256     action "Restoring interface configuration" "$script"
257     rc=$?
258     if test $rc = 0; then
259         level=debug
260     else
261         level=err
262     fi
263     log="logger -p daemon.$level -t ovs-save"
264     $log "force-reload-kmod interface restore script exited with status $rc:"
265     $log -f "$script"
266 }
267
268 ## --------------- ##
269 ## enable-protocol ##
270 ## --------------- ##
271
272 enable_protocol () {
273     # Translate the protocol name to a number, because "iptables -n -L" prints
274     # some protocols by name (despite the -n) and therefore we need to look for
275     # both forms.
276     #
277     # (iptables -S output is more uniform but old iptables doesn't have it.)
278     protonum=`grep "^$PROTOCOL[         ]" /etc/protocols | awk '{print $2}'`
279     if expr X"$protonum" : X'[0-9]\{1,\}$' > /dev/null; then :; else
280         log_failure_msg "unknown protocol $PROTOCOL"
281         return 1
282     fi
283
284     name=$PROTOCOL
285     match="(\$2 == \"$PROTOCOL\" || \$2 == $protonum)"
286     insert="iptables -I INPUT -p $PROTOCOL"
287     if test X"$DPORT" != X; then
288         name="$name to port $DPORT"
289         match="$match && /dpt:$DPORT/"
290         insert="$insert --dport $DPORT"
291     fi
292     if test X"$SPORT" != X; then
293         name="$name from port $SPORT"
294         match="$match && /spt:$SPORT/"
295         insert="$insert --sport $SPORT"
296     fi
297     insert="$insert -j ACCEPT"
298
299     if (iptables -n -L INPUT) >/dev/null 2>&1; then
300         if iptables -n -L INPUT | awk "$match { n++ } END { exit n == 0 }"
301         then
302             # There's already a rule for this protocol.  Don't override it.
303             log_success_msg "iptables already has a rule for $name, not explicitly enabling"
304         else
305             action "Enabling $name with iptables" $insert
306         fi
307     elif (iptables --version) >/dev/null 2>&1; then
308         action "cannot list iptables rules, not adding a rule for $name"
309     else
310         action "iptables binary not installed, not adding a rule for $name"
311     fi
312 }
313
314 ## ---- ##
315 ## main ##
316 ## ---- ##
317
318 set_defaults () {
319     SYSTEM_ID=
320
321     DELETE_BRIDGES=no
322
323     DAEMON_CWD=/
324     FORCE_COREFILES=yes
325     MLOCKALL=yes
326     OVSDB_SERVER_PRIORITY=-10
327     OVS_VSWITCHD_PRIORITY=-10
328
329     DB_FILE=$etcdir/conf.db
330     DB_SOCK=$rundir/db.sock
331     DB_SCHEMA=$datadir/vswitch.ovsschema
332
333     PROTOCOL=gre
334     DPORT=
335     SPORT=
336
337     if (lsb_release --id) >/dev/null 2>&1; then
338         SYSTEM_TYPE=`lsb_release --id -s`
339         system_release=`lsb_release --release -s`
340         system_codename=`lsb_release --codename -s`
341         SYSTEM_VERSION="${system_release}-${system_codename}"
342     else
343         SYSTEM_TYPE=unknown
344         SYSTEM_VERSION=unknown
345     fi
346 }
347
348 usage () {
349     set_defaults
350     cat <<EOF
351 $0: controls Open vSwitch daemons
352 usage: $0 [OPTIONS] COMMAND
353
354 This program is intended to be invoked internally by Open vSwitch startup
355 scripts.  System administrators should not normally invoke it directly.
356
357 Commands:
358   start              start Open vSwitch daemons
359   stop               stop Open vSwitch daemons
360   status             check whether Open vSwitch daemons are running
361   version            print versions of Open vSwitch daemons
362   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
363                      module, reload kernel module, start OVS, restore state
364   enable-protocol    enable protocol specified in options with iptables
365   help               display this help message
366
367 One of the following options should be specified when starting Open vSwitch:
368   --system-id=UUID   set specific ID to uniquely identify this system
369   --system-id=random  use a random but persistent UUID to identify this system
370
371 Other important options for starting Open vSwitch:
372   --system-type=TYPE  set system type (e.g. "XenServer")
373   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
374   --external-id="key=value"
375                      add given key-value pair to Open_vSwitch external-ids
376   --delete-bridges   delete all bridges just before starting ovs-vswitchd
377
378 Less important options for starting Open vSwitch:
379   --daemon-cwd=DIR   current working directory for OVS daemons (default: $DAEMON_CWD)
380   --no-force-corefiles
381                      do not forcibly enable core dumps for OVS daemons
382   --no-mlockall      do not lock all of ovs-vswitchd into memory
383   --ovsdb-server-priority=NICE
384                      set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
385   --ovs-vswitchd-priority=NICE
386                      set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
387
388 File location options:
389   --db-file=FILE     database file name (default: $DB_FILE)
390   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
391   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
392
393 Options for enable-protocol:
394   --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
395   --sport=PORT       source port to match (for tcp or udp protocol)
396   --dport=PORT       ddestination port to match (for tcp or udp protocol)
397
398 Other options:
399   -h, --help                  display this help message
400   -V, --version               display version information
401
402 Default directories with "configure" option and environment variable override:
403   logs: @LOGDIR@ (--log-dir, OVS_LOGDIR)
404   pidfiles and sockets: @RUNDIR@ (--run-dir, OVS_RUNDIR)
405   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
406   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
407   user binaries: @bindir@ (--bindir, OVS_BINDIR)
408   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
409
410 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
411 EOF
412
413     exit 0
414 }
415
416 set_option () {
417     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
418     eval set=\${$var+yes}
419     eval old_value=\$$var
420     if test X$set = X || \
421         (test $type = bool && \
422         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
423         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
424         return
425     fi
426     eval $var=\$value
427 }
428
429 set_defaults
430 extra_ids=
431 command=
432 for arg
433 do
434     case $arg in
435         -h | --help)
436             usage
437             ;;
438         -V | --version)
439             echo "$0 (Open vSwitch) $VERSION$BUILDNR"
440             exit 0
441             ;;
442         --external-id=*)
443             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
444             case $value in
445                 *=*)
446                     extra_ids="$extra_ids external-ids:$value"
447                     ;;
448                 *)
449                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
450                     exit 1
451                     ;;
452             esac
453             ;;
454         --[a-z]*=*)
455             option=`expr X"$arg" : 'X--\([^=]*\)'`
456             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
457             type=string
458             set_option
459             ;;
460         --no-[a-z]*)
461             option=`expr X"$arg" : 'X--no-\(.*\)'`
462             value=no
463             type=bool
464             set_option
465             ;;
466         --[a-z]*)
467             option=`expr X"$arg" : 'X--\(.*\)'`
468             value=yes
469             type=bool
470             set_option
471             ;;
472         -*)
473             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
474             exit 1
475             ;;
476         *)
477             if test X"$command" = X; then
478                 command=$arg
479             else
480                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
481                 exit 1
482             fi
483             ;;
484     esac
485 done
486 case $command in
487     start)
488         start
489         ;;
490     stop)
491         stop
492         ;;
493     status)
494         daemon_status ovsdb-server && daemon_status ovs-vswitchd
495         ;;
496     version)
497         ovsdb-server --version && ovs-vswitchd --version
498         ;;
499     force-reload-kmod)
500         force_reload_kmod
501         ;;
502     enable-protocol)
503         enable_protocol
504         ;;
505     help)
506         usage
507         ;;
508     '')
509         echo >&2 "$0: missing command name (use --help for help)"
510         exit 1
511         ;;
512     *)
513         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
514         exit 1
515         ;;
516 esac
517