> On Thu, Jun 27, 2013 at 01:00:24PM +0900, YAMAMOTO Takashi wrote:
>>
>> Signed-off-by: YAMAMOTO Takashi <[email protected]>
>> ---
>> bin/rpc-cli | 236
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 236 insertions(+)
>> create mode 100755 bin/rpc-cli
>>
>> diff --git a/bin/rpc-cli b/bin/rpc-cli
>> new file mode 100755
>> index 0000000..211f9a1
>> --- /dev/null
>> +++ b/bin/rpc-cli
>> @@ -0,0 +1,236 @@
>> +#!/usr/bin/env python
>> +#
>> +# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
>> +# Copyright (C) 2013 YAMAMOTO Takashi <yamamoto at valinux co jp>
>> +#
>> +# Licensed under the Apache License, Version 2.0 (the "License");
>> +# you may not use this file except in compliance with the License.
>> +# You may obtain a copy of the License at
>> +#
>> +# http://www.apache.org/licenses/LICENSE-2.0
>> +#
>> +# Unless required by applicable law or agreed to in writing, software
>> +# distributed under the License is distributed on an "AS IS" BASIS,
>> +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> +# implied.
>> +# See the License for the specific language governing permissions and
>> +# limitations under the License.
>> +
>> +# a simple command line msgpack-rpc client
>> +#
>> +# a usage example:
>> +# % PYTHONPATH=. ./bin/rpc-cli \
>> +# --peers=echo-server=localhost:9999,hoge=localhost:9998
>> +# (Cmd) request echo-server echo ["hoge"]
>> +# RESULT hoge
>> +# (Cmd) request echo-server notify ["notify-method",
>> ["param1","param2"]]
>> +# RESULT notify-method
>> +# (Cmd)
>> +# NOTIFICATION from echo-server ['notify-method', ['param1', 'param2']]
>> +# (Cmd)
>> +
>> +import ryu.contrib
>> +
>> +from oslo.config import cfg
>> +
>> +import cmd
>> +import signal
>> +import socket
>> +import sys
>> +import termios
>> +
>> +from ryu.lib import rpc
>> +
>> +
>> +CONF = cfg.CONF
>> +CONF.register_cli_opts([
>> + # eg. rpc-cli --peers=hoge=localhost:9998,fuga=localhost:9999
>> + cfg.ListOpt('peers', default=[], help='list of peers')
>> +])
>> +
>> +
>> +class Peer(object):
>> + def __init__(self, name, addr):
>> + self._name = name
>> + self._addr = addr
>> + self.client = None
>> + try:
>> + self.connect()
>> + except:
>> + pass
>> +
>> + def connect(self):
>> + self.client = None
>> + s = socket.create_connection(self._addr)
>> + self.client = rpc.Client(s, notification_callback=self.notification)
>> +
>> + def try_to_connect(self, verbose=False):
>> + if self.client:
>> + return
>> + try:
>> + self.connect()
>> + assert self.client
>> + except Exception, e:
>> + if verbose:
>> + print "connection failure", e
>> + raise EOFError
>> +
>> + def notification(self, n):
>> + print "NOTIFICATION from", self._name, n
>> +
>> + def call(self, method, params):
>> + return self._do(lambda: self.client.call(method, params))
>> +
>> + def send_notification(self, method, params):
>> + self._do(lambda: self.client.send_notification(method, params))
>> +
>> + def _do(self, f):
>> + def g():
>> + try:
>> + return f()
>> + except EOFError:
>> + self.client = None
>> + raise
>> +
>> + self.try_to_connect(verbose=True)
>> + try:
>> + return g()
>> + except EOFError:
>> + print "disconnected. trying to connect..."
>> + self.try_to_connect(verbose=True)
>> + print "connected. retrying the request..."
>> + return g()
>> +
>> +
>> +peers = {}
>> +
>> +
>> +def add_peer(name, host, port):
>> + peers[name] = Peer(name, (host, port))
>> +
>> +
>> +class Cmd(cmd.Cmd):
>> + def __init__(self, *args, **kwargs):
>> + self._in_onecmd = False
>> + self._notification_check_interval = 1 # worth to be configurable?
>> + cmd.Cmd.__init__(self, *args, **kwargs)
>> +
>> + def _request(self, line, f):
>> + args = line.split(None, 2)
>> + try:
>> + peer = args[0]
>> + method = args[1]
>> + params = eval(args[2])
>> + except:
>> + print "argument error"
>> + return
>> + try:
>> + p = peers[peer]
>> + except KeyError:
>> + print "unknown peer", peer
>> + return
>> + try:
>> + f(p, method, params)
>> + except rpc.RPCError, e:
>> + print "RPC ERROR", e
>> + except EOFError:
>> + print "disconnected"
>> +
>> + def _complete_peer(self, text, line, begidx, endidx):
>> + if len((line + 'x').split()) >= 3:
>> + return []
>> + return [name for name in peers if name.startswith(text)]
>> +
>> + def do_request(self, line):
>> + """request <peer> <method> <params>
>> + send a msgpack-rpc request and print a response.
>> + <params> is a python code snippet, it should be eval'ed to a list.
>> + """
>> +
>> + def f(p, method, params):
>> + result = p.call(method, params)
>> + print "RESULT", result
>> +
>> + self._request(line, f)
>> +
>> + def do_notify(self, line):
>> + """notify <peer> <method> <params>
>> + send a msgpack-rpc notification.
>> + <params> is a python code snippet, it should be eval'ed to a list.
>> + """
>> +
>> + def f(p, method, params):
>> + p.send_notification(method, params)
>> +
>> + self._request(line, f)
>> +
>> + def complete_request(self, text, line, begidx, endidx):
>> + return self._complete_peer(text, line, begidx, endidx)
>> +
>> + def complete_notify(self, text, line, begidx, endidx):
>> + return self._complete_peer(text, line, begidx, endidx)
>> +
>> + def do_EOF(self, line):
>> + sys.exit(0)
>> +
>> + def emptyline(self):
>> + self._peek_notification()
>> +
>> + def preloop(self):
>> + self._peek_notification()
>
> preloop method is defined twice.
thanks. i meant precmd here.
YAMAMOTO Takashi
>
>
>> +
>> + def _peek_notification(self):
>> + for k, p in peers.iteritems():
>> + if p.client:
>> + try:
>> + p.client.peek_notification()
>> + except EOFError:
>> + p.client = None
>> + print "disconnected", p._name
>> +
>> + @staticmethod
>> + def _save_termios():
>> + return termios.tcgetattr(sys.stdin.fileno())
>> +
>> + @staticmethod
>> + def _restore_termios(t):
>> + termios.tcsetattr(sys.stdin.fileno(), termios.TCSADRAIN, t)
>> +
>> + def preloop(self):
>> + self._saved_termios = self._save_termios()
>> + signal.signal(signal.SIGALRM, self._timeout)
>> + signal.alarm(1)
>> +
>> + def onecmd(self, str):
>> + self._in_onecmd = True
>> + try:
>> + return cmd.Cmd.onecmd(self, str)
>> + finally:
>> + self._in_onecmd = False
>> +
>> + def _timeout(self, sig, frame):
>> + if not self._in_onecmd:
>> + # restore terminal settings. (cooked/raw, ...)
>> + # required for pypy at least.
>> + # this doesn't seem to be needed for cpython readline
>> + # module but i'm not sure if it's by spec or luck.
>> + o = self._save_termios()
>> + self._restore_termios(self._saved_termios)
>> + self._peek_notification()
>> + self._restore_termios(o)
>> + signal.alarm(self._notification_check_interval)
>> +
>> +
>> +def main():
>> + CONF(project='rpc-cli', version='rpc-cli')
>> +
>> + for p_str in CONF.peers:
>> + name, addr = p_str.split('=')
>> + host, port = addr.rsplit(':', 1)
>> + add_peer(name, host, port)
>> +
>> + Cmd().cmdloop()
>> +
>> +
>> +if __name__ == "__main__":
>> + main()
>> --
>> 1.8.1.5
>>
>>
>> ------------------------------------------------------------------------------
>> This SF.net email is sponsored by Windows:
>>
>> Build for Windows Store.
>>
>> http://p.sf.net/sfu/windows-dev2dev
>> _______________________________________________
>> Ryu-devel mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/ryu-devel
>>
>
> --
> yamahata
>
> ------------------------------------------------------------------------------
> This SF.net email is sponsored by Windows:
>
> Build for Windows Store.
>
> http://p.sf.net/sfu/windows-dev2dev
> _______________________________________________
> Ryu-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/ryu-devel
------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:
Build for Windows Store.
http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel