On Mon, 16 Dec 2013 17:52:11 +0900
YAMAMOTO Takashi <[email protected]> wrote:

> the placement (ryu/tests/bin) was suggested by FUJITA Tomonori.
> 
> Signed-off-by: YAMAMOTO Takashi <[email protected]>
> ---
>  ryu/cmd/of_config_cli.py    | 473 
> ++++++++++++++++++++++++++++++++++++++++++++
>  ryu/tests/bin/of-config-cli |  20 ++
>  2 files changed, 493 insertions(+)
>  create mode 100755 ryu/cmd/of_config_cli.py
>  create mode 100755 ryu/tests/bin/of-config-cli
> 
> diff --git a/ryu/cmd/of_config_cli.py b/ryu/cmd/of_config_cli.py
> new file mode 100755
> index 0000000..1803849
> --- /dev/null
> +++ b/ryu/cmd/of_config_cli.py
> @@ -0,0 +1,473 @@
> +#!/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 OF-CONFIG client
> +#
> +# a usage example:
> +#     % PYTHONPATH=. ./bin/of_config_cli \
> +#      --peers=sw1=localhost:1830:username:password
> +#     (Cmd) raw_get sw1
> +
> +import ryu.contrib
> +
> +from oslo.config import cfg
> +
> +import cmd
> +import sys
> +import lxml.etree as ET
> +
> +from ryu.lib import of_config
> +from ryu.lib.of_config import capable_switch
> +from ryu.lib.of_config import constants as consts
> +from ncclient.operations.rpc import RPCError
> +import ryu.lib.of_config.classes as ofc
> +
> +
> +CONF = cfg.CONF
> +CONF.register_cli_opts([
> +    cfg.ListOpt('peers', default=[], help='list of peers')
> +])
> +
> +
> +class Peer(capable_switch.OFCapableSwitch):
> +    def __init__(self, name, host, port, username, password):
> +        self._name = name
> +        super(Peer, self).__init__(
> +            host=host, port=port, username=username, password=password,
> +            unknown_host_cb=lambda host, fingeprint: True)
> +
> +
> +peers = {}
> +
> +
> +def add_peer(name, host, port, username, password):
> +    peers[name] = Peer(name, host, port, username, password)
> +
> +
> +def et_tostring_pp(tree):
> +    # pretty_print is an lxml feature, not available in ElementTree
> +    try:
> +        return ET.tostring(tree, pretty_print=True)
> +    except TypeError:
> +        return ET.tostring(tree)
> +
> +
> +def validate(tree):
> +    schema = ET.XMLSchema(file=of_config.OF_CONFIG_1_1_1_XSD)
> +    if not schema(tree):
> +        print schema.error_log
> +
> +
> +def _pythonify(name):
> +    # XXX code duplication
> +    return name.replace('-', '_')

Plans to add other functions here? Otherwise, I don't see any point to
inventing a new function that wraps one liner.


> +class Cmd(cmd.Cmd):
> +    def __init__(self, *args, **kwargs):
> +        self._in_onecmd = False
> +        cmd.Cmd.__init__(self, *args, **kwargs)
> +
> +    def _request(self, line, f):
> +        args = line.split()
> +        try:
> +            peer = args[0]
> +        except:
> +            print "argument error"
> +            return
> +        try:
> +            p = peers[peer]
> +        except KeyError:
> +            print "unknown peer", peer
> +            return
> +        try:
> +            f(p, args[1:])
> +        except 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_list_cap(self, line):
> +        """list_cap <peer>
> +        """
> +
> +        def f(p, args):
> +            for i in p.netconf.server_capabilities:
> +                print i
> +
> +        self._request(line, f)
> +
> +    def do_raw_get(self, line):

What 'raw_' means?

> +        """raw_get <peer>
> +        """
> +
> +        def f(p, args):
> +            result = p.raw_get()
> +            tree = ET.fromstring(result)
> +            validate(tree)
> +            print et_tostring_pp(tree)
> +
> +        self._request(line, f)
> +
> +    def do_raw_get_config(self, line):
> +        """raw_get_config <peer> <source>
> +        """
> +
> +        def f(p, args):
> +            try:
> +                source = args[0]
> +            except:
> +                print "argument error"
> +                return
> +            result = p.raw_get_config(source)
> +            tree = ET.fromstring(result)
> +            validate(tree)
> +            print et_tostring_pp(tree)
> +
> +        self._request(line, f)
> +
> +    def do_get(self, line):
> +        """get <peer>
> +        eg. get_config sw1
> +        """
> +
> +        def f(p, args):
> +            print p.get()
> +
> +        self._request(line, f)
> +
> +    def do_get_config(self, line):
> +        """get_config <peer> <source>
> +        eg. get_config sw1 startup
> +        """
> +
> +        def f(p, args):
> +            try:
> +                source = args[0]
> +            except:
> +                print "argument error"
> +                return
> +            print p.get_config(source)
> +
> +        self._request(line, f)
> +
> +    def do_list_port(self, line):
> +        """list_port <peer>
> +        """
> +
> +        def f(p, args):
> +            o = p.get()
> +            for p in o.resources.port:
> +                print p.resource_id, p.name, p.number
> +
> +        self._request(line, f)
> +
> +    _port_settings = [
> +        'admin-state',
> +        'no-forward',
> +        'no-packet-in',
> +        'no-receive',
> +    ]
> +
> +    def do_get_port_config(self, line):
> +        """get_config_port <peer> <source> <port>
> +        eg. get_port_config sw1 running LogicalSwitch7-Port2
> +        """
> +
> +        def f(p, args):
> +            try:
> +                source, port = args
> +            except:
> +                print "argument error"
> +                return
> +            o = p.get_config(source)
> +            for p in o.resources.port:
> +                if p.resource_id != port:
> +                    continue
> +                print p.resource_id
> +                conf = p.configuration
> +                for k in self._port_settings:
> +                    try:
> +                        v = getattr(conf, _pythonify(k))
> +                    except AttributeError:
> +                        continue
> +                    print k, v

The above is only for debugging?


> +        self._request(line, f)
> +
> +    def do_set_port_config(self, line):
> +        """set_port_config <peer> <target> <port> <key> <value>
> +        eg. set_port_config sw1 running LogicalSwitch7-Port2 admin-state down
> +        eg. set_port_config sw1 running LogicalSwitch7-Port2 no-forward false
> +        """
> +
> +        def f(p, args):
> +            try:
> +                target, port, key, value = args
> +            except:
> +                print "argument error"
> +                print args
> +                return
> +
> +            # get switch id
> +            o = p.get()
> +            capable_switch_id = o.id
> +
> +            try:
> +                capable_switch = ofc.OFCapableSwitchType(
> +                    id=capable_switch_id,
> +                    resources=ofc.OFCapableSwitchResourcesType(
> +                        port=[
> +                            ofc.OFPortType(
> +                                resource_id=port,
> +                                configuration=ofc.OFPortConfigurationType(
> +                                    **{_pythonify(key): value}))

Can Ryu hide '_pythonify' stuff from the consumers of this library?

> +                        ]
> +                    )
> +                )
> +            except TypeError:
> +                print "argument error"
> +                return
> +            try:
> +                p.edit_config(target, capable_switch)
> +            except Exception, e:
> +                print e
> +
> +        self._request(line, f)
> +
> +    def do_list_queue(self, line):
> +        """list_queue <peer>
> +        """
> +
> +        def f(p, args):
> +            o = p.get()
> +            if o.resources.queue:
> +                for q in o.resources.queue:
> +                    print q.resource_id, q.port
> +
> +        self._request(line, f)
> +
> +    _queue_settings = [
> +        'max-rate',
> +        'min-rate',
> +        'experimenter',
> +    ]
> +
> +    def do_get_queue_config(self, line):
> +        """get_queue_port <peer> <source> <queue>
> +        eg. get_queue_config sw1 running LogicalSwitch7-Port1-Queue922
> +        """
> +
> +        def f(p, args):
> +            try:
> +                source, queue = args
> +            except:
> +                print "argument error"
> +                return
> +            o = p.get_config(source)
> +            for q in o.resources.queue:
> +                if q.resource_id != queue:
> +                    continue
> +                print q.resource_id
> +                conf = q.properties
> +                for k in self._queue_settings:
> +                    try:
> +                        v = getattr(conf, _pythonify(k))
> +                    except AttributeError:
> +                        continue
> +                    print k, v
> +
> +        self._request(line, f)
> +
> +    def do_set_queue_config(self, line):
> +        """set_queue_config <peer> <target> <queue> <key> <value>
> +        eg. set_queue_config sw1 running LogicalSwitch7-Port1-Queue922 \
> +max-rate 100
> +        """
> +
> +        def f(p, args):
> +            try:
> +                target, queue, key, value = args
> +            except:
> +                print "argument error"
> +                print args
> +                return
> +
> +            # get switch id
> +            o = p.get()
> +            capable_switch_id = o.id
> +
> +            try:
> +                capable_switch = ofc.OFCapableSwitchType(
> +                    id=capable_switch_id,
> +                    resources=ofc.OFCapableSwitchResourcesType(
> +                        queue=[
> +                            ofc.OFQueueType(
> +                                resource_id=queue,
> +                                properties=ofc.OFQueuePropertiesType(
> +                                    **{_pythonify(key): value})),
> +                        ]
> +                    )
> +                )
> +            except TypeError:
> +                print "argument error"
> +                return
> +            try:
> +                p.edit_config(target, capable_switch)
> +            except Exception, e:
> +                print e
> +
> +        self._request(line, f)
> +
> +    def do_list_logical_switch(self, line):
> +        """list_logical_switch <peer>
> +        """
> +
> +        def f(p, args):
> +            o = p.get()
> +            for s in o.logical_switches.switch:
> +                print s.id, s.datapath_id
> +
> +        self._request(line, f)
> +
> +    def do_show_logical_switch(self, line):
> +        """show_logical_switch <peer> <logical switch>
> +        """
> +
> +        def f(p, args):
> +            try:
> +                (lsw,) = args
> +            except:
> +                print "argument error"
> +                return
> +            o = p.get()
> +            for s in o.logical_switches.switch:
> +                if s.id != lsw:
> +                    continue
> +                print s.id
> +                print 'datapath-id', s.datapath_id
> +                if s.resources.queue:
> +                    print 'queues:'
> +                    for q in s.resources.queue:
> +                        print '\t', q
> +                if s.resources.port:
> +                    print 'ports:'
> +                    for p in s.resources.port:
> +                        print '\t', p
> +
> +        self._request(line, f)
> +
> +    _lsw_settings = [
> +        'lost-connection-behavior',
> +    ]
> +
> +    def do_get_logical_switch_config(self, line):
> +        """get_logical_switch_config <peer> <source> <logical switch>
> +        """
> +
> +        def f(p, args):
> +            try:
> +                source, lsw = args
> +            except:
> +                print "argument error"
> +                return
> +            o = p.get_config(source)
> +            for l in o.logical_switches.switch:
> +                if l.id != lsw:
> +                    continue
> +                print l.id
> +                for k in self._lsw_settings:
> +                    try:
> +                        v = getattr(l, _pythonify(k))
> +                    except AttributeError:
> +                        continue
> +                    print k, v
> +
> +        self._request(line, f)
> +
> +    def do_set_logical_switch_config(self, line):
> +        """set_logical_switch_config <peer> <logical switch> <key> <value>
> +        eg. set_logical_switch_config sw1 running LogicalSwitch7 \
> +lost-connection-behavior failStandaloneMode
> +        """
> +
> +        def f(p, args):
> +            try:
> +                target, lsw, key, value = args
> +            except:
> +                print "argument error"
> +                return
> +
> +            # get switch id
> +            o = p.get_config(target)
> +            capable_switch_id = o.id
> +
> +            try:
> +                capable_switch = ofc.OFCapableSwitchType(
> +                    id=capable_switch_id,
> +                    logical_switches=ofc.OFCapableSwitchLogicalSwitchesType(
> +                        switch=[ofc.OFLogicalSwitchType(
> +                            id=lsw,
> +                            **{_pythonify(key): value}
> +                        )]
> +                    )
> +                )
> +            except TypeError:
> +                print "argument error"
> +                return
> +            try:
> +                p.edit_config(target, capable_switch)
> +            except Exception, e:
> +                print e
> +
> +        self._request(line, f)
> +
> +    completedefault = _complete_peer
> +
> +    def complete_EOF(self, _text, _line, _begidx, _endidx):
> +        return []
> +
> +    def do_EOF(self, _line):
> +        sys.exit(0)
> +
> +    def onecmd(self, string):
> +        self._in_onecmd = True
> +        try:
> +            return cmd.Cmd.onecmd(self, string)
> +        finally:
> +            self._in_onecmd = False
> +
> +
> +def main():
> +    CONF(project='of-config-cli', version='of-config-cli')
> +
> +    for p_str in CONF.peers:
> +        name, addr = p_str.split('=')
> +        host, port, username, password = addr.rsplit(':', 3)
> +        add_peer(name, host, port, username, password)
> +
> +    Cmd().cmdloop()
> +
> +
> +if __name__ == "__main__":
> +    main()
> diff --git a/ryu/tests/bin/of-config-cli b/ryu/tests/bin/of-config-cli
> new file mode 100755
> index 0000000..c076ee8
> --- /dev/null
> +++ b/ryu/tests/bin/of-config-cli
> @@ -0,0 +1,20 @@
> +#!/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.
> +
> +from ryu.cmd.of_config_cli import main
> +main()
> -- 
> 1.8.3.1
> 
> 
> ------------------------------------------------------------------------------
> Rapidly troubleshoot problems before they affect your business. Most IT 
> organizations don't have a clear picture of how application performance 
> affects their revenue. With AppDynamics, you get 100% visibility into your 
> Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
> http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
> _______________________________________________
> Ryu-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/ryu-devel

------------------------------------------------------------------------------
Rapidly troubleshoot problems before they affect your business. Most IT 
organizations don't have a clear picture of how application performance 
affects their revenue. With AppDynamics, you get 100% visibility into your 
Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro!
http://pubads.g.doubleclick.net/gampad/clk?id=84349831&iu=/4140/ostg.clktrk
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to