Refactor initscripts into distro-independent and distro-specific pieces.
[cascardo/ovs.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_modules_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 ovs_vsctl () {
55     ovs-vsctl --no-wait --timeout=5 "$@"
56 }
57
58 ovsdb_tool () {
59     ovsdb-tool -vANY:console:emer "$@"
60 }
61
62 upgrade_db () {
63     schemaver=`ovsdb_tool schema-version "$DB_SCHEMA"`
64     if test ! -e "$DB_FILE"; then
65         log_warning_msg "$DB_FILE does not exist"
66         install -d -m 755 -o root -g root `dirname $DB_FILE`
67
68         action "Creating empty database $DB_FILE" true
69         ovsdb_tool create "$DB_FILE" "$DB_SCHEMA"
70     elif test X"`ovsdb_tool needs-conversion "$DB_FILE" "$DB_SCHEMA"`" != Xno; then
71         # Back up the old version.
72         version=`ovsdb_tool db-version "$DB_FILE"`
73         cksum=`ovsdb_tool db-cksum "$DB_FILE" | awk '{print $1}'`
74         cp "$DB_FILE" "$DB_FILE.backup$version-$cksum"
75
76         # Compact database.  This is important if the old schema did not enable
77         # garbage collection (i.e. if it did not have any tables with "isRoot":
78         # true) but the new schema does.  In that situation the old database
79         # may contain a transaction that creates a record followed by a
80         # transaction that creates the first use of the record.  Replaying that
81         # series of transactions against the new database schema (as "convert"
82         # does) would cause the record to be dropped by the first transaction,
83         # then the second transaction would cause a referential integrity
84         # failure (for a strong reference).
85         ovsdb_tool compact "$DB_FILE"
86
87         # Upgrade or downgrade schema.
88         ovsdb_tool convert "$DB_FILE" "$DB_SCHEMA"
89     fi
90 }
91
92 set_system_ids () {
93     set ovs_vsctl set Open_vSwitch .
94
95     OVS_VERSION=`ovs-vswitchd --version | sed 's/.*) //;1q'`
96     set "$@" ovs-version="$OVS_VERSION"
97
98     case $SYSTEM_ID in
99         random)
100             id_file=$etcdir/system-id.conf
101             uuid_file=$etcdir/install_uuid.conf
102             if test -e "$id_file"; then
103                 SYSTEM_ID=`cat "$id_file"`
104             elif test -e "$uuid_file"; then
105                 # Migrate from old file name.
106                 . "$uuid_file"
107                 SYSTEM_ID=$INSTALLATION_UUID
108                 echo "$SYSTEM_ID" > "$id_file"
109             elif SYSTEM_ID=`uuidgen`; then
110                 echo "$SYSTEM_ID" > "$id_file"
111             else
112                 log_failure_msg "missing uuidgen, could not generate system ID"
113             fi
114             ;;
115
116         '')
117             log_failure_msg "system ID not configured, please use --system-id"
118             ;;
119
120         *)
121             ;;
122     esac
123     set "$@" external-ids:system-id="\"$SYSTEM_ID\""
124
125     if test X"$SYSTEM_TYPE" != X; then
126         set "$@" system-type="\"$SYSTEM_TYPE\""
127     else
128         log_failure_msg "no default system type, please use --system-type"
129     fi
130
131     if test X"$SYSTEM_VERSION" != X; then
132         set "$@" system-version="\"$SYSTEM_VERSION\""
133     else
134         log_failure_msg "no default system version, please use --system-version"
135     fi
136
137     action "Configuring Open vSwitch system IDs" "$@" $extra_ids
138 }
139
140 start () {
141     if test X"$FORCE_COREFILES" = Xyes; then
142         ulimit -Sc 67108864
143     fi
144
145     insert_modules_if_required || return 1
146
147     if daemon_is_running ovsdb-server; then
148         log_success_msg "ovsdb-server is already running"
149     else
150         # Create initial database or upgrade database schema.
151         upgrade_db || return 1
152
153         # Start ovsdb-server.
154         set ovsdb-server "$DB_FILE"
155         set "$@" -vANY:CONSOLE:EMER -vANY:SYSLOG:ERR -vANY:FILE:INFO
156         set "$@" --remote=punix:"$DB_SOCK"
157         set "$@" --remote=db:Open_vSwitch,manager_options
158         set "$@" --private-key=db:SSL,private_key
159         set "$@" --certificate=db:SSL,certificate
160         set "$@" --bootstrap-ca-cert=db:SSL,ca_cert
161         start_daemon "$OVSDB_SERVER_PRIORITY" "$@" || return 1
162
163         # Initialize database settings.
164         ovs_vsctl -- init -- set Open_vSwitch . db-version="$schemaver" \
165             || return 1
166         set_system_ids || return 1
167         if test X"$DELETE_BRIDGES" = Xyes; then
168             for bridge in `ovs_vsctl list-br`; do
169                 ovs_vsctl del-br $bridge
170             done
171         fi
172     fi
173
174     if daemon_is_running ovs-vswitchd; then
175         log_success_msg "ovs-vswitchd is already running"
176     else
177         # Increase the limit on the number of open file descriptors since
178         # ovs-vswitchd needs a few per bridge
179         ulimit -n 4096
180
181         # Start ovs-vswitchd.
182         set ovs-vswitchd unix:"$DB_SOCK"
183         set "$@" -vANY:CONSOLE:EMER -vANY:SYSLOG:ERR -vANY:FILE:INFO
184         if test X"$MLOCKALL" != Xno; then
185             set "$@" --mlockall
186         fi
187         start_daemon "$VSWITCHD_PRIORITY" "$@"
188     fi
189 }
190
191 ## ---- ##
192 ## stop ##
193 ## ---- ##
194
195 stop () {
196     stop_daemon ovs-vswitchd
197     stop_daemon ovsdb-server
198 }
199
200 ## ----------------- ##
201 ## force-reload-kmod ##
202 ## ----------------- ##
203
204 internal_interfaces () {
205     # Outputs a list of internal interfaces:
206     #
207     #   - There is an internal interface for every bridge, whether it
208     #     has an Interface record or not and whether the Interface
209     #     record's 'type' is properly set or not.
210     #
211     #   - There is an internal interface for each Interface record whose
212     #     'type' is 'internal'.
213     #
214     # But ignore interfaces that don't really exist.
215     for d in `(ovs_vsctl --bare \
216                 -- --columns=name find Interface type=internal \
217                 -- list-br) | sort -u`
218     do
219         if test -e "/sys/class/net/$d"; then
220             printf "%s " "$d"
221         fi
222     done
223 }
224
225 force_reload_kmod () {
226     ifaces=`internal_interfaces`
227     action "Detected internal interfaces: $ifaces" true
228
229     stop
230
231     script=`mktemp`
232     action "Save interface configuration to $script" true
233     if "$datadir/scripts/ovs-save" $ifaces > "$script"; then
234         :
235     else
236         log_warning_msg "Failed to save configuration, not replacing kernel module"
237         start
238         exit 1
239     fi
240     chmod +x "$script"
241
242     for dp in `ovs-dpctl dump-dps`; do
243         action "Removing datapath: $dp" "$dpctl" del-dp "$dp"
244     done
245
246     if test -e /sys/module/openvswitch_mod; then
247         action "Removing openvswitch module" rmmod openvswitch_mod
248     fi
249
250     start
251
252     action "Restore interface configuration from $script" "$script"
253 }
254
255 ## ---- ##
256 ## main ##
257 ## ---- ##
258
259 set_defaults () {
260     SYSTEM_ID=
261
262     DELETE_BRIDGES=no
263
264     DAEMON_CWD=/
265     FORCE_COREFILES=yes
266     MLOCKALL=yes
267     OVSDB_SERVER_PRIORITY=-10
268     OVS_VSWITCHD_PRIORITY=-10
269
270     DB_FILE=$etcdir/conf.db
271     DB_SOCK=$rundir/db.sock
272     DB_SCHEMA=$datadir/vswitch.ovsschema
273
274     if (lsb_release --id) >/dev/null 2>&1; then
275         SYSTEM_TYPE=`lsb_release --id -s`
276         system_release=`lsb_release --release -s`
277         system_codename=`lsb_release --codename -s`
278         SYSTEM_VERSION="${system_release}-${system_codename}"
279     else
280         SYSTEM_TYPE=unknown
281         SYSTEM_VERSION=unknown
282     fi
283 }
284
285 usage () {
286     set_defaults
287     cat <<EOF
288 $0: controls Open vSwitch daemons
289 usage: $0 [OPTIONS] COMMAND
290
291 This program is intended to be invoked internally by Open vSwitch startup
292 scripts.  System administrators should not normally invoke it directly.
293
294 Commands:
295   start              start Open vSwitch daemons
296   stop               stop Open vSwitch daemons
297   status             check whether Open vSwitch daemons are running
298   version            print versions of Open vSwitch daemons
299   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
300                      module, reload kernel module, start OVS, restore state
301   help               display this help message
302
303 One of the following options should be specified when starting Open vSwitch:
304   --system-id=UUID   set specific ID to uniquely identify this system
305   --system-id=random  use a random but persistent UUID to identify this system
306
307 Other important options for starting Open vSwitch:
308   --system-type=TYPE  set system type (e.g. "XenServer")
309   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
310   --external-id="key=value"
311                      add given key-value pair to Open_vSwitch external-ids
312   --delete-bridges   delete all bridges just before starting ovs-vswitchd
313
314 Less important options for starting Open vSwitch:
315   --daemon-cwd=DIR   current working directory for OVS daemons (default: $DAEMON_CWD)
316   --no-force-corefiles
317                      do not forcibly enable core dumps for OVS daemons
318   --no-mlockall      do not lock all of ovs-vswitchd into memory
319   --ovsdb-server-priority=NICE
320                      set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
321   --ovs-vswitchd-priority=NICE
322                      set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
323
324 File location options:
325   --db-file=FILE     database file name (default: $DB_FILE)
326   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
327   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
328
329 Other options:
330   -h, --help                  display this help message
331   -V, --version               display version information
332
333 Default directories with "configure" option and environment variable override:
334   logs: @LOGDIR@ (--log-dir, OVS_LOGDIR)
335   pidfiles and sockets: @RUNDIR@ (--run-dir, OVS_RUNDIR)
336   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
337   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
338   user binaries: @bindir@ (--bindir, OVS_BINDIR)
339   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
340
341 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
342 EOF
343
344     exit 0
345 }
346
347 set_option () {
348     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
349     eval set=\${$var+yes}
350     eval old_value=\$$var
351     if test X$set = X || \
352         (test $type = bool && \
353         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
354         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
355         return
356     fi
357     eval $var=\$value
358 }
359
360 set_defaults
361 extra_ids=
362 command=
363 for arg
364 do
365     case $arg in
366         -h | --help)
367             usage
368             ;;
369         -V | --version)
370             echo "$0 (Open vSwitch) $VERSION$BUILDNR"
371             exit 0
372             ;;
373         --external-id=*)
374             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
375             case $value in
376                 *=*)
377                     extra_ids="$extra_ids external-ids:$value"
378                     ;;
379                 *)
380                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
381                     exit 1
382                     ;;
383             esac
384             ;;
385         --[a-z]*=*)
386             option=`expr X"$arg" : 'X--\([^=]*\)'`
387             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
388             type=string
389             set_option
390             ;;
391         --no-[a-z]*)
392             option=`expr X"$arg" : 'X--no-\(.*\)'`
393             value=no
394             type=bool
395             set_option
396             ;;
397         --[a-z]*)
398             option=`expr X"$arg" : 'X--\(.*\)'`
399             value=yes
400             type=bool
401             set_option
402             ;;
403         -*)
404             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
405             exit 1
406             ;;
407         *)
408             if test X"$command" = X; then
409                 command=$arg
410             else
411                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
412                 exit 1
413             fi
414             ;;
415     esac
416 done
417 case $command in
418     start)
419         start
420         ;;
421     stop)
422         stop
423         ;;
424     status)
425         daemon_status ovsdb-server && daemon_status ovs-vswitchd
426         ;;
427     version)
428         ovsdb-server --version && ovs-vswitchd --version
429         ;;
430     force-reload-kmod)
431         force_reload_kmod
432         ;;
433     help)
434         usage
435         ;;
436     '')
437         echo >&2 "$0: missing command name (use --help for help)"
438         exit 1
439         ;;
440     *)
441         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
442         exit 1
443         ;;
444 esac
445