Set release dates for 2.3.0.
[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     make("check")
148 commands.append(check)
149
150
151 def tag():
152     ctags = ['ctags', '-R', '-f', '.tags']
153
154     try:
155         _sh(*(ctags + ['--exclude="datapath/"']))
156     except:
157         try:
158             _sh(*ctags)  # Some versions of ctags don't have --exclude
159         except:
160             pass
161
162     try:
163         _sh('cscope', '-R', '-b')
164     except:
165         pass
166 commands.append(tag)
167
168
169 def kill():
170     for proc in ["ovs-vswitchd", "ovsdb-server"]:
171         if os.path.exists("%s/run/openvswitch/%s.pid" % (ROOT, proc)):
172             _sh("ovs-appctl", "-t", proc, "exit", check=False)
173             time.sleep(.1)
174         _sh("sudo", "killall", "-q", "-2", proc, check=False)
175 commands.append(kill)
176
177
178 def reset():
179     kill()
180     if os.path.exists(ROOT):
181         shutil.rmtree(ROOT)
182     for dp in _sh("ovs-dpctl dump-dps", capture=True):
183         _sh("ovs-dpctl", "del-dp", dp.strip())
184 commands.append(reset)
185
186
187 def run():
188     kill()
189     for d in ["log", "run"]:
190         d = "%s/%s" % (ROOT, d)
191         shutil.rmtree(d, ignore_errors=True)
192         os.makedirs(d)
193
194     pki_dir = ROOT + "/pki"
195     if not os.path.exists(pki_dir):
196         os.mkdir(pki_dir)
197         os.chdir(pki_dir)
198         _sh("ovs-pki init")
199         _sh("ovs-pki req+sign ovsclient")
200         os.chdir(OVS_SRC)
201
202     if not os.path.exists(ROOT + "/conf.db"):
203         _sh("ovsdb-tool", "create", ROOT + "/conf.db",
204             OVS_SRC + "/vswitchd/vswitch.ovsschema")
205
206     opts = ["--pidfile", "--log-file", "--enable-dummy"]
207
208     _sh(*(["ovsdb-server",
209            "--remote=punix:%s/run/db.sock" % ROOT,
210            "--remote=db:Open_vSwitch,Open_vSwitch,manager_options",
211            "--private-key=db:Open_vSwitch,SSL,private_key",
212            "--certificate=db:Open_vSwitch,SSL,certificate",
213            "--bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert",
214            "--detach", "-vconsole:off"] + opts))
215
216     _sh("ovs-vsctl --no-wait --bootstrap set-ssl %s/ovsclient-privkey.pem" \
217         " %s/ovsclient-cert.pem %s/vswitchd.cacert"
218         % (pki_dir, pki_dir, pki_dir))
219     version = _sh("ovs-vsctl --no-wait --version", capture=True)
220     version = version[0].strip().split()[3]
221     root_uuid = _sh("ovs-vsctl --no-wait --bare list Open_vSwitch",
222                     capture=True)[0].strip()
223     _sh("ovs-vsctl --no-wait set Open_vSwitch %s ovs_version=%s"
224         % (root_uuid, version))
225
226     cmd = [BUILD_GCC + "/vswitchd/ovs-vswitchd"]
227     if options.gdb:
228         cmd = ["gdb", "--args"] + cmd
229     elif options.valgrind:
230         cmd = ["valgrind", "--track-origins=yes", "--leak-check=full",
231                "--suppressions=%s/tests/glibc.supp" % OVS_SRC,
232                "--suppressions=%s/tests/openssl.supp" % OVS_SRC] + cmd
233     else:
234         cmd = ["sudo"] + cmd
235         opts = opts + ["-vconsole:off", "--detach"]
236     _sh(*(cmd + opts))
237 commands.append(run)
238
239
240 def modinst():
241     if not os.path.exists("/lib/modules"):
242         print "Missing modules directory.  Is this a Linux system?"
243         sys.exit(1)
244
245     try:
246         _sh("rmmod", "openvswitch")
247     except subprocess.CalledProcessError, e:
248         pass  # Module isn't loaded
249
250     try:
251         _sh("rm /lib/modules/%s/extra/openvswitch.ko" % uname())
252     except subprocess.CalledProcessError, e:
253         pass  # Module isn't installed
254
255     conf()
256     make()
257     make("modules_install")
258
259     _sh("modprobe", "openvswitch")
260     _sh("dmesg | grep openvswitch | tail -1")
261 commands.append(modinst)
262
263
264 def env():
265     print "export PATH=" + ENV["PATH"]
266 commands.append(env)
267
268
269 def doc():
270     parser.print_help()
271     print \
272 """
273 This program is designed to help developers build and run Open vSwitch without
274 necessarily needing to know the gory details. Given some basic requirements
275 (described below), it can be used to build and run Open vSwitch, keeping
276 runtime files in the user's home directory.
277
278 Basic Configuration:
279     # This section can be run as a script on ubuntu systems.
280
281     # First install the basic requirements needed to build Open vSwitch.
282     sudo apt-get install git build-essential libtool autoconf pkg-config \\
283             libssl-dev gdb linux-headers-`uname -r`
284
285     # Next clone the Open vSwitch source.
286     git clone https://github.com/openvswitch/ovs.git %(ovs)s
287
288     # Setup environment variables.
289     `%(v)s env`
290
291     # Build the switch.
292     %(v)s conf make
293
294     # Install the kernel module
295     sudo insmod %(ovs)s/datapath/linux/openvswitch.ko
296
297     # Run the switch.
298     %(v)s run
299
300 Commands:
301     conf    - Configure the ovs source.
302     make    - Build the source (must have been configured).
303     check   - Run the unit tests.
304     tag     - Run ctags and cscope over the source.
305     kill    - Kill all running instances of ovs.
306     reset   - Reset any runtime configuration in %(run)s.
307     run     - Run ovs.
308     modinst - Build ovs and install the kernel module.
309     env     - Print the required path environment variable.
310     doc     - Print this message.
311 """ % {"ovs": OVS_SRC, "v": sys.argv[0], "run": ROOT}
312     sys.exit(0)
313 commands.append(doc)
314
315
316 def main():
317     global options
318     global parser
319
320     description = "Open vSwitch developer configuration. Try `%prog doc`."
321     cmd_names = [c.__name__ for c in commands]
322     parser = optparse.OptionParser(usage="usage: %prog"
323                                    + " [options] [%s] ..."
324                                    % "|".join(cmd_names),
325                                    description=description)
326
327     group = optparse.OptionGroup(parser, "conf")
328     group.add_option("--disable-Werror", dest="werror", action="store_false",
329                      default=True, help="compile without the Werror flag")
330     group.add_option("--cache-time", dest="cache_time",
331                      action="store_true", help="configure with cached timing")
332     group.add_option("--mandir", dest="mandir", metavar="MANDIR",
333                      help="configure the man documentation install directory")
334     group.add_option("--with-dpdk", dest="with_dpdk", metavar="DPDK_BUILD",
335                      help="built with dpdk libraries located at DPDK_BUILD");
336
337     for i in range(4):
338         group.add_option("--O%d" % i, dest="optimize", action="store_const",
339                          const=i, help="compile with -O%d" % i)
340     parser.add_option_group(group)
341
342     group = optparse.OptionGroup(parser, "run")
343     group.add_option("-g", "--gdb", dest="gdb", action="store_true",
344                      help="run ovs-vswitchd under gdb")
345     group.add_option("--valgrind", dest="valgrind", action="store_true",
346                      help="run ovs-vswitchd under valgrind")
347     parser.add_option_group(group)
348
349     options, args = parser.parse_args()
350
351     for arg in args:
352         if arg not in cmd_names:
353             print "Unknown argument " + arg
354             doc()
355
356     try:
357         os.chdir(OVS_SRC)
358     except OSError:
359         print "Missing %s." % OVS_SRC
360         doc()
361
362     for arg in args:
363         for cmd in commands:
364             if arg == cmd.__name__:
365                 cmd()
366
367
368 if __name__ == '__main__':
369     main()