> Sorry for late response.
> Can you please add man page for rpc-cli? The contents of man page can
> be mostly trivial/empty because it's necessary for satisfying rpmlint of
> Fedora.
> 
> add ryu/doc/source/man/msgpack-rpc.rst
> update ryu/doc/source/conf.py

ok, i will.

YAMAMOTO Takashi

> 
> thanks,
> 
> On Mon, Jul 01, 2013 at 02:37:08PM +0900, YAMAMOTO Takashi wrote:
>> 
>> Signed-off-by: YAMAMOTO Takashi <yamam...@valinux.co.jp>
>> ---
>>  bin/rpc-cli  | 237 
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  run_tests.sh |   2 +-
>>  setup.py     |   3 +-
>>  3 files changed, 240 insertions(+), 2 deletions(-)
>>  create mode 100755 bin/rpc-cli
>> 
>> diff --git a/bin/rpc-cli b/bin/rpc-cli
>> new file mode 100755
>> index 0000000..05696b3
>> --- /dev/null
>> +++ b/bin/rpc-cli
>> @@ -0,0 +1,237 @@
>> +#!/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?
>> +        self._saved_termios = None
>> +        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 postcmd(self, _stop, _line):
>> +        self._peek_notification()
>> +
>> +    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", k
>> +
>> +    @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, string):
>> +        self._in_onecmd = True
>> +        try:
>> +            return cmd.Cmd.onecmd(self, string)
>> +        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()
>> diff --git a/run_tests.sh b/run_tests.sh
>> index 5e0d631..0551fe1 100755
>> --- a/run_tests.sh
>> +++ b/run_tests.sh
>> @@ -90,7 +90,7 @@ run_tests() {
>>  run_pylint() {
>>    echo "Running pylint ..."
>>    PYLINT_OPTIONS="--rcfile=.pylintrc --output-format=parseable"
>> -  PYLINT_INCLUDE="ryu bin/ryu-manager ryu/tests/bin/ryu-client"
>> +  PYLINT_INCLUDE="ryu bin/ryu-manager bin/rpc-cli ryu/tests/bin/ryu-client"
>>    export PYTHONPATH=$PYTHONPATH:.ryu
>>    PYLINT_LOG=pylint.log
>>  
>> diff --git a/setup.py b/setup.py
>> index efbb550..3f855b6 100644
>> --- a/setup.py
>> +++ b/setup.py
>> @@ -59,7 +59,8 @@ setup(name='ryu',
>>        install_requires=requires,
>>        license='Apache License 2.0',
>>        packages=find_packages(),
>> -      scripts=['bin/ryu-manager', ],
>> +      scripts=['bin/ryu-manager',
>> +               'bin/rpc-cli'],
>>        data_files=data_files,
>>        include_package_data=True,
>>        )
>> -- 
>> 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
>> Ryu-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/ryu-devel
>> 
> 
> -- 
> yamahata
> 
> ------------------------------------------------------------------------------
> See everything from the browser to the database with AppDynamics
> Get end-to-end visibility with application monitoring from AppDynamics
> Isolate bottlenecks and diagnose root cause in seconds.
> Start your free trial of AppDynamics Pro today!
> http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
> _______________________________________________
> Ryu-devel mailing list
> Ryu-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/ryu-devel

------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to