9bdb3df1b21c9de82f4241fe89990dd5623e0254
[sliver-openvswitch.git] / utilities / ovs-ctl.in
1 #! /bin/sh
2 # Copyright (C) 2009, 2010, 2011, 2012 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" || 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     if test -e /sys/module/bridge; then
56         log_warning_msg "bridge module is loaded, not loading brcompat_mod"
57         return 1
58     fi
59     test -e /sys/module/brcompat_mod && return 0
60     action "Inserting brcompat module" modprobe brcompat_mod
61 }
62
63 insert_mod_if_required () {
64     insert_openvswitch_mod_if_required || return 1
65     if test X"$BRCOMPAT" = Xyes; then
66         insert_brcompat_mod_if_required || return 1
67     fi
68 }
69
70 ovs_vsctl () {
71     ovs-vsctl --no-wait --timeout=5 "$@"
72 }
73
74 ovsdb_tool () {
75     ovsdb-tool -vANY:console:off "$@"
76 }
77
78 create_db () {
79     action "Creating empty database $DB_FILE" ovsdb_tool create "$DB_FILE" "$DB_SCHEMA"
80 }
81
82 upgrade_db () {
83     schemaver=`ovsdb_tool schema-version "$DB_SCHEMA"`
84     if test ! -e "$DB_FILE"; then
85         log_warning_msg "$DB_FILE does not exist"
86         install -d -m 755 -o root -g root `dirname $DB_FILE`
87         create_db
88     elif test X"`ovsdb_tool needs-conversion "$DB_FILE" "$DB_SCHEMA"`" != Xno; then
89         # Back up the old version.
90         version=`ovsdb_tool db-version "$DB_FILE"`
91         cksum=`ovsdb_tool db-cksum "$DB_FILE" | awk '{print $1}'`
92         backup=$DB_FILE.backup$version-$cksum
93         action "Backing up database to $backup" cp "$DB_FILE" "$backup" || return 1
94
95         # Compact database.  This is important if the old schema did not enable
96         # garbage collection (i.e. if it did not have any tables with "isRoot":
97         # true) but the new schema does.  In that situation the old database
98         # may contain a transaction that creates a record followed by a
99         # transaction that creates the first use of the record.  Replaying that
100         # series of transactions against the new database schema (as "convert"
101         # does) would cause the record to be dropped by the first transaction,
102         # then the second transaction would cause a referential integrity
103         # failure (for a strong reference).
104         #
105         # Errors might occur on an Open vSwitch downgrade if ovsdb-tool doesn't
106         # understand some feature of the schema used in the OVSDB version that
107         # we're downgrading from, so we don't give up on error.
108         action "Compacting database" ovsdb_tool compact "$DB_FILE"
109
110         # Upgrade or downgrade schema.
111         if action "Converting database schema" ovsdb_tool convert "$DB_FILE" "$DB_SCHEMA"; then
112             :
113         else
114             log_warning_msg "Schema conversion failed, using empty database instead"
115             rm -f "$DB_FILE"
116             create_db
117         fi
118     fi
119 }
120
121 set_system_ids () {
122     set ovs_vsctl set Open_vSwitch .
123
124     OVS_VERSION=`ovs-vswitchd --version | sed 's/.*) //;1q'`
125     set "$@" ovs-version="$OVS_VERSION"
126
127     case $SYSTEM_ID in
128         random)
129             id_file=$etcdir/system-id.conf
130             uuid_file=$etcdir/install_uuid.conf
131             if test -e "$id_file"; then
132                 SYSTEM_ID=`cat "$id_file"`
133             elif test -e "$uuid_file"; then
134                 # Migrate from old file name.
135                 . "$uuid_file"
136                 SYSTEM_ID=$INSTALLATION_UUID
137                 echo "$SYSTEM_ID" > "$id_file"
138             elif SYSTEM_ID=`uuidgen`; then
139                 echo "$SYSTEM_ID" > "$id_file"
140             else
141                 log_failure_msg "missing uuidgen, could not generate system ID"
142             fi
143             ;;
144
145         '')
146             log_failure_msg "system ID not configured, please use --system-id"
147             ;;
148
149         *)
150             ;;
151     esac
152     set "$@" external-ids:system-id="\"$SYSTEM_ID\""
153
154     if test X"$SYSTEM_TYPE" != X; then
155         set "$@" system-type="\"$SYSTEM_TYPE\""
156     else
157         log_failure_msg "no default system type, please use --system-type"
158     fi
159
160     if test X"$SYSTEM_VERSION" != X; then
161         set "$@" system-version="\"$SYSTEM_VERSION\""
162     else
163         log_failure_msg "no default system version, please use --system-version"
164     fi
165
166     action "Configuring Open vSwitch system IDs" "$@" $extra_ids
167 }
168
169 start () {
170     if test X"$FORCE_COREFILES" = Xyes; then
171         ulimit -Sc 67108864
172     fi
173
174     insert_mod_if_required || return 1
175
176     if daemon_is_running ovsdb-server; then
177         log_success_msg "ovsdb-server is already running"
178     else
179         # Create initial database or upgrade database schema.
180         upgrade_db || return 1
181
182         # Start ovsdb-server.
183         set ovsdb-server "$DB_FILE"
184         set "$@" -vANY:CONSOLE:EMER -vANY:SYSLOG:ERR -vANY:FILE:INFO
185         set "$@" --remote=punix:"$DB_SOCK"
186         set "$@" --remote=db:Open_vSwitch,manager_options
187         set "$@" --private-key=db:SSL,private_key
188         set "$@" --certificate=db:SSL,certificate
189         set "$@" --bootstrap-ca-cert=db:SSL,ca_cert
190         start_daemon "$OVSDB_SERVER_PRIORITY" "$@" || return 1
191
192         # Initialize database settings.
193         ovs_vsctl -- init -- set Open_vSwitch . db-version="$schemaver" \
194             || return 1
195         set_system_ids || return 1
196         if test X"$DELETE_BRIDGES" = Xyes; then
197             for bridge in `ovs_vsctl list-br`; do
198                 ovs_vsctl del-br $bridge
199             done
200         fi
201     fi
202
203     if daemon_is_running ovs-vswitchd; then
204         log_success_msg "ovs-vswitchd is already running"
205     else
206         # Increase the limit on the number of open file descriptors.
207         # ovs-vswitchd needs 16 per datapath, plus a few extra, so this
208         # should allow for 256 (or more) bridges.
209         ulimit -n 5000
210
211         # Start ovs-vswitchd.
212         set ovs-vswitchd unix:"$DB_SOCK"
213         set "$@" -vANY:CONSOLE:EMER -vANY:SYSLOG:ERR -vANY:FILE:INFO
214         if test X"$MLOCKALL" != Xno; then
215             set "$@" --mlockall
216         fi
217         start_daemon "$OVS_VSWITCHD_PRIORITY" "$@"
218     fi
219
220     if daemon_is_running ovs-brcompatd; then
221         log_success_msg "ovs-brcompatd is already running"
222     elif test X"$BRCOMPAT" = Xyes; then
223         set ovs-brcompatd
224         set "$@" -vANY:CONSOLE:EMER -vANY:SYSLOG:ERR -vANY:FILE:INFO
225         start_daemon "$OVS_BRCOMPATD_PRIORITY" "$@"
226     fi
227 }
228
229 ## ---- ##
230 ## stop ##
231 ## ---- ##
232
233 stop () {
234     stop_daemon ovs-brcompatd
235     stop_daemon ovs-vswitchd
236     stop_daemon ovsdb-server
237 }
238
239 ## ----------------- ##
240 ## force-reload-kmod ##
241 ## ----------------- ##
242
243 internal_interfaces () {
244     # Outputs a list of internal interfaces:
245     #
246     #   - There is an internal interface for every bridge, whether it
247     #     has an Interface record or not and whether the Interface
248     #     record's 'type' is properly set or not.
249     #
250     #   - There is an internal interface for each Interface record whose
251     #     'type' is 'internal'.
252     #
253     # But ignore interfaces that don't really exist.
254     for d in `(ovs_vsctl --bare \
255                 -- --columns=name find Interface type=internal \
256                 -- list-br) | sort -u`
257     do
258         if test -e "/sys/class/net/$d"; then
259             printf "%s " "$d"
260         fi
261     done
262 }
263
264 save_interfaces () {
265     "$datadir/scripts/ovs-save" $ifaces > "$script"
266 }
267
268 force_reload_kmod () {
269     ifaces=`internal_interfaces`
270     action "Detected internal interfaces: $ifaces" true
271
272     stop
273
274     script=`mktemp`
275     trap 'rm -f "$script"' 0 1 2 13 15
276     if action "Saving interface configuration" save_interfaces; then
277         :
278     else
279         log_warning_msg "Failed to save configuration, not replacing kernel module"
280         start
281         exit 1
282     fi
283     chmod +x "$script"
284
285     for dp in `ovs-dpctl dump-dps`; do
286         action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
287     done
288
289     if test -e /sys/module/brcompat_mod; then
290         action "Removing brcompat module" rmmod brcompat_mod
291     fi
292     if test -e /sys/module/openvswitch_mod; then
293         action "Removing openvswitch module" rmmod openvswitch_mod
294     fi
295
296     start
297
298     action "Restoring interface configuration" "$script"
299     rc=$?
300     if test $rc = 0; then
301         level=debug
302     else
303         level=err
304     fi
305     log="logger -p daemon.$level -t ovs-save"
306     $log "force-reload-kmod interface restore script exited with status $rc:"
307     $log -f "$script"
308 }
309
310 ## --------------- ##
311 ## enable-protocol ##
312 ## --------------- ##
313
314 enable_protocol () {
315     # Translate the protocol name to a number, because "iptables -n -L" prints
316     # some protocols by name (despite the -n) and therefore we need to look for
317     # both forms.
318     #
319     # (iptables -S output is more uniform but old iptables doesn't have it.)
320     protonum=`grep "^$PROTOCOL[         ]" /etc/protocols | awk '{print $2}'`
321     if expr X"$protonum" : X'[0-9]\{1,\}$' > /dev/null; then :; else
322         log_failure_msg "unknown protocol $PROTOCOL"
323         return 1
324     fi
325
326     name=$PROTOCOL
327     match="(\$2 == \"$PROTOCOL\" || \$2 == $protonum)"
328     insert="iptables -I INPUT -p $PROTOCOL"
329     if test X"$DPORT" != X; then
330         name="$name to port $DPORT"
331         match="$match && /dpt:$DPORT/"
332         insert="$insert --dport $DPORT"
333     fi
334     if test X"$SPORT" != X; then
335         name="$name from port $SPORT"
336         match="$match && /spt:$SPORT/"
337         insert="$insert --sport $SPORT"
338     fi
339     insert="$insert -j ACCEPT"
340
341     if (iptables -n -L INPUT) >/dev/null 2>&1; then
342         if iptables -n -L INPUT | awk "$match { n++ } END { exit n == 0 }"
343         then
344             # There's already a rule for this protocol.  Don't override it.
345             log_success_msg "iptables already has a rule for $name, not explicitly enabling"
346         else
347             action "Enabling $name with iptables" $insert
348         fi
349     elif (iptables --version) >/dev/null 2>&1; then
350         action "cannot list iptables rules, not adding a rule for $name"
351     else
352         action "iptables binary not installed, not adding a rule for $name"
353     fi
354 }
355
356 ## ---- ##
357 ## main ##
358 ## ---- ##
359
360 set_defaults () {
361     SYSTEM_ID=
362
363     DELETE_BRIDGES=no
364     BRCOMPAT=no
365
366     DAEMON_CWD=/
367     FORCE_COREFILES=yes
368     MLOCKALL=yes
369     OVSDB_SERVER_PRIORITY=-10
370     OVS_VSWITCHD_PRIORITY=-10
371     OVS_BRCOMPATD_PRIORITY=-10
372
373     DB_FILE=$etcdir/conf.db
374     DB_SOCK=$rundir/db.sock
375     DB_SCHEMA=$datadir/vswitch.ovsschema
376
377     PROTOCOL=gre
378     DPORT=
379     SPORT=
380
381     type_file=$etcdir/system-type.conf
382     version_file=$etcdir/system-version.conf
383
384     if test -e "$type_file" ; then
385         SYSTEM_TYPE=`cat $type_file`
386         SYSTEM_VERSION=`cat $version_file`
387     elif (lsb_release --id) >/dev/null 2>&1; then
388         SYSTEM_TYPE=`lsb_release --id -s`
389         system_release=`lsb_release --release -s`
390         system_codename=`lsb_release --codename -s`
391         SYSTEM_VERSION="${system_release}-${system_codename}"
392     else
393         SYSTEM_TYPE=unknown
394         SYSTEM_VERSION=unknown
395     fi
396 }
397
398 usage () {
399     set_defaults
400     cat <<EOF
401 $0: controls Open vSwitch daemons
402 usage: $0 [OPTIONS] COMMAND
403
404 This program is intended to be invoked internally by Open vSwitch startup
405 scripts.  System administrators should not normally invoke it directly.
406
407 Commands:
408   start              start Open vSwitch daemons
409   stop               stop Open vSwitch daemons
410   status             check whether Open vSwitch daemons are running
411   version            print versions of Open vSwitch daemons
412   load-kmod          insert modules if not already present
413   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
414                      module, reload kernel module, start OVS, restore state
415   enable-protocol    enable protocol specified in options with iptables
416   help               display this help message
417
418 One of the following options is required for "start" and "force-reload-kmod":
419   --system-id=UUID   set specific ID to uniquely identify this system
420   --system-id=random  use a random but persistent UUID to identify this system
421
422 Other important options for "start" and "force-reload-kmod":
423   --system-type=TYPE  set system type (e.g. "XenServer")
424   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
425   --external-id="key=value"
426                      add given key-value pair to Open_vSwitch external-ids
427   --delete-bridges   delete all bridges just before starting ovs-vswitchd
428
429 Less important options for "start" and "force-reload-kmod":
430   --daemon-cwd=DIR               set working dir for OVS daemons (default: $DAEMON_CWD)
431   --no-force-corefiles           do not force on core dumps for OVS daemons
432   --no-mlockall                  do not lock all of ovs-vswitchd into memory
433   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
434   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
435   --ovs-brcompatd-priority=NICE  set ovs-brcompatd's niceness (default: $OVS_BRCOMPATD_PRIORITY)
436
437 Options for "start", "force-reload-kmod", "load-kmod", "status", and "version":
438   --brcompat         enable Linux bridge compatibility module and daemon
439
440 File location options:
441   --db-file=FILE     database file name (default: $DB_FILE)
442   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
443   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
444
445 Options for "enable-protocol":
446   --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
447   --sport=PORT       source port to match (for tcp or udp protocol)
448   --dport=PORT       ddestination port to match (for tcp or udp protocol)
449
450 Other options:
451   -h, --help                  display this help message
452   -V, --version               display version information
453
454 Default directories with "configure" option and environment variable override:
455   logs: @LOGDIR@ (--log-dir, OVS_LOGDIR)
456   pidfiles and sockets: @RUNDIR@ (--run-dir, OVS_RUNDIR)
457   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
458   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
459   user binaries: @bindir@ (--bindir, OVS_BINDIR)
460   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
461
462 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
463 EOF
464
465     exit 0
466 }
467
468 set_option () {
469     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
470     eval set=\${$var+yes}
471     eval old_value=\$$var
472     if test X$set = X || \
473         (test $type = bool && \
474         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
475         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
476         return
477     fi
478     eval $var=\$value
479 }
480
481 daemons () {
482     echo ovsdb-server ovs-vswitchd
483     if test X"$BRCOMPAT" = Xyes; then
484         echo ovs-brcompatd
485     fi
486 }
487
488 set_defaults
489 extra_ids=
490 command=
491 for arg
492 do
493     case $arg in
494         -h | --help)
495             usage
496             ;;
497         -V | --version)
498             echo "$0 (Open vSwitch) $VERSION$BUILDNR"
499             exit 0
500             ;;
501         --external-id=*)
502             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
503             case $value in
504                 *=*)
505                     extra_ids="$extra_ids external-ids:$value"
506                     ;;
507                 *)
508                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
509                     exit 1
510                     ;;
511             esac
512             ;;
513         --[a-z]*=*)
514             option=`expr X"$arg" : 'X--\([^=]*\)'`
515             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
516             type=string
517             set_option
518             ;;
519         --no-[a-z]*)
520             option=`expr X"$arg" : 'X--no-\(.*\)'`
521             value=no
522             type=bool
523             set_option
524             ;;
525         --[a-z]*)
526             option=`expr X"$arg" : 'X--\(.*\)'`
527             value=yes
528             type=bool
529             set_option
530             ;;
531         -*)
532             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
533             exit 1
534             ;;
535         *)
536             if test X"$command" = X; then
537                 command=$arg
538             else
539                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
540                 exit 1
541             fi
542             ;;
543     esac
544 done
545 case $command in
546     start)
547         start
548         ;;
549     stop)
550         stop
551         ;;
552     status)
553         rc=0
554         for daemon in `daemons`; do
555             daemon_status $daemon || rc=$?
556         done
557         exit $rc
558         ;;
559     version)
560         for daemon in `daemons`; do
561             $daemon --version
562         done
563         ;;
564     force-reload-kmod)
565         force_reload_kmod
566         ;;
567     load-kmod)
568         insert_mod_if_required
569         ;;
570     enable-protocol)
571         enable_protocol
572         ;;
573     help)
574         usage
575         ;;
576     '')
577         echo >&2 "$0: missing command name (use --help for help)"
578         exit 1
579         ;;
580     *)
581         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
582         exit 1
583         ;;
584 esac
585