update from RIFT as of 696b75d2fe9fb046261b08c616f1bcf6c0b54a9b second try
[osm/SO.git] / rwcm / plugins / rwconman / rift / tasklets / rwconmantasklet / rwconman_config.py
index 0abed99..6440464 100644 (file)
@@ -16,6 +16,7 @@
 #
 
 import asyncio
+import gi
 import os
 import stat
 import subprocess
@@ -28,18 +29,24 @@ from gi.repository import (
     RwConmanYang as conmanY,
     ProtobufC,
 )
+gi.require_version('RwKeyspec', '1.0')
+from gi.repository.RwKeyspec import quoted_key
 
 import rift.tasklets
+import rift.package.script
+import rift.package.store
 
 from . import rwconman_conagent as conagent
 from . import RiftCM_rpc
 from . import riftcm_config_plugin
 
+
 if sys.version_info < (3, 4, 4):
     asyncio.ensure_future = asyncio.async
 
-def get_vnf_unique_name(nsr_name, vnfr_short_name, member_vnf_index):
-    return "{}.{}.{}".format(nsr_name, vnfr_short_name, member_vnf_index)
+def get_vnf_unique_name(nsr_name, vnfr_name, member_vnf_index):
+    return "{}.{}.{}".format(nsr_name, vnfr_name, member_vnf_index)
+
 
 class ConmanConfigError(Exception):
     pass
@@ -49,6 +56,10 @@ class InitialConfigError(ConmanConfigError):
     pass
 
 
+class ScriptNotFoundError(InitialConfigError):
+    pass
+
+
 def log_this_vnf(vnf_cfg):
     log_vnf = ""
     used_item_list = ['nsr_name', 'vnfr_name', 'member_vnf_index', 'mgmt_ip_address']
@@ -127,19 +138,15 @@ class ConfigManagerConfig(object):
         self._log = log
         self._loop = loop
         self._parent = parent
+        self._project = parent._project
+
         self._nsr_dict = {}
         self.pending_cfg = {}
         self.terminate_cfg = {}
         self.pending_tasks = [] # User for NSRid get retry
                                 # (mainly excercised at restart case)
-        self._config_xpath = "C,/cm-config"
-        self._opdata_xpath = "D,/rw-conman:cm-state"
 
-        self.cm_config = conmanY.SoConfig()
-        # RO specific configuration
-        self.ro_config = {}
-        for key in self.cm_config.ro_endpoint.fields:
-            self.ro_config[key] = None
+        self._opdata_xpath = self._project.add_project("D,/rw-conman:cm-state")
 
         # Initialize cm-state
         self.cm_state = {}
@@ -147,20 +154,24 @@ class ConfigManagerConfig(object):
         self.cm_state['states'] = "Initialized"
 
         # Initialize objects to register
-        self.cmdts_obj = ConfigManagerDTS(self._log, self._loop, self, self._dts)
+        self.cmdts_obj = ConfigManagerDTS(self._log, self._loop, self, self._dts, self._project)
         self._config_agent_mgr = conagent.RiftCMConfigAgent(
             self._dts,
             self._log,
             self._loop,
             self,
         )
+
+        self.riftcm_rpc_handler = RiftCM_rpc.RiftCMRPCHandler(self._dts, self._log, self._loop, self._project,
+                                        PretendNsm(
+                                            self._dts, self._log, self._loop, self))
+
         self.reg_handles = [
             self.cmdts_obj,
             self._config_agent_mgr,
-            RiftCM_rpc.RiftCMRPCHandler(self._dts, self._log, self._loop,
-                                        PretendNsm(
-                                            self._dts, self._log, self._loop, self)),
+            self.riftcm_rpc_handler
         ]
+        self._op_reg = None
 
     def is_nsr_valid(self, nsr_id):
         if nsr_id in self._nsr_dict:
@@ -170,17 +181,19 @@ class ConfigManagerConfig(object):
     def add_to_pending_tasks(self, task):
         if self.pending_tasks:
             for p_task in self.pending_tasks:
-                if p_task['nsrid'] == task['nsrid']:
+                if (p_task['nsrid'] == task['nsrid']) and \
+                   (p_task['event'] == task['event']):
                     # Already queued
                     return
         try:
             self.pending_tasks.append(task)
             self._log.debug("add_to_pending_tasks (nsrid:%s)",
                             task['nsrid'])
-            if len(self.pending_tasks) == 1:
+            if len(self.pending_tasks) >= 1:
                 self._loop.create_task(self.ConfigManagerConfig_pending_loop())
                 # TBD - change to info level
                 self._log.debug("Started pending_loop!")
+
         except Exception as e:
             self._log.error("Failed adding to pending tasks (%s)", str(e))
 
@@ -201,26 +214,28 @@ class ConfigManagerConfig(object):
             """
             if self.pending_tasks:
                 self._log.debug("self.pending_tasks len=%s", len(self.pending_tasks))
-                task = self.pending_tasks[0]
+                task = self.pending_tasks.pop(0)
                 done = False
                 if 'nsrid' in task:
                     nsrid = task['nsrid']
-                    self._log.debug("Will execute pending task for NSR id(%s)", nsrid)
+                    self._log.debug("Will execute pending task for NSR id: %s", nsrid)
                     try:
                         # Try to configure this NSR
                         task['retries'] -= 1
-                        done = yield from self.config_NSR(nsrid)
+                        done = yield from self.config_NSR(nsrid, task['event'])
                         self._log.info("self.config_NSR status=%s", done)
 
                     except Exception as e:
-                        self._log.error("Failed(%s) configuring NSR(%s)," \
+                        self._log.error("Failed(%s) configuring NSR(%s) for task %s," \
                                         "retries remained:%d!",
-                                        str(e), nsrid, task['retries'])
-                    finally:
-                        self.pending_tasks.remove(task)
+                                        str(e), nsrid, task['event'] , task['retries'])
+                        self._log.exception(e)
+                        if task['event'] == 'terminate':
+                            # Ignore failure
+                            done = True
 
                     if done:
-                        self._log.debug("Finished pending task NSR id(%s):", nsrid)
+                        self._log.debug("Finished pending task NSR id: %s", nsrid)
                     else:
                         self._log.error("Failed configuring NSR(%s), retries remained:%d!",
                                         nsrid, task['retries'])
@@ -241,7 +256,19 @@ class ConfigManagerConfig(object):
         # Initialize all handles that needs to be registered
         for reg in self.reg_handles:
             yield from reg.register()
-        
+
+    def deregister(self):
+        # De-register all reg handles
+        self._log.debug("De-register ConfigManagerConfig for project {}".
+                        format(self._project))
+
+        for reg in self.reg_handles:
+            reg.deregister()
+            reg = None
+
+        self._op_reg.delete_element(self._opdata_xpath)
+        self._op_reg.deregister()
+
     @asyncio.coroutine
     def register_cm_state_opdata(self):
 
@@ -252,16 +279,13 @@ class ConfigManagerConfig(object):
                 conmanY.RecordState.CFG_PROCESS : "cfg_process",
                 conmanY.RecordState.CFG_PROCESS_FAILED : "cfg_process_failed",
                 conmanY.RecordState.CFG_SCHED : "cfg_sched",
-                conmanY.RecordState.CFG_DELAY : "cfg_delay",
                 conmanY.RecordState.CONNECTING : "connecting",
                 conmanY.RecordState.FAILED_CONNECTION : "failed_connection",
-                conmanY.RecordState.NETCONF_CONNECTED : "netconf_connected",
-                conmanY.RecordState.NETCONF_SSH_CONNECTED : "netconf_ssh_connected",
-                conmanY.RecordState.RESTCONF_CONNECTED : "restconf_connected",
                 conmanY.RecordState.CFG_SEND : "cfg_send",
                 conmanY.RecordState.CFG_FAILED : "cfg_failed",
                 conmanY.RecordState.READY_NO_CFG : "ready_no_cfg",
                 conmanY.RecordState.READY : "ready",
+                conmanY.RecordState.TERMINATE : "terminate",
                 }
             return state_dict[state]
 
@@ -271,9 +295,9 @@ class ConfigManagerConfig(object):
             self._log.debug("Received cm-state: msg=%s, action=%s", msg, action)
 
             if action == rwdts.QueryAction.READ:
-                show_output = conmanY.CmOpdata()
-                show_output.from_dict(self.cm_state)
                 self._log.debug("Responding to SHOW cm-state: %s", self.cm_state)
+                show_output = conmanY.YangData_RwProject_Project_CmState()
+                show_output.from_dict(self.cm_state)
                 xact_info.respond_xpath(rwdts.XactRspCode.ACK,
                                         xpath=self._opdata_xpath,
                                         msg=show_output)
@@ -285,370 +309,566 @@ class ConfigManagerConfig(object):
 
         try:
             handler=rift.tasklets.DTS.RegistrationHandler(on_prepare=on_prepare)
-            yield from self._dts.register(xpath=self._opdata_xpath,
-                                          handler=handler,
-                                          flags=rwdts.Flag.PUBLISHER)
+            self._op_reg = yield from self._dts.register(xpath=self._opdata_xpath,
+                                                         handler=handler,
+                                                         flags=rwdts.Flag.PUBLISHER)
             self._log.info("Successfully registered for opdata(%s)", self._opdata_xpath)
         except Exception as e:
             self._log.error("Failed to register for opdata as (%s)", e)
+   
+    def get_config_method(self, vnf_config):
+          cfg_types = ['juju', 'script']
+          for method in cfg_types:
+              if method in vnf_config:
+                  return method
+          return None
 
     @asyncio.coroutine
     def process_nsd_vnf_configuration(self, nsr_obj, vnfr):
 
-        def get_config_method(vnf_config):
-            cfg_types = ['netconf', 'juju', 'script']
-            for method in cfg_types:
-                if method in vnf_config:
-                    return method
-            return None
-            
-        def get_cfg_file_extension(method,  configuration_options):
-            ext_dict = {
-                "netconf" : "xml",
-                "script" : {
-                    "bash" : "sh",
-                    "expect" : "exp",
-                },
-                "juju" : "yml"
-            }
-
-            if method == "netconf":
-                return ext_dict[method]
-            elif method == "script":
-                return ext_dict[method][configuration_options['script_type']]
-            elif method == "juju":
-                return ext_dict[method]
-            else:
-                return "cfg"
-
-        # This is how the YAML file should look like,
-        # This routine will be called for each VNF, so keep appending the file.
-        # priority order is determined by the number,
-        # hence no need to generate the file in that order. A dictionary will be
-        # used that will take care of the order by number.
-        '''
-        1 : <== This is priority
-          name : trafsink_vnfd
-          member_vnf_index : 2
-          configuration_delay : 120
-          configuration_type : netconf
-          configuration_options :
-            username : admin
-            password : admin
-            port : 2022
-            target : running
-        2 :
-          name : trafgen_vnfd
-          member_vnf_index : 1
-          configuration_delay : 0
-          configuration_type : netconf
-          configuration_options :
-            username : admin
-            password : admin
-            port : 2022
-            target : running
-        '''
+        # Get vnf_configuration from vnfr
+        vnf_config = vnfr['vnf_configuration']
 
         # Save some parameters needed as short cuts in flat structure (Also generated)
         vnf_cfg = vnfr['vnf_cfg']
         # Prepare unique name for this VNF
         vnf_cfg['vnf_unique_name'] = get_vnf_unique_name(
-            vnf_cfg['nsr_name'], vnfr['short_name'], vnfr['member_vnf_index_ref'])
-
-        nsr_obj.cfg_path_prefix = '{}/{}_{}'.format(
-            nsr_obj.this_nsr_dir, vnfr['short_name'], vnfr['member_vnf_index_ref'])
-        nsr_vnfr = '{}/{}_{}'.format(
-            vnf_cfg['nsr_name'], vnfr['short_name'], vnfr['member_vnf_index_ref'])
-
-        # Get vnf_configuration from vnfr
-        vnf_config = vnfr['vnf_configuration']
+            vnf_cfg['nsr_name'], vnfr['name'], vnfr['member_vnf_index_ref'])
 
         self._log.debug("vnf_configuration = %s", vnf_config)
 
-        # Create priority dictionary
-        cfg_priority_order = 0
-        if ('config_attributes' in vnf_config and
-            'config_priority' in vnf_config['config_attributes']):
-            cfg_priority_order = vnf_config['config_attributes']['config_priority']
-
-        if cfg_priority_order not in nsr_obj.nsr_cfg_config_attributes_dict:
-            # No VNFR with this priority yet, initialize the list
-            nsr_obj.nsr_cfg_config_attributes_dict[cfg_priority_order] = []
+        method = self.get_config_method(vnf_config)
 
-        method = get_config_method(vnf_config)
         if method is not None:
-            # Create all sub dictionaries first
-            config_priority = {
-                'id' : vnfr['id'],
-                'name' : vnfr['short_name'],
-                'member_vnf_index' : vnfr['member_vnf_index_ref'],
-            }
-
-            if 'config_delay' in vnf_config['config_attributes']:
-                config_priority['configuration_delay'] = vnf_config['config_attributes']['config_delay']
-                vnf_cfg['config_delay'] = config_priority['configuration_delay']
-
-            configuration_options = {}
             self._log.debug("config method=%s", method)
-            config_priority['configuration_type'] = method
             vnf_cfg['config_method'] = method
 
             # Set config agent based on method
             self._config_agent_mgr.set_config_agent(
-                nsr_obj.agent_nsr, vnf_cfg['agent_vnfr'], method)
-
-            cfg_opt_list = [
-                'port', 'target', 'script_type', 'ip_address', 'user', 'secret',
-            ]
-            for cfg_opt in cfg_opt_list:
-                if cfg_opt in vnf_config[method]:
-                    configuration_options[cfg_opt] = vnf_config[method][cfg_opt]
-                    vnf_cfg[cfg_opt] = configuration_options[cfg_opt]
-
-            cfg_opt_list = ['mgmt_ip_address', 'username', 'password']
-            for cfg_opt in cfg_opt_list:
-                if cfg_opt in vnf_config['config_access']:
-                    configuration_options[cfg_opt] = vnf_config['config_access'][cfg_opt]
-                    vnf_cfg[cfg_opt] = configuration_options[cfg_opt]
-
-            # Add to the cp_dict
-            vnf_cp_dict = nsr_obj._cp_dict[vnfr['member_vnf_index_ref']]
-            vnf_cp_dict['rw_mgmt_ip'] = vnf_cfg['mgmt_ip_address']
-            vnf_cp_dict['rw_username'] = vnf_cfg['username']
-            vnf_cp_dict['rw_password'] = vnf_cfg['password']
-            
+                  nsr_obj.agent_nsr, vnf_cfg['agent_vnfr'], method)
+        else:
+            self._log.info("VNF:(%s) is not to be configured by Configuration Manager!",
+                             log_this_vnf(vnfr['vnf_cfg']))
+            yield from nsr_obj.update_vnf_cm_state(vnfr, conmanY.RecordState.READY_NO_CFG)
 
-            # TBD - see if we can neatly include the config in "config_attributes" file, no need though
-            #config_priority['config_template'] = vnf_config['config_template']
-            # Create config file
-            vnf_cfg['juju_script'] = os.path.join(self._parent.cfg_dir, 'juju_if.py')
+        # Update the cm-state
+        nsr_obj.populate_cm_state_from_vnf_cfg()
 
-            if 'config_template' in vnf_config:
-                vnf_cfg['cfg_template'] = '{}_{}_template.cfg'.format(nsr_obj.cfg_path_prefix, config_priority['configuration_type'])
-                vnf_cfg['cfg_file'] = '{}.{}'.format(nsr_obj.cfg_path_prefix, get_cfg_file_extension(method, configuration_options))
-                vnf_cfg['xlate_script'] = os.path.join(self._parent.cfg_dir, 'xlate_cfg.py')
-                try:
-                    # Now write this template into file
-                    with open(vnf_cfg['cfg_template'], "w") as cf:
-                        cf.write(vnf_config['config_template'])
-                except Exception as e:
-                    self._log.error("Processing NSD, failed to generate configuration template : %s (Error : %s)",
-                                    vnf_config['config_template'], str(e))
-                    raise
+    @asyncio.coroutine
+    def update_config_primitives(self, nsr_obj):
 
-            self._log.debug("VNF endpoint so far: %s", vnf_cfg)
+         # Process all config-primitives in the member VNFs
+        for vnfr in nsr_obj.vnfrs:
+            vnfd = vnfr['vnf_cfg']['agent_vnfr'].vnfd
 
-            # Populate filled up dictionary
-            config_priority['configuration_options'] = configuration_options
-            nsr_obj.nsr_cfg_config_attributes_dict[cfg_priority_order].append(config_priority)
-            nsr_obj.num_vnfs_to_cfg += 1
-            nsr_obj._vnfr_dict[vnf_cfg['vnf_unique_name']] = vnfr
-            nsr_obj._vnfr_dict[vnfr['id']] = vnfr
+            try:
+                prims = vnfd.vnf_configuration.config_primitive
+                if not prims:
+                    self._log.debug("VNFR {} with VNFD {} has no config primitives defined".
+                                    format(vnfr['name'], vnfd.name))
+                    return
+            except AttributeError as e:
+                self._log.error("No config primitives found on VNFR {} ({})".
+                                format(vnfr['name'], vnfd.name))
+                continue
+
+            cm_state = nsr_obj.find_vnfr_cm_state(vnfr['id'])
+            srcs = cm_state['config_parameter']['config_parameter_source']
+            reqs = cm_state['config_parameter']['config_parameter_request']
+
+            vnf_configuration = vnfd.vnf_configuration.as_dict()
+            vnf_configuration['config_primitive'] = []
+            
+            for prim in prims:
+                confp = prim.as_dict()
+                if 'parameter' not in confp:
+                    continue
 
-            self._log.debug("VNF:(%s) config_attributes = %s",
-                            log_this_vnf(vnfr['vnf_cfg']),
-                            nsr_obj.nsr_cfg_config_attributes_dict)
+                for param in confp['parameter']:
+                    # First check the param in capabilities
+                    found = False
+                    for src in srcs:
+                        for p in src['parameter']:
+                            if (p['config_primitive_ref'] == confp['name']) \
+                               and (p['parameter_ref'] == param['name']):
+                                param['default_value'] = src['value']
+                                found = True
+                                break
+                        if found:
+                            break
+
+                    if not found:
+                        for req in reqs:
+                            for p in req['parameter']:
+                                if (p['config_primitive_ref'] == confp['name']) \
+                                   and (p['parameter_ref'] == param['name']):
+                                    param['default_value'] = req['value']
+                                    found = True
+                                    break
+                            if found:
+                                break
+
+                self._log.debug("Config primitive: {}".format(confp))
+                vnf_configuration['config_primitive'].append(confp)
+
+            cm_state['vnf_configuration'] = vnf_configuration
+
+    @asyncio.coroutine
+    def get_resolved_xpath(self, xpath, name, vnf_name, xpath_prefix):
+        # For now, use DTS to resolve the path
+        # TODO (pjoseph): Add better xpath support
+
+        dts_path = xpath
+        if xpath.startswith('../'):
+            prefix = xpath_prefix
+            xp = xpath
+            while xp.startswith('../'):
+                idx = prefix.rfind('/')
+                if idx == -1:
+                    raise ValueError("VNF {}, Did not find the xpath specified: {}".
+                                     format(vnf_name, xpath))
+                prefix = prefix[:idx]
+                xp = xp[3:]
+
+            dts_path = prefix + '/' + xp
+
+        elif xpath.startswith('/'):
+            dts_path = 'C,' + xpath
+        elif xpath.startswith('C,/') or xpath.startswith('D,/'):
+            dts_path = xpath
         else:
-            self._log.info("VNF:(%s) is not to be configured by Configuration Manager!",
-                           log_this_vnf(vnfr['vnf_cfg']))
-            yield from nsr_obj.update_vnf_cm_state(vnfr, conmanY.RecordState.READY_NO_CFG)
+            self._log.error("Invalid xpath {} for source {} in VNF {}".
+                            format(xpath, name, vnf_name))
+            raise ValueError("Descriptor xpath {} in source {} for VNF {} "
+                             "is invalid".
+                             format(xpath, name, vnf_name))
 
-        # Update the cm-state
-        nsr_obj.populate_vm_state_from_vnf_cfg()
+        dts_path = self._project.add_project(dts_path)
+        return dts_path
 
     @asyncio.coroutine
-    def config_NSR(self, id):
+    def resolve_xpath(self, xpath, name, vnfd):
+        xpath_prefix = "C,/project-vnfd:vnfd-catalog/vnfd[id={}]/config-parameter" \
+                "/config-parameter-source[name={}]" \
+                "/descriptor".format(quoted_key(vnfd.id), quoted_key(name))
+
+        dts_path = yield from self.get_resolved_xpath(xpath, name,
+                                                      vnfd.name, xpath_prefix)
+        idx = dts_path.rfind('/')
+        if idx == -1:
+            raise ValueError("VNFD {}, descriptor xpath {} should point to " \
+                             "an attribute".format(vnfd.name, xpath))
+
+        attr = dts_path[idx+1:]
+        dts_path = dts_path[:idx]
+        self._log.debug("DTS path: {}, attribute: {}".format(dts_path, attr))
+
+        resp = yield from self.cmdts_obj.get_xpath(dts_path)
+        if resp is None:
+            raise ValueError("Xpath {} in capability {} for VNFD {} is not found".
+                             format(xpath, name, vnfd.name))
+        self._log.debug("DTS response: {}".format(resp.as_dict()))
 
-        def my_yaml_dump(config_attributes_dict, yf):
+        try:
+            val = getattr(resp, attr)
+        except AttributeError as e:
+            self._log.error("Did not find attribute : {}".format(attr))
+            try:
+                val = getattr(resp, attr.replace('-', '_'))
+            except AttributeError as e:
+                raise ValueError("Did not find attribute {} in XPath {} "
+                                 "for capability {} in VNF {}".
+                                 format(attr, dts_path, vnfd.name))
 
-            yaml_dict = dict(sorted(config_attributes_dict.items()))
-            yf.write(yaml.dump(yaml_dict, default_flow_style=False))
-        
-        nsr_dict = self._nsr_dict
-        self._log.info("Configure NSR, id = %s", id)
+        self._log.debug("XPath {}: {}".format(xpath, val))
+        return val
+
+    @asyncio.coroutine
+    def resolve_attribute(self, attribute, name, vnfd, vnfr):
+        idx = attribute.rfind(',')
+        if idx == -1:
+            raise ValueError ("Invalid attribute {} for capability {} in "
+                              "VNFD specified".
+                              format(attribute, name, vnfd.name))
+        xpath = attribute[:idx].strip()
+        attr = attribute[idx+1:].strip()
+        self._log.debug("Attribute {}, {}".format(xpath, attr))
+        if xpath.startswith('C,/'):
+            raise ValueError("Attribute {} for capability {} in VNFD cannot "
+                             "be a config".
+                             format(attribute, name, vnfd.name))
+
+        xpath_prefix = "D,/vnfr:vnfr-catalog/vnfr[id={}]/config_parameter" \
+                "/config-parameter-source[name={}]" \
+                "/attribute".format(quoted_key(vnfr['id']), quoted_key(name))
+        dts_path = yield from self.get_resolved_xpath(xpath, name,
+                                                      vnfr['name'],
+                                                      xpath_prefix)
+        self._log.debug("DTS query: {}".format(dts_path))
+
+        resp = yield from self.cmdts_obj.get_xpath(dts_path)
+        if resp is None:
+            raise ValueError("Attribute {} in request {} for VNFD {} is " \
+                             "not found".
+                             format(xpath, name, vnfd.name))
+        self._log.debug("DTS response: {}".format(resp.as_dict()))
 
-        #####################TBD###########################
-        # yield from self._config_agent_mgr.invoke_config_agent_plugins('notify_create_nsr', self.id, self._nsd)
-        # yield from self._config_agent_mgr.invoke_config_agent_plugins('notify_nsr_active', self.id, self._vnfrs)
-        
         try:
-            if id not in nsr_dict:
-                nsr_obj = ConfigManagerNSR(self._log, self._loop, self, id)
-                nsr_dict[id] = nsr_obj
-            else:
-                self._log.info("NSR(%s) is already initialized!", id)
-                nsr_obj = nsr_dict[id]
-        except Exception as e:
-            self._log.error("Failed creating NSR object for (%s) as (%s)", id, str(e))
-            raise
+            val = getattr(resp, attr)
+        except AttributeError as e:
+            self._log.debug("Did not find attribute {}".format(attr))
+            try:
+                val = getattr(resp, attr.replace('-', '_'))
+            except AttributeError as e:
+                raise ValueError("Did not find attribute {} in XPath {} "
+                                 "for source {} in VNF {}".
+                                 format(attr, dts_path, vnfd.name))
 
-        # Try to configure this NSR only if not already processed
-        if nsr_obj.cm_nsr['state'] != nsr_obj.state_to_string(conmanY.RecordState.INIT):
-            self._log.debug("NSR(%s) is already processed, state=%s",
-                            nsr_obj.nsr_name, nsr_obj.cm_nsr['state'])
-            yield from nsr_obj.publish_cm_state()
-            return True
+        self._log.debug("Attribute {}: {}".format(attribute, val))
+        return val
 
-        cmdts_obj = self.cmdts_obj
+    @asyncio.coroutine
+    def process_vnf_config_parameter(self, nsr_obj):
+        nsd = nsr_obj.agent_nsr.nsd
+
+        # Process all capabilities in all the member VNFs
+        for vnfr in nsr_obj.vnfrs:
+            vnfd = vnfr['vnf_cfg']['agent_vnfr'].vnfd
+
+            try:
+                cparam = vnfd.config_parameter
+            except AttributeError as e:
+                self._log.debug("VNFR {} does not have VNF config parameter".
+                                format(vnfr.name))
+                continue
+
+            srcs = []
+            try:
+                srcs = cparam.config_parameter_source
+            except AttributeError as e:
+                self._log.debug("VNFR {} has no source defined".
+                                format(vnfr.name))
+
+            # Get the cm state dict for this vnfr
+            cm_state = nsr_obj.find_vnfr_cm_state(vnfr['id'])
+
+            cm_srcs = []
+            for src in srcs:
+                self._log.debug("VNFR {}: source {}".
+                                format(vnfr['name'], src.as_dict()))
+
+                param_refs = []
+                for p in src.parameter:
+                    param_refs.append({
+                        'config_primitive_ref': p.config_primitive_name_ref,
+                        'parameter_ref': p.config_primitive_parameter_ref
+                    })
+
+                try:
+                    val = src.value
+                    self._log.debug("Got value {}".format(val))
+                    if val:
+                        cm_srcs.append({'name': src.name,
+                                        'value': str(val),
+                                        'parameter': param_refs})
+                        continue
+                except AttributeError as e:
+                    pass
+
+                try:
+                    xpath = src.descriptor
+                    # resolve xpath
+                    if xpath:
+                        val = yield from self.resolve_xpath(xpath, src.name, vnfd)
+                        self._log.debug("Got xpath value: {}".format(val))
+                        cm_srcs.append({'name': src.name,
+                                        'value': str(val),
+                                        'parameter': param_refs})
+                        continue
+                except AttributeError as e:
+                    pass
+
+                try:
+                    attribute = src.attribute
+                    # resolve attribute
+                    if attribute:
+                        val = yield from self.resolve_attribute(attribute,
+                                                                src.name,
+                                                                vnfd, vnfr)
+                        self._log.debug("Got attribute value: {}".format(val))
+                        cm_srcs.append({'name': src.name,
+                                        'value': str(val),
+                                        'parameter': param_refs})
+                        continue
+                except AttributeError as e:
+                    pass
+
+                try:
+                    prim = src.primitive_ref
+                    if prim:
+                        raise NotImplementedError("{}: VNF config parameter {}"
+                                                  "source support for config"
+                                                  "primitive not yet supported".
+                                                  format(vnfr.name, prim))
+                except AttributeError as e:
+                    pass
+
+            self._log.debug("VNF config parameter sources: {}".format(cm_srcs))
+            cm_state['config_parameter']['config_parameter_source'] = cm_srcs
+
+            try:
+                reqs = cparam.config_parameter_request
+            except AttributeError as e:
+                self._log.debug("VNFR {} has no requests defined".
+                                format(vnfr.name))
+                continue
+
+            cm_reqs = []
+            for req in reqs:
+                self._log.debug("VNFR{}: request {}".
+                                format(vnfr['name'], req.as_dict()))
+                param_refs = []
+                for p in req.parameter:
+                    param_refs.append({
+                        'config_primitive_ref': p.config_primitive_name_ref,
+                        'parameter_ref': p.config_primitive_parameter_ref
+                    })
+                cm_reqs.append({'name': req.name,
+                                'parameter': param_refs})
+
+            self._log.debug("VNF requests: {}".format(cm_reqs))
+            cm_state['config_parameter']['config_parameter_request'] = cm_reqs
+
+        # Publish all config parameter for the VNFRs
+        # yield from nsr_obj.publish_cm_state()
+
+        cparam_map = []
         try:
-            # Fetch NSR
-            nsr = yield from cmdts_obj.get_nsr(id)
-            self._log.debug("Full NSR : %s", nsr)
-            if nsr['operational_status'] != "running":
-                self._log.info("NSR(%s) is not ready yet!", nsr['nsd_name_ref'])
-                return False
-            self._nsr = nsr
-
-            # Create Agent NSR class
-            nsr_config = yield from cmdts_obj.get_nsr_config(id)
-            self._log.debug("NSR {} config: {}".format(id, nsr_config))
-            nsr_obj.agent_nsr = riftcm_config_plugin.RiftCMnsr(nsr, nsr_config)
+            cparam_map = nsd.config_parameter_map
+        except AttributeError as e:
+            self._log.warning("No config parameter map specified for nsr: {}".
+                            format(nsr_obj.nsr_name))
+
+        for cp in cparam_map:
+            src_vnfr = nsr_obj.agent_nsr.get_member_vnfr(
+                cp.config_parameter_source.member_vnf_index_ref)
+            cm_state = nsr_obj.find_vnfr_cm_state(src_vnfr.id)
+            if cm_state is None:
+                raise ValueError("Config parameter sources are not defined "
+                        "for VNF member {} ({})".
+                        format(cp.config_parameter_source.member_vnf_index_ref,
+                               src_vnfr.name))
+            srcs = cm_state['config_parameter']['config_parameter_source']
+
+            src_attr = cp.config_parameter_source.config_parameter_source_ref
+            val = None
+            for src in srcs:
+                if src['name'] == src_attr:
+                    val = src['value']
+                    break
+
+            req_vnfr = nsr_obj.agent_nsr.get_member_vnfr(
+                cp.config_parameter_request.member_vnf_index_ref)
+            req_attr = cp.config_parameter_request.config_parameter_request_ref
+            cm_state = nsr_obj.find_vnfr_cm_state(req_vnfr.id)
+            try:
+                cm_reqs = cm_state['config_parameter']['config_parameter_request']
+            except KeyError as e:
+                raise ValueError("VNFR index {} ({}) has no requests defined".
+                        format(cp.config_parameter_reequest.member_vnf_index_ref,
+                               req_vnfr['name']))
+
+            for i, item in enumerate(cm_reqs):
+                if item['name'] == req_attr:
+                    item['value'] = str(val)
+                    cm_reqs[i] = item
+                    self._log.debug("Request in VNFR {}: {}".
+                                    format(req_vnfr.name, item))
+                    break
+
+        yield from self.update_config_primitives(nsr_obj)
+
+        # TODO: Confd crashing with the config-parameter publish
+        # So removing config-parameter and publishing cm-state
+        for vnfr in nsr_obj.vnfrs:
+            # Get the cm state dict for this vnfr
+            cm_state = nsr_obj.find_vnfr_cm_state(vnfr['id'])
+            del cm_state['config_parameter']['config_parameter_source']
+            del cm_state['config_parameter']['config_parameter_request']
+
+        # Publish resolved dependencies for the VNFRs
+        yield from nsr_obj.publish_cm_state()
 
+    @asyncio.coroutine
+    def config_NSR(self, id, event):
+
+        cmdts_obj = self.cmdts_obj
+        if event == 'running':
+            self._log.info("Configure NSR running, id = %s", id)
             try:
-                yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.RECEIVED)
-
-                # Parse NSR
-                if nsr is not None:
-                    nsr_obj.set_nsr_name(nsr['nsd_name_ref'])
-                    nsr_dir = os.path.join(self._parent.cfg_dir, nsr_obj.nsr_name)
-                    self._log.info("Checking NS config directory: %s", nsr_dir)
-                    if not os.path.isdir(nsr_dir):
-                        os.makedirs(nsr_dir)
-                        # self._log.critical("NS %s is not to be configured by Service Orchestrator!", nsr_obj.nsr_name)
-                        # yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.READY_NO_CFG)
-                        # return
-
-                    nsr_obj.set_config_dir(self)
-                    
+                nsr_obj = None
+                try:
+                    if id not in self._nsr_dict:
+                        nsr_obj = ConfigManagerNSR(self._log, self._loop, self, self._project, id)
+                        self._nsr_dict[id] = nsr_obj
+                    else:
+                        self._log.info("NSR(%s) is already initialized!", id)
+                        nsr_obj = self._nsr_dict[id]
+
+                except Exception as e:
+                    self._log.error("Failed creating NSR object for (%s) as (%s)", id, str(e))
+                    raise e
+
+                # Try to configure this NSR only if not already processed
+                if nsr_obj.cm_nsr['state'] != nsr_obj.state_to_string(conmanY.RecordState.INIT):
+                    self._log.debug("NSR(%s) is already processed, state=%s",
+                                    nsr_obj.nsr_name, nsr_obj.cm_nsr['state'])
+                    # Publish again in case NSM restarted
+                    yield from nsr_obj.publish_cm_state()
+                    return True
+
+                # Fetch NSR
+                nsr = yield from cmdts_obj.get_nsr(id)
+                self._log.debug("Full NSR : %s", nsr)
+                if nsr['operational_status'] != "running":
+                    self._log.info("NSR(%s) is not ready yet!", nsr['nsd_name_ref'])
+                    return False
+                self._nsr = nsr
+
+                # Create Agent NSR class
+                nsr_config = yield from cmdts_obj.get_nsr_config(id)
+                self._log.debug("NSR {} config: {}".format(id, nsr_config))
+
+                if nsr_config is None:
+                    # The NST Terminate has been initiated before the configuration. Hence 
+                    # not proceeding with config.
+                    self._log.warning("NSR - %s is deleted before Configuration. Not proceeding with configuration.", id)
+                    return True
+
+                nsr_obj.agent_nsr = riftcm_config_plugin.RiftCMnsr(nsr, nsr_config,
+                                                                   self._project)
+
+                unique_cfg_vnfr_list = list()
+                unique_agent_vnfr_list = list()
+                try:
+                    yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.RECEIVED)
+
+                    nsr_obj.set_nsr_name(nsr['name_ref'])
                     for const_vnfr in nsr['constituent_vnfr_ref']:
                         self._log.debug("Fetching VNFR (%s)", const_vnfr['vnfr_id'])
                         vnfr_msg = yield from cmdts_obj.get_vnfr(const_vnfr['vnfr_id'])
                         if vnfr_msg:
                             vnfr = vnfr_msg.as_dict()
-                            self._log.info("create VNF:{}/{}".format(nsr_obj.nsr_name, vnfr['short_name']))
+                            self._log.info("create VNF:{}/{} operational status {}".format(nsr_obj.nsr_name, vnfr['name'], vnfr['operational_status']))
                             agent_vnfr = yield from nsr_obj.add_vnfr(vnfr, vnfr_msg)
+                            method = self.get_config_method(vnfr['vnf_configuration'])
+                            if method is not None:
+                                unique_cfg_vnfr_list.append(vnfr)
+                                unique_agent_vnfr_list.append(agent_vnfr)
 
-                            # Preserve order, self.process_nsd_vnf_configuration()
-                            # sets up the config agent based on the method
+                            #  Process VNF Cfg 
+                            # Set up the config agent based on the method
                             yield from self.process_nsd_vnf_configuration(nsr_obj, vnfr)
-                            yield from self._config_agent_mgr.invoke_config_agent_plugins(
-                                'notify_create_vnfr',
-                                nsr_obj.agent_nsr,
-                                agent_vnfr)
+                        else:
+                            self._log.warning("NSR %s, VNFR not found yet (%s)", nsr_obj.nsr_name, const_vnfr['vnfr_id'])
 
-                        #####################TBD###########################
-                        # self._log.debug("VNF active. Apply initial config for vnfr {}".format(vnfr.name))
-                        # yield from self._config_agent_mgr.invoke_config_agent_plugins('apply_initial_config',
-                        #                                             vnfr.id, vnfr)
-                        # yield from self._config_agent_mgr.invoke_config_agent_plugins('notify_terminate_vnf', self.id, vnfr)
-
-            except Exception as e:
-                self._log.error("Failed processing NSR (%s) as (%s)", nsr_obj.nsr_name, str(e))
-                self._log.exception(e)
-                yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.CFG_PROCESS_FAILED)
-                raise
+                    # Process VNF config parameter
+                    yield from self.process_vnf_config_parameter(nsr_obj)
 
-            try:
-                # Generate config_config_attributes.yaml (For debug reference)
-                with open(nsr_obj.config_attributes_file, "w") as yf:
-                    my_yaml_dump(nsr_obj.nsr_cfg_config_attributes_dict, yf)
-            except Exception as e:
-                self._log.error("NS:(%s) failed to write config attributes file as (%s)", nsr_obj.nsr_name, str(e))
-
-            try:
-                # Generate nsr_xlate_dict.yaml (For debug reference)
-                with open(nsr_obj.xlate_dict_file, "w") as yf:
-                    yf.write(yaml.dump(nsr_obj._cp_dict, default_flow_style=False))
-            except Exception as e:
-                self._log.error("NS:(%s) failed to write nsr xlate tags file as (%s)", nsr_obj.nsr_name, str(e))
+                    # Invoke the config agent plugin
+                    for agent_vnfr in unique_agent_vnfr_list:
+                        yield from self._config_agent_mgr.invoke_config_agent_plugins(
+                                'notify_create_vnfr',
+                                 nsr_obj.agent_nsr,
+                                 agent_vnfr)
 
-            self._log.debug("Starting to configure each VNF")
+                except Exception as e:
+                    self._log.error("Failed processing NSR (%s) as (%s)", nsr_obj.nsr_name, str(e))
+                    self._log.exception(e)
+                    yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.CFG_PROCESS_FAILED)
+                    raise e
 
-            # Check if this NS has input parametrs
-            self._log.info("Checking NS configuration order: %s", nsr_obj.config_attributes_file)
+                self._log.debug("Starting to configure each VNF")
 
-            if os.path.exists(nsr_obj.config_attributes_file):
-                # Apply configuration is specified order
                 try:
-                    # Go in loop to configure by specified order
-                    self._log.info("Using Dynamic configuration input parametrs for NS: %s", nsr_obj.nsr_name)
-
-                    # cfg_delay = nsr_obj.nsr_cfg_config_attributes_dict['configuration_delay']
-                    # if cfg_delay:
-                    #     self._log.info("Applying configuration delay for NS (%s) ; %d seconds",
-                    #                    nsr_obj.nsr_name, cfg_delay)
-                    #     yield from asyncio.sleep(cfg_delay, loop=self._loop)
-
-                    for config_attributes_dict in nsr_obj.nsr_cfg_config_attributes_dict.values():
-                        # Iterate through each priority level
-                        for vnf_config_attributes_dict in config_attributes_dict:
-                            # Iterate through each vnfr at this priority level
-                                
-                            # Make up vnf_unique_name with vnfd name and member index
-                            #vnfr_name = "{}.{}".format(nsr_obj.nsr_name, vnf_config_attributes_dict['name'])
-                            vnf_unique_name = get_vnf_unique_name(
-                                nsr_obj.nsr_name,
-                                vnf_config_attributes_dict['name'],
-                                str(vnf_config_attributes_dict['member_vnf_index']),
-                            )
-                            self._log.info("NS (%s) : VNF (%s) - Processing configuration attributes",
-                                           nsr_obj.nsr_name, vnf_unique_name)
+                    for cfg_vnfr in unique_cfg_vnfr_list:
+                       # Apply configuration 
+                        vnf_unique_name = get_vnf_unique_name(
+                            nsr_obj.nsr_name,
+                            cfg_vnfr['name'],
+                            str(cfg_vnfr['member_vnf_index_ref']),
+                        )
 
-                            # Find vnfr for this vnf_unique_name
-                            if vnf_unique_name not in nsr_obj._vnfr_dict:
-                                self._log.error("NS (%s) - Can not find VNF to be configured: %s", nsr_obj.nsr_name, vnf_unique_name)
-                            else:
-                                # Save this unique VNF's config input parameters
-                                nsr_obj.vnf_config_attributes_dict[vnf_unique_name] = vnf_config_attributes_dict
-                                nsr_obj.ConfigVNF(nsr_obj._vnfr_dict[vnf_unique_name])
+                        # Find vnfr for this vnf_unique_name
+                        if vnf_unique_name not in nsr_obj._vnfr_dict:
+                            self._log.error("NS (%s) - Can not find VNF to be configured: %s", nsr_obj.nsr_name, vnf_unique_name)
+                        else:
+                            # Save this unique VNF's config input parameters
+                            nsr_obj.ConfigVNF(nsr_obj._vnfr_dict[vnf_unique_name])
 
                     # Now add the entire NS to the pending config list.
-                    self._log.info("Scheduling NSR:{} configuration".format(nsr_obj.nsr_name))
-                    self._parent.add_to_pending(nsr_obj)
+                    self._log.info("Scheduling NSR:{} configuration ".format(nsr_obj.nsr_name))
+                    self._parent.add_to_pending(nsr_obj, unique_cfg_vnfr_list)
                     self._parent.add_nsr_obj(nsr_obj)
 
                 except Exception as e:
                     self._log.error("Failed processing input parameters for NS (%s) as %s", nsr_obj.nsr_name, str(e))
+                    self._log.exception(e)
                     raise
-            else:
-                self._log.error("No configuration input parameters for NSR (%s)", nsr_obj.nsr_name)
 
-        except Exception as e:
-            self._log.error("Failed to configure NS (%s) as (%s)", nsr_obj.nsr_name, str(e))
-            yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.CFG_PROCESS_FAILED)
-            raise
+            except Exception as e:
+                self._log.exception(e)
+                if nsr_obj:
+                    self._log.error("Failed to configure NS (%s) as (%s)", nsr_obj.nsr_name, str(e))
+                    yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.CFG_PROCESS_FAILED)
+                raise e
+
+        elif event == 'terminate':
+            self._log.info("Configure NSR terminate, id = %s", id)
+            nsr_obj = self._parent.get_nsr_obj(id)
+            if nsr_obj is None:
+                # Can be none if the terminate is called again due to DTS query
+                return True
+
+            try:
+                yield from self.process_ns_terminate_config(nsr_obj, self._project.name)
+            except Exception as e:
+                self._log.warn("Terminate config failed for NSR {}: {}".
+                               format(id, e))
+                self._log.exception(e)
+
+            try:
+                yield from nsr_obj.update_ns_cm_state(conmanY.RecordState.TERMINATE)
+                yield from self.terminate_NSR(id)
+            except Exception as e:
+                self._log.error("Terminate failed for NSR {}: {}".
+                               format(id, e))
+                self._log.exception(e)
 
         return True
 
     @asyncio.coroutine
     def terminate_NSR(self, id):
-        nsr_dict = self._nsr_dict
-        if id not in nsr_dict:
+        if id not in self._nsr_dict:
             self._log.error("NSR(%s) does not exist!", id)
             return
         else:
+            nsr_obj = self._nsr_dict[id]
+
             # Remove this NSR if we have it on pending task list
             for task in self.pending_tasks:
                 if task['nsrid'] == id:
                     self.del_from_pending_tasks(task)
 
-            # Remove this object from global list
-            nsr_obj = nsr_dict.pop(id, None)
-
-            # Remove this NS cm-state from global status list
-            self.cm_state['cm_nsr'].remove(nsr_obj.cm_nsr)
-
-            # Also remove any scheduled configuration event
+            # Remove any scheduled configuration event
             for nsr_obj_p in self._parent.pending_cfg:
                 if nsr_obj_p == nsr_obj:
                     assert id == nsr_obj_p._nsr_id
-                    #self._parent.pending_cfg.remove(nsr_obj_p)
-                    # Mark this as being deleted so we do not try to configure it if we are in cfg_delay (will wake up and continue to process otherwise)
+                    # Mark this as being deleted so we do not try to reconfigure it
+                    # if we are in cfg_delay (will wake up and continue to process otherwise)
                     nsr_obj_p.being_deleted = True
                     self._log.info("Removed scheduled configuration for NSR(%s)", nsr_obj.nsr_name)
 
-            self._parent.remove_nsr_obj(id)
-
             # Call Config Agent to clean up for each VNF
             for agent_vnfr in nsr_obj.agent_nsr.vnfrs:
                 yield from self._config_agent_mgr.invoke_config_agent_plugins(
@@ -656,13 +876,38 @@ class ConfigManagerConfig(object):
                     nsr_obj.agent_nsr,
                     agent_vnfr)
 
-            # publish delete cm-state (cm-nsr)
-            yield from nsr_obj.delete_cm_nsr()
+            self._log.info("NSR(%s/%s) is terminated", nsr_obj.nsr_name, id)
 
-            #####################TBD###########################
-            # yield from self._config_agent_mgr.invoke_config_agent_plugins('notify_terminate_ns', self.id)
+    @asyncio.coroutine
+    def delete_NSR(self, id):
+        if id not in self._nsr_dict:
+            self._log.debug("NSR(%s) does not exist!", id)
+            return
+        else:
+            # Remove this NSR if we have it on pending task list
+            for task in self.pending_tasks:
+                if task['nsrid'] == id:
+                    self.del_from_pending_tasks(task)
+
+        # Remove this object from global list
+        nsr_obj = self._nsr_dict.pop(id, None)
+
+        # Remove this NS cm-state from global status list
+        self.cm_state['cm_nsr'].remove(nsr_obj.cm_nsr)
+
+        self._parent.remove_nsr_obj(id)
+
+        # publish delete cm-state (cm-nsr)
+        yield from nsr_obj.delete_cm_nsr()
+
+        # Deleting any config jobs for NSR.
+        job_manager = self.riftcm_rpc_handler.job_manager.handler
+        job_manager._terminate_nsr(id)        
+
+        #####################TBD###########################
+        # yield from self._config_agent_mgr.invoke_config_agent_plugins('notify_terminate_ns', self.id)
 
-            self._log.info("NSR(%s/%s) is deleted", nsr_obj.nsr_name, id)
+        self._log.info("NSR(%s/%s) is deleted", nsr_obj.nsr_name, id)
 
     @asyncio.coroutine
     def process_initial_config(self, nsr_obj, conf, script, vnfr_name=None):
@@ -678,10 +923,6 @@ class ConfigManagerConfig(object):
             if vnfr_name:
                 inp['vnfr_name'] = vnfr_name
 
-            # TODO (pjoseph): Add config agents, we need to identify which all
-            # config agents are required from this NS and provide only those
-            inp['config-agent'] = {}
-
             # Add parameters for initial config
             inp['parameter'] = {}
             for parameter in parameters:
@@ -696,6 +937,20 @@ class ConfigManagerConfig(object):
                                        format(nsr_obj.nsr_name, parameter, e))
 
 
+            # Add config agents specific to each VNFR
+            inp['config-agent'] = {}
+            for vnfr in nsr_obj.agent_nsr.vnfrs:
+                # Get the config agent for the VNFR
+                # If vnfr name is specified, add only CA specific to that
+                if (vnfr_name is None) or \
+                   (vnfr_name == vnfr.name):
+                    agent = self._config_agent_mgr.get_vnfr_config_agent(vnfr.vnfr_msg)
+                    if agent:
+                        if agent.agent_type != riftcm_config_plugin.DEFAULT_CAP_TYPE:
+                            inp['config-agent'][vnfr.member_vnf_index] = agent.agent_data
+                            inp['config-agent'][vnfr.member_vnf_index] \
+                                ['service-name'] = agent.get_service_name(vnfr.id)
+
             # Add vnfrs specific data
             inp['vnfr'] = {}
             for vnfr in nsr_obj.vnfrs:
@@ -704,6 +959,7 @@ class ConfigManagerConfig(object):
                 v['name'] = vnfr['name']
                 v['mgmt_ip_address'] = vnfr['vnf_cfg']['mgmt_ip_address']
                 v['mgmt_port'] = vnfr['vnf_cfg']['port']
+                v['datacenter'] = vnfr['datacenter']
 
                 if 'dashboard_url' in vnfr:
                     v['dashboard_url'] = vnfr['dashboard_url']
@@ -711,23 +967,27 @@ class ConfigManagerConfig(object):
                 if 'connection_point' in vnfr:
                     v['connection_point'] = []
                     for cp in vnfr['connection_point']:
-                        v['connection_point'].append(
-                            {
-                                'name': cp['name'],
-                                'ip_address': cp['ip_address'],
-                            }
-                        )
+                        cp_info = dict(name=cp['name'],
+                                       ip_address=cp['ip_address'],
+                                       mac_address=cp.get('mac_address', None),
+                                       connection_point_id=cp.get('connection_point_id',None))
+                        
+                        if 'virtual_cps' in cp:
+                            cp_info['virtual_cps'] = [ {k:v for k,v in vcp.items()
+                                                        if k in ['ip_address', 'mac_address']}
+                                                       for vcp in cp['virtual_cps'] ]
+                        v['connection_point'].append(cp_info)
 
-                v['vdur'] = []
-                vdu_data = [(vdu['name'], vdu['management_ip'], vdu['vm_management_ip'], vdu['id'])
-                        for vdu in vnfr['vdur']]
-
-                for data in vdu_data:
-                    data = dict(zip(['name', 'management_ip', 'vm_management_ip', 'id'] , data))
-                    v['vdur'].append(data)
+                
+                if 'vdur' in vnfr:
+                    vdu_data = [(vdu.get('name',None), vdu.get('management_ip',None), vdu.get('vm_management_ip',None), vdu.get('id',None))
+                                for vdu in vnfr['vdur']]
+    
+                    v['vdur'] = [ dict(zip(['name', 'management_ip', 'vm_management_ip', 'id', 'vdu_id_ref'] , data)) for data in vdu_data ]
 
                 inp['vnfr'][vnfr['member_vnf_index_ref']] = v
 
+
             self._log.debug("Input data for {}: {}".
                             format((vnfr_name if vnfr_name else nsr_obj.nsr_name),
                                    inp))
@@ -759,109 +1019,134 @@ class ConfigManagerConfig(object):
         self._log.debug("Running the CMD: {}".format(cmd))
 
         process = yield from asyncio.create_subprocess_shell(cmd,
-                                                             loop=self._loop)
-        yield from process.wait()
-
-        if process.returncode:
-            msg = "NSR/VNFR {} initial config using {} failed with {}". \
+                                                             loop=self._loop,
+                                                             stdout=subprocess.PIPE,
+                                                             stderr=subprocess.PIPE)
+        stdout, stderr = yield from process.communicate()
+        rc = yield from process.wait()
+
+        if rc:
+            msg = "NSR/VNFR {} initial config using {} failed with {}: {}". \
                   format(vnfr_name if vnfr_name else nsr_obj.nsr_name,
-                         script, process.returncode)
+                         script, rc, stderr)
             self._log.error(msg)
             raise InitialConfigError(msg)
-        else:
-            # os.remove(inp_file)
-            pass
 
-    def get_script_file(self, script_name, d_name, d_id, d_type):
-          # Get the full path to the script
-          script = ''
-          # If script name starts with /, assume it is full path
-          if script_name[0] == '/':
-              # The script has full path, use as is
-              script = script_name
-          else:
-              script = os.path.join(os.environ['RIFT_ARTIFACTS'],
-                                    'launchpad/packages',
-                                    d_type,
-                                    d_id,
-                                    d_name,
-                                    'scripts',
-                                    script_name)
-              self._log.debug("Checking for script at %s", script)
-              if not os.path.exists(script):
-                  self._log.debug("Did not find script %s", script)
-                  script = os.path.join(os.environ['RIFT_INSTALL'],
-                                        'usr/bin',
-                                        script_name)
-
-              # Seen cases in jenkins, where the script execution fails
-              # with permission denied. Setting the permission on script
-              # to make sure it has execute permission
-              perm = os.stat(script).st_mode
-              if not (perm  &  stat.S_IXUSR):
-                  self._log.warn("NSR/VNFR {} initial config script {} " \
-                                "without execute permission: {}".
-                                format(d_name, script, perm))
-                  os.chmod(script, perm | stat.S_IXUSR)
-              return script
+        try:
+            os.remove(inp_file)
+        except Exception as e:
+            self._log.error("Error removing input file {}: {}".
+                            format(inp_file, e))
+
+    def get_script_file(self, script_name, d_name, d_id, d_type, project=None):
+        # Get the full path to the script
+        script = os.path.join(os.getenv('RIFT_VAR_ROOT'),
+                                      'launchpad/packages',
+                                      d_type,
+                                      project if project else "",
+                                      d_id,
+                                      'scripts',
+                                      script_name) 
+
+        self._log.debug("Checking for script at %s", script)
+        if not os.path.exists(script):
+            err_msg = ("{} {}: Did not find script {} for config".
+                       format(d_type, d_name, script))
+            self._log.error(err_msg)
+            raise ScriptNotFoundError(err_msg)
+
+        # Seen cases in jenkins, where the script execution fails
+        # with permission denied. Setting the permission on script
+        # to make sure it has execute permission
+        perm = os.stat(script).st_mode
+        if not (perm  &  stat.S_IXUSR):
+            self._log.warning("NSR/VNFR {} script {} " \
+                                    "without execute permission: {}".
+                                    format(d_name, script, perm))
+            os.chmod(script, perm | stat.S_IXUSR)
+        return script
 
     @asyncio.coroutine
-    def process_ns_initial_config(self, nsr_obj):
-        '''Apply the initial-config-primitives specified in NSD'''
-
+    def process_ns_initial_config(self, nsr_obj, project=None):
+        '''Apply the initial-service-primitives specified in NSD'''
         nsr = yield from self.cmdts_obj.get_nsr(nsr_obj.nsr_id)
-        if 'initial_config_primitive' not in nsr:
+        self._log.debug("NS initial config: {}".format(nsr))
+        if 'initial_service_primitive' not in nsr:
             return
-
         if nsr is not None:
             nsd = yield from self.cmdts_obj.get_nsd(nsr_obj.nsr_id)
-            for conf in nsr['initial_config_primitive']:
+            for conf in nsr['initial_service_primitive']:
                 self._log.debug("NSR {} initial config: {}".
                                 format(nsr_obj.nsr_name, conf))
                 script = self.get_script_file(conf['user_defined_script'],
                                               nsd.name,
                                               nsd.id,
-                                              'nsd')
+                                              'nsd', 
+                                              project
+                                            )
 
                 yield from self.process_initial_config(nsr_obj, conf, script)
 
     @asyncio.coroutine
-    def process_vnf_initial_config(self, nsr_obj, vnfr):
+    def process_vnf_initial_config(self, nsr_obj, vnfr, project=None):
         '''Apply the initial-config-primitives specified in VNFD'''
-
         vnfr_name = vnfr.name
 
-        vnfd = yield from self.cmdts_obj.get_vnfd(vnfr.vnfd.id)
-        if vnfd is None:
-            msg = "VNFR {}, unable to get VNFD {}". \
-                  format(vnfr_name, vnfr.vnfd.id)
-            self._log.error(msg)
-            raise InitialConfigError(msg)
-
+        vnfd = vnfr.vnfd
         vnf_cfg = vnfd.vnf_configuration
 
         for conf in vnf_cfg.initial_config_primitive:
-                self._log.debug("VNFR {} initial config: {}".
-                                format(vnfr_name, conf))
+                self._log.debug("VNFR {} initial config: {} for vnfd id {}".
+                                format(vnfr_name, conf, vnfd.id))
 
                 if not conf.user_defined_script:
-                    self._log.debug("VNFR {} did not fine user defined script: {}".
+                    self._log.debug("VNFR {} did not find user defined script: {}".
                                     format(vnfr_name, conf))
                     continue
 
                 script = self.get_script_file(conf.user_defined_script,
-                                              vnfd.id,
                                               vnfd.name,
-                                              'vnfd')
+                                              vnfd.id,
+                                              'vnfd', 
+                                               project
+                                                )
 
                 yield from self.process_initial_config(nsr_obj,
                                                        conf.as_dict(),
                                                        script,
                                                        vnfr_name=vnfr_name)
 
+    @asyncio.coroutine
+    def process_ns_terminate_config(self, nsr_obj, project=None):
+        '''Apply the terminate-service-primitives specified in NSD'''
+
+        nsr = self._nsr
+        if 'terminate_service_primitive' not in nsr: 
+            return
+
+        if nsr is not None:
+            nsd = nsr_obj.agent_nsr.nsd
+            for conf in nsr['terminate_service_primitive']:
+                self._log.debug("NSR {} terminate service: {}". 
+                                format(nsr_obj.nsr_name, conf))
+                script = self.get_script_file(conf['user_defined_script'],
+                                              nsd.name,
+                                              nsd.id,
+                                              'nsd', 
+                                               project)
+
+                try:
+                    yield from self.process_initial_config(nsr_obj, conf, script)
+
+                except Exception as e:
+                    # Ignore any failures on terminate
+                    self._log.warning("NSR {} terminate config script {} failed: {}".
+                                      format(nsr_obj.nsr_name, script, e))
+                    break
+
 
 class ConfigManagerNSR(object):
-    def __init__(self, log, loop, parent, id):
+    def __init__(self, log, loop, parent, project, id):
         self._log = log
         self._loop = loop
         self._rwcal = None
@@ -869,6 +1154,7 @@ class ConfigManagerNSR(object):
         self._cp_dict = {}
         self._nsr_id = id
         self._parent = parent
+        self._project = project
         self._log.info("Instantiated NSR entry for id=%s", id)
         self.nsr_cfg_config_attributes_dict = {}
         self.vnf_config_attributes_dict = {}
@@ -897,10 +1183,9 @@ class ConfigManagerNSR(object):
     @property
     def nsr_opdata_xpath(self):
         ''' Returns full xpath for this NSR cm-state opdata '''
-        return(
-            "D,/rw-conman:cm-state" +
-            "/rw-conman:cm-nsr[rw-conman:id='{}']"
-        ).format(self._nsr_id)
+        return self._project.add_project((
+            "D,/rw-conman:cm-state/rw-conman:cm-nsr[rw-conman:id={}]"
+        ).format(quoted_key(self._nsr_id)))
 
     @property
     def vnfrs(self):
@@ -918,7 +1203,7 @@ class ConfigManagerNSR(object):
     def publish_cm_state(self):
         ''' This function publishes cm_state for this NSR '''
 
-        cm_state = conmanY.CmOpdata()
+        cm_state = conmanY.YangData_RwProject_Project_CmState()
         cm_state_nsr = cm_state.cm_nsr.add()
         cm_state_nsr.from_dict(self.cm_nsr)
         #with self._dts.transaction() as xact:
@@ -939,54 +1224,6 @@ class ConfigManagerNSR(object):
         self.nsr_name = name
         self.cm_nsr['name'] = name
 
-    def set_config_dir(self, caller):
-        self.this_nsr_dir = os.path.join(
-            caller._parent.cfg_dir, self.nsr_name, caller._nsr['name_ref'])
-        if not os.path.exists(self.this_nsr_dir):
-            os.makedirs(self.this_nsr_dir)
-            self._log.debug("NSR:(%s), Created configuration directory(%s)",
-                            caller._nsr['name_ref'], self.this_nsr_dir)
-        self.config_attributes_file = os.path.join(self.this_nsr_dir, "configuration_config_attributes.yml")
-        self.xlate_dict_file = os.path.join(self.this_nsr_dir, "nsr_xlate_dict.yml")
-        
-    def xlate_conf(self, vnfr, vnf_cfg):
-
-        # If configuration type is not already set, try to read from attributes
-        if vnf_cfg['interface_type'] is None:
-            # Prepare unique name for this VNF
-            vnf_unique_name = get_vnf_unique_name(
-                    vnf_cfg['nsr_name'],
-                    vnfr['short_name'],
-                    vnfr['member_vnf_index_ref'],
-                    )
-
-            # Find this particular (unique) VNF's config attributes
-            if (vnf_unique_name in self.vnf_config_attributes_dict):
-                vnf_cfg_config_attributes_dict = self.vnf_config_attributes_dict[vnf_unique_name]
-                vnf_cfg['interface_type'] = vnf_cfg_config_attributes_dict['configuration_type']
-                if 'configuration_options' in vnf_cfg_config_attributes_dict:
-                    cfg_opts = vnf_cfg_config_attributes_dict['configuration_options']
-                    for key, value in cfg_opts.items():
-                        vnf_cfg[key] = value
-
-        cfg_path_prefix = '{}/{}/{}_{}'.format(
-                self._parent._parent.cfg_dir,
-                vnf_cfg['nsr_name'],
-                vnfr['short_name'],
-                vnfr['member_vnf_index_ref'],
-                )
-
-        vnf_cfg['cfg_template'] = '{}_{}_template.cfg'.format(cfg_path_prefix, vnf_cfg['interface_type'])
-        vnf_cfg['cfg_file'] = '{}.cfg'.format(cfg_path_prefix)
-        vnf_cfg['xlate_script'] = self._parent._parent.cfg_dir + '/xlate_cfg.py'
-
-        self._log.debug("VNF endpoint so far: %s", vnf_cfg)
-
-        self._log.info("Checking cfg_template %s", vnf_cfg['cfg_template'])
-        if os.path.exists(vnf_cfg['cfg_template']):
-            return True
-        return False
-
     def ConfigVNF(self, vnfr):
 
         vnf_cfg = vnfr['vnf_cfg']
@@ -995,7 +1232,7 @@ class ConfigManagerNSR(object):
         if (vnf_cm_state['state'] == self.state_to_string(conmanY.RecordState.READY_NO_CFG)
             or
             vnf_cm_state['state'] == self.state_to_string(conmanY.RecordState.READY)):
-            self._log.warning("NS/VNF (%s/%s) is already configured! Skipped.", self.nsr_name, vnfr['short_name'])
+            self._log.warning("NS/VNF (%s/%s) is already configured! Skipped.", self.nsr_name, vnfr['name'])
             return
 
         #UPdate VNF state
@@ -1007,35 +1244,13 @@ class ConfigManagerNSR(object):
             self._cp_dict['rw_mgmt_ip'] = vnf_cfg['mgmt_ip_address']
             self._cp_dict['rw_username'] = vnf_cfg['username']
             self._cp_dict['rw_password'] = vnf_cfg['password']
-            ############################################################
-            # TBD - Need to lookup above 3 for a given VNF, not global #
-            # Once we do that no need to dump below file again before  #
-            # each VNF configuration translation.                      #
-            # This will require all existing config templates to be    #
-            # changed for above three tags to include member index     #
-            ############################################################
-            try:
-                nsr_obj = vnf_cfg['nsr_obj']
-                # Generate config_config_attributes.yaml (For debug reference)
-                with open(nsr_obj.xlate_dict_file, "w") as yf:
-                    yf.write(yaml.dump(nsr_obj._cp_dict, default_flow_style=False))
-            except Exception as e:
-                self._log.error("NS:(%s) failed to write nsr xlate tags file as (%s)", nsr_obj.nsr_name, str(e))
-            
-            if 'cfg_template' in vnf_cfg:
-                script_cmd = 'python3 {} -i {} -o {} -x "{}"'.format(vnf_cfg['xlate_script'], vnf_cfg['cfg_template'], vnf_cfg['cfg_file'], self.xlate_dict_file)
-                self._log.debug("xlate script command (%s)", script_cmd)
-                #xlate_msg = subprocess.check_output(script_cmd).decode('utf-8')
-                xlate_msg = subprocess.check_output(script_cmd, shell=True).decode('utf-8')
-                self._log.info("xlate script output (%s)", xlate_msg)
         except Exception as e:
             vnf_cm_state['state'] = self.state_to_string(conmanY.RecordState.CFG_PROCESS_FAILED)
-            self._log.error("Failed to execute translation script for VNF: %s with (%s)", log_this_vnf(vnf_cfg), str(e))
+            self._log.error("Failed to set tags for VNF: %s with (%s)", log_this_vnf(vnf_cfg), str(e))
             return
 
         self._log.info("Applying config to VNF: %s = %s!", log_this_vnf(vnf_cfg), vnf_cfg)
         try:
-            #self.vnf_cfg_list.append(vnf_cfg)
             self._log.debug("Scheduled configuration!")
             vnf_cm_state['state'] = self.state_to_string(conmanY.RecordState.CFG_SCHED)
         except Exception as e:
@@ -1054,8 +1269,6 @@ class ConfigManagerNSR(object):
                     {
                         'cm_vnfr': [
                             {
-                                'cfg_location': 'location1',
-                                'cfg_type': 'script',
                                 'connection_point': [
                                     {'ip_address': '1.1.1.1', 'name': 'vnf1cp1'},
                                     {'ip_address': '1.1.1.2', 'name': 'vnf1cp2'}
@@ -1067,8 +1280,6 @@ class ConfigManagerNSR(object):
                                 'state': 'init'
                             },
                             {
-                                'cfg_location': 'location2',
-                                'cfg_type': 'netconf',
                                 'connection_point': [{'ip_address': '2.1.1.1', 'name': 'vnf2cp1'},
                                                      {'ip_address': '2.1.1.2', 'name': 'vnf2cp2'}],
                                 'id': 'vnfrid2',
@@ -1084,7 +1295,7 @@ class ConfigManagerNSR(object):
                 'states': 'Initialized, '
             })
 
-    def populate_vm_state_from_vnf_cfg(self):
+    def populate_cm_state_from_vnf_cfg(self):
         # Fill in each VNFR from this nsr object
         vnfr_list = self._vnfr_list
         for vnfr in vnfr_list:
@@ -1098,18 +1309,22 @@ class ConfigManagerNSR(object):
 
                 # Fill in VNF configuration details
                 vnf_cm_state['cfg_type'] = vnf_cfg['config_method']
-                vnf_cm_state['cfg_location'] = vnf_cfg['cfg_file']
 
                 # Fill in each connection-point for this VNF
                 if "connection_point" in vnfr:
                     cp_list = vnfr['connection_point']
                     for cp_item_dict in cp_list:
-                        vnf_cm_state['connection_point'].append(
-                            {
-                                'name' : cp_item_dict['name'],
-                                'ip_address' : cp_item_dict['ip_address'],
-                            }
-                        )
+                        try:
+                            vnf_cm_state['connection_point'].append(
+                                {
+                                    'name' : cp_item_dict['name'],
+                                    'ip_address' : cp_item_dict['ip_address'],
+                                    'connection_point_id' : cp_item_dict['connection_point_id'],
+                                }
+                            )
+                        except Exception:
+                            # Added to make mano_ut work
+                            pass
 
     def state_to_string(self, state):
         state_dict = {
@@ -1118,16 +1333,13 @@ class ConfigManagerNSR(object):
             conmanY.RecordState.CFG_PROCESS : "cfg_process",
             conmanY.RecordState.CFG_PROCESS_FAILED : "cfg_process_failed",
             conmanY.RecordState.CFG_SCHED : "cfg_sched",
-            conmanY.RecordState.CFG_DELAY : "cfg_delay",
             conmanY.RecordState.CONNECTING : "connecting",
             conmanY.RecordState.FAILED_CONNECTION : "failed_connection",
-            conmanY.RecordState.NETCONF_CONNECTED : "netconf_connected",
-            conmanY.RecordState.NETCONF_SSH_CONNECTED : "netconf_ssh_connected",
-            conmanY.RecordState.RESTCONF_CONNECTED : "restconf_connected",
             conmanY.RecordState.CFG_SEND : "cfg_send",
             conmanY.RecordState.CFG_FAILED : "cfg_failed",
             conmanY.RecordState.READY_NO_CFG : "ready_no_cfg",
             conmanY.RecordState.READY : "ready",
+            conmanY.RecordState.TERMINATE : "terminate",
         }
         return state_dict[state]
 
@@ -1146,16 +1358,19 @@ class ConfigManagerNSR(object):
             # Not found, Create and Initialize this VNF cm-state
             vnf_cm_state = {
                 'id' : vnfr['id'],
-                'name' : vnfr['short_name'],
+                'name' : vnfr['name'],
                 'state' : self.state_to_string(conmanY.RecordState.RECEIVED),
                 'mgmt_interface' :
                 {
                     'ip_address' : vnf_cfg['mgmt_ip_address'],
                     'port' : vnf_cfg['port'],
                 },
-                'cfg_type' : vnf_cfg['config_method'],
-                'cfg_location' : vnf_cfg['cfg_file'],
                 'connection_point' : [],
+                'config_parameter' :
+                {
+                    'config_parameter_source' : [],
+                    'config_parameter_request' : [],
+                },
             }
             self.cm_nsr['cm_vnfr'].append(vnf_cm_state)
 
@@ -1178,7 +1393,7 @@ class ConfigManagerNSR(object):
             vnf_cm_state = self.find_vnfr_cm_state(vnfr['id'])
             if vnf_cm_state is None:
                 self._log.error("No opdata found for NS/VNF:%s/%s!",
-                                self.nsr_name, vnfr['short_name'])
+                                self.nsr_name, vnfr['name'])
                 return
 
             if vnf_cm_state['state'] != self.state_to_string(state):
@@ -1188,7 +1403,7 @@ class ConfigManagerNSR(object):
                 yield from self.publish_cm_state()
                 self._log.info("VNF ({}/{}/{}) state change: {} -> {}"
                                .format(self.nsr_name,
-                                       vnfr['short_name'],
+                                       vnfr['name'],
                                        vnfr['member_vnf_index_ref'],
                                        old_state,
                                        vnf_cm_state['state']))
@@ -1227,20 +1442,21 @@ class ConfigManagerNSR(object):
                     self._cp_dict[vnfr['member_vnf_index_ref']].update(subnet)
                     self._cp_dict.update(subnet)
                     self._log.debug("VNF:(%s) Updated assigned subnet = %s",
-                                    vnfr['short_name'], subnet)
+                                    vnfr['name'], subnet)
             except Exception as e:
                 self._log.error("VNF:(%s) VLR Error = %s",
-                                vnfr['short_name'], e)
-            
+                                vnfr['name'], e)
+
         if vnfr['id'] not in self._vnfr_dict:
-            self._log.info("NSR(%s) : Adding VNF Record for name=%s, id=%s", self._nsr_id, vnfr['short_name'], vnfr['id'])
+            self._log.info("NSR(%s) : Adding VNF Record for name=%s, id=%s", self._nsr_id, vnfr['name'], vnfr['id'])
             # Add this vnfr to the list for show, or single traversal
             self._vnfr_list.append(vnfr)
         else:
-            self._log.warning("NSR(%s) : VNF Record for name=%s, id=%s already exists, overwriting", self._nsr_id, vnfr['short_name'], vnfr['id'])
+            self._log.warning("NSR(%s) : VNF Record for name=%s, id=%s already exists, overwriting",
+                              self._nsr_id, vnfr['name'], vnfr['id'])
 
         # Make vnfr available by id as well as by name
-        unique_name = get_vnf_unique_name(self.nsr_name, vnfr['short_name'], vnfr['member_vnf_index_ref'])
+        unique_name = get_vnf_unique_name(self.nsr_name, vnfr['name'], vnfr['member_vnf_index_ref'])
         self._vnfr_dict[unique_name] = vnfr
         self._vnfr_dict[vnfr['id']] = vnfr
 
@@ -1251,11 +1467,11 @@ class ConfigManagerNSR(object):
             'agent_vnfr' : self.agent_nsr.add_vnfr(vnfr, vnfr_msg),
             'nsr_name' : self.nsr_name,
             'nsr_id' : self._nsr_id,
-            'vnfr_name' : vnfr['short_name'],
+            'vnfr_name' : vnfr['name'],
             'member_vnf_index' : vnfr['member_vnf_index_ref'],
             'port' : 0,
-            'username' : 'admin',
-            'password' : 'admin',
+            'username' : '@rift',
+            'password' : 'rift',
             'config_method' : 'None',
             'protocol' : 'None',
             'mgmt_ip_address' : '0.0.0.0',
@@ -1264,6 +1480,7 @@ class ConfigManagerNSR(object):
             'script_type' : 'bash',
         }
 
+        ##########################
         # Update the mgmt ip address
         # In case the config method is none, this is not
         # updated later
@@ -1273,7 +1490,7 @@ class ConfigManagerNSR(object):
         except Exception as e:
             self._log.warn(
                 "VNFR {}({}), unable to retrieve mgmt ip address: {}".
-                format(vnfr['short_name'], vnfr['id'], e))
+                format(vnfr['name'], vnfr['id'], e))
 
         vnfr['vnf_cfg'] = vnf_cfg
         self.find_or_create_vnfr_cm_state(vnf_cfg)
@@ -1293,6 +1510,10 @@ class ConfigManagerNSR(object):
                     cp_list += vdur['internal_connection_point']
 
                 for cp_item_dict in cp_list:
+                    if 'ip_address' not in cp_item_dict:
+                        self._log.error("connection point {} doesnot have an ip address assigned ".
+                                                                        format(cp_item_dict['name']))
+                        continue
                     # Populate global dictionary
                     self._cp_dict[
                         cp_item_dict['name']
@@ -1313,7 +1534,7 @@ class ConfigManagerNSR(object):
         if 'internal_vlr' in vnfr:
             for ivlr in vnfr['internal_vlr']:
                 yield from populate_subnets_from_vlr(ivlr['vlr_ref'])
-                
+
         # Update vnfr
         vnf_cfg['agent_vnfr']._vnfr = vnfr
         return vnf_cfg['agent_vnfr']
@@ -1323,49 +1544,54 @@ class XPaths(object):
     @staticmethod
     def nsr_opdata(k=None):
         return ("D,/nsr:ns-instance-opdata/nsr:nsr" +
-                ("[nsr:ns-instance-config-ref='{}']".format(k) if k is not None else ""))
+                ("[nsr:ns-instance-config-ref={}]".format(quoted_key(k)) if k is not None else ""))
 
     @staticmethod
     def nsd_msg(k=None):
-        return ("C,/nsd:nsd-catalog/nsd:nsd" +
-                "[nsd:id = '{}']".format(k) if k is not None else "")
+        return ("C,/project-nsd:nsd-catalog/project-nsd:nsd" +
+                "[project-nsd:id={}]".format(quoted_key(k)) if k is not None else "")
 
     @staticmethod
     def vnfr_opdata(k=None):
         return ("D,/vnfr:vnfr-catalog/vnfr:vnfr" +
-                ("[vnfr:id='{}']".format(k) if k is not None else ""))
+                ("[vnfr:id={}]".format(quoted_key(k)) if k is not None else ""))
 
     @staticmethod
-    def vnfd(k=None):
+    def vnfd_path(k=None):
         return ("C,/vnfd:vnfd-catalog/vnfd:vnfd" +
-                ("[vnfd:id='{}']".format(k) if k is not None else ""))
+                ("[vnfd:id={}]".format(quoted_key(k)) if k is not None else ""))
 
     @staticmethod
     def config_agent(k=None):
         return ("D,/rw-config-agent:config-agent/rw-config-agent:account" +
-                ("[rw-config-agent:name='{}']".format(k) if k is not None else ""))
+                ("[rw-config-agent:name={}]".format(quoted_key(k)) if k is not None else ""))
 
     @staticmethod
     def nsr_config(k=None):
-        return ("C,/nsr:ns-instance-config/nsr:nsr[nsr:id='{}']".format(k) if k is not None else "")
+        return ("C,/nsr:ns-instance-config/nsr:nsr" +
+                ("[nsr:id={}]".format(quoted_key(k)) if k is not None else ""))
 
     @staticmethod
     def vlr(k=None):
-        return ("D,/vlr:vlr-catalog/vlr:vlr[vlr:id='{}']".format(k) if k is not None else "")
+        return ("D,/vlr:vlr-catalog/vlr:vlr" +
+                ("[vlr:id={}]".format(quoted_key(k)) if k is not None else ""))
 
 class ConfigManagerDTS(object):
     ''' This class either reads from DTS or publishes to DTS '''
 
-    def __init__(self, log, loop, parent, dts):
+    def __init__(self, log, loop, parent, dts, project):
         self._log = log
         self._loop = loop
         self._parent = parent
         self._dts = dts
+        self._project = project
 
     @asyncio.coroutine
-    def _read_dts(self, xpath, do_trace=False):
+    def _read_dts(self, path, do_trace=False):
+        xpath = self._project.add_project(path)
         self._log.debug("_read_dts path = %s", xpath)
         flags = rwdts.XactFlag.MERGE
+        flags += rwdts.XactFlag.TRACE if do_trace else 0
         res_iter = yield from self._dts.query_read(
                 xpath, flags=flags
                 )
@@ -1382,6 +1608,15 @@ class ConfigManagerDTS(object):
         return results
 
 
+    @asyncio.coroutine
+    def get_xpath(self, xpath):
+        self._log.debug("Attempting to get xpath: {}".format(xpath))
+        resp = yield from self._read_dts(xpath, False)
+        if len(resp) > 0:
+            self._log.debug("Got DTS resp: {}".format(resp[0]))
+            return resp[0]
+        return None
+
     @asyncio.coroutine
     def get_nsr(self, id):
         self._log.debug("Attempting to get NSR: %s", id)
@@ -1426,9 +1661,9 @@ class ConfigManagerDTS(object):
         return vnfr_msg
 
     @asyncio.coroutine
-    def get_vnfd(self, vnfd_id):
-        self._log.debug("Attempting to get VNFD: %s", vnfd_id)
-        vnfdl = yield from self._read_dts(XPaths.vnfd(vnfd_id), do_trace=False)
+    def get_vnfd(self, id):
+        self._log.debug("Attempting to get VNFD: %s", XPaths.vnfd_path(id))
+        vnfdl = yield from self._read_dts(XPaths.vnfd_path(id), do_trace=False)
         vnfd_msg = None
         if len(vnfdl) > 0:
             vnfd_msg = vnfdl[0]
@@ -1437,7 +1672,7 @@ class ConfigManagerDTS(object):
     @asyncio.coroutine
     def get_vlr(self, id):
         self._log.debug("Attempting to get VLR subnet: %s", id)
-        vlrl = yield from self._read_dts(XPaths.vlr(id), do_trace=True)
+        vlrl = yield from self._read_dts(XPaths.vlr(id), do_trace=False)
         vlr_msg = None
         if len(vlrl) > 0:
             vlr_msg = vlrl[0]
@@ -1450,19 +1685,21 @@ class ConfigManagerDTS(object):
         return cfgagentl
 
     @asyncio.coroutine
-    def update(self, path, msg, flags=rwdts.XactFlag.REPLACE):
+    def update(self, xpath, msg, flags=rwdts.XactFlag.REPLACE):
         """
         Update a cm-state (cm-nsr) record in DTS with the path and message
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Updating cm-state %s:%s dts_pub_hdl = %s", path, msg, self.dts_pub_hdl)
         self.dts_pub_hdl.update_element(path, msg, flags)
         self._log.debug("Updated cm-state, %s:%s", path, msg)
 
     @asyncio.coroutine
-    def delete(self, path):
+    def delete(self, xpath):
         """
         Delete cm-nsr record in DTS with the path only
         """
+        path = self._project.add_project(xpath)
         self._log.debug("Deleting cm-nsr %s dts_pub_hdl = %s", path, self.dts_pub_hdl)
         self.dts_pub_hdl.delete_element(path)
         self._log.debug("Deleted cm-nsr, %s", path)
@@ -1471,12 +1708,23 @@ class ConfigManagerDTS(object):
     def register(self):
         yield from self.register_to_publish()
         yield from self.register_for_nsr()
-        
+
+    def deregister(self):
+        self._log.debug("De-registering conman config for project {}".
+                        format(self._project.name))
+        if self.dts_reg_hdl:
+            self.dts_reg_hdl.deregister()
+            self.dts_reg_hdl = None
+
+        if self.dts_pub_hdl:
+            self.dts_pub_hdl.deregister()
+            self.dts_pub_hdl = None
+
     @asyncio.coroutine
     def register_to_publish(self):
         ''' Register to DTS for publishing cm-state opdata '''
 
-        xpath = "D,/rw-conman:cm-state/rw-conman:cm-nsr"
+        xpath = self._project.add_project("D,/rw-conman:cm-state/rw-conman:cm-nsr")
         self._log.debug("Registering to publish cm-state @ %s", xpath)
         hdl = rift.tasklets.DTS.RegistrationHandler()
         with self._dts.group_create() as group:
@@ -1486,7 +1734,7 @@ class ConfigManagerDTS(object):
 
     @property
     def nsr_xpath(self):
-        return "D,/nsr:ns-instance-opdata/nsr:nsr"
+        return self._project.add_project("D,/nsr:ns-instance-opdata/nsr:nsr")
 
     @asyncio.coroutine
     def register_for_nsr(self):
@@ -1502,15 +1750,20 @@ class ConfigManagerDTS(object):
 
             if (query_action == rwdts.QueryAction.UPDATE or
                 query_action == rwdts.QueryAction.CREATE):
-                msg_dict = msg.as_dict()
-                # Update Each NSR/VNFR state)
-                if ('operational_status' in msg_dict and
-                    msg_dict['operational_status'] == 'running'):
+                # Update Each NSR/VNFR state
+                if msg.operational_status in ['running', 'terminate']:
                     # Add to the task list
-                    self._parent.add_to_pending_tasks({'nsrid' : msg_dict['ns_instance_config_ref'], 'retries' : 5})
+                    self._parent.add_to_pending_tasks({
+                        'nsrid' : msg.ns_instance_config_ref,
+                        'retries' : 5,
+                        'event' : msg.operational_status,
+                    })
+
             elif query_action == rwdts.QueryAction.DELETE:
                 nsr_id = msg.ns_instance_config_ref
-                asyncio.ensure_future(self._parent.terminate_NSR(nsr_id), loop=self._loop)
+                self._log.debug("Got terminate for NSR id %s", nsr_id)
+                asyncio.ensure_future(self._parent.delete_NSR(nsr_id), loop=self._loop)
+
             else:
                 raise NotImplementedError(
                     "%s action on cm-state not supported",