]> git.proxmox.com Git - mirror_ovs.git/blob - tests/test-jsonrpc.py
tests: Log commands being executed for async message control test.
[mirror_ovs.git] / tests / test-jsonrpc.py
1 # Copyright (c) 2009, 2010, 2011 Nicira, Inc.
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
15 from __future__ import print_function
16
17 import argparse
18 import errno
19 import os
20 import sys
21
22 import ovs.daemon
23 import ovs.json
24 import ovs.jsonrpc
25 import ovs.poller
26 import ovs.stream
27
28
29 def handle_rpc(rpc, msg):
30 done = False
31 reply = None
32
33 if msg.type == ovs.jsonrpc.Message.T_REQUEST:
34 if msg.method == "echo":
35 reply = ovs.jsonrpc.Message.create_reply(msg.params, msg.id)
36 else:
37 reply = ovs.jsonrpc.Message.create_error(
38 {"error": "unknown method"}, msg.id)
39 sys.stderr.write("unknown request %s" % msg.method)
40 elif msg.type == ovs.jsonrpc.Message.T_NOTIFY:
41 if msg.method == "shutdown":
42 done = True
43 else:
44 rpc.error(errno.ENOTTY)
45 sys.stderr.write("unknown notification %s" % msg.method)
46 else:
47 rpc.error(errno.EPROTO)
48 sys.stderr.write("unsolicited JSON-RPC reply or error\n")
49
50 if reply:
51 rpc.send(reply)
52 return done
53
54
55 def do_listen(name):
56 if sys.platform != 'win32' or (
57 ovs.daemon._detach and ovs.daemon._detached):
58 # On Windows the child is a new process created which should be the
59 # one that creates the PassiveStream. Without this check, the new
60 # child process will create a new PassiveStream overwriting the one
61 # that the parent process created.
62 error, pstream = ovs.stream.PassiveStream.open(name)
63 if error:
64 sys.stderr.write("could not listen on \"%s\": %s\n"
65 % (name, os.strerror(error)))
66 sys.exit(1)
67
68 ovs.daemon.daemonize()
69
70 rpcs = []
71 done = False
72 while True:
73 # Accept new connections.
74 error, stream = pstream.accept()
75 if stream:
76 rpcs.append(ovs.jsonrpc.Connection(stream))
77 elif error != errno.EAGAIN:
78 sys.stderr.write("PassiveStream.accept() failed\n")
79 sys.exit(1)
80
81 # Service existing connections.
82 dead_rpcs = []
83 for rpc in rpcs:
84 rpc.run()
85
86 error = 0
87 if not rpc.get_backlog():
88 error, msg = rpc.recv()
89 if not error:
90 if handle_rpc(rpc, msg):
91 done = True
92
93 error = rpc.get_status()
94 if error:
95 rpc.close()
96 dead_rpcs.append(rpc)
97 rpcs = [rpc for rpc in rpcs if rpc not in dead_rpcs]
98
99 if done and not rpcs:
100 break
101
102 poller = ovs.poller.Poller()
103 pstream.wait(poller)
104 for rpc in rpcs:
105 rpc.wait(poller)
106 if not rpc.get_backlog():
107 rpc.recv_wait(poller)
108 poller.block()
109 pstream.close()
110
111
112 def do_request(name, method, params_string):
113 params = ovs.json.from_string(params_string)
114 msg = ovs.jsonrpc.Message.create_request(method, params)
115 s = msg.is_valid()
116 if s:
117 sys.stderr.write("not a valid JSON-RPC request: %s\n" % s)
118 sys.exit(1)
119
120 error, stream = ovs.stream.Stream.open_block(ovs.stream.Stream.open(name))
121 if error:
122 sys.stderr.write("could not open \"%s\": %s\n"
123 % (name, os.strerror(error)))
124 sys.exit(1)
125
126 rpc = ovs.jsonrpc.Connection(stream)
127
128 error = rpc.send(msg)
129 if error:
130 sys.stderr.write("could not send request: %s\n" % os.strerror(error))
131 sys.exit(1)
132
133 error, msg = rpc.recv_block()
134 if error:
135 sys.stderr.write("error waiting for reply: %s\n" % os.strerror(error))
136 sys.exit(1)
137
138 print(ovs.json.to_string(msg.to_json()))
139
140 rpc.close()
141
142
143 def do_notify(name, method, params_string):
144 params = ovs.json.from_string(params_string)
145 msg = ovs.jsonrpc.Message.create_notify(method, params)
146 s = msg.is_valid()
147 if s:
148 sys.stderr.write("not a valid JSON-RPC notification: %s\n" % s)
149 sys.exit(1)
150
151 error, stream = ovs.stream.Stream.open_block(ovs.stream.Stream.open(name))
152 if error:
153 sys.stderr.write("could not open \"%s\": %s\n"
154 % (name, os.strerror(error)))
155 sys.exit(1)
156
157 rpc = ovs.jsonrpc.Connection(stream)
158
159 error = rpc.send_block(msg)
160 if error:
161 sys.stderr.write("could not send notification: %s\n"
162 % os.strerror(error))
163 sys.exit(1)
164
165 rpc.close()
166
167
168 def main(argv):
169
170 parser = argparse.ArgumentParser(
171 description="JSON-RPC test utility for Python.",
172 formatter_class=argparse.RawDescriptionHelpFormatter)
173
174 commands = {"listen": (do_listen, 1),
175 "request": (do_request, 3),
176 "notify": (do_notify, 3),
177 "help": (parser.print_help, (0,))}
178
179 group_description = """\
180 listen LOCAL listen for connections on LOCAL
181 request REMOTE METHOD PARAMS send request, print reply
182 notify REMOTE METHOD PARAMS send notification and exit
183 """ + ovs.stream.usage("JSON-RPC")
184
185 group = parser.add_argument_group(title="Commands",
186 description=group_description)
187 group.add_argument('command', metavar="COMMAND", nargs=1,
188 choices=commands, help="Command to use.")
189 group.add_argument('command_args', metavar="ARG", nargs='*',
190 help="Arguments to COMMAND.")
191
192 ovs.daemon.add_args(parser)
193 args = parser.parse_args()
194 ovs.daemon.handle_args(args)
195
196 command_name = args.command[0]
197 args = args.command_args
198 if command_name not in commands:
199 sys.stderr.write("%s: unknown command \"%s\" "
200 "(use --help for help)\n" % (argv[0], command_name))
201 sys.exit(1)
202
203 func, n_args = commands[command_name]
204 if type(n_args) == tuple:
205 if len(args) < n_args[0]:
206 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
207 "only %d provided\n"
208 % (argv[0], command_name, n_args, len(args)))
209 sys.exit(1)
210 elif type(n_args) == int:
211 if len(args) != n_args:
212 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
213 "provided\n"
214 % (argv[0], command_name, n_args, len(args)))
215 sys.exit(1)
216 else:
217 assert False
218
219 func(*args)
220
221
222 if __name__ == '__main__':
223 main(sys.argv)