]> git.proxmox.com Git - ovs.git/blame - tests/test-jsonrpc.py
pktbuf: Move from 'ofproto' to 'lib'.
[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
8ea171ab
RB
15from __future__ import print_function
16
b153e667 17import argparse
99155935 18import errno
99155935
BP
19import os
20import sys
21
22import ovs.daemon
23import ovs.json
24import ovs.jsonrpc
25import ovs.poller
26import ovs.stream
27
e60a5e26 28
99155935
BP
29def 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")
e60a5e26 49
99155935
BP
50 if reply:
51 rpc.send(reply)
52 return done
53
e60a5e26 54
99155935 55def do_listen(name):
99155935
BP
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)
603e325f 91 rpcs = [rpc for rpc in rpcs if rpc not in dead_rpcs]
99155935
BP
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
e60a5e26 105
99155935
BP
106def 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)
e60a5e26 131
8ea171ab 132 print(ovs.json.to_string(msg.to_json()))
99155935
BP
133
134 rpc.close()
e60a5e26
EJ
135
136
99155935
BP
137def 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
e60a5e26 161
99155935 162def main(argv):
99155935 163
b153e667
EJ
164 parser = argparse.ArgumentParser(
165 description="JSON-RPC test utility for Python.",
166 formatter_class=argparse.RawDescriptionHelpFormatter)
99155935
BP
167
168 commands = {"listen": (do_listen, 1),
169 "request": (do_request, 3),
170 "notify": (do_notify, 3),
b153e667
EJ
171 "help": (parser.print_help, (0,))}
172
173 group_description = """\
174listen LOCAL listen for connections on LOCAL
175request REMOTE METHOD PARAMS send request, print reply
176notify 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
603e325f 192 if command_name not in commands:
99155935 193 sys.stderr.write("%s: unknown command \"%s\" "
d2dc8f58 194 "(use --help for help)\n" % (argv[0], command_name))
99155935
BP
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"
d2dc8f58 202 % (argv[0], command_name, n_args, len(args)))
99155935
BP
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"
d2dc8f58 208 % (argv[0], command_name, n_args, len(args)))
99155935
BP
209 sys.exit(1)
210 else:
211 assert False
212
213 func(*args)
214
e60a5e26 215
99155935
BP
216if __name__ == '__main__':
217 main(sys.argv)