ba3c5a25f9658043ac66ed043d814cf0b5447916
[osm/SO.git] / rwlaunchpad / plugins / rwvns / rift / tasklets / rwvnstasklet / rwvnstasklet.py
1
2 #
3 # Copyright 2016-2017 RIFT.IO Inc
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 #
17
18 import asyncio
19 import sys
20
21 import gi
22 gi.require_version('RwVnsYang', '1.0')
23 gi.require_version('RwDts', '1.0')
24 from gi.repository import (
25 RwVnsYang,
26 RwDts as rwdts,
27 RwTypes,
28 )
29
30 import rift.tasklets
31 from rift.mano.utils.project import (
32 ManoProject,
33 ProjectHandler,
34 )
35 import rift.mano.sdn
36
37 from rift.vlmgr import (
38 VlrDtsHandler,
39 VldDtsHandler,
40 VirtualLinkRecord,
41 )
42
43 from rift.topmgr import (
44 NwtopStaticDtsHandler,
45 NwtopDiscoveryDtsHandler,
46 NwtopDataStore,
47 )
48
49
50 class VlRecordError(Exception):
51 """ Vlr Record creation Error """
52 pass
53
54
55 class VlRecordNotFound(Exception):
56 """ Vlr Record not found"""
57 pass
58
59
60 class SDNAccountHandlers(object):
61 def __init__(self, dts, log, log_hdl, acctstore, loop, project):
62 self._log = log
63 self._log_hdl = log_hdl
64 self._dts = dts
65 self._loop = loop
66 self._acctstore = acctstore
67 self._project = project
68
69 self._log.debug("Creating SDN account config handler")
70 self.sdn_cfg_handler = rift.mano.sdn.SDNAccountConfigSubscriber(
71 self._dts, self._log, project, self._log_hdl,
72 rift.mano.sdn.SDNAccountConfigCallbacks(
73 on_add_apply=self.on_sdn_account_added,
74 on_delete_apply=self.on_sdn_account_deleted,
75 ),
76 self._acctstore
77
78 )
79
80 self._log.debug("Creating SDN account opdata handler")
81 self.sdn_operdata_handler = rift.mano.sdn.SDNAccountDtsOperdataHandler(
82 self._dts, self._log, self._loop, project,
83 )
84
85 def on_sdn_account_deleted(self, account_name):
86 self._log.debug("SDN account deleted")
87 self.sdn_operdata_handler.delete_sdn_account(account_name)
88
89 def on_sdn_account_added(self, account):
90 self._log.debug("SDN account added")
91 self.sdn_operdata_handler.add_sdn_account(account)
92
93 @asyncio.coroutine
94 def register(self):
95 self.sdn_cfg_handler.register()
96 yield from self.sdn_operdata_handler.register()
97
98 def deregister(self):
99 self.sdn_cfg_handler.deregister()
100 self.sdn_operdata_handler.deregister()
101
102
103 class VnsManager(object):
104 """ The Virtual Network Service Manager """
105 def __init__(self, dts, log, log_hdl, loop, project):
106 self._dts = dts
107 self._log = log
108 self._log_hdl = log_hdl
109 self._loop = loop
110 self._project = project
111 self._acctstore = {}
112 self._vlr_handler = VlrDtsHandler(dts, log, loop, self)
113 self._vld_handler = VldDtsHandler(dts, log, loop, self)
114 self._sdn_handlers = SDNAccountHandlers(dts, log, log_hdl, self._acctstore, loop, project)
115 self._nwtopdata_store = NwtopDataStore(log)
116 self._nwtopdiscovery_handler = NwtopDiscoveryDtsHandler(dts, log, loop, project,
117 self._acctstore, self._nwtopdata_store)
118 self._nwtopstatic_handler = NwtopStaticDtsHandler(dts, log, loop, project,
119 self._acctstore, self._nwtopdata_store)
120 self._vlrs = {}
121
122 @asyncio.coroutine
123 def register_vlr_handler(self):
124 """ Register vlr DTS handler """
125 self._log.debug("Registering DTS VLR handler")
126 yield from self._vlr_handler.register()
127
128 @asyncio.coroutine
129 def register_vld_handler(self):
130 """ Register vlr DTS handler """
131 self._log.debug("Registering DTS VLD handler")
132 yield from self._vld_handler.register()
133
134 @asyncio.coroutine
135 def register_sdn_handlers(self):
136 """ Register SDN DTS handlers """
137 self._log.debug("Registering SDN Account handlers")
138 yield from self._sdn_handlers.register()
139
140 @asyncio.coroutine
141 def register_nwtopstatic_handler(self):
142 """ Register static NW topology DTS handler """
143 self._log.debug("Registering static DTS NW topology handler")
144 yield from self._nwtopstatic_handler.register()
145
146 @asyncio.coroutine
147 def register_nwtopdiscovery_handler(self):
148 """ Register discovery-based NW topology DTS handler """
149 self._log.debug("Registering discovery-based DTS NW topology handler")
150 yield from self._nwtopdiscovery_handler.register()
151
152 @asyncio.coroutine
153 def register(self):
154 """ Register all static DTS handlers"""
155 yield from self.register_sdn_handlers()
156 yield from self.register_vlr_handler()
157 yield from self.register_vld_handler()
158 yield from self.register_nwtopstatic_handler()
159 yield from self.register_nwtopdiscovery_handler()
160
161 def deregister(self):
162 self._nwtopdiscovery_handler.deregister()
163 self._nwtopstatic_handler.deregister()
164 self._vld_handler.deregister()
165 self._vlr_handler.deregister()
166 self._sdn_handlers.deregister()
167
168 def create_vlr(self, msg):
169 """ Create VLR """
170 if msg.id in self._vlrs:
171 err = "Vlr id %s already exists" % msg.id
172 self._log.error(err)
173 # raise VlRecordError(err)
174 return self._vlrs[msg.id]
175
176 self._log.info("Creating VirtualLinkRecord %s", msg.id)
177 self._vlrs[msg.id] = VirtualLinkRecord(self._dts,
178 self._log,
179 self._loop,
180 self,
181 msg,
182 msg.res_id
183 )
184 return self._vlrs[msg.id]
185
186 def get_vlr(self, vlr_id):
187 """ Get VLR by vlr id """
188 return self._vlrs[vlr_id]
189
190 @asyncio.coroutine
191 def delete_vlr(self, vlr_id, xact):
192 """ Delete VLR with the passed id"""
193 if vlr_id not in self._vlrs:
194 err = "Delete Failed - Vlr id %s not found" % vlr_id
195 self._log.error(err)
196 raise VlRecordNotFound(err)
197
198 self._log.info("Deleting virtual link id %s", vlr_id)
199 yield from self._vlrs[vlr_id].terminate(xact)
200 del self._vlrs[vlr_id]
201 self._log.info("Deleted virtual link id %s", vlr_id)
202
203 def find_vlr_by_vld_id(self, vld_id):
204 """ Find a VLR matching the VLD Id """
205 for vlr in self._vlrs.values():
206 if vlr.vld_id == vld_id:
207 return vlr
208 return None
209
210 @asyncio.coroutine
211 def run(self):
212 """ Run this VNSM instance """
213 self._log.debug("Run VNSManager - registering static DTS handlers")
214 yield from self.register()
215
216 def vld_in_use(self, vld_id):
217 """ Is this VLD in use """
218 return False
219
220 @asyncio.coroutine
221 def publish_vlr(self, xact, xpath, msg):
222 """ Publish a VLR """
223 path = self._project.add_project(xpath)
224 self._log.debug("Publish vlr called with path %s, msg %s",
225 path, msg)
226 yield from self._vlr_handler.update(xact, path, msg)
227
228 @asyncio.coroutine
229 def unpublish_vlr(self, xact, xpath):
230 """ Publish a VLR """
231 path = self._project.add_project(xpath)
232 self._log.debug("Unpublish vlr called with path %s", path)
233 yield from self._vlr_handler.delete(xact, path)
234
235
236 class VnsProject(ManoProject):
237
238 def __init__(self, name, tasklet, **kw):
239 super(VnsProject, self).__init__(tasklet.log, name)
240 self.update(tasklet)
241
242 self._vlr_handler = None
243 self._vnsm = None
244 # A mapping of instantiated vlr_id's to VirtualLinkRecord objects
245 self._vlrs = {}
246
247 @asyncio.coroutine
248 def register (self):
249 self._vnsm = VnsManager(dts=self._dts,
250 log=self.log,
251 log_hdl=self._log_hdl,
252 loop=self._loop,
253 project=self)
254 yield from self._vnsm.run()
255
256 # NSM needs to detect VLD deletion that has active VLR
257 # self._vld_handler = VldDescriptorConfigDtsHandler(
258 # self._dts, self.log, self.loop, self._vlrs,
259 # )
260 # yield from self._vld_handler.register()
261
262 def deregister(self):
263 self._log.debug("De-register project {}".format(self.name))
264 self._vnsm.deregister()
265
266
267 class VnsTasklet(rift.tasklets.Tasklet):
268 """ The VNS tasklet class """
269 def __init__(self, *args, **kwargs):
270 super(VnsTasklet, self).__init__(*args, **kwargs)
271 self.rwlog.set_category("rw-mano-log")
272 self.rwlog.set_subcategory("vns")
273
274 self._dts = None
275 self._project_handler = None
276 self.projects = {}
277
278 @property
279 def dts(self):
280 return self._dts
281
282 def start(self):
283 super(VnsTasklet, self).start()
284 self.log.info("Starting VnsTasklet")
285
286 self.log.debug("Registering with dts")
287 self._dts = rift.tasklets.DTS(self.tasklet_info,
288 RwVnsYang.get_schema(),
289 self.loop,
290 self.on_dts_state_change)
291
292 self.log.debug("Created DTS Api GI Object: %s", self._dts)
293
294 def on_instance_started(self):
295 """ The task instance started callback"""
296 self.log.debug("Got instance started callback")
297
298 def stop(self):
299 try:
300 self._dts.deinit()
301 except Exception:
302 print("Caught Exception in VNS stop:", sys.exc_info()[0])
303 raise
304
305 @asyncio.coroutine
306 def init(self):
307 """ task init callback"""
308 self.log.debug("creating project handler")
309 self.project_handler = ProjectHandler(self, VnsProject)
310 self.project_handler.register()
311
312 @asyncio.coroutine
313 def run(self):
314 """ tasklet run callback """
315 pass
316
317 @asyncio.coroutine
318 def on_dts_state_change(self, state):
319 """Take action according to current dts state to transition
320 application into the corresponding application state
321
322 Arguments
323 state - current dts state
324 """
325 switch = {
326 rwdts.State.INIT: rwdts.State.REGN_COMPLETE,
327 rwdts.State.CONFIG: rwdts.State.RUN,
328 }
329
330 handlers = {
331 rwdts.State.INIT: self.init,
332 rwdts.State.RUN: self.run,
333 }
334
335 # Transition application to next state
336 handler = handlers.get(state, None)
337 if handler is not None:
338 yield from handler()
339
340 # Transition dts to next state
341 next_state = switch.get(state, None)
342 if next_state is not None:
343 self._dts.handle.set_state(next_state)