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