add some convenient OF-Config classes
some python classes for a set of OF-Config 1.1.1 types. the goal is to allow programmers use OF-Config without direct XML manipulations. 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
82dafb7300
commit
e0ddf4c190
144
ryu/lib/of_config/base.py
Normal file
144
ryu/lib/of_config/base.py
Normal file
@ -0,0 +1,144 @@
|
||||
# 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.
|
||||
|
||||
# convenient classes to manipulate OF-Config XML
|
||||
# in a little more pythonic way.
|
||||
# currently assuming OF-Config 1.1.1.
|
||||
|
||||
from ryu.lib import stringify
|
||||
|
||||
from lxml import objectify
|
||||
import lxml.etree as ET
|
||||
|
||||
|
||||
_ns_of111 = 'urn:onf:of111:config:yang'
|
||||
_ns_netconf = 'urn:ietf:params:xml:ns:netconf:base:1.0'
|
||||
_nsmap = {
|
||||
'of111': _ns_of111,
|
||||
'nc': _ns_netconf,
|
||||
}
|
||||
|
||||
|
||||
def _pythonify(name):
|
||||
return name.replace('-', '_')
|
||||
|
||||
|
||||
class _e(object):
|
||||
def __init__(self, name, is_list):
|
||||
self.name = name
|
||||
self.cls = None
|
||||
self.is_list = is_list
|
||||
|
||||
|
||||
# complexType
|
||||
class _ct(_e):
|
||||
def __init__(self, name, cls, is_list):
|
||||
super(_ct, self).__init__(name, is_list)
|
||||
self.cls = cls
|
||||
|
||||
|
||||
class _Base(stringify.StringifyMixin):
|
||||
_M = objectify.ElementMaker(annotate=False,
|
||||
namespace=_ns_of111,
|
||||
nsmap=_nsmap)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
for e in self._ELEMENTS:
|
||||
k = _pythonify(e.name)
|
||||
try:
|
||||
v = kwargs.pop(k)
|
||||
except KeyError:
|
||||
if e.is_list:
|
||||
v = []
|
||||
else:
|
||||
v = None
|
||||
setattr(self, k, v)
|
||||
if kwargs:
|
||||
raise TypeError('unknown kwargs %s' % kwargs)
|
||||
|
||||
def to_et(self, tag):
|
||||
def convert(v):
|
||||
if isinstance(v, _Base):
|
||||
return v.to_et(e.name)
|
||||
elif isinstance(v, objectify.ObjectifiedElement):
|
||||
assert ET.QName(v.tag).localname == itag
|
||||
return v
|
||||
return self._M(itag, v)
|
||||
|
||||
args = []
|
||||
for e in self._ELEMENTS:
|
||||
itag = e.name
|
||||
k = _pythonify(itag)
|
||||
v = getattr(self, k)
|
||||
if v is None:
|
||||
continue
|
||||
if isinstance(v, list):
|
||||
assert e.is_list
|
||||
ele = map(convert, v)
|
||||
else:
|
||||
assert not e.is_list
|
||||
ele = [convert(v)]
|
||||
args.extend(ele)
|
||||
return self._M(tag, *args)
|
||||
|
||||
def to_xml(self, tag):
|
||||
e = self.to_et(tag)
|
||||
return ET.tostring(e, pretty_print=True)
|
||||
|
||||
@classmethod
|
||||
def from_xml(cls, xmlstring):
|
||||
et = objectify.fromstring(xmlstring)
|
||||
return cls.from_et(et)
|
||||
|
||||
@classmethod
|
||||
def from_et(cls, et):
|
||||
def convert(v):
|
||||
if not e.cls is None:
|
||||
return e.cls.from_et(v)
|
||||
return v
|
||||
|
||||
kwargs = {}
|
||||
for e in cls._ELEMENTS:
|
||||
try:
|
||||
v = et[e.name]
|
||||
except AttributeError:
|
||||
continue
|
||||
assert isinstance(v, objectify.ObjectifiedElement)
|
||||
if len(v) == 1:
|
||||
v = convert(v)
|
||||
if e.is_list:
|
||||
v = [v]
|
||||
else:
|
||||
assert e.is_list
|
||||
v = map(convert, v)
|
||||
k = _pythonify(e.name)
|
||||
assert not k in kwargs
|
||||
kwargs[k] = v
|
||||
return cls(**kwargs)
|
||||
|
||||
|
||||
class _Unimpl(_Base):
|
||||
_ELEMENTS = [
|
||||
_e('raw_et', is_list=False),
|
||||
]
|
||||
|
||||
def to_et(self, tag):
|
||||
assert self.raw_et.tag == tag
|
||||
return self.raw_et
|
||||
|
||||
@classmethod
|
||||
def from_et(cls, et):
|
||||
return cls(raw_et=et)
|
35
ryu/lib/of_config/classes.py
Normal file
35
ryu/lib/of_config/classes.py
Normal file
@ -0,0 +1,35 @@
|
||||
# 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.
|
||||
|
||||
# convenient classes to manipulate OF-Config XML
|
||||
# in a little more pythonic way.
|
||||
# currently assuming OF-Config 1.1.1.
|
||||
|
||||
from ryu.lib import stringify
|
||||
|
||||
|
||||
from .base import _Base, _ct, _e, _ns_netconf
|
||||
from .generated_classes import *
|
||||
|
||||
|
||||
# probably should not be here but for convenience
|
||||
class NETCONF_Config(_Base):
|
||||
_ELEMENTS = [
|
||||
_ct('capable-switch', OFCapableSwitchType, is_list=False),
|
||||
]
|
||||
|
||||
def to_xml(self):
|
||||
return super(NETCONF_Config, self).to_xml('{%s}config' % _ns_netconf)
|
154
ryu/lib/of_config/generated_classes.py
Normal file
154
ryu/lib/of_config/generated_classes.py
Normal file
@ -0,0 +1,154 @@
|
||||
# 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.
|
||||
|
||||
# NOTE: this file is intendend to be replaced with mechanically generated
|
||||
# file if/when OF-Config yang specification is available with a suitable
|
||||
# license.
|
||||
|
||||
from ryu.lib.of_config.base import _Base, _e, _ct
|
||||
|
||||
|
||||
class OFPortConfigurationType(_Base):
|
||||
_ELEMENTS = [
|
||||
_e('admin-state', is_list=False),
|
||||
_e('no-receive', is_list=False),
|
||||
_e('no-forward', is_list=False),
|
||||
_e('no-packet-in', is_list=False),
|
||||
]
|
||||
|
||||
|
||||
class OFPortType(_Base):
|
||||
_ELEMENTS = [
|
||||
_e('resource-id', is_list=False),
|
||||
_e('number', is_list=False),
|
||||
_e('name', is_list=False),
|
||||
_e('current-rate', is_list=False),
|
||||
_e('max-rate', is_list=False),
|
||||
_ct('configuration', OFPortConfigurationType, is_list=False),
|
||||
_ct('state', None, is_list=False),
|
||||
_ct('features', None, is_list=False),
|
||||
_ct('tunnel-type', None, is_list=False),
|
||||
]
|
||||
|
||||
|
||||
class OFQueuePropertiesType(_Base):
|
||||
_ELEMENTS = [
|
||||
_e('min-rate', is_list=False),
|
||||
_e('max-rate', is_list=False),
|
||||
_e('experimenter', is_list=True),
|
||||
]
|
||||
|
||||
|
||||
class OFQueueType(_Base):
|
||||
_ELEMENTS = [
|
||||
_e('resource-id', is_list=False),
|
||||
_e('id', is_list=False),
|
||||
_e('port', is_list=False),
|
||||
_ct('properties', OFQueuePropertiesType, is_list=False),
|
||||
]
|
||||
|
||||
|
||||
class OFCapableSwitchResourcesType(_Base):
|
||||
_ELEMENTS = [
|
||||
_ct('port', OFPortType, is_list=True),
|
||||
_ct('queue', OFQueueType, is_list=True),
|
||||
_ct('owned-certificate', None, is_list=True),
|
||||
_ct('external-certificate', None, is_list=True),
|
||||
_ct('flow-table', None, is_list=True),
|
||||
]
|
||||
|
||||
|
||||
class OFControllerStateType(_Base):
|
||||
_ELEMENTS = [
|
||||
_e('connection-state', is_list=False),
|
||||
_e('current-version', is_list=False),
|
||||
|
||||
# XXX OF-Config 1.1.1 is inconsistent about supported-versions.
|
||||
#
|
||||
# according to its xml schema (p.43), i believe this should look
|
||||
# like the following. it's what linc/of_config does, too.
|
||||
# <supported-versions>1.3</supported-versions>
|
||||
#
|
||||
# on the other hand, it has an example (p.45) like the following.
|
||||
# this one is compatible with OF-Config 1.1.
|
||||
# <supported-versions>
|
||||
# <version>1.2</version>
|
||||
# <version>1.1</version>
|
||||
# </supported-versions>
|
||||
|
||||
_e('supported-versions', is_list=True),
|
||||
_e('local-ip-address-in-use', is_list=False),
|
||||
_e('local-port-in-use', is_list=False),
|
||||
]
|
||||
|
||||
|
||||
class OFControllerType(_Base):
|
||||
_ELEMENTS = [
|
||||
_e('id', is_list=False),
|
||||
_e('role', is_list=False),
|
||||
_e('ip-address', is_list=False),
|
||||
_e('port', is_list=False),
|
||||
_e('local-ip-address', is_list=False),
|
||||
_e('local-port', is_list=False),
|
||||
_e('protocol', is_list=False),
|
||||
_ct('state', OFControllerStateType, is_list=False),
|
||||
]
|
||||
|
||||
|
||||
class OFLogicalSwitchControllersType(_Base):
|
||||
_ELEMENTS = [
|
||||
_ct('controller', OFControllerType, is_list=True),
|
||||
]
|
||||
|
||||
|
||||
class OFLogicalSwitchResourcesType(_Base):
|
||||
_ELEMENTS = [
|
||||
_e('port', is_list=True),
|
||||
_e('queue', is_list=True),
|
||||
_e('certificate', is_list=False),
|
||||
_e('flow-table', is_list=True),
|
||||
]
|
||||
|
||||
|
||||
class OFLogicalSwitchType(_Base):
|
||||
_ELEMENTS = [
|
||||
_e('id', is_list=False),
|
||||
_ct('capabilities', None, is_list=False),
|
||||
_e('datapath-id', is_list=False),
|
||||
_e('enabled', is_list=False),
|
||||
_e('check-controller-certificate', is_list=False),
|
||||
_e('lost-connection-behavior', is_list=False),
|
||||
_ct('controllers', OFLogicalSwitchControllersType, is_list=False),
|
||||
_ct('resources', OFLogicalSwitchResourcesType, is_list=False),
|
||||
]
|
||||
|
||||
|
||||
class OFCapableSwitchLogicalSwitchesType(_Base):
|
||||
_ELEMENTS = [
|
||||
# this is named 'logical-switch' for OF-Config 1.1.
|
||||
_ct('switch', OFLogicalSwitchType, is_list=True),
|
||||
]
|
||||
|
||||
|
||||
class OFCapableSwitchType(_Base):
|
||||
_ELEMENTS = [
|
||||
_e('id', is_list=False),
|
||||
_e('config-version', is_list=False),
|
||||
_ct('configuration-points', None, is_list=False),
|
||||
_ct('resources', OFCapableSwitchResourcesType, is_list=False),
|
||||
_ct('logical-switches', OFCapableSwitchLogicalSwitchesType,
|
||||
is_list=False),
|
||||
]
|
Loading…
x
Reference in New Issue
Block a user