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