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 thanks, On Mon, Jul 01, 2013 at 02:37:08PM +0900, YAMAMOTO Takashi wrote: > > Signed-off-by: YAMAMOTO Takashi <[email protected]> > --- > 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 > [email protected] > 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 [email protected] https://lists.sourceforge.net/lists/listinfo/ryu-devel
