backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / controller / handler.py
1 # Copyright (C) 2011-2014 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2011, 2012 Isaku Yamahata <yamahata at valinux co jp>
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #    http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 import inspect
18 import logging
19 import sys
20
21 LOG = logging.getLogger('ryu.controller.handler')
22
23 # just represent OF datapath state. datapath specific so should be moved.
24 HANDSHAKE_DISPATCHER = "handshake"
25 CONFIG_DISPATCHER = "config"
26 MAIN_DISPATCHER = "main"
27 DEAD_DISPATCHER = "dead"
28
29
30 class _Caller(object):
31     """Describe how to handle an event class.
32     """
33
34     def __init__(self, dispatchers, ev_source):
35         """Initialize _Caller.
36
37         :param dispatchers: A list of states or a state, in which this
38                             is in effect.
39                             None and [] mean all states.
40         :param ev_source: The module which generates the event.
41                           ev_cls.__module__ for set_ev_cls.
42                           None for set_ev_handler.
43         """
44         self.dispatchers = dispatchers
45         self.ev_source = ev_source
46
47
48 # should be named something like 'observe_event'
49 def set_ev_cls(ev_cls, dispatchers=None):
50     """
51     A decorator for Ryu application to declare an event handler.
52
53     Decorated method will become an event handler.
54     ev_cls is an event class whose instances this RyuApp wants to receive.
55     dispatchers argument specifies one of the following negotiation phases
56     (or a list of them) for which events should be generated for this handler.
57     Note that, in case an event changes the phase, the phase before the change
58     is used to check the interest.
59
60     .. tabularcolumns:: |l|L|
61
62     =========================================== ===============================
63     Negotiation phase                           Description
64     =========================================== ===============================
65     ryu.controller.handler.HANDSHAKE_DISPATCHER Sending and waiting for hello
66                                                 message
67     ryu.controller.handler.CONFIG_DISPATCHER    Version negotiated and sent
68                                                 features-request message
69     ryu.controller.handler.MAIN_DISPATCHER      Switch-features message
70                                                 received and sent set-config
71                                                 message
72     ryu.controller.handler.DEAD_DISPATCHER      Disconnect from the peer.  Or
73                                                 disconnecting due to some
74                                                 unrecoverable errors.
75     =========================================== ===============================
76     """
77     def _set_ev_cls_dec(handler):
78         if 'callers' not in dir(handler):
79             handler.callers = {}
80         for e in _listify(ev_cls):
81             handler.callers[e] = _Caller(_listify(dispatchers), e.__module__)
82         return handler
83     return _set_ev_cls_dec
84
85
86 def set_ev_handler(ev_cls, dispatchers=None):
87     def _set_ev_cls_dec(handler):
88         if 'callers' not in dir(handler):
89             handler.callers = {}
90         for e in _listify(ev_cls):
91             handler.callers[e] = _Caller(_listify(dispatchers), None)
92         return handler
93     return _set_ev_cls_dec
94
95
96 def _has_caller(meth):
97     return hasattr(meth, 'callers')
98
99
100 def _listify(may_list):
101     if may_list is None:
102         may_list = []
103     if not isinstance(may_list, list):
104         may_list = [may_list]
105     return may_list
106
107
108 def register_instance(i):
109     for _k, m in inspect.getmembers(i, inspect.ismethod):
110         # LOG.debug('instance %s k %s m %s', i, _k, m)
111         if _has_caller(m):
112             for ev_cls, c in m.callers.items():
113                 i.register_handler(ev_cls, m)
114
115
116 def _is_method(f):
117     return inspect.isfunction(f) or inspect.ismethod(f)
118
119
120 def get_dependent_services(cls):
121     services = []
122     for _k, m in inspect.getmembers(cls, _is_method):
123         if _has_caller(m):
124             for ev_cls, c in m.callers.items():
125                 service = getattr(sys.modules[ev_cls.__module__],
126                                   '_SERVICE_NAME', None)
127                 if service:
128                     # avoid cls that registers the own events (like
129                     # ofp_handler)
130                     if cls.__module__ != service:
131                         services.append(service)
132
133     m = sys.modules[cls.__module__]
134     services.extend(getattr(m, '_REQUIRED_APP', []))
135     services = list(set(services))
136     return services
137
138
139 def register_service(service):
140     """
141     Register the ryu application specified by 'service' as
142     a provider of events defined in the calling module.
143
144     If an application being loaded consumes events (in the sense of
145     set_ev_cls) provided by the 'service' application, the latter
146     application will be automatically loaded.
147
148     This mechanism is used to e.g. automatically start ofp_handler if
149     there are applications consuming OFP events.
150     """
151     frame = inspect.currentframe()
152     m_name = frame.f_back.f_globals['__name__']
153     m = sys.modules[m_name]
154     m._SERVICE_NAME = service