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