thanks for reviewing.
> 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.
it depends on what the future versions of of-config will use.
currently it seems that '-' is the only python-incompatible thing.
>
>
>> +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?
XML.
>
>> + """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?
which 'The above'?
i added get_port_config merely for symmetry to set_port_config.
it's redundant as you can get the same info with get_config command.
>
>
>> + 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?
i'll try.
YAMAMOTO Takashi
>
>> + ]
>> + )
>> + )
>> + 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
------------------------------------------------------------------------------
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