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 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
)
64 sys
.stderr
.write("could not listen on \"%s\": %s\n"
65 % (name
, os
.strerror(error
)))
68 ovs
.daemon
.daemonize()
73 # Accept new connections.
74 error
, stream
= pstream
.accept()
76 rpcs
.append(ovs
.jsonrpc
.Connection(stream
))
77 elif error
!= errno
.EAGAIN
:
78 sys
.stderr
.write("PassiveStream.accept() failed\n")
81 # Service existing connections.
87 if not rpc
.get_backlog():
88 error
, msg
= rpc
.recv()
90 if handle_rpc(rpc
, msg
):
93 error
= rpc
.get_status()
97 rpcs
= [rpc
for rpc
in rpcs
if rpc
not in dead_rpcs
]
102 poller
= ovs
.poller
.Poller()
106 if not rpc
.get_backlog():
107 rpc
.recv_wait(poller
)
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
)
117 sys
.stderr
.write("not a valid JSON-RPC request: %s\n" % s
)
120 error
, stream
= ovs
.stream
.Stream
.open_block(ovs
.stream
.Stream
.open(name
))
122 sys
.stderr
.write("could not open \"%s\": %s\n"
123 % (name
, os
.strerror(error
)))
126 rpc
= ovs
.jsonrpc
.Connection(stream
)
128 error
= rpc
.send(msg
)
130 sys
.stderr
.write("could not send request: %s\n" % os
.strerror(error
))
133 error
, msg
= rpc
.recv_block()
135 sys
.stderr
.write("error waiting for reply: %s\n" % os
.strerror(error
))
138 print(ovs
.json
.to_string(msg
.to_json()))
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
)
148 sys
.stderr
.write("not a valid JSON-RPC notification: %s\n" % s
)
151 error
, stream
= ovs
.stream
.Stream
.open_block(ovs
.stream
.Stream
.open(name
))
153 sys
.stderr
.write("could not open \"%s\": %s\n"
154 % (name
, os
.strerror(error
)))
157 rpc
= ovs
.jsonrpc
.Connection(stream
)
159 error
= rpc
.send_block(msg
)
161 sys
.stderr
.write("could not send notification: %s\n"
162 % os
.strerror(error
))
170 parser
= argparse
.ArgumentParser(
171 description
="JSON-RPC test utility for Python.",
172 formatter_class
=argparse
.RawDescriptionHelpFormatter
)
174 commands
= {"listen": (do_listen
, 1),
175 "request": (do_request
, 3),
176 "notify": (do_notify
, 3),
177 "help": (parser
.print_help
, (0,))}
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")
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.")
192 ovs
.daemon
.add_args(parser
)
193 args
= parser
.parse_args()
194 ovs
.daemon
.handle_args(args
)
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
))
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 "
208 % (argv
[0], command_name
, n_args
, len(args
)))
210 elif type(n_args
) == int:
211 if len(args
) != n_args
:
212 sys
.stderr
.write("%s: \"%s\" requires %d arguments but %d "
214 % (argv
[0], command_name
, n_args
, len(args
)))
222 if __name__
== '__main__':