Merge from OSM SO master
[osm/SO.git] / rwlaunchpad / plugins / rwnsm / rift / tasklets / rwnsmtasklet / rwnsmtasklet.py
index 0797b55..ea17e60 100755 (executable)
@@ -35,7 +35,7 @@ from enum import Enum
 
 import gi
 gi.require_version('RwYang', '1.0')
-gi.require_version('RwNsdYang', '1.0')
+gi.require_version('ProjectNsdYang', '1.0')
 gi.require_version('RwDts', '1.0')
 gi.require_version('RwNsmYang', '1.0')
 gi.require_version('RwNsrYang', '1.0')
@@ -46,12 +46,12 @@ from gi.repository import (
     RwYang,
     RwNsrYang,
     NsrYang,
-    NsdYang,
+    ProjectNsdYang as NsdYang,
     RwVlrYang,
     VnfrYang,
     RwVnfrYang,
     RwNsmYang,
-    RwsdnYang,
+    RwsdnalYang,
     RwDts as rwdts,
     RwTypes,
     ProtobufC,
@@ -395,7 +395,7 @@ class VnffgRecord(object):
                     vnfr = yield from self._nsr.fetch_vnfr(nsr_vnfr.xpath)
                     self._log.debug("Received VNFR is %s", vnfr)
 
-                sff =  RwsdnYang.VNFFGSff()
+                sff =  RwsdnalYang.VNFFGSff()
                 sff_list[nsr_vnfr.vnfd.id] = sff
                 sff.name = nsr_vnfr.name
                 sff.function_type = nsr_vnfr.vnfd.service_function_chain
@@ -985,7 +985,7 @@ class VirtualNetworkFunctionRecord(object):
         vnfr.vnfd = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_Vnfd. \
                     from_dict(self.vnfd.as_dict(),
                               ignore_missing_keys=True)
-        vnfr.member_vnf_index_ref = str(self.member_vnf_index)
+        vnfr.member_vnf_index_ref = self.member_vnf_index
         vnfr.vnf_configuration.from_dict(self._vnfd.vnf_configuration.as_dict())
 
         if self._vnfd.mgmt_interface.has_field("port"):
@@ -1094,6 +1094,8 @@ class VirtualNetworkFunctionRecord(object):
             return None
 
         # For every connection point in the VNFD fill in the identifier
+        self._log.debug("Add connection point for VNF %s: %s",
+                        self.vnfr_msg.name, self._vnfd.connection_point)
         for conn_p in self._vnfd.connection_point:
             cpr = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr_ConnectionPoint()
             cpr.name = conn_p.name
@@ -1125,9 +1127,6 @@ class VirtualNetworkFunctionRecord(object):
         self._log.info("Created VNF with xpath %s and vnfr %s",
                        self.xpath, self.vnfr_msg)
 
-        self._log.info("Instantiated VNFR with xpath %s and vnfd %s, vnfr %s",
-                       self.xpath, self._vnfd, self.vnfr_msg)
-
     @asyncio.coroutine
     def update_state(self, vnfr_msg):
         """ Update this VNFR"""
@@ -1444,7 +1443,7 @@ class NetworkServiceRecord(object):
         """  Fetch Cloud Account for the passed vnfd id """
         if self._nsr_cfg_msg.vnf_cloud_account_map:
            vim_accounts = [(vnf.cloud_account,vnf.om_datacenter)  for vnf in self._nsr_cfg_msg.vnf_cloud_account_map \
-                           if vnfd_member_index == vnf.member_vnf_index_ref]
+                           if str(vnfd_member_index) == vnf.member_vnf_index_ref]
            if vim_accounts and vim_accounts[0]:
                return vim_accounts[0]
         return (self.cloud_account_name,self.om_datacenter_name)
@@ -2039,10 +2038,10 @@ class NetworkServiceRecord(object):
         for group in self.nsd_msg.placement_groups:
             for member_vnfd in group.member_vnfd:
                 if (member_vnfd.vnfd_id_ref == vnfd_msg.id) and \
-                   (member_vnfd.member_vnf_index_ref == const_vnfd.member_vnf_index):
+                   (member_vnfd.member_vnf_index_ref == str(const_vnfd.member_vnf_index)):
                     group_info = self.resolve_placement_group_cloud_construct(group)
                     if group_info is None:
-                        self._log.error("Could not resolve cloud-construct for placement group: %s", group.name)
+                        self._log.info("Could not resolve cloud-construct for placement group: %s", group.name)
                         ### raise PlacementGroupError("Could not resolve cloud-construct for placement group: {}".format(group.name))
                     else:
                         self._log.info("Successfully resolved cloud construct for placement group: %s for VNF: %s (Member Index: %s)",
@@ -2057,10 +2056,11 @@ class NetworkServiceRecord(object):
         # Fetch the VNFD associated with this VNF
         placement_groups = self.get_placement_groups(vnfd_msg, const_vnfd)
         self._log.info("Cloud Account for VNF %d is %s",const_vnfd.member_vnf_index,cloud_account_name)
-        self._log.info("Launching VNF: %s (Member Index: %s) in NSD plancement Groups: %s",
+        self._log.info("Launching VNF: %s (Member Index: %s) in NSD plancement Groups: %s, restart mode self.restart_mode %s",
                        vnfd_msg.name,
                        const_vnfd.member_vnf_index,
-                       [ group.name for group in placement_groups])
+                       [ group.name for group in placement_groups],
+                       self.restart_mode)
         vnfr = yield from VirtualNetworkFunctionRecord.create_record(self._dts,
                                             self._log,
                                             self._loop,
@@ -2235,7 +2235,7 @@ class NetworkServiceRecord(object):
     def nsd_xpath(self):
         """ Return NSD config xpath."""
         return self._project.add_project((
-            "C,/nsd:nsd-catalog/nsd:nsd[nsd:id = '{}']"
+            "C,/project-nsd:nsd-catalog/project-nsd:nsd[project-nsd:id = '{}']"
         ).format(self.nsd_id))
 
     @asyncio.coroutine
@@ -2682,6 +2682,26 @@ class InputParameterSubstitution(object):
         self.log = log
         self.project = project
 
+    def _fix_xpath(self, xpath):
+        # Fix the parameter.xpath to include project and correct namespace
+        self.log.error("Provided xpath: {}".format(xpath))
+        #Split the xpath at the /
+        attrs = xpath.split('/')
+        new_xp = attrs[0]
+        for attr in attrs[1:]:
+            new_ns = 'project-nsd'
+            name = attr
+            if ':' in attr:
+                # Includes namespace
+                ns, name = attr.split(':', 2)
+                if ns == "rw-nsd":
+                    ns = "rw-project-nsd"
+
+            new_xp = new_xp + '/' + new_ns + ':' + name
+
+        self.log.error("Updated xpath: {}".format(new_xp))
+        return new_xp
+
     def __call__(self, nsd, nsr_config):
         """Substitutes input parameters from the NSR config into the NSD
 
@@ -2700,7 +2720,7 @@ class InputParameterSubstitution(object):
         # to be modified
         optional_input_parameters = set()
         for input_parameter in nsd.input_parameter_xpath:
-            optional_input_parameters.add(self.project.add_project(input_parameter.xpath))
+            optional_input_parameters.add(input_parameter.xpath)
 
         # Apply the input parameters to the descriptor
         if nsr_config.input_parameter:
@@ -2718,7 +2738,8 @@ class InputParameterSubstitution(object):
                         )
 
                 try:
-                    xpath.setxattr(nsd, param.xpath, param.value)
+                    xp = self._fix_xpath(param.xpath)
+                    xpath.setxattr(nsd, xp, param.value)
 
                 except Exception as e:
                     self.log.exception(e)
@@ -2780,7 +2801,7 @@ class NetworkServiceDescriptor(object):
     def path_for_id(nsd_id):
         """ Return path for the passed nsd_id"""
         return self._nsm._project.add_project(
-            "C,/nsd:nsd-catalog/nsd:nsd[nsd:id = '{}'".
+            "C,/project-nsd:nsd-catalog/project-nsd:nsd[project-nsd:id = '{}'".
             format(nsd_id))
 
     def path(self):
@@ -2794,7 +2815,7 @@ class NetworkServiceDescriptor(object):
 
 class NsdDtsHandler(object):
     """ The network service descriptor DTS handler """
-    XPATH = "C,/nsd:nsd-catalog/nsd:nsd"
+    XPATH = "C,/project-nsd:nsd-catalog/project-nsd:nsd"
 
     def __init__(self, dts, log, loop, nsm):
         self._dts = dts
@@ -2824,11 +2845,17 @@ class NsdDtsHandler(object):
             is_recovery = xact.xact is None and action == rwdts.AppconfAction.INSTALL
             self._log.debug("Got nsd apply cfg (xact:%s) (action:%s)",
                             xact, action)
-            # Create/Update an NSD record
-            for cfg in self._regh.get_xact_elements(xact):
-                # Only interested in those NSD cfgs whose ID was received in prepare callback
-                if cfg.id in scratch.get('nsds', []) or is_recovery:
-                    self._nsm.update_nsd(cfg)
+
+            if self._regh:
+                # Create/Update an NSD record
+                for cfg in self._regh.get_xact_elements(xact):
+                    # Only interested in those NSD cfgs whose ID was received in prepare callback
+                    if cfg.id in scratch.get('nsds', []) or is_recovery:
+                        self._nsm.update_nsd(cfg)
+
+            else:
+                self._log.error("No reg handle for {} for project {}".
+                                format(self.__class__, self._project.name))
 
             scratch.pop('nsds', None)
 
@@ -2900,7 +2927,7 @@ class NsdDtsHandler(object):
 
 class VnfdDtsHandler(object):
     """ DTS handler for VNFD config changes """
-    XPATH = "C,/vnfd:vnfd-catalog/vnfd:vnfd"
+    XPATH = "C,/project-vnfd:vnfd-catalog/project-vnfd:vnfd"
 
     def __init__(self, dts, log, loop, nsm):
         self._dts = dts
@@ -2930,15 +2957,20 @@ class VnfdDtsHandler(object):
             self._log.debug("Got NSM VNFD apply (xact: %s) (action: %s)(scr: %s)",
                             xact, action, scratch)
 
-            # Create/Update a VNFD record
-            for cfg in self._regh.get_xact_elements(xact):
-                # Only interested in those VNFD cfgs whose ID was received in prepare callback
-                if cfg.id in scratch.get('vnfds', []):
-                    self._nsm.update_vnfd(cfg)
+            if self._regh:
+                # Create/Update a VNFD record
+                for cfg in self._regh.get_xact_elements(xact):
+                    # Only interested in those VNFD cfgs whose ID was received in prepare callback
+                    if cfg.id in scratch.get('vnfds', []):
+                        self._nsm.update_vnfd(cfg)
 
-            for cfg in self._regh.elements:
-                if cfg.id in scratch.get('deleted_vnfds', []):
-                    yield from self._nsm.delete_vnfd(cfg.id)
+                        for cfg in self._regh.elements:
+                            if cfg.id in scratch.get('deleted_vnfds', []):
+                                yield from self._nsm.delete_vnfd(cfg.id)
+
+            else:
+                self._log.error("Reg handle none for {} in project {}".
+                                format(self.__class__, self._project))
 
             scratch.pop('vnfds', None)
             scratch.pop('deleted_vnfds', None)
@@ -3350,11 +3382,20 @@ class NsrDtsHandler(object):
 
             if action == rwdts.AppconfAction.INSTALL and xact.id is None:
                 key_pairs = []
-                for element in self._key_pair_regh.elements:
-                    key_pairs.append(element)
-                for element in self._nsr_regh.elements:
-                    nsr = handle_create_nsr(element, key_pairs, restart_mode=True)
-                    self._loop.create_task(begin_instantiation(nsr))
+                if self._key_pair_regh:
+                    for element in self._key_pair_regh.elements:
+                        key_pairs.append(element)
+                else:
+                    self._log.error("Reg handle none for key pair in project {}".
+                                    format(self._project))
+
+                if self._nsr_regh:
+                    for element in self._nsr_regh.elements:
+                        nsr = handle_create_nsr(element, key_pairs, restart_mode=True)
+                        self._loop.create_task(begin_instantiation(nsr))
+                else:
+                    self._log.error("Reg handle none for NSR in project {}".
+                                    format(self._project))
 
 
             (added_msgs, deleted_msgs, updated_msgs) = get_add_delete_update_cfgs(self._nsr_regh,
@@ -3633,7 +3674,7 @@ class VnfrDtsHandler(object):
 
             schema = VnfrYang.YangData_RwProject_Project_VnfrCatalog_Vnfr.schema()
             path_entry = schema.keyspec_to_entry(ks_path)
-            if path_entry.key00.id not in self._nsm._vnfrs:
+            if not path_entry or (path_entry.key00.id not in self._nsm._vnfrs):
                 # Check if this is a monitoring param xpath
                 if 'vnfr:monitoring-param' not in xpath:
                     self._log.error("%s request for non existent record path %s",
@@ -3663,7 +3704,7 @@ class VnfrDtsHandler(object):
 
     def deregister(self):
         self._log.debug("De-register VNFR for project {}".
-                        format(self._project.name))
+                        format(self._nsm._project.name))
         if self._regh:
             self._regh.deregister()
             self._regh = None
@@ -3725,7 +3766,7 @@ class NsdRefCountDtsHandler(object):
 
     def deregister(self):
         self._log.debug("De-register NSD Ref count for project {}".
-                        format(self._project.name))
+                        format(self._nsm._project.name))
         if self._regh:
             self._regh.deregister()
             self._regh = None
@@ -3851,7 +3892,7 @@ class NsManager(object):
     def deregister(self):
         """ Register all static DTS handlers """
         for dts_handle in self._dts_handlers:
-            yield from dts_handle.deregister()
+            dts_handle.deregister()
 
 
     def get_ns_by_nsr_id(self, nsr_id):
@@ -3986,9 +4027,10 @@ class NsManager(object):
             self._log.error(msg)
             raise NetworkServiceRecordError(msg)
 
-        self._log.info("Create NetworkServiceRecord nsr id %s from nsd_id %s",
+        self._log.info("Create NetworkServiceRecord nsr id %s from nsd_id %s, restart mode %s",
                        nsr_msg.id,
-                       nsr_msg.nsd.id)
+                       nsr_msg.nsd.id,
+                       restart_mode)
 
         nsm_plugin = self._ro_plugin_selector.ro_plugin
         sdn_account_name = self._cloud_account_handler.get_cloud_account_sdn_name(nsr_msg.cloud_account)
@@ -4538,6 +4580,14 @@ class NsmProject(ManoProject):
         self._vnffgmgr.deregister()
         self._cloud_account_handler.deregister()
         self._ro_plugin_selector.deregister()
+        self._nsm = None
+
+    @asyncio.coroutine
+    def delete_prepare(self):
+        # Check if any NS instance is present
+        if self._nsm and self._nsm._nsrs:
+            return False
+        return True
 
 
 class NsmTasklet(rift.tasklets.Tasklet):