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