of_config: sample test code to use ofconfig capable_switch
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
e2566bbd70
commit
3cfb6fa6e9
229
ryu/tests/integrated/test_of_config.py
Normal file
229
ryu/tests/integrated/test_of_config.py
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
|
||||||
|
# Copyright (C) 2013 Isaku Yamahata <yamahata at private email ne 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 gevent
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
import lxml.etree
|
||||||
|
import ncclient
|
||||||
|
|
||||||
|
from ryu.base import app_manager
|
||||||
|
from ryu.lib.netconf import constants as nc_consts
|
||||||
|
from ryu.lib import of_config
|
||||||
|
from ryu.lib.of_config import capable_switch
|
||||||
|
from ryu.lib.of_config import constants as ofc_consts
|
||||||
|
|
||||||
|
|
||||||
|
# Change those depending on switch configuration
|
||||||
|
HOST = '127.0.0.1'
|
||||||
|
PORT = 1830
|
||||||
|
USERNAME = 'linc'
|
||||||
|
PASSWORD = 'linc'
|
||||||
|
|
||||||
|
CAPABLE_SWITCH_ID = 'CapableSwitch0'
|
||||||
|
LOGICAL_SWITCH = 'LogicalSwitch0'
|
||||||
|
PORT_ID = 'LogicalSwitch0-Port2'
|
||||||
|
CONTROLLER_ID = 'Switch0-DefaultController'
|
||||||
|
|
||||||
|
PORT_DICT = {
|
||||||
|
'capable_switch': CAPABLE_SWITCH_ID,
|
||||||
|
'port_id': PORT_ID,
|
||||||
|
'logical_switch': LOGICAL_SWITCH,
|
||||||
|
'controller_id': CONTROLLER_ID,
|
||||||
|
'ip': HOST,
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_PORT_DOWN = '''
|
||||||
|
<nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
|
||||||
|
<capable-switch xmlns="urn:onf:of111:config:yang">
|
||||||
|
<id>%(capable_switch)s</id>
|
||||||
|
<resources>
|
||||||
|
<port>
|
||||||
|
<resource-id>%(port_id)s</resource-id>
|
||||||
|
<configuration operation="merge">
|
||||||
|
<admin-state>down</admin-state>
|
||||||
|
<no-receive>false</no-receive>
|
||||||
|
<no-forward>false</no-forward>
|
||||||
|
<no-packet-in>false</no-packet-in>
|
||||||
|
</configuration>
|
||||||
|
</port>
|
||||||
|
</resources>
|
||||||
|
</capable-switch>
|
||||||
|
</nc:config>
|
||||||
|
''' % PORT_DICT
|
||||||
|
|
||||||
|
SWITCH_ADVERTISED = '''
|
||||||
|
<nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
|
||||||
|
<capable-switch xmlns="urn:onf:of111:config:yang">
|
||||||
|
<id>%(capable_switch)s</id>
|
||||||
|
<resources>
|
||||||
|
<port>
|
||||||
|
<resource-id>%(port_id)s</resource-id>
|
||||||
|
<features>
|
||||||
|
<advertised operation="merge">
|
||||||
|
<rate>10Mb-FD</rate>
|
||||||
|
<auto-negotiate>true</auto-negotiate>
|
||||||
|
<medium>copper</medium>
|
||||||
|
<pause>unsupported</pause>
|
||||||
|
</advertised>
|
||||||
|
</features>
|
||||||
|
</port>
|
||||||
|
</resources>
|
||||||
|
</capable-switch>
|
||||||
|
</nc:config>
|
||||||
|
''' % PORT_DICT
|
||||||
|
|
||||||
|
SWITCH_CONTROLLER = '''
|
||||||
|
<nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
|
||||||
|
<capable-switch xmlns="urn:onf:of111:config:yang">
|
||||||
|
<id>%(capable_switch)s</id>
|
||||||
|
<logical-switches>
|
||||||
|
<switch>
|
||||||
|
<id>%(logical_switch)s</id>
|
||||||
|
<controllers>
|
||||||
|
<controller operation="merge">
|
||||||
|
<id>%(controller_id)s</id>
|
||||||
|
<role>master</role>
|
||||||
|
<ip-address>%(ip)s</ip-address>
|
||||||
|
<port>6633</port>
|
||||||
|
<protocol>tcp</protocol>
|
||||||
|
</controller>
|
||||||
|
</controllers>
|
||||||
|
</switch>
|
||||||
|
</logical-switches>
|
||||||
|
</capable-switch>
|
||||||
|
</nc:config>
|
||||||
|
''' % PORT_DICT
|
||||||
|
|
||||||
|
|
||||||
|
def _get_schema():
|
||||||
|
# file_name = of_config.OF_CONFIG_1_0_XSD
|
||||||
|
# file_name = of_config.OF_CONFIG_1_1_XSD
|
||||||
|
file_name = of_config.OF_CONFIG_1_1_1_XSD
|
||||||
|
return lxml.etree.XMLSchema(file=file_name)
|
||||||
|
|
||||||
|
|
||||||
|
class OFConfigClient(app_manager.RyuApp):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(OFConfigClient, self).__init__(*args, **kwargs)
|
||||||
|
self.switch = capable_switch.OFCapableSwitch(
|
||||||
|
host=HOST, port=PORT, username=USERNAME, password=PASSWORD)
|
||||||
|
gevent.spawn(self._do_of_config)
|
||||||
|
|
||||||
|
def _validate(self, tree):
|
||||||
|
xmlschema = _get_schema()
|
||||||
|
try:
|
||||||
|
xmlschema.assertValid(tree)
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def _do_get(self):
|
||||||
|
data_xml = self.switch.get()
|
||||||
|
|
||||||
|
tree = lxml.etree.fromstring(data_xml)
|
||||||
|
# print(lxml.etree.tostring(tree, pretty_print=True))
|
||||||
|
self._validate(tree)
|
||||||
|
|
||||||
|
name_spaces = set()
|
||||||
|
for e in tree.getiterator():
|
||||||
|
name_spaces.add(capable_switch.get_ns_tag(e.tag)[0])
|
||||||
|
print(name_spaces)
|
||||||
|
|
||||||
|
return tree
|
||||||
|
|
||||||
|
def _do_get_config(self, source):
|
||||||
|
print('source = %s' % source)
|
||||||
|
config_xml = self.switch.get_config(source)
|
||||||
|
|
||||||
|
tree = lxml.etree.fromstring(config_xml)
|
||||||
|
# print(lxml.etree.tostring(tree, pretty_print=True))
|
||||||
|
self._validate(tree)
|
||||||
|
|
||||||
|
def _do_edit_config(self, config):
|
||||||
|
tree = lxml.etree.fromstring(config)
|
||||||
|
self._validate(tree)
|
||||||
|
self.switch.edit_config(target='running', config=config)
|
||||||
|
|
||||||
|
def _print_ports(self, tree, ns):
|
||||||
|
for port in tree.findall('{%s}%s/{%s}%s' % (ns, ofc_consts.RESOURCES,
|
||||||
|
ns, ofc_consts.PORT)):
|
||||||
|
print(lxml.etree.tostring(port, pretty_print=True))
|
||||||
|
|
||||||
|
def _set_ports_down(self):
|
||||||
|
"""try to set all ports down with etree operation"""
|
||||||
|
tree = self._do_get()
|
||||||
|
print lxml.etree.tostring(tree, pretty_print=True)
|
||||||
|
|
||||||
|
qname = lxml.etree.QName(tree.tag)
|
||||||
|
ns = qname.namespace
|
||||||
|
self._print_ports(tree, ns)
|
||||||
|
|
||||||
|
switch_id = tree.find('{%s}%s' % (ns, ofc_consts.ID))
|
||||||
|
resources = tree.find('{%s}%s' % (ns, ofc_consts.RESOURCES))
|
||||||
|
configuration = tree.find(
|
||||||
|
'{%s}%s/{%s}%s/{%s}%s' % (ns, ofc_consts.RESOURCES,
|
||||||
|
ns, ofc_consts.PORT,
|
||||||
|
ns, ofc_consts.CONFIGURATION))
|
||||||
|
admin_state = tree.find(
|
||||||
|
'{%s}%s/{%s}%s/{%s}%s/{%s}%s' % (ns, ofc_consts.RESOURCES,
|
||||||
|
ns, ofc_consts.PORT,
|
||||||
|
ns, ofc_consts.CONFIGURATION,
|
||||||
|
ns, ofc_consts.ADMIN_STATE))
|
||||||
|
|
||||||
|
config_ = lxml.etree.Element(
|
||||||
|
'{%s}%s' % (ncclient.xml_.BASE_NS_1_0, nc_consts.CONFIG))
|
||||||
|
capable_switch_ = lxml.etree.SubElement(config_, tree.tag)
|
||||||
|
switch_id_ = lxml.etree.SubElement(capable_switch_, switch_id.tag)
|
||||||
|
switch_id_.text = switch_id.text
|
||||||
|
resources_ = lxml.etree.SubElement(capable_switch_,
|
||||||
|
resources.tag)
|
||||||
|
for port in tree.findall(
|
||||||
|
'{%s}%s/{%s}%s' % (ns, ofc_consts.RESOURCES,
|
||||||
|
ns, ofc_consts.PORT)):
|
||||||
|
resource_id = port.find('{%s}%s' % (ns, ofc_consts.RESOURCE_ID))
|
||||||
|
|
||||||
|
port_ = lxml.etree.SubElement(resources_, port.tag)
|
||||||
|
resource_id_ = lxml.etree.SubElement(port_, resource_id.tag)
|
||||||
|
resource_id_.text = resource_id.text
|
||||||
|
configuration_ = lxml.etree.SubElement(port_, configuration.tag)
|
||||||
|
configuration_.set(ofc_consts.OPERATION, nc_consts.MERGE)
|
||||||
|
admin_state_ = lxml.etree.SubElement(configuration_,
|
||||||
|
admin_state.tag)
|
||||||
|
admin_state_.text = ofc_consts.DOWN
|
||||||
|
self._do_edit_config(lxml.etree.tostring(config_, pretty_print=True))
|
||||||
|
|
||||||
|
tree = self._do_get()
|
||||||
|
self._print_ports(tree, ns)
|
||||||
|
|
||||||
|
def _do_of_config(self):
|
||||||
|
self._do_get()
|
||||||
|
self._do_get_config('running')
|
||||||
|
self._do_get_config('startup')
|
||||||
|
|
||||||
|
# LINC doesn't support 'candidate' datastore
|
||||||
|
try:
|
||||||
|
self._do_get_config('candidate')
|
||||||
|
except ncclient.NCClientError:
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
# use raw XML format
|
||||||
|
self._do_edit_config(SWITCH_PORT_DOWN)
|
||||||
|
self._do_edit_config(SWITCH_ADVERTISED)
|
||||||
|
self._do_edit_config(SWITCH_CONTROLLER)
|
||||||
|
|
||||||
|
self._set_ports_down()
|
||||||
|
|
||||||
|
self.switch.close_session()
|
Loading…
Reference in New Issue
Block a user