3 # Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
4 # Copyright (C) 2013 YAMAMOTO Takashi <yamamoto at valinux co jp>
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
19 # a simple command line OF-CONFIG client
22 # % PYTHONPATH=. ./bin/of_config_cli \
23 # --peers=sw1=localhost:1830:username:password
26 from __future__ import print_function
31 import lxml.etree as ET
32 from ncclient.operations.rpc import RPCError
35 from ryu.lib import of_config
36 from ryu.lib.of_config import capable_switch
37 import ryu.lib.of_config.classes as ofc
41 CONF.register_cli_opts([
42 cfg.ListOpt('peers', default=[], help='list of peers')
46 class Peer(capable_switch.OFCapableSwitch):
47 def __init__(self, name, host, port, username, password):
49 super(Peer, self).__init__(
50 host=host, port=port, username=username, password=password,
51 unknown_host_cb=lambda host, fingeprint: True)
57 def add_peer(name, host, port, username, password):
58 peers[name] = Peer(name, host, port, username, password)
61 def et_tostring_pp(tree):
62 # pretty_print is an lxml feature, not available in ElementTree
64 return ET.tostring(tree, pretty_print=True)
66 return ET.tostring(tree)
70 schema = ET.XMLSchema(file=of_config.OF_CONFIG_1_1_1_XSD)
72 print(schema.error_log)
76 def __init__(self, *args, **kwargs):
77 self._in_onecmd = False
78 cmd.Cmd.__init__(self, *args, **kwargs)
80 def _request(self, line, f):
85 print("argument error")
90 print("unknown peer %s" % peer)
95 print("RPC Error %s" % e)
99 def _complete_peer(self, text, line, _begidx, _endidx):
100 if len((line + 'x').split()) >= 3:
102 return [name for name in peers if name.startswith(text)]
104 def do_list_cap(self, line):
109 for i in p.netconf.server_capabilities:
112 self._request(line, f)
114 def do_raw_get(self, line):
120 tree = ET.fromstring(result)
122 print(et_tostring_pp(tree))
124 self._request(line, f)
126 def do_raw_get_config(self, line):
127 """raw_get_config <peer> <source>
134 print("argument error")
136 result = p.raw_get_config(source)
137 tree = ET.fromstring(result)
139 print(et_tostring_pp(tree))
141 self._request(line, f)
143 def do_get(self, line):
151 self._request(line, f)
153 def do_commit(self, line):
161 self._request(line, f)
163 def do_discard(self, line):
169 print(p.discard_changes())
171 self._request(line, f)
173 def do_get_config(self, line):
174 """get_config <peer> <source>
175 eg. get_config sw1 startup
182 print("argument error")
184 print(p.get_config(source))
186 self._request(line, f)
188 def do_delete_config(self, line):
189 """delete_config <peer> <source>
190 eg. delete_config sw1 startup
197 print("argument error")
199 print(p.delete_config(source))
201 self._request(line, f)
203 def do_copy_config(self, line):
204 """copy_config <peer> <source> <target>
205 eg. copy_config sw1 running startup
210 source, target = args
212 print("argument error")
214 print(p.copy_config(source, target))
216 self._request(line, f)
218 def do_list_port(self, line):
224 for p in o.resources.port:
225 print('%s %s %s' % (p.resource_id, p.name, p.number))
227 self._request(line, f)
236 def do_get_port_config(self, line):
237 """get_config_port <peer> <source> <port>
238 eg. get_port_config sw1 running LogicalSwitch7-Port2
245 print("argument error")
247 o = p.get_config(source)
248 for p in o.resources.port:
249 if p.resource_id != port:
252 conf = p.configuration
253 for k in self._port_settings:
256 except AttributeError:
258 print('%s %s' % (k, v))
260 self._request(line, f)
262 def do_set_port_config(self, line):
263 """set_port_config <peer> <target> <port> <key> <value>
264 eg. set_port_config sw1 running LogicalSwitch7-Port2 admin-state down
265 eg. set_port_config sw1 running LogicalSwitch7-Port2 no-forward false
270 target, port, key, value = args
272 print("argument error")
278 capable_switch_id = o.id
281 capable_switch = ofc.OFCapableSwitchType(
282 id=capable_switch_id,
283 resources=ofc.OFCapableSwitchResourcesType(
287 configuration=ofc.OFPortConfigurationType(
293 print("argument error")
296 p.edit_config(target, capable_switch)
297 except Exception as e:
300 self._request(line, f)
302 def do_list_queue(self, line):
308 if o.resources.queue:
309 for q in o.resources.queue:
310 print('%s %s' % (q.resource_id, q.port))
312 self._request(line, f)
320 def do_get_queue_config(self, line):
321 """get_queue_port <peer> <source> <queue>
322 eg. get_queue_config sw1 running LogicalSwitch7-Port1-Queue922
329 print("argument error")
331 o = p.get_config(source)
332 for q in o.resources.queue:
333 if q.resource_id != queue:
337 for k in self._queue_settings:
340 except AttributeError:
342 print('%s %s' % (k, v))
344 self._request(line, f)
346 def do_set_queue_config(self, line):
347 """set_queue_config <peer> <target> <queue> <key> <value>
348 eg. set_queue_config sw1 running LogicalSwitch7-Port1-Queue922 \
354 target, queue, key, value = args
356 print("argument error")
362 capable_switch_id = o.id
365 capable_switch = ofc.OFCapableSwitchType(
366 id=capable_switch_id,
367 resources=ofc.OFCapableSwitchResourcesType(
371 properties=ofc.OFQueuePropertiesType(
377 print("argument error")
380 p.edit_config(target, capable_switch)
381 except Exception as e:
384 self._request(line, f)
386 def do_add_queue(self, line):
387 """add_queue <peer> <target> <logical-switch> <queue>
388 eg. add_queue sw1 running LogicalSwitch7 NameOfNewQueue
393 target, lsw, queue = args
395 print("argument error")
401 capable_switch_id = o.id
404 capable_switch = ofc.OFCapableSwitchType(
405 id=capable_switch_id,
406 resources=ofc.OFCapableSwitchResourcesType(
408 ofc.OFQueueType(resource_id=queue)
411 logical_switches=ofc.OFCapableSwitchLogicalSwitchesType(
412 switch=[ofc.OFLogicalSwitchType(
414 resources=ofc.OFLogicalSwitchResourcesType(
420 print("argument error")
423 p.edit_config(target, capable_switch)
424 except Exception as e:
427 self._request(line, f)
429 def do_list_logical_switch(self, line):
430 """list_logical_switch <peer>
435 for s in o.logical_switches.switch:
436 print('%s %s' % (s.id, s.datapath_id))
438 self._request(line, f)
440 def do_show_logical_switch(self, line):
441 """show_logical_switch <peer> <logical switch>
448 print("argument error")
451 for s in o.logical_switches.switch:
455 print('datapath-id %s' % s.datapath_id)
456 if s.resources.queue:
458 for q in s.resources.queue:
462 for p in s.resources.port:
465 self._request(line, f)
468 'lost-connection-behavior',
471 def do_get_logical_switch_config(self, line):
472 """get_logical_switch_config <peer> <source> <logical switch>
479 print("argument error")
481 o = p.get_config(source)
482 for l in o.logical_switches.switch:
486 for k in self._lsw_settings:
489 except AttributeError:
491 print('%s %s' % (k, v))
493 self._request(line, f)
495 def do_set_logical_switch_config(self, line):
496 """set_logical_switch_config <peer> <logical switch> <key> <value>
497 eg. set_logical_switch_config sw1 running LogicalSwitch7 \
498 lost-connection-behavior failStandaloneMode
503 target, lsw, key, value = args
505 print("argument error")
509 o = p.get_config(target)
510 capable_switch_id = o.id
513 capable_switch = ofc.OFCapableSwitchType(
514 id=capable_switch_id,
515 logical_switches=ofc.OFCapableSwitchLogicalSwitchesType(
516 switch=[ofc.OFLogicalSwitchType(
523 print("argument error")
526 p.edit_config(target, capable_switch)
527 except Exception as e:
530 self._request(line, f)
532 completedefault = _complete_peer
534 def complete_EOF(self, _text, _line, _begidx, _endidx):
537 def do_EOF(self, _line):
540 def onecmd(self, string):
541 self._in_onecmd = True
543 return cmd.Cmd.onecmd(self, string)
545 self._in_onecmd = False
548 def main(args=None, prog=None):
549 CONF(args=args, prog=prog,
550 project='of-config-cli', version='of-config-cli')
552 for p_str in CONF.peers:
553 name, addr = p_str.split('=')
554 host, port, username, password = addr.rsplit(':', 3)
555 add_peer(name, host, port, username, password)
560 if __name__ == "__main__":