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