a simple of-config client command
the placement (ryu/tests/bin) was suggested by FUJITA Tomonori. Signed-off-by: YAMAMOTO Takashi <yamamoto@valinux.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
28c6aa1cd7
commit
abfc1bd729
473
ryu/cmd/of_config_cli.py
Executable file
473
ryu/cmd/of_config_cli.py
Executable file
@ -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('-', '_')
|
||||
|
||||
|
||||
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):
|
||||
"""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
|
||||
|
||||
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}))
|
||||
]
|
||||
)
|
||||
)
|
||||
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()
|
20
ryu/tests/bin/of-config-cli
Executable file
20
ryu/tests/bin/of-config-cli
Executable file
@ -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()
|
Loading…
Reference in New Issue
Block a user