]> git.proxmox.com Git - mirror_ovs.git/blob - tests/test-jsonrpc.py
ovn-northd: Sort options in put_dhcp(v6)_opts.
[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 error, pstream = ovs.stream.PassiveStream.open(name)
57 if error:
58 sys.stderr.write("could not listen on \"%s\": %s\n"
59 % (name, os.strerror(error)))
60 sys.exit(1)
61
62 ovs.daemon.daemonize()
63
64 rpcs = []
65 done = False
66 while True:
67 # Accept new connections.
68 error, stream = pstream.accept()
69 if stream:
70 rpcs.append(ovs.jsonrpc.Connection(stream))
71 elif error != errno.EAGAIN:
72 sys.stderr.write("PassiveStream.accept() failed\n")
73 sys.exit(1)
74
75 # Service existing connections.
76 dead_rpcs = []
77 for rpc in rpcs:
78 rpc.run()
79
80 error = 0
81 if not rpc.get_backlog():
82 error, msg = rpc.recv()
83 if not error:
84 if handle_rpc(rpc, msg):
85 done = True
86
87 error = rpc.get_status()
88 if error:
89 rpc.close()
90 dead_rpcs.append(rpc)
91 rpcs = [rpc for rpc in rpcs if rpc not in dead_rpcs]
92
93 if done and not rpcs:
94 break
95
96 poller = ovs.poller.Poller()
97 pstream.wait(poller)
98 for rpc in rpcs:
99 rpc.wait(poller)
100 if not rpc.get_backlog():
101 rpc.recv_wait(poller)
102 poller.block()
103 pstream.close()
104
105
106 def do_request(name, method, params_string):
107 params = ovs.json.from_string(params_string)
108 msg = ovs.jsonrpc.Message.create_request(method, params)
109 s = msg.is_valid()
110 if s:
111 sys.stderr.write("not a valid JSON-RPC request: %s\n" % s)
112 sys.exit(1)
113
114 error, stream = ovs.stream.Stream.open_block(ovs.stream.Stream.open(name))
115 if error:
116 sys.stderr.write("could not open \"%s\": %s\n"
117 % (name, os.strerror(error)))
118 sys.exit(1)
119
120 rpc = ovs.jsonrpc.Connection(stream)
121
122 error = rpc.send(msg)
123 if error:
124 sys.stderr.write("could not send request: %s\n" % os.strerror(error))
125 sys.exit(1)
126
127 error, msg = rpc.recv_block()
128 if error:
129 sys.stderr.write("error waiting for reply: %s\n" % os.strerror(error))
130 sys.exit(1)
131
132 print(ovs.json.to_string(msg.to_json()))
133
134 rpc.close()
135
136
137 def do_notify(name, method, params_string):
138 params = ovs.json.from_string(params_string)
139 msg = ovs.jsonrpc.Message.create_notify(method, params)
140 s = msg.is_valid()
141 if s:
142 sys.stderr.write("not a valid JSON-RPC notification: %s\n" % s)
143 sys.exit(1)
144
145 error, stream = ovs.stream.Stream.open_block(ovs.stream.Stream.open(name))
146 if error:
147 sys.stderr.write("could not open \"%s\": %s\n"
148 % (name, os.strerror(error)))
149 sys.exit(1)
150
151 rpc = ovs.jsonrpc.Connection(stream)
152
153 error = rpc.send_block(msg)
154 if error:
155 sys.stderr.write("could not send notification: %s\n"
156 % os.strerror(error))
157 sys.exit(1)
158
159 rpc.close()
160
161
162 def main(argv):
163
164 parser = argparse.ArgumentParser(
165 description="JSON-RPC test utility for Python.",
166 formatter_class=argparse.RawDescriptionHelpFormatter)
167
168 commands = {"listen": (do_listen, 1),
169 "request": (do_request, 3),
170 "notify": (do_notify, 3),
171 "help": (parser.print_help, (0,))}
172
173 group_description = """\
174 listen LOCAL listen for connections on LOCAL
175 request REMOTE METHOD PARAMS send request, print reply
176 notify REMOTE METHOD PARAMS send notification and exit
177 """ + ovs.stream.usage("JSON-RPC")
178
179 group = parser.add_argument_group(title="Commands",
180 description=group_description)
181 group.add_argument('command', metavar="COMMAND", nargs=1,
182 choices=commands, help="Command to use.")
183 group.add_argument('command_args', metavar="ARG", nargs='*',
184 help="Arguments to COMMAND.")
185
186 ovs.daemon.add_args(parser)
187 args = parser.parse_args()
188 ovs.daemon.handle_args(args)
189
190 command_name = args.command[0]
191 args = args.command_args
192 if command_name not in commands:
193 sys.stderr.write("%s: unknown command \"%s\" "
194 "(use --help for help)\n" % (argv[0], command_name))
195 sys.exit(1)
196
197 func, n_args = commands[command_name]
198 if type(n_args) == tuple:
199 if len(args) < n_args[0]:
200 sys.stderr.write("%s: \"%s\" requires at least %d arguments but "
201 "only %d provided\n"
202 % (argv[0], command_name, n_args, len(args)))
203 sys.exit(1)
204 elif type(n_args) == int:
205 if len(args) != n_args:
206 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
207 "provided\n"
208 % (argv[0], command_name, n_args, len(args)))
209 sys.exit(1)
210 else:
211 assert False
212
213 func(*args)
214
215
216 if __name__ == '__main__':
217 main(sys.argv)