87e7a86dd99001c869d833a9b2e0ede6dc3687b1
[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:Open_vSwitch,SSL,private_key
210         set "$@" --certificate=db:Open_vSwitch,SSL,certificate
211         set "$@" --bootstrap-ca-cert=db:Open_vSwitch,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_flows () {
297    if set X `ovs_vsctl -- --real list-br`; then
298         shift
299         if "$datadir/scripts/ovs-save" save-flows "$@" > "$script_flows"; then
300             chmod +x "$script_flows"
301             return 0
302         fi
303     fi
304     script_flows=
305     return 1
306 }
307
308 save_interfaces () {
309     "$datadir/scripts/ovs-save" save-interfaces ${ifaces} \
310         > "${script_interfaces}"
311 }
312
313 restore_flows () {
314     [ -n "${script_flows}" ] && \
315         action "Restoring saved flows" "${script_flows}"
316 }
317
318 force_reload_kmod () {
319     ifaces=`internal_interfaces`
320     action "Detected internal interfaces: $ifaces" true
321
322     script_interfaces=`mktemp`
323     script_flows=`mktemp`
324     trap 'rm -f "${script_interfaces}" "${script_flows}" ' 0
325
326     action "Saving flows" save_flows
327
328     # Restart the database first, since a large database may take a
329     # while to load, and we want to minimize forwarding disruption.
330     stop_ovsdb
331     start_ovsdb
332
333     stop_forwarding
334
335     if action "Saving interface configuration" save_interfaces; then
336         :
337     else
338         log_warning_msg "Failed to save configuration, not replacing kernel module"
339         start_forwarding
340         exit 1
341     fi
342     chmod +x "$script_interfaces"
343
344     for dp in `ovs-dpctl dump-dps`; do
345         action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
346     done
347
348     # try both old and new names in case this is post upgrade
349     if test -e /sys/module/brcompat_mod; then
350         action "Removing brcompat module" rmmod brcompat_mod
351     elif test -e /sys/module/brcompat; then
352         action "Removing brcompat module" rmmod brcompat
353     fi
354     if test -e /sys/module/openvswitch_mod; then
355         action "Removing openvswitch module" rmmod openvswitch_mod
356     elif test -e /sys/module/openvswitch; then
357         action "Removing openvswitch module" rmmod openvswitch
358     fi
359
360     start_forwarding
361
362     restore_flows
363
364     action "Restoring interface configuration" "$script_interfaces"
365     rc=$?
366     if test $rc = 0; then
367         level=debug
368     else
369         level=err
370     fi
371     log="logger -p daemon.$level -t ovs-save"
372     $log "force-reload-kmod interface restore script exited with status $rc:"
373     $log -f "$script_interfaces"
374
375     "$datadir/scripts/ovs-check-dead-ifs"
376 }
377
378 ## ------- ##
379 ## restart ##
380 ## ------- ##
381
382 restart () {
383     if daemon_is_running ovsdb-server && daemon_is_running ovs-vswitchd; then
384         script_flows=`mktemp`
385         trap 'rm -f "${script_flows}"' 0
386
387         action "Saving flows" save_flows
388     fi
389
390     # Restart the database first, since a large database may take a
391     # while to load, and we want to minimize forwarding disruption.
392     stop_ovsdb
393     start_ovsdb
394
395     stop_forwarding
396     start_forwarding
397
398     # Restore the saved flows. Do not return error if restore fails.
399     restore_flows || true
400 }
401
402 ## --------------- ##
403 ## enable-protocol ##
404 ## --------------- ##
405
406 enable_protocol () {
407     # Translate the protocol name to a number, because "iptables -n -L" prints
408     # some protocols by name (despite the -n) and therefore we need to look for
409     # both forms.
410     #
411     # (iptables -S output is more uniform but old iptables doesn't have it.)
412     protonum=`grep "^$PROTOCOL[         ]" /etc/protocols | awk '{print $2}'`
413     if expr X"$protonum" : X'[0-9]\{1,\}$' > /dev/null; then :; else
414         log_failure_msg "unknown protocol $PROTOCOL"
415         return 1
416     fi
417
418     name=$PROTOCOL
419     match="(\$2 == \"$PROTOCOL\" || \$2 == $protonum)"
420     insert="iptables -I INPUT -p $PROTOCOL"
421     if test X"$DPORT" != X; then
422         name="$name to port $DPORT"
423         match="$match && /dpt:$DPORT/"
424         insert="$insert --dport $DPORT"
425     fi
426     if test X"$SPORT" != X; then
427         name="$name from port $SPORT"
428         match="$match && /spt:$SPORT/"
429         insert="$insert --sport $SPORT"
430     fi
431     insert="$insert -j ACCEPT"
432
433     if (iptables -n -L INPUT) >/dev/null 2>&1; then
434         if iptables -n -L INPUT | awk "$match { n++ } END { exit n == 0 }"
435         then
436             # There's already a rule for this protocol.  Don't override it.
437             log_success_msg "iptables already has a rule for $name, not explicitly enabling"
438         else
439             action "Enabling $name with iptables" $insert
440         fi
441     elif (iptables --version) >/dev/null 2>&1; then
442         action "cannot list iptables rules, not adding a rule for $name"
443     else
444         action "iptables binary not installed, not adding a rule for $name"
445     fi
446 }
447
448 ## ---- ##
449 ## main ##
450 ## ---- ##
451
452 set_defaults () {
453     SYSTEM_ID=
454
455     DELETE_BRIDGES=no
456     BRCOMPAT=no
457
458     DAEMON_CWD=/
459     FORCE_COREFILES=yes
460     MLOCKALL=yes
461     OVSDB_SERVER_PRIORITY=-10
462     OVS_VSWITCHD_PRIORITY=-10
463     OVS_BRCOMPATD_PRIORITY=-10
464     OVSDB_SERVER_WRAPPER=
465     OVS_VSWITCHD_WRAPPER=
466     OVS_BRCOMPATD_WRAPPER=
467
468     DB_FILE=$dbdir/conf.db
469     DB_SOCK=$rundir/db.sock
470     DB_SCHEMA=$datadir/vswitch.ovsschema
471     EXTRA_DBS=
472
473     PROTOCOL=gre
474     DPORT=
475     SPORT=
476
477     type_file=$etcdir/system-type.conf
478     version_file=$etcdir/system-version.conf
479
480     if test -e "$type_file" ; then
481         SYSTEM_TYPE=`cat $type_file`
482         SYSTEM_VERSION=`cat $version_file`
483     elif (lsb_release --id) >/dev/null 2>&1; then
484         SYSTEM_TYPE=`lsb_release --id -s`
485         system_release=`lsb_release --release -s`
486         system_codename=`lsb_release --codename -s`
487         SYSTEM_VERSION="${system_release}-${system_codename}"
488     else
489         SYSTEM_TYPE=unknown
490         SYSTEM_VERSION=unknown
491     fi
492 }
493
494 usage () {
495     set_defaults
496     cat <<EOF
497 $0: controls Open vSwitch daemons
498 usage: $0 [OPTIONS] COMMAND
499
500 This program is intended to be invoked internally by Open vSwitch startup
501 scripts.  System administrators should not normally invoke it directly.
502
503 Commands:
504   start              start Open vSwitch daemons
505   stop               stop Open vSwitch daemons
506   restart            stop and start Open vSwitch daemons
507   status             check whether Open vSwitch daemons are running
508   version            print versions of Open vSwitch daemons
509   load-kmod          insert modules if not already present
510   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
511                      module, reload kernel module, start OVS, restore state
512   enable-protocol    enable protocol specified in options with iptables
513   help               display this help message
514
515 One of the following options is required for "start", "restart" and "force-reload-kmod":
516   --system-id=UUID   set specific ID to uniquely identify this system
517   --system-id=random  use a random but persistent UUID to identify this system
518
519 Other important options for "start", "restart" and "force-reload-kmod":
520   --system-type=TYPE  set system type (e.g. "XenServer")
521   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
522   --external-id="key=value"
523                      add given key-value pair to Open_vSwitch external-ids
524   --delete-bridges   delete all bridges just before starting ovs-vswitchd
525
526 Less important options for "start", "restart" and "force-reload-kmod":
527   --daemon-cwd=DIR               set working dir for OVS daemons (default: $DAEMON_CWD)
528   --no-force-corefiles           do not force on core dumps for OVS daemons
529   --no-mlockall                  do not lock all of ovs-vswitchd into memory
530   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
531   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
532   --ovs-brcompatd-priority=NICE  set ovs-brcompatd's niceness (default: $OVS_BRCOMPATD_PRIORITY)
533
534 Debugging options for "start", "restart" and "force-reload-kmod":
535   --ovsdb-server-wrapper=WRAPPER
536   --ovs-vswitchd-wrapper=WRAPPER
537   --ovs-vswitchd-wrapper=WRAPPER
538      run specified daemon under WRAPPER (either 'valgrind' or 'strace')
539
540 Options for "start", "restart", "force-reload-kmod", "load-kmod", "status", and "version":
541   --brcompat         enable Linux bridge compatibility module and daemon
542
543 File location options:
544   --db-file=FILE     database file name (default: $DB_FILE)
545   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
546   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
547
548 Options for "enable-protocol":
549   --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
550   --sport=PORT       source port to match (for tcp or udp protocol)
551   --dport=PORT       ddestination port to match (for tcp or udp protocol)
552
553 Other options:
554   -h, --help                  display this help message
555   -V, --version               display version information
556
557 Default directories with "configure" option and environment variable override:
558   logs: @LOGDIR@ (--with-logdir, OVS_LOGDIR)
559   pidfiles and sockets: @RUNDIR@ (--with-rundir, OVS_RUNDIR)
560   conf.db: @DBDIR@ (--with-dbdir, OVS_DBDIR)
561   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
562   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
563   user binaries: @bindir@ (--bindir, OVS_BINDIR)
564   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
565
566 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
567 EOF
568
569     exit 0
570 }
571
572 set_option () {
573     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
574     eval set=\${$var+yes}
575     eval old_value=\$$var
576     if test X$set = X || \
577         (test $type = bool && \
578         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
579         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
580         return
581     fi
582     eval $var=\$value
583 }
584
585 daemons () {
586     echo ovsdb-server ovs-vswitchd
587     if test X"$BRCOMPAT" = Xyes; then
588         echo ovs-brcompatd
589     fi
590 }
591
592 set_defaults
593 extra_ids=
594 command=
595 for arg
596 do
597     case $arg in
598         -h | --help)
599             usage
600             ;;
601         -V | --version)
602             echo "$0 (Open vSwitch) $VERSION"
603             exit 0
604             ;;
605         --external-id=*)
606             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
607             case $value in
608                 *=*)
609                     extra_ids="$extra_ids external-ids:$value"
610                     ;;
611                 *)
612                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
613                     exit 1
614                     ;;
615             esac
616             ;;
617         --[a-z]*=*)
618             option=`expr X"$arg" : 'X--\([^=]*\)'`
619             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
620             type=string
621             set_option
622             ;;
623         --no-[a-z]*)
624             option=`expr X"$arg" : 'X--no-\(.*\)'`
625             value=no
626             type=bool
627             set_option
628             ;;
629         --[a-z]*)
630             option=`expr X"$arg" : 'X--\(.*\)'`
631             value=yes
632             type=bool
633             set_option
634             ;;
635         -*)
636             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
637             exit 1
638             ;;
639         *)
640             if test X"$command" = X; then
641                 command=$arg
642             else
643                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
644                 exit 1
645             fi
646             ;;
647     esac
648 done
649 case $command in
650     start)
651         start_ovsdb
652         start_forwarding
653         ;;
654     stop)
655         stop_forwarding
656         stop_ovsdb
657         ;;
658     restart)
659         restart
660         ;;
661     status)
662         rc=0
663         for daemon in `daemons`; do
664             daemon_status $daemon || rc=$?
665         done
666         exit $rc
667         ;;
668     version)
669         for daemon in `daemons`; do
670             $daemon --version
671         done
672         ;;
673     force-reload-kmod)
674             force_reload_kmod
675         ;;
676     load-kmod)
677         insert_mod_if_required
678         ;;
679     enable-protocol)
680         enable_protocol
681         ;;
682     help)
683         usage
684         ;;
685     '')
686         echo >&2 "$0: missing command name (use --help for help)"
687         exit 1
688         ;;
689     *)
690         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
691         exit 1
692         ;;
693 esac