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