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