update from RIFT as of 696b75d2fe9fb046261b08c616f1bcf6c0b54a9b second try
[osm/SO.git] / rwlaunchpad / plugins / rwvns / rift / tasklets / rwvnstasklet / rwvnstasklet.py
index 6ec2421..97ef76c 100755 (executable)
@@ -1,6 +1,6 @@
 
-# 
-#   Copyright 2016 RIFT.IO Inc
+#
+#   Copyright 2016-2017 RIFT.IO Inc
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -28,12 +28,17 @@ from gi.repository import (
 )
 
 import rift.tasklets
+from rift.mano.utils.project import (
+    ManoProject,
+    ProjectHandler,
+)
 import rift.mano.sdn
 
 from rift.vlmgr import (
     VlrDtsHandler,
     VldDtsHandler,
     VirtualLinkRecord,
+    VirtualLinkEventListener
 )
 
 from rift.topmgr import (
@@ -54,16 +59,17 @@ class VlRecordNotFound(Exception):
 
 
 class SDNAccountHandlers(object):
-    def __init__(self, dts, log, log_hdl, acctstore, loop):
+    def __init__(self, dts, log, log_hdl, acctstore, loop, project):
         self._log = log
         self._log_hdl = log_hdl
         self._dts = dts
         self._loop = loop
         self._acctstore = acctstore
+        self._project = project
   
         self._log.debug("Creating SDN account config handler")
         self.sdn_cfg_handler = rift.mano.sdn.SDNAccountConfigSubscriber(
-              self._dts, self._log, self._log_hdl,
+              self._dts, self._log, project, self._log_hdl,
               rift.mano.sdn.SDNAccountConfigCallbacks(
                   on_add_apply=self.on_sdn_account_added,
                   on_delete_apply=self.on_sdn_account_deleted,
@@ -74,7 +80,7 @@ class SDNAccountHandlers(object):
   
         self._log.debug("Creating SDN account opdata handler")
         self.sdn_operdata_handler = rift.mano.sdn.SDNAccountDtsOperdataHandler(
-              self._dts, self._log, self._loop,
+              self._dts, self._log, self._loop, project,
         )
   
     def on_sdn_account_deleted(self, account_name):
@@ -90,21 +96,29 @@ class SDNAccountHandlers(object):
         self.sdn_cfg_handler.register()
         yield from self.sdn_operdata_handler.register()
 
+    def deregister(self):
+        self.sdn_cfg_handler.deregister()
+        self.sdn_operdata_handler.deregister()
+
 
 class VnsManager(object):
     """ The Virtual Network Service Manager """
-    def __init__(self, dts, log, log_hdl, loop):
+    def __init__(self, dts, log, log_hdl, loop, project):
         self._dts = dts
         self._log = log
         self._log_hdl = log_hdl
         self._loop = loop
+        self._project = project
         self._acctstore = {}
         self._vlr_handler = VlrDtsHandler(dts, log, loop, self)
         self._vld_handler = VldDtsHandler(dts, log, loop, self)
-        self._sdn_handlers = SDNAccountHandlers(dts, log, log_hdl, self._acctstore, loop)
+        self._sdn_handlers = SDNAccountHandlers(dts, log, log_hdl, self._acctstore, loop, self._project)
         self._nwtopdata_store = NwtopDataStore(log)
-        self._nwtopdiscovery_handler = NwtopDiscoveryDtsHandler(dts, log, loop, self._acctstore, self._nwtopdata_store)
-        self._nwtopstatic_handler = NwtopStaticDtsHandler(dts, log, loop, self._acctstore, self._nwtopdata_store)
+        self._nwtopdiscovery_handler = NwtopDiscoveryDtsHandler(dts, log, loop, project,
+                                                                self._acctstore, self._nwtopdata_store)
+        self._nwtopstatic_handler = NwtopStaticDtsHandler(dts, log, loop, project,
+                                                          self._acctstore, self._nwtopdata_store)
+        self._vl_event_listener = VirtualLinkEventListener(dts, log, loop, self)
         self._vlrs = {}
 
     @asyncio.coroutine
@@ -137,6 +151,12 @@ class VnsManager(object):
         self._log.debug("Registering  discovery-based DTS NW topology handler")
         yield from self._nwtopdiscovery_handler.register()
 
+    @asyncio.coroutine
+    def register_vl_event_listener(self):
+        """ Register Virtual Link related events DTS handler """
+        self._log.debug("Registering  Virtual Link Event listener")
+        yield from self._vl_event_listener.register()
+
     @asyncio.coroutine
     def register(self):
         """ Register all static DTS handlers"""
@@ -145,6 +165,15 @@ class VnsManager(object):
         yield from self.register_vld_handler()
         yield from self.register_nwtopstatic_handler()
         yield from self.register_nwtopdiscovery_handler()
+        yield from self.register_vl_event_listener()
+
+    def deregister(self):
+        self._vl_event_listener.deregister()
+        self._nwtopdiscovery_handler.deregister()
+        self._nwtopstatic_handler.deregister()
+        self._vld_handler.deregister()
+        self._vlr_handler.deregister()
+        self._sdn_handlers.deregister()
 
     def create_vlr(self, msg):
         """ Create VLR """
@@ -160,7 +189,6 @@ class VnsManager(object):
                                                self._loop,
                                                self,
                                                msg,
-                                               msg.res_id
                                                )
         return self._vlrs[msg.id]
 
@@ -181,7 +209,7 @@ class VnsManager(object):
         del self._vlrs[vlr_id]
         self._log.info("Deleted virtual link id %s", vlr_id)
 
-    def find_vlr_by_vld_id(self, vld_id):
+    def find_vlR_by_vld_id(self, vld_id):
         """ Find a VLR matching the VLD Id """
         for vlr in self._vlrs.values():
             if vlr.vld_id == vld_id:
@@ -199,18 +227,87 @@ class VnsManager(object):
         return False
 
     @asyncio.coroutine
-    def publish_vlr(self, xact, path, msg):
+    def publish_vlr(self, xact, xpath, msg):
         """ Publish a VLR """
+        path = self._project.add_project(xpath)
         self._log.debug("Publish vlr called with path %s, msg %s",
                         path, msg)
         yield from self._vlr_handler.update(xact, path, msg)
 
     @asyncio.coroutine
-    def unpublish_vlr(self, xact, path):
+    def unpublish_vlr(self, xact, xpath):
         """ Publish a VLR """
+        path = self._project.add_project(xpath)
         self._log.debug("Unpublish vlr called with path %s", path)
         yield from self._vlr_handler.delete(xact, path)
 
+    def create_virual_link_event(self, event_id, event_msg):
+        """ Update Virtual Link Event """
+        self._log.debug("Creating Virtual Link Event id [%s], msg [%s]",
+                       event_id, event_msg)
+
+    @asyncio.coroutine
+    def update_virual_link_event(self, event_id, event_msg):
+        """ Update Virtual Link Event """
+        self._log.debug("Updating Virtual Link Event id [%s], msg [%s]",
+                        event_id, event_msg)
+        # event id and vlr_id are the same.
+        # Use event id to look up the VLR and update and publish state change
+        vlr = None
+
+        if event_id in self._vlrs:
+            vlr = self._vlrs[event_id]
+
+        if vlr is None:
+            self._log.error("Received VLR Event notifcation for unknown VLR - event-id:%s",
+                            event_id)
+            return
+
+        if event_msg.resource_info.resource_state == 'active':
+            with self._dts.transaction(flags=0) as xact:
+                yield from vlr.ready(event_msg, xact)
+        elif event_msg.resource_info.resource_state == 'failed':
+            with self._dts.transaction(flags=0) as xact:
+                if event_msg.resource_info.resource_errors:
+                    vlr._state_failed_reason = str(event_msg.resource_info.resource_errors)
+                yield from vlr.failed(event_msg, xact)
+        else:
+            self._log.warning("Receieved unknown resource state %s for event id %s vlr:%s",
+                              event_msg.resource_info.resource_state, event_id, vlr.name)
+
+    def delete_virual_link_event(self, event_id):
+        """ Delete Virtual Link Event """
+        self._log.debug("Deleting Virtual Link Event id [%s]",
+                        event_id)
+
+
+class VnsProject(ManoProject):
+
+    def __init__(self, name, tasklet, **kw):
+        super(VnsProject, self).__init__(tasklet.log, name)
+        self.update(tasklet)
+
+        self._vlr_handler = None
+        self._vnsm = None
+        # A mapping of instantiated vlr_id's to VirtualLinkRecord objects
+        self._vlrs = {}
+
+    @asyncio.coroutine
+    def register (self):
+        try:
+            self._vnsm = VnsManager(dts=self._dts,
+                                    log=self.log,
+                                    log_hdl=self.log_hdl,
+                                    loop=self.loop,
+                                    project=self)
+            yield from self._vnsm.run()
+        except Exception as e:
+            self.log.exception("VNS Task failed to run", e)
+
+    def deregister(self):
+        self._log.debug("De-register project {}".format(self.name))
+        self._vnsm.deregister()
+
 
 class VnsTasklet(rift.tasklets.Tasklet):
     """ The VNS tasklet class """
@@ -220,21 +317,25 @@ class VnsTasklet(rift.tasklets.Tasklet):
         self.rwlog.set_subcategory("vns")
 
         self._dts = None
-        self._vlr_handler = None
+        self._project_handler = None
+        self.projects = {}
 
-        self._vnsm = None
-        # A mapping of instantiated vlr_id's to VirtualLinkRecord objects
-        self._vlrs = {}
+    @property
+    def dts(self):
+        return self._dts
 
     def start(self):
         super(VnsTasklet, self).start()
         self.log.info("Starting VnsTasklet")
 
         self.log.debug("Registering with dts")
-        self._dts = rift.tasklets.DTS(self.tasklet_info,
-                                      RwVnsYang.get_schema(),
-                                      self.loop,
-                                      self.on_dts_state_change)
+        try:
+            self._dts = rift.tasklets.DTS(self.tasklet_info,
+                                          RwVnsYang.get_schema(),
+                                          self.loop,
+                                          self.on_dts_state_change)
+        except Exception:
+            self.log.exception("Caught Exception in VNS start:", e)
 
         self.log.debug("Created DTS Api GI Object: %s", self._dts)
 
@@ -252,17 +353,9 @@ class VnsTasklet(rift.tasklets.Tasklet):
     @asyncio.coroutine
     def init(self):
         """ task init callback"""
-        self._vnsm = VnsManager(dts=self._dts,
-                                log=self.log,
-                                log_hdl=self.log_hdl,
-                                loop=self.loop)
-        yield from self._vnsm.run()
-
-        # NSM needs to detect VLD deletion that has active VLR
-        # self._vld_handler = VldDescriptorConfigDtsHandler(
-        #         self._dts, self.log, self.loop, self._vlrs,
-        #         )
-        # yield from self._vld_handler.register()
+        self.log.debug("creating project handler")
+        self.project_handler = ProjectHandler(self, VnsProject)
+        self.project_handler.register()
 
     @asyncio.coroutine
     def run(self):