unixctl: Fix comment on unixctl_command_register().
[sliver-openvswitch.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 check_force_cores () {
176     if test X"$FORCE_COREFILES" = Xyes; then
177         ulimit -Sc 67108864
178     fi
179 }
180
181 start_ovsdb () {
182     check_force_cores
183
184     if daemon_is_running ovsdb-server; then
185         log_success_msg "ovsdb-server is already running"
186     else
187         # Create initial database or upgrade database schema.
188         upgrade_db || return 1
189
190         # Start ovsdb-server.
191         set ovsdb-server "$DB_FILE"
192         set "$@" -vconsole:emer -vsyslog:err -vfile:info
193         set "$@" --remote=punix:"$DB_SOCK"
194         set "$@" --remote=db:Open_vSwitch,manager_options
195         set "$@" --private-key=db:SSL,private_key
196         set "$@" --certificate=db:SSL,certificate
197         set "$@" --bootstrap-ca-cert=db:SSL,ca_cert
198         start_daemon "$OVSDB_SERVER_PRIORITY" "$OVSDB_SERVER_WRAPPER" "$@" \
199             || return 1
200
201         # Initialize database settings.
202         ovs_vsctl -- init -- set Open_vSwitch . db-version="$schemaver" \
203             || return 1
204         set_system_ids || return 1
205         if test X"$DELETE_BRIDGES" = Xyes; then
206             for bridge in `ovs_vsctl list-br`; do
207         ovs_vsctl del-br $bridge
208             done
209         fi
210     fi
211 }
212
213 start_forwarding () {
214     check_force_cores
215
216     insert_mod_if_required || return 1
217
218     if daemon_is_running ovs-vswitchd; then
219         log_success_msg "ovs-vswitchd is already running"
220     else
221         # Increase the limit on the number of open file descriptors.
222         # ovs-vswitchd needs 16 per datapath, plus a few extra, so this
223         # should allow for 256 (or more) bridges.
224         ulimit -n 5000
225
226             # Start ovs-vswitchd.
227             set ovs-vswitchd unix:"$DB_SOCK"
228             set "$@" -vconsole:emer -vsyslog:err -vfile:info
229             if test X"$MLOCKALL" != Xno; then
230                 set "$@" --mlockall
231             fi
232             start_daemon "$OVS_VSWITCHD_PRIORITY" "$OVS_VSWITCHD_WRAPPER" "$@"
233     fi
234
235     if daemon_is_running ovs-brcompatd; then
236             log_success_msg "ovs-brcompatd is already running"
237     elif test X"$BRCOMPAT" = Xyes; then
238         set ovs-brcompatd
239             set "$@" -vconsole:emer -vsyslog:err -vfile:info
240             start_daemon "$OVS_BRCOMPATD_PRIORITY" "$OVS_BRCOMPATD_WRAPPER" "$@"
241     fi
242 }
243
244 ## ---- ##
245 ## stop ##
246 ## ---- ##
247
248 stop_ovsdb () {
249     stop_daemon ovsdb-server
250 }
251
252 stop_forwarding () {
253     stop_daemon ovs-brcompatd
254     stop_daemon ovs-vswitchd
255 }
256
257 ## ----------------- ##
258 ## force-reload-kmod ##
259 ## ----------------- ##
260
261 internal_interfaces () {
262     # Outputs a list of internal interfaces:
263     #
264     #   - There is an internal interface for every bridge, whether it
265     #     has an Interface record or not and whether the Interface
266     #     record's 'type' is properly set or not.
267     #
268     #   - There is an internal interface for each Interface record whose
269     #     'type' is 'internal'.
270     #
271     # But ignore interfaces that don't really exist.
272     for d in `(ovs_vsctl --bare \
273                 -- --columns=name find Interface type=internal \
274                     -- list-br) | sort -u`
275     do
276         if test -e "/sys/class/net/$d"; then
277                 printf "%s " "$d"
278             fi
279     done
280 }
281
282 save_interfaces () {
283     "$datadir/scripts/ovs-save" $ifaces > "$script"
284 }
285
286 force_reload_kmod () {
287     ifaces=`internal_interfaces`
288     action "Detected internal interfaces: $ifaces" true
289
290     # Restart the database first, since a large database may take a
291     # while to load, and we want to minimize forwarding disruption.
292     stop_ovsdb
293     start_ovsdb
294
295     stop_forwarding
296
297     script=`mktemp`
298     trap 'rm -f "$script"' 0 1 2 13 15
299     if action "Saving interface configuration" save_interfaces; then
300         :
301     else
302         log_warning_msg "Failed to save configuration, not replacing kernel module"
303         start_forwarding
304         exit 1
305     fi
306     chmod +x "$script"
307
308     for dp in `ovs-dpctl dump-dps`; do
309         action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
310     done
311
312     # try both old and new names in case this is post upgrade
313     if test -e /sys/module/brcompat_mod; then
314         action "Removing brcompat module" rmmod brcompat_mod
315     elif test -e /sys/module/brcompat; then
316         action "Removing brcompat module" rmmod brcompat
317     fi
318     if test -e /sys/module/openvswitch_mod; then
319         action "Removing openvswitch module" rmmod openvswitch_mod
320     elif test -e /sys/module/openvswitch; then
321         action "Removing openvswitch module" rmmod openvswitch
322     fi
323
324     start_forwarding
325
326     action "Restoring interface configuration" "$script"
327     rc=$?
328     if test $rc = 0; then
329         level=debug
330     else
331         level=err
332     fi
333     log="logger -p daemon.$level -t ovs-save"
334     $log "force-reload-kmod interface restore script exited with status $rc:"
335     $log -f "$script"
336
337     "$datadir/scripts/ovs-check-dead-ifs"
338 }
339
340 ## --------------- ##
341 ## enable-protocol ##
342 ## --------------- ##
343
344 enable_protocol () {
345     # Translate the protocol name to a number, because "iptables -n -L" prints
346     # some protocols by name (despite the -n) and therefore we need to look for
347     # both forms.
348     #
349     # (iptables -S output is more uniform but old iptables doesn't have it.)
350     protonum=`grep "^$PROTOCOL[         ]" /etc/protocols | awk '{print $2}'`
351     if expr X"$protonum" : X'[0-9]\{1,\}$' > /dev/null; then :; else
352         log_failure_msg "unknown protocol $PROTOCOL"
353         return 1
354     fi
355
356     name=$PROTOCOL
357     match="(\$2 == \"$PROTOCOL\" || \$2 == $protonum)"
358     insert="iptables -I INPUT -p $PROTOCOL"
359     if test X"$DPORT" != X; then
360         name="$name to port $DPORT"
361         match="$match && /dpt:$DPORT/"
362         insert="$insert --dport $DPORT"
363     fi
364     if test X"$SPORT" != X; then
365         name="$name from port $SPORT"
366         match="$match && /spt:$SPORT/"
367         insert="$insert --sport $SPORT"
368     fi
369     insert="$insert -j ACCEPT"
370
371     if (iptables -n -L INPUT) >/dev/null 2>&1; then
372         if iptables -n -L INPUT | awk "$match { n++ } END { exit n == 0 }"
373         then
374             # There's already a rule for this protocol.  Don't override it.
375             log_success_msg "iptables already has a rule for $name, not explicitly enabling"
376         else
377             action "Enabling $name with iptables" $insert
378         fi
379     elif (iptables --version) >/dev/null 2>&1; then
380         action "cannot list iptables rules, not adding a rule for $name"
381     else
382         action "iptables binary not installed, not adding a rule for $name"
383     fi
384 }
385
386 ## ---- ##
387 ## main ##
388 ## ---- ##
389
390 set_defaults () {
391     SYSTEM_ID=
392
393     DELETE_BRIDGES=no
394     BRCOMPAT=no
395
396     DAEMON_CWD=/
397     FORCE_COREFILES=yes
398     MLOCKALL=yes
399     OVSDB_SERVER_PRIORITY=-10
400     OVS_VSWITCHD_PRIORITY=-10
401     OVS_BRCOMPATD_PRIORITY=-10
402     OVSDB_SERVER_WRAPPER=
403     OVS_VSWITCHD_WRAPPER=
404     OVS_BRCOMPATD_WRAPPER=
405
406     DB_FILE=$dbdir/conf.db
407     DB_SOCK=$rundir/db.sock
408     DB_SCHEMA=$datadir/vswitch.ovsschema
409
410     PROTOCOL=gre
411     DPORT=
412     SPORT=
413
414     type_file=$etcdir/system-type.conf
415     version_file=$etcdir/system-version.conf
416
417     if test -e "$type_file" ; then
418         SYSTEM_TYPE=`cat $type_file`
419         SYSTEM_VERSION=`cat $version_file`
420     elif (lsb_release --id) >/dev/null 2>&1; then
421         SYSTEM_TYPE=`lsb_release --id -s`
422         system_release=`lsb_release --release -s`
423         system_codename=`lsb_release --codename -s`
424         SYSTEM_VERSION="${system_release}-${system_codename}"
425     else
426         SYSTEM_TYPE=unknown
427         SYSTEM_VERSION=unknown
428     fi
429 }
430
431 usage () {
432     set_defaults
433     cat <<EOF
434 $0: controls Open vSwitch daemons
435 usage: $0 [OPTIONS] COMMAND
436
437 This program is intended to be invoked internally by Open vSwitch startup
438 scripts.  System administrators should not normally invoke it directly.
439
440 Commands:
441   start              start Open vSwitch daemons
442   stop               stop Open vSwitch daemons
443   status             check whether Open vSwitch daemons are running
444   version            print versions of Open vSwitch daemons
445   load-kmod          insert modules if not already present
446   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
447                      module, reload kernel module, start OVS, restore state
448   enable-protocol    enable protocol specified in options with iptables
449   help               display this help message
450
451 One of the following options is required for "start" and "force-reload-kmod":
452   --system-id=UUID   set specific ID to uniquely identify this system
453   --system-id=random  use a random but persistent UUID to identify this system
454
455 Other important options for "start" and "force-reload-kmod":
456   --system-type=TYPE  set system type (e.g. "XenServer")
457   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
458   --external-id="key=value"
459                      add given key-value pair to Open_vSwitch external-ids
460   --delete-bridges   delete all bridges just before starting ovs-vswitchd
461
462 Less important options for "start" and "force-reload-kmod":
463   --daemon-cwd=DIR               set working dir for OVS daemons (default: $DAEMON_CWD)
464   --no-force-corefiles           do not force on core dumps for OVS daemons
465   --no-mlockall                  do not lock all of ovs-vswitchd into memory
466   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
467   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
468   --ovs-brcompatd-priority=NICE  set ovs-brcompatd's niceness (default: $OVS_BRCOMPATD_PRIORITY)
469
470 Debugging options for "start" and "force-reload-kmod":
471   --ovsdb-server-wrapper=WRAPPER
472   --ovs-vswitchd-wrapper=WRAPPER
473   --ovs-vswitchd-wrapper=WRAPPER
474      run specified daemon under WRAPPER (either 'valgrind' or 'strace')
475
476 Options for "start", "force-reload-kmod", "load-kmod", "status", and "version":
477   --brcompat         enable Linux bridge compatibility module and daemon
478
479 File location options:
480   --db-file=FILE     database file name (default: $DB_FILE)
481   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
482   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
483
484 Options for "enable-protocol":
485   --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
486   --sport=PORT       source port to match (for tcp or udp protocol)
487   --dport=PORT       ddestination port to match (for tcp or udp protocol)
488
489 Other options:
490   -h, --help                  display this help message
491   -V, --version               display version information
492
493 Default directories with "configure" option and environment variable override:
494   logs: @LOGDIR@ (--with-logdir, OVS_LOGDIR)
495   pidfiles and sockets: @RUNDIR@ (--with-rundir, OVS_RUNDIR)
496   conf.db: @DBDIR@ (--with-dbdir, OVS_DBDIR)
497   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
498   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
499   user binaries: @bindir@ (--bindir, OVS_BINDIR)
500   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
501
502 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
503 EOF
504
505     exit 0
506 }
507
508 set_option () {
509     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
510     eval set=\${$var+yes}
511     eval old_value=\$$var
512     if test X$set = X || \
513         (test $type = bool && \
514         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
515         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
516         return
517     fi
518     eval $var=\$value
519 }
520
521 daemons () {
522     echo ovsdb-server ovs-vswitchd
523     if test X"$BRCOMPAT" = Xyes; then
524         echo ovs-brcompatd
525     fi
526 }
527
528 set_defaults
529 extra_ids=
530 command=
531 for arg
532 do
533     case $arg in
534         -h | --help)
535             usage
536             ;;
537         -V | --version)
538             echo "$0 (Open vSwitch) $VERSION"
539             exit 0
540             ;;
541         --external-id=*)
542             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
543             case $value in
544                 *=*)
545                     extra_ids="$extra_ids external-ids:$value"
546                     ;;
547                 *)
548                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
549                     exit 1
550                     ;;
551             esac
552             ;;
553         --[a-z]*=*)
554             option=`expr X"$arg" : 'X--\([^=]*\)'`
555             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
556             type=string
557             set_option
558             ;;
559         --no-[a-z]*)
560             option=`expr X"$arg" : 'X--no-\(.*\)'`
561             value=no
562             type=bool
563             set_option
564             ;;
565         --[a-z]*)
566             option=`expr X"$arg" : 'X--\(.*\)'`
567             value=yes
568             type=bool
569             set_option
570             ;;
571         -*)
572             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
573             exit 1
574             ;;
575         *)
576             if test X"$command" = X; then
577                 command=$arg
578             else
579                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
580                 exit 1
581             fi
582             ;;
583     esac
584 done
585 case $command in
586     start)
587         start_ovsdb
588         start_forwarding
589         ;;
590     stop)
591         stop_forwarding
592         stop_ovsdb
593         ;;
594     status)
595         rc=0
596         for daemon in `daemons`; do
597             daemon_status $daemon || rc=$?
598         done
599         exit $rc
600         ;;
601     version)
602         for daemon in `daemons`; do
603             $daemon --version
604         done
605         ;;
606     force-reload-kmod)
607             force_reload_kmod
608         ;;
609     load-kmod)
610         insert_mod_if_required
611         ;;
612     enable-protocol)
613         enable_protocol
614         ;;
615     help)
616         usage
617         ;;
618     '')
619         echo >&2 "$0: missing command name (use --help for help)"
620         exit 1
621         ;;
622     *)
623         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
624         exit 1
625         ;;
626 esac
627