os-ken/ryu/lib/of_config/base.py
YAMAMOTO Takashi ac94864869 of_config: allows both of of-config element names and python style names
for convenience of api consumers, allows both of of-config style
element names (eg. logical-switches) and python style attribute
names (eg. logical_switches).

Signed-off-by: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2013-12-25 12:13:01 +09:00

156 lines
4.2 KiB
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.
# 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)
assert not e.name in kwargs
except KeyError:
k = 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)
def __getattribute__(self, k):
return stringify.StringifyMixin.__getattribute__(self, _pythonify(k))
def __setattr__(self, k, v):
stringify.StringifyMixin.__setattr__(self, _pythonify(k), v)
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)