dpif-netlink: add GENEVE creation support
[cascardo/ovs.git] / utilities / ovs-dev.py
1 #!/usr/bin/env python
2 # Copyright (c) 2013, 2014, 2015, 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 import optparse
17 import os
18 import shutil
19 import subprocess
20 import sys
21 import time
22
23 ENV = os.environ
24 HOME = ENV["HOME"]
25 PWD = os.getcwd()
26 OVS_SRC = HOME + "/ovs"
27 if os.path.exists(PWD + "/WHY-OVS.md"):
28     OVS_SRC = PWD  # Use current directory as OVS source tree
29 RUNDIR = OVS_SRC + "/_run"
30 BUILD_GCC = OVS_SRC + "/_build-gcc"
31 BUILD_CLANG = OVS_SRC + "/_build-clang"
32
33 options = None
34 parser = None
35 commands = []
36
37
38 def set_path(build):
39     PATH = "%(ovs)s/utilities:%(ovs)s/ovsdb:%(ovs)s/vswitchd" % {"ovs": build}
40
41     ENV["PATH"] = PATH + ":" + ENV["PATH"]
42
43
44 def _sh(*args, **kwargs):
45     print("------> " + " ".join(args))
46     shell = len(args) == 1
47     if kwargs.get("capture", False):
48         proc = subprocess.Popen(args, stdout=subprocess.PIPE, shell=shell)
49         return proc.stdout.readlines()
50     elif kwargs.get("check", True):
51         subprocess.check_call(args, shell=shell)
52     else:
53         subprocess.call(args, shell=shell)
54
55
56 def uname():
57     return _sh("uname", "-r", capture=True)[0].decode().strip()
58
59
60 def sudo():
61     if os.geteuid() != 0:
62         _sh(" ".join(["sudo"] + sys.argv), check=True)
63         sys.exit(0)
64
65
66 def conf():
67     tag()
68
69     try:
70         os.remove(OVS_SRC + "/Makefile")
71     except OSError:
72         pass
73
74     configure = ["../configure",
75                  "--prefix=" + RUNDIR, "--localstatedir=" + RUNDIR,
76                  "--with-logdir=%s/log" % RUNDIR,
77                  "--with-rundir=%s/run" % RUNDIR,
78                  "--enable-silent-rules", "--with-dbdir=" + RUNDIR, "--silent"]
79
80     cflags = "-g -fno-omit-frame-pointer"
81
82     if options.werror:
83         configure.append("--enable-Werror")
84
85     if options.cache_time:
86         configure.append("--enable-cache-time")
87
88     if options.mandir:
89         configure.append("--mandir=" + options.mandir)
90
91     if options.with_dpdk:
92         configure.append("--with-dpdk=" + options.with_dpdk)
93         cflags += " -Wno-cast-align -Wno-bad-function-cast"  # DPDK warnings.
94
95     if options.optimize is None:
96         options.optimize = 0
97
98     cflags += " -O%s" % str(options.optimize)
99
100     ENV["CFLAGS"] = cflags
101
102     _sh("./boot.sh")
103
104     try:
105         os.mkdir(BUILD_GCC)
106     except OSError:
107         pass  # Directory exists.
108
109     os.chdir(BUILD_GCC)
110     _sh(*(configure + ["--with-linux=/lib/modules/%s/build" % uname()]))
111
112     try:
113         _sh("clang --version", check=True)
114         clang = True
115     except subprocess.CalledProcessError:
116         clang = False
117
118     try:
119         _sh("sparse --version", check=True)
120         sparse = True
121     except subprocess.CalledProcessError:
122         sparse = False
123
124     if clang:
125         try:
126             os.mkdir(BUILD_CLANG)
127         except OSError:
128             pass  # Directory exists.
129
130         ENV["CC"] = "clang"
131         os.chdir(BUILD_CLANG)
132         _sh(*configure)
133
134     if sparse:
135         c1 = "C=1"
136     else:
137         c1 = ""
138
139     os.chdir(OVS_SRC)
140
141     make_str = "\t$(MAKE) -C %s $@\n"
142
143     mf = open(OVS_SRC + "/Makefile", "w")
144     mf.write("all:\n%:\n")
145     if clang:
146         mf.write(make_str % BUILD_CLANG)
147     mf.write("\t$(MAKE) -C %s %s $@\n" % (BUILD_GCC, c1))
148     mf.write("\ncheck-valgrind:\n")
149     mf.write("\ncheck:\n")
150     mf.write(make_str % BUILD_GCC)
151     mf.close()
152 commands.append(conf)
153
154
155 def make(args=""):
156     make = "make -s -j 8 " + args
157     _sh(make)
158 commands.append(make)
159
160
161 def check():
162     flags = ""
163     if options.jobs:
164         flags += "-j%d " % options.jobs
165     else:
166         flags += "-j8 "
167     if options.tests:
168         for arg in str.split(options.tests):
169             if arg[0].isdigit():
170                 flags += "%s " % arg
171             else:
172                 flags += "-k %s " % arg
173     ENV["TESTSUITEFLAGS"] = flags
174     make("check")
175 commands.append(check)
176
177
178 def tag():
179     ctags = ['ctags', '-R', '-f', '.tags']
180
181     try:
182         _sh(*(ctags + ['--exclude="datapath/"']))
183     except:
184         try:
185             _sh(*ctags)  # Some versions of ctags don't have --exclude
186         except:
187             pass
188
189     try:
190         _sh('cscope', '-R', '-b')
191     except:
192         pass
193 commands.append(tag)
194
195
196 def kill():
197     sudo()
198     for proc in ["ovs-vswitchd", "ovsdb-server"]:
199         if os.path.exists("%s/run/openvswitch/%s.pid" % (RUNDIR, proc)):
200             _sh("ovs-appctl", "-t", proc, "exit", check=False)
201             time.sleep(.1)
202         _sh("killall", "-q", "-2", proc, check=False)
203 commands.append(kill)
204
205
206 def reset():
207     sudo()
208     kill()
209     if os.path.exists(RUNDIR):
210         shutil.rmtree(RUNDIR)
211     for dp in _sh("ovs-dpctl dump-dps", capture=True):
212         _sh("ovs-dpctl", "del-dp", dp.decode().strip())
213 commands.append(reset)
214
215
216 def run():
217     sudo()
218     kill()
219     for d in ["log", "run"]:
220         d = "%s/%s" % (RUNDIR, d)
221         shutil.rmtree(d, ignore_errors=True)
222         os.makedirs(d)
223
224     pki_dir = RUNDIR + "/pki"
225     if not os.path.exists(pki_dir):
226         os.mkdir(pki_dir)
227         os.chdir(pki_dir)
228         _sh("ovs-pki init")
229         _sh("ovs-pki req+sign ovsclient")
230         os.chdir(OVS_SRC)
231
232     if not os.path.exists(RUNDIR + "/conf.db"):
233         _sh("ovsdb-tool", "create", RUNDIR + "/conf.db",
234             OVS_SRC + "/vswitchd/vswitch.ovsschema")
235
236     opts = ["--pidfile", "--log-file"]
237
238     if (options.user == "") or (options.user == "root:root"):
239         _sh("chown", "root:root", "-R", RUNDIR)
240         if '--user' in sys.argv:
241             sys.argv.remove("--user")
242     else:
243         _sh("chown", options.user, "-R", RUNDIR)
244         opts = ["--user", options.user] + opts
245
246     if (options.monitor):
247         opts = ["--monitor"] + opts
248
249     _sh(*(["ovsdb-server",
250            "--remote=punix:%s/run/db.sock" % RUNDIR,
251            "--remote=db:Open_vSwitch,Open_vSwitch,manager_options",
252            "--private-key=db:Open_vSwitch,SSL,private_key",
253            "--certificate=db:Open_vSwitch,SSL,certificate",
254            "--bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert",
255            "--detach", "-vconsole:off"] + opts))
256
257     _sh("ovs-vsctl --no-wait --bootstrap set-ssl %s/ovsclient-privkey.pem"
258         " %s/ovsclient-cert.pem %s/vswitchd.cacert"
259         % (pki_dir, pki_dir, pki_dir))
260     version = _sh("ovs-vsctl --no-wait --version", capture=True)
261     version = version[0].decode().strip().split()[3]
262     root_uuid = _sh("ovs-vsctl --no-wait --bare list Open_vSwitch",
263                     capture=True)[0].decode().strip()
264     _sh("ovs-vsctl --no-wait set Open_vSwitch %s ovs_version=%s"
265         % (root_uuid, version))
266
267     build = BUILD_CLANG if options.clang else BUILD_GCC
268     cmd = [build + "/vswitchd/ovs-vswitchd"]
269
270     if options.dpdk:
271         _sh("ovs-vsctl --no-wait set Open_vSwitch %s "
272             "other_config:dpdk-init=true" % root_uuid)
273         _sh("ovs-vsctl --no-wait set Open_vSwitch %s other_config:"
274             "dpdk-extra=\"%s\"" % (root_uuid, ' '.join(options.dpdk)))
275     else:
276         _sh("ovs-vsctl --no-wait set Open_vSwitch %s "
277             "other_config:dpdk-init=false" % root_uuid)
278
279     if options.gdb:
280         cmd = ["gdb", "--args"] + cmd
281     elif options.valgrind:
282         cmd = ["valgrind", "--track-origins=yes", "--leak-check=full",
283                "--suppressions=%s/tests/glibc.supp" % OVS_SRC,
284                "--suppressions=%s/tests/openssl.supp" % OVS_SRC] + cmd
285     else:
286         opts = opts + ["-vconsole:off", "--detach", "--enable-dummy"]
287     _sh(*(cmd + opts))
288 commands.append(run)
289
290
291 def modinst():
292     if not os.path.exists("/lib/modules"):
293         print("Missing modules directory.  Is this a Linux system?")
294         sys.exit(1)
295
296     sudo()
297     try:
298         _sh("rmmod", "openvswitch")
299     except subprocess.CalledProcessError:
300         pass  # Module isn't loaded
301
302     try:
303         _sh("rm -f /lib/modules/%s/extra/openvswitch.ko" % uname())
304         _sh("rm -f /lib/modules/%s/extra/vport-*.ko" % uname())
305     except subprocess.CalledProcessError:
306         pass  # Module isn't installed
307
308     conf()
309     make()
310     make("modules_install")
311
312     _sh("modprobe", "openvswitch")
313     _sh("dmesg | grep openvswitch | tail -1")
314     _sh("find /lib/modules/%s/ -iname vport-*.ko -exec insmod '{}' \;"
315         % uname())
316 commands.append(modinst)
317
318
319 def env():
320     print("export PATH=" + ENV["PATH"])
321 commands.append(env)
322
323
324 def doc():
325     parser.print_help()
326     print("""
327 This program is designed to help developers build and run Open vSwitch without
328 necessarily needing to know the gory details. Given some basic requirements
329 (described below), it can be used to build and run Open vSwitch, keeping
330 runtime files in the user's home directory.
331
332 Basic Configuration:
333     # This section can be run as a script on ubuntu systems.
334
335     # First install the basic requirements needed to build Open vSwitch.
336     sudo apt-get install git build-essential libtool autoconf pkg-config \\
337             libssl-dev gdb libcap-ng-dev linux-headers-`uname -r`
338
339     # Next clone the Open vSwitch source.
340     git clone https://github.com/openvswitch/ovs.git %(ovs)s
341
342     # Setup environment variables.
343     `%(v)s env`
344
345     # Build the switch.
346     %(v)s conf make
347
348     # Install the kernel module
349     sudo insmod %(ovs)s/datapath/linux/openvswitch.ko
350
351     # If needed, manually load all required vport modules:
352     sudo insmod %(ovs)s/datapath/linux/vport-vxlan.ko
353     sudo insmod %(ovs)s/datapath/linux/vport-geneve.ko
354     [...]
355
356     # Run the switch.
357     %(v)s run
358
359 Commands:
360     conf    - Configure the ovs source.
361     make    - Build the source (must have been configured).
362     check   - Run the unit tests.
363     tag     - Run ctags and cscope over the source.
364     kill    - Kill all running instances of ovs.
365     reset   - Reset any runtime configuration in %(run)s.
366     run     - Run ovs.
367     modinst - Build ovs and install the kernel module.
368     env     - Print the required path environment variable.
369     doc     - Print this message.
370
371 Note:
372     If running as non-root user, "kill", "reset", "run" and "modinst"
373     will always run as the root user, by rerun the commands with "sudo".
374 """ % {"ovs": OVS_SRC, "v": sys.argv[0], "run": RUNDIR})
375     sys.exit(0)
376 commands.append(doc)
377
378
379 def parse_subargs(option, opt_str, value, parser):
380     subopts = []
381
382     while parser.rargs:
383         dpdkarg = parser.rargs.pop(0)
384         if dpdkarg == "--":
385             break
386         subopts.append(dpdkarg)
387
388     setattr(parser.values, option.dest, subopts)
389
390
391 def main():
392     global options
393     global parser
394
395     description = "Open vSwitch developer configuration. Try `%prog doc`."
396     cmd_names = [c.__name__ for c in commands]
397     usage = "usage: %prog" + " [options] [%s] ..." % "|".join(cmd_names)
398     parser = optparse.OptionParser(usage=usage, description=description)
399
400     group = optparse.OptionGroup(parser, "conf")
401     group.add_option("--disable-Werror", dest="werror", action="store_false",
402                      default=True, help="compile without the Werror flag")
403     group.add_option("--cache-time", dest="cache_time",
404                      action="store_true", help="configure with cached timing")
405     group.add_option("--mandir", dest="mandir", metavar="MANDIR",
406                      help="configure the man documentation install directory")
407     group.add_option("--with-dpdk", dest="with_dpdk", metavar="DPDK_BUILD",
408                      help="built with dpdk libraries located at DPDK_BUILD")
409     parser.add_option_group(group)
410
411     group = optparse.OptionGroup(parser, "Optimization Flags")
412     for i in ["s", "g"] + list(range(4)) + ["fast"]:
413         group.add_option("--O%s" % str(i), dest="optimize",
414                          action="store_const", const=i,
415                          help="compile with -O%s" % str(i))
416     parser.add_option_group(group)
417
418     group = optparse.OptionGroup(parser, "check")
419     group.add_option("-j", "--jobs", dest="jobs", metavar="N", type="int",
420                      help="Run N tests in parallel")
421     group.add_option("--tests", dest="tests", metavar="FILTER",
422                      help="""run specific tests and/or a test category
423                           eg, --tests=\"1-10 megaflow\"""")
424     parser.add_option_group(group)
425
426     group = optparse.OptionGroup(parser, "run")
427     group.add_option("-g", "--gdb", dest="gdb", action="store_true",
428                      help="run ovs-vswitchd under gdb")
429     group.add_option("--valgrind", dest="valgrind", action="store_true",
430                      help="run ovs-vswitchd under valgrind")
431     group.add_option("--dpdk", dest="dpdk", action="callback",
432                      callback=parse_subargs,
433                      help="run ovs-vswitchd with dpdk subopts (ended by --)")
434     group.add_option("--clang", dest="clang", action="store_true",
435                      help="Use binaries built by clang")
436     group.add_option("--user", dest="user", action="store", default="",
437                      help="run all daemons as a non root user")
438     group.add_option("--monitor", dest="monitor", action="store_true",
439                      help="run daemons with --monitor option")
440
441     parser.add_option_group(group)
442
443     options, args = parser.parse_args()
444
445     for arg in args:
446         if arg not in cmd_names:
447             print("Unknown argument " + arg)
448             doc()
449
450     if options.clang:
451         set_path(BUILD_CLANG)
452     else:
453         set_path(BUILD_GCC)
454
455     try:
456         os.chdir(OVS_SRC)
457     except OSError:
458         print("Missing %s." % OVS_SRC)
459         doc()
460
461     for arg in args:
462         for cmd in commands:
463             if arg == cmd.__name__:
464                 cmd()
465
466
467 if __name__ == '__main__':
468     main()