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