this consists of: - a simple internal management api (management.py) - a user interface backend (cli.py)
Signed-off-by: YAMAMOTO Takashi <[email protected]> --- bin/ryu-manager | 1 + ryu/app/cli.py | 147 +++++++++++++++++++++++++++++++++++++++++++++++++ ryu/base/management.py | 57 +++++++++++++++++++ ryu/logger.py | 31 +++++++++++ 4 files changed, 236 insertions(+) create mode 100644 ryu/app/cli.py create mode 100644 ryu/base/management.py create mode 100644 ryu/logger.py diff --git a/bin/ryu-manager b/bin/ryu-manager index f154bfe..f2a57f1 100755 --- a/bin/ryu-manager +++ b/bin/ryu-manager @@ -33,6 +33,7 @@ from oslo.config import cfg import logging import sys +import ryu.logger from ryu import log log.early_init_log(logging.DEBUG) diff --git a/ryu/app/cli.py b/ryu/app/cli.py new file mode 100644 index 0000000..4efc787 --- /dev/null +++ b/ryu/app/cli.py @@ -0,0 +1,147 @@ +# 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 management cli application. +# this module requires telnetsrv. + +import gevent +import gevent.server +import logging +import functools + +from oslo.config import cfg + +from telnetsrv.green import command +from telnetsrv.green import TelnetHandler + +from ryu import version +from ryu.base import app_manager +from ryu.base import management + + +CONF = cfg.CONF +CONF.register_opts([ + cfg.StrOpt('cli_host', default='localhost', help='cli listen host'), + cfg.IntOpt('cli_port', default=4989, help='cli listen port') +]) + + +class PrefixedLogger(object): + def __init__(self, logger, prefix): + self.logger = logger + self.prefix = prefix + + def __getattr__(self, name): + basemethod = getattr(self.logger, name) + if not name in ['debug', 'info', 'warn', 'error', 'critical', + 'exception']: + raise AttributeError + + def method(msg, *args, **kwargs): + return basemethod("%s %s" % (self.prefix, msg), *args, **kwargs) + return method + + +def command_log(*args, **kwargs): + def _log(f): + # XXX see the implementation of @command for command_name + @functools.wraps(f) + def wrapper(self, params): + self.logger.info("command %s %s" % (wrapper.command_name, params)) + f(self, params) + return wrapper + return lambda f: command(*args, **kwargs)(_log(f)) + + +class CliHandler(TelnetHandler): + PROMPT = 'ryu-manager %s> ' % version + + def __init__(self, request, client_address, server): + self.client_address = client_address + logger = logging.getLogger("ryu.app.Cli") + plogger = PrefixedLogger(logger, "CLI %s" % (client_address,)) + self.logger = plogger # for us + self.logging = plogger # for TelnetHandler + TelnetHandler.__init__(self, request, client_address, server) + + def session_start(self): + self.logger.info("session start") + + def session_end(self): + # XXX due to a bug in telnetsrv 0.4, this isn't called on + # a forcible disconnect. + # see https://github.com/yamt/telnetsrvlib/tree/fix-disconnect + # for a fix. + self.logger.info("session end") + + @command_log('set-log-level') + def command_set_log_level(self, params): + '''<logger> <level> + set log level of the specified logger + ''' + try: + name = params[0] + newlvl = int(params[1]) + except (ValueError, IndexError): + self.writeerror('invalid parameter') + return + try: + oldlvl = management.get_log_level(name) + management.set_log_level(name, newlvl) + except LookupError: + self.writeerror('logger %s is unknown' % (name,)) + return + self.writeresponse('logger %s level %s -> %s' % + (name, oldlvl, newlvl)) + + @command_log('show-bricks') + def command_show_bricks(self, params): + ''' + show a list of configured bricks + ''' + map(lambda b: self.writeresponse('%s' % (b,)), + management.list_bricks()) + + @command_log('show-loggers') + def command_show_loggers(self, params): + ''' + show loggers + ''' + map(lambda name: self.writeresponse('logger %s level %s' % + (name, + management.get_log_level(name))), + management.list_loggers()) + + @command_log('show-options') + def command_show_options(self, params): + ''' + show options + ''' + class MyLogger: + def log(mylogger_self, lvl, fmt, *args): + self.writeresponse(fmt % args) + CONF.log_opt_values(MyLogger(), None) + + +class Cli(app_manager.RyuApp): + def __init__(self, *args, **kwargs): + super(Cli, self).__init__(*args, **kwargs) + gevent.spawn(self.loop) + + def loop(self): + server = gevent.server.StreamServer((CONF.cli_host, CONF.cli_port), + CliHandler.streamserver_handle) + server.serve_forever() diff --git a/ryu/base/management.py b/ryu/base/management.py new file mode 100644 index 0000000..55ae7dc --- /dev/null +++ b/ryu/base/management.py @@ -0,0 +1,57 @@ +# 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. + +# internal management api + +import logging + +import ryu.logger + + +def set_log_level(name, newlvl): + """ + Set the log level of the specified logger + """ + if not name in ryu.logger.RyuLogger.loggers: + raise LookupError + logger = logging.getLogger(name) + oldlvl = logger.getEffectiveLevel() + logger.setLevel(newlvl) + + +def get_log_level(name): + """ + Return the log level of the specified logger + """ + if not name in ryu.logger.RyuLogger.loggers: + raise LookupError + logger = logging.getLogger(name) + return logger.getEffectiveLevel() + + +def list_loggers(): + """ + Return a list of logger names + """ + return ryu.logger.RyuLogger.loggers + + +def list_bricks(): + """ + Return a list of configured bricks + """ + from ryu.base.app_manager import SERVICE_BRICKS + return SERVICE_BRICKS.keys() diff --git a/ryu/logger.py b/ryu/logger.py new file mode 100644 index 0000000..2e2aa91 --- /dev/null +++ b/ryu/logger.py @@ -0,0 +1,31 @@ +# 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. + +import logging + + +class RyuLogger(logging.getLoggerClass()): + loggers = set() + + def __init__(self, name): + try: + super(RyuLogger, self).__init__(name) + except TypeError: + # probably our super class is old-type + logging.Logger.__init__(self, name) + RyuLogger.loggers.add(name) + +logging.setLoggerClass(RyuLogger) -- 1.7.12 ------------------------------------------------------------------------------ Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_feb _______________________________________________ Ryu-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ryu-devel
