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