1 # Copyright (c) 2009, 2010, 2011 Nicira, Inc.
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:
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 from __future__ import print_function
29 def handle_rpc(rpc, msg):
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)
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":
44 rpc.error(errno.ENOTTY)
45 sys.stderr.write("unknown notification %s" % msg.method)
47 rpc.error(errno.EPROTO)
48 sys.stderr.write("unsolicited JSON-RPC reply or error\n")
56 error, pstream = ovs.stream.PassiveStream.open(name)
58 sys.stderr.write("could not listen on \"%s\": %s\n"
59 % (name, os.strerror(error)))
62 ovs.daemon.daemonize()
67 # Accept new connections.
68 error, stream = pstream.accept()
70 rpcs.append(ovs.jsonrpc.Connection(stream))
71 elif error != errno.EAGAIN:
72 sys.stderr.write("PassiveStream.accept() failed\n")
75 # Service existing connections.
81 if not rpc.get_backlog():
82 error, msg = rpc.recv()
84 if handle_rpc(rpc, msg):
87 error = rpc.get_status()
91 rpcs = [rpc for rpc in rpcs if rpc not in dead_rpcs]
96 poller = ovs.poller.Poller()
100 if not rpc.get_backlog():
101 rpc.recv_wait(poller)
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)
111 sys.stderr.write("not a valid JSON-RPC request: %s\n" % s)
114 error, stream = ovs.stream.Stream.open_block(ovs.stream.Stream.open(name))
116 sys.stderr.write("could not open \"%s\": %s\n"
117 % (name, os.strerror(error)))
120 rpc = ovs.jsonrpc.Connection(stream)
122 error = rpc.send(msg)
124 sys.stderr.write("could not send request: %s\n" % os.strerror(error))
127 error, msg = rpc.recv_block()
129 sys.stderr.write("error waiting for reply: %s\n" % os.strerror(error))
132 print(ovs.json.to_string(msg.to_json()))
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)
142 sys.stderr.write("not a valid JSON-RPC notification: %s\n" % s)
145 error, stream = ovs.stream.Stream.open_block(ovs.stream.Stream.open(name))
147 sys.stderr.write("could not open \"%s\": %s\n"
148 % (name, os.strerror(error)))
151 rpc = ovs.jsonrpc.Connection(stream)
153 error = rpc.send_block(msg)
155 sys.stderr.write("could not send notification: %s\n"
156 % os.strerror(error))
164 parser = argparse.ArgumentParser(
165 description="JSON-RPC test utility for Python.",
166 formatter_class=argparse.RawDescriptionHelpFormatter)
168 commands = {"listen": (do_listen, 1),
169 "request": (do_request, 3),
170 "notify": (do_notify, 3),
171 "help": (parser.print_help, (0,))}
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")
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.")
186 ovs.daemon.add_args(parser)
187 args = parser.parse_args()
188 ovs.daemon.handle_args(args)
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))
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 "
202 % (argv[0], command_name, n_args, len(args)))
204 elif type(n_args) == int:
205 if len(args) != n_args:
206 sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
208 % (argv[0], command_name, n_args, len(args)))
216 if __name__ == '__main__':