checkpatch: Don't enforce char limit on tests.
[cascardo/ovs.git] / utilities / ovs-ctl.in
1 #! /bin/sh
2 # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2016 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 # Keep track of removed vports so we can reload them if needed
34 removed_vports=""
35
36 insert_mods () {
37     # Try loading openvswitch again.
38     action "Inserting openvswitch module" modprobe openvswitch
39
40     for vport in $removed_vports; do
41         # Don't treat failures to load vports as fatal error
42         action "Inserting $vport module" modprobe $vport || true
43     done
44 }
45
46 insert_mod_if_required () {
47     # If this kernel has no module support, expect we're done.
48     if test ! -e /proc/modules
49     then
50         log_success_msg "Kernel has no loadable module support. Skipping modprobe"
51         return 0
52     fi
53
54     # If openvswitch is already loaded then we're done.
55     test -e /sys/module/openvswitch && return 0
56
57     # Load openvswitch.  If that's successful then we're done.
58     insert_mods && return 0
59
60     # If the bridge module is loaded, then that might be blocking
61     # openvswitch.  Try to unload it, if there are no bridges.
62     test -e /sys/module/bridge || return 1
63     bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
64     if test "$bridges" != "*"; then
65         log_warning_msg "not removing bridge module because bridges exist ($bridges)"
66         return 1
67     fi
68     action "removing bridge module" rmmod bridge || return 1
69
70     # Try loading openvswitch again.
71     insert_mods
72 }
73
74 ovs_vsctl () {
75     ovs-vsctl --no-wait "$@"
76 }
77
78 set_system_ids () {
79     set ovs_vsctl set Open_vSwitch .
80
81     OVS_VERSION=`ovs-vswitchd --version | sed 's/.*) //;1q'`
82     set "$@" ovs-version="$OVS_VERSION"
83
84     case $SYSTEM_ID in
85         random)
86             id_file=$etcdir/system-id.conf
87             uuid_file=$etcdir/install_uuid.conf
88             if test -e "$id_file"; then
89                 SYSTEM_ID=`cat "$id_file"`
90             elif test -e "$uuid_file"; then
91                 # Migrate from old file name.
92                 . "$uuid_file"
93                 SYSTEM_ID=$INSTALLATION_UUID
94                 echo "$SYSTEM_ID" > "$id_file"
95             elif SYSTEM_ID=`uuidgen`; then
96                 echo "$SYSTEM_ID" > "$id_file"
97             else
98                 log_failure_msg "missing uuidgen, could not generate system ID"
99             fi
100             ;;
101
102         '')
103             log_failure_msg "system ID not configured, please use --system-id"
104             ;;
105
106         *)
107             ;;
108     esac
109     set "$@" external-ids:system-id="\"$SYSTEM_ID\""
110
111     set "$@" external-ids:hostname="\"$(hostname)\""
112
113     if test X"$SYSTEM_TYPE" != X; then
114         set "$@" system-type="\"$SYSTEM_TYPE\""
115     else
116         log_failure_msg "no default system type, please use --system-type"
117     fi
118
119     if test X"$SYSTEM_VERSION" != X; then
120         set "$@" system-version="\"$SYSTEM_VERSION\""
121     else
122         log_failure_msg "no default system version, please use --system-version"
123     fi
124
125     action "Configuring Open vSwitch system IDs" "$@" $extra_ids
126 }
127
128 check_force_cores () {
129     if test X"$FORCE_COREFILES" = Xyes; then
130         ulimit -c 67108864
131     fi
132 }
133
134 del_transient_ports () {
135     for port in `ovs-vsctl --bare -- --columns=name find port other_config:transient=true`; do
136         ovs_vsctl -- del-port "$port"
137     done
138 }
139
140 do_start_ovsdb () {
141     check_force_cores
142
143     if daemon_is_running ovsdb-server; then
144         log_success_msg "ovsdb-server is already running"
145     else
146         # Create initial database or upgrade database schema.
147         upgrade_db $DB_FILE $DB_SCHEMA || return 1
148
149         # Start ovsdb-server.
150         set ovsdb-server "$DB_FILE"
151         for db in $EXTRA_DBS; do
152             case $db in
153                 /*) ;;
154                 *) db=$dbdir/$db ;;
155             esac
156
157             if test ! -f "$db"; then
158                 log_warning_msg "$db (from \$EXTRA_DBS) does not exist."
159             elif ovsdb-tool db-version "$db" >/dev/null; then
160                 set "$@" "$db"
161             else
162                 log_warning_msg "$db (from \$EXTRA_DBS) cannot be read as a database (see error message above)"
163             fi
164         done
165         set "$@" -vconsole:emer -vsyslog:err -vfile:info
166         set "$@" --remote=punix:"$DB_SOCK"
167         set "$@" --private-key=db:Open_vSwitch,SSL,private_key
168         set "$@" --certificate=db:Open_vSwitch,SSL,certificate
169         set "$@" --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert
170         start_daemon "$OVSDB_SERVER_PRIORITY" "$OVSDB_SERVER_WRAPPER" "$@" \
171             || return 1
172
173         # Initialize database settings.
174         ovs_vsctl -- init -- set Open_vSwitch . db-version="$schemaver" \
175             || return 1
176         set_system_ids || return 1
177         if test X"$DELETE_BRIDGES" = Xyes; then
178             for bridge in `ovs_vsctl list-br`; do
179                 ovs_vsctl del-br $bridge
180             done
181         fi
182         if test X"$DELETE_TRANSIENT_PORTS" = Xyes; then
183             del_transient_ports
184         fi
185     fi
186 }
187
188 start_ovsdb() {
189     if test X"$OVSDB_SERVER" = Xyes; then
190         do_start_ovsdb
191     fi
192 }
193
194 add_managers () {
195     # Now that ovs-vswitchd has started and completed its initial
196     # configuration, tell ovsdb-server to conenct to the remote managers.  We
197     # used to do this at ovsdb-server startup time, but waiting for
198     # ovs-vswitchd to finish configuring means that remote managers see less
199     # churn in the database at startup or restart.  (For example, managers
200     # won't briefly see empty datapath-id or ofport columns for records that
201     # exist at startup.)
202     action "Enabling remote OVSDB managers" \
203         ovs-appctl -t ovsdb-server ovsdb-server/add-remote \
204             db:Open_vSwitch,Open_vSwitch,manager_options
205 }
206
207 do_start_forwarding () {
208     check_force_cores
209
210     insert_mod_if_required || return 1
211
212     if daemon_is_running ovs-vswitchd; then
213         log_success_msg "ovs-vswitchd is already running"
214     else
215         # Increase the limit on the number of open file descriptors.
216         # On Linux, ovs-vswitchd needs about three file descriptors
217         # per bridge and "n-handler-threads" file descriptors per bridge
218         # port, so this allows a very large number of bridges and ports.
219         MAXFD=65535
220         if [ $(ulimit -n) -lt $MAXFD ]; then
221             ulimit -n $MAXFD
222         fi
223
224             # Start ovs-vswitchd.
225             set ovs-vswitchd unix:"$DB_SOCK"
226             set "$@" -vconsole:emer -vsyslog:err -vfile:info
227             if test X"$MLOCKALL" != Xno; then
228                 set "$@" --mlockall
229             fi
230             start_daemon "$OVS_VSWITCHD_PRIORITY" "$OVS_VSWITCHD_WRAPPER" "$@"
231     fi
232 }
233
234 start_forwarding () {
235     if test X"$OVS_VSWITCHD" = Xyes; then
236         do_start_forwarding
237     fi
238 }
239
240 ## ---- ##
241 ## stop ##
242 ## ---- ##
243
244 stop_ovsdb () {
245     if test X"$OVSDB_SERVER" = Xyes; then
246         stop_daemon ovsdb-server
247     fi
248 }
249
250 stop_forwarding () {
251     if test X"$OVS_VSWITCHD" = Xyes; then
252         stop_daemon ovs-vswitchd
253     fi
254 }
255
256 ## ----------------- ##
257 ## force-reload-kmod ##
258 ## ----------------- ##
259
260 internal_interfaces () {
261     # Outputs a list of internal interfaces:
262     #
263     #   - There is an internal interface for every bridge, whether it
264     #     has an Interface record or not and whether the Interface
265     #     record's 'type' is properly set or not.
266     #
267     #   - There is an internal interface for each Interface record whose
268     #     'type' is 'internal'.
269     #
270     # But ignore interfaces that don't really exist.
271     for d in `(ovs_vsctl --bare \
272                 -- --columns=name find Interface type=internal \
273                     -- list-br) | sort -u`
274     do
275         if test -e "/sys/class/net/$d"; then
276                 printf "%s " "$d"
277             fi
278     done
279 }
280
281 ovs_save () {
282     bridges=`ovs_vsctl -- --real list-br`
283     if [ -n "${bridges}" ] && \
284         "$datadir/scripts/ovs-save" "$1" ${bridges} > "$2"; then
285         chmod +x "$2"
286         return 0
287     fi
288     [ -z "${bridges}" ] && return 0
289 }
290
291 save_flows_if_required () {
292     if test X"$DELETE_BRIDGES" != Xyes; then
293         action "Saving flows" ovs_save save-flows "${script_flows}"
294     fi
295 }
296
297 save_interfaces () {
298     "$datadir/scripts/ovs-save" save-interfaces ${ifaces} \
299         > "${script_interfaces}"
300 }
301
302 flow_restore_wait () {
303     if test X"$OVS_VSWITCHD" = Xyes; then
304         ovs_vsctl set open_vswitch . other_config:flow-restore-wait="true"
305     fi
306 }
307
308 flow_restore_complete () {
309     if test X"$OVS_VSWITCHD" = Xyes; then
310         ovs_vsctl --if-exists remove open_vswitch . other_config \
311                   flow-restore-wait="true"
312     fi
313 }
314
315 restore_flows () {
316     [ -x "${script_flows}" ] && \
317         action "Restoring saved flows" "${script_flows}"
318 }
319
320 restore_interfaces () {
321     [ ! -x "${script_interfaces}" ] && return 0
322     action "Restoring interface configuration" "${script_interfaces}"
323     rc=$?
324     if test $rc = 0; then
325         level=debug
326     else
327         level=err
328     fi
329     log="logger -p daemon.$level -t ovs-save"
330     $log "interface restore script exited with status $rc:"
331     $log -f "$script_interfaces"
332 }
333
334 init_restore_scripts () {
335     script_interfaces=`mktemp`
336     script_flows=`mktemp`
337     trap 'rm -f "${script_interfaces}" "${script_flows}"' 0
338 }
339
340 force_reload_kmod () {
341
342     if test X"$OVS_VSWITCHD" != Xyes; then
343         log_failure_msg "Reloading of kmod without ovs-vswitchd is an error"
344         exit 1
345     fi
346
347     ifaces=`internal_interfaces`
348     action "Detected internal interfaces: $ifaces" true
349
350     init_restore_scripts
351     save_flows_if_required
352
353     # Restart the database first, since a large database may take a
354     # while to load, and we want to minimize forwarding disruption.
355     stop_ovsdb
356     start_ovsdb
357
358     stop_forwarding
359
360     if action "Saving interface configuration" save_interfaces; then
361         :
362     else
363         log_warning_msg "Failed to save configuration, not replacing kernel module"
364         start_forwarding
365         add_managers
366         exit 1
367     fi
368     chmod +x "$script_interfaces"
369
370     for dp in `ovs-dpctl dump-dps`; do
371         action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
372     done
373
374     for vport in `awk '/^vport_/ { print $1 }' /proc/modules`; do
375         action "Removing $vport module" rmmod $vport
376         if ! grep -q $vport /proc/modules; then
377             removed_vports="$removed_vports $vport"
378         fi
379     done
380
381     if test -e /sys/module/openvswitch; then
382         action "Removing openvswitch module" rmmod openvswitch
383     fi
384
385     # Start vswitchd by asking it to wait till flow restore is finished.
386     flow_restore_wait
387     start_forwarding
388
389     # Restore saved flows and inform vswitchd that we are done.
390     restore_flows
391     flow_restore_complete
392     add_managers
393
394     restore_interfaces
395
396     "$datadir/scripts/ovs-check-dead-ifs"
397 }
398
399 ## ------- ##
400 ## restart ##
401 ## ------- ##
402
403 restart () {
404     if daemon_is_running ovsdb-server && daemon_is_running ovs-vswitchd; then
405         init_restore_scripts
406         if test X"$OVS_VSWITCHD" = Xyes; then
407             save_flows_if_required
408         fi
409     fi
410
411     # Restart the database first, since a large database may take a
412     # while to load, and we want to minimize forwarding disruption.
413     stop_ovsdb
414     start_ovsdb
415
416     stop_forwarding
417
418     # Start vswitchd by asking it to wait till flow restore is finished.
419     flow_restore_wait
420     start_forwarding
421
422     # Restore saved flows and inform vswitchd that we are done.
423     restore_flows
424     flow_restore_complete
425     add_managers
426
427     # Restore the interfaces if required. Return true even if restore fails.
428     restore_interfaces || true
429 }
430
431 ## --------------- ##
432 ## enable-protocol ##
433 ## --------------- ##
434
435 enable_protocol () {
436     # Translate the protocol name to a number, because "iptables -n -L" prints
437     # some protocols by name (despite the -n) and therefore we need to look for
438     # both forms.
439     #
440     # (iptables -S output is more uniform but old iptables doesn't have it.)
441     protonum=`grep "^$PROTOCOL[         ]" /etc/protocols | awk '{print $2}'`
442     if expr X"$protonum" : X'[0-9]\{1,\}$' > /dev/null; then :; else
443         log_failure_msg "unknown protocol $PROTOCOL"
444         return 1
445     fi
446
447     name=$PROTOCOL
448     match="(\$2 == \"$PROTOCOL\" || \$2 == $protonum)"
449     insert="iptables -I INPUT -p $PROTOCOL"
450     if test X"$DPORT" != X; then
451         name="$name to port $DPORT"
452         match="$match && /dpt:$DPORT/"
453         insert="$insert --dport $DPORT"
454     fi
455     if test X"$SPORT" != X; then
456         name="$name from port $SPORT"
457         match="$match && /spt:$SPORT/"
458         insert="$insert --sport $SPORT"
459     fi
460     insert="$insert -j ACCEPT"
461
462     if (iptables -n -L INPUT) >/dev/null 2>&1; then
463         if iptables -n -L INPUT | awk "$match { n++ } END { exit n == 0 }"
464         then
465             # There's already a rule for this protocol.  Don't override it.
466             log_success_msg "iptables already has a rule for $name, not explicitly enabling"
467         else
468             action "Enabling $name with iptables" $insert
469         fi
470     elif (iptables --version) >/dev/null 2>&1; then
471         action "cannot list iptables rules, not adding a rule for $name"
472     else
473         action "iptables binary not installed, not adding a rule for $name"
474     fi
475 }
476
477 ## ---- ##
478 ## main ##
479 ## ---- ##
480
481 set_defaults () {
482     SYSTEM_ID=
483
484     DELETE_BRIDGES=no
485     DELETE_TRANSIENT_PORTS=no
486
487     DAEMON_CWD=/
488     FORCE_COREFILES=yes
489     MLOCKALL=yes
490     OVSDB_SERVER=yes
491     OVS_VSWITCHD=yes
492     OVSDB_SERVER_PRIORITY=-10
493     OVS_VSWITCHD_PRIORITY=-10
494     OVSDB_SERVER_WRAPPER=
495     OVS_VSWITCHD_WRAPPER=
496
497     DB_FILE=$dbdir/conf.db
498     DB_SOCK=$rundir/db.sock
499     DB_SCHEMA=$datadir/vswitch.ovsschema
500     EXTRA_DBS=
501
502     PROTOCOL=gre
503     DPORT=
504     SPORT=
505
506     type_file=$etcdir/system-type.conf
507     version_file=$etcdir/system-version.conf
508
509     if test -e "$type_file" ; then
510         SYSTEM_TYPE=`cat $type_file`
511         SYSTEM_VERSION=`cat $version_file`
512     elif (lsb_release --id) >/dev/null 2>&1; then
513         SYSTEM_TYPE=`lsb_release --id -s`
514         system_release=`lsb_release --release -s`
515         system_codename=`lsb_release --codename -s`
516         SYSTEM_VERSION="${system_release}-${system_codename}"
517     else
518         SYSTEM_TYPE=unknown
519         SYSTEM_VERSION=unknown
520     fi
521 }
522
523 usage () {
524     set_defaults
525     cat <<EOF
526 $0: controls Open vSwitch daemons
527 usage: $0 [OPTIONS] COMMAND
528
529 This program is intended to be invoked internally by Open vSwitch startup
530 scripts.  System administrators should not normally invoke it directly.
531
532 Commands:
533   start              start Open vSwitch daemons
534   stop               stop Open vSwitch daemons
535   restart            stop and start Open vSwitch daemons
536   status             check whether Open vSwitch daemons are running
537   version            print versions of Open vSwitch daemons
538   load-kmod          insert modules if not already present
539   force-reload-kmod  save OVS network device state, stop OVS, unload kernel
540                      module, reload kernel module, start OVS, restore state
541   enable-protocol    enable protocol specified in options with iptables
542   help               display this help message
543
544 One of the following options is required for "start", "restart" and "force-reload-kmod":
545   --system-id=UUID   set specific ID to uniquely identify this system
546   --system-id=random  use a random but persistent UUID to identify this system
547
548 Other important options for "start", "restart" and "force-reload-kmod":
549   --system-type=TYPE  set system type (e.g. "XenServer")
550   --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
551   --external-id="key=value"
552                      add given key-value pair to Open_vSwitch external-ids
553   --delete-bridges   delete all bridges just before starting ovs-vswitchd
554
555 Less important options for "start", "restart" and "force-reload-kmod":
556   --daemon-cwd=DIR               set working dir for OVS daemons (default: $DAEMON_CWD)
557   --no-force-corefiles           do not force on core dumps for OVS daemons
558   --no-mlockall                  do not lock all of ovs-vswitchd into memory
559   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
560   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
561
562 Debugging options for "start", "restart" and "force-reload-kmod":
563   --ovsdb-server-wrapper=WRAPPER
564   --ovs-vswitchd-wrapper=WRAPPER
565   --ovs-vswitchd-wrapper=WRAPPER
566      run specified daemon under WRAPPER (either 'valgrind' or 'strace')
567
568 File location options:
569   --db-file=FILE     database file name (default: $DB_FILE)
570   --db-sock=SOCKET   JSON-RPC socket name (default: $DB_SOCK)
571   --db-schema=FILE   database schema file name (default: $DB_SCHEMA)
572
573 Options for "enable-protocol":
574   --protocol=PROTOCOL  protocol to enable with iptables (default: gre)
575   --sport=PORT       source port to match (for tcp or udp protocol)
576   --dport=PORT       ddestination port to match (for tcp or udp protocol)
577
578 Other options:
579   -h, --help                  display this help message
580   -V, --version               display version information
581
582 Default directories with "configure" option and environment variable override:
583   logs: @LOGDIR@ (--with-logdir, OVS_LOGDIR)
584   pidfiles and sockets: @RUNDIR@ (--with-rundir, OVS_RUNDIR)
585   conf.db: @DBDIR@ (--with-dbdir, OVS_DBDIR)
586   system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
587   data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
588   user binaries: @bindir@ (--bindir, OVS_BINDIR)
589   system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
590
591 Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
592 EOF
593
594     exit 0
595 }
596
597 set_option () {
598     var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
599     eval set=\${$var+yes}
600     eval old_value=\$$var
601     if test X$set = X || \
602         (test $type = bool && \
603         test X"$old_value" != Xno && test X"$old_value" != Xyes); then
604         echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
605         return
606     fi
607     eval $var=\$value
608 }
609
610 daemons () {
611     echo ovsdb-server ovs-vswitchd
612 }
613
614 set_defaults
615 extra_ids=
616 command=
617 for arg
618 do
619     case $arg in
620         -h | --help)
621             usage
622             ;;
623         -V | --version)
624             echo "$0 (Open vSwitch) $VERSION"
625             exit 0
626             ;;
627         --external-id=*)
628             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
629             case $value in
630                 *=*)
631                     extra_ids="$extra_ids external-ids:$value"
632                     ;;
633                 *)
634                     echo >&2 "$0: --external-id argument not in the form \"key=value\""
635                     exit 1
636                     ;;
637             esac
638             ;;
639         --[a-z]*=*)
640             option=`expr X"$arg" : 'X--\([^=]*\)'`
641             value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
642             type=string
643             set_option
644             ;;
645         --no-[a-z]*)
646             option=`expr X"$arg" : 'X--no-\(.*\)'`
647             value=no
648             type=bool
649             set_option
650             ;;
651         --[a-z]*)
652             option=`expr X"$arg" : 'X--\(.*\)'`
653             value=yes
654             type=bool
655             set_option
656             ;;
657         -*)
658             echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
659             exit 1
660             ;;
661         *)
662             if test X"$command" = X; then
663                 command=$arg
664             else
665                 echo >&2 "$0: exactly one non-option argument required (use --help for help)"
666                 exit 1
667             fi
668             ;;
669     esac
670 done
671 case $command in
672     start)
673         start_ovsdb || exit 1
674         start_forwarding
675         add_managers
676         ;;
677     stop)
678         stop_forwarding
679         stop_ovsdb
680         ;;
681     restart)
682         restart
683         ;;
684     status)
685         rc=0
686         for daemon in `daemons`; do
687             daemon_status $daemon || rc=$?
688         done
689         exit $rc
690         ;;
691     version)
692         for daemon in `daemons`; do
693             $daemon --version
694         done
695         ;;
696     force-reload-kmod)
697             force_reload_kmod
698         ;;
699     load-kmod)
700         insert_mod_if_required
701         ;;
702     enable-protocol)
703         enable_protocol
704         ;;
705     help)
706         usage
707         ;;
708     '')
709         echo >&2 "$0: missing command name (use --help for help)"
710         exit 1
711         ;;
712     *)
713         echo >&2 "$0: unknown command \"$command\" (use --help for help)"
714         exit 1
715         ;;
716 esac