1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
# Copyright (C) 2017 Nippon Telegraph and Telephone Corporation.
#
# 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.
"""
Events for Zebra protocol service.
"""
import inspect
import logging
from os_ken import utils
from os_ken.controller import event
from os_ken.lib.packet import zebra
LOG = logging.getLogger(__name__)
MOD = utils.import_module(__name__)
ZEBRA_EVENTS = []
class EventZebraBase(event.EventBase):
"""
The base class for Zebra protocol service event class.
The subclasses have at least ``zclient`` and the same attributes with
:py:class: `os_ken.lib.packet.zebra.ZebraMessage`.
``zclient`` is an instance of Zebra client class. See
:py:class: `os_ken.services.protocols.zebra.client.zclient.ZClient` or
:py:class: `os_ken.services.protocols.zebra.server.zserver.ZClient`.
The subclasses are named as::
``"Event" + <Zebra message body class name>``
For Example, if the service received ZEBRA_INTERFACE_ADD message,
the body class should be
:py:class: `os_ken.lib.packet.zebra.ZebraInterfaceAdd`, then the event
class will be named as::
"Event" + "ZebraInterfaceAdd" = "EventZebraInterfaceAdd"
``msg`` argument must be an instance of
:py:class: `os_ken.lib.packet.zebra.ZebraMessage` and used to extract the
attributes for the event classes.
"""
def __init__(self, zclient, msg):
super(EventZebraBase, self).__init__()
assert isinstance(msg, zebra.ZebraMessage)
self.__dict__ = msg.__dict__
self.zclient = zclient
def __repr__(self):
m = ', '.join(
['%s=%r' % (k, v)
for k, v in self.__dict__.items() if not k.startswith('_')])
return "%s(%s)" % (self.__class__.__name__, m)
__str__ = __repr__
def _event_name(body_cls):
return 'Event%s' % body_cls.__name__
def message_to_event(zclient, msg):
"""
Converts Zebra protocol message instance to Zebra protocol service
event instance.
If corresponding event class is not defined, returns None.
:param zclient: Zebra client instance.
:param msg: Zebra protocol message.
:return: Zebra protocol service event.
"""
if not isinstance(msg, zebra.ZebraMessage):
return None
body_cls = msg.get_body_class(msg.version, msg.command)
ev_cls = getattr(MOD, _event_name(body_cls), None)
if ev_cls is None:
return None
return ev_cls(zclient, msg)
def _define_event_class(body_cls):
name = _event_name(body_cls)
event_cls = type(name, (EventZebraBase,), {})
globals()[name] = event_cls
return event_cls
def _generate_event_classes():
for zebra_cls in zebra.__dict__.values():
if (not inspect.isclass(zebra_cls)
or not issubclass(zebra_cls, zebra._ZebraMessageBody)
or zebra_cls.__name__.startswith('_')):
continue
ev = _define_event_class(zebra_cls)
# LOG.debug('Generated Zebra event: %s' % ev)
ZEBRA_EVENTS.append(ev)
_generate_event_classes()
|