ovs-ofctl: Support bucket commands
[cascardo/ovs.git] / utilities / ovs-dev.py
1 #!/usr/bin/python
2 # Copyright (c) 2013, 2014 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 /lib/modules/%s/extra/openvswitch.ko" % uname())
273     except subprocess.CalledProcessError, e:
274         pass  # Module isn't installed
275
276     conf()
277     make()
278     make("modules_install")
279
280     _sh("modprobe", "openvswitch")
281     _sh("dmesg | grep openvswitch | tail -1")
282 commands.append(modinst)
283
284
285 def env():
286     print "export PATH=" + ENV["PATH"]
287 commands.append(env)
288
289
290 def doc():
291     parser.print_help()
292     print \
293 """
294 This program is designed to help developers build and run Open vSwitch without
295 necessarily needing to know the gory details. Given some basic requirements
296 (described below), it can be used to build and run Open vSwitch, keeping
297 runtime files in the user's home directory.
298
299 Basic Configuration:
300     # This section can be run as a script on ubuntu systems.
301
302     # First install the basic requirements needed to build Open vSwitch.
303     sudo apt-get install git build-essential libtool autoconf pkg-config \\
304             libssl-dev gdb linux-headers-`uname -r`
305
306     # Next clone the Open vSwitch source.
307     git clone https://github.com/openvswitch/ovs.git %(ovs)s
308
309     # Setup environment variables.
310     `%(v)s env`
311
312     # Build the switch.
313     %(v)s conf make
314
315     # Install the kernel module
316     sudo insmod %(ovs)s/datapath/linux/openvswitch.ko
317
318     # Run the switch.
319     %(v)s run
320
321 Commands:
322     conf    - Configure the ovs source.
323     make    - Build the source (must have been configured).
324     check   - Run the unit tests.
325     tag     - Run ctags and cscope over the source.
326     kill    - Kill all running instances of ovs.
327     reset   - Reset any runtime configuration in %(run)s.
328     run     - Run ovs.
329     modinst - Build ovs and install the kernel module.
330     env     - Print the required path environment variable.
331     doc     - Print this message.
332 """ % {"ovs": OVS_SRC, "v": sys.argv[0], "run": ROOT}
333     sys.exit(0)
334 commands.append(doc)
335
336 def parse_subargs(option, opt_str, value, parser):
337     subopts = []
338
339     while parser.rargs:
340         dpdkarg = parser.rargs.pop(0)
341         if dpdkarg == "--":
342             break
343         subopts.append(dpdkarg)
344
345     setattr(parser.values, option.dest, subopts)
346
347 def main():
348     global options
349     global parser
350
351     description = "Open vSwitch developer configuration. Try `%prog doc`."
352     cmd_names = [c.__name__ for c in commands]
353     parser = optparse.OptionParser(usage="usage: %prog"
354                                    + " [options] [%s] ..."
355                                    % "|".join(cmd_names),
356                                    description=description)
357
358     group = optparse.OptionGroup(parser, "conf")
359     group.add_option("--disable-Werror", dest="werror", action="store_false",
360                      default=True, help="compile without the Werror flag")
361     group.add_option("--cache-time", dest="cache_time",
362                      action="store_true", help="configure with cached timing")
363     group.add_option("--mandir", dest="mandir", metavar="MANDIR",
364                      help="configure the man documentation install directory")
365     group.add_option("--with-dpdk", dest="with_dpdk", metavar="DPDK_BUILD",
366                      help="built with dpdk libraries located at DPDK_BUILD");
367     parser.add_option_group(group)
368
369     group = optparse.OptionGroup(parser, "Optimization Flags")
370     for i in ["s", "g"] + range(4) + ["fast"]:
371         group.add_option("--O%s" % str(i), dest="optimize",
372                          action="store_const", const=i,
373                          help="compile with -O%s" % str(i))
374     parser.add_option_group(group)
375
376     group = optparse.OptionGroup(parser, "check")
377     group.add_option("-j", "--jobs", dest="jobs", metavar="N", type="int",
378                      help="Run N tests in parallel")
379     group.add_option("--tests", dest="tests", metavar="FILTER",
380                      help="""run specific tests and/or a test category
381                           eg, --tests=\"1-10 megaflow\"""")
382     parser.add_option_group(group)
383
384     group = optparse.OptionGroup(parser, "run")
385     group.add_option("-g", "--gdb", dest="gdb", action="store_true",
386                      help="run ovs-vswitchd under gdb")
387     group.add_option("--valgrind", dest="valgrind", action="store_true",
388                      help="run ovs-vswitchd under valgrind")
389     group.add_option("--dpdk", dest="dpdk", action="callback",
390                      callback=parse_subargs,
391                      help="run ovs-vswitchd with dpdk subopts (ended by --)")
392     group.add_option("--clang", dest="clang", action="store_true",
393                      help="Use binaries built by clang")
394
395     parser.add_option_group(group)
396
397     options, args = parser.parse_args()
398
399     for arg in args:
400         if arg not in cmd_names:
401             print "Unknown argument " + arg
402             doc()
403
404     if options.clang:
405         set_path(BUILD_CLANG)
406     else:
407         set_path(BUILD_GCC)
408
409     try:
410         os.chdir(OVS_SRC)
411     except OSError:
412         print "Missing %s." % OVS_SRC
413         doc()
414
415     for arg in args:
416         for cmd in commands:
417             if arg == cmd.__name__:
418                 cmd()
419
420
421 if __name__ == '__main__':
422     main()