utilities: New helper script ovs-dev.py.
[sliver-openvswitch.git] / utilities / ovs-dev.py
1 #!/usr/bin/python
2 # Copyright (c) 2013 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 PATH = "%(ovs)s/utilities:%(ovs)s/ovsdb:%(ovs)s/vswitchd" % {"ovs": OVS_SRC}
28
29 ENV["CFLAGS"] = "-g -O0 -Wall -Wextra -Wno-deprecated-declarations"
30 ENV["PATH"] = PATH + ":" + ENV["PATH"]
31
32 options = None
33 parser = None
34 commands = []
35
36
37 def _sh(*args, **kwargs):
38     print "------> " + " ".join(args)
39     shell = len(args) == 1
40     if kwargs.get("capture", False):
41         proc = subprocess.Popen(args, stdout=subprocess.PIPE, shell=shell)
42         return proc.stdout.readlines()
43     elif kwargs.get("check", True):
44         subprocess.check_call(args, shell=shell)
45     else:
46         subprocess.call(args, shell=shell)
47
48
49 def uname():
50     return _sh("uname", "-r", capture=True)[0].strip()
51
52
53 def conf():
54     tag()
55     configure = ["./configure", "--prefix=" + ROOT, "--localstatedir=" + ROOT,
56                  "--with-logdir=%s/log" % ROOT, "--with-rundir=%s/run" % ROOT,
57                  "--with-linux=/lib/modules/%s/build" % uname(),
58                  "--with-dbdir=" + ROOT]
59
60     if options.werror:
61         configure.append("--enable-Werror")
62
63     if options.cache_time:
64         configure.append("--enable-cache-time")
65
66     if options.mandir:
67         configure.append("--mandir=" + options.mandir)
68
69     _sh("./boot.sh")
70     _sh(*configure)
71 commands.append(conf)
72
73
74 def make(args=""):
75     make = "make -s -j 8 " + args
76     try:
77         _sh("cgcc", "--version", capture=True)
78         make += " C=1"
79     except OSError:
80         pass
81     _sh(make)
82 commands.append(make)
83
84
85 def check():
86     make("check")
87 commands.append(check)
88
89
90 def tag():
91     ctags = ['ctags', '-R', '-f', '.tags']
92
93     try:
94         _sh(*(ctags + ['--exclude="datapath/"']))
95     except:
96         try:
97             _sh(*ctags)  # Some versions of ctags don't have --exclude
98         except:
99             pass
100
101     try:
102         _sh('cscope', '-R', '-b')
103     except:
104         pass
105 commands.append(tag)
106
107
108 def kill():
109     for proc in ["ovs-vswitchd", "ovsdb-server"]:
110         if os.path.exists("%s/run/openvswitch/%s.pid" % (ROOT, proc)):
111             _sh("ovs-appctl", "-t", proc, "exit", check=False)
112             time.sleep(.1)
113         _sh("sudo", "killall", "-q", "-2", proc, check=False)
114 commands.append(kill)
115
116
117 def reset():
118     kill()
119     if os.path.exists(ROOT):
120         shutil.rmtree(ROOT)
121     for dp in _sh("ovs-dpctl dump-dps", capture=True):
122         _sh("ovs-dpctl", "del-dp", dp.strip())
123 commands.append(reset)
124
125
126 def run():
127     kill()
128     for d in ["log", "run"]:
129         d = "%s/%s" % (ROOT, d)
130         shutil.rmtree(d, ignore_errors=True)
131         os.makedirs(d)
132
133     pki_dir = ROOT + "/pki"
134     if not os.path.exists(pki_dir):
135         os.mkdir(pki_dir)
136         os.chdir(pki_dir)
137         _sh("ovs-pki init")
138         _sh("ovs-pki req+sign ovsclient")
139         os.chdir(OVS_SRC)
140
141     if not os.path.exists(ROOT + "/conf.db"):
142         _sh("ovsdb-tool", "create", ROOT + "/conf.db",
143             OVS_SRC + "/vswitchd/vswitch.ovsschema")
144
145     opts = ["--pidfile", "--log-file", "--enable-dummy"]
146
147     _sh(*(["ovsdb-server",
148            "--remote=punix:%s/run/db.sock" % ROOT,
149            "--remote=db:Open_vSwitch,Open_vSwitch,manager_options",
150            "--private-key=db:Open_vSwitch,SSL,private_key",
151            "--certificate=db:Open_vSwitch,SSL,certificate",
152            "--bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert",
153            "--detach", "-vconsole:off"] + opts))
154
155     _sh("ovs-vsctl --no-wait --bootstrap set-ssl %s/ovsclient-privkey.pem" \
156         " %s/ovsclient-cert.pem %s/vswitchd.cacert"
157         % (pki_dir, pki_dir, pki_dir))
158     version = _sh("ovs-vsctl --no-wait --version", capture=True)
159     version = version[0].strip().split()[3]
160     root_uuid = _sh("ovs-vsctl --no-wait --bare list Open_vSwitch",
161                     capture=True)[0].strip()
162     _sh("ovs-vsctl --no-wait set Open_vSwitch %s ovs_version=%s"
163         % (root_uuid, version))
164
165     cmd = [OVS_SRC + "/vswitchd/ovs-vswitchd"]
166     if options.gdb:
167         cmd = ["gdb", "--args"] + cmd
168     elif options.valgrind:
169         cmd = ["valgrind", "--track-origins=yes"] + cmd
170     else:
171         cmd = ["sudo"] + cmd
172         opts = opts + ["-vconsole:off", "--detach"]
173     _sh(*(cmd + opts))
174 commands.append(run)
175
176
177 def modinst():
178     if not os.path.exists("/lib/modules"):
179         print "Missing modules directory.  Is this a Linux system?"
180         sys.exit(1)
181
182     try:
183         _sh("rmmod", "openvswitch")
184     except subprocess.CalledProcessError, e:
185         pass  # Module isn't loaded
186
187     try:
188         _sh("rm /lib/modules/%s/extra/openvswitch.ko" % uname())
189     except subprocess.CalledProcessError, e:
190         pass  # Module isn't installed
191
192     conf()
193     make()
194     make("modules_install")
195
196     _sh("modprobe", "openvswitch")
197     _sh("dmesg | grep openvswitch | tail -1")
198 commands.append(modinst)
199
200
201 def env():
202     print "export PATH=" + ENV["PATH"]
203 commands.append(env)
204
205
206 def doc():
207     parser.print_help()
208     print \
209 """
210 This program is designed to help developers build and run Open vSwitch without
211 necessarily needing to know the gory details. Given some basic requirements
212 (described below), it can be used to build and run Open vSwitch, keeping
213 runtime files in the user's home directory.
214
215 Basic Configuration:
216     # This section can be run as a script on ubuntu systems.
217
218     # First install the basic requirements needed to build Open vSwitch.
219     sudo apt-get install git build-essential libtool autoconf pkg-config \\
220             libssl-dev pkg-config gdb linux-headers-`uname -r`
221
222     # Next clone the Open vSwitch source.
223     git clone git://git.openvswitch.org/openvswitch %(ovs)s
224
225     # Setup environment variables.
226     `%(v)s env`
227
228     # Build the switch.
229     %(v)s conf make
230
231     # Install the kernel module
232     sudo insmod %(ovs)s/datapath/linux/openvswitch.ko
233
234     # Run the switch.
235     %(v)s run
236
237 Commands:
238     conf    - Configure the ovs source.
239     make    - Build the source (must have been configured).
240     check   - Run the unit tests.
241     tag     - Run ctags and cscope over the source.
242     kill    - Kill all running instances of ovs.
243     reset   - Reset any runtime configuration in %(run)s.
244     run     - Run ovs.
245     modinst - Build ovs and install the kernel module.
246     env     - Print the required path environment variable.
247     doc     - Print this message.
248 """ % {"ovs": OVS_SRC, "v": sys.argv[0], "run": ROOT}
249     sys.exit(0)
250 commands.append(doc)
251
252
253 def main():
254     global options
255     global parser
256
257     description = "Open vSwitch developer configuration. Try `%prog doc`."
258     cmd_names = [c.__name__ for c in commands]
259     parser = optparse.OptionParser(usage="usage: %prog"
260                                    + " [options] [%s] ..."
261                                    % "|".join(cmd_names),
262                                    description=description)
263
264     group = optparse.OptionGroup(parser, "conf")
265     group.add_option("--disable-Werror", dest="werror", action="store_false",
266                      default=True, help="compile without the Werror flag")
267     group.add_option("--cache-time", dest="cache_time",
268                      action="store_true", help="configure with cached timing")
269     group.add_option("--mandir", dest="mandir", metavar="MANDIR",
270                      help="configure the man documentation install directory")
271     parser.add_option_group(group)
272
273     group = optparse.OptionGroup(parser, "run")
274     group.add_option("-g", "--gdb", dest="gdb", action="store_true",
275                      help="run ovs-vswitchd under gdb")
276     group.add_option("--valgrind", dest="valgrind", action="store_true",
277                      help="run ovs-vswitchd under valgrind")
278     parser.add_option_group(group)
279
280     options, args = parser.parse_args()
281
282     for arg in args:
283         if arg not in cmd_names:
284             print "Unknown argument " + arg
285             doc()
286
287     try:
288         os.chdir(OVS_SRC)
289     except OSError:
290         print "Missing %s." % OVS_SRC
291         doc()
292
293     for arg in args:
294         for cmd in commands:
295             if arg == cmd.__name__:
296                 cmd()
297
298
299 if __name__ == '__main__':
300     main()