]> git.proxmox.com Git - mirror_ovs.git/blame - tests/test-jsonrpc.py
ovs-dev.py: Build with both GCC and Clang.
[mirror_ovs.git] / tests / test-jsonrpc.py
CommitLineData
e0edde6f 1# Copyright (c) 2009, 2010, 2011 Nicira, Inc.
99155935
BP
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at:
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
b153e667 15import argparse
99155935 16import errno
99155935
BP
17import os
18import sys
19
20import ovs.daemon
21import ovs.json
22import ovs.jsonrpc
23import ovs.poller
24import ovs.stream
25
e60a5e26 26
99155935
BP
27def handle_rpc(rpc, msg):
28 done = False
29 reply = None
30
31 if msg.type == ovs.jsonrpc.Message.T_REQUEST:
32 if msg.method == "echo":
33 reply = ovs.jsonrpc.Message.create_reply(msg.params, msg.id)
34 else:
35 reply = ovs.jsonrpc.Message.create_error(
36 {"error": "unknown method"}, msg.id)
37 sys.stderr.write("unknown request %s" % msg.method)
38 elif msg.type == ovs.jsonrpc.Message.T_NOTIFY:
39 if msg.method == "shutdown":
40 done = True
41 else:
42 rpc.error(errno.ENOTTY)
43 sys.stderr.write("unknown notification %s" % msg.method)
44 else:
45 rpc.error(errno.EPROTO)
46 sys.stderr.write("unsolicited JSON-RPC reply or error\n")
e60a5e26 47
99155935
BP
48 if reply:
49 rpc.send(reply)
50 return done
51
e60a5e26 52
99155935 53def do_listen(name):
99155935
BP
54 error, pstream = ovs.stream.PassiveStream.open(name)
55 if error:
56 sys.stderr.write("could not listen on \"%s\": %s\n"
57 % (name, os.strerror(error)))
58 sys.exit(1)
59
60 ovs.daemon.daemonize()
61
62 rpcs = []
63 done = False
64 while True:
65 # Accept new connections.
66 error, stream = pstream.accept()
67 if stream:
68 rpcs.append(ovs.jsonrpc.Connection(stream))
69 elif error != errno.EAGAIN:
70 sys.stderr.write("PassiveStream.accept() failed\n")
71 sys.exit(1)
72
73 # Service existing connections.
74 dead_rpcs = []
75 for rpc in rpcs:
76 rpc.run()
77
78 error = 0
79 if not rpc.get_backlog():
80 error, msg = rpc.recv()
81 if not error:
82 if handle_rpc(rpc, msg):
83 done = True
84
85 error = rpc.get_status()
86 if error:
87 rpc.close()
88 dead_rpcs.append(rpc)
89 rpcs = [rpc for rpc in rpcs if not rpc in dead_rpcs]
90
91 if done and not rpcs:
92 break
93
94 poller = ovs.poller.Poller()
95 pstream.wait(poller)
96 for rpc in rpcs:
97 rpc.wait(poller)
98 if not rpc.get_backlog():
99 rpc.recv_wait(poller)
100 poller.block()
101 pstream.close()
102
e60a5e26 103
99155935
BP
104def do_request(name, method, params_string):
105 params = ovs.json.from_string(params_string)
106 msg = ovs.jsonrpc.Message.create_request(method, params)
107 s = msg.is_valid()
108 if s:
109 sys.stderr.write("not a valid JSON-RPC request: %s\n" % s)
110 sys.exit(1)
111
112 error, stream = ovs.stream.Stream.open_block(ovs.stream.Stream.open(name))
113 if error:
114 sys.stderr.write("could not open \"%s\": %s\n"
115 % (name, os.strerror(error)))
116 sys.exit(1)
117
118 rpc = ovs.jsonrpc.Connection(stream)
119
120 error = rpc.send(msg)
121 if error:
122 sys.stderr.write("could not send request: %s\n" % os.strerror(error))
123 sys.exit(1)
124
125 error, msg = rpc.recv_block()
126 if error:
127 sys.stderr.write("error waiting for reply: %s\n" % os.strerror(error))
128 sys.exit(1)
e60a5e26 129
99155935
BP
130 print ovs.json.to_string(msg.to_json())
131
132 rpc.close()
e60a5e26
EJ
133
134
99155935
BP
135def do_notify(name, method, params_string):
136 params = ovs.json.from_string(params_string)
137 msg = ovs.jsonrpc.Message.create_notify(method, params)
138 s = msg.is_valid()
139 if s:
140 sys.stderr.write("not a valid JSON-RPC notification: %s\n" % s)
141 sys.exit(1)
142
143 error, stream = ovs.stream.Stream.open_block(ovs.stream.Stream.open(name))
144 if error:
145 sys.stderr.write("could not open \"%s\": %s\n"
146 % (name, os.strerror(error)))
147 sys.exit(1)
148
149 rpc = ovs.jsonrpc.Connection(stream)
150
151 error = rpc.send_block(msg)
152 if error:
153 sys.stderr.write("could not send notification: %s\n"
154 % os.strerror(error))
155 sys.exit(1)
156
157 rpc.close()
158
e60a5e26 159
99155935 160def main(argv):
99155935 161
b153e667
EJ
162 parser = argparse.ArgumentParser(
163 description="JSON-RPC test utility for Python.",
164 formatter_class=argparse.RawDescriptionHelpFormatter)
99155935
BP
165
166 commands = {"listen": (do_listen, 1),
167 "request": (do_request, 3),
168 "notify": (do_notify, 3),
b153e667
EJ
169 "help": (parser.print_help, (0,))}
170
171 group_description = """\
172listen LOCAL listen for connections on LOCAL
173request REMOTE METHOD PARAMS send request, print reply
174notify REMOTE METHOD PARAMS send notification and exit
175""" + ovs.stream.usage("JSON-RPC")
176
177 group = parser.add_argument_group(title="Commands",
178 description=group_description)
179 group.add_argument('command', metavar="COMMAND", nargs=1,
180 choices=commands, help="Command to use.")
181 group.add_argument('command_args', metavar="ARG", nargs='*',
182 help="Arguments to COMMAND.")
183
184 ovs.daemon.add_args(parser)
185 args = parser.parse_args()
186 ovs.daemon.handle_args(args)
187
188 command_name = args.command[0]
189 args = args.command_args
99155935
BP
190 if not command_name in commands:
191 sys.stderr.write("%s: unknown command \"%s\" "
d2dc8f58 192 "(use --help for help)\n" % (argv[0], command_name))
99155935
BP
193 sys.exit(1)
194
195 func, n_args = commands[command_name]
196 if type(n_args) == tuple:
197 if len(args) < n_args[0]:
198 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
199 "only %d provided\n"
d2dc8f58 200 % (argv[0], command_name, n_args, len(args)))
99155935
BP
201 sys.exit(1)
202 elif type(n_args) == int:
203 if len(args) != n_args:
204 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
205 "provided\n"
d2dc8f58 206 % (argv[0], command_name, n_args, len(args)))
99155935
BP
207 sys.exit(1)
208 else:
209 assert False
210
211 func(*args)
212
e60a5e26 213
99155935
BP
214if __name__ == '__main__':
215 main(sys.argv)