01741e755b7141ed33cea8e42baf97cbb9eb04bb
[sliver-openvswitch.git] / utilities / ovs-ctl.in
1 #! /bin/sh
2 # Copyright (C) 2009, 2010, 2011 Nicira Networks, 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.sh" || 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_mod is already loaded then we're done.
35     test -e /sys/module/openvswitch_mod && return 0
36
37     # Load openvswitch_mod.  If that's successful then we're done.
38     action "Inserting openvswitch module" modprobe openvswitch_mod && return 0
39
40     # If the bridge module is loaded, then that might be blocking
41     # openvswitch_mod.  Try to unload it, if there are no bridges.
42     test -e /sys/module/bridge || return 1
43     bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
44     if test "$bridges" != "*"; then
45         log_warning_msg "not removing bridge module because bridges exist ($bridges)"
46         return 1
47     fi
48     action "removing bridge module" rmmod bridge || return 1
49
50     # Try loading openvswitch_mod again.
51     action "Inserting openvswitch module" modprobe openvswitch_mod
52 }
53
54 insert_brcompat_mod_if_required () {
55     test -e /sys/module/brcompat_mod && return 0
56     action "Inserting brcompat module" modprobe brcompat_mod
57 }
58
59 ovs_vsctl () {
60     ovs-vsctl --no-wait --timeout=5 "$@"
61 }
62
63 ovsdb_tool () {
64     ovsdb-tool -vANY:console:emer "$@"
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 start () {
159     if test X"$FORCE_COREFILES" = Xyes; then
160         ulimit -Sc 67108864
161     fi
162
163     insert_openvswitch_mod_if_required || return 1
164     if test X"$BRCOMPAT" = Xyes; then
165         insert_brcompat_mod_if_required || return 1
166     fi
167
168     if daemon_is_running ovsdb-server; then
169         log_success_msg "ovsdb-server is already running"
170     else
171         # Create initial database or upgrade database schema.
172         upgrade_db || return 1
173
174         # Start ovsdb-server.
175         set ovsdb-server "$DB_FILE"
176         set "$@" -vANY:CONSOLE:EMER -vANY:SYSLOG:ERR -vANY:FILE:INFO
177         set "$@" --remote=punix:"$DB_SOCK"
178         set "$@" --remote=db:Open_vSwitch,manager_options
179         set "$@" --private-key=db:SSL,private_key
180         set "$@" --certificate=db:SSL,certificate
181         set "$@" --bootstrap-ca-cert=db:SSL,ca_cert
182         start_daemon "$OVSDB_SERVER_PRIORITY" "$@" || return 1
183
184         # Initialize database settings.
185         ovs_vsctl -- init -- set Open_vSwitch . db-version="$schemaver" \
186             || return 1
187         set_system_ids || return 1
188         if test X"$DELETE_BRIDGES" = Xyes; then
189             for bridge in `ovs_vsctl list-br`; do
190                 ovs_vsctl del-br $bridge
191             done
192         fi
193     fi
194
195     if daemon_is_running ovs-vswitchd; then
196         log_success_msg "ovs-vswitchd is already running"
197     else
198         # Increase the limit on the number of open file descriptors since
199         # ovs-vswitchd needs a few per bridge
200         ulimit -n 4096
201
202         # Start ovs-vswitchd.
203         set ovs-vswitchd unix:"$DB_SOCK"
204         set "$@" -vANY:CONSOLE:EMER -vANY:SYSLOG:ERR -vANY:FILE:INFO
205         if test X"$MLOCKALL" != Xno; then
206             set "$@" --mlockall
207         fi
208         start_daemon "$OVS_VSWITCHD_PRIORITY" "$@"
209     fi
210
211     if daemon_is_running ovs-brcompatd; then
212         log_success_msg "ovs-brcompatd is already running"
213     elif test X"$BRCOMPAT" = Xyes; then
214         set ovs-brcompatd
215         set "$@" -vANY:CONSOLE:EMER -vANY:SYSLOG:ERR -vANY:FILE:INFO
216         start_daemon "$OVS_BRCOMPATD_PRIORITY" "$@"
217     fi
218 }
219
220 ## ---- ##
221 ## stop ##
222 ## ---- ##
223
224 stop () {
225     stop_daemon ovs-brcompatd
226     stop_daemon ovs-vswitchd
227     stop_daemon ovsdb-server
228 }
229
230 ## ----------------- ##
231 ## force-reload-kmod ##
232 ## ----------------- ##
233
234 internal_interfaces () {
235     # Outputs a list of internal interfaces:
236     #
237     #   - There is an internal interface for every bridge, whether it
238     #     has an Interface record or not and whether the Interface
239     #     record's 'type' is properly set or not.
240     #
241     #   - There is an internal interface for each Interface record whose
242     #     'type' is 'internal'.
243     #
244     # But ignore interfaces that don't really exist.
245     for d in `(ovs_vsctl --bare \
246                 -- --columns=name find Interface type=internal \
247                 -- list-br) | sort -u`
248     do
249         if test -e "/sys/class/net/$d"; then
250             printf "%s " "$d"
251         fi
252     done
253 }
254
255 save_interfaces () {
256     "$datadir/scripts/ovs-save" $ifaces > "$script"
257 }
258
259 force_reload_kmod () {
260     ifaces=`internal_interfaces`
261     action "Detected internal interfaces: $ifaces" true
262
263     stop
264
265     script=`mktemp`
266     trap 'rm -f "$script"' 0 1 2 13 15
267     if action "Saving interface configuration" save_interfaces; then
268         :
269     else
270         log_warning_msg "Failed to save configuration, not replacing kernel module"
271         start
272         exit 1
273     fi
274     chmod +x "$script"
275
276     for dp in `ovs-dpctl dump-dps`; do
277         action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
278     done
279
280     if test -e /sys/module/brcompat_mod; then
281         action "Removing brcompat module" rmmod brcompat_mod
282     fi
283     if test -e /sys/module/openvswitch_mod; then
284         action "Removing openvswitch module" rmmod openvswitch_mod
285     fi
286
287     start
288
289     action "Restoring interface configuration" "$script"
290     rc=$?
291     if test $rc = 0; then
292         level=debug
293     else
294         level=err
295     fi
296     log="logger -p daemon.$level -t ovs-save"
297     $log "force-reload-kmod interface restore script exited with status $rc:"
298     $log -f "$script"
299 }
300
301 ## --------------- ##
302 ## enable-protocol ##
303 ## --------------- ##
304
305 enable_protocol () {
306     # Translate the protocol name to a number, because "iptables -n -L" prints
307     # some protocols by name (despite the -n) and therefore we need to look for
308     # both forms.
309     #
310     # (iptables -S output is more uniform but old iptables doesn't have it.)
311     protonum=`grep "^$PROTOCOL[         ]" /etc/protocols | awk '{print $2}'`
312     if expr X"$protonum" : X'[0-9]\{1,\}$' > /dev/null; then :; else
313         log_failure_msg "unknown protocol $PROTOCOL"
314         return 1
315     fi
316
317     name=$PROTOCOL
318     match="(\$2 == \"$PROTOCOL\" || \$2 == $protonum)"
319     insert="iptables -I INPUT -p $PROTOCOL"
320     if test X"$DPORT" != X; then
321         name="$name to port $DPORT"
322         match="$match && /dpt:$DPORT/"
323         insert="$insert --dport $DPORT"
324     fi
325     if test X"$SPORT" != X; then
326         name="$name from port $SPORT"
327         match="$match && /spt:$SPORT/"
328         insert="$insert --sport $SPORT"
329     fi
330     insert="$insert -j ACCEPT"
331
332     if (iptables -n -L INPUT) >/dev/null 2>&1; then
333         if iptables -n -L INPUT | awk "$match { n++ } END { exit n == 0 }"
334         then
335             # There's already a rule for this protocol.  Don't override it.
336             log_success_msg "iptables already has a rule for $name, not explicitly enabling"
337         else
338             action "Enabling $name with iptables" $insert
339         fi
340     elif (iptables --version) >/dev/null 2>&1; then
341         action "cannot list iptables rules, not adding a rule for $name"
342     else
343         action "iptables binary not installed, not adding a rule for $name"
344     fi
345 }
346
347 ## ---- ##
348 ## main ##
349 ## ---- ##
350
351 set_defaults () {
352     SYSTEM_ID=
353
354     DELETE_BRIDGES=no
355     BRCOMPAT=no
356
357     DAEMON_CWD=/
358     FORCE_COREFILES=yes
359     MLOCKALL=yes
360     OVSDB_SERVER_PRIORITY=-10
361     OVS_VSWITCHD_PRIORITY=-10
362     OVS_BRCOMPATD_PRIORITY=-10
363
364     DB_FILE=$etcdir/conf.db
365     DB_SOCK=$rundir/db.sock
366     DB_SCHEMA=$datadir/vswitch.ovsschema
367
368     PROTOCOL=gre
369     DPORT=
370     SPORT=
371
372     if (lsb_release --id) >/dev/null 2>&1; then
373         SYSTEM_TYPE=`lsb_release --id -s`
374         system_release=`lsb_release --release -s`
375         system_codename=`lsb_release --codename -s`
376         SYSTEM_VERSION="${system_release}-${system_codename}"
377     else
378         SYSTEM_TYPE=unknown
379         SYSTEM_VERSION=unknown
380     fi
381 }
382
383 usage () {
384     set_defaults
385     cat <<EOF
386 $0: controls Open vSwitch daemons
387 usage: $0 [OPTIONS] COMMAND
388
389 This program is intended to be invoked internally by Open vSwitch startup
390 scripts.  System administrators should not normally invoke it directly.
391
392 Commands:
393   start              start Open vSwitch daemons
394   stop               stop Open vSwitch daemons
395   status             check whether Open vSwitch daemons are running
396   version            print versions of Open vSwitch daemons
397   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
398                      module, reload kernel module, start OVS, restore state
399   enable-protocol    enable protocol specified in options with iptables
400   help               display this help message
401
402 One of the following options is required for "start" and "force-reload-kmod":
403   --system-id=UUID   set specific ID to uniquely identify this system
404   --system-id=random  use a random but persistent UUID to identify this system
405
406 Other important options for "start" and "force-reload-kmod":
407   --system-type=TYPE  set system type (e.g. "XenServer")
408   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
409   --external-id="key=value"
410                      add given key-value pair to Open_vSwitch external-ids
411   --delete-bridges   delete all bridges just before starting ovs-vswitchd
412
413 Less important options for "start" and "force-reload-kmod":
414   --daemon-cwd=DIR               set working dir for OVS daemons (default: $DAEMON_CWD)
415   --no-force-corefiles           do not force on core dumps for OVS daemons
416   --no-mlockall                  do not lock all of ovs-vswitchd into memory
417   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
418   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
419   --ovs-brcompatd-priority=NICE  set ovs-brcompatd's niceness (default: $OVS_BRCOMPATD_PRIORITY)
420
421 Options for "start", "force-reload-kmod", "status", and "version":
422   --brcompat         enable Linux bridge compatibility module and daemon
423
424 File location options:
425   --db-file=FILE     database file name (default: $DB_FILE)
426   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
427   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
428
429 Options for "enable-protocol":
430   --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
431   --sport=PORT       source port to match (for tcp or udp protocol)
432   --dport=PORT       ddestination port to match (for tcp or udp protocol)
433
434 Other options:
435   -h, --help                  display this help message
436   -V, --version               display version information
437
438 Default directories with "configure" option and environment variable override:
439   logs: @LOGDIR@ (--log-dir, OVS_LOGDIR)
440   pidfiles and sockets: @RUNDIR@ (--run-dir, OVS_RUNDIR)
441   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
442   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
443   user binaries: @bindir@ (--bindir, OVS_BINDIR)
444   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
445
446 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
447 EOF
448
449     exit 0
450 }
451
452 set_option () {
453     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
454     eval set=\${$var+yes}
455     eval old_value=\$$var
456     if test X$set = X || \
457         (test $type = bool && \
458         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
459         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
460         return
461     fi
462     eval $var=\$value
463 }
464
465 daemons () {
466     echo ovsdb-server ovs-vswitchd
467     if test X"$BRCOMPAT" = Xyes; then
468         echo ovs-brcompatd
469     fi
470 }
471
472 set_defaults
473 extra_ids=
474 command=
475 for arg
476 do
477     case $arg in
478         -h | --help)
479             usage
480             ;;
481         -V | --version)
482             echo "$0 (Open vSwitch) $VERSION$BUILDNR"
483             exit 0
484             ;;
485         --external-id=*)
486             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
487             case $value in
488                 *=*)
489                     extra_ids="$extra_ids external-ids:$value"
490                     ;;
491                 *)
492                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
493                     exit 1
494                     ;;
495             esac
496             ;;
497         --[a-z]*=*)
498             option=`expr X"$arg" : 'X--\([^=]*\)'`
499             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
500             type=string
501             set_option
502             ;;
503         --no-[a-z]*)
504             option=`expr X"$arg" : 'X--no-\(.*\)'`
505             value=no
506             type=bool
507             set_option
508             ;;
509         --[a-z]*)
510             option=`expr X"$arg" : 'X--\(.*\)'`
511             value=yes
512             type=bool
513             set_option
514             ;;
515         -*)
516             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
517             exit 1
518             ;;
519         *)
520             if test X"$command" = X; then
521                 command=$arg
522             else
523                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
524                 exit 1
525             fi
526             ;;
527     esac
528 done
529 case $command in
530     start)
531         start
532         ;;
533     stop)
534         stop
535         ;;
536     status)
537         rc=0
538         for daemon in `daemons`; do
539             daemon_status $daemon || rc=$?
540         done
541         exit $rc
542         ;;
543     version)
544         for daemon in `daemons`; do
545             $daemon --version
546         done
547         ;;
548     force-reload-kmod)
549         force_reload_kmod
550         ;;
551     enable-protocol)
552         enable_protocol
553         ;;
554     help)
555         usage
556         ;;
557     '')
558         echo >&2 "$0: missing command name (use --help for help)"
559         exit 1
560         ;;
561     *)
562         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
563         exit 1
564         ;;
565 esac
566