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