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